upgrade to xpdf 3.00.
[swftools.git] / pdf2swf / xpdf / FoFiType1C.cc
blob91a21adc5b6f12f51ace1ba8ed0d4f51a7aae0c5
1 //========================================================================
2 //
3 // FoFiType1C.cc
4 //
5 // Copyright 1999-2003 Glyph & Cog, LLC
6 //
7 //========================================================================
9 #include <aconf.h>
11 #ifdef USE_GCC_PRAGMAS
12 #pragma implementation
13 #endif
15 #include <stdlib.h>
16 #include <string.h>
17 #include <math.h>
18 #include "gmem.h"
19 #include "GString.h"
20 #include "FoFiEncodings.h"
21 #include "FoFiType1C.h"
23 //------------------------------------------------------------------------
25 static char hexChars[17] = "0123456789ABCDEF";
27 //------------------------------------------------------------------------
28 // FoFiType1C
29 //------------------------------------------------------------------------
31 FoFiType1C *FoFiType1C::make(char *fileA, int lenA) {
32 FoFiType1C *ff;
34 ff = new FoFiType1C(fileA, lenA, gFalse);
35 if (!ff->parse()) {
36 delete ff;
37 return NULL;
39 return ff;
42 FoFiType1C *FoFiType1C::load(char *fileName) {
43 FoFiType1C *ff;
44 char *fileA;
45 int lenA;
47 if (!(fileA = FoFiBase::readFile(fileName, &lenA))) {
48 return NULL;
50 ff = new FoFiType1C(fileA, lenA, gTrue);
51 if (!ff->parse()) {
52 delete ff;
53 return NULL;
55 return ff;
58 FoFiType1C::FoFiType1C(char *fileA, int lenA, GBool freeFileDataA):
59 FoFiBase(fileA, lenA, freeFileDataA)
61 name = NULL;
62 encoding = NULL;
63 privateDicts = NULL;
64 fdSelect = NULL;
65 charset = NULL;
68 FoFiType1C::~FoFiType1C() {
69 int i;
71 if (name) {
72 delete name;
74 if (encoding &&
75 encoding != fofiType1StandardEncoding &&
76 encoding != fofiType1ExpertEncoding) {
77 for (i = 0; i < 256; ++i) {
78 gfree(encoding[i]);
80 gfree(encoding);
82 if (privateDicts) {
83 gfree(privateDicts);
85 if (fdSelect) {
86 gfree(fdSelect);
88 if (charset &&
89 charset != fofiType1CISOAdobeCharset &&
90 charset != fofiType1CExpertCharset &&
91 charset != fofiType1CExpertSubsetCharset) {
92 gfree(charset);
96 char *FoFiType1C::getName() {
97 return name ? name->getCString() : (char *)NULL;
100 char **FoFiType1C::getEncoding() {
101 return encoding;
104 Gushort *FoFiType1C::getCIDToGIDMap(int *nCIDs) {
105 Gushort *map;
106 int n, i;
108 // a CID font's top dict has ROS as the first operator
109 if (topDict.firstOp != 0x0c1e) {
110 *nCIDs = 0;
111 return NULL;
114 // in a CID font, the charset data is the GID-to-CID mapping, so all
115 // we have to do is reverse it
116 n = 0;
117 for (i = 0; i < nGlyphs; ++i) {
118 if (charset[i] > n) {
119 n = charset[i];
122 ++n;
123 map = (Gushort *)gmalloc(n * sizeof(Gushort));
124 memset(map, 0, n * sizeof(Gushort));
125 for (i = 0; i < nGlyphs; ++i) {
126 map[charset[i]] = i;
128 *nCIDs = n;
129 return map;
132 void FoFiType1C::convertToType1(char **newEncoding, GBool ascii,
133 FoFiOutputFunc outputFunc,
134 void *outputStream) {
135 Type1CEexecBuf eb;
136 Type1CIndex subrIdx;
137 Type1CIndexVal val;
138 char buf[512];
139 char **enc;
140 GBool ok;
141 int i;
143 // write header and font dictionary, up to encoding
144 ok = gTrue;
145 (*outputFunc)(outputStream, "%!FontType1-1.0: ", 17);
146 (*outputFunc)(outputStream, name->getCString(), name->getLength());
147 if (topDict.versionSID != 0) {
148 getString(topDict.versionSID, buf, &ok);
149 (*outputFunc)(outputStream, buf, strlen(buf));
151 (*outputFunc)(outputStream, "\n", 1);
152 // the dictionary needs room for 12 entries: the following 9, plus
153 // Private and CharStrings (in the eexec section) and FID (which is
154 // added by definefont)
155 (*outputFunc)(outputStream, "12 dict begin\n", 14);
156 (*outputFunc)(outputStream, "/FontInfo 10 dict dup begin\n", 28);
157 if (topDict.versionSID != 0) {
158 (*outputFunc)(outputStream, "/version (", 10);
159 (*outputFunc)(outputStream, buf, strlen(buf));
160 (*outputFunc)(outputStream, ") readonly def\n", 15);
162 if (topDict.noticeSID != 0) {
163 getString(topDict.noticeSID, buf, &ok);
164 (*outputFunc)(outputStream, "/Notice (", 9);
165 (*outputFunc)(outputStream, buf, strlen(buf));
166 (*outputFunc)(outputStream, ") readonly def\n", 15);
168 if (topDict.copyrightSID != 0) {
169 getString(topDict.copyrightSID, buf, &ok);
170 (*outputFunc)(outputStream, "/Copyright (", 12);
171 (*outputFunc)(outputStream, buf, strlen(buf));
172 (*outputFunc)(outputStream, ") readonly def\n", 15);
174 if (topDict.fullNameSID != 0) {
175 getString(topDict.fullNameSID, buf, &ok);
176 (*outputFunc)(outputStream, "/FullName (", 11);
177 (*outputFunc)(outputStream, buf, strlen(buf));
178 (*outputFunc)(outputStream, ") readonly def\n", 15);
180 if (topDict.familyNameSID != 0) {
181 getString(topDict.familyNameSID, buf, &ok);
182 (*outputFunc)(outputStream, "/FamilyName (", 13);
183 (*outputFunc)(outputStream, buf, strlen(buf));
184 (*outputFunc)(outputStream, ") readonly def\n", 15);
186 if (topDict.weightSID != 0) {
187 getString(topDict.weightSID, buf, &ok);
188 (*outputFunc)(outputStream, "/Weight (", 9);
189 (*outputFunc)(outputStream, buf, strlen(buf));
190 (*outputFunc)(outputStream, ") readonly def\n", 15);
192 if (topDict.isFixedPitch) {
193 (*outputFunc)(outputStream, "/isFixedPitch true def\n", 23);
194 } else {
195 (*outputFunc)(outputStream, "/isFixedPitch false def\n", 24);
197 sprintf(buf, "/ItalicAngle %g def\n", topDict.italicAngle);
198 (*outputFunc)(outputStream, buf, strlen(buf));
199 sprintf(buf, "/UnderlinePosition %g def\n", topDict.underlinePosition);
200 (*outputFunc)(outputStream, buf, strlen(buf));
201 sprintf(buf, "/UnderlineThickness %g def\n", topDict.underlineThickness);
202 (*outputFunc)(outputStream, buf, strlen(buf));
203 (*outputFunc)(outputStream, "end readonly def\n", 17);
204 (*outputFunc)(outputStream, "/FontName /", 11);
205 (*outputFunc)(outputStream, name->getCString(), name->getLength());
206 (*outputFunc)(outputStream, " def\n", 5);
207 sprintf(buf, "/PaintType %d def\n", topDict.paintType);
208 (*outputFunc)(outputStream, buf, strlen(buf));
209 (*outputFunc)(outputStream, "/FontType 1 def\n", 16);
210 sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] readonly def\n",
211 topDict.fontMatrix[0], topDict.fontMatrix[1], topDict.fontMatrix[2],
212 topDict.fontMatrix[3], topDict.fontMatrix[4], topDict.fontMatrix[5]);
213 (*outputFunc)(outputStream, buf, strlen(buf));
214 sprintf(buf, "/FontBBox [%g %g %g %g] readonly def\n",
215 topDict.fontBBox[0], topDict.fontBBox[1],
216 topDict.fontBBox[2], topDict.fontBBox[3]);
217 (*outputFunc)(outputStream, buf, strlen(buf));
218 sprintf(buf, "/StrokeWidth %g def\n", topDict.strokeWidth);
219 (*outputFunc)(outputStream, buf, strlen(buf));
220 if (topDict.uniqueID != 0) {
221 sprintf(buf, "/UniqueID %d def\n", topDict.uniqueID);
222 (*outputFunc)(outputStream, buf, strlen(buf));
225 // write the encoding
226 (*outputFunc)(outputStream, "/Encoding ", 10);
227 if (!newEncoding && encoding == fofiType1StandardEncoding) {
228 (*outputFunc)(outputStream, "StandardEncoding def\n", 21);
229 } else {
230 (*outputFunc)(outputStream, "256 array\n", 10);
231 (*outputFunc)(outputStream,
232 "0 1 255 {1 index exch /.notdef put} for\n", 40);
233 enc = newEncoding ? newEncoding : encoding;
234 for (i = 0; i < 256; ++i) {
235 if (enc[i]) {
236 sprintf(buf, "dup %d /%s put\n", i, enc[i]);
237 (*outputFunc)(outputStream, buf, strlen(buf));
240 (*outputFunc)(outputStream, "readonly def\n", 13);
242 (*outputFunc)(outputStream, "currentdict end\n", 16);
244 // start the binary section
245 (*outputFunc)(outputStream, "currentfile eexec\n", 18);
246 eb.outputFunc = outputFunc;
247 eb.outputStream = outputStream;
248 eb.ascii = ascii;
249 eb.r1 = 55665;
250 eb.line = 0;
252 // write the private dictionary
253 eexecWrite(&eb, "\x83\xca\x73\xd5");
254 eexecWrite(&eb, "dup /Private 32 dict dup begin\n");
255 eexecWrite(&eb, "/RD {string currentfile exch readstring pop}"
256 " executeonly def\n");
257 eexecWrite(&eb, "/ND {noaccess def} executeonly def\n");
258 eexecWrite(&eb, "/NP {noaccess put} executeonly def\n");
259 eexecWrite(&eb, "/MinFeature {16 16} def\n");
260 eexecWrite(&eb, "/password 5839 def\n");
261 if (privateDicts[0].nBlueValues) {
262 eexecWrite(&eb, "/BlueValues [");
263 for (i = 0; i < privateDicts[0].nBlueValues; ++i) {
264 sprintf(buf, "%s%d", i > 0 ? " " : "", privateDicts[0].blueValues[i]);
265 eexecWrite(&eb, buf);
267 eexecWrite(&eb, "] def\n");
269 if (privateDicts[0].nOtherBlues) {
270 eexecWrite(&eb, "/OtherBlues [");
271 for (i = 0; i < privateDicts[0].nOtherBlues; ++i) {
272 sprintf(buf, "%s%d", i > 0 ? " " : "", privateDicts[0].otherBlues[i]);
273 eexecWrite(&eb, buf);
275 eexecWrite(&eb, "] def\n");
277 if (privateDicts[0].nFamilyBlues) {
278 eexecWrite(&eb, "/FamilyBlues [");
279 for (i = 0; i < privateDicts[0].nFamilyBlues; ++i) {
280 sprintf(buf, "%s%d", i > 0 ? " " : "", privateDicts[0].familyBlues[i]);
281 eexecWrite(&eb, buf);
283 eexecWrite(&eb, "] def\n");
285 if (privateDicts[0].nFamilyOtherBlues) {
286 eexecWrite(&eb, "/FamilyOtherBlues [");
287 for (i = 0; i < privateDicts[0].nFamilyOtherBlues; ++i) {
288 sprintf(buf, "%s%d", i > 0 ? " " : "",
289 privateDicts[0].familyOtherBlues[i]);
290 eexecWrite(&eb, buf);
292 eexecWrite(&eb, "] def\n");
294 if (privateDicts[0].blueScale != 0.039625) {
295 sprintf(buf, "/BlueScale %g def\n", privateDicts[0].blueScale);
296 eexecWrite(&eb, buf);
298 if (privateDicts[0].blueShift != 7) {
299 sprintf(buf, "/BlueShift %d def\n", privateDicts[0].blueShift);
300 eexecWrite(&eb, buf);
302 if (privateDicts[0].blueFuzz != 1) {
303 sprintf(buf, "/BlueFuzz %d def\n", privateDicts[0].blueFuzz);
304 eexecWrite(&eb, buf);
306 if (privateDicts[0].hasStdHW) {
307 sprintf(buf, "/StdHW [%g] def\n", privateDicts[0].stdHW);
308 eexecWrite(&eb, buf);
310 if (privateDicts[0].hasStdVW) {
311 sprintf(buf, "/StdVW [%g] def\n", privateDicts[0].stdVW);
312 eexecWrite(&eb, buf);
314 if (privateDicts[0].nStemSnapH) {
315 eexecWrite(&eb, "/StemSnapH [");
316 for (i = 0; i < privateDicts[0].nStemSnapH; ++i) {
317 sprintf(buf, "%s%g", i > 0 ? " " : "", privateDicts[0].stemSnapH[i]);
318 eexecWrite(&eb, buf);
320 eexecWrite(&eb, "] def\n");
322 if (privateDicts[0].nStemSnapV) {
323 eexecWrite(&eb, "/StemSnapV [");
324 for (i = 0; i < privateDicts[0].nStemSnapV; ++i) {
325 sprintf(buf, "%s%g", i > 0 ? " " : "", privateDicts[0].stemSnapV[i]);
326 eexecWrite(&eb, buf);
328 eexecWrite(&eb, "] def\n");
330 if (privateDicts[0].hasForceBold) {
331 sprintf(buf, "/ForceBold %s def\n",
332 privateDicts[0].forceBold ? "true" : "false");
333 eexecWrite(&eb, buf);
335 if (privateDicts[0].forceBoldThreshold != 0) {
336 sprintf(buf, "/ForceBoldThreshold %g def\n",
337 privateDicts[0].forceBoldThreshold);
338 eexecWrite(&eb, buf);
340 if (privateDicts[0].languageGroup != 0) {
341 sprintf(buf, "/LanguageGroup %d def\n", privateDicts[0].languageGroup);
342 eexecWrite(&eb, buf);
344 if (privateDicts[0].expansionFactor != 0.06) {
345 sprintf(buf, "/ExpansionFactor %g def\n", privateDicts[0].expansionFactor);
346 eexecWrite(&eb, buf);
349 // set up subroutines
350 ok = gTrue;
351 getIndex(privateDicts[0].subrsOffset, &subrIdx, &ok);
352 if (!ok) {
353 subrIdx.pos = -1;
356 // write the CharStrings
357 sprintf(buf, "2 index /CharStrings %d dict dup begin\n", nGlyphs);
358 eexecWrite(&eb, buf);
359 for (i = 0; i < nGlyphs; ++i) {
360 ok = gTrue;
361 getIndexVal(&charStringsIdx, i, &val, &ok);
362 if (ok) {
363 getString(charset[i], buf, &ok);
364 if (ok) {
365 eexecCvtGlyph(&eb, buf, val.pos, val.len, &subrIdx, &privateDicts[0]);
369 eexecWrite(&eb, "end\n");
370 eexecWrite(&eb, "end\n");
371 eexecWrite(&eb, "readonly put\n");
372 eexecWrite(&eb, "noaccess put\n");
373 eexecWrite(&eb, "dup /FontName get exch definefont pop\n");
374 eexecWrite(&eb, "mark currentfile closefile\n");
376 // trailer
377 if (ascii && eb.line > 0) {
378 (*outputFunc)(outputStream, "\n", 1);
380 for (i = 0; i < 8; ++i) {
381 (*outputFunc)(outputStream, "0000000000000000000000000000000000000000000000000000000000000000\n", 65);
383 (*outputFunc)(outputStream, "cleartomark\n", 12);
386 void FoFiType1C::convertToCIDType0(char *psName,
387 FoFiOutputFunc outputFunc,
388 void *outputStream) {
389 int *cidMap;
390 GString *charStrings;
391 int *charStringOffsets;
392 Type1CIndex subrIdx;
393 Type1CIndexVal val;
394 int nCIDs, gdBytes;
395 char buf[512], buf2[512];
396 GBool ok;
397 int gid, offset, n, i, j, k;
399 // compute the CID count and build the CID-to-GID mapping
400 nCIDs = 0;
401 for (i = 0; i < nGlyphs; ++i) {
402 if (charset[i] >= nCIDs) {
403 nCIDs = charset[i] + 1;
406 cidMap = (int *)gmalloc(nCIDs * sizeof(int));
407 for (i = 0; i < nCIDs; ++i) {
408 cidMap[i] = -1;
410 for (i = 0; i < nGlyphs; ++i) {
411 cidMap[charset[i]] = i;
414 // build the charstrings
415 charStrings = new GString();
416 charStringOffsets = (int *)gmalloc((nCIDs + 1) * sizeof(int));
417 for (i = 0; i < nCIDs; ++i) {
418 charStringOffsets[i] = charStrings->getLength();
419 if ((gid = cidMap[i]) >= 0) {
420 ok = gTrue;
421 getIndexVal(&charStringsIdx, gid, &val, &ok);
422 if (ok) {
423 getIndex(privateDicts[fdSelect[gid]].subrsOffset, &subrIdx, &ok);
424 if (!ok) {
425 subrIdx.pos = -1;
427 cvtGlyph(val.pos, val.len, charStrings,
428 &subrIdx, &privateDicts[fdSelect[gid]], gTrue);
432 charStringOffsets[nCIDs] = charStrings->getLength();
434 // compute gdBytes = number of bytes needed for charstring offsets
435 // (offset size needs to account for the charstring offset table,
436 // with a worst case of five bytes per entry, plus the charstrings
437 // themselves)
438 i = (nCIDs + 1) * 5 + charStrings->getLength();
439 if (i < 0x100) {
440 gdBytes = 1;
441 } else if (i < 0x10000) {
442 gdBytes = 2;
443 } else if (i < 0x1000000) {
444 gdBytes = 3;
445 } else {
446 gdBytes = 4;
449 // begin the font dictionary
450 (*outputFunc)(outputStream, "/CIDInit /ProcSet findresource begin\n", 37);
451 (*outputFunc)(outputStream, "20 dict begin\n", 14);
452 (*outputFunc)(outputStream, "/CIDFontName /", 14);
453 (*outputFunc)(outputStream, psName, strlen(psName));
454 (*outputFunc)(outputStream, " def\n", 5);
455 (*outputFunc)(outputStream, "/CIDFontType 0 def\n", 19);
456 (*outputFunc)(outputStream, "/CIDSystemInfo 3 dict dup begin\n", 32);
457 if (topDict.registrySID > 0 && topDict.orderingSID > 0) {
458 ok = gTrue;
459 getString(topDict.registrySID, buf, &ok);
460 if (ok) {
461 (*outputFunc)(outputStream, " /Registry (", 13);
462 (*outputFunc)(outputStream, buf, strlen(buf));
463 (*outputFunc)(outputStream, ") def\n", 6);
465 ok = gTrue;
466 getString(topDict.orderingSID, buf, &ok);
467 if (ok) {
468 (*outputFunc)(outputStream, " /Ordering (", 13);
469 (*outputFunc)(outputStream, buf, strlen(buf));
470 (*outputFunc)(outputStream, ") def\n", 6);
472 } else {
473 (*outputFunc)(outputStream, " /Registry (Adobe) def\n", 24);
474 (*outputFunc)(outputStream, " /Ordering (Identity) def\n", 27);
476 sprintf(buf, " /Supplement %d def\n", topDict.supplement);
477 (*outputFunc)(outputStream, buf, strlen(buf));
478 (*outputFunc)(outputStream, "end def\n", 8);
479 sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] def\n",
480 topDict.fontMatrix[0], topDict.fontMatrix[1], topDict.fontMatrix[2],
481 topDict.fontMatrix[3], topDict.fontMatrix[4], topDict.fontMatrix[5]);
482 (*outputFunc)(outputStream, buf, strlen(buf));
483 sprintf(buf, "/FontBBox [%g %g %g %g] def\n",
484 topDict.fontBBox[0], topDict.fontBBox[1],
485 topDict.fontBBox[2], topDict.fontBBox[3]);
486 (*outputFunc)(outputStream, buf, strlen(buf));
487 (*outputFunc)(outputStream, "/FontInfo 1 dict dup begin\n", 27);
488 (*outputFunc)(outputStream, " /FSType 8 def\n", 16);
489 (*outputFunc)(outputStream, "end def\n", 8);
491 // CIDFont-specific entries
492 sprintf(buf, "/CIDCount %d def\n", nCIDs);
493 (*outputFunc)(outputStream, buf, strlen(buf));
494 (*outputFunc)(outputStream, "/FDBytes 1 def\n", 15);
495 sprintf(buf, "/GDBytes %d def\n", gdBytes);
496 (*outputFunc)(outputStream, buf, strlen(buf));
497 (*outputFunc)(outputStream, "/CIDMapOffset 0 def\n", 20);
498 if (topDict.paintType != 0) {
499 sprintf(buf, "/PaintType %d def\n", topDict.paintType);
500 (*outputFunc)(outputStream, buf, strlen(buf));
501 sprintf(buf, "/StrokeWidth %g def\n", topDict.strokeWidth);
502 (*outputFunc)(outputStream, buf, strlen(buf));
505 // FDArray entry
506 sprintf(buf, "/FDArray %d array\n", nFDs);
507 (*outputFunc)(outputStream, buf, strlen(buf));
508 for (i = 0; i < nFDs; ++i) {
509 sprintf(buf, "dup %d 10 dict begin\n", i);
510 (*outputFunc)(outputStream, buf, strlen(buf));
511 (*outputFunc)(outputStream, "/FontType 1 def\n", 16);
512 (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
513 sprintf(buf, "/PaintType %d def\n", topDict.paintType);
514 (*outputFunc)(outputStream, buf, strlen(buf));
515 (*outputFunc)(outputStream, "/Private 32 dict begin\n", 23);
516 if (privateDicts[i].nBlueValues) {
517 (*outputFunc)(outputStream, "/BlueValues [", 13);
518 for (j = 0; j < privateDicts[i].nBlueValues; ++j) {
519 sprintf(buf, "%s%d", j > 0 ? " " : "", privateDicts[i].blueValues[j]);
520 (*outputFunc)(outputStream, buf, strlen(buf));
522 (*outputFunc)(outputStream, "] def\n", 6);
524 if (privateDicts[i].nOtherBlues) {
525 (*outputFunc)(outputStream, "/OtherBlues [", 13);
526 for (j = 0; j < privateDicts[i].nOtherBlues; ++j) {
527 sprintf(buf, "%s%d", j > 0 ? " " : "", privateDicts[i].otherBlues[j]);
528 (*outputFunc)(outputStream, buf, strlen(buf));
530 (*outputFunc)(outputStream, "] def\n", 6);
532 if (privateDicts[i].nFamilyBlues) {
533 (*outputFunc)(outputStream, "/FamilyBlues [", 14);
534 for (j = 0; j < privateDicts[i].nFamilyBlues; ++j) {
535 sprintf(buf, "%s%d", j > 0 ? " " : "", privateDicts[i].familyBlues[j]);
536 (*outputFunc)(outputStream, buf, strlen(buf));
538 (*outputFunc)(outputStream, "] def\n", 6);
540 if (privateDicts[i].nFamilyOtherBlues) {
541 (*outputFunc)(outputStream, "/FamilyOtherBlues [", 19);
542 for (j = 0; j < privateDicts[i].nFamilyOtherBlues; ++j) {
543 sprintf(buf, "%s%d", j > 0 ? " " : "",
544 privateDicts[i].familyOtherBlues[j]);
545 (*outputFunc)(outputStream, buf, strlen(buf));
547 (*outputFunc)(outputStream, "] def\n", 6);
549 if (privateDicts[i].blueScale != 0.039625) {
550 sprintf(buf, "/BlueScale %g def\n", privateDicts[i].blueScale);
551 (*outputFunc)(outputStream, buf, strlen(buf));
553 if (privateDicts[i].blueShift != 7) {
554 sprintf(buf, "/BlueShift %d def\n", privateDicts[i].blueShift);
555 (*outputFunc)(outputStream, buf, strlen(buf));
557 if (privateDicts[i].blueFuzz != 1) {
558 sprintf(buf, "/BlueFuzz %d def\n", privateDicts[i].blueFuzz);
559 (*outputFunc)(outputStream, buf, strlen(buf));
561 if (privateDicts[i].hasStdHW) {
562 sprintf(buf, "/StdHW [%g] def\n", privateDicts[i].stdHW);
563 (*outputFunc)(outputStream, buf, strlen(buf));
565 if (privateDicts[i].hasStdVW) {
566 sprintf(buf, "/StdVW [%g] def\n", privateDicts[i].stdVW);
567 (*outputFunc)(outputStream, buf, strlen(buf));
569 if (privateDicts[i].nStemSnapH) {
570 (*outputFunc)(outputStream, "/StemSnapH [", 12);
571 for (j = 0; j < privateDicts[i].nStemSnapH; ++j) {
572 sprintf(buf, "%s%g", j > 0 ? " " : "", privateDicts[i].stemSnapH[j]);
573 (*outputFunc)(outputStream, buf, strlen(buf));
575 (*outputFunc)(outputStream, "] def\n", 6);
577 if (privateDicts[i].nStemSnapV) {
578 (*outputFunc)(outputStream, "/StemSnapV [", 12);
579 for (j = 0; j < privateDicts[i].nStemSnapV; ++j) {
580 sprintf(buf, "%s%g", j > 0 ? " " : "", privateDicts[i].stemSnapV[j]);
581 (*outputFunc)(outputStream, buf, strlen(buf));
583 (*outputFunc)(outputStream, "] def\n", 6);
585 if (privateDicts[i].hasForceBold) {
586 sprintf(buf, "/ForceBold %s def\n",
587 privateDicts[i].forceBold ? "true" : "false");
588 (*outputFunc)(outputStream, buf, strlen(buf));
590 if (privateDicts[i].forceBoldThreshold != 0) {
591 sprintf(buf, "/ForceBoldThreshold %g def\n",
592 privateDicts[i].forceBoldThreshold);
593 (*outputFunc)(outputStream, buf, strlen(buf));
595 if (privateDicts[i].languageGroup != 0) {
596 sprintf(buf, "/LanguageGroup %d def\n", privateDicts[i].languageGroup);
597 (*outputFunc)(outputStream, buf, strlen(buf));
599 if (privateDicts[i].expansionFactor != 0.06) {
600 sprintf(buf, "/ExpansionFactor %g def\n",
601 privateDicts[i].expansionFactor);
602 (*outputFunc)(outputStream, buf, strlen(buf));
604 (*outputFunc)(outputStream, "currentdict end def\n", 20);
605 (*outputFunc)(outputStream, "currentdict end put\n", 20);
607 (*outputFunc)(outputStream, "def\n", 4);
609 // start the binary section
610 offset = (nCIDs + 1) * (1 + gdBytes);
611 sprintf(buf, "(Hex) %d StartData\n",
612 offset + charStrings->getLength());
613 (*outputFunc)(outputStream, buf, strlen(buf));
615 // write the charstring offset (CIDMap) table
616 for (i = 0; i <= nCIDs; i += 6) {
617 for (j = 0; j < 6 && i+j <= nCIDs; ++j) {
618 if (i+j < nCIDs && cidMap[i+j] >= 0) {
619 buf[0] = (char)fdSelect[cidMap[i+j]];
620 } else {
621 buf[0] = (char)0;
623 n = offset + charStringOffsets[i+j];
624 for (k = gdBytes; k >= 1; --k) {
625 buf[k] = (char)(n & 0xff);
626 n >>= 8;
628 for (k = 0; k <= gdBytes; ++k) {
629 sprintf(buf2, "%02x", buf[k] & 0xff);
630 (*outputFunc)(outputStream, buf2, 2);
633 (*outputFunc)(outputStream, "\n", 1);
636 // write the charstring data
637 n = charStrings->getLength();
638 for (i = 0; i < n; i += 32) {
639 for (j = 0; j < 32 && i+j < n; ++j) {
640 sprintf(buf, "%02x", charStrings->getChar(i+j) & 0xff);
641 (*outputFunc)(outputStream, buf, strlen(buf));
643 if (i + 32 >= n) {
644 (*outputFunc)(outputStream, ">", 1);
646 (*outputFunc)(outputStream, "\n", 1);
649 gfree(charStringOffsets);
650 delete charStrings;
651 gfree(cidMap);
654 void FoFiType1C::convertToType0(char *psName,
655 FoFiOutputFunc outputFunc,
656 void *outputStream) {
657 int *cidMap;
658 Type1CIndex subrIdx;
659 Type1CIndexVal val;
660 int nCIDs;
661 char buf[512];
662 Type1CEexecBuf eb;
663 GBool ok;
664 int fd, i, j, k;
666 // compute the CID count and build the CID-to-GID mapping
667 nCIDs = 0;
668 for (i = 0; i < nGlyphs; ++i) {
669 if (charset[i] >= nCIDs) {
670 nCIDs = charset[i] + 1;
673 cidMap = (int *)gmalloc(nCIDs * sizeof(int));
674 for (i = 0; i < nCIDs; ++i) {
675 cidMap[i] = -1;
677 for (i = 0; i < nGlyphs; ++i) {
678 cidMap[charset[i]] = i;
681 // write the descendant Type 1 fonts
682 for (i = 0; i < nCIDs; i += 256) {
684 //~ this assumes that all CIDs in this block have the same FD --
685 //~ to handle multiple FDs correctly, need to somehow divide the
686 //~ font up by FD
687 fd = 0;
688 for (j = 0; j < 256 && i+j < nCIDs; ++j) {
689 if (cidMap[i+j] >= 0) {
690 fd = fdSelect[cidMap[i+j]];
691 break;
695 // font dictionary (unencrypted section)
696 (*outputFunc)(outputStream, "16 dict begin\n", 14);
697 (*outputFunc)(outputStream, "/FontName /", 11);
698 (*outputFunc)(outputStream, psName, strlen(psName));
699 sprintf(buf, "_%02x def\n", i >> 8);
700 (*outputFunc)(outputStream, buf, strlen(buf));
701 (*outputFunc)(outputStream, "/FontType 1 def\n", 16);
702 sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] def\n",
703 topDict.fontMatrix[0], topDict.fontMatrix[1],
704 topDict.fontMatrix[2], topDict.fontMatrix[3],
705 topDict.fontMatrix[4], topDict.fontMatrix[5]);
706 (*outputFunc)(outputStream, buf, strlen(buf));
707 sprintf(buf, "/FontBBox [%g %g %g %g] def\n",
708 topDict.fontBBox[0], topDict.fontBBox[1],
709 topDict.fontBBox[2], topDict.fontBBox[3]);
710 (*outputFunc)(outputStream, buf, strlen(buf));
711 sprintf(buf, "/PaintType %d def\n", topDict.paintType);
712 (*outputFunc)(outputStream, buf, strlen(buf));
713 if (topDict.paintType != 0) {
714 sprintf(buf, "/StrokeWidth %g def\n", topDict.strokeWidth);
715 (*outputFunc)(outputStream, buf, strlen(buf));
717 (*outputFunc)(outputStream, "/Encoding 256 array\n", 20);
718 for (j = 0; j < 256 && i+j < nCIDs; ++j) {
719 sprintf(buf, "dup %d /c%02x put\n", j, j);
720 (*outputFunc)(outputStream, buf, strlen(buf));
722 if (j < 256) {
723 sprintf(buf, "%d 1 255 { 1 index exch /.notdef put } for\n", j);
724 (*outputFunc)(outputStream, buf, strlen(buf));
726 (*outputFunc)(outputStream, "readonly def\n", 13);
727 (*outputFunc)(outputStream, "currentdict end\n", 16);
729 // start the binary section
730 (*outputFunc)(outputStream, "currentfile eexec\n", 18);
731 eb.outputFunc = outputFunc;
732 eb.outputStream = outputStream;
733 eb.ascii = gTrue;
734 eb.r1 = 55665;
735 eb.line = 0;
737 // start the private dictionary
738 eexecWrite(&eb, "\x83\xca\x73\xd5");
739 eexecWrite(&eb, "dup /Private 32 dict dup begin\n");
740 eexecWrite(&eb, "/RD {string currentfile exch readstring pop}"
741 " executeonly def\n");
742 eexecWrite(&eb, "/ND {noaccess def} executeonly def\n");
743 eexecWrite(&eb, "/NP {noaccess put} executeonly def\n");
744 eexecWrite(&eb, "/MinFeature {16 16} def\n");
745 eexecWrite(&eb, "/password 5839 def\n");
746 if (privateDicts[fd].nBlueValues) {
747 eexecWrite(&eb, "/BlueValues [");
748 for (k = 0; k < privateDicts[fd].nBlueValues; ++k) {
749 sprintf(buf, "%s%d", k > 0 ? " " : "", privateDicts[fd].blueValues[k]);
750 eexecWrite(&eb, buf);
752 eexecWrite(&eb, "] def\n");
754 if (privateDicts[fd].nOtherBlues) {
755 eexecWrite(&eb, "/OtherBlues [");
756 for (k = 0; k < privateDicts[fd].nOtherBlues; ++k) {
757 sprintf(buf, "%s%d", k > 0 ? " " : "", privateDicts[fd].otherBlues[k]);
758 eexecWrite(&eb, buf);
760 eexecWrite(&eb, "] def\n");
762 if (privateDicts[fd].nFamilyBlues) {
763 eexecWrite(&eb, "/FamilyBlues [");
764 for (k = 0; k < privateDicts[fd].nFamilyBlues; ++k) {
765 sprintf(buf, "%s%d", k > 0 ? " " : "",
766 privateDicts[fd].familyBlues[k]);
767 eexecWrite(&eb, buf);
769 eexecWrite(&eb, "] def\n");
771 if (privateDicts[fd].nFamilyOtherBlues) {
772 eexecWrite(&eb, "/FamilyOtherBlues [");
773 for (k = 0; k < privateDicts[fd].nFamilyOtherBlues; ++k) {
774 sprintf(buf, "%s%d", k > 0 ? " " : "",
775 privateDicts[fd].familyOtherBlues[k]);
776 eexecWrite(&eb, buf);
778 eexecWrite(&eb, "] def\n");
780 if (privateDicts[fd].blueScale != 0.039625) {
781 sprintf(buf, "/BlueScale %g def\n", privateDicts[fd].blueScale);
782 eexecWrite(&eb, buf);
784 if (privateDicts[fd].blueShift != 7) {
785 sprintf(buf, "/BlueShift %d def\n", privateDicts[fd].blueShift);
786 eexecWrite(&eb, buf);
788 if (privateDicts[fd].blueFuzz != 1) {
789 sprintf(buf, "/BlueFuzz %d def\n", privateDicts[fd].blueFuzz);
790 eexecWrite(&eb, buf);
792 if (privateDicts[fd].hasStdHW) {
793 sprintf(buf, "/StdHW [%g] def\n", privateDicts[fd].stdHW);
794 eexecWrite(&eb, buf);
796 if (privateDicts[fd].hasStdVW) {
797 sprintf(buf, "/StdVW [%g] def\n", privateDicts[fd].stdVW);
798 eexecWrite(&eb, buf);
800 if (privateDicts[fd].nStemSnapH) {
801 eexecWrite(&eb, "/StemSnapH [");
802 for (k = 0; k < privateDicts[fd].nStemSnapH; ++k) {
803 sprintf(buf, "%s%g", k > 0 ? " " : "", privateDicts[fd].stemSnapH[k]);
804 eexecWrite(&eb, buf);
806 eexecWrite(&eb, "] def\n");
808 if (privateDicts[fd].nStemSnapV) {
809 eexecWrite(&eb, "/StemSnapV [");
810 for (k = 0; k < privateDicts[fd].nStemSnapV; ++k) {
811 sprintf(buf, "%s%g", k > 0 ? " " : "", privateDicts[fd].stemSnapV[k]);
812 eexecWrite(&eb, buf);
814 eexecWrite(&eb, "] def\n");
816 if (privateDicts[fd].hasForceBold) {
817 sprintf(buf, "/ForceBold %s def\n",
818 privateDicts[fd].forceBold ? "true" : "false");
819 eexecWrite(&eb, buf);
821 if (privateDicts[fd].forceBoldThreshold != 0) {
822 sprintf(buf, "/ForceBoldThreshold %g def\n",
823 privateDicts[fd].forceBoldThreshold);
824 eexecWrite(&eb, buf);
826 if (privateDicts[fd].languageGroup != 0) {
827 sprintf(buf, "/LanguageGroup %d def\n", privateDicts[fd].languageGroup);
828 eexecWrite(&eb, buf);
830 if (privateDicts[fd].expansionFactor != 0.06) {
831 sprintf(buf, "/ExpansionFactor %g def\n",
832 privateDicts[fd].expansionFactor);
833 eexecWrite(&eb, buf);
836 // set up the subroutines
837 ok = gTrue;
838 getIndex(privateDicts[fd].subrsOffset, &subrIdx, &ok);
839 if (!ok) {
840 subrIdx.pos = -1;
843 // start the CharStrings
844 sprintf(buf, "2 index /CharStrings 256 dict dup begin\n");
845 eexecWrite(&eb, buf);
847 // write the .notdef CharString
848 ok = gTrue;
849 getIndexVal(&charStringsIdx, 0, &val, &ok);
850 if (ok) {
851 eexecCvtGlyph(&eb, ".notdef", val.pos, val.len,
852 &subrIdx, &privateDicts[fd]);
855 // write the CharStrings
856 for (j = 0; j < 256 && i+j < nCIDs; ++j) {
857 if (cidMap[i+j] >= 0) {
858 ok = gTrue;
859 getIndexVal(&charStringsIdx, cidMap[i+j], &val, &ok);
860 if (ok) {
861 sprintf(buf, "c%02x", j);
862 eexecCvtGlyph(&eb, buf, val.pos, val.len,
863 &subrIdx, &privateDicts[fd]);
867 eexecWrite(&eb, "end\n");
868 eexecWrite(&eb, "end\n");
869 eexecWrite(&eb, "readonly put\n");
870 eexecWrite(&eb, "noaccess put\n");
871 eexecWrite(&eb, "dup /FontName get exch definefont pop\n");
872 eexecWrite(&eb, "mark currentfile closefile\n");
874 // trailer
875 if (eb.line > 0) {
876 (*outputFunc)(outputStream, "\n", 1);
878 for (j = 0; j < 8; ++j) {
879 (*outputFunc)(outputStream, "0000000000000000000000000000000000000000000000000000000000000000\n", 65);
881 (*outputFunc)(outputStream, "cleartomark\n", 12);
884 // write the Type 0 parent font
885 (*outputFunc)(outputStream, "16 dict begin\n", 14);
886 (*outputFunc)(outputStream, "/FontName /", 11);
887 (*outputFunc)(outputStream, psName, strlen(psName));
888 (*outputFunc)(outputStream, " def\n", 5);
889 (*outputFunc)(outputStream, "/FontType 0 def\n", 16);
890 (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
891 (*outputFunc)(outputStream, "/FMapType 2 def\n", 16);
892 (*outputFunc)(outputStream, "/Encoding [\n", 12);
893 for (i = 0; i < nCIDs; i += 256) {
894 sprintf(buf, "%d\n", i >> 8);
895 (*outputFunc)(outputStream, buf, strlen(buf));
897 (*outputFunc)(outputStream, "] def\n", 6);
898 (*outputFunc)(outputStream, "/FDepVector [\n", 14);
899 for (i = 0; i < nCIDs; i += 256) {
900 (*outputFunc)(outputStream, "/", 1);
901 (*outputFunc)(outputStream, psName, strlen(psName));
902 sprintf(buf, "_%02x findfont\n", i >> 8);
903 (*outputFunc)(outputStream, buf, strlen(buf));
905 (*outputFunc)(outputStream, "] def\n", 6);
906 (*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40);
908 gfree(cidMap);
911 void FoFiType1C::eexecCvtGlyph(Type1CEexecBuf *eb, char *glyphName,
912 int offset, int nBytes,
913 Type1CIndex *subrIdx,
914 Type1CPrivateDict *pDict) {
915 char buf[512];
916 GString *charBuf;
918 // generate the charstring
919 charBuf = new GString();
920 cvtGlyph(offset, nBytes, charBuf, subrIdx, pDict, gTrue);
922 sprintf(buf, "/%s %d RD ", glyphName, charBuf->getLength());
923 eexecWrite(eb, buf);
924 eexecWriteCharstring(eb, (Guchar *)charBuf->getCString(),
925 charBuf->getLength());
926 eexecWrite(eb, " ND\n");
928 delete charBuf;
931 void FoFiType1C::cvtGlyph(int offset, int nBytes, GString *charBuf,
932 Type1CIndex *subrIdx, Type1CPrivateDict *pDict,
933 GBool top) {
934 Type1CIndexVal val;
935 GBool ok, dFP;
936 double d, dx, dy;
937 Gushort r2;
938 Guchar byte;
939 int pos, subrBias, start, i, k;
941 start = charBuf->getLength();
942 if (top) {
943 charBuf->append((char)73);
944 charBuf->append((char)58);
945 charBuf->append((char)147);
946 charBuf->append((char)134);
947 nOps = 0;
948 nHints = 0;
949 firstOp = gTrue;
952 pos = offset;
953 while (pos < offset + nBytes) {
954 ok = gTrue;
955 pos = getOp(pos, gTrue, &ok);
956 if (!ok) {
957 break;
959 if (!ops[nOps - 1].isNum) {
960 --nOps; // drop the operator
961 switch (ops[nOps].op) {
962 case 0x0001: // hstem
963 if (firstOp) {
964 cvtGlyphWidth(nOps & 1, charBuf, pDict);
965 firstOp = gFalse;
967 if (nOps & 1) {
968 //~ error(-1, "Wrong number of args (%d) to Type 2 hstem", nOps);
970 d = 0;
971 dFP = gFalse;
972 for (k = 0; k < nOps; k += 2) {
973 if (ops[k+1].num < 0) {
974 d += ops[k].num + ops[k+1].num;
975 dFP |= ops[k].isFP | ops[k+1].isFP;
976 cvtNum(d, dFP, charBuf);
977 cvtNum(-ops[k+1].num, ops[k+1].isFP, charBuf);
978 } else {
979 d += ops[k].num;
980 dFP |= ops[k].isFP;
981 cvtNum(d, dFP, charBuf);
982 cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
983 d += ops[k+1].num;
984 dFP |= ops[k+1].isFP;
986 charBuf->append((char)1);
988 nHints += nOps / 2;
989 nOps = 0;
990 break;
991 case 0x0003: // vstem
992 if (firstOp) {
993 cvtGlyphWidth(nOps & 1, charBuf, pDict);
994 firstOp = gFalse;
996 if (nOps & 1) {
997 //~ error(-1, "Wrong number of args (%d) to Type 2 vstem", nOps);
999 d = 0;
1000 dFP = gFalse;
1001 for (k = 0; k < nOps; k += 2) {
1002 if (ops[k+1].num < 0) {
1003 d += ops[k].num + ops[k+1].num;
1004 dFP |= ops[k].isFP | ops[k+1].isFP;
1005 cvtNum(d, dFP, charBuf);
1006 cvtNum(-ops[k+1].num, ops[k+1].isFP, charBuf);
1007 } else {
1008 d += ops[k].num;
1009 dFP |= ops[k].isFP;
1010 cvtNum(d, dFP, charBuf);
1011 cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
1012 d += ops[k+1].num;
1013 dFP |= ops[k+1].isFP;
1015 charBuf->append((char)3);
1017 nHints += nOps / 2;
1018 nOps = 0;
1019 break;
1020 case 0x0004: // vmoveto
1021 if (firstOp) {
1022 cvtGlyphWidth(nOps == 2, charBuf, pDict);
1023 firstOp = gFalse;
1025 if (nOps != 1) {
1026 //~ error(-1, "Wrong number of args (%d) to Type 2 vmoveto", nOps);
1028 cvtNum(ops[0].num, ops[0].isFP, charBuf);
1029 charBuf->append((char)4);
1030 nOps = 0;
1031 break;
1032 case 0x0005: // rlineto
1033 if (nOps < 2 || nOps % 2 != 0) {
1034 //~ error(-1, "Wrong number of args (%d) to Type 2 rlineto", nOps);
1036 for (k = 0; k < nOps; k += 2) {
1037 cvtNum(ops[k].num, ops[k].isFP, charBuf);
1038 cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
1039 charBuf->append((char)5);
1041 nOps = 0;
1042 break;
1043 case 0x0006: // hlineto
1044 if (nOps < 1) {
1045 //~ error(-1, "Wrong number of args (%d) to Type 2 hlineto", nOps);
1047 for (k = 0; k < nOps; ++k) {
1048 cvtNum(ops[k].num, ops[k].isFP, charBuf);
1049 charBuf->append((char)((k & 1) ? 7 : 6));
1051 nOps = 0;
1052 break;
1053 case 0x0007: // vlineto
1054 if (nOps < 1) {
1055 //~ error(-1, "Wrong number of args (%d) to Type 2 vlineto", nOps);
1057 for (k = 0; k < nOps; ++k) {
1058 cvtNum(ops[k].num, ops[k].isFP, charBuf);
1059 charBuf->append((char)((k & 1) ? 6 : 7));
1061 nOps = 0;
1062 break;
1063 case 0x0008: // rrcurveto
1064 if (nOps < 6 || nOps % 6 != 0) {
1065 //~ error(-1, "Wrong number of args (%d) to Type 2 rrcurveto", nOps);
1067 for (k = 0; k < nOps; k += 6) {
1068 cvtNum(ops[k].num, ops[k].isFP, charBuf);
1069 cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
1070 cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
1071 cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
1072 cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf);
1073 cvtNum(ops[k+5].num, ops[k+5].isFP, charBuf);
1074 charBuf->append((char)8);
1076 nOps = 0;
1077 break;
1078 case 0x000a: // callsubr
1079 if (nOps >= 1) {
1080 subrBias = (subrIdx->len < 1240)
1081 ? 107 : (subrIdx->len < 33900) ? 1131 : 32768;
1082 k = subrBias + (int)ops[nOps - 1].num;
1083 --nOps;
1084 ok = gTrue;
1085 getIndexVal(subrIdx, k, &val, &ok);
1086 if (ok) {
1087 cvtGlyph(val.pos, val.len, charBuf, subrIdx, pDict, gFalse);
1089 } else {
1090 //~ error(-1, "Too few args to Type 2 callsubr");
1092 // don't clear the stack
1093 break;
1094 case 0x000b: // return
1095 // don't clear the stack
1096 break;
1097 case 0x000e: // endchar / seac
1098 if (firstOp) {
1099 cvtGlyphWidth(nOps == 1 || nOps == 5, charBuf, pDict);
1100 firstOp = gFalse;
1102 if (nOps == 4) {
1103 cvtNum(0, gFalse, charBuf);
1104 cvtNum(ops[0].num, ops[0].isFP, charBuf);
1105 cvtNum(ops[1].num, ops[1].isFP, charBuf);
1106 cvtNum(ops[2].num, ops[2].isFP, charBuf);
1107 cvtNum(ops[3].num, ops[3].isFP, charBuf);
1108 charBuf->append((char)12)->append((char)6);
1109 } else if (nOps == 0) {
1110 charBuf->append((char)14);
1111 } else {
1112 //~ error(-1, "Wrong number of args (%d) to Type 2 endchar", nOps);
1114 nOps = 0;
1115 break;
1116 case 0x000f: // (obsolete)
1117 // this op is ignored, but we need the glyph width
1118 if (firstOp) {
1119 cvtGlyphWidth(nOps > 0, charBuf, pDict);
1120 firstOp = gFalse;
1122 nOps = 0;
1123 break;
1124 case 0x0010: // blend
1125 //~ error(-1, "Unimplemented Type 2 charstring op: %d", file[i]);
1126 nOps = 0;
1127 break;
1128 case 0x0012: // hstemhm
1129 // ignored
1130 if (firstOp) {
1131 cvtGlyphWidth(nOps & 1, charBuf, pDict);
1132 firstOp = gFalse;
1134 if (nOps & 1) {
1135 //~ error(-1, "Wrong number of args (%d) to Type 2 hstemhm", nOps);
1137 nHints += nOps / 2;
1138 nOps = 0;
1139 break;
1140 case 0x0013: // hintmask
1141 // ignored
1142 if (firstOp) {
1143 cvtGlyphWidth(nOps & 1, charBuf, pDict);
1144 firstOp = gFalse;
1146 if (nOps > 0) {
1147 if (nOps & 1) {
1148 //~ error(-1, "Wrong number of args (%d) to Type 2 hintmask/vstemhm",
1149 //~ nOps);
1151 nHints += nOps / 2;
1153 pos += (nHints + 7) >> 3;
1154 nOps = 0;
1155 break;
1156 case 0x0014: // cntrmask
1157 // ignored
1158 if (firstOp) {
1159 cvtGlyphWidth(nOps & 1, charBuf, pDict);
1160 firstOp = gFalse;
1162 if (nOps > 0) {
1163 if (nOps & 1) {
1164 //~ error(-1, "Wrong number of args (%d) to Type 2 cntrmask/vstemhm",
1165 //~ nOps);
1167 nHints += nOps / 2;
1169 pos += (nHints + 7) >> 3;
1170 nOps = 0;
1171 break;
1172 case 0x0015: // rmoveto
1173 if (firstOp) {
1174 cvtGlyphWidth(nOps == 3, charBuf, pDict);
1175 firstOp = gFalse;
1177 if (nOps != 2) {
1178 //~ error(-1, "Wrong number of args (%d) to Type 2 rmoveto", nOps);
1180 cvtNum(ops[0].num, ops[0].isFP, charBuf);
1181 cvtNum(ops[1].num, ops[1].isFP, charBuf);
1182 charBuf->append((char)21);
1183 nOps = 0;
1184 break;
1185 case 0x0016: // hmoveto
1186 if (firstOp) {
1187 cvtGlyphWidth(nOps == 2, charBuf, pDict);
1188 firstOp = gFalse;
1190 if (nOps != 1) {
1191 //~ error(-1, "Wrong number of args (%d) to Type 2 hmoveto", nOps);
1193 cvtNum(ops[0].num, ops[0].isFP, charBuf);
1194 charBuf->append((char)22);
1195 nOps = 0;
1196 break;
1197 case 0x0017: // vstemhm
1198 // ignored
1199 if (firstOp) {
1200 cvtGlyphWidth(nOps & 1, charBuf, pDict);
1201 firstOp = gFalse;
1203 if (nOps & 1) {
1204 //~ error(-1, "Wrong number of args (%d) to Type 2 vstemhm", nOps);
1206 nHints += nOps / 2;
1207 nOps = 0;
1208 break;
1209 case 0x0018: // rcurveline
1210 if (nOps < 8 || (nOps - 2) % 6 != 0) {
1211 //~ error(-1, "Wrong number of args (%d) to Type 2 rcurveline", nOps);
1213 for (k = 0; k < nOps - 2; k += 6) {
1214 cvtNum(ops[k].num, ops[k].isFP, charBuf);
1215 cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
1216 cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
1217 cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
1218 cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf);
1219 cvtNum(ops[k+5].num, ops[k+5].isFP, charBuf);
1220 charBuf->append((char)8);
1222 cvtNum(ops[k].num, ops[k].isFP, charBuf);
1223 cvtNum(ops[k+1].num, ops[k].isFP, charBuf);
1224 charBuf->append((char)5);
1225 nOps = 0;
1226 break;
1227 case 0x0019: // rlinecurve
1228 if (nOps < 8 || (nOps - 6) % 2 != 0) {
1229 //~ error(-1, "Wrong number of args (%d) to Type 2 rlinecurve", nOps);
1231 for (k = 0; k < nOps - 6; k += 2) {
1232 cvtNum(ops[k].num, ops[k].isFP, charBuf);
1233 cvtNum(ops[k+1].num, ops[k].isFP, charBuf);
1234 charBuf->append((char)5);
1236 cvtNum(ops[k].num, ops[k].isFP, charBuf);
1237 cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
1238 cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
1239 cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
1240 cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf);
1241 cvtNum(ops[k+5].num, ops[k+5].isFP, charBuf);
1242 charBuf->append((char)8);
1243 nOps = 0;
1244 break;
1245 case 0x001a: // vvcurveto
1246 if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
1247 //~ error(-1, "Wrong number of args (%d) to Type 2 vvcurveto", nOps);
1249 if (nOps % 2 == 1) {
1250 cvtNum(ops[0].num, ops[0].isFP, charBuf);
1251 cvtNum(ops[1].num, ops[1].isFP, charBuf);
1252 cvtNum(ops[2].num, ops[2].isFP, charBuf);
1253 cvtNum(ops[3].num, ops[3].isFP, charBuf);
1254 cvtNum(0, gFalse, charBuf);
1255 cvtNum(ops[4].num, ops[4].isFP, charBuf);
1256 charBuf->append((char)8);
1257 k = 5;
1258 } else {
1259 k = 0;
1261 for (; k < nOps; k += 4) {
1262 cvtNum(0, gFalse, charBuf);
1263 cvtNum(ops[k].num, ops[k].isFP, charBuf);
1264 cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
1265 cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
1266 cvtNum(0, gFalse, charBuf);
1267 cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
1268 charBuf->append((char)8);
1270 nOps = 0;
1271 break;
1272 case 0x001b: // hhcurveto
1273 if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
1274 //~ error(-1, "Wrong number of args (%d) to Type 2 hhcurveto", nOps);
1276 if (nOps % 2 == 1) {
1277 cvtNum(ops[1].num, ops[1].isFP, charBuf);
1278 cvtNum(ops[0].num, ops[0].isFP, charBuf);
1279 cvtNum(ops[2].num, ops[2].isFP, charBuf);
1280 cvtNum(ops[3].num, ops[3].isFP, charBuf);
1281 cvtNum(ops[4].num, ops[4].isFP, charBuf);
1282 cvtNum(0, gFalse, charBuf);
1283 charBuf->append((char)8);
1284 k = 5;
1285 } else {
1286 k = 0;
1288 for (; k < nOps; k += 4) {
1289 cvtNum(ops[k].num, ops[k].isFP, charBuf);
1290 cvtNum(0, gFalse, charBuf);
1291 cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
1292 cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
1293 cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
1294 cvtNum(0, gFalse, charBuf);
1295 charBuf->append((char)8);
1297 nOps = 0;
1298 break;
1299 case 0x001d: // callgsubr
1300 if (nOps >= 1) {
1301 k = gsubrBias + (int)ops[nOps - 1].num;
1302 --nOps;
1303 ok = gTrue;
1304 getIndexVal(&gsubrIdx, k, &val, &ok);
1305 if (ok) {
1306 cvtGlyph(val.pos, val.len, charBuf, subrIdx, pDict, gFalse);
1308 } else {
1309 //~ error(-1, "Too few args to Type 2 callgsubr");
1311 // don't clear the stack
1312 break;
1313 case 0x001e: // vhcurveto
1314 if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
1315 //~ error(-1, "Wrong number of args (%d) to Type 2 vhcurveto", nOps);
1317 for (k = 0; k < nOps && k != nOps-5; k += 4) {
1318 if (k % 8 == 0) {
1319 cvtNum(ops[k].num, ops[k].isFP, charBuf);
1320 cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
1321 cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
1322 cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
1323 charBuf->append((char)30);
1324 } else {
1325 cvtNum(ops[k].num, ops[k].isFP, charBuf);
1326 cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
1327 cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
1328 cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
1329 charBuf->append((char)31);
1332 if (k == nOps-5) {
1333 if (k % 8 == 0) {
1334 cvtNum(0, gFalse, charBuf);
1335 cvtNum(ops[k].num, ops[k].isFP, charBuf);
1336 cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
1337 cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
1338 cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
1339 cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf);
1340 } else {
1341 cvtNum(ops[k].num, ops[k].isFP, charBuf);
1342 cvtNum(0, gFalse, charBuf);
1343 cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
1344 cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
1345 cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf);
1346 cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
1348 charBuf->append((char)8);
1350 nOps = 0;
1351 break;
1352 case 0x001f: // hvcurveto
1353 if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
1354 //~ error(-1, "Wrong number of args (%d) to Type 2 hvcurveto", nOps);
1356 for (k = 0; k < nOps && k != nOps-5; k += 4) {
1357 if (k % 8 == 0) {
1358 cvtNum(ops[k].num, ops[k].isFP, charBuf);
1359 cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
1360 cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
1361 cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
1362 charBuf->append((char)31);
1363 } else {
1364 cvtNum(ops[k].num, ops[k].isFP, charBuf);
1365 cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
1366 cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
1367 cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
1368 charBuf->append((char)30);
1371 if (k == nOps-5) {
1372 if (k % 8 == 0) {
1373 cvtNum(ops[k].num, ops[k].isFP, charBuf);
1374 cvtNum(0, gFalse, charBuf);
1375 cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
1376 cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
1377 cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf);
1378 cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
1379 } else {
1380 cvtNum(0, gFalse, charBuf);
1381 cvtNum(ops[k].num, ops[k].isFP, charBuf);
1382 cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
1383 cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
1384 cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
1385 cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf);
1387 charBuf->append((char)8);
1389 nOps = 0;
1390 break;
1391 case 0x0c00: // dotsection (should be Type 1 only?)
1392 // ignored
1393 nOps = 0;
1394 break;
1395 case 0x0c03: // and
1396 case 0x0c04: // or
1397 case 0x0c05: // not
1398 case 0x0c08: // store
1399 case 0x0c09: // abs
1400 case 0x0c0a: // add
1401 case 0x0c0b: // sub
1402 case 0x0c0c: // div
1403 case 0x0c0d: // load
1404 case 0x0c0e: // neg
1405 case 0x0c0f: // eq
1406 case 0x0c12: // drop
1407 case 0x0c14: // put
1408 case 0x0c15: // get
1409 case 0x0c16: // ifelse
1410 case 0x0c17: // random
1411 case 0x0c18: // mul
1412 case 0x0c1a: // sqrt
1413 case 0x0c1b: // dup
1414 case 0x0c1c: // exch
1415 case 0x0c1d: // index
1416 case 0x0c1e: // roll
1417 //~ error(-1, "Unimplemented Type 2 charstring op: 12.%d", file[i+1]);
1418 nOps = 0;
1419 break;
1420 case 0x0c22: // hflex
1421 if (nOps != 7) {
1422 //~ error(-1, "Wrong number of args (%d) to Type 2 hflex", nOps);
1424 cvtNum(ops[0].num, ops[0].isFP, charBuf);
1425 cvtNum(0, gFalse, charBuf);
1426 cvtNum(ops[1].num, ops[1].isFP, charBuf);
1427 cvtNum(ops[2].num, ops[2].isFP, charBuf);
1428 cvtNum(ops[3].num, ops[3].isFP, charBuf);
1429 cvtNum(0, gFalse, charBuf);
1430 charBuf->append((char)8);
1431 cvtNum(ops[4].num, ops[4].isFP, charBuf);
1432 cvtNum(0, gFalse, charBuf);
1433 cvtNum(ops[5].num, ops[5].isFP, charBuf);
1434 cvtNum(-ops[2].num, ops[2].isFP, charBuf);
1435 cvtNum(ops[6].num, ops[6].isFP, charBuf);
1436 cvtNum(0, gFalse, charBuf);
1437 charBuf->append((char)8);
1438 nOps = 0;
1439 break;
1440 case 0x0c23: // flex
1441 if (nOps != 13) {
1442 //~ error(-1, "Wrong number of args (%d) to Type 2 flex", nOps);
1444 cvtNum(ops[0].num, ops[0].isFP, charBuf);
1445 cvtNum(ops[1].num, ops[1].isFP, charBuf);
1446 cvtNum(ops[2].num, ops[2].isFP, charBuf);
1447 cvtNum(ops[3].num, ops[3].isFP, charBuf);
1448 cvtNum(ops[4].num, ops[4].isFP, charBuf);
1449 cvtNum(ops[5].num, ops[5].isFP, charBuf);
1450 charBuf->append((char)8);
1451 cvtNum(ops[6].num, ops[6].isFP, charBuf);
1452 cvtNum(ops[7].num, ops[7].isFP, charBuf);
1453 cvtNum(ops[8].num, ops[8].isFP, charBuf);
1454 cvtNum(ops[9].num, ops[9].isFP, charBuf);
1455 cvtNum(ops[10].num, ops[10].isFP, charBuf);
1456 cvtNum(ops[11].num, ops[11].isFP, charBuf);
1457 charBuf->append((char)8);
1458 nOps = 0;
1459 break;
1460 case 0x0c24: // hflex1
1461 if (nOps != 9) {
1462 //~ error(-1, "Wrong number of args (%d) to Type 2 hflex1", nOps);
1464 cvtNum(ops[0].num, ops[0].isFP, charBuf);
1465 cvtNum(ops[1].num, ops[1].isFP, charBuf);
1466 cvtNum(ops[2].num, ops[2].isFP, charBuf);
1467 cvtNum(ops[3].num, ops[3].isFP, charBuf);
1468 cvtNum(ops[4].num, ops[4].isFP, charBuf);
1469 cvtNum(0, gFalse, charBuf);
1470 charBuf->append((char)8);
1471 cvtNum(ops[5].num, ops[5].isFP, charBuf);
1472 cvtNum(0, gFalse, charBuf);
1473 cvtNum(ops[6].num, ops[6].isFP, charBuf);
1474 cvtNum(ops[7].num, ops[7].isFP, charBuf);
1475 cvtNum(ops[8].num, ops[8].isFP, charBuf);
1476 cvtNum(-(ops[1].num + ops[3].num + ops[7].num),
1477 ops[1].isFP | ops[3].isFP | ops[7].isFP, charBuf);
1478 charBuf->append((char)8);
1479 nOps = 0;
1480 break;
1481 case 0x0c25: // flex1
1482 if (nOps != 11) {
1483 //~ error(-1, "Wrong number of args (%d) to Type 2 flex1", nOps);
1485 cvtNum(ops[0].num, ops[0].isFP, charBuf);
1486 cvtNum(ops[1].num, ops[1].isFP, charBuf);
1487 cvtNum(ops[2].num, ops[2].isFP, charBuf);
1488 cvtNum(ops[3].num, ops[3].isFP, charBuf);
1489 cvtNum(ops[4].num, ops[4].isFP, charBuf);
1490 cvtNum(ops[5].num, ops[5].isFP, charBuf);
1491 charBuf->append((char)8);
1492 cvtNum(ops[6].num, ops[6].isFP, charBuf);
1493 cvtNum(ops[7].num, ops[7].isFP, charBuf);
1494 cvtNum(ops[8].num, ops[8].isFP, charBuf);
1495 cvtNum(ops[9].num, ops[9].isFP, charBuf);
1496 dx = ops[0].num + ops[2].num + ops[4].num + ops[6].num + ops[8].num;
1497 dy = ops[1].num + ops[3].num + ops[5].num + ops[7].num + ops[9].num;
1498 if (fabs(dx) > fabs(dy)) {
1499 cvtNum(ops[10].num, ops[10].isFP, charBuf);
1500 cvtNum(-dy, ops[1].isFP | ops[3].isFP | ops[5].isFP |
1501 ops[7].isFP | ops[9].isFP, charBuf);
1502 } else {
1503 cvtNum(-dx, ops[0].isFP | ops[2].isFP | ops[4].isFP |
1504 ops[6].isFP | ops[8].isFP, charBuf);
1505 cvtNum(ops[10].num, ops[10].isFP, charBuf);
1507 charBuf->append((char)8);
1508 nOps = 0;
1509 break;
1510 default:
1511 //~ error(-1, "Illegal Type 2 charstring op: %04x",
1512 //~ ops[nOps].op);
1513 nOps = 0;
1514 break;
1519 // charstring encryption
1520 if (top) {
1521 r2 = 4330;
1522 for (i = start; i < charBuf->getLength(); ++i) {
1523 byte = charBuf->getChar(i) ^ (r2 >> 8);
1524 charBuf->setChar(i, byte);
1525 r2 = (byte + r2) * 52845 + 22719;
1530 void FoFiType1C::cvtGlyphWidth(GBool useOp, GString *charBuf,
1531 Type1CPrivateDict *pDict) {
1532 double w;
1533 GBool wFP;
1534 int i;
1536 if (useOp) {
1537 w = pDict->nominalWidthX + ops[0].num;
1538 wFP = pDict->nominalWidthXFP | ops[0].isFP;
1539 for (i = 1; i < nOps; ++i) {
1540 ops[i-1] = ops[i];
1542 --nOps;
1543 } else {
1544 w = pDict->defaultWidthX;
1545 wFP = pDict->defaultWidthXFP;
1547 cvtNum(0, gFalse, charBuf);
1548 cvtNum(w, wFP, charBuf);
1549 charBuf->append((char)13);
1552 void FoFiType1C::cvtNum(double x, GBool isFP, GString *charBuf) {
1553 Guchar buf[12];
1554 int y, n;
1556 n = 0;
1557 if (isFP) {
1558 if (x >= -32768 && x < 32768) {
1559 y = (int)(x * 256.0);
1560 buf[0] = 255;
1561 buf[1] = (Guchar)(y >> 24);
1562 buf[2] = (Guchar)(y >> 16);
1563 buf[3] = (Guchar)(y >> 8);
1564 buf[4] = (Guchar)y;
1565 buf[5] = 255;
1566 buf[6] = 0;
1567 buf[7] = 0;
1568 buf[8] = 1;
1569 buf[9] = 0;
1570 buf[10] = 12;
1571 buf[11] = 12;
1572 n = 12;
1573 } else {
1574 //~ error(-1, "Type 2 fixed point constant out of range");
1576 } else {
1577 y = (int)x;
1578 if (y >= -107 && y <= 107) {
1579 buf[0] = (Guchar)(y + 139);
1580 n = 1;
1581 } else if (y > 107 && y <= 1131) {
1582 y -= 108;
1583 buf[0] = (Guchar)((y >> 8) + 247);
1584 buf[1] = (Guchar)(y & 0xff);
1585 n = 2;
1586 } else if (y < -107 && y >= -1131) {
1587 y = -y - 108;
1588 buf[0] = (Guchar)((y >> 8) + 251);
1589 buf[1] = (Guchar)(y & 0xff);
1590 n = 2;
1591 } else {
1592 buf[0] = 255;
1593 buf[1] = (Guchar)(y >> 24);
1594 buf[2] = (Guchar)(y >> 16);
1595 buf[3] = (Guchar)(y >> 8);
1596 buf[4] = (Guchar)y;
1597 n = 5;
1600 charBuf->append((char *)buf, n);
1603 void FoFiType1C::eexecWrite(Type1CEexecBuf *eb, char *s) {
1604 Guchar *p;
1605 Guchar x;
1607 for (p = (Guchar *)s; *p; ++p) {
1608 x = *p ^ (eb->r1 >> 8);
1609 eb->r1 = (x + eb->r1) * 52845 + 22719;
1610 if (eb->ascii) {
1611 (*eb->outputFunc)(eb->outputStream, &hexChars[x >> 4], 1);
1612 (*eb->outputFunc)(eb->outputStream, &hexChars[x & 0x0f], 1);
1613 eb->line += 2;
1614 if (eb->line == 64) {
1615 (*eb->outputFunc)(eb->outputStream, "\n", 1);
1616 eb->line = 0;
1618 } else {
1619 (*eb->outputFunc)(eb->outputStream, (char *)&x, 1);
1624 void FoFiType1C::eexecWriteCharstring(Type1CEexecBuf *eb,
1625 Guchar *s, int n) {
1626 Guchar x;
1627 int i;
1629 // eexec encryption
1630 for (i = 0; i < n; ++i) {
1631 x = s[i] ^ (eb->r1 >> 8);
1632 eb->r1 = (x + eb->r1) * 52845 + 22719;
1633 if (eb->ascii) {
1634 (*eb->outputFunc)(eb->outputStream, &hexChars[x >> 4], 1);
1635 (*eb->outputFunc)(eb->outputStream, &hexChars[x & 0x0f], 1);
1636 eb->line += 2;
1637 if (eb->line == 64) {
1638 (*eb->outputFunc)(eb->outputStream, "\n", 1);
1639 eb->line = 0;
1641 } else {
1642 (*eb->outputFunc)(eb->outputStream, (char *)&x, 1);
1647 GBool FoFiType1C::parse() {
1648 Type1CIndex fdIdx;
1649 Type1CIndexVal val;
1650 int i;
1652 parsedOk = gTrue;
1654 // some tools embed Type 1C fonts with an extra whitespace char at
1655 // the beginning
1656 if (len > 0 && file[0] != '\x01') {
1657 ++file;
1658 --len;
1661 // find the indexes
1662 getIndex(getU8(2, &parsedOk), &nameIdx, &parsedOk);
1663 getIndex(nameIdx.endPos, &topDictIdx, &parsedOk);
1664 getIndex(topDictIdx.endPos, &stringIdx, &parsedOk);
1665 getIndex(stringIdx.endPos, &gsubrIdx, &parsedOk);
1666 if (!parsedOk) {
1667 return gFalse;
1669 gsubrBias = (gsubrIdx.len < 1240) ? 107
1670 : (gsubrIdx.len < 33900) ? 1131 : 32768;
1672 // read the first font name
1673 getIndexVal(&nameIdx, 0, &val, &parsedOk);
1674 if (!parsedOk) {
1675 return gFalse;
1677 name = new GString((char *)&file[val.pos], val.len);
1679 // read the top dict for the first font
1680 readTopDict();
1682 // for CID fonts: read the FDArray dicts and private dicts
1683 if (topDict.firstOp == 0x0c1e) {
1684 if (topDict.fdArrayOffset == 0) {
1685 nFDs = 1;
1686 privateDicts = (Type1CPrivateDict *)gmalloc(sizeof(Type1CPrivateDict));
1687 readPrivateDict(0, 0, &privateDicts[0]);
1688 } else {
1689 getIndex(topDict.fdArrayOffset, &fdIdx, &parsedOk);
1690 if (!parsedOk) {
1691 return gFalse;
1693 nFDs = fdIdx.len;
1694 privateDicts = (Type1CPrivateDict *)
1695 gmalloc(nFDs * sizeof(Type1CPrivateDict));
1696 for (i = 0; i < nFDs; ++i) {
1697 getIndexVal(&fdIdx, i, &val, &parsedOk);
1698 if (!parsedOk) {
1699 return gFalse;
1701 readFD(val.pos, val.len, &privateDicts[i]);
1705 // for 8-bit fonts: read the private dict
1706 } else {
1707 privateDicts = (Type1CPrivateDict *)gmalloc(sizeof(Type1CPrivateDict));
1708 readPrivateDict(topDict.privateOffset, topDict.privateSize,
1709 &privateDicts[0]);
1712 // check for parse errors in the private dict(s)
1713 if (!parsedOk) {
1714 return gFalse;
1717 // get the charstrings index
1718 if (topDict.charStringsOffset <= 0) {
1719 parsedOk = gFalse;
1720 return gFalse;
1722 getIndex(topDict.charStringsOffset, &charStringsIdx, &parsedOk);
1723 if (!parsedOk) {
1724 return gFalse;
1726 nGlyphs = charStringsIdx.len;
1728 // for CID fonts: read the FDSelect table
1729 if (topDict.firstOp == 0x0c1e) {
1730 readFDSelect();
1731 if (!parsedOk) {
1732 return gFalse;
1736 // read the charset
1737 if (!readCharset()) {
1738 parsedOk = gFalse;
1739 return gFalse;
1742 // for 8-bit fonts: build the encoding
1743 if (topDict.firstOp != 0x0c14 && topDict.firstOp != 0x0c1e) {
1744 buildEncoding();
1745 if (!parsedOk) {
1746 return gFalse;
1750 return parsedOk;
1753 void FoFiType1C::readTopDict() {
1754 Type1CIndexVal topDictPtr;
1755 int pos;
1757 topDict.firstOp = -1;
1758 topDict.versionSID = 0;
1759 topDict.noticeSID = 0;
1760 topDict.copyrightSID = 0;
1761 topDict.fullNameSID = 0;
1762 topDict.familyNameSID = 0;
1763 topDict.weightSID = 0;
1764 topDict.isFixedPitch = 0;
1765 topDict.italicAngle = 0;
1766 topDict.underlinePosition = -100;
1767 topDict.underlineThickness = 50;
1768 topDict.paintType = 0;
1769 topDict.charstringType = 2;
1770 topDict.fontMatrix[0] = 0.001;
1771 topDict.fontMatrix[1] = 0;
1772 topDict.fontMatrix[2] = 0;
1773 topDict.fontMatrix[3] = 0.001;
1774 topDict.fontMatrix[4] = 0;
1775 topDict.fontMatrix[5] = 0;
1776 topDict.uniqueID = 0;
1777 topDict.fontBBox[0] = 0;
1778 topDict.fontBBox[1] = 0;
1779 topDict.fontBBox[2] = 0;
1780 topDict.fontBBox[3] = 0;
1781 topDict.strokeWidth = 0;
1782 topDict.charsetOffset = 0;
1783 topDict.encodingOffset = 0;
1784 topDict.charStringsOffset = 0;
1785 topDict.privateSize = 0;
1786 topDict.privateOffset = 0;
1787 topDict.registrySID = 0;
1788 topDict.orderingSID = 0;
1789 topDict.supplement = 0;
1790 topDict.fdArrayOffset = 0;
1791 topDict.fdSelectOffset = 0;
1793 getIndexVal(&topDictIdx, 0, &topDictPtr, &parsedOk);
1794 pos = topDictPtr.pos;
1795 nOps = 0;
1796 while (pos < topDictPtr.pos + topDictPtr.len) {
1797 pos = getOp(pos, gFalse, &parsedOk);
1798 if (!parsedOk) {
1799 break;
1801 if (!ops[nOps - 1].isNum) {
1802 --nOps; // drop the operator
1803 if (topDict.firstOp < 0) {
1804 topDict.firstOp = ops[nOps].op;
1806 switch (ops[nOps].op) {
1807 case 0x0000: topDict.versionSID = (int)ops[0].num; break;
1808 case 0x0001: topDict.noticeSID = (int)ops[0].num; break;
1809 case 0x0c00: topDict.copyrightSID = (int)ops[0].num; break;
1810 case 0x0002: topDict.fullNameSID = (int)ops[0].num; break;
1811 case 0x0003: topDict.familyNameSID = (int)ops[0].num; break;
1812 case 0x0004: topDict.weightSID = (int)ops[0].num; break;
1813 case 0x0c01: topDict.isFixedPitch = (int)ops[0].num; break;
1814 case 0x0c02: topDict.italicAngle = ops[0].num; break;
1815 case 0x0c03: topDict.underlinePosition = ops[0].num; break;
1816 case 0x0c04: topDict.underlineThickness = ops[0].num; break;
1817 case 0x0c05: topDict.paintType = (int)ops[0].num; break;
1818 case 0x0c06: topDict.charstringType = (int)ops[0].num; break;
1819 case 0x0c07: topDict.fontMatrix[0] = ops[0].num;
1820 topDict.fontMatrix[1] = ops[1].num;
1821 topDict.fontMatrix[2] = ops[2].num;
1822 topDict.fontMatrix[3] = ops[3].num;
1823 topDict.fontMatrix[4] = ops[4].num;
1824 topDict.fontMatrix[5] = ops[5].num; break;
1825 case 0x000d: topDict.uniqueID = (int)ops[0].num; break;
1826 case 0x0005: topDict.fontBBox[0] = ops[0].num;
1827 topDict.fontBBox[1] = ops[1].num;
1828 topDict.fontBBox[2] = ops[2].num;
1829 topDict.fontBBox[3] = ops[3].num; break;
1830 case 0x0c08: topDict.strokeWidth = ops[0].num; break;
1831 case 0x000f: topDict.charsetOffset = (int)ops[0].num; break;
1832 case 0x0010: topDict.encodingOffset = (int)ops[0].num; break;
1833 case 0x0011: topDict.charStringsOffset = (int)ops[0].num; break;
1834 case 0x0012: topDict.privateSize = (int)ops[0].num;
1835 topDict.privateOffset = (int)ops[1].num; break;
1836 case 0x0c1e: topDict.registrySID = (int)ops[0].num;
1837 topDict.orderingSID = (int)ops[1].num;
1838 topDict.supplement = (int)ops[2].num; break;
1839 case 0x0c24: topDict.fdArrayOffset = (int)ops[0].num; break;
1840 case 0x0c25: topDict.fdSelectOffset = (int)ops[0].num; break;
1842 nOps = 0;
1847 // Read a CID font dict (FD) - this pulls out the private dict
1848 // pointer, and reads the private dict.
1849 void FoFiType1C::readFD(int offset, int length, Type1CPrivateDict *pDict) {
1850 int pos, pSize, pOffset;
1852 pSize = pOffset = 0;
1853 pos = offset;
1854 nOps = 0;
1855 while (pos < offset + length) {
1856 pos = getOp(pos, gFalse, &parsedOk);
1857 if (!parsedOk) {
1858 return;
1860 if (!ops[nOps - 1].isNum) {
1861 if (ops[nOps - 1].op == 0x0012) {
1862 if (nOps < 3) {
1863 parsedOk = gFalse;
1864 return;
1866 pSize = (int)ops[0].num;
1867 pOffset = (int)ops[1].num;
1868 break;
1870 nOps = 0;
1873 readPrivateDict(pOffset, pSize, pDict);
1876 void FoFiType1C::readPrivateDict(int offset, int length,
1877 Type1CPrivateDict *pDict) {
1878 int pos;
1880 pDict->nBlueValues = 0;
1881 pDict->nOtherBlues = 0;
1882 pDict->nFamilyBlues = 0;
1883 pDict->nFamilyOtherBlues = 0;
1884 pDict->blueScale = 0.039625;
1885 pDict->blueShift = 7;
1886 pDict->blueFuzz = 1;
1887 pDict->hasStdHW = gFalse;
1888 pDict->hasStdVW = gFalse;
1889 pDict->nStemSnapH = 0;
1890 pDict->nStemSnapV = 0;
1891 pDict->hasForceBold = gFalse;
1892 pDict->forceBoldThreshold = 0;
1893 pDict->languageGroup = 0;
1894 pDict->expansionFactor = 0.06;
1895 pDict->initialRandomSeed = 0;
1896 pDict->subrsOffset = 0;
1897 pDict->defaultWidthX = 0;
1898 pDict->defaultWidthXFP = 0;
1899 pDict->nominalWidthX = 0;
1900 pDict->nominalWidthXFP = 0;
1902 // no dictionary
1903 if (offset == 0 || length == 0) {
1904 return;
1907 pos = offset;
1908 nOps = 0;
1909 while (pos < offset + length) {
1910 pos = getOp(pos, gFalse, &parsedOk);
1911 if (!parsedOk) {
1912 break;
1914 if (!ops[nOps - 1].isNum) {
1915 --nOps; // drop the operator
1916 switch (ops[nOps].op) {
1917 case 0x0006:
1918 pDict->nBlueValues = getDeltaIntArray(pDict->blueValues,
1919 type1CMaxBlueValues);
1920 break;
1921 case 0x0007:
1922 pDict->nOtherBlues = getDeltaIntArray(pDict->otherBlues,
1923 type1CMaxOtherBlues);
1924 break;
1925 case 0x0008:
1926 pDict->nFamilyBlues = getDeltaIntArray(pDict->familyBlues,
1927 type1CMaxBlueValues);
1928 break;
1929 case 0x0009:
1930 pDict->nFamilyOtherBlues = getDeltaIntArray(pDict->familyOtherBlues,
1931 type1CMaxOtherBlues);
1932 break;
1933 case 0x0c09:
1934 pDict->blueScale = ops[0].num;
1935 break;
1936 case 0x0c0a:
1937 pDict->blueShift = (int)ops[0].num;
1938 break;
1939 case 0x0c0b:
1940 pDict->blueFuzz = (int)ops[0].num;
1941 break;
1942 case 0x000a:
1943 pDict->stdHW = ops[0].num;
1944 pDict->hasStdHW = gTrue;
1945 break;
1946 case 0x000b:
1947 pDict->stdVW = ops[0].num;
1948 pDict->hasStdVW = gTrue;
1949 break;
1950 case 0x0c0c:
1951 pDict->nStemSnapH = getDeltaFPArray(pDict->stemSnapH,
1952 type1CMaxStemSnap);
1953 break;
1954 case 0x0c0d:
1955 pDict->nStemSnapV = getDeltaFPArray(pDict->stemSnapV,
1956 type1CMaxStemSnap);
1957 break;
1958 case 0x0c0e:
1959 pDict->forceBold = ops[0].num != 0;
1960 pDict->hasForceBold = gTrue;
1961 break;
1962 case 0x0c0f:
1963 pDict->forceBoldThreshold = ops[0].num;
1964 break;
1965 case 0x0c11:
1966 pDict->languageGroup = (int)ops[0].num;
1967 break;
1968 case 0x0c12:
1969 pDict->expansionFactor = ops[0].num;
1970 break;
1971 case 0x0c13:
1972 pDict->initialRandomSeed = (int)ops[0].num;
1973 break;
1974 case 0x0013:
1975 pDict->subrsOffset = offset + (int)ops[0].num;
1976 break;
1977 case 0x0014:
1978 pDict->defaultWidthX = ops[0].num;
1979 break;
1980 case 0x0015:
1981 pDict->nominalWidthX = ops[0].num;
1982 break;
1984 nOps = 0;
1989 void FoFiType1C::readFDSelect() {
1990 int fdSelectFmt, pos, nRanges, gid0, gid1, fd, i, j;
1992 fdSelect = (Guchar *)gmalloc(nGlyphs);
1993 if (topDict.fdSelectOffset == 0) {
1994 for (i = 0; i < nGlyphs; ++i) {
1995 fdSelect[i] = 0;
1997 } else {
1998 pos = topDict.fdSelectOffset;
1999 fdSelectFmt = getU8(pos++, &parsedOk);
2000 if (!parsedOk) {
2001 return;
2003 if (fdSelectFmt == 0) {
2004 if (!checkRegion(pos, nGlyphs)) {
2005 parsedOk = gFalse;
2006 return;
2008 memcpy(fdSelect, file + pos, nGlyphs);
2009 } else if (fdSelectFmt == 3) {
2010 nRanges = getU16BE(pos, &parsedOk);
2011 pos += 2;
2012 gid0 = getU16BE(pos, &parsedOk);
2013 pos += 2;
2014 for (i = 1; i <= nRanges; ++i) {
2015 fd = getU8(pos++, &parsedOk);
2016 gid1 = getU16BE(pos, &parsedOk);
2017 if (!parsedOk) {
2018 return;
2020 pos += 2;
2021 if (gid0 > gid1 || gid1 > nGlyphs) {
2022 //~ error(-1, "Bad FDSelect table in CID font");
2023 parsedOk = gFalse;
2024 return;
2026 for (j = gid0; j < gid1; ++j) {
2027 fdSelect[j] = fd;
2029 gid0 = gid1;
2031 } else {
2032 //~ error(-1, "Unknown FDSelect table format in CID font");
2033 for (i = 0; i < nGlyphs; ++i) {
2034 fdSelect[i] = 0;
2040 void FoFiType1C::buildEncoding() {
2041 char buf[256];
2042 int nCodes, nRanges, encFormat;
2043 int pos, c, sid, nLeft, nSups, i, j;
2045 if (topDict.encodingOffset == 0) {
2046 encoding = fofiType1StandardEncoding;
2048 } else if (topDict.encodingOffset == 1) {
2049 encoding = fofiType1ExpertEncoding;
2051 } else {
2052 encoding = (char **)gmalloc(256 * sizeof(char *));
2053 for (i = 0; i < 256; ++i) {
2054 encoding[i] = NULL;
2056 pos = topDict.encodingOffset;
2057 encFormat = getU8(pos++, &parsedOk);
2058 if (!parsedOk) {
2059 return;
2061 if ((encFormat & 0x7f) == 0) {
2062 nCodes = 1 + getU8(pos++, &parsedOk);
2063 if (!parsedOk) {
2064 return;
2066 if (nCodes > nGlyphs) {
2067 nCodes = nGlyphs;
2069 for (i = 1; i < nCodes; ++i) {
2070 c = getU8(pos++, &parsedOk);
2071 if (!parsedOk) {
2072 return;
2074 if (encoding[c]) {
2075 gfree(encoding[c]);
2077 encoding[c] = copyString(getString(charset[i], buf, &parsedOk));
2079 } else if ((encFormat & 0x7f) == 1) {
2080 nRanges = getU8(pos++, &parsedOk);
2081 if (!parsedOk) {
2082 return;
2084 nCodes = 1;
2085 for (i = 0; i < nRanges; ++i) {
2086 c = getU8(pos++, &parsedOk);
2087 nLeft = getU8(pos++, &parsedOk);
2088 if (!parsedOk) {
2089 return;
2091 for (j = 0; j <= nLeft && nCodes < nGlyphs; ++j) {
2092 if (c < 256) {
2093 if (encoding[c]) {
2094 gfree(encoding[c]);
2096 encoding[c] = copyString(getString(charset[nCodes], buf,
2097 &parsedOk));
2099 ++nCodes;
2100 ++c;
2104 if (encFormat & 0x80) {
2105 nSups = getU8(pos++, &parsedOk);
2106 if (!parsedOk) {
2107 return;
2109 for (i = 0; i < nSups; ++i) {
2110 c = getU8(pos++, &parsedOk);;
2111 if (!parsedOk) {
2112 return;;
2114 sid = getU16BE(pos, &parsedOk);
2115 pos += 2;
2116 if (!parsedOk) {
2117 return;
2119 if (encoding[c]) {
2120 gfree(encoding[c]);
2122 encoding[c] = copyString(getString(sid, buf, &parsedOk));
2128 GBool FoFiType1C::readCharset() {
2129 int charsetFormat, c, pos;
2130 int nLeft, i, j;
2132 if (topDict.charsetOffset == 0) {
2133 charset = fofiType1CISOAdobeCharset;
2134 } else if (topDict.charsetOffset == 1) {
2135 charset = fofiType1CExpertCharset;
2136 } else if (topDict.charsetOffset == 2) {
2137 charset = fofiType1CExpertSubsetCharset;
2138 } else {
2139 charset = (Gushort *)gmalloc(nGlyphs * sizeof(Gushort));
2140 for (i = 0; i < nGlyphs; ++i) {
2141 charset[i] = 0;
2143 pos = topDict.charsetOffset;
2144 charsetFormat = getU8(pos++, &parsedOk);
2145 if (charsetFormat == 0) {
2146 for (i = 1; i < nGlyphs; ++i) {
2147 charset[i] = (Gushort)getU16BE(pos, &parsedOk);
2148 pos += 2;
2149 if (!parsedOk) {
2150 break;
2153 } else if (charsetFormat == 1) {
2154 i = 1;
2155 while (i < nGlyphs) {
2156 c = getU16BE(pos, &parsedOk);
2157 pos += 2;
2158 nLeft = getU8(pos++, &parsedOk);
2159 if (!parsedOk) {
2160 break;
2162 for (j = 0; j <= nLeft && i < nGlyphs; ++j) {
2163 charset[i++] = (Gushort)c++;
2166 } else if (charsetFormat == 2) {
2167 i = 1;
2168 while (i < nGlyphs) {
2169 c = getU16BE(pos, &parsedOk);
2170 pos += 2;
2171 nLeft = getU16BE(pos, &parsedOk);
2172 pos += 2;
2173 if (!parsedOk) {
2174 break;
2176 for (j = 0; j <= nLeft && i < nGlyphs; ++j) {
2177 charset[i++] = (Gushort)c++;
2181 if (!parsedOk) {
2182 gfree(charset);
2183 charset = NULL;
2184 return gFalse;
2187 return gTrue;
2190 int FoFiType1C::getOp(int pos, GBool charstring, GBool *ok) {
2191 static char nybChars[16] = "0123456789.ee -";
2192 Type1COp op;
2193 char buf[65];
2194 int b0, b1, nyb0, nyb1, x, i;
2196 b0 = getU8(pos++, ok);
2197 op.isNum = gTrue;
2198 op.isFP = gFalse;
2200 if (b0 == 28) {
2201 x = getU8(pos++, ok);
2202 x = (x << 8) | getU8(pos++, ok);
2203 if (x & 0x8000) {
2204 x |= ~0xffff;
2206 op.num = x;
2208 } else if (!charstring && b0 == 29) {
2209 x = getU8(pos++, ok);
2210 x = (x << 8) | getU8(pos++, ok);
2211 x = (x << 8) | getU8(pos++, ok);
2212 x = (x << 8) | getU8(pos++, ok);
2213 if (x & 0x80000000) {
2214 x |= ~0xffffffff;
2216 op.num = x;
2218 } else if (!charstring && b0 == 30) {
2219 i = 0;
2220 do {
2221 b1 = getU8(pos++, ok);
2222 nyb0 = b1 >> 4;
2223 nyb1 = b1 & 0x0f;
2224 if (nyb0 == 0xf) {
2225 break;
2227 buf[i++] = nybChars[nyb0];
2228 if (i == 64) {
2229 break;
2231 if (nyb0 == 0xc) {
2232 buf[i++] = '-';
2234 if (i == 64) {
2235 break;
2237 if (nyb1 == 0xf) {
2238 break;
2240 buf[i++] = nybChars[nyb1];
2241 if (i == 64) {
2242 break;
2244 if (nyb1 == 0xc) {
2245 buf[i++] = '-';
2247 } while (i < 64);
2248 buf[i] = '\0';
2249 op.num = atof(buf);
2250 op.isFP = gTrue;
2252 } else if (b0 >= 32 && b0 <= 246) {
2253 op.num = b0 - 139;
2255 } else if (b0 >= 247 && b0 <= 250) {
2256 op.num = ((b0 - 247) << 8) + getU8(pos++, ok) + 108;
2258 } else if (b0 >= 251 && b0 <= 254) {
2259 op.num = -((b0 - 251) << 8) - getU8(pos++, ok) - 108;
2261 } else if (charstring && b0 == 255) {
2262 x = getU8(pos++, ok);
2263 x = (x << 8) | getU8(pos++, ok);
2264 x = (x << 8) | getU8(pos++, ok);
2265 x = (x << 8) | getU8(pos++, ok);
2266 if (x & 0x80000000) {
2267 x |= ~0xffffffff;
2269 op.num = (double)x / 65536.0;
2270 op.isFP = gTrue;
2272 } else if (b0 == 12) {
2273 op.isNum = gFalse;
2274 op.op = 0x0c00 + getU8(pos++, ok);
2276 } else {
2277 op.isNum = gFalse;
2278 op.op = b0;
2281 if (nOps < 49) {
2282 ops[nOps++] = op;
2285 return pos;
2288 // Convert the delta-encoded ops array to an array of ints.
2289 int FoFiType1C::getDeltaIntArray(int *arr, int maxLen) {
2290 int x;
2291 int n, i;
2293 if ((n = nOps) > maxLen) {
2294 n = maxLen;
2296 x = 0;
2297 for (i = 0; i < n; ++i) {
2298 x += (int)ops[i].num;
2299 arr[i] = x;
2301 return n;
2304 // Convert the delta-encoded ops array to an array of doubles.
2305 int FoFiType1C::getDeltaFPArray(double *arr, int maxLen) {
2306 double x;
2307 int n, i;
2309 if ((n = nOps) > maxLen) {
2310 n = maxLen;
2312 x = 0;
2313 for (i = 0; i < n; ++i) {
2314 x += ops[i].num;
2315 arr[i] = x;
2317 return n;
2320 void FoFiType1C::getIndex(int pos, Type1CIndex *idx, GBool *ok) {
2321 idx->pos = pos;
2322 idx->len = getU16BE(pos, ok);
2323 if (idx->len == 0) {
2324 // empty indexes are legal
2325 idx->offSize = 0;
2326 idx->startPos = idx->endPos = 0;
2327 } else {
2328 idx->offSize = getU8(pos + 2, ok);
2329 if (idx->offSize < 1 || idx->offSize > 4) {
2330 *ok = gFalse;
2332 idx->startPos = pos + 3 + (idx->len + 1) * idx->offSize - 1;
2333 if (idx->startPos < 0 || idx->startPos >= len) {
2334 *ok = gFalse;
2336 idx->endPos = idx->startPos + getUVarBE(pos + 3 + idx->len * idx->offSize,
2337 idx->offSize, ok);
2338 if (idx->endPos < idx->startPos || idx->endPos > len) {
2339 *ok = gFalse;
2344 void FoFiType1C::getIndexVal(Type1CIndex *idx, int i,
2345 Type1CIndexVal *val, GBool *ok) {
2346 int pos0, pos1;
2348 if (i < 0 || i >= idx->len) {
2349 *ok = gFalse;
2350 return;
2352 pos0 = idx->startPos + getUVarBE(idx->pos + 3 + i * idx->offSize,
2353 idx->offSize, ok);
2354 pos1 = idx->startPos + getUVarBE(idx->pos + 3 + (i + 1) * idx->offSize,
2355 idx->offSize, ok);
2356 if (pos0 < idx->startPos || pos0 >= idx->endPos ||
2357 pos1 <= idx->startPos || pos1 > idx->endPos ||
2358 pos1 < pos0) {
2359 *ok = gFalse;
2361 val->pos = pos0;
2362 val->len = pos1 - pos0;
2365 char *FoFiType1C::getString(int sid, char *buf, GBool *ok) {
2366 Type1CIndexVal val;
2367 int n;
2369 if (sid < 391) {
2370 strcpy(buf, fofiType1CStdStrings[sid]);
2371 } else {
2372 sid -= 391;
2373 getIndexVal(&stringIdx, sid, &val, ok);
2374 if (ok) {
2375 if ((n = val.len) > 255) {
2376 n = 255;
2378 strncpy(buf, (char *)&file[val.pos], n);
2379 buf[n] = '\0';
2380 } else {
2381 buf[0] = '\0';
2384 return buf;