aboutsummaryrefslogtreecommitdiffstats
path: root/recipes/gs
diff options
context:
space:
mode:
authorOtavio Salvador <otavio@ossystems.com.br>2009-07-10 14:49:27 -0300
committerOtavio Salvador <otavio@ossystems.com.br>2009-07-13 10:59:09 -0300
commit43f8a1989aa709749ce9aedd4feba6c4f6306925 (patch)
tree0835b21fede8d61f9c2c2c4bd68913eb516f460b /recipes/gs
parenta41c726ede88bd70b0428481819097489d728bf3 (diff)
downloadopenembedded-43f8a1989aa709749ce9aedd4feba6c4f6306925.tar.gz
openembedded-43f8a1989aa709749ce9aedd4feba6c4f6306925.tar.bz2
openembedded-43f8a1989aa709749ce9aedd4feba6c4f6306925.zip
gs: add 8.64
This has based in Debian's 8.64~dfsg-12 package and all patches has been taken from it. Signed-off-by: Otavio Salvador <otavio@ossystems.com.br>
Diffstat (limited to 'recipes/gs')
-rw-r--r--recipes/gs/gs/0001_svn_snapshot.patch24362
-rw-r--r--recipes/gs/gs/0002_svn_snapshot_jbig2dec.patch17181
-rw-r--r--recipes/gs/gs/1001_install_cjk_examples.patch18
-rw-r--r--recipes/gs/gs/1002_ps2pdf_man_fix.patch126
-rw-r--r--recipes/gs/gs/1003_fix_autoconf_create_from_infiles.patch14
-rw-r--r--recipes/gs/gs/1004_CVE-2009-0792_CVE-2009-0584_CVE-2009-0583.patch1154
-rw-r--r--recipes/gs/gs/1006_system-jasper.patch28
-rw-r--r--recipes/gs/gs/1007_fix_pphs_script_not_lib.patch22
-rw-r--r--recipes/gs/gs/2001_docdir_fix_for_debian.patch16
-rw-r--r--recipes/gs/gs/2002_gs_man_fix_debian.patch40
-rw-r--r--recipes/gs/gs_8.64.bb54
11 files changed, 43015 insertions, 0 deletions
diff --git a/recipes/gs/gs/0001_svn_snapshot.patch b/recipes/gs/gs/0001_svn_snapshot.patch
new file mode 100644
index 0000000000..4650b11e73
--- /dev/null
+++ b/recipes/gs/gs/0001_svn_snapshot.patch
@@ -0,0 +1,24362 @@
+Description: /jbig2dec changes r9437 → r9781 (release 8.64 → 2009-06-08)
+ - subdirs /jasper, /libpng and /jbig2dec skipped
+ - version bump skipped
+ - some $Id$ changes suppressed or fuzzy
+Author: Jonas Smedegaard <dr@jones.dk>
+diff --git a/Resource/Init/gs_init.ps b/Resource/Init/gs_init.ps
+--- a/Resource/Init/gs_init.ps
++++ b/Resource/Init/gs_init.ps
+@@ -209,7 +209,7 @@ currentdict /DEVICE known not
+ % during initialization.
+ /MaxDictStack 500
+ /MaxExecStack 5000
+- /MaxOpStack 65414
++ /MaxOpStack 100000
+ .dicttomark .setuserparams
+ } if
+
+diff --git a/Resource/Init/gs_pdfwr.ps b/Resource/Init/gs_pdfwr.ps
+--- a/Resource/Init/gs_pdfwr.ps
++++ b/Resource/Init/gs_pdfwr.ps
+@@ -665,18 +665,28 @@ currentdict /.pdf_hook_DSC_Creator undef
+ /MonoImageResolution { }
+ % Font embedding parameters
+ /AlwaysEmbed
+- { dup length 0 gt
+- { dup 0 get false eq
++ { dup length 0 gt
++ { dup 0 get type /booleantype eq } { false } ifelse
++ { dup 0 get
++ { dup length 1 sub 1 exch getinterval
++ }
+ { dup length 1 sub 1 exch getinterval exch pop /~AlwaysEmbed exch
+- } if
+- } if
++ } ifelse
++ }
++ { exch pop /.AlwaysEmbed exch
++ } ifelse
+ }
+ /NeverEmbed
+- { dup length 0 gt
+- { dup 0 get false eq
+- { dup length 1 sub 1 exch getinterval exch pop /~NeverEmbed exch
+- } if
+- } if
++ { dup length 0 gt
++ { dup 0 get type /booleantype eq } { false } ifelse
++ { dup 0 get
++ { dup length 1 sub 1 exch getinterval
++ }
++ { dup length 1 sub 1 exch getinterval exch pop /~NeverEmbed exch
++ } ifelse
++ }
++ { exch pop /.NeverEmbed exch
++ } ifelse
+ }
+ /CannotEmbedFontPolicy { }
+ /EmbedAllFonts { }
+diff --git a/Resource/Init/gs_res.ps b/Resource/Init/gs_res.ps
+--- a/Resource/Init/gs_res.ps
++++ b/Resource/Init/gs_res.ps
+@@ -349,6 +349,15 @@ ne {
+ } if
+ pop pop
+
++pssystemparams dup /GenericResourceDir get exch /GenericResourcePathSep get
++(Init) exch (gs_init.ps) concatstrings concatstrings concatstrings
++status {
++ pop pop pop pop
++} {
++ (\n*** Warning: GenericResourceDir doesn't point to a valid resource directory.) =
++ ( the -sGenericResourceDir=... option can be used to set this.\n) =
++} ifelse
++
+ % Define the generic algorithm for computing resource file names.
+ /.rfnstring 8192 string def
+ /.genericrfn % <key> <scratch> <prefix> .genericrfn <filename>
+diff --git a/Resource/Init/gs_setpd.ps b/Resource/Init/gs_setpd.ps
+--- a/Resource/Init/gs_setpd.ps
++++ b/Resource/Init/gs_setpd.ps
+@@ -171,13 +171,8 @@ level2dict begin
+ % the default policy to "7" (impose) to avoid numerous problems with
+ % printing within CUPS...
+ %
+- NOMEDIAATTRS {
+- /PolicyNotFound 7
+- /PageSize 7
+- } {
+- /PolicyNotFound 1
+- /PageSize 0
+- } ifelse
++ /PageSize NOMEDIAATTRS { 7 } { 0 } ifelse
++ /PolicyNotFound 1
+ /PolicyReport {
+ dup /.LockSafetyParams known {
+ % Only possible error is invalidaccess
+@@ -810,20 +805,17 @@ SETPDDEBUG { (Installing.) = pstack flush } if
+ % NB: This shoud be the only use of the .setuseciecolor
+ % operator anywhere.
+ %
+- % If UseCIEColor is transitioned to false, set some
+- % color space other than /DeviceGray, to insure that
+- % initgraphics will actually perform a setcolorspace
++ % Set some color space other than /DeviceGray, to insure
++ % that initgraphics will actually perform a setcolorspace
+ % operation (there is an optimization in setcolorspace
+ % that does nothing if the operand and current color
+- % spaces are the same, and UseCIEColor is false).
++ % spaces are the same)
+
+ /.setuseciecolor where
+ {
+ pop 1 index /UseCIEColor .knownget
+ {
+- dup .setuseciecolor not
+- { /DeviceRGB setcolorspace }
+- if
++ .setuseciecolor /DeviceRGB setcolorspace
+ }
+ if
+ }
+diff --git a/Resource/Init/gs_statd.ps b/Resource/Init/gs_statd.ps
+--- a/Resource/Init/gs_statd.ps
++++ b/Resource/Init/gs_statd.ps
+@@ -109,6 +109,8 @@ STRICT { (%END SIZES) .skipeof } if
+ /halfletter {396 612 //.setpagesize exec} bind def
+ % minimum of a4 and letter (a4 width, letter length)
+ /pa4 {595 792 //.setpagesize exec} bind def
++ % Japanese postcard size, 100mm x 148mm
++ /hagaki {283 420 //.setpagesize exec} bind def
+ % /tabloid {792 1224 //.setpagesize exec} bind def % 11x17 portrait
+ % /csheet {1224 1584 //.setpagesize exec} bind def % ANSI C 17x22
+ % /dsheet {1584 2448 //.setpagesize exec} bind def % ANSI D 22x34
+@@ -134,7 +136,7 @@ STRICT { (%END SIZES) .skipeof } if
+ /flsa /flse /halfletter
+ /isob0 /isob1 /isob2 /isob3 /isob4 /isob5 /isob6
+ /jisb0 /jisb1 /jisb2 /jisb3 /jisb4 /jisb5 /jisb6
+- /pa4
++ /pa4 /hagaki
+ %END SIZES
+ ] cvlit readonly def
+
+diff --git a/Resource/Init/gs_ttf.ps b/Resource/Init/gs_ttf.ps
+--- a/Resource/Init/gs_ttf.ps
++++ b/Resource/Init/gs_ttf.ps
+@@ -827,7 +827,8 @@ end readonly def % .loadttfontdict
+ } if
+ /ttc_offset 0 def
+ } ifelse
+- /tables f offsets 4 getu16 16 mul string readstring pop def
++ % Peek because table counter may be incorrect.
++ /tables f offsets 4 getu16 16 mul string .peekstring pop def
+ /tabdict tables length 16 idiv dict def
+ % tabs = tables we want to keep, sorted by file position.
+ /tabs [ 0 16 tables length 1 sub {
+@@ -868,7 +869,7 @@ mark
+ % Read data. Updates offsets, tabs; stores data in tabdict.
+ /.readttdata {
+ /file_table_pos 10 dict def
+- /fpos offsets length tables length add ttc_offset add def
++ /fpos offsets length ttc_offset add def
+ /sfpos offsets length tabs length 16 mul add def
+ offsets 4 tabs length putu16
+ tabs {
+diff --git a/Resource/Init/gs_typ32.ps b/Resource/Init/gs_typ32.ps
+--- a/Resource/Init/gs_typ32.ps
++++ b/Resource/Init/gs_typ32.ps
+@@ -37,7 +37,8 @@ systemdict /.makeglyph32 .undef
+ % Define a string large enough to hold the metrics,
+ % an uncompressed bitmap (worst case = 5x expansion),
+ % and the 2 RTC codes (3 bytes).
+- dup length 4 index length 5 mul add 10 add string
++ dup length 4 index length 5 mul add 10 add
++ 65535 .min string
+ % Stack: metrics bitmap cid font metstr buffer
+ dup 0 3 index putinterval
+ dup 2 index length 1 index length 1 index sub getinterval
+diff --git a/Resource/Init/opdfread.ps b/Resource/Init/opdfread.ps
+--- a/Resource/Init/opdfread.ps
++++ b/Resource/Init/opdfread.ps
+@@ -152,6 +152,7 @@ end % A dictionary for local binding
+ /TTFDEBUG DefaultSwitch
+ /RotatePages DefaultSwitch
+ /FitPages DefaultSwitch
++/CenterPages DefaultSwitch
+ /SetPageSize DefaultSwitch
+
+ /error % mark <object> .... error -
+@@ -167,10 +168,16 @@ end % A dictionary for local binding
+ } bind def
+
+ //SetPageSize {
+- //RotatePages //FitPages or {
+- mark (/RotatePages, /FitPages are not allowed with /SetPageSize) //error exec
++ //RotatePages //FitPages or //CenterPages or{
++ mark (/RotatePages, /FitPages and CenterPages are not allowed with /SetPageSize) //error exec
+ } if
+-} if
++}
++{
++ //FitPages //CenterPages and {
++ mark (CenterPages is not allowed with /FitPages) //error exec
++ } if
++}
++ifelse
+
+ % ===================== Utilities =========================================
+
+@@ -851,23 +858,43 @@ currentdict end readonly def
+ } {
+ false
+ } ifelse
+- { //FitPages {
+- 1 index 5 index div 1 index 7 index div % bw bh px0 py0 pw ph sx sy
+- 2 copy gt {
+- exch
++ { //CenterPages {
++ //PDFR_DEBUG {
++ (Rotating page, and then centering it) ==
++ } if
++ 90 rotate
++ 0 5 index neg translate
++ 5 index 1 index exch sub 2 div
++ 2 index 6 index sub 2 div neg % bw bh px0 py0 pw ph lm bm
++ translate
++ } {
++ //FitPages {
++ 1 index 5 index div 1 index 7 index div % bw bh px0 py0 pw ph sx sy
++ 2 copy gt {
++ exch
++ } if
++ pop dup scale % bw bh px0 py0 pw ph
+ } if
+- pop dup scale % bw bh px0 py0 pw ph
+- } if
+- 90 rotate
+- 0 5 index neg translate
++ 90 rotate
++ 0 5 index neg translate
++ } ifelse
+ } {
+- //FitPages {
+- 1 index 6 index div 1 index 6 index div % bw bh px0 py0 pw ph sx sy
+- 2 copy gt {
+- exch
++ //CenterPages {
++ //PDFR_DEBUG {
++ (Ccentering page) ==
++ } if
++ 1 index 6 index sub 2 div
++ 1 index 6 index sub 2 div % bw bh px0 py0 pw ph lm bm
++ translate
++ } {
++ //FitPages {
++ 1 index 6 index div 1 index 6 index div % bw bh px0 py0 pw ph sx sy
++ 2 copy gt {
++ exch
++ } if
++ pop dup scale % bw bh px0 py0 pw ph
+ } if
+- pop dup scale % bw bh px0 py0 pw ph
+- } if
++ } ifelse
+ } ifelse
+ pop pop % bw bh px0 py0
+ translate % bw bh
+diff --git a/Resource/Init/pdf_base.ps b/Resource/Init/pdf_base.ps
+--- a/Resource/Init/pdf_base.ps
++++ b/Resource/Init/pdf_base.ps
+@@ -720,6 +720,10 @@ currentdict /no_debug_dict undef
+ ( **** Operator 'endobj' is misspelled as 'endjobj'.\n) pdfformaterror
+ endobj exit
+ } bind
++ /enbobj { % Bug 690397.
++ ( **** Operator 'endobj' is misspelled as 'enbobj'.\n) pdfformaterror
++ endobj exit
++ } bind
+ % OmniForm generates PDF file with endobj missing in some
+ % objects. AR ignores this. So we have to do it too.
+ /obj { pop pop endobj exit } bind
+diff --git a/Resource/Init/pdf_draw.ps b/Resource/Init/pdf_draw.ps
+--- a/Resource/Init/pdf_draw.ps
++++ b/Resource/Init/pdf_draw.ps
+@@ -397,16 +397,20 @@ end
+ % Stack: mark ... smaskdict
+ dup /BC knownoget {
+ dup /Background exch 4 2 roll
+- gsave
++ gsave //nodict begin
+ 1 index /G oget /Group oget /CS knownoget {
+ resolvecolorspace dup setgcolorspace csput
+ } if
+ aload pop setcolor [ currentgray ]
+- grestore
++ end grestore
+ /GrayBackground exch 3 2 roll
+ } if
+ dup /TR knownoget {
+- resolveidfnproc /TransferFunction exch 3 2 roll
++ dup /Identity eq {
++ pop
++ } {
++ resolvefnproc /TransferFunction exch 3 2 roll
++ } ifelse
+ } if
+ dup /G oget dup /BBox oget /BBox exch 4 2 roll
+ /.execmaskgroup cvx 2 packedarray cvx /Draw exch 3 2 roll
+@@ -414,16 +418,44 @@ end
+ } ifelse SMask
+ } bdef
+
++% Functions specific to the Device* colorspaces to force the switch to
++% the Device* colorspace so that the SMask will not get a CIEBased* colorspace
++% in the case when UseCIEColor changes the Device* colorspace to something else.
++% Also see the logic in pdf_main.ps:pdfopen that similarly defines these resources.
++/forceDefaultCS <<
++ {
++ currentcolorspace setcolorspace % this will switch to Device colorspace
++ } bind
++ /DeviceGray exch
++ /DeviceRGB 1 index
++ /DeviceCMYK 1 index
++>>
++def
++
+ % This procedure is called to actually render the soft mask.
+ /.execmaskgroup { % <masknum> <paramdict> <formdict> .execmaskgroup -
+- % Save our place in PDFfile, and do a gsave to avoid resetting
+- % the color space.
+- currentcolorspace 4 1 roll
++ % Save our place in PDFfile. Do not use gsave-grestore when creating
++ % a soft mask with .begintransparencygroup because high level devices
++ % need to modify the graphic state by storing the soft mask ID.
++ % Save the ExtGState (//nodict begin) BEFORE changing the colorspace
++ mark currentcolor counttomark dup 4 add exch roll pop
++ currentcolorspace 4 1 roll .getuseciecolor 4 1 roll //nodict begin
+ PDFfile fileposition 4 1 roll
+ % We have to select the group's color space so that the
+ % background color will be interpreted correctly.
+- dup /Group oget /CS knownoget { resolvecolorspace dup setgcolorspace csput } if
+- exch dup /BBox get aload pop .begintransparencymaskgroup {
++ % [save/restore]DefaultCS make sure that the SMask logic sees
++ % the Device* spaces, not CIEBased* that UseCIEColor may have
++ % established.
++ false .setuseciecolor % SMask gets processed without UseCIEColor
++ dup /Group oget /CS knownoget {
++ resolvecolorspace dup setgcolorspace csput
++ //true % use currentcolorspace
++ } {
++ % inheriting the colorspace -- make sure Device* spaces are not CIEBased
++ forceDefaultCS currentcolorspace 0 get .knownget { exec } if
++ //false % no defined colorspace
++ } ifelse
++ 3 -1 roll dup /BBox get aload pop .begintransparencymaskgroup {
+ dup /Resources knownoget { oforce } { 0 dict } ifelse
+ exch false resolvestream
+ .execgroup .endtransparencymask
+@@ -431,12 +463,12 @@ end
+ .discardtransparencymask stop
+ } if
+ PDFfile exch setfileposition
+- setcolorspace
++ .setuseciecolor setcolorspace setcolor end % restore colorspace, color and ExtGState (end)
+ } bdef
+ % Paint a Form+Group XObject, either for a transparency mask or for a Do.
+ /.execgroup { % <resdict> <stream> .execgroup -
+ gsave //nodict begin
+- null SMask
++ newpath null SMask
+ 1 .setopacityalpha 1 .setshapealpha
+ /Compatible .setblendmode
+ % Execute the body of the Form, similar to DoForm.
+@@ -773,7 +805,7 @@ currentdict end readonly def
+ exch //false resolvestream pdfopdict .pdfruncontext
+
+ countdictstack exch sub dup 0 gt {
+- ( **** Warning: Pattern stream has imbalanced q/Q operators (too many q's)\n)
++ ( **** Warning: Pattern stream has unbalanced q/Q operators \(too many q's\)\n)
+ pdfformaterror
+ { Q } repeat
+ } {
+@@ -796,16 +828,18 @@ currentdict end readonly def
+ 1 index /File get dup fileposition 3 1 roll
+ % Stack: dict savepos pos file
+ dup 3 -1 roll setfileposition
+- dup 3 index /Length oget
+-
+- dup 65535 le {
+- dup 0 eq {
+- pop pop ()
++ dup 3 index /Length knownoget {
++ dup 65535 le {
++ dup 0 eq {
++ pop pop ()
++ } {
++ string readstring pop
++ } ifelse
+ } {
+- string readstring pop
++ () /SubFileDecode filter /ReusableStreamDecode filter
+ } ifelse
+ } {
+- () /SubFileDecode filter /ReusableStreamDecode filter
++ 0 (endstream) /SubFileDecode filter /ReusableStreamDecode filter
+ } ifelse
+ % Stack: dict savepos file string
+ 3 1 roll exch setfileposition
+@@ -820,6 +854,7 @@ currentdict end readonly def
+ 2 index /Resources knownoget { oforce } { 0 dict } ifelse
+ /.pdfpaintproc cvx
+ ] cvx put
++ dup /.pattern_uses_transparency 1 index patternusestransparency put
+ PDFDEBUG { pdfdict /PDFSTEPcount .knownget { 1 le } { true } ifelse { (%Pattern: ) print dup === flush } if } if
+ } bdef
+
+@@ -1108,24 +1143,41 @@ end
+ } bdef
+
+ /doimagesmask { % <imagemask> doimagesmask -
+- PDFusingtransparency { currentdict /SMask knownoget } { false } ifelse {
+- .begintransparencymaskimage
+- PDFfile fileposition exch
+- gsave //nodict begin
+- null /SoftMask gput
+- 1 .setopacityalpha 1 .setshapealpha
+- /Compatible .setblendmode
+- DoImage
+- end grestore
+- PDFfile exch setfileposition
+- 0 .endtransparencymask
++ PDFusingtransparency {
++ currentdict /SMask knownoget
++ } {
++ false
++ } ifelse
++ { % We are doing transparency and SMask is present in the image
++ % stack: <imagemask> <SMask>
++ currentdevice .devicename /pdfwrite eq {
++ pop % pdfwrite will process SMask directly during 'doimage'
++ } {
++ .begintransparencymaskimage
++ PDFfile fileposition exch
++ gsave //nodict begin
++ null /SoftMask gput
++ 1 .setopacityalpha 1 .setshapealpha
++ /Compatible .setblendmode
++ DoImage
++ end grestore
++ PDFfile exch setfileposition
++ 0 .endtransparencymask
++ } ifelse
+ << /Subtype /Group /Isolated true
+ /.image_with_SMask true % pdfwrite needs : see gs/src/ztrans.c, gs/src/gdevpdft.c
+ >> 0 0 1 1 .begintransparencygroup
+ doimage
+ .endtransparencygroup
+ } {
+- doimage
++ SoftMask //null ne {
++ % the image doesn't have an SMask, but the ExtGState does, force a group.
++ << /Subtype /Group /Isolated true >> 0 0 1 1 .begintransparencygroup
++ doimage
++ .endtransparencygroup
++ }
++ { doimage }
++ ifelse
+ } ifelse
+ } bdef
+
+@@ -1164,9 +1216,7 @@ end
+ % which is done under a rush of 8.63 release.
+ % The purpose is to disable a conversion of an image with soft mask
+ % into a Type 103 image, which currently allocates a full mask buffer
+- % before writing clist. Note that imagemask installs
+- % the transparency mask anyway (likely another bug),
+- % so the image is still masked.
++ % before writing clist.
+ % With this workaround the Matte color is not working (ignored).
+ is_big_mask not
+ } {
+@@ -1226,11 +1276,17 @@ end
+ /.paintform cvx
+ ] cvx /PaintProc exch put
+ % Adjust pdfemptycount since we have an extra dictionary on the stack
+- pdfemptycount exch
+- /pdfemptycount where pop count 2 sub /pdfemptycount exch put
+- q execform Q % gsave / grestore around the Form
++ pdfemptycount countdictstack 3 -1 roll
++ /pdfemptycount count 1 sub store
++ q execform % gsave / grestore around the Form
+ % Restore pdfemptycount
+- /pdfemptycount where pop exch /pdfemptycount exch put
++ countdictstack exch sub
++ dup 1 gt {
++ ( **** Warning: Pattern stream has unbalanced q/Q operators \(too many q's\)\n)
++ pdfformaterror
++ } if
++ { Q } repeat
++ /pdfemptycount exch store
+ } bdef
+
+ /_dops_save 1 array def
+@@ -1298,6 +1354,8 @@ end
+ oforce //unabbrevtypedict 1 index type .knownget { exec } if
+ } bdef
+
++/is_space_dict << 0 0 9 9 10 10 12 12 13 13 32 32 >> readonly def
++
+ drawopdict begin
+ /BI { mark } bdef
+ /ID {
+@@ -1314,23 +1372,34 @@ drawopdict begin
+ % between the last byte of valid data and an EOL.
+ % Some files (PDFOUT v3.8d by GenText) have EI immediately following
+ % the stream. Some have no EOL and garbage bytes.
+- % Therefore, we skip all bytes before EI or EOL
+- 0
+- { PDFsource read not { //true exit } if
+- dup 10 eq 1 index 13 eq or
+- { pop PDFsource token pop /EI ne exit
+- }
+- if
+- exch 69 eq 1 index 73 eq and { //false exit } if % 'EI'
+- }
+- loop
+- exch pop
+- { /ID cvx /syntaxerror signalerror
+- }
+- if
++ % Sometimes (bug 690300) CCITTDecode filter consumes 'E' in 'EI'.
++ % Therefore, we search for <start>I<sp|end> or <start|sp>EI<sp|end>
++ PDFsource read not {
++ /ID cvx /syntaxerror signalerror
++ } if
++ dup 73 eq {
++ pop 10 69 73 % Seed to: <sp>EI
++ } {
++ 10 10 3 -1 roll % Seed to: <sp><sp><any>
++ } ifelse
++ { PDFsource read not dup { 10 exch } if
++ //is_space_dict 2 index known
++ 3 index 73 eq and 4 index 69 eq and
++ //is_space_dict 6 index known and {
++ pop pop pop pop pop exit
++ } {
++ {
++ pop pop pop /ID cvx /syntaxerror signalerror
++ } {
++ 4 -1 roll pop
++ } ifelse
++ } ifelse
++ } loop
+ } bdef
+ end
+
++currentdict /is_space_dict undef
++
+ % ================================ Text ================================ %
+
+ drawopdict begin
+@@ -1401,38 +1470,42 @@ end
+ /drawborder { % <annot> drawborder -
+ gsave
+ dup /BS known 1 index /Border known or {
+- dup /BS knownoget {
++ dup /BS knownoget {
+ dup type /dicttype ne % <annot> <border> <bad?>
+ } {
+ dup /Border oget
+- dup type /arraytype ne % <annot> [border] <bad?>
+- } ifelse
+- {
+- ( **** Warning: Wrong type of annotation border object.\n)
++ dup type /arraytype eq {
++ dup length 3 lt
++ } {
++ //true
++ } ifelse % <annot> [border] <bad?>
++ } ifelse {
++ ( **** Warning: Wrong annotation border object, no border is drawn.\n)
+ pdfformaterror
++ pop { 0 0 0 }
+ } if
+ dup type /dicttype eq {
+- dup /W knownoget not { 1 } if
++ dup /W knownoget not { 1 } if
+ % Per PDF1.6 Reference table 8.13, /W in the border style dictionary is
+ % expressed in points (an absolute unit), so compensate here for any
+ % scaling of the PostScript user space done due to /UserUnit.
+ % Scaling due to -dPDFFitPage is not undone, to keep the correct border width
+ % compared to the size of the surrounding marks.
+- //systemdict /NoUserUnit .knownget not { false } if not
++ //systemdict /NoUserUnit .knownget not { //false } if not
+ //systemdict /PDFFitPage known not and { % UserUnit is ignored if -dPDFFitPage
+ Page /UserUnit knownoget { div } if
+ } if
+- [] 2 index /S knownoget {
+- /D eq { 2 index /D knownoget not { [3] } if exch pop } if
+- } if 3 -1 roll pop strokeborder
+- } {
++ {} 2 index /S knownoget {
++ /D eq { 2 index /D knownoget not { {3} } if exch pop } if
++ } if 3 -1 roll pop strokeborder
++ } {
+ dup 2 get
+- exch dup length 3 gt { 3 get } { pop [] } ifelse
++ exch dup length 3 gt { 3 get } { pop {} } ifelse
+ strokeborder
+ } ifelse
+- } {
+- 1 [] strokeborder
+- } ifelse
++ } {
++ 1 {} strokeborder
++ } ifelse
+ grestore
+ } bdef
+
+diff --git a/Resource/Init/pdf_font.ps b/Resource/Init/pdf_font.ps
+--- a/Resource/Init/pdf_font.ps
++++ b/Resource/Init/pdf_font.ps
+@@ -652,6 +652,11 @@ setglobal
+ % Yet another case of broken PDF's that Adobe Reader accepts.
+ 1 index dup /FontName known {
+ /FontName oget
++ dup type /nametype ne {
++ ( **** /FontName attribute in FontDescriptor is not a name.\n)
++ pdfformaterror
++ cvn
++ } if
+ } {
+ ( **** FontDescriptor missing required /FontName key. BaseFont name used.\n)
+ pdfformaterror
+@@ -735,9 +740,43 @@ setglobal
+ % The whole type1 stream can be executed directly. There's no need to process
+ % Length1, 2, 3 keys.
+
+-/readtype1dict 5 dict dup begin
++/readtype1dict 10 dict dup begin
+ /definefont {
+ exch pop
++
++ /topFontDict where {
++ { /FontType % in PLRM order
++ /FontMatrix
++ /FontName
++ /FontInfo
++ /WMode
++ /Encoding
++ /FontBBox
++ /UniqueID
++ /XUID
++ /PaintType
++ /StrokeWidth
++ /Metrics
++ /Metrics2
++ /CDevProc
++ /CharStrings
++ /Private
++ /WeightVector
++ } {
++ 2 copy .knownget {
++ % Stack: font topFontDict /key val
++ 3 index 3 1 roll put
++ dup /MisplacedKey 0 put
++ } {
++ pop
++ } ifelse
++ } forall
++ /MisplacedKey known {
++ ( **** Warning: Type 1 font defines some of the keys in the external scope.\n)
++ pdfformaterror
++ } if
++ } if
++
+ dup /UniqueID .knownget {
+ dup dup 0 lt exch 16#ffffff gt or {
+ ( **** Warning: Ignoring invalid /UniqueID = ) exch =string cvs
+@@ -793,10 +832,31 @@ setglobal
+ pdfformaterror
+ } ifelse } .bind def
+
+- currentdict dup dup
+- /undef_proc_warning undef
+- /missing-type1-procs undef
+- /readonly-op-dict undef
++ /prev_get /get load def
++
++ /get {
++ dup /FontName eq {
++ % No warning, probably FontName is defined elsewhere; see definefont above.
++ .knownget not { /Missing } if
++ } {
++ dup /UniqueID eq {
++ % We don't want fonts to check /UniqueID and do 'restore'.
++ pop pop 16#FEDCBA98 % Arbitrary and invalid value
++ } {
++ prev_get
++ } ifelse
++ } ifelse
++ } bdef
++
++ /prev_begin /begin load def
++
++ /begin {
++ dup //systemdict eq { pop 0 dict } if
++ prev_begin
++ } bdef
++
++ { /undef_proc_warning /missing-type1-procs /readonly-op-dict }
++ { currentdict exch undef } forall
+
+ end readonly def
+
+@@ -1348,8 +1408,8 @@ currentdict /eexec_pdf_param_dict .undef
+ concatstrings concatstrings
+ cvn
+ QUIET not {
+- (Substituting CID font resource ) print dup ==only
+- ( for ) print 1 index ==only (.\n) print
++ (Substituting CID font ) print dup ==only
++ ( for ) print 1 index ==only (, see doc/Use.htm#CIDFontSubstitution.) =
+ } if
+ exch pop
+ dup /CIDFont resourcestatus {
+@@ -1579,11 +1639,11 @@ currentdict /eexec_pdf_param_dict .undef
+ } 2 bndef
+
+ <01000401> <01000402> <01000403> <01000404> % Type 1C
+- <01000C02>
++ <01000C02> <01000C03>
+ { exch pop
+ dup /Subtype get
+ fontloadprocs exch get exec
+- } 5 bndef
++ } 6 bndef
+
+ <00010000> (true) (typ1) (ttcf) % TrueType OpenType
+ { exch pop readtruetype
+@@ -1627,9 +1687,15 @@ currentdict /bndef undef
+ % /key res res desc stream
+ dup //null ne {
+ PDFfile fileposition
+- 1 index //true resolvestream dup
+- 4 string readstring pop
+- exch closefile
++ mark {
++ 2 index //true resolvestream dup
++ 4 string readstring pop
++ exch closefile
++ } stopped {
++ cleartomark /bad_stream
++ } {
++ exch pop
++ } ifelse
+ PDFfile 3 -1 roll setfileposition
+ dup length 4 lt { pop /bad_stream } if
+ } {
+diff --git a/Resource/Init/pdf_main.ps b/Resource/Init/pdf_main.ps
+--- a/Resource/Init/pdf_main.ps
++++ b/Resource/Init/pdf_main.ps
+@@ -955,15 +955,22 @@ pdfdict begin
+ { Trailer /Root oget /Pages oget
+ dup /Count knownoget {
+ dup 0 le {
+- pop ( **** Warning: Invalid Page count.\n) pdfformaterror
+- % find the last page and use that as the Count
+- 1 1 999999999 {
+- dup pdffindpage?
+- exch pop
+- //null eq { exit } { pop } ifelse
+- } for
+- 1 sub % decrement to last page that we were able to find
+- 2 copy /Count exch put
++ pop
++ dup /Kids knownoget {
++ pop
++ ( **** Warning: Invalid Page count.\n) pdfformaterror
++ % find the last page and use that as the Count
++ 1 1 999999999 {
++ dup pdffindpage?
++ exch pop
++ //null eq { exit } { pop } ifelse
++ } for
++ 1 sub % decrement to last page that we were able to find
++ 2 copy /Count exch put
++ } {
++ 0 % return 0 and keep 0 page count.
++ ( **** Warning: PDF document has no pages.\n) pdfformaterror
++ } ifelse
+ } if
+ exch pop
+ } {
+@@ -1215,9 +1222,18 @@ end readonly def
+ /Link {
+ mark exch
+ dup /C knownoget { /Color exch 3 -1 roll } if
+- { /Rect /Border }
+- { 2 copy knownoget { 3 -1 roll } { pop } ifelse }
+- forall dup /A knownoget {
++ dup /Rect knownoget { /Rect exch 3 -1 roll } if
++ dup /Border knownoget {
++ dup type /arraytype eq {
++ dup length 3 lt
++ } {
++ //true
++ } ifelse {
++ pop [ 0 0 0 ] % Following AR5 use invisible border.
++ } if
++ /Border exch 3 -1 roll
++ } if
++ dup /A knownoget {
+ dup /URI known {
+ /A mark 3 2 roll % <<>> /A [ <<action>>
+ { oforce } forall
+@@ -1539,7 +1555,7 @@ currentdict /PDF2PS_matrix_key undef
+ % Some PDF files don't have matching q/Q (gsave/grestore) so we need
+ % to clean up any left over dicts from the dictstack
+ countdictstack PDFdictstackcount sub dup 0 ne {
+- ( **** Warning: File has imbalanced q/Q operators \(too many q's\)\n)
++ ( **** Warning: File has unbalanced q/Q operators \(too many q's\)\n)
+ pdfformaterror
+ { end } repeat
+ } {
+@@ -1626,17 +1642,27 @@ currentdict /PDF2PS_matrix_key undef
+ /extgstateusestransparency { % <gstate dict> extgstateusestransparency <bool>
+ //false exch % Assume no transparency
+ { % establish loop context
+- exch pop oforce
+ dup /BM knownoget { dup /Normal ne exch /Compatible ne and
+ { pop not exit } if
+ } if
+ dup /ca knownoget { 1 ne { pop not exit } if } if
+ dup /CA knownoget { 1 ne { pop not exit } if } if
+ dup /SMask knownoget { /None ne { pop not exit } if } if
+- pop
+- } forall
++ pop exit
++ } loop
+ } bind def
+
++% Check if transparency is used in a Pattern
++/patternusestransparency { % <Pattern dict> patternusestransparency <bool>
++ //false exch % Assume no transparency
++ {
++ 4 dict 1 index resourceusestransparency { pop not exit } if
++ dup /ExtGState knownoget { extgstateusestransparency { pop not exit } if } if
++ pop exit
++ } loop
++} bind def
++
++
+ % Check the Resources of a page or Form. Check for loops in the resource chain.
+ /resourceusestransparency { % <dict> <dict> resourceusestransparency <bool>
+ { % Use loop to provide an exitable context.
+@@ -1651,19 +1677,33 @@ currentdict /PDF2PS_matrix_key undef
+ } if
+ 2 copy //true put % In the current chain.
+ dup /ExtGState knownoget {
+- extgstateusestransparency
++ //false exch
++ { exch pop oforce extgstateusestransparency { pop //true exit } if
++ } forall
++ { pop //true exit } if
++ } if
++ dup /Pattern knownoget {
++ //false exch
++ { exch pop oforce patternusestransparency { pop //true exit } if
++ } forall
+ { pop //true exit } if
+ } if
+ dup /XObject knownoget {
+- //false exch {
+- exch pop oforce dup /Subtype get
+- dup /Image eq { 1 index /SMask known { pop pop not exit } if } if
+- /Form eq {
+- 3 index exch resourceusestransparency { not exit } if
+- } {
+- pop
+- } ifelse
+- } forall { pop //true exit } if
++ dup type /dicttype eq {
++ //false exch {
++ exch pop oforce dup /Subtype get
++ dup /Image eq { 1 index /SMask known { pop pop not exit } if } if
++ /Form eq {
++ 3 index exch resourceusestransparency { not exit } if
++ } {
++ pop
++ } ifelse
++ } forall { pop //true exit } if
++ } {
++ ( **** Ignoring non-dictionary /XObject attribute.\n)
++ pdfformaterror
++ pop
++ } ifelse
+ } if
+ 2 copy //false put % Visited but not in the current chain.
+ pop //false exit
+@@ -1748,9 +1788,13 @@ currentdict /PDF2PS_matrix_key undef
+ { exch pop oforce /ColorSpace oget 3 index colorspacespotcolors } forall
+ } if
+ /XObject knownoget {
+- { exch pop oforce dup
+- /Subtype get /Form eq { resourcespotcolors } { pop } ifelse
+- } forall
++ dup type /dicttype eq {
++ { exch pop oforce dup
++ /Subtype get /Form eq { resourcespotcolors } { pop } ifelse
++ } forall
++ } {
++ pop % Just ignore here, already reported by resourceusestransparency.
++ } ifelse
+ } if
+ exit
+ } loop
+diff --git a/Resource/Init/pdf_ops.ps b/Resource/Init/pdf_ops.ps
+--- a/Resource/Init/pdf_ops.ps
++++ b/Resource/Init/pdf_ops.ps
+@@ -115,7 +115,7 @@ nodict readonly pop
+ } {
+ //true % formaterror -- not a gsave dict
+ } ifelse
+- { (\n **** File has imbalanced q/Q operators \(too many Q's\) ****\n)
++ { (\n **** File has unbalanced q/Q operators \(too many Q's\) ****\n)
+ pdfformaterror
+ } if
+ } bdef
+@@ -371,10 +371,16 @@ end def
+ } bdef
+ /fsexec % <fillop|strokeop> fsexec -
+ { % Preserve the current point, if any.
++ SoftMask //null ne {
++ mark /Subtype /Group /Isolated true .dicttomark pathbbox .begintransparencygroup
++ } if
+ { currentpoint } stopped
+ { $error /newerror false put cvx exec }
+ { 3 -1 roll cvx exec moveto }
+ ifelse
++ SoftMask //null ne {
++ .endtransparencygroup
++ } if
+ } bdef
+
+ % ---------------- Path painting and clipping ---------------- %
+diff --git a/Resource/Init/pdf_sec.ps b/Resource/Init/pdf_sec.ps
+--- a/Resource/Init/pdf_sec.ps
++++ b/Resource/Init/pdf_sec.ps
+@@ -328,16 +328,17 @@ def
+ pop
+ % this step is for the AES cipher only
+ Trailer /Encrypt oget
+- dup /StmF known
+- {
+- dup /StmF oget
+- exch /CF oget exch oget /CFM oget
+- /AESV2 eq {
+- (sAlT) concatstrings
+- } if
+- }
+- { pop }
+- ifelse
++ dup /StmF knownoget {
++ exch /CF knownoget {
++ exch oget /CFM oget /AESV2 eq {
++ (sAlT) concatstrings
++ } if
++ } {
++ pop
++ } ifelse
++ } {
++ pop
++ } ifelse
+ md5 0 FileKey length 5 add 2 index length .min getinterval
+ } bind def
+
+@@ -397,12 +398,15 @@ def
+ { % If StrF is present ...
+ dup /Identity eq not % Check if StrF != Identity
+ { /StdCF eq
+- { Trailer /Encryption oget /StdCF oget /CFM oget
+- /AESV2 eq
+- % Decrypt string
+- { 1 index aesdecode }
+- { 1 index arc4decode }
+- ifelse
++ { Trailer /Encrypt oget /CF knownoget {
++ /StdCF oget /CFM oget /AESV2 eq
++ } {
++ //false
++ } ifelse { % Decrypt string
++ 1 index aesdecode
++ } {
++ 1 index arc4decode
++ } ifelse
+ }
+ { 1 index arc4decode }
+ ifelse % If StrF != StdCF
+@@ -477,8 +481,10 @@ currentdict /PDFScanRules_null undef
+ } if
+ % Check if the stream encryption handler (StmF) == Identity.
+ PDFDEBUG {
+- Trailer /Encrypt oget /CF get /StdCF get /CFM get
+- (Encrypt StmF is StdCF with CFM ) print =
++ Trailer /Encrypt oget /CF knownoget {
++ /StdCF oget /CFM oget
++ (Encrypt StmF is StdCF with CFM ) print =
++ } if
+ } if
+ /StmF knownoget % Get StmF (if present)
+ not { /Identity } if % If StmF not present default = Identity
+@@ -504,13 +510,13 @@ currentdict /PDFScanRules_null undef
+ exch
+ % Stack: readdata? dict parms filternames file/string
+ 3 index /StreamKey get
+- Trailer /Encrypt oget dup /StmF
+- known
+- {
+- dup /StmF oget % stack: key Encrypt StmF
+- exch /CF oget
+- exch oget /CFM oget % stack: key StmF-CFM
+- /AESV2 eq
++ Trailer /Encrypt oget
++ dup /StmF knownoget
++ { % stack: key Encrypt StmF
++ exch /CF knownoget {
++ exch oget /CFM oget % stack: key StmF-CFM
++ /AESV2 eq
++ } { pop //false } ifelse
+ { aesdecodefilter } % install the requested filter
+ { arc4decodefilter }
+ ifelse
+diff --git a/base/Makefile.in b/base/Makefile.in
+--- a/base/Makefile.in
++++ b/base/Makefile.in
+@@ -82,6 +82,7 @@ CUPSLIBDIRS=@CUPSLIBDIRS@
+ CUPSSERVERBIN=@CUPSSERVERBIN@
+ CUPSSERVERROOT=@CUPSSERVERROOT@
+ CUPSDATA=@CUPSDATA@
++CUPSPDFTORASTER=@CUPSPDFTORASTER@
+
+ # Define the default directory/ies for the runtime
+ # initialization and font files. Separate multiple directories with a :.
+@@ -180,11 +181,14 @@ JBIG2_LIB=jbig2dec
+ SHARE_JBIG2=@SHARE_JBIG2@
+ JBIG2SRCDIR=@JBIG2DIR@
+
+-# uncomment the following to compile in the Luratech ldf_jb2 codec
++# uncomment the following three lines and one of the last two to
++# compile in the Luratech ldf_jb2 codec
+ #JBIG2_LIB=luratech
+ #SHARE_JBIG2=0
+ #JBIG2SRCDIR=ldf_jb2
+-#JBIG2_CFLAGS=-DUSE_LDF_JB2
++#JBIG2_CFLAGS=-DUSE_LDF_JB2 -DLINUX
++#JBIG2_CFLAGS=-DUSE_LDF_JB2 -DMAC -DMAC_OS_X_BUILD
++
+
+ # Choose the library to use for (JPXDecode support)
+ # whether to link to an external build or compile in from source
+@@ -194,11 +198,13 @@ SHARE_JPX=@SHARE_JASPER@
+ JPXSRCDIR=@JASPERDIR@
+ JPX_CFLAGS=-DJAS_CONFIGURE
+
+-# uncomment the following to compile in the Luratech lwf_jp2 codec
++# uncomment the following three lines and one of the last two to
++# compile in the Luratech lwf_jp2 codec
+ #JPX_LIB=luratech
+ #SHARE_JPX=0
+ #JPXSRCDIR=lwf_jp2
+ #JPX_CFLAGS=-DUSE_LWF_JP2 -DLINUX
++#JPX_CFLAGS=-DUSE_LWF_JP2 -DMAC -DMAC_OS_X_BUILD
+
+ # Define the directory where the icclib source are stored.
+ # See icclib.mak for more information
+@@ -506,7 +512,7 @@ include $(GLSRCDIR)/unixinst.mak
+ # Clean up after the autotools scripts
+ # configure.ac and Makefile.in are symlinks from a subdir
+ # (created by autogen.sh) and so are safe to remove
+-distclean : clean config-clean
++distclean : clean config-clean soclean debugclean
+ -$(RM_) -r $(BINDIR) $(GLOBJDIR) $(PSOBJDIR)
+ -$(RM_) -r autom4te.cache
+ -$(RM_) config.log config.status
+diff --git a/base/configure.ac b/base/configure.ac
+--- a/base/configure.ac
++++ b/base/configure.ac
+@@ -420,6 +420,9 @@ dnl look for CUPS...
+ AC_ARG_ENABLE([cups], AC_HELP_STRING([--disable-cups],
+ [Don't include CUPS support]))
+
++AC_ARG_WITH([pdftoraster], AC_HELP_STRING([--without-pdftoraster],
++ [Don't include CUPS' pdftoraster filter]))
++
+ CUPSDEV=""
+ CUPSINCLUDE=""
+ CUPSCFLAGS=""
+@@ -429,6 +432,8 @@ CUPSCONFIG="${CUPSCONFIG:=}"
+ CUPSSERVERBIN=""
+ CUPSSERVERROOT=""
+ CUPSDATA=""
++CUPSVERSION="0"
++CUPSPDFTORASTER="0"
+
+ if ( test -d cups ); then
+ if test x$enable_cups != xno; then
+@@ -446,6 +451,12 @@ if ( test -d cups ); then
+ CUPSDATA="`$CUPSCONFIG --datadir`"
+ CUPSINCLUDE="include cups/cups.mak"
+ CUPSDEV="\$(DD)cups.dev"
++ CUPSVERSION="`$CUPSCONFIG --version`"
++ if ( test x$with_pdftoraster != xno ); then
++ if test "$CUPSVERSION" ">" "1.2"; then
++ CUPSPDFTORASTER="1"
++ fi
++ fi
+ fi
+ fi
+ fi
+@@ -458,6 +469,7 @@ AC_SUBST(CUPSINCLUDE)
+ AC_SUBST(CUPSSERVERBIN)
+ AC_SUBST(CUPSSERVERROOT)
+ AC_SUBST(CUPSDATA)
++AC_SUBST(CUPSPDFTORASTER)
+
+
+ dnl look for IJS implementation
+@@ -781,7 +793,7 @@ P_DEVS=""
+ F_DEVS=""
+
+ dnl Known printers
+-HP_DEVS="cdj500 djet500 djet500c dnj650c cljet5pr deskjet laserjet ljetplus ljet2p ljet3 ljet3d ljet4 ljet4d lj4dith lj5mono lj5gray cdeskjet cdjcolor cdjmono cdj550 pj pjxl pjxl300 lp2563 paintjet pjetxl cljet5 cljet5c pxlmono pxlcolor cdj670 cdj850 cdj880 cdj890 cdj970 cdj1600 chp2200 pcl3 hpdjplus hpdjportable hpdj310 hpdj320 hpdj340 hpdj400 hpdj500 hpdj500c hpdj510 hpdj520 hpdj540 hpdj550c hpdj560c hpdj600 hpdj660c hpdj670c hpdj680c hpdj690c hpdj850c hpdj855c hpdj870c hpdj890c hpdj1120c lj3100sw"
++HP_DEVS="cdj500 djet500 djet500c dnj650c cljet5pr deskjet laserjet ljetplus ljet2p ljet3 ljet3d ljet4 ljet4d lj4dith lj5mono lj5gray cdeskjet cdjcolor cdjmono cdj550 pj pjxl pjxl300 lp2563 paintjet pjetxl cljet5 cljet5c pxlmono pxlcolor cdj670 cdj850 cdj880 cdj890 cdj970 cdj1600 cdnj500 chp2200 pcl3 hpdjplus hpdjportable hpdj310 hpdj320 hpdj340 hpdj400 hpdj500 hpdj500c hpdj510 hpdj520 hpdj540 hpdj550c hpdj560c hpdj600 hpdj660c hpdj670c hpdj680c hpdj690c hpdj850c hpdj855c hpdj870c hpdj890c hpdj1120c lj3100sw"
+ PCLXL_DEVS="pxlmono pxlcolor"
+ EPSON_DEVS="eps9high eps9mid epson epsonc escp lp8000 lq850 photoex st800 stcolor alc1900 alc2000 alc4000 alc4100 alc8500 alc8600 alc9100 lp3000c lp8000c lp8200c lp8300c lp8500c lp8800c lp9000c lp9200c lp9500c lp9800c lps6500 epl2050 epl2050p epl2120 epl2500 epl2750 epl5800 epl5900 epl6100 epl6200 lp1800 lp1900 lp2200 lp2400 lp2500 lp7500 lp7700 lp7900 lp8100 lp8300f lp8400f lp8600 lp8600f lp8700 lp8900 lp9000b lp9100 lp9200b lp9300 lp9400 lp9600 lp9600s lps4500"
+ CANON_DEVS="bj10e bj200 bjc600 bjc800 lbp8 lips3 bjcmono bjcgray bjccmyk bjccolor"
+diff --git a/base/contrib.mak b/base/contrib.mak
+--- a/base/contrib.mak
++++ b/base/contrib.mak
+@@ -782,7 +782,7 @@ $(DD)inferno.dev : $(inferno_) $(DD)page.dev
+ $(SETPDEV) $(DD)inferno $(inferno_)
+
+ $(GLOBJ)gdevifno.$(OBJ) : $(GLSRC)gdevifno.c $(PDEVH)\
+- $(gsparam_h) $(gxlum_h)
++ $(gsparam_h)
+ $(GLCC) $(GLO_)gdevifno.$(OBJ) $(C_) $(GLSRC)gdevifno.c
+
+ ### --------------------------- MGR devices ---------------------------- ###
+diff --git a/base/devs.mak b/base/devs.mak
+--- a/base/devs.mak
++++ b/base/devs.mak
+@@ -418,12 +418,10 @@ $(GLOBJ)gdevvglb.$(OBJ) : $(GLSRC)gdevvglb.c $(GDEV) $(gdevpccm_h) $(gsparam_h)
+ ### NON PORTABLE, ONLY UNIX WITH GCC SUPPORT
+
+ $(GLOBJ)lvga256.so : $(lvga256_)
+- $(CCLD) -shared -Wl,'-solvga256.so' $(lvga256_) -lvga -lvgagl
+- mv lvga256.so $(GLOBJ)lvga256.so
++ $(CCLD) $(LDFLAGS) -shared -o $(GLOBJ)lvga256.so $(lvga256_) -lvga -lvgagl
+
+ $(GLOBJ)vgalib.so : $(vgalib_)
+- $(CCLD) -shared -Wl,'-sovgalib.so' $(vgalib_) -lvga -lvgagl
+- mv vgalib.so $(GLOBJ)vgalib.so
++ $(CCLD) $(LDFLAGS) -shared -o $(GLOBJ)vgalib.so $(vgalib_) -lvga -lvgagl
+
+ ### -------------------------- The X11 device -------------------------- ###
+
+@@ -526,8 +524,7 @@ $(GLOBJ)gdevxalt.$(OBJ) : $(GLSRC)gdevxalt.c $(GDEVX) $(math__h) $(memory__h)\
+ ### NON PORTABLE, ONLY UNIX WITH GCC SUPPORT
+
+ $(GLOBJ)X11.so : $(x11alt_) $(x11_)
+- $(CCLD) -shared -Wl,'-soX11.so' $(x11alt_) $(x11_) -L/usr/X11R6/lib -lXt -lSM -lICE -lXext -lX11 $(XLIBDIRS)
+- mv X11.so $(GLOBJ)X11.so
++ $(CCLD) $(LDFLAGS) -shared -o $(GLOBJ)X11.so $(x11alt_) $(x11_) -L/usr/X11R6/lib -lXt -lSM -lICE -lXext -lX11 $(XLIBDIRS)
+
+ ###### --------------- Memory-buffered printer devices --------------- ######
+
+diff --git a/base/dmmain.c b/base/dmmain.c
+--- a/base/dmmain.c
++++ /dev/null
+@@ -1,997 +0,0 @@
+-/* Copyright (C) 2001-2006 Artifex Software, Inc.
+- All Rights Reserved.
+-
+- This software is provided AS-IS with no warranty, either express or
+- implied.
+-
+- This software is distributed under license and may not be copied, modified
+- or distributed except as expressly authorized under the terms of that
+- license. Refer to licensing information at http://www.artifex.com/
+- or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
+- San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
+-*/
+-/* $Id: dmmain.c 8022 2007-06-05 22:23:38Z giles $ */
+-
+-/* Ghostscript shlib example wrapper for Macintosh (Classic/Carbon) contributed
+- by Nigel Hathaway. Uses the Metrowerks CodeWarrior SIOUX command-line library.
+- */
+-
+-#if __ide_target("Ghostscript PPC (Debug)") || __ide_target("Ghostscript PPC (Release)")
+-#define TARGET_API_MAC_CARBON 0
+-#define TARGET_API_MAC_OS8 1
+-#define ACCESSOR_CALLS_ARE_FUNCTIONS 1
+-#endif
+-
+-#include <Carbon.h>
+-
+-#include <stdlib.h>
+-#include <string.h>
+-#include <stdio.h>
+-#include <console.h>
+-#include <SIOUX.h>
+-#include <SIOUXGlobals.h>
+-#include <SIOUXMenus.h>
+-
+-#include "gscdefs.h"
+-#define GSREVISION gs_revision
+-#include "ierrors.h"
+-#include "iapi.h"
+-
+-#if DEBUG
+-#include "vdtrace.h"
+-#endif
+-
+-#include "gdevdsp.h"
+-
+-#define kScrollBarWidth 15
+-#define MAX_ARGS 25
+-
+-Boolean gRunningOnX = false;
+-Boolean gDone;
+-ControlActionUPP gActionFunctionScrollUPP;
+-
+-const char start_string[] = "systemdict /start get exec\n";
+-void *instance;
+-
+-const unsigned int display_format = DISPLAY_COLORS_RGB | DISPLAY_UNUSED_FIRST |
+- DISPLAY_DEPTH_8 | DISPLAY_BIGENDIAN |
+- DISPLAY_TOPFIRST;
+-typedef struct IMAGE_S IMAGE;
+-struct IMAGE_S {
+- void *handle;
+- void *device;
+- WindowRef windowRef;
+- ControlRef scrollbarVertRef;
+- ControlRef scrollbarHorizRef;
+- PixMapHandle pixmapHdl;
+- UInt64 update_time;
+- int update_interval;
+- IMAGE *next;
+-};
+-
+-IMAGE *first_image;
+-
+-static IMAGE *image_find(void *handle, void *device);
+-
+-static int GSDLLCALL gsdll_stdin(void *instance, char *buf, int len);
+-static int GSDLLCALL gsdll_stdout(void *instance, const char *str, int len);
+-static int GSDLLCALL gsdll_stderr(void *instance, const char *str, int len);
+-static int GSDLLCALL gsdll_poll(void *handle);
+-
+-static int display_open(void *handle, void *device);
+-static int display_preclose(void *handle, void *device);
+-static int display_close(void *handle, void *device);
+-static int display_presize(void *handle, void *device, int width, int height,
+- int raster, unsigned int format);
+-static int display_size(void *handle, void *device, int width, int height,
+- int raster, unsigned int format, unsigned char *pimage);
+-static int display_sync(void *handle, void *device);
+-static int display_page(void *handle, void *device, int copies, int flush);
+-static int display_update(void *handle, void *device,
+- int x, int y, int w, int h);
+-
+-static size_t get_input(void *ptr, size_t size);
+-
+-static void window_create (IMAGE *img);
+-static void window_invalidate (WindowRef windowRef);
+-static void window_adjust_scrollbars (WindowRef windowRef);
+-
+-void main (void);
+-OSErr quitAppEventHandler (AppleEvent *,AppleEvent *,SInt32);
+-void doEvents (EventRecord *);
+-void doMouseDown (EventRecord *);
+-void doUpdate (EventRecord *);
+-void doUpdateWindow (EventRecord *);
+-void doOSEvent (EventRecord *);
+-void doInContent (EventRecord *,WindowRef);
+-pascal void actionFunctionScroll (ControlRef,ControlPartCode);
+-
+-/*********************************************************************/
+-/* stdio functions */
+-static int GSDLLCALL
+-gsdll_stdin(void *instance, char *buf, int len)
+-{
+- if (isatty(fileno(stdin)))
+- return get_input(buf, len);
+- else
+- return fread(buf, 1, len, stdin);
+-}
+-
+-static int GSDLLCALL
+-gsdll_stdout(void *instance, const char *str, int len)
+-{
+- int n = fwrite(str, 1, len, stdout);
+- fflush(stdout);
+- return n;
+-}
+-
+-static int GSDLLCALL
+-gsdll_stderr(void *instance, const char *str, int len)
+-{
+- return gsdll_stdout(instance, str, len);
+-}
+-
+-/* Poll the caller for cooperative multitasking. */
+-/* If this function is NULL, polling is not needed */
+-static int GSDLLCALL gsdll_poll(void *handle)
+-{
+- EventRecord eventStructure;
+-
+- while (WaitNextEvent(everyEvent, &eventStructure, 0, NULL))
+- doEvents(&eventStructure);
+-
+- return (gDone ? e_Fatal : 0);
+-}
+-/*********************************************************************/
+-
+-/* new dll display device */
+-
+-/* New device has been opened */
+-/* This is the first event from this device. */
+-static int display_open(void *handle, void *device)
+-{
+- IMAGE *img = (IMAGE *)malloc(sizeof(IMAGE));
+- if (img == NULL)
+- return -1;
+- memset(img, 0, sizeof(IMAGE));
+-
+- /* add to list */
+- if (first_image)
+- img->next = first_image;
+- first_image = img;
+-
+- /* remember device and handle */
+- img->handle = handle;
+- img->device = device;
+-
+- /* create window */
+- window_create(img);
+-
+- gsdll_poll(handle);
+- return 0;
+-}
+-
+-/* Device is about to be closed. */
+-/* Device will not be closed until this function returns. */
+-static int display_preclose(void *handle, void *device)
+-{
+- /* do nothing - no thread synchonisation needed */
+- return 0;
+-}
+-
+-/* Device has been closed. */
+-/* This is the last event from this device. */
+-static int display_close(void *handle, void *device)
+-{
+- IMAGE *img = image_find(handle, device);
+- if (img == NULL)
+- return -1;
+-
+- gsdll_poll(handle);
+-
+- /* remove from list */
+- if (img == first_image)
+- first_image = img->next;
+- else
+- {
+- IMAGE *tmp;
+- for (tmp = first_image; tmp!=0; tmp=tmp->next)
+- {
+- if (img == tmp->next)
+- tmp->next = img->next;
+- }
+- }
+-
+- DisposePixMap(img->pixmapHdl); // need to go in doCloseWindow()
+- DisposeWindow(img->windowRef);
+-
+- free(img);
+-
+- return 0;
+-}
+-
+-/* Device is about to be resized. */
+-/* Resize will only occur if this function returns 0. */
+-static int display_presize(void *handle, void *device, int width, int height,
+- int raster, unsigned int format)
+-{
+- /* Check for correct format (32-bit RGB), fatal error if not */
+- if (format != display_format)
+- {
+- printf("DisplayFormat has been set to an incompatible value.\n");
+- fflush(stdout);
+- return e_rangecheck;
+- }
+-
+- return 0;
+-}
+-
+-/* Device has been resized. */
+-/* New pointer to raster returned in pimage */
+-static int display_size(void *handle, void *device, int width, int height,
+- int raster, unsigned int format, unsigned char *pimage)
+-{
+- PixMapPtr pixmap;
+- IMAGE *img = image_find(handle, device);
+- if (img == NULL)
+- return -1;
+-
+- /* Check that image is within allowable bounds */
+- if (raster > 0x3fff)
+- {
+- printf("QuickDraw can't cope with an image this big.\n");
+- fflush(stdout);
+- if (img->pixmapHdl)
+- {
+- DisposePixMap(img->pixmapHdl);
+- img->pixmapHdl = NULL;
+- }
+- return e_rangecheck;
+- }
+-
+- /* Create the PixMap */
+- if (!img->pixmapHdl)
+- img->pixmapHdl = NewPixMap();
+-
+- pixmap = *(img->pixmapHdl);
+- pixmap->baseAddr = (char*)pimage;
+- pixmap->rowBytes = (((SInt16)raster) & 0x3fff) | 0x8000;
+- pixmap->bounds.right = width;
+- pixmap->bounds.bottom = height;
+- pixmap->packType = 0;
+- pixmap->packSize = 0;
+- pixmap->pixelType = RGBDirect;
+- pixmap->pixelSize = 32;
+- pixmap->cmpCount = 3;
+- pixmap->cmpSize = 8;
+-
+- /* Update the display window */
+- window_adjust_scrollbars(img->windowRef);
+- window_invalidate(img->windowRef);
+- return gsdll_poll(handle);
+-}
+-
+-/* flushpage */
+-static int display_sync(void *handle, void *device)
+-{
+- IMAGE *img = image_find(handle, device);
+- if (img == NULL)
+- return -1;
+-
+- window_invalidate(img->windowRef);
+- gsdll_poll(handle);
+-
+- return 0;
+-}
+-
+-/* showpage */
+-/* If you want to pause on showpage, then don't return immediately */
+-static int display_page(void *handle, void *device, int copies, int flush)
+-{
+- return display_sync(handle, device);
+-}
+-
+-/* Poll the caller for cooperative multitasking. */
+-/* If this function is NULL, polling is not needed */
+-static int display_update(void *handle, void *device,
+- int x, int y, int w, int h)
+-{
+- UInt64 t1;
+- UInt64 t2;
+- int delta;
+- IMAGE *img = image_find(handle, device);
+- if (img == NULL)
+- return -1;
+-
+- Microseconds((UnsignedWide*)&t1);
+- delta = (t1 - img->update_time) / 1000000L;
+- if (img->update_interval < 1)
+- img->update_interval = 1; /* seconds */
+- if (delta < 0)
+- img->update_time = t1;
+- else if (delta > img->update_interval)
+- {
+- /* redraw window */
+- window_invalidate(img->windowRef);
+-
+- /* Make sure the update interval is at least 10 times
+- * what it takes to paint the window
+- */
+- Microseconds((UnsignedWide*)&t2);
+- delta = (t2 - t1) / 1000;
+- if (delta < 0)
+- delta += 60000; /* delta = time to redraw */
+- if (delta > img->update_interval * 100)
+- img->update_interval = delta/100;
+- img->update_time = t2;
+- }
+-
+- return gsdll_poll(handle);
+-}
+-
+-display_callback display = {
+- sizeof(display_callback),
+- DISPLAY_VERSION_MAJOR,
+- DISPLAY_VERSION_MINOR,
+- display_open,
+- display_preclose,
+- display_close,
+- display_presize,
+- display_size,
+- display_sync,
+- display_page,
+- display_update,
+- NULL, /* memalloc */
+- NULL, /* memfree */
+- NULL /* display_separation */
+-};
+-
+-static IMAGE * image_find(void *handle, void *device)
+-{
+- IMAGE *img;
+- for (img = first_image; img!=0; img=img->next) {
+- if ((img->handle == handle) && (img->device == device))
+- return img;
+- }
+- return NULL;
+-}
+-
+-/*********************************************************************/
+-
+-static char *stdin_buf = NULL;
+-static size_t stdin_bufpos = 0;
+-static size_t stdin_bufsize = 0;
+-
+-/* This function is a fudge which allows the SIOUX window to be waiting for
+- input and not be modal at the same time. (Why didn't MetroWerks think of that?)
+- It is based on the SIOUX function ReadCharsFromConsole(), and contains an
+- event loop which allows other windows to be active.
+- It collects characters up to when the user presses ENTER, stores the complete
+- buffer and gives as much to the calling function as it wants until it runs
+- out, at which point it gets another line (or set of lines if pasting from the
+- clipboard) from the user.
+-*/
+-static size_t get_input(void *ptr, size_t size)
+-{
+- EventRecord eventStructure;
+- long charswaiting, old_charswaiting = 0;
+- char *text;
+-
+-#if SIOUX_USE_WASTE
+- Handle textHandle;
+-#endif
+-
+- /* If needing more input, set edit start position */
+- if (!stdin_buf)
+-#if SIOUX_USE_WASTE
+- SIOUXselstart = WEGetTextLength(SIOUXTextWindow->edit);
+-#else
+- SIOUXselstart = (*SIOUXTextWindow->edit)->teLength;
+-#endif
+-
+- /* Wait until user presses exit (or quits) */
+- while(!gDone && !stdin_buf)
+- {
+-#if SIOUX_USE_WASTE
+- charswaiting = WEGetTextLength(SIOUXTextWindow->edit) - SIOUXselstart;
+-#else
+- if ((*SIOUXTextWindow->edit)->teLength > 0)
+- charswaiting = (*SIOUXTextWindow->edit)->teLength - SIOUXselstart;
+- else
+- charswaiting = ((unsigned short) (*SIOUXTextWindow->edit)->teLength) - SIOUXselstart;
+-#endif
+-
+- /* If something has happened, see if we need to do anything */
+- if (charswaiting != old_charswaiting)
+- {
+-#if SIOUX_USE_WASTE
+- textHandle = WEGetText(SIOUXTextWindow->edit);
+- HLock(textHandle);
+- text = *textHandle + SIOUXselstart;
+-#else
+- text = (*(*SIOUXTextWindow->edit)->hText) + SIOUXselstart;
+-#endif
+- /* If user has pressed enter, gather up the buffer ready for returning */
+- if (text[charswaiting-1] == '\r')
+- {
+- stdin_buf = malloc(charswaiting);
+- if (!stdin_buf)
+- return -1;
+- stdin_bufsize = charswaiting;
+- memcpy(stdin_buf, text, stdin_bufsize);
+- SIOUXselstart += charswaiting;
+-
+- text = stdin_buf;
+- while (text = memchr(text, '\r', charswaiting - (text - stdin_buf)))
+- *text = '\n';
+- }
+-#if SIOUX_USE_WASTE
+- HUnlock(textHandle);
+-#endif
+- old_charswaiting = charswaiting;
+-
+- if (stdin_buf)
+- break;
+- }
+-
+- /* Wait for next event and process it */
+- SIOUXState = SCANFING;
+-
+- if(WaitNextEvent(everyEvent, &eventStructure, SIOUXSettings.sleep ,NULL))
+- doEvents(&eventStructure);
+- else
+- SIOUXHandleOneEvent(&eventStructure);
+-
+- SIOUXState = IDLE;
+- }
+-
+- /* If data has been entered, return as much as has been requested */
+- if (stdin_buf && !gDone)
+- {
+- if (size >= stdin_bufsize - stdin_bufpos)
+- {
+- size = stdin_bufsize - stdin_bufpos;
+- memcpy (ptr, stdin_buf + stdin_bufpos, size);
+- free(stdin_buf);
+- stdin_buf = NULL;
+- stdin_bufpos = 0;
+- stdin_bufsize = 0;
+- }
+- else
+- {
+- memcpy (ptr, stdin_buf + stdin_bufpos, size);
+- stdin_bufpos += size;
+- }
+- return size;
+- }
+- else if (stdin_buf)
+- {
+- free(stdin_buf);
+- stdin_buf = NULL;
+- stdin_bufpos = 0;
+- stdin_bufsize = 0;
+- }
+-
+- return 0;
+-}
+-
+-/*********************************************************************/
+-
+-static void window_create(IMAGE *img)
+-{
+- WindowRef windowRef;
+- Str255 windowTitle = "\pGhostscript Image";
+- Rect windowRect = {20,4,580,420};//, portRect;
+- Rect scrollbarRect = {0,0,0,0};
+-
+-#if TARGET_API_MAC_CARBON
+- GetAvailableWindowPositioningBounds(GetMainDevice(),&windowRect);
+-#endif
+-
+- /* Create a new suitablty positioned window */
+- windowRect.top = windowRect.top * 2 + 2;
+- windowRect.bottom -= 10;
+- windowRect.left += 4;
+- windowRect.right = ((windowRect.bottom - windowRect.top) * 3) / 4 + windowRect.left;
+-
+- if(!(windowRef = NewCWindow(NULL, &windowRect, windowTitle, true,
+- zoomDocProc, (WindowRef) -1, false, 0)))
+- ExitToShell();
+-
+- img->windowRef = windowRef;
+-
+- SetWRefCon(img->windowRef, (SInt32)img);
+-
+- /* Create the window's scrollbars */
+-#if TARGET_API_MAC_CARBON
+- if(gRunningOnX)
+- ChangeWindowAttributes(windowRef,kWindowLiveResizeAttribute,0);
+-
+- CreateScrollBarControl(windowRef, &scrollbarRect, 0, 0, 0, 0,
+- true, gActionFunctionScrollUPP, &(img->scrollbarVertRef));
+-
+- CreateScrollBarControl(windowRef, &scrollbarRect, 0, 0, 0, 0,
+- true, gActionFunctionScrollUPP, &(img->scrollbarHorizRef));
+-#else
+- img->scrollbarVertRef = NewControl(windowRef,&scrollbarRect,"\p",false,0,0,0,scrollBarProc,0);
+- img->scrollbarHorizRef = NewControl(windowRef,&scrollbarRect,"\p",false,0,0,0,scrollBarProc,0);
+-#endif
+-
+- window_adjust_scrollbars(windowRef);
+-}
+-
+-static void window_invalidate(WindowRef windowRef)
+-{
+- Rect portRect;
+-
+- GetWindowPortBounds(windowRef, &portRect);
+- InvalWindowRect(windowRef, &portRect);
+-}
+-
+-static void window_adjust_scrollbars(WindowRef windowRef)
+-{
+- IMAGE *img;
+- Rect portRect;
+-
+- img = (IMAGE*)GetWRefCon(windowRef);
+- GetWindowPortBounds(windowRef,&portRect);
+-
+- /* Move the crollbars to the edges of the window */
+- HideControl(img->scrollbarVertRef);
+- HideControl(img->scrollbarHorizRef);
+-
+- MoveControl(img->scrollbarVertRef,portRect.right - kScrollBarWidth,
+- portRect.top - 1);
+- MoveControl(img->scrollbarHorizRef,portRect.left - 1,
+- portRect.bottom - kScrollBarWidth);
+-
+- SizeControl(img->scrollbarVertRef,kScrollBarWidth + 1,
+- portRect.bottom - portRect.top - kScrollBarWidth + 1);
+- SizeControl(img->scrollbarHorizRef, portRect.right - portRect.left - kScrollBarWidth + 1,
+- kScrollBarWidth + 1);
+-
+- /* Adjust the scroll position showing */
+- if (img->pixmapHdl)
+- {
+- PixMap *pixmap = *(img->pixmapHdl);
+- int visibleHeight = portRect.bottom - portRect.top - kScrollBarWidth;
+- int visibleWidth = portRect.right - portRect.left - kScrollBarWidth;
+-
+- if (pixmap->bounds.bottom > visibleHeight)
+- {
+- SetControl32BitMaximum(img->scrollbarVertRef,
+- pixmap->bounds.bottom - visibleHeight);
+- SetControlViewSize(img->scrollbarVertRef,visibleHeight);
+- }
+- else
+- SetControlMaximum(img->scrollbarVertRef, 0);
+-
+- if (pixmap->bounds.right > visibleWidth)
+- {
+- SetControl32BitMaximum(img->scrollbarHorizRef,
+- pixmap->bounds.right - visibleWidth);
+- SetControlViewSize(img->scrollbarHorizRef, visibleWidth);
+- }
+- else
+- SetControlMaximum(img->scrollbarHorizRef, 0);
+- }
+-
+- ShowControl(img->scrollbarVertRef);
+- ShowControl(img->scrollbarHorizRef);
+-}
+-
+-/*********************************************************************/
+-void main(void)
+-{
+- int code;
+- int exit_code;
+- int argc;
+- char **argv;
+- char dformat[64], ddevice[32];
+- SInt32 response;
+-
+- /* Initialize operating environment */
+-#if TARGET_API_MAC_CARBON
+- MoreMasterPointers(224);
+-#else
+- MoreMasters();
+-#endif
+- InitCursor();
+- FlushEvents(everyEvent,0);
+-
+- if (AEInstallEventHandler(kCoreEventClass,kAEQuitApplication,
+- NewAEEventHandlerUPP((AEEventHandlerProcPtr) quitAppEventHandler),
+- 0L,false) != noErr)
+- ExitToShell();
+-
+- gActionFunctionScrollUPP = NewControlActionUPP(&actionFunctionScroll);
+-
+- Gestalt(gestaltMenuMgrAttr,&response);
+- if(response & gestaltMenuMgrAquaLayoutMask)
+- gRunningOnX = true;
+-
+- /* Initialize SIOUX */
+- SIOUXSettings.initializeTB = false;
+- SIOUXSettings.standalone = false;
+- SIOUXSettings.asktosaveonclose = false;
+- SIOUXSettings.sleep = GetCaretTime();
+- SIOUXSettings.userwindowtitle = "\pGhostscript";
+-
+- /* Get arguments from user */
+- argc = ccommand(&argv);
+-
+- /* Show command line window */
+- if (InstallConsole(0))
+- ExitToShell();
+-
+- /* Part of fudge to make SIOUX accept characters without becoming modal */
+- SelectWindow(SIOUXTextWindow->window);
+- PostEvent(keyDown, 0x4c00); // Enter
+- ReadCharsFromConsole(dformat, 0x7FFF);
+- clrscr();
+-
+- /* Add in the display format as the first command line argument */
+- if (argc >= MAX_ARGS - 1)
+- {
+- printf("Too many command line arguments\n");
+- return;
+- }
+-
+- memmove(&argv[3], &argv[1], (argc-1) * sizeof(char**));
+- argc += 2;
+- argv[1] = ddevice;
+- argv[2] = dformat;
+-
+- sprintf(ddevice, "-sDEVICE=display");
+- sprintf(dformat, "-dDisplayFormat=%d", display_format);
+-
+- /* Run Ghostscript */
+- if (gsapi_new_instance(&instance, NULL) < 0)
+- {
+- printf("Can't create Ghostscript instance\n");
+- return;
+- }
+-
+-#ifdef DEBUG
+- visual_tracer_init();
+- set_visual_tracer(&visual_tracer);
+-#endif
+-
+- gsapi_set_stdio(instance, gsdll_stdin, gsdll_stdout, gsdll_stderr);
+- gsapi_set_poll(instance, gsdll_poll);
+- gsapi_set_display_callback(instance, &display);
+-
+- code = gsapi_init_with_args(instance, argc, argv);
+- if (code == 0)
+- code = gsapi_run_string(instance, start_string, 0, &exit_code);
+- else
+- {
+- printf("Failed to initialize. Error %d.\n", code);
+- fflush(stdout);
+- }
+- code = gsapi_exit(instance);
+- if (code != 0)
+- {
+- printf("Failed to terminate. Error %d.\n", code);
+- fflush(stdout);
+- }
+-
+- gsapi_delete_instance(instance);
+-
+-#ifdef DEBUG
+- visual_tracer_close();
+-#endif
+-
+- /* Ghostscript has finished - let user see output before quitting */
+- WriteCharsToConsole("\r[Finished - hit any key to quit]", 33);
+- fflush(stdout);
+-
+- /* Process events until a key is hit or user quits from menu */
+- while(!gDone)
+- {
+- EventRecord eventStructure;
+-
+- if(WaitNextEvent(everyEvent,&eventStructure,SIOUXSettings.sleep,NULL))
+- {
+- if (eventStructure.what == keyDown)
+- gDone = true;
+-
+- doEvents(&eventStructure);
+- }
+- else
+- SIOUXHandleOneEvent(&eventStructure);
+- }
+-}
+-
+-/*********************************************************************/
+-
+-void doEvents(EventRecord *eventStrucPtr)
+-{
+- WindowRef windowRef;
+-
+- if (eventStrucPtr->what == mouseDown &&
+- FindWindow(eventStrucPtr->where,&windowRef) == inMenuBar)
+- SelectWindow(SIOUXTextWindow->window);
+-
+- SIOUXSettings.standalone = true;
+- if (SIOUXHandleOneEvent(eventStrucPtr))
+- {
+- if (SIOUXQuitting)
+- gDone = true;
+- SIOUXSettings.standalone = false;
+- return;
+- }
+- SIOUXSettings.standalone = false;
+-
+- switch(eventStrucPtr->what)
+- {
+- case kHighLevelEvent:
+- AEProcessAppleEvent(eventStrucPtr);
+- break;
+-
+- case mouseDown:
+- doMouseDown(eventStrucPtr);
+- break;
+-
+- case keyDown:
+- case autoKey:
+- break;
+-
+- case updateEvt:
+- doUpdate(eventStrucPtr);
+- break;
+-
+- case activateEvt:
+- DrawGrowIcon(windowRef);
+- break;
+-
+- case osEvt:
+- doOSEvent(eventStrucPtr);
+- break;
+- }
+-}
+-
+-void doMouseDown(EventRecord *eventStrucPtr)
+-{
+- WindowRef windowRef;
+- WindowPartCode partCode, zoomPart;
+- BitMap screenBits;
+- Rect constraintRect, mainScreenRect;
+- Point standardStateHeightAndWidth;
+- long newSize;
+-
+- partCode = FindWindow(eventStrucPtr->where,&windowRef);
+-
+- switch(partCode)
+- {
+- case inMenuBar:
+- break;
+-
+- case inContent:
+- if(windowRef != FrontWindow())
+- SelectWindow(windowRef);
+- else
+- doInContent(eventStrucPtr,windowRef);
+- break;
+-
+- case inDrag:
+- DragWindow(windowRef,eventStrucPtr->where,NULL);
+- break;
+-
+- case inGoAway:
+- break;
+-
+- case inGrow:
+- constraintRect.top = 75;
+- constraintRect.left = 250;
+- constraintRect.bottom = constraintRect.right = 32767;
+- newSize = GrowWindow(windowRef,eventStrucPtr->where,&constraintRect);
+- if (newSize != 0)
+- SizeWindow(windowRef,LoWord(newSize),HiWord(newSize),true);
+- window_adjust_scrollbars(windowRef);
+- window_invalidate(windowRef);
+- break;
+-
+- case inZoomIn:
+- case inZoomOut:
+- mainScreenRect = GetQDGlobalsScreenBits(&screenBits)->bounds;
+- standardStateHeightAndWidth.v = mainScreenRect.bottom;
+- standardStateHeightAndWidth.h = mainScreenRect.right;
+-
+- if(IsWindowInStandardState(windowRef,&standardStateHeightAndWidth,NULL))
+- zoomPart = inZoomIn;
+- else
+- zoomPart = inZoomOut;
+-
+- if(TrackBox(windowRef,eventStrucPtr->where,partCode))
+- {
+- ZoomWindowIdeal(windowRef,zoomPart,&standardStateHeightAndWidth);
+- window_adjust_scrollbars(windowRef);
+- }
+- break;
+- }
+-}
+-
+-void doUpdate(EventRecord *eventStrucPtr)
+-{
+- WindowRef windowRef;
+-
+- windowRef = (WindowRef) eventStrucPtr->message;
+-
+- window_adjust_scrollbars(windowRef);
+-
+- BeginUpdate(windowRef);
+-
+- SetPortWindowPort(windowRef);
+- doUpdateWindow(eventStrucPtr);
+-
+- EndUpdate(windowRef);
+-}
+-
+-void doUpdateWindow(EventRecord *eventStrucPtr)
+-{
+- IMAGE *img;
+- WindowRef windowRef;
+- Rect srcRect, destRect, fillRect;
+- PixMapHandle srcPixmapHdl, destPixmapHdl;
+- RGBColor grayColour = { 0xC000,0xC000,0xC000 };
+- SInt32 hScroll, vScroll;
+-
+- windowRef = (WindowRef) eventStrucPtr->message;
+- img = (IMAGE*)GetWRefCon(windowRef);
+- srcPixmapHdl = img->pixmapHdl;
+- destPixmapHdl = GetPortPixMap(GetWindowPort(windowRef));
+- hScroll = GetControl32BitValue(img->scrollbarHorizRef);
+- vScroll = GetControl32BitValue(img->scrollbarVertRef);
+-
+- if (srcPixmapHdl)
+- {
+- PixMap *pixmap = *srcPixmapHdl;
+- PixPatHandle hdlPixPat = NewPixPat();
+- MakeRGBPat(hdlPixPat, &grayColour);
+-
+- GetWindowPortBounds(windowRef,&destRect);
+- destRect.right -= kScrollBarWidth;
+- destRect.bottom -= kScrollBarWidth;
+-
+- if (destRect.right > pixmap->bounds.right)
+- {
+- fillRect.top = destRect.top;
+- fillRect.bottom = destRect.bottom;
+- fillRect.left = pixmap->bounds.right;
+- fillRect.right = destRect.right;
+- FillCRect(&fillRect, hdlPixPat);
+- destRect.right = pixmap->bounds.right;
+- }
+- if (destRect.bottom > pixmap->bounds.bottom)
+- {
+- fillRect.top = pixmap->bounds.bottom;
+- fillRect.bottom = destRect.bottom;
+- fillRect.left = destRect.left;
+- fillRect.right = destRect.right;
+- FillCRect(&fillRect, hdlPixPat);
+- destRect.bottom = pixmap->bounds.bottom;
+- }
+- DisposePixPat(hdlPixPat);
+-
+- srcRect = destRect;
+- srcRect.left += hScroll;
+- srcRect.right += hScroll;
+- srcRect.top += vScroll;
+- srcRect.bottom += vScroll;
+-
+- CopyBits((BitMap*)*srcPixmapHdl, (BitMap*)*destPixmapHdl,
+- &srcRect, &destRect, srcCopy, NULL);
+- }
+-
+- DrawGrowIcon(windowRef);
+-}
+-
+-void doOSEvent(EventRecord *eventStrucPtr)
+-{
+- switch((eventStrucPtr->message >> 24) & 0x000000FF)
+- {
+- case suspendResumeMessage:
+- if((eventStrucPtr->message & resumeFlag) == 1)
+- SetThemeCursor(kThemeArrowCursor);
+- break;
+- }
+-}
+-
+-void doInContent(EventRecord *eventStrucPtr,WindowRef windowRef)
+-{
+- ControlPartCode controlPartCode;
+- ControlRef controlRef;
+-
+- SetPortWindowPort(windowRef);
+- GlobalToLocal(&eventStrucPtr->where);
+-
+- if(controlRef = FindControlUnderMouse(eventStrucPtr->where,windowRef,&controlPartCode))
+- {
+-#if TARGET_API_MAC_CARBON
+- TrackControl(controlRef,eventStrucPtr->where,(ControlActionUPP) -1);
+-#else
+- if (controlPartCode == kControlIndicatorPart)
+- TrackControl(controlRef,eventStrucPtr->where,NULL);
+- else
+- TrackControl(controlRef,eventStrucPtr->where,gActionFunctionScrollUPP);
+-#endif
+-
+- window_invalidate(windowRef);
+- }
+-}
+-
+-pascal void actionFunctionScroll(ControlRef controlRef,ControlPartCode controlPartCode)
+-{
+- SInt32 scrollDistance, controlValue, oldControlValue, controlMax;
+-
+- if(controlPartCode != kControlNoPart)
+- {
+- if(controlPartCode != kControlIndicatorPart)
+- {
+- switch(controlPartCode)
+- {
+- case kControlUpButtonPart:
+- case kControlDownButtonPart:
+- scrollDistance = 10;
+- break;
+-
+- case kControlPageUpPart:
+- case kControlPageDownPart:
+- scrollDistance = 100;
+- break;
+-
+- default:
+- scrollDistance = 0;
+- break;
+- }
+-
+- if (scrollDistance)
+- {
+- if((controlPartCode == kControlDownButtonPart) ||
+- (controlPartCode == kControlPageDownPart))
+- scrollDistance = -scrollDistance;
+-
+- controlValue = GetControl32BitValue(controlRef);
+-
+- if(((controlValue == GetControl32BitMaximum(controlRef)) && scrollDistance < 0) ||
+- ((controlValue == GetControl32BitMinimum(controlRef)) && scrollDistance > 0))
+- return;
+-
+- oldControlValue = controlValue;
+- controlMax = GetControl32BitMaximum(controlRef);
+- controlValue = oldControlValue - scrollDistance;
+-
+- if(controlValue < 0)
+- controlValue = 0;
+- else if(controlValue > controlMax)
+- controlValue = controlMax;
+-
+- SetControl32BitValue(controlRef,controlValue);
+- }
+- }
+- }
+-}
+-
+-OSErr quitAppEventHandler(AppleEvent *appEvent,AppleEvent *reply,SInt32 handlerRefcon)
+-{
+- OSErr osError;
+- DescType returnedType;
+- Size actualSize;
+-
+- osError = AEGetAttributePtr(appEvent,keyMissedKeywordAttr,typeWildCard,&returnedType,NULL,0,
+- &actualSize);
+-
+- if(osError == errAEDescNotFound)
+- {
+- gDone = true;
+- osError = noErr;
+- }
+- else if(osError == noErr)
+- osError = errAEParamMissed;
+-
+- return osError;
+-}
+-
+-/*********************************************************************/
+-
+diff --git a/base/dmmain.r b/base/dmmain.r
+--- a/base/dmmain.r
++++ /dev/null
+@@ -1,2537 +0,0 @@
+-/* Copyright (C) 2001-2006 Artifex Software, Inc.
+- All Rights Reserved.
+-
+- This software is provided AS-IS with no warranty, either express or
+- implied.
+-
+- This software is distributed under license and may not be copied, modified
+- or distributed except as expressly authorized under the terms of that
+- license. Refer to licensing information at http://www.artifex.com/
+- or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
+- San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
+-*/
+-/* $Id: dmmain.r 8022 2007-06-05 22:23:38Z giles $ */
+-
+-/* Resource data (Rez format) for the MacOS Ghostscript shlib example wrapper
+- contributed by Nigel Hathaway. See dmmain.c for rest of this code.
+- */
+-
+-#include "Types.r"
+-
+-resource 'BNDL' (128) {
+- 'MCGS',
+- 0,
+- { /* array TypeArray: 2 elements */
+- /* [1] */
+- 'ICN#',
+- { /* array IDArray: 1 elements */
+- /* [1] */
+- 0, 128
+- },
+- /* [2] */
+- 'FREF',
+- { /* array IDArray: 2 elements */
+- /* [1] */
+- 0, 128,
+- /* [2] */
+- 1, 129
+- }
+- }
+-};
+-
+-resource 'FREF' (128) {
+- 'APPL',
+- 0,
+- ""
+-};
+-
+-resource 'FREF' (129) {
+- '****',
+- 1,
+- ""
+-};
+-
+-data 'MWBB' (1008) {
+- $"0001 0000" /* .... */
+-};
+-
+-data 'MPSR' (1005) {
+- $"0009 4D6F 6E61 636F 0000 0000 0000 0000" /* .Monaco........ */
+- $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */
+- $"0000 0003 0004 0030 0004 01CA 027B 0030" /* .......0....{.0 */
+- $"0004 01CA 027B BA5E B2EF 0000 0000 0000" /* ....{^...... */
+- $"0000 0000 0000 0100" /* ........ */
+-};
+-
+-resource 'ICN#' (128, "Application Icon") {
+- { /* array: 2 elements */
+- /* [1] */
+- $"0000 0000 0000 0800 0000 0A00 000B F200"
+- $"007F 4200 00FC 0700 01F0 1F80 03E0 1F80"
+- $"03E5 3FC0 03E0 1FC0 03E0 0FC0 03F0 0780"
+- $"01F8 8300 00FC 4600 003C 0800 00F4 0000"
+- $"03E0 0000 07E0 0000 07FF 6000 07FF FF00"
+- $"07FF FFC0 01FF FFE0 007F FFF0 0000 17F0"
+- $"0780 01F8 0F04 00F0 0E08 03E0 0F07 FFD0"
+- $"0780 D820 03F0 0380 007F FC00 0005 40",
+- /* [2] */
+- $"0000 1800 0000 1E00 0000 1E00 001F FF00"
+- $"00FF FF00 01FF FF00 03FF FF80 03FF FFC0"
+- $"07FF FFC0 07FF FFC0 07FF FFC0 03FF FFC0"
+- $"03FF FF80 01FF FF00 007F FE00 03FF F000"
+- $"07FF F800 07FF FE00 0FFF FF80 0FFF FFE0"
+- $"07FF FFF0 03FF FFF8 01FF FFF8 027F FFFC"
+- $"1FFF FFFC 1FFF FFFC 1FFF FFF8 1FFF FFF8"
+- $"1FFF FFF0 07FF FFC0 01FF FF00 007F FC"
+- }
+-};
+-
+-resource 'ics#' (128, "Application Icon") {
+- { /* array: 2 elements */
+- /* [1] */
+- $"0000 00A0 0F10 1C78 1878 1C18 0E20 0600"
+- $"1800 3FD0 1FF8 057C 300C 3358 18A8 0340",
+- /* [2] */
+- $"0070 07F0 1FF0 1FF8 3FF8 3FF8 1FF8 1FF0"
+- $"3FF0 3FFC 3FFE 1FFE 7FFE 7FFE 7FFC 1FF0"
+- }
+-};
+-
+-resource 'icl8' (128, "Application Icon") {
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 F600 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 5656 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 00F6 FCF8 F900 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 00F6 56F9 FCAC"
+- $"FCFC ACFE F600 FFF6 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 F5FA FDFF FFFF FFFF"
+- $"FD81 F800 00F7 FFF7 0000 0000 0000 0000"
+- $"0000 0000 0000 00F6 E0FF FFFF FFFD F92B"
+- $"0000 0000 F6AC FFFA 0000 0000 0000 0000"
+- $"0000 0000 0000 2BFF EAFF FFFE F700 0000"
+- $"0000 0056 FFFF FFFF 8100 0000 0000 0000"
+- $"0000 0000 0000 FCFF FFFF FF56 0000 00F5"
+- $"F500 FAFF FFFF FFFF FFF8 0000 0000 0000"
+- $"0000 0000 00F6 FFFF FFFF FE00 0079 0055"
+- $"F600 FBFF FFFF FFFF FFFD 0000 0000 0000"
+- $"0000 0000 002B FFFF FFFF FC00 007A F6F5"
+- $"4F00 00AC FFFF FFFF FFFF 0000 0000 0000"
+- $"0000 0000 00F6 FFFF FFFF FFF5 0000 F500"
+- $"0000 00F5 ACFF FFFF FFFC 0000 0000 0000"
+- $"0000 0000 0000 FCFF FFFF FF81 0000 0024"
+- $"F600 0000 F5FD FFFF FF2B 0000 0000 0000"
+- $"0000 0000 0000 F5FF FFFF FFFF 8100 0000"
+- $"7A7A 0000 00FA FFFF F800 0000 0000 0000"
+- $"0000 0000 0000 00F6 FDFF FFFF FFFB 0000"
+- $"F579 0000 00FB F4F8 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0056 FFFF FFFF F800"
+- $"0000 00F6 8181 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 00F8 81FE FFFF FDFA F500"
+- $"0000 2BF7 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 00F5 FCFF FFFF FBF6 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 00AC FFFF FFFF FC2B 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 2BFF FFFF FFFF FFFF E0FC FC81"
+- $"FAF9 FAF7 2B00 0000 0000 0000 0000 0000"
+- $"0000 0000 F6FF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF ACF9 F600 0000 0000 0000"
+- $"0000 0000 00FC FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FF81 F600 0000 0000"
+- $"0000 0000 0000 FAFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FE2B 0000 0000"
+- $"0000 0000 0000 0000 F8FB FCFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFD 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 00F5 F7F7"
+- $"2BF7 F8FA FAFD FFFF FFFF FFFF F900 0000"
+- $"0000 0000 F7AC FFFF FCF6 0000 0000 0000"
+- $"0000 0000 0000 F5FE FFFF FFFF F900 0000"
+- $"0000 00F6 FFFF FFFB 0000 0000 2B81 F700"
+- $"0000 0000 0000 00F9 FFFF FFFF 0000 0000"
+- $"0000 002B FFFF FF2B 0000 0000 FAFB 0000"
+- $"0000 0000 00F5 F8FF FFFF FEF6 F500 0000"
+- $"0000 00F5 FEFF FFFC 0000 0000 F5FC FDFC"
+- $"ACFC ACFC FDFF FFFF FF81 F556 F500 0000"
+- $"0000 0000 F8FF FFFF FBF5 0000 0000 F6FA"
+- $"81AC FCFC FCFA 562B F5F8 FCF5 0000 0000"
+- $"0000 0000 002B FCFF FFFE FCF9 F82B 0000"
+- $"0000 0000 2BF7 FAFC FD56 0000 0000 0000"
+- $"0000 0000 0000 00F7 FAFE FFFF FFFF FFFF"
+- $"FFFF FFFF FFAC 812B 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 F52B F9F9 FAF9"
+- $"FAF8 F72B F6"
+-};
+-
+-resource 'icl4' (128, "Application Icon") {
+- $"0000 0000 0000 0000 0000 C000 0000 0000"
+- $"0000 0000 0000 0000 0000 CD00 0000 0000"
+- $"0000 0000 0000 0000 000C ECD0 0000 0000"
+- $"0000 0000 000C DDEE EEEE C0FC 0000 0000"
+- $"0000 0000 0DFF FFFF AEC0 0CFC 0000 0000"
+- $"0000 000C FFFF FEDC 0000 CEFD 0000 0000"
+- $"0000 00CA FFFA C000 000D AFFF D000 0000"
+- $"0000 00EF FFFD 000C 00DF FFFF FD00 0000"
+- $"0000 0CFF FFF0 0D0C C0EF FFFF FE00 0000"
+- $"0000 0CFF FFE0 07C0 C00E FFFF FF00 0000"
+- $"0000 00FF FFF0 0000 0000 EFFF FE00 0000"
+- $"0000 00EF FFFE 0000 C000 CAFF FC00 0000"
+- $"0000 000F FFFF D000 7D00 0DFF C000 0000"
+- $"0000 000C EFFF FE00 0D00 0EFD 0000 0000"
+- $"0000 0000 0DFF FFD0 000C DD00 0000 0000"
+- $"0000 000C EEFF AD00 00CC 0000 0000 0000"
+- $"0000 00EF FFE0 0000 0000 0000 0000 0000"
+- $"0000 0EFF FFEC 0000 0000 0000 0000 0000"
+- $"0000 CFFF FFFF FEED DDDC C000 0000 0000"
+- $"0000 CFFF FFFF FFFF FFFF FFED C000 0000"
+- $"0000 0EFF FFFF FFFF FFFF FFFF FDC0 0000"
+- $"0000 00DF FFFF FFFF FFFF FFFF FFAC 0000"
+- $"0000 0000 CEEF FFFF FFFF FFFF FFFE 0000"
+- $"0000 0000 0000 00CC CCDD DAFF FFFF D000"
+- $"0000 CEFF EC00 0000 0000 000F FFFF D000"
+- $"000C FFFE 0000 CEC0 0000 000D FFFF 0000"
+- $"000C FFFC 0000 DD00 0000 00DF FFF0 C000"
+- $"0000 FFFE 0000 0EFE EEEE FFFF FD0D 0000"
+- $"0000 CFFF E000 00CD DEEE EDDC 0DE0 0000"
+- $"0000 0CEF FFED CC00 0000 CCDD FC00 0000"
+- $"0000 000C DAFF FFFF FFFF FEEC 0000 0000"
+- $"0000 0000 000C DDDD DDCC"
+-};
+-
+-resource 'ics8' (128, "Application Icon") {
+- $"0000 0000 0000 0000 0000 2B00 0000 0000"
+- $"0000 0000 0000 2B56 F8F9 F856 0000 0000"
+- $"0000 0000 FBFF FFFB 56F5 F7FC 0000 0000"
+- $"0000 00FC FFFD F500 00F9 FFFF F900 0000"
+- $"0000 F5FF FF56 2B2A F6FB FFFF FF00 0000"
+- $"0000 00FE FFFB 00F5 0000 FBFF FC00 0000"
+- $"0000 00F8 FFFF FA00 7900 F7FD F500 0000"
+- $"0000 00F5 F9FF FDF6 00F6 F800 0000 0000"
+- $"0000 2BEA FF56 0000 0000 0000 0000 0000"
+- $"0000 81FF FFFF FEFD FCFC FAF8 0000 0000"
+- $"0000 F6FE FFFF FFFF FFFF FFFF FEF7 0000"
+- $"0000 0000 2B56 FA81 81FC FDFF FFFF F600"
+- $"0000 ACFE 2B00 2BF5 0000 00F8 FFFF F500"
+- $"00F5 FFFC 0000 FA56 56F8 F9FD FE56 F500"
+- $"0000 56E0 FBF7 F6F6 F856 56F9 56F6 0000"
+- $"0000 0000 F881 FCAC FC81 FA2B"
+-};
+-
+-resource 'ics4' (128, "Application Icon") {
+- $"0000 0000 00C0 0000 0000 00CD CDCD 0000"
+- $"0000 EFFD D0CE 0000 000E FA00 0DFF D000"
+- $"000F FDCC 0EFF F000 000F FE00 00EF E000"
+- $"000C FFD0 D0CE 0000 0000 DFF0 0CC0 0000"
+- $"00CF FD00 0000 0000 00DF FFFA EEDD 0000"
+- $"00CA FFFF FFFF FC00 0000 CDDE DEEF FFC0"
+- $"00EF C0C0 000C FF00 00FE 00DD CDDF AD00"
+- $"00DF DCC0 DCDD D000 0000 DDEE EDDC"
+-};
+-
+-resource 'icm8' (128, "Application Icon") {
+- $"0000 0000 0000 0000 0000 F800 0000 0000"
+- $"0000 0000 2BFA FBAC 8156 F681 0000 0000"
+- $"0000 00FA FFFD F7F5 0056 FDFF F800 0000"
+- $"0000 F5FF FF56 2B2A F556 FFFF FF00 0000"
+- $"0000 00FB FFFE F600 4F00 56FF F800 0000"
+- $"0000 00F5 81EA FEF5 00F6 F8F6 0000 0000"
+- $"0000 F8FF FFFA 2BF6 F600 0000 0000 0000"
+- $"0000 56FF FFFF FFFF FFFF E0FC F9F5 0000"
+- $"0000 00F6 F981 FBFC FCAC FDFF FFFD F500"
+- $"0000 FDFD F600 F700 0000 0056 FFFE F500"
+- $"0000 ACFE 2B00 F7F9 8181 FBFB 81F7 0000"
+- $"0000 00F7 FAFB FBFA FAF9 56F8 F6"
+-};
+-
+-resource 'icm4' (128, "Application Icon") {
+- $"0000 0000 00C0 0000 0000 CDEE ECCE 0000"
+- $"000D FAC0 0DEF C000 000F FD0C 0DFF F000"
+- $"000E FFC0 C0DF C000 0000 DFEC 00CC 0000"
+- $"00CF FDC0 C000 0000 00DF FFFF FFFE D000"
+- $"000C DDEE EEFF FF00 00AE C0C0 000D FEC0"
+- $"00FE C0CD DEDE DC00 000C DDED DDDC C0"
+-};
+-
+-resource 'icm#' (128, "Application Icon") {
+- { /* array: 2 elements */
+- /* [1] */
+- $"0000 0350 1C30 1C78 1C10 0620 1900 3FF8"
+- $"0B7C 300C 31B0 0720",
+- /* [2] */
+- $"0070 0FF0 1FF8 3FF8 3FF8 1FF0 3FF8 3FFC"
+- $"1FFE 7FFE 7FFE 3FF8"
+- }
+-};
+-
+-resource 'icns' (128, "Application Icon") {
+- { /* array elementArray: 20 elements */
+- /* [1] */
+- 'ICN#',
+- $"0000 0000 0000 0800 0000 0A00 000B F200"
+- $"007F 4200 00FC 0700 01F0 1F80 03E0 1F80"
+- $"03E5 3FC0 03E0 1FC0 03E0 0FC0 03F0 0780"
+- $"01F8 8300 00FC 4600 003C 0800 00F4 0000"
+- $"03E0 0000 07E0 0000 07FF 6000 07FF FF00"
+- $"07FF FFC0 01FF FFE0 007F FFF0 0000 17F0"
+- $"0780 01F8 0F04 00F0 0E08 03E0 0F07 FFD0"
+- $"0780 D820 03F0 0380 007F FC00 0005 4000"
+- $"0000 1800 0000 1E00 0000 1E00 001F FF00"
+- $"00FF FF00 01FF FF00 03FF FF80 03FF FFC0"
+- $"07FF FFC0 07FF FFC0 07FF FFC0 03FF FFC0"
+- $"03FF FF80 01FF FF00 007F FE00 03FF F000"
+- $"07FF F800 07FF FE00 0FFF FF80 0FFF FFE0"
+- $"07FF FFF0 03FF FFF8 01FF FFF8 027F FFFC"
+- $"1FFF FFFC 1FFF FFFC 1FFF FFF8 1FFF FFF8"
+- $"1FFF FFF0 07FF FFC0 01FF FF00 007F FC00",
+- /* [2] */
+- 'icl4',
+- $"0000 0000 0000 0000 0000 C000 0000 0000"
+- $"0000 0000 0000 0000 0000 CD00 0000 0000"
+- $"0000 0000 0000 0000 000C ECD0 0000 0000"
+- $"0000 0000 000C DDEE EEEE C0FC 0000 0000"
+- $"0000 0000 0DFF FFFF AEC0 0CFC 0000 0000"
+- $"0000 000C FFFF FEDC 0000 CEFD 0000 0000"
+- $"0000 00CA FFFA C000 000D AFFF D000 0000"
+- $"0000 00EF FFFD 000C 00DF FFFF FD00 0000"
+- $"0000 0CFF FFF0 0D0C C0EF FFFF FE00 0000"
+- $"0000 0CFF FFE0 07C0 C00E FFFF FF00 0000"
+- $"0000 00FF FFF0 0000 0000 EFFF FE00 0000"
+- $"0000 00EF FFFE 0000 C000 CAFF FC00 0000"
+- $"0000 000F FFFF D000 7D00 0DFF C000 0000"
+- $"0000 000C EFFF FE00 0D00 0EFD 0000 0000"
+- $"0000 0000 0DFF FFD0 000C DD00 0000 0000"
+- $"0000 000C EEFF AD00 00CC 0000 0000 0000"
+- $"0000 00EF FFE0 0000 0000 0000 0000 0000"
+- $"0000 0EFF FFEC 0000 0000 0000 0000 0000"
+- $"0000 CFFF FFFF FEED DDDC C000 0000 0000"
+- $"0000 CFFF FFFF FFFF FFFF FFED C000 0000"
+- $"0000 0EFF FFFF FFFF FFFF FFFF FDC0 0000"
+- $"0000 00DF FFFF FFFF FFFF FFFF FFAC 0000"
+- $"0000 0000 CEEF FFFF FFFF FFFF FFFE 0000"
+- $"0000 0000 0000 00CC CCDD DAFF FFFF D000"
+- $"0000 CEFF EC00 0000 0000 000F FFFF D000"
+- $"000C FFFE 0000 CEC0 0000 000D FFFF 0000"
+- $"000C FFFC 0000 DD00 0000 00DF FFF0 C000"
+- $"0000 FFFE 0000 0EFE EEEE FFFF FD0D 0000"
+- $"0000 CFFF E000 00CD DEEE EDDC 0DE0 0000"
+- $"0000 0CEF FFED CC00 0000 CCDD FC00 0000"
+- $"0000 000C DAFF FFFF FFFF FEEC 0000 0000"
+- $"0000 0000 000C DDDD DDCC 0000 0000 0000",
+- /* [3] */
+- 'icl8',
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 F600 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 5656 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 00F6 FCF8 F900 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 00F6 56F9 FCAC"
+- $"FCFC ACFE F600 FFF6 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 F5FA FDFF FFFF FFFF"
+- $"FD81 F800 00F7 FFF7 0000 0000 0000 0000"
+- $"0000 0000 0000 00F6 E0FF FFFF FFFD F92B"
+- $"0000 0000 F6AC FFFA 0000 0000 0000 0000"
+- $"0000 0000 0000 2BFF EAFF FFFE F700 0000"
+- $"0000 0056 FFFF FFFF 8100 0000 0000 0000"
+- $"0000 0000 0000 FCFF FFFF FF56 0000 00F5"
+- $"F500 FAFF FFFF FFFF FFF8 0000 0000 0000"
+- $"0000 0000 00F6 FFFF FFFF FE00 0079 0055"
+- $"F600 FBFF FFFF FFFF FFFD 0000 0000 0000"
+- $"0000 0000 002B FFFF FFFF FC00 007A F6F5"
+- $"4F00 00AC FFFF FFFF FFFF 0000 0000 0000"
+- $"0000 0000 00F6 FFFF FFFF FFF5 0000 F500"
+- $"0000 00F5 ACFF FFFF FFFC 0000 0000 0000"
+- $"0000 0000 0000 FCFF FFFF FF81 0000 0024"
+- $"F600 0000 F5FD FFFF FF2B 0000 0000 0000"
+- $"0000 0000 0000 F5FF FFFF FFFF 8100 0000"
+- $"7A7A 0000 00FA FFFF F800 0000 0000 0000"
+- $"0000 0000 0000 00F6 FDFF FFFF FFFB 0000"
+- $"F579 0000 00FB F4F8 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0056 FFFF FFFF F800"
+- $"0000 00F6 8181 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 00F8 81FE FFFF FDFA F500"
+- $"0000 2BF7 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 00F5 FCFF FFFF FBF6 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 00AC FFFF FFFF FC2B 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 2BFF FFFF FFFF FFFF E0FC FC81"
+- $"FAF9 FAF7 2B00 0000 0000 0000 0000 0000"
+- $"0000 0000 F6FF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF ACF9 F600 0000 0000 0000"
+- $"0000 0000 00FC FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FF81 F600 0000 0000"
+- $"0000 0000 0000 FAFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FE2B 0000 0000"
+- $"0000 0000 0000 0000 F8FB FCFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFD 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 00F5 F7F7"
+- $"2BF7 F8FA FAFD FFFF FFFF FFFF F900 0000"
+- $"0000 0000 F7AC FFFF FCF6 0000 0000 0000"
+- $"0000 0000 0000 F5FE FFFF FFFF F900 0000"
+- $"0000 00F6 FFFF FFFB 0000 0000 2B81 F700"
+- $"0000 0000 0000 00F9 FFFF FFFF 0000 0000"
+- $"0000 002B FFFF FF2B 0000 0000 FAFB 0000"
+- $"0000 0000 00F5 F8FF FFFF FEF6 F500 0000"
+- $"0000 00F5 FEFF FFFC 0000 0000 F5FC FDFC"
+- $"ACFC ACFC FDFF FFFF FF81 F556 F500 0000"
+- $"0000 0000 F8FF FFFF FBF5 0000 0000 F6FA"
+- $"81AC FCFC FCFA 562B F5F8 FCF5 0000 0000"
+- $"0000 0000 002B FCFF FFFE FCF9 F82B 0000"
+- $"0000 0000 2BF7 FAFC FD56 0000 0000 0000"
+- $"0000 0000 0000 00F7 FAFE FFFF FFFF FFFF"
+- $"FFFF FFFF FFAC 812B 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 F52B F9F9 FAF9"
+- $"FAF8 F72B F600 0000 0000 0000 0000 0000",
+- /* [4] */
+- 'il32',
+- $"91FF 00DF 9CFF 01A0 909A FF03 D350 AF80"
+- $"91FF 02CF A080 8140 0538 24D5 FF00 DF8D"
+- $"FF02 EF80 2081 0008 0420 60A2 FFFF BF00"
+- $"BF8C FF01 CF10 8100 022C 86BF 81FF 03DF"
+- $"3000 728B FF01 CF10 8000 0110 B083 FF01"
+- $"9410 8000 0066 8AFF 0040 8100 00A2 80FF"
+- $"03E5 E3FF 7C83 0000 A088 FF00 DF81 0008"
+- $"10FF FF82 FF91 C7FF 6083 0000 3088 FF00"
+- $"BF81 0009 40FF FF66 E3D5 BAFF F330 8300"
+- $"88FF 00DF 8200 03EF FFF1 E381 FF01 EF30"
+- $"8100 0044 89FF 004C 8100 006C 80FF 01F1"
+- $"C780 FF05 EF20 0000 04C5 89FF 01DF 1081"
+- $"0000 6C80 FF01 7458 80FF 0380 0000 A08B"
+- $"FF01 D120 8100 0460 FFFF E382 80FF 0254"
+- $"10A2 8EFF 0192 0280 0000 A081 FF03 DB64"
+- $"60EF 8DFF 07AF 6412 0204 2080 EF80 FF01"
+- $"CFBB 8EFF 01EF 4480 0001 50CF 96FF 0040"
+- $"8100 0150 CF95 FF00 CF84 0003 1040 4268"
+- $"8080 01BF D18C FF01 CF02 8D00 0238 92DF"
+- $"89FF 0044 8F00 0204 62DF 88FF 0070 9000"
+- $"0110 CF89 FF02 A060 408D 0001 22EF 8DFF"
+- $"00DF 81BF 04A0 8070 2002 8200 0090 84FF"
+- $"05B4 3600 0046 DB89 FF01 DF20 8100 0090"
+- $"83FF 00DF 8000 0058 81FF 02CF 68BF 85FF"
+- $"0080 8000 0110 EF83 FF00 BF80 0000 BF81"
+- $"FF01 705A 84FF 07EF A410 0000 10CF EF83"
+- $"FF04 EF10 0000 5281 FF02 EF42 2082 4000"
+- $"2681 0003 68E7 96EF 84FF 05A2 0200 0052"
+- $"EF81 FF02 D380 6080 4007 4480 90BF EFA4"
+- $"54EF 86FF 08C3 4000 0010 5080 AFCF 83FF"
+- $"05CF AF80 4C24 A28A FF02 BF70 2086 0004"
+- $"0400 3260 C38F FF02 EFBF 9081 8003 A0BF"
+- $"C7DF 88FF 91FF 00DE 9BFF 02FE A090 9AFF"
+- $"03D3 50AF 8091 FF02 CFA0 8081 4005 3824"
+- $"D4FF 00DF 8DFF 02EF 8020 8100 0804 2060"
+- $"A2FF FFBF 00BF 8CFF 01CF 1081 0002 2C85"
+- $"BF81 FF03 DF30 0072 8BFF 01CF 1080 0001"
+- $"10B0 83FF 0194 1080 0000 668A FF00 4081"
+- $"0000 A280 FF03 ECEB FF7C 8300 00A0 88FF"
+- $"00DF 8100 0810 FFFF A6FF B1D7 FF60 8300"
+- $"002F 88FF 00BF 8100 0940 FFFF 92EB E1CE"
+- $"FFF2 3083 0088 FF00 DE82 0003 EFFF F5EB"
+- $"81FF 01EF 3081 0000 4489 FF00 4C81 0000"
+- $"6B80 FF01 F5D7 80FF 05EF 2000 0004 C589"
+- $"FF01 DF10 8100 006B 80FF 019C 8780 FF03"
+- $"8000 00A0 8BFF 01D1 2081 0004 60FF FFEB"
+- $"A680 FF02 5410 A28E FF01 9202 8000 00A0"
+- $"81FF 03DB 6360 EF8D FF07 AF64 1202 0420"
+- $"80EF 80FF 01CF BB8E FF01 EF44 8000 0150"
+- $"CF96 FF00 3F81 0001 50CF 95FF 00CF 8400"
+- $"0310 4042 6880 8001 BFD1 8CFF 01CF 028D"
+- $"0002 3892 DF89 FF00 448F 0002 0462 DF88"
+- $"FF00 7090 0001 10CF 89FF 02A0 6040 8D00"
+- $"0122 EF8D FF00 DF81 BF04 9F80 7020 0282"
+- $"0000 9084 FF05 B336 0000 46DB 89FF 01DF"
+- $"2081 0000 9083 FF00 DF80 0000 5881 FF04"
+- $"CF68 BFFE FE83 FF00 8080 0001 10EF 83FF"
+- $"00BF 8000 00BF 81FF 0170 5A84 FF07 EFA4"
+- $"1000 0010 CFEE 83FF 04EF 1000 0052 81FF"
+- $"08EF 4220 4040 3F3F 4026 8100 0368 E795"
+- $"EF84 FF05 A102 0000 52EF 81FF 0DD3 8060"
+- $"403F 3F43 8090 BFEF A354 EF86 FF08 C340"
+- $"0000 1050 80AF CF82 FF06 FECF AF7F 4C24"
+- $"A28A FF02 BF70 2086 0004 0400 3260 C38F"
+- $"FF02 EFBF 9081 8003 A0BF C7DF 88FF 90FF"
+- $"01FE DC9B FF03 FCA0 90FE 99FF 03D3 50AF"
+- $"8091 FF02 CFA0 7F81 4005 3C24 D8FF 00DF"
+- $"8DFF 02ED 8020 8100 0804 1E60 A4FF FFBF"
+- $"00BF 8CFF 01CF 0F81 0003 2C80 BEFD 80FF"
+- $"03DF 3000 748B FF01 CF10 8000 0110 B082"
+- $"FF02 FE94 1080 0000 6C8A FF00 4081 0000"
+- $"A480 FF03 F0EF FF7C 8300 00A0 88FF 00DE"
+- $"8100 0810 FFFF B8FF C2DF FF5F 8300 002E"
+- $"88FF 00BF 8100 0940 FFFF A7ED E7D8 FFF0"
+- $"2F83 0088 FF00 DC82 0003 EFFF F6EE 81FF"
+- $"01EE 3081 0000 4489 FF00 4C81 000E 6AFD"
+- $"FFFF F6DE FDFF FFEF 2000 0008 C589 FF01"
+- $"DE10 8100 056A FFFF FEAF 9E80 FF03 8000"
+- $"00A0 8BFF 01D2 2081 0004 60FF FFEF B880"
+- $"FF02 5410 A48E FF01 9404 8000 00A0 81FF"
+- $"03DB 645F EF8C FF08 FDAF 6414 0404 1F80"
+- $"EE80 FF01 CEBB 8EFF 01EF 4680 0002 50CE"
+- $"FE95 FF00 3E81 0001 4ECE 95FF 00CD 8400"
+- $"0310 4044 6880 8001 BFD2 8CFF 01CF 048D"
+- $"0002 3894 DF89 FF00 478F 0002 0464 DF88"
+- $"FF00 6F90 0001 10CF 88FF 03FE A060 408D"
+- $"0001 23ED 86FF 00FE 83FF 00DF 81BF 049C"
+- $"8070 2004 8200 0090 83FF 07FE B23C 0000"
+- $"48DA FD88 FF01 DF20 8100 0090 83FF 00DF"
+- $"8000 0057 81FF 04CF 70BF FCFC 82FF 01FE"
+- $"8080 0001 10ED 83FF 00BF 8000 00BF 81FF"
+- $"0270 58FD 83FF 07EF A410 0000 10CF EC83"
+- $"FF04 EF10 0000 5481 FF08 ED44 2040 403D"
+- $"3D40 2881 0003 68E7 9AEF 83FF 06FE A304"
+- $"0000 53EF 81FF 0DD2 8060 3E3C 3C45 8090"
+- $"BEEE A357 EF86 FF14 C240 0000 1050 80AF"
+- $"CFFF FDFF FFFE FCCF AF7A 4C24 A48A FF02"
+- $"BE70 1E86 0004 0800 3460 C78E FF03 FDEF"
+- $"BF90 8180 04A0 BFCA DFFD 87FF",
+- /* [5] */
+- 'l8mk',
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0005 FF00 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0005 FFFF 0500 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 00FF FFFF FF00 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 00FF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF 0000 0000 0000 0000"
+- $"0000 0000 0000 00FF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF 0000 0000 0000 0000"
+- $"0000 0000 0000 FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FF00 0000 0000 0000"
+- $"0000 0000 0000 FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF 0000 0000 0000"
+- $"0000 0000 00FF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF 0000 0000 0000"
+- $"0000 0000 00FF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF 0000 0000 0000"
+- $"0000 0000 00FF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF 0000 0000 0000"
+- $"0000 0000 0000 FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF 0000 0000 0000"
+- $"0000 0000 0000 FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FF00 0000 0000 0000"
+- $"0000 0000 0000 00FF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 00FF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FF00 0000 0000 0000 0000"
+- $"0000 0000 0000 05FF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 00FF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FF00 0000 0000 0000 0000 0000"
+- $"0000 0000 00FF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FF00 0000 0000 0000 0000"
+- $"0000 0000 FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FF00 0000 0000 0000"
+- $"0000 0000 FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FF00 0000 0000"
+- $"0000 0000 00FF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF 0000 0000"
+- $"0000 0000 0000 FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FF00 0000"
+- $"0000 0000 0000 0005 FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FF00 0000"
+- $"0000 0000 0000 0500 00FF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF 0000"
+- $"0000 0005 FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF 0000"
+- $"0000 00FF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF 0000"
+- $"0000 00FF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FF00 0000"
+- $"0000 00FF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FF00 0000"
+- $"0000 0005 FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF 0000 0000"
+- $"0000 0000 00FF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF 0000 0000 0000"
+- $"0000 0000 0000 00FF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0005 FFFF FFFF FFFF"
+- $"FFFF FFFF FF05 0000 0000 0000 0000 0000",
+- /* [6] */
+- 'ich#',
+- $"0000 0000 0000 0000 0001 0000 0000 0002"
+- $"8000 0000 0002 4000 0000 000C 4000 0000"
+- $"1FFC 6000 0001 FFE0 6000 0007 FF00 E000"
+- $"000F F801 F000 003F E003 F800 003F 800F"
+- $"FC00 007F 800F FC00 007F 091F FE00 007F"
+- $"010F FE00 00FF 0887 FE00 007F 8003 FE00"
+- $"007F 8001 FC00 003F C000 FC00 003F E0C0"
+- $"F000 001F F020 7000 000F F840 C000 0001"
+- $"F801 8000 0003 FC0E 0000 000F F000 0000"
+- $"007F 0000 0000 007E 0000 0000 00FF 8000"
+- $"0000 01FF F690 0000 01FF FFFF 0000 01FF"
+- $"FFFF F000 00FF FFFF FC00 007F FFFF FF00"
+- $"003F FFFF FF80 0007 FFFF FFC0 0000 5FFF"
+- $"FFC0 0000 0001 FFE0 01FC 0000 1FE0 03F0"
+- $"0000 1FC0 03E0 1800 1FC0 03E0 3000 1F80"
+- $"07E0 1801 FF00 03F0 0FFF FC40 01F8 02FF"
+- $"4100 00FC 0000 0E00 007F C000 F800 000F"
+- $"FFFF C000 0001 FFFE 0000 0000 0480 0000"
+- $"0000 0006 0000 0000 0007 4000 0000 0007"
+- $"8000 0000 0007 C000 0000 100F E000 0000"
+- $"7FFF E000 0003 FFFF E000 000F FFFF E000"
+- $"001F FFFF F000 003F FFFF F800 007F FFFF"
+- $"FC00 007F FFFF FE00 00FF FFFF FE00 00FF"
+- $"FFFF FE00 00FF FFFF FE00 00FF FFFF FE00"
+- $"00FF FFFF FE00 007F FFFF FC00 007F FFFF"
+- $"F800 001F FFFF F000 001F FFFF F000 0007"
+- $"FFFF C000 0003 FFFE 0000 007F FFFC 0000"
+- $"007F FFFE 0000 00FF FFFF 8000 01FF FFFF"
+- $"C000 03FF FFFF F800 01FF FFFF FC00 01FF"
+- $"FFFF FF00 01FF FFFF FF80 00FF FFFF FFC0"
+- $"007F FFFF FFE0 001F FFFF FFF0 0000 FFFF"
+- $"FFF0 0043 FFFF FFF0 03FF FFFF FFF0 07FF"
+- $"FFFF FFF0 07FF FFFF FFF0 07FF FFFF FFE0"
+- $"07FF FFFF FFE0 03FF FFFF FFC0 07FF FFFF"
+- $"FF80 01FF FFFF FF00 01FF FFFF FE00 001F"
+- $"FFFF F000 0007 FFFF 8000 0000 3FE4 0000",
+- /* [7] */
+- 'ich4',
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 00CE 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 00DC"
+- $"D000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 00F0 DD00 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 DAE0"
+- $"CFC0 0000 0000 0000 0000 0000 0000 0000"
+- $"0CDE EFFF FFFF FE00 0FA0 0000 0000 0000"
+- $"0000 0000 0000 00DE FFFF FFFF FFED C000"
+- $"CFF0 0000 0000 0000 0000 0000 0000 CFFF"
+- $"FFFF FFFF C000 0000 EFF0 0000 0000 0000"
+- $"0000 0000 000C FFFF FFFF ECC0 0000 000D"
+- $"FFFD 0000 0000 0000 0000 0000 00DF FFFF"
+- $"FFD0 0000 0000 0CFF FFFF E000 0000 0000"
+- $"0000 0000 0CFF FFFF FD00 0000 0000 EFFF"
+- $"FFFF FE00 0000 0000 0000 0000 0AFF FFFF"
+- $"F000 0000 C00D FFFF FFFF FFC0 0000 0000"
+- $"0000 0000 CFFF FFFF D000 D00D C00D FFFF"
+- $"FFFF FFE0 0000 0000 0000 0000 CFFF FFFF"
+- $"0000 9007 C00C FFFF FFFF FFF0 0000 0000"
+- $"0000 0000 CFFF FFFF 0000 7C00 C000 CAFF"
+- $"FFFF FFF0 0000 0000 0000 0000 CFFF FFFF"
+- $"D000 0C00 0000 00FF FFFF FFE0 0000 0000"
+- $"0000 0000 0FFF FFFF F000 0000 0000 000F"
+- $"FFFF FFC0 0000 0000 0000 0000 0DFF FFFF"
+- $"FD00 0000 CC00 000C FFFF FE00 0000 0000"
+- $"0000 0000 00AF FFFF FFD0 0000 7DD0 0000"
+- $"EFFF E000 0000 0000 0000 0000 000E FFFF"
+- $"FFFE 0000 0690 0000 DFFE 0000 0000 0000"
+- $"0000 0000 000C EFFF FFFF E000 0CC0 000C"
+- $"FFDC 0000 0000 0000 0000 0000 0000 0CDF"
+- $"FFFF FD00 0000 00DF E000 0000 0000 0000"
+- $"0000 0000 0000 00EF FFFF FD00 0000 DED0"
+- $"0000 0000 0000 0000 0000 0000 00CD EFFF"
+- $"FFAE C000 000C C000 0000 0000 0000 0000"
+- $"0000 0000 0DFF FFFE DC00 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 DFFF FFFD"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 000C FFFF FFFE DC00 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 000E FFFF FFFF"
+- $"FFFE EDED CCDC C000 0000 0000 0000 0000"
+- $"0000 000F FFFF FFFF FFFF FFFF FFFF FFFD"
+- $"DC00 0000 0000 0000 0000 000E FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFED C000 0000 0000"
+- $"0000 000C FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FED0 0000 0000 0000 0000 CFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFA 0000 0000"
+- $"0000 0000 0CAF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF EC00 0000 0000 0000 0000 DEAF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FE00 0000"
+- $"0000 0000 0000 0000 CDDD EFFF FFFF FFFF"
+- $"FFFF FFFF FFC0 0000 0000 0000 0000 0000"
+- $"0000 0000 000C CCDD FFFF FFFF FFE0 0000"
+- $"0000 00CD EFFF FDC0 0000 0000 0000 0000"
+- $"00DF FFFF FFE0 0000 0000 00EF FFFF C000"
+- $"0000 0000 0000 0000 000A FFFF FFC0 0000"
+- $"0000 0CFF FFFC 0000 000F ECC0 0000 0000"
+- $"000E FFFF FF00 0000 0000 0CFF FFF0 0000"
+- $"00DF D000 0000 0000 0CDF FFFF A000 0000"
+- $"0000 0DFF FFFC 0000 00CF AC00 0000 00CD"
+- $"EAFF FFFE 0CC0 0000 0000 00AF FFFE 0000"
+- $"0000 EFFF FFFF FFFF FFFF FED0 CD00 0000"
+- $"0000 00CF FFFF E000 0000 0CDE EFFF FFFE"
+- $"EDDC 00CE D000 0000 0000 000C FFFF FFC0"
+- $"0000 0000 0000 0000 000C DFFC 0000 0000"
+- $"0000 0000 0DFF FFFF EEDC C000 0000 00CC"
+- $"DEEA FD00 0000 0000 0000 0000 000C EFFF"
+- $"FFFF FFFF FFFF FFFF FFDC 0000 0000 0000"
+- $"0000 0000 0000 00CD FFFF FFFF FFFF FEFD"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"00CC CCDC CD00 0000 0000 0000 0000 0000",
+- /* [8] */
+- 'ich8',
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 F6AC"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 81F6"
+- $"FA00 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 00F5 FF00"
+- $"5681 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 FAAC 8100"
+- $"2BFF 2B00 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"00F8 F9FB FBFF FFFF FFFF FFFE FFAC F500"
+- $"00FF FD00 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 F9AC"
+- $"FFFF FFFF FFFF FFFF FFFF ACFA F600 0000"
+- $"2BFF FF00 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 F8FF FFFF"
+- $"FFFF FFFF FFFF FFFF F800 0000 0000 0000"
+- $"FBFF FF00 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 00F8 FFFF FFFF"
+- $"FFFF FFFF FBF7 F600 0000 0000 0000 F5FA"
+- $"FFFF FFFA 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 F9FF FFFF FFFF"
+- $"FFFF FA00 0000 0000 0000 0000 00F8 FEFF"
+- $"FFFF FFFF 8100 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 00F8 FFFF FFFF FFFF"
+- $"FFF9 0000 0000 0000 0000 0000 FCFF FFFF"
+- $"FFFF FFFF FFFC 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 00AC FFFF FFFF FFFF"
+- $"FFF6 0000 0000 00F6 F600 00F9 FFFF FFFF"
+- $"FFFF FFFF FFFF 2B00 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 F5FF FFFF FFFF FFFF"
+- $"F900 0000 7A00 007A 4F00 00FA FFFF FFFF"
+- $"FFFF FFFF FFFF FB00 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 F8FF FFFF FFFF FFFF"
+- $"0000 0000 C800 0079 2B00 00F6 FEFF FFFF"
+- $"FFFF FFFF FFFF FF00 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 F8FF FFFF FFFF FFFF"
+- $"0000 0000 A5F6 00F5 5500 0000 F6FE FFFF"
+- $"FFFF FFFF FFFF FF00 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 2BFF FFFF FFFF FFFF"
+- $"FA00 0000 F52A 0000 0000 0000 00F5 FEFF"
+- $"FFFF FFFF FFFF FC00 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 00FF FFFF FFFF FFFF"
+- $"FF00 0000 0000 0000 0000 0000 0000 F6FF"
+- $"FFFF FFFF FFFF F800 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 00F9 FFFF FFFF FFFF"
+- $"FF81 0000 0000 00F5 4FF5 0000 0000 00F6"
+- $"FFFF FFFF FFFC 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 FDFF FFFF FFFF"
+- $"FFFF 8100 0000 0000 55C9 5500 0000 0000"
+- $"FBFF FFFF FB00 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 00AC FFFF FFFF"
+- $"FFFF FFAC 0000 0000 25A4 C900 0000 0000"
+- $"FBFF FFFD 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 00F5 ACFF FFFF"
+- $"FFFF FFFF FB00 0000 0055 2B00 0000 00F6"
+- $"FEFF 81F5 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 00F6 FAFF"
+- $"FFFF FFFF FFF9 0000 0000 0000 0000 F9FF"
+- $"ACF5 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 FBFE"
+- $"FFFF FFFF FFF9 0000 0000 0000 FAFC F900"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 2B56 ACFF FFFF"
+- $"FFFF FEFB 2B00 0000 0000 00F6 F800 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 00FA FFFF FFFF FFFD"
+- $"F92B 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 FAFF FFFF FFFF FFF8"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 00F6 FFFF FFFF FFFF FFFE"
+- $"F92B 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 00FD FFFF FFFF FFFF FFFF"
+- $"FFFF FFFB FBFB FB56 F8F8 F8F8 F600 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 00FF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFF9"
+- $"FAF6 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 00AC FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF AC81 2B00 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 00F6 FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFAC 5600 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 F8FF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFD 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 00F8 FDFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FDF5 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 56FB FEFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFAC 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"2BFA F9FA FDFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF F800 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 00F5 F8F8 F8FB"
+- $"FDFF FFFF FFFF FFFF FFFF FB00 0000 0000"
+- $"0000 0000 0000 F5FA FCFF FFFF FFFA F500"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"00F5 FAFF FFFF FFFF FFFF FB00 0000 0000"
+- $"0000 0000 0000 ACFF FFFF FFFF F600 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 00FD FFFF FFFF FFFF F800 0000 0000"
+- $"0000 0000 002B FFFF FFFF FF56 0000 0000"
+- $"0000 F5FD FCF8 F600 0000 0000 0000 0000"
+- $"0000 00FB FFFF FFFF FFFE 0000 0000 0000"
+- $"0000 0000 00F8 FFFF FFFF FF00 0000 0000"
+- $"0000 F9FF 5600 0000 0000 0000 0000 0000"
+- $"00F6 F9FF FFFF FFFF FDF5 0000 0000 0000"
+- $"0000 0000 00F8 FFFF FFFF FFF6 0000 0000"
+- $"0000 F6FF FFF8 0000 0000 0000 0000 F6F9"
+- $"FBFF FFFF FFFF FFFC 00F6 F800 0000 0000"
+- $"0000 0000 0000 FEFF FFFF FFFB 0000 0000"
+- $"0000 00F6 FCFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFD 5600 F6FA 0000 0000 0000"
+- $"0000 0000 0000 F7FF FFFF FFFF FBF6 0000"
+- $"0000 0000 002B FAFB ACFF FFFF FFFF FFAC"
+- $"FBFB F8F8 0000 F6AC FA00 0000 0000 0000"
+- $"0000 0000 0000 002B FFFF FFFF FFFF F800"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 00F6 F9FF FFF8 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 F581 FFFF FFFF FFFF"
+- $"FBFB F9F8 2B00 0000 0000 0000 0000 2BF8"
+- $"F9FB FBFF FDF9 F500 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 00F9 FBFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFE 812B 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 F8FA"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFD FDF9"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 2BF8 F8F8 F8F8 F8F8 F500 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000",
+- /* [9] */
+- 'ih32',
+- $"CBFF 01D5 40AB FF02 71D5 71A9 FF04 E300"
+- $"FF8E 71A7 FF06 8035 60FF D500 C09B FF03"
+- $"AA8E 5555 8300 070E 0B39 E6FF FF00 2B98"
+- $"FF01 8E39 8700 0239 75D5 80FF 02C6 0000"
+- $"96FF 00AA 8700 010B AA84 FF02 5500 0095"
+- $"FF00 AA85 0002 4EB5 D584 FF01 E380 8000"
+- $"0075 93FF 0080 8400 0071 87FF 01AA 1C82"
+- $"0000 6091 FF00 AA84 0000 8087 FF00 5085"
+- $"0000 4090 FF00 3983 0001 06E3 82FF 04D0"
+- $"CDFF FF87 8700 00C6 8EFF 00E3 8400 0080"
+- $"80FF 076A FFFF 6DB5 FFFF 7187 0000 558E"
+- $"FF00 AA84 0081 FF08 20FF FF6A B5FF FFD5"
+- $"1087 008E FF00 AA84 0081 FF04 39CD FFE6"
+- $"9C80 FF01 D51C 8600 8EFF 00C6 8400 0080"
+- $"80FF 01E6 CE84 FF01 E31C 8400 0040 8FFF"
+- $"000B 8400 8AFF 00D5 8400 00AA 8FFF 007F"
+- $"8400 006A 82FF 02E6 B5DA 82FF 00D5 8200"
+- $"0045 91FF 002B 8400 006A 82FF 0283 2083"
+- $"82FF 0055 8000 0055 93FF 002B 8400 0040"
+- $"81FF 02DA 2020 82FF 0355 0000 2B94 FF01"
+- $"E639 8400 0055 81FF 0190 B581 FF04 D523"
+- $"005B E396 FF01 D571 8300 008E 85FF 0391"
+- $"0639 E399 FF01 600B 8200 0080 83FF 0280"
+- $"4080 98FF 02D5 8E40 8100 0307 1C55 C683"
+- $"FF01 E3AA 99FF 0079 8200 021C 80C6 A3FF"
+- $"0080 8300 00AA A4FF 00D5 8400 021C 80C6"
+- $"A2FF 002B 8800 8055 015B 9C81 AA00 D597"
+- $"FF94 0003 0580 80D5 92FF 0030 9600 0307"
+- $"3575 C68F FF01 DA04 9900 0135 918E FF00"
+- $"AA9B 0000 2B8E FF01 AA2B 9A00 012B E38F"
+- $"FF02 8E55 1C97 0000 3C93 FF00 C080 8000"
+- $"2B92 0000 AA9D FF00 E380 AA02 551C 0485"
+- $"0000 5588 FF02 E380 4380 0002 0B6B EA8F"
+- $"FF01 E380 8400 0055 88FF 0035 8200 00D5"
+- $"93FF 002B 8300 00AA 87FF 00C6 8200 009C"
+- $"83FF 04E3 2B47 AAD5 89FF 0055 8200 001C"
+- $"88FF 00AA 8200 84FF 028E 0098 89FF 01E3"
+- $"8082 0001 2BE3 88FF 00AA 8200 00DA 83FF"
+- $"03D5 000B AA85 FF03 DF88 550B 8200 0340"
+- $"FFD5 AA88 FF00 1C81 0000 5584 FF01 D53C"
+- $"8D00 042B 9CFF DA78 89FF 00AE 8200 0155"
+- $"DA84 FF03 CD80 5539 8300 0935 5555 AAAA"
+- $"FFFF CD40 808B FF01 C80B 8200 00AA 91FF"
+- $"04DF 8000 05AA 8DFF 01E3 7183 0004 5555"
+- $"8EAA C686 FF08 C6AA 8E55 550E 2380 E391"
+- $"FF01 8E55 9000 0304 1C60 C697 FF01 AA80"
+- $"8A00 0220 2B80 9FFF 00C6 84AA 00E3 92FF"
+- $"CAFF 04FE D340 FFFE A9FF 0271 D571 A9FF"
+- $"04E3 00FF 8E71 9EFF 00FE 85FF 0680 355F"
+- $"FFD5 00C0 9BFF 03AA 8E55 5583 0007 0E0B"
+- $"39E5 FFFF 002B 98FF 018E 3987 0002 3975"
+- $"D580 FF02 C600 0096 FF00 A887 0002 0BA9"
+- $"FD83 FF02 5500 0095 FF00 AA85 0002 4EB3"
+- $"D484 FF01 E380 8000 0075 93FF 0080 8400"
+- $"0071 87FF 01AA 1C82 0000 6091 FF00 AA84"
+- $"0000 8087 FF00 4F85 0000 4090 FF00 3983"
+- $"0001 06E3 82FF 04DC DCFF FF87 8700 00C6"
+- $"8EFF 00E2 8400 0080 80FF 0795 FFFF 97CA"
+- $"FFFF 7187 0000 548E FF00 AA84 0081 FF08"
+- $"60FE FF95 CAFF FFD3 1087 008E FF00 AA84"
+- $"0081 FF09 72DC FFED B8FF FFFE D41C 8600"
+- $"8EFF 00C6 8400 0080 80FF 01ED DB84 FF01"
+- $"E31C 8400 0040 8EFF 01FE 0B84 008A FF00"
+- $"D584 0000 A98F FF00 7F84 0001 69FE 81FF"
+- $"03ED C9E5 FE81 FF00 D582 0000 4591 FF00"
+- $"2B84 0000 6982 FF02 A660 A682 FF00 5580"
+- $"0000 5593 FF00 2B84 0000 4081 FF02 E560"
+- $"6082 FF03 5500 002B 94FF 01E6 3984 0000"
+- $"5581 FF01 B0CA 81FF 04D5 2300 5BE3 96FF"
+- $"01D5 7183 0000 8E85 FF03 8F06 38E3 99FF"
+- $"0160 0B82 0000 8083 FF02 8040 8097 FF03"
+- $"FED4 8E40 8100 0307 1C55 C683 FF01 E2AA"
+- $"99FF 0077 8200 021C 7FC6 A3FF 0080 8300"
+- $"00AA A4FF 00D3 8400 021C 7FC6 A2FF 002A"
+- $"8800 8055 015B 9C81 AA02 D5FF FE95 FF94"
+- $"0003 0580 80D5 92FF 0030 9600 0307 3575"
+- $"C68F FF01 D904 9900 0135 918E FF00 AA9B"
+- $"0000 2B8E FF01 AA2B 9A00 012B E38F FF02"
+- $"8E55 1C97 0000 3C93 FF00 C080 8000 2B92"
+- $"0000 A99D FF00 E180 AA02 551C 0485 0000"
+- $"5588 FF02 E280 4380 0003 0B6B E9FE 8EFF"
+- $"01E3 8084 0000 5587 FF01 FE35 8200 00D5"
+- $"87FF 01FE FE87 FF00 2B83 0000 AA87 FF00"
+- $"C682 0000 9C83 FF06 E32B 47AA D5FE FE87"
+- $"FF00 5582 0001 1CFE 87FF 00AA 8200 84FF"
+- $"028E 0098 89FF 01E3 8082 0002 2BE3 FE87"
+- $"FF00 AA82 0000 DA83 FF03 D500 0BAA 81FF"
+- $"07FD FDFF FFDF 8855 0B82 0003 40FF D5AA"
+- $"88FF 001C 8100 0055 83FF 02FE D53C 8D00"
+- $"042B 9CFF D978 89FF 00AD 8200 0155 D984"
+- $"FF03 CD7F 5539 8300 0935 5555 AAAA FFFF"
+- $"CD40 808B FF01 C70B 8200 00AA 88FF 00FE"
+- $"81FD 08FF FFFE FEDF 8000 05AA 8DFF 01E3"
+- $"7183 0007 5555 8EAA C6FF FFFE 81FF 0AFE"
+- $"FEC6 AA8E 5455 0E23 80E3 91FF 018D 5590"
+- $"0003 041C 60C6 96FF 02FD A980 8A00 0320"
+- $"2B7F FE9E FF00 C684 AA03 E3FF FFFE 8FFF"
+- $"9AFF 01FD FDAB FF04 FAD0 40FF FDA8 FF03"
+- $"FD71 D571 A9FF 04E3 00FF 8E71 9EFF 00FC"
+- $"85FF 0680 3568 FFD5 00C0 9BFF 03AA 8E55"
+- $"5583 0007 150B 39E5 FFFF 002B 98FF 018E"
+- $"3987 0002 3978 D580 FF02 C600 0096 FF00"
+- $"A387 0002 0BA5 F883 FF02 5500 0095 FF00"
+- $"AA85 0003 4EAA D2FD 83FF 01E3 8080 0000"
+- $"7893 FF00 8084 0000 7187 FF01 AA1C 8200"
+- $"006A 91FF 00AA 8400 0080 87FF 004C 8500"
+- $"0040 90FF 0039 8300 010B E382 FF04 E4E3"
+- $"FFFF 8787 0000 C68E FF00 DF84 0000 8080"
+- $"FF07 AAFF FFAE D5FF FF70 8700 0052 8EFF"
+- $"00AA 8400 81FF 0880 FAFF AAD5 FFFF D010"
+- $"8700 8EFF 00AA 8400 80FF 0AFD 8EE3 FFEF"
+- $"C6FF FFFC D21C 8600 8EFF 00C3 8400 0080"
+- $"80FF 01EF E183 FF02 FDE3 1C84 0000 408E"
+- $"FF01 FA0B 8400 8AFF 00D5 8400 00A8 8FFF"
+- $"007F 8400 0167 FC81 FF03 EFD2 EAFC 81FF"
+- $"00D5 8200 0053 90FF 01FD 2B84 0000 6781"
+- $"FF03 FDB7 80B5 82FF 0055 8000 0055 93FF"
+- $"002B 8400 0040 81FF 02EA 8080 82FF 0355"
+- $"0000 2B94 FF01 E839 8400 0055 81FF 01C0"
+- $"D581 FF04 D523 0060 E396 FF01 D571 8300"
+- $"008E 85FF 038E 0B37 E399 FF01 6B15 8200"
+- $"0080 83FF 0280 4080 97FF 03FC D28E 4081"
+- $"0004 071C 53C6 FD82 FF02 E1AA FD98 FF00"
+- $"7C82 0004 1C7D C6FF FDA1 FF00 8083 0000"
+- $"AAA4 FF00 D084 0002 1B7D C5A1 FF01 FD28"
+- $"8800 8055 0160 9C81 AA02 D5FF FC95 FF94"
+- $"0003 0B80 80D5 92FF 0035 9600 0307 3578"
+- $"C68F FF01 DD07 9900 0135 958E FF00 AA9B"
+- $"0000 2B8E FF01 A82B 9A00 012B E38E FF03"
+- $"FD8E 551C 9700 013E FD92 FF00 C080 8000"
+- $"2B92 0000 A88B FF00 FD8E FF00 DC80 AA02"
+- $"551C 0785 0000 5588 FF02 E180 4E80 0003"
+- $"0E6B E6FC 8EFF 01E3 8084 0000 5587 FF01"
+- $"FD33 8200 00D5 87FF 01FD FD87 FF00 2B83"
+- $"0000 AA87 FF00 C682 0000 9A83 FF06 E32B"
+- $"55AA D5FC FC85 FF02 FDFF 5582 0001 1CFC"
+- $"87FF 00AA 8200 84FF 038E 0095 FD88 FF01"
+- $"E380 8200 022B E3FA 87FF 00AA 8200 00DF"
+- $"83FF 03D5 000B A881 FF07 F8F8 FFFF DF90"
+- $"550B 8200 0340 FFD5 AA88 FF00 1C81 0000"
+- $"5583 FF02 FCD5 408D 0004 2B9C FFDD 7E88"
+- $"FF01 FDAF 8200 0155 DD84 FF03 CD7D 5539"
+- $"8300 0940 5555 A8AA FDFD CD47 808B FF01"
+- $"CC0B 8200 00AA 88FF 00FA 81F8 08FF FFFA"
+- $"FCDF 8000 0BA8 8CFF 02FD E371 8300 0755"
+- $"558E AAC6 FFFF FC81 FF0A FAFC C6AA 8E52"
+- $"530E 2380 E391 FF01 8C55 9000 0307 1C6B"
+- $"C696 FF02 F8A5 808A 0003 352B 7CFD 9EFF"
+- $"00C6 84AA 03E3 FFFF FC8F FF",
+- /* [10] */
+- 'h8mk',
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0005 0500"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0005 FFFF"
+- $"0005 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0005 FFFF"
+- $"FF00 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 00FF FFFF"
+- $"FFFF 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0005 0000 0000 0000 0000 FFFF FFFF"
+- $"FFFF FF00 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"00FF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FF00 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FF00 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FF00 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 00FF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FF00 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 00FF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 00FF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FF00 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FF00 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FF00 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FF00 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FF00 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 05FF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FF00 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 00FF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0005 FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FF00 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 00FF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 00DB FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 00FF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FF00"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0005 FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FF05 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 00FF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FF00"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FF00 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 00FF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 05FF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FF00 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 00FF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 00FF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF 0000 0000 0000 0000"
+- $"0000 0000 0000 00DB FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FF00 0000 0000 0000"
+- $"0000 0000 0000 0000 FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF 0000 0000 0000"
+- $"0000 0000 0000 0000 00FF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FF00 0000 0000"
+- $"0000 0000 0000 0000 0000 0005 FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF 0000 0000"
+- $"0000 0000 0000 0000 0005 0000 0000 FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF 0000 0000"
+- $"0000 0000 0000 FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF 0000 0000"
+- $"0000 0000 0005 FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF 0000 0000"
+- $"0000 0000 00FF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF 0000 0000"
+- $"0000 0000 00FF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FF00 0000 0000"
+- $"0000 0000 00FF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FF00 0000 0000"
+- $"0000 0000 0000 FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF 0000 0000 0000"
+- $"0000 0000 0005 FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FF00 0000 0000 0000"
+- $"0000 0000 0000 00DB FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF 0000 0000 0000 0000"
+- $"0000 0000 0000 0005 FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FF00 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 00FF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0005 FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"0500 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 FFFF FFFF FFFF FFFF FF00 0005 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000",
+- /* [11] */
+- 'ics#',
+- $"0000 00A0 0F10 1C78 1878 1C18 0E20 0600"
+- $"1800 3FD0 1FF8 057C 300C 3358 18A8 0340"
+- $"0070 07F0 1FF0 1FF8 3FF8 3FF8 1FF8 1FF0"
+- $"3FF0 3FFC 3FFE 1FFE 7FFE 7FFE 7FFC 1FF0",
+- /* [12] */
+- 'ics4',
+- $"0000 0000 00C0 0000 0000 00CD CDCD 0000"
+- $"0000 EFFD D0CE 0000 000E FA00 0DFF D000"
+- $"000F FDCC 0EFF F000 000F FE00 00EF E000"
+- $"000C FFD0 D0CE 0000 0000 DFF0 0CC0 0000"
+- $"00CF FD00 0000 0000 00DF FFFA EEDD 0000"
+- $"00CA FFFF FFFF FC00 0000 CDDE DEEF FFC0"
+- $"00EF C0C0 000C FF00 00FE 00DD CDDF AD00"
+- $"00DF DCC0 DCDD D000 0000 DDEE EDDC 0000",
+- /* [13] */
+- 'ics8',
+- $"0000 0000 0000 0000 0000 2B00 0000 0000"
+- $"0000 0000 0000 2B56 F8F9 F856 0000 0000"
+- $"0000 0000 FBFF FFFB 56F5 F7FC 0000 0000"
+- $"0000 00FC FFFD F500 00F9 FFFF F900 0000"
+- $"0000 F5FF FF56 2B2A F6FB FFFF FF00 0000"
+- $"0000 00FE FFFB 00F5 0000 FBFF FC00 0000"
+- $"0000 00F8 FFFF FA00 7900 F7FD F500 0000"
+- $"0000 00F5 F9FF FDF6 00F6 F800 0000 0000"
+- $"0000 2BEA FF56 0000 0000 0000 0000 0000"
+- $"0000 81FF FFFF FEFD FCFC FAF8 0000 0000"
+- $"0000 F6FE FFFF FFFF FFFF FFFF FEF7 0000"
+- $"0000 0000 2B56 FA81 81FC FDFF FFFF F600"
+- $"0000 ACFE 2B00 2BF5 0000 00F8 FFFF F500"
+- $"00F5 FFFC 0000 FA56 56F8 F9FD FE56 F500"
+- $"0000 56E0 FBF7 F6F6 F856 56F9 56F6 0000"
+- $"0000 0000 F881 FCAC FC81 FA2B 0000 0000",
+- /* [14] */
+- 'is32',
+- $"87FF 00C3 87FF 06F3 C79F 9F8C B598 84FF"
+- $"08F3 6008 0B53 9FE8 B34C 84FF 0948 002C"
+- $"EBF8 F884 0400 8182 FF0A E700 0093 B9D2"
+- $"E061 0000 0C82 FF0A F713 0057 FCF5 F1FB"
+- $"5000 4383 FF09 B008 0073 FF8C FFB4 2DE7"
+- $"83FF 08EB 8202 28E3 FFD9 B0FB 83FF 03CB"
+- $"1100 9089 FF00 6880 0006 142B 4050 75B2"
+- $"F782 FF01 D01C 8500 011A AF83 FF13 BF90"
+- $"7860 6048 2401 0009 DFFF FFF7 3B16 C8FF"
+- $"CDEF 80FF 139F 0004 DFFF FFEB 0444 FFFF"
+- $"7F97 9F9F 852D 1A97 F780 FF0B 9A10 54B3"
+- $"DFD4 A79F 9187 96D0 82FF 08EF A36C 4440"
+- $"4863 84C8 81FF 87FF 00C3 87FF 06F3 C79F"
+- $"9F8C B598 84FF 08F3 6008 0B52 9FE8 B34C"
+- $"84FF 0948 002C EBFA FA84 0400 8182 FF0A"
+- $"E700 0093 CDDF E960 0000 0C82 FF0A F713"
+- $"0057 FCF8 F5FB 5000 4383 FF09 B008 0072"
+- $"FFAD FFB4 2DE7 83FF 08EB 8202 28E3 FFD9"
+- $"B0FB 83FF 03CB 1100 8F89 FF00 6880 0006"
+- $"142B 4050 74B2 F782 FF01 D01C 8500 011A"
+- $"AF83 FF13 BF90 7860 6048 2401 0008 DFFF"
+- $"FFF7 3A16 C8FF CDEF 80FF 139F 0004 DFFF"
+- $"FFEB 0444 FFFF 7F97 9F9F 852D 1A97 F780"
+- $"FF0B 9910 54B3 DFD4 A79F 9086 96D0 82FF"
+- $"08EF A36C 4440 4863 84C8 81FF 86FF 01FE"
+- $"C287 FF06 F3C7 9F9F 8DB6 9884 FF08 F35F"
+- $"080B 519F E8B3 4D84 FF09 4800 2DEB FBFB"
+- $"8304 0083 82FF 0AE7 0000 93D7 E5ED 5F00"
+- $"000C 82FF 0AF6 1300 56FC F9F6 FB50 0044"
+- $"83FF 09B0 0800 72FF BDFF B42D E783 FF08"
+- $"EA83 0328 E3FF D9B0 FB83 FF03 CB12 008F"
+- $"89FF 0068 8000 0614 2B40 5075 B2F7 82FF"
+- $"01D1 1C85 0001 1AAF 83FF 2ABF 9078 6060"
+- $"4724 0100 09DF FFFF F73C 16C8 FFCF EEFE"
+- $"FFFF 9F00 04DF FFFF EB04 45FF FF7E 979F"
+- $"9F86 2D1A 98F6 80FF 0B9A 1055 B3DF D3A7"
+- $"9D91 8596 D182 FF08 EFA3 6C44 4048 6584"
+- $"C981 FF",
+- /* [15] */
+- 's8mk',
+- $"0000 0000 0000 0000 0005 FF05 0000 0000"
+- $"0000 0000 00FF FFFF FFFF FFFF 0000 0000"
+- $"0000 00FF FFFF FFFF FFFF FFFF 0000 0000"
+- $"0000 00FF FFFF FFFF FFFF FFFF FF00 0000"
+- $"0000 FFFF FFFF FFFF FFFF FFFF FF00 0000"
+- $"0000 FFFF FFFF FFFF FFFF FFFF FF00 0000"
+- $"0000 00FF FFFF FFFF FFFF FFFF FF00 0000"
+- $"0000 00FF FFFF FFFF FFFF FFFF 0000 0000"
+- $"0000 FFFF FFFF FFFF FFFF FFFF 0000 0000"
+- $"0000 FFFF FFFF FFFF FFFF FFFF FFFF 0000"
+- $"0000 FFFF FFFF FFFF FFFF FFFF FFFF FF00"
+- $"0000 0005 FFFF FFFF FFFF FFFF FFFF FF00"
+- $"00FF FFFF FFFF FFFF FFFF FFFF FFFF FF00"
+- $"00FF FFFF FFFF FFFF FFFF FFFF FFFF FF00"
+- $"0005 FFFF FFFF FFFF FFFF FFFF FFFF 0000"
+- $"0000 00FF FFFF FFFF FFFF FFFF 0000 0000",
+- /* [16] */
+- 'icm#',
+- $"0000 0350 1C30 1C78 1C10 0620 1900 3FF8"
+- $"0B7C 300C 31B0 0720 0070 0FF0 1FF8 3FF8"
+- $"3FF8 1FF0 3FF8 3FFC 1FFE 7FFE 7FFE 3FF8",
+- /* [17] */
+- 'icm4',
+- $"0000 0000 00C0 0000 0000 CDEE ECCE 0000"
+- $"000D FAC0 0DEF C000 000F FD0C 0DFF F000"
+- $"000E FFC0 C0DF C000 0000 DFEC 00CC 0000"
+- $"00CF FDC0 C000 0000 00DF FFFF FFFE D000"
+- $"000C DDEE EEFF FF00 00AE C0C0 000D FEC0"
+- $"00FE C0CD DEDE DC00 000C DDED DDDC C000",
+- /* [18] */
+- 'icm8',
+- $"0000 0000 0000 0000 0000 F800 0000 0000"
+- $"0000 0000 2BFA FBAC 8156 F681 0000 0000"
+- $"0000 00FA FFFD F7F5 0056 FDFF F800 0000"
+- $"0000 F5FF FF56 2B2A F556 FFFF FF00 0000"
+- $"0000 00FB FFFE F600 4F00 56FF F800 0000"
+- $"0000 00F5 81EA FEF5 00F6 F8F6 0000 0000"
+- $"0000 F8FF FFFA 2BF6 F600 0000 0000 0000"
+- $"0000 56FF FFFF FFFF FFFF E0FC F9F5 0000"
+- $"0000 00F6 F981 FBFC FCAC FDFF FFFD F500"
+- $"0000 FDFD F600 F700 0000 0056 FFFE F500"
+- $"0000 ACFE 2B00 F7F9 8181 FBFB 81F7 0000"
+- $"0000 00F7 FAFB FBFA FAF9 56F8 F600 0000",
+- /* [19] */
+- 'it32',
+- $"0000 0000 FFFF FFFF FFFF C9FF 0100 00FC"
+- $"FF01 0000 F8FF 0000 80FF 0100 00F7 FF01"
+- $"0000 80FF 0100 00F6 FF01 0000 81FF 0100"
+- $"00F5 FF80 0080 FF80 00F4 FF80 0081 FF80"
+- $"00F2 FF81 0081 FF80 00F1 FF00 4080 0082"
+- $"FF81 00ED FF82 0001 2020 83FF 8100 D9FF"
+- $"8D00 0240 2020 8200 0020 84FF 8100 D3FF"
+- $"9B00 85FF 8200 CDFF 9C00 0140 0087 FF82"
+- $"00CA FF9F 0089 FF82 00C7 FF9E 0001 2000"
+- $"8AFF 8300 C5FF 9E00 8EFF 8300 C3FF 9800"
+- $"0040 8000 91FF 8400 C1FF 9C00 93FF 8400"
+- $"C0FF 9700 0160 0096 FF85 00BF FF93 0002"
+- $"4040 0099 FF88 00BC FF94 0000 4099 FF89"
+- $"0001 2000 BAFF 9300 9BFF 8C00 0020 B8FF"
+- $"9300 9AFF 9000 B6FF 9200 9BFF 9000 0120"
+- $"20B4 FF92 009A FF00 4094 00B3 FF91 009A"
+- $"FF97 00B1 FF92 0099 FF00 4097 00B1 FF91"
+- $"0090 FF00 2085 FF01 4040 9800 AFFF 9100"
+- $"0020 8EFF 023A 2020 85FF 9A00 AFFF 9100"
+- $"88FF 0020 83FF 8020 85FF 9B00 AEFF 9100"
+- $"87FF 0120 2083 FF80 2085 FF9B 00AD FF92"
+- $"0086 FF80 2083 FF02 203A 2086 FF9A 00AD"
+- $"FF91 0087 FF80 2083 FF80 2086 FF9B 00AC"
+- $"FF91 0087 FF80 2083 FF80 2087 FF00 4099"
+- $"00AC FF91 0087 FF80 2084 FF80 2087 FF99"
+- $"00AC FF91 0087 FF81 2084 FF01 2020 88FF"
+- $"9800 ACFF 9100 88FF 8020 92FF 9700 ACFF"
+- $"9200 88FF 8020 92FF 9600 ACFF 9200 A1FF"
+- $"9200 0140 00AE FF91 00A2 FF93 00AE FF92"
+- $"00A2 FF91 00AF FF00 4091 00A3 FF90 00B0"
+- $"FF92 00A3 FF8D 0000 60B1 FF01 4040 9000"
+- $"0040 A3FF 8B00 0120 00B2 FF91 0001 4040"
+- $"8CFF 8220 8EFF 8B00 0020 B4FF 9300 8DFF"
+- $"8220 8DFF 8A00 B5FF 9300 0040 8CFF 8320"
+- $"8CFF 8900 B7FF 9200 0140 408C FF82 208C"
+- $"FF88 00B9 FF94 008B FF83 208B FF87 00BB"
+- $"FF94 008B FF82 208B FF86 00BD FF00 2093"
+- $"008A FF81 208C FF85 00BF FF94 008A FF01"
+- $"2020 8CFF 0040 8300 0020 C2FF 9300 99FF"
+- $"8400 C6FF 9200 97FF 8300 CAFF 9000 96FF"
+- $"8300 CDFF 8F00 93FF 0500 2000 2000 00CE"
+- $"FF01 2020 8E00 90FF 8040 8000 CFFF 0300"
+- $"0020 208D 008F FF01 0000 8040 CFFF 0040"
+- $"9100 90FF 8000 CFFF 9300 E4FF 8E00 0040"
+- $"8100 E6FF 9100 E7FF 0120 208E 00E9 FF8F"
+- $"00EA FF8F 00EA FF90 00E9 FF92 00E8 FF94"
+- $"00E5 FF98 00E2 FF9C 00DD FFA8 00D2 FFA5"
+- $"0004 2000 0040 4089 00C4 FFBC 0000 20BD"
+- $"FFC3 00B7 FFC4 0001 4040 B4FF C800 0020"
+- $"B2FF 0020 CA00 AFFF 0020 CB00 0040 AEFF"
+- $"CD00 0020 ACFF 0020 CF00 ABFF D100 ABFF"
+- $"D000 ABFF D000 ABFF D000 ACFF CF00 AFFF"
+- $"CB00 0020 B0FF CA00 B4FF C700 B9FF C200"
+- $"C2FF B800 D6FF A500 DEFF 9C00 E1FF 0200"
+- $"0020 9600 A2FF 0020 8900 0140 40B1 FF95"
+- $"009F FF03 0000 2020 8900 0040 B4FF 9300"
+- $"9DFF 8D00 0060 B7FF 9200 9CFF 0040 8C00"
+- $"B9FF 9100 9CFF 8D00 BBFF 9000 9CFF 8C00"
+- $"92FF 0200 2020 8200 9FFF 8F00 9CFF 8B00"
+- $"0020 92FF 0400 0020 2000 A3FF 8F00 9CFF"
+- $"8B00 0060 91FF 8100 A5FF 8E00 9DFF 8B00"
+- $"92FF 8100 A4FF 8E00 9EFF 8B00 91FF 8100"
+- $"0060 A3FF 8E00 9FFF 8B00 92FF 8200 A0FF"
+- $"8F00 A0FF 8B00 92FF 8200 0040 9CFF 0100"
+- $"408F 0082 FF00 009B FF8B 0000 2092 FF84"
+- $"0095 FF01 4020 9100 0140 4082 FF01 0000"
+- $"9CFF 8B00 93FF AE00 0240 4000 83FF 0100"
+- $"009D FF8C 0093 FF01 0020 AC00 84FF 0120"
+- $"009F FF8C 0094 FFAA 0085 FF01 2020 A0FF"
+- $"0020 8C00 95FF 0100 40A2 0087 FF80 00A2"
+- $"FF8D 0097 FF94 0000 2084 008A FF03 0000"
+- $"2000 A4FF 8D00 0020 9BFF 8E00 0020 8FFF"
+- $"0400 4000 0020 A6FF 0020 8D00 BBFF 8400"
+- $"A8FF 0040 8E00 B5FF 0040 8300 0120 00AC"
+- $"FF91 00AF FF02 0040 4083 00B0 FF95 00A3"
+- $"FF8A 00B4 FF99 0097 FF8C 0001 4000 B8FF"
+- $"BC00 0220 0000 BDFF BA00 0020 C3FF B000"
+- $"0020 8000 C9FF A400 0120 2083 00D3 FF9F"
+- $"0004 2020 4000 00DC FF92 00FF FFFF FFB3"
+- $"FFFF FFCA FF00 FBFD FF00 FBFC FF03 FBFB"
+- $"0000 F6FF 01FB FB81 FF01 0000 80FF 00FB"
+- $"F4FF 0000 80FF 0100 00F7 FF01 0000 80FF"
+- $"0100 00F5 FF02 FB00 0081 FF01 0000 F5FF"
+- $"8000 80FF 8000 F4FF 8000 81FF 8000 F2FF"
+- $"8100 81FF 8000 F1FF 0040 8000 82FF 8100"
+- $"D6FF 00FB 93FF 8200 0220 20FB 82FF 8100"
+- $"D9FF 8D00 0240 2020 8200 0220 FFFB 82FF"
+- $"8100 D3FF 9B00 01FB FB83 FF82 00CD FF9C"
+- $"0001 4000 87FF 8200 CAFF 9F00 89FF 8200"
+- $"C7FF 9E00 0120 008A FF83 00C5 FF9E 008E"
+- $"FF83 00C0 FF02 FBFB FF98 0000 4080 0001"
+- $"FBFB 8FFF 8400 C0FF 00FB 9C00 03FF FFFB"
+- $"FB8F FF84 00C0 FF97 0003 6000 FBFB 94FF"
+- $"8500 BFFF 9300 0440 4000 FBFB 97FF 8800"
+- $"BCFF 9400 0440 FFFF FBFB 95FF 8900 0120"
+- $"00BA FF93 009B FF8C 0000 20B8 FF93 009A"
+- $"FF90 00B6 FF92 009B FF90 0001 2020 B4FF"
+- $"9200 99FF 01FB 4094 00B3 FF91 009A FF97"
+- $"00B1 FF92 008D FF00 FB88 FF00 4097 00B1"
+- $"FF91 008E FF02 FBFF 6085 FF01 4040 9800"
+- $"AFFF 9100 0020 8EFF 026E 6060 85FF 9A00"
+- $"ADFF 01FB FF91 0088 FF00 6083 FF80 6085"
+- $"FF9B 0000 FBAB FF01 FBFF 9100 87FF 0160"
+- $"6083 FF80 6085 FF9B 0000 FBAC FF92 0086"
+- $"FF80 6083 FF02 606E 6084 FF01 FBFF 9A00"
+- $"ADFF 9100 87FF 8060 83FF 8060 86FF 9B00"
+- $"ACFF 9100 87FF 8060 01FB FB81 FF80 6085"
+- $"FF02 FBFB 4099 00AC FF91 0087 FF80 6084"
+- $"FF80 6084 FF02 FBFB FF99 00AC FF91 0086"
+- $"FF00 FB81 6082 FF03 FBFF 6060 88FF 9800"
+- $"ACFF 9100 88FF 8060 90FF 01FB FF97 00AC"
+- $"FF92 0088 FF80 608F FF02 FBFF FF96 00AC"
+- $"FF92 0088 FF03 FBFF FFFB 92FF 9200 0140"
+- $"00AC FF01 FBFB 9100 A2FF 9300 ACFF 01FB"
+- $"FB92 00A2 FF91 00AF FF00 4091 00A3 FF90"
+- $"0000 FBAF FF92 0001 FBFB 8CFF 80FB 8FFF"
+- $"8D00 0060 B1FF 0140 4090 0002 40FF FB91"
+- $"FF00 FB8C FF8B 0001 2000 B2FF 9100 0240"
+- $"40FB 8BFF 8260 01FF FB8C FF8B 0001 20FB"
+- $"B1FF 01FB FF93 0001 FBFB 89FF 01FB FF82"
+- $"6001 FBFB 8BFF 8A00 B5FF 9300 0040 8CFF"
+- $"8360 8CFF 8900 B7FF 9200 0140 408B FF00"
+- $"FB82 608C FF88 00B9 FF94 008B FF83 608B"
+- $"FF87 00BB FF94 008B FF82 608B FF86 00BD"
+- $"FF00 2093 008A FF81 608C FF85 00BE FF00"
+- $"FB94 008A FF01 6060 8CFF 0040 8300 0020"
+- $"C2FF 9300 99FF 8400 C6FF 9200 94FF 02FB"
+- $"FBFF 8300 CAFF 9000 94FF 01FB FB83 00CD"
+- $"FF8F 0093 FF06 0020 0020 0000 FBCD FF01"
+- $"2020 8E00 90FF 8040 8000 CFFF 0300 0020"
+- $"208D 008F FF01 0000 8040 CFFF 0040 9100"
+- $"80FF 00FB 8AFF 01FB FF80 0001 FFFB CAFF"
+- $"02FB FFFF 9300 E1FF 02FB FBFF 8E00 0040"
+- $"8100 01FF FBE2 FF01 FBFB 9100 81FF 00FB"
+- $"E2FF 0120 208E 0000 FBE8 FF8F 00EA FF8F"
+- $"00EA FF90 00E8 FF00 FB92 0001 FBFB E5FF"
+- $"00FB 9400 E5FF 9800 00FB DFFF 01FB FB9C"
+- $"00DD FFA8 008F FF01 FBFB BEFF A500 0420"
+- $"0000 4040 8900 C4FF BC00 0020 BDFF C300"
+- $"B7FF C400 0140 40B4 FFC8 0000 20B2 FF00"
+- $"20CA 00AF FF00 20CB 0000 40AE FFCD 0000"
+- $"20AB FF01 FB20 CF00 ABFF D100 ABFF D000"
+- $"ABFF D000 ABFF D000 A8FF 00FB 80FF CF00"
+- $"AFFF CB00 0220 FBFB AEFF CA00 ABFF 00FB"
+- $"85FF C700 B9FF C200 00FB C1FF B800 D4FF"
+- $"01FB FBA5 00D3 FF01 FBFB 86FF 9C00 A3FF"
+- $"00FB BAFF 0200 0020 9600 A2FF 0020 8900"
+- $"0440 40FF FBFB AEFF 9500 9FFF 0300 0020"
+- $"2089 0004 40FF FFFB FBB0 FF93 009C FF00"
+- $"FB8D 0000 60B7 FF92 009A FF02 FBFB 408C"
+- $"00B9 FF91 009C FF8D 009C FF01 FBFB 9AFF"
+- $"9000 9CFF 8C00 92FF 0200 2020 8200 80FF"
+- $"01FB FB9A FF8F 009C FF8B 0002 20FF FB90"
+- $"FF04 0000 2020 0084 FF01 FBFB 9AFF 8F00"
+- $"00FB 9BFF 8B00 0060 91FF 8100 A1FF 00FB"
+- $"80FF 8E00 80FF 00FB 99FF 8B00 92FF 8100"
+- $"A4FF 8E00 81FF 00FB 99FF 8B00 91FF 8100"
+- $"0060 A3FF 8E00 81FF 01FB FB99 FF8B 0092"
+- $"FF82 0080 FF00 FB9C FF8F 00A0 FF8B 0092"
+- $"FF82 0003 40FF FFFB 99FF 0100 408F 0082"
+- $"FF00 009B FF8B 0000 2092 FF84 0088 FF83"
+- $"FB84 FF01 4020 9100 0140 4082 FF01 0000"
+- $"9CFF 8B00 90FF 02FB FBFF AE00 0240 4000"
+- $"81FF 03FB FB00 009D FF8C 0093 FF01 0020"
+- $"AC00 84FF 0120 009F FF8C 0094 FFAA 0085"
+- $"FF01 2020 9EFF 02FB FB20 8C00 02FF FFFB"
+- $"92FF 0100 40A2 0002 FFFF FB84 FF80 00A2"
+- $"FF8D 0096 FF00 FB94 0000 2084 0001 FFFB"
+- $"84FF 00FB 80FF 0300 0020 00A4 FF8D 0000"
+- $"209B FF8E 0000 208F FF04 0040 0000 20A6"
+- $"FF00 208D 009E FF8A FB8D FF84 0000 FBA6"
+- $"FF01 FB40 8E00 AFFF 80FB 80FF 0040 8300"
+- $"0120 00A9 FF02 FBFF FF91 00AB FF80 FB03"
+- $"FF00 4040 8300 B0FF 9500 89FF 01FB FB89"
+- $"FF81 FB85 FF8A 00B4 FF99 0097 FF8C 0001"
+- $"4000 B8FF BC00 0220 0000 BDFF BA00 0020"
+- $"BFFF 00FB 80FF B000 0020 8000 C7FF 01FB"
+- $"FBA4 0001 2020 8300 CCFF 01FB FB82 FF9F"
+- $"0008 2020 4000 00FF FFFB FBD8 FF92 0084"
+- $"FF01 FBFB FFFF FFFF AAFF FFFF CAFF 00F0"
+- $"FDFF 00F0 FCFF 03F0 F000 00F6 FF01 F0F0"
+- $"81FF 0100 0080 FF00 F0F4 FF00 0080 FF01"
+- $"0000 F7FF 0100 0080 FF01 0000 F5FF 02F0"
+- $"0000 81FF 0100 00F5 FF80 0080 FF80 00F4"
+- $"FF80 0081 FF80 00F2 FF81 0081 FF80 00F1"
+- $"FF00 4080 0082 FF81 00D6 FF00 F093 FF82"
+- $"0002 4040 F082 FF81 00D9 FF8D 0080 4082"
+- $"0002 40FF F082 FF81 00D3 FF9B 0001 F0F0"
+- $"83FF 8200 CDFF 9C00 0140 0087 FF82 00CA"
+- $"FF9F 0089 FF82 00C7 FF9E 0001 4000 8AFF"
+- $"8300 C5FF 9E00 8EFF 8300 C0FF 02F0 F0FF"
+- $"9800 0040 8000 01F0 F08F FF84 00C0 FF00"
+- $"F09C 0003 FFFF F0F0 8FFF 8400 C0FF 9700"
+- $"0340 00F0 F094 FF85 00BF FF93 0004 4040"
+- $"00F0 F097 FF88 00BC FF94 0004 40FF FFF0"
+- $"F095 FF89 0001 4000 BAFF 9300 9BFF 8C00"
+- $"0040 B8FF 9300 9AFF 9000 B6FF 9200 9BFF"
+- $"9000 0140 40B4 FF92 0099 FF01 F040 9400"
+- $"B3FF 9100 9AFF 9700 B1FF 9200 8DFF 00F0"
+- $"88FF 0040 9700 B1FF 9100 8EFF 02F0 FF80"
+- $"85FF 0140 4098 00AF FF91 0000 408E FF02"
+- $"A580 8085 FF9A 00AD FF01 F0FF 9100 88FF"
+- $"0080 83FF 8080 85FF 9B00 00F0 ABFF 01F0"
+- $"FF91 0087 FF01 8080 83FF 8080 85FF 9B00"
+- $"00F0 ACFF 9200 86FF 8080 83FF 0280 A580"
+- $"84FF 01F0 FF9A 00AD FF91 0087 FF80 8083"
+- $"FF80 8086 FF9B 00AC FF91 0087 FF80 8001"
+- $"F0F0 81FF 8080 85FF 02F0 F040 9900 ACFF"
+- $"9100 87FF 8080 84FF 8080 84FF 02F0 F0FF"
+- $"9900 ACFF 9100 86FF 00F0 8180 82FF 03F0"
+- $"FF80 8088 FF98 00AC FF91 0088 FF80 8090"
+- $"FF01 F0FF 9700 ACFF 9200 88FF 8080 8FFF"
+- $"02F0 FFFF 9600 ACFF 9200 88FF 03F0 FFFF"
+- $"F092 FF92 0001 4000 ACFF 01F0 F091 00A2"
+- $"FF93 00AC FF01 F0F0 9200 A2FF 9100 AFFF"
+- $"0040 9100 A3FF 9000 00F0 AFFF 9200 01F0"
+- $"F08C FF80 F08F FF8D 0000 80B1 FF01 4040"
+- $"9000 0240 FFF0 91FF 00F0 8CFF 8B00 0140"
+- $"00B2 FF91 0002 4040 F08B FF82 8001 FFF0"
+- $"8CFF 8B00 0140 F0B1 FF01 F0FF 9300 01F0"
+- $"F089 FF01 F0FF 8280 01F0 F08B FF8A 00B5"
+- $"FF93 0000 408C FF83 808C FF89 00B7 FF92"
+- $"0001 4040 8BFF 00F0 8280 8CFF 8800 B9FF"
+- $"9400 8BFF 8380 8BFF 8700 BBFF 9400 8BFF"
+- $"8280 8BFF 8600 BDFF 0040 9300 8AFF 8180"
+- $"8CFF 8500 BEFF 00F0 9400 8AFF 0180 808C"
+- $"FF00 4083 0000 40C2 FF93 0099 FF84 00C6"
+- $"FF92 0094 FF02 F0F0 FF83 00CA FF90 0094"
+- $"FF01 F0F0 8300 CDFF 8F00 93FF 0600 4000"
+- $"4000 00F0 CDFF 0140 408E 0090 FF80 4080"
+- $"00CF FF03 0000 4040 8D00 8FFF 0100 0080"
+- $"40CF FF00 4091 0080 FF00 F08A FF01 F0FF"
+- $"8000 01FF F0CA FF02 F0FF FF93 00E1 FF02"
+- $"F0F0 FF8E 0000 4081 0001 FFF0 E2FF 01F0"
+- $"F091 0081 FF00 F0E2 FF01 4040 8E00 00F0"
+- $"E8FF 8F00 EAFF 8F00 EAFF 9000 E8FF 00F0"
+- $"9200 01F0 F0E5 FF00 F094 00E5 FF98 0000"
+- $"F0DF FF01 F0F0 9C00 DDFF A800 8FFF 01F0"
+- $"F0BE FFA5 0004 4000 0040 4089 00C4 FFBC"
+- $"0000 40BD FFC3 00B7 FFC4 0001 4040 B4FF"
+- $"C800 0040 B2FF 0040 CA00 AFFF 0040 CB00"
+- $"0040 AEFF CD00 0040 ABFF 01F0 40CF 00AB"
+- $"FFD1 00AB FFD0 00AB FFD0 00AB FFD0 00A8"
+- $"FF00 F080 FFCF 00AF FFCB 0002 40F0 F0AE"
+- $"FFCA 00AB FF00 F085 FFC7 00B9 FFC2 0000"
+- $"F0C1 FFB8 00D4 FF01 F0F0 A500 D3FF 01F0"
+- $"F086 FF9C 00A3 FF00 F0BA FF02 0000 4096"
+- $"00A2 FF00 4089 0004 4040 FFF0 F0AE FF95"
+- $"009F FF03 0000 4040 8900 0440 FFFF F0F0"
+- $"B0FF 9300 9CFF 00F0 8D00 0080 B7FF 9200"
+- $"9AFF 02F0 F040 8C00 B9FF 9100 9CFF 8D00"
+- $"9CFF 01F0 F09A FF90 009C FF8C 0092 FF02"
+- $"0040 4082 0080 FF01 F0F0 9AFF 8F00 9CFF"
+- $"8B00 0240 FFF0 90FF 0400 0040 4000 84FF"
+- $"01F0 F09A FF8F 0000 F09B FF8B 0000 4091"
+- $"FF81 00A1 FF00 F080 FF8E 0080 FF00 F099"
+- $"FF8B 0092 FF81 00A4 FF8E 0081 FF00 F099"
+- $"FF8B 0091 FF81 0000 40A3 FF8E 0081 FF01"
+- $"F0F0 99FF 8B00 92FF 8200 80FF 00F0 9CFF"
+- $"8F00 A0FF 8B00 92FF 8200 0340 FFFF F099"
+- $"FF01 0040 8F00 82FF 0000 9BFF 8B00 0040"
+- $"92FF 8400 88FF 83F0 84FF 0140 4091 0001"
+- $"4040 82FF 0100 009C FF8B 0090 FF02 F0F0"
+- $"FFAE 0002 4040 0081 FF03 F0F0 0000 9DFF"
+- $"8C00 93FF 0100 40AC 0084 FF01 4000 9FFF"
+- $"8C00 94FF AA00 85FF 0140 409E FF02 F0F0"
+- $"408C 0002 FFFF F092 FF01 0040 A200 02FF"
+- $"FFF0 84FF 8000 A2FF 8D00 96FF 00F0 9400"
+- $"0040 8400 01FF F084 FF00 F080 FF03 0000"
+- $"4000 A4FF 8D00 0040 9BFF 8E00 0040 8FFF"
+- $"0400 4000 0040 A6FF 0040 8D00 9EFF 8AF0"
+- $"8DFF 8400 00F0 A6FF 01F0 408E 00AF FF80"
+- $"F080 FF00 4083 0001 4000 A9FF 02F0 FFFF"
+- $"9100 ABFF 80F0 03FF 0040 4083 00B0 FF95"
+- $"0089 FF01 F0F0 89FF 81F0 85FF 8A00 B4FF"
+- $"9900 97FF 8C00 0140 00B8 FFBC 0002 4000"
+- $"00BD FFBA 0000 40BF FF00 F080 FFB0 0000"
+- $"4080 00C7 FF01 F0F0 A400 0140 4083 00CC"
+- $"FF01 F0F0 82FF 9F00 8040 0500 00FF FFF0"
+- $"F0D8 FF92 0084 FF01 F0F0 FFFF FFFF AAFF",
+- /* [20] */
+- 't8mk',
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0005"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0500 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0505 FFFF 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0005 0500"
+- $"00FF FFFF FF00 0000 0500 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"FFFF FFFF FFFF 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"FFFF FFFF FFFF FF00 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0005"
+- $"FFFF FFFF FFFF FFFF 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"FFFF FFFF FFFF FFFF FF00 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"FFFF FFFF FFFF FFFF FFFF 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 00FF"
+- $"FFFF FFFF FFFF FFFF FFFF 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 BFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FF00 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0500 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 00FF FFFF FFFF"
+- $"DBFF FFFF FFFF FFFF FFFF FFFF 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF BFDB DBFF FFFF FFFF"
+- $"DBFF FFFF FFFF FFFF FFFF FFFF 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FF00 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 00FF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF BFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FF00 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FF00 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 00FF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FF00 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 00FF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FF00 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0505 00FF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF BFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FF00 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"05FF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FF00 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FF00 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 00FF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FF00"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF DBFF"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 00FF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"DB00 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 00FF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFDB DB00 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FF00 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 00FF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FF00 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 00FF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0500 FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FF05 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0500 FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FF05 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 00FF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FF00 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 00FF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 00FF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 00FF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 00FF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 00FF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 00FF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 00FF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFBF FF00 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0505 FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FF00 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0505 FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 BFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF 0500 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 00FF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF 9B00 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 00BF BFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFDB FF00 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFDB 0500 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0005 00FF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FF00 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 00FF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFBF BFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FF00 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 00FF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FF00"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 00DB"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0005"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFBF FFFF FFFF FFFF DB00 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FF00 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FF00 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFDB FFDB FFFF 0500 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 00DB DBFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF BFBF"
+- $"FFFF FF00 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 00FF FFDB DBFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFBF BFBF"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 BFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FF00 0500"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0500 00FF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0005 0500 FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FF00 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0005 05FF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 00DB DBFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 00FF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 05FF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FF00 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 05FF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FF00 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FF00 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0505 FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FF00 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 00FF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FF00"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 00FF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FF00 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 00FF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FF00 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 00FF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FF00 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 00FF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFBF FFFF FFFF"
+- $"FFFF FFFF FFFF FF00 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 00FF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 DBFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 DBFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FF00 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 00FF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 05DB FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FF00 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FF00"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 00FF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FF00 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0500 0000 FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FF00 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0005 0000"
+- $"0000 0000 0000 FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 00FF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FF00 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FF00 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 00FF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FF00 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0500 0000 0000 0000"
+- $"0000 0000 0000 FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FF00 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 00DB FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF BFBF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FF00 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 FFFF DBDB FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF BFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FF00 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0005 FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FF00 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0005"
+- $"05BF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FF00 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FF00 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FF00 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 00FF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 00FF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 00FF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FF00 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 00FF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FF00 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 00FF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 00FF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 00FF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FF00 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFBF BFFF FFFF FFFF FFFF FFFF"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFDB FF00"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"00FF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFDB 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0005"
+- $"05DB FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FF00 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF DBFF 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 00FF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFBF FFFF DB00 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 DBFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF 0500 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 05BF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFBF"
+- $"FFFF FFFF FFFF DBFF 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0500 00FF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFBF"
+- $"FFFF FFFF FFFF 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 00FF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 00FF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"BFFF 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 00FF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF DBFF FF00"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 00FF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF DB00 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0005"
+- $"0000 00FF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF DBFF FFFF 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0505 FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFDB DBFF"
+- $"FFFF FFFF FF00 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0505 0000 0000 00FF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF FFFF FFFF FFFF FFDB DBBF"
+- $"FFFF 0000 0505 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"00FF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+- $"FFFF FFFF FFFF 0000 0000 0000 0005 0500"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- $"0000 0000 0000 0000 0000 0000 0000 0000"
+- }
+-};
+diff --git a/base/gdevbit.c b/base/gdevbit.c
+--- a/base/gdevbit.c
++++ b/base/gdevbit.c
+@@ -653,7 +653,7 @@ bit_put_params(gx_device * pdev, gs_param_list * plist)
+ pdev->color_info.depth == 32 ? cmyk_8bit_map_cmyk_color :
+ bit_map_cmyk_color);
+ }
+- /* Reset the sparable and linear shift, masks, bits. */
++ /* Reset the separable and linear shift, masks, bits. */
+ set_linear_color_bits_mask_shift(pdev);
+ pdev->color_info.separable_and_linear = GX_CINFO_SEP_LIN;
+ ((gx_device_bit *)pdev)->FirstLine = FirstLine;
+@@ -671,16 +671,18 @@ bit_print_page(gx_device_printer * pdev, FILE * prn_stream)
+ byte *in = gs_alloc_bytes(pdev->memory, line_size, "bit_print_page(in)");
+ byte *data;
+ int nul = !strcmp(pdev->fname, "nul") || !strcmp(pdev->fname, "/dev/null");
+- int lnum = ((gx_device_bit *)pdev)->FirstLine;
+- int bottom = ((gx_device_bit *)pdev)->LastLine;
++ int lnum = ((gx_device_bit *)pdev)->FirstLine >= pdev->height ? pdev->height - 1 :
++ ((gx_device_bit *)pdev)->FirstLine;
++ int bottom = ((gx_device_bit *)pdev)->LastLine >= pdev->height ? pdev->height - 1 :
++ ((gx_device_bit *)pdev)->LastLine;
+ int line_count = any_abs(bottom - lnum);
+ int i, step = lnum > bottom ? -1 : 1;
+
+ if (in == 0)
+ return_error(gs_error_VMerror);
+ if ((lnum == 0) && (bottom == 0))
+- bottom = pdev->height - 1;
+- for (i = 0; i < line_count; i++, lnum += step) {
++ line_count = pdev->height - 1; /* default when LastLine == 0, FirstLine == 0 */
++ for (i = 0; i <= line_count; i++, lnum += step) {
+ gdev_prn_get_bits(pdev, lnum, in, &data);
+ if (!nul)
+ fwrite(data, 1, line_size, prn_stream);
+diff --git a/base/gdevdevn.c b/base/gdevdevn.c
+--- a/base/gdevdevn.c
++++ b/base/gdevdevn.c
+@@ -216,7 +216,7 @@ devn_get_color_comp_index(gx_device * dev, gs_devn_params * pdevn_params,
+ {
+ int num_order = pdevn_params->num_separation_order_names;
+ int color_component_number = 0;
+- int max_spot_colors = GX_DEVICE_MAX_SEPARATIONS;
++ int max_spot_colors = GX_DEVICE_MAX_SEPARATIONS - MAX_DEVICE_PROCESS_COLORS;
+
+ /*
+ * Check if the component is in either the process color model list
+@@ -470,8 +470,9 @@ devn_put_params(gx_device * pdev, gs_param_list * plist,
+ case 0:
+ if (page_spot_colors < -1)
+ return_error(gs_error_rangecheck);
+- if (page_spot_colors > GX_DEVICE_COLOR_MAX_COMPONENTS)
+- page_spot_colors = GX_DEVICE_COLOR_MAX_COMPONENTS;
++ if (page_spot_colors > GX_DEVICE_COLOR_MAX_COMPONENTS - MAX_DEVICE_PROCESS_COLORS)
++ page_spot_colors = GX_DEVICE_COLOR_MAX_COMPONENTS - MAX_DEVICE_PROCESS_COLORS;
++ /* Need to leave room for the process colors in GX_DEVICE_COLOR_MAX_COMPONENTS */
+ }
+ /*
+ * The DeviceN device can have zero components if nothing has been
+diff --git a/base/gdevifno.c b/base/gdevifno.c
+--- a/base/gdevifno.c
++++ b/base/gdevifno.c
+@@ -22,14 +22,12 @@
+
+ #include "gdevprn.h"
+ #include "gsparam.h"
+-#include "gxlum.h"
+-#include <stdlib.h>
+
+ #define nil ((void*)0)
+
+ /*
+- * ERROR
+- * is used to go up the stack and
++ * ERROR
++ * is used to go up the stack and
+ * eventually return_error(gs_error_Fatal) to gs.
+ */
+ #define ERROR (-2)
+@@ -49,11 +47,13 @@ struct Rectangle {
+ };
+ static Point ZP = { 0, 0 };
+
+-static WImage* initwriteimage(FILE *f, Rectangle r, int ldepth);
+-static int writeimageblock(WImage *w, uchar *data, int ndata);
++static WImage* initwriteimage(FILE *f, Rectangle r, int ldepth, gs_memory_t *mem);
++static int writeimageblock(WImage *w, uchar *data, int ndata, gs_memory_t *mem);
+ static int bytesperline(Rectangle, int);
+ static int rgb2cmap(int, int, int);
+-static long cmap2rgb(int);
++/* static long cmap2rgb(int); */ /* not currently used */
++
++void init_p9color(ulong *p9color);
+
+ #define X_DPI 100
+ #define Y_DPI 100
+@@ -72,8 +72,16 @@ typedef struct inferno_device_s {
+ int color, gray;
+ int cmapcall;
+ int nbits;
++ ulong *p9color; /* index blue most sig, red least sig */
+ } inferno_device;
+
++/* structure descriptor for the garbage collector */
++/* we must use the final version because gx_device_common requires
++ a finalisation call, but such procedures aren't inherited. */
++gs_private_st_suffix_add1_final(st_inferno_device, inferno_device,
++ "inferno_device", inferno_device_enum_ptrs, inferno_device_reloc_ptrs,
++ gx_device_finalize, st_device_printer, p9color);
++
+ static const gx_device_procs inferno_procs =
+ prn_color_params_procs(inferno_open, gdev_prn_output_page, inferno_close,
+ inferno_rgb2cmap, inferno_cmap2rgb,
+@@ -81,7 +89,8 @@ static const gx_device_procs inferno_procs =
+
+
+ inferno_device far_data gs_inferno_device =
+-{ prn_device_body(inferno_device, inferno_procs, "inferno",
++{ prn_device_stype_body(inferno_device, inferno_procs, "inferno",
++ &st_inferno_device,
+ DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
+ X_DPI, Y_DPI,
+ 0,0,0,0, /* margins */
+@@ -98,7 +107,7 @@ inferno_device far_data gs_inferno_device =
+ * ghostscript asks us how to convert between
+ * rgb and color map entries
+ */
+-static gx_color_index
++static gx_color_index
+ inferno_rgb2cmap(gx_device *dev, const gx_color_value cv[]) {
+ int shift;
+ inferno_device *bdev = (inferno_device*) dev;
+@@ -128,7 +137,7 @@ inferno_rgb2cmap(gx_device *dev, const gx_color_value cv[]) {
+ /*
+ * we keep track of what ldepth bitmap this is by watching
+ * what colors gs asks for.
+- *
++ *
+ * one catch: sometimes print_page gets called more than one
+ * per page (for multiple copies) without cmap calls inbetween.
+ * if bdev->cmapcall is 0 when print_page gets called, it uses
+@@ -149,7 +158,7 @@ inferno_rgb2cmap(gx_device *dev, const gx_color_value cv[]) {
+ return ((((blue<<4)|green)<<4)|red);
+ }
+
+-static int
++static int
+ inferno_cmap2rgb(gx_device *dev, gx_color_index color,
+ gx_color_value rgb[3]) {
+ int shift, i;
+@@ -186,13 +195,12 @@ inferno_cmap2rgb(gx_device *dev, gx_color_index color,
+ #define Glevs 16
+ #define Blevs 16
+ #define Mlevs 16
+-#define Rfactor 1 /* multiple of red level in p9color[] index */
++#define Rfactor 1 /* multiple of red level in e cp9color[] index */
+ #define Gfactor Rlevs
+ #define Bfactor (Rlevs*Glevs)
+-
+-ulong p9color[Rlevs*Glevs*Blevs]; /* index blue most sig, red least sig */
++#define p9color_size (sizeof(ulong)*Rlevs*Glevs*Blevs)
+
+-void init_p9color(void) /* init at run time since p9color[] is so big */
++void init_p9color(ulong *p9color) /* init at run time since p9color[] is so big */
+ {
+ int r, g, b, o;
+ ulong* cur = p9color;
+@@ -232,18 +240,25 @@ inferno_open(gx_device *dev)
+ bdev->ldepth = 3;
+ bdev->nbits = 4; /* 4 bits per color per pixel (12 bpp, then we dither) */
+ /* if you change this, change the entry in gs_inferno_device */
+- init_p9color();
++ bdev->p9color = (ulong *)gs_alloc_bytes(bdev->memory, p9color_size, "plan 9 colour cube");
++ if (bdev->p9color == NULL)
++ return_error(gs_error_VMerror);
++ init_p9color(bdev->p9color);
+ return gdev_prn_open(dev);
+ }
+
+-/*
++/*
+ * inferno_close() is called at the end, once everything
+ * is finished. we have nothing to do.
+ */
+ static int
+ inferno_close(gx_device *dev)
+ {
++ inferno_device *bdev = (inferno_device*) dev;
+ int code;
++
++ gs_free_object(dev->memory, bdev->p9color, "plan 9 colour cube");
++
+ code = gdev_prn_close(dev);
+ if(code < 0)
+ return_error(code);
+@@ -258,7 +273,7 @@ inferno_close(gx_device *dev)
+ static int
+ inferno_print_page(gx_device_printer *pdev, FILE *f)
+ {
+- uchar buf[16384]; /* == 8192 dots across */
++ uchar *buf;
+ uchar *p;
+ WImage *w;
+ int bpl, y;
+@@ -274,7 +289,7 @@ inferno_print_page(gx_device_printer *pdev, FILE *f)
+ Rectangle r;
+
+ gsbpl = gdev_prn_raster(pdev);
+- if(gsbpl > sizeof(buf)) {
++ if(gsbpl > 16384) { /* == 8192 dots across */
+ errprintf("bitmap far too wide for inferno\n");
+ return_error(gs_error_Fatal);
+ }
+@@ -290,12 +305,18 @@ inferno_print_page(gx_device_printer *pdev, FILE *f)
+ r.max.x = pdev->width;
+ r.max.y = pdev->height;
+ bpl = bytesperline(r, ldepth);
+- w = initwriteimage(f, r, ldepth);
++ w = initwriteimage(f, r, ldepth, bdev->memory);
+ if(w == nil) {
+ errprintf("initwriteimage failed\n");
+ return_error(gs_error_Fatal);
+ }
+
++ buf = gs_alloc_bytes(bdev->memory, gsbpl, "inferno line buffer");
++ if(buf == NULL) {
++ errprintf("couldn't allocate line buffer\n");
++ return_error(gs_error_VMerror);
++ }
++
+ /*
+ * i wonder if it is faster to put the switch around the for loops
+ * to save all the ldepth lookups.
+@@ -314,10 +335,10 @@ inferno_print_page(gx_device_printer *pdev, FILE *f)
+ r<<=4;
+ g<<=4;
+ b<<=4;
+- p[x] = rgb2cmap(r,g,b);
++ p[x] = rgb2cmap(r,g,b);
+ }
+ if(1){
+- u = p9color[us];
++ u = bdev->p9color[us];
+ /* the ulong in p9color is a 2x2 matrix. pull the entry
+ * u[x%2][y%2], more or less.
+ */
+@@ -345,19 +366,25 @@ inferno_print_page(gx_device_printer *pdev, FILE *f)
+ xmod = pdev->width % ppb[ldepth];
+ if(xmod)
+ p[(x-1)/ppb[ldepth]] <<= ((ppb[ldepth]-xmod)*bpp[ldepth]);
+- if(writeimageblock(w, p, bpl) == ERROR)
++ if(writeimageblock(w, p, bpl, bdev->memory) == ERROR) {
++ gs_free_object(bdev->memory, buf, "inferno line buffer");
++ /* w leaks here */
+ return_error(gs_error_Fatal);
++ }
+ }
+- if(writeimageblock(w, nil, 0) == ERROR)
++ gs_free_object(bdev->memory, buf, "inferno line buffer");
++ if(writeimageblock(w, nil, 0, bdev->memory) == ERROR) {
+ return_error(gs_error_Fatal);
++ }
+
+ return 0;
+ }
+
+ /*
+ * this is a modified version of the image compressor
+- * from fb/bit2enc. it is modified only in that it
++ * from fb/bit2enc. it is modified only in that it
+ * now compiles as part of gs.
++ * some updates have been made to use dynamic memory.
+ */
+
+ /*
+@@ -402,7 +429,7 @@ struct WImage {
+ /*
+ * ibase is the pointer to where the beginning of
+ * the input "is" in memory. whenever we "slide" the
+- * buffer N bytes, what we are actually doing is
++ * buffer N bytes, what we are actually doing is
+ * decrementing ibase by N.
+ * the ulongs in the Hlist structures are just
+ * pointers relative to ibase.
+@@ -537,7 +564,7 @@ gobbleline(WImage *w)
+ /* hash table lookup */
+ for(hp=w->hash[w->h].next;hp;hp=hp->next){
+ /*
+- * the next block is an optimization of
++ * the next block is an optimization of
+ * for(s=p, t=w->ibase+hp->p; s<es && *s == *t; s++, t++)
+ * ;
+ */
+@@ -563,7 +590,7 @@ gobbleline(WImage *w)
+ }
+
+ /*
+- * if we didn't find a long enough run, append to
++ * if we didn't find a long enough run, append to
+ * the raw dump buffer
+ */
+ if(runlen<NMATCH){
+@@ -636,7 +663,7 @@ shiftwindow(WImage *w, uchar *data, uchar *edata)
+ }
+
+ static WImage*
+-initwriteimage(FILE *f, Rectangle r, int ldepth)
++initwriteimage(FILE *f, Rectangle r, int ldepth, gs_memory_t *mem)
+ {
+ WImage *w;
+ int n, bpl;
+@@ -648,7 +675,7 @@ initwriteimage(FILE *f, Rectangle r, int ldepth)
+ }
+
+ n = NMEM+NMATCH+NRUN+bpl*2;
+- w = malloc(n+sizeof(*w));
++ w = (WImage*)gs_alloc_bytes(mem, n+sizeof(*w), "inferno image");
+ if(w == nil)
+ return nil;
+ w->inbuf = (uchar*) &w[1];
+@@ -673,7 +700,7 @@ initwriteimage(FILE *f, Rectangle r, int ldepth)
+ }
+
+ static int
+-writeimageblock(WImage *w, uchar *data, int ndata)
++writeimageblock(WImage *w, uchar *data, int ndata, gs_memory_t *mem)
+ {
+ uchar *edata;
+
+@@ -685,7 +712,7 @@ writeimageblock(WImage *w, uchar *data, int ndata)
+ if(w->r.min.y != w->origr.max.y) {
+ errprintf("not enough data supplied to writeimage\n");
+ }
+- free(w);
++ gs_free_object(mem, w, "inferno image");
+ return 0;
+ }
+
+@@ -704,7 +731,7 @@ writeimageblock(WImage *w, uchar *data, int ndata)
+ }
+
+ /*
+- * functions from the Plan9/Brazil drawing libraries
++ * functions from the Plan9/Brazil drawing libraries
+ */
+ static int
+ bytesperline(Rectangle r, int ld)
+diff --git a/base/gdevm24.c b/base/gdevm24.c
+--- a/base/gdevm24.c
++++ b/base/gdevm24.c
+@@ -24,11 +24,10 @@
+ /*
+ * Define whether to use the library's memset.
+ */
+-/*#define USE_MEMSET*/
++#define USE_MEMSET
++
+ /*
+- * Define whether to use memcpy for very wide fills. We thought this
+- * made a big difference, but it turned out to be an artifact of the
+- * profiler.
++ * Define whether to use memcpy for very wide fills.
+ */
+ /*#define USE_MEMCPY*/
+
+diff --git a/base/gdevmem.c b/base/gdevmem.c
+--- a/base/gdevmem.c
++++ b/base/gdevmem.c
+@@ -168,9 +168,11 @@ gs_make_mem_device(gx_device_memory * dev, const gx_device_memory * mdproto,
+ dev->cached_colors = target->cached_colors;
+ }
+ if (dev->color_info.depth == 1) {
+- gdev_mem_mono_set_inverted(dev,
+- (target == 0 ||
+- dev->color_info.polarity == GX_CINFO_POLARITY_SUBTRACTIVE));
++ gx_color_value cv[3];
++
++ cv[0] = cv[1] = cv[2] = 0;
++ gdev_mem_mono_set_inverted(dev, (target == 0 ||
++ (*dev_proc(dev, map_rgb_color))((gx_device *)dev, cv) != 0));
+ }
+ check_device_separable((gx_device *)dev);
+ gx_device_fill_in_procs((gx_device *)dev);
+diff --git a/base/gdevp14.c b/base/gdevp14.c
+--- a/base/gdevp14.c
++++ b/base/gdevp14.c
+@@ -43,6 +43,8 @@
+ #include "gxclpath.h"
+ #include "gxdcconv.h"
+ #include "vdtrace.h"
++#include "gscolorbuffer.h"
++#include "gsptype2.h"
+
+ /* Visual trace options : set one to 1. */
+ #define VD_PAINT_MASK 0
+@@ -50,7 +52,8 @@
+ #define VD_PAINT_ALPHA 1
+
+ #if RAW_DUMP
+-unsigned char global_index = 0;
++unsigned int global_index = 0;
++unsigned int clist_band_count = 0;
+ #endif
+
+ /*
+@@ -82,6 +85,9 @@ gs_private_st_ptrs2(st_pdf14_ctx, pdf14_ctx, "pdf14_ctx",
+ pdf14_ctx_enum_ptrs, pdf14_ctx_reloc_ptrs,
+ stack, maskbuf);
+
++gs_private_st_ptrs1(st_pdf14_clr, pdf14_parent_color_t, "pdf14_clr",
++ pdf14_clr_enum_ptrs, pdf14_clr_reloc_ptrs,
++ previous);
+
+ /* ------ The device descriptors ------ */
+
+@@ -120,6 +126,8 @@ static int pdf14_clist_get_param_compressed_color_list(pdf14_device * p14dev);
+
+ static const gx_color_map_procs *
+ pdf14_get_cmap_procs(const gs_imager_state *, const gx_device *);
++static const gx_color_map_procs *
++ pdf14_get_cmap_procs_group(const gs_imager_state *, const gx_device *);
+
+ #define XSIZE (int)(8.5 * X_DPI) /* 8.5 x 11 inch page, by default */
+ #define YSIZE (int)(11 * Y_DPI)
+@@ -228,6 +236,27 @@ static int pdf14_cmykspot_put_image(gx_device * dev, gs_imager_state * pis,
+ static int pdf14_custom_put_image(gx_device * dev, gs_imager_state * pis,
+ gx_device * target);
+
++/* Used to alter device color mapping procs based upon group or softmask color space */
++static int pdf14_update_device_color_procs(gx_device *dev,
++ gs_transparency_color_t group_color,
++ gs_imager_state *pis);
++
++
++/* Used to alter device color mapping procs based upon group or softmask color space */
++/* Uses color procs stack so that it can be used with clist writer */
++static int
++pdf14_update_device_color_procs_push_c(gx_device *dev,
++ gs_transparency_color_t group_color,
++ gs_imager_state *pis);
++
++static int
++pdf14_update_device_color_procs_pop_c(gx_device *dev,
++ gs_imager_state *pis);
++
++
++static void pdf14_push_parent_color(gx_device *dev, const gs_imager_state *pis);
++static void pdf14_pop_parent_color(gx_device *dev, const gs_imager_state *pis);
++
+ static const pdf14_procs_t gray_pdf14_procs = {
+ pdf14_unpack_additive,
+ pdf14_put_image
+@@ -274,9 +303,10 @@ static const pdf14_nonseparable_blending_procs_t custom_blending_procs = {
+ };
+
+ const pdf14_device gs_pdf14_Gray_device = {
+- std_device_color_stype_body(pdf14_device, &pdf14_Gray_procs, "pdf14gray",
++ std_device_std_color_full_body_type(pdf14_device, &pdf14_Gray_procs, "pdf14gray",
+ &st_pdf14_device,
+- XSIZE, YSIZE, X_DPI, Y_DPI, 8, 255, 256),
++ XSIZE, YSIZE, X_DPI, Y_DPI, 8,
++ 0, 0, 0, 0, 0, 0),
+ { 0 }, /* Procs */
+ NULL, /* target */
+ { 0 }, /* devn_params - not used */
+@@ -365,7 +395,7 @@ const pdf14_device gs_pdf14_custom_device = {
+ static
+ ENUM_PTRS_WITH(pdf14_device_enum_ptrs, pdf14_device *pdev)
+ {
+- index -= 3;
++ index -= 4;
+ if (index < pdev->devn_params.separations.num_separations)
+ ENUM_RETURN(pdev->devn_params.separations.names[index].data);
+ index -= pdev->devn_params.separations.num_separations;
+@@ -374,10 +404,13 @@ ENUM_PTRS_WITH(pdf14_device_enum_ptrs, pdf14_device *pdev)
+ return 0;
+ }
+ case 0: return ENUM_OBJ(pdev->ctx);
+-case 1: ENUM_RETURN(gx_device_enum_ptr(pdev->target));
+-case 2: ENUM_RETURN(pdev->devn_params.compressed_color_list);
++case 1: return ENUM_OBJ(pdev->trans_group_parent_cmap_procs);
++case 2: ENUM_RETURN(gx_device_enum_ptr(pdev->target));
++case 3: ENUM_RETURN(pdev->devn_params.compressed_color_list);
+ ENUM_PTRS_END
+
++
++
+ static RELOC_PTRS_WITH(pdf14_device_reloc_ptrs, pdf14_device *pdev)
+ {
+ {
+@@ -389,6 +422,7 @@ static RELOC_PTRS_WITH(pdf14_device_reloc_ptrs, pdf14_device *pdev)
+ }
+ RELOC_PTR(pdf14_device, devn_params.compressed_color_list);
+ RELOC_VAR(pdev->ctx);
++ RELOC_VAR(pdev->trans_group_parent_cmap_procs);
+ pdev->target = gx_device_reloc_ptr(pdev->target, gcst);
+ }
+ RELOC_PTRS_END
+@@ -406,6 +440,12 @@ pdf14_buf_new(gs_int_rect *rect, bool has_alpha_g, bool has_shape, bool idle,
+ int n_chan,
+ gs_memory_t *memory)
+ {
++
++ /* Note that alpha_g is the alpha for the GROUP */
++ /* This is distinct from the alpha that may also exist */
++ /* for the objects within the group. Hence it can introduce */
++ /* yet another plane */
++
+ pdf14_buf *result;
+ int rowstride = (rect->q.x - rect->p.x + 3) & -4;
+ int height = (rect->q.y - rect->p.y);
+@@ -421,6 +461,7 @@ pdf14_buf_new(gs_int_rect *rect, bool has_alpha_g, bool has_shape, bool idle,
+ if (result == NULL)
+ return result;
+
++ result->saved = NULL;
+ result->isolated = false;
+ result->knockout = false;
+ result->has_alpha_g = has_alpha_g;
+@@ -433,6 +474,9 @@ pdf14_buf_new(gs_int_rect *rect, bool has_alpha_g, bool has_shape, bool idle,
+ result->maskbuf = NULL;
+ result->idle = idle;
+ result->mask_id = 0;
++ result->parent_color_info_procs.get_cmap_procs = NULL;
++ result->parent_color_info_procs.parent_color_mapping_procs = NULL;
++ result->parent_color_info_procs.parent_color_comp_index = NULL;
+
+ if (height <= 0 || idle) {
+ /* Empty clipping - will skip all drawings. */
+@@ -479,7 +523,8 @@ pdf14_ctx_new(gs_int_rect *rect, int n_chan, bool additive, gs_memory_t *memory)
+ if (result == NULL)
+ return result;
+
+- buf = pdf14_buf_new(rect, false, false, false, n_chan, memory);
++ /* Note: buffer creation expects alpha to be in number of channels */
++ buf = pdf14_buf_new(rect, false, false, false, n_chan+1, memory);
+ if (buf == NULL) {
+ gs_free_object(memory, result, "pdf14_ctx_new");
+ return NULL;
+@@ -541,7 +586,7 @@ pdf14_push_transparency_group(pdf14_ctx *ctx, gs_int_rect *rect,
+ bool isolated, bool knockout,
+ byte alpha, byte shape,
+ gs_blend_mode_t blend_mode, bool idle,
+- uint mask_id)
++ uint mask_id, int numcomps)
+ {
+ pdf14_buf *tos = ctx->stack;
+ pdf14_buf *buf, *backdrop;
+@@ -559,8 +604,18 @@ pdf14_push_transparency_group(pdf14_ctx *ctx, gs_int_rect *rect,
+
+ has_shape = tos->has_shape || tos->knockout;
+
+- buf = pdf14_buf_new(rect, !isolated, has_shape, idle, ctx->n_chan, ctx->memory);
+- if_debug3('v', "[v]push buf: %d x %d, %d channels\n", buf->rect.p.x, buf->rect.p.y, buf->n_chan);
++ /* We need to create this based upon the size of
++ the color space + an alpha channel. NOT the device size
++ or the previous ctx size. */
++
++ /* The second parameter in pdf14_buf_new decides if we should
++ add a GROUP alpha channel to the buffer. If it is NOT isolated, then this
++ buffer will be added. If it is isolated, then the buffer will not be added.
++ I question the redundancy here of the alpha and the group alpha channel, but
++ that will need to be looked at later. */
++
++ buf = pdf14_buf_new(rect, !isolated, has_shape, idle, numcomps+1, ctx->memory);
++ if_debug3('v', "[v]push buf: %d x %d, %d channels\n", buf->rect.q.x - buf->rect.p.x, buf->rect.q.y - buf->rect.p.y, buf->n_chan);
+ if (buf == NULL)
+ return_error(gs_error_VMerror);
+ buf->isolated = isolated;
+@@ -589,17 +644,36 @@ pdf14_push_transparency_group(pdf14_ctx *ctx, gs_int_rect *rect,
+ (buf->has_shape ? 1 : 0)));
+ else
+ pdf14_preserve_backdrop(buf, tos, has_shape);
++
++
++#if RAW_DUMP
++
++ /* Dump the current buffer to see what we have. */
++
++ dump_raw_buffer(ctx->stack->rect.q.y-ctx->stack->rect.p.y,
++ ctx->stack->rowstride, ctx->stack->n_planes,
++ ctx->stack->planestride, ctx->stack->rowstride,
++ "TransGroupPush",ctx->stack->data);
++
++ global_index++;
++
++
++#endif
++
+ return 0;
++
+ }
+
+ static int
+ pdf14_pop_transparency_group(pdf14_ctx *ctx,
+- const pdf14_nonseparable_blending_procs_t * pblend_procs)
++ const pdf14_nonseparable_blending_procs_t * pblend_procs, int curr_num_color_comp)
+ {
+ pdf14_buf *tos = ctx->stack;
+ pdf14_buf *nos = tos->saved;
+ pdf14_buf *maskbuf = tos->maskbuf;
+ int x0, x1, y0, y1;
++ byte *new_data_buf;
++ int num_noncolor_planes, new_num_planes;
+
+ if (nos == NULL)
+ return_error(gs_error_rangecheck);
+@@ -637,9 +711,94 @@ pdf14_pop_transparency_group(pdf14_ctx *ctx,
+ x0 = max(x0, maskbuf->rect.p.x);
+ x1 = min(x1, maskbuf->rect.q.x);
+ }
+- if (x0 < x1 && y0 < y1)
+- pdf14_compose_group(tos, nos, maskbuf, x0, x1, y0, y1,
+- ctx->n_chan, ctx->additive, pblend_procs);
++
++
++#if RAW_DUMP
++
++ /* Dump the current buffer to see what we have. */
++
++ dump_raw_buffer(ctx->stack->rect.q.y-ctx->stack->rect.p.y,
++ ctx->stack->rowstride, ctx->stack->n_planes,
++ ctx->stack->planestride, ctx->stack->rowstride,
++ "Trans_Group_Pop",ctx->stack->data);
++
++
++#endif
++
++
++ /* If the color spaces are different and we actually did do a swap of the procs for color */
++ if(nos->parent_color_info_procs.num_components != curr_num_color_comp && nos->parent_color_info_procs.parent_color_mapping_procs != NULL){
++
++ if (x0 < x1 && y0 < y1) {
++
++ /* The NOS blending color space is different than that of the
++ TOS. It is necessary to transform the TOS buffer data to the
++ color space of the NOS prior to doing the pdf14_compose_group
++ operation. For now we are going to do very generic transformations.
++ This will be replaced when we bring in the updated color flow. */
++
++ /* Allocate the new buffer. If the number of channels in the the new
++ color space was less than or equal to the previous one, we could
++ reuse. Save that for a later optimization. */
++
++ num_noncolor_planes = tos->n_planes - curr_num_color_comp;
++ new_num_planes = num_noncolor_planes + nos->parent_color_info_procs.num_components;
++ new_data_buf = gs_alloc_bytes(ctx->memory, tos->planestride*new_num_planes,
++ "pdf14_buf_new");
++ if (new_data_buf == NULL)
++ return_error(gs_error_VMerror);
++
++ /* Initialize with 0. Need to double check about this...
++ may need to do some adjustments for the shape etc plane */
++ /* i.e. copy over those planes that exist beyond the count
++ of the number of color components */
++
++ memset(new_data_buf, 0, tos->planestride*new_num_planes);
++
++ /* Go ahead and do the conversion on the buffer */
++
++ /* later this will be replaced by gscms_transform_color_buffer */
++ /* This simple function is for planar data only. */
++
++ gs_transform_color_buffer_generic(tos->data,tos->rowstride,tos->planestride,
++ curr_num_color_comp,tos->rect,new_data_buf,nos->parent_color_info_procs.num_components,num_noncolor_planes);
++
++ /* Free the old object */
++
++ gs_free_object(ctx->memory, tos->data, "pdf14_buf_free");
++ tos->data = new_data_buf;
++
++ /* Adjust the plane and channel size now */
++
++ tos->n_chan = nos->n_chan;
++ tos->n_planes = nos->n_planes;
++
++#if RAW_DUMP
++
++ /* Dump the current buffer to see what we have. */
++
++ dump_raw_buffer(ctx->stack->rect.q.y-ctx->stack->rect.p.y,
++ ctx->stack->rowstride, ctx->stack->n_planes,
++ ctx->stack->planestride, ctx->stack->rowstride,
++ "Trans_Group_ColorConv",ctx->stack->data);
++
++#endif
++
++ /* compose */
++
++ pdf14_compose_group(tos, nos, maskbuf, x0, x1, y0, y1, nos->n_chan,
++ nos->parent_color_info_procs.isadditive,
++ nos->parent_color_info_procs.parent_blending_procs);
++
++ }
++
++
++ } else {
++
++ if (x0 < x1 && y0 < y1)
++ pdf14_compose_group(tos, nos, maskbuf, x0, x1, y0, y1,nos->n_chan, ctx->additive, pblend_procs);
++
++ }
+
+ exit:
+ ctx->stack = nos;
+@@ -651,6 +810,7 @@ exit:
+ */
+ ctx->maskbuf = (maskbuf != NULL ? maskbuf->maskbuf : NULL);
+ }
++
+ if_debug1('v', "[v]pop buf, idle=%d\n", tos->idle);
+ pdf14_buf_free(tos, ctx->memory);
+ if (maskbuf != NULL) {
+@@ -669,10 +829,13 @@ exit:
+ static int
+ pdf14_push_transparency_mask(pdf14_ctx *ctx, gs_int_rect *rect, byte bg_alpha,
+ byte *transfer_fn, bool idle, bool replacing,
+- uint mask_id)
++ uint mask_id, gs_transparency_mask_subtype_t subtype,
++ bool SMask_is_CIE, int numcomps)
+ {
+- pdf14_buf *buf;
+
++
++ pdf14_buf *buf;
++
+ if_debug2('v', "[v]pdf14_push_transparency_mask, idle=%d, replacing=%d\n", idle, replacing);
+ if (replacing && ctx->maskbuf != NULL) {
+ if (ctx->maskbuf->maskbuf != NULL) {
+@@ -688,7 +851,15 @@ pdf14_push_transparency_mask(pdf14_ctx *ctx, gs_int_rect *rect, byte bg_alpha,
+ pdf14_buf_free(ctx->maskbuf, ctx->memory);
+ ctx->maskbuf = NULL;
+ }
+- buf = pdf14_buf_new(rect, false, false, idle, ctx->n_chan, ctx->memory);
++
++ /* An optimization to consider is that if the SubType is Alpha
++ then we really should only be allocating the alpha band and
++ only draw with that channel. Current architecture makes that
++ a bit tricky. We need to create this based upon the size of
++ the color space + an alpha channel. NOT the device size
++ or the previous ctx size */
++
++ buf = pdf14_buf_new(rect, false, false, idle, numcomps+1, ctx->memory);
+ if (buf == NULL)
+ return_error(gs_error_VMerror);
+
+@@ -708,8 +879,32 @@ pdf14_push_transparency_mask(pdf14_ctx *ctx, gs_int_rect *rect, byte bg_alpha,
+ buf->maskbuf = ctx->maskbuf;
+ }
+
++
++#if RAW_DUMP
++
++ /* Dump the current buffer to see what we have. */
++
++ if (ctx->stack->planestride > 0 ){
++ dump_raw_buffer(ctx->stack->rect.q.y-ctx->stack->rect.p.y,
++ ctx->stack->rowstride, ctx->stack->n_planes,
++ ctx->stack->planestride, ctx->stack->rowstride,
++ "Raw_Buf_PreSmask",ctx->stack->data);
++
++ global_index++;
++ }
++
++
++#endif
++
+ buf->saved = ctx->stack;
+ ctx->stack = buf;
++
++ /* Soft Mask related information so we know how to
++ compute luminosity when we pop the soft mask */
++
++ buf->SMask_is_CIE = SMask_is_CIE;
++ buf->SMask_SubType = subtype;
++
+ if (buf->data != NULL)
+ memset(buf->data, 0, buf->planestride * buf->n_chan);
+ return 0;
+@@ -719,15 +914,78 @@ static int
+ pdf14_pop_transparency_mask(pdf14_ctx *ctx)
+ {
+ pdf14_buf *tos = ctx->stack;
++ byte *new_data_buf;
+
+ if_debug1('v', "[v]pdf14_pop_transparency_mask, idle=%d\n", tos->idle);
+ ctx->stack = tos->saved;
++ tos->saved = NULL; /* To avoid issues with GC */
++
+ if (tos->maskbuf) {
+ /* The maskbuf of the ctx->maskbuf entry is never used, free it now */
++ /* In other words, the Smask will not have an Smask */
+ pdf14_buf_free(tos->maskbuf, ctx->memory);
+ tos->maskbuf = NULL;
+ }
+- ctx->maskbuf = tos;
++
++ if (tos->data == NULL) {
++
++ /* This can occur in clist rendering if the soft mask does
++ not intersect the current band. It would be nice to
++ catch this earlier and just avoid creating the structure
++ to begin with. For now we need to delete the structure
++ that was created. */
++
++ pdf14_buf_free(tos, ctx->memory);
++ ctx->maskbuf = NULL;
++
++ } else {
++
++ /* Lets get this to a monochrome buffer and map it to a luminance only value */
++ /* This will reduce our memory. We won't reuse the existing one, due */
++ /* Due to the fact that on certain systems we may have issues recovering */
++ /* the data after a resize */
++
++ new_data_buf = gs_alloc_bytes(ctx->memory, tos->planestride,
++ "pdf14_buf_new");
++ if (new_data_buf == NULL)
++ return_error(gs_error_VMerror);
++
++ /* Initialize with 0. Need to do this since in Smask_Luminosity_Mapping
++ we won't be filling everything during the remap if it had not been
++ written into by the PDF14 fill rect */
++
++ memset(new_data_buf, 0, tos->planestride);
++
++ Smask_Luminosity_Mapping(tos->rect.q.y - tos->rect.p.y ,tos->rect.q.x - tos->rect.p.x,tos->n_chan,
++ tos->rowstride, tos->planestride, new_data_buf, tos->data, ctx->additive,
++ tos->SMask_is_CIE, tos->SMask_SubType);
++
++ /* Free the old object, NULL test was above */
++
++ gs_free_object(ctx->memory, tos->data, "pdf14_buf_free");
++ tos->data = new_data_buf;
++
++ /* Data is single channel now */
++
++ tos->n_chan = 1;
++ tos->n_planes = 1;
++
++ /* If we were CIE based, clean up the joint cache we created.
++ see comments in gs_begin_transparency_mask */
++
++ /* if ( tos->SMask_is_CIE ){
++
++ gs_free_object(mem, pis->cie_joint_caches,
++ "gx_cie_to_xyz_free(joint caches)");
++
++ } */
++
++ /* Assign as mask buffer */
++
++ ctx->maskbuf = tos;
++
++ }
++
+ return 0;
+ }
+
+@@ -744,7 +1002,7 @@ pdf14_open(gx_device *dev)
+ rect.p.y = 0;
+ rect.q.x = dev->width;
+ rect.q.y = dev->height;
+- pdev->ctx = pdf14_ctx_new(&rect, dev->color_info.num_components + 1,
++ pdev->ctx = pdf14_ctx_new(&rect, dev->color_info.num_components,
+ pdev->color_info.polarity != GX_CINFO_POLARITY_SUBTRACTIVE, dev->memory);
+ if (pdev->ctx == NULL)
+ return_error(gs_error_VMerror);
+@@ -852,6 +1110,21 @@ pdf14_put_image(gx_device * dev, gs_imager_state * pis, gx_device * target)
+ return code;
+ }
+
++#if RAW_DUMP
++
++ /* Dump the current buffer to see what we have. */
++
++ dump_raw_buffer(pdev->ctx->stack->rect.q.y-pdev->ctx->stack->rect.p.y,
++ pdev->ctx->stack->rect.q.x-pdev->ctx->stack->rect.p.x,
++ pdev->ctx->stack->n_planes,
++ pdev->ctx->stack->planestride, pdev->ctx->stack->rowstride,
++ "PDF14_PUTIMAGE",pdev->ctx->stack->data);
++
++ global_index++;
++ clist_band_count++;
++
++#endif
++
+ linebuf = gs_alloc_bytes(pdev->memory, width * num_comp, "pdf14_put_image");
+ for (y = 0; y < height; y++) {
+ gx_image_plane_t planes;
+@@ -898,7 +1171,6 @@ pdf14_cmykspot_put_image(gx_device * dev, gs_imager_state * pis, gx_device * tar
+ pdf14_device * pdev = (pdf14_device *)dev;
+ pdf14_buf *buf = pdev->ctx->stack;
+ gs_int_rect rect = buf->rect;
+- int x0 = rect.p.x, y0 = rect.p.y;
+ int x1, y1, width, height;
+ gs_devn_params * pdevn_params = &pdev->devn_params;
+ gs_separations * pseparations = &pdevn_params->separations;
+@@ -930,6 +1202,7 @@ pdf14_cmykspot_put_image(gx_device * dev, gs_imager_state * pis, gx_device * tar
+ "CMYK_SPOT_PUTIMAGE",pdev->ctx->stack->data);
+
+ global_index++;
++ clist_band_count++;
+
+
+ #endif
+@@ -1112,6 +1385,24 @@ pdf14_fill_path(gx_device *dev, const gs_imager_state *pis,
+ const gx_clip_path *pcpath)
+ {
+ gs_imager_state new_is = *pis;
++ int code;
++ gs_pattern2_instance_t *pinst = NULL;
++
++
++ if (pdcolor != NULL && gx_dc_is_pattern2_color(pdcolor)) {
++
++ pinst =
++ (gs_pattern2_instance_t *)pdcolor->ccolor.pattern;
++ pinst->saved->has_transparency = true;
++
++ /* The transparency color space operations are driven
++ by the pdf14 clist writer device. */
++
++ pinst->saved->trans_device = dev;
++
++ }
++
++
+
+ /*
+ * The blend operations are not idempotent. Force non-idempotent
+@@ -1119,7 +1410,20 @@ pdf14_fill_path(gx_device *dev, const gs_imager_state *pis,
+ */
+ new_is.log_op |= lop_pdf14;
+ pdf14_set_marking_params(dev, pis);
+- return gx_default_fill_path(dev, &new_is, ppath, params, pdcolor, pcpath);
++
++ new_is.trans_device = dev;
++ new_is.has_transparency = true;
++
++ code = gx_default_fill_path(dev, &new_is, ppath, params, pdcolor, pcpath);
++
++ new_is.trans_device = NULL;
++ new_is.has_transparency = false;
++
++ if (pinst != NULL){
++ pinst->saved->trans_device = NULL;
++ }
++
++ return code;
+ }
+
+ static int
+@@ -1258,13 +1562,18 @@ static pdf14_default_colorspace_t
+ pdf14_determine_default_blend_cs(gx_device * pdev)
+ {
+ if (pdev->color_info.polarity == GX_CINFO_POLARITY_ADDITIVE)
++
+ /*
+ * Note: We do not allow the SeparationOrder device parameter for
+ * additive devices. Thus we always have 1 colorant for DeviceGray
+- * and 3 colorants for DeviceRGB. We do not currently support
+- * blending in a DeviceGray color space. Thus we oniy use DeviceRGB.
++ * and 3 colorants for DeviceRGB.
+ */
+- return PDF14_DeviceRGB;
++
++ if (pdev->color_info.num_components == 1)
++ return PDF14_DeviceGray;
++ else
++ return PDF14_DeviceRGB;
++
+ else {
+ /*
+ * Check if the device is CMYK only or CMYK plus spot colors.
+@@ -1332,6 +1641,22 @@ get_pdf14_device_proto(gx_device * dev, pdf14_device ** pdevproto,
+ switch (dev_cs) {
+ case PDF14_DeviceGray:
+ *pdevproto = (pdf14_device *)&gs_pdf14_Gray_device;
++
++ /* We want gray to be single channel. Low level
++ initialization of gray device prototype is
++ peculiar in that in dci_std_color_num_components
++ the comment is
++ "A device is monochrome only if it is bi-level"
++
++ Here we want monochrome anytime we have a gray device.
++ To avoid breaking things elsewhere, we will overide
++ the prototype intialization here */
++
++ *ptempdevproto = **pdevproto;
++ ptempdevproto->color_info.max_components = 1;
++ ptempdevproto->color_info.num_components = ptempdevproto->color_info.max_components;
++ *pdevproto = ptempdevproto;
++
+ break;
+ case PDF14_DeviceRGB:
+ *pdevproto = (pdf14_device *)&gs_pdf14_RGB_device;
+@@ -1438,12 +1763,14 @@ gx_update_pdf14_compositor(gx_device * pdev, gs_imager_state * pis,
+ pis->get_cmap_procs = p14dev->save_get_cmap_procs;
+ gx_set_cmap_procs(pis, p14dev->target);
+ /* Send image out raster data to output device */
+- { /* hack: Reset lop_pdf14, which could be set by
+- pdf14_fill_path, pdf14_stroke_path
+- to prevent a failure ingx_image_enum_begin. */
++ {
++ /* Make a copy so we can change the ROP */
+ gs_imager_state new_is = *pis;
+
+- new_is.log_op &= ~lop_pdf14;
++ /* We don't use the imager state log_op since this is for the */
++ /* clist playback. Putting the image (band in the case of the */
++ /* clist) only needs to use the default ROP to copy the data */
++ new_is.log_op = rop3_default;
+ p14dev->pdf14_procs->put_image(pdev, &new_is, p14dev->target);
+ }
+ pdf14_disable_device(pdev);
+@@ -1529,11 +1856,12 @@ pdf14_create_compositor(gx_device * dev, gx_device * * pcdev,
+ if (op_pct->params.retain_any_comps && !op_pct->params.retain_spot_comps)
+ {
+
+- p14dev->drawn_comps = op_pct->params.drawn_comps;
++ p14dev->drawn_comps = op_pct->params.drawn_comps;
+
+ } else {
+
+- p14dev->drawn_comps = (1 << p14dev->color_info.num_components) - 1;
++ /* Draw everything. If this parameter was not set, clist does not fill it in. */
++ p14dev->drawn_comps = ( (gx_color_index) 1 << (p14dev->color_info.num_components)) - (gx_color_index) 1;
+ }
+
+ *pcdev = dev;
+@@ -1698,18 +2026,99 @@ pdf14_begin_transparency_group(gx_device *dev,
+ double alpha = pis->opacity.alpha * pis->shape.alpha;
+ gs_int_rect rect;
+ int code;
++ bool isolated;
++ bool sep_target = (strcmp(pdev->dname, "PDF14cmykspot") == 0);
++ int group_color_numcomps;
++ gs_transparency_color_t group_color;
++
++ /* If the target device supports separations, then
++ we should should NOT create the group. The exception to this
++ rule would be if we just popped a transparency mask */
+
+ code = compute_group_device_int_rect(pdev, &rect, pbbox, pis);
++
+ if (code < 0)
+ return code;
+ if_debug4('v', "[v]pdf14_begin_transparency_group, I = %d, K = %d, alpha = %g, bm = %d\n",
+ ptgp->Isolated, ptgp->Knockout, alpha, pis->blend_mode);
++
++ /* If the group color is unknown, then we must use the previous group color
++ space or the device process color space */
++
++ if (ptgp->group_color == UNKNOWN){
++
++ if (pdev->ctx->stack){
++ /* Use previous group color space */
++ group_color_numcomps = pdev->ctx->stack->n_chan-1; /* Remove alpha */
++ } else {
++ /* Use process color space */
++ group_color_numcomps = pdev->color_info.num_components;
++ }
++
++ switch (group_color_numcomps) {
++ case 1:
++ group_color = GRAY_SCALE;
++ break;
++ case 3:
++ group_color = DEVICE_RGB;
++ break;
++ case 4:
++ group_color = DEVICE_CMYK;
++ break;
++ default:
++
++ /* We can end up here if we are in
++ a deviceN color space and
++ we have a sep output device */
++
++ group_color = DEVICEN;
++
++ break;
++
++ }
++
++ } else {
++
++ group_color_numcomps = ptgp->group_color_numcomps;
++ group_color = ptgp->group_color;
++
++ }
++
++ /* If needed, update the color mapping procs. But only if we dont have a sep device.
++ The exception would be if we are in doing the group for a soft mask */
++
++ if (!sep_target) {
++ code = pdf14_update_device_color_procs(dev,group_color,pis);
++ } else {
++ code = 0;
++ group_color_numcomps = pdev->color_info.num_components;
++ }
++
++ /* Note that our initial device buffer may have had a different color space
++ than the first transparency group. In such a case, we really should force
++ this first group to be isolated, anytime that the parent color space is
++ different than its child group, it should be isolated, per the PDF spec */
++
++ if (code == 1){
++
++ isolated = true;
++ if_debug0('v', "[v]Transparency group color space change\n");
++
++ } else {
++
++ isolated = ptgp->Isolated;
++
++ }
++
++ if (code < 0)
++ return code;
++
+ code = pdf14_push_transparency_group(pdev->ctx, &rect,
+- ptgp->Isolated, ptgp->Knockout,
++ isolated, ptgp->Knockout,
+ (byte)floor (255 * alpha + 0.5),
+ (byte)floor (255 * pis->shape.alpha + 0.5),
+ pis->blend_mode, ptgp->idle,
+- ptgp->mask_id);
++ ptgp->mask_id,group_color_numcomps);
+ return code;
+ }
+
+@@ -1720,6 +2129,7 @@ pdf14_end_transparency_group(gx_device *dev,
+ {
+ pdf14_device *pdev = (pdf14_device *)dev;
+ int code;
++ pdf14_parent_color_t *parent_color;
+
+ if_debug0('v', "[v]pdf14_end_transparency_group\n");
+ vd_get_dc('c');
+@@ -1727,11 +2137,437 @@ pdf14_end_transparency_group(gx_device *dev,
+ vd_set_scale(0.01);
+ vd_set_origin(0, 0);
+ vd_erase(RGB(192, 192, 192));
+- code = pdf14_pop_transparency_group(pdev->ctx, pdev->blend_procs);
++ code = pdf14_pop_transparency_group(pdev->ctx, pdev->blend_procs,pdev->color_info.num_components);
++
++
++ /* May need to reset some color stuff related
++ * to a mismatch between the parents color space
++ * and the group blending space */
++
++ parent_color = &(pdev->ctx->stack->parent_color_info_procs);
++
++ if (!(parent_color->parent_color_mapping_procs == NULL &&
++ parent_color->parent_color_comp_index == NULL)) {
++
++ pis->get_cmap_procs = parent_color->get_cmap_procs;
++ gx_set_cmap_procs(pis, dev);
++
++ pdev->procs.get_color_mapping_procs = parent_color->parent_color_mapping_procs;
++ pdev->procs.get_color_comp_index = parent_color->parent_color_comp_index;
++ pdev->color_info.polarity = parent_color->polarity;
++ pdev->color_info.num_components = parent_color->num_components;
++ pdev->blend_procs = parent_color->parent_blending_procs;
++ pdev->ctx->additive = parent_color->isadditive;
++ pdev->pdf14_procs = parent_color->unpack_procs;
++ pdev->color_info.depth = parent_color->depth;
++
++ parent_color->get_cmap_procs = NULL;
++ parent_color->parent_color_comp_index = NULL;
++ parent_color->parent_color_mapping_procs = NULL;
++ }
++
++
++
++
++
++
++
++
++
+ vd_release_dc;
+ return code;
+ }
+
++
++static int
++pdf14_update_device_color_procs(gx_device *dev,
++ gs_transparency_color_t group_color,
++ gs_imager_state *pis)
++{
++
++ pdf14_device *pdevproto;
++ pdf14_device *pdev = (pdf14_device *)dev;
++ const pdf14_procs_t *new_14procs;
++ pdf14_parent_color_t *parent_color_info = &(pdev->ctx->stack->parent_color_info_procs);
++ gx_color_polarity_t new_polarity;
++ int new_num_comps;
++ bool new_additive;
++ byte new_depth;
++
++ if_debug0('v', "[v]pdf14_update_device_color_procs\n");
++
++
++ /* Update the device procs at this
++ stage. Many of the procs are based upon the color
++ space of the device. We want to remain in
++ the color space defined by the color space of
++ the soft mask or transparency group as opposed to the
++ device color space.
++ Later, when we pop the softmask we will collapse it
++ to a single band and then compose with it
++ to the device color space (or the parent layer
++ space). In the case where we pop an isolated transparency
++ group, we will do the blending in the proper color
++ space and then transform the data when we pop the group.
++ Remember that only isolated groups can have color spaces
++ that are different than their parent. */
++
++ parent_color_info->get_cmap_procs = NULL;
++ parent_color_info->parent_color_mapping_procs = NULL;
++ parent_color_info->parent_color_comp_index = NULL;
++
++ switch (group_color) {
++
++ case GRAY_SCALE:
++
++ new_polarity = GX_CINFO_POLARITY_ADDITIVE;
++ new_num_comps = 1;
++ pdevproto = (pdf14_device *)&gs_pdf14_Gray_device;
++ new_additive = true;
++ new_14procs = &gray_pdf14_procs;
++ new_depth = 8;
++
++
++ break;
++
++ case DEVICE_RGB:
++ case CIE_XYZ:
++
++ new_polarity = GX_CINFO_POLARITY_ADDITIVE;
++ new_num_comps = 3;
++ pdevproto = (pdf14_device *)&gs_pdf14_RGB_device;
++ new_additive = true;
++ new_14procs = &rgb_pdf14_procs;
++ new_depth = 24;
++
++ break;
++
++ case DEVICE_CMYK:
++
++ new_polarity = GX_CINFO_POLARITY_SUBTRACTIVE;
++ new_num_comps = 4;
++ pdevproto = (pdf14_device *)&gs_pdf14_CMYK_device;
++ new_additive = false;
++ new_14procs = &cmyk_pdf14_procs;
++ new_depth = 32;
++
++ break;
++
++ default:
++ return_error(gs_error_rangecheck);
++ break;
++
++ }
++
++ if_debug2('v', "[v]pdf14_update_device_color_procs,num_components_old = %d num_components_new = %d\n",
++ pdev->color_info.num_components,new_num_comps);
++
++ /* Save the old information */
++
++ parent_color_info->get_cmap_procs = pis->get_cmap_procs;
++ parent_color_info->parent_color_mapping_procs =
++ pdev->procs.get_color_mapping_procs;
++ parent_color_info->parent_color_comp_index =
++ pdev->procs.get_color_comp_index;
++ parent_color_info->parent_blending_procs = pdev->blend_procs;
++ parent_color_info->polarity = pdev->color_info.polarity;
++ parent_color_info->num_components = pdev->color_info.num_components;
++ parent_color_info->isadditive = pdev->ctx->additive;
++ parent_color_info->unpack_procs = pdev->pdf14_procs;
++ parent_color_info->depth = pdev->color_info.depth;
++
++ /* Set new information */
++
++ pis->get_cmap_procs = pdf14_get_cmap_procs_group;
++ gx_set_cmap_procs(pis, dev);
++ pdev->procs.get_color_mapping_procs =
++ pdevproto->static_procs->get_color_mapping_procs;
++ pdev->procs.get_color_comp_index =
++ pdevproto->static_procs->get_color_comp_index;
++ pdev->blend_procs = pdevproto->blend_procs;
++ pdev->color_info.polarity = new_polarity;
++ pdev->color_info.num_components = new_num_comps;
++ pdev->ctx->additive = new_additive;
++ pdev->pdf14_procs = new_14procs;
++ pdev->color_info.depth = new_depth;
++
++ return(1); /* Lets us detect that we did do an update */
++
++}
++
++
++/* A new version that works with the color_procs stack
++ for transparency groups */
++
++static int
++pdf14_update_device_color_procs_push_c(gx_device *dev,
++ gs_transparency_color_t group_color,
++ gs_imager_state *pis)
++{
++
++ pdf14_device *pdevproto;
++ pdf14_device *pdev = (pdf14_device *)dev;
++ gx_device_clist_writer * cldev = (gx_device_clist_writer *)pdev->pclist_device;
++ const pdf14_procs_t *new_14procs;
++ bool update_color_info;
++ gx_color_polarity_t new_polarity;
++ int new_num_comps;
++ bool new_additive;
++ byte new_depth;
++
++ if_debug0('v', "[v]pdf14_update_device_color_procs_push_c\n");
++
++ /* Check if we need to alter the device procs at this
++ stage. Many of the procs are based upon the color
++ space of the device. We want to remain in
++ the color space defined by the color space of
++ the soft mask or transparency group as opposed to the
++ device color space.
++ Later, when we pop the softmask we will collapse it
++ to a single band and then compose with it
++ to the device color space (or the parent layer
++ space). In the case where we pop an isolated transparency
++ group, we will do the blending in the proper color
++ space and then transform the data when we pop the group.
++ Remember that only isolated groups can have color spaces
++ that are different than their parent. */
++
++ update_color_info = false;
++
++ switch (group_color) {
++
++ case GRAY_SCALE:
++
++ if (pdev->color_info.num_components != 1){
++
++ update_color_info = true;
++ new_polarity = GX_CINFO_POLARITY_ADDITIVE;
++ new_num_comps = 1;
++ pdevproto = (pdf14_device *)&gs_pdf14_Gray_device;
++ new_additive = true;
++ new_14procs = &gray_pdf14_procs;
++ new_depth = 8;
++
++ }
++
++ break;
++
++ case DEVICE_RGB:
++ case CIE_XYZ:
++
++ if (pdev->color_info.num_components != 3){
++
++ update_color_info = true;
++ new_polarity = GX_CINFO_POLARITY_ADDITIVE;
++ new_num_comps = 3;
++ pdevproto = (pdf14_device *)&gs_pdf14_RGB_device;
++ new_additive = true;
++ new_14procs = &rgb_pdf14_procs;
++ new_depth = 24;
++ }
++
++ break;
++
++ case DEVICE_CMYK:
++
++ if (pdev->color_info.num_components != 4){
++
++ update_color_info = true;
++ new_polarity = GX_CINFO_POLARITY_SUBTRACTIVE;
++ new_num_comps = 4;
++ pdevproto = (pdf14_device *)&gs_pdf14_CMYK_device;
++ new_additive = false;
++ new_14procs = &cmyk_pdf14_procs;
++ new_depth = 32;
++
++ }
++
++ break;
++
++ default:
++ return_error(gs_error_rangecheck);
++ break;
++
++ }
++
++ if (update_color_info){
++
++ if_debug2('v', "[v]pdf14_update_device_color_procs_push_c,num_components_old = %d num_components_new = %d\n",
++ pdev->color_info.num_components,new_num_comps);
++
++ /* Set new information in the device */
++
++ pis->get_cmap_procs = pdf14_get_cmap_procs_group;
++ gx_set_cmap_procs(pis, dev);
++ pdev->procs.get_color_mapping_procs =
++ pdevproto->static_procs->get_color_mapping_procs;
++ pdev->procs.get_color_comp_index =
++ pdevproto->static_procs->get_color_comp_index;
++ pdev->blend_procs = pdevproto->blend_procs;
++ pdev->color_info.polarity = new_polarity;
++ pdev->color_info.num_components = new_num_comps;
++ pdev->pdf14_procs = new_14procs;
++ pdev->color_info.depth = new_depth;
++
++ cldev->clist_color_info.depth = pdev->color_info.depth;
++ cldev->clist_color_info.polarity = pdev->color_info.polarity;
++ cldev->clist_color_info.num_components = pdev->color_info.num_components;
++
++
++
++ if (pdev->ctx)
++ {
++ pdev->ctx->additive = new_additive;
++ }
++
++ return(1); /* Lets us detect that we did do an update */
++
++ }
++
++ if_debug0('v', "[v]procs not updated\n");
++
++ return 0;
++}
++
++
++static int
++pdf14_update_device_color_procs_pop_c(gx_device *dev,gs_imager_state *pis)
++{
++
++ pdf14_device *pdev = (pdf14_device *)dev;
++ pdf14_parent_color_t *parent_color = pdev->trans_group_parent_cmap_procs;
++ gx_device_clist_writer * cldev = (gx_device_clist_writer *)pdev->pclist_device;
++
++
++ if_debug0('v', "[v]pdf14_update_device_color_procs_pop_c\n");
++
++ /* The color procs are always pushed. Simply restore them. */
++
++ if (!(parent_color->parent_color_mapping_procs == NULL &&
++ parent_color->parent_color_comp_index == NULL)) {
++
++ if_debug2('v', "[v]pdf14_update_device_color_procs_pop_c,num_components_old = %d num_components_new = %d\n",
++ pdev->color_info.num_components,parent_color->num_components);
++
++ pis->get_cmap_procs = parent_color->get_cmap_procs;
++ gx_set_cmap_procs(pis, dev);
++
++ pdev->procs.get_color_mapping_procs = parent_color->parent_color_mapping_procs;
++ pdev->procs.get_color_comp_index = parent_color->parent_color_comp_index;
++ pdev->color_info.polarity = parent_color->polarity;
++ pdev->color_info.depth = parent_color->depth;
++ pdev->color_info.num_components = parent_color->num_components;
++ pdev->blend_procs = parent_color->parent_blending_procs;
++ pdev->pdf14_procs = parent_color->unpack_procs;
++
++ /* clist writer fill rect has no access to imager state */
++ /* and it forwards the target device. this information */
++ /* is passed along to use in this case */
++
++ cldev->clist_color_info.depth = pdev->color_info.depth;
++ cldev->clist_color_info.polarity = pdev->color_info.polarity;
++ cldev->clist_color_info.num_components = pdev->color_info.num_components;
++
++ if (pdev->ctx){
++ pdev->ctx->additive = parent_color->isadditive;
++ }
++
++ if_debug0('v', "[v]procs updated\n");
++
++ } else {
++
++ if_debug0('v', "[v]pdf14_update_device_color_procs_pop_c ERROR \n");
++
++ }
++
++ return 0;
++}
++
++
++
++
++
++
++
++
++ /* When a transparency group is pushed, the parent colorprocs
++ are initialized. Since the color mapping procs are
++ all based upon the device, we must have a nested list
++ based upon the transparency group color space. This
++ nesting must be outside the nested ctx structures
++ to allow the nesting for the clist writer */
++
++static void
++pdf14_push_parent_color(gx_device *dev, const gs_imager_state *pis)
++{
++
++ pdf14_device *pdev = (pdf14_device *)dev;
++ pdf14_parent_color_t *new_parent_color;
++
++ if_debug0('v', "[v]pdf14_push_parent_color\n");
++
++ /* Allocate a new one */
++
++ new_parent_color = gs_alloc_struct(dev->memory, pdf14_parent_color_t,&st_pdf14_clr,
++ "pdf14_clr_new");
++
++ /* Link to old one */
++
++ new_parent_color->previous = pdev->trans_group_parent_cmap_procs;
++
++ /* Reassign new one to dev */
++
++ pdev->trans_group_parent_cmap_procs = new_parent_color;
++
++ /* Initialize with values */
++
++ new_parent_color->get_cmap_procs = pis->get_cmap_procs;
++ new_parent_color->parent_color_mapping_procs =
++ pdev->procs.get_color_mapping_procs;
++ new_parent_color->parent_color_comp_index =
++ pdev->procs.get_color_comp_index;
++ new_parent_color->parent_blending_procs = pdev->blend_procs;
++ new_parent_color->polarity = pdev->color_info.polarity;
++ new_parent_color->num_components = pdev->color_info.num_components;
++ new_parent_color->unpack_procs = pdev->pdf14_procs;
++ new_parent_color->depth = pdev->color_info.depth;
++
++ /* isadditive is only used in ctx */
++ if (pdev->ctx)
++ {
++ new_parent_color->isadditive = pdev->ctx->additive;
++ }
++
++}
++
++ /* When a transparency group is popped, the parent colorprocs
++ must be restored. Since the color mapping procs are
++ all based upon the device, we must have a nested list
++ based upon the transparency group color space. This
++ nesting must be outside the nested ctx structures
++ to allow the nesting for the clist writer */
++
++static void
++pdf14_pop_parent_color(gx_device *dev, const gs_imager_state *pis)
++{
++
++ pdf14_device *pdev = (pdf14_device *)dev;
++ pdf14_parent_color_t *old_parent_color_info = pdev->trans_group_parent_cmap_procs;
++
++ if_debug0('v', "[v]pdf14_pop_parent_color\n");
++
++ /* Update the link */
++
++ pdev->trans_group_parent_cmap_procs = old_parent_color_info->previous;
++
++ /* Free the old one */
++
++ gs_free_object(dev->memory, old_parent_color_info, "pdf14_clr_free");
++
++
++}
++
++
+ static int
+ pdf14_begin_transparency_mask(gx_device *dev,
+ const gx_transparency_mask_params_t *ptmp,
+@@ -1746,6 +2582,8 @@ pdf14_begin_transparency_mask(gx_device *dev,
+ "pdf14_begin_transparency_mask");
+ gs_int_rect rect;
+ int code;
++ int group_color_numcomps;
++ gs_transparency_color_t group_color;
+
+ if (transfer_fn == NULL)
+ return_error(gs_error_VMerror);
+@@ -1756,19 +2594,105 @@ pdf14_begin_transparency_mask(gx_device *dev,
+ bg_alpha = (int)(255 * ptmp->GrayBackground + 0.5);
+ if_debug1('v', "pdf14_begin_transparency_mask, bg_alpha = %d\n", bg_alpha);
+ memcpy(transfer_fn, ptmp->transfer_fn, size_of(ptmp->transfer_fn));
++
++ /* If the group color is unknown, then we must use the previous group color
++ space or the device process color space */
++
++ if (ptmp->group_color == UNKNOWN){
++
++ if (pdev->ctx->stack){
++ /* Use previous group color space */
++ group_color_numcomps = pdev->ctx->stack->n_chan-1; /* Remove alpha */
++ } else {
++ /* Use process color space */
++ group_color_numcomps = pdev->color_info.num_components;
++ }
++
++ switch (group_color_numcomps) {
++ case 1:
++ group_color = GRAY_SCALE;
++ break;
++ case 3:
++ group_color = DEVICE_RGB;
++ break;
++ case 4:
++ group_color = DEVICE_CMYK;
++ break;
++ default:
++
++ /* We can end up here if we are in
++ a deviceN color space and
++ we have a sep output device */
++
++ group_color = DEVICEN;
++
++ break;
++
++ }
++
++ } else {
++
++ group_color = ptmp->group_color;
++ group_color_numcomps = ptmp->group_color_numcomps;
++
++ }
++
++
++ /* Always update the color mapping procs. Otherwise we end up
++ fowarding to the target device. */
++ code = pdf14_update_device_color_procs(dev,group_color,pis);
++ if (code < 0)
++ return code;
++
++ /* Note that the soft mask always follows the group color requirements even
++ when we have a separable device */
++
+ return pdf14_push_transparency_mask(pdev->ctx, &rect, bg_alpha,
+ transfer_fn, ptmp->idle, ptmp->replacing,
+- ptmp->mask_id);
++ ptmp->mask_id, ptmp->subtype,
++ ptmp->SMask_is_CIE, group_color_numcomps);
+ }
+
+ static int
+-pdf14_end_transparency_mask(gx_device *dev,
++pdf14_end_transparency_mask(gx_device *dev, gs_imager_state *pis,
+ gs_transparency_mask_t **pptm)
+ {
+ pdf14_device *pdev = (pdf14_device *)dev;
++ pdf14_parent_color_t *parent_color;
++ int ok;
+
+ if_debug0('v', "pdf14_end_transparency_mask\n");
+- return pdf14_pop_transparency_mask(pdev->ctx);
++
++ ok = pdf14_pop_transparency_mask(pdev->ctx);
++
++ /* May need to reset some color stuff related
++ * to a mismatch between the Smask color space
++ * and the Smask blending space */
++
++ if (pdev->ctx->stack != NULL ) {
++
++ parent_color = &(pdev->ctx->stack->parent_color_info_procs);
++
++ if (!(parent_color->parent_color_mapping_procs == NULL &&
++ parent_color->parent_color_comp_index == NULL)) {
++
++ pis->get_cmap_procs = parent_color->get_cmap_procs;;
++ gx_set_cmap_procs(pis, dev);
++ pdev->procs.get_color_mapping_procs = parent_color->parent_color_mapping_procs;
++ pdev->procs.get_color_comp_index = parent_color->parent_color_comp_index;
++ pdev->color_info.polarity = parent_color->polarity;
++ pdev->color_info.num_components = parent_color->num_components;
++ pdev->color_info.depth = parent_color->depth;
++ pdev->blend_procs = parent_color->parent_blending_procs;
++ pdev->ctx->additive = parent_color->isadditive;
++ pdev->pdf14_procs = parent_color->unpack_procs;
++ parent_color->get_cmap_procs = NULL;
++ parent_color->parent_color_comp_index = NULL;
++ parent_color->parent_color_mapping_procs = NULL;
++ }
++ }
++
++ return ok;
+ }
+
+ static int
+@@ -1793,7 +2717,6 @@ pdf14_mark_fill_rectangle(gx_device * dev,
+ int alpha_g_off = shape_off + (has_shape ? planestride : 0);
+ bool overprint = pdev->overprint;
+ gx_color_index drawn_comps = pdev->drawn_comps;
+- bool overprint_mode = pdev->overprint_mode;
+ gx_color_index comps;
+ byte shape = 0; /* Quiet compiler. */
+ byte src_alpha;
+@@ -1879,8 +2802,8 @@ pdf14_mark_fill_rectangle(gx_device * dev,
+ }
+ line += rowstride;
+ }
+-
+-#if RAW_DUMP
++#if 0
++/* #if RAW_DUMP */
+
+ /* Dump the current buffer to see what we have. */
+
+@@ -1993,6 +2916,9 @@ pdf14_mark_fill_rectangle_ko_simple(gx_device * dev,
+ static cmap_proc_gray(pdf14_cmap_gray_direct);
+ static cmap_proc_rgb(pdf14_cmap_rgb_direct);
+ static cmap_proc_cmyk(pdf14_cmap_cmyk_direct);
++static cmap_proc_gray(pdf14_cmap_gray_direct_group);
++static cmap_proc_rgb(pdf14_cmap_rgb_direct_group);
++static cmap_proc_cmyk(pdf14_cmap_cmyk_direct_group);
+ static cmap_proc_rgb_alpha(pdf14_cmap_rgb_alpha_direct);
+ static cmap_proc_separation(pdf14_cmap_separation_direct);
+ static cmap_proc_devicen(pdf14_cmap_devicen_direct);
+@@ -2008,6 +2934,16 @@ static const gx_color_map_procs pdf14_cmap_many = {
+ pdf14_cmap_is_halftoned
+ };
+
++static const gx_color_map_procs pdf14_cmap_many_group = {
++ pdf14_cmap_gray_direct_group,
++ pdf14_cmap_rgb_direct_group,
++ pdf14_cmap_cmyk_direct_group,
++ pdf14_cmap_rgb_alpha_direct,
++ pdf14_cmap_separation_direct,
++ pdf14_cmap_devicen_direct,
++ pdf14_cmap_is_halftoned
++ };
++
+ /**
+ * Note: copied from gxcmap.c because it's inlined.
+ **/
+@@ -2098,17 +3034,232 @@ pdf14_cmap_cmyk_direct(frac c, frac m, frac y, frac k, gx_device_color * pdc,
+ color_set_pure(pdc, color);
+ }
+
++/* color mapping for when we have an smask or a isolated transparency group with another color space */
++static void
++pdf14_cmap_gray_direct_group(frac gray, gx_device_color * pdc, const gs_imager_state * pis,
++ gx_device * dev, gs_color_select_t select)
++{
++ int i, ncomps = dev->color_info.num_components;
++ frac cm_comps[GX_DEVICE_COLOR_MAX_COMPONENTS];
++ gx_color_value cv[GX_DEVICE_COLOR_MAX_COMPONENTS];
++ gx_color_index color;
++ gx_device *trans_device;
++
++ /* We may be coming from the clist writer
++ which often forwards us the target device.
++ If this occurs we actually need to get to
++ the color space defined by the transparency group
++ and we use the operators defined by the transparency device
++ to do the job.
++ */
++
++ if (pis->trans_device != NULL){
++
++ trans_device = pis->trans_device;
++
++ } else {
++
++ trans_device = dev;
++ }
++
++ ncomps = trans_device->color_info.num_components;
++
++ /* If we are doing concretization of colors in an SMask or isolated group
++ then just return the color as is */
++
++ if (ncomps == 1 ){
++
++ cv[0] = frac2cv(gray);
++
++ /* encode as a color index */
++ color = pdf14_encode_smask_color(trans_device,cv,1);
++
++ /* check if the encoding was successful; we presume failure is rare */
++ if (color != gx_no_color_index)
++ color_set_pure(pdc, color);
++
++ } else {
++
++ /* map to the color model */
++ dev_proc(trans_device, get_color_mapping_procs)(trans_device)->map_gray(trans_device, gray, cm_comps);
++
++ for (i = 0; i < ncomps; i++)
++ cv[i] = frac2cv(cm_comps[i]);
++
++ /* encode as a color index */
++ color = dev_proc(trans_device, encode_color)(trans_device, cv);
++
++ /* check if the encoding was successful; we presume failure is rare */
++ if (color != gx_no_color_index)
++ color_set_pure(pdc, color);
++
++ }
++
++}
++
++/* color mapping for when we have an smask or a isolated transparency group with another color space */
++static void
++pdf14_cmap_rgb_direct_group(frac r, frac g, frac b, gx_device_color * pdc,
++ const gs_imager_state * pis, gx_device * dev, gs_color_select_t select)
++{
++ int i, ncomps = dev->color_info.num_components;
++ frac cm_comps[GX_DEVICE_COLOR_MAX_COMPONENTS];
++ gx_color_value cv[GX_DEVICE_COLOR_MAX_COMPONENTS];
++ gx_color_index color;
++ gx_device *trans_device;
++
++ /* We may be coming from the clist writer
++ which often forwards us the target device.
++ If this occurs we actually need to get to
++ the color space defined by the transparency group
++ and we use the operators defined by the transparency device
++ to do the job.
++ */
++
++ if (pis->trans_device != NULL){
++
++ trans_device = pis->trans_device;
++
++ } else {
++
++ trans_device = dev;
++ }
++
++ ncomps = trans_device->color_info.num_components;
++
++ if ( ncomps == 3 ){
++
++ cv[0] = frac2cv(r);
++ cv[1] = frac2cv(g);
++ cv[2] = frac2cv(b);
++
++ /* encode as a color index */
++ color = pdf14_encode_smask_color(trans_device,cv,3);
++
++ /* check if the encoding was successful; we presume failure is rare */
++ if (color != gx_no_color_index)
++ color_set_pure(pdc, color);
++
++ } else {
++
++ /* map to the device color model */
++ /* We can end up here, if for example we had a DeviceN
++ color space with a CIE based alternate space and
++ a output device that was RGB but a blending
++ space that was CMYK. The proper way to solve this
++ is to introduce another color space for the graphic
++ state that has its own Joint CIE Cache between the
++ source and a CMYK CRD (the transparency color space).
++ The problem is that we can
++ only have one CRD, which is defined by the output
++ device. We will fix these issues with the
++ new ICC base color architecture. */
++
++ dev_proc(trans_device, get_color_mapping_procs)(trans_device)->map_rgb(trans_device, pis, r, g, b, cm_comps);
++
++ for (i = 0; i < ncomps; i++)
++ cv[i] = frac2cv(cm_comps[i]);
++
++ /* encode as a color index */
++ color = dev_proc(trans_device, encode_color)(trans_device, cv);
++
++ /* check if the encoding was successful; we presume failure is rare */
++ if (color != gx_no_color_index)
++ color_set_pure(pdc, color);
++
++ }
++}
++
++/* color mapping for when we have an smask or a isolated transparency group with another color space */
++static void
++pdf14_cmap_cmyk_direct_group(frac c, frac m, frac y, frac k, gx_device_color * pdc,
++ const gs_imager_state * pis, gx_device * dev, gs_color_select_t select)
++{
++ int i, ncomps = dev->color_info.num_components;
++ frac cm_comps[GX_DEVICE_COLOR_MAX_COMPONENTS];
++ gx_color_value cv[GX_DEVICE_COLOR_MAX_COMPONENTS];
++ gx_color_index color;
++ gx_device *trans_device;
++
++ /* We may be coming from the clist writer
++ which often forwards us the target device.
++ If this occurs we actually need to get to
++ the color space defined by the transparency group
++ and we use the operators defined by the transparency device
++ to do the job.
++ */
++
++ if (pis->trans_device != NULL){
++
++ trans_device = pis->trans_device;
++
++ } else {
++
++ trans_device = dev;
++ }
++
++ ncomps = trans_device->color_info.num_components;
++
++ if (ncomps == 4 ){
++
++ cv[0] = frac2cv(c);
++ cv[1] = frac2cv(m);
++ cv[2] = frac2cv(y);
++ cv[3] = frac2cv(k);
++
++ /* encode as a color index */
++ color = pdf14_encode_smask_color(trans_device,cv,4);
++
++ /* check if the encoding was successful; we presume failure is rare */
++ if (color != gx_no_color_index)
++ color_set_pure(pdc, color);
++
++ } else {
++
++ /* map to the color model */
++ dev_proc(trans_device, get_color_mapping_procs)(trans_device)->map_cmyk(trans_device, c, m, y, k, cm_comps);
++
++ for (i = 0; i < ncomps; i++)
++ cv[i] = frac2cv(cm_comps[i]);
++
++ color = dev_proc(trans_device, encode_color)(trans_device, cv);
++ if (color != gx_no_color_index)
++ color_set_pure(pdc, color);
++
++ }
++}
++
+ static void
+ pdf14_cmap_rgb_alpha_direct(frac r, frac g, frac b, frac alpha, gx_device_color * pdc,
+ const gs_imager_state * pis, gx_device * dev, gs_color_select_t select)
+ {
+- int i, ncomps = dev->color_info.num_components;
++ int i, ncomps;
+ frac cm_comps[GX_DEVICE_COLOR_MAX_COMPONENTS];
+- gx_color_value cv_alpha, cv[GX_DEVICE_COLOR_MAX_COMPONENTS];
++ gx_color_value cv[GX_DEVICE_COLOR_MAX_COMPONENTS];
+ gx_color_index color;
++ gx_device *trans_device;
++
++ /* We may be coming from the clist writer
++ which often forwards us the target device.
++ If this occurs we actually need to get to
++ the color space defined by the transparency group
++ and we use the operators defined by the transparency device
++ to do the job.
++ */
++
++ if (pis->trans_device != NULL){
++
++ trans_device = pis->trans_device;
++
++ } else {
++
++ trans_device = dev;
++ }
++
++ ncomps = trans_device->color_info.num_components;
+
+ /* map to the color model */
+- dev_proc(dev, get_color_mapping_procs)(dev)->map_rgb(dev, pis, r, g, b, cm_comps);
++ dev_proc(trans_device, get_color_mapping_procs)(trans_device)->map_rgb(trans_device, pis, r, g, b, cm_comps);
+
+ /* pre-multiply to account for the alpha weighting */
+ if (alpha != frac_1) {
+@@ -2126,11 +3277,13 @@ pdf14_cmap_rgb_alpha_direct(frac r, frac g, frac b, frac alpha, gx_device_color
+ cv[i] = frac2cv(cm_comps[i]);
+
+ /* encode as a color index */
+- if (dev_proc(dev, map_rgb_alpha_color) != gx_default_map_rgb_alpha_color &&
++ /* if (dev_proc(dev, map_rgb_alpha_color) != gx_default_map_rgb_alpha_color &&
+ (cv_alpha = frac2cv(alpha)) != gx_max_color_value)
+- color = dev_proc(dev, map_rgb_alpha_color)(dev, cv[0], cv[1], cv[2], cv_alpha);
+ else
+- color = dev_proc(dev, encode_color)(dev, cv);
++ color = dev_proc(dev, encode_color)(dev, cv); */
++
++ color = dev_proc(trans_device, encode_color)(trans_device, cv);
++
+
+ /* check if the encoding was successful; we presume failure is rare */
+ if (color != gx_no_color_index)
+@@ -2185,7 +3338,6 @@ pdf14_cmap_separation_direct(frac all, gx_device_color * pdc, const gs_imager_st
+ color_set_pure(pdc, color);
+ }
+
+-
+ static void
+ pdf14_cmap_devicen_direct(const frac * pcc,
+ gx_device_color * pdc, const gs_imager_state * pis, gx_device * dev,
+@@ -2195,12 +3347,32 @@ pdf14_cmap_devicen_direct(const frac * pcc,
+ frac cm_comps[GX_DEVICE_COLOR_MAX_COMPONENTS];
+ gx_color_value cv[GX_DEVICE_COLOR_MAX_COMPONENTS];
+ gx_color_index color;
++ gx_device *trans_device;
++
++ /* We may be coming from the clist writer
++ which often forwards us the target device.
++ If this occurs we actually need to get to
++ the color space defined by the transparency group
++ and we use the operators defined by the transparency device
++ to do the job.
++ */
++
++ if (pis->trans_device != NULL){
++
++ trans_device = pis->trans_device;
++
++ } else {
++
++ trans_device = dev;
++ }
++
++ ncomps = trans_device->color_info.num_components;
+
+ /* map to the color model */
+ map_components_to_colorants(pcc, &(pis->color_component_map), cm_comps);;
+
+ /* apply the transfer function(s); convert to color values */
+- if (dev->color_info.polarity == GX_CINFO_POLARITY_ADDITIVE)
++ if (trans_device->color_info.polarity == GX_CINFO_POLARITY_ADDITIVE)
+ for (i = 0; i < ncomps; i++)
+ cv[i] = frac2cv(gx_map_color_frac(pis,
+ cm_comps[i], effective_transfer[i]));
+@@ -2210,7 +3382,7 @@ pdf14_cmap_devicen_direct(const frac * pcc,
+ (frac)(frac_1 - cm_comps[i]), effective_transfer[i]));
+
+ /* encode as a color index */
+- color = dev_proc(dev, encode_color)(dev, cv);
++ color = dev_proc(trans_device, encode_color)(trans_device, cv);
+
+ /* check if the encoding was successful; we presume failure is rare */
+ if (color != gx_no_color_index)
+@@ -2230,6 +3402,14 @@ pdf14_get_cmap_procs(const gs_imager_state *pis, const gx_device * dev)
+ return &pdf14_cmap_many;
+ }
+
++static const gx_color_map_procs *
++pdf14_get_cmap_procs_group(const gs_imager_state *pis, const gx_device * dev)
++{
++ /* The pdf14 marking device itself is always continuous tone. */
++ return &pdf14_cmap_many_group;
++}
++
++
+ static int
+ pdf14_pattern_manage(gx_device *pdev, gx_bitmap_id id,
+ gs_pattern1_instance_t *pinst, pattern_manage_t function)
+@@ -2271,6 +3451,23 @@ gs_pdf14_device_push(gs_memory_t *mem, gs_imager_state * pis,
+ code = dev_proc((gx_device *) p14dev, open_device) ((gx_device *) p14dev);
+ *pdev = (gx_device *) p14dev;
+ pdf14_set_marking_params((gx_device *)p14dev, pis);
++
++ p14dev->trans_group_parent_cmap_procs = NULL;
++
++#if RAW_DUMP
++
++ /* Dump the current buffer to see what we have. */
++
++ dump_raw_buffer(p14dev->ctx->stack->rect.q.y-p14dev->ctx->stack->rect.p.y,
++ p14dev->ctx->stack->rect.q.x-p14dev->ctx->stack->rect.p.x,
++ p14dev->ctx->stack->n_planes,
++ p14dev->ctx->stack->planestride, p14dev->ctx->stack->rowstride,
++ "Device_Push",p14dev->ctx->stack->data);
++
++ global_index++;
++
++
++#endif
+ return code;
+ }
+
+@@ -2370,6 +3567,8 @@ c_pdf14trans_write(const gs_composite_t * pct, byte * data, uint * psize, gx_dev
+ return code;
+ *pbuf++ = (pparams->Isolated & 1) + ((pparams->Knockout & 1) << 1);
+ *pbuf++ = pparams->blend_mode;
++ *pbuf++ = pparams->group_color;
++ put_value(pbuf, pparams->group_color_numcomps);
+ put_value(pbuf, pparams->opacity.alpha);
+ put_value(pbuf, pparams->shape.alpha);
+ put_value(pbuf, pparams->bbox);
+@@ -2381,6 +3580,8 @@ c_pdf14trans_write(const gs_composite_t * pct, byte * data, uint * psize, gx_dev
+ if (code < 0)
+ return code;
+ put_value(pbuf, pparams->subtype);
++ *pbuf++ = pparams->group_color;
++ put_value(pbuf, pparams->group_color_numcomps);
+ *pbuf++ = pparams->replacing;
+ *pbuf++ = pparams->function_is_identity;
+ *pbuf++ = pparams->Background_components;
+@@ -2498,6 +3699,8 @@ c_pdf14trans_read(gs_composite_t * * ppct, const byte * data,
+ params.Isolated = (*data) & 1;
+ params.Knockout = (*data++ >> 1) & 1;
+ params.blend_mode = *data++;
++ params.group_color = *data++; /* Trans group color */
++ read_value(data,params.group_color_numcomps); /* color group size */
+ read_value(data, params.opacity.alpha);
+ read_value(data, params.shape.alpha);
+ read_value(data, params.bbox);
+@@ -2518,6 +3721,8 @@ c_pdf14trans_read(gs_composite_t * * ppct, const byte * data,
+ */
+ data = cmd_read_matrix(&params.ctm, data);
+ read_value(data, params.subtype);
++ params.group_color = *data++;
++ read_value(data, params.group_color_numcomps);
+ params.replacing = *data++;
+ params.function_is_identity = *data++;
+ params.Background_components = *data++;
+@@ -2958,19 +4163,19 @@ static dev_proc_begin_typed_image(pdf14_clist_begin_typed_image);
+ static const gx_device_procs pdf14_clist_Gray_procs =
+ pdf14_clist_procs(gx_default_DevGray_get_color_mapping_procs,
+ gx_default_DevGray_get_color_comp_index,
+- gx_default_8bit_map_gray_color,
+- gx_default_8bit_map_color_gray);
++ pdf14_encode_color,
++ pdf14_decode_color);
+
+ static const gx_device_procs pdf14_clist_RGB_procs =
+ pdf14_clist_procs(gx_default_DevRGB_get_color_mapping_procs,
+ gx_default_DevRGB_get_color_comp_index,
+- gx_default_rgb_map_rgb_color,
+- gx_default_rgb_map_color_rgb);
++ pdf14_encode_color,
++ pdf14_decode_color);
+
+ static const gx_device_procs pdf14_clist_CMYK_procs =
+ pdf14_clist_procs(gx_default_DevCMYK_get_color_mapping_procs,
+ gx_default_DevCMYK_get_color_comp_index,
+- cmyk_8bit_map_cmyk_color, cmyk_8bit_map_color_cmyk);
++ pdf14_encode_color, pdf14_decode_color);
+
+ static const gx_device_procs pdf14_clist_CMYKspot_procs =
+ pdf14_clist_procs(pdf14_cmykspot_get_color_mapping_procs,
+@@ -3080,6 +4285,22 @@ get_pdf14_clist_device_proto(gx_device * dev, pdf14_clist_device ** pdevproto,
+ switch (dev_cs) {
+ case PDF14_DeviceGray:
+ *pdevproto = (pdf14_clist_device *)&pdf14_clist_Gray_device;
++
++ /* We want gray to be single channel. Low level
++ initialization of gray device prototype is
++ peculiar in that in dci_std_color_num_components
++ the comment is
++ "A device is monochrome only if it is bi-level"
++
++ Here we want monochrome anytime we have a gray device.
++ To avoid breaking things elsewhere, we will overide
++ the prototype intialization here */
++
++ *ptempdevproto = **pdevproto;
++ ptempdevproto->color_info.max_components = 1;
++ ptempdevproto->color_info.num_components = ptempdevproto->color_info.max_components;
++ *pdevproto = ptempdevproto;
++
+ break;
+ case PDF14_DeviceRGB:
+ *pdevproto = (pdf14_clist_device *)&pdf14_clist_RGB_device;
+@@ -3596,6 +4817,7 @@ pdf14_clist_create_compositor(gx_device * dev, gx_device ** pcdev,
+ {
+ pdf14_clist_device * pdev = (pdf14_clist_device *)dev;
+ int code;
++ bool sep_target;
+
+ /* We only handle a few PDF 1.4 transparency operations 4 */
+ if (gs_is_pdf14trans_compositor(pct)) {
+@@ -3672,8 +4894,92 @@ pdf14_clist_create_compositor(gx_device * dev, gx_device ** pcdev,
+ if (pdf14pct->params.Background_components != 0 &&
+ pdf14pct->params.Background_components != pdev->color_info.num_components)
+ return_error(gs_error_rangecheck);
++
++ /* We need to update the clist writer device procs based upon the
++ the group color space. For simplicity, the list item is created even if the
++ color space did not change */
++
++ /* First store the current ones */
++
++ pdf14_push_parent_color(dev, pis);
++
++ /* Now update the device procs. Not
++ if we have a sep target though */
++
++ sep_target = (strcmp(pdev->dname, "PDF14clistcustom") == 0) || (strcmp(pdev->dname, "PDF14clistcmykspot") == 0);
++
++ if (!sep_target)
++ code = pdf14_update_device_color_procs_push_c(dev,
++ pdf14pct->params.group_color,pis);
++
++ /* Note that our initial device buffer may have had a different color space
++ than the first transparency group. In such a case, we really should force
++ this first group to be isolated, anytime that the parent color space is
++ different than its child group, it should be isolated, per the PDF spec */
++ /* MJV */
++ /* if (code == 1){
++
++ isolated = true;
++ if_debug0('v', "[v]Transparency group color space change\n");
++
++ } else {
++
++ isolated = ptgp->Isolated;
++
++ } */
++
+ break;
+- default:
++
++ case PDF14_BEGIN_TRANS_MASK:
++
++ /* We need to update the clist writer device procs based upon the
++ the group color space. For simplicity, the list item is created even if the
++ color space did not change */
++
++ /* First store the current ones */
++
++ pdf14_push_parent_color(dev, pis);
++
++ /* Now update the device procs */
++
++ code = pdf14_update_device_color_procs_push_c(dev,
++ pdf14pct->params.group_color,pis);
++
++ break;
++
++
++ /* When we get a trans group pop, we need to update the color mapping procs */
++ case PDF14_END_TRANS_GROUP:
++
++ /* We need to update the clist writer device procs based upon the
++ the group color space. */
++
++ /* First restore our procs */
++
++ code = pdf14_update_device_color_procs_pop_c(dev,pis);
++
++ /* Now pop the old one */
++
++ pdf14_pop_parent_color(dev, pis);
++
++ break;
++
++ case PDF14_END_TRANS_MASK:
++
++ /* We need to update the clist writer device procs based upon the
++ the group color space. */
++
++ /* First restore our procs */
++
++ code = pdf14_update_device_color_procs_pop_c(dev,pis);
++
++ /* Now pop the old one */
++
++ pdf14_pop_parent_color(dev, pis);
++
++ break;
++
++ default:
+ break; /* Pass remaining ops to target */
+ }
+ }
+@@ -3772,6 +5078,7 @@ pdf14_clist_update_params(pdf14_clist_device * pdev, const gs_imager_state * pis
+ return code;
+ }
+
++
+ /*
+ * fill_path routine for the PDF 1.4 transaprency compositor device for
+ * writing the clist.
+@@ -3785,6 +5092,7 @@ pdf14_clist_fill_path(gx_device *dev, const gs_imager_state *pis,
+ pdf14_clist_device * pdev = (pdf14_clist_device *)dev;
+ gs_imager_state new_is = *pis;
+ int code;
++ gs_pattern2_instance_t *pinst = NULL;
+
+ /*
+ * Ensure that that the PDF 1.4 reading compositor will have the current
+@@ -3795,12 +5103,47 @@ pdf14_clist_fill_path(gx_device *dev, const gs_imager_state *pis,
+ code = pdf14_clist_update_params(pdev, pis);
+ if (code < 0)
+ return code;
++
++ /* If we are doing a shading fill and we are in a tranparency
++ group of a different color space, then we do not want to
++ do the shading in the device color space. It must occur in
++ the source space. To handle it in the device space would
++ require knowing all the nested transparency group color spaces
++ as well as the transparency. Some of the shading code
++ ignores this, so we have to pass on the clist_writer device
++ to enable proper mapping to the transparency group color space. */
++
++ if (pdcolor != NULL && gx_dc_is_pattern2_color(pdcolor) && pdev->trans_group_parent_cmap_procs != NULL) {
++
++ pinst =
++ (gs_pattern2_instance_t *)pdcolor->ccolor.pattern;
++ pinst->saved->has_transparency = true;
++
++ /* The transparency color space operations are driven
++ by the pdf14 clist writer device. */
++
++ pinst->saved->trans_device = dev;
++
++ }
++
+ /*
+ * The blend operations are not idempotent. Force non-idempotent
+ * filling and stroking operations.
+ */
+ new_is.log_op |= lop_pdf14;
+- return gx_forward_fill_path(dev, &new_is, ppath, params, pdcolor, pcpath);
++ new_is.trans_device = dev;
++ new_is.has_transparency = true;
++
++ code = gx_forward_fill_path(dev, &new_is, ppath, params, pdcolor, pcpath);
++
++ new_is.trans_device = NULL;
++ new_is.has_transparency = false;
++
++ if (pinst != NULL){
++ pinst->saved->trans_device = NULL;
++ }
++
++ return code;
+ }
+
+ /*
+@@ -3887,9 +5230,19 @@ pdf14_clist_begin_image(gx_device * dev,
+ code = pdf14_clist_update_params(pdev, pis);
+ if (code < 0)
+ return code;
++
+ /* Pass image to the target */
+- return gx_forward_begin_image(dev, pis, pim, format, prect,
++ code = gx_forward_begin_image(dev, pis, pim, format, prect,
+ pdcolor, pcpath, memory, pinfo);
++
++ if (code < 0)
++ return gx_default_begin_image(dev, pis, pim, format, prect,
++ pdcolor, pcpath, memory, pinfo);
++ else return code;
++
++
++
++
+ }
+
+ static int
+@@ -3902,6 +5255,7 @@ pdf14_clist_begin_typed_image(gx_device * dev, const gs_imager_state * pis,
+ {
+ pdf14_clist_device * pdev = (pdf14_clist_device *)dev;
+ int code;
++ gs_imager_state * pis_noconst = pis; /* Break 'const'. */
+
+ /*
+ * Ensure that that the PDF 1.4 reading compositor will have the current
+@@ -3909,12 +5263,39 @@ pdf14_clist_begin_typed_image(gx_device * dev, const gs_imager_state * pis,
+ * do not have access to the imager state. Thus we have to pass any
+ * changes explictly.
+ */
++
+ code = pdf14_clist_update_params(pdev, pis);
+ if (code < 0)
+ return code;
++
+ /* Pass image to the target */
+- return gx_forward_begin_typed_image(dev, pis, pmat,
+- pic, prect, pdcolor, pcpath, mem, pinfo);
++
++ /* Do a quick change to the imager state
++ so that if we can return with -1 in
++ case the clist writer cannot handle
++ this image itself. In such a case,
++ we want to make sure we dont use the
++ target device. I don't necc. like
++ doing it this way. Probably need to
++ go back and do something a bit
++ more elegant. */
++
++ pis_noconst->has_transparency = true;
++ code = gx_forward_begin_typed_image(dev, pis, pmat,
++ pic, prect, pdcolor, pcpath, mem, pinfo);
++ if (code < 0){
++
++ code = gx_default_begin_typed_image(dev, pis, pmat, pic, prect,
++ pdcolor, pcpath, mem, pinfo);
++ pis_noconst->has_transparency = false;
++ return code;
++
++ } else {
++
++ pis_noconst->has_transparency = false;
++ return code;
++
++ }
+ }
+
+ /*
+@@ -3934,6 +5315,9 @@ c_pdf14trans_clist_write_update(const gs_composite_t * pcte, gx_device * dev,
+ pdf14_clist_device * p14dev;
+ int code = 0;
+
++ p14dev = (pdf14_clist_device *)(*pcdev);
++
++
+ /* We only handle the push/pop operations */
+ switch (pdf14pct->params.pdf14_op) {
+ case PDF14_PUSH_DEVICE:
+@@ -3947,6 +5331,15 @@ c_pdf14trans_clist_write_update(const gs_composite_t * pcte, gx_device * dev,
+ * transfer functions will be applied at the end after we have done
+ * our PDF 1.4 blend operations.
+ */
++
++ /* Also if the bit depth is not 8 per channel we need to adjust
++ as all the pdf14 compositing code is for 8 bits per channel. The
++ clist writer device uses this information to make sure the proper
++ bit depth is written */
++
++ if (cdev->clist_color_info.num_components * 8 != cdev->clist_color_info.depth)
++ cdev->clist_color_info.depth = cdev->clist_color_info.num_components * 8;
++
+ p14dev = (pdf14_clist_device *)(*pcdev);
+ p14dev->saved_target_color_info = dev->color_info;
+ dev->color_info = (*pcdev)->color_info;
+diff --git a/base/gdevp14.h b/base/gdevp14.h
+--- a/base/gdevp14.h
++++ b/base/gdevp14.h
+@@ -31,6 +31,58 @@ typedef enum {
+ typedef struct pdf14_buf_s pdf14_buf;
+ #endif
+
++/*
++ * This structure contains procedures for processing routine which differ
++ * between the different blending color spaces.
++ */
++typedef struct {
++ /*
++ * Unpack a device color. This routine is similar to the device's
++ * decode_color procedure except for two things. The procedure produces
++ * 1 byte values instead of gx_color_values (2 bytes) and the output
++ * values are inverted for subtractive color spaces (like CMYK).
++ * A separate procedure is used instead of the decode_color to minimize
++ * execution time.
++ */
++ void (* unpack_color)(int num_comp, gx_color_index color,
++ pdf14_device * p14dev, byte * out);
++ /*
++ * This procedure sends the final rasterized transparency data to the
++ * output device as an image.
++ */
++ int (* put_image)(gx_device * dev,
++ gs_imager_state * pis, gx_device * target);
++} pdf14_procs_s;
++
++typedef pdf14_procs_s pdf14_procs_t;
++
++/* A structure to hold information
++ * about the parent color related
++ * procs and other information.
++ * These may change depending upon
++ * if the blending space is different
++ * than the base space. The structure
++ * is a list that is updated upon
++ * every transparency group push and pop */
++
++typedef struct pdf14_parent_color_s pdf14_parent_color_t;
++
++struct pdf14_parent_color_s {
++
++ int num_components;
++ bool isadditive;
++ gx_color_polarity_t polarity;
++ byte depth; /* used in clist writer cmd_put_color */
++ const gx_color_map_procs *(*get_cmap_procs)(const gs_imager_state *,
++ const gx_device *);
++ const gx_cm_color_map_procs *(*parent_color_mapping_procs)(const gx_device *);
++ int (*parent_color_comp_index)(gx_device *, const char *, int, int);
++ const pdf14_procs_t * unpack_procs;
++ const pdf14_nonseparable_blending_procs_t * parent_blending_procs;
++ pdf14_parent_color_t *previous;
++
++};
++
+ typedef struct pdf14_ctx_s pdf14_ctx;
+
+ struct pdf14_buf_s {
+@@ -60,7 +112,14 @@ struct pdf14_buf_s {
+ gs_int_rect bbox;
+ pdf14_buf *maskbuf; /* Save pdf14_ctx_s::maksbuf. */
+ bool idle;
++
++ bool SMask_is_CIE;
++ gs_transparency_mask_subtype_t SMask_SubType;
++
+ uint mask_id;
++ pdf14_parent_color_t parent_color_info_procs;
++
++ gs_transparency_color_t color_space; /* Different groups can have different spaces for blending */
+ };
+
+ struct pdf14_ctx_s {
+@@ -97,30 +156,7 @@ typedef struct gs_pdf14trans_params_s gs_pdf14trans_params_t;
+ typedef struct pdf14_device_s pdf14_device;
+ #endif
+
+-/*
+- * This structure contains procedures for processing routine which differ
+- * between the different blending color spaces.
+- */
+-typedef struct {
+- /*
+- * Unpack a device color. This routine is similar to the device's
+- * decode_color procedure except for two things. The procedure produces
+- * 1 byte values instead of gx_color_values (2 bytes) and the output
+- * values are inverted for subtractive color spaces (like CMYK).
+- * A separate procedure is used instead of the decode_color to minimize
+- * execution time.
+- */
+- void (* unpack_color)(int num_comp, gx_color_index color,
+- pdf14_device * p14dev, byte * out);
+- /*
+- * This procedure sends the final rasterized transparency data to the
+- * output device as an image.
+- */
+- int (* put_image)(gx_device * dev,
+- gs_imager_state * pis, gx_device * target);
+-} pdf14_procs_s;
+
+-typedef pdf14_procs_s pdf14_procs_t;
+
+ /*
+ * Define the default post-clist (clist reader) PDF 1.4 compositing device.
+@@ -155,6 +191,9 @@ typedef struct pdf14_device_s {
+ dev_proc_decode_color(*my_decode_color);
+ dev_proc_get_color_mapping_procs(*my_get_color_mapping_procs);
+ dev_proc_get_color_comp_index(*my_get_color_comp_index);
++
++ pdf14_parent_color_t *trans_group_parent_cmap_procs;
++
+ } pdf14_device_t;
+
+ /*
+diff --git a/base/gdevpbm.c b/base/gdevpbm.c
+--- a/base/gdevpbm.c
++++ b/base/gdevpbm.c
+@@ -682,6 +682,13 @@ pbm_print_page_loop(gx_device_printer * pdev, char magic, FILE * pstream,
+ case '7': /* pam */
+ case '9': /* plan9bm */
+ break;
++ case '3': /* pkm */
++ case '6': /* pkmraw */
++ if (fprintf(pstream, "%d\n", 255) < 0) {
++ code = gs_note_error(gs_error_ioerror);
++ goto punt;
++ }
++ break;
+ default:
+ if (fprintf(pstream, "%d\n", pdev->color_info.max_gray) < 0) {
+ code = gs_note_error(gs_error_ioerror);
+@@ -992,9 +999,9 @@ pkm_print_row_4(gx_device_printer * pdev, byte * data, int depth,
+ gx_color_value rgb[3];
+
+ cmyk_1bit_map_color_rgb((gx_device *)pdev, (gx_color_index)i, rgb);
+- rv[i] = rgb[0] / gx_max_color_value;
+- gv[i] = rgb[1] / gx_max_color_value;
+- bv[i] = rgb[2] / gx_max_color_value;
++ rv[i] = rgb[0] / gx_max_color_value * 0xff;
++ gv[i] = rgb[1] / gx_max_color_value * 0xff;
++ bv[i] = rgb[2] / gx_max_color_value * 0xff;
+ }
+ /*
+ * Contrary to what the documentation implies, gcc compiles putc
+diff --git a/base/gdevpdf.c b/base/gdevpdf.c
+--- a/base/gdevpdf.c
++++ b/base/gdevpdf.c
+@@ -15,7 +15,6 @@
+ /* PDF-writing driver */
+ #include "fcntl_.h"
+ #include "memory_.h"
+-#include "string_.h"
+ #include "time_.h"
+ #include "unistd_.h"
+ #include "gx.h"
+@@ -211,6 +210,9 @@ pdf_open_temp_file(gx_device_pdf *pdev, pdf_temp_file_t *ptf)
+ {
+ char fmode[4];
+
++ if (strlen(gp_fmode_binary_suffix) > 2)
++ return_error(gs_error_invalidfileaccess);
++
+ strcpy(fmode, "w+");
+ strcat(fmode, gp_fmode_binary_suffix);
+ ptf->file =
+@@ -784,11 +786,11 @@ pdf_print_orientation(gx_device_pdf * pdev, pdf_page_t *page)
+
+ /* Close the current page. */
+ static int
+-pdf_close_page(gx_device_pdf * pdev)
++pdf_close_page(gx_device_pdf * pdev, int num_copies)
+ {
+- int page_num = ++(pdev->next_page);
++ int page_num;
+ pdf_page_t *page;
+- int code;
++ int code, i;
+
+ /*
+ * If the very first page is blank, we need to open the document
+@@ -806,89 +808,99 @@ pdf_close_page(gx_device_pdf * pdev)
+ }
+ pdf_close_contents(pdev, true);
+
+- /*
+- * We can't write the page object or the annotations array yet, because
+- * later pdfmarks might add elements to them. Write the other objects
+- * that the page references, and record what we'll need later.
+- *
+- * Start by making sure the pages array element exists.
+- */
+-
+- pdf_page_id(pdev, page_num);
+- page = &pdev->pages[page_num - 1];
+- page->MediaBox.x = pdev->MediaSize[0];
+- page->MediaBox.y = pdev->MediaSize[1];
+- page->contents_id = pdev->contents_id;
+- page->NumCopies_set = pdev->NumCopies_set;
+- page->NumCopies = pdev->NumCopies;
+- /* pdf_store_page_resources sets procsets, resource_ids[]. */
+- code = pdf_store_page_resources(pdev, page);
+- if (code < 0)
+- return code;
+-
+- /* Write the Functions. */
+-
+- code = pdf_write_resource_objects(pdev, resourceFunction);
+- if (code < 0)
+- return code;
+-
+- /* Save viewer's memory with cleaning resources. */
+-
+- if (pdev->MaxViewerMemorySize < 10000000) {
+- /* fixme: the condition above and the cleaning algorithm
+- may be improved with counting stored resource size
+- and creating multiple streams per page. */
+-
+- if (pdev->ForOPDFRead) {
+- pdf_resource_t *pres = pdf_find_resource_by_resource_id(pdev, resourcePage, pdev->contents_id);
++ if (!pdev->DoNumCopies)
++ num_copies = 1;
++
++ for(i=0;i<num_copies;i++) {
++ bool clear_resource_use = i < num_copies - 1 ? 0 : 1;
++
++ page_num = ++(pdev->next_page);
++ /*
++ * We can't write the page object or the annotations array yet, because
++ * later pdfmarks might add elements to them. Write the other objects
++ * that the page references, and record what we'll need later.
++ *
++ * Start by making sure the pages array element exists.
++ */
++
++ pdf_page_id(pdev, page_num);
++ page = &pdev->pages[page_num - 1];
++ page->MediaBox.x = pdev->MediaSize[0];
++ page->MediaBox.y = pdev->MediaSize[1];
++ page->contents_id = pdev->contents_id;
++ page->NumCopies_set = pdev->NumCopies_set;
++ page->NumCopies = pdev->NumCopies;
++ /* pdf_store_page_resources sets procsets, resource_ids[]. */
++ code = pdf_store_page_resources(pdev, page, clear_resource_use);
++ if (code < 0)
++ return code;
++
++ /* Write the Functions. */
++
++ code = pdf_write_resource_objects(pdev, resourceFunction);
++ if (code < 0)
++ return code;
++
++ /* Save viewer's memory with cleaning resources. */
++
++ if (pdev->MaxViewerMemorySize < 10000000) {
++ /* fixme: the condition above and the cleaning algorithm
++ may be improved with counting stored resource size
++ and creating multiple streams per page. */
++
++ if (pdev->ForOPDFRead) {
++ pdf_resource_t *pres = pdf_find_resource_by_resource_id(pdev, resourcePage, pdev->contents_id);
+
+- if (pres != NULL) {
+- code = cos_dict_put_c_strings((cos_dict_t *)pres->object, "/.CleanResources", "/All");
+- if (code < 0)
+- return code;
++ if (pres != NULL) {
++ code = cos_dict_put_c_strings((cos_dict_t *)pres->object, "/.CleanResources", "/All");
++ if (code < 0)
++ return code;
++ }
+ }
++ code = pdf_close_text_document(pdev);
++ if (code < 0)
++ return code;
++ code = pdf_write_and_free_all_resource_objects(pdev);
++ if (code < 0)
++ return code;
+ }
+- code = pdf_close_text_document(pdev);
+- if (code < 0)
+- return code;
+- code = pdf_write_and_free_all_resource_objects(pdev);
+- if (code < 0)
+- return code;
+- }
+
+- /* Close use of text on the page. */
++ /* Close use of text on the page. */
+
+- pdf_close_text_page(pdev);
++ pdf_close_text_page(pdev);
+
+- /* Accumulate text rotation. */
++ /* Accumulate text rotation. */
+
+- page->text_rotation.Rotate =
+- (pdev->params.AutoRotatePages == arp_PageByPage ?
+- pdf_dominant_rotation(&page->text_rotation) : -1);
+- {
+- int i;
++ page->text_rotation.Rotate =
++ (pdev->params.AutoRotatePages == arp_PageByPage ?
++ pdf_dominant_rotation(&page->text_rotation) : -1);
++ {
++ int i;
+
+- for (i = 0; i < countof(page->text_rotation.counts); ++i)
+- pdev->text_rotation.counts[i] += page->text_rotation.counts[i];
+- }
++ for (i = 0; i < countof(page->text_rotation.counts); ++i)
++ pdev->text_rotation.counts[i] += page->text_rotation.counts[i];
++ }
+
+- /* Record information from DSC comments. */
++ /* Record information from DSC comments. */
+
+- page->dsc_info = pdev->page_dsc_info;
+- if (page->dsc_info.orientation < 0)
+- page->dsc_info.orientation = pdev->doc_dsc_info.orientation;
++ page->dsc_info = pdev->page_dsc_info;
++ if (page->dsc_info.orientation < 0)
++ page->dsc_info.orientation = pdev->doc_dsc_info.orientation;
+ #ifdef Bug688793
+- if (page->dsc_info.viewing_orientation < 0)
+- page->dsc_info.viewing_orientation =
++ if (page->dsc_info.viewing_orientation < 0)
++ page->dsc_info.viewing_orientation =
+ pdev->doc_dsc_info.viewing_orientation;
+ #endif
+- if (page->dsc_info.bounding_box.p.x >= page->dsc_info.bounding_box.q.x ||
+- page->dsc_info.bounding_box.p.y >= page->dsc_info.bounding_box.q.y
+- )
+- page->dsc_info.bounding_box = pdev->doc_dsc_info.bounding_box;
++ if (page->dsc_info.bounding_box.p.x >= page->dsc_info.bounding_box.q.x ||
++ page->dsc_info.bounding_box.p.y >= page->dsc_info.bounding_box.q.y
++ )
++ page->dsc_info.bounding_box = pdev->doc_dsc_info.bounding_box;
+
+- /* Finish up. */
++ /* Finish up. */
+
++ if(pdf_ferror(pdev))
++ return(gs_note_error(gs_error_ioerror));
++ }
+ pdf_reset_page(pdev);
+ return (pdf_ferror(pdev) ? gs_note_error(gs_error_ioerror) : 0);
+ }
+@@ -1030,7 +1042,7 @@ static int
+ pdf_output_page(gx_device * dev, int num_copies, int flush)
+ {
+ gx_device_pdf *const pdev = (gx_device_pdf *) dev;
+- int code = pdf_close_page(pdev);
++ int code = pdf_close_page(pdev, num_copies);
+
+ return (code < 0 ? code :
+ pdf_ferror(pdev) ? gs_note_error(gs_error_ioerror) :
+@@ -1067,7 +1079,7 @@ pdf_close(gx_device * dev)
+ return code;
+ }
+ if (pdev->contents_id != 0)
+- pdf_close_page(pdev);
++ pdf_close_page(pdev, 1);
+
+ /* Write the page objects. */
+
+@@ -1122,7 +1134,6 @@ pdf_close(gx_device * dev)
+ if (code >= 0)
+ code = code1;
+
+-
+ /* Create the Pages tree. */
+
+ pdf_open_obj(pdev, Pages_id);
+@@ -1134,7 +1145,7 @@ pdf_close(gx_device * dev)
+ {
+ int i;
+
+- for (i = 0; i < pdev->next_page; ++i)
++ for (i = 0; i < pdev->next_page; ++i)
+ pprintld1(s, "%ld 0 R\n", pdev->pages[i].Page->id);
+ }
+ pprintd1(s, "] /Count %d\n", pdev->next_page);
+diff --git a/base/gdevpdfb.c b/base/gdevpdfb.c
+--- a/base/gdevpdfb.c
++++ b/base/gdevpdfb.c
+@@ -260,8 +260,8 @@ pdf_copy_mono(gx_device_pdf *pdev,
+ * We don't have to worry about color space scaling: the color
+ * space is always a Device space.
+ */
+- code = pdf_color_space(pdev, &cs_value, NULL, pcs,
+- &writer.pin->color_spaces, in_line);
++ code = pdf_color_space_named(pdev, &cs_value, NULL, pcs,
++ &writer.pin->color_spaces, in_line, NULL, 0);
+ if (code < 0)
+ return code;
+ pcsvalue = &cs_value;
+@@ -410,8 +410,8 @@ pdf_copy_color_data(gx_device_pdf * pdev, const byte * base, int sourcex,
+ pdf_image_writer_init(piw);
+ pdev->ParamCompatibilityLevel = pdev->CompatibilityLevel;
+ if ((code = pdf_begin_write_image(pdev, piw, id, w, h, NULL, in_line)) < 0 ||
+- (code = pdf_color_space(pdev, &cs_value, NULL, pcs,
+- &piw->pin->color_spaces, in_line)) < 0 ||
++ (code = pdf_color_space_named(pdev, &cs_value, NULL, pcs,
++ &piw->pin->color_spaces, in_line, NULL, 0)) < 0 ||
+ (for_pattern < 2 || nbytes < 512000 ?
+ (code = psdf_setup_lossless_filters((gx_device_psdf *) pdev,
+ &piw->binary[0], (gs_pixel_image_t *)pim, false)) :
+diff --git a/base/gdevpdfc.c b/base/gdevpdfc.c
+--- a/base/gdevpdfc.c
++++ b/base/gdevpdfc.c
+@@ -345,7 +345,7 @@ pdf_separation_color_space(gx_device_pdf *pdev,
+
+ if ((code = cos_array_add(pca, cos_c_string_value(&v, csname))) < 0 ||
+ (code = cos_array_add_no_copy(pca, snames)) < 0 ||
+- (code = pdf_color_space(pdev, &v, &ranges, alt_space, pcsn, false)) < 0 ||
++ (code = pdf_color_space_named(pdev, &v, &ranges, alt_space, pcsn, false, NULL, 0)) < 0 ||
+ (code = cos_array_add(pca, &v)) < 0 ||
+ (code = pdf_function_scaled(pdev, pfn, ranges, &v)) < 0 ||
+ (code = cos_array_add(pca, &v)) < 0 ||
+@@ -472,8 +472,8 @@ pdf_indexed_color_space(gx_device_pdf *pdev, cos_value_t *pvalue,
+ * in PDF, unlike PostScript, the values from the lookup table are
+ * scaled automatically.
+ */
+- if ((code = pdf_color_space(pdev, pvalue, NULL, base_space,
+- &pdf_color_space_names, false)) < 0 ||
++ if ((code = pdf_color_space_named(pdev, pvalue, NULL, base_space,
++ &pdf_color_space_names, false, NULL, 0)) < 0 ||
+ (code = cos_array_add(pca,
+ cos_c_string_value(&v,
+ pdf_color_space_names.Indexed
+@@ -571,9 +571,9 @@ pdf_color_space_named(gx_device_pdf *pdev, cos_value_t *pvalue,
+ ) {
+ if (res_name != NULL)
+ return 0; /* Ignore .includecolorspace */
+- return pdf_color_space( pdev, pvalue, ppranges,
++ return pdf_color_space_named( pdev, pvalue, ppranges,
+ pcs->base_space,
+- pcsn, by_name);
++ pcsn, by_name, NULL, 0);
+ }
+ break;
+ default:
+@@ -832,7 +832,7 @@ pdf_color_space_named(gx_device_pdf *pdev, cos_value_t *pvalue,
+ csa->colorant_name, &name_string, &name_string_length);
+ if (code < 0)
+ return code;
+- code = pdf_color_space(pdev, &v_separation, NULL, csa->cspace, pcsn, false);
++ code = pdf_color_space_named(pdev, &v_separation, NULL, csa->cspace, pcsn, false, NULL, 0);
+ if (code < 0)
+ return code;
+ code = pdf_string_to_cos_name(pdev, name_string, name_string_length, &v_colorant_name);
+@@ -878,9 +878,9 @@ pdf_color_space_named(gx_device_pdf *pdev, cos_value_t *pvalue,
+ break;
+
+ case gs_color_space_index_Pattern:
+- if ((code = pdf_color_space(pdev, pvalue, ppranges,
++ if ((code = pdf_color_space_named(pdev, pvalue, ppranges,
+ pcs->base_space,
+- &pdf_color_space_names, false)) < 0 ||
++ &pdf_color_space_names, false, NULL, 0)) < 0 ||
+ (code = cos_array_add(pca,
+ cos_c_string_value(&v, "/Pattern"))) < 0 ||
+ (code = cos_array_add(pca, pvalue)) < 0
+@@ -957,16 +957,6 @@ pdf_color_space_named(gx_device_pdf *pdev, cos_value_t *pvalue,
+ return 0;
+ }
+
+-int
+-pdf_color_space(gx_device_pdf *pdev, cos_value_t *pvalue,
+- const gs_range_t **ppranges,
+- const gs_color_space *pcs,
+- const pdf_color_space_names_t *pcsn,
+- bool by_name)
+-{
+- return pdf_color_space_named(pdev, pvalue, ppranges, pcs, pcsn, by_name, NULL, 0);
+-}
+-
+ /* ---------------- Miscellaneous ---------------- */
+
+ /* Create colored and uncolored Pattern color spaces. */
+@@ -1018,7 +1008,7 @@ pdf_cs_Pattern_uncolored_hl(gx_device_pdf *pdev,
+ const gs_color_space *pcs, cos_value_t *pvalue)
+ {
+ /* Only for high level colors. */
+- return pdf_color_space(pdev, pvalue, NULL, pcs, &pdf_color_space_names, true);
++ return pdf_color_space_named(pdev, pvalue, NULL, pcs, &pdf_color_space_names, true, NULL, 0);
+ }
+
+ /* Set the ProcSets bits corresponding to an image color space. */
+diff --git a/base/gdevpdfe.c b/base/gdevpdfe.c
+--- a/base/gdevpdfe.c
++++ b/base/gdevpdfe.c
+@@ -24,7 +24,6 @@
+ #include "gdevpdfx.h"
+ #include "gdevpdfg.h"
+ #include "gdevpdfo.h"
+-#include "gdevpdtf.h"
+ #include "ConvertUTF.h"
+
+
+@@ -730,204 +729,12 @@ pdf_document_metadata(gx_device_pdf *pdev)
+ if (code < 0)
+ return code;
+ sprintf(buf, "%ld 0 R", pres->object->id);
+- cos_dict_put_c_key_object(pdev->Catalog, "/Metadata", pres->object);
++ code = cos_dict_put_c_key_object(pdev->Catalog, "/Metadata", pres->object);
++ if (code < 0)
++ return code;
+ }
+ return 0;
+ }
+
+ /* -------------------------------------------- */
+
+-/* Write Font metadata */
+-static int
+-pdf_write_font_metadata(gx_device_pdf *pdev, const pdf_base_font_t *pbfont,
+- const byte *digest, int digest_length)
+-{
+- char instance_uuid[40];
+- int code;
+- stream *s = pdev->strm;
+- gs_font_info_t info;
+- gs_font_base *pfont = pbfont->complete;
+-
+- if (pfont == NULL)
+- pfont = pbfont->copied;
+- /* Fixme: For True Type fonts need to get Coipyright, Owner from the TT data. */
+- pdf_make_uuid(digest, pdf_uuid_time(pdev), pdev->DocumentTimeSeq, instance_uuid, sizeof(instance_uuid));
+- code = pfont->procs.font_info((gs_font *)pfont, NULL,
+- (FONT_INFO_COPYRIGHT | FONT_INFO_NOTICE |
+- FONT_INFO_FAMILY_NAME | FONT_INFO_FULL_NAME),
+- &info);
+- if (code < 0)
+- return code;
+- pdf_xml_ins_beg(s, "xpacket");
+- pdf_xml_attribute_name(s, "begin");
+- pdf_xml_copy(s, dd);
+- pdf_xml_attribute_name(s, "id");
+- pdf_xml_attribute_value(s, "W5M0MpCehiHzreSzNTczkc9d");
+- pdf_xml_ins_end(s);
+- pdf_xml_newline(s);
+-
+- pdf_xml_copy(s, "<?adobe-xap-filters esc=\"CRLF\"?>\n");
+- pdf_xml_copy(s, "<x:xmpmeta xmlns:x='adobe:ns:meta/'"
+- " x:xmptk='XMP toolkit 2.9.1-13, framework 1.6'>\n");
+- {
+- pdf_xml_copy(s, "<rdf:RDF xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#' "
+- "xmlns:iX='http://ns.adobe.com/iX/1.0/'>\n");
+- {
+-
+- pdf_xml_tag_open_beg(s, "rdf:Description");
+- pdf_xml_attribute_name(s, "rdf:about");
+- pdf_xml_attribute_value(s, instance_uuid);
+- pdf_xml_attribute_name(s, "xmlns:xmp");
+- pdf_xml_attribute_value(s, "http://ns.adobe.com/xap/1.0/");
+- pdf_xml_tag_end(s);
+- {
+- pdf_xml_tag_open_beg(s, "xmp:Title");
+- pdf_xml_tag_end(s);
+- {
+- pdf_xml_tag_open(s, "rdf:Alt");
+- {
+- pdf_xml_tag_open_beg(s, "rdf:li");
+- pdf_xml_attribute_name(s, "xml:lang");
+- pdf_xml_attribute_value(s, "x-default");
+- pdf_xml_tag_end(s);
+- {
+- pdf_xml_data_write(s, pbfont->font_name.data, pbfont->font_name.size);
+- }
+- pdf_xml_tag_close(s, "rdf:li");
+- }
+- pdf_xml_tag_close(s, "rdf:Alt");
+- }
+- pdf_xml_tag_close(s, "xmp:Title");
+- }
+- pdf_xml_tag_close(s, "rdf:Description");
+- pdf_xml_newline(s);
+-
+-
+- pdf_xml_tag_open_beg(s, "rdf:Description");
+- pdf_xml_attribute_name(s, "rdf:about");
+- pdf_xml_attribute_value(s, instance_uuid);
+- pdf_xml_attribute_name(s, "xmlns:xmpRights");
+- pdf_xml_attribute_value(s, "http://ns.adobe.com/xap/1.0/rights/");
+- pdf_xml_tag_end(s);
+- if (info.members & FONT_INFO_COPYRIGHT) {
+- pdf_xml_tag_open_beg(s, "xmpRights:Copyright");
+- pdf_xml_tag_end(s);
+- {
+- pdf_xml_tag_open(s, "rdf:Alt");
+- {
+- pdf_xml_tag_open_beg(s, "rdf:li");
+- pdf_xml_attribute_name(s, "xml:lang");
+- pdf_xml_attribute_value(s, "x-default");
+- pdf_xml_tag_end(s);
+- {
+- pdf_xml_data_write(s, info.Copyright.data, info.Copyright.size);
+- }
+- pdf_xml_tag_close(s, "rdf:li");
+- }
+- pdf_xml_tag_close(s, "rdf:Alt");
+- }
+- pdf_xml_tag_close(s, "xmpRights:Copyright");
+-
+- /* Don't have an Owner, write Copyright instead. */
+- pdf_xml_tag_open_beg(s, "xmpRights:Owner");
+- pdf_xml_tag_end(s);
+- {
+- pdf_xml_tag_open(s, "rdf:Alt");
+- {
+- pdf_xml_tag_open_beg(s, "rdf:li");
+- pdf_xml_attribute_name(s, "xml:lang");
+- pdf_xml_attribute_value(s, "x-default");
+- pdf_xml_tag_end(s);
+- {
+- pdf_xml_data_write(s, info.Copyright.data, info.Copyright.size);
+- }
+- pdf_xml_tag_close(s, "rdf:li");
+- }
+- pdf_xml_tag_close(s, "rdf:Alt");
+- }
+- pdf_xml_tag_close(s, "xmpRights:Owner");
+- }
+- {
+- pdf_xml_tag_open_beg(s, "xmpRights:Marked");
+- pdf_xml_tag_end(s);
+- {
+- pdf_xml_string_write(s, "True");
+- }
+- pdf_xml_tag_close(s, "xmpRights:Marked");
+- }
+- if (info.members & FONT_INFO_NOTICE) {
+- pdf_xml_tag_open_beg(s, "xmpRights:UsageTerms");
+- pdf_xml_tag_end(s);
+- {
+- pdf_xml_tag_open(s, "rdf:Alt");
+- {
+- pdf_xml_tag_open_beg(s, "rdf:li");
+- pdf_xml_attribute_name(s, "xml:lang");
+- pdf_xml_attribute_value(s, "x-default");
+- pdf_xml_tag_end(s);
+- {
+- pdf_xml_data_write(s, info.Notice.data, info.Notice.size);
+- }
+- pdf_xml_tag_close(s, "rdf:li");
+- }
+- pdf_xml_tag_close(s, "rdf:Alt");
+- }
+- pdf_xml_tag_close(s, "xmpRights:UsageTerms");
+- }
+- pdf_xml_tag_close(s, "rdf:Description");
+- pdf_xml_newline(s);
+- }
+- pdf_xml_copy(s, "</rdf:RDF>\n");
+- }
+- pdf_xml_copy(s, "</x:xmpmeta>\n");
+-
+- pdf_xml_copy(s, " \n");
+- pdf_xml_copy(s, " \n");
+- pdf_xml_copy(s, "<?xpacket end='w'?>");
+- return 0;
+-}
+-
+-int
+-pdf_font_metadata(gx_device_pdf *pdev, const pdf_base_font_t *pbfont,
+- const byte *digest, int digest_length, gs_id *metadata_object_id)
+-{
+- /* Acrobat Distiller does not create font Metadata, and the ISO spec says
+- * only that files 'should' contain font Metadata. Attempts to include
+- * font metadata cause Acrobat to complain about XMP schemas (because
+- * the ISO spec uses non-existent tags).
+- * For now we disable writing of font Metadata
+- */
+- return 0;
+-
+- *metadata_object_id = gs_no_id;
+- if (pdev->CompatibilityLevel < 1.4)
+- return 0;
+- /* The PDF/A specification redss about
+- "embedded Type 0, Type 1, or TrueType font programs",
+- but we believe that "embedded Type 0 font programs"
+- do not exist.
+- We create Metadata for Type 1,2,42,9,11.
+- */
+- if (pdev->PDFA) {
+- pdf_resource_t *pres;
+- int code;
+- int options = DATA_STREAM_NOT_BINARY;
+-
+- if (pdev->EncryptMetadata)
+- options |= DATA_STREAM_ENCRYPT;
+- code = pdf_open_aside(pdev, resourceOther, gs_no_id, &pres, true, options);
+- if (code < 0)
+- return code;
+- code = pdf_write_font_metadata(pdev, pbfont, digest, digest_length);
+- if (code < 0)
+- return code;
+- code = pdf_close_aside(pdev);
+- if (code < 0)
+- return code;
+- code = COS_WRITE_OBJECT(pres->object, pdev);
+- if (code < 0)
+- return code;
+- *metadata_object_id = pres->object->id;
+- }
+- return 0;
+-}
+diff --git a/base/gdevpdfg.c b/base/gdevpdfg.c
+--- a/base/gdevpdfg.c
++++ b/base/gdevpdfg.c
+@@ -187,6 +187,8 @@ pdf_viewer_state_from_imager_state(gx_device_pdf * pdev,
+ pdf_viewer_state_from_imager_state_aux(&vs, pis);
+ gx_hld_save_color(pis, pdevc, &vs.saved_fill_color);
+ gx_hld_save_color(pis, pdevc, &vs.saved_stroke_color);
++ vs.fill_used_process_color = 0;
++ vs.stroke_used_process_color = 0;
+ pdf_load_viewer_state(pdev, &vs);
+ }
+
+@@ -376,8 +378,8 @@ pdf_reset_color(gx_device_pdf * pdev, const gs_imager_state * pis,
+ scn:
+ command = ppscc->setcolorn;
+ if (!gx_hld_saved_color_same_cspace(&temp, psc)) {
+- code = pdf_color_space(pdev, &cs_value, NULL, pcs,
+- &pdf_color_space_names, true);
++ code = pdf_color_space_named(pdev, &cs_value, NULL, pcs,
++ &pdf_color_space_names, true, NULL, 0);
+ /* fixme : creates redundant PDF objects. */
+ if (code == gs_error_rangecheck) {
+ /* The color space can't write to PDF. */
+@@ -812,6 +814,7 @@ pdf_write_spot_function(gx_device_pdf *pdev, const gx_ht_order *porder,
+ uint i;
+ int code = 0;
+
++ params.array_size = 0;
+ params.m = 2;
+ params.Domain = domain_spot;
+ params.n = 1;
+diff --git a/base/gdevpdfg.h b/base/gdevpdfg.h
+--- a/base/gdevpdfg.h
++++ b/base/gdevpdfg.h
+@@ -87,11 +87,6 @@ int pdf_cspace_init_Device(gs_memory_t *mem, gs_color_space **ppcs, int num_comp
+ * to be scaled (to convert a CIEBased space to ICCBased), store a pointer
+ * to the ranges in *ppranges, otherwise set *ppranges to 0.
+ */
+-int pdf_color_space(gx_device_pdf *pdev, cos_value_t *pvalue,
+- const gs_range_t **ppranges,
+- const gs_color_space *pcs,
+- const pdf_color_space_names_t *pcsn,
+- bool by_name);
+ int pdf_color_space_named(gx_device_pdf *pdev, cos_value_t *pvalue,
+ const gs_range_t **ppranges,
+ const gs_color_space *pcs,
+@@ -346,5 +341,3 @@ int pdf_copy_color_data(gx_device_pdf * pdev, const byte * base, int sourcex,
+
+ /* Write metadata */
+ int pdf_document_metadata(gx_device_pdf *pdev);
+-int pdf_font_metadata(gx_device_pdf *pdev, const pdf_base_font_t *pbfont,
+- const byte *digest, int digest_length, gs_id *metadata_object_id);
+diff --git a/base/gdevpdfi.c b/base/gdevpdfi.c
+--- a/base/gdevpdfi.c
++++ b/base/gdevpdfi.c
+@@ -369,8 +369,11 @@ pdf_begin_typed_image_impl(gx_device_pdf *pdev, const gs_imager_state * pis,
+ )
+ goto nyi;
+ }
+- in_line = context == PDF_IMAGE_DEFAULT &&
+- can_write_image_in_line(pdev, pim1);
++ /* If image is not type 3X and we can write in-line then make it so */
++
++ in_line = context == PDF_IMAGE_DEFAULT &&
++ can_write_image_in_line(pdev, pim1);
++
+ image[0].type1 = *pim1;
+ break;
+ }
+@@ -653,9 +656,9 @@ pdf_begin_typed_image_impl(gx_device_pdf *pdev, const gs_imager_state * pis,
+ */
+ cos_c_string_value(&cs_value, names->DeviceRGB);
+ } else {
+- code = pdf_color_space(pdev, &cs_value, &pranges,
++ code = pdf_color_space_named(pdev, &cs_value, &pranges,
+ pcs,
+- names, in_line);
++ names, in_line, NULL, 0);
+ if (code < 0)
+ convert_to_process_colors = true;
+ }
+@@ -1326,8 +1329,11 @@ pdf_image3x_make_mcde(gx_device *dev, const gs_imager_state *pis,
+ if (code < 0)
+ return code;
+ }
+- return cos_dict_put_c_key_object(cos_stream_dict(pmcs), "/SMask",
+- pmie->writer.pres->object);
++/* Don't put SMask here because pmie->writer.pres->object may be substituted
++ * after the image stream is accummulated. pdf_end_and_do_image will set
++ * SMask with the right value. Bug 690345.
++ */
++ return 0;
+ }
+
+ pdf_resource_t *pdf_substitute_pattern(pdf_resource_t *pres)
+diff --git a/base/gdevpdfj.c b/base/gdevpdfj.c
+--- a/base/gdevpdfj.c
++++ b/base/gdevpdfj.c
+@@ -14,7 +14,6 @@
+ /* $Id$ */
+ /* Image-writing utilities for pdfwrite driver */
+ #include "memory_.h"
+-#include "string_.h"
+ #include "gx.h"
+ #include "gserrors.h"
+ #include "gdevpdfx.h"
+@@ -24,6 +23,7 @@
+ #include "gsiparm4.h"
+ #include "gdevpsds.h"
+ #include "spngpx.h"
++#include <stdlib.h> /* for atoi */
+
+ #define CHECK(expr)\
+ BEGIN if ((code = (expr)) < 0) return code; END
+@@ -445,9 +445,32 @@ pdf_end_image_binary(gx_device_pdf *pdev, pdf_image_writer *piw, int data_h)
+ else
+ code = psdf_end_binary(&piw->binary[0]);
+ /* If the image ended prematurely, update the Height. */
+- if (data_h != piw->height)
+- code1 = cos_dict_put_c_key_int(cos_stream_dict(piw->data),
++ if (data_h != piw->height) {
++ char data[255];
++ int OutHeight;
++ cos_value_t *value;
++ value = (cos_value_t *)cos_dict_find(cos_stream_dict(piw->data),
++ (const byte *)piw->pin->Height, strlen(piw->pin->Height));
++ if (!value || value->contents.chars.size > 255)
++ return(gs_error_rangecheck);
++ strncpy((char *)&data, (const char *)value->contents.chars.data, value->contents.chars.size);
++ data[value->contents.chars.size] = 0x00;
++ OutHeight = atoi(data);
++ if (OutHeight != piw->height) {
++ /* Looks like we are downsampling, so we can't use the number
++ * of rows of data actually received, we must divide those by
++ * the sampling factor.
++ */
++ float factor = (float)OutHeight / piw->height;
++ OutHeight = (int)(factor * data_h);
++ code1 = cos_dict_put_c_key_int(cos_stream_dict(piw->data),
++ piw->pin->Height, OutHeight);
++ } else {
++
++ code1 = cos_dict_put_c_key_int(cos_stream_dict(piw->data),
+ piw->pin->Height, data_h);
++ }
++ }
+ return code < 0 ? code : code1;
+ }
+
+diff --git a/base/gdevpdfk.c b/base/gdevpdfk.c
+--- a/base/gdevpdfk.c
++++ b/base/gdevpdfk.c
+@@ -255,8 +255,8 @@ pdf_make_iccbased(gx_device_pdf *pdev, cos_array_t *pca, int ncomps,
+ case gs_color_space_index_DeviceCMYK:
+ break; /* implicit (default) */
+ default:
+- if ((code = pdf_color_space(pdev, &v, NULL, pcs_alt,
+- &pdf_color_space_names, false)) < 0 ||
++ if ((code = pdf_color_space_named(pdev, &v, NULL, pcs_alt,
++ &pdf_color_space_names, false, NULL, 0)) < 0 ||
+ (code = cos_dict_put_c_key(cos_stream_dict(pcstrm), "/Alternate",
+ &v)) < 0
+ )
+diff --git a/base/gdevpdfm.c b/base/gdevpdfm.c
+--- a/base/gdevpdfm.c
++++ b/base/gdevpdfm.c
+@@ -15,7 +15,6 @@
+ /* pdfmark processing for PDF-writing driver */
+ #include "math_.h"
+ #include "memory_.h"
+-#include "string_.h"
+ #include "gx.h"
+ #include "gserrors.h"
+ #include "gsutil.h" /* for bytes_compare */
+@@ -108,7 +107,8 @@ pdfmark_page_number(gx_device_pdf * pdev, const gs_param_string * pnstr)
+ {
+ int page = pdev->next_page + 1;
+
+- if (pnstr->data == 0);
++ if (pnstr->data == 0)
++ page -= 1;
+ else if (pdf_key_eq(pnstr, "/Next"))
+ ++page;
+ else if (pdf_key_eq(pnstr, "/Prev"))
+diff --git a/base/gdevpdfo.c b/base/gdevpdfo.c
+--- a/base/gdevpdfo.c
++++ b/base/gdevpdfo.c
+@@ -14,7 +14,6 @@
+ /* $Id$ */
+ /* Cos object support */
+ #include "memory_.h"
+-#include "string_.h"
+ #include "gx.h"
+ #include "gserrors.h"
+ #include "gsparam.h"
+diff --git a/base/gdevpdfp.c b/base/gdevpdfp.c
+--- a/base/gdevpdfp.c
++++ b/base/gdevpdfp.c
+@@ -14,7 +14,6 @@
+ /* $Id$ */
+ /* Get/put parameters for PDF-writing driver */
+ #include "memory_.h"
+-#include "string_.h"
+ #include "gx.h"
+ #include "gserrors.h"
+ #include "gdevpdfx.h"
+@@ -109,6 +108,8 @@ static const gs_param_item_t pdf_param_items[] = {
+ pi("SetPageSize", gs_param_type_bool, SetPageSize),
+ pi("RotatePages", gs_param_type_bool, RotatePages),
+ pi("FitPages", gs_param_type_bool, FitPages),
++ pi("CenterPages", gs_param_type_bool, CenterPages),
++ pi("DoNumCopies", gs_param_type_bool, DoNumCopies),
+ #undef pi
+ gs_param_item_end
+ };
+@@ -194,12 +195,10 @@ gdev_pdf_get_params(gx_device * dev, gs_param_list * plist)
+ float cl = (float)pdev->CompatibilityLevel;
+ int code;
+ int cdv = CoreDistVersion;
+- int EmbedFontObjects = 1;
+
+ pdev->ParamCompatibilityLevel = cl;
+ code = gdev_psdf_get_params(dev, plist);
+ if (code < 0 ||
+- (code = param_write_int(plist, ".EmbedFontObjects", &EmbedFontObjects)) < 0 ||
+ (code = param_write_int(plist, "CoreDistVersion", &cdv)) < 0 ||
+ (code = param_write_float(plist, "CompatibilityLevel", &cl)) < 0 ||
+ (pdev->is_ps2write && (code = param_write_string(plist, "OPDFReadProcsetPath", &pdev->OPDFReadProcsetPath)) < 0) ||
+diff --git a/base/gdevpdfr.c b/base/gdevpdfr.c
+--- a/base/gdevpdfr.c
++++ b/base/gdevpdfr.c
+@@ -14,7 +14,6 @@
+ /* $Id$ */
+ /* Named object pdfmark processing */
+ #include "memory_.h"
+-#include "string_.h"
+ #include "gx.h"
+ #include "gserrors.h"
+ #include "gsutil.h" /* for bytes_compare */
+diff --git a/base/gdevpdft.c b/base/gdevpdft.c
+--- a/base/gdevpdft.c
++++ b/base/gdevpdft.c
+@@ -103,8 +103,8 @@ pdf_make_group_dict(gx_device_pdf * pdev, const gs_pdf14trans_params_t * pparams
+ if (gstate != NULL) {
+ const gs_color_space *cs = gstate->color_space;
+
+- code = pdf_color_space(pdev, &cs_value, NULL, cs,
+- &pdf_color_space_names, false);
++ code = pdf_color_space_named(pdev, &cs_value, NULL, cs,
++ &pdf_color_space_names, false, NULL, 0);
+ if (code < 0)
+ return code;
+ code = cos_dict_put_c_key(group_dict, "/CS", &cs_value);
+@@ -211,6 +211,8 @@ pdf_end_transparency_group(gs_imager_state * pis, gx_device_pdf * pdev)
+ {
+ int bottom = (pdev->ResourcesBeforeUsage ? 1 : 0);
+
++ if (!is_in_page(pdev))
++ return 0; /* corresponds to check in pdf_begin_transparency_group */
+ if (pdev->image_with_SMask) {
+ /* An internal group for the image implementation.
+ See pdf_begin_transparency_group. */
+@@ -396,6 +398,7 @@ gdev_pdf_begin_transparency_mask(gx_device *dev,
+
+ int
+ gdev_pdf_end_transparency_mask(gx_device *dev,
++ gs_imager_state *pis,
+ gs_transparency_mask_t **pptm)
+ {
+ return 0;
+diff --git a/base/gdevpdfu.c b/base/gdevpdfu.c
+--- a/base/gdevpdfu.c
++++ b/base/gdevpdfu.c
+@@ -15,7 +15,6 @@
+ /* Output utilities for PDF-writing driver */
+ #include "memory_.h"
+ #include "jpeglib_.h" /* for sdct.h */
+-#include "string_.h"
+ #include "gx.h"
+ #include "gserrors.h"
+ #include "gscdefs.h"
+@@ -304,7 +303,7 @@ pdf_open_document(gx_device_pdf * pdev)
+ int width = (int)(pdev->width * 72.0 / pdev->HWResolution[0] + 0.5);
+ int height = (int)(pdev->height * 72.0 / pdev->HWResolution[1] + 0.5);
+
+- stream_write(s, (byte *)"%!PS-Adobe-2.0\r", 15);
++ stream_write(s, (byte *)"%!\r", 3);
+ sprintf(BBox, "%%%%BoundingBox: 0 0 %d %d\r", width, height);
+ stream_write(s, (byte *)BBox, strlen(BBox));
+ if(pdev->SetPageSize)
+@@ -313,6 +312,8 @@ pdf_open_document(gx_device_pdf * pdev)
+ stream_puts(s, "/RotatePages true def\n");
+ if(pdev->FitPages)
+ stream_puts(s, "/FitPages true def\n");
++ if(pdev->CenterPages)
++ stream_puts(s, "/CenterPages true def\n");
+ if (pdev->params.CompressPages || pdev->CompressEntireFile) {
+ /* When CompressEntireFile is true and ASCII85EncodePages is false,
+ the ASCII85Encode filter is applied, rather one may expect the opposite.
+@@ -975,7 +976,10 @@ pdf_print_resource_statistics(gx_device_pdf * pdev)
+ long
+ pdf_open_separate(gx_device_pdf * pdev, long id)
+ {
+- pdf_open_document(pdev);
++ int code;
++ code = pdf_open_document(pdev);
++ if (code < 0)
++ return code;
+ pdev->asides.save_strm = pdev->strm;
+ pdev->strm = pdev->asides.strm;
+ return pdf_open_obj(pdev, id);
+@@ -1214,7 +1218,7 @@ pdf_write_and_free_all_resource_objects(gx_device_pdf *pdev)
+ * Sets page->{procsets, resource_ids[]}.
+ */
+ int
+-pdf_store_page_resources(gx_device_pdf *pdev, pdf_page_t *page)
++pdf_store_page_resources(gx_device_pdf *pdev, pdf_page_t *page, bool clear_usage)
+ {
+ int i;
+
+@@ -1243,7 +1247,8 @@ pdf_store_page_resources(gx_device_pdf *pdev, pdf_page_t *page)
+ }
+ pprints1(s, "/%s\n", pres->rname);
+ pprintld1(s, "%ld 0 R", id);
+- pres->where_used -= pdev->used_mask;
++ if (clear_usage)
++ pres->where_used -= pdev->used_mask;
+ }
+ }
+ }
+@@ -1418,8 +1423,10 @@ pdf_unclip(gx_device_pdf * pdev)
+ void
+ pdf_store_default_Producer(char buf[PDF_MAX_PRODUCER])
+ {
+- sprintf(buf, ((gs_revision % 100) == 0 ? "(%s %1.1f)" : "(%s %1.2f)"),
+- gs_product, gs_revision / 100.0);
++ if ((gs_revision % 100) == 0)
++ sprintf(buf, "(%s %1.1f)", gs_product, gs_revision / 100.0);
++ else
++ sprintf(buf, "(%s %1.2f)", gs_product, gs_revision / 100.0);
+ }
+
+ /* Write matrix values. */
+diff --git a/base/gdevpdfv.c b/base/gdevpdfv.c
+--- a/base/gdevpdfv.c
++++ b/base/gdevpdfv.c
+@@ -426,8 +426,8 @@ pdf_put_colored_pattern(gx_device_pdf *pdev, const gx_drawing_color *pdc,
+ * We don't have to worry about color space scaling: the color
+ * space is always a Device space.
+ */
+- code = pdf_color_space(pdev, &cs_value, NULL, pcs_Device,
+- &pdf_color_space_names, true);
++ code = pdf_color_space_named(pdev, &cs_value, NULL, pcs_Device,
++ &pdf_color_space_names, true, NULL, 0);
+ if (code < 0)
+ return code;
+ if (!have_pattern_streams) {
+@@ -494,8 +494,8 @@ pdf_put_shading_common(cos_dict_t *pscd, const gs_shading_t *psh,
+ if (code < 0 ||
+ (psh->params.AntiAlias &&
+ (code = cos_dict_put_c_strings(pscd, "/AntiAlias", "true")) < 0) ||
+- (code = pdf_color_space(pscd->pdev, &cs_value, ppranges, pcs,
+- &pdf_color_space_names, false)) < 0 ||
++ (code = pdf_color_space_named(pscd->pdev, &cs_value, ppranges, pcs,
++ &pdf_color_space_names, false, NULL, 0)) < 0 ||
+ (code = cos_dict_put_c_key(pscd, "/ColorSpace", &cs_value)) < 0
+ )
+ return code;
+diff --git a/base/gdevpdfx.h b/base/gdevpdfx.h
+--- a/base/gdevpdfx.h
++++ b/base/gdevpdfx.h
+@@ -653,6 +653,8 @@ struct gx_device_pdf_s {
+ bool SetPageSize;
+ bool RotatePages;
+ bool FitPages;
++ bool CenterPages;
++ bool DoNumCopies;
+ };
+
+ #define is_in_page(pdev)\
+@@ -887,7 +889,7 @@ int pdf_write_and_free_all_resource_objects(gx_device_pdf *pdev);
+ * Store the resource sets for a content stream (page or XObject).
+ * Sets page->{procsets, resource_ids[], fonts_id}.
+ */
+-int pdf_store_page_resources(gx_device_pdf *pdev, pdf_page_t *page);
++int pdf_store_page_resources(gx_device_pdf *pdev, pdf_page_t *page, bool clear_usage);
+
+ /* Copy data from a temporary file to a stream. */
+ void pdf_copy_data(stream *s, FILE *file, long count, stream_arcfour_state *ss);
+diff --git a/base/gdevpdtb.c b/base/gdevpdtb.c
+--- a/base/gdevpdtb.c
++++ b/base/gdevpdtb.c
+@@ -15,7 +15,6 @@
+ /* BaseFont implementation for pdfwrite */
+ #include "memory_.h"
+ #include "ctype_.h"
+-#include "string_.h"
+ #include "gx.h"
+ #include "gserrors.h"
+ #include "gsutil.h" /* for bytes_compare */
+@@ -27,7 +26,6 @@
+ #include "gdevpdfx.h"
+ #include "gdevpdfo.h"
+ #include "gdevpdtb.h"
+-#include "gdevpdfg.h"
+ #include "gdevpdtf.h"
+ #include "smd5.h"
+
+@@ -38,7 +36,7 @@
+ * TrueType are subsetted. We do the latter, except that we always
+ * subset large TrueType fonts.
+ */
+-#define MAX_NO_SUBSET_GLYPHS 500 /* arbitrary */
++#define MAX_NO_SUBSET_GLYPHS 4096 /* arbitrary */
+
+ /* ---------------- Private ---------------- */
+
+@@ -632,17 +630,6 @@ pdf_write_embedded_font(gx_device_pdf *pdev, pdf_base_font_t *pbfont, font_type
+ return code;
+ }
+ code = pdf_end_fontfile(pdev, &writer);
+- if (pdev->PDFA && code >= 0) {
+- gs_id metadata_object_id;
+-
+- code = pdf_font_metadata(pdev, pbfont, digest, sizeof(digest), &metadata_object_id);
+- if (metadata_object_id && code >= 0) {
+- char buf[20];
+-
+- sprintf(buf, "%ld 0 R", metadata_object_id);
+- code = cos_dict_put_string_copy(*ppcd, "/Metadata", buf);
+- }
+- }
+ break;
+
+ default:
+diff --git a/base/gdevpdtc.c b/base/gdevpdtc.c
+--- a/base/gdevpdtc.c
++++ b/base/gdevpdtc.c
+@@ -14,7 +14,6 @@
+ /* $Id$ */
+ /* Composite and CID-based text processing for pdfwrite. */
+ #include "memory_.h"
+-#include "string_.h"
+ #include "gx.h"
+ #include "gserrors.h"
+ #include "gxfcmap.h"
+@@ -254,6 +253,10 @@ attach_cmap_resource(gx_device_pdf *pdev, pdf_font_resource_t *pdfont,
+ pdf_resource_t *pcmres = 0; /* CMap */
+ int code;
+
++ /* Make sure cmap names is properly initialised. Silences Coverity warning */
++ if (!pcmn)
++ return_error(gs_error_unknownerror);
++
+ /*
+ * If the CMap isn't standard, write it out if necessary.
+ */
+@@ -324,6 +327,12 @@ attach_cmap_resource(gx_device_pdf *pdev, pdf_font_resource_t *pdfont,
+ pdfont->u.type0.CMapName.data = chars;
+ pdfont->u.type0.CMapName.size = size;
+ } else {
++ if (!*pcmn)
++ /* Should not be possible, if *pcmn is NULL then either
++ * is_identity is true or we create pcmres.
++ */
++ return_error(gs_error_invalidfont);
++
+ sprintf(pdfont->u.type0.Encoding_name, "/%s", *pcmn);
+ pdfont->u.type0.CMapName.data = (const byte *)*pcmn;
+ pdfont->u.type0.CMapName.size = strlen(*pcmn);
+@@ -626,6 +635,10 @@ scan_cmap_text(pdf_text_enum_t *pte, void *vbuf)
+ pte->text.operation = save_op;
+ }
+ pte->current_font = subfont0;
++ if (!subfont0 || !pdsubf0)
++ /* This should be impossible */
++ return_error(gs_error_invalidfont);
++
+ code = gs_matrix_multiply(&subfont0->FontMatrix, &font->FontMatrix, &m3);
+ /* We thought that it should be gs_matrix_multiply(&font->FontMatrix, &subfont0->FontMatrix, &m3); */
+ if (code < 0)
+diff --git a/base/gdevpdte.c b/base/gdevpdte.c
+--- a/base/gdevpdte.c
++++ b/base/gdevpdte.c
+@@ -16,7 +16,6 @@
+
+ #include "math_.h"
+ #include "memory_.h"
+-#include "string_.h"
+ #include "gx.h"
+ #include "gserrors.h"
+ #include "gsutil.h"
+diff --git a/base/gdevpdtf.c b/base/gdevpdtf.c
+--- a/base/gdevpdtf.c
++++ b/base/gdevpdtf.c
+@@ -14,7 +14,6 @@
+ /* $Id$ */
+ /* Font and CMap resource implementation for pdfwrite text */
+ #include "memory_.h"
+-#include "string_.h"
+ #include "gx.h"
+ #include "gserrors.h"
+ #include "gsutil.h" /* for bytes_compare */
+diff --git a/base/gdevpdti.c b/base/gdevpdti.c
+--- a/base/gdevpdti.c
++++ b/base/gdevpdti.c
+@@ -14,7 +14,6 @@
+ /* $Id$ */
+ /* Bitmap font implementation for pdfwrite */
+ #include "memory_.h"
+-#include "string_.h"
+ #include "gx.h"
+ #include "gxpath.h"
+ #include "gserrors.h"
+diff --git a/base/gdevpdtt.c b/base/gdevpdtt.c
+--- a/base/gdevpdtt.c
++++ b/base/gdevpdtt.c
+@@ -328,13 +328,19 @@ gdev_pdf_text_begin(gx_device * dev, gs_imager_state * pis,
+ /* Track the dominant text rotation. */
+ {
+ gs_matrix tmat;
++ gs_point p;
+ int i;
+
+- gs_matrix_multiply(&font->FontMatrix, &ctm_only(pis), &tmat);
+- if (is_xxyy(&tmat))
+- i = (tmat.xx >= 0 ? 0 : 2);
+- else if (is_xyyx(&tmat))
+- i = (tmat.xy >= 0 ? 1 : 3);
++ gs_matrix_multiply(&font->FontMatrix, &ctm_only(pis), &tmat);
++ gs_distance_transform(1, 0, &tmat, &p);
++ if (p.x > fabs(p.y))
++ i = 0;
++ else if (p.x < -fabs(p.y))
++ i = 2;
++ else if (p.y > fabs(p.x))
++ i = 1;
++ else if (p.y < -fabs(p.x))
++ i = 3;
+ else
+ i = 4;
+ pdf_current_page(pdev)->text_rotation.counts[i] += text->size;
+@@ -734,7 +740,7 @@ pdf_check_encoding_compatibility(const pdf_font_resource_t *pdfont,
+ }
+
+ /*
+- * Check the Encoding has listed glyphs.
++ * Check whether the Encoding has listed glyphs.
+ */
+ static bool
+ pdf_check_encoding_has_glyphs(const pdf_font_resource_t *pdfont,
+@@ -945,7 +951,9 @@ pdf_obtain_cidfont_resource(gx_device_pdf *pdev, gs_font *subfont,
+ {
+ int code = 0;
+
+- pdf_attached_font_resource(pdev, subfont, ppdsubf, NULL, NULL, NULL, NULL);
++ code = pdf_attached_font_resource(pdev, subfont, ppdsubf, NULL, NULL, NULL, NULL);
++ if (code < 0)
++ return code;
+ if (*ppdsubf != NULL) {
+ const gs_font_base *cfont = pdf_font_resource_font(*ppdsubf, false);
+
+@@ -1636,7 +1644,9 @@ pdf_obtain_font_resource_encoded(gx_device_pdf *pdev, gs_font *font,
+ same_encoding = ((base_font->procs.same_font(base_font, font,
+ FONT_SAME_ENCODING) & FONT_SAME_ENCODING) != 0);
+ /* Find or make font resource. */
+- pdf_attached_font_resource(pdev, base_font, ppdfont, NULL, NULL, NULL, NULL);
++ code = pdf_attached_font_resource(pdev, base_font, ppdfont, NULL, NULL, NULL, NULL);
++ if (code < 0)
++ return code;
+ if (*ppdfont != NULL && base_font != font) {
+ if (pdfont_not_allowed == *ppdfont)
+ *ppdfont = NULL;
+diff --git a/base/gdevpdtw.c b/base/gdevpdtw.c
+--- a/base/gdevpdtw.c
++++ b/base/gdevpdtw.c
+@@ -510,6 +510,12 @@ pdf_write_contents_cid2(gx_device_pdf *pdev, pdf_font_resource_t *pdfont)
+ }
+ }
+
++ if (map_id == 0 && pdev->PDFA) {
++ code = stream_puts(pdev->strm, "/CIDToGIDMap /Identity\n");
++ if (code < 0)
++ return code;
++ }
++
+ code = write_contents_cid_common(pdev, pdfont, 2);
+ if (code < 0)
+ return code;
+diff --git a/base/gdevprn.c b/base/gdevprn.c
+--- a/base/gdevprn.c
++++ b/base/gdevprn.c
+@@ -973,9 +973,7 @@ gdev_prn_colors_used(gx_device *dev, int y, int height,
+ gx_device_clist_writer *cldev;
+
+ /* If this isn't a banded device, return default values. */
+- if (dev_proc(dev, get_bits_rectangle) !=
+- gs_clist_device_procs.get_bits_rectangle
+- ) {
++ if (dev_proc(dev, open_device) != gs_clist_device_procs.open_device) {
+ *range_start = 0;
+ colors_used->or = ((gx_color_index)1 << dev->color_info.depth) - 1;
+ return dev->height;
+diff --git a/base/gdevprn.h b/base/gdevprn.h
+--- a/base/gdevprn.h
++++ b/base/gdevprn.h
+@@ -406,10 +406,24 @@ extern const gx_device_procs prn_std_procs;
+ (float)((rm) * 72.0), (float)((tm) * 72.0)\
+ ),\
+ prn_device_body_rest_(print_page)
++#define prn_device_margins_stype_body(dtype, procs, dname, stype, w10, h10, xdpi, ydpi, lo, to, lm, bm, rm, tm, ncomp, depth, mg, mc, dg, dc, print_page)\
++ std_device_full_body_type(dtype, &procs, dname, stype,\
++ (int)((float)(w10) * (xdpi) / 10 + 0.5),\
++ (int)((float)(h10) * (ydpi) / 10 + 0.5),\
++ xdpi, ydpi,\
++ ncomp, depth, mg, mc, dg, dc,\
++ (float)(-(lo) * (xdpi)), (float)(-(to) * (ydpi)),\
++ (float)((lm) * 72.0), (float)((bm) * 72.0),\
++ (float)((rm) * 72.0), (float)((tm) * 72.0)\
++ ),\
++ prn_device_body_rest_(print_page)
+
+ #define prn_device_body(dtype, procs, dname, w10, h10, xdpi, ydpi, lm, bm, rm, tm, ncomp, depth, mg, mc, dg, dc, print_page)\
+ prn_device_margins_body(dtype, procs, dname, w10, h10, xdpi, ydpi,\
+ lm, tm, lm, bm, rm, tm, ncomp, depth, mg, mc, dg, dc, print_page)
++#define prn_device_stype_body(dtype, procs, dname, stype, w10, h10, xdpi, ydpi, lm, bm, rm, tm, ncomp, depth, mg, mc, dg, dc, print_page)\
++ prn_device_margins_stype_body(dtype, procs, dname, stype, w10, h10, xdpi, ydpi,\
++ lm, tm, lm, bm, rm, tm, ncomp, depth, mg, mc, dg, dc, print_page)
+
+ #define prn_device_margins_body_extended(dtype, procs, dname, w10, h10, xdpi, ydpi, lo, to, lm, bm, rm, tm, mcomp, ncomp, pol, depth, gi, mg, mc, dg, dc, ef, cn, print_page)\
+ std_device_full_body_type_extended(dtype, &procs, dname, &st_device_printer,\
+diff --git a/base/gdevps.c b/base/gdevps.c
+--- a/base/gdevps.c
++++ b/base/gdevps.c
+@@ -15,7 +15,6 @@
+ /* PostScript-writing driver */
+ #include "math_.h"
+ #include "memory_.h"
+-#include "string_.h"
+ #include "time_.h"
+ #include "gx.h"
+ #include "gserrors.h"
+diff --git a/base/gdevpsdi.c b/base/gdevpsdi.c
+--- a/base/gdevpsdi.c
++++ b/base/gdevpsdi.c
+@@ -132,50 +132,52 @@ choose_DCT_params(gx_device *pdev, const gs_color_space *pcs,
+ set_linear_color_bits_mask_shift((gx_device *)&mdev);
+ mdev.color_info.separable_and_linear = GX_CINFO_SEP_LIN;
+
+- /* Check for an RGB-like color space.
+- To recognize that we make a matrix as it were a linear operator,
+- suppress an ununiformity by subtracting the image of {0,0,0},
+- and then check for giagonal domination. */
+- cc.paint.values[0] = cc.paint.values[1] = cc.paint.values[2] = MIN_FLOAT;
+- convert_color((gx_device *)&mdev, pcs, pis, &cc, c[3]);
+- cc.paint.values[0] = MAX_FLOAT; cc.paint.values[1] = MIN_FLOAT; cc.paint.values[2] = MIN_FLOAT;
+- convert_color((gx_device *)&mdev, pcs, pis, &cc, c[0]);
+- cc.paint.values[0] = MIN_FLOAT; cc.paint.values[1] = MAX_FLOAT; cc.paint.values[2] = MIN_FLOAT;
+- convert_color((gx_device *)&mdev, pcs, pis, &cc, c[1]);
+- cc.paint.values[0] = MIN_FLOAT; cc.paint.values[1] = MIN_FLOAT; cc.paint.values[2] = MAX_FLOAT;
+- convert_color((gx_device *)&mdev, pcs, pis, &cc, c[2]);
+- c[0][0] -= c[3][0]; c[0][1] -= c[3][1]; c[0][2] -= c[3][2];
+- c[1][0] -= c[3][0]; c[1][1] -= c[3][1]; c[1][2] -= c[3][2];
+- c[2][0] -= c[3][0]; c[2][1] -= c[3][1]; c[2][2] -= c[3][2];
+- c[0][0] = any_abs(c[0][0]); c[0][1] = any_abs(c[0][1]); c[0][2] = any_abs(c[0][2]);
+- c[1][0] = any_abs(c[1][0]); c[1][1] = any_abs(c[1][1]); c[1][2] = any_abs(c[1][2]);
+- c[2][0] = any_abs(c[2][0]); c[2][1] = any_abs(c[2][1]); c[2][2] = any_abs(c[2][2]);
+- if (c[0][0] * domination > c[0][1] && c[0][0] * domination > c[0][2] &&
+- c[1][1] * domination > c[1][0] && c[1][1] * domination > c[1][2] &&
+- c[2][2] * domination > c[2][0] && c[2][2] * domination > c[2][1]) {
+- /* Yes, it looks like an RGB color space.
+- Replace ColorTransform with 1. */
+- code = param_write_int((gs_param_list *)list, "ColorTransform", &one);
+- if (code < 0)
+- return code;
+- goto done;
+- }
++ if (pis) {
++ /* Check for an RGB-like color space.
++ To recognize that we make a matrix as it were a linear operator,
++ suppress an ununiformity by subtracting the image of {0,0,0},
++ and then check for giagonal domination. */
++ cc.paint.values[0] = cc.paint.values[1] = cc.paint.values[2] = MIN_FLOAT;
++ convert_color((gx_device *)&mdev, pcs, pis, &cc, c[3]);
++ cc.paint.values[0] = MAX_FLOAT; cc.paint.values[1] = MIN_FLOAT; cc.paint.values[2] = MIN_FLOAT;
++ convert_color((gx_device *)&mdev, pcs, pis, &cc, c[0]);
++ cc.paint.values[0] = MIN_FLOAT; cc.paint.values[1] = MAX_FLOAT; cc.paint.values[2] = MIN_FLOAT;
++ convert_color((gx_device *)&mdev, pcs, pis, &cc, c[1]);
++ cc.paint.values[0] = MIN_FLOAT; cc.paint.values[1] = MIN_FLOAT; cc.paint.values[2] = MAX_FLOAT;
++ convert_color((gx_device *)&mdev, pcs, pis, &cc, c[2]);
++ c[0][0] -= c[3][0]; c[0][1] -= c[3][1]; c[0][2] -= c[3][2];
++ c[1][0] -= c[3][0]; c[1][1] -= c[3][1]; c[1][2] -= c[3][2];
++ c[2][0] -= c[3][0]; c[2][1] -= c[3][1]; c[2][2] -= c[3][2];
++ c[0][0] = any_abs(c[0][0]); c[0][1] = any_abs(c[0][1]); c[0][2] = any_abs(c[0][2]);
++ c[1][0] = any_abs(c[1][0]); c[1][1] = any_abs(c[1][1]); c[1][2] = any_abs(c[1][2]);
++ c[2][0] = any_abs(c[2][0]); c[2][1] = any_abs(c[2][1]); c[2][2] = any_abs(c[2][2]);
++ if (c[0][0] * domination > c[0][1] && c[0][0] * domination > c[0][2] &&
++ c[1][1] * domination > c[1][0] && c[1][1] * domination > c[1][2] &&
++ c[2][2] * domination > c[2][0] && c[2][2] * domination > c[2][1]) {
++ /* Yes, it looks like an RGB color space.
++ Replace ColorTransform with 1. */
++ code = param_write_int((gs_param_list *)list, "ColorTransform", &one);
++ if (code < 0)
++ return code;
++ goto done;
++ }
+
+- /* Check for a Lab-like color space.
+- Colors {v,0,0} should map to grays. */
+- cc.paint.values[0] = MAX_FLOAT; cc.paint.values[1] = cc.paint.values[2] = 0;
+- convert_color((gx_device *)&mdev, pcs, pis, &cc, c[0]);
+- cc.paint.values[0] /= 2;
+- convert_color((gx_device *)&mdev, pcs, pis, &cc, c[1]);
+- cc.paint.values[0] /= 2;
+- convert_color((gx_device *)&mdev, pcs, pis, &cc, c[2]);
+- c[0][1] -= c[0][0]; c[0][2] -= c[0][0];
+- c[1][1] -= c[1][0]; c[1][2] -= c[1][0];
+- c[2][1] -= c[2][0]; c[2][2] -= c[2][0];
+- c[0][1] = any_abs(c[0][1]); c[0][2] = any_abs(c[0][2]);
+- c[1][1] = any_abs(c[1][1]); c[1][2] = any_abs(c[1][2]);
+- c[2][1] = any_abs(c[2][1]); c[2][2] = any_abs(c[2][2]);
+- if (c[0][0] * domination > c[0][1] && c[0][0] * domination > c[0][2] &&
++ /* Check for a Lab-like color space.
++ Colors {v,0,0} should map to grays. */
++ cc.paint.values[0] = MAX_FLOAT; cc.paint.values[1] = cc.paint.values[2] = 0;
++ convert_color((gx_device *)&mdev, pcs, pis, &cc, c[0]);
++ cc.paint.values[0] /= 2;
++ convert_color((gx_device *)&mdev, pcs, pis, &cc, c[1]);
++ cc.paint.values[0] /= 2;
++ convert_color((gx_device *)&mdev, pcs, pis, &cc, c[2]);
++ c[0][1] -= c[0][0]; c[0][2] -= c[0][0];
++ c[1][1] -= c[1][0]; c[1][2] -= c[1][0];
++ c[2][1] -= c[2][0]; c[2][2] -= c[2][0];
++ c[0][1] = any_abs(c[0][1]); c[0][2] = any_abs(c[0][2]);
++ c[1][1] = any_abs(c[1][1]); c[1][2] = any_abs(c[1][2]);
++ c[2][1] = any_abs(c[2][1]); c[2][2] = any_abs(c[2][2]);
++ }
++ if (pis && c[0][0] * domination > c[0][1] && c[0][0] * domination > c[0][2] &&
+ c[1][0] * domination > c[1][1] && c[1][0] * domination > c[1][2] &&
+ c[2][0] * domination > c[2][1] && c[2][0] * domination > c[2][2]) {
+ /* Yes, it looks like an Lab color space.
+diff --git a/base/gdevpsdp.c b/base/gdevpsdp.c
+--- a/base/gdevpsdp.c
++++ b/base/gdevpsdp.c
+@@ -487,22 +487,22 @@ psdf_DCT_put_params(gs_param_list * plist, stream_state * st)
+ }
+
+ /* Put [~](Always|Never)Embed parameters. */
++/* Returns 0 = OK, 1 = no paramewter specified, <0 = error. */
+ static int
+ param_read_embed_array(gs_param_list * plist, gs_param_name pname,
+- gs_param_string_array * psa, int ecode)
++ gs_param_string_array * psa)
+ {
+ int code;
+
+ psa->data = 0, psa->size = 0;
+ switch (code = param_read_name_array(plist, pname, psa)) {
+ default:
+- ecode = code;
+- param_signal_error(plist, pname, ecode);
++ param_signal_error(plist, pname, code);
+ case 0:
+ case 1:
+ break;
+ }
+- return ecode;
++ return code;
+ }
+ static bool
+ param_string_eq(const gs_param_string *ps1, const gs_param_string *ps2)
+@@ -563,88 +563,83 @@ delete_embed(gs_param_string_array *prsa, const gs_param_string_array *pnsa,
+ }
+ prsa->size = count;
+ }
++static int merge_embed(gs_param_string_array * psa, gs_param_string_array * asa,
++ gs_memory_t *mem)
++{
++ gs_param_string_array rsa;
++ gs_param_string *rdata;
++ int code;
++
++ rdata = gs_alloc_struct_array(mem, psa->size + asa->size,
++ gs_param_string,
++ &st_param_string_element,
++ "psdf_put_embed_param(update)");
++ if (rdata == 0)
++ return_error(gs_error_VMerror);
++ memcpy(rdata, psa->data, psa->size * sizeof(*psa->data));
++ rsa.data = rdata;
++ rsa.size = psa->size;
++ rsa.persistent = false;
++ code = add_embed(&rsa, asa, mem);
++ if (code < 0) {
++ gs_free_object(mem, rdata, "psdf_put_embed_param(update)");
++ return code;
++ }
++ gs_free_const_object(mem, psa->data, "psdf_put_embed_param(free)");
++ *psa = rsa;
++ return 0;
++}
++
+ static int
+ psdf_put_embed_param(gs_param_list * plist, gs_param_name notpname,
+- gs_param_name allpname, gs_param_string_array * psa,
++ gs_param_name pname, gs_param_string_array * psa,
+ gs_memory_t *mem, int ecode)
+ {
+- gs_param_name pname = notpname + 1;
++ gs_param_name allpname = pname + 1;
+ gs_param_string_array sa, nsa, asa;
+- bool replace;
+- gs_param_string *rdata;
+- gs_param_string_array rsa;
+- int code = 0;
++ int code;
+
+ mem = gs_memory_stable(mem);
+- ecode = param_read_embed_array(plist, pname, &sa, ecode);
+- ecode = param_read_embed_array(plist, notpname, &nsa, ecode);
+- ecode = param_read_embed_array(plist, allpname, &asa, ecode);
+- if (ecode < 0)
+- return ecode;
+- /*
+- * Figure out whether we're replacing (sa == asa or asa and no sa,
+- * no nsa) or updating (all other cases).
+- */
+- if (asa.data == 0 || nsa.data != 0)
+- replace = false;
+- else if (sa.data == 0)
+- replace = true;
+- else if (sa.size != asa.size)
+- replace = false;
+- else {
+- /* Test whether sa == asa. */
+- uint i;
++ code = param_read_embed_array(plist, pname, &sa);
++ if (code < 0)
++ return code;
++ if (code == 0) {
++ /* Optimize for sa == *psa. */
++ int i;
+
+- replace = true;
+- for (i = 0; i < sa.size; ++i)
+- if (!param_string_eq(&sa.data[i], &asa.data[i])) {
+- replace = false;
+- break;
+- }
+- if (replace)
+- return 0; /* no-op */
+- }
+- if (replace) {
+- /* Wholesale replacement, only asa is relevant. */
+- rdata = gs_alloc_struct_array(mem, asa.size, gs_param_string,
+- &st_param_string_element,
+- "psdf_put_embed_param(replace)");
+- if (rdata == 0)
+- return_error(gs_error_VMerror);
+- rsa.data = rdata;
+- rsa.size = 0;
+- if ((code = add_embed(&rsa, &asa, mem)) < 0) {
+- gs_free_object(mem, rdata, "psdf_put_embed_param(replace)");
+- ecode = code;
++ if (sa.size == psa->size) {
++ for (i = 0; i < sa.size; ++i) {
++ if (!param_string_eq(&sa.data[i], &psa->data[i]))
++ break;
++ }
+ } else
+- delete_embed(psa, psa, mem);
+- } else if (sa.data || nsa.data) {
+- /* Incremental update, sa and nsa are relevant, asa is not. */
+- rdata = gs_alloc_struct_array(mem, psa->size + sa.size,
+- gs_param_string,
+- &st_param_string_element,
+- "psdf_put_embed_param(update)");
+- if (rdata == 0)
+- return_error(gs_error_VMerror);
+- memcpy(rdata, psa->data, psa->size * sizeof(*psa->data));
+- rsa.data = rdata;
+- rsa.size = psa->size;
+- if ((code = add_embed(&rsa, &sa, mem)) < 0) {
+- gs_free_object(mem, rdata, "psdf_put_embed_param(update)");
+- ecode = code;
++ i = -1;
++ if (i == sa.size) {
++ /* equal, no-op. */
+ } else {
+- delete_embed(&rsa, &nsa, mem);
+- rsa.data = gs_resize_object(mem, rdata, rsa.size,
++ delete_embed(psa, psa, mem);
++ code = merge_embed(psa, &sa, mem);
++ if (code < 0)
++ return code;
++ }
++ }
++ code = param_read_embed_array(plist, notpname, &nsa);
++ if (code < 0)
++ return code;
++ if (nsa.data != 0)
++ delete_embed(psa, &nsa, mem);
++ code = param_read_embed_array(plist, allpname, &asa);
++ if (code < 0)
++ return code;
++ if (asa.data != 0) {
++ code = merge_embed(psa, &asa, mem);
++ if (code < 0)
++ return code;
++ }
++ if (psa->data)
++ psa->data = gs_resize_object(mem, (gs_param_string *)psa->data, psa->size,
+ "psdf_put_embed_param(resize)");
+- }
+- } else
+- return 0; /* no-op */
+- if (code >= 0) {
+- gs_free_const_object(mem, psa->data, "psdf_put_embed_param(free)");
+- rsa.persistent = false;
+- *psa = rsa;
+- }
+- return ecode;
++ return 0;
+ }
+
+ /* Put an image Dict parameter. */
+diff --git a/base/gdevpsf2.c b/base/gdevpsf2.c
+--- a/base/gdevpsf2.c
++++ b/base/gdevpsf2.c
+@@ -28,7 +28,6 @@
+ #include "gxfont1.h"
+ #include "gxfcid.h"
+ #include "stream.h"
+-#include "sfilter.h"
+ #include "gdevpsf.h"
+
+ /* Define additional opcodes used in Dicts, but not in CharStrings. */
+@@ -1534,15 +1533,15 @@ psf_write_cid0_font(stream *s, gs_font_cid0 *pfont, int options,
+ */
+ uint
+ Top_size = 0x7fffff,
+- GSubrs_offset = 0x7fffff,
+- charset_offset = 0x7fffff,
+- FDSelect_offset = 0x7fffff,
+- CharStrings_offset = 0x7fffff,
+- Font_offset = 0x7fffff,
++ GSubrs_offset = 0x1ffffff,
++ charset_offset = 0x1ffffff,
++ FDSelect_offset = 0x1ffffff,
++ CharStrings_offset = 0x1ffffff,
++ Font_offset = 0x1ffffff,
+ FDArray_offsets[257],
+ Private_offsets[257],
+ Subrs_offsets[257],
+- End_offset = 0x7fffff;
++ End_offset = 0x1ffffff;
+ int j;
+ psf_glyph_enum_t genum;
+ gs_font_info_t info;
+@@ -1639,8 +1638,11 @@ psf_write_cid0_font(stream *s, gs_font_cid0 *pfont, int options,
+ fdselect_size = cff_FDSelect_size(&writer, &genum, &fdselect_format);
+
+ /* Compute the size of the CharStrings Index. */
+- charstrings_size =
+- cff_write_CharStrings_offsets(&writer, &genum, &charstrings_count);
++ /* Compute the size of the CharStrings Index. */
++ code = cff_write_CharStrings_offsets(&writer, &genum, &charstrings_count);
++ if (code < 0)
++ return code;
++ charstrings_size = (uint)code;
+
+ /* Compute the size of the (local) Subrs Indexes. */
+ for (j = 0; j < num_fonts; ++j) {
+diff --git a/base/gdevpsfm.c b/base/gdevpsfm.c
+--- a/base/gdevpsfm.c
++++ b/base/gdevpsfm.c
+@@ -20,7 +20,6 @@
+ #include "spprint.h"
+ #include "spsdf.h"
+ #include "gdevpsf.h"
+-#include "memory_.h"
+
+ /* ---------------- Utilities ---------------- */
+
+diff --git a/base/gdevpsft.c b/base/gdevpsft.c
+--- a/base/gdevpsft.c
++++ b/base/gdevpsft.c
+@@ -711,6 +711,30 @@ write_post(stream *s, gs_font *font, post_t *post)
+ return 0;
+ }
+
++static inline bool check_position(int pos1, int pos2)
++{
++ if (pos1 == pos2)
++ return false;
++ eprintf2("Actual TT subtable offset %d differs from one in the TT header %d.\n", pos1, pos2);
++ return true;
++}
++
++void remove_table(byte *tables, char *tag, uint *numTables)
++{
++ /* Not a high performance implementation because it is called seldom. */
++ int i;
++
++ for (i = 0; i < *numTables;) {
++ byte *tab = tables + i * 16;
++
++ if (!memcmp(tab, tag, 4)) {
++ memmove(tab, tab + 16, 16 * (*numTables - i - 1));
++ --*numTables;
++ } else
++ ++i;
++ }
++}
++
+ /* ---------------- Main program ---------------- */
+
+ /* Write the definition of a TrueType font. */
+@@ -758,8 +782,15 @@ psf_write_truetype_data(stream *s, gs_font_type42 *pfont, int options,
+ uint cmap_length = 0;
+ ulong OS_2_start = 0;
+ uint OS_2_length = OS_2_LENGTH1;
++ ulong maxp_start = 0;
++ uint maxp_length = 0;
++ struct { int glyf, loca, cmap, name, os_2, mtx[2], post, head;
++ } subtable_positions;
++ int start_position = stell(s);
++ int enlarged_numGlyphs = 0;
+ int code;
+
++ memset(&subtable_positions, 0, sizeof(subtable_positions));
+ have_hvhea[0] = have_hvhea[1] = 0;
+ if (alt_font_name)
+ font_name = *alt_font_name;
+@@ -814,6 +845,8 @@ psf_write_truetype_data(stream *s, gs_font_type42 *pfont, int options,
+ case W('m','a','x','p'):
+ READ_SFNTS(pfont, start, length, data);
+ numGlyphs = U16(data + 4);
++ maxp_start = start;
++ maxp_length = length;
+ break;
+ case W('n','a','m','e'):
+ if (writing_cid)
+@@ -849,6 +882,10 @@ psf_write_truetype_data(stream *s, gs_font_type42 *pfont, int options,
+ case W('k','e','r','n'):
+ case W('p','r','e','p'):
+ break; /* always copy these if present */
++ case W('E','B','D','T'):
++ case W('E','B','L','C'):
++ case W('E','B','S','C'):
++ continue;
+ default:
+ if (writing_cid)
+ continue;
+@@ -888,19 +925,30 @@ psf_write_truetype_data(stream *s, gs_font_type42 *pfont, int options,
+ gs_glyph_data_free(&glyph_data, "psf_write_truetype_data");
+ }
+ }
+- /*
+- * For subset fonts, we should trim the loca table so that it only
+- * contains entries through max_glyph. Unfortunately, this would
+- * require changing numGlyphs in maxp, which in turn would affect hdmx,
+- * hhea, hmtx, vdmx, vhea, vmtx, and possibly other tables. This is way
+- * more work than we want to do right now.
+- */
+ if (writing_stripped) {
+ glyf_length = 0;
+ loca_length = 0;
+ } else {
+- /*loca_length = (max_glyph + 2) << 2;*/
+- loca_length = (numGlyphs + 1) << 2;
++ if (max_glyph + 1 > numGlyphs) {
++ /* Either original font is wrong,
++ or we added glyphs to it due to font merge.
++ Need to adjust maxp, hmtx, vmtx, vdmx, hdmx,
++ assuming that the merge doesn't change hhea
++ and other tables.
++ Since changing hdmx, vdmx is too difficult,
++ and since they're not required for PDF,
++ we'll simply skip them.
++ */
++ enlarged_numGlyphs = max_glyph + 1;
++ if (enlarged_numGlyphs > 0xFFFF) {
++ eprintf1("The number of glyphs %d exceeds capability of True Type format.\n", enlarged_numGlyphs);
++ return_error(gs_error_unregistered);
++ }
++ loca_length = (enlarged_numGlyphs + 1) << 2;
++ remove_table(tables, "hdmx", &numTables);
++ remove_table(tables, "vdmx", &numTables);
++ } else
++ loca_length = (numGlyphs + 1) << 2;
+ indexToLocFormat = (glyf_length > 0x1fffc);
+ if (!indexToLocFormat)
+ loca_length >>= 1;
+@@ -962,10 +1010,11 @@ psf_write_truetype_data(stream *s, gs_font_type42 *pfont, int options,
+ byte *tab = &tables[numTables * 16];
+
+ if (!writing_stripped) {
++ subtable_positions.glyf = offset;
+ offset = put_table(tab, "glyf", glyf_checksum,
+ offset, glyf_length);
+ tab += 16;
+-
++ subtable_positions.loca = offset;
+ offset = put_table(tab, "loca", loca_checksum[indexToLocFormat],
+ offset, loca_length);
+ tab += 16;
+@@ -974,18 +1023,21 @@ psf_write_truetype_data(stream *s, gs_font_type42 *pfont, int options,
+ if (!have_cmap) {
+ cmap_length = size_cmap(font, TT_BIAS, 256,
+ GS_MIN_GLYPH_INDEX + max_glyph, options);
++ subtable_positions.cmap = offset;
+ offset = put_table(tab, "cmap", 0L /****** NO CHECKSUM ******/,
+ offset, cmap_length);
+ tab += 16;
+ }
+
+ if (!have_name) {
++ subtable_positions.name = offset;
+ offset = put_table(tab, "name", 0L /****** NO CHECKSUM ******/,
+ offset, size_name(&font_name));
+ tab += 16;
+ }
+
+ if (!no_generate) {
++ subtable_positions.os_2 = offset;
+ offset = put_table(tab, "OS/2", 0L /****** NO CHECKSUM ******/,
+ offset, OS_2_length);
+ tab += 16;
+@@ -994,6 +1046,7 @@ psf_write_truetype_data(stream *s, gs_font_type42 *pfont, int options,
+ if (generate_mtx)
+ for (i = 0; i < 2; ++i)
+ if (have_hvhea[i]) {
++ subtable_positions.mtx[i] = offset;
+ offset = put_table(tab, (i ? "vmtx" : "hmtx"),
+ 0L /****** NO CHECKSUM ******/,
+ offset,
+@@ -1002,6 +1055,7 @@ psf_write_truetype_data(stream *s, gs_font_type42 *pfont, int options,
+ }
+
+ if (!have_post) {
++ subtable_positions.post = offset;
+ offset = put_table(tab, "post", 0L /****** NO CHECKSUM ******/,
+ offset, post.length);
+ tab += 16;
+@@ -1011,6 +1065,7 @@ psf_write_truetype_data(stream *s, gs_font_type42 *pfont, int options,
+ * Note that the 'head' table must have length 54, even though
+ * it occupies 56 bytes on the file.
+ */
++ subtable_positions.head = offset;
+ offset = put_table(tab, "head", head_checksum, offset, 54);
+ tab += 16;
+ }
+@@ -1082,6 +1137,19 @@ psf_write_truetype_data(stream *s, gs_font_type42 *pfont, int options,
+ put_pad(s, OS_2_length);
+ }
+ break;
++ case W('m','a','x','p'):
++ if (enlarged_numGlyphs) {
++ /* Must keep the table size. */
++ byte buf[6];
++
++ READ_SFNTS(pfont, maxp_start, sizeof(buf), buf);
++ put_u16(buf + 4, enlarged_numGlyphs);
++ stream_write(s, buf, min(length, sizeof(buf)));
++ if (length > sizeof(buf)) /* Paranoid Safety */
++ write_range(s, pfont, start + sizeof(buf), length - sizeof(buf));
++ } else
++ write_range(s, pfont, start, length);
++ break;
+ case W('h','h','e','a'):
+ case W('v','h','e','a'):
+ if (generate_mtx) {
+@@ -1098,9 +1166,12 @@ psf_write_truetype_data(stream *s, gs_font_type42 *pfont, int options,
+ }
+
+ if (!writing_stripped) {
++ int n = max(numGlyphs, enlarged_numGlyphs) + 1;
+
+ /* Write glyf. */
+
++ if (check_position(subtable_positions.glyf + start_position, stell(s)))
++ return_error(gs_error_unregistered);
+ psf_enumerate_glyphs_reset(penum);
+ for (offset = 0; psf_enumerate_glyphs_next(penum, &glyph) != 1; ) {
+ gs_glyph_data_t glyph_data;
+@@ -1131,6 +1202,8 @@ psf_write_truetype_data(stream *s, gs_font_type42 *pfont, int options,
+
+ /* Write loca. */
+
++ if (check_position(subtable_positions.loca + start_position, stell(s)))
++ return_error(gs_error_unregistered);
+ psf_enumerate_glyphs_reset(penum);
+ glyph_prev = 0;
+ for (offset = 0; psf_enumerate_glyphs_next(penum, &glyph) != 1; ) {
+@@ -1153,25 +1226,36 @@ psf_write_truetype_data(stream *s, gs_font_type42 *pfont, int options,
+
+ }
+ /* Pad to numGlyphs + 1 entries (including the trailing entry). */
+- for (; glyph_prev <= numGlyphs; ++glyph_prev)
++ for (; glyph_prev < n; ++glyph_prev)
+ put_loca(s, offset, indexToLocFormat);
+ put_pad(s, loca_length);
+
+ /* If necessary, write cmap, name, and OS/2. */
+
+- if (!have_cmap)
++ if (!have_cmap) {
++ if (check_position(subtable_positions.cmap + start_position, stell(s)))
++ return_error(gs_error_unregistered);
+ write_cmap(s, font, TT_BIAS, 256, GS_MIN_GLYPH_INDEX + max_glyph,
+ options, cmap_length);
+- if (!have_name)
++ }
++ if (!have_name) {
++ if (check_position(subtable_positions.name + start_position, stell(s)))
++ return_error(gs_error_unregistered);
+ write_name(s, &font_name);
+- if (!have_OS_2)
++ }
++ if (!have_OS_2) {
++ if (check_position(subtable_positions.os_2 + start_position, stell(s)))
++ return_error(gs_error_unregistered);
+ write_OS_2(s, font, TT_BIAS, 256);
++ }
+
+ /* If necessary, write [hv]mtx. */
+
+ if (generate_mtx)
+ for (i = 0; i < 2; ++i)
+ if (have_hvhea[i]) {
++ if (check_position(subtable_positions.mtx[i] + start_position, stell(s)))
++ return_error(gs_error_unregistered);
+ write_mtx(s, pfont, &mtx[i], i);
+ put_pad(s, mtx[i].length);
+ }
+@@ -1179,6 +1263,8 @@ psf_write_truetype_data(stream *s, gs_font_type42 *pfont, int options,
+ /* If necessary, write post. */
+
+ if (!have_post) {
++ if (check_position(subtable_positions.post + start_position, stell(s)))
++ return_error(gs_error_unregistered);
+ if (options & WRITE_TRUETYPE_POST) {
+ code = write_post(s, font, &post);
+ if (code < 0)
+@@ -1207,6 +1293,8 @@ psf_write_truetype_data(stream *s, gs_font_type42 *pfont, int options,
+ #endif
+ put_u32(head + 8, HEAD_MAGIC - file_checksum); /* per spec */
+ #undef HEAD_MAGIC
++ if (check_position(subtable_positions.head + start_position, stell(s)))
++ return_error(gs_error_unregistered);
+ stream_write(s, head, 56);
+
+ return 0;
+diff --git a/base/gdevpsfx.c b/base/gdevpsfx.c
+--- a/base/gdevpsfx.c
++++ b/base/gdevpsfx.c
+@@ -464,8 +464,8 @@ psf_convert_type1_to_type2(stream *s, const gs_glyph_data_t *pgd,
+ END
+ fixed mx0 = 0, my0 = 0; /* See ce1_setcurrentpoint. */
+
+- /* Quiet a Coverity uninitialsed variable warning */
+- cis.lsb.y = 0;
++ /* In case we do not get an sbw or hsbw op */
++ cis.lsb.x = cis.lsb.y = cis.width.x = cis.width.y = fixed_0;
+
+ /*
+ * Do a first pass to collect hints. Note that we must also process
+@@ -508,6 +508,8 @@ psf_convert_type1_to_type2(stream *s, const gs_glyph_data_t *pgd,
+ case ce1_callothersubr:
+ if (*csp == int2fixed(3))
+ replace_hints = true;
++ if (*csp == int2fixed(12) || *csp == int2fixed(13))
++ cis.os_count -= fixed2int(csp[-1]);
+ cis.os_count -= 2;
+ continue;
+ case CE_OFFSET + ce1_dotsection:
+diff --git a/base/gdevpsu.c b/base/gdevpsu.c
+--- a/base/gdevpsu.c
++++ b/base/gdevpsu.c
+@@ -288,7 +288,7 @@ psw_write_page_header(stream *s, const gx_device *dev,
+ if (!pdpc->ProduceEPS)
+ pprintld2(s, "%%%%PageBoundingBox: 0 0 %ld %ld\n", width, height);
+
+- stream_puts(s, "%%%%BeginPageSetup\n");
++ stream_puts(s, "%%BeginPageSetup\n");
+ /*
+ * Adobe's documentation says that page setup must be placed outside the
+ * save/restore that encapsulates the page contents, and that the
+@@ -307,7 +307,7 @@ psw_write_page_header(stream *s, const gx_device *dev,
+ } page_size;
+ static const page_size sizes[] = {
+ {"/11x17", 792, 1224},
+- {"/a3", 842, 1190},
++ {"/a3", 842, 1191},
+ {"/a4", 595, 842},
+ {"/b5", 501, 709},
+ {"/ledger", 1224, 792},
+@@ -317,9 +317,16 @@ psw_write_page_header(stream *s, const gx_device *dev,
+ };
+ const page_size *p = sizes;
+
+- while (p->size_name[0] == '/' &&
+- (p->width != width || p->height != height))
+- ++p;
++ while (p->size_name[0] == '/') {
++ if((p->width - 5) <= width && (p->width + 5) >= width) {
++ if((p->height - 5) <= height && (p->height + 5) >= height) {
++ break;
++ } else
++ ++p;
++ }
++ else
++ ++p;
++ }
+ pprintd2(s, "%d %d ", width, height);
+ pprints1(s, "%s setpagesize\n", p->size_name);
+ }
+diff --git a/base/gdevpxen.h b/base/gdevpxen.h
+--- a/base/gdevpxen.h
++++ b/base/gdevpxen.h
+@@ -198,6 +198,7 @@ typedef enum {
+ * The arguments are:
+ * media size code, resolution for width/height, width, height.
+ */
++
+ #define px_enumerate_media(m)\
+ m(eDefaultPaperSize, -1, -1, -1)\
+ m(eLetterPaper, 300, 2550, 3300)\
+@@ -210,18 +211,18 @@ typedef enum {
+ m(eMonarchEnvelope, 300, 1162, 2250)\
+ m(eC5Envelope, 300, 1913, 2704)\
+ m(eDLEnvelope, 300, 1299, 2598)\
+- m(eJB4Paper, -1, -1, -1)\
++ m(eJB4Paper, 300, 3035, 4299)\
+ m(eJB5Paper, 300, 2150, 3035)\
+ m(eB5Envelope, 300, 2078, 2952)\
+ m(eB5Paper, 300, 2150, 3035)\
+- m(eJPostcard, 300, 1181, 1748)\
+- m(eJDoublePostcard, -1, -1, -1)\
++ m(eJPostcard, 300, 1181, 1748)\
++ m(eJDoublePostcard, 300, 2362, 1748)\
+ m(eA5Paper,300,1748, 2480)\
+- m(eA6Paper,-1, -1, -1)\
+- m(eJB6Paper,-1, -1, -1)\
+- m(eJIS8K, -1, -1, -1)\
+- m(eJIS16K, -1, -1, -1)\
+- m(eJISExec, -1, -1, -1)
++ m(eA6Paper,300, 1240, 1748)\
++ m(eJB6Paper,300, 1512, 2150)\
++ m(eJIS8K, 300, 3154, 4606)\
++ m(eJIS16K, 300, 2303, 3154)\
++ m(eJISExec, 300, 2551, 3898)
+
+ typedef enum {
+ eDefaultSource = 0,
+diff --git a/base/gdevsgi.c b/base/gdevsgi.c
+--- a/base/gdevsgi.c
++++ b/base/gdevsgi.c
+@@ -65,18 +65,77 @@ typedef struct sgi_cursor_s {
+ int lnum;
+ } sgi_cursor;
+
++/* write a short int to disk as big-endean */
++static int putshort(unsigned int val, FILE *outf)
++{
++ unsigned char buf[2];
++
++ buf[0] = (val>>8);
++ buf[1] = val;
++ return fwrite(buf,2,1,outf);
++}
++
++/* write an int to disk as big-endean */
++static int putint(unsigned int val, FILE *outf)
++{
++ unsigned char buf[4];
++
++ buf[0] = (val>>24);
++ buf[1] = (val>>16);
++ buf[2] = (val>>8);
++ buf[3] = val;
++ return fwrite(buf,4,1,outf);
++}
++
++/* write the header field by field in big-endian */
++static void putheader(IMAGE *header, FILE *outf)
++{
++ int i;
++ char filler= '\0';
++
++ putshort(header->imagic, outf);
++ fputc(1, outf); /* RLE */
++ fputc(1, outf); /* bpp */
++ putshort(header->dim, outf);
++ putshort(header->xsize, outf);
++ putshort(header->ysize, outf);
++ putshort(header->zsize, outf);
++
++ putint(header->min_color, outf);
++ putint(header->max_color, outf);
++ putint(header->wastebytes, outf);
++
++ fwrite(header->name,80,1,outf);
++
++ putint(header->colormap, outf);
++
++ /* put the filler for the rest */
++ for (i=0; i<404; i++)
++ fputc(filler,outf);
++ }
++
+ static int
+ sgi_begin_page(gx_device_printer *bdev, FILE *pstream, sgi_cursor *pcur)
+ {
+- uint line_size = gdev_mem_bytes_per_scan_line((gx_device_printer*)bdev);
+- byte *data = (byte*)gs_malloc(bdev->memory, line_size, 1, "sgi_begin_page");
+- IMAGE *header= (IMAGE*)gs_malloc(bdev->memory, sizeof(IMAGE),1,"sgi_begin_page");
+- char filler= '\0';
+- int i;
++ uint line_size;
++ byte *data;
++ IMAGE *header;
+
+- if ((data == (byte*)0)||(header == (IMAGE*)0)) return -1;
++ if (bdev->PageCount >= 1 && !bdev->file_is_new) { /* support single page only */
++ eprintf("sgi rgb format only supports one page per file.\n"
++ "Please use the '%%d' OutputFile option to create one file for each page.\n");
++ return_error(gs_error_rangecheck);
++ }
++ line_size = gdev_mem_bytes_per_scan_line((gx_device_printer*)bdev);
++ data = (byte*)gs_malloc(bdev->memory, line_size, 1, "sgi_begin_page");
++ header= (IMAGE*)gs_malloc(bdev->memory, sizeof(IMAGE),1,"sgi_begin_page");
+
+- bzero(header,sizeof(IMAGE));
++ if ((data == (byte*)0)||(header == (IMAGE*)0)) {
++ gs_free(bdev->memory, data, line_size, 1, "sgi_begin_page");
++ gs_free(bdev->memory, header, sizeof(IMAGE),1,"sgi_begin_page");
++ return_error(gs_error_VMerror);
++ }
++ memset(header,0, sizeof(IMAGE));
+ header->imagic = IMAGIC;
+ header->type = RLE(1);
+ header->dim = 3;
+@@ -89,8 +148,7 @@ sgi_begin_page(gx_device_printer *bdev, FILE *pstream, sgi_cursor *pcur)
+ strncpy(header->name,"gs picture",80);
+ header->colormap = CM_NORMAL;
+ header->dorev=0;
+- fwrite(header,sizeof(IMAGE),1,pstream);
+- for (i=0; i<512-sizeof(IMAGE); i++) fputc(filler,pstream);
++ putheader(header,pstream);
+ pcur->dev = bdev;
+ pcur->bpp = bdev->color_info.depth;
+ pcur->line_size = line_size;
+@@ -115,16 +173,24 @@ sgi_print_page(gx_device_printer *pdev, FILE *pstream)
+ int code = sgi_begin_page(bdev, pstream, &cur);
+ uint bpe, mask;
+ int separation;
+- long *rowsizes=(long*)gs_malloc(pdev->memory, 4,3*bdev->height,"sgi_print_page");
++ int *rowsizes;
+ byte *edata ;
+ long lastval;
+ int rownumber;
+-#define aref2(a,b) a*bdev->height+b
++
++ if (pdev->PageCount >= 1 && !pdev->file_is_new)
++ return_error(gs_error_rangecheck); /* support single page only, can't happen */
++
++#define aref2(a,b) (a)*bdev->height+(b)
++ rowsizes=(int*)gs_malloc(pdev->memory, sizeof(int),3*bdev->height,"sgi_print_page");
+ edata = (byte*)gs_malloc(pdev->memory, cur.line_size, 1, "sgi_begin_page");
+- if((code<0)||(rowsizes==(long*)NULL)||(edata==(byte*)NULL)) return(-1);
+- fwrite(rowsizes,sizeof(long),3*bdev->height,pstream); /* rowstarts */
+- fwrite(rowsizes,sizeof(long),3*bdev->height,pstream); /* rowsizes */
+- lastval = 512+sizeof(long)*6*bdev->height;
++
++ if((code<0)||(rowsizes==(int*)NULL)||(edata==(byte*)NULL)) {
++ code = gs_note_error(gs_error_VMerror);
++ goto free_mem;
++ }
++
++ lastval = 512+4*6*bdev->height; /* skip offset table */
+ fseek(pstream,lastval,0);
+ for (separation=0; separation < 3; separation++)
+ {
+@@ -144,11 +210,11 @@ sgi_print_page(gx_device_printer *pdev, FILE *pstream)
+ for (bp = cur.data, x=0, shift = 8 - cur.bpp;
+ x < bdev->width;
+ )
+- { ulong pixel = 0;
++ { uint pixel = 0;
+ uint r, g, b;
+ switch (cur.bpp >> 3)
+ {
+- case 3: pixel = (ulong)*bp << 16; bp++;
++ case 3: pixel = (uint)*bp << 16; bp++;
+ case 2: pixel += (uint)*bp << 8; bp++;
+ case 1: pixel += *bp; bp++; break;
+ case 0: pixel = *bp >> shift;
+@@ -197,24 +263,22 @@ sgi_print_page(gx_device_printer *pdev, FILE *pstream)
+ }
+ *optr++ = 0;
+ rowsizes[aref2(separation,rownumber++)] = optr-startcol;
+- fwrite(startcol,1,optr-startcol,pstream);
++ if (fwrite(startcol,1,optr-startcol,pstream) != optr-startcol) {
++ code = gs_note_error(gs_error_ioerror);
++ goto free_mem;
++ }
+ }
+ }
+ fseek(pstream,512L,0);
+ for(separation=0; separation<3; separation++)
+ for(rownumber=0; rownumber<bdev->height; rownumber++)
+- {fputc((char)(lastval>>24),pstream);
+- fputc((char)(lastval>>16),pstream);
+- fputc((char)(lastval>>8),pstream);
+- fputc((char)(lastval),pstream);
++ {putint(lastval,pstream);
+ lastval+=rowsizes[aref2(separation,rownumber)];}
+ for(separation=0; separation<3; separation++)
+ for(rownumber=0; rownumber<bdev->height; rownumber++)
+ {lastval=rowsizes[aref2(separation,rownumber)];
+- fputc((char)(lastval>>24),pstream);
+- fputc((char)(lastval>>16),pstream);
+- fputc((char)(lastval>>8),pstream);
+- fputc((char)(lastval),pstream);}
++ putint(lastval,pstream);}
++ free_mem:
+ gs_free(pdev->memory, (char*)cur.data, cur.line_size, 1,
+ "sgi_print_page(done)");
+ gs_free(pdev->memory, (char*)edata, cur.line_size, 1, "sgi_print_page(done)");
+diff --git a/base/gdevsgi.h b/base/gdevsgi.h
+--- a/base/gdevsgi.h
++++ b/base/gdevsgi.h
+@@ -46,11 +46,11 @@ typedef struct {
+ unsigned short xsize;
+ unsigned short ysize;
+ unsigned short zsize;
+- unsigned long min_color;
+- unsigned long max_color;
+- unsigned long wastebytes;
++ unsigned int min_color;
++ unsigned int max_color;
++ unsigned int wastebytes;
+ char name[80];
+- unsigned long colormap;
++ unsigned int colormap;
+
+ long file; /* stuff used in core only */
+ unsigned short flags;
+diff --git a/base/gdevtfax.c b/base/gdevtfax.c
+--- a/base/gdevtfax.c
++++ b/base/gdevtfax.c
+@@ -38,6 +38,7 @@ struct gx_device_tfax_s {
+ long MaxStripSize; /* 0 = no limit, other is UNCOMPRESSED limit */
+ /* The type and range of FillOrder follows TIFF 6 spec */
+ int FillOrder; /* 1 = lowest column in the high-order bit, 2 = reverse */
++ bool BigEndian; /* true = big endian; false = little endian*/
+ gdev_tiff_state tiff; /* for TIFF output only */
+ };
+ typedef struct gx_device_tfax_s gx_device_tfax;
+@@ -51,7 +52,8 @@ static const gx_device_procs gdev_tfax_std_procs =
+ {\
+ FAX_DEVICE_BODY(gx_device_tfax, gdev_tfax_std_procs, dname, print_page),\
+ 0 /* unlimited strip size byte count */,\
+- 1 /* lowest column in the high-order bit */\
++ 1 /* lowest column in the high-order bit */,\
++ arch_is_big_endian /* default to native endian (i.e. use big endian iff the platform is so*/\
+ }
+
+ const gx_device_tfax gs_tiffcrle_device =
+@@ -78,6 +80,8 @@ tfax_get_params(gx_device * dev, gs_param_list * plist)
+ ecode = code;
+ if ((code = param_write_int(plist, "FillOrder", &tfdev->FillOrder)) < 0)
+ ecode = code;
++ if ((code = param_write_bool(plist, "BigEndian", &tfdev->BigEndian)) < 0)
++ ecode = code;
+ return ecode;
+ }
+ static int
+@@ -89,6 +93,7 @@ tfax_put_params(gx_device * dev, gs_param_list * plist)
+ long mss = tfdev->MaxStripSize;
+ int fill_order = tfdev->FillOrder;
+ const char *param_name;
++ bool big_endian = tfdev->BigEndian;
+
+ switch (code = param_read_long(plist, (param_name = "MaxStripSize"), &mss)) {
+ case 0:
+@@ -119,6 +124,16 @@ tfax_put_params(gx_device * dev, gs_param_list * plist)
+ case 1:
+ break;
+ }
++
++ /* Read BigEndian option as bool */
++ switch (code = param_read_bool(plist, (param_name = "BigEndian"), &big_endian)) {
++ default:
++ ecode = code;
++ param_signal_error(plist, param_name, ecode);
++ case 0:
++ case 1:
++ break;
++ }
+
+ if (ecode < 0)
+ return ecode;
+@@ -128,6 +143,7 @@ tfax_put_params(gx_device * dev, gs_param_list * plist)
+
+ tfdev->MaxStripSize = mss;
+ tfdev->FillOrder = fill_order;
++ tfdev->BigEndian = big_endian;
+ return code;
+ }
+
+@@ -195,19 +211,27 @@ static dev_proc_print_page(tifflzw_print_page);
+ static dev_proc_print_page(tiffpack_print_page);
+
+ const gx_device_tfax gs_tifflzw_device = {
+- prn_device_std_body(gx_device_tfax, prn_std_procs, "tifflzw",
++ prn_device_std_body(gx_device_tfax, gdev_tfax_std_procs, "tifflzw",
+ DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
+ X_DPI, Y_DPI,
+ 0, 0, 0, 0, /* margins */
+- 1, tifflzw_print_page)
++ 1, tifflzw_print_page),
++ 1 /* AdjustWidth, not used */,
++ 0 /* unlimited strip size byte count */,
++ 1 /* lowest column in the high-order bit, not used */,
++ arch_is_big_endian /* default to native endian (i.e. use big endian iff the platform is so*/
+ };
+
+ const gx_device_tfax gs_tiffpack_device = {
+- prn_device_std_body(gx_device_tfax, prn_std_procs, "tiffpack",
++ prn_device_std_body(gx_device_tfax, gdev_tfax_std_procs, "tiffpack",
+ DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
+ X_DPI, Y_DPI,
+ 0, 0, 0, 0, /* margins */
+- 1, tiffpack_print_page)
++ 1, tiffpack_print_page),
++ 1 /* AdjustWidth, not used */,
++ 0 /* unlimited strip size byte count */,
++ 1 /* lowest column in the high-order bit, not used */,
++ arch_is_big_endian /* default to native endian (i.e. use big endian iff the platform is so*/
+ };
+
+ /* Define the TIFF directory we use, beyond the standard entries. */
+@@ -249,7 +273,7 @@ tifff_print_page(gx_device_printer * dev, FILE * prn_stream,
+ tfax_begin_page(tfdev, prn_stream, pdir, pstate->Columns);
+ pstate->FirstBitLowOrder = tfdev->FillOrder == 2;
+ code = gdev_fax_print_page_stripped(dev, prn_stream, pstate, tfdev->tiff.rows);
+- gdev_tiff_end_page(&tfdev->tiff, prn_stream);
++ gdev_tiff_end_page(&tfdev->tiff, prn_stream, tfdev->BigEndian != arch_is_big_endian);
+ return code;
+ }
+ static int
+@@ -332,7 +356,7 @@ tifflzw_print_page(gx_device_printer * dev, FILE * prn_stream)
+ state.EarlyChange = 1; /* PLRM is sort of confusing, but this is correct */
+ code = gdev_stream_print_page(dev, prn_stream, &s_LZWE_template,
+ (stream_state *) & state);
+- gdev_tiff_end_page(&tfdev->tiff, prn_stream);
++ gdev_tiff_end_page(&tfdev->tiff, prn_stream, tfdev->BigEndian != arch_is_big_endian);
+ return code;
+ }
+
+@@ -353,7 +377,7 @@ tiffpack_print_page(gx_device_printer * dev, FILE * prn_stream)
+ state.record_size = gdev_mem_bytes_per_scan_line((gx_device *) dev);
+ code = gdev_stream_print_page(dev, prn_stream, &s_RLE_template,
+ (stream_state *) & state);
+- gdev_tiff_end_page(&tfdev->tiff, prn_stream);
++ gdev_tiff_end_page(&tfdev->tiff, prn_stream, tfdev->BigEndian != arch_is_big_endian);
+ return code;
+ }
+
+@@ -371,7 +395,7 @@ tfax_begin_page(gx_device_tfax * tfdev, FILE * fp,
+ &tfdev->tiff, fp,
+ (const TIFF_dir_entry *)pdir,
+ sizeof(*pdir) / sizeof(TIFF_dir_entry),
+- NULL, 0, tfdev->MaxStripSize);
++ NULL, 0, tfdev->MaxStripSize, tfdev->BigEndian != arch_is_big_endian);
+ tfdev->width = save_width;
+ return code;
+ }
+diff --git a/base/gdevtfnx.c b/base/gdevtfnx.c
+--- a/base/gdevtfnx.c
++++ b/base/gdevtfnx.c
+@@ -27,36 +27,34 @@
+ #define X_DPI 72
+ #define Y_DPI 72
+
+-typedef struct gx_device_tiff_s {
+- gx_device_common;
+- gx_prn_device_common;
+- gdev_tiff_state tiff;
+-} gx_device_tiff;
+-
+ static dev_proc_print_page(tiff12_print_page);
+ static dev_proc_print_page(tiff24_print_page);
+
+ static const gx_device_procs tiff12_procs =
+-prn_color_procs(gdev_prn_open, gdev_prn_output_page, gdev_prn_close,
+- gx_default_rgb_map_rgb_color, gx_default_rgb_map_color_rgb);
++prn_color_params_procs(gdev_prn_open, gdev_prn_output_page, gdev_prn_close,
++ gx_default_rgb_map_rgb_color, gx_default_rgb_map_color_rgb,
++ tiff_get_params, tiff_put_params);
+ static const gx_device_procs tiff24_procs =
+-prn_color_procs(gdev_prn_open, gdev_prn_output_page, gdev_prn_close,
+- gx_default_rgb_map_rgb_color, gx_default_rgb_map_color_rgb);
++prn_color_params_procs(gdev_prn_open, gdev_prn_output_page, gdev_prn_close,
++ gx_default_rgb_map_rgb_color, gx_default_rgb_map_color_rgb,
++ tiff_get_params, tiff_put_params);
+
+-const gx_device_printer gs_tiff12nc_device = {
++const gx_device_tiff gs_tiff12nc_device = {
+ prn_device_std_body(gx_device_tiff, tiff12_procs, "tiff12nc",
+ DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
+ X_DPI, Y_DPI,
+ 0, 0, 0, 0,
+- 24, tiff12_print_page)
++ 24, tiff12_print_page),
++ arch_is_big_endian /* default to native endian (i.e. use big endian iff the platform is so*/
+ };
+
+-const gx_device_printer gs_tiff24nc_device = {
++const gx_device_tiff gs_tiff24nc_device = {
+ prn_device_std_body(gx_device_tiff, tiff24_procs, "tiff24nc",
+ DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
+ X_DPI, Y_DPI,
+ 0, 0, 0, 0,
+- 24, tiff24_print_page)
++ 24, tiff24_print_page),
++ arch_is_big_endian /* default to native endian (i.e. use big endian iff the platform is so*/
+ };
+
+ /* ------ Private definitions ------ */
+@@ -97,14 +95,21 @@ static int
+ tiff12_print_page(gx_device_printer * pdev, FILE * file)
+ {
+ gx_device_tiff *const tfdev = (gx_device_tiff *)pdev;
+- int code;
+-
++ int code, i;
++ bool swap_bytes = tfdev->BigEndian != arch_is_big_endian;
++ tiff_rgb_values val_12_swapped = val_12_template;
++ if (swap_bytes)
++ {
++ for (i=0; i<3; i++)
++ SWAP_SHORT(val_12_swapped.bps[i]);
++ }
++
+ /* Write the page directory. */
+ code = gdev_tiff_begin_page(pdev, &tfdev->tiff, file,
+ (const TIFF_dir_entry *)&dir_rgb_template,
+- sizeof(dir_rgb_template) / sizeof(TIFF_dir_entry),
+- (const byte *)&val_12_template,
+- sizeof(val_12_template), 0);
++ sizeof(dir_rgb_template) / sizeof(TIFF_dir_entry),
++ (const byte *)&val_12_swapped,
++ sizeof(val_12_swapped), 0, swap_bytes);
+ if (code < 0)
+ return code;
+
+@@ -138,7 +143,7 @@ tiff12_print_page(gx_device_printer * pdev, FILE * file)
+ }
+
+ gdev_tiff_end_strip(&tfdev->tiff, file);
+- gdev_tiff_end_page(&tfdev->tiff, file);
++ gdev_tiff_end_page(&tfdev->tiff, file, swap_bytes);
+ gs_free_object(pdev->memory, line, "tiff12_print_page");
+ }
+
+@@ -149,14 +154,21 @@ static int
+ tiff24_print_page(gx_device_printer * pdev, FILE * file)
+ {
+ gx_device_tiff *const tfdev = (gx_device_tiff *)pdev;
+- int code;
++ int code, i;
++ bool swap_bytes = tfdev->BigEndian != arch_is_big_endian;
++ tiff_rgb_values val_24_swapped = val_24_template;
++ if (swap_bytes)
++ {
++ for (i=0; i<3; i++)
++ SWAP_SHORT(val_24_swapped.bps[i]);
++ }
+
+ /* Write the page directory. */
+ code = gdev_tiff_begin_page(pdev, &tfdev->tiff, file,
+ (const TIFF_dir_entry *)&dir_rgb_template,
+- sizeof(dir_rgb_template) / sizeof(TIFF_dir_entry),
+- (const byte *)&val_24_template,
+- sizeof(val_24_template), 0);
++ sizeof(dir_rgb_template) / sizeof(TIFF_dir_entry),
++ (const byte *)&val_24_swapped,
++ sizeof(val_24_swapped), 0, swap_bytes);
+ if (code < 0)
+ return code;
+
+@@ -176,7 +188,7 @@ tiff24_print_page(gx_device_printer * pdev, FILE * file)
+ fwrite((char *)row, raster, 1, file);
+ }
+ gdev_tiff_end_strip(&tfdev->tiff, file);
+- gdev_tiff_end_page(&tfdev->tiff, file);
++ gdev_tiff_end_page(&tfdev->tiff, file, swap_bytes);
+ gs_free_object(pdev->memory, line, "tiff24_print_page");
+ }
+
+diff --git a/base/gdevtifs.c b/base/gdevtifs.c
+--- a/base/gdevtifs.c
++++ b/base/gdevtifs.c
+@@ -80,8 +80,49 @@ static const TIFF_std_directory_values std_values_initial =
+ {0, 0}
+ };
+
++/* Get/put the BigEndian parameter. */
++int
++tiff_get_params(gx_device * dev, gs_param_list * plist)
++{
++ gx_device_tiff *const tfdev = (gx_device_tiff *)dev;
++ int code = gdev_prn_get_params(dev, plist);
++ int ecode = code;
++
++ if ((code = param_write_bool(plist, "BigEndian", &tfdev->BigEndian)) < 0)
++ ecode = code;
++ return ecode;
++}
++
++int
++tiff_put_params(gx_device * dev, gs_param_list * plist)
++{
++ gx_device_tiff *const tfdev = (gx_device_tiff *)dev;
++ int ecode = 0;
++ int code;
++ const char *param_name;
++ bool big_endian = tfdev->BigEndian;
++
++ /* Read BigEndian option as bool */
++ switch (code = param_read_bool(plist, (param_name = "BigEndian"), &big_endian)) {
++ default:
++ ecode = code;
++ param_signal_error(plist, param_name, ecode);
++ case 0:
++ case 1:
++ break;
++ }
++
++ if (ecode < 0)
++ return ecode;
++ code = gdev_prn_put_params(dev, plist);
++ if (code < 0)
++ return code;
++
++ tfdev->BigEndian = big_endian;
++ return code;
++}
++
+ /* Fix up tag values on big-endian machines if necessary. */
+-#if arch_is_big_endian
+ static void
+ tiff_fixup_tag(TIFF_dir_entry * dp)
+ {
+@@ -97,16 +138,55 @@ tiff_fixup_tag(TIFF_dir_entry * dp)
+ break;
+ }
+ }
+-#else
+-# define tiff_fixup_tag(dp) DO_NOTHING
+-#endif
++
++static size_t fwrite_short(TIFF_ushort nVal, FILE *stream, bool swap_bytes)
++{
++ TIFF_ushort v;
++
++ if (swap_bytes)
++ v = nVal << 8 | nVal >> 8;
++ else
++ v = nVal;
++ return fwrite(&v, sizeof(v), 1, stream);
++}
++
++static size_t fwrite_long(TIFF_ulong nVal, FILE *stream, bool swap_bytes)
++{
++ TIFF_ulong v;
++
++ if (swap_bytes)
++ v = nVal << 24 | nVal >> 24 | (nVal & 0xff0000) >> 8 | (nVal & 0xff00) << 8;
++ else
++ v = nVal;
++ return fwrite(&v, sizeof(v), 1, stream);
++ }
++
++static void fwrite_entry(TIFF_dir_entry *entry, FILE *stream, bool swap_bytes)
++{
++ fwrite_short(entry->tag, stream, swap_bytes);
++ fwrite_short(entry->type, stream, swap_bytes);
++ fwrite_long(entry->count, stream, swap_bytes);
++ fwrite_long(entry->value, stream, swap_bytes);
++}
++
++static void fwrite_std_values(TIFF_std_directory_values *std_values, FILE *stream, bool swap_bytes)
++{
++ fwrite_long(std_values->diroff, stream, swap_bytes);
++ fwrite_long(std_values->xresValue[0], stream, swap_bytes);
++ fwrite_long(std_values->xresValue[1], stream, swap_bytes);
++ fwrite_long(std_values->yresValue[0], stream, swap_bytes);
++ fwrite_long(std_values->yresValue[1], stream, swap_bytes);
++ fwrite(std_values->softwareValue, 1, maxSoftware, stream);
++ fwrite(std_values->dateTimeValue, 1, 20, stream);
++}
+
+ /* Begin a TIFF page. */
+ int
+ gdev_tiff_begin_page(gx_device_printer * pdev, gdev_tiff_state * tifs,
+ FILE * fp,
+ const TIFF_dir_entry * entries, int entry_count,
+- const byte * values, int value_size, long max_strip_size)
++ const byte * values, int value_size, long max_strip_size,
++ bool swap_bytes)
+ {
+ gs_memory_t *mem = pdev->memory;
+ TIFF_std_directory_entries std_entries;
+@@ -117,29 +197,26 @@ gdev_tiff_begin_page(gx_device_printer * pdev, gdev_tiff_state * tifs,
+ (sizeof(TIFF_std_directory_entries) / sizeof(TIFF_dir_entry))
+ int nse, nce, ntags;
+ TIFF_std_directory_values std_values;
++ bool big_endian = arch_is_big_endian ^ swap_bytes;
+
+ #define std_value_size sizeof(TIFF_std_directory_values)
+
+ tifs->mem = mem;
+ if (gdev_prn_file_is_new(pdev)) {
+ /* This is a new file; write the TIFF header. */
+- static const TIFF_header hdr = {
+-#if arch_is_big_endian
+- TIFF_magic_big_endian,
+-#else
+- TIFF_magic_little_endian,
+-#endif
+- TIFF_version_value,
+- sizeof(TIFF_header)
+- };
+-
+- fwrite((const char *)&hdr, sizeof(hdr), 1, fp);
++ TIFF_header hdr;
++ hdr.magic = big_endian ? TIFF_magic_big_endian : TIFF_magic_little_endian;
++ hdr.version = TIFF_version_value;
++ hdr.diroff = sizeof(TIFF_header);
++ fwrite((char *)&hdr.magic, sizeof(hdr.magic), 1, fp);
++ fwrite_short(hdr.version, fp, swap_bytes);
++ fwrite_long(hdr.diroff, fp, swap_bytes);
+ tifs->prev_dir = 0;
+ } else { /* Patch pointer to this directory from previous. */
+ TIFF_ulong offset = (TIFF_ulong) tifs->dir_off;
+
+ fseek(fp, tifs->prev_dir, SEEK_SET);
+- fwrite((char *)&offset, sizeof(offset), 1, fp);
++ fwrite_long(offset, fp, swap_bytes);
+ fseek(fp, tifs->dir_off, SEEK_SET);
+ }
+
+@@ -163,8 +240,7 @@ gdev_tiff_begin_page(gx_device_printer * pdev, gdev_tiff_state * tifs,
+ /* Write count of tags in directory. */
+ {
+ TIFF_short dircount = ntags;
+-
+- fwrite((char *)&dircount, sizeof(dircount), 1, fp);
++ fwrite_short(dircount, fp, swap_bytes);
+ }
+ tifs->dir_off = ftell(fp);
+
+@@ -254,7 +330,8 @@ gdev_tiff_begin_page(gx_device_printer * pdev, gdev_tiff_state * tifs,
+ offset_of(TIFF_dir_entry, value);
+ }
+ }
+- tiff_fixup_tag(&entry); /* don't fix up indirects */
++ if (big_endian)
++ tiff_fixup_tag(&entry); /* don't fix up indirects */
+ if (entry.type & TIFF_INDIRECT) {
+ /* Fix up the offset for an indirect value. */
+ entry.type -= TIFF_INDIRECT;
+@@ -262,12 +339,13 @@ gdev_tiff_begin_page(gx_device_printer * pdev, gdev_tiff_state * tifs,
+ tifs->dir_off + ntags * sizeof(TIFF_dir_entry) +
+ (std ? 0 : std_value_size);
+ }
+- fwrite((char *)&entry, sizeof(entry), 1, fp);
++ fwrite_entry(&entry, fp, swap_bytes);
+ }
+
+ /* Write the indirect values. */
+- fwrite((const char *)&std_values, sizeof(std_values), 1, fp);
+- fwrite((const char *)values, value_size, 1, fp);
++ fwrite_std_values(&std_values, fp, swap_bytes);
++ if (values)
++ fwrite((const char *)values, value_size, 1, fp);
+ /* Write placeholders for the strip offsets. */
+ fwrite(tifs->StripOffsets, sizeof(TIFF_ulong), 2 * tifs->strip_count, fp);
+ tifs->strip_index = 0;
+@@ -299,21 +377,23 @@ gdev_tiff_end_strip(gdev_tiff_state * tifs, FILE * fp)
+
+ /* End a TIFF page. */
+ int
+-gdev_tiff_end_page(gdev_tiff_state * tifs, FILE * fp)
++gdev_tiff_end_page(gdev_tiff_state * tifs, FILE * fp, bool swap_bytes)
+ {
+ gs_memory_t *mem = tifs->mem;
+ long dir_off = tifs->dir_off;
+- int tags_size = tifs->ntags * sizeof(TIFF_dir_entry);
+-
++ int tags_size = tifs->ntags * sizeof(TIFF_dir_entry), i;
++
+ tifs->prev_dir =
+ dir_off + tags_size + offset_of(TIFF_std_directory_values, diroff);
+ tifs->dir_off = ftell(fp);
+ /* Patch strip byte counts and offsets values. */
+ /* The offset in the file was determined at begin_page and may be indirect */
+ fseek(fp, tifs->offset_StripOffsets, SEEK_SET);
+- fwrite(tifs->StripOffsets, sizeof(TIFF_ulong), tifs->strip_count, fp);
++ for (i=0; i<tifs->strip_count; i++)
++ fwrite_long(tifs->StripOffsets[i], fp, swap_bytes);
+ fseek(fp, tifs->offset_StripByteCounts, SEEK_SET);
+- fwrite(tifs->StripByteCounts, sizeof(TIFF_ulong), tifs->strip_count, fp);
++ for (i=0; i<tifs->strip_count; i++)
++ fwrite_long(tifs->StripByteCounts[i], fp, swap_bytes);
+ gs_free_object(mem, tifs->StripOffsets, "gdev_tiff_begin_page(StripOffsets)");
+ return 0;
+ }
+diff --git a/base/gdevtifs.h b/base/gdevtifs.h
+--- a/base/gdevtifs.h
++++ b/base/gdevtifs.h
+@@ -43,6 +43,9 @@ typedef unsigned long TIFF_ulong;
+ # endif
+ #endif
+
++#define SWAP_SHORT(x)\
++ x = x << 8 | x >> 8\
++
+ /*
+ * Define the TIFF file header.
+ */
+@@ -197,6 +200,16 @@ typedef struct gdev_tiff_state_s {
+ TIFF_ulong *StripByteCounts;
+ } gdev_tiff_state;
+
++typedef struct gx_device_tiff_s {
++ gx_device_common;
++ gx_prn_device_common;
++ bool BigEndian; /* true = big endian; false = little endian*/
++ gdev_tiff_state tiff;
++} gx_device_tiff;
++
++dev_proc_get_params(tiff_get_params);
++dev_proc_put_params(tiff_put_params);
++
+ /*
+ * Begin writing a TIFF page. This procedure supplies a standard set of
+ * tags; the client can provide additional tags (pre-sorted) and
+@@ -206,7 +219,7 @@ int gdev_tiff_begin_page(gx_device_printer * pdev, gdev_tiff_state * tifs,
+ FILE * fp,
+ const TIFF_dir_entry * entries, int entry_count,
+ const byte * values, int value_size,
+- long max_strip_size);
++ long max_strip_size, bool swap_bytes);
+
+ /*
+ * Finish writing a TIFF strip. All data written since begin or last
+@@ -218,6 +231,6 @@ int gdev_tiff_end_strip(gdev_tiff_state * tifs, FILE * fp);
+ * Finish writing a TIFF page. StripOffsets and StripByteCounts are
+ * patched into the file.
+ */
+-int gdev_tiff_end_page(gdev_tiff_state * tifs, FILE * fp);
++int gdev_tiff_end_page(gdev_tiff_state * tifs, FILE * fp, bool swap_bytes);
+
+ #endif /* gdevtifs_INCLUDED */
+diff --git a/base/gdevtrac.c b/base/gdevtrac.c
+--- a/base/gdevtrac.c
++++ b/base/gdevtrac.c
+@@ -318,7 +318,6 @@ trace_stroke_path(gx_device * dev, const gs_imager_state * pis,
+
+ typedef struct trace_image_enum_s {
+ gx_image_enum_common;
+- gs_memory_t *memory;
+ int rows_left;
+ } trace_image_enum_t;
+ gs_private_st_suffix_add0(st_trace_image_enum, trace_image_enum_t,
+diff --git a/base/gdevtsep.c b/base/gdevtsep.c
+--- a/base/gdevtsep.c
++++ b/base/gdevtsep.c
+@@ -38,24 +38,20 @@
+
+ /* ------ The tiffgray device ------ */
+
+-typedef struct gx_device_tiff_s {
+- gx_device_common;
+- gx_prn_device_common;
+- gdev_tiff_state tiff;
+-} gx_device_tiff;
+-
+ static dev_proc_print_page(tiffgray_print_page);
+
+ static const gx_device_procs tiffgray_procs =
+-prn_color_procs(gdev_prn_open, gdev_prn_output_page, gdev_prn_close,
+- gx_default_gray_map_rgb_color, gx_default_gray_map_color_rgb);
++prn_color_params_procs(gdev_prn_open, gdev_prn_output_page, gdev_prn_close,
++ gx_default_gray_map_rgb_color, gx_default_gray_map_color_rgb,
++ tiff_get_params, tiff_put_params);
+
+-const gx_device_printer gs_tiffgray_device = {
++const gx_device_tiff gs_tiffgray_device = {
+ prn_device_body(gx_device_tiff, tiffgray_procs, "tiffgray",
+ DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
+ X_DPI, Y_DPI,
+ 0, 0, 0, 0, /* Margins */
+- 1, 8, 255, 0, 256, 0, tiffgray_print_page)
++ 1, 8, 255, 0, 256, 0, tiffgray_print_page),
++ arch_is_big_endian /* default to native endian (i.e. use big endian iff the platform is so*/
+ };
+
+ /* ------ Private definitions ------ */
+@@ -93,15 +89,19 @@ tiffgray_print_page(gx_device_printer * pdev, FILE * file)
+ {
+ gx_device_tiff *const tfdev = (gx_device_tiff *)pdev;
+ int code;
++ bool swap_bytes = tfdev->BigEndian != arch_is_big_endian;
++ tiff_gray_values val_gray_swapped = val_gray_template;
++ if (swap_bytes)
++ SWAP_SHORT(val_gray_swapped.bps[0]);
+
+ if (pdev->height > (max_long - ftell(file))/(pdev->width)) /* note width is never 0 in print_page */
+ return_error(gs_error_rangecheck); /* this will overflow max_long */
+ /* Write the page directory. */
+ code = gdev_tiff_begin_page(pdev, &tfdev->tiff, file,
+ (const TIFF_dir_entry *)&dir_gray_template,
+- sizeof(dir_gray_template) / sizeof(TIFF_dir_entry),
+- (const byte *)&val_gray_template,
+- sizeof(val_gray_template), 0);
++ sizeof(dir_gray_template) / sizeof(TIFF_dir_entry),
++ (const byte *)&val_gray_swapped,
++ sizeof(val_gray_swapped), 0, swap_bytes);
+ if (code < 0)
+ return code;
+
+@@ -121,7 +121,7 @@ tiffgray_print_page(gx_device_printer * pdev, FILE * file)
+ fwrite((char *)row, raster, 1, file);
+ }
+ gdev_tiff_end_strip(&tfdev->tiff, file);
+- gdev_tiff_end_page(&tfdev->tiff, file);
++ gdev_tiff_end_page(&tfdev->tiff, file, swap_bytes);
+ gs_free_object(pdev->memory, line, "tiffgray_print_page");
+ }
+
+@@ -135,7 +135,7 @@ static dev_proc_print_page(tiff32nc_print_page);
+ #define cmyk_procs(p_map_color_rgb, p_map_cmyk_color)\
+ gdev_prn_open, NULL, NULL, gdev_prn_output_page, gdev_prn_close,\
+ NULL, p_map_color_rgb, NULL, NULL, NULL, NULL, NULL, NULL,\
+- gdev_prn_get_params, gdev_prn_put_params,\
++ tiff_get_params, tiff_put_params,\
+ p_map_cmyk_color, NULL, NULL, NULL, gx_page_device_get_page_device
+
+ /* 8-bit-per-plane separated CMYK color. */
+@@ -144,12 +144,13 @@ static const gx_device_procs tiff32nc_procs = {
+ cmyk_procs(cmyk_8bit_map_color_cmyk, cmyk_8bit_map_cmyk_color)
+ };
+
+-const gx_device_printer gs_tiff32nc_device = {
++const gx_device_tiff gs_tiff32nc_device = {
+ prn_device_body(gx_device_tiff, tiff32nc_procs, "tiff32nc",
+ DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
+ X_DPI, Y_DPI,
+ 0, 0, 0, 0, /* Margins */
+- 4, 32, 255, 255, 256, 256, tiff32nc_print_page)
++ 4, 32, 255, 255, 256, 256, tiff32nc_print_page),
++ arch_is_big_endian /* default to native endian (i.e. use big endian iff the platform is so*/
+ };
+
+ /* ------ Private definitions ------ */
+@@ -189,15 +190,23 @@ tiff32nc_print_page(gx_device_printer * pdev, FILE * file)
+ gx_device_tiff *const tfdev = (gx_device_tiff *)pdev;
+ int code;
+ ulong cur_size = gdev_prn_file_is_new(pdev) ? 0 : tfdev->tiff.dir_off;
++ tiff_cmyk_values val_cmyk_swapped = val_cmyk_template;
++ bool swap_bytes = tfdev->BigEndian != arch_is_big_endian;
++ if (swap_bytes)
++ {
++ int i;
++ for (i=0; i<4; i++)
++ SWAP_SHORT(val_cmyk_swapped.bps[i]);
++ }
+
+ if (pdev->height > (max_long - cur_size)/(pdev->width*4)) /* note width is never 0 in print_page */
+ return_error(gs_error_rangecheck); /* this will overflow max_long */
+ /* Write the page directory. */
+ code = gdev_tiff_begin_page(pdev, &tfdev->tiff, file,
+ (const TIFF_dir_entry *)&dir_cmyk_template,
+- sizeof(dir_cmyk_template) / sizeof(TIFF_dir_entry),
+- (const byte *)&val_cmyk_template,
+- sizeof(val_cmyk_template), 0);
++ sizeof(dir_cmyk_template) / sizeof(TIFF_dir_entry),
++ (const byte *)&val_cmyk_swapped,
++ sizeof(val_cmyk_swapped), 0, swap_bytes);
+ if (code < 0)
+ return code;
+
+@@ -217,7 +226,7 @@ tiff32nc_print_page(gx_device_printer * pdev, FILE * file)
+ fwrite((char *)row, raster, 1, file);
+ }
+ gdev_tiff_end_strip(&tfdev->tiff, file);
+- gdev_tiff_end_page(&tfdev->tiff, file);
++ gdev_tiff_end_page(&tfdev->tiff, file, swap_bytes);
+ gs_free_object(pdev->memory, line, "tiff32nc_print_page");
+ }
+
+@@ -259,6 +268,7 @@ typedef struct tiffsep_device_s {
+ /* tiff state for separation files */
+ gdev_tiff_state tiff[GX_DEVICE_COLOR_MAX_COMPONENTS];
+ FILE * sep_file[GX_DEVICE_COLOR_MAX_COMPONENTS];
++ bool BigEndian; /* true = big endian; false = little endian */
+ gs_devn_params devn_params; /* DeviceN generated parameters */
+ equivalent_cmyk_color_params equiv_cmyk_colors;
+ } tiffsep_device;
+@@ -392,7 +402,8 @@ gs_private_st_composite_final(st_tiffsep_device, tiffsep_device,
+ prn_device_body_rest_(tiffsep_print_page),\
+ { 0 }, /* tiff state for comp file */\
+ {{ 0 }}, /* tiff state for separation files */\
+- { 0 } /* separation files */
++ { 0 }, /* separation files */\
++ arch_is_big_endian /* true = big endian; false = little endian */
+
+ /*
+ * Select the default number of components based upon the number of bits
+@@ -579,12 +590,16 @@ static int
+ tiffsep_get_params(gx_device * pdev, gs_param_list * plist)
+ {
+ int code = gdev_prn_get_params(pdev, plist);
+-
+ if (code < 0)
+ return code;
+- return devn_get_params(pdev, plist,
++
++ code = devn_get_params(pdev, plist,
+ &(((tiffsep_device *)pdev)->devn_params),
+ &(((tiffsep_device *)pdev)->equiv_cmyk_colors));
++ if (code < 0)
++ return code;
++
++ return param_write_bool(plist, "BigEndian", &((tiffsep_device *)pdev)->BigEndian);
+ }
+
+ /* Set parameters. We allow setting the number of bits per component. */
+@@ -592,7 +607,19 @@ static int
+ tiffsep_put_params(gx_device * pdev, gs_param_list * plist)
+ {
+ tiffsep_device * const pdevn = (tiffsep_device *) pdev;
+-
++ int code;
++ const char *param_name;
++
++ /* Read BigEndian option as bool */
++ switch (code = param_read_bool(plist, (param_name = "BigEndian"), &pdevn->BigEndian)) {
++ default:
++ param_signal_error(plist, param_name, code);
++ return code;
++ case 0:
++ case 1:
++ break;
++ }
++
+ return devn_printer_put_params(pdev, plist,
+ &(pdevn->devn_params), &(pdevn->equiv_cmyk_colors));
+ }
+@@ -770,11 +797,18 @@ number_output_separations(int num_dev_comp, int num_std_colorants,
+ static void
+ build_comp_to_sep_map(tiffsep_device * pdev, short * map_comp_to_sep)
+ {
+- int num_sep = pdev->devn_params.separations.num_separations;
++ int num_sep = pdev->devn_params.page_spot_colors;
+ int num_std_colorants = pdev->devn_params.num_std_colorant_names;
+ int sep_num;
++ int num_channels;
+
+- for (sep_num = 0; sep_num < num_std_colorants + num_sep; sep_num++) {
++ /* since both proc colors and spot colors are packed in same encoded value we
++ need to have this limit */
++
++ num_channels =
++ ( (num_std_colorants + num_sep) < (GX_DEVICE_COLOR_MAX_COMPONENTS) ? (num_std_colorants + num_sep) : (GX_DEVICE_COLOR_MAX_COMPONENTS) );
++
++ for (sep_num = 0; sep_num < num_channels; sep_num++) {
+ int comp_num = pdev->devn_params.separation_order_map[sep_num];
+
+ if (comp_num >= 0 && comp_num < GX_DEVICE_COLOR_MAX_COMPONENTS)
+@@ -949,6 +983,14 @@ tiffsep_print_page(gx_device_printer * pdev, FILE * file)
+ const char *fmt;
+ gs_parsed_file_name_t parsed;
+ int non_encodable_count = 0;
++ tiff_cmyk_values val_cmyk_swapped = val_cmyk_template;
++ bool swap_bytes = tfdev->BigEndian != arch_is_big_endian;
++ if (swap_bytes)
++ {
++ int i;
++ for (i=0; i<4; i++)
++ SWAP_SHORT(val_cmyk_swapped.bps[i]);
++ }
+
+ build_comp_to_sep_map(tfdev, map_comp_to_sep);
+
+@@ -972,9 +1014,9 @@ tiffsep_print_page(gx_device_printer * pdev, FILE * file)
+ return_error(gs_error_rangecheck); /* this will overflow max_long */
+ code = gdev_tiff_begin_page(pdev, &tfdev->tiff_comp, file,
+ (const TIFF_dir_entry *)&dir_cmyk_template,
+- sizeof(dir_cmyk_template) / sizeof(TIFF_dir_entry),
+- (const byte *)&val_cmyk_template,
+- sizeof(val_cmyk_template), 0);
++ sizeof(dir_cmyk_template) / sizeof(TIFF_dir_entry),
++ (const byte *)&val_cmyk_swapped,
++ sizeof(val_cmyk_swapped), 0, swap_bytes);
+ pdev->color_info.depth = save_depth;
+ if (code < 0)
+ return code;
+@@ -1016,8 +1058,8 @@ tiffsep_print_page(gx_device_printer * pdev, FILE * file)
+ tfdev->sep_file[comp_num],
+ (const TIFF_dir_entry *)&dir_gray_template,
+ sizeof(dir_gray_template) / sizeof(TIFF_dir_entry),
+- (const byte *)&val_gray_template,
+- sizeof(val_gray_template), 0);
++ (const byte *)&val_cmyk_swapped,
++ sizeof(val_cmyk_swapped), 0, swap_bytes);
+ pdev->color_info.depth = save_depth;
+ if (code < 0)
+ return code;
+@@ -1069,12 +1111,12 @@ tiffsep_print_page(gx_device_printer * pdev, FILE * file)
+ }
+ /* Update the strip data */
+ gdev_tiff_end_strip(&(tfdev->tiff_comp), file);
+- gdev_tiff_end_page(&(tfdev->tiff_comp), file);
++ gdev_tiff_end_page(&(tfdev->tiff_comp), file, swap_bytes);
+ for (comp_num = 0; comp_num < num_comp; comp_num++ ) {
+ gdev_tiff_end_strip(&(tfdev->tiff[comp_num]),
+ tfdev->sep_file[comp_num]);
+ gdev_tiff_end_page(&(tfdev->tiff[comp_num]),
+- tfdev->sep_file[comp_num]);
++ tfdev->sep_file[comp_num], swap_bytes);
+ }
+ gs_free_object(pdev->memory, line, "tiffsep_print_page");
+ gs_free_object(pdev->memory, sep_line, "tiffsep_print_page");
+diff --git a/base/gdevvec.c b/base/gdevvec.c
+--- a/base/gdevvec.c
++++ b/base/gdevvec.c
+@@ -247,7 +247,7 @@ void
+ gdev_vector_reset(gx_device_vector * vdev)
+ {
+ static const gs_imager_state state_initial =
+- {gs_imager_state_initial(1)};
++ {gs_imager_state_initial(1, false)};
+
+ vdev->state = state_initial;
+ gx_hld_saved_color_init(&vdev->saved_fill_color);
+diff --git a/base/gsalloc.c b/base/gsalloc.c
+--- a/base/gsalloc.c
++++ b/base/gsalloc.c
+@@ -202,7 +202,7 @@ ialloc_alloc_state(gs_memory_t * parent, uint chunk_size)
+ iimem->large_size = ((chunk_size / 4) & -obj_align_mod) + 1;
+ iimem->is_controlled = false;
+ iimem->gc_status.vm_threshold = chunk_size * 3L;
+- iimem->gc_status.max_vm = max_long;
++ iimem->gc_status.max_vm = 0x7fffffff;
+ iimem->gc_status.psignal = NULL;
+ iimem->gc_status.signal_value = 0;
+ iimem->gc_status.enabled = false;
+diff --git a/base/gsccolor.h b/base/gsccolor.h
+--- a/base/gsccolor.h
++++ b/base/gsccolor.h
+@@ -64,4 +64,19 @@ extern_st(st_client_color);
+ client_color_enum_ptrs, client_color_reloc_ptrs, pattern)
+ #define st_client_color_max_ptrs 1
+
++/* Define the color space for a transparency */
++/* Used to keep track of parent versus child */
++/* color space changes with Smask and for */
++/* blending */
++typedef enum {
++ GRAY_SCALE,
++ DEVICE_RGB,
++ DEVICE_CMYK,
++ CIE_XYZ,
++ DEVICEN,
++ UNKNOWN,
++ OTHER
++} gs_transparency_color_t;
++
++
+ #endif /* gsccolor_INCLUDED */
+diff --git a/base/gscdef.c b/base/gscdef.c
+--- a/base/gscdef.c
++++ b/base/gscdef.c
+@@ -43,7 +43,7 @@ const char *const gs_productfamily = GS_PRODUCTFAMILY;
+
+ #ifndef GS_PRODUCT
+ # define GS_PRODUCT\
+- GS_PRODUCTFAMILY ""
++ GS_PRODUCTFAMILY " SVN PRE-RELEASE"
+ #endif
+ const char *const gs_product = GS_PRODUCT;
+
+diff --git a/base/gscolor2.c b/base/gscolor2.c
+--- a/base/gscolor2.c
++++ b/base/gscolor2.c
+@@ -239,20 +239,10 @@ gx_final_Indexed(const gs_color_space * pcs)
+ rc_adjust_const(pcs->params.indexed.lookup.map, -1,
+ "gx_adjust_Indexed");
+ } else {
+- /* Bug 689822 "Memory leaks during rendering clist."
+- */
+-#if 0 /* Disabled due to bug 689990 "pcl6.exe crash with gs revision 8928".
+- Rather this automatic freeing of pcs->params.indexed.lookup.table.data
+- complies to a fundamental change of Revision 7765 "Non-backwards compatible change:
+- use consistent reference count allocation discipline for color spaces.",
+- some interpreters still don't fully comply to the discipline.
+- It caused a crash in memory management due to dual attempt to free the string.
+- */
+ byte *data = (byte *)pcs->params.indexed.lookup.table.data; /* Break 'const'. */
+
+ gs_free_string(pcs->rc.memory, data,
+ pcs->params.indexed.lookup.table.size, "gx_final_Indexed");
+-#endif
+ }
+ }
+
+diff --git a/base/gscolorbuffer.c b/base/gscolorbuffer.c
+new file mode 100644
+--- /dev/null
++++ b/base/gscolorbuffer.c
+@@ -0,0 +1,270 @@
++/* Copyright (C) 2001-2009 Artifex Software, Inc.
++ All Rights Reserved.
++
++ This software is provided AS-IS with no warranty, either express or
++ implied.
++
++ This software is distributed under license and may not be copied, modified
++ or distributed except as expressly authorized under the terms of that
++ license. Refer to licensing information at http://www.artifex.com/
++ or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
++ San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
++*/
++
++
++/* Simple operators and place holding support for doing conversions on buffers
++ of data. These functions perform device (non CIE or ICC color conversions)
++ on buffers of data. Eventually these will be replaced with functions for
++ using the ICC based linked mappings with the external CMS. This is far from
++ efficient at this point, but gets the job done */
++
++#include "string_.h"
++#include "stdpre.h"
++#include "gstypes.h"
++#include "gsmemory.h"
++#include "gxblend.h"
++#include "gscolorbuffer.h"
++
++#define float_color_to_byte_color(float_color) ( \
++ (0.0 < (float_color) && (float_color) < 1.0) ? \
++ ((unsigned char) ((float_color) * 255.0)) : \
++ (((float_color) <= 0.0) ? 0x00 : 0xFF) \
++ )
++
++/* We could use the conversions that are defined in gxdcconv.c,
++ however for now we will use something even easier. This is
++ temporary until we get the proper ICC flows in place */
++
++static void
++rgb_to_cmyk(byte rgb[],byte cmyk[])
++{
++
++ /* Real sleazy min black generation */
++
++ cmyk[0] = 255 - rgb[0];
++ cmyk[1] = 255 - rgb[1];
++ cmyk[2] = 255 - rgb[2];
++
++ cmyk[3] = (cmyk[0] < cmyk[1]) ?
++ min(cmyk[0], cmyk[2]) : min(cmyk[1], cmyk[2]);
++
++}
++
++static void
++rgb_to_gray(byte rgb[], byte gray[])
++{
++
++ float temp_value;
++
++ /* compute a luminance component */
++ temp_value = rgb[0]*0.3 + rgb[1]*0.59 + rgb[2]*0.11;
++ temp_value = temp_value * (1.0 / 255.0 ); /* May need to be optimized */
++ gray[0] = float_color_to_byte_color(temp_value);
++
++}
++
++static void
++cmyk_to_rgb(byte cmyk[], byte rgb[])
++{
++
++ /* real ugly, but temporary */
++
++ rgb[0] = 255 - min(cmyk[0] + cmyk[3],255);
++ rgb[1] = 255 - min(cmyk[1] + cmyk[3],255);
++ rgb[2] = 255 - min(cmyk[2] + cmyk[3],255);
++
++}
++
++static void
++cmyk_to_gray(byte cmyk[], byte gray[])
++{
++
++ float temp_value;
++
++ temp_value = ((255 - cmyk[0])*0.3 +
++ (255 - cmyk[1])*0.59 +
++ (255 - cmyk[2]) * 0.11) * (255 - cmyk[3]);
++ temp_value = temp_value * (1.0 / 65025.0 );
++
++ gray[0] = float_color_to_byte_color(temp_value);
++
++}
++
++static void
++gray_to_cmyk(byte gray[], byte cmyk[])
++{
++
++ /* Just do black. */
++ cmyk[0] = 0;
++ cmyk[1] = 0;
++ cmyk[2] = 0;
++ cmyk[3] = 255 - gray[0];
++
++}
++
++static void
++gray_to_rgb(byte gray[], byte rgb[])
++{
++
++ rgb[0] = gray[0];
++ rgb[1] = gray[0];
++ rgb[2] = gray[0];
++
++}
++
++
++void
++gs_transform_color_buffer_generic(byte *inputbuffer,
++ int row_stride, int plane_stride,
++ int input_num_color, gs_int_rect rect, byte *outputbuffer,
++ int output_num_color, int num_noncolor_planes)
++
++{
++ int num_rows, num_cols, x, y, z;
++ void (* color_remap)(byte input[],byte output[]) = NULL;
++ byte input_vector[4],output_vector[4];
++ int plane_offset[PDF14_MAX_PLANES],alpha_offset_in,max_num_channels;
++
++ num_rows = rect.q.y - rect.p.y;
++ num_cols = rect.q.x - rect.p.x;
++
++ /* Check for spot + cmyk case */
++
++ if (output_num_color > 4)
++ {
++
++ /* To CMYK always */
++ switch (input_num_color) {
++
++ case 1:
++ color_remap = gray_to_cmyk;
++ break;
++
++ case 3:
++ color_remap = rgb_to_cmyk;
++ break;
++
++ case 4:
++ color_remap = NULL; /* Copy data */
++ break;
++
++ default:
++
++ /* Should never be here. Groups must
++ be gray, rgb or CMYK. Exception
++ may be ICC with XPS */
++
++ break;
++
++ }
++
++ } else {
++
++ /* Pick the mapping to use */
++
++ switch (input_num_color) {
++
++ case 1:
++ if (output_num_color == 3)
++ color_remap = gray_to_rgb;
++ else
++ color_remap = gray_to_cmyk;
++ break;
++
++ case 3:
++ if (output_num_color == 1)
++ color_remap = rgb_to_gray;
++ else
++ color_remap = rgb_to_cmyk;
++ break;
++
++ case 4:
++ if (output_num_color == 1)
++ color_remap = cmyk_to_gray;
++ else
++ color_remap = cmyk_to_rgb;
++ break;
++
++ default:
++
++ /* Should never be here. Groups must
++ be gray, rgb or CMYK. Until we
++ have ICC working here with XPS */
++
++ break;
++
++ }
++
++ }
++
++ /* data is planar */
++
++ max_num_channels = max(input_num_color, output_num_color) +
++ num_noncolor_planes;
++
++ for (z = 0; z < max_num_channels; z++)
++ plane_offset[z] = z * plane_stride;
++
++ if (color_remap == NULL) {
++
++ /* Blending group was CMYK, output is CMYK + spot */
++
++ memcpy(outputbuffer, inputbuffer, 4*plane_stride);
++
++ /* Add any data that are beyond the standard color data (e.g. alpha) */
++
++ if (num_noncolor_planes > 0)
++ memcpy(&(outputbuffer[plane_offset[output_num_color]]),
++ &(inputbuffer[plane_offset[input_num_color]]),
++ num_noncolor_planes*plane_stride);
++
++ } else {
++
++ /* Have to remap */
++
++ alpha_offset_in = input_num_color*plane_stride;
++
++ for (y = 0; y < num_rows; y++) {
++
++ for (x = 0; x < num_cols; x++) {
++
++ /* If the source alpha is transparent, then move on */
++
++ if (inputbuffer[x + alpha_offset_in] != 0x00) {
++
++ /* grab the input */
++
++ for (z = 0; z<input_num_color; z++)
++ input_vector[z] = inputbuffer[x+plane_offset[z]];
++
++ /* convert */
++
++ color_remap(input_vector,output_vector);
++
++ /* store the output */
++
++ for (z = 0; z < output_num_color; z++)
++ outputbuffer[x+plane_offset[z]] = output_vector[z];
++
++ /* Add any that are beyond the standard color data */
++
++ for(z = 0; z < num_noncolor_planes; z++)
++ outputbuffer[x + plane_offset[output_num_color+z]] =
++ inputbuffer[x + plane_offset[input_num_color+z]];
++
++ }
++
++ }
++
++ /* update our positions */
++
++ for (z = 0; z < max_num_channels; z++)
++ plane_offset[z] += row_stride;
++
++ alpha_offset_in += row_stride;
++
++ }
++
++ }
++
++}
+diff --git a/base/gscolorbuffer.h b/base/gscolorbuffer.h
+new file mode 100644
+--- /dev/null
++++ b/base/gscolorbuffer.h
+@@ -0,0 +1,25 @@
++/* Copyright (C) 2001-2006 Artifex Software, Inc.
++ All Rights Reserved.
++
++ This software is provided AS-IS with no warranty, either express or
++ implied.
++
++ This software is distributed under license and may not be copied, modified
++ or distributed except as expressly authorized under the terms of that
++ license. Refer to licensing information at http://www.artifex.com/
++ or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
++ San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
++*/
++
++/* Client color structure definition */
++
++/* Simple operators and place holding support for doing conversions on buffers
++ of data. These functions perform device (non CIE or ICC color conversions)
++ on buffers of data. Eventually these will be replaced with functions for
++ using the ICC based linked mappings with the external CMS. */
++
++/* This just does planar data for now */
++void gs_transform_color_buffer_generic(byte *inputbuffer,
++ int rowstride, int planestride,
++ int input_num_color, gs_int_rect rect,byte *outputbuffer,
++ int output_num_color,int num_noncolor_planes);
+diff --git a/base/gscspace.c b/base/gscspace.c
+--- a/base/gscspace.c
++++ b/base/gscspace.c
+@@ -193,6 +193,12 @@ bool gs_color_space_is_CIE(const gs_color_space * pcs)
+
+ }
+
++/* See if the space is ICC based */
++bool gs_color_space_is_ICC(const gs_color_space * pcs)
++{
++ return(gs_color_space_get_index(pcs) == gs_color_space_index_CIEICC);
++}
++
+
+ /* Get the number of components in a color space. */
+ int
+diff --git a/base/gscspace.h b/base/gscspace.h
+--- a/base/gscspace.h
++++ b/base/gscspace.h
+@@ -289,8 +289,9 @@ gs_color_space *gs_cspace_new_DeviceCMYK(gs_memory_t *mem);
+ /* Get the index of a color space. */
+ gs_color_space_index gs_color_space_get_index(const gs_color_space *);
+
+-/* Tell if the space is CIE based */
++/* Tell if the space is CIE or ICC based */
+ bool gs_color_space_is_CIE(const gs_color_space * pcs);
++bool gs_color_space_is_ICC(const gs_color_space * pcs);
+
+ /* Get the number of components in a color space. */
+ int gs_color_space_num_components(const gs_color_space *);
+diff --git a/base/gserror.h b/base/gserror.h
+--- a/base/gserror.h
++++ b/base/gserror.h
+@@ -60,7 +60,7 @@ int gs_throw_imp(const char *func, const char *file, int line,
+ /* Use throw at origin of error
+ */
+ #define gs_throw_code(code) \
+- gs_throw((code), gs_errstr((code)))
++ gs_throw1((code), "%s", gs_errstr((code)))
+
+ #define gs_throw(code, fmt) \
+ gs_throw_imp(__func__, __FILE__, __LINE__, 0, code, fmt)
+@@ -87,7 +87,7 @@ int gs_throw_imp(const char *func, const char *file, int line,
+ /* Bubble the code up the stack
+ */
+ #define gs_rethrow_code(code) \
+- gs_rethrow((code), gs_errstr((code)))
++ gs_rethrow1((code), "%s", gs_errstr((code)))
+
+ #define gs_rethrow(code, fmt) \
+ gs_throw_imp(__func__, __FILE__, __LINE__, 1, code, fmt)
+diff --git a/base/gsfont.c b/base/gsfont.c
+--- a/base/gsfont.c
++++ b/base/gsfont.c
+@@ -269,6 +269,7 @@ gs_font_dir_alloc2_limits(gs_memory_t * struct_mem, gs_memory_t * bits_mem,
+ pdir->san = 0;
+ pdir->global_glyph_code = NULL;
+ pdir->text_enum_id = 0;
++ pdir->hash = 42; /* initialize the hash to a randomly picked number */
+ return pdir;
+ }
+
+diff --git a/base/gsht1.c b/base/gsht1.c
+--- a/base/gsht1.c
++++ b/base/gsht1.c
+@@ -344,8 +344,10 @@ process_transfer(gx_ht_order * porder, gs_state * pgs,
+ pmap->proc = proc; /* 0 => use closure */
+ pmap->closure = *pmc;
+ pmap->id = gs_next_ids(mem, 1);
+- load_transfer_map(pgs, pmap, 0.0);
+ porder->transfer = pmap;
++ if (proc == gs_mapped_transfer)
++ return 0; /* nothing to load, the source is uninitialzed */
++ load_transfer_map(pgs, pmap, 0.0);
+ return 0;
+ }
+
+diff --git a/base/gsicc.c b/base/gsicc.c
+--- a/base/gsicc.c
++++ b/base/gsicc.c
+@@ -1,6 +1,6 @@
+ /* Copyright (C) 2001-2006 Artifex Software, Inc.
+ All Rights Reserved.
+-
++
+ This software is provided AS-IS with no warranty, either express or
+ implied.
+
+@@ -95,7 +95,7 @@ RELOC_PTRS_END
+ * Color space methods for ICCBased color spaces.
+ *
+ * As documented, ICCBased color spaces may be used as both base and
+- * alternative color spaces. Futhermore,, they can themselves contain paint
++ * alternative color spaces. Futhermore, they can themselves contain paint
+ * color spaces as alternative color space. In this implementation we allow
+ * them to be used as base and alternative color spaces, but only to contain
+ * "small" base color spaces (CIEBased or smaller). This arrangement avoids
+@@ -104,9 +104,9 @@ RELOC_PTRS_END
+ *
+ * Several of the methods used by ICCBased color space apply as well to
+ * DeviceN color spaces, in that they are generic to color spaces having
+- * a variable number of components. We have elected not to attempt to
++ * a variable number of components. We have elected not to attempt to
+ * extract and combine these operations, because this would save only a
+- * small amount of code, and much more could be saved by intorducing certain
++ * small amount of code, and much more could be saved by introducing certain
+ * common elements (ranges, number of components, etc.) into the color space
+ * root class.
+ */
+@@ -141,7 +141,7 @@ static const gs_color_space_type gs_color_space_type_CIEICC = {
+ gx_spot_colors_set_overprint, /* set_overprint */
+ gx_final_CIEICC, /* final */
+ gx_no_adjust_color_count, /* adjust_color_count */
+- gx_serialize_CIEICC, /* serialize */
++ gx_serialize_CIEICC, /* serialize */
+ gx_cspace_is_linear_default
+ };
+
+@@ -192,11 +192,11 @@ gx_restrict_CIEICC(gs_client_color * pcc, const gs_color_space * pcs)
+ }
+
+ /*
+- * Return the conrecte space to which this color space will map. If the
++ * Return the concrete space to which this color space will map. If the
+ * ICCBased color space is being used in native mode, the concrete space
+ * will be dependent on the current color rendering dictionary, as it is
+ * for all CIE bases. If the alternate color space is being used, then
+- * this question is passed on the the appropriate method of that space.
++ * this question is passed on to the appropriate method of that space.
+ */
+ static const gs_color_space *
+ gx_concrete_space_CIEICC(const gs_color_space * pcs, const gs_imager_state * pis)
+@@ -253,8 +253,9 @@ gx_concretize_CIEICC(
+ gx_restrict_CIEICC(&lcc, pcs);
+ for (i = 0; i < ncomps; i++)
+ inv[i] = lcc.paint.values[i];
+-
+- /* Since the original limits were wrong for this case, We need to adjust things a bit different */
++
++ /* Since the original limits were wrong for this case,
++ we need to adjust things a bit different */
+
+ /* For input Lab color space massage the values into Lab range */
+
+@@ -262,7 +263,7 @@ gx_concretize_CIEICC(
+
+ inv[0] *= 100;
+ inv[1] = inv[1]*255 - 128;
+- inv[2] = inv[2]*255 - 128;
++ inv[2] = inv[2]*255 - 128;
+
+ } */
+
+@@ -441,7 +442,7 @@ gx_load_icc_profile(gs_cie_icc *picc_info)
+ FILE *fid;
+
+ #endif
+-
++
+ /* verify that the file is legitimate */
+ if (picc_info->file_id != (instrp->read_id | instrp->write_id))
+ return_error(gs_error_ioerror);
+@@ -449,7 +450,7 @@ gx_load_icc_profile(gs_cie_icc *picc_info)
+ * Load the top-level ICC profile.
+ *
+ * If an ICC profile fails to load, generate an error.
+- *
++ *
+ * Testing demonstrates, however, Acrobat Reader silently
+ * ignores the error and uses the alternate color space.
+ * This behaviour is implemented by catching the error using
+@@ -467,7 +468,7 @@ gx_load_icc_profile(gs_cie_icc *picc_info)
+ gs_vector3 * ppt;
+
+ pfile = gx_wrap_icc_stream (instrp);
+-
++
+ if ((picc->read(picc, pfile, 0)) != 0)
+ goto return_rangecheck;
+
+@@ -483,8 +484,8 @@ gx_load_icc_profile(gs_cie_icc *picc_info)
+ free(iccbuffer);
+
+ #endif
+-
+-
++
++
+ /* verify the profile type */
+ profile_class = picc->header->deviceClass;
+ if ( profile_class != icSigInputClass &&
+@@ -540,7 +541,7 @@ gx_load_icc_profile(gs_cie_icc *picc_info)
+ * If absolute colorimetry is employed, the XYZ or L*a*b* values
+ * generated will be absolute in the chromatic sense (they are
+ * not literally "absolute", as we still must have overall
+- * intensity information inorder to determine weighted spectral
++ * intensity information in order to determine weighted spectral
+ * power levels). To achieve relative colorimetry for the output,
+ * these colors must be evaluated relative to the source white
+ * and black points. Hence, in this case, the appropriate white
+@@ -575,7 +576,7 @@ gx_load_icc_profile(gs_cie_icc *picc_info)
+ if (plu == NULL)
+ goto return_rangecheck;
+
+- /*
++ /*
+ * Get the appropriate white and black points. See the note on
+ * rendering intent above for a discussion of why we are using
+ * the profile space illuminant and pure black. (Pure black need
+@@ -673,7 +674,7 @@ gs_cspace_build_CIEICC(
+ * valid WhitepPoint since PostScript always requires this, but ICC
+ * assumes a D50 WhitePoint as a default
+ */
+- picc_info->common.points.WhitePoint.u = (float)0.9642; /* Profile illuminant - D50 */
++ picc_info->common.points.WhitePoint.u = (float)0.9642; /* Profile illuminant - D50 */
+ picc_info->common.points.WhitePoint.v = 1.0000;
+ picc_info->common.points.WhitePoint.w = (float)0.8249;
+ picc_info->common.install_cspace = gx_install_CIEICC;
+@@ -692,7 +693,7 @@ gs_cspace_build_CIEICC(
+
+ /* ---------------- Serialization. -------------------------------- */
+
+-static int
++static int
+ gx_serialize_CIEICC(const gs_color_space * pcs, stream * s)
+ {
+ const gs_icc_params * p = &pcs->params.icc;
+diff --git a/base/gsiodev.c b/base/gsiodev.c
+--- a/base/gsiodev.c
++++ b/base/gsiodev.c
+@@ -20,6 +20,7 @@
+ #include "gserrors.h"
+ #include "gp.h"
+ #include "gscdefs.h"
++#include "gsfname.h"
+ #include "gsparam.h"
+ #include "gsstruct.h"
+ #include "gxiodev.h"
+@@ -351,3 +352,84 @@ gs_fopen_errno_to_code(int eno)
+ return_error(gs_error_ioerror);
+ }
+ }
++
++/* Generic interface for filesystem enumeration given a path that may */
++/* include a %iodev% prefix */
++
++typedef struct gs_file_enum_s gs_file_enum;
++struct gs_file_enum_s {
++ gs_memory_t *memory;
++ gx_io_device *piodev; /* iodev's are static, so don't need GC tracing */
++ file_enum *pfile_enum;
++ int prepend_iodev_name;
++};
++
++gs_private_st_ptrs1(st_gs_file_enum, gs_file_enum, "gs_file_enum",
++ gs_file_enum_enum_ptrs, gs_file_enum_reloc_ptrs, pfile_enum);
++
++file_enum *
++gs_enumerate_files_init(const char *pat, uint patlen, gs_memory_t * mem)
++{
++ file_enum *pfen;
++ gs_file_enum *pgs_file_enum;
++ gx_io_device *iodev = NULL;
++ gs_parsed_file_name_t pfn;
++ int code = 0;
++
++ /* Get the iodevice */
++ code = gs_parse_file_name(&pfn, pat, patlen);
++ if (code < 0)
++ return NULL;
++ iodev = (pfn.iodev == NULL) ? iodev_default : pfn.iodev;
++
++ /* Check for several conditions that just cause us to return success */
++ if (pfn.len == 0 || iodev->procs.enumerate_files == iodev_no_enumerate_files) {
++ return NULL; /* no pattern, or device not found -- just return */
++ }
++ pfen = iodev->procs.enumerate_files(iodev, (const char *)pfn.fname,
++ pfn.len, mem);
++ if (pfen == 0)
++ return NULL;
++ pgs_file_enum = gs_alloc_struct(mem, gs_file_enum, &st_gs_file_enum,
++ "gs_enumerate_files_init");
++ if (pgs_file_enum == 0)
++ return NULL;
++ pgs_file_enum->memory = mem;
++ pgs_file_enum->piodev = iodev;
++ pgs_file_enum->pfile_enum = pfen;
++ pgs_file_enum->prepend_iodev_name = (pfn.iodev != NULL);
++ return (file_enum *)pgs_file_enum;
++}
++
++uint
++gs_enumerate_files_next(file_enum * pfen, char *ptr, uint maxlen)
++{
++ gs_file_enum *pgs_file_enum = (gs_file_enum *)pfen;
++ int iodev_name_len = pgs_file_enum->prepend_iodev_name ?
++ strlen(pgs_file_enum->piodev->dname) : 0;
++ uint return_len;
++
++ if (iodev_name_len > maxlen)
++ return maxlen + 1; /* signal overflow error */
++ if (iodev_name_len > 0)
++ memcpy(ptr, pgs_file_enum->piodev->dname, iodev_name_len);
++ return_len = pgs_file_enum->piodev->procs.enumerate_next(pgs_file_enum->pfile_enum,
++ ptr + iodev_name_len, maxlen - iodev_name_len);
++ if (return_len == ~0) {
++ gs_memory_t *mem = pgs_file_enum->memory;
++
++ gs_free_object(mem, pgs_file_enum, "gs_enumerate_files_close");
++ return ~0;
++ }
++ return return_len+iodev_name_len;
++}
++
++void
++gs_enumerate_files_close(file_enum * pfen)
++{
++ gs_file_enum *pgs_file_enum = (gs_file_enum *)pfen;
++ gs_memory_t *mem = pgs_file_enum->memory;
++
++ pgs_file_enum->piodev->procs.enumerate_close(pgs_file_enum->pfile_enum);
++ gs_free_object(mem, pgs_file_enum, "gs_enumerate_files_close");
++}
+diff --git a/base/gsiorom.c b/base/gsiorom.c
+--- a/base/gsiorom.c
++++ b/base/gsiorom.c
+@@ -148,6 +148,7 @@ s_block_read_seek(register stream * s, long pos)
+ s->position = pos - offset;
+ pw.ptr = s->cbuf - 1;
+ pw.limit = pw.ptr + s->cbsize;
++ s->srptr = s->srlimit = s->cbuf - 1;
+ if ((s->end_status = s_block_read_process((stream_state *)s, NULL, &pw, 0)) == ERRC)
+ return ERRC;
+ if (s->end_status == 1)
+@@ -181,41 +182,58 @@ s_block_read_process(stream_state * st, stream_cursor_read * ignore_pr,
+ int status = 1;
+ int compression = ((get_u32_big_endian(node) & 0x80000000) != 0) ? 1 : 0;
+ uint32_t filelen = get_u32_big_endian(node) & 0x7fffffff; /* ignore compression bit */
+- uint32_t blocks = (filelen+ROMFS_BLOCKSIZE-1)/ ROMFS_BLOCKSIZE;
+- int iblock = (s->position + s->file_offset + pw->ptr + 1 - s->cbuf) / ROMFS_BLOCKSIZE;
+- unsigned long block_length = get_u32_big_endian(node+1+(2*iblock));
+- unsigned const long block_offset = get_u32_big_endian(node+2+(2*iblock));
++ uint32_t blocks = (filelen+ROMFS_BLOCKSIZE-1) / ROMFS_BLOCKSIZE;
++ uint32_t iblock = (s->position + s->file_offset + (s->srlimit + 1 - s->cbuf)) / ROMFS_BLOCKSIZE;
++ uint32_t block_length = get_u32_big_endian(node+1+(2*iblock));
++ uint32_t block_offset = get_u32_big_endian(node+2+(2*iblock));
+ unsigned const char *block_data = ((unsigned char *)node) + block_offset;
+ int count = iblock < (blocks - 1) ? ROMFS_BLOCKSIZE : filelen - (ROMFS_BLOCKSIZE * iblock);
+
+- if (count > max_count) {
+- return ERRC; /* should not happen */
+- }
+- if (block_data == NULL) {
+- return EOFC;
+- }
++ if (s->position == filelen || block_data == NULL)
++ return EOFC; /* at EOF */
+ if (s->file_limit < max_long) {
+- long limit_count = s->file_offset + s->file_limit - s->position;
++ /* Adjust count for subfile limit */
++ uint32_t limit_count = s->file_offset + s->file_limit - s->position;
+
+ if (count > limit_count)
+ count = limit_count;
+ }
+-
+- if (count < ROMFS_BLOCKSIZE || iblock == (blocks - 1))
+- status = EOFC; /* at EOF when not filling entire buffer */
+ /* get the block into the buffer */
+ if (compression) {
+ unsigned long buflen = ROMFS_BLOCKSIZE;
++ const byte *dest = (pw->ptr + 1); /* destination for unpack */
++ int need_copy = false;
+
++ /* If the dest is not in our buffer, we can only use it if there */
++ /* is enough space in it */
++ if ((dest < s->cbuf) || (dest >= (s->cbuf + s->cbsize))) {
++ /* the destination is _not_ in our buffer. If the area isn't */
++ /* big enough we need to ucompress to our buffer, then copy */
++ /* the data afterward. INVARIANT: if the buffer is outside */
++ /* the cbuf, then the cbuf must be empty. */
++ if (max_count < count) {
++#ifdef DEBUG
++ if ((sbufptr(s)) != s->srlimit)
++ eprintf("cbuf not empty as expected\n.");
++#endif
++ dest = s->cbuf;
++ need_copy = true;
++ }
++ }
+ /* Decompress the data into this block */
+- code = uncompress (pw->ptr+1, &buflen, block_data, block_length);
+- if (count != buflen) {
++ code = uncompress (dest, &buflen, block_data, block_length);
++ if (count != buflen)
+ return ERRC;
++ if (need_copy) {
++ memcpy(pw->ptr+1, dest, max_count);
++ count = max_count;
+ }
+ } else {
+ /* not compressed -- just copy it */
+- memcpy(pw->ptr+1, block_data, block_length);
+ count = block_length;
++ if (count > max_count)
++ count = max_count;
++ memcpy(pw->ptr+1, block_data, count);
+ }
+ if (count < 0)
+ count = 0;
+@@ -353,7 +371,7 @@ romfs_enumerate_next(file_enum *pfen, char *ptr, uint maxlen)
+ while (gs_romfs[penum->list_index] != 0) {
+ const uint32_t *node = gs_romfs[penum->list_index];
+ uint32_t filelen = get_u32_big_endian(node) & 0x7fffffff; /* ignore compression bit */
+- long blocks = (filelen+ROMFS_BLOCKSIZE-1)/ ROMFS_BLOCKSIZE;
++ uint32_t blocks = (filelen+ROMFS_BLOCKSIZE-1)/ ROMFS_BLOCKSIZE;
+ char *filename = (char *)(&(node[1+(2*blocks)]));
+
+ penum->list_index++; /* bump to next unconditionally */
+diff --git a/base/gsistate.c b/base/gsistate.c
+--- a/base/gsistate.c
++++ b/base/gsistate.c
+@@ -63,7 +63,8 @@ ENUM_PTRS_BEGIN(imager_state_enum_ptrs)
+ ENUM_SUPER(gs_imager_state, st_line_params, line_params, st_imager_state_num_ptrs - st_line_params_num_ptrs);
+ ENUM_PTR(0, gs_imager_state, client_data);
+ ENUM_PTR(1, gs_imager_state, transparency_stack);
+-#define E1(i,elt) ENUM_PTR(i+2,gs_imager_state,elt);
++ ENUM_PTR(2, gs_imager_state, trans_device);
++#define E1(i,elt) ENUM_PTR(i+3,gs_imager_state,elt);
+ gs_cr_state_do_ptrs(E1)
+ #undef E1
+ ENUM_PTRS_END
+@@ -72,6 +73,7 @@ static RELOC_PTRS_BEGIN(imager_state_reloc_ptrs)
+ RELOC_SUPER(gs_imager_state, st_line_params, line_params);
+ RELOC_PTR(gs_imager_state, client_data);
+ RELOC_PTR(gs_imager_state, transparency_stack);
++ RELOC_PTR(gs_imager_state, trans_device);
+ #define R1(i,elt) RELOC_PTR(gs_imager_state,elt);
+ gs_cr_state_do_ptrs(R1)
+ #undef R1
+@@ -93,6 +95,7 @@ gs_imager_state_initialize(gs_imager_state * pis, gs_memory_t * mem)
+ pis->memory = mem;
+ pis->client_data = 0;
+ pis->transparency_stack = 0;
++ pis->trans_device = 0;
+ /* Color rendering state */
+ pis->halftone = 0;
+ {
+diff --git a/base/gsmchunk.c b/base/gsmchunk.c
+--- a/base/gsmchunk.c
++++ b/base/gsmchunk.c
+@@ -362,8 +362,13 @@ chunk_obj_alloc(gs_memory_t *mem, uint size, gs_memory_type_ptr_t type, client_n
+ }
+ if (current == NULL) {
+ /* No chunks with enough space, allocate one */
+- if (chunk_mem_node_add(cmem, newsize, &current) < 0)
++ if (chunk_mem_node_add(cmem, newsize, &current) < 0) {
++#ifdef DEBUG
++ if (gs_debug_c('a'))
++ dlprintf1("[a+]chunk_obj_alloc(chunk_mem_node_add)(%u) Failed.\n", size);
++#endif
+ return NULL;
++ }
+ }
+ /* Find the first free area in the current chunk that is big enough */
+ /* LATER: might be better to find the 'best fit' */
+@@ -423,6 +428,11 @@ chunk_obj_alloc(gs_memory_t *mem, uint size, gs_memory_type_ptr_t type, client_n
+ }
+
+ /* return the client area of the object we allocated */
++#ifdef DEBUG
++ if (gs_debug_c('A'))
++ dlprintf3("[a+]chunk_obj_alloc (%s)(%u) = 0x%lx: OK.\n",
++ client_name_string(cname), size, (ulong) newobj);
++#endif
+ return (byte *)(newobj) + sizeof(chunk_obj_node_t);
+ }
+
+@@ -484,13 +494,21 @@ chunk_alloc_struct_array(gs_memory_t * mem, uint num_elements,
+ static void *
+ chunk_resize_object(gs_memory_t * mem, void *ptr, uint new_num_elements, client_name_t cname)
+ {
+- /* get the type from the old object */
+- chunk_obj_node_t *obj = ((chunk_obj_node_t *)ptr) - 1;
+- uint new_size = (obj->type->ssize * new_num_elements);
+-
+ /* This isn't particularly efficient, but it is rarely used */
++ chunk_obj_node_t *obj = ((chunk_obj_node_t *)ptr) - 1;
++ ulong new_size = (obj->type->ssize * new_num_elements);
++ ulong old_size = obj->size;
++ /* get the type from the old object */
++ gs_memory_type_ptr_t type = obj->type;
++ void *new_ptr;
++
++ if (new_size == old_size)
++ return ptr;
++ if ((new_ptr = chunk_obj_alloc(mem, new_size, type, cname)) == 0)
++ return 0;
++ memcpy(new_ptr, ptr, min(old_size, new_size));
+ chunk_free_object(mem, ptr, cname);
+- return chunk_obj_alloc(mem, new_size, obj->type, cname);
++ return new_ptr;
+ }
+
+ static void
+@@ -542,6 +560,9 @@ chunk_free_object(gs_memory_t * mem, void *ptr, client_name_t cname)
+ else
+ prev_obj->next = obj->next;
+
++ if_debug3('A', "[a-]chunk_free_object(%s) 0x%lx(%u)\n",
++ client_name_string(cname), (ulong) ptr, obj->size);
++
+ /* Add this object's space (including the header) to the free list */
+
+ /* Scan free list to find where this element goes */
+diff --git a/base/gsovrc.c b/base/gsovrc.c
+--- a/base/gsovrc.c
++++ b/base/gsovrc.c
+@@ -82,7 +82,8 @@ read_color_index(gx_color_index * pcindex, const byte * data, uint size)
+ if (++nbytes > size)
+ return_error(gs_error_rangecheck);
+ else {
+- int c = *data;
++ unsigned char byte = *data;
++ gx_color_index c = byte;
+
+ cindex += (c & 0x7f) << shift;
+ if ((c & 0x80) == 0)
+diff --git a/base/gsparam2.c b/base/gsparam2.c
+--- a/base/gsparam2.c
++++ b/base/gsparam2.c
+@@ -373,7 +373,7 @@ sget_bytes(stream *src, byte *data, uint size)
+
+ int status = sgets(src, data, size, &ignore_count);
+
+- if (status < 0 && status != EOFC)
++ if (status < 0 && status != EOFC) {
+ return_error(gs_error_ioerror);
+ };
+
+diff --git a/base/gsptype1.c b/base/gsptype1.c
+--- a/base/gsptype1.c
++++ b/base/gsptype1.c
+@@ -111,6 +111,7 @@ void
+ gs_pattern1_init(gs_pattern1_template_t * ppat)
+ {
+ gs_pattern_common_init((gs_pattern_template_t *)ppat, &gs_pattern1_type);
++ ppat->uses_transparency = 0; /* false */
+ }
+
+ /* Make an instance of a PatternType 1 pattern. */
+@@ -169,8 +170,8 @@ gs_pattern1_make_pattern(gs_client_color * pcc,
+ if_debug6('t', "[t]step_matrix=[%g %g %g %g %g %g]\n",
+ inst.step_matrix.xx, inst.step_matrix.xy, inst.step_matrix.yx,
+ inst.step_matrix.yy, inst.step_matrix.tx, inst.step_matrix.ty);
+- if_debug4('t', "[t]bbox=(%g,%g),(%g,%g)\n",
+- bbox.p.x, bbox.p.y, bbox.q.x, bbox.q.y);
++ if_debug5('t', "[t]bbox=(%g,%g),(%g,%g), uses_transparency=%d\n",
++ bbox.p.x, bbox.p.y, bbox.q.x, bbox.q.y, inst.template.uses_transparency);
+ {
+ float bbw = bbox.q.x - bbox.p.x;
+ float bbh = bbox.q.y - bbox.p.y;
+@@ -1471,7 +1472,7 @@ gx_dc_pattern_read_raster(gx_color_tile *ptile, const gx_dc_serialized_tile_t *b
+ dp += l;
+ }
+ if (left == 0)
+- return 0;
++ return size; /* we've consumed it all */
+ if (offset1 <= sizeof(gx_dc_serialized_tile_t) + size_b) {
+ int l = min(sizeof(gx_dc_serialized_tile_t) + size_b - offset1, left);
+
+@@ -1495,7 +1496,7 @@ gx_dc_pattern_read_raster(gx_color_tile *ptile, const gx_dc_serialized_tile_t *b
+ dp += l;
+ }
+ if (left == 0)
+- return 0;
++ return size;
+ if (offset1 <= sizeof(gx_dc_serialized_tile_t) + size_b + size_c) {
+ int l = min(sizeof(gx_dc_serialized_tile_t) + size_b + size_c - offset1, left);
+
+diff --git a/base/gsptype1.h b/base/gsptype1.h
+--- a/base/gsptype1.h
++++ b/base/gsptype1.h
+@@ -41,6 +41,7 @@ typedef struct gs_pattern1_template_s {
+ gs_pattern_template_common;
+ int PaintType;
+ int TilingType;
++ bool uses_transparency;
+ gs_rect BBox;
+ float XStep;
+ float YStep;
+diff --git a/base/gsshade.c b/base/gsshade.c
+--- a/base/gsshade.c
++++ b/base/gsshade.c
+@@ -306,8 +306,6 @@ gs_shading_FfGt_init(gs_shading_t ** ppsh,
+ return code;
+ if (bpf < 0)
+ return bpf;
+- if (params->Decode != 0 && params->Decode[0] == params->Decode[1])
+- return_error(gs_error_rangecheck);
+ ALLOC_SHADING(&st_shading_FfGt, shading_type_Free_form_Gouraud_triangle,
+ shading_FfGt_procs, "gs_shading_FfGt_init");
+ psh->params.BitsPerFlag = bpf;
+diff --git a/base/gsstate.c b/base/gsstate.c
+--- a/base/gsstate.c
++++ b/base/gsstate.c
+@@ -192,7 +192,7 @@ gstate_copy_client_data(gs_state * pgs, void *dto, void *dfrom,
+
+ /* Define the initial value of the graphics state. */
+ static const gs_imager_state gstate_initial = {
+- gs_imager_state_initial(1.0)
++ gs_imager_state_initial(1.0, true) /* is_gstate == true */
+ };
+
+ /*
+@@ -218,7 +218,7 @@ gs_state_alloc(gs_memory_t * mem)
+ if (pgs == 0)
+ return 0;
+ pgs->saved = 0;
+- *(gs_imager_state *)pgs = gstate_initial;
++ *(gs_imager_state *)pgs = gstate_initial; /* this sets is_gstate == true */
+
+ /*
+ * Just enough of the state is initialized at this point
+diff --git a/base/gstparam.h b/base/gstparam.h
+--- a/base/gstparam.h
++++ b/base/gstparam.h
+@@ -85,6 +85,8 @@ typedef struct gs_transparency_group_params_s {
+ bool image_with_SMask;
+ bool idle;
+ uint mask_id;
++ int group_color_numcomps;
++ gs_transparency_color_t group_color;
+ } gs_transparency_group_params_t;
+
+ /* Define the parameter structure for a transparency mask. */
+@@ -99,6 +101,7 @@ typedef enum {
+ /* See the gx_transparency_mask_params_t type below */
+ /* (Update gs_trans_mask_params_init if these change.) */
+ typedef struct gs_transparency_mask_params_s {
++ const gs_color_space *ColorSpace;
+ gs_transparency_mask_subtype_t subtype;
+ int Background_components;
+ float Background[GS_CLIENT_COLOR_MAX_COMPONENTS];
+@@ -113,6 +116,9 @@ typedef struct gs_transparency_mask_params_s {
+ /* The post clist version of transparency mask parameters */
+ typedef struct gx_transparency_mask_params_s {
+ gs_transparency_mask_subtype_t subtype;
++ bool SMask_is_CIE;
++ int group_color_numcomps;
++ gs_transparency_color_t group_color;
+ int Background_components;
+ float Background[GS_CLIENT_COLOR_MAX_COMPONENTS];
+ float GrayBackground;
+diff --git a/base/gstrans.c b/base/gstrans.c
+--- a/base/gstrans.c
++++ b/base/gstrans.c
+@@ -24,6 +24,7 @@
+ #include "gdevdevn.h"
+ #include "gxblend.h"
+ #include "gdevp14.h"
++#include "gscspace.h"
+
+ #define PUSH_TS 0
+
+@@ -183,24 +184,10 @@ gs_begin_transparency_group(gs_state *pgs,
+ const gs_rect *pbbox)
+ {
+ gs_pdf14trans_params_t params = { 0 };
++ const gs_color_space *blend_color_space;
++ gs_imager_state * pis = (gs_imager_state *)pgs;
+
+-#ifdef DEBUG
+- if (gs_debug_c('v')) {
+- static const char *const cs_names[] = {
+- GS_COLOR_SPACE_TYPE_NAMES
+- };
+
+- dlprintf5("[v](0x%lx)begin_transparency_group [%g %g %g %g]\n",
+- (ulong)pgs, pbbox->p.x, pbbox->p.y, pbbox->q.x, pbbox->q.y);
+- if (ptgp->ColorSpace)
+- dprintf1(" CS = %s",
+- cs_names[(int)gs_color_space_get_index(ptgp->ColorSpace)]);
+- else
+- dputs(" (no CS)");
+- dprintf2(" Isolated = %d Knockout = %d\n",
+- ptgp->Isolated, ptgp->Knockout);
+- }
+-#endif
+ /*
+ * Put parameters into a compositor parameter and then call the
+ * create_compositor. This will pass the data to the PDF 1.4
+@@ -213,11 +200,98 @@ gs_begin_transparency_group(gs_state *pgs,
+ params.opacity = pgs->opacity;
+ params.shape = pgs->shape;
+ params.blend_mode = pgs->blend_mode;
+- /*
+- * We are currently doing nothing with the colorspace. Currently
+- * the blending colorspace is based upon the processs color model
+- * of the output device.
+- */
++
++ /* The blending procs must be based upon the current color space */
++ /* Note: This function is called during the c-list writer side.
++ Store some information so that we know what the color space is
++ so that we can adjust according later during the clist reader */
++
++ /* Note that we currently will use the concrete space for any space other than a
++ device space. However, if the device is a sep device it will blend
++ in DeviceN color space as required. */
++
++ if (gs_color_space_get_index(pgs->color_space) <= gs_color_space_index_DeviceCMYK) {
++
++ blend_color_space = pgs->color_space;
++
++ } else {
++
++ /* ICC and CIE based color space. Problem right now is that the
++ current code does a concretization to the color space
++ defined by the CRD. This is not the space that we want
++ to blend in. Instead we want all colors to be mapped TO
++ the ICC color space. Then when the group is popped they
++ should be converted to the parent space.
++ That I will need to fix another day with the color changes.
++ For now we will punt and set our blending space as the
++ concrete space for the ICC space, which is defined by
++ the output (or default) CRD. */
++
++ blend_color_space = cs_concrete_space(pgs->color_space, pis);
++
++ }
++
++ /* Note that if the /CS parameter was not present in the push
++ of the transparency group, then we must actually inherent
++ the previous group color space, or the color space of the
++ target device (process color model). Note here we just want
++ to set it as a unknown type for clist writing, as we . We will later
++ during clist reading
++ */
++
++ if (ptgp->ColorSpace == NULL) {
++
++ params.group_color = UNKNOWN;
++ params.group_color_numcomps = 0;
++
++ } else {
++
++ switch (cs_num_components(blend_color_space)) {
++ case 1:
++ params.group_color = GRAY_SCALE;
++ params.group_color_numcomps = 1; /* Need to check */
++ break;
++ case 3:
++ params.group_color = DEVICE_RGB;
++ params.group_color_numcomps = 3;
++ break;
++ case 4:
++ params.group_color = DEVICE_CMYK;
++ params.group_color_numcomps = 4;
++ break;
++ default:
++
++ /* We can end up here if we are in
++ a deviceN color space and
++ we have a sep output device */
++
++ params.group_color = DEVICEN;
++ params.group_color_numcomps = cs_num_components(blend_color_space);
++
++ break;
++
++ }
++
++ }
++
++#ifdef DEBUG
++ if (gs_debug_c('v')) {
++ static const char *const cs_names[] = {
++ GS_COLOR_SPACE_TYPE_NAMES
++ };
++
++ dlprintf6("[v](0x%lx)begin_transparency_group [%g %g %g %g] Num_grp_clr_comp = %d\n",
++ (ulong)pgs, pbbox->p.x, pbbox->p.y, pbbox->q.x, pbbox->q.y,params.group_color_numcomps);
++ if (ptgp->ColorSpace)
++ dprintf1(" CS = %s",
++ cs_names[(int)gs_color_space_get_index(ptgp->ColorSpace)]);
++ else
++ dputs(" (no CS)");
++ dprintf2(" Isolated = %d Knockout = %d\n",
++ ptgp->Isolated, ptgp->Knockout);
++ }
++#endif
++
+ params.bbox = *pbbox;
+ return gs_state_update_pdf14trans(pgs, &params);
+ }
+@@ -236,6 +310,11 @@ gx_begin_transparency_group(gs_imager_state * pis, gx_device * pdev,
+ tgp.Knockout = pparams->Knockout;
+ tgp.idle = pparams->idle;
+ tgp.mask_id = pparams->mask_id;
++
++ /* Needed so that we do proper blending */
++ tgp.group_color = pparams->group_color;
++ tgp.group_color_numcomps = pparams->group_color_numcomps;
++
+ pis->opacity.alpha = pparams->opacity.alpha;
+ pis->shape.alpha = pparams->shape.alpha;
+ pis->blend_mode = pparams->blend_mode;
+@@ -246,8 +325,8 @@ gx_begin_transparency_group(gs_imager_state * pis, gx_device * pdev,
+ GS_COLOR_SPACE_TYPE_NAMES
+ };
+
+- dlprintf5("[v](0x%lx)gx_begin_transparency_group [%g %g %g %g]\n",
+- (ulong)pis, bbox.p.x, bbox.p.y, bbox.q.x, bbox.q.y);
++ dlprintf6("[v](0x%lx)gx_begin_transparency_group [%g %g %g %g] Num_grp_clr_comp = %d\n",
++ (ulong)pis, bbox.p.x, bbox.p.y, bbox.q.x, bbox.q.y,pparams->group_color_numcomps);
+ if (tgp.ColorSpace)
+ dprintf1(" CS = %s",
+ cs_names[(int)gs_color_space_get_index(tgp.ColorSpace)]);
+@@ -298,6 +377,7 @@ void
+ gs_trans_mask_params_init(gs_transparency_mask_params_t *ptmp,
+ gs_transparency_mask_subtype_t subtype)
+ {
++ ptmp->ColorSpace = 0;
+ ptmp->subtype = subtype;
+ ptmp->Background_components = 0;
+ ptmp->TransferFunction = mask_transfer_identity;
+@@ -313,16 +393,14 @@ gs_begin_transparency_mask(gs_state * pgs,
+ gs_pdf14trans_params_t params = { 0 };
+ const int l = sizeof(params.Background[0]) * ptmp->Background_components;
+ int i;
++ const gs_color_space *blend_color_space;
++ gs_imager_state * pis = (gs_imager_state *)pgs;
+
+- if_debug8('v', "[v](0x%lx)gs_begin_transparency_mask [%g %g %g %g]\n\
+- subtype = %d Background_components = %d %s\n",
+- (ulong)pgs, pbbox->p.x, pbbox->p.y, pbbox->q.x, pbbox->q.y,
+- (int)ptmp->subtype, ptmp->Background_components,
+- (ptmp->TransferFunction == mask_transfer_identity ? "no TR" :
+- "has TR"));
+ params.pdf14_op = PDF14_BEGIN_TRANS_MASK;
+ params.bbox = *pbbox;
+ params.subtype = ptmp->subtype;
++ /* params.SMask_is_CIE = gs_color_space_is_CIE(pgs->color_space); */ /* See comments in gs_begin_transparency_mask */
++ params.SMask_is_CIE = false;
+ params.Background_components = ptmp->Background_components;
+ memcpy(params.Background, ptmp->Background, l);
+ params.GrayBackground = ptmp->GrayBackground;
+@@ -331,6 +409,18 @@ gs_begin_transparency_mask(gs_state * pgs,
+ (ptmp->TransferFunction == mask_transfer_identity);
+ params.mask_is_image = mask_is_image;
+ params.replacing = ptmp->replacing;
++ /* Note that the SMask buffer may have a different
++ numcomps than the device buffer */
++ params.group_color_numcomps = cs_num_components(pgs->color_space);
++
++ if_debug9('v', "[v](0x%lx)gs_begin_transparency_mask [%g %g %g %g]\n\
++ subtype = %d Background_components = %d Num_grp_clr_comp = %d %s\n",
++ (ulong)pgs, pbbox->p.x, pbbox->p.y, pbbox->q.x, pbbox->q.y,
++ (int)ptmp->subtype, ptmp->Background_components,
++ params.group_color_numcomps,
++ (ptmp->TransferFunction == mask_transfer_identity ? "no TR" :
++ "has TR"));
++
+ /* Sample the transfer function */
+ for (i = 0; i < MASK_TRANSFER_FUNCTION_SIZE; i++) {
+ float in = (float)(i * (1.0 / (MASK_TRANSFER_FUNCTION_SIZE - 1)));
+@@ -339,9 +429,115 @@ gs_begin_transparency_mask(gs_state * pgs,
+ ptmp->TransferFunction(in, &out, ptmp->TransferFunction_data);
+ params.transfer_fn[i] = (byte)floor((double)(out * 255 + 0.5));
+ }
++
++ /* If we have a CIE space & a luminosity subtype
++ we will need to do our concretization
++ to CIEXYZ so that we can obtain the proper
++ luminance value. This is what SHOULD happen
++ according to the spec. However AR does not
++ follow this. It always seems to do the soft mask
++ creation in the device space. For this reason
++ we will do that too. SMask_is_CIE is always false for now */
++
++ /* The blending procs are currently based upon the device type.
++ We need to have them based upon the current color space */
++
++ /* Note: This function is called during the c-list writer side. */
++
++
++ if ( params.SMask_is_CIE && params.subtype == TRANSPARENCY_MASK_Luminosity ){
++
++ /* Install Color Space to go to CIEXYZ */
++
++ /* int ok;
++ ok = gx_cie_to_xyz_alloc2(pgs->color_space,pgs); */ /* quite compiler */
++ params.group_color_numcomps = 3; /* CIEXYZ */
++
++ /* Mark the proper spaces so that we make
++ * the appropriate changes in the device */
++
++ params.group_color = CIE_XYZ;
++
++ } else {
++
++ /* Set the group color type, which may be
++ * different than the device type. Note
++ we want to check the concrete space due
++ to the fact that things are done
++ in device space always. */
++
++
++ if(!gs_color_space_is_CIE(pgs->color_space)){
++
++ blend_color_space = pgs->color_space;
++
++ } else {
++
++ /* ICC or CIE based color space. Problem right now is that the
++ current code does a concretization to the color space
++ defined by the CRD. This is not the space that we want
++ to blend in. Instead we want all colors to be mapped TO
++ the ICC color space. Then when the group is popped they
++ should be converted to the parent space.
++ That I will need to fix another day with the color changes.
++ For now we will punt and set our blending space as the
++ concrete space for the ICC space, which is defined by
++ the output (or default) CRD. */
++
++ blend_color_space = cs_concrete_space(pgs->color_space, pis);
++
++ }
++
++
++ /* Note that if the /CS parameter was not present in the push
++ of the transparency group, then we must actually inherent
++ the previous group color space, or the color space of the
++ target device (process color model). Note here we just want
++ to set it as a unknown type for clist writing, as we . We will later
++ during clist reading
++ */
++
++ if (ptmp->ColorSpace == NULL) {
++
++ params.group_color = UNKNOWN;
++ params.group_color_numcomps = 0;
++
++ } else {
++
++
++ switch (cs_num_components(blend_color_space)) {
++
++ case 1:
++ params.group_color = GRAY_SCALE;
++ params.group_color_numcomps = 1; /* Need to check */
++ break;
++ case 3:
++ params.group_color = DEVICE_RGB;
++ params.group_color_numcomps = 3;
++ break;
++ case 4:
++ params.group_color = DEVICE_CMYK;
++ params.group_color_numcomps = 4;
++ break;
++ default:
++ /* Transparency soft mask spot
++ colors are NEVER available.
++ We must use the alternate tint
++ transform */
++ return_error(gs_error_rangecheck);
++ break;
++
++ }
++
++ }
++
++ }
++
+ return gs_state_update_pdf14trans(pgs, &params);
+ }
+
++/* This occurs on the c-list reader side */
++
+ int
+ gx_begin_transparency_mask(gs_imager_state * pis, gx_device * pdev,
+ const gs_pdf14trans_params_t * pparams)
+@@ -349,7 +545,10 @@ gx_begin_transparency_mask(gs_imager_state * pis, gx_device * pdev,
+ gx_transparency_mask_params_t tmp;
+ const int l = sizeof(pparams->Background[0]) * pparams->Background_components;
+
++ tmp.group_color = pparams->group_color;
+ tmp.subtype = pparams->subtype;
++ tmp.SMask_is_CIE = pparams->SMask_is_CIE;
++ tmp.group_color_numcomps = pparams->group_color_numcomps;
+ tmp.Background_components = pparams->Background_components;
+ memcpy(tmp.Background, pparams->Background, l);
+ tmp.GrayBackground = pparams->GrayBackground;
+@@ -358,11 +557,12 @@ gx_begin_transparency_mask(gs_imager_state * pis, gx_device * pdev,
+ tmp.replacing = pparams->replacing;
+ tmp.mask_id = pparams->mask_id;
+ memcpy(tmp.transfer_fn, pparams->transfer_fn, size_of(tmp.transfer_fn));
+- if_debug8('v', "[v](0x%lx)gx_begin_transparency_mask [%g %g %g %g]\n\
+- subtype = %d Background_components = %d %s\n",
++ if_debug9('v', "[v](0x%lx)gx_begin_transparency_mask [%g %g %g %g]\n\
++ subtype = %d Background_components = %d Num_grp_clr_comp = %d %s\n",
+ (ulong)pis, pparams->bbox.p.x, pparams->bbox.p.y,
+ pparams->bbox.q.x, pparams->bbox.q.y,
+ (int)tmp.subtype, tmp.Background_components,
++ tmp.group_color_numcomps,
+ (tmp.function_is_identity ? "no TR" :
+ "has TR"));
+ if (dev_proc(pdev, begin_transparency_mask) != 0)
+@@ -392,8 +592,9 @@ gx_end_transparency_mask(gs_imager_state * pis, gx_device * pdev,
+ {
+ if_debug2('v', "[v](0x%lx)gx_end_transparency_mask(%d)\n", (ulong)pis,
+ (int)pparams->csel);
++
+ if (dev_proc(pdev, end_transparency_mask) != 0)
+- return (*dev_proc(pdev, end_transparency_mask)) (pdev, NULL);
++ return (*dev_proc(pdev, end_transparency_mask)) (pdev, pis, NULL);
+ else
+ return 0;
+ }
+diff --git a/base/gstrans.h b/base/gstrans.h
+--- a/base/gstrans.h
++++ b/base/gstrans.h
+@@ -20,6 +20,7 @@
+ #include "gstparam.h"
+ #include "gxcomp.h"
+ #include "gsmatrix.h"
++#include "gxblend.h"
+
+ /*
+ * Define the operations for the PDF 1.4 transparency compositor.
+@@ -95,6 +96,9 @@ struct gs_pdf14trans_params_s {
+ bool overprint_mode;
+ bool idle; /* For clist reader.*/
+ uint mask_id; /* For clist reader.*/
++ bool SMask_is_CIE;
++ int group_color_numcomps;
++ gs_transparency_color_t group_color;
+ };
+
+ #ifndef gs_pdf14trans_params_DEFINED
+diff --git a/base/gstype1.c b/base/gstype1.c
+--- a/base/gstype1.c
++++ b/base/gstype1.c
+@@ -283,6 +283,19 @@ gs_type1_interpret(gs_type1_state * pcis, const gs_glyph_data_t *pgd,
+ goto cc;
+ case cx_endchar:
+ if (pcis->seac_accent < 0) {
++ if(!pcis->sb_set && !pcis->width_set) {
++ /* No sbw/hsbw op, error condition but Adobe interpreters ignore it.
++ Rewind the data pointer to the beginning of the glyph, re-initialise
++ the hinter, execute a '0' sbw op, and then carry on as if we had
++ actually received one. */
++ cip = pgd->bits.data;
++ t1_hinter__init(h, pcis->path);
++ code = t1_hinter__sbw(h, fixed_0, fixed_0, fixed_0, fixed_0);
++ if (code < 0)
++ return code;
++ gs_type1_sbw(pcis, fixed_0, fixed_0, fixed_0, fixed_0);
++ goto rsbw;
++ }
+ code = t1_hinter__endglyph(h);
+ if (code < 0)
+ return code;
+diff --git a/base/gstype42.c b/base/gstype42.c
+--- a/base/gstype42.c
++++ b/base/gstype42.c
+@@ -258,8 +258,23 @@ gs_type42_font_init(gs_font_type42 * pfont, int subfontID)
+ the bug 688467 fails otherwise.
+ */
+ /* pfont->key_name.chars is ASCIIZ due to copy_font_name. */
++ char buf[gs_font_name_max + 2];
++
++ if (pfont->key_name.size) {
++ int l = min(sizeof(buf) - 1, pfont->key_name.size);
++
++ memcpy(buf, pfont->key_name.chars, l);
++ buf[l] = 0;
++ } else if (pfont->font_name.size) {
++ int l = min(sizeof(buf) - 1, pfont->font_name.size);
++
++ memcpy(buf, pfont->font_name.chars, l);
++ buf[l] = 0;
++ } else
++ buf[0] = 0;
++
+ eprintf3("Warning: 'loca' length %d is greater than numGlyphs %d in the font %s.\n",
+- pfont->data.numGlyphs + 1, pfont->data.trueNumGlyphs, pfont->key_name.chars);
++ pfont->data.numGlyphs + 1, pfont->data.trueNumGlyphs, buf);
+ if (loca_size > pfont->data.trueNumGlyphs + 1) {
+ /* Bug 689516 demonstrates a font, in which numGlyps is smaller than loca size,
+ and there are useful glyphs behind maxp.numGlyphs. */
+diff --git a/base/gxblend.c b/base/gxblend.c
+--- a/base/gxblend.c
++++ b/base/gxblend.c
+@@ -17,13 +17,203 @@
+ #include "gx.h"
+ #include "gstparam.h"
+ #include "gxblend.h"
++#include "gxcolor2.h"
+
+ typedef int art_s32;
+
+ #if RAW_DUMP
+-extern unsigned char global_index;
++extern unsigned int global_index;
++extern unsigned int clist_band_count;
+ #endif
+
++/* This function is used for mapping the SMask source to a
++ monochrome luminosity value which basically is the alpha value
++ Note, that separation colors are not allowed here. Everything
++ must be in CMYK, RGB or monochrome. */
++
++/* Note, data is planar */
++
++void
++Smask_Luminosity_Mapping(int num_rows, int num_cols, int n_chan, int row_stride,
++ int plane_stride, byte *dst, const byte *src, bool isadditive,
++ bool SMask_is_CIE, gs_transparency_mask_subtype_t SMask_SubType)
++{
++
++ int x,y;
++ int mask_alpha_offset,mask_C_offset,mask_M_offset,mask_Y_offset,mask_K_offset;
++ int mask_R_offset,mask_G_offset,mask_B_offset;
++ byte *dstptr;
++
++#if RAW_DUMP
++
++ dump_raw_buffer(num_rows, row_stride, n_chan,
++ plane_stride, row_stride,
++ "Raw_Mask", src);
++
++ global_index++;
++
++#endif
++
++ dstptr = dst;
++
++ /* If we are CIE AND subtype is Luminosity then we should just grab the Y channel */
++
++ if ( SMask_is_CIE && SMask_SubType == TRANSPARENCY_MASK_Luminosity ){
++
++
++ memcpy(dst, &(src[plane_stride]), plane_stride);
++ return;
++
++ }
++
++ /* If we are alpha type, then just grab that */
++ /* We need to optimize this so that we are only drawing alpha in the rect fills */
++
++ if ( SMask_SubType == TRANSPARENCY_MASK_Alpha ){
++
++ mask_alpha_offset = (n_chan - 1) * plane_stride;
++ memcpy(dst, &(src[mask_alpha_offset]), plane_stride);
++ return;
++
++ }
++
++ /* To avoid the if statement inside this loop,
++ decide on additive or subractive now */
++
++ if (isadditive || n_chan == 2)
++ {
++
++ /* Now we need to split Gray from RGB */
++
++ if( n_chan == 2 )
++ {
++ /* Gray Scale case */
++
++ mask_alpha_offset = (n_chan - 1) * plane_stride;
++ mask_R_offset = 0;
++
++ for ( y = 0; y < num_rows; y++ )
++ {
++
++ for ( x = 0; x < num_cols; x++ ){
++
++ /* With the current design this will indicate if
++ we ever did a fill at this pixel. if not then move on.
++ This could have some serious optimization */
++
++ if (src[x + mask_alpha_offset] != 0x00) {
++
++ dstptr[x] = src[x + mask_R_offset];
++
++ }
++
++ }
++
++ dstptr += row_stride;
++ mask_alpha_offset += row_stride;
++ mask_R_offset += row_stride;
++
++ }
++
++ } else {
++
++
++
++ /* RGB case */
++
++ mask_R_offset = 0;
++ mask_G_offset = plane_stride;
++ mask_B_offset = 2 * plane_stride;
++ mask_alpha_offset = (n_chan - 1) * plane_stride;
++
++ for ( y = 0; y < num_rows; y++ )
++ {
++
++ for ( x = 0; x < num_cols; x++ ){
++
++ /* With the current design this will indicate if
++ we ever did a fill at this pixel. if not then move on */
++
++ if (src[x + mask_alpha_offset] != 0x00) {
++
++ /* Get luminosity of Device RGB value */
++
++ float temp;
++
++ temp = ( 0.30 * src[x + mask_R_offset] +
++ 0.59 * src[x + mask_G_offset] +
++ 0.11 * src[x + mask_B_offset] );
++
++ temp = temp * (1.0 / 255.0 ); /* May need to be optimized */
++ dstptr[x] = float_color_to_byte_color(temp);
++
++ }
++
++ }
++
++ dstptr += row_stride;
++ mask_alpha_offset += row_stride;
++ mask_R_offset += row_stride;
++ mask_G_offset += row_stride;
++ mask_B_offset += row_stride;
++
++ }
++
++ }
++
++ } else {
++
++ /* CMYK case */
++
++ mask_alpha_offset = (n_chan - 1) * plane_stride;
++ mask_C_offset = 0;
++ mask_M_offset = plane_stride;
++ mask_Y_offset = 2 * plane_stride;
++ mask_K_offset = 3 * plane_stride;
++
++ for ( y = 0; y < num_rows; y++ ){
++
++ for ( x = 0; x < num_cols; x++ ){
++
++ /* With the current design this will indicate if
++ we ever did a fill at this pixel. if not then move on */
++
++ if (src[x + mask_alpha_offset] != 0x00){
++
++ /* PDF spec says to use Y = 0.30 (1 - C)(1 - K) +
++ 0.59 (1 - M)(1 - K) + 0.11 (1 - Y)(1 - K) */
++ /* For device CMYK */
++
++ float temp;
++
++ temp = ( 0.30 * ( 0xff - src[x + mask_C_offset]) +
++ 0.59 * ( 0xff - src[x + mask_M_offset]) +
++ 0.11 * ( 0xff - src[x + mask_Y_offset]) ) *
++ ( 0xff - src[x + mask_K_offset]);
++
++ temp = temp * (1.0 / 65025.0 ); /* May need to be optimized */
++
++ dstptr[x] = float_color_to_byte_color(temp);
++
++ }
++
++ }
++
++ dstptr += row_stride;
++ mask_alpha_offset += row_stride;
++ mask_C_offset += row_stride;
++ mask_M_offset += row_stride;
++ mask_Y_offset += row_stride;
++ mask_K_offset += row_stride;
++
++ }
++
++
++ }
++
++
++}
++
+ void
+ art_blend_luminosity_rgb_8(int n_chan, byte *dst, const byte *backdrop,
+ const byte *src)
+@@ -1236,13 +1426,20 @@ dump_raw_buffer(int num_rows, int width, int n_chan,
+ FILE *fid;
+ int z,y;
+ byte *buff_ptr;
++ int max_bands;
++
++ /* clist_band_count is incremented at every pdf14putimage */
++ /* Useful for catching this thing and only dumping */
++ /* during a particular band if we have a large file */
++ /* if (clist_band_count != 80) return; */
+
+ buff_ptr = Buffer;
+
+- sprintf(full_file_name,"%d)%s_%dx%dx%d.raw",global_index,filename,width,num_rows,n_chan);
++ max_bands = ( n_chan < 57 ? n_chan : 56); /* Photoshop handles at most 56 bands */
++ sprintf(full_file_name,"%d)%s_%dx%dx%d.raw",global_index,filename,width,num_rows,max_bands);
+ fid = fopen(full_file_name,"wb");
+
+- for (z = 0; z < n_chan; ++z) {
++ for (z = 0; z < max_bands; ++z) {
+
+ /* grab pointer to the next plane */
+
+diff --git a/base/gxblend.h b/base/gxblend.h
+--- a/base/gxblend.h
++++ b/base/gxblend.h
+@@ -19,12 +19,13 @@
+ #include "gxcindex.h"
+ #include "gxcvalue.h"
+ #include "gxfrac.h"
++#include "gxdevcli.h"
+
+ #define RAW_DUMP 0
+
+ /* #define DUMP_TO_PNG */
+
+-#define PDF14_MAX_PLANES (GX_DEVICE_COLOR_MAX_COMPONENTS + 1) /* one extra for alpha channel */
++#define PDF14_MAX_PLANES GX_DEVICE_COLOR_MAX_COMPONENTS+3 /* Needed for alpha channel, shape, group alpha */
+
+ typedef bits16 ArtPixMaxDepth;
+
+@@ -75,6 +76,27 @@ typedef struct {
+ typedef pdf14_nonseparable_blending_procs_s
+ pdf14_nonseparable_blending_procs_t;
+
++
++/* This is used to so that we can change procedures based
++ * upon the Smask color space. previously we always
++ * went to the device space */
++
++typedef struct {
++
++ pdf14_nonseparable_blending_procs_t device_procs;
++ gx_device_procs color_mapping_procs;
++
++} pdf14_parent_cs_params_s;
++
++typedef pdf14_parent_cs_params_s pdf14_parent_cs_params_t;
++
++/* This function is used for mapping Smask CMYK or RGB data to a monochrome alpha buffer */
++
++void Smask_Luminosity_Mapping(int num_rows, int num_cols, int n_chan, int row_stride,
++ int plane_stride, byte *dst, const byte *src, bool isadditive,
++ bool SMask_is_CIE, gs_transparency_mask_subtype_t SMask_SubType);
++
++
+ /**
+ * art_blend_pixel: Compute PDF 1.4 blending function.
+ * @dst: Where to store resulting pixel.
+@@ -340,6 +362,12 @@ void pdf14_compose_group(pdf14_buf *tos, pdf14_buf *nos, pdf14_buf *maskbuf,
+ int x0, int x1, int y0, int y1, int n_chan, bool additive,
+ const pdf14_nonseparable_blending_procs_t * pblend_procs);
+
++gx_color_index pdf14_encode_smask_color(gx_device *dev,
++ const gx_color_value colors[], int ncomp);
++
++int pdf14_decode_smask_color(gx_device * dev, gx_color_index color,
++ gx_color_value * out, int ncomp);
++
+
+ gx_color_index pdf14_encode_color(gx_device *dev, const gx_color_value colors[]);
+
+diff --git a/base/gxblend1.c b/base/gxblend1.c
+--- a/base/gxblend1.c
++++ b/base/gxblend1.c
+@@ -24,6 +24,7 @@
+ #include "gdevdevn.h"
+ #include "gdevp14.h"
+ #include "vdtrace.h"
++#include "gxdcconv.h"
+
+ #ifdef DUMP_TO_PNG
+ #include "png_.h"
+@@ -32,8 +33,7 @@
+ /*
+ * Unpack a device color. This routine is similar to the device's
+ * decode_color procedure except for two things. The procedure produces 1
+- * byte values instead of gx_color_values (2 bytes) and the output values
+- * are inverted for subtractive color spaces (like CMYK). A separate
++ * byte values instead of gx_color_values (2 bytes). A separate
+ * procedure is used instead of the decode_color to minimize execution time.
+ */
+ void
+@@ -138,11 +138,14 @@ pdf14_unpack_custom(int num_comp, gx_color_index color,
+ out[i] = 0xff - gx_color_value_to_byte(cm_values[i]);
+ }
+
+-
++#if RAW_DUMP
++extern unsigned int global_index;
++#endif
+
+ void
+ pdf14_preserve_backdrop(pdf14_buf *buf, pdf14_buf *tos, bool has_shape)
+ {
++
+ /* make copy of backdrop for compositing */
+ int x0 = max(buf->rect.p.x, tos->rect.p.x);
+ int x1 = min(buf->rect.q.x, tos->rect.q.x);
+@@ -154,7 +157,8 @@ pdf14_preserve_backdrop(pdf14_buf *buf, pdf14_buf *tos, bool has_shape)
+ byte *buf_plane = buf->data + x0 - buf->rect.p.x + (y0 - buf->rect.p.y) * buf->rowstride;
+ byte *tos_plane = tos->data + x0 - tos->rect.p.x + (y0 - tos->rect.p.y) * tos->rowstride;
+ int i;
+- int n_chan_copy = buf->n_chan + (tos->has_shape ? 1 : 0);
++ /*int n_chan_copy = buf->n_chan + (tos->has_shape ? 1 : 0);*/
++ int n_chan_copy = tos->n_chan + (tos->has_shape ? 1 : 0);
+
+ for (i = 0; i < n_chan_copy; i++) {
+ byte *buf_ptr = buf_plane;
+@@ -172,8 +176,29 @@ pdf14_preserve_backdrop(pdf14_buf *buf, pdf14_buf *tos, bool has_shape)
+ if (has_shape && !tos->has_shape)
+ memset (buf_plane, 0, buf->planestride);
+ }
++
++
++#if RAW_DUMP
++
++ if (x0 < x1 && y0 < y1) {
++
++ byte *buf_plane = buf->data + x0 - buf->rect.p.x +
++ (y0 - buf->rect.p.y) * buf->rowstride;
++
++ dump_raw_buffer(y1-y0, x1 - x0, buf->n_planes,
++ buf->planestride, buf->rowstride,
++ "BackDropInit",buf_plane);
++
++ global_index++;
++
++ }
++
++#endif
++
+ }
+
++
++
+ void
+ pdf14_compose_group(pdf14_buf *tos, pdf14_buf *nos, pdf14_buf *maskbuf,
+ int x0, int x1, int y0, int y1, int n_chan, bool additive,
+@@ -206,6 +231,9 @@ pdf14_compose_group(pdf14_buf *tos, pdf14_buf *nos, pdf14_buf *maskbuf,
+ int nos_shape_offset = n_chan * nos_planestride;
+ bool nos_has_shape = nos->has_shape;
+ byte *mask_tr_fn = NULL; /* Quiet compiler. */
++#if RAW_DUMP
++ byte *composed_ptr = NULL;
++#endif
+
+ rect_merge(nos->bbox, tos->bbox);
+
+@@ -224,6 +252,28 @@ pdf14_compose_group(pdf14_buf *tos, pdf14_buf *nos, pdf14_buf *maskbuf,
+ mask_tr_fn = maskbuf->transfer_fn;
+ }
+
++#if RAW_DUMP
++
++ composed_ptr = nos_ptr;
++
++ dump_raw_buffer(y1-y0, width, tos->n_planes,
++ tos_planestride, tos->rowstride,
++ "ImageTOS",tos_ptr);
++
++ dump_raw_buffer(y1-y0, width, nos->n_planes,
++ nos_planestride, nos->rowstride,
++ "ImageNOS",nos_ptr);
++
++ if(maskbuf != NULL){
++
++ dump_raw_buffer(y1-y0, width, maskbuf->n_planes,
++ maskbuf->planestride, maskbuf->rowstride,
++ "Mask",mask_ptr);
++ }
++
++#endif
++
++
+ for (y = y0; y < y1; ++y) {
+ for (x = 0; x < width; ++x) {
+ byte pix_alpha = alpha;
+@@ -244,28 +294,9 @@ pdf14_compose_group(pdf14_buf *tos, pdf14_buf *nos, pdf14_buf *maskbuf,
+ }
+
+ if (mask_ptr != NULL) {
+- int mask_alpha = mask_ptr[x + num_comp * mask_planestride];
++
++ byte mask = mask_ptr[x];
+ int tmp;
+- byte mask;
+-
+- /*
+- * The mask data is really monochrome. Thus for additive (RGB)
+- * we use the R channel for alpha since R = G = B. For
+- * subtractive (CMYK) we use the K channel.
+- */
+- if (mask_alpha == 255) {
+- /* todo: rgba->mask */
+- mask = additive ? mask_ptr[x]
+- : 255 - mask_ptr[x + 3 * mask_planestride];
+- } else if (mask_alpha == 0)
+- mask = mask_bg_alpha;
+- else {
+- int t2 = additive ? mask_ptr[x]
+- : 255 - mask_ptr[x + 3 * mask_planestride];
+-
+- t2 = (t2 - mask_bg_alpha) * mask_alpha + 0x80;
+- mask = mask_bg_alpha + ((t2 + (t2 >> 8)) >> 8);
+- }
+ mask = mask_tr_fn[mask];
+ tmp = pix_alpha * mask + 0x80;
+ pix_alpha = (tmp + (tmp >> 8)) >> 8;
+@@ -332,9 +363,62 @@ pdf14_compose_group(pdf14_buf *tos, pdf14_buf *nos, pdf14_buf *maskbuf,
+ if (mask_ptr != NULL)
+ mask_ptr += maskbuf->rowstride;
+ }
++
++
++ /* Lets look at composed result */
++
++
++#if RAW_DUMP
++
++ /* The group alpha should disappear */
++ dump_raw_buffer(y1-y0, width, tos->n_planes - tos->has_alpha_g,
++ nos_planestride, nos->rowstride,
++ "Composed",composed_ptr);
++
++ global_index++;
++
++
++#endif
++
+ }
+
+ /*
++ * Encode a list of smask colorant values into a gx_color_index_value.
++ * This has its own encoder as it may have a different number of colorants
++ * compared to the actual device.
++ */
++gx_color_index
++pdf14_encode_smask_color(gx_device *dev, const gx_color_value colors[],int ncomp)
++{
++ int drop = sizeof(gx_color_value) * 8 - 8;
++ gx_color_index color = 0;
++ int i;
++
++ for (i = 0; i < ncomp; i++) {
++ color <<= 8;
++ color |= (colors[i] >> drop);
++ }
++ return (color == gx_no_color_index ? color ^ 1 : color);
++}
++
++/*
++ * Decode a gx_color_index value back to a list of colorant values.
++ * This has its own decoder as it may have a different number of colorants
++ * compared to the actual device.*/
++int
++pdf14_decode_smask_color(gx_device * dev, gx_color_index color, gx_color_value * out, int ncomp)
++{
++ int i;
++
++ for (i = 0; i < ncomp; i++) {
++ out[ncomp - i - 1] = (gx_color_value) ((color & 0xff) * 0x101);
++ color >>= 8;
++ }
++ return 0;
++}
++
++
++/*
+ * Encode a list of colorant values into a gx_color_index_value.
+ */
+ gx_color_index
+diff --git a/base/gxccman.c b/base/gxccman.c
+--- a/base/gxccman.c
++++ b/base/gxccman.c
+@@ -333,9 +333,8 @@ gx_add_fm_pair(register gs_font_dir * dir, gs_font * font, const gs_uid * puid,
+ return code;
+ }
+ pair->FontType = font->FontType;
+- /* The OSF/1 compiler doesn't like casting a pointer to */
+- /* a shorter int.... */
+- pair->hash = (uint) (ulong) pair % 549; /* scramble bits */
++ pair->hash = (uint) (dir->hash % 549); /* scramble bits */
++ dir->hash += 371;
+ pair->mxx = mxx, pair->mxy = mxy;
+ pair->myx = myx, pair->myy = myy;
+ pair->num_chars = 0;
+diff --git a/base/gxchar.c b/base/gxchar.c
+--- a/base/gxchar.c
++++ b/base/gxchar.c
+@@ -33,10 +33,6 @@
+ #include "gzpath.h"
+ #include "gxfcid.h"
+
+-/* Define whether or not to cache characters rotated by angles other than */
+-/* multiples of 90 degrees. */
+-static const bool CACHE_ROTATED_CHARS = true;
+-
+ /* Define the maximum size of a full temporary bitmap when rasterizing, */
+ /* in bits (not bytes). */
+ static const uint MAX_TEMP_BITMAP_BITS = 80000;
+@@ -1429,22 +1425,6 @@ gs_show_current_font(const gs_show_enum * penum)
+
+ /* ------ Internal routines ------ */
+
+-static inline bool
+-is_matrix_good_for_caching(const gs_matrix_fixed *m)
+-{
+- /* Skewing or non-rectangular rotation are not supported,
+- but we ignore a small noise skew. */
+- const float axx = any_abs(m->xx), axy = any_abs(m->xy);
+- const float ayx = any_abs(m->yx), ayy = any_abs(m->yy);
+- const float thr = 5000; /* examples/alphabet.ps */
+-
+- if (ayx * thr < axx || axy * thr < ayy)
+- return true;
+- if (axx * thr < ayx || ayy * thr < axy)
+- return true;
+- return false;
+-}
+-
+ /* Initialize the gstate-derived parts of a show enumerator. */
+ /* We do this both when starting the show operation, */
+ /* and when returning from the kshow callout. */
+@@ -1476,9 +1456,6 @@ show_state_setup(gs_show_enum * penum)
+ gs_setcharmatrix(pgs, &mat);
+ }
+ penum->current_font = pfont;
+- /* Skewing or non-rectangular rotation are not supported. */
+- if (!CACHE_ROTATED_CHARS && is_matrix_good_for_caching(&pgs->char_tm))
+- penum->can_cache = 0;
+ if (penum->can_cache >= 0 &&
+ gx_effective_clip_path(pgs, &pcpath) >= 0
+ ) {
+@@ -1532,10 +1509,8 @@ show_set_scale(const gs_show_enum * penum, gs_log2_scale_point *log2_scale)
+
+ if ((penum->charpath_flag == cpm_show ||
+ penum->charpath_flag == cpm_charwidth) &&
+- SHOW_USES_OUTLINE(penum) &&
+- /* gx_path_is_void_inline(pgs->path) && */
+- /* Oversampling rotated characters doesn't work well. */
+- is_matrix_good_for_caching(&pgs->char_tm)
++ SHOW_USES_OUTLINE(penum)
++ /* && gx_path_is_void_inline(pgs->path) */
+ ) {
+ const gs_font_base *pfont = (const gs_font_base *)penum->current_font;
+ gs_fixed_point extent;
+diff --git a/base/gxcie.h b/base/gxcie.h
+--- a/base/gxcie.h
++++ b/base/gxcie.h
+@@ -52,6 +52,10 @@ extern int gx_cie_to_xyz_alloc(gs_imager_state **,
+ const gs_color_space *, gs_memory_t *);
+ extern void gx_cie_to_xyz_free(gs_imager_state *);
+
++
++extern int gx_cie_to_xyz_alloc2(gs_color_space * pcs, gs_state * pgs);
++
++
+ /* Defined in gsciemap.c */
+
+ /*
+diff --git a/base/gxclimag.c b/base/gxclimag.c
+--- a/base/gxclimag.c
++++ b/base/gxclimag.c
+@@ -475,7 +475,7 @@ clist_begin_typed_image(gx_device * dev,
+ * worthwhile.
+ */
+ gx_color_index all =
+- ((gx_color_index)1 << dev->color_info.depth) - 1;
++ ((gx_color_index)1 << cdev->clist_color_info.depth) - 1;
+
+ if (bits_per_pixel > 4 || pim->Interpolate || num_components > 1)
+ colors_used = all;
+@@ -536,13 +536,22 @@ clist_begin_typed_image(gx_device * dev,
+ return 0;
+
+ /*
+- * We couldn't handle the image. Use the default algorithms, which
++ * We couldn't handle the image. It is up to the caller to
++ * use the default algorithms, which
+ * break the image up into rectangles or small pixmaps.
++ * If we are doing the PDF14 transparency device
++ * then we want to make sure we do NOT use the target
++ * device. In this case we return -1.
+ */
+ use_default:
+ gs_free_object(mem, pie, "clist_begin_typed_image");
+- return gx_default_begin_typed_image(dev, pis, pmat, pic, prect,
+- pdcolor, pcpath, mem, pinfo);
++
++ if (pis->has_transparency){
++ return -1;
++ } else {
++ return gx_default_begin_typed_image(dev, pis, pmat, pic, prect,
++ pdcolor, pcpath, mem, pinfo);
++ }
+ }
+
+ /* Error cleanup for clist_image_plane_data. */
+@@ -1488,7 +1497,7 @@ cmd_image_plane_data(gx_device_clist_writer * cldev, gx_clist_state * pcls,
+ code = cmd_put_set_data_x(cldev, pcls, data_x);
+ if (code < 0)
+ return code;
+- offset = ((data_x & ~7) * cldev->color_info.depth) >> 3;
++ offset = ((data_x & ~7) * cldev->clist_color_info.depth) >> 3;
+ }
+ code = set_cmd_put_op(dp, cldev, pcls, cmd_opv_image_data, len);
+ if (code < 0)
+diff --git a/base/gxclist.c b/base/gxclist.c
+--- a/base/gxclist.c
++++ b/base/gxclist.c
+@@ -190,7 +190,7 @@ clist_init_io_procs(gx_device_clist *pclist_dev, bool in_memory)
+ /* Initialization for imager state. */
+ /* The initial scale is arbitrary. */
+ const gs_imager_state clist_imager_state_initial =
+-{gs_imager_state_initial(300.0 / 72.0)};
++{gs_imager_state_initial(300.0 / 72.0, false)};
+
+ /*
+ * The buffer area (data, data_size) holds a bitmap cache when both writing
+@@ -358,6 +358,16 @@ clist_init_data(gx_device * dev, byte * init_data, uint data_size)
+ gx_device *pbdev = (gx_device *)&bdev;
+ int code;
+
++ /* the clist writer has its own color info that depends upon the
++ transparency group color space (if transparency exists). The data that is
++ used in the clist writing. Here it is initialized with
++ the target device color info. The values will be pushed and popped
++ in a stack if we have changing color spaces in the transparency groups. */
++
++ cdev->clist_color_info.depth = dev->color_info.depth;
++ cdev->clist_color_info.polarity = dev->color_info.polarity;
++ cdev->clist_color_info.num_components = dev->color_info.num_components;
++
+ /* Call create_buf_device to get the memory planarity set up. */
+ cdev->buf_procs.create_buf_device(&pbdev, target, 0, NULL, NULL, clist_get_band_complexity(0, 0));
+ /* HACK - if the buffer device can't do copy_alpha, disallow */
+diff --git a/base/gxclist.h b/base/gxclist.h
+--- a/base/gxclist.h
++++ b/base/gxclist.h
+@@ -281,6 +281,14 @@ struct gx_device_clist_writer_s {
+ uint mask_id;
+ uint temp_mask_id; /* Mask id of a mask of an image with SMask. */
+ bool is_fillpage;
++ gx_device_color_info clist_color_info; /* color information to be used during clist writing.
++ It may be different than the target device if we
++ are in a transparency group. Since the fill rect
++ commands use the forward procs and we have no
++ access to the graphic state information in those
++ routines, this is the logical place to put this
++ information */
++
+ };
+ #ifndef gx_device_clist_writer_DEFINED
+ #define gx_device_clist_writer_DEFINED
+diff --git a/base/gxclpath.c b/base/gxclpath.c
+--- a/base/gxclpath.c
++++ b/base/gxclpath.c
+@@ -55,7 +55,7 @@ colored_halftone_colors_used(gx_device_clist_writer *cldev,
+ * standard CMYK color mapping function.
+ */
+ if (dev_proc(cldev, map_cmyk_color) != cmyk_1bit_map_cmyk_color)
+- return ((gx_color_index)1 << cldev->color_info.depth) - 1;
++ return ((gx_color_index)1 << cldev->color_info.depth) - 1; /* What about tranparency? Need to check this */
+ /*
+ * Note that c_base[0], and the low-order bit of plane_mask,
+ * correspond to cyan: this requires reversing the bit order of
+@@ -186,7 +186,7 @@ cmd_put_drawing_color(gx_device_clist_writer * cldev, gx_clist_state * pcls,
+ }
+ }
+
+- while (left) {
++ do {
+ prefix_size = 2 + 1 + (offset > 0 ? enc_u_sizew(offset) : 0);
+ req_size = left + prefix_size + enc_u_sizew(left);
+ code = cmd_get_buffer_space(cldev, pcls, req_size);
+@@ -223,10 +223,10 @@ cmd_put_drawing_color(gx_device_clist_writer * cldev, gx_clist_state * pcls,
+ }
+ offset += portion_size;
+ left -= portion_size;
+- }
++ } while (left);
+
+ /* should properly calculate colors_used, but for now just punt */
+- pcls->colors_used.or = ((gx_color_index)1 << cldev->color_info.depth) - 1;
++ pcls->colors_used.or = ((gx_color_index)1 << cldev->clist_color_info.depth) - 1;
+
+ /* Here we can't know whether a pattern paints colors besides
+ black and white, so assume that it does.
+@@ -273,7 +273,7 @@ cmd_drawing_colors_used(gx_device_clist_writer *cldev,
+ else if (gx_dc_is_colored_halftone(pdcolor))
+ return colored_halftone_colors_used(cldev, pdcolor);
+ else
+- return ((gx_color_index)1 << cldev->color_info.depth) - 1;
++ return ((gx_color_index)1 << cldev->clist_color_info.depth) - 1;
+ }
+
+
+diff --git a/base/gxclrast.c b/base/gxclrast.c
+--- a/base/gxclrast.c
++++ b/base/gxclrast.c
+@@ -172,6 +172,12 @@ top_up_cbuf(command_buf_t *pcb, const byte **pcbp)
+ pcb->end_status = sgets(pcb->s, cb_top, nread, &nread);
+ if ( nread == 0 ) {
+ /* No data for this band at all. */
++ if (cb_top >= pcb->end) {
++ /* should not happen */
++ *pcbp = pcb->data;
++ pcb->data[0] = cmd_opv_end_run;
++ return_error(gs_error_ioerror);
++ }
+ *cb_top = cmd_opv_end_run;
+ nread = 1;
+ }
+@@ -619,7 +625,7 @@ in: /* Initialize for a new page. */
+ /* Make sure the buffer contains a full command. */
+ if (cbp >= cbuf.limit) {
+ if (cbuf.end_status < 0) { /* End of file or error. */
+- if (cbp == cbuf.end) {
++ if (cbp >= cbuf.end) {
+ code = (cbuf.end_status == EOFC ? 0 :
+ gs_note_error(gs_error_ioerror));
+ break;
+diff --git a/base/gxclrect.c b/base/gxclrect.c
+--- a/base/gxclrect.c
++++ b/base/gxclrect.c
+@@ -166,7 +166,7 @@ cmd_write_page_rect_cmd(gx_device_clist_writer * cldev, int op)
+ static inline byte *
+ cmd_put_frac31_color(gx_device_clist_writer * cldev, const frac31 *c, byte *dp)
+ {
+- int num_components = cldev->color_info.num_components;
++ int num_components = cldev->clist_color_info.num_components;
+ int j;
+
+ for (j = 0; j < num_components; j++)
+@@ -178,7 +178,7 @@ static inline int
+ cmd_size_frac31_color(gx_device_clist_writer * cldev, const frac31 *c)
+ {
+ int j, s = 0;
+- int num_components = cldev->color_info.num_components;
++ int num_components = cldev->clist_color_info.num_components;
+
+ for (j = 0; j < num_components; j++)
+ s += cmd_size_frac31(c[j]);
+@@ -494,7 +494,7 @@ clist_strip_tile_rectangle(gx_device * dev, const gx_strip_bitmap * tile,
+ &((gx_device_clist *)dev)->writer;
+ int depth =
+ (color1 == gx_no_color_index && color0 == gx_no_color_index ?
+- dev->color_info.depth : 1);
++ cdev->clist_color_info.depth : 1);
+ gx_color_index colors_used =
+ (color1 == gx_no_color_index && color0 == gx_no_color_index ?
+ /* We can't know what colors will be used: assume the worst. */
+@@ -695,7 +695,8 @@ clist_copy_color(gx_device * dev,
+ {
+ gx_device_clist_writer * const cdev =
+ &((gx_device_clist *)dev)->writer;
+- int depth = dev->color_info.depth;
++ int depth = cdev->clist_color_info.depth; /* Could be different than target
++ if 1.4 device */
+ int y0;
+ int data_x_bit;
+ /* We can't know what colors will be used: assume the worst. */
+@@ -946,8 +947,8 @@ clist_strip_copy_rop(gx_device * dev,
+ const gx_strip_bitmap *tiles = textures;
+ int y0;
+ /* Compute the set of possible colors that this operation can generate. */
+- gx_color_index all = ((gx_color_index)1 << dev->color_info.depth) - 1;
+- bool subtractive = dev->color_info.num_components == 4; /****** HACK ******/
++ gx_color_index all = ((gx_color_index)1 << cdev->clist_color_info.depth) - 1;
++ bool subtractive = dev->color_info.num_components >= 4; /****** HACK ******/
+ gx_color_index S =
+ (scolors ? scolors[0] | scolors[1] : sdata ? all : 0);
+ gx_color_index T =
+@@ -1017,7 +1018,7 @@ clist_strip_copy_rop(gx_device * dev,
+ do {
+ code = clist_change_tile(cdev, re.pcls, tiles,
+ (tcolors != 0 ? 1 :
+- dev->color_info.depth));
++ cdev->clist_color_info.depth));
+ } while (RECT_RECOVER(code));
+ if (code < 0 && !(code == gs_error_limitcheck) && SET_BAND_CODE(code))
+ goto error_in_rect;
+@@ -1062,7 +1063,7 @@ clist_strip_copy_rop(gx_device * dev,
+ when tile_space_phase < rep_width && tile_space_phase + rwidth > rep_width,
+ each line to be converted into 2 ones.
+ */
+- int depth = dev->color_info.depth;
++ int depth = cdev->clist_color_info.depth;
+
+ # if 0
+ /* Align bitmap data : */
+diff --git a/base/gxclutil.c b/base/gxclutil.c
+--- a/base/gxclutil.c
++++ b/base/gxclutil.c
+@@ -500,7 +500,8 @@ cmd_put_color(gx_device_clist_writer * cldev, gx_clist_state * pcls,
+ return code;
+ } else {
+ /* Check if the "delta" mode command can be used. */
+- int num_bytes = (cldev->color_info.depth + 7) >> 3;
++ int num_bytes = (cldev->clist_color_info.depth + 7) >> 3; /* clist_color_info may be different than target device
++ due to transparency group during clist writing phase */
+ int delta_bytes = (num_bytes + 1) / 2;
+ gx_color_index delta_offset = cmd_delta_offsets[num_bytes];
+ gx_color_index delta_mask = cmd_delta_masks[num_bytes];
+diff --git a/base/gxcpath.c b/base/gxcpath.c
+--- a/base/gxcpath.c
++++ b/base/gxcpath.c
+@@ -782,6 +782,7 @@ gx_cpath_enum_init(gs_cpath_enum * penum, const gx_clip_path * pcpath)
+ if ((penum->using_path = pcpath->path_valid)) {
+ gx_path_enum_init(&penum->path_enum, &pcpath->path);
+ penum->rp = penum->visit = 0;
++ penum->first_visit = visit_left;
+ } else {
+ gx_path empty_path;
+ gx_clip_list *clp = gx_cpath_list_private(pcpath);
+@@ -791,6 +792,7 @@ gx_cpath_enum_init(gs_cpath_enum * penum, const gx_clip_path * pcpath)
+ /* Initialize the pointers in the path_enum properly. */
+ gx_path_init_local(&empty_path, pcpath->path.memory);
+ gx_path_enum_init(&penum->path_enum, &empty_path);
++ penum->first_visit = visit_left;
+ penum->visit = head;
+ for (rp = head; rp != 0; rp = rp->next)
+ rp->to_visit =
+diff --git a/base/gxdcolor.c b/base/gxdcolor.c
+--- a/base/gxdcolor.c
++++ b/base/gxdcolor.c
+@@ -717,11 +717,14 @@ gx_dc_write_color(
+ uint * psize )
+ {
+ int depth = dev->color_info.depth;
+- int num_bytes = (depth + 8) >> 3; /* NB: +8, not +7 */
++ int num_bytes; /* NB: +8, not +7 */
+
+ /* gx_no_color_index is encoded as a single byte */
+- if (color == gx_no_color_index)
++ if (color == gx_no_color_index) {
+ num_bytes = 1;
++ } else {
++ num_bytes = sizeof(gx_color_index) + 1;
++ }
+
+ /* check for adequate space */
+ if (*psize < num_bytes) {
+@@ -735,8 +738,6 @@ gx_dc_write_color(
+ *psize = 1;
+ *pdata = 0xff;
+ } else {
+- if (depth < 8 * arch_sizeof_color_index)
+- color &= ((gx_color_index)1 << depth) - 1;
+ while (--num_bytes >= 0) {
+ pdata[num_bytes] = color & 0xff;
+ color >>= 8;
+@@ -763,6 +764,7 @@ gx_dc_write_color(
+ *
+ * Returns: # of bytes read, or < 0 in the event of an error
+ */
++
+ int
+ gx_dc_read_color(
+ gx_color_index * pcolor,
+@@ -771,21 +773,22 @@ gx_dc_read_color(
+ int size )
+ {
+ gx_color_index color = 0;
+- int depth = dev->color_info.depth;
+- int i, num_bytes = (depth + 8) >> 3; /* NB: +8, not +7 */
++ int i, num_bytes;
+
+ /* check that enough data has been provided */
+- if (size < 1 || (pdata[0] != 0xff && size < num_bytes))
++ if (size < 1 || (pdata[0] != 0xff && size < sizeof(gx_color_index)))
+ return_error(gs_error_rangecheck);
+
+ /* check of gx_no_color_index */
+ if (pdata[0] == 0xff) {
+ *pcolor = gx_no_color_index;
+ return 1;
++ } else {
++ num_bytes = sizeof(gx_color_index) + 1;
+ }
+
+ /* num_bytes > arch_sizeof_color_index, discard first byte */
+- for (i = (num_bytes >= arch_sizeof_color_index ? 1 : 0); i < num_bytes; i++)
++ for (i = 0; i < num_bytes; i++)
+ color = (color << 8) | pdata[i];
+ *pcolor = color;
+ return num_bytes;
+diff --git a/base/gxdevcli.h b/base/gxdevcli.h
+--- a/base/gxdevcli.h
++++ b/base/gxdevcli.h
+@@ -1198,6 +1198,7 @@ typedef struct gs_param_list_s gs_param_list;
+ */
+ #define dev_t_proc_end_transparency_mask(proc, dev_t)\
+ int proc(gx_device *dev,\
++ gs_imager_state *pis,\
+ gs_transparency_mask_t **pptm)
+ #define dev_proc_end_transparency_mask(proc)\
+ dev_t_proc_end_transparency_mask(proc, gx_device)
+diff --git a/base/gxfapiu.c b/base/gxfapiu.c
+--- a/base/gxfapiu.c
++++ b/base/gxfapiu.c
+@@ -31,7 +31,7 @@
+
+ /* -------------------- UFST callback dispatcher ------------- */
+
+-/* This code provides dispatching UFST callbacks to the PDL */
++/* This code provides dispatching UFST callbacks to the PDL */
+
+ struct IF_STATE;
+
+diff --git a/base/gxfapiu.h b/base/gxfapiu.h
+--- a/base/gxfapiu.h
++++ b/base/gxfapiu.h
+@@ -20,7 +20,7 @@
+ #include "gp.h"
+
+ /* Set UFST callbacks. */
+-/* Warning : the language switch progect doesn't guarantee
++/* Warning : the language switch project doesn't guarantee
+ that this function is called when switching
+ to another interpreter. Therefore each interpreter must take
+ care for its own callback methods before they
+@@ -29,7 +29,7 @@
+ /* Warning : this function may cause a reentrancy problem
+ due to a modification of static variables.
+ Nevertheless this problem isn't important in a
+- sngle interpreter build because the values
++ single interpreter build because the values
+ really change on the first demand only.
+ See also a comment in gs_fapiufst_finit.
+ */
+diff --git a/base/gxfcache.h b/base/gxfcache.h
+--- a/base/gxfcache.h
++++ b/base/gxfcache.h
+@@ -300,6 +300,8 @@ struct gs_font_dir_s {
+ uint enum_index; /* index (N) */
+ uint enum_offset; /* ccache.table[offset] is N'th non-zero entry */
+
++ uint hash;
++
+ /* User parameter AlignToPixels. */
+ bool align_to_pixels;
+
+diff --git a/base/gxfcopy.c b/base/gxfcopy.c
+--- a/base/gxfcopy.c
++++ b/base/gxfcopy.c
+@@ -1976,7 +1976,11 @@ gs_copy_font(gs_font *font, const gs_matrix *orig_matrix, gs_memory_t *mem, gs_f
+ memset(&info, 0, sizeof(info));
+ info.Flags_requested = ~0;
+ code = font->procs.font_info(font, NULL, ~0, &info);
+- if (code < 0)
++
++ /* We can ignore a lack of FontInfo for TrueType fonts which
++ * are descendants of CID fonts
++ */
++ if (code < 0 && !(font->FontType == ft_CID_TrueType))
+ return code;
+
+ /* Allocate the generic copied information. */
+diff --git a/base/gxfixed.h b/base/gxfixed.h
+--- a/base/gxfixed.h
++++ b/base/gxfixed.h
+@@ -22,12 +22,23 @@
+ * quantities: integers lose accuracy in crucial places,
+ * and floating point arithmetic is slow.
+ */
++#if ARCH_SIZEOF_INT == 4
++typedef int fixed;
++typedef uint ufixed; /* only used in a very few places */
++# define ARCH_SIZEOF_FIXED ARCH_SIZEOF_INT
++# define max_fixed max_int
++# define min_fixed min_int
++#else
++# if ARCH_SIZEOF_LONG == 4
+ typedef long fixed;
+ typedef ulong ufixed; /* only used in a very few places */
+-#define ARCH_SIZEOF_FIXED ARCH_SIZEOF_LONG
++# define ARCH_SIZEOF_FIXED ARCH_SIZEOF_LONG
++# define max_fixed max_long
++# define min_fixed min_long
++# endif
++#endif
++
+
+-#define max_fixed max_long
+-#define min_fixed min_long
+ #define fixed_0 0L
+ #define fixed_epsilon 1L
+ /*
+@@ -119,13 +130,9 @@ typedef ulong ufixed; /* only used in a very few places */
+ #define fixed_truncated(x) ((x) < 0 ? fixed_ceiling(x) : fixed_floor(x))
+
+ /* Define the largest and smallest integer values that fit in a fixed. */
+-#if arch_sizeof_int == arch_sizeof_long
+-# define max_int_in_fixed fixed2int(max_fixed)
+-# define min_int_in_fixed fixed2int(min_fixed)
+-#else
+-# define max_int_in_fixed max_int
+-# define min_int_in_fixed min_int
+-#endif
++#define max_int_in_fixed fixed2int(max_fixed)
++#define min_int_in_fixed fixed2int(min_fixed)
++
+ /*
+ * Define a macro for checking for overflow of the sum of two fixed values
+ * and and setting the result to the sum if no overflow.
+diff --git a/base/gxhldevc.c b/base/gxhldevc.c
+--- a/base/gxhldevc.c
++++ b/base/gxhldevc.c
+@@ -44,10 +44,9 @@ void gx_hld_saved_color_init(gx_hl_saved_color * psc)
+ */
+ const gs_state * gx_hld_get_gstate_ptr(const gs_imager_state * pis)
+ {
+- extern_st(st_gs_state); /* only for testing */
+
+- /* Check to verify the structure type is really st_gs_state */
+- if (pis == NULL || gs_object_type(pis->memory, pis) != &st_gs_state)
++ /* Check to verify the structure type is really (gs_state *) */
++ if (pis == NULL || pis->is_gstate == false)
+ return NULL;
+
+ return (const gs_state *) pis;
+diff --git a/base/gximag3x.c b/base/gximag3x.c
+--- a/base/gximag3x.c
++++ b/base/gximag3x.c
+@@ -599,8 +599,20 @@ gx_image3x_plane_data(gx_image_enum_common_t * info,
+ h = min(height, h1);
+ /* Initialized rows_used in case we get an error. */
+ *rows_used = 0;
++
++/* FIX_ME. In the soft mask branch
++ the file associated with bug 689290
++ gets into an endless loop. This
++ is related to the size mismatch of the
++ soft mask which is 1x1 and the
++ image size */
++
+ if (h <= 0)
++#ifdef ENDLESS_LOOP
+ return 0;
++#else
++ return 1;
++#endif
+
+ /* Handle masks from separate sources. */
+ for (i = 0; i < NUM_MASKS; ++i)
+diff --git a/base/gxiodev.h b/base/gxiodev.h
+--- a/base/gxiodev.h
++++ b/base/gxiodev.h
+@@ -175,6 +175,12 @@ int gs_putdevparams(gx_io_device *, gs_param_list *);
+ /* if opening a file fails. */
+ int gs_fopen_errno_to_code(int);
+
++/* Interface functions for clients that want iodev independent access to */
++/* the gp_enumerate functions */
++file_enum *gs_enumerate_files_init(const char *pat, uint patlen, gs_memory_t * mem);
++uint gs_enumerate_files_next(file_enum * pfen, char *ptr, uint maxlen);
++void gs_enumerate_files_close(file_enum * pfen);
++
+ /* Test whether a string is equal to a character. */
+ /* (This is used for access testing in file_open procedures.) */
+ #define streq1(str, chr)\
+diff --git a/base/gxistate.h b/base/gxistate.h
+--- a/base/gxistate.h
++++ b/base/gxistate.h
+@@ -215,6 +215,7 @@ typedef struct gs_devicen_color_map_s {
+ * than &pis->ctm.
+ */
+ #define gs_imager_state_common\
++ bool is_gstate; /* is this imager state part of gstate ? */\
+ gs_memory_t *memory;\
+ void *client_data;\
+ gx_line_params line_params;\
+@@ -231,6 +232,8 @@ typedef struct gs_devicen_color_map_s {
+ bool text_knockout;\
+ uint text_rendering_mode;\
+ gs_transparency_state_t *transparency_stack;\
++ bool has_transparency; /* used to keep from doing shading fills in device color space */\
++ gx_device *trans_device; /* trans device has all mappings to group color space */\
+ bool overprint;\
+ int overprint_mode;\
+ int effective_overprint_mode;\
+@@ -246,7 +249,7 @@ typedef struct gs_devicen_color_map_s {
+ (*get_cmap_procs)(const gs_imager_state *, const gx_device *);\
+ gs_color_rendering_state_common
+ #define st_imager_state_num_ptrs\
+- (st_line_params_num_ptrs + st_cr_state_num_ptrs + 2)
++ (st_line_params_num_ptrs + st_cr_state_num_ptrs + 3)
+ /* Access macros */
+ #define ctm_only(pis) (*(const gs_matrix *)&(pis)->ctm)
+ #define ctm_only_writable(pis) (*(gs_matrix *)&(pis)->ctm)
+@@ -267,12 +270,12 @@ struct gs_imager_state_s {
+ };
+
+ /* Initialization for gs_imager_state */
+-#define gs_imager_state_initial(scale)\
+- 0, 0, { gx_line_params_initial },\
++#define gs_imager_state_initial(scale, is_gstate)\
++ is_gstate, 0, 0, { gx_line_params_initial },\
+ { (float)(scale), 0.0, 0.0, (float)(-(scale)), 0.0, 0.0 },\
+ false, {0, 0}, {0, 0}, false, \
+ lop_default, gx_max_color_value, BLEND_MODE_Compatible,\
+- { 1.0 }, { 1.0 }, 0, 0/*false*/, 0, 0, 0/*false*/, 0, 0, 1.0, \
++ { 1.0 }, { 1.0 }, 0, 0/*false*/, 0, 0, 0, 0, 0/*false*/, 0, 0, 1.0, \
+ { fixed_half, fixed_half }, 0/*false*/, 0/*false*/, 0/*false*/, 1.0,\
+ 1, INIT_CUSTOM_COLOR_PTR /* 'Custom color' callback pointer */ \
+ gx_default_get_cmap_procs
+diff --git a/base/gxpcmap.c b/base/gxpcmap.c
+--- a/base/gxpcmap.c
++++ b/base/gxpcmap.c
+@@ -886,13 +886,24 @@ gx_pattern_load(gx_device_color * pdc, const gs_imager_state * pis,
+ if (saved->pattern_cache == 0)
+ saved->pattern_cache = pis->pattern_cache;
+ gs_setdevice_no_init(saved, (gx_device *)adev);
++ if (pinst->template.uses_transparency) {
++ /* This should not occur from PS or PDF, but is provided for other clients (XPS) */
++ if_debug0('v', "gx_pattern_load: pushing the pdf14 compositor device into this graphics state\n");
++ if ((code = gs_push_pdf14trans_device(saved)) < 0)
++ return code;
++ }
+ code = (*pinst->template.PaintProc)(&pdc->ccolor, saved);
+ if (code < 0) {
+ dev_proc(adev, close_device)((gx_device *)adev);
+- /* Freeing the state will free the device. */
++ /* Freeing the state will free the device and the pdf14 compositor (if any). */
+ gs_state_free(saved);
+ return code;
+ }
++ if (pinst->template.uses_transparency) {
++ if_debug0('v', "gx_pattern_load: popping the pdf14 compositor device from this graphics state\n");
++ if ((code = gs_pop_pdf14trans_device(saved)) < 0)
++ return code;
++ }
+ /* We REALLY don't like the following cast.... */
+ code = gx_pattern_cache_add_entry((gs_imager_state *)pis,
+ adev, &ctile);
+diff --git a/base/gxshade6.c b/base/gxshade6.c
+--- a/base/gxshade6.c
++++ b/base/gxshade6.c
+@@ -190,6 +190,8 @@ is_linear_color_applicable(const patch_fill_state_t *pfs)
+ return false;
+ if (pfs->dev->color_info.separable_and_linear != GX_CINFO_SEP_LIN)
+ return false;
++ if (pfs->pis->has_transparency == true)
++ return false; /* set in pdf14 dev if we are in a trans group */
+ if (gx_get_cmap_procs(pfs->pis, pfs->dev)->is_halftoned(pfs->pis, pfs->dev))
+ return false;
+ return true;
+diff --git a/base/gxtype1.c b/base/gxtype1.c
+--- a/base/gxtype1.c
++++ b/base/gxtype1.c
+@@ -573,7 +573,12 @@ gs_type1_glyph_info(gs_font *font, gs_glyph glyph, const gs_matrix *pmat,
+ code = pdata->interpret(&cis, &gdata, &value);
+ switch (code) {
+ case 0: /* done with no [h]sbw, error */
+- code = gs_note_error(gs_error_invalidfont);
++ /* Adobe interpreters ignore the error! */
++ info->width[wmode].x = 0;
++ info->width[wmode].y = 0;
++ info->v.x = 0;
++ info->v.y = 0;
++ break;
+ default: /* code < 0, error */
+ return code;
+ case type1_result_callothersubr: /* unknown OtherSubr */
+diff --git a/base/lib.mak b/base/lib.mak
+--- a/base/lib.mak
++++ b/base/lib.mak
+@@ -450,6 +450,7 @@ gxpcolor_h=$(GLSRC)gxpcolor.h\
+ gscolor_h=$(GLSRC)gscolor.h $(gxtmap_h)
+ gsstate_h=$(GLSRC)gsstate.h\
+ $(gscolor_h) $(gscpm_h) $(gscsel_h) $(gsdevice_h) $(gsht_h) $(gsline_h)
++gscolorbuffer_h=$(GLSRC)gscolorbuffer.h
+
+ gzacpath_h=$(GLSRC)gzacpath.h $(GLSRC)gxcpath.h
+ gzcpath_h=$(GLSRC)gzcpath.h $(gxcpath_h) $(gzpath_h)
+@@ -1314,7 +1315,7 @@ $(GLOBJ)sdcte.$(OBJ) : $(GLSRC)sdcte.c $(AK)\
+ $(GLOBJ)sjpege.$(OBJ) : $(GLSRC)sjpege.c $(AK)\
+ $(stdio__h) $(string__h) $(gx_h)\
+ $(jerror__h) $(jpeglib__h)\
+- $(gserrors_h) $(sjpeg_h) $(sdct_h) $(strimpl_h)
++ $(sjpeg_h) $(sdct_h) $(strimpl_h)
+ $(GLJCC) $(GLO_)sjpege.$(OBJ) $(C_) $(GLSRC)sjpege.c
+
+ # sdeparam is used by the filter operator and the PS/PDF writer.
+@@ -1344,7 +1345,7 @@ $(GLOBJ)sdctd.$(OBJ) : $(GLSRC)sdctd.c $(AK)\
+ $(GLOBJ)sjpegd.$(OBJ) : $(GLSRC)sjpegd.c $(AK)\
+ $(stdio__h) $(string__h) $(gx_h)\
+ $(jerror__h) $(jpeglib__h)\
+- $(gserrors_h) $(sjpeg_h) $(sdct_h) $(strimpl_h)
++ $(sjpeg_h) $(sdct_h) $(strimpl_h)
+ $(GLJCC) $(GLO_)sjpegd.$(OBJ) $(C_) $(GLSRC)sjpegd.c
+
+ # sddparam is used by the filter operator.
+@@ -1471,7 +1472,7 @@ $(GLD)sjpx_jasper.dev : $(LIB_MAK) $(ECHOGS_XE) \
+ # jasper.dev is created in jasper.mak
+
+ $(GLOBJ)sjpx.$(OBJ) : $(GLSRC)sjpx.c $(AK) \
+- $(memory__h) $(gsmalloc_h) $(gserror_h) $(gserrors_h) \
++ $(memory__h) $(gsmalloc_h) $(gserror_h) \
+ $(gdebug_h) $(strimpl_h) $(sjpx_h)
+ $(GLJASCC) $(GLO_)sjpx.$(OBJ) $(C_) $(GLSRC)sjpx.c
+
+@@ -2477,6 +2478,12 @@ $(GLOBJ)gsncdummy.$(OBJ) : $(GLSRC)gsncdummy.c $(GXERR) $(math__h)\
+ $(memory__h) $(gscdefs_h) $(gscspace_h) $(gscie_h) $(gsicc_h)\
+ $(gxdevice_h) $(gzstate_h) $(gsutil_h) $(gxcie_h) $(gsncdummy_h)
+ $(GLCC) $(GLO_)gsncdummy.$(OBJ) $(C_) $(GLSRC)gsncdummy.c
++
++# ---------------- Color Buffer Proc. Support Used In Trans. ---------------- #
++
++$(GLOBJ)gscolorbuffer.$(OBJ) : $(GLSRC)gscolorbuffer.c $(GXERR)\
++ $(stdpre_h) $(gstypes_h) $(gsmemory_h) $(gxblend_h)
++ $(GLCC) $(GLO_)gscolorbuffer.$(OBJ) $(C_) $(GLSRC)gscolorbuffer.c
+
+ # ================ Display Postscript extensions ================ #
+
+@@ -2560,15 +2567,15 @@ $(GLD)traplib.dev : $(LIB_MAK) $(ECHOGS_XE) $(traplib_)
+
+ # ---------------- Transparency ---------------- #
+
+-gstrans_h=$(GLSRC)gstrans.h $(gstparam_h) $(gxcomp_h) $(gsmatrix_h)
++gstrans_h=$(GLSRC)gstrans.h $(gstparam_h) $(gxcomp_h) $(gsmatrix_h) $(gxblend_h)
+ gsipar3x_h=$(GLSRC)gsipar3x.h $(gsiparam_h) $(gsiparm3_h)
+ gximag3x_h=$(GLSRC)gximag3x.h $(gsipar3x_h) $(gxiparam_h)
+-gxblend_h=$(GLSRC)gxblend.h $(gxcindex_h) $(gxcvalue_h) $(gxxfrac_h)
++gxblend_h=$(GLSRC)gxblend.h $(gxcindex_h) $(gxcvalue_h) $(gxxfrac_h) $(gxdevcli_h)
+ gdevp14_h=$(GLSRC)gdevp14.h $(GLSRC)gxcmap.h
+
+ $(GLOBJ)gstrans.$(OBJ) : $(GLSRC)gstrans.c $(GXERR)\
+- $(math__h) $(memory__h) $(gdevp14_h)\
+- $(gstrans_h) $(gsutil_h) $(gxdevcli_h) $(gzstate_h)
++ $(math__h) $(memory__h) $(gdevp14_h) $(gstrans_h)\
++ $(gsutil_h) $(gxdevcli_h) $(gzstate_h) $(gscspace_h)
+ $(GLCC) $(GLO_)gstrans.$(OBJ) $(C_) $(GLSRC)gstrans.c
+
+ $(GLOBJ)gximag3x.$(OBJ) : $(GLSRC)gximag3x.c $(GXERR) $(math__h) $(memory__h)\
+@@ -2578,24 +2585,25 @@ $(GLOBJ)gximag3x.$(OBJ) : $(GLSRC)gximag3x.c $(GXERR) $(math__h) $(memory__h)\
+ $(GLCC) $(GLO_)gximag3x.$(OBJ) $(C_) $(GLSRC)gximag3x.c
+
+ $(GLOBJ)gxblend.$(OBJ) : $(GLSRC)gxblend.c $(GX) $(memory__h)\
+- $(gstparam_h) $(gxblend_h)
++ $(gstparam_h) $(gxblend_h) $(gxcolor2_h)
+ $(GLCC) $(GLO_)gxblend.$(OBJ) $(C_) $(GLSRC)gxblend.c
+
+ $(GLOBJ)gxblend1.$(OBJ) : $(GLSRC)gxblend1.c $(GX) $(memory__h)\
+ $(gstparam_h) $(gxrect_h) $(gxdcconv_h) $(gxblend_h) $(gxdevcli_h) $(gxistate_h)\
+- $(gdevdevn_h) $(gdevp14_h) $(vdtrace_h)
++ $(gdevdevn_h) $(gdevp14_h) $(vdtrace_h) $(gxdcconv_h)
+ $(GLCC) $(GLO_)gxblend1.$(OBJ) $(C_) $(GLSRC)gxblend1.c
+
+ $(GLOBJ)gdevp14.$(OBJ) : $(GLSRC)gdevp14.c $(GXERR) $(math__h) $(memory__h)\
+ $(gscdefs_h) $(gxdevice_h) $(gsdevice_h) $(gsstruct_h) $(gscoord_h) $(gxistate_h) $(gxdcolor_h)\
+ $(gxiparam_h) $(gstparam_h) $(gxblend_h) $(gxtext_h) $(gsdfilt_h) $(gsimage_h)\
+ $(gsrect_h) $(gzstate_h) $(gdevdevn_h) $(gdevp14_h) $(gsovrc_h) $(gxcmap_h) $(gscolor1_h)\
+- $(gstrans_h) $(gsutil_h) $(gxcldev_h) $(gxclpath_h) $(gxdcconv_h) $(vdtrace_h)
++ $(gstrans_h) $(gsutil_h) $(gxcldev_h) $(gxclpath_h) $(gxdcconv_h) $(vdtrace_h)\
++ $(gscolorbuffer_h) $(gsptype2_h)
+ $(GLCC) $(GLO_)gdevp14.$(OBJ) $(C_) $(GLSRC)gdevp14.c
+
+ translib_=$(GLOBJ)gstrans.$(OBJ) $(GLOBJ)gximag3x.$(OBJ)\
+ $(GLOBJ)gxblend.$(OBJ) $(GLOBJ)gxblend1.$(OBJ) $(GLOBJ)gdevp14.$(OBJ) $(GLOBJ)gdevdevn.$(OBJ)\
+- $(GLOBJ)gdevdcrd.$(OBJ)
++ $(GLOBJ)gdevdcrd.$(OBJ) $(GLOBJ)gscolorbuffer.$(OBJ)
+ $(GLD)translib.dev : $(LIB_MAK) $(ECHOGS_XE) $(translib_)\
+ $(GLD)cspixlib.dev $(GLD)bboxutil.dev $(GLD)cielib.dev
+ $(SETMOD) $(GLD)translib $(translib_)
+diff --git a/base/lwf_jp2.mak b/base/lwf_jp2.mak
+--- a/base/lwf_jp2.mak
++++ b/base/lwf_jp2.mak
+@@ -171,7 +171,6 @@ lwf_jp2_HDRS = \
+ $(LWF_JP2_SRC)jp2t_memory.h \
+ $(LWF_JP2_SRC)jp2t_progression.h \
+ $(LWF_JP2_SRC)jp2t_transcoder.h \
+- $(LWF_JP2_SRC)lwf_jp2_geo.h \
+ $(LWF_JP2_SRC)lwf_jp2.h
+
+ # switch in the selected library .dev
+diff --git a/base/saes.h b/base/saes.h
+--- a/base/saes.h
++++ b/base/saes.h
+@@ -47,8 +47,9 @@ int s_aes_set_key(stream_aes_state * state,
+ /* state declaration macro;
+ should be updated for the aes_context finalization */
+ #define private_st_aes_state() \
+- gs_private_st_simple(st_aes_state, stream_aes_state,\
+- "aes filter state")
++ gs_private_st_ptrs1(st_aes_state, stream_aes_state, "aes filter state",\
++ aes_state_enum_ptrs, aes_state_reloc_ptrs, ctx)
++
+ extern const stream_template s_aes_template;
+
+ /* (de)crypt a section of text in a buffer -- the procedure is the same
+diff --git a/base/sfxcommon.c b/base/sfxcommon.c
+--- a/base/sfxcommon.c
++++ b/base/sfxcommon.c
+@@ -75,8 +75,13 @@ file_open_stream(const char *fname, uint len, const char *file_access,
+ return 0; /* so this is the same as len == 0, so return NULL */
+ code = (*fopen_proc)(iodev, (char *)(*ps)->cbuf, fmode, &file,
+ (char *)(*ps)->cbuf, (*ps)->bsize);
+- if (code < 0)
++ if (code < 0) {
++ /* discard the stuff we allocated to keep from accumulating stuff needing GC */
++ gs_free_object(mem, (*ps)->cbuf, "file_close(buffer)");
++ gs_free_object(mem, *ps, "file_prepare_stream(stream)");
++ *ps = NULL;
+ return code;
++ }
+ file_init_stream(*ps, file, fmode, (*ps)->cbuf, (*ps)->bsize);
+ return 0;
+ }
+@@ -181,6 +186,7 @@ file_prepare_stream(const char *fname, uint len, const char *file_access,
+ buffer[0] = 0; /* safety */
+ s->cbuf = buffer;
+ s->bsize = s->cbsize = buffer_size;
++ s->save_close = 0; /* in case this stream gets disabled before init finishes */
+ *ps = s;
+ return 0;
+ }
+diff --git a/base/sjpegd.c b/base/sjpegd.c
+--- a/base/sjpegd.c
++++ b/base/sjpegd.c
+@@ -18,7 +18,6 @@
+ #include "jpeglib_.h"
+ #include "jerror_.h"
+ #include "gx.h"
+-#include "gserrors.h"
+ #include "strimpl.h"
+ #include "sdct.h"
+ #include "sjpeg.h"
+diff --git a/base/sjpege.c b/base/sjpege.c
+--- a/base/sjpege.c
++++ b/base/sjpege.c
+@@ -18,7 +18,6 @@
+ #include "jpeglib_.h"
+ #include "jerror_.h"
+ #include "gx.h"
+-#include "gserrors.h"
+ #include "strimpl.h"
+ #include "sdct.h"
+ #include "sjpeg.h"
+diff --git a/base/sjpx.c b/base/sjpx.c
+--- a/base/sjpx.c
++++ b/base/sjpx.c
+@@ -15,7 +15,6 @@
+ /* JPXDecode filter implementation -- hooks in libjasper */
+
+ #include "memory_.h"
+-#include "gserrors.h"
+ #include "gserror.h"
+ #include "gdebug.h"
+ #include "strimpl.h"
+diff --git a/base/stream.c b/base/stream.c
+--- a/base/stream.c
++++ b/base/stream.c
+@@ -1259,9 +1259,9 @@ s_close_disable(stream *s)
+ int
+ file_close_disable(stream * s)
+ {
+- int code = (*s->save_close)(s);
+-
+- if (code)
++ int code;
++
++ if ((*s->save_close != NULL) && ((code = (*s->save_close)(s)) != 0))
+ return code;
+ s_close_disable(s);
+ return file_close_finish(s);
+diff --git a/base/ttinterp.c b/base/ttinterp.c
+--- a/base/ttinterp.c
++++ b/base/ttinterp.c
+@@ -1836,6 +1836,10 @@ static int nInstrCount=0;
+ {
+ CUR.IP += (Int)(args[0]);
+ CUR.step_ins = FALSE;
++
++ /* See JMPR below */
++ if(CUR.code[CUR.IP] != 0x2D && CUR.code[CUR.IP - 1] == 0x2D)
++ CUR.IP -= 1;
+ }
+ }
+
+@@ -1848,6 +1852,16 @@ static int nInstrCount=0;
+ {
+ CUR.IP += (Int)(args[0]);
+ CUR.step_ins = FALSE;
++
++ if(CUR.code[CUR.IP] != 0x2D && CUR.code[CUR.IP - 1] == 0x2D)
++ /* The JPMR is meant to stop at the ENDF instruction to finish
++ * the function. However the programmer made a mistake, and ended
++ * up one byte too far. I suspect that some TT interpreters handle this
++ * by detecting that the IP has gone off the end of the function. We can
++ * allow for simple cases here by just checking the preceding byte.
++ * Fonts with this problem are not uncommon.
++ */
++ CUR.IP -= 1;
+ }
+
+
+@@ -1861,6 +1875,10 @@ static int nInstrCount=0;
+ {
+ CUR.IP += (Int)(args[0]);
+ CUR.step_ins = FALSE;
++
++ /* See JMPR above */
++ if(CUR.code[CUR.IP] != 0x2D && CUR.code[CUR.IP - 1] == 0x2D)
++ CUR.IP -= 1;
+ }
+ }
+
+@@ -3856,7 +3874,11 @@ static int nInstrCount=0;
+ if ( BOUNDS( args[0], CUR.zp0.n_points ) ||
+ BOUNDS( args[1], CUR.cvtSize ) )
+ {
+- CUR.error = TT_Err_Invalid_Reference;
++ /* Ignore these errors, abort the instruction
++ * and continue. This restores the FreeType
++ * behaviour when pedantic_hinting is false. For bug
++ * #689471, see also Ins_SHC above and bug #688501.
++ */
+ return;
+ }
+
+diff --git a/base/winlib.mak b/base/winlib.mak
+--- a/base/winlib.mak
++++ b/base/winlib.mak
+@@ -80,7 +80,11 @@ UFST_LIB_EXT=.lib
+ # Define conditinal name for FreeType bridge :
+ !ifdef FT_ROOT
+ FT_BRIDGE = 1
+-FT_LIB_EXT=.lib
++FT_CFLAGS=$(I_)$(FT_ROOT)$(D)include$(_I)
++!ifndef FT_LIB
++FT_LIB = freetype238MT_D
++!endif
++FT_LIBS=$(FT_ROOT)$(D)objs$(D)$(FT_LIB).lib
+ !endif
+
+ # Define the files to be removed by `make clean'.
+diff --git a/base/wrfont.c b/base/wrfont.c
+--- a/base/wrfont.c
++++ /dev/null
+@@ -1,78 +0,0 @@
+-/* Copyright (C) 2001-2006 Artifex Software, Inc.
+- All Rights Reserved.
+-
+- This software is provided AS-IS with no warranty, either express or
+- implied.
+-
+- This software is distributed under license and may not be copied, modified
+- or distributed except as expressly authorized under the terms of that
+- license. Refer to licensing information at http://www.artifex.com/
+- or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
+- San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
+-*/
+-
+-/* $Id: wrfont.c 8022 2007-06-05 22:23:38Z giles $ */
+-/*
+-Support functions to serialize fonts as PostScript code that can
+-then be passed to FreeType via the FAPI FreeType bridge.
+-Started by Graham Asher, 9th August 2002.
+-*/
+-
+-#include "wrfont.h"
+-#include "stdio_.h"
+-
+-#define EEXEC_KEY 55665
+-#define EEXEC_FACTOR 52845
+-#define EEXEC_OFFSET 22719
+-
+-void WRF_init(WRF_output* a_output,unsigned char* a_buffer,long a_buffer_size)
+- {
+- a_output->m_pos = a_buffer;
+- a_output->m_limit = a_buffer_size;
+- a_output->m_count = 0;
+- a_output->m_encrypt = false;
+- a_output->m_key = EEXEC_KEY;
+- }
+-
+-void WRF_wbyte(WRF_output* a_output,unsigned char a_byte)
+- {
+- if (a_output->m_count < a_output->m_limit)
+- {
+- if (a_output->m_encrypt)
+- {
+- a_byte ^= (a_output->m_key >> 8);
+- a_output->m_key = (unsigned short)((a_output->m_key + a_byte) * EEXEC_FACTOR + EEXEC_OFFSET);
+- }
+- *a_output->m_pos++ = a_byte;
+- }
+- a_output->m_count++;
+- }
+-
+-void WRF_wtext(WRF_output* a_output,const unsigned char* a_string,long a_length)
+- {
+- while (a_length > 0)
+- {
+- WRF_wbyte(a_output,*a_string++);
+- a_length--;
+- }
+- }
+-
+-void WRF_wstring(WRF_output* a_output,const char* a_string)
+- {
+- while (*a_string)
+- WRF_wbyte(a_output,*a_string++);
+- }
+-
+-void WRF_wfloat(WRF_output* a_output,double a_float)
+- {
+- char buffer[32];
+- sprintf(buffer,"%f",a_float);
+- WRF_wstring(a_output,buffer);
+- }
+-
+-void WRF_wint(WRF_output* a_output,long a_int)
+- {
+- char buffer[32];
+- sprintf(buffer,"%ld",a_int);
+- WRF_wstring(a_output,buffer);
+- }
+diff --git a/base/wrfont.h b/base/wrfont.h
+--- a/base/wrfont.h
++++ /dev/null
+@@ -1,42 +0,0 @@
+-/* Copyright (C) 2001-2006 Artifex Software, Inc.
+- All Rights Reserved.
+-
+- This software is provided AS-IS with no warranty, either express or
+- implied.
+-
+- This software is distributed under license and may not be copied, modified
+- or distributed except as expressly authorized under the terms of that
+- license. Refer to licensing information at http://www.artifex.com/
+- or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
+- San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
+-*/
+-
+-/* $Id: wrfont.h 8022 2007-06-05 22:23:38Z giles $ */
+-/*
+-Header for support functions to serialize fonts as PostScript code that can
+-then be passed to FreeType via the FAPI FreeType bridge.
+-Started by Graham Asher, 9th August 2002.
+-*/
+-
+-#ifndef wrfont_INCLUDED
+-#define wrfont_INCLUDED
+-
+-#include "stdpre.h"
+-
+-typedef struct WRF_output_
+- {
+- unsigned char* m_pos;
+- long m_limit;
+- long m_count;
+- bool m_encrypt;
+- unsigned short m_key;
+- } WRF_output;
+-
+-void WRF_init(WRF_output* a_output,unsigned char* a_buffer,long a_buffer_size);
+-void WRF_wbyte(WRF_output* a_output,unsigned char a_byte);
+-void WRF_wtext(WRF_output* a_output,const unsigned char* a_string,long a_length);
+-void WRF_wstring(WRF_output* a_output,const char* a_string);
+-void WRF_wfloat(WRF_output* a_output,double a_float);
+-void WRF_wint(WRF_output* a_output,long a_int);
+-
+-#endif
+diff --git a/base/write_t1.c b/base/write_t1.c
+--- a/base/write_t1.c
++++ /dev/null
+@@ -1,193 +0,0 @@
+-/* Copyright (C) 2001-2006 Artifex Software, Inc.
+- All Rights Reserved.
+-
+- This software is provided AS-IS with no warranty, either express or
+- implied.
+-
+- This software is distributed under license and may not be copied, modified
+- or distributed except as expressly authorized under the terms of that
+- license. Refer to licensing information at http://www.artifex.com/
+- or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
+- San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
+-*/
+-
+-/* $Id: write_t1.c 8022 2007-06-05 22:23:38Z giles $ */
+-
+-/*
+-Functions to serialize a type 1 font as PostScript code that can then be
+-passed to FreeType via the FAPI FreeType bridge.
+-Started by Graham Asher, 26th July 2002.
+-*/
+-
+-#include "wrfont.h"
+-#include "write_t1.h"
+-
+-/*
+-Public structures and functions in this file are prefixed with FF_ because they are part of
+-the FAPI FreeType implementation.
+-*/
+-
+-static void write_word_entry(FAPI_font* a_fapi_font,WRF_output* a_output,const char* a_name,int a_index,int a_divisor)
+- {
+- short x;
+- WRF_wbyte(a_output,'/');
+- WRF_wstring(a_output,a_name);
+- WRF_wbyte(a_output,' ');
+- /* Get the value and convert it from unsigned to signed by assigning it to a short. */
+- x = a_fapi_font->get_word(a_fapi_font,a_index,0);
+- /* Divide by the divisor to bring it back to font units. */
+- x = (short)(x / a_divisor);
+- WRF_wint(a_output,x);
+- WRF_wstring(a_output," def\n");
+- }
+-
+-static void write_array_entry_with_count(FAPI_font* a_fapi_font,WRF_output* a_output,const char* a_name,int a_index,int a_count,int a_divisor)
+- {
+- int i;
+-
+- if (a_count <= 0)
+- return;
+-
+- WRF_wbyte(a_output,'/');
+- WRF_wstring(a_output,a_name);
+- WRF_wstring(a_output," [");
+- for (i = 0; i < a_count; i++)
+- {
+- /* Get the value and convert it from unsigned to signed by assigning it to a short. */
+- short x = a_fapi_font->get_word(a_fapi_font,a_index,i);
+- /* Divide by the divisor to bring it back to font units. */
+- x = (short)(x / a_divisor);
+- WRF_wint(a_output,x);
+- WRF_wbyte(a_output,(byte)(i == a_count - 1 ? ']' : ' '));
+- }
+- WRF_wstring(a_output," def\n");
+- }
+-
+-
+-static void write_array_entry(FAPI_font* a_fapi_font,WRF_output* a_output,const char* a_name,int a_index,int a_divisor)
+- {
+- /* NOTE that the feature index must be preceded by the count index for this to work. */
+- int count = a_fapi_font->get_word(a_fapi_font,a_index - 1,0);
+- write_array_entry_with_count(a_fapi_font,a_output,a_name,a_index,count,a_divisor);
+- }
+-
+-static void write_subrs(FAPI_font* a_fapi_font,WRF_output* a_output)
+- {
+- int i;
+- int count = a_fapi_font->get_word(a_fapi_font,FAPI_FONT_FEATURE_Subrs_count,0);
+- if (count <= 0)
+- return;
+-
+- WRF_wstring(a_output,"/Subrs ");
+- WRF_wint(a_output,count);
+- WRF_wstring(a_output," array\n");
+-
+- for (i = 0; i < count; i++)
+- {
+- long length = a_fapi_font->get_subr(a_fapi_font,i,0,0);
+- long buffer_size;
+- WRF_wstring(a_output,"dup ");
+- WRF_wint(a_output,i);
+- WRF_wbyte(a_output,' ');
+- WRF_wint(a_output,length);
+- WRF_wstring(a_output," RD ");
+-
+- /* Get the subroutine into the buffer and encrypt it in place. */
+- buffer_size = a_output->m_limit - a_output->m_count;
+- if (buffer_size >= length)
+- {
+- a_fapi_font->get_subr(a_fapi_font,i,a_output->m_pos,(ushort)length);
+- WRF_wtext(a_output,a_output->m_pos,length);
+- }
+- else
+- a_output->m_count += length;
+-
+- WRF_wstring(a_output," NP\n");
+- }
+-
+- WRF_wstring(a_output,"ND\n");
+- }
+-
+-static void write_private_dictionary(FAPI_font* a_fapi_font,WRF_output* a_output)
+- {
+- a_output->m_encrypt = true;
+-
+- /* Write 4 bytes that must encrypt to at least one character that cannot be a valid hexadecimal character. */
+- WRF_wstring(a_output,"XXXX");
+-
+- /*+ to do: correct size of dictionary from 8. */
+- WRF_wstring(a_output,"dup /Private 8 dict dup begin\n");
+-
+- WRF_wstring(a_output,"/MinFeature {16 16} def\n");
+- WRF_wstring(a_output,"/password 5839 def\n");
+- WRF_wstring(a_output,"/lenIV -1 def\n"); /* indicate that /subrs are not encoded. */
+- write_word_entry(a_fapi_font,a_output,"BlueFuzz",FAPI_FONT_FEATURE_BlueFuzz,16);
+-
+- WRF_wstring(a_output,"/BlueScale ");
+- WRF_wfloat(a_output,a_fapi_font->get_long(a_fapi_font,FAPI_FONT_FEATURE_BlueScale,0) / 65536.0);
+- WRF_wstring(a_output," def\n");
+-
+- write_word_entry(a_fapi_font,a_output,"BlueShift",FAPI_FONT_FEATURE_BlueShift,16);
+- write_array_entry(a_fapi_font,a_output,"BlueValues",FAPI_FONT_FEATURE_BlueValues,16);
+- write_array_entry(a_fapi_font,a_output,"OtherBlues",FAPI_FONT_FEATURE_OtherBlues,16);
+- write_array_entry(a_fapi_font,a_output,"FamilyBlues",FAPI_FONT_FEATURE_FamilyBlues,16);
+- write_array_entry(a_fapi_font,a_output,"FamilyOtherBlues",FAPI_FONT_FEATURE_FamilyOtherBlues,16);
+- write_word_entry(a_fapi_font,a_output,"ForceBold",FAPI_FONT_FEATURE_ForceBold,1);
+- write_array_entry_with_count(a_fapi_font,a_output,"StdHW",FAPI_FONT_FEATURE_StdHW,1,16);
+- write_array_entry_with_count(a_fapi_font,a_output,"StdVW",FAPI_FONT_FEATURE_StdVW,1,16);
+- write_array_entry(a_fapi_font,a_output,"StemSnapH",FAPI_FONT_FEATURE_StemSnapH,16);
+- write_array_entry(a_fapi_font,a_output,"StemSnapV",FAPI_FONT_FEATURE_StemSnapV,16);
+-
+- write_subrs(a_fapi_font,a_output);
+- }
+-
+-static void write_main_dictionary(FAPI_font* a_fapi_font,WRF_output* a_output)
+- {
+- int i;
+- WRF_wstring(a_output,"5 dict begin\n");
+-
+- WRF_wstring(a_output,"/FontType 1 def\n");
+-
+- WRF_wstring(a_output,"/FontMatrix [");
+- for (i = 0; i < 6; i++)
+- {
+- WRF_wfloat(a_output,a_fapi_font->get_float(a_fapi_font,FAPI_FONT_FEATURE_FontMatrix,i));
+- WRF_wbyte(a_output,(byte)(i == 5 ? ']' : ' '));
+- }
+- WRF_wbyte(a_output,'\n');
+-
+- /* For now, specify standard encoding - I think GS will pass glyph indices so doesn't matter. */
+- WRF_wstring(a_output,"/Encoding StandardEncoding def\n");
+-
+- WRF_wstring(a_output,"/FontBBox {");
+- for (i = 0; i < 4; i++)
+- {
+- short x = a_fapi_font->get_word(a_fapi_font,FAPI_FONT_FEATURE_FontBBox,i);
+- WRF_wint(a_output,x);
+- WRF_wbyte(a_output,(byte)(i == 3 ? '}' : ' '));
+- }
+- WRF_wbyte(a_output,'\n');
+- WRF_wstring(a_output,"currentdict end\ncurrentfile eexec\n");
+- write_private_dictionary(a_fapi_font,a_output);
+- }
+-
+-/**
+-Write a Type 1 font in textual format and return its length in bytes.
+-If a_buffer_size is less than the total length, only a_buffer_size bytes are written, but the total
+-length is returned correctly.
+-
+-The PostScript is non-standard. The main dictionary contains no /Charstrings dictionary. This
+-is supplied to FreeType using the incremental interface, There is also no /PaintType entry. This is required
+-by PostScript but FreeType doesn't use it.
+-*/
+-long FF_serialize_type1_font(FAPI_font* a_fapi_font,unsigned char* a_buffer,long a_buffer_size)
+- {
+- WRF_output output;
+- WRF_init(&output,a_buffer,a_buffer_size);
+-
+- /* Leading comment identifying a Type 1 font. */
+- WRF_wstring(&output,"%!PS-AdobeFont-1\n");
+-
+- write_main_dictionary(a_fapi_font,&output);
+- return output.m_count;
+- }
+diff --git a/base/write_t1.h b/base/write_t1.h
+--- a/base/write_t1.h
++++ /dev/null
+@@ -1,28 +0,0 @@
+-/* Copyright (C) 2001-2006 Artifex Software, Inc.
+- All Rights Reserved.
+-
+- This software is provided AS-IS with no warranty, either express or
+- implied.
+-
+- This software is distributed under license and may not be copied, modified
+- or distributed except as expressly authorized under the terms of that
+- license. Refer to licensing information at http://www.artifex.com/
+- or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
+- San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
+-*/
+-
+-/* $Id: write_t1.h 8022 2007-06-05 22:23:38Z giles $ */
+-/*
+-Header for functions to serialize a type 1 font as PostScript code that can
+-then be passed to FreeType via the FAPI FreeType bridge.
+-Started by Graham Asher, 26th July 2002.
+-*/
+-
+-#ifndef write_t1_INCLUDED
+-#define write_t1_INCLUDED
+-
+-#include "ifapi.h"
+-
+-long FF_serialize_type1_font(FAPI_font* a_fapi_font,unsigned char* a_buffer,long a_buffer_size);
+-
+-#endif
+diff --git a/base/write_t2.c b/base/write_t2.c
+--- a/base/write_t2.c
++++ /dev/null
+@@ -1,378 +0,0 @@
+-/* Copyright (C) 2001-2006 Artifex Software, Inc.
+- All Rights Reserved.
+-
+- This software is provided AS-IS with no warranty, either express or
+- implied.
+-
+- This software is distributed under license and may not be copied, modified
+- or distributed except as expressly authorized under the terms of that
+- license. Refer to licensing information at http://www.artifex.com/
+- or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
+- San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
+-*/
+-
+-/* $Id: write_t2.c 8022 2007-06-05 22:23:38Z giles $ */
+-
+-/*
+-Functions to serialize a type 1 font so that it can then be
+-passed to FreeType via the FAPI FreeType bridge.
+-Started by Graham Asher, 9th August 2002.
+-*/
+-
+-#include "wrfont.h"
+-#include "write_t2.h"
+-#include "ghost.h"
+-#include "gxfont.h"
+-#include "gxfont1.h"
+-
+-/*
+-Public structures and functions in this file are prefixed with FF_ because they are part of
+-the FAPI FreeType implementation.
+-*/
+-
+-static void write_4_byte_int(unsigned char* a_output,long a_int)
+- {
+- a_output[0] = (unsigned char)(a_int >> 24);
+- a_output[1] = (unsigned char)(a_int >> 16);
+- a_output[2] = (unsigned char)(a_int >> 8);
+- a_output[3] = (unsigned char)(a_int & 0xFF);
+- }
+-
+-static void write_type2_int(WRF_output* a_output,long a_int)
+- {
+- if (a_int >= -107 && a_int <= 107)
+- WRF_wbyte(a_output,(unsigned char)(a_int + 139));
+- else if (a_int >= -32768 && a_int <= 32767)
+- {
+- if (a_int >= 108 && a_int <= 1131)
+- a_int += 63124;
+- else if (a_int >= -1131 && a_int <= -108)
+- a_int = -a_int + 64148;
+- else
+- WRF_wbyte(a_output,28);
+- WRF_wbyte(a_output,(unsigned char)(a_int >> 8));
+- WRF_wbyte(a_output,(unsigned char)(a_int & 0xFF));
+- }
+- else
+- {
+- unsigned char buffer[4];
+- WRF_wbyte(a_output,29);
+- write_4_byte_int(buffer,a_int);
+- WRF_wtext(a_output,buffer,4);
+- }
+- }
+-
+-static void write_type2_float(WRF_output* a_output,double a_float)
+- {
+- char buffer[32];
+- const char* p = buffer;
+- int high = true;
+- char c = 0;
+- sprintf(buffer,"%f",a_float);
+- WRF_wbyte(a_output,30);
+- for (;;)
+- {
+- char n = 0;
+- if (*p >= '0' && *p <= '9')
+- n = (char)(*p - '0');
+- else if (*p == '.')
+- n = 0xA;
+- else if (*p == 'e' || *p == 'E')
+- {
+- if (p[1] == '-')
+- {
+- p++;
+- n = 0xC;
+- }
+- else
+- n = 0xB;
+- }
+- else if (*p == '-')
+- n = 0xE;
+- else if (*p == 0)
+- n = 0xF;
+- if (high)
+- {
+- if (*p == 0)
+- WRF_wbyte(a_output,0xFF);
+- else
+- c = (char)(n << 4);
+- }
+- else
+- {
+- c |= n;
+- WRF_wbyte(a_output,c);
+- }
+-
+- if (*p == 0)
+- break;
+-
+- high = !high;
+- p++;
+- }
+- }
+-
+-static void write_header(WRF_output* a_output)
+- {
+- WRF_wtext(a_output,(const unsigned char*)"\x1\x0\x4\x1",4);
+- }
+-
+-static void write_name_index(WRF_output* a_output)
+- {
+- /* Write a dummy name of 'x'. */
+- WRF_wtext(a_output,(const unsigned char*)"\x0\x1\x1\x1\x2""x",6);
+- }
+-
+-static void write_word_entry(FAPI_font* a_fapi_font,WRF_output* a_output,int a_feature_id,
+- int a_feature_count,bool a_two_byte_op,int a_op,int a_divisor)
+- {
+- if (a_feature_count > 0)
+- {
+- int i;
+- for (i = 0; i < a_feature_count; i++)
+- {
+- /* Get the value and convert it from unsigned to signed. */
+- short x = a_fapi_font->get_word(a_fapi_font,a_feature_id,i);
+- /* Divide by the divisor to bring it back to font units. */
+- x = (short)(x / a_divisor);
+- write_type2_int(a_output,x);
+- }
+- if (a_two_byte_op)
+- WRF_wbyte(a_output,12);
+- WRF_wbyte(a_output,(unsigned char)a_op);
+- }
+- }
+-
+-static void write_delta_array_entry(FAPI_font* a_fapi_font,WRF_output* a_output,int a_feature_id,
+- bool a_two_byte_op,int a_op,int a_divisor)
+- {
+- int i;
+- /* NOTE that the feature index (a_feature_id) must be preceded by the count index for this to work. */
+- int count = a_fapi_font->get_word(a_fapi_font,a_feature_id - 1,0);
+- if (count > 0)
+- {
+- short prev_value = 0;
+- for (i = 0; i < count; i++)
+- {
+- /* Get the value and convert it from unsigned to signed. */
+- short value = a_fapi_font->get_word(a_fapi_font,a_feature_id,i);
+- /* Divide by the divisor to bring it back to font units. */
+- value = (short)(value / a_divisor);
+- write_type2_int(a_output,value - prev_value);
+- prev_value = value;
+- }
+- if (a_two_byte_op)
+- WRF_wbyte(a_output,12);
+- WRF_wbyte(a_output,(unsigned char)a_op);
+- }
+- }
+-
+-static void write_float_entry(FAPI_font* a_fapi_font,WRF_output* a_output,int a_feature_id,int a_feature_count,bool a_two_byte_op,int a_op)
+- {
+- if (a_feature_count > 0)
+- {
+- int i;
+- for (i = 0; i < a_feature_count; i++)
+- {
+- double x = a_fapi_font->get_float(a_fapi_font,a_feature_id,i);
+- write_type2_float(a_output,x);
+- }
+- if (a_two_byte_op)
+- WRF_wbyte(a_output,12);
+- WRF_wbyte(a_output,(unsigned char)a_op);
+- }
+- }
+-
+-static void write_font_dict_index(FAPI_font* a_fapi_font,WRF_output* a_output,
+- unsigned char** a_charset_offset_ptr,
+- unsigned char** a_charstrings_offset_ptr,
+- unsigned char** a_private_dict_length_ptr)
+- {
+- unsigned char* data_start = 0;
+- WRF_wtext(a_output,(const unsigned char *)"\x0\x1\x2\x0\x1\x0\x0",7); /* count = 1, offset size = 2, first offset = 1, last offset = 0 (to be filled in later). */
+- if (a_output->m_pos)
+- data_start = a_output->m_pos;
+- write_word_entry(a_fapi_font,a_output,FAPI_FONT_FEATURE_FontBBox,4,false,5,1);
+- write_float_entry(a_fapi_font,a_output,FAPI_FONT_FEATURE_FontMatrix,6,true,7);
+- write_type2_int(a_output,0); /* 0 = Standard Encoding. */
+- WRF_wbyte(a_output,16); /* 16 = opcode for 'encoding'. */
+- *a_charset_offset_ptr = a_output->m_pos;
+- WRF_wtext(a_output,(const unsigned char *)"\x1d""xxxx",5); /* placeholder for the offset to the charset, which will be a 5-byte integer. */
+- WRF_wbyte(a_output,15); /* opcode for 'charset' */
+- *a_charstrings_offset_ptr = a_output->m_pos;
+- WRF_wtext(a_output,(const unsigned char *)"\x1d""xxxx",5); /* placeholder for the offset to the Charstrings index, which will be a 5-byte integer. */
+- WRF_wbyte(a_output,17); /* opcode for 'Charstrings' */
+- *a_private_dict_length_ptr = a_output->m_pos;
+- WRF_wtext(a_output,(const unsigned char *)"\x1d""xxxx\x1d""yyyy",10); /* placeholder for size and offset of Private dictionary, which will be 5-byte integers. */
+- WRF_wbyte(a_output,18); /* opcode for 'Private' */
+- if (a_output->m_pos)
+- {
+- int last_offset = a_output->m_pos - data_start + 1;
+- data_start[-2] = (unsigned char)(last_offset >> 8);
+- data_start[-1] = (unsigned char)(last_offset & 0xFF);
+- }
+- }
+-
+-/**
+-Write the character set. Return the number of characters.
+-For the moment this is always 1. The number cannot be obtained
+-via the FAPI interface, and FreeType doesn't need to know anything more
+-than the fact that there is at least one character.
+-*/
+-static int write_charset(WRF_output* a_output,unsigned char* a_charset_offset_ptr)
+- {
+- const int characters = 1;
+- int i = 0;
+-
+- /* Write the offset to the start of the charset to the top dictionary. */
+- if (a_output->m_pos)
+- write_4_byte_int(a_charset_offset_ptr + 1,a_output->m_count);
+-
+- /*
+- Write the charset. Write one less than the number of characters,
+- because the first one is assumed to be .notdef. For the moment
+- write all the others as .notdef (SID = 0) because we don't actually
+- need the charset at the moment.
+- */
+- WRF_wbyte(a_output,0); /* format = 0 */
+- for (i = 1; i < characters; i++)
+- {
+- WRF_wbyte(a_output,0);
+- WRF_wbyte(a_output,0);
+- }
+-
+- return characters;
+- }
+-
+-/**
+-Write a set of empty charstrings. The only reason for the existence of the charstrings index is to tell
+-FreeType how many glyphs there are.
+-*/
+-static void write_charstrings_index(WRF_output* a_output,int a_characters,unsigned char* a_charstrings_offset_ptr)
+- {
+- /* Write the offset to the charstrings index to the top dictionary. */
+- if (a_output->m_pos)
+- write_4_byte_int(a_charstrings_offset_ptr + 1,a_output->m_count);
+-
+- /* Write the index. */
+- WRF_wbyte(a_output,(unsigned char)(a_characters >> 8));
+- WRF_wbyte(a_output,(unsigned char)(a_characters & 0xFF));
+- WRF_wbyte(a_output,1); /* offset size = 1. */
+- while (a_characters-- >= 0)
+- WRF_wbyte(a_output,1); /* offset = 1 */
+- }
+-
+-static void write_subrs_index(FAPI_font* a_fapi_font,WRF_output* a_output)
+- {
+- unsigned char* cur_offset = 0;
+- unsigned char* data_start = 0;
+- int i;
+- int count = a_fapi_font->get_word(a_fapi_font,FAPI_FONT_FEATURE_Subrs_count,0);
+-
+- WRF_wbyte(a_output,(unsigned char)(count >> 8));
+- WRF_wbyte(a_output,(unsigned char)(count & 0xFF));
+-
+- if (count <= 0)
+- return;
+-
+- WRF_wbyte(a_output,4); /* offset size = 4 bytes */
+- WRF_wtext(a_output,(const unsigned char *)"\x0\x0\x0\x1",4); /* first offset = 1 */
+-
+- if (a_output->m_pos)
+- cur_offset = a_output->m_pos;
+-
+- /* Write dummy bytes for the offsets at the end of each data item. */
+- for (i = 0; i < count; i++)
+- WRF_wtext(a_output,(const unsigned char *)"xxxx",4);
+-
+- if (a_output->m_pos)
+- data_start = a_output->m_pos;
+-
+- for (i = 0; i < count; i++)
+- {
+- long buffer_size = a_output->m_limit - a_output->m_count;
+- long length = a_fapi_font->get_subr(a_fapi_font,i,a_output->m_pos,(ushort)buffer_size);
+- if (a_output->m_pos)
+- WRF_wtext(a_output,a_output->m_pos,length);
+- else
+- a_output->m_count += length;
+- if (cur_offset)
+- {
+- long pos = a_output->m_pos - data_start + 1;
+- write_4_byte_int(cur_offset,pos);
+- cur_offset += 4;
+- }
+- }
+- }
+-
+-static void write_private_dict(FAPI_font* a_fapi_font,WRF_output* a_output,unsigned char* a_private_dict_length_ptr)
+- {
+- /* Write the offset to the start of the private dictionary to the top dictionary. */
+- unsigned char* start = a_output->m_pos;
+- if (a_output->m_pos)
+- write_4_byte_int(a_private_dict_length_ptr + 6,a_output->m_count);
+-
+- write_word_entry(a_fapi_font,a_output,FAPI_FONT_FEATURE_BlueFuzz,1,true,11,16);
+-
+- write_type2_float(a_output,a_fapi_font->get_long(a_fapi_font,FAPI_FONT_FEATURE_BlueScale,0) / 65536.0);
+- WRF_wbyte(a_output,12);
+- WRF_wbyte(a_output,9);
+-
+- write_word_entry(a_fapi_font,a_output,FAPI_FONT_FEATURE_BlueShift,1,true,10,16);
+- write_delta_array_entry(a_fapi_font,a_output,FAPI_FONT_FEATURE_BlueValues,false,6,16);
+- write_delta_array_entry(a_fapi_font,a_output,FAPI_FONT_FEATURE_OtherBlues,false,7,16);
+- write_delta_array_entry(a_fapi_font,a_output,FAPI_FONT_FEATURE_FamilyBlues,false,8,16);
+- write_delta_array_entry(a_fapi_font,a_output,FAPI_FONT_FEATURE_FamilyOtherBlues,false,9,16);
+- write_word_entry(a_fapi_font,a_output,FAPI_FONT_FEATURE_ForceBold,1,true,14,1);
+- write_word_entry(a_fapi_font,a_output,FAPI_FONT_FEATURE_StdHW,1,false,10,16);
+- write_word_entry(a_fapi_font,a_output,FAPI_FONT_FEATURE_StdVW,1,false,11,16);
+- write_delta_array_entry(a_fapi_font,a_output,FAPI_FONT_FEATURE_StemSnapH,true,12,16);
+- write_delta_array_entry(a_fapi_font,a_output,FAPI_FONT_FEATURE_StemSnapV,true,13,16);
+-
+- /*
+- Write the default width and the nominal width. These values are not available via
+- the FAPI interface so we have to get a pointer to the Type 1 font structure and
+- extract them directly.
+- */
+- {
+- gs_font_type1* t1 = (gs_font_type1*)a_fapi_font->client_font_data;
+- write_type2_float(a_output,fixed2float(t1->data.defaultWidthX));
+- WRF_wbyte(a_output,20);
+- write_type2_float(a_output,fixed2float(t1->data.nominalWidthX));
+- WRF_wbyte(a_output,21);
+- }
+-
+- /* Write the length in bytes of the private dictionary to the top dictionary. */
+- if (a_output->m_pos)
+- write_4_byte_int(a_private_dict_length_ptr + 1,a_output->m_pos - start);
+- }
+-
+-/**
+-Write a Type 2 font in binary format and return its length in bytes.
+-If a_buffer_size is less than the total length, only a_buffer_size bytes are written, but the total
+-length is returned correctly.
+-*/
+-long FF_serialize_type2_font(FAPI_font* a_fapi_font,unsigned char* a_buffer,long a_buffer_size)
+- {
+- unsigned char* charset_offset_ptr = NULL;
+- unsigned char* charstrings_offset_ptr = NULL;
+- unsigned char* private_dict_length_ptr = NULL;
+- int characters = 0;
+-
+- WRF_output output;
+- WRF_init(&output,a_buffer,a_buffer_size);
+-
+- write_header(&output);
+- write_name_index(&output);
+- write_font_dict_index(a_fapi_font,&output,&charset_offset_ptr,&charstrings_offset_ptr,&private_dict_length_ptr);
+-
+- /* Write an empty string index. */
+- WRF_wtext(&output,(const unsigned char *)"\x0\x0",2);
+-
+- write_subrs_index(a_fapi_font,&output);
+- characters = write_charset(&output,charset_offset_ptr);
+- write_charstrings_index(&output,characters,charstrings_offset_ptr);
+- write_private_dict(a_fapi_font,&output,private_dict_length_ptr);
+-
+- return output.m_count;
+- }
+diff --git a/base/write_t2.h b/base/write_t2.h
+--- a/base/write_t2.h
++++ /dev/null
+@@ -1,28 +0,0 @@
+-/* Copyright (C) 2001-2006 Artifex Software, Inc.
+- All Rights Reserved.
+-
+- This software is provided AS-IS with no warranty, either express or
+- implied.
+-
+- This software is distributed under license and may not be copied, modified
+- or distributed except as expressly authorized under the terms of that
+- license. Refer to licensing information at http://www.artifex.com/
+- or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
+- San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
+-*/
+-
+-/* $Id: write_t2.h 8022 2007-06-05 22:23:38Z giles $ */
+-/*
+-Header for functions to serialize a type 2 (CFF) font so that it can
+-then be passed to FreeType via the FAPI FreeType bridge.
+-Started by Graham Asher, 9th August 2002.
+-*/
+-
+-#ifndef write_t2_INCLUDED
+-#define write_t2_INCLUDED
+-
+-#include "ifapi.h"
+-
+-long FF_serialize_type2_font(FAPI_font* a_fapi_font,unsigned char* a_buffer,long a_buffer_size);
+-
+-#endif
+diff --git a/contrib/contrib.mak b/contrib/contrib.mak
+--- a/contrib/contrib.mak
++++ b/contrib/contrib.mak
+@@ -50,6 +50,7 @@ CONTRIBSRC=$(CONTRIBDIR)$(D)
+ # cdj880 HP DeskJet 880
+ # cdj890 HP DeskJet 890
+ # cdj970 HP DeskJet 970
++# cdnj500 HP DesignJet 500
+ # chp2200 HP Business Inkjet 2200
+ # dl2100 DEC DL2100
+ # dmprt dot matrix printer driver for Ghostscript (it can use
+@@ -232,6 +233,14 @@ $(GLOBJ)gdevdj9.$(OBJ) : $(CONTRIBSRC)gdevdj9.c $(PDEVH) $(math__h) $(string__h)
+ $(GLCC) $(GLO_)gdevdj9.$(OBJ) $(C_) $(CONTRIBSRC)gdevdj9.c
+
+
++### -------------- cdnj500 - HP DesignJet 500 ------------- ###
++
++### NOTE: Same as chp2200 (some PJL and CRD changes).
++
++$(DD)cdnj500.dev : $(cdeskjet8_) $(DD)page.dev
++ $(SETPDEV2) $(DD)cdnj500 $(cdeskjet8_)
++
++
+ ### -------------- chp2200 - HP Business Inkjet 2200 ------------- ###
+
+ ### NOTE: Depends on the presence of the cdj850 section.
+diff --git a/contrib/gdevcd8.c b/contrib/gdevcd8.c
+--- a/contrib/gdevcd8.c
++++ b/contrib/gdevcd8.c
+@@ -34,6 +34,7 @@
+
+ A printer driver for the HP670, HP690, HP850, HP855
+ HP870, HP890, HP1100, HP1600 and HP2200 color printers.
++ Also work with HP DesignJet 500 large-format color printer.
+ To be used with the Ghostscript printing system.
+
+ CREDITS: Much of the driver is based on ideas derived
+@@ -44,6 +45,8 @@
+
+ The support for the hp2200 was added by Siow-Kiat Tan.
+
++ The support for the dnj500 was added by Timur Maximov.
++
+ -------------------------------------------------------------------*/
+
+ /* Note: Depending on how you transfered the files,
+@@ -459,7 +462,7 @@ typedef enum {
+
+ /* Printer types */
+ typedef enum {
+- DJ670C, DJ850C, DJ880C, DJ890C, DJ1600C, HP2200C
++ DJ670C, DJ850C, DJ880C, DJ890C, DJ1600C, HP2200C, DNJ500C
+ } cdj_printer_type_t;
+
+
+@@ -492,6 +495,7 @@ static dev_proc_put_params(cdj850_put_params);
+
+ static dev_proc_print_page(cdj850_print_page);
+ static dev_proc_print_page(chp2200_print_page);
++static dev_proc_print_page(cdnj500_print_page);
+
+ /* The device descriptors */
+
+@@ -636,7 +640,7 @@ typedef struct {
+ (bpp > 8 ? 5 : 2), (bpp > 8 ? 5 : bpp > 1 ? 2 : 0),\
+ print_page, -1 /* cmyk */, correct)
+
+-/* The prn_rgb_color_device is used by the HP2200 */
++/* The prn_rgb_color_device is used by the HP2200 and DNJ500 */
+ #define prn_rgb_colour_device(dtype, procs, dev_name, x_dpi, y_dpi, bpp, print_page, correct)\
+ prn_colour_device_body(dtype, procs, dev_name,\
+ DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS, x_dpi, y_dpi, 0, 0, 0, 0,\
+@@ -683,7 +687,7 @@ typedef struct {
+ terminate_page\
+ }
+
+-/* HP2200 is a RGB printer */
++/* HP2200 and DNJ500 is a RGB printer */
+ #define chp_2200_device(procs, dev_name, x_dpi, y_dpi, bpp, print_page, correction, quality, papertype, intensities,ptype,compression,mastergamma,gammavalc,gammavalm,gammavaly,gammavalk,blackcorrect,start_raster_mode,print_non_blank_line,terminate_page)\
+ { prn_rgb_colour_device(gx_device_cdj850, procs, dev_name, x_dpi, y_dpi, bpp, print_page, correction),\
+ quality,\
+@@ -783,6 +787,14 @@ static void
+ static void
+ chp2200_terminate_page(gx_device_printer * pdev, FILE * prn_stream);
+
++/* Functions for the DNJ500C */
++static void
++ cdnj500_start_raster_mode(gx_device_printer * pdev,
++ int papersize, FILE * prn_stream);
++
++static void
++ cdnj500_terminate_page(gx_device_printer * pdev, FILE * prn_stream);
++
+
+ static const gx_device_procs cdj670_procs =
+ cmyk_colour_procs(hp_colour_open, cdj850_get_params, cdj850_put_params,
+@@ -804,7 +816,7 @@ static const gx_device_procs cdj1600_procs =
+ cmyk_colour_procs(hp_colour_open, cdj850_get_params, cdj850_put_params,
+ gdev_pcl_map_rgb_color, gdev_pcl_map_color_rgb, NULL);
+
+-/* HP2200 is a RGB printer */
++/* HP2200 and DNJ500 is a RGB printer */
+ static const gx_device_procs chp2200_procs =
+ cmyk_colour_procs(hp_colour_open, cdj850_get_params, cdj850_put_params,
+ gx_default_rgb_map_rgb_color, gx_default_rgb_map_color_rgb, NULL);
+@@ -853,6 +865,14 @@ chp_2200_device(chp2200_procs, "chp2200", 300, 300, 24, chp2200_print_page, 0,
+ chp2200_start_raster_mode, NULL /*unused*/,
+ chp2200_terminate_page);
+
++/* DNJ500 does not need color matching and halftoning parameters */
++const gx_device_cdj850 gs_cdnj500_device =
++chp_2200_device(chp2200_procs, "cdnj500", 300, 300, 24, cdnj500_print_page, 0,
++ NORMAL, PLAIN_PAPER, 0 /*unused*/, DNJ500C, 10,
++ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, /*all unused*/
++ cdnj500_start_raster_mode, NULL /*unused*/,
++ cdnj500_terminate_page);
++
+ /* Forward references */
+ static int cdj_put_param_int(gs_param_list *, gs_param_name,
+ int *, int, int, int);
+@@ -892,6 +912,11 @@ hp_colour_open(gx_device * pdev)
+ 0.25, 0.46, 0.25, 0.08
+ };
+
++ /* margins for DNJ500C */
++ static const float cdnj500[4] = {
++ 0.00, 0.00, 0.00, 0.00
++ };
++
+ const float *m = (float *)0;
+
+ /* Set up colour params if put_params has not already done so */
+@@ -1011,6 +1036,20 @@ hp_colour_open(gx_device * pdev)
+ }
+ m = (gdev_pcl_paper_size(pdev) == PAPER_SIZE_A4 ? chp2200_a4 : chp2200_letter);
+ break;
++ /* DNJ500 supports 300dpi and 600dpi with any combinations */
++ case DNJ500C:
++ cdj850->xscal = 0; /* unused */
++ cdj850->yscal = 0; /* unused */
++ cdj850->intensities = 0; /* unused */
++ if (cdj850->quality == DRAFT) {
++ gx_device_set_resolution(pdev, 300.0, 300.0);
++ } else if (cdj850->quality == NORMAL) {
++ gx_device_set_resolution(pdev, 600.0, 600.0);
++ } else { /* quality == PRESENTATION */
++ gx_device_set_resolution(pdev, 600.0, 600.0);
++ }
++ m = cdnj500;
++ break;
+ default:
+ assert(0);
+ }
+@@ -1205,6 +1244,14 @@ chp2200_terminate_page(gx_device_printer * pdev, FILE * prn_stream)
+ fputs("\033%-12345X@PJL EOJ\012\033%-12345X", prn_stream); /* Send the PJL EOJ */
+ }
+
++/* DNJ500 terminate page routine */
++static void
++cdnj500_terminate_page(gx_device_printer * pdev, FILE * prn_stream)
++{
++ fputs("\033*rC", prn_stream); /* End graphics */
++ fputs("\033%-12345X@PJL EOJ \n", prn_stream); /* Send the PJL EOJ */
++}
++
+ /* Here comes the hp850 output routine -------------------- */
+ static int
+ cdj850_print_page(gx_device_printer * pdev, FILE * prn_stream)
+@@ -1781,6 +1828,149 @@ chp2200_print_page(gx_device_printer * pdev, FILE * prn_stream)
+ return 0;
+ }
+
++#define HIBYTE(w) ((byte)(((unsigned int) (w) >> 8) & 0xFF))
++#define LOBYTE(w) ((byte)(w))
++
++/* DNJ500 output routine -------------------- */
++static int
++cdnj500_print_page(gx_device_printer * pdev, FILE * prn_stream)
++{
++ byte CRD_SeqC[] = {0x1b, 0x2a, 0x67, 0x31, 0x32, 0x57, 0x06, 0x1F, 0x00, 0x01,
++ /* Esc * |g |# of bytes |W |frmt |SP |# of cmpnts*/
++ 0x00, 0x00, 0x00, 0x00, 0x0a, 0x01, 0x20, 0x01};
++ /* |Horz Res |Vert Rez |compr|orien|bits |planes*/
++
++ /* x,y resolution for color planes, assume x=y */
++ int xres = cdj850->x_pixels_per_inch;
++ int yres = cdj850->y_pixels_per_inch;
++
++ gs_memory_t *mem = pdev->memory;
++ int width_in_pixels = pdev->width;
++ int width_in_bytes = width_in_pixels * 3; /* assume 24 bits (3 bytes per pixel) */
++ byte *lbuf = gs_alloc_bytes(mem, width_in_bytes,
++ "(input)cdnj500_print_page");
++ byte *lseedbuf = gs_alloc_bytes(mem, width_in_bytes,
++ "(seed)cdnj500_print_page");
++ /* allocate twice the input size for worse case compressed output*/
++ byte *loutputbuf = gs_alloc_bytes(mem, width_in_bytes*2,
++ "(output)cdnj500_print_page");
++
++ int lnum = 0;
++ int iEmptyRows = 0;
++ int iBlock = 0;
++ bool begin = true;
++ byte *data = lbuf;
++
++ if ((lbuf == 0) || (lseedbuf == 0) || (loutputbuf == 0))
++ return_error(gs_error_VMerror);
++
++ /* Start Raster mode */
++ (*cdj850->start_raster_mode) (pdev,
++ gdev_pcl_paper_size((gx_device *)pdev),
++ prn_stream);
++
++ /* This will configure the raster-mode */
++ CRD_SeqC[10] = HIBYTE(xres);
++ CRD_SeqC[11] = LOBYTE(xres);
++ CRD_SeqC[12] = HIBYTE(yres);
++ CRD_SeqC[13] = LOBYTE(yres);
++
++ for (lnum = 0; lnum < pdev->height; ++lnum)
++ {
++ int result = -1;
++
++ /*gdev_prn_get_bits(pdev, lnum, lbuf, &data);*/
++ result = gdev_prn_copy_scan_lines(pdev, lnum, data, width_in_bytes);
++
++ if ((result == 1) && IsScanlineDirty(data, width_in_bytes))
++ {
++ unsigned int OutputLen = 0;
++
++ /*
++ * Printers with low memory (64 MB or less) can run out of memory during decompressing
++ * the image data and will abort the job. To prevent this, restart raster command.
++ * Raghu (hpijs)
++ */
++ if (iBlock == 448) /* from DesignJet 500 winNT driver */
++ {
++ /* terminate the scanline */
++ fputs("0Y", prn_stream);
++
++ /* End graphics */
++ fputs("\033*rC", prn_stream);
++
++ /* Reset in block lines counter */
++ iBlock = 0;
++ }
++ if (iBlock == 0)
++ {
++ /* Send CRD */
++ fwrite(CRD_SeqC, sizeof(byte), sizeof(CRD_SeqC), prn_stream);
++
++ /* Raster mode */
++ fputs("\033*r1A", prn_stream);
++
++ /* start the scanline */
++ fputs("\033*b", prn_stream);
++
++ /* reset seed buffer */
++ INIT_WHITE(lseedbuf, width_in_bytes);
++ }
++ iBlock++;
++
++ if (iEmptyRows)
++ {
++ /* send vertical Y move */
++ fprintf(prn_stream, "%dy", iEmptyRows);
++
++ /* reset empty row count */
++ iEmptyRows = 0;
++
++ /* reset seed buffer */
++ INIT_WHITE(lseedbuf, width_in_bytes);
++ }
++
++ OutputLen = Mode10(width_in_pixels,
++ data,
++ lseedbuf,
++ loutputbuf);
++
++ if (OutputLen)
++ {
++ fprintf(prn_stream, "%dw", OutputLen);
++ fwrite(loutputbuf, sizeof(byte), OutputLen, prn_stream);
++
++ /* save the current scanline as the seed for the next scanline*/
++ memcpy((void*)lseedbuf, (const void*)data, width_in_bytes);
++ }
++ else
++ {
++ fputs("0w", prn_stream);
++ }
++
++ /* Content printing already started */
++ begin = false;
++ }
++ else
++ {
++ /* Skip empty area on top page */
++ if (begin == false) iEmptyRows++;
++ }
++ }
++
++ /* terminate the scanline */
++ fputs("0Y", prn_stream);
++
++ /* terminate page and eject paper */
++ (*cdj850->terminate_page) (pdev, prn_stream);
++
++ gs_free_object(mem, lbuf, "(input)cdnj500_print_page");
++ gs_free_object(mem, lseedbuf, "(seed)cdnj500_print_page");
++ gs_free_object(mem, loutputbuf, "(output)cdnj500_print_page");
++
++ return 0;
++}
++
+
+ #define odd(i) ((i & 01) != 0)
+
+@@ -3084,9 +3274,6 @@ cdj880_start_raster_mode(gx_device_printer * pdev, int paper_size,
+ return;
+ } /* end configure raster-mode */
+
+-#define HIBYTE(w) ((byte)(((unsigned int) (w) >> 8) & 0xFF))
+-#define LOBYTE(w) ((byte)(w))
+-
+ /* Start Raster mode for HP2200 */
+ static void
+ chp2200_start_raster_mode(gx_device_printer * pdev, int paper_size,
+@@ -3153,6 +3340,70 @@ chp2200_start_raster_mode(gx_device_printer * pdev, int paper_size,
+ return;
+ } /* end configure raster-mode */
+
++/* Start Raster mode for DNJ500 */
++static void
++cdnj500_start_raster_mode(gx_device_printer * pdev, int paper_size,
++ FILE * prn_stream)
++{
++ /* x,y resolution for color planes, assume x=y */
++ int xres = cdj850->x_pixels_per_inch;
++ int yres = cdj850->y_pixels_per_inch;
++ float x = pdev->width / pdev->x_pixels_per_inch * 10;
++ float y = pdev->height / pdev->y_pixels_per_inch * 10;
++
++ /* Exit from any previous language */
++ fprintf(prn_stream, "\033%%-12345X");
++
++ /* send @PJL JOB NAME before entering the language
++ * this will be matched by a @PJL EOJ after leaving the language
++ */
++ fprintf(prn_stream, "@PJL JOB NAME=\"GS %.2fx%.2f\" \n", x * 2.54, y * 2.54);
++
++ /* Color use */
++ fprintf(prn_stream, "@PJL SET RENDERMODE = COLOR \n");
++// fprintf(prn_stream, "@PJL SET RENDERMODE = TRUEBLACK \n");
++
++ /* Color correction */
++ fprintf(prn_stream, "@PJL SET COLORSPACE = SRGB \n");
++// fprintf(prn_stream, "@PJL SET COLORSPACE = DEVICERGB \n");
++
++ /* Predef qual set (TODO: need add options) */
++ if (cdj850->quality == DRAFT) {
++ fprintf(prn_stream, "@PJL SET RENDERINTENT = PERCEPTUAL \n");
++ fprintf(prn_stream, "@PJL SET RET = ON \n");
++ fprintf(prn_stream, "@PJL SET MAXDETAIL = OFF \n");
++ } else if (cdj850->quality == NORMAL) {
++ fprintf(prn_stream, "@PJL SET RENDERINTENT = PERCEPTUAL \n");
++ fprintf(prn_stream, "@PJL SET RET = ON \n");
++ fprintf(prn_stream, "@PJL SET MAXDETAIL = ON \n");
++ } else { /* quality == PRESENTATION */
++ fprintf(prn_stream, "@PJL SET RENDERINTENT = SATURATION \n");
++ fprintf(prn_stream, "@PJL SET RET = OFF \n");
++ fprintf(prn_stream, "@PJL SET MAXDETAIL = ON \n");
++ }
++
++ /* Set "remove margins between pages" (need not separated pages) */
++// fprintf(prn_stream, "@PJL SET NESTMODE = OFF \n");
++
++ /* Disable automatic cutter */
++// fprintf(prn_stream, "@PJL SET CUTTER = OFF \n");
++
++ /* Set page size (useful for standart format cutting) */
++// fprintf(prn_stream, "@PJL SET PAPERLENGTH = %d \n", (int)(y * 72.0));
++// fprintf(prn_stream, "@PJL SET PAPERWIDTH = %d \n" , (int)(x * 72.0));
++
++ /* Set the language to PCL3 enhanced */
++ fprintf(prn_stream, "@PJL ENTER LANGUAGE=PCL3GUI \n");
++
++ /* Print Quality, -1 = draft, 0 = normal, 1 = presentation */
++ fprintf(prn_stream, "\033*o%dM", cdj850->quality);
++
++ /* Unit of Measure*/
++ fprintf(prn_stream, "\033&u%dD", (int)xres);
++
++ return;
++} /* end configure raster-mode */
++
+ static int near
+ cdj_put_param_int(gs_param_list * plist, gs_param_name pname, int *pvalue,
+ int minval, int maxval, int ecode)
+diff --git a/contrib/pcl3/eprn/gdeveprn.c b/contrib/pcl3/eprn/gdeveprn.c
+--- a/contrib/pcl3/eprn/gdeveprn.c
++++ b/contrib/pcl3/eprn/gdeveprn.c
+@@ -314,7 +314,7 @@ static void print_flags(ms_MediaCode flags, const ms_Flag *user_flags)
+ if (user_flags != NULL) {
+ while (user_flags->code != ms_none) {
+ if (user_flags->code & flags) {
+- errprintf(user_flags->name);
++ errprintf("%s", user_flags->name);
+ flags &= ~user_flags->code;
+ }
+ user_flags++;
+diff --git a/contrib/pcl3/src/gdevpcl3.c b/contrib/pcl3/src/gdevpcl3.c
+--- a/contrib/pcl3/src/gdevpcl3.c
++++ b/contrib/pcl3/src/gdevpcl3.c
+@@ -1315,7 +1315,7 @@ static int pcl3_open_device(gx_device *device)
+ "%s page setup requested by the document as being for `",
+ epref, epref);
+ if (ms_find_name_from_code(buffer, sizeof(buffer),
+- dev->eprn.code, flag_description) == 0) eprintf(buffer);
++ dev->eprn.code, flag_description) == 0) eprintf1("%s", buffer);
+ else eprintf("UNKNOWN"); /* should never happen */
+ eprintf3("' (%.0f x %.0f bp).\n"
+ "%s The driver does not know how to do this in PCL.\n",
+diff --git a/cups/cups.mak b/cups/cups.mak
+--- a/cups/cups.mak
++++ b/cups/cups.mak
+@@ -33,6 +33,7 @@ cups_= $(GLOBJ)gdevcups.$(OBJ)
+ # CUPSSERVERBIN=`cups-config --serverbin`
+ # CUPSSERVERROOT=`cups-config --serverroot`
+ # CUPSDATA=`cups-config --datadir`
++# CUPSPDFTORASTER= 1 if CUPS is new enough (cups-config --version)
+
+ $(DD)cups.dev : $(CUPS_MAK) $(cups_) $(GLD)page.dev
+ $(SETPDEV2) $(DD)cups $(cups_)
+@@ -49,18 +50,24 @@ pdftoraster: $(PDFTORASTER_XE)
+ pdftoraster_=cups/pdftoraster.c
+
+ $(PDFTORASTER_XE): $(pdftoraster_)
+- $(GLCC) `cups-config --image --libs` -DBINDIR='"$(bindir)"' -DGS='"$(GS)"' -o $@ $(pdftoraster_)
++ if [ "$(CUPSPDFTORASTER)" = "1" ]; then \
++ $(GLCC) $(LDFLAGS) -DBINDIR='"$(bindir)"' -DGS='"$(GS)"' -o $@ $(pdftoraster_) `cups-config --image --libs`; \
++ fi
+
+ install: install-cups
+
+ install-cups: cups
+ -mkdir -p $(DESTDIR)$(CUPSSERVERBIN)/filter
+ $(INSTALL_PROGRAM) cups/pstoraster $(DESTDIR)$(CUPSSERVERBIN)/filter
+- $(INSTALL_PROGRAM) $(PDFTORASTER_XE) $(DESTDIR)$(CUPSSERVERBIN)/filter
++ if [ "$(CUPSPDFTORASTER)" = "1" ]; then \
++ $(INSTALL_PROGRAM) $(PDFTORASTER_XE) $(DESTDIR)$(CUPSSERVERBIN)/filter; \
++ fi
+ $(INSTALL_PROGRAM) cups/pstopxl $(DESTDIR)$(CUPSSERVERBIN)/filter
+ -mkdir -p $(DESTDIR)$(CUPSSERVERROOT)
+ $(INSTALL_DATA) cups/pstoraster.convs $(DESTDIR)$(CUPSSERVERROOT)
+- $(INSTALL_DATA) cups/pdftoraster.convs $(DESTDIR)$(CUPSSERVERROOT)
++ if [ "$(CUPSPDFTORASTER)" = "1" ]; then \
++ $(INSTALL_DATA) cups/pdftoraster.convs $(DESTDIR)$(CUPSSERVERROOT); \
++ fi
+ -mkdir -p $(DESTDIR)$(CUPSDATA)/model
+ $(INSTALL_DATA) cups/pxlcolor.ppd $(DESTDIR)$(CUPSDATA)/model
+ $(INSTALL_DATA) cups/pxlmono.ppd $(DESTDIR)$(CUPSDATA)/model
+diff --git a/cups/gdevcups.c b/cups/gdevcups.c
+--- a/cups/gdevcups.c
++++ b/cups/gdevcups.c
+@@ -252,9 +252,7 @@ private gx_device_procs cups_procs =
+ NULL, /* image_data */
+ NULL, /* end_image */
+ NULL, /* strip_tile_rectangle */
+- NULL /* strip_copy_rop */
+-#ifdef dev_t_proc_encode_color
+- ,
++ NULL, /* strip_copy_rop */
+ NULL, /* get_clipping_box */
+ NULL, /* begin_typed_image */
+ NULL, /* get_bits_rectangle */
+@@ -268,11 +266,26 @@ private gx_device_procs cups_procs =
+ NULL, /* begin_transparency_mask */
+ NULL, /* end_transparency_mask */
+ NULL, /* discard_transparency_layer */
++#ifdef dev_t_proc_encode_color
+ cups_get_color_mapping_procs,
+- NULL, /* get_color_comp_index */
++ gx_error_get_color_comp_index, /* Dummy to avoid segfault */
+ cups_encode_color,
+- cups_decode_color
++ cups_decode_color,
++#else
++ NULL, /* get_color_mapping_procs */
++ NULL, /* get_color_comp_index */
++ NULL, /* encode_color */
++ NULL, /* decode_color */
+ #endif /* dev_t_proc_encode_color */
++ NULL, /* pattern_manage */
++ NULL, /* fill_rectangle_hl_color */
++ NULL, /* include_color_space */
++ NULL, /* fill_linear_color_scanline */
++ NULL, /* fill_linear_color_trapezoid */
++ NULL, /* fill_linear_color_triangle */
++ NULL, /* update_spot_equivalent_colors */
++ NULL, /* ret_devn_params */
++ NULL /* fillpage */
+ };
+
+ #define prn_device_body_copies(dtype, procs, dname, w10, h10, xdpi, ydpi, lo, to, lm, bm, rm, tm, ncomp, depth, mg, mc, dg, dc, print_pages)\
+@@ -365,9 +378,10 @@ gx_device_cups gs_cups_device =
+ /* cupsString */
+ "", /* cupsMarkerType */
+ "", /* cupsRenderingIntent */
+- "Letter" /* cupsPageSizeName */
++ "" /* cupsPageSizeName */
+ #endif /* CUPS_RASTER_SYNCv1 */
+- }
++ },
++ 0 /* landscape */
+ };
+
+ /*
+@@ -414,7 +428,6 @@ static unsigned char cupsRevLower1[16] =
+ 0x20, 0x60, 0xa0, 0xe0, 0x30, 0x70, 0xb0, 0xf0
+ };
+
+-
+ /*
+ * Local functions...
+ */
+@@ -592,6 +605,8 @@ private void
+ cups_get_matrix(gx_device *pdev, /* I - Device info */
+ gs_matrix *pmat) /* O - Physical transform matrix */
+ {
++ ppd_attr_t *backside = NULL;
++
+ dprintf2("DEBUG2: cups_get_matrix(%p, %p)\n", pdev, pmat);
+
+ /*
+@@ -610,7 +625,12 @@ cups_get_matrix(gx_device *pdev, /* I - Device info */
+
+ if (cupsPPD)
+ {
++ backside = ppdFindAttr(cupsPPD, "cupsBackSide", NULL);
+ dprintf1("DEBUG2: cupsPPD = %p\n", cupsPPD);
++ if (backside) {
++ dprintf1("DEBUG2: cupsBackSide = %s\n", backside->value);
++ cupsPPD->flip_duplex = 0;
++ }
+ dprintf1("DEBUG2: cupsPPD->flip_duplex = %d\n", cupsPPD->flip_duplex);
+ }
+
+@@ -620,36 +640,96 @@ cups_get_matrix(gx_device *pdev, /* I - Device info */
+ * Do landscape orientation...
+ */
+
+- if (cups->header.Duplex && !cups->header.Tumble &&
+- cupsPPD && cupsPPD->flip_duplex && !(cups->page & 1))
++ if (cups->header.Duplex && cupsPPD &&
++ (cups->header.Tumble &&
++ (backside && !strcasecmp(backside->value, "Flipped"))) &&
++ !(cups->page & 1))
+ {
+ pmat->xx = 0.0;
+- pmat->xy = (float)cups->header.HWResolution[0] / 72.0;
+- pmat->yx = -(float)cups->header.HWResolution[1] / 72.0;
++ pmat->xy = (float)cups->header.HWResolution[1] / 72.0;
++ pmat->yx = (float)cups->header.HWResolution[0] / 72.0;
+ pmat->yy = 0.0;
+- pmat->tx = -(float)cups->header.HWResolution[0] * pdev->HWMargins[2] / 72.0;
++ pmat->tx = -(float)cups->header.HWResolution[0] * pdev->HWMargins[1] / 72.0;
++ pmat->ty = -(float)cups->header.HWResolution[1] * pdev->HWMargins[0] / 72.0;
++ }
++ else if (cups->header.Duplex && cupsPPD &&
++ (!cups->header.Tumble &&
++ (backside && !strcasecmp(backside->value, "Flipped"))) &&
++ !(cups->page & 1))
++ {
++ pmat->xx = 0.0;
++ pmat->xy = -(float)cups->header.HWResolution[1] / 72.0;
++ pmat->yx = (float)cups->header.HWResolution[0] / 72.0;
++ pmat->yy = 0.0;
++ pmat->tx = -(float)cups->header.HWResolution[0] * pdev->HWMargins[1] / 72.0;
++ pmat->ty = (float)cups->header.HWResolution[1] *
++ ((float)cups->header.PageSize[0] - pdev->HWMargins[2]) / 72.0;
++ }
++ else if (cups->header.Duplex && cupsPPD &&
++ ((!cups->header.Tumble &&
++ (cupsPPD->flip_duplex ||
++ (backside && !strcasecmp(backside->value, "Rotated")))) ||
++ (cups->header.Tumble &&
++ (backside && !strcasecmp(backside->value, "ManualTumble")))) &&
++ !(cups->page & 1))
++ {
++ pmat->xx = 0.0;
++ pmat->xy = -(float)cups->header.HWResolution[1] / 72.0;
++ pmat->yx = (float)cups->header.HWResolution[0] / 72.0;
++ pmat->yy = 0.0;
++ pmat->tx = -(float)cups->header.HWResolution[0] * pdev->HWMargins[1] / 72.0;
+ pmat->ty = (float)cups->header.HWResolution[1] *
+- ((float)cups->header.PageSize[0] - pdev->HWMargins[3]) / 72.0;
++ ((float)cups->header.PageSize[0] - pdev->HWMargins[2]) / 72.0;
+ }
+ else
+ {
+ pmat->xx = 0.0;
+- pmat->xy = (float)cups->header.HWResolution[0] / 72.0;
+- pmat->yx = (float)cups->header.HWResolution[1] / 72.0;
++ pmat->xy = (float)cups->header.HWResolution[1] / 72.0;
++ pmat->yx = (float)cups->header.HWResolution[0] / 72.0;
+ pmat->yy = 0.0;
+- pmat->tx = -(float)cups->header.HWResolution[0] * pdev->HWMargins[0] / 72.0;
+- pmat->ty = -(float)cups->header.HWResolution[1] * pdev->HWMargins[1] / 72.0;
++ pmat->tx = -(float)cups->header.HWResolution[0] * pdev->HWMargins[1] / 72.0;
++ pmat->ty = -(float)cups->header.HWResolution[1] * pdev->HWMargins[0] / 72.0;
+ }
+ }
+- else if (cups->header.Duplex && !cups->header.Tumble &&
+- cupsPPD && cupsPPD->flip_duplex && !(cups->page & 1))
++ else if (cups->header.Duplex && cupsPPD &&
++ (cups->header.Tumble &&
++ (backside && !strcasecmp(backside->value, "Flipped"))) &&
++ !(cups->page & 1))
++ {
++ pmat->xx = (float)cups->header.HWResolution[0] / 72.0;
++ pmat->xy = 0.0;
++ pmat->yx = 0.0;
++ pmat->yy = -(float)cups->header.HWResolution[1] / 72.0;
++ pmat->tx = -(float)cups->header.HWResolution[0] * pdev->HWMargins[0] / 72.0;
++ pmat->ty = (float)cups->header.HWResolution[1] *
++ ((float)cups->header.PageSize[1] - pdev->HWMargins[3]) / 72.0;
++ }
++ else if (cups->header.Duplex && cupsPPD &&
++ (!cups->header.Tumble &&
++ (backside && !strcasecmp(backside->value, "Flipped"))) &&
++ !(cups->page & 1))
++ {
++ pmat->xx = (float)cups->header.HWResolution[0] / 72.0;
++ pmat->xy = 0.0;
++ pmat->yx = 0.0;
++ pmat->yy = (float)cups->header.HWResolution[1] / 72.0;
++ pmat->tx = -(float)cups->header.HWResolution[0] * pdev->HWMargins[0] / 72.0;
++ pmat->ty = -(float)cups->header.HWResolution[1] * pdev->HWMargins[1] / 72.0;
++ }
++ else if (cups->header.Duplex && cupsPPD &&
++ ((!cups->header.Tumble &&
++ (cupsPPD->flip_duplex ||
++ (backside && !strcasecmp(backside->value, "Rotated")))) ||
++ (cups->header.Tumble &&
++ (backside && !strcasecmp(backside->value, "ManualTumble")))) &&
++ !(cups->page & 1))
+ {
+ pmat->xx = (float)cups->header.HWResolution[0] / 72.0;
+ pmat->xy = 0.0;
+ pmat->yx = 0.0;
+ pmat->yy = (float)cups->header.HWResolution[1] / 72.0;
+- pmat->tx = -(float)cups->header.HWResolution[0] * pdev->HWMargins[2] / 72.0;
+- pmat->ty = -(float)cups->header.HWResolution[1] * pdev->HWMargins[3] / 72.0;
++ pmat->tx = -(float)cups->header.HWResolution[0] * pdev->HWMargins[0] / 72.0;
++ pmat->ty = -(float)cups->header.HWResolution[1] * pdev->HWMargins[1] / 72.0;
+ }
+ else
+ {
+@@ -1556,14 +1636,16 @@ cups_map_rgb(gx_device *pdev,
+ private gx_color_index /* O - Color index */
+ cups_map_cmyk_color(gx_device *pdev,
+ /* I - Device info */
+- gx_color_value c, /* I - Cyan value */
+- gx_color_value m, /* I - Magenta value */
+- gx_color_value y, /* I - Yellow value */
+- gx_color_value k) /* I - Black value */
++ const gx_color_value cv[4])/* I - CMYK color values */
+ {
+ gx_color_index i; /* Temporary index */
++ gx_color_value c, m, y, k;
+ gx_color_value ic, im, iy, ik; /* Integral CMYK values */
+
++ c = cv[0];
++ m = cv[1];
++ y = cv[2];
++ k = cv[3];
+
+ #ifdef DEBUG
+ dprintf5("DEBUG2: cups_map_cmyk_color(%p, %d, %d, %d, %d)\n", pdev,
+@@ -1722,7 +1804,7 @@ cups_map_color_rgb(gx_device *pdev,/* I - Device info */
+ /* O - RGB values */
+ {
+ unsigned char c0, c1, c2, c3; /* Color index components */
+- gx_color_value k, divk; /* Black & divisor */
++ gx_color_value c, m, y, k, divk; /* Colors, Black & divisor */
+
+
+ #ifdef DEBUG
+@@ -1966,11 +2048,10 @@ cups_map_color_rgb(gx_device *pdev,/* I - Device info */
+
+ private gx_color_index /* O - Color index */
+ cups_map_rgb_color(gx_device *pdev,/* I - Device info */
+- gx_color_value r, /* I - Red value */
+- gx_color_value g, /* I - Green value */
+- gx_color_value b) /* I - Blue value */
++ const gx_color_value cv[3])/* I - RGB color values */
+ {
+ gx_color_index i; /* Temporary index */
++ gx_color_value r, g, b;
+ gx_color_value ic, im, iy, ik; /* Integral CMYK values */
+ gx_color_value mk; /* Maximum K value */
+ int tc, tm, ty; /* Temporary color values */
+@@ -1981,6 +2062,9 @@ cups_map_rgb_color(gx_device *pdev,/* I - Device info */
+ ciel, ciea, cieb;
+ /* CIE Lab colors */
+
++ r = cv[0];
++ g = cv[1];
++ b = cv[2];
+
+ #ifdef DEBUG
+ dprintf4("DEBUG2: cups_map_rgb_color(%p, %d, %d, %d)\n", pdev, r, g, b);
+@@ -2709,7 +2793,12 @@ cups_put_params(gx_device *pdev, /* I - Device info */
+ gdev_prn_space_params sp; /* Space parameter data */
+ int width, /* New width of page */
+ height; /* New height of page */
+-
++ ppd_attr_t *backside = NULL,
++ *backsiderequiresflippedmargins = NULL;
++ float swap;
++ int xflip = 0,
++ yflip = 0;
++ int found = 0;
+
+ dprintf2("DEBUG2: cups_put_params(%p, %p)\n", pdev, plist);
+
+@@ -2921,6 +3010,87 @@ cups_put_params(gx_device *pdev, /* I - Device info */
+
+ if (cupsPPD != NULL)
+ {
++ dprintf1("DEBUG2: cups->header.Duplex = %d\n", cups->header.Duplex);
++ dprintf1("DEBUG2: cups->page = %d\n", cups->page);
++ dprintf1("DEBUG2: cupsPPD = %p\n", cupsPPD);
++
++ backside = ppdFindAttr(cupsPPD, "cupsBackSide", NULL);
++ if (backside) {
++ dprintf1("DEBUG2: cupsBackSide = %s\n", backside->value);
++ cupsPPD->flip_duplex = 0;
++ }
++ dprintf1("DEBUG2: cupsPPD->flip_duplex = %d\n", cupsPPD->flip_duplex);
++
++ backsiderequiresflippedmargins =
++ ppdFindAttr(cupsPPD, "APDuplexRequiresFlippedMargin", NULL);
++ if (backsiderequiresflippedmargins)
++ dprintf1("DEBUG2: APDuplexRequiresFlippedMargin = %s\n",
++ backsiderequiresflippedmargins->value);
++
++ if (cups->header.Duplex &&
++ (cups->header.Tumble &&
++ (backside && !strcasecmp(backside->value, "Flipped"))) &&
++ !(cups->page & 1))
++ {
++ xflip = 1;
++ if (backsiderequiresflippedmargins &&
++ !strcasecmp(backsiderequiresflippedmargins->value, "False"))
++ yflip = 0;
++ else
++ yflip = 1;
++ }
++ else if (cups->header.Duplex &&
++ (!cups->header.Tumble &&
++ (backside && !strcasecmp(backside->value, "Flipped"))) &&
++ !(cups->page & 1))
++ {
++ xflip = 0;
++ if (backsiderequiresflippedmargins &&
++ !strcasecmp(backsiderequiresflippedmargins->value, "False"))
++ yflip = 1;
++ else
++ yflip = 0;
++ }
++ else if (cups->header.Duplex &&
++ ((!cups->header.Tumble &&
++ (cupsPPD->flip_duplex ||
++ (backside && !strcasecmp(backside->value, "Rotated")))) ||
++ (cups->header.Tumble &&
++ (backside && !strcasecmp(backside->value, "ManualTumble")))) &&
++ !(cups->page & 1))
++ {
++ xflip = 1;
++ if (backsiderequiresflippedmargins &&
++ !strcasecmp(backsiderequiresflippedmargins->value, "True"))
++ yflip = 0;
++ else
++ yflip = 1;
++ }
++ else
++ {
++ xflip = 0;
++ yflip = 0;
++ }
++
++#ifdef CUPS_RASTER_SYNCv1
++ /*
++ * Chack whether cupsPageSizeName has a valid value
++ */
++
++ if (strlen(cups->header.cupsPageSizeName) != 0) {
++ found = 0;
++ for (i = cupsPPD->num_sizes, size = cupsPPD->sizes;
++ i > 0;
++ i --, size ++)
++ if (strcasecmp(cups->header.cupsPageSizeName, size->name) == 0) {
++ found = 1;
++ break;
++ }
++ if (found == 0) cups->header.cupsPageSizeName[0] = '\0';
++ }
++ dprintf1("DEBUG2: cups->header.cupsPageSizeName = %s\n", cups->header.cupsPageSizeName);
++#endif
++
+ /*
+ * Find the matching page size...
+ */
+@@ -2930,6 +3100,10 @@ cups_put_params(gx_device *pdev, /* I - Device info */
+ i --, size ++)
+ if (fabs(cups->MediaSize[1] - size->length) < 5.0 &&
+ fabs(cups->MediaSize[0] - size->width) < 5.0 &&
++#ifdef CUPS_RASTER_SYNCv1
++ ((strlen(cups->header.cupsPageSizeName) == 0) ||
++ (strcasecmp(cups->header.cupsPageSizeName, size->name) == 0)) &&
++#endif
+ (!margins_set ||
+ (fabs(cups->HWMargins[0] - size->left) < 1.0 &&
+ fabs(cups->HWMargins[1] - size->bottom) < 1.0)))
+@@ -2949,6 +3123,14 @@ cups_put_params(gx_device *pdev, /* I - Device info */
+ margins[1] = size->bottom / 72.0;
+ margins[2] = (size->width - size->right) / 72.0;
+ margins[3] = (size->length - size->top) / 72.0;
++ if (xflip == 1)
++ {
++ swap = margins[0]; margins[0] = margins[2]; margins[2] = swap;
++ }
++ if (yflip == 1)
++ {
++ swap = margins[1]; margins[1] = margins[3]; margins[3] = swap;
++ }
+ }
+ else
+ {
+@@ -2962,6 +3144,10 @@ cups_put_params(gx_device *pdev, /* I - Device info */
+ i --, size ++)
+ if (fabs(cups->MediaSize[0] - size->length) < 5.0 &&
+ fabs(cups->MediaSize[1] - size->width) < 5.0 &&
++#ifdef CUPS_RASTER_SYNCv1
++ ((strlen(cups->header.cupsPageSizeName) == 0) ||
++ (strcasecmp(cups->header.cupsPageSizeName, size->name) == 0)) &&
++#endif
+ (!margins_set ||
+ (fabs(cups->HWMargins[0] - size->left) < 1.0 &&
+ fabs(cups->HWMargins[1] - size->bottom) < 1.0)))
+@@ -2979,10 +3165,18 @@ cups_put_params(gx_device *pdev, /* I - Device info */
+
+ cups->landscape = 1;
+
+- margins[0] = size->left / 72.0;
+- margins[1] = size->bottom / 72.0;
+- margins[2] = (size->width - size->right) / 72.0;
+- margins[3] = (size->length - size->top) / 72.0;
++ margins[0] = (size->length - size->top) / 72.0;
++ margins[1] = size->left / 72.0;
++ margins[2] = size->bottom / 72.0;
++ margins[3] = (size->width - size->right) / 72.0;
++ if (xflip == 1)
++ {
++ swap = margins[1]; margins[1] = margins[3]; margins[3] = swap;
++ }
++ if (yflip == 1)
++ {
++ swap = margins[0]; margins[0] = margins[2]; margins[2] = swap;
++ }
+ }
+ else
+ {
+@@ -2994,6 +3188,14 @@ cups_put_params(gx_device *pdev, /* I - Device info */
+
+ for (i = 0; i < 4; i ++)
+ margins[i] = cupsPPD->custom_margins[i] / 72.0;
++ if (xflip == 1)
++ {
++ swap = margins[0]; margins[0] = margins[2]; margins[2] = swap;
++ }
++ if (yflip == 1)
++ {
++ swap = margins[1]; margins[1] = margins[3]; margins[3] = swap;
++ }
+ }
+ }
+
+@@ -3020,9 +3222,9 @@ cups_put_params(gx_device *pdev, /* I - Device info */
+ cups->header.cupsPageSize[1] = pdev->MediaSize[1];
+
+ cups->header.cupsImagingBBox[0] = pdev->HWMargins[0];
+- cups->header.cupsImagingBBox[1] = pdev->HWMargins[3];
++ cups->header.cupsImagingBBox[1] = pdev->HWMargins[1];
+ cups->header.cupsImagingBBox[2] = pdev->MediaSize[0] - pdev->HWMargins[2];
+- cups->header.cupsImagingBBox[3] = pdev->MediaSize[1] - pdev->HWMargins[1];
++ cups->header.cupsImagingBBox[3] = pdev->MediaSize[1] - pdev->HWMargins[3];
+
+ if ((sf = cups->header.cupsBorderlessScalingFactor) < 1.0)
+ sf = 1.0;
+@@ -3034,11 +3236,11 @@ cups_put_params(gx_device *pdev, /* I - Device info */
+ cups->header.PageSize[1] = pdev->MediaSize[1] * sf;
+
+ cups->header.ImagingBoundingBox[0] = pdev->HWMargins[0] * sf;
+- cups->header.ImagingBoundingBox[1] = pdev->HWMargins[3] * sf;
++ cups->header.ImagingBoundingBox[1] = pdev->HWMargins[1] * sf;
+ cups->header.ImagingBoundingBox[2] = (pdev->MediaSize[0] -
+ pdev->HWMargins[2]) * sf;
+ cups->header.ImagingBoundingBox[3] = (pdev->MediaSize[1] -
+- pdev->HWMargins[1]) * sf;
++ pdev->HWMargins[3]) * sf;
+ #else
+ cups->header.Margins[0] = pdev->HWMargins[0];
+ cups->header.Margins[1] = pdev->HWMargins[1];
+@@ -3065,9 +3267,9 @@ cups_put_params(gx_device *pdev, /* I - Device info */
+
+ if (cups->landscape)
+ {
+- width = (pdev->MediaSize[1] - pdev->HWMargins[0] - pdev->HWMargins[2]) *
++ width = (pdev->MediaSize[1] - pdev->HWMargins[1] - pdev->HWMargins[3]) *
+ pdev->HWResolution[0] / 72.0f + 0.499f;
+- height = (pdev->MediaSize[0] - pdev->HWMargins[1] - pdev->HWMargins[3]) *
++ height = (pdev->MediaSize[0] - pdev->HWMargins[0] - pdev->HWMargins[2]) *
+ pdev->HWResolution[1] / 72.0f + 0.499f;
+ }
+ else
+@@ -3568,10 +3770,21 @@ cups_print_chunked(gx_device_printer *pdev,
+ *dstptr; /* Pointer to bits */
+ int count; /* Count for loop */
+ int flip; /* Flip scanline? */
++ ppd_attr_t *backside = NULL;
+
+-
+- if (cups->header.Duplex && !cups->header.Tumble &&
+- cupsPPD && cupsPPD->flip_duplex && !(cups->page & 1))
++ if (cupsPPD) {
++ backside = ppdFindAttr(cupsPPD, "cupsBackSide", NULL);
++ if (backside)
++ cupsPPD->flip_duplex = 0;
++ }
++ if (cups->header.Duplex && cupsPPD &&
++ ((!cups->header.Tumble &&
++ (cupsPPD->flip_duplex ||
++ (backside && !strcasecmp(backside->value, "Rotated")))) ||
++ (cups->header.Tumble &&
++ (backside && (!strcasecmp(backside->value, "Flipped") ||
++ !strcasecmp(backside->value, "ManualTumble"))))) &&
++ !(cups->page & 1))
+ flip = 1;
+ else
+ flip = 0;
+@@ -3751,10 +3964,21 @@ cups_print_banded(gx_device_printer *pdev,
+ unsigned char *cptr, *mptr, *yptr, /* Pointer to components */
+ *kptr, *lcptr, *lmptr; /* ... */
+ int flip; /* Flip scanline? */
++ ppd_attr_t *backside = NULL;
+
+-
+- if (cups->header.Duplex && !cups->header.Tumble &&
+- cupsPPD && cupsPPD->flip_duplex && !(cups->page & 1))
++ if (cupsPPD) {
++ backside = ppdFindAttr(cupsPPD, "cupsBackSide", NULL);
++ if (backside)
++ cupsPPD->flip_duplex = 0;
++ }
++ if (cups->header.Duplex && cupsPPD &&
++ ((!cups->header.Tumble &&
++ (cupsPPD->flip_duplex ||
++ (backside && !strcasecmp(backside->value, "Rotated")))) ||
++ (cups->header.Tumble &&
++ (backside && (!strcasecmp(backside->value, "Flipped") ||
++ !strcasecmp(backside->value, "ManualTumble"))))) &&
++ !(cups->page & 1))
+ flip = 1;
+ else
+ flip = 0;
+diff --git a/cups/pstoraster.in b/cups/pstoraster.in
+--- a/cups/pstoraster.in
++++ b/cups/pstoraster.in
+@@ -52,10 +52,10 @@ else
+ fi
+
+ echo INFO: Starting GPL Ghostscript `$bindir/@GS@ --version`... 1>&2
+-echo DEBUG: Running $bindir/@GS@ $gsopts -sOUTPUTFILE="%stdout" -c"$profile" "$ifile" 1>&2
++echo DEBUG: Running $bindir/@GS@ $gsopts -sOUTPUTFILE="%stdout" -c "$profile" -f "$ifile" 1>&2
+
+ # Now run Ghostscript...
+-exec $bindir/@GS@ $gsopts -sOUTPUTFILE="%stdout" -c"$profile" "$ifile"
++exec $bindir/@GS@ $gsopts -sOUTPUTFILE="%stdout" -c "$profile" -f "$ifile"
+
+ #
+ # End of "$Id$".
+diff --git a/doc/C-style.htm b/doc/C-style.htm
+--- a/doc/C-style.htm
++++ b/doc/C-style.htm
+@@ -661,8 +661,7 @@ indent&nbsp;-bad&nbsp;-nbap&nbsp;-nsob&nbsp;-br&nbsp;-ce&nbsp;-cli4&nbsp;-npcs&n
+ <p>
+ does a 98% accurate job of producing our preferred style. Unfortunately,
+ there are bugs in all versions of GNU <code>indent</code>, requiring
+-both pre- and post-processing of the code. The <code>gsindent</code>
+-script in the Ghostscript fileset contains the necessary workarounds.
++both pre- and post-processing of the code.
+
+ <p>
+ Put indentation points every 4 spaces, with 8 spaces = 1 tab stop.
+diff --git a/doc/Develop.htm b/doc/Develop.htm
+--- a/doc/Develop.htm
++++ b/doc/Develop.htm
+@@ -4666,8 +4666,8 @@ Macintosh files:
+ <a href="../base/macos_carbon_d_pre.h">base/macos_carbon_d_pre.h</a>,
+ <a href="../base/macos_classic_d_pre.h">base/macos_classic_d_pre.h</a>,
+
+-<a href="../base/dmmain.c">base/dmmain.c</a>,
+-<a href="../base/dmmain.r">base/dmmain.r</a>.
++<a href="../psi/dmmain.c">psi/dmmain.c</a>,
++<a href="../psi/dmmain.r">psi/dmmain.r</a>.
+
+ <dt>
+ VMS files:
+diff --git a/doc/Language.htm b/doc/Language.htm
+--- a/doc/Language.htm
++++ b/doc/Language.htm
+@@ -1227,10 +1227,25 @@ at the beginning of the procedure.
+
+ <dl>
+ <dt><code>&lt;string&gt; &lt;boolean&gt; .setdebug -</code>
+-<dd>If the Ghostscript interpreter was built with the <code>DEBUG</code>
+-flag set, sets or resets any subset of the debugging flags normally
+-controlled by <code>-Z</code> in the command line. Has no effect
+-otherwise.
++<dd>Sets or clears any subset of the debugging flags included in
++<code>&lt;string&gt;</code> based on the value of
++<code>&lt;boolean&gt;</code>. These correspond to the debug
++flags set by <code>-Z</code> on the command line and enable
++debug and tracing output from various internal modules.
++
++<p>Note that most tracing output is only produced if the Ghostscript
++interpreter was built with the <code>DEBUG</code> preprocessor
++symbol defined.
++
++<p>The <code>zsetdebug()</code> C function, which implements this
++operator, is a useful breakpoint for debuggers.
++Inserting '<code>() true .setdebug</code>' in the interpreted code will
++trigger a breakpoint at that location without side effects. The
++current flag state is available in C as the <code>gs_debug[]</code>
++array, indexed by character value. The <code>zsetdebug</code> function will
++be entered, and <code>gs_debug[]</code> updated, whether or not Ghostscript
++is built with the <code>DEBUG</code> preprocessor symbol defined, so this
++is useful even with release builds.
+ </dl>
+
+ <dl>
+diff --git a/doc/Make.htm b/doc/Make.htm
+--- a/doc/Make.htm
++++ b/doc/Make.htm
+@@ -112,7 +112,7 @@
+ <li><a href="#QNX">QNX</a>
+ </ul>
+ <li><a href="#UFST_build">How to build Ghostscript with UFST</a>
+-<li><a href="#FT_build">How to build Ghostscript with Free Type</a>
++<li><a href="#FT_build">How to build Ghostscript with FreeType</a>
+ </ul></blockquote>
+
+ <!-- [1.2 end table of contents] =========================================== -->
+@@ -662,31 +662,38 @@ memory requirements, and may be essential if you are planning on putting
+ Ghostscript into ROM.
+
+ <p>
+-To compile the initialization files (<code>lib/gs_init.ps</code>, etc.)
+-into the executable, change the <code>0</code> to a <b><tt>1</tt></b> in
+-the line
++By default, most top level make files now default to compiling the initialization
++files (<code>lib/gs_init.ps</code>, etc.) into the executable. To disable this,
++change the <code>1</code> to a <b><tt>0</tt></b> in the line
+
+ <blockquote><code>
+-COMPILE_INITS=0
++COMPILE_INITS=1
+ </code></blockquote>
+
+ <p>
+-Compiled initialization includes the default font map.
+-It is used only if Ghostscript cannot find or open the default font
+-map file at run time.
++Files are now compiled into the executable as a %rom% file system that can
++be searched, opened, etc. as with the normal (%os%) file system. The data
++is (mostly) compressed. The set of files built into the %rom% file system
++is specified in the <code>psi/psromfs.mak</code> file. Refer to the file
++<code>base/mkromfs.c</code> for a description of the parameters that
++control source and destination pathnames, file enumeration exclusion,
++compression, etc.
+
+ <p>
+-To compile fonts into the executable, see <a
+-href="Fonts.htm#Precompiling">Precompiling fonts</a>.
++While fonts normally are compiled into the executable using <code>mkromfs</code>
++(above) from the Resource/Font/ directory, it is possible to compile Type 1 fonts
++into the executable using an older method that converts Type 1 fonts into C code.
++See <a href="Fonts.htm#Precompiling">Precompiling fonts</a>.
+
+ <p>
+-To compile threshold-array halftones into the executable, see the "Compiled
+-halftone" section of <code>int.mak</code> for a sample makefile fragment,
+-<code>genht.c</code> for the syntax of halftone data files, and
+-<code>lib/ht_ccsto.ps</code> for a sample data file. Note that even
+-though the data files use PostScript syntax, compiled halftones do not
+-require the PostScript interpreter and may be used with the graphics library
+-alone.
++Similarly, Halftone resources can be compiled into the executable using
++<code>mkromfs</code>, but also threshold-array halftones can be compiled
++into the executable. See the "Compiled halftone" section of <code>int.mak</code>
++for a sample makefile fragment, <code>genht.c</code> for the syntax of
++halftone data files, and <code>lib/ht_ccsto.ps</code> for a sample data file.
++ Note that even though the data files use PostScript syntax, compiled halftones
++do not require the PostScript interpreter and may be used with the graphics
++library alone.
+
+ <h4><a name="GNU_readline"></a>GNU readline</h4>
+
+@@ -2764,46 +2771,64 @@ msvc32.mak sets the other options automatically.
+
+ <p>
+
+-<h2><a name="FT_build"></a>How to build Ghostscript with Free Type</h2>
++<h2><a name="FT_build"></a>How to build Ghostscript with FreeType</h2>
+
+ <p>
+-<em>Note: This section is only for users who wish to use Ghostscript with Free Type font renderer.
++<em>Note: This section is only for users who wish to use Ghostscript with FreeType font renderer.
+ Other users please skip this section.
+ </em>
+
+ <p>
+-Ghostscript sources do not include Free Type sources. You need to obtain them from Free Type group.
+-Ghostscript includes only some source modules that provide a bridge to Free Type.
++Ghostscript sources do not include a copy of the FreeType sources.
++You need to obtain them from the
++<a href="http://freetype.org/">FreeType Project</a>.
++Ghostscript includes only some source modules that provide a
++bridge to FreeType.
+
+ <p>
+-Ghostscript makefiles do not include any script for building Free Type libraries.
+-Refer to Free Type manual how to build them. Free Type object libraries must be built
+-before building Ghostscript with the Free Type bridge.
++Ghostscript makefiles do not include any script for building FreeType
++libraries. Refer to FreeType manual how to build them. FreeType object
++libraries must be built before building Ghostscript with the FreeType
++bridge.
+
+ <p>
+-To build Ghostscript with Free Type, specify additional options for "make":
++Note that Ghostscript requires FreeType to be built with the optional
++incremental font support. Check that FT_CONFIG_OPTION_INCREMENTAL is
++defined in the headers for your FreeType build.
++<p>
++To build Ghostscript with FreeType, specify these additional options for
++"make" either on the command line, or in the top-level makefile:
+
+ <dl>
+ <dt><code>FT_BRIDGE=1</code>
+-<dd>forces the Free Type bridge to build.
++<dd>Enables the FreeType bridge.
+
+-<dt><code>FT_ROOT=path</code>
+-<dd>specifies the path to Free Type root directory or folder.
++<dt><code>FT_CFLAGS=<i>options</i></code>
++<dd>Specifies C compiler include directives and options for FreeType
++library. Refer to the FreeType manual for information about them.
+
+-<dt><code>FT_CFLAGS=options</code>
+-<dd>specifies C compiler options for Free Type library. Refer to Free Type manual for information about them.
+-
+-<dt><code>FT_LIB_EXT=extension</code>
+-<dd>sets the file name extension for object libraries. You must use the appropriate one for your platform and linker.
++<dt><code>FT_LIBS=<i>link-options</i></code>
++<dd>Specifies the path the the object library or options for linking
++with FreeType. You must use the appropriate one for your platform and
++linker.
+ </dl>
+
+ <p>An example for Unix/GCC :
+ <blockquote>
+-<tt>FT_BRIDGE=1 FT_ROOT=../FreeType FT_CFLAGS=-DGCCx86 FT_LIB_EXT=.a</tt>
++<tt>make FT_BRIDGE=1 FT_CFLAGS=-Ifreetype/include FT_LIBS=freetype/objs/libfreetype.a</tt>
++</blockquote>
++or
++<blockquote>
++<tt>make FT_BRIDGE=1 FT_CFLAGS=`pkg-config --cflags freetype2` FT_LIBS=`pkg-config --libs freetype2`</tt>
+ </blockquote>
+
+-<p>For Windows/MSVC you need only specify FT_ROOT.
+-msvc32.mak sets the other options automatically.
++<p>For Windows/MSVC you need only specify FT_ROOT to be the path to the
++top level source directory of your FreeType build.
++msvc32.mak sets the other options automatically. However,
++because the freetype project files for MSVC embed the version and build
++type in the library filename, it may be necessary to override the default
++library name, by passing for example FT_LIB=freetype241MT. FT_LIB only
++has an effect on the MSVC build, unlike FT_LIBS which is used by all the builds.
+
+ <p>
+
+diff --git a/doc/News.htm b/doc/News.htm
+--- a/doc/News.htm
++++ b/doc/News.htm
+@@ -55,35 +55,10 @@ overview</a>.
+
+ <!-- [2.0 begin contents] ================================================== -->
+
+-<h3><a name="Version8.64"></a>Version 8.64 (2009-02-03)</h3>
++<h3><a name="Version8.64"></a>Version 8.65 (SVN PRE-RELEASE)</h3>
+
+ <p>
+-This is the fifth scheduled release in the stable Ghostscript 8.6x
+-series.
+-
+-<p>
+-Approximately 100 bugs have been fixed since the 8.63 release.
+-
+-<p>
+-Of particular note in this release are improvements to overprint and
+-spot color support in documents with transparency, improvements to PDF
+-and PS output, proper handling of PDF-specific text rendering modes and
+-support for reading AES-encrypted PDF documents.
+-
+-<p>
+-Also improved is handling of CJK text, especially in vertical writing
+-modes, memory footprint processing some files at high resolution and
+-support for using the system's default paper size on unix.
+-
+-<p>
+-The interpreter's handling of color spaces has been moved from
+-PostScript code to C.
+-
+-<p>
+-A number of the included printer drivers and cups wrappers have been
+-updated to support a PDF-based workflow. Also fixed are several
+-long-standing bugs in the pcl drivers with respect to duplex, resolution
+-and paper tray selection.
++This is an unreleased development snapshot.
+
+ <p> The following <a href="http://bugs.ghostscript.com/">bugs</a> were
+ open at the time of the last release: <blockquote>
+@@ -556,17 +531,7 @@ open at the time of the last release: <blockquote>
+ <h3><a name="8.64_Incompatible_changes"></a>Incompatible changes</h3>
+
+ <p>
+-In this release the C source files have been split into two new
+-directories. Interpreter source files are now in <tt>psi</tt> and the
+-graphics library and output devices are now in <tt>base</tt>. Previously
+-everything was in <tt>src</tt>. This may cause problems with existing
+-references in external build files or when applying patches generated
+-against an older version.
+-
+-<p>
+-The compiled in font set in Resource/Fonts has been updated to the
+-version from the 8.11 release. This is the same set which was
+-recommended prior to the 8.63.
++No incompatible changes have been recorded.
+
+ <h3><a name="8.64_changelog"></a>Changelog</h3>
+
+@@ -593,7 +558,7 @@ or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
+ San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
+
+ <p>
+-<small>Ghostscript version 8.64, 3 February 2009
++<small>Ghostscript version 8.64, 4 February 2009
+
+ <!-- [3.0 end visible trailer] ============================================= -->
+
+diff --git a/doc/Ps2pdf.htm b/doc/Ps2pdf.htm
+--- a/doc/Ps2pdf.htm
++++ b/doc/Ps2pdf.htm
+@@ -59,12 +59,7 @@ to Portable Document Format (PDF) files.
+ <p>
+ <code>ps2pdf</code> is implemented as a very small command script (batch
+ file) that invokes Ghostscript, selecting a special "output device" called
+-<code>pdfwrite</code>. In order to use <b><tt>ps2pdf</tt></b>, the
+-<code>pdfwrite</code> device must be included in the makefile when
+-Ghostscript was compiled; see the <a
+-href="Make.htm#Features_and_devices">documentation on building
+-Ghostscript</a> for details: this is currently the case on all platforms, in
+-Ghostscript as we distribute it.
++<code>pdfwrite</code>.
+
+ <hr>
+
+@@ -245,6 +240,14 @@ wide variety of uses, possibly at the expense of a larger output file.
+
+ </ul>
+
++<dt><code>-dNumCopies</code>
++<dd>When present, causes pdfwrite to use the #copies or /NumCopies entry in the page
++device dictionary to duplicate each page in the output PDF file as many times as
++the 'copies' value. This is intended for use by workflow applications like CUPS
++and should not be used for generating general purpose PDF files. In particular any
++pdfmark operations which rely on page numbers, such as Link or Outline annotations
++will not work correctly with this flag.
++
+ </dl>
+
+ <p>
+diff --git a/doc/Ps2ps2.htm b/doc/Ps2ps2.htm
+--- a/doc/Ps2ps2.htm
++++ b/doc/Ps2ps2.htm
+@@ -193,12 +193,17 @@ especially for fonts which Ghostscript had converted into bitmaps
+ See <a href="#Options">Options</a> about the <code>PageSize</code> entry of the <b><tt>Policies</tt></b>
+ dictionary while the conversion step).
+ Default value : <em>false</em>.
+-Must be <em>false</em> if <code>-dSetPageSize=true</code>.
++Must be <em>false</em> if <code>-dSetPageSize=true</code> or <code>-dCenterPages=true</code>.
++
++<dt><code>-dCenterPages=</code><em>boolean</em>.
++<dd>The printer will center the page image on the selected media. Compatible with <code>-dRotatePages=true</code>, which may rotate the image on the media if it fits better, and then center it.
++Default value : <em>false</em>.
++Must be <em>false</em> if <code>-dSetPageSize=true</code> or <code>-dFitPages=true</code>.
+
+ <dt><code>-dSetPageSize=</code><em>boolean</em>.
+ <dd>The printer will try to set page size from the job.
+ Only use with printers which can handle random <em>PageSize</em>.
+-Must be <em>false</em> if <code>-dRotatePages=true</code> or <b><tt>-dFitPages=true</tt></b>.
++Must be <em>false</em> if <code>-dRotatePages=true</code>, <code>-dCenterPages=true</code> or <code>-dFitPages=true</code>.
+
+ </dl>
+
+diff --git a/doc/Psfiles.htm b/doc/Psfiles.htm
+--- a/doc/Psfiles.htm
++++ b/doc/Psfiles.htm
+@@ -833,6 +833,11 @@ information.
+ </dl>
+
+ <dl>
++<dt><a href="../lib/viewrgb.ps"><tt>viewrgb.ps</tt></a>
++<dd>A utility for displaying files created by -sDEVICE=bitrgb.
++</dl>
++
++<dl>
+ <dt><a href="../lib/waterfal.ps"><tt>waterfal.ps</tt></a>
+ <dd>A utility to print a "waterfall" of fonts at different sizes.
+ </dl>
+diff --git a/doc/Use.htm b/doc/Use.htm
+--- a/doc/Use.htm
++++ b/doc/Use.htm
+@@ -521,9 +521,6 @@ program by using the special file name '<code>-</code>' which is interpreted as
+ </blockquote>
+
+ <p>
+-<em>Ghostscript cannot read PDF files from standard input or a pipe because the PDF language inherently requires random access to the file. Thus '<tt>-</tt>' only works with PostScript documents.</em>
+-
+-<p>
+ When Ghostscript finishes reading from the pipe, it quits rather than
+ going into interactive mode. Because of this, options and files after the '<tt>-</tt>' in the command line will be ignored.
+
+@@ -834,9 +831,12 @@ switches</a> in the command line, if any;
+ <li>The directories specified by the <code>GS_LIB</code>
+ environment variable, if any;
+
+-<li>The directories specified by the
+-<code>GS_LIB_DEFAULT</code> macro (if any) in the makefile
+-when this executable was built.
++<li>If built with COMPILE_INITS=1 (currently the default build) the files in the
++<code>%rom%Resource/Init/</code> and <code>%rom%lib/</code> file system built
++into the executable ;
++
++<li>The directories specified by the <code>GS_LIB_DEFAULT</code> macro
++(if any) in the makefile when this executable was built.
+ </ol>
+
+ <p>
+@@ -856,11 +856,9 @@ in the current directory first by using the
+
+ <p>
+ Note that Ghostscript does not use this file searching algorithm for the
+-<code>run</code> or <b><tt>file</tt></b>
+-operators: for these operators, it simply opens the file with the name
+-given. To run a file using the searching algorithm, use
+-<code>runlibfile</code> instead of
+-<code>run</code>.
++<b><tt>run</tt></b> or <b><tt>file</tt></b> operators: for these operators, it
++simply opens the file with the name given. To run a file using the searching
++algorithm, use <code>runlibfile</code> instead of <code>run</code>.
+
+ <h3><a name="PS_resources"></a>Finding PostScript Level 2 resources</h3>
+
+@@ -877,12 +875,16 @@ specifies an absolute path. The user may set it as explained in
+
+ <p>
+ If the user doesn't set the system parameter <code>GenericResourceDir</code>,
+-Ghostscript creates a default value for it with
+-attaching the string <code>../Resource</code>
+-to directory paths explained in
+-<a href="#Finding_files">How Ghostscript finds files</a>,
+-except the current directory.
+-The first successful combination is used.
++or use the <code>-sGenericResourceDir=</code> command line option, Ghostscript
++creates a default value for it by looking on the directory paths explained in
++<a href="#Finding_files">How Ghostscript finds files</a>, excluding the current directory.
++The first path with <code>Resource</code> in it is used, including any prefix
++up to the path separator character following the string <code>Resource</code>.
++For example, when COMPILE_INITS=1 (the current default build), if the first path
++is <code>%rom%Resource/Init/</code>, then the <code>GenericResourceDir</code>
++systemparam will be set to <code>%rom%Resource/</code> by default.
++
++
+
+ <p>
+ If the value of the system parameter <code>GenericResourceDir</code>
+@@ -2509,9 +2511,8 @@ another program is "driving" Ghostscript.
+ <dl>
+ <dt><code>-dNOPROMPT</code>
+ <dd>Disables the prompt printed by Ghostscript when it expects interactive
+-input, as well as the end-of-page prompt (<code>-dNOPAGEPROMPT</code>);
+-also disables the implicit <code>flushpage</code> that normally occurs
+-each time Ghostscript asks for more input. This allows piping input
++input, as well as the end-of-page prompt (<code>-dNOPAGEPROMPT</code>).
++This allows piping input
+ directly into Ghostscript, as long as the data doesn't refer to
+ <code>currentfile</code>.
+ </dl>
+@@ -3244,6 +3245,8 @@ guide to international paper sizes can be found at
+ <td>&nbsp;<td align=right>8.5<td>&nbsp;<td align=right>13.0<td>&nbsp;<td align=right>216<td>&nbsp;<td align=right>330<td>&nbsp;<td align=right>612<td>&nbsp;<td align=right>936<td>&nbsp;<td>European foolscap
+ <tr> <td>halfletter
+ <td>&nbsp;<td align=right>5.5<td>&nbsp;<td align=right>8.5<td>&nbsp;<td align=right>140<td>&nbsp;<td align=right>216<td>&nbsp;<td align=right>396<td>&nbsp;<td align=right>612<td>&nbsp;<td>&nbsp;
++<tr> <td>hagaki
++ <td>&nbsp;<td align=right>3.9<td>&nbsp;<td align=right>5.8<td>&nbsp;<td align=right>100<td>&nbsp;<td align=right>148<td>&nbsp;<td align=right>283<td>&nbsp;<td align=right>420<td>&nbsp;<td>Japanese postcard
+ </table>
+
+ <p>
+diff --git a/lib/cat.ps b/lib/cat.ps
+new file mode 100644
+--- /dev/null
++++ b/lib/cat.ps
+@@ -0,0 +1,74 @@
++% Copyright (C) 1996-2003 Artifex Software, Inc. All rights reserved.
++%
++% This software is provided AS-IS with no warranty, either express or
++% implied.
++%
++% This software is distributed under license and may not be copied,
++% modified or distributed except as expressly authorized under the terms
++% of the license contained in the file LICENSE in this distribution.
++%
++% For more information about licensing, please refer to
++% http://www.ghostscript.com/licensing/. For information on
++% commercial licensing, go to http://www.artifex.com/licensing/ or
++% contact Artifex Software, Inc., 101 Lucas Valley Road #110,
++% San Rafael, CA 94903, U.S.A., +1(415)492-9861.
++%
++% $Id: cat.ps 8331 2008-02-05 11:07:00Z kens $
++%
++% Appends one file to another. Primarily used to overcome the
++% 'copy' limitation of Windows command shell for ps2epsi
++%
++% the files to be appended are given by the environament
++% variables %infile% and %outfile%. %infile% is appended to
++% %outfile%
++%
++
++/datastring 1024 string def
++
++{
++ (outfile) getenv
++ {
++ /outfilename exch def
++ (infile) getenv
++ {
++ /infilename exch def
++
++ infilename status
++ {
++ pop pop pop pop outfilename status
++ {
++ pop pop pop pop
++ infilename (r) file /infile exch def
++ outfilename (a+) file /outfile exch def
++ {
++ infile datastring readstring
++ {
++ outfile exch writestring
++ }
++ {
++ dup length 0 gt
++ {outfile exch writestring} {pop} ifelse
++ exit
++ } ifelse
++ } loop
++ infile closefile
++ outfile closefile
++ }
++ {
++ (Failed to find file ) print outfilename ==
++ } ifelse
++ }
++ {
++ (Failed to find file ) print infilename ==
++ } ifelse
++ }
++ {
++ (Couldn't find %infile% environment variable) ==
++ } ifelse
++ }
++ {
++ (Couldn't find %outfile% environment variable) ==
++ }
++ ifelse
++} bind
++exec
+diff --git a/lib/ps2ai.ps b/lib/ps2ai.ps
+--- a/lib/ps2ai.ps
++++ b/lib/ps2ai.ps
+@@ -25,7 +25,7 @@
+ % redefine it. This can be used by other programs to overwrite
+ % some settings from externally
+ %
+-/cdef { 1 index where { pop pop pop } { def } ifelse } def
++/cdef { 1 index where { pop pop pop } { def } ifelse } bind def
+ %
+ %xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ %
+@@ -131,18 +131,19 @@
+ % Nothing of Interest below here
+ %xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ matrix identmatrix setmatrix % make ctm [1 0 0 1 0 0]
++/bdef {bind def} bind def
+ /oldgsave {} def /oldgrestore {} def
+ /initgraphics {} def /initmatrix {} def
+ % undefine PPD PageSizes to be more printer independant
+ /letter {} def /legal {} def /a4 {} def /b5 {} def /lettersmall {} def
+-/setpagedevice { pop } def % for level 2 PPD PageSizes
++/setpagedevice { pop } bdef % for level 2 PPD PageSizes
+ /Courier findfont 12 scalefont setfont % handle no setfont
+ /initclip {0 0 moveto 0 792 lineto 612 792 lineto 612 0 lineto closepath
+- clip newpath } def
+-/xdef {exch def} def
+-/trx {transform exch} def
+-/cbdef {cvx bind def} def
+-/jltz {dup abs 0.0001 lt {pop 0} if} def % get rid of scientific notation bug
++ clip newpath } bdef
++/xdef {exch def} bdef
++/trx {transform exch} bdef
++/cbdef {cvx bind def} bdef
++/jltz {dup abs 0.0001 lt {pop 0} if} bdef % get rid of scientific notation bug
+ /clstate false def % closepath state
+ /dpth false def % destroy path (ie newpath)
+ /fclp false def % first paint after clip
+@@ -165,7 +166,7 @@ matrix identmatrix setmatrix % make ctm [1 0 0 1 0 0]
+ /green {1 mag blk ccomp sub} def
+ /blue {1 yel blk ccomp sub} def
+ red green blue setrgbcolor
+- } def
++ } bdef
+ } ifelse
+ /currentcmykcolor where {pop}
+ {/currentcmykcolor {
+@@ -180,7 +181,7 @@ matrix identmatrix setmatrix % make ctm [1 0 0 1 0 0]
+ /yel rawY blk sub def
+ /blk blk def
+ cyan mag yel blk
+- } def
++ } bdef
+ } ifelse
+ % If using Mac Ghostscript
+ jMacGS {
+@@ -193,10 +194,9 @@ jout {joutput (w) file /joutput xdef} if
+ %
+ % Output
+ %
+-jout {/jp { joutput exch writestring } bind def }{/jp {print}bind def} ifelse
+-/jpnum {jltz ( ) jp =string cvs jp } bind def
+-/jpmat { dup /jarry exch def length 1 sub /j_num exch def
+- (\[) jp 0 1 j_num {jarry exch get jpnum} for (\]) jp } def
++jout {/jp { joutput exch writestring } bdef }{/jp {print} bdef} ifelse
++/jpnum {jltz ( ) jp =string cvs jp } bdef
++/jpmat { (\[) jp { jpnum } forall (\]) jp } bdef
+ %
+ % Stack to Paths converters
+ %
+@@ -207,20 +207,20 @@ jout {/jp { joutput exch writestring } bind def }{/jp {print}bind def} ifelse
+ spth 1 eq {clstate {(s\n) jp }{(S\n) jp } ifelse} if
+ spth 2 eq {clstate {(f\n) jp }{(F\n) jp } ifelse} if
+ } if
+-} def
++} bdef
+ /jpm {
+ ckpnt
+ /dpth true def
+- transform 2 copy /yst xdef /xst xdef exch jpnum jpnum ( m\n) jp } bind def
+-/jpl { trx jpnum jpnum ( l\n) jp } bind def
++ transform 2 copy /yst xdef /xst xdef exch jpnum jpnum ( m\n) jp } bdef
++/jpl { trx jpnum jpnum ( l\n) jp } bdef
+ /jpc { 6 4 roll trx jpnum jpnum 4 2 roll trx jpnum jpnum trx
+- jpnum jpnum ( c\n) jp } bind def
+-/jpp {xst jpnum yst jpnum ( l\n) jp /clstate true def} def
++ jpnum jpnum ( c\n) jp } bdef
++/jpp {xst jpnum yst jpnum ( l\n) jp /clstate true def} bdef
+ /cntpaths { % count paths on stack
+ oldgsave
+ {pop pop /jnump jnump 1 add def} {pop pop} {6 {pop} repeat}{} pathforall
+ oldgrestore
+-} def
++} bdef
+ /ppforall {
+ cntpaths % find out how many paths are on the stack
+ jnump 1 gt { (*u\n) jp } if
+@@ -229,34 +229,34 @@ jout {/jp { joutput exch writestring } bind def }{/jp {print}bind def} ifelse
+ jnump 1 gt { (*U\n) jp } if
+ /jnump 0 def /clstate false def /dpth false def /fclp false def
+ oldnewpath
+-} bind def
++} bdef
+ %
+ % Painting Operators
+ %
+ /oldnewpath [/newpath load] cbdef
+-/newpath { (\n) jp /spth 0 def ppforall} def
+-/stroke { (\n) jp /spth 1 def ppforall } def
+-/fill {(\n) jp /spth 2 def ppforall } def
+-/eofill {(1 D\n) jp fill (0 D\n) jp} def
++/newpath { (\n) jp /spth 0 def ppforall} bdef
++/stroke { (\n) jp /spth 1 def ppforall } bdef
++/fill {(\n) jp /spth 2 def ppforall } bdef
++/eofill {(1 D\n) jp fill (0 D\n) jp} bdef
+ /clip {clarry gcnt get {(Q\nq\n) jp}{(q\n) jp} ifelse
+- /fclp true def clarry gcnt true put} def
+-/eoclip {(1 D\n) jp clip (0 D\n) jp} def
++ /fclp true def clarry gcnt true put} bdef
++/eoclip {(1 D\n) jp clip (0 D\n) jp} bdef
+ %
+ % Text Operators
+ %
+ /oldshow [/show load] cbdef
+-/curpt {stringwidth pop jx add jy} def
++/curpt {stringwidth pop jx add jy} bdef
+ /jNN {dup 0 eq {pop oldgsave currentfont /FontMatrix get setmatrix kscl
+ oldgrestore} if
+-} def
++} bdef
+ /curftmatrix {
+ currentfont /FontMatrix get dup 0 get jNN abs /norm exch def
+ dup 0 get norm div exch dup
+ 1 get norm div exch dup 2 get norm div exch dup 3 get norm div exch dup
+ 4 get exch 5 get 6 array astore matrix currentmatrix matrix concatmatrix
+-} def
++} bdef
+ % AI does not support negitive font sizes
+-/curftsize {currentfont /FontMatrix get 0 get jNN abs 1000 mul} def
++/curftsize {currentfont /FontMatrix get 0 get jNN abs 1000 mul} bdef
+ /hstr (X) def
+ /vbar (|) 0 get def /undsc (_) 0 get def
+ /ftnamefix { % handle font names with |,_ (previously encoded)
+@@ -268,10 +268,10 @@ jstr cvs
+ } ifelse
+ } ifelse
+ } forall flush
+-} bind def
+-%/curftname {currentfont /FontName get ftnamefix}def
++} bdef
++%/curftname {currentfont /FontName get ftnamefix} bdef
+ /curftname { currentfont /FontName known {currentfont /FontName get}
+- { (Times-Roman)} ifelse ftnamefix } def
++ { (Times-Roman)} ifelse ftnamefix } bdef
+ /lftpar (\() 0 get def
+ /rhtpar (\)) 0 get def
+ /bckslsh (\\) 0 get def
+@@ -286,11 +286,11 @@ jstr cvs
+ } ifelse
+ } ifelse
+ } forall (\)) jp flush
+-} bind def
++} bdef
+ % AI 3 text format pieces
+ jtxt3 {
+ /j3txt { j3ftxt {(0 Ts 100 Tz 0 Tt 0 TA 0 0 5 TC 100 100 200 TW 0 0 0 Ti\n) jp
+- (0 Ta 0 Tq 0 0 TI 0 Tc 0 Tw\n) jp} if } def
++ (0 Ta 0 Tq 0 0 TI 0 Tc 0 Tw\n) jp} if } bdef
+ /show {oldgsave (0 To\n) jp
+ currentpoint 2 copy /jy exch def /jx exch def translate
+ curftmatrix /jitm exch def
+@@ -299,8 +299,8 @@ jtxt3 {
+ (0) jp j_ax curftsize div 100 mul jpnum ( 100 TC\n) jp % percent(?)
+ dup curpt moveto mark exch handft ( Tx\n) jp (TO\n) jp /j3ftxt false def
+ cleartomark currentpoint oldgrestore moveto
+-} def
+-/ashow {exch pop exch /j_ax exch def show /j_ax {0} def } def
++} bdef
++/ashow {exch pop exch /j_ax exch def show /j_ax {0} def } bdef
+ }
+ {
+ /show {oldgsave (u\n) jp currentpoint 2 copy /jy exch def /jx exch def translate
+@@ -308,19 +308,19 @@ jtxt3 {
+ curftsize dup jpnum jpnum ( 0 0 z\n) jp
+ curftmatrix jpmat ( e\n) jp
+ dup curpt moveto mark exch handft ( t T U\n) jp
+- cleartomark currentpoint oldgrestore moveto} def
++ cleartomark currentpoint oldgrestore moveto} bdef
+ /ashow {oldgsave (u\n) jp currentpoint translate (\/) jp curftname jstr cvs jp
+ curftsize dup jpnum jpnum exch kscl mul jpnum ( 0 z\n) jp
+ curftmatrix jpmat ( e\n) jp dup curpt moveto mark exch handft
+- ( t T U\n) jp cleartomark currentpoint oldgrestore moveto} def
++ ( t T U\n) jp cleartomark currentpoint oldgrestore moveto} bdef
+ } ifelse
+-/widthshow { show pop pop pop} def
+-/awidthshow {ashow pop pop pop} def
+-/kshow {show pop} def
+-%/show {true charpath fill} bind def % get outline of charactor
++/widthshow { show pop pop pop} bdef
++/awidthshow {ashow pop pop pop} bdef
++/kshow {show pop} bdef
++%/show {true charpath fill} bdef % get outline of charactor
+ joutln {/show { true charpath currentpoint
+- /jy exch def /jx exch def fill jx jy moveto} bind def} if
+-%/show {oldshow} def % do nothing different
++ /jy exch def /jx exch def fill jx jy moveto} bdef} if
++%/show {oldshow} bdef % do nothing different
+ %
+ % Color Operators
+ %
+@@ -328,11 +328,11 @@ joutln {/show { true charpath currentpoint
+ /setcmykcolor {oldsetcmykcolor
+ currentcmykcolor 4 -1 roll jpnum 3 -1 roll jpnum 2 -1 roll jpnum jpnum ( k\n) jp
+ currentcmykcolor 4 -1 roll jpnum 3 -1 roll jpnum 2 -1 roll jpnum jpnum ( K\n) jp
+- } def
++ } bdef
+ /oldsetgray [/setgray load] cbdef
+-/setgray {0 0 0 4 -1 roll 1 exch sub setcmykcolor} def
++/setgray {0 0 0 4 -1 roll 1 exch sub setcmykcolor} bdef
+ /oldsethsbcolor [/sethsbcolor load] cbdef
+-/sethsbcolor {oldsethsbcolor currentcmykcolor setcmykcolor} def
++/sethsbcolor {oldsethsbcolor currentcmykcolor setcmykcolor} bdef
+ /oldsetrgbcolor [/setrgbcolor load] cbdef
+ /setrgbcolor {oldsetrgbcolor currentrgbcolor /bval xdef /gval xdef /rval xdef
+ /rawC 1 rval sub def /rawM 1 gval sub def /rawY 1 bval sub def
+@@ -344,24 +344,24 @@ currentcmykcolor 4 -1 roll jpnum 3 -1 roll jpnum 2 -1 roll jpnum jpnum ( K\n) jp
+ /mag rawM blk sub def
+ /yel rawY blk sub def
+ /blk blk def
+- cyan mag yel blk setcmykcolor } def
++ cyan mag yel blk setcmykcolor } bdef
+ %
+ % State Operators
+ %
+ /oldsetlinewidth [/setlinewidth load] cbdef
+ /setlinewidth {kscl abs mul jltz oldsetlinewidth
+- currentlinewidth jpnum ( w\n) jp } def
++ currentlinewidth jpnum ( w\n) jp } bdef
+ /oldsetlinecap [/setlinecap load] cbdef
+-/setlinecap {dup oldsetlinecap jpnum ( J\n) jp} def
++/setlinecap {dup oldsetlinecap jpnum ( J\n) jp} bdef
+ /oldsetlinejoin [/setlinejoin load] cbdef
+-/setlinejoin {dup oldsetlinejoin jpnum ( j\n) jp} def
++/setlinejoin {dup oldsetlinejoin jpnum ( j\n) jp} bdef
+ /oldsetmiterlimit [/setmiterlimit load] cbdef
+-/setmiterlimit {dup oldsetmiterlimit jpnum ( M\n) jp}def
++/setmiterlimit {dup oldsetmiterlimit jpnum ( M\n) jp}bdef
+ /oldsetdash [/setdash load] cbdef
+ /setdash {exch [ exch {kscl abs mul} forall ] exch kscl abs mul oldsetdash
+- currentdash exch jpmat jpnum ( d\n) jp } def
++ currentdash exch jpmat jpnum ( d\n) jp } bdef
+ /oldsetflat [/setflat load] cbdef
+-/setflat {dup oldsetflat jpnum ( i\n) jp } def
++/setflat {dup oldsetflat jpnum ( i\n) jp } bdef
+ %
+ % More State Operators
+ %
+@@ -372,12 +372,12 @@ currentcmykcolor 4 -1 roll jpnum 3 -1 roll jpnum 2 -1 roll jpnum jpnum ( K\n) jp
+ 1 0 moveto currentpoint transform
+ dup mul exch dup mul add sqrt 10000 mul round 10000 div
+ oldgrestore
+-} def
++} bdef
+ /currentstate {currentcmykcolor setcmykcolor
+ currentflat jpnum ( i) jp currentlinecap jpnum ( J) jp
+ currentlinejoin jpnum ( j) jp currentlinewidth jpnum ( w) jp
+ currentmiterlimit jpnum ( M ) jp currentdash exch jpmat jpnum ( d\n) jp
+-} def
++} bdef
+ /jdifG {
+ currentcmykcolor /jok xdef /joy xdef /jom xdef /joc xdef
+ currentflat /jof xdef currentlinecap /jolc xdef currentlinejoin /jolj xdef
+@@ -394,18 +394,18 @@ currentcmykcolor 4 -1 roll jpnum 3 -1 roll jpnum 2 -1 roll jpnum jpnum ( K\n) jp
+ false joad {true exit} forall {pop pop true}{false} ifelse
+ false jnad {true exit} forall {pop pop true}{false} ifelse ne
+ jood jnod ne 10 {or} repeat {currentstate} if
+-} def
++} bdef
+ /oldgsave [/gsave load] cbdef
+-/gsave {oldgsave /gcnt gcnt 1 add def } def % clarry gcnt false put} def
+-% (%%Note:gsave ) jp gcnt jpnum (\n) jp} def
++/gsave {oldgsave /gcnt gcnt 1 add def } bdef % clarry gcnt false put} bdef
++% (%%Note:gsave ) jp gcnt jpnum (\n) jp} bdef
+ /oldgrestore [/grestore load] cbdef
+ /grestore {dpth {newpath} if clarry gcnt get {(Q\n) jp clarry gcnt false put} if
+- jdifG /gcnt gcnt 1 sub def } def
+-% oldgrestore currentstate } def
+-% (%%Note:grestore ) jp gcnt 1 add jpnum (\n) jp} def
++ jdifG /gcnt gcnt 1 sub def } bdef
++% oldgrestore currentstate } bdef
++% (%%Note:grestore ) jp gcnt 1 add jpnum (\n) jp} bdef
+ /oldrestore [/restore load] cbdef
+ % a kludgy way of saving the clipping path status information
+-/restore {clarry aload pop 11 -1 roll oldrestore clarry astore pop} def
++/restore {clarry aload pop 11 -1 roll oldrestore clarry astore pop} bdef
+ /showpage { 0 1 9 {clarry exch get {(Q\n) jp} if } for
+ (%%Note: If Error, make sure there are matched pairs of 'q's and 'Q's\n) jp
+ (%%Note: in the file. Add 'Q's before '%%Trailer' until equal\n) jp
+@@ -424,7 +424,7 @@ currentcmykcolor 4 -1 roll jpnum 3 -1 roll jpnum 2 -1 roll jpnum jpnum ( K\n) jp
+ (Adobe_packedarray /terminate get exec\n) jp
+ } ifelse
+ ( showpage\n%EOF\n%%EndDocument\n) jp
+- jout {joutput closefile} if jMacGS not {quit} if /j3ftxt true def } def
++ jout {joutput closefile} if jMacGS not {quit} if /j3ftxt true def } bdef
+ %
+ % Error handling
+ %
+@@ -432,13 +432,13 @@ errordict begin
+ % Attempt to handle the error caused by bitmap fonts (TeX,Windows.ps,etc)
+ % this is a big-time kludge
+ jbiterr {
+- /undefined {pop pop (Times-Roman)} def
+- /typecheck {pop pop} def
++ /undefined {pop pop (Times-Roman)} bdef
++ /typecheck {pop pop} bdef
+ } if
+ jerr {
+ /handleerror {
+ (%%Note: ps2ai error, aborting rest of conversion\n) jp showpage
+- } def
++ } bdef
+ } if
+ end
+ %
+@@ -447,22 +447,22 @@ end
+ /jmacimp { % stroked line instead of thin filled boxes
+ /@a { 3 -1 roll 2 div dup 3 -1 roll add exch 3 -1 roll add exch moveto
+ 3 -1 roll 2 div dup 3 -1 roll add exch 3 -1 roll exch sub exch lineto
+- abs setlinewidth stroke pop pop} def
++ abs setlinewidth stroke pop pop} bdef
+ /@b { 3 -1 roll 2 div dup 3 -1 roll add exch 3 -1 roll add exch moveto
+ pop
+ 3 -1 roll 2 div dup 3 -1 roll add exch 3 -1 roll add exch lineto
+- abs setlinewidth stroke} def
+- /endp {showpage pm restore} def % because the restore stops clean up
+-} def
++ abs setlinewidth stroke} bdef
++ /endp {showpage pm restore} bdef % because the restore stops clean up
++} bdef
+ %
+ % Handle (some) PS Level 2
+ %
+ /rectstroke { 4 2 roll moveto 1 index 0 rlineto 0 exch rlineto neg 0 rlineto
+- closepath stroke} def
++ closepath stroke} bdef
+ /rectfill { 4 2 roll moveto 1 index 0 rlineto 0 exch rlineto neg 0 rlineto
+- fill } def
++ fill } bdef
+ /rectclip { 4 2 roll moveto 1 index 0 rlineto 0 exch rlineto neg 0 rlineto
+- closepath clip newpath jMacfix {jmacimp} if } def
++ closepath clip newpath jMacfix {jmacimp} if } bdef
+ %
+ % Add a header prolog to the output file so it is still view/print-able
+ %
+diff --git a/lib/ps2epsi b/lib/ps2epsi
+--- a/lib/ps2epsi
++++ b/lib/ps2epsi
+@@ -50,6 +50,8 @@ else
+ outfile=$2
+ fi
+
++"$GS_EXECUTABLE" -q -dBATCH -dNOPAUSE -dSAFER -dDELAYSAFER -sDEVICE=bbox -sOutputFile=/dev/null "${infile}" 2>${outfile}
++
+ ls -l "${infile}" |
+ awk 'F==1 {
+ cd="%%CreationDate: " $6 " " $7 " " $8;
+@@ -70,12 +72,27 @@ awk 'F==1 {
+ print "/epsicreator (" c "\\n) def";
+ print "/epsicrdt (" cd "\\n) def";
+ print "/epsifor (" f "\\n) def";
+- print "end";
+ exit(0);
+ }
+ ' U="$USERNAME$LOGNAME" F=1 - F=2 "${infile}" >"$tmpfile"
+
+-"$GS_EXECUTABLE" -q -sPAPERSIZE=a0 -dNOPAUSE -dSAFER -dDELAYSAFER -r72 -sDEVICE=bit -sOutputFile=/dev/null "$tmpfile" ps2epsi.ps "$tmpfile" <"${infile}" 1>&2
++ls -l "${outfile}" |
++awk 'F==1 {
++ b="%%BoundingBox: 0 0 0 0\\n";
++ }
++ /^%%BoundingBox:/ {b=$0; next;}
++ /^%%HiResBoundingBox:/ {
++ hb=$0;
++ print "ps2edict where {pop} {/ps2edict 30 dict def} ifelse";
++ print "ps2edict begin";
++ print "/BBoxString (" b "\\n) def";
++ print "/HiresBBoxString (" hb "\\n) def";
++ print "end";
++ exit(0);
++ }
++ ' F=1 - F=2 "${outfile}" >>"$tmpfile"
++
++"$GS_EXECUTABLE" -q -dNOPAUSE -dSAFER -dDELAYSAFER -r72 -sDEVICE=bit -sOutputFile=/dev/null "$tmpfile" ps2epsi.ps "$tmpfile" <"${infile}" 1>&2
+ rm -f "$tmpfile"
+ rm -rf "$tmpdir"
+
+diff --git a/lib/ps2epsi.bat b/lib/ps2epsi.bat
+--- a/lib/ps2epsi.bat
++++ b/lib/ps2epsi.bat
+@@ -8,6 +8,10 @@ call gssetgs.bat
+ set infile=%1
+ set outfile=%2
+
++rem First we need to determine the bounding box. ps2epsi.ps below will pick
++rem the result up from %outfile%
++%GSC% -q -dNOPAUSE -dBATCH -dSAFER -dDELAYSAFER -sDEVICE=bbox -sOutputFile=NUL %infile% 2> %outfile%
++
+ rem Ghostscript uses %outfile% to define the output file
+ %GSC% -q -dNOPAUSE -dSAFER -dDELAYSAFER -sDEVICE=bit -sOutputFile=NUL ps2epsi.ps < %infile%
+
+@@ -18,7 +22,9 @@ echo /InitDictCount countdictstack def gsave save mark newpath >> %outfile%
+ echo userdict /setpagedevice /pop load put >> %outfile%
+
+ rem Append the original onto the preview header
+-copy %outfile% + %infile%
++rem cat.ps uses the %infile% and %outfile% environment variables for the filenames
++%GSC% -q -dNOPAUSE -dBATCH -dSAFER -dDELAYSAFER -sDEVICE=bit -sOutputFile=NUL cat.ps
++
+
+ echo %%%%EndDocument >> %outfile%
+ echo countdictstack InitDictCount sub { end } repeat >> %outfile%
+diff --git a/lib/ps2epsi.cmd b/lib/ps2epsi.cmd
+--- a/lib/ps2epsi.cmd
++++ b/lib/ps2epsi.cmd
+@@ -11,6 +11,10 @@ if %2/==/ goto usage
+ set infile=%1
+ set outfile=%2
+
++rem First we need to determine the bounding box. ps2epsi.ps below will pick
++rem the result up from %outfile%
++gsos2 -q -dNOPAUSE -dBATCH -dSAFER -dDELAYSAFER -sDEVICE=bbox -sOutputFile=NUL %infile% 2> %outfile%
++
+ rem Ghostscript uses %outfile% to define the output file
+ gsos2 -q -dNOPAUSE -dSAFER -dDELAYSAFER -sDEVICE=bit -sOutputFile=NUL ps2epsi.ps < %infile%
+
+diff --git a/lib/ps2epsi.ps b/lib/ps2epsi.ps
+--- a/lib/ps2epsi.ps
++++ b/lib/ps2epsi.ps
+@@ -1,3 +1,4 @@
++
+ % Copyright (C) 1990, 2000 Aladdin Enterprises. All rights reserved.
+ %
+ % This software is provided AS-IS with no warranty, either express or
+@@ -53,7 +54,13 @@ ps2edict begin
+
+ % The main procedure
+ /ps2epsi
+- { % Open the file
++ {
++ % bbox written to outfile by bbox device from ps2epsi command file
++ outfile (r) file /epsifile exch def
++ /BBoxString epsifile 256 string readline pop def
++ /HiresBBoxString epsifile 256 string readline pop def
++ epsifile closefile
++ % Open the file
+ outfile (w) file /epsifile exch def
+ % Get the device parameters
+ currentdevice getdeviceprops .dicttomark
+@@ -160,18 +167,9 @@ ps2edict begin
+ dup rm gt
+ % If the new index is greater, we save index and element
+ { /rm exch def } { pop } ifelse
+- } {
+- pop
+- } ifelse
++ } if
+ } for
+
+- % Calculate the bounding box values.
+- % Note that these must be corrected to produce closed-open intervals.
+- /llx lm def
+- /lly devheight bm sub 1 sub def
+- /urx rm 1 add def
+- /ury devheight tm sub def
+-
+ % Write out the magic string and bounding box information
+ epsifile (%!PS-Adobe-2.0 EPSF-1.2\n) writestring
+ /epsititle where { pop epsifile epsititle writestring } if
+@@ -195,11 +193,8 @@ ps2edict begin
+ epsifile (\n) writestring
+ epsifile flushfile
+
+- epsifile (%%BoundingBox: ) writestring
+- epsifile llx write==only epsifile ( ) writestring
+- epsifile lly write==only epsifile ( ) writestring
+- epsifile urx write==only epsifile ( ) writestring
+- epsifile ury write==
++ epsifile BBoxString writestring epsifile (\r) writestring
++ epsifile HiresBBoxString writestring epsifile (\r) writestring
+
+ % Define character and bit widths for the output line buffer:
+ /cwidth rm lm sub 1 add def
+diff --git a/lib/viewrgb.ps b/lib/viewrgb.ps
+new file mode 100755
+--- /dev/null
++++ b/lib/viewrgb.ps
+@@ -0,0 +1,146 @@
++% Copyright (C) 2009 Artifex Software, Inc. All rights reserved.
++%
++% This software is provided AS-IS with no warranty, either express or
++% implied.
++%
++% This software is distributed under license and may not be copied, modified
++% or distributed except as expressly authorized under the terms of that
++% license. Refer to licensing information at http://www.artifex.com/
++% or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
++% San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
++
++% $Id$
++
++% viewrgb.ps
++% Display a raw RGB file created by -sDEVICE=bitrgb.
++% If SCALE is defined, maps input pixels to output pixels with that scale;
++% if SCALE is undefined, scales the image to fit the page.
++% If BITS is defined, it is the number of bits per sample (1,2,8,12).
++% NB: BITS=1 (corresponding to -dGrayValues=16) is not supported.
++% if BITS is undefined, its default value is 1.
++
++/viewrgb { % <filename> <width> viewrgb -
++ 20 dict begin
++ /w exch def
++ /fname exch def
++ /bpc /BITS where { pop BITS } { 1 } ifelse def
++ /f fname (r) file def
++ mark fname status pop pop pop /flen exch def cleartomark
++ /h flen
++ w [ 0 4 8 0 0 0 0 0 24 ] bpc get
++ dup 0 eq {
++ (*** -dBITS=) print bpc =print ( is not supported. ***) = flush
++ quit
++ } if
++ mul 7 add 8 idiv idiv def
++ QUIET not { (Dimensions: ) print [w h] == flush } if
++ % Set up scaling.
++ /SCALE where {
++ pop
++ % Map pixels SCALE-for-1. Assume orthogonal transformation.
++ SCALE 1 0 dtransform add abs div
++ SCALE 0 1 dtransform add abs div
++ } {
++ % Scale the image (uniformly) to fit the page.
++ clippath pathbbox pop pop translate
++ pathbbox 3 -1 roll sub h div
++ 3 1 roll exch sub w div .min dup
++ } ifelse scale
++ bpc 1 eq {
++ [ /Indexed /DeviceRGB 15 <
++ 000000
++ 0000FF
++ 00FF00
++ 00FFFF
++ FF0000
++ FF00FF
++ FFFF00
++ FFFFFF
++ 000000
++ 0000FF
++ 00FF00
++ 00FFFF
++ FF0000
++ FF00FF
++ FFFF00
++ FFFFFF
++ >
++ ] setcolorspace
++ /BPC 4 def % change to 4 bit indexed
++ } {
++ bpc 2 eq {
++ [ /Indexed /DeviceRGB 255 <
++ 000000 000055 0000AA 0000FF
++ 005500 005555 0055AA 0055FF
++ 00AA00 00AA55 00AAAA 00AAFF
++ 00FF00 00FF55 00FFAA 00FFFF
++ 550000 550055 5500AA 5500FF
++ 555500 555555 5555AA 5555FF
++ 55AA00 55AA55 55AAAA 55AAFF
++ 55FF00 55FF55 55FFAA 55FFFF
++ AA0000 AA0055 AA00AA AA00FF
++ AA5500 AA5555 AA55AA AA55FF
++ AAAA00 AAAA55 AAAAAA AAAAFF
++ AAFF00 AAFF55 AAFFAA AAFFFF
++ FF0000 FF0055 FF00AA FF00FF
++ FF5500 FF5555 FF55AA FF55FF
++ FFAA00 FFAA55 FFAAAA FFAAFF
++ FFFF00 FFFF55 FFFFAA FFFFFF
++
++ 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000
++ 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000
++ 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000
++ 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000
++
++ 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000
++ 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000
++ 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000
++ 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000
++
++ 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000
++ 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000
++ 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000
++ 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000
++
++ 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000
++ 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000
++ 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000
++ 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000
++ >
++ ] setcolorspace
++ /BPC 8 def % change to 4 bit indexed
++ } {
++ /DeviceRGB setcolorspace
++ /BPC bpc def
++ }
++ ifelse
++ }
++ ifelse
++ << /ImageType 1
++ /Width w
++ /Height h
++ /BitsPerComponent BPC
++ /ImageMatrix [1 0 0 -1 0 h]
++ /DataSource f
++ /MultipleDataSources false
++ bpc 4 lt { /Decode [ 0 [ 0 15 255 ] bpc get ] } { /Decode [ 0 1 0 1 0 1 ] } ifelse
++ >> image
++ showpage
++ f closefile
++ end
++} bind def
++
++% If the program was invoked from the command line, run it now.
++[ shellarguments {
++ counttomark 2 eq {
++ cvi viewrgb
++ } {
++ cleartomark
++ (\nUsage: gs -- viewrgb.ps filename.rgb width\n) print
++ ( e.g.: gs -- viewrgb.ps my.rgb 2550\n) print flush
++ ( -dSCALE=### sets specific scaling \(default = 1.0\)) = flush
++ ( -dBITS=# sets the BitsPerComponent \(1, 2, 8, 12] \(default = 1\)) = flush
++ } ifelse
++} {
++ pop
++} ifelse
+diff --git a/psi/dmmain.c b/psi/dmmain.c
+new file mode 100644
+--- /dev/null
++++ b/psi/dmmain.c
+@@ -0,0 +1,997 @@
++/* Copyright (C) 2001-2006 Artifex Software, Inc.
++ All Rights Reserved.
++
++ This software is provided AS-IS with no warranty, either express or
++ implied.
++
++ This software is distributed under license and may not be copied, modified
++ or distributed except as expressly authorized under the terms of that
++ license. Refer to licensing information at http://www.artifex.com/
++ or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
++ San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
++*/
++/* $Id$ */
++
++/* Ghostscript shlib example wrapper for Macintosh (Classic/Carbon) contributed
++ by Nigel Hathaway. Uses the Metrowerks CodeWarrior SIOUX command-line library.
++ */
++
++#if __ide_target("Ghostscript PPC (Debug)") || __ide_target("Ghostscript PPC (Release)")
++#define TARGET_API_MAC_CARBON 0
++#define TARGET_API_MAC_OS8 1
++#define ACCESSOR_CALLS_ARE_FUNCTIONS 1
++#endif
++
++#include <Carbon.h>
++
++#include <stdlib.h>
++#include <string.h>
++#include <stdio.h>
++#include <console.h>
++#include <SIOUX.h>
++#include <SIOUXGlobals.h>
++#include <SIOUXMenus.h>
++
++#include "gscdefs.h"
++#define GSREVISION gs_revision
++#include "ierrors.h"
++#include "iapi.h"
++
++#if DEBUG
++#include "vdtrace.h"
++#endif
++
++#include "gdevdsp.h"
++
++#define kScrollBarWidth 15
++#define MAX_ARGS 25
++
++Boolean gRunningOnX = false;
++Boolean gDone;
++ControlActionUPP gActionFunctionScrollUPP;
++
++const char start_string[] = "systemdict /start get exec\n";
++void *instance;
++
++const unsigned int display_format = DISPLAY_COLORS_RGB | DISPLAY_UNUSED_FIRST |
++ DISPLAY_DEPTH_8 | DISPLAY_BIGENDIAN |
++ DISPLAY_TOPFIRST;
++typedef struct IMAGE_S IMAGE;
++struct IMAGE_S {
++ void *handle;
++ void *device;
++ WindowRef windowRef;
++ ControlRef scrollbarVertRef;
++ ControlRef scrollbarHorizRef;
++ PixMapHandle pixmapHdl;
++ UInt64 update_time;
++ int update_interval;
++ IMAGE *next;
++};
++
++IMAGE *first_image;
++
++static IMAGE *image_find(void *handle, void *device);
++
++static int GSDLLCALL gsdll_stdin(void *instance, char *buf, int len);
++static int GSDLLCALL gsdll_stdout(void *instance, const char *str, int len);
++static int GSDLLCALL gsdll_stderr(void *instance, const char *str, int len);
++static int GSDLLCALL gsdll_poll(void *handle);
++
++static int display_open(void *handle, void *device);
++static int display_preclose(void *handle, void *device);
++static int display_close(void *handle, void *device);
++static int display_presize(void *handle, void *device, int width, int height,
++ int raster, unsigned int format);
++static int display_size(void *handle, void *device, int width, int height,
++ int raster, unsigned int format, unsigned char *pimage);
++static int display_sync(void *handle, void *device);
++static int display_page(void *handle, void *device, int copies, int flush);
++static int display_update(void *handle, void *device,
++ int x, int y, int w, int h);
++
++static size_t get_input(void *ptr, size_t size);
++
++static void window_create (IMAGE *img);
++static void window_invalidate (WindowRef windowRef);
++static void window_adjust_scrollbars (WindowRef windowRef);
++
++void main (void);
++OSErr quitAppEventHandler (AppleEvent *,AppleEvent *,SInt32);
++void doEvents (EventRecord *);
++void doMouseDown (EventRecord *);
++void doUpdate (EventRecord *);
++void doUpdateWindow (EventRecord *);
++void doOSEvent (EventRecord *);
++void doInContent (EventRecord *,WindowRef);
++pascal void actionFunctionScroll (ControlRef,ControlPartCode);
++
++/*********************************************************************/
++/* stdio functions */
++static int GSDLLCALL
++gsdll_stdin(void *instance, char *buf, int len)
++{
++ if (isatty(fileno(stdin)))
++ return get_input(buf, len);
++ else
++ return fread(buf, 1, len, stdin);
++}
++
++static int GSDLLCALL
++gsdll_stdout(void *instance, const char *str, int len)
++{
++ int n = fwrite(str, 1, len, stdout);
++ fflush(stdout);
++ return n;
++}
++
++static int GSDLLCALL
++gsdll_stderr(void *instance, const char *str, int len)
++{
++ return gsdll_stdout(instance, str, len);
++}
++
++/* Poll the caller for cooperative multitasking. */
++/* If this function is NULL, polling is not needed */
++static int GSDLLCALL gsdll_poll(void *handle)
++{
++ EventRecord eventStructure;
++
++ while (WaitNextEvent(everyEvent, &eventStructure, 0, NULL))
++ doEvents(&eventStructure);
++
++ return (gDone ? e_Fatal : 0);
++}
++/*********************************************************************/
++
++/* new dll display device */
++
++/* New device has been opened */
++/* This is the first event from this device. */
++static int display_open(void *handle, void *device)
++{
++ IMAGE *img = (IMAGE *)malloc(sizeof(IMAGE));
++ if (img == NULL)
++ return -1;
++ memset(img, 0, sizeof(IMAGE));
++
++ /* add to list */
++ if (first_image)
++ img->next = first_image;
++ first_image = img;
++
++ /* remember device and handle */
++ img->handle = handle;
++ img->device = device;
++
++ /* create window */
++ window_create(img);
++
++ gsdll_poll(handle);
++ return 0;
++}
++
++/* Device is about to be closed. */
++/* Device will not be closed until this function returns. */
++static int display_preclose(void *handle, void *device)
++{
++ /* do nothing - no thread synchonisation needed */
++ return 0;
++}
++
++/* Device has been closed. */
++/* This is the last event from this device. */
++static int display_close(void *handle, void *device)
++{
++ IMAGE *img = image_find(handle, device);
++ if (img == NULL)
++ return -1;
++
++ gsdll_poll(handle);
++
++ /* remove from list */
++ if (img == first_image)
++ first_image = img->next;
++ else
++ {
++ IMAGE *tmp;
++ for (tmp = first_image; tmp!=0; tmp=tmp->next)
++ {
++ if (img == tmp->next)
++ tmp->next = img->next;
++ }
++ }
++
++ DisposePixMap(img->pixmapHdl); // need to go in doCloseWindow()
++ DisposeWindow(img->windowRef);
++
++ free(img);
++
++ return 0;
++}
++
++/* Device is about to be resized. */
++/* Resize will only occur if this function returns 0. */
++static int display_presize(void *handle, void *device, int width, int height,
++ int raster, unsigned int format)
++{
++ /* Check for correct format (32-bit RGB), fatal error if not */
++ if (format != display_format)
++ {
++ printf("DisplayFormat has been set to an incompatible value.\n");
++ fflush(stdout);
++ return e_rangecheck;
++ }
++
++ return 0;
++}
++
++/* Device has been resized. */
++/* New pointer to raster returned in pimage */
++static int display_size(void *handle, void *device, int width, int height,
++ int raster, unsigned int format, unsigned char *pimage)
++{
++ PixMapPtr pixmap;
++ IMAGE *img = image_find(handle, device);
++ if (img == NULL)
++ return -1;
++
++ /* Check that image is within allowable bounds */
++ if (raster > 0x3fff)
++ {
++ printf("QuickDraw can't cope with an image this big.\n");
++ fflush(stdout);
++ if (img->pixmapHdl)
++ {
++ DisposePixMap(img->pixmapHdl);
++ img->pixmapHdl = NULL;
++ }
++ return e_rangecheck;
++ }
++
++ /* Create the PixMap */
++ if (!img->pixmapHdl)
++ img->pixmapHdl = NewPixMap();
++
++ pixmap = *(img->pixmapHdl);
++ pixmap->baseAddr = (char*)pimage;
++ pixmap->rowBytes = (((SInt16)raster) & 0x3fff) | 0x8000;
++ pixmap->bounds.right = width;
++ pixmap->bounds.bottom = height;
++ pixmap->packType = 0;
++ pixmap->packSize = 0;
++ pixmap->pixelType = RGBDirect;
++ pixmap->pixelSize = 32;
++ pixmap->cmpCount = 3;
++ pixmap->cmpSize = 8;
++
++ /* Update the display window */
++ window_adjust_scrollbars(img->windowRef);
++ window_invalidate(img->windowRef);
++ return gsdll_poll(handle);
++}
++
++/* flushpage */
++static int display_sync(void *handle, void *device)
++{
++ IMAGE *img = image_find(handle, device);
++ if (img == NULL)
++ return -1;
++
++ window_invalidate(img->windowRef);
++ gsdll_poll(handle);
++
++ return 0;
++}
++
++/* showpage */
++/* If you want to pause on showpage, then don't return immediately */
++static int display_page(void *handle, void *device, int copies, int flush)
++{
++ return display_sync(handle, device);
++}
++
++/* Poll the caller for cooperative multitasking. */
++/* If this function is NULL, polling is not needed */
++static int display_update(void *handle, void *device,
++ int x, int y, int w, int h)
++{
++ UInt64 t1;
++ UInt64 t2;
++ int delta;
++ IMAGE *img = image_find(handle, device);
++ if (img == NULL)
++ return -1;
++
++ Microseconds((UnsignedWide*)&t1);
++ delta = (t1 - img->update_time) / 1000000L;
++ if (img->update_interval < 1)
++ img->update_interval = 1; /* seconds */
++ if (delta < 0)
++ img->update_time = t1;
++ else if (delta > img->update_interval)
++ {
++ /* redraw window */
++ window_invalidate(img->windowRef);
++
++ /* Make sure the update interval is at least 10 times
++ * what it takes to paint the window
++ */
++ Microseconds((UnsignedWide*)&t2);
++ delta = (t2 - t1) / 1000;
++ if (delta < 0)
++ delta += 60000; /* delta = time to redraw */
++ if (delta > img->update_interval * 100)
++ img->update_interval = delta/100;
++ img->update_time = t2;
++ }
++
++ return gsdll_poll(handle);
++}
++
++display_callback display = {
++ sizeof(display_callback),
++ DISPLAY_VERSION_MAJOR,
++ DISPLAY_VERSION_MINOR,
++ display_open,
++ display_preclose,
++ display_close,
++ display_presize,
++ display_size,
++ display_sync,
++ display_page,
++ display_update,
++ NULL, /* memalloc */
++ NULL, /* memfree */
++ NULL /* display_separation */
++};
++
++static IMAGE * image_find(void *handle, void *device)
++{
++ IMAGE *img;
++ for (img = first_image; img!=0; img=img->next) {
++ if ((img->handle == handle) && (img->device == device))
++ return img;
++ }
++ return NULL;
++}
++
++/*********************************************************************/
++
++static char *stdin_buf = NULL;
++static size_t stdin_bufpos = 0;
++static size_t stdin_bufsize = 0;
++
++/* This function is a fudge which allows the SIOUX window to be waiting for
++ input and not be modal at the same time. (Why didn't MetroWerks think of that?)
++ It is based on the SIOUX function ReadCharsFromConsole(), and contains an
++ event loop which allows other windows to be active.
++ It collects characters up to when the user presses ENTER, stores the complete
++ buffer and gives as much to the calling function as it wants until it runs
++ out, at which point it gets another line (or set of lines if pasting from the
++ clipboard) from the user.
++*/
++static size_t get_input(void *ptr, size_t size)
++{
++ EventRecord eventStructure;
++ long charswaiting, old_charswaiting = 0;
++ char *text;
++
++#if SIOUX_USE_WASTE
++ Handle textHandle;
++#endif
++
++ /* If needing more input, set edit start position */
++ if (!stdin_buf)
++#if SIOUX_USE_WASTE
++ SIOUXselstart = WEGetTextLength(SIOUXTextWindow->edit);
++#else
++ SIOUXselstart = (*SIOUXTextWindow->edit)->teLength;
++#endif
++
++ /* Wait until user presses exit (or quits) */
++ while(!gDone && !stdin_buf)
++ {
++#if SIOUX_USE_WASTE
++ charswaiting = WEGetTextLength(SIOUXTextWindow->edit) - SIOUXselstart;
++#else
++ if ((*SIOUXTextWindow->edit)->teLength > 0)
++ charswaiting = (*SIOUXTextWindow->edit)->teLength - SIOUXselstart;
++ else
++ charswaiting = ((unsigned short) (*SIOUXTextWindow->edit)->teLength) - SIOUXselstart;
++#endif
++
++ /* If something has happened, see if we need to do anything */
++ if (charswaiting != old_charswaiting)
++ {
++#if SIOUX_USE_WASTE
++ textHandle = WEGetText(SIOUXTextWindow->edit);
++ HLock(textHandle);
++ text = *textHandle + SIOUXselstart;
++#else
++ text = (*(*SIOUXTextWindow->edit)->hText) + SIOUXselstart;
++#endif
++ /* If user has pressed enter, gather up the buffer ready for returning */
++ if (text[charswaiting-1] == '\r')
++ {
++ stdin_buf = malloc(charswaiting);
++ if (!stdin_buf)
++ return -1;
++ stdin_bufsize = charswaiting;
++ memcpy(stdin_buf, text, stdin_bufsize);
++ SIOUXselstart += charswaiting;
++
++ text = stdin_buf;
++ while (text = memchr(text, '\r', charswaiting - (text - stdin_buf)))
++ *text = '\n';
++ }
++#if SIOUX_USE_WASTE
++ HUnlock(textHandle);
++#endif
++ old_charswaiting = charswaiting;
++
++ if (stdin_buf)
++ break;
++ }
++
++ /* Wait for next event and process it */
++ SIOUXState = SCANFING;
++
++ if(WaitNextEvent(everyEvent, &eventStructure, SIOUXSettings.sleep ,NULL))
++ doEvents(&eventStructure);
++ else
++ SIOUXHandleOneEvent(&eventStructure);
++
++ SIOUXState = IDLE;
++ }
++
++ /* If data has been entered, return as much as has been requested */
++ if (stdin_buf && !gDone)
++ {
++ if (size >= stdin_bufsize - stdin_bufpos)
++ {
++ size = stdin_bufsize - stdin_bufpos;
++ memcpy (ptr, stdin_buf + stdin_bufpos, size);
++ free(stdin_buf);
++ stdin_buf = NULL;
++ stdin_bufpos = 0;
++ stdin_bufsize = 0;
++ }
++ else
++ {
++ memcpy (ptr, stdin_buf + stdin_bufpos, size);
++ stdin_bufpos += size;
++ }
++ return size;
++ }
++ else if (stdin_buf)
++ {
++ free(stdin_buf);
++ stdin_buf = NULL;
++ stdin_bufpos = 0;
++ stdin_bufsize = 0;
++ }
++
++ return 0;
++}
++
++/*********************************************************************/
++
++static void window_create(IMAGE *img)
++{
++ WindowRef windowRef;
++ Str255 windowTitle = "\pGhostscript Image";
++ Rect windowRect = {20,4,580,420};//, portRect;
++ Rect scrollbarRect = {0,0,0,0};
++
++#if TARGET_API_MAC_CARBON
++ GetAvailableWindowPositioningBounds(GetMainDevice(),&windowRect);
++#endif
++
++ /* Create a new suitablty positioned window */
++ windowRect.top = windowRect.top * 2 + 2;
++ windowRect.bottom -= 10;
++ windowRect.left += 4;
++ windowRect.right = ((windowRect.bottom - windowRect.top) * 3) / 4 + windowRect.left;
++
++ if(!(windowRef = NewCWindow(NULL, &windowRect, windowTitle, true,
++ zoomDocProc, (WindowRef) -1, false, 0)))
++ ExitToShell();
++
++ img->windowRef = windowRef;
++
++ SetWRefCon(img->windowRef, (SInt32)img);
++
++ /* Create the window's scrollbars */
++#if TARGET_API_MAC_CARBON
++ if(gRunningOnX)
++ ChangeWindowAttributes(windowRef,kWindowLiveResizeAttribute,0);
++
++ CreateScrollBarControl(windowRef, &scrollbarRect, 0, 0, 0, 0,
++ true, gActionFunctionScrollUPP, &(img->scrollbarVertRef));
++
++ CreateScrollBarControl(windowRef, &scrollbarRect, 0, 0, 0, 0,
++ true, gActionFunctionScrollUPP, &(img->scrollbarHorizRef));
++#else
++ img->scrollbarVertRef = NewControl(windowRef,&scrollbarRect,"\p",false,0,0,0,scrollBarProc,0);
++ img->scrollbarHorizRef = NewControl(windowRef,&scrollbarRect,"\p",false,0,0,0,scrollBarProc,0);
++#endif
++
++ window_adjust_scrollbars(windowRef);
++}
++
++static void window_invalidate(WindowRef windowRef)
++{
++ Rect portRect;
++
++ GetWindowPortBounds(windowRef, &portRect);
++ InvalWindowRect(windowRef, &portRect);
++}
++
++static void window_adjust_scrollbars(WindowRef windowRef)
++{
++ IMAGE *img;
++ Rect portRect;
++
++ img = (IMAGE*)GetWRefCon(windowRef);
++ GetWindowPortBounds(windowRef,&portRect);
++
++ /* Move the crollbars to the edges of the window */
++ HideControl(img->scrollbarVertRef);
++ HideControl(img->scrollbarHorizRef);
++
++ MoveControl(img->scrollbarVertRef,portRect.right - kScrollBarWidth,
++ portRect.top - 1);
++ MoveControl(img->scrollbarHorizRef,portRect.left - 1,
++ portRect.bottom - kScrollBarWidth);
++
++ SizeControl(img->scrollbarVertRef,kScrollBarWidth + 1,
++ portRect.bottom - portRect.top - kScrollBarWidth + 1);
++ SizeControl(img->scrollbarHorizRef, portRect.right - portRect.left - kScrollBarWidth + 1,
++ kScrollBarWidth + 1);
++
++ /* Adjust the scroll position showing */
++ if (img->pixmapHdl)
++ {
++ PixMap *pixmap = *(img->pixmapHdl);
++ int visibleHeight = portRect.bottom - portRect.top - kScrollBarWidth;
++ int visibleWidth = portRect.right - portRect.left - kScrollBarWidth;
++
++ if (pixmap->bounds.bottom > visibleHeight)
++ {
++ SetControl32BitMaximum(img->scrollbarVertRef,
++ pixmap->bounds.bottom - visibleHeight);
++ SetControlViewSize(img->scrollbarVertRef,visibleHeight);
++ }
++ else
++ SetControlMaximum(img->scrollbarVertRef, 0);
++
++ if (pixmap->bounds.right > visibleWidth)
++ {
++ SetControl32BitMaximum(img->scrollbarHorizRef,
++ pixmap->bounds.right - visibleWidth);
++ SetControlViewSize(img->scrollbarHorizRef, visibleWidth);
++ }
++ else
++ SetControlMaximum(img->scrollbarHorizRef, 0);
++ }
++
++ ShowControl(img->scrollbarVertRef);
++ ShowControl(img->scrollbarHorizRef);
++}
++
++/*********************************************************************/
++void main(void)
++{
++ int code;
++ int exit_code;
++ int argc;
++ char **argv;
++ char dformat[64], ddevice[32];
++ SInt32 response;
++
++ /* Initialize operating environment */
++#if TARGET_API_MAC_CARBON
++ MoreMasterPointers(224);
++#else
++ MoreMasters();
++#endif
++ InitCursor();
++ FlushEvents(everyEvent,0);
++
++ if (AEInstallEventHandler(kCoreEventClass,kAEQuitApplication,
++ NewAEEventHandlerUPP((AEEventHandlerProcPtr) quitAppEventHandler),
++ 0L,false) != noErr)
++ ExitToShell();
++
++ gActionFunctionScrollUPP = NewControlActionUPP(&actionFunctionScroll);
++
++ Gestalt(gestaltMenuMgrAttr,&response);
++ if(response & gestaltMenuMgrAquaLayoutMask)
++ gRunningOnX = true;
++
++ /* Initialize SIOUX */
++ SIOUXSettings.initializeTB = false;
++ SIOUXSettings.standalone = false;
++ SIOUXSettings.asktosaveonclose = false;
++ SIOUXSettings.sleep = GetCaretTime();
++ SIOUXSettings.userwindowtitle = "\pGhostscript";
++
++ /* Get arguments from user */
++ argc = ccommand(&argv);
++
++ /* Show command line window */
++ if (InstallConsole(0))
++ ExitToShell();
++
++ /* Part of fudge to make SIOUX accept characters without becoming modal */
++ SelectWindow(SIOUXTextWindow->window);
++ PostEvent(keyDown, 0x4c00); // Enter
++ ReadCharsFromConsole(dformat, 0x7FFF);
++ clrscr();
++
++ /* Add in the display format as the first command line argument */
++ if (argc >= MAX_ARGS - 1)
++ {
++ printf("Too many command line arguments\n");
++ return;
++ }
++
++ memmove(&argv[3], &argv[1], (argc-1) * sizeof(char**));
++ argc += 2;
++ argv[1] = ddevice;
++ argv[2] = dformat;
++
++ sprintf(ddevice, "-sDEVICE=display");
++ sprintf(dformat, "-dDisplayFormat=%d", display_format);
++
++ /* Run Ghostscript */
++ if (gsapi_new_instance(&instance, NULL) < 0)
++ {
++ printf("Can't create Ghostscript instance\n");
++ return;
++ }
++
++#ifdef DEBUG
++ visual_tracer_init();
++ set_visual_tracer(&visual_tracer);
++#endif
++
++ gsapi_set_stdio(instance, gsdll_stdin, gsdll_stdout, gsdll_stderr);
++ gsapi_set_poll(instance, gsdll_poll);
++ gsapi_set_display_callback(instance, &display);
++
++ code = gsapi_init_with_args(instance, argc, argv);
++ if (code == 0)
++ code = gsapi_run_string(instance, start_string, 0, &exit_code);
++ else
++ {
++ printf("Failed to initialize. Error %d.\n", code);
++ fflush(stdout);
++ }
++ code = gsapi_exit(instance);
++ if (code != 0)
++ {
++ printf("Failed to terminate. Error %d.\n", code);
++ fflush(stdout);
++ }
++
++ gsapi_delete_instance(instance);
++
++#ifdef DEBUG
++ visual_tracer_close();
++#endif
++
++ /* Ghostscript has finished - let user see output before quitting */
++ WriteCharsToConsole("\r[Finished - hit any key to quit]", 33);
++ fflush(stdout);
++
++ /* Process events until a key is hit or user quits from menu */
++ while(!gDone)
++ {
++ EventRecord eventStructure;
++
++ if(WaitNextEvent(everyEvent,&eventStructure,SIOUXSettings.sleep,NULL))
++ {
++ if (eventStructure.what == keyDown)
++ gDone = true;
++
++ doEvents(&eventStructure);
++ }
++ else
++ SIOUXHandleOneEvent(&eventStructure);
++ }
++}
++
++/*********************************************************************/
++
++void doEvents(EventRecord *eventStrucPtr)
++{
++ WindowRef windowRef;
++
++ if (eventStrucPtr->what == mouseDown &&
++ FindWindow(eventStrucPtr->where,&windowRef) == inMenuBar)
++ SelectWindow(SIOUXTextWindow->window);
++
++ SIOUXSettings.standalone = true;
++ if (SIOUXHandleOneEvent(eventStrucPtr))
++ {
++ if (SIOUXQuitting)
++ gDone = true;
++ SIOUXSettings.standalone = false;
++ return;
++ }
++ SIOUXSettings.standalone = false;
++
++ switch(eventStrucPtr->what)
++ {
++ case kHighLevelEvent:
++ AEProcessAppleEvent(eventStrucPtr);
++ break;
++
++ case mouseDown:
++ doMouseDown(eventStrucPtr);
++ break;
++
++ case keyDown:
++ case autoKey:
++ break;
++
++ case updateEvt:
++ doUpdate(eventStrucPtr);
++ break;
++
++ case activateEvt:
++ DrawGrowIcon(windowRef);
++ break;
++
++ case osEvt:
++ doOSEvent(eventStrucPtr);
++ break;
++ }
++}
++
++void doMouseDown(EventRecord *eventStrucPtr)
++{
++ WindowRef windowRef;
++ WindowPartCode partCode, zoomPart;
++ BitMap screenBits;
++ Rect constraintRect, mainScreenRect;
++ Point standardStateHeightAndWidth;
++ long newSize;
++
++ partCode = FindWindow(eventStrucPtr->where,&windowRef);
++
++ switch(partCode)
++ {
++ case inMenuBar:
++ break;
++
++ case inContent:
++ if(windowRef != FrontWindow())
++ SelectWindow(windowRef);
++ else
++ doInContent(eventStrucPtr,windowRef);
++ break;
++
++ case inDrag:
++ DragWindow(windowRef,eventStrucPtr->where,NULL);
++ break;
++
++ case inGoAway:
++ break;
++
++ case inGrow:
++ constraintRect.top = 75;
++ constraintRect.left = 250;
++ constraintRect.bottom = constraintRect.right = 32767;
++ newSize = GrowWindow(windowRef,eventStrucPtr->where,&constraintRect);
++ if (newSize != 0)
++ SizeWindow(windowRef,LoWord(newSize),HiWord(newSize),true);
++ window_adjust_scrollbars(windowRef);
++ window_invalidate(windowRef);
++ break;
++
++ case inZoomIn:
++ case inZoomOut:
++ mainScreenRect = GetQDGlobalsScreenBits(&screenBits)->bounds;
++ standardStateHeightAndWidth.v = mainScreenRect.bottom;
++ standardStateHeightAndWidth.h = mainScreenRect.right;
++
++ if(IsWindowInStandardState(windowRef,&standardStateHeightAndWidth,NULL))
++ zoomPart = inZoomIn;
++ else
++ zoomPart = inZoomOut;
++
++ if(TrackBox(windowRef,eventStrucPtr->where,partCode))
++ {
++ ZoomWindowIdeal(windowRef,zoomPart,&standardStateHeightAndWidth);
++ window_adjust_scrollbars(windowRef);
++ }
++ break;
++ }
++}
++
++void doUpdate(EventRecord *eventStrucPtr)
++{
++ WindowRef windowRef;
++
++ windowRef = (WindowRef) eventStrucPtr->message;
++
++ window_adjust_scrollbars(windowRef);
++
++ BeginUpdate(windowRef);
++
++ SetPortWindowPort(windowRef);
++ doUpdateWindow(eventStrucPtr);
++
++ EndUpdate(windowRef);
++}
++
++void doUpdateWindow(EventRecord *eventStrucPtr)
++{
++ IMAGE *img;
++ WindowRef windowRef;
++ Rect srcRect, destRect, fillRect;
++ PixMapHandle srcPixmapHdl, destPixmapHdl;
++ RGBColor grayColour = { 0xC000,0xC000,0xC000 };
++ SInt32 hScroll, vScroll;
++
++ windowRef = (WindowRef) eventStrucPtr->message;
++ img = (IMAGE*)GetWRefCon(windowRef);
++ srcPixmapHdl = img->pixmapHdl;
++ destPixmapHdl = GetPortPixMap(GetWindowPort(windowRef));
++ hScroll = GetControl32BitValue(img->scrollbarHorizRef);
++ vScroll = GetControl32BitValue(img->scrollbarVertRef);
++
++ if (srcPixmapHdl)
++ {
++ PixMap *pixmap = *srcPixmapHdl;
++ PixPatHandle hdlPixPat = NewPixPat();
++ MakeRGBPat(hdlPixPat, &grayColour);
++
++ GetWindowPortBounds(windowRef,&destRect);
++ destRect.right -= kScrollBarWidth;
++ destRect.bottom -= kScrollBarWidth;
++
++ if (destRect.right > pixmap->bounds.right)
++ {
++ fillRect.top = destRect.top;
++ fillRect.bottom = destRect.bottom;
++ fillRect.left = pixmap->bounds.right;
++ fillRect.right = destRect.right;
++ FillCRect(&fillRect, hdlPixPat);
++ destRect.right = pixmap->bounds.right;
++ }
++ if (destRect.bottom > pixmap->bounds.bottom)
++ {
++ fillRect.top = pixmap->bounds.bottom;
++ fillRect.bottom = destRect.bottom;
++ fillRect.left = destRect.left;
++ fillRect.right = destRect.right;
++ FillCRect(&fillRect, hdlPixPat);
++ destRect.bottom = pixmap->bounds.bottom;
++ }
++ DisposePixPat(hdlPixPat);
++
++ srcRect = destRect;
++ srcRect.left += hScroll;
++ srcRect.right += hScroll;
++ srcRect.top += vScroll;
++ srcRect.bottom += vScroll;
++
++ CopyBits((BitMap*)*srcPixmapHdl, (BitMap*)*destPixmapHdl,
++ &srcRect, &destRect, srcCopy, NULL);
++ }
++
++ DrawGrowIcon(windowRef);
++}
++
++void doOSEvent(EventRecord *eventStrucPtr)
++{
++ switch((eventStrucPtr->message >> 24) & 0x000000FF)
++ {
++ case suspendResumeMessage:
++ if((eventStrucPtr->message & resumeFlag) == 1)
++ SetThemeCursor(kThemeArrowCursor);
++ break;
++ }
++}
++
++void doInContent(EventRecord *eventStrucPtr,WindowRef windowRef)
++{
++ ControlPartCode controlPartCode;
++ ControlRef controlRef;
++
++ SetPortWindowPort(windowRef);
++ GlobalToLocal(&eventStrucPtr->where);
++
++ if(controlRef = FindControlUnderMouse(eventStrucPtr->where,windowRef,&controlPartCode))
++ {
++#if TARGET_API_MAC_CARBON
++ TrackControl(controlRef,eventStrucPtr->where,(ControlActionUPP) -1);
++#else
++ if (controlPartCode == kControlIndicatorPart)
++ TrackControl(controlRef,eventStrucPtr->where,NULL);
++ else
++ TrackControl(controlRef,eventStrucPtr->where,gActionFunctionScrollUPP);
++#endif
++
++ window_invalidate(windowRef);
++ }
++}
++
++pascal void actionFunctionScroll(ControlRef controlRef,ControlPartCode controlPartCode)
++{
++ SInt32 scrollDistance, controlValue, oldControlValue, controlMax;
++
++ if(controlPartCode != kControlNoPart)
++ {
++ if(controlPartCode != kControlIndicatorPart)
++ {
++ switch(controlPartCode)
++ {
++ case kControlUpButtonPart:
++ case kControlDownButtonPart:
++ scrollDistance = 10;
++ break;
++
++ case kControlPageUpPart:
++ case kControlPageDownPart:
++ scrollDistance = 100;
++ break;
++
++ default:
++ scrollDistance = 0;
++ break;
++ }
++
++ if (scrollDistance)
++ {
++ if((controlPartCode == kControlDownButtonPart) ||
++ (controlPartCode == kControlPageDownPart))
++ scrollDistance = -scrollDistance;
++
++ controlValue = GetControl32BitValue(controlRef);
++
++ if(((controlValue == GetControl32BitMaximum(controlRef)) && scrollDistance < 0) ||
++ ((controlValue == GetControl32BitMinimum(controlRef)) && scrollDistance > 0))
++ return;
++
++ oldControlValue = controlValue;
++ controlMax = GetControl32BitMaximum(controlRef);
++ controlValue = oldControlValue - scrollDistance;
++
++ if(controlValue < 0)
++ controlValue = 0;
++ else if(controlValue > controlMax)
++ controlValue = controlMax;
++
++ SetControl32BitValue(controlRef,controlValue);
++ }
++ }
++ }
++}
++
++OSErr quitAppEventHandler(AppleEvent *appEvent,AppleEvent *reply,SInt32 handlerRefcon)
++{
++ OSErr osError;
++ DescType returnedType;
++ Size actualSize;
++
++ osError = AEGetAttributePtr(appEvent,keyMissedKeywordAttr,typeWildCard,&returnedType,NULL,0,
++ &actualSize);
++
++ if(osError == errAEDescNotFound)
++ {
++ gDone = true;
++ osError = noErr;
++ }
++ else if(osError == noErr)
++ osError = errAEParamMissed;
++
++ return osError;
++}
++
++/*********************************************************************/
++
+diff --git a/psi/dmmain.r b/psi/dmmain.r
+new file mode 100644
+--- /dev/null
++++ b/psi/dmmain.r
+@@ -0,0 +1,2537 @@
++/* Copyright (C) 2001-2006 Artifex Software, Inc.
++ All Rights Reserved.
++
++ This software is provided AS-IS with no warranty, either express or
++ implied.
++
++ This software is distributed under license and may not be copied, modified
++ or distributed except as expressly authorized under the terms of that
++ license. Refer to licensing infor