"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.

    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 }