Changeset 250 for trunk/poppler


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

Location:
trunk/poppler/mypoppler
Files:
15 added
2 deleted
133 edited
1 moved

Legend:

Unmodified
Added
Removed
  • trunk/poppler/mypoppler/config.h

    r134 r250  
    156156
    157157#define POPPLER_DATADIR "."
     158
     159#define HAVE_GETTIMEOFDAY 1
  • trunk/poppler/mypoppler/fofi/FoFiBase.cc

    r2 r250  
    1515#include <stdio.h>
    1616#include "goo/gmem.h"
     17#include "poppler/Error.h"
    1718#include "FoFiBase.h"
    1819
     
    3940
    4041  if (!(f = fopen(fileName, "rb"))) {
     42    error(-1, "Cannot open '%s'", fileName);
    4143    return NULL;
    4244  }
    43   fseek(f, 0, SEEK_END);
     45  if (fseek(f, 0, SEEK_END) != 0) {
     46    error(-1, "Cannot seek to end of '%s'", fileName);
     47    fclose(f);
     48    return NULL;
     49  }
    4450  n = (int)ftell(f);
    45   fseek(f, 0, SEEK_SET);
     51  if (fseek(f, 0, SEEK_SET) != 0) {
     52    error(-1, "Cannot seek to start of '%s'", fileName);
     53    fclose(f);
     54    return NULL;
     55  }
    4656  buf = (char *)gmalloc(n);
    4757  if ((int)fread(buf, 1, n, f) != n) {
  • 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
  • trunk/poppler/mypoppler/fofi/FoFiTrueType.h

    r2 r250  
    3535  static FoFiTrueType *load(char *fileName, int faceIndexA=0);
    3636
    37   FoFiTrueType(char *fileA, int lenA, GBool freeFileDataA, int faceIndexA=0);
    3837  virtual ~FoFiTrueType();
     38
     39  // Returns true if this an OpenType font containing CFF data, false
     40  // if it's a TrueType font (or OpenType font with TrueType data).
     41  GBool isOpenTypeCFF() { return openTypeCFF; }
    3942
    4043  // Return the number of cmaps defined by this font.
     
    5255
    5356  // Return the GID corresponding to <c> according to the <i>th cmap.
    54   Gushort mapCodeToGID(int i, int c);
     57  Gushort mapCodeToGID(int i, Guint c);
     58
     59  // map gid to vertical glyph gid if exist.
     60  //   if not exist return original gid
     61  Guint mapToVertGID(Guint orgGID);
    5562
    5663  // Returns the GID corresponding to <name> according to the post
     
    5865  // font does not have a post table.
    5966  int mapNameToGID(char *name);
     67
     68  // Return the mapping from CIDs to GIDs, and return the number of
     69  // CIDs in *<nCIDs>.  This is only useful for CID fonts.  (Only
     70  // useful for OpenType CFF fonts.)
     71  Gushort *getCIDToGIDMap(int *nCIDs);
    6072
    6173  // Returns the least restrictive embedding licensing right (as
     
    7486  // If <encoding> is NULL, the encoding is unknown or undefined.  The
    7587  // <codeToGID> array specifies the mapping from char codes to GIDs.
     88  // (Not useful for OpenType CFF fonts.)
    7689  void convertToType42(char *psName, char **encoding,
    7790                       Gushort *codeToGID,
    7891                       FoFiOutputFunc outputFunc, void *outputStream);
     92
     93  // Convert to a Type 1 font, suitable for embedding in a PostScript
     94  // file.  This is only useful with 8-bit fonts.  If <newEncoding> is
     95  // not NULL, it will be used in place of the encoding in the Type 1C
     96  // font.  If <ascii> is true the eexec section will be hex-encoded,
     97  // otherwise it will be left as binary data.  If <psName> is
     98  // non-NULL, it will be used as the PostScript font name.  (Only
     99  // useful for OpenType CFF fonts.)
     100  void convertToType1(char *psName, char **newEncoding, GBool ascii,
     101                      FoFiOutputFunc outputFunc, void *outputStream);
    79102
    80103  // Convert to a Type 2 CIDFont, suitable for embedding in a
     
    82105  // name (so we don't need to depend on the 'name' table in the
    83106  // font).  The <cidMap> array maps CIDs to GIDs; it has <nCIDs>
    84   // entries.
     107  // entries.  (Not useful for OpenType CFF fonts.)
    85108  void convertToCIDType2(char *psName, Gushort *cidMap, int nCIDs,
    86109                         GBool needVerticalMetrics,
     110                         FoFiOutputFunc outputFunc, void *outputStream);
     111
     112  // Convert to a Type 0 CIDFont, suitable for embedding in a
     113  // PostScript file.  <psName> will be used as the PostScript font
     114  // name.  (Only useful for OpenType CFF fonts.)
     115  void convertToCIDType0(char *psName,
    87116                         FoFiOutputFunc outputFunc, void *outputStream);
    88117
     
    91120  // PostScript font name (so we don't need to depend on the 'name'
    92121  // table in the font).  The <cidMap> array maps CIDs to GIDs; it has
    93   // <nCIDs> entries.
     122  // <nCIDs> entries.  (Not useful for OpenType CFF fonts.)
    94123  void convertToType0(char *psName, Gushort *cidMap, int nCIDs,
    95124                      GBool needVerticalMetrics,
     125                      FoFiOutputFunc outputFunc, void *outputStream);
     126
     127  // Convert to a Type 0 (but non-CID) composite font, suitable for
     128  // embedding in a PostScript file.  <psName> will be used as the
     129  // PostScript font name.  (Only useful for OpenType CFF fonts.)
     130  void convertToType0(char *psName,
    96131                      FoFiOutputFunc outputFunc, void *outputStream);
    97132
     
    100135  // to <name>.  If <codeToGID> is non-NULL, the font is re-encoded,
    101136  // using a Windows Unicode cmap.  If <name> is NULL and the font is
    102   // complete and correct, it will be written unmodified.
     137  // complete and correct, it will be written unmodified.  (Not useful
     138  // for OpenType CFF fonts.)
    103139  void writeTTF(FoFiOutputFunc outputFunc, void *outputStream,
    104140                char *name = NULL, Gushort *codeToGID = NULL);
    105141
     142  int setupGSUB(const char *tagName);
    106143private:
    107144
     145  FoFiTrueType(char *fileA, int lenA, GBool freeFileDataA, int faceIndexA);
    108146  void cvtEncoding(char **encoding,
    109147                   FoFiOutputFunc outputFunc,
     
    123161  void readPostTable();
    124162  int seekTable(char *tag);
     163  Guint charToTag(const char *tagName);
     164  Guint doMapToVertGID(Guint orgGID);
     165  Guint scanLookupList(Guint listIndex, Guint orgGID);
     166  Guint scanLookupSubTable(Guint subTable, Guint orgGID);
     167  int checkGIDInCoverage(Guint coverage, Guint orgGID);
    125168
    126169  TrueTypeTable *tables;
     
    132175  int bbox[4];
    133176  GooHash *nameToGID;
     177  GBool openTypeCFF;
    134178
    135179  GBool parsedOk;
    136180  int faceIndex;
     181  Guint gsubFeatureTable;
     182  Guint gsubLookupList;
    137183};
    138184
  • trunk/poppler/mypoppler/fofi/FoFiType1.cc

    r2 r250  
    7676                             FoFiOutputFunc outputFunc, void *outputStream) {
    7777  char buf[512];
    78   char *line;
     78  char *line, *line2, *p;
    7979  int i;
    8080
     
    102102  (*outputFunc)(outputStream, "readonly def\n", 13);
    103103 
    104   // copy everything after the encoding
     104  // find the end of the encoding data
     105  //~ this ought to parse PostScript tokens
    105106  if (!strncmp(line, "/Encoding StandardEncoding def", 30)) {
    106107    line = getNextLine(line);
    107108  } else {
    108     for (line = getNextLine(line);
    109          line && strncmp(line, "readonly def", 12);
    110          line = getNextLine(line)) ;
     109    // skip "/Encoding" + one whitespace char,
     110    // then look for 'def' preceded by PostScript whitespace
     111    p = line + 10;
     112    line = NULL;
     113    for (; p < (char *)file + len; ++p) {
     114      if ((*p == ' ' || *p == '\t' || *p == '\x0a' ||
     115           *p == '\x0d' || *p == '\x0c' || *p == '\0') &&
     116          p + 4 <= (char *)file + len &&
     117          !strncmp(p + 1, "def", 3)) {
     118        line = p + 4;
     119        break;
     120      }
     121    }
     122  }
     123
     124  // some fonts have two /Encoding entries in their dictionary, so we
     125  // check for a second one here
     126  if (line) {
     127    for (line2 = line, i = 0;
     128         i < 20 && line2 && strncmp(line2, "/Encoding", 9);
     129         line2 = getNextLine(line2), ++i) ;
     130    if (i < 20 && line2) {
     131      (*outputFunc)(outputStream, line, line2 - line);
     132      if (!strncmp(line2, "/Encoding StandardEncoding def", 30)) {
     133        line = getNextLine(line2);
     134      } else {
     135        // skip "/Encoding" + one whitespace char,
     136        // then look for 'def' preceded by PostScript whitespace
     137        p = line2 + 10;
     138        line = NULL;
     139        for (; p < (char *)file + len; ++p) {
     140          if ((*p == ' ' || *p == '\t' || *p == '\x0a' ||
     141               *p == '\x0d' || *p == '\x0c' || *p == '\0') &&
     142              p + 4 <= (char *)file + len &&
     143              !strncmp(p + 1, "def", 3)) {
     144            line = p + 4;
     145            break;
     146          }
     147        }
     148      }
     149    }
     150
     151    // copy everything after the encoding
    111152    if (line) {
    112       line = getNextLine(line);
    113     }
    114   }
    115   if (line) {
    116     (*outputFunc)(outputStream, line, ((char *)file + len) - line);
     153      (*outputFunc)(outputStream, line, ((char *)file + len) - line);
     154    }
    117155  }
    118156}
     
    179217            c = *p2;
    180218            *p2 = '\0';
    181             if ((code = atoi(p)) < 256) {
    182               *p2 = c;
     219            code = atoi(p);
     220            *p2 = c;
     221            if (code == 8 && *p2 == '#') {
     222              code = 0;
     223              for (++p2; *p2 >= '0' && *p2 <= '7'; ++p2) {
     224                code = code * 8 + (*p2 - '0');
     225              }
     226            }
     227            if (code < 256) {
    183228              for (p = p2; *p == ' ' || *p == '\t'; ++p) ;
    184229              if (*p == '/') {
  • trunk/poppler/mypoppler/fofi/FoFiType1C.cc

    r2 r250  
    130130}
    131131
    132 void FoFiType1C::convertToType1(char **newEncoding, GBool ascii,
     132void FoFiType1C::convertToType1(char *psName, char **newEncoding, GBool ascii,
    133133                                FoFiOutputFunc outputFunc,
    134134                                void *outputStream) {
     135  int psNameLen;
    135136  Type1CEexecBuf eb;
    136137  Type1CIndex subrIdx;
    137138  Type1CIndexVal val;
    138   char buf[512];
     139  GooString *buf;
     140  char buf2[256];
    139141  char **enc;
    140142  GBool ok;
    141143  int i;
    142144
     145  if (psName) {
     146    psNameLen = strlen(psName);
     147  } else {
     148    psName = name->getCString();
     149    psNameLen = name->getLength();
     150  }
     151
    143152  // write header and font dictionary, up to encoding
    144153  ok = gTrue;
    145154  (*outputFunc)(outputStream, "%!FontType1-1.0: ", 17);
    146   (*outputFunc)(outputStream, name->getCString(), name->getLength());
     155  (*outputFunc)(outputStream, psName, psNameLen);
    147156  if (topDict.versionSID != 0) {
    148     getString(topDict.versionSID, buf, &ok);
    149     (*outputFunc)(outputStream, buf, strlen(buf));
     157    getString(topDict.versionSID, buf2, &ok);
     158    (*outputFunc)(outputStream, buf2, strlen(buf2));
    150159  }
    151160  (*outputFunc)(outputStream, "\n", 1);
     
    157166  if (topDict.versionSID != 0) {
    158167    (*outputFunc)(outputStream, "/version (", 10);
    159     (*outputFunc)(outputStream, buf, strlen(buf));
     168    (*outputFunc)(outputStream, buf2, strlen(buf2));
    160169    (*outputFunc)(outputStream, ") readonly def\n", 15);
    161170  }
    162171  if (topDict.noticeSID != 0) {
    163     getString(topDict.noticeSID, buf, &ok);
     172    getString(topDict.noticeSID, buf2, &ok);
    164173    (*outputFunc)(outputStream, "/Notice (", 9);
    165     (*outputFunc)(outputStream, buf, strlen(buf));
     174    (*outputFunc)(outputStream, buf2, strlen(buf2));
    166175    (*outputFunc)(outputStream, ") readonly def\n", 15);
    167176  }
    168177  if (topDict.copyrightSID != 0) {
    169     getString(topDict.copyrightSID, buf, &ok);
     178    getString(topDict.copyrightSID, buf2, &ok);
    170179    (*outputFunc)(outputStream, "/Copyright (", 12);
    171     (*outputFunc)(outputStream, buf, strlen(buf));
     180    (*outputFunc)(outputStream, buf2, strlen(buf2));
    172181    (*outputFunc)(outputStream, ") readonly def\n", 15);
    173182  }
    174183  if (topDict.fullNameSID != 0) {
    175     getString(topDict.fullNameSID, buf, &ok);
     184    getString(topDict.fullNameSID, buf2, &ok);
    176185    (*outputFunc)(outputStream, "/FullName (", 11);
    177     (*outputFunc)(outputStream, buf, strlen(buf));
     186    (*outputFunc)(outputStream, buf2, strlen(buf2));
    178187    (*outputFunc)(outputStream, ") readonly def\n", 15);
    179188  }
    180189  if (topDict.familyNameSID != 0) {
    181     getString(topDict.familyNameSID, buf, &ok);
     190    getString(topDict.familyNameSID, buf2, &ok);
    182191    (*outputFunc)(outputStream, "/FamilyName (", 13);
    183     (*outputFunc)(outputStream, buf, strlen(buf));
     192    (*outputFunc)(outputStream, buf2, strlen(buf2));
    184193    (*outputFunc)(outputStream, ") readonly def\n", 15);
    185194  }
    186195  if (topDict.weightSID != 0) {
    187     getString(topDict.weightSID, buf, &ok);
     196    getString(topDict.weightSID, buf2, &ok);
    188197    (*outputFunc)(outputStream, "/Weight (", 9);
    189     (*outputFunc)(outputStream, buf, strlen(buf));
     198    (*outputFunc)(outputStream, buf2, strlen(buf2));
    190199    (*outputFunc)(outputStream, ") readonly def\n", 15);
    191200  }
     
    195204    (*outputFunc)(outputStream, "/isFixedPitch false def\n", 24);
    196205  }
    197   sprintf(buf, "/ItalicAngle %g def\n", topDict.italicAngle);
    198   (*outputFunc)(outputStream, buf, strlen(buf));
    199   sprintf(buf, "/UnderlinePosition %g def\n", topDict.underlinePosition);
    200   (*outputFunc)(outputStream, buf, strlen(buf));
    201   sprintf(buf, "/UnderlineThickness %g def\n", topDict.underlineThickness);
    202   (*outputFunc)(outputStream, buf, strlen(buf));
     206  buf = GooString::format("/ItalicAngle {0:.4g} def\n", topDict.italicAngle);
     207  (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
     208  delete buf;
     209  buf = GooString::format("/UnderlinePosition {0:.4g} def\n",
     210                        topDict.underlinePosition);
     211  (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
     212  delete buf;
     213  buf = GooString::format("/UnderlineThickness {0:.4g} def\n",
     214                        topDict.underlineThickness);
     215  (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
     216  delete buf;
    203217  (*outputFunc)(outputStream, "end readonly def\n", 17);
    204218  (*outputFunc)(outputStream, "/FontName /", 11);
    205   (*outputFunc)(outputStream, name->getCString(), name->getLength());
     219  (*outputFunc)(outputStream, psName, psNameLen);
    206220  (*outputFunc)(outputStream, " def\n", 5);
    207   sprintf(buf, "/PaintType %d def\n", topDict.paintType);
    208   (*outputFunc)(outputStream, buf, strlen(buf));
     221  buf = GooString::format("/PaintType {0:d} def\n", topDict.paintType);
     222  (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
     223  delete buf;
    209224  (*outputFunc)(outputStream, "/FontType 1 def\n", 16);
    210   sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] readonly def\n",
    211           topDict.fontMatrix[0], topDict.fontMatrix[1], topDict.fontMatrix[2],
    212           topDict.fontMatrix[3], topDict.fontMatrix[4], topDict.fontMatrix[5]);
    213   (*outputFunc)(outputStream, buf, strlen(buf));
    214   sprintf(buf, "/FontBBox [%g %g %g %g] readonly def\n",
    215           topDict.fontBBox[0], topDict.fontBBox[1],
    216           topDict.fontBBox[2], topDict.fontBBox[3]);
    217   (*outputFunc)(outputStream, buf, strlen(buf));
    218   sprintf(buf, "/StrokeWidth %g def\n", topDict.strokeWidth);
    219   (*outputFunc)(outputStream, buf, strlen(buf));
     225  buf = GooString::format("/FontMatrix [{0:.8g} {1:.8g} {2:.8g} {3:.8g} {4:.8g} {5:.8g}] readonly def\n",
     226                        topDict.fontMatrix[0], topDict.fontMatrix[1],
     227                        topDict.fontMatrix[2], topDict.fontMatrix[3],
     228                        topDict.fontMatrix[4], topDict.fontMatrix[5]);
     229  (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
     230  delete buf;
     231  buf = GooString::format("/FontBBox [{0:.4g} {1:.4g} {2:.4g} {3:.4g}] readonly def\n",
     232                        topDict.fontBBox[0], topDict.fontBBox[1],
     233                        topDict.fontBBox[2], topDict.fontBBox[3]);
     234  (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
     235  delete buf;
     236  buf = GooString::format("/StrokeWidth {0:.4g} def\n", topDict.strokeWidth);
     237  (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
     238  delete buf;
    220239  if (topDict.uniqueID != 0) {
    221     sprintf(buf, "/UniqueID %d def\n", topDict.uniqueID);
    222     (*outputFunc)(outputStream, buf, strlen(buf));
     240    buf = GooString::format("/UniqueID {0:d} def\n", topDict.uniqueID);
     241    (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
     242    delete buf;
    223243  }
    224244
     
    234254    for (i = 0; i < 256; ++i) {
    235255      if (enc[i]) {
    236         sprintf(buf, "dup %d /%s put\n", i, enc[i]);
    237         (*outputFunc)(outputStream, buf, strlen(buf));
     256        buf = GooString::format("dup {0:d} /{1:s} put\n", i, enc[i]);
     257        (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
     258        delete buf;
    238259      }
    239260    }
     
    262283    eexecWrite(&eb, "/BlueValues [");
    263284    for (i = 0; i < privateDicts[0].nBlueValues; ++i) {
    264       sprintf(buf, "%s%d", i > 0 ? " " : "", privateDicts[0].blueValues[i]);
    265       eexecWrite(&eb, buf);
     285      buf = GooString::format("{0:s}{1:d}",
     286                            i > 0 ? " " : "", privateDicts[0].blueValues[i]);
     287      eexecWrite(&eb, buf->getCString());
     288      delete buf;
    266289    }
    267290    eexecWrite(&eb, "] def\n");
     
    270293    eexecWrite(&eb, "/OtherBlues [");
    271294    for (i = 0; i < privateDicts[0].nOtherBlues; ++i) {
    272       sprintf(buf, "%s%d", i > 0 ? " " : "", privateDicts[0].otherBlues[i]);
    273       eexecWrite(&eb, buf);
     295      buf = GooString::format("{0:s}{1:d}",
     296                            i > 0 ? " " : "", privateDicts[0].otherBlues[i]);
     297      eexecWrite(&eb, buf->getCString());
     298      delete buf;
    274299    }
    275300    eexecWrite(&eb, "] def\n");
     
    278303    eexecWrite(&eb, "/FamilyBlues [");
    279304    for (i = 0; i < privateDicts[0].nFamilyBlues; ++i) {
    280       sprintf(buf, "%s%d", i > 0 ? " " : "", privateDicts[0].familyBlues[i]);
    281       eexecWrite(&eb, buf);
     305      buf = GooString::format("{0:s}{1:d}",
     306                            i > 0 ? " " : "", privateDicts[0].familyBlues[i]);
     307      eexecWrite(&eb, buf->getCString());
     308      delete buf;
    282309    }
    283310    eexecWrite(&eb, "] def\n");
     
    286313    eexecWrite(&eb, "/FamilyOtherBlues [");
    287314    for (i = 0; i < privateDicts[0].nFamilyOtherBlues; ++i) {
    288       sprintf(buf, "%s%d", i > 0 ? " " : "",
    289               privateDicts[0].familyOtherBlues[i]);
    290       eexecWrite(&eb, buf);
     315      buf = GooString::format("{0:s}{1:d}", i > 0 ? " " : "",
     316                            privateDicts[0].familyOtherBlues[i]);
     317      eexecWrite(&eb, buf->getCString());
     318      delete buf;
    291319    }
    292320    eexecWrite(&eb, "] def\n");
    293321  }
    294322  if (privateDicts[0].blueScale != 0.039625) {
    295     sprintf(buf, "/BlueScale %g def\n", privateDicts[0].blueScale);
    296     eexecWrite(&eb, buf);
     323    buf = GooString::format("/BlueScale {0:.4g} def\n",
     324                          privateDicts[0].blueScale);
     325    eexecWrite(&eb, buf->getCString());
     326    delete buf;
    297327  }
    298328  if (privateDicts[0].blueShift != 7) {
    299     sprintf(buf, "/BlueShift %d def\n", privateDicts[0].blueShift);
    300     eexecWrite(&eb, buf);
     329    buf = GooString::format("/BlueShift {0:d} def\n", privateDicts[0].blueShift);
     330    eexecWrite(&eb, buf->getCString());
     331    delete buf;
    301332  }
    302333  if (privateDicts[0].blueFuzz != 1) {
    303     sprintf(buf, "/BlueFuzz %d def\n", privateDicts[0].blueFuzz);
    304     eexecWrite(&eb, buf);
     334    buf = GooString::format("/BlueFuzz {0:d} def\n", privateDicts[0].blueFuzz);
     335    eexecWrite(&eb, buf->getCString());
     336    delete buf;
    305337  }
    306338  if (privateDicts[0].hasStdHW) {
    307     sprintf(buf, "/StdHW [%g] def\n", privateDicts[0].stdHW);
    308     eexecWrite(&eb, buf);
     339    buf = GooString::format("/StdHW [{0:.4g}] def\n", privateDicts[0].stdHW);
     340    eexecWrite(&eb, buf->getCString());
     341    delete buf;
    309342  }
    310343  if (privateDicts[0].hasStdVW) {
    311     sprintf(buf, "/StdVW [%g] def\n", privateDicts[0].stdVW);
    312     eexecWrite(&eb, buf);
     344    buf = GooString::format("/StdVW [{0:.4g}] def\n", privateDicts[0].stdVW);
     345    eexecWrite(&eb, buf->getCString());
     346    delete buf;
    313347  }
    314348  if (privateDicts[0].nStemSnapH) {
    315349    eexecWrite(&eb, "/StemSnapH [");
    316350    for (i = 0; i < privateDicts[0].nStemSnapH; ++i) {
    317       sprintf(buf, "%s%g", i > 0 ? " " : "", privateDicts[0].stemSnapH[i]);
    318       eexecWrite(&eb, buf);
     351      buf = GooString::format("{0:s}{1:.4g}",
     352                            i > 0 ? " " : "", privateDicts[0].stemSnapH[i]);
     353      eexecWrite(&eb, buf->getCString());
     354      delete buf;
    319355    }
    320356    eexecWrite(&eb, "] def\n");
     
    323359    eexecWrite(&eb, "/StemSnapV [");
    324360    for (i = 0; i < privateDicts[0].nStemSnapV; ++i) {
    325       sprintf(buf, "%s%g", i > 0 ? " " : "", privateDicts[0].stemSnapV[i]);
    326       eexecWrite(&eb, buf);
     361      buf = GooString::format("{0:s}{1:.4g}",
     362                            i > 0 ? " " : "", privateDicts[0].stemSnapV[i]);
     363      eexecWrite(&eb, buf->getCString());
     364      delete buf;
    327365    }
    328366    eexecWrite(&eb, "] def\n");
    329367  }
    330368  if (privateDicts[0].hasForceBold) {
    331     sprintf(buf, "/ForceBold %s def\n",
    332             privateDicts[0].forceBold ? "true" : "false");
    333     eexecWrite(&eb, buf);
     369    buf = GooString::format("/ForceBold {0:s} def\n",
     370                          privateDicts[0].forceBold ? "true" : "false");
     371    eexecWrite(&eb, buf->getCString());
     372    delete buf;
    334373  }
    335374  if (privateDicts[0].forceBoldThreshold != 0) {
    336     sprintf(buf, "/ForceBoldThreshold %g def\n",
    337             privateDicts[0].forceBoldThreshold);
    338     eexecWrite(&eb, buf);
     375    buf = GooString::format("/ForceBoldThreshold {0:.4g} def\n",
     376                          privateDicts[0].forceBoldThreshold);
     377    eexecWrite(&eb, buf->getCString());
     378    delete buf;
    339379  }
    340380  if (privateDicts[0].languageGroup != 0) {
    341     sprintf(buf, "/LanguageGroup %d def\n", privateDicts[0].languageGroup);
    342     eexecWrite(&eb, buf);
     381    buf = GooString::format("/LanguageGroup {0:d} def\n",
     382                          privateDicts[0].languageGroup);
     383    eexecWrite(&eb, buf->getCString());
     384    delete buf;
    343385  }
    344386  if (privateDicts[0].expansionFactor != 0.06) {
    345     sprintf(buf, "/ExpansionFactor %g def\n", privateDicts[0].expansionFactor);
    346     eexecWrite(&eb, buf);
     387    buf = GooString::format("/ExpansionFactor {0:.4g} def\n",
     388                          privateDicts[0].expansionFactor);
     389    eexecWrite(&eb, buf->getCString());
     390    delete buf;
    347391  }
    348392
     
    355399
    356400  // write the CharStrings
    357   sprintf(buf, "2 index /CharStrings %d dict dup begin\n", nGlyphs);
    358   eexecWrite(&eb, buf);
     401  buf = GooString::format("2 index /CharStrings {0:d} dict dup begin\n",
     402                        nGlyphs);
     403  eexecWrite(&eb, buf->getCString());
     404  delete buf;
    359405  for (i = 0; i < nGlyphs; ++i) {
    360406    ok = gTrue;
    361407    getIndexVal(&charStringsIdx, i, &val, &ok);
    362408    if (ok) {
    363       getString(charset[i], buf, &ok);
     409      getString(charset[i], buf2, &ok);
    364410      if (ok) {
    365         eexecCvtGlyph(&eb, buf, val.pos, val.len, &subrIdx, &privateDicts[0]);
     411        eexecCvtGlyph(&eb, buf2, val.pos, val.len, &subrIdx, &privateDicts[0]);
    366412      }
    367413    }
     
    393439  Type1CIndexVal val;
    394440  int nCIDs, gdBytes;
    395   char buf[512], buf2[512];
     441  GooString *buf;
     442  char buf2[256];
    396443  GBool ok;
    397444  int gid, offset, n, i, j, k;
     
    457504  if (topDict.registrySID > 0 && topDict.orderingSID > 0) {
    458505    ok = gTrue;
    459     getString(topDict.registrySID, buf, &ok);
     506    getString(topDict.registrySID, buf2, &ok);
    460507    if (ok) {
    461508      (*outputFunc)(outputStream, "  /Registry (", 13);
    462       (*outputFunc)(outputStream, buf, strlen(buf));
     509      (*outputFunc)(outputStream, buf2, strlen(buf2));
    463510      (*outputFunc)(outputStream, ") def\n", 6);
    464511    }
    465512    ok = gTrue;
    466     getString(topDict.orderingSID, buf, &ok);
     513    getString(topDict.orderingSID, buf2, &ok);
    467514    if (ok) {
    468515      (*outputFunc)(outputStream, "  /Ordering (", 13);
    469       (*outputFunc)(outputStream, buf, strlen(buf));
     516      (*outputFunc)(outputStream, buf2, strlen(buf2));
    470517      (*outputFunc)(outputStream, ") def\n", 6);
    471518    }
     
    474521    (*outputFunc)(outputStream, "  /Ordering (Identity) def\n", 27);
    475522  }
    476   sprintf(buf, "  /Supplement %d def\n", topDict.supplement);
    477   (*outputFunc)(outputStream, buf, strlen(buf));
     523  buf = GooString::format("  /Supplement {0:d} def\n", topDict.supplement);
     524  (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
     525  delete buf;
    478526  (*outputFunc)(outputStream, "end def\n", 8);
    479527  if (topDict.hasFontMatrix) {
    480     sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] def\n",
    481             topDict.fontMatrix[0], topDict.fontMatrix[1],
    482             topDict.fontMatrix[2], topDict.fontMatrix[3],
    483             topDict.fontMatrix[4], topDict.fontMatrix[5]);
    484     (*outputFunc)(outputStream, buf, strlen(buf));
     528    buf = GooString::format("/FontMatrix [{0:.8g} {1:.8g} {2:.8g} {3:.8g} {4:.8g} {5:.8g}] def\n",
     529                          topDict.fontMatrix[0], topDict.fontMatrix[1],
     530                          topDict.fontMatrix[2], topDict.fontMatrix[3],
     531                          topDict.fontMatrix[4], topDict.fontMatrix[5]);
     532    (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
     533    delete buf;
    485534  } else if (privateDicts[0].hasFontMatrix) {
    486535    (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
     
    489538                  "/FontMatrix [0.001 0 0 0.001 0 0] def\n", 38);
    490539  }
    491   sprintf(buf, "/FontBBox [%g %g %g %g] def\n",
    492           topDict.fontBBox[0], topDict.fontBBox[1],
    493           topDict.fontBBox[2], topDict.fontBBox[3]);
    494   (*outputFunc)(outputStream, buf, strlen(buf));
     540  buf = GooString::format("/FontBBox [{0:.4g} {1:.4g} {2:.4g} {3:.4g}] def\n",
     541                        topDict.fontBBox[0], topDict.fontBBox[1],
     542                        topDict.fontBBox[2], topDict.fontBBox[3]);
     543  (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
     544  delete buf;
    495545  (*outputFunc)(outputStream, "/FontInfo 1 dict dup begin\n", 27);
    496546  (*outputFunc)(outputStream, "  /FSType 8 def\n", 16);
     
    498548
    499549  // CIDFont-specific entries
    500   sprintf(buf, "/CIDCount %d def\n", nCIDs);
    501   (*outputFunc)(outputStream, buf, strlen(buf));
     550  buf = GooString::format("/CIDCount {0:d} def\n", nCIDs);
     551  (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
     552  delete buf;
    502553  (*outputFunc)(outputStream, "/FDBytes 1 def\n", 15);
    503   sprintf(buf, "/GDBytes %d def\n", gdBytes);
    504   (*outputFunc)(outputStream, buf, strlen(buf));
     554  buf = GooString::format("/GDBytes {0:d} def\n", gdBytes);
     555  (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
     556  delete buf;
    505557  (*outputFunc)(outputStream, "/CIDMapOffset 0 def\n", 20);
    506558  if (topDict.paintType != 0) {
    507     sprintf(buf, "/PaintType %d def\n", topDict.paintType);
    508     (*outputFunc)(outputStream, buf, strlen(buf));
    509     sprintf(buf, "/StrokeWidth %g def\n", topDict.strokeWidth);
    510     (*outputFunc)(outputStream, buf, strlen(buf));
     559    buf = GooString::format("/PaintType {0:d} def\n", topDict.paintType);
     560    (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
     561    delete buf;
     562    buf = GooString::format("/StrokeWidth {0:.4g} def\n", topDict.strokeWidth);
     563    (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
     564    delete buf;
    511565  }
    512566
    513567  // FDArray entry
    514   sprintf(buf, "/FDArray %d array\n", nFDs);
    515   (*outputFunc)(outputStream, buf, strlen(buf));
     568  buf = GooString::format("/FDArray {0:d} array\n", nFDs);
     569  (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
     570  delete buf;
    516571  for (i = 0; i < nFDs; ++i) {
    517     sprintf(buf, "dup %d 10 dict begin\n", i);
    518     (*outputFunc)(outputStream, buf, strlen(buf));
     572    buf = GooString::format("dup {0:d} 10 dict begin\n", i);
     573    (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
     574    delete buf;
    519575    (*outputFunc)(outputStream, "/FontType 1 def\n", 16);
    520576    if (privateDicts[i].hasFontMatrix) {
    521       sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] def\n",
    522               privateDicts[i].fontMatrix[0],
    523               privateDicts[i].fontMatrix[1],
    524               privateDicts[i].fontMatrix[2],
    525               privateDicts[i].fontMatrix[3],
    526               privateDicts[i].fontMatrix[4],
    527               privateDicts[i].fontMatrix[5]);
    528       (*outputFunc)(outputStream, buf, strlen(buf));
     577      buf = GooString::format("/FontMatrix [{0:.8g} {1:.8g} {2:.8g} {3:.8g} {4:.8g} {5:.8g}] def\n",
     578                            privateDicts[i].fontMatrix[0],
     579                            privateDicts[i].fontMatrix[1],
     580                            privateDicts[i].fontMatrix[2],
     581                            privateDicts[i].fontMatrix[3],
     582                            privateDicts[i].fontMatrix[4],
     583                            privateDicts[i].fontMatrix[5]);
     584      (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
     585      delete buf;
    529586    } else {
    530587      (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
    531588    }
    532     sprintf(buf, "/PaintType %d def\n", topDict.paintType);
    533     (*outputFunc)(outputStream, buf, strlen(buf));
     589    buf = GooString::format("/PaintType {0:d} def\n", topDict.paintType);
     590    (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
     591    delete buf;
    534592    (*outputFunc)(outputStream, "/Private 32 dict begin\n", 23);
    535593    if (privateDicts[i].nBlueValues) {
    536594      (*outputFunc)(outputStream, "/BlueValues [", 13);
    537595      for (j = 0; j < privateDicts[i].nBlueValues; ++j) {
    538         sprintf(buf, "%s%d", j > 0 ? " " : "", privateDicts[i].blueValues[j]);
    539         (*outputFunc)(outputStream, buf, strlen(buf));
     596        buf = GooString::format("{0:s}{1:d}",
     597                              j > 0 ? " " : "", privateDicts[i].blueValues[j]);
     598        (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
     599        delete buf;
    540600      }
    541601      (*outputFunc)(outputStream, "] def\n", 6);
     
    544604      (*outputFunc)(outputStream, "/OtherBlues [", 13);
    545605      for (j = 0; j < privateDicts[i].nOtherBlues; ++j) {
    546         sprintf(buf, "%s%d", j > 0 ? " " : "", privateDicts[i].otherBlues[j]);
    547         (*outputFunc)(outputStream, buf, strlen(buf));
     606        buf = GooString::format("{0:s}{1:d}",
     607                              j > 0 ? " " : "", privateDicts[i].otherBlues[j]);
     608        (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
     609        delete buf;
    548610      }
    549611      (*outputFunc)(outputStream, "] def\n", 6);
     
    552614      (*outputFunc)(outputStream, "/FamilyBlues [", 14);
    553615      for (j = 0; j < privateDicts[i].nFamilyBlues; ++j) {
    554         sprintf(buf, "%s%d", j > 0 ? " " : "", privateDicts[i].familyBlues[j]);
    555         (*outputFunc)(outputStream, buf, strlen(buf));
     616        buf = GooString::format("{0:s}{1:d}",
     617                              j > 0 ? " " : "",
     618                              privateDicts[i].familyBlues[j]);
     619        (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
     620        delete buf;
    556621      }
    557622      (*outputFunc)(outputStream, "] def\n", 6);
     
    560625      (*outputFunc)(outputStream, "/FamilyOtherBlues [", 19);
    561626      for (j = 0; j < privateDicts[i].nFamilyOtherBlues; ++j) {
    562         sprintf(buf, "%s%d", j > 0 ? " " : "",
    563                 privateDicts[i].familyOtherBlues[j]);
    564         (*outputFunc)(outputStream, buf, strlen(buf));
     627        buf = GooString::format("{0:s}{1:d}", j > 0 ? " " : "",
     628                              privateDicts[i].familyOtherBlues[j]);
     629        (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
     630        delete buf;
    565631      }
    566632      (*outputFunc)(outputStream, "] def\n", 6);
    567633    }
    568634    if (privateDicts[i].blueScale != 0.039625) {
    569       sprintf(buf, "/BlueScale %g def\n", privateDicts[i].blueScale);
    570       (*outputFunc)(outputStream, buf, strlen(buf));
     635      buf = GooString::format("/BlueScale {0:.4g} def\n",
     636                            privateDicts[i].blueScale);
     637      (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
     638      delete buf;
    571639    }
    572640    if (privateDicts[i].blueShift != 7) {
    573       sprintf(buf, "/BlueShift %d def\n", privateDicts[i].blueShift);
    574       (*outputFunc)(outputStream, buf, strlen(buf));
     641      buf = GooString::format("/BlueShift {0:d} def\n",
     642                            privateDicts[i].blueShift);
     643      (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
     644      delete buf;
    575645    }
    576646    if (privateDicts[i].blueFuzz != 1) {
    577       sprintf(buf, "/BlueFuzz %d def\n", privateDicts[i].blueFuzz);
    578       (*outputFunc)(outputStream, buf, strlen(buf));
     647      buf = GooString::format("/BlueFuzz {0:d} def\n", privateDicts[i].blueFuzz);
     648      (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
     649      delete buf;
    579650    }
    580651    if (privateDicts[i].hasStdHW) {
    581       sprintf(buf, "/StdHW [%g] def\n", privateDicts[i].stdHW);
    582       (*outputFunc)(outputStream, buf, strlen(buf));
     652      buf = GooString::format("/StdHW [{0:.4g}] def\n", privateDicts[i].stdHW);
     653      (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
     654      delete buf;
    583655    }
    584656    if (privateDicts[i].hasStdVW) {
    585       sprintf(buf, "/StdVW [%g] def\n", privateDicts[i].stdVW);
    586       (*outputFunc)(outputStream, buf, strlen(buf));
     657      buf = GooString::format("/StdVW [{0:.4g}] def\n", privateDicts[i].stdVW);
     658      (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
     659      delete buf;
    587660    }
    588661    if (privateDicts[i].nStemSnapH) {
    589662      (*outputFunc)(outputStream, "/StemSnapH [", 12);
    590663      for (j = 0; j < privateDicts[i].nStemSnapH; ++j) {
    591         sprintf(buf, "%s%g", j > 0 ? " " : "", privateDicts[i].stemSnapH[j]);
    592         (*outputFunc)(outputStream, buf, strlen(buf));
     664        buf = GooString::format("{0:s}{1:.4g}",
     665                              j > 0 ? " " : "", privateDicts[i].stemSnapH[j]);
     666        (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
     667        delete buf;
    593668      }
    594669      (*outputFunc)(outputStream, "] def\n", 6);
     
    597672      (*outputFunc)(outputStream, "/StemSnapV [", 12);
    598673      for (j = 0; j < privateDicts[i].nStemSnapV; ++j) {
    599         sprintf(buf, "%s%g", j > 0 ? " " : "", privateDicts[i].stemSnapV[j]);
    600         (*outputFunc)(outputStream, buf, strlen(buf));
     674        buf = GooString::format("{0:s}{1:.4g}",
     675                              j > 0 ? " " : "", privateDicts[i].stemSnapV[j]);
     676        (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
     677        delete buf;
    601678      }
    602679      (*outputFunc)(outputStream, "] def\n", 6);
    603680    }
    604681    if (privateDicts[i].hasForceBold) {
    605       sprintf(buf, "/ForceBold %s def\n",
    606               privateDicts[i].forceBold ? "true" : "false");
    607       (*outputFunc)(outputStream, buf, strlen(buf));
     682      buf = GooString::format("/ForceBold {0:s} def\n",
     683                            privateDicts[i].forceBold ? "true" : "false");
     684      (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
     685      delete buf;
    608686    }
    609687    if (privateDicts[i].forceBoldThreshold != 0) {
    610       sprintf(buf, "/ForceBoldThreshold %g def\n",
    611               privateDicts[i].forceBoldThreshold);
    612       (*outputFunc)(outputStream, buf, strlen(buf));
     688      buf = GooString::format("/ForceBoldThreshold {0:.4g} def\n",
     689                            privateDicts[i].forceBoldThreshold);
     690      (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
     691      delete buf;
    613692    }
    614693    if (privateDicts[i].languageGroup != 0) {
    615       sprintf(buf, "/LanguageGroup %d def\n", privateDicts[i].languageGroup);
    616       (*outputFunc)(outputStream, buf, strlen(buf));
     694      buf = GooString::format("/LanguageGroup {0:d} def\n",
     695                            privateDicts[i].languageGroup);
     696      (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
     697      delete buf;
    617698    }
    618699    if (privateDicts[i].expansionFactor != 0.06) {
    619       sprintf(buf, "/ExpansionFactor %g def\n",
    620               privateDicts[i].expansionFactor);
    621       (*outputFunc)(outputStream, buf, strlen(buf));
     700      buf = GooString::format("/ExpansionFactor {0:.4g} def\n",
     701                            privateDicts[i].expansionFactor);
     702      (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
     703      delete buf;
    622704    }
    623705    (*outputFunc)(outputStream, "currentdict end def\n", 20);
     
    628710  // start the binary section
    629711  offset = (nCIDs + 1) * (1 + gdBytes);
    630   sprintf(buf, "(Hex) %d StartData\n",
    631           offset + charStrings->getLength());
    632   (*outputFunc)(outputStream, buf, strlen(buf));
     712  buf = GooString::format("(Hex) {0:d} StartData\n",
     713                        offset + charStrings->getLength());
     714  (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
     715  delete buf;
    633716
    634717  // write the charstring offset (CIDMap) table
     
    636719    for (j = 0; j < 6 && i+j <= nCIDs; ++j) {
    637720      if (i+j < nCIDs && cidMap[i+j] >= 0) {
    638         buf[0] = (char)fdSelect[cidMap[i+j]];
     721        buf2[0] = (char)fdSelect[cidMap[i+j]];
    639722      } else {
    640         buf[0] = (char)0;
     723        buf2[0] = (char)0;
    641724      }
    642725      n = offset + charStringOffsets[i+j];
    643726      for (k = gdBytes; k >= 1; --k) {
    644         buf[k] = (char)(n & 0xff);
     727        buf2[k] = (char)(n & 0xff);
    645728        n >>= 8;
    646729      }
    647730      for (k = 0; k <= gdBytes; ++k) {
    648         sprintf(buf2, "%02x", buf[k] & 0xff);
    649         (*outputFunc)(outputStream, buf2, 2);
     731        buf = GooString::format("{0:02x}", buf2[k] & 0xff);
     732        (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
     733        delete buf;
    650734      }
    651735    }
     
    657741  for (i = 0; i < n; i += 32) {
    658742    for (j = 0; j < 32 && i+j < n; ++j) {
    659       sprintf(buf, "%02x", charStrings->getChar(i+j) & 0xff);
    660       (*outputFunc)(outputStream, buf, strlen(buf));
     743      buf = GooString::format("{0:02x}", charStrings->getChar(i+j) & 0xff);
     744      (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
     745      delete buf;
    661746    }
    662747    if (i + 32 >= n) {
     
    678763  Type1CIndexVal val;
    679764  int nCIDs;
    680   char buf[512];
     765  GooString *buf;
    681766  Type1CEexecBuf eb;
    682767  GBool ok;
     
    703788    //~ this assumes that all CIDs in this block have the same FD --
    704789    //~ to handle multiple FDs correctly, need to somehow divide the
    705     //~ font up by FD
     790    //~ font up by FD; as a kludge we ignore CID 0, which is .notdef
    706791    fd = 0;
    707     for (j = 0; j < 256 && i+j < nCIDs; ++j) {
     792    for (j = i==0 ? 1 : 0; j < 256 && i+j < nCIDs; ++j) {
    708793      if (cidMap[i+j] >= 0) {
    709794        fd = fdSelect[cidMap[i+j]];
     
    716801    (*outputFunc)(outputStream, "/FontName /", 11);
    717802    (*outputFunc)(outputStream, psName, strlen(psName));
    718     sprintf(buf, "_%02x def\n", i >> 8);
    719     (*outputFunc)(outputStream, buf, strlen(buf));
     803    buf = GooString::format("_{0:02x} def\n", i >> 8);
     804    (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
     805    delete buf;
    720806    (*outputFunc)(outputStream, "/FontType 1 def\n", 16);
    721807    if (privateDicts[fd].hasFontMatrix) {
    722       sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] def\n",
    723               privateDicts[fd].fontMatrix[0],
    724               privateDicts[fd].fontMatrix[1],
    725               privateDicts[fd].fontMatrix[2],
    726               privateDicts[fd].fontMatrix[3],
    727               privateDicts[fd].fontMatrix[4],
    728               privateDicts[fd].fontMatrix[5]);
    729       (*outputFunc)(outputStream, buf, strlen(buf));
     808      buf = GooString::format("/FontMatrix [{0:.8g} {1:.8g} {2:.8g} {3:.8g} {4:.8g} {5:.8g}] def\n",
     809                            privateDicts[fd].fontMatrix[0],
     810                            privateDicts[fd].fontMatrix[1],
     811                            privateDicts[fd].fontMatrix[2],
     812                            privateDicts[fd].fontMatrix[3],
     813                            privateDicts[fd].fontMatrix[4],
     814                            privateDicts[fd].fontMatrix[5]);
     815      (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
     816      delete buf;
    730817    } else if (topDict.hasFontMatrix) {
    731818      (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
     
    734821                    "/FontMatrix [0.001 0 0 0.001 0 0] def\n", 38);
    735822    }
    736     sprintf(buf, "/FontBBox [%g %g %g %g] def\n",
    737             topDict.fontBBox[0], topDict.fontBBox[1],
    738             topDict.fontBBox[2], topDict.fontBBox[3]);
    739     (*outputFunc)(outputStream, buf, strlen(buf));
    740     sprintf(buf, "/PaintType %d def\n", topDict.paintType);
    741     (*outputFunc)(outputStream, buf, strlen(buf));
     823    buf = GooString::format("/FontBBox [{0:.4g} {1:.4g} {2:.4g} {3:.4g}] def\n",
     824                          topDict.fontBBox[0], topDict.fontBBox[1],
     825                          topDict.fontBBox[2], topDict.fontBBox[3]);
     826    (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
     827    delete buf;
     828    buf = GooString::format("/PaintType {0:d} def\n", topDict.paintType);
     829    (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
     830    delete buf;
    742831    if (topDict.paintType != 0) {
    743       sprintf(buf, "/StrokeWidth %g def\n", topDict.strokeWidth);
    744       (*outputFunc)(outputStream, buf, strlen(buf));
     832      buf = GooString::format("/StrokeWidth {0:.4g} def\n", topDict.strokeWidth);
     833      (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
     834      delete buf;
    745835    }
    746836    (*outputFunc)(outputStream, "/Encoding 256 array\n", 20);
    747837    for (j = 0; j < 256 && i+j < nCIDs; ++j) {
    748       sprintf(buf, "dup %d /c%02x put\n", j, j);
    749       (*outputFunc)(outputStream, buf, strlen(buf));
     838      buf = GooString::format("dup {0:d} /c{1:02x} put\n", j, j);
     839      (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
     840      delete buf;
    750841    }
    751842    if (j < 256) {
    752       sprintf(buf, "%d 1 255 { 1 index exch /.notdef put } for\n", j);
    753       (*outputFunc)(outputStream, buf, strlen(buf));
     843      buf = GooString::format("{0:d} 1 255 {{ 1 index exch /.notdef put }} for\n",
     844                            j);
     845      (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
     846      delete buf;
    754847    }
    755848    (*outputFunc)(outputStream, "readonly def\n", 13);
     
    776869      eexecWrite(&eb, "/BlueValues [");
    777870      for (k = 0; k < privateDicts[fd].nBlueValues; ++k) {
    778         sprintf(buf, "%s%d", k > 0 ? " " : "", privateDicts[fd].blueValues[k]);
    779         eexecWrite(&eb, buf);
     871        buf = GooString::format("{0:s}{1:d}",
     872                              k > 0 ? " " : "",
     873                              privateDicts[fd].blueValues[k]);
     874        eexecWrite(&eb, buf->getCString());
     875        delete buf;
    780876      }
    781877      eexecWrite(&eb, "] def\n");
     
    784880      eexecWrite(&eb, "/OtherBlues [");
    785881      for (k = 0; k < privateDicts[fd].nOtherBlues; ++k) {
    786         sprintf(buf, "%s%d", k > 0 ? " " : "", privateDicts[fd].otherBlues[k]);
    787         eexecWrite(&eb, buf);
     882        buf = GooString::format("{0:s}{1:d}",
     883                              k > 0 ? " " : "",
     884                              privateDicts[fd].otherBlues[k]);
     885        eexecWrite(&eb, buf->getCString());
     886        delete buf;
    788887      }
    789888      eexecWrite(&eb, "] def\n");
     
    792891      eexecWrite(&eb, "/FamilyBlues [");
    793892      for (k = 0; k < privateDicts[fd].nFamilyBlues; ++k) {
    794         sprintf(buf, "%s%d", k > 0 ? " " : "",
    795                 privateDicts[fd].familyBlues[k]);
    796         eexecWrite(&eb, buf);
     893        buf = GooString::format("{0:s}{1:d}", k > 0 ? " " : "",
     894                              privateDicts[fd].familyBlues[k]);
     895        eexecWrite(&eb, buf->getCString());
     896        delete buf;
    797897      }
    798898      eexecWrite(&eb, "] def\n");
     
    801901      eexecWrite(&eb, "/FamilyOtherBlues [");
    802902      for (k = 0; k < privateDicts[fd].nFamilyOtherBlues; ++k) {
    803         sprintf(buf, "%s%d", k > 0 ? " " : "",
    804                 privateDicts[fd].familyOtherBlues[k]);
    805         eexecWrite(&eb, buf);
     903        buf = GooString::format("{0:s}{1:d}", k > 0 ? " " : "",
     904                              privateDicts[fd].familyOtherBlues[k]);
     905        eexecWrite(&eb, buf->getCString());
     906        delete buf;
    806907      }
    807908      eexecWrite(&eb, "] def\n");
    808909    }
    809910    if (privateDicts[fd].blueScale != 0.039625) {
    810       sprintf(buf, "/BlueScale %g def\n", privateDicts[fd].blueScale);
    811       eexecWrite(&eb, buf);
     911      buf = GooString::format("/BlueScale {0:.4g} def\n",
     912                            privateDicts[fd].blueScale);
     913      eexecWrite(&eb, buf->getCString());
     914      delete buf;
    812915    }
    813916    if (privateDicts[fd].blueShift != 7) {
    814       sprintf(buf, "/BlueShift %d def\n", privateDicts[fd].blueShift);
    815       eexecWrite(&eb, buf);
     917      buf = GooString::format("/BlueShift {0:d} def\n",
     918                            privateDicts[fd].blueShift);
     919      eexecWrite(&eb, buf->getCString());
     920      delete buf;
    816921    }
    817922    if (privateDicts[fd].blueFuzz != 1) {
    818       sprintf(buf, "/BlueFuzz %d def\n", privateDicts[fd].blueFuzz);
    819       eexecWrite(&eb, buf);
     923      buf = GooString::format("/BlueFuzz {0:d} def\n",
     924                            privateDicts[fd].blueFuzz);
     925      eexecWrite(&eb, buf->getCString());
     926      delete buf;
    820927    }
    821928    if (privateDicts[fd].hasStdHW) {
    822       sprintf(buf, "/StdHW [%g] def\n", privateDicts[fd].stdHW);
    823       eexecWrite(&eb, buf);
     929      buf = GooString::format("/StdHW [{0:.4g}] def\n", privateDicts[fd].stdHW);
     930      eexecWrite(&eb, buf->getCString());
     931      delete buf;
    824932    }
    825933    if (privateDicts[fd].hasStdVW) {
    826       sprintf(buf, "/StdVW [%g] def\n", privateDicts[fd].stdVW);
    827       eexecWrite(&eb, buf);
     934      buf = GooString::format("/StdVW [{0:.4g}] def\n", privateDicts[fd].stdVW);
     935      eexecWrite(&eb, buf->getCString());
     936      delete buf;
    828937    }
    829938    if (privateDicts[fd].nStemSnapH) {
    830939      eexecWrite(&eb, "/StemSnapH [");
    831940      for (k = 0; k < privateDicts[fd].nStemSnapH; ++k) {
    832         sprintf(buf, "%s%g", k > 0 ? " " : "", privateDicts[fd].stemSnapH[k]);
    833         eexecWrite(&eb, buf);
     941        buf = GooString::format("{0:s}{1:.4g}",
     942                              k > 0 ? " " : "", privateDicts[fd].stemSnapH[k]);
     943        eexecWrite(&eb, buf->getCString());
     944        delete buf;
    834945      }
    835946      eexecWrite(&eb, "] def\n");
     
    838949      eexecWrite(&eb, "/StemSnapV [");
    839950      for (k = 0; k < privateDicts[fd].nStemSnapV; ++k) {
    840         sprintf(buf, "%s%g", k > 0 ? " " : "", privateDicts[fd].stemSnapV[k]);
    841         eexecWrite(&eb, buf);
     951        buf = GooString::format("{0:s}{1:.4g}",
     952                              k > 0 ? " " : "", privateDicts[fd].stemSnapV[k]);
     953        eexecWrite(&eb, buf->getCString());
     954        delete buf;
    842955      }
    843956      eexecWrite(&eb, "] def\n");
    844957    }
    845958    if (privateDicts[fd].hasForceBold) {
    846       sprintf(buf, "/ForceBold %s def\n",
    847               privateDicts[fd].forceBold ? "true" : "false");
    848       eexecWrite(&eb, buf);
     959      buf = GooString::format("/ForceBold {0:s} def\n",
     960                            privateDicts[fd].forceBold ? "true" : "false");
     961      eexecWrite(&eb, buf->getCString());
     962      delete buf;
    849963    }
    850964    if (privateDicts[fd].forceBoldThreshold != 0) {
    851       sprintf(buf, "/ForceBoldThreshold %g def\n",
    852               privateDicts[fd].forceBoldThreshold);
    853       eexecWrite(&eb, buf);
     965      buf = GooString::format("/ForceBoldThreshold {0:.4g} def\n",
     966                            privateDicts[fd].forceBoldThreshold);
     967      eexecWrite(&eb, buf->getCString());
     968      delete buf;
    854969    }
    855970    if (privateDicts[fd].languageGroup != 0) {
    856       sprintf(buf, "/LanguageGroup %d def\n", privateDicts[fd].languageGroup);
    857       eexecWrite(&eb, buf);
     971      buf = GooString::format("/LanguageGroup {0:d} def\n",
     972                            privateDicts[fd].languageGroup);
     973      eexecWrite(&eb, buf->getCString());
     974      delete buf;
    858975    }
    859976    if (privateDicts[fd].expansionFactor != 0.06) {
    860       sprintf(buf, "/ExpansionFactor %g def\n",
    861               privateDicts[fd].expansionFactor);
    862       eexecWrite(&eb, buf);
     977      buf = GooString::format("/ExpansionFactor {0:.4g} def\n",
     978                            privateDicts[fd].expansionFactor);
     979      eexecWrite(&eb, buf->getCString());
     980      delete buf;
    863981    }
    864982
     
    871989
    872990    // start the CharStrings
    873     sprintf(buf, "2 index /CharStrings 256 dict dup begin\n");
    874     eexecWrite(&eb, buf);
     991    eexecWrite(&eb, "2 index /CharStrings 256 dict dup begin\n");
    875992
    876993    // write the .notdef CharString
     
    8881005        getIndexVal(&charStringsIdx, cidMap[i+j], &val, &ok);
    8891006        if (ok) {
    890           sprintf(buf, "c%02x", j);
    891           eexecCvtGlyph(&eb, buf, val.pos, val.len,
     1007          buf = GooString::format("c{0:02x}", j);
     1008          eexecCvtGlyph(&eb, buf->getCString(), val.pos, val.len,
    8921009                        &subrIdx, &privateDicts[fd]);
     1010          delete buf;
    8931011        }
    8941012      }
     
    9181036  (*outputFunc)(outputStream, "/FontType 0 def\n", 16);
    9191037  if (topDict.hasFontMatrix) {
    920     sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] def\n",
    921             topDict.fontMatrix[0], topDict.fontMatrix[1],
    922             topDict.fontMatrix[2], topDict.fontMatrix[3],
    923             topDict.fontMatrix[4], topDict.fontMatrix[5]);
    924     (*outputFunc)(outputStream, buf, strlen(buf));
     1038    buf = GooString::format("/FontMatrix [{0:.8g} {1:.8g} {2:.8g} {3:.8g} {4:.8g} {5:.8g}] def\n",
     1039                          topDict.fontMatrix[0], topDict.fontMatrix[1],
     1040                          topDict.fontMatrix[2], topDict.fontMatrix[3],
     1041                          topDict.fontMatrix[4], topDict.fontMatrix[5]);
     1042    (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
     1043    delete buf;
    9251044  } else {
    9261045    (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
     
    9291048  (*outputFunc)(outputStream, "/Encoding [\n", 12);
    9301049  for (i = 0; i < nCIDs; i += 256) {
    931     sprintf(buf, "%d\n", i >> 8);
    932     (*outputFunc)(outputStream, buf, strlen(buf));
     1050    buf = GooString::format("{0:d}\n", i >> 8);
     1051    (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
     1052    delete buf;
    9331053  }
    9341054  (*outputFunc)(outputStream, "] def\n", 6);
     
    9371057    (*outputFunc)(outputStream, "/", 1);
    9381058    (*outputFunc)(outputStream, psName, strlen(psName));
    939     sprintf(buf, "_%02x findfont\n", i >> 8);
    940     (*outputFunc)(outputStream, buf, strlen(buf));
     1059    buf = GooString::format("_{0:02x} findfont\n", i >> 8);
     1060    (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
     1061    delete buf;
    9411062  }
    9421063  (*outputFunc)(outputStream, "] def\n", 6);
     
    9501071                               Type1CIndex *subrIdx,
    9511072                               Type1CPrivateDict *pDict) {
    952   char buf[512];
     1073  GooString *buf;
    9531074  GooString *charBuf;
    9541075
     
    9571078  cvtGlyph(offset, nBytes, charBuf, subrIdx, pDict, gTrue);
    9581079
    959   sprintf(buf, "/%s %d RD ", glyphName, charBuf->getLength());
    960   eexecWrite(eb, buf);
     1080  buf = GooString::format("/{0:s} {1:d} RD ", glyphName, charBuf->getLength());
     1081  eexecWrite(eb, buf->getCString());
     1082  delete buf;
    9611083  eexecWriteCharstring(eb, (Guchar *)charBuf->getCString(),
    9621084                       charBuf->getLength());
     
    19222044void FoFiType1C::readFD(int offset, int length, Type1CPrivateDict *pDict) {
    19232045  int pos, pSize, pOffset;
    1924   double fontMatrix[6];
     2046  double fontMatrix[6] = {0};
    19252047  GBool hasFontMatrix;
    19262048
     
    19362058    if (!ops[nOps - 1].isNum) {
    19372059      if (ops[nOps - 1].op == 0x0012) {
    1938         if (nOps < 3) {
    1939           parsedOk = gFalse;
    1940           return;
    1941         }
    1942         pSize = (int)ops[0].num;
    1943         pOffset = (int)ops[1].num;
    1944         break;
     2060        if (nOps < 3) {
     2061          parsedOk = gFalse;
     2062          return;
     2063        }
     2064        pSize = (int)ops[0].num;
     2065        pOffset = (int)ops[1].num;
     2066        break;
    19452067      } else if (ops[nOps - 1].op == 0x0c07) {
    1946         fontMatrix[0] = ops[0].num;
    1947         fontMatrix[1] = ops[1].num;
    1948         fontMatrix[2] = ops[2].num;
    1949         fontMatrix[3] = ops[3].num;
    1950         fontMatrix[4] = ops[4].num;
    1951         fontMatrix[5] = ops[5].num;
    1952         hasFontMatrix = gTrue;
     2068        fontMatrix[0] = ops[0].num;
     2069        fontMatrix[1] = ops[1].num;
     2070        fontMatrix[2] = ops[2].num;
     2071        fontMatrix[3] = ops[3].num;
     2072        fontMatrix[4] = ops[4].num;
     2073        fontMatrix[5] = ops[5].num;
     2074        hasFontMatrix = gTrue;
    19532075      }
    19542076      nOps = 0;
  • trunk/poppler/mypoppler/fofi/FoFiType1C.h

    r2 r250  
    139139  static FoFiType1C *load(char *fileName);
    140140
    141   FoFiType1C(char *fileA, int lenA, GBool freeFileDataA);
    142141  virtual ~FoFiType1C();
    143142
     
    157156  // not NULL, it will be used in place of the encoding in the Type 1C
    158157  // font.  If <ascii> is true the eexec section will be hex-encoded,
    159   // otherwise it will be left as binary data.
    160   void convertToType1(char **newEncoding, GBool ascii,
     158  // otherwise it will be left as binary data.  If <psName> is non-NULL,
     159  // it will be used as the PostScript font name.
     160  void convertToType1(char *psName, char **newEncoding, GBool ascii,
    161161                      FoFiOutputFunc outputFunc, void *outputStream);
    162162
     
    175175private:
    176176
     177  FoFiType1C(char *fileA, int lenA, GBool freeFileDataA);
    177178  void eexecCvtGlyph(Type1CEexecBuf *eb, char *glyphName,
    178179                     int offset, int nBytes,
  • trunk/poppler/mypoppler/goo/FixedPoint.cc

    r2 r250  
    1919#include "FixedPoint.h"
    2020
     21#define ln2 ((FixedPoint)0.69314718)
     22
     23#define ln2 ((FixedPoint)0.69314718)
     24
    2125FixedPoint FixedPoint::sqrt(FixedPoint x) {
    2226  FixedPoint y0, y1, z;
     
    2529    y1.val = 0;
    2630  } else {
    27     y1.val = x.val >> 1;
     31    y1.val = x.val == 1 ? 2 : x.val >> 1;
    2832    do {
    2933      y0.val = y1.val;
     
    3539}
    3640
    37 //~ this is not very accurate
    3841FixedPoint FixedPoint::pow(FixedPoint x, FixedPoint y) {
    3942  FixedPoint t, t2, lnx0, lnx, z0, z;
    40   int d, i;
     43  int d, n, i;
    4144
    4245  if (y.val <= 0) {
     
    5760    t = y * lnx;
    5861    // exp(y * ln(x))
     62    n = floor(t / ln2);
     63    t -= ln2 * n;
    5964    t2 = t;
    6065    d = 1;
     
    6873      d *= i;
    6974    } while (::abs(z.val - z0.val) > 2 && d < (1 << fixptShift));
     75    if (n >= 0) {
     76      z.val <<= n;
     77    } else if (n < 0) {
     78      z.val >>= -n;
     79    }
    7080  }
    7181  return z;
     
    93103}
    94104
     105GBool FixedPoint::divCheck(FixedPoint x, FixedPoint y, FixedPoint *result) {
     106#if 1 //~tmp
     107  FixPtInt64 z;
     108
     109  z = ((FixPtInt64)x.val << fixptShift) / y.val;
     110  if ((z == 0 && x != 0) ||
     111      z >= ((FixPtInt64)1 << 31) || z < -((FixPtInt64)1 << 31)) {
     112    return gFalse;
     113  }
     114  result->val = z;
     115  return gTrue;
     116#else
     117#endif
     118}
     119
    95120#endif // USE_FIXEDPOINT
  • trunk/poppler/mypoppler/goo/FixedPoint.h

    r2 r250  
    1212#define FIXEDPOINT_H
    1313
    14 #include <config.h>
     14#include <poppler/poppler-config.h>
    1515
    1616#if USE_FIXEDPOINT
     
    2222#include <stdio.h>
    2323#include <stdlib.h>
     24#include "gtypes.h"
    2425
    2526#define fixptShift 16
     
    136137  static FixedPoint pow(FixedPoint x, FixedPoint y);
    137138
     139  // Compute *result = x/y; return false if there is an underflow or
     140  // overflow.
     141  static GBool divCheck(FixedPoint x, FixedPoint y, FixedPoint *result);
     142
    138143private:
    139144
  • trunk/poppler/mypoppler/goo/GooMutex.h

    r2 r250  
    4646#define gUnlockMutex(m) DosReleaseMutexSem(*m)
    4747
    48 
    49 #else
    50 // assume pthreads
     48#else // assume pthreads
    5149
    5250#include <pthread.h>
  • trunk/poppler/mypoppler/goo/GooString.cc

    r2 r250  
    1919#include <string.h>
    2020#include <ctype.h>
    21 #include "gtypes.h"
     21#include <assert.h>
     22#include <math.h>
     23#include "gmem.h"
    2224#include "GooString.h"
    2325
    24 static inline int size(int len) {
     26//------------------------------------------------------------------------
     27
     28union GooStringFormatArg {
     29  int i;
     30  Guint ui;
     31  long l;
     32  Gulong ul;
     33  double f;
     34  char c;
     35  char *s;
     36  GooString *gs;
     37};
     38
     39enum GooStringFormatType {
     40  fmtIntDecimal,
     41  fmtIntHex,
     42  fmtIntOctal,
     43  fmtIntBinary,
     44  fmtUIntDecimal,
     45  fmtUIntHex,
     46  fmtUIntOctal,
     47  fmtUIntBinary,
     48  fmtLongDecimal,
     49  fmtLongHex,
     50  fmtLongOctal,
     51  fmtLongBinary,
     52  fmtULongDecimal,
     53  fmtULongHex,
     54  fmtULongOctal,
     55  fmtULongBinary,
     56  fmtDouble,
     57  fmtDoubleTrim,
     58  fmtChar,
     59  fmtString,
     60  fmtGooString,
     61  fmtSpace
     62};
     63
     64static char *formatStrings[] = {
     65  "d", "x", "o", "b", "ud", "ux", "uo", "ub",
     66  "ld", "lx", "lo", "lb", "uld", "ulx", "ulo", "ulb",
     67  "f", "g",
     68  "c",
     69  "s",
     70  "t",
     71  "w",
     72  NULL
     73};
     74
     75//------------------------------------------------------------------------
     76
     77int inline GooString::roundedSize(int len) {
    2578  int delta;
    26 
     79  if (len <= STR_STATIC_SIZE-1)
     80      return STR_STATIC_SIZE;
    2781  delta = len < 256 ? 7 : 255;
    2882  return ((len + 1) + delta) & ~delta;
    2983}
    3084
    31 inline void GooString::resize(int length1) {
    32   char *s1;
    33 
    34   if (!s) {
    35     s = new char[size(length1)];
    36   } else if (size(length1) != size(length)) {
    37     s1 = new char[size(length1)];
    38     if (length1 < length) {
    39       memcpy(s1, s, length1);
    40       s1[length1] = '\0';
     85// Make sure that the buffer is big enough to contain <newLength> characters
     86// plus terminating 0.
     87// We assume that if this is being called from the constructor, <s> was set
     88// to NULL and <length> was set to 0 to indicate unused string before calling us.
     89void inline GooString::resize(int newLength) {
     90  char *s1 = s;
     91
     92  if (!s || (roundedSize(length) != roundedSize(newLength))) {
     93    // requires re-allocating data for string
     94    if (newLength < STR_STATIC_SIZE) {
     95      s1 = sStatic;
    4196    } else {
    42       memcpy(s1, s, length + 1);
    43     }
    44     delete[] s;
    45     s = s1;
    46   }
     97      // allocate a rounded amount
     98      if (s == sStatic)
     99        s1 = (char*)gmalloc(roundedSize(newLength));
     100      else
     101        s1 = (char*)grealloc(s, roundedSize(newLength));
     102    }
     103    if (s == sStatic || s1 == sStatic) {
     104      // copy the minimum, we only need to if are moving to or
     105      // from sStatic.
     106      // assert(s != s1) the roundedSize condition ensures this
     107      if (newLength < length) {
     108        memcpy(s1, s, newLength);
     109      } else {
     110        memcpy(s1, s, length);
     111      }
     112    }
     113
     114  }
     115
     116  s = s1;
     117  length = newLength;
     118  s[length] = '\0';
     119}
     120
     121GooString* GooString::Set(const char *s1, int s1Len, const char *s2, int s2Len)
     122{
     123    int newLen = 0;
     124    char *p;
     125
     126    if (s1) {
     127        if (CALC_STRING_LEN == s1Len) {
     128            s1Len = strlen(s1);
     129        } else
     130            assert(s1Len >= 0);
     131        newLen += s1Len;
     132    }
     133
     134    if (s2) {
     135        if (CALC_STRING_LEN == s2Len) {
     136            s2Len = strlen(s2);
     137        } else
     138            assert(s2Len >= 0);
     139        newLen += s2Len;
     140    }
     141
     142    resize(newLen);
     143    p = s;
     144    if (s1) {
     145        memcpy(p, s1, s1Len);
     146        p += s1Len;
     147    }
     148    if (s2) {
     149        memcpy(p, s2, s2Len);
     150        p += s2Len;
     151    }
     152    return this;
    47153}
    48154
    49155GooString::GooString() {
    50156  s = NULL;
    51   resize(length = 0);
    52   s[0] = '\0';
     157  length = 0;
     158  Set(NULL);
    53159}
    54160
    55161GooString::GooString(const char *sA) {
    56   int n = strlen(sA);
    57 
    58162  s = NULL;
    59   resize(length = n);
    60   memcpy(s, sA, n + 1);
     163  length = 0;
     164  Set(sA, CALC_STRING_LEN);
    61165}
    62166
    63167GooString::GooString(const char *sA, int lengthA) {
    64168  s = NULL;
    65   resize(length = lengthA);
    66   memcpy(s, sA, length * sizeof(char));
    67   s[length] = '\0';
     169  length = 0;
     170  Set(sA, lengthA);
    68171}
    69172
    70173GooString::GooString(GooString *str, int idx, int lengthA) {
    71174  s = NULL;
    72   resize(length = lengthA);
    73   memcpy(s, str->getCString() + idx, length);
    74   s[length] = '\0';
     175  length = 0;
     176  assert(idx + lengthA <= str->length);
     177  Set(str->getCString() + idx, lengthA);
    75178}
    76179
    77180GooString::GooString(GooString *str) {
    78181  s = NULL;
    79   resize(length = str->getLength());
    80   memcpy(s, str->getCString(), length + 1);
     182  length = 0;
     183  Set(str->getCString(), str->length);
    81184}
    82185
    83186GooString::GooString(GooString *str1, GooString *str2) {
    84   int n1 = str1->getLength();
    85   int n2 = str2->getLength();
    86 
    87187  s = NULL;
    88   resize(length = n1 + n2);
    89   memcpy(s, str1->getCString(), n1);
    90   memcpy(s + n1, str2->getCString(), n2 + 1);
     188  length = 0;
     189  Set(str1->getCString(), str1->length, str2->getCString(), str2->length);
    91190}
    92191
    93192GooString *GooString::fromInt(int x) {
    94193  char buf[24]; // enough space for 64-bit ints plus a little extra
     194  char *p;
     195  int len;
     196  formatInt(x, buf, sizeof(buf), gFalse, 0, 10, &p, &len);
     197  return new GooString(p, len);
     198}
     199
     200GooString *GooString::format(char *fmt, ...) {
     201  va_list argList;
     202  GooString *s;
     203
     204  s = new GooString();
     205  va_start(argList, fmt);
     206  s->appendfv(fmt, argList);
     207  va_end(argList);
     208  return s;
     209}
     210
     211GooString *GooString::formatv(char *fmt, va_list argList) {
     212  GooString *s;
     213
     214  s = new GooString();
     215  s->appendfv(fmt, argList);
     216  return s;
     217}
     218
     219GooString::~GooString() {
     220  if (s != sStatic)
     221    free(s);
     222}
     223
     224GooString *GooString::clear() {
     225  resize(0);
     226  return this;
     227}
     228
     229GooString *GooString::append(char c) {
     230  return append((const char*)&c, 1);
     231}
     232
     233GooString *GooString::append(GooString *str) {
     234  return append(str->getCString(), str->getLength());
     235}
     236
     237GooString *GooString::append(const char *str, int lengthA) {
     238  int prevLen = length;
     239  if (CALC_STRING_LEN == lengthA)
     240    lengthA = strlen(str);
     241  resize(length + lengthA);
     242  memcpy(s + prevLen, str, lengthA);
     243  return this;
     244}
     245
     246GooString *GooString::appendf(char *fmt, ...) {
     247  va_list argList;
     248
     249  va_start(argList, fmt);
     250  appendfv(fmt, argList);
     251  va_end(argList);
     252  return this;
     253}
     254
     255GooString *GooString::appendfv(char *fmt, va_list argList) {
     256  GooStringFormatArg *args;
     257  int argsLen, argsSize;
     258  GooStringFormatArg arg;
     259  int idx, width, prec;
     260  GBool reverseAlign, zeroFill;
     261  GooStringFormatType ft;
     262  char buf[65];
     263  int len, i;
     264  char *p0, *p1, *str;
     265
     266  argsLen = 0;
     267  argsSize = 8;
     268  args = (GooStringFormatArg *)gmallocn(argsSize, sizeof(GooStringFormatArg));
     269
     270  p0 = fmt;
     271  while (*p0) {
     272    if (*p0 == '{') {
     273      ++p0;
     274      if (*p0 == '{') {
     275        ++p0;
     276        append('{');
     277      } else {
     278
     279        // parse the format string
     280        if (!(*p0 >= '0' && *p0 <= '9')) {
     281          break;
     282        }
     283        idx = *p0 - '0';
     284        for (++p0; *p0 >= '0' && *p0 <= '9'; ++p0) {
     285          idx = 10 * idx + (*p0 - '0');
     286        }
     287        if (*p0 != ':') {
     288          break;
     289        }
     290        ++p0;
     291        if (*p0 == '-') {
     292          reverseAlign = gTrue;
     293          ++p0;
     294        } else {
     295          reverseAlign = gFalse;
     296        }
     297        width = 0;
     298        zeroFill = *p0 == '0';
     299        for (; *p0 >= '0' && *p0 <= '9'; ++p0) {
     300          width = 10 * width + (*p0 - '0');
     301        }
     302        if (*p0 == '.') {
     303          ++p0;
     304          prec = 0;
     305          for (; *p0 >= '0' && *p0 <= '9'; ++p0) {
     306            prec = 10 * prec + (*p0 - '0');
     307          }
     308        } else {
     309          prec = 0;
     310        }
     311        for (ft = (GooStringFormatType)0;
     312             formatStrings[ft];
     313             ft = (GooStringFormatType)(ft + 1)) {
     314          if (!strncmp(p0, formatStrings[ft], strlen(formatStrings[ft]))) {
     315            break;
     316          }
     317        }
     318        if (!formatStrings[ft]) {
     319          break;
     320        }
     321        p0 += strlen(formatStrings[ft]);
     322        if (*p0 != '}') {
     323          break;
     324        }
     325        ++p0;
     326
     327        // fetch the argument
     328        if (idx > argsLen) {
     329          break;
     330        }
     331        if (idx == argsLen) {
     332          if (argsLen == argsSize) {
     333            argsSize *= 2;
     334            args = (GooStringFormatArg *)greallocn(args, argsSize,
     335                                                 sizeof(GooStringFormatArg));
     336          }
     337          switch (ft) {
     338          case fmtIntDecimal:
     339          case fmtIntHex:
     340          case fmtIntOctal:
     341          case fmtIntBinary:
     342          case fmtSpace:
     343            args[argsLen].i = va_arg(argList, int);
     344            break;
     345          case fmtUIntDecimal:
     346          case fmtUIntHex:
     347          case fmtUIntOctal:
     348          case fmtUIntBinary:
     349            args[argsLen].ui = va_arg(argList, Guint);
     350            break;
     351          case fmtLongDecimal:
     352          case fmtLongHex:
     353          case fmtLongOctal:
     354          case fmtLongBinary:
     355            args[argsLen].l = va_arg(argList, long);
     356            break;
     357          case fmtULongDecimal:
     358          case fmtULongHex:
     359          case fmtULongOctal:
     360          case fmtULongBinary:
     361            args[argsLen].ul = va_arg(argList, Gulong);
     362            break;
     363          case fmtDouble:
     364          case fmtDoubleTrim:
     365            args[argsLen].f = va_arg(argList, double);
     366            break;
     367          case fmtChar:
     368            args[argsLen].c = (char)va_arg(argList, int);
     369            break;
     370          case fmtString:
     371            args[argsLen].s = va_arg(argList, char *);
     372            break;
     373          case fmtGooString:
     374            args[argsLen].gs = va_arg(argList, GooString *);
     375            break;
     376          }
     377          ++argsLen;
     378        }
     379
     380        // format the argument
     381        arg = args[idx];
     382        switch (ft) {
     383        case fmtIntDecimal:
     384          formatInt(arg.i, buf, sizeof(buf), zeroFill, width, 10, &str, &len);
     385          break;
     386        case fmtIntHex:
     387          formatInt(arg.i, buf, sizeof(buf), zeroFill, width, 16, &str, &len);
     388          break;
     389        case fmtIntOctal:
     390          formatInt(arg.i, buf, sizeof(buf), zeroFill, width, 8, &str, &len);
     391          break;
     392        case fmtIntBinary:
     393          formatInt(arg.i, buf, sizeof(buf), zeroFill, width, 2, &str, &len);
     394          break;
     395        case fmtUIntDecimal:
     396          formatUInt(arg.ui, buf, sizeof(buf), zeroFill, width, 10,
     397                     &str, &len);
     398          break;
     399        case fmtUIntHex:
     400          formatUInt(arg.ui, buf, sizeof(buf), zeroFill, width, 16,
     401                     &str, &len);
     402          break;
     403        case fmtUIntOctal:
     404          formatUInt(arg.ui, buf, sizeof(buf), zeroFill, width, 8, &str, &len);
     405          break;
     406        case fmtUIntBinary:
     407          formatUInt(arg.ui, buf, sizeof(buf), zeroFill, width, 2, &str, &len);
     408          break;
     409        case fmtLongDecimal:
     410          formatInt(arg.l, buf, sizeof(buf), zeroFill, width, 10, &str, &len);
     411          break;
     412        case fmtLongHex:
     413          formatInt(arg.l, buf, sizeof(buf), zeroFill, width, 16, &str, &len);
     414          break;
     415        case fmtLongOctal:
     416          formatInt(arg.l, buf, sizeof(buf), zeroFill, width, 8, &str, &len);
     417          break;
     418        case fmtLongBinary:
     419          formatInt(arg.l, buf, sizeof(buf), zeroFill, width, 2, &str, &len);
     420          break;
     421        case fmtULongDecimal:
     422          formatUInt(arg.ul, buf, sizeof(buf), zeroFill, width, 10,
     423                     &str, &len);
     424          break;
     425        case fmtULongHex:
     426          formatUInt(arg.ul, buf, sizeof(buf), zeroFill, width, 16,
     427                     &str, &len);
     428          break;
     429        case fmtULongOctal:
     430          formatUInt(arg.ul, buf, sizeof(buf), zeroFill, width, 8, &str, &len);
     431          break;
     432        case fmtULongBinary:
     433          formatUInt(arg.ul, buf, sizeof(buf), zeroFill, width, 2, &str, &len);
     434          break;
     435        case fmtDouble:
     436          formatDouble(arg.f, buf, sizeof(buf), prec, gFalse, &str, &len);
     437          break;
     438        case fmtDoubleTrim:
     439          formatDouble(arg.f, buf, sizeof(buf), prec, gTrue, &str, &len);
     440          break;
     441        case fmtChar:
     442          buf[0] = arg.c;
     443          str = buf;
     444          len = 1;
     445          reverseAlign = !reverseAlign;
     446          break;
     447        case fmtString:
     448          str = arg.s;
     449          len = strlen(str);
     450          reverseAlign = !reverseAlign;
     451          break;
     452        case fmtGooString:
     453          str = arg.gs->getCString();
     454          len = arg.gs->getLength();
     455          reverseAlign = !reverseAlign;
     456          break;
     457        case fmtSpace:
     458          str = buf;
     459          len = 0;
     460          width = arg.i;
     461          break;
     462        }
     463
     464        // append the formatted arg, handling width and alignment
     465        if (!reverseAlign && len < width) {
     466          for (i = len; i < width; ++i) {
     467            append(' ');
     468          }
     469        }
     470        append(str, len);
     471        if (reverseAlign && len < width) {
     472          for (i = len; i < width; ++i) {
     473            append(' ');
     474          }
     475        }
     476      }
     477
     478    } else if (*p0 == '}') {
     479      ++p0;
     480      if (*p0 == '}') {
     481        ++p0;
     482      }
     483      append('}');
     484     
     485    } else {
     486      for (p1 = p0 + 1; *p1 && *p1 != '{' && *p1 != '}'; ++p1) ;
     487      append(p0, p1 - p0);
     488      p0 = p1;
     489    }
     490  }
     491
     492  gfree(args);
     493  return this;
     494}
     495
     496void GooString::formatInt(long x, char *buf, int bufSize,
     497                        GBool zeroFill, int width, int base,
     498                        char **p, int *len) {
     499  static char vals[17] = "0123456789abcdef";
    95500  GBool neg;
    96   Guint y;
    97   int i;
    98 
    99   i = 24;
     501  int start, i, j;
     502
     503  i = bufSize;
     504  if ((neg = x < 0)) {
     505    x = -x;
     506  }
     507  start = neg ? 1 : 0;
    100508  if (x == 0) {
    101509    buf[--i] = '0';
    102510  } else {
    103     if ((neg = x < 0)) {
    104       y = (Guint)-x;
    105     } else {
    106       y = (Guint)x;
    107     }
    108     while (i > 0 && y > 0) {
    109       buf[--i] = '0' + y % 10;
    110       y /= 10;
    111     }
    112     if (neg && i > 0) {
    113       buf[--i] = '-';
    114     }
    115   }
    116   return new GooString(buf + i, 24 - i);
    117 }
    118 
    119 GooString::~GooString() {
    120   delete[] s;
    121 }
    122 
    123 GooString *GooString::clear() {
    124   s[length = 0] = '\0';
    125   resize(0);
    126   return this;
    127 }
    128 
    129 GooString *GooString::append(char c) {
    130   resize(length + 1);
    131   s[length++] = c;
    132   s[length] = '\0';
    133   return this;
    134 }
    135 
    136 GooString *GooString::append(GooString *str) {
    137   int n = str->getLength();
    138 
    139   resize(length + n);
    140   memcpy(s + length, str->getCString(), n + 1);
    141   length += n;
    142   return this;
    143 }
    144 
    145 GooString *GooString::append(const char *str) {
    146   int n = strlen(str);
    147 
    148   resize(length + n);
    149   memcpy(s + length, str, n + 1);
    150   length += n;
    151   return this;
    152 }
    153 
    154 GooString *GooString::append(const char *str, int lengthA) {
    155   resize(length + lengthA);
    156   memcpy(s + length, str, lengthA);
    157   length += lengthA;
    158   s[length] = '\0';
    159   return this;
     511    while (i > start && x) {
     512      buf[--i] = vals[x % base];
     513      x /= base;
     514    }
     515  }
     516  if (zeroFill) {
     517    for (j = bufSize - i; i > start && j < width - start; ++j) {
     518      buf[--i] = '0';
     519    }
     520  }
     521  if (neg) {
     522    buf[--i] = '-';
     523  }
     524  *p = buf + i;
     525  *len = bufSize - i;
     526}
     527
     528void GooString::formatUInt(Gulong x, char *buf, int bufSize,
     529                         GBool zeroFill, int width, int base,
     530                         char **p, int *len) {
     531  static char vals[17] = "0123456789abcdef";
     532  int i, j;
     533
     534  i = bufSize;
     535  if (x == 0) {
     536    buf[--i] = '0';
     537  } else {
     538    while (i > 0 && x) {
     539      buf[--i] = vals[x % base];
     540      x /= base;
     541    }
     542  }
     543  if (zeroFill) {
     544    for (j = bufSize - i; i > 0 && j < width; ++j) {
     545      buf[--i] = '0';
     546    }
     547  }
     548  *p = buf + i;
     549  *len = bufSize - i;
     550}
     551
     552void GooString::formatDouble(double x, char *buf, int bufSize, int prec,
     553                           GBool trim, char **p, int *len) {
     554  GBool neg, started;
     555  double x2;
     556  int d, i, j;
     557
     558  if ((neg = x < 0)) {
     559    x = -x;
     560  }
     561  x = floor(x * pow((double)10, prec) + 0.5);
     562  i = bufSize;
     563  started = !trim;
     564  for (j = 0; j < prec && i > 1; ++j) {
     565    x2 = floor(0.1 * (x + 0.5));
     566    d = (int)floor(x - 10 * x2 + 0.5);
     567    if (started || d != 0) {
     568      buf[--i] = '0' + d;
     569      started = gTrue;
     570    }
     571    x = x2;
     572  }
     573  if (i > 1 && started) {
     574    buf[--i] = '.';
     575  }
     576  if (i > 1) {
     577    do {
     578      x2 = floor(0.1 * (x + 0.5));
     579      d = (int)floor(x - 10 * x2 + 0.5);
     580      buf[--i] = '0' + d;
     581      x = x2;
     582    } while (i > 1 && x);
     583  }
     584  if (neg) {
     585    buf[--i] = '-';
     586  }
     587  *p = buf + i;
     588  *len = bufSize - i;
    160589}
    161590
    162591GooString *GooString::insert(int i, char c) {
    163   int j;
    164 
    165   resize(length + 1);
    166   for (j = length + 1; j > i; --j)
    167     s[j] = s[j-1];
    168   s[i] = c;
    169   ++length;
    170   return this;
     592  return insert(i, (const char*)&c, 1);
    171593}
    172594
    173595GooString *GooString::insert(int i, GooString *str) {
    174   int n = str->getLength();
    175   int j;
    176 
    177   resize(length + n);
    178   for (j = length; j >= i; --j)
    179     s[j+n] = s[j];
    180   memcpy(s+i, str->getCString(), n);
    181   length += n;
    182   return this;
    183 }
    184 
    185 GooString *GooString::insert(int i, const char *str) {
    186   int n = strlen(str);
    187   int j;
    188 
    189   resize(length + n);
    190   for (j = length; j >= i; --j)
    191     s[j+n] = s[j];
    192   memcpy(s+i, str, n);
    193   length += n;
    194   return this;
     596  return insert(i, str->getCString(), str->getLength());
    195597}
    196598
    197599GooString *GooString::insert(int i, const char *str, int lengthA) {
    198600  int j;
     601  int prevLen = length;
     602  if (CALC_STRING_LEN == lengthA)
     603    lengthA = strlen(str);
    199604
    200605  resize(length + lengthA);
    201   for (j = length; j >= i; --j)
     606  for (j = prevLen; j >= i; --j)
    202607    s[j+lengthA] = s[j];
    203608  memcpy(s+i, str, lengthA);
    204   length += lengthA;
    205609  return this;
    206610}
     
    216620      s[j] = s[j + n];
    217621    }
    218     resize(length -= n);
     622    resize(length - n);
    219623  }
    220624  return this;
  • trunk/poppler/mypoppler/goo/GooString.h

    r2 r250  
    99//========================================================================
    1010
    11 #ifndef GSTRING_H
    12 #define GSTRING_H
     11#ifndef GooString_H
     12#define GooString_H
    1313
    1414#ifdef USE_GCC_PRAGMAS
     
    1616#endif
    1717
     18#include <stdarg.h>
     19#include <stdlib.h> // for NULL
    1820#include "gtypes.h"
    1921
     
    3436  GooString(GooString *str, int idx, int lengthA);
    3537
     38  // Set content of a string to concatination of <s1> and <s2>. They can both
     39  // be NULL. if <s1Len> or <s2Len> is CALC_STRING_LEN, then length of the string
     40  // will be calculated with strlen(). Otherwise we assume they are a valid
     41  // length of string (or its substring)
     42  GooString* Set(const char *s1, int s1Len=CALC_STRING_LEN, const char *s2=NULL, int s2Len=CALC_STRING_LEN);
     43
    3644  // Copy a string.
    3745  GooString(GooString *str);
     
    4351  // Convert an integer to a string.
    4452  static GooString *fromInt(int x);
     53
     54  // Create a formatted string.  Similar to printf, but without the
     55  // string overflow issues.  Formatting elements consist of:
     56  //     {<arg>:[<width>][.<precision>]<type>}
     57  // where:
     58  // - <arg> is the argument number (arg 0 is the first argument
     59  //   following the format string) -- NB: args must be first used in
     60  //   order; they can be reused in any order
     61  // - <width> is the field width -- negative to reverse the alignment;
     62  //   starting with a leading zero to zero-fill (for integers)
     63  // - <precision> is the number of digits to the right of the decimal
     64  //   point (for floating point numbers)
     65  // - <type> is one of:
     66  //     d, x, o, b -- int in decimal, hex, octal, binary
     67  //     ud, ux, uo, ub -- unsigned int
     68  //     ld, lx, lo, lb, uld, ulx, ulo, ulb -- long, unsigned long
     69  //     f, g -- double
     70  //     c -- char
     71  //     s -- string (char *)
     72  //     t -- GooString *
     73  //     w -- blank space; arg determines width
     74  // To get literal curly braces, use {{ or }}.
     75  static GooString *format(char *fmt, ...);
     76  static GooString *formatv(char *fmt, va_list argList);
    4577
    4678  // Destructor.
     
    6597  GooString *append(char c);
    6698  GooString *append(GooString *str);
    67   GooString *append(const char *str);
    68   GooString *append(const char *str, int lengthA);
     99  GooString *append(const char *str, int lengthA=CALC_STRING_LEN);
     100
     101  // Append a formatted string.
     102  GooString *appendf(char *fmt, ...);
     103  GooString *appendfv(char *fmt, va_list argList);
    69104
    70105  // Insert a character or string.
    71106  GooString *insert(int i, char c);
    72107  GooString *insert(int i, GooString *str);
    73   GooString *insert(int i, const char *str);
    74   GooString *insert(int i, const char *str, int lengthA);
     108  GooString *insert(int i, const char *str, int lengthA=CALC_STRING_LEN);
    75109
    76110  // Delete a character or range of characters.
     
    90124
    91125private:
     126  // you can tweak this number for a different speed/memory usage tradeoffs.
     127  // In libc malloc() rounding is 16 so it's best to choose a value that
     128  // results in sizeof(GooString) be a multiple of 16.
     129  // 24 makes sizeof(GooString) to be 32.
     130  static const int STR_STATIC_SIZE = 24;
     131  // a special value telling that the length of the string is not given
     132  // so it must be calculated from the strings
     133  static const int CALC_STRING_LEN = -1;
    92134
     135  int  roundedSize(int len);
     136
     137  char sStatic[STR_STATIC_SIZE];
    93138  int length;
    94139  char *s;
    95140
    96   void resize(int length1);
     141  void resize(int newLength);
     142  static void formatInt(long x, char *buf, int bufSize,
     143                        GBool zeroFill, int width, int base,
     144                        char **p, int *len);
     145  static void formatUInt(Gulong x, char *buf, int bufSize,
     146                         GBool zeroFill, int width, int base,
     147                         char **p, int *len);
     148  static void formatDouble(double x, char *buf, int bufSize, int prec,
     149                           GBool trim, char **p, int *len);
    97150};
    98151
  • trunk/poppler/mypoppler/goo/GooTimer.cc

    r2 r250  
    1010#include <config.h>
    1111
    12 #ifdef HAVE_GETTIMEOFDAY
    13 
    1412#ifdef USE_GCC_PRAGMAS
    1513#pragma implementation
    1614#endif
    1715
     16#include "GooTimer.h"
    1817#include <string.h>
    19 #include "GooTimer.h"
     18
     19#define USEC_PER_SEC 1000000
    2020
    2121//------------------------------------------------------------------------
     
    2323//------------------------------------------------------------------------
    2424
     25GooTimer::GooTimer() {
     26  start();
     27}
    2528
    26 GooTimer::GooTimer() {
    27   gettimeofday (&start, NULL);
     29void GooTimer::start() {
     30#ifdef HAVE_GETTIMEOFDAY
     31  gettimeofday(&start_time, NULL);
     32#elif defined(_MSC_VER)
     33  QueryPerformanceCounter(&start_time);
     34#endif
    2835  active = true;
    2936}
    3037
    31 
    32 void
    33 GooTimer::stop() {
    34   gettimeofday (&end, NULL);
     38void GooTimer::stop() {
     39#ifdef HAVE_GETTIMEOFDAY
     40  gettimeofday(&end_time, NULL);
     41#elif defined(_MSC_VER)
     42  QueryPerformanceCounter(&end_time);
     43#endif
    3544  active = false;
    3645}
    3746
    38 #define USEC_PER_SEC 1000000
    39 double
    40 GooTimer::getElapsed ()
     47#ifdef HAVE_GETTIMEOFDAY
     48double GooTimer::getElapsed()
    4149{
    4250  double total;
     
    4452
    4553  if (active)
    46     gettimeofday (&end, NULL);
     54    gettimeofday(&end_time, NULL);
    4755
    48   if (start.tv_usec > end.tv_usec)
    49     {
    50       end.tv_usec += USEC_PER_SEC;
    51       end.tv_sec--;
    52     }
     56  if (start_time.tv_usec > end_time.tv_usec) {
     57      end_time.tv_usec += USEC_PER_SEC;
     58      end_time.tv_sec--;
     59  }
    5360
    54   elapsed.tv_usec = end.tv_usec - start.tv_usec;
    55   elapsed.tv_sec = end.tv_sec - start.tv_sec;
     61  elapsed.tv_usec = end_time.tv_usec - start_time.tv_usec;
     62  elapsed.tv_sec = end_time.tv_sec - start_time.tv_sec;
    5663
    5764  total = elapsed.tv_sec + ((double) elapsed.tv_usec / 1e6);
    5865  if (total < 0)
    59     {
    6066      total = 0;
    61     }
    6267
    6368  return total;
    6469}
     70#elif defined(_MSC_VER)
     71double GooTimer::getElapsed()
     72{
     73  LARGE_INTEGER   freq;
     74  double          time_in_secs;
     75  QueryPerformanceFrequency(&freq);
    6576
     77  if (active)
     78    QueryPerformanceCounter(&end_time);
     79
     80  time_in_secs = (double)(end_time.QuadPart-start_time.QuadPart)/(double)freq.QuadPart;
     81  return time_in_secs * 1000.0;
     82
     83}
     84#else
     85double GooTimer::getElapsed()
     86{
     87#warning "no support for GooTimer"
     88  return 0;
     89}
    6690#endif
     91
  • trunk/poppler/mypoppler/goo/GooTimer.h

    r2 r250  
    11//========================================================================
    22//
    3 // GooList.h
     3// GooTimer.h
    44//
    55// Copyright 2001-2003 Glyph & Cog, LLC
    66//
    77//========================================================================
    8 
    9 #ifdef HAVE_GETTIMEOFDAY
    108
    119#ifndef GOOTIMER_H
     
    1715
    1816#include "gtypes.h"
     17#ifdef HAVE_GETTIMEOFDAY
    1918#include <sys/time.h>
     19#endif
     20
     21#ifdef _MSC_VER
     22#include <windows.h>
     23#endif
    2024
    2125//------------------------------------------------------------------------
    22 // GooList
     26// GooTimer
    2327//------------------------------------------------------------------------
    2428
     
    2933  GooTimer();
    3034
    31   void stop ();
     35  void start();
     36  void stop();
    3237  double getElapsed();
    3338
    34 
    3539private:
    36 
    37         struct timeval start;
    38         struct timeval end;
    39         GBool active;
     40#ifdef HAVE_GETTIMEOFDAY
     41  struct timeval start_time;
     42  struct timeval end_time;
     43#elif defined(_MSC_VER)
     44  LARGE_INTEGER start_time;
     45  LARGE_INTEGER end_time;
     46#endif
     47  GBool active;
    4048};
    4149
    4250#endif
    43 
    44 #endif
  • trunk/poppler/mypoppler/goo/GooVector.h

    r27 r250  
    1 #ifndef _VECTOR_H
    2 #define _VECTOR_H
     1#ifndef GOO_VECTOR_H
     2#define GOO_VECTOR_H
    33#include "goo/gtypes.h"
    44
  • trunk/poppler/mypoppler/goo/gfile.cc

    r134 r250  
    1111#include <config.h>
    1212
    13 #ifndef WIN32
     13#ifdef WIN32
     14#  include <time.h>
     15#else
    1416#  if defined(MACOS)
    1517#    include <sys/stat.h>
     
    453455#if defined(WIN32)
    454456  //---------- Win32 ----------
    455   char *s;
    456 
    457   if (!(s = _tempnam(getenv("TEMP"), NULL))) {
    458     return gFalse;
    459   }
    460   *name = new GooString(s);
    461   free(s);
    462   if (ext) {
    463     (*name)->append(ext);
    464   }
    465   if (!(*f = fopen((*name)->getCString(), mode))) {
    466     delete (*name);
    467     return gFalse;
    468   }
    469   return gTrue;
     457  char *tempDir;
     458  GooString *s, *s2;
     459  char buf[32];
     460  FILE *f2;
     461  int t, i;
     462
     463  // this has the standard race condition problem, but I haven't found
     464  // a better way to generate temp file names with extensions on
     465  // Windows
     466  if ((tempDir = getenv("TEMP"))) {
     467    s = new GooString(tempDir);
     468    s->append('\\');
     469  } else {
     470    s = new GooString();
     471  }
     472  s->append("x");
     473  t = (int)time(NULL);
     474  for (i = 0; i < 1000; ++i) {
     475    sprintf(buf, "%d", t + i);
     476    s2 = s->copy()->append(buf);
     477    if (ext) {
     478      s2->append(ext);
     479    }
     480    if (!(f2 = fopen(s2->getCString(), "r"))) {
     481      if (!(f2 = fopen(s2->getCString(), mode))) {
     482        delete s2;
     483        delete s;
     484        return gFalse;
     485      }
     486      *name = s2;
     487      *f = f2;
     488      delete s;
     489      return gTrue;
     490    }
     491    fclose(f2);
     492    delete s2;
     493  }
     494  delete s;
     495  return gFalse;
    470496#elif defined(VMS) || defined(__EMX__) || defined(ACORN) || defined(MACOS) || defined(OS2)
    471497  //---------- non-Unix ----------
     
    644670  delete path;
    645671#if defined(WIN32)
    646   if (hnd) {
     672  if (hnd != INVALID_HANDLE_VALUE) {
    647673    FindClose(hnd);
    648     hnd = NULL;
     674    hnd = INVALID_HANDLE_VALUE;
    649675  }
    650676#elif defined(ACORN)
     
    660686
    661687#if defined(WIN32)
    662   if (hnd) {
     688  if (hnd != INVALID_HANDLE_VALUE) {
    663689    e = new GDirEntry(path->getCString(), ffd.cFileName, doStat);
    664     if (hnd  && !FindNextFile(hnd, &ffd)) {
     690    if (!FindNextFile(hnd, &ffd)) {
    665691      FindClose(hnd);
    666       hnd = NULL;
     692      hnd = INVALID_HANDLE_VALUE;
    667693    }
    668694  } else {
     
    706732  GooString *tmp;
    707733
    708   if (hnd)
     734  if (hnd != INVALID_HANDLE_VALUE)
    709735    FindClose(hnd);
    710736  tmp = path->copy();
  • trunk/poppler/mypoppler/goo/gmem.cc

    r115 r250  
    1818
    1919typedef struct _GMemHdr {
     20  unsigned int magic;
    2021  int size;
    2122  int index;
    22   struct _GMemHdr *next;
     23  struct _GMemHdr *next, *prev;
    2324} GMemHdr;
    2425
    2526#define gMemHdrSize ((sizeof(GMemHdr) + 7) & ~7)
    2627#define gMemTrlSize (sizeof(long))
     28
     29#define gMemMagic 0xabcd9999
    2730
    2831#if gmemTrlSize==8
     
    3639  ((((size) + gMemTrlSize - 1) / gMemTrlSize) * gMemTrlSize)
    3740
    38 #define gMemNLists    64
    39 #define gMemListShift  4
    40 #define gMemListMask  (gMemNLists - 1)
    41 static GMemHdr *gMemList[gMemNLists] = {
    42   NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
    43   NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
    44   NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
    45   NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
    46   NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
    47   NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
    48   NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
    49   NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
    50 };
     41static GMemHdr *gMemHead = NULL;
     42static GMemHdr *gMemTail = NULL;
    5143
    5244static int gMemIndex = 0;
     
    5648#endif /* DEBUG_MEM */
    5749
    58 void *gmalloc(size_t size) {
    59 #ifdef DEBUG_MEM
    60   size_t size1;
     50void *gmalloc(size_t size) GMEM_EXCEP {
     51#ifdef DEBUG_MEM
     52  int size1;
    6153  char *mem;
    6254  GMemHdr *hdr;
    6355  void *data;
    64   int lst;
    6556  unsigned long *trl, *p;
    6657
    67   if (size <= 0)
    68     return NULL;
     58  if (size <= 0) {
     59    return NULL;
     60  }
    6961  size1 = gMemDataSize(size);
    7062  if (!(mem = (char *)malloc(size1 + gMemHdrSize + gMemTrlSize))) {
     63#if USE_EXCEPTIONS
     64    throw GMemException();
     65#else
    7166    fprintf(stderr, "Out of memory\n");
    7267    exit(1);
     68#endif
    7369  }
    7470  hdr = (GMemHdr *)mem;
    7571  data = (void *)(mem + gMemHdrSize);
    7672  trl = (unsigned long *)(mem + gMemHdrSize + size1);
     73  hdr->magic = gMemMagic;
    7774  hdr->size = size;
    7875  hdr->index = gMemIndex++;
    79   lst = ((int)hdr >> gMemListShift) & gMemListMask;
    80   hdr->next = gMemList[lst];
    81   gMemList[lst] = hdr;
     76  if (gMemTail) {
     77    gMemTail->next = hdr;
     78    hdr->prev = gMemTail;
     79    gMemTail = hdr;
     80  } else {
     81    hdr->prev = NULL;
     82    gMemHead = gMemTail = hdr;
     83  }
     84  hdr->next = NULL;
    8285  ++gMemAlloc;
    8386  gMemInUse += size;
    84   for (p = (unsigned long *)data; p <= trl; ++p)
     87  for (p = (unsigned long *)data; p <= trl; ++p) {
    8588    *p = gMemDeadVal;
     89  }
    8690  return data;
    8791#else
    8892  void *p;
    8993
    90   if (size <= 0)
    91     return NULL;
     94  if (size <= 0) {
     95    return NULL;
     96  }
    9297  if (!(p = malloc(size))) {
     98#if USE_EXCEPTIONS
     99    throw GMemException();
     100#else
    93101    fprintf(stderr, "Out of memory\n");
    94102    exit(1);
     103#endif
    95104  }
    96105  return p;
     
    98107}
    99108
    100 void *grealloc(void *p, size_t size) {
     109void *grealloc(void *p, size_t size) GMEM_EXCEP {
    101110#ifdef DEBUG_MEM
    102111  GMemHdr *hdr;
    103112  void *q;
    104   size_t oldSize;
    105 
    106   if (size <= 0) {
    107     if (p)
     113  int oldSize;
     114
     115  if (size <= 0) {
     116    if (p) {
    108117      gfree(p);
     118    }
    109119    return NULL;
    110120  }
     
    123133
    124134  if (size <= 0) {
    125     if (p)
     135    if (p) {
    126136      free(p);
    127     return NULL;
    128   }
    129   if (p)
     137    }
     138    return NULL;
     139  }
     140  if (p) {
    130141    q = realloc(p, size);
    131   else
     142  } else {
    132143    q = malloc(size);
     144  }
    133145  if (!q) {
     146#if USE_EXCEPTIONS
     147    throw GMemException();
     148#else
    134149    fprintf(stderr, "Out of memory\n");
    135150    exit(1);
     151#endif
    136152  }
    137153  return q;
     
    139155}
    140156
    141 void *gmallocn(int nObjs, int objSize) {
     157void *gmallocn(int nObjs, int objSize) GMEM_EXCEP {
    142158  int n;
    143159
     160  if (nObjs == 0) {
     161    return NULL;
     162  }
    144163  n = nObjs * objSize;
    145   if (objSize == 0 || n / objSize != nObjs) {
     164  if (objSize <= 0 || nObjs < 0 || nObjs >= INT_MAX / objSize) {
     165#if USE_EXCEPTIONS
     166    throw GMemException();
     167#else
    146168    fprintf(stderr, "Bogus memory allocation size\n");
    147169    exit(1);
     170#endif
    148171  }
    149172  return gmalloc(n);
    150173}
    151174
    152 void *greallocn(void *p, int nObjs, int objSize) {
     175void *gmallocn_checkoverflow(int nObjs, int objSize) GMEM_EXCEP {
    153176  int n;
    154177
     178  if (nObjs == 0) {
     179    return NULL;
     180  }
    155181  n = nObjs * objSize;
    156   if (objSize == 0 || n / objSize != nObjs) {
     182  if (objSize <= 0 || nObjs < 0 || nObjs >= INT_MAX / objSize) {
     183#if USE_EXCEPTIONS
     184    throw GMemException();
     185#else
    157186    fprintf(stderr, "Bogus memory allocation size\n");
    158     exit(1);
     187    return NULL;
     188#endif
     189  }
     190  return gmalloc(n);
     191}
     192
     193void *greallocn(void *p, int nObjs, int objSize) GMEM_EXCEP {
     194  int n;
     195
     196  if (nObjs == 0) {
     197    if (p) {
     198      gfree(p);
     199    }
     200    return NULL;
     201  }
     202  n = nObjs * objSize;
     203  if (objSize <= 0 || nObjs < 0 || nObjs >= INT_MAX / objSize) {
     204#if USE_EXCEPTIONS
     205    throw GMemException();
     206#else
     207    fprintf(stderr, "Bogus memory allocation size\n");
     208    exit(1);
     209#endif
    159210  }
    160211  return grealloc(p, n);
     
    163214void gfree(void *p) {
    164215#ifdef DEBUG_MEM
    165   size_t size;
     216  int size;
    166217  GMemHdr *hdr;
    167   GMemHdr *prevHdr, *q;
    168   int lst;
    169218  unsigned long *trl, *clr;
    170219
    171220  if (p) {
    172221    hdr = (GMemHdr *)((char *)p - gMemHdrSize);
    173     lst = ((int)hdr >> gMemListShift) & gMemListMask;
    174     for (prevHdr = NULL, q = gMemList[lst]; q; prevHdr = q, q = q->next) {
    175       if (q == hdr)
    176         break;
    177     }
    178     if (q) {
    179       if (prevHdr)
    180         prevHdr->next = hdr->next;
    181       else
    182         gMemList[lst] = hdr->next;
     222    if (hdr->magic == gMemMagic &&
     223        ((hdr->prev == NULL) == (hdr == gMemHead)) &&
     224        ((hdr->next == NULL) == (hdr == gMemTail))) {
     225      if (hdr->prev) {
     226        hdr->prev->next = hdr->next;
     227      } else {
     228        gMemHead = hdr->next;
     229      }
     230      if (hdr->next) {
     231        hdr->next->prev = hdr->prev;
     232      } else {
     233        gMemTail = hdr->prev;
     234      }
    183235      --gMemAlloc;
    184236      gMemInUse -= hdr->size;
     
    189241                hdr->index, p);
    190242      }
    191       for (clr = (unsigned long *)hdr; clr <= trl; ++clr)
     243      for (clr = (unsigned long *)hdr; clr <= trl; ++clr) {
    192244        *clr = gMemDeadVal;
     245      }
    193246      free(hdr);
    194247    } else {
     
    197250  }
    198251#else
    199   if (p)
     252  if (p) {
    200253    free(p);
     254  }
    201255#endif
    202256}
     
    205259void gMemReport(FILE *f) {
    206260  GMemHdr *p;
    207   int lst;
    208261
    209262  fprintf(f, "%d memory allocations in all\n", gMemIndex);
     
    212265    fprintf(f, " index     size\n");
    213266    fprintf(f, "-------- --------\n");
    214     for (lst = 0; lst < gMemNLists; ++lst) {
    215       for (p = gMemList[lst]; p; p = p->next)
    216         fprintf(f, "%8d %8d\n", p->index, p->size);
     267    for (p = gMemHead; p; p = p->next) {
     268      fprintf(f, "%8d %8d\n", p->index, p->size);
    217269    }
    218270  } else {
     
    229281  return s1;
    230282}
     283
     284char *gstrndup(const char *s, size_t n) {
     285  char *s1 = (char*)gmalloc(n + 1); /* cannot return NULL for size > 0 */
     286  s1[n] = '\0';
     287  memcpy(s1, s, n);
     288  return s1;
     289}
  • trunk/poppler/mypoppler/goo/gmem.h

    r2 r250  
    1111
    1212#include <stdio.h>
     13#include <poppler/poppler-config.h>
     14
     15#if USE_EXCEPTIONS
     16
     17class GMemException {
     18public:
     19  GMemException() {}
     20  ~GMemException() {}
     21};
     22
     23#define GMEM_EXCEP throw(GMemException)
     24
     25#else // USE_EXCEPTIONS
     26
     27#define GMEM_EXCEP
     28
     29#endif // USE_EXCEPTIONS
    1330
    1431#ifdef __cplusplus
     
    2037 * returns NULL.
    2138 */
    22 extern void *gmalloc(size_t size);
     39extern void *gmalloc(size_t size) GMEM_EXCEP;
    2340
    2441/*
     
    2643 * returns NULL.  If <p> is NULL, calls malloc instead of realloc().
    2744 */
    28 extern void *grealloc(void *p, size_t size);
     45extern void *grealloc(void *p, size_t size) GMEM_EXCEP;
    2946
    3047/*
     
    3350 * bytes, but there is an additional error check that the total size
    3451 * doesn't overflow an int.
     52 * The gmallocn_checkoverflow variant returns NULL instead of exiting
     53 * the application if a overflow is detected
    3554 */
    36 extern void *gmallocn(int nObjs, int objSize);
    37 extern void *greallocn(void *p, int nObjs, int objSize);
     55extern void *gmallocn(int nObjs, int objSize) GMEM_EXCEP;
     56extern void *gmallocn_checkoverflow(int nObjs, int objSize) GMEM_EXCEP;
     57extern void *greallocn(void *p, int nObjs, int objSize) GMEM_EXCEP;
    3858
    3959/*
     
    5676extern char *copyString(char *s);
    5777
     78/*
     79 * Allocate memory and copy a limited-length string to it.
     80 */
     81extern char *gstrndup(const char *s, size_t n);
     82
    5883#ifdef __cplusplus
    5984}
  • trunk/poppler/mypoppler/poppler/Annot.cc

    r2 r250  
    1414
    1515#include <stdlib.h>
     16#include <math.h>
    1617#include "goo/gmem.h"
     18#include "GooList.h"
     19#include "Error.h"
    1720#include "Object.h"
    1821#include "Catalog.h"
    1922#include "Gfx.h"
    2023#include "Lexer.h"
    21 #include "UGooString.h"
    2224#include "Annot.h"
     25#include "GfxFont.h"
     26#include "CharCodeToUnicode.h"
     27#include "PDFDocEncoding.h"
     28#include "Form.h"
     29#include "Error.h"
     30#include "Page.h"
     31#include "XRef.h"
     32#include "Movie.h"
     33#include <string.h>
     34
     35#define annotFlagHidden    0x0002
     36#define annotFlagPrint     0x0004
     37#define annotFlagNoView    0x0020
     38
     39#define fieldFlagReadOnly           0x00000001
     40#define fieldFlagRequired           0x00000002
     41#define fieldFlagNoExport           0x00000004
     42#define fieldFlagMultiline          0x00001000
     43#define fieldFlagPassword           0x00002000
     44#define fieldFlagNoToggleToOff      0x00004000
     45#define fieldFlagRadio              0x00008000
     46#define fieldFlagPushbutton         0x00010000
     47#define fieldFlagCombo              0x00020000
     48#define fieldFlagEdit               0x00040000
     49#define fieldFlagSort               0x00080000
     50#define fieldFlagFileSelect         0x00100000
     51#define fieldFlagMultiSelect        0x00200000
     52#define fieldFlagDoNotSpellCheck    0x00400000
     53#define fieldFlagDoNotScroll        0x00800000
     54#define fieldFlagComb               0x01000000
     55#define fieldFlagRichText           0x02000000
     56#define fieldFlagRadiosInUnison     0x02000000
     57#define fieldFlagCommitOnSelChange  0x04000000
     58
     59#define fieldQuadLeft   0
     60#define fieldQuadCenter 1
     61#define fieldQuadRight  2
     62
     63// distance of Bezier control point from center for circle approximation
     64// = (4 * (sqrt(2) - 1) / 3) * r
     65#define bezierCircle 0.55228475
     66
     67AnnotLineEndingStyle parseAnnotLineEndingStyle(GooString *string) {
     68  if (string != NULL) {
     69    if (!string->cmp("Square")) {
     70      return annotLineEndingSquare;
     71    } else if (!string->cmp("Circle")) {
     72      return annotLineEndingCircle;
     73    } else if (!string->cmp("Diamond")) {
     74      return annotLineEndingDiamond;
     75    } else if (!string->cmp("OpenArrow")) {
     76      return annotLineEndingOpenArrow;
     77    } else if (!string->cmp("ClosedArrow")) {
     78      return annotLineEndingClosedArrow;
     79    } else if (!string->cmp("Butt")) {
     80      return annotLineEndingButt;
     81    } else if (!string->cmp("ROpenArrow")) {
     82      return annotLineEndingROpenArrow;
     83    } else if (!string->cmp("RClosedArrow")) {
     84      return annotLineEndingRClosedArrow;
     85    } else if (!string->cmp("Slash")) {
     86      return annotLineEndingSlash;
     87    } else {
     88      return annotLineEndingNone;
     89    }
     90  } else {
     91    return annotLineEndingNone;
     92  } 
     93}
     94
     95AnnotExternalDataType parseAnnotExternalData(Dict* dict) {
     96  Object obj1;
     97  AnnotExternalDataType type;
     98
     99  if (dict->lookup("Subtype", &obj1)->isName()) {
     100    GooString *typeName = new GooString(obj1.getName());
     101
     102    if (!typeName->cmp("Markup3D")) {
     103      type = annotExternalDataMarkup3D;
     104    } else {
     105      type = annotExternalDataMarkupUnknown;
     106    }
     107    delete typeName;
     108  } else {
     109    type = annotExternalDataMarkupUnknown;
     110  }
     111  obj1.free();
     112
     113  return type;
     114}
     115
     116//------------------------------------------------------------------------
     117// AnnotBorderEffect
     118//------------------------------------------------------------------------
     119
     120AnnotBorderEffect::AnnotBorderEffect(Dict *dict) {
     121  Object obj1;
     122
     123  if (dict->lookup("S", &obj1)->isName()) {
     124    GooString *effectName = new GooString(obj1.getName());
     125
     126    if (!effectName->cmp("C"))
     127      effectType = borderEffectCloudy;
     128    else
     129      effectType = borderEffectNoEffect;
     130    delete effectName;
     131  } else {
     132    effectType = borderEffectNoEffect;
     133  }
     134  obj1.free();
     135
     136  if ((dict->lookup("I", &obj1)->isNum()) && effectType == borderEffectCloudy) {
     137    intensity = obj1.getNum();
     138  } else {
     139    intensity = 0;
     140  }
     141  obj1.free();
     142}
     143
     144//------------------------------------------------------------------------
     145// AnnotCalloutLine
     146//------------------------------------------------------------------------
     147
     148AnnotCalloutLine::AnnotCalloutLine(double x1, double y1, double x2, double y2) {
     149  this->x1 = x1;
     150  this->y1 = y1;
     151  this->x2 = x2;
     152  this->y2 = y2;
     153}
     154
     155//------------------------------------------------------------------------
     156// AnnotCalloutMultiLine
     157//------------------------------------------------------------------------
     158
     159AnnotCalloutMultiLine::AnnotCalloutMultiLine(double x1, double y1, double x2,
     160    double y2, double x3, double y3) : AnnotCalloutLine(x1, y1, x2, y2) {
     161  this->x3 = x3;
     162  this->y3 = y3;
     163}
     164
     165//------------------------------------------------------------------------
     166// AnnotQuadrilateral
     167//------------------------------------------------------------------------
     168
     169AnnotQuadrilaterals::AnnotQuadrilaterals(Array *array, PDFRectangle *rect) {
     170  int arrayLength = array->getLength();
     171  GBool correct = gTrue;
     172  int quadsLength = 0;
     173  AnnotQuadrilateral **quads;
     174  double quadArray[8];
     175
     176  // default values
     177  quadrilaterals = NULL;
     178  quadrilateralsLength = 0;
     179
     180  if ((arrayLength % 8) == 0) {
     181    int i = 0;
     182
     183    quadsLength = arrayLength / 8;
     184    quads = (AnnotQuadrilateral **) gmallocn
     185        ((quadsLength), sizeof(AnnotQuadrilateral *));
     186    memset(quads, 0, quadsLength * sizeof(AnnotQuadrilateral *));
     187
     188    while (i < (quadsLength) && correct) {
     189      for (int j = 0; j < 8 && correct; j++) {
     190        Object obj;
     191        if (array->get(i * 8 + j, &obj)->isNum()) {
     192          quadArray[j] = obj.getNum();
     193          if (j % 2 == 1) {
     194              if (quadArray[j] < rect->y1 || quadArray[j] > rect->y2)
     195                  correct = gFalse;
     196          } else {
     197              if (quadArray[j] < rect->x1 || quadArray[j] > rect->x2)
     198                  correct = gFalse;
     199          }
     200        } else {
     201            correct = gFalse;
     202        }
     203        obj.free();
     204      }
     205
     206      if (correct)
     207        quads[i] = new AnnotQuadrilateral(quadArray[0], quadArray[1],
     208                                          quadArray[2], quadArray[3],
     209                                          quadArray[4], quadArray[5],
     210                                          quadArray[6], quadArray[7]);
     211      i++;
     212    }
     213
     214    if (correct) {
     215      quadrilateralsLength = quadsLength;
     216      quadrilaterals = quads;
     217    } else {
     218      for (int j = 0; j < i; j++)
     219        delete quads[j];
     220      gfree (quads);
     221    }
     222  }
     223}
     224
     225AnnotQuadrilaterals::~AnnotQuadrilaterals() {
     226  if (quadrilaterals) {
     227    for(int i = 0; i < quadrilateralsLength; i++)
     228      delete quadrilaterals[i];
     229
     230    gfree (quadrilaterals);
     231  }
     232}
     233
     234double AnnotQuadrilaterals::getX1(int quadrilateral) {
     235  if (quadrilateral >= 0  && quadrilateral < quadrilateralsLength)
     236    return quadrilaterals[quadrilateral]->x1;
     237  return 0;
     238}
     239
     240double AnnotQuadrilaterals::getY1(int quadrilateral) {
     241  if (quadrilateral >= 0  && quadrilateral < quadrilateralsLength)
     242    return quadrilaterals[quadrilateral]->y1;
     243  return 0;
     244}
     245
     246double AnnotQuadrilaterals::getX2(int quadrilateral) {
     247  if (quadrilateral >= 0  && quadrilateral < quadrilateralsLength)
     248    return quadrilaterals[quadrilateral]->x2;
     249  return 0;
     250}
     251
     252double AnnotQuadrilaterals::getY2(int quadrilateral) {
     253  if (quadrilateral >= 0  && quadrilateral < quadrilateralsLength)
     254    return quadrilaterals[quadrilateral]->y2;
     255  return 0;
     256}
     257
     258double AnnotQuadrilaterals::getX3(int quadrilateral) {
     259  if (quadrilateral >= 0  && quadrilateral < quadrilateralsLength)
     260    return quadrilaterals[quadrilateral]->x3;
     261  return 0;
     262}
     263
     264double AnnotQuadrilaterals::getY3(int quadrilateral) {
     265  if (quadrilateral >= 0  && quadrilateral < quadrilateralsLength)
     266    return quadrilaterals[quadrilateral]->y3;
     267  return 0;
     268}
     269
     270double AnnotQuadrilaterals::getX4(int quadrilateral) {
     271  if (quadrilateral >= 0  && quadrilateral < quadrilateralsLength)
     272    return quadrilaterals[quadrilateral]->x4;
     273  return 0;
     274}
     275
     276double AnnotQuadrilaterals::getY4(int quadrilateral) {
     277  if (quadrilateral >= 0  && quadrilateral < quadrilateralsLength)
     278    return quadrilaterals[quadrilateral]->y4;
     279  return 0;
     280}
     281
     282AnnotQuadrilaterals::AnnotQuadrilateral::AnnotQuadrilateral(double x1, double y1,
     283        double x2, double y2, double x3, double y3, double x4, double y4) {
     284  this->x1 = x1;
     285  this->y1 = y1;
     286  this->x2 = x2;
     287  this->y2 = y2;
     288  this->x3 = x3;
     289  this->y3 = y3;
     290  this->x4 = x4;
     291  this->y4 = y4;
     292}
     293
     294//------------------------------------------------------------------------
     295// AnnotQuadPoints
     296//------------------------------------------------------------------------
     297
     298AnnotQuadPoints::AnnotQuadPoints(double x1, double y1, double x2, double y2,
     299    double x3, double y3, double x4, double y4) {
     300  this->x1 = x1;
     301  this->y1 = y1;
     302  this->x2 = x2;
     303  this->y2 = y2;
     304  this->x3 = x3;
     305  this->y3 = y3;
     306  this->x4 = x4;
     307  this->y4 = y4;
     308}
     309
     310//------------------------------------------------------------------------
     311// AnnotBorder
     312//------------------------------------------------------------------------
     313AnnotBorder::AnnotBorder() {
     314  type = typeUnknown;
     315  width = 1;
     316  dashLength = 0;
     317  dash = NULL;
     318  style = borderSolid;
     319}
     320
     321AnnotBorder::~AnnotBorder() {
     322  if (dash)
     323    gfree (dash);
     324}
     325 
     326//------------------------------------------------------------------------
     327// AnnotBorderArray
     328//------------------------------------------------------------------------
     329
     330AnnotBorderArray::AnnotBorderArray() {
     331  type = typeArray;
     332  horizontalCorner = 0;
     333  verticalCorner = 0;
     334}
     335
     336AnnotBorderArray::AnnotBorderArray(Array *array) {
     337  Object obj1;
     338  int arrayLength = array->getLength();
     339
     340  if (arrayLength >= 3) {
     341    // implementation note 81 in Appendix H.
     342
     343    if (array->get(0, &obj1)->isNum())
     344      horizontalCorner = obj1.getNum();
     345    obj1.free();
     346
     347    if (array->get(1, &obj1)->isNum())
     348      verticalCorner = obj1.getNum();
     349    obj1.free();
     350
     351    if (array->get(2, &obj1)->isNum())
     352      width = obj1.getNum();
     353    obj1.free();
     354
     355    // TODO: check not all zero ? (Line Dash Pattern Page 217 PDF 8.1)
     356    if (arrayLength > 3) {
     357      GBool correct = gTrue;
     358      int tempLength = array->getLength() - 3;
     359      double *tempDash = (double *) gmallocn (tempLength, sizeof (double));
     360
     361      for(int i = 0; i < tempLength && i < DASH_LIMIT && correct; i++) {
     362
     363        if (array->get((i + 3), &obj1)->isNum()) {
     364          tempDash[i] = obj1.getNum();
     365
     366          if (tempDash[i] < 0)
     367            correct = gFalse;
     368
     369        } else {
     370          correct = gFalse;
     371        }
     372        obj1.free();
     373      }
     374
     375      if (correct) {
     376        dashLength = tempLength;
     377        dash = tempDash;
     378        style = borderDashed;
     379      } else {
     380        gfree (tempDash);
     381      }
     382    }
     383  }
     384}
     385
     386//------------------------------------------------------------------------
     387// AnnotBorderBS
     388//------------------------------------------------------------------------
     389
     390AnnotBorderBS::AnnotBorderBS() {
     391  type = typeBS;
     392}
     393
     394AnnotBorderBS::AnnotBorderBS(Dict *dict) {
     395  Object obj1, obj2;
     396
     397  // acroread 8 seems to need both W and S entries for
     398  // any border to be drawn, even though the spec
     399  // doesn't claim anything of that sort. We follow
     400  // that behaviour by veryifying both entries exist
     401  // otherwise we set the borderWidth to 0
     402  // --jrmuizel
     403  dict->lookup("W", &obj1);
     404  dict->lookup("S", &obj2);
     405  if (obj1.isNum() && obj2.isName()) {
     406    GooString *styleName = new GooString(obj2.getName());
     407
     408    width = obj1.getNum();
     409
     410    if (!styleName->cmp("S")) {
     411      style = borderSolid;
     412    } else if (!styleName->cmp("D")) {
     413      style = borderDashed;
     414    } else if (!styleName->cmp("B")) {
     415      style = borderBeveled;
     416    } else if (!styleName->cmp("I")) {
     417      style = borderInset;
     418    } else if (!styleName->cmp("U")) {
     419      style = borderUnderlined;
     420    } else {
     421      style = borderSolid;
     422    }
     423    delete styleName;
     424  } else {
     425    width = 0;
     426  }
     427  obj2.free();
     428  obj1.free();
     429
     430  // TODO: check not all zero (Line Dash Pattern Page 217 PDF 8.1)
     431  if (dict->lookup("D", &obj1)->isArray()) {
     432    GBool correct = gTrue;
     433    int tempLength = obj1.arrayGetLength();
     434    double *tempDash = (double *) gmallocn (tempLength, sizeof (double));
     435
     436    for(int i = 0; i < tempLength && correct; i++) {
     437      Object obj2;
     438
     439      if (obj1.arrayGet(i, &obj2)->isNum()) {
     440        tempDash[i] = obj2.getNum();
     441
     442        if (tempDash[i] < 0)
     443          correct = gFalse;
     444      } else {
     445        correct = gFalse;
     446      }
     447      obj2.free();
     448    }
     449
     450    if (correct) {
     451      dashLength = tempLength;
     452      dash = tempDash;
     453      style = borderDashed;
     454    } else {
     455      gfree (tempDash);
     456    }
     457
     458  }
     459
     460  if (!dash) {
     461    dashLength = 1;
     462    dash = (double *) gmallocn (dashLength, sizeof (double));
     463    dash[0] = 3;
     464  }
     465  obj1.free();
     466}
     467
     468//------------------------------------------------------------------------
     469// AnnotColor
     470//------------------------------------------------------------------------
     471
     472AnnotColor::AnnotColor() {
     473  length = 0;
     474  values = NULL;
     475}
     476
     477AnnotColor::AnnotColor(Array *array) {
     478  // TODO: check what Acrobat does in the case of having more than 5 numbers.
     479  if (array->getLength() < 5) {
     480    length = array->getLength();
     481    values = (double *) gmallocn (length, sizeof(double));
     482
     483    for(int i = 0; i < length; i++) { 
     484      Object obj1;
     485
     486      if (array->get(i, &obj1)->isNum()) {
     487        values[i] = obj1.getNum();
     488
     489        if (values[i] < 0 || values[i] > 1)
     490          values[i] = 0;
     491      } else {
     492        values[i] = 0;
     493      }
     494      obj1.free();
     495    }
     496  }
     497}
     498
     499AnnotColor::~AnnotColor() {
     500  if (values)
     501    gfree (values);
     502}
     503
     504//------------------------------------------------------------------------
     505// AnnotBorderStyle
     506//------------------------------------------------------------------------
     507
     508AnnotBorderStyle::AnnotBorderStyle(AnnotBorderType typeA, double widthA,
     509                                   double *dashA, int dashLengthA,
     510                                   double rA, double gA, double bA) {
     511  type = typeA;
     512  width = widthA;
     513  dash = dashA;
     514  dashLength = dashLengthA;
     515  r = rA;
     516  g = gA;
     517  b = bA;
     518}
     519
     520AnnotBorderStyle::~AnnotBorderStyle() {
     521  if (dash) {
     522    gfree(dash);
     523  }
     524}
     525
     526//------------------------------------------------------------------------
     527// AnnotIconFit
     528//------------------------------------------------------------------------
     529
     530AnnotIconFit::AnnotIconFit(Dict* dict) {
     531  Object obj1;
     532
     533  if (dict->lookup("SW", &obj1)->isName()) {
     534    GooString *scaleName = new GooString(obj1.getName());
     535
     536    if(!scaleName->cmp("B")) {
     537      scaleWhen = scaleBigger;
     538    } else if(!scaleName->cmp("S")) {
     539      scaleWhen = scaleSmaller;
     540    } else if(!scaleName->cmp("N")) {
     541      scaleWhen = scaleNever;
     542    } else {
     543      scaleWhen = scaleAlways;
     544    }
     545    delete scaleName;
     546  } else {
     547    scaleWhen = scaleAlways;
     548  }
     549  obj1.free();
     550
     551  if (dict->lookup("S", &obj1)->isName()) {
     552    GooString *scaleName = new GooString(obj1.getName());
     553
     554    if(!scaleName->cmp("A")) {
     555      scale = scaleAnamorphic;
     556    } else {
     557      scale = scaleProportional;
     558    }
     559    delete scaleName;
     560  } else {
     561    scale = scaleProportional;
     562  }
     563  obj1.free();
     564
     565  if (dict->lookup("A", &obj1)->isArray() && obj1.arrayGetLength() == 2) {
     566    Object obj2;
     567    (obj1.arrayGet(0, &obj2)->isNum() ? left = obj2.getNum() : left = 0);
     568    obj2.free();
     569    (obj1.arrayGet(1, &obj2)->isNum() ? bottom = obj2.getNum() : bottom = 0);
     570    obj2.free();
     571
     572    if (left < 0 || left > 1)
     573      left = 0.5;
     574
     575    if (bottom < 0 || bottom > 1)
     576      bottom = 0.5;
     577
     578  } else {
     579    left = bottom = 0.5;
     580  }
     581  obj1.free();
     582
     583  if (dict->lookup("FB", &obj1)->isBool()) {
     584    fullyBounds = obj1.getBool();
     585  } else {
     586    fullyBounds = gFalse;
     587  }
     588  obj1.free();
     589}
     590
     591//------------------------------------------------------------------------
     592// AnnotAppearanceCharacs
     593//------------------------------------------------------------------------
     594
     595AnnotAppearanceCharacs::AnnotAppearanceCharacs(Dict *dict) {
     596  Object obj1;
     597
     598  if (dict->lookup("R", &obj1)->isInt()) {
     599    rotation = obj1.getInt();
     600  } else {
     601    rotation = 0;
     602  }
     603  obj1.free();
     604
     605  if (dict->lookup("BC", &obj1)->isArray()) {
     606    borderColor = new AnnotColor(obj1.getArray());
     607  } else {
     608    borderColor = NULL;
     609  }
     610  obj1.free();
     611
     612  if (dict->lookup("BG", &obj1)->isArray()) {
     613    backColor = new AnnotColor(obj1.getArray());
     614  } else {
     615    backColor = NULL;
     616  }
     617  obj1.free();
     618
     619  if (dict->lookup("CA", &obj1)->isName()) {
     620    normalCaption = new GooString(obj1.getName());
     621  } else {
     622    normalCaption = NULL;
     623  }
     624  obj1.free();
     625
     626  if (dict->lookup("RC", &obj1)->isName()) {
     627    rolloverCaption = new GooString(obj1.getName());
     628  } else {
     629    rolloverCaption = NULL;
     630  }
     631  obj1.free();
     632
     633  if (dict->lookup("AC", &obj1)->isName()) {
     634    alternateCaption = new GooString(obj1.getName());
     635  } else {
     636    alternateCaption = NULL;
     637  }
     638  obj1.free();
     639
     640  if (dict->lookup("IF", &obj1)->isDict()) {
     641    iconFit = new AnnotIconFit(obj1.getDict());
     642  } else {
     643    iconFit = NULL;
     644  }
     645  obj1.free();
     646
     647  if (dict->lookup("TP", &obj1)->isInt()) {
     648    position = (AnnotAppearanceCharacsTextPos) obj1.getInt();
     649  } else {
     650    position = captionNoIcon;
     651  }
     652  obj1.free();
     653}
     654
     655AnnotAppearanceCharacs::~AnnotAppearanceCharacs() {
     656  if (borderColor)
     657    delete borderColor;
     658
     659  if (backColor)
     660    delete backColor;
     661
     662  if (normalCaption)
     663    delete normalCaption;
     664
     665  if (rolloverCaption)
     666    delete rolloverCaption;
     667
     668  if (alternateCaption)
     669    delete alternateCaption;
     670
     671  if (iconFit)
     672    delete iconFit;
     673}
    23674
    24675//------------------------------------------------------------------------
     
    26677//------------------------------------------------------------------------
    27678
    28 Annot::Annot(XRef *xrefA, Dict *acroForm, Dict *dict) {
    29   Object apObj, asObj, obj1, obj2;
    30   GBool regen, isTextField;
    31   double t;
    32 
    33   ok = gFalse;
     679Annot::Annot(XRef *xrefA, Dict *dict, Catalog* catalog) {
     680  hasRef = false;
     681  flags = flagUnknown;
     682  type = typeUnknown;
     683  initialize (xrefA, dict, catalog);
     684}
     685
     686Annot::Annot(XRef *xrefA, Dict *dict, Catalog* catalog, Object *obj) {
     687  if (obj->isRef()) {
     688    hasRef = gTrue;
     689    ref = obj->getRef();
     690  } else {
     691    hasRef = gFalse;
     692  }
     693  flags = flagUnknown;
     694  type = typeUnknown;
     695  initialize (xrefA, dict, catalog);
     696}
     697
     698void Annot::initialize(XRef *xrefA, Dict *dict, Catalog *catalog) {
     699  Object apObj, asObj, obj1, obj2, obj3;
     700
     701  appRef.num = 0;
     702  appRef.gen = 65535;
     703  ok = gTrue;
    34704  xref = xrefA;
    35705  appearBuf = NULL;
    36 
    37   if (dict->lookup("Rect", &obj1)->isArray() &&
    38       obj1.arrayGetLength() == 4) {
    39     //~ should check object types here
    40     obj1.arrayGet(0, &obj2);
    41     xMin = obj2.getNum();
     706  fontSize = 0;
     707
     708  //----- parse the rectangle
     709  rect = new PDFRectangle();
     710  if (dict->lookup("Rect", &obj1)->isArray() && obj1.arrayGetLength() == 4) {
     711    Object obj2;
     712    (obj1.arrayGet(0, &obj2)->isNum() ? rect->x1 = obj2.getNum() : rect->x1 = 0);
    42713    obj2.free();
    43     obj1.arrayGet(1, &obj2);
    44     yMin = obj2.getNum();
     714    (obj1.arrayGet(1, &obj2)->isNum() ? rect->y1 = obj2.getNum() : rect->y1 = 0);
    45715    obj2.free();
    46     obj1.arrayGet(2, &obj2);
    47     xMax = obj2.getNum();
     716    (obj1.arrayGet(2, &obj2)->isNum() ? rect->x2 = obj2.getNum() : rect->x2 = 1);
    48717    obj2.free();
    49     obj1.arrayGet(3, &obj2);
    50     yMax = obj2.getNum();
     718    (obj1.arrayGet(3, &obj2)->isNum() ? rect->y2 = obj2.getNum() : rect->y2 = 1);
    51719    obj2.free();
    52     if (xMin > xMax) {
    53       t = xMin; xMin = xMax; xMax = t;
    54     }
    55     if (yMin > yMax) {
    56       t = yMin; yMin = yMax; yMax = t;
    57     }
    58   } else {
    59     //~ this should return an error
    60     xMin = yMin = 0;
    61     xMax = yMax = 1;
    62   }
    63   obj1.free();
     720
     721    if (rect->x1 > rect->x2) {
     722      double t = rect->x1;
     723      rect->x1 = rect->x2;
     724      rect->x2 = t;
     725    }
     726
     727    if (rect->y1 > rect->y2) {
     728      double t = rect->y1;
     729      rect->y1 = rect->y2;
     730      rect->y2 = t;
     731    }
     732  } else {
     733    rect->x1 = rect->y1 = 0;
     734    rect->x2 = rect->y2 = 1;
     735    error(-1, "Bad bounding box for annotation");
     736    ok = gFalse;
     737  }
     738  obj1.free();
     739
     740  if (dict->lookup("Contents", &obj1)->isString()) {
     741    contents = obj1.getString()->copy();
     742  } else {
     743    contents = NULL;
     744  }
     745  obj1.free();
     746
     747  /* TODO: Page Object indirect reference (should be parsed ?) */
     748  pageDict = NULL;
     749  /*if (dict->lookup("P", &obj1)->isDict()) {
     750    pageDict = NULL;
     751  } else {
     752    pageDict = NULL;
     753  }
     754  obj1.free();
     755  */
     756
     757  if (dict->lookup("NM", &obj1)->isString()) {
     758    name = obj1.getString()->copy();
     759  } else {
     760    name = NULL;
     761  }
     762  obj1.free();
     763
     764  if (dict->lookup("M", &obj1)->isString()) {
     765    modified = obj1.getString()->copy();
     766  } else {
     767    modified = NULL;
     768  }
     769  obj1.free();
     770
     771  //----- get the flags
     772  if (dict->lookup("F", &obj1)->isInt()) {
     773    flags |= obj1.getInt();
     774  } else {
     775    flags = flagUnknown;
     776  }
     777  obj1.free();
     778
     779  if (dict->lookup("AP", &obj1)->isDict()) {
     780    Object obj2;
     781
     782    if (dict->lookup("AS", &obj2)->isName()) {
     783      Object obj3;
     784
     785      appearState = new GooString(obj2.getName());
     786      if (obj1.dictLookup("N", &obj3)->isDict()) {
     787        Object obj4;
     788
     789        if (obj3.dictLookupNF(appearState->getCString(), &obj4)->isRef()) {
     790          obj4.copy(&appearance);
     791        } else {
     792          obj4.free();
     793          if (obj3.dictLookupNF("Off", &obj4)->isRef()) {
     794            obj4.copy(&appearance);
     795          }
     796        }
     797        obj4.free();
     798      }
     799      obj3.free();
     800    } else {
     801      obj2.free();
     802
     803      appearState = NULL;
     804      if (obj1.dictLookupNF("N", &obj2)->isRef()) {
     805        obj2.copy(&appearance);
     806      }
     807    }
     808    obj2.free();
     809  } else {
     810    appearState = NULL;
     811  }
     812  obj1.free();
     813
     814  //----- parse the border style
     815  if (dict->lookup("BS", &obj1)->isDict()) {
     816    border = new AnnotBorderBS(obj1.getDict());
     817  } else {
     818    obj1.free();
     819
     820    if (dict->lookup("Border", &obj1)->isArray())
     821      border = new AnnotBorderArray(obj1.getArray());
     822    else
     823      // Adobe draws no border at all if the last element is of
     824      // the wrong type.
     825      border = NULL;
     826  }
     827  obj1.free();
     828
     829  if (dict->lookup("C", &obj1)->isArray()) {
     830    color = new AnnotColor(obj1.getArray());
     831  } else {
     832    color = NULL;
     833  }
     834  obj1.free();
     835
     836  if (dict->lookup("StructParent", &obj1)->isInt()) {
     837    treeKey = obj1.getInt();
     838  } else {
     839    treeKey = 0;
     840  }
     841  obj1.free();
     842
     843  /* TODO: optional content should be parsed */
     844  optionalContent = NULL;
     845 
     846  /*if (dict->lookup("OC", &obj1)->isDict()) {
     847    optionalContent = NULL;
     848  } else {
     849    optionalContent = NULL;
     850  }
     851  obj1.free();
     852  */
     853}
     854
     855double Annot::getXMin() {
     856  return rect->x1;
     857}
     858
     859double Annot::getYMin() {
     860  return rect->y1;
     861}
     862
     863void Annot::readArrayNum(Object *pdfArray, int key, double *value) {
     864  Object valueObject;
     865
     866  pdfArray->arrayGet(key, &valueObject);
     867  if (valueObject.isNum()) {
     868    *value = valueObject.getNum();
     869  } else {
     870    *value = 0;
     871    ok = gFalse;
     872  }
     873  valueObject.free();
     874}
     875
     876Annot::~Annot() {
     877  delete rect;
     878
     879  if (contents)
     880    delete contents;
     881
     882  if (pageDict)
     883    delete pageDict;
     884
     885  if (name)
     886    delete name;
     887
     888  if (modified)
     889    delete modified;
     890
     891  appearance.free();
     892
     893  if (appearState)
     894    delete appearState;
     895
     896  if (border)
     897    delete border;
     898
     899  if (color)
     900    delete color;
     901
     902  if (optionalContent)
     903    delete optionalContent;
     904}
     905
     906// Set the current fill or stroke color, based on <a> (which should
     907// have 1, 3, or 4 elements).  If <adjust> is +1, color is brightened;
     908// if <adjust> is -1, color is darkened; otherwise color is not
     909// modified.
     910void Annot::setColor(Array *a, GBool fill, int adjust) {
     911  Object obj1;
     912  double color[4];
     913  int nComps, i;
     914
     915  nComps = a->getLength();
     916  if (nComps > 4) {
     917    nComps = 4;
     918  }
     919  for (i = 0; i < nComps && i < 4; ++i) {
     920    if (a->get(i, &obj1)->isNum()) {
     921      color[i] = obj1.getNum();
     922    } else {
     923      color[i] = 0;
     924    }
     925    obj1.free();
     926  }
     927  if (nComps == 4) {
     928    adjust = -adjust;
     929  }
     930  if (adjust > 0) {
     931    for (i = 0; i < nComps; ++i) {
     932      color[i] = 0.5 * color[i] + 0.5;
     933    }
     934  } else if (adjust < 0) {
     935    for (i = 0; i < nComps; ++i) {
     936      color[i] = 0.5 * color[i];
     937    }
     938  }
     939  if (nComps == 4) {
     940    appearBuf->appendf("{0:.2f} {1:.2f} {2:.2f} {3:.2f} {4:c}\n",
     941        color[0], color[1], color[2], color[3],
     942        fill ? 'k' : 'K');
     943  } else if (nComps == 3) {
     944    appearBuf->appendf("{0:.2f} {1:.2f} {2:.2f} {3:s}\n",
     945        color[0], color[1], color[2],
     946        fill ? "rg" : "RG");
     947  } else {
     948    appearBuf->appendf("{0:.2f} {1:c}\n",
     949        color[0],
     950        fill ? 'g' : 'G');
     951  }
     952}
     953
     954// Draw an (approximate) circle of radius <r> centered at (<cx>, <cy>).
     955// If <fill> is true, the circle is filled; otherwise it is stroked.
     956void Annot::drawCircle(double cx, double cy, double r, GBool fill) {
     957  appearBuf->appendf("{0:.2f} {1:.2f} m\n",
     958      cx + r, cy);
     959  appearBuf->appendf("{0:.2f} {1:.2f} {2:.2f} {3:.2f} {4:.2f} {5:.2f} c\n",
     960      cx + r, cy + bezierCircle * r,
     961      cx + bezierCircle * r, cy + r,
     962      cx, cy + r);
     963  appearBuf->appendf("{0:.2f} {1:.2f} {2:.2f} {3:.2f} {4:.2f} {5:.2f} c\n",
     964      cx - bezierCircle * r, cy + r,
     965      cx - r, cy + bezierCircle * r,
     966      cx - r, cy);
     967  appearBuf->appendf("{0:.2f} {1:.2f} {2:.2f} {3:.2f} {4:.2f} {5:.2f} c\n",
     968      cx - r, cy - bezierCircle * r,
     969      cx - bezierCircle * r, cy - r,
     970      cx, cy - r);
     971  appearBuf->appendf("{0:.2f} {1:.2f} {2:.2f} {3:.2f} {4:.2f} {5:.2f} c\n",
     972      cx + bezierCircle * r, cy - r,
     973      cx + r, cy - bezierCircle * r,
     974      cx + r, cy);
     975  appearBuf->append(fill ? "f\n" : "s\n");
     976}
     977
     978// Draw the top-left half of an (approximate) circle of radius <r>
     979// centered at (<cx>, <cy>).
     980void Annot::drawCircleTopLeft(double cx, double cy, double r) {
     981  double r2;
     982
     983  r2 = r / sqrt(2.0);
     984  appearBuf->appendf("{0:.2f} {1:.2f} m\n",
     985      cx + r2, cy + r2);
     986  appearBuf->appendf("{0:.2f} {1:.2f} {2:.2f} {3:.2f} {4:.2f} {5:.2f} c\n",
     987      cx + (1 - bezierCircle) * r2,
     988      cy + (1 + bezierCircle) * r2,
     989      cx - (1 - bezierCircle) * r2,
     990      cy + (1 + bezierCircle) * r2,
     991      cx - r2,
     992      cy + r2);
     993  appearBuf->appendf("{0:.2f} {1:.2f} {2:.2f} {3:.2f} {4:.2f} {5:.2f} c\n",
     994      cx - (1 + bezierCircle) * r2,
     995      cy + (1 - bezierCircle) * r2,
     996      cx - (1 + bezierCircle) * r2,
     997      cy - (1 - bezierCircle) * r2,
     998      cx - r2,
     999      cy - r2);
     1000  appearBuf->append("S\n");
     1001}
     1002
     1003// Draw the bottom-right half of an (approximate) circle of radius <r>
     1004// centered at (<cx>, <cy>).
     1005void Annot::drawCircleBottomRight(double cx, double cy, double r) {
     1006  double r2;
     1007
     1008  r2 = r / sqrt(2.0);
     1009  appearBuf->appendf("{0:.2f} {1:.2f} m\n",
     1010      cx - r2, cy - r2);
     1011  appearBuf->appendf("{0:.2f} {1:.2f} {2:.2f} {3:.2f} {4:.2f} {5:.2f} c\n",
     1012      cx - (1 - bezierCircle) * r2,
     1013      cy - (1 + bezierCircle) * r2,
     1014      cx + (1 - bezierCircle) * r2,
     1015      cy - (1 + bezierCircle) * r2,
     1016      cx + r2,
     1017      cy - r2);
     1018  appearBuf->appendf("{0:.2f} {1:.2f} {2:.2f} {3:.2f} {4:.2f} {5:.2f} c\n",
     1019      cx + (1 + bezierCircle) * r2,
     1020      cy - (1 - bezierCircle) * r2,
     1021      cx + (1 + bezierCircle) * r2,
     1022      cy + (1 - bezierCircle) * r2,
     1023      cx + r2,
     1024      cy + r2);
     1025  appearBuf->append("S\n");
     1026}
     1027
     1028void Annot::draw(Gfx *gfx, GBool printing) {
     1029  Object obj;
     1030
     1031  // check the flags
     1032  if ((flags & annotFlagHidden) ||
     1033      (printing && !(flags & annotFlagPrint)) ||
     1034      (!printing && (flags & annotFlagNoView))) {
     1035    return;
     1036  }
     1037
     1038  // draw the appearance stream
     1039  appearance.fetch(xref, &obj);
     1040  gfx->drawAnnot(&obj, (type == typeLink) ? border : (AnnotBorder *)NULL, color,
     1041      rect->x1, rect->y1, rect->x2, rect->y2);
     1042  obj.free();
     1043}
     1044
     1045//------------------------------------------------------------------------
     1046// AnnotPopup
     1047//------------------------------------------------------------------------
     1048
     1049AnnotPopup::AnnotPopup(XRef *xrefA, Dict *dict, Catalog *catalog, Object *obj) :
     1050    Annot(xrefA, dict, catalog, obj) {
     1051  type = typePopup;
     1052  initialize(xrefA, dict, catalog);
     1053}
     1054
     1055AnnotPopup::~AnnotPopup() {
     1056  /*
     1057  if (parent)
     1058    delete parent;
     1059  */
     1060}
     1061
     1062void AnnotPopup::initialize(XRef *xrefA, Dict *dict, Catalog *catalog) {
     1063  Object obj1;
     1064  /*
     1065  if (dict->lookup("Parent", &obj1)->isDict()) {
     1066    parent = NULL;
     1067  } else {
     1068    parent = NULL;
     1069  }
     1070  obj1.free();
     1071  */
     1072  if (dict->lookup("Open", &obj1)->isBool()) {
     1073    open = obj1.getBool();
     1074  } else {
     1075    open = gFalse;
     1076  }
     1077  obj1.free();
     1078}
     1079
     1080//------------------------------------------------------------------------
     1081// AnnotMarkup
     1082//------------------------------------------------------------------------
     1083 
     1084AnnotMarkup::AnnotMarkup(XRef *xrefA, Dict *dict, Catalog *catalog, Object *obj) :
     1085    Annot(xrefA, dict, catalog, obj) {
     1086  initialize(xrefA, dict, catalog, obj);
     1087}
     1088
     1089AnnotMarkup::~AnnotMarkup() {
     1090  if (label)
     1091    delete label;
     1092
     1093  if (popup)
     1094    delete popup;
     1095
     1096  if (date)
     1097    delete date;
     1098
     1099  if (inReplyTo)
     1100    delete inReplyTo;
     1101
     1102  if (subject)
     1103    delete subject;
     1104}
     1105
     1106void AnnotMarkup::initialize(XRef *xrefA, Dict *dict, Catalog *catalog, Object *obj) {
     1107  Object obj1;
     1108
     1109  if (dict->lookup("T", &obj1)->isString()) {
     1110    label = obj1.getString()->copy();
     1111  } else {
     1112    label = NULL;
     1113  }
     1114  obj1.free();
     1115
     1116  if (dict->lookup("Popup", &obj1)->isDict()) {
     1117    popup = new AnnotPopup(xrefA, obj1.getDict(), catalog, obj);
     1118  } else {
     1119    popup = NULL;
     1120  }
     1121  obj1.free();
     1122
     1123  if (dict->lookup("CA", &obj1)->isNum()) {
     1124    opacity = obj1.getNum();
     1125  } else {
     1126    opacity = 1.0;
     1127  }
     1128  obj1.free();
     1129
     1130  if (dict->lookup("CreationDate", &obj1)->isString()) {
     1131    date = obj1.getString()->copy();
     1132  } else {
     1133    date = NULL;
     1134  }
     1135  obj1.free();
     1136
     1137  if (dict->lookup("IRT", &obj1)->isDict()) {
     1138    inReplyTo = obj1.getDict();
     1139  } else {
     1140    inReplyTo = NULL;
     1141  }
     1142  obj1.free();
     1143
     1144  if (dict->lookup("Subj", &obj1)->isString()) {
     1145    subject = obj1.getString()->copy();
     1146  } else {
     1147    subject = NULL;
     1148  }
     1149  obj1.free();
     1150
     1151  if (dict->lookup("RT", &obj1)->isName()) {
     1152    GooString *replyName = new GooString(obj1.getName());
     1153
     1154    if (!replyName->cmp("R")) {
     1155      replyTo = replyTypeR;
     1156    } else if (!replyName->cmp("Group")) {
     1157      replyTo = replyTypeGroup;
     1158    } else {
     1159      replyTo = replyTypeR;
     1160    }
     1161    delete replyName;
     1162  } else {
     1163    replyTo = replyTypeR;
     1164  }
     1165  obj1.free();
     1166
     1167  if (dict->lookup("ExData", &obj1)->isDict()) {
     1168    exData = parseAnnotExternalData(obj1.getDict());
     1169  } else {
     1170    exData = annotExternalDataMarkupUnknown;
     1171  }
     1172  obj1.free();
     1173}
     1174
     1175//------------------------------------------------------------------------
     1176// AnnotText
     1177//------------------------------------------------------------------------
     1178
     1179AnnotText::AnnotText(XRef *xrefA, Dict *dict, Catalog *catalog, Object *obj) :
     1180    AnnotMarkup(xrefA, dict, catalog, obj) {
     1181
     1182  type = typeText;
     1183  flags |= flagNoZoom | flagNoRotate;
     1184  initialize (xrefA, catalog, dict);
     1185}
     1186
     1187void AnnotText::setModified(GooString *date) {
     1188  if (date) {
     1189    delete modified;
     1190    modified = new GooString(date);
     1191  }
     1192}
     1193
     1194void AnnotText::initialize(XRef *xrefA, Catalog *catalog, Dict *dict) {
     1195  Object obj1;
     1196
     1197  if (dict->lookup("Open", &obj1)->isBool())
     1198    open = obj1.getBool();
     1199  else
     1200    open = gFalse;
     1201  obj1.free();
     1202
     1203  if (dict->lookup("Name", &obj1)->isName()) {
     1204    GooString *iconName = new GooString(obj1.getName());
     1205
     1206    if (!iconName->cmp("Comment")) {
     1207      icon = iconComment;
     1208    } else if (!iconName->cmp("Key")) {
     1209      icon = iconKey;
     1210    } else if (!iconName->cmp("Help")) {
     1211      icon = iconHelp;
     1212    } else if (!iconName->cmp("NewParagraph")) {
     1213      icon = iconNewParagraph;
     1214    } else if (!iconName->cmp("Paragraph")) {
     1215      icon = iconParagraph;
     1216    } else if (!iconName->cmp("Insert")) {
     1217      icon = iconInsert;
     1218    } else {
     1219      icon = iconNote;
     1220    }
     1221    delete iconName;
     1222  } else {
     1223    icon = iconNote;
     1224  }
     1225  obj1.free();
     1226
     1227  if (dict->lookup("StateModel", &obj1)->isString()) {
     1228    Object obj2;
     1229    GooString *modelName = obj1.getString();
     1230
     1231    if (dict->lookup("State", &obj2)->isString()) {
     1232      GooString *stateName = obj2.getString();
     1233
     1234      if (!stateName->cmp("Marked")) {
     1235        state = stateMarked;
     1236      } else if (!stateName->cmp("Unmarked")) {
     1237        state = stateUnmarked;
     1238      } else if (!stateName->cmp("Accepted")) {
     1239        state = stateAccepted;
     1240      } else if (!stateName->cmp("Rejected")) {
     1241        state = stateRejected;
     1242      } else if (!stateName->cmp("Cancelled")) {
     1243        state = stateCancelled;
     1244      } else if (!stateName->cmp("Completed")) {
     1245        state = stateCompleted;
     1246      } else if (!stateName->cmp("None")) {
     1247        state = stateNone;
     1248      } else {
     1249        state = stateUnknown;
     1250      }
     1251
     1252    } else {
     1253      state = stateUnknown;
     1254    }
     1255    obj2.free();
     1256
     1257    if (!modelName->cmp("Marked")) {
     1258      switch (state) {
     1259        case stateUnknown:
     1260          state = stateMarked;
     1261          break;
     1262        case stateAccepted:
     1263        case stateRejected:
     1264        case stateCancelled:
     1265        case stateCompleted:
     1266        case stateNone:
     1267          state = stateUnknown;
     1268          break;
     1269        default:
     1270          break;
     1271      }
     1272    } else if (!modelName->cmp("Review")) {
     1273      switch (state) {
     1274        case stateUnknown:
     1275          state = stateNone;
     1276          break;
     1277        case stateMarked:
     1278        case stateUnmarked:
     1279          state = stateUnknown;
     1280          break;
     1281        default:
     1282          break;
     1283      }
     1284    } else {
     1285      state = stateUnknown;
     1286    }
     1287
     1288  } else {
     1289    state = stateUnknown;
     1290  }
     1291  obj1.free();
     1292}
     1293
     1294//------------------------------------------------------------------------
     1295// AnnotLink
     1296//------------------------------------------------------------------------
     1297
     1298AnnotLink::AnnotLink(XRef *xrefA, Dict *dict, Catalog *catalog, Object *obj) :
     1299    Annot(xrefA, dict, catalog, obj) {
     1300
     1301  type = typeLink;
     1302  initialize (xrefA, catalog, dict);
     1303}
     1304
     1305AnnotLink::~AnnotLink() {
     1306  /*
     1307  if (actionDict)
     1308    delete actionDict;
     1309
     1310  if (uriAction)
     1311    delete uriAction;
     1312  */
     1313  if (quadrilaterals)
     1314    delete quadrilaterals;
     1315}
     1316
     1317void AnnotLink::initialize(XRef *xrefA, Catalog *catalog, Dict *dict) {
     1318  Object obj1;
     1319  /*
     1320  if (dict->lookup("A", &obj1)->isDict()) {
     1321    actionDict = NULL;
     1322  } else {
     1323    actionDict = NULL;
     1324  }
     1325  obj1.free();
     1326  */
     1327  if (dict->lookup("H", &obj1)->isName()) {
     1328    GooString *effect = new GooString(obj1.getName());
     1329
     1330    if (!effect->cmp("N")) {
     1331      linkEffect = effectNone;
     1332    } else if (!effect->cmp("I")) {
     1333      linkEffect = effectInvert;
     1334    } else if (!effect->cmp("O")) {
     1335      linkEffect = effectOutline;
     1336    } else if (!effect->cmp("P")) {
     1337      linkEffect = effectPush;
     1338    } else {
     1339      linkEffect = effectInvert;
     1340    }
     1341    delete effect;
     1342  } else {
     1343    linkEffect = effectInvert;
     1344  }
     1345  obj1.free();
     1346  /*
     1347  if (dict->lookup("PA", &obj1)->isDict()) {
     1348    uriAction = NULL;
     1349  } else {
     1350    uriAction = NULL;
     1351  }
     1352  obj1.free();
     1353  */
     1354  if (dict->lookup("QuadPoints", &obj1)->isArray()) {
     1355    quadrilaterals = new AnnotQuadrilaterals(obj1.getArray(), rect);
     1356  } else {
     1357    quadrilaterals = NULL;
     1358  }
     1359  obj1.free();
     1360}
     1361
     1362void AnnotLink::draw(Gfx *gfx, GBool printing) {
     1363  Object obj;
     1364
     1365  // check the flags
     1366  if ((flags & annotFlagHidden) ||
     1367      (printing && !(flags & annotFlagPrint)) ||
     1368      (!printing && (flags & annotFlagNoView))) {
     1369    return;
     1370  }
     1371
     1372  // draw the appearance stream
     1373  appearance.fetch(xref, &obj);
     1374  gfx->drawAnnot(&obj, border, color,
     1375                 rect->x1, rect->y1, rect->x2, rect->y2);
     1376  obj.free();
     1377}
     1378
     1379//------------------------------------------------------------------------
     1380// AnnotFreeText
     1381//------------------------------------------------------------------------
     1382
     1383AnnotFreeText::AnnotFreeText(XRef *xrefA, Dict *dict, Catalog *catalog, Object *obj) :
     1384    AnnotMarkup(xrefA, dict, catalog, obj) {
     1385  type = typeFreeText;
     1386  initialize(xrefA, catalog, dict);
     1387}
     1388
     1389AnnotFreeText::~AnnotFreeText() {
     1390  delete appearanceString;
     1391
     1392  if (styleString)
     1393    delete styleString;
     1394
     1395  if (calloutLine)
     1396    delete calloutLine;
     1397
     1398  if (borderEffect)
     1399    delete borderEffect;
     1400
     1401  if (rectangle)
     1402    delete rectangle;
     1403}
     1404
     1405void AnnotFreeText::initialize(XRef *xrefA, Catalog *catalog, Dict *dict) {
     1406  Object obj1;
     1407
     1408  if (dict->lookup("DA", &obj1)->isString()) {
     1409    appearanceString = obj1.getString()->copy();
     1410  } else {
     1411    appearanceString = new GooString();
     1412    error(-1, "Bad appearance for annotation");
     1413    ok = gFalse;
     1414  }
     1415  obj1.free();
     1416
     1417  if (dict->lookup("Q", &obj1)->isInt()) {
     1418    quadding = (AnnotFreeTextQuadding) obj1.getInt();
     1419  } else {
     1420    quadding = quaddingLeftJustified;
     1421  }
     1422  obj1.free();
     1423
     1424  if (dict->lookup("DS", &obj1)->isString()) {
     1425    styleString = obj1.getString()->copy();
     1426  } else {
     1427    styleString = NULL;
     1428  }
     1429  obj1.free();
     1430
     1431  if (dict->lookup("CL", &obj1)->isArray() && obj1.arrayGetLength() >= 4) {
     1432    double x1, y1, x2, y2;
     1433    Object obj2;
     1434
     1435    (obj1.arrayGet(0, &obj2)->isNum() ? x1 = obj2.getNum() : x1 = 0);
     1436    obj2.free();
     1437    (obj1.arrayGet(1, &obj2)->isNum() ? y1 = obj2.getNum() : y1 = 0);
     1438    obj2.free();
     1439    (obj1.arrayGet(2, &obj2)->isNum() ? x2 = obj2.getNum() : x2 = 0);
     1440    obj2.free();
     1441    (obj1.arrayGet(3, &obj2)->isNum() ? y2 = obj2.getNum() : y2 = 0);
     1442    obj2.free();
     1443
     1444    if (obj1.arrayGetLength() == 6) {
     1445      double x3, y3;
     1446      (obj1.arrayGet(4, &obj2)->isNum() ? x3 = obj2.getNum() : x3 = 0);
     1447      obj2.free();
     1448      (obj1.arrayGet(5, &obj2)->isNum() ? y3 = obj2.getNum() : y3 = 0);
     1449      obj2.free();
     1450      calloutLine = new AnnotCalloutMultiLine(x1, y1, x2, y2, x3, y3);
     1451    } else {
     1452      calloutLine = new AnnotCalloutLine(x1, y1, x2, y2);
     1453    }
     1454  } else {
     1455    calloutLine = NULL;
     1456  }
     1457  obj1.free();
     1458
     1459  if (dict->lookup("IT", &obj1)->isName()) {
     1460    GooString *intentName = new GooString(obj1.getName());
     1461
     1462    if (!intentName->cmp("FreeText")) {
     1463      intent = intentFreeText;
     1464    } else if (!intentName->cmp("FreeTextCallout")) {
     1465      intent = intentFreeTextCallout;
     1466    } else if (!intentName->cmp("FreeTextTypeWriter")) {
     1467      intent = intentFreeTextTypeWriter;
     1468    } else {
     1469      intent = intentFreeText;
     1470    }
     1471    delete intentName;
     1472  } else {
     1473    intent = intentFreeText;
     1474  }
     1475  obj1.free();
     1476
     1477  if (dict->lookup("BE", &obj1)->isDict()) {
     1478    borderEffect = new AnnotBorderEffect(obj1.getDict());
     1479  } else {
     1480    borderEffect = NULL;
     1481  }
     1482  obj1.free();
     1483
     1484  if (dict->lookup("RD", &obj1)->isArray() && obj1.arrayGetLength() == 4) {
     1485    Object obj2;
     1486    rectangle = new PDFRectangle();
     1487
     1488    (obj1.arrayGet(0, &obj2)->isNum() ? rectangle->x1 = obj2.getNum() :
     1489      rectangle->x1 = 0);
     1490    obj2.free();
     1491    (obj1.arrayGet(1, &obj2)->isNum() ? rectangle->y1 = obj2.getNum() :
     1492      rectangle->y1 = 0);
     1493    obj2.free();
     1494    (obj1.arrayGet(2, &obj2)->isNum() ? rectangle->x2 = obj2.getNum() :
     1495      rectangle->x2 = 1);
     1496    obj2.free();
     1497    (obj1.arrayGet(3, &obj2)->isNum() ? rectangle->y2 = obj2.getNum() :
     1498      rectangle->y2 = 1);
     1499    obj2.free();
     1500
     1501    if (rectangle->x1 > rectangle->x2) {
     1502      double t = rectangle->x1;
     1503      rectangle->x1 = rectangle->x2;
     1504      rectangle->x2 = t;
     1505    }
     1506    if (rectangle->y1 > rectangle->y2) {
     1507      double t = rectangle->y1;
     1508      rectangle->y1 = rectangle->y2;
     1509      rectangle->y2 = t;
     1510    }
     1511
     1512    if ((rectangle->x1 + rectangle->x2) > (rect->x2 - rect->x1))
     1513      rectangle->x1 = rectangle->x2 = 0;
     1514
     1515    if ((rectangle->y1 + rectangle->y2) > (rect->y2 - rect->y1))
     1516      rectangle->y1 = rectangle->y2 = 0;
     1517  } else {
     1518    rectangle = NULL;
     1519  }
     1520  obj1.free();
     1521
     1522  if (dict->lookup("LE", &obj1)->isName()) {
     1523    GooString *styleName = new GooString(obj1.getName());
     1524    endStyle = parseAnnotLineEndingStyle(styleName);
     1525    delete styleName;
     1526  } else {
     1527    endStyle = annotLineEndingNone;
     1528  }
     1529  obj1.free();
     1530}
     1531
     1532//------------------------------------------------------------------------
     1533// AnnotLine
     1534//------------------------------------------------------------------------
     1535
     1536AnnotLine::AnnotLine(XRef *xrefA, Dict *dict, Catalog *catalog, Object *obj) :
     1537    AnnotMarkup(xrefA, dict, catalog, obj) {
     1538  type = typeLine;
     1539  initialize(xrefA, catalog, dict);
     1540}
     1541
     1542AnnotLine::~AnnotLine() {
     1543  if (interiorColor)
     1544    delete interiorColor;
     1545
     1546  if (measure)
     1547    delete measure;
     1548}
     1549
     1550void AnnotLine::initialize(XRef *xrefA, Catalog *catalog, Dict *dict) {
     1551  Object obj1;
     1552
     1553  if (dict->lookup("L", &obj1)->isArray() && obj1.arrayGetLength() == 4) {
     1554    Object obj2;
     1555
     1556    (obj1.arrayGet(0, &obj2)->isNum() ? x1 = obj2.getNum() : x1 = 0);
     1557    obj2.free();
     1558    (obj1.arrayGet(1, &obj2)->isNum() ? y1 = obj2.getNum() : y1 = 0);
     1559    obj2.free();
     1560    (obj1.arrayGet(2, &obj2)->isNum() ? x2 = obj2.getNum() : x2 = 0);
     1561    obj2.free();
     1562    (obj1.arrayGet(3, &obj2)->isNum() ? y2 = obj2.getNum() : y2 = 0);
     1563    obj2.free();
     1564
     1565  } else {
     1566    x1 = y1 = x2 = y2 = 0;
     1567  }
     1568  obj1.free();
     1569
     1570  if (dict->lookup("LE", &obj1)->isArray() && obj1.arrayGetLength() == 2) {
     1571    Object obj2;
     1572
     1573    if(obj1.arrayGet(0, &obj2)->isString())
     1574      startStyle = parseAnnotLineEndingStyle(obj2.getString());
     1575    else
     1576      startStyle = annotLineEndingNone;
     1577    obj2.free();
     1578
     1579    if(obj1.arrayGet(1, &obj2)->isString())
     1580      endStyle = parseAnnotLineEndingStyle(obj2.getString());
     1581    else
     1582      endStyle = annotLineEndingNone;
     1583    obj2.free();
     1584
     1585  } else {
     1586    startStyle = endStyle = annotLineEndingNone;
     1587  }
     1588  obj1.free();
     1589
     1590  if (dict->lookup("IC", &obj1)->isArray()) {
     1591    interiorColor = new AnnotColor(obj1.getArray());
     1592  } else {
     1593    interiorColor = NULL;
     1594  }
     1595  obj1.free();
     1596
     1597  if (dict->lookup("LL", &obj1)->isNum()) {
     1598    leaderLineLength = obj1.getNum();
     1599  } else {
     1600    leaderLineLength = 0;
     1601  }
     1602  obj1.free();
     1603
     1604  if (dict->lookup("LLE", &obj1)->isNum()) {
     1605    leaderLineExtension = obj1.getNum();
     1606
     1607    if (leaderLineExtension < 0)
     1608      leaderLineExtension = 0;
     1609  } else {
     1610    leaderLineExtension = 0;
     1611  }
     1612  obj1.free();
     1613
     1614  if (dict->lookup("Cap", &obj1)->isBool()) {
     1615    caption = obj1.getBool();
     1616  } else {
     1617    caption = gFalse;
     1618  }
     1619  obj1.free();
     1620
     1621  if (dict->lookup("IT", &obj1)->isName()) {
     1622    GooString *intentName = new GooString(obj1.getName());
     1623
     1624    if(!intentName->cmp("LineArrow")) {
     1625      intent = intentLineArrow;
     1626    } else if(!intentName->cmp("LineDimension")) {
     1627      intent = intentLineDimension;
     1628    } else {
     1629      intent = intentLineArrow;
     1630    }
     1631    delete intentName;
     1632  } else {
     1633    intent = intentLineArrow;
     1634  }
     1635  obj1.free();
     1636
     1637  if (dict->lookup("LLO", &obj1)->isNum()) {
     1638    leaderLineOffset = obj1.getNum();
     1639
     1640    if (leaderLineOffset < 0)
     1641      leaderLineOffset = 0;
     1642  } else {
     1643    leaderLineOffset = 0;
     1644  }
     1645  obj1.free();
     1646
     1647  if (dict->lookup("CP", &obj1)->isName()) {
     1648    GooString *captionName = new GooString(obj1.getName());
     1649
     1650    if(!captionName->cmp("Inline")) {
     1651      captionPos = captionPosInline;
     1652    } else if(!captionName->cmp("Top")) {
     1653      captionPos = captionPosTop;
     1654    } else {
     1655      captionPos = captionPosInline;
     1656    }
     1657    delete captionName;
     1658  } else {
     1659    captionPos = captionPosInline;
     1660  }
     1661  obj1.free();
     1662
     1663  if (dict->lookup("Measure", &obj1)->isDict()) {
     1664    measure = NULL;
     1665  } else {
     1666    measure = NULL;
     1667  }
     1668  obj1.free();
     1669
     1670  if ((dict->lookup("CO", &obj1)->isArray()) && (obj1.arrayGetLength() == 2)) {
     1671    Object obj2;
     1672
     1673    (obj1.arrayGet(0, &obj2)->isNum() ? captionTextHorizontal = obj2.getNum() :
     1674      captionTextHorizontal = 0);
     1675    obj2.free();
     1676    (obj1.arrayGet(1, &obj2)->isNum() ? captionTextVertical = obj2.getNum() :
     1677      captionTextVertical = 0);
     1678    obj2.free();
     1679  } else {
     1680    captionTextHorizontal = captionTextVertical = 0;
     1681  }
     1682  obj1.free();
     1683}
     1684
     1685//------------------------------------------------------------------------
     1686// AnnotTextMarkup
     1687//------------------------------------------------------------------------
     1688
     1689void AnnotTextMarkup::initialize(XRef *xrefA, Catalog *catalog, Dict *dict) {
     1690  Object obj1;
     1691
     1692  if(dict->lookup("QuadPoints", &obj1)->isArray()) {
     1693    quadrilaterals = new AnnotQuadrilaterals(obj1.getArray(), rect);
     1694  } else {
     1695    quadrilaterals = NULL;
     1696  }
     1697  obj1.free();
     1698}
     1699
     1700AnnotTextMarkup::~AnnotTextMarkup() {
     1701  if(quadrilaterals) {
     1702    delete quadrilaterals;
     1703  }
     1704}
     1705
     1706//------------------------------------------------------------------------
     1707// AnnotWidget
     1708//------------------------------------------------------------------------
     1709
     1710AnnotWidget::AnnotWidget(XRef *xrefA, Dict *dict, Catalog *catalog, Object *obj) :
     1711    Annot(xrefA, dict, catalog, obj) {
     1712  type = typeWidget;
     1713  initialize(xrefA, catalog, dict);
     1714}
     1715
     1716AnnotWidget::~AnnotWidget() {
     1717  if (appearCharacs)
     1718    delete appearCharacs;
     1719 
     1720  if (action)
     1721    delete action;
     1722   
     1723  if (additionActions)
     1724    delete additionActions;
     1725   
     1726  if (parent)
     1727    delete parent;
     1728}
     1729
     1730void AnnotWidget::initialize(XRef *xrefA, Catalog *catalog, Dict *dict) {
     1731  Object obj1;
     1732
     1733  form = catalog->getForm ();
     1734  widget = form->findWidgetByRef (ref);
    641735
    651736  // check if field apperances need to be regenerated
     1737  // Only text or choice fields needs to have appearance regenerated
     1738  // see section 8.6.2 "Variable Text" of PDFReference
    661739  regen = gFalse;
    67   if (acroForm) {
    68     acroForm->lookup("NeedAppearances", &obj1);
    69     if (obj1.isBool() && obj1.getBool()) {
    70       regen = gTrue;
     1740  if (widget != NULL && (widget->getType () == formText || widget->getType () == formChoice)) {
     1741    regen = form->getNeedAppearances ();
     1742  }
     1743
     1744  // If field doesn't have an AP we'll have to generate it
     1745  if (appearance.isNone () || appearance.isNull ())
     1746    regen = gTrue;
     1747
     1748  if(dict->lookup("H", &obj1)->isName()) {
     1749    GooString *modeName = new GooString(obj1.getName());
     1750
     1751    if(!modeName->cmp("N")) {
     1752      mode = highlightModeNone;
     1753    } else if(!modeName->cmp("O")) {
     1754      mode = highlightModeOutline;
     1755    } else if(!modeName->cmp("P") || !modeName->cmp("T")) {
     1756      mode = highlightModePush;
     1757    } else {
     1758      mode = highlightModeInvert;
     1759    }
     1760    delete modeName;
     1761  } else {
     1762    mode = highlightModeInvert;
     1763  }
     1764  obj1.free();
     1765
     1766  if(dict->lookup("MK", &obj1)->isDict()) {
     1767    appearCharacs = new AnnotAppearanceCharacs(obj1.getDict());
     1768  } else {
     1769    appearCharacs = NULL;
     1770  }
     1771  obj1.free();
     1772
     1773  if(dict->lookup("A", &obj1)->isDict()) {
     1774    action = NULL;
     1775  } else {
     1776    action = NULL;
     1777  }
     1778  obj1.free();
     1779
     1780  if(dict->lookup("AA", &obj1)->isDict()) {
     1781    additionActions = NULL;
     1782  } else {
     1783    additionActions = NULL;
     1784  }
     1785  obj1.free();
     1786
     1787  if(dict->lookup("Parent", &obj1)->isDict()) {
     1788    parent = NULL;
     1789  } else {
     1790    parent = NULL;
     1791  }
     1792  obj1.free();
     1793}
     1794
     1795// Grand unified handler for preparing text strings to be drawn into form
     1796// fields.  Takes as input a text string (in PDFDocEncoding or UTF-16).
     1797// Converts some or all of this string to the appropriate encoding for the
     1798// specified font, and computes the width of the text.  Can optionally stop
     1799// converting when a specified width has been reached, to perform line-breaking
     1800// for multi-line fields.
     1801//
     1802// Parameters:
     1803//   text: input text string to convert
     1804//   outBuf: buffer for writing re-encoded string
     1805//   i: index at which to start converting; will be updated to point just after
     1806//      last character processed
     1807//   font: the font which will be used for display
     1808//   width: computed width (unscaled by font size) will be stored here
     1809//   widthLimit: if non-zero, stop converting to keep width under this value
     1810//      (should be scaled down by font size)
     1811//   charCount: count of number of characters will be stored here
     1812//   noReencode: if set, do not try to translate the character encoding
     1813//      (useful for Zapf Dingbats or other unusual encodings)
     1814//      can only be used with simple fonts, not CID-keyed fonts
     1815//
     1816// TODO: Handle surrogate pairs in UTF-16.
     1817//       Should be able to generate output for any CID-keyed font.
     1818//       Doesn't handle vertical fonts--should it?
     1819void AnnotWidget::layoutText(GooString *text, GooString *outBuf, int *i,
     1820                             GfxFont *font, double *width, double widthLimit,
     1821                             int *charCount, GBool noReencode)
     1822{
     1823  CharCode c;
     1824  Unicode uChar, *uAux;
     1825  double w = 0.0;
     1826  int uLen, n;
     1827  double dx, dy, ox, oy;
     1828  GBool unicode = text->hasUnicodeMarker();
     1829  CharCodeToUnicode *ccToUnicode = font->getToUnicode();
     1830  GBool spacePrev;              // previous character was a space
     1831
     1832  // State for backtracking when more text has been processed than fits within
     1833  // widthLimit.  We track for both input (text) and output (outBuf) the offset
     1834  // to the first character to discard.
     1835  //
     1836  // We keep track of several points:
     1837  //   1 - end of previous completed word which fits
     1838  //   2 - previous character which fit
     1839  int last_i1, last_i2, last_o1, last_o2;
     1840
     1841  if (unicode && text->getLength() % 2 != 0) {
     1842    error(-1, "AnnotWidget::layoutText, bad unicode string");
     1843    return;
     1844  }
     1845
     1846  // skip Unicode marker on string if needed
     1847  if (unicode && *i == 0)
     1848    *i = 2;
     1849
     1850  // Start decoding and copying characters, until either:
     1851  //   we reach the end of the string
     1852  //   we reach the maximum width
     1853  //   we reach a newline character
     1854  // As we copy characters, keep track of the last full word to fit, so that we
     1855  // can backtrack if we exceed the maximum width.
     1856  last_i1 = last_i2 = *i;
     1857  last_o1 = last_o2 = 0;
     1858  spacePrev = gFalse;
     1859  outBuf->clear();
     1860
     1861  while (*i < text->getLength()) {
     1862    last_i2 = *i;
     1863    last_o2 = outBuf->getLength();
     1864
     1865    if (unicode) {
     1866      uChar = (unsigned char)(text->getChar(*i)) << 8;
     1867      uChar += (unsigned char)(text->getChar(*i + 1));
     1868      *i += 2;
     1869    } else {
     1870      if (noReencode)
     1871        uChar = text->getChar(*i) & 0xff;
     1872    &nbs