home *** CD-ROM | disk | FTP | other *** search
/ PSION CD 2 / PsionCDVol2.iso / Programs / 720 / PDF090B4-SorceCode / pdf / FontFile.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-09-30  |  44.8 KB  |  1,722 lines

  1. //========================================================================
  2. //
  3. // FontFile.cc
  4. //
  5. // Copyright 1999 Derek B. Noonburg
  6. //
  7. //========================================================================
  8. //
  9. // Ported to EPOC by Sander van der Wal
  10. //
  11. // $Log: FontFile.cpp $
  12. // Revision 1.3  2000-09-20 20:54:08+02  svdwal
  13. // some bugfixes from xpdf 0.91
  14. //
  15. // Revision 1.2  2000-09-17 13:38:24+02  svdwal
  16. // Ported
  17. //
  18.  
  19. #ifdef __GNUC__
  20. #pragma implementation
  21. #endif
  22.  
  23. #ifdef __SYMBIAN32__
  24. #include <e32std.h>
  25. #endif
  26.  
  27. static inline TReal fabs(TReal aX) { return Abs(aX); }
  28. #include <stdlib.h>
  29.  
  30. #include "gmem.h"
  31.  
  32. #include "Error.h"
  33. #include "FontFile.h"
  34. #include "StdFontInfo.h"
  35. #include "CompactFontInfo.h"
  36.  
  37. #include "PDFGlobal.h"
  38. #include "Pdf.rsg"
  39.  
  40.  
  41. //------------------------------------------------------------------------
  42.  
  43. static Guint getWord(Guchar *ptr, int size);
  44. static double getNum(Guchar **ptr, GBool *fp);
  45. static char *getString(int sid, Guchar *stringIdxPtr,
  46.                Guchar *stringStartPtr, int stringOffSize,
  47.                char *buf);
  48.  
  49. //------------------------------------------------------------------------
  50.  
  51. static inline char *nextLine(char *line, char *end) {
  52.   while (line < end && *line != '\n' && *line != '\r')
  53.     ++line;
  54.   while (line < end && *line == '\n' || *line == '\r')
  55.     ++line;
  56.   return line;
  57. }
  58.  
  59. static const char hexChars[17] = "0123456789ABCDEF";
  60.  
  61. //------------------------------------------------------------------------
  62. // FontFile
  63. //------------------------------------------------------------------------
  64.  
  65. FontFile::FontFile() {
  66. }
  67.  
  68. FontFile::~FontFile() {
  69. }
  70.  
  71. //------------------------------------------------------------------------
  72. // Type1FontFile
  73. //------------------------------------------------------------------------
  74.  
  75. Type1FontFile::Type1FontFile() {
  76. }
  77.  
  78. void Type1FontFile::ConstructL(char *file, int len)
  79. {
  80.   char *line, *line1, *p;
  81.   char buf[256];
  82.   int n, code, i;
  83.  
  84.   freeEnc = gTrue;
  85.  
  86.   for (i = 1, line = file; i <= 100 && line < file + len && !encoding; ++i) {
  87.  
  88.     // get font name
  89.     if (!strncmp(line, "/FontName", 9)) {
  90.       strncpy(buf, line, 255);
  91.       buf[255] = '\0';
  92.       if ((p = strchr(buf+9, '/')) &&
  93.           (p = strtok(p+1, " \t\n\r")))
  94.         name = copyStringL(p);
  95.       line = nextLine(line, file + len);
  96.  
  97.     // get encoding
  98.     } else if (!strncmp(line, "/Encoding StandardEncoding def", 30)) {
  99.       encoding = Global().FontFile.type1StdEncoding->copyL();
  100.     } 
  101.     else if (!strncmp(line, "/Encoding 256 array", 19)) {
  102.       encoding = new(ELeave) FontEncoding();
  103.       encoding->ConstructL();
  104.       for (i = 0; i < 300; ++i) {
  105.         line1 = nextLine(line, file + len);
  106.         if ((n = line1 - line) > 255)
  107.           n = 255;
  108.         strncpy(buf, line, n);
  109.         buf[n] = '\0';
  110.         p = strtok(buf, " \t");
  111.         if (p && !strcmp(p, "dup")) {
  112.           p = strtok(NULL, " \t");
  113.           if (p) {
  114.             if ((code = atoi(p)) < 256) {
  115.               p = strtok(NULL, " \t");
  116.               if (p) {
  117.                 if (p[0] == '/') {
  118.                   encoding->addChar(code, copyStringL(p+1));
  119.                 }
  120.               }
  121.             }
  122.           }
  123.         } 
  124.         else {
  125.           p = strtok(NULL, " \t\n\r");
  126.           if (p && !strcmp(p, "def")) {
  127.             break;
  128.           }
  129.         }
  130.         line = line1;
  131.       }
  132.       //~ check for getinterval/putinterval junk
  133.  
  134.     } 
  135.     else {
  136.       line = nextLine(line, file + len);
  137.     }
  138.   }
  139. }
  140.  
  141. Type1FontFile* Type1FontFile::NewLC(char *file, int len)
  142. {
  143.   Type1FontFile* self =new(ELeave) Type1FontFile();
  144.   CleanupStack::PushL(self);
  145.   self->ConstructL(file, len);
  146.   return self;
  147.  
  148.        
  149. }
  150.  
  151. Type1FontFile* Type1FontFile::NewL(char *file, int len)
  152. {
  153.   Type1FontFile* self = Type1FontFile::NewLC(file, len);
  154.   CleanupStack::Pop();
  155.   return self;
  156. }
  157.  
  158.  
  159. Type1FontFile::~Type1FontFile() {
  160.   delete name;
  161.   if (freeEnc)
  162.     delete encoding;
  163. }
  164.  
  165. FontEncoding *Type1FontFile::getEncoding(GBool taken) {
  166.   if (taken)
  167.     freeEnc = gFalse;
  168.   return encoding;
  169. }
  170.  
  171. //------------------------------------------------------------------------
  172. // Type1CFontFile
  173. //------------------------------------------------------------------------
  174.  
  175. Type1CFontFile::Type1CFontFile() {
  176. }
  177.  
  178. void Type1CFontFile::ConstructL(char *file, int /* len */) 
  179. {
  180.   char buf[256];
  181.   Guchar *topPtr, *idxStartPtr, *idxPtr0, *idxPtr1;
  182.   Guchar *stringIdxPtr, *stringStartPtr;
  183.   int topOffSize, idxOffSize, stringOffSize;
  184.   int nFonts, nStrings, nGlyphs;
  185.   int nCodes, nRanges, nLeft, nSups;
  186.   Gushort *glyphNames;
  187.   int charset, enc, charstrings;
  188.   int charsetFormat, encFormat;
  189.   int c, sid;
  190.   double op[48];
  191.   double x;
  192.   GBool isFP;
  193.   int key;
  194.   int i, j, n;
  195.  
  196.   freeEnc = gTrue;
  197.  
  198.   // read header
  199.   topPtr = (Guchar *)file + (file[2] & 0xff);
  200.   topOffSize = file[3] & 0xff;
  201.  
  202.   // read name index (first font only)
  203.   nFonts = getWord(topPtr, 2);
  204.   idxOffSize = topPtr[2];
  205.   topPtr += 3;
  206.   idxStartPtr = topPtr + (nFonts + 1) * idxOffSize - 1;
  207.   idxPtr0 = idxStartPtr + getWord(topPtr, idxOffSize);
  208.   idxPtr1 = idxStartPtr + getWord(topPtr + idxOffSize, idxOffSize);
  209.   if ((n = idxPtr1 - idxPtr0) > 255)
  210.     n = 255;
  211.   strncpy(buf, (char *)idxPtr0, n);
  212.   buf[n] = '\0';
  213.   name = copyStringL(buf);
  214.   topPtr = idxStartPtr + getWord(topPtr + nFonts * idxOffSize, idxOffSize);
  215.  
  216.   // read top dict index (first font only)
  217.   nFonts = getWord(topPtr, 2);
  218.   idxOffSize = topPtr[2];
  219.   topPtr += 3;
  220.   idxStartPtr = topPtr + (nFonts + 1) * idxOffSize - 1;
  221.   idxPtr0 = idxStartPtr + getWord(topPtr, idxOffSize);
  222.   idxPtr1 = idxStartPtr + getWord(topPtr + idxOffSize, idxOffSize);
  223.   charset = 0;
  224.   enc = 0;
  225.   charstrings = 0;
  226.   i = 0;
  227.   while (idxPtr0 < idxPtr1) {
  228.     if (*idxPtr0 <= 27 || *idxPtr0 == 31) {
  229.       key = *idxPtr0++;
  230.       if (key == 0x0c)
  231.         key = (key << 8) | *idxPtr0++;
  232.       if (key == 0x0f) { // charset
  233.         charset = (int)op[0];
  234.       } else if (key == 0x10) { // encoding
  235.         enc = (int)op[0];
  236.       } else if (key == 0x11) { // charstrings
  237.         charstrings = (int)op[0];
  238.       }
  239.       i = 0;
  240.     } else {
  241.       x = getNum(&idxPtr0, &isFP);
  242.       if (i < 48)
  243.     op[i++] = x;
  244.     }
  245.   }
  246.   topPtr = idxStartPtr + getWord(topPtr + nFonts * idxOffSize, idxOffSize);
  247.  
  248.   // read string index
  249.   nStrings = getWord(topPtr, 2);
  250.   stringOffSize = topPtr[2];
  251.   topPtr += 3;
  252.   stringIdxPtr = topPtr;
  253.   stringStartPtr = topPtr + (nStrings + 1) * stringOffSize - 1;
  254.   topPtr = stringStartPtr + getWord(topPtr + nStrings * stringOffSize,
  255.                     stringOffSize);
  256.  
  257.   // get number of glyphs from charstrings index
  258.   topPtr = (Guchar *)file + charstrings;
  259.   nGlyphs = getWord(topPtr, 2);
  260.  
  261.   // read charset
  262.   if (charset == 0) {
  263.     glyphNames = (Gushort *) &type1CISOAdobeCharset[0];
  264.   } else if (charset == 1) {
  265.     glyphNames = (Gushort *) &type1CExpertCharset[0];
  266.   } else if (charset == 2) {
  267.     glyphNames = (Gushort *) &type1CExpertSubsetCharset[0];
  268.   } else {
  269.     glyphNames = (Gushort *)User::AllocLC(nGlyphs * sizeof(Gushort));
  270.     glyphNames[0] = 0;
  271.     topPtr = (Guchar *)file + charset;
  272.     charsetFormat = *topPtr++;
  273.     if (charsetFormat == 0) {
  274.       for (i = 1; i < nGlyphs; ++i) {
  275.     glyphNames[i] = getWord(topPtr, 2);
  276.     topPtr += 2;
  277.       }
  278.     } else if (charsetFormat == 1) {
  279.       i = 1;
  280.       while (i < nGlyphs) {
  281.     c = getWord(topPtr, 2);
  282.     topPtr += 2;
  283.     nLeft = *topPtr++;
  284.     for (j = 0; j <= nLeft; ++j)
  285.       glyphNames[i++] = c++;
  286.       }
  287.     } else if (charsetFormat == 2) {
  288.       i = 1;
  289.       while (i < nGlyphs) {
  290.     c = getWord(topPtr, 2);
  291.     topPtr += 2;
  292.     nLeft = getWord(topPtr, 2);
  293.     topPtr += 2;
  294.     for (j = 0; j <= nLeft; ++j)
  295.       glyphNames[i++] = c++;
  296.       }
  297.     }
  298.   }
  299.  
  300.   // read encoding (glyph -> code mapping)
  301.   if (enc == 0) {
  302.     encoding = Global().FontFile.type1StdEncoding->copyL();
  303.   } else if (enc == 1) {
  304.     encoding = Global().FontFile.type1ExpertEncoding->copyL();
  305.   } else {
  306.     encoding = new(ELeave) FontEncoding();
  307.     encoding->ConstructL();
  308.     topPtr = (Guchar *)file + enc;
  309.     encFormat = *topPtr++;
  310.     if ((encFormat & 0x7f) == 0) {
  311.       nCodes = 1 + *topPtr++;
  312.       if (nCodes > nGlyphs) {
  313.     nCodes = nGlyphs;
  314.       }
  315.       for (i = 1; i < nCodes; ++i) {
  316.     c = *topPtr++;
  317.     getString(glyphNames[i], stringIdxPtr, stringStartPtr,
  318.           stringOffSize, buf);
  319.     encoding->addChar(c, copyStringL(buf));
  320.       }
  321.     } else if ((encFormat & 0x7f) == 1) {
  322.       nRanges = *topPtr++;
  323.       nCodes = 1;
  324.       for (i = 0; i < nRanges; ++i) {
  325.     c = *topPtr++;
  326.     nLeft = *topPtr++;
  327.     for (j = 0; j <= nLeft && nCodes < nGlyphs; ++j) {
  328.       getString(glyphNames[nCodes], stringIdxPtr, stringStartPtr,
  329.             stringOffSize, buf);
  330.       encoding->addChar(c, copyStringL(buf));
  331.       ++nCodes;
  332.       ++c;
  333.     }
  334.       }
  335.     }
  336.     if (encFormat & 0x80) {
  337.       nSups = *topPtr++;
  338.       for (i = 0; i < nSups; ++i) {
  339.     c = *topPtr++;
  340.     sid = getWord(topPtr, 2);
  341.     topPtr += 2;
  342.     getString(sid, stringIdxPtr, stringStartPtr,
  343.           stringOffSize, buf);
  344.     encoding->addChar(c, copyStringL(buf));
  345.       }
  346.     }
  347.   }
  348.  
  349.   if (charset > 2)
  350.     CleanupStack::PopAndDestroy(); // glyphNames
  351. }
  352.  
  353. Type1CFontFile* Type1CFontFile::NewLC(char *file, int len)
  354. {
  355.   Type1CFontFile* self = new(ELeave) Type1CFontFile();
  356.   CleanupStack::PushL(self);
  357.   self->ConstructL(file, len);
  358.   return self;
  359. }
  360.  
  361. Type1CFontFile* Type1CFontFile::NewL(char *file, int len)
  362. {
  363.   Type1CFontFile* self = Type1CFontFile::NewLC(file, len);
  364.   CleanupStack::Pop();
  365.   return self;
  366. }
  367.  
  368.  
  369. Type1CFontFile::~Type1CFontFile() {
  370.   delete name;
  371.   if (freeEnc)
  372.     delete encoding;
  373. }
  374.  
  375. FontEncoding *Type1CFontFile::getEncoding(GBool taken) {
  376.   if (taken)
  377.     freeEnc = gFalse;
  378.   return encoding;
  379. }
  380.  
  381. static Guint getWord(Guchar *ptr, int size) {
  382.   Guint x;
  383.   int i;
  384.  
  385.   x = 0;
  386.   for (i = 0; i < size; ++i)
  387.     x = (x << 8) + *ptr++;
  388.   return x;
  389. }
  390.  
  391. static double getNum(Guchar **ptr, GBool *fp) {
  392.   static const char nybChars[16] = "0123456789.ee -";
  393.   int b0, b, nyb0, nyb1;
  394.   double x;
  395.   char buf[65];
  396.   int i;
  397.  
  398.   x = 0;
  399.   *fp = gFalse;
  400.   b0 = (*ptr)[0];
  401.   if (b0 < 28) {
  402.     x = 0;
  403.   } else if (b0 == 28) {
  404.     x = ((*ptr)[1] << 8) + (*ptr)[2];
  405.     *ptr += 3;
  406.   } else if (b0 == 29) {
  407.     x = ((*ptr)[1] << 24) + ((*ptr)[2] << 16) + ((*ptr)[3] << 8) + (*ptr)[4];
  408.     *ptr += 5;
  409.   } else if (b0 == 30) {
  410.     *ptr += 1;
  411.     i = 0;
  412.     do {
  413.       b = *(*ptr)++;
  414.       nyb0 = b >> 4;
  415.       nyb1 = b & 0x0f;
  416.       if (nyb0 == 0xf)
  417.     break;
  418.       buf[i++] = nybChars[nyb0];
  419.       if (i == 64)
  420.     break;
  421.       if (nyb0 == 0xc)
  422.     buf[i++] = '-';
  423.       if (i == 64)
  424.     break;
  425.       if (nyb1 == 0xf)
  426.     break;
  427.       buf[i++] = nybChars[nyb1];
  428.       if (i == 64)
  429.     break;
  430.       if (nyb1 == 0xc)
  431.     buf[i++] = '-';
  432.     } while (i < 64);
  433.     buf[i] = '\0';
  434.     x = atof(buf);
  435.     *fp = gTrue;
  436.   } else if (b0 == 31) {
  437.     x = 0;
  438.   } else if (b0 < 247) {
  439.     x = b0 - 139;
  440.     *ptr += 1;
  441.   } else if (b0 < 251) {
  442.     x = ((b0 - 247) << 8) + (*ptr)[1] + 108;
  443.     *ptr += 2;
  444.   } else {
  445.     x = -((b0 - 251) << 8) - (*ptr)[1] - 108;
  446.     *ptr += 2;
  447.   }
  448.   return x;
  449. }
  450.  
  451. static char *getString(int sid, Guchar *stringIdxPtr,
  452.                Guchar *stringStartPtr, int stringOffSize,
  453.                char *buf) {
  454.   Guchar *idxPtr0, *idxPtr1;
  455.   int len;
  456.  
  457.   if (sid < 391) {
  458.     strcpy(buf, type1CStdStrings[sid]);
  459.   } else {
  460.     sid -= 391;
  461.     idxPtr0 = stringStartPtr + getWord(stringIdxPtr + sid * stringOffSize,
  462.                        stringOffSize);
  463.     idxPtr1 = stringStartPtr + getWord(stringIdxPtr + (sid+1) * stringOffSize,
  464.                        stringOffSize);
  465.     if ((len = idxPtr1 - idxPtr0) > 255)
  466.       len = 255;
  467.     strncpy(buf, (char *)idxPtr0, len);
  468.     buf[len] = '\0';
  469.   }
  470.   return buf;
  471. }
  472.  
  473. //------------------------------------------------------------------------
  474. // Type1CFontConverter
  475. //------------------------------------------------------------------------
  476.  
  477. Type1CFontConverter::Type1CFontConverter(char *file, int len, FILE *out) {
  478.   this->file = file;
  479.   this->len = len;
  480.   this->out = out;
  481.   r1 = 55665;
  482.   line = 0;
  483. }
  484.  
  485. Type1CFontConverter::~Type1CFontConverter() {
  486. }
  487.  
  488. void Type1CFontConverter::convert() {
  489.   char *fontName;
  490.   struct {
  491.     int version;
  492.     int notice;
  493.     int copyright;
  494.     int fullName;
  495.     int familyName;
  496.     int weight;
  497.     int isFixedPitch;
  498.     double italicAngle;
  499.     double underlinePosition;
  500.     double underlineThickness;
  501.     int paintType;
  502.     int charstringType;        //~ ???
  503.     double fontMatrix[6];
  504.     int uniqueID;
  505.     double fontBBox[4];
  506.     double strokeWidth;        //~ ???
  507.     int charset;
  508.     int encoding;
  509.     int charStrings;
  510.     int privateSize;
  511.     int privateOffset;
  512.   } dict;
  513.   char buf[256], eBuf[256];
  514.   Guchar *topPtr, *idxStartPtr, *idxPtr0, *idxPtr1;
  515.   Guchar *stringIdxPtr, *stringStartPtr;
  516.   int topOffSize, idxOffSize, stringOffSize;
  517.   int nFonts, nStrings, nGlyphs;
  518.   int nCodes, nRanges, nLeft, nSups;
  519.   Gushort *glyphNames;
  520.   int charsetFormat, encFormat;
  521.   int subrsOffset, nSubrs;
  522.   int nCharStrings;
  523.   int c, sid;
  524.   double x;
  525.   GBool isFP;
  526.   int key;
  527.   int i, j, n;
  528.  
  529.   // read header
  530.   topPtr = (Guchar *)file + (file[2] & 0xff);
  531.   topOffSize = file[3] & 0xff;
  532.  
  533.   // read name (first font only)
  534.   nFonts = getWord(topPtr, 2);
  535.   idxOffSize = topPtr[2];
  536.   topPtr += 3;
  537.   idxStartPtr = topPtr + (nFonts + 1) * idxOffSize - 1;
  538.   idxPtr0 = idxStartPtr + getWord(topPtr, idxOffSize);
  539.   idxPtr1 = idxStartPtr + getWord(topPtr + idxOffSize, idxOffSize);
  540.   if ((n = idxPtr1 - idxPtr0) > 255)
  541.     n = 255;
  542.   strncpy(buf, (char *)idxPtr0, n);
  543.   buf[n] = '\0';
  544.   fontName = copyStringL(buf);
  545.   CleanupStack::PushL(fontName);
  546.   topPtr = idxStartPtr + getWord(topPtr + nFonts * idxOffSize, idxOffSize);
  547.  
  548.   // read top dict (first font only)
  549.   nFonts = getWord(topPtr, 2);
  550.   idxOffSize = topPtr[2];
  551.   topPtr += 3;
  552.   idxStartPtr = topPtr + (nFonts + 1) * idxOffSize - 1;
  553.   idxPtr0 = idxStartPtr + getWord(topPtr, idxOffSize);
  554.   idxPtr1 = idxStartPtr + getWord(topPtr + idxOffSize, idxOffSize);
  555.   dict.version = 0;
  556.   dict.notice = 0;
  557.   dict.copyright = 0;
  558.   dict.fullName = 0;
  559.   dict.familyName = 0;
  560.   dict.weight = 0;
  561.   dict.isFixedPitch = 0;
  562.   dict.italicAngle = 0;
  563.   dict.underlinePosition = -100;
  564.   dict.underlineThickness = 50;
  565.   dict.paintType = 0;
  566.   dict.charstringType = 2;
  567.   dict.fontMatrix[0] = 0.001;
  568.   dict.fontMatrix[1] = 0;
  569.   dict.fontMatrix[2] = 0;
  570.   dict.fontMatrix[3] = 0.001;
  571.   dict.fontMatrix[4] = 0;
  572.   dict.fontMatrix[5] = 0;
  573.   dict.uniqueID = 0;
  574.   dict.fontBBox[0] = 0;
  575.   dict.fontBBox[1] = 0;
  576.   dict.fontBBox[2] = 0;
  577.   dict.fontBBox[3] = 0;
  578.   dict.strokeWidth = 0;
  579.   dict.charset = 0;
  580.   dict.encoding = 0;
  581.   dict.charStrings = 0;
  582.   dict.privateSize = 0;
  583.   dict.privateOffset = 0;
  584.   i = 0;
  585.   while (idxPtr0 < idxPtr1) {
  586.     if (*idxPtr0 <= 27 || *idxPtr0 == 31) {
  587.       key = *idxPtr0++;
  588.       if (key == 0x0c)
  589.     key = (key << 8) | *idxPtr0++;
  590.       switch (key) {
  591.       case 0x0000: dict.version = (int)op[0]; break;
  592.       case 0x0001: dict.notice = (int)op[0]; break;
  593.       case 0x0c00: dict.copyright = (int)op[0]; break;
  594.       case 0x0002: dict.fullName = (int)op[0]; break;
  595.       case 0x0003: dict.familyName = (int)op[0]; break;
  596.       case 0x0004: dict.weight = (int)op[0]; break;
  597.       case 0x0c01: dict.isFixedPitch = (int)op[0]; break;
  598.       case 0x0c02: dict.italicAngle = op[0]; break;
  599.       case 0x0c03: dict.underlinePosition = op[0]; break;
  600.       case 0x0c04: dict.underlineThickness = op[0]; break;
  601.       case 0x0c05: dict.paintType = (int)op[0]; break;
  602.       case 0x0c06: dict.charstringType = (int)op[0]; break;
  603.       case 0x0c07: dict.fontMatrix[0] = op[0];
  604.                dict.fontMatrix[1] = op[1];
  605.                dict.fontMatrix[2] = op[2];
  606.                dict.fontMatrix[3] = op[3];
  607.                dict.fontMatrix[4] = op[4];
  608.                dict.fontMatrix[5] = op[5]; break;
  609.       case 0x000d: dict.uniqueID = (int)op[0]; break;
  610.       case 0x0005: dict.fontBBox[0] = op[0];
  611.                dict.fontBBox[1] = op[1];
  612.                dict.fontBBox[2] = op[2];
  613.                dict.fontBBox[3] = op[3]; break;
  614.       case 0x0c08: dict.strokeWidth = op[0]; break;
  615.       case 0x000f: dict.charset = (int)op[0]; break;
  616.       case 0x0010: dict.encoding = (int)op[0]; break;
  617.       case 0x0011: dict.charStrings = (int)op[0]; break;
  618.       case 0x0012: dict.privateSize = (int)op[0];
  619.                dict.privateOffset = (int)op[1]; break;
  620.       }
  621.       i = 0;
  622.     } else {
  623.       x = getNum(&idxPtr0, &isFP);
  624.       if (i < 48) {
  625.     op[i] = x;
  626.     fp[i++] = isFP;
  627.       }
  628.     }
  629.   }
  630.   topPtr = idxStartPtr + getWord(topPtr + nFonts * idxOffSize, idxOffSize);
  631.  
  632.   // read string index
  633.   nStrings = getWord(topPtr, 2);
  634.   stringOffSize = topPtr[2];
  635.   topPtr += 3;
  636.   stringIdxPtr = topPtr;
  637.   stringStartPtr = topPtr + (nStrings + 1) * stringOffSize - 1;
  638.   topPtr = stringStartPtr + getWord(topPtr + nStrings * stringOffSize,
  639.                     stringOffSize);
  640.  
  641. #if 1 //~
  642.   // get global subrs
  643.   int nGSubrs;
  644.   int gSubrOffSize;
  645.  
  646.   nGSubrs = getWord(topPtr, 2);
  647.   gSubrOffSize = topPtr[2];
  648.   topPtr += 3;
  649. #endif
  650.  
  651.   // write header and font dictionary, up to encoding
  652.   fprintf(out, "%%!FontType1-1.0: %s", fontName);
  653.   if (dict.version != 0) {
  654.     fprintf(out, "%s",
  655.         getString(dict.version, stringIdxPtr, stringStartPtr,
  656.               stringOffSize, buf));
  657.   }
  658.   fprintf(out, "\n");
  659.   fprintf(out, "11 dict begin\n");
  660.   fprintf(out, "/FontInfo 10 dict dup begin\n");
  661.   if (dict.version != 0) {
  662.     fprintf(out, "/version (%s) readonly def\n",
  663.         getString(dict.version, stringIdxPtr, stringStartPtr,
  664.               stringOffSize, buf));
  665.   }
  666.   if (dict.notice != 0) {
  667.     fprintf(out, "/Notice (%s) readonly def\n",
  668.         getString(dict.notice, stringIdxPtr, stringStartPtr,
  669.               stringOffSize, buf));
  670.   }
  671.   if (dict.copyright != 0) {
  672.     fprintf(out, "/Copyright (%s) readonly def\n",
  673.         getString(dict.copyright, stringIdxPtr, stringStartPtr,
  674.               stringOffSize, buf));
  675.   }
  676.   if (dict.fullName != 0) {
  677.     fprintf(out, "/FullName (%s) readonly def\n",
  678.         getString(dict.fullName, stringIdxPtr, stringStartPtr,
  679.               stringOffSize, buf));
  680.   }
  681.   if (dict.familyName != 0) {
  682.     fprintf(out, "/FamilyName (%s) readonly def\n",
  683.         getString(dict.familyName, stringIdxPtr, stringStartPtr,
  684.               stringOffSize, buf));
  685.   }
  686.   if (dict.weight != 0) {
  687.     fprintf(out, "/Weight (%s) readonly def\n",
  688.         getString(dict.weight, stringIdxPtr, stringStartPtr,
  689.               stringOffSize, buf));
  690.   }
  691.   fprintf(out, "/isFixedPitch %s def\n", dict.isFixedPitch ? "true" : "false");
  692.   fprintf(out, "/ItalicAngle %g def\n", dict.italicAngle);
  693.   fprintf(out, "/UnderlinePosition %g def\n", dict.underlinePosition);
  694.   fprintf(out, "/UnderlineThickness %g def\n", dict.underlineThickness);
  695.   fprintf(out, "end readonly def\n");
  696.   fprintf(out, "/FontName /%s def\n", fontName);
  697.   fprintf(out, "/PaintType %d def\n", dict.paintType);
  698.   fprintf(out, "/FontType 1 def\n");
  699.   fprintf(out, "/FontMatrix [%g %g %g %g %g %g] readonly def\n",
  700.       dict.fontMatrix[0], dict.fontMatrix[1], dict.fontMatrix[2],
  701.       dict.fontMatrix[3], dict.fontMatrix[4], dict.fontMatrix[5]);
  702.   fprintf(out, "/FontBBox [%g %g %g %g] readonly def\n",
  703.       dict.fontBBox[0], dict.fontBBox[1],
  704.       dict.fontBBox[2], dict.fontBBox[3]);
  705.   if (dict.uniqueID != 0) {
  706.     fprintf(out, "/UniqueID %d def\n", dict.uniqueID);
  707.   }
  708.  
  709.   // get number of glyphs from charstrings index
  710.   topPtr = (Guchar *)file + dict.charStrings;
  711.   nGlyphs = getWord(topPtr, 2);
  712.  
  713.   // read charset
  714.   if (dict.charset == 0) {
  715.     glyphNames = (Gushort*) &type1CISOAdobeCharset[0];
  716.   } else if (dict.charset == 1) {
  717.     glyphNames = (Gushort*) &type1CExpertCharset[0];
  718.   } else if (dict.charset == 2) {
  719.     glyphNames = (Gushort*) &type1CExpertSubsetCharset[0];
  720.   } else {
  721.     glyphNames = (Gushort *)User::AllocLC(nGlyphs * sizeof(Gushort));
  722.     glyphNames[0] = 0;
  723.     topPtr = (Guchar *)file + dict.charset;
  724.     charsetFormat = *topPtr++;
  725.     if (charsetFormat == 0) {
  726.       for (i = 1; i < nGlyphs; ++i) {
  727.     glyphNames[i] = getWord(topPtr, 2);
  728.     topPtr += 2;
  729.       }
  730.     } else if (charsetFormat == 1) {
  731.       i = 1;
  732.       while (i < nGlyphs) {
  733.     c = getWord(topPtr, 2);
  734.     topPtr += 2;
  735.     nLeft = *topPtr++;
  736.     for (j = 0; j <= nLeft; ++j)
  737.       glyphNames[i++] = c++;
  738.       }
  739.     } else if (charsetFormat == 2) {
  740.       i = 1;
  741.       while (i < nGlyphs) {
  742.     c = getWord(topPtr, 2);
  743.     topPtr += 2;
  744.     nLeft = getWord(topPtr, 2);
  745.     topPtr += 2;
  746.     for (j = 0; j <= nLeft; ++j)
  747.       glyphNames[i++] = c++;
  748.       }
  749.     }
  750.   }
  751.  
  752.   // read encoding (glyph -> code mapping), write Type 1 encoding
  753.   fprintf(out, "/Encoding ");
  754.   if (dict.encoding == 0) {
  755.     fprintf(out, "StandardEncoding def\n");
  756.   } else {
  757.     fprintf(out, "256 array\n");
  758.     fprintf(out, "0 1 255 {1 index exch /.notdef put} for\n");
  759.     if (dict.encoding == 1) {
  760.       for (i = 0; i < 256; ++i) {
  761.     if (type1ExpertEncodingNames[i])
  762.       fprintf(out, "dup %d /%s put\n", i, type1ExpertEncodingNames[i]);
  763.       }
  764.     } else {
  765.       topPtr = (Guchar *)file + dict.encoding;
  766.       encFormat = *topPtr++;
  767.       if ((encFormat & 0x7f) == 0) {
  768.     nCodes = 1 + *topPtr++;
  769.     if (nCodes > nGlyphs) {
  770.       nCodes = nGlyphs;
  771.     }
  772.     for (i = 1; i < nCodes; ++i) {
  773.       c = *topPtr++;
  774.       fprintf(out, "dup %d /%s put\n", c,
  775.           getString(glyphNames[i], stringIdxPtr, stringStartPtr,
  776.                 stringOffSize, buf));
  777.     }
  778.       } else if ((encFormat & 0x7f) == 1) {
  779.     nRanges = *topPtr++;
  780.     nCodes = 1;
  781.     for (i = 0; i < nRanges; ++i) {
  782.       c = *topPtr++;
  783.       nLeft = *topPtr++;
  784.       for (j = 0; j <= nLeft && nCodes < nGlyphs; ++j) {
  785.         fprintf(out, "dup %d /%s put\n", c,
  786.             getString(glyphNames[nCodes], stringIdxPtr, stringStartPtr,
  787.                   stringOffSize, buf));
  788.         ++nCodes;
  789.         ++c;
  790.       }
  791.     }
  792.       }
  793.       if (encFormat & 0x80) {
  794.     nSups = *topPtr++;
  795.     for (i = 0; i < nSups; ++i) {
  796.       c = *topPtr++;
  797.       sid = getWord(topPtr, 2);
  798.       topPtr += 2;
  799.       fprintf(out, "dup %d /%s put\n", c,
  800.           getString(sid, stringIdxPtr, stringStartPtr,
  801.                 stringOffSize, buf));
  802.     }
  803.       }
  804.     }
  805.     fprintf(out, "readonly def\n");
  806.   }
  807.   fprintf(out, "currentdict end\n");
  808.   fprintf(out, "currentfile eexec\n");
  809.  
  810.   // get private dictionary
  811.   eexecWrite("\x83\xca\x73\xd5");
  812.   eexecWrite("dup /Private 32 dict dup begin\n");
  813.   eexecWrite("/RD {string currentfile exch readstring pop} executeonly def\n");
  814.   eexecWrite("/ND {noaccess def} executeonly def\n");
  815.   eexecWrite("/NP {noaccess put} executeonly def\n");
  816.   eexecWrite("/MinFeature {16 16} ND\n");
  817.   eexecWrite("/password 5839 def\n");
  818.   subrsOffset = 0;
  819.   defaultWidthX = 0;
  820.   nominalWidthX = 0;
  821.   topPtr = (Guchar *)file + dict.privateOffset;
  822.   idxPtr0 = topPtr;
  823.   idxPtr1 = idxPtr0 + dict.privateSize;
  824.   i = 0;
  825.   while (idxPtr0 < idxPtr1) {
  826.     if (*idxPtr0 <= 27 || *idxPtr0 == 31) {
  827.       key = *idxPtr0++;
  828.       if (key == 0x0c)
  829.     key = (key << 8) | *idxPtr0++;
  830.       switch (key) {
  831.       case 0x0006:
  832.     getDeltaInt(eBuf, "BlueValues", op, i);
  833.     eexecWrite(eBuf);
  834.     break;
  835.       case 0x0007:
  836.     getDeltaInt(eBuf, "OtherBlues", op, i);
  837.     eexecWrite(eBuf);
  838.     break;
  839.       case 0x0008:
  840.     getDeltaInt(eBuf, "FamilyBlues", op, i);
  841.     eexecWrite(eBuf);
  842.     break;
  843.       case 0x0009:
  844.     getDeltaInt(eBuf, "FamilyOtherBlues", op, i);
  845.     eexecWrite(eBuf);
  846.     break;
  847.       case 0x0c09:
  848.     sprintf(eBuf, "/BlueScale %g def\n", op[0]);
  849.     eexecWrite(eBuf);
  850.     break;
  851.       case 0x0c0a:
  852.     sprintf(eBuf, "/BlueShift %d def\n", (int)op[0]);
  853.     eexecWrite(eBuf);
  854.     break;
  855.       case 0x0c0b:
  856.     sprintf(eBuf, "/BlueFuzz %d def\n", (int)op[0]);
  857.     eexecWrite(eBuf);
  858.     break;
  859.       case 0x000a:
  860.     sprintf(eBuf, "/StdHW [%g] def\n", op[0]);
  861.     eexecWrite(eBuf);
  862.     break;
  863.       case 0x000b:
  864.     sprintf(eBuf, "/StdVW [%g] def\n", op[0]);
  865.     eexecWrite(eBuf);
  866.     break;
  867.       case 0x0c0c:
  868.     getDeltaReal(eBuf, "StemSnapH", op, i);
  869.     eexecWrite(eBuf);
  870.     break;
  871.       case 0x0c0d:
  872.     getDeltaReal(eBuf, "StemSnapV", op, i);
  873.     eexecWrite(eBuf);
  874.     break;
  875.       case 0x0c0e:
  876.     sprintf(eBuf, "/ForceBold %s def\n", op[0] ? "true" : "false");
  877.     eexecWrite(eBuf);
  878.     break;
  879.       case 0x0c0f:
  880.     sprintf(eBuf, "/ForceBoldThreshold %g def\n", op[0]);
  881.     eexecWrite(eBuf);
  882.     break;
  883.       case 0x0c11:
  884.     sprintf(eBuf, "/LanguageGroup %d def\n", (int)op[0]);
  885.     eexecWrite(eBuf);
  886.     break;
  887.       case 0x0c12:
  888.     sprintf(eBuf, "/ExpansionFactor %g def\n", op[0]);
  889.     eexecWrite(eBuf);
  890.     break;
  891.       case 0x0c13:
  892.     error(-1, R_GOT_TYPE_1C_INITIALRANDOMSEED);
  893.     break;
  894.       case 0x0013:
  895.     subrsOffset = (int)op[0];
  896.     break;
  897.       case 0x0014:
  898.     defaultWidthX = op[0];
  899.     defaultWidthXFP = fp[0];
  900.     break;
  901.       case 0x0015:
  902.     nominalWidthX = op[0];
  903.     nominalWidthXFP = fp[0];
  904.     break;
  905.       default:
  906.     error(-1, R_UNKNOWN_TYPE_1C_PRIVATE_DICT_ENTRY__04X, key);
  907.     break;
  908.       }
  909.       i = 0;
  910.     } else {
  911.       x = getNum(&idxPtr0, &isFP);
  912.       if (i < 48) {
  913.     op[i] = x;
  914.     fp[i++] = isFP;
  915.       }
  916.     }
  917.   }
  918.  
  919.   // get subrs
  920.   if (subrsOffset != 0) {
  921.     topPtr += subrsOffset;
  922.     nSubrs = getWord(topPtr, 2);
  923.     idxOffSize = topPtr[2];
  924.     topPtr += 3;
  925.     sprintf(eBuf, "/Subrs %d array\n", nSubrs);
  926.     eexecWrite(eBuf);
  927.     idxStartPtr = topPtr + (nSubrs + 1) * idxOffSize - 1;
  928.     idxPtr1 = idxStartPtr + getWord(topPtr, idxOffSize);
  929.     for (i = 0; i < nSubrs; ++i) {
  930.       idxPtr0 = idxPtr1;
  931.       idxPtr1 = idxStartPtr + getWord(topPtr + (i+1)*idxOffSize, idxOffSize);
  932.       n = idxPtr1 - idxPtr0;
  933. #if 1 //~
  934.       error(-1, R_UNIMPLEMENTED_TYPE_2_SUBRS);
  935. #else
  936.       sprintf(eBuf, "dup %d %d RD ", i, n);
  937.       eexecWrite(eBuf);
  938.       cvtGlyph(idxPtr0, n);
  939.       eexecWrite(" NP\n");
  940. #endif
  941.     }
  942.     eexecWrite("ND\n");
  943.   }
  944.  
  945.   // get CharStrings
  946.   topPtr = (Guchar *)file + dict.charStrings;
  947.   nCharStrings = getWord(topPtr, 2);
  948.   idxOffSize = topPtr[2];
  949.   topPtr += 3;
  950.   sprintf(eBuf, "2 index /CharStrings %d dict dup begin\n", nCharStrings);
  951.   eexecWrite(eBuf);
  952.   idxStartPtr = topPtr + (nCharStrings + 1) * idxOffSize - 1;
  953.   idxPtr1 = idxStartPtr + getWord(topPtr, idxOffSize);
  954.   for (i = 0; i < nCharStrings; ++i) {
  955.     idxPtr0 = idxPtr1;
  956.     idxPtr1 = idxStartPtr + getWord(topPtr + (i+1)*idxOffSize, idxOffSize);
  957.     n = idxPtr1 - idxPtr0;
  958.     cvtGlyph(getString(glyphNames[i], stringIdxPtr, stringStartPtr,
  959.                stringOffSize, buf),
  960.          idxPtr0, n);
  961.   }
  962.   eexecWrite("end\n");
  963.   eexecWrite("end\n");
  964.   eexecWrite("readonly put\n");
  965.   eexecWrite("noaccess put\n");
  966.   eexecWrite("dup /FontName get exch definefont pop\n");
  967.   eexecWrite("mark currentfile closefile\n");
  968.  
  969.   // trailer
  970.   if (line > 0)
  971.     fputc('\n', out);
  972.   for (i = 0; i < 8; ++i) {
  973.     fprintf(out, "0000000000000000000000000000000000000000000000000000000000000000\n");
  974.   }
  975.   fprintf(out, "cleartomark\n");
  976.  
  977.   // clean up
  978.   if (dict.charset > 2)
  979.     CleanupStack::PopAndDestroy(); // glyphNames
  980.   CleanupStack::PopAndDestroy();   // fontName
  981. }
  982.  
  983. void Type1CFontConverter::eexecWrite(char *s) {
  984.   Guchar *p;
  985.   Guchar x;
  986.  
  987.   for (p = (Guchar *)s; *p; ++p) {
  988.     x = *p ^ (r1 >> 8);
  989.     r1 = (x + r1) * 52845 + 22719;
  990.     fputc(hexChars[x >> 4], out);
  991.     fputc(hexChars[x & 0x0f], out);
  992.     line += 2;
  993.     if (line == 64) {
  994.       fputc('\n', out);
  995.       line = 0;
  996.     }
  997.   }
  998. }
  999.  
  1000. void Type1CFontConverter::cvtGlyph(char *name, Guchar *s, int n) {
  1001.   int nHints;
  1002.   int x;
  1003.   GBool first = gTrue;
  1004.   char eBuf[256];
  1005.   double d, dx, dy;
  1006.   GBool dFP;
  1007.   int i, k;
  1008.  
  1009.   charBuf = GString::NewL();
  1010.   charBuf->appendL((char)73);
  1011.   charBuf->appendL((char)58);
  1012.   charBuf->appendL((Guchar)147);
  1013.   charBuf->appendL((Guchar)134);
  1014.  
  1015.   i = 0;
  1016.   nOps = 0;
  1017.   nHints = 0;
  1018.   while (i < n) {
  1019.     if (s[i] == 12) {
  1020.       switch (s[i+1]) {
  1021.       case 0:            // dotsection (should be Type 1 only?)
  1022.     //~ ignored
  1023.     break;
  1024.       case 34:            // hflex
  1025.     if (nOps != 7) {
  1026.       error(-1, R_WRONG_NUMBER_OF_ARGS___D__TO_TYPE_2_HFLEX, nOps);
  1027.     }
  1028.     eexecDumpNum(op[0], fp[0]);
  1029.     eexecDumpNum(0, gFalse);
  1030.     eexecDumpNum(op[1], fp[1]);
  1031.     eexecDumpNum(op[2], fp[2]);
  1032.     eexecDumpNum(op[3], fp[3]);
  1033.     eexecDumpNum(0, gFalse);
  1034.     eexecDumpOp1(8);
  1035.     eexecDumpNum(op[4], fp[4]);
  1036.     eexecDumpNum(0, gFalse);
  1037.     eexecDumpNum(op[5], fp[5]);
  1038.     eexecDumpNum(-op[2], fp[2]);
  1039.     eexecDumpNum(op[6], fp[6]);
  1040.     eexecDumpNum(0, gFalse);
  1041.     eexecDumpOp1(8);
  1042.     break;
  1043.       case 35:            // flex
  1044.     if (nOps != 13) {
  1045.       error(-1, R_WRONG_NUMBER_OF_ARGS___D__TO_TYPE_2_FLEX, nOps);
  1046.     }
  1047.     eexecDumpNum(op[0], fp[0]);
  1048.     eexecDumpNum(op[1], fp[1]);
  1049.     eexecDumpNum(op[2], fp[2]);
  1050.     eexecDumpNum(op[3], fp[3]);
  1051.     eexecDumpNum(op[4], fp[4]);
  1052.     eexecDumpNum(op[5], fp[5]);
  1053.     eexecDumpOp1(8);
  1054.     eexecDumpNum(op[6], fp[6]);
  1055.     eexecDumpNum(op[7], fp[7]);
  1056.     eexecDumpNum(op[8], fp[8]);
  1057.     eexecDumpNum(op[9], fp[9]);
  1058.     eexecDumpNum(op[10], fp[10]);
  1059.     eexecDumpNum(op[11], fp[11]);
  1060.     eexecDumpOp1(8);
  1061.     break;
  1062.       case 36:            // hflex1
  1063.     if (nOps != 9) {
  1064.       error(-1, R_WRONG_NUMBER_OF_ARGS___D__TO_TYPE_2_HFLEX1, nOps);
  1065.     }
  1066.     eexecDumpNum(op[0], fp[0]);
  1067.     eexecDumpNum(op[1], fp[1]);
  1068.     eexecDumpNum(op[2], fp[2]);
  1069.     eexecDumpNum(op[3], fp[3]);
  1070.     eexecDumpNum(op[4], fp[4]);
  1071.     eexecDumpNum(0, gFalse);
  1072.     eexecDumpOp1(8);
  1073.     eexecDumpNum(op[5], fp[5]);
  1074.     eexecDumpNum(0, gFalse);
  1075.     eexecDumpNum(op[6], fp[6]);
  1076.     eexecDumpNum(op[7], fp[7]);
  1077.     eexecDumpNum(op[8], fp[8]);
  1078.     eexecDumpNum(-(op[1] + op[3] + op[7]), fp[1] | fp[3] | fp[7]);
  1079.     eexecDumpOp1(8);
  1080.     break;
  1081.       case 37:            // flex1
  1082.     if (nOps != 11) {
  1083.       error(-1, R_WRONG_NUMBER_OF_ARGS___D__TO_TYPE_2_FLEX1, nOps);
  1084.     }
  1085.     eexecDumpNum(op[0], fp[0]);
  1086.     eexecDumpNum(op[1], fp[1]);
  1087.     eexecDumpNum(op[2], fp[2]);
  1088.     eexecDumpNum(op[3], fp[3]);
  1089.     eexecDumpNum(op[4], fp[4]);
  1090.     eexecDumpNum(op[5], fp[5]);
  1091.     eexecDumpOp1(8);
  1092.     eexecDumpNum(op[6], fp[6]);
  1093.     eexecDumpNum(op[7], fp[7]);
  1094.     eexecDumpNum(op[8], fp[8]);
  1095.     eexecDumpNum(op[9], fp[9]);
  1096.     dx = op[0] + op[2] + op[4] + op[6] + op[8];
  1097.     dy = op[1] + op[3] + op[5] + op[7] + op[9];
  1098.     if (fabs(dx) > fabs(dy)) {
  1099.       eexecDumpNum(op[10], fp[10]);
  1100.       eexecDumpNum(-dy, fp[1] | fp[3] | fp[5] | fp[7] | fp[9]);
  1101.     } else {
  1102.       eexecDumpNum(-dx, fp[0] | fp[2] | fp[4] | fp[6] | fp[8]);
  1103.       eexecDumpNum(op[10], fp[10]);
  1104.     }
  1105.     eexecDumpOp1(8);
  1106.     break;
  1107.       case 3:            // and
  1108.       case 4:            // or
  1109.       case 5:            // not
  1110.       case 8:            // store
  1111.       case 9:            // abs
  1112.       case 10:            // add
  1113.       case 11:            // sub
  1114.       case 12:            // div
  1115.       case 13:            // load
  1116.       case 14:            // neg
  1117.       case 15:            // eq
  1118.       case 18:            // drop
  1119.       case 20:            // put
  1120.       case 21:            // get
  1121.       case 22:            // ifelse
  1122.       case 23:            // random
  1123.       case 24:            // mul
  1124.       case 26:            // sqrt
  1125.       case 27:            // dup
  1126.       case 28:            // exch
  1127.       case 29:            // index
  1128.       case 30:            // roll
  1129.     error(-1, R_UNIMPLEMENTED_TYPE_2_CHARSTRING_OP__12__D, s[i+1]);
  1130.     break;
  1131.       default:
  1132.     error(-1, R_ILLEGAL_TYPE_2_CHARSTRING_OP__12__D, s[i+1]);
  1133.     break;
  1134.       }
  1135.       i += 2;
  1136.       nOps = 0;
  1137.     } else if (s[i] == 19) {    // hintmask
  1138.       //~ ignored
  1139.       if (first) {
  1140.     cvtGlyphWidth(nOps == 1);
  1141.     first = gFalse;
  1142.       }
  1143.       if (nOps > 0) {
  1144.     if (nOps & 1) {
  1145.       error(-1, R_WRONG_NUMBER_OF_ARGS___D__TO_TYPE_2_HINTMASK_VSTEMHM,
  1146.         nOps);
  1147.     }
  1148.     nHints += nOps / 2;
  1149.       }
  1150.       i += 1 + ((nHints + 7) >> 3);
  1151.       nOps = 0;
  1152.     } else if (s[i] == 20) {    // cntrmask
  1153.       //~ ignored
  1154.       if (first) {
  1155.     cvtGlyphWidth(nOps == 1);
  1156.     first = gFalse;
  1157.       }
  1158.       if (nOps > 0) {
  1159.     if (nOps & 1) {
  1160.       error(-1, R_WRONG_NUMBER_OF_ARGS___D__TO_TYPE_2_CNTRMASK_VSTEMHM,
  1161.         nOps);
  1162.     }
  1163.     nHints += nOps / 2;
  1164.       }
  1165.       i += 1 + ((nHints + 7) >> 3);
  1166.       nOps = 0;
  1167.     } else if (s[i] == 28) {
  1168.       x = (s[i+1] << 8) + s[i+2];
  1169.       if (x & 0x8000)
  1170.     x |= -1 << 15;
  1171.       if (nOps < 48) {
  1172.     fp[nOps] = gFalse;
  1173.     op[nOps++] = x;
  1174.       }
  1175.       i += 3;
  1176.     } else if (s[i] <= 31) {
  1177.       switch (s[i]) {
  1178.       case 4:            // vmoveto
  1179.     if (first) {
  1180.       cvtGlyphWidth(nOps == 2);
  1181.       first = gFalse;
  1182.     }
  1183.     if (nOps != 1)
  1184.       error(-1, R_WRONG_NUMBER_OF_ARGS___D__TO_TYPE_2_VMOVETO, nOps);
  1185.     eexecDumpNum(op[0], fp[0]);
  1186.     eexecDumpOp1(4);
  1187.     break;
  1188.       case 5:            // rlineto
  1189.     if (nOps < 2 || nOps % 2 != 0)
  1190.       error(-1, R_WRONG_NUMBER_OF_ARGS___D__TO_TYPE_2_RLINETO, nOps);
  1191.     for (k = 0; k < nOps; k += 2) {
  1192.       eexecDumpNum(op[k], fp[k]);
  1193.       eexecDumpNum(op[k+1], fp[k+1]);
  1194.       eexecDumpOp1(5);
  1195.     }
  1196.     break;
  1197.       case 6:            // hlineto
  1198.     if (nOps < 1)
  1199.       error(-1, R_WRONG_NUMBER_OF_ARGS___D__TO_TYPE_2_HLINETO, nOps);
  1200.     for (k = 0; k < nOps; ++k) {
  1201.       eexecDumpNum(op[k], fp[k]);
  1202.       eexecDumpOp1((k & 1) ? 7 : 6);
  1203.     }
  1204.     break;
  1205.       case 7:            // vlineto
  1206.     if (nOps < 1)
  1207.       error(-1, R_WRONG_NUMBER_OF_ARGS___D__TO_TYPE_2_VLINETO, nOps);
  1208.     for (k = 0; k < nOps; ++k) {
  1209.       eexecDumpNum(op[k], fp[k]);
  1210.       eexecDumpOp1((k & 1) ? 6 : 7);
  1211.     }
  1212.     break;
  1213.       case 8:            // rrcurveto
  1214.     if (nOps < 6 || nOps % 6 != 0)
  1215.       error(-1, R_WRONG_NUMBER_OF_ARGS___D__TO_TYPE_2_RRCURVETO, nOps);
  1216.     for (k = 0; k < nOps; k += 6) {
  1217.       eexecDumpNum(op[k], fp[k]);
  1218.       eexecDumpNum(op[k+1], fp[k+1]);
  1219.       eexecDumpNum(op[k+2], fp[k+2]);
  1220.       eexecDumpNum(op[k+3], fp[k+3]);
  1221.       eexecDumpNum(op[k+4], fp[k+4]);
  1222.       eexecDumpNum(op[k+5], fp[k+5]);
  1223.       eexecDumpOp1(8);
  1224.     }
  1225.     break;
  1226.       case 14:            // endchar / seac
  1227.     if (first) {
  1228.       cvtGlyphWidth(nOps == 1 || nOps == 5);
  1229.       first = gFalse;
  1230.     }
  1231.     if (nOps == 4) {
  1232.       eexecDumpNum(0, 0);
  1233.       eexecDumpNum(op[0], fp[0]);
  1234.       eexecDumpNum(op[1], fp[1]);
  1235.       eexecDumpNum(op[2], fp[2]);
  1236.       eexecDumpNum(op[3], fp[3]);
  1237.       eexecDumpOp2(6);
  1238.     } else if (nOps == 0) {
  1239.       eexecDumpOp1(14);
  1240.     } else {
  1241.       error(-1, R_WRONG_NUMBER_OF_ARGS___D__TO_TYPE_2_ENDCHAR, nOps);
  1242.     }
  1243.     break;
  1244.       case 21:            // rmoveto
  1245.     if (first) {
  1246.       cvtGlyphWidth(nOps == 3);
  1247.       first = gFalse;
  1248.     }
  1249.     if (nOps != 2)
  1250.       error(-1, R_WRONG_NUMBER_OF_ARGS___D__TO_TYPE_2_RMOVETO, nOps);
  1251.     eexecDumpNum(op[0], fp[0]);
  1252.     eexecDumpNum(op[1], fp[1]);
  1253.     eexecDumpOp1(21);
  1254.     break;
  1255.       case 22:            // hmoveto
  1256.     if (first) {
  1257.       cvtGlyphWidth(nOps == 2);
  1258.       first = gFalse;
  1259.     }
  1260.     if (nOps != 1)
  1261.       error(-1, R_WRONG_NUMBER_OF_ARGS___D__TO_TYPE_2_HMOVETO, nOps);
  1262.     eexecDumpNum(op[0], fp[0]);
  1263.     eexecDumpOp1(22);
  1264.     break;
  1265.       case 24:            // rcurveline
  1266.     if (nOps < 8 || (nOps - 2) % 6 != 0)
  1267.       error(-1, R_WRONG_NUMBER_OF_ARGS___D__TO_TYPE_2_RCURVELINE, nOps);
  1268.     for (k = 0; k < nOps - 2; k += 6) {
  1269.       eexecDumpNum(op[k], fp[k]);
  1270.       eexecDumpNum(op[k+1], fp[k+1]);
  1271.       eexecDumpNum(op[k+2], fp[k+2]);
  1272.       eexecDumpNum(op[k+3], fp[k+3]);
  1273.       eexecDumpNum(op[k+4], fp[k+4]);
  1274.       eexecDumpNum(op[k+5], fp[k+5]);
  1275.       eexecDumpOp1(8);
  1276.     }
  1277.     eexecDumpNum(op[k], fp[k]);
  1278.     eexecDumpNum(op[k+1], fp[k]);
  1279.     eexecDumpOp1(5);
  1280.     break;
  1281.       case 25:            // rlinecurve
  1282.     if (nOps < 8 || (nOps - 6) % 2 != 0)
  1283.       error(-1, R_WRONG_NUMBER_OF_ARGS___D__TO_TYPE_2_RLINECURVE, nOps);
  1284.     for (k = 0; k < nOps - 6; k += 2) {
  1285.       eexecDumpNum(op[k], fp[k]);
  1286.       eexecDumpNum(op[k+1], fp[k]);
  1287.       eexecDumpOp1(5);
  1288.     }
  1289.     eexecDumpNum(op[k], fp[k]);
  1290.     eexecDumpNum(op[k+1], fp[k+1]);
  1291.     eexecDumpNum(op[k+2], fp[k+2]);
  1292.     eexecDumpNum(op[k+3], fp[k+3]);
  1293.     eexecDumpNum(op[k+4], fp[k+4]);
  1294.     eexecDumpNum(op[k+5], fp[k+5]);
  1295.     eexecDumpOp1(8);
  1296.     break;
  1297.       case 26:            // vvcurveto
  1298.     if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0))
  1299.       error(-1, R_WRONG_NUMBER_OF_ARGS___D__TO_TYPE_2_VVCURVETO, nOps);
  1300.     if (nOps % 2 == 1) {
  1301.       eexecDumpNum(op[0], fp[0]);
  1302.       eexecDumpNum(op[1], fp[1]);
  1303.       eexecDumpNum(op[2], fp[2]);
  1304.       eexecDumpNum(op[3], fp[3]);
  1305.       eexecDumpNum(0, gFalse);
  1306.       eexecDumpNum(op[4], fp[4]);
  1307.       eexecDumpOp1(8);
  1308.       k = 5;
  1309.     } else {
  1310.       k = 0;
  1311.     }
  1312.     for (; k < nOps; k += 4) {
  1313.       eexecDumpNum(0, gFalse);
  1314.       eexecDumpNum(op[k], fp[k]);
  1315.       eexecDumpNum(op[k+1], fp[k+1]);
  1316.       eexecDumpNum(op[k+2], fp[k+2]);
  1317.       eexecDumpNum(0, gFalse);
  1318.       eexecDumpNum(op[k+3], fp[k+3]);
  1319.       eexecDumpOp1(8);
  1320.     }
  1321.     break;
  1322.       case 27:            // hhcurveto
  1323.     if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0))
  1324.       error(-1, R_WRONG_NUMBER_OF_ARGS___D__TO_TYPE_2_HHCURVETO, nOps);
  1325.     if (nOps % 2 == 1) {
  1326.       eexecDumpNum(op[1], fp[1]);
  1327.       eexecDumpNum(op[0], fp[0]);
  1328.       eexecDumpNum(op[2], fp[2]);
  1329.       eexecDumpNum(op[3], fp[3]);
  1330.       eexecDumpNum(op[4], fp[4]);
  1331.       eexecDumpNum(0, gFalse);
  1332.       eexecDumpOp1(8);
  1333.       k = 5;
  1334.     } else {
  1335.       k = 0;
  1336.     }
  1337.     for (; k < nOps; k += 4) {
  1338.       eexecDumpNum(op[k], fp[k]);
  1339.       eexecDumpNum(0, gFalse);
  1340.       eexecDumpNum(op[k+1], fp[k+1]);
  1341.       eexecDumpNum(op[k+2], fp[k+2]);
  1342.       eexecDumpNum(op[k+3], fp[k+3]);
  1343.       eexecDumpNum(0, gFalse);
  1344.       eexecDumpOp1(8);
  1345.     }
  1346.     break;
  1347.       case 30:            // vhcurveto
  1348.     if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0))
  1349.       error(-1, R_WRONG_NUMBER_OF_ARGS___D__TO_TYPE_2_VHCURVETO, nOps);
  1350.     for (k = 0; k < nOps && k != nOps-5; k += 4) {
  1351.       if (k % 8 == 0) {
  1352.         eexecDumpNum(op[k], fp[k]);
  1353.         eexecDumpNum(op[k+1], fp[k+1]);
  1354.         eexecDumpNum(op[k+2], fp[k+2]);
  1355.         eexecDumpNum(op[k+3], fp[k+3]);
  1356.         eexecDumpOp1(30);
  1357.       } else {
  1358.         eexecDumpNum(op[k], fp[k]);
  1359.         eexecDumpNum(op[k+1], fp[k+1]);
  1360.         eexecDumpNum(op[k+2], fp[k+2]);
  1361.         eexecDumpNum(op[k+3], fp[k+3]);
  1362.         eexecDumpOp1(31);
  1363.       }
  1364.     }
  1365.     if (k == nOps-5) {
  1366.       if (k % 8 == 0) {
  1367.         eexecDumpNum(0, gFalse);
  1368.         eexecDumpNum(op[k], fp[k]);
  1369.         eexecDumpNum(op[k+1], fp[k+1]);
  1370.         eexecDumpNum(op[k+2], fp[k+2]);
  1371.         eexecDumpNum(op[k+3], fp[k+3]);
  1372.         eexecDumpNum(op[k+4], fp[k+4]);
  1373.       } else {
  1374.         eexecDumpNum(op[k], fp[k]);
  1375.         eexecDumpNum(0, gFalse);
  1376.         eexecDumpNum(op[k+1], fp[k+1]);
  1377.         eexecDumpNum(op[k+2], fp[k+2]);
  1378.         eexecDumpNum(op[k+4], fp[k+4]);
  1379.         eexecDumpNum(op[k+3], fp[k+3]);
  1380.       }
  1381.       eexecDumpOp1(8);
  1382.     }
  1383.     break;
  1384.       case 31:            // hvcurveto
  1385.     if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0))
  1386.       error(-1, R_WRONG_NUMBER_OF_ARGS___D__TO_TYPE_2_HVCURVETO, nOps);
  1387.     for (k = 0; k < nOps && k != nOps-5; k += 4) {
  1388.       if (k % 8 == 0) {
  1389.         eexecDumpNum(op[k], fp[k]);
  1390.         eexecDumpNum(op[k+1], fp[k+1]);
  1391.         eexecDumpNum(op[k+2], fp[k+2]);
  1392.         eexecDumpNum(op[k+3], fp[k+3]);
  1393.         eexecDumpOp1(31);
  1394.       } else {
  1395.         eexecDumpNum(op[k], fp[k]);
  1396.         eexecDumpNum(op[k+1], fp[k+1]);
  1397.         eexecDumpNum(op[k+2], fp[k+2]);
  1398.         eexecDumpNum(op[k+3], fp[k+3]);
  1399.         eexecDumpOp1(30);
  1400.       }
  1401.     }
  1402.     if (k == nOps-5) {
  1403.       if (k % 8 == 0) {
  1404.         eexecDumpNum(op[k], fp[k]);
  1405.         eexecDumpNum(0, gFalse);
  1406.         eexecDumpNum(op[k+1], fp[k+1]);
  1407.         eexecDumpNum(op[k+2], fp[k+2]);
  1408.         eexecDumpNum(op[k+4], fp[k+4]);
  1409.         eexecDumpNum(op[k+3], fp[k+3]);
  1410.       } else {
  1411.         eexecDumpNum(0, gFalse);
  1412.         eexecDumpNum(op[k], fp[k]);
  1413.         eexecDumpNum(op[k+1], fp[k+1]);
  1414.         eexecDumpNum(op[k+2], fp[k+2]);
  1415.         eexecDumpNum(op[k+3], fp[k+3]);
  1416.         eexecDumpNum(op[k+4], fp[k+4]);
  1417.       }
  1418.       eexecDumpOp1(8);
  1419.     }
  1420.     break;
  1421.       case 1:            // hstem
  1422.     if (first) {
  1423.       cvtGlyphWidth(nOps & 1);
  1424.       first = gFalse;
  1425.     }
  1426.     if (nOps & 1) {
  1427.       error(-1, R_WRONG_NUMBER_OF_ARGS___D__TO_TYPE_2_HSTEM, nOps);
  1428.     }
  1429.     d = 0;
  1430.     dFP = gFalse;
  1431.     for (k = 0; k < nOps; k += 2) {
  1432.       if (op[k+1] < 0) {
  1433.         d += op[k] + op[k+1];
  1434.         dFP |= fp[k] | fp[k+1];
  1435.         eexecDumpNum(d, dFP);
  1436.         eexecDumpNum(-op[k+1], fp[k+1]);
  1437.       } else {
  1438.         d += op[k];
  1439.         dFP |= fp[k];
  1440.         eexecDumpNum(d, dFP);
  1441.         eexecDumpNum(op[k+1], fp[k+1]);
  1442.         d += op[k+1];
  1443.         dFP |= fp[k+1];
  1444.       }
  1445.       eexecDumpOp1(1);
  1446.     }
  1447.     nHints += nOps / 2;
  1448.     break;
  1449.       case 3:            // vstem
  1450.     if (first) {
  1451.       cvtGlyphWidth(nOps & 1);
  1452.       first = gFalse;
  1453.     }
  1454.     if (nOps & 1) {
  1455.       error(-1, R_WRONG_NUMBER_OF_ARGS___D__TO_TYPE_2_VSTEM, nOps);
  1456.     }
  1457.     d = 0;
  1458.     dFP = gFalse;
  1459.     for (k = 0; k < nOps; k += 2) {
  1460.       if (op[k+1] < 0) {
  1461.         d += op[k] + op[k+1];
  1462.         dFP |= fp[k] | fp[k+1];
  1463.         eexecDumpNum(d, dFP);
  1464.         eexecDumpNum(-op[k+1], fp[k+1]);
  1465.       } else {
  1466.         d += op[k];
  1467.         dFP |= fp[k];
  1468.         eexecDumpNum(d, dFP);
  1469.         eexecDumpNum(op[k+1], fp[k+1]);
  1470.         d += op[k+1];
  1471.         dFP |= fp[k+1];
  1472.       }
  1473.       eexecDumpOp1(3);
  1474.     }
  1475.     nHints += nOps / 2;
  1476.     break;
  1477.       case 18:            // hstemhm
  1478.     //~ ignored
  1479.     if (first) {
  1480.       cvtGlyphWidth(nOps & 1);
  1481.       first = gFalse;
  1482.     }
  1483.     if (nOps & 1) {
  1484.       error(-1, R_WRONG_NUMBER_OF_ARGS___D__TO_TYPE_2_HSTEMHM, nOps);
  1485.     }
  1486.     nHints += nOps / 2;
  1487.     break;
  1488.       case 23:            // vstemhm
  1489.     //~ ignored
  1490.     if (first) {
  1491.       cvtGlyphWidth(nOps & 1);
  1492.       first = gFalse;
  1493.     }
  1494.     if (nOps & 1) {
  1495.       error(-1, R_WRONG_NUMBER_OF_ARGS___D__TO_TYPE_2_VSTEMHM, nOps);
  1496.     }
  1497.     nHints += nOps / 2;
  1498.     break;
  1499.       case 10:            // callsubr
  1500.       case 11:            // return
  1501.       case 16:            // blend
  1502.       case 29:            // callgsubr
  1503.     error(-1, R_UNIMPLEMENTED_TYPE_2_CHARSTRING_OP__12__D, s[i]);
  1504.     break;
  1505.       default:
  1506.     error(-1, R_ILLEGAL_TYPE_2_CHARSTRING_OP__12__D, s[i]);
  1507.     break;
  1508.       }
  1509.       ++i;
  1510.       nOps = 0;
  1511.     } else if (s[i] <= 246) {
  1512.       if (nOps < 48) {
  1513.     fp[nOps] = gFalse;
  1514.     op[nOps++] = (int)s[i] - 139;
  1515.       }
  1516.       ++i;
  1517.     } else if (s[i] <= 250) {
  1518.       if (nOps < 48) {
  1519.     fp[nOps] = gFalse;
  1520.     op[nOps++] = (((int)s[i] - 247) << 8) + (int)s[i+1] + 108;
  1521.       }
  1522.       i += 2;
  1523.     } else if (s[i] <= 254) {
  1524.       if (nOps < 48) {
  1525.     fp[nOps] = gFalse;
  1526.     op[nOps++] = -(((int)s[i] - 251) << 8) - (int)s[i+1] - 108;
  1527.       }
  1528.       i += 2;
  1529.     } else {
  1530.       x = (s[i+1] << 24) | (s[i+2] << 16) | (s[i+3] << 8) | s[i+4];
  1531.       if (x & 0x80000000)
  1532.     x |= -1 << 31;
  1533.       if (nOps < 48) {
  1534.     fp[nOps] = gTrue;
  1535.     op[nOps++] = (double)x / 65536.0;
  1536.       }
  1537.       i += 5;
  1538.     }
  1539.   }
  1540.  
  1541.   sprintf(eBuf, "/%s %d RD ", name, charBuf->getLength());
  1542.   eexecWrite(eBuf);
  1543.   eexecWriteCharstring((Guchar *)charBuf->getCString(), charBuf->getLength());
  1544.   eexecWrite(" ND\n");
  1545.   delete charBuf;
  1546. }
  1547.  
  1548. void Type1CFontConverter::cvtGlyphWidth(GBool useOp) {
  1549.   double w;
  1550.   GBool wFP;
  1551.   int i;
  1552.  
  1553.   if (useOp) {
  1554.     w = nominalWidthX + op[0];
  1555.     wFP = nominalWidthXFP | fp[0];
  1556.     for (i = 1; i < nOps; ++i) {
  1557.       op[i-1] = op[i];
  1558.       fp[i-1] = fp[i];
  1559.     }
  1560.     --nOps;
  1561.   } else {
  1562.     w = defaultWidthX;
  1563.     wFP = defaultWidthXFP;
  1564.   }
  1565.   eexecDumpNum(0, gFalse);
  1566.   eexecDumpNum(w, wFP);
  1567.   eexecDumpOp1(13);
  1568. }
  1569.  
  1570. void Type1CFontConverter::eexecDumpNum(double x, GBool fp) {
  1571.   Guchar buf[12];
  1572.   int y, n;
  1573.  
  1574.   n = 0;
  1575.   if (fp) {
  1576.     if (x >= -32768 && x < 32768) {
  1577.       y = (int)(x * 256.0);
  1578.       buf[0] = 255;
  1579.       buf[1] = (Guchar)(y >> 24);
  1580.       buf[2] = (Guchar)(y >> 16);
  1581.       buf[3] = (Guchar)(y >> 8);
  1582.       buf[4] = (Guchar)y;
  1583.       buf[5] = 255;
  1584.       buf[6] = 0;
  1585.       buf[7] = 0;
  1586.       buf[8] = 1;
  1587.       buf[9] = 0;
  1588.       buf[10] = 12;
  1589.       buf[11] = 12;
  1590.       n = 12;
  1591.     } else {
  1592.       error(-1, R_TYPE_2_FIXED_POINT_CONSTANT_OUT_OF_RANGE);
  1593.     }
  1594.   } else {
  1595.     y = (int)x;
  1596.     if (y >= -107 && y <= 107) {
  1597.       buf[0] = (Guchar)(y + 139);
  1598.       n = 1;
  1599.     } else if (y > 107 && y <= 1131) {
  1600.       y -= 108;
  1601.       buf[0] = (Guchar)((y >> 8) + 247);
  1602.       buf[1] = (Guchar)(y & 0xff);
  1603.       n = 2;
  1604.     } else if (y < -107 && y >= -1131) {
  1605.       y = -y - 108;
  1606.       buf[0] = (Guchar)((y >> 8) + 251);
  1607.       buf[1] = (Guchar)(y & 0xff);
  1608.       n = 2;
  1609.     } else {
  1610.       buf[0] = 255;
  1611.       buf[1] = (Guchar)(y >> 24);
  1612.       buf[2] = (Guchar)(y >> 16);
  1613.       buf[3] = (Guchar)(y >> 8);
  1614.       buf[4] = (Guchar)y;
  1615.       n = 5;
  1616.     }
  1617.   }
  1618.   charBuf->appendL((char *)buf, n);
  1619. }
  1620.  
  1621. void Type1CFontConverter::eexecDumpOp1(int op) {
  1622.   charBuf->appendL((char)op);
  1623. }
  1624.  
  1625. void Type1CFontConverter::eexecDumpOp2(int op) {
  1626.   charBuf->appendL((char)12);
  1627.   charBuf->appendL((char)op);
  1628. }
  1629.  
  1630. void Type1CFontConverter::eexecWriteCharstring(Guchar *s, int n) {
  1631.   Gushort r2;
  1632.   Guchar x;
  1633.   int i;
  1634.  
  1635.   r2 = 4330;
  1636.  
  1637.   for (i = 0; i < n; ++i) {
  1638.     // charstring encryption
  1639.     x = s[i];
  1640.     x ^= (r2 >> 8);
  1641.     r2 = (x + r2) * 52845 + 22719;
  1642.  
  1643.     // eexec encryption
  1644.     x ^= (r1 >> 8);
  1645.     r1 = (x + r1) * 52845 + 22719;
  1646.     fputc(hexChars[x >> 4], out);
  1647.     fputc(hexChars[x & 0x0f], out);
  1648.     line += 2;
  1649.     if (line == 64) {
  1650.       fputc('\n', out);
  1651.       line = 0;
  1652.     }
  1653.   }
  1654. }
  1655.  
  1656. void Type1CFontConverter::getDeltaInt(char *buf, char *name, double *op,
  1657.                       int n) {
  1658.   int x, i;
  1659.  
  1660.   (void)sprintf(buf, "/%s [", name);
  1661.   buf += strlen(buf);
  1662.   x = 0;
  1663.   for (i = 0; i < n; ++i) {
  1664.     x += (int)op[i];
  1665.     (void)sprintf(buf, "%s%d", i > 0 ? " " : "", x);
  1666.     buf += strlen(buf);
  1667.   }
  1668.   sprintf(buf, "] def\n");
  1669. }
  1670.  
  1671. void Type1CFontConverter::getDeltaReal(char *buf, char *name, double *op,
  1672.                        int n) {
  1673.   double x;
  1674.   int i;
  1675.  
  1676.   (void)sprintf(buf, "/%s [", name);
  1677.   buf += strlen(buf); 
  1678.   x = 0;
  1679.   for (i = 0; i < n; ++i) {
  1680.     x += op[i];
  1681.     (void)sprintf(buf, "%s%g", i > 0 ? " " : "", x);
  1682.     buf += strlen(buf);
  1683.   }
  1684.   sprintf(buf, "] def\n");
  1685. }
  1686.  
  1687.  
  1688. #ifdef __SYMBIAN32__
  1689.  
  1690. #include "PDFGlobal.h"
  1691.  
  1692. StdFontInfoGlobal::StdFontInfoGlobal()
  1693.   type1StdEncoding = 0;
  1694.   type1ExpertEncoding = 0;
  1695. }
  1696.  
  1697. TInt StdFontInfoGlobal::Construct()
  1698.   type1StdEncoding = new FontEncoding();
  1699.   if (!type1StdEncoding)
  1700.     return KErrNoMemory;
  1701.   
  1702.   type1StdEncoding->Construct(type1StdEncodingNames, type1StdEncodingSize);
  1703.   
  1704.   type1ExpertEncoding = new FontEncoding ();
  1705.   if (!type1ExpertEncoding)
  1706.     return KErrNoMemory;
  1707.  
  1708.   type1ExpertEncoding->Construct(type1ExpertEncodingNames, type1ExpertEncodingSize);
  1709.  
  1710.   return KErrNone;
  1711. }
  1712.  
  1713.  
  1714. StdFontInfoGlobal::~StdFontInfoGlobal()
  1715. {
  1716.   delete type1StdEncoding; 
  1717.   delete type1ExpertEncoding;
  1718. }
  1719.  
  1720. #endif