"Fossies" - the Fresh Open Source Software Archive

Member "xpdf-4.04/fofi/FoFiType1C.cc" (18 Apr 2022, 97383 Bytes) of package /linux/misc/xpdf-4.04.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "FoFiType1C.cc" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 4.03_vs_4.04.

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