fixed version of \pdftexversion on manual (thanks to David Carlisle)
[luatex.git] / source / libs / poppler / poppler-0.32.0 / fofi / FoFiType1C.cc
blobc4595a3260ea6a6dec85edee29b15853d43595b0
1 //========================================================================
2 //
3 // FoFiType1C.cc
4 //
5 // Copyright 1999-2003 Glyph & Cog, LLC
6 //
7 //========================================================================
9 //========================================================================
11 // Modified under the Poppler project - http://poppler.freedesktop.org
13 // All changes made under the Poppler project to this file are licensed
14 // under GPL version 2 or later
16 // Copyright (C) 2009, 2010 Albert Astals Cid <aacid@kde.org>
17 // Copyright (C) 2012 Thomas Freitag <Thomas.Freitag@alfa.de>
19 // To see a description of the changes please see the Changelog file that
20 // came with your tarball or type make ChangeLog if you are building from git
22 //========================================================================
24 #include <config.h>
26 #ifdef USE_GCC_PRAGMAS
27 #pragma implementation
28 #endif
30 #include <stdlib.h>
31 #include <string.h>
32 #include <math.h>
33 #include "goo/gmem.h"
34 #include "goo/gstrtod.h"
35 #include "goo/GooString.h"
36 #include "FoFiEncodings.h"
37 #include "FoFiType1C.h"
39 //------------------------------------------------------------------------
41 static char hexChars[17] = "0123456789ABCDEF";
43 //------------------------------------------------------------------------
44 // FoFiType1C
45 //------------------------------------------------------------------------
47 FoFiType1C *FoFiType1C::make(char *fileA, int lenA) {
48 FoFiType1C *ff;
50 ff = new FoFiType1C(fileA, lenA, gFalse);
51 if (!ff->parse()) {
52 delete ff;
53 return NULL;
55 return ff;
58 FoFiType1C *FoFiType1C::load(char *fileName) {
59 FoFiType1C *ff;
60 char *fileA;
61 int lenA;
63 if (!(fileA = FoFiBase::readFile(fileName, &lenA))) {
64 return NULL;
66 ff = new FoFiType1C(fileA, lenA, gTrue);
67 if (!ff->parse()) {
68 delete ff;
69 return NULL;
71 return ff;
74 FoFiType1C::FoFiType1C(char *fileA, int lenA, GBool freeFileDataA):
75 FoFiBase(fileA, lenA, freeFileDataA)
77 name = NULL;
78 encoding = NULL;
79 privateDicts = NULL;
80 fdSelect = NULL;
81 charset = NULL;
82 charsetLength = 0;
85 FoFiType1C::~FoFiType1C() {
86 int i;
88 if (name) {
89 delete name;
91 if (encoding &&
92 encoding != fofiType1StandardEncoding &&
93 encoding != fofiType1ExpertEncoding) {
94 for (i = 0; i < 256; ++i) {
95 gfree(encoding[i]);
97 gfree(encoding);
99 if (privateDicts) {
100 gfree(privateDicts);
102 if (fdSelect) {
103 gfree(fdSelect);
105 if (charset &&
106 charset != fofiType1CISOAdobeCharset &&
107 charset != fofiType1CExpertCharset &&
108 charset != fofiType1CExpertSubsetCharset) {
109 gfree(charset);
113 char *FoFiType1C::getName() {
114 return name ? name->getCString() : (char *)NULL;
117 char **FoFiType1C::getEncoding() {
118 return encoding;
121 GooString *FoFiType1C::getGlyphName(int gid) {
122 char buf[256];
123 GBool ok;
125 ok = gTrue;
126 if (gid < 0 || gid >= charsetLength)
127 return NULL;
128 getString(charset[gid], buf, &ok);
129 if (!ok) {
130 return NULL;
132 return new GooString(buf);
135 int *FoFiType1C::getCIDToGIDMap(int *nCIDs) {
136 int *map;
137 int n, i;
139 // a CID font's top dict has ROS as the first operator
140 if (topDict.firstOp != 0x0c1e) {
141 *nCIDs = 0;
142 return NULL;
145 // in a CID font, the charset data is the GID-to-CID mapping, so all
146 // we have to do is reverse it
147 n = 0;
148 for (i = 0; i < nGlyphs && i < charsetLength; ++i) {
149 if (charset[i] > n) {
150 n = charset[i];
153 ++n;
154 map = (int *)gmallocn(n, sizeof(int));
155 memset(map, 0, n * sizeof(int));
156 for (i = 0; i < nGlyphs; ++i) {
157 map[charset[i]] = i;
159 *nCIDs = n;
160 return map;
163 void FoFiType1C::getFontMatrix(double *mat) {
164 int i;
166 if (topDict.firstOp == 0x0c1e && privateDicts[0].hasFontMatrix) {
167 if (topDict.hasFontMatrix) {
168 mat[0] = topDict.fontMatrix[0] * privateDicts[0].fontMatrix[0] +
169 topDict.fontMatrix[1] * privateDicts[0].fontMatrix[2];
170 mat[1] = topDict.fontMatrix[0] * privateDicts[0].fontMatrix[1] +
171 topDict.fontMatrix[1] * privateDicts[0].fontMatrix[3];
172 mat[2] = topDict.fontMatrix[2] * privateDicts[0].fontMatrix[0] +
173 topDict.fontMatrix[3] * privateDicts[0].fontMatrix[2];
174 mat[3] = topDict.fontMatrix[2] * privateDicts[0].fontMatrix[1] +
175 topDict.fontMatrix[3] * privateDicts[0].fontMatrix[3];
176 mat[4] = topDict.fontMatrix[4] * privateDicts[0].fontMatrix[0] +
177 topDict.fontMatrix[5] * privateDicts[0].fontMatrix[2];
178 mat[5] = topDict.fontMatrix[4] * privateDicts[0].fontMatrix[1] +
179 topDict.fontMatrix[5] * privateDicts[0].fontMatrix[3];
180 } else {
181 for (i = 0; i < 6; ++i) {
182 mat[i] = privateDicts[0].fontMatrix[i];
185 } else {
186 for (i = 0; i < 6; ++i) {
187 mat[i] = topDict.fontMatrix[i];
192 void FoFiType1C::convertToType1(char *psName, const char **newEncoding, GBool ascii,
193 FoFiOutputFunc outputFunc,
194 void *outputStream) {
195 int psNameLen;
196 Type1CEexecBuf eb;
197 Type1CIndex subrIdx;
198 Type1CIndexVal val;
199 GooString *buf;
200 char buf2[256];
201 const char **enc;
202 GBool ok;
203 int i;
205 if (psName) {
206 psNameLen = strlen(psName);
207 } else {
208 psName = name->getCString();
209 psNameLen = name->getLength();
212 // write header and font dictionary, up to encoding
213 ok = gTrue;
214 (*outputFunc)(outputStream, "%!FontType1-1.0: ", 17);
215 (*outputFunc)(outputStream, psName, psNameLen);
216 if (topDict.versionSID != 0) {
217 getString(topDict.versionSID, buf2, &ok);
218 (*outputFunc)(outputStream, buf2, strlen(buf2));
220 (*outputFunc)(outputStream, "\n", 1);
221 // the dictionary needs room for 12 entries: the following 9, plus
222 // Private and CharStrings (in the eexec section) and FID (which is
223 // added by definefont)
224 (*outputFunc)(outputStream, "12 dict begin\n", 14);
225 (*outputFunc)(outputStream, "/FontInfo 10 dict dup begin\n", 28);
226 if (topDict.versionSID != 0) {
227 (*outputFunc)(outputStream, "/version ", 9);
228 writePSString(buf2, outputFunc, outputStream);
229 (*outputFunc)(outputStream, " readonly def\n", 14);
231 if (topDict.noticeSID != 0) {
232 getString(topDict.noticeSID, buf2, &ok);
233 (*outputFunc)(outputStream, "/Notice ", 8);
234 writePSString(buf2, outputFunc, outputStream);
235 (*outputFunc)(outputStream, " readonly def\n", 14);
237 if (topDict.copyrightSID != 0) {
238 getString(topDict.copyrightSID, buf2, &ok);
239 (*outputFunc)(outputStream, "/Copyright ", 11);
240 writePSString(buf2, outputFunc, outputStream);
241 (*outputFunc)(outputStream, " readonly def\n", 14);
243 if (topDict.fullNameSID != 0) {
244 getString(topDict.fullNameSID, buf2, &ok);
245 (*outputFunc)(outputStream, "/FullName ", 10);
246 writePSString(buf2, outputFunc, outputStream);
247 (*outputFunc)(outputStream, " readonly def\n", 14);
249 if (topDict.familyNameSID != 0) {
250 getString(topDict.familyNameSID, buf2, &ok);
251 (*outputFunc)(outputStream, "/FamilyName ", 12);
252 writePSString(buf2, outputFunc, outputStream);
253 (*outputFunc)(outputStream, " readonly def\n", 14);
255 if (topDict.weightSID != 0) {
256 getString(topDict.weightSID, buf2, &ok);
257 (*outputFunc)(outputStream, "/Weight ", 8);
258 writePSString(buf2, outputFunc, outputStream);
259 (*outputFunc)(outputStream, " readonly def\n", 14);
261 if (topDict.isFixedPitch) {
262 (*outputFunc)(outputStream, "/isFixedPitch true def\n", 23);
263 } else {
264 (*outputFunc)(outputStream, "/isFixedPitch false def\n", 24);
266 buf = GooString::format("/ItalicAngle {0:.4g} def\n", topDict.italicAngle);
267 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
268 delete buf;
269 buf = GooString::format("/UnderlinePosition {0:.4g} def\n",
270 topDict.underlinePosition);
271 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
272 delete buf;
273 buf = GooString::format("/UnderlineThickness {0:.4g} def\n",
274 topDict.underlineThickness);
275 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
276 delete buf;
277 (*outputFunc)(outputStream, "end readonly def\n", 17);
278 (*outputFunc)(outputStream, "/FontName /", 11);
279 (*outputFunc)(outputStream, psName, psNameLen);
280 (*outputFunc)(outputStream, " def\n", 5);
281 buf = GooString::format("/PaintType {0:d} def\n", topDict.paintType);
282 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
283 delete buf;
284 (*outputFunc)(outputStream, "/FontType 1 def\n", 16);
285 buf = GooString::format("/FontMatrix [{0:.8g} {1:.8g} {2:.8g} {3:.8g} {4:.8g} {5:.8g}] readonly def\n",
286 topDict.fontMatrix[0], topDict.fontMatrix[1],
287 topDict.fontMatrix[2], topDict.fontMatrix[3],
288 topDict.fontMatrix[4], topDict.fontMatrix[5]);
289 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
290 delete buf;
291 buf = GooString::format("/FontBBox [{0:.4g} {1:.4g} {2:.4g} {3:.4g}] readonly def\n",
292 topDict.fontBBox[0], topDict.fontBBox[1],
293 topDict.fontBBox[2], topDict.fontBBox[3]);
294 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
295 delete buf;
296 buf = GooString::format("/StrokeWidth {0:.4g} def\n", topDict.strokeWidth);
297 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
298 delete buf;
299 if (topDict.uniqueID != 0) {
300 buf = GooString::format("/UniqueID {0:d} def\n", topDict.uniqueID);
301 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
302 delete buf;
305 // write the encoding
306 (*outputFunc)(outputStream, "/Encoding ", 10);
307 if (!newEncoding && encoding == fofiType1StandardEncoding) {
308 (*outputFunc)(outputStream, "StandardEncoding def\n", 21);
309 } else {
310 (*outputFunc)(outputStream, "256 array\n", 10);
311 (*outputFunc)(outputStream,
312 "0 1 255 {1 index exch /.notdef put} for\n", 40);
313 enc = newEncoding ? newEncoding : (const char **)encoding;
314 for (i = 0; i < 256; ++i) {
315 if (enc[i]) {
316 buf = GooString::format("dup {0:d} /{1:s} put\n", i, enc[i]);
317 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
318 delete buf;
321 (*outputFunc)(outputStream, "readonly def\n", 13);
323 (*outputFunc)(outputStream, "currentdict end\n", 16);
325 // start the binary section
326 (*outputFunc)(outputStream, "currentfile eexec\n", 18);
327 eb.outputFunc = outputFunc;
328 eb.outputStream = outputStream;
329 eb.ascii = ascii;
330 eb.r1 = 55665;
331 eb.line = 0;
333 // write the private dictionary
334 eexecWrite(&eb, "\x83\xca\x73\xd5");
335 eexecWrite(&eb, "dup /Private 32 dict dup begin\n");
336 eexecWrite(&eb, "/RD {string currentfile exch readstring pop}"
337 " executeonly def\n");
338 eexecWrite(&eb, "/ND {noaccess def} executeonly def\n");
339 eexecWrite(&eb, "/NP {noaccess put} executeonly def\n");
340 eexecWrite(&eb, "/MinFeature {16 16} def\n");
341 eexecWrite(&eb, "/password 5839 def\n");
342 if (privateDicts[0].nBlueValues) {
343 eexecWrite(&eb, "/BlueValues [");
344 for (i = 0; i < privateDicts[0].nBlueValues; ++i) {
345 buf = GooString::format("{0:s}{1:d}",
346 i > 0 ? " " : "", privateDicts[0].blueValues[i]);
347 eexecWrite(&eb, buf->getCString());
348 delete buf;
350 eexecWrite(&eb, "] def\n");
352 if (privateDicts[0].nOtherBlues) {
353 eexecWrite(&eb, "/OtherBlues [");
354 for (i = 0; i < privateDicts[0].nOtherBlues; ++i) {
355 buf = GooString::format("{0:s}{1:d}",
356 i > 0 ? " " : "", privateDicts[0].otherBlues[i]);
357 eexecWrite(&eb, buf->getCString());
358 delete buf;
360 eexecWrite(&eb, "] def\n");
362 if (privateDicts[0].nFamilyBlues) {
363 eexecWrite(&eb, "/FamilyBlues [");
364 for (i = 0; i < privateDicts[0].nFamilyBlues; ++i) {
365 buf = GooString::format("{0:s}{1:d}",
366 i > 0 ? " " : "", privateDicts[0].familyBlues[i]);
367 eexecWrite(&eb, buf->getCString());
368 delete buf;
370 eexecWrite(&eb, "] def\n");
372 if (privateDicts[0].nFamilyOtherBlues) {
373 eexecWrite(&eb, "/FamilyOtherBlues [");
374 for (i = 0; i < privateDicts[0].nFamilyOtherBlues; ++i) {
375 buf = GooString::format("{0:s}{1:d}", i > 0 ? " " : "",
376 privateDicts[0].familyOtherBlues[i]);
377 eexecWrite(&eb, buf->getCString());
378 delete buf;
380 eexecWrite(&eb, "] def\n");
382 if (privateDicts[0].blueScale != 0.039625) {
383 buf = GooString::format("/BlueScale {0:.4g} def\n",
384 privateDicts[0].blueScale);
385 eexecWrite(&eb, buf->getCString());
386 delete buf;
388 if (privateDicts[0].blueShift != 7) {
389 buf = GooString::format("/BlueShift {0:d} def\n", privateDicts[0].blueShift);
390 eexecWrite(&eb, buf->getCString());
391 delete buf;
393 if (privateDicts[0].blueFuzz != 1) {
394 buf = GooString::format("/BlueFuzz {0:d} def\n", privateDicts[0].blueFuzz);
395 eexecWrite(&eb, buf->getCString());
396 delete buf;
398 if (privateDicts[0].hasStdHW) {
399 buf = GooString::format("/StdHW [{0:.4g}] def\n", privateDicts[0].stdHW);
400 eexecWrite(&eb, buf->getCString());
401 delete buf;
403 if (privateDicts[0].hasStdVW) {
404 buf = GooString::format("/StdVW [{0:.4g}] def\n", privateDicts[0].stdVW);
405 eexecWrite(&eb, buf->getCString());
406 delete buf;
408 if (privateDicts[0].nStemSnapH) {
409 eexecWrite(&eb, "/StemSnapH [");
410 for (i = 0; i < privateDicts[0].nStemSnapH; ++i) {
411 buf = GooString::format("{0:s}{1:.4g}",
412 i > 0 ? " " : "", privateDicts[0].stemSnapH[i]);
413 eexecWrite(&eb, buf->getCString());
414 delete buf;
416 eexecWrite(&eb, "] def\n");
418 if (privateDicts[0].nStemSnapV) {
419 eexecWrite(&eb, "/StemSnapV [");
420 for (i = 0; i < privateDicts[0].nStemSnapV; ++i) {
421 buf = GooString::format("{0:s}{1:.4g}",
422 i > 0 ? " " : "", privateDicts[0].stemSnapV[i]);
423 eexecWrite(&eb, buf->getCString());
424 delete buf;
426 eexecWrite(&eb, "] def\n");
428 if (privateDicts[0].hasForceBold) {
429 buf = GooString::format("/ForceBold {0:s} def\n",
430 privateDicts[0].forceBold ? "true" : "false");
431 eexecWrite(&eb, buf->getCString());
432 delete buf;
434 if (privateDicts[0].forceBoldThreshold != 0) {
435 buf = GooString::format("/ForceBoldThreshold {0:.4g} def\n",
436 privateDicts[0].forceBoldThreshold);
437 eexecWrite(&eb, buf->getCString());
438 delete buf;
440 if (privateDicts[0].languageGroup != 0) {
441 buf = GooString::format("/LanguageGroup {0:d} def\n",
442 privateDicts[0].languageGroup);
443 eexecWrite(&eb, buf->getCString());
444 delete buf;
446 if (privateDicts[0].expansionFactor != 0.06) {
447 buf = GooString::format("/ExpansionFactor {0:.4g} def\n",
448 privateDicts[0].expansionFactor);
449 eexecWrite(&eb, buf->getCString());
450 delete buf;
453 // set up subroutines
454 ok = gTrue;
455 getIndex(privateDicts[0].subrsOffset, &subrIdx, &ok);
456 if (!ok) {
457 subrIdx.pos = -1;
460 // write the CharStrings
461 buf = GooString::format("2 index /CharStrings {0:d} dict dup begin\n",
462 nGlyphs);
463 eexecWrite(&eb, buf->getCString());
464 delete buf;
465 for (i = 0; i < nGlyphs; ++i) {
466 ok = gTrue;
467 getIndexVal(&charStringsIdx, i, &val, &ok);
468 if (ok && i < charsetLength) {
469 getString(charset[i], buf2, &ok);
470 if (ok) {
471 eexecCvtGlyph(&eb, buf2, val.pos, val.len, &subrIdx, &privateDicts[0]);
475 eexecWrite(&eb, "end\n");
476 eexecWrite(&eb, "end\n");
477 eexecWrite(&eb, "readonly put\n");
478 eexecWrite(&eb, "noaccess put\n");
479 eexecWrite(&eb, "dup /FontName get exch definefont pop\n");
480 eexecWrite(&eb, "mark currentfile closefile\n");
482 // trailer
483 if (ascii && eb.line > 0) {
484 (*outputFunc)(outputStream, "\n", 1);
486 for (i = 0; i < 8; ++i) {
487 (*outputFunc)(outputStream, "0000000000000000000000000000000000000000000000000000000000000000\n", 65);
489 (*outputFunc)(outputStream, "cleartomark\n", 12);
492 void FoFiType1C::convertToCIDType0(char *psName, int *codeMap, int nCodes,
493 FoFiOutputFunc outputFunc,
494 void *outputStream) {
495 int *cidMap;
496 GooString *charStrings;
497 int *charStringOffsets;
498 Type1CIndex subrIdx;
499 Type1CIndexVal val;
500 int nCIDs, gdBytes;
501 GooString *buf;
502 char buf2[256];
503 GBool ok;
504 int gid, offset, n, i, j, k;
506 // compute the CID count and build the CID-to-GID mapping
507 if (codeMap) {
508 nCIDs = nCodes;
509 cidMap = (int *)gmallocn(nCIDs, sizeof(int));
510 for (i = 0; i < nCodes; ++i) {
511 if (codeMap[i] >= 0 && codeMap[i] < nGlyphs) {
512 cidMap[i] = codeMap[i];
513 } else {
514 cidMap[i] = -1;
517 } else if (topDict.firstOp == 0x0c1e) {
518 nCIDs = 0;
519 for (i = 0; i < nGlyphs && i < charsetLength; ++i) {
520 if (charset[i] >= nCIDs) {
521 nCIDs = charset[i] + 1;
524 cidMap = (int *)gmallocn(nCIDs, sizeof(int));
525 for (i = 0; i < nCIDs; ++i) {
526 cidMap[i] = -1;
528 for (i = 0; i < nGlyphs && i < charsetLength; ++i) {
529 cidMap[charset[i]] = i;
531 } else {
532 nCIDs = nGlyphs;
533 cidMap = (int *)gmallocn(nCIDs, sizeof(int));
534 for (i = 0; i < nCIDs; ++i) {
535 cidMap[i] = i;
539 // build the charstrings
540 charStrings = new GooString();
541 charStringOffsets = (int *)gmallocn(nCIDs + 1, sizeof(int));
542 for (i = 0; i < nCIDs; ++i) {
543 charStringOffsets[i] = charStrings->getLength();
544 if ((gid = cidMap[i]) >= 0) {
545 ok = gTrue;
546 getIndexVal(&charStringsIdx, gid, &val, &ok);
547 if (ok) {
548 getIndex(privateDicts[fdSelect ? fdSelect[gid] : 0].subrsOffset,
549 &subrIdx, &ok);
550 if (!ok) {
551 subrIdx.pos = -1;
553 cvtGlyph(val.pos, val.len, charStrings,
554 &subrIdx, &privateDicts[fdSelect ? fdSelect[gid] : 0], gTrue);
558 charStringOffsets[nCIDs] = charStrings->getLength();
560 // compute gdBytes = number of bytes needed for charstring offsets
561 // (offset size needs to account for the charstring offset table,
562 // with a worst case of five bytes per entry, plus the charstrings
563 // themselves)
564 i = (nCIDs + 1) * 5 + charStrings->getLength();
565 if (i < 0x100) {
566 gdBytes = 1;
567 } else if (i < 0x10000) {
568 gdBytes = 2;
569 } else if (i < 0x1000000) {
570 gdBytes = 3;
571 } else {
572 gdBytes = 4;
575 // begin the font dictionary
576 (*outputFunc)(outputStream, "/CIDInit /ProcSet findresource begin\n", 37);
577 (*outputFunc)(outputStream, "20 dict begin\n", 14);
578 (*outputFunc)(outputStream, "/CIDFontName /", 14);
579 (*outputFunc)(outputStream, psName, strlen(psName));
580 (*outputFunc)(outputStream, " def\n", 5);
581 (*outputFunc)(outputStream, "/CIDFontType 0 def\n", 19);
582 (*outputFunc)(outputStream, "/CIDSystemInfo 3 dict dup begin\n", 32);
583 if (topDict.registrySID > 0 && topDict.orderingSID > 0) {
584 ok = gTrue;
585 getString(topDict.registrySID, buf2, &ok);
586 if (ok) {
587 (*outputFunc)(outputStream, " /Registry (", 13);
588 (*outputFunc)(outputStream, buf2, strlen(buf2));
589 (*outputFunc)(outputStream, ") def\n", 6);
591 ok = gTrue;
592 getString(topDict.orderingSID, buf2, &ok);
593 if (ok) {
594 (*outputFunc)(outputStream, " /Ordering (", 13);
595 (*outputFunc)(outputStream, buf2, strlen(buf2));
596 (*outputFunc)(outputStream, ") def\n", 6);
598 } else {
599 (*outputFunc)(outputStream, " /Registry (Adobe) def\n", 24);
600 (*outputFunc)(outputStream, " /Ordering (Identity) def\n", 27);
602 buf = GooString::format(" /Supplement {0:d} def\n", topDict.supplement);
603 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
604 delete buf;
605 (*outputFunc)(outputStream, "end def\n", 8);
606 if (topDict.hasFontMatrix) {
607 buf = GooString::format("/FontMatrix [{0:.8g} {1:.8g} {2:.8g} {3:.8g} {4:.8g} {5:.8g}] def\n",
608 topDict.fontMatrix[0], topDict.fontMatrix[1],
609 topDict.fontMatrix[2], topDict.fontMatrix[3],
610 topDict.fontMatrix[4], topDict.fontMatrix[5]);
611 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
612 delete buf;
613 } else if (privateDicts[0].hasFontMatrix) {
614 (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
615 } else {
616 (*outputFunc)(outputStream,
617 "/FontMatrix [0.001 0 0 0.001 0 0] def\n", 38);
619 buf = GooString::format("/FontBBox [{0:.4g} {1:.4g} {2:.4g} {3:.4g}] def\n",
620 topDict.fontBBox[0], topDict.fontBBox[1],
621 topDict.fontBBox[2], topDict.fontBBox[3]);
622 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
623 delete buf;
624 (*outputFunc)(outputStream, "/FontInfo 1 dict dup begin\n", 27);
625 (*outputFunc)(outputStream, " /FSType 8 def\n", 16);
626 (*outputFunc)(outputStream, "end def\n", 8);
628 // CIDFont-specific entries
629 buf = GooString::format("/CIDCount {0:d} def\n", nCIDs);
630 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
631 delete buf;
632 (*outputFunc)(outputStream, "/FDBytes 1 def\n", 15);
633 buf = GooString::format("/GDBytes {0:d} def\n", gdBytes);
634 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
635 delete buf;
636 (*outputFunc)(outputStream, "/CIDMapOffset 0 def\n", 20);
637 if (topDict.paintType != 0) {
638 buf = GooString::format("/PaintType {0:d} def\n", topDict.paintType);
639 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
640 delete buf;
641 buf = GooString::format("/StrokeWidth {0:.4g} def\n", topDict.strokeWidth);
642 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
643 delete buf;
646 // FDArray entry
647 buf = GooString::format("/FDArray {0:d} array\n", nFDs);
648 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
649 delete buf;
650 for (i = 0; i < nFDs; ++i) {
651 buf = GooString::format("dup {0:d} 10 dict begin\n", i);
652 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
653 delete buf;
654 (*outputFunc)(outputStream, "/FontType 1 def\n", 16);
655 if (privateDicts[i].hasFontMatrix) {
656 buf = GooString::format("/FontMatrix [{0:.8g} {1:.8g} {2:.8g} {3:.8g} {4:.8g} {5:.8g}] def\n",
657 privateDicts[i].fontMatrix[0],
658 privateDicts[i].fontMatrix[1],
659 privateDicts[i].fontMatrix[2],
660 privateDicts[i].fontMatrix[3],
661 privateDicts[i].fontMatrix[4],
662 privateDicts[i].fontMatrix[5]);
663 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
664 delete buf;
665 } else {
666 (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
668 buf = GooString::format("/PaintType {0:d} def\n", topDict.paintType);
669 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
670 delete buf;
671 (*outputFunc)(outputStream, "/Private 32 dict begin\n", 23);
672 if (privateDicts[i].nBlueValues) {
673 (*outputFunc)(outputStream, "/BlueValues [", 13);
674 for (j = 0; j < privateDicts[i].nBlueValues; ++j) {
675 buf = GooString::format("{0:s}{1:d}",
676 j > 0 ? " " : "", privateDicts[i].blueValues[j]);
677 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
678 delete buf;
680 (*outputFunc)(outputStream, "] def\n", 6);
682 if (privateDicts[i].nOtherBlues) {
683 (*outputFunc)(outputStream, "/OtherBlues [", 13);
684 for (j = 0; j < privateDicts[i].nOtherBlues; ++j) {
685 buf = GooString::format("{0:s}{1:d}",
686 j > 0 ? " " : "", privateDicts[i].otherBlues[j]);
687 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
688 delete buf;
690 (*outputFunc)(outputStream, "] def\n", 6);
692 if (privateDicts[i].nFamilyBlues) {
693 (*outputFunc)(outputStream, "/FamilyBlues [", 14);
694 for (j = 0; j < privateDicts[i].nFamilyBlues; ++j) {
695 buf = GooString::format("{0:s}{1:d}",
696 j > 0 ? " " : "",
697 privateDicts[i].familyBlues[j]);
698 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
699 delete buf;
701 (*outputFunc)(outputStream, "] def\n", 6);
703 if (privateDicts[i].nFamilyOtherBlues) {
704 (*outputFunc)(outputStream, "/FamilyOtherBlues [", 19);
705 for (j = 0; j < privateDicts[i].nFamilyOtherBlues; ++j) {
706 buf = GooString::format("{0:s}{1:d}", j > 0 ? " " : "",
707 privateDicts[i].familyOtherBlues[j]);
708 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
709 delete buf;
711 (*outputFunc)(outputStream, "] def\n", 6);
713 if (privateDicts[i].blueScale != 0.039625) {
714 buf = GooString::format("/BlueScale {0:.4g} def\n",
715 privateDicts[i].blueScale);
716 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
717 delete buf;
719 if (privateDicts[i].blueShift != 7) {
720 buf = GooString::format("/BlueShift {0:d} def\n",
721 privateDicts[i].blueShift);
722 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
723 delete buf;
725 if (privateDicts[i].blueFuzz != 1) {
726 buf = GooString::format("/BlueFuzz {0:d} def\n", privateDicts[i].blueFuzz);
727 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
728 delete buf;
730 if (privateDicts[i].hasStdHW) {
731 buf = GooString::format("/StdHW [{0:.4g}] def\n", privateDicts[i].stdHW);
732 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
733 delete buf;
735 if (privateDicts[i].hasStdVW) {
736 buf = GooString::format("/StdVW [{0:.4g}] def\n", privateDicts[i].stdVW);
737 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
738 delete buf;
740 if (privateDicts[i].nStemSnapH) {
741 (*outputFunc)(outputStream, "/StemSnapH [", 12);
742 for (j = 0; j < privateDicts[i].nStemSnapH; ++j) {
743 buf = GooString::format("{0:s}{1:.4g}",
744 j > 0 ? " " : "", privateDicts[i].stemSnapH[j]);
745 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
746 delete buf;
748 (*outputFunc)(outputStream, "] def\n", 6);
750 if (privateDicts[i].nStemSnapV) {
751 (*outputFunc)(outputStream, "/StemSnapV [", 12);
752 for (j = 0; j < privateDicts[i].nStemSnapV; ++j) {
753 buf = GooString::format("{0:s}{1:.4g}",
754 j > 0 ? " " : "", privateDicts[i].stemSnapV[j]);
755 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
756 delete buf;
758 (*outputFunc)(outputStream, "] def\n", 6);
760 if (privateDicts[i].hasForceBold) {
761 buf = GooString::format("/ForceBold {0:s} def\n",
762 privateDicts[i].forceBold ? "true" : "false");
763 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
764 delete buf;
766 if (privateDicts[i].forceBoldThreshold != 0) {
767 buf = GooString::format("/ForceBoldThreshold {0:.4g} def\n",
768 privateDicts[i].forceBoldThreshold);
769 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
770 delete buf;
772 if (privateDicts[i].languageGroup != 0) {
773 buf = GooString::format("/LanguageGroup {0:d} def\n",
774 privateDicts[i].languageGroup);
775 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
776 delete buf;
778 if (privateDicts[i].expansionFactor != 0.06) {
779 buf = GooString::format("/ExpansionFactor {0:.4g} def\n",
780 privateDicts[i].expansionFactor);
781 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
782 delete buf;
784 (*outputFunc)(outputStream, "currentdict end def\n", 20);
785 (*outputFunc)(outputStream, "currentdict end put\n", 20);
787 (*outputFunc)(outputStream, "def\n", 4);
789 // start the binary section
790 offset = (nCIDs + 1) * (1 + gdBytes);
791 buf = GooString::format("(Hex) {0:d} StartData\n",
792 offset + charStrings->getLength());
793 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
794 delete buf;
796 // write the charstring offset (CIDMap) table
797 for (i = 0; i <= nCIDs; i += 6) {
798 for (j = 0; j < 6 && i+j <= nCIDs; ++j) {
799 if (i+j < nCIDs && cidMap[i+j] >= 0 && fdSelect) {
800 buf2[0] = (char)fdSelect[cidMap[i+j]];
801 } else {
802 buf2[0] = (char)0;
804 n = offset + charStringOffsets[i+j];
805 for (k = gdBytes; k >= 1; --k) {
806 buf2[k] = (char)(n & 0xff);
807 n >>= 8;
809 for (k = 0; k <= gdBytes; ++k) {
810 buf = GooString::format("{0:02x}", buf2[k] & 0xff);
811 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
812 delete buf;
815 (*outputFunc)(outputStream, "\n", 1);
818 // write the charstring data
819 n = charStrings->getLength();
820 for (i = 0; i < n; i += 32) {
821 for (j = 0; j < 32 && i+j < n; ++j) {
822 buf = GooString::format("{0:02x}", charStrings->getChar(i+j) & 0xff);
823 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
824 delete buf;
826 if (i + 32 >= n) {
827 (*outputFunc)(outputStream, ">", 1);
829 (*outputFunc)(outputStream, "\n", 1);
832 gfree(charStringOffsets);
833 delete charStrings;
834 gfree(cidMap);
837 void FoFiType1C::convertToType0(char *psName, int *codeMap, int nCodes,
838 FoFiOutputFunc outputFunc,
839 void *outputStream) {
840 int *cidMap;
841 Type1CIndex subrIdx;
842 Type1CIndexVal val;
843 int nCIDs;
844 GooString *buf;
845 Type1CEexecBuf eb;
846 GBool ok;
847 int fd, i, j, k;
849 // compute the CID count and build the CID-to-GID mapping
850 if (codeMap) {
851 nCIDs = nCodes;
852 cidMap = (int *)gmallocn(nCIDs, sizeof(int));
853 for (i = 0; i < nCodes; ++i) {
854 if (codeMap[i] >= 0 && codeMap[i] < nGlyphs) {
855 cidMap[i] = codeMap[i];
856 } else {
857 cidMap[i] = -1;
860 } else if (topDict.firstOp == 0x0c1e) {
861 nCIDs = 0;
862 for (i = 0; i < nGlyphs && i < charsetLength; ++i) {
863 if (charset[i] >= nCIDs) {
864 nCIDs = charset[i] + 1;
867 cidMap = (int *)gmallocn(nCIDs, sizeof(int));
868 for (i = 0; i < nCIDs; ++i) {
869 cidMap[i] = -1;
871 for (i = 0; i < nGlyphs && i < charsetLength; ++i) {
872 cidMap[charset[i]] = i;
874 } else {
875 nCIDs = nGlyphs;
876 cidMap = (int *)gmallocn(nCIDs, sizeof(int));
877 for (i = 0; i < nCIDs; ++i) {
878 cidMap[i] = i;
882 // write the descendant Type 1 fonts
883 for (i = 0; i < nCIDs; i += 256) {
885 //~ this assumes that all CIDs in this block have the same FD --
886 //~ to handle multiple FDs correctly, need to somehow divide the
887 //~ font up by FD; as a kludge we ignore CID 0, which is .notdef
888 fd = 0;
889 // if fdSelect is NULL, we have an 8-bit font, so just leave fd=0
890 if (fdSelect) {
891 for (j = i==0 ? 1 : 0; j < 256 && i+j < nCIDs; ++j) {
892 if (cidMap[i+j] >= 0) {
893 fd = fdSelect[cidMap[i+j]];
894 break;
899 // font dictionary (unencrypted section)
900 (*outputFunc)(outputStream, "16 dict begin\n", 14);
901 (*outputFunc)(outputStream, "/FontName /", 11);
902 (*outputFunc)(outputStream, psName, strlen(psName));
903 buf = GooString::format("_{0:02x} def\n", i >> 8);
904 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
905 delete buf;
906 (*outputFunc)(outputStream, "/FontType 1 def\n", 16);
907 if (privateDicts[fd].hasFontMatrix) {
908 buf = GooString::format("/FontMatrix [{0:.8g} {1:.8g} {2:.8g} {3:.8g} {4:.8g} {5:.8g}] def\n",
909 privateDicts[fd].fontMatrix[0],
910 privateDicts[fd].fontMatrix[1],
911 privateDicts[fd].fontMatrix[2],
912 privateDicts[fd].fontMatrix[3],
913 privateDicts[fd].fontMatrix[4],
914 privateDicts[fd].fontMatrix[5]);
915 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
916 delete buf;
917 } else if (topDict.hasFontMatrix) {
918 (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
919 } else {
920 (*outputFunc)(outputStream,
921 "/FontMatrix [0.001 0 0 0.001 0 0] def\n", 38);
923 buf = GooString::format("/FontBBox [{0:.4g} {1:.4g} {2:.4g} {3:.4g}] def\n",
924 topDict.fontBBox[0], topDict.fontBBox[1],
925 topDict.fontBBox[2], topDict.fontBBox[3]);
926 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
927 delete buf;
928 buf = GooString::format("/PaintType {0:d} def\n", topDict.paintType);
929 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
930 delete buf;
931 if (topDict.paintType != 0) {
932 buf = GooString::format("/StrokeWidth {0:.4g} def\n", topDict.strokeWidth);
933 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
934 delete buf;
936 (*outputFunc)(outputStream, "/Encoding 256 array\n", 20);
937 for (j = 0; j < 256 && i+j < nCIDs; ++j) {
938 buf = GooString::format("dup {0:d} /c{1:02x} put\n", j, j);
939 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
940 delete buf;
942 if (j < 256) {
943 buf = GooString::format("{0:d} 1 255 {{ 1 index exch /.notdef put }} for\n",
945 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
946 delete buf;
948 (*outputFunc)(outputStream, "readonly def\n", 13);
949 (*outputFunc)(outputStream, "currentdict end\n", 16);
951 // start the binary section
952 (*outputFunc)(outputStream, "currentfile eexec\n", 18);
953 eb.outputFunc = outputFunc;
954 eb.outputStream = outputStream;
955 eb.ascii = gTrue;
956 eb.r1 = 55665;
957 eb.line = 0;
959 // start the private dictionary
960 eexecWrite(&eb, "\x83\xca\x73\xd5");
961 eexecWrite(&eb, "dup /Private 32 dict dup begin\n");
962 eexecWrite(&eb, "/RD {string currentfile exch readstring pop}"
963 " executeonly def\n");
964 eexecWrite(&eb, "/ND {noaccess def} executeonly def\n");
965 eexecWrite(&eb, "/NP {noaccess put} executeonly def\n");
966 eexecWrite(&eb, "/MinFeature {16 16} def\n");
967 eexecWrite(&eb, "/password 5839 def\n");
968 if (privateDicts[fd].nBlueValues) {
969 eexecWrite(&eb, "/BlueValues [");
970 for (k = 0; k < privateDicts[fd].nBlueValues; ++k) {
971 buf = GooString::format("{0:s}{1:d}",
972 k > 0 ? " " : "",
973 privateDicts[fd].blueValues[k]);
974 eexecWrite(&eb, buf->getCString());
975 delete buf;
977 eexecWrite(&eb, "] def\n");
979 if (privateDicts[fd].nOtherBlues) {
980 eexecWrite(&eb, "/OtherBlues [");
981 for (k = 0; k < privateDicts[fd].nOtherBlues; ++k) {
982 buf = GooString::format("{0:s}{1:d}",
983 k > 0 ? " " : "",
984 privateDicts[fd].otherBlues[k]);
985 eexecWrite(&eb, buf->getCString());
986 delete buf;
988 eexecWrite(&eb, "] def\n");
990 if (privateDicts[fd].nFamilyBlues) {
991 eexecWrite(&eb, "/FamilyBlues [");
992 for (k = 0; k < privateDicts[fd].nFamilyBlues; ++k) {
993 buf = GooString::format("{0:s}{1:d}", k > 0 ? " " : "",
994 privateDicts[fd].familyBlues[k]);
995 eexecWrite(&eb, buf->getCString());
996 delete buf;
998 eexecWrite(&eb, "] def\n");
1000 if (privateDicts[fd].nFamilyOtherBlues) {
1001 eexecWrite(&eb, "/FamilyOtherBlues [");
1002 for (k = 0; k < privateDicts[fd].nFamilyOtherBlues; ++k) {
1003 buf = GooString::format("{0:s}{1:d}", k > 0 ? " " : "",
1004 privateDicts[fd].familyOtherBlues[k]);
1005 eexecWrite(&eb, buf->getCString());
1006 delete buf;
1008 eexecWrite(&eb, "] def\n");
1010 if (privateDicts[fd].blueScale != 0.039625) {
1011 buf = GooString::format("/BlueScale {0:.4g} def\n",
1012 privateDicts[fd].blueScale);
1013 eexecWrite(&eb, buf->getCString());
1014 delete buf;
1016 if (privateDicts[fd].blueShift != 7) {
1017 buf = GooString::format("/BlueShift {0:d} def\n",
1018 privateDicts[fd].blueShift);
1019 eexecWrite(&eb, buf->getCString());
1020 delete buf;
1022 if (privateDicts[fd].blueFuzz != 1) {
1023 buf = GooString::format("/BlueFuzz {0:d} def\n",
1024 privateDicts[fd].blueFuzz);
1025 eexecWrite(&eb, buf->getCString());
1026 delete buf;
1028 if (privateDicts[fd].hasStdHW) {
1029 buf = GooString::format("/StdHW [{0:.4g}] def\n", privateDicts[fd].stdHW);
1030 eexecWrite(&eb, buf->getCString());
1031 delete buf;
1033 if (privateDicts[fd].hasStdVW) {
1034 buf = GooString::format("/StdVW [{0:.4g}] def\n", privateDicts[fd].stdVW);
1035 eexecWrite(&eb, buf->getCString());
1036 delete buf;
1038 if (privateDicts[fd].nStemSnapH) {
1039 eexecWrite(&eb, "/StemSnapH [");
1040 for (k = 0; k < privateDicts[fd].nStemSnapH; ++k) {
1041 buf = GooString::format("{0:s}{1:.4g}",
1042 k > 0 ? " " : "", privateDicts[fd].stemSnapH[k]);
1043 eexecWrite(&eb, buf->getCString());
1044 delete buf;
1046 eexecWrite(&eb, "] def\n");
1048 if (privateDicts[fd].nStemSnapV) {
1049 eexecWrite(&eb, "/StemSnapV [");
1050 for (k = 0; k < privateDicts[fd].nStemSnapV; ++k) {
1051 buf = GooString::format("{0:s}{1:.4g}",
1052 k > 0 ? " " : "", privateDicts[fd].stemSnapV[k]);
1053 eexecWrite(&eb, buf->getCString());
1054 delete buf;
1056 eexecWrite(&eb, "] def\n");
1058 if (privateDicts[fd].hasForceBold) {
1059 buf = GooString::format("/ForceBold {0:s} def\n",
1060 privateDicts[fd].forceBold ? "true" : "false");
1061 eexecWrite(&eb, buf->getCString());
1062 delete buf;
1064 if (privateDicts[fd].forceBoldThreshold != 0) {
1065 buf = GooString::format("/ForceBoldThreshold {0:.4g} def\n",
1066 privateDicts[fd].forceBoldThreshold);
1067 eexecWrite(&eb, buf->getCString());
1068 delete buf;
1070 if (privateDicts[fd].languageGroup != 0) {
1071 buf = GooString::format("/LanguageGroup {0:d} def\n",
1072 privateDicts[fd].languageGroup);
1073 eexecWrite(&eb, buf->getCString());
1074 delete buf;
1076 if (privateDicts[fd].expansionFactor != 0.06) {
1077 buf = GooString::format("/ExpansionFactor {0:.4g} def\n",
1078 privateDicts[fd].expansionFactor);
1079 eexecWrite(&eb, buf->getCString());
1080 delete buf;
1083 // set up the subroutines
1084 ok = gTrue;
1085 getIndex(privateDicts[fd].subrsOffset, &subrIdx, &ok);
1086 if (!ok) {
1087 subrIdx.pos = -1;
1090 // start the CharStrings
1091 eexecWrite(&eb, "2 index /CharStrings 256 dict dup begin\n");
1093 // write the .notdef CharString
1094 ok = gTrue;
1095 getIndexVal(&charStringsIdx, 0, &val, &ok);
1096 if (ok) {
1097 eexecCvtGlyph(&eb, ".notdef", val.pos, val.len,
1098 &subrIdx, &privateDicts[fd]);
1101 // write the CharStrings
1102 for (j = 0; j < 256 && i+j < nCIDs; ++j) {
1103 if (cidMap[i+j] >= 0) {
1104 ok = gTrue;
1105 getIndexVal(&charStringsIdx, cidMap[i+j], &val, &ok);
1106 if (ok) {
1107 buf = GooString::format("c{0:02x}", j);
1108 eexecCvtGlyph(&eb, buf->getCString(), val.pos, val.len,
1109 &subrIdx, &privateDicts[fd]);
1110 delete buf;
1114 eexecWrite(&eb, "end\n");
1115 eexecWrite(&eb, "end\n");
1116 eexecWrite(&eb, "readonly put\n");
1117 eexecWrite(&eb, "noaccess put\n");
1118 eexecWrite(&eb, "dup /FontName get exch definefont pop\n");
1119 eexecWrite(&eb, "mark currentfile closefile\n");
1121 // trailer
1122 if (eb.line > 0) {
1123 (*outputFunc)(outputStream, "\n", 1);
1125 for (j = 0; j < 8; ++j) {
1126 (*outputFunc)(outputStream, "0000000000000000000000000000000000000000000000000000000000000000\n", 65);
1128 (*outputFunc)(outputStream, "cleartomark\n", 12);
1131 // write the Type 0 parent font
1132 (*outputFunc)(outputStream, "16 dict begin\n", 14);
1133 (*outputFunc)(outputStream, "/FontName /", 11);
1134 (*outputFunc)(outputStream, psName, strlen(psName));
1135 (*outputFunc)(outputStream, " def\n", 5);
1136 (*outputFunc)(outputStream, "/FontType 0 def\n", 16);
1137 if (topDict.hasFontMatrix) {
1138 buf = GooString::format("/FontMatrix [{0:.8g} {1:.8g} {2:.8g} {3:.8g} {4:.8g} {5:.8g}] def\n",
1139 topDict.fontMatrix[0], topDict.fontMatrix[1],
1140 topDict.fontMatrix[2], topDict.fontMatrix[3],
1141 topDict.fontMatrix[4], topDict.fontMatrix[5]);
1142 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
1143 delete buf;
1144 } else {
1145 (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
1147 (*outputFunc)(outputStream, "/FMapType 2 def\n", 16);
1148 (*outputFunc)(outputStream, "/Encoding [\n", 12);
1149 for (i = 0; i < nCIDs; i += 256) {
1150 buf = GooString::format("{0:d}\n", i >> 8);
1151 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
1152 delete buf;
1154 (*outputFunc)(outputStream, "] def\n", 6);
1155 (*outputFunc)(outputStream, "/FDepVector [\n", 14);
1156 for (i = 0; i < nCIDs; i += 256) {
1157 (*outputFunc)(outputStream, "/", 1);
1158 (*outputFunc)(outputStream, psName, strlen(psName));
1159 buf = GooString::format("_{0:02x} findfont\n", i >> 8);
1160 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
1161 delete buf;
1163 (*outputFunc)(outputStream, "] def\n", 6);
1164 (*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40);
1166 gfree(cidMap);
1169 void FoFiType1C::eexecCvtGlyph(Type1CEexecBuf *eb, const char *glyphName,
1170 int offset, int nBytes,
1171 Type1CIndex *subrIdx,
1172 Type1CPrivateDict *pDict) {
1173 GooString *buf;
1174 GooString *charBuf;
1176 // generate the charstring
1177 charBuf = new GooString();
1178 cvtGlyph(offset, nBytes, charBuf, subrIdx, pDict, gTrue);
1180 buf = GooString::format("/{0:s} {1:d} RD ", glyphName, charBuf->getLength());
1181 eexecWrite(eb, buf->getCString());
1182 delete buf;
1183 eexecWriteCharstring(eb, (Guchar *)charBuf->getCString(),
1184 charBuf->getLength());
1185 eexecWrite(eb, " ND\n");
1187 delete charBuf;
1190 void FoFiType1C::cvtGlyph(int offset, int nBytes, GooString *charBuf,
1191 Type1CIndex *subrIdx, Type1CPrivateDict *pDict,
1192 GBool top) {
1193 Type1CIndexVal val;
1194 GBool ok, dFP;
1195 double d, dx, dy;
1196 Gushort r2;
1197 Guchar byte;
1198 int pos, subrBias, start, i, k;
1200 start = charBuf->getLength();
1201 if (top) {
1202 charBuf->append((char)73);
1203 charBuf->append((char)58);
1204 charBuf->append((char)147);
1205 charBuf->append((char)134);
1206 nOps = 0;
1207 nHints = 0;
1208 firstOp = gTrue;
1209 openPath = gFalse;
1212 pos = offset;
1213 while (pos < offset + nBytes) {
1214 ok = gTrue;
1215 pos = getOp(pos, gTrue, &ok);
1216 if (!ok) {
1217 break;
1219 if (!ops[nOps - 1].isNum) {
1220 --nOps; // drop the operator
1221 switch (ops[nOps].op) {
1222 case 0x0001: // hstem
1223 if (firstOp) {
1224 cvtGlyphWidth(nOps & 1, charBuf, pDict);
1225 firstOp = gFalse;
1227 if (nOps & 1) {
1228 //~ error(-1, "Wrong number of args (%d) to Type 2 hstem", nOps);
1230 d = 0;
1231 dFP = gFalse;
1232 for (k = 0; k < nOps; k += 2) {
1233 // convert Type 2 edge hints (-20 or -21) to Type 1 ghost hints
1234 if (ops[k+1].num < 0) {
1235 d += ops[k].num + ops[k+1].num;
1236 dFP |= ops[k].isFP | ops[k+1].isFP;
1237 cvtNum(d, dFP, charBuf);
1238 cvtNum(-ops[k+1].num, ops[k+1].isFP, charBuf);
1239 } else {
1240 d += ops[k].num;
1241 dFP |= ops[k].isFP;
1242 cvtNum(d, dFP, charBuf);
1243 cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
1244 d += ops[k+1].num;
1245 dFP |= ops[k+1].isFP;
1247 charBuf->append((char)1);
1249 nHints += nOps / 2;
1250 nOps = 0;
1251 break;
1252 case 0x0003: // vstem
1253 if (firstOp) {
1254 cvtGlyphWidth(nOps & 1, charBuf, pDict);
1255 firstOp = gFalse;
1257 if (nOps & 1) {
1258 //~ error(-1, "Wrong number of args (%d) to Type 2 vstem", nOps);
1260 d = 0;
1261 dFP = gFalse;
1262 for (k = 0; k < nOps; k += 2) {
1263 // convert Type 2 edge hints (-20 or -21) to Type 1 ghost hints
1264 if (ops[k+1].num < 0) {
1265 d += ops[k].num + ops[k+1].num;
1266 dFP |= ops[k].isFP | ops[k+1].isFP;
1267 cvtNum(d, dFP, charBuf);
1268 cvtNum(-ops[k+1].num, ops[k+1].isFP, charBuf);
1269 } else {
1270 d += ops[k].num;
1271 dFP |= ops[k].isFP;
1272 cvtNum(d, dFP, charBuf);
1273 cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
1274 d += ops[k+1].num;
1275 dFP |= ops[k+1].isFP;
1277 charBuf->append((char)3);
1279 nHints += nOps / 2;
1280 nOps = 0;
1281 break;
1282 case 0x0004: // vmoveto
1283 if (firstOp) {
1284 cvtGlyphWidth(nOps == 2, charBuf, pDict);
1285 firstOp = gFalse;
1287 if (openPath) {
1288 charBuf->append((char)9);
1289 openPath = gFalse;
1291 if (nOps != 1) {
1292 //~ error(-1, "Wrong number of args (%d) to Type 2 vmoveto", nOps);
1294 cvtNum(ops[0].num, ops[0].isFP, charBuf);
1295 charBuf->append((char)4);
1296 nOps = 0;
1297 break;
1298 case 0x0005: // rlineto
1299 if (nOps < 2 || nOps % 2 != 0) {
1300 //~ error(-1, "Wrong number of args (%d) to Type 2 rlineto", nOps);
1302 for (k = 0; k < nOps; k += 2) {
1303 cvtNum(ops[k].num, ops[k].isFP, charBuf);
1304 cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
1305 charBuf->append((char)5);
1307 nOps = 0;
1308 openPath = gTrue;
1309 break;
1310 case 0x0006: // hlineto
1311 if (nOps < 1) {
1312 //~ error(-1, "Wrong number of args (%d) to Type 2 hlineto", nOps);
1314 for (k = 0; k < nOps; ++k) {
1315 cvtNum(ops[k].num, ops[k].isFP, charBuf);
1316 charBuf->append((char)((k & 1) ? 7 : 6));
1318 nOps = 0;
1319 openPath = gTrue;
1320 break;
1321 case 0x0007: // vlineto
1322 if (nOps < 1) {
1323 //~ error(-1, "Wrong number of args (%d) to Type 2 vlineto", nOps);
1325 for (k = 0; k < nOps; ++k) {
1326 cvtNum(ops[k].num, ops[k].isFP, charBuf);
1327 charBuf->append((char)((k & 1) ? 6 : 7));
1329 nOps = 0;
1330 openPath = gTrue;
1331 break;
1332 case 0x0008: // rrcurveto
1333 if (nOps < 6 || nOps % 6 != 0) {
1334 //~ error(-1, "Wrong number of args (%d) to Type 2 rrcurveto", nOps);
1336 for (k = 0; k < nOps; k += 6) {
1337 cvtNum(ops[k].num, ops[k].isFP, charBuf);
1338 cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
1339 cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
1340 cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
1341 cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf);
1342 cvtNum(ops[k+5].num, ops[k+5].isFP, charBuf);
1343 charBuf->append((char)8);
1345 nOps = 0;
1346 openPath = gTrue;
1347 break;
1348 case 0x000a: // callsubr
1349 if (nOps >= 1) {
1350 subrBias = (subrIdx->len < 1240)
1351 ? 107 : (subrIdx->len < 33900) ? 1131 : 32768;
1352 k = subrBias + (int)ops[nOps - 1].num;
1353 --nOps;
1354 ok = gTrue;
1355 getIndexVal(subrIdx, k, &val, &ok);
1356 if (ok) {
1357 cvtGlyph(val.pos, val.len, charBuf, subrIdx, pDict, gFalse);
1359 } else {
1360 //~ error(-1, "Too few args to Type 2 callsubr");
1362 // don't clear the stack
1363 break;
1364 case 0x000b: // return
1365 // don't clear the stack
1366 break;
1367 case 0x000e: // endchar / seac
1368 if (firstOp) {
1369 cvtGlyphWidth(nOps == 1 || nOps == 5, charBuf, pDict);
1370 firstOp = gFalse;
1372 if (openPath) {
1373 charBuf->append((char)9);
1374 openPath = gFalse;
1376 if (nOps == 4) {
1377 cvtNum(0, gFalse, charBuf);
1378 cvtNum(ops[0].num, ops[0].isFP, charBuf);
1379 cvtNum(ops[1].num, ops[1].isFP, charBuf);
1380 cvtNum(ops[2].num, ops[2].isFP, charBuf);
1381 cvtNum(ops[3].num, ops[3].isFP, charBuf);
1382 charBuf->append((char)12)->append((char)6);
1383 } else if (nOps == 0) {
1384 charBuf->append((char)14);
1385 } else {
1386 //~ error(-1, "Wrong number of args (%d) to Type 2 endchar", nOps);
1388 nOps = 0;
1389 break;
1390 case 0x000f: // (obsolete)
1391 // this op is ignored, but we need the glyph width
1392 if (firstOp) {
1393 cvtGlyphWidth(nOps > 0, charBuf, pDict);
1394 firstOp = gFalse;
1396 nOps = 0;
1397 break;
1398 case 0x0010: // blend
1399 //~ error(-1, "Unimplemented Type 2 charstring op: %d", file[i]);
1400 nOps = 0;
1401 break;
1402 case 0x0012: // hstemhm
1403 // ignored
1404 if (firstOp) {
1405 cvtGlyphWidth(nOps & 1, charBuf, pDict);
1406 firstOp = gFalse;
1408 if (nOps & 1) {
1409 //~ error(-1, "Wrong number of args (%d) to Type 2 hstemhm", nOps);
1411 nHints += nOps / 2;
1412 nOps = 0;
1413 break;
1414 case 0x0013: // hintmask
1415 // ignored
1416 if (firstOp) {
1417 cvtGlyphWidth(nOps & 1, charBuf, pDict);
1418 firstOp = gFalse;
1420 if (nOps > 0) {
1421 if (nOps & 1) {
1422 //~ error(-1, "Wrong number of args (%d) to Type 2 hintmask/vstemhm",
1423 //~ nOps);
1425 nHints += nOps / 2;
1427 pos += (nHints + 7) >> 3;
1428 nOps = 0;
1429 break;
1430 case 0x0014: // cntrmask
1431 // ignored
1432 if (firstOp) {
1433 cvtGlyphWidth(nOps & 1, charBuf, pDict);
1434 firstOp = gFalse;
1436 if (nOps > 0) {
1437 if (nOps & 1) {
1438 //~ error(-1, "Wrong number of args (%d) to Type 2 cntrmask/vstemhm",
1439 //~ nOps);
1441 nHints += nOps / 2;
1443 pos += (nHints + 7) >> 3;
1444 nOps = 0;
1445 break;
1446 case 0x0015: // rmoveto
1447 if (firstOp) {
1448 cvtGlyphWidth(nOps == 3, charBuf, pDict);
1449 firstOp = gFalse;
1451 if (openPath) {
1452 charBuf->append((char)9);
1453 openPath = gFalse;
1455 if (nOps != 2) {
1456 //~ error(-1, "Wrong number of args (%d) to Type 2 rmoveto", nOps);
1458 cvtNum(ops[0].num, ops[0].isFP, charBuf);
1459 cvtNum(ops[1].num, ops[1].isFP, charBuf);
1460 charBuf->append((char)21);
1461 nOps = 0;
1462 break;
1463 case 0x0016: // hmoveto
1464 if (firstOp) {
1465 cvtGlyphWidth(nOps == 2, charBuf, pDict);
1466 firstOp = gFalse;
1468 if (openPath) {
1469 charBuf->append((char)9);
1470 openPath = gFalse;
1472 if (nOps != 1) {
1473 //~ error(-1, "Wrong number of args (%d) to Type 2 hmoveto", nOps);
1475 cvtNum(ops[0].num, ops[0].isFP, charBuf);
1476 charBuf->append((char)22);
1477 nOps = 0;
1478 break;
1479 case 0x0017: // vstemhm
1480 // ignored
1481 if (firstOp) {
1482 cvtGlyphWidth(nOps & 1, charBuf, pDict);
1483 firstOp = gFalse;
1485 if (nOps & 1) {
1486 //~ error(-1, "Wrong number of args (%d) to Type 2 vstemhm", nOps);
1488 nHints += nOps / 2;
1489 nOps = 0;
1490 break;
1491 case 0x0018: // rcurveline
1492 if (nOps < 8 || (nOps - 2) % 6 != 0) {
1493 //~ error(-1, "Wrong number of args (%d) to Type 2 rcurveline", nOps);
1495 for (k = 0; k < nOps - 2; k += 6) {
1496 cvtNum(ops[k].num, ops[k].isFP, charBuf);
1497 cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
1498 cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
1499 cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
1500 cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf);
1501 cvtNum(ops[k+5].num, ops[k+5].isFP, charBuf);
1502 charBuf->append((char)8);
1504 cvtNum(ops[k].num, ops[k].isFP, charBuf);
1505 cvtNum(ops[k+1].num, ops[k].isFP, charBuf);
1506 charBuf->append((char)5);
1507 nOps = 0;
1508 openPath = gTrue;
1509 break;
1510 case 0x0019: // rlinecurve
1511 if (nOps < 8 || (nOps - 6) % 2 != 0) {
1512 //~ error(-1, "Wrong number of args (%d) to Type 2 rlinecurve", nOps);
1514 for (k = 0; k < nOps - 6; k += 2) {
1515 cvtNum(ops[k].num, ops[k].isFP, charBuf);
1516 cvtNum(ops[k+1].num, ops[k].isFP, charBuf);
1517 charBuf->append((char)5);
1519 cvtNum(ops[k].num, ops[k].isFP, charBuf);
1520 cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
1521 cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
1522 cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
1523 cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf);
1524 cvtNum(ops[k+5].num, ops[k+5].isFP, charBuf);
1525 charBuf->append((char)8);
1526 nOps = 0;
1527 openPath = gTrue;
1528 break;
1529 case 0x001a: // vvcurveto
1530 if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
1531 //~ error(-1, "Wrong number of args (%d) to Type 2 vvcurveto", nOps);
1533 if (nOps % 2 == 1) {
1534 cvtNum(ops[0].num, ops[0].isFP, charBuf);
1535 cvtNum(ops[1].num, ops[1].isFP, charBuf);
1536 cvtNum(ops[2].num, ops[2].isFP, charBuf);
1537 cvtNum(ops[3].num, ops[3].isFP, charBuf);
1538 cvtNum(0, gFalse, charBuf);
1539 cvtNum(ops[4].num, ops[4].isFP, charBuf);
1540 charBuf->append((char)8);
1541 k = 5;
1542 } else {
1543 k = 0;
1545 for (; k < nOps; k += 4) {
1546 cvtNum(0, gFalse, charBuf);
1547 cvtNum(ops[k].num, ops[k].isFP, charBuf);
1548 cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
1549 cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
1550 cvtNum(0, gFalse, charBuf);
1551 cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
1552 charBuf->append((char)8);
1554 nOps = 0;
1555 openPath = gTrue;
1556 break;
1557 case 0x001b: // hhcurveto
1558 if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
1559 //~ error(-1, "Wrong number of args (%d) to Type 2 hhcurveto", nOps);
1561 if (nOps % 2 == 1) {
1562 cvtNum(ops[1].num, ops[1].isFP, charBuf);
1563 cvtNum(ops[0].num, ops[0].isFP, charBuf);
1564 cvtNum(ops[2].num, ops[2].isFP, charBuf);
1565 cvtNum(ops[3].num, ops[3].isFP, charBuf);
1566 cvtNum(ops[4].num, ops[4].isFP, charBuf);
1567 cvtNum(0, gFalse, charBuf);
1568 charBuf->append((char)8);
1569 k = 5;
1570 } else {
1571 k = 0;
1573 for (; k < nOps; k += 4) {
1574 cvtNum(ops[k].num, ops[k].isFP, charBuf);
1575 cvtNum(0, gFalse, charBuf);
1576 cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
1577 cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
1578 cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
1579 cvtNum(0, gFalse, charBuf);
1580 charBuf->append((char)8);
1582 nOps = 0;
1583 openPath = gTrue;
1584 break;
1585 case 0x001d: // callgsubr
1586 if (nOps >= 1) {
1587 k = gsubrBias + (int)ops[nOps - 1].num;
1588 --nOps;
1589 ok = gTrue;
1590 getIndexVal(&gsubrIdx, k, &val, &ok);
1591 if (ok) {
1592 cvtGlyph(val.pos, val.len, charBuf, subrIdx, pDict, gFalse);
1594 } else {
1595 //~ error(-1, "Too few args to Type 2 callgsubr");
1597 // don't clear the stack
1598 break;
1599 case 0x001e: // vhcurveto
1600 if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
1601 //~ error(-1, "Wrong number of args (%d) to Type 2 vhcurveto", nOps);
1603 for (k = 0; k < nOps && k != nOps-5; k += 4) {
1604 if (k % 8 == 0) {
1605 cvtNum(ops[k].num, ops[k].isFP, charBuf);
1606 cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
1607 cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
1608 cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
1609 charBuf->append((char)30);
1610 } else {
1611 cvtNum(ops[k].num, ops[k].isFP, charBuf);
1612 cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
1613 cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
1614 cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
1615 charBuf->append((char)31);
1618 if (k == nOps-5) {
1619 if (k % 8 == 0) {
1620 cvtNum(0, gFalse, charBuf);
1621 cvtNum(ops[k].num, ops[k].isFP, charBuf);
1622 cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
1623 cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
1624 cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
1625 cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf);
1626 } else {
1627 cvtNum(ops[k].num, ops[k].isFP, charBuf);
1628 cvtNum(0, gFalse, charBuf);
1629 cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
1630 cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
1631 cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf);
1632 cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
1634 charBuf->append((char)8);
1636 nOps = 0;
1637 openPath = gTrue;
1638 break;
1639 case 0x001f: // hvcurveto
1640 if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
1641 //~ error(-1, "Wrong number of args (%d) to Type 2 hvcurveto", nOps);
1643 for (k = 0; k < nOps && k != nOps-5; k += 4) {
1644 if (k % 8 == 0) {
1645 cvtNum(ops[k].num, ops[k].isFP, charBuf);
1646 cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
1647 cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
1648 cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
1649 charBuf->append((char)31);
1650 } else {
1651 cvtNum(ops[k].num, ops[k].isFP, charBuf);
1652 cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
1653 cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
1654 cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
1655 charBuf->append((char)30);
1658 if (k == nOps-5) {
1659 if (k % 8 == 0) {
1660 cvtNum(ops[k].num, ops[k].isFP, charBuf);
1661 cvtNum(0, gFalse, charBuf);
1662 cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
1663 cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
1664 cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf);
1665 cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
1666 } else {
1667 cvtNum(0, gFalse, charBuf);
1668 cvtNum(ops[k].num, ops[k].isFP, charBuf);
1669 cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
1670 cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
1671 cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
1672 cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf);
1674 charBuf->append((char)8);
1676 nOps = 0;
1677 openPath = gTrue;
1678 break;
1679 case 0x0c00: // dotsection (should be Type 1 only?)
1680 // ignored
1681 nOps = 0;
1682 break;
1683 case 0x0c03: // and
1684 case 0x0c04: // or
1685 case 0x0c05: // not
1686 case 0x0c08: // store
1687 case 0x0c09: // abs
1688 case 0x0c0a: // add
1689 case 0x0c0b: // sub
1690 case 0x0c0c: // div
1691 case 0x0c0d: // load
1692 case 0x0c0e: // neg
1693 case 0x0c0f: // eq
1694 case 0x0c12: // drop
1695 case 0x0c14: // put
1696 case 0x0c15: // get
1697 case 0x0c16: // ifelse
1698 case 0x0c17: // random
1699 case 0x0c18: // mul
1700 case 0x0c1a: // sqrt
1701 case 0x0c1b: // dup
1702 case 0x0c1c: // exch
1703 case 0x0c1d: // index
1704 case 0x0c1e: // roll
1705 //~ error(-1, "Unimplemented Type 2 charstring op: 12.%d", file[i+1]);
1706 nOps = 0;
1707 break;
1708 case 0x0c22: // hflex
1709 if (nOps != 7) {
1710 //~ error(-1, "Wrong number of args (%d) to Type 2 hflex", nOps);
1712 cvtNum(ops[0].num, ops[0].isFP, charBuf);
1713 cvtNum(0, gFalse, charBuf);
1714 cvtNum(ops[1].num, ops[1].isFP, charBuf);
1715 cvtNum(ops[2].num, ops[2].isFP, charBuf);
1716 cvtNum(ops[3].num, ops[3].isFP, charBuf);
1717 cvtNum(0, gFalse, charBuf);
1718 charBuf->append((char)8);
1719 cvtNum(ops[4].num, ops[4].isFP, charBuf);
1720 cvtNum(0, gFalse, charBuf);
1721 cvtNum(ops[5].num, ops[5].isFP, charBuf);
1722 cvtNum(-ops[2].num, ops[2].isFP, charBuf);
1723 cvtNum(ops[6].num, ops[6].isFP, charBuf);
1724 cvtNum(0, gFalse, charBuf);
1725 charBuf->append((char)8);
1726 nOps = 0;
1727 openPath = gTrue;
1728 break;
1729 case 0x0c23: // flex
1730 if (nOps != 13) {
1731 //~ error(-1, "Wrong number of args (%d) to Type 2 flex", nOps);
1733 cvtNum(ops[0].num, ops[0].isFP, charBuf);
1734 cvtNum(ops[1].num, ops[1].isFP, charBuf);
1735 cvtNum(ops[2].num, ops[2].isFP, charBuf);
1736 cvtNum(ops[3].num, ops[3].isFP, charBuf);
1737 cvtNum(ops[4].num, ops[4].isFP, charBuf);
1738 cvtNum(ops[5].num, ops[5].isFP, charBuf);
1739 charBuf->append((char)8);
1740 cvtNum(ops[6].num, ops[6].isFP, charBuf);
1741 cvtNum(ops[7].num, ops[7].isFP, charBuf);
1742 cvtNum(ops[8].num, ops[8].isFP, charBuf);
1743 cvtNum(ops[9].num, ops[9].isFP, charBuf);
1744 cvtNum(ops[10].num, ops[10].isFP, charBuf);
1745 cvtNum(ops[11].num, ops[11].isFP, charBuf);
1746 charBuf->append((char)8);
1747 nOps = 0;
1748 openPath = gTrue;
1749 break;
1750 case 0x0c24: // hflex1
1751 if (nOps != 9) {
1752 //~ error(-1, "Wrong number of args (%d) to Type 2 hflex1", nOps);
1754 cvtNum(ops[0].num, ops[0].isFP, charBuf);
1755 cvtNum(ops[1].num, ops[1].isFP, charBuf);
1756 cvtNum(ops[2].num, ops[2].isFP, charBuf);
1757 cvtNum(ops[3].num, ops[3].isFP, charBuf);
1758 cvtNum(ops[4].num, ops[4].isFP, charBuf);
1759 cvtNum(0, gFalse, charBuf);
1760 charBuf->append((char)8);
1761 cvtNum(ops[5].num, ops[5].isFP, charBuf);
1762 cvtNum(0, gFalse, charBuf);
1763 cvtNum(ops[6].num, ops[6].isFP, charBuf);
1764 cvtNum(ops[7].num, ops[7].isFP, charBuf);
1765 cvtNum(ops[8].num, ops[8].isFP, charBuf);
1766 cvtNum(-(ops[1].num + ops[3].num + ops[7].num),
1767 ops[1].isFP | ops[3].isFP | ops[7].isFP, charBuf);
1768 charBuf->append((char)8);
1769 nOps = 0;
1770 openPath = gTrue;
1771 break;
1772 case 0x0c25: // flex1
1773 if (nOps != 11) {
1774 //~ error(-1, "Wrong number of args (%d) to Type 2 flex1", nOps);
1776 cvtNum(ops[0].num, ops[0].isFP, charBuf);
1777 cvtNum(ops[1].num, ops[1].isFP, charBuf);
1778 cvtNum(ops[2].num, ops[2].isFP, charBuf);
1779 cvtNum(ops[3].num, ops[3].isFP, charBuf);
1780 cvtNum(ops[4].num, ops[4].isFP, charBuf);
1781 cvtNum(ops[5].num, ops[5].isFP, charBuf);
1782 charBuf->append((char)8);
1783 cvtNum(ops[6].num, ops[6].isFP, charBuf);
1784 cvtNum(ops[7].num, ops[7].isFP, charBuf);
1785 cvtNum(ops[8].num, ops[8].isFP, charBuf);
1786 cvtNum(ops[9].num, ops[9].isFP, charBuf);
1787 dx = ops[0].num + ops[2].num + ops[4].num + ops[6].num + ops[8].num;
1788 dy = ops[1].num + ops[3].num + ops[5].num + ops[7].num + ops[9].num;
1789 if (fabs(dx) > fabs(dy)) {
1790 cvtNum(ops[10].num, ops[10].isFP, charBuf);
1791 cvtNum(-dy, ops[1].isFP | ops[3].isFP | ops[5].isFP |
1792 ops[7].isFP | ops[9].isFP, charBuf);
1793 } else {
1794 cvtNum(-dx, ops[0].isFP | ops[2].isFP | ops[4].isFP |
1795 ops[6].isFP | ops[8].isFP, charBuf);
1796 cvtNum(ops[10].num, ops[10].isFP, charBuf);
1798 charBuf->append((char)8);
1799 nOps = 0;
1800 openPath = gTrue;
1801 break;
1802 default:
1803 //~ error(-1, "Illegal Type 2 charstring op: %04x",
1804 //~ ops[nOps].op);
1805 nOps = 0;
1806 break;
1811 // charstring encryption
1812 if (top) {
1813 r2 = 4330;
1814 for (i = start; i < charBuf->getLength(); ++i) {
1815 byte = charBuf->getChar(i) ^ (r2 >> 8);
1816 charBuf->setChar(i, byte);
1817 r2 = (byte + r2) * 52845 + 22719;
1822 void FoFiType1C::cvtGlyphWidth(GBool useOp, GooString *charBuf,
1823 Type1CPrivateDict *pDict) {
1824 double w;
1825 GBool wFP;
1826 int i;
1828 if (useOp) {
1829 w = pDict->nominalWidthX + ops[0].num;
1830 wFP = pDict->nominalWidthXFP | ops[0].isFP;
1831 for (i = 1; i < nOps; ++i) {
1832 ops[i-1] = ops[i];
1834 --nOps;
1835 } else {
1836 w = pDict->defaultWidthX;
1837 wFP = pDict->defaultWidthXFP;
1839 cvtNum(0, gFalse, charBuf);
1840 cvtNum(w, wFP, charBuf);
1841 charBuf->append((char)13);
1844 void FoFiType1C::cvtNum(double x, GBool isFP, GooString *charBuf) {
1845 Guchar buf[12];
1846 int y, n;
1848 n = 0;
1849 if (isFP) {
1850 if (x >= -32768 && x < 32768) {
1851 y = (int)(x * 256.0);
1852 buf[0] = 255;
1853 buf[1] = (Guchar)(y >> 24);
1854 buf[2] = (Guchar)(y >> 16);
1855 buf[3] = (Guchar)(y >> 8);
1856 buf[4] = (Guchar)y;
1857 buf[5] = 255;
1858 buf[6] = 0;
1859 buf[7] = 0;
1860 buf[8] = 1;
1861 buf[9] = 0;
1862 buf[10] = 12;
1863 buf[11] = 12;
1864 n = 12;
1865 } else {
1866 //~ error(-1, "Type 2 fixed point constant out of range");
1868 } else {
1869 y = (int)x;
1870 if (y >= -107 && y <= 107) {
1871 buf[0] = (Guchar)(y + 139);
1872 n = 1;
1873 } else if (y > 107 && y <= 1131) {
1874 y -= 108;
1875 buf[0] = (Guchar)((y >> 8) + 247);
1876 buf[1] = (Guchar)(y & 0xff);
1877 n = 2;
1878 } else if (y < -107 && y >= -1131) {
1879 y = -y - 108;
1880 buf[0] = (Guchar)((y >> 8) + 251);
1881 buf[1] = (Guchar)(y & 0xff);
1882 n = 2;
1883 } else {
1884 buf[0] = 255;
1885 buf[1] = (Guchar)(y >> 24);
1886 buf[2] = (Guchar)(y >> 16);
1887 buf[3] = (Guchar)(y >> 8);
1888 buf[4] = (Guchar)y;
1889 n = 5;
1892 charBuf->append((char *)buf, n);
1895 void FoFiType1C::eexecWrite(Type1CEexecBuf *eb, const char *s) {
1896 Guchar *p;
1897 Guchar x;
1899 for (p = (Guchar *)s; *p; ++p) {
1900 x = *p ^ (eb->r1 >> 8);
1901 eb->r1 = (x + eb->r1) * 52845 + 22719;
1902 if (eb->ascii) {
1903 (*eb->outputFunc)(eb->outputStream, &hexChars[x >> 4], 1);
1904 (*eb->outputFunc)(eb->outputStream, &hexChars[x & 0x0f], 1);
1905 eb->line += 2;
1906 if (eb->line == 64) {
1907 (*eb->outputFunc)(eb->outputStream, "\n", 1);
1908 eb->line = 0;
1910 } else {
1911 (*eb->outputFunc)(eb->outputStream, (char *)&x, 1);
1916 void FoFiType1C::eexecWriteCharstring(Type1CEexecBuf *eb,
1917 Guchar *s, int n) {
1918 Guchar x;
1919 int i;
1921 // eexec encryption
1922 for (i = 0; i < n; ++i) {
1923 x = s[i] ^ (eb->r1 >> 8);
1924 eb->r1 = (x + eb->r1) * 52845 + 22719;
1925 if (eb->ascii) {
1926 (*eb->outputFunc)(eb->outputStream, &hexChars[x >> 4], 1);
1927 (*eb->outputFunc)(eb->outputStream, &hexChars[x & 0x0f], 1);
1928 eb->line += 2;
1929 if (eb->line == 64) {
1930 (*eb->outputFunc)(eb->outputStream, "\n", 1);
1931 eb->line = 0;
1933 } else {
1934 (*eb->outputFunc)(eb->outputStream, (char *)&x, 1);
1939 void FoFiType1C::writePSString(char *s, FoFiOutputFunc outputFunc,
1940 void *outputStream) {
1941 char buf[80];
1942 char *p;
1943 int i, c;
1945 i = 0;
1946 buf[i++] = '(';
1947 for (p = s; *p; ++p) {
1948 c = *p & 0xff;
1949 if (c == '(' || c == ')' || c == '\\') {
1950 buf[i++] = '\\';
1951 buf[i++] = c;
1952 } else if (c < 0x20 || c >= 0x80) {
1953 buf[i++] = '\\';
1954 buf[i++] = '0' + ((c >> 6) & 7);
1955 buf[i++] = '0' + ((c >> 3) & 7);
1956 buf[i++] = '0' + (c & 7);
1957 } else {
1958 buf[i++] = c;
1960 if (i >= 64) {
1961 buf[i++] = '\\';
1962 buf[i++] = '\n';
1963 (*outputFunc)(outputStream, buf, i);
1964 i = 0;
1967 buf[i++] = ')';
1968 (*outputFunc)(outputStream, buf, i);
1971 GBool FoFiType1C::parse() {
1972 Type1CIndex fdIdx;
1973 Type1CIndexVal val;
1974 int i;
1976 parsedOk = gTrue;
1978 // some tools embed Type 1C fonts with an extra whitespace char at
1979 // the beginning
1980 if (len > 0 && file[0] != '\x01') {
1981 ++file;
1982 --len;
1985 // find the indexes
1986 getIndex(getU8(2, &parsedOk), &nameIdx, &parsedOk);
1987 getIndex(nameIdx.endPos, &topDictIdx, &parsedOk);
1988 getIndex(topDictIdx.endPos, &stringIdx, &parsedOk);
1989 getIndex(stringIdx.endPos, &gsubrIdx, &parsedOk);
1990 if (!parsedOk) {
1991 return gFalse;
1993 gsubrBias = (gsubrIdx.len < 1240) ? 107
1994 : (gsubrIdx.len < 33900) ? 1131 : 32768;
1996 // read the first font name
1997 getIndexVal(&nameIdx, 0, &val, &parsedOk);
1998 if (!parsedOk) {
1999 return gFalse;
2001 name = new GooString((char *)&file[val.pos], val.len);
2003 // read the top dict for the first font
2004 readTopDict();
2006 // for CID fonts: read the FDArray dicts and private dicts
2007 if (topDict.firstOp == 0x0c1e) {
2008 if (topDict.fdArrayOffset == 0) {
2009 nFDs = 1;
2010 privateDicts = (Type1CPrivateDict *)gmalloc(sizeof(Type1CPrivateDict));
2011 readPrivateDict(0, 0, &privateDicts[0]);
2012 } else {
2013 getIndex(topDict.fdArrayOffset, &fdIdx, &parsedOk);
2014 if (!parsedOk) {
2015 return gFalse;
2017 nFDs = fdIdx.len;
2018 privateDicts = (Type1CPrivateDict *)
2019 gmallocn(nFDs, sizeof(Type1CPrivateDict));
2020 for (i = 0; i < nFDs; ++i) {
2021 getIndexVal(&fdIdx, i, &val, &parsedOk);
2022 if (!parsedOk) {
2023 return gFalse;
2025 readFD(val.pos, val.len, &privateDicts[i]);
2029 // for 8-bit fonts: read the private dict
2030 } else {
2031 nFDs = 1;
2032 privateDicts = (Type1CPrivateDict *)gmalloc(sizeof(Type1CPrivateDict));
2033 readPrivateDict(topDict.privateOffset, topDict.privateSize,
2034 &privateDicts[0]);
2037 // check for parse errors in the private dict(s)
2038 if (!parsedOk) {
2039 return gFalse;
2042 // get the charstrings index
2043 if (topDict.charStringsOffset <= 0) {
2044 parsedOk = gFalse;
2045 return gFalse;
2047 getIndex(topDict.charStringsOffset, &charStringsIdx, &parsedOk);
2048 if (!parsedOk) {
2049 return gFalse;
2051 nGlyphs = charStringsIdx.len;
2053 // for CID fonts: read the FDSelect table
2054 if (topDict.firstOp == 0x0c1e) {
2055 readFDSelect();
2056 if (!parsedOk) {
2057 return gFalse;
2061 // read the charset
2062 if (!readCharset()) {
2063 parsedOk = gFalse;
2064 return gFalse;
2067 // for 8-bit fonts: build the encoding
2068 if (topDict.firstOp != 0x0c14 && topDict.firstOp != 0x0c1e) {
2069 buildEncoding();
2070 if (!parsedOk) {
2071 return gFalse;
2075 return parsedOk;
2078 void FoFiType1C::readTopDict() {
2079 Type1CIndexVal topDictPtr;
2080 int pos;
2082 topDict.firstOp = -1;
2083 topDict.versionSID = 0;
2084 topDict.noticeSID = 0;
2085 topDict.copyrightSID = 0;
2086 topDict.fullNameSID = 0;
2087 topDict.familyNameSID = 0;
2088 topDict.weightSID = 0;
2089 topDict.isFixedPitch = 0;
2090 topDict.italicAngle = 0;
2091 topDict.underlinePosition = -100;
2092 topDict.underlineThickness = 50;
2093 topDict.paintType = 0;
2094 topDict.charstringType = 2;
2095 topDict.fontMatrix[0] = 0.001;
2096 topDict.fontMatrix[1] = 0;
2097 topDict.fontMatrix[2] = 0;
2098 topDict.fontMatrix[3] = 0.001;
2099 topDict.fontMatrix[4] = 0;
2100 topDict.fontMatrix[5] = 0;
2101 topDict.hasFontMatrix = gFalse;
2102 topDict.uniqueID = 0;
2103 topDict.fontBBox[0] = 0;
2104 topDict.fontBBox[1] = 0;
2105 topDict.fontBBox[2] = 0;
2106 topDict.fontBBox[3] = 0;
2107 topDict.strokeWidth = 0;
2108 topDict.charsetOffset = 0;
2109 topDict.encodingOffset = 0;
2110 topDict.charStringsOffset = 0;
2111 topDict.privateSize = 0;
2112 topDict.privateOffset = 0;
2113 topDict.registrySID = 0;
2114 topDict.orderingSID = 0;
2115 topDict.supplement = 0;
2116 topDict.fdArrayOffset = 0;
2117 topDict.fdSelectOffset = 0;
2119 getIndexVal(&topDictIdx, 0, &topDictPtr, &parsedOk);
2120 pos = topDictPtr.pos;
2121 nOps = 0;
2122 while (pos < topDictPtr.pos + topDictPtr.len) {
2123 pos = getOp(pos, gFalse, &parsedOk);
2124 if (!parsedOk) {
2125 break;
2127 if (!ops[nOps - 1].isNum) {
2128 --nOps; // drop the operator
2129 if (topDict.firstOp < 0) {
2130 topDict.firstOp = ops[nOps].op;
2132 switch (ops[nOps].op) {
2133 case 0x0000: topDict.versionSID = (int)ops[0].num; break;
2134 case 0x0001: topDict.noticeSID = (int)ops[0].num; break;
2135 case 0x0c00: topDict.copyrightSID = (int)ops[0].num; break;
2136 case 0x0002: topDict.fullNameSID = (int)ops[0].num; break;
2137 case 0x0003: topDict.familyNameSID = (int)ops[0].num; break;
2138 case 0x0004: topDict.weightSID = (int)ops[0].num; break;
2139 case 0x0c01: topDict.isFixedPitch = (int)ops[0].num; break;
2140 case 0x0c02: topDict.italicAngle = ops[0].num; break;
2141 case 0x0c03: topDict.underlinePosition = ops[0].num; break;
2142 case 0x0c04: topDict.underlineThickness = ops[0].num; break;
2143 case 0x0c05: topDict.paintType = (int)ops[0].num; break;
2144 case 0x0c06: topDict.charstringType = (int)ops[0].num; break;
2145 case 0x0c07: topDict.fontMatrix[0] = ops[0].num;
2146 topDict.fontMatrix[1] = ops[1].num;
2147 topDict.fontMatrix[2] = ops[2].num;
2148 topDict.fontMatrix[3] = ops[3].num;
2149 topDict.fontMatrix[4] = ops[4].num;
2150 topDict.fontMatrix[5] = ops[5].num;
2151 topDict.hasFontMatrix = gTrue; break;
2152 case 0x000d: topDict.uniqueID = (int)ops[0].num; break;
2153 case 0x0005: topDict.fontBBox[0] = ops[0].num;
2154 topDict.fontBBox[1] = ops[1].num;
2155 topDict.fontBBox[2] = ops[2].num;
2156 topDict.fontBBox[3] = ops[3].num; break;
2157 case 0x0c08: topDict.strokeWidth = ops[0].num; break;
2158 case 0x000f: topDict.charsetOffset = (int)ops[0].num; break;
2159 case 0x0010: topDict.encodingOffset = (int)ops[0].num; break;
2160 case 0x0011: topDict.charStringsOffset = (int)ops[0].num; break;
2161 case 0x0012: topDict.privateSize = (int)ops[0].num;
2162 topDict.privateOffset = (int)ops[1].num; break;
2163 case 0x0c1e: topDict.registrySID = (int)ops[0].num;
2164 topDict.orderingSID = (int)ops[1].num;
2165 topDict.supplement = (int)ops[2].num; break;
2166 case 0x0c24: topDict.fdArrayOffset = (int)ops[0].num; break;
2167 case 0x0c25: topDict.fdSelectOffset = (int)ops[0].num; break;
2169 nOps = 0;
2174 // Read a CID font dict (FD) - this pulls out the private dict
2175 // pointer, and reads the private dict. It also pulls the FontMatrix
2176 // (if any) out of the FD.
2177 void FoFiType1C::readFD(int offset, int length, Type1CPrivateDict *pDict) {
2178 int pos, pSize, pOffset;
2179 double fontMatrix[6] = {0};
2180 GBool hasFontMatrix;
2182 hasFontMatrix = gFalse;
2183 fontMatrix[0] = fontMatrix[1] = fontMatrix[2] = 0; // make gcc happy
2184 fontMatrix[3] = fontMatrix[4] = fontMatrix[5] = 0;
2185 pSize = pOffset = 0;
2186 pos = offset;
2187 nOps = 0;
2188 while (pos < offset + length) {
2189 pos = getOp(pos, gFalse, &parsedOk);
2190 if (!parsedOk) {
2191 return;
2193 if (!ops[nOps - 1].isNum) {
2194 if (ops[nOps - 1].op == 0x0012) {
2195 if (nOps < 3) {
2196 parsedOk = gFalse;
2197 return;
2199 pSize = (int)ops[0].num;
2200 pOffset = (int)ops[1].num;
2201 break;
2202 } else if (ops[nOps - 1].op == 0x0c07) {
2203 fontMatrix[0] = ops[0].num;
2204 fontMatrix[1] = ops[1].num;
2205 fontMatrix[2] = ops[2].num;
2206 fontMatrix[3] = ops[3].num;
2207 fontMatrix[4] = ops[4].num;
2208 fontMatrix[5] = ops[5].num;
2209 hasFontMatrix = gTrue;
2211 nOps = 0;
2214 readPrivateDict(pOffset, pSize, pDict);
2215 if (hasFontMatrix) {
2216 pDict->fontMatrix[0] = fontMatrix[0];
2217 pDict->fontMatrix[1] = fontMatrix[1];
2218 pDict->fontMatrix[2] = fontMatrix[2];
2219 pDict->fontMatrix[3] = fontMatrix[3];
2220 pDict->fontMatrix[4] = fontMatrix[4];
2221 pDict->fontMatrix[5] = fontMatrix[5];
2222 pDict->hasFontMatrix = gTrue;
2226 void FoFiType1C::readPrivateDict(int offset, int length,
2227 Type1CPrivateDict *pDict) {
2228 int pos;
2230 pDict->hasFontMatrix = gFalse;
2231 pDict->nBlueValues = 0;
2232 pDict->nOtherBlues = 0;
2233 pDict->nFamilyBlues = 0;
2234 pDict->nFamilyOtherBlues = 0;
2235 pDict->blueScale = 0.039625;
2236 pDict->blueShift = 7;
2237 pDict->blueFuzz = 1;
2238 pDict->hasStdHW = gFalse;
2239 pDict->hasStdVW = gFalse;
2240 pDict->nStemSnapH = 0;
2241 pDict->nStemSnapV = 0;
2242 pDict->hasForceBold = gFalse;
2243 pDict->forceBoldThreshold = 0;
2244 pDict->languageGroup = 0;
2245 pDict->expansionFactor = 0.06;
2246 pDict->initialRandomSeed = 0;
2247 pDict->subrsOffset = 0;
2248 pDict->defaultWidthX = 0;
2249 pDict->defaultWidthXFP = gFalse;
2250 pDict->nominalWidthX = 0;
2251 pDict->nominalWidthXFP = gFalse;
2253 // no dictionary
2254 if (offset == 0 || length == 0) {
2255 return;
2258 pos = offset;
2259 nOps = 0;
2260 while (pos < offset + length) {
2261 pos = getOp(pos, gFalse, &parsedOk);
2262 if (!parsedOk) {
2263 break;
2265 if (!ops[nOps - 1].isNum) {
2266 --nOps; // drop the operator
2267 switch (ops[nOps].op) {
2268 case 0x0006:
2269 pDict->nBlueValues = getDeltaIntArray(pDict->blueValues,
2270 type1CMaxBlueValues);
2271 break;
2272 case 0x0007:
2273 pDict->nOtherBlues = getDeltaIntArray(pDict->otherBlues,
2274 type1CMaxOtherBlues);
2275 break;
2276 case 0x0008:
2277 pDict->nFamilyBlues = getDeltaIntArray(pDict->familyBlues,
2278 type1CMaxBlueValues);
2279 break;
2280 case 0x0009:
2281 pDict->nFamilyOtherBlues = getDeltaIntArray(pDict->familyOtherBlues,
2282 type1CMaxOtherBlues);
2283 break;
2284 case 0x0c09:
2285 pDict->blueScale = ops[0].num;
2286 break;
2287 case 0x0c0a:
2288 pDict->blueShift = (int)ops[0].num;
2289 break;
2290 case 0x0c0b:
2291 pDict->blueFuzz = (int)ops[0].num;
2292 break;
2293 case 0x000a:
2294 pDict->stdHW = ops[0].num;
2295 pDict->hasStdHW = gTrue;
2296 break;
2297 case 0x000b:
2298 pDict->stdVW = ops[0].num;
2299 pDict->hasStdVW = gTrue;
2300 break;
2301 case 0x0c0c:
2302 pDict->nStemSnapH = getDeltaFPArray(pDict->stemSnapH,
2303 type1CMaxStemSnap);
2304 break;
2305 case 0x0c0d:
2306 pDict->nStemSnapV = getDeltaFPArray(pDict->stemSnapV,
2307 type1CMaxStemSnap);
2308 break;
2309 case 0x0c0e:
2310 pDict->forceBold = ops[0].num != 0;
2311 pDict->hasForceBold = gTrue;
2312 break;
2313 case 0x0c0f:
2314 pDict->forceBoldThreshold = ops[0].num;
2315 break;
2316 case 0x0c11:
2317 pDict->languageGroup = (int)ops[0].num;
2318 break;
2319 case 0x0c12:
2320 pDict->expansionFactor = ops[0].num;
2321 break;
2322 case 0x0c13:
2323 pDict->initialRandomSeed = (int)ops[0].num;
2324 break;
2325 case 0x0013:
2326 pDict->subrsOffset = offset + (int)ops[0].num;
2327 break;
2328 case 0x0014:
2329 pDict->defaultWidthX = ops[0].num;
2330 pDict->defaultWidthXFP = ops[0].isFP;
2331 break;
2332 case 0x0015:
2333 pDict->nominalWidthX = ops[0].num;
2334 pDict->nominalWidthXFP = ops[0].isFP;
2335 break;
2337 nOps = 0;
2342 void FoFiType1C::readFDSelect() {
2343 int fdSelectFmt, pos, nRanges, gid0, gid1, fd, i, j;
2345 fdSelect = (Guchar *)gmalloc(nGlyphs);
2346 if (topDict.fdSelectOffset == 0) {
2347 for (i = 0; i < nGlyphs; ++i) {
2348 fdSelect[i] = 0;
2350 } else {
2351 pos = topDict.fdSelectOffset;
2352 fdSelectFmt = getU8(pos++, &parsedOk);
2353 if (!parsedOk) {
2354 return;
2356 if (fdSelectFmt == 0) {
2357 if (!checkRegion(pos, nGlyphs)) {
2358 parsedOk = gFalse;
2359 return;
2361 memcpy(fdSelect, file + pos, nGlyphs);
2362 } else if (fdSelectFmt == 3) {
2363 nRanges = getU16BE(pos, &parsedOk);
2364 pos += 2;
2365 gid0 = getU16BE(pos, &parsedOk);
2366 pos += 2;
2367 for (i = 1; i <= nRanges; ++i) {
2368 fd = getU8(pos++, &parsedOk);
2369 gid1 = getU16BE(pos, &parsedOk);
2370 if (!parsedOk) {
2371 return;
2373 pos += 2;
2374 if (gid0 > gid1 || gid1 > nGlyphs) {
2375 //~ error(-1, "Bad FDSelect table in CID font");
2376 parsedOk = gFalse;
2377 return;
2379 for (j = gid0; j < gid1; ++j) {
2380 fdSelect[j] = fd;
2382 gid0 = gid1;
2384 } else {
2385 //~ error(-1, "Unknown FDSelect table format in CID font");
2386 for (i = 0; i < nGlyphs; ++i) {
2387 fdSelect[i] = 0;
2393 void FoFiType1C::buildEncoding() {
2394 char buf[256];
2395 int nCodes, nRanges, encFormat;
2396 int pos, c, sid, nLeft, nSups, i, j;
2398 if (topDict.encodingOffset == 0) {
2399 encoding = (char **)fofiType1StandardEncoding;
2401 } else if (topDict.encodingOffset == 1) {
2402 encoding = (char **)fofiType1ExpertEncoding;
2404 } else {
2405 encoding = (char **)gmallocn(256, sizeof(char *));
2406 for (i = 0; i < 256; ++i) {
2407 encoding[i] = NULL;
2409 pos = topDict.encodingOffset;
2410 encFormat = getU8(pos++, &parsedOk);
2411 if (!parsedOk) {
2412 return;
2414 if ((encFormat & 0x7f) == 0) {
2415 nCodes = 1 + getU8(pos++, &parsedOk);
2416 if (!parsedOk) {
2417 return;
2419 if (nCodes > nGlyphs) {
2420 nCodes = nGlyphs;
2422 for (i = 1; i < nCodes && i < charsetLength; ++i) {
2423 c = getU8(pos++, &parsedOk);
2424 if (!parsedOk) {
2425 return;
2427 if (encoding[c]) {
2428 gfree(encoding[c]);
2430 encoding[c] = copyString(getString(charset[i], buf, &parsedOk));
2432 } else if ((encFormat & 0x7f) == 1) {
2433 nRanges = getU8(pos++, &parsedOk);
2434 if (!parsedOk) {
2435 return;
2437 nCodes = 1;
2438 for (i = 0; i < nRanges; ++i) {
2439 c = getU8(pos++, &parsedOk);
2440 nLeft = getU8(pos++, &parsedOk);
2441 if (!parsedOk) {
2442 return;
2444 for (j = 0; j <= nLeft && nCodes < nGlyphs && nCodes < charsetLength; ++j) {
2445 if (c < 256) {
2446 if (encoding[c]) {
2447 gfree(encoding[c]);
2449 encoding[c] = copyString(getString(charset[nCodes], buf,
2450 &parsedOk));
2452 ++nCodes;
2453 ++c;
2457 if (encFormat & 0x80) {
2458 nSups = getU8(pos++, &parsedOk);
2459 if (!parsedOk) {
2460 return;
2462 for (i = 0; i < nSups; ++i) {
2463 c = getU8(pos++, &parsedOk);;
2464 if (!parsedOk) {
2465 return;;
2467 sid = getU16BE(pos, &parsedOk);
2468 pos += 2;
2469 if (!parsedOk) {
2470 return;
2472 if (encoding[c]) {
2473 gfree(encoding[c]);
2475 encoding[c] = copyString(getString(sid, buf, &parsedOk));
2481 GBool FoFiType1C::readCharset() {
2482 int charsetFormat, c, pos;
2483 int nLeft, i, j;
2485 if (topDict.charsetOffset == 0) {
2486 charset = fofiType1CISOAdobeCharset;
2487 charsetLength = sizeof(fofiType1CISOAdobeCharset) / sizeof(Gushort);
2488 } else if (topDict.charsetOffset == 1) {
2489 charset = fofiType1CExpertCharset;
2490 charsetLength = sizeof(fofiType1CExpertCharset) / sizeof(Gushort);
2491 } else if (topDict.charsetOffset == 2) {
2492 charset = fofiType1CExpertSubsetCharset;
2493 charsetLength = sizeof(fofiType1CExpertSubsetCharset) / sizeof(Gushort);
2494 } else {
2495 charset = (Gushort *)gmallocn(nGlyphs, sizeof(Gushort));
2496 charsetLength = nGlyphs;
2497 for (i = 0; i < nGlyphs; ++i) {
2498 charset[i] = 0;
2500 pos = topDict.charsetOffset;
2501 charsetFormat = getU8(pos++, &parsedOk);
2502 if (charsetFormat == 0) {
2503 for (i = 1; i < nGlyphs; ++i) {
2504 charset[i] = (Gushort)getU16BE(pos, &parsedOk);
2505 pos += 2;
2506 if (!parsedOk) {
2507 break;
2510 } else if (charsetFormat == 1) {
2511 i = 1;
2512 while (i < nGlyphs) {
2513 c = getU16BE(pos, &parsedOk);
2514 pos += 2;
2515 nLeft = getU8(pos++, &parsedOk);
2516 if (!parsedOk) {
2517 break;
2519 for (j = 0; j <= nLeft && i < nGlyphs; ++j) {
2520 charset[i++] = (Gushort)c++;
2523 } else if (charsetFormat == 2) {
2524 i = 1;
2525 while (i < nGlyphs) {
2526 c = getU16BE(pos, &parsedOk);
2527 pos += 2;
2528 nLeft = getU16BE(pos, &parsedOk);
2529 pos += 2;
2530 if (!parsedOk) {
2531 break;
2533 for (j = 0; j <= nLeft && i < nGlyphs; ++j) {
2534 charset[i++] = (Gushort)c++;
2538 if (!parsedOk) {
2539 gfree(charset);
2540 charset = NULL;
2541 charsetLength = 0;
2542 return gFalse;
2545 return gTrue;
2548 int FoFiType1C::getOp(int pos, GBool charstring, GBool *ok) {
2549 static char nybChars[16] = "0123456789.ee -";
2550 Type1COp op;
2551 char buf[65];
2552 int b0, b1, nyb0, nyb1, x, i;
2554 b0 = getU8(pos++, ok);
2555 op.isNum = gTrue;
2556 op.isFP = gFalse;
2558 if (b0 == 28) {
2559 x = getU8(pos++, ok);
2560 x = (x << 8) | getU8(pos++, ok);
2561 if (x & 0x8000) {
2562 x |= ~0xffff;
2564 op.num = x;
2566 } else if (!charstring && b0 == 29) {
2567 x = getU8(pos++, ok);
2568 x = (x << 8) | getU8(pos++, ok);
2569 x = (x << 8) | getU8(pos++, ok);
2570 x = (x << 8) | getU8(pos++, ok);
2571 if (x & 0x80000000) {
2572 x |= ~0xffffffff;
2574 op.num = x;
2576 } else if (!charstring && b0 == 30) {
2577 i = 0;
2578 do {
2579 b1 = getU8(pos++, ok);
2580 nyb0 = b1 >> 4;
2581 nyb1 = b1 & 0x0f;
2582 if (nyb0 == 0xf) {
2583 break;
2585 buf[i++] = nybChars[nyb0];
2586 if (i == 64) {
2587 break;
2589 if (nyb0 == 0xc) {
2590 buf[i++] = '-';
2592 if (i == 64) {
2593 break;
2595 if (nyb1 == 0xf) {
2596 break;
2598 buf[i++] = nybChars[nyb1];
2599 if (i == 64) {
2600 break;
2602 if (nyb1 == 0xc) {
2603 buf[i++] = '-';
2605 } while (i < 64);
2606 buf[i] = '\0';
2607 op.num = gatof(buf);
2608 op.isFP = gTrue;
2610 } else if (b0 >= 32 && b0 <= 246) {
2611 op.num = b0 - 139;
2613 } else if (b0 >= 247 && b0 <= 250) {
2614 op.num = ((b0 - 247) << 8) + getU8(pos++, ok) + 108;
2616 } else if (b0 >= 251 && b0 <= 254) {
2617 op.num = -((b0 - 251) << 8) - getU8(pos++, ok) - 108;
2619 } else if (charstring && b0 == 255) {
2620 x = getU8(pos++, ok);
2621 x = (x << 8) | getU8(pos++, ok);
2622 x = (x << 8) | getU8(pos++, ok);
2623 x = (x << 8) | getU8(pos++, ok);
2624 if (x & 0x80000000) {
2625 x |= ~0xffffffff;
2627 op.num = (double)x / 65536.0;
2628 op.isFP = gTrue;
2630 } else if (b0 == 12) {
2631 op.isNum = gFalse;
2632 op.op = 0x0c00 + getU8(pos++, ok);
2634 } else {
2635 op.isNum = gFalse;
2636 op.op = b0;
2639 if (nOps < 49) {
2640 ops[nOps++] = op;
2643 return pos;
2646 // Convert the delta-encoded ops array to an array of ints.
2647 int FoFiType1C::getDeltaIntArray(int *arr, int maxLen) {
2648 int x;
2649 int n, i;
2651 if ((n = nOps) > maxLen) {
2652 n = maxLen;
2654 x = 0;
2655 for (i = 0; i < n; ++i) {
2656 x += (int)ops[i].num;
2657 arr[i] = x;
2659 return n;
2662 // Convert the delta-encoded ops array to an array of doubles.
2663 int FoFiType1C::getDeltaFPArray(double *arr, int maxLen) {
2664 double x;
2665 int n, i;
2667 if ((n = nOps) > maxLen) {
2668 n = maxLen;
2670 x = 0;
2671 for (i = 0; i < n; ++i) {
2672 x += ops[i].num;
2673 arr[i] = x;
2675 return n;
2678 void FoFiType1C::getIndex(int pos, Type1CIndex *idx, GBool *ok) {
2679 idx->pos = pos;
2680 idx->len = getU16BE(pos, ok);
2681 if (idx->len == 0) {
2682 // empty indexes are legal and contain just the length field
2683 idx->offSize = 0;
2684 idx->startPos = idx->endPos = pos + 2;
2685 } else {
2686 idx->offSize = getU8(pos + 2, ok);
2687 if (idx->offSize < 1 || idx->offSize > 4) {
2688 *ok = gFalse;
2690 idx->startPos = pos + 3 + (idx->len + 1) * idx->offSize - 1;
2691 if (idx->startPos < 0 || idx->startPos >= len) {
2692 *ok = gFalse;
2694 idx->endPos = idx->startPos + getUVarBE(pos + 3 + idx->len * idx->offSize,
2695 idx->offSize, ok);
2696 if (idx->endPos < idx->startPos || idx->endPos > len) {
2697 *ok = gFalse;
2702 void FoFiType1C::getIndexVal(Type1CIndex *idx, int i,
2703 Type1CIndexVal *val, GBool *ok) {
2704 int pos0, pos1;
2706 if (i < 0 || i >= idx->len) {
2707 *ok = gFalse;
2708 return;
2710 pos0 = idx->startPos + getUVarBE(idx->pos + 3 + i * idx->offSize,
2711 idx->offSize, ok);
2712 pos1 = idx->startPos + getUVarBE(idx->pos + 3 + (i + 1) * idx->offSize,
2713 idx->offSize, ok);
2714 if (pos0 < idx->startPos || pos0 > idx->endPos ||
2715 pos1 <= idx->startPos || pos1 > idx->endPos ||
2716 pos1 < pos0) {
2717 *ok = gFalse;
2719 val->pos = pos0;
2720 val->len = pos1 - pos0;
2723 char *FoFiType1C::getString(int sid, char *buf, GBool *ok) {
2724 Type1CIndexVal val;
2725 int n;
2727 if (sid < 0) {
2728 buf[0] = '\0';
2729 } else if (sid < 391) {
2730 strcpy(buf, fofiType1CStdStrings[sid]);
2731 } else {
2732 sid -= 391;
2733 getIndexVal(&stringIdx, sid, &val, ok);
2734 if (*ok) {
2735 if ((n = val.len) > 255) {
2736 n = 255;
2738 strncpy(buf, (char *)&file[val.pos], n);
2739 buf[n] = '\0';
2740 } else {
2741 buf[0] = '\0';
2744 return buf;