]> git.ipfire.org Git - thirdparty/cups.git/blobdiff - pdftops/PSOutputDev.cxx
Import CUPS 1.4svn-r7226.
[thirdparty/cups.git] / pdftops / PSOutputDev.cxx
diff --git a/pdftops/PSOutputDev.cxx b/pdftops/PSOutputDev.cxx
deleted file mode 100644 (file)
index 6c8abf0..0000000
+++ /dev/null
@@ -1,5040 +0,0 @@
-//========================================================================
-//
-// PSOutputDev.cc
-//
-// Copyright 1996-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#include <config.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma implementation
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <stddef.h>
-#include <stdarg.h>
-#include <signal.h>
-#include <math.h>
-#include "GString.h"
-#include "GList.h"
-#include "config.h"
-#include "GlobalParams.h"
-#include "Object.h"
-#include "Error.h"
-#include "Function.h"
-#include "Gfx.h"
-#include "GfxState.h"
-#include "GfxFont.h"
-#include "UnicodeMap.h"
-#include "FoFiType1C.h"
-#include "FoFiTrueType.h"
-#include "Catalog.h"
-#include "Page.h"
-#include "Stream.h"
-#include "Annot.h"
-#include "XRef.h"
-#include "PSOutputDev.h"
-
-#ifdef MACOS
-// needed for setting type/creator of MacOS files
-#include "ICSupport.h"
-#endif
-
-//------------------------------------------------------------------------
-// PostScript prolog and setup
-//------------------------------------------------------------------------
-
-// The '~' escapes mark prolog code that is emitted only in certain
-// levels:
-//
-//   ~[123][sn]
-//      ^   ^----- s=psLevel*Sep, n=psLevel*
-//      +----- 1=psLevel1*, 2=psLevel2*, 3=psLevel3*
-
-static char *prolog[] = {
-  "/xpdf 75 dict def xpdf begin",
-  "% PDF special state",
-  "/pdfDictSize 15 def",
-  "~1sn",
-  "/pdfStates 64 array def",
-  "  0 1 63 {",
-  "    pdfStates exch pdfDictSize dict",
-  "    dup /pdfStateIdx 3 index put",
-  "    put",
-  "  } for",
-  "~123sn",
-  "/pdfSetup {",
-  "  3 1 roll 2 array astore",
-  "  /setpagedevice where {",
-  "    pop 3 dict begin",
-  "      /PageSize exch def",
-  "      /ImagingBBox null def",
-  "      /Policies 1 dict dup begin /PageSize 3 def end def",
-  "      { /Duplex true def } if",
-  "    currentdict end setpagedevice",
-  "  } {",
-  "    pop pop",
-  "  } ifelse",
-  "} def",
-  "~1sn",
-  "/pdfOpNames [",
-  "  /pdfFill /pdfStroke /pdfLastFill /pdfLastStroke",
-  "  /pdfTextMat /pdfFontSize /pdfCharSpacing /pdfTextRender",
-  "  /pdfTextRise /pdfWordSpacing /pdfHorizScaling /pdfTextClipPath",
-  "] def",
-  "~123sn",
-  "/pdfStartPage {",
-  "~1sn",
-  "  pdfStates 0 get begin",
-  "~23sn",
-  "  pdfDictSize dict begin",
-  "~23n",
-  "  /pdfFillCS [] def",
-  "  /pdfFillXform {} def",
-  "  /pdfStrokeCS [] def",
-  "  /pdfStrokeXform {} def",
-  "~1n",
-  "  /pdfFill 0 def",
-  "  /pdfStroke 0 def",
-  "~1s",
-  "  /pdfFill [0 0 0 1] def",
-  "  /pdfStroke [0 0 0 1] def",
-  "~23sn",
-  "  /pdfFill [0] def",
-  "  /pdfStroke [0] def",
-  "  /pdfFillOP false def",
-  "  /pdfStrokeOP false def",
-  "~123sn",
-  "  /pdfLastFill false def",
-  "  /pdfLastStroke false def",
-  "  /pdfTextMat [1 0 0 1 0 0] def",
-  "  /pdfFontSize 0 def",
-  "  /pdfCharSpacing 0 def",
-  "  /pdfTextRender 0 def",
-  "  /pdfTextRise 0 def",
-  "  /pdfWordSpacing 0 def",
-  "  /pdfHorizScaling 1 def",
-  "  /pdfTextClipPath [] def",
-  "} def",
-  "/pdfEndPage { end } def",
-  "~23s",
-  "% separation convention operators",
-  "/findcmykcustomcolor where {",
-  "  pop",
-  "}{",
-  "  /findcmykcustomcolor { 5 array astore } def",
-  "} ifelse",
-  "/setcustomcolor where {",
-  "  pop",
-  "}{",
-  "  /setcustomcolor {",
-  "    exch",
-  "    [ exch /Separation exch dup 4 get exch /DeviceCMYK exch",
-  "      0 4 getinterval cvx",
-  "      [ exch /dup load exch { mul exch dup } /forall load",
-  "        /pop load dup ] cvx",
-  "    ] setcolorspace setcolor",
-  "  } def",
-  "} ifelse",
-  "/customcolorimage where {",
-  "  pop",
-  "}{",
-  "  /customcolorimage {",
-  "    gsave",
-  "    [ exch /Separation exch dup 4 get exch /DeviceCMYK exch",
-  "      0 4 getinterval",
-  "      [ exch /dup load exch { mul exch dup } /forall load",
-  "        /pop load dup ] cvx",
-  "    ] setcolorspace",
-  "    10 dict begin",
-  "      /ImageType 1 def",
-  "      /DataSource exch def",
-  "      /ImageMatrix exch def",
-  "      /BitsPerComponent exch def",
-  "      /Height exch def",
-  "      /Width exch def",
-  "      /Decode [1 0] def",
-  "    currentdict end",
-  "    image",
-  "    grestore",
-  "  } def",
-  "} ifelse",
-  "~123sn",
-  "% PDF color state",
-  "~1n",
-  "/g { dup /pdfFill exch def setgray",
-  "     /pdfLastFill true def /pdfLastStroke false def } def",
-  "/G { dup /pdfStroke exch def setgray",
-  "     /pdfLastStroke true def /pdfLastFill false def } def",
-  "/fCol {",
-  "  pdfLastFill not {",
-  "    pdfFill setgray",
-  "    /pdfLastFill true def /pdfLastStroke false def",
-  "  } if",
-  "} def",
-  "/sCol {",
-  "  pdfLastStroke not {",
-  "    pdfStroke setgray",
-  "    /pdfLastStroke true def /pdfLastFill false def",
-  "  } if",
-  "} def",
-  "~1s",
-  "/k { 4 copy 4 array astore /pdfFill exch def setcmykcolor",
-  "     /pdfLastFill true def /pdfLastStroke false def } def",
-  "/K { 4 copy 4 array astore /pdfStroke exch def setcmykcolor",
-  "     /pdfLastStroke true def /pdfLastFill false def } def",
-  "/fCol {",
-  "  pdfLastFill not {",
-  "    pdfFill aload pop setcmykcolor",
-  "    /pdfLastFill true def /pdfLastStroke false def",
-  "  } if",
-  "} def",
-  "/sCol {",
-  "  pdfLastStroke not {",
-  "    pdfStroke aload pop setcmykcolor",
-  "    /pdfLastStroke true def /pdfLastFill false def",
-  "  } if",
-  "} def",
-  "~23n",
-  "/cs { /pdfFillXform exch def dup /pdfFillCS exch def",
-  "      setcolorspace } def",
-  "/CS { /pdfStrokeXform exch def dup /pdfStrokeCS exch def",
-  "      setcolorspace } def",
-  "/sc { pdfLastFill not { pdfFillCS setcolorspace } if",
-  "      dup /pdfFill exch def aload pop pdfFillXform setcolor",
-  "     /pdfLastFill true def /pdfLastStroke false def } def",
-  "/SC { pdfLastStroke not { pdfStrokeCS setcolorspace } if",
-  "      dup /pdfStroke exch def aload pop pdfStrokeXform setcolor",
-  "     /pdfLastStroke true def /pdfLastFill false def } def",
-  "/op { /pdfFillOP exch def",
-  "      pdfLastFill { pdfFillOP setoverprint } if } def",
-  "/OP { /pdfStrokeOP exch def",
-  "      pdfLastStroke { pdfStrokeOP setoverprint } if } def",
-  "/fCol {",
-  "  pdfLastFill not {",
-  "    pdfFillCS setcolorspace",
-  "    pdfFill aload pop pdfFillXform setcolor",
-  "    pdfFillOP setoverprint",
-  "    /pdfLastFill true def /pdfLastStroke false def",
-  "  } if",
-  "} def",
-  "/sCol {",
-  "  pdfLastStroke not {",
-  "    pdfStrokeCS setcolorspace",
-  "    pdfStroke aload pop pdfStrokeXform setcolor",
-  "    pdfStrokeOP setoverprint",
-  "    /pdfLastStroke true def /pdfLastFill false def",
-  "  } if",
-  "} def",
-  "~23s",
-  "/k { 4 copy 4 array astore /pdfFill exch def setcmykcolor",
-  "     /pdfLastFill true def /pdfLastStroke false def } def",
-  "/K { 4 copy 4 array astore /pdfStroke exch def setcmykcolor",
-  "     /pdfLastStroke true def /pdfLastFill false def } def",
-  "/ck { 6 copy 6 array astore /pdfFill exch def",
-  "      findcmykcustomcolor exch setcustomcolor",
-  "      /pdfLastFill true def /pdfLastStroke false def } def",
-  "/CK { 6 copy 6 array astore /pdfStroke exch def",
-  "      findcmykcustomcolor exch setcustomcolor",
-  "      /pdfLastStroke true def /pdfLastFill false def } def",
-  "/op { /pdfFillOP exch def",
-  "      pdfLastFill { pdfFillOP setoverprint } if } def",
-  "/OP { /pdfStrokeOP exch def",
-  "      pdfLastStroke { pdfStrokeOP setoverprint } if } def",
-  "/fCol {",
-  "  pdfLastFill not {",
-  "    pdfFill aload length 4 eq {",
-  "      setcmykcolor",
-  "    }{",
-  "      findcmykcustomcolor exch setcustomcolor",
-  "    } ifelse",
-  "    pdfFillOP setoverprint",
-  "    /pdfLastFill true def /pdfLastStroke false def",
-  "  } if",
-  "} def",
-  "/sCol {",
-  "  pdfLastStroke not {",
-  "    pdfStroke aload length 4 eq {",
-  "      setcmykcolor",
-  "    }{",
-  "      findcmykcustomcolor exch setcustomcolor",
-  "    } ifelse",
-  "    pdfStrokeOP setoverprint",
-  "    /pdfLastStroke true def /pdfLastFill false def",
-  "  } if",
-  "} def",
-  "~123sn",
-  "% build a font",
-  "/pdfMakeFont {",
-  "  4 3 roll findfont",
-  "  4 2 roll matrix scale makefont",
-  "  dup length dict begin",
-  "    { 1 index /FID ne { def } { pop pop } ifelse } forall",
-  "    /Encoding exch def",
-  "    currentdict",
-  "  end",
-  "  definefont pop",
-  "} def",
-  "/pdfMakeFont16 {",
-  "  exch findfont",
-  "  dup length dict begin",
-  "    { 1 index /FID ne { def } { pop pop } ifelse } forall",
-  "    /WMode exch def",
-  "    currentdict",
-  "  end",
-  "  definefont pop",
-  "} def",
-  "~3sn",
-  "/pdfMakeFont16L3 {",
-  "  1 index /CIDFont resourcestatus {",
-  "    pop pop 1 index /CIDFont findresource /CIDFontType known",
-  "  } {",
-  "    false",
-  "  } ifelse",
-  "  {",
-  "    0 eq { /Identity-H } { /Identity-V } ifelse",
-  "    exch 1 array astore composefont pop",
-  "  } {",
-  "    pdfMakeFont16",
-  "  } ifelse",
-  "} def",
-  "~123sn",
-  "% graphics state operators",
-  "~1sn",
-  "/q {",
-  "  gsave",
-  "  pdfOpNames length 1 sub -1 0 { pdfOpNames exch get load } for",
-  "  pdfStates pdfStateIdx 1 add get begin",
-  "  pdfOpNames { exch def } forall",
-  "} def",
-  "/Q { end grestore } def",
-  "~23sn",
-  "/q { gsave pdfDictSize dict begin } def",
-  "/Q {",
-  "  end grestore",
-  "  /pdfLastFill where {",
-  "    pop",
-  "    pdfLastFill {",
-  "      pdfFillOP setoverprint",
-  "    } {",
-  "      pdfStrokeOP setoverprint",
-  "    } ifelse",
-  "  } if",
-  "} def",
-  "~123sn",
-  "/cm { concat } def",
-  "/d { setdash } def",
-  "/i { setflat } def",
-  "/j { setlinejoin } def",
-  "/J { setlinecap } def",
-  "/M { setmiterlimit } def",
-  "/w { setlinewidth } def",
-  "% path segment operators",
-  "/m { moveto } def",
-  "/l { lineto } def",
-  "/c { curveto } def",
-  "/re { 4 2 roll moveto 1 index 0 rlineto 0 exch rlineto",
-  "      neg 0 rlineto closepath } def",
-  "/h { closepath } def",
-  "% path painting operators",
-  "/S { sCol stroke } def",
-  "/Sf { fCol stroke } def",
-  "/f { fCol fill } def",
-  "/f* { fCol eofill } def",
-  "% clipping operators",
-  "/W { clip newpath } def",
-  "/W* { eoclip newpath } def",
-  "% text state operators",
-  "/Tc { /pdfCharSpacing exch def } def",
-  "/Tf { dup /pdfFontSize exch def",
-  "      dup pdfHorizScaling mul exch matrix scale",
-  "      pdfTextMat matrix concatmatrix dup 4 0 put dup 5 0 put",
-  "      exch findfont exch makefont setfont } def",
-  "/Tr { /pdfTextRender exch def } def",
-  "/Ts { /pdfTextRise exch def } def",
-  "/Tw { /pdfWordSpacing exch def } def",
-  "/Tz { /pdfHorizScaling exch def } def",
-  "% text positioning operators",
-  "/Td { pdfTextMat transform moveto } def",
-  "/Tm { /pdfTextMat exch def } def",
-  "% text string operators",
-  "/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 {",
-  "    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
-  "  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 newpath",
-  "         /pdfTextClipPath [] def } def",
-  "~1ns",
-  "% Level 1 image operators",
-  "~1n",
-  "/pdfIm1 {",
-  "  /pdfImBuf1 4 index string def",
-  "  { currentfile pdfImBuf1 readhexstring pop } image",
-  "} def",
-  "~1s",
-  "/pdfIm1Sep {",
-  "  /pdfImBuf1 4 index string def",
-  "  /pdfImBuf2 4 index string def",
-  "  /pdfImBuf3 4 index string def",
-  "  /pdfImBuf4 4 index string def",
-  "  { currentfile pdfImBuf1 readhexstring pop }",
-  "  { currentfile pdfImBuf2 readhexstring pop }",
-  "  { currentfile pdfImBuf3 readhexstring pop }",
-  "  { currentfile pdfImBuf4 readhexstring pop }",
-  "  true 4 colorimage",
-  "} def",
-  "~1ns",
-  "/pdfImM1 {",
-  "  fCol /pdfImBuf1 4 index 7 add 8 idiv string def",
-  "  { currentfile pdfImBuf1 readhexstring pop } imagemask",
-  "} def",
-  "/pdfImM1a {",
-  "  { 2 copy get exch 1 add exch } imagemask",
-  "  pop pop",
-  "} def",
-  "~23sn",
-  "% Level 2 image operators",
-  "/pdfImBuf 100 string def",
-  "/pdfIm {",
-  "  image",
-  "  { currentfile pdfImBuf readline",
-  "    not { pop exit } if",
-  "    (%-EOD-) eq { exit } if } loop",
-  "} def",
-  "~23s",
-  "/pdfImSep {",
-  "  findcmykcustomcolor exch",
-  "  dup /Width get /pdfImBuf1 exch string def",
-  "  dup /Decode get aload pop 1 index sub /pdfImDecodeRange exch def",
-  "  /pdfImDecodeLow exch def",
-  "  begin Width Height BitsPerComponent ImageMatrix DataSource end",
-  "  /pdfImData exch def",
-  "  { pdfImData pdfImBuf1 readstring pop",
-  "    0 1 2 index length 1 sub {",
-  "      1 index exch 2 copy get",
-  "      pdfImDecodeRange mul 255 div pdfImDecodeLow add round cvi",
-  "      255 exch sub put",
-  "    } for }",
-  "  6 5 roll customcolorimage",
-  "  { currentfile pdfImBuf readline",
-  "    not { pop exit } if",
-  "    (%-EOD-) eq { exit } if } loop",
-  "} def",
-  "~23sn",
-  "/pdfImM {",
-  "  fCol imagemask",
-  "  { currentfile pdfImBuf readline",
-  "    not { pop exit } if",
-  "    (%-EOD-) eq { exit } if } loop",
-  "} def",
-  "/pdfImClip {",
-  "  gsave",
-  "  0 2 4 index length 1 sub {",
-  "    dup 4 index exch 2 copy",
-  "    get 5 index div put",
-  "    1 add 3 index exch 2 copy",
-  "    get 3 index div put",
-  "  } for",
-  "  pop pop rectclip",
-  "} def",
-  "/pdfImClipEnd { grestore } def",
-  "~23n",
-  "% shading operators",
-  "/colordelta {",
-  "  false 0 1 3 index length 1 sub {",
-  "    dup 4 index exch get 3 index 3 2 roll get sub abs 0.004 gt {",
-  "      pop true",
-  "    } if",
-  "  } for",
-  "  exch pop exch pop",
-  "} def",
-  "/funcCol { func n array astore } def",
-  "/funcSH {",
-  "  dup 0 eq {",
-  "    true",
-  "  } {",
-  "    dup 6 eq {",
-  "      false",
-  "    } {",
-  "      4 index 4 index funcCol dup",
-  "      6 index 4 index funcCol dup",
-  "      3 1 roll colordelta 3 1 roll",
-  "      5 index 5 index funcCol dup",
-  "      3 1 roll colordelta 3 1 roll",
-  "      6 index 8 index funcCol dup",
-  "      3 1 roll colordelta 3 1 roll",
-  "      colordelta or or or",
-  "    } ifelse",
-  "  } ifelse",
-  "  {",
-  "    1 add",
-  "    4 index 3 index add 0.5 mul exch 4 index 3 index add 0.5 mul exch",
-  "    6 index 6 index 4 index 4 index 4 index funcSH",
-  "    2 index 6 index 6 index 4 index 4 index funcSH",
-  "    6 index 2 index 4 index 6 index 4 index funcSH",
-  "    5 3 roll 3 2 roll funcSH pop pop",
-  "  } {",
-  "    pop 3 index 2 index add 0.5 mul 3 index  2 index add 0.5 mul",
-  "    funcCol sc",
-  "    dup 4 index exch mat transform m",
-  "    3 index 3 index mat transform l",
-  "    1 index 3 index mat transform l",
-  "    mat transform l pop pop h f*",
-  "  } ifelse",
-  "} def",
-  "/axialCol {",
-  "  dup 0 lt {",
-  "    pop t0",
-  "  } {",
-  "    dup 1 gt {",
-  "      pop t1",
-  "    } {",
-  "      dt mul t0 add",
-  "    } ifelse",
-  "  } ifelse",
-  "  func n array astore",
-  "} def",
-  "/axialSH {",
-  "  dup 0 eq {",
-  "    true",
-  "  } {",
-  "    dup 8 eq {",
-  "      false",
-  "    } {",
-  "      2 index axialCol 2 index axialCol colordelta",
-  "    } ifelse",
-  "  } ifelse",
-  "  {",
-  "    1 add 3 1 roll 2 copy add 0.5 mul",
-  "    dup 4 3 roll exch 4 index axialSH",
-  "    exch 3 2 roll axialSH",
-  "  } {",
-  "    pop 2 copy add 0.5 mul axialCol sc",
-  "    exch dup dx mul x0 add exch dy mul y0 add",
-  "    3 2 roll dup dx mul x0 add exch dy mul y0 add",
-  "    dx abs dy abs ge {",
-  "      2 copy yMin sub dy mul dx div add yMin m",
-  "      yMax sub dy mul dx div add yMax l",
-  "      2 copy yMax sub dy mul dx div add yMax l",
-  "      yMin sub dy mul dx div add yMin l",
-  "      h f*",
-  "    } {",
-  "      exch 2 copy xMin sub dx mul dy div add xMin exch m",
-  "      xMax sub dx mul dy div add xMax exch l",
-  "      exch 2 copy xMax sub dx mul dy div add xMax exch l",
-  "      xMin sub dx mul dy div add xMin exch l",
-  "      h f*",
-  "    } ifelse",
-  "  } ifelse",
-  "} def",
-  "/radialCol {",
-  "  dup t0 lt {",
-  "    pop t0",
-  "  } {",
-  "    dup t1 gt {",
-  "      pop t1",
-  "    } if",
-  "  } ifelse",
-  "  func n array astore",
-  "} def",
-  "/radialSH {",
-  "  dup 0 eq {",
-  "    true",
-  "  } {",
-  "    dup 8 eq {",
-  "      false",
-  "    } {",
-  "      2 index dt mul t0 add radialCol",
-  "      2 index dt mul t0 add radialCol colordelta",
-  "    } ifelse",
-  "  } ifelse",
-  "  {",
-  "    1 add 3 1 roll 2 copy add 0.5 mul",
-  "    dup 4 3 roll exch 4 index radialSH",
-  "    exch 3 2 roll radialSH",
-  "  } {",
-  "    pop 2 copy add 0.5 mul dt mul t0 add axialCol sc",
-  "    exch dup dx mul x0 add exch dup dy mul y0 add exch dr mul r0 add",
-  "    0 360 arc h",
-  "    dup dx mul x0 add exch dup dy mul y0 add exch dr mul r0 add",
-  "    0 360 arc h f*",
-  "  } ifelse",
-  "} def",
-  "~123sn",
-  "end",
-  NULL
-};
-
-static char *cmapProlog[] = {
-  "/CIDInit /ProcSet findresource begin",
-  "10 dict begin",
-  "  begincmap",
-  "  /CMapType 1 def",
-  "  /CMapName /Identity-H def",
-  "  /CIDSystemInfo 3 dict dup begin",
-  "    /Registry (Adobe) def",
-  "    /Ordering (Identity) def",
-  "    /Supplement 0 def",
-  "  end def",
-  "  1 begincodespacerange",
-  "    <0000> <ffff>",
-  "  endcodespacerange",
-  "  0 usefont",
-  "  1 begincidrange",
-  "    <0000> <ffff> 0",
-  "  endcidrange",
-  "  endcmap",
-  "  currentdict CMapName exch /CMap defineresource pop",
-  "end",
-  "10 dict begin",
-  "  begincmap",
-  "  /CMapType 1 def",
-  "  /CMapName /Identity-V def",
-  "  /CIDSystemInfo 3 dict dup begin",
-  "    /Registry (Adobe) def",
-  "    /Ordering (Identity) def",
-  "    /Supplement 0 def",
-  "  end def",
-  "  /WMode 1 def",
-  "  1 begincodespacerange",
-  "    <0000> <ffff>",
-  "  endcodespacerange",
-  "  0 usefont",
-  "  1 begincidrange",
-  "    <0000> <ffff> 0",
-  "  endcidrange",
-  "  endcmap",
-  "  currentdict CMapName exch /CMap defineresource pop",
-  "end",
-  "end",
-  NULL
-};
-
-//------------------------------------------------------------------------
-// Fonts
-//------------------------------------------------------------------------
-
-struct PSSubstFont {
-  char *psName;                        // PostScript name
-  double mWidth;               // width of 'm' character
-};
-
-static char *psFonts[] = {
-  "Courier",
-  "Courier-Bold",
-  "Courier-Oblique",
-  "Courier-BoldOblique",
-  "Helvetica",
-  "Helvetica-Bold",
-  "Helvetica-Oblique",
-  "Helvetica-BoldOblique",
-  "Symbol",
-  "Times-Roman",
-  "Times-Bold",
-  "Times-Italic",
-  "Times-BoldItalic",
-  "ZapfDingbats",
-  NULL
-};
-
-static PSSubstFont psSubstFonts[] = {
-  {"Helvetica",             0.833},
-  {"Helvetica-Oblique",     0.833},
-  {"Helvetica-Bold",        0.889},
-  {"Helvetica-BoldOblique", 0.889},
-  {"Times-Roman",           0.788},
-  {"Times-Italic",          0.722},
-  {"Times-Bold",            0.833},
-  {"Times-BoldItalic",      0.778},
-  {"Courier",               0.600},
-  {"Courier-Oblique",       0.600},
-  {"Courier-Bold",          0.600},
-  {"Courier-BoldOblique",   0.600}
-};
-
-// Encoding info for substitute 16-bit font
-struct PSFont16Enc {
-  Ref fontID;
-  GString *enc;
-};
-
-//------------------------------------------------------------------------
-// process colors
-//------------------------------------------------------------------------
-
-#define psProcessCyan     1
-#define psProcessMagenta  2
-#define psProcessYellow   4
-#define psProcessBlack    8
-#define psProcessCMYK    15
-
-//------------------------------------------------------------------------
-// PSOutCustomColor
-//------------------------------------------------------------------------
-
-class PSOutCustomColor {
-public:
-
-  PSOutCustomColor(double cA, double mA,
-                  double yA, double kA, GString *nameA);
-  ~PSOutCustomColor();
-
-  double c, m, y, k;
-  GString *name;
-  PSOutCustomColor *next;
-};
-
-PSOutCustomColor::PSOutCustomColor(double cA, double mA,
-                                  double yA, double kA, GString *nameA) {
-  c = cA;
-  m = mA;
-  y = yA;
-  k = kA;
-  name = nameA;
-  next = NULL;
-}
-
-PSOutCustomColor::~PSOutCustomColor() {
-  delete name;
-}
-
-//------------------------------------------------------------------------
-// DeviceNRecoder
-//------------------------------------------------------------------------
-
-class DeviceNRecoder: public FilterStream {
-public:
-
-  DeviceNRecoder(Stream *strA, int widthA, int heightA,
-                GfxImageColorMap *colorMapA);
-  virtual ~DeviceNRecoder();
-  virtual StreamKind getKind() { return strWeird; }
-  virtual void reset();
-  virtual int getChar()
-    { return (bufIdx >= bufSize && !fillBuf()) ? EOF : buf[bufIdx++]; }
-  virtual int lookChar()
-    { return (bufIdx >= bufSize && !fillBuf()) ? EOF : buf[bufIdx]; }
-  virtual GString *getPSFilter(int psLevel, char *indent) { return NULL; }
-  virtual GBool isBinary(GBool last = gTrue) { return gTrue; }
-  virtual GBool isEncoder() { return gTrue; }
-
-private:
-
-  GBool fillBuf();
-
-  int width, height;
-  GfxImageColorMap *colorMap;
-  Function *func;
-  ImageStream *imgStr;
-  int buf[gfxColorMaxComps];
-  int pixelIdx;
-  int bufIdx;
-  int bufSize;
-};
-
-DeviceNRecoder::DeviceNRecoder(Stream *strA, int widthA, int heightA,
-                              GfxImageColorMap *colorMapA):
-    FilterStream(strA) {
-  width = widthA;
-  height = heightA;
-  colorMap = colorMapA;
-  imgStr = NULL;
-  pixelIdx = 0;
-  bufIdx = gfxColorMaxComps;
-  bufSize = ((GfxDeviceNColorSpace *)colorMap->getColorSpace())->
-              getAlt()->getNComps();
-  func = ((GfxDeviceNColorSpace *)colorMap->getColorSpace())->
-           getTintTransformFunc();
-}
-
-DeviceNRecoder::~DeviceNRecoder() {
-  if (imgStr) {
-    delete imgStr;
-  }
-}
-
-void DeviceNRecoder::reset() {
-  imgStr = new ImageStream(str, width, colorMap->getNumPixelComps(),
-                          colorMap->getBits());
-  imgStr->reset();
-}
-
-GBool DeviceNRecoder::fillBuf() {
-  Guchar pixBuf[gfxColorMaxComps];
-  GfxColor color;
-  double x[gfxColorMaxComps], y[gfxColorMaxComps];
-  int i;
-
-  if (pixelIdx >= width * height) {
-    return gFalse;
-  }
-  imgStr->getPixel(pixBuf);
-  colorMap->getColor(pixBuf, &color);
-  for (i = 0;
-       i < ((GfxDeviceNColorSpace *)colorMap->getColorSpace())->getNComps();
-       ++i) {
-    x[i] = colToDbl(color.c[i]);
-  }
-  func->transform(x, y);
-  for (i = 0; i < bufSize; ++i) {
-    buf[i] = (int)(y[i] * 255 + 0.5);
-  }
-  bufIdx = 0;
-  ++pixelIdx;
-  return gTrue;
-}
-
-//------------------------------------------------------------------------
-// PSOutputDev
-//------------------------------------------------------------------------
-
-extern "C" {
-typedef void (*SignalFunc)(int);
-}
-
-static void outputToFile(void *stream, char *data, int len) {
-  fwrite(data, 1, len, (FILE *)stream);
-}
-
-PSOutputDev::PSOutputDev(char *fileName, XRef *xrefA, Catalog *catalog,
-                        int firstPage, int lastPage, PSOutMode modeA,
-                        int imgLLXA, int imgLLYA, int imgURXA, int imgURYA,
-                        GBool manualCtrlA, const char *pageRangesA) {
-  FILE *f;
-  PSFileType fileTypeA;
-
-  underlayCbk = NULL;
-  underlayCbkData = NULL;
-  overlayCbk = NULL;
-  overlayCbkData = NULL;
-
-  fontIDs = NULL;
-  fontFileIDs = NULL;
-  fontFileNames = NULL;
-  font16Enc = NULL;
-  xobjStack = NULL;
-  embFontList = NULL;
-  customColors = NULL;
-  haveTextClip = gFalse;
-  t3String = NULL;
-
-  // open file or pipe
-  if (!strcmp(fileName, "-")) {
-    fileTypeA = psStdout;
-    f = stdout;
-  } else if (fileName[0] == '|') {
-    fileTypeA = psPipe;
-#ifdef HAVE_POPEN
-#ifndef WIN32
-    signal(SIGPIPE, (SignalFunc)SIG_IGN);
-#endif
-    if (!(f = popen(fileName + 1, "w"))) {
-      error(-1, "Couldn't run print command '%s'", fileName);
-      ok = gFalse;
-      return;
-    }
-#else
-    error(-1, "Print commands are not supported ('%s')", fileName);
-    ok = gFalse;
-    return;
-#endif
-  } else {
-    fileTypeA = psFile;
-    if (!(f = fopen(fileName, "w"))) {
-      error(-1, "Couldn't open PostScript file '%s'", fileName);
-      ok = gFalse;
-      return;
-    }
-  }
-
-  init(outputToFile, f, fileTypeA,
-       xrefA, catalog, firstPage, lastPage, modeA,
-       imgLLXA, imgLLYA, imgURXA, imgURYA, manualCtrlA, pageRangesA);
-}
-
-PSOutputDev::PSOutputDev(PSOutputFunc outputFuncA, void *outputStreamA,
-                        XRef *xrefA, Catalog *catalog,
-                        int firstPage, int lastPage, PSOutMode modeA,
-                        int imgLLXA, int imgLLYA, int imgURXA, int imgURYA,
-                        GBool manualCtrlA, const char *pageRangesA) {
-  underlayCbk = NULL;
-  underlayCbkData = NULL;
-  overlayCbk = NULL;
-  overlayCbkData = NULL;
-
-  fontIDs = NULL;
-  fontFileIDs = NULL;
-  fontFileNames = NULL;
-  font16Enc = NULL;
-  xobjStack = NULL;
-  embFontList = NULL;
-  customColors = NULL;
-  haveTextClip = gFalse;
-  t3String = NULL;
-
-  init(outputFuncA, outputStreamA, psGeneric,
-       xrefA, catalog, firstPage, lastPage, modeA,
-       imgLLXA, imgLLYA, imgURXA, imgURYA, manualCtrlA, pageRangesA);
-}
-
-void PSOutputDev::init(PSOutputFunc outputFuncA, void *outputStreamA,
-                      PSFileType fileTypeA, XRef *xrefA, Catalog *catalog,
-                      int firstPage, int lastPage, PSOutMode modeA,
-                      int imgLLXA, int imgLLYA, int imgURXA, int imgURYA,
-                      GBool manualCtrlA, const char *pageRangesA) {
-  Page *page;
-  PDFRectangle *box;
-
-  // initialize
-  ok = gTrue;
-  outputFunc = outputFuncA;
-  outputStream = outputStreamA;
-  fileType = fileTypeA;
-  xref = xrefA;
-  level = globalParams->getPSLevel();
-  mode = modeA;
-  paperWidth = globalParams->getPSPaperWidth();
-  paperHeight = globalParams->getPSPaperHeight();
-  imgLLX = imgLLXA;
-  imgLLY = imgLLYA;
-  imgURX = imgURXA;
-  imgURY = imgURYA;
-  pageRanges = pageRangesA;
-  if (imgLLX == 0 && imgURX == 0 && imgLLY == 0 && imgURY == 0) {
-    globalParams->getPSImageableArea(&imgLLX, &imgLLY, &imgURX, &imgURY);
-  }
-  if (paperWidth < 0 || paperHeight < 0) {
-    // this check is needed in case the document has zero pages
-    if (firstPage > 0 && firstPage <= catalog->getNumPages()) {
-      page = catalog->getPage(firstPage);
-      paperWidth = (int)ceil(page->getMediaWidth());
-      paperHeight = (int)ceil(page->getMediaHeight());
-    } else {
-      paperWidth = 1;
-      paperHeight = 1;
-    }
-    imgLLX = imgLLY = 0;
-    imgURX = paperWidth;
-    imgURY = paperHeight;
-  }
-  manualCtrl = manualCtrlA;
-  if (mode == psModeForm) {
-    lastPage = firstPage;
-  }
-  processColors = 0;
-  inType3Char = gFalse;
-
-#if OPI_SUPPORT
-  // initialize OPI nesting levels
-  opi13Nest = 0;
-  opi20Nest = 0;
-#endif
-
-  tx0 = ty0 = 0;
-  xScale0 = yScale0 = 0;
-  rotate0 = -1;
-  clipLLX0 = clipLLY0 = 0;
-  clipURX0 = clipURY0 = -1;
-
-  // initialize fontIDs, fontFileIDs, and fontFileNames lists
-  fontIDSize = 64;
-  fontIDLen = 0;
-  fontIDs = (Ref *)gmallocn(fontIDSize, sizeof(Ref));
-  fontFileIDSize = 64;
-  fontFileIDLen = 0;
-  fontFileIDs = (Ref *)gmallocn(fontFileIDSize, sizeof(Ref));
-  fontFileNameSize = 64;
-  fontFileNameLen = 0;
-  fontFileNames = (GString **)gmallocn(fontFileNameSize, sizeof(GString *));
-  nextTrueTypeNum = 0;
-  font16EncLen = 0;
-  font16EncSize = 0;
-
-  xobjStack = new GList();
-  numSaves = 0;
-  numTilingPatterns = 0;
-  nextFunc = 0;
-
-  // initialize embedded font resource comment list
-  embFontList = new GString();
-
-  if (!manualCtrl) {
-    // this check is needed in case the document has zero pages
-    if (firstPage > 0 && firstPage <= catalog->getNumPages()) {
-      writeHeader(firstPage, lastPage,
-                 catalog->getPage(firstPage)->getMediaBox(),
-                 catalog->getPage(firstPage)->getCropBox(),
-                 catalog->getPage(firstPage)->getRotate());
-    } else {
-      box = new PDFRectangle(0, 0, 1, 1);
-      writeHeader(firstPage, lastPage, box, box, 0);
-      delete box;
-    }
-    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 *mediaBox, PDFRectangle *cropBox,
-                             int pageRotate) {
-  Object info, obj1;
-  double x1, y1, x2, y2;
-  GString *s;
-  int i;
-
-  switch (mode) {
-  case psModePS:
-    writePS("%!PS-Adobe-3.0\n");
-    break;
-  case psModeEPS:
-    writePS("%!PS-Adobe-3.0 EPSF-3.0\n");
-    break;
-  case psModeForm:
-    writePS("%!PS-Adobe-3.0 Resource-Form\n");
-    break;
-  }
-
-  // Tell CUPS pstops filter not to do its own rotation...
-  int cups_rotate = 0;
-  int width = (int)ceil(mediaBox->x2 - mediaBox->x1);
-  int height = (int)ceil(mediaBox->y2 - mediaBox->y1);
-  int imgWidth = (int)ceil(cropBox->x2 - cropBox->x1);
-
-  if (width > height && width > imgWidth) cups_rotate = 90;
-
-  writePSFmt("%%cupsRotation: %d\n", cups_rotate);
-
-  writePSFmt("%%Producer: xpdf/pdftops %s\n", xpdfVersion);
-  xref->getDocInfo(&info);
-  if (info.isDict() && info.dictLookup("Creator", &obj1)->isString()) {
-    writePS("%%Creator: ");
-    s = obj1.getString();
-    if ((s->getChar(0) & 0xff) == 0xfe &&
-       (s->getChar(1) & 0xff) == 0xff) {
-      // Convert UTF-16 to UTF-8...
-      for (i = 2; i < s->getLength() && i < 400; i += 2) {
-       int ch = ((s->getChar(i) & 255) << 8) | (s->getChar(i + 1) & 255);
-
-        if (ch >= 0xd800 && ch <= 0xdbff) {
-         // Multi-word UTF-16 char...
-         i += 2;
-         int lch = ((s->getChar(i) & 255) << 8) | (s->getChar(i + 1) & 255);
-
-          if (lch < 0xdc00 || lch >= 0xdfff) continue;
-
-          ch = (((ch & 0x3ff) << 10) | (lch & 0x3ff)) + 0x10000;
-       }
-
-       if (ch < 0x80)
-       {
-        /*
-         * Single byte ASCII...
-         */
-
-         writePSChar(ch);
-       }
-       else if (ch < 0x800)
-       {
-        /*
-         * Two-byte UTF-8...
-         */
-
-         writePSChar(0xc0 | (ch >> 6));
-         writePSChar(0x80 | (ch & 0x3f));
-       }
-       else if (ch < 0x10000)
-       {
-        /*
-         * Three-byte UTF-8...
-         */
-
-         writePSChar(0xe0 | (ch >> 12));
-         writePSChar(0x80 | ((ch >> 6) & 0x3f));
-         writePSChar(0x80 | (ch & 0x3f));
-       }
-       else
-       {
-        /*
-         * Four-byte UTF-8...
-         */
-
-         writePSChar(0xf0 | (ch >> 18));
-         writePSChar(0x80 | ((ch >> 12) & 0x3f));
-         writePSChar(0x80 | ((ch >> 6) & 0x3f));
-         writePSChar(0x80 | (ch & 0x3f));
-       }
-      }
-    } else {
-      for (i = 0; i < s->getLength() && i < 200; ++i) {
-       writePSChar(s->getChar(i));
-      }
-    }
-    writePS("\n");
-  }
-  obj1.free();
-  if (info.isDict() && info.dictLookup("Title", &obj1)->isString()) {
-    writePS("%%Title: ");
-    s = obj1.getString();
-    if ((s->getChar(0) & 0xff) == 0xfe &&
-       (s->getChar(1) & 0xff) == 0xff) {
-      // Convert UTF-16 to UTF-8...
-      for (i = 2; i < s->getLength() && i < 400; i += 2) {
-       int ch = ((s->getChar(i) & 255) << 8) | (s->getChar(i + 1) & 255);
-
-        if (ch >= 0xd800 && ch <= 0xdbff) {
-         // Multi-word UTF-16 char...
-         i += 2;
-         int lch = ((s->getChar(i) & 255) << 8) | (s->getChar(i + 1) & 255);
-
-          if (lch < 0xdc00 || lch >= 0xdfff) continue;
-
-          ch = (((ch & 0x3ff) << 10) | (lch & 0x3ff)) + 0x10000;
-       }
-
-       if (ch < 0x80)
-       {
-        /*
-         * Single byte ASCII...
-         */
-
-         writePSChar(ch);
-       }
-       else if (ch < 0x800)
-       {
-        /*
-         * Two-byte UTF-8...
-         */
-
-         writePSChar(0xc0 | (ch >> 6));
-         writePSChar(0x80 | (ch & 0x3f));
-       }
-       else if (ch < 0x10000)
-       {
-        /*
-         * Three-byte UTF-8...
-         */
-
-         writePSChar(0xe0 | (ch >> 12));
-         writePSChar(0x80 | ((ch >> 6) & 0x3f));
-         writePSChar(0x80 | (ch & 0x3f));
-       }
-       else
-       {
-        /*
-         * Four-byte UTF-8...
-         */
-
-         writePSChar(0xf0 | (ch >> 18));
-         writePSChar(0x80 | ((ch >> 12) & 0x3f));
-         writePSChar(0x80 | ((ch >> 6) & 0x3f));
-         writePSChar(0x80 | (ch & 0x3f));
-       }
-      }
-    } else {
-      for (i = 0; i < s->getLength() && i < 200; ++i) {
-       writePSChar(s->getChar(i));
-      }
-    }
-    writePS("\n");
-  }
-  obj1.free();
-  info.free();
-  writePSFmt("%%%%LanguageLevel: %d\n",
-            (level == psLevel1 || level == psLevel1Sep) ? 1 :
-            (level == psLevel2 || level == psLevel2Sep) ? 2 : 3);
-  if (level == psLevel1Sep || level == psLevel2Sep || level == psLevel3Sep) {
-    writePS("%%DocumentProcessColors: (atend)\n");
-    writePS("%%DocumentCustomColors: (atend)\n");
-  }
-  writePS("%%DocumentSuppliedResources: (atend)\n");
-
-  switch (mode) {
-  case psModePS:
-    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");
-    writePS("%%PageMedia: plain\n");
-    writePS("%%EndDefaults\n");
-    break;
-  case psModeEPS:
-    epsX1 = cropBox->x1;
-    epsY1 = cropBox->y1;
-    epsX2 = cropBox->x2;
-    epsY2 = cropBox->y2;
-    if (pageRotate == 0 || pageRotate == 180) {
-      x1 = epsX1;
-      y1 = epsY1;
-      x2 = epsX2;
-      y2 = epsY2;
-    } else { // pageRotate == 90 || pageRotate == 270
-      x1 = 0;
-      y1 = 0;
-      x2 = epsY2 - epsY1;
-      y2 = epsX2 - epsX1;
-    }
-    writePSFmt("%%%%BoundingBox: %d %d %d %d\n",
-              (int)floor(x1), (int)floor(y1), (int)ceil(x2), (int)ceil(y2));
-    if (floor(x1) != ceil(x1) || floor(y1) != ceil(y1) ||
-       floor(x2) != ceil(x2) || floor(y2) != ceil(y2)) {
-      writePSFmt("%%%%HiResBoundingBox: %g %g %g %g\n", x1, y1, x2, y2);
-    }
-    writePS("%%EndComments\n");
-    break;
-  case psModeForm:
-    writePS("%%EndComments\n");
-    writePS("32 dict dup begin\n");
-    writePSFmt("/BBox [%d %d %d %d] def\n",
-              (int)floor(mediaBox->x1), (int)floor(mediaBox->y1),
-              (int)ceil(mediaBox->x2), (int)ceil(mediaBox->y2));
-    writePS("/FormType 1 def\n");
-    writePS("/Matrix [1 0 0 1 0 0] def\n");
-    break;
-  }
-}
-
-void PSOutputDev::writeXpdfProcset() {
-  GBool lev1, lev2, lev3, sep, nonSep;
-  char **p;
-  char *q;
-
-  writePSFmt("%%%%BeginResource: procset xpdf %s 0\n", xpdfVersion);
-  lev1 = lev2 = lev3 = sep = nonSep = gTrue;
-  for (p = prolog; *p; ++p) {
-    if ((*p)[0] == '~') {
-      lev1 = lev2 = lev3 = sep = nonSep = gFalse;
-      for (q = *p + 1; *q; ++q) {
-       switch (*q) {
-       case '1': lev1 = gTrue; break;
-       case '2': lev2 = gTrue; break;
-       case '3': lev3 = gTrue; break;
-       case 's': sep = gTrue; break;
-       case 'n': nonSep = gTrue; break;
-       }
-      }
-    } else if ((level == psLevel1 && lev1 && nonSep) ||
-              (level == psLevel1Sep && lev1 && sep) ||
-              (level == psLevel2 && lev2 && nonSep) ||
-              (level == psLevel2Sep && lev2 && sep) ||
-              (level == psLevel3 && lev3 && nonSep) ||
-              (level == psLevel3Sep && lev3 && sep)) {
-      writePSFmt("%s\n", *p);
-    }
-  }
-  writePS("%%EndResource\n");
-
-  if (level >= psLevel3) {
-    for (p = cmapProlog; *p; ++p) {
-      writePSFmt("%s\n", *p);
-    }
-  }
-}
-
-void PSOutputDev::writeDocSetup(Catalog *catalog,
-                               int firstPage, int lastPage) {
-  Page *page;
-  Dict *resDict;
-  Annots *annots;
-  Object obj1, obj2;
-  int pg, i;
-
-  if (mode == psModeForm) {
-    // swap the form and xpdf dicts
-    writePS("xpdf end begin dup begin\n");
-  } else {
-    writePS("xpdf begin\n");
-  }
-  for (pg = firstPage; pg <= lastPage; ++pg) {
-    page = catalog->getPage(pg);
-    if ((resDict = page->getResourceDict())) {
-      setupResources(resDict);
-    }
-    annots = new Annots(xref, catalog, page->getAnnots(&obj1));
-    obj1.free();
-    for (i = 0; i < annots->getNumAnnots(); ++i) {
-      if (annots->getAnnot(i)->getAppearance(&obj1)->isStream()) {
-       obj1.streamGetDict()->lookup("Resources", &obj2);
-       if (obj2.isDict()) {
-         setupResources(obj2.getDict());
-       }
-       obj2.free();
-      }
-      obj1.free();
-    }
-    delete annots;
-  }
-  if (mode != psModeForm) {
-    if (mode != psModeEPS && !manualCtrl) {
-      writePSFmt("%d %d %s pdfSetup\n",
-                paperWidth, paperHeight,
-                globalParams->getPSDuplex() ? "true" : "false");
-    }
-#if OPI_SUPPORT
-    if (globalParams->getPSOPI()) {
-      writePS("/opiMatrix matrix currentmatrix def\n");
-    }
-#endif
-  }
-}
-
-void PSOutputDev::writePageTrailer() {
-  if (mode != psModeForm) {
-    writePS("pdfEndPage\n");
-  }
-}
-
-void PSOutputDev::writeTrailer() {
-  PSOutCustomColor *cc;
-
-  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");
-        }
-      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());
-      }
-    }
-  }
-}
-
-void PSOutputDev::setupResources(Dict *resDict) {
-  Object xObjDict, xObjRef, xObj, patDict, patRef, pat, resObj;
-  Ref ref0, ref1;
-  GBool skip;
-  int i, j;
-
-  setupFonts(resDict);
-  setupImages(resDict);
-
-  //----- recursively scan XObjects
-  resDict->lookup("XObject", &xObjDict);
-  if (xObjDict.isDict()) {
-    for (i = 0; i < xObjDict.dictGetLength(); ++i) {
-
-      // avoid infinite recursion on XObjects
-      skip = gFalse;
-      if ((xObjDict.dictGetValNF(i, &xObjRef)->isRef())) {
-       ref0 = xObjRef.getRef();
-       for (j = 0; j < xobjStack->getLength(); ++j) {
-         ref1 = *(Ref *)xobjStack->get(j);
-         if (ref1.num == ref0.num && ref1.gen == ref0.gen) {
-           skip = gTrue;
-           break;
-         }
-       }
-       if (!skip) {
-         xobjStack->append(&ref0);
-       }
-      }
-      if (!skip) {
-
-       // process the XObject's resource dictionary
-       xObjDict.dictGetVal(i, &xObj);
-       if (xObj.isStream()) {
-         xObj.streamGetDict()->lookup("Resources", &resObj);
-         if (resObj.isDict()) {
-           setupResources(resObj.getDict());
-         }
-         resObj.free();
-       }
-       xObj.free();
-      }
-
-      if (xObjRef.isRef() && !skip) {
-       xobjStack->del(xobjStack->getLength() - 1);
-      }
-      xObjRef.free();
-    }
-  }
-  xObjDict.free();
-
-  //----- recursively scan Patterns
-  resDict->lookup("Pattern", &patDict);
-  if (patDict.isDict()) {
-    inType3Char = gTrue;
-    for (i = 0; i < patDict.dictGetLength(); ++i) {
-
-      // avoid infinite recursion on Patterns
-      skip = gFalse;
-      if ((patDict.dictGetValNF(i, &patRef)->isRef())) {
-       ref0 = patRef.getRef();
-       for (j = 0; j < xobjStack->getLength(); ++j) {
-         ref1 = *(Ref *)xobjStack->get(j);
-         if (ref1.num == ref0.num && ref1.gen == ref0.gen) {
-           skip = gTrue;
-           break;
-         }
-       }
-       if (!skip) {
-         xobjStack->append(&ref0);
-       }
-      }
-      if (!skip) {
-
-       // process the Pattern's resource dictionary
-       patDict.dictGetVal(i, &pat);
-       if (pat.isStream()) {
-         pat.streamGetDict()->lookup("Resources", &resObj);
-         if (resObj.isDict()) {
-           setupResources(resObj.getDict());
-         }
-         resObj.free();
-       }
-       pat.free();
-      }
-
-      if (patRef.isRef() && !skip) {
-       xobjStack->del(xobjStack->getLength() - 1);
-      }
-      patRef.free();
-    }
-    inType3Char = gFalse;
-  }
-  patDict.free();
-}
-
-void PSOutputDev::setupFonts(Dict *resDict) {
-  Object obj1, obj2;
-  Ref r;
-  GfxFontDict *gfxFontDict;
-  GfxFont *font;
-  int i;
-
-  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) {
-      if ((font = gfxFontDict->getFont(i))) {
-       setupFont(font, resDict);
-      }
-    }
-    delete gfxFontDict;
-  }
-  obj1.free();
-}
-
-void PSOutputDev::setupFont(GfxFont *font, Dict *parentResDict) {
-  Ref fontFileID;
-  GString *name;
-  PSFontParam *fontParam;
-  GString *psName;
-  char type3Name[64], buf[16];
-  GBool subst;
-  UnicodeMap *uMap;
-  char *charName;
-  double xs, ys;
-  int code;
-  double w1, w2;
-  double *fm;
-  int i, j;
-
-  // check if font is already set up
-  for (i = 0; i < fontIDLen; ++i) {
-    if (fontIDs[i].num == font->getID()->num &&
-       fontIDs[i].gen == font->getID()->gen) {
-      return;
-    }
-  }
-
-  // add entry to fontIDs list
-  if (fontIDLen >= fontIDSize) {
-    fontIDSize += 64;
-    fontIDs = (Ref *)greallocn(fontIDs, fontIDSize, sizeof(Ref));
-  }
-  fontIDs[fontIDLen++] = *font->getID();
-
-  xs = ys = 1;
-  subst = gFalse;
-
-  // check for resident 8-bit font
-  if (font->getName() &&
-      (fontParam = globalParams->getPSFont(font->getName()))) {
-    psName = new GString(fontParam->psFontName->getCString());
-
-  // check for embedded Type 1 font
-  } else if (globalParams->getPSEmbedType1() &&
-            font->getType() == fontType1 &&
-            font->getEmbeddedFontID(&fontFileID)) {
-    psName = filterPSName(font->getEmbeddedFontName());
-    setupEmbeddedType1Font(&fontFileID, psName);
-
-  // check for embedded Type 1C font
-  } else if (globalParams->getPSEmbedType1() &&
-            font->getType() == fontType1C &&
-            font->getEmbeddedFontID(&fontFileID)) {
-    psName = filterPSName(font->getEmbeddedFontName());
-    setupEmbeddedType1CFont(font, &fontFileID, psName);
-
-  // check for external Type 1 font file
-  } else if (globalParams->getPSEmbedType1() &&
-            font->getType() == fontType1 &&
-            font->getExtFontFile()) {
-    // this assumes that the PS font name matches the PDF font name
-    psName = font->getName()->copy();
-    setupExternalType1Font(font->getExtFontFile(), psName);
-
-  // check for embedded TrueType font
-  } else if (globalParams->getPSEmbedTrueType() &&
-            font->getType() == fontTrueType &&
-            font->getEmbeddedFontID(&fontFileID)) {
-    psName = filterPSName(font->getEmbeddedFontName());
-    setupEmbeddedTrueTypeFont(font, &fontFileID, psName);
-
-  // check for external TrueType font file
-  } else if (globalParams->getPSEmbedTrueType() &&
-            font->getType() == fontTrueType &&
-            font->getExtFontFile()) {
-    psName = filterPSName(font->getName());
-    setupExternalTrueTypeFont(font, psName);
-
-  // check for embedded CID PostScript font
-  } else if (globalParams->getPSEmbedCIDPostScript() &&
-            font->getType() == fontCIDType0C &&
-            font->getEmbeddedFontID(&fontFileID)) {
-    psName = filterPSName(font->getEmbeddedFontName());
-    setupEmbeddedCIDType0Font(font, &fontFileID, psName);
-
-  // check for embedded CID TrueType font
-  } else if (globalParams->getPSEmbedCIDTrueType() &&
-            font->getType() == fontCIDType2 &&
-            font->getEmbeddedFontID(&fontFileID)) {
-    psName = filterPSName(font->getEmbeddedFontName());
-    //~ should check to see if font actually uses vertical mode
-    setupEmbeddedCIDTrueTypeFont(font, &fontFileID, psName, gTrue);
-
-  } else if (font->getType() == fontType3) {
-    sprintf(type3Name, "T3_%d_%d",
-           font->getID()->num, font->getID()->gen);
-    psName = new GString(type3Name);
-    setupType3Font(font, psName, parentResDict);
-
-  // do 8-bit font substitution
-  } else if (!font->isCIDFont()) {
-    subst = gTrue;
-    name = font->getName();
-    psName = NULL;
-    if (name) {
-      for (i = 0; psFonts[i]; ++i) {
-       if (name->cmp(psFonts[i]) == 0) {
-         psName = new GString(psFonts[i]);
-         break;
-       }
-      }
-    }
-    if (!psName) {
-      if (font->isFixedWidth()) {
-       i = 8;
-      } else if (font->isSerif()) {
-       i = 4;
-      } else {
-       i = 0;
-      }
-      if (font->isBold()) {
-       i += 2;
-      }
-      if (font->isItalic()) {
-       i += 1;
-      }
-      psName = new GString(psSubstFonts[i].psName);
-      for (code = 0; code < 256; ++code) {
-       if ((charName = ((Gfx8BitFont *)font)->getCharName(code)) &&
-           charName[0] == 'm' && charName[1] == '\0') {
-         break;
-       }
-      }
-      if (code < 256) {
-       w1 = ((Gfx8BitFont *)font)->getWidth(code);
-      } else {
-       w1 = 0;
-      }
-      w2 = psSubstFonts[i].mWidth;
-      xs = w1 / w2;
-      if (xs < 0.1) {
-       xs = 1;
-      }
-      if (font->getType() == fontType3) {
-       // This is a hack which makes it possible to substitute for some
-       // Type 3 fonts.  The problem is that it's impossible to know what
-       // the base coordinate system used in the font is without actually
-       // rendering the font.
-       ys = xs;
-       fm = font->getFontMatrix();
-       if (fm[0] != 0) {
-         ys *= fm[3] / fm[0];
-       }
-      } else {
-       ys = 1;
-      }
-    }
-
-  // do 16-bit font substitution
-  } else if ((fontParam = globalParams->
-               getPSFont16(font->getName(),
-                           ((GfxCIDFont *)font)->getCollection(),
-                           font->getWMode()))) {
-    subst = gTrue;
-    psName = fontParam->psFontName->copy();
-    if (font16EncLen >= font16EncSize) {
-      font16EncSize += 16;
-      font16Enc = (PSFont16Enc *)greallocn(font16Enc,
-                                          font16EncSize, sizeof(PSFont16Enc));
-    }
-    font16Enc[font16EncLen].fontID = *font->getID();
-    font16Enc[font16EncLen].enc = fontParam->encoding->copy();
-    if ((uMap = globalParams->getUnicodeMap(font16Enc[font16EncLen].enc))) {
-      uMap->decRefCnt();
-      ++font16EncLen;
-    } else {
-      error(-1, "Couldn't find Unicode map for 16-bit font encoding '%s'",
-           font16Enc[font16EncLen].enc->getCString());
-    }
-
-  // give up - can't do anything with this font
-  } else {
-    error(-1, "Couldn't find a font to substitute for '%s' ('%s' character collection)",
-         font->getName() ? font->getName()->getCString() : "(unnamed)",
-         ((GfxCIDFont *)font)->getCollection()
-           ? ((GfxCIDFont *)font)->getCollection()->getCString()
-           : "(unknown)");
-    return;
-  }
-
-  // generate PostScript code to set up the font
-  if (font->isCIDFont()) {
-    if (level == psLevel3 || level == psLevel3Sep) {
-      writePSFmt("/F%d_%d /%s %d pdfMakeFont16L3\n",
-                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->getCString(),
-                font->getWMode());
-    }
-  } else {
-    writePSFmt("/F%d_%d /%s %g %g\n",
-              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) {
-       if (font->getType() == fontTrueType &&
-           !subst &&
-           !((Gfx8BitFont *)font)->getHasEncoding()) {
-         sprintf(buf, "c%02x", i+j);
-         charName = buf;
-       } else {
-         charName = ((Gfx8BitFont *)font)->getCharName(i+j);
-         // this is a kludge for broken PDF files that encode char 32
-         // as .notdef
-         if (i+j == 32 && charName && !strcmp(charName, ".notdef")) {
-           charName = "space";
-         }
-       }
-       writePS("/");
-       writePSName(charName ? charName : (char *)".notdef");
-       // the empty name is legal in PDF and PostScript, but PostScript
-       // uses a double-slash (//...) for "immediately evaluated names",
-       // so we need to add a space character here
-       if (charName && !charName[0]) {
-         writePS(" ");
-       }
-      }
-      writePS((i == 256-8) ? (char *)"]\n" : (char *)"\n");
-    }
-    writePS("pdfMakeFont\n");
-  }
-
-  delete psName;
-}
-
-void PSOutputDev::setupEmbeddedType1Font(Ref *id, GString *psName) {
-  static char hexChar[17] = "0123456789abcdef";
-  Object refObj, strObj, obj1, obj2, obj3;
-  Dict *dict;
-  int length1, length2, length3;
-  int c;
-  int start[4];
-  GBool binMode;
-  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;
-  }
-
-  // add entry to fontFileIDs list
-  if (fontFileIDLen >= fontFileIDSize) {
-    fontFileIDSize += 64;
-    fontFileIDs = (Ref *)greallocn(fontFileIDs, fontFileIDSize, sizeof(Ref));
-  }
-  fontFileIDs[fontFileIDLen++] = *id;
-
-  // get the font stream and info
-  refObj.initRef(id->num, id->gen);
-  refObj.fetch(xref, &strObj);
-  refObj.free();
-  if (!strObj.isStream()) {
-    error(-1, "Embedded font file object is not a stream");
-    goto err1;
-  }
-  if (!(dict = strObj.streamGetDict())) {
-    error(-1, "Embedded font stream is missing its dictionary");
-    goto err1;
-  }
-  dict->lookup("Length1", &obj1);
-  dict->lookup("Length2", &obj2);
-  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->getCString());
-  embFontList->append("%%+ font ");
-  embFontList->append(psName->getCString());
-  embFontList->append("\n");
-
-  // copy ASCII portion of font
-  strObj.streamReset();
-  for (i = 0; i < length1 && (c = strObj.streamGetChar()) != EOF; ++i) {
-    writePSChar(c);
-  }
-
-  // figure out if encrypted portion is binary or ASCII
-  binMode = gFalse;
-  for (i = 0; i < 4; ++i) {
-    start[i] = strObj.streamGetChar();
-    if (start[i] == EOF) {
-      error(-1, "Unexpected end of file in embedded font stream");
-      goto err1;
-    }
-    if (!((start[i] >= '0' && start[i] <= '9') ||
-         (start[i] >= 'A' && start[i] <= 'F') ||
-         (start[i] >= 'a' && start[i] <= 'f')))
-      binMode = gTrue;
-  }
-
-  // convert binary data to ASCII
-  if (binMode) {
-    for (i = 0; i < 4; ++i) {
-      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;
-      }
-      writePSChar(hexChar[(c >> 4) & 0x0f]);
-      writePSChar(hexChar[c & 0x0f]);
-      if (++i % 32 == 0) {
-       writePSChar('\n');
-      }
-    }
-    if (i % 32 > 0) {
-      writePSChar('\n');
-    }
-
-  // already in ASCII format -- just copy it
-  } else {
-    for (i = 0; i < 4; ++i) {
-      writePSChar(start[i]);
-    }
-    for (i = 4; i < length2; ++i) {
-      if ((c = strObj.streamGetChar()) == EOF) {
-       break;
-      }
-      writePSChar(c);
-    }
-  }
-
-  // write padding and "cleartomark"
-  for (i = 0; i < 8; ++i) {
-    writePS("00000000000000000000000000000000"
-           "00000000000000000000000000000000\n");
-  }
-  writePS("cleartomark\n");
-
-  // ending comment
-  writePS("%%EndResource\n");
-
- err1:
-  strObj.streamClose();
-  strObj.free();
-}
-
-//~ This doesn't handle .pfb files or binary eexec data (which only
-//~ happens in pfb files?).
-void PSOutputDev::setupExternalType1Font(GString *fileName, GString *psName) {
-  FILE *fontFile;
-  int c;
-  int i;
-
-  // check if font is already embedded
-  for (i = 0; i < fontFileNameLen; ++i) {
-    if (!fontFileNames[i]->cmp(fileName)) {
-      return;
-    }
-  }
-
-  // add entry to fontFileNames list
-  if (fontFileNameLen >= fontFileNameSize) {
-    fontFileNameSize += 64;
-    fontFileNames = (GString **)greallocn(fontFileNames,
-                                         fontFileNameSize, sizeof(GString *));
-  }
-  fontFileNames[fontFileNameLen++] = fileName->copy();
-
-  // beginning comment
-  writePSFmt("%%%%BeginResource: font %s\n", psName->getCString());
-  embFontList->append("%%+ font ");
-  embFontList->append(psName->getCString());
-  embFontList->append("\n");
-
-  // copy the font file
-  if (!(fontFile = fopen(fileName->getCString(), "rb"))) {
-    error(-1, "Couldn't open external font file");
-    return;
-  }
-  while ((c = fgetc(fontFile)) != EOF) {
-    writePSChar(c);
-  }
-  fclose(fontFile);
-
-  // ending comment
-  writePS("%%EndResource\n");
-}
-
-void PSOutputDev::setupEmbeddedType1CFont(GfxFont *font, Ref *id,
-                                         GString *psName) {
-  char *fontBuf;
-  int fontLen;
-  FoFiType1C *ffT1C;
-  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;
-  }
-
-  // add entry to fontFileIDs list
-  if (fontFileIDLen >= fontFileIDSize) {
-    fontFileIDSize += 64;
-    fontFileIDs = (Ref *)greallocn(fontFileIDs, fontFileIDSize, sizeof(Ref));
-  }
-  fontFileIDs[fontFileIDLen++] = *id;
-
-  // beginning comment
-  writePSFmt("%%%%BeginResource: font %s\n", psName->getCString());
-  embFontList->append("%%+ font ");
-  embFontList->append(psName->getCString());
-  embFontList->append("\n");
-
-  // convert it to a Type 1 font
-  fontBuf = font->readEmbFontFile(xref, &fontLen);
-  if ((ffT1C = FoFiType1C::make(fontBuf, fontLen))) {
-    ffT1C->convertToType1(NULL, gTrue, outputFunc, outputStream);
-    delete ffT1C;
-  }
-  gfree(fontBuf);
-
-  // ending comment
-  writePS("%%EndResource\n");
-}
-
-void PSOutputDev::setupEmbeddedTrueTypeFont(GfxFont *font, Ref *id,
-                                           GString *psName) {
-  char unique[32];
-  char *fontBuf;
-  int fontLen;
-  FoFiTrueType *ffTT;
-  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) {
-      sprintf(unique, "_%d", nextTrueTypeNum++);
-      psName->append(unique);
-      break;
-    }
-  }
-
-  // add entry to fontFileIDs list
-  if (i == fontFileIDLen) {
-    if (fontFileIDLen >= fontFileIDSize) {
-      fontFileIDSize += 64;
-      fontFileIDs = (Ref *)greallocn(fontFileIDs, fontFileIDSize, sizeof(Ref));
-    }
-    fontFileIDs[fontFileIDLen++] = *id;
-  }
-
-  // beginning comment
-  writePSFmt("%%%%BeginResource: font %s\n", psName->getCString());
-  embFontList->append("%%+ font ");
-  embFontList->append(psName->getCString());
-  embFontList->append("\n");
-
-  // convert it to a Type 42 font
-  fontBuf = font->readEmbFontFile(xref, &fontLen);
-  if ((ffTT = FoFiTrueType::make(fontBuf, fontLen))) {
-    codeToGID = ((Gfx8BitFont *)font)->getCodeToGIDMap(ffTT);
-    ffTT->convertToType42(psName->getCString(),
-                         ((Gfx8BitFont *)font)->getHasEncoding()
-                           ? ((Gfx8BitFont *)font)->getEncoding()
-                           : (char **)NULL,
-                         codeToGID, outputFunc, outputStream);
-    gfree(codeToGID);
-    delete ffTT;
-  }
-  gfree(fontBuf);
-
-  // ending comment
-  writePS("%%EndResource\n");
-}
-
-void PSOutputDev::setupExternalTrueTypeFont(GfxFont *font, GString *psName) {
-  char unique[32];
-  GString *fileName;
-  char *fontBuf;
-  int fontLen;
-  FoFiTrueType *ffTT;
-  Gushort *codeToGID;
-  int i;
-
-  // check if font is already embedded
-  fileName = font->getExtFontFile();
-  for (i = 0; i < fontFileNameLen; ++i) {
-    if (!fontFileNames[i]->cmp(fileName)) {
-      sprintf(unique, "_%d", nextTrueTypeNum++);
-      psName->append(unique);
-      break;
-    }
-  }
-
-  // add entry to fontFileNames list
-  if (i == fontFileNameLen) {
-    if (fontFileNameLen >= fontFileNameSize) {
-      fontFileNameSize += 64;
-      fontFileNames =
-       (GString **)greallocn(fontFileNames,
-                             fontFileNameSize, sizeof(GString *));
-    }
-    fontFileNames[fontFileNameLen++] = fileName->copy();
-  }
-
-  // beginning comment
-  writePSFmt("%%%%BeginResource: font %s\n", psName->getCString());
-  embFontList->append("%%+ font ");
-  embFontList->append(psName->getCString());
-  embFontList->append("\n");
-
-  // convert it to a Type 42 font
-  fontBuf = font->readExtFontFile(&fontLen);
-  if ((ffTT = FoFiTrueType::make(fontBuf, fontLen))) {
-    codeToGID = ((Gfx8BitFont *)font)->getCodeToGIDMap(ffTT);
-    ffTT->convertToType42(psName->getCString(),
-                         ((Gfx8BitFont *)font)->getHasEncoding()
-                           ? ((Gfx8BitFont *)font)->getEncoding()
-                           : (char **)NULL,
-                         codeToGID, outputFunc, outputStream);
-    delete ffTT;
-  }
-  gfree(fontBuf);
-
-  // ending comment
-  writePS("%%EndResource\n");
-}
-
-void PSOutputDev::setupEmbeddedCIDType0Font(GfxFont *font, Ref *id,
-                                           GString *psName) {
-  char *fontBuf;
-  int fontLen;
-  FoFiType1C *ffT1C;
-  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;
-  }
-
-  // add entry to fontFileIDs list
-  if (fontFileIDLen >= fontFileIDSize) {
-    fontFileIDSize += 64;
-    fontFileIDs = (Ref *)greallocn(fontFileIDs, fontFileIDSize, sizeof(Ref));
-  }
-  fontFileIDs[fontFileIDLen++] = *id;
-
-  // beginning comment
-  writePSFmt("%%%%BeginResource: font %s\n", psName->getCString());
-  embFontList->append("%%+ font ");
-  embFontList->append(psName->getCString());
-  embFontList->append("\n");
-
-  // convert it to a Type 0 font
-  fontBuf = font->readEmbFontFile(xref, &fontLen);
-  if ((ffT1C = FoFiType1C::make(fontBuf, fontLen))) {
-    if (globalParams->getPSLevel() >= psLevel3) {
-      // Level 3: use a CID font
-      ffT1C->convertToCIDType0(psName->getCString(), outputFunc, outputStream);
-    } else {
-      // otherwise: use a non-CID composite font
-      ffT1C->convertToType0(psName->getCString(), outputFunc, outputStream);
-    }
-    delete ffT1C;
-  }
-  gfree(fontBuf);
-
-  // ending comment
-  writePS("%%EndResource\n");
-}
-
-void PSOutputDev::setupEmbeddedCIDTrueTypeFont(GfxFont *font, Ref *id,
-                                              GString *psName,
-                                              GBool needVerticalMetrics) {
-  char unique[32];
-  char *fontBuf;
-  int fontLen;
-  FoFiTrueType *ffTT;
-  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) {
-      sprintf(unique, "_%d", nextTrueTypeNum++);
-      psName->append(unique);
-      break;
-    }
-  }
-
-  // add entry to fontFileIDs list
-  if (fontFileIDLen >= fontFileIDSize) {
-    fontFileIDSize += 64;
-    fontFileIDs = (Ref *)greallocn(fontFileIDs, fontFileIDSize, sizeof(Ref));
-  }
-  fontFileIDs[fontFileIDLen++] = *id;
-
-  // beginning comment
-  writePSFmt("%%%%BeginResource: font %s\n", psName->getCString());
-  embFontList->append("%%+ font ");
-  embFontList->append(psName->getCString());
-  embFontList->append("\n");
-
-  // convert it to a Type 0 font
-  fontBuf = font->readEmbFontFile(xref, &fontLen);
-  if ((ffTT = FoFiTrueType::make(fontBuf, fontLen))) {
-    if (globalParams->getPSLevel() >= psLevel3) {
-      // Level 3: use a CID font
-      ffTT->convertToCIDType2(psName->getCString(),
-                             ((GfxCIDFont *)font)->getCIDToGID(),
-                             ((GfxCIDFont *)font)->getCIDToGIDLen(),
-                             needVerticalMetrics,
-                             outputFunc, outputStream);
-    } else {
-      // otherwise: use a non-CID composite font
-      ffTT->convertToType0(psName->getCString(),
-                          ((GfxCIDFont *)font)->getCIDToGID(),
-                          ((GfxCIDFont *)font)->getCIDToGIDLen(),
-                          needVerticalMetrics,
-                          outputFunc, outputStream);
-    }
-    delete ffTT;
-  }
-  gfree(fontBuf);
-
-  // ending comment
-  writePS("%%EndResource\n");
-}
-
-void PSOutputDev::setupType3Font(GfxFont *font, GString *psName,
-                                Dict *parentResDict) {
-  Dict *resDict;
-  Dict *charProcs;
-  Object charProc;
-  Gfx *gfx;
-  PDFRectangle box;
-  double *m;
-  char buf[256];
-  int i;
-
-  // 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->getCString());
-  embFontList->append("%%+ font ");
-  embFontList->append(psName->getCString());
-  embFontList->append("\n");
-
-  // font dictionary
-  writePS("8 dict begin\n");
-  writePS("/FontType 3 def\n");
-  m = font->getFontMatrix();
-  writePSFmt("/FontMatrix [%g %g %g %g %g %g] def\n",
-            m[0], m[1], m[2], m[3], m[4], m[5]);
-  m = font->getFontBBox();
-  writePSFmt("/FontBBox [%g %g %g %g] def\n",
-            m[0], m[1], m[2], m[3]);
-  writePS("/Encoding 256 array def\n");
-  writePS("  0 1 255 { Encoding exch /.notdef put } for\n");
-  writePS("/BuildGlyph {\n");
-  writePS("  exch /CharProcs get exch\n");
-  writePS("  2 copy known not { pop /.notdef } if\n");
-  writePS("  get exec\n");
-  writePS("} bind def\n");
-  writePS("/BuildChar {\n");
-  writePS("  1 index /Encoding get exch get\n");
-  writePS("  1 index /BuildGlyph get exec\n");
-  writePS("} bind def\n");
-  if ((charProcs = ((Gfx8BitFont *)font)->getCharProcs())) {
-    writePSFmt("/CharProcs %d dict def\n", charProcs->getLength());
-    writePS("CharProcs begin\n");
-    box.x1 = m[0];
-    box.y1 = m[1];
-    box.x2 = m[2];
-    box.y2 = m[3];
-    gfx = new Gfx(xref, this, resDict, &box, NULL);
-    inType3Char = gTrue;
-    t3Cacheable = gFalse;
-    for (i = 0; i < charProcs->getLength(); ++i) {
-      writePS("/");
-      writePSName(charProcs->getKey(i));
-      writePS(" {\n");
-      gfx->display(charProcs->getVal(i, &charProc));
-      charProc.free();
-      if (t3String) {
-       if (t3Cacheable) {
-         sprintf(buf, "%g %g %g %g %g %g setcachedevice\n",
-                 t3WX, t3WY, t3LLX, t3LLY, t3URX, t3URY);
-       } else {
-         sprintf(buf, "%g %g setcharwidth\n", t3WX, t3WY);
-       }
-       (*outputFunc)(outputStream, buf, strlen(buf));
-       (*outputFunc)(outputStream, t3String->getCString(),
-                     t3String->getLength());
-       delete t3String;
-       t3String = NULL;
-      }
-      (*outputFunc)(outputStream, "Q\n", 2);
-      writePS("} def\n");
-    }
-    inType3Char = gFalse;
-    delete gfx;
-    writePS("end\n");
-  }
-  writePS("currentdict end\n");
-  writePSFmt("/%s exch definefont pop\n", psName->getCString());
-
-  // ending comment
-  writePS("%%EndResource\n");
-}
-
-void PSOutputDev::setupImages(Dict *resDict) {
-  Object xObjDict, xObj, xObjRef, subtypeObj;
-  int i;
-
-  if (!(mode == psModeForm || inType3Char)) {
-    return;
-  }
-
-  resDict->lookup("XObject", &xObjDict);
-  if (xObjDict.isDict()) {
-    for (i = 0; i < xObjDict.dictGetLength(); ++i) {
-      xObjDict.dictGetValNF(i, &xObjRef);
-      xObjDict.dictGetVal(i, &xObj);
-      if (xObj.isStream()) {
-       xObj.streamGetDict()->lookup("Subtype", &subtypeObj);
-       if (subtypeObj.isName("Image")) {
-         if (xObjRef.isRef()) {
-           setupImage(xObjRef.getRef(), xObj.getStream());
-         } else {
-           error(-1, "Image in resource dict is not an indirect reference");
-         }
-       }
-       subtypeObj.free();
-      }
-      xObj.free();
-      xObjRef.free();
-    }
-  }
-  xObjDict.free();
-}
-
-void PSOutputDev::setupImage(Ref id, Stream *str) {
-  GBool useASCIIHex;
-  int c;
-  int size, line, col, i;
-
-  // construct an encoder stream
-  useASCIIHex = level == psLevel1 || level == psLevel1Sep ||
-                globalParams->getPSASCIIHex();
-  if (useASCIIHex) {
-    str = new ASCIIHexEncoder(str);
-  } else {
-    str = new ASCII85Encoder(str);
-  }
-
-  // compute image data size
-  str->reset();
-  col = size = 0;
-  do {
-    do {
-      c = str->getChar();
-    } while (c == '\n' || c == '\r');
-    if (c == (useASCIIHex ? '>' : '~') || c == EOF) {
-      break;
-    }
-    if (c == 'z') {
-      ++col;
-    } else {
-      ++col;
-      for (i = 1; i <= (useASCIIHex ? 1 : 4); ++i) {
-       do {
-         c = str->getChar();
-       } while (c == '\n' || c == '\r');
-       if (c == (useASCIIHex ? '>' : '~') || c == EOF) {
-         break;
-       }
-       ++col;
-      }
-    }
-    if (col > 225) {
-      ++size;
-      col = 0;
-    }
-  } while (c != (useASCIIHex ? '>' : '~') && 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();
-  line = col = 0;
-  writePS((char *)(useASCIIHex ? "dup 0 <" : "dup 0 <~"));
-  do {
-    do {
-      c = str->getChar();
-    } while (c == '\n' || c == '\r');
-    if (c == (useASCIIHex ? '>' : '~') || c == EOF) {
-      break;
-    }
-    if (c == 'z') {
-      writePSChar(c);
-      ++col;
-    } else {
-      writePSChar(c);
-      ++col;
-      for (i = 1; i <= (useASCIIHex ? 1 : 4); ++i) {
-       do {
-         c = str->getChar();
-       } while (c == '\n' || c == '\r');
-       if (c == (useASCIIHex ? '>' : '~') || c == EOF) {
-         break;
-       }
-       writePSChar(c);
-       ++col;
-      }
-    }
-    // each line is: "dup nnnnn <~...data...~> put<eol>"
-    // so max data length = 255 - 20 = 235
-    // chunks are 1 or 4 bytes each, so we have to stop at 232
-    // but make it 225 just to be safe
-    if (col > 225) {
-      writePS((char *)(useASCIIHex ? "> put\n" : "~> put\n"));
-      ++line;
-      writePSFmt((char *)(useASCIIHex ? "dup %d <" : "dup %d <~"), line);
-      col = 0;
-    }
-  } while (c != (useASCIIHex ? '>' : '~') && c != EOF);
-  writePS((char *)(useASCIIHex ? "> put\n" : "~> put\n"));
-  writePS("pop\n");
-  str->close();
-
-  delete str;
-}
-
-GBool PSOutputDev::startPage(int pageNum, GfxState *state) {
-  int x1, y1, x2, y2, width, height;
-  int imgWidth, imgHeight, imgWidth2, imgHeight2;
-  GBool landscape;
-
-
-  if (mode == psModePS) {
-    writePSFmt("%%%%Page: %d %d\n", pageNum, seqPage);
-    writePS("%%BeginPageSetup\n");
-  }
-
-  // underlays
-  if (underlayCbk) {
-    (*underlayCbk)(this, underlayCbkData);
-  }
-  if (overlayCbk) {
-    saveState(NULL);
-  }
-
-  switch (mode) {
-
-  case psModePS:
-    // rotate, translate, and scale page
-    imgWidth = imgURX - imgLLX;
-    imgHeight = imgURY - imgLLY;
-    x1 = (int)floor(state->getX1());
-    y1 = (int)floor(state->getY1());
-    x2 = (int)ceil(state->getX2());
-    y2 = (int)ceil(state->getY2());
-    width = x2 - x1;
-    height = y2 - y1;
-    tx = ty = 0;
-    // rotation and portrait/landscape mode
-    if (rotate0 >= 0) {
-      rotate = (360 - rotate0) % 360;
-      landscape = gFalse;
-    } else {
-      rotate = (360 - state->getRotate()) % 360;
-
-      fprintf(stderr, "DEBUG: Page rotate=%d, width=%d, height=%d, imgWidth=%d, imgHeight=%d\n",
-              state->getRotate(), width, height, imgWidth, imgHeight);
-
-      if (rotate == 0 || rotate == 180) {
-       if (width > height && width > imgWidth) {
-         rotate += 90;
-         landscape = gTrue;
-       } else {
-         landscape = gFalse;
-       }
-      } else { // rotate == 90 || rotate == 270
-       if (height > width && height > imgWidth) {
-         rotate = 270 - rotate;
-         landscape = gTrue;
-       } else {
-         landscape = gFalse;
-       }
-      }
-    }
-
-    writePSFmt("%%%%PageOrientation: %s\n",
-              landscape ? "Landscape" : "Portrait");
-    writePS("pdfStartPage\n");
-    if (rotate == 0) {
-      imgWidth2 = imgWidth;
-      imgHeight2 = imgHeight;
-    } else if (rotate == 90) {
-      writePS("90 rotate\n");
-      ty = -imgWidth;
-      imgWidth2 = imgHeight;
-      imgHeight2 = imgWidth;
-    } else if (rotate == 180) {
-      writePS("180 rotate\n");
-      imgWidth2 = imgWidth;
-      imgHeight2 = imgHeight;
-      tx = -imgWidth;
-      ty = -imgHeight;
-    } else { // rotate == 270
-      writePS("270 rotate\n");
-      tx = -imgHeight;
-      imgWidth2 = imgHeight;
-      imgHeight2 = imgWidth;
-    }
-    // shrink or expand
-    if (xScale0 > 0 && yScale0 > 0) {
-      xScale = xScale0;
-      yScale = yScale0;
-    } else if ((globalParams->getPSShrinkLarger() &&
-        (width > imgWidth2 || height > imgHeight2)) ||
-       (globalParams->getPSExpandSmaller() &&
-        (width < imgWidth2 && height < imgHeight2))) {
-      xScale = (double)imgWidth2 / (double)width;
-      yScale = (double)imgHeight2 / (double)height;
-      if (yScale < xScale) {
-       xScale = yScale;
-      } else {
-       yScale = xScale;
-      }
-    } else {
-      xScale = yScale = 1;
-      paperWidth = width;
-      paperHeight = height;
-    }
-
-    // deal with odd bounding boxes or clipping
-    if (clipLLX0 < clipURX0 && clipLLY0 < clipURY0) {
-      tx -= xScale * clipLLX0;
-      ty -= yScale * clipLLY0;
-    } else {
-      tx -= xScale * x1;
-      ty -= yScale * y1;
-    }
-    // center
-    if (globalParams->getPSCenter()) {
-      if (clipLLX0 < clipURX0 && clipLLY0 < clipURY0) {
-       tx += (imgWidth2 - xScale * (clipURX0 - clipLLX0)) / 2;
-       ty += (imgHeight2 - yScale * (clipURY0 - clipLLY0)) / 2;
-      } else {
-       tx += (imgWidth2 - xScale * width) / 2;
-       ty += (imgHeight2 - yScale * height) / 2;
-      }
-    }
-    tx += rotate == 0 ? imgLLX + tx0 : imgLLY + ty0;
-    ty += rotate == 0 ? imgLLY + ty0 : -(imgLLX + tx0);
-    if (tx != 0 || ty != 0) {
-      writePSFmt("%g %g translate\n", tx, ty);
-    }
-    if (xScale != 1 || yScale != 1) {
-      writePSFmt("%0.4f %0.4f scale\n", xScale, xScale);
-    }
-    if (clipLLX0 < clipURX0 && clipLLY0 < clipURY0) {
-      writePSFmt("%g %g %g %g re W\n",
-                clipLLX0, clipLLY0, clipURX0 - clipLLX0, clipURY0 - clipLLY0);
-    } else {
-      writePSFmt("%d %d %d %d re W\n", x1, y1, x2 - x1, y2 - y1);
-    }
-
-    writePS("%%EndPageSetup\n");
-    ++seqPage;
-    break;
-
-  case psModeEPS:
-    writePS("pdfStartPage\n");
-    tx = ty = 0;
-    rotate = (360 - state->getRotate()) % 360;
-    if (rotate == 0) {
-    } else if (rotate == 90) {
-      writePS("90 rotate\n");
-      tx = -epsX1;
-      ty = -epsY2;
-    } else if (rotate == 180) {
-      writePS("180 rotate\n");
-      tx = -(epsX1 + epsX2);
-      ty = -(epsY1 + epsY2);
-    } else { // rotate == 270
-      writePS("270 rotate\n");
-      tx = -epsX2;
-      ty = -epsY1;
-    }
-    if (tx != 0 || ty != 0) {
-      writePSFmt("%g %g translate\n", tx, ty);
-    }
-    xScale = yScale = 1;
-    break;
-
-  case psModeForm:
-    writePS("/PaintProc {\n");
-    writePS("begin xpdf begin\n");
-    writePS("pdfStartPage\n");
-    tx = ty = 0;
-    xScale = yScale = 1;
-    rotate = 0;
-    break;
-  }
-
-  if (!checkRange(pageNum))
-    return (gFalse);
-  else
-    return (gTrue);
-}
-
-void PSOutputDev::endPage() {
-  if (overlayCbk) {
-    restoreState(NULL);
-    (*overlayCbk)(this, overlayCbkData);
-  }
-
-  if (mode == psModeForm) {
-    writePS("pdfEndPage\n");
-    writePS("end end\n");
-    writePS("} def\n");
-    writePS("end end\n");
-  } else {
-    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,
-                           double m21, double m22, double m31, double m32) {
-  writePSFmt("[%g %g %g %g %g %g] cm\n", m11, m12, m21, m22, m31, m32);
-}
-
-void PSOutputDev::updateLineDash(GfxState *state) {
-  double *dash;
-  double start;
-  int length, i;
-
-  state->getLineDash(&dash, &length, &start);
-  writePS("[");
-  for (i = 0; i < length; ++i) {
-    writePSFmt("%g%s",
-              dash[i] == 0 ? 1 : dash[i],
-              (i == length-1) ? "" : " ");
-  }
-  writePSFmt("] %g d\n", start);
-}
-
-void PSOutputDev::updateFlatness(GfxState *state) {
-  writePSFmt("%d i\n", state->getFlatness());
-}
-
-void PSOutputDev::updateLineJoin(GfxState *state) {
-  writePSFmt("%d j\n", state->getLineJoin());
-}
-
-void PSOutputDev::updateLineCap(GfxState *state) {
-  writePSFmt("%d J\n", state->getLineCap());
-}
-
-void PSOutputDev::updateMiterLimit(GfxState *state) {
-  writePSFmt("%g M\n", state->getMiterLimit());
-}
-
-void PSOutputDev::updateLineWidth(GfxState *state) {
-  writePSFmt("%g w\n", state->getLineWidth());
-}
-
-void PSOutputDev::updateFillColorSpace(GfxState *state) {
-  switch (level) {
-  case psLevel1:
-  case psLevel1Sep:
-    break;
-  case psLevel2:
-  case psLevel3:
-    if (state->getFillColorSpace()->getMode() != csPattern) {
-      dumpColorSpaceL2(state->getFillColorSpace(), gTrue, gFalse);
-      writePS(" cs\n");
-    }
-    break;
-  case psLevel2Sep:
-  case psLevel3Sep:
-    break;
-  }
-}
-
-void PSOutputDev::updateStrokeColorSpace(GfxState *state) {
-  switch (level) {
-  case psLevel1:
-  case psLevel1Sep:
-    break;
-  case psLevel2:
-  case psLevel3:
-    if (state->getStrokeColorSpace()->getMode() != csPattern) {
-      dumpColorSpaceL2(state->getStrokeColorSpace(), gTrue, gFalse);
-      writePS(" CS\n");
-    }
-    break;
-  case psLevel2Sep:
-  case psLevel3Sep:
-    break;
-  }
-}
-
-void PSOutputDev::updateFillColor(GfxState *state) {
-  GfxColor color;
-  GfxColor *colorPtr;
-  GfxGray gray;
-  GfxCMYK cmyk;
-  GfxSeparationColorSpace *sepCS;
-  double c, m, y, k;
-  int i;
-
-  switch (level) {
-  case psLevel1:
-    state->getFillGray(&gray);
-    writePSFmt("%g g\n", colToDbl(gray));
-    break;
-  case psLevel1Sep:
-    state->getFillCMYK(&cmyk);
-    c = colToDbl(cmyk.c);
-    m = colToDbl(cmyk.m);
-    y = colToDbl(cmyk.y);
-    k = colToDbl(cmyk.k);
-    writePSFmt("%g %g %g %g k\n", c, m, y, k);
-    addProcessColor(c, m, y, k);
-    break;
-  case psLevel2:
-  case psLevel3:
-    if (state->getFillColorSpace()->getMode() != csPattern) {
-      colorPtr = state->getFillColor();
-      writePS("[");
-      for (i = 0; i < state->getFillColorSpace()->getNComps(); ++i) {
-       if (i > 0) {
-         writePS(" ");
-       }
-       writePSFmt("%g", colToDbl(colorPtr->c[i]));
-      }
-      writePS("] sc\n");
-    }
-    break;
-  case psLevel2Sep:
-  case psLevel3Sep:
-    if (state->getFillColorSpace()->getMode() == csSeparation) {
-      sepCS = (GfxSeparationColorSpace *)state->getFillColorSpace();
-      color.c[0] = gfxColorComp1;
-      sepCS->getCMYK(&color, &cmyk);
-      writePSFmt("%g %g %g %g %g (%s) ck\n",
-                colToDbl(state->getFillColor()->c[0]),
-                colToDbl(cmyk.c), colToDbl(cmyk.m),
-                colToDbl(cmyk.y), colToDbl(cmyk.k),
-                sepCS->getName()->getCString());
-      addCustomColor(sepCS);
-    } else {
-      state->getFillCMYK(&cmyk);
-      c = colToDbl(cmyk.c);
-      m = colToDbl(cmyk.m);
-      y = colToDbl(cmyk.y);
-      k = colToDbl(cmyk.k);
-      writePSFmt("%g %g %g %g k\n", c, m, y, k);
-      addProcessColor(c, m, y, k);
-    }
-    break;
-  }
-  t3Cacheable = gFalse;
-}
-
-void PSOutputDev::updateStrokeColor(GfxState *state) {
-  GfxColor color;
-  GfxColor *colorPtr;
-  GfxGray gray;
-  GfxCMYK cmyk;
-  GfxSeparationColorSpace *sepCS;
-  double c, m, y, k;
-  int i;
-
-  switch (level) {
-  case psLevel1:
-    state->getStrokeGray(&gray);
-    writePSFmt("%g G\n", colToDbl(gray));
-    break;
-  case psLevel1Sep:
-    state->getStrokeCMYK(&cmyk);
-    c = colToDbl(cmyk.c);
-    m = colToDbl(cmyk.m);
-    y = colToDbl(cmyk.y);
-    k = colToDbl(cmyk.k);
-    writePSFmt("%g %g %g %g K\n", c, m, y, k);
-    addProcessColor(c, m, y, k);
-    break;
-  case psLevel2:
-  case psLevel3:
-    if (state->getStrokeColorSpace()->getMode() != csPattern) {
-      colorPtr = state->getStrokeColor();
-      writePS("[");
-      for (i = 0; i < state->getStrokeColorSpace()->getNComps(); ++i) {
-       if (i > 0) {
-         writePS(" ");
-       }
-       writePSFmt("%g", colToDbl(colorPtr->c[i]));
-      }
-      writePS("] SC\n");
-    }
-    break;
-  case psLevel2Sep:
-  case psLevel3Sep:
-    if (state->getStrokeColorSpace()->getMode() == csSeparation) {
-      sepCS = (GfxSeparationColorSpace *)state->getStrokeColorSpace();
-      color.c[0] = gfxColorComp1;
-      sepCS->getCMYK(&color, &cmyk);
-      writePSFmt("%g %g %g %g %g (%s) CK\n",
-                colToDbl(state->getStrokeColor()->c[0]),
-                colToDbl(cmyk.c), colToDbl(cmyk.m),
-                colToDbl(cmyk.y), colToDbl(cmyk.k),
-                sepCS->getName()->getCString());
-      addCustomColor(sepCS);
-    } else {
-      state->getStrokeCMYK(&cmyk);
-      c = colToDbl(cmyk.c);
-      m = colToDbl(cmyk.m);
-      y = colToDbl(cmyk.y);
-      k = colToDbl(cmyk.k);
-      writePSFmt("%g %g %g %g K\n", c, m, y, k);
-      addProcessColor(c, m, y, k);
-    }
-    break;
-  }
-  t3Cacheable = gFalse;
-}
-
-void PSOutputDev::addProcessColor(double c, double m, double y, double k) {
-  if (c > 0) {
-    processColors |= psProcessCyan;
-  }
-  if (m > 0) {
-    processColors |= psProcessMagenta;
-  }
-  if (y > 0) {
-    processColors |= psProcessYellow;
-  }
-  if (k > 0) {
-    processColors |= psProcessBlack;
-  }
-}
-
-void PSOutputDev::addCustomColor(GfxSeparationColorSpace *sepCS) {
-  PSOutCustomColor *cc;
-  GfxColor color;
-  GfxCMYK cmyk;
-
-  for (cc = customColors; cc; cc = cc->next) {
-    if (!cc->name->cmp(sepCS->getName())) {
-      return;
-    }
-  }
-  color.c[0] = gfxColorComp1;
-  sepCS->getCMYK(&color, &cmyk);
-  cc = new PSOutCustomColor(colToDbl(cmyk.c), colToDbl(cmyk.m),
-                           colToDbl(cmyk.y), colToDbl(cmyk.k),
-                           sepCS->getName()->copy());
-  cc->next = customColors;
-  customColors = cc;
-}
-
-void PSOutputDev::updateFillOverprint(GfxState *state) {
-  if (level >= psLevel2) {
-    writePSFmt("%s op\n", state->getFillOverprint() ? "true" : "false");
-  }
-}
-
-void PSOutputDev::updateStrokeOverprint(GfxState *state) {
-  if (level >= psLevel2) {
-    writePSFmt("%s OP\n", state->getStrokeOverprint() ? "true" : "false");
-  }
-}
-
-void PSOutputDev::updateFont(GfxState *state) {
-  if (state->getFont()) {
-    writePSFmt("/F%d_%d %g Tf\n",
-              state->getFont()->getID()->num, state->getFont()->getID()->gen,
-              fabs(state->getFontSize()) < 0.00001 ? 0.00001
-                                                   : state->getFontSize());
-  }
-}
-
-void PSOutputDev::updateTextMat(GfxState *state) {
-  double *mat;
-
-  mat = state->getTextMat();
-  if (fabs(mat[0] * mat[3] - mat[1] * mat[2]) < 0.00001) {
-    // avoid a singular (or close-to-singular) matrix
-    writePSFmt("[0.00001 0 0 0.00001 %g %g] Tm\n", mat[4], mat[5]);
-  } else {
-    writePSFmt("[%g %g %g %g %g %g] Tm\n",
-              mat[0], mat[1], mat[2], mat[3], mat[4], mat[5]);
-  }
-}
-
-void PSOutputDev::updateCharSpace(GfxState *state) {
-  writePSFmt("%g Tc\n", state->getCharSpace());
-}
-
-void PSOutputDev::updateRender(GfxState *state) {
-  int rm;
-
-  rm = state->getRender();
-  writePSFmt("%d Tr\n", rm);
-  rm &= 3;
-  if (rm != 0 && rm != 3) {
-    t3Cacheable = gFalse;
-  }
-}
-
-void PSOutputDev::updateRise(GfxState *state) {
-  writePSFmt("%g Ts\n", state->getRise());
-}
-
-void PSOutputDev::updateWordSpace(GfxState *state) {
-  writePSFmt("%g Tw\n", state->getWordSpace());
-}
-
-void PSOutputDev::updateHorizScaling(GfxState *state) {
-  double h;
-
-  h = state->getHorizScaling();
-  if (fabs(h) < 0.01) {
-    h = 0.01;
-  }
-  writePSFmt("%g Tz\n", h);
-}
-
-void PSOutputDev::updateTextPos(GfxState *state) {
-  writePSFmt("%g %g Td\n", state->getLineX(), state->getLineY());
-}
-
-void PSOutputDev::updateTextShift(GfxState *state, double shift) {
-  if (state->getFont()->getWMode()) {
-    writePSFmt("%g TJmV\n", shift);
-  } else {
-    writePSFmt("%g TJm\n", shift);
-  }
-}
-
-void PSOutputDev::stroke(GfxState *state) {
-  doPath(state->getPath());
-  if (t3String) {
-    // if we're construct a cacheable Type 3 glyph, we need to do
-    // everything in the fill color
-    writePS("Sf\n");
-  } else {
-    writePS("S\n");
-  }
-}
-
-void PSOutputDev::fill(GfxState *state) {
-  doPath(state->getPath());
-  writePS("f\n");
-}
-
-void PSOutputDev::eoFill(GfxState *state) {
-  doPath(state->getPath());
-  writePS("f*\n");
-}
-
-void PSOutputDev::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) {
-  PDFRectangle box;
-  Gfx *gfx;
-
-  // define a Type 3 font
-  writePS("8 dict begin\n");
-  writePS("/FontType 3 def\n");
-  writePS("/FontMatrix [1 0 0 1 0 0] def\n");
-  writePSFmt("/FontBBox [%g %g %g %g] def\n",
-            bbox[0], bbox[1], bbox[2], bbox[3]);
-  writePS("/Encoding 256 array def\n");
-  writePS("  0 1 255 { Encoding exch /.notdef put } for\n");
-  writePS("  Encoding 120 /x put\n");
-  writePS("/BuildGlyph {\n");
-  writePS("  exch /CharProcs get exch\n");
-  writePS("  2 copy known not { pop /.notdef } if\n");
-  writePS("  get exec\n");
-  writePS("} bind def\n");
-  writePS("/BuildChar {\n");
-  writePS("  1 index /Encoding get exch get\n");
-  writePS("  1 index /BuildGlyph get exec\n");
-  writePS("} bind def\n");
-  writePS("/CharProcs 1 dict def\n");
-  writePS("CharProcs begin\n");
-  box.x1 = bbox[0];
-  box.y1 = bbox[1];
-  box.x2 = bbox[2];
-  box.y2 = bbox[3];
-  gfx = new Gfx(xref, this, resDict, &box, NULL);
-  writePS("/x {\n");
-  if (paintType == 2) {
-    writePSFmt("%g 0 %g %g %g %g setcachedevice\n",
-              xStep, bbox[0], bbox[1], bbox[2], bbox[3]);
-  } else {
-    writePSFmt("%g 0 setcharwidth\n", xStep);
-  }
-  inType3Char = gTrue;
-  ++numTilingPatterns;
-  gfx->display(str);
-  --numTilingPatterns;
-  inType3Char = gFalse;
-  writePS("} def\n");
-  delete gfx;
-  writePS("end\n");
-  writePS("currentdict end\n");
-  writePSFmt("/xpdfTile%d exch definefont pop\n", numTilingPatterns);
-
-  // draw the tiles
-  writePSFmt("/xpdfTile%d findfont setfont\n", numTilingPatterns);
-  writePSFmt("gsave [%g %g %g %g %g %g] concat\n",
-            mat[0], mat[1], mat[2], mat[3], mat[4], mat[5]);
-  writePSFmt("%d 1 %d { %g exch %g mul m %d 1 %d { pop (x) show } for } for\n",
-            y0, y1 - 1, x0 * xStep, yStep, x0, x1 - 1);
-  writePS("grestore\n");
-}
-
-void PSOutputDev::functionShadedFill(GfxState *state,
-                                    GfxFunctionShading *shading) {
-  double x0, y0, x1, y1;
-  double *mat;
-  int i;
-
-  shading->getDomain(&x0, &y0, &x1, &y1);
-  mat = shading->getMatrix();
-  writePSFmt("/mat [%g %g %g %g %g %g] def\n",
-            mat[0], mat[1], mat[2], mat[3], mat[4], mat[5]);
-  writePSFmt("/n %d def\n", shading->getColorSpace()->getNComps());
-  if (shading->getNFuncs() == 1) {
-    writePS("/func ");
-    cvtFunction(shading->getFunc(0));
-    writePS("def\n");
-  } else {
-    writePS("/func {\n");
-    for (i = 0; i < shading->getNFuncs(); ++i) {
-      if (i < shading->getNFuncs() - 1) {
-       writePS("2 copy\n");
-      }
-      cvtFunction(shading->getFunc(i));
-      writePS("exec\n");
-      if (i < shading->getNFuncs() - 1) {
-       writePS("3 1 roll\n");
-      }
-    }
-    writePS("} def\n");
-  }
-  writePSFmt("%g %g %g %g 0 funcSH\n", x0, y0, x1, y1);
-}
-
-void PSOutputDev::axialShadedFill(GfxState *state, GfxAxialShading *shading) {
-  double xMin, yMin, xMax, yMax;
-  double x0, y0, x1, y1, dx, dy, mul;
-  double tMin, tMax, t, t0, t1;
-  int i;
-
-  // get the clip region bbox
-  state->getUserClipBBox(&xMin, &yMin, &xMax, &yMax);
-
-  // compute min and max t values, based on the four corners of the
-  // clip region bbox
-  shading->getCoords(&x0, &y0, &x1, &y1);
-  dx = x1 - x0;
-  dy = y1 - y0;
-  mul = 1 / (dx * dx + dy * dy);
-  tMin = tMax = ((xMin - x0) * dx + (yMin - y0) * dy) * mul;
-  t = ((xMin - x0) * dx + (yMax - y0) * dy) * mul;
-  if (t < tMin) {
-    tMin = t;
-  } else if (t > tMax) {
-    tMax = t;
-  }
-  t = ((xMax - x0) * dx + (yMin - y0) * dy) * mul;
-  if (t < tMin) {
-    tMin = t;
-  } else if (t > tMax) {
-    tMax = t;
-  }
-  t = ((xMax - x0) * dx + (yMax - y0) * dy) * mul;
-  if (t < tMin) {
-    tMin = t;
-  } else if (t > tMax) {
-    tMax = t;
-  }
-  if (tMin < 0 && !shading->getExtend0()) {
-    tMin = 0;
-  }
-  if (tMax > 1 && !shading->getExtend1()) {
-    tMax = 1;
-  }
-
-  // get the function domain
-  t0 = shading->getDomain0();
-  t1 = shading->getDomain1();
-
-  // generate the PS code
-  writePSFmt("/t0 %g def\n", t0);
-  writePSFmt("/t1 %g def\n", t1);
-  writePSFmt("/dt %g def\n", t1 - t0);
-  writePSFmt("/x0 %g def\n", x0);
-  writePSFmt("/y0 %g def\n", y0);
-  writePSFmt("/dx %g def\n", x1 - x0);
-  writePSFmt("/x1 %g def\n", x1);
-  writePSFmt("/y1 %g def\n", y1);
-  writePSFmt("/dy %g def\n", y1 - y0);
-  writePSFmt("/xMin %g def\n", xMin);
-  writePSFmt("/yMin %g def\n", yMin);
-  writePSFmt("/xMax %g def\n", xMax);
-  writePSFmt("/yMax %g def\n", yMax);
-  writePSFmt("/n %d def\n", shading->getColorSpace()->getNComps());
-  if (shading->getNFuncs() == 1) {
-    writePS("/func ");
-    cvtFunction(shading->getFunc(0));
-    writePS("def\n");
-  } else {
-    writePS("/func {\n");
-    for (i = 0; i < shading->getNFuncs(); ++i) {
-      if (i < shading->getNFuncs() - 1) {
-       writePS("dup\n");
-      }
-      cvtFunction(shading->getFunc(i));
-      writePS("exec\n");
-      if (i < shading->getNFuncs() - 1) {
-       writePS("exch\n");
-      }
-    }
-    writePS("} def\n");
-  }
-  writePSFmt("%g %g 0 axialSH\n", tMin, tMax);
-}
-
-void PSOutputDev::radialShadedFill(GfxState *state,
-                                  GfxRadialShading *shading) {
-  double x0, y0, r0, x1, y1, r1, t0, t1, sMin, sMax;
-  double xMin, yMin, xMax, yMax;
-  double d0, d1;
-  int i;
-
-  // get the shading info
-  shading->getCoords(&x0, &y0, &r0, &x1, &y1, &r1);
-  t0 = shading->getDomain0();
-  t1 = shading->getDomain1();
-
-  // compute the (possibly extended) s range
-  sMin = 0;
-  sMax = 1;
-  if (shading->getExtend0()) {
-    if (r0 < r1) {
-      // extend the smaller end
-      sMin = -r0 / (r1 - r0);
-    } else {
-      // extend the larger end
-      state->getUserClipBBox(&xMin, &yMin, &xMax, &yMax);
-      d0 = (x0 - xMin) * (x0 - xMin);
-      d1 = (x0 - xMax) * (x0 - xMax);
-      sMin = d0 > d1 ? d0 : d1;
-      d0 = (y0 - yMin) * (y0 - yMin);
-      d1 = (y0 - yMax) * (y0 - yMax);
-      sMin += d0 > d1 ? d0 : d1;
-      sMin = (sqrt(sMin) - r0) / (r1 - r0);
-      if (sMin > 0) {
-       sMin = 0;
-      } else if (sMin < -20) {
-       // sanity check
-       sMin = -20;
-      }
-    }
-  }
-  if (shading->getExtend1()) {
-    if (r1 < r0) {
-      // extend the smaller end
-      sMax = -r0 / (r1 - r0);
-    } else if (r1 > r0) {
-      // extend the larger end
-      state->getUserClipBBox(&xMin, &yMin, &xMax, &yMax);
-      d0 = (x1 - xMin) * (x1 - xMin);
-      d1 = (x1 - xMax) * (x1 - xMax);
-      sMax = d0 > d1 ? d0 : d1;
-      d0 = (y1 - yMin) * (y1 - yMin);
-      d1 = (y1 - yMax) * (y1 - yMax);
-      sMax += d0 > d1 ? d0 : d1;
-      sMax = (sqrt(sMax) - r0) / (r1 - r0);
-      if (sMax < 1) {
-       sMax = 1;
-      } else if (sMax > 20) {
-       // sanity check
-       sMax = 20;
-      }
-    }
-  }
-
-  // generate the PS code
-  writePSFmt("/x0 %g def\n", x0);
-  writePSFmt("/x1 %g def\n", x1);
-  writePSFmt("/dx %g def\n", x1 - x0);
-  writePSFmt("/y0 %g def\n", y0);
-  writePSFmt("/y1 %g def\n", y1);
-  writePSFmt("/dy %g def\n", y1 - y0);
-  writePSFmt("/r0 %g def\n", r0);
-  writePSFmt("/r1 %g def\n", r1);
-  writePSFmt("/dr %g def\n", r1 - r0);
-  writePSFmt("/t0 %g def\n", t0);
-  writePSFmt("/t1 %g def\n", t1);
-  writePSFmt("/dt %g def\n", t1 - t0);
-  writePSFmt("/n %d def\n", shading->getColorSpace()->getNComps());
-  if (shading->getNFuncs() == 1) {
-    writePS("/func ");
-    cvtFunction(shading->getFunc(0));
-    writePS("def\n");
-  } else {
-    writePS("/func {\n");
-    for (i = 0; i < shading->getNFuncs(); ++i) {
-      if (i < shading->getNFuncs() - 1) {
-       writePS("dup\n");
-      }
-      cvtFunction(shading->getFunc(i));
-      writePS("exec\n");
-      if (i < shading->getNFuncs() - 1) {
-       writePS("exch\n");
-      }
-    }
-    writePS("} def\n");
-  }
-  writePSFmt("%g %g 0 radialSH\n", sMin, sMax);
-}
-
-void PSOutputDev::clip(GfxState *state) {
-  doPath(state->getPath());
-  writePS("W\n");
-}
-
-void PSOutputDev::eoClip(GfxState *state) {
-  doPath(state->getPath());
-  writePS("W*\n");
-}
-
-void PSOutputDev::doPath(GfxPath *path) {
-  GfxSubpath *subpath;
-  double x0, y0, x1, y1, x2, y2, x3, y3, x4, y4;
-  int n, m, i, j;
-
-  n = path->getNumSubpaths();
-
-  if (n == 1 && path->getSubpath(0)->getNumPoints() == 5) {
-    subpath = path->getSubpath(0);
-    x0 = subpath->getX(0);
-    y0 = subpath->getY(0);
-    x4 = subpath->getX(4);
-    y4 = subpath->getY(4);
-    if (x4 == x0 && y4 == y0) {
-      x1 = subpath->getX(1);
-      y1 = subpath->getY(1);
-      x2 = subpath->getX(2);
-      y2 = subpath->getY(2);
-      x3 = subpath->getX(3);
-      y3 = subpath->getY(3);
-      if (x0 == x1 && x2 == x3 && y0 == y3 && y1 == y2) {
-       writePSFmt("%g %g %g %g re\n",
-                  x0 < x2 ? x0 : x2, y0 < y1 ? y0 : y1,
-                  fabs(x2 - x0), fabs(y1 - y0));
-       return;
-      } else if (x0 == x3 && x1 == x2 && y0 == y1 && y2 == y3) {
-       writePSFmt("%g %g %g %g re\n",
-                  x0 < x1 ? x0 : x1, y0 < y2 ? y0 : y2,
-                  fabs(x1 - x0), fabs(y2 - y0));
-       return;
-      }
-    }
-  }
-
-  for (i = 0; i < n; ++i) {
-    subpath = path->getSubpath(i);
-    m = subpath->getNumPoints();
-    writePSFmt("%g %g m\n", subpath->getX(0), subpath->getY(0));
-    j = 1;
-    while (j < m) {
-      if (subpath->getCurve(j)) {
-       writePSFmt("%g %g %g %g %g %g c\n", subpath->getX(j), subpath->getY(j),
-                  subpath->getX(j+1), subpath->getY(j+1),
-                  subpath->getX(j+2), subpath->getY(j+2));
-       j += 3;
-      } else {
-       writePSFmt("%g %g l\n", subpath->getX(j), subpath->getY(j));
-       ++j;
-      }
-    }
-    if (subpath->isClosed()) {
-      writePS("h\n");
-    }
-  }
-}
-
-void PSOutputDev::drawString(GfxState *state, GString *s) {
-  GfxFont *font;
-  int wMode;
-  GString *s2;
-  double dx, dy, dx2, dy2, originX, originY;
-  char *p;
-  UnicodeMap *uMap;
-  CharCode code;
-  Unicode u[8];
-  char buf[8];
-  int len, nChars, uLen, n, m, i, j;
-
-  // check for invisible text -- this is used by Acrobat Capture
-  if (state->getRender() == 3) {
-    return;
-  }
-
-  // ignore empty strings
-  if (s->getLength() == 0) {
-    return;
-  }
-
-  // get the font
-  if (!(font = state->getFont())) {
-    return;
-  }
-  wMode = font->getWMode();
-
-  // check for a subtitute 16-bit font
-  uMap = NULL;
-  if (font->isCIDFont()) {
-    for (i = 0; i < font16EncLen; ++i) {
-      if (font->getID()->num == font16Enc[i].fontID.num &&
-         font->getID()->gen == font16Enc[i].fontID.gen) {
-       uMap = globalParams->getUnicodeMap(font16Enc[i].enc);
-       break;
-      }
-    }
-  }
-
-  // compute width of chars in string, ignoring char spacing and word
-  // spacing -- the Tj operator will adjust for the metrics of the
-  // font that's actually used
-  dx = dy = 0;
-  nChars = 0;
-  p = s->getCString();
-  len = s->getLength();
-  if (font->isCIDFont()) {
-    s2 = new GString();
-  } else {
-    s2 = s;
-  }
-  while (len > 0) {
-    n = font->getNextChar(p, len, &code,
-                         u, (int)(sizeof(u) / sizeof(Unicode)), &uLen,
-                         &dx2, &dy2, &originX, &originY);
-    if (font->isCIDFont()) {
-      if (uMap) {
-       for (i = 0; i < uLen; ++i) {
-         m = uMap->mapUnicode(u[i], buf, (int)sizeof(buf));
-         for (j = 0; j < m; ++j) {
-           s2->append(buf[j]);
-         }
-       }
-       //~ this really needs to get the number of chars in the target
-       //~ encoding - which may be more than the number of Unicode
-       //~ chars
-       nChars += uLen;
-      } else {
-       s2->append((char)((code >> 8) & 0xff));
-       s2->append((char)(code & 0xff));
-       ++nChars;
-      }
-    }
-    dx += dx2;
-    dy += dy2;
-    p += n;
-    len -= n;
-  }
-  dx *= state->getFontSize() * state->getHorizScaling();
-  dy *= state->getFontSize();
-  if (uMap) {
-    uMap->decRefCnt();
-  }
-
-  if (s2->getLength() > 0) {
-    writePSString(s2);
-    if (font->isCIDFont()) {
-      if (wMode) {
-       writePSFmt(" %d %g Tj16V\n", nChars, dy);
-      } else {
-       writePSFmt(" %d %g Tj16\n", nChars, dx);
-      }
-    } else {
-      writePSFmt(" %g Tj\n", dx);
-    }
-  }
-  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,
-                               int width, int height, GBool invert,
-                               GBool inlineImg) {
-  int len;
-
-  len = height * ((width + 7) / 8);
-  if (level == psLevel1 || level == psLevel1Sep) {
-    doImageL1(ref, NULL, invert, inlineImg, str, width, height, len);
-  } else {
-    doImageL2(ref, NULL, invert, inlineImg, str, width, height, len,
-             NULL, NULL, 0, 0, gFalse);
-  }
-}
-
-void PSOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
-                           int width, int height, GfxImageColorMap *colorMap,
-                           int *maskColors, GBool inlineImg) {
-  int len;
-
-  len = height * ((width * colorMap->getNumPixelComps() *
-                  colorMap->getBits() + 7) / 8);
-  switch (level) {
-  case psLevel1:
-    doImageL1(ref, colorMap, gFalse, inlineImg, str, width, height, len);
-    break;
-  case psLevel1Sep:
-    //~ handle indexed, separation, ... color spaces
-    doImageL1Sep(colorMap, gFalse, inlineImg, str, width, height, len);
-    break;
-  case psLevel2:
-  case psLevel2Sep:
-  case psLevel3:
-  case psLevel3Sep:
-    doImageL2(ref, colorMap, gFalse, inlineImg, str,
-             width, height, len, maskColors, NULL, 0, 0, gFalse);
-    break;
-  }
-  t3Cacheable = gFalse;
-}
-
-void PSOutputDev::drawMaskedImage(GfxState *state, Object *ref, Stream *str,
-                                 int width, int height,
-                                 GfxImageColorMap *colorMap,
-                                 Stream *maskStr,
-                                 int maskWidth, int maskHeight,
-                                 GBool maskInvert) {
-  int len;
-
-  len = height * ((width * colorMap->getNumPixelComps() *
-                  colorMap->getBits() + 7) / 8);
-  switch (level) {
-  case psLevel1:
-    doImageL1(ref, colorMap, gFalse, gFalse, str, width, height, len);
-    break;
-  case psLevel1Sep:
-    //~ handle indexed, separation, ... color spaces
-    doImageL1Sep(colorMap, gFalse, gFalse, str, width, height, len);
-    break;
-  case psLevel2:
-  case psLevel2Sep:
-  case psLevel3:
-  case psLevel3Sep:
-    doImageL2(ref, colorMap, gFalse, gFalse, str, width, height, len,
-             NULL, maskStr, maskWidth, maskHeight, maskInvert);
-    break;
-  }
-  t3Cacheable = gFalse;
-}
-
-void PSOutputDev::doImageL1(Object *ref, GfxImageColorMap *colorMap,
-                           GBool invert, GBool inlineImg,
-                           Stream *str, int width, int height, int len) {
-  ImageStream *imgStr;
-  Guchar pixBuf[gfxColorMaxComps];
-  GfxGray gray;
-  int col, x, y, c, i;
-
-  if (inType3Char && !colorMap) {
-    if (inlineImg) {
-      // create an array
-      str = new FixedLengthEncoder(str, len);
-      str = new ASCIIHexEncoder(str);
-      str->reset();
-      col = 0;
-      writePS("[<");
-      do {
-       do {
-         c = str->getChar();
-       } while (c == '\n' || c == '\r');
-       if (c == '>' || c == EOF) {
-         break;
-       }
-       writePSChar(c);
-       ++col;
-       // each line is: "<...data...><eol>"
-       // so max data length = 255 - 4 = 251
-       // but make it 240 just to be safe
-       // chunks are 2 bytes each, so we need to stop on an even col number
-       if (col == 240) {
-         writePS(">\n<");
-         col = 0;
-       }
-      } while (c != '>' && c != EOF);
-      writePS(">]\n");
-      writePS("0\n");
-      str->close();
-      delete str;
-    } else {
-      // set up to use the array already created by setupImages()
-      writePSFmt("ImData_%d_%d 0\n", ref->getRefNum(), ref->getRefGen());
-    }
-  }
-
-  // image/imagemask command
-  if (inType3Char && !colorMap) {
-    writePSFmt("%d %d %s [%d 0 0 %d 0 %d] pdfImM1a\n",
-              width, height, invert ? "true" : "false",
-              width, -height, height);
-  } else if (colorMap) {
-    writePSFmt("%d %d 8 [%d 0 0 %d 0 %d] pdfIm1\n",
-              width, height,
-              width, -height, height);
-  } else {
-    writePSFmt("%d %d %s [%d 0 0 %d 0 %d] pdfImM1\n",
-              width, height, invert ? "true" : "false",
-              width, -height, height);
-  }
-
-  // image data
-  if (!(inType3Char && !colorMap)) {
-
-    if (colorMap) {
-
-      // set up to process the data stream
-      imgStr = new ImageStream(str, width, colorMap->getNumPixelComps(),
-                              colorMap->getBits());
-      imgStr->reset();
-
-      // process the data stream
-      i = 0;
-      for (y = 0; y < height; ++y) {
-
-       // write the line
-       for (x = 0; x < width; ++x) {
-         imgStr->getPixel(pixBuf);
-         colorMap->getGray(pixBuf, &gray);
-         writePSFmt("%02x", colToByte(gray));
-         if (++i == 32) {
-           writePSChar('\n');
-           i = 0;
-         }
-       }
-      }
-      if (i != 0) {
-       writePSChar('\n');
-      }
-      delete imgStr;
-
-    // imagemask
-    } else {
-      str->reset();
-      i = 0;
-      for (y = 0; y < height; ++y) {
-       for (x = 0; x < width; x += 8) {
-         writePSFmt("%02x", str->getChar() & 0xff);
-         if (++i == 32) {
-           writePSChar('\n');
-           i = 0;
-         }
-       }
-      }
-      if (i != 0) {
-       writePSChar('\n');
-      }
-      str->close();
-    }
-  }
-}
-
-void PSOutputDev::doImageL1Sep(GfxImageColorMap *colorMap,
-                              GBool invert, GBool inlineImg,
-                              Stream *str, int width, int height, int len) {
-  ImageStream *imgStr;
-  Guchar *lineBuf;
-  Guchar pixBuf[gfxColorMaxComps];
-  GfxCMYK cmyk;
-  int x, y, i, comp;
-
-  // width, height, matrix, bits per component
-  writePSFmt("%d %d 8 [%d 0 0 %d 0 %d] pdfIm1Sep\n",
-            width, height,
-            width, -height, height);
-
-  // allocate a line buffer
-  lineBuf = (Guchar *)gmalloc(4 * width);
-
-  // set up to process the data stream
-  imgStr = new ImageStream(str, width, colorMap->getNumPixelComps(),
-                          colorMap->getBits());
-  imgStr->reset();
-
-  // process the data stream
-  i = 0;
-  for (y = 0; y < height; ++y) {
-
-    // read the line
-    for (x = 0; x < width; ++x) {
-      imgStr->getPixel(pixBuf);
-      colorMap->getCMYK(pixBuf, &cmyk);
-      lineBuf[4*x+0] = colToByte(cmyk.c);
-      lineBuf[4*x+1] = colToByte(cmyk.m);
-      lineBuf[4*x+2] = colToByte(cmyk.y);
-      lineBuf[4*x+3] = colToByte(cmyk.k);
-      addProcessColor(colToDbl(cmyk.c), colToDbl(cmyk.m),
-                     colToDbl(cmyk.y), colToDbl(cmyk.k));
-    }
-
-    // write one line of each color component
-    for (comp = 0; comp < 4; ++comp) {
-      for (x = 0; x < width; ++x) {
-       writePSFmt("%02x", lineBuf[4*x + comp]);
-       if (++i == 32) {
-         writePSChar('\n');
-         i = 0;
-       }
-      }
-    }
-  }
-
-  if (i != 0) {
-    writePSChar('\n');
-  }
-
-  delete imgStr;
-  gfree(lineBuf);
-}
-
-void PSOutputDev::doImageL2(Object *ref, GfxImageColorMap *colorMap,
-                           GBool invert, GBool inlineImg,
-                           Stream *str, int width, int height, int len,
-                           int *maskColors, Stream *maskStr,
-                           int maskWidth, int maskHeight, GBool maskInvert) {
-  ImageStream *imgStr;
-  Guchar *line, *pix;
-  GString *s;
-  int n, numComps;
-  GBool useRLE, useASCII, useASCIIHex, useCompressed;
-  GfxSeparationColorSpace *sepCS;
-  GfxColor color;
-  GfxCMYK cmyk;
-  int c;
-  int col, i, x, x0, y, y0, maskXor;
-
-  // color key masking
-  if (maskColors && colorMap && !inlineImg) {
-    // can't read the stream twice for inline images -- but masking
-    // isn't allowed with inline images anyway
-    writePS("[\n");
-    numComps = colorMap->getNumPixelComps();
-    imgStr = new ImageStream(str, width, numComps, colorMap->getBits());
-    imgStr->reset();
-    for (y = 0, y0 = 0; y < height; ++y) {
-      if (!(line = imgStr->getLine())) {
-       break;
-      }
-      for (x = 0, x0 = 0, pix = line; x < width; ++x, pix += numComps) {
-       for (i = 0; i < numComps; ++i) {
-         if (pix[i] < maskColors[2*i] ||
-             pix[i] > maskColors[2*i+1]) {
-           break;
-         }
-       }
-       if (i == numComps) {
-         if (y0 < y) {
-           writePSFmt("0 %d %d %d\n", height - y, width, y - y0);
-         }
-         if (x0 < x) {
-           writePSFmt("%d %d %d 1\n", x0, height - y - 1, x - x0);
-         }
-         x0 = x + 1;
-         y0 = y + 1;
-       }
-      }
-      if (x0 > 0 && x0 < width) {
-       writePSFmt("%d %d %d 1\n", x0, height - y - 1, width - x0);
-      }
-    }
-    if (y0 < height) {
-      writePSFmt("0 0 %d %d\n", width, height - y0);
-    }
-    delete imgStr;
-    str->close();
-    writePSFmt("] %d %d pdfImClip\n", width, height);
-
-  // explicit masking
-  } else if (maskStr) {
-    writePS("[\n");
-    imgStr = new ImageStream(maskStr, maskWidth, 1, 1);
-    imgStr->reset();
-    maskXor = maskInvert ? 1 : 0;
-    for (y = 0, y0 = 0; y < maskHeight; ++y) {
-      if (!(line = imgStr->getLine())) {
-       break;
-      }
-      for (x = 0, x0 = 0, pix = line; x < maskWidth; ++x, ++pix) {
-       if (*pix ^ maskXor) {
-         if (y0 < y) {
-           writePSFmt("0 %d %d %d\n", maskHeight - y, maskWidth, y - y0);
-         }
-         if (x0 < x) {
-           writePSFmt("%d %d %d 1\n", x0, maskHeight - y - 1, x - x0);
-         }
-         x0 = x + 1;
-         y0 = y + 1;
-       }
-      }
-      if (x0 > 0 && x0 < maskWidth) {
-       writePSFmt("%d %d %d 1\n", x0, maskHeight - y - 1, maskWidth - x0);
-      }
-    }
-    if (y0 < maskHeight) {
-      writePSFmt("0 0 %d %d\n", maskWidth, maskHeight - y0);
-    }
-    delete imgStr;
-    maskStr->close();
-    writePSFmt("] %d %d pdfImClip\n", maskWidth, maskHeight);
-  }
-
-  // color space
-  if (colorMap) {
-    dumpColorSpaceL2(colorMap->getColorSpace(), gFalse, gTrue);
-    writePS(" setcolorspace\n");
-  }
-
-  useASCIIHex = globalParams->getPSASCIIHex();
-
-  // set up the image data
-  if (mode == psModeForm || inType3Char) {
-    if (inlineImg) {
-      // create an array
-      str = new FixedLengthEncoder(str, len);
-      if (useASCIIHex) {
-       str = new ASCIIHexEncoder(str);
-      } else {
-       str = new ASCII85Encoder(str);
-      }
-      str->reset();
-      col = 0;
-      writePS((char *)(useASCIIHex ? "[<" : "[<~"));
-      do {
-       do {
-         c = str->getChar();
-       } while (c == '\n' || c == '\r');
-       if (c == (useASCIIHex ? '>' : '~') || c == EOF) {
-         break;
-       }
-       if (c == 'z') {
-         writePSChar(c);
-         ++col;
-       } else {
-         writePSChar(c);
-         ++col;
-         for (i = 1; i <= (useASCIIHex ? 1 : 4); ++i) {
-           do {
-             c = str->getChar();
-           } while (c == '\n' || c == '\r');
-           if (c == (useASCIIHex ? '>' : '~') || c == EOF) {
-             break;
-           }
-           writePSChar(c);
-           ++col;
-         }
-       }
-       // each line is: "<~...data...~><eol>"
-       // so max data length = 255 - 6 = 249
-       // chunks are 1 or 5 bytes each, so we have to stop at 245
-       // but make it 240 just to be safe
-       if (col > 240) {
-         writePS((char *)(useASCIIHex ? ">\n<" : "~>\n<~"));
-         col = 0;
-       }
-      } while (c != (useASCIIHex ? '>' : '~') && c != EOF);
-      writePS((char *)(useASCIIHex ? ">]\n" : "~>]\n"));
-      writePS("0\n");
-      str->close();
-      delete str;
-    } else {
-      // set up to use the array already created by setupImages()
-      writePSFmt("ImData_%d_%d 0\n", ref->getRefNum(), ref->getRefGen());
-    }
-  }
-
-  // image dictionary
-  writePS("<<\n  /ImageType 1\n");
-
-  // width, height, matrix, bits per component
-  writePSFmt("  /Width %d\n", width);
-  writePSFmt("  /Height %d\n", height);
-  writePSFmt("  /ImageMatrix [%d 0 0 %d 0 %d]\n", width, -height, height);
-  if (colorMap && colorMap->getColorSpace()->getMode() == csDeviceN) {
-    writePSFmt("  /BitsPerComponent 8\n");
-  } else {
-    writePSFmt("  /BitsPerComponent %d\n",
-              colorMap ? colorMap->getBits() : 1);
-  }
-
-  // decode 
-  if (colorMap) {
-    writePS("  /Decode [");
-    if ((level == psLevel2Sep || level == psLevel3Sep) &&
-       colorMap->getColorSpace()->getMode() == csSeparation) {
-      // this matches up with the code in the pdfImSep operator
-      n = (1 << colorMap->getBits()) - 1;
-      writePSFmt("%g %g", colorMap->getDecodeLow(0) * n,
-                colorMap->getDecodeHigh(0) * n);
-    } else if (colorMap->getColorSpace()->getMode() == csDeviceN) {
-      numComps = ((GfxDeviceNColorSpace *)colorMap->getColorSpace())->
-                  getAlt()->getNComps();
-      for (i = 0; i < numComps; ++i) {
-       if (i > 0) {
-         writePS(" ");
-       }
-       writePS("0 1");
-      }
-    } else {
-      numComps = colorMap->getNumPixelComps();
-      for (i = 0; i < numComps; ++i) {
-       if (i > 0) {
-         writePS(" ");
-       }
-       writePSFmt("%g %g", colorMap->getDecodeLow(i),
-                  colorMap->getDecodeHigh(i));
-      }
-    }
-    writePS("]\n");
-  } else {
-    writePSFmt("  /Decode [%d %d]\n", invert ? 1 : 0, invert ? 0 : 1);
-  }
-
-  if (mode == psModeForm || inType3Char) {
-
-    // data source
-    writePS("  /DataSource { 2 copy get exch 1 add exch }\n");
-
-    // end of image dictionary
-    writePSFmt(">>\n%s\n", colorMap ? "image" : "imagemask");
-
-    // get rid of the array and index
-    writePS("pop pop\n");
-
-  } else {
-
-    // data source
-    writePS("  /DataSource currentfile\n");
-    s = str->getPSFilter(level < psLevel2 ? 1 : level < psLevel3 ? 2 : 3,
-                        "    ");
-    if ((colorMap && colorMap->getColorSpace()->getMode() == csDeviceN) ||
-       inlineImg || !s) {
-      useRLE = gTrue;
-      useASCII = gTrue;
-      useCompressed = gFalse;
-    } else {
-      useRLE = gFalse;
-      useASCII = str->isBinary();
-      useCompressed = gTrue;
-    }
-    if (useASCII) {
-      writePSFmt("    /ASCII%sDecode filter\n",
-                useASCIIHex ? "Hex" : "85");
-    }
-    if (useRLE) {
-      writePS("    /RunLengthDecode filter\n");
-    }
-    if (useCompressed) {
-      writePS(s->getCString());
-    }
-    if (s) {
-      delete s;
-    }
-
-    // cut off inline image streams at appropriate length
-    if (inlineImg) {
-      str = new FixedLengthEncoder(str, len);
-    } else if (useCompressed) {
-      str = str->getBaseStream();
-    }
-
-    // recode DeviceN data
-    if (colorMap && colorMap->getColorSpace()->getMode() == csDeviceN) {
-      str = new DeviceNRecoder(str, width, height, colorMap);
-    }
-
-    // add RunLengthEncode and ASCIIHex/85 encode filters
-    if (useRLE) {
-      str = new RunLengthEncoder(str);
-    }
-    if (useASCII) {
-      if (useASCIIHex) {
-       str = new ASCIIHexEncoder(str);
-      } else {
-       str = new ASCII85Encoder(str);
-      }
-    }
-
-    // end of image dictionary
-    writePS(">>\n");
-#if OPI_SUPPORT
-    if (opi13Nest) {
-      if (inlineImg) {
-       // this can't happen -- OPI dictionaries are in XObjects
-       error(-1, "Internal: OPI in inline image");
-       n = 0;
-      } else {
-       // need to read the stream to count characters -- the length
-       // is data-dependent (because of ASCII and RLE filters)
-       str->reset();
-       n = 0;
-       while ((c = str->getChar()) != EOF) {
-         ++n;
-       }
-       str->close();
-      }
-      // +6/7 for "pdfIm\n" / "pdfImM\n"
-      // +8 for newline + trailer
-      n += colorMap ? 14 : 15;
-      writePSFmt("%%%%BeginData: %d Hex Bytes\n", n);
-    }
-#endif
-    if ((level == psLevel2Sep || level == psLevel3Sep) && colorMap &&
-       colorMap->getColorSpace()->getMode() == csSeparation) {
-      color.c[0] = gfxColorComp1;
-      sepCS = (GfxSeparationColorSpace *)colorMap->getColorSpace();
-      sepCS->getCMYK(&color, &cmyk);
-      writePSFmt("%g %g %g %g (%s) pdfImSep\n",
-                colToDbl(cmyk.c), colToDbl(cmyk.m),
-                colToDbl(cmyk.y), colToDbl(cmyk.k),
-                sepCS->getName()->getCString());
-    } else {
-      writePSFmt("%s\n", colorMap ? "pdfIm" : "pdfImM");
-    }
-
-    // copy the stream data
-    str->reset();
-    while ((c = str->getChar()) != EOF) {
-      writePSChar(c);
-    }
-    str->close();
-
-    // add newline and trailer to the end
-    writePSChar('\n');
-    writePS("%-EOD-\n");
-#if OPI_SUPPORT
-    if (opi13Nest) {
-      writePS("%%EndData\n");
-    }
-#endif
-
-    // delete encoders
-    if (useRLE || useASCII || inlineImg) {
-      delete str;
-    }
-  }
-
-  if ((maskColors && colorMap && !inlineImg) || maskStr) {
-    writePS("pdfImClipEnd\n");
-  }
-}
-
-void PSOutputDev::dumpColorSpaceL2(GfxColorSpace *colorSpace,
-                                  GBool genXform, GBool updateColors) {
-  GfxCalGrayColorSpace *calGrayCS;
-  GfxCalRGBColorSpace *calRGBCS;
-  GfxLabColorSpace *labCS;
-  GfxIndexedColorSpace *indexedCS;
-  GfxSeparationColorSpace *separationCS;
-  GfxDeviceNColorSpace *deviceNCS;
-  GfxColorSpace *baseCS;
-  Guchar *lookup, *p;
-  double x[gfxColorMaxComps], y[gfxColorMaxComps];
-  GfxColor color;
-  GfxCMYK cmyk;
-  Function *func;
-  int n, numComps, numAltComps;
-  int byte;
-  int i, j, k;
-
-  switch (colorSpace->getMode()) {
-
-  case csDeviceGray:
-    writePS("/DeviceGray");
-    if (genXform) {
-      writePS(" {}");
-    }
-    if (updateColors) {
-      processColors |= psProcessBlack;
-    }
-    break;
-
-  case csCalGray:
-    calGrayCS = (GfxCalGrayColorSpace *)colorSpace;
-    writePS("[/CIEBasedA <<\n");
-    writePSFmt(" /DecodeA {%g exp} bind\n", calGrayCS->getGamma());
-    writePSFmt(" /MatrixA [%g %g %g]\n",
-              calGrayCS->getWhiteX(), calGrayCS->getWhiteY(),
-              calGrayCS->getWhiteZ());
-    writePSFmt(" /WhitePoint [%g %g %g]\n",
-              calGrayCS->getWhiteX(), calGrayCS->getWhiteY(),
-              calGrayCS->getWhiteZ());
-    writePSFmt(" /BlackPoint [%g %g %g]\n",
-              calGrayCS->getBlackX(), calGrayCS->getBlackY(),
-              calGrayCS->getBlackZ());
-    writePS(">>]");
-    if (genXform) {
-      writePS(" {}");
-    }
-    if (updateColors) {
-      processColors |= psProcessBlack;
-    }
-    break;
-
-  case csDeviceRGB:
-    writePS("/DeviceRGB");
-    if (genXform) {
-      writePS(" {}");
-    }
-    if (updateColors) {
-      processColors |= psProcessCMYK;
-    }
-    break;
-
-  case csCalRGB:
-    calRGBCS = (GfxCalRGBColorSpace *)colorSpace;
-    writePS("[/CIEBasedABC <<\n");
-    writePSFmt(" /DecodeABC [{%g exp} bind {%g exp} bind {%g exp} bind]\n",
-              calRGBCS->getGammaR(), calRGBCS->getGammaG(),
-              calRGBCS->getGammaB());
-    writePSFmt(" /MatrixABC [%g %g %g %g %g %g %g %g %g]\n",
-              calRGBCS->getMatrix()[0], calRGBCS->getMatrix()[1],
-              calRGBCS->getMatrix()[2], calRGBCS->getMatrix()[3],
-              calRGBCS->getMatrix()[4], calRGBCS->getMatrix()[5],
-              calRGBCS->getMatrix()[6], calRGBCS->getMatrix()[7],
-              calRGBCS->getMatrix()[8]);
-    writePSFmt(" /WhitePoint [%g %g %g]\n",
-              calRGBCS->getWhiteX(), calRGBCS->getWhiteY(),
-              calRGBCS->getWhiteZ());
-    writePSFmt(" /BlackPoint [%g %g %g]\n",
-              calRGBCS->getBlackX(), calRGBCS->getBlackY(),
-              calRGBCS->getBlackZ());
-    writePS(">>]");
-    if (genXform) {
-      writePS(" {}");
-    }
-    if (updateColors) {
-      processColors |= psProcessCMYK;
-    }
-    break;
-
-  case csDeviceCMYK:
-    writePS("/DeviceCMYK");
-    if (genXform) {
-      writePS(" {}");
-    }
-    if (updateColors) {
-      processColors |= psProcessCMYK;
-    }
-    break;
-
-  case csLab:
-    labCS = (GfxLabColorSpace *)colorSpace;
-    writePS("[/CIEBasedABC <<\n");
-    writePSFmt(" /RangeABC [0 100 %g %g %g %g]\n",
-              labCS->getAMin(), labCS->getAMax(),
-              labCS->getBMin(), labCS->getBMax());
-    writePS(" /DecodeABC [{16 add 116 div} bind {500 div} bind {200 div} bind]\n");
-    writePS(" /MatrixABC [1 1 1 1 0 0 0 0 -1]\n");
-    writePS(" /DecodeLMN\n");
-    writePS("   [{dup 6 29 div ge {dup dup mul mul}\n");
-    writePSFmt("     {4 29 div sub 108 841 div mul } ifelse %g mul} bind\n",
-              labCS->getWhiteX());
-    writePS("    {dup 6 29 div ge {dup dup mul mul}\n");
-    writePSFmt("     {4 29 div sub 108 841 div mul } ifelse %g mul} bind\n",
-              labCS->getWhiteY());
-    writePS("    {dup 6 29 div ge {dup dup mul mul}\n");
-    writePSFmt("     {4 29 div sub 108 841 div mul } ifelse %g mul} bind]\n",
-              labCS->getWhiteZ());
-    writePSFmt(" /WhitePoint [%g %g %g]\n",
-              labCS->getWhiteX(), labCS->getWhiteY(), labCS->getWhiteZ());
-    writePSFmt(" /BlackPoint [%g %g %g]\n",
-              labCS->getBlackX(), labCS->getBlackY(), labCS->getBlackZ());
-    writePS(">>]");
-    if (genXform) {
-      writePS(" {}");
-    }
-    if (updateColors) {
-      processColors |= psProcessCMYK;
-    }
-    break;
-
-  case csICCBased:
-    // there is no transform function to the alternate color space, so
-    // we can use it directly
-    dumpColorSpaceL2(((GfxICCBasedColorSpace *)colorSpace)->getAlt(),
-                    genXform, updateColors);
-    break;
-
-  case csIndexed:
-    indexedCS = (GfxIndexedColorSpace *)colorSpace;
-    baseCS = indexedCS->getBase();
-    writePS("[/Indexed ");
-    dumpColorSpaceL2(baseCS, gFalse, gFalse);
-    n = indexedCS->getIndexHigh();
-    numComps = baseCS->getNComps();
-    lookup = indexedCS->getLookup();
-    writePSFmt(" %d <\n", n);
-    if (baseCS->getMode() == csDeviceN) {
-      func = ((GfxDeviceNColorSpace *)baseCS)->getTintTransformFunc();
-      numAltComps = ((GfxDeviceNColorSpace *)baseCS)->getAlt()->getNComps();
-      p = lookup;
-      for (i = 0; i <= n; i += 8) {
-       writePS("  ");
-       for (j = i; j < i+8 && j <= n; ++j) {
-         for (k = 0; k < numComps; ++k) {
-           x[k] = *p++ / 255.0;
-         }
-         func->transform(x, y);
-         for (k = 0; k < numAltComps; ++k) {
-           byte = (int)(y[k] * 255 + 0.5);
-           if (byte < 0) {
-             byte = 0;
-           } else if (byte > 255) {
-             byte = 255;
-           }
-           writePSFmt("%02x", byte);
-         }
-         if (updateColors) {
-           color.c[0] = dblToCol(j);
-           indexedCS->getCMYK(&color, &cmyk);
-           addProcessColor(colToDbl(cmyk.c), colToDbl(cmyk.m),
-                           colToDbl(cmyk.y), colToDbl(cmyk.k));
-         }
-       }
-       writePS("\n");
-      }
-    } else {
-      for (i = 0; i <= n; i += 8) {
-       writePS("  ");
-       for (j = i; j < i+8 && j <= n; ++j) {
-         for (k = 0; k < numComps; ++k) {
-           writePSFmt("%02x", lookup[j * numComps + k]);
-         }
-         if (updateColors) {
-           color.c[0] = dblToCol(j);
-           indexedCS->getCMYK(&color, &cmyk);
-           addProcessColor(colToDbl(cmyk.c), colToDbl(cmyk.m),
-                           colToDbl(cmyk.y), colToDbl(cmyk.k));
-         }
-       }
-       writePS("\n");
-      }
-    }
-    writePS(">]");
-    if (genXform) {
-      writePS(" {}");
-    }
-    break;
-
-  case csSeparation:
-    separationCS = (GfxSeparationColorSpace *)colorSpace;
-    writePS("[/Separation /");
-    writePSName(separationCS->getName()->getCString());
-    writePS(" ");
-    dumpColorSpaceL2(separationCS->getAlt(), gFalse, gFalse);
-    writePS("\n");
-    cvtFunction(separationCS->getFunc());
-    writePS("]");
-    if (genXform) {
-      writePS(" {}");
-    }
-    if (updateColors) {
-      addCustomColor(separationCS);
-    }
-    break;
-
-  case csDeviceN:
-    // DeviceN color spaces are a Level 3 PostScript feature.
-    deviceNCS = (GfxDeviceNColorSpace *)colorSpace;
-    dumpColorSpaceL2(deviceNCS->getAlt(), gFalse, updateColors);
-    if (genXform) {
-      writePS(" ");
-      cvtFunction(deviceNCS->getTintTransformFunc());
-    }
-    break;
-
-  case csPattern:
-    //~ unimplemented
-    break;
-  }
-}
-
-#if OPI_SUPPORT
-void PSOutputDev::opiBegin(GfxState *state, Dict *opiDict) {
-  Object dict;
-
-  if (globalParams->getPSOPI()) {
-    opiDict->lookup("2.0", &dict);
-    if (dict.isDict()) {
-      opiBegin20(state, dict.getDict());
-      dict.free();
-    } else {
-      dict.free();
-      opiDict->lookup("1.3", &dict);
-      if (dict.isDict()) {
-       opiBegin13(state, dict.getDict());
-      }
-      dict.free();
-    }
-  }
-}
-
-void PSOutputDev::opiBegin20(GfxState *state, Dict *dict) {
-  Object obj1, obj2, obj3, obj4;
-  double width, height, left, right, top, bottom;
-  int w, h;
-  int i;
-
-  writePS("%%BeginOPI: 2.0\n");
-  writePS("%%Distilled\n");
-
-  dict->lookup("F", &obj1);
-  if (getFileSpec(&obj1, &obj2)) {
-    writePSFmt("%%%%ImageFileName: %s\n",
-              obj2.getString()->getCString());
-    obj2.free();
-  }
-  obj1.free();
-
-  dict->lookup("MainImage", &obj1);
-  if (obj1.isString()) {
-    writePSFmt("%%%%MainImage: %s\n", obj1.getString()->getCString());
-  }
-  obj1.free();
-
-  //~ ignoring 'Tags' entry
-  //~ need to use writePSString() and deal with >255-char lines
-
-  dict->lookup("Size", &obj1);
-  if (obj1.isArray() && obj1.arrayGetLength() == 2) {
-    obj1.arrayGet(0, &obj2);
-    width = obj2.getNum();
-    obj2.free();
-    obj1.arrayGet(1, &obj2);
-    height = obj2.getNum();
-    obj2.free();
-    writePSFmt("%%%%ImageDimensions: %g %g\n", width, height);
-  }
-  obj1.free();
-
-  dict->lookup("CropRect", &obj1);
-  if (obj1.isArray() && obj1.arrayGetLength() == 4) {
-    obj1.arrayGet(0, &obj2);
-    left = obj2.getNum();
-    obj2.free();
-    obj1.arrayGet(1, &obj2);
-    top = obj2.getNum();
-    obj2.free();
-    obj1.arrayGet(2, &obj2);
-    right = obj2.getNum();
-    obj2.free();
-    obj1.arrayGet(3, &obj2);
-    bottom = obj2.getNum();
-    obj2.free();
-    writePSFmt("%%%%ImageCropRect: %g %g %g %g\n", left, top, right, bottom);
-  }
-  obj1.free();
-
-  dict->lookup("Overprint", &obj1);
-  if (obj1.isBool()) {
-    writePSFmt("%%%%ImageOverprint: %s\n", obj1.getBool() ? "true" : "false");
-  }
-  obj1.free();
-
-  dict->lookup("Inks", &obj1);
-  if (obj1.isName()) {
-    writePSFmt("%%%%ImageInks: %s\n", obj1.getName());
-  } else if (obj1.isArray() && obj1.arrayGetLength() >= 1) {
-    obj1.arrayGet(0, &obj2);
-    if (obj2.isName()) {
-      writePSFmt("%%%%ImageInks: %s %d",
-                obj2.getName(), (obj1.arrayGetLength() - 1) / 2);
-      for (i = 1; i+1 < obj1.arrayGetLength(); i += 2) {
-       obj1.arrayGet(i, &obj3);
-       obj1.arrayGet(i+1, &obj4);
-       if (obj3.isString() && obj4.isNum()) {
-         writePS(" ");
-         writePSString(obj3.getString());
-         writePSFmt(" %g", obj4.getNum());
-       }
-       obj3.free();
-       obj4.free();
-      }
-      writePS("\n");
-    }
-    obj2.free();
-  }
-  obj1.free();
-
-  writePS("gsave\n");
-
-  writePS("%%BeginIncludedImage\n");
-
-  dict->lookup("IncludedImageDimensions", &obj1);
-  if (obj1.isArray() && obj1.arrayGetLength() == 2) {
-    obj1.arrayGet(0, &obj2);
-    w = obj2.getInt();
-    obj2.free();
-    obj1.arrayGet(1, &obj2);
-    h = obj2.getInt();
-    obj2.free();
-    writePSFmt("%%%%IncludedImageDimensions: %d %d\n", w, h);
-  }
-  obj1.free();
-
-  dict->lookup("IncludedImageQuality", &obj1);
-  if (obj1.isNum()) {
-    writePSFmt("%%%%IncludedImageQuality: %g\n", obj1.getNum());
-  }
-  obj1.free();
-
-  ++opi20Nest;
-}
-
-void PSOutputDev::opiBegin13(GfxState *state, Dict *dict) {
-  Object obj1, obj2;
-  int left, right, top, bottom, samples, bits, width, height;
-  double c, m, y, k;
-  double llx, lly, ulx, uly, urx, ury, lrx, lry;
-  double tllx, tlly, tulx, tuly, turx, tury, tlrx, tlry;
-  double horiz, vert;
-  int i, j;
-
-  writePS("save\n");
-  writePS("/opiMatrix2 matrix currentmatrix def\n");
-  writePS("opiMatrix setmatrix\n");
-
-  dict->lookup("F", &obj1);
-  if (getFileSpec(&obj1, &obj2)) {
-    writePSFmt("%%ALDImageFileName: %s\n",
-              obj2.getString()->getCString());
-    obj2.free();
-  }
-  obj1.free();
-
-  dict->lookup("CropRect", &obj1);
-  if (obj1.isArray() && obj1.arrayGetLength() == 4) {
-    obj1.arrayGet(0, &obj2);
-    left = obj2.getInt();
-    obj2.free();
-    obj1.arrayGet(1, &obj2);
-    top = obj2.getInt();
-    obj2.free();
-    obj1.arrayGet(2, &obj2);
-    right = obj2.getInt();
-    obj2.free();
-    obj1.arrayGet(3, &obj2);
-    bottom = obj2.getInt();
-    obj2.free();
-    writePSFmt("%%ALDImageCropRect: %d %d %d %d\n", left, top, right, bottom);
-  }
-  obj1.free();
-
-  dict->lookup("Color", &obj1);
-  if (obj1.isArray() && obj1.arrayGetLength() == 5) {
-    obj1.arrayGet(0, &obj2);
-    c = obj2.getNum();
-    obj2.free();
-    obj1.arrayGet(1, &obj2);
-    m = obj2.getNum();
-    obj2.free();
-    obj1.arrayGet(2, &obj2);
-    y = obj2.getNum();
-    obj2.free();
-    obj1.arrayGet(3, &obj2);
-    k = obj2.getNum();
-    obj2.free();
-    obj1.arrayGet(4, &obj2);
-    if (obj2.isString()) {
-      writePSFmt("%%ALDImageColor: %g %g %g %g ", c, m, y, k);
-      writePSString(obj2.getString());
-      writePS("\n");
-    }
-    obj2.free();
-  }
-  obj1.free();
-
-  dict->lookup("ColorType", &obj1);
-  if (obj1.isName()) {
-    writePSFmt("%%ALDImageColorType: %s\n", obj1.getName());
-  }
-  obj1.free();
-
-  //~ ignores 'Comments' entry
-  //~ need to handle multiple lines
-
-  dict->lookup("CropFixed", &obj1);
-  if (obj1.isArray()) {
-    obj1.arrayGet(0, &obj2);
-    ulx = obj2.getNum();
-    obj2.free();
-    obj1.arrayGet(1, &obj2);
-    uly = obj2.getNum();
-    obj2.free();
-    obj1.arrayGet(2, &obj2);
-    lrx = obj2.getNum();
-    obj2.free();
-    obj1.arrayGet(3, &obj2);
-    lry = obj2.getNum();
-    obj2.free();
-    writePSFmt("%%ALDImageCropFixed: %g %g %g %g\n", ulx, uly, lrx, lry);
-  }
-  obj1.free();
-
-  dict->lookup("GrayMap", &obj1);
-  if (obj1.isArray()) {
-    writePS("%ALDImageGrayMap:");
-    for (i = 0; i < obj1.arrayGetLength(); i += 16) {
-      if (i > 0) {
-       writePS("\n%%+");
-      }
-      for (j = 0; j < 16 && i+j < obj1.arrayGetLength(); ++j) {
-       obj1.arrayGet(i+j, &obj2);
-       writePSFmt(" %d", obj2.getInt());
-       obj2.free();
-      }
-    }
-    writePS("\n");
-  }
-  obj1.free();
-
-  dict->lookup("ID", &obj1);
-  if (obj1.isString()) {
-    writePSFmt("%%ALDImageID: %s\n", obj1.getString()->getCString());
-  }
-  obj1.free();
-
-  dict->lookup("ImageType", &obj1);
-  if (obj1.isArray() && obj1.arrayGetLength() == 2) {
-    obj1.arrayGet(0, &obj2);
-    samples = obj2.getInt();
-    obj2.free();
-    obj1.arrayGet(1, &obj2);
-    bits = obj2.getInt();
-    obj2.free();
-    writePSFmt("%%ALDImageType: %d %d\n", samples, bits);
-  }
-  obj1.free();
-
-  dict->lookup("Overprint", &obj1);
-  if (obj1.isBool()) {
-    writePSFmt("%%ALDImageOverprint: %s\n", obj1.getBool() ? "true" : "false");
-  }
-  obj1.free();
-
-  dict->lookup("Position", &obj1);
-  if (obj1.isArray() && obj1.arrayGetLength() == 8) {
-    obj1.arrayGet(0, &obj2);
-    llx = obj2.getNum();
-    obj2.free();
-    obj1.arrayGet(1, &obj2);
-    lly = obj2.getNum();
-    obj2.free();
-    obj1.arrayGet(2, &obj2);
-    ulx = obj2.getNum();
-    obj2.free();
-    obj1.arrayGet(3, &obj2);
-    uly = obj2.getNum();
-    obj2.free();
-    obj1.arrayGet(4, &obj2);
-    urx = obj2.getNum();
-    obj2.free();
-    obj1.arrayGet(5, &obj2);
-    ury = obj2.getNum();
-    obj2.free();
-    obj1.arrayGet(6, &obj2);
-    lrx = obj2.getNum();
-    obj2.free();
-    obj1.arrayGet(7, &obj2);
-    lry = obj2.getNum();
-    obj2.free();
-    opiTransform(state, llx, lly, &tllx, &tlly);
-    opiTransform(state, ulx, uly, &tulx, &tuly);
-    opiTransform(state, urx, ury, &turx, &tury);
-    opiTransform(state, lrx, lry, &tlrx, &tlry);
-    writePSFmt("%%ALDImagePosition: %g %g %g %g %g %g %g %g\n",
-              tllx, tlly, tulx, tuly, turx, tury, tlrx, tlry);
-    obj2.free();
-  }
-  obj1.free();
-
-  dict->lookup("Resolution", &obj1);
-  if (obj1.isArray() && obj1.arrayGetLength() == 2) {
-    obj1.arrayGet(0, &obj2);
-    horiz = obj2.getNum();
-    obj2.free();
-    obj1.arrayGet(1, &obj2);
-    vert = obj2.getNum();
-    obj2.free();
-    writePSFmt("%%ALDImageResoution: %g %g\n", horiz, vert);
-    obj2.free();
-  }
-  obj1.free();
-
-  dict->lookup("Size", &obj1);
-  if (obj1.isArray() && obj1.arrayGetLength() == 2) {
-    obj1.arrayGet(0, &obj2);
-    width = obj2.getInt();
-    obj2.free();
-    obj1.arrayGet(1, &obj2);
-    height = obj2.getInt();
-    obj2.free();
-    writePSFmt("%%ALDImageDimensions: %d %d\n", width, height);
-  }
-  obj1.free();
-
-  //~ ignoring 'Tags' entry
-  //~ need to use writePSString() and deal with >255-char lines
-
-  dict->lookup("Tint", &obj1);
-  if (obj1.isNum()) {
-    writePSFmt("%%ALDImageTint: %g\n", obj1.getNum());
-  }
-  obj1.free();
-
-  dict->lookup("Transparency", &obj1);
-  if (obj1.isBool()) {
-    writePSFmt("%%ALDImageTransparency: %s\n", obj1.getBool() ? "true" : "false");
-  }
-  obj1.free();
-
-  writePS("%%BeginObject: image\n");
-  writePS("opiMatrix2 setmatrix\n");
-  ++opi13Nest;
-}
-
-// Convert PDF user space coordinates to PostScript default user space
-// coordinates.  This has to account for both the PDF CTM and the
-// PSOutputDev page-fitting transform.
-void PSOutputDev::opiTransform(GfxState *state, double x0, double y0,
-                              double *x1, double *y1) {
-  double t;
-
-  state->transform(x0, y0, x1, y1);
-  *x1 += tx;
-  *y1 += ty;
-  if (rotate == 90) {
-    t = *x1;
-    *x1 = -*y1;
-    *y1 = t;
-  } else if (rotate == 180) {
-    *x1 = -*x1;
-    *y1 = -*y1;
-  } else if (rotate == 270) {
-    t = *x1;
-    *x1 = *y1;
-    *y1 = -t;
-  }
-  *x1 *= xScale;
-  *y1 *= yScale;
-}
-
-void PSOutputDev::opiEnd(GfxState *state, Dict *opiDict) {
-  Object dict;
-
-  if (globalParams->getPSOPI()) {
-    opiDict->lookup("2.0", &dict);
-    if (dict.isDict()) {
-      writePS("%%EndIncludedImage\n");
-      writePS("%%EndOPI\n");
-      writePS("grestore\n");
-      --opi20Nest;
-      dict.free();
-    } else {
-      dict.free();
-      opiDict->lookup("1.3", &dict);
-      if (dict.isDict()) {
-       writePS("%%EndObject\n");
-       writePS("restore\n");
-       --opi13Nest;
-      }
-      dict.free();
-    }
-  }
-}
-
-GBool PSOutputDev::getFileSpec(Object *fileSpec, Object *fileName) {
-  if (fileSpec->isString()) {
-    fileSpec->copy(fileName);
-    return gTrue;
-  }
-  if (fileSpec->isDict()) {
-    fileSpec->dictLookup("DOS", fileName);
-    if (fileName->isString()) {
-      return gTrue;
-    }
-    fileName->free();
-    fileSpec->dictLookup("Mac", fileName);
-    if (fileName->isString()) {
-      return gTrue;
-    }
-    fileName->free();
-    fileSpec->dictLookup("Unix", fileName);
-    if (fileName->isString()) {
-      return gTrue;
-    }
-    fileName->free();
-    fileSpec->dictLookup("F", fileName);
-    if (fileName->isString()) {
-      return gTrue;
-    }
-    fileName->free();
-  }
-  return gFalse;
-}
-#endif // OPI_SUPPORT
-
-void PSOutputDev::type3D0(GfxState *state, double wx, double wy) {
-  writePSFmt("%g %g setcharwidth\n", wx, wy);
-  writePS("q\n");
-}
-
-void PSOutputDev::type3D1(GfxState *state, double wx, double wy,
-                         double llx, double lly, double urx, double ury) {
-  t3WX = wx;
-  t3WY = wy;
-  t3LLX = llx;
-  t3LLY = lly;
-  t3URX = urx;
-  t3URY = ury;
-  t3String = new GString();
-  writePS("q\n");
-  t3Cacheable = gTrue;
-}
-
-void PSOutputDev::psXObject(Stream *psStream, Stream *level1Stream) {
-  Stream *str;
-  int c;
-
-  if ((level == psLevel1 || level == psLevel1Sep) && level1Stream) {
-    str = level1Stream;
-  } else {
-    str = psStream;
-  }
-  str->reset();
-  while ((c = str->getChar()) != EOF) {
-    writePSChar(c);
-  }
-  str->close();
-}
-
-//~ can nextFunc be reset to 0 -- maybe at the start of each page?
-//~   or maybe at the start of each color space / pattern?
-void PSOutputDev::cvtFunction(Function *func) {
-  SampledFunction *func0;
-  ExponentialFunction *func2;
-  StitchingFunction *func3;
-  PostScriptFunction *func4;
-  int thisFunc, m, n, nSamples, i, j, k;
-
-  switch (func->getType()) {
-
-  case -1:                     // identity
-    writePS("{}\n");
-    break;
-
-  case 0:                      // sampled
-    func0 = (SampledFunction *)func;
-    thisFunc = nextFunc++;
-    m = func0->getInputSize();
-    n = func0->getOutputSize();
-    nSamples = n;
-    for (i = 0; i < m; ++i) {
-      nSamples *= func0->getSampleSize(i);
-    }
-    writePSFmt("/xpdfSamples%d [\n", thisFunc);
-    for (i = 0; i < nSamples; ++i) {
-      writePSFmt("%g\n", func0->getSamples()[i]);
-    }
-    writePS("] def\n");
-    writePSFmt("{ %d array %d array %d 2 roll\n", 2*m, m, m+2);
-    // [e01] [efrac] x0 x1 ... xm-1
-    for (i = m-1; i >= 0; --i) {
-      // [e01] [efrac] x0 x1 ... xi
-      writePSFmt("%g sub %g mul %g add\n",
-             func0->getDomainMin(i),
-             (func0->getEncodeMax(i) - func0->getEncodeMin(i)) /
-               (func0->getDomainMax(i) - func0->getDomainMin(i)),
-             func0->getEncodeMin(i));
-      // [e01] [efrac] x0 x1 ... xi-1 xi'
-      writePSFmt("dup 0 lt { pop 0 } { dup %d gt { pop %d } if } ifelse\n",
-                func0->getSampleSize(i) - 1, func0->getSampleSize(i) - 1);
-      // [e01] [efrac] x0 x1 ... xi-1 xi'
-      writePS("dup floor cvi exch dup ceiling cvi exch 2 index sub\n");
-      // [e01] [efrac] x0 x1 ... xi-1 floor(xi') ceiling(xi') xi'-floor(xi')
-      writePSFmt("%d index %d 3 2 roll put\n", i+3, i);
-      // [e01] [efrac] x0 x1 ... xi-1 floor(xi') ceiling(xi')
-      writePSFmt("%d index %d 3 2 roll put\n", i+3, 2*i+1);
-      // [e01] [efrac] x0 x1 ... xi-1 floor(xi')
-      writePSFmt("%d index %d 3 2 roll put\n", i+2, 2*i);
-      // [e01] [efrac] x0 x1 ... xi-1
-    }
-    // [e01] [efrac]
-    for (i = 0; i < n; ++i) {
-      // [e01] [efrac] y(0) ... y(i-1)
-      for (j = 0; j < (1<<m); ++j) {
-       // [e01] [efrac] y(0) ... y(i-1) s(0) s(1) ... s(j-1)
-       writePSFmt("xpdfSamples%d\n", thisFunc);
-       k = m - 1;
-       writePSFmt("%d index %d get\n", i+j+2, 2 * k + ((j >> k) & 1));
-       for (k = m - 2; k >= 0; --k) {
-         writePSFmt("%d mul %d index %d get add\n",
-                    func0->getSampleSize(k),
-                    i + j + 3,
-                    2 * k + ((j >> k) & 1));
-       }
-       if (n > 1) {
-         writePSFmt("%d mul %d add ", n, i);
-       }
-       writePS("get\n");
-      }
-      // [e01] [efrac] y(0) ... y(i-1) s(0) s(1) ... s(2^m-1)
-      for (j = 0; j < m; ++j) {
-       // [e01] [efrac] y(0) ... y(i-1) s(0) s(1) ... s(2^(m-j)-1)
-       for (k = 0; k < (1 << (m - j)); k += 2) {
-         // [e01] [efrac] y(0) ... y(i-1) <k/2 s' values> <2^(m-j)-k s values>
-         writePSFmt("%d index %d get dup\n", i + k/2 + (1 << (m-j)) - k, j);
-         writePS("3 2 roll mul exch 1 exch sub 3 2 roll mul add\n");
-         writePSFmt("%d 1 roll\n", k/2 + (1 << m-j) - k - 1);
-       }
-       // [e01] [efrac] s'(0) s'(1) ... s(2^(m-j-1)-1)
-      }
-      // [e01] [efrac] y(0) ... y(i-1) s
-      writePSFmt("%g mul %g add\n",
-                func0->getDecodeMax(i) - func0->getDecodeMin(i),
-                func0->getDecodeMin(i));
-      writePSFmt("dup %g lt { pop %g } { dup %g gt { pop %g } if } ifelse\n",
-                func0->getRangeMin(i), func0->getRangeMin(i),
-                func0->getRangeMax(i), func0->getRangeMax(i));
-      // [e01] [efrac] y(0) ... y(i-1) y(i)
-    }
-    // [e01] [efrac] y(0) ... y(n-1)
-    writePSFmt("%d %d roll pop pop }\n", n+2, n);
-    break;
-
-  case 2:                      // exponential
-    func2 = (ExponentialFunction *)func;
-    n = func2->getOutputSize();
-    writePSFmt("{ dup %g lt { pop %g } { dup %g gt { pop %g } if } ifelse\n",
-              func2->getDomainMin(0), func2->getDomainMin(0),
-              func2->getDomainMax(0), func2->getDomainMax(0));
-    // x
-    for (i = 0; i < n; ++i) {
-      // x y(0) .. y(i-1)
-      writePSFmt("%d index %g exp %g mul %g add\n",
-                i, func2->getE(), func2->getC1()[i] - func2->getC0()[i],
-                func2->getC0()[i]);
-      if (func2->getHasRange()) {
-       writePSFmt("dup %g lt { pop %g } { dup %g gt { pop %g } if } ifelse\n",
-                  func2->getRangeMin(i), func2->getRangeMin(i),
-                  func2->getRangeMax(i), func2->getRangeMax(i));
-      }
-    }
-    // x y(0) .. y(n-1)
-    writePSFmt("%d %d roll pop }\n", n+1, n);
-    break;
-
-  case 3:                      // stitching
-    func3 = (StitchingFunction *)func;
-    thisFunc = nextFunc++;
-    for (i = 0; i < func3->getNumFuncs(); ++i) {
-      cvtFunction(func3->getFunc(i));
-      writePSFmt("/xpdfFunc%d_%d exch def\n", thisFunc, i);
-    }
-    writePSFmt("{ dup %g lt { pop %g } { dup %g gt { pop %g } if } ifelse\n",
-              func3->getDomainMin(0), func3->getDomainMin(0),
-              func3->getDomainMax(0), func3->getDomainMax(0));
-    for (i = 0; i < func3->getNumFuncs() - 1; ++i) {
-      writePSFmt("dup %g lt { %g sub %g mul %g add xpdfFunc%d_%d } {\n",
-                func3->getBounds()[i+1],
-                func3->getBounds()[i],
-                (func3->getEncode()[2*i+1] - func3->getEncode()[2*i]) /
-                  (func3->getBounds()[i+1] - func3->getBounds()[i]),
-                func3->getEncode()[2*i],
-                thisFunc, i);
-    }
-    writePSFmt("%g sub %g mul %g add xpdfFunc%d_%d\n",
-              func3->getBounds()[i],
-              (func3->getEncode()[2*i+1] - func3->getEncode()[2*i]) /
-                (func3->getBounds()[i+1] - func3->getBounds()[i]),
-              func3->getEncode()[2*i],
-              thisFunc, i);
-    for (i = 0; i < func3->getNumFuncs() - 1; ++i) {
-      writePS("} ifelse\n");
-    }
-    writePS("}\n");
-    break;
-
-  case 4:                      // PostScript
-    func4 = (PostScriptFunction *)func;
-    writePS(func4->getCodeString()->getCString());
-    writePS("\n");
-    break;
-  }
-}
-
-void PSOutputDev::writePSChar(char c) {
-  if (t3String) {
-    t3String->append(c);
-  } else {
-    (*outputFunc)(outputStream, &c, 1);
-  }
-}
-
-void PSOutputDev::writePS(char *s) {
-  if (t3String) {
-    t3String->append(s);
-  } else {
-    (*outputFunc)(outputStream, s, strlen(s));
-  }
-}
-
-void PSOutputDev::writePSFmt(const char *fmt, ...) {
-  va_list args;
-  char buf[512];
-
-  va_start(args, fmt);
-  vsprintf(buf, fmt, args);
-  va_end(args);
-  if (t3String) {
-    t3String->append(buf);
-  } else {
-    (*outputFunc)(outputStream, buf, strlen(buf));
-  }
-}
-
-void PSOutputDev::writePSString(GString *s) {
-  Guchar *p;
-  int n, line;
-  char buf[8];
-
-  writePSChar('(');
-  line = 1;
-  for (p = (Guchar *)s->getCString(), n = s->getLength(); n; ++p, --n) {
-    if (line >= 64) {
-      writePSChar('\\');
-      writePSChar('\n');
-      line = 0;
-    }
-    if (*p == '(' || *p == ')' || *p == '\\') {
-      writePSChar('\\');
-      writePSChar((char)*p);
-      line += 2;
-    } else if (*p < 0x20 || *p >= 0x80) {
-      sprintf(buf, "\\%03o", *p);
-      writePS(buf);
-      line += 4;
-    } else {
-      writePSChar((char)*p);
-      ++line;
-    }
-  }
-  writePSChar(')');
-}
-
-void PSOutputDev::writePSName(char *s) {
-  char *p;
-  char c;
-
-  p = s;
-  while ((c = *p++)) {
-    if (c <= (char)0x20 || c >= (char)0x7f ||
-       c == '(' || c == ')' || c == '<' || c == '>' ||
-       c == '[' || c == ']' || c == '{' || c == '}' ||
-       c == '/' || c == '%') {
-      writePSFmt("#%02x", c & 0xff);
-    } else {
-      writePSChar(c);
-    }
-  }
-}
-
-GString *PSOutputDev::filterPSName(GString *name) {
-  GString *name2;
-  char buf[8];
-  int i;
-  char c;
-
-  name2 = new GString();
-
-  // ghostscript chokes on names that begin with out-of-limits
-  // numbers, e.g., 1e4foo is handled correctly (as a name), but
-  // 1e999foo generates a limitcheck error
-  c = name->getChar(0);
-  if (c >= '0' && c <= '9') {
-    name2->append('f');
-  }
-
-  for (i = 0; i < name->getLength(); ++i) {
-    c = name->getChar(i);
-    if (c <= (char)0x20 || c >= (char)0x7f ||
-       c == '(' || c == ')' || c == '<' || c == '>' ||
-       c == '[' || c == ']' || c == '{' || c == '}' ||
-       c == '/' || c == '%') {
-      sprintf(buf, "#%02x", c & 0xff);
-      name2->append(buf);
-    } else {
-      name2->append(c);
-    }
-  }
-  return name2;
-}
-
-GBool                                  /* O - gTrue if selected, gFalse otherwise */
-PSOutputDev::checkRange(int page)      /* I - Page number */
-{
-  const char   *range;                 /* Pointer into range string */
-  int          lower, upper;           /* Lower and upper page numbers */
-
-
-  if (pageRanges == NULL)
-    return (gTrue);                            /* No range, print all pages... */
-
-  for (range = pageRanges; *range != '\0';)
-  {
-    if (*range == '-')
-    {
-      lower = 1;
-      range ++;
-      upper = strtol(range, (char **)&range, 10);
-    }
-    else
-    {
-      lower = strtol(range, (char **)&range, 10);
-
-      if (*range == '-')
-      {
-        range ++;
-       if (!isdigit(*range & 255))
-         upper = 65535;
-       else
-         upper = strtol(range, (char **)&range, 10);
-      }
-      else
-        upper = lower;
-    }
-
-    if (page >= lower && page <= upper)
-      return (gTrue);
-
-    if (*range == ',')
-      range ++;
-    else
-      break;
-  }
-
-  return (gFalse);
-}