Back to index

tetex-bin  3.0
FoFiType1C.cc
Go to the documentation of this file.
00001 //========================================================================
00002 //
00003 // FoFiType1C.cc
00004 //
00005 // Copyright 1999-2003 Glyph & Cog, LLC
00006 //
00007 //========================================================================
00008 
00009 #include <aconf.h>
00010 
00011 #ifdef USE_GCC_PRAGMAS
00012 #pragma implementation
00013 #endif
00014 
00015 #include <stdlib.h>
00016 #include <string.h>
00017 #include <math.h>
00018 #include "gmem.h"
00019 #include "GString.h"
00020 #include "FoFiEncodings.h"
00021 #include "FoFiType1C.h"
00022 
00023 //------------------------------------------------------------------------
00024 
00025 static char hexChars[17] = "0123456789ABCDEF";
00026 
00027 //------------------------------------------------------------------------
00028 // FoFiType1C
00029 //------------------------------------------------------------------------
00030 
00031 FoFiType1C *FoFiType1C::make(char *fileA, int lenA) {
00032   FoFiType1C *ff;
00033 
00034   ff = new FoFiType1C(fileA, lenA, gFalse);
00035   if (!ff->parse()) {
00036     delete ff;
00037     return NULL;
00038   }
00039   return ff;
00040 }
00041 
00042 FoFiType1C *FoFiType1C::load(char *fileName) {
00043   FoFiType1C *ff;
00044   char *fileA;
00045   int lenA;
00046 
00047   if (!(fileA = FoFiBase::readFile(fileName, &lenA))) {
00048     return NULL;
00049   }
00050   ff = new FoFiType1C(fileA, lenA, gTrue);
00051   if (!ff->parse()) {
00052     delete ff;
00053     return NULL;
00054   }
00055   return ff;
00056 }
00057 
00058 FoFiType1C::FoFiType1C(char *fileA, int lenA, GBool freeFileDataA):
00059   FoFiBase(fileA, lenA, freeFileDataA)
00060 {
00061   name = NULL;
00062   encoding = NULL;
00063   privateDicts = NULL;
00064   fdSelect = NULL;
00065   charset = NULL;
00066 }
00067 
00068 FoFiType1C::~FoFiType1C() {
00069   int i;
00070 
00071   if (name) {
00072     delete name;
00073   }
00074   if (encoding &&
00075       encoding != fofiType1StandardEncoding &&
00076       encoding != fofiType1ExpertEncoding) {
00077     for (i = 0; i < 256; ++i) {
00078       gfree(encoding[i]);
00079     }
00080     gfree(encoding);
00081   }
00082   if (privateDicts) {
00083     gfree(privateDicts);
00084   }
00085   if (fdSelect) {
00086     gfree(fdSelect);
00087   }
00088   if (charset &&
00089       charset != fofiType1CISOAdobeCharset &&
00090       charset != fofiType1CExpertCharset &&
00091       charset != fofiType1CExpertSubsetCharset) {
00092     gfree(charset);
00093   }
00094 }
00095 
00096 char *FoFiType1C::getName() {
00097   return name ? name->getCString() : (char *)NULL;
00098 }
00099 
00100 char **FoFiType1C::getEncoding() {
00101   return encoding;
00102 }
00103 
00104 Gushort *FoFiType1C::getCIDToGIDMap(int *nCIDs) {
00105   Gushort *map;
00106   int n, i;
00107 
00108   // a CID font's top dict has ROS as the first operator
00109   if (topDict.firstOp != 0x0c1e) {
00110     *nCIDs = 0;
00111     return NULL;
00112   }
00113 
00114   // in a CID font, the charset data is the GID-to-CID mapping, so all
00115   // we have to do is reverse it
00116   n = 0;
00117   for (i = 0; i < nGlyphs; ++i) {
00118     if (charset[i] > n) {
00119       n = charset[i];
00120     }
00121   }
00122   ++n;
00123   map = (Gushort *)gmalloc(n * sizeof(Gushort));
00124   memset(map, 0, n * sizeof(Gushort));
00125   for (i = 0; i < nGlyphs; ++i) {
00126     map[charset[i]] = i;
00127   }
00128   *nCIDs = n;
00129   return map;
00130 }
00131 
00132 void FoFiType1C::convertToType1(char **newEncoding, GBool ascii,
00133                             FoFiOutputFunc outputFunc,
00134                             void *outputStream) {
00135   Type1CEexecBuf eb;
00136   Type1CIndex subrIdx;
00137   Type1CIndexVal val;
00138   char buf[512];
00139   char **enc;
00140   GBool ok;
00141   int i;
00142 
00143   // write header and font dictionary, up to encoding
00144   ok = gTrue;
00145   (*outputFunc)(outputStream, "%!FontType1-1.0: ", 17);
00146   (*outputFunc)(outputStream, name->getCString(), name->getLength());
00147   if (topDict.versionSID != 0) {
00148     getString(topDict.versionSID, buf, &ok);
00149     (*outputFunc)(outputStream, buf, strlen(buf));
00150   }
00151   (*outputFunc)(outputStream, "\n", 1);
00152   // the dictionary needs room for 12 entries: the following 9, plus
00153   // Private and CharStrings (in the eexec section) and FID (which is
00154   // added by definefont)
00155   (*outputFunc)(outputStream, "12 dict begin\n", 14);
00156   (*outputFunc)(outputStream, "/FontInfo 10 dict dup begin\n", 28);
00157   if (topDict.versionSID != 0) {
00158     (*outputFunc)(outputStream, "/version (", 10);
00159     (*outputFunc)(outputStream, buf, strlen(buf));
00160     (*outputFunc)(outputStream, ") readonly def\n", 15);
00161   }
00162   if (topDict.noticeSID != 0) {
00163     getString(topDict.noticeSID, buf, &ok);
00164     (*outputFunc)(outputStream, "/Notice (", 9);
00165     (*outputFunc)(outputStream, buf, strlen(buf));
00166     (*outputFunc)(outputStream, ") readonly def\n", 15);
00167   }
00168   if (topDict.copyrightSID != 0) {
00169     getString(topDict.copyrightSID, buf, &ok);
00170     (*outputFunc)(outputStream, "/Copyright (", 12);
00171     (*outputFunc)(outputStream, buf, strlen(buf));
00172     (*outputFunc)(outputStream, ") readonly def\n", 15);
00173   }
00174   if (topDict.fullNameSID != 0) {
00175     getString(topDict.fullNameSID, buf, &ok);
00176     (*outputFunc)(outputStream, "/FullName (", 11);
00177     (*outputFunc)(outputStream, buf, strlen(buf));
00178     (*outputFunc)(outputStream, ") readonly def\n", 15);
00179   }
00180   if (topDict.familyNameSID != 0) {
00181     getString(topDict.familyNameSID, buf, &ok);
00182     (*outputFunc)(outputStream, "/FamilyName (", 13);
00183     (*outputFunc)(outputStream, buf, strlen(buf));
00184     (*outputFunc)(outputStream, ") readonly def\n", 15);
00185   }
00186   if (topDict.weightSID != 0) {
00187     getString(topDict.weightSID, buf, &ok);
00188     (*outputFunc)(outputStream, "/Weight (", 9);
00189     (*outputFunc)(outputStream, buf, strlen(buf));
00190     (*outputFunc)(outputStream, ") readonly def\n", 15);
00191   }
00192   if (topDict.isFixedPitch) {
00193     (*outputFunc)(outputStream, "/isFixedPitch true def\n", 23);
00194   } else {
00195     (*outputFunc)(outputStream, "/isFixedPitch false def\n", 24);
00196   }
00197   sprintf(buf, "/ItalicAngle %g def\n", topDict.italicAngle);
00198   (*outputFunc)(outputStream, buf, strlen(buf));
00199   sprintf(buf, "/UnderlinePosition %g def\n", topDict.underlinePosition);
00200   (*outputFunc)(outputStream, buf, strlen(buf));
00201   sprintf(buf, "/UnderlineThickness %g def\n", topDict.underlineThickness);
00202   (*outputFunc)(outputStream, buf, strlen(buf));
00203   (*outputFunc)(outputStream, "end readonly def\n", 17);
00204   (*outputFunc)(outputStream, "/FontName /", 11);
00205   (*outputFunc)(outputStream, name->getCString(), name->getLength());
00206   (*outputFunc)(outputStream, " def\n", 5);
00207   sprintf(buf, "/PaintType %d def\n", topDict.paintType);
00208   (*outputFunc)(outputStream, buf, strlen(buf));
00209   (*outputFunc)(outputStream, "/FontType 1 def\n", 16);
00210   sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] readonly def\n",
00211          topDict.fontMatrix[0], topDict.fontMatrix[1], topDict.fontMatrix[2],
00212          topDict.fontMatrix[3], topDict.fontMatrix[4], topDict.fontMatrix[5]);
00213   (*outputFunc)(outputStream, buf, strlen(buf));
00214   sprintf(buf, "/FontBBox [%g %g %g %g] readonly def\n",
00215          topDict.fontBBox[0], topDict.fontBBox[1],
00216          topDict.fontBBox[2], topDict.fontBBox[3]);
00217   (*outputFunc)(outputStream, buf, strlen(buf));
00218   sprintf(buf, "/StrokeWidth %g def\n", topDict.strokeWidth);
00219   (*outputFunc)(outputStream, buf, strlen(buf));
00220   if (topDict.uniqueID != 0) {
00221     sprintf(buf, "/UniqueID %d def\n", topDict.uniqueID);
00222     (*outputFunc)(outputStream, buf, strlen(buf));
00223   }
00224 
00225   // write the encoding
00226   (*outputFunc)(outputStream, "/Encoding ", 10);
00227   if (!newEncoding && encoding == fofiType1StandardEncoding) {
00228     (*outputFunc)(outputStream, "StandardEncoding def\n", 21);
00229   } else {
00230     (*outputFunc)(outputStream, "256 array\n", 10);
00231     (*outputFunc)(outputStream,
00232                 "0 1 255 {1 index exch /.notdef put} for\n", 40);
00233     enc = newEncoding ? newEncoding : encoding;
00234     for (i = 0; i < 256; ++i) {
00235       if (enc[i]) {
00236        sprintf(buf, "dup %d /%s put\n", i, enc[i]);
00237        (*outputFunc)(outputStream, buf, strlen(buf));
00238       }
00239     }
00240     (*outputFunc)(outputStream, "readonly def\n", 13);
00241   }
00242   (*outputFunc)(outputStream, "currentdict end\n", 16);
00243 
00244   // start the binary section
00245   (*outputFunc)(outputStream, "currentfile eexec\n", 18);
00246   eb.outputFunc = outputFunc;
00247   eb.outputStream = outputStream;
00248   eb.ascii = ascii;
00249   eb.r1 = 55665;
00250   eb.line = 0;
00251 
00252   // write the private dictionary
00253   eexecWrite(&eb, "\x83\xca\x73\xd5");
00254   eexecWrite(&eb, "dup /Private 32 dict dup begin\n");
00255   eexecWrite(&eb, "/RD {string currentfile exch readstring pop}"
00256             " executeonly def\n");
00257   eexecWrite(&eb, "/ND {noaccess def} executeonly def\n");
00258   eexecWrite(&eb, "/NP {noaccess put} executeonly def\n");
00259   eexecWrite(&eb, "/MinFeature {16 16} def\n");
00260   eexecWrite(&eb, "/password 5839 def\n");
00261   if (privateDicts[0].nBlueValues) {
00262     eexecWrite(&eb, "/BlueValues [");
00263     for (i = 0; i < privateDicts[0].nBlueValues; ++i) {
00264       sprintf(buf, "%s%d", i > 0 ? " " : "", privateDicts[0].blueValues[i]);
00265       eexecWrite(&eb, buf);
00266     }
00267     eexecWrite(&eb, "] def\n");
00268   }
00269   if (privateDicts[0].nOtherBlues) {
00270     eexecWrite(&eb, "/OtherBlues [");
00271     for (i = 0; i < privateDicts[0].nOtherBlues; ++i) {
00272       sprintf(buf, "%s%d", i > 0 ? " " : "", privateDicts[0].otherBlues[i]);
00273       eexecWrite(&eb, buf);
00274     }
00275     eexecWrite(&eb, "] def\n");
00276   }
00277   if (privateDicts[0].nFamilyBlues) {
00278     eexecWrite(&eb, "/FamilyBlues [");
00279     for (i = 0; i < privateDicts[0].nFamilyBlues; ++i) {
00280       sprintf(buf, "%s%d", i > 0 ? " " : "", privateDicts[0].familyBlues[i]);
00281       eexecWrite(&eb, buf);
00282     }
00283     eexecWrite(&eb, "] def\n");
00284   }
00285   if (privateDicts[0].nFamilyOtherBlues) {
00286     eexecWrite(&eb, "/FamilyOtherBlues [");
00287     for (i = 0; i < privateDicts[0].nFamilyOtherBlues; ++i) {
00288       sprintf(buf, "%s%d", i > 0 ? " " : "",
00289              privateDicts[0].familyOtherBlues[i]);
00290       eexecWrite(&eb, buf);
00291     }
00292     eexecWrite(&eb, "] def\n");
00293   }
00294   if (privateDicts[0].blueScale != 0.039625) {
00295     sprintf(buf, "/BlueScale %g def\n", privateDicts[0].blueScale);
00296     eexecWrite(&eb, buf);
00297   }
00298   if (privateDicts[0].blueShift != 7) {
00299     sprintf(buf, "/BlueShift %d def\n", privateDicts[0].blueShift);
00300     eexecWrite(&eb, buf);
00301   }
00302   if (privateDicts[0].blueFuzz != 1) {
00303     sprintf(buf, "/BlueFuzz %d def\n", privateDicts[0].blueFuzz);
00304     eexecWrite(&eb, buf);
00305   }
00306   if (privateDicts[0].hasStdHW) {
00307     sprintf(buf, "/StdHW [%g] def\n", privateDicts[0].stdHW);
00308     eexecWrite(&eb, buf);
00309   }
00310   if (privateDicts[0].hasStdVW) {
00311     sprintf(buf, "/StdVW [%g] def\n", privateDicts[0].stdVW);
00312     eexecWrite(&eb, buf);
00313   }
00314   if (privateDicts[0].nStemSnapH) {
00315     eexecWrite(&eb, "/StemSnapH [");
00316     for (i = 0; i < privateDicts[0].nStemSnapH; ++i) {
00317       sprintf(buf, "%s%g", i > 0 ? " " : "", privateDicts[0].stemSnapH[i]);
00318       eexecWrite(&eb, buf);
00319     }
00320     eexecWrite(&eb, "] def\n");
00321   }
00322   if (privateDicts[0].nStemSnapV) {
00323     eexecWrite(&eb, "/StemSnapV [");
00324     for (i = 0; i < privateDicts[0].nStemSnapV; ++i) {
00325       sprintf(buf, "%s%g", i > 0 ? " " : "", privateDicts[0].stemSnapV[i]);
00326       eexecWrite(&eb, buf);
00327     }
00328     eexecWrite(&eb, "] def\n");
00329   }
00330   if (privateDicts[0].hasForceBold) {
00331     sprintf(buf, "/ForceBold %s def\n",
00332            privateDicts[0].forceBold ? "true" : "false");
00333     eexecWrite(&eb, buf);
00334   }
00335   if (privateDicts[0].forceBoldThreshold != 0) {
00336     sprintf(buf, "/ForceBoldThreshold %g def\n",
00337            privateDicts[0].forceBoldThreshold);
00338     eexecWrite(&eb, buf);
00339   }
00340   if (privateDicts[0].languageGroup != 0) {
00341     sprintf(buf, "/LanguageGroup %d def\n", privateDicts[0].languageGroup);
00342     eexecWrite(&eb, buf);
00343   }
00344   if (privateDicts[0].expansionFactor != 0.06) {
00345     sprintf(buf, "/ExpansionFactor %g def\n", privateDicts[0].expansionFactor);
00346     eexecWrite(&eb, buf);
00347   }
00348 
00349   // set up subroutines
00350   ok = gTrue;
00351   getIndex(privateDicts[0].subrsOffset, &subrIdx, &ok);
00352   if (!ok) {
00353     subrIdx.pos = -1;
00354   }
00355 
00356   // write the CharStrings
00357   sprintf(buf, "2 index /CharStrings %d dict dup begin\n", nGlyphs);
00358   eexecWrite(&eb, buf);
00359   for (i = 0; i < nGlyphs; ++i) {
00360     ok = gTrue;
00361     getIndexVal(&charStringsIdx, i, &val, &ok);
00362     if (ok) {
00363       getString(charset[i], buf, &ok);
00364       if (ok) {
00365        eexecCvtGlyph(&eb, buf, val.pos, val.len, &subrIdx, &privateDicts[0]);
00366       }
00367     }
00368   }
00369   eexecWrite(&eb, "end\n");
00370   eexecWrite(&eb, "end\n");
00371   eexecWrite(&eb, "readonly put\n");
00372   eexecWrite(&eb, "noaccess put\n");
00373   eexecWrite(&eb, "dup /FontName get exch definefont pop\n");
00374   eexecWrite(&eb, "mark currentfile closefile\n");
00375 
00376   // trailer
00377   if (ascii && eb.line > 0) {
00378     (*outputFunc)(outputStream, "\n", 1);
00379   }
00380   for (i = 0; i < 8; ++i) {
00381     (*outputFunc)(outputStream, "0000000000000000000000000000000000000000000000000000000000000000\n", 65);
00382   }
00383   (*outputFunc)(outputStream, "cleartomark\n", 12);
00384 }
00385 
00386 void FoFiType1C::convertToCIDType0(char *psName,
00387                                FoFiOutputFunc outputFunc,
00388                                void *outputStream) {
00389   int *cidMap;
00390   GString *charStrings;
00391   int *charStringOffsets;
00392   Type1CIndex subrIdx;
00393   Type1CIndexVal val;
00394   int nCIDs, gdBytes;
00395   char buf[512], buf2[512];
00396   GBool ok;
00397   int gid, offset, n, i, j, k;
00398 
00399   // compute the CID count and build the CID-to-GID mapping
00400   nCIDs = 0;
00401   for (i = 0; i < nGlyphs; ++i) {
00402     if (charset[i] >= nCIDs) {
00403       nCIDs = charset[i] + 1;
00404     }
00405   }
00406   cidMap = (int *)gmalloc(nCIDs * sizeof(int));
00407   for (i = 0; i < nCIDs; ++i) {
00408     cidMap[i] = -1;
00409   }
00410   for (i = 0; i < nGlyphs; ++i) {
00411     cidMap[charset[i]] = i;
00412   }
00413 
00414   // build the charstrings
00415   charStrings = new GString();
00416   charStringOffsets = (int *)gmalloc((nCIDs + 1) * sizeof(int));
00417   for (i = 0; i < nCIDs; ++i) {
00418     charStringOffsets[i] = charStrings->getLength();
00419     if ((gid = cidMap[i]) >= 0) {
00420       ok = gTrue;
00421       getIndexVal(&charStringsIdx, gid, &val, &ok);
00422       if (ok) {
00423        getIndex(privateDicts[fdSelect[gid]].subrsOffset, &subrIdx, &ok);
00424        if (!ok) {
00425          subrIdx.pos = -1;
00426        }
00427        cvtGlyph(val.pos, val.len, charStrings,
00428                &subrIdx, &privateDicts[fdSelect[gid]], gTrue);
00429       }
00430     }
00431   }
00432   charStringOffsets[nCIDs] = charStrings->getLength();
00433 
00434   // compute gdBytes = number of bytes needed for charstring offsets
00435   // (offset size needs to account for the charstring offset table,
00436   // with a worst case of five bytes per entry, plus the charstrings
00437   // themselves)
00438   i = (nCIDs + 1) * 5 + charStrings->getLength();
00439   if (i < 0x100) {
00440     gdBytes = 1;
00441   } else if (i < 0x10000) {
00442     gdBytes = 2;
00443   } else if (i < 0x1000000) {
00444     gdBytes = 3;
00445   } else {
00446     gdBytes = 4;
00447   }
00448 
00449   // begin the font dictionary
00450   (*outputFunc)(outputStream, "/CIDInit /ProcSet findresource begin\n", 37);
00451   (*outputFunc)(outputStream, "20 dict begin\n", 14);
00452   (*outputFunc)(outputStream, "/CIDFontName /", 14);
00453   (*outputFunc)(outputStream, psName, strlen(psName));
00454   (*outputFunc)(outputStream, " def\n", 5);
00455   (*outputFunc)(outputStream, "/CIDFontType 0 def\n", 19);
00456   (*outputFunc)(outputStream, "/CIDSystemInfo 3 dict dup begin\n", 32);
00457   if (topDict.registrySID > 0 && topDict.orderingSID > 0) {
00458     ok = gTrue;
00459     getString(topDict.registrySID, buf, &ok);
00460     if (ok) {
00461       (*outputFunc)(outputStream, "  /Registry (", 13);
00462       (*outputFunc)(outputStream, buf, strlen(buf));
00463       (*outputFunc)(outputStream, ") def\n", 6);
00464     }
00465     ok = gTrue;
00466     getString(topDict.orderingSID, buf, &ok);
00467     if (ok) {
00468       (*outputFunc)(outputStream, "  /Ordering (", 13);
00469       (*outputFunc)(outputStream, buf, strlen(buf));
00470       (*outputFunc)(outputStream, ") def\n", 6);
00471     }
00472   } else {
00473     (*outputFunc)(outputStream, "  /Registry (Adobe) def\n", 24);
00474     (*outputFunc)(outputStream, "  /Ordering (Identity) def\n", 27);
00475   }
00476   sprintf(buf, "  /Supplement %d def\n", topDict.supplement);
00477   (*outputFunc)(outputStream, buf, strlen(buf));
00478   (*outputFunc)(outputStream, "end def\n", 8);
00479   sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] def\n",
00480          topDict.fontMatrix[0], topDict.fontMatrix[1], topDict.fontMatrix[2],
00481          topDict.fontMatrix[3], topDict.fontMatrix[4], topDict.fontMatrix[5]);
00482   (*outputFunc)(outputStream, buf, strlen(buf));
00483   sprintf(buf, "/FontBBox [%g %g %g %g] def\n",
00484          topDict.fontBBox[0], topDict.fontBBox[1],
00485          topDict.fontBBox[2], topDict.fontBBox[3]);
00486   (*outputFunc)(outputStream, buf, strlen(buf));
00487   (*outputFunc)(outputStream, "/FontInfo 1 dict dup begin\n", 27);
00488   (*outputFunc)(outputStream, "  /FSType 8 def\n", 16);
00489   (*outputFunc)(outputStream, "end def\n", 8);
00490 
00491   // CIDFont-specific entries
00492   sprintf(buf, "/CIDCount %d def\n", nCIDs);
00493   (*outputFunc)(outputStream, buf, strlen(buf));
00494   (*outputFunc)(outputStream, "/FDBytes 1 def\n", 15);
00495   sprintf(buf, "/GDBytes %d def\n", gdBytes);
00496   (*outputFunc)(outputStream, buf, strlen(buf));
00497   (*outputFunc)(outputStream, "/CIDMapOffset 0 def\n", 20);
00498   if (topDict.paintType != 0) {
00499     sprintf(buf, "/PaintType %d def\n", topDict.paintType);
00500     (*outputFunc)(outputStream, buf, strlen(buf));
00501     sprintf(buf, "/StrokeWidth %g def\n", topDict.strokeWidth);
00502     (*outputFunc)(outputStream, buf, strlen(buf));
00503   }
00504 
00505   // FDArray entry
00506   sprintf(buf, "/FDArray %d array\n", nFDs);
00507   (*outputFunc)(outputStream, buf, strlen(buf));
00508   for (i = 0; i < nFDs; ++i) {
00509     sprintf(buf, "dup %d 10 dict begin\n", i);
00510     (*outputFunc)(outputStream, buf, strlen(buf));
00511     (*outputFunc)(outputStream, "/FontType 1 def\n", 16);
00512     (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
00513     sprintf(buf, "/PaintType %d def\n", topDict.paintType);
00514     (*outputFunc)(outputStream, buf, strlen(buf));
00515     (*outputFunc)(outputStream, "/Private 32 dict begin\n", 23);
00516     if (privateDicts[i].nBlueValues) {
00517       (*outputFunc)(outputStream, "/BlueValues [", 13);
00518       for (j = 0; j < privateDicts[i].nBlueValues; ++j) {
00519        sprintf(buf, "%s%d", j > 0 ? " " : "", privateDicts[i].blueValues[j]);
00520        (*outputFunc)(outputStream, buf, strlen(buf));
00521       }
00522       (*outputFunc)(outputStream, "] def\n", 6);
00523     }
00524     if (privateDicts[i].nOtherBlues) {
00525       (*outputFunc)(outputStream, "/OtherBlues [", 13);
00526       for (j = 0; j < privateDicts[i].nOtherBlues; ++j) {
00527        sprintf(buf, "%s%d", j > 0 ? " " : "", privateDicts[i].otherBlues[j]);
00528        (*outputFunc)(outputStream, buf, strlen(buf));
00529       }
00530       (*outputFunc)(outputStream, "] def\n", 6);
00531     }
00532     if (privateDicts[i].nFamilyBlues) {
00533       (*outputFunc)(outputStream, "/FamilyBlues [", 14);
00534       for (j = 0; j < privateDicts[i].nFamilyBlues; ++j) {
00535        sprintf(buf, "%s%d", j > 0 ? " " : "", privateDicts[i].familyBlues[j]);
00536        (*outputFunc)(outputStream, buf, strlen(buf));
00537       }
00538       (*outputFunc)(outputStream, "] def\n", 6);
00539     }
00540     if (privateDicts[i].nFamilyOtherBlues) {
00541       (*outputFunc)(outputStream, "/FamilyOtherBlues [", 19);
00542       for (j = 0; j < privateDicts[i].nFamilyOtherBlues; ++j) {
00543        sprintf(buf, "%s%d", j > 0 ? " " : "",
00544               privateDicts[i].familyOtherBlues[j]);
00545        (*outputFunc)(outputStream, buf, strlen(buf));
00546       }
00547       (*outputFunc)(outputStream, "] def\n", 6);
00548     }
00549     if (privateDicts[i].blueScale != 0.039625) {
00550       sprintf(buf, "/BlueScale %g def\n", privateDicts[i].blueScale);
00551       (*outputFunc)(outputStream, buf, strlen(buf));
00552     }
00553     if (privateDicts[i].blueShift != 7) {
00554       sprintf(buf, "/BlueShift %d def\n", privateDicts[i].blueShift);
00555       (*outputFunc)(outputStream, buf, strlen(buf));
00556     }
00557     if (privateDicts[i].blueFuzz != 1) {
00558       sprintf(buf, "/BlueFuzz %d def\n", privateDicts[i].blueFuzz);
00559       (*outputFunc)(outputStream, buf, strlen(buf));
00560     }
00561     if (privateDicts[i].hasStdHW) {
00562       sprintf(buf, "/StdHW [%g] def\n", privateDicts[i].stdHW);
00563       (*outputFunc)(outputStream, buf, strlen(buf));
00564     }
00565     if (privateDicts[i].hasStdVW) {
00566       sprintf(buf, "/StdVW [%g] def\n", privateDicts[i].stdVW);
00567       (*outputFunc)(outputStream, buf, strlen(buf));
00568     }
00569     if (privateDicts[i].nStemSnapH) {
00570       (*outputFunc)(outputStream, "/StemSnapH [", 12);
00571       for (j = 0; j < privateDicts[i].nStemSnapH; ++j) {
00572        sprintf(buf, "%s%g", j > 0 ? " " : "", privateDicts[i].stemSnapH[j]);
00573        (*outputFunc)(outputStream, buf, strlen(buf));
00574       }
00575       (*outputFunc)(outputStream, "] def\n", 6);
00576     }
00577     if (privateDicts[i].nStemSnapV) {
00578       (*outputFunc)(outputStream, "/StemSnapV [", 12);
00579       for (j = 0; j < privateDicts[i].nStemSnapV; ++j) {
00580        sprintf(buf, "%s%g", j > 0 ? " " : "", privateDicts[i].stemSnapV[j]);
00581        (*outputFunc)(outputStream, buf, strlen(buf));
00582       }
00583       (*outputFunc)(outputStream, "] def\n", 6);
00584     }
00585     if (privateDicts[i].hasForceBold) {
00586       sprintf(buf, "/ForceBold %s def\n",
00587              privateDicts[i].forceBold ? "true" : "false");
00588       (*outputFunc)(outputStream, buf, strlen(buf));
00589     }
00590     if (privateDicts[i].forceBoldThreshold != 0) {
00591       sprintf(buf, "/ForceBoldThreshold %g def\n",
00592              privateDicts[i].forceBoldThreshold);
00593       (*outputFunc)(outputStream, buf, strlen(buf));
00594     }
00595     if (privateDicts[i].languageGroup != 0) {
00596       sprintf(buf, "/LanguageGroup %d def\n", privateDicts[i].languageGroup);
00597       (*outputFunc)(outputStream, buf, strlen(buf));
00598     }
00599     if (privateDicts[i].expansionFactor != 0.06) {
00600       sprintf(buf, "/ExpansionFactor %g def\n",
00601              privateDicts[i].expansionFactor);
00602       (*outputFunc)(outputStream, buf, strlen(buf));
00603     }
00604     (*outputFunc)(outputStream, "currentdict end def\n", 20);
00605     (*outputFunc)(outputStream, "currentdict end put\n", 20);
00606   }
00607   (*outputFunc)(outputStream, "def\n", 4);
00608 
00609   // start the binary section
00610   offset = (nCIDs + 1) * (1 + gdBytes);
00611   sprintf(buf, "(Hex) %d StartData\n",
00612          offset + charStrings->getLength());
00613   (*outputFunc)(outputStream, buf, strlen(buf));
00614 
00615   // write the charstring offset (CIDMap) table
00616   for (i = 0; i <= nCIDs; i += 6) {
00617     for (j = 0; j < 6 && i+j <= nCIDs; ++j) {
00618       if (i+j < nCIDs && cidMap[i+j] >= 0) {
00619        buf[0] = (char)fdSelect[cidMap[i+j]];
00620       } else {
00621        buf[0] = (char)0;
00622       }
00623       n = offset + charStringOffsets[i+j];
00624       for (k = gdBytes; k >= 1; --k) {
00625        buf[k] = (char)(n & 0xff);
00626        n >>= 8;
00627       }
00628       for (k = 0; k <= gdBytes; ++k) {
00629        sprintf(buf2, "%02x", buf[k] & 0xff);
00630        (*outputFunc)(outputStream, buf2, 2);
00631       }
00632     }
00633     (*outputFunc)(outputStream, "\n", 1);
00634   }
00635 
00636   // write the charstring data
00637   n = charStrings->getLength();
00638   for (i = 0; i < n; i += 32) {
00639     for (j = 0; j < 32 && i+j < n; ++j) {
00640       sprintf(buf, "%02x", charStrings->getChar(i+j) & 0xff);
00641       (*outputFunc)(outputStream, buf, strlen(buf));
00642     }
00643     if (i + 32 >= n) {
00644       (*outputFunc)(outputStream, ">", 1);
00645     }
00646     (*outputFunc)(outputStream, "\n", 1);
00647   }
00648 
00649   gfree(charStringOffsets);
00650   delete charStrings;
00651   gfree(cidMap);
00652 }
00653 
00654 void FoFiType1C::convertToType0(char *psName,
00655                             FoFiOutputFunc outputFunc,
00656                             void *outputStream) {
00657   int *cidMap;
00658   Type1CIndex subrIdx;
00659   Type1CIndexVal val;
00660   int nCIDs;
00661   char buf[512];
00662   Type1CEexecBuf eb;
00663   GBool ok;
00664   int fd, i, j, k;
00665 
00666   // compute the CID count and build the CID-to-GID mapping
00667   nCIDs = 0;
00668   for (i = 0; i < nGlyphs; ++i) {
00669     if (charset[i] >= nCIDs) {
00670       nCIDs = charset[i] + 1;
00671     }
00672   }
00673   cidMap = (int *)gmalloc(nCIDs * sizeof(int));
00674   for (i = 0; i < nCIDs; ++i) {
00675     cidMap[i] = -1;
00676   }
00677   for (i = 0; i < nGlyphs; ++i) {
00678     cidMap[charset[i]] = i;
00679   }
00680 
00681   // write the descendant Type 1 fonts
00682   for (i = 0; i < nCIDs; i += 256) {
00683 
00684     //~ this assumes that all CIDs in this block have the same FD --
00685     //~ to handle multiple FDs correctly, need to somehow divide the
00686     //~ font up by FD
00687     fd = 0;
00688     for (j = 0; j < 256 && i+j < nCIDs; ++j) {
00689       if (cidMap[i+j] >= 0) {
00690        fd = fdSelect[cidMap[i+j]];
00691        break;
00692       }
00693     }
00694 
00695     // font dictionary (unencrypted section)
00696     (*outputFunc)(outputStream, "16 dict begin\n", 14);
00697     (*outputFunc)(outputStream, "/FontName /", 11);
00698     (*outputFunc)(outputStream, psName, strlen(psName));
00699     sprintf(buf, "_%02x def\n", i >> 8);
00700     (*outputFunc)(outputStream, buf, strlen(buf));
00701     (*outputFunc)(outputStream, "/FontType 1 def\n", 16);
00702     sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] def\n",
00703            topDict.fontMatrix[0], topDict.fontMatrix[1],
00704            topDict.fontMatrix[2], topDict.fontMatrix[3],
00705            topDict.fontMatrix[4], topDict.fontMatrix[5]);
00706     (*outputFunc)(outputStream, buf, strlen(buf));
00707     sprintf(buf, "/FontBBox [%g %g %g %g] def\n",
00708            topDict.fontBBox[0], topDict.fontBBox[1],
00709            topDict.fontBBox[2], topDict.fontBBox[3]);
00710     (*outputFunc)(outputStream, buf, strlen(buf));
00711     sprintf(buf, "/PaintType %d def\n", topDict.paintType);
00712     (*outputFunc)(outputStream, buf, strlen(buf));
00713     if (topDict.paintType != 0) {
00714       sprintf(buf, "/StrokeWidth %g def\n", topDict.strokeWidth);
00715       (*outputFunc)(outputStream, buf, strlen(buf));
00716     }
00717     (*outputFunc)(outputStream, "/Encoding 256 array\n", 20);
00718     for (j = 0; j < 256 && i+j < nCIDs; ++j) {
00719       sprintf(buf, "dup %d /c%02x put\n", j, j);
00720       (*outputFunc)(outputStream, buf, strlen(buf));
00721     }
00722     if (j < 256) {
00723       sprintf(buf, "%d 1 255 { 1 index exch /.notdef put } for\n", j);
00724       (*outputFunc)(outputStream, buf, strlen(buf));
00725     }
00726     (*outputFunc)(outputStream, "readonly def\n", 13);
00727     (*outputFunc)(outputStream, "currentdict end\n", 16);
00728 
00729     // start the binary section
00730     (*outputFunc)(outputStream, "currentfile eexec\n", 18);
00731     eb.outputFunc = outputFunc;
00732     eb.outputStream = outputStream;
00733     eb.ascii = gTrue;
00734     eb.r1 = 55665;
00735     eb.line = 0;
00736 
00737     // start the private dictionary
00738     eexecWrite(&eb, "\x83\xca\x73\xd5");
00739     eexecWrite(&eb, "dup /Private 32 dict dup begin\n");
00740     eexecWrite(&eb, "/RD {string currentfile exch readstring pop}"
00741               " executeonly def\n");
00742     eexecWrite(&eb, "/ND {noaccess def} executeonly def\n");
00743     eexecWrite(&eb, "/NP {noaccess put} executeonly def\n");
00744     eexecWrite(&eb, "/MinFeature {16 16} def\n");
00745     eexecWrite(&eb, "/password 5839 def\n");
00746     if (privateDicts[fd].nBlueValues) {
00747       eexecWrite(&eb, "/BlueValues [");
00748       for (k = 0; k < privateDicts[fd].nBlueValues; ++k) {
00749        sprintf(buf, "%s%d", k > 0 ? " " : "", privateDicts[fd].blueValues[k]);
00750        eexecWrite(&eb, buf);
00751       }
00752       eexecWrite(&eb, "] def\n");
00753     }
00754     if (privateDicts[fd].nOtherBlues) {
00755       eexecWrite(&eb, "/OtherBlues [");
00756       for (k = 0; k < privateDicts[fd].nOtherBlues; ++k) {
00757        sprintf(buf, "%s%d", k > 0 ? " " : "", privateDicts[fd].otherBlues[k]);
00758        eexecWrite(&eb, buf);
00759       }
00760       eexecWrite(&eb, "] def\n");
00761     }
00762     if (privateDicts[fd].nFamilyBlues) {
00763       eexecWrite(&eb, "/FamilyBlues [");
00764       for (k = 0; k < privateDicts[fd].nFamilyBlues; ++k) {
00765        sprintf(buf, "%s%d", k > 0 ? " " : "",
00766               privateDicts[fd].familyBlues[k]);
00767        eexecWrite(&eb, buf);
00768       }
00769       eexecWrite(&eb, "] def\n");
00770     }
00771     if (privateDicts[fd].nFamilyOtherBlues) {
00772       eexecWrite(&eb, "/FamilyOtherBlues [");
00773       for (k = 0; k < privateDicts[fd].nFamilyOtherBlues; ++k) {
00774        sprintf(buf, "%s%d", k > 0 ? " " : "",
00775               privateDicts[fd].familyOtherBlues[k]);
00776        eexecWrite(&eb, buf);
00777       }
00778       eexecWrite(&eb, "] def\n");
00779     }
00780     if (privateDicts[fd].blueScale != 0.039625) {
00781       sprintf(buf, "/BlueScale %g def\n", privateDicts[fd].blueScale);
00782       eexecWrite(&eb, buf);
00783     }
00784     if (privateDicts[fd].blueShift != 7) {
00785       sprintf(buf, "/BlueShift %d def\n", privateDicts[fd].blueShift);
00786       eexecWrite(&eb, buf);
00787     }
00788     if (privateDicts[fd].blueFuzz != 1) {
00789       sprintf(buf, "/BlueFuzz %d def\n", privateDicts[fd].blueFuzz);
00790       eexecWrite(&eb, buf);
00791     }
00792     if (privateDicts[fd].hasStdHW) {
00793       sprintf(buf, "/StdHW [%g] def\n", privateDicts[fd].stdHW);
00794       eexecWrite(&eb, buf);
00795     }
00796     if (privateDicts[fd].hasStdVW) {
00797       sprintf(buf, "/StdVW [%g] def\n", privateDicts[fd].stdVW);
00798       eexecWrite(&eb, buf);
00799     }
00800     if (privateDicts[fd].nStemSnapH) {
00801       eexecWrite(&eb, "/StemSnapH [");
00802       for (k = 0; k < privateDicts[fd].nStemSnapH; ++k) {
00803        sprintf(buf, "%s%g", k > 0 ? " " : "", privateDicts[fd].stemSnapH[k]);
00804        eexecWrite(&eb, buf);
00805       }
00806       eexecWrite(&eb, "] def\n");
00807     }
00808     if (privateDicts[fd].nStemSnapV) {
00809       eexecWrite(&eb, "/StemSnapV [");
00810       for (k = 0; k < privateDicts[fd].nStemSnapV; ++k) {
00811        sprintf(buf, "%s%g", k > 0 ? " " : "", privateDicts[fd].stemSnapV[k]);
00812        eexecWrite(&eb, buf);
00813       }
00814       eexecWrite(&eb, "] def\n");
00815     }
00816     if (privateDicts[fd].hasForceBold) {
00817       sprintf(buf, "/ForceBold %s def\n",
00818              privateDicts[fd].forceBold ? "true" : "false");
00819       eexecWrite(&eb, buf);
00820     }
00821     if (privateDicts[fd].forceBoldThreshold != 0) {
00822       sprintf(buf, "/ForceBoldThreshold %g def\n",
00823              privateDicts[fd].forceBoldThreshold);
00824       eexecWrite(&eb, buf);
00825     }
00826     if (privateDicts[fd].languageGroup != 0) {
00827       sprintf(buf, "/LanguageGroup %d def\n", privateDicts[fd].languageGroup);
00828       eexecWrite(&eb, buf);
00829     }
00830     if (privateDicts[fd].expansionFactor != 0.06) {
00831       sprintf(buf, "/ExpansionFactor %g def\n",
00832              privateDicts[fd].expansionFactor);
00833       eexecWrite(&eb, buf);
00834     }
00835 
00836     // set up the subroutines
00837     ok = gTrue;
00838     getIndex(privateDicts[fd].subrsOffset, &subrIdx, &ok);
00839     if (!ok) {
00840       subrIdx.pos = -1;
00841     }
00842 
00843     // start the CharStrings
00844     sprintf(buf, "2 index /CharStrings 256 dict dup begin\n");
00845     eexecWrite(&eb, buf);
00846 
00847     // write the .notdef CharString
00848     ok = gTrue;
00849     getIndexVal(&charStringsIdx, 0, &val, &ok);
00850     if (ok) {
00851       eexecCvtGlyph(&eb, ".notdef", val.pos, val.len,
00852                   &subrIdx, &privateDicts[fd]);
00853     }
00854 
00855     // write the CharStrings
00856     for (j = 0; j < 256 && i+j < nCIDs; ++j) {
00857       if (cidMap[i+j] >= 0) {
00858        ok = gTrue;
00859        getIndexVal(&charStringsIdx, cidMap[i+j], &val, &ok);
00860        if (ok) {
00861          sprintf(buf, "c%02x", j);
00862          eexecCvtGlyph(&eb, buf, val.pos, val.len,
00863                      &subrIdx, &privateDicts[fd]);
00864        }
00865       }
00866     }
00867     eexecWrite(&eb, "end\n");
00868     eexecWrite(&eb, "end\n");
00869     eexecWrite(&eb, "readonly put\n");
00870     eexecWrite(&eb, "noaccess put\n");
00871     eexecWrite(&eb, "dup /FontName get exch definefont pop\n");
00872     eexecWrite(&eb, "mark currentfile closefile\n");
00873 
00874     // trailer
00875     if (eb.line > 0) {
00876       (*outputFunc)(outputStream, "\n", 1);
00877     }
00878     for (j = 0; j < 8; ++j) {
00879       (*outputFunc)(outputStream, "0000000000000000000000000000000000000000000000000000000000000000\n", 65);
00880     }
00881     (*outputFunc)(outputStream, "cleartomark\n", 12);
00882   }
00883 
00884   // write the Type 0 parent font
00885   (*outputFunc)(outputStream, "16 dict begin\n", 14);
00886   (*outputFunc)(outputStream, "/FontName /", 11);
00887   (*outputFunc)(outputStream, psName, strlen(psName));
00888   (*outputFunc)(outputStream, " def\n", 5);
00889   (*outputFunc)(outputStream, "/FontType 0 def\n", 16);
00890   (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
00891   (*outputFunc)(outputStream, "/FMapType 2 def\n", 16);
00892   (*outputFunc)(outputStream, "/Encoding [\n", 12);
00893   for (i = 0; i < nCIDs; i += 256) {
00894     sprintf(buf, "%d\n", i >> 8);
00895     (*outputFunc)(outputStream, buf, strlen(buf));
00896   }
00897   (*outputFunc)(outputStream, "] def\n", 6);
00898   (*outputFunc)(outputStream, "/FDepVector [\n", 14);
00899   for (i = 0; i < nCIDs; i += 256) {
00900     (*outputFunc)(outputStream, "/", 1);
00901     (*outputFunc)(outputStream, psName, strlen(psName));
00902     sprintf(buf, "_%02x findfont\n", i >> 8);
00903     (*outputFunc)(outputStream, buf, strlen(buf));
00904   }
00905   (*outputFunc)(outputStream, "] def\n", 6);
00906   (*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40);
00907 
00908   gfree(cidMap);
00909 }
00910 
00911 void FoFiType1C::eexecCvtGlyph(Type1CEexecBuf *eb, char *glyphName,
00912                             int offset, int nBytes,
00913                             Type1CIndex *subrIdx,
00914                             Type1CPrivateDict *pDict) {
00915   char buf[512];
00916   GString *charBuf;
00917 
00918   // generate the charstring
00919   charBuf = new GString();
00920   cvtGlyph(offset, nBytes, charBuf, subrIdx, pDict, gTrue);
00921 
00922   sprintf(buf, "/%s %d RD ", glyphName, charBuf->getLength());
00923   eexecWrite(eb, buf);
00924   eexecWriteCharstring(eb, (Guchar *)charBuf->getCString(),
00925                      charBuf->getLength());
00926   eexecWrite(eb, " ND\n");
00927 
00928   delete charBuf;
00929 }
00930 
00931 void FoFiType1C::cvtGlyph(int offset, int nBytes, GString *charBuf,
00932                        Type1CIndex *subrIdx, Type1CPrivateDict *pDict,
00933                        GBool top) {
00934   Type1CIndexVal val;
00935   GBool ok, dFP;
00936   double d, dx, dy;
00937   Gushort r2;
00938   Guchar byte;
00939   int pos, subrBias, start, i, k;
00940 
00941   start = charBuf->getLength();
00942   if (top) {
00943     charBuf->append((char)73);
00944     charBuf->append((char)58);
00945     charBuf->append((char)147);
00946     charBuf->append((char)134);
00947     nOps = 0;
00948     nHints = 0;
00949     firstOp = gTrue;
00950   }
00951 
00952   pos = offset;
00953   while (pos < offset + nBytes) {
00954     ok = gTrue;
00955     pos = getOp(pos, gTrue, &ok);
00956     if (!ok) {
00957       break;
00958     }
00959     if (!ops[nOps - 1].isNum) {
00960       --nOps; // drop the operator
00961       switch (ops[nOps].op) {
00962       case 0x0001:          // hstem
00963        if (firstOp) {
00964          cvtGlyphWidth(nOps & 1, charBuf, pDict);
00965          firstOp = gFalse;
00966        }
00967        if (nOps & 1) {
00968          //~ error(-1, "Wrong number of args (%d) to Type 2 hstem", nOps);
00969        }
00970        d = 0;
00971        dFP = gFalse;
00972        for (k = 0; k < nOps; k += 2) {
00973          if (ops[k+1].num < 0) {
00974            d += ops[k].num + ops[k+1].num;
00975            dFP |= ops[k].isFP | ops[k+1].isFP;
00976            cvtNum(d, dFP, charBuf);
00977            cvtNum(-ops[k+1].num, ops[k+1].isFP, charBuf);
00978          } else {
00979            d += ops[k].num;
00980            dFP |= ops[k].isFP;
00981            cvtNum(d, dFP, charBuf);
00982            cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
00983            d += ops[k+1].num;
00984            dFP |= ops[k+1].isFP;
00985          }
00986          charBuf->append((char)1);
00987        }
00988        nHints += nOps / 2;
00989        nOps = 0;
00990        break;
00991       case 0x0003:          // vstem
00992        if (firstOp) {
00993          cvtGlyphWidth(nOps & 1, charBuf, pDict);
00994          firstOp = gFalse;
00995        }
00996        if (nOps & 1) {
00997          //~ error(-1, "Wrong number of args (%d) to Type 2 vstem", nOps);
00998        }
00999        d = 0;
01000        dFP = gFalse;
01001        for (k = 0; k < nOps; k += 2) {
01002          if (ops[k+1].num < 0) {
01003            d += ops[k].num + ops[k+1].num;
01004            dFP |= ops[k].isFP | ops[k+1].isFP;
01005            cvtNum(d, dFP, charBuf);
01006            cvtNum(-ops[k+1].num, ops[k+1].isFP, charBuf);
01007          } else {
01008            d += ops[k].num;
01009            dFP |= ops[k].isFP;
01010            cvtNum(d, dFP, charBuf);
01011            cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
01012            d += ops[k+1].num;
01013            dFP |= ops[k+1].isFP;
01014          }
01015          charBuf->append((char)3);
01016        }
01017        nHints += nOps / 2;
01018        nOps = 0;
01019        break;
01020       case 0x0004:          // vmoveto
01021        if (firstOp) {
01022          cvtGlyphWidth(nOps == 2, charBuf, pDict);
01023          firstOp = gFalse;
01024        }
01025        if (nOps != 1) {
01026          //~ error(-1, "Wrong number of args (%d) to Type 2 vmoveto", nOps);
01027        }
01028        cvtNum(ops[0].num, ops[0].isFP, charBuf);
01029        charBuf->append((char)4);
01030        nOps = 0;
01031        break;
01032       case 0x0005:          // rlineto
01033        if (nOps < 2 || nOps % 2 != 0) {
01034          //~ error(-1, "Wrong number of args (%d) to Type 2 rlineto", nOps);
01035        }
01036        for (k = 0; k < nOps; k += 2) {
01037          cvtNum(ops[k].num, ops[k].isFP, charBuf);
01038          cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
01039          charBuf->append((char)5);
01040        }
01041        nOps = 0;
01042        break;
01043       case 0x0006:          // hlineto
01044        if (nOps < 1) {
01045          //~ error(-1, "Wrong number of args (%d) to Type 2 hlineto", nOps);
01046        }
01047        for (k = 0; k < nOps; ++k) {
01048          cvtNum(ops[k].num, ops[k].isFP, charBuf);
01049          charBuf->append((char)((k & 1) ? 7 : 6));
01050        }
01051        nOps = 0;
01052        break;
01053       case 0x0007:          // vlineto
01054        if (nOps < 1) {
01055          //~ error(-1, "Wrong number of args (%d) to Type 2 vlineto", nOps);
01056        }
01057        for (k = 0; k < nOps; ++k) {
01058          cvtNum(ops[k].num, ops[k].isFP, charBuf);
01059          charBuf->append((char)((k & 1) ? 6 : 7));
01060        }
01061        nOps = 0;
01062        break;
01063       case 0x0008:          // rrcurveto
01064        if (nOps < 6 || nOps % 6 != 0) {
01065          //~ error(-1, "Wrong number of args (%d) to Type 2 rrcurveto", nOps);
01066        }
01067        for (k = 0; k < nOps; k += 6) {
01068          cvtNum(ops[k].num, ops[k].isFP, charBuf);
01069          cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
01070          cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
01071          cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
01072          cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf);
01073          cvtNum(ops[k+5].num, ops[k+5].isFP, charBuf);
01074          charBuf->append((char)8);
01075        }
01076        nOps = 0;
01077        break;
01078       case 0x000a:          // callsubr
01079        if (nOps >= 1) {
01080          subrBias = (subrIdx->len < 1240)
01081                       ? 107 : (subrIdx->len < 33900) ? 1131 : 32768;
01082          k = subrBias + (int)ops[nOps - 1].num;
01083          --nOps;
01084          ok = gTrue;
01085          getIndexVal(subrIdx, k, &val, &ok);
01086          if (ok) {
01087            cvtGlyph(val.pos, val.len, charBuf, subrIdx, pDict, gFalse);
01088          }
01089        } else {
01090          //~ error(-1, "Too few args to Type 2 callsubr");
01091        }
01092        // don't clear the stack
01093        break;
01094       case 0x000b:          // return
01095        // don't clear the stack
01096        break;
01097       case 0x000e:          // endchar / seac
01098        if (firstOp) {
01099          cvtGlyphWidth(nOps == 1 || nOps == 5, charBuf, pDict);
01100          firstOp = gFalse;
01101        }
01102        if (nOps == 4) {
01103          cvtNum(0, gFalse, charBuf);
01104          cvtNum(ops[0].num, ops[0].isFP, charBuf);
01105          cvtNum(ops[1].num, ops[1].isFP, charBuf);
01106          cvtNum(ops[2].num, ops[2].isFP, charBuf);
01107          cvtNum(ops[3].num, ops[3].isFP, charBuf);
01108          charBuf->append((char)12)->append((char)6);
01109        } else if (nOps == 0) {
01110          charBuf->append((char)14);
01111        } else {
01112          //~ error(-1, "Wrong number of args (%d) to Type 2 endchar", nOps);
01113        }
01114        nOps = 0;
01115        break;
01116       case 0x000f:          // (obsolete)
01117        // this op is ignored, but we need the glyph width
01118        if (firstOp) {
01119          cvtGlyphWidth(nOps > 0, charBuf, pDict);
01120          firstOp = gFalse;
01121        }
01122        nOps = 0;
01123        break;
01124       case 0x0010:          // blend
01125        //~ error(-1, "Unimplemented Type 2 charstring op: %d", file[i]);
01126        nOps = 0;
01127        break;
01128       case 0x0012:          // hstemhm
01129        // ignored
01130        if (firstOp) {
01131          cvtGlyphWidth(nOps & 1, charBuf, pDict);
01132          firstOp = gFalse;
01133        }
01134        if (nOps & 1) {
01135          //~ error(-1, "Wrong number of args (%d) to Type 2 hstemhm", nOps);
01136        }
01137        nHints += nOps / 2;
01138        nOps = 0;
01139        break;
01140       case 0x0013:          // hintmask
01141        // ignored
01142        if (firstOp) {
01143          cvtGlyphWidth(nOps & 1, charBuf, pDict);
01144          firstOp = gFalse;
01145        }
01146        if (nOps > 0) {
01147          if (nOps & 1) {
01148            //~ error(-1, "Wrong number of args (%d) to Type 2 hintmask/vstemhm",
01149            //~       nOps);
01150          }
01151          nHints += nOps / 2;
01152        }
01153        pos += (nHints + 7) >> 3;
01154        nOps = 0;
01155        break;
01156       case 0x0014:          // cntrmask
01157        // ignored
01158        if (firstOp) {
01159          cvtGlyphWidth(nOps & 1, charBuf, pDict);
01160          firstOp = gFalse;
01161        }
01162        if (nOps > 0) {
01163          if (nOps & 1) {
01164            //~ error(-1, "Wrong number of args (%d) to Type 2 cntrmask/vstemhm",
01165            //~       nOps);
01166          }
01167          nHints += nOps / 2;
01168        }
01169        pos += (nHints + 7) >> 3;
01170        nOps = 0;
01171        break;
01172       case 0x0015:          // rmoveto
01173        if (firstOp) {
01174          cvtGlyphWidth(nOps == 3, charBuf, pDict);
01175          firstOp = gFalse;
01176        }
01177        if (nOps != 2) {
01178          //~ error(-1, "Wrong number of args (%d) to Type 2 rmoveto", nOps);
01179        }
01180        cvtNum(ops[0].num, ops[0].isFP, charBuf);
01181        cvtNum(ops[1].num, ops[1].isFP, charBuf);
01182        charBuf->append((char)21);
01183        nOps = 0;
01184        break;
01185       case 0x0016:          // hmoveto
01186        if (firstOp) {
01187          cvtGlyphWidth(nOps == 2, charBuf, pDict);
01188          firstOp = gFalse;
01189        }
01190        if (nOps != 1) {
01191          //~ error(-1, "Wrong number of args (%d) to Type 2 hmoveto", nOps);
01192        }
01193        cvtNum(ops[0].num, ops[0].isFP, charBuf);
01194        charBuf->append((char)22);
01195        nOps = 0;
01196        break;
01197       case 0x0017:          // vstemhm
01198        // ignored
01199        if (firstOp) {
01200          cvtGlyphWidth(nOps & 1, charBuf, pDict);
01201          firstOp = gFalse;
01202        }
01203        if (nOps & 1) {
01204          //~ error(-1, "Wrong number of args (%d) to Type 2 vstemhm", nOps);
01205        }
01206        nHints += nOps / 2;
01207        nOps = 0;
01208        break;
01209       case 0x0018:          // rcurveline
01210        if (nOps < 8 || (nOps - 2) % 6 != 0) {
01211          //~ error(-1, "Wrong number of args (%d) to Type 2 rcurveline", nOps);
01212        }
01213        for (k = 0; k < nOps - 2; k += 6) {
01214          cvtNum(ops[k].num, ops[k].isFP, charBuf);
01215          cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
01216          cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
01217          cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
01218          cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf);
01219          cvtNum(ops[k+5].num, ops[k+5].isFP, charBuf);
01220          charBuf->append((char)8);
01221        }
01222        cvtNum(ops[k].num, ops[k].isFP, charBuf);
01223        cvtNum(ops[k+1].num, ops[k].isFP, charBuf);
01224        charBuf->append((char)5);
01225        nOps = 0;
01226        break;
01227       case 0x0019:          // rlinecurve
01228        if (nOps < 8 || (nOps - 6) % 2 != 0) {
01229          //~ error(-1, "Wrong number of args (%d) to Type 2 rlinecurve", nOps);
01230        }
01231        for (k = 0; k < nOps - 6; k += 2) {
01232          cvtNum(ops[k].num, ops[k].isFP, charBuf);
01233          cvtNum(ops[k+1].num, ops[k].isFP, charBuf);
01234          charBuf->append((char)5);
01235        }
01236        cvtNum(ops[k].num, ops[k].isFP, charBuf);
01237        cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
01238        cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
01239        cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
01240        cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf);
01241        cvtNum(ops[k+5].num, ops[k+5].isFP, charBuf);
01242        charBuf->append((char)8);
01243        nOps = 0;
01244        break;
01245       case 0x001a:          // vvcurveto
01246        if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
01247          //~ error(-1, "Wrong number of args (%d) to Type 2 vvcurveto", nOps);
01248        }
01249        if (nOps % 2 == 1) {
01250          cvtNum(ops[0].num, ops[0].isFP, charBuf);
01251          cvtNum(ops[1].num, ops[1].isFP, charBuf);
01252          cvtNum(ops[2].num, ops[2].isFP, charBuf);
01253          cvtNum(ops[3].num, ops[3].isFP, charBuf);
01254          cvtNum(0, gFalse, charBuf);
01255          cvtNum(ops[4].num, ops[4].isFP, charBuf);
01256          charBuf->append((char)8);
01257          k = 5;
01258        } else {
01259          k = 0;
01260        }
01261        for (; k < nOps; k += 4) {
01262          cvtNum(0, gFalse, charBuf);
01263          cvtNum(ops[k].num, ops[k].isFP, charBuf);
01264          cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
01265          cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
01266          cvtNum(0, gFalse, charBuf);
01267          cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
01268          charBuf->append((char)8);
01269        }
01270        nOps = 0;
01271        break;
01272       case 0x001b:          // hhcurveto
01273        if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
01274          //~ error(-1, "Wrong number of args (%d) to Type 2 hhcurveto", nOps);
01275        }
01276        if (nOps % 2 == 1) {
01277          cvtNum(ops[1].num, ops[1].isFP, charBuf);
01278          cvtNum(ops[0].num, ops[0].isFP, charBuf);
01279          cvtNum(ops[2].num, ops[2].isFP, charBuf);
01280          cvtNum(ops[3].num, ops[3].isFP, charBuf);
01281          cvtNum(ops[4].num, ops[4].isFP, charBuf);
01282          cvtNum(0, gFalse, charBuf);
01283          charBuf->append((char)8);
01284          k = 5;
01285        } else {
01286          k = 0;
01287        }
01288        for (; k < nOps; k += 4) {
01289          cvtNum(ops[k].num, ops[k].isFP, charBuf);
01290          cvtNum(0, gFalse, charBuf);
01291          cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
01292          cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
01293          cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
01294          cvtNum(0, gFalse, charBuf);
01295          charBuf->append((char)8);
01296        }
01297        nOps = 0;
01298        break;
01299       case 0x001d:          // callgsubr
01300        if (nOps >= 1) {
01301          k = gsubrBias + (int)ops[nOps - 1].num;
01302          --nOps;
01303          ok = gTrue;
01304          getIndexVal(&gsubrIdx, k, &val, &ok);
01305          if (ok) {
01306            cvtGlyph(val.pos, val.len, charBuf, subrIdx, pDict, gFalse);
01307          }
01308        } else {
01309          //~ error(-1, "Too few args to Type 2 callgsubr");
01310        }
01311        // don't clear the stack
01312        break;
01313       case 0x001e:          // vhcurveto
01314        if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
01315          //~ error(-1, "Wrong number of args (%d) to Type 2 vhcurveto", nOps);
01316        }
01317        for (k = 0; k < nOps && k != nOps-5; k += 4) {
01318          if (k % 8 == 0) {
01319            cvtNum(ops[k].num, ops[k].isFP, charBuf);
01320            cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
01321            cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
01322            cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
01323            charBuf->append((char)30);
01324          } else {
01325            cvtNum(ops[k].num, ops[k].isFP, charBuf);
01326            cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
01327            cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
01328            cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
01329            charBuf->append((char)31);
01330          }
01331        }
01332        if (k == nOps-5) {
01333          if (k % 8 == 0) {
01334            cvtNum(0, gFalse, charBuf);
01335            cvtNum(ops[k].num, ops[k].isFP, charBuf);
01336            cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
01337            cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
01338            cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
01339            cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf);
01340          } else {
01341            cvtNum(ops[k].num, ops[k].isFP, charBuf);
01342            cvtNum(0, gFalse, charBuf);
01343            cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
01344            cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
01345            cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf);
01346            cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
01347          }
01348          charBuf->append((char)8);
01349        }
01350        nOps = 0;
01351        break;
01352       case 0x001f:          // hvcurveto
01353        if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
01354          //~ error(-1, "Wrong number of args (%d) to Type 2 hvcurveto", nOps);
01355        }
01356        for (k = 0; k < nOps && k != nOps-5; k += 4) {
01357          if (k % 8 == 0) {
01358            cvtNum(ops[k].num, ops[k].isFP, charBuf);
01359            cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
01360            cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
01361            cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
01362            charBuf->append((char)31);
01363          } else {
01364            cvtNum(ops[k].num, ops[k].isFP, charBuf);
01365            cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
01366            cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
01367            cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
01368            charBuf->append((char)30);
01369          }
01370        }
01371        if (k == nOps-5) {
01372          if (k % 8 == 0) {
01373            cvtNum(ops[k].num, ops[k].isFP, charBuf);
01374            cvtNum(0, gFalse, charBuf);
01375            cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
01376            cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
01377            cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf);
01378            cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
01379          } else {
01380            cvtNum(0, gFalse, charBuf);
01381            cvtNum(ops[k].num, ops[k].isFP, charBuf);
01382            cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
01383            cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
01384            cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
01385            cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf);
01386          }
01387          charBuf->append((char)8);
01388        }
01389        nOps = 0;
01390        break;
01391       case 0x0c00:          // dotsection (should be Type 1 only?)
01392        // ignored
01393        nOps = 0;
01394        break;
01395       case 0x0c03:          // and
01396       case 0x0c04:          // or
01397       case 0x0c05:          // not
01398       case 0x0c08:          // store
01399       case 0x0c09:          // abs
01400       case 0x0c0a:          // add
01401       case 0x0c0b:          // sub
01402       case 0x0c0c:          // div
01403       case 0x0c0d:          // load
01404       case 0x0c0e:          // neg
01405       case 0x0c0f:          // eq
01406       case 0x0c12:          // drop
01407       case 0x0c14:          // put
01408       case 0x0c15:          // get
01409       case 0x0c16:          // ifelse
01410       case 0x0c17:          // random
01411       case 0x0c18:          // mul
01412       case 0x0c1a:          // sqrt
01413       case 0x0c1b:          // dup
01414       case 0x0c1c:          // exch
01415       case 0x0c1d:          // index
01416       case 0x0c1e:          // roll
01417        //~ error(-1, "Unimplemented Type 2 charstring op: 12.%d", file[i+1]);
01418        nOps = 0;
01419        break;
01420       case 0x0c22:          // hflex
01421        if (nOps != 7) {
01422          //~ error(-1, "Wrong number of args (%d) to Type 2 hflex", nOps);
01423        }
01424        cvtNum(ops[0].num, ops[0].isFP, charBuf);
01425        cvtNum(0, gFalse, charBuf);
01426        cvtNum(ops[1].num, ops[1].isFP, charBuf);
01427        cvtNum(ops[2].num, ops[2].isFP, charBuf);
01428        cvtNum(ops[3].num, ops[3].isFP, charBuf);
01429        cvtNum(0, gFalse, charBuf);
01430        charBuf->append((char)8);
01431        cvtNum(ops[4].num, ops[4].isFP, charBuf);
01432        cvtNum(0, gFalse, charBuf);
01433        cvtNum(ops[5].num, ops[5].isFP, charBuf);
01434        cvtNum(-ops[2].num, ops[2].isFP, charBuf);
01435        cvtNum(ops[6].num, ops[6].isFP, charBuf);
01436        cvtNum(0, gFalse, charBuf);
01437        charBuf->append((char)8);
01438        nOps = 0;
01439        break;
01440       case 0x0c23:          // flex
01441        if (nOps != 13) {
01442          //~ error(-1, "Wrong number of args (%d) to Type 2 flex", nOps);
01443        }
01444        cvtNum(ops[0].num, ops[0].isFP, charBuf);
01445        cvtNum(ops[1].num, ops[1].isFP, charBuf);
01446        cvtNum(ops[2].num, ops[2].isFP, charBuf);
01447        cvtNum(ops[3].num, ops[3].isFP, charBuf);
01448        cvtNum(ops[4].num, ops[4].isFP, charBuf);
01449        cvtNum(ops[5].num, ops[5].isFP, charBuf);
01450        charBuf->append((char)8);
01451        cvtNum(ops[6].num, ops[6].isFP, charBuf);
01452        cvtNum(ops[7].num, ops[7].isFP, charBuf);
01453        cvtNum(ops[8].num, ops[8].isFP, charBuf);
01454        cvtNum(ops[9].num, ops[9].isFP, charBuf);
01455        cvtNum(ops[10].num, ops[10].isFP, charBuf);
01456        cvtNum(ops[11].num, ops[11].isFP, charBuf);
01457        charBuf->append((char)8);
01458        nOps = 0;
01459        break;
01460       case 0x0c24:          // hflex1
01461        if (nOps != 9) {
01462          //~ error(-1, "Wrong number of args (%d) to Type 2 hflex1", nOps);
01463        }
01464        cvtNum(ops[0].num, ops[0].isFP, charBuf);
01465        cvtNum(ops[1].num, ops[1].isFP, charBuf);
01466        cvtNum(ops[2].num, ops[2].isFP, charBuf);
01467        cvtNum(ops[3].num, ops[3].isFP, charBuf);
01468        cvtNum(ops[4].num, ops[4].isFP, charBuf);
01469        cvtNum(0, gFalse, charBuf);
01470        charBuf->append((char)8);
01471        cvtNum(ops[5].num, ops[5].isFP, charBuf);
01472        cvtNum(0, gFalse, charBuf);
01473        cvtNum(ops[6].num, ops[6].isFP, charBuf);
01474        cvtNum(ops[7].num, ops[7].isFP, charBuf);
01475        cvtNum(ops[8].num, ops[8].isFP, charBuf);
01476        cvtNum(-(ops[1].num + ops[3].num + ops[7].num),
01477               ops[1].isFP | ops[3].isFP | ops[7].isFP, charBuf);
01478        charBuf->append((char)8);
01479        nOps = 0;
01480        break;
01481       case 0x0c25:          // flex1
01482        if (nOps != 11) {
01483          //~ error(-1, "Wrong number of args (%d) to Type 2 flex1", nOps);
01484        }
01485        cvtNum(ops[0].num, ops[0].isFP, charBuf);
01486        cvtNum(ops[1].num, ops[1].isFP, charBuf);
01487        cvtNum(ops[2].num, ops[2].isFP, charBuf);
01488        cvtNum(ops[3].num, ops[3].isFP, charBuf);
01489        cvtNum(ops[4].num, ops[4].isFP, charBuf);
01490        cvtNum(ops[5].num, ops[5].isFP, charBuf);
01491        charBuf->append((char)8);
01492        cvtNum(ops[6].num, ops[6].isFP, charBuf);
01493        cvtNum(ops[7].num, ops[7].isFP, charBuf);
01494        cvtNum(ops[8].num, ops[8].isFP, charBuf);
01495        cvtNum(ops[9].num, ops[9].isFP, charBuf);
01496        dx = ops[0].num + ops[2].num + ops[4].num + ops[6].num + ops[8].num;
01497        dy = ops[1].num + ops[3].num + ops[5].num + ops[7].num + ops[9].num;
01498        if (fabs(dx) > fabs(dy)) {
01499          cvtNum(ops[10].num, ops[10].isFP, charBuf);
01500          cvtNum(-dy, ops[1].isFP | ops[3].isFP | ops[5].isFP |
01501                     ops[7].isFP | ops[9].isFP, charBuf);
01502        } else {
01503          cvtNum(-dx, ops[0].isFP | ops[2].isFP | ops[4].isFP |
01504                     ops[6].isFP | ops[8].isFP, charBuf);
01505          cvtNum(ops[10].num, ops[10].isFP, charBuf);
01506        }
01507        charBuf->append((char)8);
01508        nOps = 0;
01509        break;
01510       default:
01511        //~ error(-1, "Illegal Type 2 charstring op: %04x",
01512        //~       ops[nOps].op);
01513        nOps = 0;
01514        break;
01515       }
01516     }
01517   }
01518 
01519   // charstring encryption
01520   if (top) {
01521     r2 = 4330;
01522     for (i = start; i < charBuf->getLength(); ++i) {
01523       byte = charBuf->getChar(i) ^ (r2 >> 8);
01524       charBuf->setChar(i, byte);
01525       r2 = (byte + r2) * 52845 + 22719;
01526     }
01527   }
01528 }
01529 
01530 void FoFiType1C::cvtGlyphWidth(GBool useOp, GString *charBuf,
01531                             Type1CPrivateDict *pDict) {
01532   double w;
01533   GBool wFP;
01534   int i;
01535 
01536   if (useOp) {
01537     w = pDict->nominalWidthX + ops[0].num;
01538     wFP = pDict->nominalWidthXFP | ops[0].isFP;
01539     for (i = 1; i < nOps; ++i) {
01540       ops[i-1] = ops[i];
01541     }
01542     --nOps;
01543   } else {
01544     w = pDict->defaultWidthX;
01545     wFP = pDict->defaultWidthXFP;
01546   }
01547   cvtNum(0, gFalse, charBuf);
01548   cvtNum(w, wFP, charBuf);
01549   charBuf->append((char)13);
01550 }
01551 
01552 void FoFiType1C::cvtNum(double x, GBool isFP, GString *charBuf) {
01553   Guchar buf[12];
01554   int y, n;
01555 
01556   n = 0;
01557   if (isFP) {
01558     if (x >= -32768 && x < 32768) {
01559       y = (int)(x * 256.0);
01560       buf[0] = 255;
01561       buf[1] = (Guchar)(y >> 24);
01562       buf[2] = (Guchar)(y >> 16);
01563       buf[3] = (Guchar)(y >> 8);
01564       buf[4] = (Guchar)y;
01565       buf[5] = 255;
01566       buf[6] = 0;
01567       buf[7] = 0;
01568       buf[8] = 1;
01569       buf[9] = 0;
01570       buf[10] = 12;
01571       buf[11] = 12;
01572       n = 12;
01573     } else {
01574       //~ error(-1, "Type 2 fixed point constant out of range");
01575     }
01576   } else {
01577     y = (int)x;
01578     if (y >= -107 && y <= 107) {
01579       buf[0] = (Guchar)(y + 139);
01580       n = 1;
01581     } else if (y > 107 && y <= 1131) {
01582       y -= 108;
01583       buf[0] = (Guchar)((y >> 8) + 247);
01584       buf[1] = (Guchar)(y & 0xff);
01585       n = 2;
01586     } else if (y < -107 && y >= -1131) {
01587       y = -y - 108;
01588       buf[0] = (Guchar)((y >> 8) + 251);
01589       buf[1] = (Guchar)(y & 0xff);
01590       n = 2;
01591     } else {
01592       buf[0] = 255;
01593       buf[1] = (Guchar)(y >> 24);
01594       buf[2] = (Guchar)(y >> 16);
01595       buf[3] = (Guchar)(y >> 8);
01596       buf[4] = (Guchar)y;
01597       n = 5;
01598     }
01599   }
01600   charBuf->append((char *)buf, n);
01601 }
01602 
01603 void FoFiType1C::eexecWrite(Type1CEexecBuf *eb, char *s) {
01604   Guchar *p;
01605   Guchar x;
01606 
01607   for (p = (Guchar *)s; *p; ++p) {
01608     x = *p ^ (eb->r1 >> 8);
01609     eb->r1 = (x + eb->r1) * 52845 + 22719;
01610     if (eb->ascii) {
01611       (*eb->outputFunc)(eb->outputStream, &hexChars[x >> 4], 1);
01612       (*eb->outputFunc)(eb->outputStream, &hexChars[x & 0x0f], 1);
01613       eb->line += 2;
01614       if (eb->line == 64) {
01615        (*eb->outputFunc)(eb->outputStream, "\n", 1);
01616        eb->line = 0;
01617       }
01618     } else {
01619       (*eb->outputFunc)(eb->outputStream, (char *)&x, 1);
01620     }
01621   }
01622 }
01623 
01624 void FoFiType1C::eexecWriteCharstring(Type1CEexecBuf *eb,
01625                                   Guchar *s, int n) {
01626   Guchar x;
01627   int i;
01628 
01629   // eexec encryption
01630   for (i = 0; i < n; ++i) {
01631     x = s[i] ^ (eb->r1 >> 8);
01632     eb->r1 = (x + eb->r1) * 52845 + 22719;
01633     if (eb->ascii) {
01634       (*eb->outputFunc)(eb->outputStream, &hexChars[x >> 4], 1);
01635       (*eb->outputFunc)(eb->outputStream, &hexChars[x & 0x0f], 1);
01636       eb->line += 2;
01637       if (eb->line == 64) {
01638        (*eb->outputFunc)(eb->outputStream, "\n", 1);
01639        eb->line = 0;
01640       }
01641     } else {
01642       (*eb->outputFunc)(eb->outputStream, (char *)&x, 1);
01643     }
01644   }
01645 }
01646 
01647 GBool FoFiType1C::parse() {
01648   Type1CIndex fdIdx;
01649   Type1CIndexVal val;
01650   int i;
01651 
01652   parsedOk = gTrue;
01653 
01654   // some tools embed Type 1C fonts with an extra whitespace char at
01655   // the beginning
01656   if (len > 0 && file[0] != '\x01') {
01657     ++file;
01658     --len;
01659   }
01660 
01661   // find the indexes
01662   getIndex(getU8(2, &parsedOk), &nameIdx, &parsedOk);
01663   getIndex(nameIdx.endPos, &topDictIdx, &parsedOk);
01664   getIndex(topDictIdx.endPos, &stringIdx, &parsedOk);
01665   getIndex(stringIdx.endPos, &gsubrIdx, &parsedOk);
01666   if (!parsedOk) {
01667     return gFalse;
01668   }
01669   gsubrBias = (gsubrIdx.len < 1240) ? 107
01670                                     : (gsubrIdx.len < 33900) ? 1131 : 32768;
01671 
01672   // read the first font name
01673   getIndexVal(&nameIdx, 0, &val, &parsedOk);
01674   if (!parsedOk) {
01675     return gFalse;
01676   }
01677   name = new GString((char *)&file[val.pos], val.len);
01678 
01679   // read the top dict for the first font
01680   readTopDict();
01681 
01682   // for CID fonts: read the FDArray dicts and private dicts
01683   if (topDict.firstOp == 0x0c1e) {
01684     if (topDict.fdArrayOffset == 0) {
01685       nFDs = 1;
01686       privateDicts = (Type1CPrivateDict *)gmalloc(sizeof(Type1CPrivateDict));
01687       readPrivateDict(0, 0, &privateDicts[0]);
01688     } else {
01689       getIndex(topDict.fdArrayOffset, &fdIdx, &parsedOk);
01690       if (!parsedOk) {
01691        return gFalse;
01692       }
01693       nFDs = fdIdx.len;
01694       privateDicts = (Type1CPrivateDict *)
01695                         gmalloc(nFDs * sizeof(Type1CPrivateDict));
01696       for (i = 0; i < nFDs; ++i) {
01697        getIndexVal(&fdIdx, i, &val, &parsedOk);
01698        if (!parsedOk) {
01699          return gFalse;
01700        }
01701        readFD(val.pos, val.len, &privateDicts[i]);
01702       }
01703     }
01704 
01705   // for 8-bit fonts: read the private dict
01706   } else {
01707     privateDicts = (Type1CPrivateDict *)gmalloc(sizeof(Type1CPrivateDict));
01708     readPrivateDict(topDict.privateOffset, topDict.privateSize,
01709                   &privateDicts[0]);
01710   }
01711 
01712   // check for parse errors in the private dict(s)
01713   if (!parsedOk) {
01714     return gFalse;
01715   }
01716 
01717   // get the charstrings index
01718   if (topDict.charStringsOffset <= 0) {
01719     parsedOk = gFalse;
01720     return gFalse;
01721   }
01722   getIndex(topDict.charStringsOffset, &charStringsIdx, &parsedOk);
01723   if (!parsedOk) {
01724     return gFalse;
01725   }
01726   nGlyphs = charStringsIdx.len;
01727 
01728   // for CID fonts: read the FDSelect table
01729   if (topDict.firstOp == 0x0c1e) {
01730     readFDSelect();
01731     if (!parsedOk) {
01732       return gFalse;
01733     }
01734   }
01735 
01736   // read the charset
01737   if (!readCharset()) {
01738     parsedOk = gFalse;
01739     return gFalse;
01740   }
01741 
01742   // for 8-bit fonts: build the encoding
01743   if (topDict.firstOp != 0x0c14 && topDict.firstOp != 0x0c1e) {
01744     buildEncoding();
01745     if (!parsedOk) {
01746       return gFalse;
01747     }
01748   }
01749 
01750   return parsedOk;
01751 }
01752 
01753 void FoFiType1C::readTopDict() {
01754   Type1CIndexVal topDictPtr;
01755   int pos;
01756 
01757   topDict.firstOp = -1;
01758   topDict.versionSID = 0;
01759   topDict.noticeSID = 0;
01760   topDict.copyrightSID = 0;
01761   topDict.fullNameSID = 0;
01762   topDict.familyNameSID = 0;
01763   topDict.weightSID = 0;
01764   topDict.isFixedPitch = 0;
01765   topDict.italicAngle = 0;
01766   topDict.underlinePosition = -100;
01767   topDict.underlineThickness = 50;
01768   topDict.paintType = 0;
01769   topDict.charstringType = 2;
01770   topDict.fontMatrix[0] = 0.001;
01771   topDict.fontMatrix[1] = 0;
01772   topDict.fontMatrix[2] = 0;
01773   topDict.fontMatrix[3] = 0.001;
01774   topDict.fontMatrix[4] = 0;
01775   topDict.fontMatrix[5] = 0;
01776   topDict.uniqueID = 0;
01777   topDict.fontBBox[0] = 0;
01778   topDict.fontBBox[1] = 0;
01779   topDict.fontBBox[2] = 0;
01780   topDict.fontBBox[3] = 0;
01781   topDict.strokeWidth = 0;
01782   topDict.charsetOffset = 0;
01783   topDict.encodingOffset = 0;
01784   topDict.charStringsOffset = 0;
01785   topDict.privateSize = 0;
01786   topDict.privateOffset = 0;
01787   topDict.registrySID = 0;
01788   topDict.orderingSID = 0;
01789   topDict.supplement = 0;
01790   topDict.fdArrayOffset = 0;
01791   topDict.fdSelectOffset = 0;
01792 
01793   getIndexVal(&topDictIdx, 0, &topDictPtr, &parsedOk);
01794   pos = topDictPtr.pos;
01795   nOps = 0;
01796   while (pos < topDictPtr.pos + topDictPtr.len) {
01797     pos = getOp(pos, gFalse, &parsedOk);
01798     if (!parsedOk) {
01799       break;
01800     }
01801     if (!ops[nOps - 1].isNum) {
01802       --nOps; // drop the operator
01803       if (topDict.firstOp < 0) {
01804        topDict.firstOp = ops[nOps].op;
01805       }
01806       switch (ops[nOps].op) {
01807       case 0x0000: topDict.versionSID = (int)ops[0].num; break;
01808       case 0x0001: topDict.noticeSID = (int)ops[0].num; break;
01809       case 0x0c00: topDict.copyrightSID = (int)ops[0].num; break;
01810       case 0x0002: topDict.fullNameSID = (int)ops[0].num; break;
01811       case 0x0003: topDict.familyNameSID = (int)ops[0].num; break;
01812       case 0x0004: topDict.weightSID = (int)ops[0].num; break;
01813       case 0x0c01: topDict.isFixedPitch = (int)ops[0].num; break;
01814       case 0x0c02: topDict.italicAngle = ops[0].num; break;
01815       case 0x0c03: topDict.underlinePosition = ops[0].num; break;
01816       case 0x0c04: topDict.underlineThickness = ops[0].num; break;
01817       case 0x0c05: topDict.paintType = (int)ops[0].num; break;
01818       case 0x0c06: topDict.charstringType = (int)ops[0].num; break;
01819       case 0x0c07: topDict.fontMatrix[0] = ops[0].num;
01820                   topDict.fontMatrix[1] = ops[1].num;
01821                   topDict.fontMatrix[2] = ops[2].num;
01822                   topDict.fontMatrix[3] = ops[3].num;
01823                   topDict.fontMatrix[4] = ops[4].num;
01824                   topDict.fontMatrix[5] = ops[5].num; break;
01825       case 0x000d: topDict.uniqueID = (int)ops[0].num; break;
01826       case 0x0005: topDict.fontBBox[0] = ops[0].num;
01827                   topDict.fontBBox[1] = ops[1].num;
01828                   topDict.fontBBox[2] = ops[2].num;
01829                   topDict.fontBBox[3] = ops[3].num; break;
01830       case 0x0c08: topDict.strokeWidth = ops[0].num; break;
01831       case 0x000f: topDict.charsetOffset = (int)ops[0].num; break;
01832       case 0x0010: topDict.encodingOffset = (int)ops[0].num; break;
01833       case 0x0011: topDict.charStringsOffset = (int)ops[0].num; break;
01834       case 0x0012: topDict.privateSize = (int)ops[0].num;
01835                   topDict.privateOffset = (int)ops[1].num; break;
01836       case 0x0c1e: topDict.registrySID = (int)ops[0].num;
01837                   topDict.orderingSID = (int)ops[1].num;
01838                  topDict.supplement = (int)ops[2].num; break;
01839       case 0x0c24: topDict.fdArrayOffset = (int)ops[0].num; break;
01840       case 0x0c25: topDict.fdSelectOffset = (int)ops[0].num; break;
01841       }
01842       nOps = 0;
01843     }
01844   }
01845 }
01846 
01847 // Read a CID font dict (FD) - this pulls out the private dict
01848 // pointer, and reads the private dict.
01849 void FoFiType1C::readFD(int offset, int length, Type1CPrivateDict *pDict) {
01850   int pos, pSize, pOffset;
01851 
01852   pSize = pOffset = 0;
01853   pos = offset;
01854   nOps = 0;
01855   while (pos < offset + length) {
01856     pos = getOp(pos, gFalse, &parsedOk);
01857     if (!parsedOk) {
01858       return;
01859     }
01860     if (!ops[nOps - 1].isNum) {
01861       if (ops[nOps - 1].op == 0x0012) {
01862        if (nOps < 3) {
01863          parsedOk = gFalse;
01864          return;
01865        }
01866        pSize = (int)ops[0].num;
01867        pOffset = (int)ops[1].num;
01868        break;
01869       }
01870       nOps = 0;
01871     }
01872   }
01873   readPrivateDict(pOffset, pSize, pDict);
01874 }
01875 
01876 void FoFiType1C::readPrivateDict(int offset, int length,
01877                              Type1CPrivateDict *pDict) {
01878   int pos;
01879 
01880   pDict->nBlueValues = 0;
01881   pDict->nOtherBlues = 0;
01882   pDict->nFamilyBlues = 0;
01883   pDict->nFamilyOtherBlues = 0;
01884   pDict->blueScale = 0.039625;
01885   pDict->blueShift = 7;
01886   pDict->blueFuzz = 1;
01887   pDict->hasStdHW = gFalse;
01888   pDict->hasStdVW = gFalse;
01889   pDict->nStemSnapH = 0;
01890   pDict->nStemSnapV = 0;
01891   pDict->hasForceBold = gFalse;
01892   pDict->forceBoldThreshold = 0;
01893   pDict->languageGroup = 0;
01894   pDict->expansionFactor = 0.06;
01895   pDict->initialRandomSeed = 0;
01896   pDict->subrsOffset = 0;
01897   pDict->defaultWidthX = 0;
01898   pDict->defaultWidthXFP = 0;
01899   pDict->nominalWidthX = 0;
01900   pDict->nominalWidthXFP = 0;
01901 
01902   // no dictionary
01903   if (offset == 0 || length == 0) {
01904     return;
01905   }
01906 
01907   pos = offset;
01908   nOps = 0;
01909   while (pos < offset + length) {
01910     pos = getOp(pos, gFalse, &parsedOk);
01911     if (!parsedOk) {
01912       break;
01913     }
01914     if (!ops[nOps - 1].isNum) {
01915       --nOps; // drop the operator
01916       switch (ops[nOps].op) {
01917       case 0x0006:
01918        pDict->nBlueValues = getDeltaIntArray(pDict->blueValues,
01919                                          type1CMaxBlueValues);
01920        break;
01921       case 0x0007:
01922        pDict->nOtherBlues = getDeltaIntArray(pDict->otherBlues,
01923                                          type1CMaxOtherBlues);
01924        break;
01925       case 0x0008:
01926        pDict->nFamilyBlues = getDeltaIntArray(pDict->familyBlues,
01927                                           type1CMaxBlueValues);
01928        break;
01929       case 0x0009:
01930        pDict->nFamilyOtherBlues = getDeltaIntArray(pDict->familyOtherBlues,
01931                                               type1CMaxOtherBlues);
01932        break;
01933       case 0x0c09:
01934        pDict->blueScale = ops[0].num;
01935        break;
01936       case 0x0c0a:
01937        pDict->blueShift = (int)ops[0].num;
01938        break;
01939       case 0x0c0b:
01940        pDict->blueFuzz = (int)ops[0].num;
01941        break;
01942       case 0x000a:
01943        pDict->stdHW = ops[0].num;
01944        pDict->hasStdHW = gTrue;
01945        break;
01946       case 0x000b:
01947        pDict->stdVW = ops[0].num;
01948        pDict->hasStdVW = gTrue;
01949        break;
01950       case 0x0c0c:
01951        pDict->nStemSnapH = getDeltaFPArray(pDict->stemSnapH,
01952                                        type1CMaxStemSnap);
01953        break;
01954       case 0x0c0d:
01955        pDict->nStemSnapV = getDeltaFPArray(pDict->stemSnapV,
01956                                        type1CMaxStemSnap);
01957        break;
01958       case 0x0c0e:
01959        pDict->forceBold = ops[0].num != 0;
01960        pDict->hasForceBold = gTrue;
01961        break;
01962       case 0x0c0f:
01963        pDict->forceBoldThreshold = ops[0].num;
01964        break;
01965       case 0x0c11:
01966        pDict->languageGroup = (int)ops[0].num;
01967        break;
01968       case 0x0c12:
01969        pDict->expansionFactor = ops[0].num;
01970        break;
01971       case 0x0c13:
01972        pDict->initialRandomSeed = (int)ops[0].num;
01973        break;
01974       case 0x0013:
01975        pDict->subrsOffset = offset + (int)ops[0].num;
01976        break;
01977       case 0x0014:
01978        pDict->defaultWidthX = ops[0].num;
01979        break;
01980       case 0x0015:
01981        pDict->nominalWidthX = ops[0].num;
01982        break;
01983       }
01984       nOps = 0;
01985     }
01986   }
01987 }
01988 
01989 void FoFiType1C::readFDSelect() {
01990   int fdSelectFmt, pos, nRanges, gid0, gid1, fd, i, j;
01991 
01992   fdSelect = (Guchar *)gmalloc(nGlyphs);
01993   if (topDict.fdSelectOffset == 0) {
01994     for (i = 0; i < nGlyphs; ++i) {
01995       fdSelect[i] = 0;
01996     }
01997   } else {
01998     pos = topDict.fdSelectOffset;
01999     fdSelectFmt = getU8(pos++, &parsedOk);
02000     if (!parsedOk) {
02001       return;
02002     }
02003     if (fdSelectFmt == 0) {
02004       if (!checkRegion(pos, nGlyphs)) {
02005        parsedOk = gFalse;
02006        return;
02007       }
02008       memcpy(fdSelect, file + pos, nGlyphs);
02009     } else if (fdSelectFmt == 3) {
02010       nRanges = getU16BE(pos, &parsedOk);
02011       pos += 2;
02012       gid0 = getU16BE(pos, &parsedOk);
02013       pos += 2;
02014       for (i = 1; i <= nRanges; ++i) {
02015        fd = getU8(pos++, &parsedOk);
02016        gid1 = getU16BE(pos, &parsedOk);
02017        if (!parsedOk) {
02018          return;
02019        }
02020        pos += 2;
02021        if (gid0 > gid1 || gid1 > nGlyphs) {
02022          //~ error(-1, "Bad FDSelect table in CID font");
02023          parsedOk = gFalse;
02024          return;
02025        }
02026        for (j = gid0; j < gid1; ++j) {
02027          fdSelect[j] = fd;
02028        }
02029        gid0 = gid1;
02030       }
02031     } else {
02032       //~ error(-1, "Unknown FDSelect table format in CID font");
02033       for (i = 0; i < nGlyphs; ++i) {
02034        fdSelect[i] = 0;
02035       }
02036     }
02037   }
02038 }
02039 
02040 void FoFiType1C::buildEncoding() {
02041   char buf[256];
02042   int nCodes, nRanges, encFormat;
02043   int pos, c, sid, nLeft, nSups, i, j;
02044 
02045   if (topDict.encodingOffset == 0) {
02046     encoding = fofiType1StandardEncoding;
02047 
02048   } else if (topDict.encodingOffset == 1) {
02049     encoding = fofiType1ExpertEncoding;
02050 
02051   } else {
02052     encoding = (char **)gmalloc(256 * sizeof(char *));
02053     for (i = 0; i < 256; ++i) {
02054       encoding[i] = NULL;
02055     }
02056     pos = topDict.encodingOffset;
02057     encFormat = getU8(pos++, &parsedOk);
02058     if (!parsedOk) {
02059       return;
02060     }
02061     if ((encFormat & 0x7f) == 0) {
02062       nCodes = 1 + getU8(pos++, &parsedOk);
02063       if (!parsedOk) {
02064        return;
02065       }
02066       if (nCodes > nGlyphs) {
02067        nCodes = nGlyphs;
02068       }
02069       for (i = 1; i < nCodes; ++i) {
02070        c = getU8(pos++, &parsedOk);
02071        if (!parsedOk) {
02072          return;
02073        }
02074        if (encoding[c]) {
02075          gfree(encoding[c]);
02076        }
02077        encoding[c] = copyString(getString(charset[i], buf, &parsedOk));
02078       }
02079     } else if ((encFormat & 0x7f) == 1) {
02080       nRanges = getU8(pos++, &parsedOk);
02081       if (!parsedOk) {
02082        return;
02083       }
02084       nCodes = 1;
02085       for (i = 0; i < nRanges; ++i) {
02086        c = getU8(pos++, &parsedOk);
02087        nLeft = getU8(pos++, &parsedOk);
02088        if (!parsedOk) {
02089          return;
02090        }
02091        for (j = 0; j <= nLeft && nCodes < nGlyphs; ++j) {
02092          if (c < 256) {
02093            if (encoding[c]) {
02094              gfree(encoding[c]);
02095            }
02096            encoding[c] = copyString(getString(charset[nCodes], buf,
02097                                           &parsedOk));
02098          }
02099          ++nCodes;
02100          ++c;
02101        }
02102       }
02103     }
02104     if (encFormat & 0x80) {
02105       nSups = getU8(pos++, &parsedOk);
02106       if (!parsedOk) {
02107        return;
02108       }
02109       for (i = 0; i < nSups; ++i) {
02110        c = getU8(pos++, &parsedOk);;
02111        if (!parsedOk) {
02112          return;;
02113        }
02114        sid = getU16BE(pos, &parsedOk);
02115        pos += 2;
02116        if (!parsedOk) {
02117          return;
02118        }
02119        if (encoding[c]) {
02120          gfree(encoding[c]);
02121        }
02122        encoding[c] = copyString(getString(sid, buf, &parsedOk));
02123       }
02124     }
02125   }
02126 }
02127 
02128 GBool FoFiType1C::readCharset() {
02129   int charsetFormat, c, pos;
02130   int nLeft, i, j;
02131 
02132   if (topDict.charsetOffset == 0) {
02133     charset = fofiType1CISOAdobeCharset;
02134   } else if (topDict.charsetOffset == 1) {
02135     charset = fofiType1CExpertCharset;
02136   } else if (topDict.charsetOffset == 2) {
02137     charset = fofiType1CExpertSubsetCharset;
02138   } else {
02139     charset = (Gushort *)gmalloc(nGlyphs * sizeof(Gushort));
02140     for (i = 0; i < nGlyphs; ++i) {
02141       charset[i] = 0;
02142     }
02143     pos = topDict.charsetOffset;
02144     charsetFormat = getU8(pos++, &parsedOk);
02145     if (charsetFormat == 0) {
02146       for (i = 1; i < nGlyphs; ++i) {
02147        charset[i] = (Gushort)getU16BE(pos, &parsedOk);
02148        pos += 2;
02149        if (!parsedOk) {
02150          break;
02151        }
02152       }
02153     } else if (charsetFormat == 1) {
02154       i = 1;
02155       while (i < nGlyphs) {
02156        c = getU16BE(pos, &parsedOk);
02157        pos += 2;
02158        nLeft = getU8(pos++, &parsedOk);
02159        if (!parsedOk) {
02160          break;
02161        }
02162        for (j = 0; j <= nLeft && i < nGlyphs; ++j) {
02163          charset[i++] = (Gushort)c++;
02164        }
02165       }
02166     } else if (charsetFormat == 2) {
02167       i = 1;
02168       while (i < nGlyphs) {
02169        c = getU16BE(pos, &parsedOk);
02170        pos += 2;
02171        nLeft = getU16BE(pos, &parsedOk);
02172        pos += 2;
02173        if (!parsedOk) {
02174          break;
02175        }
02176        for (j = 0; j <= nLeft && i < nGlyphs; ++j) {
02177          charset[i++] = (Gushort)c++;
02178        }
02179       }
02180     }
02181     if (!parsedOk) {
02182       gfree(charset);
02183       charset = NULL;
02184       return gFalse;
02185     }
02186   }
02187   return gTrue;
02188 }
02189 
02190 int FoFiType1C::getOp(int pos, GBool charstring, GBool *ok) {
02191   static char nybChars[16] = "0123456789.ee -";
02192   Type1COp op;
02193   char buf[65];
02194   int b0, b1, nyb0, nyb1, x, i;
02195 
02196   b0 = getU8(pos++, ok);
02197   op.isNum = gTrue;
02198   op.isFP = gFalse;
02199 
02200   if (b0 == 28) {
02201     x = getU8(pos++, ok);
02202     x = (x << 8) | getU8(pos++, ok);
02203     if (x & 0x8000) {
02204       x |= ~0xffff;
02205     }
02206     op.num = x;
02207 
02208   } else if (!charstring && b0 == 29) {
02209     x = getU8(pos++, ok);
02210     x = (x << 8) | getU8(pos++, ok);
02211     x = (x << 8) | getU8(pos++, ok);
02212     x = (x << 8) | getU8(pos++, ok);
02213     if (x & 0x80000000) {
02214       x |= ~0xffffffff;
02215     }
02216     op.num = x;
02217 
02218   } else if (!charstring && b0 == 30) {
02219     i = 0;
02220     do {
02221       b1 = getU8(pos++, ok);
02222       nyb0 = b1 >> 4;
02223       nyb1 = b1 & 0x0f;
02224       if (nyb0 == 0xf) {
02225        break;
02226       }
02227       buf[i++] = nybChars[nyb0];
02228       if (i == 64) {
02229        break;
02230       }
02231       if (nyb0 == 0xc) {
02232        buf[i++] = '-';
02233       }
02234       if (i == 64) {
02235        break;
02236       }
02237       if (nyb1 == 0xf) {
02238        break;
02239       }
02240       buf[i++] = nybChars[nyb1];
02241       if (i == 64) {
02242        break;
02243       }
02244       if (nyb1 == 0xc) {
02245        buf[i++] = '-';
02246       }
02247     } while (i < 64);
02248     buf[i] = '\0';
02249     op.num = atof(buf);
02250     op.isFP = gTrue;
02251 
02252   } else if (b0 >= 32 && b0 <= 246) {
02253     op.num = b0 - 139;
02254 
02255   } else if (b0 >= 247 && b0 <= 250) {
02256     op.num = ((b0 - 247) << 8) + getU8(pos++, ok) + 108;
02257 
02258   } else if (b0 >= 251 && b0 <= 254) {
02259     op.num = -((b0 - 251) << 8) - getU8(pos++, ok) - 108;
02260 
02261   } else if (charstring && b0 == 255) {
02262     x = getU8(pos++, ok);
02263     x = (x << 8) | getU8(pos++, ok);
02264     x = (x << 8) | getU8(pos++, ok);
02265     x = (x << 8) | getU8(pos++, ok);
02266     if (x & 0x80000000) {
02267       x |= ~0xffffffff;
02268     }
02269     op.num = (double)x / 65536.0;
02270     op.isFP = gTrue;
02271 
02272   } else if (b0 == 12) {
02273     op.isNum = gFalse;
02274     op.op = 0x0c00 + getU8(pos++, ok);
02275 
02276   } else {
02277     op.isNum = gFalse;
02278     op.op = b0;
02279   }
02280 
02281   if (nOps < 49) {
02282     ops[nOps++] = op;
02283   }
02284 
02285   return pos;
02286 }
02287 
02288 // Convert the delta-encoded ops array to an array of ints.
02289 int FoFiType1C::getDeltaIntArray(int *arr, int maxLen) {
02290   int x;
02291   int n, i;
02292 
02293   if ((n = nOps) > maxLen) {
02294     n = maxLen;
02295   }
02296   x = 0;
02297   for (i = 0; i < n; ++i) {
02298     x += (int)ops[i].num;
02299     arr[i] = x;
02300   }
02301   return n;
02302 }
02303 
02304 // Convert the delta-encoded ops array to an array of doubles.
02305 int FoFiType1C::getDeltaFPArray(double *arr, int maxLen) {
02306   double x;
02307   int n, i;
02308 
02309   if ((n = nOps) > maxLen) {
02310     n = maxLen;
02311   }
02312   x = 0;
02313   for (i = 0; i < n; ++i) {
02314     x += ops[i].num;
02315     arr[i] = x;
02316   }
02317   return n;
02318 }
02319 
02320 void FoFiType1C::getIndex(int pos, Type1CIndex *idx, GBool *ok) {
02321   idx->pos = pos;
02322   idx->len = getU16BE(pos, ok);
02323   if (idx->len == 0) {
02324     // empty indexes are legal
02325     idx->offSize = 0;
02326     idx->startPos = idx->endPos = 0;
02327   } else {
02328     idx->offSize = getU8(pos + 2, ok);
02329     if (idx->offSize < 1 || idx->offSize > 4) {
02330       *ok = gFalse;
02331     }
02332     idx->startPos = pos + 3 + (idx->len + 1) * idx->offSize - 1;
02333     if (idx->startPos < 0 || idx->startPos >= len) {
02334       *ok = gFalse;
02335     }
02336     idx->endPos = idx->startPos + getUVarBE(pos + 3 + idx->len * idx->offSize,
02337                                        idx->offSize, ok);
02338     if (idx->endPos < idx->startPos || idx->endPos > len) {
02339       *ok = gFalse;
02340     }
02341   }
02342 }
02343 
02344 void FoFiType1C::getIndexVal(Type1CIndex *idx, int i,
02345                           Type1CIndexVal *val, GBool *ok) {
02346   int pos0, pos1;
02347 
02348   if (i < 0 || i >= idx->len) {
02349     *ok = gFalse;
02350     return;
02351   }
02352   pos0 = idx->startPos + getUVarBE(idx->pos + 3 + i * idx->offSize,
02353                                idx->offSize, ok);
02354   pos1 = idx->startPos + getUVarBE(idx->pos + 3 + (i + 1) * idx->offSize,
02355                                idx->offSize, ok);
02356   if (pos0 < idx->startPos || pos0 >= idx->endPos ||
02357       pos1 <= idx->startPos || pos1 > idx->endPos ||
02358       pos1 < pos0) {
02359     *ok = gFalse;
02360   }
02361   val->pos = pos0;
02362   val->len = pos1 - pos0;
02363 }
02364 
02365 char *FoFiType1C::getString(int sid, char *buf, GBool *ok) {
02366   Type1CIndexVal val;
02367   int n;
02368 
02369   if (sid < 391) {
02370     strcpy(buf, fofiType1CStdStrings[sid]);
02371   } else {
02372     sid -= 391;
02373     getIndexVal(&stringIdx, sid, &val, ok);
02374     if (ok) {
02375       if ((n = val.len) > 255) {
02376        n = 255;
02377       }
02378       strncpy(buf, (char *)&file[val.pos], n);
02379       buf[n] = '\0';
02380     } else {
02381       buf[0] = '\0';
02382     }
02383   }
02384   return buf;
02385 }