"Fossies" - the Fresh Open Source Software Archive 
Member "xpdf-4.04/fofi/FoFiType1C.cc" (18 Apr 2022, 97383 Bytes) of package /linux/misc/xpdf-4.04.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "FoFiType1C.cc" see the
Fossies "Dox" file reference documentation and the latest
Fossies "Diffs" side-by-side code changes report:
4.03_vs_4.04.
1 //========================================================================
2 //
3 // FoFiType1C.cc
4 //
5 // Copyright 1999-2003 Glyph & Cog, LLC
6 //
7 //========================================================================
8
9 #include <aconf.h>
10
11 #ifdef USE_GCC_PRAGMAS
12 #pragma implementation
13 #endif
14
15 #include <stdlib.h>
16 #include <string.h>
17 #include <math.h>
18 #include "gmem.h"
19 #include "gmempp.h"
20 #include "GString.h"
21 #include "GHash.h"
22 #include "FoFiEncodings.h"
23 #include "FoFiType1C.h"
24
25 //------------------------------------------------------------------------
26
27 static char hexChars[17] = "0123456789ABCDEF";
28
29 #define type1cSubrRecursionLimit 20
30
31 //------------------------------------------------------------------------
32
33 GBool Type1COp::isZero() {
34 switch (kind) {
35 case type1COpInteger: return intgr == 0;
36 case type1COpFloat: return flt == 0;
37 case type1COpRational: return rat.num == 0;
38 default: return gFalse; // shouldn't happen
39 }
40 }
41
42 GBool Type1COp::isNegative() {
43 switch (kind) {
44 case type1COpInteger:
45 return intgr < 0;
46 case type1COpFloat:
47 return flt < 0;
48 case type1COpRational:
49 return (rat.num < 0) != (rat.den < 0);
50 default:
51 // shouldn't happen
52 return gFalse;
53 }
54 }
55
56 int Type1COp::toInt() {
57 switch (kind) {
58 case type1COpInteger:
59 return intgr;
60 case type1COpFloat:
61 if (flt < -2e9 || flt > 2e9) {
62 return 0;
63 }
64 return (int)flt;
65 case type1COpRational:
66 if (rat.den == 0) {
67 return 0;
68 }
69 return rat.num / rat.den;
70 default:
71 // shouldn't happen
72 return 0;
73 }
74 }
75
76 double Type1COp::toFloat() {
77 switch (kind) {
78 case type1COpInteger:
79 return (double)intgr;
80 case type1COpFloat:
81 return flt;
82 case type1COpRational:
83 if (rat.den == 0) {
84 return 0;
85 }
86 return (double)rat.num / (double)rat.den;
87 default:
88 // shouldn't happen
89 return 0.0;
90 }
91 }
92
93 //------------------------------------------------------------------------
94 // FoFiType1C
95 //------------------------------------------------------------------------
96
97 FoFiType1C *FoFiType1C::make(char *fileA, int lenA) {
98 FoFiType1C *ff;
99
100 ff = new FoFiType1C(fileA, lenA, gFalse);
101 if (!ff->parse()) {
102 delete ff;
103 return NULL;
104 }
105 return ff;
106 }
107
108 FoFiType1C *FoFiType1C::load(char *fileName) {
109 FoFiType1C *ff;
110 char *fileA;
111 int lenA;
112
113 if (!(fileA = FoFiBase::readFile(fileName, &lenA))) {
114 return NULL;
115 }
116 ff = new FoFiType1C(fileA, lenA, gTrue);
117 if (!ff->parse()) {
118 delete ff;
119 return NULL;
120 }
121 return ff;
122 }
123
124 FoFiType1C::FoFiType1C(char *fileA, int lenA, GBool freeFileDataA):
125 FoFiBase(fileA, lenA, freeFileDataA)
126 {
127 name = NULL;
128 encoding = NULL;
129 privateDicts = NULL;
130 fdSelect = NULL;
131 charset = NULL;
132 }
133
134 FoFiType1C::~FoFiType1C() {
135 int i;
136
137 if (name) {
138 delete name;
139 }
140 if (encoding &&
141 encoding != (char **)fofiType1StandardEncoding &&
142 encoding != (char **)fofiType1ExpertEncoding) {
143 for (i = 0; i < 256; ++i) {
144 gfree(encoding[i]);
145 }
146 gfree(encoding);
147 }
148 if (privateDicts) {
149 gfree(privateDicts);
150 }
151 if (fdSelect) {
152 gfree(fdSelect);
153 }
154 if (charset &&
155 charset != fofiType1CISOAdobeCharset &&
156 charset != fofiType1CExpertCharset &&
157 charset != fofiType1CExpertSubsetCharset) {
158 gfree(charset);
159 }
160 }
161
162 char *FoFiType1C::getName() {
163 return name ? name->getCString() : (char *)NULL;
164 }
165
166 char **FoFiType1C::getEncoding() {
167 return encoding;
168 }
169
170 GString *FoFiType1C::getGlyphName(int gid) {
171 char buf[256];
172 GBool ok;
173
174 ok = gTrue;
175 getString(charset[gid], buf, &ok);
176 if (!ok) {
177 return NULL;
178 }
179 return new GString(buf);
180 }
181
182 GHash *FoFiType1C::getNameToGIDMap() {
183 GHash *map;
184 char name[256];
185 GBool ok;
186 int gid;
187
188 map = new GHash(gTrue);
189 for (gid = 0; gid < nGlyphs; ++gid) {
190 ok = gTrue;
191 getString(charset[gid], name, &ok);
192 if (ok) {
193 map->add(new GString(name), gid);
194 }
195 }
196 return map;
197 }
198
199 int *FoFiType1C::getCIDToGIDMap(int *nCIDs) {
200 int *map;
201 int n, i;
202
203 // a CID font's top dict has ROS as the first operator
204 if (topDict.firstOp != 0x0c1e) {
205 *nCIDs = 0;
206 return NULL;
207 }
208
209 // in a CID font, the charset data is the GID-to-CID mapping, so all
210 // we have to do is reverse it
211 n = 0;
212 for (i = 0; i < nGlyphs; ++i) {
213 if (charset[i] > n) {
214 n = charset[i];
215 }
216 }
217 ++n;
218 map = (int *)gmallocn(n, sizeof(int));
219 memset(map, 0, n * sizeof(int));
220 for (i = 0; i < nGlyphs; ++i) {
221 map[charset[i]] = i;
222 }
223 *nCIDs = n;
224 return map;
225 }
226
227 void FoFiType1C::getFontMatrix(double *mat) {
228 int i;
229
230 if (topDict.firstOp == 0x0c1e && privateDicts[0].hasFontMatrix) {
231 if (topDict.hasFontMatrix) {
232 mat[0] = topDict.fontMatrix[0] * privateDicts[0].fontMatrix[0] +
233 topDict.fontMatrix[1] * privateDicts[0].fontMatrix[2];
234 mat[1] = topDict.fontMatrix[0] * privateDicts[0].fontMatrix[1] +
235 topDict.fontMatrix[1] * privateDicts[0].fontMatrix[3];
236 mat[2] = topDict.fontMatrix[2] * privateDicts[0].fontMatrix[0] +
237 topDict.fontMatrix[3] * privateDicts[0].fontMatrix[2];
238 mat[3] = topDict.fontMatrix[2] * privateDicts[0].fontMatrix[1] +
239 topDict.fontMatrix[3] * privateDicts[0].fontMatrix[3];
240 mat[4] = topDict.fontMatrix[4] * privateDicts[0].fontMatrix[0] +
241 topDict.fontMatrix[5] * privateDicts[0].fontMatrix[2];
242 mat[5] = topDict.fontMatrix[4] * privateDicts[0].fontMatrix[1] +
243 topDict.fontMatrix[5] * privateDicts[0].fontMatrix[3];
244 } else {
245 for (i = 0; i < 6; ++i) {
246 mat[i] = privateDicts[0].fontMatrix[i];
247 }
248 }
249 } else {
250 for (i = 0; i < 6; ++i) {
251 mat[i] = topDict.fontMatrix[i];
252 }
253 }
254 }
255
256 void FoFiType1C::convertToType1(char *psName, const char **newEncoding,
257 GBool ascii, FoFiOutputFunc outputFunc,
258 void *outputStream) {
259 int psNameLen;
260 Type1CEexecBuf eb;
261 Type1CIndex subrIdx;
262 Type1CIndexVal val;
263 GString *buf;
264 char buf2[256];
265 const char **enc;
266 GBool ok;
267 int i;
268
269 if (psName) {
270 psNameLen = (int)strlen(psName);
271 } else {
272 psName = name->getCString();
273 psNameLen = name->getLength();
274 }
275
276 // write header and font dictionary, up to encoding
277 ok = gTrue;
278 (*outputFunc)(outputStream, "%!FontType1-1.0: ", 17);
279 (*outputFunc)(outputStream, psName, psNameLen);
280 if (topDict.versionSID != 0) {
281 getString(topDict.versionSID, buf2, &ok);
282 (*outputFunc)(outputStream, buf2, (int)strlen(buf2));
283 }
284 (*outputFunc)(outputStream, "\n", 1);
285 // the dictionary needs room for 12 entries: the following 9, plus
286 // Private and CharStrings (in the eexec section) and FID (which is
287 // added by definefont)
288 (*outputFunc)(outputStream, "12 dict begin\n", 14);
289 (*outputFunc)(outputStream, "/FontInfo 10 dict dup begin\n", 28);
290 if (topDict.versionSID != 0) {
291 (*outputFunc)(outputStream, "/version ", 9);
292 writePSString(buf2, outputFunc, outputStream);
293 (*outputFunc)(outputStream, " readonly def\n", 14);
294 }
295 if (topDict.noticeSID != 0) {
296 getString(topDict.noticeSID, buf2, &ok);
297 (*outputFunc)(outputStream, "/Notice ", 8);
298 writePSString(buf2, outputFunc, outputStream);
299 (*outputFunc)(outputStream, " readonly def\n", 14);
300 }
301 if (topDict.copyrightSID != 0) {
302 getString(topDict.copyrightSID, buf2, &ok);
303 (*outputFunc)(outputStream, "/Copyright ", 11);
304 writePSString(buf2, outputFunc, outputStream);
305 (*outputFunc)(outputStream, " readonly def\n", 14);
306 }
307 if (topDict.fullNameSID != 0) {
308 getString(topDict.fullNameSID, buf2, &ok);
309 (*outputFunc)(outputStream, "/FullName ", 10);
310 writePSString(buf2, outputFunc, outputStream);
311 (*outputFunc)(outputStream, " readonly def\n", 14);
312 }
313 if (topDict.familyNameSID != 0) {
314 getString(topDict.familyNameSID, buf2, &ok);
315 (*outputFunc)(outputStream, "/FamilyName ", 12);
316 writePSString(buf2, outputFunc, outputStream);
317 (*outputFunc)(outputStream, " readonly def\n", 14);
318 }
319 if (topDict.weightSID != 0) {
320 getString(topDict.weightSID, buf2, &ok);
321 (*outputFunc)(outputStream, "/Weight ", 8);
322 writePSString(buf2, outputFunc, outputStream);
323 (*outputFunc)(outputStream, " readonly def\n", 14);
324 }
325 if (topDict.isFixedPitch) {
326 (*outputFunc)(outputStream, "/isFixedPitch true def\n", 23);
327 } else {
328 (*outputFunc)(outputStream, "/isFixedPitch false def\n", 24);
329 }
330 buf = GString::format("/ItalicAngle {0:.4g} def\n", topDict.italicAngle);
331 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
332 delete buf;
333 buf = GString::format("/UnderlinePosition {0:.4g} def\n",
334 topDict.underlinePosition);
335 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
336 delete buf;
337 buf = GString::format("/UnderlineThickness {0:.4g} def\n",
338 topDict.underlineThickness);
339 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
340 delete buf;
341 (*outputFunc)(outputStream, "end readonly def\n", 17);
342 (*outputFunc)(outputStream, "/FontName /", 11);
343 (*outputFunc)(outputStream, psName, psNameLen);
344 (*outputFunc)(outputStream, " def\n", 5);
345 buf = GString::format("/PaintType {0:d} def\n", topDict.paintType);
346 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
347 delete buf;
348 (*outputFunc)(outputStream, "/FontType 1 def\n", 16);
349 buf = GString::format("/FontMatrix [{0:.8g} {1:.8g} {2:.8g} {3:.8g} {4:.8g} {5:.8g}] readonly def\n",
350 topDict.fontMatrix[0], topDict.fontMatrix[1],
351 topDict.fontMatrix[2], topDict.fontMatrix[3],
352 topDict.fontMatrix[4], topDict.fontMatrix[5]);
353 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
354 delete buf;
355 buf = GString::format("/FontBBox [{0:.4g} {1:.4g} {2:.4g} {3:.4g}] readonly def\n",
356 topDict.fontBBox[0], topDict.fontBBox[1],
357 topDict.fontBBox[2], topDict.fontBBox[3]);
358 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
359 delete buf;
360 buf = GString::format("/StrokeWidth {0:.4g} def\n", topDict.strokeWidth);
361 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
362 delete buf;
363 if (topDict.uniqueID != 0) {
364 buf = GString::format("/UniqueID {0:d} def\n", topDict.uniqueID);
365 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
366 delete buf;
367 }
368
369 // write the encoding
370 (*outputFunc)(outputStream, "/Encoding ", 10);
371 if (!newEncoding && encoding == (char **)fofiType1StandardEncoding) {
372 (*outputFunc)(outputStream, "StandardEncoding def\n", 21);
373 } else {
374 (*outputFunc)(outputStream, "256 array\n", 10);
375 (*outputFunc)(outputStream,
376 "0 1 255 {1 index exch /.notdef put} for\n", 40);
377 enc = newEncoding ? newEncoding : (const char **)encoding;
378 for (i = 0; i < 256; ++i) {
379 if (enc[i]) {
380 buf = GString::format("dup {0:d} /{1:s} put\n", i, enc[i]);
381 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
382 delete buf;
383 }
384 }
385 (*outputFunc)(outputStream, "readonly def\n", 13);
386 }
387 (*outputFunc)(outputStream, "currentdict end\n", 16);
388
389 // start the binary section
390 (*outputFunc)(outputStream, "currentfile eexec\n", 18);
391 eb.outputFunc = outputFunc;
392 eb.outputStream = outputStream;
393 eb.ascii = ascii;
394 eb.r1 = 55665;
395 eb.line = 0;
396
397 // write the private dictionary
398 eexecWrite(&eb, "\x83\xca\x73\xd5");
399 eexecWrite(&eb, "dup /Private 32 dict dup begin\n");
400 eexecWrite(&eb, "/RD {string currentfile exch readstring pop}"
401 " executeonly def\n");
402 eexecWrite(&eb, "/ND {noaccess def} executeonly def\n");
403 eexecWrite(&eb, "/NP {noaccess put} executeonly def\n");
404 eexecWrite(&eb, "/MinFeature {16 16} def\n");
405 eexecWrite(&eb, "/password 5839 def\n");
406 if (privateDicts[0].nBlueValues) {
407 eexecWrite(&eb, "/BlueValues [");
408 // number of entries must be even
409 int n = privateDicts[0].nBlueValues & ~1;
410 for (i = 0; i < n; ++i) {
411 buf = GString::format("{0:s}{1:d}",
412 i > 0 ? " " : "", privateDicts[0].blueValues[i]);
413 eexecWrite(&eb, buf->getCString());
414 delete buf;
415 }
416 eexecWrite(&eb, "] def\n");
417 }
418 if (privateDicts[0].nOtherBlues) {
419 eexecWrite(&eb, "/OtherBlues [");
420 // number of entries must be even
421 int n = privateDicts[0].nOtherBlues & ~1;
422 for (i = 0; i < n; ++i) {
423 buf = GString::format("{0:s}{1:d}",
424 i > 0 ? " " : "", privateDicts[0].otherBlues[i]);
425 eexecWrite(&eb, buf->getCString());
426 delete buf;
427 }
428 eexecWrite(&eb, "] def\n");
429 }
430 if (privateDicts[0].nFamilyBlues) {
431 eexecWrite(&eb, "/FamilyBlues [");
432 // number of entries must be even
433 int n = privateDicts[0].nFamilyBlues & ~1;
434 for (i = 0; i < n; ++i) {
435 buf = GString::format("{0:s}{1:d}",
436 i > 0 ? " " : "", privateDicts[0].familyBlues[i]);
437 eexecWrite(&eb, buf->getCString());
438 delete buf;
439 }
440 eexecWrite(&eb, "] def\n");
441 }
442 if (privateDicts[0].nFamilyOtherBlues) {
443 eexecWrite(&eb, "/FamilyOtherBlues [");
444 // number of entries must be even
445 int n = privateDicts[0].nFamilyOtherBlues & ~1;
446 for (i = 0; i < n; ++i) {
447 buf = GString::format("{0:s}{1:d}", i > 0 ? " " : "",
448 privateDicts[0].familyOtherBlues[i]);
449 eexecWrite(&eb, buf->getCString());
450 delete buf;
451 }
452 eexecWrite(&eb, "] def\n");
453 }
454 if (privateDicts[0].blueScale != 0.039625) {
455 buf = GString::format("/BlueScale {0:.4g} def\n",
456 privateDicts[0].blueScale);
457 eexecWrite(&eb, buf->getCString());
458 delete buf;
459 }
460 if (privateDicts[0].blueShift != 7) {
461 buf = GString::format("/BlueShift {0:d} def\n", privateDicts[0].blueShift);
462 eexecWrite(&eb, buf->getCString());
463 delete buf;
464 }
465 if (privateDicts[0].blueFuzz != 1) {
466 buf = GString::format("/BlueFuzz {0:d} def\n", privateDicts[0].blueFuzz);
467 eexecWrite(&eb, buf->getCString());
468 delete buf;
469 }
470 if (privateDicts[0].hasStdHW) {
471 buf = GString::format("/StdHW [{0:.4g}] def\n", privateDicts[0].stdHW);
472 eexecWrite(&eb, buf->getCString());
473 delete buf;
474 }
475 if (privateDicts[0].hasStdVW) {
476 buf = GString::format("/StdVW [{0:.4g}] def\n", privateDicts[0].stdVW);
477 eexecWrite(&eb, buf->getCString());
478 delete buf;
479 }
480 if (privateDicts[0].nStemSnapH) {
481 // the StemSnapH array should be unique values in ascending order --
482 // if not, just skip it
483 for (i = 1; i < privateDicts[0].nStemSnapH; ++i) {
484 if (privateDicts[0].stemSnapH[i-1] >= privateDicts[0].stemSnapH[i]) {
485 break;
486 }
487 }
488 if (i == privateDicts[0].nStemSnapH) {
489 eexecWrite(&eb, "/StemSnapH [");
490 for (i = 0; i < privateDicts[0].nStemSnapH; ++i) {
491 buf = GString::format("{0:s}{1:.4g}",
492 i > 0 ? " " : "", privateDicts[0].stemSnapH[i]);
493 eexecWrite(&eb, buf->getCString());
494 delete buf;
495 }
496 eexecWrite(&eb, "] def\n");
497 }
498 }
499 if (privateDicts[0].nStemSnapV) {
500 // the StemSnapV array should be unique values in ascending order --
501 // if not, just skip it
502 for (i = 1; i < privateDicts[0].nStemSnapV; ++i) {
503 if (privateDicts[0].stemSnapV[i-1] >= privateDicts[0].stemSnapV[i]) {
504 break;
505 }
506 }
507 if (i == privateDicts[0].nStemSnapV) {
508 eexecWrite(&eb, "/StemSnapV [");
509 for (i = 0; i < privateDicts[0].nStemSnapV; ++i) {
510 buf = GString::format("{0:s}{1:.4g}",
511 i > 0 ? " " : "", privateDicts[0].stemSnapV[i]);
512 eexecWrite(&eb, buf->getCString());
513 delete buf;
514 }
515 eexecWrite(&eb, "] def\n");
516 }
517 }
518 if (privateDicts[0].hasForceBold) {
519 buf = GString::format("/ForceBold {0:s} def\n",
520 privateDicts[0].forceBold ? "true" : "false");
521 eexecWrite(&eb, buf->getCString());
522 delete buf;
523 }
524 if (privateDicts[0].forceBoldThreshold != 0) {
525 buf = GString::format("/ForceBoldThreshold {0:.4g} def\n",
526 privateDicts[0].forceBoldThreshold);
527 eexecWrite(&eb, buf->getCString());
528 delete buf;
529 }
530 if (privateDicts[0].languageGroup != 0) {
531 buf = GString::format("/LanguageGroup {0:d} def\n",
532 privateDicts[0].languageGroup);
533 eexecWrite(&eb, buf->getCString());
534 delete buf;
535 }
536 if (privateDicts[0].expansionFactor != 0.06) {
537 buf = GString::format("/ExpansionFactor {0:.4g} def\n",
538 privateDicts[0].expansionFactor);
539 eexecWrite(&eb, buf->getCString());
540 delete buf;
541 }
542
543 // set up subroutines
544 ok = gTrue;
545 getIndex(privateDicts[0].subrsOffset, &subrIdx, &ok);
546 if (!ok) {
547 subrIdx.pos = -1;
548 }
549
550 // write the CharStrings
551 buf = GString::format("2 index /CharStrings {0:d} dict dup begin\n",
552 nGlyphs);
553 eexecWrite(&eb, buf->getCString());
554 delete buf;
555 for (i = 0; i < nGlyphs; ++i) {
556 ok = gTrue;
557 getIndexVal(&charStringsIdx, i, &val, &ok);
558 if (ok) {
559 getString(charset[i], buf2, &ok);
560 if (ok) {
561 eexecCvtGlyph(&eb, buf2, val.pos, val.len, &subrIdx, &privateDicts[0]);
562 }
563 }
564 }
565 eexecWrite(&eb, "end\n");
566 eexecWrite(&eb, "end\n");
567 eexecWrite(&eb, "readonly put\n");
568 eexecWrite(&eb, "noaccess put\n");
569 eexecWrite(&eb, "dup /FontName get exch definefont pop\n");
570 eexecWrite(&eb, "mark currentfile closefile\n");
571
572 // trailer
573 if (ascii && eb.line > 0) {
574 (*outputFunc)(outputStream, "\n", 1);
575 }
576 for (i = 0; i < 8; ++i) {
577 (*outputFunc)(outputStream, "0000000000000000000000000000000000000000000000000000000000000000\n", 65);
578 }
579 (*outputFunc)(outputStream, "cleartomark\n", 12);
580 }
581
582 void FoFiType1C::convertToCIDType0(char *psName, int *codeMap, int nCodes,
583 FoFiOutputFunc outputFunc,
584 void *outputStream) {
585 int *cidMap;
586 GString *charStrings;
587 int *charStringOffsets;
588 Type1CIndex subrIdx;
589 Type1CIndexVal val;
590 int nCIDs, gdBytes;
591 GString *buf;
592 char buf2[256];
593 GBool ok;
594 int gid, offset, n, i, j, k;
595
596 // compute the CID count and build the CID-to-GID mapping
597 if (codeMap) {
598 nCIDs = nCodes;
599 cidMap = (int *)gmallocn(nCIDs, sizeof(int));
600 for (i = 0; i < nCodes; ++i) {
601 if (codeMap[i] >= 0 && codeMap[i] < nGlyphs) {
602 cidMap[i] = codeMap[i];
603 } else {
604 cidMap[i] = -1;
605 }
606 }
607 } else if (topDict.firstOp == 0x0c1e) {
608 nCIDs = 0;
609 for (i = 0; i < nGlyphs; ++i) {
610 if (charset[i] >= nCIDs) {
611 nCIDs = charset[i] + 1;
612 }
613 }
614 cidMap = (int *)gmallocn(nCIDs, sizeof(int));
615 for (i = 0; i < nCIDs; ++i) {
616 cidMap[i] = -1;
617 }
618 for (i = 0; i < nGlyphs; ++i) {
619 cidMap[charset[i]] = i;
620 }
621 } else {
622 nCIDs = nGlyphs;
623 cidMap = (int *)gmallocn(nCIDs, sizeof(int));
624 for (i = 0; i < nCIDs; ++i) {
625 cidMap[i] = i;
626 }
627 }
628
629 // build the charstrings
630 charStrings = new GString();
631 charStringOffsets = (int *)gmallocn(nCIDs + 1, sizeof(int));
632 for (i = 0; i < nCIDs; ++i) {
633 charStringOffsets[i] = charStrings->getLength();
634 if ((gid = cidMap[i]) >= 0) {
635 ok = gTrue;
636 getIndexVal(&charStringsIdx, gid, &val, &ok);
637 if (ok) {
638 getIndex(privateDicts[fdSelect ? fdSelect[gid] : 0].subrsOffset,
639 &subrIdx, &ok);
640 if (!ok) {
641 subrIdx.pos = -1;
642 }
643 cvtGlyph(val.pos, val.len, charStrings,
644 &subrIdx, &privateDicts[fdSelect ? fdSelect[gid] : 0],
645 gTrue, 0);
646 }
647 }
648 }
649 charStringOffsets[nCIDs] = charStrings->getLength();
650
651 // compute gdBytes = number of bytes needed for charstring offsets
652 // (offset size needs to account for the charstring offset table,
653 // with a worst case of five bytes per entry, plus the charstrings
654 // themselves)
655 i = (nCIDs + 1) * 5 + charStrings->getLength();
656 if (i < 0x100) {
657 gdBytes = 1;
658 } else if (i < 0x10000) {
659 gdBytes = 2;
660 } else if (i < 0x1000000) {
661 gdBytes = 3;
662 } else {
663 gdBytes = 4;
664 }
665
666 // begin the font dictionary
667 (*outputFunc)(outputStream, "/CIDInit /ProcSet findresource begin\n", 37);
668 (*outputFunc)(outputStream, "20 dict begin\n", 14);
669 (*outputFunc)(outputStream, "/CIDFontName /", 14);
670 (*outputFunc)(outputStream, psName, (int)strlen(psName));
671 (*outputFunc)(outputStream, " def\n", 5);
672 (*outputFunc)(outputStream, "/CIDFontType 0 def\n", 19);
673 (*outputFunc)(outputStream, "/CIDSystemInfo 3 dict dup begin\n", 32);
674 if (topDict.registrySID > 0 && topDict.orderingSID > 0) {
675 ok = gTrue;
676 getString(topDict.registrySID, buf2, &ok);
677 if (ok) {
678 (*outputFunc)(outputStream, " /Registry (", 13);
679 (*outputFunc)(outputStream, buf2, (int)strlen(buf2));
680 (*outputFunc)(outputStream, ") def\n", 6);
681 }
682 ok = gTrue;
683 getString(topDict.orderingSID, buf2, &ok);
684 if (ok) {
685 (*outputFunc)(outputStream, " /Ordering (", 13);
686 (*outputFunc)(outputStream, buf2, (int)strlen(buf2));
687 (*outputFunc)(outputStream, ") def\n", 6);
688 }
689 } else {
690 (*outputFunc)(outputStream, " /Registry (Adobe) def\n", 24);
691 (*outputFunc)(outputStream, " /Ordering (Identity) def\n", 27);
692 }
693 buf = GString::format(" /Supplement {0:d} def\n", topDict.supplement);
694 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
695 delete buf;
696 (*outputFunc)(outputStream, "end def\n", 8);
697 if (topDict.hasFontMatrix) {
698 buf = GString::format("/FontMatrix [{0:.8g} {1:.8g} {2:.8g} {3:.8g} {4:.8g} {5:.8g}] def\n",
699 topDict.fontMatrix[0], topDict.fontMatrix[1],
700 topDict.fontMatrix[2], topDict.fontMatrix[3],
701 topDict.fontMatrix[4], topDict.fontMatrix[5]);
702 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
703 delete buf;
704 } else if (privateDicts[0].hasFontMatrix) {
705 (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
706 } else {
707 (*outputFunc)(outputStream,
708 "/FontMatrix [0.001 0 0 0.001 0 0] def\n", 38);
709 }
710 buf = GString::format("/FontBBox [{0:.4g} {1:.4g} {2:.4g} {3:.4g}] def\n",
711 topDict.fontBBox[0], topDict.fontBBox[1],
712 topDict.fontBBox[2], topDict.fontBBox[3]);
713 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
714 delete buf;
715 (*outputFunc)(outputStream, "/FontInfo 1 dict dup begin\n", 27);
716 (*outputFunc)(outputStream, " /FSType 8 def\n", 16);
717 (*outputFunc)(outputStream, "end def\n", 8);
718
719 // CIDFont-specific entries
720 buf = GString::format("/CIDCount {0:d} def\n", nCIDs);
721 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
722 delete buf;
723 (*outputFunc)(outputStream, "/FDBytes 1 def\n", 15);
724 buf = GString::format("/GDBytes {0:d} def\n", gdBytes);
725 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
726 delete buf;
727 (*outputFunc)(outputStream, "/CIDMapOffset 0 def\n", 20);
728 if (topDict.paintType != 0) {
729 buf = GString::format("/PaintType {0:d} def\n", topDict.paintType);
730 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
731 delete buf;
732 buf = GString::format("/StrokeWidth {0:.4g} def\n", topDict.strokeWidth);
733 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
734 delete buf;
735 }
736
737 // FDArray entry
738 buf = GString::format("/FDArray {0:d} array\n", nFDs);
739 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
740 delete buf;
741 for (i = 0; i < nFDs; ++i) {
742 buf = GString::format("dup {0:d} 10 dict begin\n", i);
743 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
744 delete buf;
745 (*outputFunc)(outputStream, "/FontType 1 def\n", 16);
746 if (privateDicts[i].hasFontMatrix) {
747 buf = GString::format("/FontMatrix [{0:.8g} {1:.8g} {2:.8g} {3:.8g} {4:.8g} {5:.8g}] def\n",
748 privateDicts[i].fontMatrix[0],
749 privateDicts[i].fontMatrix[1],
750 privateDicts[i].fontMatrix[2],
751 privateDicts[i].fontMatrix[3],
752 privateDicts[i].fontMatrix[4],
753 privateDicts[i].fontMatrix[5]);
754 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
755 delete buf;
756 } else {
757 (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
758 }
759 buf = GString::format("/PaintType {0:d} def\n", topDict.paintType);
760 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
761 delete buf;
762 (*outputFunc)(outputStream, "/Private 32 dict begin\n", 23);
763 if (privateDicts[i].nBlueValues) {
764 (*outputFunc)(outputStream, "/BlueValues [", 13);
765 for (j = 0; j < privateDicts[i].nBlueValues; ++j) {
766 buf = GString::format("{0:s}{1:d}",
767 j > 0 ? " " : "", privateDicts[i].blueValues[j]);
768 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
769 delete buf;
770 }
771 (*outputFunc)(outputStream, "] def\n", 6);
772 }
773 if (privateDicts[i].nOtherBlues) {
774 (*outputFunc)(outputStream, "/OtherBlues [", 13);
775 for (j = 0; j < privateDicts[i].nOtherBlues; ++j) {
776 buf = GString::format("{0:s}{1:d}",
777 j > 0 ? " " : "", privateDicts[i].otherBlues[j]);
778 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
779 delete buf;
780 }
781 (*outputFunc)(outputStream, "] def\n", 6);
782 }
783 if (privateDicts[i].nFamilyBlues) {
784 (*outputFunc)(outputStream, "/FamilyBlues [", 14);
785 for (j = 0; j < privateDicts[i].nFamilyBlues; ++j) {
786 buf = GString::format("{0:s}{1:d}",
787 j > 0 ? " " : "",
788 privateDicts[i].familyBlues[j]);
789 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
790 delete buf;
791 }
792 (*outputFunc)(outputStream, "] def\n", 6);
793 }
794 if (privateDicts[i].nFamilyOtherBlues) {
795 (*outputFunc)(outputStream, "/FamilyOtherBlues [", 19);
796 for (j = 0; j < privateDicts[i].nFamilyOtherBlues; ++j) {
797 buf = GString::format("{0:s}{1:d}", j > 0 ? " " : "",
798 privateDicts[i].familyOtherBlues[j]);
799 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
800 delete buf;
801 }
802 (*outputFunc)(outputStream, "] def\n", 6);
803 }
804 if (privateDicts[i].blueScale != 0.039625) {
805 buf = GString::format("/BlueScale {0:.4g} def\n",
806 privateDicts[i].blueScale);
807 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
808 delete buf;
809 }
810 if (privateDicts[i].blueShift != 7) {
811 buf = GString::format("/BlueShift {0:d} def\n",
812 privateDicts[i].blueShift);
813 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
814 delete buf;
815 }
816 if (privateDicts[i].blueFuzz != 1) {
817 buf = GString::format("/BlueFuzz {0:d} def\n", privateDicts[i].blueFuzz);
818 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
819 delete buf;
820 }
821 if (privateDicts[i].hasStdHW) {
822 buf = GString::format("/StdHW [{0:.4g}] def\n", privateDicts[i].stdHW);
823 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
824 delete buf;
825 }
826 if (privateDicts[i].hasStdVW) {
827 buf = GString::format("/StdVW [{0:.4g}] def\n", privateDicts[i].stdVW);
828 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
829 delete buf;
830 }
831 if (privateDicts[i].nStemSnapH) {
832 // the StemSnapH array should be unique values in ascending order --
833 // if not, just skip it
834 for (j = 1; j < privateDicts[i].nStemSnapH; ++j) {
835 if (privateDicts[i].stemSnapH[j-1] >= privateDicts[i].stemSnapH[j]) {
836 break;
837 }
838 }
839 if (j == privateDicts[i].nStemSnapH) {
840 (*outputFunc)(outputStream, "/StemSnapH [", 12);
841 for (j = 0; j < privateDicts[i].nStemSnapH; ++j) {
842 buf = GString::format("{0:s}{1:.4g}",
843 j > 0 ? " " : "", privateDicts[i].stemSnapH[j]);
844 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
845 delete buf;
846 }
847 (*outputFunc)(outputStream, "] def\n", 6);
848 }
849 }
850 if (privateDicts[i].nStemSnapV) {
851 // the StemSnapV array should be unique values in ascending order --
852 // if not, just skip it
853 for (j = 1; j < privateDicts[i].nStemSnapV; ++j) {
854 if (privateDicts[i].stemSnapV[j-1] >= privateDicts[i].stemSnapV[j]) {
855 break;
856 }
857 }
858 if (j == privateDicts[i].nStemSnapV) {
859 (*outputFunc)(outputStream, "/StemSnapV [", 12);
860 for (j = 0; j < privateDicts[i].nStemSnapV; ++j) {
861 buf = GString::format("{0:s}{1:.4g}",
862 j > 0 ? " " : "", privateDicts[i].stemSnapV[j]);
863 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
864 delete buf;
865 }
866 (*outputFunc)(outputStream, "] def\n", 6);
867 }
868 }
869 if (privateDicts[i].hasForceBold) {
870 buf = GString::format("/ForceBold {0:s} def\n",
871 privateDicts[i].forceBold ? "true" : "false");
872 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
873 delete buf;
874 }
875 if (privateDicts[i].forceBoldThreshold != 0) {
876 buf = GString::format("/ForceBoldThreshold {0:.4g} def\n",
877 privateDicts[i].forceBoldThreshold);
878 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
879 delete buf;
880 }
881 if (privateDicts[i].languageGroup != 0) {
882 buf = GString::format("/LanguageGroup {0:d} def\n",
883 privateDicts[i].languageGroup);
884 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
885 delete buf;
886 }
887 if (privateDicts[i].expansionFactor != 0.06) {
888 buf = GString::format("/ExpansionFactor {0:.4g} def\n",
889 privateDicts[i].expansionFactor);
890 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
891 delete buf;
892 }
893 (*outputFunc)(outputStream, "currentdict end def\n", 20);
894 (*outputFunc)(outputStream, "currentdict end put\n", 20);
895 }
896 (*outputFunc)(outputStream, "def\n", 4);
897
898 // start the binary section
899 offset = (nCIDs + 1) * (1 + gdBytes);
900 buf = GString::format("(Hex) {0:d} StartData\n",
901 offset + charStrings->getLength());
902 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
903 delete buf;
904
905 // write the charstring offset (CIDMap) table
906 for (i = 0; i <= nCIDs; i += 6) {
907 for (j = 0; j < 6 && i+j <= nCIDs; ++j) {
908 if (i+j < nCIDs && cidMap[i+j] >= 0 && fdSelect) {
909 buf2[0] = (char)fdSelect[cidMap[i+j]];
910 } else {
911 buf2[0] = (char)0;
912 }
913 n = offset + charStringOffsets[i+j];
914 for (k = gdBytes; k >= 1; --k) {
915 buf2[k] = (char)(n & 0xff);
916 n >>= 8;
917 }
918 for (k = 0; k <= gdBytes; ++k) {
919 buf = GString::format("{0:02x}", buf2[k] & 0xff);
920 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
921 delete buf;
922 }
923 }
924 (*outputFunc)(outputStream, "\n", 1);
925 }
926
927 // write the charstring data
928 n = charStrings->getLength();
929 for (i = 0; i < n; i += 32) {
930 for (j = 0; j < 32 && i+j < n; ++j) {
931 buf = GString::format("{0:02x}", charStrings->getChar(i+j) & 0xff);
932 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
933 delete buf;
934 }
935 if (i + 32 >= n) {
936 (*outputFunc)(outputStream, ">", 1);
937 }
938 (*outputFunc)(outputStream, "\n", 1);
939 }
940
941 gfree(charStringOffsets);
942 delete charStrings;
943 gfree(cidMap);
944 }
945
946 void FoFiType1C::convertToType0(char *psName, int *codeMap, int nCodes,
947 FoFiOutputFunc outputFunc,
948 void *outputStream) {
949 int *cidMap;
950 Type1CIndex subrIdx;
951 Type1CIndexVal val;
952 int nCIDs;
953 GString *buf;
954 Type1CEexecBuf eb;
955 GBool ok;
956 int fd, i, j, k;
957
958 // compute the CID count and build the CID-to-GID mapping
959 if (codeMap) {
960 nCIDs = nCodes;
961 cidMap = (int *)gmallocn(nCIDs, sizeof(int));
962 for (i = 0; i < nCodes; ++i) {
963 if (codeMap[i] >= 0 && codeMap[i] < nGlyphs) {
964 cidMap[i] = codeMap[i];
965 } else {
966 cidMap[i] = -1;
967 }
968 }
969 } else if (topDict.firstOp == 0x0c1e) {
970 nCIDs = 0;
971 for (i = 0; i < nGlyphs; ++i) {
972 if (charset[i] >= nCIDs) {
973 nCIDs = charset[i] + 1;
974 }
975 }
976 cidMap = (int *)gmallocn(nCIDs, sizeof(int));
977 for (i = 0; i < nCIDs; ++i) {
978 cidMap[i] = -1;
979 }
980 for (i = 0; i < nGlyphs; ++i) {
981 cidMap[charset[i]] = i;
982 }
983 } else {
984 nCIDs = nGlyphs;
985 cidMap = (int *)gmallocn(nCIDs, sizeof(int));
986 for (i = 0; i < nCIDs; ++i) {
987 cidMap[i] = i;
988 }
989 }
990
991 // write the descendant Type 1 fonts
992 for (i = 0; i < nCIDs; i += 256) {
993
994 //~ this assumes that all CIDs in this block have the same FD --
995 //~ to handle multiple FDs correctly, need to somehow divide the
996 //~ font up by FD; as a kludge we ignore CID 0, which is .notdef
997 fd = 0;
998 // if fdSelect is NULL, we have an 8-bit font, so just leave fd=0
999 if (fdSelect) {
1000 for (j = i==0 ? 1 : 0; j < 256 && i+j < nCIDs; ++j) {
1001 if (cidMap[i+j] >= 0) {
1002 fd = fdSelect[cidMap[i+j]];
1003 break;
1004 }
1005 }
1006 }
1007 if (fd < 0 || fd >= nFDs) {
1008 // this will only happen in a broken/damaged font
1009 fd = 0;
1010 }
1011
1012 // font dictionary (unencrypted section)
1013 (*outputFunc)(outputStream, "16 dict begin\n", 14);
1014 (*outputFunc)(outputStream, "/FontName /", 11);
1015 (*outputFunc)(outputStream, psName, (int)strlen(psName));
1016 buf = GString::format("_{0:02x} def\n", i >> 8);
1017 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
1018 delete buf;
1019 (*outputFunc)(outputStream, "/FontType 1 def\n", 16);
1020 if (privateDicts[fd].hasFontMatrix) {
1021 buf = GString::format("/FontMatrix [{0:.8g} {1:.8g} {2:.8g} {3:.8g} {4:.8g} {5:.8g}] def\n",
1022 privateDicts[fd].fontMatrix[0],
1023 privateDicts[fd].fontMatrix[1],
1024 privateDicts[fd].fontMatrix[2],
1025 privateDicts[fd].fontMatrix[3],
1026 privateDicts[fd].fontMatrix[4],
1027 privateDicts[fd].fontMatrix[5]);
1028 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
1029 delete buf;
1030 } else if (topDict.hasFontMatrix) {
1031 (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
1032 } else {
1033 (*outputFunc)(outputStream,
1034 "/FontMatrix [0.001 0 0 0.001 0 0] def\n", 38);
1035 }
1036 buf = GString::format("/FontBBox [{0:.4g} {1:.4g} {2:.4g} {3:.4g}] def\n",
1037 topDict.fontBBox[0], topDict.fontBBox[1],
1038 topDict.fontBBox[2], topDict.fontBBox[3]);
1039 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
1040 delete buf;
1041 buf = GString::format("/PaintType {0:d} def\n", topDict.paintType);
1042 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
1043 delete buf;
1044 if (topDict.paintType != 0) {
1045 buf = GString::format("/StrokeWidth {0:.4g} def\n", topDict.strokeWidth);
1046 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
1047 delete buf;
1048 }
1049 (*outputFunc)(outputStream, "/Encoding 256 array\n", 20);
1050 for (j = 0; j < 256 && i+j < nCIDs; ++j) {
1051 buf = GString::format("dup {0:d} /c{1:02x} put\n", j, j);
1052 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
1053 delete buf;
1054 }
1055 if (j < 256) {
1056 buf = GString::format("{0:d} 1 255 {{ 1 index exch /.notdef put }} for\n",
1057 j);
1058 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
1059 delete buf;
1060 }
1061 (*outputFunc)(outputStream, "readonly def\n", 13);
1062 (*outputFunc)(outputStream, "currentdict end\n", 16);
1063
1064 // start the binary section
1065 (*outputFunc)(outputStream, "currentfile eexec\n", 18);
1066 eb.outputFunc = outputFunc;
1067 eb.outputStream = outputStream;
1068 eb.ascii = gTrue;
1069 eb.r1 = 55665;
1070 eb.line = 0;
1071
1072 // start the private dictionary
1073 eexecWrite(&eb, "\x83\xca\x73\xd5");
1074 eexecWrite(&eb, "dup /Private 32 dict dup begin\n");
1075 eexecWrite(&eb, "/RD {string currentfile exch readstring pop}"
1076 " executeonly def\n");
1077 eexecWrite(&eb, "/ND {noaccess def} executeonly def\n");
1078 eexecWrite(&eb, "/NP {noaccess put} executeonly def\n");
1079 eexecWrite(&eb, "/MinFeature {16 16} def\n");
1080 eexecWrite(&eb, "/password 5839 def\n");
1081 if (privateDicts[fd].nBlueValues) {
1082 eexecWrite(&eb, "/BlueValues [");
1083 for (k = 0; k < privateDicts[fd].nBlueValues; ++k) {
1084 buf = GString::format("{0:s}{1:d}",
1085 k > 0 ? " " : "",
1086 privateDicts[fd].blueValues[k]);
1087 eexecWrite(&eb, buf->getCString());
1088 delete buf;
1089 }
1090 eexecWrite(&eb, "] def\n");
1091 }
1092 if (privateDicts[fd].nOtherBlues) {
1093 eexecWrite(&eb, "/OtherBlues [");
1094 for (k = 0; k < privateDicts[fd].nOtherBlues; ++k) {
1095 buf = GString::format("{0:s}{1:d}",
1096 k > 0 ? " " : "",
1097 privateDicts[fd].otherBlues[k]);
1098 eexecWrite(&eb, buf->getCString());
1099 delete buf;
1100 }
1101 eexecWrite(&eb, "] def\n");
1102 }
1103 if (privateDicts[fd].nFamilyBlues) {
1104 eexecWrite(&eb, "/FamilyBlues [");
1105 for (k = 0; k < privateDicts[fd].nFamilyBlues; ++k) {
1106 buf = GString::format("{0:s}{1:d}", k > 0 ? " " : "",
1107 privateDicts[fd].familyBlues[k]);
1108 eexecWrite(&eb, buf->getCString());
1109 delete buf;
1110 }
1111 eexecWrite(&eb, "] def\n");
1112 }
1113 if (privateDicts[fd].nFamilyOtherBlues) {
1114 eexecWrite(&eb, "/FamilyOtherBlues [");
1115 for (k = 0; k < privateDicts[fd].nFamilyOtherBlues; ++k) {
1116 buf = GString::format("{0:s}{1:d}", k > 0 ? " " : "",
1117 privateDicts[fd].familyOtherBlues[k]);
1118 eexecWrite(&eb, buf->getCString());
1119 delete buf;
1120 }
1121 eexecWrite(&eb, "] def\n");
1122 }
1123 if (privateDicts[fd].blueScale != 0.039625) {
1124 buf = GString::format("/BlueScale {0:.4g} def\n",
1125 privateDicts[fd].blueScale);
1126 eexecWrite(&eb, buf->getCString());
1127 delete buf;
1128 }
1129 if (privateDicts[fd].blueShift != 7) {
1130 buf = GString::format("/BlueShift {0:d} def\n",
1131 privateDicts[fd].blueShift);
1132 eexecWrite(&eb, buf->getCString());
1133 delete buf;
1134 }
1135 if (privateDicts[fd].blueFuzz != 1) {
1136 buf = GString::format("/BlueFuzz {0:d} def\n",
1137 privateDicts[fd].blueFuzz);
1138 eexecWrite(&eb, buf->getCString());
1139 delete buf;
1140 }
1141 if (privateDicts[fd].hasStdHW) {
1142 buf = GString::format("/StdHW [{0:.4g}] def\n", privateDicts[fd].stdHW);
1143 eexecWrite(&eb, buf->getCString());
1144 delete buf;
1145 }
1146 if (privateDicts[fd].hasStdVW) {
1147 buf = GString::format("/StdVW [{0:.4g}] def\n", privateDicts[fd].stdVW);
1148 eexecWrite(&eb, buf->getCString());
1149 delete buf;
1150 }
1151 if (privateDicts[fd].nStemSnapH) {
1152 // the StemSnapH array should be unique values in ascending order --
1153 // if not, just skip it
1154 for (k = 1; k < privateDicts[fd].nStemSnapH; ++k) {
1155 if (privateDicts[fd].stemSnapH[k-1] >= privateDicts[fd].stemSnapH[k]) {
1156 break;
1157 }
1158 }
1159 if (k == privateDicts[fd].nStemSnapH) {
1160 eexecWrite(&eb, "/StemSnapH [");
1161 for (k = 0; k < privateDicts[fd].nStemSnapH; ++k) {
1162 buf = GString::format("{0:s}{1:.4g}",
1163 k > 0 ? " " : "",
1164 privateDicts[fd].stemSnapH[k]);
1165 eexecWrite(&eb, buf->getCString());
1166 delete buf;
1167 }
1168 eexecWrite(&eb, "] def\n");
1169 }
1170 }
1171 if (privateDicts[fd].nStemSnapV) {
1172 // the StemSnapV array should be unique values in ascending order --
1173 // if not, just skip it
1174 for (k = 1; k < privateDicts[fd].nStemSnapV; ++k) {
1175 if (privateDicts[fd].stemSnapV[k-1] >= privateDicts[fd].stemSnapV[k]) {
1176 break;
1177 }
1178 }
1179 if (k == privateDicts[fd].nStemSnapV) {
1180 eexecWrite(&eb, "/StemSnapV [");
1181 for (k = 0; k < privateDicts[fd].nStemSnapV; ++k) {
1182 buf = GString::format("{0:s}{1:.4g}",
1183 k > 0 ? " " : "",
1184 privateDicts[fd].stemSnapV[k]);
1185 eexecWrite(&eb, buf->getCString());
1186 delete buf;
1187 }
1188 eexecWrite(&eb, "] def\n");
1189 }
1190 }
1191 if (privateDicts[fd].hasForceBold) {
1192 buf = GString::format("/ForceBold {0:s} def\n",
1193 privateDicts[fd].forceBold ? "true" : "false");
1194 eexecWrite(&eb, buf->getCString());
1195 delete buf;
1196 }
1197 if (privateDicts[fd].forceBoldThreshold != 0) {
1198 buf = GString::format("/ForceBoldThreshold {0:.4g} def\n",
1199 privateDicts[fd].forceBoldThreshold);
1200 eexecWrite(&eb, buf->getCString());
1201 delete buf;
1202 }
1203 if (privateDicts[fd].languageGroup != 0) {
1204 buf = GString::format("/LanguageGroup {0:d} def\n",
1205 privateDicts[fd].languageGroup);
1206 eexecWrite(&eb, buf->getCString());
1207 delete buf;
1208 }
1209 if (privateDicts[fd].expansionFactor != 0.06) {
1210 buf = GString::format("/ExpansionFactor {0:.4g} def\n",
1211 privateDicts[fd].expansionFactor);
1212 eexecWrite(&eb, buf->getCString());
1213 delete buf;
1214 }
1215
1216 // set up the subroutines
1217 ok = gTrue;
1218 getIndex(privateDicts[fd].subrsOffset, &subrIdx, &ok);
1219 if (!ok) {
1220 subrIdx.pos = -1;
1221 }
1222
1223 // start the CharStrings
1224 eexecWrite(&eb, "2 index /CharStrings 256 dict dup begin\n");
1225
1226 // write the .notdef CharString
1227 ok = gTrue;
1228 getIndexVal(&charStringsIdx, 0, &val, &ok);
1229 if (ok) {
1230 eexecCvtGlyph(&eb, ".notdef", val.pos, val.len,
1231 &subrIdx, &privateDicts[fd]);
1232 }
1233
1234 // write the CharStrings
1235 for (j = 0; j < 256 && i+j < nCIDs; ++j) {
1236 if (cidMap[i+j] >= 0) {
1237 ok = gTrue;
1238 getIndexVal(&charStringsIdx, cidMap[i+j], &val, &ok);
1239 if (ok) {
1240 buf = GString::format("c{0:02x}", j);
1241 eexecCvtGlyph(&eb, buf->getCString(), val.pos, val.len,
1242 &subrIdx, &privateDicts[fd]);
1243 delete buf;
1244 }
1245 }
1246 }
1247 eexecWrite(&eb, "end\n");
1248 eexecWrite(&eb, "end\n");
1249 eexecWrite(&eb, "readonly put\n");
1250 eexecWrite(&eb, "noaccess put\n");
1251 eexecWrite(&eb, "dup /FontName get exch definefont pop\n");
1252 eexecWrite(&eb, "mark currentfile closefile\n");
1253
1254 // trailer
1255 if (eb.line > 0) {
1256 (*outputFunc)(outputStream, "\n", 1);
1257 }
1258 for (j = 0; j < 8; ++j) {
1259 (*outputFunc)(outputStream, "0000000000000000000000000000000000000000000000000000000000000000\n", 65);
1260 }
1261 (*outputFunc)(outputStream, "cleartomark\n", 12);
1262 }
1263
1264 // write the Type 0 parent font
1265 (*outputFunc)(outputStream, "16 dict begin\n", 14);
1266 (*outputFunc)(outputStream, "/FontName /", 11);
1267 (*outputFunc)(outputStream, psName, (int)strlen(psName));
1268 (*outputFunc)(outputStream, " def\n", 5);
1269 (*outputFunc)(outputStream, "/FontType 0 def\n", 16);
1270 if (topDict.hasFontMatrix) {
1271 buf = GString::format("/FontMatrix [{0:.8g} {1:.8g} {2:.8g} {3:.8g} {4:.8g} {5:.8g}] def\n",
1272 topDict.fontMatrix[0], topDict.fontMatrix[1],
1273 topDict.fontMatrix[2], topDict.fontMatrix[3],
1274 topDict.fontMatrix[4], topDict.fontMatrix[5]);
1275 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
1276 delete buf;
1277 } else {
1278 (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
1279 }
1280 (*outputFunc)(outputStream, "/FMapType 2 def\n", 16);
1281 (*outputFunc)(outputStream, "/Encoding [\n", 12);
1282 for (i = 0; i < nCIDs; i += 256) {
1283 buf = GString::format("{0:d}\n", i >> 8);
1284 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
1285 delete buf;
1286 }
1287 (*outputFunc)(outputStream, "] def\n", 6);
1288 (*outputFunc)(outputStream, "/FDepVector [\n", 14);
1289 for (i = 0; i < nCIDs; i += 256) {
1290 (*outputFunc)(outputStream, "/", 1);
1291 (*outputFunc)(outputStream, psName, (int)strlen(psName));
1292 buf = GString::format("_{0:02x} findfont\n", i >> 8);
1293 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
1294 delete buf;
1295 }
1296 (*outputFunc)(outputStream, "] def\n", 6);
1297 (*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40);
1298
1299 gfree(cidMap);
1300 }
1301
1302 void FoFiType1C::eexecCvtGlyph(Type1CEexecBuf *eb, const char *glyphName,
1303 int offset, int nBytes,
1304 Type1CIndex *subrIdx,
1305 Type1CPrivateDict *pDict) {
1306 GString *buf;
1307 GString *charBuf;
1308
1309 // generate the charstring
1310 charBuf = new GString();
1311 cvtGlyph(offset, nBytes, charBuf, subrIdx, pDict, gTrue, 0);
1312
1313 buf = GString::format("/{0:s} {1:d} RD ", glyphName, charBuf->getLength());
1314 eexecWrite(eb, buf->getCString());
1315 delete buf;
1316 eexecWriteCharstring(eb, (Guchar *)charBuf->getCString(),
1317 charBuf->getLength());
1318 eexecWrite(eb, " ND\n");
1319
1320 delete charBuf;
1321 }
1322
1323 void FoFiType1C::cvtGlyph(int offset, int nBytes, GString *charBuf,
1324 Type1CIndex *subrIdx, Type1CPrivateDict *pDict,
1325 GBool top, int recursion) {
1326 Type1CIndexVal val;
1327 Type1COp zero, tmp;
1328 GBool ok, dInt;
1329 double d, dx, dy;
1330 Gushort r2;
1331 Guchar byte;
1332 int pos, subrBias, start, num, den, i, k;
1333
1334 if (recursion > type1cSubrRecursionLimit) {
1335 //~ error(-1, "Recursive loop in Type1C glyph");
1336 return;
1337 }
1338
1339 start = charBuf->getLength();
1340 if (top) {
1341 charBuf->append((char)73);
1342 charBuf->append((char)58);
1343 charBuf->append((char)147);
1344 charBuf->append((char)134);
1345 nOps = 0;
1346 nHints = 0;
1347 firstOp = gTrue;
1348 openPath = gFalse;
1349 }
1350
1351 zero.kind = type1COpInteger;
1352 zero.intgr = 0;
1353
1354 pos = offset;
1355 while (pos < offset + nBytes) {
1356 ok = gTrue;
1357 pos = getOp(pos, gTrue, &ok);
1358 if (!ok) {
1359 break;
1360 }
1361 if (ops[nOps - 1].kind == type1COpOperator) {
1362 --nOps; // drop the operator
1363 switch (ops[nOps].op) {
1364 case 0x0001: // hstem
1365 if (firstOp) {
1366 cvtGlyphWidth(nOps & 1, charBuf, pDict);
1367 firstOp = gFalse;
1368 }
1369 if (nOps & 1) {
1370 //~ error(-1, "Wrong number of args (%d) to Type 2 hstem", nOps);
1371 }
1372 d = 0;
1373 dInt = gTrue;
1374 for (k = 0; k+1 < nOps; k += 2) {
1375 // convert Type 2 edge hints (-20 or -21) to Type 1 ghost hints
1376 if (ops[k+1].isNegative()) {
1377 d += ops[k].toFloat() + ops[k+1].toFloat();
1378 dInt &= ops[k].kind == type1COpInteger;
1379 dInt &= ops[k+1].kind == type1COpInteger;
1380 if (dInt) {
1381 tmp.kind = type1COpInteger;
1382 tmp.intgr = (int)(d + 0.5);
1383 } else {
1384 tmp.kind = type1COpFloat;
1385 tmp.flt = d;
1386 }
1387 cvtNum(tmp, charBuf);
1388 if (ops[k+1].kind == type1COpInteger) {
1389 tmp.kind = type1COpInteger;
1390 tmp.intgr = -ops[k+1].intgr;
1391 } else if (ops[k+1].kind == type1COpRational) {
1392 tmp.kind = type1COpRational;
1393 tmp.rat.num = -ops[k+1].rat.num;
1394 tmp.rat.den = ops[k+1].rat.den;
1395 } else {
1396 tmp.kind = type1COpFloat;
1397 tmp.flt = -ops[k+1].toFloat();
1398 }
1399 cvtNum(tmp, charBuf);
1400 } else {
1401 d += ops[k].toFloat();
1402 dInt &= ops[k].kind == type1COpInteger;
1403 if (dInt) {
1404 tmp.kind = type1COpInteger;
1405 tmp.intgr = (int)(d + 0.5);
1406 } else {
1407 tmp.kind = type1COpFloat;
1408 tmp.flt = d;
1409 }
1410 cvtNum(tmp, charBuf);
1411 cvtNum(ops[k+1], charBuf);
1412 d += ops[k+1].toFloat();
1413 dInt &= ops[k+1].kind == type1COpInteger;
1414 }
1415 charBuf->append((char)1);
1416 }
1417 nHints += nOps / 2;
1418 nOps = 0;
1419 break;
1420 case 0x0003: // vstem
1421 if (firstOp) {
1422 cvtGlyphWidth(nOps & 1, charBuf, pDict);
1423 firstOp = gFalse;
1424 }
1425 if (nOps & 1) {
1426 //~ error(-1, "Wrong number of args (%d) to Type 2 vstem", nOps);
1427 }
1428 d = 0;
1429 dInt = gTrue;
1430 for (k = 0; k+1 < nOps; k += 2) {
1431 // convert Type 2 edge hints (-20 or -21) to Type 1 ghost hints
1432 if (ops[k+1].isNegative()) {
1433 d += ops[k].toFloat() + ops[k+1].toFloat();
1434 dInt &= ops[k].kind == type1COpInteger;
1435 dInt &= ops[k+1].kind == type1COpInteger;
1436 if (dInt) {
1437 tmp.kind = type1COpInteger;
1438 tmp.intgr = (int)(d + 0.5);
1439 } else {
1440 tmp.kind = type1COpFloat;
1441 tmp.flt = d;
1442 }
1443 cvtNum(tmp, charBuf);
1444 if (ops[k+1].kind == type1COpInteger) {
1445 tmp.kind = type1COpInteger;
1446 tmp.intgr = -ops[k+1].intgr;
1447 } else if (ops[k+1].kind == type1COpRational) {
1448 tmp.kind = type1COpRational;
1449 tmp.rat.num = -ops[k+1].rat.num;
1450 tmp.rat.den = ops[k+1].rat.den;
1451 } else {
1452 tmp.kind = type1COpFloat;
1453 tmp.flt = -ops[k+1].toFloat();
1454 }
1455 cvtNum(tmp, charBuf);
1456 } else {
1457 d += ops[k].toFloat();
1458 dInt &= ops[k].kind == type1COpInteger;
1459 if (dInt) {
1460 tmp.kind = type1COpInteger;
1461 tmp.intgr = (int)(d + 0.5);
1462 } else {
1463 tmp.kind = type1COpFloat;
1464 tmp.flt = d;
1465 }
1466 cvtNum(tmp, charBuf);
1467 cvtNum(ops[k+1], charBuf);
1468 d += ops[k+1].toFloat();
1469 dInt &= ops[k+1].kind == type1COpInteger;
1470 }
1471 charBuf->append((char)3);
1472 }
1473 nHints += nOps / 2;
1474 nOps = 0;
1475 break;
1476 case 0x0004: // vmoveto
1477 if (firstOp) {
1478 cvtGlyphWidth(nOps == 2, charBuf, pDict);
1479 firstOp = gFalse;
1480 }
1481 if (openPath) {
1482 charBuf->append((char)9);
1483 openPath = gFalse;
1484 }
1485 if (nOps != 1) {
1486 //~ error(-1, "Wrong number of args (%d) to Type 2 vmoveto", nOps);
1487 }
1488 cvtNum(ops[0], charBuf);
1489 charBuf->append((char)4);
1490 nOps = 0;
1491 break;
1492 case 0x0005: // rlineto
1493 if (nOps < 2 || nOps % 2 != 0) {
1494 //~ error(-1, "Wrong number of args (%d) to Type 2 rlineto", nOps);
1495 }
1496 for (k = 0; k+1 < nOps; k += 2) {
1497 cvtNum(ops[k], charBuf);
1498 cvtNum(ops[k+1], charBuf);
1499 charBuf->append((char)5);
1500 }
1501 nOps = 0;
1502 openPath = gTrue;
1503 break;
1504 case 0x0006: // hlineto
1505 if (nOps < 1) {
1506 //~ error(-1, "Wrong number of args (%d) to Type 2 hlineto", nOps);
1507 }
1508 for (k = 0; k < nOps; ++k) {
1509 cvtNum(ops[k], charBuf);
1510 charBuf->append((char)((k & 1) ? 7 : 6));
1511 }
1512 nOps = 0;
1513 openPath = gTrue;
1514 break;
1515 case 0x0007: // vlineto
1516 if (nOps < 1) {
1517 //~ error(-1, "Wrong number of args (%d) to Type 2 vlineto", nOps);
1518 }
1519 for (k = 0; k < nOps; ++k) {
1520 cvtNum(ops[k], charBuf);
1521 charBuf->append((char)((k & 1) ? 6 : 7));
1522 }
1523 nOps = 0;
1524 openPath = gTrue;
1525 break;
1526 case 0x0008: // rrcurveto
1527 if (nOps < 6 || nOps % 6 != 0) {
1528 //~ error(-1, "Wrong number of args (%d) to Type 2 rrcurveto", nOps);
1529 }
1530 for (k = 0; k < nOps; k += 6) {
1531 cvtNum(ops[k], charBuf);
1532 cvtNum(ops[k+1], charBuf);
1533 cvtNum(ops[k+2], charBuf);
1534 cvtNum(ops[k+3], charBuf);
1535 cvtNum(ops[k+4], charBuf);
1536 cvtNum(ops[k+5], charBuf);
1537 charBuf->append((char)8);
1538 }
1539 nOps = 0;
1540 openPath = gTrue;
1541 break;
1542 case 0x000a: // callsubr
1543 if (nOps >= 1) {
1544 subrBias = (subrIdx->len < 1240)
1545 ? 107 : (subrIdx->len < 33900) ? 1131 : 32768;
1546 k = subrBias + ops[nOps - 1].toInt();
1547 --nOps;
1548 ok = gTrue;
1549 getIndexVal(subrIdx, k, &val, &ok);
1550 if (ok) {
1551 cvtGlyph(val.pos, val.len, charBuf, subrIdx, pDict, gFalse,
1552 recursion + 1);
1553 }
1554 } else {
1555 //~ error(-1, "Too few args to Type 2 callsubr");
1556 }
1557 // don't clear the stack
1558 break;
1559 case 0x000b: // return
1560 // don't clear the stack
1561 break;
1562 case 0x000e: // endchar / seac
1563 if (firstOp) {
1564 cvtGlyphWidth(nOps == 1 || nOps == 5, charBuf, pDict);
1565 firstOp = gFalse;
1566 }
1567 if (openPath) {
1568 charBuf->append((char)9);
1569 openPath = gFalse;
1570 }
1571 if (nOps == 4) {
1572 cvtNum(zero, charBuf);
1573 cvtNum(ops[0], charBuf);
1574 cvtNum(ops[1], charBuf);
1575 cvtNum(ops[2], charBuf);
1576 cvtNum(ops[3], charBuf);
1577 charBuf->append((char)12)->append((char)6);
1578 } else if (nOps == 0) {
1579 charBuf->append((char)14);
1580 } else {
1581 //~ error(-1, "Wrong number of args (%d) to Type 2 endchar", nOps);
1582 }
1583 nOps = 0;
1584 break;
1585 case 0x000f: // (obsolete)
1586 // this op is ignored, but we need the glyph width
1587 if (firstOp) {
1588 cvtGlyphWidth(nOps > 0, charBuf, pDict);
1589 firstOp = gFalse;
1590 }
1591 nOps = 0;
1592 break;
1593 case 0x0010: // blend
1594 //~ error(-1, "Unimplemented Type 2 charstring op: %d", file[i]);
1595 nOps = 0;
1596 break;
1597 case 0x0012: // hstemhm
1598 // ignored
1599 if (firstOp) {
1600 cvtGlyphWidth(nOps & 1, charBuf, pDict);
1601 firstOp = gFalse;
1602 }
1603 if (nOps & 1) {
1604 //~ error(-1, "Wrong number of args (%d) to Type 2 hstemhm", nOps);
1605 }
1606 nHints += nOps / 2;
1607 nOps = 0;
1608 break;
1609 case 0x0013: // hintmask
1610 // ignored
1611 if (firstOp) {
1612 cvtGlyphWidth(nOps & 1, charBuf, pDict);
1613 firstOp = gFalse;
1614 }
1615 if (nOps > 0) {
1616 if (nOps & 1) {
1617 //~ error(-1, "Wrong number of args (%d) to Type 2 hintmask/vstemhm",
1618 //~ nOps);
1619 }
1620 nHints += nOps / 2;
1621 }
1622 pos += (nHints + 7) >> 3;
1623 nOps = 0;
1624 break;
1625 case 0x0014: // cntrmask
1626 // ignored
1627 if (firstOp) {
1628 cvtGlyphWidth(nOps & 1, charBuf, pDict);
1629 firstOp = gFalse;
1630 }
1631 if (nOps > 0) {
1632 if (nOps & 1) {
1633 //~ error(-1, "Wrong number of args (%d) to Type 2 cntrmask/vstemhm",
1634 //~ nOps);
1635 }
1636 nHints += nOps / 2;
1637 }
1638 pos += (nHints + 7) >> 3;
1639 nOps = 0;
1640 break;
1641 case 0x0015: // rmoveto
1642 if (firstOp) {
1643 cvtGlyphWidth(nOps == 3, charBuf, pDict);
1644 firstOp = gFalse;
1645 }
1646 if (openPath) {
1647 charBuf->append((char)9);
1648 openPath = gFalse;
1649 }
1650 if (nOps != 2) {
1651 //~ error(-1, "Wrong number of args (%d) to Type 2 rmoveto", nOps);
1652 }
1653 cvtNum(ops[0], charBuf);
1654 cvtNum(ops[1], charBuf);
1655 charBuf->append((char)21);
1656 nOps = 0;
1657 break;
1658 case 0x0016: // hmoveto
1659 if (firstOp) {
1660 cvtGlyphWidth(nOps == 2, charBuf, pDict);
1661 firstOp = gFalse;
1662 }
1663 if (openPath) {
1664 charBuf->append((char)9);
1665 openPath = gFalse;
1666 }
1667 if (nOps != 1) {
1668 //~ error(-1, "Wrong number of args (%d) to Type 2 hmoveto", nOps);
1669 }
1670 cvtNum(ops[0], charBuf);
1671 charBuf->append((char)22);
1672 nOps = 0;
1673 break;
1674 case 0x0017: // vstemhm
1675 // ignored
1676 if (firstOp) {
1677 cvtGlyphWidth(nOps & 1, charBuf, pDict);
1678 firstOp = gFalse;
1679 }
1680 if (nOps & 1) {
1681 //~ error(-1, "Wrong number of args (%d) to Type 2 vstemhm", nOps);
1682 }
1683 nHints += nOps / 2;
1684 nOps = 0;
1685 break;
1686 case 0x0018: // rcurveline
1687 if (nOps < 8 || (nOps - 2) % 6 != 0) {
1688 //~ error(-1, "Wrong number of args (%d) to Type 2 rcurveline", nOps);
1689 }
1690 for (k = 0; k <= nOps - 8; k += 6) {
1691 cvtNum(ops[k], charBuf);
1692 cvtNum(ops[k+1], charBuf);
1693 cvtNum(ops[k+2], charBuf);
1694 cvtNum(ops[k+3], charBuf);
1695 cvtNum(ops[k+4], charBuf);
1696 cvtNum(ops[k+5], charBuf);
1697 charBuf->append((char)8);
1698 }
1699 cvtNum(ops[k], charBuf);
1700 cvtNum(ops[k+1], charBuf);
1701 charBuf->append((char)5);
1702 nOps = 0;
1703 openPath = gTrue;
1704 break;
1705 case 0x0019: // rlinecurve
1706 if (nOps < 8 || (nOps - 6) % 2 != 0) {
1707 //~ error(-1, "Wrong number of args (%d) to Type 2 rlinecurve", nOps);
1708 }
1709 for (k = 0; k <= nOps - 8; k += 2) {
1710 cvtNum(ops[k], charBuf);
1711 cvtNum(ops[k+1], charBuf);
1712 charBuf->append((char)5);
1713 }
1714 cvtNum(ops[k], charBuf);
1715 cvtNum(ops[k+1], charBuf);
1716 cvtNum(ops[k+2], charBuf);
1717 cvtNum(ops[k+3], charBuf);
1718 cvtNum(ops[k+4], charBuf);
1719 cvtNum(ops[k+5], charBuf);
1720 charBuf->append((char)8);
1721 nOps = 0;
1722 openPath = gTrue;
1723 break;
1724 case 0x001a: // vvcurveto
1725 if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
1726 //~ error(-1, "Wrong number of args (%d) to Type 2 vvcurveto", nOps);
1727 }
1728 if (nOps % 2 == 1 && nOps >= 5) {
1729 cvtNum(ops[0], charBuf);
1730 cvtNum(ops[1], charBuf);
1731 cvtNum(ops[2], charBuf);
1732 cvtNum(ops[3], charBuf);
1733 cvtNum(zero, charBuf);
1734 cvtNum(ops[4], charBuf);
1735 charBuf->append((char)8);
1736 k = 5;
1737 } else {
1738 k = 0;
1739 }
1740 for (; k+3 < nOps; k += 4) {
1741 cvtNum(zero, charBuf);
1742 cvtNum(ops[k], charBuf);
1743 cvtNum(ops[k+1], charBuf);
1744 cvtNum(ops[k+2], charBuf);
1745 cvtNum(zero, charBuf);
1746 cvtNum(ops[k+3], charBuf);
1747 charBuf->append((char)8);
1748 }
1749 nOps = 0;
1750 openPath = gTrue;
1751 break;
1752 case 0x001b: // hhcurveto
1753 if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
1754 //~ error(-1, "Wrong number of args (%d) to Type 2 hhcurveto", nOps);
1755 }
1756 if (nOps % 2 == 1 && nOps >= 5) {
1757 cvtNum(ops[1], charBuf);
1758 cvtNum(ops[0], charBuf);
1759 cvtNum(ops[2], charBuf);
1760 cvtNum(ops[3], charBuf);
1761 cvtNum(ops[4], charBuf);
1762 cvtNum(zero, charBuf);
1763 charBuf->append((char)8);
1764 k = 5;
1765 } else {
1766 k = 0;
1767 }
1768 for (; k+3 < nOps; k += 4) {
1769 cvtNum(ops[k], charBuf);
1770 cvtNum(zero, charBuf);
1771 cvtNum(ops[k+1], charBuf);
1772 cvtNum(ops[k+2], charBuf);
1773 cvtNum(ops[k+3], charBuf);
1774 cvtNum(zero, charBuf);
1775 charBuf->append((char)8);
1776 }
1777 nOps = 0;
1778 openPath = gTrue;
1779 break;
1780 case 0x001d: // callgsubr
1781 if (nOps >= 1) {
1782 k = gsubrBias + ops[nOps - 1].toInt();
1783 --nOps;
1784 ok = gTrue;
1785 getIndexVal(&gsubrIdx, k, &val, &ok);
1786 if (ok) {
1787 cvtGlyph(val.pos, val.len, charBuf, subrIdx, pDict, gFalse,
1788 recursion + 1);
1789 }
1790 } else {
1791 //~ error(-1, "Too few args to Type 2 callgsubr");
1792 }
1793 // don't clear the stack
1794 break;
1795 case 0x001e: // vhcurveto
1796 if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
1797 //~ error(-1, "Wrong number of args (%d) to Type 2 vhcurveto", nOps);
1798 }
1799 for (k = 0; k+3 < nOps && k != nOps-5; k += 4) {
1800 if (k % 8 == 0) {
1801 cvtNum(ops[k], charBuf);
1802 cvtNum(ops[k+1], charBuf);
1803 cvtNum(ops[k+2], charBuf);
1804 cvtNum(ops[k+3], charBuf);
1805 charBuf->append((char)30);
1806 } else {
1807 cvtNum(ops[k], charBuf);
1808 cvtNum(ops[k+1], charBuf);
1809 cvtNum(ops[k+2], charBuf);
1810 cvtNum(ops[k+3], charBuf);
1811 charBuf->append((char)31);
1812 }
1813 }
1814 if (k == nOps-5) {
1815 if (k % 8 == 0) {
1816 cvtNum(zero, charBuf);
1817 cvtNum(ops[k], charBuf);
1818 cvtNum(ops[k+1], charBuf);
1819 cvtNum(ops[k+2], charBuf);
1820 cvtNum(ops[k+3], charBuf);
1821 cvtNum(ops[k+4], charBuf);
1822 } else {
1823 cvtNum(ops[k], charBuf);
1824 cvtNum(zero, charBuf);
1825 cvtNum(ops[k+1], charBuf);
1826 cvtNum(ops[k+2], charBuf);
1827 cvtNum(ops[k+4], charBuf);
1828 cvtNum(ops[k+3], charBuf);
1829 }
1830 charBuf->append((char)8);
1831 }
1832 nOps = 0;
1833 openPath = gTrue;
1834 break;
1835 case 0x001f: // hvcurveto
1836 if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
1837 //~ error(-1, "Wrong number of args (%d) to Type 2 hvcurveto", nOps);
1838 }
1839 for (k = 0; k+3 < nOps && k != nOps-5; k += 4) {
1840 if (k % 8 == 0) {
1841 cvtNum(ops[k], charBuf);
1842 cvtNum(ops[k+1], charBuf);
1843 cvtNum(ops[k+2], charBuf);
1844 cvtNum(ops[k+3], charBuf);
1845 charBuf->append((char)31);
1846 } else {
1847 cvtNum(ops[k], charBuf);
1848 cvtNum(ops[k+1], charBuf);
1849 cvtNum(ops[k+2], charBuf);
1850 cvtNum(ops[k+3], charBuf);
1851 charBuf->append((char)30);
1852 }
1853 }
1854 if (k == nOps-5) {
1855 if (k % 8 == 0) {
1856 cvtNum(ops[k], charBuf);
1857 cvtNum(zero, charBuf);
1858 cvtNum(ops[k+1], charBuf);
1859 cvtNum(ops[k+2], charBuf);
1860 cvtNum(ops[k+4], charBuf);
1861 cvtNum(ops[k+3], charBuf);
1862 } else {
1863 cvtNum(zero, charBuf);
1864 cvtNum(ops[k], charBuf);
1865 cvtNum(ops[k+1], charBuf);
1866 cvtNum(ops[k+2], charBuf);
1867 cvtNum(ops[k+3], charBuf);
1868 cvtNum(ops[k+4], charBuf);
1869 }
1870 charBuf->append((char)8);
1871 }
1872 nOps = 0;
1873 openPath = gTrue;
1874 break;
1875 case 0x0c00: // dotsection (should be Type 1 only?)
1876 // ignored
1877 nOps = 0;
1878 break;
1879 case 0x0c0c: // div
1880 if (nOps >= 2) {
1881 num = ops[nOps-2].toInt();
1882 den = ops[nOps-1].toInt();
1883 --nOps;
1884 ops[nOps-1].kind = type1COpRational;
1885 ops[nOps-1].rat.num = num;
1886 ops[nOps-1].rat.den = den;
1887 } else {
1888 //~ error(-1, "Wrong number of args (%d) to Type 2 div", nOps);
1889 }
1890 break;
1891 case 0x0c03: // and
1892 case 0x0c04: // or
1893 case 0x0c05: // not
1894 case 0x0c08: // store
1895 case 0x0c09: // abs
1896 case 0x0c0a: // add
1897 case 0x0c0b: // sub
1898 case 0x0c0d: // load
1899 case 0x0c0e: // neg
1900 case 0x0c0f: // eq
1901 case 0x0c12: // drop
1902 case 0x0c14: // put
1903 case 0x0c15: // get
1904 case 0x0c16: // ifelse
1905 case 0x0c17: // random
1906 case 0x0c18: // mul
1907 case 0x0c1a: // sqrt
1908 case 0x0c1b: // dup
1909 case 0x0c1c: // exch
1910 case 0x0c1d: // index
1911 case 0x0c1e: // roll
1912 //~ error(-1, "Unimplemented Type 2 charstring op: 12.%d", file[i+1]);
1913 nOps = 0;
1914 break;
1915 case 0x0c22: // hflex
1916 if (nOps == 7) {
1917 cvtNum(ops[0], charBuf);
1918 cvtNum(zero, charBuf);
1919 cvtNum(ops[1], charBuf);
1920 cvtNum(ops[2], charBuf);
1921 cvtNum(ops[3], charBuf);
1922 cvtNum(zero, charBuf);
1923 charBuf->append((char)8);
1924 cvtNum(ops[4], charBuf);
1925 cvtNum(zero, charBuf);
1926 cvtNum(ops[5], charBuf);
1927 if (ops[2].kind == type1COpInteger) {
1928 tmp.kind = type1COpInteger;
1929 tmp.intgr = -ops[2].intgr;
1930 } else if (ops[2].kind == type1COpRational) {
1931 tmp.kind = type1COpRational;
1932 tmp.rat.num = -ops[2].rat.num;
1933 tmp.rat.den = ops[2].rat.den;
1934 } else {
1935 tmp.kind = type1COpFloat;
1936 tmp.flt = -ops[2].toFloat();
1937 }
1938 cvtNum(tmp, charBuf);
1939 cvtNum(ops[6], charBuf);
1940 cvtNum(zero, charBuf);
1941 charBuf->append((char)8);
1942 } else {
1943 //~ error(-1, "Wrong number of args (%d) to Type 2 hflex", nOps);
1944 }
1945 nOps = 0;
1946 openPath = gTrue;
1947 break;
1948 case 0x0c23: // flex
1949 if (nOps == 13) {
1950 cvtNum(ops[0], charBuf);
1951 cvtNum(ops[1], charBuf);
1952 cvtNum(ops[2], charBuf);
1953 cvtNum(ops[3], charBuf);
1954 cvtNum(ops[4], charBuf);
1955 cvtNum(ops[5], charBuf);
1956 charBuf->append((char)8);
1957 cvtNum(ops[6], charBuf);
1958 cvtNum(ops[7], charBuf);
1959 cvtNum(ops[8], charBuf);
1960 cvtNum(ops[9], charBuf);
1961 cvtNum(ops[10], charBuf);
1962 cvtNum(ops[11], charBuf);
1963 charBuf->append((char)8);
1964 } else {
1965 //~ error(-1, "Wrong number of args (%d) to Type 2 flex", nOps);
1966 }
1967 nOps = 0;
1968 openPath = gTrue;
1969 break;
1970 case 0x0c24: // hflex1
1971 if (nOps == 9) {
1972 cvtNum(ops[0], charBuf);
1973 cvtNum(ops[1], charBuf);
1974 cvtNum(ops[2], charBuf);
1975 cvtNum(ops[3], charBuf);
1976 cvtNum(ops[4], charBuf);
1977 cvtNum(zero, charBuf);
1978 charBuf->append((char)8);
1979 cvtNum(ops[5], charBuf);
1980 cvtNum(zero, charBuf);
1981 cvtNum(ops[6], charBuf);
1982 cvtNum(ops[7], charBuf);
1983 cvtNum(ops[8], charBuf);
1984 if (ops[1].kind == type1COpInteger &&
1985 ops[3].kind == type1COpInteger &&
1986 ops[7].kind == type1COpInteger) {
1987 tmp.kind = type1COpInteger;
1988 tmp.intgr = -(ops[1].intgr + ops[3].intgr + ops[7].intgr);
1989 } else {
1990 tmp.kind = type1COpFloat;
1991 tmp.flt = -(ops[1].toFloat() + ops[3].toFloat() + ops[7].toFloat());
1992 }
1993 cvtNum(tmp, charBuf);
1994 charBuf->append((char)8);
1995 } else {
1996 //~ error(-1, "Wrong number of args (%d) to Type 2 hflex1", nOps);
1997 }
1998 nOps = 0;
1999 openPath = gTrue;
2000 break;
2001 case 0x0c25: // flex1
2002 if (nOps == 11) {
2003 cvtNum(ops[0], charBuf);
2004 cvtNum(ops[1], charBuf);
2005 cvtNum(ops[2], charBuf);
2006 cvtNum(ops[3], charBuf);
2007 cvtNum(ops[4], charBuf);
2008 cvtNum(ops[5], charBuf);
2009 charBuf->append((char)8);
2010 cvtNum(ops[6], charBuf);
2011 cvtNum(ops[7], charBuf);
2012 cvtNum(ops[8], charBuf);
2013 cvtNum(ops[9], charBuf);
2014 dx = ops[0].toFloat() + ops[2].toFloat() + ops[4].toFloat()
2015 + ops[6].toFloat() + ops[8].toFloat();
2016 dy = ops[1].toFloat() + ops[3].toFloat() + ops[5].toFloat()
2017 + ops[7].toFloat() + ops[9].toFloat();
2018 if (fabs(dx) > fabs(dy)) {
2019 cvtNum(ops[10], charBuf);
2020 if (ops[1].kind == type1COpInteger &&
2021 ops[3].kind == type1COpInteger &&
2022 ops[5].kind == type1COpInteger &&
2023 ops[7].kind == type1COpInteger &&
2024 ops[9].kind == type1COpInteger) {
2025 tmp.kind = type1COpInteger;
2026 tmp.intgr = -(int)dy;
2027 } else {
2028 tmp.kind = type1COpFloat;
2029 tmp.flt = -dy;
2030 }
2031 cvtNum(tmp, charBuf);
2032 } else {
2033 if (ops[0].kind == type1COpInteger &&
2034 ops[2].kind == type1COpInteger &&
2035 ops[4].kind == type1COpInteger &&
2036 ops[6].kind == type1COpInteger &&
2037 ops[8].kind == type1COpInteger) {
2038 tmp.kind = type1COpInteger;
2039 tmp.intgr = -(int)dx;
2040 } else {
2041 tmp.kind = type1COpFloat;
2042 tmp.flt = -dx;
2043 }
2044 cvtNum(tmp, charBuf);
2045 cvtNum(ops[10], charBuf);
2046 }
2047 charBuf->append((char)8);
2048 } else {
2049 //~ error(-1, "Wrong number of args (%d) to Type 2 flex1", nOps);
2050 }
2051 nOps = 0;
2052 openPath = gTrue;
2053 break;
2054 default:
2055 //~ error(-1, "Illegal Type 2 charstring op: %04x",
2056 //~ ops[nOps].op);
2057 nOps = 0;
2058 break;
2059 }
2060 }
2061 }
2062
2063 // charstring encryption
2064 if (top) {
2065 r2 = 4330;
2066 for (i = start; i < charBuf->getLength(); ++i) {
2067 byte = (Guchar)(charBuf->getChar(i) ^ (r2 >> 8));
2068 charBuf->setChar(i, byte);
2069 r2 = (Gushort)((byte + r2) * 52845 + 22719);
2070 }
2071 }
2072 }
2073
2074 void FoFiType1C::cvtGlyphWidth(GBool useOp, GString *charBuf,
2075 Type1CPrivateDict *pDict) {
2076 Type1COp zero, w;
2077 int i;
2078
2079 if (useOp) {
2080 if (pDict->nominalWidthXInt & (ops[0].kind == type1COpInteger)) {
2081 w.kind = type1COpInteger;
2082 w.intgr = (int)(pDict->nominalWidthX + ops[0].intgr);
2083 } else {
2084 w.kind = type1COpFloat;
2085 w.flt = pDict->nominalWidthX + ops[0].toFloat();
2086 }
2087 for (i = 1; i < nOps; ++i) {
2088 ops[i-1] = ops[i];
2089 }
2090 --nOps;
2091 } else {
2092 if (pDict->defaultWidthXInt) {
2093 w.kind = type1COpInteger;
2094 w.intgr = (int)pDict->defaultWidthX;
2095 } else {
2096 w.kind = type1COpFloat;
2097 w.flt = pDict->defaultWidthX;
2098 }
2099 }
2100 zero.kind = type1COpInteger;
2101 zero.intgr = 0;
2102 cvtNum(zero, charBuf);
2103 cvtNum(w, charBuf);
2104 charBuf->append((char)13);
2105 }
2106
2107 void FoFiType1C::cvtNum(Type1COp op, GString *charBuf) {
2108 Type1COp tmp;
2109 Guchar buf[12];
2110 int y, n;
2111
2112 n = 0;
2113 switch (op.kind) {
2114 case type1COpInteger:
2115 y = op.intgr;
2116 if (y >= -107 && y <= 107) {
2117 buf[0] = (Guchar)(y + 139);
2118 n = 1;
2119 } else if (y > 107 && y <= 1131) {
2120 y -= 108;
2121 buf[0] = (Guchar)((y >> 8) + 247);
2122 buf[1] = (Guchar)(y & 0xff);
2123 n = 2;
2124 } else if (y < -107 && y >= -1131) {
2125 y = -y - 108;
2126 buf[0] = (Guchar)((y >> 8) + 251);
2127 buf[1] = (Guchar)(y & 0xff);
2128 n = 2;
2129 } else {
2130 buf[0] = 255;
2131 buf[1] = (Guchar)(y >> 24);
2132 buf[2] = (Guchar)(y >> 16);
2133 buf[3] = (Guchar)(y >> 8);
2134 buf[4] = (Guchar)y;
2135 n = 5;
2136 }
2137 break;
2138 case type1COpFloat:
2139 if (op.flt >= -32768 && op.flt < 32768) {
2140 y = (int)(op.flt * 256.0);
2141 buf[0] = 255;
2142 buf[1] = (Guchar)(y >> 24);
2143 buf[2] = (Guchar)(y >> 16);
2144 buf[3] = (Guchar)(y >> 8);
2145 buf[4] = (Guchar)y;
2146 buf[5] = 255;
2147 buf[6] = 0;
2148 buf[7] = 0;
2149 buf[8] = 1;
2150 buf[9] = 0;
2151 buf[10] = 12;
2152 buf[11] = 12;
2153 n = 12;
2154 } else {
2155 //~ error(-1, "Type 2 fixed point constant out of range");
2156 }
2157 break;
2158 case type1COpRational:
2159 tmp.kind = type1COpInteger;
2160 tmp.intgr = op.rat.num;
2161 cvtNum(tmp, charBuf);
2162 tmp.intgr = op.rat.den;
2163 cvtNum(tmp, charBuf);
2164 buf[0] = 0x0c;
2165 buf[1] = 0x0c;
2166 n = 2;
2167 break;
2168 default: // shouldn't happen
2169 break;
2170 }
2171 charBuf->append((char *)buf, n);
2172 }
2173
2174 void FoFiType1C::eexecWrite(Type1CEexecBuf *eb, const char *s) {
2175 Guchar *p;
2176 Guchar x;
2177
2178 for (p = (Guchar *)s; *p; ++p) {
2179 x = *p ^ (Guchar)(eb->r1 >> 8);
2180 eb->r1 = (Gushort)((x + eb->r1) * 52845 + 22719);
2181 if (eb->ascii) {
2182 (*eb->outputFunc)(eb->outputStream, &hexChars[x >> 4], 1);
2183 (*eb->outputFunc)(eb->outputStream, &hexChars[x & 0x0f], 1);
2184 eb->line += 2;
2185 if (eb->line == 64) {
2186 (*eb->outputFunc)(eb->outputStream, "\n", 1);
2187 eb->line = 0;
2188 }
2189 } else {
2190 (*eb->outputFunc)(eb->outputStream, (char *)&x, 1);
2191 }
2192 }
2193 }
2194
2195 void FoFiType1C::eexecWriteCharstring(Type1CEexecBuf *eb,
2196 Guchar *s, int n) {
2197 Guchar x;
2198 int i;
2199
2200 // eexec encryption
2201 for (i = 0; i < n; ++i) {
2202 x = s[i] ^ (Guchar)(eb->r1 >> 8);
2203 eb->r1 = (Gushort)((x + eb->r1) * 52845 + 22719);
2204 if (eb->ascii) {
2205 (*eb->outputFunc)(eb->outputStream, &hexChars[x >> 4], 1);
2206 (*eb->outputFunc)(eb->outputStream, &hexChars[x & 0x0f], 1);
2207 eb->line += 2;
2208 if (eb->line == 64) {
2209 (*eb->outputFunc)(eb->outputStream, "\n", 1);
2210 eb->line = 0;
2211 }
2212 } else {
2213 (*eb->outputFunc)(eb->outputStream, (char *)&x, 1);
2214 }
2215 }
2216 }
2217
2218 void FoFiType1C::writePSString(char *s, FoFiOutputFunc outputFunc,
2219 void *outputStream) {
2220 char buf[80];
2221 char *p;
2222 int i, c;
2223
2224 i = 0;
2225 buf[i++] = '(';
2226 for (p = s; *p; ++p) {
2227 c = *p & 0xff;
2228 if (c == '(' || c == ')' || c == '\\') {
2229 buf[i++] = '\\';
2230 buf[i++] = (char)c;
2231 } else if (c < 0x20 || c >= 0x80) {
2232 buf[i++] = '\\';
2233 buf[i++] = (char)('0' + ((c >> 6) & 7));
2234 buf[i++] = (char)('0' + ((c >> 3) & 7));
2235 buf[i++] = (char)('0' + (c & 7));
2236 } else {
2237 buf[i++] = (char)c;
2238 }
2239 if (i >= 64) {
2240 buf[i++] = '\\';
2241 buf[i++] = '\n';
2242 (*outputFunc)(outputStream, buf, i);
2243 i = 0;
2244 }
2245 }
2246 buf[i++] = ')';
2247 (*outputFunc)(outputStream, buf, i);
2248 }
2249
2250 void FoFiType1C::convertToOpenType(FoFiOutputFunc outputFunc,
2251 void *outputStream,
2252 int nWidths, Gushort *widths,
2253 Guchar *cmapTable, int cmapTableLen) {
2254 // dummy OS/2 table (taken from FoFiTrueType::writeTTF)
2255 static Guchar os2Tab[86] = {
2256 0, 1, // version
2257 0, 1, // xAvgCharWidth
2258 0x01, 0x90, // usWeightClass
2259 0, 5, // usWidthClass
2260 0, 0, // fsType
2261 0, 0, // ySubscriptXSize
2262 0, 0, // ySubscriptYSize
2263 0, 0, // ySubscriptXOffset
2264 0, 0, // ySubscriptYOffset
2265 0, 0, // ySuperscriptXSize
2266 0, 0, // ySuperscriptYSize
2267 0, 0, // ySuperscriptXOffset
2268 0, 0, // ySuperscriptYOffset
2269 0, 0, // yStrikeoutSize
2270 0, 0, // yStrikeoutPosition
2271 0, 0, // sFamilyClass
2272 0, 0, 0, 0, 0, // panose
2273 0, 0, 0, 0, 0,
2274 0, 0, 0, 0, // ulUnicodeRange1
2275 0, 0, 0, 0, // ulUnicodeRange2
2276 0, 0, 0, 0, // ulUnicodeRange3
2277 0, 0, 0, 0, // ulUnicodeRange4
2278 0, 0, 0, 0, // achVendID
2279 0, 0, // fsSelection
2280 0, 0, // usFirstCharIndex
2281 0, 0, // usLastCharIndex
2282 0, 0, // sTypoAscender
2283 0, 0, // sTypoDescender
2284 0, 0, // sTypoLineGap
2285 0x20, 0x00, // usWinAscent
2286 0x20, 0x00, // usWinDescent
2287 0, 0, 0, 1, // ulCodePageRange1
2288 0, 0, 0, 0 // ulCodePageRange2
2289 };
2290 Guchar headTable[54], hheaTable[36], maxpTable[6];
2291 Guchar nameTable[26], postTable[32];
2292 Guchar *hmtxTable;
2293 static const char *tableTag[9] = {
2294 "CFF ",
2295 "OS/2",
2296 "cmap",
2297 "head",
2298 "hhea",
2299 "hmtx",
2300 "maxp",
2301 "name",
2302 "post"
2303 };
2304 Guchar *tableData[9];
2305 int tableLength[9];
2306 Guchar header[12 + 9*16];
2307 double mat[6];
2308 Gushort maxWidth;
2309 Guint checksum, fileChecksum;
2310 int unitsPerEm, xMin, yMin, xMax, yMax, offset, i;
2311
2312 //--- CFF_ table
2313 tableData[0] = file;
2314 tableLength[0] = len;
2315
2316 //--- OS/2 table
2317 tableData[1] = os2Tab;
2318 tableLength[1] = 86;
2319
2320 //--- cmap table
2321 tableData[2] = cmapTable;
2322 tableLength[2] = cmapTableLen;
2323
2324 //--- head table
2325 getFontMatrix(mat);
2326 if (mat[0] == 0) {
2327 unitsPerEm = 1000;
2328 } else {
2329 unitsPerEm = (int)(1 / mat[0] + 0.5);
2330 }
2331 xMin = (int)(topDict.fontBBox[0] + 0.5);
2332 yMin = (int)(topDict.fontBBox[1] + 0.5);
2333 xMax = (int)(topDict.fontBBox[2] + 0.5);
2334 yMax = (int)(topDict.fontBBox[3] + 0.5);
2335 headTable[ 0] = 0x00; // version
2336 headTable[ 1] = 0x01;
2337 headTable[ 2] = 0x00;
2338 headTable[ 3] = 0x00;
2339 headTable[ 4] = 0x00; // revision
2340 headTable[ 5] = 0x00;
2341 headTable[ 6] = 0x00;
2342 headTable[ 7] = 0x00;
2343 headTable[ 8] = 0x00; // checksumAdjustment
2344 headTable[ 9] = 0x00; // (set later)
2345 headTable[10] = 0x00;
2346 headTable[11] = 0x00;
2347 headTable[12] = 0x5f; // magicNumber
2348 headTable[13] = 0x0f;
2349 headTable[14] = 0x3c;
2350 headTable[15] = 0xf5;
2351 headTable[16] = 0x00; // flags
2352 headTable[17] = 0x03;
2353 headTable[18] = (Guchar)(unitsPerEm >> 8); // unitsPerEm
2354 headTable[19] = (Guchar)unitsPerEm;
2355 headTable[20] = 0x00; // created
2356 headTable[21] = 0x00;
2357 headTable[22] = 0x00;
2358 headTable[23] = 0x00;
2359 headTable[24] = 0x00;
2360 headTable[25] = 0x00;
2361 headTable[26] = 0x00;
2362 headTable[27] = 0x00;
2363 headTable[28] = 0x00; // modified
2364 headTable[29] = 0x00;
2365 headTable[30] = 0x00;
2366 headTable[31] = 0x00;
2367 headTable[32] = 0x00;
2368 headTable[33] = 0x00;
2369 headTable[34] = 0x00;
2370 headTable[35] = 0x00;
2371 headTable[36] = (Guchar)(xMin >> 8); // xMin
2372 headTable[37] = (Guchar)xMin;
2373 headTable[38] = (Guchar)(yMin >> 8); // yMin
2374 headTable[39] = (Guchar)yMin;
2375 headTable[40] = (Guchar)(xMax >> 8); // xMax
2376 headTable[41] = (Guchar)xMax;
2377 headTable[42] = (Guchar)(yMax >> 8); // yMax
2378 headTable[43] = (Guchar)yMax;
2379 headTable[44] = 0; // macStyle
2380 headTable[45] = 0;
2381 headTable[46] = 0; // lowestRecPPEM
2382 headTable[47] = 3;
2383 headTable[48] = 0; // fontDirectionHint
2384 headTable[49] = 2; // (deprecated)
2385 headTable[50] = 0; // indexToLocFormat
2386 headTable[51] = 0; // (n/a to CFF fonts)
2387 headTable[52] = 0; // glyphDataFormat
2388 headTable[53] = 0; // (n/a to CFF fonts)
2389 tableData[3] = headTable;
2390 tableLength[3] = 54;
2391
2392 //--- hhea table
2393 maxWidth = widths[0];
2394 for (i = 1; i < nWidths; ++i) {
2395 if (widths[i] > maxWidth) {
2396 maxWidth = widths[i];
2397 }
2398 }
2399 hheaTable[ 0] = 0x00; // version
2400 hheaTable[ 1] = 0x01;
2401 hheaTable[ 2] = 0x00;
2402 hheaTable[ 3] = 0x00;
2403 hheaTable[ 4] = (Guchar)(yMax >> 8); // ascender
2404 hheaTable[ 5] = (Guchar)yMax;
2405 hheaTable[ 6] = (Guchar)(yMin >> 8); // descender
2406 hheaTable[ 7] = (Guchar)yMin;
2407 hheaTable[ 8] = 0; // lineGap
2408 hheaTable[ 9] = 0;
2409 hheaTable[10] = (Guchar)(maxWidth >> 8); // advanceWidthMax
2410 hheaTable[11] = (Guchar)maxWidth;
2411 hheaTable[12] = 0; // minLeftSideBearing
2412 hheaTable[13] = 0;
2413 hheaTable[14] = 0; // minRightSideBearing
2414 hheaTable[15] = 0;
2415 hheaTable[16] = (Guchar)(maxWidth >> 8); // xMaxExtent
2416 hheaTable[17] = (Guchar)maxWidth;
2417 hheaTable[18] = 0; // caretSlopeRise
2418 hheaTable[19] = 1;
2419 hheaTable[20] = 0; // caretSlopeRun
2420 hheaTable[21] = 0;
2421 hheaTable[22] = 0; // caretOffset
2422 hheaTable[23] = 0;
2423 hheaTable[24] = 0; // reserved
2424 hheaTable[25] = 0;
2425 hheaTable[26] = 0; // reserved
2426 hheaTable[27] = 0;
2427 hheaTable[28] = 0; // reserved
2428 hheaTable[29] = 0;
2429 hheaTable[30] = 0; // reserved
2430 hheaTable[31] = 0;
2431 hheaTable[32] = 0; // metricDataFormat
2432 hheaTable[33] = 0;
2433 hheaTable[34] = (Guchar)(nWidths >> 8); // numberOfHMetrics
2434 hheaTable[35] = (Guchar)nWidths;
2435 tableData[4] = hheaTable;
2436 tableLength[4] = 36;
2437
2438 //--- hmtx table
2439 //~ this currently sets LSB to 0 for all glyphs
2440 hmtxTable = (Guchar *)gmallocn(nWidths, 4);
2441 for (i = 0; i < nWidths; ++i) {
2442 hmtxTable[4*i ] = (Guchar)(widths[i] >> 8);
2443 hmtxTable[4*i+1] = (Guchar)widths[i];
2444 hmtxTable[4*i+2] = 0;
2445 hmtxTable[4*i+3] = 0;
2446 }
2447 tableData[5] = hmtxTable;
2448 tableLength[5] = 4 * nWidths;
2449
2450 //--- maxp table
2451 maxpTable[0] = 0x00; // version = 0.5
2452 maxpTable[1] = 0x00;
2453 maxpTable[2] = 0x50;
2454 maxpTable[3] = 0x00;
2455 maxpTable[4] = (Guchar)(nGlyphs >> 8); // numGlyphs
2456 maxpTable[5] = (Guchar)nGlyphs;
2457 tableData[6] = maxpTable;
2458 tableLength[6] = 6;
2459
2460 //--- name table
2461 nameTable[ 0] = 0x00; // format
2462 nameTable[ 1] = 0x00;
2463 nameTable[ 2] = 0x00; // count
2464 nameTable[ 3] = 0x01;
2465 nameTable[ 4] = 0x00; // stringOffset
2466 nameTable[ 5] = 0x12;
2467 nameTable[ 6] = 0x00; // platformID
2468 nameTable[ 7] = 0x00;
2469 nameTable[ 8] = 0x00; // encodingID
2470 nameTable[ 9] = 0x03;
2471 nameTable[10] = 0x00; // languageID
2472 nameTable[11] = 0x00;
2473 nameTable[12] = 0x00; // nameID
2474 nameTable[13] = 0x00;
2475 nameTable[14] = 0x00; // length
2476 nameTable[15] = 0x08;
2477 nameTable[16] = 0x00; // offset
2478 nameTable[17] = 0x00;
2479 nameTable[18] = 0x00; // string data
2480 nameTable[19] = (Guchar)'n';
2481 nameTable[20] = 0x00;
2482 nameTable[21] = (Guchar)'o';
2483 nameTable[22] = 0x00;
2484 nameTable[23] = (Guchar)'n';
2485 nameTable[24] = 0x00;
2486 nameTable[25] = (Guchar)'e';
2487 tableData[7] = nameTable;
2488 tableLength[7] = 26;
2489
2490 //--- post table
2491 postTable[ 0] = 0x00; // version = 3.0
2492 postTable[ 1] = 0x03;
2493 postTable[ 2] = 0x00;
2494 postTable[ 3] = 0x00;
2495 postTable[ 4] = 0x00; // italicAngle
2496 postTable[ 5] = 0x00;
2497 postTable[ 6] = 0x00;
2498 postTable[ 7] = 0x00;
2499 postTable[ 8] = 0x00; // underlinePosition
2500 postTable[ 9] = 0x00;
2501 postTable[10] = 0x00; // underlineThickness
2502 postTable[11] = 0x00;
2503 postTable[12] = 0x00; // isFixedPitch
2504 postTable[13] = 0x00;
2505 postTable[14] = 0x00;
2506 postTable[15] = 0x00;
2507 postTable[16] = 0x00; // minMemType42
2508 postTable[17] = 0x00;
2509 postTable[18] = 0x00;
2510 postTable[19] = 0x00;
2511 postTable[20] = 0x00; // maxMemType42
2512 postTable[21] = 0x00;
2513 postTable[22] = 0x00;
2514 postTable[23] = 0x00;
2515 postTable[24] = 0x00; // minMemType1
2516 postTable[25] = 0x00;
2517 postTable[26] = 0x00;
2518 postTable[27] = 0x00;
2519 postTable[28] = 0x00; // maxMemType1
2520 postTable[29] = 0x00;
2521 postTable[30] = 0x00;
2522 postTable[31] = 0x00;
2523 tableData[8] = postTable;
2524 tableLength[8] = 32;
2525
2526 //--- header and table directory
2527 header[ 0] = 'O'; // sfnt version
2528 header[ 1] = 'T';
2529 header[ 2] = 'T';
2530 header[ 3] = 'O';
2531 header[ 4] = 0x00; // numTables
2532 header[ 5] = 0x09;
2533 header[ 6] = 0x00; // searchRange
2534 header[ 7] = 0x80;
2535 header[ 8] = 0x00; // entrySelector
2536 header[ 9] = 0x03;
2537 header[10] = 0x00; // rangeShift
2538 header[11] = 0x10;
2539 offset = 12 + 9*16;
2540 fileChecksum = 0;
2541 for (i = 0; i < 9; ++i) {
2542 header[12 + i*16 + 0] = tableTag[i][0];
2543 header[12 + i*16 + 1] = tableTag[i][1];
2544 header[12 + i*16 + 2] = tableTag[i][2];
2545 header[12 + i*16 + 3] = tableTag[i][3];
2546 checksum = computeOpenTypeTableChecksum(tableData[i], tableLength[i]);
2547 fileChecksum += checksum;
2548 header[12 + i*16 + 4] = (Guchar)(checksum >> 24);
2549 header[12 + i*16 + 5] = (Guchar)(checksum >> 16);
2550 header[12 + i*16 + 6] = (Guchar)(checksum >> 8);
2551 header[12 + i*16 + 7] = (Guchar)checksum;
2552 header[12 + i*16 + 8] = (Guchar)(offset >> 24);
2553 header[12 + i*16 + 9] = (Guchar)(offset >> 16);
2554 header[12 + i*16 + 10] = (Guchar)(offset >> 8);
2555 header[12 + i*16 + 11] = (Guchar)offset;
2556 header[12 + i*16 + 12] = (Guchar)(tableLength[i] >> 24);
2557 header[12 + i*16 + 13] = (Guchar)(tableLength[i] >> 16);
2558 header[12 + i*16 + 14] = (Guchar)(tableLength[i] >> 8);
2559 header[12 + i*16 + 15] = (Guchar)tableLength[i];
2560 offset += tableLength[i];
2561 if (tableLength[i] & 3) {
2562 offset += 4 - (tableLength[i] & 3);
2563 }
2564 }
2565
2566 //--- file checksum
2567 fileChecksum += computeOpenTypeTableChecksum(header, 12 + 9*16);
2568 fileChecksum = 0xb1b0afba - fileChecksum;
2569 headTable[ 8] = (Guchar)(fileChecksum >> 24);
2570 headTable[ 9] = (Guchar)(fileChecksum >> 16);
2571 headTable[10] = (Guchar)(fileChecksum >> 8);
2572 headTable[11] = (Guchar)fileChecksum;
2573
2574 //--- write the OpenType font
2575 (*outputFunc)(outputStream, (char *)header, 12 + 9*16);
2576 for (i = 0; i < 9; ++i) {
2577 (*outputFunc)(outputStream, (char *)tableData[i], tableLength[i]);
2578 if (tableLength[i] & 3) {
2579 (*outputFunc)(outputStream, "\0\0\0", 4 - (tableLength[i] & 3));
2580 }
2581 }
2582
2583 gfree(hmtxTable);
2584 }
2585
2586 Guint FoFiType1C::computeOpenTypeTableChecksum(Guchar *data, int length) {
2587 Guint checksum, word;
2588 int i;
2589
2590 checksum = 0;
2591 for (i = 0; i+3 < length; i += 4) {
2592 word = ((data[i ] & 0xff) << 24) +
2593 ((data[i+1] & 0xff) << 16) +
2594 ((data[i+2] & 0xff) << 8) +
2595 (data[i+3] & 0xff);
2596 checksum += word;
2597 }
2598 if (length & 3) {
2599 word = 0;
2600 i = length & ~3;
2601 switch (length & 3) {
2602 case 3:
2603 word |= (data[i+2] & 0xff) << 8;
2604 case 2:
2605 word |= (data[i+1] & 0xff) << 16;
2606 case 1:
2607 word |= (data[i ] & 0xff) << 24;
2608 break;
2609 }
2610 checksum += word;
2611 }
2612 return checksum;
2613 }
2614
2615 GBool FoFiType1C::parse() {
2616 Type1CIndex fdIdx;
2617 Type1CIndexVal val;
2618 int i;
2619
2620 parsedOk = gTrue;
2621
2622 // some tools embed Type 1C fonts with an extra whitespace char at
2623 // the beginning
2624 if (len > 0 && file[0] != '\x01') {
2625 ++file;
2626 --len;
2627 }
2628
2629 // find the indexes
2630 getIndex(getU8(2, &parsedOk), &nameIdx, &parsedOk);
2631 getIndex(nameIdx.endPos, &topDictIdx, &parsedOk);
2632 getIndex(topDictIdx.endPos, &stringIdx, &parsedOk);
2633 getIndex(stringIdx.endPos, &gsubrIdx, &parsedOk);
2634 if (!parsedOk) {
2635 return gFalse;
2636 }
2637 gsubrBias = (gsubrIdx.len < 1240) ? 107
2638 : (gsubrIdx.len < 33900) ? 1131 : 32768;
2639
2640 // read the first font name
2641 getIndexVal(&nameIdx, 0, &val, &parsedOk);
2642 if (!parsedOk) {
2643 return gFalse;
2644 }
2645 name = new GString((char *)&file[val.pos], val.len);
2646
2647 // read the top dict for the first font
2648 readTopDict();
2649
2650 // for CID fonts: read the FDArray dicts and private dicts
2651 if (topDict.firstOp == 0x0c1e) {
2652 if (topDict.fdArrayOffset == 0) {
2653 nFDs = 1;
2654 privateDicts = (Type1CPrivateDict *)gmalloc(sizeof(Type1CPrivateDict));
2655 readPrivateDict(0, 0, &privateDicts[0]);
2656 } else {
2657 getIndex(topDict.fdArrayOffset, &fdIdx, &parsedOk);
2658 if (!parsedOk) {
2659 return gFalse;
2660 }
2661 nFDs = fdIdx.len;
2662 privateDicts = (Type1CPrivateDict *)
2663 gmallocn(nFDs, sizeof(Type1CPrivateDict));
2664 for (i = 0; i < nFDs; ++i) {
2665 getIndexVal(&fdIdx, i, &val, &parsedOk);
2666 if (!parsedOk) {
2667 return gFalse;
2668 }
2669 readFD(val.pos, val.len, &privateDicts[i]);
2670 }
2671 }
2672
2673 // for 8-bit fonts: read the private dict
2674 } else {
2675 nFDs = 1;
2676 privateDicts = (Type1CPrivateDict *)gmalloc(sizeof(Type1CPrivateDict));
2677 readPrivateDict(topDict.privateOffset, topDict.privateSize,
2678 &privateDicts[0]);
2679 }
2680
2681 // check for parse errors in the private dict(s)
2682 if (!parsedOk) {
2683 return gFalse;
2684 }
2685
2686 // get the charstrings index
2687 if (topDict.charStringsOffset <= 0) {
2688 parsedOk = gFalse;
2689 return gFalse;
2690 }
2691 getIndex(topDict.charStringsOffset, &charStringsIdx, &parsedOk);
2692 if (!parsedOk) {
2693 return gFalse;
2694 }
2695 nGlyphs = charStringsIdx.len;
2696
2697 // for CID fonts: read the FDSelect table
2698 if (topDict.firstOp == 0x0c1e) {
2699 readFDSelect();
2700 if (!parsedOk) {
2701 return gFalse;
2702 }
2703 }
2704
2705 // read the charset
2706 if (!readCharset()) {
2707 parsedOk = gFalse;
2708 return gFalse;
2709 }
2710
2711 // for 8-bit fonts: build the encoding
2712 if (topDict.firstOp != 0x0c14 && topDict.firstOp != 0x0c1e) {
2713 buildEncoding();
2714 if (!parsedOk) {
2715 return gFalse;
2716 }
2717 }
2718
2719 return parsedOk;
2720 }
2721
2722 void FoFiType1C::readTopDict() {
2723 Type1CIndexVal topDictPtr;
2724 int pos;
2725
2726 topDict.firstOp = -1;
2727 topDict.versionSID = 0;
2728 topDict.noticeSID = 0;
2729 topDict.copyrightSID = 0;
2730 topDict.fullNameSID = 0;
2731 topDict.familyNameSID = 0;
2732 topDict.weightSID = 0;
2733 topDict.isFixedPitch = 0;
2734 topDict.italicAngle = 0;
2735 topDict.underlinePosition = -100;
2736 topDict.underlineThickness = 50;
2737 topDict.paintType = 0;
2738 topDict.charstringType = 2;
2739 topDict.fontMatrix[0] = 0.001;
2740 topDict.fontMatrix[1] = 0;
2741 topDict.fontMatrix[2] = 0;
2742 topDict.fontMatrix[3] = 0.001;
2743 topDict.fontMatrix[4] = 0;
2744 topDict.fontMatrix[5] = 0;
2745 topDict.hasFontMatrix = gFalse;
2746 topDict.uniqueID = 0;
2747 topDict.fontBBox[0] = 0;
2748 topDict.fontBBox[1] = 0;
2749 topDict.fontBBox[2] = 0;
2750 topDict.fontBBox[3] = 0;
2751 topDict.strokeWidth = 0;
2752 topDict.charsetOffset = 0;
2753 topDict.encodingOffset = 0;
2754 topDict.charStringsOffset = 0;
2755 topDict.privateSize = 0;
2756 topDict.privateOffset = 0;
2757 topDict.registrySID = 0;
2758 topDict.orderingSID = 0;
2759 topDict.supplement = 0;
2760 topDict.fdArrayOffset = 0;
2761 topDict.fdSelectOffset = 0;
2762
2763 getIndexVal(&topDictIdx, 0, &topDictPtr, &parsedOk);
2764 pos = topDictPtr.pos;
2765 nOps = 0;
2766 while (pos < topDictPtr.pos + topDictPtr.len) {
2767 pos = getOp(pos, gFalse, &parsedOk);
2768 if (!parsedOk) {
2769 break;
2770 }
2771 if (ops[nOps - 1].kind == type1COpOperator) {
2772 --nOps; // drop the operator
2773 if (topDict.firstOp < 0) {
2774 topDict.firstOp = ops[nOps].op;
2775 }
2776 switch (ops[nOps].op) {
2777 case 0x0000: topDict.versionSID = ops[0].toInt(); break;
2778 case 0x0001: topDict.noticeSID = ops[0].toInt(); break;
2779 case 0x0c00: topDict.copyrightSID = ops[0].toInt(); break;
2780 case 0x0002: topDict.fullNameSID = ops[0].toInt(); break;
2781 case 0x0003: topDict.familyNameSID = ops[0].toInt(); break;
2782 case 0x0004: topDict.weightSID = ops[0].toInt(); break;
2783 case 0x0c01: topDict.isFixedPitch = ops[0].toInt(); break;
2784 case 0x0c02: topDict.italicAngle = ops[0].toFloat(); break;
2785 case 0x0c03: topDict.underlinePosition = ops[0].toFloat(); break;
2786 case 0x0c04: topDict.underlineThickness = ops[0].toFloat(); break;
2787 case 0x0c05: topDict.paintType = ops[0].toInt(); break;
2788 case 0x0c06: topDict.charstringType = ops[0].toInt(); break;
2789 case 0x0c07: topDict.fontMatrix[0] = ops[0].toFloat();
2790 topDict.fontMatrix[1] = ops[1].toFloat();
2791 topDict.fontMatrix[2] = ops[2].toFloat();
2792 topDict.fontMatrix[3] = ops[3].toFloat();
2793 topDict.fontMatrix[4] = ops[4].toFloat();
2794 topDict.fontMatrix[5] = ops[5].toFloat();
2795 topDict.hasFontMatrix = gTrue;
2796 break;
2797 case 0x000d: topDict.uniqueID = ops[0].toInt(); break;
2798 case 0x0005: topDict.fontBBox[0] = ops[0].toFloat();
2799 topDict.fontBBox[1] = ops[1].toFloat();
2800 topDict.fontBBox[2] = ops[2].toFloat();
2801 topDict.fontBBox[3] = ops[3].toFloat();
2802 break;
2803 case 0x0c08: topDict.strokeWidth = ops[0].toFloat(); break;
2804 case 0x000f: topDict.charsetOffset = ops[0].toInt(); break;
2805 case 0x0010: topDict.encodingOffset = ops[0].toInt(); break;
2806 case 0x0011: topDict.charStringsOffset = ops[0].toInt(); break;
2807 case 0x0012: topDict.privateSize = ops[0].toInt();
2808 topDict.privateOffset = ops[1].toInt();
2809 break;
2810 case 0x0c1e: topDict.registrySID = ops[0].toInt();
2811 topDict.orderingSID = ops[1].toInt();
2812 topDict.supplement = ops[2].toInt();
2813 break;
2814 case 0x0c24: topDict.fdArrayOffset = ops[0].toInt(); break;
2815 case 0x0c25: topDict.fdSelectOffset = ops[0].toInt(); break;
2816 }
2817 nOps = 0;
2818 }
2819 }
2820 }
2821
2822 // Read a CID font dict (FD) - this pulls out the private dict
2823 // pointer, and reads the private dict. It also pulls the FontMatrix
2824 // (if any) out of the FD.
2825 void FoFiType1C::readFD(int offset, int length, Type1CPrivateDict *pDict) {
2826 int pos, pSize, pOffset;
2827 double fontMatrix[6];
2828 GBool hasFontMatrix;
2829
2830 hasFontMatrix = gFalse;
2831 fontMatrix[0] = fontMatrix[1] = fontMatrix[2] = 0; // make gcc happy
2832 fontMatrix[3] = fontMatrix[4] = fontMatrix[5] = 0;
2833 pSize = pOffset = 0;
2834 pos = offset;
2835 nOps = 0;
2836 while (pos < offset + length) {
2837 pos = getOp(pos, gFalse, &parsedOk);
2838 if (!parsedOk) {
2839 return;
2840 }
2841 if (ops[nOps - 1].kind == type1COpOperator) {
2842 if (ops[nOps - 1].op == 0x0012) {
2843 if (nOps < 3) {
2844 parsedOk = gFalse;
2845 return;
2846 }
2847 pSize = ops[0].toInt();
2848 pOffset = ops[1].toInt();
2849 break;
2850 } else if (ops[nOps - 1].op == 0x0c07) {
2851 fontMatrix[0] = ops[0].toFloat();
2852 fontMatrix[1] = ops[1].toFloat();
2853 fontMatrix[2] = ops[2].toFloat();
2854 fontMatrix[3] = ops[3].toFloat();
2855 fontMatrix[4] = ops[4].toFloat();
2856 fontMatrix[5] = ops[5].toFloat();
2857 hasFontMatrix = gTrue;
2858 }
2859 nOps = 0;
2860 }
2861 }
2862 readPrivateDict(pOffset, pSize, pDict);
2863 if (hasFontMatrix) {
2864 pDict->fontMatrix[0] = fontMatrix[0];
2865 pDict->fontMatrix[1] = fontMatrix[1];
2866 pDict->fontMatrix[2] = fontMatrix[2];
2867 pDict->fontMatrix[3] = fontMatrix[3];
2868 pDict->fontMatrix[4] = fontMatrix[4];
2869 pDict->fontMatrix[5] = fontMatrix[5];
2870 pDict->hasFontMatrix = gTrue;
2871 }
2872 }
2873
2874 void FoFiType1C::readPrivateDict(int offset, int length,
2875 Type1CPrivateDict *pDict) {
2876 int pos;
2877
2878 pDict->hasFontMatrix = gFalse;
2879 pDict->nBlueValues = 0;
2880 pDict->nOtherBlues = 0;
2881 pDict->nFamilyBlues = 0;
2882 pDict->nFamilyOtherBlues = 0;
2883 pDict->blueScale = 0.039625;
2884 pDict->blueShift = 7;
2885 pDict->blueFuzz = 1;
2886 pDict->hasStdHW = gFalse;
2887 pDict->hasStdVW = gFalse;
2888 pDict->nStemSnapH = 0;
2889 pDict->nStemSnapV = 0;
2890 pDict->hasForceBold = gFalse;
2891 pDict->forceBoldThreshold = 0;
2892 pDict->languageGroup = 0;
2893 pDict->expansionFactor = 0.06;
2894 pDict->initialRandomSeed = 0;
2895 pDict->subrsOffset = 0;
2896 pDict->defaultWidthX = 0;
2897 pDict->defaultWidthXInt = gTrue;
2898 pDict->nominalWidthX = 0;
2899 pDict->nominalWidthXInt = gTrue;
2900
2901 // no dictionary
2902 if (offset == 0 || length == 0) {
2903 return;
2904 }
2905
2906 pos = offset;
2907 nOps = 0;
2908 while (pos < offset + length) {
2909 pos = getOp(pos, gFalse, &parsedOk);
2910 if (!parsedOk) {
2911 break;
2912 }
2913 if (ops[nOps - 1].kind == type1COpOperator) {
2914 --nOps; // drop the operator
2915 switch (ops[nOps].op) {
2916 case 0x0006:
2917 pDict->nBlueValues = getDeltaIntArray(pDict->blueValues,
2918 type1CMaxBlueValues);
2919 break;
2920 case 0x0007:
2921 pDict->nOtherBlues = getDeltaIntArray(pDict->otherBlues,
2922 type1CMaxOtherBlues);
2923 break;
2924 case 0x0008:
2925 pDict->nFamilyBlues = getDeltaIntArray(pDict->familyBlues,
2926 type1CMaxBlueValues);
2927 break;
2928 case 0x0009:
2929 pDict->nFamilyOtherBlues = getDeltaIntArray(pDict->familyOtherBlues,
2930 type1CMaxOtherBlues);
2931 break;
2932 case 0x0c09:
2933 pDict->blueScale = ops[0].toFloat();
2934 break;
2935 case 0x0c0a:
2936 pDict->blueShift = ops[0].toInt();
2937 break;
2938 case 0x0c0b:
2939 pDict->blueFuzz = ops[0].toInt();
2940 break;
2941 case 0x000a:
2942 pDict->stdHW = ops[0].toFloat();
2943 pDict->hasStdHW = gTrue;
2944 break;
2945 case 0x000b:
2946 pDict->stdVW = ops[0].toFloat();
2947 pDict->hasStdVW = gTrue;
2948 break;
2949 case 0x0c0c:
2950 pDict->nStemSnapH = getDeltaFPArray(pDict->stemSnapH,
2951 type1CMaxStemSnap);
2952 break;
2953 case 0x0c0d:
2954 pDict->nStemSnapV = getDeltaFPArray(pDict->stemSnapV,
2955 type1CMaxStemSnap);
2956 break;
2957 case 0x0c0e:
2958 pDict->forceBold = !ops[0].isZero();
2959 pDict->hasForceBold = gTrue;
2960 break;
2961 case 0x0c0f:
2962 pDict->forceBoldThreshold = ops[0].toFloat();
2963 break;
2964 case 0x0c11:
2965 pDict->languageGroup = ops[0].toInt();
2966 break;
2967 case 0x0c12:
2968 pDict->expansionFactor = ops[0].toFloat();
2969 break;
2970 case 0x0c13:
2971 pDict->initialRandomSeed = ops[0].toInt();
2972 break;
2973 case 0x0013:
2974 pDict->subrsOffset = offset + ops[0].toInt();
2975 break;
2976 case 0x0014:
2977 pDict->defaultWidthX = ops[0].toFloat();
2978 pDict->defaultWidthXInt = ops[0].kind == type1COpInteger;
2979 break;
2980 case 0x0015:
2981 pDict->nominalWidthX = ops[0].toFloat();
2982 pDict->nominalWidthXInt = ops[0].kind == type1COpInteger;
2983 break;
2984 }
2985 nOps = 0;
2986 }
2987 }
2988 }
2989
2990 void FoFiType1C::readFDSelect() {
2991 int fdSelectFmt, pos, nRanges, gid0, gid1, fd, i, j;
2992
2993 fdSelect = (Guchar *)gmalloc(nGlyphs);
2994 for (i = 0; i < nGlyphs; ++i) {
2995 fdSelect[i] = 0;
2996 }
2997 if (topDict.fdSelectOffset != 0) {
2998 pos = topDict.fdSelectOffset;
2999 fdSelectFmt = getU8(pos++, &parsedOk);
3000 if (!parsedOk) {
3001 return;
3002 }
3003 if (fdSelectFmt == 0) {
3004 if (!checkRegion(pos, nGlyphs)) {
3005 parsedOk = gFalse;
3006 return;
3007 }
3008 for (gid0 = 0; gid0 < nGlyphs; ++gid0) {
3009 if (file[pos + gid0] >= nFDs) {
3010 //~ error(-1, "Bad FDSelect table in CID font");
3011 parsedOk = gFalse;
3012 return;
3013 }
3014 fdSelect[gid0] = file[pos + gid0];
3015 }
3016 } else if (fdSelectFmt == 3) {
3017 nRanges = getU16BE(pos, &parsedOk);
3018 pos += 2;
3019 gid0 = getU16BE(pos, &parsedOk);
3020 pos += 2;
3021 for (i = 1; i <= nRanges; ++i) {
3022 fd = getU8(pos++, &parsedOk);
3023 gid1 = getU16BE(pos, &parsedOk);
3024 if (!parsedOk) {
3025 return;
3026 }
3027 pos += 2;
3028 if (gid0 > gid1 || gid1 > nGlyphs || fd >= nFDs) {
3029 //~ error(-1, "Bad FDSelect table in CID font");
3030 parsedOk = gFalse;
3031 return;
3032 }
3033 for (j = gid0; j < gid1; ++j) {
3034 fdSelect[j] = (Guchar)fd;
3035 }
3036 gid0 = gid1;
3037 }
3038 } else {
3039 //~ error(-1, "Unknown FDSelect table format in CID font");
3040 }
3041 }
3042 }
3043
3044 void FoFiType1C::buildEncoding() {
3045 char buf[256];
3046 int nCodes, nRanges, encFormat;
3047 int pos, c, sid, nLeft, nSups, i, j;
3048
3049 if (topDict.encodingOffset == 0) {
3050 encoding = (char **)fofiType1StandardEncoding;
3051
3052 } else if (topDict.encodingOffset == 1) {
3053 encoding = (char **)fofiType1ExpertEncoding;
3054
3055 } else {
3056 encoding = (char **)gmallocn(256, sizeof(char *));
3057 for (i = 0; i < 256; ++i) {
3058 encoding[i] = NULL;
3059 }
3060 pos = topDict.encodingOffset;
3061 encFormat = getU8(pos++, &parsedOk);
3062 if (!parsedOk) {
3063 return;
3064 }
3065 if ((encFormat & 0x7f) == 0) {
3066 nCodes = 1 + getU8(pos++, &parsedOk);
3067 if (!parsedOk) {
3068 return;
3069 }
3070 if (nCodes > nGlyphs) {
3071 nCodes = nGlyphs;
3072 }
3073 for (i = 1; i < nCodes; ++i) {
3074 c = getU8(pos++, &parsedOk);
3075 if (!parsedOk) {
3076 return;
3077 }
3078 if (encoding[c]) {
3079 gfree(encoding[c]);
3080 }
3081 encoding[c] = copyString(getString(charset[i], buf, &parsedOk));
3082 }
3083 } else if ((encFormat & 0x7f) == 1) {
3084 nRanges = getU8(pos++, &parsedOk);
3085 if (!parsedOk) {
3086 return;
3087 }
3088 nCodes = 1;
3089 for (i = 0; i < nRanges; ++i) {
3090 c = getU8(pos++, &parsedOk);
3091 nLeft = getU8(pos++, &parsedOk);
3092 if (!parsedOk) {
3093 return;
3094 }
3095 for (j = 0; j <= nLeft && nCodes < nGlyphs; ++j) {
3096 if (c < 256) {
3097 if (encoding[c]) {
3098 gfree(encoding[c]);
3099 }
3100 encoding[c] = copyString(getString(charset[nCodes], buf,
3101 &parsedOk));
3102 }
3103 ++nCodes;
3104 ++c;
3105 }
3106 }
3107 }
3108 if (encFormat & 0x80) {
3109 nSups = getU8(pos++, &parsedOk);
3110 if (!parsedOk) {
3111 return;
3112 }
3113 for (i = 0; i < nSups; ++i) {
3114 c = getU8(pos++, &parsedOk);;
3115 if (!parsedOk) {
3116 return;;
3117 }
3118 sid = getU16BE(pos, &parsedOk);
3119 pos += 2;
3120 if (!parsedOk) {
3121 return;
3122 }
3123 if (encoding[c]) {
3124 gfree(encoding[c]);
3125 }
3126 encoding[c] = copyString(getString(sid, buf, &parsedOk));
3127 }
3128 }
3129 }
3130 }
3131
3132 GBool FoFiType1C::readCharset() {
3133 int charsetFormat, c, pos;
3134 int nLeft, i, j;
3135
3136 if (topDict.charsetOffset == 0) {
3137 charset = fofiType1CISOAdobeCharset;
3138 if (nGlyphs > 229) {
3139 nGlyphs = 229;
3140 }
3141 } else if (topDict.charsetOffset == 1) {
3142 charset = fofiType1CExpertCharset;
3143 if (nGlyphs > 166) {
3144 nGlyphs = 166;
3145 }
3146 } else if (topDict.charsetOffset == 2) {
3147 charset = fofiType1CExpertSubsetCharset;
3148 if (nGlyphs > 87) {
3149 nGlyphs = 87;
3150 }
3151 } else {
3152 charset = (Gushort *)gmallocn(nGlyphs, sizeof(Gushort));
3153 for (i = 0; i < nGlyphs; ++i) {
3154 charset[i] = 0;
3155 }
3156 pos = topDict.charsetOffset;
3157 charsetFormat = getU8(pos++, &parsedOk);
3158 if (charsetFormat == 0) {
3159 for (i = 1; i < nGlyphs; ++i) {
3160 charset[i] = (Gushort)getU16BE(pos, &parsedOk);
3161 pos += 2;
3162 if (!parsedOk) {
3163 break;
3164 }
3165 }
3166 } else if (charsetFormat == 1) {
3167 i = 1;
3168 while (i < nGlyphs) {
3169 c = getU16BE(pos, &parsedOk);
3170 pos += 2;
3171 nLeft = getU8(pos++, &parsedOk);
3172 if (!parsedOk) {
3173 break;
3174 }
3175 for (j = 0; j <= nLeft && i < nGlyphs; ++j) {
3176 charset[i++] = (Gushort)c++;
3177 }
3178 }
3179 } else if (charsetFormat == 2) {
3180 i = 1;
3181 while (i < nGlyphs) {
3182 c = getU16BE(pos, &parsedOk);
3183 pos += 2;
3184 nLeft = getU16BE(pos, &parsedOk);
3185 pos += 2;
3186 if (!parsedOk) {
3187 break;
3188 }
3189 for (j = 0; j <= nLeft && i < nGlyphs; ++j) {
3190 charset[i++] = (Gushort)c++;
3191 }
3192 }
3193 }
3194 if (!parsedOk) {
3195 gfree(charset);
3196 charset = NULL;
3197 return gFalse;
3198 }
3199 }
3200 return gTrue;
3201 }
3202
3203 int FoFiType1C::getOp(int pos, GBool charstring, GBool *ok) {
3204 static char nybChars[16] = "0123456789.ee -";
3205 Type1COp op;
3206 char buf[65];
3207 int b0, b1, nyb0, nyb1, x, i;
3208
3209 b0 = getU8(pos++, ok);
3210
3211 if (b0 == 28) {
3212 x = getU8(pos++, ok);
3213 x = (x << 8) | getU8(pos++, ok);
3214 if (x & 0x8000) {
3215 x |= ~0xffff;
3216 }
3217 op.kind = type1COpInteger;
3218 op.intgr = x;
3219
3220 } else if (!charstring && b0 == 29) {
3221 x = getU8(pos++, ok);
3222 x = (x << 8) | getU8(pos++, ok);
3223 x = (x << 8) | getU8(pos++, ok);
3224 x = (x << 8) | getU8(pos++, ok);
3225 if (x & 0x80000000) {
3226 x |= ~0xffffffff;
3227 }
3228 op.kind = type1COpInteger;
3229 op.intgr = x;
3230
3231 } else if (!charstring && b0 == 30) {
3232 i = 0;
3233 do {
3234 b1 = getU8(pos++, ok);
3235 nyb0 = b1 >> 4;
3236 nyb1 = b1 & 0x0f;
3237 if (nyb0 == 0xf) {
3238 break;
3239 }
3240 buf[i++] = nybChars[nyb0];
3241 if (i == 64) {
3242 break;
3243 }
3244 if (nyb0 == 0xc) {
3245 buf[i++] = '-';
3246 }
3247 if (i == 64) {
3248 break;
3249 }
3250 if (nyb1 == 0xf) {
3251 break;
3252 }
3253 buf[i++] = nybChars[nyb1];
3254 if (i == 64) {
3255 break;
3256 }
3257 if (nyb1 == 0xc) {
3258 buf[i++] = '-';
3259 }
3260 } while (i < 64);
3261 buf[i] = '\0';
3262 op.kind = type1COpFloat;
3263 op.flt = atof(buf);
3264
3265 } else if (b0 >= 32 && b0 <= 246) {
3266 op.kind = type1COpInteger;
3267 op.intgr = b0 - 139;
3268
3269 } else if (b0 >= 247 && b0 <= 250) {
3270 op.kind = type1COpInteger;
3271 op.intgr = ((b0 - 247) << 8) + getU8(pos++, ok) + 108;
3272
3273 } else if (b0 >= 251 && b0 <= 254) {
3274 op.kind = type1COpInteger;
3275 op.intgr = -((b0 - 251) << 8) - getU8(pos++, ok) - 108;
3276
3277 } else if (charstring && b0 == 255) {
3278 x = getU8(pos++, ok);
3279 x = (x << 8) | getU8(pos++, ok);
3280 x = (x << 8) | getU8(pos++, ok);
3281 x = (x << 8) | getU8(pos++, ok);
3282 if (x & 0x80000000) {
3283 x |= ~0xffffffff;
3284 }
3285 op.kind = type1COpFloat;
3286 op.flt = (double)x / 65536.0;
3287
3288 } else if (b0 == 12) {
3289 op.kind = type1COpOperator;
3290 op.op = 0x0c00 + getU8(pos++, ok);
3291
3292 } else {
3293 op.kind = type1COpOperator;
3294 op.op = b0;
3295 }
3296
3297 if (nOps < 49) {
3298 ops[nOps++] = op;
3299 }
3300
3301 return pos;
3302 }
3303
3304 // Convert the delta-encoded ops array to an array of ints.
3305 int FoFiType1C::getDeltaIntArray(int *arr, int maxLen) {
3306 int x;
3307 int n, i;
3308
3309 if ((n = nOps) > maxLen) {
3310 n = maxLen;
3311 }
3312 x = 0;
3313 for (i = 0; i < n; ++i) {
3314 x += ops[i].toInt();
3315 arr[i] = x;
3316 }
3317 return n;
3318 }
3319
3320 // Convert the delta-encoded ops array to an array of doubles.
3321 int FoFiType1C::getDeltaFPArray(double *arr, int maxLen) {
3322 double x;
3323 int n, i;
3324
3325 if ((n = nOps) > maxLen) {
3326 n = maxLen;
3327 }
3328 x = 0;
3329 for (i = 0; i < n; ++i) {
3330 x += ops[i].toFloat();
3331 arr[i] = x;
3332 }
3333 return n;
3334 }
3335
3336 void FoFiType1C::getIndex(int pos, Type1CIndex *idx, GBool *ok) {
3337 idx->pos = pos;
3338 idx->len = getU16BE(pos, ok);
3339 if (idx->len == 0) {
3340 // empty indexes are legal and contain just the length field
3341 idx->offSize = 0;
3342 idx->startPos = idx->endPos = pos + 2;
3343 } else {
3344 idx->offSize = getU8(pos + 2, ok);
3345 if (idx->offSize < 1 || idx->offSize > 4) {
3346 *ok = gFalse;
3347 }
3348 idx->startPos = pos + 3 + (idx->len + 1) * idx->offSize - 1;
3349 if (idx->startPos < 0 || idx->startPos >= len) {
3350 *ok = gFalse;
3351 }
3352 idx->endPos = idx->startPos + getUVarBE(pos + 3 + idx->len * idx->offSize,
3353 idx->offSize, ok);
3354 if (idx->endPos < idx->startPos || idx->endPos > len) {
3355 *ok = gFalse;
3356 }
3357 }
3358 }
3359
3360 void FoFiType1C::getIndexVal(Type1CIndex *idx, int i,
3361 Type1CIndexVal *val, GBool *ok) {
3362 int pos0, pos1;
3363
3364 if (i < 0 || i >= idx->len) {
3365 val->pos = 0;
3366 val->len = 0;
3367 *ok = gFalse;
3368 return;
3369 }
3370 pos0 = idx->startPos + getUVarBE(idx->pos + 3 + i * idx->offSize,
3371 idx->offSize, ok);
3372 pos1 = idx->startPos + getUVarBE(idx->pos + 3 + (i + 1) * idx->offSize,
3373 idx->offSize, ok);
3374 if (pos0 < idx->startPos || pos0 > idx->endPos ||
3375 pos1 <= idx->startPos || pos1 > idx->endPos ||
3376 pos1 < pos0) {
3377 *ok = gFalse;
3378 }
3379 val->pos = pos0;
3380 val->len = pos1 - pos0;
3381 }
3382
3383 char *FoFiType1C::getString(int sid, char *buf, GBool *ok) {
3384 Type1CIndexVal val;
3385 int n;
3386
3387 if (sid < 0) {
3388 buf[0] = '\0';
3389 } else if (sid < 391) {
3390 strcpy(buf, fofiType1CStdStrings[sid]);
3391 } else {
3392 sid -= 391;
3393 getIndexVal(&stringIdx, sid, &val, ok);
3394 if (*ok) {
3395 if ((n = val.len) > 255) {
3396 n = 255;
3397 }
3398 strncpy(buf, (char *)&file[val.pos], n);
3399 buf[n] = '\0';
3400 } else {
3401 buf[0] = '\0';
3402 }
3403 }
3404 return buf;
3405 }