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