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