]> www.fi.muni.cz Git - evince.git/commitdiff
Imported Xpdf 3.00 and fixed build.
authorMartin Kretzschmar <mkretzschmar@src.gnome.org>
Mon, 17 May 2004 19:37:57 +0000 (19:37 +0000)
committerMartin Kretzschmar <mkretzschmar@src.gnome.org>
Mon, 17 May 2004 19:37:57 +0000 (19:37 +0000)
* ANNOUNCE:
* CHANGES:
* Makefile.am:
* README:
* aconf-win32.h:
* configure.in:
* dj_make.bat:
* doc/pdffonts.1:
* doc/pdffonts.cat:
* doc/pdffonts.hlp:
* doc/pdfimages.1:
* doc/pdfimages.cat:
* doc/pdfimages.hlp:
* doc/pdfinfo.1:
* doc/pdfinfo.cat:
* doc/pdfinfo.hlp:
* doc/pdftopbm.1:
* doc/pdftopbm.cat:
* doc/pdftopbm.hlp:
* doc/pdftops.1:
* doc/pdftops.cat:
* doc/pdftops.hlp:
* doc/pdftotext.1:
* doc/pdftotext.cat:
* doc/pdftotext.hlp:
* doc/xpdf.1:
* doc/xpdf.cat:
* doc/xpdf.hlp:
* doc/xpdfrc.5:
* doc/xpdfrc.cat:
* doc/xpdfrc.hlp:
* fofi/Makefile.in:
* goo/GHash.cc:
* goo/GHash.h:
* ms_make.bat:
* splash/Makefile.in:
* xpdf/DisplayFontTable.h:
* xpdf/ErrorCodes.h:
* xpdf/FTFont.cc:
* xpdf/FTFont.h:
* xpdf/FontFile.cc:
* xpdf/FontFile.h:
* xpdf/Function.h:
* xpdf/GPOutputDev.cc:
* xpdf/Gfx.cc:
* xpdf/Gfx.h:
* xpdf/GfxFont.cc:
* xpdf/GfxFont.h:
* xpdf/GfxState.cc:
* xpdf/GfxState.h:
* xpdf/GlobalParams.cc:
* xpdf/GlobalParams.h:
* xpdf/Makefile.am:
* xpdf/Object.cc:
* xpdf/Object.h:
* xpdf/Outline.cc:
* xpdf/OutputDev.cc:
* xpdf/OutputDev.h:
* xpdf/PBMOutputDev.cc:
* xpdf/PBMOutputDev.h:
* xpdf/PDFDoc.cc:
* xpdf/PDFDoc.h:
* xpdf/PSOutputDev.cc:
* xpdf/PSOutputDev.h:
* xpdf/Page.cc:
* xpdf/Page.h:
* xpdf/Parser.cc:
* xpdf/SFont.cc:
* xpdf/SFont.h:
* xpdf/Stream.cc:
* xpdf/Stream.h:
* xpdf/T1Font.cc:
* xpdf/T1Font.h:
* xpdf/TTFont.cc:
* xpdf/TTFont.h:
* xpdf/TextOutputDev.cc:
* xpdf/TextOutputDev.h:
* xpdf/XOutputDev.cc:
* xpdf/XOutputDev.h:
* xpdf/XPixmapOutputDev.cc:
* xpdf/XPixmapOutputDev.h:
* xpdf/XRef.cc:
* xpdf/XRef.h:
* xpdf/config.h:
* xpdf/gpdf-control.cc:
* xpdf/pdffonts.cc:
* xpdf/pdfimages.cc:
* xpdf/pdfinfo.cc:
* xpdf/pdftopbm.cc:
* xpdf/pdftops.cc:
* xpdf/pdftotext.cc:
* xpdf/tests/Makefile.am:
* xpdf/vms_make.com:
* xpdf/xpdf.cc: Imported Xpdf 3.00 and fixed build.

57 files changed:
pdf/goo/GHash.cc
pdf/goo/GHash.h
pdf/xpdf/DisplayFontTable.h [deleted file]
pdf/xpdf/ErrorCodes.h
pdf/xpdf/FTFont.cc [deleted file]
pdf/xpdf/FTFont.h [deleted file]
pdf/xpdf/FontFile.cc [deleted file]
pdf/xpdf/FontFile.h [deleted file]
pdf/xpdf/Function.h
pdf/xpdf/Gfx.cc
pdf/xpdf/Gfx.h
pdf/xpdf/GfxFont.cc
pdf/xpdf/GfxFont.h
pdf/xpdf/GfxState.cc
pdf/xpdf/GfxState.h
pdf/xpdf/GlobalParams.cc
pdf/xpdf/GlobalParams.h
pdf/xpdf/Makefile.am
pdf/xpdf/Object.cc
pdf/xpdf/Object.h
pdf/xpdf/Outline.cc
pdf/xpdf/OutputDev.cc
pdf/xpdf/OutputDev.h
pdf/xpdf/PBMOutputDev.cc [deleted file]
pdf/xpdf/PBMOutputDev.h [deleted file]
pdf/xpdf/PDFDoc.cc
pdf/xpdf/PDFDoc.h
pdf/xpdf/PSOutputDev.cc
pdf/xpdf/PSOutputDev.h
pdf/xpdf/Page.cc
pdf/xpdf/Page.h
pdf/xpdf/Parser.cc
pdf/xpdf/SFont.cc [deleted file]
pdf/xpdf/SFont.h [deleted file]
pdf/xpdf/Stream.cc
pdf/xpdf/Stream.h
pdf/xpdf/T1Font.cc [deleted file]
pdf/xpdf/T1Font.h [deleted file]
pdf/xpdf/TTFont.cc [deleted file]
pdf/xpdf/TTFont.h [deleted file]
pdf/xpdf/TextOutputDev.cc
pdf/xpdf/TextOutputDev.h
pdf/xpdf/XOutputDev.cc [deleted file]
pdf/xpdf/XOutputDev.h [deleted file]
pdf/xpdf/XPixmapOutputDev.cc [deleted file]
pdf/xpdf/XPixmapOutputDev.h [deleted file]
pdf/xpdf/XRef.cc
pdf/xpdf/XRef.h
pdf/xpdf/pdffonts.cc
pdf/xpdf/pdfimages.cc
pdf/xpdf/pdfinfo.cc
pdf/xpdf/pdftopbm.cc [deleted file]
pdf/xpdf/pdftops.cc
pdf/xpdf/pdftotext.cc
pdf/xpdf/vms_make.com
pdf/xpdf/xpdf.cc
pdf/xpdf/xpdfconfig.h

index 7036316b3c93e36cf034b4d854cfe6384b97a976..1dd0e26c2497edfb00213b2d468caa49c4af72f5 100644 (file)
 
 struct GHashBucket {
   GString *key;
-  void *val;
+  union {
+    void *p;
+    int i;
+  } val;
   GHashBucket *next;
 };
 
@@ -61,35 +64,37 @@ GHash::~GHash() {
 }
 
 void GHash::add(GString *key, void *val) {
-  GHashBucket **oldTab;
   GHashBucket *p;
-  int oldSize, i, h;
+  int h;
 
   // expand the table if necessary
   if (len >= size) {
-    oldSize = size;
-    oldTab = tab;
-    size = 2*size + 1;
-    tab = (GHashBucket **)gmalloc(size * sizeof(GHashBucket *));
-    for (h = 0; h < size; ++h) {
-      tab[h] = NULL;
-    }
-    for (i = 0; i < oldSize; ++i) {
-      while (oldTab[i]) {
-       p = oldTab[i];
-       oldTab[i] = oldTab[i]->next;
-       h = hash(p->key);
-       p->next = tab[h];
-       tab[h] = p;
-      }
-    }
-    gfree(oldTab);
+    expand();
+  }
+
+  // add the new symbol
+  p = new GHashBucket;
+  p->key = key;
+  p->val.p = val;
+  h = hash(key);
+  p->next = tab[h];
+  tab[h] = p;
+  ++len;
+}
+
+void GHash::add(GString *key, int val) {
+  GHashBucket *p;
+  int h;
+
+  // expand the table if necessary
+  if (len >= size) {
+    expand();
   }
 
   // add the new symbol
   p = new GHashBucket;
   p->key = key;
-  p->val = val;
+  p->val.i = val;
   h = hash(key);
   p->next = tab[h];
   tab[h] = p;
@@ -103,7 +108,17 @@ void *GHash::lookup(GString *key) {
   if (!(p = find(key, &h))) {
     return NULL;
   }
-  return p->val;
+  return p->val.p;
+}
+
+int GHash::lookupInt(GString *key) {
+  GHashBucket *p;
+  int h;
+
+  if (!(p = find(key, &h))) {
+    return 0;
+  }
+  return p->val.i;
 }
 
 void *GHash::lookup(char *key) {
@@ -113,7 +128,17 @@ void *GHash::lookup(char *key) {
   if (!(p = find(key, &h))) {
     return NULL;
   }
-  return p->val;
+  return p->val.p;
+}
+
+int GHash::lookupInt(char *key) {
+  GHashBucket *p;
+  int h;
+
+  if (!(p = find(key, &h))) {
+    return 0;
+  }
+  return p->val.i;
 }
 
 void *GHash::remove(GString *key) {
@@ -133,7 +158,30 @@ void *GHash::remove(GString *key) {
   if (deleteKeys) {
     delete p->key;
   }
-  val = p->val;
+  val = p->val.p;
+  delete p;
+  --len;
+  return val;
+}
+
+int GHash::removeInt(GString *key) {
+  GHashBucket *p;
+  GHashBucket **q;
+  int val;
+  int h;
+
+  if (!(p = find(key, &h))) {
+    return 0;
+  }
+  q = &tab[h];
+  while (*q != p) {
+    q = &((*q)->next);
+  }
+  *q = p->next;
+  if (deleteKeys) {
+    delete p->key;
+  }
+  val = p->val.i;
   delete p;
   --len;
   return val;
@@ -156,7 +204,30 @@ void *GHash::remove(char *key) {
   if (deleteKeys) {
     delete p->key;
   }
-  val = p->val;
+  val = p->val.p;
+  delete p;
+  --len;
+  return val;
+}
+
+int GHash::removeInt(char *key) {
+  GHashBucket *p;
+  GHashBucket **q;
+  int val;
+  int h;
+
+  if (!(p = find(key, &h))) {
+    return 0;
+  }
+  q = &tab[h];
+  while (*q != p) {
+    q = &((*q)->next);
+  }
+  *q = p->next;
+  if (deleteKeys) {
+    delete p->key;
+  }
+  val = p->val.i;
   delete p;
   --len;
   return val;
@@ -184,7 +255,27 @@ GBool GHash::getNext(GHashIter **iter, GString **key, void **val) {
     (*iter)->p = tab[(*iter)->h];
   }
   *key = (*iter)->p->key;
-  *val = (*iter)->p->val;
+  *val = (*iter)->p->val.p;
+  return gTrue;
+}
+
+GBool GHash::getNext(GHashIter **iter, GString **key, int *val) {
+  if (!*iter) {
+    return gFalse;
+  }
+  if ((*iter)->p) {
+    (*iter)->p = (*iter)->p->next;
+  }
+  while (!(*iter)->p) {
+    if (++(*iter)->h == size) {
+      delete *iter;
+      *iter = NULL;
+      return gFalse;
+    }
+    (*iter)->p = tab[(*iter)->h];
+  }
+  *key = (*iter)->p->key;
+  *val = (*iter)->p->val.i;
   return gTrue;
 }
 
@@ -193,6 +284,30 @@ void GHash::killIter(GHashIter **iter) {
   *iter = NULL;
 }
 
+void GHash::expand() {
+  GHashBucket **oldTab;
+  GHashBucket *p;
+  int oldSize, h, i;
+
+  oldSize = size;
+  oldTab = tab;
+  size = 2*size + 1;
+  tab = (GHashBucket **)gmalloc(size * sizeof(GHashBucket *));
+  for (h = 0; h < size; ++h) {
+    tab[h] = NULL;
+  }
+  for (i = 0; i < oldSize; ++i) {
+    while (oldTab[i]) {
+      p = oldTab[i];
+      oldTab[i] = oldTab[i]->next;
+      h = hash(p->key);
+      p->next = tab[h];
+      tab[h] = p;
+    }
+  }
+  gfree(oldTab);
+}
+
 GHashBucket *GHash::find(GString *key, int *h) {
   GHashBucket *p;
 
index 69c767b3aaef0235337b902f6e242f1faa8a2a15..4a6e08d68965d2c5ac360c89c55d474c75bbece0 100644 (file)
@@ -29,17 +29,24 @@ public:
   GHash(GBool deleteKeysA = gFalse);
   ~GHash();
   void add(GString *key, void *val);
+  void add(GString *key, int val);
   void *lookup(GString *key);
+  int lookupInt(GString *key);
   void *lookup(char *key);
+  int lookupInt(char *key);
   void *remove(GString *key);
+  int removeInt(GString *key);
   void *remove(char *key);
+  int removeInt(char *key);
   int getLength() { return len; }
   void startIter(GHashIter **iter);
   GBool getNext(GHashIter **iter, GString **key, void **val);
+  GBool getNext(GHashIter **iter, GString **key, int *val);
   void killIter(GHashIter **iter);
 
 private:
 
+  void expand();
   GHashBucket *find(GString *key, int *h);
   GHashBucket *find(char *key, int *h);
   int hash(GString *key);
diff --git a/pdf/xpdf/DisplayFontTable.h b/pdf/xpdf/DisplayFontTable.h
deleted file mode 100644 (file)
index 3c2379f..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-//========================================================================
-//
-// DisplayFontTable.h
-//
-// Copyright 2001-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-static struct {
-  char *name;
-  char *xlfd;
-  char *encoding;
-} displayFontTab[] = {
-  {"Courier",               "-*-courier-medium-r-normal-*-%s-*-*-*-*-*-iso8859-1",         "Latin1"},
-  {"Courier-Bold",          "-*-courier-bold-r-normal-*-%s-*-*-*-*-*-iso8859-1",           "Latin1"},
-  {"Courier-BoldOblique",   "-*-courier-bold-o-normal-*-%s-*-*-*-*-*-iso8859-1",           "Latin1"},
-  {"Courier-Oblique",       "-*-courier-medium-o-normal-*-%s-*-*-*-*-*-iso8859-1",         "Latin1"},
-  {"Helvetica",             "-*-helvetica-medium-r-normal-*-%s-*-*-*-*-*-iso8859-1",       "Latin1"},
-  {"Helvetica-Bold",        "-*-helvetica-bold-r-normal-*-%s-*-*-*-*-*-iso8859-1",         "Latin1"},
-  {"Helvetica-BoldOblique", "-*-helvetica-bold-o-normal-*-%s-*-*-*-*-*-iso8859-1",         "Latin1"},
-  {"Helvetica-Oblique",     "-*-helvetica-medium-o-normal-*-%s-*-*-*-*-*-iso8859-1",       "Latin1"},
-  {"Symbol",                "-*-symbol-medium-r-normal-*-%s-*-*-*-*-*-adobe-fontspecific", "Symbol"},
-  {"Times-Bold",            "-*-times-bold-r-normal-*-%s-*-*-*-*-*-iso8859-1",             "Latin1"},
-  {"Times-BoldItalic",      "-*-times-bold-i-normal-*-%s-*-*-*-*-*-iso8859-1",             "Latin1"},
-  {"Times-Italic",          "-*-times-medium-i-normal-*-%s-*-*-*-*-*-iso8859-1",           "Latin1"},
-  {"Times-Roman",           "-*-times-medium-r-normal-*-%s-*-*-*-*-*-iso8859-1",           "Latin1"},
-  {"ZapfDingbats",          "-*-zapfdingbats-medium-r-normal-*-%s-*-*-*-*-*-*-*",          "ZapfDingbats"},
-  {NULL}
-};
index 6eb14350c77451deeb5863e7a1aaf23bab1c7fa0..b28528df5647ea66631d41fa282970e267c4248c 100644 (file)
@@ -31,4 +31,6 @@
 
 #define errBadPageNum       9  // invalid page number
 
+#define errFileIO          10   // file I/O error
+
 #endif
diff --git a/pdf/xpdf/FTFont.cc b/pdf/xpdf/FTFont.cc
deleted file mode 100644 (file)
index 1a5ecfa..0000000
+++ /dev/null
@@ -1,703 +0,0 @@
-//========================================================================
-//
-// FTFont.cc
-//
-// Copyright 2001-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#include <aconf.h>
-
-#if FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
-
-#ifdef USE_GCC_PRAGMAS
-#pragma implementation
-#endif
-
-#include <math.h>
-#include <string.h>
-#include "gmem.h"
-#include "freetype/ftoutln.h"
-#include "freetype/internal/ftobjs.h"
-#if 1 //~ cff cid->gid map
-#include "freetype/internal/cfftypes.h"
-#include "freetype/internal/tttypes.h"
-#endif
-#include "GlobalParams.h"
-#include "GfxState.h"
-#include "FTFont.h"
-
-//------------------------------------------------------------------------
-
-FTFontEngine::FTFontEngine(Display *displayA, Visual *visualA, int depthA,
-                          Colormap colormapA, GBool aaA):
-  SFontEngine(displayA, visualA, depthA, colormapA) {
-
-  ok = gFalse;
-  if (FT_Init_FreeType(&lib)) {
-    return;
-  }
-  aa = aaA;
-  ok = gTrue;
-}
-
-FTFontEngine::~FTFontEngine() {
-  FT_Done_FreeType(lib);
-}
-
-//------------------------------------------------------------------------
-
-FTFontFile::FTFontFile(FTFontEngine *engineA, char *fontFileName,
-                      char **fontEnc, Gushort *codeToGID) {
-  char *name;
-  int i;
-
-  ok = gFalse;
-  engine = engineA;
-  codeMap = NULL;
-  cidToGID = NULL;
-  cidToGIDLen = 0;
-
-  if (FT_New_Face(engine->lib, fontFileName, 0, &face)) {
-    return;
-  }
-
-  if (!strcmp(face->driver->root.clazz->module_name, "type1") ||
-      !strcmp(face->driver->root.clazz->module_name, "cff")) {
-    mode = ftFontModeCodeMapDirect;
-    codeMap = (Guint *)gmalloc(256 * sizeof(Guint));
-    for (i = 0; i < 256; ++i) {
-      codeMap[i] = 0;
-      if ((name = fontEnc[i])) {
-       codeMap[i] = FT_Get_Name_Index(face, name);
-      }
-    }
-
-  } else {
-    mode = ftFontModeCodeMapDirect;
-    codeMap = (Guint *)gmalloc(256 * sizeof(Guint));
-    for (i = 0; i < 256; ++i) {
-      codeMap[i] = (int)codeToGID[i];
-    }
-  }
-
-  ok = gTrue;
-}
-
-FTFontFile::FTFontFile(FTFontEngine *engineA, char *fontFileName,
-                      Gushort *cidToGIDA, int cidToGIDLenA, GBool embedded) {
-  int i;
-
-  ok = gFalse;
-  engine = engineA;
-  codeMap = NULL;
-  cidToGID = NULL;
-  cidToGIDLen = 0;
-
-  if (FT_New_Face(engine->lib, fontFileName, 0, &face)) {
-    return;
-  }
-  cidToGIDLen = cidToGIDLenA;
-  cidToGID = (Gushort *)gmalloc(cidToGIDLen * sizeof(Gushort));
-  memcpy(cidToGID, cidToGIDA, cidToGIDLen * sizeof(Gushort));
-  if (!strcmp(face->driver->root.clazz->module_name, "t1cid")) {
-    mode = ftFontModeCID;
-  } else if (!strcmp(face->driver->root.clazz->module_name, "cff")) {
-    mode = ftFontModeCFFCharset;
-  } else if (embedded) {
-    mode = ftFontModeCIDToGIDMap;
-  } else {
-    mode = ftFontModeUnicode;
-    for (i = 0; i < face->num_charmaps; ++i) {
-      if ((face->charmaps[i]->platform_id == 3 &&
-          face->charmaps[i]->encoding_id == 1) ||
-         face->charmaps[i]->platform_id == 0) {
-       break;
-      }
-    }
-    if (i == face->num_charmaps) {
-      i = 0;
-    }
-    FT_Set_Charmap(face, face->charmaps[i]);
-  }
-  ok = gTrue;
-}
-
-FTFontFile::FTFontFile(FTFontEngine *engineA, char *fontFileName,
-                      GBool embedded) {
-  int i;
-
-  ok = gFalse;
-  engine = engineA;
-  codeMap = NULL;
-  cidToGID = NULL;
-  cidToGIDLen = 0;
-
-  if (FT_New_Face(engine->lib, fontFileName, 0, &face)) {
-    return;
-  }
-  if (!strcmp(face->driver->root.clazz->module_name, "t1cid")) {
-    mode = ftFontModeCID;
-  } else if (embedded) {
-    mode = ftFontModeCFFCharset;
-  } else {
-    mode = ftFontModeUnicode;
-    for (i = 0; i < face->num_charmaps; ++i) {
-      if ((face->charmaps[i]->platform_id == 3 &&
-          face->charmaps[i]->encoding_id == 1) ||
-         face->charmaps[i]->platform_id == 0) {
-       break;
-      }
-    }
-    if (i == face->num_charmaps) {
-      i = 0;
-    }
-    FT_Set_Charmap(face, face->charmaps[i]);
-  }
-  ok = gTrue;
-}
-
-FTFontFile::~FTFontFile() {
-  if (face) {
-    FT_Done_Face(face);
-  }
-  if (codeMap) {
-    gfree(codeMap);
-  }
-  if (cidToGID) {
-    gfree(cidToGID);
-  }
-}
-
-//------------------------------------------------------------------------
-
-FTFont::FTFont(FTFontFile *fontFileA, double *m) {
-  FTFontEngine *engine;
-  FT_Face face;
-  double size, div;
-  int x, xMin, xMax;
-  int y, yMin, yMax;
-  int i;
-
-  ok = gFalse;
-  fontFile = fontFileA;
-  engine = fontFile->engine;
-  face = fontFile->face;
-  if (FT_New_Size(face, &sizeObj)) {
-    return;
-  }
-  face->size = sizeObj;
-  size = sqrt(m[2]*m[2] + m[3]*m[3]);
-  if (FT_Set_Pixel_Sizes(face, 0, (int)size)) {
-    return;
-  }
-
-  div = face->bbox.xMax > 20000 ? 65536 : 1;
-
-  // transform the four corners of the font bounding box -- the min
-  // and max values form the bounding box of the transformed font
-  x = (int)((m[0] * face->bbox.xMin + m[2] * face->bbox.yMin) /
-           (div * face->units_per_EM));
-  xMin = xMax = x;
-  y = (int)((m[1] * face->bbox.xMin + m[3] * face->bbox.yMin) /
-           (div * face->units_per_EM));
-  yMin = yMax = y;
-  x = (int)((m[0] * face->bbox.xMin + m[2] * face->bbox.yMax) /
-           (div * face->units_per_EM));
-  if (x < xMin) {
-    xMin = x;
-  } else if (x > xMax) {
-    xMax = x;
-  }
-  y = (int)((m[1] * face->bbox.xMin + m[3] * face->bbox.yMax) /
-           (div * face->units_per_EM));
-  if (y < yMin) {
-    yMin = y;
-  } else if (y > yMax) {
-    yMax = y;
-  }
-  x = (int)((m[0] * face->bbox.xMax + m[2] * face->bbox.yMin) /
-           (div * face->units_per_EM));
-  if (x < xMin) {
-    xMin = x;
-  } else if (x > xMax) {
-    xMax = x;
-  }
-  y = (int)((m[1] * face->bbox.xMax + m[3] * face->bbox.yMin) /
-           (div * face->units_per_EM));
-  if (y < yMin) {
-    yMin = y;
-  } else if (y > yMax) {
-    yMax = y;
-  }
-  x = (int)((m[0] * face->bbox.xMax + m[2] * face->bbox.yMax) /
-           (div * face->units_per_EM));
-  if (x < xMin) {
-    xMin = x;
-  } else if (x > xMax) {
-    xMax = x;
-  }
-  y = (int)((m[1] * face->bbox.xMax + m[3] * face->bbox.yMax) /
-           (div * face->units_per_EM));
-  if (y < yMin) {
-    yMin = y;
-  } else if (y > yMax) {
-    yMax = y;
-  }
-  // This is a kludge: some buggy PDF generators embed fonts with
-  // zero bounding boxes.
-  if (xMax == xMin) {
-    xMin = 0;
-    xMax = (int)size;
-  }
-  if (yMax == yMin) {
-    yMin = 0;
-    yMax = (int)(1.2 * size);
-  }
-  // this should be (max - min + 1), but we add some padding to
-  // deal with rounding errors, bogus bboxes, etc.
-  glyphW = xMax - xMin + 3;
-  glyphW += glyphW >> 1;
-  glyphH = yMax - yMin + 3;
-  glyphH += glyphH >> 1;
-  if (engine->aa) {
-    glyphSize = glyphW * glyphH;
-  } else {
-    glyphSize = ((glyphW + 7) >> 3) * glyphH;
-  }
-
-  // set up the glyph pixmap cache
-  cacheAssoc = 8;
-  if (glyphSize <= 256) {
-    cacheSets = 8;
-  } else if (glyphSize <= 512) {
-    cacheSets = 4;
-  } else if (glyphSize <= 1024) {
-    cacheSets = 2;
-  } else {
-    cacheSets = 1;
-  }
-  cache = (Guchar *)gmalloc(cacheSets * cacheAssoc * glyphSize);
-  cacheTags = (FTFontCacheTag *)gmalloc(cacheSets * cacheAssoc *
-                                       sizeof(FTFontCacheTag));
-  for (i = 0; i < cacheSets * cacheAssoc; ++i) {
-    cacheTags[i].mru = i & (cacheAssoc - 1);
-  }
-
-  // create the XImage
-  if (!(image = XCreateImage(engine->display, engine->visual, engine->depth,
-                            ZPixmap, 0, NULL, glyphW, glyphH, 8, 0))) {
-    return;
-  }
-  image->data = (char *)gmalloc(glyphH * image->bytes_per_line);
-
-  // compute the transform matrix
-  matrix.xx = (FT_Fixed)((m[0] / size) * 65536);
-  matrix.yx = (FT_Fixed)((m[1] / size) * 65536);
-  matrix.xy = (FT_Fixed)((m[2] / size) * 65536);
-  matrix.yy = (FT_Fixed)((m[3] / size) * 65536);
-
-  ok = gTrue;
-}
-
-FTFont::~FTFont() {
-  gfree(cacheTags);
-  gfree(cache);
-  gfree(image->data);
-  image->data = NULL;
-  XDestroyImage(image);
-}
-
-GBool FTFont::drawChar(Drawable d, int w, int h, GC gc,
-                      int x, int y, int r, int g, int b,
-                      CharCode c, Unicode u) {
-  FTFontEngine *engine;
-  XColor xcolor;
-  int bgR, bgG, bgB;
-  Gulong colors[5];
-  Guchar *bitmap, *p;
-  GBool tempBitmap;
-  XImage *img;
-  int pix;
-  int xOffset, yOffset, x0, y0, x1, y1, gw, gh, w0, h0;
-  int xx, yy, xx1;
-
-  engine = fontFile->engine;
-
-  // no Unicode index for this char - don't draw anything
-  if (fontFile->mode == ftFontModeUnicode && u == 0) {
-    return gFalse;
-  }
-
-  // generate the glyph pixmap
-  if (!(bitmap = getGlyphPixmap(c, u, &xOffset, &yOffset, &gw, &gh,
-                               &tempBitmap))) {
-    return gFalse;
-  }
-
-  // compute: (x0,y0) = position in destination drawable
-  //          (x1,y1) = position in glyph image
-  //          (w0,h0) = size of image transfer
-  x0 = x - xOffset;
-  y0 = y - yOffset;
-  x1 = 0;
-  y1 = 0;
-  w0 = gw;
-  h0 = gh;
-  if (x0 < 0) {
-    x1 = -x0;
-    w0 += x0;
-    x0 = 0;
-  }
-  if (x0 + w0 > w) {
-    w0 = w - x0;
-  }
-  if (w0 < 0) {
-    goto done;
-  }
-  if (y0 < 0) {
-    y1 = -y0;
-    h0 += y0;
-    y0 = 0;
-  }
-  if (y0 + h0 > h) {
-    h0 = h - y0;
-  }
-  if (h0 < 0) {
-    goto done;
-  }
-
-  // getGlyphPixmap may have returned a larger-than-cache-entry
-  // bitmap, in which case we need to allocate a temporary XImage here
-  if (tempBitmap) {
-    if (!(img = XCreateImage(engine->display, engine->visual, engine->depth,
-                            ZPixmap, 0, NULL, gw, gh, 8, 0))) {
-      goto done;
-    }
-    img->data = (char *)gmalloc(gh * img->bytes_per_line);
-  } else {
-    img = image;
-  }
-
-  // read the X image
-  XGetSubImage(engine->display, d, x0, y0, w0, h0, (1 << engine->depth) - 1,
-              ZPixmap, img, x1, y1);
-
-  if (engine->aa) {
-
-    // compute the colors
-    xcolor.pixel = XGetPixel(img, x1 + w0/2, y1 + h0/2);
-    XQueryColor(engine->display, engine->colormap, &xcolor);
-    bgR = xcolor.red;
-    bgG = xcolor.green;
-    bgB = xcolor.blue;
-    colors[1] = engine->findColor((r + 3*bgR) / 4,
-                                 (g + 3*bgG) / 4,
-                                 (b + 3*bgB) / 4);
-    colors[2] = engine->findColor((r + bgR) / 2,
-                                 (g + bgG) / 2,
-                                 (b + bgB) / 2);
-    colors[3] = engine->findColor((3*r + bgR) / 4,
-                                 (3*g + bgG) / 4,
-                                 (3*b + bgB) / 4);
-    colors[4] = engine->findColor(r, g, b);
-
-    // stuff the glyph pixmap into the X image
-    p = bitmap;
-    for (yy = 0; yy < gh; ++yy) {
-      for (xx = 0; xx < gw; ++xx) {
-       pix = *p++ & 0xff;
-       // this is a heuristic which seems to produce decent
-       // results -- the linear mapping would be:
-       // pix = (pix * 5) / 256;
-       pix = ((pix + 10) * 5) / 256;
-       if (pix > 4) {
-         pix = 4;
-       }
-       if (pix > 0) {
-         XPutPixel(img, xx, yy, colors[pix]);
-       }
-      }
-    }
-
-  } else {
-
-    // one color
-    colors[1] = engine->findColor(r, g, b);
-
-    // stuff the glyph bitmap into the X image
-    p = bitmap;
-    for (yy = 0; yy < gh; ++yy) {
-      for (xx = 0; xx < gw; xx += 8) {
-       pix = *p++;
-       for (xx1 = xx; xx1 < xx + 8 && xx1 < gw; ++xx1) {
-         if (pix & 0x80) {
-           XPutPixel(img, xx1, yy, colors[1]);
-         }
-         pix <<= 1;
-       }
-      }
-    }
-
-  }
-
-  // draw the X image
-  XPutImage(engine->display, d, gc, img, x1, y1, x0, y0, w0, h0);
-
-  if (tempBitmap) {
-    gfree(img->data);
-    img->data = NULL;
-    XDestroyImage(img);
-  }
- done:
-  if (tempBitmap) {
-    gfree(bitmap);
-  }
-  return gTrue;
-}
-
-Guchar *FTFont::getGlyphPixmap(CharCode c, Unicode u,
-                              int *x, int *y, int *w, int *h,
-                              GBool *tempBitmap) {
-  FT_GlyphSlot slot;
-  FT_UInt idx;
-  int rowSize;
-  int i, j, k;
-  Guchar *ret, *p, *q;
-
-  // check the cache
-  i = (c & (cacheSets - 1)) * cacheAssoc;
-  for (j = 0; j < cacheAssoc; ++j) {
-    if ((cacheTags[i+j].mru & 0x8000) && cacheTags[i+j].code == c) {
-      *x = cacheTags[i+j].x;
-      *y = cacheTags[i+j].y;
-      *w = cacheTags[i+j].w;
-      *h = cacheTags[i+j].h;
-      for (k = 0; k < cacheAssoc; ++k) {
-       if (k != j &&
-           (cacheTags[i+k].mru & 0x7fff) < (cacheTags[i+j].mru & 0x7fff)) {
-         ++cacheTags[i+k].mru;
-       }
-      }
-      cacheTags[i+j].mru = 0x8000;
-      *tempBitmap = gFalse;
-      return cache + (i+j) * glyphSize;
-    }
-  }
-
-  // generate the glyph pixmap or bitmap
-  fontFile->face->size = sizeObj;
-  FT_Set_Transform(fontFile->face, &matrix, NULL);
-  slot = fontFile->face->glyph;
-  idx = getGlyphIndex(c, u);
-  // if we have the FT2 bytecode interpreter, autohinting won't be used
-#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
-  if (FT_Load_Glyph(fontFile->face, idx,
-                   fontFile->engine->aa ? FT_LOAD_NO_BITMAP
-                                        : FT_LOAD_DEFAULT)) {
-    return gFalse;
-  }
-#else
-  // FT2's autohinting doesn't always work very well (especially with
-  // font subsets), so turn it off if anti-aliasing is enabled; if
-  // anti-aliasing is disabled, this seems to be a tossup - some fonts
-  // look better with hinting, some without, so leave hinting on
-  if (FT_Load_Glyph(fontFile->face, idx,
-               fontFile->engine->aa ? FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP
-                                    : FT_LOAD_DEFAULT)) {
-    return gFalse;
-  }
-#endif
-  if (FT_Render_Glyph(slot,
-                     fontFile->engine->aa ? ft_render_mode_normal :
-                                            ft_render_mode_mono)) {
-    return gFalse;
-  }
-
-  // copy the glyph into the cache or a temporary bitmap
-  *x = -slot->bitmap_left;
-  *y = slot->bitmap_top;
-  *w = slot->bitmap.width;
-  *h = slot->bitmap.rows;
-  if (fontFile->engine->aa) {
-    rowSize = *w;
-  } else {
-    rowSize = (*w + 7) >> 3;
-  }
-  if (*w > glyphW || *h > glyphH) {
-    // the glyph doesn't fit in the bounding box -- return a
-    // temporary, uncached bitmap (this shouldn't happen but some
-    // fonts have incorrect bboxes)
-    ret = (Guchar *)gmalloc(*h * rowSize);
-    *tempBitmap = gTrue;
-  } else {
-    // store glyph pixmap in cache
-    ret = NULL; // make gcc happy
-    for (j = 0; j < cacheAssoc; ++j) {
-      if ((cacheTags[i+j].mru & 0x7fff) == cacheAssoc - 1) {
-       cacheTags[i+j].mru = 0x8000;
-       cacheTags[i+j].code = c;
-       cacheTags[i+j].x = *x;
-       cacheTags[i+j].y = *y;
-       cacheTags[i+j].w = *w;
-       cacheTags[i+j].h = *h;
-       ret = cache + (i+j) * glyphSize;
-      } else {
-       ++cacheTags[i+j].mru;
-      }
-    }
-    *tempBitmap = gFalse;
-  }
-  for (k = 0, p = ret, q = slot->bitmap.buffer;
-       k < slot->bitmap.rows;
-       ++k, p += rowSize, q += slot->bitmap.pitch) {
-    memcpy(p, q, rowSize);
-  }
-  return ret;
-}
-
-GBool FTFont::getCharPath(CharCode c, Unicode u, GfxState *state) {
-  static FT_Outline_Funcs outlineFuncs = {
-    &charPathMoveTo,
-    &charPathLineTo,
-    &charPathConicTo,
-    &charPathCubicTo,
-    0, 0
-  };
-  FT_GlyphSlot slot;
-  FT_UInt idx;
-  FT_Glyph glyph;
-
-  fontFile->face->size = sizeObj;
-  FT_Set_Transform(fontFile->face, &matrix, NULL);
-  slot = fontFile->face->glyph;
-  idx = getGlyphIndex(c, u);
-#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
-  if (FT_Load_Glyph(fontFile->face, idx, FT_LOAD_DEFAULT)) {
-    return gFalse;
-  }
-#else
-  // FT2's autohinting doesn't always work very well (especially with
-  // font subsets), so turn it off if anti-aliasing is enabled; if
-  // anti-aliasing is disabled, this seems to be a tossup - some fonts
-  // look better with hinting, some without, so leave hinting on
-  if (FT_Load_Glyph(fontFile->face, idx,
-                   fontFile->engine->aa ? FT_LOAD_NO_HINTING
-                                        : FT_LOAD_DEFAULT)) {
-    return gFalse;
-  }
-#endif
-  if (FT_Get_Glyph(slot, &glyph)) {
-    return gFalse;
-  }
-  FT_Outline_Decompose(&((FT_OutlineGlyph)glyph)->outline,
-                      &outlineFuncs, state);
-  return gTrue;
-}
-
-int FTFont::charPathMoveTo(FT_Vector *pt, void *state) {
-  ((GfxState *)state)->moveTo(pt->x / 64.0, -pt->y / 64.0);
-  return 0;
-}
-
-int FTFont::charPathLineTo(FT_Vector *pt, void *state) {
-  ((GfxState *)state)->lineTo(pt->x / 64.0, -pt->y / 64.0);
-  return 0;
-}
-
-int FTFont::charPathConicTo(FT_Vector *ctrl, FT_Vector *pt, void *state) {
-  double x0, y0, x1, y1, x2, y2, x3, y3, xc, yc;
-
-  x0 = ((GfxState *)state)->getCurX();
-  y0 = ((GfxState *)state)->getCurY();
-  xc = ctrl->x / 64.0;
-  yc = -ctrl->y / 64.0;
-  x3 = pt->x / 64.0;
-  y3 = -pt->y / 64.0;
-
-  // A second-order Bezier curve is defined by two endpoints, p0 and
-  // p3, and one control point, pc:
-  //
-  //     p(t) = (1-t)^2*p0 + t*(1-t)*pc + t^2*p3
-  //
-  // A third-order Bezier curve is defined by the same two endpoints,
-  // p0 and p3, and two control points, p1 and p2:
-  //
-  //     p(t) = (1-t)^3*p0 + 3t*(1-t)^2*p1 + 3t^2*(1-t)*p2 + t^3*p3
-  //
-  // Applying some algebra, we can convert a second-order curve to a
-  // third-order curve:
-  //
-  //     p1 = (1/3) * (p0 + 2pc)
-  //     p2 = (1/3) * (2pc + p3)
-
-  x1 = (1.0 / 3.0) * (x0 + 2 * xc);
-  y1 = (1.0 / 3.0) * (y0 + 2 * yc);
-  x2 = (1.0 / 3.0) * (2 * xc + x3);
-  y2 = (1.0 / 3.0) * (2 * yc + y3);
-
-  ((GfxState *)state)->curveTo(x1, y1, x2, y2, x3, y3);
-  return 0;
-}
-
-int FTFont::charPathCubicTo(FT_Vector *ctrl1, FT_Vector *ctrl2,
-                           FT_Vector *pt, void *state) {
-  ((GfxState *)state)->curveTo(ctrl1->x / 64.0, -ctrl1->y / 64.0,
-                              ctrl2->x / 64.0, -ctrl2->y / 64.0,
-                              pt->x / 64.0, -pt->y / 64.0);
-  return 0;
-}
-
-FT_UInt FTFont::getGlyphIndex(CharCode c, Unicode u) {
-  FT_UInt idx;
-  int j;
-
-  idx = 0; // make gcc happy
-  switch (fontFile->mode) {
-  case ftFontModeUnicode:
-    idx = FT_Get_Char_Index(fontFile->face, (FT_ULong)u);
-    break;
-  case ftFontModeCodeMapDirect:
-    if (c <= 0xff) {
-      idx = (FT_UInt)fontFile->codeMap[c];
-    } else {
-      idx = 0;
-    }
-    break;
-  case ftFontModeCIDToGIDMap:
-    if (fontFile->cidToGIDLen) {
-      if ((int)c < fontFile->cidToGIDLen) {
-       idx = (FT_UInt)fontFile->cidToGID[c];
-      } else {
-       idx = (FT_UInt)0;
-      }
-    } else {
-      idx = (FT_UInt)c;
-    }
-    break;
-  case ftFontModeCFFCharset:
-#if 1 //~ cff cid->gid map
-    {
-#if FREETYPE_MAJOR == 2 && FREETYPE_MINOR == 0
-      CFF_Font *cff = (CFF_Font *)((TT_Face)fontFile->face)->extra.data;
-#else
-      CFF_Font cff = (CFF_Font)((TT_Face)fontFile->face)->extra.data;
-#endif
-      idx = 0;
-      for (j = 0; j < (int)cff->num_glyphs; ++j) {
-       if (cff->charset.sids[j] == c) {
-         idx = j;
-         break;
-       }
-      }
-    }
-#endif
-    break;
-  case ftFontModeCID:
-    idx = c;
-    break;
-  }
-  return idx;
-}
-
-#endif // FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
diff --git a/pdf/xpdf/FTFont.h b/pdf/xpdf/FTFont.h
deleted file mode 100644 (file)
index 8da5558..0000000
+++ /dev/null
@@ -1,134 +0,0 @@
-//========================================================================
-//
-// FTFont.h
-//
-// An X wrapper for the FreeType font rasterizer.
-//
-// Copyright 2001-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#ifndef FTFONT_H
-#define FTFONT_H
-
-#include <aconf.h>
-
-#if FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
-
-#ifdef USE_GCC_PRAGMAS
-#pragma interface
-#endif
-
-#include <freetype/freetype.h>
-#include "CharTypes.h"
-#include "SFont.h"
-
-//------------------------------------------------------------------------
-
-class FTFontEngine: public SFontEngine {
-public:
-
-  FTFontEngine(Display *displayA, Visual *visualA, int depthA,
-              Colormap colormapA, GBool aaA);
-  GBool isOk() { return ok; }
-  virtual ~FTFontEngine();
-
-private:
-
-  FT_Library lib;
-  GBool aa;
-  Gulong palette[5];
-  GBool ok;
-
-  friend class FTFontFile;
-  friend class FTFont;
-};
-
-//------------------------------------------------------------------------
-
-enum FTFontIndexMode {
-  ftFontModeUnicode,
-  ftFontModeCodeMapDirect,
-  ftFontModeCIDToGIDMap,
-  ftFontModeCFFCharset,
-  ftFontModeCID
-};
-
-class FTFontFile: public SFontFile {
-public:
-
-  // 8-bit font, TrueType or Type 1/1C
-  FTFontFile(FTFontEngine *engineA, char *fontFileName,
-            char **fontEnc, Gushort *codeToGID);
-
-  // CID font, TrueType
-  FTFontFile(FTFontEngine *engineA, char *fontFileName,
-            Gushort *cidToGIDA, int cidToGIDLenA, GBool embedded);
-
-  // CID font, Type 0C (CFF)
-  FTFontFile(FTFontEngine *engineA, char *fontFileName,
-            GBool embedded);
-
-  GBool isOk() { return ok; }
-  virtual ~FTFontFile();
-
-private:
-
-  FTFontEngine *engine;
-  FT_Face face;
-  FTFontIndexMode mode;
-  Guint *codeMap;
-  Gushort *cidToGID;
-  int cidToGIDLen;
-  GBool ok;
-
-  friend class FTFont;
-};
-
-//------------------------------------------------------------------------
-
-struct FTFontCacheTag {
-  Gushort code;
-  Gushort mru;                 // valid bit (0x8000) and MRU index
-  int x, y, w, h;              // offset and size of glyph
-};
-
-class FTFont: public SFont {
-public:
-
-  FTFont(FTFontFile *fontFileA, double *m);
-  GBool isOk() { return ok; }
-  virtual ~FTFont();
-  virtual GBool drawChar(Drawable d, int w, int h, GC gc,
-                        int x, int y, int r, int g, int b,
-                        CharCode c, Unicode u);
-  virtual GBool getCharPath(CharCode c, Unicode u, GfxState *state);
-
-private:
-
-  Guchar *getGlyphPixmap(CharCode c, Unicode u,
-                        int *x, int *y, int *w, int *h,
-                        GBool *tempBitmap);
-  static int charPathMoveTo(FT_Vector *pt, void *state);
-  static int charPathLineTo(FT_Vector *pt, void *state);
-  static int charPathConicTo(FT_Vector *ctrl, FT_Vector *pt, void *state);
-  static int charPathCubicTo(FT_Vector *ctrl1, FT_Vector *ctrl2,
-                            FT_Vector *pt, void *state);
-  FT_UInt getGlyphIndex(CharCode c, Unicode u);
-
-  FTFontFile *fontFile;
-  FT_Size sizeObj;
-  XImage *image;
-  FT_Matrix matrix;
-  int glyphW, glyphH;          // size of glyph pixmaps
-  int glyphSize;               // size of glyph pixmaps, in bytes
-  Guchar *cache;               // glyph pixmap cache
-  FTFontCacheTag *cacheTags;   // cache tags, i.e., char codes
-  int cacheSets;               // number of sets in cache
-  int cacheAssoc;              // cache associativity (glyphs per set)
-  GBool ok;
-};
-
-#endif // FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
-
-#endif
diff --git a/pdf/xpdf/FontFile.cc b/pdf/xpdf/FontFile.cc
deleted file mode 100644 (file)
index 0c44422..0000000
+++ /dev/null
@@ -1,4113 +0,0 @@
-//========================================================================
-//
-// FontFile.cc
-//
-// Copyright 1999-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma implementation
-#endif
-
-#include <locale.h>
-#include <math.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <stdarg.h>
-#include <string.h>
-#include <ctype.h>
-#include "gmem.h"
-#include "GHash.h"
-#include "Error.h"
-#include "GlobalParams.h"
-#include "CharCodeToUnicode.h"
-#include "FontEncodingTables.h"
-#include "FontFile.h"
-
-#include "CompactFontTables.h"
-
-//------------------------------------------------------------------------
-
-static inline char *nextLine(char *line, char *end) {
-  while (line < end && *line != '\n' && *line != '\r')
-    ++line;
-  while (line < end && (*line == '\n' || *line == '\r'))
-    ++line;
-  return line;
-}
-
-static char hexChars[17] = "0123456789ABCDEF";
-
-//------------------------------------------------------------------------
-// FontFile
-//------------------------------------------------------------------------
-
-FontFile::FontFile() {
-}
-
-FontFile::~FontFile() {
-}
-
-//------------------------------------------------------------------------
-// Type1FontFile
-//------------------------------------------------------------------------
-
-Type1FontFile::Type1FontFile(char *file, int len) {
-  char *line, *line1, *p, *p2;
-  GBool haveEncoding;
-  char buf[256];
-  char c;
-  int n, code, i, j;
-
-  name = NULL;
-  encoding = (char **)gmalloc(256 * sizeof(char *));
-  for (i = 0; i < 256; ++i) {
-    encoding[i] = NULL;
-  }
-  haveEncoding = gFalse;
-
-  for (i = 1, line = file;
-       i <= 100 && line < file + len && !haveEncoding;
-       ++i) {
-
-    // get font name
-    if (!strncmp(line, "/FontName", 9)) {
-      strncpy(buf, line, 255);
-      buf[255] = '\0';
-      if ((p = strchr(buf+9, '/')) &&
-         (p = strtok(p+1, " \t\n\r"))) {
-       name = copyString(p);
-      }
-      line = nextLine(line, file + len);
-
-    // get encoding
-    } else if (!strncmp(line, "/Encoding StandardEncoding def", 30)) {
-      for (j = 0; j < 256; ++j) {
-       if (standardEncoding[j]) {
-         encoding[j] = copyString(standardEncoding[j]);
-       }
-      }
-      haveEncoding = gTrue;
-    } else if (!strncmp(line, "/Encoding 256 array", 19)) {
-      for (j = 0; j < 300; ++j) {
-       line1 = nextLine(line, file + len);
-       if ((n = line1 - line) > 255) {
-         n = 255;
-       }
-       strncpy(buf, line, n);
-       buf[n] = '\0';
-       for (p = buf; *p == ' ' || *p == '\t'; ++p) ;
-       if (!strncmp(p, "dup", 3)) {
-         for (p += 3; *p == ' ' || *p == '\t'; ++p) ;
-         for (p2 = p; *p2 >= '0' && *p2 <= '9'; ++p2) ;
-         if (*p2) {
-           c = *p2;
-           *p2 = '\0';
-           if ((code = atoi(p)) < 256) {
-             *p2 = c;
-             for (p = p2; *p == ' ' || *p == '\t'; ++p) ;
-             if (*p == '/') {
-               ++p;
-               for (p2 = p; *p2 && *p2 != ' ' && *p2 != '\t'; ++p2) ;
-               *p2 = '\0';
-               encoding[code] = copyString(p);
-             }
-           }
-         }
-       } else {
-         if (strtok(buf, " \t") &&
-             (p = strtok(NULL, " \t\n\r")) && !strcmp(p, "def")) {
-           break;
-         }
-       }
-       line = line1;
-      }
-      //~ check for getinterval/putinterval junk
-      haveEncoding = gTrue;
-
-    } else {
-      line = nextLine(line, file + len);
-    }
-  }
-}
-
-Type1FontFile::~Type1FontFile() {
-  int i;
-
-  if (name) {
-    gfree(name);
-  }
-  for (i = 0; i < 256; ++i) {
-    gfree(encoding[i]);
-  }
-  gfree(encoding);
-}
-
-//------------------------------------------------------------------------
-// Type1CFontFile
-//------------------------------------------------------------------------
-
-struct Type1CTopDict {
-  int version;
-  int notice;
-  int copyright;
-  int fullName;
-  int familyName;
-  int weight;
-  int isFixedPitch;
-  double italicAngle;
-  double underlinePosition;
-  double underlineThickness;
-  int paintType;
-  int charstringType;
-  double fontMatrix[6];
-  int uniqueID;
-  double fontBBox[4];
-  double strokeWidth;
-  int charset;
-  int encoding;
-  int charStrings;
-  int privateSize;
-  int privateOffset;
-
-  //----- CIDFont entries
-  int registry;
-  int ordering;
-  int supplement;
-  int fdArrayOffset;
-  int fdSelectOffset;
-};
-
-struct Type1CPrivateDict {
-  GString *dictData;
-  int subrsOffset;
-  double defaultWidthX;
-  GBool defaultWidthXFP;
-  double nominalWidthX;
-  GBool nominalWidthXFP;
-};
-
-Type1CFontFile::Type1CFontFile(char *fileA, int lenA) {
-  int nameIdxPos, namePos, nameLen;
-
-  file = (Guchar *)fileA;
-  len = lenA;
-  name = NULL;
-  encoding = NULL;
-  ok = gFalse;
-
-  // some tools embed Type 1C fonts with an extra whitespace char at
-  // the beginning
-  if (len > 0 && file[0] != '\x01') {
-    ++file;
-    --len;
-  }
-
-  // make sure the header exists
-  if (len < 4) {
-    return;
-  }
-
-  // read name index (first font only)
-  nameIdxPos = file[2] & 0xff;
-  if ((namePos = getIndexValPos(nameIdxPos, 0, &nameLen)) < 0) {
-    return;
-  }
-  name = new GString((char *)&file[namePos], nameLen);
-
-  topDictIdxPos = getIndexEnd(nameIdxPos);
-  stringIdxPos = getIndexEnd(topDictIdxPos);
-  gsubrIdxPos = getIndexEnd(stringIdxPos);
-
-  ok = gTrue;
-}
-
-Type1CFontFile::~Type1CFontFile() {
-  int i;
-
-  delete name;
-  if (encoding) {
-    for (i = 0; i < 256; ++i) {
-      gfree(encoding[i]);
-    }
-    gfree(encoding);
-  }
-}
-
-char *Type1CFontFile::getName() {
-  return name->getCString();
-}
-
-char **Type1CFontFile::getEncoding() {
-  if (!encoding) {
-    readEncoding();
-  }
-  return encoding;
-}
-
-void Type1CFontFile::readEncoding() {
-  char buf[256];
-  int idxPos, idxLen, pos;
-  int nGlyphs;
-  int nCodes, nRanges, nLeft, nSups;
-  Gushort *glyphNames;
-  int charset, enc, charstrings;
-  int encFormat;
-  int c, sid;
-  double x;
-  GBool isFP;
-  int key;
-  int i, j;
-
-  encoding = (char **)gmalloc(256 * sizeof(char *));
-  for (i = 0; i < 256; ++i) {
-    encoding[i] = NULL;
-  }
-
-  // read top dict (first font only)
-  if ((idxPos = getIndexValPos(topDictIdxPos, 0, &idxLen)) < 0) {
-    return;
-  }
-  charset = enc = charstrings = 0;
-  i = 0;
-  pos = idxPos;
-  while (pos < idxPos + idxLen) {
-    if (file[pos] <= 27 || file[pos] == 31) {
-      key = file[pos++];
-      if (key == 0x0c) {
-       if (pos >= idxPos + idxLen) {
-         return;
-       }
-       key = (key << 8) | file[pos++];
-      }
-      if (key == 0x0f) { // charset
-       charset = (int)op[0];
-      } else if (key == 0x10) { // encoding
-       enc = (int)op[0];
-      } else if (key == 0x11) { // charstrings
-       charstrings = (int)op[0];
-      }
-      i = 0;
-    } else {
-      x = getNum(&pos, &isFP);
-      if (i < 48) {
-       op[i++] = x;
-      }
-    }
-  }
-
-  // get number of glyphs from charstrings index
-  nGlyphs = getIndexLen(charstrings);
-
-  // read charset (GID -> name mapping)
-  glyphNames = readCharset(charset, nGlyphs);
-
-  // read encoding (GID -> code mapping)
-  if (enc == 0) {
-    for (i = 0; i < 256; ++i) {
-      if (standardEncoding[i]) {
-       encoding[i] = copyString(standardEncoding[i]);
-      }
-    }
-  } else if (enc == 1) {
-    for (i = 0; i < 256; ++i) {
-      if (expertEncoding[i]) {
-       encoding[i] = copyString(expertEncoding[i]);
-      }
-    }
-  } else {
-    pos = enc;
-    if (pos < 0 || pos >= len) {
-      goto err0;
-    }
-    encFormat = file[pos++];
-    if ((encFormat & 0x7f) == 0) {
-      if (pos >= len) {
-       goto err0;
-      }
-      nCodes = 1 + file[pos++];
-      if (nCodes > nGlyphs) {
-       nCodes = nGlyphs;
-      }
-      if (pos + nCodes - 1 > len) {
-       goto err0;
-      }
-      for (i = 1; i < nCodes; ++i) {
-       c = file[pos++];
-       if (encoding[c]) {
-         gfree(encoding[c]);
-       }
-       encoding[c] = copyString(getString(glyphNames[i], buf));
-      }
-    } else if ((encFormat & 0x7f) == 1) {
-      if (pos >= len) {
-       goto err0;
-      }
-      nRanges = file[pos++];
-      if (pos + 2 * nRanges > len) {
-       goto err0;
-      }
-      nCodes = 1;
-      for (i = 0; i < nRanges; ++i) {
-       c = file[pos++];
-       nLeft = file[pos++];
-       for (j = 0; j <= nLeft && nCodes < nGlyphs; ++j) {
-         if (c < 256) {
-           if (encoding[c]) {
-             gfree(encoding[c]);
-           }
-           encoding[c] = copyString(getString(glyphNames[nCodes], buf));
-         }
-         ++nCodes;
-         ++c;
-       }
-      }
-    }
-    if (encFormat & 0x80) {
-      if (pos >= len) {
-       goto err0;
-      }
-      nSups = file[pos++];
-      if (pos + nSups * 3 > len) {
-       goto err0;
-      }
-      for (i = 0; i < nSups; ++i) {
-       c = file[pos++];
-       sid = getWord(pos, 2);
-       pos += 2;
-       if (encoding[c]) {
-         gfree(encoding[c]);
-       }
-       encoding[c] = copyString(getString(sid, buf));
-      }
-    }
-  }
-
- err0:
-  if (charset < 0 || charset > 2) {
-    gfree(glyphNames);
-  }
-}
-
-void Type1CFontFile::convertToType1(FontFileOutputFunc outputFuncA,
-                                   void *outputStreamA) {
-  Type1CTopDict dict;
-  Type1CPrivateDict privateDict;
-  char buf[512], eBuf[256];
-  int idxPos, idxLen, pos;
-  int nGlyphs, nCodes, nRanges, nLeft, nSups;
-  Gushort *glyphNames;
-  int encFormat, nCharStrings;
-  int c, sid;
-  int i, j;
-
-  outputFunc = outputFuncA;
-  outputStream = outputStreamA;
-
-  // read top dict (first font only)
-  readTopDict(&dict);
-
-  // write header and font dictionary, up to encoding
-  (*outputFunc)(outputStream, "%!FontType1-1.0: ", 17);
-  (*outputFunc)(outputStream, name->getCString(), name->getLength());
-  if (dict.version != 0) {
-    getString(dict.version, buf);
-    (*outputFunc)(outputStream, buf, strlen(buf));
-  }
-  (*outputFunc)(outputStream, "\n", 1);
-  // the dictionary needs room for 12 entries: the following 9, plus
-  // Private and CharStrings (in the eexec section) and FID (which is
-  // added by definefont)
-  (*outputFunc)(outputStream, "12 dict begin\n", 14);
-  (*outputFunc)(outputStream, "/FontInfo 10 dict dup begin\n", 28);
-  if (dict.version != 0) {
-    (*outputFunc)(outputStream, "/version (", 10);
-    (*outputFunc)(outputStream, buf, strlen(buf));
-    (*outputFunc)(outputStream, ") readonly def\n", 15);
-  }
-  if (dict.notice != 0) {
-    getString(dict.notice, buf);
-    (*outputFunc)(outputStream, "/Notice (", 9);
-    (*outputFunc)(outputStream, buf, strlen(buf));
-    (*outputFunc)(outputStream, ") readonly def\n", 15);
-  }
-  if (dict.copyright != 0) {
-    getString(dict.copyright, buf);
-    (*outputFunc)(outputStream, "/Copyright (", 12);
-    (*outputFunc)(outputStream, buf, strlen(buf));
-    (*outputFunc)(outputStream, ") readonly def\n", 15);
-  }
-  if (dict.fullName != 0) {
-    getString(dict.fullName, buf);
-    (*outputFunc)(outputStream, "/FullName (", 11);
-    (*outputFunc)(outputStream, buf, strlen(buf));
-    (*outputFunc)(outputStream, ") readonly def\n", 15);
-  }
-  if (dict.familyName != 0) {
-    getString(dict.familyName, buf);
-    (*outputFunc)(outputStream, "/FamilyName (", 13);
-    (*outputFunc)(outputStream, buf, strlen(buf));
-    (*outputFunc)(outputStream, ") readonly def\n", 15);
-  }
-  if (dict.weight != 0) {
-    getString(dict.weight, buf);
-    (*outputFunc)(outputStream, "/Weight (", 9);
-    (*outputFunc)(outputStream, buf, strlen(buf));
-    (*outputFunc)(outputStream, ") readonly def\n", 15);
-  }
-  if (dict.isFixedPitch) {
-    (*outputFunc)(outputStream, "/isFixedPitch true def\n", 23);
-  } else {
-    (*outputFunc)(outputStream, "/isFixedPitch false def\n", 24);
-  }
-  sprintf(buf, "/ItalicAngle %g def\n", dict.italicAngle);
-  (*outputFunc)(outputStream, buf, strlen(buf));
-  sprintf(buf, "/UnderlinePosition %g def\n", dict.underlinePosition);
-  (*outputFunc)(outputStream, buf, strlen(buf));
-  sprintf(buf, "/UnderlineThickness %g def\n", dict.underlineThickness);
-  (*outputFunc)(outputStream, buf, strlen(buf));
-  (*outputFunc)(outputStream, "end readonly def\n", 17);
-  (*outputFunc)(outputStream, "/FontName /", 11);
-  (*outputFunc)(outputStream, name->getCString(), name->getLength());
-  (*outputFunc)(outputStream, " def\n", 5);
-  sprintf(buf, "/PaintType %d def\n", dict.paintType);
-  (*outputFunc)(outputStream, buf, strlen(buf));
-  (*outputFunc)(outputStream, "/FontType 1 def\n", 16);
-  sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] readonly def\n",
-         dict.fontMatrix[0], dict.fontMatrix[1], dict.fontMatrix[2],
-         dict.fontMatrix[3], dict.fontMatrix[4], dict.fontMatrix[5]);
-  (*outputFunc)(outputStream, buf, strlen(buf));
-  sprintf(buf, "/FontBBox [%g %g %g %g] readonly def\n",
-         dict.fontBBox[0], dict.fontBBox[1],
-         dict.fontBBox[2], dict.fontBBox[3]);
-  (*outputFunc)(outputStream, buf, strlen(buf));
-  sprintf(buf, "/StrokeWidth %g def\n", dict.strokeWidth);
-  (*outputFunc)(outputStream, buf, strlen(buf));
-  if (dict.uniqueID != 0) {
-    sprintf(buf, "/UniqueID %d def\n", dict.uniqueID);
-    (*outputFunc)(outputStream, buf, strlen(buf));
-  }
-
-  // get number of glyphs from charstrings index
-  nGlyphs = getIndexLen(dict.charStrings);
-
-  // read charset
-  glyphNames = readCharset(dict.charset, nGlyphs);
-
-  // read encoding (glyph -> code mapping), write Type 1 encoding
-  (*outputFunc)(outputStream, "/Encoding ", 10);
-  if (dict.encoding == 0) {
-    (*outputFunc)(outputStream, "StandardEncoding def\n", 21);
-  } else {
-    (*outputFunc)(outputStream, "256 array\n", 10);
-    (*outputFunc)(outputStream,
-                 "0 1 255 {1 index exch /.notdef put} for\n", 40);
-    if (dict.encoding == 1) {
-      for (i = 0; i < 256; ++i) {
-       if (expertEncoding[i]) {
-         sprintf(buf, "dup %d /%s put\n", i, expertEncoding[i]);
-         (*outputFunc)(outputStream, buf, strlen(buf));
-       }
-      }
-    } else {
-      pos = dict.encoding;
-      if (pos < 0 || pos >= len) {
-       goto err0;
-      }
-      encFormat = file[pos++];
-      if ((encFormat & 0x7f) == 0) {
-       if (pos >= len) {
-         goto err0;
-       }
-       nCodes = 1 + file[pos++];
-       if (nCodes > nGlyphs) {
-         nCodes = nGlyphs;
-       }
-       if (pos + nCodes - 1 > len) {
-         goto err0;
-       }
-       for (i = 1; i < nCodes; ++i) {
-         c = file[pos++];
-         sprintf(buf, "dup %d /", c);
-         (*outputFunc)(outputStream, buf, strlen(buf));
-         getString(glyphNames[i], buf);
-         (*outputFunc)(outputStream, buf, strlen(buf));
-         (*outputFunc)(outputStream, " put\n", 5);
-       }
-      } else if ((encFormat & 0x7f) == 1) {
-       if (pos >= len) {
-         goto err0;
-       }
-       nRanges = file[pos++];
-       if (pos + 2 * nRanges > len) {
-         goto err0;
-       }
-       nCodes = 1;
-       for (i = 0; i < nRanges; ++i) {
-         c = file[pos++];
-         nLeft = file[pos++];
-         for (j = 0; j <= nLeft && nCodes < nGlyphs; ++j) {
-           sprintf(buf, "dup %d /", c);
-           (*outputFunc)(outputStream, buf, strlen(buf));
-           getString(glyphNames[nCodes], buf);
-           (*outputFunc)(outputStream, buf, strlen(buf));
-           (*outputFunc)(outputStream, " put\n", 5);
-           ++nCodes;
-           ++c;
-         }
-       }
-      }
-      if (encFormat & 0x80) {
-       if (pos >= len) {
-         goto err0;
-       }
-       nSups = file[pos++];
-       if (pos + nSups * 3 > len) {
-         goto err0;
-       }
-       for (i = 0; i < nSups; ++i) {
-         c = file[pos++];
-         sid = getWord(pos, 2);
-         pos += 2;
-         sprintf(buf, "dup %d /", c);
-         (*outputFunc)(outputStream, buf, strlen(buf));
-         getString(sid, buf);
-         (*outputFunc)(outputStream, buf, strlen(buf));
-         (*outputFunc)(outputStream, " put\n", 5);
-       }
-      }
-     err0:;
-    }
-    (*outputFunc)(outputStream, "readonly def\n", 13);
-  }
-  (*outputFunc)(outputStream, "currentdict end\n", 16);
-
-  // start the binary section
-  (*outputFunc)(outputStream, "currentfile eexec\n", 18);
-  r1 = 55665;
-  line = 0;
-
-  // get private dictionary
-  eexecWrite("\x83\xca\x73\xd5");
-  eexecWrite("dup /Private 32 dict dup begin\n");
-  eexecWrite("/RD {string currentfile exch readstring pop} executeonly def\n");
-  eexecWrite("/ND {noaccess def} executeonly def\n");
-  eexecWrite("/NP {noaccess put} executeonly def\n");
-  eexecWrite("/MinFeature {16 16} def\n");
-  eexecWrite("/password 5839 def\n");
-  readPrivateDict(&privateDict, dict.privateOffset, dict.privateSize);
-  eexecWrite(privateDict.dictData->getCString());
-  defaultWidthX = privateDict.defaultWidthX;
-  defaultWidthXFP = privateDict.defaultWidthXFP;
-  nominalWidthX = privateDict.nominalWidthX;
-  nominalWidthXFP = privateDict.nominalWidthXFP;
-
-  // set up subroutines
-  subrIdxPos = privateDict.subrsOffset;
-  i = getIndexLen(gsubrIdxPos);
-  gsubrBias = (i < 1240) ? 107 : (i < 33900) ? 1131 : 32768;
-  i = getIndexLen(subrIdxPos);
-  subrBias = (i < 1240) ? 107 : (i < 33900) ? 1131 : 32768;
-
-  // get CharStrings
-  nCharStrings = getIndexLen(dict.charStrings);
-  sprintf(eBuf, "2 index /CharStrings %d dict dup begin\n", nCharStrings);
-  eexecWrite(eBuf);
-  for (i = 0; i < nCharStrings; ++i) {
-    if ((idxPos = getIndexValPos(dict.charStrings, i, &idxLen)) >= 0) {
-      eexecCvtGlyph(getString(glyphNames[i], buf), idxPos, idxLen);
-    }
-  }
-  eexecWrite("end\n");
-  eexecWrite("end\n");
-  eexecWrite("readonly put\n");
-  eexecWrite("noaccess put\n");
-  eexecWrite("dup /FontName get exch definefont pop\n");
-  eexecWrite("mark currentfile closefile\n");
-
-  // trailer
-  if (line > 0) {
-    (*outputFunc)(outputStream, "\n", 1);
-  }
-  for (i = 0; i < 8; ++i) {
-    (*outputFunc)(outputStream, "0000000000000000000000000000000000000000000000000000000000000000\n", 65);
-  }
-  (*outputFunc)(outputStream, "cleartomark\n", 12);
-
-  // clean up
-  delete privateDict.dictData;
-  if (dict.charset > 2) {
-    gfree(glyphNames);
-  }
-}
-
-void Type1CFontFile::convertToCIDType0(char *psName,
-                                      FontFileOutputFunc outputFuncA,
-                                      void *outputStreamA) {
-  Type1CTopDict dict;
-  Type1CPrivateDict *privateDicts;
-  GString *charStrings;
-  int *charStringOffsets;
-  Gushort *charset;
-  int *cidMap;
-  Guchar *fdSelect;
-  int idxPos, idxLen, pos;
-  char buf[512], buf2[16];
-  int nGlyphs, nCIDs, gdBytes, nFDs;
-  int fdSelectFmt, nRanges, gid0, gid1, fd, offset;
-  int key;
-  double x;
-  GBool isFP;
-  int i, j, k, n;
-
-  outputFunc = outputFuncA;
-  outputStream = outputStreamA;
-
-  (*outputFunc)(outputStream, "/CIDInit /ProcSet findresource begin\n", 37);
-
-  // read top dict (first font only)
-  readTopDict(&dict);
-
-  // read the FDArray dictionaries and Private dictionaries
-  if (dict.fdArrayOffset == 0) {
-    nFDs = 1;
-    privateDicts = (Type1CPrivateDict *)
-                     gmalloc(nFDs * sizeof(Type1CPrivateDict));
-    privateDicts[0].dictData = new GString();
-    privateDicts[0].subrsOffset = 0;
-    privateDicts[0].defaultWidthX = 0;
-    privateDicts[0].defaultWidthXFP = gFalse;
-    privateDicts[0].nominalWidthX = 0;
-    privateDicts[0].nominalWidthXFP = gFalse;
-  } else {
-    if ((nFDs = getIndexLen(dict.fdArrayOffset)) < 0) {
-      goto err0;
-    }
-    privateDicts = (Type1CPrivateDict *)
-                     gmalloc(nFDs * sizeof(Type1CPrivateDict));
-    for (i = 0; i < nFDs; ++i) {
-      privateDicts[i].dictData = NULL;
-    }
-    for (i = 0; i < nFDs; ++i) {
-      privateDicts[i].dictData = NULL;
-      if ((idxPos = getIndexValPos(dict.fdArrayOffset, i, &idxLen)) < 0) {
-       goto err1;
-      }
-      pos = idxPos;
-      j = 0;
-      while (pos < idxPos + idxLen) {
-       if (file[pos] <= 27 || file[pos] == 31) {
-         key = file[pos++];
-         if (key == 0x0c) {
-           if (pos >= idxPos + idxLen) {
-             goto err1;
-           }
-           key = (key << 8) | file[pos++];
-         }
-         if (key == 0x0012) {
-           readPrivateDict(&privateDicts[i], (int)op[1], (int)op[0]);
-         }
-         j = 0;
-       } else {
-         x = getNum(&pos, &isFP);
-         if (j < 48) {
-           op[j] = x;
-           fp[j++] = isFP;
-         }
-       }
-      }
-      if (!privateDicts[i].dictData) {
-       privateDicts[i].dictData = new GString();
-       privateDicts[i].subrsOffset = 0;
-       privateDicts[i].defaultWidthX = 0;
-       privateDicts[i].defaultWidthXFP = gFalse;
-       privateDicts[i].nominalWidthX = 0;
-       privateDicts[i].nominalWidthXFP = gFalse;
-      }
-    }
-  }
-
-  // get the glyph count
-  if ((nGlyphs = getIndexLen(dict.charStrings)) < 0) {
-    goto err1;
-  }
-
-  // read the FDSelect table
-  fdSelect = (Guchar *)gmalloc(nGlyphs);
-  if (dict.fdSelectOffset == 0) {
-    for (i = 0; i < nGlyphs; ++i) {
-      fdSelect[i] = 0;
-    }
-  } else {
-    pos = dict.fdSelectOffset;
-    if (pos < 0 || pos >= len) {
-      goto err2;
-    }
-    fdSelectFmt = file[pos++];
-    if (fdSelectFmt == 0) {
-      if (pos + nGlyphs > len) {
-       goto err2;
-      }
-      memcpy(fdSelect, file + pos, nGlyphs);
-    } else if (fdSelectFmt == 3) {
-      if (pos + 4 > len) {
-       goto err2;
-      }
-      nRanges = getWord(pos, 2);
-      pos += 2;
-      gid0 = getWord(pos, 2);
-      pos += 2;
-      if (pos + nRanges * 3 > len) {
-       goto err2;
-      }
-      for (i = 1; i <= nRanges; ++i) {
-       fd = file[pos++];
-       gid1 = getWord(pos, 2);
-       pos += 2;
-       for (j = gid0; j < gid1; ++j) {
-         fdSelect[j] = fd;
-       }
-       gid0 = gid1;
-      }
-    } else {
-      error(-1, "Unknown FDSelect table format in CID font");
-      for (i = 0; i < nGlyphs; ++i) {
-       fdSelect[i] = 0;
-      }
-    }
-  }
-
-  // read the charset, compute the CID-to-GID mapping
-  charset = readCharset(dict.charset, nGlyphs);
-  nCIDs = 0;
-  for (i = 0; i < nGlyphs; ++i) {
-    if (charset[i] >= nCIDs) {
-      nCIDs = charset[i] + 1;
-    }
-  }
-  cidMap = (int *)gmalloc(nCIDs * sizeof(int));
-  for (i = 0; i < nCIDs; ++i) {
-    cidMap[i] = -1;
-  }
-  for (i = 0; i < nGlyphs; ++i) {
-    cidMap[charset[i]] = i;
-  }
-
-  // set up global subroutines
-  i = getIndexLen(gsubrIdxPos);
-  gsubrBias = (i < 1240) ? 107 : (i < 33900) ? 1131 : 32768;
-
-  // build the charstrings
-  charStrings = new GString();
-  charStringOffsets = (int *)gmalloc((nCIDs + 1) * sizeof(int));
-  for (i = 0; i < nCIDs; ++i) {
-    charStringOffsets[i] = charStrings->getLength();
-    if (cidMap[i] >= 0) {
-      if ((idxPos = getIndexValPos(dict.charStrings,
-                                  cidMap[i], &idxLen)) >= 0) {
-       j = fdSelect[cidMap[i]];
-       defaultWidthX = privateDicts[j].defaultWidthX;
-       defaultWidthXFP = privateDicts[j].defaultWidthXFP;
-       nominalWidthX = privateDicts[j].nominalWidthX;
-       nominalWidthXFP = privateDicts[j].nominalWidthXFP;
-       subrIdxPos = privateDicts[j].subrsOffset;
-       k = getIndexLen(subrIdxPos);
-       subrBias = (k < 1240) ? 107 : (k < 33900) ? 1131 : 32768;
-       cvtGlyph(idxPos, idxLen, gTrue);
-       charStrings->append(charBuf);
-       delete charBuf;
-      }
-    }
-  }
-  charStringOffsets[nCIDs] = charStrings->getLength();
-
-  // compute gdBytes = number of bytes needed for charstring offsets
-  // (offset size needs to account for the charstring offset table,
-  // with a worst case of five bytes per entry, plus the charstrings
-  // themselves)
-  i = (nCIDs + 1) * 5 + charStrings->getLength();
-  if (i < 0x100) {
-    gdBytes = 1;
-  } else if (i < 0x10000) {
-    gdBytes = 2;
-  } else if (i < 0x1000000) {
-    gdBytes = 3;
-  } else {
-    gdBytes = 4;
-  }
-
-  // begin the font dictionary
-  (*outputFunc)(outputStream, "20 dict begin\n", 14);
-  (*outputFunc)(outputStream, "/CIDFontName /", 14);
-  (*outputFunc)(outputStream, psName, strlen(psName));
-  (*outputFunc)(outputStream, " def\n", 5);
-  (*outputFunc)(outputStream, "/CIDFontType 0 def\n", 19);
-  (*outputFunc)(outputStream, "/CIDSystemInfo 3 dict dup begin\n", 32);
-  if (dict.registry > 0 && dict.ordering > 0) {
-    getString(dict.registry, buf);
-    (*outputFunc)(outputStream, "  /Registry (", 13);
-    (*outputFunc)(outputStream, buf, strlen(buf));
-    (*outputFunc)(outputStream, ") def\n", 6);
-    getString(dict.ordering, buf);
-    (*outputFunc)(outputStream, "  /Ordering (", 13);
-    (*outputFunc)(outputStream, buf, strlen(buf));
-    (*outputFunc)(outputStream, ") def\n", 6);
-  } else {
-    (*outputFunc)(outputStream, "  /Registry (Adobe) def\n", 24);
-    (*outputFunc)(outputStream, "  /Ordering (Identity) def\n", 27);
-  }
-  sprintf(buf, "  /Supplement %d def\n", dict.supplement);
-  (*outputFunc)(outputStream, buf, strlen(buf));
-  (*outputFunc)(outputStream, "end def\n", 8);
-  sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] def\n",
-         dict.fontMatrix[0], dict.fontMatrix[1], dict.fontMatrix[2],
-         dict.fontMatrix[3], dict.fontMatrix[4], dict.fontMatrix[5]);
-  (*outputFunc)(outputStream, buf, strlen(buf));
-  sprintf(buf, "/FontBBox [%g %g %g %g] def\n",
-         dict.fontBBox[0], dict.fontBBox[1],
-         dict.fontBBox[2], dict.fontBBox[3]);
-  (*outputFunc)(outputStream, buf, strlen(buf));
-  (*outputFunc)(outputStream, "/FontInfo 1 dict dup begin\n", 27);
-  (*outputFunc)(outputStream, "  /FSType 8 def\n", 16);
-  (*outputFunc)(outputStream, "end def\n", 8);
-
-  // CIDFont-specific entries
-  sprintf(buf, "/CIDCount %d def\n", nCIDs);
-  (*outputFunc)(outputStream, buf, strlen(buf));
-  (*outputFunc)(outputStream, "/FDBytes 1 def\n", 15);
-  sprintf(buf, "/GDBytes %d def\n", gdBytes);
-  (*outputFunc)(outputStream, buf, strlen(buf));
-  (*outputFunc)(outputStream, "/CIDMapOffset 0 def\n", 20);
-  if (dict.paintType != 0) {
-    sprintf(buf, "/PaintType %d def\n", dict.paintType);
-    (*outputFunc)(outputStream, buf, strlen(buf));
-    sprintf(buf, "/StrokeWidth %g def\n", dict.strokeWidth);
-    (*outputFunc)(outputStream, buf, strlen(buf));
-  }
-
-  // FDArray entry
-  sprintf(buf, "/FDArray %d array\n", nFDs);
-  (*outputFunc)(outputStream, buf, strlen(buf));
-  for (i = 0; i < nFDs; ++i) {
-    sprintf(buf, "dup %d 10 dict begin\n", i);
-    (*outputFunc)(outputStream, buf, strlen(buf));
-    (*outputFunc)(outputStream, "/FontType 1 def\n", 16);
-    (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
-    sprintf(buf, "/PaintType %d def\n", dict.paintType);
-    (*outputFunc)(outputStream, buf, strlen(buf));
-    (*outputFunc)(outputStream, "/Private 32 dict begin\n", 23);
-    (*outputFunc)(outputStream, privateDicts[i].dictData->getCString(),
-                 privateDicts[i].dictData->getLength());
-    (*outputFunc)(outputStream, "currentdict end def\n", 20);
-    (*outputFunc)(outputStream, "currentdict end put\n", 20);
-  }
-  (*outputFunc)(outputStream, "def\n", 4);
-
-  // start the binary section
-  offset = (nCIDs + 1) * (1 + gdBytes);
-  sprintf(buf, "(Hex) %d StartData\n",
-         offset + charStrings->getLength());
-  (*outputFunc)(outputStream, buf, strlen(buf));
-
-  // write the charstring offset (CIDMap) table
-  for (i = 0; i <= nCIDs; i += 6) {
-    for (j = 0; j < 6 && i+j <= nCIDs; ++j) {
-      if (i+j < nCIDs && cidMap[i+j] >= 0) {
-       buf[0] = (char)fdSelect[cidMap[i+j]];
-      } else {
-       buf[0] = (char)0;
-      }
-      n = offset + charStringOffsets[i+j];
-      for (k = gdBytes; k >= 1; --k) {
-       buf[k] = (char)(n & 0xff);
-       n >>= 8;
-      }
-      for (k = 0; k <= gdBytes; ++k) {
-       sprintf(buf2, "%02x", buf[k] & 0xff);
-       (*outputFunc)(outputStream, buf2, 2);
-      }
-    }
-    (*outputFunc)(outputStream, "\n", 1);
-  }
-
-  // write the charstring data
-  n = charStrings->getLength();
-  for (i = 0; i < n; i += 32) {
-    for (j = 0; j < 32 && i+j < n; ++j) {
-      sprintf(buf, "%02x", charStrings->getChar(i+j) & 0xff);
-      (*outputFunc)(outputStream, buf, strlen(buf));
-    }
-    if (i + 32 >= n) {
-      (*outputFunc)(outputStream, ">", 1);
-    }
-    (*outputFunc)(outputStream, "\n", 1);
-  }
-
-  gfree(charStringOffsets);
-  delete charStrings;
-  gfree(cidMap);
-  gfree(charset);
- err2:
-  gfree(fdSelect);
- err1:
-  for (i = 0; i < nFDs; ++i) {
-    if (privateDicts[i].dictData) {
-      delete privateDicts[i].dictData;
-    }
-  }
-  gfree(privateDicts);
- err0:;
-}
-
-void Type1CFontFile::convertToType0(char *psName,
-                                   FontFileOutputFunc outputFuncA,
-                                   void *outputStreamA) {
-  Type1CTopDict dict;
-  Type1CPrivateDict *privateDicts;
-  Gushort *charset;
-  int *cidMap;
-  Guchar *fdSelect;
-  int idxPos, idxLen, pos;
-  char buf[512];
-  char eBuf[256];
-  int nGlyphs, nCIDs, nFDs;
-  int fdSelectFmt, nRanges, gid0, gid1, fd;
-  int key;
-  double x;
-  GBool isFP;
-  int i, j;
-
-  outputFunc = outputFuncA;
-  outputStream = outputStreamA;
-
-  // read top dict (first font only)
-  readTopDict(&dict);
-
-  // read the FDArray dictionaries and Private dictionaries
-  if (dict.fdArrayOffset == 0) {
-    nFDs = 1;
-    privateDicts = (Type1CPrivateDict *)
-                     gmalloc(nFDs * sizeof(Type1CPrivateDict));
-    privateDicts[0].dictData = new GString();
-    privateDicts[0].subrsOffset = 0;
-    privateDicts[0].defaultWidthX = 0;
-    privateDicts[0].defaultWidthXFP = gFalse;
-    privateDicts[0].nominalWidthX = 0;
-    privateDicts[0].nominalWidthXFP = gFalse;
-  } else {
-    if ((nFDs = getIndexLen(dict.fdArrayOffset)) < 0) {
-      goto err0;
-    }
-    privateDicts = (Type1CPrivateDict *)
-                     gmalloc(nFDs * sizeof(Type1CPrivateDict));
-    for (i = 0; i < nFDs; ++i) {
-      privateDicts[i].dictData = NULL;
-    }
-    for (i = 0; i < nFDs; ++i) {
-      privateDicts[i].dictData = NULL;
-      if ((idxPos = getIndexValPos(dict.fdArrayOffset, i, &idxLen)) < 0) {
-       goto err1;
-      }
-      pos = idxPos;
-      j = 0;
-      while (pos < idxPos + idxLen) {
-       if (file[pos] <= 27 || file[pos] == 31) {
-         key = file[pos++];
-         if (key == 0x0c) {
-           if (pos >= idxPos + idxLen) {
-             goto err1;
-           }
-           key = (key << 8) | file[pos++];
-         }
-         if (key == 0x0012) {
-           readPrivateDict(&privateDicts[i], (int)op[1], (int)op[0]);
-         }
-         j = 0;
-       } else {
-         x = getNum(&pos, &isFP);
-         if (j < 48) {
-           op[j] = x;
-           fp[j++] = isFP;
-         }
-       }
-      }
-      if (!privateDicts[i].dictData) {
-       privateDicts[i].dictData = new GString();
-       privateDicts[i].subrsOffset = 0;
-       privateDicts[i].defaultWidthX = 0;
-       privateDicts[i].defaultWidthXFP = gFalse;
-       privateDicts[i].nominalWidthX = 0;
-       privateDicts[i].nominalWidthXFP = gFalse;
-      }
-    }
-  }
-
-  // get the glyph count
-  if ((nGlyphs = getIndexLen(dict.charStrings)) < 0) {
-    goto err1;
-  }
-
-  // read the FDSelect table
-  fdSelect = (Guchar *)gmalloc(nGlyphs);
-  if (dict.fdSelectOffset == 0) {
-    for (i = 0; i < nGlyphs; ++i) {
-      fdSelect[i] = 0;
-    }
-  } else {
-    pos = dict.fdSelectOffset;
-    if (pos < 0 || pos >= len) {
-      goto err2;
-    }
-    fdSelectFmt = file[pos++];
-    if (fdSelectFmt == 0) {
-      if (pos + nGlyphs > len) {
-       goto err2;
-      }
-      memcpy(fdSelect, file + pos, nGlyphs);
-    } else if (fdSelectFmt == 3) {
-      if (pos + 4 > len) {
-       goto err2;
-      }
-      nRanges = getWord(pos, 2);
-      pos += 2;
-      gid0 = getWord(pos, 2);
-      pos += 2;
-      if (pos + nRanges * 3 > len) {
-       goto err2;
-      }
-      for (i = 1; i <= nRanges; ++i) {
-       fd = file[pos++];
-       gid1 = getWord(pos, 2);
-       pos += 2;
-       for (j = gid0; j < gid1; ++j) {
-         fdSelect[j] = fd;
-       }
-       gid0 = gid1;
-      }
-    } else {
-      error(-1, "Unknown FDSelect table format in CID font");
-      for (i = 0; i < nGlyphs; ++i) {
-       fdSelect[i] = 0;
-      }
-    }
-  }
-
-  // read the charset, compute the CID-to-GID mapping
-  charset = readCharset(dict.charset, nGlyphs);
-  nCIDs = 0;
-  for (i = 0; i < nGlyphs; ++i) {
-    if (charset[i] >= nCIDs) {
-      nCIDs = charset[i] + 1;
-    }
-  }
-  cidMap = (int *)gmalloc(nCIDs * sizeof(int));
-  for (i = 0; i < nCIDs; ++i) {
-    cidMap[i] = -1;
-  }
-  for (i = 0; i < nGlyphs; ++i) {
-    cidMap[charset[i]] = i;
-  }
-
-  // set up global subroutines
-  i = getIndexLen(gsubrIdxPos);
-  gsubrBias = (i < 1240) ? 107 : (i < 33900) ? 1131 : 32768;
-
-  // write the descendant Type 1 fonts
-  for (i = 0; i < nCIDs; i += 256) {
-
-    //~ this assumes that all CIDs in this block have the same FD --
-    //~ to handle multiple FDs correctly, need to somehow divide the
-    //~ font up by FD
-    fd = 0;
-    for (j = 0; j < 256 && i+j < nCIDs; ++j) {
-      if (cidMap[i+j] >= 0) {
-       fd = fdSelect[cidMap[i+j]];
-       break;
-      }
-    }
-
-    // font dictionary (unencrypted section)
-    (*outputFunc)(outputStream, "16 dict begin\n", 14);
-    (*outputFunc)(outputStream, "/FontName /", 11);
-    (*outputFunc)(outputStream, psName, strlen(psName));
-    sprintf(buf, "_%02x def\n", i >> 8);
-    (*outputFunc)(outputStream, buf, strlen(buf));
-    (*outputFunc)(outputStream, "/FontType 1 def\n", 16);
-    sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] def\n",
-           dict.fontMatrix[0], dict.fontMatrix[1], dict.fontMatrix[2],
-           dict.fontMatrix[3], dict.fontMatrix[4], dict.fontMatrix[5]);
-    (*outputFunc)(outputStream, buf, strlen(buf));
-    sprintf(buf, "/FontBBox [%g %g %g %g] def\n",
-           dict.fontBBox[0], dict.fontBBox[1],
-           dict.fontBBox[2], dict.fontBBox[3]);
-    (*outputFunc)(outputStream, buf, strlen(buf));
-    sprintf(buf, "/PaintType %d def\n", dict.paintType);
-    (*outputFunc)(outputStream, buf, strlen(buf));
-    if (dict.paintType != 0) {
-      sprintf(buf, "/StrokeWidth %g def\n", dict.strokeWidth);
-      (*outputFunc)(outputStream, buf, strlen(buf));
-    }
-    (*outputFunc)(outputStream, "/Encoding 256 array\n", 20);
-    for (j = 0; j < 256 && i+j < nCIDs; ++j) {
-      sprintf(buf, "dup %d /c%02x put\n", j, j);
-      (*outputFunc)(outputStream, buf, strlen(buf));
-    }
-    if (j < 256) {
-      sprintf(buf, "%d 1 255 { 1 index exch /.notdef put } for\n", j);
-      (*outputFunc)(outputStream, buf, strlen(buf));
-    }
-    (*outputFunc)(outputStream, "readonly def\n", 13);
-    (*outputFunc)(outputStream, "currentdict end\n", 16);
-
-    // start the binary section
-    (*outputFunc)(outputStream, "currentfile eexec\n", 18);
-    r1 = 55665;
-    line = 0;
-
-    // start the private dictionary
-    eexecWrite("\x83\xca\x73\xd5");
-    eexecWrite("dup /Private 32 dict dup begin\n");
-    eexecWrite("/RD {string currentfile exch readstring pop} executeonly def\n");
-    eexecWrite("/ND {noaccess def} executeonly def\n");
-    eexecWrite("/NP {noaccess put} executeonly def\n");
-    eexecWrite("/MinFeature {16 16} def\n");
-    eexecWrite("/password 5839 def\n");
-    eexecWrite(privateDicts[fd].dictData->getCString());
-    defaultWidthX = privateDicts[fd].defaultWidthX;
-    defaultWidthXFP = privateDicts[fd].defaultWidthXFP;
-    nominalWidthX = privateDicts[fd].nominalWidthX;
-    nominalWidthXFP = privateDicts[fd].nominalWidthXFP;
-
-    // set up the subroutines
-    subrIdxPos = privateDicts[fd].subrsOffset;
-    j = getIndexLen(subrIdxPos);
-    subrBias = (j < 1240) ? 107 : (j < 33900) ? 1131 : 32768;
-
-    // start the CharStrings
-    sprintf(eBuf, "2 index /CharStrings 256 dict dup begin\n");
-    eexecWrite(eBuf);
-
-    // write the .notdef CharString
-    if ((idxPos = getIndexValPos(dict.charStrings, 0, &idxLen)) >= 0) {
-      eexecCvtGlyph(".notdef", idxPos, idxLen);
-    }
-
-    // write the CharStrings
-    for (j = 0; j < 256 && i+j < nCIDs; ++j) {
-      if (cidMap[i+j] >= 0) {
-       if ((idxPos = getIndexValPos(dict.charStrings,
-                                    cidMap[i+j], &idxLen)) >= 0) {
-         sprintf(buf, "c%02x", j);
-         eexecCvtGlyph(buf, idxPos, idxLen);
-       }
-      }
-    }
-    eexecWrite("end\n");
-    eexecWrite("end\n");
-    eexecWrite("readonly put\n");
-    eexecWrite("noaccess put\n");
-    eexecWrite("dup /FontName get exch definefont pop\n");
-    eexecWrite("mark currentfile closefile\n");
-
-    // trailer
-    if (line > 0) {
-      (*outputFunc)(outputStream, "\n", 1);
-    }
-    for (j = 0; j < 8; ++j) {
-      (*outputFunc)(outputStream, "0000000000000000000000000000000000000000000000000000000000000000\n", 65);
-    }
-    (*outputFunc)(outputStream, "cleartomark\n", 12);
-  }
-
-  // write the Type 0 parent font
-  (*outputFunc)(outputStream, "16 dict begin\n", 14);
-  (*outputFunc)(outputStream, "/FontName /", 11);
-  (*outputFunc)(outputStream, psName, strlen(psName));
-  (*outputFunc)(outputStream, " def\n", 5);
-  (*outputFunc)(outputStream, "/FontType 0 def\n", 16);
-  (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
-  (*outputFunc)(outputStream, "/FMapType 2 def\n", 16);
-  (*outputFunc)(outputStream, "/Encoding [\n", 12);
-  for (i = 0; i < nCIDs; i += 256) {
-    sprintf(buf, "%d\n", i >> 8);
-    (*outputFunc)(outputStream, buf, strlen(buf));
-  }
-  (*outputFunc)(outputStream, "] def\n", 6);
-  (*outputFunc)(outputStream, "/FDepVector [\n", 14);
-  for (i = 0; i < nCIDs; i += 256) {
-    (*outputFunc)(outputStream, "/", 1);
-    (*outputFunc)(outputStream, psName, strlen(psName));
-    sprintf(buf, "_%02x findfont\n", i >> 8);
-    (*outputFunc)(outputStream, buf, strlen(buf));
-  }
-  (*outputFunc)(outputStream, "] def\n", 6);
-  (*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40);
-
-  // clean up
-  gfree(cidMap);
-  gfree(charset);
- err2:
-  gfree(fdSelect);
- err1:
-  for (i = 0; i < nFDs; ++i) {
-    if (privateDicts[i].dictData) {
-      delete privateDicts[i].dictData;
-    }
-  }
-  gfree(privateDicts);
- err0:;
-}
-
-void Type1CFontFile::readTopDict(Type1CTopDict *dict) {
-  int idxPos, idxLen, pos;
-  double x;
-  GBool isFP;
-  int key;
-  int i;
-
-  dict->version = 0;
-  dict->notice = 0;
-  dict->copyright = 0;
-  dict->fullName = 0;
-  dict->familyName = 0;
-  dict->weight = 0;
-  dict->isFixedPitch = 0;
-  dict->italicAngle = 0;
-  dict->underlinePosition = -100;
-  dict->underlineThickness = 50;
-  dict->paintType = 0;
-  dict->charstringType = 2;
-  dict->fontMatrix[0] = 0.001;
-  dict->fontMatrix[1] = 0;
-  dict->fontMatrix[2] = 0;
-  dict->fontMatrix[3] = 0.001;
-  dict->fontMatrix[4] = 0;
-  dict->fontMatrix[5] = 0;
-  dict->uniqueID = 0;
-  dict->fontBBox[0] = 0;
-  dict->fontBBox[1] = 0;
-  dict->fontBBox[2] = 0;
-  dict->fontBBox[3] = 0;
-  dict->strokeWidth = 0;
-  dict->charset = 0;
-  dict->encoding = 0;
-  dict->charStrings = 0;
-  dict->privateSize = 0;
-  dict->privateOffset = 0;
-  dict->registry = 0;
-  dict->ordering = 0;
-  dict->supplement = 0;
-  dict->fdArrayOffset = 0;
-  dict->fdSelectOffset = 0;
-  if ((idxPos = getIndexValPos(topDictIdxPos, 0, &idxLen)) < 0) {
-    return;
-  }
-  i = 0;
-  pos = idxPos;
-  while (pos < idxPos + idxLen) {
-    if (file[pos] <= 27 || file[pos] == 31) {
-      key = file[pos++];
-      if (key == 0x0c) {
-       if (pos >= idxPos + idxLen) {
-         break;
-       }
-       key = (key << 8) | file[pos++];
-      }
-      switch (key) {
-      case 0x0000: dict->version = (int)op[0]; break;
-      case 0x0001: dict->notice = (int)op[0]; break;
-      case 0x0c00: dict->copyright = (int)op[0]; break;
-      case 0x0002: dict->fullName = (int)op[0]; break;
-      case 0x0003: dict->familyName = (int)op[0]; break;
-      case 0x0004: dict->weight = (int)op[0]; break;
-      case 0x0c01: dict->isFixedPitch = (int)op[0]; break;
-      case 0x0c02: dict->italicAngle = op[0]; break;
-      case 0x0c03: dict->underlinePosition = op[0]; break;
-      case 0x0c04: dict->underlineThickness = op[0]; break;
-      case 0x0c05: dict->paintType = (int)op[0]; break;
-      case 0x0c06: dict->charstringType = (int)op[0]; break;
-      case 0x0c07: dict->fontMatrix[0] = op[0];
-                  dict->fontMatrix[1] = op[1];
-                  dict->fontMatrix[2] = op[2];
-                  dict->fontMatrix[3] = op[3];
-                  dict->fontMatrix[4] = op[4];
-                  dict->fontMatrix[5] = op[5]; break;
-      case 0x000d: dict->uniqueID = (int)op[0]; break;
-      case 0x0005: dict->fontBBox[0] = op[0];
-                  dict->fontBBox[1] = op[1];
-                  dict->fontBBox[2] = op[2];
-                  dict->fontBBox[3] = op[3]; break;
-      case 0x0c08: dict->strokeWidth = op[0]; break;
-      case 0x000f: dict->charset = (int)op[0]; break;
-      case 0x0010: dict->encoding = (int)op[0]; break;
-      case 0x0011: dict->charStrings = (int)op[0]; break;
-      case 0x0012: dict->privateSize = (int)op[0];
-                  dict->privateOffset = (int)op[1]; break;
-      case 0x0c1e: dict->registry = (int)op[0];
-                  dict->ordering = (int)op[1];
-                  dict->supplement = (int)op[2]; break;
-      case 0x0c24: dict->fdArrayOffset = (int)op[0]; break;
-      case 0x0c25: dict->fdSelectOffset = (int)op[0]; break;
-      }
-      i = 0;
-    } else {
-      x = getNum(&pos, &isFP);
-      if (i < 48) {
-       op[i] = x;
-       fp[i++] = isFP;
-      }
-    }
-  }
-}
-
-void Type1CFontFile::readPrivateDict(Type1CPrivateDict *privateDict,
-                                    int offset, int size) {
-  int pos;
-  char eBuf[256];
-  int key;
-  double x;
-  GBool isFP;
-  int i;
-
-  privateDict->dictData = new GString();
-  privateDict->subrsOffset = 0;
-  privateDict->defaultWidthX = 0;
-  privateDict->defaultWidthXFP = gFalse;
-  privateDict->nominalWidthX = 0;
-  privateDict->nominalWidthXFP = gFalse;
-  if (offset < 0 || offset + size > len) {
-    return;
-  }
-  pos = offset;
-  i = 0;
-  while (pos < offset + size) {
-    if (file[pos] <= 27 || file[pos] == 31) {
-      key = file[pos++];
-      if (key == 0x0c) {
-       if (pos >= offset + size) {
-         break;
-       }
-       key = (key << 8) | file[pos++];
-      }
-      switch (key) {
-      case 0x0006:
-       getDeltaInt(eBuf, "BlueValues", op, i);
-       privateDict->dictData->append(eBuf);
-       break;
-      case 0x0007:
-       getDeltaInt(eBuf, "OtherBlues", op, i);
-       privateDict->dictData->append(eBuf);
-       break;
-      case 0x0008:
-       getDeltaInt(eBuf, "FamilyBlues", op, i);
-       privateDict->dictData->append(eBuf);
-       break;
-      case 0x0009:
-       getDeltaInt(eBuf, "FamilyOtherBlues", op, i);
-       privateDict->dictData->append(eBuf);
-       break;
-      case 0x0c09:
-       sprintf(eBuf, "/BlueScale %g def\n", op[0]);
-       privateDict->dictData->append(eBuf);
-       break;
-      case 0x0c0a:
-       sprintf(eBuf, "/BlueShift %d def\n", (int)op[0]);
-       privateDict->dictData->append(eBuf);
-       break;
-      case 0x0c0b:
-       sprintf(eBuf, "/BlueFuzz %d def\n", (int)op[0]);
-       privateDict->dictData->append(eBuf);
-       break;
-      case 0x000a:
-       sprintf(eBuf, "/StdHW [%g] def\n", op[0]);
-       privateDict->dictData->append(eBuf);
-       break;
-      case 0x000b:
-       sprintf(eBuf, "/StdVW [%g] def\n", op[0]);
-       privateDict->dictData->append(eBuf);
-       break;
-      case 0x0c0c:
-       getDeltaReal(eBuf, "StemSnapH", op, i);
-       privateDict->dictData->append(eBuf);
-       break;
-      case 0x0c0d:
-       getDeltaReal(eBuf, "StemSnapV", op, i);
-       privateDict->dictData->append(eBuf);
-       break;
-      case 0x0c0e:
-       sprintf(eBuf, "/ForceBold %s def\n", op[0] ? "true" : "false");
-       privateDict->dictData->append(eBuf);
-       break;
-      case 0x0c0f:
-       sprintf(eBuf, "/ForceBoldThreshold %g def\n", op[0]);
-       privateDict->dictData->append(eBuf);
-       break;
-      case 0x0c11:
-       sprintf(eBuf, "/LanguageGroup %d def\n", (int)op[0]);
-       privateDict->dictData->append(eBuf);
-       break;
-      case 0x0c12:
-       sprintf(eBuf, "/ExpansionFactor %g def\n", op[0]);
-       privateDict->dictData->append(eBuf);
-       break;
-      case 0x0c13:
-       error(-1, "Got Type 1C InitialRandomSeed");
-       break;
-      case 0x0013:
-       privateDict->subrsOffset = offset + (int)op[0];
-       break;
-      case 0x0014:
-       privateDict->defaultWidthX = op[0];
-       privateDict->defaultWidthXFP = fp[0];
-       break;
-      case 0x0015:
-       privateDict->nominalWidthX = op[0];
-       privateDict->nominalWidthXFP = fp[0];
-       break;
-      default:
-       error(-1, "Unknown Type 1C private dict entry %04x", key);
-       break;
-      }
-      i = 0;
-    } else {
-      x = getNum(&pos, &isFP);
-      if (i < 48) {
-       op[i] = x;
-       fp[i++] = isFP;
-      }
-    }
-  }
-}
-
-Gushort *Type1CFontFile::readCharset(int charset, int nGlyphs) {
-  Gushort *glyphNames;
-  int pos;
-  int charsetFormat, c;
-  int nLeft, i, j;
-
-  if (charset == 0) {
-    glyphNames = type1CISOAdobeCharset;
-  } else if (charset == 1) {
-    glyphNames = type1CExpertCharset;
-  } else if (charset == 2) {
-    glyphNames = type1CExpertSubsetCharset;
-  } else {
-    glyphNames = (Gushort *)gmalloc(nGlyphs * sizeof(Gushort));
-    for (i = 0; i < nGlyphs; ++i) {
-      glyphNames[i] = 0;
-    }
-    pos = charset;
-    if (pos < 0 || pos >= len) {
-      goto err0;
-    }
-    charsetFormat = file[pos++];
-    if (charsetFormat == 0) {
-      if (pos + (nGlyphs - 1) * 2 >= len) {
-       goto err0;
-      }
-      for (i = 1; i < nGlyphs; ++i) {
-       glyphNames[i] = getWord(pos, 2);
-       pos += 2;
-      }
-    } else if (charsetFormat == 1) {
-      i = 1;
-      while (i < nGlyphs) {
-       if (pos + 3 > len) {
-         goto err0;
-       }
-       c = getWord(pos, 2);
-       pos += 2;
-       nLeft = file[pos++];
-       for (j = 0; j <= nLeft && i < nGlyphs; ++j) {
-         glyphNames[i++] = c++;
-       }
-      }
-    } else if (charsetFormat == 2) {
-      i = 1;
-      while (i < nGlyphs) {
-       if (pos + 4 > len) {
-         goto err0;
-       }
-       c = getWord(pos, 2);
-       pos += 2;
-       nLeft = getWord(pos, 2);
-       pos += 2;
-       for (j = 0; j <= nLeft && i < nGlyphs; ++j) {
-         glyphNames[i++] = c++;
-       }
-      }
-    }
-  }
- err0:
-  return glyphNames;
-}
-
-void Type1CFontFile::eexecWrite(char *s) {
-  Guchar *p;
-  Guchar x;
-
-  for (p = (Guchar *)s; *p; ++p) {
-    x = *p ^ (r1 >> 8);
-    r1 = (x + r1) * 52845 + 22719;
-    (*outputFunc)(outputStream, &hexChars[x >> 4], 1);
-    (*outputFunc)(outputStream, &hexChars[x & 0x0f], 1);
-    line += 2;
-    if (line == 64) {
-      (*outputFunc)(outputStream, "\n", 1);
-      line = 0;
-    }
-  }
-}
-
-void Type1CFontFile::eexecCvtGlyph(char *glyphName, int pos, int n) {
-  char eBuf[256];
-
-  cvtGlyph(pos, n, gTrue);
-  sprintf(eBuf, "/%s %d RD ", glyphName, charBuf->getLength());
-  eexecWrite(eBuf);
-  eexecWriteCharstring((Guchar *)charBuf->getCString(), charBuf->getLength());
-  eexecWrite(" ND\n");
-  delete charBuf;
-}
-
-void Type1CFontFile::cvtGlyph(int pos, int n, GBool top) {
-  int x;
-  int subrPos, subrLen;
-  double d, dx, dy;
-  GBool dFP;
-  Gushort r2;
-  Guchar byte;
-  int i, k;
-
-  if (pos < 0 || pos + n > len) {
-    return;
-  }
-
-  if (top) {
-    charBuf = new GString();
-    charBuf->append((char)73);
-    charBuf->append((char)58);
-    charBuf->append((char)147);
-    charBuf->append((char)134);
-    nOps = 0;
-    nHints = 0;
-    firstOp = gTrue;
-  }
-
-  i = pos;
-  while (i < pos + n) {
-    if (file[i] == 12) {
-      if (i + 2 > pos + n) {
-       break;
-      }
-      switch (file[i+1]) {
-      case 0:                  // dotsection (should be Type 1 only?)
-       // ignored
-       break;
-      case 34:                 // hflex
-       if (nOps != 7) {
-         error(-1, "Wrong number of args (%d) to Type 2 hflex", nOps);
-       }
-       eexecDumpNum(op[0], fp[0]);
-       eexecDumpNum(0, gFalse);
-       eexecDumpNum(op[1], fp[1]);
-       eexecDumpNum(op[2], fp[2]);
-       eexecDumpNum(op[3], fp[3]);
-       eexecDumpNum(0, gFalse);
-       eexecDumpOp1(8);
-       eexecDumpNum(op[4], fp[4]);
-       eexecDumpNum(0, gFalse);
-       eexecDumpNum(op[5], fp[5]);
-       eexecDumpNum(-op[2], fp[2]);
-       eexecDumpNum(op[6], fp[6]);
-       eexecDumpNum(0, gFalse);
-       eexecDumpOp1(8);
-       break;
-      case 35:                 // flex
-       if (nOps != 13) {
-         error(-1, "Wrong number of args (%d) to Type 2 flex", nOps);
-       }
-       eexecDumpNum(op[0], fp[0]);
-       eexecDumpNum(op[1], fp[1]);
-       eexecDumpNum(op[2], fp[2]);
-       eexecDumpNum(op[3], fp[3]);
-       eexecDumpNum(op[4], fp[4]);
-       eexecDumpNum(op[5], fp[5]);
-       eexecDumpOp1(8);
-       eexecDumpNum(op[6], fp[6]);
-       eexecDumpNum(op[7], fp[7]);
-       eexecDumpNum(op[8], fp[8]);
-       eexecDumpNum(op[9], fp[9]);
-       eexecDumpNum(op[10], fp[10]);
-       eexecDumpNum(op[11], fp[11]);
-       eexecDumpOp1(8);
-       break;
-      case 36:                 // hflex1
-       if (nOps != 9) {
-         error(-1, "Wrong number of args (%d) to Type 2 hflex1", nOps);
-       }
-       eexecDumpNum(op[0], fp[0]);
-       eexecDumpNum(op[1], fp[1]);
-       eexecDumpNum(op[2], fp[2]);
-       eexecDumpNum(op[3], fp[3]);
-       eexecDumpNum(op[4], fp[4]);
-       eexecDumpNum(0, gFalse);
-       eexecDumpOp1(8);
-       eexecDumpNum(op[5], fp[5]);
-       eexecDumpNum(0, gFalse);
-       eexecDumpNum(op[6], fp[6]);
-       eexecDumpNum(op[7], fp[7]);
-       eexecDumpNum(op[8], fp[8]);
-       eexecDumpNum(-(op[1] + op[3] + op[7]), fp[1] | fp[3] | fp[7]);
-       eexecDumpOp1(8);
-       break;
-      case 37:                 // flex1
-       if (nOps != 11) {
-         error(-1, "Wrong number of args (%d) to Type 2 flex1", nOps);
-       }
-       eexecDumpNum(op[0], fp[0]);
-       eexecDumpNum(op[1], fp[1]);
-       eexecDumpNum(op[2], fp[2]);
-       eexecDumpNum(op[3], fp[3]);
-       eexecDumpNum(op[4], fp[4]);
-       eexecDumpNum(op[5], fp[5]);
-       eexecDumpOp1(8);
-       eexecDumpNum(op[6], fp[6]);
-       eexecDumpNum(op[7], fp[7]);
-       eexecDumpNum(op[8], fp[8]);
-       eexecDumpNum(op[9], fp[9]);
-       dx = op[0] + op[2] + op[4] + op[6] + op[8];
-       dy = op[1] + op[3] + op[5] + op[7] + op[9];
-       if (fabs(dx) > fabs(dy)) {
-         eexecDumpNum(op[10], fp[10]);
-         eexecDumpNum(-dy, fp[1] | fp[3] | fp[5] | fp[7] | fp[9]);
-       } else {
-         eexecDumpNum(-dx, fp[0] | fp[2] | fp[4] | fp[6] | fp[8]);
-         eexecDumpNum(op[10], fp[10]);
-       }
-       eexecDumpOp1(8);
-       break;
-      case 3:                  // and
-      case 4:                  // or
-      case 5:                  // not
-      case 8:                  // store
-      case 9:                  // abs
-      case 10:                 // add
-      case 11:                 // sub
-      case 12:                 // div
-      case 13:                 // load
-      case 14:                 // neg
-      case 15:                 // eq
-      case 18:                 // drop
-      case 20:                 // put
-      case 21:                 // get
-      case 22:                 // ifelse
-      case 23:                 // random
-      case 24:                 // mul
-      case 26:                 // sqrt
-      case 27:                 // dup
-      case 28:                 // exch
-      case 29:                 // index
-      case 30:                 // roll
-       error(-1, "Unimplemented Type 2 charstring op: 12.%d", file[i+1]);
-       break;
-      default:
-       error(-1, "Illegal Type 2 charstring op: 12.%d", file[i+1]);
-       break;
-      }
-      i += 2;
-      nOps = 0;
-    } else if (file[i] == 19) {        // hintmask
-      // ignored
-      if (firstOp) {
-       cvtGlyphWidth(nOps & 1);
-       firstOp = gFalse;
-      }
-      if (nOps > 0) {
-       if (nOps & 1) {
-         error(-1, "Wrong number of args (%d) to Type 2 hintmask/vstemhm",
-               nOps);
-       }
-       nHints += nOps / 2;
-      }
-      i += 1 + ((nHints + 7) >> 3);
-      nOps = 0;
-    } else if (file[i] == 20) {        // cntrmask
-      // ignored
-      if (firstOp) {
-       cvtGlyphWidth(nOps & 1);
-       firstOp = gFalse;
-      }
-      if (nOps > 0) {
-       if (nOps & 1) {
-         error(-1, "Wrong number of args (%d) to Type 2 cntrmask/vstemhm",
-               nOps);
-       }
-       nHints += nOps / 2;
-      }
-      i += 1 + ((nHints + 7) >> 3);
-      nOps = 0;
-    } else if (file[i] == 28) {
-      if (i + 3 > len) {
-       break;
-      }
-      x = (file[i+1] << 8) + file[i+2];
-      if (x & 0x8000) {
-       x |= -1 << 15;
-      }
-      if (nOps < 48) {
-       fp[nOps] = gFalse;
-       op[nOps++] = x;
-      }
-      i += 3;
-    } else if (file[i] == 10) {        // callsubr
-      if (nOps >= 1) {
-       k = subrBias + (int)op[nOps - 1];
-       --nOps;
-       if ((subrPos = getIndexValPos(subrIdxPos, k, &subrLen)) >= 0) {
-         cvtGlyph(subrPos, subrLen, gFalse);
-       }
-      } else {
-       error(-1, "Too few args to Type 2 callsubr");
-      }
-      // don't clear the stack
-      ++i;
-    } else if (file[i] == 29) {        // callgsubr
-      if (nOps >= 1) {
-       k = gsubrBias + (int)op[nOps - 1];
-       --nOps;
-       if ((subrPos = getIndexValPos(gsubrIdxPos, k, &subrLen)) >= 0) {
-         cvtGlyph(subrPos, subrLen, gFalse);
-       }
-      } else {
-       error(-1, "Too few args to Type 2 callgsubr");
-      }
-      // don't clear the stack
-      ++i;
-    } else if (file[i] == 11) {        // return
-      // don't clear the stack
-      ++i;
-    } else if (file[i] <= 31) {
-      switch (file[i]) {
-      case 4:                  // vmoveto
-       if (firstOp) {
-         cvtGlyphWidth(nOps == 2);
-         firstOp = gFalse;
-       }
-       if (nOps != 1) {
-         error(-1, "Wrong number of args (%d) to Type 2 vmoveto", nOps);
-       }
-       eexecDumpNum(op[0], fp[0]);
-       eexecDumpOp1(4);
-       break;
-      case 5:                  // rlineto
-       if (nOps < 2 || nOps % 2 != 0) {
-         error(-1, "Wrong number of args (%d) to Type 2 rlineto", nOps);
-       }
-       for (k = 0; k < nOps; k += 2) {
-         eexecDumpNum(op[k], fp[k]);
-         eexecDumpNum(op[k+1], fp[k+1]);
-         eexecDumpOp1(5);
-       }
-       break;
-      case 6:                  // hlineto
-       if (nOps < 1) {
-         error(-1, "Wrong number of args (%d) to Type 2 hlineto", nOps);
-       }
-       for (k = 0; k < nOps; ++k) {
-         eexecDumpNum(op[k], fp[k]);
-         eexecDumpOp1((k & 1) ? 7 : 6);
-       }
-       break;
-      case 7:                  // vlineto
-       if (nOps < 1) {
-         error(-1, "Wrong number of args (%d) to Type 2 vlineto", nOps);
-       }
-       for (k = 0; k < nOps; ++k) {
-         eexecDumpNum(op[k], fp[k]);
-         eexecDumpOp1((k & 1) ? 6 : 7);
-       }
-       break;
-      case 8:                  // rrcurveto
-       if (nOps < 6 || nOps % 6 != 0) {
-         error(-1, "Wrong number of args (%d) to Type 2 rrcurveto", nOps);
-       }
-       for (k = 0; k < nOps; k += 6) {
-         eexecDumpNum(op[k], fp[k]);
-         eexecDumpNum(op[k+1], fp[k+1]);
-         eexecDumpNum(op[k+2], fp[k+2]);
-         eexecDumpNum(op[k+3], fp[k+3]);
-         eexecDumpNum(op[k+4], fp[k+4]);
-         eexecDumpNum(op[k+5], fp[k+5]);
-         eexecDumpOp1(8);
-       }
-       break;
-      case 14:                 // endchar / seac
-       if (firstOp) {
-         cvtGlyphWidth(nOps == 1 || nOps == 5);
-         firstOp = gFalse;
-       }
-       if (nOps == 4) {
-         eexecDumpNum(0, 0);
-         eexecDumpNum(op[0], fp[0]);
-         eexecDumpNum(op[1], fp[1]);
-         eexecDumpNum(op[2], fp[2]);
-         eexecDumpNum(op[3], fp[3]);
-         eexecDumpOp2(6);
-       } else if (nOps == 0) {
-         eexecDumpOp1(14);
-       } else {
-         error(-1, "Wrong number of args (%d) to Type 2 endchar", nOps);
-       }
-       break;
-      case 21:                 // rmoveto
-       if (firstOp) {
-         cvtGlyphWidth(nOps == 3);
-         firstOp = gFalse;
-       }
-       if (nOps != 2) {
-         error(-1, "Wrong number of args (%d) to Type 2 rmoveto", nOps);
-       }
-       eexecDumpNum(op[0], fp[0]);
-       eexecDumpNum(op[1], fp[1]);
-       eexecDumpOp1(21);
-       break;
-      case 22:                 // hmoveto
-       if (firstOp) {
-         cvtGlyphWidth(nOps == 2);
-         firstOp = gFalse;
-       }
-       if (nOps != 1) {
-         error(-1, "Wrong number of args (%d) to Type 2 hmoveto", nOps);
-       }
-       eexecDumpNum(op[0], fp[0]);
-       eexecDumpOp1(22);
-       break;
-      case 24:                 // rcurveline
-       if (nOps < 8 || (nOps - 2) % 6 != 0) {
-         error(-1, "Wrong number of args (%d) to Type 2 rcurveline", nOps);
-       }
-       for (k = 0; k < nOps - 2; k += 6) {
-         eexecDumpNum(op[k], fp[k]);
-         eexecDumpNum(op[k+1], fp[k+1]);
-         eexecDumpNum(op[k+2], fp[k+2]);
-         eexecDumpNum(op[k+3], fp[k+3]);
-         eexecDumpNum(op[k+4], fp[k+4]);
-         eexecDumpNum(op[k+5], fp[k+5]);
-         eexecDumpOp1(8);
-       }
-       eexecDumpNum(op[k], fp[k]);
-       eexecDumpNum(op[k+1], fp[k]);
-       eexecDumpOp1(5);
-       break;
-      case 25:                 // rlinecurve
-       if (nOps < 8 || (nOps - 6) % 2 != 0) {
-         error(-1, "Wrong number of args (%d) to Type 2 rlinecurve", nOps);
-       }
-       for (k = 0; k < nOps - 6; k += 2) {
-         eexecDumpNum(op[k], fp[k]);
-         eexecDumpNum(op[k+1], fp[k]);
-         eexecDumpOp1(5);
-       }
-       eexecDumpNum(op[k], fp[k]);
-       eexecDumpNum(op[k+1], fp[k+1]);
-       eexecDumpNum(op[k+2], fp[k+2]);
-       eexecDumpNum(op[k+3], fp[k+3]);
-       eexecDumpNum(op[k+4], fp[k+4]);
-       eexecDumpNum(op[k+5], fp[k+5]);
-       eexecDumpOp1(8);
-       break;
-      case 26:                 // vvcurveto
-       if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
-         error(-1, "Wrong number of args (%d) to Type 2 vvcurveto", nOps);
-       }
-       if (nOps % 2 == 1) {
-         eexecDumpNum(op[0], fp[0]);
-         eexecDumpNum(op[1], fp[1]);
-         eexecDumpNum(op[2], fp[2]);
-         eexecDumpNum(op[3], fp[3]);
-         eexecDumpNum(0, gFalse);
-         eexecDumpNum(op[4], fp[4]);
-         eexecDumpOp1(8);
-         k = 5;
-       } else {
-         k = 0;
-       }
-       for (; k < nOps; k += 4) {
-         eexecDumpNum(0, gFalse);
-         eexecDumpNum(op[k], fp[k]);
-         eexecDumpNum(op[k+1], fp[k+1]);
-         eexecDumpNum(op[k+2], fp[k+2]);
-         eexecDumpNum(0, gFalse);
-         eexecDumpNum(op[k+3], fp[k+3]);
-         eexecDumpOp1(8);
-       }
-       break;
-      case 27:                 // hhcurveto
-       if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
-         error(-1, "Wrong number of args (%d) to Type 2 hhcurveto", nOps);
-       }
-       if (nOps % 2 == 1) {
-         eexecDumpNum(op[1], fp[1]);
-         eexecDumpNum(op[0], fp[0]);
-         eexecDumpNum(op[2], fp[2]);
-         eexecDumpNum(op[3], fp[3]);
-         eexecDumpNum(op[4], fp[4]);
-         eexecDumpNum(0, gFalse);
-         eexecDumpOp1(8);
-         k = 5;
-       } else {
-         k = 0;
-       }
-       for (; k < nOps; k += 4) {
-         eexecDumpNum(op[k], fp[k]);
-         eexecDumpNum(0, gFalse);
-         eexecDumpNum(op[k+1], fp[k+1]);
-         eexecDumpNum(op[k+2], fp[k+2]);
-         eexecDumpNum(op[k+3], fp[k+3]);
-         eexecDumpNum(0, gFalse);
-         eexecDumpOp1(8);
-       }
-       break;
-      case 30:                 // vhcurveto
-       if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
-         error(-1, "Wrong number of args (%d) to Type 2 vhcurveto", nOps);
-       }
-       for (k = 0; k < nOps && k != nOps-5; k += 4) {
-         if (k % 8 == 0) {
-           eexecDumpNum(op[k], fp[k]);
-           eexecDumpNum(op[k+1], fp[k+1]);
-           eexecDumpNum(op[k+2], fp[k+2]);
-           eexecDumpNum(op[k+3], fp[k+3]);
-           eexecDumpOp1(30);
-         } else {
-           eexecDumpNum(op[k], fp[k]);
-           eexecDumpNum(op[k+1], fp[k+1]);
-           eexecDumpNum(op[k+2], fp[k+2]);
-           eexecDumpNum(op[k+3], fp[k+3]);
-           eexecDumpOp1(31);
-         }
-       }
-       if (k == nOps-5) {
-         if (k % 8 == 0) {
-           eexecDumpNum(0, gFalse);
-           eexecDumpNum(op[k], fp[k]);
-           eexecDumpNum(op[k+1], fp[k+1]);
-           eexecDumpNum(op[k+2], fp[k+2]);
-           eexecDumpNum(op[k+3], fp[k+3]);
-           eexecDumpNum(op[k+4], fp[k+4]);
-         } else {
-           eexecDumpNum(op[k], fp[k]);
-           eexecDumpNum(0, gFalse);
-           eexecDumpNum(op[k+1], fp[k+1]);
-           eexecDumpNum(op[k+2], fp[k+2]);
-           eexecDumpNum(op[k+4], fp[k+4]);
-           eexecDumpNum(op[k+3], fp[k+3]);
-         }
-         eexecDumpOp1(8);
-       }
-       break;
-      case 31:                 // hvcurveto
-       if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
-         error(-1, "Wrong number of args (%d) to Type 2 hvcurveto", nOps);
-       }
-       for (k = 0; k < nOps && k != nOps-5; k += 4) {
-         if (k % 8 == 0) {
-           eexecDumpNum(op[k], fp[k]);
-           eexecDumpNum(op[k+1], fp[k+1]);
-           eexecDumpNum(op[k+2], fp[k+2]);
-           eexecDumpNum(op[k+3], fp[k+3]);
-           eexecDumpOp1(31);
-         } else {
-           eexecDumpNum(op[k], fp[k]);
-           eexecDumpNum(op[k+1], fp[k+1]);
-           eexecDumpNum(op[k+2], fp[k+2]);
-           eexecDumpNum(op[k+3], fp[k+3]);
-           eexecDumpOp1(30);
-         }
-       }
-       if (k == nOps-5) {
-         if (k % 8 == 0) {
-           eexecDumpNum(op[k], fp[k]);
-           eexecDumpNum(0, gFalse);
-           eexecDumpNum(op[k+1], fp[k+1]);
-           eexecDumpNum(op[k+2], fp[k+2]);
-           eexecDumpNum(op[k+4], fp[k+4]);
-           eexecDumpNum(op[k+3], fp[k+3]);
-         } else {
-           eexecDumpNum(0, gFalse);
-           eexecDumpNum(op[k], fp[k]);
-           eexecDumpNum(op[k+1], fp[k+1]);
-           eexecDumpNum(op[k+2], fp[k+2]);
-           eexecDumpNum(op[k+3], fp[k+3]);
-           eexecDumpNum(op[k+4], fp[k+4]);
-         }
-         eexecDumpOp1(8);
-       }
-       break;
-      case 1:                  // hstem
-       if (firstOp) {
-         cvtGlyphWidth(nOps & 1);
-         firstOp = gFalse;
-       }
-       if (nOps & 1) {
-         error(-1, "Wrong number of args (%d) to Type 2 hstem", nOps);
-       }
-       d = 0;
-       dFP = gFalse;
-       for (k = 0; k < nOps; k += 2) {
-         if (op[k+1] < 0) {
-           d += op[k] + op[k+1];
-           dFP |= fp[k] | fp[k+1];
-           eexecDumpNum(d, dFP);
-           eexecDumpNum(-op[k+1], fp[k+1]);
-         } else {
-           d += op[k];
-           dFP |= fp[k];
-           eexecDumpNum(d, dFP);
-           eexecDumpNum(op[k+1], fp[k+1]);
-           d += op[k+1];
-           dFP |= fp[k+1];
-         }
-         eexecDumpOp1(1);
-       }
-       nHints += nOps / 2;
-       break;
-      case 3:                  // vstem
-       if (firstOp) {
-         cvtGlyphWidth(nOps & 1);
-         firstOp = gFalse;
-       }
-       if (nOps & 1) {
-         error(-1, "Wrong number of args (%d) to Type 2 vstem", nOps);
-       }
-       d = 0;
-       dFP = gFalse;
-       for (k = 0; k < nOps; k += 2) {
-         if (op[k+1] < 0) {
-           d += op[k] + op[k+1];
-           dFP |= fp[k] | fp[k+1];
-           eexecDumpNum(d, dFP);
-           eexecDumpNum(-op[k+1], fp[k+1]);
-         } else {
-           d += op[k];
-           dFP |= fp[k];
-           eexecDumpNum(d, dFP);
-           eexecDumpNum(op[k+1], fp[k+1]);
-           d += op[k+1];
-           dFP |= fp[k+1];
-         }
-         eexecDumpOp1(3);
-       }
-       nHints += nOps / 2;
-       break;
-      case 15:                 // (obsolete)
-       // this op is ignored, but we need the glyph width
-       if (firstOp) {
-         cvtGlyphWidth(nOps > 0);
-         firstOp = gFalse;
-       }
-       break;
-      case 18:                 // hstemhm
-       // ignored
-       if (firstOp) {
-         cvtGlyphWidth(nOps & 1);
-         firstOp = gFalse;
-       }
-       if (nOps & 1) {
-         error(-1, "Wrong number of args (%d) to Type 2 hstemhm", nOps);
-       }
-       nHints += nOps / 2;
-       break;
-      case 23:                 // vstemhm
-       // ignored
-       if (firstOp) {
-         cvtGlyphWidth(nOps & 1);
-         firstOp = gFalse;
-       }
-       if (nOps & 1) {
-         error(-1, "Wrong number of args (%d) to Type 2 vstemhm", nOps);
-       }
-       nHints += nOps / 2;
-       break;
-      case 16:                 // blend
-       error(-1, "Unimplemented Type 2 charstring op: %d", file[i]);
-       break;
-      default:
-       error(-1, "Illegal Type 2 charstring op: %d", file[i]);
-       break;
-      }
-      ++i;
-      nOps = 0;
-    } else if (file[i] <= 246) {
-      if (nOps < 48) {
-       fp[nOps] = gFalse;
-       op[nOps++] = (int)file[i] - 139;
-      }
-      ++i;
-    } else if (file[i] <= 250) {
-      if (i + 2 > len) {
-       break;
-      }
-      if (nOps < 48) {
-       fp[nOps] = gFalse;
-       op[nOps++] = (((int)file[i] - 247) << 8) + (int)file[i+1] + 108;
-      }
-      i += 2;
-    } else if (file[i] <= 254) {
-      if (i + 2 > len) {
-       break;
-      }
-      if (nOps < 48) {
-       fp[nOps] = gFalse;
-       op[nOps++] = -(((int)file[i] - 251) << 8) - (int)file[i+1] - 108;
-      }
-      i += 2;
-    } else {
-      if (i + 5 > len) {
-       break;
-      }
-      x = (file[i+1] << 24) | (file[i+2] << 16) | (file[i+3] << 8) | file[i+4];
-      if (x & 0x80000000) {
-       x |= -1 << 31;
-      }
-      if (nOps < 48) {
-       fp[nOps] = gTrue;
-       op[nOps++] = (double)x / 65536.0;
-      }
-      i += 5;
-    }
-  }
-
-  // charstring encryption
-  if (top) {
-    r2 = 4330;
-    for (i = 0; i < charBuf->getLength(); ++i) {
-      byte = charBuf->getChar(i) ^ (r2 >> 8);
-      charBuf->setChar(i, byte);
-      r2 = (byte + r2) * 52845 + 22719;
-    }
-  }
-}
-
-void Type1CFontFile::cvtGlyphWidth(GBool useOp) {
-  double w;
-  GBool wFP;
-  int i;
-
-  if (useOp) {
-    w = nominalWidthX + op[0];
-    wFP = nominalWidthXFP | fp[0];
-    for (i = 1; i < nOps; ++i) {
-      op[i-1] = op[i];
-      fp[i-1] = fp[i];
-    }
-    --nOps;
-  } else {
-    w = defaultWidthX;
-    wFP = defaultWidthXFP;
-  }
-  eexecDumpNum(0, gFalse);
-  eexecDumpNum(w, wFP);
-  eexecDumpOp1(13);
-}
-
-void Type1CFontFile::eexecDumpNum(double x, GBool fpA) {
-  Guchar buf[12];
-  int y, n;
-
-  n = 0;
-  if (fpA) {
-    if (x >= -32768 && x < 32768) {
-      y = (int)(x * 256.0);
-      buf[0] = 255;
-      buf[1] = (Guchar)(y >> 24);
-      buf[2] = (Guchar)(y >> 16);
-      buf[3] = (Guchar)(y >> 8);
-      buf[4] = (Guchar)y;
-      buf[5] = 255;
-      buf[6] = 0;
-      buf[7] = 0;
-      buf[8] = 1;
-      buf[9] = 0;
-      buf[10] = 12;
-      buf[11] = 12;
-      n = 12;
-    } else {
-      error(-1, "Type 2 fixed point constant out of range");
-    }
-  } else {
-    y = (int)x;
-    if (y >= -107 && y <= 107) {
-      buf[0] = (Guchar)(y + 139);
-      n = 1;
-    } else if (y > 107 && y <= 1131) {
-      y -= 108;
-      buf[0] = (Guchar)((y >> 8) + 247);
-      buf[1] = (Guchar)(y & 0xff);
-      n = 2;
-    } else if (y < -107 && y >= -1131) {
-      y = -y - 108;
-      buf[0] = (Guchar)((y >> 8) + 251);
-      buf[1] = (Guchar)(y & 0xff);
-      n = 2;
-    } else {
-      buf[0] = 255;
-      buf[1] = (Guchar)(y >> 24);
-      buf[2] = (Guchar)(y >> 16);
-      buf[3] = (Guchar)(y >> 8);
-      buf[4] = (Guchar)y;
-      n = 5;
-    }
-  }
-  charBuf->append((char *)buf, n);
-}
-
-void Type1CFontFile::eexecDumpOp1(int opA) {
-  charBuf->append((char)opA);
-}
-
-void Type1CFontFile::eexecDumpOp2(int opA) {
-  charBuf->append((char)12);
-  charBuf->append((char)opA);
-}
-
-void Type1CFontFile::eexecWriteCharstring(Guchar *s, int n) {
-  Guchar x;
-  int i;
-
-  // eexec encryption
-  for (i = 0; i < n; ++i) {
-    x = s[i] ^ (r1 >> 8);
-    r1 = (x + r1) * 52845 + 22719;
-    (*outputFunc)(outputStream, &hexChars[x >> 4], 1);
-    (*outputFunc)(outputStream, &hexChars[x & 0x0f], 1);
-    line += 2;
-    if (line == 64) {
-      (*outputFunc)(outputStream, "\n", 1);
-      line = 0;
-    }
-  }
-}
-
-void Type1CFontFile::getDeltaInt(char *buf, char *key, double *opA,
-                                int n) {
-  int x, i;
-
-  sprintf(buf, "/%s [", key);
-  buf += strlen(buf);
-  x = 0;
-  for (i = 0; i < n; ++i) {
-    x += (int)opA[i];
-    sprintf(buf, "%s%d", i > 0 ? " " : "", x);
-    buf += strlen(buf);
-  }
-  sprintf(buf, "] def\n");
-}
-
-void Type1CFontFile::getDeltaReal(char *buf, char *key, double *opA,
-                                 int n) {
-  double x;
-  int i;
-
-  sprintf(buf, "/%s [", key);
-  buf += strlen(buf);
-  x = 0;
-  for (i = 0; i < n; ++i) {
-    x += opA[i];
-    sprintf(buf, "%s%g", i > 0 ? " " : "", x);
-    buf += strlen(buf);
-  }
-  sprintf(buf, "] def\n");
-}
-
-int Type1CFontFile::getIndexLen(int indexPos) {
-  if (indexPos + 2 > len) {
-    return -1;
-  }
-  return (int)getWord(indexPos, 2);
-}
-
-int Type1CFontFile::getIndexValPos(int indexPos, int i, int *valLen) {
-  int n, offSize, idxStartPos;
-  int pos0, pos1;
-
-  if (indexPos < 0 || indexPos + 3 > len) {
-    return -1;
-  }
-  n = (int)getWord(indexPos, 2);
-  if (i >= n) {
-    return -1;
-  }
-  offSize = file[indexPos + 2];
-  if (offSize < 1 || offSize > 4) {
-    return -1;
-  }
-  idxStartPos = indexPos + 3 + (n + 1) * offSize - 1;
-  if (idxStartPos >= len) {
-    return -1;
-  }
-  pos0 = idxStartPos + getWord(indexPos + 3 + i * offSize, offSize);
-  pos1 = idxStartPos + getWord(indexPos + 3 + (i + 1) * offSize, offSize);
-  if (pos0 < 0 || pos0 >= len || pos1 < pos0 || pos1 > len) {
-    return -1;
-  }
-  *valLen = pos1 - pos0;
-  return pos0;
-}
-
-int Type1CFontFile::getIndexEnd(int indexPos) {
-  int n, offSize, idxStartPos;
-
-  if (indexPos < 0 || indexPos + 3 > len) {
-    return -1;
-  }
-  n = (int)getWord(indexPos, 2);
-  offSize = file[indexPos + 2];
-  idxStartPos = indexPos + 3 + (n + 1) * offSize - 1;
-  if (idxStartPos >= len) {
-    return -1;
-  }
-  return idxStartPos + getWord(indexPos + 3 + n * offSize, offSize);
-}
-
-Guint Type1CFontFile::getWord(int pos, int size) {
-  Guint x;
-  int i;
-
-  if (pos < 0 || pos + size > len) {
-    return 0;
-  }
-  x = 0;
-  for (i = 0; i < size; ++i) {
-    x = (x << 8) + file[pos + i];
-  }
-  return x;
-}
-
-double Type1CFontFile::getNum(int *pos, GBool *isFP) {
-  static char nybChars[16] = "0123456789.ee -";
-  int b0, b, nyb0, nyb1;
-  double x;
-  char buf[65];
-  int i;
-
-  x = 0;
-  *isFP = gFalse;
-  if (*pos >= len) {
-    return 0;
-  }
-  b0 = file[*pos];
-  if (b0 < 28) {
-    x = 0;
-  } else if (b0 == 28) {
-    if (*pos + 3 <= len) {
-      x = (file[*pos + 1] << 8) + file[*pos + 2];
-      *pos += 3;
-    }
-  } else if (b0 == 29) {
-    if (*pos + 5 <= len) {
-      x = (file[*pos + 1] << 24) + (file[*pos + 2] << 16) +
-         (file[*pos + 3] << 8) + file[*pos + 4];
-      *pos += 5;
-    }
-  } else if (b0 == 30) {
-    *pos += 1;
-    i = 0;
-    do {
-      if (*pos >= len) {
-       break;
-      }
-      b = file[(*pos)++];
-      nyb0 = b >> 4;
-      nyb1 = b & 0x0f;
-      if (nyb0 == 0xf) {
-       break;
-      }
-      buf[i++] = nybChars[nyb0];
-      if (i == 64) {
-       break;
-      }
-      if (nyb0 == 0xc) {
-       buf[i++] = '-';
-      }
-      if (i == 64) {
-       break;
-      }
-      if (nyb1 == 0xf) {
-       break;
-      }
-      buf[i++] = nybChars[nyb1];
-      if (i == 64) {
-       break;
-      }
-      if (nyb1 == 0xc) {
-       buf[i++] = '-';
-      }
-    } while (i < 64);
-    buf[i] = '\0';
-    {
-      char *theLocale = setlocale(LC_NUMERIC, "C");
-      x = atof(buf);
-      setlocale(LC_NUMERIC, theLocale);
-    }
-    *isFP = gTrue;
-  } else if (b0 == 31) {
-    x = 0;
-  } else if (b0 < 247) {
-    x = b0 - 139;
-    *pos += 1;
-  } else if (b0 < 251) {
-    if (*pos + 2 <= len) {
-      x = ((b0 - 247) << 8) + file[*pos + 1] + 108;
-      *pos += 2;
-    }
-  } else {
-    if (*pos + 2 <= len) {
-      x = -((b0 - 251) << 8) - file[*pos + 1] - 108;
-      *pos += 2;
-    }
-  }
-  return x;
-}
-
-char *Type1CFontFile::getString(int sid, char *buf) {
-  int idxPos, n;
-
-  if (sid < 391) {
-    strcpy(buf, type1CStdStrings[sid]);
-  } else {
-    sid -= 391;
-    idxPos = getIndexValPos(stringIdxPos, sid, &n);
-    if (idxPos < 0 || n < 0 || n > 255 || idxPos + n > len) {
-      buf[0] = '\0';
-    } else {
-      strncpy(buf, (char *)&file[idxPos], n);
-      buf[n] = '\0';
-    }
-  }
-  return buf;
-}
-
-//------------------------------------------------------------------------
-// TrueTypeFontFile
-//------------------------------------------------------------------------
-
-//
-// Terminology
-// -----------
-//
-// character code = number used as an element of a text string
-//
-// character name = glyph name = name for a particular glyph within a
-//                  font
-//
-// glyph index = position (within some internal table in the font)
-//               where the instructions to draw a particular glyph are
-//               stored
-//
-// Type 1 fonts
-// ------------
-//
-// Type 1 fonts contain:
-//
-// Encoding: array of glyph names, maps char codes to glyph names
-//
-//           Encoding[charCode] = charName
-//
-// CharStrings: dictionary of instructions, keyed by character names,
-//              maps character name to glyph data
-//
-//              CharStrings[charName] = glyphData
-//
-// TrueType fonts
-// --------------
-//
-// TrueType fonts contain:
-//
-// 'cmap' table: mapping from character code to glyph index; there may
-//               be multiple cmaps in a TrueType font
-//
-//               cmap[charCode] = glyphIdx
-//
-// 'post' table: mapping from glyph index to glyph name
-//
-//               post[glyphIdx] = glyphName
-//
-// Type 42 fonts
-// -------------
-//
-// Type 42 fonts contain:
-//
-// Encoding: array of glyph names, maps char codes to glyph names
-//
-//           Encoding[charCode] = charName
-//
-// CharStrings: dictionary of glyph indexes, keyed by character names,
-//              maps character name to glyph index
-//
-//              CharStrings[charName] = glyphIdx
-//
-
-struct TTFontTableHdr {
-  char tag[4];
-  Guint checksum;
-  Guint offset;
-  Guint length;
-};
-
-struct T42Table {
-  char *tag;                   // 4-byte tag
-  GBool required;              // required by the TrueType spec?
-};
-
-struct TTFontCmap {
-  int platform;
-  int encoding;
-  int offset;
-  int len;
-  int fmt;
-};
-
-// TrueType tables to be embedded in Type 42 fonts.
-// NB: the table names must be in alphabetical order here.
-#define nT42Tables 11
-static T42Table t42Tables[nT42Tables] = {
-  { "cvt ", gTrue  },
-  { "fpgm", gTrue  },
-  { "glyf", gTrue  },
-  { "head", gTrue  },
-  { "hhea", gTrue  },
-  { "hmtx", gTrue  },
-  { "loca", gTrue  },
-  { "maxp", gTrue  },
-  { "prep", gTrue  },
-  { "vhea", gFalse },
-  { "vmtx", gFalse }
-};
-#define t42HeadTable 3
-#define t42LocaTable 6
-#define t42GlyfTable 2
-
-// Glyph names in some arbitrary standard that Apple uses for their
-// TrueType fonts.
-static char *macGlyphNames[258] = {
-  ".notdef",
-  "null",
-  "CR",
-  "space",
-  "exclam",
-  "quotedbl",
-  "numbersign",
-  "dollar",
-  "percent",
-  "ampersand",
-  "quotesingle",
-  "parenleft",
-  "parenright",
-  "asterisk",
-  "plus",
-  "comma",
-  "hyphen",
-  "period",
-  "slash",
-  "zero",
-  "one",
-  "two",
-  "three",
-  "four",
-  "five",
-  "six",
-  "seven",
-  "eight",
-  "nine",
-  "colon",
-  "semicolon",
-  "less",
-  "equal",
-  "greater",
-  "question",
-  "at",
-  "A",
-  "B",
-  "C",
-  "D",
-  "E",
-  "F",
-  "G",
-  "H",
-  "I",
-  "J",
-  "K",
-  "L",
-  "M",
-  "N",
-  "O",
-  "P",
-  "Q",
-  "R",
-  "S",
-  "T",
-  "U",
-  "V",
-  "W",
-  "X",
-  "Y",
-  "Z",
-  "bracketleft",
-  "backslash",
-  "bracketright",
-  "asciicircum",
-  "underscore",
-  "grave",
-  "a",
-  "b",
-  "c",
-  "d",
-  "e",
-  "f",
-  "g",
-  "h",
-  "i",
-  "j",
-  "k",
-  "l",
-  "m",
-  "n",
-  "o",
-  "p",
-  "q",
-  "r",
-  "s",
-  "t",
-  "u",
-  "v",
-  "w",
-  "x",
-  "y",
-  "z",
-  "braceleft",
-  "bar",
-  "braceright",
-  "asciitilde",
-  "Adieresis",
-  "Aring",
-  "Ccedilla",
-  "Eacute",
-  "Ntilde",
-  "Odieresis",
-  "Udieresis",
-  "aacute",
-  "agrave",
-  "acircumflex",
-  "adieresis",
-  "atilde",
-  "aring",
-  "ccedilla",
-  "eacute",
-  "egrave",
-  "ecircumflex",
-  "edieresis",
-  "iacute",
-  "igrave",
-  "icircumflex",
-  "idieresis",
-  "ntilde",
-  "oacute",
-  "ograve",
-  "ocircumflex",
-  "odieresis",
-  "otilde",
-  "uacute",
-  "ugrave",
-  "ucircumflex",
-  "udieresis",
-  "dagger",
-  "degree",
-  "cent",
-  "sterling",
-  "section",
-  "bullet",
-  "paragraph",
-  "germandbls",
-  "registered",
-  "copyright",
-  "trademark",
-  "acute",
-  "dieresis",
-  "notequal",
-  "AE",
-  "Oslash",
-  "infinity",
-  "plusminus",
-  "lessequal",
-  "greaterequal",
-  "yen",
-  "mu1",
-  "partialdiff",
-  "summation",
-  "product",
-  "pi",
-  "integral",
-  "ordfeminine",
-  "ordmasculine",
-  "Ohm",
-  "ae",
-  "oslash",
-  "questiondown",
-  "exclamdown",
-  "logicalnot",
-  "radical",
-  "florin",
-  "approxequal",
-  "increment",
-  "guillemotleft",
-  "guillemotright",
-  "ellipsis",
-  "nbspace",
-  "Agrave",
-  "Atilde",
-  "Otilde",
-  "OE",
-  "oe",
-  "endash",
-  "emdash",
-  "quotedblleft",
-  "quotedblright",
-  "quoteleft",
-  "quoteright",
-  "divide",
-  "lozenge",
-  "ydieresis",
-  "Ydieresis",
-  "fraction",
-  "currency",
-  "guilsinglleft",
-  "guilsinglright",
-  "fi",
-  "fl",
-  "daggerdbl",
-  "periodcentered",
-  "quotesinglbase",
-  "quotedblbase",
-  "perthousand",
-  "Acircumflex",
-  "Ecircumflex",
-  "Aacute",
-  "Edieresis",
-  "Egrave",
-  "Iacute",
-  "Icircumflex",
-  "Idieresis",
-  "Igrave",
-  "Oacute",
-  "Ocircumflex",
-  "applelogo",
-  "Ograve",
-  "Uacute",
-  "Ucircumflex",
-  "Ugrave",
-  "dotlessi",
-  "circumflex",
-  "tilde",
-  "overscore",
-  "breve",
-  "dotaccent",
-  "ring",
-  "cedilla",
-  "hungarumlaut",
-  "ogonek",
-  "caron",
-  "Lslash",
-  "lslash",
-  "Scaron",
-  "scaron",
-  "Zcaron",
-  "zcaron",
-  "brokenbar",
-  "Eth",
-  "eth",
-  "Yacute",
-  "yacute",
-  "Thorn",
-  "thorn",
-  "minus",
-  "multiply",
-  "onesuperior",
-  "twosuperior",
-  "threesuperior",
-  "onehalf",
-  "onequarter",
-  "threequarters",
-  "franc",
-  "Gbreve",
-  "gbreve",
-  "Idot",
-  "Scedilla",
-  "scedilla",
-  "Cacute",
-  "cacute",
-  "Ccaron",
-  "ccaron",
-  "dmacron"
-};
-
-struct TrueTypeLoca {
-  int idx;
-  int pos;
-  int length;
-};
-
-TrueTypeFontFile::TrueTypeFontFile(char *fileA, int lenA) {
-  int pos, pos2, i, idx, n, length;
-  Guint size, startPos, endPos;
-
-  file = fileA;
-  len = lenA;
-
-  encoding = NULL;
-  cmaps = NULL;
-  nCmaps = 0;
-
-  // read table directory
-  nTables = getUShort(4);
-  tableHdrs = (TTFontTableHdr *)gmalloc(nTables * sizeof(TTFontTableHdr));
-  pos = 12;
-  for (i = 0; i < nTables; ++i) {
-    tableHdrs[i].tag[0] = getByte(pos+0);
-    tableHdrs[i].tag[1] = getByte(pos+1);
-    tableHdrs[i].tag[2] = getByte(pos+2);
-    tableHdrs[i].tag[3] = getByte(pos+3);
-    tableHdrs[i].checksum = getULong(pos+4);
-    tableHdrs[i].offset = getULong(pos+8);
-    tableHdrs[i].length = getULong(pos+12);
-    if (tableHdrs[i].offset + tableHdrs[i].length < tableHdrs[i].offset ||
-       tableHdrs[i].offset + tableHdrs[i].length > (Guint)len) {
-      tableHdrs[i].offset = (Guint)-1;
-    }
-    pos += 16;
-  }
-
-  // check for tables that are required by both the TrueType spec
-  // and the Type 42 spec
-  if (seekTable("head") < 0 ||
-      seekTable("hhea") < 0 ||
-      seekTable("loca") < 0 ||
-      seekTable("maxp") < 0 ||
-      seekTable("glyf") < 0 ||
-      seekTable("hmtx") < 0) {
-    error(-1, "TrueType font file is missing a required table");
-    return;
-  }
-
-  // some embedded TrueType fonts have an incorrect (too small) cmap
-  // table size
-  idx = seekTableIdx("cmap");
-  if (idx >= 0) {
-    pos = tableHdrs[idx].offset;
-    n = getUShort(pos + 2);
-    size = (Guint)(4 + 8 * n);
-    for (i = 0; i < n; ++i) {
-      startPos = getULong(pos + 4 + 8*i + 4);
-      length = getUShort(pos + startPos + 2);
-      endPos = startPos + length;
-      if (endPos > size) {
-       size = endPos;
-      }
-    }
-    if ((mungedCmapSize = size > tableHdrs[idx].length)) {
-#if 0 // don't bother printing this error message - it's too common
-      error(-1, "Bad cmap table size in TrueType font");
-#endif
-      tableHdrs[idx].length = size;
-    }
-  } else {
-    mungedCmapSize = gFalse;
-  }
-
-  // read the 'head' table
-  pos = seekTable("head");
-  bbox[0] = getShort(pos + 36);
-  bbox[1] = getShort(pos + 38);
-  bbox[2] = getShort(pos + 40);
-  bbox[3] = getShort(pos + 42);
-  locaFmt = getShort(pos + 50);
-
-  // read the 'maxp' table
-  pos = seekTable("maxp");
-  nGlyphs = getUShort(pos + 4);
-
-  // read the 'cmap' table
-  if ((pos = seekTable("cmap")) >= 0) {
-    pos2 = pos + 2;
-    if ((nCmaps = getUShort(pos2)) > 0) {
-      pos2 += 2;
-      cmaps = (TTFontCmap *)gmalloc(nCmaps * sizeof(TTFontCmap));
-      for (i = 0; i < nCmaps; ++i) {
-       cmaps[i].platform = getUShort(pos2);
-       cmaps[i].encoding = getUShort(pos2 + 2);
-       cmaps[i].offset = pos + getULong(pos2 + 4);
-       pos2 += 8;
-       cmaps[i].fmt = getUShort(cmaps[i].offset);
-       cmaps[i].len = getUShort(cmaps[i].offset + 2);
-      }
-    }
-  }
-}
-
-TrueTypeFontFile::~TrueTypeFontFile() {
-  int i;
-
-  if (encoding) {
-    for (i = 0; i < 256; ++i) {
-      gfree(encoding[i]);
-    }
-    gfree(encoding);
-  }
-  if (cmaps) {
-    gfree(cmaps);
-  }
-  gfree(tableHdrs);
-}
-
-char *TrueTypeFontFile::getName() {
-  return NULL;
-}
-
-char **TrueTypeFontFile::getEncoding() {
-  int i;
-
-  if (!encoding) {
-    encoding = (char **)gmalloc(256 * sizeof(char *));
-    for (i = 0; i < 256; ++i) {
-      encoding[i] = NULL;
-    }
-  }
-  return encoding;
-}
-
-int TrueTypeFontFile::getNumCmaps() {
-  return nCmaps;
-}
-
-int TrueTypeFontFile::getCmapPlatform(int i) {
-  return cmaps[i].platform;
-}
-
-int TrueTypeFontFile::getCmapEncoding(int i) {
-  return cmaps[i].encoding;
-}
-
-int TrueTypeFontFile::findCmap(int platform, int enc) {
-  int i;
-
-  for (i = 0; i < nCmaps; ++i) {
-    if (cmaps[i].platform == platform && cmaps[i].encoding == enc) {
-      return i;
-    }
-  }
-  return -1;
-}
-
-Gushort TrueTypeFontFile::mapCodeToGID(int i, int c) {
-  if (i < 0 || i >= nCmaps) {
-    return 0;
-  }
-  return (Gushort)getCmapEntry(cmaps[i].fmt, cmaps[i].offset, c);
-}
-
-GHash *TrueTypeFontFile::getNameToGID() {
-  GHash *nameToGID;
-  Guint fmt;
-  GString *s;
-  int stringIdx, stringPos, pos, i, j, n;
-
-  if ((pos = seekTable("post")) < 0) {
-    return NULL;
-  }
-
-  fmt = getULong(pos);
-  nameToGID = NULL;
-
-  // Apple font
-  if (fmt == 0x00010000) {
-    nameToGID = new GHash(gTrue);
-    for (i = 0; i < 258; ++i) {
-      nameToGID->add(new GString(macGlyphNames[i]), (void *)i);
-    }
-
-  // Microsoft font
-  } else if (fmt == 0x00020000) {
-    nameToGID = new GHash(gTrue);
-    n = getUShort(pos + 32);
-    if (n > nGlyphs) {
-      n = nGlyphs;
-    }
-    stringIdx = 0;
-    stringPos = pos + 34 + 2*nGlyphs;
-    for (i = 0; i < nGlyphs; ++i) {
-      j = getUShort(pos + 34 + 2*i);
-      if (j < 258) {
-       nameToGID->remove(macGlyphNames[j]);
-       nameToGID->add(new GString(macGlyphNames[j]), (void *)i);
-      } else {
-       j -= 258;
-       if (j != stringIdx) {
-         for (stringIdx = 0, stringPos = pos + 34 + 2*nGlyphs;
-              stringIdx < j;
-              ++stringIdx, stringPos += 1 + getByte(stringPos)) ;
-       }
-       n = getByte(stringPos);
-       if (stringPos >= 0 && stringPos + 1 + n <= len) {
-         s = new GString(file + stringPos + 1, n);
-         nameToGID->remove(s);
-         nameToGID->add(s, (void *)i);
-       }
-       ++stringIdx;
-       stringPos += 1 + n;
-      }
-    }
-
-  // Apple subset
-  } else if (fmt == 0x000280000) {
-    nameToGID = new GHash(gTrue);
-    for (i = 0; i < nGlyphs; ++i) {
-      j = getByte(pos + 32 + i);
-      if (j < 258) {
-       nameToGID->remove(macGlyphNames[j]);
-       nameToGID->add(new GString(macGlyphNames[j]), (void *)i);
-      }
-    }
-  }
-
-  return nameToGID;
-}
-
-void TrueTypeFontFile::convertToType42(char *name, char **encodingA,
-                                      GBool pdfFontHasEncoding,
-                                      Gushort *codeToGID,
-                                      FontFileOutputFunc outputFunc,
-                                      void *outputStream) {
-  char buf[512];
-
-  // write the header
-  sprintf(buf, "%%!PS-TrueTypeFont-%g\n", getFixed(0));
-  (*outputFunc)(outputStream, buf, strlen(buf));
-
-  // begin the font dictionary
-  (*outputFunc)(outputStream, "10 dict begin\n", 14);
-  (*outputFunc)(outputStream, "/FontName /", 11);
-  (*outputFunc)(outputStream, name, strlen(name));
-  (*outputFunc)(outputStream, " def\n", 5);
-  (*outputFunc)(outputStream, "/FontType 42 def\n", 17);
-  (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
-  sprintf(buf, "/FontBBox [%d %d %d %d] def\n",
-         bbox[0], bbox[1], bbox[2], bbox[3]);
-  (*outputFunc)(outputStream, buf, strlen(buf));
-  (*outputFunc)(outputStream, "/PaintType 0 def\n", 17);
-
-  // write the guts of the dictionary
-  cvtEncoding(encodingA, pdfFontHasEncoding, outputFunc, outputStream);
-  cvtCharStrings(encodingA, pdfFontHasEncoding, codeToGID,
-                outputFunc, outputStream);
-  cvtSfnts(outputFunc, outputStream, NULL);
-
-  // end the dictionary and define the font
-  (*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40);
-}
-
-void TrueTypeFontFile::convertToCIDType2(char *name, Gushort *cidMap,
-                                        int nCIDs,
-                                        FontFileOutputFunc outputFunc,
-                                        void *outputStream) {
-  char buf[512];
-  Gushort cid;
-  int i, j, k;
-
-  // write the header
-  sprintf(buf, "%%!PS-TrueTypeFont-%g\n", getFixed(0));
-  (*outputFunc)(outputStream, buf, strlen(buf));
-
-  // begin the font dictionary
-  (*outputFunc)(outputStream, "20 dict begin\n", 14);
-  (*outputFunc)(outputStream, "/CIDFontName /", 14);
-  (*outputFunc)(outputStream, name, strlen(name));
-  (*outputFunc)(outputStream, " def\n", 5);
-  (*outputFunc)(outputStream, "/CIDFontType 2 def\n", 19);
-  (*outputFunc)(outputStream, "/FontType 42 def\n", 17);
-  (*outputFunc)(outputStream, "/CIDSystemInfo 3 dict dup begin\n", 32);
-  (*outputFunc)(outputStream, "  /Registry (Adobe) def\n", 24);
-  (*outputFunc)(outputStream, "  /Ordering (Identity) def\n", 27);
-  (*outputFunc)(outputStream, "  /Supplement 0 def\n", 20);
-  (*outputFunc)(outputStream, "  end def\n", 10);
-  (*outputFunc)(outputStream, "/GDBytes 2 def\n", 15);
-  if (cidMap) {
-    sprintf(buf, "/CIDCount %d def\n", nCIDs);
-    (*outputFunc)(outputStream, buf, strlen(buf));
-    if (nCIDs > 32767) {
-      (*outputFunc)(outputStream, "/CIDMap [", 9);
-      for (i = 0; i < nCIDs; i += 32768 - 16) {
-       (*outputFunc)(outputStream, "<\n", 2);
-       for (j = 0; j < 32768 - 16 && i+j < nCIDs; j += 16) {
-         (*outputFunc)(outputStream, "  ", 2);
-         for (k = 0; k < 16 && i+j+k < nCIDs; ++k) {
-           cid = cidMap[i+j+k];
-           sprintf(buf, "%02x%02x", (cid >> 8) & 0xff, cid & 0xff);
-           (*outputFunc)(outputStream, buf, strlen(buf));
-         }
-         (*outputFunc)(outputStream, "\n", 1);
-       }
-       (*outputFunc)(outputStream, "  >", 3);
-      }
-      (*outputFunc)(outputStream, "\n", 1);
-      (*outputFunc)(outputStream, "] def\n", 6);
-    } else {
-      (*outputFunc)(outputStream, "/CIDMap <\n", 10);
-      for (i = 0; i < nCIDs; i += 16) {
-       (*outputFunc)(outputStream, "  ", 2);
-       for (j = 0; j < 16 && i+j < nCIDs; ++j) {
-         cid = cidMap[i+j];
-         sprintf(buf, "%02x%02x", (cid >> 8) & 0xff, cid & 0xff);
-         (*outputFunc)(outputStream, buf, strlen(buf));
-       }
-       (*outputFunc)(outputStream, "\n", 1);
-      }
-      (*outputFunc)(outputStream, "> def\n", 6);
-    }
-  } else {
-    // direct mapping - just fill the string(s) with s[i]=i
-    sprintf(buf, "/CIDCount %d def\n", nGlyphs);
-    (*outputFunc)(outputStream, buf, strlen(buf));
-    if (nGlyphs > 32767) {
-      (*outputFunc)(outputStream, "/CIDMap [\n", 10);
-      for (i = 0; i < nGlyphs; i += 32767) {
-       j = nGlyphs - i < 32767 ? nGlyphs - i : 32767;
-       sprintf(buf, "  %d string 0 1 %d {\n", 2 * j, j - 1);
-       (*outputFunc)(outputStream, buf, strlen(buf));
-       sprintf(buf, "    2 copy dup 2 mul exch %d add -8 bitshift put\n", i);
-       (*outputFunc)(outputStream, buf, strlen(buf));
-       sprintf(buf, "    1 index exch dup 2 mul 1 add exch %d add"
-               " 255 and put\n", i);
-       (*outputFunc)(outputStream, buf, strlen(buf));
-       (*outputFunc)(outputStream, "  } for\n", 8);
-      }
-      (*outputFunc)(outputStream, "] def\n", 6);
-    } else {
-      sprintf(buf, "/CIDMap %d string\n", 2 * nGlyphs);
-      (*outputFunc)(outputStream, buf, strlen(buf));
-      sprintf(buf, "  0 1 %d {\n", nGlyphs - 1);
-      (*outputFunc)(outputStream, buf, strlen(buf));
-      (*outputFunc)(outputStream,
-                   "    2 copy dup 2 mul exch -8 bitshift put\n", 42);
-      (*outputFunc)(outputStream,
-                   "    1 index exch dup 2 mul 1 add exch 255 and put\n", 50);
-      (*outputFunc)(outputStream, "  } for\n", 8);
-      (*outputFunc)(outputStream, "def\n", 4);
-    }
-  }
-  (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
-  sprintf(buf, "/FontBBox [%d %d %d %d] def\n",
-         bbox[0], bbox[1], bbox[2], bbox[3]);
-  (*outputFunc)(outputStream, buf, strlen(buf));
-  (*outputFunc)(outputStream, "/PaintType 0 def\n", 17);
-  (*outputFunc)(outputStream, "/Encoding [] readonly def\n", 26);
-  (*outputFunc)(outputStream, "/CharStrings 1 dict dup begin\n", 30);
-  (*outputFunc)(outputStream, "  /.notdef 0 def\n", 17);
-  (*outputFunc)(outputStream, "  end readonly def\n", 19);
-
-  // write the guts of the dictionary
-  cvtSfnts(outputFunc, outputStream, NULL);
-
-  // end the dictionary and define the font
-  (*outputFunc)(outputStream,
-               "CIDFontName currentdict end /CIDFont defineresource pop\n",
-               56);
-}
-
-void TrueTypeFontFile::convertToType0(char *name, Gushort *cidMap,
-                                     int nCIDs,
-                                     FontFileOutputFunc outputFunc,
-                                     void *outputStream) {
-  char buf[512];
-  GString *sfntsName;
-  int n, i, j;
-
-  // write the Type 42 sfnts array
-  sfntsName = (new GString(name))->append("_sfnts");
-  cvtSfnts(outputFunc, outputStream, sfntsName);
-  delete sfntsName;
-
-  // write the descendant Type 42 fonts
-  n = cidMap ? nCIDs : nGlyphs;
-  for (i = 0; i < n; i += 256) {
-    (*outputFunc)(outputStream, "10 dict begin\n", 14);
-    (*outputFunc)(outputStream, "/FontName /", 11);
-    (*outputFunc)(outputStream, name, strlen(name));
-    sprintf(buf, "_%02x def\n", i >> 8);
-    (*outputFunc)(outputStream, buf, strlen(buf));
-    (*outputFunc)(outputStream, "/FontType 42 def\n", 17);
-    (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
-    sprintf(buf, "/FontBBox [%d %d %d %d] def\n",
-           bbox[0], bbox[1], bbox[2], bbox[3]);
-    (*outputFunc)(outputStream, buf, strlen(buf));
-    (*outputFunc)(outputStream, "/PaintType 0 def\n", 17);
-    (*outputFunc)(outputStream, "/sfnts ", 7);
-    (*outputFunc)(outputStream, name, strlen(name));
-    (*outputFunc)(outputStream, "_sfnts def\n", 11);
-    (*outputFunc)(outputStream, "/Encoding 256 array\n", 20);
-    for (j = 0; j < 256 && i+j < n; ++j) {
-      sprintf(buf, "dup %d /c%02x put\n", j, j);
-      (*outputFunc)(outputStream, buf, strlen(buf));
-    }
-    (*outputFunc)(outputStream, "readonly def\n", 13);
-    (*outputFunc)(outputStream, "/CharStrings 257 dict dup begin\n", 32);
-    (*outputFunc)(outputStream, "/.notdef 0 def\n", 15);
-    for (j = 0; j < 256 && i+j < n; ++j) {
-      sprintf(buf, "/c%02x %d def\n", j, cidMap ? cidMap[i+j] : i+j);
-      (*outputFunc)(outputStream, buf, strlen(buf));
-    }
-    (*outputFunc)(outputStream, "end readonly def\n", 17);
-    (*outputFunc)(outputStream,
-                 "FontName currentdict end definefont pop\n", 40);
-  }
-
-  // write the Type 0 parent font
-  (*outputFunc)(outputStream, "16 dict begin\n", 14);
-  (*outputFunc)(outputStream, "/FontName /", 11);
-  (*outputFunc)(outputStream, name, strlen(name));
-  (*outputFunc)(outputStream, " def\n", 5);
-  (*outputFunc)(outputStream, "/FontType 0 def\n", 16);
-  (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
-  (*outputFunc)(outputStream, "/FMapType 2 def\n", 16);
-  (*outputFunc)(outputStream, "/Encoding [\n", 12);
-  for (i = 0; i < n; i += 256) {
-    sprintf(buf, "%d\n", i >> 8);
-    (*outputFunc)(outputStream, buf, strlen(buf));
-  }
-  (*outputFunc)(outputStream, "] def\n", 6);
-  (*outputFunc)(outputStream, "/FDepVector [\n", 14);
-  for (i = 0; i < n; i += 256) {
-    (*outputFunc)(outputStream, "/", 1);
-    (*outputFunc)(outputStream, name, strlen(name));
-    sprintf(buf, "_%02x findfont\n", i >> 8);
-    (*outputFunc)(outputStream, buf, strlen(buf));
-  }
-  (*outputFunc)(outputStream, "] def\n", 6);
-  (*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40);
-}
-
-int TrueTypeFontFile::getByte(int pos) {
-  if (pos < 0 || pos >= len) {
-    return 0;
-  }
-  return file[pos] & 0xff;
-}
-
-int TrueTypeFontFile::getChar(int pos) {
-  int x;
-
-  if (pos < 0 || pos >= len) {
-    return 0;
-  }
-  x = file[pos] & 0xff;
-  if (x & 0x80)
-    x |= 0xffffff00;
-  return x;
-}
-
-int TrueTypeFontFile::getUShort(int pos) {
-  int x;
-
-  if (pos < 0 || pos+1 >= len) {
-    return 0;
-  }
-  x = file[pos] & 0xff;
-  x = (x << 8) + (file[pos+1] & 0xff);
-  return x;
-}
-
-int TrueTypeFontFile::getShort(int pos) {
-  int x;
-
-  if (pos < 0 || pos+1 >= len) {
-    return 0;
-  }
-  x = file[pos] & 0xff;
-  x = (x << 8) + (file[pos+1] & 0xff);
-  if (x & 0x8000)
-    x |= 0xffff0000;
-  return x;
-}
-
-Guint TrueTypeFontFile::getULong(int pos) {
-  int x;
-
-  if (pos < 0 || pos+3 >= len) {
-    return 0;
-  }
-  x = file[pos] & 0xff;
-  x = (x << 8) + (file[pos+1] & 0xff);
-  x = (x << 8) + (file[pos+2] & 0xff);
-  x = (x << 8) + (file[pos+3] & 0xff);
-  return x;
-}
-
-double TrueTypeFontFile::getFixed(int pos) {
-  int x, y;
-
-  x = getShort(pos);
-  y = getUShort(pos+2);
-  return (double)x + (double)y / 65536;
-}
-
-int TrueTypeFontFile::seekTable(char *tag) {
-  int i;
-
-  for (i = 0; i < nTables; ++i) {
-    if (!strncmp(tableHdrs[i].tag, tag, 4)) {
-      return (int)tableHdrs[i].offset;
-    }
-  }
-  return -1;
-}
-
-int TrueTypeFontFile::seekTableIdx(char *tag) {
-  int i;
-
-  for (i = 0; i < nTables; ++i) {
-    if (!strncmp(tableHdrs[i].tag, tag, 4)) {
-      if (tableHdrs[i].offset == (Guint)-1) {
-       return -1;
-      }
-      return i;
-    }
-  }
-  return -1;
-}
-
-void TrueTypeFontFile::cvtEncoding(char **encodingA, GBool pdfFontHasEncoding,
-                                  FontFileOutputFunc outputFunc,
-                                  void *outputStream) {
-  char *name;
-  char buf[64];
-  int i;
-
-  (*outputFunc)(outputStream, "/Encoding 256 array\n", 20);
-  if (pdfFontHasEncoding) {
-    for (i = 0; i < 256; ++i) {
-      if (!(name = encodingA[i])) {
-       name = ".notdef";
-      }
-      sprintf(buf, "dup %d /", i);
-      (*outputFunc)(outputStream, buf, strlen(buf));
-      (*outputFunc)(outputStream, name, strlen(name));
-      (*outputFunc)(outputStream, " put\n", 5);
-    }
-  } else {
-    for (i = 0; i < 256; ++i) {
-      sprintf(buf, "dup %d /c%02x put\n", i, i);
-      (*outputFunc)(outputStream, buf, strlen(buf));
-    }
-  }
-  (*outputFunc)(outputStream, "readonly def\n", 13);
-}
-
-void TrueTypeFontFile::cvtCharStrings(char **encodingA,
-                                     GBool pdfFontHasEncoding,
-                                     Gushort *codeToGID,
-                                     FontFileOutputFunc outputFunc,
-                                     void *outputStream) {
-  char *name;
-  char buf[64], buf2[16];
-  int i, k;
-
-  // always define '.notdef'
-  (*outputFunc)(outputStream, "/CharStrings 256 dict dup begin\n", 32);
-  (*outputFunc)(outputStream, "/.notdef 0 def\n", 15);
-
-  // if there's no 'cmap' table, punt
-  if (nCmaps == 0) {
-    goto err;
-  }
-
-  // map char name to glyph index:
-  // 1. use encoding to map name to char code
-  // 2. use codeToGID to map char code to glyph index
-  // N.B. We do this in reverse order because font subsets can have
-  //      weird encodings that use the same character name twice, and
-  //      the first definition is probably the one we want.
-  k = 0; // make gcc happy
-  for (i = 255; i >= 0; --i) {
-    if (pdfFontHasEncoding) {
-      name = encodingA[i];
-    } else {
-      sprintf(buf2, "c%02x", i);
-      name = buf2;
-    }
-    if (name && strcmp(name, ".notdef")) {
-      k = codeToGID[i];
-      // note: Distiller (maybe Adobe's PS interpreter in general)
-      // doesn't like TrueType fonts that have CharStrings entries
-      // which point to nonexistent glyphs, hence the (k < nGlyphs)
-      // test
-      if (k > 0 && k < nGlyphs) {
-       (*outputFunc)(outputStream, "/", 1);
-       (*outputFunc)(outputStream, name, strlen(name));
-       sprintf(buf, " %d def\n", k);
-       (*outputFunc)(outputStream, buf, strlen(buf));
-      }
-    }
-  }
-
- err:
-  (*outputFunc)(outputStream, "end readonly def\n", 17);
-}
-
-int TrueTypeFontFile::getCmapEntry(int cmapFmt, int pos, int code) {
-  int cmapLen, cmapFirst;
-  int segCnt, segEnd, segStart, segDelta, segOffset;
-  int a, b, m, i;
-
-  switch (cmapFmt) {
-  case 0: // byte encoding table (Apple standard)
-    cmapLen = getUShort(pos + 2);
-    if (code >= cmapLen) {
-      return 0;
-    }
-    return getByte(pos + 6 + code);
-
-  case 4: // segment mapping to delta values (Microsoft standard)
-    segCnt = getUShort(pos + 6) / 2;
-    a = -1;
-    b = segCnt - 1;
-    segEnd = getUShort(pos + 14 + 2*b);
-    if (code > segEnd) {
-      // malformed font -- the TrueType spec requires the last segEnd
-      // to be 0xffff
-      return 0;
-    }
-    // invariant: seg[a].end < code <= seg[b].end
-    while (b - a > 1) {
-      m = (a + b) / 2;
-      segEnd = getUShort(pos + 14 + 2*m);
-      if (segEnd < code) {
-       a = m;
-      } else {
-       b = m;
-      }
-    }
-    segStart = getUShort(pos + 16 + 2*segCnt + 2*b);
-    segDelta = getUShort(pos + 16 + 4*segCnt + 2*b);
-    segOffset = getUShort(pos + 16 + 6*segCnt + 2*b);
-    if (code < segStart) {
-      return 0;
-    }
-    if (segOffset == 0) {
-      i = (code + segDelta) & 0xffff;
-    } else {
-      i = getUShort(pos + 16 + 6*segCnt + 2*b +
-                   segOffset + 2 * (code - segStart));
-      if (i != 0) {
-       i = (i + segDelta) & 0xffff;
-      }
-    }
-    return i;
-
-  case 6: // trimmed table mapping
-    cmapFirst = getUShort(pos + 6);
-    cmapLen = getUShort(pos + 8);
-    if (code < cmapFirst || code >= cmapFirst + cmapLen) {
-      return 0;
-    }
-    return getUShort(pos + 10 + 2*(code - cmapFirst));
-
-  default:
-    // shouldn't happen - this is checked earlier
-    break;
-  }
-  return 0;
-}
-
-static int cmpTrueTypeLocaIdx(const void *p1, const void *p2) {
-  return ((TrueTypeLoca *)p1)->idx - ((TrueTypeLoca *)p2)->idx;
-}
-
-static int cmpTrueTypeLocaPos(const void *p1, const void *p2) {
-  if (((TrueTypeLoca *)p1)->pos == ((TrueTypeLoca *)p2)->pos) {
-    return ((TrueTypeLoca *)p1)->idx - ((TrueTypeLoca *)p2)->idx;
-  } else {
-    return ((TrueTypeLoca *)p1)->pos - ((TrueTypeLoca *)p2)->pos;
-  }
-}
-
-void TrueTypeFontFile::cvtSfnts(FontFileOutputFunc outputFunc,
-                               void *outputStream, GString *name) {
-  TTFontTableHdr newTableHdrs[nT42Tables];
-  char tableDir[12 + nT42Tables*16];
-  char headTable[54];
-  TrueTypeLoca *origLocaTable;
-  char *locaTable;
-  int nNewTables;
-  Guint checksum;
-  int pos, glyfPos, length, glyphLength, pad;
-  int i, j, k;
-
-  // construct the 'head' table, zero out the font checksum
-  memcpy(headTable, file + seekTable("head"), 54);
-  headTable[8] = headTable[9] = headTable[10] = headTable[11] = (char)0;
-
-  // read the original 'loca' table and sort it into proper order --
-  // some (non-compliant) fonts have out-of-order loca tables; in
-  // order to correctly handle the case where (compliant) fonts have
-  // empty entries in the middle of the table, cmpTrueTypeLocaPos uses
-  // pos as its primary sort key, and idx as its secondary key
-  // (ensuring that adjacent entries with the same pos value remain in
-  // the same order)
-  origLocaTable = (TrueTypeLoca *)gmalloc((nGlyphs + 1) *
-                                         sizeof(TrueTypeLoca));
-  pos = seekTable("loca");
-  for (i = 0; i <= nGlyphs; ++i) {
-    origLocaTable[i].idx = i;
-    if (locaFmt) {
-      origLocaTable[i].pos = getULong(pos + 4*i);
-    } else {
-      origLocaTable[i].pos = 2 * getUShort(pos + 2*i);
-    }
-  }
-  qsort(origLocaTable, nGlyphs + 1, sizeof(TrueTypeLoca), &cmpTrueTypeLocaPos);
-  for (i = 0; i < nGlyphs; ++i) {
-    origLocaTable[i].length = origLocaTable[i+1].pos - origLocaTable[i].pos;
-  }
-  origLocaTable[nGlyphs].length = 0;
-  qsort(origLocaTable, nGlyphs + 1, sizeof(TrueTypeLoca), &cmpTrueTypeLocaIdx);
-
-  // construct the new 'loca' table, padding each glyph out to a
-  // multiple of 4 bytes
-  locaTable = (char *)gmalloc((nGlyphs + 1) * (locaFmt ? 4 : 2));
-  pos = 0;
-  for (i = 0; i <= nGlyphs; ++i) {
-    if (locaFmt) {
-      locaTable[4*i  ] = (char)(pos >> 24);
-      locaTable[4*i+1] = (char)(pos >> 16);
-      locaTable[4*i+2] = (char)(pos >>  8);
-      locaTable[4*i+3] = (char) pos;
-    } else {
-      locaTable[2*i  ] = (char)(pos >> 9);
-      locaTable[2*i+1] = (char)(pos >> 1);
-    }
-    length = origLocaTable[i].length;
-    if (length & 3) {
-      length += 4 - (length & 3);
-    }
-    pos += length;
-  }
-
-  // count the number of tables
-  nNewTables = 0;
-  for (i = 0; i < nT42Tables; ++i) {
-    if (t42Tables[i].required ||
-       seekTable(t42Tables[i].tag) >= 0) {
-      ++nNewTables;
-    }
-  }
-
-  // construct the new table headers, including table checksums
-  // (pad each table out to a multiple of 4 bytes)
-  pos = 12 + nNewTables*16;
-  k = 0;
-  for (i = 0; i < nT42Tables; ++i) {
-    length = -1;
-    checksum = 0; // make gcc happy
-    if (i == t42HeadTable) {
-      length = 54;
-      checksum = computeTableChecksum(headTable, 54);
-    } else if (i == t42LocaTable) {
-      length = (nGlyphs + 1) * (locaFmt ? 4 : 2);
-      checksum = computeTableChecksum(locaTable, length);
-    } else if (i == t42GlyfTable) {
-      length = 0;
-      checksum = 0;
-      glyfPos = seekTable("glyf");
-      for (j = 0; j < nGlyphs; ++j) {
-       glyphLength = origLocaTable[j].length;
-       pad = (glyphLength & 3) ? 4 - (glyphLength & 3) : 0;
-       length += glyphLength + pad;
-       if (glyphLength >= 0 &&
-           glyfPos + origLocaTable[j].pos + glyphLength <= len) {
-         checksum +=
-             computeTableChecksum(file + glyfPos + origLocaTable[j].pos,
-                                  glyphLength);
-       }
-      }
-    } else {
-      if ((j = seekTableIdx(t42Tables[i].tag)) >= 0) {
-       length = tableHdrs[j].length;
-       checksum = computeTableChecksum(file + tableHdrs[j].offset, length);
-      } else if (t42Tables[i].required) {
-       error(-1, "Embedded TrueType font is missing a required table ('%s')",
-             t42Tables[i].tag);
-       length = 0;
-       checksum = 0;
-      }
-    }
-    if (length >= 0) {
-      strncpy(newTableHdrs[k].tag, t42Tables[i].tag, 4);
-      newTableHdrs[k].checksum = checksum;
-      newTableHdrs[k].offset = pos;
-      newTableHdrs[k].length = length;
-      pad = (length & 3) ? 4 - (length & 3) : 0;
-      pos += length + pad;
-      ++k;
-    }
-  }
-
-  // construct the table directory
-  tableDir[0] = 0x00;          // sfnt version
-  tableDir[1] = 0x01;
-  tableDir[2] = 0x00;
-  tableDir[3] = 0x00;
-  tableDir[4] = 0;             // numTables
-  tableDir[5] = nNewTables;
-  tableDir[6] = 0;             // searchRange
-  tableDir[7] = (char)128;
-  tableDir[8] = 0;             // entrySelector
-  tableDir[9] = 3;
-  tableDir[10] = 0;            // rangeShift
-  tableDir[11] = (char)(16 * nNewTables - 128);
-  pos = 12;
-  for (i = 0; i < nNewTables; ++i) {
-    tableDir[pos   ] = newTableHdrs[i].tag[0];
-    tableDir[pos+ 1] = newTableHdrs[i].tag[1];
-    tableDir[pos+ 2] = newTableHdrs[i].tag[2];
-    tableDir[pos+ 3] = newTableHdrs[i].tag[3];
-    tableDir[pos+ 4] = (char)(newTableHdrs[i].checksum >> 24);
-    tableDir[pos+ 5] = (char)(newTableHdrs[i].checksum >> 16);
-    tableDir[pos+ 6] = (char)(newTableHdrs[i].checksum >>  8);
-    tableDir[pos+ 7] = (char) newTableHdrs[i].checksum;
-    tableDir[pos+ 8] = (char)(newTableHdrs[i].offset >> 24);
-    tableDir[pos+ 9] = (char)(newTableHdrs[i].offset >> 16);
-    tableDir[pos+10] = (char)(newTableHdrs[i].offset >>  8);
-    tableDir[pos+11] = (char) newTableHdrs[i].offset;
-    tableDir[pos+12] = (char)(newTableHdrs[i].length >> 24);
-    tableDir[pos+13] = (char)(newTableHdrs[i].length >> 16);
-    tableDir[pos+14] = (char)(newTableHdrs[i].length >>  8);
-    tableDir[pos+15] = (char) newTableHdrs[i].length;
-    pos += 16;
-  }
-
-  // compute the font checksum and store it in the head table
-  checksum = computeTableChecksum(tableDir, 12 + nNewTables*16);
-  for (i = 0; i < nNewTables; ++i) {
-    checksum += newTableHdrs[i].checksum;
-  }
-  checksum = 0xb1b0afba - checksum; // because the TrueType spec says so
-  headTable[ 8] = (char)(checksum >> 24);
-  headTable[ 9] = (char)(checksum >> 16);
-  headTable[10] = (char)(checksum >>  8);
-  headTable[11] = (char) checksum;
-
-  // start the sfnts array
-  if (name) {
-    (*outputFunc)(outputStream, "/", 1);
-    (*outputFunc)(outputStream, name->getCString(), name->getLength());
-    (*outputFunc)(outputStream, " [\n", 3);
-  } else {
-    (*outputFunc)(outputStream, "/sfnts [\n", 9);
-  }
-
-  // write the table directory
-  dumpString(tableDir, 12 + nNewTables*16, outputFunc, outputStream);
-
-  // write the tables
-  for (i = 0; i < nNewTables; ++i) {
-    if (i == t42HeadTable) {
-      dumpString(headTable, 54, outputFunc, outputStream);
-    } else if (i == t42LocaTable) {
-      length = (nGlyphs + 1) * (locaFmt ? 4 : 2);
-      dumpString(locaTable, length, outputFunc, outputStream);
-    } else if (i == t42GlyfTable) {
-      glyfPos = seekTable("glyf");
-      for (j = 0; j < nGlyphs; ++j) {
-       length = origLocaTable[j].length;
-       if (length > 0 &&
-           glyfPos + origLocaTable[j].pos + length <= len) {
-         dumpString(file + glyfPos + origLocaTable[j].pos, length,
-                    outputFunc, outputStream);
-       }
-      }
-    } else {
-      // length == 0 means the table is missing and the error was
-      // already reported during the construction of the table
-      // headers
-      if ((length = newTableHdrs[i].length) > 0) {
-       j = seekTable(t42Tables[i].tag);
-       if (j >= 0) {
-         dumpString(file + seekTable(t42Tables[i].tag), length,
-                    outputFunc, outputStream);
-       }
-      }
-    }
-  }
-
-  // end the sfnts array
-  (*outputFunc)(outputStream, "] def\n", 6);
-
-  gfree(origLocaTable);
-  gfree(locaTable);
-}
-
-void TrueTypeFontFile::dumpString(char *s, int length,
-                                 FontFileOutputFunc outputFunc,
-                                 void *outputStream) {
-  char buf[64];
-  int pad, i, j;
-
-  (*outputFunc)(outputStream, "<", 1);
-  for (i = 0; i < length; i += 32) {
-    for (j = 0; j < 32 && i+j < length; ++j) {
-      sprintf(buf, "%02X", s[i+j] & 0xff);
-      (*outputFunc)(outputStream, buf, strlen(buf));
-    }
-    if (i % (65536 - 32) == 65536 - 64) {
-      (*outputFunc)(outputStream, ">\n<", 3);
-    } else if (i+32 < length) {
-      (*outputFunc)(outputStream, "\n", 1);
-    }
-  }
-  if (length & 3) {
-    pad = 4 - (length & 3);
-    for (i = 0; i < pad; ++i) {
-      (*outputFunc)(outputStream, "00", 2);
-    }
-  }
-  // add an extra zero byte because the Adobe Type 42 spec says so
-  (*outputFunc)(outputStream, "00>\n", 4);
-}
-
-Guint TrueTypeFontFile::computeTableChecksum(char *data, int length) {
-  Guint checksum, word;
-  int i;
-
-  checksum = 0;
-  for (i = 0; i+3 < length; i += 4) {
-    word = ((data[i  ] & 0xff) << 24) +
-           ((data[i+1] & 0xff) << 16) +
-           ((data[i+2] & 0xff) <<  8) +
-            (data[i+3] & 0xff);
-    checksum += word;
-  }
-  if (length & 3) {
-    word = 0;
-    i = length & ~3;
-    switch (length & 3) {
-    case 3:
-      word |= (data[i+2] & 0xff) <<  8;
-    case 2:
-      word |= (data[i+1] & 0xff) << 16;
-    case 1:
-      word |= (data[i  ] & 0xff) << 24;
-      break;
-    }
-    checksum += word;
-  }
-  return checksum;
-}
-
-void TrueTypeFontFile::writeTTF(FILE *out) {
-  static char cmapTab[20] = {
-    0, 0,                      // table version number
-    0, 1,                      // number of encoding tables
-    0, 1,                      // platform ID
-    0, 0,                      // encoding ID
-    0, 0, 0, 12,               // offset of subtable
-    0, 0,                      // subtable format
-    0, 1,                      // subtable length
-    0, 1,                      // subtable version
-    0,                         // map char 0 -> glyph 0
-    0                          // pad to multiple of four bytes
-  };
-  static char nameTab[8] = {
-    0, 0,                      // format
-    0, 0,                      // number of name records
-    0, 6,                      // offset to start of string storage
-    0, 0                       // pad to multiple of four bytes
-  };
-  static char postTab[32] = {
-    0, 1, 0, 0,                        // format
-    0, 0, 0, 0,                        // italic angle
-    0, 0,                      // underline position
-    0, 0,                      // underline thickness
-    0, 0, 0, 0,                        // fixed pitch
-    0, 0, 0, 0,                        // min Type 42 memory
-    0, 0, 0, 0,                        // max Type 42 memory
-    0, 0, 0, 0,                        // min Type 1 memory
-    0, 0, 0, 0                 // max Type 1 memory
-  };
-  GBool haveCmap, haveName, havePost;
-  GBool dirCmap, dirName, dirPost;
-  GBool unsortedLoca;
-  int nNewTables, nZeroLengthTables, nAllTables;
-  TTFontTableHdr *newTableHdrs;
-  char *tableDir;
-  TrueTypeLoca *origLocaTable;
-  char *locaTable;
-  int length, glyfLength;
-  Guint t, pos, pos2, pos3;
-  int i, j, k;
-
-  // check for missing/broken tables
-  haveCmap = seekTable("cmap") >= 0;
-  haveName = seekTable("name") >= 0;
-  havePost = seekTable("post") >= 0;
-  unsortedLoca = gFalse;
-  pos = seekTable("loca");
-  pos2 = 0;
-  for (i = 0; i <= nGlyphs; ++i) {
-    if (locaFmt) {
-      pos3 = getULong(pos + 4*i);
-    } else {
-      pos3 = 2 * getUShort(pos + 2*i);
-    }
-    if (pos3 < pos2) {
-      unsortedLoca = gTrue;
-      break;
-    }
-    pos2 = pos3;
-  }
-  nNewTables = (haveCmap ? 0 : 1) + (haveName ? 0 : 1) + (havePost ? 0 : 1);
-  nZeroLengthTables = 0;
-  for (i = 0; i < nTables; ++i) {
-    if (tableHdrs[i].length == 0) {
-      ++nZeroLengthTables;
-    }
-  }
-  if (!nNewTables && !nZeroLengthTables && !mungedCmapSize && !unsortedLoca) {
-    // nothing is broken - write the TTF file as is
-    fwrite(file, 1, len, out);
-    return;
-  }
-
-  // if the glyph data isn't sorted (as listed in the 'loca' table),
-  // construct a new 'loca' table
-  if (unsortedLoca) {
-    origLocaTable = (TrueTypeLoca *)gmalloc((nGlyphs + 1) *
-                                           sizeof(TrueTypeLoca));
-    pos = seekTable("loca");
-    for (i = 0; i <= nGlyphs; ++i) {
-      origLocaTable[i].idx = i;
-      if (locaFmt) {
-       origLocaTable[i].pos = getULong(pos + 4*i);
-      } else {
-       origLocaTable[i].pos = 2 * getUShort(pos + 2*i);
-      }
-    }
-    qsort(origLocaTable, nGlyphs + 1, sizeof(TrueTypeLoca),
-         &cmpTrueTypeLocaPos);
-    for (i = 0; i < nGlyphs; ++i) {
-      origLocaTable[i].length = origLocaTable[i+1].pos - origLocaTable[i].pos;
-    }
-    origLocaTable[nGlyphs].length = 0;
-    qsort(origLocaTable, nGlyphs + 1, sizeof(TrueTypeLoca),
-         &cmpTrueTypeLocaIdx);
-    locaTable = (char *)gmalloc((nGlyphs + 1) * (locaFmt ? 4 : 2));
-    pos = 0;
-    for (i = 0; i <= nGlyphs; ++i) {
-      if (locaFmt) {
-       locaTable[4*i  ] = (char)(pos >> 24);
-       locaTable[4*i+1] = (char)(pos >> 16);
-       locaTable[4*i+2] = (char)(pos >>  8);
-       locaTable[4*i+3] = (char) pos;
-      } else {
-       locaTable[2*i  ] = (char)(pos >> 9);
-       locaTable[2*i+1] = (char)(pos >> 1);
-      }
-      length = origLocaTable[i].length;
-      if (length & 3) {
-       length += 4 - (length & 3);
-      }
-      pos += length;
-    }
-    glyfLength = pos;
-  } else {
-    origLocaTable = NULL; // make gcc happy
-    locaTable = NULL; // make gcc happy
-    glyfLength = 0; // make gcc happy
-  }
-
-  // construct the new table directory
-  nAllTables = nTables - nZeroLengthTables + nNewTables;
-  newTableHdrs = (TTFontTableHdr *)gmalloc(nAllTables *
-                                          sizeof(TTFontTableHdr));
-  dirCmap = haveCmap;
-  dirName = haveName;
-  dirPost = havePost;
-  pos = 12 + nAllTables * 16;
-  j = 0;
-  for (i = 0; i < nTables; ++i) {
-    if (!dirCmap && strncmp(tableHdrs[i].tag, "cmap", 4) > 0) {
-      memcpy(newTableHdrs[j].tag, "cmap", 4);
-      newTableHdrs[j].checksum = 0; //~ should compute the checksum
-      newTableHdrs[j].offset = pos;
-      pos += newTableHdrs[j].length = sizeof(cmapTab);
-      if (pos & 3) {
-       pos += 4 - (pos & 3);
-      }
-      ++j;
-      dirCmap = gTrue;
-    }
-    if (!dirName && strncmp(tableHdrs[i].tag, "name", 4) > 0) {
-      memcpy(newTableHdrs[j].tag, "name", 4);
-      newTableHdrs[j].checksum = 0; //~ should compute the checksum
-      newTableHdrs[j].offset = pos;
-      pos += newTableHdrs[j].length = sizeof(nameTab);
-      if (pos & 3) {
-       pos += 4 - (pos & 3);
-      }
-      ++j;
-      dirName = gTrue;
-    }
-    if (!dirPost && strncmp(tableHdrs[i].tag, "post", 4) > 0) {
-      memcpy(newTableHdrs[j].tag, "post", 4);
-      newTableHdrs[j].checksum = 0; //~ should compute the checksum
-      newTableHdrs[j].offset = pos;
-      pos += newTableHdrs[j].length = sizeof(postTab);
-      if (pos & 3) {
-       pos += 4 - (pos & 3);
-      }
-      ++j;
-      dirPost = gTrue;
-    }
-    // throw away zero-length tables - they confuse FreeType
-    if (tableHdrs[i].length > 0) {
-      memcpy(newTableHdrs[j].tag, tableHdrs[i].tag, 4);
-      newTableHdrs[j].checksum = tableHdrs[i].checksum;
-      newTableHdrs[j].offset = pos;
-      if (unsortedLoca && !strncmp(tableHdrs[i].tag, "loca", 4)) {
-       newTableHdrs[j].length = (nGlyphs + 1) * (locaFmt ? 4 : 2);
-      } else if (unsortedLoca && !strncmp(tableHdrs[i].tag, "glyf", 4)) {
-       newTableHdrs[j].length = glyfLength;
-      } else {
-       newTableHdrs[j].length = tableHdrs[i].length;
-      }
-      pos += newTableHdrs[j].length;
-      if (pos & 3) {
-       pos += 4 - (pos & 3);
-      }
-      ++j;
-    }
-  }
-  if (!dirCmap) {
-    memcpy(newTableHdrs[j].tag, "cmap", 4);
-    newTableHdrs[j].checksum = 0; //~ should compute the checksum
-    newTableHdrs[j].offset = pos;
-    pos += newTableHdrs[j].length = sizeof(cmapTab);
-    if (pos & 3) {
-      pos += 4 - (pos & 3);
-    }
-    ++j;
-  }
-  if (!dirName) {
-    memcpy(newTableHdrs[j].tag, "name", 4);
-    newTableHdrs[j].checksum = 0; //~ should compute the checksum
-    newTableHdrs[j].offset = pos;
-    pos += newTableHdrs[j].length = sizeof(nameTab);
-    if (pos & 3) {
-      pos += 4 - (pos & 3);
-    }
-    ++j;
-  }
-  if (!dirPost) {
-    memcpy(newTableHdrs[j].tag, "post", 4);
-    newTableHdrs[j].checksum = 0; //~ should compute the checksum
-    newTableHdrs[j].offset = pos;
-    pos += newTableHdrs[j].length = sizeof(postTab);
-    if (pos & 3) {
-      pos += 4 - (pos & 3);
-    }
-    ++j;
-  }
-  tableDir = (char *)gmalloc(12 + nAllTables * 16);
-  tableDir[0] = 0x00;                                  // sfnt version
-  tableDir[1] = 0x01;
-  tableDir[2] = 0x00;
-  tableDir[3] = 0x00;
-  tableDir[4] = (char)((nAllTables >> 8) & 0xff);      // numTables
-  tableDir[5] = (char)(nAllTables & 0xff);
-  for (i = -1, t = (Guint)nAllTables; t; ++i, t >>= 1) ;
-  t = 1 << (4 + i);
-  tableDir[6] = (char)((t >> 8) & 0xff);               // searchRange
-  tableDir[7] = (char)(t & 0xff);
-  tableDir[8] = (char)((i >> 8) & 0xff);               // entrySelector
-  tableDir[9] = (char)(i & 0xff);
-  t = nAllTables * 16 - t;
-  tableDir[10] = (char)((t >> 8) & 0xff);              // rangeShift
-  tableDir[11] = (char)(t & 0xff);
-  pos = 12;
-  for (i = 0; i < nAllTables; ++i) {
-    tableDir[pos   ] = newTableHdrs[i].tag[0];
-    tableDir[pos+ 1] = newTableHdrs[i].tag[1];
-    tableDir[pos+ 2] = newTableHdrs[i].tag[2];
-    tableDir[pos+ 3] = newTableHdrs[i].tag[3];
-    tableDir[pos+ 4] = (char)(newTableHdrs[i].checksum >> 24);
-    tableDir[pos+ 5] = (char)(newTableHdrs[i].checksum >> 16);
-    tableDir[pos+ 6] = (char)(newTableHdrs[i].checksum >>  8);
-    tableDir[pos+ 7] = (char) newTableHdrs[i].checksum;
-    tableDir[pos+ 8] = (char)(newTableHdrs[i].offset >> 24);
-    tableDir[pos+ 9] = (char)(newTableHdrs[i].offset >> 16);
-    tableDir[pos+10] = (char)(newTableHdrs[i].offset >>  8);
-    tableDir[pos+11] = (char) newTableHdrs[i].offset;
-    tableDir[pos+12] = (char)(newTableHdrs[i].length >> 24);
-    tableDir[pos+13] = (char)(newTableHdrs[i].length >> 16);
-    tableDir[pos+14] = (char)(newTableHdrs[i].length >>  8);
-    tableDir[pos+15] = (char) newTableHdrs[i].length;
-    pos += 16;
-  }
-
-  // write the table directory
-  fwrite(tableDir, 1, 12 + 16 * nAllTables, out);
-
-  // write the tables
-  for (i = 0; i < nAllTables; ++i) {
-    if (!haveCmap && !strncmp(newTableHdrs[i].tag, "cmap", 4)) {
-      fwrite(cmapTab, 1, newTableHdrs[i].length, out);
-    } else if (!haveName && !strncmp(newTableHdrs[i].tag, "name", 4)) {
-      fwrite(nameTab, 1, newTableHdrs[i].length, out);
-    } else if (!havePost && !strncmp(newTableHdrs[i].tag, "post", 4)) {
-      fwrite(postTab, 1, newTableHdrs[i].length, out);
-    } else if (unsortedLoca && !strncmp(newTableHdrs[i].tag, "loca", 4)) {
-      fwrite(locaTable, 1, newTableHdrs[i].length, out);
-    } else if (unsortedLoca && !strncmp(newTableHdrs[i].tag, "glyf", 4)) {
-      pos = seekTable("glyf");
-      for (j = 0; j < nGlyphs; ++j) {
-       length = origLocaTable[j].length;
-       if (length > 0 &&
-           pos + origLocaTable[j].pos + length <= (Guint)len) {
-         fwrite(file + pos + origLocaTable[j].pos, 1, length, out);
-         if ((k = length & 3)) {
-           for (; k < 4; ++k) {
-             fputc((char)0, out);
-           }
-         }
-       }
-      }
-    } else {
-      fwrite(file + seekTable(newTableHdrs[i].tag),
-            1, newTableHdrs[i].length, out);
-    }
-    if ((j = (newTableHdrs[i].length & 3))) {
-      for (; j < 4; ++j) {
-       fputc((char)0, out);
-      }
-    }
-  }
-    
-  gfree(tableDir);
-  gfree(newTableHdrs);
-  if (unsortedLoca) {
-    gfree(origLocaTable);
-    gfree(locaTable);
-  }
-}
diff --git a/pdf/xpdf/FontFile.h b/pdf/xpdf/FontFile.h
deleted file mode 100644 (file)
index 7aa5ba9..0000000
+++ /dev/null
@@ -1,261 +0,0 @@
-//========================================================================
-//
-// FontFile.h
-//
-// Copyright 1999-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#ifndef FONTFILE_H
-#define FONTFILE_H
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma interface
-#endif
-
-#include <stdio.h>
-#include "gtypes.h"
-#include "GString.h"
-#include "CharTypes.h"
-
-class GHash;
-class CharCodeToUnicode;
-
-//------------------------------------------------------------------------
-
-typedef void (*FontFileOutputFunc)(void *stream, char *data, int len);
-
-//------------------------------------------------------------------------
-// FontFile
-//------------------------------------------------------------------------
-
-class FontFile {
-public:
-
-  FontFile();
-  virtual ~FontFile();
-
-  // Returns the font name, as specified internally by the font file.
-  // Returns NULL if no name is available.
-  virtual char *getName() = 0;
-
-  // Returns the custom font encoding, or NULL if the encoding is not
-  // available.
-  virtual char **getEncoding() = 0;
-};
-
-//------------------------------------------------------------------------
-// Type1FontFile
-//------------------------------------------------------------------------
-
-class Type1FontFile: public FontFile {
-public:
-
-  Type1FontFile(char *file, int len);
-  virtual ~Type1FontFile();
-  virtual char *getName() { return name; }
-  virtual char **getEncoding() { return encoding; }
-
-private:
-
-  char *name;
-  char **encoding;
-};
-
-//------------------------------------------------------------------------
-// Type1CFontFile
-//------------------------------------------------------------------------
-
-struct Type1CTopDict;
-struct Type1CPrivateDict;
-
-class Type1CFontFile: public FontFile {
-public:
-
-  Type1CFontFile(char *fileA, int lenA);
-  virtual ~Type1CFontFile();
-  GBool isOk() { return ok; }
-
-  virtual char *getName();
-  virtual char **getEncoding();
-
-  // Convert to a Type 1 font, suitable for embedding in a PostScript
-  // file.  The name will be used as the PostScript font name.
-  void convertToType1(FontFileOutputFunc outputFuncA, void *outputStreamA);
-
-  // Convert to a Type 0 CIDFont, suitable for embedding in a
-  // PostScript file.  The name will be used as the PostScript font
-  // name.
-  void convertToCIDType0(char *psName,
-                        FontFileOutputFunc outputFuncA, void *outputStreamA);
-
-  // Convert to a Type 0 (but non-CID) composite font, suitable for
-  // embedding in a PostScript file.  The name will be used as the
-  // PostScript font name.
-  void convertToType0(char *psName,
-                     FontFileOutputFunc outputFuncA, void *outputStreamA);
-
-private:
-
-  void readEncoding();
-  void readTopDict(Type1CTopDict *dict);
-  void readPrivateDict(Type1CPrivateDict *privateDict,
-                      int offset, int size);
-  Gushort *readCharset(int charset, int nGlyphs);
-  void eexecWrite(char *s);
-  void eexecCvtGlyph(char *glyphName, int pos, int n);
-  void cvtGlyph(int pos, int n, GBool top);
-  void cvtGlyphWidth(GBool useOp);
-  void eexecDumpNum(double x, GBool fpA);
-  void eexecDumpOp1(int opA);
-  void eexecDumpOp2(int opA);
-  void eexecWriteCharstring(Guchar *s, int n);
-  void getDeltaInt(char *buf, char *key, double *opA, int n);
-  void getDeltaReal(char *buf, char *key, double *opA, int n);
-  int getIndexLen(int indexPos);
-  int getIndexValPos(int indexPos, int i, int *valLen);
-  int getIndexEnd(int indexPos);
-  Guint getWord(int pos, int size);
-  double getNum(int *pos, GBool *fp);
-  char *getString(int sid, char *buf);
-
-  Guchar *file;
-  int len;
-
-  GString *name;
-  char **encoding;
-
-  int topDictIdxPos;
-  int stringIdxPos;
-  int gsubrIdxPos;
-  int subrIdxPos;
-  int gsubrBias;
-  int subrBias;
-
-  FontFileOutputFunc outputFunc;
-  void *outputStream;
-  double op[48];               // operands
-  GBool fp[48];                        // true if operand is fixed point
-  int nOps;                    // number of operands
-  int nHints;                  // number of hints for the current glyph
-  GBool firstOp;               // true if we haven't hit the first op yet
-  double defaultWidthX;                // default glyph width
-  double nominalWidthX;                // nominal glyph width
-  GBool defaultWidthXFP;       // true if defaultWidthX is fixed point
-  GBool nominalWidthXFP;       // true if nominalWidthX is fixed point
-  Gushort r1;                  // eexec encryption key
-  GString *charBuf;            // charstring output buffer
-  int line;                    // number of eexec chars on current line
-
-  GBool ok;
-};
-
-//------------------------------------------------------------------------
-// TrueTypeFontFile
-//------------------------------------------------------------------------
-
-struct TTFontTableHdr;
-struct TTFontCmap;
-
-class TrueTypeFontFile: public FontFile {
-public:
-
-  TrueTypeFontFile(char *fileA, int lenA);
-  ~TrueTypeFontFile();
-
-  // This always returns NULL, since it's probably better to trust the
-  // font name in the PDF file rather than the one in the TrueType
-  // font file.
-  virtual char *getName();
-
-  virtual char **getEncoding();
-
-  // Return the number of cmaps defined by this font.
-  int getNumCmaps();
-
-  // Return the platform ID of the <i>th cmap.
-  int getCmapPlatform(int i);
-
-  // Return the encoding ID of the <i>th cmap.
-  int getCmapEncoding(int i);
-
-  // Return the index of the cmap for <platform>, <encoding>.  Returns
-  // -1 if there is no corresponding cmap.
-  int findCmap(int platform, int enc);
-
-  // Return the GID corresponding to <c> according to the <i>th cmap.
-  Gushort mapCodeToGID(int i, int c);
-
-  // Return a name-to-GID mapping, constructed from the font's post
-  // table.  Returns NULL if there is no post table.
-  GHash *getNameToGID();
-
-  // Convert to a Type 42 font, suitable for embedding in a PostScript
-  // file.  The name will be used as the PostScript font name (so we
-  // don't need to depend on the 'name' table in the font).  The
-  // encoding is needed because the PDF Font object can modify the
-  // encoding.
-  void convertToType42(char *name, char **encodingA,
-                      GBool pdfFontHasEncoding,
-                      Gushort *codeToGID,
-                      FontFileOutputFunc outputFunc, void *outputStream);
-
-  // Convert to a Type 2 CIDFont, suitable for embedding in a
-  // PostScript file.  The name will be used as the PostScript font
-  // name (so we don't need to depend on the 'name' table in the
-  // font).
-  void convertToCIDType2(char *name, Gushort *cidMap, int nCIDs,
-                        FontFileOutputFunc outputFunc, void *outputStream);
-
-  // Convert to a Type 0 (but non-CID) composite font, suitable for
-  // embedding in a PostScript file.  The name will be used as the
-  // PostScript font name (so we don't need to depend on the 'name'
-  // table in the font).
-  void convertToType0(char *name, Gushort *cidMap, int nCIDs,
-                     FontFileOutputFunc outputFunc, void *outputStream);
-
-  // Write a TTF file, filling in any missing tables that are required
-  // by the TrueType spec.  If the font already has all the required
-  // tables, it will be written unmodified.
-  void writeTTF(FILE *out);
-
-private:
-
-  char *file;
-  int len;
-
-  char **encoding;
-
-  TTFontTableHdr *tableHdrs;
-  int nTables;
-  int bbox[4];
-  int locaFmt;
-  int nGlyphs;
-  GBool mungedCmapSize;
-  TTFontCmap *cmaps;
-  int nCmaps;
-
-  int getByte(int pos);
-  int getChar(int pos);
-  int getUShort(int pos);
-  int getShort(int pos);
-  Guint getULong(int pos);
-  double getFixed(int pos);
-  int seekTable(char *tag);
-  int seekTableIdx(char *tag);
-  void cvtEncoding(char **encodingA, GBool pdfFontHasEncoding,
-                  FontFileOutputFunc outputFunc, void *outputStream);
-  void cvtCharStrings(char **encodingA, GBool pdfFontHasEncoding,
-                     Gushort *codeToGID,
-                     FontFileOutputFunc outputFunc, void *outputStream);
-  int getCmapEntry(int cmapFmt, int pos, int code);
-  void cvtSfnts(FontFileOutputFunc outputFunc, void *outputStream,
-               GString *name);
-  void dumpString(char *s, int length,
-                 FontFileOutputFunc outputFunc, void *outputStream);
-  Guint computeTableChecksum(char *data, int length);
-};
-
-#endif
index d795a513cae94b7d6fa9ae12664dd3b29cc3654e..0ceb03515c352493f275de75afd010e6a2c7fea1 100644 (file)
@@ -27,8 +27,8 @@ class PSStack;
 // Function
 //------------------------------------------------------------------------
 
-#define funcMaxInputs  8
-#define funcMaxOutputs 8
+#define funcMaxInputs   8
+#define funcMaxOutputs 32
 
 class Function {
 public:
index d10820854d52622e398d438b4cc8e5aeeec8f0be..a52aa02ac8dbfe71ca43cf3774e3d2a047f8f7ca 100644 (file)
@@ -1254,6 +1254,7 @@ void Gfx::doPatternFill(GBool eoFill) {
 void Gfx::doTilingPatternFill(GfxTilingPattern *tPat, GBool eoFill) {
   GfxPatternColorSpace *patCS;
   GfxColorSpace *cs;
+  GfxPath *savedPath;
   double xMin, yMin, xMax, yMax, x, y, x1, y1;
   double cxMin, cyMin, cxMax, cyMax;
   int xi0, yi0, xi1, yi1, xi, yi;
@@ -1303,6 +1304,7 @@ void Gfx::doTilingPatternFill(GfxTilingPattern *tPat, GBool eoFill) {
   imb[5] = (m1[1] * m1[4] - m1[0] * m1[5]) * det;
 
   // save current graphics state
+  savedPath = state->getPath()->copy();
   saveState();
 
   // set underlying color space (for uncolored tiling patterns); set
@@ -1378,17 +1380,17 @@ void Gfx::doTilingPatternFill(GfxTilingPattern *tPat, GBool eoFill) {
   //~ edge instead of left/bottom (?)
   xstep = fabs(tPat->getXStep());
   ystep = fabs(tPat->getYStep());
-  xi0 = (int)floor(xMin / xstep);
-  xi1 = (int)ceil(xMax / xstep);
-  yi0 = (int)floor(yMin / ystep);
-  yi1 = (int)ceil(yMax / ystep);
+  xi0 = (int)floor((xMin - tPat->getBBox()[0]) / xstep);
+  xi1 = (int)ceil((xMax - tPat->getBBox()[0]) / xstep);
+  yi0 = (int)floor((yMin - tPat->getBBox()[1]) / ystep);
+  yi1 = (int)ceil((yMax - tPat->getBBox()[1]) / ystep);
   for (i = 0; i < 4; ++i) {
     m1[i] = m[i];
   }
   for (yi = yi0; yi < yi1; ++yi) {
     for (xi = xi0; xi < xi1; ++xi) {
-      x = xi * xstep - tPat->getBBox()[0];
-      y = yi * ystep - tPat->getBBox()[1];
+      x = xi * xstep;
+      y = yi * ystep;
       m1[4] = x * m[0] + y * m[2] + m[4];
       m1[5] = x * m[1] + y * m[3] + m[5];
       doForm1(tPat->getContentStream(), tPat->getResDict(),
@@ -1398,10 +1400,12 @@ void Gfx::doTilingPatternFill(GfxTilingPattern *tPat, GBool eoFill) {
 
   // restore graphics state
   restoreState();
+  state->setPath(savedPath);
 }
 
 void Gfx::doShadingPatternFill(GfxShadingPattern *sPat, GBool eoFill) {
   GfxShading *shading;
+  GfxPath *savedPath;
   double *ctm, *btm, *ptm;
   double m[6], ictm[6], m1[6];
   double xMin, yMin, xMax, yMax;
@@ -1410,6 +1414,7 @@ void Gfx::doShadingPatternFill(GfxShadingPattern *sPat, GBool eoFill) {
   shading = sPat->getShading();
 
   // save current graphics state
+  savedPath = state->getPath()->copy();
   saveState();
 
   // clip to bbox
@@ -1483,10 +1488,12 @@ void Gfx::doShadingPatternFill(GfxShadingPattern *sPat, GBool eoFill) {
 
   // restore graphics state
   restoreState();
+  state->setPath(savedPath);
 }
 
 void Gfx::opShFill(Object args[], int numArgs) {
   GfxShading *shading;
+  GfxPath *savedPath;
   double xMin, yMin, xMax, yMax;
 
   if (!(shading = res->lookupShading(args[0].getName()))) {
@@ -1494,6 +1501,7 @@ void Gfx::opShFill(Object args[], int numArgs) {
   }
 
   // save current graphics state
+  savedPath = state->getPath()->copy();
   saveState();
 
   // clip to bbox
@@ -1527,6 +1535,7 @@ void Gfx::opShFill(Object args[], int numArgs) {
 
   // restore graphics state
   restoreState();
+  state->setPath(savedPath);
 
   delete shading;
 }
@@ -2335,6 +2344,8 @@ void Gfx::doShowText(GString *s) {
     newCTM[2] = mat[2] * newCTM[0] + mat[3] * newCTM[2];
     newCTM[3] = mat[2] * newCTM[1] + mat[3] * newCTM[3];
     newCTM[0] *= state->getFontSize();
+    newCTM[1] *= state->getFontSize();
+    newCTM[2] *= state->getFontSize();
     newCTM[3] *= state->getFontSize();
     newCTM[0] *= state->getHorizScaling();
     newCTM[2] *= state->getHorizScaling();
@@ -2361,7 +2372,8 @@ void Gfx::doShowText(GString *s) {
       saveState();
       state->setCTM(newCTM[0], newCTM[1], newCTM[2], newCTM[3], x, y);
       //~ out->updateCTM(???)
-      if (!out->beginType3Char(state, code, u, uLen)) {
+      if (!out->beginType3Char(state, curX + riseX, curY + riseY, tdx, tdy,
+                              code, u, uLen)) {
        ((Gfx8BitFont *)font)->getCharProc(code, &charProc);
        if ((resDict = ((Gfx8BitFont *)font)->getResources())) {
          pushResources(resDict);
@@ -2970,7 +2982,7 @@ Stream *Gfx::buildImageStream() {
   obj.free();
 
   // make stream
-  str = new EmbedStream(parser->getStream(), &dict);
+  str = new EmbedStream(parser->getStream(), &dict, gFalse, 0);
   str = str->addFilters(&dict);
 
   return str;
index 20898ec8cedcf8cb989e51872d05cd88bc002a95..2069e97abcc07e3a349fc42e890961eef091dd58 100644 (file)
@@ -35,7 +35,7 @@ class GfxFunctionShading;
 class GfxAxialShading;
 class GfxRadialShading;
 class GfxState;
-class GfxColor;
+struct GfxColor;
 class Gfx;
 class PDFRectangle;
 
index 6f83676398bf6e5f0a0811af58613604af033257..ed9f076d99105ace3aea48dfcf490ee031c115d6 100644 (file)
@@ -17,7 +17,6 @@
 #include <string.h>
 #include <ctype.h>
 #include "gmem.h"
-#include "GHash.h"
 #include "Error.h"
 #include "Object.h"
 #include "Dict.h"
@@ -26,7 +25,9 @@
 #include "CharCodeToUnicode.h"
 #include "FontEncodingTables.h"
 #include "BuiltinFontTables.h"
-#include "FontFile.h"
+#include "FoFiType1.h"
+#include "FoFiType1C.h"
+#include "FoFiTrueType.h"
 #include "GfxFont.h"
 
 //------------------------------------------------------------------------
@@ -89,7 +90,10 @@ static StdFontMapEntry stdFontMap[] = {
   { "TimesNewRomanPS-BoldMT",       "Times-Bold" },
   { "TimesNewRomanPS-Italic",       "Times-Italic" },
   { "TimesNewRomanPS-ItalicMT",     "Times-Italic" },
-  { "TimesNewRomanPSMT",            "Times-Roman" }
+  { "TimesNewRomanPSMT",            "Times-Roman" },
+  { "TimesNewRomanPSMT,Bold",       "Times-Bold" },
+  { "TimesNewRomanPSMT,BoldItalic", "Times-BoldItalic" },
+  { "TimesNewRomanPSMT,Italic",     "Times-Italic" }
 };
 
 //------------------------------------------------------------------------
@@ -400,7 +404,8 @@ Gfx8BitFont::Gfx8BitFont(XRef *xref, char *tagA, Ref idA, GString *nameA,
   GBool baseEncFromFontFile;
   char *buf;
   int len;
-  FontFile *fontFile;
+  FoFiType1 *ffT1;
+  FoFiType1C *ffT1C;
   int code, code2;
   char *charName;
   GBool missing, hex;
@@ -554,43 +559,51 @@ Gfx8BitFont::Gfx8BitFont(XRef *xref, char *tagA, Ref idA, GString *nameA,
   // check embedded or external font file for base encoding
   // (only for Type 1 fonts - trying to get an encoding out of a
   // TrueType font is a losing proposition)
-  fontFile = NULL;
+  ffT1 = NULL;
+  ffT1C = NULL;
   buf = NULL;
-  if ((type == fontType1 || type == fontType1C) &&
-      (extFontFile || embFontID.num >= 0)) {
+  if (type == fontType1 && (extFontFile || embFontID.num >= 0)) {
     if (extFontFile) {
-      buf = readExtFontFile(&len);
+      ffT1 = FoFiType1::load(extFontFile->getCString());
     } else {
       buf = readEmbFontFile(xref, &len);
+      ffT1 = FoFiType1::make(buf, len);
     }
-    if (buf) {
-      if (type == fontType1C && !strncmp(buf, "%!", 2)) {
-       // various tools (including Adobe's) occasionally embed Type 1
-       // fonts but label them Type 1C
-       type = fontType1;
-      }
-      if (type == fontType1) {
-       fontFile = new Type1FontFile(buf, len);
-      } else {
-       fontFile = new Type1CFontFile(buf, len);
-       if (!((Type1CFontFile *)fontFile)->isOk()) {
-         delete fontFile;
-         fontFile = NULL;
+    if (ffT1) {
+      if (ffT1->getName()) {
+       if (embFontName) {
+         delete embFontName;
        }
+       embFontName = new GString(ffT1->getName());
+      }
+      if (!baseEnc) {
+       baseEnc = ffT1->getEncoding();
+       baseEncFromFontFile = gTrue;
       }
-      if (fontFile && fontFile->getName()) {
+    }
+  } else if (type == fontType1C && (extFontFile || embFontID.num >= 0)) {
+    if (extFontFile) {
+      ffT1C = FoFiType1C::load(extFontFile->getCString());
+    } else {
+      buf = readEmbFontFile(xref, &len);
+      ffT1C = FoFiType1C::make(buf, len);
+    }
+    if (ffT1C) {
+      if (ffT1C->getName()) {
        if (embFontName) {
          delete embFontName;
        }
-       embFontName = new GString(fontFile->getName());
+       embFontName = new GString(ffT1C->getName());
       }
-      if (fontFile && !baseEnc) {
-       baseEnc = fontFile->getEncoding();
+      if (!baseEnc) {
+       baseEnc = ffT1C->getEncoding();
        baseEncFromFontFile = gTrue;
       }
-      gfree(buf);
     }
   }
+  if (buf) {
+    gfree(buf);
+  }
 
   // get default base encoding
   if (!baseEnc) {
@@ -612,6 +625,20 @@ Gfx8BitFont::Gfx8BitFont(XRef *xref, char *tagA, Ref idA, GString *nameA,
     }
   }
 
+  // some Type 1C font files have empty encodings, which can break the
+  // T1C->T1 conversion (since the 'seac' operator depends on having
+  // the accents in the encoding), so we fill in any gaps from
+  // StandardEncoding
+  if (type == fontType1C && (extFontFile || embFontID.num >= 0) &&
+      baseEncFromFontFile) {
+    for (i = 0; i < 256; ++i) {
+      if (!enc[i] && standardEncoding[i]) {
+       enc[i] = standardEncoding[i];
+       encFree[i] = gFalse;
+      }
+    }
+  }
+
   // merge differences into encoding
   if (obj1.isDict()) {
     obj1.dictLookup("Differences", &obj2);
@@ -641,8 +668,11 @@ Gfx8BitFont::Gfx8BitFont(XRef *xref, char *tagA, Ref idA, GString *nameA,
     obj2.free();
   }
   obj1.free();
-  if (fontFile) {
-    delete fontFile;
+  if (ffT1) {
+    delete ffT1;
+  }
+  if (ffT1C) {
+    delete ffT1C;
   }
 
   //----- build the mapping to Unicode -----
@@ -860,12 +890,11 @@ CharCodeToUnicode *Gfx8BitFont::getToUnicode() {
   return ctu;
 }
 
-Gushort *Gfx8BitFont::getCodeToGIDMap(TrueTypeFontFile *ff) {
+Gushort *Gfx8BitFont::getCodeToGIDMap(FoFiTrueType *ff) {
   Gushort *map;
   int cmapPlatform, cmapEncoding;
   int unicodeCmap, macRomanCmap, msSymbolCmap, cmap;
   GBool useMacRoman, useUnicode;
-  GHash *nameToGID;
   char *charName;
   Unicode u;
   int code, i, n;
@@ -966,13 +995,10 @@ Gushort *Gfx8BitFont::getCodeToGIDMap(TrueTypeFontFile *ff) {
   }
 
   // try the TrueType 'post' table to handle any unmapped characters
-  if ((nameToGID = ff->getNameToGID())) {
-    for (i = 0; i < 256; ++i) {
-      if (!map[i] && (charName = enc[i])) {
-       map[i] = (Gushort)(int)nameToGID->lookup(charName);
-      }
+  for (i = 0; i < 256; ++i) {
+    if (!map[i] && (charName = enc[i])) {
+      map[i] = (Gushort)(int)ff->mapNameToGID(charName);
     }
-    delete nameToGID;
   }
 
   return map;
@@ -983,7 +1009,7 @@ Dict *Gfx8BitFont::getCharProcs() {
 }
 
 Object *Gfx8BitFont::getCharProc(int code, Object *proc) {
-  if (charProcs.isDict()) {
+  if (enc[code] && charProcs.isDict()) {
     charProcs.dictLookup(enc[code], proc);
   } else {
     proc->initNull();
@@ -1406,7 +1432,9 @@ int GfxCIDFont::getWMode() {
 }
 
 CharCodeToUnicode *GfxCIDFont::getToUnicode() {
-  ctu->incRefCnt();
+  if (ctu) {
+    ctu->incRefCnt();
+  }
   return ctu;
 }
 
index ddd88be3e55fb3ff1cbfa008074fb74e59ef61f4..62dfd0881ad24b9842f61e3cdf52d221ebb95825 100644 (file)
@@ -23,7 +23,7 @@
 class Dict;
 class CMap;
 class CharCodeToUnicode;
-class TrueTypeFontFile;
+class FoFiTrueType;
 struct GfxFontCIDWidths;
 
 //------------------------------------------------------------------------
@@ -220,7 +220,7 @@ public:
 
   // Return a char code-to-GID mapping for the provided font file.
   // (This is only useful for TrueType fonts.)
-  Gushort *getCodeToGIDMap(TrueTypeFontFile *ff);
+  Gushort *getCodeToGIDMap(FoFiTrueType *ff);
 
   // Return the Type 3 CharProc dictionary, or NULL if none.
   Dict *getCharProcs();
index d20293974753b9a12294dea87b928379f91082c7..be6040550181f6ff04f79ef1999a44a6c3d27f96 100644 (file)
@@ -766,12 +766,18 @@ void GfxICCBasedColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
 void GfxICCBasedColorSpace::getDefaultRanges(double *decodeLow,
                                             double *decodeRange,
                                             int maxImgPixel) {
+  alt->getDefaultRanges(decodeLow, decodeRange, maxImgPixel);
+
+#if 0
+  // this is nominally correct, but some PDF files don't set the
+  // correct ranges in the ICCBased dict
   int i;
 
   for (i = 0; i < nComps; ++i) {
     decodeLow[i] = rangeMin[i];
     decodeRange[i] = rangeMax[i] - rangeMin[i];
   }
+#endif
 }
 
 //------------------------------------------------------------------------
@@ -1053,6 +1059,11 @@ GfxColorSpace *GfxDeviceNColorSpace::parse(Array *arr) {
     goto err2;
   }
   nCompsA = obj1.arrayGetLength();
+  if (nCompsA > gfxColorMaxComps) {
+    error(-1, "DeviceN color space with more than %d > %d components",
+         nCompsA, gfxColorMaxComps);
+    nCompsA = gfxColorMaxComps;
+  }
   for (i = 0; i < nCompsA; ++i) {
     if (!obj1.arrayGet(i, &obj2)->isName()) {
       error(-1, "Bad DeviceN color space (names)");
@@ -2030,13 +2041,18 @@ GfxImageColorMap::GfxImageColorMap(int bitsA, Object *decode,
     colorSpace2 = indexedCS->getBase();
     indexHigh = indexedCS->getIndexHigh();
     nComps2 = colorSpace2->getNComps();
-    lookup = (double *)gmalloc((indexHigh + 1) * nComps2 * sizeof(double));
+    lookup = (double *)gmalloc((maxPixel + 1) * nComps2 * sizeof(double));
     lookup2 = indexedCS->getLookup();
     colorSpace2->getDefaultRanges(x, y, indexHigh);
-    for (i = 0; i <= indexHigh; ++i) {
+    for (i = 0; i <= maxPixel; ++i) {
       j = (int)(decodeLow[0] + (i * decodeRange[0]) / maxPixel + 0.5);
+      if (j < 0) {
+       j = 0;
+      } else if (j > indexHigh) {
+       j = indexHigh;
+      }
       for (k = 0; k < nComps2; ++k) {
-       lookup[j*nComps2 + k] = x[k] + (lookup2[i*nComps2 + k] / 255.0) * y[k];
+       lookup[i*nComps2 + k] = x[k] + (lookup2[j*nComps2 + k] / 255.0) * y[k];
       }
     }
   } else if (colorSpace->getMode() == csSeparation) {
@@ -2079,17 +2095,15 @@ GfxImageColorMap::GfxImageColorMap(GfxImageColorMap *colorMap) {
   nComps2 = colorMap->nComps2;
   colorSpace2 = NULL;
   lookup = NULL;
+  n = 1 << bits;
   if (colorSpace->getMode() == csIndexed) {
     colorSpace2 = ((GfxIndexedColorSpace *)colorSpace)->getBase();
-    n = ((GfxIndexedColorSpace *)colorSpace)->getIndexHigh();
-    n = (n + 1) * nComps2 * sizeof(double);
+    n = n * nComps2 * sizeof(double);
   } else if (colorSpace->getMode() == csSeparation) {
     colorSpace2 = ((GfxSeparationColorSpace *)colorSpace)->getAlt();
-    n = (1 << bits) - 1;
-    n = (n + 1) * nComps2 * sizeof(double);
+    n = n * nComps2 * sizeof(double);
   } else {
-    n = (1 << bits) - 1;
-    n = (n + 1) * nComps * sizeof(double);
+    n = n * nComps * sizeof(double);
   }
   lookup = (double *)gmalloc(n);
   memcpy(lookup, colorMap->lookup, n);
@@ -2497,6 +2511,11 @@ GfxState::GfxState(GfxState *state) {
   saved = NULL;
 }
 
+void GfxState::setPath(GfxPath *pathA) {
+  delete path;
+  path = pathA;
+}
+
 void GfxState::getUserClipBBox(double *xMin, double *yMin,
                               double *xMax, double *yMax) {
   double ictm[6];
index d072fd3a13cced9222ef4c45d499f24474b53cd5..f747a831b12b90837cf3d737476cf3abeb606bc3 100644 (file)
@@ -429,7 +429,6 @@ private:
     *names[gfxColorMaxComps];
   GfxColorSpace *alt;          // alternate color space
   Function *func;              // tint transform (into alternate color space)
-  
 };
 
 //------------------------------------------------------------------------
@@ -910,6 +909,7 @@ public:
   double getRise() { return rise; }
   int getRender() { return render; }
   GfxPath *getPath() { return path; }
+  void setPath(GfxPath *pathA);
   double getCurX() { return curX; }
   double getCurY() { return curY; }
   void getClipBBox(double *xMin, double *yMin, double *xMax, double *yMax)
index 9aa54e9e7ad32645176b6643933017711cf1939a..c125430200d7d39251a754852c7265ee5ea24cdc 100644 (file)
@@ -13,6 +13,7 @@
 #endif
 
 #include <string.h>
+#include <stdio.h>
 #include <ctype.h>
 #if HAVE_PAPER_H
 #include <paper.h>
@@ -49,7 +50,6 @@
 
 #include "NameToUnicodeTable.h"
 #include "UnicodeMapTables.h"
-#include "DisplayFontTable.h"
 #include "UTF8.h"
 
 //------------------------------------------------------------------------
 
 //------------------------------------------------------------------------
 
+static struct {
+  char *name;
+  char *fileName;
+} displayFontTab[] = {
+  {"Courier",               "n022003l.pfb"},
+  {"Courier-Bold",          "n022004l.pfb"},
+  {"Courier-BoldOblique",   "n022024l.pfb"},
+  {"Courier-Oblique",       "n022023l.pfb"},
+  {"Helvetica",             "n019003l.pfb"},
+  {"Helvetica-Bold",        "n019004l.pfb"},
+  {"Helvetica-BoldOblique", "n019024l.pfb"},
+  {"Helvetica-Oblique",     "n019023l.pfb"},
+  {"Symbol",                "s050000l.pfb"},
+  {"Times-Bold",            "n021004l.pfb"},
+  {"Times-BoldItalic",      "n021024l.pfb"},
+  {"Times-Italic",          "n021023l.pfb"},
+  {"Times-Roman",           "n021003l.pfb"},
+  {"ZapfDingbats",          "d050000l.pfb"},
+  {NULL}
+};
+
+static char *displayFontDirs[] = {
+  "/usr/share/ghostscript/fonts",
+  "/usr/local/share/ghostscript/fonts",
+  "/usr/share/fonts/default/Type1",
+  NULL
+};
+
+//------------------------------------------------------------------------
+
 GlobalParams *globalParams = NULL;
 
 //------------------------------------------------------------------------
@@ -70,10 +100,6 @@ DisplayFontParam::DisplayFontParam(GString *nameA,
   name = nameA;
   kind = kindA;
   switch (kind) {
-  case displayFontX:
-    x.xlfd = NULL;
-    x.encoding = NULL;
-    break;
   case displayFontT1:
     t1.fileName = NULL;
     break;
@@ -83,24 +109,9 @@ DisplayFontParam::DisplayFontParam(GString *nameA,
   }
 }
 
-DisplayFontParam::DisplayFontParam(char *nameA, char *xlfdA, char *encodingA) {
-  name = new GString(nameA);
-  kind = displayFontX;
-  x.xlfd = new GString(xlfdA);
-  x.encoding = new GString(encodingA);
-}
-
 DisplayFontParam::~DisplayFontParam() {
   delete name;
   switch (kind) {
-  case displayFontX:
-    if (x.xlfd) {
-      delete x.xlfd;
-    }
-    if (x.encoding) {
-      delete x.encoding;
-    }
-    break;
   case displayFontT1:
     if (t1.fileName) {
       delete t1.fileName;
@@ -140,7 +151,6 @@ PSFontParam::~PSFontParam() {
 
 GlobalParams::GlobalParams(char *cfgFileName) {
   UnicodeMap *map;
-  DisplayFontParam *dfp;
   GString *fileName;
   FILE *f;
   int i;
@@ -190,6 +200,13 @@ GlobalParams::GlobalParams(char *cfgFileName) {
   psPaperWidth = defPaperWidth;
   psPaperHeight = defPaperHeight;
 #endif
+  psImageableLLX = psImageableLLY = 0;
+  psImageableURX = psPaperWidth;
+  psImageableURY = psPaperHeight;
+  psCrop = gTrue;
+  psExpandSmaller = gFalse;
+  psShrinkLarger = gTrue;
+  psCenter = gTrue;
   psDuplex = gFalse;
   psLevel = psLevel2;
   psFile = NULL;
@@ -214,8 +231,9 @@ GlobalParams::GlobalParams(char *cfgFileName) {
   textKeepTinyChars = gFalse;
   fontDirs = new GList();
   initialZoom = new GString("125");
-  t1libControl = fontRastAALow;
-  freetypeControl = fontRastAALow;
+  enableT1lib = gTrue;
+  enableFreeType = gTrue;
+  antialias = gTrue;
   urlCommand = NULL;
   movieCommand = NULL;
   mapNumericCharNames = gTrue;
@@ -251,14 +269,6 @@ GlobalParams::GlobalParams(char *cfgFileName) {
   map = new UnicodeMap("UCS-2", gTrue, &mapUCS2);
   residentUnicodeMaps->add(map->getEncodingName(), map);
 
-  // default displayFonts table
-  for (i = 0; displayFontTab[i].name; ++i) {
-    dfp = new DisplayFontParam(displayFontTab[i].name,
-                              displayFontTab[i].xlfd,
-                              displayFontTab[i].encoding);
-    displayFonts->add(dfp->name, dfp);
-  }
-
   // look for a user config file, then a system-wide config file
   f = NULL;
   fileName = NULL;
@@ -356,18 +366,10 @@ void GlobalParams::parseFile(GString *fileName, FILE *f) {
        parseCMapDir(tokens, fileName, line);
       } else if (!cmd->cmp("toUnicodeDir")) {
        parseToUnicodeDir(tokens, fileName, line);
-      } else if (!cmd->cmp("displayFontX")) {
-       parseDisplayFont(tokens, displayFonts, displayFontX, fileName, line);
       } else if (!cmd->cmp("displayFontT1")) {
        parseDisplayFont(tokens, displayFonts, displayFontT1, fileName, line);
       } else if (!cmd->cmp("displayFontTT")) {
        parseDisplayFont(tokens, displayFonts, displayFontTT, fileName, line);
-      } else if (!cmd->cmp("displayNamedCIDFontX")) {
-       parseDisplayFont(tokens, displayNamedCIDFonts,
-                        displayFontX, fileName, line);
-      } else if (!cmd->cmp("displayCIDFontX")) {
-       parseDisplayFont(tokens, displayCIDFonts,
-                        displayFontX, fileName, line);
       } else if (!cmd->cmp("displayNamedCIDFontT1")) {
        parseDisplayFont(tokens, displayNamedCIDFonts,
                         displayFontT1, fileName, line);
@@ -391,6 +393,17 @@ void GlobalParams::parseFile(GString *fileName, FILE *f) {
        parsePSFont16("psFont16", psFonts16, tokens, fileName, line);
       } else if (!cmd->cmp("psPaperSize")) {
        parsePSPaperSize(tokens, fileName, line);
+      } else if (!cmd->cmp("psImageableArea")) {
+       parsePSImageableArea(tokens, fileName, line);
+      } else if (!cmd->cmp("psCrop")) {
+       parseYesNo("psCrop", &psCrop, tokens, fileName, line);
+      } else if (!cmd->cmp("psExpandSmaller")) {
+       parseYesNo("psExpandSmaller", &psExpandSmaller,
+                  tokens, fileName, line);
+      } else if (!cmd->cmp("psShrinkLarger")) {
+       parseYesNo("psShrinkLarger", &psShrinkLarger, tokens, fileName, line);
+      } else if (!cmd->cmp("psCenter")) {
+       parseYesNo("psCenter", &psCenter, tokens, fileName, line);
       } else if (!cmd->cmp("psDuplex")) {
        parseYesNo("psDuplex", &psDuplex, tokens, fileName, line);
       } else if (!cmd->cmp("psLevel")) {
@@ -424,12 +437,12 @@ void GlobalParams::parseFile(GString *fileName, FILE *f) {
        parseFontDir(tokens, fileName, line);
       } else if (!cmd->cmp("initialZoom")) {
        parseInitialZoom(tokens, fileName, line);
-      } else if (!cmd->cmp("t1libControl")) {
-       parseFontRastControl("t1libControl", &t1libControl,
-                            tokens, fileName, line);
-      } else if (!cmd->cmp("freetypeControl")) {
-       parseFontRastControl("freetypeControl", &freetypeControl,
-                            tokens, fileName, line);
+      } else if (!cmd->cmp("enableT1lib")) {
+       parseYesNo("enableT1lib", &enableT1lib, tokens, fileName, line);
+      } else if (!cmd->cmp("enableFreeType")) {
+       parseYesNo("enableFreeType", &enableFreeType, tokens, fileName, line);
+      } else if (!cmd->cmp("antialias")) {
+       parseYesNo("antialias", &antialias, tokens, fileName, line);
       } else if (!cmd->cmp("urlCommand")) {
        parseCommand("urlCommand", &urlCommand, tokens, fileName, line);
       } else if (!cmd->cmp("movieCommand")) {
@@ -441,12 +454,19 @@ void GlobalParams::parseFile(GString *fileName, FILE *f) {
        parseYesNo("printCommands", &printCommands, tokens, fileName, line);
       } else if (!cmd->cmp("errQuiet")) {
        parseYesNo("errQuiet", &errQuiet, tokens, fileName, line);
-      } else if (!cmd->cmp("fontpath") || !cmd->cmp("fontmap")) {
-       error(-1, "Unknown config file command");
-       error(-1, "-- the config file format has changed since Xpdf 0.9x");
       } else {
        error(-1, "Unknown config file command '%s' (%s:%d)",
              cmd->getCString(), fileName->getCString(), line);
+       if (!cmd->cmp("displayFontX") ||
+           !cmd->cmp("displayNamedCIDFontX") ||
+           !cmd->cmp("displayCIDFontX")) {
+         error(-1, "-- Xpdf no longer supports X fonts");
+       } else if (!cmd->cmp("t1libControl") || !cmd->cmp("freetypeControl")) {
+         error(-1, "-- The t1libControl and freetypeControl options have been replaced");
+         error(-1, "   by the enableT1lib, enableFreeType, and antialias options");
+       } else if (!cmd->cmp("fontpath") || !cmd->cmp("fontmap")) {
+         error(-1, "-- the config file format has changed since Xpdf 0.9x");
+       }
       }
     }
 
@@ -580,13 +600,6 @@ void GlobalParams::parseDisplayFont(GList *tokens, GHash *fontHash,
   param = new DisplayFontParam(((GString *)tokens->get(1))->copy(), kind);
   
   switch (kind) {
-  case displayFontX:
-    if (tokens->getLength() != 4) {
-      goto err2;
-    }
-    param->x.xlfd = ((GString *)tokens->get(2))->copy();
-    param->x.encoding = ((GString *)tokens->get(3))->copy();
-    break;
   case displayFontT1:
     if (tokens->getLength() != 3) {
       goto err2;
@@ -629,12 +642,28 @@ void GlobalParams::parsePSPaperSize(GList *tokens, GString *fileName,
     psPaperWidth = atoi(tok->getCString());
     tok = (GString *)tokens->get(2);
     psPaperHeight = atoi(tok->getCString());
+    psImageableLLX = psImageableLLY = 0;
+    psImageableURX = psPaperWidth;
+    psImageableURY = psPaperHeight;
   } else {
     error(-1, "Bad 'psPaperSize' config file command (%s:%d)",
          fileName->getCString(), line);
   }
 }
 
+void GlobalParams::parsePSImageableArea(GList *tokens, GString *fileName,
+                                       int line) {
+  if (tokens->getLength() != 5) {
+    error(-1, "Bad 'psImageableArea' config file command (%s:%d)",
+         fileName->getCString(), line);
+    return;
+  }
+  psImageableLLX = atoi(((GString *)tokens->get(1))->getCString());
+  psImageableLLY = atoi(((GString *)tokens->get(2))->getCString());
+  psImageableURX = atoi(((GString *)tokens->get(3))->getCString());
+  psImageableURY = atoi(((GString *)tokens->get(4))->getCString());
+}
+
 void GlobalParams::parsePSLevel(GList *tokens, GString *fileName, int line) {
   GString *tok;
 
@@ -767,23 +796,6 @@ void GlobalParams::parseInitialZoom(GList *tokens,
   initialZoom = ((GString *)tokens->get(1))->copy();
 }
 
-void GlobalParams::parseFontRastControl(char *cmdName, FontRastControl *val,
-                                       GList *tokens, GString *fileName,
-                                       int line) {
-  GString *tok;
-
-  if (tokens->getLength() != 2) {
-    error(-1, "Bad '%s' config file command (%s:%d)",
-         cmdName, fileName->getCString(), line);
-    return;
-  }
-  tok = (GString *)tokens->get(1);
-  if (!setFontRastControl(val, tok->getCString())) {
-    error(-1, "Bad '%s' config file command (%s:%d)",
-         cmdName, fileName->getCString(), line);
-  }
-}
-
 void GlobalParams::parseCommand(char *cmdName, GString **val,
                                GList *tokens, GString *fileName, int line) {
   if (tokens->getLength() != 2) {
@@ -807,14 +819,21 @@ void GlobalParams::parseYesNo(char *cmdName, GBool *flag,
     return;
   }
   tok = (GString *)tokens->get(1);
-  if (!tok->cmp("yes")) {
+  if (!parseYesNo2(tok->getCString(), flag)) {
+    error(-1, "Bad '%s' config file command (%s:%d)",
+         cmdName, fileName->getCString(), line);
+  }
+}
+
+GBool GlobalParams::parseYesNo2(char *token, GBool *flag) {
+  if (!strcmp(token, "yes")) {
     *flag = gTrue;
-  } else if (!tok->cmp("no")) {
+  } else if (!strcmp(token, "no")) {
     *flag = gFalse;
   } else {
-    error(-1, "Bad '%s' config file command (%s:%d)",
-         cmdName, fileName->getCString(), line);
+    return gFalse;
   }
+  return gTrue;
 }
 
 GlobalParams::~GlobalParams() {
@@ -869,6 +888,54 @@ GlobalParams::~GlobalParams() {
 #endif
 }
 
+//------------------------------------------------------------------------
+
+void GlobalParams::setupBaseFonts(char *dir) {
+  GString *fontName;
+  GString *fileName;
+  FILE *f;
+  DisplayFontParam *dfp;
+  int i, j;
+
+  for (i = 0; displayFontTab[i].name; ++i) {
+    fontName = new GString(displayFontTab[i].name);
+    if (getDisplayFont(fontName)) {
+      delete fontName;
+      continue;
+    }
+    fileName = NULL;
+    if (dir) {
+      fileName = appendToPath(new GString(dir), displayFontTab[i].fileName);
+      if ((f = fopen(fileName->getCString(), "rb"))) {
+       fclose(f);
+      } else {
+       delete fileName;
+       fileName = NULL;
+      }
+    }
+#ifndef WIN32
+    for (j = 0; !fileName && displayFontDirs[j]; ++j) {
+      fileName = appendToPath(new GString(displayFontDirs[j]),
+                             displayFontTab[i].fileName);
+      if ((f = fopen(fileName->getCString(), "rb"))) {
+       fclose(f);
+      } else {
+       delete fileName;
+       fileName = NULL;
+      }
+    }
+#endif
+    if (!fileName) {
+      error(-1, "No display font for '%s'", displayFontTab[i].name);
+      delete fontName;
+      continue;
+    }
+    dfp = new DisplayFontParam(fontName, displayFontT1);
+    dfp->t1.fileName = fileName;
+    globalParams->addDisplayFont(dfp);
+  }
+}
+
 //------------------------------------------------------------------------
 // accessors
 //------------------------------------------------------------------------
@@ -1004,6 +1071,51 @@ int GlobalParams::getPSPaperHeight() {
   return h;
 }
 
+void GlobalParams::getPSImageableArea(int *llx, int *lly, int *urx, int *ury) {
+  lockGlobalParams;
+  *llx = psImageableLLX;
+  *lly = psImageableLLY;
+  *urx = psImageableURX;
+  *ury = psImageableURY;
+  unlockGlobalParams;
+}
+
+GBool GlobalParams::getPSCrop() {
+  GBool f;
+
+  lockGlobalParams;
+  f = psCrop;
+  unlockGlobalParams;
+  return f;
+}
+
+GBool GlobalParams::getPSExpandSmaller() {
+  GBool f;
+
+  lockGlobalParams;
+  f = psExpandSmaller;
+  unlockGlobalParams;
+  return f;
+}
+
+GBool GlobalParams::getPSShrinkLarger() {
+  GBool f;
+
+  lockGlobalParams;
+  f = psShrinkLarger;
+  unlockGlobalParams;
+  return f;
+}
+
+GBool GlobalParams::getPSCenter() {
+  GBool f;
+
+  lockGlobalParams;
+  f = psCenter;
+  unlockGlobalParams;
+  return f;
+}
+
 GBool GlobalParams::getPSDuplex() {
   GBool d;
 
@@ -1185,22 +1297,32 @@ GString *GlobalParams::getInitialZoom() {
   return s;
 }
 
-FontRastControl GlobalParams::getT1libControl() {
-  FontRastControl c;
+GBool GlobalParams::getEnableT1lib() {
+  GBool f;
+
+  lockGlobalParams;
+  f = enableT1lib;
+  unlockGlobalParams;
+  return f;
+}
+
+GBool GlobalParams::getEnableFreeType() {
+  GBool f;
 
   lockGlobalParams;
-  c = t1libControl;
+  f = enableFreeType;
   unlockGlobalParams;
-  return c;
+  return f;
 }
 
-FontRastControl GlobalParams::getFreeTypeControl() {
-  FontRastControl c;
+
+GBool GlobalParams::getAntialias() {
+  GBool f;
 
   lockGlobalParams;
-  c = freetypeControl;
+  f = antialias;
   unlockGlobalParams;
-  return c;
+  return f;
 }
 
 GBool GlobalParams::getMapNumericCharNames() {
@@ -1345,6 +1467,9 @@ GBool GlobalParams::setPSPaperSize(char *size) {
     unlockGlobalParams;
     return gFalse;
   }
+  psImageableLLX = psImageableLLY = 0;
+  psImageableURX = psPaperWidth;
+  psImageableURY = psPaperHeight;
   unlockGlobalParams;
   return gTrue;
 }
@@ -1352,12 +1477,49 @@ GBool GlobalParams::setPSPaperSize(char *size) {
 void GlobalParams::setPSPaperWidth(int width) {
   lockGlobalParams;
   psPaperWidth = width;
+  psImageableLLX = 0;
+  psImageableURX = psPaperWidth;
   unlockGlobalParams;
 }
 
 void GlobalParams::setPSPaperHeight(int height) {
   lockGlobalParams;
   psPaperHeight = height;
+  psImageableLLY = 0;
+  psImageableURY = psPaperHeight;
+  unlockGlobalParams;
+}
+
+void GlobalParams::setPSImageableArea(int llx, int lly, int urx, int ury) {
+  lockGlobalParams;
+  psImageableLLX = llx;
+  psImageableLLY = lly;
+  psImageableURX = urx;
+  psImageableURY = ury;
+  unlockGlobalParams;
+}
+
+void GlobalParams::setPSCrop(GBool crop) {
+  lockGlobalParams;
+  psCrop = crop;
+  unlockGlobalParams;
+}
+
+void GlobalParams::setPSExpandSmaller(GBool expand) {
+  lockGlobalParams;
+  psExpandSmaller = expand;
+  unlockGlobalParams;
+}
+
+void GlobalParams::setPSShrinkLarger(GBool shrink) {
+  lockGlobalParams;
+  psShrinkLarger = shrink;
+  unlockGlobalParams;
+}
+
+void GlobalParams::setPSCenter(GBool center) {
+  lockGlobalParams;
+  psCenter = center;
   unlockGlobalParams;
 }
 
@@ -1451,40 +1613,32 @@ void GlobalParams::setInitialZoom(char *s) {
   unlockGlobalParams;
 }
 
-GBool GlobalParams::setT1libControl(char *s) {
+GBool GlobalParams::setEnableT1lib(char *s) {
   GBool ok;
 
   lockGlobalParams;
-  ok = setFontRastControl(&t1libControl, s);
+  ok = parseYesNo2(s, &enableT1lib);
   unlockGlobalParams;
   return ok;
 }
 
-GBool GlobalParams::setFreeTypeControl(char *s) {
+GBool GlobalParams::setEnableFreeType(char *s) {
   GBool ok;
 
   lockGlobalParams;
-  ok = setFontRastControl(&freetypeControl, s);
+  ok = parseYesNo2(s, &enableFreeType);
   unlockGlobalParams;
   return ok;
 }
 
-GBool GlobalParams::setFontRastControl(FontRastControl *val, char *s) {
+
+GBool GlobalParams::setAntialias(char *s) {
+  GBool ok;
+
   lockGlobalParams;
-  if (!strcmp(s, "none")) {
-    *val = fontRastNone;
-  } else if (!strcmp(s, "plain")) {
-    *val = fontRastPlain;
-  } else if (!strcmp(s, "low")) {
-    *val = fontRastAALow;
-  } else if (!strcmp(s, "high")) {
-    *val = fontRastAAHigh;
-  } else {
-    unlockGlobalParams;
-    return gFalse;
-  }
+  ok = parseYesNo2(s, &antialias);
   unlockGlobalParams;
-  return gTrue;
+  return ok;
 }
 
 void GlobalParams::setMapNumericCharNames(GBool map) {
index 472beed9902fddf13916c047fd821daac9bab4b7..93ec06aa7d77041d90b44a47a0a3df929ad3a672 100644 (file)
@@ -43,7 +43,6 @@ extern GlobalParams *globalParams;
 //------------------------------------------------------------------------
 
 enum DisplayFontParamKind {
-  displayFontX,
   displayFontT1,
   displayFontTT
 };
@@ -56,10 +55,6 @@ public:
                                //   generic CID fonts
   DisplayFontParamKind kind;
   union {
-    struct {
-      GString *xlfd;
-      GString *encoding;
-    } x;
     struct {
       GString *fileName;
     } t1;
@@ -69,18 +64,9 @@ public:
   };
 
   DisplayFontParam(GString *nameA, DisplayFontParamKind kindA);
-  DisplayFontParam(char *nameA, char *xlfdA, char *encodingA);
   ~DisplayFontParam();
 };
 
-// Font rasterizer control.
-enum FontRastControl {
-  fontRastNone,                        // don't use this rasterizer
-  fontRastPlain,               // use it, without anti-aliasing
-  fontRastAALow,               // use it, with low-level anti-aliasing
-  fontRastAAHigh               // use it, with high-level anti-aliasing
-};
-
 //------------------------------------------------------------------------
 
 class PSFontParam {
@@ -129,6 +115,8 @@ public:
 
   ~GlobalParams();
 
+  void setupBaseFonts(char *dir);
+
   //----- accessors
 
   CharCode getMacRomanCharCode(char *charName);
@@ -143,7 +131,12 @@ public:
   GString *getPSFile();
   int getPSPaperWidth();
   int getPSPaperHeight();
+  void getPSImageableArea(int *llx, int *lly, int *urx, int *ury);
   GBool getPSDuplex();
+  GBool getPSCrop();
+  GBool getPSExpandSmaller();
+  GBool getPSShrinkLarger();
+  GBool getPSCenter();
   PSLevel getPSLevel();
   PSFontParam *getPSFont(GString *fontName);
   PSFontParam *getPSFont16(GString *fontName, GString *collection, int wMode);
@@ -159,8 +152,9 @@ public:
   GBool getTextKeepTinyChars();
   GString *findFontFile(GString *fontName, char **exts);
   GString *getInitialZoom();
-  FontRastControl getT1libControl();
-  FontRastControl getFreeTypeControl();
+  GBool getEnableT1lib();
+  GBool getEnableFreeType();
+  GBool getAntialias();
   GString *getURLCommand() { return urlCommand; }
   GString *getMovieCommand() { return movieCommand; }
   GBool getMapNumericCharNames();
@@ -180,7 +174,12 @@ public:
   GBool setPSPaperSize(char *size);
   void setPSPaperWidth(int width);
   void setPSPaperHeight(int height);
+  void setPSImageableArea(int llx, int lly, int urx, int ury);
   void setPSDuplex(GBool duplex);
+  void setPSCrop(GBool crop);
+  void setPSExpandSmaller(GBool expand);
+  void setPSShrinkLarger(GBool shrink);
+  void setPSCenter(GBool center);
   void setPSLevel(PSLevel level);
   void setPSEmbedType1(GBool embed);
   void setPSEmbedTrueType(GBool embed);
@@ -193,8 +192,9 @@ public:
   void setTextPageBreaks(GBool pageBreaks);
   void setTextKeepTinyChars(GBool keep);
   void setInitialZoom(char *s);
-  GBool setT1libControl(char *s);
-  GBool setFreeTypeControl(char *s);
+  GBool setEnableT1lib(char *s);
+  GBool setEnableFreeType(char *s);
+  GBool setAntialias(char *s);
   void setMapNumericCharNames(GBool map);
   void setPrintCommands(GBool printCommandsA);
   void setErrQuiet(GBool errQuietA);
@@ -213,6 +213,7 @@ private:
                        GString *fileName, int line);
   void parsePSFile(GList *tokens, GString *fileName, int line);
   void parsePSPaperSize(GList *tokens, GString *fileName, int line);
+  void parsePSImageableArea(GList *tokens, GString *fileName, int line);
   void parsePSLevel(GList *tokens, GString *fileName, int line);
   void parsePSFont(GList *tokens, GString *fileName, int line);
   void parsePSFont16(char *cmdName, GList *fontList,
@@ -221,14 +222,12 @@ private:
   void parseTextEOL(GList *tokens, GString *fileName, int line);
   void parseFontDir(GList *tokens, GString *fileName, int line);
   void parseInitialZoom(GList *tokens, GString *fileName, int line);
-  void parseFontRastControl(char *cmdName, FontRastControl *val,
-                           GList *tokens, GString *fileName, int line);
   void parseCommand(char *cmdName, GString **val,
                    GList *tokens, GString *fileName, int line);
   void parseYesNo(char *cmdName, GBool *flag,
                  GList *tokens, GString *fileName, int line);
+  GBool parseYesNo2(char *token, GBool *flag);
   UnicodeMap *getUnicodeMap2(GString *encodingName);
-  GBool setFontRastControl(FontRastControl *val, char *s);
 
   //----- static tables
 
@@ -260,6 +259,14 @@ private:
   GString *psFile;             // PostScript file or command (for xpdf)
   int psPaperWidth;            // paper size, in PostScript points, for
   int psPaperHeight;           //   PostScript output
+  int psImageableLLX,          // imageable area, in PostScript points,
+      psImageableLLY,          //   for PostScript output
+      psImageableURX,
+      psImageableURY;
+  GBool psCrop;                        // crop PS output to CropBox
+  GBool psExpandSmaller;       // expand smaller pages to fill paper
+  GBool psShrinkLarger;                // shrink larger pages to fit paper
+  GBool psCenter;              // center pages on the paper
   GBool psDuplex;              // enable duplexing in PostScript?
   PSLevel psLevel;             // PostScript level to generate
   GHash *psFonts;              // PostScript font info, indexed by PDF
@@ -280,9 +287,9 @@ private:
   GBool textKeepTinyChars;     // keep all characters in text output
   GList *fontDirs;             // list of font dirs [GString]
   GString *initialZoom;                // initial zoom level
-  FontRastControl t1libControl;        // t1lib rasterization mode
-  FontRastControl              // FreeType rasterization mode
-    freetypeControl;
+  GBool enableT1lib;           // t1lib enable flag
+  GBool enableFreeType;                // FreeType enable flag
+  GBool antialias;             // anti-aliasing enable flag
   GString *urlCommand;         // command executed for URL links
   GString *movieCommand;       // command executed for movie annotations
   GBool mapNumericCharNames;   // map numeric char names (from font subsets)?
index 96d57ec267e41302962764bd283c0007a53e8f37..db62813e6bad77646d0ca67b787d57556f12d940 100644 (file)
@@ -4,6 +4,8 @@ INCLUDES =                                                      \
        -I$(top_srcdir)                                         \
        -I$(top_srcdir)/goo                                     \
        -I$(top_srcdir)/lib/ggv-sidebar                         \
+       -I$(top_srcdir)/fofi                                    \
+       -I$(top_srcdir)/splash                                  \
        -DDATADIR=\""$(datadir)"\"                              \
         -DGNOMELOCALEDIR=\""$(prefix)/$(DATADIRNAME)/locale"\" \
        -DGNOMEICONDIR=\""$(datadir)/pixmaps"\"                 \
@@ -55,8 +57,6 @@ libxpdf_a_SOURCES =           \
        Error.h                 \
        FontEncodingTables.cc   \
        FontEncodingTables.h    \
-       FontFile.cc             \
-       FontFile.h              \
        Function.cc             \
        Function.h              \
        Gfx.cc                  \
@@ -67,8 +67,12 @@ libxpdf_a_SOURCES =          \
        GfxState.h              \
        GlobalParams.cc         \
        GlobalParams.h          \
+       JArithmeticDecoder.cc   \
+       JArithmeticDecoder.h    \
        JBIG2Stream.cc          \
        JBIG2Stream.h           \
+       JPXStream.cc            \
+       JPXStream.h             \
        Lexer.cc                \
        Lexer.h                 \
        Link.cc                 \
@@ -98,23 +102,15 @@ libxpdf_a_SOURCES =                \
        UnicodeMap.h            \
        UnicodeMapTables.h      \
        UnicodeTypeTable.cc     \
+       UnicodeTypeTable.h      \
        XRef.cc                 \
        XRef.h
 
 common_sources =               \
        CharTypes.h             \
        CompactFontTables.h     \
-       DisplayFontTable.h      \
        ErrorCodes.h            \
-       FTFont.cc               \
-       FTFont.h                \
        NameToUnicodeTable.h    \
-       SFont.cc                \
-       SFont.h                 \
-       T1Font.cc               \
-       T1Font.h                \
-       TTFont.cc               \
-       TTFont.h                \
        TextOutputDev.cc        \
        TextOutputDev.h         \
        UTF8.h
@@ -200,12 +196,15 @@ gnome_pdf_viewer_LDADD =                                  \
        libxpdf.a                                               \
        libgpdf.a                                               \
        $(top_builddir)/goo/libGoo.a                            \
+       $(top_builddir)/fofi/libfofi.a                          \
        $(top_builddir)/lib/ggv-sidebar/libggv-sidebar.a        \
        $(EXTRA_GNOME_LIBS)                                     \
        $(libpaper_LIBS)
 
 xpdf_SOURCES =                 \
        $(common_sources)       \
+       SplashOutputDev.cc      \
+       SplashOutputDev.h       \
        XPDFApp.cc              \
        XPDFApp.h               \
        XPDFCore.cc             \
@@ -214,10 +213,8 @@ xpdf_SOURCES =                     \
        XPDFTree.h              \
        XPDFViewer.cc           \
        XPDFViewer.h            \
-       XOutputDev.cc           \
-       XOutputDev.h            \
-       XPixmapOutputDev.cc     \
-       XPixmapOutputDev.h      \
+       XSplashOutputDev.cc     \
+       XSplashOutputDev.h      \
        PSOutputDev.cc          \
        PSOutputDev.h           \
        xpdf.cc
@@ -254,16 +251,14 @@ xpdf_LDADD =                              \
 #      pdfinfo.cc
 #pdfinfo_LDADD = ../goo/libGoo.a
 
-#pdftopbm_SOURCES =            
+#pdftopüm_SOURCES =            
 #      $(common_sources)       
-#      PBMOutputDev.cc         
-#      PBMOutputDev.h          
 #      XOutputDev.cc           
 #      XOutputDev.h            
 #      XOutputFontInfo.h       
 #      pdftopbm.cc
 
-#pdftopbm_LDADD = ../goo/libGoo.a $(EXTRA_GNOME_LIBS)
+#pdftoppm_LDADD = ../goo/libGoo.a $(EXTRA_GNOME_LIBS)
 
 #bitmaps =             
 #      about.xbm               
index b0976fdea84134ede965f0ec6c456983185f3b2b..ddd6da693cd771902347191b52efff2197366b76 100644 (file)
@@ -58,6 +58,13 @@ Object *Object::initDict(XRef *xref) {
   return this;
 }
 
+Object *Object::initDict(Dict *dictA) {
+  initObj(objDict);
+  dict = dictA;
+  dict->incRef();
+  return this;
+}
+
 Object *Object::initStream(Stream *streamA) {
   initObj(objStream);
   stream = streamA;
index 8f0b370bc849b5d88b4de1af92041ccd685ef8ad..8b1807c5ba52326e6d36b07043d635bbc2b00b9b 100644 (file)
@@ -95,6 +95,7 @@ public:
     { initObj(objNull); return this; }
   Object *initArray(XRef *xref);
   Object *initDict(XRef *xref);
+  Object *initDict(Dict *dictA);
   Object *initStream(Stream *streamA);
   Object *initRef(int numA, int genA)
     { initObj(objRef); ref.num = numA; ref.gen = genA; return this; }
index 23efed18aa2b9ba30d004bea7355fa2237220ff5..b7e064586a6e9b7d49db6fa7253c54fbd74aabfb 100644 (file)
 //------------------------------------------------------------------------
 
 Outline::Outline(Object *outlineObj, XRef *xref) {
-  Object first;
+  Object first, last;
 
   items = NULL;
   if (!outlineObj->isDict()) {
     return;
   }
   items = OutlineItem::readItemList(outlineObj->dictLookupNF("First", &first),
+                                   outlineObj->dictLookupNF("Last", &last),
                                    xref);
   first.free();
+  last.free();
 }
 
 Outline::~Outline() {
@@ -68,6 +70,8 @@ OutlineItem::OutlineItem(Dict *dict, XRef *xrefA) {
        title[i] = pdfDocEncoding[s->getChar(i) & 0xff];
       }
     }
+  } else {
+    titleLen = 0;
   }
   obj1.free();
 
@@ -82,6 +86,7 @@ OutlineItem::OutlineItem(Dict *dict, XRef *xrefA) {
   obj1.free();
 
   dict->lookupNF("First", &firstRef);
+  dict->lookupNF("Last", &lastRef);
   dict->lookupNF("Next", &nextRef);
 
   startsOpen = gFalse;
@@ -102,17 +107,19 @@ OutlineItem::~OutlineItem() {
     delete action;
   }
   firstRef.free();
+  lastRef.free();
   nextRef.free();
 }
 
-GList *OutlineItem::readItemList(Object *itemRef, XRef *xrefA) {
+GList *OutlineItem::readItemList(Object *firstItemRef, Object *lastItemRef,
+                                XRef *xrefA) {
   GList *items;
   OutlineItem *item;
   Object obj;
   Object *p;
 
   items = new GList();
-  p = itemRef;
+  p = firstItemRef;
   while (p->isRef()) {
     if (!p->fetch(xrefA, &obj)->isDict()) {
       obj.free();
@@ -121,6 +128,10 @@ GList *OutlineItem::readItemList(Object *itemRef, XRef *xrefA) {
     item = new OutlineItem(obj.getDict(), xrefA);
     obj.free();
     items->append(item);
+    if (p->getRef().num == lastItemRef->getRef().num &&
+       p->getRef().gen == lastItemRef->getRef().gen) {
+      break;
+    }
     p = &item->nextRef;
   }
   return items;
@@ -128,7 +139,7 @@ GList *OutlineItem::readItemList(Object *itemRef, XRef *xrefA) {
 
 void OutlineItem::open() {
   if (!kids) {
-    kids = readItemList(&firstRef, xref);
+    kids = readItemList(&firstRef, &lastRef, xref);
   }
 }
 
index cbb5df5f7f6aad28c5c340d8bfeb8155f039c33a..e83882df9816b154ec97d1ea5eef1b5ee850943e 100644 (file)
@@ -60,7 +60,8 @@ void OutputDev::updateAll(GfxState *state) {
   updateFont(state);
 }
 
-GBool OutputDev::beginType3Char(GfxState *state,
+GBool OutputDev::beginType3Char(GfxState *state, double x, double y,
+                               double dx, double dy,
                                CharCode code, Unicode *u, int uLen) {
   return gFalse;
 }
index 67737af52edfc5d00bfa3533454b3c61a2f76fbb..bbf8b692e26dc5d090541a618bc935102261cb0f 100644 (file)
@@ -126,7 +126,8 @@ public:
                        double originX, double originY,
                        CharCode code, Unicode *u, int uLen) {}
   virtual void drawString(GfxState *state, GString *s) {}
-  virtual GBool beginType3Char(GfxState *state,
+  virtual GBool beginType3Char(GfxState *state, double x, double y,
+                              double dx, double dy,
                               CharCode code, Unicode *u, int uLen);
   virtual void endType3Char(GfxState *state) {}
   virtual void endTextObject(GfxState *state) {}
diff --git a/pdf/xpdf/PBMOutputDev.cc b/pdf/xpdf/PBMOutputDev.cc
deleted file mode 100644 (file)
index dde860a..0000000
+++ /dev/null
@@ -1,162 +0,0 @@
-//========================================================================
-//
-// PBMOutputDev.cc
-//
-// Copyright 1998-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma implementation
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <string.h>
-#include "gmem.h"
-#include "GString.h"
-#include "Object.h"
-#include "Stream.h"
-#include "GfxState.h"
-#include "GfxFont.h"
-#include "Error.h"
-#include "PBMOutputDev.h"
-
-//------------------------------------------------------------------------
-
-PBMOutputDev *PBMOutputDev::makePBMOutputDev(char *displayName,
-                                            char *fileRootA) {
-  Display *displayA;
-  Pixmap pixmapA;
-  Window dummyWinA;
-  int screenA;
-  int invertA;
-  unsigned long black, white;
-  PBMOutputDev *out;
-
-  if (!(displayA = XOpenDisplay(displayName))) {
-    fprintf(stderr, "Couldn't open display '%s'\n", displayName);
-    exit(1);
-  }
-  screenA = DefaultScreen(displayA);
-
-  black = BlackPixel(displayA, screenA);
-  white = WhitePixel(displayA, screenA);
-  if ((black & 1) == (white & 1)) {
-    fprintf(stderr, "Weird black/white pixel colors\n");
-    XCloseDisplay(displayA);
-    return NULL;
-  } 
-  invertA = (white & 1) == 1 ? 0xff : 0x00;
-
-  dummyWinA = XCreateSimpleWindow(displayA, RootWindow(displayA, screenA),
-                                 0, 0, 1, 1, 0,
-                                 black, white);
-  pixmapA = XCreatePixmap(displayA, dummyWinA, 1, 1, 1);
-  out = new PBMOutputDev(displayA, screenA, pixmapA, dummyWinA,
-                        invertA, fileRootA);
-  return out;
-}
-
-void PBMOutputDev::killPBMOutputDev(PBMOutputDev *out) {
-  Display *displayA;
-  Pixmap pixmapA;
-  Window dummyWinA;
-
-  displayA = out->display;
-  pixmapA = out->pixmap;
-  dummyWinA = out->dummyWin;
-
-  delete out;
-
-  // these have to be done *after* the XOutputDev (parent of the
-  // PBMOutputDev) is deleted, since XOutputDev::~XOutputDev() needs
-  // them
-  XFreePixmap(displayA, pixmapA);
-  XDestroyWindow(displayA, dummyWinA);
-  XCloseDisplay(displayA);
-}
-
-PBMOutputDev::PBMOutputDev(Display *displayA, int screenA,
-                          Pixmap pixmapA, Window dummyWinA,
-                          int invertA, char *fileRootA):
-  XOutputDev(displayA, screenA,
-            DefaultVisual(displayA, screenA),
-            DefaultColormap(displayA, screenA),
-            gFalse,
-            WhitePixel(displayA, DefaultScreen(displayA)),
-            gFalse, 1, 1)
-{
-  display = displayA;
-  screen = screenA;
-  pixmap = pixmapA;
-  dummyWin = dummyWinA;
-  invert = invertA;
-  fileRoot = fileRootA;
-  fileName = (char *)gmalloc(strlen(fileRoot) + 20);
-}
-
-PBMOutputDev::~PBMOutputDev() {
-  gfree(fileName);
-}
-
-void PBMOutputDev::startPage(int pageNum, GfxState *state) {
-  curPage = pageNum;
-  width = (int)(state->getPageWidth() + 0.5);
-  height = (int)(state->getPageHeight() + 0.5);
-  XFreePixmap(display, pixmap);
-  pixmap = XCreatePixmap(display, dummyWin, width, height, 1);
-  setPixmap(pixmap, width, height);
-  XOutputDev::startPage(pageNum, state);
-}
-
-void PBMOutputDev::endPage() {
-  XImage *image;
-  FILE *f;
-  int p;
-  int x, y, i;
-
-  image = XCreateImage(display, DefaultVisual(display, screen),
-                      1, ZPixmap, 0, NULL, width, height, 8, 0);
-  image->data = (char *)gmalloc(height * image->bytes_per_line);
-  XGetSubImage(display, pixmap, 0, 0, width, height, 1, ZPixmap,
-              image, 0, 0);
-
-  sprintf(fileName, "%s-%06d.pbm", fileRoot, curPage);
-  if (!(f = fopen(fileName, "wb"))) {
-    fprintf(stderr, "Couldn't open output file '%s'\n", fileName);
-    goto err;
-  }
-  fprintf(f, "P4\n");
-  fprintf(f, "%d %d\n", width, height);
-
-  for (y = 0; y < height; ++y) {
-    for (x = 0; x+8 <= width; x += 8) {
-      p = 0;
-      for (i = 0; i < 8; ++i)
-       p = (p << 1) + (XGetPixel(image, x+i, y) & 1);
-      p ^= invert;
-      fputc((char)p, f);
-    }
-    if (width & 7) {
-      p = 0;
-      for (i = 0; i < (width & 7); ++i)
-       p = (p << 1) + (XGetPixel(image, x+i, y) & 1);
-      p <<= 8 - (width & 7);
-      p ^= invert;
-      fputc((char)p, f);
-    }
-  }
-
-  fclose(f);
-
- err:
-  gfree(image->data);
-  image->data = NULL;
-  XDestroyImage(image);
-
-  XOutputDev::endPage();
-}
diff --git a/pdf/xpdf/PBMOutputDev.h b/pdf/xpdf/PBMOutputDev.h
deleted file mode 100644 (file)
index 9d1539d..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-//========================================================================
-//
-// PBMOutputDev.h
-//
-// Copyright 1998-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#ifndef PBMOUTPUTDEV_H
-#define PBMOUTPUTDEV_H
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma interface
-#endif
-
-#include <stddef.h>
-#include "config.h"
-#include "XOutputDev.h"
-
-//------------------------------------------------------------------------
-
-class PBMOutputDev: public XOutputDev {
-public:
-
-  // NB: Users must use makePBMOutputDev and killPBMOutputDev rather
-  // than the constructor and destructor.  (This is due to some
-  // constraints in the underlying XOutputDev object.)
-
-  static PBMOutputDev *makePBMOutputDev(char *displayName,
-                                       char *fileRootA);
-
-  static void killPBMOutputDev(PBMOutputDev *out);
-
-  virtual ~PBMOutputDev();
-
-  //----- initialization and control
-
-  // Start a page.
-  virtual void startPage(int pageNum, GfxState *state);
-
-  // End a page.
-  virtual void endPage();
-
-private:
-
-  PBMOutputDev(Display *displayA, int screenA,
-              Pixmap pixmapA, Window dummyWinA,
-              int invertA, char *fileRootA);
-
-  char *fileRoot;
-  char *fileName;
-  int curPage;
-
-  Display *display;
-  int screen;
-  Pixmap pixmap;
-  Window dummyWin;
-  int width, height;
-  int invert;
-};
-
-#endif
index c92048bd9896392882aec54a8cd6567bf894f946..e156c3f7232e5c247ba1109ffca4e4d1cac86f75 100644 (file)
@@ -206,7 +206,7 @@ void PDFDoc::checkHeader() {
 }
 
 void PDFDoc::displayPage(OutputDev *out, int page, double hDPI, double vDPI,
-                        int rotate, GBool doLinks,
+                        int rotate, GBool crop, GBool doLinks,
                         GBool (*abortCheckCbk)(void *data),
                         void *abortCheckCbkData,
                          GBool (*annotDisplayDecideCbk)(Annot *annot, void *user_data),
@@ -223,18 +223,19 @@ void PDFDoc::displayPage(OutputDev *out, int page, double hDPI, double vDPI,
       links = NULL;
     }
     getLinks(p);
-    p->display(out, hDPI, vDPI, rotate, links, catalog,
+    p->display(out, hDPI, vDPI, rotate, crop, links, catalog,
               abortCheckCbk, abortCheckCbkData,
                annotDisplayDecideCbk, annotDisplayDecideCbkData);
   } else {
-    p->display(out, hDPI, vDPI, rotate, NULL, catalog,
+    p->display(out, hDPI, vDPI, rotate, crop, NULL, catalog,
               abortCheckCbk, abortCheckCbkData,
                annotDisplayDecideCbk, annotDisplayDecideCbkData);
   }
 }
 
 void PDFDoc::displayPages(OutputDev *out, int firstPage, int lastPage,
-                         double hDPI, double vDPI, int rotate, GBool doLinks,
+                         double hDPI, double vDPI, int rotate,
+                         GBool crop, GBool doLinks,
                          GBool (*abortCheckCbk)(void *data),
                          void *abortCheckCbkData,
                           GBool (*annotDisplayDecideCbk)(Annot *annot, void *user_data),
@@ -242,7 +243,7 @@ void PDFDoc::displayPages(OutputDev *out, int firstPage, int lastPage,
   int page;
 
   for (page = firstPage; page <= lastPage; ++page) {
-    displayPage(out, page, hDPI, vDPI, rotate, doLinks,
+    displayPage(out, page, hDPI, vDPI, rotate, crop, doLinks,
                abortCheckCbk, abortCheckCbkData,
                 annotDisplayDecideCbk, annotDisplayDecideCbkData);
   }
@@ -250,8 +251,8 @@ void PDFDoc::displayPages(OutputDev *out, int firstPage, int lastPage,
 
 void PDFDoc::displayPageSlice(OutputDev *out, int page,
                              double hDPI, double vDPI,
-                             int rotate, int sliceX, int sliceY,
-                             int sliceW, int sliceH,
+                             int rotate, GBool crop,
+                             int sliceX, int sliceY, int sliceW, int sliceH,
                              GBool (*abortCheckCbk)(void *data),
                              void *abortCheckCbkData,
                               GBool (*annotDisplayDecideCbk)(Annot *annot, void *user_data),
@@ -259,7 +260,8 @@ void PDFDoc::displayPageSlice(OutputDev *out, int page,
   Page *p;
 
   p = catalog->getPage(page);
-  p->displaySlice(out, hDPI, vDPI, rotate, sliceX, sliceY, sliceW, sliceH,
+  p->displaySlice(out, hDPI, vDPI, rotate, crop,
+                 sliceX, sliceY, sliceW, sliceH,
                  NULL, catalog,
                   abortCheckCbk, abortCheckCbkData,
                   annotDisplayDecideCbk, annotDisplayDecideCbkData);
index 2d060dc1984e88214aa9adf3aab5958ec6d2544c..57e37a2afb7d4847904fb0e22ecd07415b5d52d5 100644 (file)
@@ -81,7 +81,7 @@ public:
 
   // Display a page.
   void displayPage(OutputDev *out, int page, double hDPI, double vDPI,
-                  int rotate, GBool doLinks,
+                  int rotate, GBool crop, GBool doLinks,
                   GBool (*abortCheckCbk)(void *data) = NULL,
                   void *abortCheckCbkData = NULL,
                    GBool (*annotDisplayDecideCbk)(Annot *annot, void *user_data) = NULL,
@@ -89,7 +89,8 @@ public:
 
   // Display a range of pages.
   void displayPages(OutputDev *out, int firstPage, int lastPage,
-                   double hDPI, double vDPI, int rotate, GBool doLinks,
+                   double hDPI, double vDPI, int rotate,
+                   GBool crop, GBool doLinks,
                    GBool (*abortCheckCbk)(void *data) = NULL,
                    void *abortCheckCbkData = NULL,
                     GBool (*annotDisplayDecideCbk)(Annot *annot, void *user_data) = NULL,
@@ -98,8 +99,8 @@ public:
   // Display part of a page.
   void displayPageSlice(OutputDev *out, int page,
                        double hDPI, double vDPI,
-                       int rotate, int sliceX, int sliceY,
-                       int sliceW, int sliceH,
+                       int rotate, GBool crop,
+                       int sliceX, int sliceY, int sliceW, int sliceH,
                        GBool (*abortCheckCbk)(void *data) = NULL,
                        void *abortCheckCbkData = NULL,
                         GBool (*annotDisplayDecideCbk)(Annot *annot, void *user_data) = NULL,
index 34d7fdc96bf406addfbca1f48710743ab3c57e30..6170dfd2c9c4d6d7c5e5b6828a1ab061efd7c2c5 100644 (file)
@@ -28,7 +28,8 @@
 #include "GfxState.h"
 #include "GfxFont.h"
 #include "UnicodeMap.h"
-#include "FontFile.h"
+#include "FoFiType1C.h"
+#include "FoFiTrueType.h"
 #include "Catalog.h"
 #include "Page.h"
 #include "Stream.h"
@@ -368,8 +369,9 @@ static char *prolog[] = {
   "       pdfTextMat dtransform rmoveto } def",
   "/TJmV { pdfFontSize 0.001 mul mul neg 0 exch",
   "        pdfTextMat dtransform rmoveto } def",
-  "/Tclip { pdfTextClipPath cvx exec clip",
+  "/Tclip { pdfTextClipPath cvx exec clip newpath",
   "         /pdfTextClipPath [] def } def",
+  "~1",
   "% Level 1 image operators",
   "/pdfIm1 {",
   "  /pdfImBuf1 4 index string def",
@@ -390,6 +392,11 @@ static char *prolog[] = {
   "  /pdfImBuf1 4 index 7 add 8 idiv string def",
   "  { currentfile pdfImBuf1 readhexstring pop } imagemask",
   "} def",
+  "/pdfImM1a {",
+  "  { 2 copy get exch 1 add exch } imagemask",
+  "  pop pop",
+  "} def",
+  "~2",
   "% Level 2 image operators",
   "/pdfImBuf 100 string def",
   "/pdfIm {",
@@ -422,6 +429,7 @@ static char *prolog[] = {
   "    not { pop exit } if",
   "    (%-EOD-) eq { exit } if } loop",
   "} def",
+  "~a",
   "end",
   NULL
 };
@@ -559,6 +567,87 @@ PSOutCustomColor::~PSOutCustomColor() {
   delete name;
 }
 
+//------------------------------------------------------------------------
+// DeviceNRecoder
+//------------------------------------------------------------------------
+
+class DeviceNRecoder: public FilterStream {
+public:
+
+  DeviceNRecoder(Stream *strA, int widthA, int heightA,
+                GfxImageColorMap *colorMapA);
+  virtual ~DeviceNRecoder();
+  virtual StreamKind getKind() { return strWeird; }
+  virtual void reset();
+  virtual int getChar()
+    { return (bufIdx >= bufSize && !fillBuf()) ? EOF : buf[bufIdx++]; }
+  virtual int lookChar()
+    { return (bufIdx >= bufSize && !fillBuf()) ? EOF : buf[bufIdx]; }
+  virtual GString *getPSFilter(int psLevel, char *indent) { return NULL; }
+  virtual GBool isBinary(GBool last = gTrue) { return gTrue; }
+  virtual GBool isEncoder() { return gTrue; }
+
+private:
+
+  GBool fillBuf();
+
+  int width, height;
+  GfxImageColorMap *colorMap;
+  Function *func;
+  ImageStream *imgStr;
+  int buf[gfxColorMaxComps];
+  int pixelIdx;
+  int bufIdx;
+  int bufSize;
+};
+
+DeviceNRecoder::DeviceNRecoder(Stream *strA, int widthA, int heightA,
+                              GfxImageColorMap *colorMapA):
+    FilterStream(strA) {
+  width = widthA;
+  height = heightA;
+  colorMap = colorMapA;
+  imgStr = NULL;
+  pixelIdx = 0;
+  bufIdx = gfxColorMaxComps;
+  bufSize = ((GfxDeviceNColorSpace *)colorMap->getColorSpace())->
+              getAlt()->getNComps();
+  func = ((GfxDeviceNColorSpace *)colorMap->getColorSpace())->
+           getTintTransformFunc();
+}
+
+DeviceNRecoder::~DeviceNRecoder() {
+  if (imgStr) {
+    delete imgStr;
+  }
+}
+
+void DeviceNRecoder::reset() {
+  imgStr = new ImageStream(str, width, colorMap->getNumPixelComps(),
+                          colorMap->getBits());
+  imgStr->reset();
+}
+
+GBool DeviceNRecoder::fillBuf() {
+  Guchar pixBuf[gfxColorMaxComps];
+  GfxColor color;
+  double y[gfxColorMaxComps];
+  int i;
+
+  if (pixelIdx >= width * height) {
+    return gFalse;
+  }
+  imgStr->getPixel(pixBuf);
+  colorMap->getColor(pixBuf, &color);
+  func->transform(color.c, y);
+  for (i = 0; i < bufSize; ++i) {
+    buf[i] = (int)(y[i] * 255 + 0.5);
+  }
+  bufIdx = 0;
+  ++pixelIdx;
+  return gTrue;
+}
+
 //------------------------------------------------------------------------
 // PSOutputDev
 //------------------------------------------------------------------------
@@ -573,7 +662,7 @@ static void outputToFile(void *stream, char *data, int len) {
 
 PSOutputDev::PSOutputDev(char *fileName, XRef *xrefA, Catalog *catalog,
                         int firstPage, int lastPage, PSOutMode modeA,
-                        int paperWidthA, int paperHeightA,
+                        int imgLLXA, int imgLLYA, int imgURXA, int imgURYA,
                         GBool manualCtrlA) {
   FILE *f;
   PSFileType fileTypeA;
@@ -624,14 +713,19 @@ PSOutputDev::PSOutputDev(char *fileName, XRef *xrefA, Catalog *catalog,
 
   init(outputToFile, f, fileTypeA,
        xrefA, catalog, firstPage, lastPage, modeA,
-       paperWidthA, paperHeightA, manualCtrlA);
+       imgLLXA, imgLLYA, imgURXA, imgURYA, manualCtrlA);
 }
 
 PSOutputDev::PSOutputDev(PSOutputFunc outputFuncA, void *outputStreamA,
                         XRef *xrefA, Catalog *catalog,
                         int firstPage, int lastPage, PSOutMode modeA,
-                        int paperWidthA, int paperHeightA,
+                        int imgLLXA, int imgLLYA, int imgURXA, int imgURYA,
                         GBool manualCtrlA) {
+  underlayCbk = NULL;
+  underlayCbkData = NULL;
+  overlayCbk = NULL;
+  overlayCbkData = NULL;
+
   fontIDs = NULL;
   fontFileIDs = NULL;
   fontFileNames = NULL;
@@ -644,15 +738,16 @@ PSOutputDev::PSOutputDev(PSOutputFunc outputFuncA, void *outputStreamA,
 
   init(outputFuncA, outputStreamA, psGeneric,
        xrefA, catalog, firstPage, lastPage, modeA,
-       paperWidthA, paperHeightA, manualCtrlA);
+       imgLLXA, imgLLYA, imgURXA, imgURYA, manualCtrlA);
 }
 
 void PSOutputDev::init(PSOutputFunc outputFuncA, void *outputStreamA,
                       PSFileType fileTypeA, XRef *xrefA, Catalog *catalog,
                       int firstPage, int lastPage, PSOutMode modeA,
-                      int paperWidthA, int paperHeightA,
+                      int imgLLXA, int imgLLYA, int imgURXA, int imgURYA,
                       GBool manualCtrlA) {
   Page *page;
+  PDFRectangle *box;
 
   // initialize
   ok = gTrue;
@@ -662,18 +757,28 @@ void PSOutputDev::init(PSOutputFunc outputFuncA, void *outputStreamA,
   xref = xrefA;
   level = globalParams->getPSLevel();
   mode = modeA;
-  paperWidth = paperWidthA;
-  paperHeight = paperHeightA;
-  if (paperWidth == 0) {
-    paperWidth = globalParams->getPSPaperWidth();
-  }
-  if (paperHeight == 0) {
-    paperHeight = globalParams->getPSPaperHeight();
+  paperWidth = globalParams->getPSPaperWidth();
+  paperHeight = globalParams->getPSPaperHeight();
+  imgLLX = imgLLXA;
+  imgLLY = imgLLYA;
+  imgURX = imgURXA;
+  imgURY = imgURYA;
+  if (imgLLX == 0 && imgURX == 0 && imgLLY == 0 && imgURY == 0) {
+    globalParams->getPSImageableArea(&imgLLX, &imgLLY, &imgURX, &imgURY);
   }
   if (paperWidth < 0 || paperHeight < 0) {
-    page = catalog->getPage(firstPage);
-    paperWidth = (int)(page->getWidth() + 0.5);
-    paperHeight = (int)(page->getHeight() + 0.5);
+    // this check is needed in case the document has zero pages
+    if (firstPage > 0 && firstPage <= catalog->getNumPages()) {
+      page = catalog->getPage(firstPage);
+      paperWidth = (int)(page->getWidth() + 0.5);
+      paperHeight = (int)(page->getHeight() + 0.5);
+    } else {
+      paperWidth = 1;
+      paperHeight = 1;
+    }
+    imgLLX = imgLLY = 0;
+    imgURX = paperWidth;
+    imgURY = paperHeight;
   }
   manualCtrl = manualCtrlA;
   if (mode == psModeForm) {
@@ -688,6 +793,12 @@ void PSOutputDev::init(PSOutputFunc outputFuncA, void *outputStreamA,
   opi20Nest = 0;
 #endif
 
+  tx0 = ty0 = 0;
+  xScale0 = yScale0 = 1;
+  rotate0 = 0;
+  clipLLX0 = clipLLY0 = 0;
+  clipURX0 = clipURY0 = -1;
+
   // initialize fontIDs, fontFileIDs, and fontFileNames lists
   fontIDSize = 64;
   fontIDLen = 0;
@@ -709,7 +820,16 @@ void PSOutputDev::init(PSOutputFunc outputFuncA, void *outputStreamA,
   embFontList = new GString();
 
   if (!manualCtrl) {
-    writeHeader(firstPage, lastPage, catalog->getPage(firstPage)->getBox());
+    // this check is needed in case the document has zero pages
+    if (firstPage > 0 && firstPage <= catalog->getNumPages()) {
+      writeHeader(firstPage, lastPage,
+                 catalog->getPage(firstPage)->getBox(),
+                 catalog->getPage(firstPage)->getCropBox());
+    } else {
+      box = new PDFRectangle(0, 0, 1, 1);
+      writeHeader(firstPage, lastPage, box, box);
+      delete box;
+    }
     if (mode != psModeForm) {
       writePS("%%BeginProlog\n");
     }
@@ -786,7 +906,8 @@ PSOutputDev::~PSOutputDev() {
   }
 }
 
-void PSOutputDev::writeHeader(int firstPage, int lastPage, PDFRectangle *box) {
+void PSOutputDev::writeHeader(int firstPage, int lastPage,
+                             PDFRectangle *mediaBox, PDFRectangle *cropBox) {
   switch (mode) {
   case psModePS:
     writePS("%!PS-Adobe-3.0\n");
@@ -819,14 +940,14 @@ void PSOutputDev::writeHeader(int firstPage, int lastPage, PDFRectangle *box) {
       writePS("%%DocumentCustomColors: (atend)\n");
     }
     writePSFmt("%%%%BoundingBox: %d %d %d %d\n",
-              (int)floor(box->x1), (int)floor(box->y1),
-              (int)ceil(box->x2), (int)ceil(box->y2));
-    if (floor(box->x1) != ceil(box->x1) ||
-       floor(box->y1) != ceil(box->y1) ||
-       floor(box->x2) != ceil(box->x2) ||
-       floor(box->y2) != ceil(box->y2)) {
+              (int)floor(cropBox->x1), (int)floor(cropBox->y1),
+              (int)ceil(cropBox->x2), (int)ceil(cropBox->y2));
+    if (floor(cropBox->x1) != ceil(cropBox->x1) ||
+       floor(cropBox->y1) != ceil(cropBox->y1) ||
+       floor(cropBox->x2) != ceil(cropBox->x2) ||
+       floor(cropBox->y2) != ceil(cropBox->y2)) {
       writePSFmt("%%%%HiResBoundingBox: %g %g %g %g\n",
-                box->x1, box->y1, box->x2, box->y2);
+                cropBox->x1, cropBox->y1, cropBox->x2, cropBox->y2);
     }
     writePS("%%DocumentSuppliedResources: (atend)\n");
     writePS("%%EndComments\n");
@@ -845,7 +966,8 @@ void PSOutputDev::writeHeader(int firstPage, int lastPage, PDFRectangle *box) {
     writePS("%%EndComments\n");
     writePS("32 dict dup begin\n");
     writePSFmt("/BBox [%d %d %d %d] def\n",
-              (int)box->x1, (int)box->y1, (int)box->x2, (int)box->y2);
+              (int)floor(mediaBox->x1), (int)floor(mediaBox->y1),
+              (int)ceil(mediaBox->x2), (int)ceil(mediaBox->y2));
     writePS("/FormType 1 def\n");
     writePS("/Matrix [1 0 0 1 0 0] def\n");
     break;
@@ -1044,8 +1166,9 @@ void PSOutputDev::setupFonts(Dict *resDict) {
   }
   if (gfxFontDict) {
     for (i = 0; i < gfxFontDict->getNumFonts(); ++i) {
-      font = gfxFontDict->getFont(i);
-      setupFont(font, resDict);
+      if ((font = gfxFontDict->getFont(i))) {
+       setupFont(font, resDict);
+      }
     }
     delete gfxFontDict;
   }
@@ -1455,7 +1578,7 @@ void PSOutputDev::setupEmbeddedType1CFont(GfxFont *font, Ref *id,
                                          GString *psName) {
   char *fontBuf;
   int fontLen;
-  Type1CFontFile *t1cFile;
+  FoFiType1C *ffT1C;
   int i;
 
   // check if font is already embedded
@@ -1480,11 +1603,10 @@ void PSOutputDev::setupEmbeddedType1CFont(GfxFont *font, Ref *id,
 
   // convert it to a Type 1 font
   fontBuf = font->readEmbFontFile(xref, &fontLen);
-  t1cFile = new Type1CFontFile(fontBuf, fontLen);
-  if (t1cFile->isOk()) {
-    t1cFile->convertToType1(outputFunc, outputStream);
+  if ((ffT1C = FoFiType1C::make(fontBuf, fontLen))) {
+    ffT1C->convertToType1(NULL, gTrue, outputFunc, outputStream);
+    delete ffT1C;
   }
-  delete t1cFile;
   gfree(fontBuf);
 
   // ending comment
@@ -1496,7 +1618,7 @@ void PSOutputDev::setupEmbeddedTrueTypeFont(GfxFont *font, Ref *id,
   char unique[32];
   char *fontBuf;
   int fontLen;
-  TrueTypeFontFile *ttFile;
+  FoFiTrueType *ffTT;
   Gushort *codeToGID;
   int i;
 
@@ -1527,15 +1649,16 @@ void PSOutputDev::setupEmbeddedTrueTypeFont(GfxFont *font, Ref *id,
 
   // convert it to a Type 42 font
   fontBuf = font->readEmbFontFile(xref, &fontLen);
-  ttFile = new TrueTypeFontFile(fontBuf, fontLen);
-  codeToGID = ((Gfx8BitFont *)font)->getCodeToGIDMap(ttFile);
-  ttFile->convertToType42(psName->getCString(),
-                         ((Gfx8BitFont *)font)->getEncoding(),
-                         ((Gfx8BitFont *)font)->getHasEncoding(),
-                         codeToGID,
-                         outputFunc, outputStream);
-  gfree(codeToGID);
-  delete ttFile;
+  if ((ffTT = FoFiTrueType::make(fontBuf, fontLen))) {
+    codeToGID = ((Gfx8BitFont *)font)->getCodeToGIDMap(ffTT);
+    ffTT->convertToType42(psName->getCString(),
+                         ((Gfx8BitFont *)font)->getHasEncoding()
+                           ? ((Gfx8BitFont *)font)->getEncoding()
+                           : (char **)NULL,
+                         codeToGID, outputFunc, outputStream);
+    gfree(codeToGID);
+    delete ffTT;
+  }
   gfree(fontBuf);
 
   // ending comment
@@ -1547,7 +1670,7 @@ void PSOutputDev::setupExternalTrueTypeFont(GfxFont *font, GString *psName) {
   GString *fileName;
   char *fontBuf;
   int fontLen;
-  TrueTypeFontFile *ttFile;
+  FoFiTrueType *ffTT;
   Gushort *codeToGID;
   int i;
 
@@ -1580,14 +1703,15 @@ void PSOutputDev::setupExternalTrueTypeFont(GfxFont *font, GString *psName) {
 
   // convert it to a Type 42 font
   fontBuf = font->readExtFontFile(&fontLen);
-  ttFile = new TrueTypeFontFile(fontBuf, fontLen);
-  codeToGID = ((Gfx8BitFont *)font)->getCodeToGIDMap(ttFile);
-  ttFile->convertToType42(psName->getCString(),
-                         ((Gfx8BitFont *)font)->getEncoding(),
-                         ((Gfx8BitFont *)font)->getHasEncoding(),
-                         codeToGID,
-                         outputFunc, outputStream);
-  delete ttFile;
+  if ((ffTT = FoFiTrueType::make(fontBuf, fontLen))) {
+    codeToGID = ((Gfx8BitFont *)font)->getCodeToGIDMap(ffTT);
+    ffTT->convertToType42(psName->getCString(),
+                         ((Gfx8BitFont *)font)->getHasEncoding()
+                           ? ((Gfx8BitFont *)font)->getEncoding()
+                           : (char **)NULL,
+                         codeToGID, outputFunc, outputStream);
+    delete ffTT;
+  }
   gfree(fontBuf);
 
   // ending comment
@@ -1598,7 +1722,7 @@ void PSOutputDev::setupEmbeddedCIDType0Font(GfxFont *font, Ref *id,
                                            GString *psName) {
   char *fontBuf;
   int fontLen;
-  Type1CFontFile *t1cFile;
+  FoFiType1C *ffT1C;
   int i;
 
   // check if font is already embedded
@@ -1623,18 +1747,16 @@ void PSOutputDev::setupEmbeddedCIDType0Font(GfxFont *font, Ref *id,
 
   // convert it to a Type 0 font
   fontBuf = font->readEmbFontFile(xref, &fontLen);
-  t1cFile = new Type1CFontFile(fontBuf, fontLen);
-  if (t1cFile->isOk()) {
+  if ((ffT1C = FoFiType1C::make(fontBuf, fontLen))) {
     if (globalParams->getPSLevel() >= psLevel3) {
       // Level 3: use a CID font
-      t1cFile->convertToCIDType0(psName->getCString(),
-                                outputFunc, outputStream);
+      ffT1C->convertToCIDType0(psName->getCString(), outputFunc, outputStream);
     } else {
       // otherwise: use a non-CID composite font
-      t1cFile->convertToType0(psName->getCString(), outputFunc, outputStream);
+      ffT1C->convertToType0(psName->getCString(), outputFunc, outputStream);
     }
+    delete ffT1C;
   }
-  delete t1cFile;
   gfree(fontBuf);
 
   // ending comment
@@ -1645,7 +1767,7 @@ void PSOutputDev::setupEmbeddedCIDTrueTypeFont(GfxFont *font, Ref *id,
                                               GString *psName) {
   char *fontBuf;
   int fontLen;
-  TrueTypeFontFile *ttFile;
+  FoFiTrueType *ffTT;
   int i;
 
   // check if font is already embedded
@@ -1670,20 +1792,22 @@ void PSOutputDev::setupEmbeddedCIDTrueTypeFont(GfxFont *font, Ref *id,
 
   // convert it to a Type 0 font
   fontBuf = font->readEmbFontFile(xref, &fontLen);
-  ttFile = new TrueTypeFontFile(fontBuf, fontLen);
-  if (globalParams->getPSLevel() >= psLevel3) {
-    ttFile->convertToCIDType2(psName->getCString(),
+  if ((ffTT = FoFiTrueType::make(fontBuf, fontLen))) {
+    if (globalParams->getPSLevel() >= psLevel3) {
+      // Level 3: use a CID font
+      ffTT->convertToCIDType2(psName->getCString(),
                              ((GfxCIDFont *)font)->getCIDToGID(),
                              ((GfxCIDFont *)font)->getCIDToGIDLen(),
                              outputFunc, outputStream);
-  } else {
-    // otherwise: use a non-CID composite font
-    ttFile->convertToType0(psName->getCString(),
+    } else {
+      // otherwise: use a non-CID composite font
+      ffTT->convertToType0(psName->getCString(),
                           ((GfxCIDFont *)font)->getCIDToGID(),
                           ((GfxCIDFont *)font)->getCIDToGIDLen(),
                           outputFunc, outputStream);
+    }
+    delete ffTT;
   }
-  delete ttFile;
   gfree(fontBuf);
 
   // ending comment
@@ -1717,7 +1841,7 @@ void PSOutputDev::setupType3Font(GfxFont *font, GString *psName,
   embFontList->append("\n");
 
   // font dictionary
-  writePS("7 dict begin\n");
+  writePS("8 dict begin\n");
   writePS("/FontType 3 def\n");
   m = font->getFontMatrix();
   writePSFmt("/FontMatrix [%g %g %g %g %g %g] def\n",
@@ -1811,11 +1935,14 @@ void PSOutputDev::setupImages(Dict *resDict) {
 }
 
 void PSOutputDev::setupImage(Ref id, Stream *str) {
+  GBool useASCIIHex;
   int c;
   int size, line, col, i;
 
   // construct an encoder stream
-  if (globalParams->getPSASCIIHex()) {
+  useASCIIHex = level == psLevel1 || level == psLevel1Sep ||
+                globalParams->getPSASCIIHex();
+  if (useASCIIHex) {
     str = new ASCIIHexEncoder(str);
   } else {
     str = new ASCII85Encoder(str);
@@ -1828,18 +1955,18 @@ void PSOutputDev::setupImage(Ref id, Stream *str) {
     do {
       c = str->getChar();
     } while (c == '\n' || c == '\r');
-    if (c == '~' || c == EOF) {
+    if (c == (useASCIIHex ? '>' : '~') || c == EOF) {
       break;
     }
     if (c == 'z') {
       ++col;
     } else {
       ++col;
-      for (i = 1; i <= 4; ++i) {
+      for (i = 1; i <= (useASCIIHex ? 1 : 4); ++i) {
        do {
          c = str->getChar();
        } while (c == '\n' || c == '\r');
-       if (c == '~' || c == EOF) {
+       if (c == (useASCIIHex ? '>' : '~') || c == EOF) {
          break;
        }
        ++col;
@@ -1849,7 +1976,7 @@ void PSOutputDev::setupImage(Ref id, Stream *str) {
       ++size;
       col = 0;
     }
-  } while (c != '~' && c != EOF);
+  } while (c != (useASCIIHex ? '>' : '~') && c != EOF);
   ++size;
   writePSFmt("%d array dup /ImData_%d_%d exch def\n", size, id.num, id.gen);
   str->close();
@@ -1857,12 +1984,12 @@ void PSOutputDev::setupImage(Ref id, Stream *str) {
   // write the data into the array
   str->reset();
   line = col = 0;
-  writePS("dup 0 <~");
+  writePS((char *)(useASCIIHex ? "dup 0 <" : "dup 0 <~"));
   do {
     do {
       c = str->getChar();
     } while (c == '\n' || c == '\r');
-    if (c == '~' || c == EOF) {
+    if (c == (useASCIIHex ? '>' : '~') || c == EOF) {
       break;
     }
     if (c == 'z') {
@@ -1871,11 +1998,11 @@ void PSOutputDev::setupImage(Ref id, Stream *str) {
     } else {
       writePSChar(c);
       ++col;
-      for (i = 1; i <= 4; ++i) {
+      for (i = 1; i <= (useASCIIHex ? 1 : 4); ++i) {
        do {
          c = str->getChar();
        } while (c == '\n' || c == '\r');
-       if (c == '~' || c == EOF) {
+       if (c == (useASCIIHex ? '>' : '~') || c == EOF) {
          break;
        }
        writePSChar(c);
@@ -1887,13 +2014,13 @@ void PSOutputDev::setupImage(Ref id, Stream *str) {
     // chunks are 1 or 4 bytes each, so we have to stop at 232
     // but make it 225 just to be safe
     if (col > 225) {
-      writePS("~> put\n");
+      writePS((char *)(useASCIIHex ? "> put\n" : "~> put\n"));
       ++line;
-      writePSFmt("dup %d <~", line);
+      writePSFmt((char *)(useASCIIHex ? "dup %d <" : "dup %d <~"), line);
       col = 0;
     }
-  } while (c != '~' && c != EOF);
-  writePS("~> put\n");
+  } while (c != (useASCIIHex ? '>' : '~') && c != EOF);
+  writePS((char *)(useASCIIHex ? "> put\n" : "~> put\n"));
   writePS("pop\n");
   str->close();
 
@@ -1901,7 +2028,8 @@ void PSOutputDev::setupImage(Ref id, Stream *str) {
 }
 
 void PSOutputDev::startPage(int pageNum, GfxState *state) {
-  int x1, y1, x2, y2, width, height, paperWidth2, paperHeight2;
+  int x1, y1, x2, y2, width, height;
+  int imgWidth, imgHeight, imgWidth2, imgHeight2;
 
 
   switch (mode) {
@@ -1911,53 +2039,70 @@ void PSOutputDev::startPage(int pageNum, GfxState *state) {
     writePS("%%BeginPageSetup\n");
 
     // rotate, translate, and scale page
+    imgWidth = imgURX - imgLLX;
+    imgHeight = imgURY - imgLLY;
     x1 = (int)(state->getX1() + 0.5);
     y1 = (int)(state->getY1() + 0.5);
     x2 = (int)(state->getX2() + 0.5);
     y2 = (int)(state->getY2() + 0.5);
     width = x2 - x1;
     height = y2 - y1;
-    if (width > height && width > paperWidth) {
-      landscape = gTrue;
+    tx = ty = 0;
+    // portrait or landscape
+    if (width > height && width > imgWidth) {
+      rotate = 90;
       writePSFmt("%%%%PageOrientation: %s\n",
                 state->getCTM()[0] ? "Landscape" : "Portrait");
       writePS("pdfStartPage\n");
       writePS("90 rotate\n");
-      tx = -x1;
-      ty = -(y1 + paperWidth);
-      paperWidth2 = paperHeight;
-      paperHeight2 = paperWidth;
+      ty = -imgWidth;
+      imgWidth2 = imgHeight;
+      imgHeight2 = imgWidth;
     } else {
-      landscape = gFalse;
+      rotate = 0;
       writePSFmt("%%%%PageOrientation: %s\n",
                 state->getCTM()[0] ? "Portrait" : "Landscape");
       writePS("pdfStartPage\n");
-      tx = -x1;
-      ty = -y1;
-      paperWidth2 = paperWidth;
-      paperHeight2 = paperHeight;
-    }
-    if (width < paperWidth2) {
-      tx += (paperWidth2 - width) / 2;
-    }
-    if (height < paperHeight2) {
-      ty += (paperHeight2 - height) / 2;
-    }
-    if (tx != 0 || ty != 0) {
-      writePSFmt("%g %g translate\n", tx, ty);
-    }
-    if (width > paperWidth2 || height > paperHeight2) {
-      xScale = (double)paperWidth2 / (double)width;
-      yScale = (double)paperHeight2 / (double)height;
+      imgWidth2 = imgWidth;
+      imgHeight2 = imgHeight;
+    }
+    // shrink or expand
+    if ((globalParams->getPSShrinkLarger() &&
+        (width > imgWidth2 || height > imgHeight2)) ||
+       (globalParams->getPSExpandSmaller() &&
+        (width < imgWidth2 && height < imgHeight2))) {
+      xScale = (double)imgWidth2 / (double)width;
+      yScale = (double)imgHeight2 / (double)height;
       if (yScale < xScale) {
        xScale = yScale;
       } else {
        yScale = xScale;
       }
-      writePSFmt("%0.4f %0.4f scale\n", xScale, xScale);
     } else {
       xScale = yScale = 1;
     }
+    // deal with odd bounding boxes
+    tx -= xScale * x1;
+    ty -= yScale * y1;
+    // center
+    if (globalParams->getPSCenter()) {
+      tx += (imgWidth2 - xScale * width) / 2;
+      ty += (imgHeight2 - yScale * height) / 2;
+    }
+    tx += imgLLX + tx0;
+    ty += imgLLY + ty0;
+    xScale *= xScale0;
+    yScale *= yScale0;
+    if (tx != 0 || ty != 0) {
+      writePSFmt("%g %g translate\n", tx, ty);
+    }
+    if (xScale != 1 || yScale != 1) {
+      writePSFmt("%0.4f %0.4f scale\n", xScale, xScale);
+    }
+    if (clipLLX0 < clipURX0 && clipLLY0 < clipURY0) {
+      writePSFmt("%g %g %g %g re W\n",
+                clipLLX0, clipLLY0, clipURX0 - clipLLX0, clipURY0 - clipLLY0);
+    }
 
     writePS("%%EndPageSetup\n");
     ++seqPage;
@@ -1967,7 +2112,7 @@ void PSOutputDev::startPage(int pageNum, GfxState *state) {
     writePS("pdfStartPage\n");
     tx = ty = 0;
     xScale = yScale = 1;
-    landscape = gFalse;
+    rotate = 0;
     break;
 
   case psModeForm:
@@ -1976,7 +2121,7 @@ void PSOutputDev::startPage(int pageNum, GfxState *state) {
     writePS("pdfStartPage\n");
     tx = ty = 0;
     xScale = yScale = 1;
-    landscape = gFalse;
+    rotate = 0;
     break;
   }
 
@@ -2229,7 +2374,12 @@ void PSOutputDev::updateWordSpace(GfxState *state) {
 }
 
 void PSOutputDev::updateHorizScaling(GfxState *state) {
-  writePSFmt("%g Tz\n", state->getHorizScaling());
+  double h;
+
+  if ((h = state->getHorizScaling()) < 0.01) {
+    h = 0.01;
+  }
+  writePSFmt("%g Tz\n", h);
 }
 
 void PSOutputDev::updateTextPos(GfxState *state) {
@@ -2451,7 +2601,7 @@ void PSOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str,
 
   len = height * ((width + 7) / 8);
   if (level == psLevel1 || level == psLevel1Sep) {
-    doImageL1(NULL, invert, inlineImg, str, width, height, len);
+    doImageL1(ref, NULL, invert, inlineImg, str, width, height, len);
   } else {
     doImageL2(ref, NULL, invert, inlineImg, str, width, height, len);
   }
@@ -2466,7 +2616,7 @@ void PSOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
                   colorMap->getBits() + 7) / 8);
   switch (level) {
   case psLevel1:
-    doImageL1(colorMap, gFalse, inlineImg, str, width, height, len);
+    doImageL1(ref, colorMap, gFalse, inlineImg, str, width, height, len);
     break;
   case psLevel1Sep:
     //~ handle indexed, separation, ... color spaces
@@ -2482,16 +2632,56 @@ void PSOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
   t3Cacheable = gFalse;
 }
 
-void PSOutputDev::doImageL1(GfxImageColorMap *colorMap,
+void PSOutputDev::doImageL1(Object *ref, GfxImageColorMap *colorMap,
                            GBool invert, GBool inlineImg,
                            Stream *str, int width, int height, int len) {
   ImageStream *imgStr;
   Guchar pixBuf[gfxColorMaxComps];
   double gray;
-  int x, y, i;
+  int col, x, y, c, i;
 
-  // width, height, matrix, bits per component
-  if (colorMap) {
+  if (inType3Char && !colorMap) {
+    if (inlineImg) {
+      // create an array
+      str = new FixedLengthEncoder(str, len);
+      str = new ASCIIHexEncoder(str);
+      str->reset();
+      col = 0;
+      writePS("[<");
+      do {
+       do {
+         c = str->getChar();
+       } while (c == '\n' || c == '\r');
+       if (c == '>' || c == EOF) {
+         break;
+       }
+       writePSChar(c);
+       ++col;
+       // each line is: "<...data...><eol>"
+       // so max data length = 255 - 4 = 251
+       // but make it 240 just to be safe
+       // chunks are 2 bytes each, so we need to stop on an even col number
+       if (col == 240) {
+         writePS(">\n<");
+         col = 0;
+       }
+      } while (c != '>' && c != EOF);
+      writePS(">]\n");
+      writePS("0\n");
+      str->close();
+      delete str;
+    } else {
+      // set up to use the array already created by setupImages()
+      writePSFmt("ImData_%d_%d 0\n", ref->getRefNum(), ref->getRefGen());
+    }
+  }
+
+  // image/imagemask command
+  if (inType3Char && !colorMap) {
+    writePSFmt("%d %d %s [%d 0 0 %d 0 %d] pdfImM1a\n",
+              width, height, invert ? "true" : "false",
+              width, -height, height);
+  } else if (colorMap) {
     writePSFmt("%d %d 8 [%d 0 0 %d 0 %d] pdfIm1\n",
               width, height,
               width, -height, height);
@@ -2501,51 +2691,54 @@ void PSOutputDev::doImageL1(GfxImageColorMap *colorMap,
               width, -height, height);
   }
 
-  // image
-  if (colorMap) {
+  // image data
+  if (!(inType3Char && !colorMap)) {
 
-    // set up to process the data stream
-    imgStr = new ImageStream(str, width, colorMap->getNumPixelComps(),
-                            colorMap->getBits());
-    imgStr->reset();
+    if (colorMap) {
 
-    // process the data stream
-    i = 0;
-    for (y = 0; y < height; ++y) {
+      // set up to process the data stream
+      imgStr = new ImageStream(str, width, colorMap->getNumPixelComps(),
+                              colorMap->getBits());
+      imgStr->reset();
 
-      // write the line
-      for (x = 0; x < width; ++x) {
-       imgStr->getPixel(pixBuf);
-       colorMap->getGray(pixBuf, &gray);
-       writePSFmt("%02x", (int)(gray * 255 + 0.5));
-       if (++i == 32) {
-         writePSChar('\n');
-         i = 0;
+      // process the data stream
+      i = 0;
+      for (y = 0; y < height; ++y) {
+
+       // write the line
+       for (x = 0; x < width; ++x) {
+         imgStr->getPixel(pixBuf);
+         colorMap->getGray(pixBuf, &gray);
+         writePSFmt("%02x", (int)(gray * 255 + 0.5));
+         if (++i == 32) {
+           writePSChar('\n');
+           i = 0;
+         }
        }
       }
-    }
-    if (i != 0) {
-      writePSChar('\n');
-    }
-    delete imgStr;
+      if (i != 0) {
+       writePSChar('\n');
+      }
+      delete imgStr;
 
-  // imagemask
-  } else {
-    str->reset();
-    i = 0;
-    for (y = 0; y < height; ++y) {
-      for (x = 0; x < width; x += 8) {
-       writePSFmt("%02x", str->getChar() & 0xff);
-       if (++i == 32) {
-         writePSChar('\n');
-         i = 0;
+    // imagemask
+    } else {
+      str->reset();
+      i = 0;
+      for (y = 0; y < height; ++y) {
+       for (x = 0; x < width; x += 8) {
+         writePSFmt("%02x", str->getChar() & 0xff);
+         if (++i == 32) {
+           writePSChar('\n');
+           i = 0;
+         }
        }
       }
+      if (i != 0) {
+       writePSChar('\n');
+      }
+      str->close();
     }
-    if (i != 0) {
-      writePSChar('\n');
-    }
-    str->close();
   }
 }
 
@@ -2611,12 +2804,12 @@ void PSOutputDev::doImageL2(Object *ref, GfxImageColorMap *colorMap,
                            Stream *str, int width, int height, int len) {
   GString *s;
   int n, numComps;
-  GBool useRLE, useASCII, useCompressed;
+  GBool useRLE, useASCII, useASCIIHex, useCompressed;
   GfxSeparationColorSpace *sepCS;
   GfxColor color;
   GfxCMYK cmyk;
   int c;
-  int line, col, i;
+  int col, i;
 
   // color space
   if (colorMap) {
@@ -2624,24 +2817,26 @@ void PSOutputDev::doImageL2(Object *ref, GfxImageColorMap *colorMap,
     writePS(" setcolorspace\n");
   }
 
+  useASCIIHex = globalParams->getPSASCIIHex();
+
   // set up the image data
   if (mode == psModeForm || inType3Char) {
     if (inlineImg) {
       // create an array
       str = new FixedLengthEncoder(str, len);
-      if (globalParams->getPSASCIIHex()) {
+      if (useASCIIHex) {
        str = new ASCIIHexEncoder(str);
       } else {
        str = new ASCII85Encoder(str);
       }
       str->reset();
-      line = col = 0;
-      writePS("[<~");
+      col = 0;
+      writePS((char *)(useASCIIHex ? "[<" : "[<~"));
       do {
        do {
          c = str->getChar();
        } while (c == '\n' || c == '\r');
-       if (c == '~' || c == EOF) {
+       if (c == (useASCIIHex ? '>' : '~') || c == EOF) {
          break;
        }
        if (c == 'z') {
@@ -2650,29 +2845,27 @@ void PSOutputDev::doImageL2(Object *ref, GfxImageColorMap *colorMap,
        } else {
          writePSChar(c);
          ++col;
-         for (i = 1; i <= 4; ++i) {
+         for (i = 1; i <= (useASCIIHex ? 1 : 4); ++i) {
            do {
              c = str->getChar();
            } while (c == '\n' || c == '\r');
-           if (c == '~' || c == EOF) {
+           if (c == (useASCIIHex ? '>' : '~') || c == EOF) {
              break;
            }
            writePSChar(c);
            ++col;
          }
        }
-       // each line is: "dup nnnnn <~...data...~> put<eol>"
-       // so max data length = 255 - 20 = 235
-       // chunks are 1 or 4 bytes each, so we have to stop at 232
-       // but make it 225 just to be safe
-       if (col > 225) {
-         writePS("~>\n");
-         ++line;
-         writePSFmt("<~", line);
+       // each line is: "<~...data...~><eol>"
+       // so max data length = 255 - 6 = 249
+       // chunks are 1 or 5 bytes each, so we have to stop at 245
+       // but make it 240 just to be safe
+       if (col > 240) {
+         writePS((char *)(useASCIIHex ? ">\n<" : "~>\n<~"));
          col = 0;
        }
-      } while (c != '~' && c != EOF);
-      writePS("~>]\n");
+      } while (c != (useASCIIHex ? '>' : '~') && c != EOF);
+      writePS((char *)(useASCIIHex ? ">]\n" : "~>]\n"));
       writePS("0\n");
       str->close();
       delete str;
@@ -2689,8 +2882,12 @@ void PSOutputDev::doImageL2(Object *ref, GfxImageColorMap *colorMap,
   writePSFmt("  /Width %d\n", width);
   writePSFmt("  /Height %d\n", height);
   writePSFmt("  /ImageMatrix [%d 0 0 %d 0 %d]\n", width, -height, height);
-  writePSFmt("  /BitsPerComponent %d\n",
-            colorMap ? colorMap->getBits() : 1);
+  if (colorMap && colorMap->getColorSpace()->getMode() == csDeviceN) {
+    writePSFmt("  /BitsPerComponent 8\n");
+  } else {
+    writePSFmt("  /BitsPerComponent %d\n",
+              colorMap ? colorMap->getBits() : 1);
+  }
 
   // decode 
   if (colorMap) {
@@ -2700,6 +2897,16 @@ void PSOutputDev::doImageL2(Object *ref, GfxImageColorMap *colorMap,
       n = (1 << colorMap->getBits()) - 1;
       writePSFmt("%g %g", colorMap->getDecodeLow(0) * n,
                 colorMap->getDecodeHigh(0) * n);
+    } else if (colorMap->getColorSpace()->getMode() == csDeviceN) {
+      numComps = ((GfxDeviceNColorSpace *)colorMap->getColorSpace())->
+                  getAlt()->getNComps();
+      for (i = 0; i < numComps; ++i) {
+       if (i > 0) {
+         writePS(" ");
+       }
+       writePSFmt("0 1", colorMap->getDecodeLow(i),
+                  colorMap->getDecodeHigh(i));
+      }
     } else {
       numComps = colorMap->getNumPixelComps();
       for (i = 0; i < numComps; ++i) {
@@ -2732,7 +2939,8 @@ void PSOutputDev::doImageL2(Object *ref, GfxImageColorMap *colorMap,
     writePS("  /DataSource currentfile\n");
     s = str->getPSFilter(level < psLevel2 ? 1 : level < psLevel3 ? 2 : 3,
                         "    ");
-    if (inlineImg || !s) {
+    if ((colorMap && colorMap->getColorSpace()->getMode() == csDeviceN) ||
+       inlineImg || !s) {
       useRLE = gTrue;
       useASCII = gTrue;
       useCompressed = gFalse;
@@ -2743,7 +2951,7 @@ void PSOutputDev::doImageL2(Object *ref, GfxImageColorMap *colorMap,
     }
     if (useASCII) {
       writePSFmt("    /ASCII%sDecode filter\n",
-                globalParams->getPSASCIIHex() ? "Hex" : "85");
+                useASCIIHex ? "Hex" : "85");
     }
     if (useRLE) {
       writePS("    /RunLengthDecode filter\n");
@@ -2762,12 +2970,17 @@ void PSOutputDev::doImageL2(Object *ref, GfxImageColorMap *colorMap,
       str = str->getBaseStream();
     }
 
+    // recode DeviceN data
+    if (colorMap && colorMap->getColorSpace()->getMode() == csDeviceN) {
+      str = new DeviceNRecoder(str, width, height, colorMap);
+    }
+
     // add RunLengthEncode and ASCIIHex/85 encode filters
     if (useRLE) {
       str = new RunLengthEncoder(str);
     }
     if (useASCII) {
-      if (globalParams->getPSASCIIHex()) {
+      if (useASCIIHex) {
        str = new ASCIIHexEncoder(str);
       } else {
        str = new ASCII85Encoder(str);
@@ -2932,6 +3145,8 @@ void PSOutputDev::dumpColorSpaceL2(GfxColorSpace *colorSpace) {
     break;
 
   case csICCBased:
+    // there is no transform function to the alternate color space, so
+    // we can use it directly
     dumpColorSpaceL2(((GfxICCBasedColorSpace *)colorSpace)->getAlt());
     break;
 
@@ -3380,10 +3595,17 @@ void PSOutputDev::opiTransform(GfxState *state, double x0, double y0,
   state->transform(x0, y0, x1, y1);
   *x1 += tx;
   *y1 += ty;
-  if (landscape) {
+  if (rotate == 90) {
     t = *x1;
     *x1 = -*y1;
     *y1 = t;
+  } else if (rotate == 180) {
+    *x1 = -*x1;
+    *y1 = -*y1;
+  } else if (rotate == 270) {
+    t = *x1;
+    *x1 = *y1;
+    *y1 = -t;
   }
   *x1 *= xScale;
   *y1 *= yScale;
index 06130fbcb853b91b9a5514561c4f95cbcfce9d7f..6c379a9c51a6624e9ef51b4b71c8e0d44a7aeaaa 100644 (file)
@@ -54,14 +54,16 @@ public:
   // Open a PostScript output file, and write the prolog.
   PSOutputDev(char *fileName, XRef *xrefA, Catalog *catalog,
              int firstPage, int lastPage, PSOutMode modeA,
-             int paperWidthA = 0, int paperHeightA = 0,
+             int imgLLXA = 0, int imgLLYA = 0,
+             int imgURXA = 0, int imgURYA = 0,
              GBool manualCtrlA = gFalse);
 
   // Open a PSOutputDev that will write to a generic stream.
   PSOutputDev(PSOutputFunc outputFuncA, void *outputStreamA,
              XRef *xrefA, Catalog *catalog,
              int firstPage, int lastPage, PSOutMode modeA,
-             int paperWidthA = 0, int paperHeightA = 0,
+             int imgLLXA = 0, int imgLLYA = 0,
+             int imgURXA = 0, int imgURYA = 0,
              GBool manualCtrlA = gFalse);
 
   // Destructor -- writes the trailer and closes the file.
@@ -86,7 +88,8 @@ public:
   //----- header/trailer (used only if manualCtrl is true)
 
   // Write the document-level header.
-  void writeHeader(int firstPage, int lastPage, PDFRectangle *box);
+  void writeHeader(int firstPage, int lastPage,
+                  PDFRectangle *mediaBox, PDFRectangle *cropBox);
 
   // Write the Xpdf procset.
   void writeXpdfProcset();
@@ -174,6 +177,14 @@ public:
   virtual void psXObject(Stream *psStream, Stream *level1Stream);
 
   //----- miscellaneous
+  void setOffset(double x, double y)
+    { tx0 = x; ty0 = y; }
+  void setScale(double x, double y)
+    { xScale0 = x; yScale0 = y; }
+  void setRotate(int rotateA)
+    { rotate0 = rotateA; }
+  void setClip(double llx, double lly, double urx, double ury)
+    { clipLLX0 = llx; clipLLY0 = lly; clipURX0 = urx; clipURY0 = ury; }
   void setUnderlayCbk(void (*cbk)(PSOutputDev *psOut, void *data),
                      void *data)
     { underlayCbk = cbk; underlayCbkData = data; }
@@ -186,7 +197,7 @@ private:
   void init(PSOutputFunc outputFuncA, void *outputStreamA,
            PSFileType fileTypeA, XRef *xrefA, Catalog *catalog,
            int firstPage, int lastPage, PSOutMode modeA,
-           int paperWidthA, int paperHeightA,
+           int imgLLXA, int imgLLYA, int imgURXA, int imgURYA,
            GBool manualCtrlA);
   void setupResources(Dict *resDict);
   void setupFonts(Dict *resDict);
@@ -204,7 +215,7 @@ private:
   void addProcessColor(double c, double m, double y, double k);
   void addCustomColor(GfxSeparationColorSpace *sepCS);
   void doPath(GfxPath *path);
-  void doImageL1(GfxImageColorMap *colorMap,
+  void doImageL1(Object *ref, GfxImageColorMap *colorMap,
                 GBool invert, GBool inlineImg,
                 Stream *str, int width, int height, int len);
   void doImageL1Sep(GfxImageColorMap *colorMap,
@@ -232,6 +243,8 @@ private:
   PSOutMode mode;              // PostScript mode (PS, EPS, form)
   int paperWidth;              // width of paper, in pts
   int paperHeight;             // height of paper, in pts
+  int imgLLX, imgLLY,          // imageable area, in pts
+      imgURX, imgURY;
 
   PSOutputFunc outputFunc;
   void *outputStream;
@@ -263,9 +276,14 @@ private:
                                //   processed
   int numSaves;                        // current number of gsaves
 
-  double tx, ty;               // global translation
-  double xScale, yScale;       // global scaling
-  GBool landscape;             // true for landscape, false for portrait
+  double tx0, ty0;             // global translation
+  double xScale0, yScale0;     // global scaling
+  int rotate0;                 // rotation angle (0, 90, 180, 270)
+  double clipLLX0, clipLLY0,
+         clipURX0, clipURY0;
+  double tx, ty;               // global translation for current page
+  double xScale, yScale;       // global scaling for current page
+  int rotate;                  // rotation angle for current page
 
   GString *embFontList;                // resource comments for embedded fonts
 
index e12e65cd2f68c1b71fae6f60c9b220d483f40db3..817e1d52823e3e16507693c91fe84bdcfad5bf4b 100644 (file)
@@ -226,18 +226,20 @@ Page::~Page() {
   contents.free();
 }
 
-void Page::display(OutputDev *out, double hDPI, double vDPI, int rotate,
+void Page::display(OutputDev *out, double hDPI, double vDPI,
+                  int rotate, GBool crop,
                   Links *links, Catalog *catalog,
                   GBool (*abortCheckCbk)(void *data),
                   void *abortCheckCbkData,
                    GBool (*annotDisplayDecideCbk)(Annot *annot, void *user_data),
                    void *annotDisplayDecideCbkData) {
-  displaySlice(out, hDPI, vDPI, rotate, -1, -1, -1, -1, links, catalog,
+  displaySlice(out, hDPI, vDPI, rotate, crop, -1, -1, -1, -1, links, catalog,
               abortCheckCbk, abortCheckCbkData,
                annotDisplayDecideCbk, annotDisplayDecideCbkData);
 }
 
-void Page::displaySlice(OutputDev *out, double hDPI, double vDPI, int rotate,
+void Page::displaySlice(OutputDev *out, double hDPI, double vDPI,
+                       int rotate, GBool crop,
                        int sliceX, int sliceY, int sliceW, int sliceH,
                        Links *links, Catalog *catalog,
                        GBool (*abortCheckCbk)(void *data),
@@ -322,7 +324,7 @@ void Page::displaySlice(OutputDev *out, double hDPI, double vDPI, int rotate,
   }
 
   gfx = new Gfx(xref, out, num, attrs->getResourceDict(),
-               hDPI, vDPI, &box, isCropped(), cropBox, rotate,
+               hDPI, vDPI, &box, crop && isCropped(), cropBox, rotate,
                abortCheckCbk, abortCheckCbkData);
   contents.fetch(xref, &obj);
   if (!obj.isNull()) {
index 8fa1ef603490aa9f1cf929573bd6984574fce0c8..ab6442c751ae509a0345b552b7246ee3760a1b1b 100644 (file)
@@ -146,7 +146,8 @@ public:
   Object *getThumb(Object *obj) { return thumb.fetch(xref, obj); }
 
   // Display a page.
-  void display(OutputDev *out, double hDPI, double vDPI, int rotate,
+  void display(OutputDev *out, double hDPI, double vDPI,
+              int rotate, GBool crop,
               Links *links, Catalog *catalog,
               GBool (*abortCheckCbk)(void *data) = NULL,
               void *abortCheckCbkData = NULL,
@@ -154,7 +155,8 @@ public:
                void *annotDisplayDecideCbkData = NULL);
 
   // Display part of a page.
-  void displaySlice(OutputDev *out, double hDPI, double vDPI, int rotate,
+  void displaySlice(OutputDev *out, double hDPI, double vDPI,
+                   int rotate, GBool crop,
                    int sliceX, int sliceY, int sliceW, int sliceH,
                    Links *links, Catalog *catalog,
                    GBool (*abortCheckCbk)(void *data) = NULL,
index 2f881d46f1880e5a1a454a6b6c2f444e3f9b8bbc..0aa66d32ef0cdf33b18b25c9955d2e948bfd3eab 100644 (file)
@@ -176,7 +176,7 @@ Stream *Parser::makeStream(Object *dict) {
   }
 
   // check for length in damaged file
-  if (xref->getStreamEnd(pos, &endPos)) {
+  if (xref && xref->getStreamEnd(pos, &endPos)) {
     length = endPos - pos;
   }
 
diff --git a/pdf/xpdf/SFont.cc b/pdf/xpdf/SFont.cc
deleted file mode 100644 (file)
index 1f421dd..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-//========================================================================
-//
-// SFont.cc
-//
-// Copyright 2001-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma implementation
-#endif
-
-#include "SFont.h"
-
-//------------------------------------------------------------------------
-
-SFontEngine::SFontEngine(Display *displayA, Visual *visualA, int depthA,
-                        Colormap colormapA) {
-  display = displayA;
-  visual = visualA;
-  depth = depthA;
-  colormap = colormapA;
-}
-
-SFontEngine::~SFontEngine() {
-}
-
-void SFontEngine::useTrueColor(int rMaxA, int rShiftA, int gMaxA, int gShiftA,
-                              int bMaxA, int bShiftA) {
-  trueColor = gTrue;
-  rMax = rMaxA;
-  rShift = rShiftA;
-  gMax = gMaxA;
-  gShift = gShiftA;
-  bMax = bMaxA;
-  bShift = bShiftA;
-}
-
-void SFontEngine::useColorCube(Gulong *colorsA, int nRGBA) {
-  trueColor = gFalse;
-  colors = colorsA;
-  nRGB = nRGBA;
-  rMax = gMax = bMax = nRGB - 1;
-}
-
-Gulong SFontEngine::findColor(int r, int g, int b) {
-  int r1, g1, b1;
-  Gulong pix;
-
-  r1 = ((r & 0xffff) * rMax) / 0xffff;
-  g1 = ((g & 0xffff) * gMax) / 0xffff;
-  b1 = ((b & 0xffff) * bMax) / 0xffff;
-  if (trueColor) {
-    pix = (r1 << rShift) + (g1 << gShift) + (b1 << bShift);
-  } else {
-    pix = colors[(r1 * nRGB + g1) * nRGB + b1];
-  }
-  return pix;
-}
-
-//------------------------------------------------------------------------
-
-SFontFile::SFontFile() {
-}
-
-SFontFile::~SFontFile() {
-}
-
-//------------------------------------------------------------------------
-
-SFont::SFont() {
-}
-
-SFont::~SFont() {
-}
-
-GBool SFont::getCharPath(CharCode c, Unicode u, GfxState *state) {
-  return gFalse;
-}
diff --git a/pdf/xpdf/SFont.h b/pdf/xpdf/SFont.h
deleted file mode 100644 (file)
index aadf991..0000000
+++ /dev/null
@@ -1,142 +0,0 @@
-//========================================================================
-//
-// SFont.h
-//
-// Base class for font rasterizers.
-//
-// Copyright 2001-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#ifndef SFONT_H
-#define SFONT_H
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma interface
-#endif
-
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-#include "gtypes.h"
-#include "CharTypes.h"
-
-class GfxState;
-
-//------------------------------------------------------------------------
-
-class SFontEngine {
-public:
-
-  SFontEngine(Display *displayA, Visual *visualA, int depthA,
-             Colormap colormapA);
-  virtual ~SFontEngine();
-
-  // Use a TrueColor visual.  Pixel values are computed as:
-  //
-  //     (r << rShift) + (g << gShift) + (b << bShift)
-  //
-  // where r, g, and b are scaled to the ranges [0,rMax], [0,gMax],
-  // and [0,bMax], respectively.
-  virtual void useTrueColor(int rMaxA, int rShiftA, int gMaxA, int gShiftA,
-                           int bMaxA, int bShiftA);
-
-  // Use an RGB color cube.  <colors> is an array containing
-  // <nRGB>*<nRGB>*<nRGB> pixel values in red,green,blue order, e.g.,
-  // for <nRGB>=2, there will be 8 entries:
-  //
-  //        |--- colors[i] ---|
-  //     i  red    green  blue
-  //     -  -----  -----  -----
-  //     0  0000   0000   0000
-  //     1  0000   0000   ffff
-  //     2  0000   ffff   0000
-  //     3  0000   ffff   ffff
-  //     4  ffff   0000   0000
-  //     5  ffff   0000   ffff
-  //     6  ffff   ffff   0000
-  //     7  ffff   ffff   ffff
-  //
-  // The <colors> array is not copied and must remain valid for the
-  // lifetime of this SFont object.
-  virtual void useColorCube(Gulong *colorsA, int nRGBA);
-
-protected:
-
-  // Find the closest match to (<r>,<g>,<b>).
-  Gulong findColor(int r, int g, int b);
-
-  //----- X parameters
-  Display *display;
-  Visual *visual;
-  int depth;
-  Colormap colormap;
-
-  GBool trueColor;             // true for TrueColor, false for RGB cube
-
-  //----- TrueColor parameters
-  int rMax, gMax, bMax;
-  int rShift, gShift, bShift;
-
-  //----- RGB color cube parameters
-  Gulong *colors;
-  int nRGB;
-};
-
-//------------------------------------------------------------------------
-
-class SFontFile {
-public:
-
-  // A typical subclass will provide a constructor along the lines of:
-  //
-  //     SomeFontFile(SomeFontEngine *engine, char *fontFileName);
-  SFontFile();
-
-  virtual ~SFontFile();
-
-private:
-};
-
-//------------------------------------------------------------------------
-
-class SFont {
-public:
-
-  // A typical subclass will provide a constructor along the lines of:
-  //
-  //     SomeFont(SomeFontFile *fontFile, double *m);
-  //
-  // where <m> is a transform matrix consisting of four elements,
-  // using the PostScript ordering conventions (without any
-  // translation):
-  //
-  //   [x' y'] = [x y] * [m0 m1]
-  //                     [m2 m3]
-  //
-  // This is the level at which fonts are cached, and so the font
-  // cannot be transformed after it is created.
-  SFont();
-
-  virtual ~SFont();
-
-  // Draw a character <c>/<u> at <x>,<y> in color (<r>,<g>,<b>).  The
-  // RGB values should each be in the range [0,65535].  Draws into
-  // <d>, clipped to the rectangle (0,0)-(<w>-1,<h>-1).  Returns true
-  // if the character was drawn successfully.
-  virtual GBool drawChar(Drawable d, int w, int h, GC gc,
-                        int x, int y, int r, int g, int b,
-                        CharCode c, Unicode u) = 0;
-
-  // Add the outline of the specified character to the current path by
-  // calling state->moveTo, lineTo, and curveTo.  Returns true if
-  // successful.  If this SFont subclass doesn't implement character
-  // paths, returns false immediately without modifying the current
-  // path.
-  virtual GBool getCharPath(CharCode c, Unicode u, GfxState *state);
-
-protected:
-};
-
-#endif
index e770b61dec2953ae1f442e26b9125102ef2dd4d7..49bbb461524ea6e59d4eecaf6ac3d5f9ecb11a07 100644 (file)
@@ -30,6 +30,7 @@
 #endif
 #include "Stream.h"
 #include "JBIG2Stream.h"
+#include "JPXStream.h"
 #include "Stream-CCITT.h"
 
 #ifdef __DJGPP__
@@ -256,6 +257,8 @@ Stream *Stream::makeFilter(char *name, Stream *str, Object *params) {
     }
     str = new JBIG2Stream(str, &globals);
     globals.free();
+  } else if (!strcmp(name, "JPXDecode")) {
+    str = new JPXStream(str);
   } else {
     error(getPos(), "Unknown filter '%s'", name);
     str = new EOFStream(str);
@@ -450,7 +453,7 @@ GBool StreamPredictor::getNextLine() {
   int i, j, k;
 
   // get PNG optimum predictor number
-  if (predictor == 15) {
+  if (predictor >= 10) {
     if ((curPred = str->getRawChar()) == EOF) {
       return gFalse;
     }
@@ -784,20 +787,38 @@ void MemStream::doDecryption(Guchar *fileKey, int keyLength,
 // EmbedStream
 //------------------------------------------------------------------------
 
-EmbedStream::EmbedStream(Stream *strA, Object *dictA):
+EmbedStream::EmbedStream(Stream *strA, Object *dictA,
+                        GBool limitedA, Guint lengthA):
     BaseStream(dictA) {
   str = strA;
+  limited = limitedA;
+  length = lengthA;
 }
 
 EmbedStream::~EmbedStream() {
 }
 
-Stream *EmbedStream::makeSubStream(Guint start, GBool limited,
-                                  Guint length, Object *dictA) {
+Stream *EmbedStream::makeSubStream(Guint start, GBool limitedA,
+                                  Guint lengthA, Object *dictA) {
   error(-1, "Internal: called makeSubStream() on EmbedStream");
   return NULL;
 }
 
+int EmbedStream::getChar() {
+  if (limited && !length) {
+    return EOF;
+  }
+  --length;
+  return str->getChar();
+}
+
+int EmbedStream::lookChar() {
+  if (limited && !length) {
+    return EOF;
+  }
+  return str->lookChar();
+}
+
 void EmbedStream::setPos(Guint pos, int dir) {
   error(-1, "Internal: called setPos() on EmbedStream");
 }
@@ -1263,7 +1284,7 @@ CCITTFaxStream::~CCITTFaxStream() {
 }
 
 void CCITTFaxStream::reset() {
-  int n;
+  short code1;
 
   str->reset();
   eof = gFalse;
@@ -1275,16 +1296,13 @@ void CCITTFaxStream::reset() {
   a0 = 1;
   buf = EOF;
 
-  // get initial end-of-line marker and 2D encoding tag
-  if (endOfBlock) {
-    if (lookBits(12) == 0x001) {
-      eatBits(12);
-    }
-  } else {
-    for (n = 0; n < 11 && lookBits(n) == 0; ++n) ;
-    if (n == 11 && lookBits(12) == 0x001) {
-      eatBits(12);
-    }
+  // skip any initial zero bits and end-of-line marker, and get the 2D
+  // encoding tag
+  while ((code1 = lookBits(12)) == 0) {
+    eatBits(1);
+  }
+  if (code1 == 0x001) {
+    eatBits(12);
   }
   if (encoding > 0) {
     nextLine2D = !lookBits(1);
@@ -1295,10 +1313,7 @@ void CCITTFaxStream::reset() {
 int CCITTFaxStream::lookChar() {
   short code1, code2, code3;
   int a0New;
-#if 0
-  GBool err;
-#endif
-  GBool gotEOL;
+  GBool err, gotEOL;
   int ret;
   int bits, i;
 
@@ -1308,9 +1323,7 @@ int CCITTFaxStream::lookChar() {
   }
 
   // read the next row
-#if 0
   err = gFalse;
-#endif
   if (codingLine[a0] >= columns) {
 
     // 2-D encoding
@@ -1412,13 +1425,8 @@ int CCITTFaxStream::lookChar() {
          return EOF;
        default:
          error(getPos(), "Bad 2D code %04x in CCITTFax stream", code1);
-#if 0
          err = gTrue;
          break;
-#else
-         eof = gTrue;
-         return EOF;
-#endif
        }
       } while (codingLine[a0] < columns);
 
@@ -1447,9 +1455,12 @@ int CCITTFaxStream::lookChar() {
 
     if (codingLine[a0] != columns) {
       error(getPos(), "CCITTFax row is wrong length (%d)", codingLine[a0]);
-#if 0
+      // force the row to be the correct length
+      while (codingLine[a0] > columns) {
+       --a0;
+      }
+      codingLine[++a0] = columns;
       err = gTrue;
-#endif
     }
 
     // byte-align the row
@@ -1505,14 +1516,11 @@ int CCITTFaxStream::lookChar() {
        }
        eof = gTrue;
       }
-    }
 
-#if 0
-    // This looks for an end-of-line marker after an error, however
-    // some (most?) CCITT streams in PDF files don't use end-of-line
-    // markers, and the just-plow-on technique works better in those
-    // cases.
-    else if (err) {
+    // look for an end-of-line marker after an error -- we only do
+    // this if we know the stream contains end-of-line markers because
+    // the "just plow on" technique tends to work better otherwise
+    } else if (err && endOfLine) {
       do {
        if (code1 == EOF) {
          eof = gTrue;
@@ -1522,13 +1530,11 @@ int CCITTFaxStream::lookChar() {
        code1 = lookBits(13);
       } while ((code1 >> 1) != 0x001);
       eatBits(12); 
-      codingLine[++a0] = columns;
       if (encoding > 0) {
        eatBits(1);
        nextLine2D = !(code1 & 1);
       }
     }
-#endif
 
     a0 = 0;
     outputBits = codingLine[1] - codingLine[0];
@@ -3747,6 +3753,10 @@ int FixedLengthEncoder::lookChar() {
   return str->getChar();
 }
 
+GBool FixedLengthEncoder::isBinary(GBool last) {
+  return str->isBinary(gTrue);
+}
+
 //------------------------------------------------------------------------
 // ASCIIHexEncoder
 //------------------------------------------------------------------------
index 0121df19c508452d9ea6b229d251e937d59fb003..0b70afa45c3d4e42a7c58ad3330b3534ae2302b8 100644 (file)
@@ -36,6 +36,7 @@ enum StreamKind {
   strDCT,
   strFlate,
   strJBIG2,
+  strJPX,
   strWeird                     // internal-use stream types
 };
 
@@ -92,7 +93,7 @@ public:
   // Does this stream type potentially contain non-printable chars?
   virtual GBool isBinary(GBool last = gTrue) = 0;
 
-  // Get the BaseStream or EmbedStream of this stream.
+  // Get the BaseStream of this stream.
   virtual BaseStream *getBaseStream() = 0;
 
   // Get the dictionary associated with this stream.
@@ -131,6 +132,7 @@ public:
   virtual Stream *makeSubStream(Guint start, GBool limited,
                                Guint length, Object *dict) = 0;
   virtual void setPos(Guint pos, int dir = 0) = 0;
+  virtual GBool isBinary(GBool last = gTrue) { return last; }
   virtual BaseStream *getBaseStream() { return this; }
   virtual Dict *getDict() { return dict.getDict(); }
 
@@ -273,7 +275,6 @@ public:
     { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
   virtual int getPos() { return bufPos + (bufPtr - buf); }
   virtual void setPos(Guint pos, int dir = 0);
-  virtual GBool isBinary(GBool last = gTrue) { return last; }
   virtual void ignoreLength() { limited = gFalse; }
   virtual Guint getStart() { return start; }
   virtual void moveStart(int delta);
@@ -314,7 +315,6 @@ public:
     { return (bufPtr < bufEnd) ? (*bufPtr & 0xff) : EOF; }
   virtual int getPos() { return (int)(bufPtr - buf); }
   virtual void setPos(Guint pos, int dir = 0);
-  virtual GBool isBinary(GBool last = gTrue) { return last; }
   virtual Guint getStart() { return start; }
   virtual void moveStart(int delta);
 #ifndef NO_DECRYPTION
@@ -345,23 +345,24 @@ private:
 class EmbedStream: public BaseStream {
 public:
 
-  EmbedStream(Stream *strA, Object *dictA);
+  EmbedStream(Stream *strA, Object *dictA, GBool limitedA, Guint lengthA);
   virtual ~EmbedStream();
-  virtual Stream *makeSubStream(Guint start, GBool limited,
-                               Guint length, Object *dictA);
+  virtual Stream *makeSubStream(Guint start, GBool limitedA,
+                               Guint lengthA, Object *dictA);
   virtual StreamKind getKind() { return str->getKind(); }
   virtual void reset() {}
-  virtual int getChar() { return str->getChar(); }
-  virtual int lookChar() { return str->lookChar(); }
+  virtual int getChar();
+  virtual int lookChar();
   virtual int getPos() { return str->getPos(); }
   virtual void setPos(Guint pos, int dir = 0);
-  virtual GBool isBinary(GBool last = gTrue) { return last; }
   virtual Guint getStart();
   virtual void moveStart(int delta);
 
 private:
 
   Stream *str;
+  GBool limited;
+  Guint length;
 };
 
 //------------------------------------------------------------------------
@@ -740,7 +741,7 @@ public:
   virtual int getChar();
   virtual int lookChar();
   virtual GString *getPSFilter(int psLevel, char *indent) { return NULL; }
-  virtual GBool isBinary(GBool last = gTrue) { return gFalse; }
+  virtual GBool isBinary(GBool last = gTrue);
   virtual GBool isEncoder() { return gTrue; }
 
 private:
@@ -825,7 +826,7 @@ public:
   virtual int lookChar()
     { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
   virtual GString *getPSFilter(int psLevel, char *indent) { return NULL; }
-  virtual GBool isBinary(GBool last = gTrue) { return gFalse; }
+  virtual GBool isBinary(GBool last = gTrue) { return gTrue; }
   virtual GBool isEncoder() { return gTrue; }
 
 private:
diff --git a/pdf/xpdf/T1Font.cc b/pdf/xpdf/T1Font.cc
deleted file mode 100644 (file)
index a03351d..0000000
+++ /dev/null
@@ -1,566 +0,0 @@
-//========================================================================
-//
-// T1Font.cc
-//
-// Copyright 2001-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#include <aconf.h>
-
-#if HAVE_T1LIB_H
-
-#ifdef USE_GCC_PRAGMAS
-#pragma implementation
-#endif
-
-#include <math.h>
-#include <string.h>
-#include <X11/Xlib.h>
-#include "gmem.h"
-#include "GfxState.h"
-#include "T1Font.h"
-
-//------------------------------------------------------------------------
-
-int T1FontEngine::t1libInitCount = 0;
-
-//------------------------------------------------------------------------
-
-T1FontEngine::T1FontEngine(Display *displayA, Visual *visualA, int depthA,
-                          Colormap colormapA, GBool aaA, GBool aaHighA):
-  SFontEngine(displayA, visualA, depthA, colormapA)
-{
-  static unsigned long grayVals[17] = {
-    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16
-  };
-
-  ok = gFalse;
-  aa = aaA;
-  aaHigh = aaHighA;
-  //~ for multithreading: need a mutex here
-  if (t1libInitCount == 0) {
-    T1_SetBitmapPad(8);
-    if (!T1_InitLib(NO_LOGFILE | IGNORE_CONFIGFILE | IGNORE_FONTDATABASE |
-                   T1_NO_AFM)) {
-      return;
-    }
-    if (aa) {
-      T1_AASetBitsPerPixel(8);
-      if (aaHigh) {
-       T1_AASetLevel(T1_AA_HIGH);
-       T1_AAHSetGrayValues(grayVals);
-      } else {
-       T1_AASetLevel(T1_AA_LOW);
-       T1_AASetGrayValues(0, 1, 2, 3, 4);
-      }
-    } else {
-      T1_AANSetGrayValues(0, 1);
-    }
-  }
-  ++t1libInitCount;
-  ok = gTrue;
-}
-
-T1FontEngine::~T1FontEngine() {
-  //~ for multithreading: need a mutex here
-  if (--t1libInitCount == 0) {
-    T1_CloseLib();
-  }
-}
-
-//------------------------------------------------------------------------
-
-T1FontFile::T1FontFile(T1FontEngine *engineA, char *fontFileName,
-                      char **fontEnc, double *bboxA) {
-  int encStrSize;
-  char *encPtr;
-  int i;
-
-  ok = gFalse;
-  engine = engineA;
-  enc = NULL;
-  encStr = NULL;
-  for (i = 0; i < 4; ++i) {
-    bbox[i] = bboxA[i];
-  }
-
-  // load the font file
-  if ((id = T1_AddFont(fontFileName)) < 0) {
-    return;
-  }
-  T1_LoadFont(id);
-
-  // reencode it
-  encStrSize = 0;
-  for (i = 0; i < 256; ++i) {
-    if (fontEnc[i]) {
-      encStrSize += strlen(fontEnc[i]) + 1;
-    }
-  }
-  enc = (char **)gmalloc(257 * sizeof(char *));
-  encStr = (char *)gmalloc(encStrSize * sizeof(char));
-  encPtr = encStr;
-  for (i = 0; i < 256; ++i) {
-    if (fontEnc[i]) {
-      strcpy(encPtr, fontEnc[i]);
-      enc[i] = encPtr;
-      encPtr += strlen(encPtr) + 1;
-    } else {
-      enc[i] = ".notdef";
-    }
-  }
-  enc[256] = "custom";
-  T1_ReencodeFont(id, enc);
-
-  ok = gTrue;
-}
-
-T1FontFile::~T1FontFile() {
-  gfree(enc);
-  gfree(encStr);
-  if (id >= 0) {
-    T1_DeleteFont(id);
-  }
-}
-
-//------------------------------------------------------------------------
-
-T1Font::T1Font(T1FontFile *fontFileA, double *m) {
-  T1FontEngine *engine;
-  T1_TMATRIX matrix;
-  BBox bbox;
-  double bbx0, bby0, bbx1, bby1;
-  int x, y, xMin, xMax, yMin, yMax;
-  int i;
-
-  ok = gFalse;
-  fontFile = fontFileA;
-  engine = fontFile->engine;
-
-  id = T1_CopyFont(fontFile->id);
-
-  // compute font size
-  size = (float)sqrt(m[2]*m[2] + m[3]*m[3]);
-
-  // transform the four corners of the font bounding box -- the min
-  // and max values form the bounding box of the transformed font
-  bbx0 = fontFile->bbox[0];
-  bby0 = fontFile->bbox[1];
-  bbx1 = fontFile->bbox[2];
-  bby1 = fontFile->bbox[3];
-  // some fonts in PDF files have bboxes which are just plain wrong,
-  // so we check the font file's bbox too
-  bbox = T1_GetFontBBox(id);
-  if (0.001 * bbox.llx < bbx0) {
-    bbx0 = 0.001 * bbox.llx;
-  }
-  if (0.001 * bbox.lly < bby0) {
-    bby0 = 0.001 * bbox.lly;
-  }
-  if (0.001 * bbox.urx > bbx1) {
-    bbx1 = 0.001 * bbox.urx;
-  }
-  if (0.001 * bbox.ury > bby1) {
-    bby1 = 0.001 * bbox.ury;
-  }
-  // some fonts are completely broken, so we fake it (with values
-  // large enough that most glyphs should fit)
-  if (bbx0 == 0 && bby0 == 0 && bbx1 == 0 && bby1 == 0) {
-    bbx0 = bby0 = -0.5;
-    bbx1 = bby1 = 1.5;
-  }
-  x = (int)(m[0] * bbx0 + m[2] * bby0);
-  xMin = xMax = x;
-  y = (int)(m[1] * bbx0 + m[3] * bby0);
-  yMin = yMax = y;
-  x = (int)(m[0] * bbx0 + m[2] * bby1);
-  if (x < xMin) {
-    xMin = x;
-  } else if (x > xMax) {
-    xMax = x;
-  }
-  y = (int)(m[1] * bbx0 + m[3] * bby1);
-  if (y < yMin) {
-    yMin = y;
-  } else if (y > yMax) {
-    yMax = y;
-  }
-  x = (int)(m[0] * bbx1 + m[2] * bby0);
-  if (x < xMin) {
-    xMin = x;
-  } else if (x > xMax) {
-    xMax = x;
-  }
-  y = (int)(m[1] * bbx1 + m[3] * bby0);
-  if (y < yMin) {
-    yMin = y;
-  } else if (y > yMax) {
-    yMax = y;
-  }
-  x = (int)(m[0] * bbx1 + m[2] * bby1);
-  if (x < xMin) {
-    xMin = x;
-  } else if (x > xMax) {
-    xMax = x;
-  }
-  y = (int)(m[1] * bbx1 + m[3] * bby1);
-  if (y < yMin) {
-    yMin = y;
-  } else if (y > yMax) {
-    yMax = y;
-  }
-  // This is a kludge: some buggy PDF generators embed fonts with
-  // zero bounding boxes.
-  if (xMax == xMin) {
-    xMin = 0;
-    xMax = (int)size;
-  }
-  if (yMax == yMin) {
-    yMin = 0;
-    yMax = (int)(1.2 * size);
-  }
-  // Another kludge: an unusually large xMin or yMin coordinate is
-  // probably wrong.
-  if (xMin > 0) {
-    xMin = 0;
-  }
-  if (yMin > 0) {
-    yMin = 0;
-  }
-  // Another kludge: t1lib doesn't correctly handle fonts with
-  // real (non-integer) bounding box coordinates.
-  if (xMax - xMin > 5000) {
-    xMin = 0;
-    xMax = (int)size;
-  }
-  if (yMax - yMin > 5000) {
-    yMin = 0;
-    yMax = (int)(1.2 * size);
-  }
-  // this should be (max - min + 1), but we add some padding to
-  // deal with rounding errors
-  glyphW = xMax - xMin + 3;
-  glyphH = yMax - yMin + 3;
-  if (engine->aa) {
-    glyphSize = glyphW * glyphH;
-  } else {
-    glyphSize = ((glyphW + 7) >> 3) * glyphH;
-  }
-
-  // set up the glyph pixmap cache
-  cacheAssoc = 8;
-  if (glyphSize <= 256) {
-    cacheSets = 8;
-  } else if (glyphSize <= 512) {
-    cacheSets = 4;
-  } else if (glyphSize <= 1024) {
-    cacheSets = 2;
-  } else {
-    cacheSets = 1;
-  }
-  cache = (Guchar *)gmalloc(cacheSets * cacheAssoc * glyphSize);
-  cacheTags = (T1FontCacheTag *)gmalloc(cacheSets * cacheAssoc *
-                                       sizeof(T1FontCacheTag));
-  for (i = 0; i < cacheSets * cacheAssoc; ++i) {
-    cacheTags[i].mru = i & (cacheAssoc - 1);
-  }
-
-  // create the XImage
-  if (!(image = XCreateImage(engine->display, engine->visual, engine->depth,
-                            ZPixmap, 0, NULL, glyphW, glyphH, 8, 0))) {
-    return;
-  }
-  image->data = (char *)gmalloc(glyphH * image->bytes_per_line);
-
-  // transform the font
-  matrix.cxx = m[0] / size;
-  matrix.cxy = m[1] / size;
-  matrix.cyx = m[2] / size;
-  matrix.cyy = m[3] / size;
-  T1_TransformFont(id, &matrix);
-
-  ok = gTrue;
-}
-
-T1Font::~T1Font() {
-  gfree(cacheTags);
-  gfree(cache);
-  if (image) {
-    gfree(image->data);
-    image->data = NULL;
-    XDestroyImage(image);
-  }
-  T1_DeleteFont(id);
-}
-
-GBool T1Font::drawChar(Drawable d, int w, int h, GC gc,
-                      int x, int y, int r, int g, int b,
-                      CharCode c, Unicode u) {
-  T1FontEngine *engine;
-  XColor xcolor;
-  int bgR, bgG, bgB;
-  Gulong colors[17];
-  Guchar *bitmap, *p;
-  GBool tempBitmap;
-  XImage *img;
-  int xOffset, yOffset, x0, y0, x1, y1, gw, gh, w0, h0;
-  int xx, yy, xx1;
-  Guchar pix, mPix;
-  int i;
-
-  engine = fontFile->engine;
-
-  // generate the glyph pixmap
-  if (!(bitmap = getGlyphPixmap(c, &xOffset, &yOffset, &gw, &gh,
-                               &tempBitmap))) {
-    return gFalse;
-  }
-
-  // compute: (x0,y0) = position in destination drawable
-  //          (x1,y1) = position in glyph image
-  //          (w0,h0) = size of image transfer
-  x0 = x - xOffset;
-  y0 = y - yOffset;
-  x1 = 0;
-  y1 = 0;
-  w0 = gw;
-  h0 = gh;
-  if (x0 < 0) {
-    x1 = -x0;
-    w0 += x0;
-    x0 = 0;
-  }
-  if (x0 + w0 > w) {
-    w0 = w - x0;
-  }
-  if (w0 < 0) {
-    goto done;
-  }
-  if (y0 < 0) {
-    y1 = -y0;
-    h0 += y0;
-    y0 = 0;
-  }
-  if (y0 + h0 > h) {
-    h0 = h - y0;
-  }
-  if (h0 < 0) {
-    goto done;
-  }
-
-  // getGlyphPixmap may have returned a larger-than-cache-entry
-  // bitmap, in which case we need to allocate a temporary XImage here
-  if (tempBitmap) {
-    if (!(img = XCreateImage(engine->display, engine->visual, engine->depth,
-                            ZPixmap, 0, NULL, gw, gh, 8, 0))) {
-      goto done;
-    }
-    img->data = (char *)gmalloc(gh * img->bytes_per_line);
-  } else {
-    img = image;
-  }
-
-  // read the X image
-  XGetSubImage(engine->display, d, x0, y0, w0, h0, (1 << engine->depth) - 1,
-              ZPixmap, img, x1, y1);
-
-  if (engine->aa) {
-
-    // compute the colors
-    xcolor.pixel = XGetPixel(img, x1 + w0/2, y1 + h0/2);
-    XQueryColor(engine->display, engine->colormap, &xcolor);
-    bgR = xcolor.red;
-    bgG = xcolor.green;
-    bgB = xcolor.blue;
-    if (engine->aaHigh) {
-      mPix = 16;
-      for (i = 1; i <= 16; ++i) {
-       colors[i] = engine->findColor((i * r + (16 - i) * bgR) / 16,
-                                     (i * g + (16 - i) * bgG) / 16,
-                                     (i * b + (16 - i) * bgB) / 16);
-      }
-    } else {
-      mPix = 4;
-      colors[1] = engine->findColor((r + 3*bgR) / 4,
-                                   (g + 3*bgG) / 4,
-                                   (b + 3*bgB) / 4);
-      colors[2] = engine->findColor((r + bgR) / 2,
-                                   (g + bgG) / 2,
-                                   (b + bgB) / 2);
-      colors[3] = engine->findColor((3*r + bgR) / 4,
-                                   (3*g + bgG) / 4,
-                                   (3*b + bgB) / 4);
-      colors[4] = engine->findColor(r, g, b);
-    }
-
-    // stuff the glyph pixmap into the X image
-    p = bitmap;
-    for (yy = 0; yy < gh; ++yy) {
-      for (xx = 0; xx < gw; ++xx) {
-       pix = *p++;
-       if (pix > 0) {
-         if (pix > mPix) {
-           pix = mPix;
-         }
-         XPutPixel(img, xx, yy, colors[pix]);
-       }
-      }
-    }
-
-  } else {
-
-    // one color
-    colors[1] = engine->findColor(r, g, b);
-
-    // stuff the glyph bitmap into the X image
-    p = bitmap;
-    for (yy = 0; yy < gh; ++yy) {
-      for (xx = 0; xx < gw; xx += 8) {
-       pix = *p++;
-       for (xx1 = xx; xx1 < xx + 8 && xx1 < gw; ++xx1) {
-         if (pix & 0x01) {
-           XPutPixel(img, xx1, yy, colors[1]);
-         }
-         pix >>= 1;
-       }
-      }
-    }
-
-  }
-
-  // draw the X image
-  XPutImage(engine->display, d, gc, img, x1, y1, x0, y0, w0, h0);
-
-  if (tempBitmap) {
-    gfree(img->data);
-    img->data = NULL;
-    XDestroyImage(img);
-  }
- done:
-  if (tempBitmap) {
-    gfree(bitmap);
-  }
-  return gTrue;
-}
-
-Guchar *T1Font::getGlyphPixmap(CharCode c, int *x, int *y, int *w, int *h,
-                              GBool *tempBitmap) {
-  T1FontEngine *engine;
-  GLYPH *glyph;
-  int gSize;
-  int i, j, k;
-  Guchar *ret;
-
-  engine = fontFile->engine;
-
-  // check the cache
-  i = (c & (cacheSets - 1)) * cacheAssoc;
-  for (j = 0; j < cacheAssoc; ++j) {
-    if ((cacheTags[i+j].mru & 0x8000) && cacheTags[i+j].code == c) {
-      *x = cacheTags[i+j].x;
-      *y = cacheTags[i+j].y;
-      *w = cacheTags[i+j].w;
-      *h = cacheTags[i+j].h;
-      for (k = 0; k < cacheAssoc; ++k) {
-       if (k != j &&
-           (cacheTags[i+k].mru & 0x7fff) < (cacheTags[i+j].mru & 0x7fff)) {
-         ++cacheTags[i+k].mru;
-       }
-      }
-      cacheTags[i+j].mru = 0x8000;
-      *tempBitmap = gFalse;
-      return cache + (i+j) * glyphSize;
-    }
-  }
-
-  // generate the glyph pixmap
-  if (engine->aa) {
-    glyph = T1_AASetChar(id, c, size, NULL);
-  } else {
-    glyph = T1_SetChar(id, c, size, NULL);
-  }
-  if (!glyph) {
-    return NULL;
-  }
-
-  // copy the glyph into the cache or a temporary bitmap
-  *x = -glyph->metrics.leftSideBearing;
-  *y = glyph->metrics.ascent;
-  *w = glyph->metrics.rightSideBearing - glyph->metrics.leftSideBearing;
-  *h = glyph->metrics.ascent - glyph->metrics.descent;
-  if (engine->aa) {
-    gSize = *w * *h;
-  } else {
-    gSize = ((*w + 7) >> 3) * *h;
-  }
-  if (*w > glyphW || *h > glyphH) {
-    // the glyph doesn't fit in the bounding box -- return a
-    // temporary, uncached bitmap (this shouldn't happen but some
-    // fonts have incorrect bboxes)
-    ret = (Guchar *)gmalloc(gSize);
-    *tempBitmap = gTrue;
-  } else {
-    // store glyph pixmap in cache
-    ret = NULL; // make gcc happy
-    for (j = 0; j < cacheAssoc; ++j) {
-      if ((cacheTags[i+j].mru & 0x7fff) == cacheAssoc - 1) {
-       cacheTags[i+j].mru = 0x8000;
-       cacheTags[i+j].code = c;
-       cacheTags[i+j].x = *x;
-       cacheTags[i+j].y = *y;
-       cacheTags[i+j].w = *w;
-       cacheTags[i+j].h = *h;
-       ret = cache + (i+j) * glyphSize;
-      } else {
-       ++cacheTags[i+j].mru;
-      }
-    }
-    *tempBitmap = gFalse;
-  }
-  if (glyph->bits) {
-    memcpy(ret, glyph->bits, gSize);
-  } else {
-    memset(ret, 0, gSize);
-  }
-  return ret;
-}
-
-GBool T1Font::getCharPath(CharCode c, Unicode u, GfxState *state) {
-  T1_OUTLINE *outline;
-  T1_PATHSEGMENT *seg;
-  T1_BEZIERSEGMENT *bez;
-  double x, y, x1, y1;
-
-  outline = T1_GetCharOutline(id, c, size, NULL);
-  x = 0;
-  y = 0;
-  for (seg = outline; seg; seg = seg->link) {
-    switch (seg->type) {
-    case T1_PATHTYPE_MOVE:
-      x += seg->dest.x / 65536.0;
-      y += seg->dest.y / 65536.0;
-      state->moveTo(x, y);
-      break;
-    case T1_PATHTYPE_LINE:
-      x += seg->dest.x / 65536.0;
-      y += seg->dest.y / 65536.0;
-      state->lineTo(x, y);
-      break;
-    case T1_PATHTYPE_BEZIER:
-      bez = (T1_BEZIERSEGMENT *)seg;
-      x1 = x + bez->dest.x / 65536.0;
-      y1 = y + bez->dest.y / 65536.0;
-      state->curveTo(x + bez->B.x / 65536.0, y + bez->B.y / 65536.0,
-                    x + bez->C.x / 65536.0, y + bez->C.y / 65536.0,
-                    x1, y1);
-      x = x1;
-      y = y1;
-      break;
-    }
-  }
-  T1_FreeOutline(outline);
-  return gTrue;
-}
-
-#endif // HAVE_T1LIB_H
diff --git a/pdf/xpdf/T1Font.h b/pdf/xpdf/T1Font.h
deleted file mode 100644 (file)
index 416f533..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
-//========================================================================
-//
-// T1Font.h
-//
-// An X wrapper for the t1lib Type 1 font rasterizer.
-//
-// Copyright 2001-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#ifndef T1FONT_H
-#define T1FONT_H
-
-#include <aconf.h>
-
-#if HAVE_T1LIB_H
-
-#ifdef USE_GCC_PRAGMAS
-#pragma interface
-#endif
-
-#include <X11/Xlib.h>
-#include <t1lib.h>
-#include "SFont.h"
-
-class GfxState;
-
-//------------------------------------------------------------------------
-
-class T1FontEngine: public SFontEngine {
-public:
-
-  T1FontEngine(Display *displayA, Visual *visualA, int depthA,
-              Colormap colormapA, GBool aaA, GBool aaHighA);
-  GBool isOk() { return ok; }
-  virtual ~T1FontEngine();
-
-private:
-
-  GBool aa;                    // use anti-aliasing?
-  GBool aaHigh;                        // use high-res anti-aliasing?
-  GBool ok;
-
-  static int t1libInitCount;
-
-  friend class T1FontFile;
-  friend class T1Font;
-};
-
-//------------------------------------------------------------------------
-
-class T1FontFile: public SFontFile {
-public:
-
-  T1FontFile(T1FontEngine *engineA, char *fontFileName,
-            char **fontEnc, double *bboxA);
-  GBool isOk() { return ok; }
-  virtual ~T1FontFile();
-
-private:
-
-  T1FontEngine *engine;
-  int id;                      // t1lib font ID
-  char **enc;
-  char *encStr;
-  double bbox[4];
-  GBool ok;
-
-  friend class T1Font;
-};
-
-//------------------------------------------------------------------------
-
-struct T1FontCacheTag {
-  Gushort code;
-  Gushort mru;                 // valid bit (0x8000) and MRU index
-  int x, y, w, h;              // offset and size of glyph
-};
-
-class T1Font: public SFont {
-public:
-
-  T1Font(T1FontFile *fontFileA, double *m);
-  GBool isOk() { return ok; }
-  virtual ~T1Font();
-  virtual GBool drawChar(Drawable d, int w, int h, GC gc,
-                        int x, int y, int r, int g, int b,
-                        CharCode c, Unicode u);
-  virtual GBool getCharPath(CharCode c, Unicode u, GfxState *state);
-
-private:
-
-  Guchar *getGlyphPixmap(CharCode c, int *x, int *y, int *w, int *h,
-                        GBool *tempBitmap);
-
-  T1FontFile *fontFile;
-  int id;
-  float size;
-  XImage *image;
-  int glyphW, glyphH;          // size of glyph pixmaps
-  int glyphSize;               // size of glyph pixmaps, in bytes
-  Guchar *cache;               // glyph pixmap cache
-  T1FontCacheTag *cacheTags;   // cache tags, i.e., char codes
-  int cacheSets;               // number of sets in cache
-  int cacheAssoc;              // cache associativity (glyphs per set)
-  GBool ok;
-};
-
-#endif // HAVE_T1LIB_H
-
-#endif
diff --git a/pdf/xpdf/TTFont.cc b/pdf/xpdf/TTFont.cc
deleted file mode 100644 (file)
index c499cf1..0000000
+++ /dev/null
@@ -1,485 +0,0 @@
-//========================================================================
-//
-// TTFont.cc
-//
-// Copyright 2001-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#include <aconf.h>
-
-#if !FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
-
-#ifdef USE_GCC_PRAGMAS
-#pragma implementation
-#endif
-
-#include <string.h>
-#include "gmem.h"
-#include "GlobalParams.h"
-#include "TTFont.h"
-
-//------------------------------------------------------------------------
-
-TTFontEngine::TTFontEngine(Display *displayA, Visual *visualA, int depthA,
-                          Colormap colormapA, GBool aaA):
-  SFontEngine(displayA, visualA, depthA, colormapA) {
-  static TT_Byte ttPalette[5] = {0, 1, 2, 3, 4};
-
-  ok = gFalse;
-  if (TT_Init_FreeType(&engine)) {
-    return;
-  }
-  aa = aaA;
-  if (aa) {
-    if (TT_Set_Raster_Gray_Palette(engine, ttPalette)) {
-      return;
-    }
-  }
-  ok = gTrue;
-}
-
-TTFontEngine::~TTFontEngine() {
-  TT_Done_FreeType(engine);
-}
-
-//------------------------------------------------------------------------
-
-TTFontFile::TTFontFile(TTFontEngine *engineA, char *fontFileName,
-                      char **fontEnc, GBool pdfFontHasEncoding) {
-  TT_Face_Properties props;
-  TT_UShort unicodeCmap, macRomanCmap, msSymbolCmap;
-  TT_UShort platform, encoding, i;
-  int j;
-
-  ok = gFalse;
-  engine = engineA;
-  codeMap = NULL;
-  if (TT_Open_Face(engine->engine, fontFileName, &face)) {
-    return;
-  }
-  if (TT_Get_Face_Properties(face, &props)) {
-    return;
-  }
-
-  // To match up with the Adobe-defined behaviour, we choose a cmap
-  // like this:
-  // 1. If the PDF font has an encoding:
-  //    1a. If the PDF font specified MacRomanEncoding and the
-  //        TrueType font has a Macintosh Roman cmap, use it, and
-  //        reverse map the char names through MacRomanEncoding to
-  //        get char codes.
-  //    1b. If the TrueType font has a Microsoft Unicode cmap or a
-  //        non-Microsoft Unicode cmap, use it, and use the Unicode
-  //        indexes, not the char codes.
-  //    1c. If the PDF font is symbolic and the TrueType font has a
-  //        Microsoft Symbol cmap, use it, and use char codes
-  //        directly (possibly with an offset of 0xf000).
-  //    1d. If the TrueType font has a Macintosh Roman cmap, use it,
-  //        as in case 1a.
-  // 2. If the PDF font does not have an encoding:
-  //    2a. If the TrueType font has a Macintosh Roman cmap, use it,
-  //        and use char codes directly (possibly with an offset of
-  //        0xf000).
-  //    2b. If the TrueType font has a Microsoft Symbol cmap, use it,
-  //        and use char codes directly (possible with an offset of
-  //        0xf000).
-  // 3. If none of these rules apply, use the first cmap and hope for
-  //    the best (this shouldn't happen).
-  unicodeCmap = macRomanCmap = msSymbolCmap = 0xffff;
-  for (i = 0; i < props.num_CharMaps; ++i) {
-    if (!TT_Get_CharMap_ID(face, i, &platform, &encoding)) {
-      if ((platform == 3 && encoding == 1) || platform == 0) {
-       unicodeCmap = i;
-      } else if (platform == 1 && encoding == 0) {
-       macRomanCmap = i;
-      } else if (platform == 3 && encoding == 0) {
-       msSymbolCmap = i;
-      }
-    }
-  }
-  i = 0;
-  mode = ttFontModeCharCode;
-  if (pdfFontHasEncoding) {
-    if (unicodeCmap != 0xffff) {
-      i = unicodeCmap;
-      mode = ttFontModeUnicode;
-    } else if (macRomanCmap != 0xffff) {
-      i = macRomanCmap;
-      mode = ttFontModeCodeMap;
-      codeMap = (Guchar *)gmalloc(256 * sizeof(Guchar));
-      for (j = 0; j < 256; ++j) {
-       if (fontEnc[j]) {
-         codeMap[j] = (Guchar)globalParams->getMacRomanCharCode(fontEnc[j]);
-       } else {
-         codeMap[j] = 0;
-       }
-      }
-    }
-  } else {
-    if (macRomanCmap != 0xffff) {
-      i = macRomanCmap;
-      mode = ttFontModeCharCode;
-    } else if (msSymbolCmap != 0xffff) {
-      i = msSymbolCmap;
-      mode = ttFontModeCharCode;
-    }
-  }
-  TT_Get_CharMap(face, i, &charMap);
-
-  ok = gTrue;
-}
-
-TTFontFile::TTFontFile(TTFontEngine *engineA, char *fontFileName,
-                      Gushort *cidToGIDA, int cidToGIDLenA) {
-  ok = gFalse;
-  engine = engineA;
-  codeMap = NULL;
-  cidToGID = cidToGIDA;
-  cidToGIDLen = cidToGIDLenA;
-  if (TT_Open_Face(engine->engine, fontFileName, &face)) {
-    return;
-  }
-  mode = ttFontModeCIDToGIDMap;
-  ok = gTrue;
-}
-
-TTFontFile::~TTFontFile() {
-  TT_Close_Face(face);
-  if (codeMap) {
-    gfree(codeMap);
-  }
-}
-
-//------------------------------------------------------------------------
-
-TTFont::TTFont(TTFontFile *fontFileA, double *m) {
-  TTFontEngine *engine;
-  TT_Face_Properties props;
-  TT_Instance_Metrics metrics;
-  int x, xMin, xMax;
-  int y, yMin, yMax;
-  int i;
-
-  ok = gFalse;
-  fontFile = fontFileA;
-  engine = fontFile->engine;
-  if (TT_New_Instance(fontFile->face, &instance) ||
-      TT_Set_Instance_Resolutions(instance, 72, 72) ||
-      TT_Set_Instance_CharSize(instance, 1000 * 64) ||
-      TT_New_Glyph(fontFile->face, &glyph) ||
-      TT_Get_Face_Properties(fontFile->face, &props) ||
-      TT_Get_Instance_Metrics(instance, &metrics)) {
-    return;
-  }
-
-  // transform the four corners of the font bounding box -- the min
-  // and max values form the bounding box of the transformed font
-  x = (int)((m[0] * props.header->xMin + m[2] * props.header->yMin) *
-           0.001 * metrics.x_ppem / props.header->Units_Per_EM);
-  xMin = xMax = x;
-  y = (int)((m[1] * props.header->xMin + m[3] * props.header->yMin) *
-           0.001 * metrics.x_ppem / props.header->Units_Per_EM);
-  yMin = yMax = y;
-  x = (int)((m[0] * props.header->xMin + m[2] * props.header->yMax) *
-           0.001 * metrics.x_ppem / props.header->Units_Per_EM);
-  if (x < xMin) {
-    xMin = x;
-  } else if (x > xMax) {
-    xMax = x;
-  }
-  y = (int)((m[1] * props.header->xMin + m[3] * props.header->yMax) *
-           0.001 * metrics.x_ppem / props.header->Units_Per_EM);
-  if (y < yMin) {
-    yMin = y;
-  } else if (y > yMax) {
-    yMax = y;
-  }
-  x = (int)((m[0] * props.header->xMax + m[2] * props.header->yMin) *
-           0.001 * metrics.x_ppem / props.header->Units_Per_EM);
-  if (x < xMin) {
-    xMin = x;
-  } else if (x > xMax) {
-    xMax = x;
-  }
-  y = (int)((m[1] * props.header->xMax + m[3] * props.header->yMin) *
-           0.001 * metrics.x_ppem / props.header->Units_Per_EM);
-  if (y < yMin) {
-    yMin = y;
-  } else if (y > yMax) {
-    yMax = y;
-  }
-  x = (int)((m[0] * props.header->xMax + m[2] * props.header->yMax) *
-           0.001 * metrics.x_ppem / props.header->Units_Per_EM);
-  if (x < xMin) {
-    xMin = x;
-  } else if (x > xMax) {
-    xMax = x;
-  }
-  y = (int)((m[1] * props.header->xMax + m[3] * props.header->yMax) *
-           0.001 * metrics.x_ppem / props.header->Units_Per_EM);
-  if (y < yMin) {
-    yMin = y;
-  } else if (y > yMax) {
-    yMax = y;
-  }
-  xOffset = -xMin;
-  yOffset = -yMin;
-  ras.width = xMax - xMin + 1;
-  ras.rows = yMax - yMin + 1;
-
-  // set up the Raster_Map structure
-  if (engine->aa) {
-    ras.width = (ras.width + 3) & ~3;
-    ras.cols = ras.width;
-  } else {
-    ras.width = (ras.width + 7) & ~7;
-    ras.cols = ras.width >> 3;
-  }
-  ras.flow = TT_Flow_Down;
-  ras.size = ras.rows * ras.cols;
-  ras.bitmap = gmalloc(ras.size);
-
-  // set up the glyph pixmap cache
-  cacheAssoc = 8;
-  if (ras.size <= 256) {
-    cacheSets = 8;
-  } else if (ras.size <= 512) {
-    cacheSets = 4;
-  } else if (ras.size <= 1024) {
-    cacheSets = 2;
-  } else {
-    cacheSets = 1;
-  }
-  cache = (Guchar *)gmalloc(cacheSets * cacheAssoc * ras.size);
-  cacheTags = (TTFontCacheTag *)gmalloc(cacheSets * cacheAssoc *
-                                       sizeof(TTFontCacheTag));
-  for (i = 0; i < cacheSets * cacheAssoc; ++i) {
-    cacheTags[i].mru = i & (cacheAssoc - 1);
-  }
-
-  // create the XImage
-  if (!(image = XCreateImage(engine->display, engine->visual, engine->depth,
-                            ZPixmap, 0, NULL, ras.width, ras.rows, 8, 0))) {
-    return;
-  }
-  image->data = (char *)gmalloc(ras.rows * image->bytes_per_line);
-
-  // compute the transform matrix
-  matrix.xx = (TT_Fixed)(m[0] * 65.536);
-  matrix.yx = (TT_Fixed)(m[1] * 65.536);
-  matrix.xy = (TT_Fixed)(m[2] * 65.536);
-  matrix.yy = (TT_Fixed)(m[3] * 65.536);
-
-  ok = gTrue;
-}
-
-TTFont::~TTFont() {
-  gfree(cacheTags);
-  gfree(cache);
-  gfree(image->data);
-  image->data = NULL;
-  XDestroyImage(image);
-  gfree(ras.bitmap);
-  TT_Done_Glyph(glyph);
-  TT_Done_Instance(instance);
-}
-
-GBool TTFont::drawChar(Drawable d, int w, int h, GC gc,
-                      int x, int y, int r, int g, int b,
-                      CharCode c, Unicode u) {
-  TTFontEngine *engine;
-  XColor xcolor;
-  int bgR, bgG, bgB;
-  Gulong colors[5];
-  TT_Byte *p;
-  TT_Byte pix;
-  int xx, yy, xx1;
-  int x0, y0, x1, y1, w0, h0;
-
-  engine = fontFile->engine;
-
-  // compute: (x0,y0) = position in destination drawable
-  //          (x1,y1) = position in glyph image
-  //          (w0,h0) = size of image transfer
-  x0 = x - xOffset;
-  y0 = y - (ras.rows - yOffset);
-  x1 = 0;
-  y1 = 0;
-  w0 = ras.width;
-  h0 = ras.rows;
-  if (x0 < 0) {
-    x1 = -x0;
-    w0 += x0;
-    x0 = 0;
-  }
-  if (x0 + w0 > w) {
-    w0 = w - x0;
-  }
-  if (w0 < 0) {
-    return gTrue;
-  }
-  if (y0 < 0) {
-    y1 = -y0;
-    h0 += y0;
-    y0 = 0;
-  }
-  if (y0 + h0 > h) {
-    h0 = h - y0;
-  }
-  if (h0 < 0) {
-    return gTrue;
-  }
-
-  // read the X image
-  XGetSubImage(engine->display, d, x0, y0, w0, h0, (1 << engine->depth) - 1,
-              ZPixmap, image, x1, y1);
-
-  // generate the glyph pixmap
-  if (!getGlyphPixmap(c, u)) {
-    return gFalse;
-  }
-
-  if (engine->aa) {
-
-    // compute the colors
-    xcolor.pixel = XGetPixel(image, x1 + w0/2, y1 + h0/2);
-    XQueryColor(engine->display, engine->colormap, &xcolor);
-    bgR = xcolor.red;
-    bgG = xcolor.green;
-    bgB = xcolor.blue;
-    colors[1] = engine->findColor((r + 3*bgR) / 4,
-                                 (g + 3*bgG) / 4,
-                                 (b + 3*bgB) / 4);
-    colors[2] = engine->findColor((r + bgR) / 2,
-                                 (g + bgG) / 2,
-                                 (b + bgB) / 2);
-    colors[3] = engine->findColor((3*r + bgR) / 4,
-                                 (3*g + bgG) / 4,
-                                 (3*b + bgB) / 4);
-    colors[4] = engine->findColor(r, g, b);
-
-    // stuff the glyph pixmap into the X image
-    p = (TT_Byte *)ras.bitmap;
-    for (yy = 0; yy < ras.rows; ++yy) {
-      for (xx = 0; xx < ras.width; ++xx) {
-       pix = *p++;
-       if (pix > 0) {
-         if (pix > 4) {
-           pix = 4;
-         }
-         XPutPixel(image, xx, yy, colors[pix]);
-       }
-      }
-    }
-
-  } else {
-
-    // one color
-    colors[1] = engine->findColor(r, g, b);
-
-    // stuff the glyph bitmap into the X image
-    p = (TT_Byte *)ras.bitmap;
-    for (yy = 0; yy < ras.rows; ++yy) {
-      for (xx = 0; xx < ras.width; xx += 8) {
-       pix = *p++;
-       for (xx1 = xx; xx1 < xx + 8 && xx1 < ras.width; ++xx1) {
-         if (pix & 0x80) {
-           XPutPixel(image, xx1, yy, colors[1]);
-         }
-         pix <<= 1;
-       }
-      }
-    }
-
-  }
-
-  // draw the X image
-  XPutImage(engine->display, d, gc, image, x1, y1, x0, y0, w0, h0);
-
-  return gTrue;
-}
-
-GBool TTFont::getGlyphPixmap(CharCode c, Unicode u) {
-  TT_UShort idx;
-  TT_Outline outline;
-  int i, j, k;
-
-  // check the cache
-  i = (c & (cacheSets - 1)) * cacheAssoc;
-  for (j = 0; j < cacheAssoc; ++j) {
-    if ((cacheTags[i+j].mru & 0x8000) && cacheTags[i+j].code == c) {
-      memcpy(ras.bitmap, cache + (i+j) * ras.size, ras.size);
-      for (k = 0; k < cacheAssoc; ++k) {
-       if (k != j &&
-           (cacheTags[i+k].mru & 0x7fff) < (cacheTags[i+j].mru & 0x7fff)) {
-         ++cacheTags[i+k].mru;
-       }
-      }
-      cacheTags[i+j].mru = 0x8000;
-      return gTrue;
-    }
-  }
-
-  // generate the glyph pixmap or bitmap
-  idx = 0; // make gcc happy
-  switch (fontFile->mode) {
-  case ttFontModeUnicode:
-    idx = TT_Char_Index(fontFile->charMap, (TT_UShort)u);
-    break;
-  case ttFontModeCharCode:
-    if ((idx = TT_Char_Index(fontFile->charMap, (TT_UShort)c)) == 0) {
-      idx = TT_Char_Index(fontFile->charMap, (TT_UShort)(0xf000 + c));
-    }
-    break;
-  case ttFontModeCodeMap:
-    if (c <= 0xff) {
-      idx = TT_Char_Index(fontFile->charMap,
-                         (TT_UShort)(fontFile->codeMap[c] & 0xff));
-    } else {
-      idx = 0;
-    }
-    break;
-  case ttFontModeCIDToGIDMap:
-    if (fontFile->cidToGIDLen) {
-      if ((int)c < fontFile->cidToGIDLen) {
-       idx = (TT_UShort)fontFile->cidToGID[c];
-      } else {
-       idx = (TT_UShort)0;
-      }
-    } else {
-      idx = (TT_UShort)c;
-    }
-    break;
-  }
-  if (TT_Load_Glyph(instance, glyph, idx, TTLOAD_DEFAULT) ||
-      TT_Get_Glyph_Outline(glyph, &outline)) {
-    return gFalse;
-  }
-  TT_Transform_Outline(&outline, &matrix);
-  memset(ras.bitmap, 0, ras.size);
-  if (fontFile->engine->aa) {
-    if (TT_Get_Glyph_Pixmap(glyph, &ras, xOffset * 64, yOffset * 64)) {
-      return gFalse;
-    }
-  } else {
-    if (TT_Get_Glyph_Bitmap(glyph, &ras, xOffset * 64, yOffset * 64)) {
-      return gFalse;
-    }
-  }
-
-  // store glyph pixmap in cache
-  for (j = 0; j < cacheAssoc; ++j) {
-    if ((cacheTags[i+j].mru & 0x7fff) == cacheAssoc - 1) {
-      cacheTags[i+j].mru = 0x8000;
-      cacheTags[i+j].code = c;
-      memcpy(cache + (i+j) * ras.size, ras.bitmap, ras.size);
-    } else {
-      ++cacheTags[i+j].mru;
-    }
-  }
-
-  return gTrue;
-}
-
-#endif // !FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
diff --git a/pdf/xpdf/TTFont.h b/pdf/xpdf/TTFont.h
deleted file mode 100644 (file)
index e4740ea..0000000
+++ /dev/null
@@ -1,127 +0,0 @@
-//========================================================================
-//
-// TTFont.h
-//
-// An X wrapper for the FreeType TrueType font rasterizer.
-//
-// Copyright 2001-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#ifndef TTFONT_H
-#define TTFONT_H
-
-#include <aconf.h>
-
-#if !FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
-
-#ifdef USE_GCC_PRAGMAS
-#pragma interface
-#endif
-
-#if HAVE_FREETYPE_FREETYPE_H
-#include <freetype/freetype.h>
-#include <freetype/ftxpost.h>
-#else
-#include <freetype.h>
-#include <ftxpost.h>
-#endif
-#include "gtypes.h"
-#include "SFont.h"
-
-//------------------------------------------------------------------------
-
-class TTFontEngine: public SFontEngine {
-public:
-
-  TTFontEngine(Display *displayA, Visual *visualA, int depthA,
-              Colormap colormapA, GBool aaA);
-  GBool isOk() { return ok; }
-  virtual ~TTFontEngine();
-
-private:
-
-  TT_Engine engine;
-  GBool aa;
-  Gulong palette[5];
-  GBool ok;
-
-  friend class TTFontFile;
-  friend class TTFont;
-};
-
-//------------------------------------------------------------------------
-
-enum TTFontIndexMode {
-  ttFontModeUnicode,
-  ttFontModeCharCode,
-  ttFontModeCodeMap,
-  ttFontModeCIDToGIDMap
-};
-
-class TTFontFile: public SFontFile {
-public:
-
-  // 8-bit font, TrueType or Type 1/1C
-  TTFontFile(TTFontEngine *engineA, char *fontFileName,
-            char **fontEnc, GBool pdfFontHasEncoding);
-
-  // CID font, TrueType
-  TTFontFile(TTFontEngine *engineA, char *fontFileName,
-            Gushort *cidToGIDA, int cidToGIDLenA);
-
-  GBool isOk() { return ok; }
-  virtual ~TTFontFile();
-
-private:
-
-  TTFontEngine *engine;
-  TT_Face face;
-  TT_CharMap charMap;
-  TTFontIndexMode mode;
-  Guchar *codeMap;
-  Gushort *cidToGID;
-  int cidToGIDLen;
-  GBool ok;
-
-  friend class TTFont;
-};
-
-//------------------------------------------------------------------------
-
-struct TTFontCacheTag {
-  Gushort code;
-  Gushort mru;                 // valid bit (0x8000) and MRU index
-};
-
-class TTFont: public SFont {
-public:
-
-  TTFont(TTFontFile *fontFileA, double *m);
-  GBool isOk() { return ok; }
-  virtual ~TTFont();
-  virtual GBool drawChar(Drawable d, int w, int h, GC gc,
-                        int x, int y, int r, int g, int b,
-                        CharCode c, Unicode u);
-
-private:
-
-  GBool getGlyphPixmap(CharCode c, Unicode u);
-
-  TTFontFile *fontFile;
-  TT_Instance instance;
-  TT_Glyph glyph;
-  TT_Raster_Map ras;
-  XImage *image;
-  TT_Matrix matrix;
-  TT_F26Dot6 xOffset, yOffset;
-  Guchar *cache;               // glyph pixmap cache
-  TTFontCacheTag *cacheTags;   // cache tags, i.e., char codes
-  int cacheSets;               // number of sets in cache
-  int cacheAssoc;              // cache associativity (glyphs per set)
-  GBool ok;
-};
-
-#endif // !FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
-
-#endif
index aeee59cd4f32f984981d915bc9b91b931fc29c67..c6fdfb92bb7627d040149200dda70547f97aa539 100644 (file)
 // this many points.
 #define textPoolStep 4
 
-// Inter-character space width which will cause addChar to break up a
-// text string.
-#define defaultSpaceWidth 0.25
+// Inter-character space width which will cause addChar to start a new
+// word.
+#define minWordBreakSpace 0.1
+
+// Negative inter-character space width, i.e., overlap, which will
+// cause addChar to start a new word.
+#define minDupBreakOverlap 0.2
 
 // Max distance between baselines of two lines within a block, as a
 // fraction of the font size.
 
 // Minimum inter-word spacing, as a fraction of the font size.  (Only
 // used for raw ordering.)
-#define minWordSpacing 0.2
+#define minWordSpacing 0.15
 
 // Maximum inter-word spacing, as a fraction of the font size.
 #define maxWordSpacing 1.5
 
+// Maximum horizontal spacing which will allow a word to be pulled
+// into a block.
+#define minColSpacing1 0.3
+
 // Minimum spacing between columns, as a fraction of the font size.
-#define minColSpacing 1.0
+#define minColSpacing2 1.0
 
 // Maximum vertical spacing between blocks within a flow, as a
 // multiple of the font size.
@@ -1591,6 +1599,7 @@ TextPage::TextPage(GBool rawOrderA) {
   curFontSize = 0;
   nest = 0;
   nTinyChars = 0;
+  lastCharOverlap = gFalse;
   if (!rawOrder) {
     for (rot = 0; rot < 4; ++rot) {
       pools[rot] = new TextPool();
@@ -1627,6 +1636,12 @@ void TextPage::startPage(GfxState *state) {
   }
 }
 
+void TextPage::endPage() {
+  if (curWord) {
+    endWord();
+  }
+}
+
 void TextPage::clear() {
   int rot;
   TextFlow *flow;
@@ -1748,7 +1763,7 @@ void TextPage::beginWord(GfxState *state, double x0, double y0) {
 
   // This check is needed because Type 3 characters can contain
   // text-drawing operations (when TextPage is being used via
-  // XOutputDev rather than TextOutputDev).
+  // {X,Win}SplashOutputDev rather than TextOutputDev).
   if (curWord) {
     ++nest;
     return;
@@ -1784,8 +1799,8 @@ void TextPage::beginWord(GfxState *state, double x0, double y0) {
 void TextPage::addChar(GfxState *state, double x, double y,
                       double dx, double dy,
                       CharCode c, Unicode *u, int uLen) {
-  double x1, y1, w1, h1, dx2, dy2, sp;
-  int n, i;
+  double x1, y1, w1, h1, dx2, dy2, base, sp;
+  int i;
 
   // if the previous char was a space, addChar will have called
   // endWord, so we need to start a new word
@@ -1826,21 +1841,46 @@ void TextPage::addChar(GfxState *state, double x, double y,
     return;
   }
 
-  // large char spacing is sometimes used to move text around -- in
-  // this case, break text into individual chars and let the coalesce
-  // function deal with it later
-  n = curWord->len;
-  if (n > 0) {
+  // start a new word if:
+  // (1) this character's baseline doesn't match the current word's
+  //     baseline, or
+  // (2) there is space between the end of the current word and this
+  //     character, or
+  // (3) this character overlaps the previous one (duplicated text), or
+  // (4) the previous character was an overlap (we want each duplicated
+  //     characters to be in a word by itself)
+  base = sp = 0; // make gcc happy
+  if (curWord->len > 0) {
     switch (curWord->rot) {
-    case 0: sp = x1 - curWord->xMax; break;
-    case 1: sp = y1 - curWord->yMax; break;
-    case 2: sp = curWord->xMin - x1; break;
-    case 3: sp = curWord->yMin - y1; break;
+    case 0:
+      base = y1;
+      sp = x1 - curWord->xMax;
+      break;
+    case 1:
+      base = x1;
+      sp = y1 - curWord->yMax;
+      break;
+    case 2:
+      base = y1;
+      sp = curWord->xMin - x1;
+      break;
+    case 3:
+      base = x1;
+      sp = curWord->yMin - y1;
+      break;
     }
-    if (sp > defaultSpaceWidth * curWord->fontSize) {
+    if (fabs(base - curWord->base) > 0.5 ||
+       sp > minWordBreakSpace * curWord->fontSize ||
+       sp < -minDupBreakOverlap * curWord->fontSize ||
+       lastCharOverlap) {
+      lastCharOverlap = gTrue;
       endWord();
       beginWord(state, x, y);
+    } else {
+      lastCharOverlap = gFalse;
     }
+  } else {
+    lastCharOverlap = gFalse;
   }
 
   // page rotation and/or transform matrices can cause text to be
@@ -1873,7 +1913,7 @@ void TextPage::addChar(GfxState *state, double x, double y,
 void TextPage::endWord() {
   // This check is needed because Type 3 characters can contain
   // text-drawing operations (when TextPage is being used via
-  // XOutputDev rather than TextOutputDev).
+  // {X,Win}SplashOutputDev rather than TextOutputDev).
   if (nest > 0) {
     --nest;
     return;
@@ -1915,7 +1955,7 @@ void TextPage::coalesce(GBool physLayout) {
   TextFlow *flow, *lastFlow;
   int rot, poolMinBaseIdx, baseIdx, startBaseIdx;
   double minBase, maxBase, newMinBase, newMaxBase;
-  double fontSize, colSpace, lineSpace, intraLineSpace, blkSpace;
+  double fontSize, colSpace1, colSpace2, lineSpace, intraLineSpace, blkSpace;
   GBool found;
   int count[4];
   int lrCount;
@@ -2000,7 +2040,8 @@ void TextPage::coalesce(GBool physLayout) {
 
       fontSize = word0->fontSize;
       minBase = maxBase = word0->base;
-      colSpace = minColSpacing * fontSize;
+      colSpace1 = minColSpacing1 * fontSize;
+      colSpace2 = minColSpacing2 * fontSize;
       lineSpace = maxLineSpacingDelta * fontSize;
       intraLineSpace = maxIntraLineDelta * fontSize;
 
@@ -2089,8 +2130,10 @@ void TextPage::coalesce(GBool physLayout) {
            if (word1->base >= minBase - intraLineSpace &&
                word1->base <= maxBase + intraLineSpace &&
                ((rot == 0 || rot == 2)
-                ? (word1->xMin < blk->xMax && word1->xMax > blk->xMin)
-                : (word1->yMin < blk->yMax && word1->yMax > blk->yMin)) &&
+                ? (word1->xMin < blk->xMax + colSpace1 &&
+                   word1->xMax > blk->xMin - colSpace1)
+                : (word1->yMin < blk->yMax + colSpace1 &&
+                   word1->yMax > blk->yMin - colSpace1)) &&
                fabs(word1->fontSize - fontSize) <
                  maxBlockFontSizeDelta2 * fontSize) {
              word2 = word1;
@@ -2129,9 +2172,9 @@ void TextPage::coalesce(GBool physLayout) {
                word1->base <= maxBase + intraLineSpace &&
                ((rot == 0 || rot == 2)
                 ? (word1->xMax <= blk->xMin &&
-                   word1->xMax > blk->xMin - colSpace)
+                   word1->xMax > blk->xMin - colSpace2)
                 : (word1->yMax <= blk->yMin &&
-                   word1->yMax > blk->yMin - colSpace)) &&
+                   word1->yMax > blk->yMin - colSpace2)) &&
                fabs(word1->fontSize - fontSize) <
                  maxBlockFontSizeDelta3 * fontSize) {
              ++n;
@@ -2151,9 +2194,9 @@ void TextPage::coalesce(GBool physLayout) {
                  word1->base <= maxBase + intraLineSpace &&
                  ((rot == 0 || rot == 2)
                   ? (word1->xMax <= blk->xMin &&
-                     word1->xMax > blk->xMin - colSpace)
+                     word1->xMax > blk->xMin - colSpace2)
                   : (word1->yMax <= blk->yMin &&
-                     word1->yMax > blk->yMin - colSpace)) &&
+                     word1->yMax > blk->yMin - colSpace2)) &&
                  fabs(word1->fontSize - fontSize) <
                    maxBlockFontSizeDelta3 * fontSize) {
                word2 = word1;
@@ -2193,9 +2236,9 @@ void TextPage::coalesce(GBool physLayout) {
                word1->base <= maxBase + intraLineSpace &&
                ((rot == 0 || rot == 2)
                 ? (word1->xMin >= blk->xMax &&
-                   word1->xMin < blk->xMax + colSpace)
+                   word1->xMin < blk->xMax + colSpace2)
                 : (word1->yMin >= blk->yMax &&
-                   word1->yMin < blk->yMax + colSpace)) &&
+                   word1->yMin < blk->yMax + colSpace2)) &&
                fabs(word1->fontSize - fontSize) <
                  maxBlockFontSizeDelta3 * fontSize) {
              ++n;
@@ -2215,9 +2258,9 @@ void TextPage::coalesce(GBool physLayout) {
                  word1->base <= maxBase + intraLineSpace &&
                  ((rot == 0 || rot == 2)
                   ? (word1->xMin >= blk->xMax &&
-                     word1->xMin < blk->xMax + colSpace)
+                     word1->xMin < blk->xMax + colSpace2)
                   : (word1->yMin >= blk->yMax &&
-                     word1->yMin < blk->yMax + colSpace)) &&
+                     word1->yMin < blk->yMax + colSpace2)) &&
                  fabs(word1->fontSize - fontSize) <
                    maxBlockFontSizeDelta3 * fontSize) {
                word2 = word1;
@@ -3435,6 +3478,7 @@ void TextOutputDev::startPage(int pageNum, GfxState *state) {
 }
 
 void TextOutputDev::endPage() {
+  text->endPage();
   text->coalesce(physLayout);
   if (outputStream) {
     text->dump(outputStream, outputFunc, physLayout);
@@ -3446,11 +3490,9 @@ void TextOutputDev::updateFont(GfxState *state) {
 }
 
 void TextOutputDev::beginString(GfxState *state, GString *s) {
-  text->beginWord(state, state->getCurX(), state->getCurY());
 }
 
 void TextOutputDev::endString(GfxState *state) {
-  text->endWord();
 }
 
 void TextOutputDev::drawChar(GfxState *state, double x, double y,
index b501907b4a257868566c632fe01dee88e4de0179..2c622376f3937b31985da9b08badcdd058173ba7 100644 (file)
@@ -354,6 +354,9 @@ public:
   // Start a new page.
   void startPage(GfxState *state);
 
+  // End the current page.
+  void endPage();
+
   // Update the current font.
   void updateFont(GfxState *state);
 
@@ -426,6 +429,8 @@ private:
   double curFontSize;          // current font size
   int nest;                    // current nesting level (for Type 3 fonts)
   int nTinyChars;              // number of "tiny" chars seen so far
+  GBool lastCharOverlap;       // set if the last added char overlapped the
+                               //   previous char
 
   TextPool *pools[4];          // a "pool" of TextWords for each rotation
   TextFlow *flows;             // linked list of flows
diff --git a/pdf/xpdf/XOutputDev.cc b/pdf/xpdf/XOutputDev.cc
deleted file mode 100644 (file)
index a156b55..0000000
+++ /dev/null
@@ -1,3986 +0,0 @@
-//========================================================================
-//
-// XOutputDev.cc
-//
-// Copyright 1996-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma implementation
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <unistd.h>
-#include <string.h>
-#include <ctype.h>
-#include <math.h>
-#include "gmem.h"
-#include "gfile.h"
-#include "GString.h"
-#include "GList.h"
-#include "Object.h"
-#include "Stream.h"
-#include "Link.h"
-#include "GfxState.h"
-#include "GfxFont.h"
-#include "UnicodeMap.h"
-#include "CharCodeToUnicode.h"
-#include "FontFile.h"
-#include "Error.h"
-#include "TextOutputDev.h"
-#include "XOutputDev.h"
-#if HAVE_T1LIB_H
-#include "T1Font.h"
-#endif
-#if FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
-#include "FTFont.h"
-#endif
-#if !FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
-#include "TTFont.h"
-#endif
-
-#ifdef VMS
-#if (__VMS_VER < 70000000)
-extern "C" int unlink(char *filename);
-#endif
-#endif
-
-#ifdef XlibSpecificationRelease
-#if XlibSpecificationRelease < 5
-typedef char *XPointer;
-#endif
-#else
-typedef char *XPointer;
-#endif
-
-//------------------------------------------------------------------------
-// Constants and macros
-//------------------------------------------------------------------------
-
-#define xoutRound(x) ((int)(x + 0.5))
-
-#define maxCurveSplits 6       // max number of splits when recursively
-                               //   drawing Bezier curves
-
-//------------------------------------------------------------------------
-// Font substitutions
-//------------------------------------------------------------------------
-
-struct XOutFontSubst {
-  char *name;
-  double mWidth;
-};
-
-// index: {symbolic:12, fixed:8, serif:4, sans-serif:0} + bold*2 + italic
-static XOutFontSubst xOutSubstFonts[16] = {
-  {"Helvetica",             0.833},
-  {"Helvetica-Oblique",     0.833},
-  {"Helvetica-Bold",        0.889},
-  {"Helvetica-BoldOblique", 0.889},
-  {"Times-Roman",           0.788},
-  {"Times-Italic",          0.722},
-  {"Times-Bold",            0.833},
-  {"Times-BoldItalic",      0.778},
-  {"Courier",               0.600},
-  {"Courier-Oblique",       0.600},
-  {"Courier-Bold",          0.600},
-  {"Courier-BoldOblique",   0.600},
-  {"Symbol",                0.576},
-  {"Symbol",                0.576},
-  {"Symbol",                0.576},
-  {"Symbol",                0.576}
-};
-
-//------------------------------------------------------------------------
-
-static void outputToFile(void *stream, char *data, int len) {
-  fwrite(data, 1, len, (FILE *)stream);
-}
-
-//------------------------------------------------------------------------
-// XOutputFont
-//------------------------------------------------------------------------
-
-XOutputFont::XOutputFont(Ref *idA, double m11OrigA, double m12OrigA,
-                        double m21OrigA, double m22OrigA,
-                        double m11A, double m12A, double m21A, double m22A,
-                        Display *displayA, XOutputDev *xOutA) {
-  id = *idA;
-  display = displayA;
-  xOut = xOutA;
-  m11Orig = m11OrigA;
-  m12Orig = m12OrigA;
-  m21Orig = m21OrigA;
-  m22Orig = m22OrigA;
-  m11 = m11A;
-  m12 = m12A;
-  m21 = m21A;
-  m22 = m22A;
-}
-
-XOutputFont::~XOutputFont() {
-}
-
-void XOutputFont::getCharPath(GfxState *state,
-                             CharCode c, Unicode *u, int ulen) {
-}
-
-#if HAVE_T1LIB_H
-//------------------------------------------------------------------------
-// XOutputT1Font
-//------------------------------------------------------------------------
-
-XOutputT1Font::XOutputT1Font(Ref *idA, T1FontFile *fontFileA,
-                            double m11OrigA, double m12OrigA,
-                            double m21OrigA, double m22OrigA,
-                            double m11A, double m12A,
-                            double m21A, double m22A,
-                            Display *displayA, XOutputDev *xOutA):
-  XOutputFont(idA, m11OrigA, m12OrigA, m21OrigA, m22OrigA,
-             m11A, m12A, m21A, m22A, displayA, xOutA)
-{
-  double matrix[4];
-
-  fontFile = fontFileA;
-
-  // create the transformed instance
-  matrix[0] = m11;
-  matrix[1] = -m12;
-  matrix[2] = m21;
-  matrix[3] = -m22;
-  font = new T1Font(fontFile, matrix);
-}
-
-XOutputT1Font::~XOutputT1Font() {
-  if (font) {
-    delete font;
-  }
-}
-
-GBool XOutputT1Font::isOk() {
-  return font != NULL;
-}
-
-void XOutputT1Font::updateGC(GC gc) {
-}
-
-void XOutputT1Font::drawChar(GfxState *state, Pixmap pixmap, int w, int h,
-                            GC gc, GfxRGB *rgb,
-                            double x, double y, double dx, double dy,
-                            CharCode c, Unicode *u, int uLen) {
-  font->drawChar(pixmap, w, h, gc, xoutRound(x), xoutRound(y),
-                (int)(rgb->r * 65535), (int)(rgb->g * 65535),
-                (int)(rgb->b * 65535), c, u[0]);
-}
-
-void XOutputT1Font::getCharPath(GfxState *state,
-                               CharCode c, Unicode *u, int uLen) {
-  font->getCharPath(c, u[0], state);
-}
-#endif // HAVE_T1LIB_H
-
-#if FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
-//------------------------------------------------------------------------
-// XOutputFTFont
-//------------------------------------------------------------------------
-
-XOutputFTFont::XOutputFTFont(Ref *idA, FTFontFile *fontFileA,
-                            double m11OrigA, double m12OrigA,
-                            double m21OrigA, double m22OrigA,
-                            double m11A, double m12A,
-                            double m21A, double m22A,
-                            Display *displayA, XOutputDev *xOutA):
-  XOutputFont(idA, m11OrigA, m12OrigA, m21OrigA, m22OrigA,
-             m11A, m12A, m21A, m22A, displayA, xOutA)
-{
-  double matrix[4];
-
-  fontFile = fontFileA;
-
-  // create the transformed instance
-  matrix[0] = m11;
-  matrix[1] = -m12;
-  matrix[2] = m21;
-  matrix[3] = -m22;
-  font = new FTFont(fontFile, matrix);
-}
-
-XOutputFTFont::~XOutputFTFont() {
-  if (font) {
-    delete font;
-  }
-}
-
-GBool XOutputFTFont::isOk() {
-  return font != NULL;
-}
-
-void XOutputFTFont::updateGC(GC gc) {
-}
-
-void XOutputFTFont::drawChar(GfxState *state, Pixmap pixmap, int w, int h,
-                            GC gc, GfxRGB *rgb,
-                            double x, double y, double dx, double dy,
-                            CharCode c, Unicode *u, int uLen) {
-  font->drawChar(pixmap, w, h, gc, xoutRound(x), xoutRound(y),
-                (int)(rgb->r * 65535), (int)(rgb->g * 65535),
-                (int)(rgb->b * 65535), c, uLen > 0 ? u[0] : 0);
-}
-
-void XOutputFTFont::getCharPath(GfxState *state,
-                               CharCode c, Unicode *u, int uLen) {
-  font->getCharPath(c, u[0], state);
-}
-#endif // FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
-
-#if !FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
-//------------------------------------------------------------------------
-// XOutputTTFont
-//------------------------------------------------------------------------
-
-XOutputTTFont::XOutputTTFont(Ref *idA, TTFontFile *fontFileA,
-                            double m11OrigA, double m12OrigA,
-                            double m21OrigA, double m22OrigA,
-                            double m11A, double m12A,
-                            double m21A, double m22A,
-                            Display *displayA, XOutputDev *xOutA):
-  XOutputFont(idA, m11OrigA, m12OrigA, m21OrigA, m22OrigA,
-             m11A, m12A, m21A, m22A, displayA, xOutA)
-{
-  double matrix[4];
-
-  fontFile = fontFileA;
-
-  // create the transformed instance
-  matrix[0] = m11;
-  matrix[1] = -m12;
-  matrix[2] = m21;
-  matrix[3] = -m22;
-  font = new TTFont(fontFile, matrix);
-}
-
-XOutputTTFont::~XOutputTTFont() {
-  if (font) {
-    delete font;
-  }
-}
-
-GBool XOutputTTFont::isOk() {
-  return font != NULL;
-}
-
-void XOutputTTFont::updateGC(GC gc) {
-}
-
-void XOutputTTFont::drawChar(GfxState *state, Pixmap pixmap, int w, int h,
-                            GC gc, GfxRGB *rgb,
-                            double x, double y, double dx, double dy,
-                            CharCode c, Unicode *u, int uLen) {
-  font->drawChar(pixmap, w, h, gc, xoutRound(x), xoutRound(y),
-                (int)(rgb->r * 65535), (int)(rgb->g * 65535),
-                (int)(rgb->b * 65535), c, u[0]);
-}
-#endif // !FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
-
-//------------------------------------------------------------------------
-// XOutputServer8BitFont
-//------------------------------------------------------------------------
-
-// Copy <fmt>, substituting <val> for one occurrence of "%s", into
-// <buf>.
-static void stringSubst(char *buf, int bufSize, char *fmt, char *val) {
-  char *p, *q;
-  int i;
-
-  i = 0;
-  p = fmt;
-  while (*p) {
-    if (p[0] == '%' && p[1] == 's') {
-      q = val;
-      while (*q && i < bufSize - 1) {
-       buf[i++] = *q++;
-      }
-      p += 2;
-    } else {
-      if (i < bufSize - 1) {
-       buf[i++] = *p;
-      }
-      ++p;
-    }
-  }
-  buf[i] = '\0';
-}
-
-XOutputServer8BitFont::XOutputServer8BitFont(Ref *idA, GString *xlfdFmt, 
-                                            UnicodeMap *xUMapA,
-                                            CharCodeToUnicode *fontUMap,
-                                            double m11OrigA, double m12OrigA,
-                                            double m21OrigA, double m22OrigA,
-                                            double m11A, double m12A,
-                                            double m21A, double m22A,
-                                            Display *displayA,
-                                            XOutputDev *xOutA):
-  XOutputFont(idA, m11OrigA, m12OrigA, m21OrigA, m22OrigA,
-             m11A, m12A, m21A, m22A, displayA, xOutA)
-{
-  double size, ntm11, ntm12, ntm21, ntm22;
-  GBool rotated;
-  int startSize, sz;
-  char fontName[500], fontSize[100];
-  Unicode u;
-  char buf;
-  int i;
-
-  // compute size and normalized transform matrix
-  size = sqrt(m21*m21 + m22*m22);
-  ntm11 = m11 / size;
-  ntm12 = -m12 / size;
-  ntm21 = m21 / size;
-  ntm22 = -m22 / size;
-
-  // try to get a rotated font?
-  rotated = !(ntm11 > 0 && ntm22 > 0 &&
-             fabs(ntm11 / ntm22 - 1) < 0.2 &&
-             fabs(ntm12) < 0.01 &&
-             fabs(ntm21) < 0.01);
-
-  // open X font -- if font is not found (which means the server can't
-  // scale fonts), try progressively smaller and then larger sizes
-  startSize = (int)size;
-  if (rotated) {
-    sprintf(fontSize, "[%s%0.2f %s%0.2f %s%0.2f %s%0.2f]",
-           ntm11<0 ? "~" : "", fabs(ntm11 * size),
-           ntm12<0 ? "~" : "", fabs(ntm12 * size),
-           ntm21<0 ? "~" : "", fabs(ntm21 * size),
-           ntm22<0 ? "~" : "", fabs(ntm22 * size));
-  } else {
-    sprintf(fontSize, "%d", startSize);
-  }
-  stringSubst(fontName, sizeof(fontName), xlfdFmt->getCString(), fontSize);
-  xFont = XLoadQueryFont(display, fontName);
-  if (!xFont) {
-    for (sz = startSize; sz >= startSize/2 && sz >= 1; --sz) {
-      sprintf(fontSize, "%d", sz);
-      stringSubst(fontName, sizeof(fontName), xlfdFmt->getCString(), fontSize);
-      if ((xFont = XLoadQueryFont(display, fontName)))
-       break;
-    }
-    if (!xFont) {
-      for (sz = startSize + 1; sz < startSize + 10; ++sz) {
-       sprintf(fontSize, "%d", sz);
-       stringSubst(fontName, sizeof(fontName), xlfdFmt->getCString(),
-                   fontSize);
-       if ((xFont = XLoadQueryFont(display, fontName))) {
-         break;
-       }
-      }
-      if (!xFont) {
-       sprintf(fontSize, "%d", startSize);
-       stringSubst(fontName, sizeof(fontName), xlfdFmt->getCString(),
-                   fontSize);
-       error(-1, "Failed to open font: '%s'", fontName);
-       return;
-      }
-    }
-  }
-
-  // Construct char code map.
-  xUMap = xUMapA;
-  for (i = 0; i < 256; ++i) {
-    if (fontUMap->mapToUnicode((CID)i, &u, 1) == 1 &&
-       xUMap->mapUnicode(u, &buf, 1) == 1) {
-      map[i] = buf & 0xff;
-    } else {
-      map[i] = 0;
-    }
-  }
-}
-
-XOutputServer8BitFont::~XOutputServer8BitFont() {
-  if (xFont) {
-    XFreeFont(display, xFont);
-  }
-}
-
-GBool XOutputServer8BitFont::isOk() {
-  return xFont != NULL;
-}
-
-void XOutputServer8BitFont::updateGC(GC gc) {
-  XSetFont(display, gc, xFont->fid);
-}
-
-void XOutputServer8BitFont::drawChar(GfxState *state, Pixmap pixmap,
-                                    int w, int h, GC gc, GfxRGB *rgb,
-                                    double x, double y, double dx, double dy,
-                                    CharCode c, Unicode *u, int uLen) {
-  Gushort c1;
-  char buf[8];
-  double dx1, dy1;
-  int m, n, i, j, k;
-
-  c1 = map[c];
-  if (c1 > 0) {
-    buf[0] = (char)c1;
-    XDrawString(display, pixmap, gc, xoutRound(x), xoutRound(y), buf, 1);
-  } else {
-    // substituted character, using more than one character
-    n = 0;
-    for (i = 0; i < uLen; ++i) {
-      n += xUMap->mapUnicode(u[i], buf, sizeof(buf));
-    }
-    if (n > 0) {
-      dx1 = dx / n;
-      dy1 = dy / n;
-      k = 0;
-      for (i = 0; i < uLen; ++i) {
-       m = xUMap->mapUnicode(u[i], buf, sizeof(buf));
-       for (j = 0; j < m; ++j) {
-         XDrawString(display, pixmap, gc,
-                     xoutRound(x + k*dx1), xoutRound(y + k*dy1),
-                     buf + j, 1);
-         ++k;
-       }
-      }
-    }
-  }
-}
-
-//------------------------------------------------------------------------
-// XOutputServer16BitFont
-//------------------------------------------------------------------------
-
-XOutputServer16BitFont::XOutputServer16BitFont(Ref *idA, GString *xlfdFmt, 
-                                              UnicodeMap *xUMapA,
-                                              CharCodeToUnicode *fontUMap,
-                                              double m11OrigA,
-                                              double m12OrigA,
-                                              double m21OrigA,
-                                              double m22OrigA,
-                                              double m11A, double m12A,
-                                              double m21A, double m22A,
-                                              Display *displayA,
-                                              XOutputDev *xOutA):
-  XOutputFont(idA, m11OrigA, m12OrigA, m21OrigA, m22OrigA,
-             m11A, m12A, m21A, m22A, displayA, xOutA)
-{
-  double size, ntm11, ntm12, ntm21, ntm22;
-  GBool rotated;
-  int startSize, sz;
-  char fontName[500], fontSize[100];
-
-  xUMap = xUMapA;
-  xUMap->incRefCnt();
-
-  // compute size and normalized transform matrix
-  size = sqrt(m21*m21 + m22*m22);
-  ntm11 = m11 / size;
-  ntm12 = -m12 / size;
-  ntm21 = m21 / size;
-  ntm22 = -m22 / size;
-
-  // try to get a rotated font?
-  rotated = !(ntm11 > 0 && ntm22 > 0 &&
-             fabs(ntm11 / ntm22 - 1) < 0.2 &&
-             fabs(ntm12) < 0.01 &&
-             fabs(ntm21) < 0.01);
-
-  // open X font -- if font is not found (which means the server can't
-  // scale fonts), try progressively smaller and then larger sizes
-  startSize = (int)size;
-  if (rotated) {
-    sprintf(fontSize, "[%s%0.2f %s%0.2f %s%0.2f %s%0.2f]",
-           ntm11<0 ? "~" : "", fabs(ntm11 * size),
-           ntm12<0 ? "~" : "", fabs(ntm12 * size),
-           ntm21<0 ? "~" : "", fabs(ntm21 * size),
-           ntm22<0 ? "~" : "", fabs(ntm22 * size));
-  } else {
-    sprintf(fontSize, "%d", startSize);
-  }
-  stringSubst(fontName, sizeof(fontName), xlfdFmt->getCString(), fontSize);
-  xFont = XLoadQueryFont(display, fontName);
-  if (!xFont) {
-    for (sz = startSize; sz >= startSize/2 && sz >= 1; --sz) {
-      sprintf(fontSize, "%d", sz);
-      stringSubst(fontName, sizeof(fontName), xlfdFmt->getCString(), fontSize);
-      if ((xFont = XLoadQueryFont(display, fontName)))
-       break;
-    }
-    if (!xFont) {
-      for (sz = startSize + 1; sz < startSize + 10; ++sz) {
-       sprintf(fontSize, "%d", sz);
-       stringSubst(fontName, sizeof(fontName), xlfdFmt->getCString(),
-                   fontSize);
-       if ((xFont = XLoadQueryFont(display, fontName))) {
-         break;
-       }
-      }
-      if (!xFont) {
-       sprintf(fontSize, "%d", startSize);
-       stringSubst(fontName, sizeof(fontName), xlfdFmt->getCString(),
-                   fontSize);
-       error(-1, "Failed to open font: '%s'", fontName);
-       return;
-      }
-    }
-  }
-}
-
-XOutputServer16BitFont::~XOutputServer16BitFont() {
-  xUMap->decRefCnt();
-  if (xFont) {
-    XFreeFont(display, xFont);
-  }
-}
-
-GBool XOutputServer16BitFont::isOk() {
-  return xFont != NULL;
-}
-
-void XOutputServer16BitFont::updateGC(GC gc) {
-  XSetFont(display, gc, xFont->fid);
-}
-
-void XOutputServer16BitFont::drawChar(GfxState *state, Pixmap pixmap,
-                                     int w, int h, GC gc, GfxRGB *rgb,
-                                     double x, double y, double dx, double dy,
-                                     CharCode c, Unicode *u, int uLen) {
-  char buf[16];
-  XChar2b c1;
-  double dx1, dy1;
-  int m, n, i, j, k;
-
-  n = 0;
-  for (i = 0; i < uLen; ++i) {
-    n += xUMap->mapUnicode(u[i], buf, sizeof(buf));
-  }
-  if (n > 0) {
-    dx1 = dx / n;
-    dy1 = dy / n;
-    k = 0;
-    for (i = 0; i < uLen; ++i) {
-      m = xUMap->mapUnicode(u[i], buf, sizeof(buf));
-      for (j = 0; j+1 < m; j += 2) {
-       c1.byte1 = buf[j];
-       c1.byte2 = buf[j+1];
-       XDrawString16(display, pixmap, gc,
-                     xoutRound(x + k*dx1), xoutRound(y + k*dy1),
-                     &c1, 1);
-       ++k;
-      }
-    }
-  } else if (c != 0) {
-    // some PDF files use CID 0, which is .notdef, so just ignore it
-    error(-1, "Unknown character (CID=%d Unicode=%04x)",
-         c, uLen > 0 ? u[0] : (Unicode)0);
-  }
-}
-
-//------------------------------------------------------------------------
-// XOutputFontCache
-//------------------------------------------------------------------------
-
-#if HAVE_T1LIB_H
-XOutputT1FontFile::~XOutputT1FontFile() {
-  delete fontFile;
-  if (tmpFileName) {
-    unlink(tmpFileName->getCString());
-    delete tmpFileName;
-  }
-}
-#endif
-
-#if FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
-XOutputFTFontFile::~XOutputFTFontFile() {
-  delete fontFile;
-  if (tmpFileName) {
-    unlink(tmpFileName->getCString());
-    delete tmpFileName;
-  }
-}
-#endif
-
-#if !FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
-XOutputTTFontFile::~XOutputTTFontFile() {
-  delete fontFile;
-  if (tmpFileName) {
-    unlink(tmpFileName->getCString());
-    delete tmpFileName;
-  }
-}
-#endif
-
-XOutputFontCache::XOutputFontCache(Display *displayA, Guint depthA,
-                                  XOutputDev *xOutA,
-                                  FontRastControl t1libControlA,
-                                  FontRastControl freetypeControlA) {
-  display = displayA;
-  depth = depthA;
-  xOut = xOutA;
-
-#if HAVE_T1LIB_H
-  t1libControl = t1libControlA;
-  t1Engine = NULL;
-  t1FontFiles = NULL;
-#endif
-
-#if FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
-  freetypeControl = freetypeControlA;
-  ftEngine = NULL;
-  ftFontFiles = NULL;
-#endif
-#if !FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
-  freetypeControl = freetypeControlA;
-  ttEngine = NULL;
-  ttFontFiles = NULL;
-#endif
-
-  clear();
-}
-
-XOutputFontCache::~XOutputFontCache() {
-  delFonts();
-}
-
-void XOutputFontCache::startDoc(int screenNum, Visual *visual,
-                               Colormap colormap, GBool trueColor,
-                               int rMul, int gMul, int bMul,
-                               int rShift, int gShift, int bShift,
-                               Gulong *colors, int numColors) {
-  delFonts();
-  clear();
-
-#if HAVE_T1LIB_H
-  if (t1libControl != fontRastNone) {
-    t1Engine = new T1FontEngine(display, visual, depth, colormap,
-                               t1libControl == fontRastAALow ||
-                                 t1libControl == fontRastAAHigh,
-                               t1libControl == fontRastAAHigh);
-    if (t1Engine->isOk()) {
-      if (trueColor) {
-       t1Engine->useTrueColor(rMul, rShift, gMul, gShift, bMul, bShift);
-      } else {
-       t1Engine->useColorCube(colors, numColors);
-      }
-    } else {
-      delete t1Engine;
-      t1Engine = NULL;
-    }
-  }
-#endif // HAVE_T1LIB_H
-
-#if FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
-  if (freetypeControl != fontRastNone) {
-    ftEngine = new FTFontEngine(display, visual, depth, colormap,
-                               freetypeControl == fontRastAALow ||
-                                 freetypeControl == fontRastAAHigh);
-    if (ftEngine->isOk()) {
-      if (trueColor) {
-       ftEngine->useTrueColor(rMul, rShift, gMul, gShift, bMul, bShift);
-      } else {
-       ftEngine->useColorCube(colors, numColors);
-      }
-    } else {
-      delete ftEngine;
-      ftEngine = NULL;
-    }
-  }
-#endif // FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
-
-#if !FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
-  if (freetypeControl != fontRastNone) {
-    ttEngine = new TTFontEngine(display, visual, depth, colormap,
-                               freetypeControl == fontRastAALow ||
-                                 freetypeControl == fontRastAAHigh);
-    if (ttEngine->isOk()) {
-      if (trueColor) {
-       ttEngine->useTrueColor(rMul, rShift, gMul, gShift, bMul, bShift);
-      } else {
-       ttEngine->useColorCube(colors, numColors);
-      }
-    } else {
-      delete ttEngine;
-      ttEngine = NULL;
-    }
-  }
-#endif // !FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
-}
-
-void XOutputFontCache::delFonts() {
-  int i;
-
-  for (i = 0; i < nFonts; ++i) {
-    delete fonts[i];
-  }
-
-#if HAVE_T1LIB_H
-  // delete Type 1 font files
-  if (t1FontFiles) {
-    deleteGList(t1FontFiles, XOutputT1FontFile);
-    t1FontFiles = NULL;
-  }
-  if (t1Engine) {
-    delete t1Engine;
-    t1Engine = NULL;
-  }
-#endif
-
-#if FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
-  // delete FreeType font files
-  if (ftFontFiles) {
-    deleteGList(ftFontFiles, XOutputFTFontFile);
-    ftFontFiles = NULL;
-  }
-  if (ftEngine) {
-    delete ftEngine;
-    ftEngine = NULL;
-  }
-#endif
-
-#if !FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
-  // delete TrueType fonts
-  if (ttFontFiles) {
-    deleteGList(ttFontFiles, XOutputTTFontFile);
-    ttFontFiles = NULL;
-  }
-  if (ttEngine) {
-    delete ttEngine;
-    ttEngine = NULL;
-  }
-#endif
-}
-
-void XOutputFontCache::clear() {
-  int i;
-
-  for (i = 0; i < xOutFontCacheSize; ++i) {
-    fonts[i] = NULL;
-  }
-  nFonts = 0;
-
-#if HAVE_T1LIB_H
-  // clear Type 1 font files
-  t1FontFiles = new GList();
-#endif
-
-#if FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
-  // clear FreeType font cache
-  ftFontFiles = new GList();
-#endif
-
-#if !FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
-  // clear TrueType font cache
-  ttFontFiles = new GList();
-#endif
-}
-
-XOutputFont *XOutputFontCache::getFont(XRef *xref, GfxFont *gfxFont,
-                                      double m11, double m12,
-                                      double m21, double m22) {
-  XOutputFont *font;
-  DisplayFontParam *dfp;
-  GString *substName;
-  double m11New, m12New, m21New, m22New;
-  double w1, w2, v;
-  double *fm;
-  char *name;
-  int index;
-  int code;
-  int i, j;
-
-  // is it the most recently used font?
-  if (nFonts > 0 && fonts[0]->matches(gfxFont->getID(), m11, m12, m21, m22)) {
-    return fonts[0];
-  }
-
-  // is it in the cache?
-  for (i = 1; i < nFonts; ++i) {
-    if (fonts[i]->matches(gfxFont->getID(), m11, m12, m21, m22)) {
-      font = fonts[i];
-      for (j = i; j > 0; --j) {
-       fonts[j] = fonts[j-1];
-      }
-      fonts[0] = font;
-      return font;
-    }
-  }
-
-  // try for a cached FontFile, an embedded font, or an external font
-  // file
-  font = NULL;
-  switch (gfxFont->getType()) {
-  case fontType1:
-  case fontType1C:
-#if HAVE_T1LIB_H
-    if (t1libControl != fontRastNone) {
-      font = tryGetT1Font(xref, gfxFont, m11, m12, m21, m22);
-    }
-#endif
-#if FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
-    if (!font) {
-      if (freetypeControl != fontRastNone) {
-       font = tryGetFTFont(xref, gfxFont, m11, m12, m21, m22);
-      }
-    }
-#endif
-    break;
-  case fontTrueType:
-  case fontCIDType2:
-#if FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
-    if (freetypeControl != fontRastNone) {
-      font = tryGetFTFont(xref, gfxFont, m11, m12, m21, m22);
-    }
-#endif
-#if !FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
-    if (freetypeControl != fontRastNone) {
-      font = tryGetTTFont(xref, gfxFont, m11, m12, m21, m22);
-    }
-#endif
-    break;
-  case fontCIDType0:
-  case fontCIDType0C:
-#if FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
-    if (freetypeControl != fontRastNone) {
-      font = tryGetFTFont(xref, gfxFont, m11, m12, m21, m22);
-    }
-#endif
-    break;
-  default:
-    break;
-  }
-
-  if (!font) {
-
-    // search for a display font mapping
-    dfp = NULL;
-    if (gfxFont->isCIDFont()) {
-      if (((GfxCIDFont *)gfxFont)->getCollection()) {
-       dfp = globalParams->
-               getDisplayCIDFont(gfxFont->getName(),
-                                 ((GfxCIDFont *)gfxFont)->getCollection());
-      } else {
-       // this error (no CMap file) was already reported by GfxFont
-       return NULL;
-      }
-    } else {
-      if (gfxFont->getName()) {
-       dfp = globalParams->getDisplayFont(gfxFont->getName());
-      }
-    }
-    if (dfp) {
-      font = tryGetFont(xref, dfp, gfxFont, m11, m12, m21, m22,
-                       m11, m12, m21, m22, gFalse);
-    }
-
-    // substitute a font (8-bit fonts only)
-    if (!font && !gfxFont->isCIDFont()) {
-
-      // choose a substitute font
-      if (gfxFont->isFixedWidth()) {
-       index = 8;
-      } else if (gfxFont->isSerif()) {
-       index = 4;
-      } else {
-       index = 0;
-      }
-      if (gfxFont->isBold()) {
-       index += 2;
-      }
-      if (gfxFont->isItalic()) {
-       index += 1;
-      }
-      substName = new GString(xOutSubstFonts[index].name);
-
-      // adjust the font matrix -- compare the width of 'm' in the
-      // original font and the substituted font
-      m11New = m11;
-      m12New = m12;
-      m21New = m21;
-      m22New = m22;
-      for (code = 0; code < 256; ++code) {
-       if ((name = ((Gfx8BitFont *)gfxFont)->getCharName(code)) &&
-           name[0] == 'm' && name[1] == '\0') {
-         break;
-       }
-      }
-      if (code < 256) {
-       w1 = ((Gfx8BitFont *)gfxFont)->getWidth(code);
-       w2 = xOutSubstFonts[index].mWidth;
-       if (gfxFont->getType() == fontType3) {
-         // This is a hack which makes it possible to substitute for some
-         // Type 3 fonts.  The problem is that it's impossible to know what
-         // the base coordinate system used in the font is without actually
-         // rendering the font.  This code tries to guess by looking at the
-         // width of the character 'm' (which breaks if the font is a
-         // subset that doesn't contain 'm').
-         if (w1 > 0 && (w1 > 1.1 * w2 || w1 < 0.9 * w2)) {
-           w1 /= w2;
-           m11New *= w1;
-           m12New *= w1;
-           m21New *= w1;
-           m22New *= w1;
-         }
-         fm = gfxFont->getFontMatrix();
-         v = (fm[0] == 0) ? 1 : (fm[3] / fm[0]);
-         m21New *= v;
-         m22New *= v;
-       } else if (!gfxFont->isSymbolic()) {
-         // if real font is substantially narrower than substituted
-         // font, reduce the font size accordingly
-         if (w1 > 0.01 && w1 < 0.9 * w2) {
-           w1 /= w2;
-           m11New *= w1;
-           m21New *= w1;
-         }
-       }
-      }
-
-      // get the font
-      dfp = globalParams->getDisplayFont(substName);
-      delete substName;
-      if (!dfp) {
-       // this should never happen since GlobalParams sets up default
-       // mappings for the Base-14 fonts
-       error(-1, "Couldn't find a font for '%s'",
-             gfxFont->getName()->getCString());
-       return NULL;
-      }
-      font = tryGetFont(xref, dfp, gfxFont, m11, m12, m21, m22,
-                       m11New, m12New, m21New, m22New, gTrue);
-    }
-  }
-
-  // check for error
-  if (!font) {
-    // This will happen if the user specifies a bogus font in the
-    // config file (a non-existent font file or a font that requires a
-    // rasterizer that is disabled or wasn't built in), or if a CID
-    // font has no associated font in the config file.
-    if (gfxFont->isCIDFont()) {
-      error(-1, "Couldn't find a font for the '%s' character collection",
-           ((GfxCIDFont *)gfxFont)->getCollection()->getCString());
-    } else {
-      error(-1, "Couldn't find a font for '%s'",
-           gfxFont->getName() ?
-               gfxFont->getName()->getCString() : "[unnamed]");
-    }
-    return NULL;
-  }
-
-  // insert font in cache
-  if (nFonts == xOutFontCacheSize) {
-    --nFonts;
-    delete fonts[nFonts];
-  }
-  for (j = nFonts; j > 0; --j) {
-    fonts[j] = fonts[j-1];
-  }
-  fonts[0] = font;
-  ++nFonts;
-
-  return font;
-}
-
-XOutputFont *XOutputFontCache::tryGetFont(XRef *xref, DisplayFontParam *dfp,
-                                         GfxFont *gfxFont,
-                                         double m11Orig, double m12Orig,
-                                         double m21Orig, double m22Orig,
-                                         double m11, double m12,
-                                         double m21, double m22,
-                                         GBool subst) {
-  XOutputFont *font;
-
-  font = NULL;
-
-  // create the new font
-  switch (dfp->kind) {
-
-  case displayFontX:
-    font = tryGetServerFont(dfp->x.xlfd, dfp->x.encoding, gfxFont,
-                           m11Orig, m12Orig, m21Orig, m22Orig,
-                           m11, m12, m21, m22);
-    break;
-
-  case displayFontT1:
-#if HAVE_T1LIB_H
-    if (t1libControl != fontRastNone && !gfxFont->isCIDFont()) {
-      font = tryGetT1FontFromFile(xref, dfp->t1.fileName, gFalse, gfxFont,
-                                 m11Orig, m12Orig, m21Orig, m22Orig,
-                                 m11, m12, m21, m22, subst);
-    }
-#endif
-#if FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
-    if (!font) {
-      if (freetypeControl != fontRastNone) {
-       font = tryGetFTFontFromFile(xref, dfp->t1.fileName, gFalse, gfxFont,
-                                   m11Orig, m12Orig, m21Orig, m22Orig,
-                                   m11, m12, m21, m22, gFalse, subst);
-      }
-    }
-#endif
-#if !((FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)) || defined(HAVE_T1LIB_H))
-    error(-1, "Config file specifies a Type 1 font,");
-    error(-1, "but xpdf was not built with t1lib or FreeType2 support");
-#endif
-    break;
-
-  case displayFontTT:
-#if FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
-    if (freetypeControl != fontRastNone) {
-      font = tryGetFTFontFromFile(xref, dfp->tt.fileName, gFalse, gfxFont,
-                                 m11Orig, m12Orig, m21Orig, m22Orig,
-                                 m11, m12, m21, m22, gFalse, subst);
-    }
-#endif
-#if !FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
-    if (freetypeControl != fontRastNone) {
-      font = tryGetTTFontFromFile(xref, dfp->tt.fileName, gFalse, gfxFont,
-                                 m11Orig, m12Orig, m21Orig, m22Orig,
-                                 m11, m12, m21, m22, subst);
-    }
-#endif
-#if !(HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
-    error(-1, "Config file specifies a TrueType font,");
-    error(-1, "but xpdf was not built with FreeType support");
-    dfp = NULL;
-#endif
-    break;
-  }
-
-  return font;
-}
-
-#if HAVE_T1LIB_H
-XOutputFont *XOutputFontCache::tryGetT1Font(XRef *xref,
-                                           GfxFont *gfxFont,
-                                           double m11, double m12,
-                                           double m21, double m22) {
-  Ref *id;
-  XOutputT1FontFile *xFontFile;
-  XOutputFont *font;
-  Ref embRef;
-  GString *fileName;
-  FILE *f;
-  char *fontBuf;
-  int fontLen;
-  Type1CFontFile *ff;
-  Object refObj, strObj;
-  int c;
-  int i;
-
-  // check the already available font files
-  id = gfxFont->getID();
-  for (i = 0; i < t1FontFiles->getLength(); ++i) {
-    xFontFile = (XOutputT1FontFile *)t1FontFiles->get(i);
-    if (xFontFile->num == id->num && xFontFile->gen == id->gen &&
-       !xFontFile->subst) {
-      font = new XOutputT1Font(id, xFontFile->fontFile,
-                              m11, m12, m21, m22,
-                              m11, m12, m21, m22, display, xOut);
-      if (!font->isOk()) {
-       delete font;
-       return NULL;
-      }
-      return font;
-    }
-  }
-
-  // check for an embedded font
-  if (gfxFont->getEmbeddedFontID(&embRef)) {
-
-    // create the font file
-    fileName = NULL;
-    if (!openTempFile(&fileName, &f, "wb", NULL)) {
-      error(-1, "Couldn't create temporary Type 1 font file");
-      return NULL;
-    }
-    if (gfxFont->getType() == fontType1C) {
-      if (!(fontBuf = gfxFont->readEmbFontFile(xref, &fontLen))) {
-       fclose(f);
-       unlink(fileName->getCString());
-       delete fileName;
-       return NULL;
-      }
-      ff = new Type1CFontFile(fontBuf, fontLen);
-      if (!ff->isOk()) {
-       delete ff;
-       gfree(fontBuf);
-       unlink(fileName->getCString());
-       delete fileName;
-       return NULL;
-      }
-      ff->convertToType1(outputToFile, f);
-      delete ff;
-      gfree(fontBuf);
-    } else { // fontType1
-      refObj.initRef(embRef.num, embRef.gen);
-      refObj.fetch(xref, &strObj);
-      refObj.free();
-      strObj.streamReset();
-      while ((c = strObj.streamGetChar()) != EOF) {
-       fputc(c, f);
-      }
-      strObj.streamClose();
-      strObj.free();
-    }
-    fclose(f);
-
-    // create the Font
-    font = tryGetT1FontFromFile(xref, fileName, gTrue, gfxFont,
-                               m11, m12, m21, m22,
-                               m11, m12, m21, m22, gFalse);
-
-    // on systems with Unix hard link semantics, this will remove the
-    // last link to the temp file
-    unlink(fileName->getCString());
-
-    delete fileName;
-
-  // check for an external font file
-  } else if ((fileName = gfxFont->getExtFontFile())) {
-    font = tryGetT1FontFromFile(xref, fileName, gFalse, gfxFont,
-                               m11, m12, m21, m22,
-                               m11, m12, m21, m22, gFalse);
-
-  } else {
-    font = NULL;
-  }
-
-  return font;
-}
-
-XOutputFont *XOutputFontCache::tryGetT1FontFromFile(XRef *xref,
-                                                   GString *fileName,
-                                                   GBool deleteFile,
-                                                   GfxFont *gfxFont,
-                                                   double m11Orig,
-                                                   double m12Orig,
-                                                   double m21Orig,
-                                                   double m22Orig,
-                                                   double m11, double m12,
-                                                   double m21, double m22,
-                                                   GBool subst) {
-  Ref *id;
-  T1FontFile *fontFile;
-  XOutputFont *font;
-
-  // create the t1lib font file
-  fontFile = new T1FontFile(t1Engine, fileName->getCString(),
-                           ((Gfx8BitFont *)gfxFont)->getEncoding(),
-                           gfxFont->getFontBBox());
-  if (!fontFile->isOk()) {
-    error(-1, "Couldn't create t1lib font from '%s'",
-         fileName->getCString());
-    delete fontFile;
-    if (deleteFile) {
-      unlink(fileName->getCString());
-    }
-    return NULL;
-  }
-
-  // add to list
-  id = gfxFont->getID();
-  t1FontFiles->append(new XOutputT1FontFile(id->num, id->gen,
-                                           subst, fontFile,
-                                           deleteFile ? fileName->copy()
-                                                      : (GString *)NULL));
-
-  // create the Font
-  font = new XOutputT1Font(gfxFont->getID(), fontFile,
-                          m11Orig, m12Orig, m21Orig, m22Orig,
-                          m11, m12, m21, m22, display, xOut);
-  if (!font->isOk()) {
-    delete font;
-    return NULL;
-  }
-  return font;
-}
-#endif // HAVE_T1LIB_H
-
-#if FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
-XOutputFont *XOutputFontCache::tryGetFTFont(XRef *xref,
-                                           GfxFont *gfxFont,
-                                           double m11, double m12,
-                                           double m21, double m22) {
-  Ref *id;
-  XOutputFTFontFile *xFontFile;
-  XOutputFont *font;
-  Ref embRef;
-  GString *fileName;
-  FILE *f;
-#if 1 //~ need this until FT can handle fonts with missing tables
-  char *fontBuf;
-  int fontLen;
-  TrueTypeFontFile *ff;
-#endif
-  Object refObj, strObj;
-  int c;
-  int i;
-
-  // check the already available font files
-  id = gfxFont->getID();
-  for (i = 0; i < ftFontFiles->getLength(); ++i) {
-    xFontFile = (XOutputFTFontFile *)ftFontFiles->get(i);
-    if (xFontFile->num == id->num && xFontFile->gen == id->gen &&
-       !xFontFile->subst) {
-      font = new XOutputFTFont(id, xFontFile->fontFile,
-                              m11, m12, m21, m22,
-                              m11, m12, m21, m22, display, xOut);
-      if (!font->isOk()) {
-       delete font;
-       return NULL;
-      }
-      return font;
-    }
-  }
-
-  // check for an embedded font
-  if (gfxFont->getEmbeddedFontID(&embRef)) {
-
-    // create the font file
-    fileName = NULL;
-    if (!openTempFile(&fileName, &f, "wb", NULL)) {
-      error(-1, "Couldn't create temporary TrueType font file");
-      return NULL;
-    }
-#if 1 //~ need this until FT can handle fonts with missing tables
-    if (gfxFont->getType() == fontTrueType ||
-       gfxFont->getType() == fontCIDType2) {
-      if (!(fontBuf = gfxFont->readEmbFontFile(xref, &fontLen))) {
-       fclose(f);
-       unlink(fileName->getCString());
-       delete fileName;
-       return NULL;
-      }
-      ff = new TrueTypeFontFile(fontBuf, fontLen);
-      ff->writeTTF(f);
-      delete ff;
-      gfree(fontBuf);
-    } else {
-      refObj.initRef(embRef.num, embRef.gen);
-      refObj.fetch(xref, &strObj);
-      refObj.free();
-      strObj.streamReset();
-      while ((c = strObj.streamGetChar()) != EOF) {
-       fputc(c, f);
-      }
-      strObj.streamClose();
-      strObj.free();
-    }
-#else
-    refObj.initRef(embRef.num, embRef.gen);
-    refObj.fetch(xref, &strObj);
-    refObj.free();
-    strObj.streamReset();
-    while ((c = strObj.streamGetChar()) != EOF) {
-      fputc(c, f);
-    }
-    strObj.streamClose();
-    strObj.free();
-#endif
-    fclose(f);
-
-    // create the Font
-    font = tryGetFTFontFromFile(xref, fileName, gTrue, gfxFont,
-                               m11, m12, m21, m22,
-                               m11, m12, m21, m22, gTrue, gFalse);
-
-    // on systems with Unix hard link semantics, this will remove the
-    // last link to the temp file
-    unlink(fileName->getCString());
-
-    delete fileName;
-
-  // check for an external font file
-  } else if ((fileName = gfxFont->getExtFontFile())) {
-    font = tryGetFTFontFromFile(xref, fileName, gFalse, gfxFont,
-                               m11, m12, m21, m22,
-                               m11, m12, m21, m22, gFalse, gFalse);
-
-  } else {
-    font = NULL;
-  }
-
-  return font;
-}
-
-XOutputFont *XOutputFontCache::tryGetFTFontFromFile(XRef *xref,
-                                                   GString *fileName,
-                                                   GBool deleteFile,
-                                                   GfxFont *gfxFont,
-                                                   double m11Orig,
-                                                   double m12Orig,
-                                                   double m21Orig,
-                                                   double m22Orig,
-                                                   double m11, double m12,
-                                                   double m21, double m22,
-                                                   GBool embedded,
-                                                   GBool subst) {
-  Ref *id;
-  FTFontFile *fontFile;
-  XOutputFont *font;
-  char *buf;
-  int len;
-  FILE *f;
-  TrueTypeFontFile *ff;
-  Gushort *codeToGID;
-
-  // create the FreeType font file
-  if (gfxFont->isCIDFont()) {
-    if (gfxFont->getType() == fontCIDType2) {
-      fontFile = new FTFontFile(ftEngine, fileName->getCString(),
-                               ((GfxCIDFont *)gfxFont)->getCIDToGID(),
-                               ((GfxCIDFont *)gfxFont)->getCIDToGIDLen(),
-                               embedded);
-    } else { // fontCIDType0, fontCIDType0C
-      fontFile = new FTFontFile(ftEngine, fileName->getCString(), embedded);
-    }
-  } else {
-    if (!(f = fopen(fileName->getCString(), "rb"))) {
-      return NULL;
-    }
-    fseek(f, 0, SEEK_END);
-    len = (int)ftell(f);
-    fseek(f, 0, SEEK_SET);
-    buf = (char *)gmalloc(len);
-    if ((int)fread(buf, 1, len, f) != len) {
-      gfree(buf);
-      fclose(f);
-      return NULL;
-    }
-    fclose(f);
-    ff = new TrueTypeFontFile(buf, len);
-    codeToGID = ((Gfx8BitFont *)gfxFont)->getCodeToGIDMap(ff);
-    fontFile = new FTFontFile(ftEngine, fileName->getCString(),
-                             ((Gfx8BitFont *)gfxFont)->getEncoding(),
-                             codeToGID);
-    gfree(codeToGID);
-    delete ff;
-    gfree(buf);
-  }
-  if (!fontFile->isOk()) {
-    error(-1, "Couldn't create FreeType font from '%s'",
-         fileName->getCString());
-    delete fontFile;
-    if (deleteFile) {
-      unlink(fileName->getCString());
-    }
-    return NULL;
-  }
-
-  // add to list
-  id = gfxFont->getID();
-  ftFontFiles->append(new XOutputFTFontFile(id->num, id->gen,
-                                           subst, fontFile,
-                                           deleteFile ? fileName->copy()
-                                                      : (GString *)NULL));
-
-  // create the Font
-  font = new XOutputFTFont(gfxFont->getID(), fontFile,
-                          m11Orig, m12Orig, m21Orig, m22Orig,
-                          m11, m12, m21, m22, display, xOut);
-  if (!font->isOk()) {
-    delete font;
-    return NULL;
-  }
-  return font;
-}
-#endif // FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
-
-#if !FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
-XOutputFont *XOutputFontCache::tryGetTTFont(XRef *xref,
-                                           GfxFont *gfxFont,
-                                           double m11, double m12,
-                                           double m21, double m22) {
-  Ref *id;
-  XOutputTTFontFile *xFontFile;
-  XOutputFont *font;
-  Ref embRef;
-  GString *fileName;
-  FILE *f;
-  Object refObj, strObj;
-  int c;
-  int i;
-
-  // check the already available font files
-  id = gfxFont->getID();
-  xFontFile = NULL;
-  for (i = 0; i < ttFontFiles->getLength(); ++i) {
-    xFontFile = (XOutputTTFontFile *)ttFontFiles->get(i);
-    if (xFontFile->num == id->num && xFontFile->gen == id->gen &&
-       !xFontFile->subst) {
-      font = new XOutputTTFont(id, xFontFile->fontFile,
-                              m11, m12, m21, m22,
-                              m11, m12, m21, m22, display, xOut);
-      if (!font->isOk()) {
-       delete font;
-       return NULL;
-      }
-      return font;
-    }
-  }
-
-  // check for an embedded font
-  if (gfxFont->getEmbeddedFontID(&embRef)) {
-
-    // create the font file
-    fileName = NULL;
-    if (!openTempFile(&fileName, &f, "wb", NULL)) {
-      error(-1, "Couldn't create temporary TrueType font file");
-      return NULL;
-    }
-    refObj.initRef(embRef.num, embRef.gen);
-    refObj.fetch(xref, &strObj);
-    refObj.free();
-    strObj.streamReset();
-    while ((c = strObj.streamGetChar()) != EOF) {
-      fputc(c, f);
-    }
-    strObj.streamClose();
-    strObj.free();
-    fclose(f);
-
-    // create the Font
-    font = tryGetTTFontFromFile(xref, fileName, gTrue, gfxFont,
-                               m11, m12, m21, m22,
-                               m11, m12, m21, m22, gFalse);
-
-    // on systems with Unix hard link semantics, this will remove the
-    // last link to the temp file
-    unlink(fileName->getCString());
-
-    delete fileName;
-
-  } else if ((fileName = gfxFont->getExtFontFile())) {
-    font = tryGetTTFontFromFile(xref, fileName, gFalse, gfxFont,
-                               m11, m12, m21, m22,
-                               m11, m12, m21, m22, gFalse);
-
-  } else {
-    font = NULL;
-  }
-
-  return font;
-}
-
-XOutputFont *XOutputFontCache::tryGetTTFontFromFile(XRef *xref,
-                                                   GString *fileName,
-                                                   GBool deleteFile,
-                                                   GfxFont *gfxFont,
-                                                   double m11Orig,
-                                                   double m12Orig,
-                                                   double m21Orig,
-                                                   double m22Orig,
-                                                   double m11, double m12,
-                                                   double m21, double m22,
-                                                   GBool subst) {
-  Ref *id;
-  TTFontFile *fontFile;
-  XOutputFont *font;
-
-  // create the FreeType font file
-  if (gfxFont->isCIDFont()) {
-    // fontCIDType2
-    fontFile = new TTFontFile(ttEngine, fileName->getCString(),
-                             ((GfxCIDFont *)gfxFont)->getCIDToGID(),
-                             ((GfxCIDFont *)gfxFont)->getCIDToGIDLen());
-  } else {
-    fontFile = new TTFontFile(ttEngine, fileName->getCString(),
-                             ((Gfx8BitFont *)gfxFont)->getEncoding(),
-                             ((Gfx8BitFont *)gfxFont)->getHasEncoding());
-  }
-  if (!fontFile->isOk()) {
-    error(-1, "Couldn't create FreeType font from '%s'",
-         fileName->getCString());
-    delete fontFile;
-    if (deleteFile) {
-      unlink(fileName->getCString());
-    }
-    return NULL;
-  }
-
-  // add to list
-  id = gfxFont->getID();
-  ttFontFiles->append(new XOutputTTFontFile(id->num, id->gen,
-                                           subst, fontFile,
-                                           deleteFile ? fileName->copy()
-                                                      : (GString *)NULL));
-
-  // create the Font
-  font = new XOutputTTFont(gfxFont->getID(), fontFile,
-                          m11Orig, m12Orig, m21Orig, m22Orig,
-                          m11, m12, m21, m22, display, xOut);
-  if (!font->isOk()) {
-    delete font;
-    return NULL;
-  }
-  return font;
-}
-#endif // !FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
-
-XOutputFont *XOutputFontCache::tryGetServerFont(GString *xlfd,
-                                               GString *encodingName,
-                                               GfxFont *gfxFont,
-                                               double m11Orig, double m12Orig,
-                                               double m21Orig, double m22Orig,
-                                               double m11, double m12,
-                                               double m21, double m22) {
-  XOutputFont *font;
-  UnicodeMap *uMap;
-  CharCodeToUnicode *ctu;
-
-  uMap = globalParams->getUnicodeMap(encodingName);
-  if (gfxFont->isCIDFont()) {
-    ctu = ((GfxCIDFont *)gfxFont)->getToUnicode();
-    font = new XOutputServer16BitFont(gfxFont->getID(), xlfd, uMap, ctu,
-                                     m11Orig, m12Orig, m21Orig, m22Orig,
-                                     m11, m12, m21, m22,
-                                     display, xOut);
-    ctu->decRefCnt();
-  } else {
-    ctu = ((Gfx8BitFont *)gfxFont)->getToUnicode();
-    font = new XOutputServer8BitFont(gfxFont->getID(), xlfd, uMap, ctu,
-                                    m11Orig, m12Orig, m21Orig, m22Orig,
-                                    m11, m12, m21, m22,
-                                    display, xOut);
-    ctu->decRefCnt();
-  }
-  uMap->decRefCnt();
-  if (!font->isOk()) {
-    delete font;
-    return NULL;
-  }
-  return font;
-}
-
-//------------------------------------------------------------------------
-// T3FontCache
-//------------------------------------------------------------------------
-
-struct T3FontCacheTag {
-  Gushort code;
-  Gushort mru;                 // valid bit (0x8000) and MRU index
-  double wx, wy;               // untransformed glyph metrics
-};
-
-class T3FontCache {
-public:
-
-  T3FontCache(Ref *fontID, double m11A, double m12A,
-             double m21A, double m22A,
-             int glyphXA, int glyphYA, int glyphWA, int glyphHA,
-             Display *displayA, Visual *visual, Guint depth,
-             Pixmap origPixmap);
-  ~T3FontCache();
-  GBool matches(Ref *idA, double m11A, double m12A,
-               double m21A, double m22A)
-    { return fontID.num == idA->num && fontID.gen == idA->gen &&
-            m11 == m11A && m12 == m12A && m21 == m21A && m22 == m22A; }
-
-  Ref fontID;                  // PDF font ID
-  double m11, m12, m21, m22;   // transform matrix
-  int glyphX, glyphY;          // pixel offset of glyph pixmaps
-  int glyphW, glyphH;          // size of glyph pixmaps, in pixels
-  int glyphSize;               // size of glyph pixmaps, in bytes
-  int cacheSets;               // number of sets in cache
-  int cacheAssoc;              // cache associativity (glyphs per set)
-  Guchar *cacheData;           // glyph pixmap cache
-  T3FontCacheTag *cacheTags;   // cache tags, i.e., char codes
-  Display *display;
-  Pixmap pixmap;
-  XImage *image;
-};
-
-T3FontCache::T3FontCache(Ref *fontIDA, double m11A, double m12A,
-                        double m21A, double m22A,
-                        int glyphXA, int glyphYA, int glyphWA, int glyphHA,
-                        Display *displayA, Visual *visual, Guint depth,
-                        Pixmap origPixmap) {
-  int i;
-
-  fontID = *fontIDA;
-  m11 = m11A;
-  m12 = m12A;
-  m21 = m21A;
-  m22 = m22A;
-  glyphX = glyphXA;
-  glyphY = glyphYA;
-  glyphW = glyphWA;
-  glyphH = glyphHA;
-  glyphSize = glyphW * glyphH;
-  cacheAssoc = 8;
-  if (glyphSize <= 256) {
-    cacheSets = 8;
-  } else if (glyphSize <= 512) {
-    cacheSets = 4;
-  } else if (glyphSize <= 1024) {
-    cacheSets = 2;
-  } else {
-    cacheSets = 1;
-  }
-  cacheData = (Guchar *)gmalloc(cacheSets * cacheAssoc * glyphSize);
-  cacheTags = (T3FontCacheTag *)gmalloc(cacheSets * cacheAssoc *
-                                       sizeof(T3FontCacheTag));
-  for (i = 0; i < cacheSets * cacheAssoc; ++i) {
-    cacheTags[i].mru = i & (cacheAssoc - 1);
-  }
-  display = displayA;
-  pixmap = XCreatePixmap(display, origPixmap, glyphW, glyphH, depth);
-  image = XCreateImage(display, visual, depth, ZPixmap, 0, NULL,
-                      glyphW, glyphH, 8, 0);
-  image->data = (char *)gmalloc(glyphH * image->bytes_per_line);
-}
-
-T3FontCache::~T3FontCache() {
-  gfree(cacheData);
-  gfree(cacheTags);
-  XFreePixmap(display, pixmap);
-  gfree(image->data);
-  image->data = NULL;
-  XDestroyImage(image);
-}
-
-struct T3GlyphStack {
-  GBool cacheable;
-  Gushort code;
-  T3FontCache *cache;
-  int cacheIdx;
-  T3FontCacheTag *cacheTag;
-  Guchar *cacheData;
-  double x, y;
-  Unicode *u;
-  int uLen;
-  GfxRGB color;
-  int origPixmapW, origPixmapH;
-  Pixmap origPixmap;
-  GC origStrokeGC;
-  GC origFillGC;
-  Region origClipRegion;
-  double origCTM4, origCTM5;
-  double wx, wy;               // untransformed glyph metrics
-  T3GlyphStack *next;
-};
-
-//------------------------------------------------------------------------
-// XOutputDev
-//------------------------------------------------------------------------
-
-XOutputDev::XOutputDev(Display *displayA, int screenNumA,
-                      Visual *visualA, Colormap colormapA,
-                      GBool reverseVideoA, unsigned long paperColorA,
-                      GBool installCmap, int rgbCubeSize,
-                      int forceDepth) {
-  XVisualInfo visualTempl;
-  XVisualInfo *visualList;
-  int nVisuals;
-  Gulong mask;
-  XColor xcolor;
-  XColor *xcolors;
-  int r, g, b, n, m;
-  GBool ok;
-
-  // no document yet
-  xref = NULL;
-
-  // display / screen / visual / colormap
-  display = displayA;
-  screenNum = screenNumA;
-  visual = visualA;
-  colormap = colormapA;
-
-  // no pixmap yet
-  pixmapW = pixmapH = 0;
-
-  // check for TrueColor visual
-  if (forceDepth != 0) {
-    depth = forceDepth;
-    trueColor = depth >= 16;
-  } else {
-    visualTempl.visualid = XVisualIDFromVisual(visual);
-    visualList = XGetVisualInfo(display, VisualIDMask,
-                               &visualTempl, &nVisuals);
-    if (nVisuals < 1) {
-      // this shouldn't happen
-      XFree((XPointer)visualList);
-      visualList = XGetVisualInfo(display, VisualNoMask, &visualTempl,
-                                 &nVisuals);
-    }
-    depth = visualList->depth;
-    if (visualList->c_class == TrueColor) {
-      trueColor = gTrue;
-      for (mask = visualList->red_mask, rShift = 0;
-          mask && !(mask & 1);
-          mask >>= 1, ++rShift) ;
-      rMul = (int)mask;
-      for (mask = visualList->green_mask, gShift = 0;
-          mask && !(mask & 1);
-          mask >>= 1, ++gShift) ;
-      gMul = (int)mask;
-      for (mask = visualList->blue_mask, bShift = 0;
-          mask && !(mask & 1);
-          mask >>= 1, ++bShift) ;
-      bMul = (int)mask;
-    } else {
-      trueColor = gFalse;
-    }
-    XFree((XPointer)visualList);
-  }
-
-  // allocate a color cube
-  if (!trueColor) {
-    redMap[BlackPixel(display, screenNum) & 0xff] = 0;
-    redMap[WhitePixel(display, screenNum) & 0xff] = 1;
-
-    // set colors in private colormap
-    if (installCmap) {
-      for (numColors = 6; numColors >= 2; --numColors) {
-       m = numColors * numColors * numColors;
-       if (XAllocColorCells(display, colormap, False, NULL, 0, colors, m)) {
-         break;
-       }
-      }
-      if (numColors >= 2) {
-       m = numColors * numColors * numColors;
-       xcolors = (XColor *)gmalloc(m * sizeof(XColor));
-       n = 0;
-       for (r = 0; r < numColors; ++r) {
-         for (g = 0; g < numColors; ++g) {
-           for (b = 0; b < numColors; ++b) {
-             xcolors[n].pixel = colors[n];
-             xcolors[n].red = (r * 65535) / (numColors - 1);
-             xcolors[n].green = (g * 65535) / (numColors - 1);
-             xcolors[n].blue = (b * 65535) / (numColors - 1);
-             xcolors[n].flags = DoRed | DoGreen | DoBlue;
-             redMap[xcolors[n].pixel & 0xff] = xcolors[n].red / 65535.0;
-             ++n;
-           }
-         }
-       }
-       XStoreColors(display, colormap, xcolors, m);
-       gfree(xcolors);
-      } else {
-       numColors = 1;
-       colors[0] = BlackPixel(display, screenNum);
-       colors[1] = WhitePixel(display, screenNum);
-      }
-
-    // allocate colors in shared colormap
-    } else {
-      if (rgbCubeSize > maxRGBCube) {
-       rgbCubeSize = maxRGBCube;
-      }
-      ok = gFalse;
-      for (numColors = rgbCubeSize; numColors >= 2; --numColors) {
-       ok = gTrue;
-       n = 0;
-       for (r = 0; r < numColors && ok; ++r) {
-         for (g = 0; g < numColors && ok; ++g) {
-           for (b = 0; b < numColors && ok; ++b) {
-             if (n == 0) {
-               colors[n] = BlackPixel(display, screenNum);
-               redMap[colors[n] & 0xff] = 0;
-               ++n;
-             } else {
-               xcolor.red = (r * 65535) / (numColors - 1);
-               xcolor.green = (g * 65535) / (numColors - 1);
-               xcolor.blue = (b * 65535) / (numColors - 1);
-               if (XAllocColor(display, colormap, &xcolor)) {
-                 colors[n++] = xcolor.pixel;
-                 redMap[xcolor.pixel & 0xff] = xcolor.red / 65535.0;
-               } else {
-                 ok = gFalse;
-               }
-             }
-           }
-         }
-       }
-       if (ok) {
-         break;
-       }
-       XFreeColors(display, colormap, &colors[1], n-1, 0);
-      }
-      if (!ok) {
-       numColors = 1;
-       colors[0] = BlackPixel(display, screenNum);
-       colors[1] = WhitePixel(display, screenNum);
-      }
-    }
-  }
-
-  // misc parameters
-  reverseVideo = reverseVideoA;
-  paperColor = paperColorA;
-
-  // set up the font cache and fonts
-  gfxFont = NULL;
-  font = NULL;
-  needFontUpdate = gFalse;
-  fontCache = new XOutputFontCache(display, depth, this,
-                                  globalParams->getT1libControl(),
-                                  globalParams->getFreeTypeControl());
-  nT3Fonts = 0;
-  t3GlyphStack = NULL;
-
-  // no text outline clipping path
-  textClipPath = NULL;
-
-  // empty state stack
-  save = NULL;
-
-  // create text object
-  text = new TextPage(gFalse);
-}
-
-XOutputDev::~XOutputDev() {
-  int i;
-
-  delete fontCache;
-  for (i = 0; i < nT3Fonts; ++i) {
-    delete t3FontCache[i];
-  }
-  delete text;
-}
-
-void XOutputDev::startDoc(XRef *xrefA) {
-  int i;
-
-  xref = xrefA;
-  fontCache->startDoc(screenNum, visual, colormap, trueColor, rMul, gMul, bMul,
-                     rShift, gShift, bShift, colors, numColors);
-  for (i = 0; i < nT3Fonts; ++i) {
-    delete t3FontCache[i];
-  }
-  nT3Fonts = 0;
-}
-
-void XOutputDev::startPage(int pageNum, GfxState *state) {
-  XGCValues gcValues;
-  XRectangle rect;
-
-  // default line flatness
-  flatness = 0;
-
-  // allocate GCs
-  gcValues.foreground = BlackPixel(display, screenNum);
-  gcValues.background = WhitePixel(display, screenNum);
-  gcValues.line_width = 0;
-  gcValues.line_style = LineSolid;
-  strokeGC = XCreateGC(display, pixmap,
-                      GCForeground | GCBackground | GCLineWidth | GCLineStyle,
-                       &gcValues);
-  fillGC = XCreateGC(display, pixmap,
-                    GCForeground | GCBackground | GCLineWidth | GCLineStyle,
-                    &gcValues);
-  gcValues.foreground = paperColor;
-  paperGC = XCreateGC(display, pixmap,
-                     GCForeground | GCBackground | GCLineWidth | GCLineStyle,
-                     &gcValues);
-
-  // initialize clip region
-  clipRegion = XCreateRegion();
-  rect.x = rect.y = 0;
-  rect.width = pixmapW;
-  rect.height = pixmapH;
-  XUnionRectWithRegion(&rect, clipRegion, clipRegion);
-  XSetRegion(display, strokeGC, clipRegion);
-  XSetRegion(display, fillGC, clipRegion);
-
-  // clear font
-  gfxFont = NULL;
-  font = NULL;
-
-  // clear window
-  XFillRectangle(display, pixmap, paperGC, 0, 0, pixmapW, pixmapH);
-
-  // clear text object
-  text->startPage(state);
-}
-
-void XOutputDev::endPage() {
-  XOutputState *s;
-
-  text->coalesce(gTrue);
-
-  // clear state stack, free all GCs, free the clip region
-  while (save) {
-    s = save;
-    save = save->next;
-    XFreeGC(display, s->strokeGC);
-    XFreeGC(display, s->fillGC);
-    XDestroyRegion(s->clipRegion);
-    delete s;
-  }
-  XFreeGC(display, strokeGC);
-  XFreeGC(display, fillGC);
-  XFreeGC(display, paperGC);
-  XDestroyRegion(clipRegion);
-}
-
-void XOutputDev::drawLink(Link *link, Catalog *catalog) {
-  double x1, y1, x2, y2;
-  LinkBorderStyle *borderStyle;
-  GfxRGB rgb;
-  double *dash;
-  char dashList[20];
-  int dashLength;
-  XPoint points[5];
-  int x, y, i;
-
-  link->getRect(&x1, &y1, &x2, &y2);
-  borderStyle = link->getBorderStyle();
-  if (borderStyle->getWidth() > 0) {
-    borderStyle->getColor(&rgb.r, &rgb.g, &rgb.b);
-    XSetForeground(display, strokeGC, findColor(&rgb));
-    borderStyle->getDash(&dash, &dashLength);
-    if (borderStyle->getType() == linkBorderDashed && dashLength > 0) {
-      if (dashLength > 20) {
-       dashLength = 20;
-      }
-      for (i = 0; i < dashLength; ++i) {
-       if ((dashList[i] = xoutRound(dash[i])) == 0) {
-         dashList[i] = 1;
-       }
-      }
-      XSetLineAttributes(display, strokeGC, xoutRound(borderStyle->getWidth()),
-                        LineOnOffDash, CapButt, JoinMiter);
-      XSetDashes(display, strokeGC, 0, dashList, dashLength);
-    } else {
-      XSetLineAttributes(display, strokeGC, xoutRound(borderStyle->getWidth()),
-                        LineSolid, CapButt, JoinMiter);
-    }
-    if (borderStyle->getType() == linkBorderUnderlined) {
-      cvtUserToDev(x1, y1, &x, &y);
-      points[0].x = x;
-      points[0].y = y;
-      cvtUserToDev(x2, y1, &x, &y);
-      points[1].x = x;
-      points[1].y = y;
-      XDrawLine(display, pixmap, strokeGC, points[0].x, points[0].y,
-               points[1].x, points[1].y);
-    } else {
-      cvtUserToDev(x1, y1, &x, &y);
-      points[0].x = points[4].x = x;
-      points[0].y = points[4].y = y;
-      cvtUserToDev(x2, y1, &x, &y);
-      points[1].x = x;
-      points[1].y = y;
-      cvtUserToDev(x2, y2, &x, &y);
-      points[2].x = x;
-      points[2].y = y;
-      cvtUserToDev(x1, y2, &x, &y);
-      points[3].x = x;
-      points[3].y = y;
-      XDrawLines(display, pixmap, strokeGC, points, 5, CoordModeOrigin);
-    }
-  }
-}
-
-void XOutputDev::saveState(GfxState *state) {
-  XOutputState *s;
-  XGCValues values;
-
-  // save current state
-  s = new XOutputState;
-  s->strokeGC = strokeGC;
-  s->fillGC = fillGC;
-  s->clipRegion = clipRegion;
-
-  // push onto state stack
-  s->next = save;
-  save = s;
-
-  // create a new current state by copying
-  strokeGC = XCreateGC(display, pixmap, 0, &values);
-  XCopyGC(display, s->strokeGC, 0xffffffff, strokeGC);
-  fillGC = XCreateGC(display, pixmap, 0, &values);
-  XCopyGC(display, s->fillGC, 0xffffffff, fillGC);
-  clipRegion = XCreateRegion();
-  XUnionRegion(s->clipRegion, clipRegion, clipRegion);
-  XSetRegion(display, strokeGC, clipRegion);
-  XSetRegion(display, fillGC, clipRegion);
-}
-
-void XOutputDev::restoreState(GfxState *state) {
-  XOutputState *s;
-
-  if (save) {
-    // kill current state
-    XFreeGC(display, strokeGC);
-    XFreeGC(display, fillGC);
-    XDestroyRegion(clipRegion);
-
-    // restore state
-    flatness = state->getFlatness();
-    strokeGC = save->strokeGC;
-    fillGC = save->fillGC;
-    clipRegion = save->clipRegion;
-    XSetRegion(display, strokeGC, clipRegion);
-    XSetRegion(display, fillGC, clipRegion);
-
-    // pop state stack
-    s = save;
-    save = save->next;
-    delete s;
-
-    // we'll need to restore the font
-    needFontUpdate = gTrue;
-  }
-}
-
-void XOutputDev::updateAll(GfxState *state) {
-  updateLineAttrs(state, gTrue);
-  updateFlatness(state);
-  updateMiterLimit(state);
-  updateFillColor(state);
-  updateStrokeColor(state);
-  needFontUpdate = gTrue;
-}
-
-void XOutputDev::updateCTM(GfxState *state, double m11, double m12,
-                          double m21, double m22, double m31, double m32) {
-  updateLineAttrs(state, gTrue);
-}
-
-void XOutputDev::updateLineDash(GfxState *state) {
-  updateLineAttrs(state, gTrue);
-}
-
-void XOutputDev::updateFlatness(GfxState *state) {
-  flatness = state->getFlatness();
-}
-
-void XOutputDev::updateLineJoin(GfxState *state) {
-  updateLineAttrs(state, gFalse);
-}
-
-void XOutputDev::updateLineCap(GfxState *state) {
-  updateLineAttrs(state, gFalse);
-}
-
-// unimplemented
-void XOutputDev::updateMiterLimit(GfxState *state) {
-}
-
-void XOutputDev::updateLineWidth(GfxState *state) {
-  updateLineAttrs(state, gFalse);
-}
-
-void XOutputDev::updateLineAttrs(GfxState *state, GBool updateDash) {
-  double width;
-  int cap, join;
-  double *dashPattern;
-  int dashLength;
-  double dashStart;
-  char dashList[20];
-  int i;
-
-  width = state->getTransformedLineWidth();
-  switch (state->getLineCap()) {
-  case 0: cap = CapButt; break;
-  case 1: cap = CapRound; break;
-  case 2: cap = CapProjecting; break;
-  default:
-    error(-1, "Bad line cap style (%d)", state->getLineCap());
-    cap = CapButt;
-    break;
-  }
-  switch (state->getLineJoin()) {
-  case 0: join = JoinMiter; break;
-  case 1: join = JoinRound; break;
-  case 2: join = JoinBevel; break;
-  default:
-    error(-1, "Bad line join style (%d)", state->getLineJoin());
-    join = JoinMiter;
-    break;
-  }
-  state->getLineDash(&dashPattern, &dashLength, &dashStart);
-#if 1 //~ work around a bug in XFree86 (???)
-  if (dashLength > 0 && cap == CapProjecting) {
-    cap = CapButt;
-  }
-#endif
-  XSetLineAttributes(display, strokeGC, xoutRound(width),
-                    dashLength > 0 ? LineOnOffDash : LineSolid,
-                    cap, join);
-  if (updateDash && dashLength > 0) {
-    if (dashLength > 20)
-      dashLength = 20;
-    for (i = 0; i < dashLength; ++i) {
-      dashList[i] = xoutRound(state->transformWidth(dashPattern[i]));
-      if (dashList[i] == 0)
-       dashList[i] = 1;
-    }
-    XSetDashes(display, strokeGC, xoutRound(dashStart), dashList, dashLength);
-  }
-}
-
-void XOutputDev::updateFillColor(GfxState *state) {
-  GfxRGB rgb;
-
-  state->getFillRGB(&rgb);
-  if (reverseVideo) {
-    rgb.r = 1 - rgb.r;
-    rgb.g = 1 - rgb.g;
-    rgb.b = 1 - rgb.b;
-  }
-  XSetForeground(display, fillGC, findColor(&rgb));
-}
-
-void XOutputDev::updateStrokeColor(GfxState *state) {
-  GfxRGB rgb;
-
-  state->getStrokeRGB(&rgb);
-  if (reverseVideo) {
-    rgb.r = 1 - rgb.r;
-    rgb.g = 1 - rgb.g;
-    rgb.b = 1 - rgb.b;
-  }
-  XSetForeground(display, strokeGC, findColor(&rgb));
-}
-
-void XOutputDev::updateFont(GfxState *state) {
-  double m11, m12, m21, m22;
-
-  needFontUpdate = gFalse;
-
-  text->updateFont(state);
-
-  if (!(gfxFont = state->getFont())) {
-    font = NULL;
-    return;
-  }
-  if (gfxFont->getType() == fontType3) {
-    font = NULL;
-    return;
-  }
-  state->getFontTransMat(&m11, &m12, &m21, &m22);
-  m11 *= state->getHorizScaling();
-  m12 *= state->getHorizScaling();
-  font = fontCache->getFont(xref, gfxFont, m11, m12, m21, m22);
-  if (font) {
-    font->updateGC(fillGC);
-    font->updateGC(strokeGC);
-  }
-}
-
-void XOutputDev::stroke(GfxState *state) {
-  XPoint *points;
-  int *lengths;
-  int n, size, numPoints, i, j;
-
-  // transform points
-  n = convertPath(state, state->getPath(),
-                 &points, &size, &numPoints, &lengths, gFalse);
-
-  // draw each subpath
-  j = 0;
-  for (i = 0; i < n; ++i) {
-    XDrawLines(display, pixmap, strokeGC, points + j, lengths[i],
-              CoordModeOrigin);
-    j += lengths[i];
-  }
-
-  // free points and lengths arrays
-  if (points != tmpPoints)
-    gfree(points);
-  if (lengths != tmpLengths)
-    gfree(lengths);
-}
-
-void XOutputDev::fill(GfxState *state) {
-  doFill(state, WindingRule);
-}
-
-void XOutputDev::eoFill(GfxState *state) {
-  doFill(state, EvenOddRule);
-}
-
-//
-//  X doesn't color the pixels on the right-most and bottom-most
-//  borders of a polygon.  This means that one-pixel-thick polygons
-//  are not colored at all.  I think this is supposed to be a
-//  feature, but I can't figure out why.  So after it fills a
-//  polygon, it also draws lines around the border.  This is done
-//  only for single-component polygons, since it's not very
-//  compatible with the compound polygon kludge (see convertPath()).
-//
-void XOutputDev::doFill(GfxState *state, int rule) {
-  XPoint *points;
-  int *lengths;
-  int n, size, numPoints, i, j;
-
-  // set fill rule
-  XSetFillRule(display, fillGC, rule);
-
-  // transform points, build separate polygons
-  n = convertPath(state, state->getPath(),
-                 &points, &size, &numPoints, &lengths, gTrue);
-
-  // fill them
-  j = 0;
-  for (i = 0; i < n; ++i) {
-    XFillPolygon(display, pixmap, fillGC, points + j, lengths[i],
-                Complex, CoordModeOrigin);
-    if (state->getPath()->getNumSubpaths() == 1) {
-      XDrawLines(display, pixmap, fillGC, points + j, lengths[i],
-                CoordModeOrigin);
-    }
-    j += lengths[i] + 1;
-  }
-
-  // free points and lengths arrays
-  if (points != tmpPoints)
-    gfree(points);
-  if (lengths != tmpLengths)
-    gfree(lengths);
-}
-
-void XOutputDev::clip(GfxState *state) {
-  doClip(state, state->getPath(), WindingRule);
-}
-
-void XOutputDev::eoClip(GfxState *state) {
-  doClip(state, state->getPath(), EvenOddRule);
-}
-
-void XOutputDev::doClip(GfxState *state, GfxPath *path, int rule) {
-  GfxSubpath *subpath;
-  Region region, region2;
-  XPoint rect[5];
-  XPoint *points;
-  int *lengths;
-  double x0, y0, x1, y1, x2, y2, x3, y3;
-  GBool gotRect;
-  int n, size, numPoints, i, j;
-
-  // special case for rectangular clipping paths -- this is a common
-  // case, and we want to make sure not to clip an extra pixel on the
-  // right and bottom edges due to the difference between the PDF and
-  // X rendering models
-  gotRect = gFalse;
-  if (path->getNumSubpaths() == 1) {
-    subpath = path->getSubpath(0);
-    if ((subpath->isClosed() && subpath->getNumPoints() == 5) ||
-       (!subpath->isClosed() && subpath->getNumPoints() == 4)) {
-      state->transform(subpath->getX(0), subpath->getY(0), &x0, &y0);
-      state->transform(subpath->getX(1), subpath->getY(1), &x1, &y1);
-      state->transform(subpath->getX(2), subpath->getY(2), &x2, &y2);
-      state->transform(subpath->getX(3), subpath->getY(3), &x3, &y3);
-      if (fabs(x0-x1) < 1 && fabs(x2-x3) < 1 &&
-         fabs(y0-y3) < 1 && fabs(y1-y2) < 1) {
-       if (x0 < x2) {
-         rect[0].x = rect[1].x = rect[4].x = (int)floor(x0);
-         rect[2].x = rect[3].x = (int)floor(x2) + 1;
-       } else {
-         rect[0].x = rect[1].x = rect[4].x = (int)floor(x0) + 1;
-         rect[2].x = rect[3].x = (int)floor(x2);
-       }
-       if (y0 < y1) {
-         rect[0].y = rect[3].y = rect[4].y = (int)floor(y0);
-         rect[1].y = rect[2].y = (int)floor(y1) + 1;
-       } else {
-         rect[0].y = rect[3].y = rect[4].y = (int)floor(y0) + 1;
-         rect[1].y = rect[2].y = (int)floor(y1);
-       }
-       gotRect = gTrue;
-      } else if (fabs(x0-x3) < 1 && fabs(x1-x2) < 1 &&
-                fabs(y0-y1) < 1 && fabs(y2-y3) < 1) {
-       if (x0 < x1) {
-         rect[0].x = rect[3].x = rect[4].x = (int)floor(x0);
-         rect[1].x = rect[2].x = (int)floor(x1) + 1;
-       } else {
-         rect[0].x = rect[3].x = rect[4].x = (int)floor(x0) + 1;
-         rect[1].x = rect[2].x = (int)floor(x1);
-       }
-       if (y0 < y2) {
-         rect[0].y = rect[1].y = rect[4].y = (int)floor(y0);
-         rect[2].y = rect[3].y = (int)floor(y2) + 1;
-       } else {
-         rect[0].y = rect[1].y = rect[4].y = (int)floor(y0) + 1;
-         rect[2].y = rect[3].y = (int)floor(y2);
-       }
-       gotRect = gTrue;
-      }
-    }
-  }
-
-  if (gotRect) {
-    region = XPolygonRegion(rect, 5, EvenOddRule);
-
-  } else {
-    // transform points, build separate polygons
-    n = convertPath(state, path, &points, &size, &numPoints, &lengths, gTrue);
-
-    // construct union of subpath regions
-    // (XPolygonRegion chokes if there aren't at least three points --
-    // this happens if the PDF file does moveto/closepath/clip, which
-    // sets an empty clipping region)
-    if (lengths[0] > 2) {
-      region = XPolygonRegion(points, lengths[0], rule);
-    } else {
-      region = XCreateRegion();
-    }
-    j = lengths[0] + 1;
-    for (i = 1; i < n; ++i) {
-      if (lengths[i] > 2) {
-       region2 = XPolygonRegion(points + j, lengths[i], rule);
-      } else {
-       region2 = XCreateRegion();
-      }
-      XUnionRegion(region2, region, region);
-      XDestroyRegion(region2);
-      j += lengths[i] + 1;
-    }
-
-    // free points and lengths arrays
-    if (points != tmpPoints) {
-      gfree(points);
-    }
-    if (lengths != tmpLengths) {
-      gfree(lengths);
-    }
-  }
-
-  // intersect region with clipping region
-  XIntersectRegion(region, clipRegion, clipRegion);
-  XDestroyRegion(region);
-  XSetRegion(display, strokeGC, clipRegion);
-  XSetRegion(display, fillGC, clipRegion);
-}
-
-//
-// Transform points in the path and convert curves to line segments.
-// Builds a set of subpaths and returns the number of subpaths.
-// If <fillHack> is set, close any unclosed subpaths and activate a
-// kludge for polygon fills:  First, it divides up the subpaths into
-// non-overlapping polygons by simply comparing bounding rectangles.
-// Then it connects subaths within a single compound polygon to a single
-// point so that X can fill the polygon (sort of).
-//
-int XOutputDev::convertPath(GfxState *state, GfxPath *path,
-                           XPoint **points, int *size,
-                           int *numPoints, int **lengths, GBool fillHack) {
-  BoundingRect *rects;
-  BoundingRect rect;
-  int n, i, ii, j, k, k0;
-
-  // get path and number of subpaths
-  n = path->getNumSubpaths();
-
-  // allocate lengths array
-  if (n < numTmpSubpaths)
-    *lengths = tmpLengths;
-  else
-    *lengths = (int *)gmalloc(n * sizeof(int));
-
-  // allocate bounding rectangles array
-  if (fillHack) {
-    if (n < numTmpSubpaths)
-      rects = tmpRects;
-    else
-      rects = (BoundingRect *)gmalloc(n * sizeof(BoundingRect));
-  } else {
-    rects = NULL;
-  }
-
-  // do each subpath
-  *points = tmpPoints;
-  *size = numTmpPoints;
-  *numPoints = 0;
-  for (i = 0; i < n; ++i) {
-
-    // transform the points
-    j = *numPoints;
-    convertSubpath(state, path->getSubpath(i), points, size, numPoints);
-
-    // construct bounding rectangle
-    if (fillHack) {
-      rects[i].xMin = rects[i].xMax = (*points)[j].x;
-      rects[i].yMin = rects[i].yMax = (*points)[j].y;
-      for (k = j + 1; k < *numPoints; ++k) {
-       if ((*points)[k].x < rects[i].xMin)
-         rects[i].xMin = (*points)[k].x;
-       else if ((*points)[k].x > rects[i].xMax)
-         rects[i].xMax = (*points)[k].x;
-       if ((*points)[k].y < rects[i].yMin)
-         rects[i].yMin = (*points)[k].y;
-       else if ((*points)[k].y > rects[i].yMax)
-         rects[i].yMax = (*points)[k].y;
-      }
-    }
-
-    // close subpath if necessary
-    if (fillHack && ((*points)[*numPoints-1].x != (*points)[j].x ||
-                    (*points)[*numPoints-1].y != (*points)[j].y)) {
-      addPoint(points, size, numPoints, (*points)[j].x, (*points)[j].y);
-    }
-
-    // length of this subpath
-    (*lengths)[i] = *numPoints - j;
-
-    // leave an extra point for compound fill hack
-    if (fillHack)
-      addPoint(points, size, numPoints, 0, 0);
-  }
-
-  // kludge: munge any points that are *way* out of bounds - these can
-  // crash certain (buggy) X servers
-  for (i = 0; i < *numPoints; ++i) {
-    if ((*points)[i].x < -4 * pixmapW) {
-      (*points)[i].x = -4 * pixmapW;
-    } else if ((*points)[i].x > 4 * pixmapW) {
-      (*points)[i].x = 4 * pixmapW;
-    }
-    if ((*points)[i].y < -pixmapH) {
-      (*points)[i].y = -4 * pixmapH;
-    } else if ((*points)[i].y > 4 * pixmapH) {
-      (*points)[i].y = 4 * pixmapH;
-    }
-  }
-
-  // combine compound polygons
-  if (fillHack) {
-    i = j = k = 0;
-    while (i < n) {
-
-      // start with subpath i
-      rect = rects[i];
-      (*lengths)[j] = (*lengths)[i];
-      k0 = k;
-      (*points)[k + (*lengths)[i]] = (*points)[k0];
-      k += (*lengths)[i] + 1;
-      ++i;
-
-      // combine overlapping polygons
-      do {
-
-       // look for the first subsequent subpath, if any, which overlaps
-       for (ii = i; ii < n; ++ii) {
-         if (rects[ii].xMax > rects[i].xMin &&
-             rects[ii].xMin < rects[i].xMax &&
-             rects[ii].yMax > rects[i].yMin &&
-             rects[ii].yMin < rects[i].yMax) {
-           break;
-         }
-       }
-
-       // if there is an overlap, combine the polygons
-       if (ii < n) {
-         for (; i <= ii; ++i) {
-           if (rects[i].xMin < rect.xMin)
-             rect.xMin = rects[j].xMin;
-           if (rects[i].xMax > rect.xMax)
-             rect.xMax = rects[j].xMax;
-           if (rects[i].yMin < rect.yMin)
-             rect.yMin = rects[j].yMin;
-           if (rects[i].yMax > rect.yMax)
-             rect.yMax = rects[j].yMax;
-           (*lengths)[j] += (*lengths)[i] + 1;
-           (*points)[k + (*lengths)[i]] = (*points)[k0];
-           k += (*lengths)[i] + 1;
-         }
-       }
-      } while (ii < n && i < n);
-
-      ++j;
-    }
-
-    // free bounding rectangles
-    if (rects != tmpRects)
-      gfree(rects);
-
-    n = j;
-  }
-
-  return n;
-}
-
-//
-// Transform points in a single subpath and convert curves to line
-// segments.
-//
-void XOutputDev::convertSubpath(GfxState *state, GfxSubpath *subpath,
-                               XPoint **points, int *size, int *n) {
-  double x0, y0, x1, y1, x2, y2, x3, y3;
-  int m, i;
-
-  m = subpath->getNumPoints();
-  i = 0;
-  while (i < m) {
-    if (i >= 1 && subpath->getCurve(i)) {
-      state->transform(subpath->getX(i-1), subpath->getY(i-1), &x0, &y0);
-      state->transform(subpath->getX(i), subpath->getY(i), &x1, &y1);
-      state->transform(subpath->getX(i+1), subpath->getY(i+1), &x2, &y2);
-      state->transform(subpath->getX(i+2), subpath->getY(i+2), &x3, &y3);
-      doCurve(points, size, n, x0, y0, x1, y1, x2, y2, x3, y3);
-      i += 3;
-    } else {
-      state->transform(subpath->getX(i), subpath->getY(i), &x1, &y1);
-      addPoint(points, size, n, xoutRound(x1), xoutRound(y1));
-      ++i;
-    }
-  }
-}
-
-//
-// Subdivide a Bezier curve.  This uses floating point to avoid
-// propagating rounding errors.  (The curves look noticeably more
-// jagged with integer arithmetic.)
-//
-void XOutputDev::doCurve(XPoint **points, int *size, int *n,
-                        double x0, double y0, double x1, double y1,
-                        double x2, double y2, double x3, double y3) {
-  double x[(1<<maxCurveSplits)+1][3];
-  double y[(1<<maxCurveSplits)+1][3];
-  int next[1<<maxCurveSplits];
-  int p1, p2, p3;
-  double xx1, yy1, xx2, yy2;
-  double dx, dy, mx, my, d1, d2;
-  double xl0, yl0, xl1, yl1, xl2, yl2;
-  double xr0, yr0, xr1, yr1, xr2, yr2, xr3, yr3;
-  double xh, yh;
-  double flat;
-
-  flat = (double)(flatness * flatness);
-  if (flat < 1)
-    flat = 1;
-
-  // initial segment
-  p1 = 0;
-  p2 = 1<<maxCurveSplits;
-  x[p1][0] = x0;  y[p1][0] = y0;
-  x[p1][1] = x1;  y[p1][1] = y1;
-  x[p1][2] = x2;  y[p1][2] = y2;
-  x[p2][0] = x3;  y[p2][0] = y3;
-  next[p1] = p2;
-
-  while (p1 < (1<<maxCurveSplits)) {
-
-    // get next segment
-    xl0 = x[p1][0];  yl0 = y[p1][0];
-    xx1 = x[p1][1];  yy1 = y[p1][1];
-    xx2 = x[p1][2];  yy2 = y[p1][2];
-    p2 = next[p1];
-    xr3 = x[p2][0];  yr3 = y[p2][0];
-
-    // compute distances from control points to midpoint of the
-    // straight line (this is a bit of a hack, but it's much faster
-    // than computing the actual distances to the line)
-    mx = (xl0 + xr3) * 0.5;
-    my = (yl0 + yr3) * 0.5;
-    dx = xx1 - mx;
-    dy = yy1 - my;
-    d1 = dx*dx + dy*dy;
-    dx = xx2 - mx;
-    dy = yy2 - my;
-    d2 = dx*dx + dy*dy;
-
-    // if curve is flat enough, or no more divisions allowed then
-    // add the straight line segment
-    if (p2 - p1 <= 1 || (d1 <= flat && d2 <= flat)) {
-      addPoint(points, size, n, xoutRound(xr3), xoutRound(yr3));
-      p1 = p2;
-
-    // otherwise, subdivide the curve
-    } else {
-      xl1 = (xl0 + xx1) * 0.5;
-      yl1 = (yl0 + yy1) * 0.5;
-      xh = (xx1 + xx2) * 0.5;
-      yh = (yy1 + yy2) * 0.5;
-      xl2 = (xl1 + xh) * 0.5;
-      yl2 = (yl1 + yh) * 0.5;
-      xr2 = (xx2 + xr3) * 0.5;
-      yr2 = (yy2 + yr3) * 0.5;
-      xr1 = (xh + xr2) * 0.5;
-      yr1 = (yh + yr2) * 0.5;
-      xr0 = (xl2 + xr1) * 0.5;
-      yr0 = (yl2 + yr1) * 0.5;
-
-      // add the new subdivision points
-      p3 = (p1 + p2) / 2;
-      x[p1][1] = xl1;  y[p1][1] = yl1;
-      x[p1][2] = xl2;  y[p1][2] = yl2;
-      next[p1] = p3;
-      x[p3][0] = xr0;  y[p3][0] = yr0;
-      x[p3][1] = xr1;  y[p3][1] = yr1;
-      x[p3][2] = xr2;  y[p3][2] = yr2;
-      next[p3] = p2;
-    }
-  }
-}
-
-//
-// Add a point to the points array.  (This would use a generic resizable
-// array type if C++ supported parameterized types in some reasonable
-// way -- templates are a disgusting kludge.)
-//
-void XOutputDev::addPoint(XPoint **points, int *size, int *k, int x, int y) {
-  if (*k >= *size) {
-    *size += 32;
-    if (*points == tmpPoints) {
-      *points = (XPoint *)gmalloc(*size * sizeof(XPoint));
-      memcpy(*points, tmpPoints, *k * sizeof(XPoint));
-    } else {
-      *points = (XPoint *)grealloc(*points, *size * sizeof(XPoint));
-    }
-  }
-  (*points)[*k].x = x;
-  (*points)[*k].y = y;
-  ++(*k);
-}
-
-void XOutputDev::beginString(GfxState *state, GString *s) {
-  text->beginWord(state, state->getCurX(), state->getCurY());
-}
-
-void XOutputDev::endString(GfxState *state) {
-  text->endWord();
-}
-
-void XOutputDev::drawChar(GfxState *state, double x, double y,
-                         double dx, double dy,
-                         double originX, double originY,
-                         CharCode code, Unicode *u, int uLen) {
-  int render;
-  double x1, y1, dx1, dy1;
-  GfxRGB rgb;
-  double saveCurX, saveCurY;
-  double *ctm;
-  double saveCTM[6];
-
-  if (needFontUpdate) {
-    updateFont(state);
-  }
-
-  text->addChar(state, x, y, dx, dy, code, u, uLen);
-
-  if (!font) {
-    return;
-  }
-
-  // check for invisible text -- this is used by Acrobat Capture
-  render = state->getRender();
-  if (render == 3) {
-    return;
-  }
-
-  x -= originX;
-  y -= originY;
-  state->transform(x, y, &x1, &y1);
-  state->transformDelta(dx, dy, &dx1, &dy1);
-
-  // fill
-  if (!(render & 1)) {
-    state->getFillRGB(&rgb);
-    if (reverseVideo) {
-      rgb.r = 1 - rgb.r;
-      rgb.g = 1 - rgb.g;
-      rgb.b = 1 - rgb.b;
-    }
-    font->drawChar(state, pixmap, pixmapW, pixmapH, fillGC, &rgb,
-                  x1, y1, dx1, dy1, code, u, uLen);
-  }
-
-  // stroke
-  if ((render & 3) == 1 || (render & 3) == 2) {
-    if (font->hasGetCharPath()) {
-      saveCurX = state->getCurX();
-      saveCurY = state->getCurY();
-      ctm = state->getCTM();
-      memcpy(saveCTM, ctm, 6 * sizeof(double));
-      state->setCTM(1, 0, 0, 1, x1, y1);
-      font->getCharPath(state, code, u, uLen);
-      stroke(state);
-      state->clearPath();
-      state->setCTM(saveCTM[0], saveCTM[1], saveCTM[2], saveCTM[3],
-                   saveCTM[4], saveCTM[5]);
-      state->moveTo(saveCurX, saveCurY);
-    } else {
-      // can't stroke the outline, so just fill it using the stroke
-      // color
-      state->getStrokeRGB(&rgb);
-      if (reverseVideo) {
-       rgb.r = 1 - rgb.r;
-       rgb.g = 1 - rgb.g;
-       rgb.b = 1 - rgb.b;
-      }
-      font->drawChar(state, pixmap, pixmapW, pixmapH, strokeGC, &rgb,
-                    x1, y1, dx1, dy1, code, u, uLen);
-    }
-  }
-
-  // clip
-  if (render & 4) {
-    if (font->hasGetCharPath()) {
-      saveCurX = state->getCurX();
-      saveCurY = state->getCurY();
-      font->getCharPath(state, code, u, uLen);
-      state->getPath()->offset(x1, y1);
-      if (textClipPath) {
-       textClipPath->append(state->getPath());
-      } else {
-       textClipPath = state->getPath()->copy();
-      }
-      state->clearPath();
-      state->moveTo(saveCurX, saveCurY);
-    }
-  }
-}
-
-GBool XOutputDev::beginType3Char(GfxState *state,
-                                CharCode code, Unicode *u, int uLen) {
-  Ref *fontID;
-  double *ctm, *bbox;
-  GfxRGB color;
-  T3FontCache *t3Font;
-  T3GlyphStack *t3gs;
-  double x1, y1, xMin, yMin, xMax, yMax, xt, yt;
-  int i, j;
-
-  if (needFontUpdate) {
-    updateFont(state);
-  }
-  if (!gfxFont) {
-    return gFalse;
-  }
-  fontID = gfxFont->getID();
-  ctm = state->getCTM();
-  state->transform(0, 0, &xt, &yt);
-
-  // is it the first (MRU) font in the cache?
-  if (!(nT3Fonts > 0 &&
-       t3FontCache[0]->matches(fontID, ctm[0], ctm[1], ctm[2], ctm[3]))) {
-
-    // is the font elsewhere in the cache?
-    for (i = 1; i < nT3Fonts; ++i) {
-      if (t3FontCache[i]->matches(fontID, ctm[0], ctm[1], ctm[2], ctm[3])) {
-       t3Font = t3FontCache[i];
-       for (j = i; j > 0; --j) {
-         t3FontCache[j] = t3FontCache[j - 1];
-       }
-       t3FontCache[0] = t3Font;
-       break;
-      }
-    }
-    if (i >= nT3Fonts) {
-
-      // create new entry in the font cache
-      if (nT3Fonts == xOutT3FontCacheSize) {
-       delete t3FontCache[nT3Fonts - 1];
-       --nT3Fonts;
-      }
-      for (j = nT3Fonts; j > 0; --j) {
-       t3FontCache[j] = t3FontCache[j - 1];
-      }
-      ++nT3Fonts;
-      bbox = gfxFont->getFontBBox();
-      if (bbox[0] == 0 && bbox[1] == 0 && bbox[2] == 0 && bbox[3] == 0) {
-       // broken bounding box -- just take a guess
-       xMin = xt - 5;
-       xMax = xMin + 30;
-       yMax = yt + 15;
-       yMin = yMax - 45;
-      } else {
-       state->transform(bbox[0], bbox[1], &x1, &y1);
-       xMin = xMax = x1;
-       yMin = yMax = y1;
-       state->transform(bbox[0], bbox[3], &x1, &y1);
-       if (x1 < xMin) {
-         xMin = x1;
-       } else if (x1 > xMax) {
-         xMax = x1;
-       }
-       if (y1 < yMin) {
-         yMin = y1;
-       } else if (y1 > yMax) {
-         yMax = y1;
-       }
-       state->transform(bbox[2], bbox[1], &x1, &y1);
-       if (x1 < xMin) {
-         xMin = x1;
-       } else if (x1 > xMax) {
-         xMax = x1;
-       }
-       if (y1 < yMin) {
-         yMin = y1;
-       } else if (y1 > yMax) {
-         yMax = y1;
-       }
-       state->transform(bbox[2], bbox[3], &x1, &y1);
-       if (x1 < xMin) {
-         xMin = x1;
-       } else if (x1 > xMax) {
-         xMax = x1;
-       }
-       if (y1 < yMin) {
-         yMin = y1;
-       } else if (y1 > yMax) {
-         yMax = y1;
-       }
-      }
-      t3FontCache[0] = new T3FontCache(fontID, ctm[0], ctm[1], ctm[2], ctm[3],
-                                      (int)floor(xMin - xt),
-                                      (int)floor(yMin - yt),
-                                      (int)ceil(xMax) - (int)floor(xMin) + 3,
-                                      (int)ceil(yMax) - (int)floor(yMin) + 3,
-                                      display, visual, depth, pixmap);
-    }
-  }
-  t3Font = t3FontCache[0];
-
-  // is the glyph in the cache?
-  i = (code & (t3Font->cacheSets - 1)) * t3Font->cacheAssoc;
-  for (j = 0; j < t3Font->cacheAssoc; ++j) {
-    if ((t3Font->cacheTags[i+j].mru & 0x8000) &&
-       t3Font->cacheTags[i+j].code == code) {
-      state->getFillRGB(&color);
-      if (reverseVideo) {
-       color.r = 1 - color.r;
-       color.g = 1 - color.g;
-       color.b = 1 - color.b;
-      }
-      text->addChar(state, 0, 0,
-                   t3Font->cacheTags[i+j].wx, t3Font->cacheTags[i+j].wy,
-                   code, u, uLen);
-      drawType3Glyph(t3Font, &t3Font->cacheTags[i+j],
-                    t3Font->cacheData + (i+j) * t3Font->glyphSize,
-                    xt, yt, &color);
-      return gTrue;
-    }
-  }
-
-  // push a new Type 3 glyph record
-  t3gs = new T3GlyphStack();
-  t3gs->next = t3GlyphStack;
-  t3GlyphStack = t3gs;
-  t3GlyphStack->cacheable = gFalse;
-  t3GlyphStack->code = code;
-  t3GlyphStack->cache = t3Font;
-  t3GlyphStack->cacheIdx = i;
-  t3GlyphStack->x = xt;
-  t3GlyphStack->y = yt;
-  t3GlyphStack->u = u;
-  t3GlyphStack->uLen = uLen;
-
-  return gFalse;
-}
-
-void XOutputDev::endType3Char(GfxState *state) {
-  XImage *image;
-  Guchar *p;
-  int x, y;
-  Gulong pixel;
-  double alpha;
-  T3GlyphStack *t3gs;
-  double *ctm;
-
-  if (t3GlyphStack->cacheable) {
-    image = t3GlyphStack->cache->image;
-    XGetSubImage(display, pixmap, 0, 0,
-                t3GlyphStack->cache->glyphW, t3GlyphStack->cache->glyphH,
-                (1 << depth) - 1, ZPixmap, image, 0, 0);
-    p = t3GlyphStack->cacheData;
-    for (y = 0; y < t3GlyphStack->cache->glyphH; ++y) {
-      for (x = 0; x < t3GlyphStack->cache->glyphW; ++x) {
-       pixel = XGetPixel(image, x, y);
-       if (trueColor) {
-         alpha = (double)((pixel >> rShift) & rMul) / (double)rMul;
-       } else {
-         alpha = redMap[pixel & 0xff];
-       }
-       if (alpha <= 0.2) {
-         *p++ = 4;
-       } else if (alpha <= 0.4) {
-         *p++ = 3;
-       } else if (alpha <= 0.6) {
-         *p++ = 2;
-       } else if (alpha <= 0.8) {
-         *p++ = 1;
-       } else {
-         *p++ = 0;
-       }
-      }
-    }
-    XDestroyRegion(clipRegion);
-    XFreeGC(display, strokeGC);
-    XFreeGC(display, fillGC);
-    pixmapW = t3GlyphStack->origPixmapW;
-    pixmapH = t3GlyphStack->origPixmapH;
-    pixmap = t3GlyphStack->origPixmap;
-    strokeGC = t3GlyphStack->origStrokeGC;
-    fillGC = t3GlyphStack->origFillGC;
-    clipRegion = t3GlyphStack->origClipRegion;
-    drawType3Glyph(t3GlyphStack->cache,
-                  t3GlyphStack->cacheTag, t3GlyphStack->cacheData,
-                  t3GlyphStack->x, t3GlyphStack->y, &t3GlyphStack->color);
-    // the CTM must be restored here in order for TextPage::addChar to
-    // work correctly
-    ctm = state->getCTM();
-    state->setCTM(ctm[0], ctm[1], ctm[2], ctm[3],
-                 t3GlyphStack->origCTM4, t3GlyphStack->origCTM5);
-  }
-  text->addChar(state, 0, 0, t3GlyphStack->wx, t3GlyphStack->wy,
-               t3GlyphStack->code, t3GlyphStack->u, t3GlyphStack->uLen);
-  t3gs = t3GlyphStack;
-  t3GlyphStack = t3gs->next;
-  delete t3gs;
-}
-
-void XOutputDev::drawType3Glyph(T3FontCache *t3Font,
-                               T3FontCacheTag *tag, Guchar *data,
-                               double x, double y, GfxRGB *color) {
-  XImage *image;
-  XColor xcolor;
-  GfxRGB bg, rgb;
-  Gulong map[5];
-  Gulong pixel;
-  Guchar *p;
-  int x0, y0, w0, h0, x1, y1;
-  int ix, iy;
-
-  // compute: (x0,y0) = position in destination pixmap
-  //          (x1,y1) = position in the XImage
-  //          (w0,h0) = size of XImage transfer
-  x0 = xoutRound(x + t3Font->glyphX);
-  y0 = xoutRound(y + t3Font->glyphY);
-  x1 = 0;
-  y1 = 0;
-  w0 = t3Font->glyphW;
-  h0 = t3Font->glyphH;
-  if (x0 < 0) {
-    x1 = -x0;
-    w0 += x0;
-    x0 = 0;
-  }
-  if (x0 + w0 > pixmapW) {
-    w0 = pixmapW - x0;
-  }
-  if (w0 <= 0) {
-    return;
-  }
-  if (y0 < 0) {
-    y1 = -y0;
-    h0 += y0;
-    y0 = 0;
-  }
-  if (y0 + h0 > pixmapH) {
-    h0 = pixmapH - y0;
-  }
-  if (h0 <= 0) {
-    return;
-  }
-
-  image = t3Font->image;
-  XGetSubImage(display, pixmap, x0, y0, w0, h0,
-              (1 << depth) - 1, ZPixmap, image, x1, y1);
-  xcolor.pixel = XGetPixel(image, t3Font->glyphW / 2, t3Font->glyphH / 2);
-  XQueryColor(display, colormap, &xcolor);
-  bg.r = xcolor.red / 65535.0;
-  bg.g = xcolor.green / 65535.0;
-  bg.b = xcolor.blue / 65535.0;
-  rgb.r = 0.25 * (color->r + 3 * bg.r);
-  rgb.g = 0.25 * (color->g + 3 * bg.g);
-  rgb.b = 0.25 * (color->b + 3 * bg.b);
-  map[1] = findColor(&rgb);
-  rgb.r = 0.5 * (color->r + bg.r);
-  rgb.g = 0.5 * (color->g + bg.g);
-  rgb.b = 0.5 * (color->b + bg.b);
-  map[2] = findColor(&rgb);
-  rgb.r = 0.25 * (3 * color->r + bg.r);
-  rgb.g = 0.25 * (3 * color->g + bg.g);
-  rgb.b = 0.25 * (3 * color->b + bg.b);
-  map[3] = findColor(&rgb);
-  map[4] = findColor(color);
-  p = data;
-  for (iy = 0; iy < t3Font->glyphH; ++iy) {
-    for (ix = 0; ix < t3Font->glyphW; ++ix) {
-      pixel = *p++;
-      if (pixel > 0) {
-       XPutPixel(image, ix, iy, map[pixel]);
-      }
-    }
-  }
-  XPutImage(display, pixmap, fillGC, image, x1, y1, x0, y0, w0, h0);
-}
-
-void XOutputDev::type3D0(GfxState *state, double wx, double wy) {
-  t3GlyphStack->wx = wx;
-  t3GlyphStack->wy = wy;
-}
-
-void XOutputDev::type3D1(GfxState *state, double wx, double wy,
-                        double llx, double lly, double urx, double ury) {
-  GfxColor fgColor;
-  XGCValues gcValues;
-  XRectangle rect;
-  double *ctm;
-  T3FontCache *t3Font;
-  double xt, yt, xMin, xMax, yMin, yMax, x1, y1;
-  int i, j;
-
-  t3Font = t3GlyphStack->cache;
-  t3GlyphStack->wx = wx;
-  t3GlyphStack->wy = wy;
-
-  // check for a valid bbox
-  state->transform(0, 0, &xt, &yt);
-  state->transform(llx, lly, &x1, &y1);
-  xMin = xMax = x1;
-  yMin = yMax = y1;
-  state->transform(llx, ury, &x1, &y1);
-  if (x1 < xMin) {
-    xMin = x1;
-  } else if (x1 > xMax) {
-    xMax = x1;
-  }
-  if (y1 < yMin) {
-    yMin = y1;
-  } else if (y1 > yMax) {
-    yMax = y1;
-  }
-  state->transform(urx, lly, &x1, &y1);
-  if (x1 < xMin) {
-    xMin = x1;
-  } else if (x1 > xMax) {
-    xMax = x1;
-  }
-  if (y1 < yMin) {
-    yMin = y1;
-  } else if (y1 > yMax) {
-    yMax = y1;
-  }
-  state->transform(urx, ury, &x1, &y1);
-  if (x1 < xMin) {
-    xMin = x1;
-  } else if (x1 > xMax) {
-    xMax = x1;
-  }
-  if (y1 < yMin) {
-    yMin = y1;
-  } else if (y1 > yMax) {
-    yMax = y1;
-  }
-  if (xMin - xt < t3Font->glyphX ||
-      yMin - yt < t3Font->glyphY ||
-      xMax - xt > t3Font->glyphX + t3Font->glyphW ||
-      yMax - yt > t3Font->glyphY + t3Font->glyphH) {
-    error(-1, "Bad bounding box in Type 3 glyph");
-    return;
-  }
-
-  // allocate a cache entry
-  t3GlyphStack->cacheable = gTrue;
-  i = t3GlyphStack->cacheIdx;
-  for (j = 0; j < t3Font->cacheAssoc; ++j) {
-    if ((t3Font->cacheTags[i+j].mru & 0x7fff) == t3Font->cacheAssoc - 1) {
-      t3Font->cacheTags[i+j].mru = 0x8000;
-      t3Font->cacheTags[i+j].code = t3GlyphStack->code;
-      t3GlyphStack->cacheTag = &t3Font->cacheTags[i+j];
-      t3GlyphStack->cacheData = t3Font->cacheData + (i+j) * t3Font->glyphSize;
-    } else {
-      ++t3Font->cacheTags[i+j].mru;
-    }
-  }
-  t3GlyphStack->cacheTag->wx = wx;
-  t3GlyphStack->cacheTag->wy = wy;
-
-  // prepare to rasterize the glyph
-  //~ do we need to handle both fill and stroke color?
-  state->getFillRGB(&t3GlyphStack->color);
-  if (reverseVideo) {
-    t3GlyphStack->color.r = 1 - t3GlyphStack->color.r;
-    t3GlyphStack->color.g = 1 - t3GlyphStack->color.g;
-    t3GlyphStack->color.b = 1 - t3GlyphStack->color.b;
-  }
-  fgColor.c[0] = reverseVideo ? 1 : 0;
-  state->setFillColorSpace(new GfxDeviceGrayColorSpace());
-  state->setFillColor(&fgColor);
-  state->setStrokeColorSpace(new GfxDeviceGrayColorSpace());
-  state->setStrokeColor(&fgColor);
-  t3GlyphStack->origPixmapW = pixmapW;
-  t3GlyphStack->origPixmapH = pixmapH;
-  t3GlyphStack->origPixmap = pixmap;
-  t3GlyphStack->origStrokeGC = strokeGC;
-  t3GlyphStack->origFillGC = fillGC;
-  t3GlyphStack->origClipRegion = clipRegion;
-  pixmapW = t3GlyphStack->cache->glyphW;
-  pixmapH = t3GlyphStack->cache->glyphH;
-  pixmap = t3GlyphStack->cache->pixmap;
-  gcValues.foreground = BlackPixel(display, screenNum);
-  gcValues.background = WhitePixel(display, screenNum);
-  gcValues.line_width = 0;
-  gcValues.line_style = LineSolid;
-  strokeGC = XCreateGC(display, pixmap,
-                      GCForeground | GCBackground | GCLineWidth | GCLineStyle,
-                      &gcValues);
-  updateLineAttrs(state, gTrue);
-  gcValues.foreground = WhitePixel(display, screenNum);
-  fillGC = XCreateGC(display, pixmap,
-                    GCForeground | GCBackground | GCLineWidth | GCLineStyle,
-                    &gcValues);
-  XFillRectangle(display, pixmap, fillGC, 0, 0, pixmapW, pixmapH);
-  XSetForeground(display, fillGC, BlackPixel(display, screenNum));
-  clipRegion = XCreateRegion();
-  rect.x = rect.y = 0;
-  rect.width = pixmapW;
-  rect.height = pixmapH;
-  XUnionRectWithRegion(&rect, clipRegion, clipRegion);
-  XSetRegion(display, strokeGC, clipRegion);
-  XSetRegion(display, fillGC, clipRegion);
-  ctm = state->getCTM();
-  t3GlyphStack->origCTM4 = ctm[4];
-  t3GlyphStack->origCTM5 = ctm[5];
-  state->setCTM(ctm[0], ctm[1], ctm[2], ctm[3], 
-               -t3GlyphStack->cache->glyphX, -t3GlyphStack->cache->glyphY);
-}
-
-void XOutputDev::endTextObject(GfxState *state) {
-  double *ctm;
-  double saveCTM[6];
-
-  if (textClipPath) {
-    ctm = state->getCTM();
-    memcpy(saveCTM, ctm, 6 * sizeof(double));
-    state->setCTM(1, 0, 0, 1, 0, 0);
-    doClip(state, textClipPath, WindingRule);
-    state->setCTM(saveCTM[0], saveCTM[1], saveCTM[2], saveCTM[3],
-                 saveCTM[4], saveCTM[5]);
-    delete textClipPath;
-    textClipPath = NULL;
-  }
-}
-
-inline Gulong XOutputDev::findColor(GfxRGB *x, GfxRGB *actual) {
-  double gray;
-  int r, g, b;
-  Gulong pixel;
-
-  if (trueColor) {
-    r = xoutRound(x->r * rMul);
-    g = xoutRound(x->g * gMul);
-    b = xoutRound(x->b * bMul);
-    pixel = ((Gulong)r << rShift) +
-            ((Gulong)g << gShift) +
-            ((Gulong)b << bShift);
-    actual->r = (double)r / rMul;
-    actual->g = (double)g / gMul;
-    actual->b = (double)b / bMul;
-  } else if (numColors == 1) {
-    gray = 0.299 * x->r + 0.587 * x->g + 0.114 * x->b;
-    if (gray < 0.5) {
-      pixel = colors[0];
-      actual->r = actual->g = actual->b = 0;
-    } else {
-      pixel = colors[1];
-      actual->r = actual->g = actual->b = 1;
-    }
-  } else {
-    r = xoutRound(x->r * (numColors - 1));
-    g = xoutRound(x->g * (numColors - 1));
-    b = xoutRound(x->b * (numColors - 1));
-    pixel = colors[(r * numColors + g) * numColors + b];
-    actual->r = (double)r / (numColors - 1);
-    actual->g = (double)g / (numColors - 1); 
-    actual->b = (double)b / (numColors - 1);
-  }
-  return pixel;
-}
-
-Gulong XOutputDev::findColor(GfxRGB *rgb) {
-  int r, g, b;
-  double gray;
-  Gulong pixel;
-
-  if (trueColor) {
-    r = xoutRound(rgb->r * rMul);
-    g = xoutRound(rgb->g * gMul);
-    b = xoutRound(rgb->b * bMul);
-    pixel = ((Gulong)r << rShift) +
-            ((Gulong)g << gShift) +
-            ((Gulong)b << bShift);
-  } else if (numColors == 1) {
-    gray = 0.299 * rgb->r + 0.587 * rgb->g + 0.114 * rgb->b;
-    if (gray < 0.5)
-      pixel = colors[0];
-    else
-      pixel = colors[1];
-  } else {
-    r = xoutRound(rgb->r * (numColors - 1));
-    g = xoutRound(rgb->g * (numColors - 1));
-    b = xoutRound(rgb->b * (numColors - 1));
-#if 0 // this makes things worse as often as better
-    // even a very light color shouldn't map to white
-    if (r == numColors - 1 && g == numColors - 1 && b == numColors - 1) {
-      if (color->getR() < 0.95)
-       --r;
-      if (color->getG() < 0.95)
-       --g;
-      if (color->getB() < 0.95)
-       --b;
-    }
-#endif
-    pixel = colors[(r * numColors + g) * numColors + b];
-  }
-  return pixel;
-}
-
-void XOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str,
-                              int width, int height, GBool invert,
-                              GBool inlineImg) {
-  ImageStream *imgStr;
-  XImage *image;
-  double *ctm;
-  GBool rot;
-  double xScale, yScale, xShear, yShear;
-  int tx, ty, scaledWidth, scaledHeight, xSign, ySign;
-  int ulx, uly, llx, lly, urx, ury, lrx, lry;
-  int ulx1, uly1, llx1, lly1, urx1, ury1, lrx1, lry1;
-  int bx0, by0, bx1, by1, bw, bh;
-  int cx0, cy0, cx1, cy1, cw, ch;
-  int yp, yq, yt, yStep, lastYStep;
-  int xp, xq, xt, xStep, xSrc;
-  GfxRGB rgb;
-  Guchar *pixBuf;
-  int imgPix;
-  double alpha;
-  XColor xcolor;
-  Gulong lastPixel;
-  GfxRGB rgb2;
-  double r0, g0, b0, r1, g1, b1;
-  Gulong pix;
-  Guchar *p;
-  int x, y, x1, y1, x2, y2;
-  int n, m, i, j;
-
-  // get CTM, check for singular matrix
-  ctm = state->getCTM();
-  if (fabs(ctm[0] * ctm[3] - ctm[1] * ctm[2]) < 0.000001) {
-    error(-1, "Singular CTM in drawImage");
-    if (inlineImg) {
-      j = height * ((width + 7) / 8);
-      str->reset();
-      for (i = 0; i < j; ++i) {
-       str->getChar();
-      }
-      str->close();
-    }
-    return;
-  }
-
-  // compute scale, shear, rotation, translation parameters
-  rot = fabs(ctm[1]) > fabs(ctm[0]);
-  if (rot) {
-    xScale = -ctm[1];
-    yScale = -ctm[2] + (ctm[0] * ctm[3]) / ctm[1];
-    xShear = ctm[3] / yScale;
-    yShear = -ctm[0] / ctm[1];
-  } else {
-    xScale = ctm[0];
-    yScale = -ctm[3] + (ctm[1] * ctm[2]) / ctm[0];
-    xShear = -ctm[2] / yScale;
-    yShear = ctm[1] / ctm[0];
-  }
-  tx = xoutRound(ctm[2] + ctm[4]);
-  ty = xoutRound(ctm[3] + ctm[5]);
-  // use ceil() to avoid gaps between "striped" images
-  scaledWidth = (int)ceil(fabs(xScale));
-  xSign = (xScale < 0) ? -1 : 1;
-  scaledHeight = (int)ceil(fabs(yScale));
-  ySign = (yScale < 0) ? -1 : 1;
-
-  // compute corners in device space
-  ulx1 = 0;
-  uly1 = 0;
-  urx1 = xSign * (scaledWidth - 1);
-  ury1 = xoutRound(yShear * urx1);
-  llx1 = xoutRound(xShear * ySign * (scaledHeight - 1));
-  lly1 = ySign * (scaledHeight - 1) + xoutRound(yShear * llx1);
-  lrx1 = xSign * (scaledWidth - 1) +
-           xoutRound(xShear * ySign * (scaledHeight - 1));
-  lry1 = ySign * (scaledHeight - 1) + xoutRound(yShear * lrx1);
-  if (rot) {
-    ulx = tx + uly1;    uly = ty - ulx1;
-    urx = tx + ury1;    ury = ty - urx1;
-    llx = tx + lly1;    lly = ty - llx1;
-    lrx = tx + lry1;    lry = ty - lrx1;
-  } else {
-    ulx = tx + ulx1;    uly = ty + uly1;
-    urx = tx + urx1;    ury = ty + ury1;
-    llx = tx + llx1;    lly = ty + lly1;
-    lrx = tx + lrx1;    lry = ty + lry1;
-  }
-
-  // bounding box:
-  //   (bx0, by0) = upper-left corner
-  //   (bx1, by1) = lower-right corner
-  //   (bw, bh) = size
-  bx0 = (ulx < urx) ? (ulx < llx) ? (ulx < lrx) ? ulx : lrx
-                                  : (llx < lrx) ? llx : lrx
-                   : (urx < llx) ? (urx < lrx) ? urx : lrx
-                                  : (llx < lrx) ? llx : lrx;
-  bx1 = (ulx > urx) ? (ulx > llx) ? (ulx > lrx) ? ulx : lrx
-                                  : (llx > lrx) ? llx : lrx
-                   : (urx > llx) ? (urx > lrx) ? urx : lrx
-                                  : (llx > lrx) ? llx : lrx;
-  by0 = (uly < ury) ? (uly < lly) ? (uly < lry) ? uly : lry
-                                  : (lly < lry) ? lly : lry
-                   : (ury < lly) ? (ury < lry) ? ury : lry
-                                  : (lly < lry) ? lly : lry;
-  by1 = (uly > ury) ? (uly > lly) ? (uly > lry) ? uly : lry
-                                  : (lly > lry) ? lly : lry
-                   : (ury > lly) ? (ury > lry) ? ury : lry
-                                  : (lly > lry) ? lly : lry;
-  bw = bx1 - bx0 + 1;
-  bh = by1 - by0 + 1;
-
-  // Bounding box clipped to pixmap, i.e., "valid" rectangle:
-  //   (cx0, cy0) = upper-left corner of valid rectangle in Pixmap
-  //   (cx1, cy1) = upper-left corner of valid rectangle in XImage
-  //   (cw, ch) = size of valid rectangle
-  // These values will be used to transfer the XImage from/to the
-  // Pixmap.
-  cw = (bx1 >= pixmapW) ? pixmapW - bx0 : bw;
-  if (bx0 < 0) {
-    cx0 = 0;
-    cx1 = -bx0;
-    cw += bx0;
-  } else {
-    cx0 = bx0;
-    cx1 = 0;
-  }
-  ch = (by1 >= pixmapH) ? pixmapH - by0 : bh;
-  if (by0 < 0) {
-    cy0 = 0;
-    cy1 = -by0;
-    ch += by0;
-  } else {
-    cy0 = by0;
-    cy1 = 0;
-  }
-
-  // check for tiny (zero width or height) images
-  // and off-page images
-  if (scaledWidth <= 0 || scaledHeight <= 0 || cw <= 0 || ch <= 0) {
-    if (inlineImg) {
-      j = height * ((width + 7) / 8);
-      str->reset();
-      for (i = 0; i < j; ++i) {
-       str->getChar();
-      }
-      str->close();
-    }
-    return;
-  }
-
-  // compute Bresenham parameters for x and y scaling
-  yp = height / scaledHeight;
-  yq = height % scaledHeight;
-  xp = width / scaledWidth;
-  xq = width % scaledWidth;
-
-  // allocate pixel buffer
-  pixBuf = (Guchar *)gmalloc((yp + 1) * width * sizeof(Guchar));
-
-  // allocate XImage and read from page pixmap
-  image = XCreateImage(display, visual, depth, ZPixmap, 0, NULL, bw, bh, 8, 0);
-  image->data = (char *)gmalloc(bh * image->bytes_per_line);
-  XGetSubImage(display, pixmap, cx0, cy0, cw, ch, (1 << depth) - 1, ZPixmap,
-              image, cx1, cy1);
-
-  // get mask color
-  state->getFillRGB(&rgb);
-  if (reverseVideo) {
-    rgb.r = 1 - rgb.r;
-    rgb.g = 1 - rgb.g;
-    rgb.b = 1 - rgb.b;
-  }
-  r0 = rgb.r;
-  g0 = rgb.g;
-  b0 = rgb.b;
-
-  // initialize background color
-  // (the specific pixel value doesn't matter here, as long as
-  // r1,g1,b1 correspond correctly to lastPixel)
-  xcolor.pixel = lastPixel = 0;
-  XQueryColor(display, colormap, &xcolor);
-  r1 = (double)xcolor.red / 65535.0;
-  g1 = (double)xcolor.green / 65535.0;
-  b1 = (double)xcolor.blue / 65535.0;
-
-  // initialize the image stream
-  imgStr = new ImageStream(str, width, 1, 1);
-  imgStr->reset();
-
-  // init y scale Bresenham
-  yt = 0;
-  lastYStep = 1;
-
-  for (y = 0; y < scaledHeight; ++y) {
-
-    // y scale Bresenham
-    yStep = yp;
-    yt += yq;
-    if (yt >= scaledHeight) {
-      yt -= scaledHeight;
-      ++yStep;
-    }
-
-    // read row(s) from image
-    n = (yp > 0) ? yStep : lastYStep;
-    if (n > 0) {
-      p = pixBuf;
-      for (i = 0; i < n; ++i) {
-       memcpy(p, imgStr->getLine(), width);
-       if (invert) {
-         for (j = 0; j < width; ++j) {
-           p[j] ^= 1;
-         }
-       }
-       p += width;
-      }
-    }
-    lastYStep = yStep;
-
-    // init x scale Bresenham
-    xt = 0;
-    xSrc = 0;
-
-    for (x = 0; x < scaledWidth; ++x) {
-
-      // x scale Bresenham
-      xStep = xp;
-      xt += xq;
-      if (xt >= scaledWidth) {
-       xt -= scaledWidth;
-       ++xStep;
-      }
-
-      // x shear
-      x1 = xSign * x + xoutRound(xShear * ySign * y);
-
-      // y shear
-      y1 = ySign * y + xoutRound(yShear * x1);
-
-      // rotation
-      if (rot) {
-       x2 = y1;
-       y2 = -x1;
-      } else {
-       x2 = x1;
-       y2 = y1;
-      }
-
-      // compute the filtered pixel at (x,y) after the
-      // x and y scaling operations
-      n = yStep > 0 ? yStep : 1;
-      m = xStep > 0 ? xStep : 1;
-      p = pixBuf + xSrc;
-      imgPix = 0;
-      for (i = 0; i < n; ++i) {
-       for (j = 0; j < m; ++j) {
-         imgPix += *p++;
-       }
-       p += width - m;
-      }
-
-      // x scale Bresenham
-      xSrc += xStep;
-
-      // blend image pixel with background
-      alpha = (double)imgPix / (double)(n * m);
-      xcolor.pixel = XGetPixel(image, tx + x2 - bx0, ty + y2 - by0);
-      if (xcolor.pixel != lastPixel) {
-       XQueryColor(display, colormap, &xcolor);
-       r1 = (double)xcolor.red / 65535.0;
-       g1 = (double)xcolor.green / 65535.0;
-       b1 = (double)xcolor.blue / 65535.0;
-       lastPixel = xcolor.pixel;
-      }
-      rgb2.r = r0 * (1 - alpha) + r1 * alpha;
-      rgb2.g = g0 * (1 - alpha) + g1 * alpha;
-      rgb2.b = b0 * (1 - alpha) + b1 * alpha;
-      pix = findColor(&rgb2);
-
-      // set pixel
-      XPutPixel(image, tx + x2 - bx0, ty + y2 - by0, pix);
-    }
-  }
-
-  // blit the image into the pixmap
-  XPutImage(display, pixmap, fillGC, image, cx1, cy1, cx0, cy0, cw, ch);
-
-  // free memory
-  delete imgStr;
-  gfree(pixBuf);
-  gfree(image->data);
-  image->data = NULL;
-  XDestroyImage(image);
-}
-
-void XOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
-                          int width, int height, GfxImageColorMap *colorMap,
-                          int *maskColors, GBool inlineImg) {
-  ImageStream *imgStr;
-  XImage *image;
-  int nComps, nVals, nBits;
-  GBool dither;
-  double *ctm;
-  GBool rot;
-  double xScale, yScale, xShear, yShear;
-  int tx, ty, scaledWidth, scaledHeight, xSign, ySign;
-  int ulx, uly, llx, lly, urx, ury, lrx, lry;
-  int ulx1, uly1, llx1, lly1, urx1, ury1, lrx1, lry1;
-  int bx0, by0, bx1, by1, bw, bh;
-  int cx0, cy0, cx1, cy1, cw, ch;
-  int yp, yq, yt, yStep, lastYStep;
-  int xp, xq, xt, xStep, xSrc;
-  GfxRGB *pixBuf;
-  Guchar *pixBuf1, *alphaBuf;
-  Guchar pixBuf2[gfxColorMaxComps];
-  GfxRGB color2, color3, actual, err, errRight;
-  GfxRGB *errDown0, *errDown1, *errDownTmp;
-  double r0, g0, b0, alpha, mul;
-  Gulong pix;
-  GfxRGB *p;
-  Guchar *q, *p1, *p2;
-  GBool oneBitMode;
-  GfxRGB oneBitRGB[2];
-  int x, y, x1, y1, x2, y2;
-  int n, m, i, j, k;
-
-  // image parameters
-  nComps = colorMap->getNumPixelComps();
-  nVals = width * nComps;
-  nBits = colorMap->getBits();
-  oneBitMode = nComps == 1 && nBits == 1 && !maskColors;
-  dither = nComps > 1 || nBits > 1;
-
-  // get CTM, check for singular matrix
-  ctm = state->getCTM();
-  if (fabs(ctm[0] * ctm[3] - ctm[1] * ctm[2]) < 0.000001) {
-    error(-1, "Singular CTM in drawImage");
-    if (inlineImg) {
-      str->reset();
-      j = height * ((nVals * nBits + 7) / 8);
-      for (i = 0; i < j; ++i) {
-       str->getChar();
-      }
-      str->close();
-    }
-    return;
-  }
-
-  // compute scale, shear, rotation, translation parameters
-  rot = fabs(ctm[1]) > fabs(ctm[0]);
-  if (rot) {
-    xScale = -ctm[1];
-    yScale = -ctm[2] + (ctm[0] * ctm[3]) / ctm[1];
-    xShear = ctm[3] / yScale;
-    yShear = -ctm[0] / ctm[1];
-  } else {
-    xScale = ctm[0];
-    yScale = -ctm[3] + (ctm[1] * ctm[2]) / ctm[0];
-    xShear = -ctm[2] / yScale;
-    yShear = ctm[1] / ctm[0];
-  }
-  tx = xoutRound(ctm[2] + ctm[4]);
-  ty = xoutRound(ctm[3] + ctm[5]);
-  if (xScale < 0) {
-    // this is the right edge which needs to be (left + width - 1)
-    --tx;
-  }
-  if (yScale < 0) {
-    // this is the bottom edge which needs to be (top + height - 1)
-    --ty;
-  }
-  // use ceil() to avoid gaps between "striped" images
-  scaledWidth = (int)ceil(fabs(xScale));
-  xSign = (xScale < 0) ? -1 : 1;
-  scaledHeight = (int)ceil(fabs(yScale));
-  ySign = (yScale < 0) ? -1 : 1;
-
-  // compute corners in device space
-  ulx1 = 0;
-  uly1 = 0;
-  urx1 = xSign * (scaledWidth - 1);
-  ury1 = xoutRound(yShear * urx1);
-  llx1 = xoutRound(xShear * ySign * (scaledHeight - 1));
-  lly1 = ySign * (scaledHeight - 1) + xoutRound(yShear * llx1);
-  lrx1 = xSign * (scaledWidth - 1) +
-           xoutRound(xShear * ySign * (scaledHeight - 1));
-  lry1 = ySign * (scaledHeight - 1) + xoutRound(yShear * lrx1);
-  if (rot) {
-    ulx = tx + uly1;    uly = ty - ulx1;
-    urx = tx + ury1;    ury = ty - urx1;
-    llx = tx + lly1;    lly = ty - llx1;
-    lrx = tx + lry1;    lry = ty - lrx1;
-  } else {
-    ulx = tx + ulx1;    uly = ty + uly1;
-    urx = tx + urx1;    ury = ty + ury1;
-    llx = tx + llx1;    lly = ty + lly1;
-    lrx = tx + lrx1;    lry = ty + lry1;
-  }
-
-  // bounding box:
-  //   (bx0, by0) = upper-left corner
-  //   (bx1, by1) = lower-right corner
-  //   (bw, bh) = size
-  bx0 = (ulx < urx) ? (ulx < llx) ? (ulx < lrx) ? ulx : lrx
-                                  : (llx < lrx) ? llx : lrx
-                   : (urx < llx) ? (urx < lrx) ? urx : lrx
-                                  : (llx < lrx) ? llx : lrx;
-  bx1 = (ulx > urx) ? (ulx > llx) ? (ulx > lrx) ? ulx : lrx
-                                  : (llx > lrx) ? llx : lrx
-                   : (urx > llx) ? (urx > lrx) ? urx : lrx
-                                  : (llx > lrx) ? llx : lrx;
-  by0 = (uly < ury) ? (uly < lly) ? (uly < lry) ? uly : lry
-                                  : (lly < lry) ? lly : lry
-                   : (ury < lly) ? (ury < lry) ? ury : lry
-                                  : (lly < lry) ? lly : lry;
-  by1 = (uly > ury) ? (uly > lly) ? (uly > lry) ? uly : lry
-                                  : (lly > lry) ? lly : lry
-                   : (ury > lly) ? (ury > lry) ? ury : lry
-                                  : (lly > lry) ? lly : lry;
-  bw = bx1 - bx0 + 1;
-  bh = by1 - by0 + 1;
-
-  // Bounding box clipped to pixmap, i.e., "valid" rectangle:
-  //   (cx0, cy0) = upper-left corner of valid rectangle in Pixmap
-  //   (cx1, cy1) = upper-left corner of valid rectangle in XImage
-  //   (cw, ch) = size of valid rectangle
-  // These values will be used to transfer the XImage from/to the
-  // Pixmap.
-  cw = (bx1 >= pixmapW) ? pixmapW - bx0 : bw;
-  if (bx0 < 0) {
-    cx0 = 0;
-    cx1 = -bx0;
-    cw += bx0;
-  } else {
-    cx0 = bx0;
-    cx1 = 0;
-  }
-  ch = (by1 >= pixmapH) ? pixmapH - by0 : bh;
-  if (by0 < 0) {
-    cy0 = 0;
-    cy1 = -by0;
-    ch += by0;
-  } else {
-    cy0 = by0;
-    cy1 = 0;
-  }
-
-  // check for tiny (zero width or height) images
-  // and off-page images
-  if (scaledWidth <= 0 || scaledHeight <= 0 || cw <= 0 || ch <= 0) {
-    if (inlineImg) {
-      str->reset();
-      j = height * ((nVals * nBits + 7) / 8);
-      for (i = 0; i < j; ++i)
-       str->getChar();
-      str->close();
-    }
-    return;
-  }
-
-  // compute Bresenham parameters for x and y scaling
-  yp = height / scaledHeight;
-  yq = height % scaledHeight;
-  xp = width / scaledWidth;
-  xq = width % scaledWidth;
-
-  // allocate pixel buffer
-  if (oneBitMode) {
-    pixBuf1 = (Guchar *)gmalloc((yp + 1) * width * sizeof(Guchar));
-    pixBuf = NULL;
-  } else {
-    pixBuf = (GfxRGB *)gmalloc((yp + 1) * width * sizeof(GfxRGB));
-    pixBuf1 = NULL;
-  }
-  if (maskColors) {
-    alphaBuf = (Guchar *)gmalloc((yp + 1) * width * sizeof(Guchar));
-  } else {
-    alphaBuf = NULL;
-  }
-
-  // allocate XImage
-  image = XCreateImage(display, visual, depth, ZPixmap, 0, NULL, bw, bh, 8, 0);
-  image->data = (char *)gmalloc(bh * image->bytes_per_line);
-
-  // if the transform is anything other than a 0/90/180/270 degree
-  // rotation/flip, or if there is color key masking, read the
-  // backgound pixmap to fill in the corners
-  if (!((ulx == llx && uly == ury) ||
-       (uly == lly && ulx == urx)) ||
-      maskColors) {
-    XGetSubImage(display, pixmap, cx0, cy0, cw, ch, (1 << depth) - 1, ZPixmap,
-                image, cx1, cy1);
-  }
-
-  // allocate error diffusion accumulators
-  if (dither) {
-    errDown0 = (GfxRGB *)gmalloc((scaledWidth + 2) * sizeof(GfxRGB));
-    errDown1 = (GfxRGB *)gmalloc((scaledWidth + 2) * sizeof(GfxRGB));
-    for (j = 0; j < scaledWidth + 2; ++j) {
-      errDown0[j].r = errDown0[j].g = errDown0[j].b = 0;
-      errDown1[j].r = errDown1[j].g = errDown1[j].b = 0;
-    }
-  } else {
-    errDown0 = errDown1 = NULL;
-  }
-
-  // optimize the one-bit-deep image case
-  if (oneBitMode) {
-    pixBuf2[0] = 0;
-    colorMap->getRGB(pixBuf2, &oneBitRGB[0]);
-    pixBuf2[0] = 1;
-    colorMap->getRGB(pixBuf2, &oneBitRGB[1]);
-  }
-
-  // initialize the image stream
-  imgStr = new ImageStream(str, width, nComps, nBits);
-  imgStr->reset();
-
-  // init y scale Bresenham
-  yt = 0;
-  lastYStep = 1;
-
-  for (y = 0; y < scaledHeight; ++y) {
-
-    // initialize error diffusion accumulators
-    if (dither) {
-      errDownTmp = errDown0;
-      errDown0 = errDown1;
-      errDown1 = errDownTmp;
-      for (j = 0; j < scaledWidth + 2; ++j) {
-       errDown1[j].r = errDown1[j].g = errDown1[j].b = 0;
-      }
-      errRight.r = errRight.g = errRight.b = 0;
-    }
-
-    // y scale Bresenham
-    yStep = yp;
-    yt += yq;
-    if (yt >= scaledHeight) {
-      yt -= scaledHeight;
-      ++yStep;
-    }
-
-    // read row(s) from image
-    n = (yp > 0) ? yStep : lastYStep;
-    if (n > 0) {
-      if (oneBitMode) {
-       p1 = pixBuf1;
-       for (i = 0; i < n; ++i) {
-         p2 = imgStr->getLine();
-         memcpy(p1, p2, width);
-         p1 += width;
-       }
-      } else {
-       p = pixBuf;
-       q = alphaBuf;
-       for (i = 0; i < n; ++i) {
-         p2 = imgStr->getLine();
-         for (j = 0; j < width; ++j) {
-            colorMap->getRGB(p2, p);
-           ++p;
-           if (q) {
-             *q = 1;
-             for (k = 0; k < nComps; ++k) {
-               if (p2[k] < maskColors[2*k] ||
-                   p2[k] > maskColors[2*k+1]) {
-                 *q = 0;
-                 break;
-               }
-             }
-             ++q;
-           }
-           p2 += nComps;
-         }
-       }
-      }
-    }
-    lastYStep = yStep;
-
-    // init x scale Bresenham
-    xt = 0;
-    xSrc = 0;
-
-    for (x = 0; x < scaledWidth; ++x) {
-
-      // x scale Bresenham
-      xStep = xp;
-      xt += xq;
-      if (xt >= scaledWidth) {
-       xt -= scaledWidth;
-       ++xStep;
-      }
-
-      // x shear
-      x1 = xSign * x + xoutRound(xShear * ySign * y);
-
-      // y shear
-      y1 = ySign * y + xoutRound(yShear * x1);
-
-      // rotation
-      if (rot) {
-       x2 = y1;
-       y2 = -x1;
-      } else {
-       x2 = x1;
-       y2 = y1;
-      }
-
-      // compute the filtered pixel at (x,y) after the
-      // x and y scaling operations
-      n = yStep > 0 ? yStep : 1;
-      m = xStep > 0 ? xStep : 1;
-      if (oneBitMode) {
-       p1 = pixBuf1 + xSrc;
-       k = 0;
-       for (i = 0; i < n; ++i) {
-         for (j = 0; j < m; ++j) {
-           k += *p1++;
-         }
-         p1 += width - m;
-       }
-       mul = (double)k / (double)(n * m);
-       r0 = mul * oneBitRGB[1].r + (1 - mul) * oneBitRGB[0].r;
-       g0 = mul * oneBitRGB[1].g + (1 - mul) * oneBitRGB[0].g;
-       b0 = mul * oneBitRGB[1].b + (1 - mul) * oneBitRGB[0].b;
-       alpha = 0;
-      } else {
-       p = pixBuf + xSrc;
-       q = alphaBuf ? alphaBuf + xSrc : (Guchar *)NULL;
-       alpha = 0;
-       r0 = g0 = b0 = 0;
-       for (i = 0; i < n; ++i) {
-         for (j = 0; j < m; ++j) {
-           r0 += p->r;
-           g0 += p->g;
-           b0 += p->b;
-           ++p;
-           if (q) {
-             alpha += *q++;
-           }
-         }
-         p += width - m;
-       }
-       mul = 1 / (double)(n * m);
-       r0 *= mul;
-       g0 *= mul;
-       b0 *= mul;
-       alpha *= mul;
-      }
-
-      // x scale Bresenham
-      xSrc += xStep;
-
-      // compute pixel
-      if (dither) {
-       color2.r = r0 + errRight.r + errDown0[x + 1].r;
-       if (color2.r > 1) {
-         color3.r = 1;
-       } else if (color2.r < 0) {
-         color3.r = 0;
-       } else {
-         color3.r = color2.r;
-       }
-       color2.g = g0 + errRight.g + errDown0[x + 1].g;
-       if (color2.g > 1) {
-         color3.g = 1;
-       } else if (color2.g < 0) {
-         color3.g = 0;
-       } else {
-         color3.g = color2.g;
-       }
-       color2.b = b0 + errRight.b + errDown0[x + 1].b;
-       if (color2.b > 1) {
-         color3.b = 1;
-       } else if (color2.b < 0) {
-         color3.b = 0;
-       } else {
-         color3.b = color2.b;
-       }
-       pix = findColor(&color3, &actual);
-       err.r = (color2.r - actual.r) / 16;
-       err.g = (color2.g - actual.g) / 16;
-       err.b = (color2.b - actual.b) / 16;
-       errRight.r = 7 * err.r;
-       errRight.g = 7 * err.g;
-       errRight.b = 7 * err.b;
-       errDown1[x].r += 3 * err.r;
-       errDown1[x].g += 3 * err.g;
-       errDown1[x].b += 3 * err.b;
-       errDown1[x + 1].r += 5 * err.r;
-       errDown1[x + 1].g += 5 * err.g;
-       errDown1[x + 1].b += 5 * err.b;
-       errDown1[x + 2].r = err.r;
-       errDown1[x + 2].g = err.g;
-       errDown1[x + 2].b = err.b;
-      } else {
-       color2.r = r0;
-       color2.g = g0;
-       color2.b = b0;
-       pix = findColor(&color2, &actual);
-      }
-
-      // set pixel
-      //~ this should do a blend when 0 < alpha < 1
-      if (alpha < 0.75) {
-       XPutPixel(image, tx + x2 - bx0, ty + y2 - by0, pix);
-      }
-    }
-  }
-
-  // blit the image into the pixmap
-  XPutImage(display, pixmap, fillGC, image, cx1, cy1, cx0, cy0, cw, ch);
-
-  // free memory
-  delete imgStr;
-  if (oneBitMode) {
-    gfree(pixBuf1);
-  } else {
-    gfree(pixBuf);
-  }
-  if (maskColors) {
-    gfree(alphaBuf);
-  }
-  gfree(image->data);
-  image->data = NULL;
-  XDestroyImage(image);
-  gfree(errDown0);
-  gfree(errDown1);
-}
-
-GBool XOutputDev::findText(Unicode *s, int len,
-                          GBool startAtTop, GBool stopAtBottom,
-                          GBool startAtLast, GBool stopAtLast,
-                          int *xMin, int *yMin,
-                          int *xMax, int *yMax) {
-  double xMin1, yMin1, xMax1, yMax1;
-  
-  xMin1 = (double)*xMin;
-  yMin1 = (double)*yMin;
-  xMax1 = (double)*xMax;
-  yMax1 = (double)*yMax;
-  if (text->findText(s, len, startAtTop, stopAtBottom,
-                    startAtLast, stopAtLast,
-                    &xMin1, &yMin1, &xMax1, &yMax1)) {
-    *xMin = xoutRound(xMin1);
-    *xMax = xoutRound(xMax1);
-    *yMin = xoutRound(yMin1);
-    *yMax = xoutRound(yMax1);
-    return gTrue;
-  }
-  return gFalse;
-}
-
-GString *XOutputDev::getText(int xMin, int yMin, int xMax, int yMax) {
-  return text->getText((double)xMin, (double)yMin,
-                      (double)xMax, (double)yMax);
-}
diff --git a/pdf/xpdf/XOutputDev.h b/pdf/xpdf/XOutputDev.h
deleted file mode 100644 (file)
index 3efa1dd..0000000
+++ /dev/null
@@ -1,680 +0,0 @@
-//========================================================================
-//
-// XOutputDev.h
-//
-// Copyright 1996-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#ifndef XOUTPUTDEV_H
-#define XOUTPUTDEV_H
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma interface
-#endif
-
-#include <stddef.h>
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-#include "config.h"
-#include "Object.h"
-#include "CharTypes.h"
-#include "GlobalParams.h"
-#include "OutputDev.h"
-
-class GString;
-class GList;
-struct GfxRGB;
-class GfxFont;
-class GfxPath;
-class GfxSubpath;
-class TextPage;
-class XOutputFontCache;
-struct T3FontCacheTag;
-class T3FontCache;
-struct T3GlyphStack;
-class XOutputDev;
-class Link;
-class Catalog;
-class DisplayFontParam;
-class UnicodeMap;
-class CharCodeToUnicode;
-
-#if HAVE_T1LIB_H
-class T1FontEngine;
-class T1FontFile;
-class T1Font;
-#endif
-
-#if FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
-class FTFontEngine;
-class FTFontFile;
-class FTFont;
-#endif
-
-#if !FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
-class TTFontEngine;
-class TTFontFile;
-class TTFont;
-#endif
-
-//------------------------------------------------------------------------
-// Constants
-//------------------------------------------------------------------------
-
-#define maxRGBCube 7           // max size of RGB color cube
-
-#define numTmpPoints 256       // number of XPoints in temporary array
-#define numTmpSubpaths 16      // number of elements in temporary arrays
-                               //   for fill/clip
-
-//------------------------------------------------------------------------
-// Misc types
-//------------------------------------------------------------------------
-
-struct BoundingRect {
-  short xMin, xMax;            // min/max x values
-  short yMin, yMax;            // min/max y values
-};
-
-//------------------------------------------------------------------------
-// XOutputFont
-//------------------------------------------------------------------------
-
-class XOutputFont {
-public:
-
-  XOutputFont(Ref *idA, double m11OrigA, double m12OrigA,
-             double m21OrigA, double m22OrigA,
-             double m11A, double m12A, double m21A, double m22A,
-             Display *displayA, XOutputDev *xOutA);
-
-  virtual ~XOutputFont();
-
-  // Does this font match the ID and transform?
-  GBool matches(Ref *idA, double m11OrigA, double m12OrigA,
-               double m21OrigA, double m22OrigA)
-    { return id.num == idA->num && id.gen == idA->gen &&
-            m11Orig == m11OrigA && m12Orig == m12OrigA &&
-            m21Orig == m21OrigA && m22Orig == m22OrigA; }
-
-  // Was font created successfully?
-  virtual GBool isOk() = 0;
-
-  // Update <gc> with this font.
-  virtual void updateGC(GC gc) = 0;
-
-  // Draw character <c>/<u> at <x>,<y> (in device space).
-  virtual void drawChar(GfxState *state, Pixmap pixmap, int w, int h,
-                       GC gc, GfxRGB *rgb,
-                       double x, double y, double dx, double dy,
-                       CharCode c, Unicode *u, int uLen) = 0;
-
-  // Returns true if this XOutputFont subclass provides the
-  // getCharPath function.
-  virtual GBool hasGetCharPath() { return gFalse; }
-
-  // Add the character outline for <c>/<u> to the current path.
-  virtual void getCharPath(GfxState *state,
-                          CharCode c, Unicode *u, int ulen);
-
-protected:
-
-  Ref id;                      // font ID
-  double m11Orig, m12Orig,     // original transform matrix
-         m21Orig, m22Orig;
-  double m11, m12, m21, m22;   // actual transform matrix (possibly
-                               //   modified for font substitution)
-  Display *display;            // X display
-  XOutputDev *xOut;
-};
-
-#if HAVE_T1LIB_H
-//------------------------------------------------------------------------
-// XOutputT1Font
-//------------------------------------------------------------------------
-
-class XOutputT1Font: public XOutputFont {
-public:
-
-  XOutputT1Font(Ref *idA, T1FontFile *fontFileA,
-               double m11OrigA, double m12OrigA,
-               double m21OrigA, double m22OrigA,
-               double m11A, double m12A,
-               double m21A, double m22A,
-               Display *displayA, XOutputDev *xOutA);
-
-  virtual ~XOutputT1Font();
-
-  // Was font created successfully?
-  virtual GBool isOk();
-
-  // Update <gc> with this font.
-  virtual void updateGC(GC gc);
-
-  // Draw character <c>/<u> at <x>,<y>.
-  virtual void drawChar(GfxState *state, Pixmap pixmap, int w, int h,
-                       GC gc, GfxRGB *rgb,
-                       double x, double y, double dx, double dy,
-                       CharCode c, Unicode *u, int uLen);
-
-  // Returns true if this XOutputFont subclass provides the
-  // getCharPath function.
-  virtual GBool hasGetCharPath() { return gTrue; }
-
-  // Add the character outline for <c>/<u> to the current path.
-  virtual void getCharPath(GfxState *state,
-                          CharCode c, Unicode *u, int ulen);
-
-private:
-
-  T1FontFile *fontFile;
-  T1Font *font;
-};
-#endif // HAVE_T1LIB_H
-
-#if FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
-//------------------------------------------------------------------------
-// XOutputFTFont
-//------------------------------------------------------------------------
-
-class XOutputFTFont: public XOutputFont {
-public:
-
-  XOutputFTFont(Ref *idA, FTFontFile *fontFileA,
-               double m11OrigA, double m12OrigA,
-               double m21OrigA, double m22OrigA,
-               double m11A, double m12A,
-               double m21A, double m22A,
-               Display *displayA, XOutputDev *xOutA);
-
-  virtual ~XOutputFTFont();
-
-  // Was font created successfully?
-  virtual GBool isOk();
-
-  // Update <gc> with this font.
-  virtual void updateGC(GC gc);
-
-  // Draw character <c>/<u> at <x>,<y>.
-  virtual void drawChar(GfxState *state, Pixmap pixmap, int w, int h,
-                       GC gc, GfxRGB *rgb,
-                       double x, double y, double dx, double dy,
-                       CharCode c, Unicode *u, int uLen);
-
-  // Returns true if this XOutputFont subclass provides the
-  // getCharPath function.
-  virtual GBool hasGetCharPath() { return gTrue; }
-
-  // Add the character outline for <c>/<u> to the current path.
-  virtual void getCharPath(GfxState *state,
-                          CharCode c, Unicode *u, int ulen);
-
-private:
-
-  FTFontFile *fontFile;
-  FTFont *font;
-};
-#endif // FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
-
-#if !FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
-//------------------------------------------------------------------------
-// XOutputTTFont
-//------------------------------------------------------------------------
-
-class XOutputTTFont: public XOutputFont {
-public:
-
-  XOutputTTFont(Ref *idA, TTFontFile *fontFileA,
-               double m11OrigA, double m12OrigA,
-               double m21OrigA, double m22OrigA,
-               double m11A, double m12A,
-               double m21A, double m22A,
-               Display *displayA, XOutputDev *xOutA);
-
-  virtual ~XOutputTTFont();
-
-  // Was font created successfully?
-  virtual GBool isOk();
-
-  // Update <gc> with this font.
-  virtual void updateGC(GC gc);
-
-  // Draw character <c>/<u> at <x>,<y>.
-  virtual void drawChar(GfxState *state, Pixmap pixmap, int w, int h,
-                       GC gc, GfxRGB *rgb,
-                       double x, double y, double dx, double dy,
-                       CharCode c, Unicode *u, int uLen);
-
-private:
-
-  TTFontFile *fontFile;
-  TTFont *font;
-};
-#endif // !FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
-
-//------------------------------------------------------------------------
-// XOutputServer8BitFont
-//------------------------------------------------------------------------
-
-class XOutputServer8BitFont: public XOutputFont {
-public:
-
-  XOutputServer8BitFont(Ref *idA, GString *xlfdFmt,
-                       UnicodeMap *xUMapA, CharCodeToUnicode *fontUMap,
-                       double m11OrigA, double m12OrigA,
-                       double m21OrigA, double m22OrigA,
-                       double m11A, double m12A, double m21A, double m22A,
-                       Display *displayA, XOutputDev *xOutA);
-
-  virtual ~XOutputServer8BitFont();
-
-  // Was font created successfully?
-  virtual GBool isOk();
-
-  // Update <gc> with this font.
-  virtual void updateGC(GC gc);
-
-  // Draw character <c>/<u> at <x>,<y>.
-  virtual void drawChar(GfxState *state, Pixmap pixmap, int w, int h,
-                       GC gc, GfxRGB *rgb,
-                       double x, double y, double dx, double dy,
-                       CharCode c, Unicode *u, int uLen);
-
-private:
-
-  XFontStruct *xFont;          // the X font
-  Gushort map[256];            // forward map (char code -> X font code)
-  UnicodeMap *xUMap;
-};
-
-//------------------------------------------------------------------------
-// XOutputServer16BitFont
-//------------------------------------------------------------------------
-
-class XOutputServer16BitFont: public XOutputFont {
-public:
-
-  XOutputServer16BitFont(Ref *idA, GString *xlfdFmt,
-                        UnicodeMap *xUMapA, CharCodeToUnicode *fontUMap,
-                        double m11OrigA, double m12OrigA,
-                        double m21OrigA, double m22OrigA,
-                        double m11A, double m12A, double m21A, double m22A,
-                        Display *displayA, XOutputDev *xOutA);
-
-  virtual ~XOutputServer16BitFont();
-
-  // Was font created successfully?
-  virtual GBool isOk();
-
-  // Update <gc> with this font.
-  virtual void updateGC(GC gc);
-
-  // Draw character <c>/<u> at <x>,<y>.
-  virtual void drawChar(GfxState *state, Pixmap pixmap, int w, int h,
-                       GC gc, GfxRGB *rgb,
-                       double x, double y, double dx, double dy,
-                       CharCode c, Unicode *u, int uLen);
-
-private:
-
-  XFontStruct *xFont;          // the X font
-  UnicodeMap *xUMap;
-};
-
-//------------------------------------------------------------------------
-// XOutputFontCache
-//------------------------------------------------------------------------
-
-#if HAVE_T1LIB_H
-class XOutputT1FontFile {
-public:
-  XOutputT1FontFile(int numA, int genA, GBool substA,
-                   T1FontFile *fontFileA, GString *tmpFileNameA)
-    { num = numA; gen = genA; subst = substA;
-      fontFile = fontFileA; tmpFileName = tmpFileNameA; }
-  ~XOutputT1FontFile();
-  int num, gen;
-  GBool subst;
-  T1FontFile *fontFile;
-  GString *tmpFileName;
-};
-#endif
-
-#if FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
-class XOutputFTFontFile {
-public:
-  XOutputFTFontFile(int numA, int genA, GBool substA,
-                   FTFontFile *fontFileA, GString *tmpFileNameA)
-    { num = numA; gen = genA; subst = substA;
-      fontFile = fontFileA; tmpFileName = tmpFileNameA; }
-  ~XOutputFTFontFile();
-  int num, gen;
-  GBool subst;
-  FTFontFile *fontFile;
-  GString *tmpFileName;
-};
-#endif
-
-#if !FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
-class XOutputTTFontFile {
-public:
-  XOutputTTFontFile(int numA, int genA, GBool substA,
-                   TTFontFile *fontFileA, GString *tmpFileNameA)
-    { num = numA; gen = genA; subst = substA;
-      fontFile = fontFileA; tmpFileName = tmpFileNameA; }
-  ~XOutputTTFontFile();
-  int num, gen;
-  GBool subst;
-  TTFontFile *fontFile;
-  GString *tmpFileName;
-};
-#endif
-
-class XOutputFontCache {
-public:
-
-  // Constructor.
-  XOutputFontCache(Display *displayA, Guint depthA,
-                  XOutputDev *xOutA,
-                  FontRastControl t1libControlA,
-                  FontRastControl freetypeControlA);
-
-  // Destructor.
-  ~XOutputFontCache();
-
-  // Initialize (or re-initialize) the font cache for a new document.
-  void startDoc(int screenNum, Visual *visual,
-               Colormap colormap, GBool trueColor,
-               int rMul, int gMul, int bMul,
-               int rShift, int gShift, int bShift,
-               Gulong *colors, int numColors);
-
-  // Get a font.  This creates a new font if necessary.
-  XOutputFont *getFont(XRef *xref, GfxFont *gfxFont, double m11, double m12,
-                      double m21, double m22);
-
-private:
-
-  void delFonts();
-  void clear();
-  XOutputFont *tryGetFont(XRef *xref, DisplayFontParam *dfp, GfxFont *gfxFont,
-                         double m11Orig, double m12Orig,
-                         double m21Orig, double m22Orig,
-                         double m11, double m12, double m21, double m22,
-                         GBool subst);
-#if HAVE_T1LIB_H
-  XOutputFont *tryGetT1Font(XRef *xref, GfxFont *gfxFont,
-                           double m11, double m12, double m21, double m22);
-  XOutputFont *tryGetT1FontFromFile(XRef *xref, GString *fileName,
-                                   GBool deleteFile, GfxFont *gfxFont,
-                                   double m11Orig, double m12Orig,
-                                   double m21Orig, double m22Orig,
-                                   double m11, double m12,
-                                   double m21, double m22, GBool subst);
-#endif
-#if FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
-  XOutputFont *tryGetFTFont(XRef *xref, GfxFont *gfxFont,
-                           double m11, double m12, double m21, double m22);
-  XOutputFont *tryGetFTFontFromFile(XRef *xref, GString *fileName,
-                                   GBool deleteFile, GfxFont *gfxFont,
-                                   double m11Orig, double m12Orig,
-                                   double m21Orig, double m22Orig,
-                                   double m11, double m12,
-                                   double m21, double m22,
-                                   GBool embedded, GBool subst);
-#endif
-#if !FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
-  XOutputFont *tryGetTTFont(XRef *xref, GfxFont *gfxFont,
-                           double m11, double m12, double m21, double m22);
-  XOutputFont *tryGetTTFontFromFile(XRef *xref, GString *fileName,
-                                   GBool deleteFile, GfxFont *gfxFont,
-                                   double m11Orig, double m12Orig,
-                                   double m21Orig, double m22Orig,
-                                   double m11, double m12,
-                                   double m21, double m22, GBool subst);
-#endif
-  XOutputFont *tryGetServerFont(GString *xlfd, GString *encodingName,
-                               GfxFont *gfxFont,
-                               double m11Orig, double m12Orig,
-                               double m21Orig, double m22Orig,
-                               double m11, double m12,
-                               double m21, double m22);
-
-  Display *display;            // X display pointer
-  XOutputDev *xOut;
-  Guint depth;                 // pixmap depth
-
-  XOutputFont *
-    fonts[xOutFontCacheSize];
-  int nFonts;
-
-#if HAVE_T1LIB_H
-  FontRastControl t1libControl;        // t1lib settings
-  T1FontEngine *t1Engine;      // Type 1 font engine
-  GList *t1FontFiles;          // list of Type 1 font files
-                               //   [XOutputT1FontFile]
-#endif
-
-#if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H
-  FontRastControl              // FreeType settings
-    freetypeControl;
-#endif
-#if FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
-  FTFontEngine *ftEngine;      // FreeType font engine
-  GList *ftFontFiles;          // list of FreeType font files
-                               //   [XOutputFTFontFile]
-#endif
-#if !FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
-  TTFontEngine *ttEngine;      // TrueType font engine
-  GList *ttFontFiles;          // list of TrueType font files
-                               //   [XOutputTTFontFile]
-#endif
-};
-
-//------------------------------------------------------------------------
-// XOutputState
-//------------------------------------------------------------------------
-
-struct XOutputState {
-  GC strokeGC;
-  GC fillGC;
-  Region clipRegion;
-  XOutputState *next;
-};
-
-//------------------------------------------------------------------------
-// XOutputDev
-//------------------------------------------------------------------------
-
-class XOutputDev: public OutputDev {
-public:
-
-  // Constructor.
-  XOutputDev(Display *displayA, int screenNumA,
-            Visual *visualA, Colormap colormapA,
-            GBool reverseVideoA, unsigned long paperColorA,
-            GBool installCmap, int rgbCubeSize,
-            int forceDepth = 0);
-
-  // Destructor.
-  virtual ~XOutputDev();
-
-  //---- get info about output device
-
-  // Does this device use upside-down coordinates?
-  // (Upside-down means (0,0) is the top left corner of the page.)
-  virtual GBool upsideDown() { return gTrue; }
-
-  // Does this device use drawChar() or drawString()?
-  virtual GBool useDrawChar() { return gTrue; }
-
-  // Does this device use beginType3Char/endType3Char?  Otherwise,
-  // text in Type 3 fonts will be drawn with drawChar/drawString.
-  virtual GBool interpretType3Chars() { return gTrue; }
-
-  //----- initialization and control
-
-  // Start a page.
-  virtual void startPage(int pageNum, GfxState *state);
-
-  // End a page.
-  virtual void endPage();
-
-  //----- link borders
-  virtual void drawLink(Link *link, Catalog *catalog);
-
-  //----- save/restore graphics state
-  virtual void saveState(GfxState *state);
-  virtual void restoreState(GfxState *state);
-
-  //----- update graphics state
-  virtual void updateAll(GfxState *state);
-  virtual void updateCTM(GfxState *state, double m11, double m12,
-                        double m21, double m22, double m31, double m32);
-  virtual void updateLineDash(GfxState *state);
-  virtual void updateFlatness(GfxState *state);
-  virtual void updateLineJoin(GfxState *state);
-  virtual void updateLineCap(GfxState *state);
-  virtual void updateMiterLimit(GfxState *state);
-  virtual void updateLineWidth(GfxState *state);
-  virtual void updateFillColor(GfxState *state);
-  virtual void updateStrokeColor(GfxState *state);
-
-  //----- update text state
-  virtual void updateFont(GfxState *state);
-
-  //----- path painting
-  virtual void stroke(GfxState *state);
-  virtual void fill(GfxState *state);
-  virtual void eoFill(GfxState *state);
-
-  //----- path clipping
-  virtual void clip(GfxState *state);
-  virtual void eoClip(GfxState *state);
-
-  //----- text drawing
-  virtual void beginString(GfxState *state, GString *s);
-  virtual void endString(GfxState *state);
-  virtual void drawChar(GfxState *state, double x, double y,
-                       double dx, double dy,
-                       double originX, double originY,
-                       CharCode code, Unicode *u, int uLen);
-  virtual GBool beginType3Char(GfxState *state,
-                              CharCode code, Unicode *u, int uLen);
-  virtual void endType3Char(GfxState *state);
-  virtual void endTextObject(GfxState *state);
-
-  //----- image drawing
-  virtual void drawImageMask(GfxState *state, Object *ref, Stream *str,
-                            int width, int height, GBool invert,
-                            GBool inlineImg);
-  virtual void drawImage(GfxState *state, Object *ref, Stream *str,
-                        int width, int height, GfxImageColorMap *colorMap,
-                        int *maskColors, GBool inlineImg);
-
-  //----- Type 3 font operators
-  virtual void type3D0(GfxState *state, double wx, double wy);
-  virtual void type3D1(GfxState *state, double wx, double wy,
-                      double llx, double lly, double urx, double ury);
-
-  //----- special access
-
-  // Called to indicate that a new PDF document has been loaded.
-  void startDoc(XRef *xrefA);
-  // Find a string.  If <startAtTop> is true, starts looking at the
-  // top of the page; else if <startAtLast> is true, starts looking
-  // immediately after the last find result; else starts looking at
-  // <xMin>,<yMin>.  If <stopAtBottom> is true, stops looking at the
-  // bottom of the page; else if <stopAtLast> is true, stops looking
-  // just before the last find result; else stops looking at
-  // <xMax>,<yMax>.
-  GBool findText(Unicode *s, int len,
-                GBool startAtTop, GBool stopAtBottom,
-                GBool startAtLast, GBool stopAtLast,
-                int *xMin, int *yMin,
-                int *xMax, int *yMax);
-
-  // Get the text which is inside the specified rectangle.
-  GString *getText(int xMin, int yMin, int xMax, int yMax);
-
-  GBool isReverseVideo() { return reverseVideo; }
-
-  // Update pixmap ID after a page change.
-  void setPixmap(Pixmap pixmapA, int pixmapWA, int pixmapHA)
-    { pixmap = pixmapA; pixmapW = pixmapWA; pixmapH = pixmapHA; }
-
-  // Get the off-screen pixmap, its size, various display info.
-  Pixmap getPixmap() { return pixmap; }
-  int getPixmapWidth() { return pixmapW; }
-  int getPixmapHeight() { return pixmapH; }
-  Display *getDisplay() { return display; }
-  Guint getDepth() { return depth; }
-
-  Gulong findColor(GfxRGB *rgb);
-
-private:
-
-  XRef *xref;                  // the xref table for this PDF file
-  Display *display;            // X display pointer
-  int screenNum;               // X screen number
-  Pixmap pixmap;               // pixmap to draw into
-  int pixmapW, pixmapH;                // size of pixmap
-  Guint depth;                 // pixmap depth
-  Visual *visual;              // X visual
-  Colormap colormap;           // X colormap
-  int flatness;                        // line flatness
-  GC paperGC;                  // GC for background
-  GC strokeGC;                 // GC with stroke color
-  GC fillGC;                   // GC with fill color
-  Region clipRegion;           // clipping region
-  GBool trueColor;             // set if using a TrueColor visual
-  int rMul, gMul, bMul;                // RGB multipliers (for TrueColor)
-  int rShift, gShift, bShift;  // RGB shifts (for TrueColor)
-  Gulong                       // color cube
-    colors[maxRGBCube * maxRGBCube * maxRGBCube];
-  unsigned long paperColor;    // paper color (pixel value)
-  int numColors;               // size of color cube
-  double redMap[256];          // map pixel (from color cube) to red value
-  GBool reverseVideo;          // reverse video mode
-  XPoint                       // temporary points array
-    tmpPoints[numTmpPoints];
-  int                          // temporary arrays for fill/clip
-    tmpLengths[numTmpSubpaths];
-  BoundingRect
-    tmpRects[numTmpSubpaths];
-  GfxFont *gfxFont;            // current PDF font
-  XOutputFont *font;           // current font
-  GBool needFontUpdate;                // set when the font needs to be updated
-  XOutputFontCache *fontCache; // font cache
-  T3FontCache *                        // Type 3 font cache
-    t3FontCache[xOutT3FontCacheSize];
-  int nT3Fonts;                        // number of valid entries in t3FontCache
-  T3GlyphStack *t3GlyphStack;  // Type 3 glyph context stack
-  GfxPath *textClipPath;       // text outline clipping path
-  XOutputState *save;          // stack of saved states
-
-  TextPage *text;              // text from the current page
-
-  void updateLineAttrs(GfxState *state, GBool updateDash);
-  void doFill(GfxState *state, int rule);
-  void doClip(GfxState *state, GfxPath *path, int rule);
-  int convertPath(GfxState *state, GfxPath *path,
-                 XPoint **points, int *size,
-                 int *numPoints, int **lengths, GBool fillHack);
-  void convertSubpath(GfxState *state, GfxSubpath *subpath,
-                     XPoint **points, int *size, int *n);
-  void doCurve(XPoint **points, int *size, int *k,
-              double x0, double y0, double x1, double y1,
-              double x2, double y2, double x3, double y3);
-  void addPoint(XPoint **points, int *size, int *k, int x, int y);
-  void drawType3Glyph(T3FontCache *t3Font,
-                     T3FontCacheTag *tag, Guchar *data,
-                     double x, double y, GfxRGB *color);
-  Gulong findColor(GfxRGB *x, GfxRGB *actual);
-};
-
-#endif
diff --git a/pdf/xpdf/XPixmapOutputDev.cc b/pdf/xpdf/XPixmapOutputDev.cc
deleted file mode 100644 (file)
index d55b2d2..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-//========================================================================
-//
-// XPixmapOutputDev.cc
-//
-// Copyright 2002-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma implementation
-#endif
-
-#include "Object.h"
-#include "GfxState.h"
-#include "XPixmapOutputDev.h"
-
-//------------------------------------------------------------------------
-
-#define xoutRound(x) ((int)(x + 0.5))
-
-//------------------------------------------------------------------------
-
-XPixmapOutputDev::XPixmapOutputDev(Display *displayA, int screenNumA,
-                                  Visual *visualA, Colormap colormapA,
-                                  GBool reverseVideoA, Gulong paperColorA,
-                                  GBool installCmapA, int rgbCubeSizeA,
-                                  GBool incrementalUpdateA,
-                                  void (*redrawCbkA)(void *data),
-                                  void *redrawCbkDataA):
-  XOutputDev(displayA, screenNumA, visualA, colormapA,
-            reverseVideoA, paperColorA, installCmapA, rgbCubeSizeA)
-{
-  incrementalUpdate = incrementalUpdateA;
-  redrawCbk = redrawCbkA;
-  redrawCbkData = redrawCbkDataA;
-}
-
-XPixmapOutputDev::~XPixmapOutputDev() {
-  if (getPixmapWidth() > 0) {
-    XFreePixmap(getDisplay(), getPixmap());
-  }
-}
-
-void XPixmapOutputDev::clear() {
-  startDoc(NULL);
-  startPage(0, NULL);
-}
-
-void XPixmapOutputDev::startPage(int pageNum, GfxState *state) {
-  int oldPixmapW, oldPixmapH, newPixmapW, newPixmapH;
-
-  // resize the off-screen pixmap (if needed)
-  oldPixmapW = getPixmapWidth();
-  oldPixmapH = getPixmapHeight();
-  newPixmapW = xoutRound(state ? state->getPageWidth() : 1);
-  newPixmapH = xoutRound(state ? state->getPageHeight() : 1);
-  if (oldPixmapW == 0 ||
-      newPixmapW != oldPixmapW || newPixmapH != oldPixmapH) {
-    if (oldPixmapW > 0) {
-      XFreePixmap(getDisplay(), getPixmap());
-    }
-    setPixmap(XCreatePixmap(getDisplay(), win, newPixmapW, newPixmapH,
-                           getDepth()),
-             newPixmapW, newPixmapH);
-  }
-
-  XOutputDev::startPage(pageNum, state);
-}
-
-void XPixmapOutputDev::endPage() {
-  if (!incrementalUpdate) {
-    (*redrawCbk)(redrawCbkData);
-  }
-  XOutputDev::endPage();
-}
-
-void XPixmapOutputDev::dump() {
-  if (incrementalUpdate) {
-    (*redrawCbk)(redrawCbkData);
-  }
-  XOutputDev::dump();
-}
diff --git a/pdf/xpdf/XPixmapOutputDev.h b/pdf/xpdf/XPixmapOutputDev.h
deleted file mode 100644 (file)
index 8b83167..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-//========================================================================
-//
-// XPixmapOutputDev.h
-//
-// Copyright 2002-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#ifndef XPIXMAPOUTPUTDEV_H
-#define XPIXMAPOUTPUTDEV_H
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma interface
-#endif
-
-#include <X11/Xlib.h>
-#include "XOutputDev.h"
-
-//------------------------------------------------------------------------
-
-class XPixmapOutputDev: public XOutputDev {
-public:
-
-  XPixmapOutputDev(Display *displayA, int screenNumA,
-                  Visual *visualA, Colormap colormapA,
-                  GBool reverseVideoA, Gulong paperColorA,
-                  GBool installCmapA, int rgbCubeSizeA,
-                  GBool incrementalUpdateA,
-                  void (*redrawCbkA)(void *data),
-                  void *redrawCbkDataA);
-
-  ~XPixmapOutputDev();
-
-  //----- initialization and control
-
-  // Start a page.
-  virtual void startPage(int pageNum, GfxState *state);
-
-  // End a page.
-  virtual void endPage();
-
-  // Dump page contents to display.
-  virtual void dump();
-
-  //----- special access
-
-  // Set the window - this is used only to create a compatible pixmap.
-  void setWindow(Window winA) { win = winA; }
-
-  // Clear out the document (used when displaying an empty window).
-  void clear();
-
-private:
-
-  GBool incrementalUpdate;     // incrementally update the display?
-  void (*redrawCbk)(void *data);
-  void *redrawCbkData;
-  Window win;
-};
-
-#endif
index eca638df76177c789ce73341f268cb1afd119b3e..e0d82d23c62ef46ddff1a8c771ceeb576c436758 100644 (file)
 #define defPermFlags 0xfffc
 #endif
 
+//------------------------------------------------------------------------
+// ObjectStream
+//------------------------------------------------------------------------
+
+class ObjectStream {
+public:
+
+  // Create an object stream, using object number <objStrNum>,
+  // generation 0.
+  ObjectStream(XRef *xref, int objStrNumA);
+
+  ~ObjectStream();
+
+  // Return the object number of this object stream.
+  int getObjStrNum() { return objStrNum; }
+
+  // Get the <objIdx>th object from this stream, which should be
+  // object number <objNum>, generation 0.
+  Object *getObject(int objIdx, int objNum, Object *obj);
+
+private:
+
+  int objStrNum;               // object number of the object stream
+  int nObjects;                        // number of objects in the stream
+  Object *objs;                        // the objects (length = nObjects)
+  int *objNums;                        // the object numbers (length = nObjects)
+};
+
+ObjectStream::ObjectStream(XRef *xref, int objStrNumA) {
+  Stream *str;
+  Parser *parser;
+  int *offsets;
+  Object objStr, obj1, obj2;
+  int first, i;
+
+  objStrNum = objStrNumA;
+  nObjects = 0;
+  objs = NULL;
+  objNums = NULL;
+
+  if (!xref->fetch(objStrNum, 0, &objStr)->isStream()) {
+    goto err1;
+  }
+
+  if (!objStr.streamGetDict()->lookup("N", &obj1)->isInt()) {
+    obj1.free();
+    goto err1;
+  }
+  nObjects = obj1.getInt();
+  obj1.free();
+  if (nObjects == 0) {
+    goto err1;
+  }
+
+  if (!objStr.streamGetDict()->lookup("First", &obj1)->isInt()) {
+    obj1.free();
+    goto err1;
+  }
+  first = obj1.getInt();
+  obj1.free();
+
+  objs = new Object[nObjects];
+  objNums = (int *)gmalloc(nObjects * sizeof(int));
+  offsets = (int *)gmalloc(nObjects * sizeof(int));
+
+  // parse the header: object numbers and offsets
+  objStr.streamReset();
+  obj1.initNull();
+  str = new EmbedStream(objStr.getStream(), &obj1, gTrue, first);
+  parser = new Parser(xref, new Lexer(xref, str));
+  for (i = 0; i < nObjects; ++i) {
+    parser->getObj(&obj1);
+    parser->getObj(&obj2);
+    if (!obj1.isInt() || !obj2.isInt()) {
+      obj1.free();
+      obj2.free();
+      delete parser;
+      gfree(offsets);
+      goto err1;
+    }
+    objNums[i] = obj1.getInt();
+    offsets[i] = obj2.getInt();
+    obj1.free();
+    obj2.free();
+  }
+  while (str->getChar() != EOF) ;
+  delete parser;
+
+  // skip to the first object - this shouldn't be necessary because
+  // the First key is supposed to be equal to offsets[0], but just in
+  // case...
+  for (i = first; i < offsets[0]; ++i) {
+    objStr.getStream()->getChar();
+  }
+
+  // parse the objects
+  for (i = 0; i < nObjects; ++i) {
+    obj1.initNull();
+    if (i == nObjects - 1) {
+      str = new EmbedStream(objStr.getStream(), &obj1, gFalse, 0);
+    } else {
+      str = new EmbedStream(objStr.getStream(), &obj1, gTrue,
+                           offsets[i+1] - offsets[i]);
+    }
+    parser = new Parser(xref, new Lexer(xref, str));
+    parser->getObj(&objs[i]);
+    while (str->getChar() != EOF) ;
+    delete parser;
+  }
+
+  gfree(offsets);
+
+ err1:
+  objStr.free();
+  return;
+}
+
+ObjectStream::~ObjectStream() {
+  int i;
+
+  if (objs) {
+    for (i = 0; i < nObjects; ++i) {
+      objs[i].free();
+    }
+    delete[] objs;
+  }
+  gfree(objNums);
+}
+
+Object *ObjectStream::getObject(int objIdx, int objNum, Object *obj) {
+  if (objIdx < 0 || objIdx >= nObjects || objNum != objNums[objIdx]) {
+    return obj->initNull();
+  }
+  return objs[objIdx].copy(obj);
+}
+
 //------------------------------------------------------------------------
 // XRef
 //------------------------------------------------------------------------
 
 XRef::XRef(BaseStream *strA, GString *ownerPassword, GString *userPassword) {
   Guint pos;
-  int i;
+  Object obj;
 
   ok = gTrue;
   errCode = errNone;
@@ -60,35 +196,28 @@ XRef::XRef(BaseStream *strA, GString *ownerPassword, GString *userPassword) {
   entries = NULL;
   streamEnds = NULL;
   streamEndsLen = 0;
+  objStr = NULL;
 
   // read the trailer
   str = strA;
   start = str->getStart();
-  pos = readTrailer();
+  pos = getStartXref();
 
-  // if there was a problem with the trailer,
-  // try to reconstruct the xref table
+  // if there was a problem with the 'startxref' position, try to
+  // reconstruct the xref table
   if (pos == 0) {
     if (!(ok = constructXRef())) {
       errCode = errDamaged;
       return;
     }
 
-  // trailer is ok - read the xref table
+  // read the xref table
   } else {
-    entries = (XRefEntry *)gmalloc(size * sizeof(XRefEntry));
-    for (i = 0; i < size; ++i) {
-      entries[i].offset = 0xffffffff;
-      entries[i].used = gFalse;
-    }
     while (readXRef(&pos)) ;
 
     // if there was a problem with the xref table,
     // try to reconstruct it
     if (!ok) {
-      gfree(entries);
-      size = 0;
-      entries = NULL;
       if (!(ok = constructXRef())) {
        errCode = errDamaged;
        return;
@@ -96,6 +225,20 @@ XRef::XRef(BaseStream *strA, GString *ownerPassword, GString *userPassword) {
     }
   }
 
+  // get the root dictionary (catalog) object
+  trailerDict.dictLookupNF("Root", &obj);
+  if (obj.isRef()) {
+    rootNum = obj.getRefNum();
+    rootGen = obj.getRefGen();
+    obj.free();
+  } else {
+    obj.free();
+    if (!(ok = constructXRef())) {
+      errCode = errDamaged;
+      return;
+    }
+  }
+
   // now set the trailer dictionary's xref pointer so we can fetch
   // indirect objects from it
   trailerDict.getDict()->setXRef(this);
@@ -117,19 +260,16 @@ XRef::~XRef() {
   if (streamEnds) {
     gfree(streamEnds);
   }
+  if (objStr) {
+    delete objStr;
+  }
 }
 
-// Read startxref position, xref table size, and root.  Returns
-// first xref position.
-Guint XRef::readTrailer() {
-  Parser *parser;
-  Object obj;
+// Read the 'startxref' position.
+Guint XRef::getStartXref() {
   char buf[xrefSearchSize+1];
-  int n;
-  Guint pos, pos1;
   char *p;
-  int c;
-  int i;
+  int c, n, i;
 
   // read last xrefSearchSize bytes
   str->setPos(xrefSearchSize, -1);
@@ -148,175 +288,126 @@ Guint XRef::readTrailer() {
     }
   }
   if (i < 0) {
-    goto err1;
+    return 0;
   }
   for (p = &buf[i+9]; isspace(*p); ++p) ;
-  pos = lastXRefPos = strToUnsigned(p);
+  lastXRefPos = strToUnsigned(p);
 
-  // find trailer dict by looking after first xref table
-  // (NB: we can't just use the trailer dict at the end of the file --
-  // this won't work for linearized files.)
-  str->setPos(start + pos);
-  for (i = 0; i < 4; ++i) {
-    buf[i] = str->getChar();
-  }
-  if (strncmp(buf, "xref", 4)) {
-    goto err1;
-  }
-  pos1 = pos + 4;
-  while (1) {
-    str->setPos(start + pos1);
-    for (i = 0; i < 35; ++i) {
-      if ((c = str->getChar()) == EOF) {
-       goto err1;
-      }
-      buf[i] = c;
-    }
-    if (!strncmp(buf, "trailer", 7)) {
-      break;
-    }
-    p = buf;
-    while (isspace(*p)) ++p;
-    while ('0' <= *p && *p <= '9') ++p;
-    while (isspace(*p)) ++p;
-    n = atoi(p);
-    while ('0' <= *p && *p <= '9') ++p;
-    while (isspace(*p)) ++p;
-    if (p == buf) {
-      goto err1;
-    }
-    pos1 += (p - buf) + n * 20;
-  }
-  pos1 += 7;
+  return lastXRefPos;
+}
+
+// Read one xref table section.  Also reads the associated trailer
+// dictionary, and returns the prev pointer (if any).
+GBool XRef::readXRef(Guint *pos) {
+  Parser *parser;
+  Object obj;
+  GBool more;
 
-  // read trailer dict
+  // start up a parser, parse one token
   obj.initNull();
   parser = new Parser(NULL,
             new Lexer(NULL,
-              str->makeSubStream(start + pos1, gFalse, 0, &obj)));
-  parser->getObj(&trailerDict);
-  if (trailerDict.isDict()) {
-    trailerDict.dictLookupNF("Size", &obj);
-    if (obj.isInt()) {
-      size = obj.getInt();
-    } else {
-      goto err3;
+              str->makeSubStream(start + *pos, gFalse, 0, &obj)));
+  parser->getObj(&obj);
+
+  // parse an old-style xref table
+  if (obj.isCmd("xref")) {
+    obj.free();
+    more = readXRefTable(parser, pos);
+
+  // parse an xref stream
+  } else if (obj.isInt()) {
+    obj.free();
+    if (!parser->getObj(&obj)->isInt()) {
+      goto err1;
     }
     obj.free();
-    trailerDict.dictLookupNF("Root", &obj);
-    if (obj.isRef()) {
-      rootNum = obj.getRefNum();
-      rootGen = obj.getRefGen();
-    } else {
-      goto err3;
+    if (!parser->getObj(&obj)->isCmd("obj")) {
+      goto err1;
+    }
+    obj.free();
+    if (!parser->getObj(&obj)->isStream()) {
+      goto err1;
     }
+    more = readXRefStream(obj.getStream(), pos);
     obj.free();
+
   } else {
-    goto err2;
+    goto err1;
   }
-  delete parser;
 
-  // return first xref position
-  return pos;
+  delete parser;
+  return more;
 
- err3:
+ err1:
   obj.free();
- err2:
-  trailerDict.free();
   delete parser;
- err1:
-  size = 0;
-  return 0;
+  ok = gFalse;
+  return gFalse;
 }
 
-// Read an xref table and the prev pointer from the trailer.
-GBool XRef::readXRef(Guint *pos) {
-  Parser *parser;
-  Object obj, obj2;
-  char s[20];
+GBool XRef::readXRefTable(Parser *parser, Guint *pos) {
+  XRefEntry entry;
   GBool more;
-  int first, newSize, n, i, j;
-  int c;
-
-  // seek to xref in stream
-  str->setPos(start + *pos);
-
-  // make sure it's an xref table
-  while ((c = str->getChar()) != EOF && isspace(c)) ;
-  s[0] = (char)c;
-  s[1] = (char)str->getChar();
-  s[2] = (char)str->getChar();
-  s[3] = (char)str->getChar();
-  if (!(s[0] == 'x' && s[1] == 'r' && s[2] == 'e' && s[3] == 'f')) {
-    goto err2;
-  }
+  Object obj, obj2;
+  Guint pos2;
+  int first, n, newSize, i;
 
-  // read xref
   while (1) {
-    while ((c = str->lookChar()) != EOF && isspace(c)) {
-      str->getChar();
-    }
-    if (c == 't') {
+    parser->getObj(&obj);
+    if (obj.isCmd("trailer")) {
+      obj.free();
       break;
     }
-    for (i = 0; (c = str->getChar()) != EOF && isdigit(c) && i < 20; ++i) {
-      s[i] = (char)c;
-    }
-    if (i == 0) {
-      goto err2;
-    }
-    s[i] = '\0';
-    first = atoi(s);
-    while ((c = str->lookChar()) != EOF && isspace(c)) {
-      str->getChar();
-    }
-    for (i = 0; (c = str->getChar()) != EOF && isdigit(c) && i < 20; ++i) {
-      s[i] = (char)c;
-    }
-    if (i == 0) {
-      goto err2;
+    if (!obj.isInt()) {
+      goto err1;
     }
-    s[i] = '\0';
-    n = atoi(s);
-    while ((c = str->lookChar()) != EOF && isspace(c)) {
-      str->getChar();
+    first = obj.getInt();
+    obj.free();
+    if (!parser->getObj(&obj)->isInt()) {
+      goto err1;
     }
-    // check for buggy PDF files with an incorrect (too small) xref
-    // table size
+    n = obj.getInt();
+    obj.free();
     if (first + n > size) {
-      newSize = first + n;
+      for (newSize = size ? 2 * size : 1024;
+          first + n > newSize;
+          newSize <<= 1) ;
       entries = (XRefEntry *)grealloc(entries, newSize * sizeof(XRefEntry));
       for (i = size; i < newSize; ++i) {
        entries[i].offset = 0xffffffff;
-       entries[i].used = gFalse;
+       entries[i].type = xrefEntryFree;
       }
       size = newSize;
     }
     for (i = first; i < first + n; ++i) {
-      for (j = 0; j < 20; ++j) {
-       if ((c = str->getChar()) == EOF) {
-         goto err2;
-       }
-       s[j] = (char)c;
+      if (!parser->getObj(&obj)->isInt()) {
+       goto err1;
+      }
+      entry.offset = (Guint)obj.getInt();
+      obj.free();
+      if (!parser->getObj(&obj)->isInt()) {
+       goto err1;
+      }
+      entry.gen = obj.getInt();
+      obj.free();
+      parser->getObj(&obj);
+      if (obj.isCmd("n")) {
+       entry.type = xrefEntryUncompressed;
+      } else if (obj.isCmd("f")) {
+       entry.type = xrefEntryFree;
+      } else {
+       goto err1;
       }
+      obj.free();
       if (entries[i].offset == 0xffffffff) {
-       s[10] = '\0';
-       entries[i].offset = strToUnsigned(s);
-       s[16] = '\0';
-       entries[i].gen = atoi(&s[11]);
-       if (s[17] == 'n') {
-         entries[i].used = gTrue;
-       } else if (s[17] == 'f') {
-         entries[i].used = gFalse;
-       } else {
-         goto err2;
-       }
+       entries[i] = entry;
        // PDF files of patents from the IBM Intellectual Property
        // Network have a bug: the xref table claims to start at 1
        // instead of 0.
        if (i == 1 && first == 1 &&
            entries[1].offset == 0 && entries[1].gen == 65535 &&
-           !entries[1].used) {
+           entries[1].type == xrefEntryFree) {
          i = first = 0;
          entries[0] = entries[1];
          entries[1].offset = 0xffffffff;
@@ -325,20 +416,12 @@ GBool XRef::readXRef(Guint *pos) {
     }
   }
 
-  // read prev pointer from trailer dictionary
-  obj.initNull();
-  parser = new Parser(NULL,
-            new Lexer(NULL,
-              str->makeSubStream(str->getPos(), gFalse, 0, &obj)));
-  parser->getObj(&obj);
-  if (!obj.isCmd("trailer")) {
-    goto err1;
-  }
-  obj.free();
-  parser->getObj(&obj);
-  if (!obj.isDict()) {
+  // read the trailer dictionary
+  if (!parser->getObj(&obj)->isDict()) {
     goto err1;
   }
+
+  // get the 'Prev' pointer
   obj.getDict()->lookupNF("Prev", &obj2);
   if (obj2.isInt()) {
     *pos = (Guint)obj2.getInt();
@@ -351,23 +434,185 @@ GBool XRef::readXRef(Guint *pos) {
   } else {
     more = gFalse;
   }
-  obj.free();
   obj2.free();
 
-  delete parser;
+  // save the first trailer dictionary
+  if (trailerDict.isNone()) {
+    obj.copy(&trailerDict);
+  }
+
+  // check for an 'XRefStm' key
+  if (obj.getDict()->lookup("XRefStm", &obj2)->isInt()) {
+    pos2 = obj2.getInt();
+    readXRef(&pos2);
+    if (!ok) {
+      goto err1;
+    }
+  }
+  obj2.free();
+
+  obj.free();
   return more;
 
  err1:
   obj.free();
- err2:
   ok = gFalse;
   return gFalse;
 }
 
+GBool XRef::readXRefStream(Stream *xrefStr, Guint *pos) {
+  Dict *dict;
+  int w[3];
+  GBool more;
+  Object obj, obj2, idx;
+  int newSize, first, n, i;
+
+  dict = xrefStr->getDict();
+
+  if (!dict->lookupNF("Size", &obj)->isInt()) {
+    goto err1;
+  }
+  newSize = obj.getInt();
+  obj.free();
+  if (newSize > size) {
+    entries = (XRefEntry *)grealloc(entries, newSize * sizeof(XRefEntry));
+    for (i = size; i < newSize; ++i) {
+      entries[i].offset = 0xffffffff;
+      entries[i].type = xrefEntryFree;
+    }
+    size = newSize;
+  }
+
+  if (!dict->lookupNF("W", &obj)->isArray() ||
+      obj.arrayGetLength() < 3) {
+    goto err1;
+  }
+  for (i = 0; i < 3; ++i) {
+    if (!obj.arrayGet(i, &obj2)->isInt()) {
+      obj2.free();
+      goto err1;
+    }
+    w[i] = obj2.getInt();
+    obj2.free();
+  }
+  obj.free();
+
+  xrefStr->reset();
+  dict->lookupNF("Index", &idx);
+  if (idx.isArray()) {
+    for (i = 0; i+1 < idx.arrayGetLength(); i += 2) {
+      if (!idx.arrayGet(i, &obj)->isInt()) {
+       idx.free();
+       goto err1;
+      }
+      first = obj.getInt();
+      obj.free();
+      if (!idx.arrayGet(i+1, &obj)->isInt()) {
+       idx.free();
+       goto err1;
+      }
+      n = obj.getInt();
+      obj.free();
+      if (!readXRefStreamSection(xrefStr, w, first, n)) {
+       idx.free();
+       goto err0;
+      }
+    }
+  } else {
+    if (!readXRefStreamSection(xrefStr, w, 0, size)) {
+      idx.free();
+      goto err0;
+    }
+  }
+  idx.free();
+
+  dict->lookupNF("Prev", &obj);
+  if (obj.isInt()) {
+    *pos = (Guint)obj.getInt();
+    more = gTrue;
+  } else {
+    more = gFalse;
+  }
+  obj.free();
+  if (trailerDict.isNone()) {
+    trailerDict.initDict(dict);
+  }
+
+  return more;
+
+ err1:
+  obj.free();
+ err0:
+  ok = gFalse;
+  return gFalse;
+}
+
+GBool XRef::readXRefStreamSection(Stream *xrefStr, int *w, int first, int n) {
+  Guint offset;
+  int type, gen, c, newSize, i, j;
+
+  if (first + n > size) {
+    for (newSize = size ? 2 * size : 1024;
+        first + n > newSize;
+        newSize <<= 1) ;
+    entries = (XRefEntry *)grealloc(entries, newSize * sizeof(XRefEntry));
+    for (i = size; i < newSize; ++i) {
+      entries[i].offset = 0xffffffff;
+      entries[i].type = xrefEntryFree;
+    }
+    size = newSize;
+  }
+  for (i = first; i < first + n; ++i) {
+    if (w[0] == 0) {
+      type = 1;
+    } else {
+      for (type = 0, j = 0; j < w[0]; ++j) {
+       if ((c = xrefStr->getChar()) == EOF) {
+         return gFalse;
+       }
+       type = (type << 8) + c;
+      }
+    }
+    for (offset = 0, j = 0; j < w[1]; ++j) {
+      if ((c = xrefStr->getChar()) == EOF) {
+       return gFalse;
+      }
+      offset = (offset << 8) + c;
+    }
+    for (gen = 0, j = 0; j < w[2]; ++j) {
+      if ((c = xrefStr->getChar()) == EOF) {
+       return gFalse;
+      }
+      gen = (gen << 8) + c;
+    }
+    switch (type) {
+    case 0:
+      entries[i].offset = offset;
+      entries[i].gen = gen;
+      entries[i].type = xrefEntryFree;
+      break;
+    case 1:
+      entries[i].offset = offset;
+      entries[i].gen = gen;
+      entries[i].type = xrefEntryUncompressed;
+      break;
+    case 2:
+      entries[i].offset = offset;
+      entries[i].gen = gen;
+      entries[i].type = xrefEntryCompressed;
+      break;
+    default:
+      return gFalse;
+    }
+  }
+
+  return gTrue;
+}
+
 // Attempt to construct an xref table for a damaged file.
 GBool XRef::constructXRef() {
   Parser *parser;
-  Object obj;
+  Object newTrailerDict, obj;
   char buf[256];
   Guint pos;
   int num, gen;
@@ -377,6 +622,10 @@ GBool XRef::constructXRef() {
   int i;
   GBool gotRoot;
 
+  gfree(entries);
+  size = 0;
+  entries = NULL;
+
   error(0, "PDF file is damaged - attempting to reconstruct xref table...");
   gotRoot = gFalse;
   streamEndsLen = streamEndsSize = 0;
@@ -391,26 +640,25 @@ GBool XRef::constructXRef() {
 
     // got trailer dictionary
     if (!strncmp(p, "trailer", 7)) {
-      gotRoot = gFalse;
       obj.initNull();
       parser = new Parser(NULL,
                 new Lexer(NULL,
                   str->makeSubStream(start + pos + 7, gFalse, 0, &obj)));
-      if (!trailerDict.isNone()) {
-       trailerDict.free();
-      }
-      parser->getObj(&trailerDict);
-      if (trailerDict.isDict()) {
-       trailerDict.dictLookupNF("Root", &obj);
+      parser->getObj(&newTrailerDict);
+      if (newTrailerDict.isDict()) {
+       newTrailerDict.dictLookupNF("Root", &obj);
        if (obj.isRef()) {
          rootNum = obj.getRefNum();
          rootGen = obj.getRefGen();
+         if (!trailerDict.isNone()) {
+           trailerDict.free();
+         }
+         newTrailerDict.copy(&trailerDict);
          gotRoot = gTrue;
        }
        obj.free();
-      } else {
-       trailerDict.free();
       }
+      newTrailerDict.free();
       delete parser;
 
     // look for object
@@ -439,14 +687,15 @@ GBool XRef::constructXRef() {
                            grealloc(entries, newSize * sizeof(XRefEntry));
                for (i = size; i < newSize; ++i) {
                  entries[i].offset = 0xffffffff;
-                 entries[i].used = gFalse;
+                 entries[i].type = xrefEntryFree;
                }
                size = newSize;
              }
-             if (!entries[num].used || gen >= entries[num].gen) {
+             if (entries[num].type == xrefEntryFree ||
+                 gen >= entries[num].gen) {
                entries[num].offset = pos - start;
                entries[num].gen = gen;
-               entries[num].used = gTrue;
+               entries[num].type = xrefEntryUncompressed;
              }
            }
          }
@@ -610,12 +859,16 @@ Object *XRef::fetch(int num, int gen, Object *obj) {
 
   // check for bogus ref - this can happen in corrupted PDF files
   if (num < 0 || num >= size) {
-    obj->initNull();
-    return obj;
+    goto err;
   }
 
   e = &entries[num];
-  if (e->gen == gen && e->offset != 0xffffffff) {
+  switch (e->type) {
+
+  case xrefEntryUncompressed:
+    if (e->gen != gen) {
+      goto err;
+    }
     obj1.initNull();
     parser = new Parser(this,
               new Lexer(this,
@@ -623,26 +876,44 @@ Object *XRef::fetch(int num, int gen, Object *obj) {
     parser->getObj(&obj1);
     parser->getObj(&obj2);
     parser->getObj(&obj3);
-    if (obj1.isInt() && obj1.getInt() == num &&
-       obj2.isInt() && obj2.getInt() == gen &&
-       obj3.isCmd("obj")) {
+    if (!obj1.isInt() || obj1.getInt() != num ||
+       !obj2.isInt() || obj2.getInt() != gen ||
+       !obj3.isCmd("obj")) {
+      goto err;
+    }
 #ifndef NO_DECRYPTION
-      parser->getObj(obj, encrypted ? fileKey : (Guchar *)NULL, keyLength,
-                    num, gen);
+    parser->getObj(obj, encrypted ? fileKey : (Guchar *)NULL, keyLength,
+                  num, gen);
 #else
-      parser->getObj(obj);
+    parser->getObj(obj);
 #endif
-    } else {
-      obj->initNull();
-    }
     obj1.free();
     obj2.free();
     obj3.free();
     delete parser;
-  } else {
-    obj->initNull();
+    break;
+
+  case xrefEntryCompressed:
+    if (gen != 0) {
+      goto err;
+    }
+    if (!objStr || objStr->getObjStrNum() != (int)e->offset) {
+      if (objStr) {
+       delete objStr;
+      }
+      objStr = new ObjectStream(this, e->offset);
+    }
+    objStr->getObject(e->gen, num, obj);
+    break;
+
+  default:
+    goto err;
   }
+
   return obj;
+
+ err:
+  return obj->initNull();
 }
 
 Object *XRef::getDocInfo(Object *obj) {
index 3f5a598e9bc058d57d888adb161747793ff879e7..bec487a114756674f828afd31ff071b2b7f0fc16 100644 (file)
 
 class Dict;
 class Stream;
+class Parser;
+class ObjectStream;
 
 //------------------------------------------------------------------------
 // XRef
 //------------------------------------------------------------------------
 
+enum XRefEntryType {
+  xrefEntryFree,
+  xrefEntryUncompressed,
+  xrefEntryCompressed
+};
+
 struct XRefEntry {
   Guint offset;
   int gen;
-  GBool used;
+  XRefEntryType type;
 };
 
 class XRef {
@@ -103,6 +111,7 @@ private:
   Guint *streamEnds;           // 'endstream' positions - only used in
                                //   damaged files
   int streamEndsLen;           // number of valid entries in streamEnds
+  ObjectStream *objStr;                // cached object stream
 #ifndef NO_DECRYPTION
   GBool encrypted;             // true if file is encrypted
   int encVersion;              // encryption algorithm
@@ -113,8 +122,11 @@ private:
   GBool ownerPasswordOk;       // true if owner password is correct
 #endif
 
-  Guint readTrailer();
+  Guint getStartXref();
   GBool readXRef(Guint *pos);
+  GBool readXRefTable(Parser *parser, Guint *pos);
+  GBool readXRefStreamSection(Stream *xrefStr, int *w, int first, int n);
+  GBool readXRefStream(Stream *xrefStr, Guint *pos);
   GBool constructXRef();
   GBool checkEncrypted(GString *ownerPassword, GString *userPassword);
   Guint strToUnsigned(char *s);
index 2fcd1a8543e52b397df7f68fc72df55ccdf32c4f..2f17995cea97bdd8bb0db906d8837e944a238a51 100644 (file)
@@ -197,8 +197,9 @@ static void scanFonts(Dict *resDict, PDFDoc *doc) {
   }
   if (gfxFontDict) {
     for (i = 0; i < gfxFontDict->getNumFonts(); ++i) {
-      font = gfxFontDict->getFont(i);
-      scanFont(font, doc);
+      if ((font = gfxFontDict->getFont(i))) {
+       scanFont(font, doc);
+      }
     }
     delete gfxFontDict;
   }
@@ -225,9 +226,9 @@ static void scanFonts(Dict *resDict, PDFDoc *doc) {
 
 static void scanFont(GfxFont *font, PDFDoc *doc) {
   Ref fontRef, embRef;
-  Object fontObj, nameObj, toUnicodeObj;
+  Object fontObj, toUnicodeObj;
   GString *name;
-  GBool subset, hasToUnicode;
+  GBool emb, subset, hasToUnicode;
   int i;
 
   fontRef = *font->getID();
@@ -242,6 +243,13 @@ static void scanFont(GfxFont *font, PDFDoc *doc) {
   // font name
   name = font->getOrigName();
 
+  // check for an embedded font
+  if (font->getType() == fontType3) {
+    emb = gTrue;
+  } else {
+    emb = font->getEmbeddedFontID(&embRef);
+  }
+
   // look for a ToUnicode map
   hasToUnicode = gFalse;
   if (doc->getXRef()->fetch(fontRef.num, fontRef.gen, &fontObj)->isDict()) {
@@ -266,7 +274,7 @@ static void scanFont(GfxFont *font, PDFDoc *doc) {
   printf("%-36s %-12s %-3s %-3s %-3s",
         name ? name->getCString() : "[none]",
         fontTypeNames[font->getType()],
-        font->getEmbeddedFontID(&embRef) ? "yes" : "no",
+        emb ? "yes" : "no",
         subset ? "yes" : "no",
         hasToUnicode ? "yes" : "no");
   if (fontRef.gen >= 100000) {
index a661fb5f990560a94b371c10a391e8f27c822be6..20e1add911f8908bfe8373105992ee66e64cb185 100644 (file)
@@ -134,7 +134,7 @@ int main(int argc, char *argv[]) {
   // write image files
   imgOut = new ImageOutputDev(imgRoot, dumpJPEG);
   if (imgOut->isOk()) {
-    doc->displayPages(imgOut, firstPage, lastPage, 72, 72, 0, gFalse);
+    doc->displayPages(imgOut, firstPage, lastPage, 72, 72, 0, gTrue, gFalse);
   }
   delete imgOut;
 
index e29e673dd1eb58a3db14fc679977725b8ae0d8b4..4a50fee2afe6f928b96bce2309847c5ee315f577 100644 (file)
 static void printInfoString(Dict *infoDict, char *key, char *text,
                            UnicodeMap *uMap);
 static void printInfoDate(Dict *infoDict, char *key, char *text);
+static void printBox(char *text, PDFRectangle *box);
 
 static int firstPage = 1;
 static int lastPage = 0;
+static GBool printBoxes = gFalse;
 static GBool printMetadata = gFalse;
 static char textEncName[128] = "";
 static char ownerPassword[33] = "\001";
@@ -49,6 +51,8 @@ static ArgDesc argDesc[] = {
    "first page to convert"},
   {"-l",      argInt,      &lastPage,         0,
    "last page to convert"},
+  {"-box",    argFlag,     &printBoxes,       0,
+   "print the page bounding boxes"},
   {"-meta",   argFlag,     &printMetadata,    0,
    "print the document metadata (XML)"},
   {"-enc",    argString,   textEncName,    sizeof(textEncName),
@@ -77,7 +81,9 @@ int main(int argc, char *argv[]) {
   GString *fileName;
   GString *ownerPW, *userPW;
   UnicodeMap *uMap;
+  Page *page;
   Object info;
+  char buf[256];
   double w, h, wISO, hISO;
   FILE *f;
   GString *metadata;
@@ -211,6 +217,32 @@ int main(int argc, char *argv[]) {
     printf("\n");
   } 
 
+  // print the boxes
+  if (printBoxes) {
+    if (multiPage) {
+      for (pg = firstPage; pg <= lastPage; ++pg) {
+       page = doc->getCatalog()->getPage(pg);
+       sprintf(buf, "Page %4d MediaBox: ", pg);
+       printBox(buf, page->getMediaBox());
+       sprintf(buf, "Page %4d CropBox:  ", pg);
+       printBox(buf, page->getCropBox());
+       sprintf(buf, "Page %4d BleedBox: ", pg);
+       printBox(buf, page->getBleedBox());
+       sprintf(buf, "Page %4d TrimBox:  ", pg);
+       printBox(buf, page->getTrimBox());
+       sprintf(buf, "Page %4d ArtBox:   ", pg);
+       printBox(buf, page->getArtBox());
+      }
+    } else {
+      page = doc->getCatalog()->getPage(firstPage);
+      printBox("MediaBox:       ", page->getMediaBox());
+      printBox("CropBox:        ", page->getCropBox());
+      printBox("BleedBox:       ", page->getBleedBox());
+      printBox("TrimBox:        ", page->getTrimBox());
+      printBox("ArtBox:         ", page->getArtBox());
+    }
+  }
+
   // print file size
 #ifdef VMS
   f = fopen(fileName->getCString(), "rb", "ctx=stm");
@@ -337,3 +369,8 @@ static void printInfoDate(Dict *infoDict, char *key, char *text) {
   }
   obj.free();
 }
+
+static void printBox(char *text, PDFRectangle *box) {
+  printf("%s%8.2f %8.2f %8.2f %8.2f\n",
+        text, box->x1, box->y1, box->x2, box->y2);
+}
diff --git a/pdf/xpdf/pdftopbm.cc b/pdf/xpdf/pdftopbm.cc
deleted file mode 100644 (file)
index a0d0af5..0000000
+++ /dev/null
@@ -1,147 +0,0 @@
-//========================================================================
-//
-// pdftopbm.cc
-//
-// Copyright 1998-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#include <aconf.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <string.h>
-#include "parseargs.h"
-#include "GString.h"
-#include "gmem.h"
-#include "GlobalParams.h"
-#include "Object.h"
-#include "Stream.h"
-#include "Array.h"
-#include "Dict.h"
-#include "XRef.h"
-#include "Catalog.h"
-#include "Page.h"
-#include "PDFDoc.h"
-#include "PBMOutputDev.h"
-#include "Error.h"
-#include "config.h"
-
-static int firstPage = 1;
-static int lastPage = 0;
-static int resolution = 150;
-static char ownerPassword[33] = "\001";
-static char userPassword[33] = "\001";
-static GBool quiet = gFalse;
-static char cfgFileName[256] = "";
-static GBool printVersion = gFalse;
-static GBool printHelp = gFalse;
-
-static ArgDesc argDesc[] = {
-  {"-f",      argInt,      &firstPage,     0,
-   "first page to print"},
-  {"-l",      argInt,      &lastPage,      0,
-   "last page to print"},
-  {"-r",      argInt,      &resolution,    0,
-   "resolution, in DPI (default is 150)"},
-  {"-opw",    argString,   ownerPassword,  sizeof(ownerPassword),
-   "owner password (for encrypted files)"},
-  {"-upw",    argString,   userPassword,   sizeof(userPassword),
-   "user password (for encrypted files)"},
-  {"-q",      argFlag,     &quiet,         0,
-   "don't print any messages or errors"},
-  {"-cfg",        argString,      cfgFileName,    sizeof(cfgFileName),
-   "configuration file to use in place of .xpdfrc"},
-  {"-v",      argFlag,     &printVersion,  0,
-   "print copyright and version info"},
-  {"-h",      argFlag,     &printHelp,     0,
-   "print usage information"},
-  {"-help",   argFlag,     &printHelp,     0,
-   "print usage information"},
-  {"--help",  argFlag,     &printHelp,     0,
-   "print usage information"},
-  {"-?",      argFlag,     &printHelp,     0,
-   "print usage information"},
-  {NULL}
-};
-
-int main(int argc, char *argv[]) {
-  PDFDoc *doc;
-  GString *fileName;
-  char *pbmRoot;
-  GString *ownerPW, *userPW;
-  PBMOutputDev *pbmOut;
-  GBool ok;
-  int exitCode;
-
-  exitCode = 99;
-
-  // parse args
-  ok = parseArgs(argDesc, &argc, argv);
-  if (!ok || argc != 3 || printVersion || printHelp) {
-    fprintf(stderr, "pdftopbm version %s\n", xpdfVersion);
-    fprintf(stderr, "%s\n", xpdfCopyright);
-    if (!printVersion) {
-      printUsage("pdftopbm", "<PDF-file> <PBM-root>", argDesc);
-    }
-    goto err0;
-  }
-  fileName = new GString(argv[1]);
-  pbmRoot = argv[2];
-
-  // read config file
-  globalParams = new GlobalParams(cfgFileName);
-  if (quiet) {
-    globalParams->setErrQuiet(quiet);
-  }
-
-  // open PDF file
-  if (ownerPassword[0] != '\001') {
-    ownerPW = new GString(ownerPassword);
-  } else {
-    ownerPW = NULL;
-  }
-  if (userPassword[0] != '\001') {
-    userPW = new GString(userPassword);
-  } else {
-    userPW = NULL;
-  }
-  doc = new PDFDoc(fileName, ownerPW, userPW);
-  if (userPW) {
-    delete userPW;
-  }
-  if (ownerPW) {
-    delete ownerPW;
-  }
-  if (!doc->isOk()) {
-    exitCode = 1;
-    goto err1;
-  }
-
-  // get page range
-  if (firstPage < 1)
-    firstPage = 1;
-  if (lastPage < 1 || lastPage > doc->getNumPages())
-    lastPage = doc->getNumPages();
-
-  // write PBM files
-  pbmOut = PBMOutputDev::makePBMOutputDev(NULL, pbmRoot);
-  pbmOut->startDoc(doc->getXRef());
-  doc->displayPages(pbmOut, firstPage, lastPage,
-                   resolution, resolution, 0, gFalse);
-  PBMOutputDev::killPBMOutputDev(pbmOut);
-
-  exitCode = 0;
-
-  // clean up
- err1:
-  delete doc;
-  delete globalParams;
- err0:
-
-  // check for memory leaks
-  Object::memCheck(stderr);
-  gMemReport(stderr);
-
-  return exitCode;
-}
index 247e45506c08b13bd612e8b2c27f15777849a758..30420060997f93797e64500ce5cab22b79c81df7 100644 (file)
@@ -47,6 +47,10 @@ static GBool noEmbedCIDTTFonts = gFalse;
 static char paperSize[15] = "";
 static int paperWidth = 0;
 static int paperHeight = 0;
+static GBool noCrop = gFalse;
+static GBool expand = gFalse;
+static GBool noShrink = gFalse;
+static GBool noCenter = gFalse;
 static GBool duplex = gFalse;
 static char ownerPassword[33] = "\001";
 static char userPassword[33] = "\001";
@@ -56,63 +60,71 @@ static GBool printVersion = gFalse;
 static GBool printHelp = gFalse;
 
 static ArgDesc argDesc[] = {
-  {"-f",      argInt,      &firstPage,      0,
+  {"-f",          argInt,      &firstPage,      0,
    "first page to print"},
-  {"-l",      argInt,      &lastPage,       0,
+  {"-l",          argInt,      &lastPage,       0,
    "last page to print"},
-  {"-level1", argFlag,     &level1,         0,
+  {"-level1",     argFlag,     &level1,         0,
    "generate Level 1 PostScript"},
-  {"-level1sep", argFlag,  &level1Sep,      0,
+  {"-level1sep",  argFlag,     &level1Sep,      0,
    "generate Level 1 separable PostScript"},
-  {"-level2", argFlag,     &level2,         0,
+  {"-level2",     argFlag,     &level2,         0,
    "generate Level 2 PostScript"},
-  {"-level2sep", argFlag,  &level2Sep,      0,
+  {"-level2sep",  argFlag,     &level2Sep,      0,
    "generate Level 2 separable PostScript"},
-  {"-level3", argFlag,     &level3,         0,
+  {"-level3",     argFlag,     &level3,         0,
    "generate Level 3 PostScript"},
-  {"-level3sep", argFlag,  &level3Sep,      0,
+  {"-level3sep",  argFlag,     &level3Sep,      0,
    "generate Level 3 separable PostScript"},
-  {"-eps",    argFlag,     &doEPS,          0,
+  {"-eps",        argFlag,     &doEPS,          0,
    "generate Encapsulated PostScript (EPS)"},
-  {"-form",   argFlag,     &doForm,         0,
+  {"-form",       argFlag,     &doForm,         0,
    "generate a PostScript form"},
 #if OPI_SUPPORT
-  {"-opi",    argFlag,     &doOPI,          0,
+  {"-opi",        argFlag,     &doOPI,          0,
    "generate OPI comments"},
 #endif
-  {"-noembt1", argFlag,     &noEmbedT1Fonts, 0,
+  {"-noembt1",    argFlag,     &noEmbedT1Fonts, 0,
    "don't embed Type 1 fonts"},
-  {"-noembtt", argFlag,    &noEmbedTTFonts, 0,
+  {"-noembtt",    argFlag,     &noEmbedTTFonts, 0,
    "don't embed TrueType fonts"},
-  {"-noembcidps", argFlag, &noEmbedCIDPSFonts, 0,
+  {"-noembcidps", argFlag,     &noEmbedCIDPSFonts, 0,
    "don't embed CID PostScript fonts"},
-  {"-noembcidtt", argFlag, &noEmbedCIDTTFonts, 0,
+  {"-noembcidtt", argFlag, &noEmbedCIDTTFonts,  0,
    "don't embed CID TrueType fonts"},
-  {"-paper",  argString,   paperSize,       sizeof(paperSize),
+  {"-paper",      argString,   paperSize,       sizeof(paperSize),
    "paper size (letter, legal, A4, A3, match)"},
-  {"-paperw", argInt,      &paperWidth,     0,
+  {"-paperw",     argInt,      &paperWidth,     0,
    "paper width, in points"},
-  {"-paperh", argInt,      &paperHeight,    0,
+  {"-paperh",     argInt,      &paperHeight,    0,
    "paper height, in points"},
-  {"-duplex", argFlag,     &duplex,         0,
+  {"-nocrop",     argFlag,     &noCrop,         0,
+   "don't crop pages to CropBox"},
+  {"-expand",     argFlag,     &expand,         0,
+   "expand pages smaller than the paper size"},
+  {"-noshrink",   argFlag,     &noShrink,       0,
+   "don't shrink pages larger than the paper size"},
+  {"-nocenter",   argFlag,     &noCenter,       0,
+   "don't center pages smaller than the paper size"},
+  {"-duplex",     argFlag,     &duplex,         0,
    "enable duplex printing"},
-  {"-opw",    argString,   ownerPassword,   sizeof(ownerPassword),
+  {"-opw",        argString,   ownerPassword,   sizeof(ownerPassword),
    "owner password (for encrypted files)"},
-  {"-upw",    argString,   userPassword,    sizeof(userPassword),
+  {"-upw",        argString,   userPassword,    sizeof(userPassword),
    "user password (for encrypted files)"},
-  {"-q",      argFlag,     &quiet,          0,
+  {"-q",          argFlag,     &quiet,          0,
    "don't print any messages or errors"},
   {"-cfg",        argString,      cfgFileName,    sizeof(cfgFileName),
    "configuration file to use in place of .xpdfrc"},
-  {"-v",      argFlag,     &printVersion,   0,
+  {"-v",          argFlag,     &printVersion,   0,
    "print copyright and version info"},
-  {"-h",      argFlag,     &printHelp,      0,
+  {"-h",          argFlag,     &printHelp,      0,
    "print usage information"},
-  {"-help",   argFlag,     &printHelp,      0,
+  {"-help",       argFlag,     &printHelp,      0,
    "print usage information"},
-  {"--help",  argFlag,     &printHelp,      0,
+  {"--help",      argFlag,     &printHelp,      0,
    "print usage information"},
-  {"-?",      argFlag,     &printHelp,      0,
+  {"-?",          argFlag,     &printHelp,      0,
    "print usage information"},
   {NULL}
 };
@@ -192,6 +204,18 @@ int main(int argc, char *argv[]) {
       globalParams->setPSPaperHeight(paperHeight);
     }
   }
+  if (noCrop) {
+    globalParams->setPSCrop(gFalse);
+  }
+  if (expand) {
+    globalParams->setPSExpandSmaller(gTrue);
+  }
+  if (noShrink) {
+    globalParams->setPSShrinkLarger(gFalse);
+  }
+  if (noCenter) {
+    globalParams->setPSCenter(gFalse);
+  }
   if (duplex) {
     globalParams->setPSDuplex(duplex);
   }
@@ -281,7 +305,8 @@ int main(int argc, char *argv[]) {
   psOut = new PSOutputDev(psFileName->getCString(), doc->getXRef(),
                          doc->getCatalog(), firstPage, lastPage, mode);
   if (psOut->isOk()) {
-    doc->displayPages(psOut, firstPage, lastPage, 72, 72, 0, gFalse);
+    doc->displayPages(psOut, firstPage, lastPage, 72, 72,
+                     0, globalParams->getPSCrop(), gFalse);
   } else {
     delete psOut;
     exitCode = 2;
index c6ad9c03383d89c168acba91203aed89cf460bf9..2de03e360c28c66f03c0d96db29ee9ae3475a96f 100644 (file)
@@ -234,7 +234,7 @@ int main(int argc, char *argv[]) {
   textOut = new TextOutputDev(textFileName->getCString(),
                              physLayout, rawOrder, htmlMeta);
   if (textOut->isOk()) {
-    doc->displayPages(textOut, firstPage, lastPage, 72, 72, 0, gFalse);
+    doc->displayPages(textOut, firstPage, lastPage, 72, 72, 0, gTrue, gFalse);
   } else {
     delete textOut;
     exitCode = 2;
index 4a59bdadfe0d15f00c020c1d8c05d9edb339a9ca..f4fb74aff888fd75e1e54a2d56269d86b532c470 100644 (file)
@@ -18,9 +18,9 @@ $ COMMON_OBJS = "Annot.obj,Array.obj,BuiltinFont.obj," + -
                 "CMap.obj,Decrypt.obj,Dict.obj,Error.obj," + -
                 "FontEncodingTables.obj,FontFile.obj," + -
                 "Function.obj,Gfx.obj,GfxFont.obj,GfxState.obj,"+ - 
-                "GlobalParams.obj,JBIG2Stream.obj,Lexer.obj," + -
-                "Link.obj,NameToCharCode.obj,Object.obj,Outline.obj,"+ -
-                "OutputDev.obj,Page.obj,Parser.obj,PDFdoc.obj," + -
+                "GlobalParams.obj,JArithmeticDecoder.obj,JBIG2Stream.obj,"+ -
+                "Lexer.obj,Link.obj,NameToCharCode.obj,Object.obj,"+ -
+                "Outline.obj,OutputDev.obj,Page.obj,Parser.obj,PDFdoc.obj," + -
                 "PDFDocEncoding.obj,PSTokenizer.obj,Stream.obj," + -
                 "UnicodeMap.obj,UnicodeTypeTable.obj,XRef.obj"
 $ COMMON_LIBS = "[]common.olb/lib,[-.goo]libgoo.olb/lib"
index bda355e05b589427b9a38f24974424643401746f..0824e4cdd43b348b4991e252cc04442665798bb8 100644 (file)
@@ -21,8 +21,9 @@
 // command line options
 //------------------------------------------------------------------------
 
-static char t1libControlStr[16] = "";
-static char freetypeControlStr[16] = "";
+static char enableT1libStr[16] = "";
+static char enableFreeTypeStr[16] = "";
+static char antialiasStr[16] = "";
 static char psFileArg[256];
 static char paperSize[15] = "";
 static int paperWidth = 0;
@@ -61,13 +62,15 @@ static ArgDesc argDesc[] = {
   {"-z",          argStringDummy, NULL,           0,
    "initial zoom level (percent, 'page', 'width')"},
 #if HAVE_T1LIB_H
-  {"-t1lib",      argString,      t1libControlStr, sizeof(t1libControlStr),
-   "t1lib font rasterizer control: none, plain, low, high"},
+  {"-t1lib",      argString,      enableT1libStr, sizeof(enableT1libStr),
+   "enable t1lib font rasterizer: yes, no"},
 #endif
 #if HAVE_FREETYPE_FREETYPE_H | HAVE_FREETYPE_H
-  {"-freetype",   argString,      freetypeControlStr, sizeof(freetypeControlStr),
-   "FreeType font rasterizer control: none, plain, low, high"},
+  {"-freetype",   argString,      enableFreeTypeStr, sizeof(enableFreeTypeStr),
+   "enable FreeType font rasterizer: yes, no"},
 #endif
+  {"-aa",         argString,      antialiasStr,   sizeof(antialiasStr),
+   "enable font anti-aliasing: yes, no"},
   {"-ps",         argString,      psFileArg,      sizeof(psFileArg),
    "default PostScript file name or command"},
   {"-paper",      argString,      paperSize,      sizeof(paperSize),
@@ -131,9 +134,19 @@ int main(int argc, char *argv[]) {
 
   // parse args
   ok = parseArgs(argDesc, &argc, argv);
+  if (!ok || printVersion || printHelp) {
+    fprintf(stderr, "xpdf version %s\n", xpdfVersion);
+    fprintf(stderr, "%s\n", xpdfCopyright);
+    if (!printVersion) {
+      printUsage("xpdf", "[<PDF-file> [<page> | +<dest>]]", argDesc);
+    }
+    exitCode = 99;
+    goto done0;
+  }
 
   // read config file
   globalParams = new GlobalParams(cfgFileName);
+  globalParams->setupBaseFonts(NULL);
   if (psFileArg[0]) {
     globalParams->setPSFile(psFileArg);
   }
@@ -160,16 +173,21 @@ int main(int argc, char *argv[]) {
       fprintf(stderr, "Bad '-eol' value on command line\n");
     }
   }
-  if (t1libControlStr[0]) {
-    if (!globalParams->setT1libControl(t1libControlStr)) {
+  if (enableT1libStr[0]) {
+    if (!globalParams->setEnableT1lib(enableT1libStr)) {
       fprintf(stderr, "Bad '-t1lib' value on command line\n");
     }
   }
-  if (freetypeControlStr[0]) {
-    if (!globalParams->setFreeTypeControl(freetypeControlStr)) {
+  if (enableFreeTypeStr[0]) {
+    if (!globalParams->setEnableFreeType(enableFreeTypeStr)) {
       fprintf(stderr, "Bad '-freetype' value on command line\n");
     }
   }
+  if (antialiasStr[0]) {
+    if (!globalParams->setAntialias(antialiasStr)) {
+      fprintf(stderr, "Bad '-aa' value on command line\n");
+    }
+  }
   if (printCommands) {
     globalParams->setPrintCommands(printCommands);
   }
@@ -290,6 +308,7 @@ int main(int argc, char *argv[]) {
   delete globalParams;
 
   // check for memory leaks
+ done0:
   Object::memCheck(stderr);
   gMemReport(stderr);
 
index ef08a7fe493726a9ec63ce25cbbde69e7bfca893..bf6baf4bf985ad3b9482d2a5fdee557dd6a129fe 100644 (file)
@@ -2,7 +2,7 @@
 //
 // config.h
 //
-// Copyright 1996-2003 Glyph & Cog, LLC
+// Copyright 1996-2004 Glyph & Cog, LLC
 //
 //========================================================================
 
 //------------------------------------------------------------------------
 
 // xpdf version
-#define xpdfVersion         "2.03"
-#define xpdfVersionNum      2.03
-#define xpdfMajorVersion    2
-#define xpdfMinorVersion    3
-#define xpdfMajorVersionStr "2"
-#define xpdfMinorVersionStr "3"
+#define xpdfVersion         "3.00"
+#define xpdfVersionNum      3.00
+#define xpdfMajorVersion    3
+#define xpdfMinorVersion    0
+#define xpdfMajorVersionStr "3"
+#define xpdfMinorVersionStr "0"
 
 // supported PDF version
-#define supportedPDFVersionStr "1.4"
-#define supportedPDFVersionNum 1.4
+#define supportedPDFVersionStr "1.5"
+#define supportedPDFVersionNum 1.5
 
 // copyright notice
-#define xpdfCopyright "Copyright 1996-2003 Glyph & Cog, LLC"
+#define xpdfCopyright "Copyright 1996-2004 Glyph & Cog, LLC"
 
 // Windows resource file stuff
-#define winxpdfVersion "WinXpdf 2.03"
-#define xpdfCopyrightAmp "Copyright 1996-2003 Glyph && Cog, LLC"
+#define winxpdfVersion "WinXpdf 3.00"
+#define xpdfCopyrightAmp "Copyright 1996-2004 Glyph && Cog, LLC"
 
 //------------------------------------------------------------------------
 // paper size