filters

FontFile.cc

00001 //========================================================================
00002 //
00003 // FontFile.cc
00004 //
00005 // Copyright 1999-2002 Glyph & Cog, LLC
00006 //
00007 //========================================================================
00008 
00009 #include <aconf.h>
00010 
00011 #ifdef USE_GCC_PRAGMAS
00012 #pragma implementation
00013 #endif
00014 
00015 #include <math.h>
00016 #include <stdlib.h>
00017 #include <stddef.h>
00018 #include <stdarg.h>
00019 #include <string.h>
00020 #include <ctype.h>
00021 #include "gmem.h"
00022 #include "Error.h"
00023 #include "GlobalParams.h"
00024 #include "CharCodeToUnicode.h"
00025 #include "FontEncodingTables.h"
00026 #include "FontFile.h"
00027 
00028 #include "CompactFontTables.h"
00029 
00030 //------------------------------------------------------------------------
00031 
00032 static inline const char *nextLine(const char *line, const char *end) {
00033   while (line < end && *line != '\n' && *line != '\r')
00034     ++line;
00035   while (line < end && *line == '\n' || *line == '\r')
00036     ++line;
00037   return line;
00038 }
00039 
00040 static const char hexChars[17] = "0123456789ABCDEF";
00041 
00042 //------------------------------------------------------------------------
00043 // FontFile
00044 //------------------------------------------------------------------------
00045 
00046 FontFile::FontFile() {
00047 }
00048 
00049 FontFile::~FontFile() {
00050 }
00051 
00052 //------------------------------------------------------------------------
00053 // Type1FontFile
00054 //------------------------------------------------------------------------
00055 
00056 Type1FontFile::Type1FontFile(const char *file, int len) {
00057   const char *line, *line1;
00058   char *p, *p2;
00059   GBool haveEncoding;
00060   char buf[256];
00061   char c;
00062   int n, code, i, j;
00063 
00064   name = NULL;
00065   encoding = (char **)gmalloc(256 * sizeof(char *));
00066   for (i = 0; i < 256; ++i) {
00067     encoding[i] = NULL;
00068   }
00069   haveEncoding = gFalse;
00070 
00071   for (i = 1, line = file;
00072        i <= 100 && line < file + len && !haveEncoding;
00073        ++i) {
00074 
00075     // get font name
00076     if (!strncmp(line, "/FontName", 9)) {
00077       strncpy(buf, line, 255);
00078       buf[255] = '\0';
00079       if ((p = strchr(buf+9, '/')) &&
00080       (p = strtok(p+1, " \t\n\r"))) {
00081     name = copyString(p);
00082       }
00083       line = nextLine(line, file + len);
00084 
00085     // get encoding
00086     } else if (!strncmp(line, "/Encoding StandardEncoding def", 30)) {
00087       for (j = 0; j < 256; ++j) {
00088     if (standardEncoding[j]) {
00089       encoding[j] = copyString(standardEncoding[j]);
00090     }
00091       }
00092       haveEncoding = gTrue;
00093     } else if (!strncmp(line, "/Encoding 256 array", 19)) {
00094       for (j = 0; j < 300; ++j) {
00095     line1 = nextLine(line, file + len);
00096     if ((n = line1 - line) > 255) {
00097       n = 255;
00098     }
00099     strncpy(buf, line, n);
00100     buf[n] = '\0';
00101     for (p = buf; *p == ' ' || *p == '\t'; ++p) ;
00102     if (!strncmp(p, "dup", 3)) {
00103       for (p += 3; *p == ' ' || *p == '\t'; ++p) ;
00104       for (p2 = p; *p2 >= '0' && *p2 <= '9'; ++p2) ;
00105       if (*p2) {
00106         c = *p2;
00107         *p2 = '\0';
00108         if ((code = atoi(p)) < 256) {
00109           *p2 = c;
00110           for (p = p2; *p == ' ' || *p == '\t'; ++p) ;
00111           if (*p == '/') {
00112         ++p;
00113         for (p2 = p; *p2 && *p2 != ' ' && *p2 != '\t'; ++p2) ;
00114         *p2 = '\0';
00115         encoding[code] = copyString(p);
00116           }
00117         }
00118       }
00119     } else {
00120       if (strtok(buf, " \t") &&
00121           (p = strtok(NULL, " \t\n\r")) && !strcmp(p, "def")) {
00122         break;
00123       }
00124     }
00125     line = line1;
00126       }
00127       //~ check for getinterval/putinterval junk
00128       haveEncoding = gTrue;
00129 
00130     } else {
00131       line = nextLine(line, file + len);
00132     }
00133   }
00134 }
00135 
00136 Type1FontFile::~Type1FontFile() {
00137   int i;
00138 
00139   if (name) {
00140     gfree(name);
00141   }
00142   for (i = 0; i < 256; ++i) {
00143     gfree(encoding[i]);
00144   }
00145   gfree(encoding);
00146 }
00147 
00148 //------------------------------------------------------------------------
00149 // Type1CFontFile
00150 //------------------------------------------------------------------------
00151 
00152 struct Type1CTopDict {
00153   int version;
00154   int notice;
00155   int copyright;
00156   int fullName;
00157   int familyName;
00158   int weight;
00159   int isFixedPitch;
00160   double italicAngle;
00161   double underlinePosition;
00162   double underlineThickness;
00163   int paintType;
00164   int charstringType;
00165   double fontMatrix[6];
00166   int uniqueID;
00167   double fontBBox[4];
00168   double strokeWidth;
00169   int charset;
00170   int encoding;
00171   int charStrings;
00172   int privateSize;
00173   int privateOffset;
00174 
00175   //----- CIDFont entries
00176   int registry;
00177   int ordering;
00178   int supplement;
00179   int fdArrayOffset;
00180   int fdSelectOffset;
00181 };
00182 
00183 struct Type1CPrivateDict {
00184   GString *dictData;
00185   int subrsOffset;
00186   double defaultWidthX;
00187   GBool defaultWidthXFP;
00188   double nominalWidthX;
00189   GBool nominalWidthXFP;
00190 };
00191 
00192 Type1CFontFile::Type1CFontFile(const char *fileA, int lenA) {
00193   Guchar *nameIdxPtr, *idxPtr0, *idxPtr1;
00194 
00195   file = fileA;
00196   len = lenA;
00197   name = NULL;
00198   encoding = NULL;
00199 
00200   // some tools embed Type 1C fonts with an extra whitespace char at
00201   // the beginning
00202   if (file[0] != '\x01') {
00203     ++file;
00204   }
00205 
00206   // read header
00207   topOffSize = file[3] & 0xff;
00208 
00209   // read name index (first font only)
00210   nameIdxPtr = (Guchar *)file + (file[2] & 0xff);
00211   idxPtr0 = getIndexValPtr(nameIdxPtr, 0);
00212   idxPtr1 = getIndexValPtr(nameIdxPtr, 1);
00213   name = new GString((char *)idxPtr0, idxPtr1 - idxPtr0);
00214 
00215   topDictIdxPtr = getIndexEnd(nameIdxPtr);
00216   stringIdxPtr = getIndexEnd(topDictIdxPtr);
00217   gsubrIdxPtr = getIndexEnd(stringIdxPtr);
00218 }
00219 
00220 Type1CFontFile::~Type1CFontFile() {
00221   int i;
00222 
00223   delete name;
00224   if (encoding) {
00225     for (i = 0; i < 256; ++i) {
00226       gfree(encoding[i]);
00227     }
00228     gfree(encoding);
00229   }
00230 }
00231 
00232 const char *Type1CFontFile::getName() {
00233   return name->getCString();
00234 }
00235 
00236 char **Type1CFontFile::getEncoding() {
00237   if (!encoding) {
00238     readNameAndEncoding();
00239   }
00240   return encoding;
00241 }
00242 
00243 void Type1CFontFile::readNameAndEncoding() {
00244   char buf[256];
00245   Guchar *idxPtr0, *idxPtr1, *ptr;
00246   int nGlyphs;
00247   int nCodes, nRanges, nLeft, nSups;
00248   Gushort *glyphNames;
00249   int charset, enc, charstrings;
00250   int encFormat;
00251   int c, sid;
00252   double x;
00253   GBool isFP;
00254   int key;
00255   int i, j;
00256 
00257   encoding = (char **)gmalloc(256 * sizeof(char *));
00258   for (i = 0; i < 256; ++i) {
00259     encoding[i] = NULL;
00260   }
00261 
00262   // read top dict (first font only)
00263   idxPtr0 = getIndexValPtr(topDictIdxPtr, 0);
00264   idxPtr1 = getIndexValPtr(topDictIdxPtr, 1);
00265   charset = enc = charstrings = 0;
00266   i = 0;
00267   ptr = idxPtr0;
00268   while (ptr < idxPtr1) {
00269     if (*ptr <= 27 || *ptr == 31) {
00270       key = *ptr++;
00271       if (key == 0x0c) {
00272     key = (key << 8) | *ptr++;
00273       }
00274       if (key == 0x0f) { // charset
00275     charset = (int)op[0];
00276       } else if (key == 0x10) { // encoding
00277     enc = (int)op[0];
00278       } else if (key == 0x11) { // charstrings
00279     charstrings = (int)op[0];
00280       }
00281       i = 0;
00282     } else {
00283       x = getNum(&ptr, &isFP);
00284       if (i < 48) {
00285     op[i++] = x;
00286       }
00287     }
00288   }
00289 
00290   // get number of glyphs from charstrings index
00291   nGlyphs = getIndexLen((Guchar *)file + charstrings);
00292 
00293   // read charset (GID -> name mapping)
00294   glyphNames = readCharset(charset, nGlyphs);
00295 
00296   // read encoding (GID -> code mapping)
00297   if (enc == 0) {
00298     for (i = 0; i < 256; ++i) {
00299       if (standardEncoding[i]) {
00300     encoding[i] = copyString(standardEncoding[i]);
00301       }
00302     }
00303   } else if (enc == 1) {
00304     for (i = 0; i < 256; ++i) {
00305       if (expertEncoding[i]) {
00306     encoding[i] = copyString(expertEncoding[i]);
00307       }
00308     }
00309   } else {
00310     ptr = (Guchar *)file + enc;
00311     encFormat = *ptr++;
00312     if ((encFormat & 0x7f) == 0) {
00313       nCodes = 1 + *ptr++;
00314       if (nCodes > nGlyphs) {
00315     nCodes = nGlyphs;
00316       }
00317       for (i = 1; i < nCodes; ++i) {
00318     c = *ptr++;
00319     encoding[c] = copyString(getString(glyphNames[i], buf));
00320       }
00321     } else if ((encFormat & 0x7f) == 1) {
00322       nRanges = *ptr++;
00323       nCodes = 1;
00324       for (i = 0; i < nRanges; ++i) {
00325     c = *ptr++;
00326     nLeft = *ptr++;
00327     for (j = 0; j <= nLeft && nCodes < nGlyphs; ++j) {
00328       encoding[c] = copyString(getString(glyphNames[nCodes], buf));
00329       ++nCodes;
00330       ++c;
00331     }
00332       }
00333     }
00334     if (encFormat & 0x80) {
00335       nSups = *ptr++;
00336       for (i = 0; i < nSups; ++i) {
00337     c = *ptr++;
00338     sid = getWord(ptr, 2);
00339     ptr += 2;
00340     encoding[c] = copyString(getString(sid, buf));
00341       }
00342     }
00343   }
00344 
00345   if (charset > 2) {
00346     gfree(glyphNames);
00347   }
00348 }
00349 
00350 void Type1CFontFile::convertToType1(FontFileOutputFunc outputFuncA,
00351                     void *outputStreamA) {
00352   Type1CTopDict dict;
00353   Type1CPrivateDict privateDict;
00354   char buf[512], eBuf[256];
00355   Guchar *idxPtr0, *idxPtr1, *subrsIdxPtr, *charStringsIdxPtr, *ptr;
00356   int nGlyphs, nCodes, nRanges, nLeft, nSups;
00357   Gushort *glyphNames;
00358   int encFormat, nSubrs, nCharStrings;
00359   int c, sid;
00360   int i, j, n;
00361 
00362   outputFunc = outputFuncA;
00363   outputStream = outputStreamA;
00364 
00365   // read top dict (first font only)
00366   readTopDict(&dict);
00367 
00368   // get global subrs
00369   //~ ... global subrs are unimplemented
00370 
00371   // write header and font dictionary, up to encoding
00372   (*outputFunc)(outputStream, "%!FontType1-1.0: ", 17);
00373   (*outputFunc)(outputStream, name->getCString(), name->getLength());
00374   if (dict.version != 0) {
00375     getString(dict.version, buf);
00376     (*outputFunc)(outputStream, buf, strlen(buf));
00377   }
00378   (*outputFunc)(outputStream, "\n", 1);
00379   (*outputFunc)(outputStream, "11 dict begin\n", 14);
00380   (*outputFunc)(outputStream, "/FontInfo 10 dict dup begin\n", 28);
00381   if (dict.version != 0) {
00382     (*outputFunc)(outputStream, "/version (", 10);
00383     (*outputFunc)(outputStream, buf, strlen(buf));
00384     (*outputFunc)(outputStream, ") readonly def\n", 15);
00385   }
00386   if (dict.notice != 0) {
00387     getString(dict.notice, buf);
00388     (*outputFunc)(outputStream, "/Notice (", 9);
00389     (*outputFunc)(outputStream, buf, strlen(buf));
00390     (*outputFunc)(outputStream, ") readonly def\n", 15);
00391   }
00392   if (dict.copyright != 0) {
00393     getString(dict.copyright, buf);
00394     (*outputFunc)(outputStream, "/Copyright (", 12);
00395     (*outputFunc)(outputStream, buf, strlen(buf));
00396     (*outputFunc)(outputStream, ") readonly def\n", 15);
00397   }
00398   if (dict.fullName != 0) {
00399     getString(dict.fullName, buf);
00400     (*outputFunc)(outputStream, "/FullName (", 11);
00401     (*outputFunc)(outputStream, buf, strlen(buf));
00402     (*outputFunc)(outputStream, ") readonly def\n", 15);
00403   }
00404   if (dict.familyName != 0) {
00405     getString(dict.familyName, buf);
00406     (*outputFunc)(outputStream, "/FamilyName (", 13);
00407     (*outputFunc)(outputStream, buf, strlen(buf));
00408     (*outputFunc)(outputStream, ") readonly def\n", 15);
00409   }
00410   if (dict.weight != 0) {
00411     getString(dict.weight, buf);
00412     (*outputFunc)(outputStream, "/Weight (", 9);
00413     (*outputFunc)(outputStream, buf, strlen(buf));
00414     (*outputFunc)(outputStream, ") readonly def\n", 15);
00415   }
00416   if (dict.isFixedPitch) {
00417     (*outputFunc)(outputStream, "/isFixedPitch true def\n", 23);
00418   } else {
00419     (*outputFunc)(outputStream, "/isFixedPitch false def\n", 24);
00420   }
00421   sprintf(buf, "/ItalicAngle %g def\n", dict.italicAngle);
00422   (*outputFunc)(outputStream, buf, strlen(buf));
00423   sprintf(buf, "/UnderlinePosition %g def\n", dict.underlinePosition);
00424   (*outputFunc)(outputStream, buf, strlen(buf));
00425   sprintf(buf, "/UnderlineThickness %g def\n", dict.underlineThickness);
00426   (*outputFunc)(outputStream, buf, strlen(buf));
00427   (*outputFunc)(outputStream, "end readonly def\n", 17);
00428   (*outputFunc)(outputStream, "/FontName /", 11);
00429   (*outputFunc)(outputStream, name->getCString(), name->getLength());
00430   (*outputFunc)(outputStream, " def\n", 5);
00431   sprintf(buf, "/PaintType %d def\n", dict.paintType);
00432   (*outputFunc)(outputStream, buf, strlen(buf));
00433   (*outputFunc)(outputStream, "/FontType 1 def\n", 16);
00434   sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] readonly def\n",
00435       dict.fontMatrix[0], dict.fontMatrix[1], dict.fontMatrix[2],
00436       dict.fontMatrix[3], dict.fontMatrix[4], dict.fontMatrix[5]);
00437   (*outputFunc)(outputStream, buf, strlen(buf));
00438   sprintf(buf, "/FontBBox [%g %g %g %g] readonly def\n",
00439       dict.fontBBox[0], dict.fontBBox[1],
00440       dict.fontBBox[2], dict.fontBBox[3]);
00441   (*outputFunc)(outputStream, buf, strlen(buf));
00442   sprintf(buf, "/StrokeWidth %g def\n", dict.strokeWidth);
00443   (*outputFunc)(outputStream, buf, strlen(buf));
00444   if (dict.uniqueID != 0) {
00445     sprintf(buf, "/UniqueID %d def\n", dict.uniqueID);
00446     (*outputFunc)(outputStream, buf, strlen(buf));
00447   }
00448 
00449   // get number of glyphs from charstrings index
00450   nGlyphs = getIndexLen((Guchar *)file + dict.charStrings);
00451 
00452   // read charset
00453   glyphNames = readCharset(dict.charset, nGlyphs);
00454 
00455   // read encoding (glyph -> code mapping), write Type 1 encoding
00456   (*outputFunc)(outputStream, "/Encoding ", 10);
00457   if (dict.encoding == 0) {
00458     (*outputFunc)(outputStream, "StandardEncoding def\n", 21);
00459   } else {
00460     (*outputFunc)(outputStream, "256 array\n", 10);
00461     (*outputFunc)(outputStream,
00462           "0 1 255 {1 index exch /.notdef put} for\n", 40);
00463     if (dict.encoding == 1) {
00464       for (i = 0; i < 256; ++i) {
00465     if (expertEncoding[i]) {
00466       sprintf(buf, "dup %d /%s put\n", i, expertEncoding[i]);
00467       (*outputFunc)(outputStream, buf, strlen(buf));
00468     }
00469       }
00470     } else {
00471       ptr = (Guchar *)file + dict.encoding;
00472       encFormat = *ptr++;
00473       if ((encFormat & 0x7f) == 0) {
00474     nCodes = 1 + *ptr++;
00475     if (nCodes > nGlyphs) {
00476       nCodes = nGlyphs;
00477     }
00478     for (i = 1; i < nCodes; ++i) {
00479       c = *ptr++;
00480       sprintf(buf, "dup %d /", c);
00481       (*outputFunc)(outputStream, buf, strlen(buf));
00482       getString(glyphNames[i], buf);
00483       (*outputFunc)(outputStream, buf, strlen(buf));
00484       (*outputFunc)(outputStream, " put\n", 5);
00485     }
00486       } else if ((encFormat & 0x7f) == 1) {
00487     nRanges = *ptr++;
00488     nCodes = 1;
00489     for (i = 0; i < nRanges; ++i) {
00490       c = *ptr++;
00491       nLeft = *ptr++;
00492       for (j = 0; j <= nLeft && nCodes < nGlyphs; ++j) {
00493         sprintf(buf, "dup %d /", c);
00494         (*outputFunc)(outputStream, buf, strlen(buf));
00495         getString(glyphNames[nCodes], buf);
00496         (*outputFunc)(outputStream, buf, strlen(buf));
00497         (*outputFunc)(outputStream, " put\n", 5);
00498         ++nCodes;
00499         ++c;
00500       }
00501     }
00502       }
00503       if (encFormat & 0x80) {
00504     nSups = *ptr++;
00505     for (i = 0; i < nSups; ++i) {
00506       c = *ptr++;
00507       sid = getWord(ptr, 2);
00508       ptr += 2;
00509       sprintf(buf, "dup %d /", c);
00510       (*outputFunc)(outputStream, buf, strlen(buf));
00511       getString(sid, buf);
00512       (*outputFunc)(outputStream, buf, strlen(buf));
00513       (*outputFunc)(outputStream, " put\n", 5);
00514     }
00515       }
00516     }
00517     (*outputFunc)(outputStream, "readonly def\n", 13);
00518   }
00519   (*outputFunc)(outputStream, "currentdict end\n", 16);
00520 
00521   // start the binary section
00522   (*outputFunc)(outputStream, "currentfile eexec\n", 18);
00523   r1 = 55665;
00524   line = 0;
00525 
00526   // get private dictionary
00527   eexecWrite("\x83\xca\x73\xd5");
00528   eexecWrite("dup /Private 32 dict dup begin\n");
00529   eexecWrite("/RD {string currentfile exch readstring pop} executeonly def\n");
00530   eexecWrite("/ND {noaccess def} executeonly def\n");
00531   eexecWrite("/NP {noaccess put} executeonly def\n");
00532   eexecWrite("/MinFeature {16 16} ND\n");
00533   readPrivateDict(&privateDict, dict.privateOffset, dict.privateSize);
00534   eexecWrite(privateDict.dictData->getCString());
00535   defaultWidthX = privateDict.defaultWidthX;
00536   defaultWidthXFP = privateDict.defaultWidthXFP;
00537   nominalWidthX = privateDict.nominalWidthX;
00538   nominalWidthXFP = privateDict.nominalWidthXFP;
00539 
00540   // get subrs
00541   if (privateDict.subrsOffset != 0) {
00542     subrsIdxPtr = (Guchar *)file + dict.privateOffset +
00543                   privateDict.subrsOffset;
00544     nSubrs = getIndexLen(subrsIdxPtr);
00545     sprintf(eBuf, "/Subrs %d array\n", nSubrs);
00546     eexecWrite(eBuf);
00547     idxPtr1 = getIndexValPtr(subrsIdxPtr, 0);
00548     for (i = 0; i < nSubrs; ++i) {
00549       idxPtr0 = idxPtr1;
00550       idxPtr1 = getIndexValPtr(subrsIdxPtr, i+1);
00551       n = idxPtr1 - idxPtr0;
00552 #if 1 //~ Type 2 subrs are unimplemented
00553       error(-1, "Unimplemented Type 2 subrs");
00554 #else
00555       sprintf(eBuf, "dup %d %d RD ", i, n);
00556       eexecWrite(eBuf);
00557       eexecCvtGlyph(idxPtr0, n);
00558       eexecWrite(" NP\n");
00559 #endif
00560     }
00561     eexecWrite("ND\n");
00562   }
00563 
00564   // get CharStrings
00565   charStringsIdxPtr = (Guchar *)file + dict.charStrings;
00566   nCharStrings = getIndexLen(charStringsIdxPtr);
00567   sprintf(eBuf, "2 index /CharStrings %d dict dup begin\n", nCharStrings);
00568   eexecWrite(eBuf);
00569   idxPtr1 = getIndexValPtr(charStringsIdxPtr, 0);
00570   for (i = 0; i < nCharStrings; ++i) {
00571     idxPtr0 = idxPtr1;
00572     idxPtr1 = getIndexValPtr(charStringsIdxPtr, i+1);
00573     n = idxPtr1 - idxPtr0;
00574     eexecCvtGlyph(getString(glyphNames[i], buf), idxPtr0, n);
00575   }
00576   eexecWrite("end\n");
00577   eexecWrite("end\n");
00578   eexecWrite("readonly put\n");
00579   eexecWrite("noaccess put\n");
00580   eexecWrite("dup /FontName get exch definefont pop\n");
00581   eexecWrite("mark currentfile closefile\n");
00582 
00583   // trailer
00584   if (line > 0) {
00585     (*outputFunc)(outputStream, "\n", 1);
00586   }
00587   for (i = 0; i < 8; ++i) {
00588     (*outputFunc)(outputStream, "0000000000000000000000000000000000000000000000000000000000000000\n", 65);
00589   }
00590   (*outputFunc)(outputStream, "cleartomark\n", 12);
00591 
00592   // clean up
00593   delete privateDict.dictData;
00594   if (dict.charset > 2) {
00595     gfree(glyphNames);
00596   }
00597 }
00598 
00599 void Type1CFontFile::convertToCIDType0(const char *psName,
00600                        FontFileOutputFunc outputFuncA,
00601                        void *outputStreamA) {
00602   Type1CTopDict dict;
00603   Type1CPrivateDict *privateDicts;
00604   GString *charStrings;
00605   int *charStringOffsets;
00606   Gushort *charset;
00607   int *cidMap;
00608   Guchar *fdSelect;
00609   Guchar *charStringsIdxPtr, *fdArrayIdx, *idxPtr0, *idxPtr1, *ptr;
00610   char buf[512], buf2[16];
00611   int nGlyphs, nCIDs, gdBytes, nFDs;
00612   int fdSelectFmt, nRanges, gid0, gid1, fd, offset;
00613   int key;
00614   double x;
00615   GBool isFP;
00616   int i, j, k, n;
00617 
00618   outputFunc = outputFuncA;
00619   outputStream = outputStreamA;
00620 
00621   (*outputFunc)(outputStream, "/CIDInit /ProcSet findresource begin\n", 37);
00622 
00623   // read top dict (first font only)
00624   readTopDict(&dict);
00625 
00626   // read the FDArray dictionaries and Private dictionaries
00627   if (dict.fdArrayOffset == 0) {
00628     nFDs = 1;
00629     privateDicts = (Type1CPrivateDict *)
00630                      gmalloc(nFDs * sizeof(Type1CPrivateDict));
00631     privateDicts[0].dictData = new GString();
00632     privateDicts[0].subrsOffset = 0;
00633     privateDicts[0].defaultWidthX = 0;
00634     privateDicts[0].defaultWidthXFP = gFalse;
00635     privateDicts[0].nominalWidthX = 0;
00636     privateDicts[0].nominalWidthXFP = gFalse;
00637   } else {
00638     fdArrayIdx = (Guchar *)file + dict.fdArrayOffset;
00639     nFDs = getIndexLen(fdArrayIdx);
00640     privateDicts = (Type1CPrivateDict *)
00641                      gmalloc(nFDs * sizeof(Type1CPrivateDict));
00642     idxPtr1 = getIndexValPtr(fdArrayIdx, 0);
00643     for (i = 0; i < nFDs; ++i) {
00644       privateDicts[i].dictData = NULL;
00645       idxPtr0 = idxPtr1;
00646       idxPtr1 = getIndexValPtr(fdArrayIdx, i + 1);
00647       ptr = idxPtr0;
00648       j = 0;
00649       while (ptr < idxPtr1) {
00650     if (*ptr <= 27 || *ptr == 31) {
00651       key = *ptr++;
00652       if (key == 0x0c) {
00653         key = (key << 8) | *ptr++;
00654       }
00655       if (key == 0x0012) {
00656         readPrivateDict(&privateDicts[i], (int)op[1], (int)op[0]);
00657       }
00658       j = 0;
00659     } else {
00660       x = getNum(&ptr, &isFP);
00661       if (j < 48) {
00662         op[j] = x;
00663         fp[j++] = isFP;
00664       }
00665     }
00666       }
00667       if (!privateDicts[i].dictData) {
00668     privateDicts[i].dictData = new GString();
00669     privateDicts[i].subrsOffset = 0;
00670     privateDicts[i].defaultWidthX = 0;
00671     privateDicts[i].defaultWidthXFP = gFalse;
00672     privateDicts[i].nominalWidthX = 0;
00673     privateDicts[i].nominalWidthXFP = gFalse;
00674       }
00675     }
00676   }
00677 
00678   // get the glyph count
00679   charStringsIdxPtr = (Guchar *)file + dict.charStrings;
00680   nGlyphs = getIndexLen(charStringsIdxPtr);
00681 
00682   // read the FDSelect table
00683   fdSelect = (Guchar *)gmalloc(nGlyphs);
00684   if (dict.fdSelectOffset == 0) {
00685     for (i = 0; i < nGlyphs; ++i) {
00686       fdSelect[i] = 0;
00687     }
00688   } else {
00689     ptr = (Guchar *)file + dict.fdSelectOffset;
00690     fdSelectFmt = *ptr++;
00691     if (fdSelectFmt == 0) {
00692       memcpy(fdSelect, ptr, nGlyphs);
00693     } else if (fdSelectFmt == 3) {
00694       nRanges = getWord(ptr, 2);
00695       ptr += 2;
00696       gid0 = getWord(ptr, 2);
00697       ptr += 2;
00698       for (i = 1; i <= nRanges; ++i) {
00699     fd = *ptr++;
00700     gid1 = getWord(ptr, 2);
00701     ptr += 2;
00702     for (j = gid0; j < gid1; ++j) {
00703       fdSelect[j] = fd;
00704     }
00705     gid0 = gid1;
00706       }
00707     } else {
00708       error(-1, "Unknown FDSelect table format in CID font");
00709       for (i = 0; i < nGlyphs; ++i) {
00710     fdSelect[i] = 0;
00711       }
00712     }
00713   }
00714 
00715   // read the charset, compute the CID-to-GID mapping
00716   charset = readCharset(dict.charset, nGlyphs);
00717   nCIDs = 0;
00718   for (i = 0; i < nGlyphs; ++i) {
00719     if (charset[i] >= nCIDs) {
00720       nCIDs = charset[i] + 1;
00721     }
00722   }
00723   cidMap = (int *)gmalloc(nCIDs * sizeof(int));
00724   for (i = 0; i < nCIDs; ++i) {
00725     cidMap[i] = -1;
00726   }
00727   for (i = 0; i < nGlyphs; ++i) {
00728     cidMap[charset[i]] = i;
00729   }
00730 
00731   // build the charstrings
00732   charStrings = new GString();
00733   charStringOffsets = (int *)gmalloc((nCIDs + 1) * sizeof(int));
00734   for (i = 0; i < nCIDs; ++i) {
00735     charStringOffsets[i] = charStrings->getLength();
00736     if (cidMap[i] >= 0) {
00737       idxPtr0 = getIndexValPtr(charStringsIdxPtr, cidMap[i]);
00738       idxPtr1 = getIndexValPtr(charStringsIdxPtr, cidMap[i]+1);
00739       n = idxPtr1 - idxPtr0;
00740       j = fdSelect[cidMap[i]];
00741       defaultWidthX = privateDicts[j].defaultWidthX;
00742       defaultWidthXFP = privateDicts[j].defaultWidthXFP;
00743       nominalWidthX = privateDicts[j].nominalWidthX;
00744       nominalWidthXFP = privateDicts[j].nominalWidthXFP;
00745       cvtGlyph(idxPtr0, n);
00746       charStrings->append(charBuf);
00747       delete charBuf;
00748     }
00749   }
00750   charStringOffsets[nCIDs] = charStrings->getLength();
00751 
00752   // compute gdBytes = number of bytes needed for charstring offsets
00753   // (offset size needs to account for the charstring offset table,
00754   // with a worst case of five bytes per entry, plus the charstrings
00755   // themselves)
00756   i = (nCIDs + 1) * 5 + charStrings->getLength();
00757   if (i < 0x100) {
00758     gdBytes = 1;
00759   } else if (i < 0x10000) {
00760     gdBytes = 2;
00761   } else if (i < 0x1000000) {
00762     gdBytes = 3;
00763   } else {
00764     gdBytes = 4;
00765   }
00766 
00767   // begin the font dictionary
00768   (*outputFunc)(outputStream, "20 dict begin\n", 14);
00769   (*outputFunc)(outputStream, "/CIDFontName /", 14);
00770   (*outputFunc)(outputStream, psName, strlen(psName));
00771   (*outputFunc)(outputStream, " def\n", 5);
00772   (*outputFunc)(outputStream, "/CIDFontType 0 def\n", 19);
00773   (*outputFunc)(outputStream, "/CIDSystemInfo 3 dict dup begin\n", 32);
00774   if (dict.registry > 0 && dict.ordering > 0) {
00775     getString(dict.registry, buf);
00776     (*outputFunc)(outputStream, "  /Registry (", 13);
00777     (*outputFunc)(outputStream, buf, strlen(buf));
00778     (*outputFunc)(outputStream, ") def\n", 6);
00779     getString(dict.ordering, buf);
00780     (*outputFunc)(outputStream, "  /Ordering (", 13);
00781     (*outputFunc)(outputStream, buf, strlen(buf));
00782     (*outputFunc)(outputStream, ") def\n", 6);
00783   } else {
00784     (*outputFunc)(outputStream, "  /Registry (Adobe) def\n", 24);
00785     (*outputFunc)(outputStream, "  /Ordering (Identity) def\n", 27);
00786   }
00787   sprintf(buf, "  /Supplement %d def\n", dict.supplement);
00788   (*outputFunc)(outputStream, buf, strlen(buf));
00789   (*outputFunc)(outputStream, "end def\n", 8);
00790   sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] def\n",
00791       dict.fontMatrix[0], dict.fontMatrix[1], dict.fontMatrix[2],
00792       dict.fontMatrix[3], dict.fontMatrix[4], dict.fontMatrix[5]);
00793   (*outputFunc)(outputStream, buf, strlen(buf));
00794   sprintf(buf, "/FontBBox [%g %g %g %g] def\n",
00795       dict.fontBBox[0], dict.fontBBox[1],
00796       dict.fontBBox[2], dict.fontBBox[3]);
00797   (*outputFunc)(outputStream, buf, strlen(buf));
00798   (*outputFunc)(outputStream, "/FontInfo 1 dict dup begin\n", 27);
00799   (*outputFunc)(outputStream, "  /FSType 8 def\n", 16);
00800   (*outputFunc)(outputStream, "end def\n", 8);
00801 
00802   // CIDFont-specific entries
00803   sprintf(buf, "/CIDCount %d def\n", nCIDs);
00804   (*outputFunc)(outputStream, buf, strlen(buf));
00805   (*outputFunc)(outputStream, "/FDBytes 1 def\n", 15);
00806   sprintf(buf, "/GDBytes %d def\n", gdBytes);
00807   (*outputFunc)(outputStream, buf, strlen(buf));
00808   (*outputFunc)(outputStream, "/CIDMapOffset 0 def\n", 20);
00809   if (dict.paintType != 0) {
00810     sprintf(buf, "/PaintType %d def\n", dict.paintType);
00811     (*outputFunc)(outputStream, buf, strlen(buf));
00812     sprintf(buf, "/StrokeWidth %g def\n", dict.strokeWidth);
00813     (*outputFunc)(outputStream, buf, strlen(buf));
00814   }
00815 
00816   // FDArray entry
00817   sprintf(buf, "/FDArray %d array\n", nFDs);
00818   (*outputFunc)(outputStream, buf, strlen(buf));
00819   for (i = 0; i < nFDs; ++i) {
00820     sprintf(buf, "dup %d 10 dict begin\n", i);
00821     (*outputFunc)(outputStream, buf, strlen(buf));
00822     (*outputFunc)(outputStream, "/FontType 1 def\n", 16);
00823     (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
00824     sprintf(buf, "/PaintType %d def\n", dict.paintType);
00825     (*outputFunc)(outputStream, buf, strlen(buf));
00826     (*outputFunc)(outputStream, "/Private 32 dict begin\n", 23);
00827     (*outputFunc)(outputStream, privateDicts[i].dictData->getCString(),
00828           privateDicts[i].dictData->getLength());
00829     (*outputFunc)(outputStream, "currentdict end def\n", 20);
00830     (*outputFunc)(outputStream, "currentdict end put\n", 20);
00831   }
00832   (*outputFunc)(outputStream, "def\n", 4);
00833 
00834   //~ need to deal with subrs
00835 
00836   // start the binary section
00837   offset = (nCIDs + 1) * (1 + gdBytes);
00838   sprintf(buf, "(Hex) %d StartData\n",
00839       offset + charStrings->getLength());
00840   (*outputFunc)(outputStream, buf, strlen(buf));
00841 
00842   // write the charstring offset (CIDMap) table
00843   for (i = 0; i <= nCIDs; i += 6) {
00844     for (j = 0; j < 6 && i+j <= nCIDs; ++j) {
00845       if (i+j < nCIDs && cidMap[i+j] >= 0) {
00846     buf[0] = (char)fdSelect[cidMap[i+j]];
00847       } else {
00848     buf[0] = (char)0;
00849       }
00850       n = offset + charStringOffsets[i+j];
00851       for (k = gdBytes; k >= 1; --k) {
00852     buf[k] = (char)(n & 0xff);
00853     n >>= 8;
00854       }
00855       for (k = 0; k <= gdBytes; ++k) {
00856     sprintf(buf2, "%02x", buf[k] & 0xff);
00857     (*outputFunc)(outputStream, buf2, 2);
00858       }
00859     }
00860     (*outputFunc)(outputStream, "\n", 1);
00861   }
00862 
00863   // write the charstring data
00864   n = charStrings->getLength();
00865   for (i = 0; i < n; i += 32) {
00866     for (j = 0; j < 32 && i+j < n; ++j) {
00867       sprintf(buf, "%02x", charStrings->getChar(i+j) & 0xff);
00868       (*outputFunc)(outputStream, buf, strlen(buf));
00869     }
00870     if (i + 32 >= n) {
00871       (*outputFunc)(outputStream, ">", 1);
00872     }
00873     (*outputFunc)(outputStream, "\n", 1);
00874   }
00875 
00876   for (i = 0; i < nFDs; ++i) {
00877     delete privateDicts[i].dictData;
00878   }
00879   gfree(privateDicts);
00880   gfree(cidMap);
00881   gfree(charset);
00882   gfree(charStringOffsets);
00883   delete charStrings;
00884   gfree(fdSelect);
00885 }
00886 
00887 void Type1CFontFile::convertToType0(const char *psName,
00888                     FontFileOutputFunc outputFuncA,
00889                     void *outputStreamA) {
00890   Type1CTopDict dict;
00891   Type1CPrivateDict *privateDicts;
00892   Gushort *charset;
00893   int *cidMap;
00894   Guchar *fdSelect;
00895   Guchar *charStringsIdxPtr, *fdArrayIdx, *idxPtr0, *idxPtr1, *ptr;
00896   char buf[512];
00897   char eBuf[256];
00898   int nGlyphs, nCIDs, nFDs;
00899   int fdSelectFmt, nRanges, gid0, gid1, fd;
00900   int key;
00901   double x;
00902   GBool isFP;
00903   int i, j, n;
00904 
00905   outputFunc = outputFuncA;
00906   outputStream = outputStreamA;
00907 
00908   // read top dict (first font only)
00909   readTopDict(&dict);
00910 
00911   // read the FDArray dictionaries and Private dictionaries
00912   if (dict.fdArrayOffset == 0) {
00913     nFDs = 1;
00914     privateDicts = (Type1CPrivateDict *)
00915                      gmalloc(nFDs * sizeof(Type1CPrivateDict));
00916     privateDicts[0].dictData = new GString();
00917     privateDicts[0].subrsOffset = 0;
00918     privateDicts[0].defaultWidthX = 0;
00919     privateDicts[0].defaultWidthXFP = gFalse;
00920     privateDicts[0].nominalWidthX = 0;
00921     privateDicts[0].nominalWidthXFP = gFalse;
00922   } else {
00923     fdArrayIdx = (Guchar *)file + dict.fdArrayOffset;
00924     nFDs = getIndexLen(fdArrayIdx);
00925     privateDicts = (Type1CPrivateDict *)
00926                      gmalloc(nFDs * sizeof(Type1CPrivateDict));
00927     idxPtr1 = getIndexValPtr(fdArrayIdx, 0);
00928     for (i = 0; i < nFDs; ++i) {
00929       privateDicts[i].dictData = NULL;
00930       idxPtr0 = idxPtr1;
00931       idxPtr1 = getIndexValPtr(fdArrayIdx, i + 1);
00932       ptr = idxPtr0;
00933       j = 0;
00934       while (ptr < idxPtr1) {
00935     if (*ptr <= 27 || *ptr == 31) {
00936       key = *ptr++;
00937       if (key == 0x0c) {
00938         key = (key << 8) | *ptr++;
00939       }
00940       if (key == 0x0012) {
00941         readPrivateDict(&privateDicts[i], (int)op[1], (int)op[0]);
00942       }
00943       j = 0;
00944     } else {
00945       x = getNum(&ptr, &isFP);
00946       if (j < 48) {
00947         op[j] = x;
00948         fp[j++] = isFP;
00949       }
00950     }
00951       }
00952       if (!privateDicts[i].dictData) {
00953     privateDicts[i].dictData = new GString();
00954     privateDicts[i].subrsOffset = 0;
00955     privateDicts[i].defaultWidthX = 0;
00956     privateDicts[i].defaultWidthXFP = gFalse;
00957     privateDicts[i].nominalWidthX = 0;
00958     privateDicts[i].nominalWidthXFP = gFalse;
00959       }
00960     }
00961   }
00962 
00963   // get the glyph count
00964   charStringsIdxPtr = (Guchar *)file + dict.charStrings;
00965   nGlyphs = getIndexLen(charStringsIdxPtr);
00966 
00967   // read the FDSelect table
00968   fdSelect = (Guchar *)gmalloc(nGlyphs);
00969   if (dict.fdSelectOffset == 0) {
00970     for (i = 0; i < nGlyphs; ++i) {
00971       fdSelect[i] = 0;
00972     }
00973   } else {
00974     ptr = (Guchar *)file + dict.fdSelectOffset;
00975     fdSelectFmt = *ptr++;
00976     if (fdSelectFmt == 0) {
00977       memcpy(fdSelect, ptr, nGlyphs);
00978     } else if (fdSelectFmt == 3) {
00979       nRanges = getWord(ptr, 2);
00980       ptr += 2;
00981       gid0 = getWord(ptr, 2);
00982       ptr += 2;
00983       for (i = 1; i <= nRanges; ++i) {
00984     fd = *ptr++;
00985     gid1 = getWord(ptr, 2);
00986     ptr += 2;
00987     for (j = gid0; j < gid1; ++j) {
00988       fdSelect[j] = fd;
00989     }
00990     gid0 = gid1;
00991       }
00992     } else {
00993       error(-1, "Unknown FDSelect table format in CID font");
00994       for (i = 0; i < nGlyphs; ++i) {
00995     fdSelect[i] = 0;
00996       }
00997     }
00998   }
00999 
01000   // read the charset, compute the CID-to-GID mapping
01001   charset = readCharset(dict.charset, nGlyphs);
01002   nCIDs = 0;
01003   for (i = 0; i < nGlyphs; ++i) {
01004     if (charset[i] >= nCIDs) {
01005       nCIDs = charset[i] + 1;
01006     }
01007   }
01008   cidMap = (int *)gmalloc(nCIDs * sizeof(int));
01009   for (i = 0; i < nCIDs; ++i) {
01010     cidMap[i] = -1;
01011   }
01012   for (i = 0; i < nGlyphs; ++i) {
01013     cidMap[charset[i]] = i;
01014   }
01015 
01016   // write the descendant Type 1 fonts
01017   for (i = 0; i < nCIDs; i += 256) {
01018 
01019     //~ this assumes that all CIDs in this block have the same FD --
01020     //~ to handle multiple FDs correctly, need to somehow divide the
01021     //~ font up by FD
01022     fd = 0;
01023     for (j = 0; j < 256 && i+j < nCIDs; ++j) {
01024       if (cidMap[i+j] >= 0) {
01025     fd = fdSelect[cidMap[i+j]];
01026     break;
01027       }
01028     }
01029 
01030     // font dictionary (unencrypted section)
01031     (*outputFunc)(outputStream, "16 dict begin\n", 14);
01032     (*outputFunc)(outputStream, "/FontName /", 11);
01033     (*outputFunc)(outputStream, psName, strlen(psName));
01034     sprintf(buf, "_%02x def\n", i >> 8);
01035     (*outputFunc)(outputStream, buf, strlen(buf));
01036     (*outputFunc)(outputStream, "/FontType 1 def\n", 16);
01037     sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] def\n",
01038         dict.fontMatrix[0], dict.fontMatrix[1], dict.fontMatrix[2],
01039         dict.fontMatrix[3], dict.fontMatrix[4], dict.fontMatrix[5]);
01040     (*outputFunc)(outputStream, buf, strlen(buf));
01041     sprintf(buf, "/FontBBox [%g %g %g %g] def\n",
01042         dict.fontBBox[0], dict.fontBBox[1],
01043         dict.fontBBox[2], dict.fontBBox[3]);
01044     (*outputFunc)(outputStream, buf, strlen(buf));
01045     sprintf(buf, "/PaintType %d def\n", dict.paintType);
01046     (*outputFunc)(outputStream, buf, strlen(buf));
01047     if (dict.paintType != 0) {
01048       sprintf(buf, "/StrokeWidth %g def\n", dict.strokeWidth);
01049       (*outputFunc)(outputStream, buf, strlen(buf));
01050     }
01051     (*outputFunc)(outputStream, "/Encoding 256 array\n", 20);
01052     for (j = 0; j < 256 && i+j < nCIDs; ++j) {
01053       sprintf(buf, "dup %d /c%02x put\n", j, j);
01054       (*outputFunc)(outputStream, buf, strlen(buf));
01055     }
01056     (*outputFunc)(outputStream, "readonly def\n", 13);
01057     (*outputFunc)(outputStream, "currentdict end\n", 16);
01058 
01059     // start the binary section
01060     (*outputFunc)(outputStream, "currentfile eexec\n", 18);
01061     r1 = 55665;
01062     line = 0;
01063 
01064     // start the private dictionary
01065     eexecWrite("\x83\xca\x73\xd5");
01066     eexecWrite("dup /Private 32 dict dup begin\n");
01067     eexecWrite("/RD {string currentfile exch readstring pop} executeonly def\n");
01068     eexecWrite("/ND {noaccess def} executeonly def\n");
01069     eexecWrite("/NP {noaccess put} executeonly def\n");
01070     eexecWrite("/MinFeature {16 16} ND\n");
01071     eexecWrite(privateDicts[fd].dictData->getCString());
01072     defaultWidthX = privateDicts[fd].defaultWidthX;
01073     defaultWidthXFP = privateDicts[fd].defaultWidthXFP;
01074     nominalWidthX = privateDicts[fd].nominalWidthX;
01075     nominalWidthXFP = privateDicts[fd].nominalWidthXFP;
01076 
01077     // start the CharStrings
01078     sprintf(eBuf, "2 index /CharStrings 256 dict dup begin\n");
01079     eexecWrite(eBuf);
01080 
01081     // write the .notdef CharString
01082     idxPtr0 = getIndexValPtr(charStringsIdxPtr, 0);
01083     idxPtr1 = getIndexValPtr(charStringsIdxPtr, 1);
01084     n = idxPtr1 - idxPtr0;
01085     eexecCvtGlyph(".notdef", idxPtr0, n);
01086 
01087     // write the CharStrings
01088     for (j = 0; j < 256 && i+j < nCIDs; ++j) {
01089       if (cidMap[i+j] >= 0) {
01090     idxPtr0 = getIndexValPtr(charStringsIdxPtr, cidMap[i+j]);
01091     idxPtr1 = getIndexValPtr(charStringsIdxPtr, cidMap[i+j]+1);
01092     n = idxPtr1 - idxPtr0;
01093     sprintf(buf, "c%02x", j);
01094     eexecCvtGlyph(buf, idxPtr0, n);
01095       }
01096     }
01097     eexecWrite("end\n");
01098     eexecWrite("end\n");
01099     eexecWrite("readonly put\n");
01100     eexecWrite("noaccess put\n");
01101     eexecWrite("dup /FontName get exch definefont pop\n");
01102     eexecWrite("mark currentfile closefile\n");
01103 
01104     // trailer
01105     if (line > 0) {
01106       (*outputFunc)(outputStream, "\n", 1);
01107     }
01108     for (j = 0; j < 8; ++j) {
01109       (*outputFunc)(outputStream, "0000000000000000000000000000000000000000000000000000000000000000\n", 65);
01110     }
01111     (*outputFunc)(outputStream, "cleartomark\n", 12);
01112   }
01113 
01114   // write the Type 0 parent font
01115   (*outputFunc)(outputStream, "16 dict begin\n", 14);
01116   (*outputFunc)(outputStream, "/FontName /", 11);
01117   (*outputFunc)(outputStream, psName, strlen(psName));
01118   (*outputFunc)(outputStream, " def\n", 5);
01119   (*outputFunc)(outputStream, "/FontType 0 def\n", 16);
01120   (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
01121   (*outputFunc)(outputStream, "/FMapType 2 def\n", 16);
01122   (*outputFunc)(outputStream, "/Encoding [\n", 12);
01123   for (i = 0; i < nCIDs; i += 256) {
01124     sprintf(buf, "%d\n", i >> 8);
01125     (*outputFunc)(outputStream, buf, strlen(buf));
01126   }
01127   (*outputFunc)(outputStream, "] def\n", 6);
01128   (*outputFunc)(outputStream, "/FDepVector [\n", 14);
01129   for (i = 0; i < nCIDs; i += 256) {
01130     (*outputFunc)(outputStream, "/", 1);
01131     (*outputFunc)(outputStream, psName, strlen(psName));
01132     sprintf(buf, "_%02x findfont\n", i >> 8);
01133     (*outputFunc)(outputStream, buf, strlen(buf));
01134   }
01135   (*outputFunc)(outputStream, "] def\n", 6);
01136   (*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40);
01137 
01138   // clean up
01139   for (i = 0; i < nFDs; ++i) {
01140     delete privateDicts[i].dictData;
01141   }
01142   gfree(privateDicts);
01143   gfree(cidMap);
01144   gfree(charset);
01145   gfree(fdSelect);
01146 }
01147 
01148 void Type1CFontFile::readTopDict(Type1CTopDict *dict) {
01149   Guchar *idxPtr0, *idxPtr1, *ptr;
01150   double x;
01151   GBool isFP;
01152   int key;
01153   int i;
01154 
01155   idxPtr0 = getIndexValPtr(topDictIdxPtr, 0);
01156   idxPtr1 = getIndexValPtr(topDictIdxPtr, 1);
01157   dict->version = 0;
01158   dict->notice = 0;
01159   dict->copyright = 0;
01160   dict->fullName = 0;
01161   dict->familyName = 0;
01162   dict->weight = 0;
01163   dict->isFixedPitch = 0;
01164   dict->italicAngle = 0;
01165   dict->underlinePosition = -100;
01166   dict->underlineThickness = 50;
01167   dict->paintType = 0;
01168   dict->charstringType = 2;
01169   dict->fontMatrix[0] = 0.001;
01170   dict->fontMatrix[1] = 0;
01171   dict->fontMatrix[2] = 0;
01172   dict->fontMatrix[3] = 0.001;
01173   dict->fontMatrix[4] = 0;
01174   dict->fontMatrix[5] = 0;
01175   dict->uniqueID = 0;
01176   dict->fontBBox[0] = 0;
01177   dict->fontBBox[1] = 0;
01178   dict->fontBBox[2] = 0;
01179   dict->fontBBox[3] = 0;
01180   dict->strokeWidth = 0;
01181   dict->charset = 0;
01182   dict->encoding = 0;
01183   dict->charStrings = 0;
01184   dict->privateSize = 0;
01185   dict->privateOffset = 0;
01186   dict->registry = 0;
01187   dict->ordering = 0;
01188   dict->supplement = 0;
01189   dict->fdArrayOffset = 0;
01190   dict->fdSelectOffset = 0;
01191   i = 0;
01192   ptr = idxPtr0;
01193   while (ptr < idxPtr1) {
01194     if (*ptr <= 27 || *ptr == 31) {
01195       key = *ptr++;
01196       if (key == 0x0c) {
01197     key = (key << 8) | *ptr++;
01198       }
01199       switch (key) {
01200       case 0x0000: dict->version = (int)op[0]; break;
01201       case 0x0001: dict->notice = (int)op[0]; break;
01202       case 0x0c00: dict->copyright = (int)op[0]; break;
01203       case 0x0002: dict->fullName = (int)op[0]; break;
01204       case 0x0003: dict->familyName = (int)op[0]; break;
01205       case 0x0004: dict->weight = (int)op[0]; break;
01206       case 0x0c01: dict->isFixedPitch = (int)op[0]; break;
01207       case 0x0c02: dict->italicAngle = op[0]; break;
01208       case 0x0c03: dict->underlinePosition = op[0]; break;
01209       case 0x0c04: dict->underlineThickness = op[0]; break;
01210       case 0x0c05: dict->paintType = (int)op[0]; break;
01211       case 0x0c06: dict->charstringType = (int)op[0]; break;
01212       case 0x0c07: dict->fontMatrix[0] = op[0];
01213                dict->fontMatrix[1] = op[1];
01214                dict->fontMatrix[2] = op[2];
01215                dict->fontMatrix[3] = op[3];
01216                dict->fontMatrix[4] = op[4];
01217                dict->fontMatrix[5] = op[5]; break;
01218       case 0x000d: dict->uniqueID = (int)op[0]; break;
01219       case 0x0005: dict->fontBBox[0] = op[0];
01220                dict->fontBBox[1] = op[1];
01221                dict->fontBBox[2] = op[2];
01222                dict->fontBBox[3] = op[3]; break;
01223       case 0x0c08: dict->strokeWidth = op[0]; break;
01224       case 0x000f: dict->charset = (int)op[0]; break;
01225       case 0x0010: dict->encoding = (int)op[0]; break;
01226       case 0x0011: dict->charStrings = (int)op[0]; break;
01227       case 0x0012: dict->privateSize = (int)op[0];
01228                dict->privateOffset = (int)op[1]; break;
01229       case 0x0c1e: dict->registry = (int)op[0];
01230                dict->ordering = (int)op[1];
01231            dict->supplement = (int)op[2]; break;
01232       case 0x0c24: dict->fdArrayOffset = (int)op[0]; break;
01233       case 0x0c25: dict->fdSelectOffset = (int)op[0]; break;
01234       }
01235       i = 0;
01236     } else {
01237       x = getNum(&ptr, &isFP);
01238       if (i < 48) {
01239     op[i] = x;
01240     fp[i++] = isFP;
01241       }
01242     }
01243   }
01244 }
01245 
01246 void Type1CFontFile::readPrivateDict(Type1CPrivateDict *privateDict,
01247                      int offset, int size) {
01248   Guchar *idxPtr0, *idxPtr1, *ptr;
01249   char eBuf[256];
01250   int key;
01251   double x;
01252   GBool isFP;
01253   int i;
01254 
01255   privateDict->dictData = new GString();
01256   privateDict->subrsOffset = 0;
01257   privateDict->defaultWidthX = 0;
01258   privateDict->defaultWidthXFP = gFalse;
01259   privateDict->nominalWidthX = 0;
01260   privateDict->nominalWidthXFP = gFalse;
01261   idxPtr0 = (Guchar *)file + offset;
01262   idxPtr1 = idxPtr0 + size;
01263   ptr = idxPtr0;
01264   i = 0;
01265   while (ptr < idxPtr1) {
01266     if (*ptr <= 27 || *ptr == 31) {
01267       key = *ptr++;
01268       if (key == 0x0c) {
01269     key = (key << 8) | *ptr++;
01270       }
01271       switch (key) {
01272       case 0x0006:
01273     getDeltaInt(eBuf, "BlueValues", op, i);
01274     privateDict->dictData->append(eBuf);
01275     break;
01276       case 0x0007:
01277     getDeltaInt(eBuf, "OtherBlues", op, i);
01278     privateDict->dictData->append(eBuf);
01279     break;
01280       case 0x0008:
01281     getDeltaInt(eBuf, "FamilyBlues", op, i);
01282     privateDict->dictData->append(eBuf);
01283     break;
01284       case 0x0009:
01285     getDeltaInt(eBuf, "FamilyOtherBlues", op, i);
01286     privateDict->dictData->append(eBuf);
01287     break;
01288       case 0x0c09:
01289     sprintf(eBuf, "/BlueScale %g def\n", op[0]);
01290     privateDict->dictData->append(eBuf);
01291     break;
01292       case 0x0c0a:
01293     sprintf(eBuf, "/BlueShift %d def\n", (int)op[0]);
01294     privateDict->dictData->append(eBuf);
01295     break;
01296       case 0x0c0b:
01297     sprintf(eBuf, "/BlueFuzz %d def\n", (int)op[0]);
01298     privateDict->dictData->append(eBuf);
01299     break;
01300       case 0x000a:
01301     sprintf(eBuf, "/StdHW [%g] def\n", op[0]);
01302     privateDict->dictData->append(eBuf);
01303     break;
01304       case 0x000b:
01305     sprintf(eBuf, "/StdVW [%g] def\n", op[0]);
01306     privateDict->dictData->append(eBuf);
01307     break;
01308       case 0x0c0c:
01309     getDeltaReal(eBuf, "StemSnapH", op, i);
01310     privateDict->dictData->append(eBuf);
01311     break;
01312       case 0x0c0d:
01313     getDeltaReal(eBuf, "StemSnapV", op, i);
01314     privateDict->dictData->append(eBuf);
01315     break;
01316       case 0x0c0e:
01317     sprintf(eBuf, "/ForceBold %s def\n", op[0] ? "true" : "false");
01318     privateDict->dictData->append(eBuf);
01319     break;
01320       case 0x0c0f:
01321     sprintf(eBuf, "/ForceBoldThreshold %g def\n", op[0]);
01322     privateDict->dictData->append(eBuf);
01323     break;
01324       case 0x0c11:
01325     sprintf(eBuf, "/LanguageGroup %d def\n", (int)op[0]);
01326     privateDict->dictData->append(eBuf);
01327     break;
01328       case 0x0c12:
01329     sprintf(eBuf, "/ExpansionFactor %g def\n", op[0]);
01330     privateDict->dictData->append(eBuf);
01331     break;
01332       case 0x0c13:
01333     error(-1, "Got Type 1C InitialRandomSeed");
01334     break;
01335       case 0x0013:
01336     privateDict->subrsOffset = (int)op[0];
01337     break;
01338       case 0x0014:
01339     privateDict->defaultWidthX = op[0];
01340     privateDict->defaultWidthXFP = fp[0];
01341     break;
01342       case 0x0015:
01343     privateDict->nominalWidthX = op[0];
01344     privateDict->nominalWidthXFP = fp[0];
01345     break;
01346       default:
01347     error(-1, "Unknown Type 1C private dict entry %04x", key);
01348     break;
01349       }
01350       i = 0;
01351     } else {
01352       x = getNum(&ptr, &isFP);
01353       if (i < 48) {
01354     op[i] = x;
01355     fp[i++] = isFP;
01356       }
01357     }
01358   }
01359 }
01360 
01361 Gushort *Type1CFontFile::readCharset(int charset, int nGlyphs) {
01362   Gushort *glyphNames;
01363   Guchar *ptr;
01364   int charsetFormat, c;
01365   int nLeft, i, j;
01366 
01367   if (charset == 0) {
01368     glyphNames = type1CISOAdobeCharset;
01369   } else if (charset == 1) {
01370     glyphNames = type1CExpertCharset;
01371   } else if (charset == 2) {
01372     glyphNames = type1CExpertSubsetCharset;
01373   } else {
01374     glyphNames = (Gushort *)gmalloc(nGlyphs * sizeof(Gushort));
01375     glyphNames[0] = 0;
01376     ptr = (Guchar *)file + charset;
01377     charsetFormat = *ptr++;
01378     if (charsetFormat == 0) {
01379       for (i = 1; i < nGlyphs; ++i) {
01380     glyphNames[i] = getWord(ptr, 2);
01381     ptr += 2;
01382       }
01383     } else if (charsetFormat == 1) {
01384       i = 1;
01385       while (i < nGlyphs) {
01386     c = getWord(ptr, 2);
01387     ptr += 2;
01388     nLeft = *ptr++;
01389     for (j = 0; j <= nLeft && i < nGlyphs; ++j) {
01390       glyphNames[i++] = c++;
01391     }
01392       }
01393     } else if (charsetFormat == 2) {
01394       i = 1;
01395       while (i < nGlyphs) {
01396     c = getWord(ptr, 2);
01397     ptr += 2;
01398     nLeft = getWord(ptr, 2);
01399     ptr += 2;
01400     for (j = 0; j <= nLeft && i < nGlyphs; ++j) {
01401       glyphNames[i++] = c++;
01402     }
01403       }
01404     }
01405   }
01406   return glyphNames;
01407 }
01408 
01409 void Type1CFontFile::eexecWrite(const char *s) {
01410   const Guchar *p;
01411   Guchar x;
01412 
01413   for (p = (const Guchar *)s; *p; ++p) {
01414     x = *p ^ (r1 >> 8);
01415     r1 = (x + r1) * 52845 + 22719;
01416     (*outputFunc)(outputStream, &hexChars[x >> 4], 1);
01417     (*outputFunc)(outputStream, &hexChars[x & 0x0f], 1);
01418     line += 2;
01419     if (line == 64) {
01420       (*outputFunc)(outputStream, "\n", 1);
01421       line = 0;
01422     }
01423   }
01424 }
01425 
01426 void Type1CFontFile::eexecCvtGlyph(const char *glyphName, const Guchar *s, int n) {
01427   char eBuf[256];
01428 
01429   cvtGlyph(s, n);
01430   sprintf(eBuf, "/%s %d RD ", glyphName, charBuf->getLength());
01431   eexecWrite(eBuf);
01432   eexecWriteCharstring((Guchar *)charBuf->getCString(), charBuf->getLength());
01433   eexecWrite(" ND\n");
01434   delete charBuf;
01435 }
01436 
01437 void Type1CFontFile::cvtGlyph(const Guchar *s, int n) {
01438   int nHints;
01439   int x;
01440   GBool first = gTrue;
01441   double d, dx, dy;
01442   GBool dFP;
01443   Gushort r2;
01444   Guchar byte;
01445   int i, k;
01446 
01447   charBuf = new GString();
01448   charBuf->append((char)73);
01449   charBuf->append((char)58);
01450   charBuf->append((char)147);
01451   charBuf->append((char)134);
01452 
01453   i = 0;
01454   nOps = 0;
01455   nHints = 0;
01456   while (i < n) {
01457     if (s[i] == 12) {
01458       switch (s[i+1]) {
01459       case 0:           // dotsection (should be Type 1 only?)
01460     // ignored
01461     break;
01462       case 34:          // hflex
01463     if (nOps != 7) {
01464       error(-1, "Wrong number of args (%d) to Type 2 hflex", nOps);
01465     }
01466     eexecDumpNum(op[0], fp[0]);
01467     eexecDumpNum(0, gFalse);
01468     eexecDumpNum(op[1], fp[1]);
01469     eexecDumpNum(op[2], fp[2]);
01470     eexecDumpNum(op[3], fp[3]);
01471     eexecDumpNum(0, gFalse);
01472     eexecDumpOp1(8);
01473     eexecDumpNum(op[4], fp[4]);
01474     eexecDumpNum(0, gFalse);
01475     eexecDumpNum(op[5], fp[5]);
01476     eexecDumpNum(-op[2], fp[2]);
01477     eexecDumpNum(op[6], fp[6]);
01478     eexecDumpNum(0, gFalse);
01479     eexecDumpOp1(8);
01480     break;
01481       case 35:          // flex
01482     if (nOps != 13) {
01483       error(-1, "Wrong number of args (%d) to Type 2 flex", nOps);
01484     }
01485     eexecDumpNum(op[0], fp[0]);
01486     eexecDumpNum(op[1], fp[1]);
01487     eexecDumpNum(op[2], fp[2]);
01488     eexecDumpNum(op[3], fp[3]);
01489     eexecDumpNum(op[4], fp[4]);
01490     eexecDumpNum(op[5], fp[5]);
01491     eexecDumpOp1(8);
01492     eexecDumpNum(op[6], fp[6]);
01493     eexecDumpNum(op[7], fp[7]);
01494     eexecDumpNum(op[8], fp[8]);
01495     eexecDumpNum(op[9], fp[9]);
01496     eexecDumpNum(op[10], fp[10]);
01497     eexecDumpNum(op[11], fp[11]);
01498     eexecDumpOp1(8);
01499     break;
01500       case 36:          // hflex1
01501     if (nOps != 9) {
01502       error(-1, "Wrong number of args (%d) to Type 2 hflex1", nOps);
01503     }
01504     eexecDumpNum(op[0], fp[0]);
01505     eexecDumpNum(op[1], fp[1]);
01506     eexecDumpNum(op[2], fp[2]);
01507     eexecDumpNum(op[3], fp[3]);
01508     eexecDumpNum(op[4], fp[4]);
01509     eexecDumpNum(0, gFalse);
01510     eexecDumpOp1(8);
01511     eexecDumpNum(op[5], fp[5]);
01512     eexecDumpNum(0, gFalse);
01513     eexecDumpNum(op[6], fp[6]);
01514     eexecDumpNum(op[7], fp[7]);
01515     eexecDumpNum(op[8], fp[8]);
01516     eexecDumpNum(-(op[1] + op[3] + op[7]), fp[1] | fp[3] | fp[7]);
01517     eexecDumpOp1(8);
01518     break;
01519       case 37:          // flex1
01520     if (nOps != 11) {
01521       error(-1, "Wrong number of args (%d) to Type 2 flex1", nOps);
01522     }
01523     eexecDumpNum(op[0], fp[0]);
01524     eexecDumpNum(op[1], fp[1]);
01525     eexecDumpNum(op[2], fp[2]);
01526     eexecDumpNum(op[3], fp[3]);
01527     eexecDumpNum(op[4], fp[4]);
01528     eexecDumpNum(op[5], fp[5]);
01529     eexecDumpOp1(8);
01530     eexecDumpNum(op[6], fp[6]);
01531     eexecDumpNum(op[7], fp[7]);
01532     eexecDumpNum(op[8], fp[8]);
01533     eexecDumpNum(op[9], fp[9]);
01534     dx = op[0] + op[2] + op[4] + op[6] + op[8];
01535     dy = op[1] + op[3] + op[5] + op[7] + op[9];
01536     if (fabs(dx) > fabs(dy)) {
01537       eexecDumpNum(op[10], fp[10]);
01538       eexecDumpNum(-dy, fp[1] | fp[3] | fp[5] | fp[7] | fp[9]);
01539     } else {
01540       eexecDumpNum(-dx, fp[0] | fp[2] | fp[4] | fp[6] | fp[8]);
01541       eexecDumpNum(op[10], fp[10]);
01542     }
01543     eexecDumpOp1(8);
01544     break;
01545       case 3:           // and
01546       case 4:           // or
01547       case 5:           // not
01548       case 8:           // store
01549       case 9:           // abs
01550       case 10:          // add
01551       case 11:          // sub
01552       case 12:          // div
01553       case 13:          // load
01554       case 14:          // neg
01555       case 15:          // eq
01556       case 18:          // drop
01557       case 20:          // put
01558       case 21:          // get
01559       case 22:          // ifelse
01560       case 23:          // random
01561       case 24:          // mul
01562       case 26:          // sqrt
01563       case 27:          // dup
01564       case 28:          // exch
01565       case 29:          // index
01566       case 30:          // roll
01567     error(-1, "Unimplemented Type 2 charstring op: 12.%d", s[i+1]);
01568     break;
01569       default:
01570     error(-1, "Illegal Type 2 charstring op: 12.%d", s[i+1]);
01571     break;
01572       }
01573       i += 2;
01574       nOps = 0;
01575     } else if (s[i] == 19) {    // hintmask
01576       // ignored
01577       if (first) {
01578     cvtGlyphWidth(nOps == 1);
01579     first = gFalse;
01580       }
01581       if (nOps > 0) {
01582     if (nOps & 1) {
01583       error(-1, "Wrong number of args (%d) to Type 2 hintmask/vstemhm",
01584         nOps);
01585     }
01586     nHints += nOps / 2;
01587       }
01588       i += 1 + ((nHints + 7) >> 3);
01589       nOps = 0;
01590     } else if (s[i] == 20) {    // cntrmask
01591       // ignored
01592       if (first) {
01593     cvtGlyphWidth(nOps == 1);
01594     first = gFalse;
01595       }
01596       if (nOps > 0) {
01597     if (nOps & 1) {
01598       error(-1, "Wrong number of args (%d) to Type 2 cntrmask/vstemhm",
01599         nOps);
01600     }
01601     nHints += nOps / 2;
01602       }
01603       i += 1 + ((nHints + 7) >> 3);
01604       nOps = 0;
01605     } else if (s[i] == 28) {
01606       x = (s[i+1] << 8) + s[i+2];
01607       if (x & 0x8000) {
01608     x |= -1 << 15;
01609       }
01610       if (nOps < 48) {
01611     fp[nOps] = gFalse;
01612     op[nOps++] = x;
01613       }
01614       i += 3;
01615     } else if (s[i] <= 31) {
01616       switch (s[i]) {
01617       case 4:           // vmoveto
01618     if (first) {
01619       cvtGlyphWidth(nOps == 2);
01620       first = gFalse;
01621     }
01622     if (nOps != 1) {
01623       error(-1, "Wrong number of args (%d) to Type 2 vmoveto", nOps);
01624     }
01625     eexecDumpNum(op[0], fp[0]);
01626     eexecDumpOp1(4);
01627     break;
01628       case 5:           // rlineto
01629     if (nOps < 2 || nOps % 2 != 0) {
01630       error(-1, "Wrong number of args (%d) to Type 2 rlineto", nOps);
01631     }
01632     for (k = 0; k < nOps; k += 2) {
01633       eexecDumpNum(op[k], fp[k]);
01634       eexecDumpNum(op[k+1], fp[k+1]);
01635       eexecDumpOp1(5);
01636     }
01637     break;
01638       case 6:           // hlineto
01639     if (nOps < 1) {
01640       error(-1, "Wrong number of args (%d) to Type 2 hlineto", nOps);
01641     }
01642     for (k = 0; k < nOps; ++k) {
01643       eexecDumpNum(op[k], fp[k]);
01644       eexecDumpOp1((k & 1) ? 7 : 6);
01645     }
01646     break;
01647       case 7:           // vlineto
01648     if (nOps < 1) {
01649       error(-1, "Wrong number of args (%d) to Type 2 vlineto", nOps);
01650     }
01651     for (k = 0; k < nOps; ++k) {
01652       eexecDumpNum(op[k], fp[k]);
01653       eexecDumpOp1((k & 1) ? 6 : 7);
01654     }
01655     break;
01656       case 8:           // rrcurveto
01657     if (nOps < 6 || nOps % 6 != 0) {
01658       error(-1, "Wrong number of args (%d) to Type 2 rrcurveto", nOps);
01659     }
01660     for (k = 0; k < nOps; k += 6) {
01661       eexecDumpNum(op[k], fp[k]);
01662       eexecDumpNum(op[k+1], fp[k+1]);
01663       eexecDumpNum(op[k+2], fp[k+2]);
01664       eexecDumpNum(op[k+3], fp[k+3]);
01665       eexecDumpNum(op[k+4], fp[k+4]);
01666       eexecDumpNum(op[k+5], fp[k+5]);
01667       eexecDumpOp1(8);
01668     }
01669     break;
01670       case 14:          // endchar / seac
01671     if (first) {
01672       cvtGlyphWidth(nOps == 1 || nOps == 5);
01673       first = gFalse;
01674     }
01675     if (nOps == 4) {
01676       eexecDumpNum(0, 0);
01677       eexecDumpNum(op[0], fp[0]);
01678       eexecDumpNum(op[1], fp[1]);
01679       eexecDumpNum(op[2], fp[2]);
01680       eexecDumpNum(op[3], fp[3]);
01681       eexecDumpOp2(6);
01682     } else if (nOps == 0) {
01683       eexecDumpOp1(14);
01684     } else {
01685       error(-1, "Wrong number of args (%d) to Type 2 endchar", nOps);
01686     }
01687     break;
01688       case 21:          // rmoveto
01689     if (first) {
01690       cvtGlyphWidth(nOps == 3);
01691       first = gFalse;
01692     }
01693     if (nOps != 2) {
01694       error(-1, "Wrong number of args (%d) to Type 2 rmoveto", nOps);
01695     }
01696     eexecDumpNum(op[0], fp[0]);
01697     eexecDumpNum(op[1], fp[1]);
01698     eexecDumpOp1(21);
01699     break;
01700       case 22:          // hmoveto
01701     if (first) {
01702       cvtGlyphWidth(nOps == 2);
01703       first = gFalse;
01704     }
01705     if (nOps != 1) {
01706       error(-1, "Wrong number of args (%d) to Type 2 hmoveto", nOps);
01707     }
01708     eexecDumpNum(op[0], fp[0]);
01709     eexecDumpOp1(22);
01710     break;
01711       case 24:          // rcurveline
01712     if (nOps < 8 || (nOps - 2) % 6 != 0) {
01713       error(-1, "Wrong number of args (%d) to Type 2 rcurveline", nOps);
01714     }
01715     for (k = 0; k < nOps - 2; k += 6) {
01716       eexecDumpNum(op[k], fp[k]);
01717       eexecDumpNum(op[k+1], fp[k+1]);
01718       eexecDumpNum(op[k+2], fp[k+2]);
01719       eexecDumpNum(op[k+3], fp[k+3]);
01720       eexecDumpNum(op[k+4], fp[k+4]);
01721       eexecDumpNum(op[k+5], fp[k+5]);
01722       eexecDumpOp1(8);
01723     }
01724     eexecDumpNum(op[k], fp[k]);
01725     eexecDumpNum(op[k+1], fp[k]);
01726     eexecDumpOp1(5);
01727     break;
01728       case 25:          // rlinecurve
01729     if (nOps < 8 || (nOps - 6) % 2 != 0) {
01730       error(-1, "Wrong number of args (%d) to Type 2 rlinecurve", nOps);
01731     }
01732     for (k = 0; k < nOps - 6; k += 2) {
01733       eexecDumpNum(op[k], fp[k]);
01734       eexecDumpNum(op[k+1], fp[k]);
01735       eexecDumpOp1(5);
01736     }
01737     eexecDumpNum(op[k], fp[k]);
01738     eexecDumpNum(op[k+1], fp[k+1]);
01739     eexecDumpNum(op[k+2], fp[k+2]);
01740     eexecDumpNum(op[k+3], fp[k+3]);
01741     eexecDumpNum(op[k+4], fp[k+4]);
01742     eexecDumpNum(op[k+5], fp[k+5]);
01743     eexecDumpOp1(8);
01744     break;
01745       case 26:          // vvcurveto
01746     if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
01747       error(-1, "Wrong number of args (%d) to Type 2 vvcurveto", nOps);
01748     }
01749     if (nOps % 2 == 1) {
01750       eexecDumpNum(op[0], fp[0]);
01751       eexecDumpNum(op[1], fp[1]);
01752       eexecDumpNum(op[2], fp[2]);
01753       eexecDumpNum(op[3], fp[3]);
01754       eexecDumpNum(0, gFalse);
01755       eexecDumpNum(op[4], fp[4]);
01756       eexecDumpOp1(8);
01757       k = 5;
01758     } else {
01759       k = 0;
01760     }
01761     for (; k < nOps; k += 4) {
01762       eexecDumpNum(0, gFalse);
01763       eexecDumpNum(op[k], fp[k]);
01764       eexecDumpNum(op[k+1], fp[k+1]);
01765       eexecDumpNum(op[k+2], fp[k+2]);
01766       eexecDumpNum(0, gFalse);
01767       eexecDumpNum(op[k+3], fp[k+3]);
01768       eexecDumpOp1(8);
01769     }
01770     break;
01771       case 27:          // hhcurveto
01772     if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
01773       error(-1, "Wrong number of args (%d) to Type 2 hhcurveto", nOps);
01774     }
01775     if (nOps % 2 == 1) {
01776       eexecDumpNum(op[1], fp[1]);
01777       eexecDumpNum(op[0], fp[0]);
01778       eexecDumpNum(op[2], fp[2]);
01779       eexecDumpNum(op[3], fp[3]);
01780       eexecDumpNum(op[4], fp[4]);
01781       eexecDumpNum(0, gFalse);
01782       eexecDumpOp1(8);
01783       k = 5;
01784     } else {
01785       k = 0;
01786     }
01787     for (; k < nOps; k += 4) {
01788       eexecDumpNum(op[k], fp[k]);
01789       eexecDumpNum(0, gFalse);
01790       eexecDumpNum(op[k+1], fp[k+1]);
01791       eexecDumpNum(op[k+2], fp[k+2]);
01792       eexecDumpNum(op[k+3], fp[k+3]);
01793       eexecDumpNum(0, gFalse);
01794       eexecDumpOp1(8);
01795     }
01796     break;
01797       case 30:          // vhcurveto
01798     if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
01799       error(-1, "Wrong number of args (%d) to Type 2 vhcurveto", nOps);
01800     }
01801     for (k = 0; k < nOps && k != nOps-5; k += 4) {
01802       if (k % 8 == 0) {
01803         eexecDumpNum(op[k], fp[k]);
01804         eexecDumpNum(op[k+1], fp[k+1]);
01805         eexecDumpNum(op[k+2], fp[k+2]);
01806         eexecDumpNum(op[k+3], fp[k+3]);
01807         eexecDumpOp1(30);
01808       } else {
01809         eexecDumpNum(op[k], fp[k]);
01810         eexecDumpNum(op[k+1], fp[k+1]);
01811         eexecDumpNum(op[k+2], fp[k+2]);
01812         eexecDumpNum(op[k+3], fp[k+3]);
01813         eexecDumpOp1(31);
01814       }
01815     }
01816     if (k == nOps-5) {
01817       if (k % 8 == 0) {
01818         eexecDumpNum(0, gFalse);
01819         eexecDumpNum(op[k], fp[k]);
01820         eexecDumpNum(op[k+1], fp[k+1]);
01821         eexecDumpNum(op[k+2], fp[k+2]);
01822         eexecDumpNum(op[k+3], fp[k+3]);
01823         eexecDumpNum(op[k+4], fp[k+4]);
01824       } else {
01825         eexecDumpNum(op[k], fp[k]);
01826         eexecDumpNum(0, gFalse);
01827         eexecDumpNum(op[k+1], fp[k+1]);
01828         eexecDumpNum(op[k+2], fp[k+2]);
01829         eexecDumpNum(op[k+4], fp[k+4]);
01830         eexecDumpNum(op[k+3], fp[k+3]);
01831       }
01832       eexecDumpOp1(8);
01833     }
01834     break;
01835       case 31:          // hvcurveto
01836     if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
01837       error(-1, "Wrong number of args (%d) to Type 2 hvcurveto", nOps);
01838     }
01839     for (k = 0; k < nOps && k != nOps-5; k += 4) {
01840       if (k % 8 == 0) {
01841         eexecDumpNum(op[k], fp[k]);
01842         eexecDumpNum(op[k+1], fp[k+1]);
01843         eexecDumpNum(op[k+2], fp[k+2]);
01844         eexecDumpNum(op[k+3], fp[k+3]);
01845         eexecDumpOp1(31);
01846       } else {
01847         eexecDumpNum(op[k], fp[k]);
01848         eexecDumpNum(op[k+1], fp[k+1]);
01849         eexecDumpNum(op[k+2], fp[k+2]);
01850         eexecDumpNum(op[k+3], fp[k+3]);
01851         eexecDumpOp1(30);
01852       }
01853     }
01854     if (k == nOps-5) {
01855       if (k % 8 == 0) {
01856         eexecDumpNum(op[k], fp[k]);
01857         eexecDumpNum(0, gFalse);
01858         eexecDumpNum(op[k+1], fp[k+1]);
01859         eexecDumpNum(op[k+2], fp[k+2]);
01860         eexecDumpNum(op[k+4], fp[k+4]);
01861         eexecDumpNum(op[k+3], fp[k+3]);
01862       } else {
01863         eexecDumpNum(0, gFalse);
01864         eexecDumpNum(op[k], fp[k]);
01865         eexecDumpNum(op[k+1], fp[k+1]);
01866         eexecDumpNum(op[k+2], fp[k+2]);
01867         eexecDumpNum(op[k+3], fp[k+3]);
01868         eexecDumpNum(op[k+4], fp[k+4]);
01869       }
01870       eexecDumpOp1(8);
01871     }
01872     break;
01873       case 1:           // hstem
01874     if (first) {
01875       cvtGlyphWidth(nOps & 1);
01876       first = gFalse;
01877     }
01878     if (nOps & 1) {
01879       error(-1, "Wrong number of args (%d) to Type 2 hstem", nOps);
01880     }
01881     d = 0;
01882     dFP = gFalse;
01883     for (k = 0; k < nOps; k += 2) {
01884       if (op[k+1] < 0) {
01885         d += op[k] + op[k+1];
01886         dFP |= fp[k] | fp[k+1];
01887         eexecDumpNum(d, dFP);
01888         eexecDumpNum(-op[k+1], fp[k+1]);
01889       } else {
01890         d += op[k];
01891         dFP |= fp[k];
01892         eexecDumpNum(d, dFP);
01893         eexecDumpNum(op[k+1], fp[k+1]);
01894         d += op[k+1];
01895         dFP |= fp[k+1];
01896       }
01897       eexecDumpOp1(1);
01898     }
01899     nHints += nOps / 2;
01900     break;
01901       case 3:           // vstem
01902     if (first) {
01903       cvtGlyphWidth(nOps & 1);
01904       first = gFalse;
01905     }
01906     if (nOps & 1) {
01907       error(-1, "Wrong number of args (%d) to Type 2 vstem", nOps);
01908     }
01909     d = 0;
01910     dFP = gFalse;
01911     for (k = 0; k < nOps; k += 2) {
01912       if (op[k+1] < 0) {
01913         d += op[k] + op[k+1];
01914         dFP |= fp[k] | fp[k+1];
01915         eexecDumpNum(d, dFP);
01916         eexecDumpNum(-op[k+1], fp[k+1]);
01917       } else {
01918         d += op[k];
01919         dFP |= fp[k];
01920         eexecDumpNum(d, dFP);
01921         eexecDumpNum(op[k+1], fp[k+1]);
01922         d += op[k+1];
01923         dFP |= fp[k+1];
01924       }
01925       eexecDumpOp1(3);
01926     }
01927     nHints += nOps / 2;
01928     break;
01929       case 18:          // hstemhm
01930     // ignored
01931     if (first) {
01932       cvtGlyphWidth(nOps & 1);
01933       first = gFalse;
01934     }
01935     if (nOps & 1) {
01936       error(-1, "Wrong number of args (%d) to Type 2 hstemhm", nOps);
01937     }
01938     nHints += nOps / 2;
01939     break;
01940       case 23:          // vstemhm
01941     // ignored
01942     if (first) {
01943       cvtGlyphWidth(nOps & 1);
01944       first = gFalse;
01945     }
01946     if (nOps & 1) {
01947       error(-1, "Wrong number of args (%d) to Type 2 vstemhm", nOps);
01948     }
01949     nHints += nOps / 2;
01950     break;
01951       case 10:          // callsubr
01952       case 11:          // return
01953       case 16:          // blend
01954       case 29:          // callgsubr
01955     error(-1, "Unimplemented Type 2 charstring op: %d", s[i]);
01956     break;
01957       default:
01958     error(-1, "Illegal Type 2 charstring op: %d", s[i]);
01959     break;
01960       }
01961       ++i;
01962       nOps = 0;
01963     } else if (s[i] <= 246) {
01964       if (nOps < 48) {
01965     fp[nOps] = gFalse;
01966     op[nOps++] = (int)s[i] - 139;
01967       }
01968       ++i;
01969     } else if (s[i] <= 250) {
01970       if (nOps < 48) {
01971     fp[nOps] = gFalse;
01972     op[nOps++] = (((int)s[i] - 247) << 8) + (int)s[i+1] + 108;
01973       }
01974       i += 2;
01975     } else if (s[i] <= 254) {
01976       if (nOps < 48) {
01977     fp[nOps] = gFalse;
01978     op[nOps++] = -(((int)s[i] - 251) << 8) - (int)s[i+1] - 108;
01979       }
01980       i += 2;
01981     } else {
01982       x = (s[i+1] << 24) | (s[i+2] << 16) | (s[i+3] << 8) | s[i+4];
01983       if (x & 0x80000000)
01984     x |= -1 << 31;
01985       if (nOps < 48) {
01986     fp[nOps] = gTrue;
01987     op[nOps++] = (double)x / 65536.0;
01988       }
01989       i += 5;
01990     }
01991   }
01992 
01993   // charstring encryption
01994   r2 = 4330;
01995   for (i = 0; i < charBuf->getLength(); ++i) {
01996     byte = charBuf->getChar(i) ^ (r2 >> 8);
01997     charBuf->setChar(i, byte);
01998     r2 = (byte + r2) * 52845 + 22719;
01999   }
02000 }
02001 
02002 void Type1CFontFile::cvtGlyphWidth(GBool useOp) {
02003   double w;
02004   GBool wFP;
02005   int i;
02006 
02007   if (useOp) {
02008     w = nominalWidthX + op[0];
02009     wFP = nominalWidthXFP | fp[0];
02010     for (i = 1; i < nOps; ++i) {
02011       op[i-1] = op[i];
02012       fp[i-1] = fp[i];
02013     }
02014     --nOps;
02015   } else {
02016     w = defaultWidthX;
02017     wFP = defaultWidthXFP;
02018   }
02019   eexecDumpNum(0, gFalse);
02020   eexecDumpNum(w, wFP);
02021   eexecDumpOp1(13);
02022 }
02023 
02024 void Type1CFontFile::eexecDumpNum(double x, GBool fpA) {
02025   Guchar buf[12];
02026   int y, n;
02027 
02028   n = 0;
02029   if (fpA) {
02030     if (x >= -32768 && x < 32768) {
02031       y = (int)(x * 256.0);
02032       buf[0] = 255;
02033       buf[1] = (Guchar)(y >> 24);
02034       buf[2] = (Guchar)(y >> 16);
02035       buf[3] = (Guchar)(y >> 8);
02036       buf[4] = (Guchar)y;
02037       buf[5] = 255;
02038       buf[6] = 0;
02039       buf[7] = 0;
02040       buf[8] = 1;
02041       buf[9] = 0;
02042       buf[10] = 12;
02043       buf[11] = 12;
02044       n = 12;
02045     } else {
02046       error(-1, "Type 2 fixed point constant out of range");
02047     }
02048   } else {
02049     y = (int)x;
02050     if (y >= -107 && y <= 107) {
02051       buf[0] = (Guchar)(y + 139);
02052       n = 1;
02053     } else if (y > 107 && y <= 1131) {
02054       y -= 108;
02055       buf[0] = (Guchar)((y >> 8) + 247);
02056       buf[1] = (Guchar)(y & 0xff);
02057       n = 2;
02058     } else if (y < -107 && y >= -1131) {
02059       y = -y - 108;
02060       buf[0] = (Guchar)((y >> 8) + 251);
02061       buf[1] = (Guchar)(y & 0xff);
02062       n = 2;
02063     } else {
02064       buf[0] = 255;
02065       buf[1] = (Guchar)(y >> 24);
02066       buf[2] = (Guchar)(y >> 16);
02067       buf[3] = (Guchar)(y >> 8);
02068       buf[4] = (Guchar)y;
02069       n = 5;
02070     }
02071   }
02072   charBuf->append((char *)buf, n);
02073 }
02074 
02075 void Type1CFontFile::eexecDumpOp1(int opA) {
02076   charBuf->append((char)opA);
02077 }
02078 
02079 void Type1CFontFile::eexecDumpOp2(int opA) {
02080   charBuf->append((char)12);
02081   charBuf->append((char)opA);
02082 }
02083 
02084 void Type1CFontFile::eexecWriteCharstring(const Guchar *s, int n) {
02085   Guchar x;
02086   int i;
02087 
02088   // eexec encryption
02089   for (i = 0; i < n; ++i) {
02090     x = s[i] ^ (r1 >> 8);
02091     r1 = (x + r1) * 52845 + 22719;
02092     (*outputFunc)(outputStream, &hexChars[x >> 4], 1);
02093     (*outputFunc)(outputStream, &hexChars[x & 0x0f], 1);
02094     line += 2;
02095     if (line == 64) {
02096       (*outputFunc)(outputStream, "\n", 1);
02097       line = 0;
02098     }
02099   }
02100 }
02101 
02102 void Type1CFontFile::getDeltaInt(char *buf, const char *key, const double *opA,
02103                  int n) {
02104   int x, i;
02105 
02106   sprintf(buf, "/%s [", key);
02107   buf += strlen(buf);
02108   x = 0;
02109   for (i = 0; i < n; ++i) {
02110     x += (int)opA[i];
02111     sprintf(buf, "%s%d", i > 0 ? " " : "", x);
02112     buf += strlen(buf);
02113   }
02114   sprintf(buf, "] def\n");
02115 }
02116 
02117 void Type1CFontFile::getDeltaReal(char *buf, const char *key, const double *opA,
02118                   int n) {
02119   double x;
02120   int i;
02121 
02122   sprintf(buf, "/%s [", key);
02123   buf += strlen(buf);
02124   x = 0;
02125   for (i = 0; i < n; ++i) {
02126     x += opA[i];
02127     sprintf(buf, "%s%g", i > 0 ? " " : "", x);
02128     buf += strlen(buf);
02129   }
02130   sprintf(buf, "] def\n");
02131 }
02132 
02133 int Type1CFontFile::getIndexLen(Guchar *indexPtr) {
02134   return (int)getWord(indexPtr, 2);
02135 }
02136 
02137 Guchar *Type1CFontFile::getIndexValPtr(Guchar *indexPtr, int i) {
02138   int n, offSize;
02139   Guchar *idxStartPtr;
02140 
02141   n = (int)getWord(indexPtr, 2);
02142   offSize = indexPtr[2];
02143   idxStartPtr = indexPtr + 3 + (n + 1) * offSize - 1;
02144   return idxStartPtr + getWord(indexPtr + 3 + i * offSize, offSize);
02145 }
02146 
02147 Guchar *Type1CFontFile::getIndexEnd(Guchar *indexPtr) {
02148   int n, offSize;
02149   Guchar *idxStartPtr;
02150 
02151   n = (int)getWord(indexPtr, 2);
02152   offSize = indexPtr[2];
02153   idxStartPtr = indexPtr + 3 + (n + 1) * offSize - 1;
02154   return idxStartPtr + getWord(indexPtr + 3 + n * offSize, offSize);
02155 }
02156 
02157 Guint Type1CFontFile::getWord(Guchar *ptr, int size) {
02158   Guint x;
02159   int i;
02160 
02161   x = 0;
02162   for (i = 0; i < size; ++i) {
02163     x = (x << 8) + *ptr++;
02164   }
02165   return x;
02166 }
02167 
02168 double Type1CFontFile::getNum(Guchar **ptr, GBool *isFP) {
02169   static char nybChars[16] = "0123456789.ee -";
02170   int b0, b, nyb0, nyb1;
02171   double x;
02172   char buf[65];
02173   int i;
02174 
02175   x = 0;
02176   *isFP = gFalse;
02177   b0 = (*ptr)[0];
02178   if (b0 < 28) {
02179     x = 0;
02180   } else if (b0 == 28) {
02181     x = ((*ptr)[1] << 8) + (*ptr)[2];
02182     *ptr += 3;
02183   } else if (b0 == 29) {
02184     x = ((*ptr)[1] << 24) + ((*ptr)[2] << 16) + ((*ptr)[3] << 8) + (*ptr)[4];
02185     *ptr += 5;
02186   } else if (b0 == 30) {
02187     *ptr += 1;
02188     i = 0;
02189     do {
02190       b = *(*ptr)++;
02191       nyb0 = b >> 4;
02192       nyb1 = b & 0x0f;
02193       if (nyb0 == 0xf) {
02194     break;
02195       }
02196       buf[i++] = nybChars[nyb0];
02197       if (i == 64) {
02198     break;
02199       }
02200       if (nyb0 == 0xc) {
02201     buf[i++] = '-';
02202       }
02203       if (i == 64) {
02204     break;
02205       }
02206       if (nyb1 == 0xf) {
02207     break;
02208       }
02209       buf[i++] = nybChars[nyb1];
02210       if (i == 64) {
02211     break;
02212       }
02213       if (nyb1 == 0xc) {
02214     buf[i++] = '-';
02215       }
02216     } while (i < 64);
02217     buf[i] = '\0';
02218     x = atof(buf);
02219     *isFP = gTrue;
02220   } else if (b0 == 31) {
02221     x = 0;
02222   } else if (b0 < 247) {
02223     x = b0 - 139;
02224     *ptr += 1;
02225   } else if (b0 < 251) {
02226     x = ((b0 - 247) << 8) + (*ptr)[1] + 108;
02227     *ptr += 2;
02228   } else {
02229     x = -((b0 - 251) << 8) - (*ptr)[1] - 108;
02230     *ptr += 2;
02231   }
02232   return x;
02233 }
02234 
02235 char *Type1CFontFile::getString(int sid, char *buf) {
02236   Guchar *idxPtr0, *idxPtr1;
02237   int n;
02238 
02239   if (sid < 391) {
02240     strcpy(buf, type1CStdStrings[sid]);
02241   } else {
02242     sid -= 391;
02243     idxPtr0 = getIndexValPtr(stringIdxPtr, sid);
02244     idxPtr1 = getIndexValPtr(stringIdxPtr, sid + 1);
02245     if ((n = idxPtr1 - idxPtr0) > 255) {
02246       n = 255;
02247     }
02248     strncpy(buf, (char *)idxPtr0, n);
02249     buf[n] = '\0';
02250   }
02251   return buf;
02252 }
02253 
02254 //------------------------------------------------------------------------
02255 // TrueTypeFontFile
02256 //------------------------------------------------------------------------
02257 
02258 //
02259 // Terminology
02260 // -----------
02261 //
02262 // character code = number used as an element of a text string
02263 //
02264 // character name = glyph name = name for a particular glyph within a
02265 //                  font
02266 //
02267 // glyph index = position (within some internal table in the font)
02268 //               where the instructions to draw a particular glyph are
02269 //               stored
02270 //
02271 // Type 1 fonts
02272 // ------------
02273 //
02274 // Type 1 fonts contain:
02275 //
02276 // Encoding: array of glyph names, maps char codes to glyph names
02277 //
02278 //           Encoding[charCode] = charName
02279 //
02280 // CharStrings: dictionary of instructions, keyed by character names,
02281 //              maps character name to glyph data
02282 //
02283 //              CharStrings[charName] = glyphData
02284 //
02285 // TrueType fonts
02286 // --------------
02287 //
02288 // TrueType fonts contain:
02289 //
02290 // 'cmap' table: mapping from character code to glyph index; there may
02291 //               be multiple cmaps in a TrueType font
02292 //
02293 //               cmap[charCode] = glyphIdx
02294 //
02295 // 'post' table: mapping from glyph index to glyph name
02296 //
02297 //               post[glyphIdx] = glyphName
02298 //
02299 // Type 42 fonts
02300 // -------------
02301 //
02302 // Type 42 fonts contain:
02303 //
02304 // Encoding: array of glyph names, maps char codes to glyph names
02305 //
02306 //           Encoding[charCode] = charName
02307 //
02308 // CharStrings: dictionary of glyph indexes, keyed by character names,
02309 //              maps character name to glyph index
02310 //
02311 //              CharStrings[charName] = glyphIdx
02312 //
02313 
02314 struct TTFontTableHdr {
02315   char tag[4];
02316   Guint checksum;
02317   Guint offset;
02318   Guint length;
02319 };
02320 
02321 struct T42Table {
02322   const char *tag;          // 4-byte tag
02323   GBool required;       // required by the TrueType spec?
02324 };
02325 
02326 // TrueType tables to be embedded in Type 42 fonts.
02327 // NB: the table names must be in alphabetical order here.
02328 #define nT42Tables 11
02329 static T42Table t42Tables[nT42Tables] = {
02330   { "cvt ", gTrue  },
02331   { "fpgm", gTrue  },
02332   { "glyf", gTrue  },
02333   { "head", gTrue  },
02334   { "hhea", gTrue  },
02335   { "hmtx", gTrue  },
02336   { "loca", gTrue  },
02337   { "maxp", gTrue  },
02338   { "prep", gTrue  },
02339   { "vhea", gFalse },
02340   { "vmtx", gFalse }
02341 };
02342 #define t42HeadTable 3
02343 #define t42LocaTable 6
02344 #define t42GlyfTable 2
02345 
02346 // Glyph names in some arbitrary standard that Apple uses for their
02347 // TrueType fonts.
02348 static const char *macGlyphNames[258] = {
02349   ".notdef",
02350   "null",
02351   "CR",
02352   "space",
02353   "exclam",
02354   "quotedbl",
02355   "numbersign",
02356   "dollar",
02357   "percent",
02358   "ampersand",
02359   "quotesingle",
02360   "parenleft",
02361   "parenright",
02362   "asterisk",
02363   "plus",
02364   "comma",
02365   "hyphen",
02366   "period",
02367   "slash",
02368   "zero",
02369   "one",
02370   "two",
02371   "three",
02372   "four",
02373   "five",
02374   "six",
02375   "seven",
02376   "eight",
02377   "nine",
02378   "colon",
02379   "semicolon",
02380   "less",
02381   "equal",
02382   "greater",
02383   "question",
02384   "at",
02385   "A",
02386   "B",
02387   "C",
02388   "D",
02389   "E",
02390   "F",
02391   "G",
02392   "H",
02393   "I",
02394   "J",
02395   "K",
02396   "L",
02397   "M",
02398   "N",
02399   "O",
02400   "P",
02401   "Q",
02402   "R",
02403   "S",
02404   "T",
02405   "U",
02406   "V",
02407   "W",
02408   "X",
02409   "Y",
02410   "Z",
02411   "bracketleft",
02412   "backslash",
02413   "bracketright",
02414   "asciicircum",
02415   "underscore",
02416   "grave",
02417   "a",
02418   "b",
02419   "c",
02420   "d",
02421   "e",
02422   "f",
02423   "g",
02424   "h",
02425   "i",
02426   "j",
02427   "k",
02428   "l",
02429   "m",
02430   "n",
02431   "o",
02432   "p",
02433   "q",
02434   "r",
02435   "s",
02436   "t",
02437   "u",
02438   "v",
02439   "w",
02440   "x",
02441   "y",
02442   "z",
02443   "braceleft",
02444   "bar",
02445   "braceright",
02446   "asciitilde",
02447   "Adieresis",
02448   "Aring",
02449   "Ccedilla",
02450   "Eacute",
02451   "Ntilde",
02452   "Odieresis",
02453   "Udieresis",
02454   "aacute",
02455   "agrave",
02456   "acircumflex",
02457   "adieresis",
02458   "atilde",
02459   "aring",
02460   "ccedilla",
02461   "eacute",
02462   "egrave",
02463   "ecircumflex",
02464   "edieresis",
02465   "iacute",
02466   "igrave",
02467   "icircumflex",
02468   "idieresis",
02469   "ntilde",
02470   "oacute",
02471   "ograve",
02472   "ocircumflex",
02473   "odieresis",
02474   "otilde",
02475   "uacute",
02476   "ugrave",
02477   "ucircumflex",
02478   "udieresis",
02479   "dagger",
02480   "degree",
02481   "cent",
02482   "sterling",
02483   "section",
02484   "bullet",
02485   "paragraph",
02486   "germandbls",
02487   "registered",
02488   "copyright",
02489   "trademark",
02490   "acute",
02491   "dieresis",
02492   "notequal",
02493   "AE",
02494   "Oslash",
02495   "infinity",
02496   "plusminus",
02497   "lessequal",
02498   "greaterequal",
02499   "yen",
02500   "mu1",
02501   "partialdiff",
02502   "summation",
02503   "product",
02504   "pi",
02505   "integral",
02506   "ordfeminine",
02507   "ordmasculine",
02508   "Ohm",
02509   "ae",
02510   "oslash",
02511   "questiondown",
02512   "exclamdown",
02513   "logicalnot",
02514   "radical",
02515   "florin",
02516   "approxequal",
02517   "increment",
02518   "guillemotleft",
02519   "guillemotright",
02520   "ellipsis",
02521   "nbspace",
02522   "Agrave",
02523   "Atilde",
02524   "Otilde",
02525   "OE",
02526   "oe",
02527   "endash",
02528   "emdash",
02529   "quotedblleft",
02530   "quotedblright",
02531   "quoteleft",
02532   "quoteright",
02533   "divide",
02534   "lozenge",
02535   "ydieresis",
02536   "Ydieresis",
02537   "fraction",
02538   "currency",
02539   "guilsinglleft",
02540   "guilsinglright",
02541   "fi",
02542   "fl",
02543   "daggerdbl",
02544   "periodcentered",
02545   "quotesinglbase",
02546   "quotedblbase",
02547   "perthousand",
02548   "Acircumflex",
02549   "Ecircumflex",
02550   "Aacute",
02551   "Edieresis",
02552   "Egrave",
02553   "Iacute",
02554   "Icircumflex",
02555   "Idieresis",
02556   "Igrave",
02557   "Oacute",
02558   "Ocircumflex",
02559   "applelogo",
02560   "Ograve",
02561   "Uacute",
02562   "Ucircumflex",
02563   "Ugrave",
02564   "dotlessi",
02565   "circumflex",
02566   "tilde",
02567   "overscore",
02568   "breve",
02569   "dotaccent",
02570   "ring",
02571   "cedilla",
02572   "hungarumlaut",
02573   "ogonek",
02574   "caron",
02575   "Lslash",
02576   "lslash",
02577   "Scaron",
02578   "scaron",
02579   "Zcaron",
02580   "zcaron",
02581   "brokenbar",
02582   "Eth",
02583   "eth",
02584   "Yacute",
02585   "yacute",
02586   "Thorn",
02587   "thorn",
02588   "minus",
02589   "multiply",
02590   "onesuperior",
02591   "twosuperior",
02592   "threesuperior",
02593   "onehalf",
02594   "onequarter",
02595   "threequarters",
02596   "franc",
02597   "Gbreve",
02598   "gbreve",
02599   "Idot",
02600   "Scedilla",
02601   "scedilla",
02602   "Cacute",
02603   "cacute",
02604   "Ccaron",
02605   "ccaron",
02606   "dmacron"
02607 };
02608 
02609 enum T42FontIndexMode {
02610   t42FontModeUnicode,
02611   t42FontModeCharCode,
02612   t42FontModeCharCodeOffset,
02613   t42FontModeMacRoman
02614 };
02615 
02616 TrueTypeFontFile::TrueTypeFontFile(const char *fileA, int lenA) {
02617   int pos, i, idx, n, length;
02618   Guint size, startPos, endPos;
02619 
02620   file = fileA;
02621   len = lenA;
02622 
02623   encoding = NULL;
02624 
02625   // read table directory
02626   nTables = getUShort(4);
02627   tableHdrs = (TTFontTableHdr *)gmalloc(nTables * sizeof(TTFontTableHdr));
02628   pos = 12;
02629   for (i = 0; i < nTables; ++i) {
02630     tableHdrs[i].tag[0] = getByte(pos+0);
02631     tableHdrs[i].tag[1] = getByte(pos+1);
02632     tableHdrs[i].tag[2] = getByte(pos+2);
02633     tableHdrs[i].tag[3] = getByte(pos+3);
02634     tableHdrs[i].checksum = getULong(pos+4);
02635     tableHdrs[i].offset = getULong(pos+8);
02636     tableHdrs[i].length = getULong(pos+12);
02637     pos += 16;
02638   }
02639 
02640   // check for tables that are required by both the TrueType spec
02641   // and the Type 42 spec
02642   if (seekTable("head") < 0 ||
02643       seekTable("hhea") < 0 ||
02644       seekTable("loca") < 0 ||
02645       seekTable("maxp") < 0 ||
02646       seekTable("glyf") < 0 ||
02647       seekTable("hmtx") < 0) {
02648     error(-1, "TrueType font file is missing a required table");
02649     return;
02650   }
02651 
02652   // some embedded TrueType fonts have an incorrect (too small) cmap
02653   // table size
02654   idx = seekTableIdx("cmap");
02655   if (idx >= 0) {
02656     pos = tableHdrs[idx].offset;
02657     n = getUShort(pos + 2);
02658     size = (Guint)(4 + 8 * n);
02659     for (i = 0; i < n; ++i) {
02660       startPos = getULong(pos + 4 + 8*i + 4);
02661       length = getUShort(pos + startPos + 2);
02662       endPos = startPos + length;
02663       if (endPos > size) {
02664     size = endPos;
02665       }
02666     }
02667     if ((mungedCmapSize = size > tableHdrs[idx].length)) {
02668 #if 0 // don't bother printing this error message - it's too common
02669       error(-1, "Bad cmap table size in TrueType font");
02670 #endif
02671       tableHdrs[idx].length = size;
02672     }
02673   } else {
02674     mungedCmapSize = gFalse;
02675   }
02676 
02677   // read the 'head' table
02678   pos = seekTable("head");
02679   bbox[0] = getShort(pos + 36);
02680   bbox[1] = getShort(pos + 38);
02681   bbox[2] = getShort(pos + 40);
02682   bbox[3] = getShort(pos + 42);
02683   locaFmt = getShort(pos + 50);
02684 
02685   // read the 'maxp' table
02686   pos = seekTable("maxp");
02687   nGlyphs = getUShort(pos + 4);
02688 }
02689 
02690 TrueTypeFontFile::~TrueTypeFontFile() {
02691   int i;
02692 
02693   if (encoding) {
02694     for (i = 0; i < 256; ++i) {
02695       gfree(encoding[i]);
02696     }
02697     gfree(encoding);
02698   }
02699   gfree(tableHdrs);
02700 }
02701 
02702 const char *TrueTypeFontFile::getName() {
02703   return NULL;
02704 }
02705 
02706 char **TrueTypeFontFile::getEncoding() {
02707   int cmap[256];
02708   int nCmaps, cmapPlatform, cmapEncoding, cmapFmt;
02709   int cmapLen, cmapOffset, cmapFirst;
02710   int segCnt, segStart, segEnd, segDelta, segOffset;
02711   int pos, i, j, k;
02712   Guint fmt;
02713   GString *s;
02714   int stringIdx, stringPos, n;
02715 
02716   if (encoding) {
02717     return encoding;
02718   }
02719 
02720   //----- construct the (char code) -> (glyph idx) mapping
02721 
02722   // map everything to the missing glyph
02723   for (i = 0; i < 256; ++i) {
02724     cmap[i] = 0;
02725   }
02726 
02727   // look for the 'cmap' table
02728   if ((pos = seekTable("cmap")) >= 0) {
02729     nCmaps = getUShort(pos+2);
02730 
02731     // if the font has a Windows-symbol cmap, use it;
02732     // otherwise, use the first cmap in the table
02733     for (i = 0; i < nCmaps; ++i) {
02734       cmapPlatform = getUShort(pos + 4 + 8*i);
02735       cmapEncoding = getUShort(pos + 4 + 8*i + 2);
02736       if (cmapPlatform == 3 && cmapEncoding == 0) {
02737     break;
02738       }
02739     }
02740     if (i >= nCmaps) {
02741       i = 0;
02742       cmapPlatform = getUShort(pos + 4);
02743       cmapEncoding = getUShort(pos + 4 + 2);
02744     }
02745     pos += getULong(pos + 4 + 8*i + 4);
02746 
02747     // read the cmap
02748     cmapFmt = getUShort(pos);
02749     switch (cmapFmt) {
02750     case 0: // byte encoding table (Apple standard)
02751       cmapLen = getUShort(pos + 2);
02752       for (i = 0; i < cmapLen && i < 256; ++i) {
02753     cmap[i] = getByte(pos + 6 + i);
02754       }
02755       break;
02756     case 4: // segment mapping to delta values (Microsoft standard)
02757       if (cmapPlatform == 3 && cmapEncoding == 0) {
02758     // Windows-symbol uses char codes 0xf000 - 0xf0ff
02759     cmapOffset = 0xf000;
02760       } else {
02761     cmapOffset = 0;
02762       }
02763       segCnt = getUShort(pos + 6) / 2;
02764       for (i = 0; i < segCnt; ++i) {
02765     segEnd = getUShort(pos + 14 + 2*i);
02766     segStart = getUShort(pos + 16 + 2*segCnt + 2*i);
02767     segDelta = getUShort(pos + 16 + 4*segCnt + 2*i);
02768     segOffset = getUShort(pos + 16 + 6*segCnt + 2*i);
02769     if (segStart - cmapOffset <= 0xff &&
02770         segEnd - cmapOffset >= 0) {
02771       for (j = (segStart - cmapOffset >= 0) ? segStart : cmapOffset;
02772            j <= segEnd && j - cmapOffset <= 0xff;
02773            ++j) {
02774         if (segOffset == 0) {
02775           k = (j + segDelta) & 0xffff;
02776         } else {
02777           k = getUShort(pos + 16 + 6*segCnt + 2*i +
02778                 segOffset + 2 * (j - segStart));
02779           if (k != 0) {
02780         k = (k + segDelta) & 0xffff;
02781           }
02782         }
02783         cmap[j - cmapOffset] = k;
02784       }
02785     }
02786       }
02787       break;
02788     case 6: // trimmed table mapping
02789       cmapFirst = getUShort(pos + 6);
02790       cmapLen = getUShort(pos + 8);
02791       for (i = cmapFirst; i < 256 && i < cmapFirst + cmapLen; ++i) {
02792     cmap[i] = getUShort(pos + 10 + 2*i);
02793       }
02794       break;
02795     default:
02796       error(-1, "Unimplemented cmap format (%d) in TrueType font file",
02797         cmapFmt);
02798       break;
02799     }
02800   }
02801 
02802   //----- construct the (glyph idx) -> (glyph name) mapping
02803   //----- and compute the (char code) -> (glyph name) mapping
02804 
02805   encoding = (char **)gmalloc(256 * sizeof(char *));
02806   for (i = 0; i < 256; ++i) {
02807     encoding[i] = NULL;
02808   }
02809 
02810   if ((pos = seekTable("post")) >= 0) {
02811     fmt = getULong(pos);
02812 
02813     // Apple font
02814     if (fmt == 0x00010000) {
02815       for (i = 0; i < 256; ++i) {
02816     j = (cmap[i] < 258) ? cmap[i] : 0;
02817     encoding[i] = copyString(macGlyphNames[j]);
02818       }
02819 
02820     // Microsoft font
02821     } else if (fmt == 0x00020000) {
02822       stringIdx = 0;
02823       stringPos = pos + 34 + 2*nGlyphs;
02824       for (i = 0; i < 256; ++i) {
02825     if (cmap[i] < nGlyphs) {
02826       j = getUShort(pos + 34 + 2 * cmap[i]);
02827       if (j < 258) {
02828         encoding[i] = copyString(macGlyphNames[j]);
02829       } else {
02830         j -= 258;
02831         if (j != stringIdx) {
02832           for (stringIdx = 0, stringPos = pos + 34 + 2*nGlyphs;
02833            stringIdx < j;
02834            ++stringIdx, stringPos += 1 + getByte(stringPos)) ;
02835         }
02836         n = getByte(stringPos);
02837         s = new GString(file + stringPos + 1, n);
02838         encoding[i] = copyString(s->getCString());
02839         delete s;
02840         ++stringIdx;
02841         stringPos += 1 + n;
02842       }
02843     } else {
02844       encoding[i] = copyString(macGlyphNames[0]);
02845     }
02846       }
02847 
02848     // Apple subset
02849     } else if (fmt == 0x000280000) {
02850       for (i = 0; i < 256; ++i) {
02851     if (cmap[i] < nGlyphs) {
02852       j = i + getChar(pos + 32 + cmap[i]);
02853     } else {
02854       j = 0;
02855     }
02856     encoding[i] = copyString(macGlyphNames[j]);
02857       }
02858 
02859     // Ugh, just assume the Apple glyph set
02860     } else {
02861       for (i = 0; i < 256; ++i) {
02862     j = (cmap[i] < 258) ? cmap[i] : 0;
02863     encoding[i] = copyString(macGlyphNames[j]);
02864       }
02865     }
02866 
02867   // no "post" table: assume the Apple glyph set
02868   } else {
02869     for (i = 0; i < 256; ++i) {
02870       j = (cmap[i] < 258) ? cmap[i] : 0;
02871       encoding[i] = copyString(macGlyphNames[j]);
02872     }
02873   }
02874 
02875   return encoding;
02876 }
02877 
02878 void TrueTypeFontFile::convertToType42(const char *name, const char **encodingA,
02879                        CharCodeToUnicode *toUnicode,
02880                        GBool pdfFontHasEncoding,
02881                        FontFileOutputFunc outputFunc,
02882                        void *outputStream) {
02883   char buf[512];
02884 
02885   // write the header
02886   sprintf(buf, "%%!PS-TrueTypeFont-%g\n", getFixed(0));
02887   (*outputFunc)(outputStream, buf, strlen(buf));
02888 
02889   // begin the font dictionary
02890   (*outputFunc)(outputStream, "10 dict begin\n", 14);
02891   (*outputFunc)(outputStream, "/FontName /", 11);
02892   (*outputFunc)(outputStream, name, strlen(name));
02893   (*outputFunc)(outputStream, " def\n", 5);
02894   (*outputFunc)(outputStream, "/FontType 42 def\n", 17);
02895   (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
02896   sprintf(buf, "/FontBBox [%d %d %d %d] def\n",
02897       bbox[0], bbox[1], bbox[2], bbox[3]);
02898   (*outputFunc)(outputStream, buf, strlen(buf));
02899   (*outputFunc)(outputStream, "/PaintType 0 def\n", 17);
02900 
02901   // write the guts of the dictionary
02902   cvtEncoding(encodingA, pdfFontHasEncoding, outputFunc, outputStream);
02903   cvtCharStrings(encodingA, toUnicode, pdfFontHasEncoding,
02904          outputFunc, outputStream);
02905   cvtSfnts(outputFunc, outputStream, NULL);
02906 
02907   // end the dictionary and define the font
02908   (*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40);
02909 }
02910 
02911 void TrueTypeFontFile::convertToCIDType2(const char *name, const Gushort *cidMap,
02912                      int nCIDs,
02913                      FontFileOutputFunc outputFunc,
02914                      void *outputStream) {
02915   char buf[512];
02916   Gushort cid;
02917   int i, j, k;
02918 
02919   // write the header
02920   sprintf(buf, "%%!PS-TrueTypeFont-%g\n", getFixed(0));
02921   (*outputFunc)(outputStream, buf, strlen(buf));
02922 
02923   // begin the font dictionary
02924   (*outputFunc)(outputStream, "20 dict begin\n", 14);
02925   (*outputFunc)(outputStream, "/CIDFontName /", 14);
02926   (*outputFunc)(outputStream, name, strlen(name));
02927   (*outputFunc)(outputStream, " def\n", 5);
02928   (*outputFunc)(outputStream, "/CIDFontType 2 def\n", 19);
02929   (*outputFunc)(outputStream, "/FontType 42 def\n", 17);
02930   (*outputFunc)(outputStream, "/CIDSystemInfo 3 dict dup begin\n", 32);
02931   (*outputFunc)(outputStream, "  /Registry (Adobe) def\n", 24);
02932   (*outputFunc)(outputStream, "  /Ordering (Identity) def\n", 27);
02933   (*outputFunc)(outputStream, "  /Supplement 0 def\n", 20);
02934   (*outputFunc)(outputStream, "  end def\n", 10);
02935   (*outputFunc)(outputStream, "/GDBytes 2 def\n", 15);
02936   if (cidMap) {
02937     sprintf(buf, "/CIDCount %d def\n", nCIDs);
02938     (*outputFunc)(outputStream, buf, strlen(buf));
02939     if (nCIDs > 32767) {
02940       (*outputFunc)(outputStream, "/CIDMap [", 9);
02941       for (i = 0; i < nCIDs; i += 32768 - 16) {
02942     (*outputFunc)(outputStream, "<\n", 2);
02943     for (j = 0; j < 32768 - 16 && i+j < nCIDs; j += 16) {
02944       (*outputFunc)(outputStream, "  ", 2);
02945       for (k = 0; k < 16 && i+j+k < nCIDs; ++k) {
02946         cid = cidMap[i+j+k];
02947         sprintf(buf, "%02x%02x", (cid >> 8) & 0xff, cid & 0xff);
02948         (*outputFunc)(outputStream, buf, strlen(buf));
02949       }
02950       (*outputFunc)(outputStream, "\n", 1);
02951     }
02952     (*outputFunc)(outputStream, "  >", 3);
02953       }
02954       (*outputFunc)(outputStream, "\n", 1);
02955       (*outputFunc)(outputStream, "] def\n", 6);
02956     } else {
02957       (*outputFunc)(outputStream, "/CIDMap <\n", 10);
02958       for (i = 0; i < nCIDs; i += 16) {
02959     (*outputFunc)(outputStream, "  ", 2);
02960     for (j = 0; j < 16 && i+j < nCIDs; ++j) {
02961       cid = cidMap[i+j];
02962       sprintf(buf, "%02x%02x", (cid >> 8) & 0xff, cid & 0xff);
02963       (*outputFunc)(outputStream, buf, strlen(buf));
02964     }
02965     (*outputFunc)(outputStream, "\n", 1);
02966       }
02967       (*outputFunc)(outputStream, "> def\n", 6);
02968     }
02969   } else {
02970     // direct mapping - just fill the string(s) with s[i]=i
02971     sprintf(buf, "/CIDCount %d def\n", nGlyphs);
02972     (*outputFunc)(outputStream, buf, strlen(buf));
02973     if (nGlyphs > 32767) {
02974       (*outputFunc)(outputStream, "/CIDMap [\n", 10);
02975       for (i = 0; i < nGlyphs; i += 32767) {
02976     j = nGlyphs - i < 32767 ? nGlyphs - i : 32767;
02977     sprintf(buf, "  %d string 0 1 %d {\n", 2 * j, j - 1);
02978     (*outputFunc)(outputStream, buf, strlen(buf));
02979     sprintf(buf, "    2 copy dup 2 mul exch %d add -8 bitshift put\n", i);
02980     (*outputFunc)(outputStream, buf, strlen(buf));
02981     sprintf(buf, "    1 index exch dup 2 mul 1 add exch %d add"
02982         " 255 and put\n", i);
02983     (*outputFunc)(outputStream, buf, strlen(buf));
02984     (*outputFunc)(outputStream, "  } for\n", 8);
02985       }
02986       (*outputFunc)(outputStream, "] def\n", 6);
02987     } else {
02988       sprintf(buf, "/CIDMap %d string\n", 2 * nGlyphs);
02989       (*outputFunc)(outputStream, buf, strlen(buf));
02990       sprintf(buf, "  0 1 %d {\n", nGlyphs - 1);
02991       (*outputFunc)(outputStream, buf, strlen(buf));
02992       (*outputFunc)(outputStream,
02993             "    2 copy dup 2 mul exch -8 bitshift put\n", 42);
02994       (*outputFunc)(outputStream,
02995             "    1 index exch dup 2 mul 1 add exch 255 and put\n", 50);
02996       (*outputFunc)(outputStream, "  } for\n", 8);
02997       (*outputFunc)(outputStream, "def\n", 4);
02998     }
02999   }
03000   (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
03001   sprintf(buf, "/FontBBox [%d %d %d %d] def\n",
03002       bbox[0], bbox[1], bbox[2], bbox[3]);
03003   (*outputFunc)(outputStream, buf, strlen(buf));
03004   (*outputFunc)(outputStream, "/PaintType 0 def\n", 17);
03005   (*outputFunc)(outputStream, "/Encoding [] readonly def\n", 26);
03006   (*outputFunc)(outputStream, "/CharStrings 1 dict dup begin\n", 30);
03007   (*outputFunc)(outputStream, "  /.notdef 0 def\n", 17);
03008   (*outputFunc)(outputStream, "  end readonly def\n", 19);
03009 
03010   // write the guts of the dictionary
03011   cvtSfnts(outputFunc, outputStream, NULL);
03012 
03013   // end the dictionary and define the font
03014   (*outputFunc)(outputStream,
03015         "CIDFontName currentdict end /CIDFont defineresource pop\n",
03016         56);
03017 }
03018 
03019 void TrueTypeFontFile::convertToType0(const char *name, const Gushort *cidMap,
03020                       int nCIDs,
03021                       FontFileOutputFunc outputFunc,
03022                       void *outputStream) {
03023   char buf[512];
03024   GString *sfntsName;
03025   int n, i, j;
03026 
03027   // write the Type 42 sfnts array
03028   sfntsName = (new GString(name))->append("_sfnts");
03029   cvtSfnts(outputFunc, outputStream, sfntsName);
03030   delete sfntsName;
03031 
03032   // write the descendant Type 42 fonts
03033   n = cidMap ? nCIDs : nGlyphs;
03034   for (i = 0; i < n; i += 256) {
03035     (*outputFunc)(outputStream, "10 dict begin\n", 14);
03036     (*outputFunc)(outputStream, "/FontName /", 11);
03037     (*outputFunc)(outputStream, name, strlen(name));
03038     sprintf(buf, "_%02x def\n", i >> 8);
03039     (*outputFunc)(outputStream, buf, strlen(buf));
03040     (*outputFunc)(outputStream, "/FontType 42 def\n", 17);
03041     (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
03042     sprintf(buf, "/FontBBox [%d %d %d %d] def\n",
03043         bbox[0], bbox[1], bbox[2], bbox[3]);
03044     (*outputFunc)(outputStream, buf, strlen(buf));
03045     (*outputFunc)(outputStream, "/PaintType 0 def\n", 17);
03046     (*outputFunc)(outputStream, "/sfnts ", 7);
03047     (*outputFunc)(outputStream, name, strlen(name));
03048     (*outputFunc)(outputStream, "_sfnts def\n", 11);
03049     (*outputFunc)(outputStream, "/Encoding 256 array\n", 20);
03050     for (j = 0; j < 256 && i+j < n; ++j) {
03051       sprintf(buf, "dup %d /c%02x put\n", j, j);
03052       (*outputFunc)(outputStream, buf, strlen(buf));
03053     }
03054     (*outputFunc)(outputStream, "readonly def\n", 13);
03055     (*outputFunc)(outputStream, "/CharStrings 257 dict dup begin\n", 32);
03056     (*outputFunc)(outputStream, "/.notdef 0 def\n", 15);
03057     for (j = 0; j < 256 && i+j < n; ++j) {
03058       sprintf(buf, "/c%02x %d def\n", j, cidMap ? cidMap[i+j] : i+j);
03059       (*outputFunc)(outputStream, buf, strlen(buf));
03060     }
03061     (*outputFunc)(outputStream, "end readonly def\n", 17);
03062     (*outputFunc)(outputStream,
03063           "FontName currentdict end definefont pop\n", 40);
03064   }
03065 
03066   // write the Type 0 parent font
03067   (*outputFunc)(outputStream, "16 dict begin\n", 14);
03068   (*outputFunc)(outputStream, "/FontName /", 11);
03069   (*outputFunc)(outputStream, name, strlen(name));
03070   (*outputFunc)(outputStream, " def\n", 5);
03071   (*outputFunc)(outputStream, "/FontType 0 def\n", 16);
03072   (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
03073   (*outputFunc)(outputStream, "/FMapType 2 def\n", 16);
03074   (*outputFunc)(outputStream, "/Encoding [\n", 12);
03075   for (i = 0; i < n; i += 256) {
03076     sprintf(buf, "%d\n", i >> 8);
03077     (*outputFunc)(outputStream, buf, strlen(buf));
03078   }
03079   (*outputFunc)(outputStream, "] def\n", 6);
03080   (*outputFunc)(outputStream, "/FDepVector [\n", 14);
03081   for (i = 0; i < n; i += 256) {
03082     (*outputFunc)(outputStream, "/", 1);
03083     (*outputFunc)(outputStream, name, strlen(name));
03084     sprintf(buf, "_%02x findfont\n", i >> 8);
03085     (*outputFunc)(outputStream, buf, strlen(buf));
03086   }
03087   (*outputFunc)(outputStream, "] def\n", 6);
03088   (*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40);
03089 }
03090 
03091 int TrueTypeFontFile::getByte(int pos) {
03092   if (pos < 0 || pos >= len) {
03093     return 0;
03094   }
03095   return file[pos] & 0xff;
03096 }
03097 
03098 int TrueTypeFontFile::getChar(int pos) {
03099   int x;
03100 
03101   if (pos < 0 || pos >= len) {
03102     return 0;
03103   }
03104   x = file[pos] & 0xff;
03105   if (x & 0x80)
03106     x |= 0xffffff00;
03107   return x;
03108 }
03109 
03110 int TrueTypeFontFile::getUShort(int pos) {
03111   int x;
03112 
03113   if (pos < 0 || pos+1 >= len) {
03114     return 0;
03115   }
03116   x = file[pos] & 0xff;
03117   x = (x << 8) + (file[pos+1] & 0xff);
03118   return x;
03119 }
03120 
03121 int TrueTypeFontFile::getShort(int pos) {
03122   int x;
03123 
03124   if (pos < 0 || pos+1 >= len) {
03125     return 0;
03126   }
03127   x = file[pos] & 0xff;
03128   x = (x << 8) + (file[pos+1] & 0xff);
03129   if (x & 0x8000)
03130     x |= 0xffff0000;
03131   return x;
03132 }
03133 
03134 Guint TrueTypeFontFile::getULong(int pos) {
03135   int x;
03136 
03137   if (pos < 0 || pos+3 >= len) {
03138     return 0;
03139   }
03140   x = file[pos] & 0xff;
03141   x = (x << 8) + (file[pos+1] & 0xff);
03142   x = (x << 8) + (file[pos+2] & 0xff);
03143   x = (x << 8) + (file[pos+3] & 0xff);
03144   return x;
03145 }
03146 
03147 double TrueTypeFontFile::getFixed(int pos) {
03148   int x, y;
03149 
03150   x = getShort(pos);
03151   y = getUShort(pos+2);
03152   return (double)x + (double)y / 65536;
03153 }
03154 
03155 int TrueTypeFontFile::seekTable(const char *tag) {
03156   int i;
03157 
03158   for (i = 0; i < nTables; ++i) {
03159     if (!strncmp(tableHdrs[i].tag, tag, 4)) {
03160       return tableHdrs[i].offset;
03161     }
03162   }
03163   return -1;
03164 }
03165 
03166 int TrueTypeFontFile::seekTableIdx(const char *tag) {
03167   int i;
03168 
03169   for (i = 0; i < nTables; ++i) {
03170     if (!strncmp(tableHdrs[i].tag, tag, 4)) {
03171       return i;
03172     }
03173   }
03174   return -1;
03175 }
03176 
03177 void TrueTypeFontFile::cvtEncoding(const char **encodingA, GBool pdfFontHasEncoding,
03178                    FontFileOutputFunc outputFunc,
03179                    void *outputStream) {
03180   const char *name;
03181   char buf[64];
03182   int i;
03183 
03184   (*outputFunc)(outputStream, "/Encoding 256 array\n", 20);
03185   if (pdfFontHasEncoding) {
03186     for (i = 0; i < 256; ++i) {
03187       if (!(name = encodingA[i])) {
03188     name = ".notdef";
03189       }
03190       sprintf(buf, "dup %d /", i);
03191       (*outputFunc)(outputStream, buf, strlen(buf));
03192       (*outputFunc)(outputStream, name, strlen(name));
03193       (*outputFunc)(outputStream, " put\n", 5);
03194     }
03195   } else {
03196     for (i = 0; i < 256; ++i) {
03197       sprintf(buf, "dup %d /c%02x put\n", i, i);
03198       (*outputFunc)(outputStream, buf, strlen(buf));
03199     }
03200   }
03201   (*outputFunc)(outputStream, "readonly def\n", 13);
03202 }
03203 
03204 void TrueTypeFontFile::cvtCharStrings(const char **encodingA,
03205                       CharCodeToUnicode *toUnicode,
03206                       GBool pdfFontHasEncoding,
03207                       FontFileOutputFunc outputFunc,
03208                       void *outputStream) {
03209   int unicodeCmap, macRomanCmap, msSymbolCmap;
03210   int nCmaps, cmapPlatform, cmapEncoding, cmapFmt, cmapOffset;
03211   T42FontIndexMode mode;
03212   const char *name;
03213   char buf[64], buf2[16];
03214   Unicode u;
03215   int pos, i, j, k;
03216 
03217   // always define '.notdef'
03218   (*outputFunc)(outputStream, "/CharStrings 256 dict dup begin\n", 32);
03219   (*outputFunc)(outputStream, "/.notdef 0 def\n", 15);
03220 
03221   // if there's no 'cmap' table, punt
03222   if ((pos = seekTable("cmap")) < 0) {
03223     goto err;
03224   }
03225 
03226   // To match up with the Adobe-defined behaviour, we choose a cmap
03227   // like this:
03228   // 1. If the PDF font has an encoding:
03229   //    1a. If the TrueType font has a Microsoft Unicode cmap, use it,
03230   //        and use the Unicode indexes, not the char codes.
03231   //    1b. If the TrueType font has a Macintosh Roman cmap, use it,
03232   //        and reverse map the char names through MacRomanEncoding to
03233   //        get char codes.
03234   // 2. If the PDF font does not have an encoding:
03235   //    2a. If the TrueType font has a Macintosh Roman cmap, use it,
03236   //        and use char codes directly.
03237   //    2b. If the TrueType font has a Microsoft Symbol cmap, use it,
03238   //        and use (0xf000 + char code).
03239   // 3. If none of these rules apply, use the first cmap and hope for
03240   //    the best (this shouldn't happen).
03241   nCmaps = getUShort(pos+2);
03242   unicodeCmap = macRomanCmap = msSymbolCmap = -1;
03243   cmapOffset = 0;
03244   for (i = 0; i < nCmaps; ++i) {
03245     cmapPlatform = getUShort(pos + 4 + 8*i);
03246     cmapEncoding = getUShort(pos + 4 + 8*i + 2);
03247     if (cmapPlatform == 3 && cmapEncoding == 1) {
03248       unicodeCmap = i;
03249     } else if (cmapPlatform == 1 && cmapEncoding == 0) {
03250       macRomanCmap = i;
03251     } else if (cmapPlatform == 3 && cmapEncoding == 0) {
03252       msSymbolCmap = i;
03253     }
03254   }
03255   i = 0;
03256   mode = t42FontModeCharCode;
03257   if (pdfFontHasEncoding) {
03258     if (unicodeCmap >= 0) {
03259       i = unicodeCmap;
03260       mode = t42FontModeUnicode;
03261     } else if (macRomanCmap >= 0) {
03262       i = macRomanCmap;
03263       mode = t42FontModeMacRoman;
03264     }
03265   } else {
03266     if (macRomanCmap >= 0) {
03267       i = macRomanCmap;
03268       mode = t42FontModeCharCode;
03269     } else if (msSymbolCmap >= 0) {
03270       i = msSymbolCmap;
03271       mode = t42FontModeCharCodeOffset;
03272       cmapOffset = 0xf000;
03273     }
03274   }
03275   cmapPlatform = getUShort(pos + 4 + 8*i);
03276   cmapEncoding = getUShort(pos + 4 + 8*i + 2);
03277   pos += getULong(pos + 4 + 8*i + 4);
03278   cmapFmt = getUShort(pos);
03279   if (cmapFmt != 0 && cmapFmt != 4 && cmapFmt != 6) {
03280     error(-1, "Unimplemented cmap format (%d) in TrueType font file",
03281       cmapFmt);
03282     goto err;
03283   }
03284 
03285   // map char name to glyph index:
03286   // 1. use encoding to map name to char code
03287   // 2. use cmap to map char code to glyph index
03288   j = 0; // make gcc happy
03289   for (i = 0; i < 256; ++i) {
03290     if (pdfFontHasEncoding) {
03291       name = encodingA[i];
03292     } else {
03293       sprintf(buf2, "c%02x", i);
03294       name = buf2;
03295     }
03296     if (name && strcmp(name, ".notdef")) {
03297       switch (mode) {
03298       case t42FontModeUnicode:
03299     toUnicode->mapToUnicode((CharCode)i, &u, 1);
03300     j = (int)u;
03301     break;
03302       case t42FontModeCharCode:
03303     j = i;
03304     break;
03305       case t42FontModeCharCodeOffset:
03306     j = cmapOffset + i;
03307     break;
03308       case t42FontModeMacRoman:
03309     j = globalParams->getMacRomanCharCode(name);
03310     break;
03311       }
03312       // note: Distiller (maybe Adobe's PS interpreter in general)
03313       // doesn't like TrueType fonts that have CharStrings entries
03314       // which point to nonexistent glyphs, hence the (k < nGlyphs)
03315       // test
03316       if ((k = getCmapEntry(cmapFmt, pos, j)) > 0 &&
03317       k < nGlyphs) {
03318     (*outputFunc)(outputStream, "/", 1);
03319     (*outputFunc)(outputStream, name, strlen(name));
03320     sprintf(buf, " %d def\n", k);
03321     (*outputFunc)(outputStream, buf, strlen(buf));
03322       }
03323     }
03324   }
03325 
03326  err:
03327   (*outputFunc)(outputStream, "end readonly def\n", 17);
03328 }
03329 
03330 int TrueTypeFontFile::getCmapEntry(int cmapFmt, int pos, int code) {
03331   int cmapLen, cmapFirst;
03332   int segCnt, segEnd, segStart, segDelta, segOffset;
03333   int a, b, m, i;
03334 
03335   switch (cmapFmt) {
03336   case 0: // byte encoding table (Apple standard)
03337     cmapLen = getUShort(pos + 2);
03338     if (code >= cmapLen) {
03339       return 0;
03340     }
03341     return getByte(pos + 6 + code);
03342 
03343   case 4: // segment mapping to delta values (Microsoft standard)
03344     segCnt = getUShort(pos + 6) / 2;
03345     a = -1;
03346     b = segCnt - 1;
03347     segEnd = getUShort(pos + 14 + 2*b);
03348     if (code > segEnd) {
03349       // malformed font -- the TrueType spec requires the last segEnd
03350       // to be 0xffff
03351       return 0;
03352     }
03353     // invariant: seg[a].end < code <= seg[b].end
03354     while (b - a > 1) {
03355       m = (a + b) / 2;
03356       segEnd = getUShort(pos + 14 + 2*m);
03357       if (segEnd < code) {
03358     a = m;
03359       } else {
03360     b = m;
03361       }
03362     }
03363     segStart = getUShort(pos + 16 + 2*segCnt + 2*b);
03364     segDelta = getUShort(pos + 16 + 4*segCnt + 2*b);
03365     segOffset = getUShort(pos + 16 + 6*segCnt + 2*b);
03366     if (segOffset == 0) {
03367       i = (code + segDelta) & 0xffff;
03368     } else {
03369       i = getUShort(pos + 16 + 6*segCnt + 2*b +
03370             segOffset + 2 * (code - segStart));
03371       if (i != 0) {
03372     i = (i + segDelta) & 0xffff;
03373       }
03374     }
03375     return i;
03376 
03377   case 6: // trimmed table mapping
03378     cmapFirst = getUShort(pos + 6);
03379     cmapLen = getUShort(pos + 8);
03380     if (code < cmapFirst || code >= cmapFirst + cmapLen) {
03381       return 0;
03382     }
03383     return getUShort(pos + 10 + 2*(code - cmapFirst));
03384 
03385   default:
03386     // shouldn't happen - this is checked earlier
03387     break;
03388   }
03389   return 0;
03390 }
03391 
03392 void TrueTypeFontFile::cvtSfnts(FontFileOutputFunc outputFunc,
03393                 void *outputStream, GString *name) {
03394   TTFontTableHdr newTableHdrs[nT42Tables];
03395   char tableDir[12 + nT42Tables*16];
03396   char headTable[54];
03397   int *origLocaTable;
03398   char *locaTable;
03399   int nNewTables;
03400   Guint checksum;
03401   int pos, glyfPos, length, glyphLength, pad;
03402   int i, j, k;
03403 
03404   // construct the 'head' table, zero out the font checksum
03405   memcpy(headTable, file + seekTable("head"), 54);
03406   headTable[8] = headTable[9] = headTable[10] = headTable[11] = (char)0;
03407 
03408   // read the original 'loca' table and construct the new one
03409   // (pad each glyph out to a multiple of 4 bytes)
03410   origLocaTable = (int *)gmalloc((nGlyphs + 1) * sizeof(int));
03411   pos = seekTable("loca");
03412   for (i = 0; i <= nGlyphs; ++i) {
03413     if (locaFmt) {
03414       origLocaTable[i] = getULong(pos + 4*i);
03415     } else {
03416       origLocaTable[i] = 2 * getUShort(pos + 2*i);
03417     }
03418   }
03419   locaTable = (char *)gmalloc((nGlyphs + 1) * (locaFmt ? 4 : 2));
03420   if (locaFmt) {
03421     locaTable[0] = locaTable[1] = locaTable[2] = locaTable[3] = 0;
03422   } else {
03423     locaTable[0] = locaTable[1] = 0;
03424   }
03425   pos = 0;
03426   for (i = 1; i <= nGlyphs; ++i) {
03427     length = origLocaTable[i] - origLocaTable[i-1];
03428     if (length & 3) {
03429       length += 4 - (length & 3);
03430     }
03431     pos += length;
03432     if (locaFmt) {
03433       locaTable[4*i  ] = (char)(pos >> 24);
03434       locaTable[4*i+1] = (char)(pos >> 16);
03435       locaTable[4*i+2] = (char)(pos >>  8);
03436       locaTable[4*i+3] = (char) pos;
03437     } else {
03438       locaTable[2*i  ] = (char)(pos >> 9);
03439       locaTable[2*i+1] = (char)(pos >> 1);
03440     }
03441   }
03442 
03443   // count the number of tables
03444   nNewTables = 0;
03445   for (i = 0; i < nT42Tables; ++i) {
03446     if (t42Tables[i].required ||
03447     seekTable(t42Tables[i].tag) >= 0) {
03448       ++nNewTables;
03449     }
03450   }
03451 
03452   // construct the new table headers, including table checksums
03453   // (pad each table out to a multiple of 4 bytes)
03454   pos = 12 + nNewTables*16;
03455   k = 0;
03456   for (i = 0; i < nT42Tables; ++i) {
03457     length = -1;
03458     checksum = 0; // make gcc happy
03459     if (i == t42HeadTable) {
03460       length = 54;
03461       checksum = computeTableChecksum(headTable, 54);
03462     } else if (i == t42LocaTable) {
03463       length = (nGlyphs + 1) * (locaFmt ? 4 : 2);
03464       checksum = computeTableChecksum(locaTable, length);
03465     } else if (i == t42GlyfTable) {
03466       length = 0;
03467       checksum = 0;
03468       glyfPos = seekTable("glyf");
03469       for (j = 0; j < nGlyphs; ++j) {
03470     glyphLength = origLocaTable[j+1] - origLocaTable[j];
03471     pad = (glyphLength & 3) ? 4 - (glyphLength & 3) : 0;
03472     length += glyphLength + pad;
03473     checksum += computeTableChecksum(file + glyfPos + origLocaTable[j],
03474                      glyphLength);
03475       }
03476     } else {
03477       if ((j = seekTableIdx(t42Tables[i].tag)) >= 0) {
03478     length = tableHdrs[j].length;
03479     checksum = computeTableChecksum(file + tableHdrs[j].offset, length);
03480       } else if (t42Tables[i].required) {
03481     error(-1, "Embedded TrueType font is missing a required table ('%s')",
03482           t42Tables[i].tag);
03483     length = 0;
03484     checksum = 0;
03485       }
03486     }
03487     if (length >= 0) {
03488       strncpy(newTableHdrs[k].tag, t42Tables[i].tag, 4);
03489       newTableHdrs[k].checksum = checksum;
03490       newTableHdrs[k].offset = pos;
03491       newTableHdrs[k].length = length;
03492       pad = (length & 3) ? 4 - (length & 3) : 0;
03493       pos += length + pad;
03494       ++k;
03495     }
03496   }
03497 
03498   // construct the table directory
03499   tableDir[0] = 0x00;       // sfnt version
03500   tableDir[1] = 0x01;
03501   tableDir[2] = 0x00;
03502   tableDir[3] = 0x00;
03503   tableDir[4] = 0;      // numTables
03504   tableDir[5] = nNewTables;
03505   tableDir[6] = 0;      // searchRange
03506   tableDir[7] = (char)128;
03507   tableDir[8] = 0;      // entrySelector
03508   tableDir[9] = 3;
03509   tableDir[10] = 0;     // rangeShift
03510   tableDir[11] = (char)(16 * nNewTables - 128);
03511   pos = 12;
03512   for (i = 0; i < nNewTables; ++i) {
03513     tableDir[pos   ] = newTableHdrs[i].tag[0];
03514     tableDir[pos+ 1] = newTableHdrs[i].tag[1];
03515     tableDir[pos+ 2] = newTableHdrs[i].tag[2];
03516     tableDir[pos+ 3] = newTableHdrs[i].tag[3];
03517     tableDir[pos+ 4] = (char)(newTableHdrs[i].checksum >> 24);
03518     tableDir[pos+ 5] = (char)(newTableHdrs[i].checksum >> 16);
03519     tableDir[pos+ 6] = (char)(newTableHdrs[i].checksum >>  8);
03520     tableDir[pos+ 7] = (char) newTableHdrs[i].checksum;
03521     tableDir[pos+ 8] = (char)(newTableHdrs[i].offset >> 24);
03522     tableDir[pos+ 9] = (char)(newTableHdrs[i].offset >> 16);
03523     tableDir[pos+10] = (char)(newTableHdrs[i].offset >>  8);
03524     tableDir[pos+11] = (char) newTableHdrs[i].offset;
03525     tableDir[pos+12] = (char)(newTableHdrs[i].length >> 24);
03526     tableDir[pos+13] = (char)(newTableHdrs[i].length >> 16);
03527     tableDir[pos+14] = (char)(newTableHdrs[i].length >>  8);
03528     tableDir[pos+15] = (char) newTableHdrs[i].length;
03529     pos += 16;
03530   }
03531 
03532   // compute the font checksum and store it in the head table
03533   checksum = computeTableChecksum(tableDir, 12 + nNewTables*16);
03534   for (i = 0; i < nNewTables; ++i) {
03535     checksum += newTableHdrs[i].checksum;
03536   }
03537   checksum = 0xb1b0afba - checksum; // because the TrueType spec says so
03538   headTable[ 8] = (char)(checksum >> 24);
03539   headTable[ 9] = (char)(checksum >> 16);
03540   headTable[10] = (char)(checksum >>  8);
03541   headTable[11] = (char) checksum;
03542 
03543   // start the sfnts array
03544   if (name) {
03545     (*outputFunc)(outputStream, "/", 1);
03546     (*outputFunc)(outputStream, name->getCString(), name->getLength());
03547     (*outputFunc)(outputStream, " [\n", 3);
03548   } else {
03549     (*outputFunc)(outputStream, "/sfnts [\n", 9);
03550   }
03551 
03552   // write the table directory
03553   dumpString(tableDir, 12 + nNewTables*16, outputFunc, outputStream);
03554 
03555   // write the tables
03556   for (i = 0; i < nNewTables; ++i) {
03557     if (i == t42HeadTable) {
03558       dumpString(headTable, 54, outputFunc, outputStream);
03559     } else if (i == t42LocaTable) {
03560       length = (nGlyphs + 1) * (locaFmt ? 4 : 2);
03561       dumpString(locaTable, length, outputFunc, outputStream);
03562     } else if (i == t42GlyfTable) {
03563       glyfPos = seekTable("glyf");
03564       for (j = 0; j < nGlyphs; ++j) {
03565     length = origLocaTable[j+1] - origLocaTable[j];
03566     if (length > 0) {
03567       dumpString(file + glyfPos + origLocaTable[j], length,
03568              outputFunc, outputStream);
03569     }
03570       }
03571     } else {
03572       // length == 0 means the table is missing and the error was
03573       // already reported during the construction of the table
03574       // headers
03575       if ((length = newTableHdrs[i].length) > 0) {
03576     dumpString(file + seekTable(t42Tables[i].tag), length,
03577            outputFunc, outputStream);
03578       }
03579     }
03580   }
03581 
03582   // end the sfnts array
03583   (*outputFunc)(outputStream, "] def\n", 6);
03584 
03585   gfree(origLocaTable);
03586   gfree(locaTable);
03587 }
03588 
03589 void TrueTypeFontFile::dumpString(const char *s, int length,
03590                   FontFileOutputFunc outputFunc,
03591                   void *outputStream) {
03592   char buf[64];
03593   int pad, i, j;
03594 
03595   (*outputFunc)(outputStream, "<", 1);
03596   for (i = 0; i < length; i += 32) {
03597     for (j = 0; j < 32 && i+j < length; ++j) {
03598       sprintf(buf, "%02X", s[i+j] & 0xff);
03599       (*outputFunc)(outputStream, buf, strlen(buf));
03600     }
03601     if (i % (65536 - 32) == 65536 - 64) {
03602       (*outputFunc)(outputStream, ">\n<", 3);
03603     } else if (i+32 < length) {
03604       (*outputFunc)(outputStream, "\n", 1);
03605     }
03606   }
03607   if (length & 3) {
03608     pad = 4 - (length & 3);
03609     for (i = 0; i < pad; ++i) {
03610       (*outputFunc)(outputStream, "00", 2);
03611     }
03612   }
03613   // add an extra zero byte because the Adobe Type 42 spec says so
03614   (*outputFunc)(outputStream, "00>\n", 4);
03615 }
03616 
03617 Guint TrueTypeFontFile::computeTableChecksum(const char *data, int length) {
03618   Guint checksum, word;
03619   int i;
03620 
03621   checksum = 0;
03622   for (i = 0; i+3 < length; i += 4) {
03623     word = ((data[i  ] & 0xff) << 24) +
03624            ((data[i+1] & 0xff) << 16) +
03625            ((data[i+2] & 0xff) <<  8) +
03626             (data[i+3] & 0xff);
03627     checksum += word;
03628   }
03629   if (length & 3) {
03630     word = 0;
03631     i = length & ~3;
03632     switch (length & 3) {
03633     case 3:
03634       word |= (data[i+2] & 0xff) <<  8;
03635     case 2:
03636       word |= (data[i+1] & 0xff) << 16;
03637     case 1:
03638       word |= (data[i  ] & 0xff) << 24;
03639       break;
03640     }
03641     checksum += word;
03642   }
03643   return checksum;
03644 }
03645 
03646 void TrueTypeFontFile::writeTTF(FILE *out) {
03647   static char cmapTab[20] = {
03648     0, 0,           // table version number
03649     0, 1,           // number of encoding tables
03650     0, 1,           // platform ID
03651     0, 0,           // encoding ID
03652     0, 0, 0, 12,        // offset of subtable
03653     0, 0,           // subtable format
03654     0, 1,           // subtable length
03655     0, 1,           // subtable version
03656     0,              // map char 0 -> glyph 0
03657     0               // pad to multiple of four bytes
03658   };
03659   static char nameTab[8] = {
03660     0, 0,           // format
03661     0, 0,           // number of name records
03662     0, 6,           // offset to start of string storage
03663     0, 0            // pad to multiple of four bytes
03664   };
03665   static char postTab[32] = {
03666     0, 1, 0, 0,         // format
03667     0, 0, 0, 0,         // italic angle
03668     0, 0,           // underline position
03669     0, 0,           // underline thickness
03670     0, 0, 0, 0,         // fixed pitch
03671     0, 0, 0, 0,         // min Type 42 memory
03672     0, 0, 0, 0,         // max Type 42 memory
03673     0, 0, 0, 0,         // min Type 1 memory
03674     0, 0, 0, 0          // max Type 1 memory
03675   };
03676   GBool haveCmap, haveName, havePost;
03677   GBool dirCmap, dirName, dirPost;
03678   int nNewTables, nAllTables, pad;
03679   char *tableDir;
03680   Guint t, pos;
03681   int i, j;
03682 
03683   // check for missing tables
03684   haveCmap = seekTable("cmap") >= 0;
03685   haveName = seekTable("name") >= 0;
03686   havePost = seekTable("post") >= 0;
03687   nNewTables = (haveCmap ? 0 : 1) + (haveName ? 0 : 1) + (havePost ? 0 : 1);
03688   if (!nNewTables && !mungedCmapSize) {
03689     // none are missing - write the TTF file as is
03690     fwrite(file, 1, len, out);
03691     return;
03692   }
03693 
03694   // construct the new table directory
03695   nAllTables = nTables + nNewTables;
03696   tableDir = (char *)gmalloc(12 + nAllTables * 16);
03697   memcpy(tableDir, file, 12 + nTables * 16);
03698   tableDir[4] = (char)((nAllTables >> 8) & 0xff);
03699   tableDir[5] = (char)(nAllTables & 0xff);
03700   for (i = -1, t = (Guint)nAllTables; t; ++i, t >>= 1) ;
03701   t = 1 << (4 + i);
03702   tableDir[6] = (char)((t >> 8) & 0xff);
03703   tableDir[7] = (char)(t & 0xff);
03704   tableDir[8] = (char)((i >> 8) & 0xff);
03705   tableDir[9] = (char)(i & 0xff);
03706   t = nAllTables * 16 - t;
03707   tableDir[10] = (char)((t >> 8) & 0xff);
03708   tableDir[11] = (char)(t & 0xff);
03709   dirCmap = haveCmap;
03710   dirName = haveName;
03711   dirPost = havePost;
03712   j = 0;
03713   pad = (len & 3) ? 4 - (len & 3) : 0;
03714   pos = len + pad + 16 * nNewTables;
03715   for (i = 0; i < nTables; ++i) {
03716     if (!dirCmap && strncmp(tableHdrs[i].tag, "cmap", 4) > 0) {
03717       tableDir[12 + 16*j     ] = 'c';
03718       tableDir[12 + 16*j +  1] = 'm';
03719       tableDir[12 + 16*j +  2] = 'a';
03720       tableDir[12 + 16*j +  3] = 'p';
03721       tableDir[12 + 16*j +  4] = (char)0; //~ should compute the checksum
03722       tableDir[12 + 16*j +  5] = (char)0;
03723       tableDir[12 + 16*j +  6] = (char)0;
03724       tableDir[12 + 16*j +  7] = (char)0;
03725       tableDir[12 + 16*j +  8] = (char)((pos >> 24) & 0xff);
03726       tableDir[12 + 16*j +  9] = (char)((pos >> 16) & 0xff);
03727       tableDir[12 + 16*j + 10] = (char)((pos >>  8) & 0xff);
03728       tableDir[12 + 16*j + 11] = (char)( pos        & 0xff);
03729       tableDir[12 + 16*j + 12] = (char)((sizeof(cmapTab) >> 24) & 0xff);
03730       tableDir[12 + 16*j + 13] = (char)((sizeof(cmapTab) >> 16) & 0xff);
03731       tableDir[12 + 16*j + 14] = (char)((sizeof(cmapTab) >>  8) & 0xff);
03732       tableDir[12 + 16*j + 15] = (char)( sizeof(cmapTab)        & 0xff);
03733       pos += sizeof(cmapTab);
03734       ++j;
03735       dirCmap = gTrue;
03736     }
03737     if (!dirName && strncmp(tableHdrs[i].tag, "name", 4) > 0) {
03738       tableDir[12 + 16*j     ] = 'n';
03739       tableDir[12 + 16*j +  1] = 'a';
03740       tableDir[12 + 16*j +  2] = 'm';
03741       tableDir[12 + 16*j +  3] = 'e';
03742       tableDir[12 + 16*j +  4] = (char)0; //~ should compute the checksum
03743       tableDir[12 + 16*j +  5] = (char)0;
03744       tableDir[12 + 16*j +  6] = (char)0;
03745       tableDir[12 + 16*j +  7] = (char)0;
03746       tableDir[12 + 16*j +  8] = (char)((pos >> 24) & 0xff);
03747       tableDir[12 + 16*j +  9] = (char)((pos >> 16) & 0xff);
03748       tableDir[12 + 16*j + 10] = (char)((pos >>  8) & 0xff);
03749       tableDir[12 + 16*j + 11] = (char)( pos        & 0xff);
03750       tableDir[12 + 16*j + 12] = (char)((sizeof(nameTab) >> 24) & 0xff);
03751       tableDir[12 + 16*j + 13] = (char)((sizeof(nameTab) >> 16) & 0xff);
03752       tableDir[12 + 16*j + 14] = (char)((sizeof(nameTab) >>  8) & 0xff);
03753       tableDir[12 + 16*j + 15] = (char)( sizeof(nameTab)        & 0xff);
03754       pos += sizeof(nameTab);
03755       ++j;
03756       dirName = gTrue;
03757     }
03758     if (!dirName && strncmp(tableHdrs[i].tag, "post", 4) > 0) {
03759       tableDir[12 + 16*j     ] = 'p';
03760       tableDir[12 + 16*j +  1] = 'o';
03761       tableDir[12 + 16*j +  2] = 's';
03762       tableDir[12 + 16*j +  3] = 't';
03763       tableDir[12 + 16*j +  4] = (char)0; //~ should compute the checksum
03764       tableDir[12 + 16*j +  5] = (char)0;
03765       tableDir[12 + 16*j +  6] = (char)0;
03766       tableDir[12 + 16*j +  7] = (char)0;
03767       tableDir[12 + 16*j +  8] = (char)((pos >> 24) & 0xff);
03768       tableDir[12 + 16*j +  9] = (char)((pos >> 16) & 0xff);
03769       tableDir[12 + 16*j + 10] = (char)((pos >>  8) & 0xff);
03770       tableDir[12 + 16*j + 11] = (char)( pos        & 0xff);
03771       tableDir[12 + 16*j + 12] = (char)((sizeof(postTab) >> 24) & 0xff);
03772       tableDir[12 + 16*j + 13] = (char)((sizeof(postTab) >> 16) & 0xff);
03773       tableDir[12 + 16*j + 14] = (char)((sizeof(postTab) >>  8) & 0xff);
03774       tableDir[12 + 16*j + 15] = (char)( sizeof(postTab)        & 0xff);
03775       pos += sizeof(postTab);
03776       ++j;
03777       dirPost = gTrue;
03778     }
03779     tableDir[12 + 16*j     ] = tableHdrs[i].tag[0];
03780     tableDir[12 + 16*j +  1] = tableHdrs[i].tag[1];
03781     tableDir[12 + 16*j +  2] = tableHdrs[i].tag[2];
03782     tableDir[12 + 16*j +  3] = tableHdrs[i].tag[3];
03783     tableDir[12 + 16*j +  4] = (char)((tableHdrs[i].checksum >> 24) & 0xff);
03784     tableDir[12 + 16*j +  5] = (char)((tableHdrs[i].checksum >> 16) & 0xff);
03785     tableDir[12 + 16*j +  6] = (char)((tableHdrs[i].checksum >>  8) & 0xff);
03786     tableDir[12 + 16*j +  7] = (char)( tableHdrs[i].checksum        & 0xff);
03787     t = tableHdrs[i].offset + nNewTables * 16;
03788     tableDir[12 + 16*j +  8] = (char)((t >> 24) & 0xff);
03789     tableDir[12 + 16*j +  9] = (char)((t >> 16) & 0xff);
03790     tableDir[12 + 16*j + 10] = (char)((t >>  8) & 0xff);
03791     tableDir[12 + 16*j + 11] = (char)( t        & 0xff);
03792     tableDir[12 + 16*j + 12] = (char)((tableHdrs[i].length >> 24) & 0xff);
03793     tableDir[12 + 16*j + 13] = (char)((tableHdrs[i].length >> 16) & 0xff);
03794     tableDir[12 + 16*j + 14] = (char)((tableHdrs[i].length >>  8) & 0xff);
03795     tableDir[12 + 16*j + 15] = (char)( tableHdrs[i].length        & 0xff);
03796     ++j;
03797   }
03798   if (!dirCmap) {
03799     tableDir[12 + 16*j     ] = 'c';
03800     tableDir[12 + 16*j +  1] = 'm';
03801     tableDir[12 + 16*j +  2] = 'a';
03802     tableDir[12 + 16*j +  3] = 'p';
03803     tableDir[12 + 16*j +  4] = (char)0; //~ should compute the checksum
03804     tableDir[12 + 16*j +  5] = (char)0;
03805     tableDir[12 + 16*j +  6] = (char)0;
03806     tableDir[12 + 16*j +  7] = (char)0;
03807     tableDir[12 + 16*j +  8] = (char)((pos >> 24) & 0xff);
03808     tableDir[12 + 16*j +  9] = (char)((pos >> 16) & 0xff);
03809     tableDir[12 + 16*j + 10] = (char)((pos >>  8) & 0xff);
03810     tableDir[12 + 16*j + 11] = (char)( pos        & 0xff);
03811     tableDir[12 + 16*j + 12] = (char)((sizeof(cmapTab) >> 24) & 0xff);
03812     tableDir[12 + 16*j + 13] = (char)((sizeof(cmapTab) >> 16) & 0xff);
03813     tableDir[12 + 16*j + 14] = (char)((sizeof(cmapTab) >>  8) & 0xff);
03814     tableDir[12 + 16*j + 15] = (char)( sizeof(cmapTab)        & 0xff);
03815     pos += sizeof(cmapTab);
03816     ++j;
03817     dirCmap = gTrue;
03818   }
03819   if (!dirName) {
03820     tableDir[12 + 16*j     ] = 'n';
03821     tableDir[12 + 16*j +  1] = 'a';
03822     tableDir[12 + 16*j +  2] = 'm';
03823     tableDir[12 + 16*j +  3] = 'e';
03824     tableDir[12 + 16*j +  4] = (char)0; //~ should compute the checksum
03825     tableDir[12 + 16*j +  5] = (char)0;
03826     tableDir[12 + 16*j +  6] = (char)0;
03827     tableDir[12 + 16*j +  7] = (char)0;
03828     tableDir[12 + 16*j +  8] = (char)((pos >> 24) & 0xff);
03829     tableDir[12 + 16*j +  9] = (char)((pos >> 16) & 0xff);
03830     tableDir[12 + 16*j + 10] = (char)((pos >>  8) & 0xff);
03831     tableDir[12 + 16*j + 11] = (char)( pos        & 0xff);
03832     tableDir[12 + 16*j + 12] = (char)((sizeof(nameTab) >> 24) & 0xff);
03833     tableDir[12 + 16*j + 13] = (char)((sizeof(nameTab) >> 16) & 0xff);
03834     tableDir[12 + 16*j + 14] = (char)((sizeof(nameTab) >>  8) & 0xff);
03835     tableDir[12 + 16*j + 15] = (char)( sizeof(nameTab)        & 0xff);
03836     pos += sizeof(nameTab);
03837     ++j;
03838     dirName = gTrue;
03839   }
03840   if (!dirPost) {
03841     tableDir[12 + 16*j     ] = 'p';
03842     tableDir[12 + 16*j +  1] = 'o';
03843     tableDir[12 + 16*j +  2] = 's';
03844     tableDir[12 + 16*j +  3] = 't';
03845     tableDir[12 + 16*j +  4] = (char)0; //~ should compute the checksum
03846     tableDir[12 + 16*j +  5] = (char)0;
03847     tableDir[12 + 16*j +  6] = (char)0;
03848     tableDir[12 + 16*j +  7] = (char)0;
03849     tableDir[12 + 16*j +  8] = (char)((pos >> 24) & 0xff);
03850     tableDir[12 + 16*j +  9] = (char)((pos >> 16) & 0xff);
03851     tableDir[12 + 16*j + 10] = (char)((pos >>  8) & 0xff);
03852     tableDir[12 + 16*j + 11] = (char)( pos        & 0xff);
03853     tableDir[12 + 16*j + 12] = (char)((sizeof(postTab) >> 24) & 0xff);
03854     tableDir[12 + 16*j + 13] = (char)((sizeof(postTab) >> 16) & 0xff);
03855     tableDir[12 + 16*j + 14] = (char)((sizeof(postTab) >>  8) & 0xff);
03856     tableDir[12 + 16*j + 15] = (char)( sizeof(postTab)        & 0xff);
03857     pos += sizeof(postTab);
03858     ++j;
03859     dirPost = gTrue;
03860   }
03861 
03862   // write the table directory
03863   fwrite(tableDir, 1, 12 + 16 * nAllTables, out);
03864 
03865   // write the original tables
03866   fwrite(file + 12 + 16*nTables, 1, len - (12 + 16*nTables), out);
03867 
03868   // write the new tables
03869   for (i = 0; i < pad; ++i) {
03870     fputc((char)0, out);
03871   }
03872   if (!haveCmap) {
03873     fwrite(cmapTab, 1, sizeof(cmapTab), out);
03874   }
03875   if (!haveName) {
03876     fwrite(nameTab, 1, sizeof(nameTab), out);
03877   }
03878   if (!havePost) {
03879     fwrite(postTab, 1, sizeof(postTab), out);
03880   }
03881 
03882   gfree(tableDir);
03883 }
KDE Home | KDE Accessibility Home | Description of Access Keys