"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.
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 }