Ignore:
Timestamp:
Jun 30, 2008, 10:13:07 AM (13 years ago)
Author:
Eugene Romanenko
Message:

PDF plugin: poppler library updated to version 0.8.3

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/poppler/mypoppler/fofi/FoFiTrueType.cc

    r2 r250  
    1919#include "goo/GooString.h"
    2020#include "goo/GooHash.h"
     21#include "FoFiType1C.h"
    2122#include "FoFiTrueType.h"
    2223
     
    109110#define glyfTag 0x676c7966
    110111#define headTag 0x68656164
     112#define hheaTag 0x68686561
     113#define hmtxTag 0x686d7478
    111114#define locaTag 0x6c6f6361
    112115#define nameTag 0x6e616d65
     116#define os2Tag  0x4f532f32
    113117#define postTag 0x706f7374
     118#define vrt2Tag 0x76727432
     119#define vertTag 0x76657274
    114120
    115121static int cmpTrueTypeLocaOffset(const void *p1, const void *p2) {
     
    279285  parsedOk = gFalse;
    280286  faceIndex = faceIndexA;
     287  gsubFeatureTable = 0;
     288  gsubLookupList = 0;
    281289
    282290  parse();
     
    314322}
    315323
    316 Gushort FoFiTrueType::mapCodeToGID(int i, int c) {
     324Gushort FoFiTrueType::mapCodeToGID(int i, Guint c) {
    317325  Gushort gid;
    318   int segCnt, segEnd, segStart, segDelta, segOffset;
    319   int cmapFirst, cmapLen;
     326  Guint segCnt, segEnd, segStart, segDelta, segOffset;
     327  Guint cmapFirst, cmapLen;
    320328  int pos, a, b, m;
    321329  GBool ok;
     
    328336  switch (cmaps[i].fmt) {
    329337  case 0:
    330     if (c < 0 || c >= cmaps[i].len - 6) {
     338    if (c >= cmaps[i].len - 6) {
    331339      return 0;
    332340    }
     
    377385    gid = getU16BE(pos + 10 + 2 * (c - cmapFirst), &ok);
    378386    break;
     387  case 12:
     388    segCnt = getU32BE(pos + 12, &ok);
     389    a = -1;
     390    b = segCnt - 1;
     391    segEnd = getU32BE(pos + 16 + 12*b+4, &ok);
     392    if (c > segEnd) {
     393      return 0;
     394    }
     395    // invariant: seg[a].end < code <= seg[b].end
     396    while (b - a > 1 && ok) {
     397      m = (a + b) / 2;
     398      segEnd = getU32BE(pos + 16 + 12*m+4, &ok);
     399      if (segEnd < c) {
     400        a = m;
     401      } else {
     402        b = m;
     403      }
     404    }
     405    segStart = getU32BE(pos + 16 + 12*b, &ok);
     406    segDelta = getU32BE(pos + 16 + 12*b+8, &ok);
     407    if (c < segStart) {
     408      return 0;
     409    }
     410    gid = segDelta + (c-segStart);
     411    break;
    379412  default:
    380413    return 0;
     
    391424  }
    392425  return nameToGID->lookupInt(name);
     426}
     427
     428Gushort *FoFiTrueType::getCIDToGIDMap(int *nCIDs) {
     429  FoFiType1C *ff;
     430  Gushort *map;
     431  int i;
     432
     433  *nCIDs = 0;
     434  if (!openTypeCFF) {
     435    return NULL;
     436  }
     437  i = seekTable("CFF ");
     438  if (!checkRegion(tables[i].offset, tables[i].len)) {
     439    return NULL;
     440  }
     441  if (!(ff = FoFiType1C::make((char *)file + tables[i].offset,
     442                              tables[i].len))) {
     443    return NULL;
     444  }
     445  map = ff->getCIDToGIDMap(nCIDs);
     446  delete ff;
     447  return map;
    393448}
    394449
     
    421476                                   FoFiOutputFunc outputFunc,
    422477                                   void *outputStream) {
    423   char buf[512];
     478  GooString *buf;
    424479  GBool ok;
     480
     481  if (openTypeCFF) {
     482    return;
     483  }
    425484
    426485  // write the header
    427486  ok = gTrue;
    428   sprintf(buf, "%%!PS-TrueTypeFont-%g\n", (double)getS32BE(0, &ok) / 65536.0);
    429   (*outputFunc)(outputStream, buf, strlen(buf));
     487  buf = GooString::format("%!PS-TrueTypeFont-{0:2g}\n",
     488                        (double)getS32BE(0, &ok) / 65536.0);
     489  (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
     490  delete buf;
    430491
    431492  // begin the font dictionary
     
    436497  (*outputFunc)(outputStream, "/FontType 42 def\n", 17);
    437498  (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
    438   sprintf(buf, "/FontBBox [%d %d %d %d] def\n",
    439           bbox[0], bbox[1], bbox[2], bbox[3]);
    440   (*outputFunc)(outputStream, buf, strlen(buf));
     499  buf = GooString::format("/FontBBox [{0:d} {1:d} {2:d} {3:d}] def\n",
     500                        bbox[0], bbox[1], bbox[2], bbox[3]);
     501  (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
     502  delete buf;
    441503  (*outputFunc)(outputStream, "/PaintType 0 def\n", 17);
    442504
     
    448510  // end the dictionary and define the font
    449511  (*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40);
     512}
     513
     514void FoFiTrueType::convertToType1(char *psName, char **newEncoding,
     515                                  GBool ascii, FoFiOutputFunc outputFunc,
     516                                  void *outputStream) {
     517  FoFiType1C *ff;
     518  int i;
     519
     520  if (!openTypeCFF) {
     521    return;
     522  }
     523  i = seekTable("CFF ");
     524  if (!checkRegion(tables[i].offset, tables[i].len)) {
     525    return;
     526  }
     527  if (!(ff = FoFiType1C::make((char *)file + tables[i].offset,
     528                              tables[i].len))) {
     529    return;
     530  }
     531  ff->convertToType1(psName, newEncoding, ascii, outputFunc, outputStream);
     532  delete ff;
    450533}
    451534
     
    455538                                     FoFiOutputFunc outputFunc,
    456539                                     void *outputStream) {
    457   char buf[512];
     540  GooString *buf;
    458541  Gushort cid;
    459542  GBool ok;
    460543  int i, j, k;
    461544
     545  if (openTypeCFF) {
     546    return;
     547  }
     548
    462549  // write the header
    463550  ok = gTrue;
    464   sprintf(buf, "%%!PS-TrueTypeFont-%g\n", (double)getS32BE(0, &ok) / 65536.0);
    465   (*outputFunc)(outputStream, buf, strlen(buf));
     551  buf = GooString::format("%!PS-TrueTypeFont-{0:2g}\n",
     552                        (double)getS32BE(0, &ok) / 65536.0);
     553  (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
     554  delete buf;
    466555
    467556  // begin the font dictionary
     
    479568  (*outputFunc)(outputStream, "/GDBytes 2 def\n", 15);
    480569  if (cidMap) {
    481     sprintf(buf, "/CIDCount %d def\n", nCIDs);
    482     (*outputFunc)(outputStream, buf, strlen(buf));
     570    buf = GooString::format("/CIDCount {0:d} def\n", nCIDs);
     571    (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
     572    delete buf;
    483573    if (nCIDs > 32767) {
    484574      (*outputFunc)(outputStream, "/CIDMap [", 9);
     
    489579          for (k = 0; k < 16 && i+j+k < nCIDs; ++k) {
    490580            cid = cidMap[i+j+k];
    491             sprintf(buf, "%02x%02x", (cid >> 8) & 0xff, cid & 0xff);
    492             (*outputFunc)(outputStream, buf, strlen(buf));
     581            buf = GooString::format("{0:02x}{1:02x}",
     582                                  (cid >> 8) & 0xff, cid & 0xff);
     583            (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
     584            delete buf;
    493585          }
    494586          (*outputFunc)(outputStream, "\n", 1);
     
    504596        for (j = 0; j < 16 && i+j < nCIDs; ++j) {
    505597          cid = cidMap[i+j];
    506           sprintf(buf, "%02x%02x", (cid >> 8) & 0xff, cid & 0xff);
    507           (*outputFunc)(outputStream, buf, strlen(buf));
     598          buf = GooString::format("{0:02x}{1:02x}",
     599                                (cid >> 8) & 0xff, cid & 0xff);
     600          (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
     601          delete buf;
    508602        }
    509603        (*outputFunc)(outputStream, "\n", 1);
     
    513607  } else {
    514608    // direct mapping - just fill the string(s) with s[i]=i
    515     sprintf(buf, "/CIDCount %d def\n", nGlyphs);
    516     (*outputFunc)(outputStream, buf, strlen(buf));
     609    buf = GooString::format("/CIDCount {0:d} def\n", nGlyphs);
     610    (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
     611    delete buf;
    517612    if (nGlyphs > 32767) {
    518613      (*outputFunc)(outputStream, "/CIDMap [\n", 10);
    519614      for (i = 0; i < nGlyphs; i += 32767) {
    520615        j = nGlyphs - i < 32767 ? nGlyphs - i : 32767;
    521         sprintf(buf, "  %d string 0 1 %d {\n", 2 * j, j - 1);
    522         (*outputFunc)(outputStream, buf, strlen(buf));
    523         sprintf(buf, "    2 copy dup 2 mul exch %d add -8 bitshift put\n", i);
    524         (*outputFunc)(outputStream, buf, strlen(buf));
    525         sprintf(buf, "    1 index exch dup 2 mul 1 add exch %d add"
    526                 " 255 and put\n", i);
    527         (*outputFunc)(outputStream, buf, strlen(buf));
     616        buf = GooString::format("  {0:d} string 0 1 {1:d} {{\n", 2 * j, j - 1);
     617        (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
     618        delete buf;
     619        buf = GooString::format("    2 copy dup 2 mul exch {0:d} add -8 bitshift put\n",
     620                              i);
     621        (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
     622        delete buf;
     623        buf = GooString::format("    1 index exch dup 2 mul 1 add exch {0:d} add"
     624                              " 255 and put\n", i);
     625        (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
     626        delete buf;
    528627        (*outputFunc)(outputStream, "  } for\n", 8);
    529628      }
    530629      (*outputFunc)(outputStream, "] def\n", 6);
    531630    } else {
    532       sprintf(buf, "/CIDMap %d string\n", 2 * nGlyphs);
    533       (*outputFunc)(outputStream, buf, strlen(buf));
    534       sprintf(buf, "  0 1 %d {\n", nGlyphs - 1);
    535       (*outputFunc)(outputStream, buf, strlen(buf));
     631      buf = GooString::format("/CIDMap {0:d} string\n", 2 * nGlyphs);
     632      (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
     633      delete buf;
     634      buf = GooString::format("  0 1 {0:d} {{\n", nGlyphs - 1);
     635      (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
     636      delete buf;
    536637      (*outputFunc)(outputStream,
    537638                    "    2 copy dup 2 mul exch -8 bitshift put\n", 42);
     
    543644  }
    544645  (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
    545   sprintf(buf, "/FontBBox [%d %d %d %d] def\n",
    546           bbox[0], bbox[1], bbox[2], bbox[3]);
    547   (*outputFunc)(outputStream, buf, strlen(buf));
     646  buf = GooString::format("/FontBBox [{0:d} {1:d} {2:d} {3:d}] def\n",
     647                        bbox[0], bbox[1], bbox[2], bbox[3]);
     648  (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
     649  delete buf;
    548650  (*outputFunc)(outputStream, "/PaintType 0 def\n", 17);
    549651  (*outputFunc)(outputStream, "/Encoding [] readonly def\n", 26);
     
    561663}
    562664
     665void FoFiTrueType::convertToCIDType0(char *psName,
     666                                     FoFiOutputFunc outputFunc,
     667                                     void *outputStream) {
     668  FoFiType1C *ff;
     669  int i;
     670
     671  if (!openTypeCFF) {
     672    return;
     673  }
     674  i = seekTable("CFF ");
     675  if (!checkRegion(tables[i].offset, tables[i].len)) {
     676    return;
     677  }
     678  if (!(ff = FoFiType1C::make((char *)file + tables[i].offset,
     679                              tables[i].len))) {
     680    return;
     681  }
     682  ff->convertToCIDType0(psName, outputFunc, outputStream);
     683  delete ff;
     684}
     685
    563686void FoFiTrueType::convertToType0(char *psName, Gushort *cidMap, int nCIDs,
    564687                                  GBool needVerticalMetrics,
    565688                                  FoFiOutputFunc outputFunc,
    566689                                  void *outputStream) {
    567   char buf[512];
     690  GooString *buf;
    568691  GooString *sfntsName;
    569692  int n, i, j;
     693
     694  if (openTypeCFF) {
     695    return;
     696  }
    570697
    571698  // write the Type 42 sfnts array
     
    580707    (*outputFunc)(outputStream, "/FontName /", 11);
    581708    (*outputFunc)(outputStream, psName, strlen(psName));
    582     sprintf(buf, "_%02x def\n", i >> 8);
    583     (*outputFunc)(outputStream, buf, strlen(buf));
     709    buf = GooString::format("_{0:02x} def\n", i >> 8);
     710    (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
     711    delete buf;
    584712    (*outputFunc)(outputStream, "/FontType 42 def\n", 17);
    585713    (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
    586     sprintf(buf, "/FontBBox [%d %d %d %d] def\n",
    587             bbox[0], bbox[1], bbox[2], bbox[3]);
    588     (*outputFunc)(outputStream, buf, strlen(buf));
     714    buf = GooString::format("/FontBBox [{0:d} {1:d} {2:d} {3:d}] def\n",
     715                          bbox[0], bbox[1], bbox[2], bbox[3]);
     716    (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
     717    delete buf;
    589718    (*outputFunc)(outputStream, "/PaintType 0 def\n", 17);
    590719    (*outputFunc)(outputStream, "/sfnts ", 7);
     
    593722    (*outputFunc)(outputStream, "/Encoding 256 array\n", 20);
    594723    for (j = 0; j < 256 && i+j < n; ++j) {
    595       sprintf(buf, "dup %d /c%02x put\n", j, j);
    596       (*outputFunc)(outputStream, buf, strlen(buf));
     724      buf = GooString::format("dup {0:d} /c{1:02x} put\n", j, j);
     725      (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
     726      delete buf;
    597727    }
    598728    (*outputFunc)(outputStream, "readonly def\n", 13);
     
    600730    (*outputFunc)(outputStream, "/.notdef 0 def\n", 15);
    601731    for (j = 0; j < 256 && i+j < n; ++j) {
    602       sprintf(buf, "/c%02x %d def\n", j, cidMap ? cidMap[i+j] : i+j);
    603       (*outputFunc)(outputStream, buf, strlen(buf));
     732      buf = GooString::format("/c{0:02x} {1:d} def\n",
     733                            j, cidMap ? cidMap[i+j] : i+j);
     734      (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
     735      delete buf;
    604736    }
    605737    (*outputFunc)(outputStream, "end readonly def\n", 17);
     
    618750  (*outputFunc)(outputStream, "/Encoding [\n", 12);
    619751  for (i = 0; i < n; i += 256) {
    620     sprintf(buf, "%d\n", i >> 8);
    621     (*outputFunc)(outputStream, buf, strlen(buf));
     752    buf = GooString::format("{0:d}\n", i >> 8);
     753    (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
     754    delete buf;
    622755  }
    623756  (*outputFunc)(outputStream, "] def\n", 6);
     
    626759    (*outputFunc)(outputStream, "/", 1);
    627760    (*outputFunc)(outputStream, psName, strlen(psName));
    628     sprintf(buf, "_%02x findfont\n", i >> 8);
    629     (*outputFunc)(outputStream, buf, strlen(buf));
     761    buf = GooString::format("_{0:02x} findfont\n", i >> 8);
     762    (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
     763    delete buf;
    630764  }
    631765  (*outputFunc)(outputStream, "] def\n", 6);
    632766  (*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40);
     767}
     768
     769void FoFiTrueType::convertToType0(char *psName,
     770                                  FoFiOutputFunc outputFunc,
     771                                  void *outputStream) {
     772  FoFiType1C *ff;
     773  int i;
     774
     775  if (!openTypeCFF) {
     776    return;
     777  }
     778  i = seekTable("CFF ");
     779  if (!checkRegion(tables[i].offset, tables[i].len)) {
     780    return;
     781  }
     782  if (!(ff = FoFiType1C::make((char *)file + tables[i].offset,
     783                              tables[i].len))) {
     784    return;
     785  }
     786  ff->convertToType0(psName, outputFunc, outputStream);
     787  delete ff;
    633788}
    634789
     
    674829    0, 0, 0, 0                  // max Type 1 memory
    675830  };
    676   GBool missingCmap, missingName, missingPost, unsortedLoca, badCmapLen;
     831  static char os2Tab[86] = {
     832    0, 1,                       // version
     833    0, 1,                       // xAvgCharWidth
     834    0, 0,                       // usWeightClass
     835    0, 0,                       // usWidthClass
     836    0, 0,                       // fsType
     837    0, 0,                       // ySubscriptXSize
     838    0, 0,                       // ySubscriptYSize
     839    0, 0,                       // ySubscriptXOffset
     840    0, 0,                       // ySubscriptYOffset
     841    0, 0,                       // ySuperscriptXSize
     842    0, 0,                       // ySuperscriptYSize
     843    0, 0,                       // ySuperscriptXOffset
     844    0, 0,                       // ySuperscriptYOffset
     845    0, 0,                       // yStrikeoutSize
     846    0, 0,                       // yStrikeoutPosition
     847    0, 0,                       // sFamilyClass
     848    0, 0, 0, 0, 0,              // panose
     849    0, 0, 0, 0, 0,
     850    0, 0, 0, 0,                 // ulUnicodeRange1
     851    0, 0, 0, 0,                 // ulUnicodeRange2
     852    0, 0, 0, 0,                 // ulUnicodeRange3
     853    0, 0, 0, 0,                 // ulUnicodeRange4
     854    0, 0, 0, 0,                 // achVendID
     855    0, 0,                       // fsSelection
     856    0, 0,                       // usFirstCharIndex
     857    0, 0,                       // usLastCharIndex
     858    0, 0,                       // sTypoAscender
     859    0, 0,                       // sTypoDescender
     860    0, 0,                       // sTypoLineGap
     861    0, 0,                       // usWinAscent
     862    0, 0,                       // usWinDescent
     863    0, 0, 0, 0,                 // ulCodePageRange1
     864    0, 0, 0, 0                  // ulCodePageRange2
     865  };
     866  GBool missingCmap, missingName, missingPost, missingOS2;
     867  GBool unsortedLoca, badCmapLen, abbrevHMTX;
    677868  int nZeroLengthTables;
     869  int nHMetrics, advWidth, lsb;
    678870  TrueTypeLoca *locaTable;
    679871  TrueTypeTable *newTables;
    680   char *newNameTab, *newCmapTab;
     872  char *newNameTab, *newCmapTab, *newHHEATab, *newHMTXTab;
    681873  int nNewTables, cmapIdx, cmapLen, glyfLen, newNameLen, newCmapLen, next;
     874  int newHHEALen, newHMTXLen;
    682875  Guint locaChecksum, glyfChecksum, fileChecksum;
    683876  char *tableDir;
     
    687880  int pos, i, j, k, n;
    688881
     882  if (openTypeCFF) {
     883    return;
     884  }
     885
    689886  // check for missing tables
     887  // (Note: if the OS/2 table is missing, the Microsoft PCL5 driver
     888  // will embed a PCL TrueType font with the pitch field set to zero,
     889  // which apparently causes divide-by-zero errors.  As far as I can
     890  // tell, the only important field in the OS/2 table is
     891  // xAvgCharWidth.)
    690892  missingCmap = (cmapIdx = seekTable("cmap")) < 0;
    691893  missingName = seekTable("name") < 0;
    692894  missingPost = seekTable("post") < 0;
     895  missingOS2 = seekTable("OS/2") < 0;
    693896
    694897  // read the loca table, check to see if it's sorted
     
    707910      unsortedLoca = gTrue;
    708911    }
     912    // glyph descriptions must be at least 12 bytes long (nContours,
     913    // xMin, yMin, xMax, yMax, instructionLength - two bytes each);
     914    // invalid glyph descriptions (even if they're never used) make
     915    // Windows choke, so we work around that problem here (ideally,
     916    // this would parse the glyph descriptions in the glyf table and
     917    // remove any that were invalid, but this quick test is a decent
     918    // start)
     919    if (i > 0 &&
     920        locaTable[i].origOffset - locaTable[i-1].origOffset > 0 &&
     921        locaTable[i].origOffset - locaTable[i-1].origOffset < 12) {
     922      locaTable[i-1].origOffset = locaTable[i].origOffset;
     923      unsortedLoca = gTrue;
     924    }
    709925    locaTable[i].idx = i;
    710926  }
     
    722938  cmapLen = 0; // make gcc happy
    723939  if (!missingCmap) {
    724     cmapLen = cmaps[0].offset + cmaps[0].len;
    725     for (i = 1; i < nCmaps; ++i) {
    726       if (cmaps[i].offset + cmaps[i].len > cmapLen) {
    727         cmapLen = cmaps[i].offset + cmaps[i].len;
     940    if (nCmaps > 0) {
     941      cmapLen = cmaps[0].offset + cmaps[0].len;
     942      for (i = 1; i < nCmaps; ++i) {
     943        if (cmaps[i].offset + cmaps[i].len > cmapLen) {
     944          cmapLen = cmaps[i].offset + cmaps[i].len;
     945        }
    728946      }
    729947    }
     
    734952  }
    735953
     954  // check for an abbreviated hmtx table (this is completely legal,
     955  // but confuses the Microsoft PCL5 printer driver, which generates
     956  // embedded fonts with the pitch field set to zero)
     957  i = seekTable("hhea");
     958  nHMetrics = getU16BE(tables[i].offset + 34, &ok);
     959  abbrevHMTX = nHMetrics < nGlyphs;
     960
    736961  // if nothing is broken, just write the TTF file as is
    737   if (!missingCmap && !missingName && !missingPost && !unsortedLoca &&
    738       !badCmapLen && nZeroLengthTables == 0 && !name && !codeToGID) {
     962  if (!missingCmap && !missingName && !missingPost && !missingOS2 &&
     963      !unsortedLoca && !badCmapLen && !abbrevHMTX && nZeroLengthTables == 0 &&
     964      !name && !codeToGID) {
    739965    (*outputFunc)(outputStream, (char *)file, len);
    740966    goto done1;
     
    8941120  }
    8951121
     1122  // generate the new hmtx table and the updated hhea table
     1123  if (abbrevHMTX) {
     1124    i = seekTable("hhea");
     1125    pos = tables[i].offset;
     1126    newHHEALen = 36;
     1127    newHHEATab = (char *)gmalloc(newHHEALen);
     1128    for (i = 0; i < newHHEALen; ++i) {
     1129      newHHEATab[i] = getU8(pos++, &ok);
     1130    }
     1131    newHHEATab[34] = nGlyphs >> 8;
     1132    newHHEATab[35] = nGlyphs & 0xff;
     1133    i = seekTable("hmtx");
     1134    pos = tables[i].offset;
     1135    newHMTXLen = 4 * nGlyphs;
     1136    newHMTXTab = (char *)gmalloc(newHMTXLen);
     1137    advWidth = 0;
     1138    for (i = 0; i < nHMetrics; ++i) {
     1139      advWidth = getU16BE(pos, &ok);
     1140      lsb = getU16BE(pos + 2, &ok);
     1141      pos += 4;
     1142      newHMTXTab[4*i    ] = advWidth >> 8;
     1143      newHMTXTab[4*i + 1] = advWidth & 0xff;
     1144      newHMTXTab[4*i + 2] = lsb >> 8;
     1145      newHMTXTab[4*i + 3] = lsb & 0xff;
     1146    }
     1147    for (; i < nGlyphs; ++i) {
     1148      lsb = getU16BE(pos, &ok);
     1149      pos += 2;
     1150      newHMTXTab[4*i    ] = advWidth >> 8;
     1151      newHMTXTab[4*i + 1] = advWidth & 0xff;
     1152      newHMTXTab[4*i + 2] = lsb >> 8;
     1153      newHMTXTab[4*i + 3] = lsb & 0xff;
     1154    }
     1155  } else {
     1156    newHHEATab = newHMTXTab = NULL;
     1157    newHHEALen = newHMTXLen = 0; // make gcc happy
     1158  }
     1159
    8961160  // construct the new table directory:
    8971161  // - keep all original tables with non-zero length
     
    9031167  nNewTables = nTables - nZeroLengthTables +
    9041168               (missingCmap ? 1 : 0) + (missingName ? 1 : 0) +
    905                (missingPost ? 1 : 0);
     1169               (missingPost ? 1 : 0) + (missingOS2 ? 1 : 0);
    9061170  newTables = (TrueTypeTable *)gmallocn(nNewTables, sizeof(TrueTypeTable));
    9071171  j = 0;
     
    9341198        newTables[j].checksum = computeTableChecksum((Guchar *)newNameTab,
    9351199                                                     newNameLen);
     1200      } else if (newTables[j].tag == hheaTag && abbrevHMTX) {
     1201        newTables[j].len = newHHEALen;
     1202        newTables[j].checksum = computeTableChecksum((Guchar *)newHHEATab,
     1203                                                     newHHEALen);
     1204      } else if (newTables[j].tag == hmtxTag && abbrevHMTX) {
     1205        newTables[j].len = newHMTXLen;
     1206        newTables[j].checksum = computeTableChecksum((Guchar *)newHMTXTab,
     1207                                                     newHMTXLen);
    9361208      }
    9371209      ++j;
     
    9691241                                                 sizeof(postTab));
    9701242    newTables[j].len = sizeof(postTab);
     1243    ++j;
     1244  }
     1245  if (missingOS2) {
     1246    newTables[j].tag = os2Tag;
     1247    newTables[j].checksum = computeTableChecksum((Guchar *)os2Tab,
     1248                                                 sizeof(os2Tab));
     1249    newTables[j].len = sizeof(os2Tab);
    9711250    ++j;
    9721251  }
     
    10571336    } else if (newTables[i].tag == postTag && missingPost) {
    10581337      (*outputFunc)(outputStream, postTab, newTables[i].len);
     1338    } else if (newTables[i].tag == os2Tag && missingOS2) {
     1339      (*outputFunc)(outputStream, os2Tab, newTables[i].len);
     1340    } else if (newTables[i].tag == hheaTag && abbrevHMTX) {
     1341      (*outputFunc)(outputStream, newHHEATab, newTables[i].len);
     1342    } else if (newTables[i].tag == hmtxTag && abbrevHMTX) {
     1343      (*outputFunc)(outputStream, newHMTXTab, newTables[i].len);
    10591344    } else if (newTables[i].tag == locaTag && unsortedLoca) {
    10601345      for (j = 0; j <= nGlyphs; ++j) {
     
    11041389  }
    11051390
     1391  gfree(newHMTXTab);
     1392  gfree(newHHEATab);
    11061393  gfree(newCmapTab);
    11071394  gfree(newNameTab);
     
    11161403                               void *outputStream) {
    11171404  char *name;
    1118   char buf[64];
     1405  GooString *buf;
    11191406  int i;
    11201407
     
    11251412        name = ".notdef";
    11261413      }
    1127       sprintf(buf, "dup %d /", i);
    1128       (*outputFunc)(outputStream, buf, strlen(buf));
     1414      buf = GooString::format("dup {0:d} /", i);
     1415      (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
     1416      delete buf;
    11291417      (*outputFunc)(outputStream, name, strlen(name));
    11301418      (*outputFunc)(outputStream, " put\n", 5);
     
    11321420  } else {
    11331421    for (i = 0; i < 256; ++i) {
    1134       sprintf(buf, "dup %d /c%02x put\n", i, i);
    1135       (*outputFunc)(outputStream, buf, strlen(buf));
     1422      buf = GooString::format("dup {0:d} /c{1:02x} put\n", i, i);
     1423      (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
     1424      delete buf;
    11361425    }
    11371426  }
     
    11441433                                  void *outputStream) {
    11451434  char *name;
    1146   char buf[64], buf2[16];
     1435  GooString *buf;
     1436  char buf2[16];
    11471437  int i, k;
    11481438
     
    11791469        (*outputFunc)(outputStream, "/", 1);
    11801470        (*outputFunc)(outputStream, name, strlen(name));
    1181         sprintf(buf, " %d def\n", k);
    1182         (*outputFunc)(outputStream, buf, strlen(buf));
     1471        buf = GooString::format(" {0:d} def\n", k);
     1472        (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
     1473        delete buf;
    11831474      }
    11841475    }
     
    14831774                              FoFiOutputFunc outputFunc,
    14841775                              void *outputStream) {
    1485   char buf[64];
     1776  GooString *buf;
    14861777  int pad, i, j;
    14871778
     
    14891780  for (i = 0; i < length; i += 32) {
    14901781    for (j = 0; j < 32 && i+j < length; ++j) {
    1491       sprintf(buf, "%02X", s[i+j] & 0xff);
    1492       (*outputFunc)(outputStream, buf, strlen(buf));
     1782      buf = GooString::format("{0:02x}", s[i+j] & 0xff);
     1783      (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
     1784      delete buf;
    14931785    }
    14941786    if (i % (65536 - 32) == 65536 - 64) {
     
    15371829}
    15381830
    1539 #define toTag(a,b,c,d) (((unsigned int)(a)<<24) | ((unsigned int)(b)<<16) | ((unsigned int)(c)<<8) | (d))
    1540 
    15411831void FoFiTrueType::parse() {
    15421832  Guint topTag;
    1543   int pos, i, j;
    1544   unsigned int head;
     1833  int pos, ver, i, j;
    15451834
    15461835  parsedOk = gTrue;
     
    15521841  }
    15531842  if (topTag == ttcfTag) {
    1554     pos = getU32BE(12, &parsedOk);
    1555     if (!parsedOk) {
    1556       return;
    1557     }
    1558   } else {
    1559     pos = 0;
    1560   }
    1561 
    1562   // read the table directory
    1563   head = getU32BE(pos, &parsedOk);
    1564   if (! parsedOk)
    1565     return;
    1566   if (head == toTag('t','t','c','f')) {
    15671843    /* TTC font */
    1568     unsigned int tableDir;
    15691844    int dircount;
    15701845
     
    15821857    if (! parsedOk)
    15831858      return;
    1584   }
    1585 
    1586   pos += 4;
    1587   nTables = getU16BE(pos, &parsedOk);
     1859  } else {
     1860    pos = 0;
     1861  }
     1862
     1863  // check the sfnt version
     1864  ver = getU32BE(pos, &parsedOk);
    15881865  if (!parsedOk) {
    15891866    return;
    15901867  }
    1591 
    1592   pos += 8;
     1868  openTypeCFF = ver == 0x4f54544f; // 'OTTO'
     1869
     1870  // read the table directory
     1871  nTables = getU16BE(pos + 4, &parsedOk);
     1872  if (!parsedOk) {
     1873    return;
     1874  }
    15931875  tables = (TrueTypeTable *)gmallocn(nTables, sizeof(TrueTypeTable));
     1876  pos += 12;
    15941877  for (i = 0; i < nTables; ++i) {
    15951878    tables[i].tag = getU32BE(pos, &parsedOk);
     
    16111894  if (seekTable("head") < 0 ||
    16121895      seekTable("hhea") < 0 ||
    1613       seekTable("loca") < 0 ||
    16141896      seekTable("maxp") < 0 ||
    1615       seekTable("glyf") < 0 ||
    1616       seekTable("hmtx") < 0) {
     1897      seekTable("hmtx") < 0 ||
     1898      (!openTypeCFF && seekTable("loca") < 0) ||
     1899      (!openTypeCFF && seekTable("glyf") < 0) ||
     1900      (openTypeCFF && seekTable("CFF ") < 0)) {
    16171901    parsedOk = gFalse;
    16181902    return;
     
    16631947  // make sure the loca table is sane (correct length and entries are
    16641948  // in bounds)
    1665   i = seekTable("loca");
    1666   if (tables[i].len < (nGlyphs + 1) * (locaFmt ? 4 : 2)) {
    1667     parsedOk = gFalse;
    1668     return;
    1669   }
    1670   for (j = 0; j <= nGlyphs; ++j) {
    1671     if (locaFmt) {
    1672       pos = (int)getU32BE(tables[i].offset + j*4, &parsedOk);
    1673     } else {
    1674       pos = getU16BE(tables[i].offset + j*2, &parsedOk);
    1675     }
    1676     if (pos < 0 || pos > len) {
     1949  if (!openTypeCFF) {
     1950    i = seekTable("loca");
     1951    if (tables[i].len < 0) {
    16771952      parsedOk = gFalse;
    1678     }
    1679   }
    1680   if (!parsedOk) {
    1681     return;
     1953      return;
     1954    }
     1955    if (tables[i].len < (nGlyphs + 1) * (locaFmt ? 4 : 2)) {
     1956      nGlyphs = tables[i].len / (locaFmt ? 4 : 2) - 1;
     1957    }
     1958    for (j = 0; j <= nGlyphs; ++j) {
     1959      if (locaFmt) {
     1960        pos = (int)getU32BE(tables[i].offset + j*4, &parsedOk);
     1961      } else {
     1962        pos = getU16BE(tables[i].offset + j*2, &parsedOk);
     1963      }
     1964      if (pos < 0 || pos > len) {
     1965        parsedOk = gFalse;
     1966      }
     1967    }
     1968    if (!parsedOk) {
     1969      return;
     1970    }
    16821971  }
    16831972
     
    17812070  return -1;
    17822071}
     2072
     2073Guint FoFiTrueType::charToTag(const char *tagName)
     2074{
     2075  int n = strlen(tagName);
     2076  Guint tag = 0;
     2077  int i;
     2078
     2079  if (n > 4) n = 4;
     2080  for (i = 0;i < n;i++) {
     2081    tag <<= 8;
     2082    tag |= tagName[i] & 0xff;
     2083  }
     2084  for (;i < 4;i++) {
     2085    tag <<= 8;
     2086    tag |= ' ';
     2087  }
     2088  return tag;
     2089}
     2090
     2091/*
     2092  setup GSUB table data
     2093  Only supporting vertical text substitution.
     2094*/
     2095int FoFiTrueType::setupGSUB(const char *tagName)
     2096{
     2097  Guint gsubTable;
     2098  unsigned int i;
     2099  Guint scriptList, featureList;
     2100  Guint scriptCount;
     2101  Guint tag;
     2102  Guint scriptTable = 0;
     2103  Guint langSys;
     2104  Guint featureCount;
     2105  Guint featureIndex;
     2106  Guint ftable = 0;
     2107  Guint llist;
     2108  Guint scriptTag;
     2109  int x;
     2110  Guint pos;
     2111
     2112  if (tagName == 0) {
     2113    gsubFeatureTable = 0;
     2114    return 0;
     2115  }
     2116  scriptTag = charToTag(tagName);
     2117  /* read GSUB Header */
     2118  if ((x = seekTable("GSUB")) < 0) {
     2119    return 0; /* GSUB table not found */
     2120  }
     2121  gsubTable = tables[x].offset;
     2122  pos = gsubTable+4;
     2123  scriptList = getU16BE(pos,&parsedOk);
     2124  pos += 2;
     2125  featureList = getU16BE(pos,&parsedOk);
     2126  pos += 2;
     2127  llist = getU16BE(pos,&parsedOk);
     2128
     2129  gsubLookupList = llist+gsubTable; /* change to offset from top of file */
     2130  /* read script list table */
     2131  pos = gsubTable+scriptList;
     2132  scriptCount = getU16BE(pos,&parsedOk);
     2133  pos += 2;
     2134  /* find  script */
     2135  for (i = 0;i < scriptCount;i++) {
     2136    tag = getU32BE(pos,&parsedOk);
     2137    pos += 4;
     2138    scriptTable = getU16BE(pos,&parsedOk);
     2139    pos += 2;
     2140    if (tag == scriptTag) {
     2141      /* found */
     2142      break;
     2143    }
     2144  }
     2145  if (i >= scriptCount) {
     2146    /* not found */
     2147    return 0;
     2148  }
     2149
     2150  /* read script table */
     2151  /* use default language system */
     2152  pos = gsubTable+scriptList+scriptTable;
     2153  langSys = getU16BE(pos,&parsedOk);/* default language system */
     2154
     2155  /* read LangSys table */
     2156  if (langSys == 0) {
     2157    /* no ldefault LangSys */
     2158    return 0;
     2159  }
     2160
     2161  pos = gsubTable+scriptList+scriptTable+langSys+2;
     2162  featureIndex = getU16BE(pos,&parsedOk); /* ReqFeatureIndex */
     2163  pos += 2;
     2164
     2165  if (featureIndex != 0xffff) {
     2166    Guint tpos;
     2167    /* read feature record */
     2168    tpos = gsubTable+featureList;
     2169    featureCount = getU16BE(tpos,&parsedOk);
     2170    tpos = gsubTable+featureList+2+featureIndex*(4+2);
     2171    tag = getU32BE(tpos,&parsedOk);
     2172    tpos += 4;
     2173    if (tag == vrt2Tag) {
     2174      /* vrt2 is preferred, overwrite vert */
     2175      ftable = getU16BE(tpos,&parsedOk);
     2176      /* convert to offset from file top */
     2177      gsubFeatureTable = ftable+gsubTable+featureList;
     2178      return 0;
     2179    } else if (tag == vertTag) {
     2180      ftable = getU16BE(tpos,&parsedOk);
     2181    }
     2182  }
     2183  featureCount = getU16BE(pos,&parsedOk);
     2184  pos += 2;
     2185  /* find 'vrt2' or 'vert' feature */
     2186  for (i = 0;i < featureCount;i++) {
     2187    Guint oldPos;
     2188
     2189    featureIndex = getU16BE(pos,&parsedOk);
     2190    pos += 2;
     2191    oldPos = pos; /* save position */
     2192    /* read feature record */
     2193    pos = gsubTable+featureList+2+featureIndex*(4+2);
     2194    tag = getU32BE(pos,&parsedOk);
     2195    pos += 4;
     2196    if (tag == vrt2Tag) {
     2197      /* vrt2 is preferred, overwrite vert */
     2198      ftable = getU16BE(pos,&parsedOk);
     2199      break;
     2200    } else if (ftable == 0 && tag == vertTag) {
     2201      ftable = getU16BE(pos,&parsedOk);
     2202    }
     2203    pos = oldPos; /* restore old position */
     2204  }
     2205  if (ftable == 0) {
     2206    /* vert nor vrt2 are not found */
     2207    return 0;
     2208  }
     2209  /* convert to offset from file top */
     2210  gsubFeatureTable = ftable+gsubTable+featureList;
     2211  return 0;
     2212}
     2213
     2214Guint FoFiTrueType::doMapToVertGID(Guint orgGID)
     2215{
     2216  Guint lookupCount;
     2217  Guint lookupListIndex;
     2218  Guint i;
     2219  Guint gid = 0;
     2220  Guint pos;
     2221
     2222  pos = gsubFeatureTable+2;
     2223  lookupCount = getU16BE(pos,&parsedOk);
     2224  pos += 2;
     2225  for (i = 0;i < lookupCount;i++) {
     2226    lookupListIndex = getU16BE(pos,&parsedOk);
     2227    pos += 2;
     2228    if ((gid = scanLookupList(lookupListIndex,orgGID)) != 0) {
     2229      break;
     2230    }
     2231  }
     2232  return gid;
     2233}
     2234
     2235Guint FoFiTrueType::mapToVertGID(Guint orgGID)
     2236{
     2237  Guint mapped;
     2238
     2239  if (gsubFeatureTable == 0) return orgGID;
     2240  if ((mapped = doMapToVertGID(orgGID)) != 0) {
     2241    return mapped;
     2242  }
     2243  return orgGID;
     2244}
     2245
     2246Guint FoFiTrueType::scanLookupList(Guint listIndex, Guint orgGID)
     2247{
     2248  Guint lookupTable;
     2249  Guint subTableCount;
     2250  Guint subTable;
     2251  Guint i;
     2252  Guint gid = 0;
     2253  Guint pos;
     2254
     2255  if (gsubLookupList == 0) return 0; /* no lookup list */
     2256  pos = gsubLookupList+2+listIndex*2;
     2257  lookupTable = getU16BE(pos,&parsedOk);
     2258  /* read lookup table */
     2259  pos = gsubLookupList+lookupTable+4;
     2260  subTableCount = getU16BE(pos,&parsedOk);
     2261  pos += 2;;
     2262  for (i = 0;i < subTableCount;i++) {
     2263    subTable = getU16BE(pos,&parsedOk);
     2264    pos += 2;
     2265    if ((gid = scanLookupSubTable(gsubLookupList+lookupTable+subTable,orgGID))
     2266         != 0) break;
     2267  }
     2268  return gid;
     2269}
     2270
     2271Guint FoFiTrueType::scanLookupSubTable(Guint subTable, Guint orgGID)
     2272{
     2273  Guint format;
     2274  Guint coverage;
     2275  int delta;
     2276  int glyphCount;
     2277  Guint substitute;
     2278  Guint gid = 0;
     2279  int coverageIndex;
     2280  int pos;
     2281
     2282  pos = subTable;
     2283  format = getU16BE(pos,&parsedOk);
     2284  pos += 2;
     2285  coverage = getU16BE(pos,&parsedOk);
     2286  pos += 2;
     2287  if ((coverageIndex =
     2288     checkGIDInCoverage(subTable+coverage,orgGID)) >= 0) {
     2289    switch (format) {
     2290    case 1:
     2291      /* format 1 */
     2292      delta = getS16BE(pos,&parsedOk);
     2293      pos += 2;
     2294      gid = orgGID+delta;
     2295      break;
     2296    case 2:
     2297      /* format 2 */
     2298      glyphCount = getS16BE(pos,&parsedOk);
     2299      pos += 2;
     2300      if (glyphCount > coverageIndex) {
     2301        pos += coverageIndex*2;
     2302        substitute = getU16BE(pos,&parsedOk);
     2303        gid = substitute;
     2304      }
     2305      break;
     2306    default:
     2307      /* unknown format */
     2308      break;
     2309    }
     2310  }
     2311  return gid;
     2312}
     2313
     2314int FoFiTrueType::checkGIDInCoverage(Guint coverage, Guint orgGID)
     2315{
     2316  int index = -1;
     2317  Guint format;
     2318  Guint count;
     2319  Guint i;
     2320  Guint pos;
     2321
     2322  pos = coverage;
     2323  format = getU16BE(pos,&parsedOk);
     2324  pos += 2;
     2325  switch (format) {
     2326  case 1:
     2327    count = getU16BE(pos,&parsedOk);
     2328    pos += 2;
     2329    for (i = 0;i < count;i++) {
     2330      Guint gid;
     2331
     2332      gid = getU16BE(pos,&parsedOk);
     2333      pos += 2;
     2334      if (gid == orgGID) {
     2335        /* found */
     2336        index = i;
     2337        break;
     2338      } else if (gid > orgGID) {
     2339        /* not found */
     2340        break;
     2341      }
     2342    }
     2343    break;
     2344  case 2:
     2345    count = getU16BE(pos,&parsedOk);
     2346    pos += 2;
     2347    for (i = 0;i < count;i++) {
     2348      Guint startGID, endGID;
     2349      Guint startIndex;
     2350
     2351      startGID = getU16BE(pos,&parsedOk);
     2352      pos += 2;
     2353      endGID = getU16BE(pos,&parsedOk);
     2354      pos += 2;
     2355      startIndex = getU16BE(pos,&parsedOk);
     2356      pos += 2;
     2357      if (startGID <= orgGID && orgGID <= endGID) {
     2358        /* found */
     2359        index = startIndex+orgGID-startGID;
     2360        break;
     2361      } else if (orgGID <= endGID) {
     2362        /* not found */
     2363        break;
     2364      }
     2365    }
     2366    break;
     2367  default:
     2368    break;
     2369  }
     2370  return index;
     2371}
     2372
Note: See TracChangeset for help on using the changeset viewer.