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

  1. //========================================================================
  2. //
  3. // GfxFont.cc
  4. //
  5. // Copyright 1996 Derek B. Noonburg
  6. //
  7. //========================================================================
  8. //
  9. // Ported to EPOC by Sander van der Wal
  10. //
  11. // $Log: GfxFont.cpp $
  12. // Revision 1.4  2000-09-24 21:10:09+02  svdwal
  13. // Memory leak fixed
  14. //
  15. // Revision 1.3  2000-09-21 14:51:12+02  svdwal
  16. // Some xpdf 0.91 bugfixes added
  17. //
  18. // Revision 1.2  2000-09-17 13:38:23+02  svdwal
  19. // Ported
  20. //
  21.  
  22. #ifdef __GNUC__
  23. #pragma implementation
  24. #endif
  25.  
  26. #ifdef __E32DEF_H__
  27. #include <e32def.h> // remove warning about NULL redefinition
  28. #endif
  29.  
  30. #include "GString.h"
  31. #include "gmem.h"
  32. #include "gfile.h"
  33.  
  34. #include "config.h"
  35. #include "Object.h"
  36. #include "Array.h"
  37. #include "Dict.h"
  38. #include "Error.h"
  39. #include "FontFile.h"
  40. #include "Stream.h"
  41. #include "GfxFont.h"
  42.  
  43. #if JAPANESE_SUPPORT
  44. #include "Japan12CMapInfo.h"
  45. #endif
  46.  
  47. #include "PDFGlobal.h"
  48. #include "Pdf.rsg"
  49. #include "PROFILE.h"
  50.  
  51.  
  52. //------------------------------------------------------------------------
  53.  
  54. static int CDECL cmpWidthExcep(const void *w1, const void *w2);
  55. static int CDECL cmpWidthExcepV(const void *w1, const void *w2);
  56.  
  57. //------------------------------------------------------------------------
  58.  
  59. static const Gushort* const defCharWidths[12] = {
  60.   courierWidths,
  61.   courierObliqueWidths,
  62.   courierBoldWidths,
  63.   courierBoldObliqueWidths,
  64.   helveticaWidths,
  65.   helveticaObliqueWidths,
  66.   helveticaBoldWidths,
  67.   helveticaBoldObliqueWidths,
  68.   timesRomanWidths,
  69.   timesItalicWidths,
  70.   timesBoldWidths,
  71.   timesBoldItalicWidths
  72. };
  73.  
  74. //------------------------------------------------------------------------
  75. // GfxFont
  76. //------------------------------------------------------------------------
  77.  
  78. GfxFont::GfxFont() {}
  79.  
  80. void GfxFont::ConstructL(char *tag1, Ref id1, Dict *fontDict) {
  81.   BuiltinFont *builtinFont;
  82.   RAutoObject obj1, obj2;
  83.   int missingWidth;
  84.   char *name2, *p;
  85.  
  86.   // get font tag and ID
  87.   tag = GString::NewL(tag1);
  88.   id = id1;
  89.  
  90.   // get base font name
  91.   name = NULL;
  92.   fontDict->lookupL("BaseFont", &obj1);
  93.   if (obj1.isName())
  94.     name = GString::NewL(obj1.getName());
  95.   obj1.free();
  96.  
  97.   // get font type
  98.   fontDict->lookupL("Subtype", &obj1);
  99.   if (obj1.isName("Type1"))
  100.     type = fontType1;
  101.   else if (obj1.isName("Type1C"))
  102.     type = fontType1C;
  103.   else if (obj1.isName("Type3"))
  104.     type = fontType3;
  105.   else if (obj1.isName("TrueType"))
  106.     type = fontTrueType;
  107.   else if (obj1.isName("Type0"))
  108.     type = fontType0;
  109.   else
  110.     type = fontUnknownType;
  111.   obj1.free();
  112.   is16 = gFalse;
  113.  
  114.   // is it a built-in font?
  115.   builtinFont = NULL;
  116.   if (name && (type == fontType1)) {
  117.     BuiltinFont (&builtinFonts)[14] = Global().GfxFont.builtinFonts;
  118.     for (register int i = 0; i < numBuiltinFonts; ++i) {
  119.       if (!strcmp(builtinFonts[i].name, name->getCString())) {
  120.         builtinFont = &builtinFonts[i];
  121.         break;
  122.       }
  123.     }
  124.   }  
  125.  
  126.   // assume Times-Roman forby default (for substitution purposes)
  127.   flags = fontSerif;
  128.   
  129.   // Newer Adobe tools are using Base14-compatible TrueType fonts
  130.   // without embedding them, so munge the names into the equivalent
  131.   // PostScript names.  This is a kludge -- it would be nice if Adobe
  132.   // followed their own spec.
  133.   if (type == fontTrueType) {
  134.     p = name->getCString();
  135.     name2 = NULL;
  136.     if (!strncmp(p, "Arial", 5)) {
  137.       if (!strcmp(p+5, ",Bold")) {
  138.     name2 = "Helvetica-Bold";
  139.       } else if (!strcmp(p+5, "Italic")) {
  140.     name2 = "Helvetica-Oblique";
  141.       } else if (!strcmp(p+5, "BoldItalic")) {
  142.     name2 = "Helvetica-BoldOblique";
  143.       } else {
  144.     name2 = "Helvetica";
  145.       }
  146.     } else if (!strncmp(p, "TimesNewRoman", 13)) {
  147.       if (!strcmp(p+5, ",Bold")) {
  148.     name2 = "Times-Bold";
  149.       } else if (!strcmp(p+5, "Italic")) {
  150.     name2 = "Times-Italic";
  151.       } else if (!strcmp(p+5, "BoldItalic")) {
  152.     name2 = "Times-BoldItalic";
  153.       } else {
  154.     name2 = "Times-Roman";
  155.       }
  156.     } else if (!strncmp(p, "CourierNew", 10)) {
  157.       if (!strcmp(p+5, ",Bold")) {
  158.     name2 = "Courier-Bold";
  159.       } else if (!strcmp(p+5, "Italic")) {
  160.     name2 = "Courier-Oblique";
  161.       } else if (!strcmp(p+5, "BoldItalic")) {
  162.     name2 = "Courier-BoldOblique";
  163.       } else {
  164.     name2 = "Courier";
  165.       }
  166.     }
  167.     if (name2) {
  168.       delete name;
  169.       name = 0;
  170.       name = GString::NewL(name2);
  171.     }
  172.   }
  173.  
  174.   // get info from font descriptor
  175.   embFontName = NULL;
  176.   embFontID.num = -1;
  177.   embFontID.gen = -1;
  178.   missingWidth = 0;
  179.   fontDict->lookupL("FontDescriptor", &obj1);
  180.   if (obj1.isDict()) {
  181.  
  182.     // get flags
  183.     obj1.dictLookupL("Flags", &obj2);
  184.     if (obj2.isInt())
  185.       flags = obj2.getInt();
  186.     obj2.free();
  187.  
  188.     // get name
  189.     obj1.dictLookupL("FontName", &obj2);
  190.     if (obj2.isName())
  191.       embFontName = GString::NewL(obj2.getName());
  192.     obj2.free();
  193.  
  194.     // look for embedded font file
  195.     if (type == fontType1) {
  196.       obj1.dictLookupNFL("FontFile", &obj2);
  197.       if (obj2.isRef())
  198.     embFontID = obj2.getRef();
  199.       obj2.free();
  200.     }
  201.     if (embFontID.num == -1 && type == fontTrueType) {
  202.       obj1.dictLookupNFL("FontFile2", &obj2);
  203.       if (obj2.isRef())
  204.     embFontID = obj2.getRef();
  205.       obj2.free();
  206.     }
  207.     if (embFontID.num == -1) {
  208.       obj1.dictLookupNFL("FontFile3", &obj2);
  209.       if (obj2.isRef()) {
  210.         RAutoObject obj3, obj4;
  211.     embFontID = obj2.getRef();
  212.     obj2.fetchL(&obj3);
  213.     if (obj3.isStream()) {
  214.       obj3.streamGetDict()->lookupL("Subtype", &obj4);
  215.       if (obj4.isName("Type1"))
  216.         type = fontType1;
  217.       else if (obj4.isName("Type1C"))
  218.         type = fontType1C;
  219.       else if (obj4.isName("Type3"))
  220.         type = fontType3;
  221.       else if (obj4.isName("TrueType"))
  222.         type = fontTrueType;
  223.       else if (obj4.isName("Type0"))
  224.         type = fontType0;
  225.       obj4.free();
  226.     }
  227.     obj3.free();
  228.       }
  229.       obj2.free();
  230.     }
  231.  
  232.     // look for MissingWidth
  233.     obj1.dictLookupL("MissingWidth", &obj2);
  234.     if (obj2.isInt()) {
  235.       missingWidth = obj2.getInt();
  236.     }
  237.     obj2.free();
  238.   }
  239.   obj1.free();
  240.  
  241.   // look for an external font file
  242.   extFontFile = NULL;
  243.   if (type == fontType1 && name)
  244.     findExtFontFile();
  245.  
  246.   // get font matrix
  247.   fontMat[0] = fontMat[3] = 1;
  248.   fontMat[1] = fontMat[2] = fontMat[4] = fontMat[5] = 0;
  249.   if (fontDict->lookupL("FontMatrix", &obj1)->isArray()) {
  250.     for (register int i = 0; i < 6 && i < obj1.arrayGetLength(); ++i) {
  251.       if (obj1.arrayGetL(i, &obj2)->isNum())
  252.     fontMat[i] = obj2.getNum();
  253.       obj2.free();
  254.     }
  255.   }
  256.   obj1.free();
  257.  
  258.   // get encoding and character widths
  259.   if (type == fontType0)
  260.     getType0EncAndWidths(fontDict);
  261.   else
  262.     getEncAndWidths(fontDict, builtinFont, missingWidth);
  263. }
  264.  
  265. GfxFont::~GfxFont() {
  266.   delete tag;
  267.   delete name;
  268.   if (!is16)
  269.     delete encoding;
  270.   delete embFontName;
  271.   delete extFontFile;
  272.   if (is16) {
  273.     User::Free(widths16.exceps);
  274.     User::Free(widths16.excepsV);
  275.   }
  276. }
  277.  
  278. double GfxFont::getWidth(GString *s) {
  279.   
  280.   PROFILE_START(GFXFONT__GETWIDTH);
  281.   
  282.   double w = 0;
  283.  
  284.   w = 0;
  285.   int len = s->getLength();
  286.   for (int i = 0; i < len; ++i)
  287.     w += widths[s->getChar(i) & 0xff];
  288.  
  289.   PROFILE_STOP(GFXFONT__GETWIDTH);
  290.  
  291.   return w;
  292. }
  293.  
  294. double GfxFont::getWidth16(int c) {
  295.   double w;
  296.   int a, b, m;
  297.  
  298.   w = widths16.defWidth;
  299.   a = -1;
  300.   b = widths16.numExceps;
  301.   // invariant: widths16.exceps[a].last < c < widths16.exceps[b].first
  302.   while (b - a > 1) {
  303.     m = (a + b) / 2;
  304.     if (widths16.exceps[m].last < c) {
  305.       a = m;
  306.     } else if (c < widths16.exceps[m].first) {
  307.       b = m;
  308.     } else {
  309.       w = widths16.exceps[m].width;
  310.       break;
  311.     }
  312.   }
  313.   return w;
  314. }
  315.  
  316. double GfxFont::getHeight16(int c) {
  317.   double h;
  318.   int a, b, m;
  319.  
  320.   h = widths16.defHeight;
  321.   a = -1;
  322.   b = widths16.numExcepsV;
  323.   // invariant: widths16.excepsV[a].last < c < widths16.excepsV[b].first
  324.   while (b - a > 1) {
  325.     m = (a + b) / 2;
  326.     if (widths16.excepsV[m].last < c) {
  327.       a = m;
  328.     } else if (c < widths16.excepsV[m].first) {
  329.       b = m;
  330.     } else {
  331.       h = widths16.excepsV[m].height;
  332.       break;
  333.     }
  334.   }
  335.   return h;
  336. }
  337.  
  338. double GfxFont::getOriginX16(int c) {
  339.   double vx;
  340.   int a, b, m;
  341.  
  342.   vx = widths16.defWidth / 2;
  343.   a = -1;
  344.   b = widths16.numExcepsV;
  345.   // invariant: widths16.excepsV[a].last < c < widths16.excepsV[b].first
  346.   while (b - a > 1) {
  347.     m = (a + b) / 2;
  348.     if (widths16.excepsV[m].last < c) {
  349.       a = m;
  350.     } else if (c < widths16.excepsV[m].first) {
  351.       b = m;
  352.     } else {
  353.       vx = widths16.excepsV[m].vx;
  354.       break;
  355.     }
  356.   }
  357.   return vx;
  358. }
  359.  
  360. double GfxFont::getOriginY16(int c) {
  361.   double vy;
  362.   int a, b, m;
  363.  
  364.   vy = widths16.defVY;
  365.   a = -1;
  366.   b = widths16.numExcepsV;
  367.   // invariant: widths16.excepsV[a].last < c < widths16.excepsV[b].first
  368.   while (b - a > 1) {
  369.     m = (a + b) / 2;
  370.     if (widths16.excepsV[m].last < c) {
  371.       a = m;
  372.     } else if (c < widths16.excepsV[m].first) {
  373.       b = m;
  374.     } else {
  375.       vy = widths16.excepsV[m].vy;
  376.       break;
  377.     }
  378.   }
  379.   return vy;
  380. }
  381.  
  382. void GfxFont::getEncAndWidths(Dict *fontDict, BuiltinFont *builtinFont,
  383.                              int missingWidth) {
  384.   RAutoObject obj1, obj2;
  385.   FontFile *fontFile;
  386.  
  387.   // Encodings start with a base encoding, which can come from
  388.   // (in order of priority):
  389.   //   1. FontDict.Encoding or FontDict.Encoding.BaseEncoding
  390.   //        - MacRoman / WinAnsi / Standard
  391.   //   2. embedded font file
  392.   //   3. default:
  393.   //        - builtin --> builtin encoding
  394.   //        - TrueType --> MacRomanEncoding
  395.   //        - others --> StandardEncoding
  396.   // and then add a list of differences from
  397.   // FontDict.Encoding.Differences.
  398.  
  399.   // check FontDict for base encoding
  400.   encoding = NULL;
  401.   fontDict->lookupL("Encoding", &obj1);
  402.   if (obj1.isDict()) {
  403.     obj1.dictLookupL("BaseEncoding", &obj2);
  404.     if (obj2.isName()) {
  405.       if (obj2.isName("MacRomanEncoding")) {
  406.         encoding = Global().GfxFont.macRomanEncoding->copyL();
  407.       } else if (obj2.isName("WinAnsiEncoding")) {
  408.         encoding = Global().GfxFont.winAnsiEncoding->copyL();
  409.       } else if (obj2.isName("StandardEncoding")) {
  410.         encoding = Global().GfxFont.standardEncoding->copyL();
  411.       }
  412.     }
  413.     obj2.free();
  414.   } else if (obj1.isName("MacRomanEncoding")) {
  415.     encoding = Global().GfxFont.macRomanEncoding->copyL();
  416.   } else if (obj1.isName("WinAnsiEncoding")) {
  417.     encoding = Global().GfxFont.winAnsiEncoding->copyL();
  418.   } else if (obj1.isName("StandardEncoding")) {
  419.     encoding = Global().GfxFont.standardEncoding->copyL();
  420.   }
  421.   obj1.free();
  422.  
  423.   // check embedded or external font file for base encoding
  424.   if ((type == fontType1 || type == fontType1C) &&
  425.       (extFontFile || embFontID.num >= 0)) {
  426.     int len;
  427.     char *buf = extFontFile ? readExtFontFileL(&len) : readEmbFontFileL(&len);
  428.     if (buf) {
  429.       CleanupStack::PushL(buf);
  430.       if (type == fontType1)
  431.         fontFile = Type1FontFile::NewLC(buf, len);
  432.       else
  433.         fontFile = Type1CFontFile::NewLC(buf, len);
  434.  
  435.       if (fontFile->getName()) {
  436.         delete embFontName;
  437.         embFontName=0;
  438.         embFontName = GString::NewL(fontFile->getName());
  439.       }
  440.       if (!encoding)
  441.     encoding = fontFile->getEncoding(gTrue);
  442.       CleanupStack::PopAndDestroy(); // delete fontFile;
  443.       CleanupStack::Pop(); // buf
  444.       User::Free(buf);
  445.     }
  446.   }
  447.  
  448.   // get default base encoding
  449.   if (!encoding) {
  450.     if (builtinFont)
  451.       encoding = builtinFont->encoding->copyL();
  452.     else if (type == fontTrueType)
  453.       encoding = Global().GfxFont.macRomanEncoding->copyL();
  454.     else
  455.       encoding = Global().GfxFont.standardEncoding->copyL();
  456.   }
  457.  
  458.   // merge differences into encoding
  459.   fontDict->lookupL("Encoding", &obj1);
  460.   if (obj1.isDict()) {
  461.     obj1.dictLookupL("Differences", &obj2);
  462.     if (obj2.isArray()) {
  463.       RAutoObject obj3;
  464.       int code = 0;
  465.       for (int i = 0; i < obj2.arrayGetLength(); ++i) {
  466.     obj2.arrayGetL(i, &obj3);
  467.     if (obj3.isInt()) {
  468.       code = obj3.getInt();
  469.     } else if (obj3.isName()) {
  470.       if (code < 256)
  471.         encoding->addChar(code, copyStringL(obj3.getName()));
  472.       ++code;
  473.     } else {
  474.       error(-1, R_WRONG_TYPE_IN_FONT_ENCODING_RESOURCE_DIFFERENCES___S_, obj3.getTypeName());
  475.     }
  476.     obj3.free();
  477.       }
  478.     }
  479.     obj2.free();
  480.   }
  481.   obj1.free();
  482.  
  483.   // get character widths
  484.   if (builtinFont)
  485.     makeWidths(fontDict, builtinFont->encoding, builtinFont->widths, missingWidth);
  486.   else
  487.     makeWidths(fontDict, NULL, NULL, missingWidth);
  488. }
  489.  
  490. void GfxFont::findExtFontFile() {
  491. #if 0
  492.   char **path;
  493.   FILE *f;
  494.   for (path = fontPath; *path; ++path) {
  495.     extFontFile = appendToPath(new(ELeave) GString(*path), name->getCString());
  496.     f = fopen(extFontFile->getCString(), "rb");
  497.     if (!f) {
  498.       extFontFile->append(".pfb");
  499.       f = fopen(extFontFile->getCString(), "rb");
  500.     }
  501.     if (!f) {
  502.       extFontFile->del(extFontFile->getLength() - 4, 4);
  503.       extFontFile->append(".pfa");
  504.       f = fopen(extFontFile->getCString(), "rb");
  505.     }
  506.     if (f) {
  507.       fclose(f);
  508.       break;
  509.     }
  510.     delete extFontFile;
  511.     extFontFile = NULL;
  512.   }
  513. #else
  514.   extFontFile = NULL;
  515. #endif
  516. }
  517.  
  518. char *GfxFont::readExtFontFileL(int* /*len*/){
  519. #if 0
  520.   TText8 *buf = 0;
  521.   RFs session;
  522.   CleanupClosePushL(session);
  523.  
  524.   RFile f;
  525.   CleanupClosePushL(f);
  526.  
  527.   session.Connect();
  528.   
  529.   TInt err = f.Open(session, *extFontFile, EFileStream|EFileRead);
  530.   if (err) {
  531.     if (err != KErrNoMemory)
  532.       error(-1, R_INTERNAL__EXTERNAL_FONT_FILE_VANISHED, extFontFile->Ptr());
  533.     User::Leave(err);
  534.   }
  535.   User::LeaveIfError(f.Size(*len));
  536.   buf = (TText8 *)User::AllocLC(*len);
  537.   err = f.Read(TPtr8(buf, *len, *len));
  538.   if (err) {
  539.     error(-1, R_ERROR_READING_EXTERNAL_FONT_FILE);
  540.     User::Leave(err);
  541.   }
  542.  
  543.   CleanupStack::PopAndDestroy(2); // f, session
  544.   return (char*) buf;
  545. #else
  546.   return 0;
  547. #endif
  548. }
  549.  
  550. char *GfxFont::readEmbFontFileL(int *len) {
  551.   char *buf;
  552.   RAutoObject obj1, obj2;
  553.   Stream *str;
  554.   int c;
  555.   int size, i;
  556.  
  557.   obj1.initRef(embFontID.num, embFontID.gen);
  558.   obj1.fetchL(&obj2);
  559.   if (!obj2.isStream()) {
  560.     error(-1, R_EMBEDDED_FONT_FILE_IS_NOT_A_STREAM);
  561.     obj2.free();
  562.     obj1.free();
  563.     embFontID.num = -1;
  564.     return NULL;
  565.   }
  566.   str = obj2.getStream();
  567.  
  568.   i = 0;
  569.   size = 4096;
  570.   buf = (char*) User::AllocLC(size);
  571.   str->reset();
  572.   while ((c = str->getChar()) != EOF) {
  573.     if (i == size) {
  574.       size += 4096;
  575.       buf = (char *)User::ReAllocL(buf, size);
  576.     }
  577.     buf[i++] = (char)c;
  578.   }
  579.   *len = i;
  580.   CleanupStack::Pop(); // buf 
  581.   obj2.free();
  582.   obj1.free();
  583.  
  584.   return buf;
  585. }
  586.  
  587. void GfxFont::makeWidths(Dict *fontDict, FontEncoding *builtinEncoding,
  588.              Gushort *builtinWidths, int missingWidth) {
  589.   register int code, code2;
  590.   register const char *charName; 
  591.  
  592.   // initialize all widths
  593.   double m = missingWidth * 0.001;
  594.   for (code = 0; code < 256; ++code) {
  595.     widths[code] = m;
  596.   }
  597.   
  598.   // use widths from built-in font
  599.   if (builtinEncoding) {
  600.     code2 = 0; // to make gcc happy
  601.     for (code = 0; code < 256; ++code) {
  602.       charName = encoding->getCharName(code);
  603.       if (charName) {
  604.         code2 = builtinEncoding->getCharCode(charName);
  605.         if (code2 >= 0)
  606.           widths[code] = builtinWidths[code2] * 0.001;
  607.       }
  608.     }
  609.   } 
  610.   else {
  611.     // get widths from font dict
  612.     RAutoObject obj1, obj2;
  613.     int firstChar, lastChar;
  614.     fontDict->lookupL("FirstChar", &obj1);
  615.     firstChar = obj1.isInt() ? obj1.getInt() : 0;
  616.     obj1.free();
  617.     fontDict->lookupL("LastChar", &obj1);
  618.     lastChar = obj1.isInt() ? obj1.getInt() : 255;
  619.     obj1.free();
  620.     double mult;
  621.     if (type == fontType3)
  622.       mult = fontMat[0];
  623.     else
  624.       mult = 0.001;
  625.     fontDict->lookupL("Widths", &obj1);
  626.     if (obj1.isArray()) {
  627.       for (code = firstChar; code <= lastChar; ++code) {
  628.     obj1.arrayGetL(code - firstChar, &obj2);
  629.         if (obj2.isNum())
  630.           widths[code] = obj2.getNum() * mult;
  631.     obj2.free();
  632.       }
  633.     } else {
  634.  
  635.       // couldn't find widths -- use defaults 
  636. #if 0 //~
  637.       //~ certain PDF generators apparently don't include widths
  638.       //~ for Arial and TimesNewRoman -- and this error message
  639.       //~ is a nuisance
  640.       error(-1, "No character widths resource for non-builtin font");
  641. #endif
  642.       int index;
  643.       if (isFixedWidth())
  644.         index = 0;
  645.       else if (isSerif())
  646.         index = 8;
  647.       else
  648.         index = 4;
  649.       if (isBold())
  650.         index += 2;
  651.       if (isItalic())
  652.         index += 1;
  653.       const Gushort *defWidths = defCharWidths[index];
  654.       code2 = 0; // to make gcc happy
  655.       for (code = 0; code < 256; ++code) {
  656.         widths[code] = 0;
  657.         charName = encoding->getCharName(code);
  658.         if (charName) {
  659.           code2 = Global().GfxFont.standardEncoding->getCharCode(charName);
  660.           if (code2 >= 0)
  661.             widths[code] = defWidths[code2] * 0.001;
  662.         }
  663.       }
  664.     }
  665.     obj1.free();
  666.   }
  667. }
  668.  
  669. void GfxFont::getType0EncAndWidths(Dict *fontDict) {
  670.   RAutoObject obj1, obj2, obj3, obj4, obj5;
  671.   int excepsSize;
  672.   int i, j, k, n;
  673.  
  674.   widths16.exceps = NULL;
  675.   widths16.excepsV = NULL;
  676.  
  677.   // get the CIDFont
  678.   fontDict->lookupL("DescendantFonts", &obj1);
  679.   if (!obj1.isArray() || obj1.arrayGetLength() != 1) {
  680.     error(-1, R_BAD_DESCENDANTFONTS_ENTRY_FOR_TYPE_0_FONT);
  681.     goto err1;
  682.   }
  683.   obj1.arrayGetL(0, &obj2);
  684.   if (!obj2.isDict()) {
  685.     error(-1, R_BAD_DESCENDANT_FONT_OF_TYPE_0_FONT);
  686.     goto err2;
  687.   }
  688.  
  689.   // get font info
  690.   obj2.dictLookupL("CIDSystemInfo", &obj3);
  691.   if (!obj3.isDict()) {
  692.     error(-1, R_BAD_CIDSYSTEMINFO_IN_TYPE_0_FONT_DESCENDANT);
  693.     goto err3;
  694.   }
  695.   obj3.dictLookupL("Registry", &obj4);
  696.   obj3.dictLookupL("Ordering", &obj5);
  697.   if (obj4.isString() && obj5.isString()) {
  698.     if (obj4.getString()->cmp("Adobe") == 0 &&
  699.     obj5.getString()->cmp("Japan1") == 0) {
  700. #if JAPANESE_SUPPORT
  701.       is16 = gTrue;
  702.       enc16.charSet = font16AdobeJapan12;
  703. #else
  704.       error(-1, R_PDF_WAS_COMPILED_WITHOUT_JAPANESE_FONT_SUPPORT);
  705.       goto err4;
  706. #endif
  707.     } else {
  708.       error(-1, R_UNKNOWN_TYPE_0_CHARACTER_SET___S__S,
  709.         obj4.getString()->getCString(), obj5.getString()->getCString());
  710.       goto err4;
  711.     }
  712.   } else {
  713.     error(-1, R_UNKNOWN_TYPE_0_CHARACTER_SET);
  714.     goto err4;
  715.   }
  716.   obj5.free();
  717.   obj4.free();
  718.   obj3.free();
  719.  
  720.   // get default char width
  721.   obj2.dictLookupL("DW", &obj3);
  722.   if (obj3.isInt())
  723.     widths16.defWidth = obj3.getInt() * 0.001;
  724.   else
  725.     widths16.defWidth = 1.0;
  726.   obj3.free();
  727.  
  728.   // get default char metrics for vertical font
  729.   obj2.dictLookupL("DW2", &obj3);
  730.   widths16.defVY = 0.880;
  731.   widths16.defHeight = -1;
  732.   if (obj3.isArray() && obj3.arrayGetLength() == 2) {
  733.     obj3.arrayGetL(0, &obj4);
  734.     if (obj4.isInt()) {
  735.       widths16.defVY = obj4.getInt() * 0.001;
  736.     }
  737.     obj4.free();
  738.     obj3.arrayGetL(1, &obj4);
  739.     if (obj4.isInt()) {
  740.       widths16.defHeight = obj4.getInt() * 0.001;
  741.     }
  742.     obj4.free();
  743.   }
  744.   obj3.free();
  745.  
  746.   // get char width exceptions
  747.   widths16.exceps = NULL;
  748.   widths16.numExceps = 0;
  749.   obj2.dictLookupL("W", &obj3);
  750.   if (obj3.isArray()) {
  751.     RAutoObject obj6, obj7, obj8;
  752.     excepsSize = 0;
  753.     k = 0;
  754.     i = 0;
  755.     while (i+1 < obj3.arrayGetLength()) {
  756.       obj3.arrayGetL(i, &obj4);
  757.       obj3.arrayGetL(i+1, &obj5);
  758.       if (obj4.isInt() && obj5.isInt()) {
  759.     obj3.arrayGetL(i+2, &obj6);
  760.     if (!obj6.isNum()) {
  761.       error(-1, R_BAD_WIDTHS_ARRAY_IN_TYPE_0_FONT);
  762.       obj6.free();
  763.       obj5.free();
  764.       obj4.free();
  765.       break;
  766.     }
  767.     if (k == excepsSize) {
  768.       excepsSize += 16;
  769.       widths16.exceps = (GfxFontWidthExcep *)
  770.             User::ReAllocL(widths16.exceps, excepsSize * sizeof(GfxFontWidthExcep));
  771.     }
  772.     widths16.exceps[k].first = obj4.getInt();
  773.     widths16.exceps[k].last = obj5.getInt();
  774.     widths16.exceps[k].width = obj6.getNum() * 0.001;
  775.     obj6.free();
  776.     ++k;
  777.     i += 3;
  778.       } else if (obj4.isInt() && obj5.isArray()) {
  779.     if (k + obj5.arrayGetLength() >= excepsSize) {
  780.       excepsSize = (k + obj5.arrayGetLength() + 15) & ~15;
  781.       widths16.exceps = (GfxFontWidthExcep *)
  782.             User::ReAllocL(widths16.exceps, excepsSize * sizeof(GfxFontWidthExcep));
  783.     }
  784.     n = obj4.getInt();
  785.     for (j = 0; j < obj5.arrayGetLength(); ++j) {
  786.       obj5.arrayGetL(j, &obj6);
  787.       if (!obj6.isNum()) {
  788.         error(-1, R_BAD_WIDTHS_ARRAY_IN_TYPE_0_FONT);
  789.         obj6.free();
  790.         break;
  791.       }
  792.       widths16.exceps[k].first = widths16.exceps[k].last = n++;
  793.       widths16.exceps[k].width = obj6.getNum() * 0.001;
  794.       obj6.free();
  795.       ++k;
  796.     }
  797.     i += 2;
  798.       } else {
  799.     error(-1, R_BAD_WIDTHS_ARRAY_IN_TYPE_0_FONT);
  800.     obj6.free();
  801.     obj5.free();
  802.     obj4.free();
  803.     break;
  804.       }
  805.       obj5.free();
  806.       obj4.free();
  807.     }
  808.     widths16.numExceps = k;
  809.     if (k > 0)
  810.       qsort(widths16.exceps, k, sizeof(GfxFontWidthExcep), &cmpWidthExcep);
  811.   }
  812.   obj3.free();
  813.  
  814.   // get char metric exceptions for vertical font
  815.   widths16.excepsV = NULL;
  816.   widths16.numExcepsV = 0;
  817.   obj2.dictLookupL("W2", &obj3);
  818.   if (obj3.isArray()) {
  819.     RAutoObject obj6, obj7, obj8;
  820.     excepsSize = 0;
  821.     k = 0;
  822.     i = 0;
  823.     while (i+1 < obj3.arrayGetLength()) {
  824.       obj3.arrayGetL(i, &obj4);
  825.       obj3.arrayGetL(i+1, &obj5);
  826.       if (obj4.isInt() && obj5.isInt()) {
  827.     obj3.arrayGetL(i+2, &obj6);
  828.     obj3.arrayGetL(i+3, &obj7);
  829.     obj3.arrayGetL(i+4, &obj8);
  830.     if (!obj6.isNum() || !obj7.isNum() || !obj8.isNum()) {
  831.       error(-1, R_BAD_WIDTHS__W2__ARRAY_IN_TYPE_0_FONT);
  832.       obj8.free();
  833.       obj7.free();
  834.       obj6.free();
  835.       obj5.free();
  836.       obj4.free();
  837.       break;
  838.     }
  839.     if (k == excepsSize) {
  840.       excepsSize += 16;
  841.       widths16.excepsV = (GfxFontWidthExcepV *)
  842.       User::ReAllocL(widths16.excepsV, excepsSize * sizeof(GfxFontWidthExcepV));
  843.     }
  844.     widths16.excepsV[k].first = obj4.getInt();
  845.     widths16.excepsV[k].last = obj5.getInt();
  846.     widths16.excepsV[k].height = obj6.getNum() * 0.001;
  847.     widths16.excepsV[k].vx = obj7.getNum() * 0.001;
  848.     widths16.excepsV[k].vy = obj8.getNum() * 0.001;
  849.     obj8.free();
  850.     obj7.free();
  851.     obj6.free();
  852.     ++k;
  853.     i += 5;
  854.       } else if (obj4.isInt() && obj5.isArray()) {
  855.     if (k + obj5.arrayGetLength() / 3 >= excepsSize) {
  856.       excepsSize = (k + obj5.arrayGetLength() / 3 + 15) & ~15;
  857.       widths16.excepsV = (GfxFontWidthExcepV *)
  858.       User::ReAllocL(widths16.excepsV, excepsSize * sizeof(GfxFontWidthExcepV));
  859.     }
  860.     n = obj4.getInt();
  861.     for (j = 0; j < obj5.arrayGetLength(); j += 3) {
  862.       obj5.arrayGetL(j, &obj6);
  863.       obj5.arrayGetL(j+1, &obj7);
  864.       obj5.arrayGetL(j+1, &obj8);
  865.       if (!obj6.isNum() || !obj7.isNum() || !obj8.isNum()) {
  866.         error(-1, R_BAD_WIDTHS__W2__ARRAY_IN_TYPE_0_FONT);
  867.         obj6.free();
  868.         break;
  869.       }
  870.       widths16.excepsV[k].first = widths16.exceps[k].last = n++;
  871.       widths16.excepsV[k].height = obj6.getNum() * 0.001;
  872.       widths16.excepsV[k].vx = obj7.getNum() * 0.001;
  873.       widths16.excepsV[k].vy = obj8.getNum() * 0.001;
  874.       obj8.free();
  875.       obj7.free();
  876.       obj6.free();
  877.       ++k;
  878.     }
  879.     i += 2;
  880.       } else {
  881.     error(-1, R_BAD_WIDTHS_ARRAY_IN_TYPE_0_FONT);
  882.     obj5.free();
  883.     obj4.free();
  884.     break;
  885.       }
  886.       obj5.free();
  887.       obj4.free();
  888.     }
  889.     widths16.numExcepsV = k;
  890.     if (k > 0) {
  891.       qsort(widths16.excepsV, k, sizeof(GfxFontWidthExcepV), &cmpWidthExcepV);
  892.     }
  893.   }
  894.   obj3.free();
  895.  
  896.   obj2.free();
  897.   obj1.free();
  898.  
  899.   // get encoding (CMap)
  900.   fontDict->lookupL("Encoding", &obj1);
  901.   if (!obj1.isName()) {
  902.     error(-1, R_BAD_ENCODING_FOR_TYPE_0_FONT);
  903.     goto err1;
  904.   }
  905. #if JAPANESE_SUPPORT
  906.   if (enc16.charSet == font16AdobeJapan12) {
  907.     for (i = 0; gfxJapan12Tab[i].name; ++i) {
  908.       if (!strcmp(obj1.getName(), gfxJapan12Tab[i].name))
  909.     break;
  910.     }
  911.     if (!gfxJapan12Tab[i].name) {
  912.       error(-1, R_UNKNOWN_ENCODING_FOR_ADOBE_JAPAN1_2_FONT,
  913.         obj1.getName());
  914.       goto err1;
  915.     }
  916.     enc16.enc = gfxJapan12Tab[i].enc;
  917.   }
  918. #endif
  919.   obj1.free();
  920.  
  921.   return;
  922.  
  923.  err4:
  924.   obj5.free();
  925.   obj4.free();
  926.  err3:
  927.   obj3.free();
  928.  err2:
  929.   obj2.free();
  930.  err1:
  931.   obj1.free();
  932.   //~ fix this --> add 16-bit font support to FontFile
  933.   encoding = new(ELeave) FontEncoding();
  934.   encoding->ConstructL();
  935.   makeWidths(fontDict, NULL, NULL, 0);
  936. }
  937.  
  938. static int CDECL cmpWidthExcep(const void *w1, const void *w2) {
  939.   return ((GfxFontWidthExcep *)w1)->first - ((GfxFontWidthExcep *)w2)->first;
  940. }
  941.  
  942. static int CDECL cmpWidthExcepV(const void *w1, const void *w2) {
  943.   return ((GfxFontWidthExcepV *)w1)->first - ((GfxFontWidthExcepV *)w2)->first;
  944. }
  945.  
  946. //------------------------------------------------------------------------
  947. // GfxFontDict
  948. //------------------------------------------------------------------------
  949.  
  950. GfxFontDict::GfxFontDict() {}
  951.  
  952. void GfxFontDict::ConstructL(Dict *fontDict) {
  953.   int i;
  954.   RAutoObject obj1, obj2;
  955.  
  956.   numFonts = 0; // fontDict->getLength();
  957.   fonts = (GfxFont **)User::AllocL(fontDict->getLength() * sizeof(GfxFont *));
  958.   // if zeroed cleanup in the destructor works
  959.   // Mem::FillZ(fonts, numFonts * sizeof(GfxFont *));
  960.   for (i = 0; i < fontDict->getLength(); ++i) {
  961.     // zero entry so that it can be safely cleaned up
  962.     fonts[i] = 0;
  963.     numFonts++;
  964.     fontDict->getValNFL(i, &obj1);
  965.     obj1.fetchL(&obj2);
  966.     if (obj1.isRef() && obj2.isDict()) {
  967.       fonts[i] = new(ELeave) GfxFont();
  968.       fonts[i]->ConstructL(fontDict->getKey(i), obj1.getRef(), obj2.getDict());
  969.     } else {
  970.       error(-1, R_FONT_RESOURCE_IS_NOT_A_DICTIONARY);
  971.     }
  972.     
  973.     obj1.free();
  974.     obj2.free();
  975.   }
  976. }
  977.  
  978. GfxFontDict::~GfxFontDict() {
  979.   int i;
  980.  
  981.   if (fonts) {
  982.     for (i = 0; i < numFonts; ++i)
  983.       delete fonts[i];
  984.   }
  985.   User::Free(fonts);
  986. }
  987.  
  988. GfxFont *GfxFontDict::lookup(char *tag) {
  989.   int i;
  990.  
  991.   for (i = 0; i < numFonts; ++i) {
  992.     if (fonts[i]->matches(tag))
  993.       return fonts[i];
  994.   }
  995.   return NULL;
  996. }
  997.  
  998. #ifdef __SYMBIAN32__
  999.  
  1000. // Initialise global data
  1001.  
  1002. FontInfoGlobal::FontInfoGlobal()
  1003. {
  1004.   standardEncoding     = 0;
  1005.   symbolEncoding       = 0;
  1006.   zapfDingbatsEncoding = 0;
  1007.   macRomanEncoding     = 0;
  1008.   winAnsiEncoding      = 0;
  1009. }
  1010.  
  1011. TInt FontInfoGlobal::Construct()
  1012. {
  1013.   standardEncoding = new FontEncoding();
  1014.   if (!standardEncoding)
  1015.     return KErrNoMemory;
  1016.   standardEncoding->Construct(standardEncodingNames, standardEncodingSize);
  1017.   
  1018.   symbolEncoding = new FontEncoding();
  1019.   if (!symbolEncoding)
  1020.     return KErrNoMemory;
  1021.   symbolEncoding->Construct(symbolEncodingNames, symbolEncodingSize);
  1022.  
  1023.   zapfDingbatsEncoding = new FontEncoding();
  1024.   if (!zapfDingbatsEncoding)
  1025.     return KErrNoMemory;
  1026.   zapfDingbatsEncoding->Construct(zapfDingbatsEncodingNames, zapfDingbatsEncodingSize);
  1027.  
  1028.   macRomanEncoding = new FontEncoding();
  1029.   if (!macRomanEncoding)
  1030.     return KErrNoMemory;
  1031.   macRomanEncoding->Construct(macRomanEncodingNames, macRomanEncodingSize);
  1032.  
  1033.   winAnsiEncoding = new FontEncoding();
  1034.   if (!winAnsiEncoding)
  1035.     return KErrNoMemory;
  1036.   winAnsiEncoding->Construct((const char**)winAnsiEncodingNames, winAnsiEncodingSize);
  1037.  
  1038.   builtinFonts[ 0] = BuiltinFont("Courier",               (Gushort *)courierWidths,              standardEncoding);
  1039.   builtinFonts[ 1] = BuiltinFont("Courier-Bold",          (Gushort *)courierBoldWidths,          standardEncoding);
  1040.   builtinFonts[ 2] = BuiltinFont("Courier-BoldOblique",   (Gushort *)courierBoldObliqueWidths,   standardEncoding);
  1041.   builtinFonts[ 3] = BuiltinFont("Courier-Oblique",       (Gushort *)courierObliqueWidths,       standardEncoding);
  1042.   builtinFonts[ 4] = BuiltinFont("Helvetica",             (Gushort *)helveticaWidths,            standardEncoding);
  1043.   builtinFonts[ 5] = BuiltinFont("Helvetica-Bold",        (Gushort *)helveticaBoldWidths,        standardEncoding);
  1044.   builtinFonts[ 6] = BuiltinFont("Helvetica-BoldOblique", (Gushort *)helveticaBoldObliqueWidths, standardEncoding);
  1045.   builtinFonts[ 7] = BuiltinFont("Helvetica-Oblique",     (Gushort *)helveticaObliqueWidths,     standardEncoding);
  1046.   builtinFonts[ 8] = BuiltinFont("Symbol",                (Gushort *)symbolWidths,               symbolEncoding);
  1047.   builtinFonts[ 9] = BuiltinFont("Times-Bold",            (Gushort *)timesBoldWidths,            standardEncoding);
  1048.   builtinFonts[10] = BuiltinFont("Times-BoldItalic",      (Gushort *)timesBoldItalicWidths,      standardEncoding);
  1049.   builtinFonts[11] = BuiltinFont("Times-Italic",          (Gushort *)timesItalicWidths,          standardEncoding);
  1050.   builtinFonts[12] = BuiltinFont("Times-Roman",           (Gushort *)timesRomanWidths,           standardEncoding);
  1051.   builtinFonts[13] = BuiltinFont("ZapfDingbats",          (Gushort *)zapfDingbatsWidths,         zapfDingbatsEncoding);
  1052.  
  1053.   return KErrNone;
  1054. };
  1055.  
  1056.  
  1057. FontInfoGlobal::~FontInfoGlobal()
  1058. {
  1059.   delete standardEncoding;
  1060.   delete symbolEncoding;
  1061.   delete zapfDingbatsEncoding;
  1062.   delete macRomanEncoding;
  1063.   delete winAnsiEncoding;
  1064. }
  1065.  
  1066. #endif