modified makefile to allow easier adjustment of build options for different targets...
[AROS-Contrib.git] / arospdf / fofi / FoFiType1C.cc
blobbcfd0eb125407e179ac9e9e92628cad5eecf439d
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 *)gmallocn(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 *psName, char **newEncoding, GBool ascii,
133 FoFiOutputFunc outputFunc,
134 void *outputStream) {
135 int psNameLen;
136 Type1CEexecBuf eb;
137 Type1CIndex subrIdx;
138 Type1CIndexVal val;
139 GString *buf;
140 char buf2[256];
141 char **enc;
142 GBool ok;
143 int i;
145 if (psName) {
146 psNameLen = strlen(psName);
147 } else {
148 psName = name->getCString();
149 psNameLen = name->getLength();
152 // write header and font dictionary, up to encoding
153 ok = gTrue;
154 (*outputFunc)(outputStream, "%!FontType1-1.0: ", 17);
155 (*outputFunc)(outputStream, psName, psNameLen);
156 if (topDict.versionSID != 0) {
157 getString(topDict.versionSID, buf2, &ok);
158 (*outputFunc)(outputStream, buf2, strlen(buf2));
160 (*outputFunc)(outputStream, "\n", 1);
161 // the dictionary needs room for 12 entries: the following 9, plus
162 // Private and CharStrings (in the eexec section) and FID (which is
163 // added by definefont)
164 (*outputFunc)(outputStream, "12 dict begin\n", 14);
165 (*outputFunc)(outputStream, "/FontInfo 10 dict dup begin\n", 28);
166 if (topDict.versionSID != 0) {
167 (*outputFunc)(outputStream, "/version (", 10);
168 (*outputFunc)(outputStream, buf2, strlen(buf2));
169 (*outputFunc)(outputStream, ") readonly def\n", 15);
171 if (topDict.noticeSID != 0) {
172 getString(topDict.noticeSID, buf2, &ok);
173 (*outputFunc)(outputStream, "/Notice (", 9);
174 (*outputFunc)(outputStream, buf2, strlen(buf2));
175 (*outputFunc)(outputStream, ") readonly def\n", 15);
177 if (topDict.copyrightSID != 0) {
178 getString(topDict.copyrightSID, buf2, &ok);
179 (*outputFunc)(outputStream, "/Copyright (", 12);
180 (*outputFunc)(outputStream, buf2, strlen(buf2));
181 (*outputFunc)(outputStream, ") readonly def\n", 15);
183 if (topDict.fullNameSID != 0) {
184 getString(topDict.fullNameSID, buf2, &ok);
185 (*outputFunc)(outputStream, "/FullName (", 11);
186 (*outputFunc)(outputStream, buf2, strlen(buf2));
187 (*outputFunc)(outputStream, ") readonly def\n", 15);
189 if (topDict.familyNameSID != 0) {
190 getString(topDict.familyNameSID, buf2, &ok);
191 (*outputFunc)(outputStream, "/FamilyName (", 13);
192 (*outputFunc)(outputStream, buf2, strlen(buf2));
193 (*outputFunc)(outputStream, ") readonly def\n", 15);
195 if (topDict.weightSID != 0) {
196 getString(topDict.weightSID, buf2, &ok);
197 (*outputFunc)(outputStream, "/Weight (", 9);
198 (*outputFunc)(outputStream, buf2, strlen(buf2));
199 (*outputFunc)(outputStream, ") readonly def\n", 15);
201 if (topDict.isFixedPitch) {
202 (*outputFunc)(outputStream, "/isFixedPitch true def\n", 23);
203 } else {
204 (*outputFunc)(outputStream, "/isFixedPitch false def\n", 24);
206 buf = GString::format("/ItalicAngle {0:.4g} def\n", topDict.italicAngle);
207 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
208 delete buf;
209 buf = GString::format("/UnderlinePosition {0:.4g} def\n",
210 topDict.underlinePosition);
211 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
212 delete buf;
213 buf = GString::format("/UnderlineThickness {0:.4g} def\n",
214 topDict.underlineThickness);
215 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
216 delete buf;
217 (*outputFunc)(outputStream, "end readonly def\n", 17);
218 (*outputFunc)(outputStream, "/FontName /", 11);
219 (*outputFunc)(outputStream, psName, psNameLen);
220 (*outputFunc)(outputStream, " def\n", 5);
221 buf = GString::format("/PaintType {0:d} def\n", topDict.paintType);
222 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
223 delete buf;
224 (*outputFunc)(outputStream, "/FontType 1 def\n", 16);
225 buf = GString::format("/FontMatrix [{0:.8g} {1:.8g} {2:.8g} {3:.8g} {4:.8g} {5:.8g}] readonly def\n",
226 topDict.fontMatrix[0], topDict.fontMatrix[1],
227 topDict.fontMatrix[2], topDict.fontMatrix[3],
228 topDict.fontMatrix[4], topDict.fontMatrix[5]);
229 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
230 delete buf;
231 buf = GString::format("/FontBBox [{0:.4g} {1:.4g} {2:.4g} {3:.4g}] readonly def\n",
232 topDict.fontBBox[0], topDict.fontBBox[1],
233 topDict.fontBBox[2], topDict.fontBBox[3]);
234 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
235 delete buf;
236 buf = GString::format("/StrokeWidth {0:.4g} def\n", topDict.strokeWidth);
237 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
238 delete buf;
239 if (topDict.uniqueID != 0) {
240 buf = GString::format("/UniqueID {0:d} def\n", topDict.uniqueID);
241 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
242 delete buf;
245 // write the encoding
246 (*outputFunc)(outputStream, "/Encoding ", 10);
247 if (!newEncoding && encoding == fofiType1StandardEncoding) {
248 (*outputFunc)(outputStream, "StandardEncoding def\n", 21);
249 } else {
250 (*outputFunc)(outputStream, "256 array\n", 10);
251 (*outputFunc)(outputStream,
252 "0 1 255 {1 index exch /.notdef put} for\n", 40);
253 enc = newEncoding ? newEncoding : encoding;
254 for (i = 0; i < 256; ++i) {
255 if (enc[i]) {
256 buf = GString::format("dup {0:d} /{1:s} put\n", i, enc[i]);
257 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
258 delete buf;
261 (*outputFunc)(outputStream, "readonly def\n", 13);
263 (*outputFunc)(outputStream, "currentdict end\n", 16);
265 // start the binary section
266 (*outputFunc)(outputStream, "currentfile eexec\n", 18);
267 eb.outputFunc = outputFunc;
268 eb.outputStream = outputStream;
269 eb.ascii = ascii;
270 eb.r1 = 55665;
271 eb.line = 0;
273 // write the private dictionary
274 eexecWrite(&eb, "\x83\xca\x73\xd5");
275 eexecWrite(&eb, "dup /Private 32 dict dup begin\n");
276 eexecWrite(&eb, "/RD {string currentfile exch readstring pop}"
277 " executeonly def\n");
278 eexecWrite(&eb, "/ND {noaccess def} executeonly def\n");
279 eexecWrite(&eb, "/NP {noaccess put} executeonly def\n");
280 eexecWrite(&eb, "/MinFeature {16 16} def\n");
281 eexecWrite(&eb, "/password 5839 def\n");
282 if (privateDicts[0].nBlueValues) {
283 eexecWrite(&eb, "/BlueValues [");
284 for (i = 0; i < privateDicts[0].nBlueValues; ++i) {
285 buf = GString::format("{0:s}{1:d}",
286 i > 0 ? " " : "", privateDicts[0].blueValues[i]);
287 eexecWrite(&eb, buf->getCString());
288 delete buf;
290 eexecWrite(&eb, "] def\n");
292 if (privateDicts[0].nOtherBlues) {
293 eexecWrite(&eb, "/OtherBlues [");
294 for (i = 0; i < privateDicts[0].nOtherBlues; ++i) {
295 buf = GString::format("{0:s}{1:d}",
296 i > 0 ? " " : "", privateDicts[0].otherBlues[i]);
297 eexecWrite(&eb, buf->getCString());
298 delete buf;
300 eexecWrite(&eb, "] def\n");
302 if (privateDicts[0].nFamilyBlues) {
303 eexecWrite(&eb, "/FamilyBlues [");
304 for (i = 0; i < privateDicts[0].nFamilyBlues; ++i) {
305 buf = GString::format("{0:s}{1:d}",
306 i > 0 ? " " : "", privateDicts[0].familyBlues[i]);
307 eexecWrite(&eb, buf->getCString());
308 delete buf;
310 eexecWrite(&eb, "] def\n");
312 if (privateDicts[0].nFamilyOtherBlues) {
313 eexecWrite(&eb, "/FamilyOtherBlues [");
314 for (i = 0; i < privateDicts[0].nFamilyOtherBlues; ++i) {
315 buf = GString::format("{0:s}{1:d}", i > 0 ? " " : "",
316 privateDicts[0].familyOtherBlues[i]);
317 eexecWrite(&eb, buf->getCString());
318 delete buf;
320 eexecWrite(&eb, "] def\n");
322 if (privateDicts[0].blueScale != 0.039625) {
323 buf = GString::format("/BlueScale {0:.4g} def\n",
324 privateDicts[0].blueScale);
325 eexecWrite(&eb, buf->getCString());
326 delete buf;
328 if (privateDicts[0].blueShift != 7) {
329 buf = GString::format("/BlueShift {0:d} def\n", privateDicts[0].blueShift);
330 eexecWrite(&eb, buf->getCString());
331 delete buf;
333 if (privateDicts[0].blueFuzz != 1) {
334 buf = GString::format("/BlueFuzz {0:d} def\n", privateDicts[0].blueFuzz);
335 eexecWrite(&eb, buf->getCString());
336 delete buf;
338 if (privateDicts[0].hasStdHW) {
339 buf = GString::format("/StdHW [{0:.4g}] def\n", privateDicts[0].stdHW);
340 eexecWrite(&eb, buf->getCString());
341 delete buf;
343 if (privateDicts[0].hasStdVW) {
344 buf = GString::format("/StdVW [{0:.4g}] def\n", privateDicts[0].stdVW);
345 eexecWrite(&eb, buf->getCString());
346 delete buf;
348 if (privateDicts[0].nStemSnapH) {
349 eexecWrite(&eb, "/StemSnapH [");
350 for (i = 0; i < privateDicts[0].nStemSnapH; ++i) {
351 buf = GString::format("{0:s}{1:.4g}",
352 i > 0 ? " " : "", privateDicts[0].stemSnapH[i]);
353 eexecWrite(&eb, buf->getCString());
354 delete buf;
356 eexecWrite(&eb, "] def\n");
358 if (privateDicts[0].nStemSnapV) {
359 eexecWrite(&eb, "/StemSnapV [");
360 for (i = 0; i < privateDicts[0].nStemSnapV; ++i) {
361 buf = GString::format("{0:s}{1:.4g}",
362 i > 0 ? " " : "", privateDicts[0].stemSnapV[i]);
363 eexecWrite(&eb, buf->getCString());
364 delete buf;
366 eexecWrite(&eb, "] def\n");
368 if (privateDicts[0].hasForceBold) {
369 buf = GString::format("/ForceBold {0:s} def\n",
370 privateDicts[0].forceBold ? "true" : "false");
371 eexecWrite(&eb, buf->getCString());
372 delete buf;
374 if (privateDicts[0].forceBoldThreshold != 0) {
375 buf = GString::format("/ForceBoldThreshold {0:.4g} def\n",
376 privateDicts[0].forceBoldThreshold);
377 eexecWrite(&eb, buf->getCString());
378 delete buf;
380 if (privateDicts[0].languageGroup != 0) {
381 buf = GString::format("/LanguageGroup {0:d} def\n",
382 privateDicts[0].languageGroup);
383 eexecWrite(&eb, buf->getCString());
384 delete buf;
386 if (privateDicts[0].expansionFactor != 0.06) {
387 buf = GString::format("/ExpansionFactor {0:.4g} def\n",
388 privateDicts[0].expansionFactor);
389 eexecWrite(&eb, buf->getCString());
390 delete buf;
393 // set up subroutines
394 ok = gTrue;
395 getIndex(privateDicts[0].subrsOffset, &subrIdx, &ok);
396 if (!ok) {
397 subrIdx.pos = -1;
400 // write the CharStrings
401 buf = GString::format("2 index /CharStrings {0:d} dict dup begin\n",
402 nGlyphs);
403 eexecWrite(&eb, buf->getCString());
404 delete buf;
405 for (i = 0; i < nGlyphs; ++i) {
406 ok = gTrue;
407 getIndexVal(&charStringsIdx, i, &val, &ok);
408 if (ok) {
409 getString(charset[i], buf2, &ok);
410 if (ok) {
411 eexecCvtGlyph(&eb, buf2, val.pos, val.len, &subrIdx, &privateDicts[0]);
415 eexecWrite(&eb, "end\n");
416 eexecWrite(&eb, "end\n");
417 eexecWrite(&eb, "readonly put\n");
418 eexecWrite(&eb, "noaccess put\n");
419 eexecWrite(&eb, "dup /FontName get exch definefont pop\n");
420 eexecWrite(&eb, "mark currentfile closefile\n");
422 // trailer
423 if (ascii && eb.line > 0) {
424 (*outputFunc)(outputStream, "\n", 1);
426 for (i = 0; i < 8; ++i) {
427 (*outputFunc)(outputStream, "0000000000000000000000000000000000000000000000000000000000000000\n", 65);
429 (*outputFunc)(outputStream, "cleartomark\n", 12);
432 void FoFiType1C::convertToCIDType0(char *psName,
433 FoFiOutputFunc outputFunc,
434 void *outputStream) {
435 int *cidMap;
436 GString *charStrings;
437 int *charStringOffsets;
438 Type1CIndex subrIdx;
439 Type1CIndexVal val;
440 int nCIDs, gdBytes;
441 GString *buf;
442 char buf2[256];
443 GBool ok;
444 int gid, offset, n, i, j, k;
446 // compute the CID count and build the CID-to-GID mapping
447 nCIDs = 0;
448 for (i = 0; i < nGlyphs; ++i) {
449 if (charset[i] >= nCIDs) {
450 nCIDs = charset[i] + 1;
453 cidMap = (int *)gmallocn(nCIDs, sizeof(int));
454 for (i = 0; i < nCIDs; ++i) {
455 cidMap[i] = -1;
457 for (i = 0; i < nGlyphs; ++i) {
458 cidMap[charset[i]] = i;
461 // build the charstrings
462 charStrings = new GString();
463 charStringOffsets = (int *)gmallocn(nCIDs + 1, sizeof(int));
464 for (i = 0; i < nCIDs; ++i) {
465 charStringOffsets[i] = charStrings->getLength();
466 if ((gid = cidMap[i]) >= 0) {
467 ok = gTrue;
468 getIndexVal(&charStringsIdx, gid, &val, &ok);
469 if (ok) {
470 getIndex(privateDicts[fdSelect[gid]].subrsOffset, &subrIdx, &ok);
471 if (!ok) {
472 subrIdx.pos = -1;
474 cvtGlyph(val.pos, val.len, charStrings,
475 &subrIdx, &privateDicts[fdSelect[gid]], gTrue);
479 charStringOffsets[nCIDs] = charStrings->getLength();
481 // compute gdBytes = number of bytes needed for charstring offsets
482 // (offset size needs to account for the charstring offset table,
483 // with a worst case of five bytes per entry, plus the charstrings
484 // themselves)
485 i = (nCIDs + 1) * 5 + charStrings->getLength();
486 if (i < 0x100) {
487 gdBytes = 1;
488 } else if (i < 0x10000) {
489 gdBytes = 2;
490 } else if (i < 0x1000000) {
491 gdBytes = 3;
492 } else {
493 gdBytes = 4;
496 // begin the font dictionary
497 (*outputFunc)(outputStream, "/CIDInit /ProcSet findresource begin\n", 37);
498 (*outputFunc)(outputStream, "20 dict begin\n", 14);
499 (*outputFunc)(outputStream, "/CIDFontName /", 14);
500 (*outputFunc)(outputStream, psName, strlen(psName));
501 (*outputFunc)(outputStream, " def\n", 5);
502 (*outputFunc)(outputStream, "/CIDFontType 0 def\n", 19);
503 (*outputFunc)(outputStream, "/CIDSystemInfo 3 dict dup begin\n", 32);
504 if (topDict.registrySID > 0 && topDict.orderingSID > 0) {
505 ok = gTrue;
506 getString(topDict.registrySID, buf2, &ok);
507 if (ok) {
508 (*outputFunc)(outputStream, " /Registry (", 13);
509 (*outputFunc)(outputStream, buf2, strlen(buf2));
510 (*outputFunc)(outputStream, ") def\n", 6);
512 ok = gTrue;
513 getString(topDict.orderingSID, buf2, &ok);
514 if (ok) {
515 (*outputFunc)(outputStream, " /Ordering (", 13);
516 (*outputFunc)(outputStream, buf2, strlen(buf2));
517 (*outputFunc)(outputStream, ") def\n", 6);
519 } else {
520 (*outputFunc)(outputStream, " /Registry (Adobe) def\n", 24);
521 (*outputFunc)(outputStream, " /Ordering (Identity) def\n", 27);
523 buf = GString::format(" /Supplement {0:d} def\n", topDict.supplement);
524 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
525 delete buf;
526 (*outputFunc)(outputStream, "end def\n", 8);
527 if (topDict.hasFontMatrix) {
528 buf = GString::format("/FontMatrix [{0:.8g} {1:.8g} {2:.8g} {3:.8g} {4:.8g} {5:.8g}] def\n",
529 topDict.fontMatrix[0], topDict.fontMatrix[1],
530 topDict.fontMatrix[2], topDict.fontMatrix[3],
531 topDict.fontMatrix[4], topDict.fontMatrix[5]);
532 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
533 delete buf;
534 } else if (privateDicts[0].hasFontMatrix) {
535 (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
536 } else {
537 (*outputFunc)(outputStream,
538 "/FontMatrix [0.001 0 0 0.001 0 0] def\n", 38);
540 buf = GString::format("/FontBBox [{0:.4g} {1:.4g} {2:.4g} {3:.4g}] def\n",
541 topDict.fontBBox[0], topDict.fontBBox[1],
542 topDict.fontBBox[2], topDict.fontBBox[3]);
543 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
544 delete buf;
545 (*outputFunc)(outputStream, "/FontInfo 1 dict dup begin\n", 27);
546 (*outputFunc)(outputStream, " /FSType 8 def\n", 16);
547 (*outputFunc)(outputStream, "end def\n", 8);
549 // CIDFont-specific entries
550 buf = GString::format("/CIDCount {0:d} def\n", nCIDs);
551 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
552 delete buf;
553 (*outputFunc)(outputStream, "/FDBytes 1 def\n", 15);
554 buf = GString::format("/GDBytes {0:d} def\n", gdBytes);
555 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
556 delete buf;
557 (*outputFunc)(outputStream, "/CIDMapOffset 0 def\n", 20);
558 if (topDict.paintType != 0) {
559 buf = GString::format("/PaintType {0:d} def\n", topDict.paintType);
560 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
561 delete buf;
562 buf = GString::format("/StrokeWidth {0:.4g} def\n", topDict.strokeWidth);
563 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
564 delete buf;
567 // FDArray entry
568 buf = GString::format("/FDArray {0:d} array\n", nFDs);
569 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
570 delete buf;
571 for (i = 0; i < nFDs; ++i) {
572 buf = GString::format("dup {0:d} 10 dict begin\n", i);
573 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
574 delete buf;
575 (*outputFunc)(outputStream, "/FontType 1 def\n", 16);
576 if (privateDicts[i].hasFontMatrix) {
577 buf = GString::format("/FontMatrix [{0:.8g} {1:.8g} {2:.8g} {3:.8g} {4:.8g} {5:.8g}] def\n",
578 privateDicts[i].fontMatrix[0],
579 privateDicts[i].fontMatrix[1],
580 privateDicts[i].fontMatrix[2],
581 privateDicts[i].fontMatrix[3],
582 privateDicts[i].fontMatrix[4],
583 privateDicts[i].fontMatrix[5]);
584 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
585 delete buf;
586 } else {
587 (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
589 buf = GString::format("/PaintType {0:d} def\n", topDict.paintType);
590 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
591 delete buf;
592 (*outputFunc)(outputStream, "/Private 32 dict begin\n", 23);
593 if (privateDicts[i].nBlueValues) {
594 (*outputFunc)(outputStream, "/BlueValues [", 13);
595 for (j = 0; j < privateDicts[i].nBlueValues; ++j) {
596 buf = GString::format("{0:s}{1:d}",
597 j > 0 ? " " : "", privateDicts[i].blueValues[j]);
598 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
599 delete buf;
601 (*outputFunc)(outputStream, "] def\n", 6);
603 if (privateDicts[i].nOtherBlues) {
604 (*outputFunc)(outputStream, "/OtherBlues [", 13);
605 for (j = 0; j < privateDicts[i].nOtherBlues; ++j) {
606 buf = GString::format("{0:s}{1:d}",
607 j > 0 ? " " : "", privateDicts[i].otherBlues[j]);
608 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
609 delete buf;
611 (*outputFunc)(outputStream, "] def\n", 6);
613 if (privateDicts[i].nFamilyBlues) {
614 (*outputFunc)(outputStream, "/FamilyBlues [", 14);
615 for (j = 0; j < privateDicts[i].nFamilyBlues; ++j) {
616 buf = GString::format("{0:s}{1:d}",
617 j > 0 ? " " : "",
618 privateDicts[i].familyBlues[j]);
619 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
620 delete buf;
622 (*outputFunc)(outputStream, "] def\n", 6);
624 if (privateDicts[i].nFamilyOtherBlues) {
625 (*outputFunc)(outputStream, "/FamilyOtherBlues [", 19);
626 for (j = 0; j < privateDicts[i].nFamilyOtherBlues; ++j) {
627 buf = GString::format("{0:s}{1:d}", j > 0 ? " " : "",
628 privateDicts[i].familyOtherBlues[j]);
629 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
630 delete buf;
632 (*outputFunc)(outputStream, "] def\n", 6);
634 if (privateDicts[i].blueScale != 0.039625) {
635 buf = GString::format("/BlueScale {0:.4g} def\n",
636 privateDicts[i].blueScale);
637 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
638 delete buf;
640 if (privateDicts[i].blueShift != 7) {
641 buf = GString::format("/BlueShift {0:d} def\n",
642 privateDicts[i].blueShift);
643 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
644 delete buf;
646 if (privateDicts[i].blueFuzz != 1) {
647 buf = GString::format("/BlueFuzz {0:d} def\n", privateDicts[i].blueFuzz);
648 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
649 delete buf;
651 if (privateDicts[i].hasStdHW) {
652 buf = GString::format("/StdHW [{0:.4g}] def\n", privateDicts[i].stdHW);
653 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
654 delete buf;
656 if (privateDicts[i].hasStdVW) {
657 buf = GString::format("/StdVW [{0:.4g}] def\n", privateDicts[i].stdVW);
658 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
659 delete buf;
661 if (privateDicts[i].nStemSnapH) {
662 (*outputFunc)(outputStream, "/StemSnapH [", 12);
663 for (j = 0; j < privateDicts[i].nStemSnapH; ++j) {
664 buf = GString::format("{0:s}{1:.4g}",
665 j > 0 ? " " : "", privateDicts[i].stemSnapH[j]);
666 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
667 delete buf;
669 (*outputFunc)(outputStream, "] def\n", 6);
671 if (privateDicts[i].nStemSnapV) {
672 (*outputFunc)(outputStream, "/StemSnapV [", 12);
673 for (j = 0; j < privateDicts[i].nStemSnapV; ++j) {
674 buf = GString::format("{0:s}{1:.4g}",
675 j > 0 ? " " : "", privateDicts[i].stemSnapV[j]);
676 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
677 delete buf;
679 (*outputFunc)(outputStream, "] def\n", 6);
681 if (privateDicts[i].hasForceBold) {
682 buf = GString::format("/ForceBold {0:s} def\n",
683 privateDicts[i].forceBold ? "true" : "false");
684 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
685 delete buf;
687 if (privateDicts[i].forceBoldThreshold != 0) {
688 buf = GString::format("/ForceBoldThreshold {0:.4g} def\n",
689 privateDicts[i].forceBoldThreshold);
690 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
691 delete buf;
693 if (privateDicts[i].languageGroup != 0) {
694 buf = GString::format("/LanguageGroup {0:d} def\n",
695 privateDicts[i].languageGroup);
696 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
697 delete buf;
699 if (privateDicts[i].expansionFactor != 0.06) {
700 buf = GString::format("/ExpansionFactor {0:.4g} def\n",
701 privateDicts[i].expansionFactor);
702 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
703 delete buf;
705 (*outputFunc)(outputStream, "currentdict end def\n", 20);
706 (*outputFunc)(outputStream, "currentdict end put\n", 20);
708 (*outputFunc)(outputStream, "def\n", 4);
710 // start the binary section
711 offset = (nCIDs + 1) * (1 + gdBytes);
712 buf = GString::format("(Hex) {0:d} StartData\n",
713 offset + charStrings->getLength());
714 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
715 delete buf;
717 // write the charstring offset (CIDMap) table
718 for (i = 0; i <= nCIDs; i += 6) {
719 for (j = 0; j < 6 && i+j <= nCIDs; ++j) {
720 if (i+j < nCIDs && cidMap[i+j] >= 0) {
721 buf2[0] = (char)fdSelect[cidMap[i+j]];
722 } else {
723 buf2[0] = (char)0;
725 n = offset + charStringOffsets[i+j];
726 for (k = gdBytes; k >= 1; --k) {
727 buf2[k] = (char)(n & 0xff);
728 n >>= 8;
730 for (k = 0; k <= gdBytes; ++k) {
731 buf = GString::format("{0:02x}", buf2[k] & 0xff);
732 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
733 delete buf;
736 (*outputFunc)(outputStream, "\n", 1);
739 // write the charstring data
740 n = charStrings->getLength();
741 for (i = 0; i < n; i += 32) {
742 for (j = 0; j < 32 && i+j < n; ++j) {
743 buf = GString::format("{0:02x}", charStrings->getChar(i+j) & 0xff);
744 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
745 delete buf;
747 if (i + 32 >= n) {
748 (*outputFunc)(outputStream, ">", 1);
750 (*outputFunc)(outputStream, "\n", 1);
753 gfree(charStringOffsets);
754 delete charStrings;
755 gfree(cidMap);
758 void FoFiType1C::convertToType0(char *psName,
759 FoFiOutputFunc outputFunc,
760 void *outputStream) {
761 int *cidMap;
762 Type1CIndex subrIdx;
763 Type1CIndexVal val;
764 int nCIDs;
765 GString *buf;
766 Type1CEexecBuf eb;
767 GBool ok;
768 int fd, i, j, k;
770 // compute the CID count and build the CID-to-GID mapping
771 nCIDs = 0;
772 for (i = 0; i < nGlyphs; ++i) {
773 if (charset[i] >= nCIDs) {
774 nCIDs = charset[i] + 1;
777 cidMap = (int *)gmallocn(nCIDs, sizeof(int));
778 for (i = 0; i < nCIDs; ++i) {
779 cidMap[i] = -1;
781 for (i = 0; i < nGlyphs; ++i) {
782 cidMap[charset[i]] = i;
785 // write the descendant Type 1 fonts
786 for (i = 0; i < nCIDs; i += 256) {
788 //~ this assumes that all CIDs in this block have the same FD --
789 //~ to handle multiple FDs correctly, need to somehow divide the
790 //~ font up by FD; as a kludge we ignore CID 0, which is .notdef
791 fd = 0;
792 for (j = i==0 ? 1 : 0; j < 256 && i+j < nCIDs; ++j) {
793 if (cidMap[i+j] >= 0) {
794 fd = fdSelect[cidMap[i+j]];
795 break;
799 // font dictionary (unencrypted section)
800 (*outputFunc)(outputStream, "16 dict begin\n", 14);
801 (*outputFunc)(outputStream, "/FontName /", 11);
802 (*outputFunc)(outputStream, psName, strlen(psName));
803 buf = GString::format("_{0:02x} def\n", i >> 8);
804 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
805 delete buf;
806 (*outputFunc)(outputStream, "/FontType 1 def\n", 16);
807 if (privateDicts[fd].hasFontMatrix) {
808 buf = GString::format("/FontMatrix [{0:.8g} {1:.8g} {2:.8g} {3:.8g} {4:.8g} {5:.8g}] def\n",
809 privateDicts[fd].fontMatrix[0],
810 privateDicts[fd].fontMatrix[1],
811 privateDicts[fd].fontMatrix[2],
812 privateDicts[fd].fontMatrix[3],
813 privateDicts[fd].fontMatrix[4],
814 privateDicts[fd].fontMatrix[5]);
815 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
816 delete buf;
817 } else if (topDict.hasFontMatrix) {
818 (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
819 } else {
820 (*outputFunc)(outputStream,
821 "/FontMatrix [0.001 0 0 0.001 0 0] def\n", 38);
823 buf = GString::format("/FontBBox [{0:.4g} {1:.4g} {2:.4g} {3:.4g}] def\n",
824 topDict.fontBBox[0], topDict.fontBBox[1],
825 topDict.fontBBox[2], topDict.fontBBox[3]);
826 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
827 delete buf;
828 buf = GString::format("/PaintType {0:d} def\n", topDict.paintType);
829 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
830 delete buf;
831 if (topDict.paintType != 0) {
832 buf = GString::format("/StrokeWidth {0:.4g} def\n", topDict.strokeWidth);
833 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
834 delete buf;
836 (*outputFunc)(outputStream, "/Encoding 256 array\n", 20);
837 for (j = 0; j < 256 && i+j < nCIDs; ++j) {
838 buf = GString::format("dup {0:d} /c{1:02x} put\n", j, j);
839 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
840 delete buf;
842 if (j < 256) {
843 buf = GString::format("{0:d} 1 255 {{ 1 index exch /.notdef put }} for\n",
845 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
846 delete buf;
848 (*outputFunc)(outputStream, "readonly def\n", 13);
849 (*outputFunc)(outputStream, "currentdict end\n", 16);
851 // start the binary section
852 (*outputFunc)(outputStream, "currentfile eexec\n", 18);
853 eb.outputFunc = outputFunc;
854 eb.outputStream = outputStream;
855 eb.ascii = gTrue;
856 eb.r1 = 55665;
857 eb.line = 0;
859 // start the private dictionary
860 eexecWrite(&eb, "\x83\xca\x73\xd5");
861 eexecWrite(&eb, "dup /Private 32 dict dup begin\n");
862 eexecWrite(&eb, "/RD {string currentfile exch readstring pop}"
863 " executeonly def\n");
864 eexecWrite(&eb, "/ND {noaccess def} executeonly def\n");
865 eexecWrite(&eb, "/NP {noaccess put} executeonly def\n");
866 eexecWrite(&eb, "/MinFeature {16 16} def\n");
867 eexecWrite(&eb, "/password 5839 def\n");
868 if (privateDicts[fd].nBlueValues) {
869 eexecWrite(&eb, "/BlueValues [");
870 for (k = 0; k < privateDicts[fd].nBlueValues; ++k) {
871 buf = GString::format("{0:s}{1:d}",
872 k > 0 ? " " : "",
873 privateDicts[fd].blueValues[k]);
874 eexecWrite(&eb, buf->getCString());
875 delete buf;
877 eexecWrite(&eb, "] def\n");
879 if (privateDicts[fd].nOtherBlues) {
880 eexecWrite(&eb, "/OtherBlues [");
881 for (k = 0; k < privateDicts[fd].nOtherBlues; ++k) {
882 buf = GString::format("{0:s}{1:d}",
883 k > 0 ? " " : "",
884 privateDicts[fd].otherBlues[k]);
885 eexecWrite(&eb, buf->getCString());
886 delete buf;
888 eexecWrite(&eb, "] def\n");
890 if (privateDicts[fd].nFamilyBlues) {
891 eexecWrite(&eb, "/FamilyBlues [");
892 for (k = 0; k < privateDicts[fd].nFamilyBlues; ++k) {
893 buf = GString::format("{0:s}{1:d}", k > 0 ? " " : "",
894 privateDicts[fd].familyBlues[k]);
895 eexecWrite(&eb, buf->getCString());
896 delete buf;
898 eexecWrite(&eb, "] def\n");
900 if (privateDicts[fd].nFamilyOtherBlues) {
901 eexecWrite(&eb, "/FamilyOtherBlues [");
902 for (k = 0; k < privateDicts[fd].nFamilyOtherBlues; ++k) {
903 buf = GString::format("{0:s}{1:d}", k > 0 ? " " : "",
904 privateDicts[fd].familyOtherBlues[k]);
905 eexecWrite(&eb, buf->getCString());
906 delete buf;
908 eexecWrite(&eb, "] def\n");
910 if (privateDicts[fd].blueScale != 0.039625) {
911 buf = GString::format("/BlueScale {0:.4g} def\n",
912 privateDicts[fd].blueScale);
913 eexecWrite(&eb, buf->getCString());
914 delete buf;
916 if (privateDicts[fd].blueShift != 7) {
917 buf = GString::format("/BlueShift {0:d} def\n",
918 privateDicts[fd].blueShift);
919 eexecWrite(&eb, buf->getCString());
920 delete buf;
922 if (privateDicts[fd].blueFuzz != 1) {
923 buf = GString::format("/BlueFuzz {0:d} def\n",
924 privateDicts[fd].blueFuzz);
925 eexecWrite(&eb, buf->getCString());
926 delete buf;
928 if (privateDicts[fd].hasStdHW) {
929 buf = GString::format("/StdHW [{0:.4g}] def\n", privateDicts[fd].stdHW);
930 eexecWrite(&eb, buf->getCString());
931 delete buf;
933 if (privateDicts[fd].hasStdVW) {
934 buf = GString::format("/StdVW [{0:.4g}] def\n", privateDicts[fd].stdVW);
935 eexecWrite(&eb, buf->getCString());
936 delete buf;
938 if (privateDicts[fd].nStemSnapH) {
939 eexecWrite(&eb, "/StemSnapH [");
940 for (k = 0; k < privateDicts[fd].nStemSnapH; ++k) {
941 buf = GString::format("{0:s}{1:.4g}",
942 k > 0 ? " " : "", privateDicts[fd].stemSnapH[k]);
943 eexecWrite(&eb, buf->getCString());
944 delete buf;
946 eexecWrite(&eb, "] def\n");
948 if (privateDicts[fd].nStemSnapV) {
949 eexecWrite(&eb, "/StemSnapV [");
950 for (k = 0; k < privateDicts[fd].nStemSnapV; ++k) {
951 buf = GString::format("{0:s}{1:.4g}",
952 k > 0 ? " " : "", privateDicts[fd].stemSnapV[k]);
953 eexecWrite(&eb, buf->getCString());
954 delete buf;
956 eexecWrite(&eb, "] def\n");
958 if (privateDicts[fd].hasForceBold) {
959 buf = GString::format("/ForceBold {0:s} def\n",
960 privateDicts[fd].forceBold ? "true" : "false");
961 eexecWrite(&eb, buf->getCString());
962 delete buf;
964 if (privateDicts[fd].forceBoldThreshold != 0) {
965 buf = GString::format("/ForceBoldThreshold {0:.4g} def\n",
966 privateDicts[fd].forceBoldThreshold);
967 eexecWrite(&eb, buf->getCString());
968 delete buf;
970 if (privateDicts[fd].languageGroup != 0) {
971 buf = GString::format("/LanguageGroup {0:d} def\n",
972 privateDicts[fd].languageGroup);
973 eexecWrite(&eb, buf->getCString());
974 delete buf;
976 if (privateDicts[fd].expansionFactor != 0.06) {
977 buf = GString::format("/ExpansionFactor {0:.4g} def\n",
978 privateDicts[fd].expansionFactor);
979 eexecWrite(&eb, buf->getCString());
980 delete buf;
983 // set up the subroutines
984 ok = gTrue;
985 getIndex(privateDicts[fd].subrsOffset, &subrIdx, &ok);
986 if (!ok) {
987 subrIdx.pos = -1;
990 // start the CharStrings
991 eexecWrite(&eb, "2 index /CharStrings 256 dict dup begin\n");
993 // write the .notdef CharString
994 ok = gTrue;
995 getIndexVal(&charStringsIdx, 0, &val, &ok);
996 if (ok) {
997 eexecCvtGlyph(&eb, ".notdef", val.pos, val.len,
998 &subrIdx, &privateDicts[fd]);
1001 // write the CharStrings
1002 for (j = 0; j < 256 && i+j < nCIDs; ++j) {
1003 if (cidMap[i+j] >= 0) {
1004 ok = gTrue;
1005 getIndexVal(&charStringsIdx, cidMap[i+j], &val, &ok);
1006 if (ok) {
1007 buf = GString::format("c{0:02x}", j);
1008 eexecCvtGlyph(&eb, buf->getCString(), val.pos, val.len,
1009 &subrIdx, &privateDicts[fd]);
1010 delete buf;
1014 eexecWrite(&eb, "end\n");
1015 eexecWrite(&eb, "end\n");
1016 eexecWrite(&eb, "readonly put\n");
1017 eexecWrite(&eb, "noaccess put\n");
1018 eexecWrite(&eb, "dup /FontName get exch definefont pop\n");
1019 eexecWrite(&eb, "mark currentfile closefile\n");
1021 // trailer
1022 if (eb.line > 0) {
1023 (*outputFunc)(outputStream, "\n", 1);
1025 for (j = 0; j < 8; ++j) {
1026 (*outputFunc)(outputStream, "0000000000000000000000000000000000000000000000000000000000000000\n", 65);
1028 (*outputFunc)(outputStream, "cleartomark\n", 12);
1031 // write the Type 0 parent font
1032 (*outputFunc)(outputStream, "16 dict begin\n", 14);
1033 (*outputFunc)(outputStream, "/FontName /", 11);
1034 (*outputFunc)(outputStream, psName, strlen(psName));
1035 (*outputFunc)(outputStream, " def\n", 5);
1036 (*outputFunc)(outputStream, "/FontType 0 def\n", 16);
1037 if (topDict.hasFontMatrix) {
1038 buf = GString::format("/FontMatrix [{0:.8g} {1:.8g} {2:.8g} {3:.8g} {4:.8g} {5:.8g}] def\n",
1039 topDict.fontMatrix[0], topDict.fontMatrix[1],
1040 topDict.fontMatrix[2], topDict.fontMatrix[3],
1041 topDict.fontMatrix[4], topDict.fontMatrix[5]);
1042 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
1043 delete buf;
1044 } else {
1045 (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
1047 (*outputFunc)(outputStream, "/FMapType 2 def\n", 16);
1048 (*outputFunc)(outputStream, "/Encoding [\n", 12);
1049 for (i = 0; i < nCIDs; i += 256) {
1050 buf = GString::format("{0:d}\n", i >> 8);
1051 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
1052 delete buf;
1054 (*outputFunc)(outputStream, "] def\n", 6);
1055 (*outputFunc)(outputStream, "/FDepVector [\n", 14);
1056 for (i = 0; i < nCIDs; i += 256) {
1057 (*outputFunc)(outputStream, "/", 1);
1058 (*outputFunc)(outputStream, psName, strlen(psName));
1059 buf = GString::format("_{0:02x} findfont\n", i >> 8);
1060 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
1061 delete buf;
1063 (*outputFunc)(outputStream, "] def\n", 6);
1064 (*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40);
1066 gfree(cidMap);
1069 void FoFiType1C::eexecCvtGlyph(Type1CEexecBuf *eb, char *glyphName,
1070 int offset, int nBytes,
1071 Type1CIndex *subrIdx,
1072 Type1CPrivateDict *pDict) {
1073 GString *buf;
1074 GString *charBuf;
1076 // generate the charstring
1077 charBuf = new GString();
1078 cvtGlyph(offset, nBytes, charBuf, subrIdx, pDict, gTrue);
1080 buf = GString::format("/{0:s} {1:d} RD ", glyphName, charBuf->getLength());
1081 eexecWrite(eb, buf->getCString());
1082 delete buf;
1083 eexecWriteCharstring(eb, (Guchar *)charBuf->getCString(),
1084 charBuf->getLength());
1085 eexecWrite(eb, " ND\n");
1087 delete charBuf;
1090 void FoFiType1C::cvtGlyph(int offset, int nBytes, GString *charBuf,
1091 Type1CIndex *subrIdx, Type1CPrivateDict *pDict,
1092 GBool top) {
1093 Type1CIndexVal val;
1094 GBool ok, dFP;
1095 double d, dx, dy;
1096 Gushort r2;
1097 Guchar byte;
1098 int pos, subrBias, start, i, k;
1100 start = charBuf->getLength();
1101 if (top) {
1102 charBuf->append((char)73);
1103 charBuf->append((char)58);
1104 charBuf->append((char)147);
1105 charBuf->append((char)134);
1106 nOps = 0;
1107 nHints = 0;
1108 firstOp = gTrue;
1109 openPath = gFalse;
1112 pos = offset;
1113 while (pos < offset + nBytes) {
1114 ok = gTrue;
1115 pos = getOp(pos, gTrue, &ok);
1116 if (!ok) {
1117 break;
1119 if (!ops[nOps - 1].isNum) {
1120 --nOps; // drop the operator
1121 switch (ops[nOps].op) {
1122 case 0x0001: // hstem
1123 if (firstOp) {
1124 cvtGlyphWidth(nOps & 1, charBuf, pDict);
1125 firstOp = gFalse;
1127 if (nOps & 1) {
1128 //~ error(-1, "Wrong number of args (%d) to Type 2 hstem", nOps);
1130 d = 0;
1131 dFP = gFalse;
1132 for (k = 0; k < nOps; k += 2) {
1133 // convert Type 2 edge hints (-20 or -21) to Type 1 ghost hints
1134 if (ops[k+1].num < 0) {
1135 d += ops[k].num + ops[k+1].num;
1136 dFP |= ops[k].isFP | ops[k+1].isFP;
1137 cvtNum(d, dFP, charBuf);
1138 cvtNum(-ops[k+1].num, ops[k+1].isFP, charBuf);
1139 } else {
1140 d += ops[k].num;
1141 dFP |= ops[k].isFP;
1142 cvtNum(d, dFP, charBuf);
1143 cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
1144 d += ops[k+1].num;
1145 dFP |= ops[k+1].isFP;
1147 charBuf->append((char)1);
1149 nHints += nOps / 2;
1150 nOps = 0;
1151 break;
1152 case 0x0003: // vstem
1153 if (firstOp) {
1154 cvtGlyphWidth(nOps & 1, charBuf, pDict);
1155 firstOp = gFalse;
1157 if (nOps & 1) {
1158 //~ error(-1, "Wrong number of args (%d) to Type 2 vstem", nOps);
1160 d = 0;
1161 dFP = gFalse;
1162 for (k = 0; k < nOps; k += 2) {
1163 // convert Type 2 edge hints (-20 or -21) to Type 1 ghost hints
1164 if (ops[k+1].num < 0) {
1165 d += ops[k].num + ops[k+1].num;
1166 dFP |= ops[k].isFP | ops[k+1].isFP;
1167 cvtNum(d, dFP, charBuf);
1168 cvtNum(-ops[k+1].num, ops[k+1].isFP, charBuf);
1169 } else {
1170 d += ops[k].num;
1171 dFP |= ops[k].isFP;
1172 cvtNum(d, dFP, charBuf);
1173 cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
1174 d += ops[k+1].num;
1175 dFP |= ops[k+1].isFP;
1177 charBuf->append((char)3);
1179 nHints += nOps / 2;
1180 nOps = 0;
1181 break;
1182 case 0x0004: // vmoveto
1183 if (firstOp) {
1184 cvtGlyphWidth(nOps == 2, charBuf, pDict);
1185 firstOp = gFalse;
1187 if (openPath) {
1188 charBuf->append((char)9);
1189 openPath = gFalse;
1191 if (nOps != 1) {
1192 //~ error(-1, "Wrong number of args (%d) to Type 2 vmoveto", nOps);
1194 cvtNum(ops[0].num, ops[0].isFP, charBuf);
1195 charBuf->append((char)4);
1196 nOps = 0;
1197 break;
1198 case 0x0005: // rlineto
1199 if (nOps < 2 || nOps % 2 != 0) {
1200 //~ error(-1, "Wrong number of args (%d) to Type 2 rlineto", nOps);
1202 for (k = 0; k < nOps; k += 2) {
1203 cvtNum(ops[k].num, ops[k].isFP, charBuf);
1204 cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
1205 charBuf->append((char)5);
1207 nOps = 0;
1208 openPath = gTrue;
1209 break;
1210 case 0x0006: // hlineto
1211 if (nOps < 1) {
1212 //~ error(-1, "Wrong number of args (%d) to Type 2 hlineto", nOps);
1214 for (k = 0; k < nOps; ++k) {
1215 cvtNum(ops[k].num, ops[k].isFP, charBuf);
1216 charBuf->append((char)((k & 1) ? 7 : 6));
1218 nOps = 0;
1219 openPath = gTrue;
1220 break;
1221 case 0x0007: // vlineto
1222 if (nOps < 1) {
1223 //~ error(-1, "Wrong number of args (%d) to Type 2 vlineto", nOps);
1225 for (k = 0; k < nOps; ++k) {
1226 cvtNum(ops[k].num, ops[k].isFP, charBuf);
1227 charBuf->append((char)((k & 1) ? 6 : 7));
1229 nOps = 0;
1230 openPath = gTrue;
1231 break;
1232 case 0x0008: // rrcurveto
1233 if (nOps < 6 || nOps % 6 != 0) {
1234 //~ error(-1, "Wrong number of args (%d) to Type 2 rrcurveto", nOps);
1236 for (k = 0; k < nOps; k += 6) {
1237 cvtNum(ops[k].num, ops[k].isFP, charBuf);
1238 cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
1239 cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
1240 cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
1241 cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf);
1242 cvtNum(ops[k+5].num, ops[k+5].isFP, charBuf);
1243 charBuf->append((char)8);
1245 nOps = 0;
1246 openPath = gTrue;
1247 break;
1248 case 0x000a: // callsubr
1249 if (nOps >= 1) {
1250 subrBias = (subrIdx->len < 1240)
1251 ? 107 : (subrIdx->len < 33900) ? 1131 : 32768;
1252 k = subrBias + (int)ops[nOps - 1].num;
1253 --nOps;
1254 ok = gTrue;
1255 getIndexVal(subrIdx, k, &val, &ok);
1256 if (ok) {
1257 cvtGlyph(val.pos, val.len, charBuf, subrIdx, pDict, gFalse);
1259 } else {
1260 //~ error(-1, "Too few args to Type 2 callsubr");
1262 // don't clear the stack
1263 break;
1264 case 0x000b: // return
1265 // don't clear the stack
1266 break;
1267 case 0x000e: // endchar / seac
1268 if (firstOp) {
1269 cvtGlyphWidth(nOps == 1 || nOps == 5, charBuf, pDict);
1270 firstOp = gFalse;
1272 if (openPath) {
1273 charBuf->append((char)9);
1274 openPath = gFalse;
1276 if (nOps == 4) {
1277 cvtNum(0, gFalse, charBuf);
1278 cvtNum(ops[0].num, ops[0].isFP, charBuf);
1279 cvtNum(ops[1].num, ops[1].isFP, charBuf);
1280 cvtNum(ops[2].num, ops[2].isFP, charBuf);
1281 cvtNum(ops[3].num, ops[3].isFP, charBuf);
1282 charBuf->append((char)12)->append((char)6);
1283 } else if (nOps == 0) {
1284 charBuf->append((char)14);
1285 } else {
1286 //~ error(-1, "Wrong number of args (%d) to Type 2 endchar", nOps);
1288 nOps = 0;
1289 break;
1290 case 0x000f: // (obsolete)
1291 // this op is ignored, but we need the glyph width
1292 if (firstOp) {
1293 cvtGlyphWidth(nOps > 0, charBuf, pDict);
1294 firstOp = gFalse;
1296 nOps = 0;
1297 break;
1298 case 0x0010: // blend
1299 //~ error(-1, "Unimplemented Type 2 charstring op: %d", file[i]);
1300 nOps = 0;
1301 break;
1302 case 0x0012: // hstemhm
1303 // ignored
1304 if (firstOp) {
1305 cvtGlyphWidth(nOps & 1, charBuf, pDict);
1306 firstOp = gFalse;
1308 if (nOps & 1) {
1309 //~ error(-1, "Wrong number of args (%d) to Type 2 hstemhm", nOps);
1311 nHints += nOps / 2;
1312 nOps = 0;
1313 break;
1314 case 0x0013: // hintmask
1315 // ignored
1316 if (firstOp) {
1317 cvtGlyphWidth(nOps & 1, charBuf, pDict);
1318 firstOp = gFalse;
1320 if (nOps > 0) {
1321 if (nOps & 1) {
1322 //~ error(-1, "Wrong number of args (%d) to Type 2 hintmask/vstemhm",
1323 //~ nOps);
1325 nHints += nOps / 2;
1327 pos += (nHints + 7) >> 3;
1328 nOps = 0;
1329 break;
1330 case 0x0014: // cntrmask
1331 // ignored
1332 if (firstOp) {
1333 cvtGlyphWidth(nOps & 1, charBuf, pDict);
1334 firstOp = gFalse;
1336 if (nOps > 0) {
1337 if (nOps & 1) {
1338 //~ error(-1, "Wrong number of args (%d) to Type 2 cntrmask/vstemhm",
1339 //~ nOps);
1341 nHints += nOps / 2;
1343 pos += (nHints + 7) >> 3;
1344 nOps = 0;
1345 break;
1346 case 0x0015: // rmoveto
1347 if (firstOp) {
1348 cvtGlyphWidth(nOps == 3, charBuf, pDict);
1349 firstOp = gFalse;
1351 if (openPath) {
1352 charBuf->append((char)9);
1353 openPath = gFalse;
1355 if (nOps != 2) {
1356 //~ error(-1, "Wrong number of args (%d) to Type 2 rmoveto", nOps);
1358 cvtNum(ops[0].num, ops[0].isFP, charBuf);
1359 cvtNum(ops[1].num, ops[1].isFP, charBuf);
1360 charBuf->append((char)21);
1361 nOps = 0;
1362 break;
1363 case 0x0016: // hmoveto
1364 if (firstOp) {
1365 cvtGlyphWidth(nOps == 2, charBuf, pDict);
1366 firstOp = gFalse;
1368 if (openPath) {
1369 charBuf->append((char)9);
1370 openPath = gFalse;
1372 if (nOps != 1) {
1373 //~ error(-1, "Wrong number of args (%d) to Type 2 hmoveto", nOps);
1375 cvtNum(ops[0].num, ops[0].isFP, charBuf);
1376 charBuf->append((char)22);
1377 nOps = 0;
1378 break;
1379 case 0x0017: // vstemhm
1380 // ignored
1381 if (firstOp) {
1382 cvtGlyphWidth(nOps & 1, charBuf, pDict);
1383 firstOp = gFalse;
1385 if (nOps & 1) {
1386 //~ error(-1, "Wrong number of args (%d) to Type 2 vstemhm", nOps);
1388 nHints += nOps / 2;
1389 nOps = 0;
1390 break;
1391 case 0x0018: // rcurveline
1392 if (nOps < 8 || (nOps - 2) % 6 != 0) {
1393 //~ error(-1, "Wrong number of args (%d) to Type 2 rcurveline", nOps);
1395 for (k = 0; k < nOps - 2; k += 6) {
1396 cvtNum(ops[k].num, ops[k].isFP, charBuf);
1397 cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
1398 cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
1399 cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
1400 cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf);
1401 cvtNum(ops[k+5].num, ops[k+5].isFP, charBuf);
1402 charBuf->append((char)8);
1404 cvtNum(ops[k].num, ops[k].isFP, charBuf);
1405 cvtNum(ops[k+1].num, ops[k].isFP, charBuf);
1406 charBuf->append((char)5);
1407 nOps = 0;
1408 openPath = gTrue;
1409 break;
1410 case 0x0019: // rlinecurve
1411 if (nOps < 8 || (nOps - 6) % 2 != 0) {
1412 //~ error(-1, "Wrong number of args (%d) to Type 2 rlinecurve", nOps);
1414 for (k = 0; k < nOps - 6; k += 2) {
1415 cvtNum(ops[k].num, ops[k].isFP, charBuf);
1416 cvtNum(ops[k+1].num, ops[k].isFP, charBuf);
1417 charBuf->append((char)5);
1419 cvtNum(ops[k].num, ops[k].isFP, charBuf);
1420 cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
1421 cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
1422 cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
1423 cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf);
1424 cvtNum(ops[k+5].num, ops[k+5].isFP, charBuf);
1425 charBuf->append((char)8);
1426 nOps = 0;
1427 openPath = gTrue;
1428 break;
1429 case 0x001a: // vvcurveto
1430 if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
1431 //~ error(-1, "Wrong number of args (%d) to Type 2 vvcurveto", nOps);
1433 if (nOps % 2 == 1) {
1434 cvtNum(ops[0].num, ops[0].isFP, charBuf);
1435 cvtNum(ops[1].num, ops[1].isFP, charBuf);
1436 cvtNum(ops[2].num, ops[2].isFP, charBuf);
1437 cvtNum(ops[3].num, ops[3].isFP, charBuf);
1438 cvtNum(0, gFalse, charBuf);
1439 cvtNum(ops[4].num, ops[4].isFP, charBuf);
1440 charBuf->append((char)8);
1441 k = 5;
1442 } else {
1443 k = 0;
1445 for (; k < nOps; k += 4) {
1446 cvtNum(0, gFalse, charBuf);
1447 cvtNum(ops[k].num, ops[k].isFP, charBuf);
1448 cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
1449 cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
1450 cvtNum(0, gFalse, charBuf);
1451 cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
1452 charBuf->append((char)8);
1454 nOps = 0;
1455 openPath = gTrue;
1456 break;
1457 case 0x001b: // hhcurveto
1458 if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
1459 //~ error(-1, "Wrong number of args (%d) to Type 2 hhcurveto", nOps);
1461 if (nOps % 2 == 1) {
1462 cvtNum(ops[1].num, ops[1].isFP, charBuf);
1463 cvtNum(ops[0].num, ops[0].isFP, charBuf);
1464 cvtNum(ops[2].num, ops[2].isFP, charBuf);
1465 cvtNum(ops[3].num, ops[3].isFP, charBuf);
1466 cvtNum(ops[4].num, ops[4].isFP, charBuf);
1467 cvtNum(0, gFalse, charBuf);
1468 charBuf->append((char)8);
1469 k = 5;
1470 } else {
1471 k = 0;
1473 for (; k < nOps; k += 4) {
1474 cvtNum(ops[k].num, ops[k].isFP, charBuf);
1475 cvtNum(0, gFalse, charBuf);
1476 cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
1477 cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
1478 cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
1479 cvtNum(0, gFalse, charBuf);
1480 charBuf->append((char)8);
1482 nOps = 0;
1483 openPath = gTrue;
1484 break;
1485 case 0x001d: // callgsubr
1486 if (nOps >= 1) {
1487 k = gsubrBias + (int)ops[nOps - 1].num;
1488 --nOps;
1489 ok = gTrue;
1490 getIndexVal(&gsubrIdx, k, &val, &ok);
1491 if (ok) {
1492 cvtGlyph(val.pos, val.len, charBuf, subrIdx, pDict, gFalse);
1494 } else {
1495 //~ error(-1, "Too few args to Type 2 callgsubr");
1497 // don't clear the stack
1498 break;
1499 case 0x001e: // vhcurveto
1500 if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
1501 //~ error(-1, "Wrong number of args (%d) to Type 2 vhcurveto", nOps);
1503 for (k = 0; k < nOps && k != nOps-5; k += 4) {
1504 if (k % 8 == 0) {
1505 cvtNum(ops[k].num, ops[k].isFP, charBuf);
1506 cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
1507 cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
1508 cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
1509 charBuf->append((char)30);
1510 } else {
1511 cvtNum(ops[k].num, ops[k].isFP, charBuf);
1512 cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
1513 cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
1514 cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
1515 charBuf->append((char)31);
1518 if (k == nOps-5) {
1519 if (k % 8 == 0) {
1520 cvtNum(0, gFalse, charBuf);
1521 cvtNum(ops[k].num, ops[k].isFP, charBuf);
1522 cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
1523 cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
1524 cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
1525 cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf);
1526 } else {
1527 cvtNum(ops[k].num, ops[k].isFP, charBuf);
1528 cvtNum(0, gFalse, charBuf);
1529 cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
1530 cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
1531 cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf);
1532 cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
1534 charBuf->append((char)8);
1536 nOps = 0;
1537 openPath = gTrue;
1538 break;
1539 case 0x001f: // hvcurveto
1540 if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
1541 //~ error(-1, "Wrong number of args (%d) to Type 2 hvcurveto", nOps);
1543 for (k = 0; k < nOps && k != nOps-5; k += 4) {
1544 if (k % 8 == 0) {
1545 cvtNum(ops[k].num, ops[k].isFP, charBuf);
1546 cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
1547 cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
1548 cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
1549 charBuf->append((char)31);
1550 } else {
1551 cvtNum(ops[k].num, ops[k].isFP, charBuf);
1552 cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
1553 cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
1554 cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
1555 charBuf->append((char)30);
1558 if (k == nOps-5) {
1559 if (k % 8 == 0) {
1560 cvtNum(ops[k].num, ops[k].isFP, charBuf);
1561 cvtNum(0, gFalse, charBuf);
1562 cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
1563 cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
1564 cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf);
1565 cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
1566 } else {
1567 cvtNum(0, gFalse, charBuf);
1568 cvtNum(ops[k].num, ops[k].isFP, charBuf);
1569 cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
1570 cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
1571 cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
1572 cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf);
1574 charBuf->append((char)8);
1576 nOps = 0;
1577 openPath = gTrue;
1578 break;
1579 case 0x0c00: // dotsection (should be Type 1 only?)
1580 // ignored
1581 nOps = 0;
1582 break;
1583 case 0x0c03: // and
1584 case 0x0c04: // or
1585 case 0x0c05: // not
1586 case 0x0c08: // store
1587 case 0x0c09: // abs
1588 case 0x0c0a: // add
1589 case 0x0c0b: // sub
1590 case 0x0c0c: // div
1591 case 0x0c0d: // load
1592 case 0x0c0e: // neg
1593 case 0x0c0f: // eq
1594 case 0x0c12: // drop
1595 case 0x0c14: // put
1596 case 0x0c15: // get
1597 case 0x0c16: // ifelse
1598 case 0x0c17: // random
1599 case 0x0c18: // mul
1600 case 0x0c1a: // sqrt
1601 case 0x0c1b: // dup
1602 case 0x0c1c: // exch
1603 case 0x0c1d: // index
1604 case 0x0c1e: // roll
1605 //~ error(-1, "Unimplemented Type 2 charstring op: 12.%d", file[i+1]);
1606 nOps = 0;
1607 break;
1608 case 0x0c22: // hflex
1609 if (nOps != 7) {
1610 //~ error(-1, "Wrong number of args (%d) to Type 2 hflex", nOps);
1612 cvtNum(ops[0].num, ops[0].isFP, charBuf);
1613 cvtNum(0, gFalse, charBuf);
1614 cvtNum(ops[1].num, ops[1].isFP, charBuf);
1615 cvtNum(ops[2].num, ops[2].isFP, charBuf);
1616 cvtNum(ops[3].num, ops[3].isFP, charBuf);
1617 cvtNum(0, gFalse, charBuf);
1618 charBuf->append((char)8);
1619 cvtNum(ops[4].num, ops[4].isFP, charBuf);
1620 cvtNum(0, gFalse, charBuf);
1621 cvtNum(ops[5].num, ops[5].isFP, charBuf);
1622 cvtNum(-ops[2].num, ops[2].isFP, charBuf);
1623 cvtNum(ops[6].num, ops[6].isFP, charBuf);
1624 cvtNum(0, gFalse, charBuf);
1625 charBuf->append((char)8);
1626 nOps = 0;
1627 openPath = gTrue;
1628 break;
1629 case 0x0c23: // flex
1630 if (nOps != 13) {
1631 //~ error(-1, "Wrong number of args (%d) to Type 2 flex", nOps);
1633 cvtNum(ops[0].num, ops[0].isFP, charBuf);
1634 cvtNum(ops[1].num, ops[1].isFP, charBuf);
1635 cvtNum(ops[2].num, ops[2].isFP, charBuf);
1636 cvtNum(ops[3].num, ops[3].isFP, charBuf);
1637 cvtNum(ops[4].num, ops[4].isFP, charBuf);
1638 cvtNum(ops[5].num, ops[5].isFP, charBuf);
1639 charBuf->append((char)8);
1640 cvtNum(ops[6].num, ops[6].isFP, charBuf);
1641 cvtNum(ops[7].num, ops[7].isFP, charBuf);
1642 cvtNum(ops[8].num, ops[8].isFP, charBuf);
1643 cvtNum(ops[9].num, ops[9].isFP, charBuf);
1644 cvtNum(ops[10].num, ops[10].isFP, charBuf);
1645 cvtNum(ops[11].num, ops[11].isFP, charBuf);
1646 charBuf->append((char)8);
1647 nOps = 0;
1648 openPath = gTrue;
1649 break;
1650 case 0x0c24: // hflex1
1651 if (nOps != 9) {
1652 //~ error(-1, "Wrong number of args (%d) to Type 2 hflex1", nOps);
1654 cvtNum(ops[0].num, ops[0].isFP, charBuf);
1655 cvtNum(ops[1].num, ops[1].isFP, charBuf);
1656 cvtNum(ops[2].num, ops[2].isFP, charBuf);
1657 cvtNum(ops[3].num, ops[3].isFP, charBuf);
1658 cvtNum(ops[4].num, ops[4].isFP, charBuf);
1659 cvtNum(0, gFalse, charBuf);
1660 charBuf->append((char)8);
1661 cvtNum(ops[5].num, ops[5].isFP, charBuf);
1662 cvtNum(0, gFalse, charBuf);
1663 cvtNum(ops[6].num, ops[6].isFP, charBuf);
1664 cvtNum(ops[7].num, ops[7].isFP, charBuf);
1665 cvtNum(ops[8].num, ops[8].isFP, charBuf);
1666 cvtNum(-(ops[1].num + ops[3].num + ops[7].num),
1667 ops[1].isFP | ops[3].isFP | ops[7].isFP, charBuf);
1668 charBuf->append((char)8);
1669 nOps = 0;
1670 openPath = gTrue;
1671 break;
1672 case 0x0c25: // flex1
1673 if (nOps != 11) {
1674 //~ error(-1, "Wrong number of args (%d) to Type 2 flex1", nOps);
1676 cvtNum(ops[0].num, ops[0].isFP, charBuf);
1677 cvtNum(ops[1].num, ops[1].isFP, charBuf);
1678 cvtNum(ops[2].num, ops[2].isFP, charBuf);
1679 cvtNum(ops[3].num, ops[3].isFP, charBuf);
1680 cvtNum(ops[4].num, ops[4].isFP, charBuf);
1681 cvtNum(ops[5].num, ops[5].isFP, charBuf);
1682 charBuf->append((char)8);
1683 cvtNum(ops[6].num, ops[6].isFP, charBuf);
1684 cvtNum(ops[7].num, ops[7].isFP, charBuf);
1685 cvtNum(ops[8].num, ops[8].isFP, charBuf);
1686 cvtNum(ops[9].num, ops[9].isFP, charBuf);
1687 dx = ops[0].num + ops[2].num + ops[4].num + ops[6].num + ops[8].num;
1688 dy = ops[1].num + ops[3].num + ops[5].num + ops[7].num + ops[9].num;
1689 if (fabs(dx) > fabs(dy)) {
1690 cvtNum(ops[10].num, ops[10].isFP, charBuf);
1691 cvtNum(-dy, ops[1].isFP | ops[3].isFP | ops[5].isFP |
1692 ops[7].isFP | ops[9].isFP, charBuf);
1693 } else {
1694 cvtNum(-dx, ops[0].isFP | ops[2].isFP | ops[4].isFP |
1695 ops[6].isFP | ops[8].isFP, charBuf);
1696 cvtNum(ops[10].num, ops[10].isFP, charBuf);
1698 charBuf->append((char)8);
1699 nOps = 0;
1700 openPath = gTrue;
1701 break;
1702 default:
1703 //~ error(-1, "Illegal Type 2 charstring op: %04x",
1704 //~ ops[nOps].op);
1705 nOps = 0;
1706 break;
1711 // charstring encryption
1712 if (top) {
1713 r2 = 4330;
1714 for (i = start; i < charBuf->getLength(); ++i) {
1715 byte = charBuf->getChar(i) ^ (r2 >> 8);
1716 charBuf->setChar(i, byte);
1717 r2 = (byte + r2) * 52845 + 22719;
1722 void FoFiType1C::cvtGlyphWidth(GBool useOp, GString *charBuf,
1723 Type1CPrivateDict *pDict) {
1724 double w;
1725 GBool wFP;
1726 int i;
1728 if (useOp) {
1729 w = pDict->nominalWidthX + ops[0].num;
1730 wFP = pDict->nominalWidthXFP | ops[0].isFP;
1731 for (i = 1; i < nOps; ++i) {
1732 ops[i-1] = ops[i];
1734 --nOps;
1735 } else {
1736 w = pDict->defaultWidthX;
1737 wFP = pDict->defaultWidthXFP;
1739 cvtNum(0, gFalse, charBuf);
1740 cvtNum(w, wFP, charBuf);
1741 charBuf->append((char)13);
1744 void FoFiType1C::cvtNum(double x, GBool isFP, GString *charBuf) {
1745 Guchar buf[12];
1746 int y, n;
1748 n = 0;
1749 if (isFP) {
1750 if (x >= -32768 && x < 32768) {
1751 y = (int)(x * 256.0);
1752 buf[0] = 255;
1753 buf[1] = (Guchar)(y >> 24);
1754 buf[2] = (Guchar)(y >> 16);
1755 buf[3] = (Guchar)(y >> 8);
1756 buf[4] = (Guchar)y;
1757 buf[5] = 255;
1758 buf[6] = 0;
1759 buf[7] = 0;
1760 buf[8] = 1;
1761 buf[9] = 0;
1762 buf[10] = 12;
1763 buf[11] = 12;
1764 n = 12;
1765 } else {
1766 //~ error(-1, "Type 2 fixed point constant out of range");
1768 } else {
1769 y = (int)x;
1770 if (y >= -107 && y <= 107) {
1771 buf[0] = (Guchar)(y + 139);
1772 n = 1;
1773 } else if (y > 107 && y <= 1131) {
1774 y -= 108;
1775 buf[0] = (Guchar)((y >> 8) + 247);
1776 buf[1] = (Guchar)(y & 0xff);
1777 n = 2;
1778 } else if (y < -107 && y >= -1131) {
1779 y = -y - 108;
1780 buf[0] = (Guchar)((y >> 8) + 251);
1781 buf[1] = (Guchar)(y & 0xff);
1782 n = 2;
1783 } else {
1784 buf[0] = 255;
1785 buf[1] = (Guchar)(y >> 24);
1786 buf[2] = (Guchar)(y >> 16);
1787 buf[3] = (Guchar)(y >> 8);
1788 buf[4] = (Guchar)y;
1789 n = 5;
1792 charBuf->append((char *)buf, n);
1795 void FoFiType1C::eexecWrite(Type1CEexecBuf *eb, char *s) {
1796 Guchar *p;
1797 Guchar x;
1799 for (p = (Guchar *)s; *p; ++p) {
1800 x = *p ^ (eb->r1 >> 8);
1801 eb->r1 = (x + eb->r1) * 52845 + 22719;
1802 if (eb->ascii) {
1803 (*eb->outputFunc)(eb->outputStream, &hexChars[x >> 4], 1);
1804 (*eb->outputFunc)(eb->outputStream, &hexChars[x & 0x0f], 1);
1805 eb->line += 2;
1806 if (eb->line == 64) {
1807 (*eb->outputFunc)(eb->outputStream, "\n", 1);
1808 eb->line = 0;
1810 } else {
1811 (*eb->outputFunc)(eb->outputStream, (char *)&x, 1);
1816 void FoFiType1C::eexecWriteCharstring(Type1CEexecBuf *eb,
1817 Guchar *s, int n) {
1818 Guchar x;
1819 int i;
1821 // eexec encryption
1822 for (i = 0; i < n; ++i) {
1823 x = s[i] ^ (eb->r1 >> 8);
1824 eb->r1 = (x + eb->r1) * 52845 + 22719;
1825 if (eb->ascii) {
1826 (*eb->outputFunc)(eb->outputStream, &hexChars[x >> 4], 1);
1827 (*eb->outputFunc)(eb->outputStream, &hexChars[x & 0x0f], 1);
1828 eb->line += 2;
1829 if (eb->line == 64) {
1830 (*eb->outputFunc)(eb->outputStream, "\n", 1);
1831 eb->line = 0;
1833 } else {
1834 (*eb->outputFunc)(eb->outputStream, (char *)&x, 1);
1839 GBool FoFiType1C::parse() {
1840 Type1CIndex fdIdx;
1841 Type1CIndexVal val;
1842 int i;
1844 parsedOk = gTrue;
1846 // some tools embed Type 1C fonts with an extra whitespace char at
1847 // the beginning
1848 if (len > 0 && file[0] != '\x01') {
1849 ++file;
1850 --len;
1853 // find the indexes
1854 getIndex(getU8(2, &parsedOk), &nameIdx, &parsedOk);
1855 getIndex(nameIdx.endPos, &topDictIdx, &parsedOk);
1856 getIndex(topDictIdx.endPos, &stringIdx, &parsedOk);
1857 getIndex(stringIdx.endPos, &gsubrIdx, &parsedOk);
1858 if (!parsedOk) {
1859 return gFalse;
1861 gsubrBias = (gsubrIdx.len < 1240) ? 107
1862 : (gsubrIdx.len < 33900) ? 1131 : 32768;
1864 // read the first font name
1865 getIndexVal(&nameIdx, 0, &val, &parsedOk);
1866 if (!parsedOk) {
1867 return gFalse;
1869 name = new GString((char *)&file[val.pos], val.len);
1871 // read the top dict for the first font
1872 readTopDict();
1874 // for CID fonts: read the FDArray dicts and private dicts
1875 if (topDict.firstOp == 0x0c1e) {
1876 if (topDict.fdArrayOffset == 0) {
1877 nFDs = 1;
1878 privateDicts = (Type1CPrivateDict *)gmalloc(sizeof(Type1CPrivateDict));
1879 readPrivateDict(0, 0, &privateDicts[0]);
1880 } else {
1881 getIndex(topDict.fdArrayOffset, &fdIdx, &parsedOk);
1882 if (!parsedOk) {
1883 return gFalse;
1885 nFDs = fdIdx.len;
1886 privateDicts = (Type1CPrivateDict *)
1887 gmallocn(nFDs, sizeof(Type1CPrivateDict));
1888 for (i = 0; i < nFDs; ++i) {
1889 getIndexVal(&fdIdx, i, &val, &parsedOk);
1890 if (!parsedOk) {
1891 return gFalse;
1893 readFD(val.pos, val.len, &privateDicts[i]);
1897 // for 8-bit fonts: read the private dict
1898 } else {
1899 privateDicts = (Type1CPrivateDict *)gmalloc(sizeof(Type1CPrivateDict));
1900 readPrivateDict(topDict.privateOffset, topDict.privateSize,
1901 &privateDicts[0]);
1904 // check for parse errors in the private dict(s)
1905 if (!parsedOk) {
1906 return gFalse;
1909 // get the charstrings index
1910 if (topDict.charStringsOffset <= 0) {
1911 parsedOk = gFalse;
1912 return gFalse;
1914 getIndex(topDict.charStringsOffset, &charStringsIdx, &parsedOk);
1915 if (!parsedOk) {
1916 return gFalse;
1918 nGlyphs = charStringsIdx.len;
1920 // for CID fonts: read the FDSelect table
1921 if (topDict.firstOp == 0x0c1e) {
1922 readFDSelect();
1923 if (!parsedOk) {
1924 return gFalse;
1928 // read the charset
1929 if (!readCharset()) {
1930 parsedOk = gFalse;
1931 return gFalse;
1934 // for 8-bit fonts: build the encoding
1935 if (topDict.firstOp != 0x0c14 && topDict.firstOp != 0x0c1e) {
1936 buildEncoding();
1937 if (!parsedOk) {
1938 return gFalse;
1942 return parsedOk;
1945 void FoFiType1C::readTopDict() {
1946 Type1CIndexVal topDictPtr;
1947 int pos;
1949 topDict.firstOp = -1;
1950 topDict.versionSID = 0;
1951 topDict.noticeSID = 0;
1952 topDict.copyrightSID = 0;
1953 topDict.fullNameSID = 0;
1954 topDict.familyNameSID = 0;
1955 topDict.weightSID = 0;
1956 topDict.isFixedPitch = 0;
1957 topDict.italicAngle = 0;
1958 topDict.underlinePosition = -100;
1959 topDict.underlineThickness = 50;
1960 topDict.paintType = 0;
1961 topDict.charstringType = 2;
1962 topDict.fontMatrix[0] = 0.001;
1963 topDict.fontMatrix[1] = 0;
1964 topDict.fontMatrix[2] = 0;
1965 topDict.fontMatrix[3] = 0.001;
1966 topDict.fontMatrix[4] = 0;
1967 topDict.fontMatrix[5] = 0;
1968 topDict.hasFontMatrix = gFalse;
1969 topDict.uniqueID = 0;
1970 topDict.fontBBox[0] = 0;
1971 topDict.fontBBox[1] = 0;
1972 topDict.fontBBox[2] = 0;
1973 topDict.fontBBox[3] = 0;
1974 topDict.strokeWidth = 0;
1975 topDict.charsetOffset = 0;
1976 topDict.encodingOffset = 0;
1977 topDict.charStringsOffset = 0;
1978 topDict.privateSize = 0;
1979 topDict.privateOffset = 0;
1980 topDict.registrySID = 0;
1981 topDict.orderingSID = 0;
1982 topDict.supplement = 0;
1983 topDict.fdArrayOffset = 0;
1984 topDict.fdSelectOffset = 0;
1986 getIndexVal(&topDictIdx, 0, &topDictPtr, &parsedOk);
1987 pos = topDictPtr.pos;
1988 nOps = 0;
1989 while (pos < topDictPtr.pos + topDictPtr.len) {
1990 pos = getOp(pos, gFalse, &parsedOk);
1991 if (!parsedOk) {
1992 break;
1994 if (!ops[nOps - 1].isNum) {
1995 --nOps; // drop the operator
1996 if (topDict.firstOp < 0) {
1997 topDict.firstOp = ops[nOps].op;
1999 switch (ops[nOps].op) {
2000 case 0x0000: topDict.versionSID = (int)ops[0].num; break;
2001 case 0x0001: topDict.noticeSID = (int)ops[0].num; break;
2002 case 0x0c00: topDict.copyrightSID = (int)ops[0].num; break;
2003 case 0x0002: topDict.fullNameSID = (int)ops[0].num; break;
2004 case 0x0003: topDict.familyNameSID = (int)ops[0].num; break;
2005 case 0x0004: topDict.weightSID = (int)ops[0].num; break;
2006 case 0x0c01: topDict.isFixedPitch = (int)ops[0].num; break;
2007 case 0x0c02: topDict.italicAngle = ops[0].num; break;
2008 case 0x0c03: topDict.underlinePosition = ops[0].num; break;
2009 case 0x0c04: topDict.underlineThickness = ops[0].num; break;
2010 case 0x0c05: topDict.paintType = (int)ops[0].num; break;
2011 case 0x0c06: topDict.charstringType = (int)ops[0].num; break;
2012 case 0x0c07: topDict.fontMatrix[0] = ops[0].num;
2013 topDict.fontMatrix[1] = ops[1].num;
2014 topDict.fontMatrix[2] = ops[2].num;
2015 topDict.fontMatrix[3] = ops[3].num;
2016 topDict.fontMatrix[4] = ops[4].num;
2017 topDict.fontMatrix[5] = ops[5].num;
2018 topDict.hasFontMatrix = gTrue; break;
2019 case 0x000d: topDict.uniqueID = (int)ops[0].num; break;
2020 case 0x0005: topDict.fontBBox[0] = ops[0].num;
2021 topDict.fontBBox[1] = ops[1].num;
2022 topDict.fontBBox[2] = ops[2].num;
2023 topDict.fontBBox[3] = ops[3].num; break;
2024 case 0x0c08: topDict.strokeWidth = ops[0].num; break;
2025 case 0x000f: topDict.charsetOffset = (int)ops[0].num; break;
2026 case 0x0010: topDict.encodingOffset = (int)ops[0].num; break;
2027 case 0x0011: topDict.charStringsOffset = (int)ops[0].num; break;
2028 case 0x0012: topDict.privateSize = (int)ops[0].num;
2029 topDict.privateOffset = (int)ops[1].num; break;
2030 case 0x0c1e: topDict.registrySID = (int)ops[0].num;
2031 topDict.orderingSID = (int)ops[1].num;
2032 topDict.supplement = (int)ops[2].num; break;
2033 case 0x0c24: topDict.fdArrayOffset = (int)ops[0].num; break;
2034 case 0x0c25: topDict.fdSelectOffset = (int)ops[0].num; break;
2036 nOps = 0;
2041 // Read a CID font dict (FD) - this pulls out the private dict
2042 // pointer, and reads the private dict. It also pulls the FontMatrix
2043 // (if any) out of the FD.
2044 void FoFiType1C::readFD(int offset, int length, Type1CPrivateDict *pDict) {
2045 int pos, pSize, pOffset;
2046 double fontMatrix[6];
2047 GBool hasFontMatrix;
2049 hasFontMatrix = gFalse;
2050 pSize = pOffset = 0;
2051 pos = offset;
2052 nOps = 0;
2053 while (pos < offset + length) {
2054 pos = getOp(pos, gFalse, &parsedOk);
2055 if (!parsedOk) {
2056 return;
2058 if (!ops[nOps - 1].isNum) {
2059 if (ops[nOps - 1].op == 0x0012) {
2060 if (nOps < 3) {
2061 parsedOk = gFalse;
2062 return;
2064 pSize = (int)ops[0].num;
2065 pOffset = (int)ops[1].num;
2066 break;
2067 } else if (ops[nOps - 1].op == 0x0c07) {
2068 fontMatrix[0] = ops[0].num;
2069 fontMatrix[1] = ops[1].num;
2070 fontMatrix[2] = ops[2].num;
2071 fontMatrix[3] = ops[3].num;
2072 fontMatrix[4] = ops[4].num;
2073 fontMatrix[5] = ops[5].num;
2074 hasFontMatrix = gTrue;
2076 nOps = 0;
2079 readPrivateDict(pOffset, pSize, pDict);
2080 if (hasFontMatrix) {
2081 pDict->fontMatrix[0] = fontMatrix[0];
2082 pDict->fontMatrix[1] = fontMatrix[1];
2083 pDict->fontMatrix[2] = fontMatrix[2];
2084 pDict->fontMatrix[3] = fontMatrix[3];
2085 pDict->fontMatrix[4] = fontMatrix[4];
2086 pDict->fontMatrix[5] = fontMatrix[5];
2087 pDict->hasFontMatrix = gTrue;
2091 void FoFiType1C::readPrivateDict(int offset, int length,
2092 Type1CPrivateDict *pDict) {
2093 int pos;
2095 pDict->hasFontMatrix = gFalse;
2096 pDict->nBlueValues = 0;
2097 pDict->nOtherBlues = 0;
2098 pDict->nFamilyBlues = 0;
2099 pDict->nFamilyOtherBlues = 0;
2100 pDict->blueScale = 0.039625;
2101 pDict->blueShift = 7;
2102 pDict->blueFuzz = 1;
2103 pDict->hasStdHW = gFalse;
2104 pDict->hasStdVW = gFalse;
2105 pDict->nStemSnapH = 0;
2106 pDict->nStemSnapV = 0;
2107 pDict->hasForceBold = gFalse;
2108 pDict->forceBoldThreshold = 0;
2109 pDict->languageGroup = 0;
2110 pDict->expansionFactor = 0.06;
2111 pDict->initialRandomSeed = 0;
2112 pDict->subrsOffset = 0;
2113 pDict->defaultWidthX = 0;
2114 pDict->defaultWidthXFP = gFalse;
2115 pDict->nominalWidthX = 0;
2116 pDict->nominalWidthXFP = gFalse;
2118 // no dictionary
2119 if (offset == 0 || length == 0) {
2120 return;
2123 pos = offset;
2124 nOps = 0;
2125 while (pos < offset + length) {
2126 pos = getOp(pos, gFalse, &parsedOk);
2127 if (!parsedOk) {
2128 break;
2130 if (!ops[nOps - 1].isNum) {
2131 --nOps; // drop the operator
2132 switch (ops[nOps].op) {
2133 case 0x0006:
2134 pDict->nBlueValues = getDeltaIntArray(pDict->blueValues,
2135 type1CMaxBlueValues);
2136 break;
2137 case 0x0007:
2138 pDict->nOtherBlues = getDeltaIntArray(pDict->otherBlues,
2139 type1CMaxOtherBlues);
2140 break;
2141 case 0x0008:
2142 pDict->nFamilyBlues = getDeltaIntArray(pDict->familyBlues,
2143 type1CMaxBlueValues);
2144 break;
2145 case 0x0009:
2146 pDict->nFamilyOtherBlues = getDeltaIntArray(pDict->familyOtherBlues,
2147 type1CMaxOtherBlues);
2148 break;
2149 case 0x0c09:
2150 pDict->blueScale = ops[0].num;
2151 break;
2152 case 0x0c0a:
2153 pDict->blueShift = (int)ops[0].num;
2154 break;
2155 case 0x0c0b:
2156 pDict->blueFuzz = (int)ops[0].num;
2157 break;
2158 case 0x000a:
2159 pDict->stdHW = ops[0].num;
2160 pDict->hasStdHW = gTrue;
2161 break;
2162 case 0x000b:
2163 pDict->stdVW = ops[0].num;
2164 pDict->hasStdVW = gTrue;
2165 break;
2166 case 0x0c0c:
2167 pDict->nStemSnapH = getDeltaFPArray(pDict->stemSnapH,
2168 type1CMaxStemSnap);
2169 break;
2170 case 0x0c0d:
2171 pDict->nStemSnapV = getDeltaFPArray(pDict->stemSnapV,
2172 type1CMaxStemSnap);
2173 break;
2174 case 0x0c0e:
2175 pDict->forceBold = ops[0].num != 0;
2176 pDict->hasForceBold = gTrue;
2177 break;
2178 case 0x0c0f:
2179 pDict->forceBoldThreshold = ops[0].num;
2180 break;
2181 case 0x0c11:
2182 pDict->languageGroup = (int)ops[0].num;
2183 break;
2184 case 0x0c12:
2185 pDict->expansionFactor = ops[0].num;
2186 break;
2187 case 0x0c13:
2188 pDict->initialRandomSeed = (int)ops[0].num;
2189 break;
2190 case 0x0013:
2191 pDict->subrsOffset = offset + (int)ops[0].num;
2192 break;
2193 case 0x0014:
2194 pDict->defaultWidthX = ops[0].num;
2195 pDict->defaultWidthXFP = ops[0].isFP;
2196 break;
2197 case 0x0015:
2198 pDict->nominalWidthX = ops[0].num;
2199 pDict->nominalWidthXFP = ops[0].isFP;
2200 break;
2202 nOps = 0;
2207 void FoFiType1C::readFDSelect() {
2208 int fdSelectFmt, pos, nRanges, gid0, gid1, fd, i, j;
2210 fdSelect = (Guchar *)gmalloc(nGlyphs);
2211 if (topDict.fdSelectOffset == 0) {
2212 for (i = 0; i < nGlyphs; ++i) {
2213 fdSelect[i] = 0;
2215 } else {
2216 pos = topDict.fdSelectOffset;
2217 fdSelectFmt = getU8(pos++, &parsedOk);
2218 if (!parsedOk) {
2219 return;
2221 if (fdSelectFmt == 0) {
2222 if (!checkRegion(pos, nGlyphs)) {
2223 parsedOk = gFalse;
2224 return;
2226 memcpy(fdSelect, file + pos, nGlyphs);
2227 } else if (fdSelectFmt == 3) {
2228 nRanges = getU16BE(pos, &parsedOk);
2229 pos += 2;
2230 gid0 = getU16BE(pos, &parsedOk);
2231 pos += 2;
2232 for (i = 1; i <= nRanges; ++i) {
2233 fd = getU8(pos++, &parsedOk);
2234 gid1 = getU16BE(pos, &parsedOk);
2235 if (!parsedOk) {
2236 return;
2238 pos += 2;
2239 if (gid0 > gid1 || gid1 > nGlyphs) {
2240 //~ error(-1, "Bad FDSelect table in CID font");
2241 parsedOk = gFalse;
2242 return;
2244 for (j = gid0; j < gid1; ++j) {
2245 fdSelect[j] = fd;
2247 gid0 = gid1;
2249 } else {
2250 //~ error(-1, "Unknown FDSelect table format in CID font");
2251 for (i = 0; i < nGlyphs; ++i) {
2252 fdSelect[i] = 0;
2258 void FoFiType1C::buildEncoding() {
2259 char buf[256];
2260 int nCodes, nRanges, encFormat;
2261 int pos, c, sid, nLeft, nSups, i, j;
2263 if (topDict.encodingOffset == 0) {
2264 encoding = (char**)fofiType1StandardEncoding;
2266 } else if (topDict.encodingOffset == 1) {
2267 encoding = (char**)fofiType1ExpertEncoding;
2269 } else {
2270 encoding = (char **)gmallocn(256, sizeof(char *));
2271 for (i = 0; i < 256; ++i) {
2272 encoding[i] = NULL;
2274 pos = topDict.encodingOffset;
2275 encFormat = getU8(pos++, &parsedOk);
2276 if (!parsedOk) {
2277 return;
2279 if ((encFormat & 0x7f) == 0) {
2280 nCodes = 1 + getU8(pos++, &parsedOk);
2281 if (!parsedOk) {
2282 return;
2284 if (nCodes > nGlyphs) {
2285 nCodes = nGlyphs;
2287 for (i = 1; i < nCodes; ++i) {
2288 c = getU8(pos++, &parsedOk);
2289 if (!parsedOk) {
2290 return;
2292 if (encoding[c]) {
2293 gfree(encoding[c]);
2295 encoding[c] = copyString(getString(charset[i], buf, &parsedOk));
2297 } else if ((encFormat & 0x7f) == 1) {
2298 nRanges = getU8(pos++, &parsedOk);
2299 if (!parsedOk) {
2300 return;
2302 nCodes = 1;
2303 for (i = 0; i < nRanges; ++i) {
2304 c = getU8(pos++, &parsedOk);
2305 nLeft = getU8(pos++, &parsedOk);
2306 if (!parsedOk) {
2307 return;
2309 for (j = 0; j <= nLeft && nCodes < nGlyphs; ++j) {
2310 if (c < 256) {
2311 if (encoding[c]) {
2312 gfree(encoding[c]);
2314 encoding[c] = copyString(getString(charset[nCodes], buf,
2315 &parsedOk));
2317 ++nCodes;
2318 ++c;
2322 if (encFormat & 0x80) {
2323 nSups = getU8(pos++, &parsedOk);
2324 if (!parsedOk) {
2325 return;
2327 for (i = 0; i < nSups; ++i) {
2328 c = getU8(pos++, &parsedOk);;
2329 if (!parsedOk) {
2330 return;;
2332 sid = getU16BE(pos, &parsedOk);
2333 pos += 2;
2334 if (!parsedOk) {
2335 return;
2337 if (encoding[c]) {
2338 gfree(encoding[c]);
2340 encoding[c] = copyString(getString(sid, buf, &parsedOk));
2346 GBool FoFiType1C::readCharset() {
2347 int charsetFormat, c, pos;
2348 int nLeft, i, j;
2350 if (topDict.charsetOffset == 0) {
2351 charset = fofiType1CISOAdobeCharset;
2352 } else if (topDict.charsetOffset == 1) {
2353 charset = fofiType1CExpertCharset;
2354 } else if (topDict.charsetOffset == 2) {
2355 charset = fofiType1CExpertSubsetCharset;
2356 } else {
2357 charset = (Gushort *)gmallocn(nGlyphs, sizeof(Gushort));
2358 for (i = 0; i < nGlyphs; ++i) {
2359 charset[i] = 0;
2361 pos = topDict.charsetOffset;
2362 charsetFormat = getU8(pos++, &parsedOk);
2363 if (charsetFormat == 0) {
2364 for (i = 1; i < nGlyphs; ++i) {
2365 charset[i] = (Gushort)getU16BE(pos, &parsedOk);
2366 pos += 2;
2367 if (!parsedOk) {
2368 break;
2371 } else if (charsetFormat == 1) {
2372 i = 1;
2373 while (i < nGlyphs) {
2374 c = getU16BE(pos, &parsedOk);
2375 pos += 2;
2376 nLeft = getU8(pos++, &parsedOk);
2377 if (!parsedOk) {
2378 break;
2380 for (j = 0; j <= nLeft && i < nGlyphs; ++j) {
2381 charset[i++] = (Gushort)c++;
2384 } else if (charsetFormat == 2) {
2385 i = 1;
2386 while (i < nGlyphs) {
2387 c = getU16BE(pos, &parsedOk);
2388 pos += 2;
2389 nLeft = getU16BE(pos, &parsedOk);
2390 pos += 2;
2391 if (!parsedOk) {
2392 break;
2394 for (j = 0; j <= nLeft && i < nGlyphs; ++j) {
2395 charset[i++] = (Gushort)c++;
2399 if (!parsedOk) {
2400 gfree(charset);
2401 charset = NULL;
2402 return gFalse;
2405 return gTrue;
2408 int FoFiType1C::getOp(int pos, GBool charstring, GBool *ok) {
2409 static char nybChars[16] = "0123456789.ee -";
2410 Type1COp op;
2411 char buf[65];
2412 int b0, b1, nyb0, nyb1, x, i;
2414 b0 = getU8(pos++, ok);
2415 op.isNum = gTrue;
2416 op.isFP = gFalse;
2418 if (b0 == 28) {
2419 x = getU8(pos++, ok);
2420 x = (x << 8) | getU8(pos++, ok);
2421 if (x & 0x8000) {
2422 x |= ~0xffff;
2424 op.num = x;
2426 } else if (!charstring && b0 == 29) {
2427 x = getU8(pos++, ok);
2428 x = (x << 8) | getU8(pos++, ok);
2429 x = (x << 8) | getU8(pos++, ok);
2430 x = (x << 8) | getU8(pos++, ok);
2431 if (x & 0x80000000) {
2432 x |= ~0xffffffff;
2434 op.num = x;
2436 } else if (!charstring && b0 == 30) {
2437 i = 0;
2438 do {
2439 b1 = getU8(pos++, ok);
2440 nyb0 = b1 >> 4;
2441 nyb1 = b1 & 0x0f;
2442 if (nyb0 == 0xf) {
2443 break;
2445 buf[i++] = nybChars[nyb0];
2446 if (i == 64) {
2447 break;
2449 if (nyb0 == 0xc) {
2450 buf[i++] = '-';
2452 if (i == 64) {
2453 break;
2455 if (nyb1 == 0xf) {
2456 break;
2458 buf[i++] = nybChars[nyb1];
2459 if (i == 64) {
2460 break;
2462 if (nyb1 == 0xc) {
2463 buf[i++] = '-';
2465 } while (i < 64);
2466 buf[i] = '\0';
2467 op.num = atof(buf);
2468 op.isFP = gTrue;
2470 } else if (b0 >= 32 && b0 <= 246) {
2471 op.num = b0 - 139;
2473 } else if (b0 >= 247 && b0 <= 250) {
2474 op.num = ((b0 - 247) << 8) + getU8(pos++, ok) + 108;
2476 } else if (b0 >= 251 && b0 <= 254) {
2477 op.num = -((b0 - 251) << 8) - getU8(pos++, ok) - 108;
2479 } else if (charstring && b0 == 255) {
2480 x = getU8(pos++, ok);
2481 x = (x << 8) | getU8(pos++, ok);
2482 x = (x << 8) | getU8(pos++, ok);
2483 x = (x << 8) | getU8(pos++, ok);
2484 if (x & 0x80000000) {
2485 x |= ~0xffffffff;
2487 op.num = (double)x / 65536.0;
2488 op.isFP = gTrue;
2490 } else if (b0 == 12) {
2491 op.isNum = gFalse;
2492 op.op = 0x0c00 + getU8(pos++, ok);
2494 } else {
2495 op.isNum = gFalse;
2496 op.op = b0;
2499 if (nOps < 49) {
2500 ops[nOps++] = op;
2503 return pos;
2506 // Convert the delta-encoded ops array to an array of ints.
2507 int FoFiType1C::getDeltaIntArray(int *arr, int maxLen) {
2508 int x;
2509 int n, i;
2511 if ((n = nOps) > maxLen) {
2512 n = maxLen;
2514 x = 0;
2515 for (i = 0; i < n; ++i) {
2516 x += (int)ops[i].num;
2517 arr[i] = x;
2519 return n;
2522 // Convert the delta-encoded ops array to an array of doubles.
2523 int FoFiType1C::getDeltaFPArray(double *arr, int maxLen) {
2524 double x;
2525 int n, i;
2527 if ((n = nOps) > maxLen) {
2528 n = maxLen;
2530 x = 0;
2531 for (i = 0; i < n; ++i) {
2532 x += ops[i].num;
2533 arr[i] = x;
2535 return n;
2538 void FoFiType1C::getIndex(int pos, Type1CIndex *idx, GBool *ok) {
2539 idx->pos = pos;
2540 idx->len = getU16BE(pos, ok);
2541 if (idx->len == 0) {
2542 // empty indexes are legal and contain just the length field
2543 idx->offSize = 0;
2544 idx->startPos = idx->endPos = pos + 2;
2545 } else {
2546 idx->offSize = getU8(pos + 2, ok);
2547 if (idx->offSize < 1 || idx->offSize > 4) {
2548 *ok = gFalse;
2550 idx->startPos = pos + 3 + (idx->len + 1) * idx->offSize - 1;
2551 if (idx->startPos < 0 || idx->startPos >= len) {
2552 *ok = gFalse;
2554 idx->endPos = idx->startPos + getUVarBE(pos + 3 + idx->len * idx->offSize,
2555 idx->offSize, ok);
2556 if (idx->endPos < idx->startPos || idx->endPos > len) {
2557 *ok = gFalse;
2562 void FoFiType1C::getIndexVal(Type1CIndex *idx, int i,
2563 Type1CIndexVal *val, GBool *ok) {
2564 int pos0, pos1;
2566 if (i < 0 || i >= idx->len) {
2567 *ok = gFalse;
2568 return;
2570 pos0 = idx->startPos + getUVarBE(idx->pos + 3 + i * idx->offSize,
2571 idx->offSize, ok);
2572 pos1 = idx->startPos + getUVarBE(idx->pos + 3 + (i + 1) * idx->offSize,
2573 idx->offSize, ok);
2574 if (pos0 < idx->startPos || pos0 > idx->endPos ||
2575 pos1 <= idx->startPos || pos1 > idx->endPos ||
2576 pos1 < pos0) {
2577 *ok = gFalse;
2579 val->pos = pos0;
2580 val->len = pos1 - pos0;
2583 char *FoFiType1C::getString(int sid, char *buf, GBool *ok) {
2584 Type1CIndexVal val;
2585 int n;
2587 if (sid < 391) {
2588 strcpy(buf, fofiType1CStdStrings[sid]);
2589 } else {
2590 sid -= 391;
2591 getIndexVal(&stringIdx, sid, &val, ok);
2592 if (*ok) {
2593 if ((n = val.len) > 255) {
2594 n = 255;
2596 strncpy(buf, (char *)&file[val.pos], n);
2597 buf[n] = '\0';
2598 } else {
2599 buf[0] = '\0';
2602 return buf;