]> www.fi.muni.cz Git - evince.git/blobdiff - pdf/xpdf/PSOutputDev.cc
Imported Xpdf 2.03 and fixed build.
[evince.git] / pdf / xpdf / PSOutputDev.cc
index 7bef193e82db1581ffa804587ab41bc8e0c27941..34d7fdc96bf406addfbca1f48710743ab3c57e30 100644 (file)
@@ -27,7 +27,6 @@
 #include "Gfx.h"
 #include "GfxState.h"
 #include "GfxFont.h"
-#include "CharCodeToUnicode.h"
 #include "UnicodeMap.h"
 #include "FontFile.h"
 #include "Catalog.h"
 static char *prolog[] = {
   "/xpdf 75 dict def xpdf begin",
   "% PDF special state",
-  "/pdfDictSize 14 def",
+  "/pdfDictSize 15 def",
+  "~1",
+  "/pdfStates 64 array def",
+  "  0 1 63 {",
+  "    pdfStates exch pdfDictSize dict",
+  "    dup /pdfStateIdx 3 index put",
+  "    put",
+  "  } for",
+  "~a",
   "/pdfSetup {",
   "  3 1 roll 2 array astore",
   "  /setpagedevice where {",
@@ -62,8 +69,19 @@ static char *prolog[] = {
   "    pop pop",
   "  } ifelse",
   "} def",
+  "~1",
+  "/pdfOpNames [",
+  "  /pdfFill /pdfStroke /pdfLastFill /pdfLastStroke",
+  "  /pdfTextMat /pdfFontSize /pdfCharSpacing /pdfTextRender",
+  "  /pdfTextRise /pdfWordSpacing /pdfHorizScaling /pdfTextClipPath",
+  "] def",
+  "~a",
   "/pdfStartPage {",
+  "~1",
+  "  pdfStates 0 get begin",
+  "~2",
   "  pdfDictSize dict begin",
+  "~a",
   "  /pdfFill [0] def",
   "  /pdfStroke [0] def",
   "  /pdfLastFill false def",
@@ -75,6 +93,7 @@ static char *prolog[] = {
   "  /pdfTextRise 0 def",
   "  /pdfWordSpacing 0 def",
   "  /pdfHorizScaling 1 def",
+  "  /pdfTextClipPath [] def",
   "} def",
   "/pdfEndPage { end } def",
   "% separation convention operators",
@@ -191,7 +210,16 @@ static char *prolog[] = {
   "  } ifelse",
   "} def",
   "% graphics state operators",
+  "~1",
+  "/q {",
+  "  gsave",
+  "  pdfOpNames length 1 sub -1 0 { pdfOpNames exch get load } for",
+  "  pdfStates pdfStateIdx 1 add get begin",
+  "  pdfOpNames { exch def } forall",
+  "} def",
+  "~2",
   "/q { gsave pdfDictSize dict begin } def",
+  "~a",
   "/Q { end grestore } def",
   "/cm { concat } def",
   "/d { setdash } def",
@@ -248,56 +276,100 @@ static char *prolog[] = {
   "/Td { pdfTextMat transform moveto } def",
   "/Tm { /pdfTextMat exch def } def",
   "% text string operators",
-  "/awcp { % awidthcharpath",
+  "/cshow where {",
+  "  pop",
+  "  /cshow2 {",
+  "    dup {",
+  "      pop pop",
+  "      1 string dup 0 3 index put 3 index exec",
+  "    } exch cshow",
+  "    pop pop",
+  "  } def",
+  "}{",
+  "  /cshow2 {",
+  "    currentfont /FontType get 0 eq {",
+  "      0 2 2 index length 1 sub {",
+  "        2 copy get exch 1 add 2 index exch get",
+  "        2 copy exch 256 mul add",
+  "        2 string dup 0 6 5 roll put dup 1 5 4 roll put",
+  "        3 index exec",
+  "      } for",
+  "    } {",
+  "      dup {",
+  "        1 string dup 0 3 index put 3 index exec",
+  "      } forall",
+  "    } ifelse",
+  "    pop pop",
+  "  } def",
+  "} ifelse",
+  "/awcp {", // awidthcharpath
   "  exch {",
-  "    1 string dup 0 3 index put 2 index charpath",
-  "    3 index 3 index rmoveto",
-  "    4 index eq { 5 index 5 index rmoveto } if",
-  "  } forall",
+  "    false charpath",
+  "    5 index 5 index rmoveto",
+  "    6 index eq { 7 index 7 index rmoveto } if",
+  "  } exch cshow2",
   "  6 {pop} repeat",
   "} def",
-  "/Tj { fCol",  // because stringwidth has to draw Type 3 chars
-  "      0 pdfTextRise pdfTextMat dtransform rmoveto",
-  "      1 index stringwidth pdfTextMat idtransform pop",
-  "      sub 1 index length dup 0 ne { div } { pop pop 0 } ifelse",
-  "      pdfWordSpacing pdfHorizScaling mul 0 pdfTextMat dtransform 32",
-  "      4 3 roll pdfCharSpacing pdfHorizScaling mul add 0",
-  "      pdfTextMat dtransform",
-  "      6 5 roll",
-  "      currentpoint 8 2 roll",
-  "      pdfTextRender 1 and 0 eq {",
-  "        6 copy awidthshow",
-  "      } if",
-  "      pdfTextRender 3 and dup 1 eq exch 2 eq or {",
-  "        8 6 roll moveto",
-  "        currentfont /FontType get 3 eq { fCol } { sCol } ifelse",
-  "        false awcp currentpoint stroke moveto",
-  "      } {",
-  "        8 {pop} repeat",
-  "      } ifelse",
-  "      0 pdfTextRise neg pdfTextMat dtransform rmoveto } def",
-  "/Tj16 { pdfTextRender 1 and 0 eq { fCol } { sCol } ifelse",
-  "        0 pdfTextRise pdfTextMat dtransform rmoveto",
-  "        2 index stringwidth pdfTextMat idtransform pop",
-  "        sub exch div",
-  "        pdfWordSpacing pdfHorizScaling mul 0 pdfTextMat dtransform 32",
-  "        4 3 roll pdfCharSpacing pdfHorizScaling mul add 0",
-  "        pdfTextMat dtransform",
-  "        6 5 roll awidthshow",
-  "        0 pdfTextRise neg pdfTextMat dtransform rmoveto } def",
-  "/Tj16V { pdfTextRender 1 and 0 eq { fCol } { sCol } ifelse",
-  "         0 pdfTextRise pdfTextMat dtransform rmoveto",
-  "         2 index stringwidth pdfTextMat idtransform exch pop",
-  "         sub exch div",
-  "         0 pdfWordSpacing pdfTextMat dtransform 32",
-  "         4 3 roll pdfCharSpacing add 0 exch",
-  "         pdfTextMat dtransform",
-  "         6 5 roll awidthshow",
-  "         0 pdfTextRise neg pdfTextMat dtransform rmoveto } def",
+  "/Tj {",
+  "  fCol",  // because stringwidth has to draw Type 3 chars
+  "  1 index stringwidth pdfTextMat idtransform pop",
+  "  sub 1 index length dup 0 ne { div } { pop pop 0 } ifelse",
+  "  pdfWordSpacing pdfHorizScaling mul 0 pdfTextMat dtransform 32",
+  "  4 3 roll pdfCharSpacing pdfHorizScaling mul add 0",
+  "  pdfTextMat dtransform",
+  "  6 5 roll Tj1",
+  "} def",
+  "/Tj16 {",
+  "  fCol",  // because stringwidth has to draw Type 3 chars
+  "  2 index stringwidth pdfTextMat idtransform pop",
+  "  sub exch div",
+  "  pdfWordSpacing pdfHorizScaling mul 0 pdfTextMat dtransform 32",
+  "  4 3 roll pdfCharSpacing pdfHorizScaling mul add 0",
+  "  pdfTextMat dtransform",
+  "  6 5 roll Tj1",
+  "} def",
+  "/Tj16V {",
+  "  fCol",  // because stringwidth has to draw Type 3 chars
+  "  2 index stringwidth pdfTextMat idtransform exch pop",
+  "  sub exch div",
+  "  0 pdfWordSpacing pdfTextMat dtransform 32",
+  "  4 3 roll pdfCharSpacing add 0 exch",
+  "  pdfTextMat dtransform",
+  "  6 5 roll Tj1",
+  "} def",
+  "/Tj1 {",
+  "  0 pdfTextRise pdfTextMat dtransform rmoveto",
+  "  currentpoint 8 2 roll",
+  "  pdfTextRender 1 and 0 eq {",
+  "    6 copy awidthshow",
+  "  } if",
+  "  pdfTextRender 3 and dup 1 eq exch 2 eq or {",
+  "    7 index 7 index moveto",
+  "    6 copy",
+  "    currentfont /FontType get 3 eq { fCol } { sCol } ifelse",
+  "    false awcp currentpoint stroke moveto",
+  "  } if",
+  "  pdfTextRender 4 and 0 ne {",
+  "    8 6 roll moveto",
+  "    false awcp",
+  "    /pdfTextClipPath [ pdfTextClipPath aload pop",
+  "      {/moveto cvx}",
+  "      {/lineto cvx}",
+  "      {/curveto cvx}",
+  "      {/closepath cvx}",
+  "    pathforall ] def",
+  "    currentpoint newpath moveto",
+  "  } {",
+  "    8 {pop} repeat",
+  "  } ifelse",
+  "  0 pdfTextRise neg pdfTextMat dtransform rmoveto",
+  "} def",
   "/TJm { pdfFontSize 0.001 mul mul neg 0",
   "       pdfTextMat dtransform rmoveto } def",
   "/TJmV { pdfFontSize 0.001 mul mul neg 0 exch",
   "        pdfTextMat dtransform rmoveto } def",
+  "/Tclip { pdfTextClipPath cvx exec clip",
+  "         /pdfTextClipPath [] def } def",
   "% Level 1 image operators",
   "/pdfIm1 {",
   "  /pdfImBuf1 4 index string def",
@@ -500,10 +572,17 @@ static void outputToFile(void *stream, char *data, int len) {
 }
 
 PSOutputDev::PSOutputDev(char *fileName, XRef *xrefA, Catalog *catalog,
-                        int firstPage, int lastPage, PSOutMode modeA) {
+                        int firstPage, int lastPage, PSOutMode modeA,
+                        int paperWidthA, int paperHeightA,
+                        GBool manualCtrlA) {
   FILE *f;
   PSFileType fileTypeA;
 
+  underlayCbk = NULL;
+  underlayCbkData = NULL;
+  overlayCbk = NULL;
+  overlayCbkData = NULL;
+
   fontIDs = NULL;
   fontFileIDs = NULL;
   fontFileNames = NULL;
@@ -511,6 +590,7 @@ PSOutputDev::PSOutputDev(char *fileName, XRef *xrefA, Catalog *catalog,
   xobjStack = NULL;
   embFontList = NULL;
   customColors = NULL;
+  haveTextClip = gFalse;
   t3String = NULL;
 
   // open file or pipe
@@ -543,12 +623,15 @@ PSOutputDev::PSOutputDev(char *fileName, XRef *xrefA, Catalog *catalog,
   }
 
   init(outputToFile, f, fileTypeA,
-       xrefA, catalog, firstPage, lastPage, modeA);
+       xrefA, catalog, firstPage, lastPage, modeA,
+       paperWidthA, paperHeightA, manualCtrlA);
 }
 
 PSOutputDev::PSOutputDev(PSOutputFunc outputFuncA, void *outputStreamA,
                         XRef *xrefA, Catalog *catalog,
-                        int firstPage, int lastPage, PSOutMode modeA) {
+                        int firstPage, int lastPage, PSOutMode modeA,
+                        int paperWidthA, int paperHeightA,
+                        GBool manualCtrlA) {
   fontIDs = NULL;
   fontFileIDs = NULL;
   fontFileNames = NULL;
@@ -556,23 +639,20 @@ PSOutputDev::PSOutputDev(PSOutputFunc outputFuncA, void *outputStreamA,
   xobjStack = NULL;
   embFontList = NULL;
   customColors = NULL;
+  haveTextClip = gFalse;
   t3String = NULL;
 
   init(outputFuncA, outputStreamA, psGeneric,
-       xrefA, catalog, firstPage, lastPage, modeA);
+       xrefA, catalog, firstPage, lastPage, modeA,
+       paperWidthA, paperHeightA, manualCtrlA);
 }
 
 void PSOutputDev::init(PSOutputFunc outputFuncA, void *outputStreamA,
                       PSFileType fileTypeA, XRef *xrefA, Catalog *catalog,
-                      int firstPage, int lastPage, PSOutMode modeA) {
+                      int firstPage, int lastPage, PSOutMode modeA,
+                      int paperWidthA, int paperHeightA,
+                      GBool manualCtrlA) {
   Page *page;
-  PDFRectangle *box;
-  Dict *resDict;
-  Annots *annots;
-  char **p;
-  int pg;
-  Object obj1, obj2;
-  int i;
 
   // initialize
   ok = gTrue;
@@ -582,13 +662,20 @@ void PSOutputDev::init(PSOutputFunc outputFuncA, void *outputStreamA,
   xref = xrefA;
   level = globalParams->getPSLevel();
   mode = modeA;
-  paperWidth = globalParams->getPSPaperWidth();
-  paperHeight = globalParams->getPSPaperHeight();
+  paperWidth = paperWidthA;
+  paperHeight = paperHeightA;
+  if (paperWidth == 0) {
+    paperWidth = globalParams->getPSPaperWidth();
+  }
+  if (paperHeight == 0) {
+    paperHeight = globalParams->getPSPaperHeight();
+  }
   if (paperWidth < 0 || paperHeight < 0) {
     page = catalog->getPage(firstPage);
     paperWidth = (int)(page->getWidth() + 0.5);
     paperHeight = (int)(page->getHeight() + 0.5);
   }
+  manualCtrl = manualCtrlA;
   if (mode == psModeForm) {
     lastPage = firstPage;
   }
@@ -611,14 +698,95 @@ void PSOutputDev::init(PSOutputFunc outputFuncA, void *outputStreamA,
   fontFileNameSize = 64;
   fontFileNameLen = 0;
   fontFileNames = (GString **)gmalloc(fontFileNameSize * sizeof(GString *));
+  nextTrueTypeNum = 0;
   font16EncLen = 0;
   font16EncSize = 0;
+
   xobjStack = new GList();
+  numSaves = 0;
 
   // initialize embedded font resource comment list
   embFontList = new GString();
 
-  // write header
+  if (!manualCtrl) {
+    writeHeader(firstPage, lastPage, catalog->getPage(firstPage)->getBox());
+    if (mode != psModeForm) {
+      writePS("%%BeginProlog\n");
+    }
+    writeXpdfProcset();
+    if (mode != psModeForm) {
+      writePS("%%EndProlog\n");
+      writePS("%%BeginSetup\n");
+    }
+    writeDocSetup(catalog, firstPage, lastPage);
+    if (mode != psModeForm) {
+      writePS("%%EndSetup\n");
+    }
+  }
+
+  // initialize sequential page number
+  seqPage = 1;
+}
+
+PSOutputDev::~PSOutputDev() {
+  PSOutCustomColor *cc;
+  int i;
+
+  if (ok) {
+    if (!manualCtrl) {
+      writePS("%%Trailer\n");
+      writeTrailer();
+      if (mode != psModeForm) {
+       writePS("%%EOF\n");
+      }
+    }
+    if (fileType == psFile) {
+#ifdef MACOS
+      ICS_MapRefNumAndAssign((short)((FILE *)outputStream)->handle);
+#endif
+      fclose((FILE *)outputStream);
+    }
+#ifdef HAVE_POPEN
+    else if (fileType == psPipe) {
+      pclose((FILE *)outputStream);
+#ifndef WIN32
+      signal(SIGPIPE, (SignalFunc)SIG_DFL);
+#endif
+    }
+#endif
+  }
+  if (embFontList) {
+    delete embFontList;
+  }
+  if (fontIDs) {
+    gfree(fontIDs);
+  }
+  if (fontFileIDs) {
+    gfree(fontFileIDs);
+  }
+  if (fontFileNames) {
+    for (i = 0; i < fontFileNameLen; ++i) {
+      delete fontFileNames[i];
+    }
+    gfree(fontFileNames);
+  }
+  if (font16Enc) {
+    for (i = 0; i < font16EncLen; ++i) {
+      delete font16Enc[i].enc;
+    }
+    gfree(font16Enc);
+  }
+  if (xobjStack) {
+    delete xobjStack;
+  }
+  while (customColors) {
+    cc = customColors;
+    customColors = cc->next;
+    delete cc;
+  }
+}
+
+void PSOutputDev::writeHeader(int firstPage, int lastPage, PDFRectangle *box) {
   switch (mode) {
   case psModePS:
     writePS("%!PS-Adobe-3.0\n");
@@ -633,6 +801,7 @@ void PSOutputDev::init(PSOutputFunc outputFuncA, void *outputStreamA,
     writePS("%%DocumentSuppliedResources: (atend)\n");
     writePSFmt("%%%%DocumentMedia: plain %d %d 0 () ()\n",
               paperWidth, paperHeight);
+    writePSFmt("%%%%BoundingBox: 0 0 %d %d\n", paperWidth, paperHeight);
     writePSFmt("%%%%Pages: %d\n", lastPage - firstPage + 1);
     writePS("%%EndComments\n");
     writePS("%%BeginDefaults\n");
@@ -649,8 +818,6 @@ void PSOutputDev::init(PSOutputFunc outputFuncA, void *outputStreamA,
       writePS("%%DocumentProcessColors: (atend)\n");
       writePS("%%DocumentCustomColors: (atend)\n");
     }
-    page = catalog->getPage(firstPage);
-    box = page->getBox();
     writePSFmt("%%%%BoundingBox: %d %d %d %d\n",
               (int)floor(box->x1), (int)floor(box->y1),
               (int)ceil(box->x2), (int)ceil(box->y2));
@@ -676,8 +843,6 @@ void PSOutputDev::init(PSOutputFunc outputFuncA, void *outputStreamA,
     }
     writePS("%%DocumentSuppliedResources: (atend)\n");
     writePS("%%EndComments\n");
-    page = catalog->getPage(firstPage);
-    box = page->getBox();
     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);
@@ -685,31 +850,48 @@ void PSOutputDev::init(PSOutputFunc outputFuncA, void *outputStreamA,
     writePS("/Matrix [1 0 0 1 0 0] def\n");
     break;
   }
+}
+
+void PSOutputDev::writeXpdfProcset() {
+  char prologLevel;
+  char **p;
 
-  // write prolog
-  if (mode != psModeForm) {
-    writePS("%%BeginProlog\n");
-  }
   writePSFmt("%%%%BeginResource: procset xpdf %s 0\n", xpdfVersion);
+  prologLevel = 'a';
   for (p = prolog; *p; ++p) {
-    writePSFmt("%s\n", *p);
+    if ((*p)[0] == '~' && (*p)[1] == '1') {
+      prologLevel = '1';
+    } else if ((*p)[0] == '~' && (*p)[1] == '2') {
+      prologLevel = '2';
+    } else if ((*p)[0] == '~' && (*p)[1] == 'a') {
+      prologLevel = 'a';
+    } else if (prologLevel == 'a' ||
+              (prologLevel == '1' && level < psLevel2) ||
+              (prologLevel == '2' && level >= psLevel2)) {
+      writePSFmt("%s\n", *p);
+    }
   }
   writePS("%%EndResource\n");
+
   if (level >= psLevel3) {
     for (p = cmapProlog; *p; ++p) {
       writePSFmt("%s\n", *p);
     }
   }
-  if (mode != psModeForm) {
-    writePS("%%EndProlog\n");
-  }
+}
+
+void PSOutputDev::writeDocSetup(Catalog *catalog,
+                               int firstPage, int lastPage) {
+  Page *page;
+  Dict *resDict;
+  Annots *annots;
+  Object obj1, obj2;
+  int pg, i;
 
-  // set up fonts and images
   if (mode == psModeForm) {
     // swap the form and xpdf dicts
     writePS("xpdf end begin dup begin\n");
   } else {
-    writePS("%%BeginSetup\n");
     writePS("xpdf begin\n");
   }
   for (pg = firstPage; pg <= lastPage; ++pg) {
@@ -732,7 +914,7 @@ void PSOutputDev::init(PSOutputFunc outputFuncA, void *outputStreamA,
     delete annots;
   }
   if (mode != psModeForm) {
-    if (mode != psModeEPS) {
+    if (mode != psModeEPS && !manualCtrl) {
       writePSFmt("%d %d %s pdfSetup\n",
                 paperWidth, paperHeight,
                 globalParams->getPSDuplex() ? "true" : "false");
@@ -742,97 +924,51 @@ void PSOutputDev::init(PSOutputFunc outputFuncA, void *outputStreamA,
       writePS("/opiMatrix matrix currentmatrix def\n");
     }
 #endif
-    writePS("%%EndSetup\n");
   }
+}
 
-  // initialize sequential page number
-  seqPage = 1;
+void PSOutputDev::writePageTrailer() {
+  if (mode != psModeForm) {
+    writePS("pdfEndPage\n");
+  }
 }
 
-PSOutputDev::~PSOutputDev() {
+void PSOutputDev::writeTrailer() {
   PSOutCustomColor *cc;
-  int i;
 
-  if (ok) {
-    if (mode == psModeForm) {
-      writePS("/Foo exch /Form defineresource pop\n");
-    } else {
-      writePS("%%Trailer\n");
-      writePS("end\n");
-      writePS("%%DocumentSuppliedResources:\n");
-      writePS(embFontList->getCString());
-      if (level == psLevel1Sep || level == psLevel2Sep ||
-         level == psLevel3Sep) {
-         writePS("%%DocumentProcessColors:");
-         if (processColors & psProcessCyan) {
-          writePS(" Cyan");
-        }
-         if (processColors & psProcessMagenta) {
-          writePS(" Magenta");
-        }
-         if (processColors & psProcessYellow) {
-          writePS(" Yellow");
-        }
-         if (processColors & psProcessBlack) {
-          writePS(" Black");
-        }
-         writePS("\n");
-         writePS("%%DocumentCustomColors:");
-        for (cc = customColors; cc; cc = cc->next) {
-          writePSFmt(" (%s)", cc->name->getCString());
+  if (mode == psModeForm) {
+    writePS("/Foo exch /Form defineresource pop\n");
+  } else {
+    writePS("end\n");
+    writePS("%%DocumentSuppliedResources:\n");
+    writePS(embFontList->getCString());
+    if (level == psLevel1Sep || level == psLevel2Sep ||
+       level == psLevel3Sep) {
+      writePS("%%DocumentProcessColors:");
+      if (processColors & psProcessCyan) {
+       writePS(" Cyan");
         }
-         writePS("\n");
-         writePS("%%CMYKCustomColor:\n");
-        for (cc = customColors; cc; cc = cc->next) {
-          writePSFmt("%%%%+ %g %g %g %g (%s)\n",
+      if (processColors & psProcessMagenta) {
+       writePS(" Magenta");
+      }
+      if (processColors & psProcessYellow) {
+       writePS(" Yellow");
+      }
+      if (processColors & psProcessBlack) {
+       writePS(" Black");
+      }
+      writePS("\n");
+      writePS("%%DocumentCustomColors:");
+      for (cc = customColors; cc; cc = cc->next) {
+       writePSFmt(" (%s)", cc->name->getCString());
+      }
+      writePS("\n");
+      writePS("%%CMYKCustomColor:\n");
+      for (cc = customColors; cc; cc = cc->next) {
+       writePSFmt("%%%%+ %g %g %g %g (%s)\n",
                   cc->c, cc->m, cc->y, cc->k, cc->name->getCString());
-        }
       }
-      writePS("%%EOF\n");
-    }
-    if (fileType == psFile) {
-#ifdef MACOS
-      ICS_MapRefNumAndAssign((short)((FILE *)outputStream)->handle);
-#endif
-      fclose((FILE *)outputStream);
-    }
-#ifdef HAVE_POPEN
-    else if (fileType == psPipe) {
-      pclose((FILE *)outputStream);
-#ifndef WIN32
-      signal(SIGPIPE, (SignalFunc)SIG_DFL);
-#endif
     }
-#endif
-  }
-  if (embFontList) {
-    delete embFontList;
-  }
-  if (fontIDs) {
-    gfree(fontIDs);
-  }
-  if (fontFileIDs) {
-    gfree(fontFileIDs);
-  }
-  if (fontFileNames) {
-    for (i = 0; i < fontFileNameLen; ++i) {
-      delete fontFileNames[i];
-    }
-    gfree(fontFileNames);
-  }
-  if (font16Enc) {
-    for (i = 0; i < font16EncLen; ++i) {
-      delete font16Enc[i].enc;
-    }
-    gfree(font16Enc);
-  }
-  if (xobjStack) {
-    delete xobjStack;
-  }
-  while (customColors) {
-    cc = customColors;
-    customColors = cc->next;
-    delete cc;
   }
 }
 
@@ -888,29 +1024,39 @@ void PSOutputDev::setupResources(Dict *resDict) {
 }
 
 void PSOutputDev::setupFonts(Dict *resDict) {
-  Object fontDict;
+  Object obj1, obj2;
+  Ref r;
   GfxFontDict *gfxFontDict;
   GfxFont *font;
   int i;
 
-  resDict->lookup("Font", &fontDict);
-  if (fontDict.isDict()) {
-    gfxFontDict = new GfxFontDict(xref, fontDict.getDict());
+  gfxFontDict = NULL;
+  resDict->lookupNF("Font", &obj1);
+  if (obj1.isRef()) {
+    obj1.fetch(xref, &obj2);
+    if (obj2.isDict()) {
+      r = obj1.getRef();
+      gfxFontDict = new GfxFontDict(xref, &r, obj2.getDict());
+    }
+    obj2.free();
+  } else if (obj1.isDict()) {
+    gfxFontDict = new GfxFontDict(xref, NULL, obj1.getDict());
+  }
+  if (gfxFontDict) {
     for (i = 0; i < gfxFontDict->getNumFonts(); ++i) {
       font = gfxFontDict->getFont(i);
       setupFont(font, resDict);
     }
     delete gfxFontDict;
   }
-  fontDict.free();
+  obj1.free();
 }
 
 void PSOutputDev::setupFont(GfxFont *font, Dict *parentResDict) {
   Ref fontFileID;
   GString *name;
   PSFontParam *fontParam;
-  GString *psNameStr;
-  char *psName;
+  GString *psName;
   char type3Name[64], buf[16];
   GBool subst;
   UnicodeMap *uMap;
@@ -937,28 +1083,25 @@ void PSOutputDev::setupFont(GfxFont *font, Dict *parentResDict) {
   fontIDs[fontIDLen++] = *font->getID();
 
   xs = ys = 1;
-  psNameStr = NULL;
   subst = gFalse;
 
   // check for resident 8-bit font
   if (font->getName() &&
       (fontParam = globalParams->getPSFont(font->getName()))) {
-    psName = fontParam->psFontName->getCString();
+    psName = new GString(fontParam->psFontName->getCString());
 
   // check for embedded Type 1 font
   } else if (globalParams->getPSEmbedType1() &&
             font->getType() == fontType1 &&
             font->getEmbeddedFontID(&fontFileID)) {
-    psNameStr = filterPSName(font->getEmbeddedFontName());
-    psName = psNameStr->getCString();
+    psName = filterPSName(font->getEmbeddedFontName());
     setupEmbeddedType1Font(&fontFileID, psName);
 
   // check for embedded Type 1C font
   } else if (globalParams->getPSEmbedType1() &&
             font->getType() == fontType1C &&
             font->getEmbeddedFontID(&fontFileID)) {
-    psNameStr = filterPSName(font->getEmbeddedFontName());
-    psName = psNameStr->getCString();
+    psName = filterPSName(font->getEmbeddedFontName());
     setupEmbeddedType1CFont(font, &fontFileID, psName);
 
   // check for external Type 1 font file
@@ -966,45 +1109,41 @@ void PSOutputDev::setupFont(GfxFont *font, Dict *parentResDict) {
             font->getType() == fontType1 &&
             font->getExtFontFile()) {
     // this assumes that the PS font name matches the PDF font name
-    psName = font->getName()->getCString();
+    psName = font->getName()->copy();
     setupExternalType1Font(font->getExtFontFile(), psName);
 
   // check for embedded TrueType font
   } else if (globalParams->getPSEmbedTrueType() &&
             font->getType() == fontTrueType &&
             font->getEmbeddedFontID(&fontFileID)) {
-    psNameStr = filterPSName(font->getEmbeddedFontName());
-    psName = psNameStr->getCString();
+    psName = filterPSName(font->getEmbeddedFontName());
     setupEmbeddedTrueTypeFont(font, &fontFileID, psName);
 
   // check for external TrueType font file
   } else if (globalParams->getPSEmbedTrueType() &&
             font->getType() == fontTrueType &&
             font->getExtFontFile()) {
-    psNameStr = filterPSName(font->getName());
-    psName = psNameStr->getCString();
+    psName = filterPSName(font->getName());
     setupExternalTrueTypeFont(font, psName);
 
   // check for embedded CID PostScript font
   } else if (globalParams->getPSEmbedCIDPostScript() &&
             font->getType() == fontCIDType0C &&
             font->getEmbeddedFontID(&fontFileID)) {
-    psNameStr = filterPSName(font->getEmbeddedFontName());
-    psName = psNameStr->getCString();
+    psName = filterPSName(font->getEmbeddedFontName());
     setupEmbeddedCIDType0Font(font, &fontFileID, psName);
 
   // check for embedded CID TrueType font
   } else if (globalParams->getPSEmbedCIDTrueType() &&
             font->getType() == fontCIDType2 &&
             font->getEmbeddedFontID(&fontFileID)) {
-    psNameStr = filterPSName(font->getEmbeddedFontName());
-    psName = psNameStr->getCString();
+    psName = filterPSName(font->getEmbeddedFontName());
     setupEmbeddedCIDTrueTypeFont(font, &fontFileID, psName);
 
   } else if (font->getType() == fontType3) {
     sprintf(type3Name, "T3_%d_%d",
            font->getID()->num, font->getID()->gen);
-    psName = type3Name;
+    psName = new GString(type3Name);
     setupType3Font(font, psName, parentResDict);
 
   // do 8-bit font substitution
@@ -1015,7 +1154,7 @@ void PSOutputDev::setupFont(GfxFont *font, Dict *parentResDict) {
     if (name) {
       for (i = 0; psFonts[i]; ++i) {
        if (name->cmp(psFonts[i]) == 0) {
-         psName = psFonts[i];
+         psName = new GString(psFonts[i]);
          break;
        }
       }
@@ -1034,7 +1173,7 @@ void PSOutputDev::setupFont(GfxFont *font, Dict *parentResDict) {
       if (font->isItalic()) {
        i += 1;
       }
-      psName = psSubstFonts[i].psName;
+      psName = new GString(psSubstFonts[i].psName);
       for (code = 0; code < 256; ++code) {
        if ((charName = ((Gfx8BitFont *)font)->getCharName(code)) &&
            charName[0] == 'm' && charName[1] == '\0') {
@@ -1072,7 +1211,7 @@ void PSOutputDev::setupFont(GfxFont *font, Dict *parentResDict) {
                            ((GfxCIDFont *)font)->getCollection(),
                            font->getWMode()))) {
     subst = gTrue;
-    psName = fontParam->psFontName->getCString();
+    psName = fontParam->psFontName->copy();
     if (font16EncLen >= font16EncSize) {
       font16EncSize += 16;
       font16Enc = (PSFont16Enc *)grealloc(font16Enc,
@@ -1102,16 +1241,17 @@ void PSOutputDev::setupFont(GfxFont *font, Dict *parentResDict) {
   if (font->isCIDFont()) {
     if (level == psLevel3 || level == psLevel3Sep) {
       writePSFmt("/F%d_%d /%s %d pdfMakeFont16L3\n",
-                font->getID()->num, font->getID()->gen, psName,
+                font->getID()->num, font->getID()->gen, psName->getCString(),
                 font->getWMode());
     } else {
       writePSFmt("/F%d_%d /%s %d pdfMakeFont16\n",
-                font->getID()->num, font->getID()->gen, psName,
+                font->getID()->num, font->getID()->gen, psName->getCString(),
                 font->getWMode());
     }
   } else {
     writePSFmt("/F%d_%d /%s %g %g\n",
-              font->getID()->num, font->getID()->gen, psName, xs, ys);
+              font->getID()->num, font->getID()->gen, psName->getCString(),
+              xs, ys);
     for (i = 0; i < 256; i += 8) {
       writePSFmt((i == 0) ? "[ " : "  ");
       for (j = 0; j < 8; ++j) {
@@ -1136,16 +1276,14 @@ void PSOutputDev::setupFont(GfxFont *font, Dict *parentResDict) {
     writePS("pdfMakeFont\n");
   }
 
-  if (psNameStr) {
-    delete psNameStr;
-  }
+  delete psName;
 }
 
-void PSOutputDev::setupEmbeddedType1Font(Ref *id, char *psName) {
+void PSOutputDev::setupEmbeddedType1Font(Ref *id, GString *psName) {
   static char hexChar[17] = "0123456789abcdef";
-  Object refObj, strObj, obj1, obj2;
+  Object refObj, strObj, obj1, obj2, obj3;
   Dict *dict;
-  int length1, length2;
+  int length1, length2, length3;
   int c;
   int start[4];
   GBool binMode;
@@ -1179,21 +1317,25 @@ void PSOutputDev::setupEmbeddedType1Font(Ref *id, char *psName) {
   }
   dict->lookup("Length1", &obj1);
   dict->lookup("Length2", &obj2);
-  if (!obj1.isInt() || !obj2.isInt()) {
+  dict->lookup("Length3", &obj3);
+  if (!obj1.isInt() || !obj2.isInt() || !obj3.isInt()) {
     error(-1, "Missing length fields in embedded font stream dictionary");
     obj1.free();
     obj2.free();
+    obj3.free();
     goto err1;
   }
   length1 = obj1.getInt();
   length2 = obj2.getInt();
+  length3 = obj3.getInt();
   obj1.free();
   obj2.free();
+  obj3.free();
 
   // beginning comment
-  writePSFmt("%%%%BeginResource: font %s\n", psName);
+  writePSFmt("%%%%BeginResource: font %s\n", psName->getCString());
   embFontList->append("%%+ font ");
-  embFontList->append(psName);
+  embFontList->append(psName->getCString());
   embFontList->append("\n");
 
   // copy ASCII portion of font
@@ -1222,6 +1364,9 @@ void PSOutputDev::setupEmbeddedType1Font(Ref *id, char *psName) {
       writePSChar(hexChar[(start[i] >> 4) & 0x0f]);
       writePSChar(hexChar[start[i] & 0x0f]);
     }
+    // if Length2 is incorrect (too small), font data gets chopped, so
+    // we take a few extra characters from the trailer just in case
+    length2 += length3 >= 8 ? 8 : length3;
     while (i < length2) {
       if ((c = strObj.streamGetChar()) == EOF) {
        break;
@@ -1266,7 +1411,7 @@ void PSOutputDev::setupEmbeddedType1Font(Ref *id, char *psName) {
 
 //~ This doesn't handle .pfb files or binary eexec data (which only
 //~ happens in pfb files?).
-void PSOutputDev::setupExternalType1Font(GString *fileName, char *psName) {
+void PSOutputDev::setupExternalType1Font(GString *fileName, GString *psName) {
   FILE *fontFile;
   int c;
   int i;
@@ -1287,9 +1432,9 @@ void PSOutputDev::setupExternalType1Font(GString *fileName, char *psName) {
   fontFileNames[fontFileNameLen++] = fileName->copy();
 
   // beginning comment
-  writePSFmt("%%%%BeginResource: font %s\n", psName);
+  writePSFmt("%%%%BeginResource: font %s\n", psName->getCString());
   embFontList->append("%%+ font ");
-  embFontList->append(psName);
+  embFontList->append(psName->getCString());
   embFontList->append("\n");
 
   // copy the font file
@@ -1307,7 +1452,7 @@ void PSOutputDev::setupExternalType1Font(GString *fileName, char *psName) {
 }
 
 void PSOutputDev::setupEmbeddedType1CFont(GfxFont *font, Ref *id,
-                                         char *psName) {
+                                         GString *psName) {
   char *fontBuf;
   int fontLen;
   Type1CFontFile *t1cFile;
@@ -1328,9 +1473,9 @@ void PSOutputDev::setupEmbeddedType1CFont(GfxFont *font, Ref *id,
   fontFileIDs[fontFileIDLen++] = *id;
 
   // beginning comment
-  writePSFmt("%%%%BeginResource: font %s\n", psName);
+  writePSFmt("%%%%BeginResource: font %s\n", psName->getCString());
   embFontList->append("%%+ font ");
-  embFontList->append(psName);
+  embFontList->append(psName->getCString());
   embFontList->append("\n");
 
   // convert it to a Type 1 font
@@ -1347,42 +1492,49 @@ void PSOutputDev::setupEmbeddedType1CFont(GfxFont *font, Ref *id,
 }
 
 void PSOutputDev::setupEmbeddedTrueTypeFont(GfxFont *font, Ref *id,
-                                           char *psName) {
+                                           GString *psName) {
+  char unique[32];
   char *fontBuf;
   int fontLen;
   TrueTypeFontFile *ttFile;
-  CharCodeToUnicode *ctu;
+  Gushort *codeToGID;
   int i;
 
   // check if font is already embedded
   for (i = 0; i < fontFileIDLen; ++i) {
     if (fontFileIDs[i].num == id->num &&
-       fontFileIDs[i].gen == id->gen)
-      return;
+       fontFileIDs[i].gen == id->gen) {
+      sprintf(unique, "_%d", nextTrueTypeNum++);
+      psName->append(unique);
+      break;
+    }
   }
 
   // add entry to fontFileIDs list
-  if (fontFileIDLen >= fontFileIDSize) {
-    fontFileIDSize += 64;
-    fontFileIDs = (Ref *)grealloc(fontFileIDs, fontFileIDSize * sizeof(Ref));
+  if (i == fontFileIDLen) {
+    if (fontFileIDLen >= fontFileIDSize) {
+      fontFileIDSize += 64;
+      fontFileIDs = (Ref *)grealloc(fontFileIDs, fontFileIDSize * sizeof(Ref));
+    }
+    fontFileIDs[fontFileIDLen++] = *id;
   }
-  fontFileIDs[fontFileIDLen++] = *id;
 
   // beginning comment
-  writePSFmt("%%%%BeginResource: font %s\n", psName);
+  writePSFmt("%%%%BeginResource: font %s\n", psName->getCString());
   embFontList->append("%%+ font ");
-  embFontList->append(psName);
+  embFontList->append(psName->getCString());
   embFontList->append("\n");
 
   // convert it to a Type 42 font
   fontBuf = font->readEmbFontFile(xref, &fontLen);
   ttFile = new TrueTypeFontFile(fontBuf, fontLen);
-  ctu = ((Gfx8BitFont *)font)->getToUnicode();
-  ttFile->convertToType42(psName, ((Gfx8BitFont *)font)->getEncoding(),
-                         ctu, ((Gfx8BitFont *)font)->getHasEncoding(),
-                         ((Gfx8BitFont *)font)->isSymbolic(),
+  codeToGID = ((Gfx8BitFont *)font)->getCodeToGIDMap(ttFile);
+  ttFile->convertToType42(psName->getCString(),
+                         ((Gfx8BitFont *)font)->getEncoding(),
+                         ((Gfx8BitFont *)font)->getHasEncoding(),
+                         codeToGID,
                          outputFunc, outputStream);
-  ctu->decRefCnt();
+  gfree(codeToGID);
   delete ttFile;
   gfree(fontBuf);
 
@@ -1390,45 +1542,51 @@ void PSOutputDev::setupEmbeddedTrueTypeFont(GfxFont *font, Ref *id,
   writePS("%%EndResource\n");
 }
 
-void PSOutputDev::setupExternalTrueTypeFont(GfxFont *font, char *psName) {
+void PSOutputDev::setupExternalTrueTypeFont(GfxFont *font, GString *psName) {
+  char unique[32];
   GString *fileName;
   char *fontBuf;
   int fontLen;
   TrueTypeFontFile *ttFile;
-  CharCodeToUnicode *ctu;
+  Gushort *codeToGID;
   int i;
 
   // check if font is already embedded
   fileName = font->getExtFontFile();
   for (i = 0; i < fontFileNameLen; ++i) {
     if (!fontFileNames[i]->cmp(fileName)) {
-      return;
+      sprintf(unique, "_%d", nextTrueTypeNum++);
+      psName->append(unique);
+      break;
     }
   }
 
   // add entry to fontFileNames list
-  if (fontFileNameLen >= fontFileNameSize) {
-    fontFileNameSize += 64;
-    fontFileNames = (GString **)grealloc(fontFileNames,
-                                        fontFileNameSize * sizeof(GString *));
+  if (i == fontFileNameLen) {
+    if (fontFileNameLen >= fontFileNameSize) {
+      fontFileNameSize += 64;
+      fontFileNames =
+       (GString **)grealloc(fontFileNames,
+                            fontFileNameSize * sizeof(GString *));
+    }
   }
   fontFileNames[fontFileNameLen++] = fileName->copy();
 
   // beginning comment
-  writePSFmt("%%%%BeginResource: font %s\n", psName);
+  writePSFmt("%%%%BeginResource: font %s\n", psName->getCString());
   embFontList->append("%%+ font ");
-  embFontList->append(psName);
+  embFontList->append(psName->getCString());
   embFontList->append("\n");
 
   // convert it to a Type 42 font
   fontBuf = font->readExtFontFile(&fontLen);
   ttFile = new TrueTypeFontFile(fontBuf, fontLen);
-  ctu = ((Gfx8BitFont *)font)->getToUnicode();
-  ttFile->convertToType42(psName, ((Gfx8BitFont *)font)->getEncoding(),
-                         ctu, ((Gfx8BitFont *)font)->getHasEncoding(),
-                         ((Gfx8BitFont *)font)->isSymbolic(),
+  codeToGID = ((Gfx8BitFont *)font)->getCodeToGIDMap(ttFile);
+  ttFile->convertToType42(psName->getCString(),
+                         ((Gfx8BitFont *)font)->getEncoding(),
+                         ((Gfx8BitFont *)font)->getHasEncoding(),
+                         codeToGID,
                          outputFunc, outputStream);
-  ctu->decRefCnt();
   delete ttFile;
   gfree(fontBuf);
 
@@ -1437,7 +1595,7 @@ void PSOutputDev::setupExternalTrueTypeFont(GfxFont *font, char *psName) {
 }
 
 void PSOutputDev::setupEmbeddedCIDType0Font(GfxFont *font, Ref *id,
-                                           char *psName) {
+                                           GString *psName) {
   char *fontBuf;
   int fontLen;
   Type1CFontFile *t1cFile;
@@ -1458,9 +1616,9 @@ void PSOutputDev::setupEmbeddedCIDType0Font(GfxFont *font, Ref *id,
   fontFileIDs[fontFileIDLen++] = *id;
 
   // beginning comment
-  writePSFmt("%%%%BeginResource: font %s\n", psName);
+  writePSFmt("%%%%BeginResource: font %s\n", psName->getCString());
   embFontList->append("%%+ font ");
-  embFontList->append(psName);
+  embFontList->append(psName->getCString());
   embFontList->append("\n");
 
   // convert it to a Type 0 font
@@ -1469,10 +1627,11 @@ void PSOutputDev::setupEmbeddedCIDType0Font(GfxFont *font, Ref *id,
   if (t1cFile->isOk()) {
     if (globalParams->getPSLevel() >= psLevel3) {
       // Level 3: use a CID font
-      t1cFile->convertToCIDType0(psName, outputFunc, outputStream);
+      t1cFile->convertToCIDType0(psName->getCString(),
+                                outputFunc, outputStream);
     } else {
       // otherwise: use a non-CID composite font
-      t1cFile->convertToType0(psName, outputFunc, outputStream);
+      t1cFile->convertToType0(psName->getCString(), outputFunc, outputStream);
     }
   }
   delete t1cFile;
@@ -1483,7 +1642,7 @@ void PSOutputDev::setupEmbeddedCIDType0Font(GfxFont *font, Ref *id,
 }
 
 void PSOutputDev::setupEmbeddedCIDTrueTypeFont(GfxFont *font, Ref *id,
-                                              char *psName) {
+                                              GString *psName) {
   char *fontBuf;
   int fontLen;
   TrueTypeFontFile *ttFile;
@@ -1504,22 +1663,23 @@ void PSOutputDev::setupEmbeddedCIDTrueTypeFont(GfxFont *font, Ref *id,
   fontFileIDs[fontFileIDLen++] = *id;
 
   // beginning comment
-  writePSFmt("%%%%BeginResource: font %s\n", psName);
+  writePSFmt("%%%%BeginResource: font %s\n", psName->getCString());
   embFontList->append("%%+ font ");
-  embFontList->append(psName);
+  embFontList->append(psName->getCString());
   embFontList->append("\n");
 
   // convert it to a Type 0 font
   fontBuf = font->readEmbFontFile(xref, &fontLen);
   ttFile = new TrueTypeFontFile(fontBuf, fontLen);
   if (globalParams->getPSLevel() >= psLevel3) {
-    ttFile->convertToCIDType2(psName,
+    ttFile->convertToCIDType2(psName->getCString(),
                              ((GfxCIDFont *)font)->getCIDToGID(),
                              ((GfxCIDFont *)font)->getCIDToGIDLen(),
                              outputFunc, outputStream);
   } else {
     // otherwise: use a non-CID composite font
-    ttFile->convertToType0(psName, ((GfxCIDFont *)font)->getCIDToGID(),
+    ttFile->convertToType0(psName->getCString(),
+                          ((GfxCIDFont *)font)->getCIDToGID(),
                           ((GfxCIDFont *)font)->getCIDToGIDLen(),
                           outputFunc, outputStream);
   }
@@ -1530,7 +1690,7 @@ void PSOutputDev::setupEmbeddedCIDTrueTypeFont(GfxFont *font, Ref *id,
   writePS("%%EndResource\n");
 }
 
-void PSOutputDev::setupType3Font(GfxFont *font, char *psName,
+void PSOutputDev::setupType3Font(GfxFont *font, GString *psName,
                                 Dict *parentResDict) {
   Dict *resDict;
   Dict *charProcs;
@@ -1543,15 +1703,17 @@ void PSOutputDev::setupType3Font(GfxFont *font, char *psName,
 
   // set up resources used by font
   if ((resDict = ((Gfx8BitFont *)font)->getResources())) {
+    inType3Char = gTrue;
     setupResources(resDict);
+    inType3Char = gFalse;
   } else {
     resDict = parentResDict;
   }
 
   // beginning comment
-  writePSFmt("%%%%BeginResource: font %s\n", psName);
+  writePSFmt("%%%%BeginResource: font %s\n", psName->getCString());
   embFontList->append("%%+ font ");
-  embFontList->append(psName);
+  embFontList->append(psName->getCString());
   embFontList->append("\n");
 
   // font dictionary
@@ -1611,7 +1773,7 @@ void PSOutputDev::setupType3Font(GfxFont *font, char *psName,
     writePS("end\n");
   }
   writePS("currentdict end\n");
-  writePSFmt("/%s exch definefont pop\n", psName);
+  writePSFmt("/%s exch definefont pop\n", psName->getCString());
 
   // ending comment
   writePS("%%EndResource\n");
@@ -1621,7 +1783,7 @@ void PSOutputDev::setupImages(Dict *resDict) {
   Object xObjDict, xObj, xObjRef, subtypeObj;
   int i;
 
-  if (mode != psModeForm) {
+  if (!(mode == psModeForm || inType3Char)) {
     return;
   }
 
@@ -1690,6 +1852,7 @@ void PSOutputDev::setupImage(Ref id, Stream *str) {
   } while (c != '~' && c != EOF);
   ++size;
   writePSFmt("%d array dup /ImData_%d_%d exch def\n", size, id.num, id.gen);
+  str->close();
 
   // write the data into the array
   str->reset();
@@ -1732,12 +1895,13 @@ void PSOutputDev::setupImage(Ref id, Stream *str) {
   } while (c != '~' && c != EOF);
   writePS("~> put\n");
   writePS("pop\n");
+  str->close();
 
   delete str;
 }
 
 void PSOutputDev::startPage(int pageNum, GfxState *state) {
-  int x1, y1, x2, y2, width, height, t;
+  int x1, y1, x2, y2, width, height, paperWidth2, paperHeight2;
 
 
   switch (mode) {
@@ -1761,9 +1925,8 @@ void PSOutputDev::startPage(int pageNum, GfxState *state) {
       writePS("90 rotate\n");
       tx = -x1;
       ty = -(y1 + paperWidth);
-      t = width;
-      width = height;
-      height = t;
+      paperWidth2 = paperHeight;
+      paperHeight2 = paperWidth;
     } else {
       landscape = gFalse;
       writePSFmt("%%%%PageOrientation: %s\n",
@@ -1771,19 +1934,21 @@ void PSOutputDev::startPage(int pageNum, GfxState *state) {
       writePS("pdfStartPage\n");
       tx = -x1;
       ty = -y1;
+      paperWidth2 = paperWidth;
+      paperHeight2 = paperHeight;
     }
-    if (width < paperWidth) {
-      tx += (paperWidth - width) / 2;
+    if (width < paperWidth2) {
+      tx += (paperWidth2 - width) / 2;
     }
-    if (height < paperHeight) {
-      ty += (paperHeight - height) / 2;
+    if (height < paperHeight2) {
+      ty += (paperHeight2 - height) / 2;
     }
     if (tx != 0 || ty != 0) {
       writePSFmt("%g %g translate\n", tx, ty);
     }
-    if (width > paperWidth || height > paperHeight) {
-      xScale = (double)paperWidth / (double)width;
-      yScale = (double)paperHeight / (double)height;
+    if (width > paperWidth2 || height > paperHeight2) {
+      xScale = (double)paperWidth2 / (double)width;
+      yScale = (double)paperHeight2 / (double)height;
       if (yScale < xScale) {
        xScale = yScale;
       } else {
@@ -1814,9 +1979,17 @@ void PSOutputDev::startPage(int pageNum, GfxState *state) {
     landscape = gFalse;
     break;
   }
+
+  if (underlayCbk) {
+    (*underlayCbk)(this, underlayCbkData);
+  }
 }
 
 void PSOutputDev::endPage() {
+  if (overlayCbk) {
+    (*overlayCbk)(this, overlayCbkData);
+  }
+
 
   if (mode == psModeForm) {
     writePS("pdfEndPage\n");
@@ -1824,18 +1997,22 @@ void PSOutputDev::endPage() {
     writePS("} def\n");
     writePS("end end\n");
   } else {
-    writePS("showpage\n");
-    writePS("%%PageTrailer\n");
-    writePS("pdfEndPage\n");
+    if (!manualCtrl) {
+      writePS("showpage\n");
+      writePS("%%PageTrailer\n");
+      writePageTrailer();
+    }
   }
 }
 
 void PSOutputDev::saveState(GfxState *state) {
   writePS("q\n");
+  ++numSaves;
 }
 
 void PSOutputDev::restoreState(GfxState *state) {
   writePS("Q\n");
+  --numSaves;
 }
 
 void PSOutputDev::updateCTM(GfxState *state, double m11, double m12,
@@ -2167,7 +2344,7 @@ void PSOutputDev::drawString(GfxState *state, GString *s) {
   int len, nChars, uLen, n, m, i, j;
 
   // check for invisible text -- this is used by Acrobat Capture
-  if ((state->getRender() & 3) == 3) {
+  if (state->getRender() == 3) {
     return;
   }
 
@@ -2254,6 +2431,17 @@ void PSOutputDev::drawString(GfxState *state, GString *s) {
   if (font->isCIDFont()) {
     delete s2;
   }
+
+  if (state->getRender() & 4) {
+    haveTextClip = gTrue;
+  }
+}
+
+void PSOutputDev::endTextObject(GfxState *state) {
+  if (haveTextClip) {
+    writePS("Tclip\n");
+    haveTextClip = gFalse;
+  }
 }
 
 void PSOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str,
@@ -2486,6 +2674,7 @@ void PSOutputDev::doImageL2(Object *ref, GfxImageColorMap *colorMap,
       } while (c != '~' && c != EOF);
       writePS("~>]\n");
       writePS("0\n");
+      str->close();
       delete str;
     } else {
       // set up to use the array already created by setupImages()
@@ -2541,7 +2730,8 @@ void PSOutputDev::doImageL2(Object *ref, GfxImageColorMap *colorMap,
 
     // data source
     writePS("  /DataSource currentfile\n");
-    s = str->getPSFilter("    ");
+    s = str->getPSFilter(level < psLevel2 ? 1 : level < psLevel3 ? 2 : 3,
+                        "    ");
     if (inlineImg || !s) {
       useRLE = gTrue;
       useASCII = gTrue;
@@ -2818,7 +3008,10 @@ void PSOutputDev::dumpColorSpaceL2(GfxColorSpace *colorSpace) {
       writePS("\n");
     }
     writePS(">]");
+#if 0 //~ this shouldn't be here since the PS file doesn't actually refer
+      //~ to this colorant (it's converted to CMYK instead)
     addCustomColor(separationCS);
+#endif
     break;
 
   case csDeviceN: