applied diff between xpdf-3.00-orig and xpdf-3.00-swftools
authorkramm <kramm>
Sat, 3 Dec 2005 14:47:24 +0000 (14:47 +0000)
committerkramm <kramm>
Sat, 3 Dec 2005 14:47:24 +0000 (14:47 +0000)
pdf2swf/xpdf/FoFiType1C.cc
pdf2swf/xpdf/Gfx.cc
pdf2swf/xpdf/GfxFont.h
pdf2swf/xpdf/GlobalParams.cc
pdf2swf/xpdf/GlobalParams.h
pdf2swf/xpdf/OutputDev.h
pdf2swf/xpdf/Page.cc
pdf2swf/xpdf/Stream.cc
pdf2swf/xpdf/config.h
pdf2swf/xpdf/gfile.h

index 499414b..a173e7c 100644 (file)
@@ -231,8 +231,11 @@ void FoFiType1C::convertToType1(char **newEncoding, GBool ascii,
     (*outputFunc)(outputStream,
                  "0 1 255 {1 index exch /.notdef put} for\n", 40);
     enc = newEncoding ? newEncoding : encoding;
+    if(!enc) {
+       fprintf(stderr, "convertToType1: Warning: No Encoding\n");
+    }
     for (i = 0; i < 256; ++i) {
-      if (enc[i]) {
+      if (enc && enc[i]) {
        sprintf(buf, "dup %d /%s put\n", i, enc[i]);
        (*outputFunc)(outputStream, buf, strlen(buf));
       }
index a13c615..49e9407 100644 (file)
@@ -439,7 +439,7 @@ Gfx::Gfx(XRef *xrefA, OutputDev *outA, int pageNum, Dict *resDict,
   fontChanged = gFalse;
   clip = clipNone;
   ignoreUndef = 0;
-  out->startPage(pageNum, state);
+  out->startPage(pageNum, state, cropBox->x1,cropBox->y1,cropBox->x2,cropBox->y2);
   out->setDefaultCTM(state->getCTM());
   out->updateAll(state);
   for (i = 0; i < 6; ++i) {
@@ -450,7 +450,7 @@ Gfx::Gfx(XRef *xrefA, OutputDev *outA, int pageNum, Dict *resDict,
   abortCheckCbkData = abortCheckCbkDataA;
 
   // set crop box
-  if (cropBox) {
+  /*if (cropBox) {
     state->moveTo(cropBox->x1, cropBox->y1);
     state->lineTo(cropBox->x2, cropBox->y1);
     state->lineTo(cropBox->x2, cropBox->y2);
@@ -459,7 +459,7 @@ Gfx::Gfx(XRef *xrefA, OutputDev *outA, int pageNum, Dict *resDict,
     state->clip();
     out->clip(state);
     state->clearPath();
-  }
+  }*/
 }
 
 Gfx::Gfx(XRef *xrefA, OutputDev *outA, Dict *resDict,
index 62dfd08..df1e00c 100644 (file)
@@ -207,7 +207,7 @@ public:
   CharCodeToUnicode *getToUnicode();
 
   // Return the character name associated with <code>.
-  char *getCharName(int code) { return enc[code]; }
+  char *getCharName(int code) { return code>=256?0:enc[code]; }
 
   // Returns true if the PDF font specified an encoding.
   GBool getHasEncoding() { return hasEncoding; }
index ee05db1..882083a 100644 (file)
 #include <string.h>
 #include <stdio.h>
 #include <ctype.h>
+#ifdef ENABLE_PLUGINS
+#  ifndef WIN32
+#    include <dlfcn.h>
+#  endif
+#endif
+#ifdef WIN32
+#  include <shlobj.h>
+#endif
 #if HAVE_PAPER_H
 #include <paper.h>
 #endif
@@ -30,6 +38,9 @@
 #include "CMap.h"
 #include "BuiltinFontTables.h"
 #include "FontEncodingTables.h"
+#ifdef ENABLE_PLUGINS
+#  include "XpdfPluginAPI.h"
+#endif
 #include "GlobalParams.h"
 
 #if MULTITHREADED
 #include "UnicodeMapTables.h"
 #include "UTF8.h"
 
+#ifdef ENABLE_PLUGINS
+#  ifdef WIN32
+extern XpdfPluginVecTable xpdfPluginVecTable;
+#  endif
+#endif
+
 //------------------------------------------------------------------------
 
 #define cidToUnicodeCacheSize     4
 
 static struct {
   char *name;
-  char *fileName;
+  char *t1FileName;
+  char *ttFileName;
 } 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"},
+  {"Courier",               "n022003l.pfb", "cour.ttf"},
+  {"Courier-Bold",          "n022004l.pfb", "courbd.ttf"},
+  {"Courier-BoldOblique",   "n022024l.pfb", "courbi.ttf"},
+  {"Courier-Oblique",       "n022023l.pfb", "couri.ttf"},
+  {"Helvetica",             "n019003l.pfb", "arial.ttf"},
+  {"Helvetica-Bold",        "n019004l.pfb", "arialbd.ttf"},
+  {"Helvetica-BoldOblique", "n019024l.pfb", "arialbi.ttf"},
+  {"Helvetica-Oblique",     "n019023l.pfb", "ariali.ttf"},
+  {"Symbol",                "s050000l.pfb", NULL},
+  {"Times-Bold",            "n021004l.pfb", "timesbd.ttf"},
+  {"Times-BoldItalic",      "n021024l.pfb", "timesbi.ttf"},
+  {"Times-Italic",          "n021023l.pfb", "timesi.ttf"},
+  {"Times-Roman",           "n021003l.pfb", "times.ttf"},
+  {"ZapfDingbats",          "d050000l.pfb", NULL},
   {NULL}
 };
 
+#ifdef WIN32
+static char *displayFontDirs[] = {
+  "c:/windows/fonts",
+  "c:/winnt/fonts",
+  NULL
+};
+#else
 static char *displayFontDirs[] = {
   "/usr/share/ghostscript/fonts",
   "/usr/local/share/ghostscript/fonts",
   "/usr/share/fonts/default/Type1",
+  "/usr/share/fonts/default/ghostscript",
+  "/usr/share/fonts/type1/gsfonts",
   NULL
 };
+#endif
 
 //------------------------------------------------------------------------
 
@@ -145,6 +173,148 @@ PSFontParam::~PSFontParam() {
   }
 }
 
+#ifdef ENABLE_PLUGINS
+//------------------------------------------------------------------------
+// Plugin
+//------------------------------------------------------------------------
+
+class Plugin {
+public:
+
+  static Plugin *load(char *type, char *name);
+  ~Plugin();
+
+private:
+
+#ifdef WIN32
+  Plugin(HMODULE libA);
+  HMODULE lib;
+#else
+  Plugin(void *dlA);
+  void *dl;
+#endif
+};
+
+Plugin *Plugin::load(char *type, char *name) {
+  GString *path;
+  Plugin *plugin;
+  XpdfPluginVecTable *vt;
+  XpdfBool (*xpdfInitPlugin)(void);
+#ifdef WIN32
+  HMODULE libA;
+#else
+  void *dlA;
+#endif
+
+  path = globalParams->getBaseDir();
+  appendToPath(path, "plugins");
+  appendToPath(path, type);
+  appendToPath(path, name);
+
+#ifdef WIN32
+  path->append(".dll");
+  if (!(libA = LoadLibrary(path->getCString()))) {
+    error(-1, "Failed to load plugin '%s'",
+         path->getCString());
+    goto err1;
+  }
+  if (!(vt = (XpdfPluginVecTable *)
+                GetProcAddress(libA, "xpdfPluginVecTable"))) {
+    error(-1, "Failed to find xpdfPluginVecTable in plugin '%s'",
+         path->getCString());
+    goto err2;
+  }
+#else
+  //~ need to deal with other extensions here
+  path->append(".so");
+  if (!(dlA = dlopen(path->getCString(), RTLD_NOW))) {
+    error(-1, "Failed to load plugin '%s': %s",
+         path->getCString(), dlerror());
+    goto err1;
+  }
+  if (!(vt = (XpdfPluginVecTable *)dlsym(dlA, "xpdfPluginVecTable"))) {
+    error(-1, "Failed to find xpdfPluginVecTable in plugin '%s'",
+         path->getCString());
+    goto err2;
+  }
+#endif
+
+  if (vt->version != xpdfPluginVecTable.version) {
+    error(-1, "Plugin '%s' is wrong version", path->getCString());
+    goto err2;
+  }
+  memcpy(vt, &xpdfPluginVecTable, sizeof(xpdfPluginVecTable));
+
+#ifdef WIN32
+  if (!(xpdfInitPlugin = (XpdfBool (*)(void))
+                            GetProcAddress(libA, "xpdfInitPlugin"))) {
+    error(-1, "Failed to find xpdfInitPlugin in plugin '%s'",
+         path->getCString());
+    goto err2;
+  }
+#else
+  if (!(xpdfInitPlugin = (XpdfBool (*)(void))dlsym(dlA, "xpdfInitPlugin"))) {
+    error(-1, "Failed to find xpdfInitPlugin in plugin '%s'",
+         path->getCString());
+    goto err2;
+  }
+#endif
+
+  if (!(*xpdfInitPlugin)()) {
+    error(-1, "Initialization of plugin '%s' failed",
+         path->getCString());
+    goto err2;
+  }
+
+#ifdef WIN32
+  plugin = new Plugin(libA);
+#else
+  plugin = new Plugin(dlA);
+#endif
+
+  delete path;
+  return plugin;
+
+ err2:
+#ifdef WIN32
+  FreeLibrary(libA);
+#else
+  dlclose(dlA);
+#endif
+ err1:
+  delete path;
+  return NULL;
+}
+
+#ifdef WIN32
+Plugin::Plugin(HMODULE libA) {
+  lib = libA;
+}
+#else
+Plugin::Plugin(void *dlA) {
+  dl = dlA;
+}
+#endif
+
+Plugin::~Plugin() {
+  void (*xpdfFreePlugin)(void);
+
+#ifdef WIN32
+  if ((xpdfFreePlugin = (void (*)(void))
+                            GetProcAddress(lib, "xpdfFreePlugin"))) {
+    (*xpdfFreePlugin)();
+  }
+  FreeLibrary(lib);
+#else
+  if ((xpdfFreePlugin = (void (*)(void))dlsym(dl, "xpdfFreePlugin"))) {
+    (*xpdfFreePlugin)();
+  }
+  dlclose(dl);
+#endif
+}
+
+#endif // ENABLE_PLUGINS
+
 //------------------------------------------------------------------------
 // parsing
 //------------------------------------------------------------------------
@@ -172,6 +342,12 @@ GlobalParams::GlobalParams(char *cfgFileName) {
     }
   }
 
+#ifdef WIN32
+  // baseDir will be set by a call to setBaseDir
+  baseDir = new GString();
+#else
+  baseDir = appendToPath(getHomeDir(), ".xpdf");
+#endif
   nameToUnicode = new NameToCharCode();
   cidToUnicodes = new GHash(gTrue);
   unicodeToUnicodes = new GHash(gTrue);
@@ -231,6 +407,7 @@ GlobalParams::GlobalParams(char *cfgFileName) {
   textKeepTinyChars = gFalse;
   fontDirs = new GList();
   initialZoom = new GString("125");
+  continuousView = gFalse;
   enableT1lib = gTrue;
   enableFreeType = gTrue;
   antialias = gTrue;
@@ -246,6 +423,11 @@ GlobalParams::GlobalParams(char *cfgFileName) {
   unicodeMapCache = new UnicodeMapCache();
   cMapCache = new CMapCache();
 
+#ifdef ENABLE_PLUGINS
+  plugins = new GList();
+  securityHandlers = new GList();
+#endif
+
   // set up the initial nameToUnicode table
   for (i = 0; nameToUnicodeTab[i].name; ++i) {
     nameToUnicode->add(nameToUnicodeTab[i].name, nameToUnicodeTab[i].u);
@@ -315,7 +497,7 @@ void GlobalParams::parseFile(GString *fileName, FILE *f) {
   char *p1, *p2;
   char buf[512];
   FILE *f2;
-  
+
   /* extract path */
   if(fileName) {
     char* cfgFileName = fileName->getCString();
@@ -460,6 +642,8 @@ void GlobalParams::parseFile(GString *fileName, FILE *f) {
        parseFontDir(tokens, fileName, line);
       } else if (!cmd->cmp("initialZoom")) {
        parseInitialZoom(tokens, fileName, line);
+      } else if (!cmd->cmp("continuousView")) {
+       parseYesNo("continuousView", &continuousView, tokens, fileName, line);
       } else if (!cmd->cmp("enableT1lib")) {
        parseYesNo("enableT1lib", &enableT1lib, tokens, fileName, line);
       } else if (!cmd->cmp("enableFreeType")) {
@@ -907,6 +1091,7 @@ GlobalParams::~GlobalParams() {
 
   delete macRomanReverseMap;
 
+  delete baseDir;
   delete nameToUnicode;
   deleteGHash(cidToUnicodes, GString);
   deleteGHash(unicodeToUnicodes, GString);
@@ -943,6 +1128,11 @@ GlobalParams::~GlobalParams() {
   delete unicodeMapCache;
   delete cMapCache;
 
+#ifdef ENABLE_PLUGINS
+  delete securityHandlers;
+  deleteGList(plugins, Plugin);
+#endif
+
 #if MULTITHREADED
   gDestroyMutex(&mutex);
   gDestroyMutex(&unicodeMapCacheMutex);
@@ -952,13 +1142,43 @@ GlobalParams::~GlobalParams() {
 
 //------------------------------------------------------------------------
 
+void GlobalParams::setBaseDir(char *dir) {
+  delete baseDir;
+  baseDir = new GString(dir);
+}
+
 void GlobalParams::setupBaseFonts(char *dir) {
   GString *fontName;
   GString *fileName;
+#ifdef WIN32
+  HMODULE shell32Lib;
+  BOOL (__stdcall *SHGetSpecialFolderPathFunc)(HWND hwndOwner,
+                                              LPTSTR lpszPath,
+                                              int nFolder,
+                                              BOOL fCreate);
+  char winFontDir[MAX_PATH];
+#endif
   FILE *f;
+  DisplayFontParamKind kind;
   DisplayFontParam *dfp;
   int i, j;
 
+#ifdef WIN32
+  // SHGetSpecialFolderPath isn't available in older versions of
+  // shell32.dll (Win95 and WinNT4), so do a dynamic load
+  winFontDir[0] = '\0';
+  if ((shell32Lib = LoadLibrary("shell32.dll"))) {
+    if ((SHGetSpecialFolderPathFunc = 
+        (BOOL (__stdcall *)(HWND hwndOwner, LPTSTR lpszPath,
+                            int nFolder, BOOL fCreate))
+        GetProcAddress(shell32Lib, "SHGetSpecialFolderPath"))) {
+      if (!(*SHGetSpecialFolderPathFunc)(NULL, winFontDir,
+                                        CSIDL_FONTS, FALSE)) {
+       winFontDir[0] = '\0';
+      }
+    }
+  }
+#endif
   for (i = 0; displayFontTab[i].name; ++i) {
     fontName = new GString(displayFontTab[i].name);
     if (getDisplayFont(fontName)) {
@@ -966,8 +1186,22 @@ void GlobalParams::setupBaseFonts(char *dir) {
       continue;
     }
     fileName = NULL;
+    kind = displayFontT1; // make gcc happy
     if (dir) {
-      fileName = appendToPath(new GString(dir), displayFontTab[i].fileName);
+      fileName = appendToPath(new GString(dir), displayFontTab[i].t1FileName);
+      kind = displayFontT1;
+      if ((f = fopen(fileName->getCString(), "rb"))) {
+       fclose(f);
+      } else {
+       delete fileName;
+       fileName = NULL;
+      }
+    }
+#ifdef WIN32
+    if (!fileName && winFontDir[0] && displayFontTab[i].ttFileName) {
+      fileName = appendToPath(new GString(winFontDir),
+                             displayFontTab[i].ttFileName);
+      kind = displayFontTT;
       if ((f = fopen(fileName->getCString(), "rb"))) {
        fclose(f);
       } else {
@@ -975,10 +1209,27 @@ void GlobalParams::setupBaseFonts(char *dir) {
        fileName = NULL;
       }
     }
-#ifndef WIN32
+    // SHGetSpecialFolderPath(CSIDL_FONTS) doesn't work on Win 2k Server
+    // or Win2003 Server, or with older versions of shell32.dll, so check
+    // the "standard" directories
+    if (displayFontTab[i].ttFileName) {
+      for (j = 0; !fileName && displayFontDirs[j]; ++j) {
+       fileName = appendToPath(new GString(displayFontDirs[j]),
+                               displayFontTab[i].ttFileName);
+       kind = displayFontTT;
+       if ((f = fopen(fileName->getCString(), "rb"))) {
+         fclose(f);
+       } else {
+         delete fileName;
+         fileName = NULL;
+       }
+      }
+    }
+#else
     for (j = 0; !fileName && displayFontDirs[j]; ++j) {
       fileName = appendToPath(new GString(displayFontDirs[j]),
-                             displayFontTab[i].fileName);
+                             displayFontTab[i].t1FileName);
+      kind = displayFontT1;
       if ((f = fopen(fileName->getCString(), "rb"))) {
        fclose(f);
       } else {
@@ -992,7 +1243,7 @@ void GlobalParams::setupBaseFonts(char *dir) {
       delete fontName;
       continue;
     }
-    dfp = new DisplayFontParam(fontName, displayFontT1);
+    dfp = new DisplayFontParam(fontName, kind);
     dfp->t1.fileName = fileName;
     globalParams->addDisplayFont(dfp);
   }
@@ -1007,6 +1258,15 @@ CharCode GlobalParams::getMacRomanCharCode(char *charName) {
   return macRomanReverseMap->lookup(charName);
 }
 
+GString *GlobalParams::getBaseDir() {
+  GString *s;
+
+  lockGlobalParams;
+  s = baseDir->copy();
+  unlockGlobalParams;
+  return s;
+}
+
 Unicode GlobalParams::mapNameToUnicode(char *charName) {
   // no need to lock - nameToUnicode is constant
   return nameToUnicode->lookup(charName);
@@ -1359,6 +1619,15 @@ GString *GlobalParams::getInitialZoom() {
   return s;
 }
 
+GBool GlobalParams::getContinuousView() {
+  GBool f;
+
+  lockGlobalParams;
+  f = continuousView;
+  unlockGlobalParams;
+  return f;
+}
+
 GBool GlobalParams::getEnableT1lib() {
   GBool f;
 
@@ -1675,6 +1944,12 @@ void GlobalParams::setInitialZoom(char *s) {
   unlockGlobalParams;
 }
 
+void GlobalParams::setContinuousView(GBool cont) {
+  lockGlobalParams;
+  continuousView = cont;
+  unlockGlobalParams;
+}
+
 GBool GlobalParams::setEnableT1lib(char *s) {
   GBool ok;
 
@@ -1720,3 +1995,63 @@ void GlobalParams::setErrQuiet(GBool errQuietA) {
   errQuiet = errQuietA;
   unlockGlobalParams;
 }
+
+void GlobalParams::addSecurityHandler(XpdfSecurityHandler *handler) {
+#ifdef ENABLE_PLUGINS
+  lockGlobalParams;
+  securityHandlers->append(handler);
+  unlockGlobalParams;
+#endif
+}
+
+XpdfSecurityHandler *GlobalParams::getSecurityHandler(char *name) {
+#ifdef ENABLE_PLUGINS
+  XpdfSecurityHandler *hdlr;
+  int i;
+
+  lockGlobalParams;
+  for (i = 0; i < securityHandlers->getLength(); ++i) {
+    hdlr = (XpdfSecurityHandler *)securityHandlers->get(i);
+    if (!stricmp(hdlr->name, name)) {
+      unlockGlobalParams;
+      return hdlr;
+    }
+  }
+  unlockGlobalParams;
+
+  if (!loadPlugin("security", name)) {
+    return NULL;
+  }
+
+  lockGlobalParams;
+  for (i = 0; i < securityHandlers->getLength(); ++i) {
+    hdlr = (XpdfSecurityHandler *)securityHandlers->get(i);
+    if (!strcmp(hdlr->name, name)) {
+      unlockGlobalParams;
+      return hdlr;
+    }
+  }
+  unlockGlobalParams;
+#endif
+
+  return NULL;
+}
+
+#ifdef ENABLE_PLUGINS
+//------------------------------------------------------------------------
+// plugins
+//------------------------------------------------------------------------
+
+GBool GlobalParams::loadPlugin(char *type, char *name) {
+  Plugin *plugin;
+
+  if (!(plugin = Plugin::load(type, name))) {
+    return gFalse;
+  }
+  lockGlobalParams;
+  plugins->append(plugin);
+  unlockGlobalParams;
+  return gTrue;
+}
+
+#endif // ENABLE_PLUGINS
index 0982036..e14ad4f 100644 (file)
@@ -33,6 +33,7 @@ class UnicodeMap;
 class UnicodeMapCache;
 class CMap;
 class CMapCache;
+struct XpdfSecurityHandler;
 class GlobalParams;
 
 //------------------------------------------------------------------------
@@ -47,6 +48,14 @@ enum DisplayFontParamKind {
   displayFontTT
 };
 
+struct DisplayFontParamT1 {
+  GString *fileName;
+};
+
+struct DisplayFontParamTT {
+  GString *fileName;
+};
+
 class DisplayFontParam {
 public:
 
@@ -55,12 +64,8 @@ public:
                                //   generic CID fonts
   DisplayFontParamKind kind;
   union {
-    struct {
-      GString *fileName;
-    } t1;
-    struct {
-      GString *fileName;
-    } tt;
+    DisplayFontParamT1 t1;
+    DisplayFontParamTT tt;
   };
 
   DisplayFontParam(GString *nameA, DisplayFontParamKind kindA);
@@ -115,12 +120,14 @@ public:
 
   ~GlobalParams();
 
+  void setBaseDir(char *dir);
   void setupBaseFonts(char *dir);
 
   //----- accessors
 
   CharCode getMacRomanCharCode(char *charName);
 
+  GString *getBaseDir();
   Unicode mapNameToUnicode(char *charName);
   UnicodeMap *getResidentUnicodeMap(GString *encodingName);
   FILE *getUnicodeMapFile(GString *encodingName);
@@ -152,6 +159,7 @@ public:
   GBool getTextKeepTinyChars();
   GString *findFontFile(GString *fontName, char **exts);
   GString *getInitialZoom();
+  GBool getContinuousView();
   GBool getEnableT1lib();
   GBool getEnableFreeType();
   GBool getAntialias();
@@ -192,12 +200,18 @@ public:
   void setTextPageBreaks(GBool pageBreaks);
   void setTextKeepTinyChars(GBool keep);
   void setInitialZoom(char *s);
+  void setContinuousView(GBool cont);
   GBool setEnableT1lib(char *s);
   GBool setEnableFreeType(char *s);
   GBool setAntialias(char *s);
   void setMapNumericCharNames(GBool map);
   void setPrintCommands(GBool printCommandsA);
   void setErrQuiet(GBool errQuietA);
+
+  //----- security handlers
+
+  void addSecurityHandler(XpdfSecurityHandler *handler);
+  XpdfSecurityHandler *getSecurityHandler(char *name);
   void parseFile(GString *fileName, FILE *f);
 
 private:
@@ -228,7 +242,10 @@ private:
                  GList *tokens, GString *fileName, int line);
   GBool parseYesNo2(char *token, GBool *flag);
   UnicodeMap *getUnicodeMap2(GString *encodingName);
-  
+#ifdef ENABLE_PLUGINS
+  GBool loadPlugin(char *type, char *name);
+#endif
+
   //----- config file base path
 
   GString*path;
@@ -240,6 +257,7 @@ private:
 
   //----- user-modifiable settings
 
+  GString *baseDir;            // base directory - for plugins, etc.
   NameToCharCode *             // mapping from char name to Unicode
     nameToUnicode;
   GHash *cidToUnicodes;                // files for mappings from char collections
@@ -291,6 +309,7 @@ private:
   GBool textKeepTinyChars;     // keep all characters in text output
   GList *fontDirs;             // list of font dirs [GString]
   GString *initialZoom;                // initial zoom level
+  GBool continuousView;                // continuous view mode
   GBool enableT1lib;           // t1lib enable flag
   GBool enableFreeType;                // FreeType enable flag
   GBool antialias;             // anti-aliasing enable flag
@@ -305,6 +324,12 @@ private:
   UnicodeMapCache *unicodeMapCache;
   CMapCache *cMapCache;
 
+#ifdef ENABLE_PLUGINS
+  GList *plugins;              // list of plugins [Plugin]
+  GList *securityHandlers;     // list of loaded security handlers
+                               //   [XpdfSecurityHandler]
+#endif
+
 #if MULTITHREADED
   GMutex mutex;
   GMutex unicodeMapCacheMutex;
index 464f16b..327aa24 100644 (file)
@@ -22,6 +22,9 @@ class GString;
 class GfxState;
 class GfxColorSpace;
 class GfxImageColorMap;
+class GfxFunctionShading;
+class GfxAxialShading;
+class GfxRadialShading;
 class Stream;
 class Link;
 class Catalog;
@@ -48,6 +51,16 @@ public:
   // Does this device use drawChar() or drawString()?
   virtual GBool useDrawChar() = 0;
 
+  // Does this device use tilingPatternFill()?  If this returns false,
+  // tiling pattern fills will be reduced to a series of other drawing
+  // operations.
+  virtual GBool useTilingPatternFill() { return gFalse; }
+
+  // Does this device use functionShadedFill(), axialShadedFill(), and
+  // radialShadedFill()?  If this returns false, these shaded fills
+  // will be reduced to a series of other drawing operations.
+  virtual GBool useShadedFills() { return gFalse; }
+
   // Is this device able to draw gradients?
   virtual GBool useGradients() = 0;
 
@@ -78,6 +91,9 @@ public:
   virtual void cvtDevToUser(double dx, double dy, double *ux, double *uy);
   virtual void cvtUserToDev(double ux, double uy, int *dx, int *dy);
 
+  double *getDefCTM() { return defCTM; }
+  double *getDefICTM() { return defICTM; }
+
   //----- link borders
   virtual void drawLink(Link *link, Catalog *catalog) {}
 
@@ -95,10 +111,15 @@ public:
   virtual void updateLineCap(GfxState *state) {}
   virtual void updateMiterLimit(GfxState *state) {}
   virtual void updateLineWidth(GfxState *state) {}
+  virtual void updateFillColorSpace(GfxState *state) {}
+  virtual void updateStrokeColorSpace(GfxState *state) {}
   virtual void updateFillColor(GfxState *state) {}
   virtual void updateStrokeColor(GfxState *state) {}
+  virtual void updateBlendMode(GfxState *state) {}
   virtual void updateFillOpacity(GfxState *state) {}
   virtual void updateStrokeOpacity(GfxState *state) {}
+  virtual void updateFillOverprint(GfxState *state) {}
+  virtual void updateStrokeOverprint(GfxState *state) {}
 
   //----- update text state
   virtual void updateFont(GfxState *state) {}
@@ -115,18 +136,29 @@ public:
   virtual void stroke(GfxState *state) {}
   virtual void fill(GfxState *state) {}
   virtual void eoFill(GfxState *state) {}
+  virtual void tilingPatternFill(GfxState *state, Object *str,
+                                int paintType, Dict *resDict,
+                                double *mat, double *bbox,
+                                int x0, int y0, int x1, int y1,
+                                double xStep, double yStep) {}
+  virtual void functionShadedFill(GfxState *state,
+                                 GfxFunctionShading *shading) {}
+  virtual void axialShadedFill(GfxState *state, GfxAxialShading *shading) {}
+  virtual void radialShadedFill(GfxState *state, GfxRadialShading *shading) {}
 
   //----- path clipping
   virtual void clip(GfxState *state) {}
   virtual void eoClip(GfxState *state) {}
 
   //----- text drawing
+  virtual void beginStringOp(GfxState *state) {}
+  virtual void endStringOp(GfxState *state) {}
   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) {}
+                       CharCode code, int nBytes, Unicode *u, int uLen) {}
   virtual void drawString(GfxState *state, GString *s) {}
   virtual GBool beginType3Char(GfxState *state, double x, double y,
                               double dx, double dy,
@@ -141,6 +173,17 @@ public:
   virtual void drawImage(GfxState *state, Object *ref, Stream *str,
                         int width, int height, GfxImageColorMap *colorMap,
                         int *maskColors, GBool inlineImg);
+  virtual void drawMaskedImage(GfxState *state, Object *ref, Stream *str,
+                              int width, int height,
+                              GfxImageColorMap *colorMap,
+                              Stream *maskStr, int maskWidth, int maskHeight,
+                              GBool maskInvert);
+  virtual void drawSoftMaskedImage(GfxState *state, Object *ref, Stream *str,
+                                  int width, int height,
+                                  GfxImageColorMap *colorMap,
+                                  Stream *maskStr,
+                                  int maskWidth, int maskHeight,
+                                  GfxImageColorMap *maskColorMap);
 
 #if OPI_SUPPORT
   //----- OPI functions
index 17666f6..5c2ae8b 100644 (file)
@@ -22,6 +22,7 @@
 #include "OutputDev.h"
 #ifndef PDF_PARSER_ONLY
 #include "Gfx.h"
+#include "GfxState.h"
 #include "Annot.h"
 #endif
 #include "Error.h"
@@ -33,7 +34,6 @@
 
 PageAttrs::PageAttrs(PageAttrs *attrs, Dict *dict) {
   Object obj1;
-  double w, h;
 
   // get old/default values
   if (attrs) {
@@ -66,18 +66,6 @@ PageAttrs::PageAttrs(PageAttrs *attrs, Dict *dict) {
     cropBox = mediaBox;
   }
 
-  // if the MediaBox is excessively larger than the CropBox,
-  // just use the CropBox
-  limitToCropBox = gFalse;
-  if (haveCropBox) {
-    w = 0.25 * (cropBox.x2 - cropBox.x1);
-    h = 0.25 * (cropBox.y2 - cropBox.y1);
-    if ((cropBox.x1 - mediaBox.x1) + (mediaBox.x2 - cropBox.x2) > w ||
-       (cropBox.y1 - mediaBox.y1) + (mediaBox.y2 - cropBox.y2) > h) {
-      limitToCropBox = gTrue;
-    }
-  }
-
   /* if the crop box is larger than the media box, cut it down to 
      media box size */
   if(haveCropBox &&
@@ -141,6 +129,7 @@ PageAttrs::~PageAttrs() {
 
 GBool PageAttrs::readBox(Dict *dict, char *key, PDFRectangle *box) {
   PDFRectangle tmp;
+  double t;
   Object obj1, obj2;
   GBool ok;
 
@@ -176,6 +165,12 @@ GBool PageAttrs::readBox(Dict *dict, char *key, PDFRectangle *box) {
     }
     obj2.free();
     if (ok) {
+      if (tmp.x1 > tmp.x2) {
+       t = tmp.x1; tmp.x1 = tmp.x2; tmp.x2 = t;
+      }
+      if (tmp.y1 > tmp.y2) {
+       t = tmp.y1; tmp.y1 = tmp.y2; tmp.y2 = t;
+      }
       *box = tmp;
     }
   } else {
@@ -232,22 +227,23 @@ Page::~Page() {
 }
 
 void Page::display(OutputDev *out, double hDPI, double vDPI,
-                  int rotate, GBool crop,
+                  int rotate, GBool useMediaBox, GBool crop,
                   Links *links, Catalog *catalog,
                   GBool (*abortCheckCbk)(void *data),
                   void *abortCheckCbkData) {
-  displaySlice(out, hDPI, vDPI, rotate, crop, -1, -1, -1, -1, links, catalog,
+  displaySlice(out, hDPI, vDPI, rotate, useMediaBox, crop,
+              -1, -1, -1, -1, links, catalog,
               abortCheckCbk, abortCheckCbkData);
 }
 
 void Page::displaySlice(OutputDev *out, double hDPI, double vDPI,
-                       int rotate, GBool crop,
+                       int rotate, GBool useMediaBox, GBool crop,
                        int sliceX, int sliceY, int sliceW, int sliceH,
                        Links *links, Catalog *catalog,
                        GBool (*abortCheckCbk)(void *data),
                        void *abortCheckCbkData) {
 #ifndef PDF_PARSER_ONLY
-  PDFRectangle *mediaBox, *cropBox;
+  PDFRectangle *mediaBox, *cropBox, *baseBox;
   PDFRectangle box;
   Gfx *gfx;
   Object obj;
@@ -263,69 +259,71 @@ void Page::displaySlice(OutputDev *out, double hDPI, double vDPI,
     rotate += 360;
   }
 
-  mediaBox = getBox();
+  mediaBox = getMediaBox();
+  cropBox = getCropBox();
   if (sliceW >= 0 && sliceH >= 0) {
+    baseBox = useMediaBox ? mediaBox : cropBox;
     kx = 72.0 / hDPI;
     ky = 72.0 / vDPI;
     if (rotate == 90) {
       if (out->upsideDown()) {
-       box.x1 = mediaBox->x1 + ky * sliceY;
-       box.x2 = mediaBox->x1 + ky * (sliceY + sliceH);
+       box.x1 = baseBox->x1 + ky * sliceY;
+       box.x2 = baseBox->x1 + ky * (sliceY + sliceH);
       } else {
-       box.x1 = mediaBox->x2 - ky * (sliceY + sliceH);
-       box.x2 = mediaBox->x2 - ky * sliceY;
+       box.x1 = baseBox->x2 - ky * (sliceY + sliceH);
+       box.x2 = baseBox->x2 - ky * sliceY;
       }
-      box.y1 = mediaBox->y1 + kx * sliceX;
-      box.y2 = mediaBox->y1 + kx * (sliceX + sliceW);
+      box.y1 = baseBox->y1 + kx * sliceX;
+      box.y2 = baseBox->y1 + kx * (sliceX + sliceW);
     } else if (rotate == 180) {
-      box.x1 = mediaBox->x2 - kx * (sliceX + sliceW);
-      box.x2 = mediaBox->x2 - kx * sliceX;
+      box.x1 = baseBox->x2 - kx * (sliceX + sliceW);
+      box.x2 = baseBox->x2 - kx * sliceX;
       if (out->upsideDown()) {
-       box.y1 = mediaBox->y1 + ky * sliceY;
-       box.y2 = mediaBox->y1 + ky * (sliceY + sliceH);
+       box.y1 = baseBox->y1 + ky * sliceY;
+       box.y2 = baseBox->y1 + ky * (sliceY + sliceH);
       } else {
-       box.y1 = mediaBox->y2 - ky * (sliceY + sliceH);
-       box.y2 = mediaBox->y2 - ky * sliceY;
+       box.y1 = baseBox->y2 - ky * (sliceY + sliceH);
+       box.y2 = baseBox->y2 - ky * sliceY;
       }
     } else if (rotate == 270) {
       if (out->upsideDown()) {
-       box.x1 = mediaBox->x2 - ky * (sliceY + sliceH);
-       box.x2 = mediaBox->x2 - ky * sliceY;
+       box.x1 = baseBox->x2 - ky * (sliceY + sliceH);
+       box.x2 = baseBox->x2 - ky * sliceY;
       } else {
-       box.x1 = mediaBox->x1 + ky * sliceY;
-       box.x2 = mediaBox->x1 + ky * (sliceY + sliceH);
+       box.x1 = baseBox->x1 + ky * sliceY;
+       box.x2 = baseBox->x1 + ky * (sliceY + sliceH);
       }
-      box.y1 = mediaBox->y2 - kx * (sliceX + sliceW);
-      box.y2 = mediaBox->y2 - kx * sliceX;
+      box.y1 = baseBox->y2 - kx * (sliceX + sliceW);
+      box.y2 = baseBox->y2 - kx * sliceX;
     } else {
-      box.x1 = mediaBox->x1 + kx * sliceX;
-      box.x2 = mediaBox->x1 + kx * (sliceX + sliceW);
+      box.x1 = baseBox->x1 + kx * sliceX;
+      box.x2 = baseBox->x1 + kx * (sliceX + sliceW);
       if (out->upsideDown()) {
-       box.y1 = mediaBox->y2 - ky * (sliceY + sliceH);
-       box.y2 = mediaBox->y2 - ky * sliceY;
+       box.y1 = baseBox->y2 - ky * (sliceY + sliceH);
+       box.y2 = baseBox->y2 - ky * sliceY;
       } else {
-       box.y1 = mediaBox->y1 + ky * sliceY;
-       box.y2 = mediaBox->y1 + ky * (sliceY + sliceH);
+       box.y1 = baseBox->y1 + ky * sliceY;
+       box.y2 = baseBox->y1 + ky * (sliceY + sliceH);
       }
     }
-  } else {
+  } else if (useMediaBox) {
     box = *mediaBox;
+  } else {
+    box = *cropBox;
+    crop = gFalse;
   }
-  cropBox = getCropBox();
 
   if (globalParams->getPrintCommands()) {
     printf("***** MediaBox = ll:%g,%g ur:%g,%g\n",
-          box.x1, box.y1, box.x2, box.y2);
-    if (isCropped()) {
-      printf("***** CropBox = ll:%g,%g ur:%g,%g\n",
-            cropBox->x1, cropBox->y1, cropBox->x2, cropBox->y2);
-    }
+          mediaBox->x1, mediaBox->y1, mediaBox->x2, mediaBox->y2);
+    printf("***** CropBox = ll:%g,%g ur:%g,%g\n",
+          cropBox->x1, cropBox->y1, cropBox->x2, cropBox->y2);
     printf("***** Rotate = %d\n", attrs->getRotate());
   }
 
   gfx = new Gfx(xref, out, num, attrs->getResourceDict(),
-               hDPI, vDPI, &box, crop && isCropped(), cropBox, rotate,
-               abortCheckCbk, abortCheckCbkData);
+               hDPI, vDPI, &box, crop ? cropBox : (PDFRectangle *)NULL,
+               rotate, abortCheckCbk, abortCheckCbkData);
   contents.fetch(xref, &obj);
   if (!obj.isNull()) {
     gfx->saveState();
@@ -346,7 +344,7 @@ void Page::displaySlice(OutputDev *out, double hDPI, double vDPI,
   }
 
   // draw non-link annotations
-  annotList = new Annots(xref, annots.fetch(xref, &obj));
+  annotList = new Annots(xref, catalog, annots.fetch(xref, &obj));
   obj.free();
   if (annotList->getNumAnnots() > 0) {
     if (globalParams->getPrintCommands()) {
@@ -362,3 +360,21 @@ void Page::displaySlice(OutputDev *out, double hDPI, double vDPI,
   delete gfx;
 #endif
 }
+
+void Page::getDefaultCTM(double *ctm, double hDPI, double vDPI,
+                        int rotate, GBool upsideDown) {
+  GfxState *state;
+  int i;
+
+  rotate += getRotate();
+  if (rotate >= 360) {
+    rotate -= 360;
+  } else if (rotate < 0) {
+    rotate += 360;
+  }
+  state = new GfxState(hDPI, vDPI, getMediaBox(), rotate, upsideDown);
+  for (i = 0; i < 6; ++i) {
+    ctm[i] = state->getCTM()[i];
+  }
+  delete state;
+}
index 297a079..7a663d3 100644 (file)
@@ -27,9 +27,9 @@ extern "C" int unlink(char *filename);
 #include "config.h"
 #include "Error.h"
 #include "Object.h"
-#ifndef NO_DECRYPTION
+#include "Lexer.h"
 #include "Decrypt.h"
-#endif
+#include "GfxState.h"
 #include "Stream.h"
 #include "JBIG2Stream.h"
 #include "JPXStream.h"
@@ -274,25 +274,19 @@ Stream *Stream::makeFilter(char *name, Stream *str, Object *params) {
 
 BaseStream::BaseStream(Object *dictA) {
   dict = *dictA;
-#ifndef NO_DECRYPTION
   decrypt = NULL;
-#endif
 }
 
 BaseStream::~BaseStream() {
   dict.free();
-#ifndef NO_DECRYPTION
   if (decrypt)
     delete decrypt;
-#endif
 }
 
-#ifndef NO_DECRYPTION
 void BaseStream::doDecryption(Guchar *fileKey, int keyLength,
                              int objNum, int objGen) {
   decrypt = new Decrypt(fileKey, keyLength, objNum, objGen);
 }
-#endif
 
 //------------------------------------------------------------------------
 // FilterStream
@@ -331,7 +325,7 @@ ImageStream::ImageStream(Stream *strA, int widthA, int nCompsA, int nBitsA) {
   } else {
     imgLineSize = nVals;
   }
-  imgLine = (Guchar *)gmalloc(imgLineSize * sizeof(Guchar));
+  imgLine = (Guchar *)gmallocn(imgLineSize, sizeof(Guchar));
   imgIdx = nVals;
 }
 
@@ -409,18 +403,33 @@ void ImageStream::skipLine() {
 
 StreamPredictor::StreamPredictor(Stream *strA, int predictorA,
                                 int widthA, int nCompsA, int nBitsA) {
+  int totalBits;
+
   str = strA;
   predictor = predictorA;
   width = widthA;
   nComps = nCompsA;
   nBits = nBitsA;
+  predLine = NULL;
+  ok = gFalse;
 
   nVals = width * nComps;
+  totalBits = nVals * nBits;
+  if (totalBits == 0 ||
+      (totalBits / nBits) / nComps != width ||
+      totalBits + 7 < 0) {
+    return;
+  }
   pixBytes = (nComps * nBits + 7) >> 3;
-  rowBytes = ((nVals * nBits + 7) >> 3) + pixBytes;
+  rowBytes = ((totalBits + 7) >> 3) + pixBytes;
+  if (rowBytes < 0) {
+    return;
+  }
   predLine = (Guchar *)gmalloc(rowBytes);
   memset(predLine, 0, rowBytes);
   predIdx = rowBytes;
+
+  ok = gTrue;
 }
 
 StreamPredictor::~StreamPredictor() {
@@ -447,12 +456,12 @@ int StreamPredictor::getChar() {
 
 GBool StreamPredictor::getNextLine() {
   int curPred;
-  Guchar upLeftBuf[4];
+  Guchar upLeftBuf[gfxColorMaxComps * 2 + 1];
   int left, up, upLeft, p, pa, pb, pc;
   int c;
   Gulong inBuf, outBuf, bitMask;
   int inBits, outBits;
-  int i, j, k;
+  int i, j, k, kk;
 
   // get PNG optimum predictor number
   if (predictor >= 10) {
@@ -465,13 +474,19 @@ GBool StreamPredictor::getNextLine() {
   }
 
   // read the raw line, apply PNG (byte) predictor
-  upLeftBuf[0] = upLeftBuf[1] = upLeftBuf[2] = upLeftBuf[3] = 0;
+  memset(upLeftBuf, 0, pixBytes + 1);
   for (i = pixBytes; i < rowBytes; ++i) {
-    upLeftBuf[3] = upLeftBuf[2];
-    upLeftBuf[2] = upLeftBuf[1];
-    upLeftBuf[1] = upLeftBuf[0];
+    for (j = pixBytes; j > 0; --j) {
+      upLeftBuf[j] = upLeftBuf[j-1];
+    }
     upLeftBuf[0] = predLine[i];
     if ((c = str->getRawChar()) == EOF) {
+      if (i > pixBytes) {
+       // this ought to return false, but some (broken) PDF files
+       // contain truncated image data, and Adobe apparently reads the
+       // last partial line
+       break;
+      }
       return gFalse;
     }
     switch (curPred) {
@@ -524,30 +539,31 @@ GBool StreamPredictor::getNextLine() {
        predLine[i] += predLine[i - nComps];
       }
     } else {
-      upLeftBuf[0] = upLeftBuf[1] = upLeftBuf[2] = upLeftBuf[3] = 0;
+      memset(upLeftBuf, 0, nComps + 1);
       bitMask = (1 << nBits) - 1;
       inBuf = outBuf = 0;
       inBits = outBits = 0;
       j = k = pixBytes;
-      for (i = 0; i < nVals; ++i) {
-       if (inBits < nBits) {
-         inBuf = (inBuf << 8) | (predLine[j++] & 0xff);
-         inBits += 8;
-       }
-       upLeftBuf[3] = upLeftBuf[2];
-       upLeftBuf[2] = upLeftBuf[1];
-       upLeftBuf[1] = upLeftBuf[0];
-       upLeftBuf[0] = (upLeftBuf[nComps] +
-                       (inBuf >> (inBits - nBits))) & bitMask;
-       outBuf = (outBuf << nBits) | upLeftBuf[0];
-       inBits -= nBits;
-       outBits += nBits;
-       if (outBits > 8) {
-         predLine[k++] = (Guchar)(outBuf >> (outBits - 8));
+      for (i = 0; i < width; ++i) {
+       for (kk = 0; kk < nComps; ++kk) {
+         if (inBits < nBits) {
+           inBuf = (inBuf << 8) | (predLine[j++] & 0xff);
+           inBits += 8;
+         }
+         upLeftBuf[kk] = (upLeftBuf[kk] +
+                          (inBuf >> (inBits - nBits))) & bitMask;
+         inBits -= nBits;
+         outBuf = (outBuf << nBits) | upLeftBuf[kk];
+         outBits += nBits;
+         if (outBits >= 8) {
+           predLine[k++] = (Guchar)(outBuf >> (outBits - 8));
+           outBits -= 8;
+         }
        }
       }
       if (outBits > 0) {
-       predLine[k++] = (Guchar)(outBuf << (8 - outBits));
+       predLine[k++] = (Guchar)((outBuf << (8 - outBits)) +
+                                (inBuf & ((1 << (8 - outBits)) - 1)));
       }
     }
   }
@@ -598,10 +614,8 @@ void FileStream::reset() {
   saved = gTrue;
   bufPtr = bufEnd = buf;
   bufPos = start;
-#ifndef NO_DECRYPTION
   if (decrypt)
     decrypt->reset();
-#endif
 }
 
 void FileStream::close() {
@@ -619,9 +633,7 @@ void FileStream::close() {
 
 GBool FileStream::fillBuf() {
   int n;
-#ifndef NO_DECRYPTION
   char *p;
-#endif
 
   bufPos += bufEnd - buf;
   bufPtr = bufEnd = buf;
@@ -638,13 +650,11 @@ GBool FileStream::fillBuf() {
   if (bufPtr >= bufEnd) {
     return gFalse;
   }
-#ifndef NO_DECRYPTION
   if (decrypt) {
     for (p = buf; p < bufEnd; ++p) {
       *p = (char)decrypt->decryptByte((Guchar)*p);
     }
   }
-#endif
   return gTrue;
 }
 
@@ -733,11 +743,9 @@ Stream *MemStream::makeSubStream(Guint startA, GBool limited,
 
 void MemStream::reset() {
   bufPtr = buf + start;
-#ifndef NO_DECRYPTION
   if (decrypt) {
     decrypt->reset();
   }
-#endif
 }
 
 void MemStream::close() {
@@ -761,10 +769,10 @@ void MemStream::setPos(Guint pos, int dir) {
 
 void MemStream::moveStart(int delta) {
   start += delta;
+  length -= delta;
   bufPtr = buf + start;
 }
 
-#ifndef NO_DECRYPTION
 void MemStream::doDecryption(Guchar *fileKey, int keyLength,
                             int objNum, int objGen) {
   char *newBuf;
@@ -783,7 +791,6 @@ void MemStream::doDecryption(Guchar *fileKey, int keyLength,
     needFree = gTrue;
   }
 }
-#endif
 
 //------------------------------------------------------------------------
 // EmbedStream
@@ -954,7 +961,7 @@ int ASCII85Stream::lookChar() {
     index = 0;
     do {
       c[0] = str->getChar();
-    } while (c[0] == '\n' || c[0] == '\r');
+    } while (Lexer::isSpace(c[0]));
     if (c[0] == '~' || c[0] == EOF) {
       eof = gTrue;
       n = 0;
@@ -966,7 +973,7 @@ int ASCII85Stream::lookChar() {
       for (k = 1; k < 5; ++k) {
        do {
          c[k] = str->getChar();
-       } while (c[k] == '\n' || c[k] == '\r');
+       } while (Lexer::isSpace(c[k]));
        if (c[k] == '~' || c[k] == EOF)
          break;
       }
@@ -1014,6 +1021,10 @@ LZWStream::LZWStream(Stream *strA, int predictor, int columns, int colors,
     FilterStream(strA) {
   if (predictor != 1) {
     pred = new StreamPredictor(this, predictor, columns, colors, bits);
+    if (!pred->isOk()) {
+      delete pred;
+      pred = NULL;
+    }
   } else {
     pred = NULL;
   }
@@ -1179,7 +1190,11 @@ GString *LZWStream::getPSFilter(int psLevel, char *indent) {
   if (!(s = str->getPSFilter(psLevel, indent))) {
     return NULL;
   }
-  s->append(indent)->append("/LZWDecode filter\n");
+  s->append(indent)->append("<< ");
+  if (!early) {
+    s->append("/EarlyChange 0 ");
+  }
+  s->append(">> /LZWDecode filter\n");
   return s;
 }
 
@@ -1262,11 +1277,14 @@ CCITTFaxStream::CCITTFaxStream(Stream *strA, int encodingA, GBool endOfLineA,
   endOfLine = endOfLineA;
   byteAlign = byteAlignA;
   columns = columnsA;
+  if (columns < 1) {
+    columns = 1;
+  }
   rows = rowsA;
   endOfBlock = endOfBlockA;
   black = blackA;
-  refLine = (short *)gmalloc((columns + 3) * sizeof(short));
-  codingLine = (short *)gmalloc((columns + 2) * sizeof(short));
+  refLine = (short *)gmallocn(columns + 4, sizeof(short));
+  codingLine = (short *)gmallocn(columns + 3, sizeof(short));
 
   eof = gFalse;
   row = 0;
@@ -1388,10 +1406,12 @@ int CCITTFaxStream::lookChar() {
          }
          break;
        case twoDimVertL1:
-         a0New = codingLine[++a0] = refLine[b1] - 1;
-         --b1;
-         while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
-           b1 += 2;
+         if (a0 == 0 || refLine[b1] - 1 > a0New) {
+           a0New = codingLine[++a0] = refLine[b1] - 1;
+           --b1;
+           while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
+             b1 += 2;
+         }
          break;
        case twoDimVertR2:
          a0New = codingLine[++a0] = refLine[b1] + 2;
@@ -1402,10 +1422,12 @@ int CCITTFaxStream::lookChar() {
          }
          break;
        case twoDimVertL2:
-         a0New = codingLine[++a0] = refLine[b1] - 2;
-         --b1;
-         while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
-           b1 += 2;
+         if (a0 == 0 || refLine[b1] - 2 > a0New) {
+           a0New = codingLine[++a0] = refLine[b1] - 2;
+           --b1;
+           while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
+             b1 += 2;
+         }
          break;
        case twoDimVertR3:
          a0New = codingLine[++a0] = refLine[b1] + 3;
@@ -1416,10 +1438,12 @@ int CCITTFaxStream::lookChar() {
          }
          break;
        case twoDimVertL3:
-         a0New = codingLine[++a0] = refLine[b1] - 3;
-         --b1;
-         while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
-           b1 += 2;
+         if (a0 == 0 || refLine[b1] - 3 > a0New) {
+           a0New = codingLine[++a0] = refLine[b1] - 3;
+           --b1;
+           while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
+             b1 += 2;
+         }
          break;
        case EOF:
          eof = gTrue;
@@ -1878,7 +1902,6 @@ DCTStream::~DCTStream() {
 }
 
 void DCTStream::reset() {
-  int minHSample, minVSample;
   int i, j;
 
   str->reset();
@@ -1900,24 +1923,21 @@ void DCTStream::reset() {
   }
 
   // compute MCU size
-  mcuWidth = minHSample = compInfo[0].hSample;
-  mcuHeight = minVSample = compInfo[0].vSample;
+  if (numComps == 1) {
+    compInfo[0].hSample = compInfo[0].vSample = 1;
+  }
+  mcuWidth = compInfo[0].hSample;
+  mcuHeight = compInfo[0].vSample;
   for (i = 1; i < numComps; ++i) {
-    if (compInfo[i].hSample < minHSample)
-      minHSample = compInfo[i].hSample;
-    if (compInfo[i].vSample < minVSample)
-      minVSample = compInfo[i].vSample;
-    if (compInfo[i].hSample > mcuWidth)
+    if (compInfo[i].hSample > mcuWidth) {
       mcuWidth = compInfo[i].hSample;
-    if (compInfo[i].vSample > mcuHeight)
+    }
+    if (compInfo[i].vSample > mcuHeight) {
       mcuHeight = compInfo[i].vSample;
+    }
   }
-  for (i = 0; i < numComps; ++i) {
-    compInfo[i].hSample /= minHSample;
-    compInfo[i].vSample /= minVSample;
-  }
-  mcuWidth = (mcuWidth / minHSample) * 8;
-  mcuHeight = (mcuHeight / minVSample) * 8;
+  mcuWidth *= 8;
+  mcuHeight *= 8;
 
   // figure out color transform
   if (!gotAdobeMarker && numComps == 3) {
@@ -1937,7 +1957,7 @@ void DCTStream::reset() {
     bufWidth = ((width + mcuWidth - 1) / mcuWidth) * mcuWidth;
     bufHeight = ((height + mcuHeight - 1) / mcuHeight) * mcuHeight;
     for (i = 0; i < numComps; ++i) {
-      frameBuf[i] = (int *)gmalloc(bufWidth * bufHeight * sizeof(int));
+      frameBuf[i] = (int *)gmallocn(bufWidth * bufHeight, sizeof(int));
       memset(frameBuf[i], 0, bufWidth * bufHeight * sizeof(int));
     }
 
@@ -1962,7 +1982,7 @@ void DCTStream::reset() {
     bufWidth = ((width + mcuWidth - 1) / mcuWidth) * mcuWidth;
     for (i = 0; i < numComps; ++i) {
       for (j = 0; j < mcuHeight; ++j) {
-       rowBuf[i][j] = (Guchar *)gmalloc(bufWidth * sizeof(Guchar));
+       rowBuf[i][j] = (Guchar *)gmallocn(bufWidth, sizeof(Guchar));
       }
     }
 
@@ -2455,7 +2475,7 @@ GBool DCTStream::readProgressiveDataUnit(DCTHuffTable *dcHuffTable,
 void DCTStream::decodeImage() {
   int dataIn[64];
   Guchar dataOut[64];
-  Guchar *quantTable;
+  Gushort *quantTable;
   int pY, pCb, pCr, pR, pG, pB;
   int x1, y1, x2, y2, x3, y3, x4, y4, x5, y5, cc, i;
   int h, v, horiz, vert, hSub, vSub;
@@ -2594,7 +2614,7 @@ void DCTStream::decodeImage() {
 //   988-991.
 // The stage numbers mentioned in the comments refer to Figure 1 in this
 // paper.
-void DCTStream::transformDataUnit(Guchar *quantTable,
+void DCTStream::transformDataUnit(Gushort *quantTable,
                                  int dataIn[64], Guchar dataOut[64]) {
   int v0, v1, v2, v3, v4, v5, v6, v7, t;
   int *p;
@@ -2822,12 +2842,13 @@ GBool DCTStream::readHeader() {
   while (!doScan) {
     c = readMarker();
     switch (c) {
-    case 0xc0:                 // SOF0
+    case 0xc0:                 // SOF0 (sequential)
+    case 0xc1:                 // SOF1 (extended sequential)
       if (!readBaselineSOF()) {
        return gFalse;
       }
       break;
-    case 0xc2:                 // SOF2
+    case 0xc2:                 // SOF2 (progressive)
       if (!readProgressiveSOF()) {
        return gFalse;
       }
@@ -2899,6 +2920,14 @@ GBool DCTStream::readBaselineSOF() {
   height = read16();
   width = read16();
   numComps = str->getChar();
+  if (numComps <= 0 || numComps > 4) {
+    error(getPos(), "Bad number of components in DCT stream", prec);
+    return gFalse;
+  }
+  if (numComps <= 0 || numComps > 4) {
+    error(getPos(), "Bad number of components in DCT stream", prec);
+    return gFalse;
+  }
   if (prec != 8) {
     error(getPos(), "Bad DCT precision %d", prec);
     return gFalse;
@@ -2988,22 +3017,32 @@ GBool DCTStream::readScanInfo() {
 }
 
 GBool DCTStream::readQuantTables() {
-  int length;
-  int i;
-  int index;
+  int length, prec, i, index;
 
   length = read16() - 2;
   while (length > 0) {
     index = str->getChar();
-    if ((index & 0xf0) || index >= 4) {
+    prec = (index >> 4) & 0x0f;
+    index &= 0x0f;
+    if (prec > 1 || index >= 4) {
       error(getPos(), "Bad DCT quantization table");
       return gFalse;
     }
-    if (index == numQuantTables)
+    if (index == numQuantTables) {
       numQuantTables = index + 1;
-    for (i = 0; i < 64; ++i)
-      quantTables[index][dctZigZag[i]] = str->getChar();
-    length -= 65;
+    }
+    for (i = 0; i < 64; ++i) {
+      if (prec) {
+       quantTables[index][dctZigZag[i]] = read16();
+      } else {
+       quantTables[index][dctZigZag[i]] = str->getChar();
+      }
+    }
+    if (prec) {
+      length -= 129;
+    } else {
+      length -= 65;
+    }
   }
   return gTrue;
 }
@@ -3144,7 +3183,7 @@ int DCTStream::readMarker() {
   do {
     do {
       c = str->getChar();
-    } while (c != 0xff);
+    } while (c != 0xff && c != EOF);
     do {
       c = str->getChar();
     } while (c == 0xff);
@@ -3216,6 +3255,8 @@ FlateDecode FlateStream::lengthDecode[flateMaxLitCodes-257] = {
   {5, 163},
   {5, 195},
   {5, 227},
+  {0, 258},
+  {0, 258},
   {0, 258}
 };
 
@@ -3252,11 +3293,573 @@ FlateDecode FlateStream::distDecode[flateMaxDistCodes] = {
   {13, 24577}
 };
 
+static FlateCode flateFixedLitCodeTabCodes[512] = {
+  {7, 0x0100},
+  {8, 0x0050},
+  {8, 0x0010},
+  {8, 0x0118},
+  {7, 0x0110},
+  {8, 0x0070},
+  {8, 0x0030},
+  {9, 0x00c0},
+  {7, 0x0108},
+  {8, 0x0060},
+  {8, 0x0020},
+  {9, 0x00a0},
+  {8, 0x0000},
+  {8, 0x0080},
+  {8, 0x0040},
+  {9, 0x00e0},
+  {7, 0x0104},
+  {8, 0x0058},
+  {8, 0x0018},
+  {9, 0x0090},
+  {7, 0x0114},
+  {8, 0x0078},
+  {8, 0x0038},
+  {9, 0x00d0},
+  {7, 0x010c},
+  {8, 0x0068},
+  {8, 0x0028},
+  {9, 0x00b0},
+  {8, 0x0008},
+  {8, 0x0088},
+  {8, 0x0048},
+  {9, 0x00f0},
+  {7, 0x0102},
+  {8, 0x0054},
+  {8, 0x0014},
+  {8, 0x011c},
+  {7, 0x0112},
+  {8, 0x0074},
+  {8, 0x0034},
+  {9, 0x00c8},
+  {7, 0x010a},
+  {8, 0x0064},
+  {8, 0x0024},
+  {9, 0x00a8},
+  {8, 0x0004},
+  {8, 0x0084},
+  {8, 0x0044},
+  {9, 0x00e8},
+  {7, 0x0106},
+  {8, 0x005c},
+  {8, 0x001c},
+  {9, 0x0098},
+  {7, 0x0116},
+  {8, 0x007c},
+  {8, 0x003c},
+  {9, 0x00d8},
+  {7, 0x010e},
+  {8, 0x006c},
+  {8, 0x002c},
+  {9, 0x00b8},
+  {8, 0x000c},
+  {8, 0x008c},
+  {8, 0x004c},
+  {9, 0x00f8},
+  {7, 0x0101},
+  {8, 0x0052},
+  {8, 0x0012},
+  {8, 0x011a},
+  {7, 0x0111},
+  {8, 0x0072},
+  {8, 0x0032},
+  {9, 0x00c4},
+  {7, 0x0109},
+  {8, 0x0062},
+  {8, 0x0022},
+  {9, 0x00a4},
+  {8, 0x0002},
+  {8, 0x0082},
+  {8, 0x0042},
+  {9, 0x00e4},
+  {7, 0x0105},
+  {8, 0x005a},
+  {8, 0x001a},
+  {9, 0x0094},
+  {7, 0x0115},
+  {8, 0x007a},
+  {8, 0x003a},
+  {9, 0x00d4},
+  {7, 0x010d},
+  {8, 0x006a},
+  {8, 0x002a},
+  {9, 0x00b4},
+  {8, 0x000a},
+  {8, 0x008a},
+  {8, 0x004a},
+  {9, 0x00f4},
+  {7, 0x0103},
+  {8, 0x0056},
+  {8, 0x0016},
+  {8, 0x011e},
+  {7, 0x0113},
+  {8, 0x0076},
+  {8, 0x0036},
+  {9, 0x00cc},
+  {7, 0x010b},
+  {8, 0x0066},
+  {8, 0x0026},
+  {9, 0x00ac},
+  {8, 0x0006},
+  {8, 0x0086},
+  {8, 0x0046},
+  {9, 0x00ec},
+  {7, 0x0107},
+  {8, 0x005e},
+  {8, 0x001e},
+  {9, 0x009c},
+  {7, 0x0117},
+  {8, 0x007e},
+  {8, 0x003e},
+  {9, 0x00dc},
+  {7, 0x010f},
+  {8, 0x006e},
+  {8, 0x002e},
+  {9, 0x00bc},
+  {8, 0x000e},
+  {8, 0x008e},
+  {8, 0x004e},
+  {9, 0x00fc},
+  {7, 0x0100},
+  {8, 0x0051},
+  {8, 0x0011},
+  {8, 0x0119},
+  {7, 0x0110},
+  {8, 0x0071},
+  {8, 0x0031},
+  {9, 0x00c2},
+  {7, 0x0108},
+  {8, 0x0061},
+  {8, 0x0021},
+  {9, 0x00a2},
+  {8, 0x0001},
+  {8, 0x0081},
+  {8, 0x0041},
+  {9, 0x00e2},
+  {7, 0x0104},
+  {8, 0x0059},
+  {8, 0x0019},
+  {9, 0x0092},
+  {7, 0x0114},
+  {8, 0x0079},
+  {8, 0x0039},
+  {9, 0x00d2},
+  {7, 0x010c},
+  {8, 0x0069},
+  {8, 0x0029},
+  {9, 0x00b2},
+  {8, 0x0009},
+  {8, 0x0089},
+  {8, 0x0049},
+  {9, 0x00f2},
+  {7, 0x0102},
+  {8, 0x0055},
+  {8, 0x0015},
+  {8, 0x011d},
+  {7, 0x0112},
+  {8, 0x0075},
+  {8, 0x0035},
+  {9, 0x00ca},
+  {7, 0x010a},
+  {8, 0x0065},
+  {8, 0x0025},
+  {9, 0x00aa},
+  {8, 0x0005},
+  {8, 0x0085},
+  {8, 0x0045},
+  {9, 0x00ea},
+  {7, 0x0106},
+  {8, 0x005d},
+  {8, 0x001d},
+  {9, 0x009a},
+  {7, 0x0116},
+  {8, 0x007d},
+  {8, 0x003d},
+  {9, 0x00da},
+  {7, 0x010e},
+  {8, 0x006d},
+  {8, 0x002d},
+  {9, 0x00ba},
+  {8, 0x000d},
+  {8, 0x008d},
+  {8, 0x004d},
+  {9, 0x00fa},
+  {7, 0x0101},
+  {8, 0x0053},
+  {8, 0x0013},
+  {8, 0x011b},
+  {7, 0x0111},
+  {8, 0x0073},
+  {8, 0x0033},
+  {9, 0x00c6},
+  {7, 0x0109},
+  {8, 0x0063},
+  {8, 0x0023},
+  {9, 0x00a6},
+  {8, 0x0003},
+  {8, 0x0083},
+  {8, 0x0043},
+  {9, 0x00e6},
+  {7, 0x0105},
+  {8, 0x005b},
+  {8, 0x001b},
+  {9, 0x0096},
+  {7, 0x0115},
+  {8, 0x007b},
+  {8, 0x003b},
+  {9, 0x00d6},
+  {7, 0x010d},
+  {8, 0x006b},
+  {8, 0x002b},
+  {9, 0x00b6},
+  {8, 0x000b},
+  {8, 0x008b},
+  {8, 0x004b},
+  {9, 0x00f6},
+  {7, 0x0103},
+  {8, 0x0057},
+  {8, 0x0017},
+  {8, 0x011f},
+  {7, 0x0113},
+  {8, 0x0077},
+  {8, 0x0037},
+  {9, 0x00ce},
+  {7, 0x010b},
+  {8, 0x0067},
+  {8, 0x0027},
+  {9, 0x00ae},
+  {8, 0x0007},
+  {8, 0x0087},
+  {8, 0x0047},
+  {9, 0x00ee},
+  {7, 0x0107},
+  {8, 0x005f},
+  {8, 0x001f},
+  {9, 0x009e},
+  {7, 0x0117},
+  {8, 0x007f},
+  {8, 0x003f},
+  {9, 0x00de},
+  {7, 0x010f},
+  {8, 0x006f},
+  {8, 0x002f},
+  {9, 0x00be},
+  {8, 0x000f},
+  {8, 0x008f},
+  {8, 0x004f},
+  {9, 0x00fe},
+  {7, 0x0100},
+  {8, 0x0050},
+  {8, 0x0010},
+  {8, 0x0118},
+  {7, 0x0110},
+  {8, 0x0070},
+  {8, 0x0030},
+  {9, 0x00c1},
+  {7, 0x0108},
+  {8, 0x0060},
+  {8, 0x0020},
+  {9, 0x00a1},
+  {8, 0x0000},
+  {8, 0x0080},
+  {8, 0x0040},
+  {9, 0x00e1},
+  {7, 0x0104},
+  {8, 0x0058},
+  {8, 0x0018},
+  {9, 0x0091},
+  {7, 0x0114},
+  {8, 0x0078},
+  {8, 0x0038},
+  {9, 0x00d1},
+  {7, 0x010c},
+  {8, 0x0068},
+  {8, 0x0028},
+  {9, 0x00b1},
+  {8, 0x0008},
+  {8, 0x0088},
+  {8, 0x0048},
+  {9, 0x00f1},
+  {7, 0x0102},
+  {8, 0x0054},
+  {8, 0x0014},
+  {8, 0x011c},
+  {7, 0x0112},
+  {8, 0x0074},
+  {8, 0x0034},
+  {9, 0x00c9},
+  {7, 0x010a},
+  {8, 0x0064},
+  {8, 0x0024},
+  {9, 0x00a9},
+  {8, 0x0004},
+  {8, 0x0084},
+  {8, 0x0044},
+  {9, 0x00e9},
+  {7, 0x0106},
+  {8, 0x005c},
+  {8, 0x001c},
+  {9, 0x0099},
+  {7, 0x0116},
+  {8, 0x007c},
+  {8, 0x003c},
+  {9, 0x00d9},
+  {7, 0x010e},
+  {8, 0x006c},
+  {8, 0x002c},
+  {9, 0x00b9},
+  {8, 0x000c},
+  {8, 0x008c},
+  {8, 0x004c},
+  {9, 0x00f9},
+  {7, 0x0101},
+  {8, 0x0052},
+  {8, 0x0012},
+  {8, 0x011a},
+  {7, 0x0111},
+  {8, 0x0072},
+  {8, 0x0032},
+  {9, 0x00c5},
+  {7, 0x0109},
+  {8, 0x0062},
+  {8, 0x0022},
+  {9, 0x00a5},
+  {8, 0x0002},
+  {8, 0x0082},
+  {8, 0x0042},
+  {9, 0x00e5},
+  {7, 0x0105},
+  {8, 0x005a},
+  {8, 0x001a},
+  {9, 0x0095},
+  {7, 0x0115},
+  {8, 0x007a},
+  {8, 0x003a},
+  {9, 0x00d5},
+  {7, 0x010d},
+  {8, 0x006a},
+  {8, 0x002a},
+  {9, 0x00b5},
+  {8, 0x000a},
+  {8, 0x008a},
+  {8, 0x004a},
+  {9, 0x00f5},
+  {7, 0x0103},
+  {8, 0x0056},
+  {8, 0x0016},
+  {8, 0x011e},
+  {7, 0x0113},
+  {8, 0x0076},
+  {8, 0x0036},
+  {9, 0x00cd},
+  {7, 0x010b},
+  {8, 0x0066},
+  {8, 0x0026},
+  {9, 0x00ad},
+  {8, 0x0006},
+  {8, 0x0086},
+  {8, 0x0046},
+  {9, 0x00ed},
+  {7, 0x0107},
+  {8, 0x005e},
+  {8, 0x001e},
+  {9, 0x009d},
+  {7, 0x0117},
+  {8, 0x007e},
+  {8, 0x003e},
+  {9, 0x00dd},
+  {7, 0x010f},
+  {8, 0x006e},
+  {8, 0x002e},
+  {9, 0x00bd},
+  {8, 0x000e},
+  {8, 0x008e},
+  {8, 0x004e},
+  {9, 0x00fd},
+  {7, 0x0100},
+  {8, 0x0051},
+  {8, 0x0011},
+  {8, 0x0119},
+  {7, 0x0110},
+  {8, 0x0071},
+  {8, 0x0031},
+  {9, 0x00c3},
+  {7, 0x0108},
+  {8, 0x0061},
+  {8, 0x0021},
+  {9, 0x00a3},
+  {8, 0x0001},
+  {8, 0x0081},
+  {8, 0x0041},
+  {9, 0x00e3},
+  {7, 0x0104},
+  {8, 0x0059},
+  {8, 0x0019},
+  {9, 0x0093},
+  {7, 0x0114},
+  {8, 0x0079},
+  {8, 0x0039},
+  {9, 0x00d3},
+  {7, 0x010c},
+  {8, 0x0069},
+  {8, 0x0029},
+  {9, 0x00b3},
+  {8, 0x0009},
+  {8, 0x0089},
+  {8, 0x0049},
+  {9, 0x00f3},
+  {7, 0x0102},
+  {8, 0x0055},
+  {8, 0x0015},
+  {8, 0x011d},
+  {7, 0x0112},
+  {8, 0x0075},
+  {8, 0x0035},
+  {9, 0x00cb},
+  {7, 0x010a},
+  {8, 0x0065},
+  {8, 0x0025},
+  {9, 0x00ab},
+  {8, 0x0005},
+  {8, 0x0085},
+  {8, 0x0045},
+  {9, 0x00eb},
+  {7, 0x0106},
+  {8, 0x005d},
+  {8, 0x001d},
+  {9, 0x009b},
+  {7, 0x0116},
+  {8, 0x007d},
+  {8, 0x003d},
+  {9, 0x00db},
+  {7, 0x010e},
+  {8, 0x006d},
+  {8, 0x002d},
+  {9, 0x00bb},
+  {8, 0x000d},
+  {8, 0x008d},
+  {8, 0x004d},
+  {9, 0x00fb},
+  {7, 0x0101},
+  {8, 0x0053},
+  {8, 0x0013},
+  {8, 0x011b},
+  {7, 0x0111},
+  {8, 0x0073},
+  {8, 0x0033},
+  {9, 0x00c7},
+  {7, 0x0109},
+  {8, 0x0063},
+  {8, 0x0023},
+  {9, 0x00a7},
+  {8, 0x0003},
+  {8, 0x0083},
+  {8, 0x0043},
+  {9, 0x00e7},
+  {7, 0x0105},
+  {8, 0x005b},
+  {8, 0x001b},
+  {9, 0x0097},
+  {7, 0x0115},
+  {8, 0x007b},
+  {8, 0x003b},
+  {9, 0x00d7},
+  {7, 0x010d},
+  {8, 0x006b},
+  {8, 0x002b},
+  {9, 0x00b7},
+  {8, 0x000b},
+  {8, 0x008b},
+  {8, 0x004b},
+  {9, 0x00f7},
+  {7, 0x0103},
+  {8, 0x0057},
+  {8, 0x0017},
+  {8, 0x011f},
+  {7, 0x0113},
+  {8, 0x0077},
+  {8, 0x0037},
+  {9, 0x00cf},
+  {7, 0x010b},
+  {8, 0x0067},
+  {8, 0x0027},
+  {9, 0x00af},
+  {8, 0x0007},
+  {8, 0x0087},
+  {8, 0x0047},
+  {9, 0x00ef},
+  {7, 0x0107},
+  {8, 0x005f},
+  {8, 0x001f},
+  {9, 0x009f},
+  {7, 0x0117},
+  {8, 0x007f},
+  {8, 0x003f},
+  {9, 0x00df},
+  {7, 0x010f},
+  {8, 0x006f},
+  {8, 0x002f},
+  {9, 0x00bf},
+  {8, 0x000f},
+  {8, 0x008f},
+  {8, 0x004f},
+  {9, 0x00ff}
+};
+
+FlateHuffmanTab FlateStream::fixedLitCodeTab = {
+  flateFixedLitCodeTabCodes, 9
+};
+
+static FlateCode flateFixedDistCodeTabCodes[32] = {
+  {5, 0x0000},
+  {5, 0x0010},
+  {5, 0x0008},
+  {5, 0x0018},
+  {5, 0x0004},
+  {5, 0x0014},
+  {5, 0x000c},
+  {5, 0x001c},
+  {5, 0x0002},
+  {5, 0x0012},
+  {5, 0x000a},
+  {5, 0x001a},
+  {5, 0x0006},
+  {5, 0x0016},
+  {5, 0x000e},
+  {0, 0x0000},
+  {5, 0x0001},
+  {5, 0x0011},
+  {5, 0x0009},
+  {5, 0x0019},
+  {5, 0x0005},
+  {5, 0x0015},
+  {5, 0x000d},
+  {5, 0x001d},
+  {5, 0x0003},
+  {5, 0x0013},
+  {5, 0x000b},
+  {5, 0x001b},
+  {5, 0x0007},
+  {5, 0x0017},
+  {5, 0x000f},
+  {0, 0x0000}
+};
+
+FlateHuffmanTab FlateStream::fixedDistCodeTab = {
+  flateFixedDistCodeTabCodes, 5
+};
+
 FlateStream::FlateStream(Stream *strA, int predictor, int columns,
                         int colors, int bits):
     FilterStream(strA) {
   if (predictor != 1) {
     pred = new StreamPredictor(this, predictor, columns, colors, bits);
+    if (!pred->isOk()) {
+      delete pred;
+      pred = NULL;
+    }
   } else {
     pred = NULL;
   }
@@ -3265,8 +3868,12 @@ FlateStream::FlateStream(Stream *strA, int predictor, int columns,
 }
 
 FlateStream::~FlateStream() {
-  gfree(litCodeTab.codes);
-  gfree(distCodeTab.codes);
+  if (litCodeTab.codes != fixedLitCodeTab.codes) {
+    gfree(litCodeTab.codes);
+  }
+  if (distCodeTab.codes != fixedDistCodeTab.codes) {
+    gfree(distCodeTab.codes);
+  }
   if (pred) {
     delete pred;
   }
@@ -3443,9 +4050,13 @@ GBool FlateStream::startBlock() {
   int check;
 
   // free the code tables from the previous block
-  gfree(litCodeTab.codes);
+  if (litCodeTab.codes != fixedLitCodeTab.codes) {
+    gfree(litCodeTab.codes);
+  }
   litCodeTab.codes = NULL;
-  gfree(distCodeTab.codes);
+  if (distCodeTab.codes != fixedDistCodeTab.codes) {
+    gfree(distCodeTab.codes);
+  }
   distCodeTab.codes = NULL;
 
   // read block header
@@ -3501,28 +4112,10 @@ err:
 }
 
 void FlateStream::loadFixedCodes() {
-  int i;
-
-  // build the literal code table
-  for (i = 0; i <= 143; ++i) {
-    codeLengths[i] = 8;
-  }
-  for (i = 144; i <= 255; ++i) {
-    codeLengths[i] = 9;
-  }
-  for (i = 256; i <= 279; ++i) {
-    codeLengths[i] = 7;
-  }
-  for (i = 280; i <= 287; ++i) {
-    codeLengths[i] = 8;
-  }
-  compHuffmanCodes(codeLengths, flateMaxLitCodes, &litCodeTab);
-
-  // build the distance code table
-  for (i = 0; i < flateMaxDistCodes; ++i) {
-    codeLengths[i] = 5;
-  }
-  compHuffmanCodes(codeLengths, flateMaxDistCodes, &distCodeTab);
+  litCodeTab.codes = fixedLitCodeTab.codes;
+  litCodeTab.maxLen = fixedLitCodeTab.maxLen;
+  distCodeTab.codes = fixedDistCodeTab.codes;
+  distCodeTab.maxLen = fixedDistCodeTab.maxLen;
 }
 
 GBool FlateStream::readDynamicCodes() {
@@ -3640,7 +4233,7 @@ void FlateStream::compHuffmanCodes(int *lengths, int n, FlateHuffmanTab *tab) {
 
   // allocate the table
   tabSize = 1 << tab->maxLen;
-  tab->codes = (FlateCode *)gmalloc(tabSize * sizeof(FlateCode));
+  tab->codes = (FlateCode *)gmallocn(tabSize, sizeof(FlateCode));
 
   // clear the table
   for (i = 0; i < tabSize; ++i) {
index 0f78e62..f21e311 100644 (file)
@@ -2,7 +2,7 @@
 //
 // config.h
 //
-// Copyright 1996-2004 Glyph & Cog, LLC
+// Copyright 1996-2005 Glyph & Cog, LLC
 //
 //========================================================================
 
 //------------------------------------------------------------------------
 
 // xpdf version
-#define xpdfVersion         "3.00"
-#define xpdfVersionNum      3.00
-#define xpdfMajorVersion    3
-#define xpdfMinorVersion    0
-#define xpdfMajorVersionStr "3"
-#define xpdfMinorVersionStr "0"
+#define xpdfVersion          "3.01"
+#define xpdfVersionNum       3.01
+#define xpdfMajorVersion     3
+#define xpdfMinorVersion     1
+#define xpdfUpdateVersion    0
+#define xpdfMajorVersionStr  "3"
+#define xpdfMinorVersionStr  "1"
+#define xpdfUpdateVersionStr "0"
 
 // supported PDF version
 #define supportedPDFVersionStr "1.5"
 #define supportedPDFVersionNum 1.5
 
 // copyright notice
-#define xpdfCopyright "Copyright 1996-2004 Glyph & Cog, LLC"
+#define xpdfCopyright "Copyright 1996-2005 Glyph & Cog, LLC"
 
 // Windows resource file stuff
-#define winxpdfVersion "WinXpdf 3.00"
-#define xpdfCopyrightAmp "Copyright 1996-2004 Glyph && Cog, LLC"
+#define winxpdfVersion "WinXpdf 3.01"
+#define xpdfCopyrightAmp "Copyright 1996-2005 Glyph && Cog, LLC"
 
 //------------------------------------------------------------------------
 // paper size
index b433aeb..10a4226 100644 (file)
 #include <stdio.h>
 #include <stdlib.h>
 #include <stddef.h>
-#include "./aconf.h"
 #if defined(WIN32)
 #  include <sys/stat.h>
 #  ifdef FPTEX
 #    include <win32lib.h>
 #  else
 #    include <windows.h>
-#    include <winbase.h>
 #  endif
 #elif defined(ACORN)
 #elif defined(MACOS)