summaryrefslogtreecommitdiff
path: root/poppler/PSOutputDev.cc
diff options
context:
space:
mode:
authorAlbert Astals Cid <aacid@kde.org>2020-07-03 23:51:42 +0200
committerAlbert Astals Cid <aacid@kde.org>2020-07-03 23:51:42 +0200
commit814fbda28cc8a37fed3134c2db8da28f86fb5ee0 (patch)
tree77872b408199925ebba6a68b0dccaa0d29274c3f /poppler/PSOutputDev.cc
parent0d48722746b9702e219df58ad14cee6184a62bef (diff)
Run clang-format
find . \( -name "*.cpp" -or -name "*.h" -or -name "*.c" -or -name "*.cc" \) -exec clang-format -i {} \; If you reached this file doing a git blame, please see README.contributors (instructions added 2 commits in the future to this one)
Diffstat (limited to 'poppler/PSOutputDev.cc')
-rw-r--r--poppler/PSOutputDev.cc13794
1 files changed, 6719 insertions, 7075 deletions
diff --git a/poppler/PSOutputDev.cc b/poppler/PSOutputDev.cc
index 3bb5967a..f836947c 100644
--- a/poppler/PSOutputDev.cc
+++ b/poppler/PSOutputDev.cc
@@ -69,10 +69,10 @@
#include "Page.h"
#include "Stream.h"
#ifdef ENABLE_ZLIB
-# include "FlateEncoder.h"
+# include "FlateEncoder.h"
#endif
#ifdef ENABLE_ZLIB_UNCOMPRESS
-# include "FlateStream.h"
+# include "FlateStream.h"
#endif
#include "Annot.h"
#include "XRef.h"
@@ -80,16 +80,16 @@
#include "FileSpec.h"
#include "CharCodeToUnicode.h"
#ifdef HAVE_SPLASH
-# include "splash/Splash.h"
-# include "splash/SplashBitmap.h"
-# include "SplashOutputDev.h"
+# include "splash/Splash.h"
+# include "splash/SplashBitmap.h"
+# include "SplashOutputDev.h"
#endif
#include "PSOutputDev.h"
#include "PDFDoc.h"
// the MSVC math.h doesn't define this
#ifndef M_PI
-#define M_PI 3.14159265358979323846
+# define M_PI 3.14159265358979323846
#endif
//------------------------------------------------------------------------
@@ -108,966 +108,964 @@
// ^ ^----- s=psLevel*Sep, n=psLevel*
// +----- 1=psLevel1*, 2=psLevel2*, 3=psLevel3*
-static const char *prolog[] = {
- "/xpdf 75 dict def xpdf begin",
- "% PDF special state",
- "/pdfDictSize 15 def",
- "~1sn",
- "/pdfStates 64 array def",
- " 0 1 63 {",
- " pdfStates exch pdfDictSize dict",
- " dup /pdfStateIdx 3 index put",
- " put",
- " } for",
- "~123sn",
- "/pdfSetup {",
- " /setpagedevice where {",
- " pop 2 dict begin",
- " /Policies 1 dict dup begin /PageSize 6 def end def",
- " { /Duplex true def } if",
- " currentdict end setpagedevice",
- " } {",
- " pop",
- " } ifelse",
- "} def",
- "/pdfSetupPaper {",
- " % Change paper size, but only if different from previous paper size otherwise",
- " % duplex fails. PLRM specifies a tolerance of 5 pts when matching paper size",
- " % so we use the same when checking if the size changes.",
- " /setpagedevice where {",
- " pop currentpagedevice",
- " /PageSize known {",
- " 2 copy",
- " currentpagedevice /PageSize get aload pop",
- " exch 4 1 roll",
- " sub abs 5 gt",
- " 3 1 roll",
- " sub abs 5 gt",
- " or",
- " } {",
- " true",
- " } ifelse",
- " {",
- " 2 array astore",
- " 2 dict begin",
- " /PageSize exch def",
- " /ImagingBBox null def",
- " currentdict end",
- " setpagedevice",
- " } {",
- " pop pop",
- " } ifelse",
- " } {",
- " pop",
- " } ifelse",
- "} def",
- "~1sn",
- "/pdfOpNames [",
- " /pdfFill /pdfStroke /pdfLastFill /pdfLastStroke",
- " /pdfTextMat /pdfFontSize /pdfCharSpacing /pdfTextRender /pdfPatternCS",
- " /pdfTextRise /pdfWordSpacing /pdfHorizScaling /pdfTextClipPath",
- "] def",
- "~123sn",
- "/pdfStartPage {",
- "~1sn",
- " pdfStates 0 get begin",
- "~23sn",
- " pdfDictSize dict begin",
- "~23n",
- " /pdfFillCS [] def",
- " /pdfFillXform {} def",
- " /pdfStrokeCS [] def",
- " /pdfStrokeXform {} def",
- "~1n",
- " /pdfFill 0 def",
- " /pdfStroke 0 def",
- "~1s",
- " /pdfFill [0 0 0 1] def",
- " /pdfStroke [0 0 0 1] def",
- "~23sn",
- " /pdfFill [0] def",
- " /pdfStroke [0] def",
- " /pdfFillOP false def",
- " /pdfStrokeOP false def",
- "~3sn",
- " /pdfOPM false def",
- "~123sn",
- " /pdfLastFill false def",
- " /pdfLastStroke false def",
- " /pdfTextMat [1 0 0 1 0 0] def",
- " /pdfFontSize 0 def",
- " /pdfCharSpacing 0 def",
- " /pdfTextRender 0 def",
- " /pdfPatternCS false def",
- " /pdfTextRise 0 def",
- " /pdfWordSpacing 0 def",
- " /pdfHorizScaling 1 def",
- " /pdfTextClipPath [] def",
- "} def",
- "/pdfEndPage { end } def",
- "~23s",
- "% separation convention operators",
- "/findcmykcustomcolor where {",
- " pop",
- "}{",
- " /findcmykcustomcolor { 5 array astore } def",
- "} ifelse",
- "/setcustomcolor where {",
- " pop",
- "}{",
- " /setcustomcolor {",
- " exch",
- " [ exch /Separation exch dup 4 get exch /DeviceCMYK exch",
- " 0 4 getinterval cvx",
- " [ exch /dup load exch { mul exch dup } /forall load",
- " /pop load dup ] cvx",
- " ] setcolorspace setcolor",
- " } def",
- "} ifelse",
- "/customcolorimage where {",
- " pop",
- "}{",
- " /customcolorimage {",
- " gsave",
- " [ exch /Separation exch dup 4 get exch /DeviceCMYK exch",
- " 0 4 getinterval",
- " [ exch /dup load exch { mul exch dup } /forall load",
- " /pop load dup ] cvx",
- " ] setcolorspace",
- " 10 dict begin",
- " /ImageType 1 def",
- " /DataSource exch def",
- " /ImageMatrix exch def",
- " /BitsPerComponent exch def",
- " /Height exch def",
- " /Width exch def",
- " /Decode [1 0] def",
- " currentdict end",
- " image",
- " grestore",
- " } def",
- "} ifelse",
- "~123sn",
- "% PDF color state",
- "~1n",
- "/g { dup /pdfFill exch def setgray",
- " /pdfLastFill true def /pdfLastStroke false def } def",
- "/G { dup /pdfStroke exch def setgray",
- " /pdfLastStroke true def /pdfLastFill false def } def",
- "/fCol {",
- " pdfLastFill not {",
- " pdfFill setgray",
- " /pdfLastFill true def /pdfLastStroke false def",
- " } if",
- "} def",
- "/sCol {",
- " pdfLastStroke not {",
- " pdfStroke setgray",
- " /pdfLastStroke true def /pdfLastFill false def",
- " } if",
- "} def",
- "~1s",
- "/k { 4 copy 4 array astore /pdfFill exch def setcmykcolor",
- " /pdfLastFill true def /pdfLastStroke false def } def",
- "/K { 4 copy 4 array astore /pdfStroke exch def setcmykcolor",
- " /pdfLastStroke true def /pdfLastFill false def } def",
- "/fCol {",
- " pdfLastFill not {",
- " pdfFill aload pop setcmykcolor",
- " /pdfLastFill true def /pdfLastStroke false def",
- " } if",
- "} def",
- "/sCol {",
- " pdfLastStroke not {",
- " pdfStroke aload pop setcmykcolor",
- " /pdfLastStroke true def /pdfLastFill false def",
- " } if",
- "} def",
- "~3n",
- "/opm { dup /pdfOPM exch def",
- " /setoverprintmode where{pop setoverprintmode}{pop}ifelse } def",
- "~23n",
- "/cs { /pdfFillXform exch def dup /pdfFillCS exch def",
- " setcolorspace } def",
- "/CS { /pdfStrokeXform exch def dup /pdfStrokeCS exch def",
- " setcolorspace } def",
- "/sc { pdfLastFill not { pdfFillCS setcolorspace } if",
- " dup /pdfFill exch def aload pop pdfFillXform setcolor",
- " /pdfLastFill true def /pdfLastStroke false def } def",
- "/SC { pdfLastStroke not { pdfStrokeCS setcolorspace } if",
- " dup /pdfStroke exch def aload pop pdfStrokeXform setcolor",
- " /pdfLastStroke true def /pdfLastFill false def } def",
- "/op { /pdfFillOP exch def",
- " pdfLastFill { pdfFillOP setoverprint } if } def",
- "/OP { /pdfStrokeOP exch def",
- " pdfLastStroke { pdfStrokeOP setoverprint } if } def",
- "/fCol {",
- " pdfLastFill not {",
- " pdfFillCS setcolorspace",
- " pdfFill aload pop pdfFillXform setcolor",
- " pdfFillOP setoverprint",
- " /pdfLastFill true def /pdfLastStroke false def",
- " } if",
- "} def",
- "/sCol {",
- " pdfLastStroke not {",
- " pdfStrokeCS setcolorspace",
- " pdfStroke aload pop pdfStrokeXform setcolor",
- " pdfStrokeOP setoverprint",
- " /pdfLastStroke true def /pdfLastFill false def",
- " } if",
- "} def",
- "~3s",
- "/opm { dup /pdfOPM exch def",
- " /setoverprintmode where{pop setoverprintmode}{pop}ifelse } def",
- "~23s",
- "/k { 4 copy 4 array astore /pdfFill exch def setcmykcolor",
- " /pdfLastFill true def /pdfLastStroke false def } def",
- "/K { 4 copy 4 array astore /pdfStroke exch def setcmykcolor",
- " /pdfLastStroke true def /pdfLastFill false def } def",
- "/ck { 6 copy 6 array astore /pdfFill exch def",
- " findcmykcustomcolor exch setcustomcolor",
- " /pdfLastFill true def /pdfLastStroke false def } def",
- "/CK { 6 copy 6 array astore /pdfStroke exch def",
- " findcmykcustomcolor exch setcustomcolor",
- " /pdfLastStroke true def /pdfLastFill false def } def",
- "/op { /pdfFillOP exch def",
- " pdfLastFill { pdfFillOP setoverprint } if } def",
- "/OP { /pdfStrokeOP exch def",
- " pdfLastStroke { pdfStrokeOP setoverprint } if } def",
- "/fCol {",
- " pdfLastFill not {",
- " pdfFill aload length 4 eq {",
- " setcmykcolor",
- " }{",
- " findcmykcustomcolor exch setcustomcolor",
- " } ifelse",
- " pdfFillOP setoverprint",
- " /pdfLastFill true def /pdfLastStroke false def",
- " } if",
- "} def",
- "/sCol {",
- " pdfLastStroke not {",
- " pdfStroke aload length 4 eq {",
- " setcmykcolor",
- " }{",
- " findcmykcustomcolor exch setcustomcolor",
- " } ifelse",
- " pdfStrokeOP setoverprint",
- " /pdfLastStroke true def /pdfLastFill false def",
- " } if",
- "} def",
- "~123sn",
- "% build a font",
- "/pdfMakeFont {",
- " 4 3 roll findfont",
- " 4 2 roll matrix scale makefont",
- " dup length dict begin",
- " { 1 index /FID ne { def } { pop pop } ifelse } forall",
- " /Encoding exch def",
- " currentdict",
- " end",
- " definefont pop",
- "} def",
- "/pdfMakeFont16 {",
- " exch findfont",
- " dup length dict begin",
- " { 1 index /FID ne { def } { pop pop } ifelse } forall",
- " /WMode exch def",
- " currentdict",
- " end",
- " definefont pop",
- "} def",
- "~3sn",
- "/pdfMakeFont16L3 {",
- " 1 index /CIDFont resourcestatus {",
- " pop pop 1 index /CIDFont findresource /CIDFontType known",
- " } {",
- " false",
- " } ifelse",
- " {",
- " 0 eq { /Identity-H } { /Identity-V } ifelse",
- " exch 1 array astore composefont pop",
- " } {",
- " pdfMakeFont16",
- " } ifelse",
- "} def",
- "~123sn",
- "% graphics state operators",
- "~1sn",
- "/q {",
- " gsave",
- " pdfOpNames length 1 sub -1 0 { pdfOpNames exch get load } for",
- " pdfStates pdfStateIdx 1 add get begin",
- " pdfOpNames { exch def } forall",
- "} def",
- "/Q { end grestore } def",
- "~23sn",
- "/q { gsave pdfDictSize dict begin } def",
- "/Q {",
- " end grestore",
- " /pdfLastFill where {",
- " pop",
- " pdfLastFill {",
- " pdfFillOP setoverprint",
- " } {",
- " pdfStrokeOP setoverprint",
- " } ifelse",
- " } if",
- "~3sn",
- " /pdfOPM where {",
- " pop",
- " pdfOPM /setoverprintmode where{pop setoverprintmode}{pop}ifelse ",
- " } if",
- "~23sn",
- "} def",
- "~123sn",
- "/cm { concat } def",
- "/d { setdash } def",
- "/i { setflat } def",
- "/j { setlinejoin } def",
- "/J { setlinecap } def",
- "/M { setmiterlimit } def",
- "/w { setlinewidth } def",
- "% path segment operators",
- "/m { moveto } def",
- "/l { lineto } def",
- "/c { curveto } def",
- "/re { 4 2 roll moveto 1 index 0 rlineto 0 exch rlineto",
- " neg 0 rlineto closepath } def",
- "/h { closepath } def",
- "% path painting operators",
- "/S { sCol stroke } def",
- "/Sf { fCol stroke } def",
- "/f { fCol fill } def",
- "/f* { fCol eofill } def",
- "% clipping operators",
- "/W { clip newpath } def",
- "/W* { eoclip newpath } def",
- "/Ws { strokepath clip newpath } def",
- "% text state operators",
- "/Tc { /pdfCharSpacing exch def } def",
- "/Tf { dup /pdfFontSize exch def",
- " dup pdfHorizScaling mul exch matrix scale",
- " pdfTextMat matrix concatmatrix dup 4 0 put dup 5 0 put",
- " exch findfont exch makefont setfont } def",
- "/Tr { /pdfTextRender exch def } def",
- "/Tp { /pdfPatternCS exch def } def",
- "/Ts { /pdfTextRise exch def } def",
- "/Tw { /pdfWordSpacing exch def } def",
- "/Tz { /pdfHorizScaling exch def } def",
- "% text positioning operators",
- "/Td { pdfTextMat transform moveto } def",
- "/Tm { /pdfTextMat exch def } def",
- "% text string operators",
- "/xyshow where {",
- " pop",
- " /xyshow2 {",
- " dup length array",
- " 0 2 2 index length 1 sub {",
- " 2 index 1 index 2 copy get 3 1 roll 1 add get",
- " pdfTextMat dtransform",
- " 4 2 roll 2 copy 6 5 roll put 1 add 3 1 roll dup 4 2 roll put",
- " } for",
- " exch pop",
- " xyshow",
- " } def",
- "}{",
- " /xyshow2 {",
- " currentfont /FontType get 0 eq {",
- " 0 2 3 index length 1 sub {",
- " currentpoint 4 index 3 index 2 getinterval show moveto",
- " 2 copy get 2 index 3 2 roll 1 add get",
- " pdfTextMat dtransform rmoveto",
- " } for",
- " } {",
- " 0 1 3 index length 1 sub {",
- " currentpoint 4 index 3 index 1 getinterval show moveto",
- " 2 copy 2 mul get 2 index 3 2 roll 2 mul 1 add get",
- " pdfTextMat dtransform rmoveto",
- " } for",
- " } ifelse",
- " pop pop",
- " } def",
- "} ifelse",
- "/cshow where {",
- " pop",
- " /xycp {", // xycharpath
- " 0 3 2 roll",
- " {",
- " pop pop currentpoint 3 2 roll",
- " 1 string dup 0 4 3 roll put false charpath moveto",
- " 2 copy get 2 index 2 index 1 add get",
- " pdfTextMat dtransform rmoveto",
- " 2 add",
- " } exch cshow",
- " pop pop",
- " } def",
- "}{",
- " /xycp {", // xycharpath
- " currentfont /FontType get 0 eq {",
- " 0 2 3 index length 1 sub {",
- " currentpoint 4 index 3 index 2 getinterval false charpath moveto",
- " 2 copy get 2 index 3 2 roll 1 add get",
- " pdfTextMat dtransform rmoveto",
- " } for",
- " } {",
- " 0 1 3 index length 1 sub {",
- " currentpoint 4 index 3 index 1 getinterval false charpath moveto",
- " 2 copy 2 mul get 2 index 3 2 roll 2 mul 1 add get",
- " pdfTextMat dtransform rmoveto",
- " } for",
- " } ifelse",
- " pop pop",
- " } def",
- "} ifelse",
- "/Tj {",
- " fCol", // because stringwidth has to draw Type 3 chars
- " 0 pdfTextRise pdfTextMat dtransform rmoveto",
- " currentpoint 4 2 roll",
- " pdfTextRender 1 and 0 eq {",
- " 2 copy xyshow2",
- " } if",
- " pdfTextRender 3 and dup 1 eq exch 2 eq or {",
- " 3 index 3 index moveto",
- " 2 copy",
- " currentfont /FontType get 3 eq { fCol } { sCol } ifelse",
- " xycp currentpoint stroke moveto",
- " } if",
- " pdfTextRender 4 and 0 ne {",
- " 4 2 roll moveto xycp",
- " /pdfTextClipPath [ pdfTextClipPath aload pop",
- " {/moveto cvx}",
- " {/lineto cvx}",
- " {/curveto cvx}",
- " {/closepath cvx}",
- " pathforall ] def",
- " currentpoint newpath moveto",
- " } {",
- " pop pop pop pop",
- " } ifelse",
- " 0 pdfTextRise neg pdfTextMat dtransform rmoveto",
- "} def",
- "/TJm { 0.001 mul pdfFontSize mul pdfHorizScaling mul neg 0",
- " pdfTextMat dtransform rmoveto } def",
- "/TJmV { 0.001 mul pdfFontSize mul neg 0 exch",
- " pdfTextMat dtransform rmoveto } def",
- "/Tclip { pdfTextClipPath cvx exec clip newpath",
- " /pdfTextClipPath [] def } def",
- "/Tclip* { pdfTextClipPath cvx exec eoclip newpath",
- " /pdfTextClipPath [] def } def",
- "~1ns",
- "% Level 1 image operators",
- "/pdfIm1 {",
- " /pdfImBuf1 4 index string def",
- " { currentfile pdfImBuf1 readhexstring pop } image",
- "} def",
- "/pdfIm1Bin {",
- " /pdfImBuf1 4 index string def",
- " { currentfile pdfImBuf1 readstring pop } image",
- "} def",
- "~1s",
- "/pdfIm1Sep {",
- " /pdfImBuf1 4 index string def",
- " /pdfImBuf2 4 index string def",
- " /pdfImBuf3 4 index string def",
- " /pdfImBuf4 4 index string def",
- " { currentfile pdfImBuf1 readhexstring pop }",
- " { currentfile pdfImBuf2 readhexstring pop }",
- " { currentfile pdfImBuf3 readhexstring pop }",
- " { currentfile pdfImBuf4 readhexstring pop }",
- " true 4 colorimage",
- "} def",
- "/pdfIm1SepBin {",
- " /pdfImBuf1 4 index string def",
- " /pdfImBuf2 4 index string def",
- " /pdfImBuf3 4 index string def",
- " /pdfImBuf4 4 index string def",
- " { currentfile pdfImBuf1 readstring pop }",
- " { currentfile pdfImBuf2 readstring pop }",
- " { currentfile pdfImBuf3 readstring pop }",
- " { currentfile pdfImBuf4 readstring pop }",
- " true 4 colorimage",
- "} def",
- "~1ns",
- "/pdfImM1 {",
- " fCol /pdfImBuf1 4 index 7 add 8 idiv string def",
- " { currentfile pdfImBuf1 readhexstring pop } imagemask",
- "} def",
- "/pdfImM1Bin {",
- " fCol /pdfImBuf1 4 index 7 add 8 idiv string def",
- " { currentfile pdfImBuf1 readstring pop } imagemask",
- "} def",
- "/pdfImStr {",
- " 2 copy exch length lt {",
- " 2 copy get exch 1 add exch",
- " } {",
- " ()",
- " } ifelse",
- "} def",
- "/pdfImM1a {",
- " { pdfImStr } imagemask",
- " pop pop",
- "} def",
- "~23sn",
- "% Level 2/3 image operators",
- "/pdfImBuf 100 string def",
- "/pdfImStr {",
- " 2 copy exch length lt {",
- " 2 copy get exch 1 add exch",
- " } {",
- " ()",
- " } ifelse",
- "} def",
- "/skipEOD {",
- " { currentfile pdfImBuf readline",
- " not { pop exit } if",
- " (%-EOD-) eq { exit } if } loop",
- "} def",
- "/pdfIm { image skipEOD } def",
- "~3sn",
- "/pdfMask {",
- " /ReusableStreamDecode filter",
- " skipEOD",
- " /maskStream exch def",
- "} def",
- "/pdfMaskEnd { maskStream closefile } def",
- "/pdfMaskInit {",
- " /maskArray exch def",
- " /maskIdx 0 def",
- "} def",
- "/pdfMaskSrc {",
- " maskIdx maskArray length lt {",
- " maskArray maskIdx get",
- " /maskIdx maskIdx 1 add def",
- " } {",
- " ()",
- " } ifelse",
- "} def",
- "~23s",
- "/pdfImSep {",
- " findcmykcustomcolor exch",
- " dup /Width get /pdfImBuf1 exch string def",
- " dup /Decode get aload pop 1 index sub /pdfImDecodeRange exch def",
- " /pdfImDecodeLow exch def",
- " begin Width Height BitsPerComponent ImageMatrix DataSource end",
- " /pdfImData exch def",
- " { pdfImData pdfImBuf1 readstring pop",
- " 0 1 2 index length 1 sub {",
- " 1 index exch 2 copy get",
- " pdfImDecodeRange mul 255 div pdfImDecodeLow add round cvi",
- " 255 exch sub put",
- " } for }",
- " 6 5 roll customcolorimage",
- " skipEOD",
- "} def",
- "~23sn",
- "/pdfImM { fCol imagemask skipEOD } def",
- "~123sn",
- "/pr { 2 index 2 index 3 2 roll putinterval 4 add } def",
- "/pdfImClip {",
- " gsave",
- " 0 2 4 index length 1 sub {",
- " dup 4 index exch 2 copy",
- " get 5 index div put",
- " 1 add 3 index exch 2 copy",
- " get 3 index div put",
- " } for",
- " pop pop rectclip",
- "} def",
- "/pdfImClipEnd { grestore } def",
- "~23sn",
- "% shading operators",
- "/colordelta {",
- " false 0 1 3 index length 1 sub {",
- " dup 4 index exch get 3 index 3 2 roll get sub abs 0.004 gt {",
- " pop true",
- " } if",
- " } for",
- " exch pop exch pop",
- "} def",
- "/funcCol { func n array astore } def",
- "/funcSH {",
- " dup 0 eq {",
- " true",
- " } {",
- " dup 6 eq {",
- " false",
- " } {",
- " 4 index 4 index funcCol dup",
- " 6 index 4 index funcCol dup",
- " 3 1 roll colordelta 3 1 roll",
- " 5 index 5 index funcCol dup",
- " 3 1 roll colordelta 3 1 roll",
- " 6 index 8 index funcCol dup",
- " 3 1 roll colordelta 3 1 roll",
- " colordelta or or or",
- " } ifelse",
- " } ifelse",
- " {",
- " 1 add",
- " 4 index 3 index add 0.5 mul exch 4 index 3 index add 0.5 mul exch",
- " 6 index 6 index 4 index 4 index 4 index funcSH",
- " 2 index 6 index 6 index 4 index 4 index funcSH",
- " 6 index 2 index 4 index 6 index 4 index funcSH",
- " 5 3 roll 3 2 roll funcSH pop pop",
- " } {",
- " pop 3 index 2 index add 0.5 mul 3 index 2 index add 0.5 mul",
- "~23n",
- " funcCol sc",
- "~23s",
- " funcCol aload pop k",
- "~23sn",
- " dup 4 index exch mat transform m",
- " 3 index 3 index mat transform l",
- " 1 index 3 index mat transform l",
- " mat transform l pop pop h f*",
- " } ifelse",
- "} def",
- "/axialCol {",
- " dup 0 lt {",
- " pop t0",
- " } {",
- " dup 1 gt {",
- " pop t1",
- " } {",
- " dt mul t0 add",
- " } ifelse",
- " } ifelse",
- " func n array astore",
- "} def",
- "/axialSH {",
- " dup 0 eq {",
- " true",
- " } {",
- " dup 8 eq {",
- " false",
- " } {",
- " 2 index axialCol 2 index axialCol colordelta",
- " } ifelse",
- " } ifelse",
- " {",
- " 1 add 3 1 roll 2 copy add 0.5 mul",
- " dup 4 3 roll exch 4 index axialSH",
- " exch 3 2 roll axialSH",
- " } {",
- " pop 2 copy add 0.5 mul",
- "~23n",
- " axialCol sc",
- "~23s",
- " axialCol aload pop k",
- "~23sn",
- " exch dup dx mul x0 add exch dy mul y0 add",
- " 3 2 roll dup dx mul x0 add exch dy mul y0 add",
- " dx abs dy abs ge {",
- " 2 copy yMin sub dy mul dx div add yMin m",
- " yMax sub dy mul dx div add yMax l",
- " 2 copy yMax sub dy mul dx div add yMax l",
- " yMin sub dy mul dx div add yMin l",
- " h f*",
- " } {",
- " exch 2 copy xMin sub dx mul dy div add xMin exch m",
- " xMax sub dx mul dy div add xMax exch l",
- " exch 2 copy xMax sub dx mul dy div add xMax exch l",
- " xMin sub dx mul dy div add xMin exch l",
- " h f*",
- " } ifelse",
- " } ifelse",
- "} def",
- "/radialCol {",
- " dup t0 lt {",
- " pop t0",
- " } {",
- " dup t1 gt {",
- " pop t1",
- " } if",
- " } ifelse",
- " func n array astore",
- "} def",
- "/radialSH {",
- " dup 0 eq {",
- " true",
- " } {",
- " dup 8 eq {",
- " false",
- " } {",
- " 2 index dt mul t0 add radialCol",
- " 2 index dt mul t0 add radialCol colordelta",
- " } ifelse",
- " } ifelse",
- " {",
- " 1 add 3 1 roll 2 copy add 0.5 mul",
- " dup 4 3 roll exch 4 index radialSH",
- " exch 3 2 roll radialSH",
- " } {",
- " pop 2 copy add 0.5 mul dt mul t0 add",
- "~23n",
- " radialCol sc",
- "~23s",
- " radialCol aload pop k",
- "~23sn",
- " encl {",
- " exch dup dx mul x0 add exch dup dy mul y0 add exch dr mul r0 add",
- " 0 360 arc h",
- " dup dx mul x0 add exch dup dy mul y0 add exch dr mul r0 add",
- " 360 0 arcn h f",
- " } {",
- " 2 copy",
- " dup dx mul x0 add exch dup dy mul y0 add exch dr mul r0 add",
- " a1 a2 arcn",
- " dup dx mul x0 add exch dup dy mul y0 add exch dr mul r0 add",
- " a2 a1 arcn h",
- " dup dx mul x0 add exch dup dy mul y0 add exch dr mul r0 add",
- " a1 a2 arc",
- " dup dx mul x0 add exch dup dy mul y0 add exch dr mul r0 add",
- " a2 a1 arc h f",
- " } ifelse",
- " } ifelse",
- "} def",
- "~123sn",
- "end",
- nullptr
-};
-
-static const char *cmapProlog[] = {
- "/CIDInit /ProcSet findresource begin",
- "10 dict begin",
- " begincmap",
- " /CMapType 1 def",
- " /CMapName /Identity-H def",
- " /CIDSystemInfo 3 dict dup begin",
- " /Registry (Adobe) def",
- " /Ordering (Identity) def",
- " /Supplement 0 def",
- " end def",
- " 1 begincodespacerange",
- " <0000> <ffff>",
- " endcodespacerange",
- " 0 usefont",
- " 1 begincidrange",
- " <0000> <ffff> 0",
- " endcidrange",
- " endcmap",
- " currentdict CMapName exch /CMap defineresource pop",
- "end",
- "10 dict begin",
- " begincmap",
- " /CMapType 1 def",
- " /CMapName /Identity-V def",
- " /CIDSystemInfo 3 dict dup begin",
- " /Registry (Adobe) def",
- " /Ordering (Identity) def",
- " /Supplement 0 def",
- " end def",
- " /WMode 1 def",
- " 1 begincodespacerange",
- " <0000> <ffff>",
- " endcodespacerange",
- " 0 usefont",
- " 1 begincidrange",
- " <0000> <ffff> 0",
- " endcidrange",
- " endcmap",
- " currentdict CMapName exch /CMap defineresource pop",
- "end",
- "end",
- nullptr
-};
+static const char *prolog[] = { "/xpdf 75 dict def xpdf begin",
+ "% PDF special state",
+ "/pdfDictSize 15 def",
+ "~1sn",
+ "/pdfStates 64 array def",
+ " 0 1 63 {",
+ " pdfStates exch pdfDictSize dict",
+ " dup /pdfStateIdx 3 index put",
+ " put",
+ " } for",
+ "~123sn",
+ "/pdfSetup {",
+ " /setpagedevice where {",
+ " pop 2 dict begin",
+ " /Policies 1 dict dup begin /PageSize 6 def end def",
+ " { /Duplex true def } if",
+ " currentdict end setpagedevice",
+ " } {",
+ " pop",
+ " } ifelse",
+ "} def",
+ "/pdfSetupPaper {",
+ " % Change paper size, but only if different from previous paper size otherwise",
+ " % duplex fails. PLRM specifies a tolerance of 5 pts when matching paper size",
+ " % so we use the same when checking if the size changes.",
+ " /setpagedevice where {",
+ " pop currentpagedevice",
+ " /PageSize known {",
+ " 2 copy",
+ " currentpagedevice /PageSize get aload pop",
+ " exch 4 1 roll",
+ " sub abs 5 gt",
+ " 3 1 roll",
+ " sub abs 5 gt",
+ " or",
+ " } {",
+ " true",
+ " } ifelse",
+ " {",
+ " 2 array astore",
+ " 2 dict begin",
+ " /PageSize exch def",
+ " /ImagingBBox null def",
+ " currentdict end",
+ " setpagedevice",
+ " } {",
+ " pop pop",
+ " } ifelse",
+ " } {",
+ " pop",
+ " } ifelse",
+ "} def",
+ "~1sn",
+ "/pdfOpNames [",
+ " /pdfFill /pdfStroke /pdfLastFill /pdfLastStroke",
+ " /pdfTextMat /pdfFontSize /pdfCharSpacing /pdfTextRender /pdfPatternCS",
+ " /pdfTextRise /pdfWordSpacing /pdfHorizScaling /pdfTextClipPath",
+ "] def",
+ "~123sn",
+ "/pdfStartPage {",
+ "~1sn",
+ " pdfStates 0 get begin",
+ "~23sn",
+ " pdfDictSize dict begin",
+ "~23n",
+ " /pdfFillCS [] def",
+ " /pdfFillXform {} def",
+ " /pdfStrokeCS [] def",
+ " /pdfStrokeXform {} def",
+ "~1n",
+ " /pdfFill 0 def",
+ " /pdfStroke 0 def",
+ "~1s",
+ " /pdfFill [0 0 0 1] def",
+ " /pdfStroke [0 0 0 1] def",
+ "~23sn",
+ " /pdfFill [0] def",
+ " /pdfStroke [0] def",
+ " /pdfFillOP false def",
+ " /pdfStrokeOP false def",
+ "~3sn",
+ " /pdfOPM false def",
+ "~123sn",
+ " /pdfLastFill false def",
+ " /pdfLastStroke false def",
+ " /pdfTextMat [1 0 0 1 0 0] def",
+ " /pdfFontSize 0 def",
+ " /pdfCharSpacing 0 def",
+ " /pdfTextRender 0 def",
+ " /pdfPatternCS false def",
+ " /pdfTextRise 0 def",
+ " /pdfWordSpacing 0 def",
+ " /pdfHorizScaling 1 def",
+ " /pdfTextClipPath [] def",
+ "} def",
+ "/pdfEndPage { end } def",
+ "~23s",
+ "% separation convention operators",
+ "/findcmykcustomcolor where {",
+ " pop",
+ "}{",
+ " /findcmykcustomcolor { 5 array astore } def",
+ "} ifelse",
+ "/setcustomcolor where {",
+ " pop",
+ "}{",
+ " /setcustomcolor {",
+ " exch",
+ " [ exch /Separation exch dup 4 get exch /DeviceCMYK exch",
+ " 0 4 getinterval cvx",
+ " [ exch /dup load exch { mul exch dup } /forall load",
+ " /pop load dup ] cvx",
+ " ] setcolorspace setcolor",
+ " } def",
+ "} ifelse",
+ "/customcolorimage where {",
+ " pop",
+ "}{",
+ " /customcolorimage {",
+ " gsave",
+ " [ exch /Separation exch dup 4 get exch /DeviceCMYK exch",
+ " 0 4 getinterval",
+ " [ exch /dup load exch { mul exch dup } /forall load",
+ " /pop load dup ] cvx",
+ " ] setcolorspace",
+ " 10 dict begin",
+ " /ImageType 1 def",
+ " /DataSource exch def",
+ " /ImageMatrix exch def",
+ " /BitsPerComponent exch def",
+ " /Height exch def",
+ " /Width exch def",
+ " /Decode [1 0] def",
+ " currentdict end",
+ " image",
+ " grestore",
+ " } def",
+ "} ifelse",
+ "~123sn",
+ "% PDF color state",
+ "~1n",
+ "/g { dup /pdfFill exch def setgray",
+ " /pdfLastFill true def /pdfLastStroke false def } def",
+ "/G { dup /pdfStroke exch def setgray",
+ " /pdfLastStroke true def /pdfLastFill false def } def",
+ "/fCol {",
+ " pdfLastFill not {",
+ " pdfFill setgray",
+ " /pdfLastFill true def /pdfLastStroke false def",
+ " } if",
+ "} def",
+ "/sCol {",
+ " pdfLastStroke not {",
+ " pdfStroke setgray",
+ " /pdfLastStroke true def /pdfLastFill false def",
+ " } if",
+ "} def",
+ "~1s",
+ "/k { 4 copy 4 array astore /pdfFill exch def setcmykcolor",
+ " /pdfLastFill true def /pdfLastStroke false def } def",
+ "/K { 4 copy 4 array astore /pdfStroke exch def setcmykcolor",
+ " /pdfLastStroke true def /pdfLastFill false def } def",
+ "/fCol {",
+ " pdfLastFill not {",
+ " pdfFill aload pop setcmykcolor",
+ " /pdfLastFill true def /pdfLastStroke false def",
+ " } if",
+ "} def",
+ "/sCol {",
+ " pdfLastStroke not {",
+ " pdfStroke aload pop setcmykcolor",
+ " /pdfLastStroke true def /pdfLastFill false def",
+ " } if",
+ "} def",
+ "~3n",
+ "/opm { dup /pdfOPM exch def",
+ " /setoverprintmode where{pop setoverprintmode}{pop}ifelse } def",
+ "~23n",
+ "/cs { /pdfFillXform exch def dup /pdfFillCS exch def",
+ " setcolorspace } def",
+ "/CS { /pdfStrokeXform exch def dup /pdfStrokeCS exch def",
+ " setcolorspace } def",
+ "/sc { pdfLastFill not { pdfFillCS setcolorspace } if",
+ " dup /pdfFill exch def aload pop pdfFillXform setcolor",
+ " /pdfLastFill true def /pdfLastStroke false def } def",
+ "/SC { pdfLastStroke not { pdfStrokeCS setcolorspace } if",
+ " dup /pdfStroke exch def aload pop pdfStrokeXform setcolor",
+ " /pdfLastStroke true def /pdfLastFill false def } def",
+ "/op { /pdfFillOP exch def",
+ " pdfLastFill { pdfFillOP setoverprint } if } def",
+ "/OP { /pdfStrokeOP exch def",
+ " pdfLastStroke { pdfStrokeOP setoverprint } if } def",
+ "/fCol {",
+ " pdfLastFill not {",
+ " pdfFillCS setcolorspace",
+ " pdfFill aload pop pdfFillXform setcolor",
+ " pdfFillOP setoverprint",
+ " /pdfLastFill true def /pdfLastStroke false def",
+ " } if",
+ "} def",
+ "/sCol {",
+ " pdfLastStroke not {",
+ " pdfStrokeCS setcolorspace",
+ " pdfStroke aload pop pdfStrokeXform setcolor",
+ " pdfStrokeOP setoverprint",
+ " /pdfLastStroke true def /pdfLastFill false def",
+ " } if",
+ "} def",
+ "~3s",
+ "/opm { dup /pdfOPM exch def",
+ " /setoverprintmode where{pop setoverprintmode}{pop}ifelse } def",
+ "~23s",
+ "/k { 4 copy 4 array astore /pdfFill exch def setcmykcolor",
+ " /pdfLastFill true def /pdfLastStroke false def } def",
+ "/K { 4 copy 4 array astore /pdfStroke exch def setcmykcolor",
+ " /pdfLastStroke true def /pdfLastFill false def } def",
+ "/ck { 6 copy 6 array astore /pdfFill exch def",
+ " findcmykcustomcolor exch setcustomcolor",
+ " /pdfLastFill true def /pdfLastStroke false def } def",
+ "/CK { 6 copy 6 array astore /pdfStroke exch def",
+ " findcmykcustomcolor exch setcustomcolor",
+ " /pdfLastStroke true def /pdfLastFill false def } def",
+ "/op { /pdfFillOP exch def",
+ " pdfLastFill { pdfFillOP setoverprint } if } def",
+ "/OP { /pdfStrokeOP exch def",
+ " pdfLastStroke { pdfStrokeOP setoverprint } if } def",
+ "/fCol {",
+ " pdfLastFill not {",
+ " pdfFill aload length 4 eq {",
+ " setcmykcolor",
+ " }{",
+ " findcmykcustomcolor exch setcustomcolor",
+ " } ifelse",
+ " pdfFillOP setoverprint",
+ " /pdfLastFill true def /pdfLastStroke false def",
+ " } if",
+ "} def",
+ "/sCol {",
+ " pdfLastStroke not {",
+ " pdfStroke aload length 4 eq {",
+ " setcmykcolor",
+ " }{",
+ " findcmykcustomcolor exch setcustomcolor",
+ " } ifelse",
+ " pdfStrokeOP setoverprint",
+ " /pdfLastStroke true def /pdfLastFill false def",
+ " } if",
+ "} def",
+ "~123sn",
+ "% build a font",
+ "/pdfMakeFont {",
+ " 4 3 roll findfont",
+ " 4 2 roll matrix scale makefont",
+ " dup length dict begin",
+ " { 1 index /FID ne { def } { pop pop } ifelse } forall",
+ " /Encoding exch def",
+ " currentdict",
+ " end",
+ " definefont pop",
+ "} def",
+ "/pdfMakeFont16 {",
+ " exch findfont",
+ " dup length dict begin",
+ " { 1 index /FID ne { def } { pop pop } ifelse } forall",
+ " /WMode exch def",
+ " currentdict",
+ " end",
+ " definefont pop",
+ "} def",
+ "~3sn",
+ "/pdfMakeFont16L3 {",
+ " 1 index /CIDFont resourcestatus {",
+ " pop pop 1 index /CIDFont findresource /CIDFontType known",
+ " } {",
+ " false",
+ " } ifelse",
+ " {",
+ " 0 eq { /Identity-H } { /Identity-V } ifelse",
+ " exch 1 array astore composefont pop",
+ " } {",
+ " pdfMakeFont16",
+ " } ifelse",
+ "} def",
+ "~123sn",
+ "% graphics state operators",
+ "~1sn",
+ "/q {",
+ " gsave",
+ " pdfOpNames length 1 sub -1 0 { pdfOpNames exch get load } for",
+ " pdfStates pdfStateIdx 1 add get begin",
+ " pdfOpNames { exch def } forall",
+ "} def",
+ "/Q { end grestore } def",
+ "~23sn",
+ "/q { gsave pdfDictSize dict begin } def",
+ "/Q {",
+ " end grestore",
+ " /pdfLastFill where {",
+ " pop",
+ " pdfLastFill {",
+ " pdfFillOP setoverprint",
+ " } {",
+ " pdfStrokeOP setoverprint",
+ " } ifelse",
+ " } if",
+ "~3sn",
+ " /pdfOPM where {",
+ " pop",
+ " pdfOPM /setoverprintmode where{pop setoverprintmode}{pop}ifelse ",
+ " } if",
+ "~23sn",
+ "} def",
+ "~123sn",
+ "/cm { concat } def",
+ "/d { setdash } def",
+ "/i { setflat } def",
+ "/j { setlinejoin } def",
+ "/J { setlinecap } def",
+ "/M { setmiterlimit } def",
+ "/w { setlinewidth } def",
+ "% path segment operators",
+ "/m { moveto } def",
+ "/l { lineto } def",
+ "/c { curveto } def",
+ "/re { 4 2 roll moveto 1 index 0 rlineto 0 exch rlineto",
+ " neg 0 rlineto closepath } def",
+ "/h { closepath } def",
+ "% path painting operators",
+ "/S { sCol stroke } def",
+ "/Sf { fCol stroke } def",
+ "/f { fCol fill } def",
+ "/f* { fCol eofill } def",
+ "% clipping operators",
+ "/W { clip newpath } def",
+ "/W* { eoclip newpath } def",
+ "/Ws { strokepath clip newpath } def",
+ "% text state operators",
+ "/Tc { /pdfCharSpacing exch def } def",
+ "/Tf { dup /pdfFontSize exch def",
+ " dup pdfHorizScaling mul exch matrix scale",
+ " pdfTextMat matrix concatmatrix dup 4 0 put dup 5 0 put",
+ " exch findfont exch makefont setfont } def",
+ "/Tr { /pdfTextRender exch def } def",
+ "/Tp { /pdfPatternCS exch def } def",
+ "/Ts { /pdfTextRise exch def } def",
+ "/Tw { /pdfWordSpacing exch def } def",
+ "/Tz { /pdfHorizScaling exch def } def",
+ "% text positioning operators",
+ "/Td { pdfTextMat transform moveto } def",
+ "/Tm { /pdfTextMat exch def } def",
+ "% text string operators",
+ "/xyshow where {",
+ " pop",
+ " /xyshow2 {",
+ " dup length array",
+ " 0 2 2 index length 1 sub {",
+ " 2 index 1 index 2 copy get 3 1 roll 1 add get",
+ " pdfTextMat dtransform",
+ " 4 2 roll 2 copy 6 5 roll put 1 add 3 1 roll dup 4 2 roll put",
+ " } for",
+ " exch pop",
+ " xyshow",
+ " } def",
+ "}{",
+ " /xyshow2 {",
+ " currentfont /FontType get 0 eq {",
+ " 0 2 3 index length 1 sub {",
+ " currentpoint 4 index 3 index 2 getinterval show moveto",
+ " 2 copy get 2 index 3 2 roll 1 add get",
+ " pdfTextMat dtransform rmoveto",
+ " } for",
+ " } {",
+ " 0 1 3 index length 1 sub {",
+ " currentpoint 4 index 3 index 1 getinterval show moveto",
+ " 2 copy 2 mul get 2 index 3 2 roll 2 mul 1 add get",
+ " pdfTextMat dtransform rmoveto",
+ " } for",
+ " } ifelse",
+ " pop pop",
+ " } def",
+ "} ifelse",
+ "/cshow where {",
+ " pop",
+ " /xycp {", // xycharpath
+ " 0 3 2 roll",
+ " {",
+ " pop pop currentpoint 3 2 roll",
+ " 1 string dup 0 4 3 roll put false charpath moveto",
+ " 2 copy get 2 index 2 index 1 add get",
+ " pdfTextMat dtransform rmoveto",
+ " 2 add",
+ " } exch cshow",
+ " pop pop",
+ " } def",
+ "}{",
+ " /xycp {", // xycharpath
+ " currentfont /FontType get 0 eq {",
+ " 0 2 3 index length 1 sub {",
+ " currentpoint 4 index 3 index 2 getinterval false charpath moveto",
+ " 2 copy get 2 index 3 2 roll 1 add get",
+ " pdfTextMat dtransform rmoveto",
+ " } for",
+ " } {",
+ " 0 1 3 index length 1 sub {",
+ " currentpoint 4 index 3 index 1 getinterval false charpath moveto",
+ " 2 copy 2 mul get 2 index 3 2 roll 2 mul 1 add get",
+ " pdfTextMat dtransform rmoveto",
+ " } for",
+ " } ifelse",
+ " pop pop",
+ " } def",
+ "} ifelse",
+ "/Tj {",
+ " fCol", // because stringwidth has to draw Type 3 chars
+ " 0 pdfTextRise pdfTextMat dtransform rmoveto",
+ " currentpoint 4 2 roll",
+ " pdfTextRender 1 and 0 eq {",
+ " 2 copy xyshow2",
+ " } if",
+ " pdfTextRender 3 and dup 1 eq exch 2 eq or {",
+ " 3 index 3 index moveto",
+ " 2 copy",
+ " currentfont /FontType get 3 eq { fCol } { sCol } ifelse",
+ " xycp currentpoint stroke moveto",
+ " } if",
+ " pdfTextRender 4 and 0 ne {",
+ " 4 2 roll moveto xycp",
+ " /pdfTextClipPath [ pdfTextClipPath aload pop",
+ " {/moveto cvx}",
+ " {/lineto cvx}",
+ " {/curveto cvx}",
+ " {/closepath cvx}",
+ " pathforall ] def",
+ " currentpoint newpath moveto",
+ " } {",
+ " pop pop pop pop",
+ " } ifelse",
+ " 0 pdfTextRise neg pdfTextMat dtransform rmoveto",
+ "} def",
+ "/TJm { 0.001 mul pdfFontSize mul pdfHorizScaling mul neg 0",
+ " pdfTextMat dtransform rmoveto } def",
+ "/TJmV { 0.001 mul pdfFontSize mul neg 0 exch",
+ " pdfTextMat dtransform rmoveto } def",
+ "/Tclip { pdfTextClipPath cvx exec clip newpath",
+ " /pdfTextClipPath [] def } def",
+ "/Tclip* { pdfTextClipPath cvx exec eoclip newpath",
+ " /pdfTextClipPath [] def } def",
+ "~1ns",
+ "% Level 1 image operators",
+ "/pdfIm1 {",
+ " /pdfImBuf1 4 index string def",
+ " { currentfile pdfImBuf1 readhexstring pop } image",
+ "} def",
+ "/pdfIm1Bin {",
+ " /pdfImBuf1 4 index string def",
+ " { currentfile pdfImBuf1 readstring pop } image",
+ "} def",
+ "~1s",
+ "/pdfIm1Sep {",
+ " /pdfImBuf1 4 index string def",
+ " /pdfImBuf2 4 index string def",
+ " /pdfImBuf3 4 index string def",
+ " /pdfImBuf4 4 index string def",
+ " { currentfile pdfImBuf1 readhexstring pop }",
+ " { currentfile pdfImBuf2 readhexstring pop }",
+ " { currentfile pdfImBuf3 readhexstring pop }",
+ " { currentfile pdfImBuf4 readhexstring pop }",
+ " true 4 colorimage",
+ "} def",
+ "/pdfIm1SepBin {",
+ " /pdfImBuf1 4 index string def",
+ " /pdfImBuf2 4 index string def",
+ " /pdfImBuf3 4 index string def",
+ " /pdfImBuf4 4 index string def",
+ " { currentfile pdfImBuf1 readstring pop }",
+ " { currentfile pdfImBuf2 readstring pop }",
+ " { currentfile pdfImBuf3 readstring pop }",
+ " { currentfile pdfImBuf4 readstring pop }",
+ " true 4 colorimage",
+ "} def",
+ "~1ns",
+ "/pdfImM1 {",
+ " fCol /pdfImBuf1 4 index 7 add 8 idiv string def",
+ " { currentfile pdfImBuf1 readhexstring pop } imagemask",
+ "} def",
+ "/pdfImM1Bin {",
+ " fCol /pdfImBuf1 4 index 7 add 8 idiv string def",
+ " { currentfile pdfImBuf1 readstring pop } imagemask",
+ "} def",
+ "/pdfImStr {",
+ " 2 copy exch length lt {",
+ " 2 copy get exch 1 add exch",
+ " } {",
+ " ()",
+ " } ifelse",
+ "} def",
+ "/pdfImM1a {",
+ " { pdfImStr } imagemask",
+ " pop pop",
+ "} def",
+ "~23sn",
+ "% Level 2/3 image operators",
+ "/pdfImBuf 100 string def",
+ "/pdfImStr {",
+ " 2 copy exch length lt {",
+ " 2 copy get exch 1 add exch",
+ " } {",
+ " ()",
+ " } ifelse",
+ "} def",
+ "/skipEOD {",
+ " { currentfile pdfImBuf readline",
+ " not { pop exit } if",
+ " (%-EOD-) eq { exit } if } loop",
+ "} def",
+ "/pdfIm { image skipEOD } def",
+ "~3sn",
+ "/pdfMask {",
+ " /ReusableStreamDecode filter",
+ " skipEOD",
+ " /maskStream exch def",
+ "} def",
+ "/pdfMaskEnd { maskStream closefile } def",
+ "/pdfMaskInit {",
+ " /maskArray exch def",
+ " /maskIdx 0 def",
+ "} def",
+ "/pdfMaskSrc {",
+ " maskIdx maskArray length lt {",
+ " maskArray maskIdx get",
+ " /maskIdx maskIdx 1 add def",
+ " } {",
+ " ()",
+ " } ifelse",
+ "} def",
+ "~23s",
+ "/pdfImSep {",
+ " findcmykcustomcolor exch",
+ " dup /Width get /pdfImBuf1 exch string def",
+ " dup /Decode get aload pop 1 index sub /pdfImDecodeRange exch def",
+ " /pdfImDecodeLow exch def",
+ " begin Width Height BitsPerComponent ImageMatrix DataSource end",
+ " /pdfImData exch def",
+ " { pdfImData pdfImBuf1 readstring pop",
+ " 0 1 2 index length 1 sub {",
+ " 1 index exch 2 copy get",
+ " pdfImDecodeRange mul 255 div pdfImDecodeLow add round cvi",
+ " 255 exch sub put",
+ " } for }",
+ " 6 5 roll customcolorimage",
+ " skipEOD",
+ "} def",
+ "~23sn",
+ "/pdfImM { fCol imagemask skipEOD } def",
+ "~123sn",
+ "/pr { 2 index 2 index 3 2 roll putinterval 4 add } def",
+ "/pdfImClip {",
+ " gsave",
+ " 0 2 4 index length 1 sub {",
+ " dup 4 index exch 2 copy",
+ " get 5 index div put",
+ " 1 add 3 index exch 2 copy",
+ " get 3 index div put",
+ " } for",
+ " pop pop rectclip",
+ "} def",
+ "/pdfImClipEnd { grestore } def",
+ "~23sn",
+ "% shading operators",
+ "/colordelta {",
+ " false 0 1 3 index length 1 sub {",
+ " dup 4 index exch get 3 index 3 2 roll get sub abs 0.004 gt {",
+ " pop true",
+ " } if",
+ " } for",
+ " exch pop exch pop",
+ "} def",
+ "/funcCol { func n array astore } def",
+ "/funcSH {",
+ " dup 0 eq {",
+ " true",
+ " } {",
+ " dup 6 eq {",
+ " false",
+ " } {",
+ " 4 index 4 index funcCol dup",
+ " 6 index 4 index funcCol dup",
+ " 3 1 roll colordelta 3 1 roll",
+ " 5 index 5 index funcCol dup",
+ " 3 1 roll colordelta 3 1 roll",
+ " 6 index 8 index funcCol dup",
+ " 3 1 roll colordelta 3 1 roll",
+ " colordelta or or or",
+ " } ifelse",
+ " } ifelse",
+ " {",
+ " 1 add",
+ " 4 index 3 index add 0.5 mul exch 4 index 3 index add 0.5 mul exch",
+ " 6 index 6 index 4 index 4 index 4 index funcSH",
+ " 2 index 6 index 6 index 4 index 4 index funcSH",
+ " 6 index 2 index 4 index 6 index 4 index funcSH",
+ " 5 3 roll 3 2 roll funcSH pop pop",
+ " } {",
+ " pop 3 index 2 index add 0.5 mul 3 index 2 index add 0.5 mul",
+ "~23n",
+ " funcCol sc",
+ "~23s",
+ " funcCol aload pop k",
+ "~23sn",
+ " dup 4 index exch mat transform m",
+ " 3 index 3 index mat transform l",
+ " 1 index 3 index mat transform l",
+ " mat transform l pop pop h f*",
+ " } ifelse",
+ "} def",
+ "/axialCol {",
+ " dup 0 lt {",
+ " pop t0",
+ " } {",
+ " dup 1 gt {",
+ " pop t1",
+ " } {",
+ " dt mul t0 add",
+ " } ifelse",
+ " } ifelse",
+ " func n array astore",
+ "} def",
+ "/axialSH {",
+ " dup 0 eq {",
+ " true",
+ " } {",
+ " dup 8 eq {",
+ " false",
+ " } {",
+ " 2 index axialCol 2 index axialCol colordelta",
+ " } ifelse",
+ " } ifelse",
+ " {",
+ " 1 add 3 1 roll 2 copy add 0.5 mul",
+ " dup 4 3 roll exch 4 index axialSH",
+ " exch 3 2 roll axialSH",
+ " } {",
+ " pop 2 copy add 0.5 mul",
+ "~23n",
+ " axialCol sc",
+ "~23s",
+ " axialCol aload pop k",
+ "~23sn",
+ " exch dup dx mul x0 add exch dy mul y0 add",
+ " 3 2 roll dup dx mul x0 add exch dy mul y0 add",
+ " dx abs dy abs ge {",
+ " 2 copy yMin sub dy mul dx div add yMin m",
+ " yMax sub dy mul dx div add yMax l",
+ " 2 copy yMax sub dy mul dx div add yMax l",
+ " yMin sub dy mul dx div add yMin l",
+ " h f*",
+ " } {",
+ " exch 2 copy xMin sub dx mul dy div add xMin exch m",
+ " xMax sub dx mul dy div add xMax exch l",
+ " exch 2 copy xMax sub dx mul dy div add xMax exch l",
+ " xMin sub dx mul dy div add xMin exch l",
+ " h f*",
+ " } ifelse",
+ " } ifelse",
+ "} def",
+ "/radialCol {",
+ " dup t0 lt {",
+ " pop t0",
+ " } {",
+ " dup t1 gt {",
+ " pop t1",
+ " } if",
+ " } ifelse",
+ " func n array astore",
+ "} def",
+ "/radialSH {",
+ " dup 0 eq {",
+ " true",
+ " } {",
+ " dup 8 eq {",
+ " false",
+ " } {",
+ " 2 index dt mul t0 add radialCol",
+ " 2 index dt mul t0 add radialCol colordelta",
+ " } ifelse",
+ " } ifelse",
+ " {",
+ " 1 add 3 1 roll 2 copy add 0.5 mul",
+ " dup 4 3 roll exch 4 index radialSH",
+ " exch 3 2 roll radialSH",
+ " } {",
+ " pop 2 copy add 0.5 mul dt mul t0 add",
+ "~23n",
+ " radialCol sc",
+ "~23s",
+ " radialCol aload pop k",
+ "~23sn",
+ " encl {",
+ " exch dup dx mul x0 add exch dup dy mul y0 add exch dr mul r0 add",
+ " 0 360 arc h",
+ " dup dx mul x0 add exch dup dy mul y0 add exch dr mul r0 add",
+ " 360 0 arcn h f",
+ " } {",
+ " 2 copy",
+ " dup dx mul x0 add exch dup dy mul y0 add exch dr mul r0 add",
+ " a1 a2 arcn",
+ " dup dx mul x0 add exch dup dy mul y0 add exch dr mul r0 add",
+ " a2 a1 arcn h",
+ " dup dx mul x0 add exch dup dy mul y0 add exch dr mul r0 add",
+ " a1 a2 arc",
+ " dup dx mul x0 add exch dup dy mul y0 add exch dr mul r0 add",
+ " a2 a1 arc h f",
+ " } ifelse",
+ " } ifelse",
+ "} def",
+ "~123sn",
+ "end",
+ nullptr };
+
+static const char *cmapProlog[] = { "/CIDInit /ProcSet findresource begin",
+ "10 dict begin",
+ " begincmap",
+ " /CMapType 1 def",
+ " /CMapName /Identity-H def",
+ " /CIDSystemInfo 3 dict dup begin",
+ " /Registry (Adobe) def",
+ " /Ordering (Identity) def",
+ " /Supplement 0 def",
+ " end def",
+ " 1 begincodespacerange",
+ " <0000> <ffff>",
+ " endcodespacerange",
+ " 0 usefont",
+ " 1 begincidrange",
+ " <0000> <ffff> 0",
+ " endcidrange",
+ " endcmap",
+ " currentdict CMapName exch /CMap defineresource pop",
+ "end",
+ "10 dict begin",
+ " begincmap",
+ " /CMapType 1 def",
+ " /CMapName /Identity-V def",
+ " /CIDSystemInfo 3 dict dup begin",
+ " /Registry (Adobe) def",
+ " /Ordering (Identity) def",
+ " /Supplement 0 def",
+ " end def",
+ " /WMode 1 def",
+ " 1 begincodespacerange",
+ " <0000> <ffff>",
+ " endcodespacerange",
+ " 0 usefont",
+ " 1 begincidrange",
+ " <0000> <ffff> 0",
+ " endcidrange",
+ " endcmap",
+ " currentdict CMapName exch /CMap defineresource pop",
+ "end",
+ "end",
+ nullptr };
//------------------------------------------------------------------------
// Fonts
//------------------------------------------------------------------------
-struct PSSubstFont {
- const char *psName; // PostScript name
- double mWidth; // width of 'm' character
+struct PSSubstFont
+{
+ const char *psName; // PostScript name
+ double mWidth; // width of 'm' character
};
// NB: must be in same order as base14SubstFonts in GfxFont.cc
-static const PSSubstFont psBase14SubstFonts[14] = {
- {"Courier", 0.600},
- {"Courier-Oblique", 0.600},
- {"Courier-Bold", 0.600},
- {"Courier-BoldOblique", 0.600},
- {"Helvetica", 0.833},
- {"Helvetica-Oblique", 0.833},
- {"Helvetica-Bold", 0.889},
- {"Helvetica-BoldOblique", 0.889},
- {"Times-Roman", 0.788},
- {"Times-Italic", 0.722},
- {"Times-Bold", 0.833},
- {"Times-BoldItalic", 0.778},
- // the last two are never used for substitution
- {"Symbol", 0},
- {"ZapfDingbats", 0}
-};
+static const PSSubstFont psBase14SubstFonts[14] = { { "Courier", 0.600 },
+ { "Courier-Oblique", 0.600 },
+ { "Courier-Bold", 0.600 },
+ { "Courier-BoldOblique", 0.600 },
+ { "Helvetica", 0.833 },
+ { "Helvetica-Oblique", 0.833 },
+ { "Helvetica-Bold", 0.889 },
+ { "Helvetica-BoldOblique", 0.889 },
+ { "Times-Roman", 0.788 },
+ { "Times-Italic", 0.722 },
+ { "Times-Bold", 0.833 },
+ { "Times-BoldItalic", 0.778 },
+ // the last two are never used for substitution
+ { "Symbol", 0 },
+ { "ZapfDingbats", 0 } };
// Mapping from Type 1/1C font file to PS font name.
-struct PST1FontName {
- Ref fontFileID;
- GooString *psName; // PostScript font name used for this
- // embedded font file
+struct PST1FontName
+{
+ Ref fontFileID;
+ GooString *psName; // PostScript font name used for this
+ // embedded font file
};
// Info for 8-bit fonts
-struct PSFont8Info {
- Ref fontID;
- int *codeToGID; // code-to-GID mapping for TrueType fonts
+struct PSFont8Info
+{
+ Ref fontID;
+ int *codeToGID; // code-to-GID mapping for TrueType fonts
};
// Encoding info for substitute 16-bit font
-struct PSFont16Enc {
- Ref fontID;
- GooString *enc;
+struct PSFont16Enc
+{
+ Ref fontID;
+ GooString *enc;
};
//------------------------------------------------------------------------
// process colors
//------------------------------------------------------------------------
-#define psProcessCyan 1
-#define psProcessMagenta 2
-#define psProcessYellow 4
-#define psProcessBlack 8
-#define psProcessCMYK 15
+#define psProcessCyan 1
+#define psProcessMagenta 2
+#define psProcessYellow 4
+#define psProcessBlack 8
+#define psProcessCMYK 15
//------------------------------------------------------------------------
// PSOutCustomColor
//------------------------------------------------------------------------
-class PSOutCustomColor {
+class PSOutCustomColor
+{
public:
+ PSOutCustomColor(double cA, double mA, double yA, double kA, GooString *nameA);
+ ~PSOutCustomColor();
- PSOutCustomColor(double cA, double mA,
- double yA, double kA, GooString *nameA);
- ~PSOutCustomColor();
+ PSOutCustomColor(const PSOutCustomColor &) = delete;
+ PSOutCustomColor &operator=(const PSOutCustomColor &) = delete;
- PSOutCustomColor(const PSOutCustomColor &) = delete;
- PSOutCustomColor& operator=(const PSOutCustomColor &) = delete;
-
- double c, m, y, k;
- GooString *name;
- PSOutCustomColor *next;
+ double c, m, y, k;
+ GooString *name;
+ PSOutCustomColor *next;
};
-PSOutCustomColor::PSOutCustomColor(double cA, double mA,
- double yA, double kA, GooString *nameA) {
- c = cA;
- m = mA;
- y = yA;
- k = kA;
- name = nameA;
- next = nullptr;
+PSOutCustomColor::PSOutCustomColor(double cA, double mA, double yA, double kA, GooString *nameA)
+{
+ c = cA;
+ m = mA;
+ y = yA;
+ k = kA;
+ name = nameA;
+ next = nullptr;
}
-PSOutCustomColor::~PSOutCustomColor() {
- delete name;
+PSOutCustomColor::~PSOutCustomColor()
+{
+ delete name;
}
//------------------------------------------------------------------------
-struct PSOutImgClipRect {
- int x0, x1, y0, y1;
+struct PSOutImgClipRect
+{
+ int x0, x1, y0, y1;
};
//------------------------------------------------------------------------
-struct PSOutPaperSize {
- PSOutPaperSize(GooString *nameA, int wA, int hA) { name = nameA; w = wA; h = hA; }
- ~PSOutPaperSize() { delete name; }
- PSOutPaperSize(const PSOutPaperSize &) = delete;
- PSOutPaperSize& operator=(const PSOutPaperSize &) = delete;
- GooString *name;
- int w, h;
+struct PSOutPaperSize
+{
+ PSOutPaperSize(GooString *nameA, int wA, int hA)
+ {
+ name = nameA;
+ w = wA;
+ h = hA;
+ }
+ ~PSOutPaperSize() { delete name; }
+ PSOutPaperSize(const PSOutPaperSize &) = delete;
+ PSOutPaperSize &operator=(const PSOutPaperSize &) = delete;
+ GooString *name;
+ int w, h;
};
//------------------------------------------------------------------------
// DeviceNRecoder
//------------------------------------------------------------------------
-class DeviceNRecoder: public FilterStream {
+class DeviceNRecoder : public FilterStream
+{
public:
-
- DeviceNRecoder(Stream *strA, int widthA, int heightA,
- GfxImageColorMap *colorMapA);
- ~DeviceNRecoder() override;
- StreamKind getKind() const override { return strWeird; }
- void reset() override;
- int getChar() override
- { return (bufIdx >= bufSize && !fillBuf()) ? EOF : buf[bufIdx++]; }
- int lookChar() override
- { return (bufIdx >= bufSize && !fillBuf()) ? EOF : buf[bufIdx]; }
- GooString *getPSFilter(int psLevel, const char *indent) override { return nullptr; }
- bool isBinary(bool last = true) override { return true; }
- bool isEncoder() override { return true; }
+ DeviceNRecoder(Stream *strA, int widthA, int heightA, GfxImageColorMap *colorMapA);
+ ~DeviceNRecoder() override;
+ StreamKind getKind() const override { return strWeird; }
+ void reset() override;
+ int getChar() override { return (bufIdx >= bufSize && !fillBuf()) ? EOF : buf[bufIdx++]; }
+ int lookChar() override { return (bufIdx >= bufSize && !fillBuf()) ? EOF : buf[bufIdx]; }
+ GooString *getPSFilter(int psLevel, const char *indent) override { return nullptr; }
+ bool isBinary(bool last = true) override { return true; }
+ bool isEncoder() override { return true; }
private:
-
- bool fillBuf();
-
- int width, height;
- GfxImageColorMap *colorMap;
- const Function *func;
- ImageStream *imgStr;
- int buf[gfxColorMaxComps];
- int pixelIdx;
- int bufIdx;
- int bufSize;
+ bool fillBuf();
+
+ int width, height;
+ GfxImageColorMap *colorMap;
+ const Function *func;
+ ImageStream *imgStr;
+ int buf[gfxColorMaxComps];
+ int pixelIdx;
+ int bufIdx;
+ int bufSize;
};
-DeviceNRecoder::DeviceNRecoder(Stream *strA, int widthA, int heightA,
- GfxImageColorMap *colorMapA):
- FilterStream(strA) {
- width = widthA;
- height = heightA;
- colorMap = colorMapA;
- imgStr = nullptr;
- pixelIdx = 0;
- bufIdx = gfxColorMaxComps;
- bufSize = ((GfxDeviceNColorSpace *)colorMap->getColorSpace())->
- getAlt()->getNComps();
- func = ((GfxDeviceNColorSpace *)colorMap->getColorSpace())->
- getTintTransformFunc();
+DeviceNRecoder::DeviceNRecoder(Stream *strA, int widthA, int heightA, GfxImageColorMap *colorMapA) : FilterStream(strA)
+{
+ width = widthA;
+ height = heightA;
+ colorMap = colorMapA;
+ imgStr = nullptr;
+ pixelIdx = 0;
+ bufIdx = gfxColorMaxComps;
+ bufSize = ((GfxDeviceNColorSpace *)colorMap->getColorSpace())->getAlt()->getNComps();
+ func = ((GfxDeviceNColorSpace *)colorMap->getColorSpace())->getTintTransformFunc();
}
-DeviceNRecoder::~DeviceNRecoder() {
- if (imgStr) {
- delete imgStr;
- }
- if (str->isEncoder()) {
- delete str;
- }
+DeviceNRecoder::~DeviceNRecoder()
+{
+ if (imgStr) {
+ delete imgStr;
+ }
+ if (str->isEncoder()) {
+ delete str;
+ }
}
-void DeviceNRecoder::reset() {
- imgStr = new ImageStream(str, width, colorMap->getNumPixelComps(),
- colorMap->getBits());
- imgStr->reset();
+void DeviceNRecoder::reset()
+{
+ imgStr = new ImageStream(str, width, colorMap->getNumPixelComps(), colorMap->getBits());
+ imgStr->reset();
}
-bool DeviceNRecoder::fillBuf() {
- unsigned char pixBuf[gfxColorMaxComps];
- GfxColor color;
- double x[gfxColorMaxComps], y[gfxColorMaxComps];
- int i;
+bool DeviceNRecoder::fillBuf()
+{
+ unsigned char pixBuf[gfxColorMaxComps];
+ GfxColor color;
+ double x[gfxColorMaxComps], y[gfxColorMaxComps];
+ int i;
- if (pixelIdx >= width * height) {
- return false;
- }
- imgStr->getPixel(pixBuf);
- colorMap->getColor(pixBuf, &color);
- for (i = 0;
- i < ((GfxDeviceNColorSpace *)colorMap->getColorSpace())->getNComps();
- ++i) {
- x[i] = colToDbl(color.c[i]);
- }
- func->transform(x, y);
- for (i = 0; i < bufSize; ++i) {
- buf[i] = (int)(y[i] * 255 + 0.5);
- }
- bufIdx = 0;
- ++pixelIdx;
- return true;
+ if (pixelIdx >= width * height) {
+ return false;
+ }
+ imgStr->getPixel(pixBuf);
+ colorMap->getColor(pixBuf, &color);
+ for (i = 0; i < ((GfxDeviceNColorSpace *)colorMap->getColorSpace())->getNComps(); ++i) {
+ x[i] = colToDbl(color.c[i]);
+ }
+ func->transform(x, y);
+ for (i = 0; i < bufSize; ++i) {
+ buf[i] = (int)(y[i] * 255 + 0.5);
+ }
+ bufIdx = 0;
+ ++pixelIdx;
+ return true;
}
//------------------------------------------------------------------------
@@ -1078,227 +1076,188 @@ extern "C" {
typedef void (*SignalFunc)(int);
}
-static void outputToFile(void *stream, const char *data, int len) {
- fwrite(data, 1, len, (FILE *)stream);
+static void outputToFile(void *stream, const char *data, int len)
+{
+ fwrite(data, 1, len, (FILE *)stream);
}
-PSOutputDev::PSOutputDev(const char *fileName, PDFDoc *docA,
- char *psTitleA,
- const std::vector<int> &pagesA, PSOutMode modeA,
- int paperWidthA, int paperHeightA,
- bool noCropA, bool duplexA,
- int imgLLXA, int imgLLYA, int imgURXA, int imgURYA,
- PSForceRasterize forceRasterizeA,
- bool manualCtrlA,
- PSOutCustomCodeCbk customCodeCbkA,
- void *customCodeCbkDataA) {
- FILE *f;
- PSFileType fileTypeA;
-
- underlayCbk = nullptr;
- underlayCbkData = nullptr;
- overlayCbk = nullptr;
- overlayCbkData = nullptr;
- customCodeCbk = customCodeCbkA;
- customCodeCbkData = customCodeCbkDataA;
-
- fontIDs = nullptr;
- t1FontNames = nullptr;
- font8Info = nullptr;
- font16Enc = nullptr;
- imgIDs = nullptr;
- formIDs = nullptr;
- paperSizes = nullptr;
- embFontList = nullptr;
- customColors = nullptr;
- haveTextClip = false;
- t3String = nullptr;
- forceRasterize = forceRasterizeA;
- psTitle = nullptr;
-
- // open file or pipe
- if (!strcmp(fileName, "-")) {
- fileTypeA = psStdout;
- f = stdout;
- } else if (fileName[0] == '|') {
- fileTypeA = psPipe;
+PSOutputDev::PSOutputDev(const char *fileName, PDFDoc *docA, char *psTitleA, const std::vector<int> &pagesA, PSOutMode modeA, int paperWidthA, int paperHeightA, bool noCropA, bool duplexA, int imgLLXA, int imgLLYA, int imgURXA, int imgURYA,
+ PSForceRasterize forceRasterizeA, bool manualCtrlA, PSOutCustomCodeCbk customCodeCbkA, void *customCodeCbkDataA)
+{
+ FILE *f;
+ PSFileType fileTypeA;
+
+ underlayCbk = nullptr;
+ underlayCbkData = nullptr;
+ overlayCbk = nullptr;
+ overlayCbkData = nullptr;
+ customCodeCbk = customCodeCbkA;
+ customCodeCbkData = customCodeCbkDataA;
+
+ fontIDs = nullptr;
+ t1FontNames = nullptr;
+ font8Info = nullptr;
+ font16Enc = nullptr;
+ imgIDs = nullptr;
+ formIDs = nullptr;
+ paperSizes = nullptr;
+ embFontList = nullptr;
+ customColors = nullptr;
+ haveTextClip = false;
+ t3String = nullptr;
+ forceRasterize = forceRasterizeA;
+ psTitle = nullptr;
+
+ // open file or pipe
+ if (!strcmp(fileName, "-")) {
+ fileTypeA = psStdout;
+ f = stdout;
+ } else if (fileName[0] == '|') {
+ fileTypeA = psPipe;
#ifdef HAVE_POPEN
-#ifndef _WIN32
- signal(SIGPIPE, (SignalFunc)SIG_IGN);
-#endif
- if (!(f = popen(fileName + 1, "w"))) {
- error(errIO, -1, "Couldn't run print command '{0:s}'", fileName);
- ok = false;
- return;
- }
+# ifndef _WIN32
+ signal(SIGPIPE, (SignalFunc)SIG_IGN);
+# endif
+ if (!(f = popen(fileName + 1, "w"))) {
+ error(errIO, -1, "Couldn't run print command '{0:s}'", fileName);
+ ok = false;
+ return;
+ }
#else
- error(errIO, -1, "Print commands are not supported ('{0:s}')", fileName);
- ok = false;
- return;
+ error(errIO, -1, "Print commands are not supported ('{0:s}')", fileName);
+ ok = false;
+ return;
#endif
- } else {
- fileTypeA = psFile;
- if (!(f = openFile(fileName, "w"))) {
- error(errIO, -1, "Couldn't open PostScript file '{0:s}'", fileName);
- ok = false;
- return;
- }
- }
-
- init(outputToFile, f, fileTypeA, psTitleA,
- docA, pagesA, modeA,
- imgLLXA, imgLLYA, imgURXA, imgURYA, manualCtrlA,
- paperWidthA, paperHeightA, noCropA, duplexA);
+ } else {
+ fileTypeA = psFile;
+ if (!(f = openFile(fileName, "w"))) {
+ error(errIO, -1, "Couldn't open PostScript file '{0:s}'", fileName);
+ ok = false;
+ return;
+ }
+ }
+
+ init(outputToFile, f, fileTypeA, psTitleA, docA, pagesA, modeA, imgLLXA, imgLLYA, imgURXA, imgURYA, manualCtrlA, paperWidthA, paperHeightA, noCropA, duplexA);
}
-PSOutputDev::PSOutputDev(PSOutputFunc outputFuncA, void *outputStreamA,
- char *psTitleA,
- PDFDoc *docA,
- const std::vector<int> &pagesA, PSOutMode modeA,
- int paperWidthA, int paperHeightA,
- bool noCropA, bool duplexA,
- int imgLLXA, int imgLLYA, int imgURXA, int imgURYA,
- PSForceRasterize forceRasterizeA,
- bool manualCtrlA,
- PSOutCustomCodeCbk customCodeCbkA,
- void *customCodeCbkDataA) {
- underlayCbk = nullptr;
- underlayCbkData = nullptr;
- overlayCbk = nullptr;
- overlayCbkData = nullptr;
- customCodeCbk = customCodeCbkA;
- customCodeCbkData = customCodeCbkDataA;
-
- fontIDs = nullptr;
- t1FontNames = nullptr;
- font8Info = nullptr;
- font16Enc = nullptr;
- imgIDs = nullptr;
- formIDs = nullptr;
- paperSizes = nullptr;
- embFontList = nullptr;
- customColors = nullptr;
- haveTextClip = false;
- t3String = nullptr;
- forceRasterize = forceRasterizeA;
- psTitle = nullptr;
-
- init(outputFuncA, outputStreamA, psGeneric, psTitleA,
- docA, pagesA, modeA,
- imgLLXA, imgLLYA, imgURXA, imgURYA, manualCtrlA,
- paperWidthA, paperHeightA, noCropA, duplexA);
+PSOutputDev::PSOutputDev(PSOutputFunc outputFuncA, void *outputStreamA, char *psTitleA, PDFDoc *docA, const std::vector<int> &pagesA, PSOutMode modeA, int paperWidthA, int paperHeightA, bool noCropA, bool duplexA, int imgLLXA, int imgLLYA,
+ int imgURXA, int imgURYA, PSForceRasterize forceRasterizeA, bool manualCtrlA, PSOutCustomCodeCbk customCodeCbkA, void *customCodeCbkDataA)
+{
+ underlayCbk = nullptr;
+ underlayCbkData = nullptr;
+ overlayCbk = nullptr;
+ overlayCbkData = nullptr;
+ customCodeCbk = customCodeCbkA;
+ customCodeCbkData = customCodeCbkDataA;
+
+ fontIDs = nullptr;
+ t1FontNames = nullptr;
+ font8Info = nullptr;
+ font16Enc = nullptr;
+ imgIDs = nullptr;
+ formIDs = nullptr;
+ paperSizes = nullptr;
+ embFontList = nullptr;
+ customColors = nullptr;
+ haveTextClip = false;
+ t3String = nullptr;
+ forceRasterize = forceRasterizeA;
+ psTitle = nullptr;
+
+ init(outputFuncA, outputStreamA, psGeneric, psTitleA, docA, pagesA, modeA, imgLLXA, imgLLYA, imgURXA, imgURYA, manualCtrlA, paperWidthA, paperHeightA, noCropA, duplexA);
}
-struct StandardMedia {
+struct StandardMedia
+{
const char *name;
int width;
int height;
};
-static const StandardMedia standardMedia[] =
-{
- { "A0", 2384, 3371 },
- { "A1", 1685, 2384 },
- { "A2", 1190, 1684 },
- { "A3", 842, 1190 },
- { "A4", 595, 842 },
- { "A5", 420, 595 },
- { "B4", 729, 1032 },
- { "B5", 516, 729 },
- { "Letter", 612, 792 },
- { "Tabloid", 792, 1224 },
- { "Ledger", 1224, 792 },
- { "Legal", 612, 1008 },
- { "Statement", 396, 612 },
- { "Executive", 540, 720 },
- { "Folio", 612, 936 },
- { "Quarto", 610, 780 },
- { "10x14", 720, 1008 },
- { nullptr, 0, 0 }
-};
+static const StandardMedia standardMedia[] = { { "A0", 2384, 3371 }, { "A1", 1685, 2384 }, { "A2", 1190, 1684 }, { "A3", 842, 1190 }, { "A4", 595, 842 }, { "A5", 420, 595 },
+ { "B4", 729, 1032 }, { "B5", 516, 729 }, { "Letter", 612, 792 }, { "Tabloid", 792, 1224 }, { "Ledger", 1224, 792 }, { "Legal", 612, 1008 },
+ { "Statement", 396, 612 }, { "Executive", 540, 720 }, { "Folio", 612, 936 }, { "Quarto", 610, 780 }, { "10x14", 720, 1008 }, { nullptr, 0, 0 } };
/* PLRM specifies a tolerance of 5 points when matching page sizes */
-static bool pageDimensionEqual(int a, int b) {
- return (abs (a - b) < 5);
+static bool pageDimensionEqual(int a, int b)
+{
+ return (abs(a - b) < 5);
}
// Shared initialization of PSOutputDev members.
// Store the values but do not process them so the function that
// created the PSOutputDev can use the various setters to change defaults.
-void PSOutputDev::init(PSOutputFunc outputFuncA, void *outputStreamA,
- PSFileType fileTypeA, char *psTitleA, PDFDoc *docA,
- const std::vector<int> &pagesA, PSOutMode modeA,
- int imgLLXA, int imgLLYA, int imgURXA, int imgURYA,
- bool manualCtrlA, int paperWidthA, int paperHeightA,
- bool noCropA, bool duplexA) {
-
- if (pagesA.empty()) {
- ok = false;
- return;
- }
-
- // initialize
- postInitDone = false;
- embedType1 = true;
- embedTrueType = true;
- embedCIDPostScript = true;
- embedCIDTrueType = true;
- fontPassthrough = false;
- optimizeColorSpace = false;
- passLevel1CustomColor = false;
- preloadImagesForms = false;
- generateOPI = false;
- useASCIIHex = false;
- useBinary = false;
- enableLZW = true;
- enableFlate = true;
- rasterMono = false;
- rasterResolution = 300;
- uncompressPreloadedImages = false;
- psCenter = true;
- rasterAntialias = false;
- displayText = true;
- ok = true;
- outputFunc = outputFuncA;
- outputStream = outputStreamA;
- fileType = fileTypeA;
- psTitle = (psTitleA? strdup(psTitleA): nullptr);
- doc = docA;
- level = globalParams->getPSLevel();
- pages = pagesA;
- mode = modeA;
- paperWidth = paperWidthA;
- paperHeight = paperHeightA;
- noCrop = noCropA;
- duplex = duplexA;
- imgLLX = imgLLXA;
- imgLLY = imgLLYA;
- imgURX = imgURXA;
- imgURY = imgURYA;
- manualCtrl = manualCtrlA;
-
- xref = nullptr;
-
- processColors = 0;
- inType3Char = false;
- inUncoloredPattern = false;
- t3FillColorOnly = false;
+void PSOutputDev::init(PSOutputFunc outputFuncA, void *outputStreamA, PSFileType fileTypeA, char *psTitleA, PDFDoc *docA, const std::vector<int> &pagesA, PSOutMode modeA, int imgLLXA, int imgLLYA, int imgURXA, int imgURYA, bool manualCtrlA,
+ int paperWidthA, int paperHeightA, bool noCropA, bool duplexA)
+{
+
+ if (pagesA.empty()) {
+ ok = false;
+ return;
+ }
+
+ // initialize
+ postInitDone = false;
+ embedType1 = true;
+ embedTrueType = true;
+ embedCIDPostScript = true;
+ embedCIDTrueType = true;
+ fontPassthrough = false;
+ optimizeColorSpace = false;
+ passLevel1CustomColor = false;
+ preloadImagesForms = false;
+ generateOPI = false;
+ useASCIIHex = false;
+ useBinary = false;
+ enableLZW = true;
+ enableFlate = true;
+ rasterMono = false;
+ rasterResolution = 300;
+ uncompressPreloadedImages = false;
+ psCenter = true;
+ rasterAntialias = false;
+ displayText = true;
+ ok = true;
+ outputFunc = outputFuncA;
+ outputStream = outputStreamA;
+ fileType = fileTypeA;
+ psTitle = (psTitleA ? strdup(psTitleA) : nullptr);
+ doc = docA;
+ level = globalParams->getPSLevel();
+ pages = pagesA;
+ mode = modeA;
+ paperWidth = paperWidthA;
+ paperHeight = paperHeightA;
+ noCrop = noCropA;
+ duplex = duplexA;
+ imgLLX = imgLLXA;
+ imgLLY = imgLLYA;
+ imgURX = imgURXA;
+ imgURY = imgURYA;
+ manualCtrl = manualCtrlA;
+
+ xref = nullptr;
+
+ processColors = 0;
+ inType3Char = false;
+ inUncoloredPattern = false;
+ t3FillColorOnly = false;
#ifdef OPI_SUPPORT
- // initialize OPI nesting levels
- opi13Nest = 0;
- opi20Nest = 0;
+ // initialize OPI nesting levels
+ opi13Nest = 0;
+ opi20Nest = 0;
#endif
- tx0 = ty0 = -1;
- xScale0 = yScale0 = 0;
- rotate0 = -1;
- clipLLX0 = clipLLY0 = 0;
- clipURX0 = clipURY0 = -1;
+ tx0 = ty0 = -1;
+ xScale0 = yScale0 = 0;
+ rotate0 = -1;
+ clipLLX0 = clipLLY0 = 0;
+ clipURX0 = clipURY0 = -1;
- // initialize sequential page number
- seqPage = 1;
+ // initialize sequential page number
+ seqPage = 1;
}
// Complete the initialization after the function that created the PSOutputDev
@@ -1306,6448 +1265,6133 @@ void PSOutputDev::init(PSOutputFunc outputFuncA, void *outputStreamA,
void PSOutputDev::postInit()
{
- Catalog *catalog;
- PDFRectangle *box;
- PSOutPaperSize *size;
- int w, h, i;
-
- if (postInitDone || !ok) {
- return;
- }
-
- postInitDone = true;
-
- xref = doc->getXRef();
- catalog = doc->getCatalog();
-
- if (paperWidth < 0 || paperHeight < 0) {
- paperMatch = true;
- } else {
- paperMatch = false;
- }
-
- paperSizes = new std::vector<PSOutPaperSize*>();
- for (const int pg : pages) {
- Page *page = catalog->getPage(pg);
- if (page == nullptr)
- paperMatch = false;
- if (!paperMatch) {
- w = paperWidth;
- h = paperHeight;
- if (w < 0 || h < 0) {
- // Unable to obtain a paper size from the document and no page size
- // specified. In this case use A4 as the page size to ensure the PS output is
- // valid. This will only occur if the PDF is very broken.
- w = 595;
- h = 842;
- }
- } else if (noCrop) {
- w = (int)ceil(page->getMediaWidth());
- h = (int)ceil(page->getMediaHeight());
- } else {
- w = (int)ceil(page->getCropWidth());
- h = (int)ceil(page->getCropHeight());
- }
- if (paperMatch) {
- const int pageRotate = page->getRotate();
- if (pageRotate == 90 || pageRotate == 270)
- std::swap(w, h);
- }
- if (w > paperWidth)
- paperWidth = w;
- if (h > paperHeight)
- paperHeight = h;
- for (i = 0; i < (int)paperSizes->size(); ++i) {
- size = (*paperSizes)[i];
- if (pageDimensionEqual(w, size->w) && pageDimensionEqual(h, size->h))
- break;
+ Catalog *catalog;
+ PDFRectangle *box;
+ PSOutPaperSize *size;
+ int w, h, i;
+
+ if (postInitDone || !ok) {
+ return;
}
- if (i == (int)paperSizes->size()) {
- const StandardMedia *media = standardMedia;
- GooString *name = nullptr;
- while (media->name) {
- if (pageDimensionEqual(w, media->width) && pageDimensionEqual(h, media->height)) {
- name = new GooString(media->name);
- w = media->width;
- h = media->height;
- break;
- }
- media++;
- }
- if (!name)
- name = GooString::format("{0:d}x{1:d}mm", int(w*25.4/72), int(h*25.4/72));
- paperSizes->push_back(new PSOutPaperSize(name, w, h));
- }
- pagePaperSize.insert(std::pair<int,int>(pg, i));
- if (!paperMatch)
- break; // we only need one entry when all pages are the same size
- }
- if (imgLLX == 0 && imgURX == 0 && imgLLY == 0 && imgURY == 0) {
- imgLLX = imgLLY = 0;
- imgURX = paperWidth;
- imgURY = paperHeight;
- }
- std::vector<int> pageList;
- if (mode == psModeForm) {
- pageList.push_back(pages[0]);
- } else {
- pageList = pages;
- }
-
- // initialize fontIDs, fontFileIDs, and fontFileNames lists
- fontIDSize = 64;
- fontIDLen = 0;
- fontIDs = (Ref *)gmallocn(fontIDSize, sizeof(Ref));
- for (i = 0; i < 14; ++i) {
- fontNames.emplace(psBase14SubstFonts[i].psName);
- }
- t1FontNameSize = 64;
- t1FontNameLen = 0;
- t1FontNames = (PST1FontName *)gmallocn(t1FontNameSize, sizeof(PST1FontName));
- font8InfoLen = 0;
- font8InfoSize = 0;
- font16EncLen = 0;
- font16EncSize = 0;
- imgIDLen = 0;
- imgIDSize = 0;
- formIDLen = 0;
- formIDSize = 0;
-
- numSaves = 0;
- numTilingPatterns = 0;
- nextFunc = 0;
-
- // initialize embedded font resource comment list
- embFontList = new GooString();
-
- if (!manualCtrl) {
- Page *page;
- // this check is needed in case the document has zero pages
- if ((page = doc->getPage(pageList[0]))) {
- writeHeader(pageList.size(),
- page->getMediaBox(),
- page->getCropBox(),
- page->getRotate(),
- psTitle);
+
+ postInitDone = true;
+
+ xref = doc->getXRef();
+ catalog = doc->getCatalog();
+
+ if (paperWidth < 0 || paperHeight < 0) {
+ paperMatch = true;
} else {
- error(errSyntaxError, -1, "Invalid page {0:d}", pageList[0]);
- box = new PDFRectangle(0, 0, 1, 1);
- writeHeader(pageList.size(), box, box, 0, psTitle);
- delete box;
- }
- if (mode != psModeForm) {
- writePS("%%BeginProlog\n");
- }
- writeXpdfProcset();
- if (mode != psModeForm) {
- writePS("%%EndProlog\n");
- writePS("%%BeginSetup\n");
- }
- writeDocSetup(catalog, pageList, duplex);
- if (mode != psModeForm) {
- writePS("%%EndSetup\n");
+ paperMatch = false;
+ }
+
+ paperSizes = new std::vector<PSOutPaperSize *>();
+ for (const int pg : pages) {
+ Page *page = catalog->getPage(pg);
+ if (page == nullptr)
+ paperMatch = false;
+ if (!paperMatch) {
+ w = paperWidth;
+ h = paperHeight;
+ if (w < 0 || h < 0) {
+ // Unable to obtain a paper size from the document and no page size
+ // specified. In this case use A4 as the page size to ensure the PS output is
+ // valid. This will only occur if the PDF is very broken.
+ w = 595;
+ h = 842;
+ }
+ } else if (noCrop) {
+ w = (int)ceil(page->getMediaWidth());
+ h = (int)ceil(page->getMediaHeight());
+ } else {
+ w = (int)ceil(page->getCropWidth());
+ h = (int)ceil(page->getCropHeight());
+ }
+ if (paperMatch) {
+ const int pageRotate = page->getRotate();
+ if (pageRotate == 90 || pageRotate == 270)
+ std::swap(w, h);
+ }
+ if (w > paperWidth)
+ paperWidth = w;
+ if (h > paperHeight)
+ paperHeight = h;
+ for (i = 0; i < (int)paperSizes->size(); ++i) {
+ size = (*paperSizes)[i];
+ if (pageDimensionEqual(w, size->w) && pageDimensionEqual(h, size->h))
+ break;
+ }
+ if (i == (int)paperSizes->size()) {
+ const StandardMedia *media = standardMedia;
+ GooString *name = nullptr;
+ while (media->name) {
+ if (pageDimensionEqual(w, media->width) && pageDimensionEqual(h, media->height)) {
+ name = new GooString(media->name);
+ w = media->width;
+ h = media->height;
+ break;
+ }
+ media++;
+ }
+ if (!name)
+ name = GooString::format("{0:d}x{1:d}mm", int(w * 25.4 / 72), int(h * 25.4 / 72));
+ paperSizes->push_back(new PSOutPaperSize(name, w, h));
+ }
+ pagePaperSize.insert(std::pair<int, int>(pg, i));
+ if (!paperMatch)
+ break; // we only need one entry when all pages are the same size
+ }
+ if (imgLLX == 0 && imgURX == 0 && imgLLY == 0 && imgURY == 0) {
+ imgLLX = imgLLY = 0;
+ imgURX = paperWidth;
+ imgURY = paperHeight;
+ }
+ std::vector<int> pageList;
+ if (mode == psModeForm) {
+ pageList.push_back(pages[0]);
+ } else {
+ pageList = pages;
+ }
+
+ // initialize fontIDs, fontFileIDs, and fontFileNames lists
+ fontIDSize = 64;
+ fontIDLen = 0;
+ fontIDs = (Ref *)gmallocn(fontIDSize, sizeof(Ref));
+ for (i = 0; i < 14; ++i) {
+ fontNames.emplace(psBase14SubstFonts[i].psName);
+ }
+ t1FontNameSize = 64;
+ t1FontNameLen = 0;
+ t1FontNames = (PST1FontName *)gmallocn(t1FontNameSize, sizeof(PST1FontName));
+ font8InfoLen = 0;
+ font8InfoSize = 0;
+ font16EncLen = 0;
+ font16EncSize = 0;
+ imgIDLen = 0;
+ imgIDSize = 0;
+ formIDLen = 0;
+ formIDSize = 0;
+
+ numSaves = 0;
+ numTilingPatterns = 0;
+ nextFunc = 0;
+
+ // initialize embedded font resource comment list
+ embFontList = new GooString();
+
+ if (!manualCtrl) {
+ Page *page;
+ // this check is needed in case the document has zero pages
+ if ((page = doc->getPage(pageList[0]))) {
+ writeHeader(pageList.size(), page->getMediaBox(), page->getCropBox(), page->getRotate(), psTitle);
+ } else {
+ error(errSyntaxError, -1, "Invalid page {0:d}", pageList[0]);
+ box = new PDFRectangle(0, 0, 1, 1);
+ writeHeader(pageList.size(), box, box, 0, psTitle);
+ delete box;
+ }
+ if (mode != psModeForm) {
+ writePS("%%BeginProlog\n");
+ }
+ writeXpdfProcset();
+ if (mode != psModeForm) {
+ writePS("%%EndProlog\n");
+ writePS("%%BeginSetup\n");
+ }
+ writeDocSetup(catalog, pageList, duplex);
+ if (mode != psModeForm) {
+ writePS("%%EndSetup\n");
+ }
}
- }
}
-PSOutputDev::~PSOutputDev() {
- PSOutCustomColor *cc;
- int i;
+PSOutputDev::~PSOutputDev()
+{
+ PSOutCustomColor *cc;
+ int i;
- if (ok) {
- if (!postInitDone) {
- postInit();
+ if (ok) {
+ if (!postInitDone) {
+ postInit();
+ }
+ if (!manualCtrl) {
+ writePS("%%Trailer\n");
+ writeTrailer();
+ if (mode != psModeForm) {
+ writePS("%%EOF\n");
+ }
+ }
+ if (fileType == psFile) {
+ fclose((FILE *)outputStream);
+ }
+#ifdef HAVE_POPEN
+ else if (fileType == psPipe) {
+ pclose((FILE *)outputStream);
+# ifndef _WIN32
+ signal(SIGPIPE, (SignalFunc)SIG_DFL);
+# endif
+ }
+#endif
}
- if (!manualCtrl) {
- writePS("%%Trailer\n");
- writeTrailer();
- if (mode != psModeForm) {
- writePS("%%EOF\n");
- }
+ if (paperSizes) {
+ for (auto entry : *paperSizes) {
+ delete entry;
+ }
+ delete paperSizes;
}
- if (fileType == psFile) {
- fclose((FILE *)outputStream);
+ if (embFontList) {
+ delete embFontList;
}
-#ifdef HAVE_POPEN
- else if (fileType == psPipe) {
- pclose((FILE *)outputStream);
-#ifndef _WIN32
- signal(SIGPIPE, (SignalFunc)SIG_DFL);
-#endif
+ if (fontIDs) {
+ gfree(fontIDs);
}
-#endif
- }
- if (paperSizes) {
- for (auto entry : *paperSizes) {
- delete entry;
- }
- delete paperSizes;
- }
- if (embFontList) {
- delete embFontList;
- }
- if (fontIDs) {
- gfree(fontIDs);
- }
- if (t1FontNames) {
- for (i = 0; i < t1FontNameLen; ++i) {
- delete t1FontNames[i].psName;
- }
- gfree(t1FontNames);
- }
- if (font8Info) {
- for (i = 0; i < font8InfoLen; ++i) {
- gfree(font8Info[i].codeToGID);
- }
- gfree(font8Info);
- }
- if (font16Enc) {
- for (i = 0; i < font16EncLen; ++i) {
- if (font16Enc[i].enc) {
- delete font16Enc[i].enc;
- }
- }
- gfree(font16Enc);
- }
- gfree(imgIDs);
- gfree(formIDs);
- while (customColors) {
- cc = customColors;
- customColors = cc->next;
- delete cc;
- }
- gfree(psTitle);
+ if (t1FontNames) {
+ for (i = 0; i < t1FontNameLen; ++i) {
+ delete t1FontNames[i].psName;
+ }
+ gfree(t1FontNames);
+ }
+ if (font8Info) {
+ for (i = 0; i < font8InfoLen; ++i) {
+ gfree(font8Info[i].codeToGID);
+ }
+ gfree(font8Info);
+ }
+ if (font16Enc) {
+ for (i = 0; i < font16EncLen; ++i) {
+ if (font16Enc[i].enc) {
+ delete font16Enc[i].enc;
+ }
+ }
+ gfree(font16Enc);
+ }
+ gfree(imgIDs);
+ gfree(formIDs);
+ while (customColors) {
+ cc = customColors;
+ customColors = cc->next;
+ delete cc;
+ }
+ gfree(psTitle);
}
-void PSOutputDev::writeHeader(int nPages,
- const PDFRectangle *mediaBox, const PDFRectangle *cropBox,
- int pageRotate, const char *title) {
- PSOutPaperSize *size;
- double x1, y1, x2, y2;
+void PSOutputDev::writeHeader(int nPages, const PDFRectangle *mediaBox, const PDFRectangle *cropBox, int pageRotate, const char *title)
+{
+ PSOutPaperSize *size;
+ double x1, y1, x2, y2;
- switch (mode) {
- case psModePS:
- writePS("%!PS-Adobe-3.0\n");
- break;
- case psModeEPS:
- writePS("%!PS-Adobe-3.0 EPSF-3.0\n");
- break;
- case psModeForm:
- writePS("%!PS-Adobe-3.0 Resource-Form\n");
- break;
- }
- writePSFmt("%Produced by poppler pdftops version: {0:s} (http://poppler.freedesktop.org)\n", PACKAGE_VERSION);
- Object info = xref->getDocInfo();
- if (info.isDict()) {
- Object obj1 = info.dictLookup("Creator");
- if (obj1.isString()) {
- writePS("%%Creator: ");
- writePSTextLine(obj1.getString());
- }
- }
- if(title) {
- char *sanitizedTitle = strdup(title);
- for (size_t i = 0; i < strlen(sanitizedTitle); ++i) {
- if (sanitizedTitle[i] == '\n' || sanitizedTitle[i] == '\r') {
- sanitizedTitle[i] = ' ';
- }
- }
- writePSFmt("%%Title: {0:s}\n", sanitizedTitle);
- free(sanitizedTitle);
- }
- writePSFmt("%%LanguageLevel: {0:d}\n",
- (level == psLevel1 || level == psLevel1Sep) ? 1 :
- (level == psLevel2 || level == psLevel2Sep) ? 2 : 3);
- if (level == psLevel1Sep || level == psLevel2Sep || level == psLevel3Sep) {
- writePS("%%DocumentProcessColors: (atend)\n");
- writePS("%%DocumentCustomColors: (atend)\n");
- }
- writePS("%%DocumentSuppliedResources: (atend)\n");
- if ((level == psLevel1 || level == psLevel1Sep) && useBinary) {
- writePS("%%DocumentData: Binary\n");
- }
-
- switch (mode) {
- case psModePS:
- for (std::size_t i = 0; i < paperSizes->size(); ++i) {
- size = (*paperSizes)[i];
- writePSFmt("%%{0:s} {1:t} {2:d} {3:d} 0 () ()\n",
- i==0 ? "DocumentMedia:" : "+", size->name, size->w, size->h);
- }
- writePSFmt("%%BoundingBox: 0 0 {0:d} {1:d}\n", paperWidth, paperHeight);
- writePSFmt("%%Pages: {0:d}\n", nPages);
- writePS("%%EndComments\n");
- if (!paperMatch) {
- size = (*paperSizes)[0];
- writePS("%%BeginDefaults\n");
- writePSFmt("%%PageMedia: {0:t}\n", size->name);
- writePS("%%EndDefaults\n");
+ switch (mode) {
+ case psModePS:
+ writePS("%!PS-Adobe-3.0\n");
+ break;
+ case psModeEPS:
+ writePS("%!PS-Adobe-3.0 EPSF-3.0\n");
+ break;
+ case psModeForm:
+ writePS("%!PS-Adobe-3.0 Resource-Form\n");
+ break;
+ }
+ writePSFmt("%Produced by poppler pdftops version: {0:s} (http://poppler.freedesktop.org)\n", PACKAGE_VERSION);
+ Object info = xref->getDocInfo();
+ if (info.isDict()) {
+ Object obj1 = info.dictLookup("Creator");
+ if (obj1.isString()) {
+ writePS("%%Creator: ");
+ writePSTextLine(obj1.getString());
+ }
+ }
+ if (title) {
+ char *sanitizedTitle = strdup(title);
+ for (size_t i = 0; i < strlen(sanitizedTitle); ++i) {
+ if (sanitizedTitle[i] == '\n' || sanitizedTitle[i] == '\r') {
+ sanitizedTitle[i] = ' ';
+ }
+ }
+ writePSFmt("%%Title: {0:s}\n", sanitizedTitle);
+ free(sanitizedTitle);
+ }
+ writePSFmt("%%LanguageLevel: {0:d}\n", (level == psLevel1 || level == psLevel1Sep) ? 1 : (level == psLevel2 || level == psLevel2Sep) ? 2 : 3);
+ if (level == psLevel1Sep || level == psLevel2Sep || level == psLevel3Sep) {
+ writePS("%%DocumentProcessColors: (atend)\n");
+ writePS("%%DocumentCustomColors: (atend)\n");
}
- break;
- case psModeEPS:
- epsX1 = cropBox->x1;
- epsY1 = cropBox->y1;
- epsX2 = cropBox->x2;
- epsY2 = cropBox->y2;
- if (pageRotate == 0 || pageRotate == 180) {
- x1 = epsX1;
- y1 = epsY1;
- x2 = epsX2;
- y2 = epsY2;
- } else { // pageRotate == 90 || pageRotate == 270
- x1 = 0;
- y1 = 0;
- x2 = epsY2 - epsY1;
- y2 = epsX2 - epsX1;
- }
- writePSFmt("%%BoundingBox: {0:d} {1:d} {2:d} {3:d}\n",
- (int)floor(x1), (int)floor(y1), (int)ceil(x2), (int)ceil(y2));
- writePSFmt("%%HiResBoundingBox: {0:.6g} {1:.6g} {2:.6g} {3:.6g}\n",
- x1, y1, x2, y2);
writePS("%%DocumentSuppliedResources: (atend)\n");
- writePS("%%EndComments\n");
- break;
- case psModeForm:
- writePS("%%EndComments\n");
- writePS("32 dict dup begin\n");
- writePSFmt("/BBox [{0:d} {1:d} {2:d} {3:d}] def\n",
- (int)floor(mediaBox->x1), (int)floor(mediaBox->y1),
- (int)ceil(mediaBox->x2), (int)ceil(mediaBox->y2));
- writePS("/FormType 1 def\n");
- writePS("/Matrix [1 0 0 1 0 0] def\n");
- break;
- }
+ if ((level == psLevel1 || level == psLevel1Sep) && useBinary) {
+ writePS("%%DocumentData: Binary\n");
+ }
+
+ switch (mode) {
+ case psModePS:
+ for (std::size_t i = 0; i < paperSizes->size(); ++i) {
+ size = (*paperSizes)[i];
+ writePSFmt("%%{0:s} {1:t} {2:d} {3:d} 0 () ()\n", i == 0 ? "DocumentMedia:" : "+", size->name, size->w, size->h);
+ }
+ writePSFmt("%%BoundingBox: 0 0 {0:d} {1:d}\n", paperWidth, paperHeight);
+ writePSFmt("%%Pages: {0:d}\n", nPages);
+ writePS("%%EndComments\n");
+ if (!paperMatch) {
+ size = (*paperSizes)[0];
+ writePS("%%BeginDefaults\n");
+ writePSFmt("%%PageMedia: {0:t}\n", size->name);
+ writePS("%%EndDefaults\n");
+ }
+ break;
+ case psModeEPS:
+ epsX1 = cropBox->x1;
+ epsY1 = cropBox->y1;
+ epsX2 = cropBox->x2;
+ epsY2 = cropBox->y2;
+ if (pageRotate == 0 || pageRotate == 180) {
+ x1 = epsX1;
+ y1 = epsY1;
+ x2 = epsX2;
+ y2 = epsY2;
+ } else { // pageRotate == 90 || pageRotate == 270
+ x1 = 0;
+ y1 = 0;
+ x2 = epsY2 - epsY1;
+ y2 = epsX2 - epsX1;
+ }
+ writePSFmt("%%BoundingBox: {0:d} {1:d} {2:d} {3:d}\n", (int)floor(x1), (int)floor(y1), (int)ceil(x2), (int)ceil(y2));
+ writePSFmt("%%HiResBoundingBox: {0:.6g} {1:.6g} {2:.6g} {3:.6g}\n", x1, y1, x2, y2);
+ writePS("%%DocumentSuppliedResources: (atend)\n");
+ writePS("%%EndComments\n");
+ break;
+ case psModeForm:
+ writePS("%%EndComments\n");
+ writePS("32 dict dup begin\n");
+ writePSFmt("/BBox [{0:d} {1:d} {2:d} {3:d}] def\n", (int)floor(mediaBox->x1), (int)floor(mediaBox->y1), (int)ceil(mediaBox->x2), (int)ceil(mediaBox->y2));
+ writePS("/FormType 1 def\n");
+ writePS("/Matrix [1 0 0 1 0 0] def\n");
+ break;
+ }
}
-void PSOutputDev::writeXpdfProcset() {
- bool lev1, lev2, lev3, sep, nonSep;
- const char **p;
- const char *q;
-
- writePSFmt("%%BeginResource: procset xpdf {0:s} 0\n", "3.00");
- writePSFmt("%%Copyright: {0:s}\n", xpdfCopyright);
- lev1 = lev2 = lev3 = sep = nonSep = true;
- for (p = prolog; *p; ++p) {
- if ((*p)[0] == '~') {
- lev1 = lev2 = lev3 = sep = nonSep = false;
- for (q = *p + 1; *q; ++q) {
- switch (*q) {
- case '1': lev1 = true; break;
- case '2': lev2 = true; break;
- case '3': lev3 = true; break;
- case 's': sep = true; break;
- case 'n': nonSep = true; break;
- }
- }
- } else if ((level == psLevel1 && lev1 && nonSep) ||
- (level == psLevel1Sep && lev1 && sep) ||
- (level == psLevel1Sep && lev2 && sep && getPassLevel1CustomColor()) ||
- (level == psLevel2 && lev2 && nonSep) ||
- (level == psLevel2Sep && lev2 && sep) ||
- (level == psLevel3 && lev3 && nonSep) ||
- (level == psLevel3Sep && lev3 && sep)) {
- writePSFmt("{0:s}\n", *p);
- }
- }
- writePS("%%EndResource\n");
-
- if (level >= psLevel3) {
- for (p = cmapProlog; *p; ++p) {
- writePSFmt("{0:s}\n", *p);
- }
- }
+void PSOutputDev::writeXpdfProcset()
+{
+ bool lev1, lev2, lev3, sep, nonSep;
+ const char **p;
+ const char *q;
+
+ writePSFmt("%%BeginResource: procset xpdf {0:s} 0\n", "3.00");
+ writePSFmt("%%Copyright: {0:s}\n", xpdfCopyright);
+ lev1 = lev2 = lev3 = sep = nonSep = true;
+ for (p = prolog; *p; ++p) {
+ if ((*p)[0] == '~') {
+ lev1 = lev2 = lev3 = sep = nonSep = false;
+ for (q = *p + 1; *q; ++q) {
+ switch (*q) {
+ case '1':
+ lev1 = true;
+ break;
+ case '2':
+ lev2 = true;
+ break;
+ case '3':
+ lev3 = true;
+ break;
+ case 's':
+ sep = true;
+ break;
+ case 'n':
+ nonSep = true;
+ break;
+ }
+ }
+ } else if ((level == psLevel1 && lev1 && nonSep) || (level == psLevel1Sep && lev1 && sep) || (level == psLevel1Sep && lev2 && sep && getPassLevel1CustomColor()) || (level == psLevel2 && lev2 && nonSep)
+ || (level == psLevel2Sep && lev2 && sep) || (level == psLevel3 && lev3 && nonSep) || (level == psLevel3Sep && lev3 && sep)) {
+ writePSFmt("{0:s}\n", *p);
+ }
+ }
+ writePS("%%EndResource\n");
+
+ if (level >= psLevel3) {
+ for (p = cmapProlog; *p; ++p) {
+ writePSFmt("{0:s}\n", *p);
+ }
+ }
}
-void PSOutputDev::writeDocSetup(Catalog *catalog,
- const std::vector<int> &pageList,
- bool duplexA) {
- Page *page;
- Dict *resDict;
- Annots *annots;
- Object *acroForm;
- GooString *s;
-
- if (mode == psModeForm) {
- // swap the form and xpdf dicts
- writePS("xpdf end begin dup begin\n");
- } else {
- writePS("xpdf begin\n");
- }
- for (const int pg : pageList) {
- page = doc->getPage(pg);
- if (!page) {
- error(errSyntaxError, -1, "Failed writing resources for page {0:d}", pg);
- continue;
- }
- if ((resDict = page->getResourceDict())) {
- setupResources(resDict);
- }
- annots = page->getAnnots();
- for (int i = 0; i < annots->getNumAnnots(); ++i) {
- Object obj1 = annots->getAnnot(i)->getAppearanceResDict();
- if (obj1.isDict()) {
- setupResources(obj1.getDict());
- }
- }
- }
- if ((acroForm = catalog->getAcroForm()) && acroForm->isDict()) {
- Object obj1 = acroForm->dictLookup("DR");
- if (obj1.isDict()) {
- setupResources(obj1.getDict());
- }
- obj1 = acroForm->dictLookup("Fields");
- if (obj1.isArray()) {
- for (int i = 0; i < obj1.arrayGetLength(); ++i) {
- Object obj2 = obj1.arrayGet(i);
- if (obj2.isDict()) {
- Object obj3 = obj2.dictLookup("DR");
- if (obj3.isDict()) {
- setupResources(obj3.getDict());
- }
- }
- }
- }
- }
- if (mode != psModeForm) {
- if (mode != psModeEPS && !manualCtrl) {
- writePSFmt("{0:s} pdfSetup\n",
- duplexA ? "true" : "false");
- if (!paperMatch) {
- writePSFmt("{0:d} {1:d} pdfSetupPaper\n", paperWidth, paperHeight);
- }
+void PSOutputDev::writeDocSetup(Catalog *catalog, const std::vector<int> &pageList, bool duplexA)
+{
+ Page *page;
+ Dict *resDict;
+ Annots *annots;
+ Object *acroForm;
+ GooString *s;
+
+ if (mode == psModeForm) {
+ // swap the form and xpdf dicts
+ writePS("xpdf end begin dup begin\n");
+ } else {
+ writePS("xpdf begin\n");
}
-#ifdef OPI_SUPPORT
- if (generateOPI) {
- writePS("/opiMatrix matrix currentmatrix def\n");
+ for (const int pg : pageList) {
+ page = doc->getPage(pg);
+ if (!page) {
+ error(errSyntaxError, -1, "Failed writing resources for page {0:d}", pg);
+ continue;
+ }
+ if ((resDict = page->getResourceDict())) {
+ setupResources(resDict);
+ }
+ annots = page->getAnnots();
+ for (int i = 0; i < annots->getNumAnnots(); ++i) {
+ Object obj1 = annots->getAnnot(i)->getAppearanceResDict();
+ if (obj1.isDict()) {
+ setupResources(obj1.getDict());
+ }
+ }
+ }
+ if ((acroForm = catalog->getAcroForm()) && acroForm->isDict()) {
+ Object obj1 = acroForm->dictLookup("DR");
+ if (obj1.isDict()) {
+ setupResources(obj1.getDict());
+ }
+ obj1 = acroForm->dictLookup("Fields");
+ if (obj1.isArray()) {
+ for (int i = 0; i < obj1.arrayGetLength(); ++i) {
+ Object obj2 = obj1.arrayGet(i);
+ if (obj2.isDict()) {
+ Object obj3 = obj2.dictLookup("DR");
+ if (obj3.isDict()) {
+ setupResources(obj3.getDict());
+ }
+ }
+ }
+ }
}
+ if (mode != psModeForm) {
+ if (mode != psModeEPS && !manualCtrl) {
+ writePSFmt("{0:s} pdfSetup\n", duplexA ? "true" : "false");
+ if (!paperMatch) {
+ writePSFmt("{0:d} {1:d} pdfSetupPaper\n", paperWidth, paperHeight);
+ }
+ }
+#ifdef OPI_SUPPORT
+ if (generateOPI) {
+ writePS("/opiMatrix matrix currentmatrix def\n");
+ }
#endif
- }
- if (customCodeCbk) {
- if ((s = (*customCodeCbk)(this, psOutCustomDocSetup, 0,
- customCodeCbkData))) {
- writePS(s->c_str());
- delete s;
- }
- }
+ }
+ if (customCodeCbk) {
+ if ((s = (*customCodeCbk)(this, psOutCustomDocSetup, 0, customCodeCbkData))) {
+ writePS(s->c_str());
+ delete s;
+ }
+ }
}
-void PSOutputDev::writePageTrailer() {
- if (mode != psModeForm) {
- writePS("pdfEndPage\n");
- }
+void PSOutputDev::writePageTrailer()
+{
+ if (mode != psModeForm) {
+ writePS("pdfEndPage\n");
+ }
}
-void PSOutputDev::writeTrailer() {
- PSOutCustomColor *cc;
+void PSOutputDev::writeTrailer()
+{
+ PSOutCustomColor *cc;
- if (mode == psModeForm) {
- writePS("/Foo exch /Form defineresource pop\n");
- } else {
- writePS("end\n");
- writePS("%%DocumentSuppliedResources:\n");
- writePS(embFontList->c_str());
- if (level == psLevel1Sep || level == psLevel2Sep ||
- level == psLevel3Sep) {
- writePS("%%DocumentProcessColors:");
- if (processColors & psProcessCyan) {
- writePS(" Cyan");
- }
- if (processColors & psProcessMagenta) {
- writePS(" Magenta");
- }
- if (processColors & psProcessYellow) {
- writePS(" Yellow");
- }
- if (processColors & psProcessBlack) {
- writePS(" Black");
- }
- writePS("\n");
- writePS("%%DocumentCustomColors:");
- for (cc = customColors; cc; cc = cc->next) {
- writePS(" ");
- writePSString(cc->name->toStr());
- }
- writePS("\n");
- writePS("%%CMYKCustomColor:\n");
- for (cc = customColors; cc; cc = cc->next) {
- writePSFmt("%%+ {0:.4g} {1:.4g} {2:.4g} {3:.4g} ",
- cc->c, cc->m, cc->y, cc->k);
- writePSString(cc->name->toStr());
- writePS("\n");
- }
- }
- }
+ if (mode == psModeForm) {
+ writePS("/Foo exch /Form defineresource pop\n");
+ } else {
+ writePS("end\n");
+ writePS("%%DocumentSuppliedResources:\n");
+ writePS(embFontList->c_str());
+ if (level == psLevel1Sep || level == psLevel2Sep || level == psLevel3Sep) {
+ writePS("%%DocumentProcessColors:");
+ if (processColors & psProcessCyan) {
+ writePS(" Cyan");
+ }
+ if (processColors & psProcessMagenta) {
+ writePS(" Magenta");
+ }
+ if (processColors & psProcessYellow) {
+ writePS(" Yellow");
+ }
+ if (processColors & psProcessBlack) {
+ writePS(" Black");
+ }
+ writePS("\n");
+ writePS("%%DocumentCustomColors:");
+ for (cc = customColors; cc; cc = cc->next) {
+ writePS(" ");
+ writePSString(cc->name->toStr());
+ }
+ writePS("\n");
+ writePS("%%CMYKCustomColor:\n");
+ for (cc = customColors; cc; cc = cc->next) {
+ writePSFmt("%%+ {0:.4g} {1:.4g} {2:.4g} {3:.4g} ", cc->c, cc->m, cc->y, cc->k);
+ writePSString(cc->name->toStr());
+ writePS("\n");
+ }
+ }
+ }
}
-void PSOutputDev::setupResources(Dict *resDict) {
- bool skip;
-
- setupFonts(resDict);
- setupImages(resDict);
- setupForms(resDict);
-
- //----- recursively scan XObjects
- Object xObjDict = resDict->lookup("XObject");
- if (xObjDict.isDict()) {
- for (int i = 0; i < xObjDict.dictGetLength(); ++i) {
-
- // avoid infinite recursion on XObjects
- skip = false;
- const Object &xObjRef = xObjDict.dictGetValNF(i);
- if (xObjRef.isRef()) {
- Ref ref0 = xObjRef.getRef();
- if (resourceIDs.find(ref0.num) != resourceIDs.end()) {
- skip = true;
- } else {
- resourceIDs.insert(ref0.num);
- }
- }
- if (!skip) {
-
- // process the XObject's resource dictionary
- Object xObj = xObjDict.dictGetVal(i);
- if (xObj.isStream()) {
- Object resObj = xObj.streamGetDict()->lookup("Resources");
- if (resObj.isDict()) {
- setupResources(resObj.getDict());
- }
- }
- }
- }
- }
-
- //----- recursively scan Patterns
- Object patDict = resDict->lookup("Pattern");
- if (patDict.isDict()) {
- inType3Char = true;
- for (int i = 0; i < patDict.dictGetLength(); ++i) {
-
- // avoid infinite recursion on Patterns
- skip = false;
- const Object &patRef = patDict.dictGetValNF(i);
- if (patRef.isRef()) {
- Ref ref0 = patRef.getRef();
- if (resourceIDs.find(ref0.num) != resourceIDs.end()) {
- skip = true;
- } else {
- resourceIDs.insert(ref0.num);
- }
- }
- if (!skip) {
-
- // process the Pattern's resource dictionary
- Object pat = patDict.dictGetVal(i);
- if (pat.isStream()) {
- Object resObj = pat.streamGetDict()->lookup("Resources");
- if (resObj.isDict()) {
- setupResources(resObj.getDict());
- }
- }
- }
+void PSOutputDev::setupResources(Dict *resDict)
+{
+ bool skip;
+
+ setupFonts(resDict);
+ setupImages(resDict);
+ setupForms(resDict);
+
+ //----- recursively scan XObjects
+ Object xObjDict = resDict->lookup("XObject");
+ if (xObjDict.isDict()) {
+ for (int i = 0; i < xObjDict.dictGetLength(); ++i) {
+
+ // avoid infinite recursion on XObjects
+ skip = false;
+ const Object &xObjRef = xObjDict.dictGetValNF(i);
+ if (xObjRef.isRef()) {
+ Ref ref0 = xObjRef.getRef();
+ if (resourceIDs.find(ref0.num) != resourceIDs.end()) {
+ skip = true;
+ } else {
+ resourceIDs.insert(ref0.num);
+ }
+ }
+ if (!skip) {
+
+ // process the XObject's resource dictionary
+ Object xObj = xObjDict.dictGetVal(i);
+ if (xObj.isStream()) {
+ Object resObj = xObj.streamGetDict()->lookup("Resources");
+ if (resObj.isDict()) {
+ setupResources(resObj.getDict());
+ }
+ }
+ }
+ }
+ }
+
+ //----- recursively scan Patterns
+ Object patDict = resDict->lookup("Pattern");
+ if (patDict.isDict()) {
+ inType3Char = true;
+ for (int i = 0; i < patDict.dictGetLength(); ++i) {
+
+ // avoid infinite recursion on Patterns
+ skip = false;
+ const Object &patRef = patDict.dictGetValNF(i);
+ if (patRef.isRef()) {
+ Ref ref0 = patRef.getRef();
+ if (resourceIDs.find(ref0.num) != resourceIDs.end()) {
+ skip = true;
+ } else {
+ resourceIDs.insert(ref0.num);
+ }
+ }
+ if (!skip) {
+
+ // process the Pattern's resource dictionary
+ Object pat = patDict.dictGetVal(i);
+ if (pat.isStream()) {
+ Object resObj = pat.streamGetDict()->lookup("Resources");
+ if (resObj.isDict()) {
+ setupResources(resObj.getDict());
+ }
+ }
+ }
+ }
+ inType3Char = false;
}
- inType3Char = false;
- }
}
-void PSOutputDev::setupFonts(Dict *resDict) {
- Ref r;
- GfxFontDict *gfxFontDict;
- GfxFont *font;
- int i;
-
- gfxFontDict = nullptr;
- const Object &obj1 = resDict->lookupNF("Font");
- if (obj1.isRef()) {
- Object obj2 = obj1.fetch(xref);
- if (obj2.isDict()) {
- r = obj1.getRef();
- gfxFontDict = new GfxFontDict(xref, &r, obj2.getDict());
- }
- } else if (obj1.isDict()) {
- gfxFontDict = new GfxFontDict(xref, nullptr, obj1.getDict());
- }
- if (gfxFontDict) {
- for (i = 0; i < gfxFontDict->getNumFonts(); ++i) {
- if ((font = gfxFontDict->getFont(i))) {
- setupFont(font, resDict);
- }
- }
- delete gfxFontDict;
- }
+void PSOutputDev::setupFonts(Dict *resDict)
+{
+ Ref r;
+ GfxFontDict *gfxFontDict;
+ GfxFont *font;
+ int i;
+
+ gfxFontDict = nullptr;
+ const Object &obj1 = resDict->lookupNF("Font");
+ if (obj1.isRef()) {
+ Object obj2 = obj1.fetch(xref);
+ if (obj2.isDict()) {
+ r = obj1.getRef();
+ gfxFontDict = new GfxFontDict(xref, &r, obj2.getDict());
+ }
+ } else if (obj1.isDict()) {
+ gfxFontDict = new GfxFontDict(xref, nullptr, obj1.getDict());
+ }
+ if (gfxFontDict) {
+ for (i = 0; i < gfxFontDict->getNumFonts(); ++i) {
+ if ((font = gfxFontDict->getFont(i))) {
+ setupFont(font, resDict);
+ }
+ }
+ delete gfxFontDict;
+ }
}
-void PSOutputDev::setupFont(GfxFont *font, Dict *parentResDict) {
- GfxFontLoc *fontLoc;
- GooString *psName;
- char buf[16];
- bool subst;
- const UnicodeMap *uMap;
- const char *charName;
- double xs, ys;
- int code;
- double w1, w2;
- int i, j;
-
- // check if font is already set up
- for (i = 0; i < fontIDLen; ++i) {
- if (fontIDs[i] == *font->getID()) {
- return;
- }
- }
-
- // add entry to fontIDs list
- if (fontIDLen >= fontIDSize) {
- fontIDSize += 64;
- fontIDs = (Ref *)greallocn(fontIDs, fontIDSize, sizeof(Ref));
- }
- fontIDs[fontIDLen++] = *font->getID();
-
- psName = nullptr;
- xs = ys = 1;
- subst = false;
-
- if (font->getType() == fontType3) {
- psName = GooString::format("T3_{0:d}_{1:d}",
- font->getID()->num, font->getID()->gen);
- setupType3Font(font, psName, parentResDict);
- } else {
- fontLoc = font->locateFont(xref, this);
- if (fontLoc != nullptr) {
- switch (fontLoc->locType) {
- case gfxFontLocEmbedded:
- switch (fontLoc->fontType) {
- case fontType1:
- // this assumes that the PS font name matches the PDF font name
- psName = font->getEmbeddedFontName() ? font->getEmbeddedFontName()->copy() : new GooString();
- setupEmbeddedType1Font(&fontLoc->embFontID, psName);
- break;
- case fontType1C:
- psName = makePSFontName(font, &fontLoc->embFontID);
- setupEmbeddedType1CFont(font, &fontLoc->embFontID, psName);
- break;
- case fontType1COT:
- psName = makePSFontName(font, &fontLoc->embFontID);
- setupEmbeddedOpenTypeT1CFont(font, &fontLoc->embFontID, psName);
- break;
- case fontTrueType:
- case fontTrueTypeOT:
- psName = makePSFontName(font, font->getID());
- setupEmbeddedTrueTypeFont(font, &fontLoc->embFontID, psName);
- break;
- case fontCIDType0C:
- psName = makePSFontName(font, &fontLoc->embFontID);
- setupEmbeddedCIDType0Font(font, &fontLoc->embFontID, psName);
- break;
- case fontCIDType2:
- case fontCIDType2OT:
- psName = makePSFontName(font, font->getID());
- //~ should check to see if font actually uses vertical mode
- setupEmbeddedCIDTrueTypeFont(font, &fontLoc->embFontID, psName, true);
- break;
- case fontCIDType0COT:
- psName = makePSFontName(font, &fontLoc->embFontID);
- setupEmbeddedOpenTypeCFFFont(font, &fontLoc->embFontID, psName);
- break;
- default:
- break;
- }
- break;
- case gfxFontLocExternal:
- //~ add cases for external 16-bit fonts
- switch (fontLoc->fontType) {
- case fontType1:
- if (font->getEmbeddedFontName()) {
- // this assumes that the PS font name matches the PDF font name
- psName = font->getEmbeddedFontName()->copy();
- } else {
- //~ this won't work -- the PS font name won't match
- psName = makePSFontName(font, font->getID());
- }
- setupExternalType1Font(fontLoc->path, psName);
- break;
- case fontTrueType:
- case fontTrueTypeOT:
- psName = makePSFontName(font, font->getID());
- setupExternalTrueTypeFont(font, fontLoc->path, psName);
- break;
- case fontCIDType2:
- case fontCIDType2OT:
- psName = makePSFontName(font, font->getID());
- //~ should check to see if font actually uses vertical mode
- setupExternalCIDTrueTypeFont(font, fontLoc->path, psName, true);
- break;
- default:
- break;
- }
- break;
- case gfxFontLocResident:
- psName = fontLoc->path->copy();
- break;
- }
- }
-
- if (!psName) {
- if (font->isCIDFont()) {
- error(errSyntaxError, -1,
- "Couldn't find a font to substitute for '{0:s}' ('{1:s}' character collection)",
- font->getName() ? font->getName()->c_str()
- : "(unnamed)",
- ((GfxCIDFont *)font)->getCollection()
- ? ((GfxCIDFont *)font)->getCollection()->c_str()
- : "(unknown)");
- if (font16EncLen >= font16EncSize) {
- font16EncSize += 16;
- font16Enc = (PSFont16Enc *)greallocn(font16Enc,
- font16EncSize,
- sizeof(PSFont16Enc));
- }
- font16Enc[font16EncLen].fontID = *font->getID();
- font16Enc[font16EncLen].enc = nullptr;
- ++font16EncLen;
- } else {
- error(errSyntaxError, -1,
- "Couldn't find a font to substitute for '{0:s}'",
- font->getName() ? font->getName()->c_str()
- : "(unnamed)");
- }
- delete fontLoc;
- return;
- }
-
- // scale substituted 8-bit fonts
- if (fontLoc->locType == gfxFontLocResident &&
- fontLoc->substIdx >= 0) {
- subst = true;
- for (code = 0; code < 256; ++code) {
- if ((charName = ((Gfx8BitFont *)font)->getCharName(code)) &&
- charName[0] == 'm' && charName[1] == '\0') {
- break;
- }
- }
- if (code < 256) {
- w1 = ((Gfx8BitFont *)font)->getWidth(code);
- } else {
- w1 = 0;
- }
- w2 = psBase14SubstFonts[fontLoc->substIdx].mWidth;
- xs = w1 / w2;
- if (xs < 0.1) {
- xs = 1;
- }
- }
-
- // handle encodings for substituted CID fonts
- if (fontLoc->locType == gfxFontLocResident &&
- fontLoc->fontType >= fontCIDType0) {
- subst = true;
- if (font16EncLen >= font16EncSize) {
- font16EncSize += 16;
- font16Enc = (PSFont16Enc *)greallocn(font16Enc,
- font16EncSize,
- sizeof(PSFont16Enc));
- }
- font16Enc[font16EncLen].fontID = *font->getID();
- if ((uMap = globalParams->getUnicodeMap(fontLoc->encoding->toStr()))) {
- font16Enc[font16EncLen].enc = fontLoc->encoding->copy();
- } else {
- error(errSyntaxError, -1,
- "Couldn't find Unicode map for 16-bit font encoding '{0:t}'",
- fontLoc->encoding);
- font16Enc[font16EncLen].enc = nullptr;
- }
- ++font16EncLen;
- }
-
- delete fontLoc;
- }
-
- // generate PostScript code to set up the font
- if (font->isCIDFont()) {
- if (level == psLevel3 || level == psLevel3Sep) {
- writePSFmt("/F{0:d}_{1:d} /{2:t} {3:d} pdfMakeFont16L3\n",
- font->getID()->num, font->getID()->gen, psName,
- font->getWMode());
+void PSOutputDev::setupFont(GfxFont *font, Dict *parentResDict)
+{
+ GfxFontLoc *fontLoc;
+ GooString *psName;
+ char buf[16];
+ bool subst;
+ const UnicodeMap *uMap;
+ const char *charName;
+ double xs, ys;
+ int code;
+ double w1, w2;
+ int i, j;
+
+ // check if font is already set up
+ for (i = 0; i < fontIDLen; ++i) {
+ if (fontIDs[i] == *font->getID()) {
+ return;
+ }
+ }
+
+ // add entry to fontIDs list
+ if (fontIDLen >= fontIDSize) {
+ fontIDSize += 64;
+ fontIDs = (Ref *)greallocn(fontIDs, fontIDSize, sizeof(Ref));
+ }
+ fontIDs[fontIDLen++] = *font->getID();
+
+ psName = nullptr;
+ xs = ys = 1;
+ subst = false;
+
+ if (font->getType() == fontType3) {
+ psName = GooString::format("T3_{0:d}_{1:d}", font->getID()->num, font->getID()->gen);
+ setupType3Font(font, psName, parentResDict);
+ } else {
+ fontLoc = font->locateFont(xref, this);
+ if (fontLoc != nullptr) {
+ switch (fontLoc->locType) {
+ case gfxFontLocEmbedded:
+ switch (fontLoc->fontType) {
+ case fontType1:
+ // this assumes that the PS font name matches the PDF font name
+ psName = font->getEmbeddedFontName() ? font->getEmbeddedFontName()->copy() : new GooString();
+ setupEmbeddedType1Font(&fontLoc->embFontID, psName);
+ break;
+ case fontType1C:
+ psName = makePSFontName(font, &fontLoc->embFontID);
+ setupEmbeddedType1CFont(font, &fontLoc->embFontID, psName);
+ break;
+ case fontType1COT:
+ psName = makePSFontName(font, &fontLoc->embFontID);
+ setupEmbeddedOpenTypeT1CFont(font, &fontLoc->embFontID, psName);
+ break;
+ case fontTrueType:
+ case fontTrueTypeOT:
+ psName = makePSFontName(font, font->getID());
+ setupEmbeddedTrueTypeFont(font, &fontLoc->embFontID, psName);
+ break;
+ case fontCIDType0C:
+ psName = makePSFontName(font, &fontLoc->embFontID);
+ setupEmbeddedCIDType0Font(font, &fontLoc->embFontID, psName);
+ break;
+ case fontCIDType2:
+ case fontCIDType2OT:
+ psName = makePSFontName(font, font->getID());
+ //~ should check to see if font actually uses vertical mode
+ setupEmbeddedCIDTrueTypeFont(font, &fontLoc->embFontID, psName, true);
+ break;
+ case fontCIDType0COT:
+ psName = makePSFontName(font, &fontLoc->embFontID);
+ setupEmbeddedOpenTypeCFFFont(font, &fontLoc->embFontID, psName);
+ break;
+ default:
+ break;
+ }
+ break;
+ case gfxFontLocExternal:
+ //~ add cases for external 16-bit fonts
+ switch (fontLoc->fontType) {
+ case fontType1:
+ if (font->getEmbeddedFontName()) {
+ // this assumes that the PS font name matches the PDF font name
+ psName = font->getEmbeddedFontName()->copy();
+ } else {
+ //~ this won't work -- the PS font name won't match
+ psName = makePSFontName(font, font->getID());
+ }
+ setupExternalType1Font(fontLoc->path, psName);
+ break;
+ case fontTrueType:
+ case fontTrueTypeOT:
+ psName = makePSFontName(font, font->getID());
+ setupExternalTrueTypeFont(font, fontLoc->path, psName);
+ break;
+ case fontCIDType2:
+ case fontCIDType2OT:
+ psName = makePSFontName(font, font->getID());
+ //~ should check to see if font actually uses vertical mode
+ setupExternalCIDTrueTypeFont(font, fontLoc->path, psName, true);
+ break;
+ default:
+ break;
+ }
+ break;
+ case gfxFontLocResident:
+ psName = fontLoc->path->copy();
+ break;
+ }
+ }
+
+ if (!psName) {
+ if (font->isCIDFont()) {
+ error(errSyntaxError, -1, "Couldn't find a font to substitute for '{0:s}' ('{1:s}' character collection)", font->getName() ? font->getName()->c_str() : "(unnamed)",
+ ((GfxCIDFont *)font)->getCollection() ? ((GfxCIDFont *)font)->getCollection()->c_str() : "(unknown)");
+ if (font16EncLen >= font16EncSize) {
+ font16EncSize += 16;
+ font16Enc = (PSFont16Enc *)greallocn(font16Enc, font16EncSize, sizeof(PSFont16Enc));
+ }
+ font16Enc[font16EncLen].fontID = *font->getID();
+ font16Enc[font16EncLen].enc = nullptr;
+ ++font16EncLen;
+ } else {
+ error(errSyntaxError, -1, "Couldn't find a font to substitute for '{0:s}'", font->getName() ? font->getName()->c_str() : "(unnamed)");
+ }
+ delete fontLoc;
+ return;
+ }
+
+ // scale substituted 8-bit fonts
+ if (fontLoc->locType == gfxFontLocResident && fontLoc->substIdx >= 0) {
+ subst = true;
+ for (code = 0; code < 256; ++code) {
+ if ((charName = ((Gfx8BitFont *)font)->getCharName(code)) && charName[0] == 'm' && charName[1] == '\0') {
+ break;
+ }
+ }
+ if (code < 256) {
+ w1 = ((Gfx8BitFont *)font)->getWidth(code);
+ } else {
+ w1 = 0;
+ }
+ w2 = psBase14SubstFonts[fontLoc->substIdx].mWidth;
+ xs = w1 / w2;
+ if (xs < 0.1) {
+ xs = 1;
+ }
+ }
+
+ // handle encodings for substituted CID fonts
+ if (fontLoc->locType == gfxFontLocResident && fontLoc->fontType >= fontCIDType0) {
+ subst = true;
+ if (font16EncLen >= font16EncSize) {
+ font16EncSize += 16;
+ font16Enc = (PSFont16Enc *)greallocn(font16Enc, font16EncSize, sizeof(PSFont16Enc));
+ }
+ font16Enc[font16EncLen].fontID = *font->getID();
+ if ((uMap = globalParams->getUnicodeMap(fontLoc->encoding->toStr()))) {
+ font16Enc[font16EncLen].enc = fontLoc->encoding->copy();
+ } else {
+ error(errSyntaxError, -1, "Couldn't find Unicode map for 16-bit font encoding '{0:t}'", fontLoc->encoding);
+ font16Enc[font16EncLen].enc = nullptr;
+ }
+ ++font16EncLen;
+ }
+
+ delete fontLoc;
+ }
+
+ // generate PostScript code to set up the font
+ if (font->isCIDFont()) {
+ if (level == psLevel3 || level == psLevel3Sep) {
+ writePSFmt("/F{0:d}_{1:d} /{2:t} {3:d} pdfMakeFont16L3\n", font->getID()->num, font->getID()->gen, psName, font->getWMode());
+ } else {
+ writePSFmt("/F{0:d}_{1:d} /{2:t} {3:d} pdfMakeFont16\n", font->getID()->num, font->getID()->gen, psName, font->getWMode());
+ }
} else {
- writePSFmt("/F{0:d}_{1:d} /{2:t} {3:d} pdfMakeFont16\n",
- font->getID()->num, font->getID()->gen, psName,
- font->getWMode());
- }
- } else {
- writePSFmt("/F{0:d}_{1:d} /{2:t} {3:.6g} {4:.6g}\n",
- font->getID()->num, font->getID()->gen, psName, xs, ys);
- for (i = 0; i < 256; i += 8) {
- writePS((char *)((i == 0) ? "[ " : " "));
- for (j = 0; j < 8; ++j) {
- if (font->getType() == fontTrueType &&
- !subst &&
- !((Gfx8BitFont *)font)->getHasEncoding()) {
- sprintf(buf, "c%02x", i+j);
- charName = buf;
- } else {
- charName = ((Gfx8BitFont *)font)->getCharName(i+j);
- }
- writePS("/");
- writePSName(charName ? charName : (char *)".notdef");
- // the empty name is legal in PDF and PostScript, but PostScript
- // uses a double-slash (//...) for "immediately evaluated names",
- // so we need to add a space character here
- if (charName && !charName[0]) {
- writePS(" ");
- }
- }
- writePS((i == 256-8) ? (char *)"]\n" : (char *)"\n");
- }
- writePS("pdfMakeFont\n");
- }
-
- delete psName;
+ writePSFmt("/F{0:d}_{1:d} /{2:t} {3:.6g} {4:.6g}\n", font->getID()->num, font->getID()->gen, psName, xs, ys);
+ for (i = 0; i < 256; i += 8) {
+ writePS((char *)((i == 0) ? "[ " : " "));
+ for (j = 0; j < 8; ++j) {
+ if (font->getType() == fontTrueType && !subst && !((Gfx8BitFont *)font)->getHasEncoding()) {
+ sprintf(buf, "c%02x", i + j);
+ charName = buf;
+ } else {
+ charName = ((Gfx8BitFont *)font)->getCharName(i + j);
+ }
+ writePS("/");
+ writePSName(charName ? charName : (char *)".notdef");
+ // the empty name is legal in PDF and PostScript, but PostScript
+ // uses a double-slash (//...) for "immediately evaluated names",
+ // so we need to add a space character here
+ if (charName && !charName[0]) {
+ writePS(" ");
+ }
+ }
+ writePS((i == 256 - 8) ? (char *)"]\n" : (char *)"\n");
+ }
+ writePS("pdfMakeFont\n");
+ }
+
+ delete psName;
}
-void PSOutputDev::setupEmbeddedType1Font(Ref *id, GooString *psName) {
- static const char hexChar[17] = "0123456789abcdef";
- Dict *dict;
- long length1, length2, length3, i;
- int c;
- int start[4];
- bool binMode;
- bool writePadding = true;
-
- // check if font is already embedded
- if (!fontNames.emplace(psName->toStr()).second) {
- return;
- }
-
- // get the font stream and info
- Object obj1, obj2, obj3;
- Object refObj(*id);
- Object strObj = refObj.fetch(xref);
- if (!strObj.isStream()) {
- error(errSyntaxError, -1, "Embedded font file object is not a stream");
- goto err1;
- }
- if (!(dict = strObj.streamGetDict())) {
- error(errSyntaxError, -1,
- "Embedded font stream is missing its dictionary");
- goto err1;
- }
- obj1 = dict->lookup("Length1");
- obj2 = dict->lookup("Length2");
- obj3 = dict->lookup("Length3");
- if (!obj1.isInt() || !obj2.isInt() || !obj3.isInt()) {
- error(errSyntaxError, -1,
- "Missing length fields in embedded font stream dictionary");
- goto err1;
- }
- length1 = obj1.getInt();
- length2 = obj2.getInt();
- length3 = obj3.getInt();
-
- // beginning comment
- writePSFmt("%%BeginResource: font {0:t}\n", psName);
- embFontList->append("%%+ font ");
- embFontList->append(psName->c_str());
- embFontList->append("\n");
-
- strObj.streamReset();
- if (strObj.streamGetChar() == 0x80 &&
- strObj.streamGetChar() == 1) {
- // PFB format
- length1 = strObj.streamGetChar() |
- (strObj.streamGetChar() << 8) |
- (strObj.streamGetChar() << 16) |
- (strObj.streamGetChar() << 24);
- } else {
+void PSOutputDev::setupEmbeddedType1Font(Ref *id, GooString *psName)
+{
+ static const char hexChar[17] = "0123456789abcdef";
+ Dict *dict;
+ long length1, length2, length3, i;
+ int c;
+ int start[4];
+ bool binMode;
+ bool writePadding = true;
+
+ // check if font is already embedded
+ if (!fontNames.emplace(psName->toStr()).second) {
+ return;
+ }
+
+ // get the font stream and info
+ Object obj1, obj2, obj3;
+ Object refObj(*id);
+ Object strObj = refObj.fetch(xref);
+ if (!strObj.isStream()) {
+ error(errSyntaxError, -1, "Embedded font file object is not a stream");
+ goto err1;
+ }
+ if (!(dict = strObj.streamGetDict())) {
+ error(errSyntaxError, -1, "Embedded font stream is missing its dictionary");
+ goto err1;
+ }
+ obj1 = dict->lookup("Length1");
+ obj2 = dict->lookup("Length2");
+ obj3 = dict->lookup("Length3");
+ if (!obj1.isInt() || !obj2.isInt() || !obj3.isInt()) {
+ error(errSyntaxError, -1, "Missing length fields in embedded font stream dictionary");
+ goto err1;
+ }
+ length1 = obj1.getInt();
+ length2 = obj2.getInt();
+ length3 = obj3.getInt();
+
+ // beginning comment
+ writePSFmt("%%BeginResource: font {0:t}\n", psName);
+ embFontList->append("%%+ font ");
+ embFontList->append(psName->c_str());
+ embFontList->append("\n");
+
strObj.streamReset();
- }
- // copy ASCII portion of font
- for (i = 0; i < length1 && (c = strObj.streamGetChar()) != EOF; ++i) {
- writePSChar(c);
- }
-
- // figure out if encrypted portion is binary or ASCII
- binMode = false;
- for (i = 0; i < 4; ++i) {
- start[i] = strObj.streamGetChar();
- if (start[i] == EOF) {
- error(errSyntaxError, -1,
- "Unexpected end of file in embedded font stream");
- goto err1;
- }
- if (!((start[i] >= '0' && start[i] <= '9') ||
- (start[i] >= 'A' && start[i] <= 'F') ||
- (start[i] >= 'a' && start[i] <= 'f')))
- binMode = true;
- }
-
- if (length2 == 0)
- {
- // length2 == 0 is an error
- // trying to solve it by just piping all
- // the stream data
- error(errSyntaxWarning, -1, "Font has length2 as 0, trying to overcome the problem reading the stream until the end");
- length2 = INT_MAX;
- writePadding = false;
- }
-
-
- // convert binary data to ASCII
- if (binMode) {
- if (start[0] == 0x80 &&
- start[1] == 2) {
- length2 = start[2] |
- (start[3] << 8) |
- (strObj.streamGetChar() << 16) |
- (strObj.streamGetChar() << 24);
- i = 0;
+ if (strObj.streamGetChar() == 0x80 && strObj.streamGetChar() == 1) {
+ // PFB format
+ length1 = strObj.streamGetChar() | (strObj.streamGetChar() << 8) | (strObj.streamGetChar() << 16) | (strObj.streamGetChar() << 24);
} else {
- for (i = 0; i < 4; ++i) {
- writePSChar(hexChar[(start[i] >> 4) & 0x0f]);
- writePSChar(hexChar[start[i] & 0x0f]);
- }
+ strObj.streamReset();
+ }
+ // copy ASCII portion of font
+ for (i = 0; i < length1 && (c = strObj.streamGetChar()) != EOF; ++i) {
+ writePSChar(c);
+ }
+
+ // figure out if encrypted portion is binary or ASCII
+ binMode = false;
+ for (i = 0; i < 4; ++i) {
+ start[i] = strObj.streamGetChar();
+ if (start[i] == EOF) {
+ error(errSyntaxError, -1, "Unexpected end of file in embedded font stream");
+ goto err1;
+ }
+ if (!((start[i] >= '0' && start[i] <= '9') || (start[i] >= 'A' && start[i] <= 'F') || (start[i] >= 'a' && start[i] <= 'f')))
+ binMode = true;
}
+
+ if (length2 == 0) {
+ // length2 == 0 is an error
+ // trying to solve it by just piping all
+ // the stream data
+ error(errSyntaxWarning, -1, "Font has length2 as 0, trying to overcome the problem reading the stream until the end");
+ length2 = INT_MAX;
+ writePadding = false;
+ }
+
+ // convert binary data to ASCII
+ if (binMode) {
+ if (start[0] == 0x80 && start[1] == 2) {
+ length2 = start[2] | (start[3] << 8) | (strObj.streamGetChar() << 16) | (strObj.streamGetChar() << 24);
+ i = 0;
+ } else {
+ for (i = 0; i < 4; ++i) {
+ writePSChar(hexChar[(start[i] >> 4) & 0x0f]);
+ writePSChar(hexChar[start[i] & 0x0f]);
+ }
+ }
#if 0 // this causes trouble for various PostScript printers
// if Length2 is incorrect (too small), font data gets chopped, so
// we take a few extra characters from the trailer just in case
length2 += length3 >= 8 ? 8 : length3;
#endif
- while (i < length2) {
- if ((c = strObj.streamGetChar()) == EOF) {
- break;
- }
- writePSChar(hexChar[(c >> 4) & 0x0f]);
- writePSChar(hexChar[c & 0x0f]);
- if (++i % 32 == 0) {
- writePSChar('\n');
- }
- }
- if (i % 32 > 0) {
- writePSChar('\n');
- }
-
- // already in ASCII format -- just copy it
- } else {
- for (i = 0; i < 4; ++i) {
- writePSChar(start[i]);
- }
- for (i = 4; i < length2; ++i) {
- if ((c = strObj.streamGetChar()) == EOF) {
- break;
- }
- writePSChar(c);
- }
- }
-
- if (writePadding)
- {
- if (length3 > 0) {
- // write fixed-content portion
- c = strObj.streamGetChar();
- if (c == 0x80) {
- c = strObj.streamGetChar();
- if (c == 1) {
- length3 = strObj.streamGetChar() |
- (strObj.streamGetChar() << 8) |
- (strObj.streamGetChar() << 16) |
- (strObj.streamGetChar() << 24);
-
- i = 0;
- while (i < length3) {
+ while (i < length2) {
if ((c = strObj.streamGetChar()) == EOF) {
- break;
+ break;
+ }
+ writePSChar(hexChar[(c >> 4) & 0x0f]);
+ writePSChar(hexChar[c & 0x0f]);
+ if (++i % 32 == 0) {
+ writePSChar('\n');
+ }
+ }
+ if (i % 32 > 0) {
+ writePSChar('\n');
+ }
+
+ // already in ASCII format -- just copy it
+ } else {
+ for (i = 0; i < 4; ++i) {
+ writePSChar(start[i]);
+ }
+ for (i = 4; i < length2; ++i) {
+ if ((c = strObj.streamGetChar()) == EOF) {
+ break;
}
writePSChar(c);
- ++i;
- }
}
- } else {
- if (c != EOF) {
- writePSChar(c);
+ }
- while ((c = strObj.streamGetChar()) != EOF) {
- writePSChar(c);
- }
+ if (writePadding) {
+ if (length3 > 0) {
+ // write fixed-content portion
+ c = strObj.streamGetChar();
+ if (c == 0x80) {
+ c = strObj.streamGetChar();
+ if (c == 1) {
+ length3 = strObj.streamGetChar() | (strObj.streamGetChar() << 8) | (strObj.streamGetChar() << 16) | (strObj.streamGetChar() << 24);
+
+ i = 0;
+ while (i < length3) {
+ if ((c = strObj.streamGetChar()) == EOF) {
+ break;
+ }
+ writePSChar(c);
+ ++i;
+ }
+ }
+ } else {
+ if (c != EOF) {
+ writePSChar(c);
+
+ while ((c = strObj.streamGetChar()) != EOF) {
+ writePSChar(c);
+ }
+ }
+ }
+ } else {
+ // write padding and "cleartomark"
+ for (i = 0; i < 8; ++i) {
+ writePS("00000000000000000000000000000000"
+ "00000000000000000000000000000000\n");
+ }
+ writePS("cleartomark\n");
}
- }
- } else {
- // write padding and "cleartomark"
- for (i = 0; i < 8; ++i) {
- writePS("00000000000000000000000000000000"
- "00000000000000000000000000000000\n");
- }
- writePS("cleartomark\n");
}
- }
- // ending comment
- writePS("%%EndResource\n");
+ // ending comment
+ writePS("%%EndResource\n");
- err1:
- if (strObj.isStream())
- strObj.streamClose();
+err1:
+ if (strObj.isStream())
+ strObj.streamClose();
}
-void PSOutputDev::setupExternalType1Font(GooString *fileName, GooString *psName) {
- static const char hexChar[17] = "0123456789abcdef";
- FILE *fontFile;
- int c;
-
- if (!fontNames.emplace(psName->toStr()).second) {
- return;
- }
-
- // beginning comment
- writePSFmt("%%BeginResource: font {0:t}\n", psName);
- embFontList->append("%%+ font ");
- embFontList->append(psName->c_str());
- embFontList->append("\n");
-
- // copy the font file
- if (!(fontFile = openFile(fileName->c_str(), "rb"))) {
- error(errIO, -1, "Couldn't open external font file");
- return;
- }
-
- c = fgetc(fontFile);
- if (c == 0x80) {
- // PFB file
- ungetc(c, fontFile);
- while (!feof(fontFile)) {
- fgetc(fontFile); // skip start of segment byte (0x80)
- int segType = fgetc(fontFile);
- long segLen = fgetc(fontFile) |
- (fgetc(fontFile) << 8) |
- (fgetc(fontFile) << 16) |
- (fgetc(fontFile) << 24);
- if (feof(fontFile))
- break;
-
- if (segType == 1) {
- // ASCII segment
- for (long i = 0; i < segLen; i++) {
- c = fgetc(fontFile);
- if (c == EOF)
- break;
- writePSChar(c);
- }
- } else if (segType == 2) {
- // binary segment
- for (long i = 0; i < segLen; i++) {
- c = fgetc(fontFile);
- if (c == EOF)
- break;
- writePSChar(hexChar[(c >> 4) & 0x0f]);
- writePSChar(hexChar[c & 0x0f]);
- if (i % 36 == 35)
- writePSChar('\n');
- }
- } else {
- // end of file
- break;
- }
- }
- } else if (c != EOF) {
- writePSChar(c);
- while ((c = fgetc(fontFile)) != EOF)
- writePSChar(c);
- }
- fclose(fontFile);
-
- // ending comment
- writePS("%%EndResource\n");
+void PSOutputDev::setupExternalType1Font(GooString *fileName, GooString *psName)
+{
+ static const char hexChar[17] = "0123456789abcdef";
+ FILE *fontFile;
+ int c;
+
+ if (!fontNames.emplace(psName->toStr()).second) {
+ return;
+ }
+
+ // beginning comment
+ writePSFmt("%%BeginResource: font {0:t}\n", psName);
+ embFontList->append("%%+ font ");
+ embFontList->append(psName->c_str());
+ embFontList->append("\n");
+
+ // copy the font file
+ if (!(fontFile = openFile(fileName->c_str(), "rb"))) {
+ error(errIO, -1, "Couldn't open external font file");
+ return;
+ }
+
+ c = fgetc(fontFile);
+ if (c == 0x80) {
+ // PFB file
+ ungetc(c, fontFile);
+ while (!feof(fontFile)) {
+ fgetc(fontFile); // skip start of segment byte (0x80)
+ int segType = fgetc(fontFile);
+ long segLen = fgetc(fontFile) | (fgetc(fontFile) << 8) | (fgetc(fontFile) << 16) | (fgetc(fontFile) << 24);
+ if (feof(fontFile))
+ break;
+
+ if (segType == 1) {
+ // ASCII segment
+ for (long i = 0; i < segLen; i++) {
+ c = fgetc(fontFile);
+ if (c == EOF)
+ break;
+ writePSChar(c);
+ }
+ } else if (segType == 2) {
+ // binary segment
+ for (long i = 0; i < segLen; i++) {
+ c = fgetc(fontFile);
+ if (c == EOF)
+ break;
+ writePSChar(hexChar[(c >> 4) & 0x0f]);
+ writePSChar(hexChar[c & 0x0f]);
+ if (i % 36 == 35)
+ writePSChar('\n');
+ }
+ } else {
+ // end of file
+ break;
+ }
+ }
+ } else if (c != EOF) {
+ writePSChar(c);
+ while ((c = fgetc(fontFile)) != EOF)
+ writePSChar(c);
+ }
+ fclose(fontFile);
+
+ // ending comment
+ writePS("%%EndResource\n");
}
-void PSOutputDev::setupEmbeddedType1CFont(GfxFont *font, Ref *id,
- GooString *psName) {
- char *fontBuf;
- int fontLen;
- FoFiType1C *ffT1C;
- int i;
-
- // check if font is already embedded
- for (i = 0; i < t1FontNameLen; ++i) {
- if (t1FontNames[i].fontFileID == *id) {
- psName->clear();
- psName->insert(0, t1FontNames[i].psName);
- return;
- }
- }
- if (t1FontNameLen == t1FontNameSize) {
- t1FontNameSize *= 2;
- t1FontNames = (PST1FontName *)greallocn(t1FontNames, t1FontNameSize,
- sizeof(PST1FontName));
- }
- t1FontNames[t1FontNameLen].fontFileID = *id;
- t1FontNames[t1FontNameLen].psName = psName->copy();
- ++t1FontNameLen;
-
- // beginning comment
- writePSFmt("%%BeginResource: font {0:t}\n", psName);
- embFontList->append("%%+ font ");
- embFontList->append(psName->c_str());
- embFontList->append("\n");
-
- // convert it to a Type 1 font
- if ((fontBuf = font->readEmbFontFile(xref, &fontLen))) {
- if ((ffT1C = FoFiType1C::make(fontBuf, fontLen))) {
- ffT1C->convertToType1(psName->c_str(), nullptr, true,
- outputFunc, outputStream);
- delete ffT1C;
- }
- gfree(fontBuf);
- }
-
- // ending comment
- writePS("%%EndResource\n");
+void PSOutputDev::setupEmbeddedType1CFont(GfxFont *font, Ref *id, GooString *psName)
+{
+ char *fontBuf;
+ int fontLen;
+ FoFiType1C *ffT1C;
+ int i;
+
+ // check if font is already embedded
+ for (i = 0; i < t1FontNameLen; ++i) {
+ if (t1FontNames[i].fontFileID == *id) {
+ psName->clear();
+ psName->insert(0, t1FontNames[i].psName);
+ return;
+ }
+ }
+ if (t1FontNameLen == t1FontNameSize) {
+ t1FontNameSize *= 2;
+ t1FontNames = (PST1FontName *)greallocn(t1FontNames, t1FontNameSize, sizeof(PST1FontName));
+ }
+ t1FontNames[t1FontNameLen].fontFileID = *id;
+ t1FontNames[t1FontNameLen].psName = psName->copy();
+ ++t1FontNameLen;
+
+ // beginning comment
+ writePSFmt("%%BeginResource: font {0:t}\n", psName);
+ embFontList->append("%%+ font ");
+ embFontList->append(psName->c_str());
+ embFontList->append("\n");
+
+ // convert it to a Type 1 font
+ if ((fontBuf = font->readEmbFontFile(xref, &fontLen))) {
+ if ((ffT1C = FoFiType1C::make(fontBuf, fontLen))) {
+ ffT1C->convertToType1(psName->c_str(), nullptr, true, outputFunc, outputStream);
+ delete ffT1C;
+ }
+ gfree(fontBuf);
+ }
+
+ // ending comment
+ writePS("%%EndResource\n");
}
-void PSOutputDev::setupEmbeddedOpenTypeT1CFont(GfxFont *font, Ref *id,
- GooString *psName) {
- char *fontBuf;
- int fontLen;
- FoFiTrueType *ffTT;
- int i;
-
- // check if font is already embedded
- for (i = 0; i < t1FontNameLen; ++i) {
- if (t1FontNames[i].fontFileID == *id) {
- psName->clear();
- psName->insert(0, t1FontNames[i].psName);
- return;
- }
- }
- if (t1FontNameLen == t1FontNameSize) {
- t1FontNameSize *= 2;
- t1FontNames = (PST1FontName *)greallocn(t1FontNames, t1FontNameSize,
- sizeof(PST1FontName));
- }
- t1FontNames[t1FontNameLen].fontFileID = *id;
- t1FontNames[t1FontNameLen].psName = psName->copy();
- ++t1FontNameLen;
-
- // beginning comment
- writePSFmt("%%BeginResource: font {0:t}\n", psName);
- embFontList->append("%%+ font ");
- embFontList->append(psName->c_str());
- embFontList->append("\n");
-
- // convert it to a Type 1 font
- if ((fontBuf = font->readEmbFontFile(xref, &fontLen))) {
- if ((ffTT = FoFiTrueType::make(fontBuf, fontLen))) {
- if (ffTT->isOpenTypeCFF()) {
- ffTT->convertToType1(psName->c_str(), nullptr, true,
- outputFunc, outputStream);
- }
- delete ffTT;
- }
- gfree(fontBuf);
- }
-
- // ending comment
- writePS("%%EndResource\n");
+void PSOutputDev::setupEmbeddedOpenTypeT1CFont(GfxFont *font, Ref *id, GooString *psName)
+{
+ char *fontBuf;
+ int fontLen;
+ FoFiTrueType *ffTT;
+ int i;
+
+ // check if font is already embedded
+ for (i = 0; i < t1FontNameLen; ++i) {
+ if (t1FontNames[i].fontFileID == *id) {
+ psName->clear();
+ psName->insert(0, t1FontNames[i].psName);
+ return;
+ }
+ }
+ if (t1FontNameLen == t1FontNameSize) {
+ t1FontNameSize *= 2;
+ t1FontNames = (PST1FontName *)greallocn(t1FontNames, t1FontNameSize, sizeof(PST1FontName));
+ }
+ t1FontNames[t1FontNameLen].fontFileID = *id;
+ t1FontNames[t1FontNameLen].psName = psName->copy();
+ ++t1FontNameLen;
+
+ // beginning comment
+ writePSFmt("%%BeginResource: font {0:t}\n", psName);
+ embFontList->append("%%+ font ");
+ embFontList->append(psName->c_str());
+ embFontList->append("\n");
+
+ // convert it to a Type 1 font
+ if ((fontBuf = font->readEmbFontFile(xref, &fontLen))) {
+ if ((ffTT = FoFiTrueType::make(fontBuf, fontLen))) {
+ if (ffTT->isOpenTypeCFF()) {
+ ffTT->convertToType1(psName->c_str(), nullptr, true, outputFunc, outputStream);
+ }
+ delete ffTT;
+ }
+ gfree(fontBuf);
+ }
+
+ // ending comment
+ writePS("%%EndResource\n");
}
-void PSOutputDev::setupEmbeddedTrueTypeFont(GfxFont *font, Ref *id,
- GooString *psName) {
- char *fontBuf;
- int fontLen;
- FoFiTrueType *ffTT;
- int *codeToGID;
-
- // beginning comment
- writePSFmt("%%BeginResource: font {0:t}\n", psName);
- embFontList->append("%%+ font ");
- embFontList->append(psName->c_str());
- embFontList->append("\n");
-
- // convert it to a Type 42 font
- if ((fontBuf = font->readEmbFontFile(xref, &fontLen))) {
- if ((ffTT = FoFiTrueType::make(fontBuf, fontLen))) {
- codeToGID = ((Gfx8BitFont *)font)->getCodeToGIDMap(ffTT);
- ffTT->convertToType42(psName->c_str(),
- ((Gfx8BitFont *)font)->getHasEncoding()
- ? ((Gfx8BitFont *)font)->getEncoding()
- : nullptr,
- codeToGID, outputFunc, outputStream);
- if (codeToGID) {
- if (font8InfoLen >= font8InfoSize) {
- font8InfoSize += 16;
- font8Info = (PSFont8Info *)greallocn(font8Info,
- font8InfoSize,
- sizeof(PSFont8Info));
- }
- font8Info[font8InfoLen].fontID = *font->getID();
- font8Info[font8InfoLen].codeToGID = codeToGID;
- ++font8InfoLen;
- }
- delete ffTT;
- }
- gfree(fontBuf);
- }
-
- // ending comment
- writePS("%%EndResource\n");
+void PSOutputDev::setupEmbeddedTrueTypeFont(GfxFont *font, Ref *id, GooString *psName)
+{
+ char *fontBuf;
+ int fontLen;
+ FoFiTrueType *ffTT;
+ int *codeToGID;
+
+ // beginning comment
+ writePSFmt("%%BeginResource: font {0:t}\n", psName);
+ embFontList->append("%%+ font ");
+ embFontList->append(psName->c_str());
+ embFontList->append("\n");
+
+ // convert it to a Type 42 font
+ if ((fontBuf = font->readEmbFontFile(xref, &fontLen))) {
+ if ((ffTT = FoFiTrueType::make(fontBuf, fontLen))) {
+ codeToGID = ((Gfx8BitFont *)font)->getCodeToGIDMap(ffTT);
+ ffTT->convertToType42(psName->c_str(), ((Gfx8BitFont *)font)->getHasEncoding() ? ((Gfx8BitFont *)font)->getEncoding() : nullptr, codeToGID, outputFunc, outputStream);
+ if (codeToGID) {
+ if (font8InfoLen >= font8InfoSize) {
+ font8InfoSize += 16;
+ font8Info = (PSFont8Info *)greallocn(font8Info, font8InfoSize, sizeof(PSFont8Info));
+ }
+ font8Info[font8InfoLen].fontID = *font->getID();
+ font8Info[font8InfoLen].codeToGID = codeToGID;
+ ++font8InfoLen;
+ }
+ delete ffTT;
+ }
+ gfree(fontBuf);
+ }
+
+ // ending comment
+ writePS("%%EndResource\n");
}
-void PSOutputDev::setupExternalTrueTypeFont(GfxFont *font, GooString *fileName,
- GooString *psName) {
- FoFiTrueType *ffTT;
- int *codeToGID;
-
- // beginning comment
- writePSFmt("%%BeginResource: font {0:t}\n", psName);
- embFontList->append("%%+ font ");
- embFontList->append(psName->c_str());
- embFontList->append("\n");
-
- // convert it to a Type 42 font
- if ((ffTT = FoFiTrueType::load(fileName->c_str()))) {
- codeToGID = ((Gfx8BitFont *)font)->getCodeToGIDMap(ffTT);
- ffTT->convertToType42(psName->c_str(),
- ((Gfx8BitFont *)font)->getHasEncoding()
- ? ((Gfx8BitFont *)font)->getEncoding()
- : nullptr,
- codeToGID, outputFunc, outputStream);
- if (codeToGID) {
- if (font8InfoLen >= font8InfoSize) {
- font8InfoSize += 16;
- font8Info = (PSFont8Info *)greallocn(font8Info,
- font8InfoSize,
- sizeof(PSFont8Info));
- }
- font8Info[font8InfoLen].fontID = *font->getID();
- font8Info[font8InfoLen].codeToGID = codeToGID;
- ++font8InfoLen;
- }
- delete ffTT;
- }
-
- // ending comment
- writePS("%%EndResource\n");
+void PSOutputDev::setupExternalTrueTypeFont(GfxFont *font, GooString *fileName, GooString *psName)
+{
+ FoFiTrueType *ffTT;
+ int *codeToGID;
+
+ // beginning comment
+ writePSFmt("%%BeginResource: font {0:t}\n", psName);
+ embFontList->append("%%+ font ");
+ embFontList->append(psName->c_str());
+ embFontList->append("\n");
+
+ // convert it to a Type 42 font
+ if ((ffTT = FoFiTrueType::load(fileName->c_str()))) {
+ codeToGID = ((Gfx8BitFont *)font)->getCodeToGIDMap(ffTT);
+ ffTT->convertToType42(psName->c_str(), ((Gfx8BitFont *)font)->getHasEncoding() ? ((Gfx8BitFont *)font)->getEncoding() : nullptr, codeToGID, outputFunc, outputStream);
+ if (codeToGID) {
+ if (font8InfoLen >= font8InfoSize) {
+ font8InfoSize += 16;
+ font8Info = (PSFont8Info *)greallocn(font8Info, font8InfoSize, sizeof(PSFont8Info));
+ }
+ font8Info[font8InfoLen].fontID = *font->getID();
+ font8Info[font8InfoLen].codeToGID = codeToGID;
+ ++font8InfoLen;
+ }
+ delete ffTT;
+ }
+
+ // ending comment
+ writePS("%%EndResource\n");
}
-void PSOutputDev::updateFontMaxValidGlyph(GfxFont *font, int maxValidGlyph) {
- if (maxValidGlyph >= 0 && font->getName()) {
- auto& fontMaxValidGlyph = perFontMaxValidGlyph[font->getName()->toStr()];
- if (fontMaxValidGlyph < maxValidGlyph) {
- fontMaxValidGlyph = maxValidGlyph;
+void PSOutputDev::updateFontMaxValidGlyph(GfxFont *font, int maxValidGlyph)
+{
+ if (maxValidGlyph >= 0 && font->getName()) {
+ auto &fontMaxValidGlyph = perFontMaxValidGlyph[font->getName()->toStr()];
+ if (fontMaxValidGlyph < maxValidGlyph) {
+ fontMaxValidGlyph = maxValidGlyph;
+ }
}
- }
}
-void PSOutputDev::setupExternalCIDTrueTypeFont(GfxFont *font,
- GooString *fileName,
- GooString *psName,
- bool needVerticalMetrics) {
- FoFiTrueType *ffTT;
- int *codeToGID;
- int codeToGIDLen;
-
- // beginning comment
- writePSFmt("%%BeginResource: font {0:t}\n", psName);
- embFontList->append("%%+ font ");
- embFontList->append(psName->c_str());
- embFontList->append("\n");
-
- // convert it to a Type 0 font
- //~ this should use fontNum to load the correct font
- if ((ffTT = FoFiTrueType::load(fileName->c_str()))) {
-
- // check for embedding permission
- if (ffTT->getEmbeddingRights() >= 1) {
- codeToGID = nullptr;
- codeToGIDLen = 0;
- if (((GfxCIDFont *)font)->getCIDToGID()) {
- codeToGIDLen = ((GfxCIDFont *)font)->getCIDToGIDLen();
- if (codeToGIDLen) {
- codeToGID = (int *)gmallocn(codeToGIDLen, sizeof(int));
- memcpy(codeToGID, ((GfxCIDFont *)font)->getCIDToGID(),
- codeToGIDLen * sizeof(int));
- }
- } else {
- codeToGID = ((GfxCIDFont *)font)->getCodeToGIDMap(ffTT, &codeToGIDLen);
- }
- if (ffTT->isOpenTypeCFF()) {
- ffTT->convertToCIDType0(psName->c_str(),
- codeToGID, codeToGIDLen,
- outputFunc, outputStream);
- } else if (globalParams->getPSLevel() >= psLevel3) {
- // Level 3: use a CID font
- ffTT->convertToCIDType2(psName->c_str(),
- codeToGID, codeToGIDLen,
- needVerticalMetrics,
- outputFunc, outputStream);
- } else {
- // otherwise: use a non-CID composite font
- int maxValidGlyph = -1;
- ffTT->convertToType0(psName->c_str(),
- codeToGID, codeToGIDLen,
- needVerticalMetrics,
- &maxValidGlyph,
- outputFunc, outputStream);
- updateFontMaxValidGlyph(font, maxValidGlyph);
- }
- gfree(codeToGID);
- } else {
- error(errSyntaxError, -1,
- "TrueType font '{0:s}' does not allow embedding",
- font->getName() ? font->getName()->c_str() : "(unnamed)");
-
+void PSOutputDev::setupExternalCIDTrueTypeFont(GfxFont *font, GooString *fileName, GooString *psName, bool needVerticalMetrics)
+{
+ FoFiTrueType *ffTT;
+ int *codeToGID;
+ int codeToGIDLen;
+
+ // beginning comment
+ writePSFmt("%%BeginResource: font {0:t}\n", psName);
+ embFontList->append("%%+ font ");
+ embFontList->append(psName->c_str());
+ embFontList->append("\n");
+
+ // convert it to a Type 0 font
+ //~ this should use fontNum to load the correct font
+ if ((ffTT = FoFiTrueType::load(fileName->c_str()))) {
+
+ // check for embedding permission
+ if (ffTT->getEmbeddingRights() >= 1) {
+ codeToGID = nullptr;
+ codeToGIDLen = 0;
+ if (((GfxCIDFont *)font)->getCIDToGID()) {
+ codeToGIDLen = ((GfxCIDFont *)font)->getCIDToGIDLen();
+ if (codeToGIDLen) {
+ codeToGID = (int *)gmallocn(codeToGIDLen, sizeof(int));
+ memcpy(codeToGID, ((GfxCIDFont *)font)->getCIDToGID(), codeToGIDLen * sizeof(int));
+ }
+ } else {
+ codeToGID = ((GfxCIDFont *)font)->getCodeToGIDMap(ffTT, &codeToGIDLen);
+ }
+ if (ffTT->isOpenTypeCFF()) {
+ ffTT->convertToCIDType0(psName->c_str(), codeToGID, codeToGIDLen, outputFunc, outputStream);
+ } else if (globalParams->getPSLevel() >= psLevel3) {
+ // Level 3: use a CID font
+ ffTT->convertToCIDType2(psName->c_str(), codeToGID, codeToGIDLen, needVerticalMetrics, outputFunc, outputStream);
+ } else {
+ // otherwise: use a non-CID composite font
+ int maxValidGlyph = -1;
+ ffTT->convertToType0(psName->c_str(), codeToGID, codeToGIDLen, needVerticalMetrics, &maxValidGlyph, outputFunc, outputStream);
+ updateFontMaxValidGlyph(font, maxValidGlyph);
+ }
+ gfree(codeToGID);
+ } else {
+ error(errSyntaxError, -1, "TrueType font '{0:s}' does not allow embedding", font->getName() ? font->getName()->c_str() : "(unnamed)");
+ }
+ delete ffTT;
}
- delete ffTT;
- }
- // ending comment
- writePS("%%EndResource\n");
+ // ending comment
+ writePS("%%EndResource\n");
}
-void PSOutputDev::setupEmbeddedCIDType0Font(GfxFont *font, Ref *id,
- GooString *psName) {
- char *fontBuf;
- int fontLen;
- FoFiType1C *ffT1C;
- int i;
-
- // check if font is already embedded
- for (i = 0; i < t1FontNameLen; ++i) {
- if (t1FontNames[i].fontFileID == *id) {
- psName->clear();
- psName->insert(0, t1FontNames[i].psName);
- return;
- }
- }
- if (t1FontNameLen == t1FontNameSize) {
- t1FontNameSize *= 2;
- t1FontNames = (PST1FontName *)greallocn(t1FontNames, t1FontNameSize,
- sizeof(PST1FontName));
- }
- t1FontNames[t1FontNameLen].fontFileID = *id;
- t1FontNames[t1FontNameLen].psName = psName->copy();
- ++t1FontNameLen;
-
- // beginning comment
- writePSFmt("%%BeginResource: font {0:t}\n", psName);
- embFontList->append("%%+ font ");
- embFontList->append(psName->c_str());
- embFontList->append("\n");
-
- // convert it to a Type 0 font
- if ((fontBuf = font->readEmbFontFile(xref, &fontLen))) {
- if ((ffT1C = FoFiType1C::make(fontBuf, fontLen))) {
- if (globalParams->getPSLevel() >= psLevel3) {
- // Level 3: use a CID font
- ffT1C->convertToCIDType0(psName->c_str(), nullptr, 0,
- outputFunc, outputStream);
- } else {
- // otherwise: use a non-CID composite font
- ffT1C->convertToType0(psName->c_str(), nullptr, 0,
- outputFunc, outputStream);
- }
- delete ffT1C;
- }
- gfree(fontBuf);
- }
-
- // ending comment
- writePS("%%EndResource\n");
+void PSOutputDev::setupEmbeddedCIDType0Font(GfxFont *font, Ref *id, GooString *psName)
+{
+ char *fontBuf;
+ int fontLen;
+ FoFiType1C *ffT1C;
+ int i;
+
+ // check if font is already embedded
+ for (i = 0; i < t1FontNameLen; ++i) {
+ if (t1FontNames[i].fontFileID == *id) {
+ psName->clear();
+ psName->insert(0, t1FontNames[i].psName);
+ return;
+ }
+ }
+ if (t1FontNameLen == t1FontNameSize) {
+ t1FontNameSize *= 2;
+ t1FontNames = (PST1FontName *)greallocn(t1FontNames, t1FontNameSize, sizeof(PST1FontName));
+ }
+ t1FontNames[t1FontNameLen].fontFileID = *id;
+ t1FontNames[t1FontNameLen].psName = psName->copy();
+ ++t1FontNameLen;
+
+ // beginning comment
+ writePSFmt("%%BeginResource: font {0:t}\n", psName);
+ embFontList->append("%%+ font ");
+ embFontList->append(psName->c_str());
+ embFontList->append("\n");
+
+ // convert it to a Type 0 font
+ if ((fontBuf = font->readEmbFontFile(xref, &fontLen))) {
+ if ((ffT1C = FoFiType1C::make(fontBuf, fontLen))) {
+ if (globalParams->getPSLevel() >= psLevel3) {
+ // Level 3: use a CID font
+ ffT1C->convertToCIDType0(psName->c_str(), nullptr, 0, outputFunc, outputStream);
+ } else {
+ // otherwise: use a non-CID composite font
+ ffT1C->convertToType0(psName->c_str(), nullptr, 0, outputFunc, outputStream);
+ }
+ delete ffT1C;
+ }
+ gfree(fontBuf);
+ }
+
+ // ending comment
+ writePS("%%EndResource\n");
}
-void PSOutputDev::setupEmbeddedCIDTrueTypeFont(GfxFont *font, Ref *id,
- GooString *psName,
- bool needVerticalMetrics) {
- char *fontBuf;
- int fontLen;
- FoFiTrueType *ffTT;
-
- // beginning comment
- writePSFmt("%%BeginResource: font {0:t}\n", psName);
- embFontList->append("%%+ font ");
- embFontList->append(psName->c_str());
- embFontList->append("\n");
-
- // convert it to a Type 0 font
- if ((fontBuf = font->readEmbFontFile(xref, &fontLen))) {
- if ((ffTT = FoFiTrueType::make(fontBuf, fontLen))) {
- if (globalParams->getPSLevel() >= psLevel3) {
- // Level 3: use a CID font
- ffTT->convertToCIDType2(psName->c_str(),
- ((GfxCIDFont *)font)->getCIDToGID(),
- ((GfxCIDFont *)font)->getCIDToGIDLen(),
- needVerticalMetrics,
- outputFunc, outputStream);
- } else {
- // otherwise: use a non-CID composite font
- int maxValidGlyph = -1;
- ffTT->convertToType0(psName->c_str(),
- ((GfxCIDFont *)font)->getCIDToGID(),
- ((GfxCIDFont *)font)->getCIDToGIDLen(),
- needVerticalMetrics,
- &maxValidGlyph,
- outputFunc, outputStream);
- updateFontMaxValidGlyph(font, maxValidGlyph);
- }
- delete ffTT;
- }
- gfree(fontBuf);
- }
-
- // ending comment
- writePS("%%EndResource\n");
+void PSOutputDev::setupEmbeddedCIDTrueTypeFont(GfxFont *font, Ref *id, GooString *psName, bool needVerticalMetrics)
+{
+ char *fontBuf;
+ int fontLen;
+ FoFiTrueType *ffTT;
+
+ // beginning comment
+ writePSFmt("%%BeginResource: font {0:t}\n", psName);
+ embFontList->append("%%+ font ");
+ embFontList->append(psName->c_str());
+ embFontList->append("\n");
+
+ // convert it to a Type 0 font
+ if ((fontBuf = font->readEmbFontFile(xref, &fontLen))) {
+ if ((ffTT = FoFiTrueType::make(fontBuf, fontLen))) {
+ if (globalParams->getPSLevel() >= psLevel3) {
+ // Level 3: use a CID font
+ ffTT->convertToCIDType2(psName->c_str(), ((GfxCIDFont *)font)->getCIDToGID(), ((GfxCIDFont *)font)->getCIDToGIDLen(), needVerticalMetrics, outputFunc, outputStream);
+ } else {
+ // otherwise: use a non-CID composite font
+ int maxValidGlyph = -1;
+ ffTT->convertToType0(psName->c_str(), ((GfxCIDFont *)font)->getCIDToGID(), ((GfxCIDFont *)font)->getCIDToGIDLen(), needVerticalMetrics, &maxValidGlyph, outputFunc, outputStream);
+ updateFontMaxValidGlyph(font, maxValidGlyph);
+ }
+ delete ffTT;
+ }
+ gfree(fontBuf);
+ }
+
+ // ending comment
+ writePS("%%EndResource\n");
}
-void PSOutputDev::setupEmbeddedOpenTypeCFFFont(GfxFont *font, Ref *id,
- GooString *psName) {
- char *fontBuf;
- int fontLen;
- FoFiTrueType *ffTT;
- int i;
-
- // check if font is already embedded
- for (i = 0; i < t1FontNameLen; ++i) {
- if (t1FontNames[i].fontFileID == *id) {
- psName->clear();
- psName->insert(0, t1FontNames[i].psName);
- return;
- }
- }
- if (t1FontNameLen == t1FontNameSize) {
- t1FontNameSize *= 2;
- t1FontNames = (PST1FontName *)greallocn(t1FontNames, t1FontNameSize,
- sizeof(PST1FontName));
- }
- t1FontNames[t1FontNameLen].fontFileID = *id;
- t1FontNames[t1FontNameLen].psName = psName->copy();
- ++t1FontNameLen;
-
- // beginning comment
- writePSFmt("%%BeginResource: font {0:t}\n", psName);
- embFontList->append("%%+ font ");
- embFontList->append(psName->c_str());
- embFontList->append("\n");
-
- // convert it to a Type 0 font
- if ((fontBuf = font->readEmbFontFile(xref, &fontLen))) {
- if ((ffTT = FoFiTrueType::make(fontBuf, fontLen))) {
- if (ffTT->isOpenTypeCFF()) {
- if (globalParams->getPSLevel() >= psLevel3) {
- // Level 3: use a CID font
- ffTT->convertToCIDType0(psName->c_str(),
- ((GfxCIDFont *)font)->getCIDToGID(),
- ((GfxCIDFont *)font)->getCIDToGIDLen(),
- outputFunc, outputStream);
- } else {
- // otherwise: use a non-CID composite font
- ffTT->convertToType0(psName->c_str(),
- ((GfxCIDFont *)font)->getCIDToGID(),
- ((GfxCIDFont *)font)->getCIDToGIDLen(),
- outputFunc, outputStream);
- }
- }
- delete ffTT;
- }
- gfree(fontBuf);
- }
-
- // ending comment
- writePS("%%EndResource\n");
+void PSOutputDev::setupEmbeddedOpenTypeCFFFont(GfxFont *font, Ref *id, GooString *psName)
+{
+ char *fontBuf;
+ int fontLen;
+ FoFiTrueType *ffTT;
+ int i;
+
+ // check if font is already embedded
+ for (i = 0; i < t1FontNameLen; ++i) {
+ if (t1FontNames[i].fontFileID == *id) {
+ psName->clear();
+ psName->insert(0, t1FontNames[i].psName);
+ return;
+ }
+ }
+ if (t1FontNameLen == t1FontNameSize) {
+ t1FontNameSize *= 2;
+ t1FontNames = (PST1FontName *)greallocn(t1FontNames, t1FontNameSize, sizeof(PST1FontName));
+ }
+ t1FontNames[t1FontNameLen].fontFileID = *id;
+ t1FontNames[t1FontNameLen].psName = psName->copy();
+ ++t1FontNameLen;
+
+ // beginning comment
+ writePSFmt("%%BeginResource: font {0:t}\n", psName);
+ embFontList->append("%%+ font ");
+ embFontList->append(psName->c_str());
+ embFontList->append("\n");
+
+ // convert it to a Type 0 font
+ if ((fontBuf = font->readEmbFontFile(xref, &fontLen))) {
+ if ((ffTT = FoFiTrueType::make(fontBuf, fontLen))) {
+ if (ffTT->isOpenTypeCFF()) {
+ if (globalParams->getPSLevel() >= psLevel3) {
+ // Level 3: use a CID font
+ ffTT->convertToCIDType0(psName->c_str(), ((GfxCIDFont *)font)->getCIDToGID(), ((GfxCIDFont *)font)->getCIDToGIDLen(), outputFunc, outputStream);
+ } else {
+ // otherwise: use a non-CID composite font
+ ffTT->convertToType0(psName->c_str(), ((GfxCIDFont *)font)->getCIDToGID(), ((GfxCIDFont *)font)->getCIDToGIDLen(), outputFunc, outputStream);
+ }
+ }
+ delete ffTT;
+ }
+ gfree(fontBuf);
+ }
+
+ // ending comment
+ writePS("%%EndResource\n");
}
-void PSOutputDev::setupType3Font(GfxFont *font, GooString *psName,
- Dict *parentResDict) {
- Dict *resDict;
- Dict *charProcs;
- Gfx *gfx;
- PDFRectangle box;
- const double *m;
- GooString *buf;
- int i;
-
- // set up resources used by font
- if ((resDict = ((Gfx8BitFont *)font)->getResources())) {
- inType3Char = true;
- setupResources(resDict);
- inType3Char = false;
- } else {
- resDict = parentResDict;
- }
-
- // beginning comment
- writePSFmt("%%BeginResource: font {0:t}\n", psName);
- embFontList->append("%%+ font ");
- embFontList->append(psName->c_str());
- embFontList->append("\n");
-
- // font dictionary
- writePS("8 dict begin\n");
- writePS("/FontType 3 def\n");
- m = font->getFontMatrix();
- writePSFmt("/FontMatrix [{0:.6g} {1:.6g} {2:.6g} {3:.6g} {4:.6g} {5:.6g}] def\n",
- m[0], m[1], m[2], m[3], m[4], m[5]);
- m = font->getFontBBox();
- writePSFmt("/FontBBox [{0:.6g} {1:.6g} {2:.6g} {3:.6g}] def\n",
- m[0], m[1], m[2], m[3]);
- writePS("/Encoding 256 array def\n");
- writePS(" 0 1 255 { Encoding exch /.notdef put } for\n");
- writePS("/BuildGlyph {\n");
- writePS(" exch /CharProcs get exch\n");
- writePS(" 2 copy known not { pop /.notdef } if\n");
- writePS(" get exec\n");
- writePS("} bind def\n");
- writePS("/BuildChar {\n");
- writePS(" 1 index /Encoding get exch get\n");
- writePS(" 1 index /BuildGlyph get exec\n");
- writePS("} bind def\n");
- if ((charProcs = ((Gfx8BitFont *)font)->getCharProcs())) {
- writePSFmt("/CharProcs {0:d} dict def\n", charProcs->getLength());
- writePS("CharProcs begin\n");
- box.x1 = m[0];
- box.y1 = m[1];
- box.x2 = m[2];
- box.y2 = m[3];
- gfx = new Gfx(doc, this, resDict, &box, nullptr);
- inType3Char = true;
- for (i = 0; i < charProcs->getLength(); ++i) {
- t3FillColorOnly = false;
- t3Cacheable = false;
- t3NeedsRestore = false;
- writePS("/");
- writePSName(charProcs->getKey(i));
- writePS(" {\n");
- Object charProc = charProcs->getVal(i);
- gfx->display(&charProc);
- if (t3String) {
- if (t3Cacheable) {
- buf = GooString::format("{0:.6g} {1:.6g} {2:.6g} {3:.6g} {4:.6g} {5:.6g} setcachedevice\n",
- t3WX, t3WY, t3LLX, t3LLY, t3URX, t3URY);
- } else {
- buf = GooString::format("{0:.6g} {1:.6g} setcharwidth\n", t3WX, t3WY);
- }
- (*outputFunc)(outputStream, buf->c_str(), buf->getLength());
- delete buf;
- (*outputFunc)(outputStream, t3String->c_str(),
- t3String->getLength());
- delete t3String;
- t3String = nullptr;
- }
- if (t3NeedsRestore) {
- (*outputFunc)(outputStream, "Q\n", 2);
- }
- writePS("} def\n");
+void PSOutputDev::setupType3Font(GfxFont *font, GooString *psName, Dict *parentResDict)
+{
+ Dict *resDict;
+ Dict *charProcs;
+ Gfx *gfx;
+ PDFRectangle box;
+ const double *m;
+ GooString *buf;
+ int i;
+
+ // set up resources used by font
+ if ((resDict = ((Gfx8BitFont *)font)->getResources())) {
+ inType3Char = true;
+ setupResources(resDict);
+ inType3Char = false;
+ } else {
+ resDict = parentResDict;
+ }
+
+ // beginning comment
+ writePSFmt("%%BeginResource: font {0:t}\n", psName);
+ embFontList->append("%%+ font ");
+ embFontList->append(psName->c_str());
+ embFontList->append("\n");
+
+ // font dictionary
+ writePS("8 dict begin\n");
+ writePS("/FontType 3 def\n");
+ m = font->getFontMatrix();
+ writePSFmt("/FontMatrix [{0:.6g} {1:.6g} {2:.6g} {3:.6g} {4:.6g} {5:.6g}] def\n", m[0], m[1], m[2], m[3], m[4], m[5]);
+ m = font->getFontBBox();
+ writePSFmt("/FontBBox [{0:.6g} {1:.6g} {2:.6g} {3:.6g}] def\n", m[0], m[1], m[2], m[3]);
+ writePS("/Encoding 256 array def\n");
+ writePS(" 0 1 255 { Encoding exch /.notdef put } for\n");
+ writePS("/BuildGlyph {\n");
+ writePS(" exch /CharProcs get exch\n");
+ writePS(" 2 copy known not { pop /.notdef } if\n");
+ writePS(" get exec\n");
+ writePS("} bind def\n");
+ writePS("/BuildChar {\n");
+ writePS(" 1 index /Encoding get exch get\n");
+ writePS(" 1 index /BuildGlyph get exec\n");
+ writePS("} bind def\n");
+ if ((charProcs = ((Gfx8BitFont *)font)->getCharProcs())) {
+ writePSFmt("/CharProcs {0:d} dict def\n", charProcs->getLength());
+ writePS("CharProcs begin\n");
+ box.x1 = m[0];
+ box.y1 = m[1];
+ box.x2 = m[2];
+ box.y2 = m[3];
+ gfx = new Gfx(doc, this, resDict, &box, nullptr);
+ inType3Char = true;
+ for (i = 0; i < charProcs->getLength(); ++i) {
+ t3FillColorOnly = false;
+ t3Cacheable = false;
+ t3NeedsRestore = false;
+ writePS("/");
+ writePSName(charProcs->getKey(i));
+ writePS(" {\n");
+ Object charProc = charProcs->getVal(i);
+ gfx->display(&charProc);
+ if (t3String) {
+ if (t3Cacheable) {
+ buf = GooString::format("{0:.6g} {1:.6g} {2:.6g} {3:.6g} {4:.6g} {5:.6g} setcachedevice\n", t3WX, t3WY, t3LLX, t3LLY, t3URX, t3URY);
+ } else {
+ buf = GooString::format("{0:.6g} {1:.6g} setcharwidth\n", t3WX, t3WY);
+ }
+ (*outputFunc)(outputStream, buf->c_str(), buf->getLength());
+ delete buf;
+ (*outputFunc)(outputStream, t3String->c_str(), t3String->getLength());
+ delete t3String;
+ t3String = nullptr;
+ }
+ if (t3NeedsRestore) {
+ (*outputFunc)(outputStream, "Q\n", 2);
+ }
+ writePS("} def\n");
+ }
+ inType3Char = false;
+ delete gfx;
+ writePS("end\n");
}
- inType3Char = false;
- delete gfx;
- writePS("end\n");
- }
- writePS("currentdict end\n");
- writePSFmt("/{0:t} exch definefont pop\n", psName);
+ writePS("currentdict end\n");
+ writePSFmt("/{0:t} exch definefont pop\n", psName);
- // ending comment
- writePS("%%EndResource\n");
+ // ending comment
+ writePS("%%EndResource\n");
}
// Make a unique PS font name, based on the names given in the PDF
-// font object, and an object ID (font file object for
-GooString *PSOutputDev::makePSFontName(GfxFont *font, const Ref *id) {
- GooString *psName;
- const GooString *s;
+// font object, and an object ID (font file object for
+GooString *PSOutputDev::makePSFontName(GfxFont *font, const Ref *id)
+{
+ GooString *psName;
+ const GooString *s;
- if ((s = font->getEmbeddedFontName())) {
- psName = filterPSName(s);
- if (fontNames.emplace(psName->toStr()).second) {
- return psName;
- }
- delete psName;
- }
- if ((s = font->getName())) {
- psName = filterPSName(s);
- if (fontNames.emplace(psName->toStr()).second) {
- return psName;
+ if ((s = font->getEmbeddedFontName())) {
+ psName = filterPSName(s);
+ if (fontNames.emplace(psName->toStr()).second) {
+ return psName;
+ }
+ delete psName;
}
- delete psName;
- }
- psName = GooString::format("FF{0:d}_{1:d}", id->num, id->gen);
- if ((s = font->getEmbeddedFontName())) {
- s = filterPSName(s);
- psName->append('_')->append(s);
- delete s;
- } else if ((s = font->getName())) {
- s = filterPSName(s);
- psName->append('_')->append(s);
- delete s;
- }
- fontNames.emplace(psName->toStr());
- return psName;
+ if ((s = font->getName())) {
+ psName = filterPSName(s);
+ if (fontNames.emplace(psName->toStr()).second) {
+ return psName;
+ }
+ delete psName;
+ }
+ psName = GooString::format("FF{0:d}_{1:d}", id->num, id->gen);
+ if ((s = font->getEmbeddedFontName())) {
+ s = filterPSName(s);
+ psName->append('_')->append(s);
+ delete s;
+ } else if ((s = font->getName())) {
+ s = filterPSName(s);
+ psName->append('_')->append(s);
+ delete s;
+ }
+ fontNames.emplace(psName->toStr());
+ return psName;
}
-void PSOutputDev::setupImages(Dict *resDict) {
- Ref imgID;
-
- if (!(mode == psModeForm || inType3Char || preloadImagesForms)) {
- return;
- }
-
- //----- recursively scan XObjects
- Object xObjDict = resDict->lookup("XObject");
- if (xObjDict.isDict()) {
- for (int i = 0; i < xObjDict.dictGetLength(); ++i) {
- const Object &xObjRef = xObjDict.dictGetValNF(i);
- Object xObj = xObjDict.dictGetVal(i);
- if (xObj.isStream()) {
- Object subtypeObj = xObj.streamGetDict()->lookup("Subtype");
- if (subtypeObj.isName("Image")) {
- if (xObjRef.isRef()) {
- imgID = xObjRef.getRef();
- int j;
- for (j = 0; j < imgIDLen; ++j) {
- if (imgIDs[j] == imgID) {
- break;
- }
- }
- if (j == imgIDLen) {
- if (imgIDLen >= imgIDSize) {
- if (imgIDSize == 0) {
- imgIDSize = 64;
- } else {
- imgIDSize *= 2;
- }
- imgIDs = (Ref *)greallocn(imgIDs, imgIDSize, sizeof(Ref));
- }
- imgIDs[imgIDLen++] = imgID;
- setupImage(imgID, xObj.getStream(), false);
- if (level >= psLevel3) {
- Object maskObj = xObj.streamGetDict()->lookup("Mask");
- if (maskObj.isStream()) {
- setupImage(imgID, maskObj.getStream(), true);
- }
- }
- }
- } else {
- error(errSyntaxError, -1,
- "Image in resource dict is not an indirect reference");
- }
- }
- }
- }
- }
+void PSOutputDev::setupImages(Dict *resDict)
+{
+ Ref imgID;
+
+ if (!(mode == psModeForm || inType3Char || preloadImagesForms)) {
+ return;
+ }
+
+ //----- recursively scan XObjects
+ Object xObjDict = resDict->lookup("XObject");
+ if (xObjDict.isDict()) {
+ for (int i = 0; i < xObjDict.dictGetLength(); ++i) {
+ const Object &xObjRef = xObjDict.dictGetValNF(i);
+ Object xObj = xObjDict.dictGetVal(i);
+ if (xObj.isStream()) {
+ Object subtypeObj = xObj.streamGetDict()->lookup("Subtype");
+ if (subtypeObj.isName("Image")) {
+ if (xObjRef.isRef()) {
+ imgID = xObjRef.getRef();
+ int j;
+ for (j = 0; j < imgIDLen; ++j) {
+ if (imgIDs[j] == imgID) {
+ break;
+ }
+ }
+ if (j == imgIDLen) {
+ if (imgIDLen >= imgIDSize) {
+ if (imgIDSize == 0) {
+ imgIDSize = 64;
+ } else {
+ imgIDSize *= 2;
+ }
+ imgIDs = (Ref *)greallocn(imgIDs, imgIDSize, sizeof(Ref));
+ }
+ imgIDs[imgIDLen++] = imgID;
+ setupImage(imgID, xObj.getStream(), false);
+ if (level >= psLevel3) {
+ Object maskObj = xObj.streamGetDict()->lookup("Mask");
+ if (maskObj.isStream()) {
+ setupImage(imgID, maskObj.getStream(), true);
+ }
+ }
+ }
+ } else {
+ error(errSyntaxError, -1, "Image in resource dict is not an indirect reference");
+ }
+ }
+ }
+ }
+ }
}
-void PSOutputDev::setupImage(Ref id, Stream *str, bool mask) {
- bool useFlate, useLZW, useRLE, useCompressed, doUseASCIIHex;
- GooString *s;
- int c;
- int size, line, col, i;
- int outerSize, outer;
-
- // filters
- //~ this does not correctly handle the DeviceN color space
- //~ -- need to use DeviceNRecoder
-
- useFlate = useLZW = useRLE = false;
- useCompressed = false;
- doUseASCIIHex = false;
-
- if (level < psLevel2) {
- doUseASCIIHex = true;
- } else {
- if (uncompressPreloadedImages) {
- /* nothing to do */;
+void PSOutputDev::setupImage(Ref id, Stream *str, bool mask)
+{
+ bool useFlate, useLZW, useRLE, useCompressed, doUseASCIIHex;
+ GooString *s;
+ int c;
+ int size, line, col, i;
+ int outerSize, outer;
+
+ // filters
+ //~ this does not correctly handle the DeviceN color space
+ //~ -- need to use DeviceNRecoder
+
+ useFlate = useLZW = useRLE = false;
+ useCompressed = false;
+ doUseASCIIHex = false;
+
+ if (level < psLevel2) {
+ doUseASCIIHex = true;
} else {
- s = str->getPSFilter(level < psLevel3 ? 2 : 3, "");
- if (s) {
- useCompressed = true;
- delete s;
- } else {
- if (level >= psLevel3 && getEnableFlate()) {
- useFlate = true;
- } else if (getEnableLZW()) {
- useLZW = true;
- } else {
- useRLE = true;
- }
- }
- }
- doUseASCIIHex = useASCIIHex;
- }
- if (useCompressed) {
- str = str->getUndecodedStream();
- }
+ if (uncompressPreloadedImages) {
+ /* nothing to do */;
+ } else {
+ s = str->getPSFilter(level < psLevel3 ? 2 : 3, "");
+ if (s) {
+ useCompressed = true;
+ delete s;
+ } else {
+ if (level >= psLevel3 && getEnableFlate()) {
+ useFlate = true;
+ } else if (getEnableLZW()) {
+ useLZW = true;
+ } else {
+ useRLE = true;
+ }
+ }
+ }
+ doUseASCIIHex = useASCIIHex;
+ }
+ if (useCompressed) {
+ str = str->getUndecodedStream();
+ }
#ifdef ENABLE_ZLIB
- if (useFlate) {
- str = new FlateEncoder(str);
- } else
+ if (useFlate) {
+ str = new FlateEncoder(str);
+ } else
#endif
- if (useLZW) {
- str = new LZWEncoder(str);
- } else if (useRLE) {
- str = new RunLengthEncoder(str);
- }
- if (doUseASCIIHex) {
- str = new ASCIIHexEncoder(str);
- } else {
- str = new ASCII85Encoder(str);
- }
-
- // compute image data size
- str->reset();
- col = size = 0;
- do {
- do {
- c = str->getChar();
- } while (c == '\n' || c == '\r');
- if (c == (doUseASCIIHex ? '>' : '~') || c == EOF) {
- break;
+ if (useLZW) {
+ str = new LZWEncoder(str);
+ } else if (useRLE) {
+ str = new RunLengthEncoder(str);
}
- if (c == 'z') {
- ++col;
+ if (doUseASCIIHex) {
+ str = new ASCIIHexEncoder(str);
} else {
- ++col;
- for (i = 1; i <= (doUseASCIIHex ? 1 : 4); ++i) {
- do {
- c = str->getChar();
- } while (c == '\n' || c == '\r');
- if (c == (doUseASCIIHex ? '>' : '~') || c == EOF) {
- break;
- }
- ++col;
- }
- if (c == (doUseASCIIHex ? '>' : '~') || c == EOF) {
- break;
- }
- }
- if (col > 225) {
- ++size;
- col = 0;
- }
- } while (c != (doUseASCIIHex ? '>' : '~') && c != EOF);
- // add one entry for the final line of data; add another entry
- // because the LZWDecode/RunLengthDecode filter may read past the end
- ++size;
- if (useLZW || useRLE) {
+ str = new ASCII85Encoder(str);
+ }
+
+ // compute image data size
+ str->reset();
+ col = size = 0;
+ do {
+ do {
+ c = str->getChar();
+ } while (c == '\n' || c == '\r');
+ if (c == (doUseASCIIHex ? '>' : '~') || c == EOF) {
+ break;
+ }
+ if (c == 'z') {
+ ++col;
+ } else {
+ ++col;
+ for (i = 1; i <= (doUseASCIIHex ? 1 : 4); ++i) {
+ do {
+ c = str->getChar();
+ } while (c == '\n' || c == '\r');
+ if (c == (doUseASCIIHex ? '>' : '~') || c == EOF) {
+ break;
+ }
+ ++col;
+ }
+ if (c == (doUseASCIIHex ? '>' : '~') || c == EOF) {
+ break;
+ }
+ }
+ if (col > 225) {
+ ++size;
+ col = 0;
+ }
+ } while (c != (doUseASCIIHex ? '>' : '~') && c != EOF);
+ // add one entry for the final line of data; add another entry
+ // because the LZWDecode/RunLengthDecode filter may read past the end
++size;
- }
- outerSize = size/65535 + 1;
-
- writePSFmt("{0:d} array dup /{1:s}Data_{2:d}_{3:d} exch def\n",
- outerSize, mask ? "Mask" : "Im", id.num, id.gen);
- str->close();
-
- // write the data into the array
- str->reset();
- for (outer = 0;outer < outerSize;outer++) {
- int innerSize = size > 65535 ? 65535 : size;
-
- // put the inner array into the outer array
- writePSFmt("{0:d} array 1 index {1:d} 2 index put\n",
- innerSize, outer);
- line = col = 0;
- writePS((char *)(doUseASCIIHex ? "dup 0 <" : "dup 0 <~"));
- for (;;) {
- do {
- c = str->getChar();
- } while (c == '\n' || c == '\r');
- if (c == (doUseASCIIHex ? '>' : '~') || c == EOF) {
- break;
- }
- if (c == 'z') {
- writePSChar(c);
- ++col;
- } else {
- writePSChar(c);
- ++col;
- for (i = 1; i <= (doUseASCIIHex ? 1 : 4); ++i) {
- do {
- c = str->getChar();
- } while (c == '\n' || c == '\r');
- if (c == (doUseASCIIHex ? '>' : '~') || c == EOF) {
- break;
- }
- writePSChar(c);
- ++col;
- }
- }
- if (c == (doUseASCIIHex ? '>' : '~') || c == EOF) {
- break;
- }
- // each line is: "dup nnnnn <~...data...~> put<eol>"
- // so max data length = 255 - 20 = 235
- // chunks are 1 or 4 bytes each, so we have to stop at 232
- // but make it 225 just to be safe
- if (col > 225) {
- writePS((char *)(doUseASCIIHex ? "> put\n" : "~> put\n"));
- ++line;
- if (line >= innerSize) break;
- writePSFmt((char *)(doUseASCIIHex ? "dup {0:d} <" : "dup {0:d} <~"), line);
- col = 0;
- }
- }
- if (c == (doUseASCIIHex ? '>' : '~') || c == EOF) {
- writePS((char *)(doUseASCIIHex ? "> put\n" : "~> put\n"));
- if (useLZW || useRLE) {
- ++line;
- writePSFmt("{0:d} <> put\n", line);
- } else {
- writePS("pop\n");
- }
- break;
+ if (useLZW || useRLE) {
+ ++size;
+ }
+ outerSize = size / 65535 + 1;
+
+ writePSFmt("{0:d} array dup /{1:s}Data_{2:d}_{3:d} exch def\n", outerSize, mask ? "Mask" : "Im", id.num, id.gen);
+ str->close();
+
+ // write the data into the array
+ str->reset();
+ for (outer = 0; outer < outerSize; outer++) {
+ int innerSize = size > 65535 ? 65535 : size;
+
+ // put the inner array into the outer array
+ writePSFmt("{0:d} array 1 index {1:d} 2 index put\n", innerSize, outer);
+ line = col = 0;
+ writePS((char *)(doUseASCIIHex ? "dup 0 <" : "dup 0 <~"));
+ for (;;) {
+ do {
+ c = str->getChar();
+ } while (c == '\n' || c == '\r');
+ if (c == (doUseASCIIHex ? '>' : '~') || c == EOF) {
+ break;
+ }
+ if (c == 'z') {
+ writePSChar(c);
+ ++col;
+ } else {
+ writePSChar(c);
+ ++col;
+ for (i = 1; i <= (doUseASCIIHex ? 1 : 4); ++i) {
+ do {
+ c = str->getChar();
+ } while (c == '\n' || c == '\r');
+ if (c == (doUseASCIIHex ? '>' : '~') || c == EOF) {
+ break;
+ }
+ writePSChar(c);
+ ++col;
+ }
+ }
+ if (c == (doUseASCIIHex ? '>' : '~') || c == EOF) {
+ break;
+ }
+ // each line is: "dup nnnnn <~...data...~> put<eol>"
+ // so max data length = 255 - 20 = 235
+ // chunks are 1 or 4 bytes each, so we have to stop at 232
+ // but make it 225 just to be safe
+ if (col > 225) {
+ writePS((char *)(doUseASCIIHex ? "> put\n" : "~> put\n"));
+ ++line;
+ if (line >= innerSize)
+ break;
+ writePSFmt((char *)(doUseASCIIHex ? "dup {0:d} <" : "dup {0:d} <~"), line);
+ col = 0;
+ }
+ }
+ if (c == (doUseASCIIHex ? '>' : '~') || c == EOF) {
+ writePS((char *)(doUseASCIIHex ? "> put\n" : "~> put\n"));
+ if (useLZW || useRLE) {
+ ++line;
+ writePSFmt("{0:d} <> put\n", line);
+ } else {
+ writePS("pop\n");
+ }
+ break;
+ }
+ writePS("pop\n");
+ size -= innerSize;
}
writePS("pop\n");
- size -= innerSize;
- }
- writePS("pop\n");
- str->close();
+ str->close();
- delete str;
+ delete str;
}
-void PSOutputDev::setupForms(Dict *resDict) {
- if (!preloadImagesForms) {
- return;
- }
-
- Object xObjDict = resDict->lookup("XObject");
- if (xObjDict.isDict()) {
- for (int i = 0; i < xObjDict.dictGetLength(); ++i) {
- const Object &xObjRef = xObjDict.dictGetValNF(i);
- Object xObj = xObjDict.dictGetVal(i);
- if (xObj.isStream()) {
- Object subtypeObj = xObj.streamGetDict()->lookup("Subtype");
- if (subtypeObj.isName("Form")) {
- if (xObjRef.isRef()) {
- setupForm(xObjRef.getRef(), &xObj);
- } else {
- error(errSyntaxError, -1,
- "Form in resource dict is not an indirect reference");
- }
- }
- }
- }
- }
+void PSOutputDev::setupForms(Dict *resDict)
+{
+ if (!preloadImagesForms) {
+ return;
+ }
+
+ Object xObjDict = resDict->lookup("XObject");
+ if (xObjDict.isDict()) {
+ for (int i = 0; i < xObjDict.dictGetLength(); ++i) {
+ const Object &xObjRef = xObjDict.dictGetValNF(i);
+ Object xObj = xObjDict.dictGetVal(i);
+ if (xObj.isStream()) {
+ Object subtypeObj = xObj.streamGetDict()->lookup("Subtype");
+ if (subtypeObj.isName("Form")) {
+ if (xObjRef.isRef()) {
+ setupForm(xObjRef.getRef(), &xObj);
+ } else {
+ error(errSyntaxError, -1, "Form in resource dict is not an indirect reference");
+ }
+ }
+ }
+ }
+ }
}
-void PSOutputDev::setupForm(Ref id, Object *strObj) {
- Dict *dict, *resDict;
- double m[6], bbox[4];
- PDFRectangle box;
- Gfx *gfx;
+void PSOutputDev::setupForm(Ref id, Object *strObj)
+{
+ Dict *dict, *resDict;
+ double m[6], bbox[4];
+ PDFRectangle box;
+ Gfx *gfx;
- // check if form is already defined
- for (int i = 0; i < formIDLen; ++i) {
- if (formIDs[i] == id) {
- return;
+ // check if form is already defined
+ for (int i = 0; i < formIDLen; ++i) {
+ if (formIDs[i] == id) {
+ return;
+ }
}
- }
- // add entry to formIDs list
- if (formIDLen >= formIDSize) {
- if (formIDSize == 0) {
- formIDSize = 64;
+ // add entry to formIDs list
+ if (formIDLen >= formIDSize) {
+ if (formIDSize == 0) {
+ formIDSize = 64;
+ } else {
+ formIDSize *= 2;
+ }
+ formIDs = (Ref *)greallocn(formIDs, formIDSize, sizeof(Ref));
+ }
+ formIDs[formIDLen++] = id;
+
+ dict = strObj->streamGetDict();
+
+ // get bounding box
+ Object bboxObj = dict->lookup("BBox");
+ if (!bboxObj.isArray()) {
+ error(errSyntaxError, -1, "Bad form bounding box");
+ return;
+ }
+ for (int i = 0; i < 4; ++i) {
+ Object obj1 = bboxObj.arrayGet(i);
+ bbox[i] = obj1.getNum();
+ }
+
+ // get matrix
+ Object matrixObj = dict->lookup("Matrix");
+ if (matrixObj.isArray()) {
+ for (int i = 0; i < 6; ++i) {
+ Object obj1 = matrixObj.arrayGet(i);
+ m[i] = obj1.getNum();
+ }
} else {
- formIDSize *= 2;
- }
- formIDs = (Ref *)greallocn(formIDs, formIDSize, sizeof(Ref));
- }
- formIDs[formIDLen++] = id;
-
- dict = strObj->streamGetDict();
-
- // get bounding box
- Object bboxObj = dict->lookup("BBox");
- if (!bboxObj.isArray()) {
- error(errSyntaxError, -1, "Bad form bounding box");
- return;
- }
- for (int i = 0; i < 4; ++i) {
- Object obj1 = bboxObj.arrayGet(i);
- bbox[i] = obj1.getNum();
- }
-
- // get matrix
- Object matrixObj = dict->lookup("Matrix");
- if (matrixObj.isArray()) {
- for (int i = 0; i < 6; ++i) {
- Object obj1 = matrixObj.arrayGet(i);
- m[i] = obj1.getNum();
- }
- } else {
- m[0] = 1; m[1] = 0;
- m[2] = 0; m[3] = 1;
- m[4] = 0; m[5] = 0;
- }
-
- // get resources
- Object resObj = dict->lookup("Resources");
- resDict = resObj.isDict() ? resObj.getDict() : nullptr;
-
- writePSFmt("/f_{0:d}_{1:d} {{\n", id.num, id.gen);
- writePS("q\n");
- writePSFmt("[{0:.6gs} {1:.6gs} {2:.6gs} {3:.6gs} {4:.6gs} {5:.6gs}] cm\n",
- m[0], m[1], m[2], m[3], m[4], m[5]);
-
- box.x1 = bbox[0];
- box.y1 = bbox[1];
- box.x2 = bbox[2];
- box.y2 = bbox[3];
- gfx = new Gfx(doc, this, resDict, &box, &box);
- gfx->display(strObj);
- delete gfx;
-
- writePS("Q\n");
- writePS("} def\n");
+ m[0] = 1;
+ m[1] = 0;
+ m[2] = 0;
+ m[3] = 1;
+ m[4] = 0;
+ m[5] = 0;
+ }
+
+ // get resources
+ Object resObj = dict->lookup("Resources");
+ resDict = resObj.isDict() ? resObj.getDict() : nullptr;
+
+ writePSFmt("/f_{0:d}_{1:d} {{\n", id.num, id.gen);
+ writePS("q\n");
+ writePSFmt("[{0:.6gs} {1:.6gs} {2:.6gs} {3:.6gs} {4:.6gs} {5:.6gs}] cm\n", m[0], m[1], m[2], m[3], m[4], m[5]);
+
+ box.x1 = bbox[0];
+ box.y1 = bbox[1];
+ box.x2 = bbox[2];
+ box.y2 = bbox[3];
+ gfx = new Gfx(doc, this, resDict, &box, &box);
+ gfx->display(strObj);
+ delete gfx;
+
+ writePS("Q\n");
+ writePS("} def\n");
}
-bool PSOutputDev::checkPageSlice(Page *page, double /*hDPI*/, double /*vDPI*/,
- int rotateA, bool useMediaBox, bool crop,
- int sliceX, int sliceY,
- int sliceW, int sliceH,
- bool printing,
- bool (*abortCheckCbk)(void *data),
- void *abortCheckCbkData,
- bool (*annotDisplayDecideCbk)(Annot *annot, void *user_data),
- void *annotDisplayDecideCbkData) {
- PreScanOutputDev *scan;
- bool rasterize;
+bool PSOutputDev::checkPageSlice(Page *page, double /*hDPI*/, double /*vDPI*/, int rotateA, bool useMediaBox, bool crop, int sliceX, int sliceY, int sliceW, int sliceH, bool printing, bool (*abortCheckCbk)(void *data),
+ void *abortCheckCbkData, bool (*annotDisplayDecideCbk)(Annot *annot, void *user_data), void *annotDisplayDecideCbkData)
+{
+ PreScanOutputDev *scan;
+ bool rasterize;
#ifdef HAVE_SPLASH
- bool useFlate, useLZW;
- SplashOutputDev *splashOut;
- SplashColor paperColor;
- PDFRectangle box;
- GfxState *state;
- SplashBitmap *bitmap;
- Stream *str0, *str;
- unsigned char *p;
- unsigned char col[4];
- double hDPI2, vDPI2;
- double m0, m1, m2, m3, m4, m5;
- int nStripes, stripeH, stripeY;
- int c, w, h, x, y, comp, i;
- int numComps, initialNumComps;
- char hexBuf[32*2 + 2]; // 32 values X 2 chars/value + line ending + null
- unsigned char digit;
- bool isGray;
+ bool useFlate, useLZW;
+ SplashOutputDev *splashOut;
+ SplashColor paperColor;
+ PDFRectangle box;
+ GfxState *state;
+ SplashBitmap *bitmap;
+ Stream *str0, *str;
+ unsigned char *p;
+ unsigned char col[4];
+ double hDPI2, vDPI2;
+ double m0, m1, m2, m3, m4, m5;
+ int nStripes, stripeH, stripeY;
+ int c, w, h, x, y, comp, i;
+ int numComps, initialNumComps;
+ char hexBuf[32 * 2 + 2]; // 32 values X 2 chars/value + line ending + null
+ unsigned char digit;
+ bool isGray;
#endif
- if (!postInitDone) {
- postInit();
- }
- if (forceRasterize == psAlwaysRasterize) {
- rasterize = true;
- } else if (forceRasterize == psNeverRasterize) {
- rasterize = false;
- } else {
- scan = new PreScanOutputDev(doc);
- page->displaySlice(scan, 72, 72, rotateA, useMediaBox, crop,
- sliceX, sliceY, sliceW, sliceH,
- printing, abortCheckCbk, abortCheckCbkData,
- annotDisplayDecideCbk, annotDisplayDecideCbkData);
- rasterize = scan->usesTransparency() || scan->usesPatternImageMask();
- delete scan;
- }
- if (!rasterize) {
- return true;
- }
+ if (!postInitDone) {
+ postInit();
+ }
+ if (forceRasterize == psAlwaysRasterize) {
+ rasterize = true;
+ } else if (forceRasterize == psNeverRasterize) {
+ rasterize = false;
+ } else {
+ scan = new PreScanOutputDev(doc);
+ page->displaySlice(scan, 72, 72, rotateA, useMediaBox, crop, sliceX, sliceY, sliceW, sliceH, printing, abortCheckCbk, abortCheckCbkData, annotDisplayDecideCbk, annotDisplayDecideCbkData);
+ rasterize = scan->usesTransparency() || scan->usesPatternImageMask();
+ delete scan;
+ }
+ if (!rasterize) {
+ return true;
+ }
#ifdef HAVE_SPLASH
- // get the rasterization parameters
- useFlate = getEnableFlate() && level >= psLevel3;
- useLZW = getEnableLZW();
- // start the PS page
- page->makeBox(rasterResolution, rasterResolution, rotateA, useMediaBox, false,
- sliceX, sliceY, sliceW, sliceH, &box, &crop);
- rotateA += page->getRotate();
- if (rotateA >= 360) {
- rotateA -= 360;
- } else if (rotateA < 0) {
- rotateA += 360;
- }
- state = new GfxState(rasterResolution, rasterResolution, &box, rotateA, false);
- startPage(page->getNum(), state, xref);
- delete state;
-
- // set up the SplashOutputDev
- if (rasterMono || level == psLevel1) {
- numComps = 1;
- paperColor[0] = 0xff;
- splashOut = new SplashOutputDev(splashModeMono8, 1, false,
- paperColor, false);
- } else if (level == psLevel1Sep || level == psLevel2Sep ||
- level == psLevel3Sep || globalParams->getOverprintPreview()) {
- numComps = 4;
- paperColor[0] = paperColor[1] = paperColor[2] = paperColor[3] = 0;
- splashOut = new SplashOutputDev(splashModeCMYK8, 1, false,
- paperColor, false);
- } else {
- numComps = 3;
- paperColor[0] = paperColor[1] = paperColor[2] = 0xff;
- splashOut = new SplashOutputDev(splashModeRGB8, 1, false,
- paperColor, false);
- }
- splashOut->setFontAntialias(rasterAntialias);
- splashOut->setVectorAntialias(rasterAntialias);
- splashOut->startDoc(doc);
-
- // break the page into stripes
- hDPI2 = xScale * rasterResolution;
- vDPI2 = yScale * rasterResolution;
- if (sliceW < 0 || sliceH < 0) {
- if (useMediaBox) {
- box = *page->getMediaBox();
+ // get the rasterization parameters
+ useFlate = getEnableFlate() && level >= psLevel3;
+ useLZW = getEnableLZW();
+ // start the PS page
+ page->makeBox(rasterResolution, rasterResolution, rotateA, useMediaBox, false, sliceX, sliceY, sliceW, sliceH, &box, &crop);
+ rotateA += page->getRotate();
+ if (rotateA >= 360) {
+ rotateA -= 360;
+ } else if (rotateA < 0) {
+ rotateA += 360;
+ }
+ state = new GfxState(rasterResolution, rasterResolution, &box, rotateA, false);
+ startPage(page->getNum(), state, xref);
+ delete state;
+
+ // set up the SplashOutputDev
+ if (rasterMono || level == psLevel1) {
+ numComps = 1;
+ paperColor[0] = 0xff;
+ splashOut = new SplashOutputDev(splashModeMono8, 1, false, paperColor, false);
+ } else if (level == psLevel1Sep || level == psLevel2Sep || level == psLevel3Sep || globalParams->getOverprintPreview()) {
+ numComps = 4;
+ paperColor[0] = paperColor[1] = paperColor[2] = paperColor[3] = 0;
+ splashOut = new SplashOutputDev(splashModeCMYK8, 1, false, paperColor, false);
} else {
- box = *page->getCropBox();
- }
- sliceX = sliceY = 0;
- sliceW = (int)((box.x2 - box.x1) * hDPI2 / 72.0);
- sliceH = (int)((box.y2 - box.y1) * vDPI2 / 72.0);
- }
- nStripes = (int)ceil((double)(sliceW * sliceH) /
- (double)rasterizationSliceSize);
- if (unlikely(nStripes == 0)) {
- delete splashOut;
- return false;
- }
- stripeH = (sliceH + nStripes - 1) / nStripes;
-
- // render the stripes
- initialNumComps = numComps;
- for (stripeY = sliceY; stripeY < sliceH; stripeY += stripeH) {
-
- // rasterize a stripe
- page->makeBox(hDPI2, vDPI2, 0, useMediaBox, false,
- sliceX, stripeY, sliceW, stripeH, &box, &crop);
- m0 = box.x2 - box.x1;
- m1 = 0;
- m2 = 0;
- m3 = box.y2 - box.y1;
- m4 = box.x1;
- m5 = box.y1;
- page->displaySlice(splashOut, hDPI2, vDPI2,
- (360 - page->getRotate()) % 360, useMediaBox, crop,
- sliceX, stripeY, sliceW, stripeH,
- printing, abortCheckCbk, abortCheckCbkData,
- annotDisplayDecideCbk, annotDisplayDecideCbkData);
-
- // draw the rasterized image
- bitmap = splashOut->getBitmap();
- numComps = initialNumComps;
- w = bitmap->getWidth();
- h = bitmap->getHeight();
- writePS("gsave\n");
- writePSFmt("[{0:.6g} {1:.6g} {2:.6g} {3:.6g} {4:.6g} {5:.6g}] concat\n",
- m0, m1, m2, m3, m4, m5);
- switch (level) {
- case psLevel1:
- writePSFmt("{0:d} {1:d} 8 [{2:d} 0 0 {3:d} 0 {4:d}] pdfIm1{5:s}\n",
- w, h, w, -h, h,
- useBinary ? "Bin" : "");
- p = bitmap->getDataPtr() + (h - 1) * bitmap->getRowSize();
- i = 0;
- if (useBinary) {
- for (y = 0; y < h; ++y) {
- for (x = 0; x < w; ++x) {
- hexBuf[i++] = *p++;
- if (i >= 64) {
- writePSBuf(hexBuf, i);
- i = 0;
- }
- }
- }
- } else {
- for (y = 0; y < h; ++y) {
- for (x = 0; x < w; ++x) {
- digit = *p / 16;
- hexBuf[i++] = digit + ((digit >= 10)? 'a' - 10: '0');
- digit = *p++ % 16;
- hexBuf[i++] = digit + ((digit >= 10)? 'a' - 10: '0');
- if (i >= 64) {
- hexBuf[i++] = '\n';
- writePSBuf(hexBuf, i);
- i = 0;
- }
- }
- }
- }
- if (i != 0) {
- if (!useBinary) {
- hexBuf[i++] = '\n';
- }
- writePSBuf(hexBuf, i);
- }
- break;
- case psLevel1Sep:
- p = bitmap->getDataPtr();
- // Check for an all gray image
- if (getOptimizeColorSpace()) {
- isGray = true;
- for (y = 0; y < h; ++y) {
- for (x = 0; x < w; ++x) {
- if (p[4*x] != p[4*x + 1] || p[4*x] != p[4*x + 2]) {
- isGray = false;
- y = h;
- break;
- }
- }
- p += bitmap->getRowSize();
- }
- } else {
- isGray = false;
- }
- writePSFmt("{0:d} {1:d} 8 [{2:d} 0 0 {3:d} 0 {4:d}] pdfIm1{5:s}{6:s}\n",
- w, h, w, -h, h,
- isGray ? "" : "Sep",
- useBinary ? "Bin" : "");
- p = bitmap->getDataPtr() + (h - 1) * bitmap->getRowSize();
- i = 0;
- col[0] = col[1] = col[2] = col[3] = 0;
- if (isGray) {
- int g;
- if ((psProcessBlack & processColors) == 0) {
- // Check if the image uses black
- for (y = 0; y < h; ++y) {
- for (x = 0; x < w; ++x) {
- if (p[4*x] > 0 || p[4*x + 3] > 0) {
- col[3] = 1;
- y = h;
- break;
- }
- }
- p -= bitmap->getRowSize();
- }
- p = bitmap->getDataPtr() + (h - 1) * bitmap->getRowSize();
- }
- for (y = 0; y < h; ++y) {
- if (useBinary) {
- // Binary gray image
- for (x = 0; x < w; ++x) {
- g = p[4*x] + p[4*x + 3];
- g = 255 - g;
- if (g < 0) g = 0;
- hexBuf[i++] = (unsigned char) g;
- if (i >= 64) {
- writePSBuf(hexBuf, i);
- i = 0;
- }
- }
- } else {
- // Hex gray image
- for (x = 0; x < w; ++x) {
- g = p[4*x] + p[4*x + 3];
- g = 255 - g;
- if (g < 0) g = 0;
- digit = g / 16;
- hexBuf[i++] = digit + ((digit >= 10)? 'a' - 10: '0');
- digit = g % 16;
- hexBuf[i++] = digit + ((digit >= 10)? 'a' - 10: '0');
- if (i >= 64) {
- hexBuf[i++] = '\n';
- writePSBuf(hexBuf, i);
- i = 0;
- }
- }
- }
- p -= bitmap->getRowSize();
- }
- } else if (((psProcessCyan | psProcessMagenta | psProcessYellow | psProcessBlack) & ~processColors) != 0) {
- // Color image, need to check color flags for each dot
- for (y = 0; y < h; ++y) {
- for (comp = 0; comp < 4; ++comp) {
- if (useBinary) {
- // Binary color image
- for (x = 0; x < w; ++x) {
- col[comp] |= p[4*x + comp];
- hexBuf[i++] = p[4*x + comp];
- if (i >= 64) {
- writePSBuf(hexBuf, i);
- i = 0;
- }
- }
- } else {
- // Gray color image
- for (x = 0; x < w; ++x) {
- col[comp] |= p[4*x + comp];
- digit = p[4*x + comp] / 16;
- hexBuf[i++] = digit + ((digit >= 10)? 'a' - 10: '0');
- digit = p[4*x + comp] % 16;
- hexBuf[i++] = digit + ((digit >= 10)? 'a' - 10: '0');
- if (i >= 64) {
- hexBuf[i++] = '\n';
- writePSBuf(hexBuf, i);
- i = 0;
- }
- }
- }
- }
- p -= bitmap->getRowSize();
- }
- } else {
- // Color image, do not need to check color flags
- for (y = 0; y < h; ++y) {
- for (comp = 0; comp < 4; ++comp) {
- if (useBinary) {
- // Binary color image
- for (x = 0; x < w; ++x) {
- hexBuf[i++] = p[4*x + comp];
- if (i >= 64) {
- writePSBuf(hexBuf, i);
- i = 0;
- }
- }
- } else {
- // Hex color image
- for (x = 0; x < w; ++x) {
- digit = p[4*x + comp] / 16;
- hexBuf[i++] = digit + ((digit >= 10)? 'a' - 10: '0');
- digit = p[4*x + comp] % 16;
- hexBuf[i++] = digit + ((digit >= 10)? 'a' - 10: '0');
- if (i >= 64) {
- hexBuf[i++] = '\n';
- writePSBuf(hexBuf, i);
- i = 0;
- }
- }
- }
- }
- p -= bitmap->getRowSize();
- }
- }
- if (i != 0) {
- if (!useBinary) {
- hexBuf[i++] = '\n';
- }
- writePSBuf(hexBuf, i);
- }
- if (col[0]) {
- processColors |= psProcessCyan;
- }
- if (col[1]) {
- processColors |= psProcessMagenta;
- }
- if (col[2]) {
- processColors |= psProcessYellow;
- }
- if (col[3]) {
- processColors |= psProcessBlack;
- }
- break;
- case psLevel2:
- case psLevel2Sep:
- case psLevel3:
- case psLevel3Sep:
- p = bitmap->getDataPtr() + (h - 1) * bitmap->getRowSize();
- str0 = new MemStream((char *)p, 0, w * h * numComps, Object(objNull));
- // Check for a color image that uses only gray
- if (!getOptimizeColorSpace()) {
- isGray = false;
- } else if (numComps == 4) {
- int compCyan;
- isGray = true;
- while ((compCyan = str0->getChar()) != EOF) {
- if (str0->getChar() != compCyan ||
- str0->getChar() != compCyan) {
- isGray = false;
- break;
- }
- str0->getChar();
- }
- } else if (numComps == 3) {
- int compRed;
- isGray = true;
- while ((compRed = str0->getChar()) != EOF) {
- if (str0->getChar() != compRed ||
- str0->getChar() != compRed) {
- isGray = false;
- break;
- }
- }
- } else {
- isGray = false;
- }
- str0->reset();
-#ifdef ENABLE_ZLIB
- if (useFlate) {
- if (isGray && numComps == 4) {
- str = new FlateEncoder(new CMYKGrayEncoder(str0));
- numComps = 1;
- } else if (isGray && numComps == 3) {
- str = new FlateEncoder(new RGBGrayEncoder(str0));
- numComps = 1;
+ numComps = 3;
+ paperColor[0] = paperColor[1] = paperColor[2] = 0xff;
+ splashOut = new SplashOutputDev(splashModeRGB8, 1, false, paperColor, false);
+ }
+ splashOut->setFontAntialias(rasterAntialias);
+ splashOut->setVectorAntialias(rasterAntialias);
+ splashOut->startDoc(doc);
+
+ // break the page into stripes
+ hDPI2 = xScale * rasterResolution;
+ vDPI2 = yScale * rasterResolution;
+ if (sliceW < 0 || sliceH < 0) {
+ if (useMediaBox) {
+ box = *page->getMediaBox();
} else {
- str = new FlateEncoder(str0);
+ box = *page->getCropBox();
}
- } else
-#endif
- if (useLZW) {
- if (isGray && numComps == 4) {
- str = new LZWEncoder(new CMYKGrayEncoder(str0));
- numComps = 1;
- } else if (isGray && numComps == 3) {
- str = new LZWEncoder(new RGBGrayEncoder(str0));
- numComps = 1;
- } else {
- str = new LZWEncoder(str0);
- }
- } else {
- if (isGray && numComps == 4) {
- str = new RunLengthEncoder(new CMYKGrayEncoder(str0));
- numComps = 1;
- } else if (isGray && numComps == 3) {
- str = new RunLengthEncoder(new RGBGrayEncoder(str0));
- numComps = 1;
- } else {
- str = new RunLengthEncoder(str0);
- }
- }
- if (numComps == 1) {
- writePS("/DeviceGray setcolorspace\n");
- } else if (numComps == 3) {
- writePS("/DeviceRGB setcolorspace\n");
- } else {
- writePS("/DeviceCMYK setcolorspace\n");
- }
- writePS("<<\n /ImageType 1\n");
- writePSFmt(" /Width {0:d}\n", bitmap->getWidth());
- writePSFmt(" /Height {0:d}\n", bitmap->getHeight());
- writePSFmt(" /ImageMatrix [{0:d} 0 0 {1:d} 0 {2:d}]\n", w, -h, h);
- writePS(" /BitsPerComponent 8\n");
- if (numComps == 1) {
- writePS(" /Decode [1 0]\n");
- } else if (numComps == 3) {
- writePS(" /Decode [0 1 0 1 0 1]\n");
- } else {
- writePS(" /Decode [0 1 0 1 0 1 0 1]\n");
- }
- writePS(" /DataSource currentfile\n");
- if (useBinary) {
- /* nothing to do */;
- } else if (useASCIIHex) {
- writePS(" /ASCIIHexDecode filter\n");
- } else {
- writePS(" /ASCII85Decode filter\n");
- }
- if (useFlate) {
- writePS(" /FlateDecode filter\n");
- } else if (useLZW) {
- writePS(" /LZWDecode filter\n");
- } else {
- writePS(" /RunLengthDecode filter\n");
- }
- writePS(">>\n");
- if (useBinary) {
- /* nothing to do */;
- } else if (useASCIIHex) {
- str = new ASCIIHexEncoder(str);
- } else {
- str = new ASCII85Encoder(str);
- }
- str->reset();
- if (useBinary) {
- // Count the bytes to write a document comment
- int len = 0;
- while (str->getChar() != EOF) {
- len++;
- }
- str->reset();
- writePSFmt("%%BeginData: {0:d} Binary Bytes\n", len+6+1);
- }
- writePS("image\n");
- while ((c = str->getChar()) != EOF) {
- writePSChar(c);
- }
- str->close();
- delete str;
- delete str0;
- writePSChar('\n');
- if (useBinary) {
- writePS("%%EndData\n");
- }
- processColors |= (numComps == 1) ? psProcessBlack : psProcessCMYK;
- break;
+ sliceX = sliceY = 0;
+ sliceW = (int)((box.x2 - box.x1) * hDPI2 / 72.0);
+ sliceH = (int)((box.y2 - box.y1) * vDPI2 / 72.0);
+ }
+ nStripes = (int)ceil((double)(sliceW * sliceH) / (double)rasterizationSliceSize);
+ if (unlikely(nStripes == 0)) {
+ delete splashOut;
+ return false;
+ }
+ stripeH = (sliceH + nStripes - 1) / nStripes;
+
+ // render the stripes
+ initialNumComps = numComps;
+ for (stripeY = sliceY; stripeY < sliceH; stripeY += stripeH) {
+
+ // rasterize a stripe
+ page->makeBox(hDPI2, vDPI2, 0, useMediaBox, false, sliceX, stripeY, sliceW, stripeH, &box, &crop);
+ m0 = box.x2 - box.x1;
+ m1 = 0;
+ m2 = 0;
+ m3 = box.y2 - box.y1;
+ m4 = box.x1;
+ m5 = box.y1;
+ page->displaySlice(splashOut, hDPI2, vDPI2, (360 - page->getRotate()) % 360, useMediaBox, crop, sliceX, stripeY, sliceW, stripeH, printing, abortCheckCbk, abortCheckCbkData, annotDisplayDecideCbk, annotDisplayDecideCbkData);
+
+ // draw the rasterized image
+ bitmap = splashOut->getBitmap();
+ numComps = initialNumComps;
+ w = bitmap->getWidth();
+ h = bitmap->getHeight();
+ writePS("gsave\n");
+ writePSFmt("[{0:.6g} {1:.6g} {2:.6g} {3:.6g} {4:.6g} {5:.6g}] concat\n", m0, m1, m2, m3, m4, m5);
+ switch (level) {
+ case psLevel1:
+ writePSFmt("{0:d} {1:d} 8 [{2:d} 0 0 {3:d} 0 {4:d}] pdfIm1{5:s}\n", w, h, w, -h, h, useBinary ? "Bin" : "");
+ p = bitmap->getDataPtr() + (h - 1) * bitmap->getRowSize();
+ i = 0;
+ if (useBinary) {
+ for (y = 0; y < h; ++y) {
+ for (x = 0; x < w; ++x) {
+ hexBuf[i++] = *p++;
+ if (i >= 64) {
+ writePSBuf(hexBuf, i);
+ i = 0;
+ }
+ }
+ }
+ } else {
+ for (y = 0; y < h; ++y) {
+ for (x = 0; x < w; ++x) {
+ digit = *p / 16;
+ hexBuf[i++] = digit + ((digit >= 10) ? 'a' - 10 : '0');
+ digit = *p++ % 16;
+ hexBuf[i++] = digit + ((digit >= 10) ? 'a' - 10 : '0');
+ if (i >= 64) {
+ hexBuf[i++] = '\n';
+ writePSBuf(hexBuf, i);
+ i = 0;
+ }
+ }
+ }
+ }
+ if (i != 0) {
+ if (!useBinary) {
+ hexBuf[i++] = '\n';
+ }
+ writePSBuf(hexBuf, i);
+ }
+ break;
+ case psLevel1Sep:
+ p = bitmap->getDataPtr();
+ // Check for an all gray image
+ if (getOptimizeColorSpace()) {
+ isGray = true;
+ for (y = 0; y < h; ++y) {
+ for (x = 0; x < w; ++x) {
+ if (p[4 * x] != p[4 * x + 1] || p[4 * x] != p[4 * x + 2]) {
+ isGray = false;
+ y = h;
+ break;
+ }
+ }
+ p += bitmap->getRowSize();
+ }
+ } else {
+ isGray = false;
+ }
+ writePSFmt("{0:d} {1:d} 8 [{2:d} 0 0 {3:d} 0 {4:d}] pdfIm1{5:s}{6:s}\n", w, h, w, -h, h, isGray ? "" : "Sep", useBinary ? "Bin" : "");
+ p = bitmap->getDataPtr() + (h - 1) * bitmap->getRowSize();
+ i = 0;
+ col[0] = col[1] = col[2] = col[3] = 0;
+ if (isGray) {
+ int g;
+ if ((psProcessBlack & processColors) == 0) {
+ // Check if the image uses black
+ for (y = 0; y < h; ++y) {
+ for (x = 0; x < w; ++x) {
+ if (p[4 * x] > 0 || p[4 * x + 3] > 0) {
+ col[3] = 1;
+ y = h;
+ break;
+ }
+ }
+ p -= bitmap->getRowSize();
+ }
+ p = bitmap->getDataPtr() + (h - 1) * bitmap->getRowSize();
+ }
+ for (y = 0; y < h; ++y) {
+ if (useBinary) {
+ // Binary gray image
+ for (x = 0; x < w; ++x) {
+ g = p[4 * x] + p[4 * x + 3];
+ g = 255 - g;
+ if (g < 0)
+ g = 0;
+ hexBuf[i++] = (unsigned char)g;
+ if (i >= 64) {
+ writePSBuf(hexBuf, i);
+ i = 0;
+ }
+ }
+ } else {
+ // Hex gray image
+ for (x = 0; x < w; ++x) {
+ g = p[4 * x] + p[4 * x + 3];
+ g = 255 - g;
+ if (g < 0)
+ g = 0;
+ digit = g / 16;
+ hexBuf[i++] = digit + ((digit >= 10) ? 'a' - 10 : '0');
+ digit = g % 16;
+ hexBuf[i++] = digit + ((digit >= 10) ? 'a' - 10 : '0');
+ if (i >= 64) {
+ hexBuf[i++] = '\n';
+ writePSBuf(hexBuf, i);
+ i = 0;
+ }
+ }
+ }
+ p -= bitmap->getRowSize();
+ }
+ } else if (((psProcessCyan | psProcessMagenta | psProcessYellow | psProcessBlack) & ~processColors) != 0) {
+ // Color image, need to check color flags for each dot
+ for (y = 0; y < h; ++y) {
+ for (comp = 0; comp < 4; ++comp) {
+ if (useBinary) {
+ // Binary color image
+ for (x = 0; x < w; ++x) {
+ col[comp] |= p[4 * x + comp];
+ hexBuf[i++] = p[4 * x + comp];
+ if (i >= 64) {
+ writePSBuf(hexBuf, i);
+ i = 0;
+ }
+ }
+ } else {
+ // Gray color image
+ for (x = 0; x < w; ++x) {
+ col[comp] |= p[4 * x + comp];
+ digit = p[4 * x + comp] / 16;
+ hexBuf[i++] = digit + ((digit >= 10) ? 'a' - 10 : '0');
+ digit = p[4 * x + comp] % 16;
+ hexBuf[i++] = digit + ((digit >= 10) ? 'a' - 10 : '0');
+ if (i >= 64) {
+ hexBuf[i++] = '\n';
+ writePSBuf(hexBuf, i);
+ i = 0;
+ }
+ }
+ }
+ }
+ p -= bitmap->getRowSize();
+ }
+ } else {
+ // Color image, do not need to check color flags
+ for (y = 0; y < h; ++y) {
+ for (comp = 0; comp < 4; ++comp) {
+ if (useBinary) {
+ // Binary color image
+ for (x = 0; x < w; ++x) {
+ hexBuf[i++] = p[4 * x + comp];
+ if (i >= 64) {
+ writePSBuf(hexBuf, i);
+ i = 0;
+ }
+ }
+ } else {
+ // Hex color image
+ for (x = 0; x < w; ++x) {
+ digit = p[4 * x + comp] / 16;
+ hexBuf[i++] = digit + ((digit >= 10) ? 'a' - 10 : '0');
+ digit = p[4 * x + comp] % 16;
+ hexBuf[i++] = digit + ((digit >= 10) ? 'a' - 10 : '0');
+ if (i >= 64) {
+ hexBuf[i++] = '\n';
+ writePSBuf(hexBuf, i);
+ i = 0;
+ }
+ }
+ }
+ }
+ p -= bitmap->getRowSize();
+ }
+ }
+ if (i != 0) {
+ if (!useBinary) {
+ hexBuf[i++] = '\n';
+ }
+ writePSBuf(hexBuf, i);
+ }
+ if (col[0]) {
+ processColors |= psProcessCyan;
+ }
+ if (col[1]) {
+ processColors |= psProcessMagenta;
+ }
+ if (col[2]) {
+ processColors |= psProcessYellow;
+ }
+ if (col[3]) {
+ processColors |= psProcessBlack;
+ }
+ break;
+ case psLevel2:
+ case psLevel2Sep:
+ case psLevel3:
+ case psLevel3Sep:
+ p = bitmap->getDataPtr() + (h - 1) * bitmap->getRowSize();
+ str0 = new MemStream((char *)p, 0, w * h * numComps, Object(objNull));
+ // Check for a color image that uses only gray
+ if (!getOptimizeColorSpace()) {
+ isGray = false;
+ } else if (numComps == 4) {
+ int compCyan;
+ isGray = true;
+ while ((compCyan = str0->getChar()) != EOF) {
+ if (str0->getChar() != compCyan || str0->getChar() != compCyan) {
+ isGray = false;
+ break;
+ }
+ str0->getChar();
+ }
+ } else if (numComps == 3) {
+ int compRed;
+ isGray = true;
+ while ((compRed = str0->getChar()) != EOF) {
+ if (str0->getChar() != compRed || str0->getChar() != compRed) {
+ isGray = false;
+ break;
+ }
+ }
+ } else {
+ isGray = false;
+ }
+ str0->reset();
+# ifdef ENABLE_ZLIB
+ if (useFlate) {
+ if (isGray && numComps == 4) {
+ str = new FlateEncoder(new CMYKGrayEncoder(str0));
+ numComps = 1;
+ } else if (isGray && numComps == 3) {
+ str = new FlateEncoder(new RGBGrayEncoder(str0));
+ numComps = 1;
+ } else {
+ str = new FlateEncoder(str0);
+ }
+ } else
+# endif
+ if (useLZW) {
+ if (isGray && numComps == 4) {
+ str = new LZWEncoder(new CMYKGrayEncoder(str0));
+ numComps = 1;
+ } else if (isGray && numComps == 3) {
+ str = new LZWEncoder(new RGBGrayEncoder(str0));
+ numComps = 1;
+ } else {
+ str = new LZWEncoder(str0);
+ }
+ } else {
+ if (isGray && numComps == 4) {
+ str = new RunLengthEncoder(new CMYKGrayEncoder(str0));
+ numComps = 1;
+ } else if (isGray && numComps == 3) {
+ str = new RunLengthEncoder(new RGBGrayEncoder(str0));
+ numComps = 1;
+ } else {
+ str = new RunLengthEncoder(str0);
+ }
+ }
+ if (numComps == 1) {
+ writePS("/DeviceGray setcolorspace\n");
+ } else if (numComps == 3) {
+ writePS("/DeviceRGB setcolorspace\n");
+ } else {
+ writePS("/DeviceCMYK setcolorspace\n");
+ }
+ writePS("<<\n /ImageType 1\n");
+ writePSFmt(" /Width {0:d}\n", bitmap->getWidth());
+ writePSFmt(" /Height {0:d}\n", bitmap->getHeight());
+ writePSFmt(" /ImageMatrix [{0:d} 0 0 {1:d} 0 {2:d}]\n", w, -h, h);
+ writePS(" /BitsPerComponent 8\n");
+ if (numComps == 1) {
+ writePS(" /Decode [1 0]\n");
+ } else if (numComps == 3) {
+ writePS(" /Decode [0 1 0 1 0 1]\n");
+ } else {
+ writePS(" /Decode [0 1 0 1 0 1 0 1]\n");
+ }
+ writePS(" /DataSource currentfile\n");
+ if (useBinary) {
+ /* nothing to do */;
+ } else if (useASCIIHex) {
+ writePS(" /ASCIIHexDecode filter\n");
+ } else {
+ writePS(" /ASCII85Decode filter\n");
+ }
+ if (useFlate) {
+ writePS(" /FlateDecode filter\n");
+ } else if (useLZW) {
+ writePS(" /LZWDecode filter\n");
+ } else {
+ writePS(" /RunLengthDecode filter\n");
+ }
+ writePS(">>\n");
+ if (useBinary) {
+ /* nothing to do */;
+ } else if (useASCIIHex) {
+ str = new ASCIIHexEncoder(str);
+ } else {
+ str = new ASCII85Encoder(str);
+ }
+ str->reset();
+ if (useBinary) {
+ // Count the bytes to write a document comment
+ int len = 0;
+ while (str->getChar() != EOF) {
+ len++;
+ }
+ str->reset();
+ writePSFmt("%%BeginData: {0:d} Binary Bytes\n", len + 6 + 1);
+ }
+ writePS("image\n");
+ while ((c = str->getChar()) != EOF) {
+ writePSChar(c);
+ }
+ str->close();
+ delete str;
+ delete str0;
+ writePSChar('\n');
+ if (useBinary) {
+ writePS("%%EndData\n");
+ }
+ processColors |= (numComps == 1) ? psProcessBlack : psProcessCMYK;
+ break;
+ }
+ writePS("grestore\n");
}
- writePS("grestore\n");
- }
- delete splashOut;
+ delete splashOut;
- // finish the PS page
- endPage();
+ // finish the PS page
+ endPage();
- return false;
+ return false;
#else // HAVE_SPLASH
- error(errSyntaxWarning, -1,
- "PDF page uses transparency and PSOutputDev was built without"
- " the Splash rasterizer - output may not be correct");
- return true;
+ error(errSyntaxWarning, -1,
+ "PDF page uses transparency and PSOutputDev was built without"
+ " the Splash rasterizer - output may not be correct");
+ return true;
#endif // HAVE_SPLASH
}
-void PSOutputDev::startPage(int pageNum, GfxState *state, XRef *xrefA) {
- Page *page;
- int x1, y1, x2, y2, width, height, t;
- int imgWidth, imgHeight, imgWidth2, imgHeight2;
- bool landscape;
- GooString *s;
- PSOutPaperSize *paperSize;
-
- if (!postInitDone) {
- postInit();
- }
- xref = xrefA;
- if (mode == psModePS) {
- GooString pageLabel;
- const bool gotLabel = doc->getCatalog()->indexToLabel(pageNum -1, &pageLabel);
- if (gotLabel) {
- // See bug13338 for why we try to avoid parentheses...
- bool needParens;
- GooString *filteredString = filterPSLabel(&pageLabel, &needParens);
- if (needParens) {
- writePSFmt("%%Page: ({0:t}) {1:d}\n", filteredString, seqPage);
- } else {
- writePSFmt("%%Page: {0:t} {1:d}\n", filteredString, seqPage);
- }
- delete filteredString;
- } else {
- writePSFmt("%%Page: {0:d} {1:d}\n", pageNum, seqPage);
- }
- if (paperMatch) {
- page = doc->getCatalog()->getPage(pageNum);
- imgLLX = imgLLY = 0;
- if (noCrop) {
- imgURX = (int)ceil(page->getMediaWidth());
- imgURY = (int)ceil(page->getMediaHeight());
- } else {
- imgURX = (int)ceil(page->getCropWidth());
- imgURY = (int)ceil(page->getCropHeight());
- }
- if (state->getRotate() == 90 || state->getRotate() == 270) {
- t = imgURX;
- imgURX = imgURY;
- imgURY = t;
- }
- }
- }
-
- // underlays
- if (underlayCbk) {
- (*underlayCbk)(this, underlayCbkData);
- }
- if (overlayCbk) {
- saveState(nullptr);
- }
-
- xScale = yScale = 1;
- switch (mode) {
-
- case psModePS:
- // rotate, translate, and scale page
- imgWidth = imgURX - imgLLX;
- imgHeight = imgURY - imgLLY;
- x1 = (int)floor(state->getX1());
- y1 = (int)floor(state->getY1());
- x2 = (int)ceil(state->getX2());
- y2 = (int)ceil(state->getY2());
- width = x2 - x1;
- height = y2 - y1;
- tx = ty = 0;
- // rotation and portrait/landscape mode
- if (paperMatch) {
- rotate = (360 - state->getRotate()) % 360;
- landscape = false;
- } else if (rotate0 >= 0) {
- rotate = (360 - rotate0) % 360;
- landscape = false;
- } else {
- rotate = (360 - state->getRotate()) % 360;
- if (rotate == 0 || rotate == 180) {
- if ((width < height && imgWidth > imgHeight && height > imgHeight) ||
- (width > height && imgWidth < imgHeight && width > imgWidth)) {
- rotate += 90;
- landscape = true;
- } else {
- landscape = false;
- }
- } else { // rotate == 90 || rotate == 270
- if ((height < width && imgWidth > imgHeight && width > imgHeight) ||
- (height > width && imgWidth < imgHeight && height > imgWidth)) {
- rotate = 270 - rotate;
- landscape = true;
- } else {
- landscape = false;
- }
- }
- }
- if (rotate == 0) {
- imgWidth2 = imgWidth;
- imgHeight2 = imgHeight;
- } else if (rotate == 90) {
- ty = -imgWidth;
- imgWidth2 = imgHeight;
- imgHeight2 = imgWidth;
- } else if (rotate == 180) {
- imgWidth2 = imgWidth;
- imgHeight2 = imgHeight;
- tx = -imgWidth;
- ty = -imgHeight;
- } else { // rotate == 270
- tx = -imgHeight;
- imgWidth2 = imgHeight;
- imgHeight2 = imgWidth;
- }
- // shrink or expand
- if (xScale0 > 0 && yScale0 > 0) {
- xScale = xScale0;
- yScale = yScale0;
- } else if ((globalParams->getPSShrinkLarger() &&
- (width > imgWidth2 || height > imgHeight2)) ||
- (globalParams->getPSExpandSmaller() &&
- (width < imgWidth2 && height < imgHeight2))) {
- xScale = (double)imgWidth2 / (double)width;
- yScale = (double)imgHeight2 / (double)height;
- if (yScale < xScale) {
- xScale = yScale;
- } else {
- yScale = xScale;
- }
- }
- // deal with odd bounding boxes or clipping
- if (clipLLX0 < clipURX0 && clipLLY0 < clipURY0) {
- tx -= xScale * clipLLX0;
- ty -= yScale * clipLLY0;
- } else {
- tx -= xScale * x1;
- ty -= yScale * y1;
- }
- // center
- if (tx0 >= 0 && ty0 >= 0) {
- tx += (rotate == 0 || rotate == 180) ? tx0 : ty0;
- ty += (rotate == 0 || rotate == 180) ? ty0 : -tx0;
- } else if (psCenter) {
- if (clipLLX0 < clipURX0 && clipLLY0 < clipURY0) {
- tx += (imgWidth2 - xScale * (clipURX0 - clipLLX0)) / 2;
- ty += (imgHeight2 - yScale * (clipURY0 - clipLLY0)) / 2;
- } else {
- tx += (imgWidth2 - xScale * width) / 2;
- ty += (imgHeight2 - yScale * height) / 2;
- }
- }
- tx += (rotate == 0 || rotate == 180) ? imgLLX : imgLLY;
- ty += (rotate == 0 || rotate == 180) ? imgLLY : -imgLLX;
-
- if (paperMatch) {
- paperSize = (*paperSizes)[pagePaperSize[pageNum]];
- writePSFmt("%%PageMedia: {0:t}\n", paperSize->name);
- }
-
- // Create a matrix with the same transform that will be output to PS
- Matrix m;
- switch (rotate) {
- default:
- case 0:
- m.init(1, 0,
- 0, 1,
- 0, 0);
- break;
- case 90:
- m.init(0, 1,
- -1, 0,
- 0, 0);
- break;
- case 180:
- m.init(-1, 0,
- 0, -1,
- 0, 0);
- break;
- case 270:
- m.init(0, -1,
- 1, 0,
- 0, 0);
- break;
- }
- m.translate(tx, ty);
- m.scale(xScale, yScale);
-
- double bboxX1, bboxY1, bboxX2, bboxY2;
- m.transform(0, 0, &bboxX1, &bboxY1);
- m.transform(width, height, &bboxX2, &bboxY2);
-
- writePSFmt("%%PageBoundingBox: {0:g} {1:g} {2:g} {3:g}\n",
- floor(std::min(bboxX1, bboxX2)),
- floor(std::min(bboxY1, bboxY2)),
- ceil (std::max(bboxX1, bboxX2)),
- ceil (std::max(bboxY1, bboxY2)));
-
- writePSFmt("%%PageOrientation: {0:s}\n",
- landscape ? "Landscape" : "Portrait");
- writePS("%%BeginPageSetup\n");
- if (paperMatch) {
- writePSFmt("{0:d} {1:d} pdfSetupPaper\n", imgURX, imgURY);
- }
- writePS("pdfStartPage\n");
- if (rotate)
- writePSFmt("{0:d} rotate\n", rotate);
- if (tx != 0 || ty != 0) {
- writePSFmt("{0:.6g} {1:.6g} translate\n", tx, ty);
- }
- if (xScale != 1 || yScale != 1) {
- writePSFmt("{0:.6f} {1:.6f} scale\n", xScale, yScale);
- }
- if (clipLLX0 < clipURX0 && clipLLY0 < clipURY0) {
- writePSFmt("{0:.6g} {1:.6g} {2:.6g} {3:.6g} re W\n",
- clipLLX0, clipLLY0, clipURX0 - clipLLX0, clipURY0 - clipLLY0);
- } else {
- writePSFmt("{0:d} {1:d} {2:d} {3:d} re W\n", x1, y1, x2 - x1, y2 - y1);
+void PSOutputDev::startPage(int pageNum, GfxState *state, XRef *xrefA)
+{
+ Page *page;
+ int x1, y1, x2, y2, width, height, t;
+ int imgWidth, imgHeight, imgWidth2, imgHeight2;
+ bool landscape;
+ GooString *s;
+ PSOutPaperSize *paperSize;
+
+ if (!postInitDone) {
+ postInit();
+ }
+ xref = xrefA;
+ if (mode == psModePS) {
+ GooString pageLabel;
+ const bool gotLabel = doc->getCatalog()->indexToLabel(pageNum - 1, &pageLabel);
+ if (gotLabel) {
+ // See bug13338 for why we try to avoid parentheses...
+ bool needParens;
+ GooString *filteredString = filterPSLabel(&pageLabel, &needParens);
+ if (needParens) {
+ writePSFmt("%%Page: ({0:t}) {1:d}\n", filteredString, seqPage);
+ } else {
+ writePSFmt("%%Page: {0:t} {1:d}\n", filteredString, seqPage);
+ }
+ delete filteredString;
+ } else {
+ writePSFmt("%%Page: {0:d} {1:d}\n", pageNum, seqPage);
+ }
+ if (paperMatch) {
+ page = doc->getCatalog()->getPage(pageNum);
+ imgLLX = imgLLY = 0;
+ if (noCrop) {
+ imgURX = (int)ceil(page->getMediaWidth());
+ imgURY = (int)ceil(page->getMediaHeight());
+ } else {
+ imgURX = (int)ceil(page->getCropWidth());
+ imgURY = (int)ceil(page->getCropHeight());
+ }
+ if (state->getRotate() == 90 || state->getRotate() == 270) {
+ t = imgURX;
+ imgURX = imgURY;
+ imgURY = t;
+ }
+ }
}
- ++seqPage;
- break;
+ // underlays
+ if (underlayCbk) {
+ (*underlayCbk)(this, underlayCbkData);
+ }
+ if (overlayCbk) {
+ saveState(nullptr);
+ }
+
+ xScale = yScale = 1;
+ switch (mode) {
+
+ case psModePS:
+ // rotate, translate, and scale page
+ imgWidth = imgURX - imgLLX;
+ imgHeight = imgURY - imgLLY;
+ x1 = (int)floor(state->getX1());
+ y1 = (int)floor(state->getY1());
+ x2 = (int)ceil(state->getX2());
+ y2 = (int)ceil(state->getY2());
+ width = x2 - x1;
+ height = y2 - y1;
+ tx = ty = 0;
+ // rotation and portrait/landscape mode
+ if (paperMatch) {
+ rotate = (360 - state->getRotate()) % 360;
+ landscape = false;
+ } else if (rotate0 >= 0) {
+ rotate = (360 - rotate0) % 360;
+ landscape = false;
+ } else {
+ rotate = (360 - state->getRotate()) % 360;
+ if (rotate == 0 || rotate == 180) {
+ if ((width < height && imgWidth > imgHeight && height > imgHeight) || (width > height && imgWidth < imgHeight && width > imgWidth)) {
+ rotate += 90;
+ landscape = true;
+ } else {
+ landscape = false;
+ }
+ } else { // rotate == 90 || rotate == 270
+ if ((height < width && imgWidth > imgHeight && width > imgHeight) || (height > width && imgWidth < imgHeight && height > imgWidth)) {
+ rotate = 270 - rotate;
+ landscape = true;
+ } else {
+ landscape = false;
+ }
+ }
+ }
+ if (rotate == 0) {
+ imgWidth2 = imgWidth;
+ imgHeight2 = imgHeight;
+ } else if (rotate == 90) {
+ ty = -imgWidth;
+ imgWidth2 = imgHeight;
+ imgHeight2 = imgWidth;
+ } else if (rotate == 180) {
+ imgWidth2 = imgWidth;
+ imgHeight2 = imgHeight;
+ tx = -imgWidth;
+ ty = -imgHeight;
+ } else { // rotate == 270
+ tx = -imgHeight;
+ imgWidth2 = imgHeight;
+ imgHeight2 = imgWidth;
+ }
+ // shrink or expand
+ if (xScale0 > 0 && yScale0 > 0) {
+ xScale = xScale0;
+ yScale = yScale0;
+ } else if ((globalParams->getPSShrinkLarger() && (width > imgWidth2 || height > imgHeight2)) || (globalParams->getPSExpandSmaller() && (width < imgWidth2 && height < imgHeight2))) {
+ xScale = (double)imgWidth2 / (double)width;
+ yScale = (double)imgHeight2 / (double)height;
+ if (yScale < xScale) {
+ xScale = yScale;
+ } else {
+ yScale = xScale;
+ }
+ }
+ // deal with odd bounding boxes or clipping
+ if (clipLLX0 < clipURX0 && clipLLY0 < clipURY0) {
+ tx -= xScale * clipLLX0;
+ ty -= yScale * clipLLY0;
+ } else {
+ tx -= xScale * x1;
+ ty -= yScale * y1;
+ }
+ // center
+ if (tx0 >= 0 && ty0 >= 0) {
+ tx += (rotate == 0 || rotate == 180) ? tx0 : ty0;
+ ty += (rotate == 0 || rotate == 180) ? ty0 : -tx0;
+ } else if (psCenter) {
+ if (clipLLX0 < clipURX0 && clipLLY0 < clipURY0) {
+ tx += (imgWidth2 - xScale * (clipURX0 - clipLLX0)) / 2;
+ ty += (imgHeight2 - yScale * (clipURY0 - clipLLY0)) / 2;
+ } else {
+ tx += (imgWidth2 - xScale * width) / 2;
+ ty += (imgHeight2 - yScale * height) / 2;
+ }
+ }
+ tx += (rotate == 0 || rotate == 180) ? imgLLX : imgLLY;
+ ty += (rotate == 0 || rotate == 180) ? imgLLY : -imgLLX;
- case psModeEPS:
- writePS("pdfStartPage\n");
- tx = ty = 0;
- rotate = (360 - state->getRotate()) % 360;
- if (rotate == 0) {
- } else if (rotate == 90) {
- writePS("90 rotate\n");
- tx = -epsX1;
- ty = -epsY2;
- } else if (rotate == 180) {
- writePS("180 rotate\n");
- tx = -(epsX1 + epsX2);
- ty = -(epsY1 + epsY2);
- } else { // rotate == 270
- writePS("270 rotate\n");
- tx = -epsX2;
- ty = -epsY1;
- }
- if (tx != 0 || ty != 0) {
- writePSFmt("{0:.6g} {1:.6g} translate\n", tx, ty);
- }
- break;
+ if (paperMatch) {
+ paperSize = (*paperSizes)[pagePaperSize[pageNum]];
+ writePSFmt("%%PageMedia: {0:t}\n", paperSize->name);
+ }
- case psModeForm:
- writePS("/PaintProc {\n");
- writePS("begin xpdf begin\n");
- writePS("pdfStartPage\n");
- tx = ty = 0;
- rotate = 0;
- break;
- }
+ // Create a matrix with the same transform that will be output to PS
+ Matrix m;
+ switch (rotate) {
+ default:
+ case 0:
+ m.init(1, 0, 0, 1, 0, 0);
+ break;
+ case 90:
+ m.init(0, 1, -1, 0, 0, 0);
+ break;
+ case 180:
+ m.init(-1, 0, 0, -1, 0, 0);
+ break;
+ case 270:
+ m.init(0, -1, 1, 0, 0, 0);
+ break;
+ }
+ m.translate(tx, ty);
+ m.scale(xScale, yScale);
+
+ double bboxX1, bboxY1, bboxX2, bboxY2;
+ m.transform(0, 0, &bboxX1, &bboxY1);
+ m.transform(width, height, &bboxX2, &bboxY2);
+
+ writePSFmt("%%PageBoundingBox: {0:g} {1:g} {2:g} {3:g}\n", floor(std::min(bboxX1, bboxX2)), floor(std::min(bboxY1, bboxY2)), ceil(std::max(bboxX1, bboxX2)), ceil(std::max(bboxY1, bboxY2)));
+
+ writePSFmt("%%PageOrientation: {0:s}\n", landscape ? "Landscape" : "Portrait");
+ writePS("%%BeginPageSetup\n");
+ if (paperMatch) {
+ writePSFmt("{0:d} {1:d} pdfSetupPaper\n", imgURX, imgURY);
+ }
+ writePS("pdfStartPage\n");
+ if (rotate)
+ writePSFmt("{0:d} rotate\n", rotate);
+ if (tx != 0 || ty != 0) {
+ writePSFmt("{0:.6g} {1:.6g} translate\n", tx, ty);
+ }
+ if (xScale != 1 || yScale != 1) {
+ writePSFmt("{0:.6f} {1:.6f} scale\n", xScale, yScale);
+ }
+ if (clipLLX0 < clipURX0 && clipLLY0 < clipURY0) {
+ writePSFmt("{0:.6g} {1:.6g} {2:.6g} {3:.6g} re W\n", clipLLX0, clipLLY0, clipURX0 - clipLLX0, clipURY0 - clipLLY0);
+ } else {
+ writePSFmt("{0:d} {1:d} {2:d} {3:d} re W\n", x1, y1, x2 - x1, y2 - y1);
+ }
+
+ ++seqPage;
+ break;
- if (customCodeCbk) {
- if ((s = (*customCodeCbk)(this, psOutCustomPageSetup, pageNum,
- customCodeCbkData))) {
- writePS(s->c_str());
- delete s;
+ case psModeEPS:
+ writePS("pdfStartPage\n");
+ tx = ty = 0;
+ rotate = (360 - state->getRotate()) % 360;
+ if (rotate == 0) {
+ } else if (rotate == 90) {
+ writePS("90 rotate\n");
+ tx = -epsX1;
+ ty = -epsY2;
+ } else if (rotate == 180) {
+ writePS("180 rotate\n");
+ tx = -(epsX1 + epsX2);
+ ty = -(epsY1 + epsY2);
+ } else { // rotate == 270
+ writePS("270 rotate\n");
+ tx = -epsX2;
+ ty = -epsY1;
+ }
+ if (tx != 0 || ty != 0) {
+ writePSFmt("{0:.6g} {1:.6g} translate\n", tx, ty);
+ }
+ break;
+
+ case psModeForm:
+ writePS("/PaintProc {\n");
+ writePS("begin xpdf begin\n");
+ writePS("pdfStartPage\n");
+ tx = ty = 0;
+ rotate = 0;
+ break;
}
- }
- writePS("%%EndPageSetup\n");
-}
+ if (customCodeCbk) {
+ if ((s = (*customCodeCbk)(this, psOutCustomPageSetup, pageNum, customCodeCbkData))) {
+ writePS(s->c_str());
+ delete s;
+ }
+ }
-void PSOutputDev::endPage() {
- if (overlayCbk) {
- restoreState(nullptr);
- (*overlayCbk)(this, overlayCbkData);
- }
+ writePS("%%EndPageSetup\n");
+}
- for (const auto& item : iccEmitted) {
- writePSFmt("userdict /{0:s} undef\n", item.c_str());
- }
- iccEmitted.clear();
+void PSOutputDev::endPage()
+{
+ if (overlayCbk) {
+ restoreState(nullptr);
+ (*overlayCbk)(this, overlayCbkData);
+ }
- if (mode == psModeForm) {
- writePS("pdfEndPage\n");
- writePS("end end\n");
- writePS("} def\n");
- writePS("end end\n");
- } else {
- if (!manualCtrl) {
- writePS("showpage\n");
+ for (const auto &item : iccEmitted) {
+ writePSFmt("userdict /{0:s} undef\n", item.c_str());
}
- writePS("%%PageTrailer\n");
- writePageTrailer();
+ iccEmitted.clear();
+
+ if (mode == psModeForm) {
+ writePS("pdfEndPage\n");
+ writePS("end end\n");
+ writePS("} def\n");
+ writePS("end end\n");
+ } else {
+ if (!manualCtrl) {
+ writePS("showpage\n");
+ }
+ writePS("%%PageTrailer\n");
+ writePageTrailer();
}
}
-void PSOutputDev::saveState(GfxState *state) {
- writePS("q\n");
- ++numSaves;
+void PSOutputDev::saveState(GfxState *state)
+{
+ writePS("q\n");
+ ++numSaves;
}
-void PSOutputDev::restoreState(GfxState *state) {
- writePS("Q\n");
- --numSaves;
+void PSOutputDev::restoreState(GfxState *state)
+{
+ writePS("Q\n");
+ --numSaves;
}
-void PSOutputDev::updateCTM(GfxState *state, double m11, double m12,
- double m21, double m22, double m31, double m32) {
- writePSFmt("[{0:.6gs} {1:.6gs} {2:.6gs} {3:.6gs} {4:.6gs} {5:.6gs}] cm\n",
- m11, m12, m21, m22, m31, m32);
+void PSOutputDev::updateCTM(GfxState *state, double m11, double m12, double m21, double m22, double m31, double m32)
+{
+ writePSFmt("[{0:.6gs} {1:.6gs} {2:.6gs} {3:.6gs} {4:.6gs} {5:.6gs}] cm\n", m11, m12, m21, m22, m31, m32);
}
-void PSOutputDev::updateLineDash(GfxState *state) {
- double *dash;
- double start;
- int length, i;
-
- state->getLineDash(&dash, &length, &start);
- writePS("[");
- for (i = 0; i < length; ++i) {
- writePSFmt("{0:.6g}{1:w}",
- dash[i] < 0 ? 0 : dash[i],
- (i == length-1) ? 0 : 1);
- }
- writePSFmt("] {0:.6g} d\n", start);
+void PSOutputDev::updateLineDash(GfxState *state)
+{
+ double *dash;
+ double start;
+ int length, i;
+
+ state->getLineDash(&dash, &length, &start);
+ writePS("[");
+ for (i = 0; i < length; ++i) {
+ writePSFmt("{0:.6g}{1:w}", dash[i] < 0 ? 0 : dash[i], (i == length - 1) ? 0 : 1);
+ }
+ writePSFmt("] {0:.6g} d\n", start);
}
-void PSOutputDev::updateFlatness(GfxState *state) {
- writePSFmt("{0:d} i\n", state->getFlatness());
+void PSOutputDev::updateFlatness(GfxState *state)
+{
+ writePSFmt("{0:d} i\n", state->getFlatness());
}
-void PSOutputDev::updateLineJoin(GfxState *state) {
- writePSFmt("{0:d} j\n", state->getLineJoin());
+void PSOutputDev::updateLineJoin(GfxState *state)
+{
+ writePSFmt("{0:d} j\n", state->getLineJoin());
}
-void PSOutputDev::updateLineCap(GfxState *state) {
- writePSFmt("{0:d} J\n", state->getLineCap());
+void PSOutputDev::updateLineCap(GfxState *state)
+{
+ writePSFmt("{0:d} J\n", state->getLineCap());
}
-void PSOutputDev::updateMiterLimit(GfxState *state) {
- writePSFmt("{0:.6g} M\n", state->getMiterLimit());
+void PSOutputDev::updateMiterLimit(GfxState *state)
+{
+ writePSFmt("{0:.6g} M\n", state->getMiterLimit());
}
-void PSOutputDev::updateLineWidth(GfxState *state) {
- writePSFmt("{0:.6g} w\n", state->getLineWidth());
+void PSOutputDev::updateLineWidth(GfxState *state)
+{
+ writePSFmt("{0:.6g} w\n", state->getLineWidth());
}
-void PSOutputDev::updateFillColorSpace(GfxState *state) {
- if (inUncoloredPattern) {
- return;
- }
- switch (level) {
- case psLevel1:
- case psLevel1Sep:
- break;
- case psLevel2:
- case psLevel3:
- if (state->getFillColorSpace()->getMode() != csPattern) {
- dumpColorSpaceL2(state, state->getFillColorSpace(), true, false, false);
- writePS(" cs\n");
+void PSOutputDev::updateFillColorSpace(GfxState *state)
+{
+ if (inUncoloredPattern) {
+ return;
+ }
+ switch (level) {
+ case psLevel1:
+ case psLevel1Sep:
+ break;
+ case psLevel2:
+ case psLevel3:
+ if (state->getFillColorSpace()->getMode() != csPattern) {
+ dumpColorSpaceL2(state, state->getFillColorSpace(), true, false, false);
+ writePS(" cs\n");
+ }
+ break;
+ case psLevel2Sep:
+ case psLevel3Sep:
+ break;
}
- break;
- case psLevel2Sep:
- case psLevel3Sep:
- break;
- }
}
-void PSOutputDev::updateStrokeColorSpace(GfxState *state) {
- if (inUncoloredPattern) {
- return;
- }
- switch (level) {
- case psLevel1:
- case psLevel1Sep:
- break;
- case psLevel2:
- case psLevel3:
- if (state->getStrokeColorSpace()->getMode() != csPattern) {
- dumpColorSpaceL2(state, state->getStrokeColorSpace(), true, false, false);
- writePS(" CS\n");
+void PSOutputDev::updateStrokeColorSpace(GfxState *state)
+{
+ if (inUncoloredPattern) {
+ return;
+ }
+ switch (level) {
+ case psLevel1:
+ case psLevel1Sep:
+ break;
+ case psLevel2:
+ case psLevel3:
+ if (state->getStrokeColorSpace()->getMode() != csPattern) {
+ dumpColorSpaceL2(state, state->getStrokeColorSpace(), true, false, false);
+ writePS(" CS\n");
+ }
+ break;
+ case psLevel2Sep:
+ case psLevel3Sep:
+ break;
}
- break;
- case psLevel2Sep:
- case psLevel3Sep:
- break;
- }
}
-void PSOutputDev::updateFillColor(GfxState *state) {
- GfxColor color;
- GfxGray gray;
- GfxCMYK cmyk;
- GfxSeparationColorSpace *sepCS;
- double c, m, y, k;
- int i;
-
- if (inUncoloredPattern) {
- return;
- }
- switch (level) {
- case psLevel1:
- state->getFillGray(&gray);
- writePSFmt("{0:.4g} g\n", colToDbl(gray));
- break;
- case psLevel2:
- case psLevel3:
- if (state->getFillColorSpace()->getMode() != csPattern) {
- const GfxColor *colorPtr = state->getFillColor();
- writePS("[");
- for (i = 0; i < state->getFillColorSpace()->getNComps(); ++i) {
- if (i > 0) {
- writePS(" ");
- }
- writePSFmt("{0:.4g}", colToDbl(colorPtr->c[i]));
- }
- writePS("] sc\n");
+void PSOutputDev::updateFillColor(GfxState *state)
+{
+ GfxColor color;
+ GfxGray gray;
+ GfxCMYK cmyk;
+ GfxSeparationColorSpace *sepCS;
+ double c, m, y, k;
+ int i;
+
+ if (inUncoloredPattern) {
+ return;
}
- break;
- case psLevel1Sep:
- case psLevel2Sep:
- case psLevel3Sep:
- if (state->getFillColorSpace()->getMode() == csSeparation && (level > psLevel1Sep || getPassLevel1CustomColor())) {
- sepCS = (GfxSeparationColorSpace *)state->getFillColorSpace();
- color.c[0] = gfxColorComp1;
- sepCS->getCMYK(&color, &cmyk);
- writePSFmt("{0:.4g} {1:.4g} {2:.4g} {3:.4g} {4:.4g} ({5:t}) ck\n",
- colToDbl(state->getFillColor()->c[0]),
- colToDbl(cmyk.c), colToDbl(cmyk.m),
- colToDbl(cmyk.y), colToDbl(cmyk.k),
- sepCS->getName());
- addCustomColor(sepCS);
- } else {
- state->getFillCMYK(&cmyk);
- c = colToDbl(cmyk.c);
- m = colToDbl(cmyk.m);
- y = colToDbl(cmyk.y);
- k = colToDbl(cmyk.k);
- if (getOptimizeColorSpace()) {
- double g;
- g = 0.299*c + 0.587*m + 0.114*y;
- if ((fabs(m - c) < 0.01 && fabs(m - y) < 0.01) ||
- (fabs(m - c) < 0.2 && fabs(m - y) < 0.2 && k + g > 1.5)) {
- c = m = y = 0.0;
- k += g;
- if (k > 1.0) k = 1.0;
- }
- }
- writePSFmt("{0:.4g} {1:.4g} {2:.4g} {3:.4g} k\n", c, m, y, k);
- addProcessColor(c, m, y, k);
+ switch (level) {
+ case psLevel1:
+ state->getFillGray(&gray);
+ writePSFmt("{0:.4g} g\n", colToDbl(gray));
+ break;
+ case psLevel2:
+ case psLevel3:
+ if (state->getFillColorSpace()->getMode() != csPattern) {
+ const GfxColor *colorPtr = state->getFillColor();
+ writePS("[");
+ for (i = 0; i < state->getFillColorSpace()->getNComps(); ++i) {
+ if (i > 0) {
+ writePS(" ");
+ }
+ writePSFmt("{0:.4g}", colToDbl(colorPtr->c[i]));
+ }
+ writePS("] sc\n");
+ }
+ break;
+ case psLevel1Sep:
+ case psLevel2Sep:
+ case psLevel3Sep:
+ if (state->getFillColorSpace()->getMode() == csSeparation && (level > psLevel1Sep || getPassLevel1CustomColor())) {
+ sepCS = (GfxSeparationColorSpace *)state->getFillColorSpace();
+ color.c[0] = gfxColorComp1;
+ sepCS->getCMYK(&color, &cmyk);
+ writePSFmt("{0:.4g} {1:.4g} {2:.4g} {3:.4g} {4:.4g} ({5:t}) ck\n", colToDbl(state->getFillColor()->c[0]), colToDbl(cmyk.c), colToDbl(cmyk.m), colToDbl(cmyk.y), colToDbl(cmyk.k), sepCS->getName());
+ addCustomColor(sepCS);
+ } else {
+ state->getFillCMYK(&cmyk);
+ c = colToDbl(cmyk.c);
+ m = colToDbl(cmyk.m);
+ y = colToDbl(cmyk.y);
+ k = colToDbl(cmyk.k);
+ if (getOptimizeColorSpace()) {
+ double g;
+ g = 0.299 * c + 0.587 * m + 0.114 * y;
+ if ((fabs(m - c) < 0.01 && fabs(m - y) < 0.01) || (fabs(m - c) < 0.2 && fabs(m - y) < 0.2 && k + g > 1.5)) {
+ c = m = y = 0.0;
+ k += g;
+ if (k > 1.0)
+ k = 1.0;
+ }
+ }
+ writePSFmt("{0:.4g} {1:.4g} {2:.4g} {3:.4g} k\n", c, m, y, k);
+ addProcessColor(c, m, y, k);
+ }
+ break;
}
- break;
- }
- t3Cacheable = false;
+ t3Cacheable = false;
}
-void PSOutputDev::updateStrokeColor(GfxState *state) {
- GfxColor color;
- GfxGray gray;
- GfxCMYK cmyk;
- GfxSeparationColorSpace *sepCS;
- double c, m, y, k;
- int i;
-
- if (inUncoloredPattern) {
- return;
- }
- switch (level) {
- case psLevel1:
- state->getStrokeGray(&gray);
- writePSFmt("{0:.4g} G\n", colToDbl(gray));
- break;
- case psLevel2:
- case psLevel3:
- if (state->getStrokeColorSpace()->getMode() != csPattern) {
- const GfxColor *colorPtr = state->getStrokeColor();
- writePS("[");
- for (i = 0; i < state->getStrokeColorSpace()->getNComps(); ++i) {
- if (i > 0) {
- writePS(" ");
- }
- writePSFmt("{0:.4g}", colToDbl(colorPtr->c[i]));
- }
- writePS("] SC\n");
+void PSOutputDev::updateStrokeColor(GfxState *state)
+{
+ GfxColor color;
+ GfxGray gray;
+ GfxCMYK cmyk;
+ GfxSeparationColorSpace *sepCS;
+ double c, m, y, k;
+ int i;
+
+ if (inUncoloredPattern) {
+ return;
}
- break;
- case psLevel1Sep:
- case psLevel2Sep:
- case psLevel3Sep:
- if (state->getStrokeColorSpace()->getMode() == csSeparation && (level > psLevel1Sep || getPassLevel1CustomColor())) {
- sepCS = (GfxSeparationColorSpace *)state->getStrokeColorSpace();
- color.c[0] = gfxColorComp1;
- sepCS->getCMYK(&color, &cmyk);
- writePSFmt("{0:.4g} {1:.4g} {2:.4g} {3:.4g} {4:.4g} ({5:t}) CK\n",
- colToDbl(state->getStrokeColor()->c[0]),
- colToDbl(cmyk.c), colToDbl(cmyk.m),
- colToDbl(cmyk.y), colToDbl(cmyk.k),
- sepCS->getName());
- addCustomColor(sepCS);
- } else {
- state->getStrokeCMYK(&cmyk);
- c = colToDbl(cmyk.c);
- m = colToDbl(cmyk.m);
- y = colToDbl(cmyk.y);
- k = colToDbl(cmyk.k);
- if (getOptimizeColorSpace()) {
- double g;
- g = 0.299*c + 0.587*m + 0.114*y;
- if ((fabs(m - c) < 0.01 && fabs(m - y) < 0.01) ||
- (fabs(m - c) < 0.2 && fabs(m - y) < 0.2 && k + g > 1.5)) {
- c = m = y = 0.0;
- k += g;
- if (k > 1.0) k = 1.0;
- }
- }
- writePSFmt("{0:.4g} {1:.4g} {2:.4g} {3:.4g} K\n", c, m, y, k);
- addProcessColor(c, m, y, k);
+ switch (level) {
+ case psLevel1:
+ state->getStrokeGray(&gray);
+ writePSFmt("{0:.4g} G\n", colToDbl(gray));
+ break;
+ case psLevel2:
+ case psLevel3:
+ if (state->getStrokeColorSpace()->getMode() != csPattern) {
+ const GfxColor *colorPtr = state->getStrokeColor();
+ writePS("[");
+ for (i = 0; i < state->getStrokeColorSpace()->getNComps(); ++i) {
+ if (i > 0) {
+ writePS(" ");
+ }
+ writePSFmt("{0:.4g}", colToDbl(colorPtr->c[i]));
+ }
+ writePS("] SC\n");
+ }
+ break;
+ case psLevel1Sep:
+ case psLevel2Sep:
+ case psLevel3Sep:
+ if (state->getStrokeColorSpace()->getMode() == csSeparation && (level > psLevel1Sep || getPassLevel1CustomColor())) {
+ sepCS = (GfxSeparationColorSpace *)state->getStrokeColorSpace();
+ color.c[0] = gfxColorComp1;
+ sepCS->getCMYK(&color, &cmyk);
+ writePSFmt("{0:.4g} {1:.4g} {2:.4g} {3:.4g} {4:.4g} ({5:t}) CK\n", colToDbl(state->getStrokeColor()->c[0]), colToDbl(cmyk.c), colToDbl(cmyk.m), colToDbl(cmyk.y), colToDbl(cmyk.k), sepCS->getName());
+ addCustomColor(sepCS);
+ } else {
+ state->getStrokeCMYK(&cmyk);
+ c = colToDbl(cmyk.c);
+ m = colToDbl(cmyk.m);
+ y = colToDbl(cmyk.y);
+ k = colToDbl(cmyk.k);
+ if (getOptimizeColorSpace()) {
+ double g;
+ g = 0.299 * c + 0.587 * m + 0.114 * y;
+ if ((fabs(m - c) < 0.01 && fabs(m - y) < 0.01) || (fabs(m - c) < 0.2 && fabs(m - y) < 0.2 && k + g > 1.5)) {
+ c = m = y = 0.0;
+ k += g;
+ if (k > 1.0)
+ k = 1.0;
+ }
+ }
+ writePSFmt("{0:.4g} {1:.4g} {2:.4g} {3:.4g} K\n", c, m, y, k);
+ addProcessColor(c, m, y, k);
+ }
+ break;
}
- break;
- }
- t3Cacheable = false;
+ t3Cacheable = false;
}
-void PSOutputDev::addProcessColor(double c, double m, double y, double k) {
- if (c > 0) {
- processColors |= psProcessCyan;
- }
- if (m > 0) {
- processColors |= psProcessMagenta;
- }
- if (y > 0) {
- processColors |= psProcessYellow;
- }
- if (k > 0) {
- processColors |= psProcessBlack;
- }
+void PSOutputDev::addProcessColor(double c, double m, double y, double k)
+{
+ if (c > 0) {
+ processColors |= psProcessCyan;
+ }
+ if (m > 0) {
+ processColors |= psProcessMagenta;
+ }
+ if (y > 0) {
+ processColors |= psProcessYellow;
+ }
+ if (k > 0) {
+ processColors |= psProcessBlack;
+ }
}
-void PSOutputDev::addCustomColor(GfxSeparationColorSpace *sepCS) {
- PSOutCustomColor *cc;
- GfxColor color;
- GfxCMYK cmyk;
-
- if (!sepCS->getName()->cmp("Black")) {
- processColors |= psProcessBlack;
- return;
- }
- if (!sepCS->getName()->cmp("Cyan")) {
- processColors |= psProcessCyan;
- return;
- }
- if (!sepCS->getName()->cmp("Yellow")) {
- processColors |= psProcessYellow;
- return;
- }
- if (!sepCS->getName()->cmp("Magenta")) {
- processColors |= psProcessMagenta;
- return;
- }
- if (!sepCS->getName()->cmp("All"))
- return;
- if (!sepCS->getName()->cmp("None"))
- return;
- for (cc = customColors; cc; cc = cc->next) {
- if (!cc->name->cmp(sepCS->getName())) {
- return;
- }
- }
- color.c[0] = gfxColorComp1;
- sepCS->getCMYK(&color, &cmyk);
- cc = new PSOutCustomColor(colToDbl(cmyk.c), colToDbl(cmyk.m),
- colToDbl(cmyk.y), colToDbl(cmyk.k),
- sepCS->getName()->copy());
- cc->next = customColors;
- customColors = cc;
+void PSOutputDev::addCustomColor(GfxSeparationColorSpace *sepCS)
+{
+ PSOutCustomColor *cc;
+ GfxColor color;
+ GfxCMYK cmyk;
+
+ if (!sepCS->getName()->cmp("Black")) {
+ processColors |= psProcessBlack;
+ return;
+ }
+ if (!sepCS->getName()->cmp("Cyan")) {
+ processColors |= psProcessCyan;
+ return;
+ }
+ if (!sepCS->getName()->cmp("Yellow")) {
+ processColors |= psProcessYellow;
+ return;
+ }
+ if (!sepCS->getName()->cmp("Magenta")) {
+ processColors |= psProcessMagenta;
+ return;
+ }
+ if (!sepCS->getName()->cmp("All"))
+ return;
+ if (!sepCS->getName()->cmp("None"))
+ return;
+ for (cc = customColors; cc; cc = cc->next) {
+ if (!cc->name->cmp(sepCS->getName())) {
+ return;
+ }
+ }
+ color.c[0] = gfxColorComp1;
+ sepCS->getCMYK(&color, &cmyk);
+ cc = new PSOutCustomColor(colToDbl(cmyk.c), colToDbl(cmyk.m), colToDbl(cmyk.y), colToDbl(cmyk.k), sepCS->getName()->copy());
+ cc->next = customColors;
+ customColors = cc;
}
-void PSOutputDev::updateFillOverprint(GfxState *state) {
- if (level >= psLevel2) {
- writePSFmt("{0:s} op\n", state->getFillOverprint() ? "true" : "false");
- }
+void PSOutputDev::updateFillOverprint(GfxState *state)
+{
+ if (level >= psLevel2) {
+ writePSFmt("{0:s} op\n", state->getFillOverprint() ? "true" : "false");
+ }
}
-void PSOutputDev::updateStrokeOverprint(GfxState *state) {
- if (level >= psLevel2) {
- writePSFmt("{0:s} OP\n", state->getStrokeOverprint() ? "true" : "false");
- }
+void PSOutputDev::updateStrokeOverprint(GfxState *state)
+{
+ if (level >= psLevel2) {
+ writePSFmt("{0:s} OP\n", state->getStrokeOverprint() ? "true" : "false");
+ }
}
-void PSOutputDev::updateOverprintMode(GfxState *state) {
- if (level >= psLevel3) {
- writePSFmt("{0:s} opm\n", state->getOverprintMode() ? "true" : "false");
- }
+void PSOutputDev::updateOverprintMode(GfxState *state)
+{
+ if (level >= psLevel3) {
+ writePSFmt("{0:s} opm\n", state->getOverprintMode() ? "true" : "false");
+ }
}
-void PSOutputDev::updateTransfer(GfxState *state) {
- Function **funcs;
- int i;
-
- funcs = state->getTransfer();
- if (funcs[0] && funcs[1] && funcs[2] && funcs[3]) {
- if (level >= psLevel2) {
- for (i = 0; i < 4; ++i) {
- cvtFunction(funcs[i]);
- }
- writePS("setcolortransfer\n");
+void PSOutputDev::updateTransfer(GfxState *state)
+{
+ Function **funcs;
+ int i;
+
+ funcs = state->getTransfer();
+ if (funcs[0] && funcs[1] && funcs[2] && funcs[3]) {
+ if (level >= psLevel2) {
+ for (i = 0; i < 4; ++i) {
+ cvtFunction(funcs[i]);
+ }
+ writePS("setcolortransfer\n");
+ } else {
+ cvtFunction(funcs[3]);
+ writePS("settransfer\n");
+ }
+ } else if (funcs[0]) {
+ cvtFunction(funcs[0]);
+ writePS("settransfer\n");
} else {
- cvtFunction(funcs[3]);
- writePS("settransfer\n");
- }
- } else if (funcs[0]) {
- cvtFunction(funcs[0]);
- writePS("settransfer\n");
- } else {
- writePS("{} settransfer\n");
- }
+ writePS("{} settransfer\n");
+ }
}
-void PSOutputDev::updateFont(GfxState *state) {
- if (state->getFont()) {
- writePSFmt("/F{0:d}_{1:d} {2:.6g} Tf\n",
- state->getFont()->getID()->num, state->getFont()->getID()->gen,
- fabs(state->getFontSize()) < 0.0001 ? 0.0001
- : state->getFontSize());
- }
+void PSOutputDev::updateFont(GfxState *state)
+{
+ if (state->getFont()) {
+ writePSFmt("/F{0:d}_{1:d} {2:.6g} Tf\n", state->getFont()->getID()->num, state->getFont()->getID()->gen, fabs(state->getFontSize()) < 0.0001 ? 0.0001 : state->getFontSize());
+ }
}
-void PSOutputDev::updateTextMat(GfxState *state) {
- const double *mat = state->getTextMat();
- if (fabs(mat[0] * mat[3] - mat[1] * mat[2]) < 0.00001) {
- // avoid a singular (or close-to-singular) matrix
- writePSFmt("[0.00001 0 0 0.00001 {0:.6g} {1:.6g}] Tm\n", mat[4], mat[5]);
- } else {
- writePSFmt("[{0:.6g} {1:.6g} {2:.6g} {3:.6g} {4:.6g} {5:.6g}] Tm\n",
- mat[0], mat[1], mat[2], mat[3], mat[4], mat[5]);
- }
+void PSOutputDev::updateTextMat(GfxState *state)
+{
+ const double *mat = state->getTextMat();
+ if (fabs(mat[0] * mat[3] - mat[1] * mat[2]) < 0.00001) {
+ // avoid a singular (or close-to-singular) matrix
+ writePSFmt("[0.00001 0 0 0.00001 {0:.6g} {1:.6g}] Tm\n", mat[4], mat[5]);
+ } else {
+ writePSFmt("[{0:.6g} {1:.6g} {2:.6g} {3:.6g} {4:.6g} {5:.6g}] Tm\n", mat[0], mat[1], mat[2], mat[3], mat[4], mat[5]);
+ }
}
-void PSOutputDev::updateCharSpace(GfxState *state) {
- writePSFmt("{0:.6g} Tc\n", state->getCharSpace());
+void PSOutputDev::updateCharSpace(GfxState *state)
+{
+ writePSFmt("{0:.6g} Tc\n", state->getCharSpace());
}
-void PSOutputDev::updateRender(GfxState *state) {
- int rm;
+void PSOutputDev::updateRender(GfxState *state)
+{
+ int rm;
- rm = state->getRender();
- writePSFmt("{0:d} Tr\n", rm);
- rm &= 3;
- if (rm != 0 && rm != 3) {
- t3Cacheable = false;
- }
+ rm = state->getRender();
+ writePSFmt("{0:d} Tr\n", rm);
+ rm &= 3;
+ if (rm != 0 && rm != 3) {
+ t3Cacheable = false;
+ }
}
-void PSOutputDev::updateRise(GfxState *state) {
- writePSFmt("{0:.6g} Ts\n", state->getRise());
+void PSOutputDev::updateRise(GfxState *state)
+{
+ writePSFmt("{0:.6g} Ts\n", state->getRise());
}
-void PSOutputDev::updateWordSpace(GfxState *state) {
- writePSFmt("{0:.6g} Tw\n", state->getWordSpace());
+void PSOutputDev::updateWordSpace(GfxState *state)
+{
+ writePSFmt("{0:.6g} Tw\n", state->getWordSpace());
}
-void PSOutputDev::updateHorizScaling(GfxState *state) {
- double h;
+void PSOutputDev::updateHorizScaling(GfxState *state)
+{
+ double h;
- h = state->getHorizScaling();
- if (fabs(h) < 0.01) {
- h = 0.01;
- }
- writePSFmt("{0:.6g} Tz\n", h);
+ h = state->getHorizScaling();
+ if (fabs(h) < 0.01) {
+ h = 0.01;
+ }
+ writePSFmt("{0:.6g} Tz\n", h);
}
-void PSOutputDev::updateTextPos(GfxState *state) {
- writePSFmt("{0:.6g} {1:.6g} Td\n", state->getLineX(), state->getLineY());
+void PSOutputDev::updateTextPos(GfxState *state)
+{
+ writePSFmt("{0:.6g} {1:.6g} Td\n", state->getLineX(), state->getLineY());
}
-void PSOutputDev::updateTextShift(GfxState *state, double shift) {
- if (state->getFont()->getWMode()) {
- writePSFmt("{0:.6g} TJmV\n", shift);
- } else {
- writePSFmt("{0:.6g} TJm\n", shift);
- }
+void PSOutputDev::updateTextShift(GfxState *state, double shift)
+{
+ if (state->getFont()->getWMode()) {
+ writePSFmt("{0:.6g} TJmV\n", shift);
+ } else {
+ writePSFmt("{0:.6g} TJm\n", shift);
+ }
}
-void PSOutputDev::saveTextPos(GfxState *state) {
- writePS("currentpoint\n");
+void PSOutputDev::saveTextPos(GfxState *state)
+{
+ writePS("currentpoint\n");
}
-void PSOutputDev::restoreTextPos(GfxState *state) {
- writePS("m\n");
+void PSOutputDev::restoreTextPos(GfxState *state)
+{
+ writePS("m\n");
}
-void PSOutputDev::stroke(GfxState *state) {
- doPath(state->getPath());
- if (inType3Char && t3FillColorOnly) {
- // if we're constructing a cacheable Type 3 glyph, we need to do
- // everything in the fill color
- writePS("Sf\n");
- } else {
- writePS("S\n");
- }
+void PSOutputDev::stroke(GfxState *state)
+{
+ doPath(state->getPath());
+ if (inType3Char && t3FillColorOnly) {
+ // if we're constructing a cacheable Type 3 glyph, we need to do
+ // everything in the fill color
+ writePS("Sf\n");
+ } else {
+ writePS("S\n");
+ }
}
-void PSOutputDev::fill(GfxState *state) {
- doPath(state->getPath());
- writePS("f\n");
+void PSOutputDev::fill(GfxState *state)
+{
+ doPath(state->getPath());
+ writePS("f\n");
}
-void PSOutputDev::eoFill(GfxState *state) {
- doPath(state->getPath());
- writePS("f*\n");
+void PSOutputDev::eoFill(GfxState *state)
+{
+ doPath(state->getPath());
+ writePS("f*\n");
}
-bool PSOutputDev::tilingPatternFillL1(GfxState *state, Catalog *cat, Object *str,
- const double *pmat, int paintType, int tilingType, Dict *resDict,
- const double *mat, const double *bbox,
- int x0, int y0, int x1, int y1,
- double xStep, double yStep) {
- PDFRectangle box;
- Gfx *gfx;
-
- // define a Type 3 font
- writePS("8 dict begin\n");
- writePS("/FontType 3 def\n");
- writePS("/FontMatrix [1 0 0 1 0 0] def\n");
- writePSFmt("/FontBBox [{0:.6g} {1:.6g} {2:.6g} {3:.6g}] def\n",
- bbox[0], bbox[1], bbox[2], bbox[3]);
- writePS("/Encoding 256 array def\n");
- writePS(" 0 1 255 { Encoding exch /.notdef put } for\n");
- writePS(" Encoding 120 /x put\n");
- writePS("/BuildGlyph {\n");
- writePS(" exch /CharProcs get exch\n");
- writePS(" 2 copy known not { pop /.notdef } if\n");
- writePS(" get exec\n");
- writePS("} bind def\n");
- writePS("/BuildChar {\n");
- writePS(" 1 index /Encoding get exch get\n");
- writePS(" 1 index /BuildGlyph get exec\n");
- writePS("} bind def\n");
- writePS("/CharProcs 1 dict def\n");
- writePS("CharProcs begin\n");
- box.x1 = bbox[0];
- box.y1 = bbox[1];
- box.x2 = bbox[2];
- box.y2 = bbox[3];
- gfx = new Gfx(doc, this, resDict, &box, nullptr);
- writePS("/x {\n");
- if (paintType == 2) {
- writePSFmt("{0:.6g} 0 {1:.6g} {2:.6g} {3:.6g} {4:.6g} setcachedevice\n",
- xStep, bbox[0], bbox[1], bbox[2], bbox[3]);
- t3FillColorOnly = true;
- } else
- {
- if (x1 - 1 <= x0) {
- writePS("1 0 setcharwidth\n");
+bool PSOutputDev::tilingPatternFillL1(GfxState *state, Catalog *cat, Object *str, const double *pmat, int paintType, int tilingType, Dict *resDict, const double *mat, const double *bbox, int x0, int y0, int x1, int y1, double xStep,
+ double yStep)
+{
+ PDFRectangle box;
+ Gfx *gfx;
+
+ // define a Type 3 font
+ writePS("8 dict begin\n");
+ writePS("/FontType 3 def\n");
+ writePS("/FontMatrix [1 0 0 1 0 0] def\n");
+ writePSFmt("/FontBBox [{0:.6g} {1:.6g} {2:.6g} {3:.6g}] def\n", bbox[0], bbox[1], bbox[2], bbox[3]);
+ writePS("/Encoding 256 array def\n");
+ writePS(" 0 1 255 { Encoding exch /.notdef put } for\n");
+ writePS(" Encoding 120 /x put\n");
+ writePS("/BuildGlyph {\n");
+ writePS(" exch /CharProcs get exch\n");
+ writePS(" 2 copy known not { pop /.notdef } if\n");
+ writePS(" get exec\n");
+ writePS("} bind def\n");
+ writePS("/BuildChar {\n");
+ writePS(" 1 index /Encoding get exch get\n");
+ writePS(" 1 index /BuildGlyph get exec\n");
+ writePS("} bind def\n");
+ writePS("/CharProcs 1 dict def\n");
+ writePS("CharProcs begin\n");
+ box.x1 = bbox[0];
+ box.y1 = bbox[1];
+ box.x2 = bbox[2];
+ box.y2 = bbox[3];
+ gfx = new Gfx(doc, this, resDict, &box, nullptr);
+ writePS("/x {\n");
+ if (paintType == 2) {
+ writePSFmt("{0:.6g} 0 {1:.6g} {2:.6g} {3:.6g} {4:.6g} setcachedevice\n", xStep, bbox[0], bbox[1], bbox[2], bbox[3]);
+ t3FillColorOnly = true;
} else {
- writePSFmt("{0:.6g} 0 setcharwidth\n", xStep);
+ if (x1 - 1 <= x0) {
+ writePS("1 0 setcharwidth\n");
+ } else {
+ writePSFmt("{0:.6g} 0 setcharwidth\n", xStep);
+ }
+ t3FillColorOnly = false;
}
- t3FillColorOnly = false;
- }
- inType3Char = true;
- if (paintType == 2) {
- inUncoloredPattern = true;
- // ensure any PS procedures that contain sCol or fCol do not change the color
- writePS("/pdfLastFill true def\n");
- writePS("/pdfLastStroke true def\n");
- }
- ++numTilingPatterns;
- gfx->display(str);
- --numTilingPatterns;
- if (paintType == 2) {
- inUncoloredPattern = false;
- // ensure the next PS procedures that uses sCol or fCol will update the color
- writePS("/pdfLastFill false def\n");
- writePS("/pdfLastStroke false def\n");
- }
- inType3Char = false;
- writePS("} def\n");
- delete gfx;
- writePS("end\n");
- writePS("currentdict end\n");
- writePSFmt("/xpdfTile{0:d} exch definefont pop\n", numTilingPatterns);
-
- // draw the tiles
- writePSFmt("/xpdfTile{0:d} findfont setfont\n", numTilingPatterns);
- writePS("fCol\n");
- writePSFmt("gsave [{0:.6g} {1:.6g} {2:.6g} {3:.6g} {4:.6g} {5:.6g}] concat\n",
- mat[0], mat[1], mat[2], mat[3], mat[4], mat[5]);
- writePSFmt("{0:d} 1 {1:d} {{ {2:.6g} exch {3:.6g} mul m {4:d} 1 {5:d} {{ pop (x) show }} for }} for\n",
- y0, y1 - 1, x0 * xStep, yStep, x0, x1 - 1);
- writePS("grestore\n");
-
- return true;
-}
+ inType3Char = true;
+ if (paintType == 2) {
+ inUncoloredPattern = true;
+ // ensure any PS procedures that contain sCol or fCol do not change the color
+ writePS("/pdfLastFill true def\n");
+ writePS("/pdfLastStroke true def\n");
+ }
+ ++numTilingPatterns;
+ gfx->display(str);
+ --numTilingPatterns;
+ if (paintType == 2) {
+ inUncoloredPattern = false;
+ // ensure the next PS procedures that uses sCol or fCol will update the color
+ writePS("/pdfLastFill false def\n");
+ writePS("/pdfLastStroke false def\n");
+ }
+ inType3Char = false;
+ writePS("} def\n");
+ delete gfx;
+ writePS("end\n");
+ writePS("currentdict end\n");
+ writePSFmt("/xpdfTile{0:d} exch definefont pop\n", numTilingPatterns);
+
+ // draw the tiles
+ writePSFmt("/xpdfTile{0:d} findfont setfont\n", numTilingPatterns);
+ writePS("fCol\n");
+ writePSFmt("gsave [{0:.6g} {1:.6g} {2:.6g} {3:.6g} {4:.6g} {5:.6g}] concat\n", mat[0], mat[1], mat[2], mat[3], mat[4], mat[5]);
+ writePSFmt("{0:d} 1 {1:d} {{ {2:.6g} exch {3:.6g} mul m {4:d} 1 {5:d} {{ pop (x) show }} for }} for\n", y0, y1 - 1, x0 * xStep, yStep, x0, x1 - 1);
+ writePS("grestore\n");
-bool PSOutputDev::tilingPatternFillL2(GfxState *state, Catalog *cat, Object *str,
- const double *pmat, int paintType, int tilingType, Dict *resDict,
- const double *mat, const double *bbox,
- int x0, int y0, int x1, int y1,
- double xStep, double yStep) {
- PDFRectangle box;
- Gfx *gfx;
-
- if (paintType == 2) {
- // setpattern with PaintType 2 needs the paint color
- writePS("currentcolor\n");
- }
- writePS("<<\n /PatternType 1\n");
- writePSFmt(" /PaintType {0:d}\n", paintType);
- writePSFmt(" /TilingType {0:d}\n", tilingType);
- writePSFmt(" /BBox [{0:.6g} {1:.6g} {2:.6g} {3:.6g}]\n", bbox[0], bbox[1], bbox[2], bbox[3]);
- writePSFmt(" /XStep {0:.6g}\n", xStep);
- writePSFmt(" /YStep {0:.6g}\n", yStep);
- writePS(" /PaintProc { \n");
- box.x1 = bbox[0];
- box.y1 = bbox[1];
- box.x2 = bbox[2];
- box.y2 = bbox[3];
- gfx = new Gfx(doc, this, resDict, &box, nullptr);
- inType3Char = true;
- if (paintType == 2) {
- inUncoloredPattern = true;
- // ensure any PS procedures that contain sCol or fCol do not change the color
- writePS("/pdfLastFill true def\n");
- writePS("/pdfLastStroke true def\n");
- }
- gfx->display(str);
- if (paintType == 2) {
- inUncoloredPattern = false;
- // ensure the next PS procedures that uses sCol or fCol will update the color
- writePS("/pdfLastFill false def\n");
- writePS("/pdfLastStroke false def\n");
- }
- inType3Char = false;
- delete gfx;
- writePS(" }\n");
- writePS(">>\n");
- writePSFmt("[{0:.6g} {1:.6g} {2:.6g} {3:.6g} {4:.6g} {5:.6g}]\n", mat[0], mat[1], mat[2], mat[3], mat[4], mat[5]);
- writePS("makepattern setpattern\n");
- writePS("clippath fill\n"); // Gfx sets up a clip before calling out->tilingPatternFill()
-
- return true;
+ return true;
}
-bool PSOutputDev::tilingPatternFill(GfxState *state, Gfx *gfxA, Catalog *cat, Object *str,
- const double *pmat, int paintType, int tilingType, Dict *resDict,
- const double *mat, const double *bbox,
- int x0, int y0, int x1, int y1,
- double xStep, double yStep) {
- if (x1 - x0 == 1 && y1 - y0 == 1) {
- // Don't need to use patterns if only one instance of the pattern is used
+bool PSOutputDev::tilingPatternFillL2(GfxState *state, Catalog *cat, Object *str, const double *pmat, int paintType, int tilingType, Dict *resDict, const double *mat, const double *bbox, int x0, int y0, int x1, int y1, double xStep,
+ double yStep)
+{
PDFRectangle box;
Gfx *gfx;
- const double singleStep_x = x0 * xStep;
- const double singleStep_y = y0 * yStep;
- const double singleStep_tx = singleStep_x * mat[0] + singleStep_y * mat[2] + mat[4];
- const double singleStep_ty = singleStep_x * mat[1] + singleStep_y * mat[3] + mat[5];
+ if (paintType == 2) {
+ // setpattern with PaintType 2 needs the paint color
+ writePS("currentcolor\n");
+ }
+ writePS("<<\n /PatternType 1\n");
+ writePSFmt(" /PaintType {0:d}\n", paintType);
+ writePSFmt(" /TilingType {0:d}\n", tilingType);
+ writePSFmt(" /BBox [{0:.6g} {1:.6g} {2:.6g} {3:.6g}]\n", bbox[0], bbox[1], bbox[2], bbox[3]);
+ writePSFmt(" /XStep {0:.6g}\n", xStep);
+ writePSFmt(" /YStep {0:.6g}\n", yStep);
+ writePS(" /PaintProc { \n");
box.x1 = bbox[0];
box.y1 = bbox[1];
box.x2 = bbox[2];
box.y2 = bbox[3];
- gfx = new Gfx(doc, this, resDict, &box, nullptr, nullptr, nullptr, gfxA);
- writePSFmt("[{0:.6g} {1:.6g} {2:.6g} {3:.6g} {4:.6g} {5:.6g}] cm\n", mat[0], mat[1], mat[2], mat[3], singleStep_tx, singleStep_ty);
+ gfx = new Gfx(doc, this, resDict, &box, nullptr);
inType3Char = true;
+ if (paintType == 2) {
+ inUncoloredPattern = true;
+ // ensure any PS procedures that contain sCol or fCol do not change the color
+ writePS("/pdfLastFill true def\n");
+ writePS("/pdfLastStroke true def\n");
+ }
gfx->display(str);
+ if (paintType == 2) {
+ inUncoloredPattern = false;
+ // ensure the next PS procedures that uses sCol or fCol will update the color
+ writePS("/pdfLastFill false def\n");
+ writePS("/pdfLastStroke false def\n");
+ }
inType3Char = false;
delete gfx;
+ writePS(" }\n");
+ writePS(">>\n");
+ writePSFmt("[{0:.6g} {1:.6g} {2:.6g} {3:.6g} {4:.6g} {5:.6g}]\n", mat[0], mat[1], mat[2], mat[3], mat[4], mat[5]);
+ writePS("makepattern setpattern\n");
+ writePS("clippath fill\n"); // Gfx sets up a clip before calling out->tilingPatternFill()
+
return true;
- }
-
- if (level == psLevel1 || level == psLevel1Sep) {
- return tilingPatternFillL1(state, cat, str, pmat, paintType, tilingType, resDict,
- mat, bbox, x0, y0, x1, y1, xStep, yStep);
- } else {
- return tilingPatternFillL2(state, cat, str, pmat, paintType, tilingType, resDict,
- mat, bbox, x0, y0, x1, y1, xStep, yStep);
- }
}
-bool PSOutputDev::functionShadedFill(GfxState *state,
- GfxFunctionShading *shading) {
- double x0, y0, x1, y1;
- int i;
-
- if (level == psLevel2Sep || level == psLevel3Sep) {
- if (shading->getColorSpace()->getMode() != csDeviceCMYK) {
- return false;
- }
- processColors |= psProcessCMYK;
- }
-
- shading->getDomain(&x0, &y0, &x1, &y1);
- const double *mat = shading->getMatrix();
- writePSFmt("/mat [{0:.6g} {1:.6g} {2:.6g} {3:.6g} {4:.6g} {5:.6g}] def\n",
- mat[0], mat[1], mat[2], mat[3], mat[4], mat[5]);
- writePSFmt("/n {0:d} def\n", shading->getColorSpace()->getNComps());
- if (shading->getNFuncs() == 1) {
- writePS("/func ");
- cvtFunction(shading->getFunc(0));
- writePS("def\n");
- } else {
- writePS("/func {\n");
- for (i = 0; i < shading->getNFuncs(); ++i) {
- if (i < shading->getNFuncs() - 1) {
- writePS("2 copy\n");
- }
- cvtFunction(shading->getFunc(i));
- writePS("exec\n");
- if (i < shading->getNFuncs() - 1) {
- writePS("3 1 roll\n");
- }
+bool PSOutputDev::tilingPatternFill(GfxState *state, Gfx *gfxA, Catalog *cat, Object *str, const double *pmat, int paintType, int tilingType, Dict *resDict, const double *mat, const double *bbox, int x0, int y0, int x1, int y1,
+ double xStep, double yStep)
+{
+ if (x1 - x0 == 1 && y1 - y0 == 1) {
+ // Don't need to use patterns if only one instance of the pattern is used
+ PDFRectangle box;
+ Gfx *gfx;
+
+ const double singleStep_x = x0 * xStep;
+ const double singleStep_y = y0 * yStep;
+ const double singleStep_tx = singleStep_x * mat[0] + singleStep_y * mat[2] + mat[4];
+ const double singleStep_ty = singleStep_x * mat[1] + singleStep_y * mat[3] + mat[5];
+ box.x1 = bbox[0];
+ box.y1 = bbox[1];
+ box.x2 = bbox[2];
+ box.y2 = bbox[3];
+ gfx = new Gfx(doc, this, resDict, &box, nullptr, nullptr, nullptr, gfxA);
+ writePSFmt("[{0:.6g} {1:.6g} {2:.6g} {3:.6g} {4:.6g} {5:.6g}] cm\n", mat[0], mat[1], mat[2], mat[3], singleStep_tx, singleStep_ty);
+ inType3Char = true;
+ gfx->display(str);
+ inType3Char = false;
+ delete gfx;
+ return true;
+ }
+
+ if (level == psLevel1 || level == psLevel1Sep) {
+ return tilingPatternFillL1(state, cat, str, pmat, paintType, tilingType, resDict, mat, bbox, x0, y0, x1, y1, xStep, yStep);
+ } else {
+ return tilingPatternFillL2(state, cat, str, pmat, paintType, tilingType, resDict, mat, bbox, x0, y0, x1, y1, xStep, yStep);
}
- writePS("} def\n");
- }
- writePSFmt("{0:.6g} {1:.6g} {2:.6g} {3:.6g} 0 funcSH\n", x0, y0, x1, y1);
-
- return true;
}
-bool PSOutputDev::axialShadedFill(GfxState *state, GfxAxialShading *shading, double /*tMin*/, double /*tMax*/) {
- double xMin, yMin, xMax, yMax;
- double x0, y0, x1, y1, dx, dy, mul;
- double tMin, tMax, t, t0, t1;
- int i;
+bool PSOutputDev::functionShadedFill(GfxState *state, GfxFunctionShading *shading)
+{
+ double x0, y0, x1, y1;
+ int i;
- if (level == psLevel2Sep || level == psLevel3Sep) {
- if (shading->getColorSpace()->getMode() != csDeviceCMYK) {
- return false;
+ if (level == psLevel2Sep || level == psLevel3Sep) {
+ if (shading->getColorSpace()->getMode() != csDeviceCMYK) {
+ return false;
+ }
+ processColors |= psProcessCMYK;
}
- processColors |= psProcessCMYK;
- }
- // get the clip region bbox
- state->getUserClipBBox(&xMin, &yMin, &xMax, &yMax);
+ shading->getDomain(&x0, &y0, &x1, &y1);
+ const double *mat = shading->getMatrix();
+ writePSFmt("/mat [{0:.6g} {1:.6g} {2:.6g} {3:.6g} {4:.6g} {5:.6g}] def\n", mat[0], mat[1], mat[2], mat[3], mat[4], mat[5]);
+ writePSFmt("/n {0:d} def\n", shading->getColorSpace()->getNComps());
+ if (shading->getNFuncs() == 1) {
+ writePS("/func ");
+ cvtFunction(shading->getFunc(0));
+ writePS("def\n");
+ } else {
+ writePS("/func {\n");
+ for (i = 0; i < shading->getNFuncs(); ++i) {
+ if (i < shading->getNFuncs() - 1) {
+ writePS("2 copy\n");
+ }
+ cvtFunction(shading->getFunc(i));
+ writePS("exec\n");
+ if (i < shading->getNFuncs() - 1) {
+ writePS("3 1 roll\n");
+ }
+ }
+ writePS("} def\n");
+ }
+ writePSFmt("{0:.6g} {1:.6g} {2:.6g} {3:.6g} 0 funcSH\n", x0, y0, x1, y1);
- // compute min and max t values, based on the four corners of the
- // clip region bbox
- shading->getCoords(&x0, &y0, &x1, &y1);
- dx = x1 - x0;
- dy = y1 - y0;
- if (fabs(dx) < 0.01 && fabs(dy) < 0.01) {
return true;
- } else {
- mul = 1 / (dx * dx + dy * dy);
- tMin = tMax = ((xMin - x0) * dx + (yMin - y0) * dy) * mul;
- t = ((xMin - x0) * dx + (yMax - y0) * dy) * mul;
- if (t < tMin) {
- tMin = t;
- } else if (t > tMax) {
- tMax = t;
- }
- t = ((xMax - x0) * dx + (yMin - y0) * dy) * mul;
- if (t < tMin) {
- tMin = t;
- } else if (t > tMax) {
- tMax = t;
- }
- t = ((xMax - x0) * dx + (yMax - y0) * dy) * mul;
- if (t < tMin) {
- tMin = t;
- } else if (t > tMax) {
- tMax = t;
- }
- if (tMin < 0 && !shading->getExtend0()) {
- tMin = 0;
- }
- if (tMax > 1 && !shading->getExtend1()) {
- tMax = 1;
- }
- }
-
- // get the function domain
- t0 = shading->getDomain0();
- t1 = shading->getDomain1();
-
- // generate the PS code
- writePSFmt("/t0 {0:.6g} def\n", t0);
- writePSFmt("/t1 {0:.6g} def\n", t1);
- writePSFmt("/dt {0:.6g} def\n", t1 - t0);
- writePSFmt("/x0 {0:.6g} def\n", x0);
- writePSFmt("/y0 {0:.6g} def\n", y0);
- writePSFmt("/dx {0:.6g} def\n", x1 - x0);
- writePSFmt("/x1 {0:.6g} def\n", x1);
- writePSFmt("/y1 {0:.6g} def\n", y1);
- writePSFmt("/dy {0:.6g} def\n", y1 - y0);
- writePSFmt("/xMin {0:.6g} def\n", xMin);
- writePSFmt("/yMin {0:.6g} def\n", yMin);
- writePSFmt("/xMax {0:.6g} def\n", xMax);
- writePSFmt("/yMax {0:.6g} def\n", yMax);
- writePSFmt("/n {0:d} def\n", shading->getColorSpace()->getNComps());
- if (shading->getNFuncs() == 1) {
- writePS("/func ");
- cvtFunction(shading->getFunc(0));
- writePS("def\n");
- } else {
- writePS("/func {\n");
- for (i = 0; i < shading->getNFuncs(); ++i) {
- if (i < shading->getNFuncs() - 1) {
- writePS("dup\n");
- }
- cvtFunction(shading->getFunc(i));
- writePS("exec\n");
- if (i < shading->getNFuncs() - 1) {
- writePS("exch\n");
- }
+}
+
+bool PSOutputDev::axialShadedFill(GfxState *state, GfxAxialShading *shading, double /*tMin*/, double /*tMax*/)
+{
+ double xMin, yMin, xMax, yMax;
+ double x0, y0, x1, y1, dx, dy, mul;
+ double tMin, tMax, t, t0, t1;
+ int i;
+
+ if (level == psLevel2Sep || level == psLevel3Sep) {
+ if (shading->getColorSpace()->getMode() != csDeviceCMYK) {
+ return false;
+ }
+ processColors |= psProcessCMYK;
}
- writePS("} def\n");
- }
- writePSFmt("{0:.6g} {1:.6g} 0 axialSH\n", tMin, tMax);
- return true;
-}
+ // get the clip region bbox
+ state->getUserClipBBox(&xMin, &yMin, &xMax, &yMax);
-bool PSOutputDev::radialShadedFill(GfxState *state, GfxRadialShading *shading, double /*sMin*/, double /*sMax*/) {
- double xMin, yMin, xMax, yMax;
- double x0, y0, r0, x1, y1, r1, t0, t1;
- double xa, ya, ra;
- double sMin, sMax, h, ta;
- double sLeft, sRight, sTop, sBottom, sZero, sDiag;
- bool haveSLeft, haveSRight, haveSTop, haveSBottom, haveSZero;
- bool haveSMin, haveSMax;
- double theta, alpha, a1, a2;
- bool enclosed;
- int i;
-
- if (level == psLevel2Sep || level == psLevel3Sep) {
- if (shading->getColorSpace()->getMode() != csDeviceCMYK) {
- return false;
- }
- processColors |= psProcessCMYK;
- }
-
- // get the shading info
- shading->getCoords(&x0, &y0, &r0, &x1, &y1, &r1);
- t0 = shading->getDomain0();
- t1 = shading->getDomain1();
-
- // Compute the point at which r(s) = 0; check for the enclosed
- // circles case; and compute the angles for the tangent lines.
- // Compute the point at which r(s) = 0; check for the enclosed
- // circles case; and compute the angles for the tangent lines.
- h = sqrt((x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0));
- if (h == 0) {
- enclosed = true;
- theta = 0; // make gcc happy
- } else if (r1 - r0 == 0) {
- enclosed = false;
- theta = 0;
- } else if (fabs(r1 - r0) >= h) {
- enclosed = true;
- theta = 0; // make gcc happy
- } else {
- enclosed = false;
- theta = asin((r1 - r0) / h);
- }
- if (enclosed) {
- a1 = 0;
- a2 = 360;
- } else {
- alpha = atan2(y1 - y0, x1 - x0);
- a1 = (180 / M_PI) * (alpha + theta) + 90;
- a2 = (180 / M_PI) * (alpha - theta) - 90;
- while (a2 < a1) {
- a2 += 360;
- }
- }
-
- // compute the (possibly extended) s range
- state->getUserClipBBox(&xMin, &yMin, &xMax, &yMax);
- if (enclosed) {
- sMin = 0;
- sMax = 1;
- } else {
- // solve x(sLeft) + r(sLeft) = xMin
- if ((haveSLeft = fabs((x1 + r1) - (x0 + r0)) > 0.000001)) {
- sLeft = (xMin - (x0 + r0)) / ((x1 + r1) - (x0 + r0));
+ // compute min and max t values, based on the four corners of the
+ // clip region bbox
+ shading->getCoords(&x0, &y0, &x1, &y1);
+ dx = x1 - x0;
+ dy = y1 - y0;
+ if (fabs(dx) < 0.01 && fabs(dy) < 0.01) {
+ return true;
} else {
- sLeft = 0; // make gcc happy
+ mul = 1 / (dx * dx + dy * dy);
+ tMin = tMax = ((xMin - x0) * dx + (yMin - y0) * dy) * mul;
+ t = ((xMin - x0) * dx + (yMax - y0) * dy) * mul;
+ if (t < tMin) {
+ tMin = t;
+ } else if (t > tMax) {
+ tMax = t;
+ }
+ t = ((xMax - x0) * dx + (yMin - y0) * dy) * mul;
+ if (t < tMin) {
+ tMin = t;
+ } else if (t > tMax) {
+ tMax = t;
+ }
+ t = ((xMax - x0) * dx + (yMax - y0) * dy) * mul;
+ if (t < tMin) {
+ tMin = t;
+ } else if (t > tMax) {
+ tMax = t;
+ }
+ if (tMin < 0 && !shading->getExtend0()) {
+ tMin = 0;
+ }
+ if (tMax > 1 && !shading->getExtend1()) {
+ tMax = 1;
+ }
}
- // solve x(sRight) - r(sRight) = xMax
- if ((haveSRight = fabs((x1 - r1) - (x0 - r0)) > 0.000001)) {
- sRight = (xMax - (x0 - r0)) / ((x1 - r1) - (x0 - r0));
+
+ // get the function domain
+ t0 = shading->getDomain0();
+ t1 = shading->getDomain1();
+
+ // generate the PS code
+ writePSFmt("/t0 {0:.6g} def\n", t0);
+ writePSFmt("/t1 {0:.6g} def\n", t1);
+ writePSFmt("/dt {0:.6g} def\n", t1 - t0);
+ writePSFmt("/x0 {0:.6g} def\n", x0);
+ writePSFmt("/y0 {0:.6g} def\n", y0);
+ writePSFmt("/dx {0:.6g} def\n", x1 - x0);
+ writePSFmt("/x1 {0:.6g} def\n", x1);
+ writePSFmt("/y1 {0:.6g} def\n", y1);
+ writePSFmt("/dy {0:.6g} def\n", y1 - y0);
+ writePSFmt("/xMin {0:.6g} def\n", xMin);
+ writePSFmt("/yMin {0:.6g} def\n", yMin);
+ writePSFmt("/xMax {0:.6g} def\n", xMax);
+ writePSFmt("/yMax {0:.6g} def\n", yMax);
+ writePSFmt("/n {0:d} def\n", shading->getColorSpace()->getNComps());
+ if (shading->getNFuncs() == 1) {
+ writePS("/func ");
+ cvtFunction(shading->getFunc(0));
+ writePS("def\n");
} else {
- sRight = 0; // make gcc happy
+ writePS("/func {\n");
+ for (i = 0; i < shading->getNFuncs(); ++i) {
+ if (i < shading->getNFuncs() - 1) {
+ writePS("dup\n");
+ }
+ cvtFunction(shading->getFunc(i));
+ writePS("exec\n");
+ if (i < shading->getNFuncs() - 1) {
+ writePS("exch\n");
+ }
+ }
+ writePS("} def\n");
}
- // solve y(sBottom) + r(sBottom) = yMin
- if ((haveSBottom = fabs((y1 + r1) - (y0 + r0)) > 0.000001)) {
- sBottom = (yMin - (y0 + r0)) / ((y1 + r1) - (y0 + r0));
+ writePSFmt("{0:.6g} {1:.6g} 0 axialSH\n", tMin, tMax);
+
+ return true;
+}
+
+bool PSOutputDev::radialShadedFill(GfxState *state, GfxRadialShading *shading, double /*sMin*/, double /*sMax*/)
+{
+ double xMin, yMin, xMax, yMax;
+ double x0, y0, r0, x1, y1, r1, t0, t1;
+ double xa, ya, ra;
+ double sMin, sMax, h, ta;
+ double sLeft, sRight, sTop, sBottom, sZero, sDiag;
+ bool haveSLeft, haveSRight, haveSTop, haveSBottom, haveSZero;
+ bool haveSMin, haveSMax;
+ double theta, alpha, a1, a2;
+ bool enclosed;
+ int i;
+
+ if (level == psLevel2Sep || level == psLevel3Sep) {
+ if (shading->getColorSpace()->getMode() != csDeviceCMYK) {
+ return false;
+ }
+ processColors |= psProcessCMYK;
+ }
+
+ // get the shading info
+ shading->getCoords(&x0, &y0, &r0, &x1, &y1, &r1);
+ t0 = shading->getDomain0();
+ t1 = shading->getDomain1();
+
+ // Compute the point at which r(s) = 0; check for the enclosed
+ // circles case; and compute the angles for the tangent lines.
+ // Compute the point at which r(s) = 0; check for the enclosed
+ // circles case; and compute the angles for the tangent lines.
+ h = sqrt((x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0));
+ if (h == 0) {
+ enclosed = true;
+ theta = 0; // make gcc happy
+ } else if (r1 - r0 == 0) {
+ enclosed = false;
+ theta = 0;
+ } else if (fabs(r1 - r0) >= h) {
+ enclosed = true;
+ theta = 0; // make gcc happy
} else {
- sBottom = 0; // make gcc happy
+ enclosed = false;
+ theta = asin((r1 - r0) / h);
}
- // solve y(sTop) - r(sTop) = yMax
- if ((haveSTop = fabs((y1 - r1) - (y0 - r0)) > 0.000001)) {
- sTop = (yMax - (y0 - r0)) / ((y1 - r1) - (y0 - r0));
+ if (enclosed) {
+ a1 = 0;
+ a2 = 360;
} else {
- sTop = 0; // make gcc happy
+ alpha = atan2(y1 - y0, x1 - x0);
+ a1 = (180 / M_PI) * (alpha + theta) + 90;
+ a2 = (180 / M_PI) * (alpha - theta) - 90;
+ while (a2 < a1) {
+ a2 += 360;
+ }
}
- // solve r(sZero) = 0
- if ((haveSZero = fabs(r1 - r0) > 0.000001)) {
- sZero = -r0 / (r1 - r0);
+
+ // compute the (possibly extended) s range
+ state->getUserClipBBox(&xMin, &yMin, &xMax, &yMax);
+ if (enclosed) {
+ sMin = 0;
+ sMax = 1;
} else {
- sZero = 0; // make gcc happy
+ // solve x(sLeft) + r(sLeft) = xMin
+ if ((haveSLeft = fabs((x1 + r1) - (x0 + r0)) > 0.000001)) {
+ sLeft = (xMin - (x0 + r0)) / ((x1 + r1) - (x0 + r0));
+ } else {
+ sLeft = 0; // make gcc happy
+ }
+ // solve x(sRight) - r(sRight) = xMax
+ if ((haveSRight = fabs((x1 - r1) - (x0 - r0)) > 0.000001)) {
+ sRight = (xMax - (x0 - r0)) / ((x1 - r1) - (x0 - r0));
+ } else {
+ sRight = 0; // make gcc happy
+ }
+ // solve y(sBottom) + r(sBottom) = yMin
+ if ((haveSBottom = fabs((y1 + r1) - (y0 + r0)) > 0.000001)) {
+ sBottom = (yMin - (y0 + r0)) / ((y1 + r1) - (y0 + r0));
+ } else {
+ sBottom = 0; // make gcc happy
+ }
+ // solve y(sTop) - r(sTop) = yMax
+ if ((haveSTop = fabs((y1 - r1) - (y0 - r0)) > 0.000001)) {
+ sTop = (yMax - (y0 - r0)) / ((y1 - r1) - (y0 - r0));
+ } else {
+ sTop = 0; // make gcc happy
+ }
+ // solve r(sZero) = 0
+ if ((haveSZero = fabs(r1 - r0) > 0.000001)) {
+ sZero = -r0 / (r1 - r0);
+ } else {
+ sZero = 0; // make gcc happy
+ }
+ // solve r(sDiag) = sqrt((xMax-xMin)^2 + (yMax-yMin)^2)
+ if (haveSZero) {
+ sDiag = (sqrt((xMax - xMin) * (xMax - xMin) + (yMax - yMin) * (yMax - yMin)) - r0) / (r1 - r0);
+ } else {
+ sDiag = 0; // make gcc happy
+ }
+ // compute sMin
+ if (shading->getExtend0()) {
+ sMin = 0;
+ haveSMin = false;
+ if (x0 < x1 && haveSLeft && sLeft < 0) {
+ sMin = sLeft;
+ haveSMin = true;
+ } else if (x0 > x1 && haveSRight && sRight < 0) {
+ sMin = sRight;
+ haveSMin = true;
+ }
+ if (y0 < y1 && haveSBottom && sBottom < 0) {
+ if (!haveSMin || sBottom > sMin) {
+ sMin = sBottom;
+ haveSMin = true;
+ }
+ } else if (y0 > y1 && haveSTop && sTop < 0) {
+ if (!haveSMin || sTop > sMin) {
+ sMin = sTop;
+ haveSMin = true;
+ }
+ }
+ if (haveSZero && sZero < 0) {
+ if (!haveSMin || sZero > sMin) {
+ sMin = sZero;
+ }
+ }
+ } else {
+ sMin = 0;
+ }
+ // compute sMax
+ if (shading->getExtend1()) {
+ sMax = 1;
+ haveSMax = false;
+ if (x1 < x0 && haveSLeft && sLeft > 1) {
+ sMax = sLeft;
+ haveSMax = true;
+ } else if (x1 > x0 && haveSRight && sRight > 1) {
+ sMax = sRight;
+ haveSMax = true;
+ }
+ if (y1 < y0 && haveSBottom && sBottom > 1) {
+ if (!haveSMax || sBottom < sMax) {
+ sMax = sBottom;
+ haveSMax = true;
+ }
+ } else if (y1 > y0 && haveSTop && sTop > 1) {
+ if (!haveSMax || sTop < sMax) {
+ sMax = sTop;
+ haveSMax = true;
+ }
+ }
+ if (haveSZero && sDiag > 1) {
+ if (!haveSMax || sDiag < sMax) {
+ sMax = sDiag;
+ }
+ }
+ } else {
+ sMax = 1;
+ }
}
- // solve r(sDiag) = sqrt((xMax-xMin)^2 + (yMax-yMin)^2)
- if (haveSZero) {
- sDiag = (sqrt((xMax - xMin) * (xMax - xMin) +
- (yMax - yMin) * (yMax - yMin)) - r0) / (r1 - r0);
- } else {
- sDiag = 0; // make gcc happy
- }
- // compute sMin
- if (shading->getExtend0()) {
- sMin = 0;
- haveSMin = false;
- if (x0 < x1 && haveSLeft && sLeft < 0) {
- sMin = sLeft;
- haveSMin = true;
- } else if (x0 > x1 && haveSRight && sRight < 0) {
- sMin = sRight;
- haveSMin = true;
- }
- if (y0 < y1 && haveSBottom && sBottom < 0) {
- if (!haveSMin || sBottom > sMin) {
- sMin = sBottom;
- haveSMin = true;
- }
- } else if (y0 > y1 && haveSTop && sTop < 0) {
- if (!haveSMin || sTop > sMin) {
- sMin = sTop;
- haveSMin = true;
- }
- }
- if (haveSZero && sZero < 0) {
- if (!haveSMin || sZero > sMin) {
- sMin = sZero;
- }
- }
- } else {
- sMin = 0;
- }
- // compute sMax
- if (shading->getExtend1()) {
- sMax = 1;
- haveSMax = false;
- if (x1 < x0 && haveSLeft && sLeft > 1) {
- sMax = sLeft;
- haveSMax = true;
- } else if (x1 > x0 && haveSRight && sRight > 1) {
- sMax = sRight;
- haveSMax = true;
- }
- if (y1 < y0 && haveSBottom && sBottom > 1) {
- if (!haveSMax || sBottom < sMax) {
- sMax = sBottom;
- haveSMax = true;
- }
- } else if (y1 > y0 && haveSTop && sTop > 1) {
- if (!haveSMax || sTop < sMax) {
- sMax = sTop;
- haveSMax = true;
- }
- }
- if (haveSZero && sDiag > 1) {
- if (!haveSMax || sDiag < sMax) {
- sMax = sDiag;
- }
- }
+
+ // generate the PS code
+ writePSFmt("/x0 {0:.6g} def\n", x0);
+ writePSFmt("/x1 {0:.6g} def\n", x1);
+ writePSFmt("/dx {0:.6g} def\n", x1 - x0);
+ writePSFmt("/y0 {0:.6g} def\n", y0);
+ writePSFmt("/y1 {0:.6g} def\n", y1);
+ writePSFmt("/dy {0:.6g} def\n", y1 - y0);
+ writePSFmt("/r0 {0:.6g} def\n", r0);
+ writePSFmt("/r1 {0:.6g} def\n", r1);
+ writePSFmt("/dr {0:.6g} def\n", r1 - r0);
+ writePSFmt("/t0 {0:.6g} def\n", t0);
+ writePSFmt("/t1 {0:.6g} def\n", t1);
+ writePSFmt("/dt {0:.6g} def\n", t1 - t0);
+ writePSFmt("/n {0:d} def\n", shading->getColorSpace()->getNComps());
+ writePSFmt("/encl {0:s} def\n", enclosed ? "true" : "false");
+ writePSFmt("/a1 {0:.6g} def\n", a1);
+ writePSFmt("/a2 {0:.6g} def\n", a2);
+ if (shading->getNFuncs() == 1) {
+ writePS("/func ");
+ cvtFunction(shading->getFunc(0));
+ writePS("def\n");
} else {
- sMax = 1;
- }
- }
-
- // generate the PS code
- writePSFmt("/x0 {0:.6g} def\n", x0);
- writePSFmt("/x1 {0:.6g} def\n", x1);
- writePSFmt("/dx {0:.6g} def\n", x1 - x0);
- writePSFmt("/y0 {0:.6g} def\n", y0);
- writePSFmt("/y1 {0:.6g} def\n", y1);
- writePSFmt("/dy {0:.6g} def\n", y1 - y0);
- writePSFmt("/r0 {0:.6g} def\n", r0);
- writePSFmt("/r1 {0:.6g} def\n", r1);
- writePSFmt("/dr {0:.6g} def\n", r1 - r0);
- writePSFmt("/t0 {0:.6g} def\n", t0);
- writePSFmt("/t1 {0:.6g} def\n", t1);
- writePSFmt("/dt {0:.6g} def\n", t1 - t0);
- writePSFmt("/n {0:d} def\n", shading->getColorSpace()->getNComps());
- writePSFmt("/encl {0:s} def\n", enclosed ? "true" : "false");
- writePSFmt("/a1 {0:.6g} def\n", a1);
- writePSFmt("/a2 {0:.6g} def\n", a2);
- if (shading->getNFuncs() == 1) {
- writePS("/func ");
- cvtFunction(shading->getFunc(0));
- writePS("def\n");
- } else {
- writePS("/func {\n");
- for (i = 0; i < shading->getNFuncs(); ++i) {
- if (i < shading->getNFuncs() - 1) {
- writePS("dup\n");
- }
- cvtFunction(shading->getFunc(i));
- writePS("exec\n");
- if (i < shading->getNFuncs() - 1) {
- writePS("exch\n");
- }
+ writePS("/func {\n");
+ for (i = 0; i < shading->getNFuncs(); ++i) {
+ if (i < shading->getNFuncs() - 1) {
+ writePS("dup\n");
+ }
+ cvtFunction(shading->getFunc(i));
+ writePS("exec\n");
+ if (i < shading->getNFuncs() - 1) {
+ writePS("exch\n");
+ }
+ }
+ writePS("} def\n");
+ }
+ writePSFmt("{0:.6g} {1:.6g} 0 radialSH\n", sMin, sMax);
+
+ // extend the 'enclosed' case
+ if (enclosed) {
+ // extend the smaller circle
+ if ((shading->getExtend0() && r0 <= r1) || (shading->getExtend1() && r1 < r0)) {
+ if (r0 <= r1) {
+ ta = t0;
+ ra = r0;
+ xa = x0;
+ ya = y0;
+ } else {
+ ta = t1;
+ ra = r1;
+ xa = x1;
+ ya = y1;
+ }
+ if (level == psLevel2Sep || level == psLevel3Sep) {
+ writePSFmt("{0:.6g} radialCol aload pop k\n", ta);
+ } else {
+ writePSFmt("{0:.6g} radialCol sc\n", ta);
+ }
+ writePSFmt("{0:.6g} {1:.6g} {2:.6g} 0 360 arc h f*\n", xa, ya, ra);
+ }
+
+ // extend the larger circle
+ if ((shading->getExtend0() && r0 > r1) || (shading->getExtend1() && r1 >= r0)) {
+ if (r0 > r1) {
+ ta = t0;
+ ra = r0;
+ xa = x0;
+ ya = y0;
+ } else {
+ ta = t1;
+ ra = r1;
+ xa = x1;
+ ya = y1;
+ }
+ if (level == psLevel2Sep || level == psLevel3Sep) {
+ writePSFmt("{0:.6g} radialCol aload pop k\n", ta);
+ } else {
+ writePSFmt("{0:.6g} radialCol sc\n", ta);
+ }
+ writePSFmt("{0:.6g} {1:.6g} {2:.6g} 0 360 arc h\n", xa, ya, ra);
+ writePSFmt("{0:.6g} {1:.6g} m {2:.6g} {3:.6g} l {4:.6g} {5:.6g} l {6:.6g} {7:.6g} l h f*\n", xMin, yMin, xMin, yMax, xMax, yMax, xMax, yMin);
+ }
}
- writePS("} def\n");
- }
- writePSFmt("{0:.6g} {1:.6g} 0 radialSH\n", sMin, sMax);
-
- // extend the 'enclosed' case
- if (enclosed) {
- // extend the smaller circle
- if ((shading->getExtend0() && r0 <= r1) ||
- (shading->getExtend1() && r1 < r0)) {
- if (r0 <= r1) {
- ta = t0;
- ra = r0;
- xa = x0;
- ya = y0;
- } else {
- ta = t1;
- ra = r1;
- xa = x1;
- ya = y1;
- }
- if (level == psLevel2Sep || level == psLevel3Sep) {
- writePSFmt("{0:.6g} radialCol aload pop k\n", ta);
- } else {
- writePSFmt("{0:.6g} radialCol sc\n", ta);
- }
- writePSFmt("{0:.6g} {1:.6g} {2:.6g} 0 360 arc h f*\n", xa, ya, ra);
- }
-
- // extend the larger circle
- if ((shading->getExtend0() && r0 > r1) ||
- (shading->getExtend1() && r1 >= r0)) {
- if (r0 > r1) {
- ta = t0;
- ra = r0;
- xa = x0;
- ya = y0;
- } else {
- ta = t1;
- ra = r1;
- xa = x1;
- ya = y1;
- }
- if (level == psLevel2Sep || level == psLevel3Sep) {
- writePSFmt("{0:.6g} radialCol aload pop k\n", ta);
- } else {
- writePSFmt("{0:.6g} radialCol sc\n", ta);
- }
- writePSFmt("{0:.6g} {1:.6g} {2:.6g} 0 360 arc h\n", xa, ya, ra);
- writePSFmt("{0:.6g} {1:.6g} m {2:.6g} {3:.6g} l {4:.6g} {5:.6g} l {6:.6g} {7:.6g} l h f*\n",
- xMin, yMin, xMin, yMax, xMax, yMax, xMax, yMin);
- }
- }
-
- return true;
+
+ return true;
}
-bool PSOutputDev::patchMeshShadedFill(GfxState *state,
- GfxPatchMeshShading *shading) {
- // TODO: support parametrized shading
- if (level < psLevel3 || shading->isParameterized()) {
- return false;
- }
+bool PSOutputDev::patchMeshShadedFill(GfxState *state, GfxPatchMeshShading *shading)
+{
+ // TODO: support parametrized shading
+ if (level < psLevel3 || shading->isParameterized()) {
+ return false;
+ }
- writePS("%% Begin patchMeshShadedFill\n");
+ writePS("%% Begin patchMeshShadedFill\n");
- // ShadingType 7 shadings are pretty much the same for pdf and ps.
- // As such, we basically just need to invert GfxPatchMeshShading::parse here.
+ // ShadingType 7 shadings are pretty much the same for pdf and ps.
+ // As such, we basically just need to invert GfxPatchMeshShading::parse here.
- writePS("<<\n");
- writePS(" /ShadingType 7\n");
- writePS(" /ColorSpace ");
- dumpColorSpaceL2(state, shading->getColorSpace(), false, false, false);
- writePS("\n");
- writePS(" /DataSource [\n");
+ writePS("<<\n");
+ writePS(" /ShadingType 7\n");
+ writePS(" /ColorSpace ");
+ dumpColorSpaceL2(state, shading->getColorSpace(), false, false, false);
+ writePS("\n");
+ writePS(" /DataSource [\n");
- const int ncomps = shading->getColorSpace()->getNComps();
+ const int ncomps = shading->getColorSpace()->getNComps();
- for (int i = 0; i < shading->getNPatches(); ++i) {
- const auto& patch = *shading->getPatch(i);
- // Print Flag, for us always f = 0
- writePS(" 0 \n");
+ for (int i = 0; i < shading->getNPatches(); ++i) {
+ const auto &patch = *shading->getPatch(i);
+ // Print Flag, for us always f = 0
+ writePS(" 0 \n");
- // Print coordinates
- const std::array<std::pair<int,int>, 16> coordindices = {{ {0,0}, {0,1}, {0,2}, {0,3},
- {1,3}, {2,3}, {3,3}, {3,2},
- {3,1}, {3,0}, {2,0}, {1,0},
- {1,1}, {1,2}, {2,2}, {2,1} }};
- for (const auto& index: coordindices) {
- writePSFmt(" {0:.6g} {1:.6g}\n", patch.x[index.first][index.second],
- patch.y[index.first][index.second]);
- }
+ // Print coordinates
+ const std::array<std::pair<int, int>, 16> coordindices = { { { 0, 0 }, { 0, 1 }, { 0, 2 }, { 0, 3 }, { 1, 3 }, { 2, 3 }, { 3, 3 }, { 3, 2 }, { 3, 1 }, { 3, 0 }, { 2, 0 }, { 1, 0 }, { 1, 1 }, { 1, 2 }, { 2, 2 }, { 2, 1 } } };
+ for (const auto &index : coordindices) {
+ writePSFmt(" {0:.6g} {1:.6g}\n", patch.x[index.first][index.second], patch.y[index.first][index.second]);
+ }
- // Print colors
- const std::array<std::pair<int, int>, 4> colindices = {{ {0,0}, {0,1}, {1,1}, {1,0} }};
- for (const auto& index: colindices) {
- writePS(" ");
- for (int comp = 0; comp < ncomps; ++comp) {
- writePSFmt(" {0:.6g}", colToDbl(patch.color[index.first][index.second].c[comp]));
- }
- writePS("\n");
+ // Print colors
+ const std::array<std::pair<int, int>, 4> colindices = { { { 0, 0 }, { 0, 1 }, { 1, 1 }, { 1, 0 } } };
+ for (const auto &index : colindices) {
+ writePS(" ");
+ for (int comp = 0; comp < ncomps; ++comp) {
+ writePSFmt(" {0:.6g}", colToDbl(patch.color[index.first][index.second].c[comp]));
+ }
+ writePS("\n");
+ }
}
- }
- writePS(" ]\n");
+ writePS(" ]\n");
- writePS(">> shfill\n");
- writePS("%% End patchMeshShadedFill\n");
- return true;
+ writePS(">> shfill\n");
+ writePS("%% End patchMeshShadedFill\n");
+ return true;
}
-void PSOutputDev::clip(GfxState *state) {
- doPath(state->getPath());
- writePS("W\n");
+void PSOutputDev::clip(GfxState *state)
+{
+ doPath(state->getPath());
+ writePS("W\n");
}
-void PSOutputDev::eoClip(GfxState *state) {
- doPath(state->getPath());
- writePS("W*\n");
+void PSOutputDev::eoClip(GfxState *state)
+{
+ doPath(state->getPath());
+ writePS("W*\n");
}
-void PSOutputDev::clipToStrokePath(GfxState *state) {
- doPath(state->getPath());
- writePS("Ws\n");
+void PSOutputDev::clipToStrokePath(GfxState *state)
+{
+ doPath(state->getPath());
+ writePS("Ws\n");
}
-void PSOutputDev::doPath(const GfxPath *path) {
- double x0, y0, x1, y1, x2, y2, x3, y3, x4, y4;
- int n, m, i, j;
-
- n = path->getNumSubpaths();
-
- if (n == 1 && path->getSubpath(0)->getNumPoints() == 5) {
- const GfxSubpath *subpath = path->getSubpath(0);
- x0 = subpath->getX(0);
- y0 = subpath->getY(0);
- x4 = subpath->getX(4);
- y4 = subpath->getY(4);
- if (x4 == x0 && y4 == y0) {
- x1 = subpath->getX(1);
- y1 = subpath->getY(1);
- x2 = subpath->getX(2);
- y2 = subpath->getY(2);
- x3 = subpath->getX(3);
- y3 = subpath->getY(3);
- if (x0 == x1 && x2 == x3 && y0 == y3 && y1 == y2) {
- writePSFmt("{0:.6g} {1:.6g} {2:.6g} {3:.6g} re\n",
- x0 < x2 ? x0 : x2, y0 < y1 ? y0 : y1,
- fabs(x2 - x0), fabs(y1 - y0));
- return;
- } else if (x0 == x3 && x1 == x2 && y0 == y1 && y2 == y3) {
- writePSFmt("{0:.6g} {1:.6g} {2:.6g} {3:.6g} re\n",
- x0 < x1 ? x0 : x1, y0 < y2 ? y0 : y2,
- fabs(x1 - x0), fabs(y2 - y0));
- return;
- }
- }
- }
-
- for (i = 0; i < n; ++i) {
- const GfxSubpath *subpath = path->getSubpath(i);
- m = subpath->getNumPoints();
- writePSFmt("{0:.6g} {1:.6g} m\n", subpath->getX(0), subpath->getY(0));
- j = 1;
- while (j < m) {
- if (subpath->getCurve(j)) {
- writePSFmt("{0:.6g} {1:.6g} {2:.6g} {3:.6g} {4:.6g} {5:.6g} c\n",
- subpath->getX(j), subpath->getY(j),
- subpath->getX(j+1), subpath->getY(j+1),
- subpath->getX(j+2), subpath->getY(j+2));
- j += 3;
- } else {
- writePSFmt("{0:.6g} {1:.6g} l\n", subpath->getX(j), subpath->getY(j));
- ++j;
- }
- }
- if (subpath->isClosed()) {
- writePS("h\n");
- }
- }
-}
+void PSOutputDev::doPath(const GfxPath *path)
+{
+ double x0, y0, x1, y1, x2, y2, x3, y3, x4, y4;
+ int n, m, i, j;
+
+ n = path->getNumSubpaths();
+
+ if (n == 1 && path->getSubpath(0)->getNumPoints() == 5) {
+ const GfxSubpath *subpath = path->getSubpath(0);
+ x0 = subpath->getX(0);
+ y0 = subpath->getY(0);
+ x4 = subpath->getX(4);
+ y4 = subpath->getY(4);
+ if (x4 == x0 && y4 == y0) {
+ x1 = subpath->getX(1);
+ y1 = subpath->getY(1);
+ x2 = subpath->getX(2);
+ y2 = subpath->getY(2);
+ x3 = subpath->getX(3);
+ y3 = subpath->getY(3);
+ if (x0 == x1 && x2 == x3 && y0 == y3 && y1 == y2) {
+ writePSFmt("{0:.6g} {1:.6g} {2:.6g} {3:.6g} re\n", x0 < x2 ? x0 : x2, y0 < y1 ? y0 : y1, fabs(x2 - x0), fabs(y1 - y0));
+ return;
+ } else if (x0 == x3 && x1 == x2 && y0 == y1 && y2 == y3) {
+ writePSFmt("{0:.6g} {1:.6g} {2:.6g} {3:.6g} re\n", x0 < x1 ? x0 : x1, y0 < y2 ? y0 : y2, fabs(x1 - x0), fabs(y2 - y0));
+ return;
+ }
+ }
+ }
-void PSOutputDev::drawString(GfxState *state, const GooString *s) {
- GfxFont *font;
- int wMode;
- int *codeToGID;
- GooString *s2;
- double dx, dy, originX, originY;
- const char *p;
- const UnicodeMap *uMap;
- CharCode code;
- const Unicode *u;
- char buf[8];
- double *dxdy;
- int dxdySize, len, nChars, uLen, n, m, i, j;
- int maxGlyphInt;
- CharCode maxGlyph;
-
- // for pdftohtml, output PS without text
- if( displayText == false )
- return;
-
- // check for invisible text -- this is used by Acrobat Capture
- if (state->getRender() == 3) {
- return;
- }
-
- // ignore empty strings
- if (s->getLength() == 0) {
- return;
- }
-
- // get the font
- if (!(font = state->getFont())) {
- return;
- }
- maxGlyphInt = (font->getName() ? perFontMaxValidGlyph[font->getName()->toStr()] : 0);
- if (maxGlyphInt < 0) maxGlyphInt = 0;
- maxGlyph = (CharCode) maxGlyphInt;
- wMode = font->getWMode();
-
- // check for a subtitute 16-bit font
- uMap = nullptr;
- codeToGID = nullptr;
- if (font->isCIDFont()) {
- for (i = 0; i < font16EncLen; ++i) {
- if (*font->getID() == font16Enc[i].fontID) {
- if (!font16Enc[i].enc) {
- // font substitution failed, so don't output any text
- return;
- }
- uMap = globalParams->getUnicodeMap(font16Enc[i].enc->toStr());
- break;
- }
- }
-
- // check for a code-to-GID map
- } else {
- for (i = 0; i < font8InfoLen; ++i) {
- if (*font->getID() == font8Info[i].fontID) {
- codeToGID = font8Info[i].codeToGID;
- break;
- }
- }
- }
-
- // compute the positioning (dx, dy) for each char in the string
- nChars = 0;
- p = s->c_str();
- len = s->getLength();
- s2 = new GooString();
- dxdySize = font->isCIDFont() ? 8 : s->getLength();
- dxdy = (double *)gmallocn(2 * dxdySize, sizeof(double));
- while (len > 0) {
- n = font->getNextChar(p, len, &code,
- &u, &uLen,
- &dx, &dy, &originX, &originY);
- dx *= state->getFontSize();
- dy *= state->getFontSize();
- if (wMode) {
- dy += state->getCharSpace();
- if (n == 1 && *p == ' ') {
- dy += state->getWordSpace();
- }
- } else {
- dx += state->getCharSpace();
- if (n == 1 && *p == ' ') {
- dx += state->getWordSpace();
- }
+ for (i = 0; i < n; ++i) {
+ const GfxSubpath *subpath = path->getSubpath(i);
+ m = subpath->getNumPoints();
+ writePSFmt("{0:.6g} {1:.6g} m\n", subpath->getX(0), subpath->getY(0));
+ j = 1;
+ while (j < m) {
+ if (subpath->getCurve(j)) {
+ writePSFmt("{0:.6g} {1:.6g} {2:.6g} {3:.6g} {4:.6g} {5:.6g} c\n", subpath->getX(j), subpath->getY(j), subpath->getX(j + 1), subpath->getY(j + 1), subpath->getX(j + 2), subpath->getY(j + 2));
+ j += 3;
+ } else {
+ writePSFmt("{0:.6g} {1:.6g} l\n", subpath->getX(j), subpath->getY(j));
+ ++j;
+ }
+ }
+ if (subpath->isClosed()) {
+ writePS("h\n");
+ }
}
- dx *= state->getHorizScaling();
+}
+
+void PSOutputDev::drawString(GfxState *state, const GooString *s)
+{
+ GfxFont *font;
+ int wMode;
+ int *codeToGID;
+ GooString *s2;
+ double dx, dy, originX, originY;
+ const char *p;
+ const UnicodeMap *uMap;
+ CharCode code;
+ const Unicode *u;
+ char buf[8];
+ double *dxdy;
+ int dxdySize, len, nChars, uLen, n, m, i, j;
+ int maxGlyphInt;
+ CharCode maxGlyph;
+
+ // for pdftohtml, output PS without text
+ if (displayText == false)
+ return;
+
+ // check for invisible text -- this is used by Acrobat Capture
+ if (state->getRender() == 3) {
+ return;
+ }
+
+ // ignore empty strings
+ if (s->getLength() == 0) {
+ return;
+ }
+
+ // get the font
+ if (!(font = state->getFont())) {
+ return;
+ }
+ maxGlyphInt = (font->getName() ? perFontMaxValidGlyph[font->getName()->toStr()] : 0);
+ if (maxGlyphInt < 0)
+ maxGlyphInt = 0;
+ maxGlyph = (CharCode)maxGlyphInt;
+ wMode = font->getWMode();
+
+ // check for a subtitute 16-bit font
+ uMap = nullptr;
+ codeToGID = nullptr;
if (font->isCIDFont()) {
- if (uMap) {
- if (nChars + uLen > dxdySize) {
- do {
- dxdySize *= 2;
- } while (nChars + uLen > dxdySize);
- dxdy = (double *)greallocn(dxdy, 2 * dxdySize, sizeof(double));
- }
- for (i = 0; i < uLen; ++i) {
- m = uMap->mapUnicode(u[i], buf, (int)sizeof(buf));
- for (j = 0; j < m; ++j) {
- s2->append(buf[j]);
- }
- //~ this really needs to get the number of chars in the target
- //~ encoding - which may be more than the number of Unicode
- //~ chars
- dxdy[2 * nChars] = dx;
- dxdy[2 * nChars + 1] = dy;
- ++nChars;
- }
- } else if (maxGlyph > 0 && code > maxGlyph) {
- // Ignore this code.
- // Using it will exceed the number of glyphs in the font and generate
- // /rangecheck in --xyshow--
- if (nChars > 0) {
- dxdy[2 * (nChars-1) ] += dx;
- dxdy[2 * (nChars-1) + 1 ] += dy;
- }
- } else {
- if (nChars + 1 > dxdySize) {
- dxdySize *= 2;
- dxdy = (double *)greallocn(dxdy, 2 * dxdySize, sizeof(double));
- }
- s2->append((char)((code >> 8) & 0xff));
- s2->append((char)(code & 0xff));
- dxdy[2 * nChars] = dx;
- dxdy[2 * nChars + 1] = dy;
- ++nChars;
- }
+ for (i = 0; i < font16EncLen; ++i) {
+ if (*font->getID() == font16Enc[i].fontID) {
+ if (!font16Enc[i].enc) {
+ // font substitution failed, so don't output any text
+ return;
+ }
+ uMap = globalParams->getUnicodeMap(font16Enc[i].enc->toStr());
+ break;
+ }
+ }
+
+ // check for a code-to-GID map
} else {
- if (!codeToGID || codeToGID[code] >= 0) {
- s2->append((char)code);
- dxdy[2 * nChars] = dx;
- dxdy[2 * nChars + 1] = dy;
- ++nChars;
- }
- }
- p += n;
- len -= n;
- }
-
- if (nChars > 0) {
- writePSString(s2->toStr());
- writePS("\n[");
- for (i = 0; i < 2 * nChars; ++i) {
- if (i > 0) {
- writePS("\n");
- }
- writePSFmt("{0:.6g}", dxdy[i]);
- }
- writePS("] Tj\n");
- }
- gfree(dxdy);
- delete s2;
-
- if (state->getRender() & 4) {
- haveTextClip = true;
- }
-}
+ for (i = 0; i < font8InfoLen; ++i) {
+ if (*font->getID() == font8Info[i].fontID) {
+ codeToGID = font8Info[i].codeToGID;
+ break;
+ }
+ }
+ }
+
+ // compute the positioning (dx, dy) for each char in the string
+ nChars = 0;
+ p = s->c_str();
+ len = s->getLength();
+ s2 = new GooString();
+ dxdySize = font->isCIDFont() ? 8 : s->getLength();
+ dxdy = (double *)gmallocn(2 * dxdySize, sizeof(double));
+ while (len > 0) {
+ n = font->getNextChar(p, len, &code, &u, &uLen, &dx, &dy, &originX, &originY);
+ dx *= state->getFontSize();
+ dy *= state->getFontSize();
+ if (wMode) {
+ dy += state->getCharSpace();
+ if (n == 1 && *p == ' ') {
+ dy += state->getWordSpace();
+ }
+ } else {
+ dx += state->getCharSpace();
+ if (n == 1 && *p == ' ') {
+ dx += state->getWordSpace();
+ }
+ }
+ dx *= state->getHorizScaling();
+ if (font->isCIDFont()) {
+ if (uMap) {
+ if (nChars + uLen > dxdySize) {
+ do {
+ dxdySize *= 2;
+ } while (nChars + uLen > dxdySize);
+ dxdy = (double *)greallocn(dxdy, 2 * dxdySize, sizeof(double));
+ }
+ for (i = 0; i < uLen; ++i) {
+ m = uMap->mapUnicode(u[i], buf, (int)sizeof(buf));
+ for (j = 0; j < m; ++j) {
+ s2->append(buf[j]);
+ }
+ //~ this really needs to get the number of chars in the target
+ //~ encoding - which may be more than the number of Unicode
+ //~ chars
+ dxdy[2 * nChars] = dx;
+ dxdy[2 * nChars + 1] = dy;
+ ++nChars;
+ }
+ } else if (maxGlyph > 0 && code > maxGlyph) {
+ // Ignore this code.
+ // Using it will exceed the number of glyphs in the font and generate
+ // /rangecheck in --xyshow--
+ if (nChars > 0) {
+ dxdy[2 * (nChars - 1)] += dx;
+ dxdy[2 * (nChars - 1) + 1] += dy;
+ }
+ } else {
+ if (nChars + 1 > dxdySize) {
+ dxdySize *= 2;
+ dxdy = (double *)greallocn(dxdy, 2 * dxdySize, sizeof(double));
+ }
+ s2->append((char)((code >> 8) & 0xff));
+ s2->append((char)(code & 0xff));
+ dxdy[2 * nChars] = dx;
+ dxdy[2 * nChars + 1] = dy;
+ ++nChars;
+ }
+ } else {
+ if (!codeToGID || codeToGID[code] >= 0) {
+ s2->append((char)code);
+ dxdy[2 * nChars] = dx;
+ dxdy[2 * nChars + 1] = dy;
+ ++nChars;
+ }
+ }
+ p += n;
+ len -= n;
+ }
-void PSOutputDev::beginTextObject(GfxState *state) {
+ if (nChars > 0) {
+ writePSString(s2->toStr());
+ writePS("\n[");
+ for (i = 0; i < 2 * nChars; ++i) {
+ if (i > 0) {
+ writePS("\n");
+ }
+ writePSFmt("{0:.6g}", dxdy[i]);
+ }
+ writePS("] Tj\n");
+ }
+ gfree(dxdy);
+ delete s2;
+
+ if (state->getRender() & 4) {
+ haveTextClip = true;
+ }
}
-void PSOutputDev::endTextObject(GfxState *state) {
- if (haveTextClip) {
- writePS("Tclip\n");
- haveTextClip = false;
- }
+void PSOutputDev::beginTextObject(GfxState *state) { }
+
+void PSOutputDev::endTextObject(GfxState *state)
+{
+ if (haveTextClip) {
+ writePS("Tclip\n");
+ haveTextClip = false;
+ }
}
-void PSOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str,
- int width, int height, bool invert,
- bool interpolate, bool inlineImg) {
- int len;
+void PSOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str, int width, int height, bool invert, bool interpolate, bool inlineImg)
+{
+ int len;
- len = height * ((width + 7) / 8);
- switch (level) {
+ len = height * ((width + 7) / 8);
+ switch (level) {
case psLevel1:
case psLevel1Sep:
- doImageL1(ref, nullptr, invert, inlineImg, str, width, height, len,
- nullptr, nullptr, 0, 0, false);
- break;
+ doImageL1(ref, nullptr, invert, inlineImg, str, width, height, len, nullptr, nullptr, 0, 0, false);
+ break;
case psLevel2:
case psLevel2Sep:
- doImageL2(state, ref, nullptr, invert, inlineImg, str, width, height, len,
- nullptr, nullptr, 0, 0, false);
- break;
+ doImageL2(state, ref, nullptr, invert, inlineImg, str, width, height, len, nullptr, nullptr, 0, 0, false);
+ break;
case psLevel3:
case psLevel3Sep:
- doImageL3(state, ref, nullptr, invert, inlineImg, str, width, height, len,
- nullptr, nullptr, 0, 0, false);
- break;
- }
+ doImageL3(state, ref, nullptr, invert, inlineImg, str, width, height, len, nullptr, nullptr, 0, 0, false);
+ break;
+ }
}
-void PSOutputDev::setSoftMaskFromImageMask(GfxState *state, Object *ref, Stream *str,
- int width, int height, bool invert,
- bool inlineImg, double *baseMatrix) {
- if (level != psLevel1 && level != psLevel1Sep) {
- maskToClippingPath(str, width, height, invert);
- }
+void PSOutputDev::setSoftMaskFromImageMask(GfxState *state, Object *ref, Stream *str, int width, int height, bool invert, bool inlineImg, double *baseMatrix)
+{
+ if (level != psLevel1 && level != psLevel1Sep) {
+ maskToClippingPath(str, width, height, invert);
+ }
}
-void PSOutputDev::unsetSoftMaskFromImageMask(GfxState * state, double *baseMatrix) {
- if (level != psLevel1 && level != psLevel1Sep) {
- writePS("pdfImClipEnd\n");
- }
+void PSOutputDev::unsetSoftMaskFromImageMask(GfxState *state, double *baseMatrix)
+{
+ if (level != psLevel1 && level != psLevel1Sep) {
+ writePS("pdfImClipEnd\n");
+ }
}
-void PSOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
- int width, int height, GfxImageColorMap *colorMap,
- bool interpolate, const int *maskColors, bool inlineImg) {
- int len;
-
- len = height * ((width * colorMap->getNumPixelComps() *
- colorMap->getBits() + 7) / 8);
- switch (level) {
- case psLevel1:
- doImageL1(ref, colorMap, false, inlineImg, str,
- width, height, len, maskColors, nullptr, 0, 0, false);
- break;
- case psLevel1Sep:
- //~ handle indexed, separation, ... color spaces
- doImageL1Sep(ref, colorMap, false, inlineImg, str,
- width, height, len, maskColors, nullptr, 0, 0, false);
- break;
- case psLevel2:
- case psLevel2Sep:
- doImageL2(state, ref, colorMap, false, inlineImg, str,
- width, height, len, maskColors, nullptr, 0, 0, false);
- break;
- case psLevel3:
- case psLevel3Sep:
- doImageL3(state, ref, colorMap, false, inlineImg, str,
- width, height, len, maskColors, nullptr, 0, 0, false);
- break;
- }
- t3Cacheable = false;
-}
+void PSOutputDev::drawImage(GfxState *state, Object *ref, Stream *str, int width, int height, GfxImageColorMap *colorMap, bool interpolate, const int *maskColors, bool inlineImg)
+{
+ int len;
-void PSOutputDev::drawMaskedImage(GfxState *state, Object *ref, Stream *str,
- int width, int height,
- GfxImageColorMap *colorMap,
- bool interpolate,
- Stream *maskStr,
- int maskWidth, int maskHeight,
- bool maskInvert, bool maskInterpolate) {
- int len;
-
- len = height * ((width * colorMap->getNumPixelComps() *
- colorMap->getBits() + 7) / 8);
- switch (level) {
- case psLevel1:
- doImageL1(ref, colorMap, false, false, str, width, height, len,
- nullptr, maskStr, maskWidth, maskHeight, maskInvert);
- break;
- case psLevel1Sep:
- //~ handle indexed, separation, ... color spaces
- doImageL1Sep(ref, colorMap, false, false, str, width, height, len,
- nullptr, maskStr, maskWidth, maskHeight, maskInvert);
- break;
- case psLevel2:
- case psLevel2Sep:
- doImageL2(state, ref, colorMap, false, false, str, width, height, len,
- nullptr, maskStr, maskWidth, maskHeight, maskInvert);
- break;
- case psLevel3:
- case psLevel3Sep:
- doImageL3(state, ref, colorMap, false, false, str, width, height, len,
- nullptr, maskStr, maskWidth, maskHeight, maskInvert);
- break;
- }
- t3Cacheable = false;
+ len = height * ((width * colorMap->getNumPixelComps() * colorMap->getBits() + 7) / 8);
+ switch (level) {
+ case psLevel1:
+ doImageL1(ref, colorMap, false, inlineImg, str, width, height, len, maskColors, nullptr, 0, 0, false);
+ break;
+ case psLevel1Sep:
+ //~ handle indexed, separation, ... color spaces
+ doImageL1Sep(ref, colorMap, false, inlineImg, str, width, height, len, maskColors, nullptr, 0, 0, false);
+ break;
+ case psLevel2:
+ case psLevel2Sep:
+ doImageL2(state, ref, colorMap, false, inlineImg, str, width, height, len, maskColors, nullptr, 0, 0, false);
+ break;
+ case psLevel3:
+ case psLevel3Sep:
+ doImageL3(state, ref, colorMap, false, inlineImg, str, width, height, len, maskColors, nullptr, 0, 0, false);
+ break;
+ }
+ t3Cacheable = false;
}
-void PSOutputDev::doImageL1(Object *ref, GfxImageColorMap *colorMap,
- bool invert, bool inlineImg,
- Stream *str, int width, int height, int len,
- const int *maskColors, Stream *maskStr,
- int maskWidth, int maskHeight, bool maskInvert) {
- ImageStream *imgStr;
- unsigned char pixBuf[gfxColorMaxComps];
- GfxGray gray;
- int col, x, y, c, i;
- char hexBuf[32*2 + 2]; // 32 values X 2 chars/value + line ending + null
- unsigned char digit, grayValue;
-
- // explicit masking
- if (maskStr && !(maskColors && colorMap)) {
- maskToClippingPath(maskStr, maskWidth, maskHeight, maskInvert);
- }
-
- if ((inType3Char || preloadImagesForms) && !colorMap) {
- if (inlineImg) {
- // create an array
- str = new FixedLengthEncoder(str, len);
- str = new ASCIIHexEncoder(str);
- str->reset();
- col = 0;
- writePS("[<");
- do {
- do {
- c = str->getChar();
- } while (c == '\n' || c == '\r');
- if (c == '>' || c == EOF) {
- break;
- }
- writePSChar(c);
- ++col;
- // each line is: "<...data...><eol>"
- // so max data length = 255 - 4 = 251
- // but make it 240 just to be safe
- // chunks are 2 bytes each, so we need to stop on an even col number
- if (col == 240) {
- writePS(">\n<");
- col = 0;
- }
- } while (c != '>' && c != EOF);
- writePS(">]\n");
- writePS("0\n");
- str->close();
- delete str;
- } else {
- // make sure the image is setup, it sometimes is not like on bug #17645
- setupImage(ref->getRef(), str, false);
- // set up to use the array already created by setupImages()
- writePSFmt("ImData_{0:d}_{1:d} 0 0\n", ref->getRefNum(), ref->getRefGen());
- }
- }
-
- // image/imagemask command
- if ((inType3Char || preloadImagesForms) && !colorMap) {
- writePSFmt("{0:d} {1:d} {2:s} [{3:d} 0 0 {4:d} 0 {5:d}] pdfImM1a\n",
- width, height, invert ? "true" : "false",
- width, -height, height);
- } else if (colorMap) {
- writePSFmt("{0:d} {1:d} 8 [{2:d} 0 0 {3:d} 0 {4:d}] pdfIm1{5:s}\n",
- width, height,
- width, -height, height,
- useBinary ? "Bin" : "");
- } else {
- writePSFmt("{0:d} {1:d} {2:s} [{3:d} 0 0 {4:d} 0 {5:d}] pdfImM1{6:s}\n",
- width, height, invert ? "true" : "false",
- width, -height, height,
- useBinary ? "Bin" : "");
- }
-
- // image data
- if (!((inType3Char || preloadImagesForms) && !colorMap)) {
+void PSOutputDev::drawMaskedImage(GfxState *state, Object *ref, Stream *str, int width, int height, GfxImageColorMap *colorMap, bool interpolate, Stream *maskStr, int maskWidth, int maskHeight, bool maskInvert, bool maskInterpolate)
+{
+ int len;
- if (colorMap) {
+ len = height * ((width * colorMap->getNumPixelComps() * colorMap->getBits() + 7) / 8);
+ switch (level) {
+ case psLevel1:
+ doImageL1(ref, colorMap, false, false, str, width, height, len, nullptr, maskStr, maskWidth, maskHeight, maskInvert);
+ break;
+ case psLevel1Sep:
+ //~ handle indexed, separation, ... color spaces
+ doImageL1Sep(ref, colorMap, false, false, str, width, height, len, nullptr, maskStr, maskWidth, maskHeight, maskInvert);
+ break;
+ case psLevel2:
+ case psLevel2Sep:
+ doImageL2(state, ref, colorMap, false, false, str, width, height, len, nullptr, maskStr, maskWidth, maskHeight, maskInvert);
+ break;
+ case psLevel3:
+ case psLevel3Sep:
+ doImageL3(state, ref, colorMap, false, false, str, width, height, len, nullptr, maskStr, maskWidth, maskHeight, maskInvert);
+ break;
+ }
+ t3Cacheable = false;
+}
- // set up to process the data stream
- imgStr = new ImageStream(str, width, colorMap->getNumPixelComps(),
- colorMap->getBits());
- imgStr->reset();
-
- // process the data stream
- i = 0;
- for (y = 0; y < height; ++y) {
-
- // write the line
- for (x = 0; x < width; ++x) {
- imgStr->getPixel(pixBuf);
- colorMap->getGray(pixBuf, &gray);
- grayValue = colToByte(gray);
- if (useBinary) {
- hexBuf[i++] = grayValue;
- } else {
- digit = grayValue / 16;
- hexBuf[i++] = digit + ((digit >= 10)? 'a' - 10: '0');
- digit = grayValue % 16;
- hexBuf[i++] = digit + ((digit >= 10)? 'a' - 10: '0');
- }
- if (i >= 64) {
- if (!useBinary) {
- hexBuf[i++] = '\n';
- }
- writePSBuf(hexBuf, i);
- i = 0;
- }
- }
- }
- if (i != 0) {
- if (!useBinary) {
- hexBuf[i++] = '\n';
- }
- writePSBuf(hexBuf, i);
- }
- str->close();
- delete imgStr;
-
- // imagemask
+void PSOutputDev::doImageL1(Object *ref, GfxImageColorMap *colorMap, bool invert, bool inlineImg, Stream *str, int width, int height, int len, const int *maskColors, Stream *maskStr, int maskWidth, int maskHeight, bool maskInvert)
+{
+ ImageStream *imgStr;
+ unsigned char pixBuf[gfxColorMaxComps];
+ GfxGray gray;
+ int col, x, y, c, i;
+ char hexBuf[32 * 2 + 2]; // 32 values X 2 chars/value + line ending + null
+ unsigned char digit, grayValue;
+
+ // explicit masking
+ if (maskStr && !(maskColors && colorMap)) {
+ maskToClippingPath(maskStr, maskWidth, maskHeight, maskInvert);
+ }
+
+ if ((inType3Char || preloadImagesForms) && !colorMap) {
+ if (inlineImg) {
+ // create an array
+ str = new FixedLengthEncoder(str, len);
+ str = new ASCIIHexEncoder(str);
+ str->reset();
+ col = 0;
+ writePS("[<");
+ do {
+ do {
+ c = str->getChar();
+ } while (c == '\n' || c == '\r');
+ if (c == '>' || c == EOF) {
+ break;
+ }
+ writePSChar(c);
+ ++col;
+ // each line is: "<...data...><eol>"
+ // so max data length = 255 - 4 = 251
+ // but make it 240 just to be safe
+ // chunks are 2 bytes each, so we need to stop on an even col number
+ if (col == 240) {
+ writePS(">\n<");
+ col = 0;
+ }
+ } while (c != '>' && c != EOF);
+ writePS(">]\n");
+ writePS("0\n");
+ str->close();
+ delete str;
+ } else {
+ // make sure the image is setup, it sometimes is not like on bug #17645
+ setupImage(ref->getRef(), str, false);
+ // set up to use the array already created by setupImages()
+ writePSFmt("ImData_{0:d}_{1:d} 0 0\n", ref->getRefNum(), ref->getRefGen());
+ }
+ }
+
+ // image/imagemask command
+ if ((inType3Char || preloadImagesForms) && !colorMap) {
+ writePSFmt("{0:d} {1:d} {2:s} [{3:d} 0 0 {4:d} 0 {5:d}] pdfImM1a\n", width, height, invert ? "true" : "false", width, -height, height);
+ } else if (colorMap) {
+ writePSFmt("{0:d} {1:d} 8 [{2:d} 0 0 {3:d} 0 {4:d}] pdfIm1{5:s}\n", width, height, width, -height, height, useBinary ? "Bin" : "");
} else {
- str->reset();
- i = 0;
- for (y = 0; y < height; ++y) {
- for (x = 0; x < width; x += 8) {
- grayValue = str->getChar();
- if (useBinary) {
- hexBuf[i++] = grayValue;
- } else {
- digit = grayValue / 16;
- hexBuf[i++] = digit + ((digit >= 10)? 'a' - 10: '0');
- digit = grayValue % 16;
- hexBuf[i++] = digit + ((digit >= 10)? 'a' - 10: '0');
- }
- if (i >= 64) {
- if (!useBinary) {
- hexBuf[i++] = '\n';
- }
- writePSBuf(hexBuf, i);
- i = 0;
- }
- }
- }
- if (i != 0) {
- if (!useBinary) {
- hexBuf[i++] = '\n';
- }
- writePSBuf(hexBuf, i);
- }
- str->close();
- }
- }
-
- if (maskStr && !(maskColors && colorMap)) {
- writePS("pdfImClipEnd\n");
- }
-}
+ writePSFmt("{0:d} {1:d} {2:s} [{3:d} 0 0 {4:d} 0 {5:d}] pdfImM1{6:s}\n", width, height, invert ? "true" : "false", width, -height, height, useBinary ? "Bin" : "");
+ }
+
+ // image data
+ if (!((inType3Char || preloadImagesForms) && !colorMap)) {
+
+ if (colorMap) {
+
+ // set up to process the data stream
+ imgStr = new ImageStream(str, width, colorMap->getNumPixelComps(), colorMap->getBits());
+ imgStr->reset();
+
+ // process the data stream
+ i = 0;
+ for (y = 0; y < height; ++y) {
+
+ // write the line
+ for (x = 0; x < width; ++x) {
+ imgStr->getPixel(pixBuf);
+ colorMap->getGray(pixBuf, &gray);
+ grayValue = colToByte(gray);
+ if (useBinary) {
+ hexBuf[i++] = grayValue;
+ } else {
+ digit = grayValue / 16;
+ hexBuf[i++] = digit + ((digit >= 10) ? 'a' - 10 : '0');
+ digit = grayValue % 16;
+ hexBuf[i++] = digit + ((digit >= 10) ? 'a' - 10 : '0');
+ }
+ if (i >= 64) {
+ if (!useBinary) {
+ hexBuf[i++] = '\n';
+ }
+ writePSBuf(hexBuf, i);
+ i = 0;
+ }
+ }
+ }
+ if (i != 0) {
+ if (!useBinary) {
+ hexBuf[i++] = '\n';
+ }
+ writePSBuf(hexBuf, i);
+ }
+ str->close();
+ delete imgStr;
+
+ // imagemask
+ } else {
+ str->reset();
+ i = 0;
+ for (y = 0; y < height; ++y) {
+ for (x = 0; x < width; x += 8) {
+ grayValue = str->getChar();
+ if (useBinary) {
+ hexBuf[i++] = grayValue;
+ } else {
+ digit = grayValue / 16;
+ hexBuf[i++] = digit + ((digit >= 10) ? 'a' - 10 : '0');
+ digit = grayValue % 16;
+ hexBuf[i++] = digit + ((digit >= 10) ? 'a' - 10 : '0');
+ }
+ if (i >= 64) {
+ if (!useBinary) {
+ hexBuf[i++] = '\n';
+ }
+ writePSBuf(hexBuf, i);
+ i = 0;
+ }
+ }
+ }
+ if (i != 0) {
+ if (!useBinary) {
+ hexBuf[i++] = '\n';
+ }
+ writePSBuf(hexBuf, i);
+ }
+ str->close();
+ }
+ }
-void PSOutputDev::doImageL1Sep(Object *ref, GfxImageColorMap *colorMap,
- bool invert, bool inlineImg,
- Stream *str, int width, int height, int len,
- const int *maskColors, Stream *maskStr,
- int maskWidth, int maskHeight, bool maskInvert) {
- ImageStream *imgStr;
- unsigned char *lineBuf;
- unsigned char pixBuf[gfxColorMaxComps];
- GfxCMYK cmyk;
- int x, y, i, comp;
- bool checkProcessColor;
- char hexBuf[32*2 + 2]; // 32 values X 2 chars/value + line ending + null
- unsigned char digit;
- bool isGray;
-
- // explicit masking
- if (maskStr && !(maskColors && colorMap)) {
- maskToClippingPath(maskStr, maskWidth, maskHeight, maskInvert);
- }
-
- // allocate a line buffer
- lineBuf = (unsigned char *)gmallocn(width, 4);
-
- // scan for all gray
- if (getOptimizeColorSpace()) {
- ImageStream *imgCheckStr;
- imgCheckStr = new ImageStream(str, width, colorMap->getNumPixelComps(),
- colorMap->getBits());
- imgCheckStr->reset();
- isGray = true;
- for (y = 0; y < height; ++y) {
- for (x = 0; x < width; ++x) {
- imgCheckStr->getPixel(pixBuf);
- colorMap->getCMYK(pixBuf, &cmyk);
- if (colToByte(cmyk.c) != colToByte(cmyk.m) || colToByte(cmyk.c) != colToByte(cmyk.y)) {
- isGray = false;
- y = height; // end outer loop
- break;
- }
- }
- }
- imgCheckStr->close();
- delete imgCheckStr;
- } else {
- isGray = false;
- }
-
- // set up to process the data stream
- imgStr = new ImageStream(str, width, colorMap->getNumPixelComps(),
- colorMap->getBits());
- imgStr->reset();
-
- // width, height, matrix, bits per component
- writePSFmt("{0:d} {1:d} 8 [{2:d} 0 0 {3:d} 0 {4:d}] pdfIm1{5:s}{6:s}\n",
- width, height,
- width, -height, height,
- isGray ? "" : "Sep",
- useBinary ? "Bin" : "");
-
- // process the data stream
- checkProcessColor = true;
- i = 0;
-
- if (isGray) {
- int g;
- for (y = 0; y < height; ++y) {
-
- // read the line
- if (checkProcessColor) {
- checkProcessColor = ((psProcessBlack & processColors) == 0);
- }
- for (x = 0; x < width; ++x) {
- imgStr->getPixel(pixBuf);
- colorMap->getCMYK(pixBuf, &cmyk);
- g = colToByte(cmyk.c) + colToByte(cmyk.k);
- if (checkProcessColor && g > 0) {
- processColors |= psProcessBlack;
- }
- g = 255 - g;
- if (g < 0) g = 0;
- if (useBinary) {
- hexBuf[i++] = g;
- } else {
- digit = g / 16;
- hexBuf[i++] = digit + ((digit >= 10)? 'a'-10: '0');
- digit = g % 16;
- hexBuf[i++] = digit + ((digit >= 10)? 'a'-10: '0');
- }
- if (i >= 64) {
- if (!useBinary) {
- hexBuf[i++] = '\n';
- }
- writePSBuf(hexBuf, i);
- i = 0;
- }
- }
- }
- } else {
- for (y = 0; y < height; ++y) {
-
- // read the line
- if (checkProcessColor) {
- checkProcessColor = (((psProcessCyan | psProcessMagenta | psProcessYellow | psProcessBlack) & ~processColors) != 0);
- }
- if (checkProcessColor) {
- for (x = 0; x < width; ++x) {
- imgStr->getPixel(pixBuf);
- colorMap->getCMYK(pixBuf, &cmyk);
- lineBuf[4*x+0] = colToByte(cmyk.c);
- lineBuf[4*x+1] = colToByte(cmyk.m);
- lineBuf[4*x+2] = colToByte(cmyk.y);
- lineBuf[4*x+3] = colToByte(cmyk.k);
- addProcessColor(colToDbl(cmyk.c), colToDbl(cmyk.m),
- colToDbl(cmyk.y), colToDbl(cmyk.k));
- }
- } else {
- for (x = 0; x < width; ++x) {
- imgStr->getPixel(pixBuf);
- colorMap->getCMYK(pixBuf, &cmyk);
- lineBuf[4*x+0] = colToByte(cmyk.c);
- lineBuf[4*x+1] = colToByte(cmyk.m);
- lineBuf[4*x+2] = colToByte(cmyk.y);
- lineBuf[4*x+3] = colToByte(cmyk.k);
- }
- }
-
- // write one line of each color component
- if (useBinary) {
- for (comp = 0; comp < 4; ++comp) {
- for (x = 0; x < width; ++x) {
- hexBuf[i++] = lineBuf[4*x + comp];
- if (i >= 64) {
- writePSBuf(hexBuf, i);
- i = 0;
- }
- }
- }
- } else {
- for (comp = 0; comp < 4; ++comp) {
- for (x = 0; x < width; ++x) {
- digit = lineBuf[4*x + comp] / 16;
- hexBuf[i++] = digit + ((digit >= 10)? 'a'-10: '0');
- digit = lineBuf[4*x + comp] % 16;
- hexBuf[i++] = digit + ((digit >= 10)? 'a'-10: '0');
- if (i >= 64) {
- hexBuf[i++] = '\n';
- writePSBuf(hexBuf, i);
- i = 0;
- }
- }
- }
- }
- }
- }
-
- if (i != 0) {
- if (!useBinary) {
- hexBuf[i++] = '\n';
- }
- writePSBuf(hexBuf, i);
- }
-
- str->close();
- delete imgStr;
- gfree(lineBuf);
-
- if (maskStr && !(maskColors && colorMap)) {
- writePS("pdfImClipEnd\n");
- }
+ if (maskStr && !(maskColors && colorMap)) {
+ writePS("pdfImClipEnd\n");
+ }
}
-void PSOutputDev::maskToClippingPath(Stream *maskStr, int maskWidth, int maskHeight, bool maskInvert) {
- ImageStream *imgStr;
- unsigned char *line;
- PSOutImgClipRect *rects0, *rects1, *rectsTmp, *rectsOut;
- int rects0Len, rects1Len, rectsSize, rectsOutLen, rectsOutSize;
- bool emitRect, addRect, extendRect;
- int i, x0, x1, y, maskXor;
-
- imgStr = new ImageStream(maskStr, maskWidth, 1, 1);
- imgStr->reset();
- rects0Len = rects1Len = rectsOutLen = 0;
- rectsSize = rectsOutSize = 64;
- rects0 = (PSOutImgClipRect *)gmallocn(rectsSize, sizeof(PSOutImgClipRect));
- rects1 = (PSOutImgClipRect *)gmallocn(rectsSize, sizeof(PSOutImgClipRect));
- rectsOut = (PSOutImgClipRect *)gmallocn(rectsOutSize, sizeof(PSOutImgClipRect));
- maskXor = maskInvert ? 1 : 0;
- for (y = 0; y < maskHeight; ++y) {
- if (!(line = imgStr->getLine())) {
- break;
+void PSOutputDev::doImageL1Sep(Object *ref, GfxImageColorMap *colorMap, bool invert, bool inlineImg, Stream *str, int width, int height, int len, const int *maskColors, Stream *maskStr, int maskWidth, int maskHeight, bool maskInvert)
+{
+ ImageStream *imgStr;
+ unsigned char *lineBuf;
+ unsigned char pixBuf[gfxColorMaxComps];
+ GfxCMYK cmyk;
+ int x, y, i, comp;
+ bool checkProcessColor;
+ char hexBuf[32 * 2 + 2]; // 32 values X 2 chars/value + line ending + null
+ unsigned char digit;
+ bool isGray;
+
+ // explicit masking
+ if (maskStr && !(maskColors && colorMap)) {
+ maskToClippingPath(maskStr, maskWidth, maskHeight, maskInvert);
+ }
+
+ // allocate a line buffer
+ lineBuf = (unsigned char *)gmallocn(width, 4);
+
+ // scan for all gray
+ if (getOptimizeColorSpace()) {
+ ImageStream *imgCheckStr;
+ imgCheckStr = new ImageStream(str, width, colorMap->getNumPixelComps(), colorMap->getBits());
+ imgCheckStr->reset();
+ isGray = true;
+ for (y = 0; y < height; ++y) {
+ for (x = 0; x < width; ++x) {
+ imgCheckStr->getPixel(pixBuf);
+ colorMap->getCMYK(pixBuf, &cmyk);
+ if (colToByte(cmyk.c) != colToByte(cmyk.m) || colToByte(cmyk.c) != colToByte(cmyk.y)) {
+ isGray = false;
+ y = height; // end outer loop
+ break;
+ }
+ }
+ }
+ imgCheckStr->close();
+ delete imgCheckStr;
+ } else {
+ isGray = false;
}
+
+ // set up to process the data stream
+ imgStr = new ImageStream(str, width, colorMap->getNumPixelComps(), colorMap->getBits());
+ imgStr->reset();
+
+ // width, height, matrix, bits per component
+ writePSFmt("{0:d} {1:d} 8 [{2:d} 0 0 {3:d} 0 {4:d}] pdfIm1{5:s}{6:s}\n", width, height, width, -height, height, isGray ? "" : "Sep", useBinary ? "Bin" : "");
+
+ // process the data stream
+ checkProcessColor = true;
i = 0;
- rects1Len = 0;
- for (x0 = 0; x0 < maskWidth && (line[x0] ^ maskXor); ++x0) ;
- for (x1 = x0; x1 < maskWidth && !(line[x1] ^ maskXor); ++x1) ;
- while (x0 < maskWidth || i < rects0Len) {
- emitRect = addRect = extendRect = false;
- if (x0 >= maskWidth) {
- emitRect = true;
- } else if (i >= rects0Len) {
- addRect = true;
- } else if (rects0[i].x0 < x0) {
- emitRect = true;
- } else if (x0 < rects0[i].x0) {
- addRect = true;
- } else if (rects0[i].x1 == x1) {
- extendRect = true;
- } else {
- emitRect = addRect = true;
- }
- if (emitRect) {
- if (rectsOutLen == rectsOutSize) {
- rectsOutSize *= 2;
- rectsOut = (PSOutImgClipRect *)greallocn(rectsOut, rectsOutSize, sizeof(PSOutImgClipRect));
+
+ if (isGray) {
+ int g;
+ for (y = 0; y < height; ++y) {
+
+ // read the line
+ if (checkProcessColor) {
+ checkProcessColor = ((psProcessBlack & processColors) == 0);
+ }
+ for (x = 0; x < width; ++x) {
+ imgStr->getPixel(pixBuf);
+ colorMap->getCMYK(pixBuf, &cmyk);
+ g = colToByte(cmyk.c) + colToByte(cmyk.k);
+ if (checkProcessColor && g > 0) {
+ processColors |= psProcessBlack;
+ }
+ g = 255 - g;
+ if (g < 0)
+ g = 0;
+ if (useBinary) {
+ hexBuf[i++] = g;
+ } else {
+ digit = g / 16;
+ hexBuf[i++] = digit + ((digit >= 10) ? 'a' - 10 : '0');
+ digit = g % 16;
+ hexBuf[i++] = digit + ((digit >= 10) ? 'a' - 10 : '0');
+ }
+ if (i >= 64) {
+ if (!useBinary) {
+ hexBuf[i++] = '\n';
+ }
+ writePSBuf(hexBuf, i);
+ i = 0;
+ }
+ }
}
- rectsOut[rectsOutLen].x0 = rects0[i].x0;
- rectsOut[rectsOutLen].x1 = rects0[i].x1;
- rectsOut[rectsOutLen].y0 = maskHeight - y - 1;
- rectsOut[rectsOutLen].y1 = maskHeight - rects0[i].y0 - 1;
- ++rectsOutLen;
- ++i;
- }
- if (addRect || extendRect) {
- if (rects1Len == rectsSize) {
- rectsSize *= 2;
- rects0 = (PSOutImgClipRect *)greallocn(rects0, rectsSize, sizeof(PSOutImgClipRect));
- rects1 = (PSOutImgClipRect *)greallocn(rects1, rectsSize, sizeof(PSOutImgClipRect));
- }
- rects1[rects1Len].x0 = x0;
- rects1[rects1Len].x1 = x1;
- if (addRect) {
- rects1[rects1Len].y0 = y;
- }
- if (extendRect) {
- rects1[rects1Len].y0 = rects0[i].y0;
- ++i;
- }
- ++rects1Len;
- for (x0 = x1; x0 < maskWidth && (line[x0] ^ maskXor); ++x0) ;
- for (x1 = x0; x1 < maskWidth && !(line[x1] ^ maskXor); ++x1) ;
- }
- }
- rectsTmp = rects0;
- rects0 = rects1;
- rects1 = rectsTmp;
- i = rects0Len;
- rects0Len = rects1Len;
- rects1Len = i;
- }
- for (i = 0; i < rects0Len; ++i) {
- if (rectsOutLen == rectsOutSize) {
- rectsOutSize *= 2;
- rectsOut = (PSOutImgClipRect *)greallocn(rectsOut, rectsOutSize, sizeof(PSOutImgClipRect));
- }
- rectsOut[rectsOutLen].x0 = rects0[i].x0;
- rectsOut[rectsOutLen].x1 = rects0[i].x1;
- rectsOut[rectsOutLen].y0 = maskHeight - y - 1;
- rectsOut[rectsOutLen].y1 = maskHeight - rects0[i].y0 - 1;
- ++rectsOutLen;
- }
- if (rectsOutLen < 65536/4) {
- writePSFmt("{0:d} array 0\n", rectsOutLen * 4);
- for (i = 0; i < rectsOutLen; ++i) {
- writePSFmt("[{0:d} {1:d} {2:d} {3:d}] pr\n",
- rectsOut[i].x0, rectsOut[i].y0,
- rectsOut[i].x1 - rectsOut[i].x0,
- rectsOut[i].y1 - rectsOut[i].y0);
- }
- writePSFmt("pop {0:d} {1:d} pdfImClip\n", maskWidth, maskHeight);
- } else {
- // would be over the limit of array size.
- // make each rectangle path and clip.
- writePS("gsave newpath\n");
- for (i = 0; i < rectsOutLen; ++i) {
- writePSFmt("{0:.6g} {1:.6g} {2:.6g} {3:.6g} re\n",
- ((double)rectsOut[i].x0)/maskWidth,
- ((double)rectsOut[i].y0)/maskHeight,
- ((double)(rectsOut[i].x1 - rectsOut[i].x0))/maskWidth,
- ((double)(rectsOut[i].y1 - rectsOut[i].y0))/maskHeight);
- }
- writePS("clip\n");
- }
- gfree(rectsOut);
- gfree(rects0);
- gfree(rects1);
- delete imgStr;
- maskStr->close();
+ } else {
+ for (y = 0; y < height; ++y) {
+
+ // read the line
+ if (checkProcessColor) {
+ checkProcessColor = (((psProcessCyan | psProcessMagenta | psProcessYellow | psProcessBlack) & ~processColors) != 0);
+ }
+ if (checkProcessColor) {
+ for (x = 0; x < width; ++x) {
+ imgStr->getPixel(pixBuf);
+ colorMap->getCMYK(pixBuf, &cmyk);
+ lineBuf[4 * x + 0] = colToByte(cmyk.c);
+ lineBuf[4 * x + 1] = colToByte(cmyk.m);
+ lineBuf[4 * x + 2] = colToByte(cmyk.y);
+ lineBuf[4 * x + 3] = colToByte(cmyk.k);
+ addProcessColor(colToDbl(cmyk.c), colToDbl(cmyk.m), colToDbl(cmyk.y), colToDbl(cmyk.k));
+ }
+ } else {
+ for (x = 0; x < width; ++x) {
+ imgStr->getPixel(pixBuf);
+ colorMap->getCMYK(pixBuf, &cmyk);
+ lineBuf[4 * x + 0] = colToByte(cmyk.c);
+ lineBuf[4 * x + 1] = colToByte(cmyk.m);
+ lineBuf[4 * x + 2] = colToByte(cmyk.y);
+ lineBuf[4 * x + 3] = colToByte(cmyk.k);
+ }
+ }
+
+ // write one line of each color component
+ if (useBinary) {
+ for (comp = 0; comp < 4; ++comp) {
+ for (x = 0; x < width; ++x) {
+ hexBuf[i++] = lineBuf[4 * x + comp];
+ if (i >= 64) {
+ writePSBuf(hexBuf, i);
+ i = 0;
+ }
+ }
+ }
+ } else {
+ for (comp = 0; comp < 4; ++comp) {
+ for (x = 0; x < width; ++x) {
+ digit = lineBuf[4 * x + comp] / 16;
+ hexBuf[i++] = digit + ((digit >= 10) ? 'a' - 10 : '0');
+ digit = lineBuf[4 * x + comp] % 16;
+ hexBuf[i++] = digit + ((digit >= 10) ? 'a' - 10 : '0');
+ if (i >= 64) {
+ hexBuf[i++] = '\n';
+ writePSBuf(hexBuf, i);
+ i = 0;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (i != 0) {
+ if (!useBinary) {
+ hexBuf[i++] = '\n';
+ }
+ writePSBuf(hexBuf, i);
+ }
+
+ str->close();
+ delete imgStr;
+ gfree(lineBuf);
+
+ if (maskStr && !(maskColors && colorMap)) {
+ writePS("pdfImClipEnd\n");
+ }
}
-void PSOutputDev::doImageL2(GfxState* state, Object *ref, GfxImageColorMap *colorMap,
- bool invert, bool inlineImg,
- Stream *str, int width, int height, int len,
- const int *maskColors, Stream *maskStr,
- int maskWidth, int maskHeight, bool maskInvert) {
- Stream *str2;
- ImageStream *imgStr;
- unsigned char *line;
- PSOutImgClipRect *rects0, *rects1, *rectsTmp, *rectsOut;
- int rects0Len, rects1Len, rectsSize, rectsOutLen, rectsOutSize;
- bool emitRect, addRect, extendRect;
- GooString *s;
- int n, numComps;
- bool useLZW, useRLE, useASCII, useCompressed;
- GfxSeparationColorSpace *sepCS;
- GfxColor color;
- GfxCMYK cmyk;
- int c;
- int col, i, j, x0, x1, y;
- char dataBuf[4096];
-
- rectsOutLen = 0;
-
- // color key masking
- if (maskColors && colorMap && !inlineImg) {
- // can't read the stream twice for inline images -- but masking
- // isn't allowed with inline images anyway
- numComps = colorMap->getNumPixelComps();
- imgStr = new ImageStream(str, width, numComps, colorMap->getBits());
+void PSOutputDev::maskToClippingPath(Stream *maskStr, int maskWidth, int maskHeight, bool maskInvert)
+{
+ ImageStream *imgStr;
+ unsigned char *line;
+ PSOutImgClipRect *rects0, *rects1, *rectsTmp, *rectsOut;
+ int rects0Len, rects1Len, rectsSize, rectsOutLen, rectsOutSize;
+ bool emitRect, addRect, extendRect;
+ int i, x0, x1, y, maskXor;
+
+ imgStr = new ImageStream(maskStr, maskWidth, 1, 1);
imgStr->reset();
- rects0Len = rects1Len = 0;
+ rects0Len = rects1Len = rectsOutLen = 0;
rectsSize = rectsOutSize = 64;
rects0 = (PSOutImgClipRect *)gmallocn(rectsSize, sizeof(PSOutImgClipRect));
rects1 = (PSOutImgClipRect *)gmallocn(rectsSize, sizeof(PSOutImgClipRect));
- rectsOut = (PSOutImgClipRect *)gmallocn(rectsOutSize,
- sizeof(PSOutImgClipRect));
- for (y = 0; y < height; ++y) {
- if (!(line = imgStr->getLine())) {
- break;
- }
- i = 0;
- rects1Len = 0;
- for (x0 = 0; x0 < width; ++x0) {
- for (j = 0; j < numComps; ++j) {
- if (line[x0*numComps+j] < maskColors[2*j] ||
- line[x0*numComps+j] > maskColors[2*j+1]) {
- break;
- }
- }
- if (j < numComps) {
- break;
- }
- }
- for (x1 = x0; x1 < width; ++x1) {
- for (j = 0; j < numComps; ++j) {
- if (line[x1*numComps+j] < maskColors[2*j] ||
- line[x1*numComps+j] > maskColors[2*j+1]) {
- break;
- }
- }
- if (j == numComps) {
- break;
- }
- }
- while (x0 < width || i < rects0Len) {
- emitRect = addRect = extendRect = false;
- if (x0 >= width) {
- emitRect = true;
- } else if (i >= rects0Len) {
- addRect = true;
- } else if (rects0[i].x0 < x0) {
- emitRect = true;
- } else if (x0 < rects0[i].x0) {
- addRect = true;
- } else if (rects0[i].x1 == x1) {
- extendRect = true;
- } else {
- emitRect = addRect = true;
- }
- if (emitRect) {
- if (rectsOutLen == rectsOutSize) {
- rectsOutSize *= 2;
- rectsOut = (PSOutImgClipRect *)greallocn(rectsOut, rectsOutSize,
- sizeof(PSOutImgClipRect));
- }
- rectsOut[rectsOutLen].x0 = rects0[i].x0;
- rectsOut[rectsOutLen].x1 = rects0[i].x1;
- rectsOut[rectsOutLen].y0 = height - y - 1;
- rectsOut[rectsOutLen].y1 = height - rects0[i].y0 - 1;
- ++rectsOutLen;
- ++i;
- }
- if (addRect || extendRect) {
- if (rects1Len == rectsSize) {
- rectsSize *= 2;
- rects0 = (PSOutImgClipRect *)greallocn(rects0, rectsSize,
- sizeof(PSOutImgClipRect));
- rects1 = (PSOutImgClipRect *)greallocn(rects1, rectsSize,
- sizeof(PSOutImgClipRect));
- }
- rects1[rects1Len].x0 = x0;
- rects1[rects1Len].x1 = x1;
- if (addRect) {
- rects1[rects1Len].y0 = y;
- }
- if (extendRect) {
- rects1[rects1Len].y0 = rects0[i].y0;
- ++i;
- }
- ++rects1Len;
- for (x0 = x1; x0 < width; ++x0) {
- for (j = 0; j < numComps; ++j) {
- if (line[x0*numComps+j] < maskColors[2*j] ||
- line[x0*numComps+j] > maskColors[2*j+1]) {
- break;
- }
- }
- if (j < numComps) {
- break;
- }
- }
- for (x1 = x0; x1 < width; ++x1) {
- for (j = 0; j < numComps; ++j) {
- if (line[x1*numComps+j] < maskColors[2*j] ||
- line[x1*numComps+j] > maskColors[2*j+1]) {
- break;
- }
- }
- if (j == numComps) {
- break;
- }
- }
- }
- }
- rectsTmp = rects0;
- rects0 = rects1;
- rects1 = rectsTmp;
- i = rects0Len;
- rects0Len = rects1Len;
- rects1Len = i;
+ rectsOut = (PSOutImgClipRect *)gmallocn(rectsOutSize, sizeof(PSOutImgClipRect));
+ maskXor = maskInvert ? 1 : 0;
+ for (y = 0; y < maskHeight; ++y) {
+ if (!(line = imgStr->getLine())) {
+ break;
+ }
+ i = 0;
+ rects1Len = 0;
+ for (x0 = 0; x0 < maskWidth && (line[x0] ^ maskXor); ++x0)
+ ;
+ for (x1 = x0; x1 < maskWidth && !(line[x1] ^ maskXor); ++x1)
+ ;
+ while (x0 < maskWidth || i < rects0Len) {
+ emitRect = addRect = extendRect = false;
+ if (x0 >= maskWidth) {
+ emitRect = true;
+ } else if (i >= rects0Len) {
+ addRect = true;
+ } else if (rects0[i].x0 < x0) {
+ emitRect = true;
+ } else if (x0 < rects0[i].x0) {
+ addRect = true;
+ } else if (rects0[i].x1 == x1) {
+ extendRect = true;
+ } else {
+ emitRect = addRect = true;
+ }
+ if (emitRect) {
+ if (rectsOutLen == rectsOutSize) {
+ rectsOutSize *= 2;
+ rectsOut = (PSOutImgClipRect *)greallocn(rectsOut, rectsOutSize, sizeof(PSOutImgClipRect));
+ }
+ rectsOut[rectsOutLen].x0 = rects0[i].x0;
+ rectsOut[rectsOutLen].x1 = rects0[i].x1;
+ rectsOut[rectsOutLen].y0 = maskHeight - y - 1;
+ rectsOut[rectsOutLen].y1 = maskHeight - rects0[i].y0 - 1;
+ ++rectsOutLen;
+ ++i;
+ }
+ if (addRect || extendRect) {
+ if (rects1Len == rectsSize) {
+ rectsSize *= 2;
+ rects0 = (PSOutImgClipRect *)greallocn(rects0, rectsSize, sizeof(PSOutImgClipRect));
+ rects1 = (PSOutImgClipRect *)greallocn(rects1, rectsSize, sizeof(PSOutImgClipRect));
+ }
+ rects1[rects1Len].x0 = x0;
+ rects1[rects1Len].x1 = x1;
+ if (addRect) {
+ rects1[rects1Len].y0 = y;
+ }
+ if (extendRect) {
+ rects1[rects1Len].y0 = rects0[i].y0;
+ ++i;
+ }
+ ++rects1Len;
+ for (x0 = x1; x0 < maskWidth && (line[x0] ^ maskXor); ++x0)
+ ;
+ for (x1 = x0; x1 < maskWidth && !(line[x1] ^ maskXor); ++x1)
+ ;
+ }
+ }
+ rectsTmp = rects0;
+ rects0 = rects1;
+ rects1 = rectsTmp;
+ i = rects0Len;
+ rects0Len = rects1Len;
+ rects1Len = i;
}
for (i = 0; i < rects0Len; ++i) {
- if (rectsOutLen == rectsOutSize) {
- rectsOutSize *= 2;
- rectsOut = (PSOutImgClipRect *)greallocn(rectsOut, rectsOutSize,
- sizeof(PSOutImgClipRect));
- }
- rectsOut[rectsOutLen].x0 = rects0[i].x0;
- rectsOut[rectsOutLen].x1 = rects0[i].x1;
- rectsOut[rectsOutLen].y0 = height - y - 1;
- rectsOut[rectsOutLen].y1 = height - rects0[i].y0 - 1;
- ++rectsOutLen;
- }
- if (rectsOutLen < 65536/4) {
- writePSFmt("{0:d} array 0\n", rectsOutLen * 4);
- for (i = 0; i < rectsOutLen; ++i) {
- writePSFmt("[{0:d} {1:d} {2:d} {3:d}] pr\n",
- rectsOut[i].x0, rectsOut[i].y0,
- rectsOut[i].x1 - rectsOut[i].x0,
- rectsOut[i].y1 - rectsOut[i].y0);
- }
- writePSFmt("pop {0:d} {1:d} pdfImClip\n", width, height);
+ if (rectsOutLen == rectsOutSize) {
+ rectsOutSize *= 2;
+ rectsOut = (PSOutImgClipRect *)greallocn(rectsOut, rectsOutSize, sizeof(PSOutImgClipRect));
+ }
+ rectsOut[rectsOutLen].x0 = rects0[i].x0;
+ rectsOut[rectsOutLen].x1 = rects0[i].x1;
+ rectsOut[rectsOutLen].y0 = maskHeight - y - 1;
+ rectsOut[rectsOutLen].y1 = maskHeight - rects0[i].y0 - 1;
+ ++rectsOutLen;
+ }
+ if (rectsOutLen < 65536 / 4) {
+ writePSFmt("{0:d} array 0\n", rectsOutLen * 4);
+ for (i = 0; i < rectsOutLen; ++i) {
+ writePSFmt("[{0:d} {1:d} {2:d} {3:d}] pr\n", rectsOut[i].x0, rectsOut[i].y0, rectsOut[i].x1 - rectsOut[i].x0, rectsOut[i].y1 - rectsOut[i].y0);
+ }
+ writePSFmt("pop {0:d} {1:d} pdfImClip\n", maskWidth, maskHeight);
} else {
- // would be over the limit of array size.
- // make each rectangle path and clip.
- writePS("gsave newpath\n");
- for (i = 0; i < rectsOutLen; ++i) {
- writePSFmt("{0:.6g} {1:.6g} {2:.6g} {3:.6g} re\n",
- ((double)rectsOut[i].x0)/width,
- ((double)rectsOut[i].y0)/height,
- ((double)(rectsOut[i].x1 - rectsOut[i].x0))/width,
- ((double)(rectsOut[i].y1 - rectsOut[i].y0))/height);
- }
- writePS("clip\n");
+ // would be over the limit of array size.
+ // make each rectangle path and clip.
+ writePS("gsave newpath\n");
+ for (i = 0; i < rectsOutLen; ++i) {
+ writePSFmt("{0:.6g} {1:.6g} {2:.6g} {3:.6g} re\n", ((double)rectsOut[i].x0) / maskWidth, ((double)rectsOut[i].y0) / maskHeight, ((double)(rectsOut[i].x1 - rectsOut[i].x0)) / maskWidth,
+ ((double)(rectsOut[i].y1 - rectsOut[i].y0)) / maskHeight);
+ }
+ writePS("clip\n");
}
gfree(rectsOut);
gfree(rects0);
gfree(rects1);
delete imgStr;
- str->close();
+ maskStr->close();
+}
- // explicit masking
- } else if (maskStr) {
- maskToClippingPath(maskStr, maskWidth, maskHeight, maskInvert);
- }
-
- // color space
- if (colorMap) {
- // Do not update the process color list for custom colors
- bool isCustomColor =
- (level == psLevel1Sep || level == psLevel2Sep || level == psLevel3Sep) &&
- colorMap->getColorSpace()->getMode() == csDeviceN;
- dumpColorSpaceL2(state, colorMap->getColorSpace(), false, !isCustomColor, false);
- writePS(" setcolorspace\n");
- }
-
- // set up the image data
- if (mode == psModeForm || inType3Char || preloadImagesForms) {
- if (inlineImg) {
- // create an array
- str2 = new FixedLengthEncoder(str, len);
- if (getEnableLZW()) {
- str2 = new LZWEncoder(str2);
- } else {
- str2 = new RunLengthEncoder(str2);
- }
- if (useASCIIHex) {
- str2 = new ASCIIHexEncoder(str2);
- } else {
- str2 = new ASCII85Encoder(str2);
- }
- str2->reset();
- col = 0;
- writePS((char *)(useASCIIHex ? "[<" : "[<~"));
- do {
- do {
- c = str2->getChar();
- } while (c == '\n' || c == '\r');
- if (c == (useASCIIHex ? '>' : '~') || c == EOF) {
- break;
- }
- if (c == 'z') {
- writePSChar(c);
- ++col;
- } else {
- writePSChar(c);
- ++col;
- for (i = 1; i <= (useASCIIHex ? 1 : 4); ++i) {
- do {
- c = str2->getChar();
- } while (c == '\n' || c == '\r');
- if (c == (useASCIIHex ? '>' : '~') || c == EOF) {
- break;
- }
- writePSChar(c);
- ++col;
- }
- }
- // each line is: "<~...data...~><eol>"
- // so max data length = 255 - 6 = 249
- // chunks are 1 or 5 bytes each, so we have to stop at 245
- // but make it 240 just to be safe
- if (col > 240) {
- writePS((char *)(useASCIIHex ? ">\n<" : "~>\n<~"));
- col = 0;
- }
- } while (c != (useASCIIHex ? '>' : '~') && c != EOF);
- writePS((char *)(useASCIIHex ? ">\n" : "~>\n"));
- // add an extra entry because the LZWDecode/RunLengthDecode filter may
- // read past the end
- writePS("<>]\n");
- writePS("0\n");
- str2->close();
- delete str2;
- } else {
- // make sure the image is setup, it sometimes is not like on bug #17645
- setupImage(ref->getRef(), str, false);
- // set up to use the array already created by setupImages()
- writePSFmt("ImData_{0:d}_{1:d} 0 0\n",ref->getRefNum(), ref->getRefGen());
- }
- }
-
- // image dictionary
- writePS("<<\n /ImageType 1\n");
-
- // width, height, matrix, bits per component
- writePSFmt(" /Width {0:d}\n", width);
- writePSFmt(" /Height {0:d}\n", height);
- writePSFmt(" /ImageMatrix [{0:d} 0 0 {1:d} 0 {2:d}]\n",
- width, -height, height);
- if (colorMap && colorMap->getColorSpace()->getMode() == csDeviceN) {
- writePS(" /BitsPerComponent 8\n");
- } else {
- writePSFmt(" /BitsPerComponent {0:d}\n",
- colorMap ? colorMap->getBits() : 1);
- }
-
- // decode
- if (colorMap) {
- writePS(" /Decode [");
- if ((level == psLevel2Sep || level == psLevel3Sep) &&
- colorMap->getColorSpace()->getMode() == csSeparation) {
- // this matches up with the code in the pdfImSep operator
- n = (1 << colorMap->getBits()) - 1;
- writePSFmt("{0:.4g} {1:.4g}", colorMap->getDecodeLow(0) * n,
- colorMap->getDecodeHigh(0) * n);
- } else if (colorMap->getColorSpace()->getMode() == csDeviceN) {
- numComps = ((GfxDeviceNColorSpace *)colorMap->getColorSpace())->
- getAlt()->getNComps();
- for (i = 0; i < numComps; ++i) {
- if (i > 0) {
- writePS(" ");
- }
- writePS("0 1");
- }
- } else {
- numComps = colorMap->getNumPixelComps();
- for (i = 0; i < numComps; ++i) {
- if (i > 0) {
- writePS(" ");
- }
- writePSFmt("{0:.4g} {1:.4g}",
- colorMap->getDecodeLow(i), colorMap->getDecodeHigh(i));
- }
- }
- writePS("]\n");
- } else {
- writePSFmt(" /Decode [{0:d} {1:d}]\n", invert ? 1 : 0, invert ? 0 : 1);
- }
-
- // data source
- if (mode == psModeForm || inType3Char || preloadImagesForms) {
- if (inlineImg) {
- writePS(" /DataSource { pdfImStr }\n");
- } else {
- writePS(" /DataSource { dup 65535 ge { pop 1 add 0 } if 2 index 2"
- " index get 1 index get exch 1 add exch }\n");
- }
- } else {
- writePS(" /DataSource currentfile\n");
- }
-
- // filters
- if ((mode == psModeForm || inType3Char || preloadImagesForms) &&
- uncompressPreloadedImages) {
- s = nullptr;
- useLZW = useRLE = false;
- useCompressed = false;
- useASCII = false;
- } else {
- s = str->getPSFilter(level < psLevel2 ? 1 : level < psLevel3 ? 2 : 3,
- " ");
- if ((colorMap && colorMap->getColorSpace()->getMode() == csDeviceN) ||
- inlineImg || !s) {
- if (getEnableLZW()) {
- useLZW = true;
- useRLE = false;
- } else {
- useRLE = true;
- useLZW = false;
- }
- useASCII = !(mode == psModeForm || inType3Char || preloadImagesForms);
- useCompressed = false;
- } else {
- useLZW = useRLE = false;
- useASCII = str->isBinary() &&
- !(mode == psModeForm || inType3Char || preloadImagesForms);
- useCompressed = true;
- }
- }
- if (useASCII) {
- writePSFmt(" /ASCII{0:s}Decode filter\n",
- useASCIIHex ? "Hex" : "85");
- }
- if (useLZW) {
- writePS(" /LZWDecode filter\n");
- } else if (useRLE) {
- writePS(" /RunLengthDecode filter\n");
- }
- if (useCompressed) {
- writePS(s->c_str());
- }
- if (s) {
- delete s;
- }
-
- if (mode == psModeForm || inType3Char || preloadImagesForms) {
-
- // end of image dictionary
- writePSFmt(">>\n{0:s}\n", colorMap ? "image" : "imagemask");
+void PSOutputDev::doImageL2(GfxState *state, Object *ref, GfxImageColorMap *colorMap, bool invert, bool inlineImg, Stream *str, int width, int height, int len, const int *maskColors, Stream *maskStr, int maskWidth, int maskHeight,
+ bool maskInvert)
+{
+ Stream *str2;
+ ImageStream *imgStr;
+ unsigned char *line;
+ PSOutImgClipRect *rects0, *rects1, *rectsTmp, *rectsOut;
+ int rects0Len, rects1Len, rectsSize, rectsOutLen, rectsOutSize;
+ bool emitRect, addRect, extendRect;
+ GooString *s;
+ int n, numComps;
+ bool useLZW, useRLE, useASCII, useCompressed;
+ GfxSeparationColorSpace *sepCS;
+ GfxColor color;
+ GfxCMYK cmyk;
+ int c;
+ int col, i, j, x0, x1, y;
+ char dataBuf[4096];
+
+ rectsOutLen = 0;
+
+ // color key masking
+ if (maskColors && colorMap && !inlineImg) {
+ // can't read the stream twice for inline images -- but masking
+ // isn't allowed with inline images anyway
+ numComps = colorMap->getNumPixelComps();
+ imgStr = new ImageStream(str, width, numComps, colorMap->getBits());
+ imgStr->reset();
+ rects0Len = rects1Len = 0;
+ rectsSize = rectsOutSize = 64;
+ rects0 = (PSOutImgClipRect *)gmallocn(rectsSize, sizeof(PSOutImgClipRect));
+ rects1 = (PSOutImgClipRect *)gmallocn(rectsSize, sizeof(PSOutImgClipRect));
+ rectsOut = (PSOutImgClipRect *)gmallocn(rectsOutSize, sizeof(PSOutImgClipRect));
+ for (y = 0; y < height; ++y) {
+ if (!(line = imgStr->getLine())) {
+ break;
+ }
+ i = 0;
+ rects1Len = 0;
+ for (x0 = 0; x0 < width; ++x0) {
+ for (j = 0; j < numComps; ++j) {
+ if (line[x0 * numComps + j] < maskColors[2 * j] || line[x0 * numComps + j] > maskColors[2 * j + 1]) {
+ break;
+ }
+ }
+ if (j < numComps) {
+ break;
+ }
+ }
+ for (x1 = x0; x1 < width; ++x1) {
+ for (j = 0; j < numComps; ++j) {
+ if (line[x1 * numComps + j] < maskColors[2 * j] || line[x1 * numComps + j] > maskColors[2 * j + 1]) {
+ break;
+ }
+ }
+ if (j == numComps) {
+ break;
+ }
+ }
+ while (x0 < width || i < rects0Len) {
+ emitRect = addRect = extendRect = false;
+ if (x0 >= width) {
+ emitRect = true;
+ } else if (i >= rects0Len) {
+ addRect = true;
+ } else if (rects0[i].x0 < x0) {
+ emitRect = true;
+ } else if (x0 < rects0[i].x0) {
+ addRect = true;
+ } else if (rects0[i].x1 == x1) {
+ extendRect = true;
+ } else {
+ emitRect = addRect = true;
+ }
+ if (emitRect) {
+ if (rectsOutLen == rectsOutSize) {
+ rectsOutSize *= 2;
+ rectsOut = (PSOutImgClipRect *)greallocn(rectsOut, rectsOutSize, sizeof(PSOutImgClipRect));
+ }
+ rectsOut[rectsOutLen].x0 = rects0[i].x0;
+ rectsOut[rectsOutLen].x1 = rects0[i].x1;
+ rectsOut[rectsOutLen].y0 = height - y - 1;
+ rectsOut[rectsOutLen].y1 = height - rects0[i].y0 - 1;
+ ++rectsOutLen;
+ ++i;
+ }
+ if (addRect || extendRect) {
+ if (rects1Len == rectsSize) {
+ rectsSize *= 2;
+ rects0 = (PSOutImgClipRect *)greallocn(rects0, rectsSize, sizeof(PSOutImgClipRect));
+ rects1 = (PSOutImgClipRect *)greallocn(rects1, rectsSize, sizeof(PSOutImgClipRect));
+ }
+ rects1[rects1Len].x0 = x0;
+ rects1[rects1Len].x1 = x1;
+ if (addRect) {
+ rects1[rects1Len].y0 = y;
+ }
+ if (extendRect) {
+ rects1[rects1Len].y0 = rects0[i].y0;
+ ++i;
+ }
+ ++rects1Len;
+ for (x0 = x1; x0 < width; ++x0) {
+ for (j = 0; j < numComps; ++j) {
+ if (line[x0 * numComps + j] < maskColors[2 * j] || line[x0 * numComps + j] > maskColors[2 * j + 1]) {
+ break;
+ }
+ }
+ if (j < numComps) {
+ break;
+ }
+ }
+ for (x1 = x0; x1 < width; ++x1) {
+ for (j = 0; j < numComps; ++j) {
+ if (line[x1 * numComps + j] < maskColors[2 * j] || line[x1 * numComps + j] > maskColors[2 * j + 1]) {
+ break;
+ }
+ }
+ if (j == numComps) {
+ break;
+ }
+ }
+ }
+ }
+ rectsTmp = rects0;
+ rects0 = rects1;
+ rects1 = rectsTmp;
+ i = rects0Len;
+ rects0Len = rects1Len;
+ rects1Len = i;
+ }
+ for (i = 0; i < rects0Len; ++i) {
+ if (rectsOutLen == rectsOutSize) {
+ rectsOutSize *= 2;
+ rectsOut = (PSOutImgClipRect *)greallocn(rectsOut, rectsOutSize, sizeof(PSOutImgClipRect));
+ }
+ rectsOut[rectsOutLen].x0 = rects0[i].x0;
+ rectsOut[rectsOutLen].x1 = rects0[i].x1;
+ rectsOut[rectsOutLen].y0 = height - y - 1;
+ rectsOut[rectsOutLen].y1 = height - rects0[i].y0 - 1;
+ ++rectsOutLen;
+ }
+ if (rectsOutLen < 65536 / 4) {
+ writePSFmt("{0:d} array 0\n", rectsOutLen * 4);
+ for (i = 0; i < rectsOutLen; ++i) {
+ writePSFmt("[{0:d} {1:d} {2:d} {3:d}] pr\n", rectsOut[i].x0, rectsOut[i].y0, rectsOut[i].x1 - rectsOut[i].x0, rectsOut[i].y1 - rectsOut[i].y0);
+ }
+ writePSFmt("pop {0:d} {1:d} pdfImClip\n", width, height);
+ } else {
+ // would be over the limit of array size.
+ // make each rectangle path and clip.
+ writePS("gsave newpath\n");
+ for (i = 0; i < rectsOutLen; ++i) {
+ writePSFmt("{0:.6g} {1:.6g} {2:.6g} {3:.6g} re\n", ((double)rectsOut[i].x0) / width, ((double)rectsOut[i].y0) / height, ((double)(rectsOut[i].x1 - rectsOut[i].x0)) / width,
+ ((double)(rectsOut[i].y1 - rectsOut[i].y0)) / height);
+ }
+ writePS("clip\n");
+ }
+ gfree(rectsOut);
+ gfree(rects0);
+ gfree(rects1);
+ delete imgStr;
+ str->close();
- // get rid of the array and index
- if (!inlineImg) writePS("pop ");
- writePS("pop pop\n");
+ // explicit masking
+ } else if (maskStr) {
+ maskToClippingPath(maskStr, maskWidth, maskHeight, maskInvert);
+ }
- } else {
+ // color space
+ if (colorMap) {
+ // Do not update the process color list for custom colors
+ bool isCustomColor = (level == psLevel1Sep || level == psLevel2Sep || level == psLevel3Sep) && colorMap->getColorSpace()->getMode() == csDeviceN;
+ dumpColorSpaceL2(state, colorMap->getColorSpace(), false, !isCustomColor, false);
+ writePS(" setcolorspace\n");
+ }
- // cut off inline image streams at appropriate length
- if (inlineImg) {
- str = new FixedLengthEncoder(str, len);
- } else if (useCompressed) {
- str = str->getUndecodedStream();
+ // set up the image data
+ if (mode == psModeForm || inType3Char || preloadImagesForms) {
+ if (inlineImg) {
+ // create an array
+ str2 = new FixedLengthEncoder(str, len);
+ if (getEnableLZW()) {
+ str2 = new LZWEncoder(str2);
+ } else {
+ str2 = new RunLengthEncoder(str2);
+ }
+ if (useASCIIHex) {
+ str2 = new ASCIIHexEncoder(str2);
+ } else {
+ str2 = new ASCII85Encoder(str2);
+ }
+ str2->reset();
+ col = 0;
+ writePS((char *)(useASCIIHex ? "[<" : "[<~"));
+ do {
+ do {
+ c = str2->getChar();
+ } while (c == '\n' || c == '\r');
+ if (c == (useASCIIHex ? '>' : '~') || c == EOF) {
+ break;
+ }
+ if (c == 'z') {
+ writePSChar(c);
+ ++col;
+ } else {
+ writePSChar(c);
+ ++col;
+ for (i = 1; i <= (useASCIIHex ? 1 : 4); ++i) {
+ do {
+ c = str2->getChar();
+ } while (c == '\n' || c == '\r');
+ if (c == (useASCIIHex ? '>' : '~') || c == EOF) {
+ break;
+ }
+ writePSChar(c);
+ ++col;
+ }
+ }
+ // each line is: "<~...data...~><eol>"
+ // so max data length = 255 - 6 = 249
+ // chunks are 1 or 5 bytes each, so we have to stop at 245
+ // but make it 240 just to be safe
+ if (col > 240) {
+ writePS((char *)(useASCIIHex ? ">\n<" : "~>\n<~"));
+ col = 0;
+ }
+ } while (c != (useASCIIHex ? '>' : '~') && c != EOF);
+ writePS((char *)(useASCIIHex ? ">\n" : "~>\n"));
+ // add an extra entry because the LZWDecode/RunLengthDecode filter may
+ // read past the end
+ writePS("<>]\n");
+ writePS("0\n");
+ str2->close();
+ delete str2;
+ } else {
+ // make sure the image is setup, it sometimes is not like on bug #17645
+ setupImage(ref->getRef(), str, false);
+ // set up to use the array already created by setupImages()
+ writePSFmt("ImData_{0:d}_{1:d} 0 0\n", ref->getRefNum(), ref->getRefGen());
+ }
}
- // recode DeviceN data
+ // image dictionary
+ writePS("<<\n /ImageType 1\n");
+
+ // width, height, matrix, bits per component
+ writePSFmt(" /Width {0:d}\n", width);
+ writePSFmt(" /Height {0:d}\n", height);
+ writePSFmt(" /ImageMatrix [{0:d} 0 0 {1:d} 0 {2:d}]\n", width, -height, height);
if (colorMap && colorMap->getColorSpace()->getMode() == csDeviceN) {
- str = new DeviceNRecoder(str, width, height, colorMap);
+ writePS(" /BitsPerComponent 8\n");
+ } else {
+ writePSFmt(" /BitsPerComponent {0:d}\n", colorMap ? colorMap->getBits() : 1);
}
- // add LZWEncode/RunLengthEncode and ASCIIHex/85 encode filters
+ // decode
+ if (colorMap) {
+ writePS(" /Decode [");
+ if ((level == psLevel2Sep || level == psLevel3Sep) && colorMap->getColorSpace()->getMode() == csSeparation) {
+ // this matches up with the code in the pdfImSep operator
+ n = (1 << colorMap->getBits()) - 1;
+ writePSFmt("{0:.4g} {1:.4g}", colorMap->getDecodeLow(0) * n, colorMap->getDecodeHigh(0) * n);
+ } else if (colorMap->getColorSpace()->getMode() == csDeviceN) {
+ numComps = ((GfxDeviceNColorSpace *)colorMap->getColorSpace())->getAlt()->getNComps();
+ for (i = 0; i < numComps; ++i) {
+ if (i > 0) {
+ writePS(" ");
+ }
+ writePS("0 1");
+ }
+ } else {
+ numComps = colorMap->getNumPixelComps();
+ for (i = 0; i < numComps; ++i) {
+ if (i > 0) {
+ writePS(" ");
+ }
+ writePSFmt("{0:.4g} {1:.4g}", colorMap->getDecodeLow(i), colorMap->getDecodeHigh(i));
+ }
+ }
+ writePS("]\n");
+ } else {
+ writePSFmt(" /Decode [{0:d} {1:d}]\n", invert ? 1 : 0, invert ? 0 : 1);
+ }
+
+ // data source
+ if (mode == psModeForm || inType3Char || preloadImagesForms) {
+ if (inlineImg) {
+ writePS(" /DataSource { pdfImStr }\n");
+ } else {
+ writePS(" /DataSource { dup 65535 ge { pop 1 add 0 } if 2 index 2"
+ " index get 1 index get exch 1 add exch }\n");
+ }
+ } else {
+ writePS(" /DataSource currentfile\n");
+ }
+
+ // filters
+ if ((mode == psModeForm || inType3Char || preloadImagesForms) && uncompressPreloadedImages) {
+ s = nullptr;
+ useLZW = useRLE = false;
+ useCompressed = false;
+ useASCII = false;
+ } else {
+ s = str->getPSFilter(level < psLevel2 ? 1 : level < psLevel3 ? 2 : 3, " ");
+ if ((colorMap && colorMap->getColorSpace()->getMode() == csDeviceN) || inlineImg || !s) {
+ if (getEnableLZW()) {
+ useLZW = true;
+ useRLE = false;
+ } else {
+ useRLE = true;
+ useLZW = false;
+ }
+ useASCII = !(mode == psModeForm || inType3Char || preloadImagesForms);
+ useCompressed = false;
+ } else {
+ useLZW = useRLE = false;
+ useASCII = str->isBinary() && !(mode == psModeForm || inType3Char || preloadImagesForms);
+ useCompressed = true;
+ }
+ }
+ if (useASCII) {
+ writePSFmt(" /ASCII{0:s}Decode filter\n", useASCIIHex ? "Hex" : "85");
+ }
if (useLZW) {
- str = new LZWEncoder(str);
+ writePS(" /LZWDecode filter\n");
} else if (useRLE) {
- str = new RunLengthEncoder(str);
+ writePS(" /RunLengthDecode filter\n");
}
- if (useASCII) {
- if (useASCIIHex) {
- str = new ASCIIHexEncoder(str);
- } else {
- str = new ASCII85Encoder(str);
- }
+ if (useCompressed) {
+ writePS(s->c_str());
+ }
+ if (s) {
+ delete s;
}
- // end of image dictionary
- writePS(">>\n");
+ if (mode == psModeForm || inType3Char || preloadImagesForms) {
+
+ // end of image dictionary
+ writePSFmt(">>\n{0:s}\n", colorMap ? "image" : "imagemask");
+
+ // get rid of the array and index
+ if (!inlineImg)
+ writePS("pop ");
+ writePS("pop pop\n");
+
+ } else {
+
+ // cut off inline image streams at appropriate length
+ if (inlineImg) {
+ str = new FixedLengthEncoder(str, len);
+ } else if (useCompressed) {
+ str = str->getUndecodedStream();
+ }
+
+ // recode DeviceN data
+ if (colorMap && colorMap->getColorSpace()->getMode() == csDeviceN) {
+ str = new DeviceNRecoder(str, width, height, colorMap);
+ }
+
+ // add LZWEncode/RunLengthEncode and ASCIIHex/85 encode filters
+ if (useLZW) {
+ str = new LZWEncoder(str);
+ } else if (useRLE) {
+ str = new RunLengthEncoder(str);
+ }
+ if (useASCII) {
+ if (useASCIIHex) {
+ str = new ASCIIHexEncoder(str);
+ } else {
+ str = new ASCII85Encoder(str);
+ }
+ }
+
+ // end of image dictionary
+ writePS(">>\n");
#ifdef OPI_SUPPORT
- if (opi13Nest) {
- if (inlineImg) {
- // this can't happen -- OPI dictionaries are in XObjects
- error(errSyntaxError, -1, "OPI in inline image");
- n = 0;
- } else {
- // need to read the stream to count characters -- the length
- // is data-dependent (because of ASCII and LZW/RLE filters)
- str->reset();
- n = 0;
- while ((c = str->getChar()) != EOF) {
- ++n;
- }
- str->close();
- }
- // +6/7 for "pdfIm\n" / "pdfImM\n"
- // +8 for newline + trailer
- n += colorMap ? 14 : 15;
- writePSFmt("%%BeginData: {0:d} Hex Bytes\n", n);
- }
+ if (opi13Nest) {
+ if (inlineImg) {
+ // this can't happen -- OPI dictionaries are in XObjects
+ error(errSyntaxError, -1, "OPI in inline image");
+ n = 0;
+ } else {
+ // need to read the stream to count characters -- the length
+ // is data-dependent (because of ASCII and LZW/RLE filters)
+ str->reset();
+ n = 0;
+ while ((c = str->getChar()) != EOF) {
+ ++n;
+ }
+ str->close();
+ }
+ // +6/7 for "pdfIm\n" / "pdfImM\n"
+ // +8 for newline + trailer
+ n += colorMap ? 14 : 15;
+ writePSFmt("%%BeginData: {0:d} Hex Bytes\n", n);
+ }
#endif
- if ((level == psLevel2Sep || level == psLevel3Sep) && colorMap &&
- colorMap->getColorSpace()->getMode() == csSeparation && colorMap->getBits() == 8) {
- color.c[0] = gfxColorComp1;
- sepCS = (GfxSeparationColorSpace *)colorMap->getColorSpace();
- sepCS->getCMYK(&color, &cmyk);
- writePSFmt("{0:.4g} {1:.4g} {2:.4g} {3:.4g} ({4:t}) pdfImSep\n",
- colToDbl(cmyk.c), colToDbl(cmyk.m),
- colToDbl(cmyk.y), colToDbl(cmyk.k),
- sepCS->getName());
- } else {
- writePSFmt("{0:s}\n", colorMap ? "pdfIm" : "pdfImM");
- }
+ if ((level == psLevel2Sep || level == psLevel3Sep) && colorMap && colorMap->getColorSpace()->getMode() == csSeparation && colorMap->getBits() == 8) {
+ color.c[0] = gfxColorComp1;
+ sepCS = (GfxSeparationColorSpace *)colorMap->getColorSpace();
+ sepCS->getCMYK(&color, &cmyk);
+ writePSFmt("{0:.4g} {1:.4g} {2:.4g} {3:.4g} ({4:t}) pdfImSep\n", colToDbl(cmyk.c), colToDbl(cmyk.m), colToDbl(cmyk.y), colToDbl(cmyk.k), sepCS->getName());
+ } else {
+ writePSFmt("{0:s}\n", colorMap ? "pdfIm" : "pdfImM");
+ }
- // copy the stream data
- str->reset();
- i = 0;
- while ((c = str->getChar()) != EOF) {
- dataBuf[i++] = c;
- if (i >= (int)sizeof(dataBuf)) {
- writePSBuf(dataBuf, i);
- i = 0;
- }
- }
- if (i > 0) {
- writePSBuf(dataBuf, i);
- }
- str->close();
+ // copy the stream data
+ str->reset();
+ i = 0;
+ while ((c = str->getChar()) != EOF) {
+ dataBuf[i++] = c;
+ if (i >= (int)sizeof(dataBuf)) {
+ writePSBuf(dataBuf, i);
+ i = 0;
+ }
+ }
+ if (i > 0) {
+ writePSBuf(dataBuf, i);
+ }
+ str->close();
- // add newline and trailer to the end
- writePSChar('\n');
- writePS("%-EOD-\n");
+ // add newline and trailer to the end
+ writePSChar('\n');
+ writePS("%-EOD-\n");
#ifdef OPI_SUPPORT
- if (opi13Nest) {
- writePS("%%EndData\n");
- }
+ if (opi13Nest) {
+ writePS("%%EndData\n");
+ }
#endif
- // delete encoders
- if (useLZW || useRLE || useASCII || inlineImg) {
- delete str;
+ // delete encoders
+ if (useLZW || useRLE || useASCII || inlineImg) {
+ delete str;
+ }
}
- }
- if ((maskColors && colorMap && !inlineImg) || maskStr) {
- if (rectsOutLen < 65536/4) {
- writePS("pdfImClipEnd\n");
- } else {
- writePS("grestore\n");
+ if ((maskColors && colorMap && !inlineImg) || maskStr) {
+ if (rectsOutLen < 65536 / 4) {
+ writePS("pdfImClipEnd\n");
+ } else {
+ writePS("grestore\n");
+ }
}
- }
}
//~ this doesn't currently support OPI
-void PSOutputDev::doImageL3(GfxState *state, Object *ref, GfxImageColorMap *colorMap,
- bool invert, bool inlineImg,
- Stream *str, int width, int height, int len,
- const int *maskColors, Stream *maskStr,
- int maskWidth, int maskHeight, bool maskInvert) {
- Stream *str2;
- GooString *s;
- int n, numComps;
- bool useFlate, useLZW, useRLE, useASCII, useCompressed;
- bool maskUseFlate, maskUseLZW, maskUseRLE, maskUseASCII, maskUseCompressed;
- GooString *maskFilters;
- GfxSeparationColorSpace *sepCS;
- GfxColor color;
- GfxCMYK cmyk;
- int c;
- int col, i;
-
- useFlate = useLZW = useRLE = useASCII = useCompressed = false;
- maskUseFlate = maskUseLZW = maskUseRLE = maskUseASCII = maskUseCompressed = false;
- maskFilters = nullptr; // make gcc happy
-
- // explicit masking
- if (maskStr) {
-
- // mask data source
- if ((mode == psModeForm || inType3Char || preloadImagesForms) &&
- uncompressPreloadedImages) {
- s = nullptr;
- } else {
- s = maskStr->getPSFilter(3, " ");
- if (!s) {
- if (getEnableFlate()) {
- maskUseFlate = true;
- } else if (getEnableLZW()) {
- maskUseLZW = true;
- } else {
- maskUseRLE = true;
- }
- maskUseASCII = !(mode == psModeForm || inType3Char || preloadImagesForms);
- } else {
- maskUseASCII = maskStr->isBinary() &&
- !(mode == psModeForm || inType3Char || preloadImagesForms);
- maskUseCompressed = true;
- }
- }
- maskFilters = new GooString();
- if (maskUseASCII) {
- maskFilters->appendf(" /ASCII{0:s}Decode filter\n",
- useASCIIHex ? "Hex" : "85");
- }
- if (maskUseFlate) {
- maskFilters->append(" /FlateDecode filter\n");
- } else if (maskUseLZW) {
- maskFilters->append(" /LZWDecode filter\n");
- } else if (maskUseRLE) {
- maskFilters->append(" /RunLengthDecode filter\n");
- }
- if (maskUseCompressed) {
- maskFilters->append(s);
+void PSOutputDev::doImageL3(GfxState *state, Object *ref, GfxImageColorMap *colorMap, bool invert, bool inlineImg, Stream *str, int width, int height, int len, const int *maskColors, Stream *maskStr, int maskWidth, int maskHeight,
+ bool maskInvert)
+{
+ Stream *str2;
+ GooString *s;
+ int n, numComps;
+ bool useFlate, useLZW, useRLE, useASCII, useCompressed;
+ bool maskUseFlate, maskUseLZW, maskUseRLE, maskUseASCII, maskUseCompressed;
+ GooString *maskFilters;
+ GfxSeparationColorSpace *sepCS;
+ GfxColor color;
+ GfxCMYK cmyk;
+ int c;
+ int col, i;
+
+ useFlate = useLZW = useRLE = useASCII = useCompressed = false;
+ maskUseFlate = maskUseLZW = maskUseRLE = maskUseASCII = maskUseCompressed = false;
+ maskFilters = nullptr; // make gcc happy
+
+ // explicit masking
+ if (maskStr) {
+
+ // mask data source
+ if ((mode == psModeForm || inType3Char || preloadImagesForms) && uncompressPreloadedImages) {
+ s = nullptr;
+ } else {
+ s = maskStr->getPSFilter(3, " ");
+ if (!s) {
+ if (getEnableFlate()) {
+ maskUseFlate = true;
+ } else if (getEnableLZW()) {
+ maskUseLZW = true;
+ } else {
+ maskUseRLE = true;
+ }
+ maskUseASCII = !(mode == psModeForm || inType3Char || preloadImagesForms);
+ } else {
+ maskUseASCII = maskStr->isBinary() && !(mode == psModeForm || inType3Char || preloadImagesForms);
+ maskUseCompressed = true;
+ }
+ }
+ maskFilters = new GooString();
+ if (maskUseASCII) {
+ maskFilters->appendf(" /ASCII{0:s}Decode filter\n", useASCIIHex ? "Hex" : "85");
+ }
+ if (maskUseFlate) {
+ maskFilters->append(" /FlateDecode filter\n");
+ } else if (maskUseLZW) {
+ maskFilters->append(" /LZWDecode filter\n");
+ } else if (maskUseRLE) {
+ maskFilters->append(" /RunLengthDecode filter\n");
+ }
+ if (maskUseCompressed) {
+ maskFilters->append(s);
+ }
+ if (s) {
+ delete s;
+ }
+ if (mode == psModeForm || inType3Char || preloadImagesForms) {
+ writePSFmt("MaskData_{0:d}_{1:d} pdfMaskInit\n", ref->getRefNum(), ref->getRefGen());
+ } else {
+ writePS("currentfile\n");
+ writePS(maskFilters->c_str());
+ writePS("pdfMask\n");
+
+ // add FlateEncode/LZWEncode/RunLengthEncode and ASCIIHex/85 encode filters
+ if (maskUseCompressed) {
+ maskStr = maskStr->getUndecodedStream();
+ }
+#ifdef ENABLE_ZLIB
+ if (maskUseFlate) {
+ maskStr = new FlateEncoder(maskStr);
+ } else
+#endif
+ if (maskUseLZW) {
+ maskStr = new LZWEncoder(maskStr);
+ } else if (maskUseRLE) {
+ maskStr = new RunLengthEncoder(maskStr);
+ }
+ if (maskUseASCII) {
+ if (useASCIIHex) {
+ maskStr = new ASCIIHexEncoder(maskStr);
+ } else {
+ maskStr = new ASCII85Encoder(maskStr);
+ }
+ }
+
+ // copy the stream data
+ maskStr->reset();
+ while ((c = maskStr->getChar()) != EOF) {
+ writePSChar(c);
+ }
+ maskStr->close();
+ writePSChar('\n');
+ writePS("%-EOD-\n");
+
+ // delete encoders
+ if (maskUseFlate || maskUseLZW || maskUseRLE || maskUseASCII) {
+ delete maskStr;
+ }
+ }
}
- if (s) {
- delete s;
+
+ // color space
+ if (colorMap) {
+ // Do not update the process color list for custom colors
+ bool isCustomColor = (level == psLevel1Sep || level == psLevel2Sep || level == psLevel3Sep) && colorMap->getColorSpace()->getMode() == csDeviceN;
+ dumpColorSpaceL2(state, colorMap->getColorSpace(), false, !isCustomColor, false);
+ writePS(" setcolorspace\n");
}
+
+ // set up the image data
if (mode == psModeForm || inType3Char || preloadImagesForms) {
- writePSFmt("MaskData_{0:d}_{1:d} pdfMaskInit\n",
- ref->getRefNum(), ref->getRefGen());
- } else {
- writePS("currentfile\n");
- writePS(maskFilters->c_str());
- writePS("pdfMask\n");
-
- // add FlateEncode/LZWEncode/RunLengthEncode and ASCIIHex/85 encode filters
- if (maskUseCompressed) {
- maskStr = maskStr->getUndecodedStream();
- }
+ if (inlineImg) {
+ // create an array
+ str2 = new FixedLengthEncoder(str, len);
#ifdef ENABLE_ZLIB
- if (maskUseFlate) {
- maskStr = new FlateEncoder(maskStr);
- } else
+ if (getEnableFlate()) {
+ str2 = new FlateEncoder(str2);
+ } else
#endif
- if (maskUseLZW) {
- maskStr = new LZWEncoder(maskStr);
- } else if (maskUseRLE) {
- maskStr = new RunLengthEncoder(maskStr);
- }
- if (maskUseASCII) {
- if (useASCIIHex) {
- maskStr = new ASCIIHexEncoder(maskStr);
- } else {
- maskStr = new ASCII85Encoder(maskStr);
- }
- }
-
- // copy the stream data
- maskStr->reset();
- while ((c = maskStr->getChar()) != EOF) {
- writePSChar(c);
- }
- maskStr->close();
- writePSChar('\n');
- writePS("%-EOD-\n");
-
- // delete encoders
- if (maskUseFlate || maskUseLZW || maskUseRLE || maskUseASCII) {
- delete maskStr;
- }
- }
- }
-
- // color space
- if (colorMap) {
- // Do not update the process color list for custom colors
- bool isCustomColor =
- (level == psLevel1Sep || level == psLevel2Sep || level == psLevel3Sep) &&
- colorMap->getColorSpace()->getMode() == csDeviceN;
- dumpColorSpaceL2(state, colorMap->getColorSpace(), false, !isCustomColor, false);
- writePS(" setcolorspace\n");
- }
-
- // set up the image data
- if (mode == psModeForm || inType3Char || preloadImagesForms) {
- if (inlineImg) {
- // create an array
- str2 = new FixedLengthEncoder(str, len);
-#ifdef ENABLE_ZLIB
- if (getEnableFlate()) {
- str2 = new FlateEncoder(str2);
- } else
-#endif
- if (getEnableLZW()) {
- str2 = new LZWEncoder(str2);
- } else {
- str2 = new RunLengthEncoder(str2);
- }
- if (useASCIIHex) {
- str2 = new ASCIIHexEncoder(str2);
- } else {
- str2 = new ASCII85Encoder(str2);
- }
- str2->reset();
- col = 0;
- writePS((char *)(useASCIIHex ? "[<" : "[<~"));
- do {
- do {
- c = str2->getChar();
- } while (c == '\n' || c == '\r');
- if (c == (useASCIIHex ? '>' : '~') || c == EOF) {
- break;
- }
- if (c == 'z') {
- writePSChar(c);
- ++col;
- } else {
- writePSChar(c);
- ++col;
- for (i = 1; i <= (useASCIIHex ? 1 : 4); ++i) {
- do {
- c = str2->getChar();
- } while (c == '\n' || c == '\r');
- if (c == (useASCIIHex ? '>' : '~') || c == EOF) {
- break;
- }
- writePSChar(c);
- ++col;
- }
- }
- // each line is: "<~...data...~><eol>"
- // so max data length = 255 - 6 = 249
- // chunks are 1 or 5 bytes each, so we have to stop at 245
- // but make it 240 just to be safe
- if (col > 240) {
- writePS((char *)(useASCIIHex ? ">\n<" : "~>\n<~"));
- col = 0;
- }
- } while (c != (useASCIIHex ? '>' : '~') && c != EOF);
- writePS((char *)(useASCIIHex ? ">\n" : "~>\n"));
- // add an extra entry because the FlateEncode/LZWDecode/RunLengthDecode filter may
- // read past the end
- writePS("<>]\n");
- writePS("0\n");
- str2->close();
- delete str2;
- } else {
- // make sure the image is setup, it sometimes is not like on bug #17645
- setupImage(ref->getRef(), str, false);
- // set up to use the array already created by setupImages()
- writePSFmt("ImData_{0:d}_{1:d} 0 0\n", ref->getRefNum(), ref->getRefGen());
- }
- }
-
- // explicit masking
- if (maskStr) {
- writePS("<<\n /ImageType 3\n");
- writePS(" /InterleaveType 3\n");
- writePS(" /DataDict\n");
- }
-
- // image (data) dictionary
- writePSFmt("<<\n /ImageType {0:d}\n", (maskColors && colorMap) ? 4 : 1);
-
- // color key masking
- if (maskColors && colorMap) {
- writePS(" /MaskColor [\n");
- numComps = colorMap->getNumPixelComps();
- for (i = 0; i < 2 * numComps; i += 2) {
- writePSFmt(" {0:d} {1:d}\n", maskColors[i], maskColors[i+1]);
+ if (getEnableLZW()) {
+ str2 = new LZWEncoder(str2);
+ } else {
+ str2 = new RunLengthEncoder(str2);
+ }
+ if (useASCIIHex) {
+ str2 = new ASCIIHexEncoder(str2);
+ } else {
+ str2 = new ASCII85Encoder(str2);
+ }
+ str2->reset();
+ col = 0;
+ writePS((char *)(useASCIIHex ? "[<" : "[<~"));
+ do {
+ do {
+ c = str2->getChar();
+ } while (c == '\n' || c == '\r');
+ if (c == (useASCIIHex ? '>' : '~') || c == EOF) {
+ break;
+ }
+ if (c == 'z') {
+ writePSChar(c);
+ ++col;
+ } else {
+ writePSChar(c);
+ ++col;
+ for (i = 1; i <= (useASCIIHex ? 1 : 4); ++i) {
+ do {
+ c = str2->getChar();
+ } while (c == '\n' || c == '\r');
+ if (c == (useASCIIHex ? '>' : '~') || c == EOF) {
+ break;
+ }
+ writePSChar(c);
+ ++col;
+ }
+ }
+ // each line is: "<~...data...~><eol>"
+ // so max data length = 255 - 6 = 249
+ // chunks are 1 or 5 bytes each, so we have to stop at 245
+ // but make it 240 just to be safe
+ if (col > 240) {
+ writePS((char *)(useASCIIHex ? ">\n<" : "~>\n<~"));
+ col = 0;
+ }
+ } while (c != (useASCIIHex ? '>' : '~') && c != EOF);
+ writePS((char *)(useASCIIHex ? ">\n" : "~>\n"));
+ // add an extra entry because the FlateEncode/LZWDecode/RunLengthDecode filter may
+ // read past the end
+ writePS("<>]\n");
+ writePS("0\n");
+ str2->close();
+ delete str2;
+ } else {
+ // make sure the image is setup, it sometimes is not like on bug #17645
+ setupImage(ref->getRef(), str, false);
+ // set up to use the array already created by setupImages()
+ writePSFmt("ImData_{0:d}_{1:d} 0 0\n", ref->getRefNum(), ref->getRefGen());
+ }
}
- writePS(" ]\n");
- }
-
- // width, height, matrix, bits per component
- writePSFmt(" /Width {0:d}\n", width);
- writePSFmt(" /Height {0:d}\n", height);
- writePSFmt(" /ImageMatrix [{0:d} 0 0 {1:d} 0 {2:d}]\n",
- width, -height, height);
- if (colorMap && colorMap->getColorSpace()->getMode() == csDeviceN) {
- writePS(" /BitsPerComponent 8\n");
- } else {
- writePSFmt(" /BitsPerComponent {0:d}\n",
- colorMap ? colorMap->getBits() : 1);
- }
-
- // decode
- if (colorMap) {
- writePS(" /Decode [");
- if ((level == psLevel2Sep || level == psLevel3Sep) &&
- colorMap->getColorSpace()->getMode() == csSeparation) {
- // this matches up with the code in the pdfImSep operator
- n = (1 << colorMap->getBits()) - 1;
- writePSFmt("{0:.4g} {1:.4g}", colorMap->getDecodeLow(0) * n,
- colorMap->getDecodeHigh(0) * n);
- } else {
- numComps = colorMap->getNumPixelComps();
- for (i = 0; i < numComps; ++i) {
- if (i > 0) {
- writePS(" ");
- }
- writePSFmt("{0:.4g} {1:.4g}", colorMap->getDecodeLow(i),
- colorMap->getDecodeHigh(i));
- }
- }
- writePS("]\n");
- } else {
- writePSFmt(" /Decode [{0:d} {1:d}]\n", invert ? 1 : 0, invert ? 0 : 1);
- }
-
- // data source
- if (mode == psModeForm || inType3Char || preloadImagesForms) {
- if (inlineImg) {
- writePS(" /DataSource { pdfImStr }\n");
+
+ // explicit masking
+ if (maskStr) {
+ writePS("<<\n /ImageType 3\n");
+ writePS(" /InterleaveType 3\n");
+ writePS(" /DataDict\n");
+ }
+
+ // image (data) dictionary
+ writePSFmt("<<\n /ImageType {0:d}\n", (maskColors && colorMap) ? 4 : 1);
+
+ // color key masking
+ if (maskColors && colorMap) {
+ writePS(" /MaskColor [\n");
+ numComps = colorMap->getNumPixelComps();
+ for (i = 0; i < 2 * numComps; i += 2) {
+ writePSFmt(" {0:d} {1:d}\n", maskColors[i], maskColors[i + 1]);
+ }
+ writePS(" ]\n");
+ }
+
+ // width, height, matrix, bits per component
+ writePSFmt(" /Width {0:d}\n", width);
+ writePSFmt(" /Height {0:d}\n", height);
+ writePSFmt(" /ImageMatrix [{0:d} 0 0 {1:d} 0 {2:d}]\n", width, -height, height);
+ if (colorMap && colorMap->getColorSpace()->getMode() == csDeviceN) {
+ writePS(" /BitsPerComponent 8\n");
} else {
- writePS(" /DataSource { dup 65535 ge { pop 1 add 0 } if 2 index 2"
- " index get 1 index get exch 1 add exch }\n");
- }
- } else {
- writePS(" /DataSource currentfile\n");
- }
-
- // filters
-
- useFlate = useLZW = useRLE = false;
- useCompressed = false;
- useASCII = false;
-
- if ((mode == psModeForm || inType3Char || preloadImagesForms) &&
- uncompressPreloadedImages) {
- s = nullptr;
- } else {
- s = str->getPSFilter(level < psLevel2 ? 1 : level < psLevel3 ? 2 : 3,
- " ");
- if ((colorMap && colorMap->getColorSpace()->getMode() == csDeviceN) ||
- inlineImg || !s) {
- if (getEnableFlate()) {
- useFlate = true;
- } else if (getEnableLZW()) {
- useLZW = true;
- } else {
- useRLE = true;
- }
- useASCII = !(mode == psModeForm || inType3Char || preloadImagesForms);
+ writePSFmt(" /BitsPerComponent {0:d}\n", colorMap ? colorMap->getBits() : 1);
+ }
+
+ // decode
+ if (colorMap) {
+ writePS(" /Decode [");
+ if ((level == psLevel2Sep || level == psLevel3Sep) && colorMap->getColorSpace()->getMode() == csSeparation) {
+ // this matches up with the code in the pdfImSep operator
+ n = (1 << colorMap->getBits()) - 1;
+ writePSFmt("{0:.4g} {1:.4g}", colorMap->getDecodeLow(0) * n, colorMap->getDecodeHigh(0) * n);
+ } else {
+ numComps = colorMap->getNumPixelComps();
+ for (i = 0; i < numComps; ++i) {
+ if (i > 0) {
+ writePS(" ");
+ }
+ writePSFmt("{0:.4g} {1:.4g}", colorMap->getDecodeLow(i), colorMap->getDecodeHigh(i));
+ }
+ }
+ writePS("]\n");
} else {
- useASCII = str->isBinary() &&
- !(mode == psModeForm || inType3Char || preloadImagesForms);
- useCompressed = true;
- }
- }
- if (useASCII) {
- writePSFmt(" /ASCII{0:s}Decode filter\n",
- useASCIIHex ? "Hex" : "85");
- }
- if (useFlate) {
- writePS(" /FlateDecode filter\n");
- } else if (useLZW) {
- writePS(" /LZWDecode filter\n");
- } else if (useRLE) {
- writePS(" /RunLengthDecode filter\n");
- }
- if (useCompressed) {
- writePS(s->c_str());
- }
- if (s) {
- delete s;
- }
-
- // end of image (data) dictionary
- writePS(">>\n");
-
- // explicit masking
- if (maskStr) {
- writePS(" /MaskDict\n");
- writePS("<<\n");
- writePS(" /ImageType 1\n");
- writePSFmt(" /Width {0:d}\n", maskWidth);
- writePSFmt(" /Height {0:d}\n", maskHeight);
- writePSFmt(" /ImageMatrix [{0:d} 0 0 {1:d} 0 {2:d}]\n",
- maskWidth, -maskHeight, maskHeight);
- writePS(" /BitsPerComponent 1\n");
- writePSFmt(" /Decode [{0:d} {1:d}]\n",
- maskInvert ? 1 : 0, maskInvert ? 0 : 1);
-
- // mask data source
+ writePSFmt(" /Decode [{0:d} {1:d}]\n", invert ? 1 : 0, invert ? 0 : 1);
+ }
+
+ // data source
if (mode == psModeForm || inType3Char || preloadImagesForms) {
- writePS(" /DataSource {pdfMaskSrc}\n");
- writePS(maskFilters->c_str());
+ if (inlineImg) {
+ writePS(" /DataSource { pdfImStr }\n");
+ } else {
+ writePS(" /DataSource { dup 65535 ge { pop 1 add 0 } if 2 index 2"
+ " index get 1 index get exch 1 add exch }\n");
+ }
} else {
- writePS(" /DataSource maskStream\n");
+ writePS(" /DataSource currentfile\n");
}
- delete maskFilters;
- writePS(">>\n");
- writePS(">>\n");
- }
+ // filters
- if (mode == psModeForm || inType3Char || preloadImagesForms) {
+ useFlate = useLZW = useRLE = false;
+ useCompressed = false;
+ useASCII = false;
+
+ if ((mode == psModeForm || inType3Char || preloadImagesForms) && uncompressPreloadedImages) {
+ s = nullptr;
+ } else {
+ s = str->getPSFilter(level < psLevel2 ? 1 : level < psLevel3 ? 2 : 3, " ");
+ if ((colorMap && colorMap->getColorSpace()->getMode() == csDeviceN) || inlineImg || !s) {
+ if (getEnableFlate()) {
+ useFlate = true;
+ } else if (getEnableLZW()) {
+ useLZW = true;
+ } else {
+ useRLE = true;
+ }
+ useASCII = !(mode == psModeForm || inType3Char || preloadImagesForms);
+ } else {
+ useASCII = str->isBinary() && !(mode == psModeForm || inType3Char || preloadImagesForms);
+ useCompressed = true;
+ }
+ }
+ if (useASCII) {
+ writePSFmt(" /ASCII{0:s}Decode filter\n", useASCIIHex ? "Hex" : "85");
+ }
+ if (useFlate) {
+ writePS(" /FlateDecode filter\n");
+ } else if (useLZW) {
+ writePS(" /LZWDecode filter\n");
+ } else if (useRLE) {
+ writePS(" /RunLengthDecode filter\n");
+ }
+ if (useCompressed) {
+ writePS(s->c_str());
+ }
+ if (s) {
+ delete s;
+ }
- // image command
- writePSFmt("{0:s}\n", colorMap ? "image" : "imagemask");
+ // end of image (data) dictionary
+ writePS(">>\n");
- } else {
+ // explicit masking
+ if (maskStr) {
+ writePS(" /MaskDict\n");
+ writePS("<<\n");
+ writePS(" /ImageType 1\n");
+ writePSFmt(" /Width {0:d}\n", maskWidth);
+ writePSFmt(" /Height {0:d}\n", maskHeight);
+ writePSFmt(" /ImageMatrix [{0:d} 0 0 {1:d} 0 {2:d}]\n", maskWidth, -maskHeight, maskHeight);
+ writePS(" /BitsPerComponent 1\n");
+ writePSFmt(" /Decode [{0:d} {1:d}]\n", maskInvert ? 1 : 0, maskInvert ? 0 : 1);
+
+ // mask data source
+ if (mode == psModeForm || inType3Char || preloadImagesForms) {
+ writePS(" /DataSource {pdfMaskSrc}\n");
+ writePS(maskFilters->c_str());
+ } else {
+ writePS(" /DataSource maskStream\n");
+ }
+ delete maskFilters;
- if ((level == psLevel2Sep || level == psLevel3Sep) && colorMap &&
- colorMap->getColorSpace()->getMode() == csSeparation && colorMap->getBits() == 8) {
- color.c[0] = gfxColorComp1;
- sepCS = (GfxSeparationColorSpace *)colorMap->getColorSpace();
- sepCS->getCMYK(&color, &cmyk);
- writePSFmt("{0:.4g} {1:.4g} {2:.4g} {3:.4g} ({4:t}) pdfImSep\n",
- colToDbl(cmyk.c), colToDbl(cmyk.m),
- colToDbl(cmyk.y), colToDbl(cmyk.k),
- sepCS->getName());
- } else {
- writePSFmt("{0:s}\n", colorMap ? "pdfIm" : "pdfImM");
+ writePS(">>\n");
+ writePS(">>\n");
}
- }
+ if (mode == psModeForm || inType3Char || preloadImagesForms) {
- // get rid of the array and index
- if (mode == psModeForm || inType3Char || preloadImagesForms) {
- if (!inlineImg) writePS("pop ");
- writePS("pop pop\n");
+ // image command
+ writePSFmt("{0:s}\n", colorMap ? "image" : "imagemask");
- // image data
- } else {
+ } else {
- // cut off inline image streams at appropriate length
- if (inlineImg) {
- str = new FixedLengthEncoder(str, len);
- } else if (useCompressed) {
- str = str->getUndecodedStream();
+ if ((level == psLevel2Sep || level == psLevel3Sep) && colorMap && colorMap->getColorSpace()->getMode() == csSeparation && colorMap->getBits() == 8) {
+ color.c[0] = gfxColorComp1;
+ sepCS = (GfxSeparationColorSpace *)colorMap->getColorSpace();
+ sepCS->getCMYK(&color, &cmyk);
+ writePSFmt("{0:.4g} {1:.4g} {2:.4g} {3:.4g} ({4:t}) pdfImSep\n", colToDbl(cmyk.c), colToDbl(cmyk.m), colToDbl(cmyk.y), colToDbl(cmyk.k), sepCS->getName());
+ } else {
+ writePSFmt("{0:s}\n", colorMap ? "pdfIm" : "pdfImM");
+ }
}
- // add FlateEncode/LZWEncode/RunLengthEncode and ASCIIHex/85 encode filters
+ // get rid of the array and index
+ if (mode == psModeForm || inType3Char || preloadImagesForms) {
+ if (!inlineImg)
+ writePS("pop ");
+ writePS("pop pop\n");
+
+ // image data
+ } else {
+
+ // cut off inline image streams at appropriate length
+ if (inlineImg) {
+ str = new FixedLengthEncoder(str, len);
+ } else if (useCompressed) {
+ str = str->getUndecodedStream();
+ }
+
+ // add FlateEncode/LZWEncode/RunLengthEncode and ASCIIHex/85 encode filters
#ifdef ENABLE_ZLIB
- if (useFlate) {
- str = new FlateEncoder(str);
- } else
+ if (useFlate) {
+ str = new FlateEncoder(str);
+ } else
#endif
- if (useLZW) {
- str = new LZWEncoder(str);
- } else if (useRLE) {
- str = new RunLengthEncoder(str);
- }
- if (useASCII) {
- if (useASCIIHex) {
- str = new ASCIIHexEncoder(str);
- } else {
- str = new ASCII85Encoder(str);
- }
- }
+ if (useLZW) {
+ str = new LZWEncoder(str);
+ } else if (useRLE) {
+ str = new RunLengthEncoder(str);
+ }
+ if (useASCII) {
+ if (useASCIIHex) {
+ str = new ASCIIHexEncoder(str);
+ } else {
+ str = new ASCII85Encoder(str);
+ }
+ }
- // copy the stream data
- str->reset();
- while ((c = str->getChar()) != EOF) {
- writePSChar(c);
- }
- str->close();
+ // copy the stream data
+ str->reset();
+ while ((c = str->getChar()) != EOF) {
+ writePSChar(c);
+ }
+ str->close();
- // add newline and trailer to the end
- writePSChar('\n');
- writePS("%-EOD-\n");
+ // add newline and trailer to the end
+ writePSChar('\n');
+ writePS("%-EOD-\n");
- // delete encoders
- if (useFlate || useLZW || useRLE || useASCII || inlineImg) {
- delete str;
+ // delete encoders
+ if (useFlate || useLZW || useRLE || useASCII || inlineImg) {
+ delete str;
+ }
}
- }
- // close the mask stream
- if (maskStr) {
- if (!(mode == psModeForm || inType3Char || preloadImagesForms)) {
- writePS("pdfMaskEnd\n");
+ // close the mask stream
+ if (maskStr) {
+ if (!(mode == psModeForm || inType3Char || preloadImagesForms)) {
+ writePS("pdfMaskEnd\n");
+ }
}
- }
}
-void PSOutputDev::dumpColorSpaceL2(GfxState *state, GfxColorSpace *colorSpace,
- bool genXform, bool updateColors,
- bool map01) {
- GfxCalGrayColorSpace *calGrayCS;
- GfxCalRGBColorSpace *calRGBCS;
- GfxLabColorSpace *labCS;
- GfxIndexedColorSpace *indexedCS;
- GfxSeparationColorSpace *separationCS;
- GfxDeviceNColorSpace *deviceNCS;
- GfxColorSpace *baseCS;
- unsigned char *lookup, *p;
- double x[gfxColorMaxComps], y[gfxColorMaxComps];
- double low[gfxColorMaxComps], range[gfxColorMaxComps];
- GfxColor color;
- GfxCMYK cmyk;
- int n, numComps, numAltComps;
- int byte;
- int i, j, k;
-
- switch (colorSpace->getMode()) {
-
- case csDeviceGray:
- writePS("/DeviceGray");
- if (genXform) {
- writePS(" {}");
- }
- if (updateColors) {
- processColors |= psProcessBlack;
- }
- break;
+void PSOutputDev::dumpColorSpaceL2(GfxState *state, GfxColorSpace *colorSpace, bool genXform, bool updateColors, bool map01)
+{
+ GfxCalGrayColorSpace *calGrayCS;
+ GfxCalRGBColorSpace *calRGBCS;
+ GfxLabColorSpace *labCS;
+ GfxIndexedColorSpace *indexedCS;
+ GfxSeparationColorSpace *separationCS;
+ GfxDeviceNColorSpace *deviceNCS;
+ GfxColorSpace *baseCS;
+ unsigned char *lookup, *p;
+ double x[gfxColorMaxComps], y[gfxColorMaxComps];
+ double low[gfxColorMaxComps], range[gfxColorMaxComps];
+ GfxColor color;
+ GfxCMYK cmyk;
+ int n, numComps, numAltComps;
+ int byte;
+ int i, j, k;
+
+ switch (colorSpace->getMode()) {
+
+ case csDeviceGray:
+ writePS("/DeviceGray");
+ if (genXform) {
+ writePS(" {}");
+ }
+ if (updateColors) {
+ processColors |= psProcessBlack;
+ }
+ break;
- case csCalGray:
- calGrayCS = (GfxCalGrayColorSpace *)colorSpace;
- writePS("[/CIEBasedA <<\n");
- writePSFmt(" /DecodeA {{{0:.4g} exp}} bind\n", calGrayCS->getGamma());
- writePSFmt(" /MatrixA [{0:.4g} {1:.4g} {2:.4g}]\n",
- calGrayCS->getWhiteX(), calGrayCS->getWhiteY(),
- calGrayCS->getWhiteZ());
- writePSFmt(" /WhitePoint [{0:.4g} {1:.4g} {2:.4g}]\n",
- calGrayCS->getWhiteX(), calGrayCS->getWhiteY(),
- calGrayCS->getWhiteZ());
- writePSFmt(" /BlackPoint [{0:.4g} {1:.4g} {2:.4g}]\n",
- calGrayCS->getBlackX(), calGrayCS->getBlackY(),
- calGrayCS->getBlackZ());
- writePS(">>]");
- if (genXform) {
- writePS(" {}");
- }
- if (updateColors) {
- processColors |= psProcessBlack;
- }
- break;
+ case csCalGray:
+ calGrayCS = (GfxCalGrayColorSpace *)colorSpace;
+ writePS("[/CIEBasedA <<\n");
+ writePSFmt(" /DecodeA {{{0:.4g} exp}} bind\n", calGrayCS->getGamma());
+ writePSFmt(" /MatrixA [{0:.4g} {1:.4g} {2:.4g}]\n", calGrayCS->getWhiteX(), calGrayCS->getWhiteY(), calGrayCS->getWhiteZ());
+ writePSFmt(" /WhitePoint [{0:.4g} {1:.4g} {2:.4g}]\n", calGrayCS->getWhiteX(), calGrayCS->getWhiteY(), calGrayCS->getWhiteZ());
+ writePSFmt(" /BlackPoint [{0:.4g} {1:.4g} {2:.4g}]\n", calGrayCS->getBlackX(), calGrayCS->getBlackY(), calGrayCS->getBlackZ());
+ writePS(">>]");
+ if (genXform) {
+ writePS(" {}");
+ }
+ if (updateColors) {
+ processColors |= psProcessBlack;
+ }
+ break;
- case csDeviceRGB:
- writePS("/DeviceRGB");
- if (genXform) {
- writePS(" {}");
- }
- if (updateColors) {
- processColors |= psProcessCMYK;
- }
- break;
+ case csDeviceRGB:
+ writePS("/DeviceRGB");
+ if (genXform) {
+ writePS(" {}");
+ }
+ if (updateColors) {
+ processColors |= psProcessCMYK;
+ }
+ break;
- case csCalRGB:
- calRGBCS = (GfxCalRGBColorSpace *)colorSpace;
- writePS("[/CIEBasedABC <<\n");
- writePSFmt(" /DecodeABC [{{{0:.4g} exp}} bind {{{1:.4g} exp}} bind {{{2:.4g} exp}} bind]\n",
- calRGBCS->getGammaR(), calRGBCS->getGammaG(),
- calRGBCS->getGammaB());
- writePSFmt(" /MatrixABC [{0:.4g} {1:.4g} {2:.4g} {3:.4g} {4:.4g} {5:.4g} {6:.4g} {7:.4g} {8:.4g}]\n",
- calRGBCS->getMatrix()[0], calRGBCS->getMatrix()[1],
- calRGBCS->getMatrix()[2], calRGBCS->getMatrix()[3],
- calRGBCS->getMatrix()[4], calRGBCS->getMatrix()[5],
- calRGBCS->getMatrix()[6], calRGBCS->getMatrix()[7],
- calRGBCS->getMatrix()[8]);
- writePSFmt(" /WhitePoint [{0:.4g} {1:.4g} {2:.4g}]\n",
- calRGBCS->getWhiteX(), calRGBCS->getWhiteY(),
- calRGBCS->getWhiteZ());
- writePSFmt(" /BlackPoint [{0:.4g} {1:.4g} {2:.4g}]\n",
- calRGBCS->getBlackX(), calRGBCS->getBlackY(),
- calRGBCS->getBlackZ());
- writePS(">>]");
- if (genXform) {
- writePS(" {}");
- }
- if (updateColors) {
- processColors |= psProcessCMYK;
- }
- break;
+ case csCalRGB:
+ calRGBCS = (GfxCalRGBColorSpace *)colorSpace;
+ writePS("[/CIEBasedABC <<\n");
+ writePSFmt(" /DecodeABC [{{{0:.4g} exp}} bind {{{1:.4g} exp}} bind {{{2:.4g} exp}} bind]\n", calRGBCS->getGammaR(), calRGBCS->getGammaG(), calRGBCS->getGammaB());
+ writePSFmt(" /MatrixABC [{0:.4g} {1:.4g} {2:.4g} {3:.4g} {4:.4g} {5:.4g} {6:.4g} {7:.4g} {8:.4g}]\n", calRGBCS->getMatrix()[0], calRGBCS->getMatrix()[1], calRGBCS->getMatrix()[2], calRGBCS->getMatrix()[3], calRGBCS->getMatrix()[4],
+ calRGBCS->getMatrix()[5], calRGBCS->getMatrix()[6], calRGBCS->getMatrix()[7], calRGBCS->getMatrix()[8]);
+ writePSFmt(" /WhitePoint [{0:.4g} {1:.4g} {2:.4g}]\n", calRGBCS->getWhiteX(), calRGBCS->getWhiteY(), calRGBCS->getWhiteZ());
+ writePSFmt(" /BlackPoint [{0:.4g} {1:.4g} {2:.4g}]\n", calRGBCS->getBlackX(), calRGBCS->getBlackY(), calRGBCS->getBlackZ());
+ writePS(">>]");
+ if (genXform) {
+ writePS(" {}");
+ }
+ if (updateColors) {
+ processColors |= psProcessCMYK;
+ }
+ break;
- case csDeviceCMYK:
- writePS("/DeviceCMYK");
- if (genXform) {
- writePS(" {}");
- }
- if (updateColors) {
- processColors |= psProcessCMYK;
- }
- break;
+ case csDeviceCMYK:
+ writePS("/DeviceCMYK");
+ if (genXform) {
+ writePS(" {}");
+ }
+ if (updateColors) {
+ processColors |= psProcessCMYK;
+ }
+ break;
- case csLab:
- labCS = (GfxLabColorSpace *)colorSpace;
- writePS("[/CIEBasedABC <<\n");
- if (map01) {
- writePS(" /RangeABC [0 1 0 1 0 1]\n");
- writePSFmt(" /DecodeABC [{{100 mul 16 add 116 div}} bind {{{0:.4g} mul {1:.4g} add}} bind {{{2:.4g} mul {3:.4g} add}} bind]\n",
- (labCS->getAMax() - labCS->getAMin()) / 500.0,
- labCS->getAMin() / 500.0,
- (labCS->getBMax() - labCS->getBMin()) / 200.0,
- labCS->getBMin() / 200.0);
- } else {
- writePSFmt(" /RangeABC [0 100 {0:.4g} {1:.4g} {2:.4g} {3:.4g}]\n",
- labCS->getAMin(), labCS->getAMax(),
- labCS->getBMin(), labCS->getBMax());
- writePS(" /DecodeABC [{16 add 116 div} bind {500 div} bind {200 div} bind]\n");
- }
- writePS(" /MatrixABC [1 1 1 1 0 0 0 0 -1]\n");
- writePS(" /DecodeLMN\n");
- writePS(" [{dup 6 29 div ge {dup dup mul mul}\n");
- writePSFmt(" {{4 29 div sub 108 841 div mul }} ifelse {0:.4g} mul}} bind\n",
- labCS->getWhiteX());
- writePS(" {dup 6 29 div ge {dup dup mul mul}\n");
- writePSFmt(" {{4 29 div sub 108 841 div mul }} ifelse {0:.4g} mul}} bind\n",
- labCS->getWhiteY());
- writePS(" {dup 6 29 div ge {dup dup mul mul}\n");
- writePSFmt(" {{4 29 div sub 108 841 div mul }} ifelse {0:.4g} mul}} bind]\n",
- labCS->getWhiteZ());
- writePSFmt(" /WhitePoint [{0:.4g} {1:.4g} {2:.4g}]\n",
- labCS->getWhiteX(), labCS->getWhiteY(), labCS->getWhiteZ());
- writePSFmt(" /BlackPoint [{0:.4g} {1:.4g} {2:.4g}]\n",
- labCS->getBlackX(), labCS->getBlackY(), labCS->getBlackZ());
- writePS(">>]");
- if (genXform) {
- writePS(" {}");
- }
- if (updateColors) {
- processColors |= psProcessCMYK;
- }
- break;
+ case csLab:
+ labCS = (GfxLabColorSpace *)colorSpace;
+ writePS("[/CIEBasedABC <<\n");
+ if (map01) {
+ writePS(" /RangeABC [0 1 0 1 0 1]\n");
+ writePSFmt(" /DecodeABC [{{100 mul 16 add 116 div}} bind {{{0:.4g} mul {1:.4g} add}} bind {{{2:.4g} mul {3:.4g} add}} bind]\n", (labCS->getAMax() - labCS->getAMin()) / 500.0, labCS->getAMin() / 500.0,
+ (labCS->getBMax() - labCS->getBMin()) / 200.0, labCS->getBMin() / 200.0);
+ } else {
+ writePSFmt(" /RangeABC [0 100 {0:.4g} {1:.4g} {2:.4g} {3:.4g}]\n", labCS->getAMin(), labCS->getAMax(), labCS->getBMin(), labCS->getBMax());
+ writePS(" /DecodeABC [{16 add 116 div} bind {500 div} bind {200 div} bind]\n");
+ }
+ writePS(" /MatrixABC [1 1 1 1 0 0 0 0 -1]\n");
+ writePS(" /DecodeLMN\n");
+ writePS(" [{dup 6 29 div ge {dup dup mul mul}\n");
+ writePSFmt(" {{4 29 div sub 108 841 div mul }} ifelse {0:.4g} mul}} bind\n", labCS->getWhiteX());
+ writePS(" {dup 6 29 div ge {dup dup mul mul}\n");
+ writePSFmt(" {{4 29 div sub 108 841 div mul }} ifelse {0:.4g} mul}} bind\n", labCS->getWhiteY());
+ writePS(" {dup 6 29 div ge {dup dup mul mul}\n");
+ writePSFmt(" {{4 29 div sub 108 841 div mul }} ifelse {0:.4g} mul}} bind]\n", labCS->getWhiteZ());
+ writePSFmt(" /WhitePoint [{0:.4g} {1:.4g} {2:.4g}]\n", labCS->getWhiteX(), labCS->getWhiteY(), labCS->getWhiteZ());
+ writePSFmt(" /BlackPoint [{0:.4g} {1:.4g} {2:.4g}]\n", labCS->getBlackX(), labCS->getBlackY(), labCS->getBlackZ());
+ writePS(">>]");
+ if (genXform) {
+ writePS(" {}");
+ }
+ if (updateColors) {
+ processColors |= psProcessCMYK;
+ }
+ break;
- case csICCBased:
+ case csICCBased:
#ifdef USE_CMS
{
- GfxICCBasedColorSpace *iccBasedCS;
- iccBasedCS = (GfxICCBasedColorSpace *)colorSpace;
- Ref ref = iccBasedCS->getRef();
- int intent = state->getCmsRenderingIntent();
- GooString *name = GooString::format("ICCBased-{0:d}-{1:d}-{2:d}", ref.num, ref.gen, intent);
- const auto& it = iccEmitted.find(name->toStr());
- if (it != iccEmitted.end()) {
- writePSFmt("{0:t}", name);
- if (genXform) {
- writePS(" {}");
- }
- } else {
- char *csa = iccBasedCS->getPostScriptCSA();
- if (csa) {
- writePSFmt("userdict /{0:t} {1:s} put\n", name, csa);
- iccEmitted.emplace(name->toStr());
- writePSFmt("{0:t}", name);
- if (genXform) {
- writePS(" {}");
- }
- } else {
- dumpColorSpaceL2(state, ((GfxICCBasedColorSpace *)colorSpace)->getAlt(),
- genXform, updateColors, false);
- }
- }
- delete name;
+ GfxICCBasedColorSpace *iccBasedCS;
+ iccBasedCS = (GfxICCBasedColorSpace *)colorSpace;
+ Ref ref = iccBasedCS->getRef();
+ int intent = state->getCmsRenderingIntent();
+ GooString *name = GooString::format("ICCBased-{0:d}-{1:d}-{2:d}", ref.num, ref.gen, intent);
+ const auto &it = iccEmitted.find(name->toStr());
+ if (it != iccEmitted.end()) {
+ writePSFmt("{0:t}", name);
+ if (genXform) {
+ writePS(" {}");
+ }
+ } else {
+ char *csa = iccBasedCS->getPostScriptCSA();
+ if (csa) {
+ writePSFmt("userdict /{0:t} {1:s} put\n", name, csa);
+ iccEmitted.emplace(name->toStr());
+ writePSFmt("{0:t}", name);
+ if (genXform) {
+ writePS(" {}");
+ }
+ } else {
+ dumpColorSpaceL2(state, ((GfxICCBasedColorSpace *)colorSpace)->getAlt(), genXform, updateColors, false);
+ }
+ }
+ delete name;
}
#else
- // there is no transform function to the alternate color space, so
- // we can use it directly
- dumpColorSpaceL2(state, ((GfxICCBasedColorSpace *)colorSpace)->getAlt(),
- genXform, updateColors, false);
+ // there is no transform function to the alternate color space, so
+ // we can use it directly
+ dumpColorSpaceL2(state, ((GfxICCBasedColorSpace *)colorSpace)->getAlt(), genXform, updateColors, false);
#endif
break;
- case csIndexed:
- indexedCS = (GfxIndexedColorSpace *)colorSpace;
- baseCS = indexedCS->getBase();
- writePS("[/Indexed ");
- dumpColorSpaceL2(state, baseCS, false, false, true);
- n = indexedCS->getIndexHigh();
- numComps = baseCS->getNComps();
- lookup = indexedCS->getLookup();
- writePSFmt(" {0:d} <\n", n);
- if (baseCS->getMode() == csDeviceN && level != psLevel3 && level != psLevel3Sep) {
- const Function *func = ((GfxDeviceNColorSpace *)baseCS)->getTintTransformFunc();
- baseCS->getDefaultRanges(low, range, indexedCS->getIndexHigh());
- if (((GfxDeviceNColorSpace *)baseCS)->getAlt()->getMode() == csLab) {
- labCS = (GfxLabColorSpace *)((GfxDeviceNColorSpace *)baseCS)->getAlt();
- } else {
- labCS = nullptr;
- }
- numAltComps = ((GfxDeviceNColorSpace *)baseCS)->getAlt()->getNComps();
- p = lookup;
- for (i = 0; i <= n; i += 8) {
- writePS(" ");
- for (j = i; j < i+8 && j <= n; ++j) {
- for (k = 0; k < numComps; ++k) {
- x[k] = low[k] + (*p++ / 255.0) * range[k];
- }
- func->transform(x, y);
- if (labCS) {
- y[0] /= 100.0;
- y[1] = (y[1] - labCS->getAMin()) /
- (labCS->getAMax() - labCS->getAMin());
- y[2] = (y[2] - labCS->getBMin()) /
- (labCS->getBMax() - labCS->getBMin());
- }
- for (k = 0; k < numAltComps; ++k) {
- byte = (int)(y[k] * 255 + 0.5);
- if (byte < 0) {
- byte = 0;
- } else if (byte > 255) {
- byte = 255;
- }
- writePSFmt("{0:02x}", byte);
- }
- if (updateColors) {
- color.c[0] = dblToCol(j);
- indexedCS->getCMYK(&color, &cmyk);
- addProcessColor(colToDbl(cmyk.c), colToDbl(cmyk.m),
- colToDbl(cmyk.y), colToDbl(cmyk.k));
- }
- }
- writePS("\n");
- }
- } else {
- for (i = 0; i <= n; i += 8) {
- writePS(" ");
- for (j = i; j < i+8 && j <= n; ++j) {
- for (k = 0; k < numComps; ++k) {
- writePSFmt("{0:02x}", lookup[j * numComps + k]);
- }
- if (updateColors) {
- color.c[0] = dblToCol(j);
- indexedCS->getCMYK(&color, &cmyk);
- addProcessColor(colToDbl(cmyk.c), colToDbl(cmyk.m),
- colToDbl(cmyk.y), colToDbl(cmyk.k));
- }
- }
- writePS("\n");
- }
- }
- writePS(">]");
- if (genXform) {
- writePS(" {}");
+ case csIndexed:
+ indexedCS = (GfxIndexedColorSpace *)colorSpace;
+ baseCS = indexedCS->getBase();
+ writePS("[/Indexed ");
+ dumpColorSpaceL2(state, baseCS, false, false, true);
+ n = indexedCS->getIndexHigh();
+ numComps = baseCS->getNComps();
+ lookup = indexedCS->getLookup();
+ writePSFmt(" {0:d} <\n", n);
+ if (baseCS->getMode() == csDeviceN && level != psLevel3 && level != psLevel3Sep) {
+ const Function *func = ((GfxDeviceNColorSpace *)baseCS)->getTintTransformFunc();
+ baseCS->getDefaultRanges(low, range, indexedCS->getIndexHigh());
+ if (((GfxDeviceNColorSpace *)baseCS)->getAlt()->getMode() == csLab) {
+ labCS = (GfxLabColorSpace *)((GfxDeviceNColorSpace *)baseCS)->getAlt();
+ } else {
+ labCS = nullptr;
+ }
+ numAltComps = ((GfxDeviceNColorSpace *)baseCS)->getAlt()->getNComps();
+ p = lookup;
+ for (i = 0; i <= n; i += 8) {
+ writePS(" ");
+ for (j = i; j < i + 8 && j <= n; ++j) {
+ for (k = 0; k < numComps; ++k) {
+ x[k] = low[k] + (*p++ / 255.0) * range[k];
+ }
+ func->transform(x, y);
+ if (labCS) {
+ y[0] /= 100.0;
+ y[1] = (y[1] - labCS->getAMin()) / (labCS->getAMax() - labCS->getAMin());
+ y[2] = (y[2] - labCS->getBMin()) / (labCS->getBMax() - labCS->getBMin());
+ }
+ for (k = 0; k < numAltComps; ++k) {
+ byte = (int)(y[k] * 255 + 0.5);
+ if (byte < 0) {
+ byte = 0;
+ } else if (byte > 255) {
+ byte = 255;
+ }
+ writePSFmt("{0:02x}", byte);
+ }
+ if (updateColors) {
+ color.c[0] = dblToCol(j);
+ indexedCS->getCMYK(&color, &cmyk);
+ addProcessColor(colToDbl(cmyk.c), colToDbl(cmyk.m), colToDbl(cmyk.y), colToDbl(cmyk.k));
+ }
+ }
+ writePS("\n");
+ }
+ } else {
+ for (i = 0; i <= n; i += 8) {
+ writePS(" ");
+ for (j = i; j < i + 8 && j <= n; ++j) {
+ for (k = 0; k < numComps; ++k) {
+ writePSFmt("{0:02x}", lookup[j * numComps + k]);
+ }
+ if (updateColors) {
+ color.c[0] = dblToCol(j);
+ indexedCS->getCMYK(&color, &cmyk);
+ addProcessColor(colToDbl(cmyk.c), colToDbl(cmyk.m), colToDbl(cmyk.y), colToDbl(cmyk.k));
+ }
+ }
+ writePS("\n");
+ }
+ }
+ writePS(">]");
+ if (genXform) {
+ writePS(" {}");
+ }
+ break;
+
+ case csSeparation:
+ separationCS = (GfxSeparationColorSpace *)colorSpace;
+ writePS("[/Separation ");
+ writePSString(separationCS->getName()->toStr());
+ writePS(" ");
+ dumpColorSpaceL2(state, separationCS->getAlt(), false, false, false);
+ writePS("\n");
+ cvtFunction(separationCS->getFunc());
+ writePS("]");
+ if (genXform) {
+ writePS(" {}");
+ }
+ if (updateColors) {
+ addCustomColor(separationCS);
+ }
+ break;
+
+ case csDeviceN:
+ deviceNCS = (GfxDeviceNColorSpace *)colorSpace;
+ if (level == psLevel3 || level == psLevel3Sep) {
+ writePS("[/DeviceN\n");
+ writePS(" [ ");
+ for (i = 0; i < deviceNCS->getNComps(); i++) {
+ writePSString(deviceNCS->getColorantName(i));
+ writePS(" ");
+ }
+ writePS("]\n");
+ dumpColorSpaceL2(state, deviceNCS->getAlt(), false, updateColors, false);
+ writePS("\n");
+ cvtFunction(deviceNCS->getTintTransformFunc(), map01 && deviceNCS->getAlt()->getMode() == csLab);
+ writePS("]\n");
+ if (genXform) {
+ writePS(" {}");
+ }
+ } else {
+ // DeviceN color spaces are a Level 3 PostScript feature.
+ dumpColorSpaceL2(state, deviceNCS->getAlt(), false, updateColors, map01);
+ if (genXform) {
+ writePS(" ");
+ cvtFunction(deviceNCS->getTintTransformFunc());
+ }
+ }
+ break;
+
+ case csPattern:
+ //~ unimplemented
+ break;
}
- break;
+}
- case csSeparation:
- separationCS = (GfxSeparationColorSpace *)colorSpace;
- writePS("[/Separation ");
- writePSString(separationCS->getName()->toStr());
- writePS(" ");
- dumpColorSpaceL2(state, separationCS->getAlt(), false, false, false);
- writePS("\n");
- cvtFunction(separationCS->getFunc());
- writePS("]");
- if (genXform) {
- writePS(" {}");
+#ifdef OPI_SUPPORT
+void PSOutputDev::opiBegin(GfxState *state, Dict *opiDict)
+{
+ if (generateOPI) {
+ Object dict = opiDict->lookup("2.0");
+ if (dict.isDict()) {
+ opiBegin20(state, dict.getDict());
+ } else {
+ dict = opiDict->lookup("1.3");
+ if (dict.isDict()) {
+ opiBegin13(state, dict.getDict());
+ }
+ }
}
- if (updateColors) {
- addCustomColor(separationCS);
+}
+
+void PSOutputDev::opiBegin20(GfxState *state, Dict *dict)
+{
+ double width, height, left, right, top, bottom;
+ int w, h;
+
+ writePS("%%BeginOPI: 2.0\n");
+ writePS("%%Distilled\n");
+
+ Object obj1 = dict->lookup("F");
+ Object obj2 = getFileSpecName(&obj1);
+ if (obj2.isString()) {
+ writePSFmt("%%ImageFileName: {0:t}\n", obj2.getString());
}
- break;
- case csDeviceN:
- deviceNCS = (GfxDeviceNColorSpace *)colorSpace;
- if (level == psLevel3 || level == psLevel3Sep) {
- writePS("[/DeviceN\n");
- writePS(" [ ");
- for (i = 0; i < deviceNCS->getNComps(); i++) {
- writePSString(deviceNCS->getColorantName(i));
- writePS(" ");
- }
- writePS("]\n");
- dumpColorSpaceL2(state, deviceNCS->getAlt(), false, updateColors, false);
- writePS("\n");
- cvtFunction(deviceNCS->getTintTransformFunc(), map01 && deviceNCS->getAlt()->getMode() == csLab);
- writePS("]\n");
- if (genXform) {
- writePS(" {}");
- }
- } else {
- // DeviceN color spaces are a Level 3 PostScript feature.
- dumpColorSpaceL2(state, deviceNCS->getAlt(), false, updateColors, map01);
- if (genXform) {
- writePS(" ");
- cvtFunction(deviceNCS->getTintTransformFunc());
- }
+ obj1 = dict->lookup("MainImage");
+ if (obj1.isString()) {
+ writePSFmt("%%MainImage: {0:t}\n", obj1.getString());
+ }
+
+ //~ ignoring 'Tags' entry
+ //~ need to use writePSString() and deal with >255-char lines
+
+ obj1 = dict->lookup("Size");
+ if (obj1.isArray() && obj1.arrayGetLength() == 2) {
+ obj2 = obj1.arrayGet(0);
+ width = obj2.getNum();
+ obj2 = obj1.arrayGet(1);
+ height = obj2.getNum();
+ writePSFmt("%%ImageDimensions: {0:.6g} {1:.6g}\n", width, height);
+ }
+
+ obj1 = dict->lookup("CropRect");
+ if (obj1.isArray() && obj1.arrayGetLength() == 4) {
+ obj2 = obj1.arrayGet(0);
+ left = obj2.getNum();
+ obj2 = obj1.arrayGet(1);
+ top = obj2.getNum();
+ obj2 = obj1.arrayGet(2);
+ right = obj2.getNum();
+ obj2 = obj1.arrayGet(3);
+ bottom = obj2.getNum();
+ writePSFmt("%%ImageCropRect: {0:.6g} {1:.6g} {2:.6g} {3:.6g}\n", left, top, right, bottom);
+ }
+
+ obj1 = dict->lookup("Overprint");
+ if (obj1.isBool()) {
+ writePSFmt("%%ImageOverprint: {0:s}\n", obj1.getBool() ? "true" : "false");
+ }
+
+ obj1 = dict->lookup("Inks");
+ if (obj1.isName()) {
+ writePSFmt("%%ImageInks: {0:s}\n", obj1.getName());
+ } else if (obj1.isArray() && obj1.arrayGetLength() >= 1) {
+ obj2 = obj1.arrayGet(0);
+ if (obj2.isName()) {
+ writePSFmt("%%ImageInks: {0:s} {1:d}", obj2.getName(), (obj1.arrayGetLength() - 1) / 2);
+ for (int i = 1; i + 1 < obj1.arrayGetLength(); i += 2) {
+ Object obj3 = obj1.arrayGet(i);
+ Object obj4 = obj1.arrayGet(i + 1);
+ if (obj3.isString() && obj4.isNum()) {
+ writePS(" ");
+ writePSString(obj3.getString()->toStr());
+ writePSFmt(" {0:.6g}", obj4.getNum());
+ }
+ }
+ writePS("\n");
+ }
}
- break;
- case csPattern:
- //~ unimplemented
- break;
- }
-}
+ writePS("gsave\n");
-#ifdef OPI_SUPPORT
-void PSOutputDev::opiBegin(GfxState *state, Dict *opiDict) {
- if (generateOPI) {
- Object dict = opiDict->lookup("2.0");
- if (dict.isDict()) {
- opiBegin20(state, dict.getDict());
- } else {
- dict = opiDict->lookup("1.3");
- if (dict.isDict()) {
- opiBegin13(state, dict.getDict());
- }
+ writePS("%%BeginIncludedImage\n");
+
+ obj1 = dict->lookup("IncludedImageDimensions");
+ if (obj1.isArray() && obj1.arrayGetLength() == 2) {
+ obj2 = obj1.arrayGet(0);
+ w = obj2.getInt();
+ obj2 = obj1.arrayGet(1);
+ h = obj2.getInt();
+ writePSFmt("%%IncludedImageDimensions: {0:d} {1:d}\n", w, h);
+ }
+
+ obj1 = dict->lookup("IncludedImageQuality");
+ if (obj1.isNum()) {
+ writePSFmt("%%IncludedImageQuality: {0:.6g}\n", obj1.getNum());
}
- }
-}
-void PSOutputDev::opiBegin20(GfxState *state, Dict *dict) {
- double width, height, left, right, top, bottom;
- int w, h;
-
- writePS("%%BeginOPI: 2.0\n");
- writePS("%%Distilled\n");
-
- Object obj1 = dict->lookup("F");
- Object obj2 = getFileSpecName(&obj1);
- if (obj2.isString()) {
- writePSFmt("%%ImageFileName: {0:t}\n", obj2.getString());
- }
-
- obj1 = dict->lookup("MainImage");
- if (obj1.isString()) {
- writePSFmt("%%MainImage: {0:t}\n", obj1.getString());
- }
-
- //~ ignoring 'Tags' entry
- //~ need to use writePSString() and deal with >255-char lines
-
- obj1 = dict->lookup("Size");
- if (obj1.isArray() && obj1.arrayGetLength() == 2) {
- obj2 = obj1.arrayGet(0);
- width = obj2.getNum();
- obj2 = obj1.arrayGet(1);
- height = obj2.getNum();
- writePSFmt("%%ImageDimensions: {0:.6g} {1:.6g}\n", width, height);
- }
-
- obj1 = dict->lookup("CropRect");
- if (obj1.isArray() && obj1.arrayGetLength() == 4) {
- obj2 = obj1.arrayGet(0);
- left = obj2.getNum();
- obj2 = obj1.arrayGet(1);
- top = obj2.getNum();
- obj2 = obj1.arrayGet(2);
- right = obj2.getNum();
- obj2 = obj1.arrayGet(3);
- bottom = obj2.getNum();
- writePSFmt("%%ImageCropRect: {0:.6g} {1:.6g} {2:.6g} {3:.6g}\n",
- left, top, right, bottom);
- }
-
- obj1 = dict->lookup("Overprint");
- if (obj1.isBool()) {
- writePSFmt("%%ImageOverprint: {0:s}\n", obj1.getBool() ? "true" : "false");
- }
-
- obj1 = dict->lookup("Inks");
- if (obj1.isName()) {
- writePSFmt("%%ImageInks: {0:s}\n", obj1.getName());
- } else if (obj1.isArray() && obj1.arrayGetLength() >= 1) {
- obj2 = obj1.arrayGet(0);
- if (obj2.isName()) {
- writePSFmt("%%ImageInks: {0:s} {1:d}",
- obj2.getName(), (obj1.arrayGetLength() - 1) / 2);
- for (int i = 1; i+1 < obj1.arrayGetLength(); i += 2) {
- Object obj3 = obj1.arrayGet(i);
- Object obj4 = obj1.arrayGet(i+1);
- if (obj3.isString() && obj4.isNum()) {
- writePS(" ");
- writePSString(obj3.getString()->toStr());
- writePSFmt(" {0:.6g}", obj4.getNum());
- }
- }
- writePS("\n");
- }
- }
-
- writePS("gsave\n");
-
- writePS("%%BeginIncludedImage\n");
-
- obj1 = dict->lookup("IncludedImageDimensions");
- if (obj1.isArray() && obj1.arrayGetLength() == 2) {
- obj2 = obj1.arrayGet(0);
- w = obj2.getInt();
- obj2 = obj1.arrayGet(1);
- h = obj2.getInt();
- writePSFmt("%%IncludedImageDimensions: {0:d} {1:d}\n", w, h);
- }
-
- obj1 = dict->lookup("IncludedImageQuality");
- if (obj1.isNum()) {
- writePSFmt("%%IncludedImageQuality: {0:.6g}\n", obj1.getNum());
- }
-
- ++opi20Nest;
+ ++opi20Nest;
}
-void PSOutputDev::opiBegin13(GfxState *state, Dict *dict) {
- int left, right, top, bottom, samples, bits, width, height;
- double c, m, y, k;
- double llx, lly, ulx, uly, urx, ury, lrx, lry;
- double tllx, tlly, tulx, tuly, turx, tury, tlrx, tlry;
- double horiz, vert;
- int i, j;
-
- writePS("save\n");
- writePS("/opiMatrix2 matrix currentmatrix def\n");
- writePS("opiMatrix setmatrix\n");
-
- Object obj1 = dict->lookup("F");
- Object obj2 = getFileSpecName(&obj1);
- if (obj2.isString()) {
- writePSFmt("%ALDImageFileName: {0:t}\n", obj2.getString());
- }
-
- obj1 = dict->lookup("CropRect");
- if (obj1.isArray() && obj1.arrayGetLength() == 4) {
- obj2 = obj1.arrayGet(0);
- left = obj2.getInt();
- obj2 = obj1.arrayGet(1);
- top = obj2.getInt();
- obj2 = obj1.arrayGet(2);
- right = obj2.getInt();
- obj2 = obj1.arrayGet(3);
- bottom = obj2.getInt();
- writePSFmt("%ALDImageCropRect: {0:d} {1:d} {2:d} {3:d}\n",
- left, top, right, bottom);
- }
-
- obj1 = dict->lookup("Color");
- if (obj1.isArray() && obj1.arrayGetLength() == 5) {
- obj2 = obj1.arrayGet(0);
- c = obj2.getNum();
- obj2 = obj1.arrayGet(1);
- m = obj2.getNum();
- obj2 = obj1.arrayGet(2);
- y = obj2.getNum();
- obj2 = obj1.arrayGet(3);
- k = obj2.getNum();
- obj2 = obj1.arrayGet(4);
+void PSOutputDev::opiBegin13(GfxState *state, Dict *dict)
+{
+ int left, right, top, bottom, samples, bits, width, height;
+ double c, m, y, k;
+ double llx, lly, ulx, uly, urx, ury, lrx, lry;
+ double tllx, tlly, tulx, tuly, turx, tury, tlrx, tlry;
+ double horiz, vert;
+ int i, j;
+
+ writePS("save\n");
+ writePS("/opiMatrix2 matrix currentmatrix def\n");
+ writePS("opiMatrix setmatrix\n");
+
+ Object obj1 = dict->lookup("F");
+ Object obj2 = getFileSpecName(&obj1);
if (obj2.isString()) {
- writePSFmt("%ALDImageColor: {0:.4g} {1:.4g} {2:.4g} {3:.4g} ",
- c, m, y, k);
- writePSString(obj2.getString()->toStr());
- writePS("\n");
- }
- }
-
- obj1 = dict->lookup("ColorType");
- if (obj1.isName()) {
- writePSFmt("%ALDImageColorType: {0:s}\n", obj1.getName());
- }
-
- //~ ignores 'Comments' entry
- //~ need to handle multiple lines
-
- obj1 = dict->lookup("CropFixed");
- if (obj1.isArray()) {
- obj2 = obj1.arrayGet(0);
- ulx = obj2.getNum();
- obj2 = obj1.arrayGet(1);
- uly = obj2.getNum();
- obj2 = obj1.arrayGet(2);
- lrx = obj2.getNum();
- obj2 = obj1.arrayGet(3);
- lry = obj2.getNum();
- writePSFmt("%ALDImageCropFixed: {0:.6g} {1:.6g} {2:.6g} {3:.6g}\n",
- ulx, uly, lrx, lry);
- }
-
- obj1 = dict->lookup("GrayMap");
- if (obj1.isArray()) {
- writePS("%ALDImageGrayMap:");
- for (i = 0; i < obj1.arrayGetLength(); i += 16) {
- if (i > 0) {
- writePS("\n%%+");
- }
- for (j = 0; j < 16 && i+j < obj1.arrayGetLength(); ++j) {
- obj2 = obj1.arrayGet(i+j);
- writePSFmt(" {0:d}", obj2.getInt());
- }
+ writePSFmt("%ALDImageFileName: {0:t}\n", obj2.getString());
+ }
+
+ obj1 = dict->lookup("CropRect");
+ if (obj1.isArray() && obj1.arrayGetLength() == 4) {
+ obj2 = obj1.arrayGet(0);
+ left = obj2.getInt();
+ obj2 = obj1.arrayGet(1);
+ top = obj2.getInt();
+ obj2 = obj1.arrayGet(2);
+ right = obj2.getInt();
+ obj2 = obj1.arrayGet(3);
+ bottom = obj2.getInt();
+ writePSFmt("%ALDImageCropRect: {0:d} {1:d} {2:d} {3:d}\n", left, top, right, bottom);
+ }
+
+ obj1 = dict->lookup("Color");
+ if (obj1.isArray() && obj1.arrayGetLength() == 5) {
+ obj2 = obj1.arrayGet(0);
+ c = obj2.getNum();
+ obj2 = obj1.arrayGet(1);
+ m = obj2.getNum();
+ obj2 = obj1.arrayGet(2);
+ y = obj2.getNum();
+ obj2 = obj1.arrayGet(3);
+ k = obj2.getNum();
+ obj2 = obj1.arrayGet(4);
+ if (obj2.isString()) {
+ writePSFmt("%ALDImageColor: {0:.4g} {1:.4g} {2:.4g} {3:.4g} ", c, m, y, k);
+ writePSString(obj2.getString()->toStr());
+ writePS("\n");
+ }
}
- writePS("\n");
- }
-
- obj1 = dict->lookup("ID");
- if (obj1.isString()) {
- writePSFmt("%ALDImageID: {0:t}\n", obj1.getString());
- }
-
- obj1 = dict->lookup("ImageType");
- if (obj1.isArray() && obj1.arrayGetLength() == 2) {
- obj2 = obj1.arrayGet(0);
- samples = obj2.getInt();
- obj2 = obj1.arrayGet(1);
- bits = obj2.getInt();
- writePSFmt("%ALDImageType: {0:d} {1:d}\n", samples, bits);
- }
-
- dict->lookup("Overprint");
- if (obj1.isBool()) {
- writePSFmt("%ALDImageOverprint: {0:s}\n",
- obj1.getBool() ? "true" : "false");
- }
-
- obj1 = dict->lookup("Position");
- if (obj1.isArray() && obj1.arrayGetLength() == 8) {
- obj2 = obj1.arrayGet(0);
- llx = obj2.getNum();
- obj2 = obj1.arrayGet(1);
- lly = obj2.getNum();
- obj2 = obj1.arrayGet(2);
- ulx = obj2.getNum();
- obj2 = obj1.arrayGet(3);
- uly = obj2.getNum();
- obj2 = obj1.arrayGet(4);
- urx = obj2.getNum();
- obj2 = obj1.arrayGet(5);
- ury = obj2.getNum();
- obj2 = obj1.arrayGet(6);
- lrx = obj2.getNum();
- obj2 = obj1.arrayGet(7);
- lry = obj2.getNum();
- opiTransform(state, llx, lly, &tllx, &tlly);
- opiTransform(state, ulx, uly, &tulx, &tuly);
- opiTransform(state, urx, ury, &turx, &tury);
- opiTransform(state, lrx, lry, &tlrx, &tlry);
- writePSFmt("%ALDImagePosition: {0:.6g} {1:.6g} {2:.6g} {3:.6g} {4:.6g} {5:.6g} {6:.6g} {7:.6g}\n",
- tllx, tlly, tulx, tuly, turx, tury, tlrx, tlry);
- }
-
- obj1 = dict->lookup("Resolution");
- if (obj1.isArray() && obj1.arrayGetLength() == 2) {
- obj2 = obj1.arrayGet(0);
- horiz = obj2.getNum();
- obj2 = obj1.arrayGet(1);
- vert = obj2.getNum();
- writePSFmt("%ALDImageResoution: {0:.6g} {1:.6g}\n", horiz, vert);
- }
-
- obj1 = dict->lookup("Size");
- if (obj1.isArray() && obj1.arrayGetLength() == 2) {
- obj2 = obj1.arrayGet(0);
- width = obj2.getInt();
- obj2 = obj1.arrayGet(1);
- height = obj2.getInt();
- writePSFmt("%ALDImageDimensions: {0:d} {1:d}\n", width, height);
- }
-
- //~ ignoring 'Tags' entry
- //~ need to use writePSString() and deal with >255-char lines
-
- obj1 = dict->lookup("Tint");
- if (obj1.isNum()) {
- writePSFmt("%ALDImageTint: {0:.6g}\n", obj1.getNum());
- }
-
- obj1 = dict->lookup("Transparency");
- if (obj1.isBool()) {
- writePSFmt("%ALDImageTransparency: {0:s}\n",
- obj1.getBool() ? "true" : "false");
- }
-
- writePS("%%BeginObject: image\n");
- writePS("opiMatrix2 setmatrix\n");
- ++opi13Nest;
+
+ obj1 = dict->lookup("ColorType");
+ if (obj1.isName()) {
+ writePSFmt("%ALDImageColorType: {0:s}\n", obj1.getName());
+ }
+
+ //~ ignores 'Comments' entry
+ //~ need to handle multiple lines
+
+ obj1 = dict->lookup("CropFixed");
+ if (obj1.isArray()) {
+ obj2 = obj1.arrayGet(0);
+ ulx = obj2.getNum();
+ obj2 = obj1.arrayGet(1);
+ uly = obj2.getNum();
+ obj2 = obj1.arrayGet(2);
+ lrx = obj2.getNum();
+ obj2 = obj1.arrayGet(3);
+ lry = obj2.getNum();
+ writePSFmt("%ALDImageCropFixed: {0:.6g} {1:.6g} {2:.6g} {3:.6g}\n", ulx, uly, lrx, lry);
+ }
+
+ obj1 = dict->lookup("GrayMap");
+ if (obj1.isArray()) {
+ writePS("%ALDImageGrayMap:");
+ for (i = 0; i < obj1.arrayGetLength(); i += 16) {
+ if (i > 0) {
+ writePS("\n%%+");
+ }
+ for (j = 0; j < 16 && i + j < obj1.arrayGetLength(); ++j) {
+ obj2 = obj1.arrayGet(i + j);
+ writePSFmt(" {0:d}", obj2.getInt());
+ }
+ }
+ writePS("\n");
+ }
+
+ obj1 = dict->lookup("ID");
+ if (obj1.isString()) {
+ writePSFmt("%ALDImageID: {0:t}\n", obj1.getString());
+ }
+
+ obj1 = dict->lookup("ImageType");
+ if (obj1.isArray() && obj1.arrayGetLength() == 2) {
+ obj2 = obj1.arrayGet(0);
+ samples = obj2.getInt();
+ obj2 = obj1.arrayGet(1);
+ bits = obj2.getInt();
+ writePSFmt("%ALDImageType: {0:d} {1:d}\n", samples, bits);
+ }
+
+ dict->lookup("Overprint");
+ if (obj1.isBool()) {
+ writePSFmt("%ALDImageOverprint: {0:s}\n", obj1.getBool() ? "true" : "false");
+ }
+
+ obj1 = dict->lookup("Position");
+ if (obj1.isArray() && obj1.arrayGetLength() == 8) {
+ obj2 = obj1.arrayGet(0);
+ llx = obj2.getNum();
+ obj2 = obj1.arrayGet(1);
+ lly = obj2.getNum();
+ obj2 = obj1.arrayGet(2);
+ ulx = obj2.getNum();
+ obj2 = obj1.arrayGet(3);
+ uly = obj2.getNum();
+ obj2 = obj1.arrayGet(4);
+ urx = obj2.getNum();
+ obj2 = obj1.arrayGet(5);
+ ury = obj2.getNum();
+ obj2 = obj1.arrayGet(6);
+ lrx = obj2.getNum();
+ obj2 = obj1.arrayGet(7);
+ lry = obj2.getNum();
+ opiTransform(state, llx, lly, &tllx, &tlly);
+ opiTransform(state, ulx, uly, &tulx, &tuly);
+ opiTransform(state, urx, ury, &turx, &tury);
+ opiTransform(state, lrx, lry, &tlrx, &tlry);
+ writePSFmt("%ALDImagePosition: {0:.6g} {1:.6g} {2:.6g} {3:.6g} {4:.6g} {5:.6g} {6:.6g} {7:.6g}\n", tllx, tlly, tulx, tuly, turx, tury, tlrx, tlry);
+ }
+
+ obj1 = dict->lookup("Resolution");
+ if (obj1.isArray() && obj1.arrayGetLength() == 2) {
+ obj2 = obj1.arrayGet(0);
+ horiz = obj2.getNum();
+ obj2 = obj1.arrayGet(1);
+ vert = obj2.getNum();
+ writePSFmt("%ALDImageResoution: {0:.6g} {1:.6g}\n", horiz, vert);
+ }
+
+ obj1 = dict->lookup("Size");
+ if (obj1.isArray() && obj1.arrayGetLength() == 2) {
+ obj2 = obj1.arrayGet(0);
+ width = obj2.getInt();
+ obj2 = obj1.arrayGet(1);
+ height = obj2.getInt();
+ writePSFmt("%ALDImageDimensions: {0:d} {1:d}\n", width, height);
+ }
+
+ //~ ignoring 'Tags' entry
+ //~ need to use writePSString() and deal with >255-char lines
+
+ obj1 = dict->lookup("Tint");
+ if (obj1.isNum()) {
+ writePSFmt("%ALDImageTint: {0:.6g}\n", obj1.getNum());
+ }
+
+ obj1 = dict->lookup("Transparency");
+ if (obj1.isBool()) {
+ writePSFmt("%ALDImageTransparency: {0:s}\n", obj1.getBool() ? "true" : "false");
+ }
+
+ writePS("%%BeginObject: image\n");
+ writePS("opiMatrix2 setmatrix\n");
+ ++opi13Nest;
}
// Convert PDF user space coordinates to PostScript default user space
// coordinates. This has to account for both the PDF CTM and the
// PSOutputDev page-fitting transform.
-void PSOutputDev::opiTransform(GfxState *state, double x0, double y0,
- double *x1, double *y1) {
- double t;
-
- state->transform(x0, y0, x1, y1);
- *x1 += tx;
- *y1 += ty;
- if (rotate == 90) {
- t = *x1;
- *x1 = -*y1;
- *y1 = t;
- } else if (rotate == 180) {
- *x1 = -*x1;
- *y1 = -*y1;
- } else if (rotate == 270) {
- t = *x1;
- *x1 = *y1;
- *y1 = -t;
- }
- *x1 *= xScale;
- *y1 *= yScale;
+void PSOutputDev::opiTransform(GfxState *state, double x0, double y0, double *x1, double *y1)
+{
+ double t;
+
+ state->transform(x0, y0, x1, y1);
+ *x1 += tx;
+ *y1 += ty;
+ if (rotate == 90) {
+ t = *x1;
+ *x1 = -*y1;
+ *y1 = t;
+ } else if (rotate == 180) {
+ *x1 = -*x1;
+ *y1 = -*y1;
+ } else if (rotate == 270) {
+ t = *x1;
+ *x1 = *y1;
+ *y1 = -t;
+ }
+ *x1 *= xScale;
+ *y1 *= yScale;
}
-void PSOutputDev::opiEnd(GfxState *state, Dict *opiDict) {
- if (generateOPI) {
- Object dict = opiDict->lookup("2.0");
- if (dict.isDict()) {
- writePS("%%EndIncludedImage\n");
- writePS("%%EndOPI\n");
- writePS("grestore\n");
- --opi20Nest;
- } else {
- dict = opiDict->lookup("1.3");
- if (dict.isDict()) {
- writePS("%%EndObject\n");
- writePS("restore\n");
- --opi13Nest;
- }
- }
- }
+void PSOutputDev::opiEnd(GfxState *state, Dict *opiDict)
+{
+ if (generateOPI) {
+ Object dict = opiDict->lookup("2.0");
+ if (dict.isDict()) {
+ writePS("%%EndIncludedImage\n");
+ writePS("%%EndOPI\n");
+ writePS("grestore\n");
+ --opi20Nest;
+ } else {
+ dict = opiDict->lookup("1.3");
+ if (dict.isDict()) {
+ writePS("%%EndObject\n");
+ writePS("restore\n");
+ --opi13Nest;
+ }
+ }
+ }
}
#endif // OPI_SUPPORT
-void PSOutputDev::type3D0(GfxState *state, double wx, double wy) {
- writePSFmt("{0:.6g} {1:.6g} setcharwidth\n", wx, wy);
- writePS("q\n");
- t3NeedsRestore = true;
+void PSOutputDev::type3D0(GfxState *state, double wx, double wy)
+{
+ writePSFmt("{0:.6g} {1:.6g} setcharwidth\n", wx, wy);
+ writePS("q\n");
+ t3NeedsRestore = true;
}
-void PSOutputDev::type3D1(GfxState *state, double wx, double wy,
- double llx, double lly, double urx, double ury) {
- t3WX = wx;
- t3WY = wy;
- t3LLX = llx;
- t3LLY = lly;
- t3URX = urx;
- t3URY = ury;
- t3String = new GooString();
- writePS("q\n");
- t3FillColorOnly = true;
- t3Cacheable = true;
- t3NeedsRestore = true;
+void PSOutputDev::type3D1(GfxState *state, double wx, double wy, double llx, double lly, double urx, double ury)
+{
+ t3WX = wx;
+ t3WY = wy;
+ t3LLX = llx;
+ t3LLY = lly;
+ t3URX = urx;
+ t3URY = ury;
+ t3String = new GooString();
+ writePS("q\n");
+ t3FillColorOnly = true;
+ t3Cacheable = true;
+ t3NeedsRestore = true;
}
-void PSOutputDev::drawForm(Ref ref) {
- writePSFmt("f_{0:d}_{1:d}\n", ref.num, ref.gen);
+void PSOutputDev::drawForm(Ref ref)
+{
+ writePSFmt("f_{0:d}_{1:d}\n", ref.num, ref.gen);
}
-void PSOutputDev::psXObject(Stream *psStream, Stream *level1Stream) {
- Stream *str;
- int c;
-
- if ((level == psLevel1 || level == psLevel1Sep) && level1Stream) {
- str = level1Stream;
- } else {
- str = psStream;
- }
- str->reset();
- while ((c = str->getChar()) != EOF) {
- writePSChar(c);
- }
- str->close();
+void PSOutputDev::psXObject(Stream *psStream, Stream *level1Stream)
+{
+ Stream *str;
+ int c;
+
+ if ((level == psLevel1 || level == psLevel1Sep) && level1Stream) {
+ str = level1Stream;
+ } else {
+ str = psStream;
+ }
+ str->reset();
+ while ((c = str->getChar()) != EOF) {
+ writePSChar(c);
+ }
+ str->close();
}
//~ can nextFunc be reset to 0 -- maybe at the start of each page?
//~ or maybe at the start of each color space / pattern?
-void PSOutputDev::cvtFunction(const Function *func, bool invertPSFunction) {
- const SampledFunction *func0;
- const ExponentialFunction *func2;
- const StitchingFunction *func3;
- const PostScriptFunction *func4;
- int thisFunc, m, n, nSamples, i, j, k;
+void PSOutputDev::cvtFunction(const Function *func, bool invertPSFunction)
+{
+ const SampledFunction *func0;
+ const ExponentialFunction *func2;
+ const StitchingFunction *func3;
+ const PostScriptFunction *func4;
+ int thisFunc, m, n, nSamples, i, j, k;
- switch (func->getType()) {
+ switch (func->getType()) {
- case -1: // identity
- writePS("{}\n");
- break;
+ case -1: // identity
+ writePS("{}\n");
+ break;
- case 0: // sampled
- func0 = (const SampledFunction *)func;
- thisFunc = nextFunc++;
- m = func0->getInputSize();
- n = func0->getOutputSize();
- nSamples = n;
- for (i = 0; i < m; ++i) {
- nSamples *= func0->getSampleSize(i);
- }
- writePSFmt("/xpdfSamples{0:d} [\n", thisFunc);
- for (i = 0; i < nSamples; ++i) {
- writePSFmt("{0:.6g}\n", func0->getSamples()[i]);
- }
- writePS("] def\n");
- writePSFmt("{{ {0:d} array {1:d} array {2:d} 2 roll\n", 2*m, m, m+2);
- // [e01] [efrac] x0 x1 ... xm-1
- for (i = m-1; i >= 0; --i) {
- // [e01] [efrac] x0 x1 ... xi
- writePSFmt("{0:.6g} sub {1:.6g} mul {2:.6g} add\n",
- func0->getDomainMin(i),
- (func0->getEncodeMax(i) - func0->getEncodeMin(i)) /
- (func0->getDomainMax(i) - func0->getDomainMin(i)),
- func0->getEncodeMin(i));
- // [e01] [efrac] x0 x1 ... xi-1 xi'
- writePSFmt("dup 0 lt {{ pop 0 }} {{ dup {0:d} gt {{ pop {1:d} }} if }} ifelse\n",
- func0->getSampleSize(i) - 1, func0->getSampleSize(i) - 1);
- // [e01] [efrac] x0 x1 ... xi-1 xi'
- writePS("dup floor cvi exch dup ceiling cvi exch 2 index sub\n");
- // [e01] [efrac] x0 x1 ... xi-1 floor(xi') ceiling(xi') xi'-floor(xi')
- writePSFmt("{0:d} index {1:d} 3 2 roll put\n", i+3, i);
- // [e01] [efrac] x0 x1 ... xi-1 floor(xi') ceiling(xi')
- writePSFmt("{0:d} index {1:d} 3 2 roll put\n", i+3, 2*i+1);
- // [e01] [efrac] x0 x1 ... xi-1 floor(xi')
- writePSFmt("{0:d} index {1:d} 3 2 roll put\n", i+2, 2*i);
- // [e01] [efrac] x0 x1 ... xi-1
- }
- // [e01] [efrac]
- for (i = 0; i < n; ++i) {
- // [e01] [efrac] y(0) ... y(i-1)
- for (j = 0; j < (1<<m); ++j) {
- // [e01] [efrac] y(0) ... y(i-1) s(0) s(1) ... s(j-1)
- writePSFmt("xpdfSamples{0:d}\n", thisFunc);
- k = m - 1;
- writePSFmt("{0:d} index {1:d} get\n", i+j+2, 2 * k + ((j >> k) & 1));
- for (k = m - 2; k >= 0; --k) {
- writePSFmt("{0:d} mul {1:d} index {2:d} get add\n",
- func0->getSampleSize(k),
- i + j + 3,
- 2 * k + ((j >> k) & 1));
- }
- if (n > 1) {
- writePSFmt("{0:d} mul {1:d} add ", n, i);
- }
- writePS("get\n");
- }
- // [e01] [efrac] y(0) ... y(i-1) s(0) s(1) ... s(2^m-1)
- for (j = 0; j < m; ++j) {
- // [e01] [efrac] y(0) ... y(i-1) s(0) s(1) ... s(2^(m-j)-1)
- for (k = 0; k < (1 << (m - j)); k += 2) {
- // [e01] [efrac] y(0) ... y(i-1) <k/2 s' values> <2^(m-j)-k s values>
- writePSFmt("{0:d} index {1:d} get dup\n",
- i + k/2 + (1 << (m-j)) - k, j);
- writePS("3 2 roll mul exch 1 exch sub 3 2 roll mul add\n");
- writePSFmt("{0:d} 1 roll\n", k/2 + (1 << (m-j)) - k - 1);
- }
- // [e01] [efrac] s'(0) s'(1) ... s(2^(m-j-1)-1)
- }
- // [e01] [efrac] y(0) ... y(i-1) s
- writePSFmt("{0:.6g} mul {1:.6g} add\n",
- func0->getDecodeMax(i) - func0->getDecodeMin(i),
- func0->getDecodeMin(i));
- writePSFmt("dup {0:.6g} lt {{ pop {1:.6g} }} {{ dup {2:.6g} gt {{ pop {3:.6g} }} if }} ifelse\n",
- func0->getRangeMin(i), func0->getRangeMin(i),
- func0->getRangeMax(i), func0->getRangeMax(i));
- // [e01] [efrac] y(0) ... y(i-1) y(i)
- }
- // [e01] [efrac] y(0) ... y(n-1)
- writePSFmt("{0:d} {1:d} roll pop pop \n", n+2, n);
- if (invertPSFunction) {
- for (i = 0; i < n; ++i) {
- writePSFmt("{0:d} -1 roll ", n);
- writePSFmt("{0:.6g} sub {1:.6g} div ", func0->getRangeMin(i), func0->getRangeMax(i) - func0->getRangeMin(i));
- }
- }
- writePS("}\n");
- break;
+ case 0: // sampled
+ func0 = (const SampledFunction *)func;
+ thisFunc = nextFunc++;
+ m = func0->getInputSize();
+ n = func0->getOutputSize();
+ nSamples = n;
+ for (i = 0; i < m; ++i) {
+ nSamples *= func0->getSampleSize(i);
+ }
+ writePSFmt("/xpdfSamples{0:d} [\n", thisFunc);
+ for (i = 0; i < nSamples; ++i) {
+ writePSFmt("{0:.6g}\n", func0->getSamples()[i]);
+ }
+ writePS("] def\n");
+ writePSFmt("{{ {0:d} array {1:d} array {2:d} 2 roll\n", 2 * m, m, m + 2);
+ // [e01] [efrac] x0 x1 ... xm-1
+ for (i = m - 1; i >= 0; --i) {
+ // [e01] [efrac] x0 x1 ... xi
+ writePSFmt("{0:.6g} sub {1:.6g} mul {2:.6g} add\n", func0->getDomainMin(i), (func0->getEncodeMax(i) - func0->getEncodeMin(i)) / (func0->getDomainMax(i) - func0->getDomainMin(i)), func0->getEncodeMin(i));
+ // [e01] [efrac] x0 x1 ... xi-1 xi'
+ writePSFmt("dup 0 lt {{ pop 0 }} {{ dup {0:d} gt {{ pop {1:d} }} if }} ifelse\n", func0->getSampleSize(i) - 1, func0->getSampleSize(i) - 1);
+ // [e01] [efrac] x0 x1 ... xi-1 xi'
+ writePS("dup floor cvi exch dup ceiling cvi exch 2 index sub\n");
+ // [e01] [efrac] x0 x1 ... xi-1 floor(xi') ceiling(xi') xi'-floor(xi')
+ writePSFmt("{0:d} index {1:d} 3 2 roll put\n", i + 3, i);
+ // [e01] [efrac] x0 x1 ... xi-1 floor(xi') ceiling(xi')
+ writePSFmt("{0:d} index {1:d} 3 2 roll put\n", i + 3, 2 * i + 1);
+ // [e01] [efrac] x0 x1 ... xi-1 floor(xi')
+ writePSFmt("{0:d} index {1:d} 3 2 roll put\n", i + 2, 2 * i);
+ // [e01] [efrac] x0 x1 ... xi-1
+ }
+ // [e01] [efrac]
+ for (i = 0; i < n; ++i) {
+ // [e01] [efrac] y(0) ... y(i-1)
+ for (j = 0; j < (1 << m); ++j) {
+ // [e01] [efrac] y(0) ... y(i-1) s(0) s(1) ... s(j-1)
+ writePSFmt("xpdfSamples{0:d}\n", thisFunc);
+ k = m - 1;
+ writePSFmt("{0:d} index {1:d} get\n", i + j + 2, 2 * k + ((j >> k) & 1));
+ for (k = m - 2; k >= 0; --k) {
+ writePSFmt("{0:d} mul {1:d} index {2:d} get add\n", func0->getSampleSize(k), i + j + 3, 2 * k + ((j >> k) & 1));
+ }
+ if (n > 1) {
+ writePSFmt("{0:d} mul {1:d} add ", n, i);
+ }
+ writePS("get\n");
+ }
+ // [e01] [efrac] y(0) ... y(i-1) s(0) s(1) ... s(2^m-1)
+ for (j = 0; j < m; ++j) {
+ // [e01] [efrac] y(0) ... y(i-1) s(0) s(1) ... s(2^(m-j)-1)
+ for (k = 0; k < (1 << (m - j)); k += 2) {
+ // [e01] [efrac] y(0) ... y(i-1) <k/2 s' values> <2^(m-j)-k s values>
+ writePSFmt("{0:d} index {1:d} get dup\n", i + k / 2 + (1 << (m - j)) - k, j);
+ writePS("3 2 roll mul exch 1 exch sub 3 2 roll mul add\n");
+ writePSFmt("{0:d} 1 roll\n", k / 2 + (1 << (m - j)) - k - 1);
+ }
+ // [e01] [efrac] s'(0) s'(1) ... s(2^(m-j-1)-1)
+ }
+ // [e01] [efrac] y(0) ... y(i-1) s
+ writePSFmt("{0:.6g} mul {1:.6g} add\n", func0->getDecodeMax(i) - func0->getDecodeMin(i), func0->getDecodeMin(i));
+ writePSFmt("dup {0:.6g} lt {{ pop {1:.6g} }} {{ dup {2:.6g} gt {{ pop {3:.6g} }} if }} ifelse\n", func0->getRangeMin(i), func0->getRangeMin(i), func0->getRangeMax(i), func0->getRangeMax(i));
+ // [e01] [efrac] y(0) ... y(i-1) y(i)
+ }
+ // [e01] [efrac] y(0) ... y(n-1)
+ writePSFmt("{0:d} {1:d} roll pop pop \n", n + 2, n);
+ if (invertPSFunction) {
+ for (i = 0; i < n; ++i) {
+ writePSFmt("{0:d} -1 roll ", n);
+ writePSFmt("{0:.6g} sub {1:.6g} div ", func0->getRangeMin(i), func0->getRangeMax(i) - func0->getRangeMin(i));
+ }
+ }
+ writePS("}\n");
+ break;
- case 2: // exponential
- func2 = (const ExponentialFunction *)func;
- n = func2->getOutputSize();
- writePSFmt("{{ dup {0:.6g} lt {{ pop {1:.6g} }} {{ dup {2:.6g} gt {{ pop {3:.6g} }} if }} ifelse\n",
- func2->getDomainMin(0), func2->getDomainMin(0),
- func2->getDomainMax(0), func2->getDomainMax(0));
- // x
- for (i = 0; i < n; ++i) {
- // x y(0) .. y(i-1)
- writePSFmt("{0:d} index {1:.6g} exp {2:.6g} mul {3:.6g} add\n",
- i, func2->getE(), func2->getC1()[i] - func2->getC0()[i],
- func2->getC0()[i]);
- if (func2->getHasRange()) {
- writePSFmt("dup {0:.6g} lt {{ pop {1:.6g} }} {{ dup {2:.6g} gt {{ pop {3:.6g} }} if }} ifelse\n",
- func2->getRangeMin(i), func2->getRangeMin(i),
- func2->getRangeMax(i), func2->getRangeMax(i));
- }
- }
- // x y(0) .. y(n-1)
- writePSFmt("{0:d} {1:d} roll pop \n", n+1, n);
- if (invertPSFunction && func2->getHasRange()) {
- for (i = 0; i < n; ++i) {
- writePSFmt("{0:d} -1 roll ", n);
- writePSFmt("{0:.6g} sub {1:.6g} div ", func2->getRangeMin(i), func2->getRangeMax(i) - func2->getRangeMin(i));
- }
- }
- writePS("}\n");
- break;
+ case 2: // exponential
+ func2 = (const ExponentialFunction *)func;
+ n = func2->getOutputSize();
+ writePSFmt("{{ dup {0:.6g} lt {{ pop {1:.6g} }} {{ dup {2:.6g} gt {{ pop {3:.6g} }} if }} ifelse\n", func2->getDomainMin(0), func2->getDomainMin(0), func2->getDomainMax(0), func2->getDomainMax(0));
+ // x
+ for (i = 0; i < n; ++i) {
+ // x y(0) .. y(i-1)
+ writePSFmt("{0:d} index {1:.6g} exp {2:.6g} mul {3:.6g} add\n", i, func2->getE(), func2->getC1()[i] - func2->getC0()[i], func2->getC0()[i]);
+ if (func2->getHasRange()) {
+ writePSFmt("dup {0:.6g} lt {{ pop {1:.6g} }} {{ dup {2:.6g} gt {{ pop {3:.6g} }} if }} ifelse\n", func2->getRangeMin(i), func2->getRangeMin(i), func2->getRangeMax(i), func2->getRangeMax(i));
+ }
+ }
+ // x y(0) .. y(n-1)
+ writePSFmt("{0:d} {1:d} roll pop \n", n + 1, n);
+ if (invertPSFunction && func2->getHasRange()) {
+ for (i = 0; i < n; ++i) {
+ writePSFmt("{0:d} -1 roll ", n);
+ writePSFmt("{0:.6g} sub {1:.6g} div ", func2->getRangeMin(i), func2->getRangeMax(i) - func2->getRangeMin(i));
+ }
+ }
+ writePS("}\n");
+ break;
- case 3: // stitching
- func3 = (const StitchingFunction *)func;
- thisFunc = nextFunc++;
- for (i = 0; i < func3->getNumFuncs(); ++i) {
- cvtFunction(func3->getFunc(i));
- writePSFmt("/xpdfFunc{0:d}_{1:d} exch def\n", thisFunc, i);
- }
- writePSFmt("{{ dup {0:.6g} lt {{ pop {1:.6g} }} {{ dup {2:.6g} gt {{ pop {3:.6g} }} if }} ifelse\n",
- func3->getDomainMin(0), func3->getDomainMin(0),
- func3->getDomainMax(0), func3->getDomainMax(0));
- for (i = 0; i < func3->getNumFuncs() - 1; ++i) {
- writePSFmt("dup {0:.6g} lt {{ {1:.6g} sub {2:.6g} mul {3:.6g} add xpdfFunc{4:d}_{5:d} }} {{\n",
- func3->getBounds()[i+1],
- func3->getBounds()[i],
- func3->getScale()[i],
- func3->getEncode()[2*i],
- thisFunc, i);
- }
- writePSFmt("{0:.6g} sub {1:.6g} mul {2:.6g} add xpdfFunc{3:d}_{4:d}\n",
- func3->getBounds()[i],
- func3->getScale()[i],
- func3->getEncode()[2*i],
- thisFunc, i);
- for (i = 0; i < func3->getNumFuncs() - 1; ++i) {
- writePS("} ifelse\n");
- }
- if (invertPSFunction && func3->getHasRange()) {
- n = func3->getOutputSize();
- for (i = 0; i < n; ++i) {
- writePSFmt("{0:d} -1 roll ", n);
- writePSFmt("{0:.6g} sub {1:.6g} div ", func3->getRangeMin(i), func3->getRangeMax(i) - func3->getRangeMin(i));
- }
- }
- writePS("}\n");
- break;
+ case 3: // stitching
+ func3 = (const StitchingFunction *)func;
+ thisFunc = nextFunc++;
+ for (i = 0; i < func3->getNumFuncs(); ++i) {
+ cvtFunction(func3->getFunc(i));
+ writePSFmt("/xpdfFunc{0:d}_{1:d} exch def\n", thisFunc, i);
+ }
+ writePSFmt("{{ dup {0:.6g} lt {{ pop {1:.6g} }} {{ dup {2:.6g} gt {{ pop {3:.6g} }} if }} ifelse\n", func3->getDomainMin(0), func3->getDomainMin(0), func3->getDomainMax(0), func3->getDomainMax(0));
+ for (i = 0; i < func3->getNumFuncs() - 1; ++i) {
+ writePSFmt("dup {0:.6g} lt {{ {1:.6g} sub {2:.6g} mul {3:.6g} add xpdfFunc{4:d}_{5:d} }} {{\n", func3->getBounds()[i + 1], func3->getBounds()[i], func3->getScale()[i], func3->getEncode()[2 * i], thisFunc, i);
+ }
+ writePSFmt("{0:.6g} sub {1:.6g} mul {2:.6g} add xpdfFunc{3:d}_{4:d}\n", func3->getBounds()[i], func3->getScale()[i], func3->getEncode()[2 * i], thisFunc, i);
+ for (i = 0; i < func3->getNumFuncs() - 1; ++i) {
+ writePS("} ifelse\n");
+ }
+ if (invertPSFunction && func3->getHasRange()) {
+ n = func3->getOutputSize();
+ for (i = 0; i < n; ++i) {
+ writePSFmt("{0:d} -1 roll ", n);
+ writePSFmt("{0:.6g} sub {1:.6g} div ", func3->getRangeMin(i), func3->getRangeMax(i) - func3->getRangeMin(i));
+ }
+ }
+ writePS("}\n");
+ break;
- case 4: // PostScript
- func4 = (const PostScriptFunction *)func;
- if (invertPSFunction) {
- GooString *codeString = new GooString(func4->getCodeString());
- for (i = codeString->getLength() -1; i > 0; i--) {
- if (codeString->getChar(i) == '}') {
- codeString->del(i);
- break;
- }
- }
- writePS(codeString->c_str());
- writePS("\n");
- delete codeString;
- n = func4->getOutputSize();
- for (i = 0; i < n; ++i) {
- writePSFmt("{0:d} -1 roll ", n);
- writePSFmt("{0:.6g} sub {1:.6g} div ", func4->getRangeMin(i), func4->getRangeMax(i) - func4->getRangeMin(i));
- }
- writePS("}\n");
- } else {
- writePS(func4->getCodeString()->c_str());
- writePS("\n");
+ case 4: // PostScript
+ func4 = (const PostScriptFunction *)func;
+ if (invertPSFunction) {
+ GooString *codeString = new GooString(func4->getCodeString());
+ for (i = codeString->getLength() - 1; i > 0; i--) {
+ if (codeString->getChar(i) == '}') {
+ codeString->del(i);
+ break;
+ }
+ }
+ writePS(codeString->c_str());
+ writePS("\n");
+ delete codeString;
+ n = func4->getOutputSize();
+ for (i = 0; i < n; ++i) {
+ writePSFmt("{0:d} -1 roll ", n);
+ writePSFmt("{0:.6g} sub {1:.6g} div ", func4->getRangeMin(i), func4->getRangeMax(i) - func4->getRangeMin(i));
+ }
+ writePS("}\n");
+ } else {
+ writePS(func4->getCodeString()->c_str());
+ writePS("\n");
+ }
+ break;
}
- break;
- }
}
-void PSOutputDev::writePSChar(char c) {
- if (t3String) {
- t3String->append(c);
- } else {
- (*outputFunc)(outputStream, &c, 1);
- }
+void PSOutputDev::writePSChar(char c)
+{
+ if (t3String) {
+ t3String->append(c);
+ } else {
+ (*outputFunc)(outputStream, &c, 1);
+ }
}
-void PSOutputDev::writePS(const char *s) {
- if (t3String) {
- t3String->append(s);
- } else {
- (*outputFunc)(outputStream, s, strlen(s));
- }
+void PSOutputDev::writePS(const char *s)
+{
+ if (t3String) {
+ t3String->append(s);
+ } else {
+ (*outputFunc)(outputStream, s, strlen(s));
+ }
}
-void PSOutputDev::writePSBuf(const char *s, int len) {
- if (t3String) {
- for (int i = 0; i < len; i++) {
- t3String->append(s[i]);
+void PSOutputDev::writePSBuf(const char *s, int len)
+{
+ if (t3String) {
+ for (int i = 0; i < len; i++) {
+ t3String->append(s[i]);
+ }
+ } else {
+ (*outputFunc)(outputStream, s, len);
}
- } else {
- (*outputFunc)(outputStream, s, len);
- }
}
-void PSOutputDev::writePSFmt(const char *fmt, ...) {
- va_list args;
- GooString *buf;
-
- va_start(args, fmt);
- if (t3String) {
- t3String->appendfv((char *)fmt, args);
- } else {
- buf = GooString::formatv((char *)fmt, args);
- (*outputFunc)(outputStream, buf->c_str(), buf->getLength());
- delete buf;
- }
- va_end(args);
-}
+void PSOutputDev::writePSFmt(const char *fmt, ...)
+{
+ va_list args;
+ GooString *buf;
-void PSOutputDev::writePSString(const std::string &s) {
- unsigned char *p;
- int n, line;
- char buf[8];
-
- writePSChar('(');
- line = 1;
- for (p = (unsigned char *)s.c_str(), n = s.size(); n; ++p, --n) {
- if (line >= 64) {
- writePSChar('\\');
- writePSChar('\n');
- line = 0;
- }
- if (*p == '(' || *p == ')' || *p == '\\') {
- writePSChar('\\');
- writePSChar((char)*p);
- line += 2;
- } else if (*p < 0x20 || *p >= 0x80) {
- sprintf(buf, "\\%03o", *p);
- writePS(buf);
- line += 4;
+ va_start(args, fmt);
+ if (t3String) {
+ t3String->appendfv((char *)fmt, args);
} else {
- writePSChar((char)*p);
- ++line;
+ buf = GooString::formatv((char *)fmt, args);
+ (*outputFunc)(outputStream, buf->c_str(), buf->getLength());
+ delete buf;
}
- }
- writePSChar(')');
+ va_end(args);
}
-void PSOutputDev::writePSName(const char *s) {
- const char *p;
- char c;
-
- p = s;
- while ((c = *p++)) {
- if (c <= (char)0x20 || c >= (char)0x7f ||
- c == '(' || c == ')' || c == '<' || c == '>' ||
- c == '[' || c == ']' || c == '{' || c == '}' ||
- c == '/' || c == '%' || c == '\\') {
- writePSFmt("#{0:02x}", c & 0xff);
- } else {
- writePSChar(c);
+void PSOutputDev::writePSString(const std::string &s)
+{
+ unsigned char *p;
+ int n, line;
+ char buf[8];
+
+ writePSChar('(');
+ line = 1;
+ for (p = (unsigned char *)s.c_str(), n = s.size(); n; ++p, --n) {
+ if (line >= 64) {
+ writePSChar('\\');
+ writePSChar('\n');
+ line = 0;
+ }
+ if (*p == '(' || *p == ')' || *p == '\\') {
+ writePSChar('\\');
+ writePSChar((char)*p);
+ line += 2;
+ } else if (*p < 0x20 || *p >= 0x80) {
+ sprintf(buf, "\\%03o", *p);
+ writePS(buf);
+ line += 4;
+ } else {
+ writePSChar((char)*p);
+ ++line;
+ }
}
- }
+ writePSChar(')');
}
-GooString *PSOutputDev::filterPSName(const GooString *name) {
- GooString *name2;
- char buf[8];
- int i;
- char c;
-
- name2 = new GooString();
-
- // ghostscript chokes on names that begin with out-of-limits
- // numbers, e.g., 1e4foo is handled correctly (as a name), but
- // 1e999foo generates a limitcheck error
- c = name->getChar(0);
- if (c >= '0' && c <= '9') {
- name2->append('f');
- }
-
- for (i = 0; i < name->getLength(); ++i) {
- c = name->getChar(i);
- if (c <= (char)0x20 || c >= (char)0x7f ||
- c == '(' || c == ')' || c == '<' || c == '>' ||
- c == '[' || c == ']' || c == '{' || c == '}' ||
- c == '/' || c == '%') {
- sprintf(buf, "#%02x", c & 0xff);
- name2->append(buf);
- } else {
- name2->append(c);
+void PSOutputDev::writePSName(const char *s)
+{
+ const char *p;
+ char c;
+
+ p = s;
+ while ((c = *p++)) {
+ if (c <= (char)0x20 || c >= (char)0x7f || c == '(' || c == ')' || c == '<' || c == '>' || c == '[' || c == ']' || c == '{' || c == '}' || c == '/' || c == '%' || c == '\\') {
+ writePSFmt("#{0:02x}", c & 0xff);
+ } else {
+ writePSChar(c);
+ }
+ }
+}
+
+GooString *PSOutputDev::filterPSName(const GooString *name)
+{
+ GooString *name2;
+ char buf[8];
+ int i;
+ char c;
+
+ name2 = new GooString();
+
+ // ghostscript chokes on names that begin with out-of-limits
+ // numbers, e.g., 1e4foo is handled correctly (as a name), but
+ // 1e999foo generates a limitcheck error
+ c = name->getChar(0);
+ if (c >= '0' && c <= '9') {
+ name2->append('f');
+ }
+
+ for (i = 0; i < name->getLength(); ++i) {
+ c = name->getChar(i);
+ if (c <= (char)0x20 || c >= (char)0x7f || c == '(' || c == ')' || c == '<' || c == '>' || c == '[' || c == ']' || c == '{' || c == '}' || c == '/' || c == '%') {
+ sprintf(buf, "#%02x", c & 0xff);
+ name2->append(buf);
+ } else {
+ name2->append(c);
+ }
}
- }
- return name2;
+ return name2;
}
// Convert GooString to GooString, with appropriate escaping
// of things that can't appear in a label
// This is heavily based on the writePSTextLine() method
-GooString* PSOutputDev::filterPSLabel(GooString *label, bool *needParens) {
- int i, step;
- bool isNumeric;
-
- // - DSC comments must be printable ASCII; control chars and
- // backslashes have to be escaped (we do cheap UCS2-to-ASCII
- // conversion by simply ignoring the high byte)
- // - parentheses are escaped. this isn't strictly necessary for matched
- // parentheses, but shouldn't be a problem
- // - lines are limited to 255 chars (we limit to 200 here to allow
- // for the keyword, which was emitted by the caller)
-
- GooString *label2 = new GooString();
- int labelLength = label->getLength();
-
- if (labelLength == 0) {
- isNumeric = false;
- } else {
- // this gets changed later if we find a non-numeric character
- isNumeric = true;
- }
-
- if ( (labelLength >= 2) &&
- ( (label->getChar(0) & 0xff) == 0xfe) &&
- ( (label->getChar(1) & 0xff) == 0xff) ) {
- // UCS2 mode
- i = 3;
- step = 2;
- if ( (label->getChar(labelLength-1) == 0) ) {
- // prune the trailing null (0x000 for UCS2)
- labelLength -= 2;
- }
- } else {
- i = 0;
- step = 1;
- }
- for (int j = 0; i < labelLength && j < 200; i += step) {
- char c = label->getChar(i);
- if ( (c < '0') || (c > '9') ) {
- isNumeric = false;
- }
- if (c == '\\') {
- label2->append("\\\\");
- j += 2;
- } else if (c == ')') {
- label2->append("\\)");
- } else if (c == '(') {
- label2->append("\\(");
- } else if (c < 0x20 || c > 0x7e) {
- GooString *aux = GooString::format("\\{0:03o}", c);
- label2->append(aux);
- j += 4;
- delete aux;
+GooString *PSOutputDev::filterPSLabel(GooString *label, bool *needParens)
+{
+ int i, step;
+ bool isNumeric;
+
+ // - DSC comments must be printable ASCII; control chars and
+ // backslashes have to be escaped (we do cheap UCS2-to-ASCII
+ // conversion by simply ignoring the high byte)
+ // - parentheses are escaped. this isn't strictly necessary for matched
+ // parentheses, but shouldn't be a problem
+ // - lines are limited to 255 chars (we limit to 200 here to allow
+ // for the keyword, which was emitted by the caller)
+
+ GooString *label2 = new GooString();
+ int labelLength = label->getLength();
+
+ if (labelLength == 0) {
+ isNumeric = false;
} else {
- label2->append(c);
- ++j;
- }
- }
- if (needParens) {
- *needParens = !(isNumeric);
- }
- return label2;
+ // this gets changed later if we find a non-numeric character
+ isNumeric = true;
+ }
+
+ if ((labelLength >= 2) && ((label->getChar(0) & 0xff) == 0xfe) && ((label->getChar(1) & 0xff) == 0xff)) {
+ // UCS2 mode
+ i = 3;
+ step = 2;
+ if ((label->getChar(labelLength - 1) == 0)) {
+ // prune the trailing null (0x000 for UCS2)
+ labelLength -= 2;
+ }
+ } else {
+ i = 0;
+ step = 1;
+ }
+ for (int j = 0; i < labelLength && j < 200; i += step) {
+ char c = label->getChar(i);
+ if ((c < '0') || (c > '9')) {
+ isNumeric = false;
+ }
+ if (c == '\\') {
+ label2->append("\\\\");
+ j += 2;
+ } else if (c == ')') {
+ label2->append("\\)");
+ } else if (c == '(') {
+ label2->append("\\(");
+ } else if (c < 0x20 || c > 0x7e) {
+ GooString *aux = GooString::format("\\{0:03o}", c);
+ label2->append(aux);
+ j += 4;
+ delete aux;
+ } else {
+ label2->append(c);
+ ++j;
+ }
+ }
+ if (needParens) {
+ *needParens = !(isNumeric);
+ }
+ return label2;
}
// Write a DSC-compliant <textline>.
-void PSOutputDev::writePSTextLine(const GooString *s) {
- int i, j, step;
- int c;
-
- // - DSC comments must be printable ASCII; control chars and
- // backslashes have to be escaped (we do cheap Unicode-to-ASCII
- // conversion by simply ignoring the high byte)
- // - lines are limited to 255 chars (we limit to 200 here to allow
- // for the keyword, which was emitted by the caller)
- // - lines that start with a left paren are treated as <text>
- // instead of <textline>, so we escape a leading paren
- if (s->getLength() >= 2 &&
- (s->getChar(0) & 0xff) == 0xfe &&
- (s->getChar(1) & 0xff) == 0xff) {
- i = 3;
- step = 2;
- } else {
- i = 0;
- step = 1;
- }
- for (j = 0; i < s->getLength() && j < 200; i += step) {
- c = s->getChar(i) & 0xff;
- if (c == '\\') {
- writePS("\\\\");
- j += 2;
- } else if (c < 0x20 || c > 0x7e || (j == 0 && c == '(')) {
- writePSFmt("\\{0:03o}", c);
- j += 4;
+void PSOutputDev::writePSTextLine(const GooString *s)
+{
+ int i, j, step;
+ int c;
+
+ // - DSC comments must be printable ASCII; control chars and
+ // backslashes have to be escaped (we do cheap Unicode-to-ASCII
+ // conversion by simply ignoring the high byte)
+ // - lines are limited to 255 chars (we limit to 200 here to allow
+ // for the keyword, which was emitted by the caller)
+ // - lines that start with a left paren are treated as <text>
+ // instead of <textline>, so we escape a leading paren
+ if (s->getLength() >= 2 && (s->getChar(0) & 0xff) == 0xfe && (s->getChar(1) & 0xff) == 0xff) {
+ i = 3;
+ step = 2;
} else {
- writePSChar(c);
- ++j;
+ i = 0;
+ step = 1;
+ }
+ for (j = 0; i < s->getLength() && j < 200; i += step) {
+ c = s->getChar(i) & 0xff;
+ if (c == '\\') {
+ writePS("\\\\");
+ j += 2;
+ } else if (c < 0x20 || c > 0x7e || (j == 0 && c == '(')) {
+ writePSFmt("\\{0:03o}", c);
+ j += 4;
+ } else {
+ writePSChar(c);
+ ++j;
+ }
}
- }
- writePS("\n");
+ writePS("\n");
}