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