diff options
Diffstat (limited to 'Master/tlpkg/tlgs/Resource/Init')
50 files changed, 1785 insertions, 914 deletions
diff --git a/Master/tlpkg/tlgs/Resource/Init/FCOfontmap-PCLPS2 b/Master/tlpkg/tlgs/Resource/Init/FCOfontmap-PCLPS2 index c54e61d16e1..91bd8f7fa26 100644 --- a/Master/tlpkg/tlgs/Resource/Init/FCOfontmap-PCLPS2 +++ b/Master/tlpkg/tlgs/Resource/Init/FCOfontmap-PCLPS2 @@ -1,4 +1,4 @@ -% Copyright (C) 2001-2019 Artifex Software, Inc. +% Copyright (C) 2001-2020 Artifex Software, Inc. % All Rights Reserved. % % This software is provided AS-IS with no warranty, either express or diff --git a/Master/tlpkg/tlgs/Resource/Init/gs_agl.ps b/Master/tlpkg/tlgs/Resource/Init/gs_agl.ps index c30b631fac8..9c1c52d2afb 100644 --- a/Master/tlpkg/tlgs/Resource/Init/gs_agl.ps +++ b/Master/tlpkg/tlgs/Resource/Init/gs_agl.ps @@ -1,4 +1,4 @@ -% Copyright (C) 2001-2019 Artifex Software, Inc. +% Copyright (C) 2001-2020 Artifex Software, Inc. % All Rights Reserved. % % This software is provided AS-IS with no warranty, either express or diff --git a/Master/tlpkg/tlgs/Resource/Init/gs_btokn.ps b/Master/tlpkg/tlgs/Resource/Init/gs_btokn.ps index b9add38368a..410b8419154 100644 --- a/Master/tlpkg/tlgs/Resource/Init/gs_btokn.ps +++ b/Master/tlpkg/tlgs/Resource/Init/gs_btokn.ps @@ -1,4 +1,4 @@ -% Copyright (C) 2001-2019 Artifex Software, Inc. +% Copyright (C) 2001-2020 Artifex Software, Inc. % All Rights Reserved. % % This software is provided AS-IS with no warranty, either express or @@ -148,46 +148,36 @@ mark % worry about interrupts or callbacks when writing to the output file. % Define procedures for accumulating the space required to represent -% an object in binary form. The procedures for composite objects (arrays -% and dictionaries) leave different results on the stack: -% <#refs> <#chars> <simple_obj> -proc- <#refs> <#chars> -% <#refs> <#chars> <array|dict> -proc- <array|dict> <#refs> <#chars> -% This is required so that .writeobjects can also accumulate the actual -% list of composite objects to write in the binary object sequence. +% an object in binary form. +% <#refs> <#chars> <obj> -proc- <#refs'> <#chars'> /cntdict mark /integertype /pop load /realtype 1 index /marktype 1 index /nulltype 1 index /booleantype 1 index - /nametype { length add } bind + /nametype { length add } .bind /stringtype 1 index - /arraytype //null - /dicttype //null + /arraytype 0 % replaced below + /dicttype 0 % replaced below .dicttomark def -/.cntobj { % <<arguments and results as for procedures in cntdict>> +/.cntobj { dup type //cntdict exch get exec } .bind def cntdict /arraytype { - dup dup length 5 -1 roll add 4 2 roll { //.cntobj exec } forall -} bind put + dup length % #refs #chars array len + 4 -1 roll add % #chars array #refs+len + dup 65536 gt { + /writeobject .systemvar /limitcheck signalerror + } if + 3 1 roll % #refs+len #chars array + //.cntobj forall +} .bind put % replace arraytype in cntdict + cntdict /dicttype { - WRITEDICTS { - dup dup length 2 mul 5 -1 roll add 4 2 roll { - % We have to use .execn here, rather than simply rolling the - % value under the top elements, because key might involve arrays - % or dictionaries. - cvlit {//.cntobj exec} exch 2 .execn //.cntobj exec - } forall - } { - /writeobject .systemvar /typecheck signalerror - } ifelse + /writeobject .systemvar /typecheck signalerror } bind put -/w2dict mark - /nametype { 2 copy .writecvs pop } bind - /stringtype 1 index -.dicttomark def /.bosheader { % <top_length> <total_length> <string8> .bosheader % <string4|8> @@ -211,70 +201,74 @@ cntdict /dicttype { } .bind def /.writeobjects { % <file> <tag> <array> .writeobjects - - mark exch - - % Count the space required for refs and strings. + % Apply the tag early and forget about it. + (12345678) dup 1 5 -1 roll % file array (...) (...) 1 tag + put exch % file (.t.) array - dup length 0 3 -1 roll - % Stack: file tag -mark- #refs #chars array - dup 4 1 roll { //.cntobj exec } forall + % Calculate the space required for refs and strings. + % Reject excessively large graphs or graphs with loops. + 0 0 % file (.t.) array #refs #chars + 2 index //.cntobj exec % file (.t.) array #refs #chars - % Write the header. + % Write the header. + 1 index 8 mul add % file (.t.) array #refs #refs*8+#chars + 2 index length exch (12345678) % file (.t.) array #refs len(array) #refs*8+#chars (...) + //.bosheader exec % file (.t.) array #refs (...) + 4 index exch writestring % file (.t.) array #refs - % Stack: file tag -mark- array1 ... (array|dict)N #refs #chars - counttomark 3 add -2 roll 4 1 roll - % Stack: -mark- array1 ... (array|dict)N tag #refs #chars file - dup counttomark 1 sub index length - 4 index 3 bitshift 4 index add - (xxxxxxxx) //.bosheader exec writestring - - % Write the objects per se. - - 3 1 roll pop - counttomark 1 sub index length 3 bitshift exch - 3 bitshift - % Stack: -mark- array1 ... (array|dict)N tag file ref# char# - counttomark 4 sub { - counttomark -1 roll dup 6 1 roll - % Stack: ... objN tag file ref# char# objN - dup type /dicttype eq { % can't be first object - { 5 1 roll (x\000xxxxxx) .bosobject - 3 index exch writestring - 4 -1 roll (x\000xxxxxx) .bosobject - 3 index exch writestring + % Traverse an array tree in width-first order and place all the + % arrays that are found on the operand stack. Acyclic graphs are + % expanded to trees. The top parameter K indicates the number + % of arrays on a given depth level. At the root level, K is equal to 1. + mark 2 index 1 % file (.t.) array #refs -mark- array K + { dup 0 le { pop exit } if + dup { + dup index { + dup type /arraytype eq { + exch 1 add + } { + pop + } ifelse } forall - } { - { (x\000xxxxxx) .bosobject - dup 1 6 index put - 3 index exch writestring - 4 -1 roll pop 0 4 1 roll % clear tag - } forall - } ifelse - } repeat + 1 sub + } repeat + } loop % file (.t.) array #refs -mark- array1 ... arrayN + counttomark 5 add -4 roll % -mark- array1 ... arrayN file (.t.) array #refs - % Write the strings and names. + % Write the content of the root array + 8 mul % -mark- array1 ... arrayN file (.t.) array #refs*8 + exch dup length 8 mul % -mark- array1 ... arrayN file (.t.) #refs*8 array len(array)*8 + 3 1 roll % -mark- array1 ... arrayN file (.t.) len(array)*8 #refs*8 array + { 3 index % -mark- array1 ... arrayN file (.t.) len(array)*8 #refs*8 obj (.t.) + .bosobject % -mark- array1 ... arrayN file (.t.) len(array)*8 #refs*8 (.t.) + 4 index exch writestring % -mark- array1 ... arrayN file (.t.) len(array)*8 #refs*8 + } forall + 3 -1 roll pop % -mark- array1 ... arrayN file len(array)*8 #refs*8 - pop pop exch pop - % Stack: -mark- array1 ... array|dictN file - counttomark 1 sub { - counttomark -1 roll { - % The counting pass ensured that the keys and values - % of any dictionary must be writable objects. - % Hence, we are processing a dictionary iff - % the next-to-top stack element is not a file. - 1 index type /filetype ne { - exch 2 index exch dup type //w2dict exch .knownget - { exec } { pop } ifelse pop - } if - dup type //w2dict exch .knownget { exec } { pop } ifelse + % Write the remaining arrays + counttomark 2 sub -1 3 { + index { % ... file #refs #str obj + (1\000345678) .bosobject % ... file #refs #str (...) + 3 index exch writestring % ... file #refs #str } forall - } repeat + } for + pop pop % -mark- array1 ... arrayN file - % Clean up. - - % Stack: -mark- file - pop pop + % Write strings and names. + counttomark 1 sub -1 1 { + index { + dup type /nametype eq { + .namestring + } if + dup type /stringtype eq { + 1 index exch writestring + } { + pop + } ifelse + } forall + } for + cleartomark % Clean up } .bind def /.writeobject { @@ -324,7 +318,6 @@ cntdict /dicttype { } bind def currentdict /cntdict .undef -currentdict /w2dict .undef % End of level2dict diff --git a/Master/tlpkg/tlgs/Resource/Init/gs_cff.ps b/Master/tlpkg/tlgs/Resource/Init/gs_cff.ps index 99d214a64b6..6cfa1ec1323 100644 --- a/Master/tlpkg/tlgs/Resource/Init/gs_cff.ps +++ b/Master/tlpkg/tlgs/Resource/Init/gs_cff.ps @@ -1,4 +1,4 @@ -% Copyright (C) 2001-2019 Artifex Software, Inc. +% Copyright (C) 2001-2020 Artifex Software, Inc. % All Rights Reserved. % % This software is provided AS-IS with no warranty, either express or diff --git a/Master/tlpkg/tlgs/Resource/Init/gs_cidcm.ps b/Master/tlpkg/tlgs/Resource/Init/gs_cidcm.ps index 5ec2fa343ac..503ec867fbf 100644 --- a/Master/tlpkg/tlgs/Resource/Init/gs_cidcm.ps +++ b/Master/tlpkg/tlgs/Resource/Init/gs_cidcm.ps @@ -1,4 +1,4 @@ -% Copyright (C) 2001-2019 Artifex Software, Inc. +% Copyright (C) 2001-2020 Artifex Software, Inc. % All Rights Reserved. % % This software is provided AS-IS with no warranty, either express or diff --git a/Master/tlpkg/tlgs/Resource/Init/gs_ciddc.ps b/Master/tlpkg/tlgs/Resource/Init/gs_ciddc.ps index f0fb5d81c36..6cdba039084 100644 --- a/Master/tlpkg/tlgs/Resource/Init/gs_ciddc.ps +++ b/Master/tlpkg/tlgs/Resource/Init/gs_ciddc.ps @@ -1,4 +1,4 @@ -% Copyright (C) 2001-2019 Artifex Software, Inc. +% Copyright (C) 2001-2020 Artifex Software, Inc. % All Rights Reserved. % % This software is provided AS-IS with no warranty, either express or diff --git a/Master/tlpkg/tlgs/Resource/Init/gs_cidfm.ps b/Master/tlpkg/tlgs/Resource/Init/gs_cidfm.ps index 5eb25f0042f..f22e45d6d63 100644 --- a/Master/tlpkg/tlgs/Resource/Init/gs_cidfm.ps +++ b/Master/tlpkg/tlgs/Resource/Init/gs_cidfm.ps @@ -1,4 +1,4 @@ -% Copyright (C) 2001-2019 Artifex Software, Inc. +% Copyright (C) 2001-2020 Artifex Software, Inc. % All Rights Reserved. % % This software is provided AS-IS with no warranty, either express or @@ -120,7 +120,12 @@ currentdict end def (DroidSansFallback.ttf) } if } if - concatstrings + % If CIDFSubstFont looks like a path/file (rather than just file) + % use it without the CIDFSubstPath string + dup .file_name_directory_separator rsearch + {pop pop pop exch pop} + {pop concatstrings} + ifelse % The CSI data just has to be valid, the substition machinery will % generally overwrite it with appropriate values for the missing font. /CSI [(Identity) 0] @@ -136,7 +141,7 @@ currentdict end def % <dir.../base.extn> .basename <dir> /.splitdirname { (/) rsearch { //true } { (\\) rsearch } ifelse - {3 -2 roll pop pop //true}{//false} ifelse + {exch concatstrings exch pop //true}{//false} ifelse } bind def % <file> .addcidfmappath - @@ -209,7 +214,7 @@ currentdict end def } loop } forall currentdict end - {exch pop (/) concatstrings /PermitFileReading exch .addcontrolpath} forall + {exch pop /PermitFileReading exch .addcontrolpath} forall % Checks for vicious substitution cycles. dup length dict copy % <<map>> diff --git a/Master/tlpkg/tlgs/Resource/Init/gs_cidfn.ps b/Master/tlpkg/tlgs/Resource/Init/gs_cidfn.ps index ca2a5a7ca20..20af1c875df 100644 --- a/Master/tlpkg/tlgs/Resource/Init/gs_cidfn.ps +++ b/Master/tlpkg/tlgs/Resource/Init/gs_cidfn.ps @@ -1,4 +1,4 @@ -% Copyright (C) 2001-2019 Artifex Software, Inc. +% Copyright (C) 2001-2020 Artifex Software, Inc. % All Rights Reserved. % % This software is provided AS-IS with no warranty, either express or diff --git a/Master/tlpkg/tlgs/Resource/Init/gs_cidtt.ps b/Master/tlpkg/tlgs/Resource/Init/gs_cidtt.ps index 12ade5e5908..e045cfddc61 100644 --- a/Master/tlpkg/tlgs/Resource/Init/gs_cidtt.ps +++ b/Master/tlpkg/tlgs/Resource/Init/gs_cidtt.ps @@ -1,4 +1,4 @@ -% Copyright (C) 2001-2019 Artifex Software, Inc. +% Copyright (C) 2001-2020 Artifex Software, Inc. % All Rights Reserved. % % This software is provided AS-IS with no warranty, either express or diff --git a/Master/tlpkg/tlgs/Resource/Init/gs_cmap.ps b/Master/tlpkg/tlgs/Resource/Init/gs_cmap.ps index 2733ea3b14c..3252089ad07 100644 --- a/Master/tlpkg/tlgs/Resource/Init/gs_cmap.ps +++ b/Master/tlpkg/tlgs/Resource/Init/gs_cmap.ps @@ -1,4 +1,4 @@ -% Copyright (C) 2001-2019 Artifex Software, Inc. +% Copyright (C) 2001-2020 Artifex Software, Inc. % All Rights Reserved. % % This software is provided AS-IS with no warranty, either express or diff --git a/Master/tlpkg/tlgs/Resource/Init/gs_cspace.ps b/Master/tlpkg/tlgs/Resource/Init/gs_cspace.ps index ff5955a9577..8aaf6b74b13 100644 --- a/Master/tlpkg/tlgs/Resource/Init/gs_cspace.ps +++ b/Master/tlpkg/tlgs/Resource/Init/gs_cspace.ps @@ -1,4 +1,4 @@ -% Copyright (C) 2001-2019 Artifex Software, Inc. +% Copyright (C) 2001-2020 Artifex Software, Inc. % All Rights Reserved. % % This software is provided AS-IS with no warranty, either express or diff --git a/Master/tlpkg/tlgs/Resource/Init/gs_dbt_e.ps b/Master/tlpkg/tlgs/Resource/Init/gs_dbt_e.ps index 01e3c8240ba..2aca0c68a39 100644 --- a/Master/tlpkg/tlgs/Resource/Init/gs_dbt_e.ps +++ b/Master/tlpkg/tlgs/Resource/Init/gs_dbt_e.ps @@ -1,4 +1,4 @@ -% Copyright (C) 2001-2019 Artifex Software, Inc. +% Copyright (C) 2001-2020 Artifex Software, Inc. % All Rights Reserved. % % This software is provided AS-IS with no warranty, either express or diff --git a/Master/tlpkg/tlgs/Resource/Init/gs_diskn.ps b/Master/tlpkg/tlgs/Resource/Init/gs_diskn.ps index d3402782d81..85ff07e3748 100644 --- a/Master/tlpkg/tlgs/Resource/Init/gs_diskn.ps +++ b/Master/tlpkg/tlgs/Resource/Init/gs_diskn.ps @@ -1,4 +1,4 @@ -% Copyright (C) 2001-2019 Artifex Software, Inc. +% Copyright (C) 2001-2020 Artifex Software, Inc. % All Rights Reserved. % % This software is provided AS-IS with no warranty, either express or diff --git a/Master/tlpkg/tlgs/Resource/Init/gs_dps1.ps b/Master/tlpkg/tlgs/Resource/Init/gs_dps1.ps index 7cf29b46b81..14cc5d6d849 100644 --- a/Master/tlpkg/tlgs/Resource/Init/gs_dps1.ps +++ b/Master/tlpkg/tlgs/Resource/Init/gs_dps1.ps @@ -1,4 +1,4 @@ -% Copyright (C) 2001-2019 Artifex Software, Inc. +% Copyright (C) 2001-2020 Artifex Software, Inc. % All Rights Reserved. % % This software is provided AS-IS with no warranty, either express or diff --git a/Master/tlpkg/tlgs/Resource/Init/gs_dps2.ps b/Master/tlpkg/tlgs/Resource/Init/gs_dps2.ps index 619984f2fe1..2dfaaa49865 100644 --- a/Master/tlpkg/tlgs/Resource/Init/gs_dps2.ps +++ b/Master/tlpkg/tlgs/Resource/Init/gs_dps2.ps @@ -1,4 +1,4 @@ -% Copyright (C) 2001-2019 Artifex Software, Inc. +% Copyright (C) 2001-2020 Artifex Software, Inc. % All Rights Reserved. % % This software is provided AS-IS with no warranty, either express or diff --git a/Master/tlpkg/tlgs/Resource/Init/gs_dscp.ps b/Master/tlpkg/tlgs/Resource/Init/gs_dscp.ps index dad0ec30e2f..15764b1772a 100644 --- a/Master/tlpkg/tlgs/Resource/Init/gs_dscp.ps +++ b/Master/tlpkg/tlgs/Resource/Init/gs_dscp.ps @@ -1,4 +1,4 @@ -% Copyright (C) 2001-2019 Artifex Software, Inc. +% Copyright (C) 2001-2020 Artifex Software, Inc. % All Rights Reserved. % % This software is provided AS-IS with no warranty, either express or diff --git a/Master/tlpkg/tlgs/Resource/Init/gs_epsf.ps b/Master/tlpkg/tlgs/Resource/Init/gs_epsf.ps index b28f742ef88..cf020751a08 100644 --- a/Master/tlpkg/tlgs/Resource/Init/gs_epsf.ps +++ b/Master/tlpkg/tlgs/Resource/Init/gs_epsf.ps @@ -1,4 +1,4 @@ -% Copyright (C) 2001-2019 Artifex Software, Inc. +% Copyright (C) 2001-2020 Artifex Software, Inc. % All Rights Reserved. % % This software is provided AS-IS with no warranty, either express or @@ -59,41 +59,44 @@ % Rescale, translate and rotate to fit the BoundingBox on the page /EPSBoundingBoxFitPage { % llx lly urx ury -- EPSDEBUG { (gs_epsf.ps: Rescaling EPS to fit page\n) print flush } if - clippath pathbbox newpath - % translate to new origin at lower left of clippath - 3 index 3 index translate - % Figure out if rotate is needed. + clippath pathbbox newpath % ellx elly eurx eury pllx plly purx pury - 1 index 4 index sub 1 index 4 index sub eq not { - 1 index 4 index sub 1 index 4 index sub gt % bbox page-clipbox page-is-landscape - 6 index 10 index sub 6 index 10 index sub gt % bbox page-clipbox page-is-landscape bbox-is-landscape - xor - }{ - //false - }ifelse - dup 10 1 roll % need-rotate compute need-rotate. - - % if we are rotating the contents, we need to also rotate the - % bounding box of the content! - { - 8 -4 roll - exch 4 -2 roll exch 4 2 roll + % Convert box corners to coordinates of the center and box sizes + 2 { % loop doing the page coordinates, the the EPS bbox coordinates + 3 -1 roll exch % ... llx urx lly ury + 2 { % loop doing Y then X coordnates + 2 copy exch sub % ... llx urx lly ury ury-lly + 3 1 roll % ... llx urx ury-lly lly ury + add 2 div % ... llx urx ury-lly (lly+ury)/2 + 4 2 roll % ... ury-lly (lly+ury)/2 llx urx + } repeat 8 4 roll + } repeat + % edx, edy = EPS dimension X and Y, ecx, ecy = EPS Center X and Y. + % pdx and pcx, etc, are for the Page values. + % edx ecx edy ecy pdx pcx pdy pcy + + % Move the origin to the center of the printable area. + 3 -1 roll exch % edx ecx edy ecy pdx pdy pcx pcy + translate % edx ecx edy ecy pdx pdy + + % Find orientation of the best fit. Square pages or files don't rotate. + 2 copy sub % edx ecx edy ecy pdx pdy pdx-pdy + 6 index 5 index sub mul % edx ecx edy ecy pdx pdy (pdx-pdy)*(edx-edy) + 0 lt { + 90 rotate + exch } if - % stack: rotate-needed bbox page-clipbox - % calculate scale to fit smaller of width or height - exch 4 -1 roll sub 3 1 roll exch sub - 4 2 roll 5 index 5 index 4 2 roll - exch 4 -1 roll sub 3 1 roll exch sub - 4 2 roll - exch 4 -1 roll div 3 1 roll exch div - 1 index 1 index lt {pop}{exch pop} ifelse - dup scale - % translate to EPS -llx,-lly - exch neg exch neg translate - % Finally perform the rotate if needed. - { clippath pathbbox pop 0 translate 90 rotate pop pop } if + % Scale to fit in the most restricting direction. + 4 -1 roll div % edx ecx ecy pdx pdy/edy + exch 5 -1 roll div % ecx ecy pdy/edy pdx/edx + //.min exec + dup scale % ecx ecy + + % Center the document + neg exch neg exch translate + } bind executeonly odef /EPSBoundingBoxProcess { % (llx lly urx ury) state -- diff --git a/Master/tlpkg/tlgs/Resource/Init/gs_fapi.ps b/Master/tlpkg/tlgs/Resource/Init/gs_fapi.ps index 1ca3dff7b52..0b493c6a516 100644 --- a/Master/tlpkg/tlgs/Resource/Init/gs_fapi.ps +++ b/Master/tlpkg/tlgs/Resource/Init/gs_fapi.ps @@ -1,4 +1,4 @@ -% Copyright (C) 2001-2019 Artifex Software, Inc. +% Copyright (C) 2001-2020 Artifex Software, Inc. % All Rights Reserved. % % This software is provided AS-IS with no warranty, either express or diff --git a/Master/tlpkg/tlgs/Resource/Init/gs_fntem.ps b/Master/tlpkg/tlgs/Resource/Init/gs_fntem.ps index 66432e11e93..d5ac0bfa72f 100644 --- a/Master/tlpkg/tlgs/Resource/Init/gs_fntem.ps +++ b/Master/tlpkg/tlgs/Resource/Init/gs_fntem.ps @@ -1,4 +1,4 @@ -% Copyright (C) 2001-2019 Artifex Software, Inc. +% Copyright (C) 2001-2020 Artifex Software, Inc. % All Rights Reserved. % % This software is provided AS-IS with no warranty, either express or diff --git a/Master/tlpkg/tlgs/Resource/Init/gs_fonts.ps b/Master/tlpkg/tlgs/Resource/Init/gs_fonts.ps index 8e361552bc8..3f4f4af8066 100644 --- a/Master/tlpkg/tlgs/Resource/Init/gs_fonts.ps +++ b/Master/tlpkg/tlgs/Resource/Init/gs_fonts.ps @@ -1,4 +1,4 @@ -% Copyright (C) 2001-2019 Artifex Software, Inc. +% Copyright (C) 2001-2020 Artifex Software, Inc. % All Rights Reserved. % % This software is provided AS-IS with no warranty, either express or @@ -69,7 +69,7 @@ end def % <dir.../base.extn> .basename <dir> /.splitdirname { (/) rsearch { //true } { (\\) rsearch } ifelse - {3 -2 roll pop pop //true}{//false} ifelse + {exch concatstrings exch pop //true}{//false} ifelse } bind def % <dict> .addfontmappermitpaths @@ -1056,6 +1056,25 @@ $error /SubstituteFont { } put //false }ifelse + % If just opening the file didn't work, try opening the file name + % in the font resource directory + { + dup + //.fonttempstring /FontResourceDir getsystemparam .genericrfn + (r) { file } stopped { + pop pop //true + } { + dup .filename + { 3 -1 roll pop exch } + { pop } + ifelse + //false + } ifelse + } + { + //false + }ifelse + { QUIET not { (Can't find \(or can't open\) font file ) print dup print diff --git a/Master/tlpkg/tlgs/Resource/Init/gs_frsd.ps b/Master/tlpkg/tlgs/Resource/Init/gs_frsd.ps index c4ed1cb0b5e..74c1dd27788 100644 --- a/Master/tlpkg/tlgs/Resource/Init/gs_frsd.ps +++ b/Master/tlpkg/tlgs/Resource/Init/gs_frsd.ps @@ -1,4 +1,4 @@ -% Copyright (C) 2001-2019 Artifex Software, Inc. +% Copyright (C) 2001-2020 Artifex Software, Inc. % All Rights Reserved. % % This software is provided AS-IS with no warranty, either express or diff --git a/Master/tlpkg/tlgs/Resource/Init/gs_icc.ps b/Master/tlpkg/tlgs/Resource/Init/gs_icc.ps index 6a4e88a0f73..fac0cb25fab 100644 --- a/Master/tlpkg/tlgs/Resource/Init/gs_icc.ps +++ b/Master/tlpkg/tlgs/Resource/Init/gs_icc.ps @@ -1,4 +1,4 @@ -% Copyright (C) 2001-2019 Artifex Software, Inc. +% Copyright (C) 2001-2020 Artifex Software, Inc. % All Rights Reserved. % % This software is provided AS-IS with no warranty, either express or diff --git a/Master/tlpkg/tlgs/Resource/Init/gs_il1_e.ps b/Master/tlpkg/tlgs/Resource/Init/gs_il1_e.ps index 3de6ab5c950..f8cfff04ca4 100644 --- a/Master/tlpkg/tlgs/Resource/Init/gs_il1_e.ps +++ b/Master/tlpkg/tlgs/Resource/Init/gs_il1_e.ps @@ -1,4 +1,4 @@ -% Copyright (C) 2001-2019 Artifex Software, Inc. +% Copyright (C) 2001-2020 Artifex Software, Inc. % All Rights Reserved. % % This software is provided AS-IS with no warranty, either express or diff --git a/Master/tlpkg/tlgs/Resource/Init/gs_init.ps b/Master/tlpkg/tlgs/Resource/Init/gs_init.ps index 722b57c1e80..849e24ef129 100644 --- a/Master/tlpkg/tlgs/Resource/Init/gs_init.ps +++ b/Master/tlpkg/tlgs/Resource/Init/gs_init.ps @@ -1,4 +1,4 @@ -% Copyright (C) 2001-2019 Artifex Software, Inc. +% Copyright (C) 2001-2020 Artifex Software, Inc. % All Rights Reserved. % % This software is provided AS-IS with no warranty, either express or @@ -34,7 +34,7 @@ % Interpreter library version number % NOTE: the interpreter code requires that the first non-comment token % in this file be an integer, and that it match the compiled-in version! -950 +9530 % Check the interpreter revision. dup revision ne @@ -197,6 +197,11 @@ currentdict /NOSAFERERRORS known currentdict /SAFERERRORS known } ifelse def +currentdict /ALLOWPSTRANSPARENCY known not +{ + /ALLOWPSTRANSPARENCY //false def +} if + currentdict /SHORTERRORS known /SHORTERRORS exch def currentdict /TTYPAUSE known /TTYPAUSE exch def currentdict /WRITESYSTEMDICT known /WRITESYSTEMDICT exch def @@ -271,9 +276,9 @@ userdict /=string 256 string put (\)\n) revisiondate 10 mod revisiondate 10 idiv 10 mod (-) revisiondate 100 idiv 10 mod revisiondate 1000 idiv 10 mod (-) revisiondate 10000 idiv ( \() - revision 10 mod - revision 100 mod 10 idiv (.) - revision 100 idiv ( ) + revision 10 mod (.) + revision 1000 mod 10 idiv (.) + revision 1000 idiv ( ) product counttomark { (%stdout) (w) file exch 0 .writecvp @@ -315,7 +320,7 @@ DELAYBIND ( have selected DELAYBIND. Unless you use this option with\n) print ( care \(and specifically, remember to call .bindnow\) it is\n) print ( possible that malicious code may be able to evade the\n) print - ( limited security offered by the SAFER option.\n) print + ( limited security offered by the SAFER option.\n) print flush } if .currentglobal //false .setglobal systemdict /.delaybind 2000 array .forceput @@ -331,7 +336,7 @@ DELAYBIND { pop /.bind cvx exec } ifelse - } .bind def + } .bind odef } executeonly if .currentglobal //true .setglobal @@ -2201,6 +2206,18 @@ systemdict /EPSBoundingBoxInit .forceundef readonly def .setglobal +/SAFERUndefinePostScriptOperators { + [ + % Used by our own test suite files + /.setdotlength % Bug687720.ps + /.sort /.setdebug /.mementolistnewblocks /getenv + /unread + ] + {systemdict exch .forceundef} forall + + //systemdict /SAFERUndefinePostScriptOperators .forceundef +} .bind executeonly def % must be bound and hidden for .forceundef + /tempfilepaths [ (TMPDIR) getenv not @@ -2381,25 +2398,6 @@ currentdict /.locksafe_userparams .undef currentdict /.setsafeglobal .undef currentdict /.locksafeglobal .undef -SAFER { -/SAFERUndefinePostScriptOperators { - [ - % Used by our own test suite files - /.pushpdf14devicefilter % transparency-example.ps - /.poppdf14devicefilter % transparency-example.ps - /.setopacityalpha % transparency-example.ps - /.setshapealpha % transparency-example.ps - /.endtransparencygroup % transparency-example.ps - /.setdotlength % Bug687720.ps - /.sort /.setdebug /.mementolistnewblocks /getenv - /unread - ] - {systemdict exch .forceundef} forall - - //systemdict /SAFERUndefinePostScriptOperators .forceundef -} .bind executeonly def % must be bound and hidden for .forceundef -} if - %% ---------------- SAFER stuff END -------------------%% /UndefinePostScriptOperators { @@ -2648,9 +2646,6 @@ FontDirectory readonly pop % If we are using DELAYBIND we have to defer the undefinition % until .bindnow. DELAYBIND not { - SAFER { - //systemdict /SAFERUndefinePostScriptOperators get exec - } if //systemdict /UndefinePostScriptOperators get exec } if end @@ -2694,7 +2689,7 @@ WRITESYSTEMDICT { ( care and specifically, remember to execute code like:\n) print ( "systemdict readonly pop"\n) print ( it is possible that malicious code may be able to evade the\n) print - ( limited security offered by the SAFER option.\n) print + ( limited security offered by the SAFER option.\n) print flush }if } { diff --git a/Master/tlpkg/tlgs/Resource/Init/gs_lev2.ps b/Master/tlpkg/tlgs/Resource/Init/gs_lev2.ps index 0fd4164650a..fefa732b198 100644 --- a/Master/tlpkg/tlgs/Resource/Init/gs_lev2.ps +++ b/Master/tlpkg/tlgs/Resource/Init/gs_lev2.ps @@ -1,4 +1,4 @@ -% Copyright (C) 2001-2019 Artifex Software, Inc. +% Copyright (C) 2001-2020 Artifex Software, Inc. % All Rights Reserved. % % This software is provided AS-IS with no warranty, either express or @@ -660,7 +660,7 @@ currentuserparams /WaitTimeout known % Search for valid (iccprofiles) directory as a sibling to (Resource) % and set it as a default if found. LIBPATH { - (Resource) search { + (Resource) rsearch { exch pop exch pop (iccprofiles) concatstrings .file_name_separator concatstrings dup (default_gray.icc) concatstrings status { diff --git a/Master/tlpkg/tlgs/Resource/Init/gs_ll3.ps b/Master/tlpkg/tlgs/Resource/Init/gs_ll3.ps index 6caa93f8047..f6d98482164 100644 --- a/Master/tlpkg/tlgs/Resource/Init/gs_ll3.ps +++ b/Master/tlpkg/tlgs/Resource/Init/gs_ll3.ps @@ -1,4 +1,4 @@ -% Copyright (C) 2001-2019 Artifex Software, Inc. +% Copyright (C) 2001-2020 Artifex Software, Inc. % All Rights Reserved. % % This software is provided AS-IS with no warranty, either express or diff --git a/Master/tlpkg/tlgs/Resource/Init/gs_mex_e.ps b/Master/tlpkg/tlgs/Resource/Init/gs_mex_e.ps index 7b28360fb0d..dda0675cd85 100644 --- a/Master/tlpkg/tlgs/Resource/Init/gs_mex_e.ps +++ b/Master/tlpkg/tlgs/Resource/Init/gs_mex_e.ps @@ -1,4 +1,4 @@ -% Copyright (C) 2001-2019 Artifex Software, Inc. +% Copyright (C) 2001-2020 Artifex Software, Inc. % All Rights Reserved. % % This software is provided AS-IS with no warranty, either express or diff --git a/Master/tlpkg/tlgs/Resource/Init/gs_mgl_e.ps b/Master/tlpkg/tlgs/Resource/Init/gs_mgl_e.ps index 7c97efb95da..e02729b1c9a 100644 --- a/Master/tlpkg/tlgs/Resource/Init/gs_mgl_e.ps +++ b/Master/tlpkg/tlgs/Resource/Init/gs_mgl_e.ps @@ -1,4 +1,4 @@ -% Copyright (C) 2001-2019 Artifex Software, Inc. +% Copyright (C) 2001-2020 Artifex Software, Inc. % All Rights Reserved. % % This software is provided AS-IS with no warranty, either express or diff --git a/Master/tlpkg/tlgs/Resource/Init/gs_mro_e.ps b/Master/tlpkg/tlgs/Resource/Init/gs_mro_e.ps index f3f15430be7..7d0e3b7c284 100644 --- a/Master/tlpkg/tlgs/Resource/Init/gs_mro_e.ps +++ b/Master/tlpkg/tlgs/Resource/Init/gs_mro_e.ps @@ -1,4 +1,4 @@ -% Copyright (C) 2001-2019 Artifex Software, Inc. +% Copyright (C) 2001-2020 Artifex Software, Inc. % All Rights Reserved. % % This software is provided AS-IS with no warranty, either express or diff --git a/Master/tlpkg/tlgs/Resource/Init/gs_pdf_e.ps b/Master/tlpkg/tlgs/Resource/Init/gs_pdf_e.ps index 382542add99..172cd72c559 100644 --- a/Master/tlpkg/tlgs/Resource/Init/gs_pdf_e.ps +++ b/Master/tlpkg/tlgs/Resource/Init/gs_pdf_e.ps @@ -1,4 +1,4 @@ -% Copyright (C) 2001-2019 Artifex Software, Inc. +% Copyright (C) 2001-2020 Artifex Software, Inc. % All Rights Reserved. % % This software is provided AS-IS with no warranty, either express or diff --git a/Master/tlpkg/tlgs/Resource/Init/gs_pdfwr.ps b/Master/tlpkg/tlgs/Resource/Init/gs_pdfwr.ps index 422e66e1a6c..a53b8c3f88e 100644 --- a/Master/tlpkg/tlgs/Resource/Init/gs_pdfwr.ps +++ b/Master/tlpkg/tlgs/Resource/Init/gs_pdfwr.ps @@ -1,4 +1,4 @@ -% Copyright (C) 2001-2019 Artifex Software, Inc. +% Copyright (C) 2001-2020 Artifex Software, Inc. % All Rights Reserved. % % This software is provided AS-IS with no warranty, either express or @@ -86,7 +86,7 @@ languagelevel 2 .setlanguagelevel /MonoImageDownsampleThreshold 1.5 /MonoImageFilter /CCITTFaxEncode /OffOptimizations 0 - /OPM 1 + /OPM 0 /Optimize //true /ParseDSCComments //true /ParseDSCCommentsForDocInfo //true diff --git a/Master/tlpkg/tlgs/Resource/Init/gs_res.ps b/Master/tlpkg/tlgs/Resource/Init/gs_res.ps index 068514bf21f..18f63a30064 100644 --- a/Master/tlpkg/tlgs/Resource/Init/gs_res.ps +++ b/Master/tlpkg/tlgs/Resource/Init/gs_res.ps @@ -1,4 +1,4 @@ -% Copyright (C) 2001-2019 Artifex Software, Inc. +% Copyright (C) 2001-2020 Artifex Software, Inc. % All Rights Reserved. % % This software is provided AS-IS with no warranty, either express or @@ -284,7 +284,7 @@ systemdict begin dup .file_name_current eq { pop } { - (Resource) search { + (Resource) rsearch { exch concatstrings exch pop .file_name_separator concatstrings exit diff --git a/Master/tlpkg/tlgs/Resource/Init/gs_resmp.ps b/Master/tlpkg/tlgs/Resource/Init/gs_resmp.ps index ba17df60a3f..5ba4f43e760 100644 --- a/Master/tlpkg/tlgs/Resource/Init/gs_resmp.ps +++ b/Master/tlpkg/tlgs/Resource/Init/gs_resmp.ps @@ -1,4 +1,4 @@ -% Copyright (C) 2001-2019 Artifex Software, Inc. +% Copyright (C) 2001-2020 Artifex Software, Inc. % All Rights Reserved. % % This software is provided AS-IS with no warranty, either express or diff --git a/Master/tlpkg/tlgs/Resource/Init/gs_setpd.ps b/Master/tlpkg/tlgs/Resource/Init/gs_setpd.ps index 0733af0fbb6..51b26899979 100644 --- a/Master/tlpkg/tlgs/Resource/Init/gs_setpd.ps +++ b/Master/tlpkg/tlgs/Resource/Init/gs_setpd.ps @@ -1,4 +1,4 @@ -% Copyright (C) 2001-2019 Artifex Software, Inc. +% Copyright (C) 2001-2020 Artifex Software, Inc. % All Rights Reserved. % % This software is provided AS-IS with no warranty, either express or diff --git a/Master/tlpkg/tlgs/Resource/Init/gs_statd.ps b/Master/tlpkg/tlgs/Resource/Init/gs_statd.ps index 3ea50eeead3..7b85ef0f558 100644 --- a/Master/tlpkg/tlgs/Resource/Init/gs_statd.ps +++ b/Master/tlpkg/tlgs/Resource/Init/gs_statd.ps @@ -1,4 +1,4 @@ -% Copyright (C) 2001-2019 Artifex Software, Inc. +% Copyright (C) 2001-2020 Artifex Software, Inc. % All Rights Reserved. % % This software is provided AS-IS with no warranty, either express or diff --git a/Master/tlpkg/tlgs/Resource/Init/gs_std_e.ps b/Master/tlpkg/tlgs/Resource/Init/gs_std_e.ps index f4ea79e310a..4bfa6c5bfcb 100644 --- a/Master/tlpkg/tlgs/Resource/Init/gs_std_e.ps +++ b/Master/tlpkg/tlgs/Resource/Init/gs_std_e.ps @@ -1,4 +1,4 @@ -% Copyright (C) 2001-2019 Artifex Software, Inc. +% Copyright (C) 2001-2020 Artifex Software, Inc. % All Rights Reserved. % % This software is provided AS-IS with no warranty, either express or diff --git a/Master/tlpkg/tlgs/Resource/Init/gs_sym_e.ps b/Master/tlpkg/tlgs/Resource/Init/gs_sym_e.ps index b9abc86f7fe..fb92a2997dd 100644 --- a/Master/tlpkg/tlgs/Resource/Init/gs_sym_e.ps +++ b/Master/tlpkg/tlgs/Resource/Init/gs_sym_e.ps @@ -1,4 +1,4 @@ -% Copyright (C) 2001-2019 Artifex Software, Inc. +% Copyright (C) 2001-2020 Artifex Software, Inc. % All Rights Reserved. % % This software is provided AS-IS with no warranty, either express or diff --git a/Master/tlpkg/tlgs/Resource/Init/gs_trap.ps b/Master/tlpkg/tlgs/Resource/Init/gs_trap.ps index 58c5888a095..e4d6cafe094 100644 --- a/Master/tlpkg/tlgs/Resource/Init/gs_trap.ps +++ b/Master/tlpkg/tlgs/Resource/Init/gs_trap.ps @@ -1,4 +1,4 @@ -% Copyright (C) 2001-2019 Artifex Software, Inc. +% Copyright (C) 2001-2020 Artifex Software, Inc. % All Rights Reserved. % % This software is provided AS-IS with no warranty, either express or diff --git a/Master/tlpkg/tlgs/Resource/Init/gs_ttf.ps b/Master/tlpkg/tlgs/Resource/Init/gs_ttf.ps index 74043d16b0c..394cba28e26 100644 --- a/Master/tlpkg/tlgs/Resource/Init/gs_ttf.ps +++ b/Master/tlpkg/tlgs/Resource/Init/gs_ttf.ps @@ -1,4 +1,4 @@ -% Copyright (C) 2001-2019 Artifex Software, Inc. +% Copyright (C) 2001-2020 Artifex Software, Inc. % All Rights Reserved. % % This software is provided AS-IS with no warranty, either express or @@ -1304,7 +1304,7 @@ currentdict /.pickcmap_with_no_xlatmap .undef TTFDEBUG { (\n1 setting alias: ) print dup ==only ( to be the same as ) print 2 index //== exec } if - 7 index 2 index 3 -1 roll exch .forceput + 7 index 2 index 3 -1 roll exch put } forall pop pop pop } @@ -1322,7 +1322,7 @@ currentdict /.pickcmap_with_no_xlatmap .undef exch pop TTFDEBUG { (\n2 setting alias: ) print 1 index ==only ( to use glyph index: ) print dup //== exec } if - 5 index 3 1 roll .forceput + 5 index 3 1 roll put //false } { @@ -1339,7 +1339,7 @@ currentdict /.pickcmap_with_no_xlatmap .undef { % CharStrings(dict) isunicode(boolean) cmap(dict) RAGL(dict) gname(name) codep(integer) gindex(integer) TTFDEBUG { (\3 nsetting alias: ) print 1 index ==only ( to be index: ) print dup //== exec } if - exch pop 5 index 3 1 roll .forceput + exch pop 5 index 3 1 roll put } { pop pop @@ -1369,7 +1369,7 @@ currentdict /.pickcmap_with_no_xlatmap .undef } ifelse ] TTFDEBUG { (Encoding: ) print dup === flush } if -} .bind executeonly odef % hides .forceput +} .bind odef % ---------------- CIDFontType 2 font loading ---------------- % @@ -1657,7 +1657,13 @@ currentdict /.pickcmap_with_no_xlatmap .undef /CharStrings currentdict end } .bind def -% - .pdfcharkeys /CharStrings <charstrings> /Encoding <encoding> +% If we're using a 1,0 cmap table, we need to store the table for the heuristic +% to know whether to image or elide GID 0. See zfapi.c ps_get_glyphname_or_cid(). +% For other cmap types, we don't. Since this just pushes key/value pairs onto the +% stack for a later dicttomark op, it doesn't matter that different branches can push +% different numbers of objects. +% +% - .pdfcharkeys [/TT_cmap cmapdict] /CharStrings <charstrings> /Encoding <encoding> /.pdfcharkeys { % The following algorithms are per the PDF 1.7 Reference. TTFDEBUG { (.pdfcharkeys beg) = } if @@ -1736,12 +1742,13 @@ currentdict /.pickcmap_with_no_xlatmap .undef } ifelse } { <00010000> //.findcmap exec { + /TT_cmap 1 index cmapdict 3 -1 roll TTFDEBUG { (Using cmap 1.0 for non-symbolic.) = } if prebuilt_encoding //null ne { prebuilt_encoding .invert_encoding exch .romanmacdict //.pdfmapchars exec prebuilt_encoding } { - 0 dict exch + 0 dict exch .romanmacdict //.pdfmapchars exec /MacRomanEncodingForTrueType .findencoding } ifelse /Encoding exch diff --git a/Master/tlpkg/tlgs/Resource/Init/gs_typ32.ps b/Master/tlpkg/tlgs/Resource/Init/gs_typ32.ps index 9799a0bec3e..2d5fc81499a 100644 --- a/Master/tlpkg/tlgs/Resource/Init/gs_typ32.ps +++ b/Master/tlpkg/tlgs/Resource/Init/gs_typ32.ps @@ -1,4 +1,4 @@ -% Copyright (C) 2001-2019 Artifex Software, Inc. +% Copyright (C) 2001-2020 Artifex Software, Inc. % All Rights Reserved. % % This software is provided AS-IS with no warranty, either express or diff --git a/Master/tlpkg/tlgs/Resource/Init/gs_typ42.ps b/Master/tlpkg/tlgs/Resource/Init/gs_typ42.ps index ba5074ce1a5..654a268c0e0 100644 --- a/Master/tlpkg/tlgs/Resource/Init/gs_typ42.ps +++ b/Master/tlpkg/tlgs/Resource/Init/gs_typ42.ps @@ -1,4 +1,4 @@ -% Copyright (C) 2001-2019 Artifex Software, Inc. +% Copyright (C) 2001-2020 Artifex Software, Inc. % All Rights Reserved. % % This software is provided AS-IS with no warranty, either express or diff --git a/Master/tlpkg/tlgs/Resource/Init/gs_type1.ps b/Master/tlpkg/tlgs/Resource/Init/gs_type1.ps index a039ccee359..18488ebe1cd 100644 --- a/Master/tlpkg/tlgs/Resource/Init/gs_type1.ps +++ b/Master/tlpkg/tlgs/Resource/Init/gs_type1.ps @@ -1,4 +1,4 @@ -% Copyright (C) 2001-2019 Artifex Software, Inc. +% Copyright (C) 2001-2020 Artifex Software, Inc. % All Rights Reserved. % % This software is provided AS-IS with no warranty, either express or diff --git a/Master/tlpkg/tlgs/Resource/Init/gs_wan_e.ps b/Master/tlpkg/tlgs/Resource/Init/gs_wan_e.ps index 406c7fae370..5d3673cc67a 100644 --- a/Master/tlpkg/tlgs/Resource/Init/gs_wan_e.ps +++ b/Master/tlpkg/tlgs/Resource/Init/gs_wan_e.ps @@ -1,4 +1,4 @@ -% Copyright (C) 2001-2019 Artifex Software, Inc. +% Copyright (C) 2001-2020 Artifex Software, Inc. % All Rights Reserved. % % This software is provided AS-IS with no warranty, either express or diff --git a/Master/tlpkg/tlgs/Resource/Init/pdf_base.ps b/Master/tlpkg/tlgs/Resource/Init/pdf_base.ps index 02503eef8bc..2cc18270c3c 100644 --- a/Master/tlpkg/tlgs/Resource/Init/pdf_base.ps +++ b/Master/tlpkg/tlgs/Resource/Init/pdf_base.ps @@ -1,4 +1,4 @@ -% Copyright (C) 2001-2019 Artifex Software, Inc. +% Copyright (C) 2001-2020 Artifex Software, Inc. % All Rights Reserved. % % This software is provided AS-IS with no warranty, either express or @@ -288,9 +288,11 @@ currentdict /num-chars-dict .undef % Execute a file, like .pdfrun, for a marking context. % This temporarily rebinds LocalResources and DefaultQstate. /.pdfruncontext { % <resdict> <file> <opdict> .pdfruncontext - - /.pdfrun load LocalResources DefaultQstate - /LocalResources 7 -1 roll - dup /ParentResources LocalResources put % save the parent LocalResources + /.pdfrun load LocalResources DefaultQstate % res file op .pdfrun Loc Qst + /LocalResources 7 -1 roll % file op .pdfrun Loc Qst /Loc res + dup 4 index ne { % Ensure Loc != res to avoid self-referencing /ParentResources + dup /ParentResources 5 index put % save the parent LocalResources + } if store % store new LocalResources /DefaultQstate qstate store 3 .execn @@ -487,7 +489,12 @@ currentdict /token_nofail_dict .undef } if oforce % but dereference {1 0 R} dup type dup /arraytype eq exch /packedarraytype eq or { - [ exch 2 index <<>> copy exch { safe_recursive exch } forall pop] + [ exch { + counttomark 1 add index <<>> copy % create a copy for the recursion + exch safe_recursive exch + pop % pop the dictionary created for this level + } forall + ] } { dup type /dicttype eq { << exch 2 index <<>> copy exch { 3 -1 roll exch safe_recursive 3 -1 roll oforce 3 1 roll exch } forall pop>> @@ -776,11 +783,123 @@ currentdict /token_nofail_dict .undef count 4 index add % Determine stack depth with objects 3 1 roll resolveobjstreamopdict .pdfrun % Get PDF objects - count counttomark 1 add index ne { % Check stack depth - ( **** Error: Incorrect object count in object stream.\n) pdfformaterror - ( Output may be incorrect.\n) pdfformaterror - /resolveobjectstream cvx /rangecheck signalerror + count counttomark 1 add index ne + { + count counttomark 1 add index gt { + ( **** Error: Incorrect object count in object stream (too many objects).\n) pdfformaterror + ( Output may be incorrect.\n) pdfformaterror + } if + + % Its possible for us to end up here with a valid file. The way we work is to read the + % stream and tokenise all the objects, but that assumes there will be delimiters or + % whitespace between each object in the stream. We can easily think of cases where + % that is not true; eg two consecutive numbers 123 456 would be tokenised as a + % single number with the value 123456. + % In this case we can use the approach below to read each object individually and + % that will define the correct number of objects. After we've collected all the + % objects we'll check the number of objects recovered again, and see if there + % are still too few. We should probably raise an error in that case, but lets wait + % until we see a case. + + % Having too many objects in an ObjStm is not illegal, dumb but not illegal. We can + % recover from this, but its complicated. The extra object could be any of the ones + % from the stream, the only way to find out is to process each object individually. + % Unfortunately, my attempts to come up with a version of .pdfrun which only tokenised + % one object got rapidly bogged down. So a new approach was needed. + % + % The idea is simple; turn the underlying file into a ReusableStream, then we can + % reposition it. Build an array of the object offsets, reposition the file to the + % start of each object in turn. For all except the last object, create a sub file + % using SubFileDeocde with an empty string, and an EODCount which is the difference + % between the offset of this object and the offset of the next. + % For the last object we just read from the offset to the end of the stream. + % + % Then call .pdfrun on that sub file, or the main stream, which will tokenise all the + % objects from that point onwards. Then discard all but the first object read. + % + % The complications arise from the fact that we need to end up with the objects on + % the stack, in the right order, preceded by a mark, a count, and an array containing + % all the object numbers. + + % First, discard everything we read up to now; we can reuse the mark which was placed + % by the preceding code to do this, as long as we remember to replace that mark. + % Handily this will leave the count and the array which contains the object numbers in place. + cleartomark + + % Replace the mark consumed by conttomark above, so that we match what the code following this error handling expects. + mark + + % copy the ObjStm dictionary and then copy the count of objects expected + 4 index 4 index + + % Copy the ObjStm dictionary, and create a file from it + 1 index //false resolvestream % Convert stream dict into a stream + + /ReusableStreamDecode filter % We need to be able to re-position the stream + + 1 index array % Create array for holding offsets + + % Get the object offsets, these are stored at teh start of the stream, interleaved + % between the object numbers. We know reading these can't fail, because we've already + % done this to create the array of object numbers, above. + 0 1 % starting index (0), increment (1) for loop + 4 index 1 sub % limit of loop is object count-1 (because we start at 0) + { + 1 index 1 index % copy array and index + 4 index % copy the file object + token pop pop % read a token (object number) and discard it + 4 index token % read another token (offset) + pop put pop % put the offset into the array at the new index + } for + + % We now have an array with all the object offsets in it + % So we need to reposition the file to the start of each object and read + % from that point. We use the difference between two offsets to setup + % a SubFileDecode filter to only read as many bytes as there are + % between the objects. Normally this should result in us reading one object, + % if there are extra objects then we'll discard the extras. By doing this + % we avoid tokenising the same data multiple times. + + % Set the loop to be from 0 to the number of objects minus 1 (starts from 0), step 1. + 2 index 1 sub 0 1 3 -1 roll + { + dup % copy the loop index + 2 index length 2 sub lt % Check if index + 1 exceeds array size (it will on last iteration) + + { % Not the last iteration + dup % copy the loop index + 2 index exch get 5 index /First get add % get the object offset, and add the value of First from the dictionary. + exch 1 add % add one to the loop index + 2 index exch get 5 index /First get add % and get the offset to the start of the next object + + 1 index sub % copy the first offset and subtract from the second to get the length + exch + 3 index dup 3 -1 roll setfileposition % copy the file and position it to the offset of the object + exch + << /EODCount 3 -1 roll /EODString () >> % Set up a dictionary for the filter + /SubFileDecode filter % and apply it to limit the number of bytes read. + } + { % On the last iteration, simly read from the file, we don't need another SubFileDecode. + 1 index exch get 4 index /First get add % get the offset, and add the value of First from the dictionary. + 2 index dup 3 -1 roll setfileposition % copy the stream, and position it at that point + }ifelse + + mark exch resolveobjstreamopdict .pdfrun % make a mark and then tokenise all the objects from there to the end of stream (or sub file) + counttomark 2 sub % Find out how many objects we created (less two, one for the count and one for the first object) + 0 1 3 -1 roll {pop pop} for % pop that many objects off the stack + 6 1 roll pop % roll the new object to be behind our working objects on the stack and pop the mark + } for + + % pop most of the working objects (array, file, and ObjStrm dictionary) + % but leave count of objects. Check that aginst the number of objects + % retrieved. If we got too few then issue a warning. + + pop pop exch pop counttomark 1 sub lt { + ( **** Error: Incorrect object count in object stream (too few objects).\n) pdfformaterror + ( Output may be incorrect.\n) pdfformaterror + } if } if + % We have the object data counttomark array astore % Put objects into an array exch pop exch pop % Remove mark and count @@ -1139,16 +1258,26 @@ currentdict /pdf_rules_dict undef dup /JBIG2Globals knownoget { % make global ctx PDFfile fileposition exch % resolvestream is not reentrant + mark exch //true resolvestream % stack after: PDFfileposition -file- % Read the data in a loop until EOF to so we can move the strings into a bytestring [ { counttomark 1 add index 60000 string readstring not { exit } if } loop ] exch pop 0 1 index { length add } forall % compute the total length % now copy the data from the array of strings into a bytestring .bytestring exch 0 exch { 3 copy putinterval length add } forall pop - .jbig2makeglobalctx - PDFfile 3 -1 roll setfileposition - 1 index exch - /.jbig2globalctx exch put + % If this fails we don't want to abort totally, there may be more content + % in the PDF file that we can render. So just run in a stopped context. + {.jbig2makeglobalctx} stopped + { + cleartomark + PDFfile exch setfileposition + } + { + exch pop + PDFfile 3 -1 roll setfileposition + 1 index exch + /.jbig2globalctx exch put + } ifelse } if } bind executeonly def diff --git a/Master/tlpkg/tlgs/Resource/Init/pdf_draw.ps b/Master/tlpkg/tlgs/Resource/Init/pdf_draw.ps index a359a9c11c3..a93a526ca85 100644 --- a/Master/tlpkg/tlgs/Resource/Init/pdf_draw.ps +++ b/Master/tlpkg/tlgs/Resource/Init/pdf_draw.ps @@ -1,4 +1,4 @@ -% Copyright (C) 2001-2019 Artifex Software, Inc. +% Copyright (C) 2001-2020 Artifex Software, Inc. % All Rights Reserved. % % This software is provided AS-IS with no warranty, either express or @@ -419,14 +419,43 @@ end % Some functions used to implement phases of HT and HTP /sethalftones { + % As is so often the case, if we get an error we need to clean up the stack, but we can't + % use mark/cleartomark, because the action which caused the error may have left a mark + % on the stack. So we need to define our own mark. On an error we'll clean up the stack + % until we reach this unique key on the stack + /SethalftonesMark exch + dup /Default eq { - pop .setdefaulthalftone - } { - resolvehalftone sethalftone + pop .setdefaulthalftone pop + } + { + {resolvehalftone} stopped + { + (\n **** Error resolving halftone. Ignoring the halftone, output may be incorrect.\n) + pdfformaterror + % Clean up the stack by checking every entry until we find our unique key + {/SethalftonesMark eq {exit} if} loop + } + { + {sethalftone} stopped + { + (\n **** Error setting halftone. Ignoring the halftone, output may be incorrect.\n) + pdfformaterror + % Clean up the stack by checking every entry until we find our unique key + {/SethalftonesMark eq {exit} if} loop + } + { + pop + }ifelse + }ifelse } ifelse } bind executeonly def /sethalftonephases { - aload pop -1 2 index 2 index .setscreenphase pop pop + {aload pop -1 2 index 2 index .setscreenphase pop pop} stopped + { + (\n **** Error setting halftone phase. Ignoring the phase, output may be incorrect.\n) + pdfformaterror + } if } bind executeonly def /HT { @@ -549,9 +578,25 @@ end cleartomark //null exit } if gsave //nodict begin - /CS knownoget { + dup /CS knownoget { + exch pop resolvecolorspace dup setgcolorspace csput - } if + } + { + % Group attributes dictionaries are supposed to contain a /CS + % entry, but Acrobat apparently also handles a /ColorSpace.... + /ColorSpace knownoget { + ( **** Error: A transparency group XObject has a /ColorSpace instead of /CS attribute.\n) + pdfformaterror + resolvecolorspace dup setgcolorspace csput + } + { + ( **** Error: Ignoring a transparency group XObject without /CS attribute.\n) + pdfformaterror + ( Output may be incorrect.\n) pdfformaterror + cleartomark //null exit + }ifelse + } ifelse aload pop setcolor [ currentgray ] end grestore /GrayBackground exch 3 2 roll @@ -643,9 +688,19 @@ def resolvecolorspace dup setgcolorspace csput //true % use currentcolorspace } { - % inheriting the colorspace -- make sure Device* spaces are not CIEBased - forceDefaultCS currentcolorspace 0 get .knownget { exec } if - //false % no defined colorspace + % Group attributes dictionaries are supposed to contain a /CS + % entry, but Acrobat apparently also handles a /ColorSpace.... + dup /Group oget /ColorSpace knownoget { + ( **** Error: A transparency group attribute dictionary has a /ColorSpace instead of /CS attribute.\n) + pdfformaterror + resolvecolorspace dup setgcolorspace csput + //true % use currentcolorspace + } + { + % inheriting the colorspace -- make sure Device* spaces are not CIEBased + forceDefaultCS currentcolorspace 0 get .knownget { exec } if + //false % no defined colorspace + } ifelse } ifelse 3 -1 roll dup dup 4 1 roll /BBox get aload pop .begintransparencymaskgroup @@ -694,7 +749,6 @@ def /GroupGState .knownget { setgstate } if newpath //null SMask - 1 .setopacityalpha 1 .setshapealpha 1 CA 1 ca /Compatible .setblendmode % Execute the body of the Form, similar to DoForm. @@ -819,7 +873,15 @@ currentdict /csncompdict undef dup dup 1 oget mark exch { oforce } forall .dicttomark dup dup //true resolvestream - /ReusableStreamDecode filter /DataSource exch put + { + /ReusableStreamDecode filter + } stopped + { + pop null +% ( **** Error: Failed to read ICC profile for an ICCBased colour space.\n) pdfformaterror +% ( Falling back to a colour space determined by the /N value.\n) pdfformaterror + }if + /DataSource exch put dup /.hash 0 put % placeholder for use by seticc icc_profile_cache key % Check that the number of components (/N) defined in the ICCBased % dictionry matches the actual profile. Bug #696120 @@ -1066,6 +1128,8 @@ currentdict end readonly def //true } ifelse { dup dup type /arraytype eq { 0 get } if + dup type /packedarraytype eq {exch pop exec dup} if + //csrdict exch .knownget { exec dup type /nametype ne { dup length 1 eq { 0 get } if } if } { @@ -1413,7 +1477,7 @@ drawopdict begin /sh { OFFlevels length 0 eq { - setfillstate resolvesh + setsmaskstate resolvesh //sh_save 0 save put PDFusingtransparency { gsave @@ -1423,8 +1487,12 @@ drawopdict begin } { clippath } ifelse - //null setup_trans + % If we get an error, just emit an empty box + { pathbbox } stopped { 0 0 0 0 } if + 4 array astore grestore + //null + setup_trans //do_shade exec teardown_trans } { @@ -2210,60 +2278,62 @@ currentdict /last-ditch-bpc-csp undef } bind executeonly def /doimagesmask { % <imagemask> doimagesmask - - PDFusingtransparency { - currentdict /SMask knownoget + PDFusingtransparency not + /PreserveSMask /GetDeviceParam .special_op { exch pop } { //false } ifelse + or { + % not using transparency OR the device supports SMask (e.g. pdfwrite) + doimage } { - //false - } ifelse - { % We are doing transparency and SMask is present in the image - % stack: <imagemask> <SMask> - /PreserveSMask /GetDeviceParam .special_op { - exch pop - }{ - //false - }ifelse - { - pop % pdfwrite will process SMask directly during 'doimage' - } { + currentdict /SMask knownoget { + % We are doing transparency and SMask is present in the image + % stack: <imagemask> <SMask> .begintransparencymaskimage PDFfile fileposition exch gsave //nodict begin //null .setSMask - 1 .setopacityalpha 1 .setshapealpha 1 CA 1 ca /Compatible .setblendmode DoImage end grestore PDFfile exch setfileposition 0 .endtransparencymask - } ifelse - << /Subtype /Group /Isolated //true - /.image_with_SMask //true - % pdfwrite needs : see gs/src/ztrans.c, gs/src/gdevpdft.c - % Code to deal with a Matte in the SMask. We know the image dictionary must have an SMask - % entry if we get here, so we don't need to check its existence. Just pull it out and see if - % the SMask has a Matte entry. If it does, get the ColorSpace from the parent image and - % put a /CS key with that colour space in the Group that we manufacture. Bug #700686 - % We also need to actually set the current colour space to be the same as the group - % code only picks up the current colour space, not the space from the dictionary. - currentdict /SMask get /Matte known {/CS currentdict /ColorSpace get dup pdfopdict /cs get exec } if - >> 0 0 1 1 .begintransparencygroup - doimage - .endtransparencygroup - % tell the compositor we're done with the SMask. - % Note that any SMask in the ExtGState should be reapplied - % by the next call to setfill(stroke)state AND this relies - % on our lazy evaulation of SMask groups - //false << /Subtype /None >> 0 0 0 0 .begintransparencymaskgroup - } { - .currentSMask //null ne { - % the image doesn't have an SMask, but the ExtGState does, force a group. - << /Subtype /Group /Isolated //true >> 0 0 1 1 .begintransparencygroup + << /Subtype /Group /Isolated //true + /.image_with_SMask //true + % pdfwrite needs : see gs/src/ztrans.c, gs/src/gdevpdft.c + % Code to deal with a Matte in the SMask. We know the image dictionary must have an SMask + % entry if we get here, so we don't need to check its existence. Just pull it out and see if + % the SMask has a Matte entry. If it does, get the ColorSpace from the parent image and + % put a /CS key with that colour space in the Group that we manufacture. Bug #700686 + % We also need to actually set the current colour space to be the same as the group + % code only picks up the current colour space, not the space from the dictionary. + currentdict /SMask get /Matte known {/CS currentdict /ColorSpace get dup pdfopdict /cs get exec } if + >> 0 0 1 1 + .begintransparencygroup + .currentstrokeconstantalpha .currentfillconstantalpha 3 -1 roll + 1 .setfillconstantalpha 1 .setstrokeconstantalpha doimage + .setfillconstantalpha .setstrokeconstantalpha .endtransparencygroup - } - { doimage } - ifelse + % tell the compositor we're done with the SMask. + % Note that any SMask in the ExtGState should be reapplied + % by the next call to setfill(stroke)state AND this relies + % on our lazy evaulation of SMask groups + //false << /Subtype /None >> 0 0 0 0 .begintransparencymaskgroup + } { + % We don't have an SMask in the image but there might be an SMask in the ExtGState + .currentSMask //null ne { + % the image doesn't have an SMask, but the ExtGState does, force a group. + << /Subtype /Group /Isolated //true >> 0 0 1 1 + .begintransparencygroup + .currentstrokeconstantalpha .currentfillconstantalpha 3 -1 roll + 1 .setfillconstantalpha 1 .setstrokeconstantalpha + doimage + .setfillconstantalpha .setstrokeconstantalpha + .endtransparencygroup + } { + doimage + } ifelse + } ifelse } ifelse } bind executeonly def @@ -2315,6 +2385,9 @@ currentdict /last-ditch-bpc-csp undef /doimage { % <imagemask> doimage - % imagedict is currentdict, gets popped from dstack + %% We must save the colour space, in case it gets changed. I did try doing this + %% at a higher level (/Do) but that caused numerous problems with pdfwrite. + currentcolorspace exch %% save the current rendering intent .currentrenderintent exch @@ -2336,9 +2409,14 @@ currentdict /last-ditch-bpc-csp undef makemaskimage } if % Stack: datasource imagemask - gsave 1 1 moveto 0 0 lineto /image setup_trans grestore - { currentdict end setfillstate //true ValidateDecode { imagemask } } - { ColorSpace setgcolorspace currentdict end setfillblend //false ValidateDecode { image } } + gsave 1 1 moveto 0 0 lineto + % If we get an error, just emit an empty box + { pathbbox } stopped { 0 0 0 0 } if + 4 array astore grestore + /image + setup_trans + { currentdict end setsmaskstate //true ValidateDecode { imagemask } } + { ColorSpace setgcolorspace currentdict end setsmaskstate //false ValidateDecode { image } } ifelse PDFSTOPONERROR { exec //false } { stopped } ifelse { dup type /dicttype eq { pop } if % Sometimes image fails to restore the stack @@ -2361,12 +2439,19 @@ currentdict /last-ditch-bpc-csp undef %% restore the rendering intent .setrenderingintent + %% and restore the colour space. We need to do this in a stopped context because + %% if we are rendering a glyph, the cache device will throw an error if we try + %% to change colour space (even when the new space is the same as the old space) + %% We can't tell if we are rendering a bitmap for a glyph, and its hard to compare + %% colour spaces, so just ignore errors for now. + {setcolorspace} stopped {pop} if + teardown_trans } bind executeonly def /.paintform { % <formdict> <resdict> <stream> .paintform - 1 index /FormResDict gput % For broken forms that inherit resources from the context. - 3 -1 roll dup /Group known PDFusingtransparency and { + 3 -1 roll dup /Group oknown PDFusingtransparency and { .paintgroupform } { pop pdfopdict .pdfruncontext @@ -2550,7 +2635,27 @@ pdfdict } forall } if - 3 index //false /resolvestream cvx + 3 index + % /Contents for the stream is not per the spec, but Acrobat handles it + dup /Contents knownoget + { + % We want to make it's a dictionary, and represents a stream + dup type /dicttype eq + { + dup /FilePosition known + { + PDFSTOPONERROR { /DoForm cvx /undefinedresource signalerror } if + ( **** Error: Invalid Form definition. Output may be incorrect.\n) pdfformaterror + exch pop + } + {pop} ifelse + } + { + pop + } + ifelse + }if + //false /resolvestream cvx /.paintform cvx ] cvx /PaintProc exch put % Adjust pdfemptycount since we have an extra dictionary on the stack @@ -2588,6 +2693,38 @@ pdfdict pop /pdfemptycount exch store + % We've now seen Form XObjects leaving junk on the stack, so we + % can't assume that when we finish the form the stack will be restored + % nor can we assume that the junk won't include a 'mark' so we an't + % simply do a cleartomark. Instead clear the stack until we get back + % to a dictionary which contains /saved_DG. We can still get errors; + % if the stream removes too many objects from the stack we will end + % up with a stackunderflow, but there's nothing we can do about that. + dup type /dicttype eq not { + //true + } { + dup /saved_DG known { + //false + } { + //true + } ifelse + } ifelse + { + ( **** Error: Form stream left garbage on the stack, attempting to recover.\n) pdfformaterror + ( Output may be incorrect.\n) pdfformaterror + { + dup type /dicttype eq not { + pop + } { + dup /saved_DG known { + exit + } { + pop + } ifelse + } ifelse + } loop + } if + %% Put back pre-existing Default* ColorSpace definitions. dup type /dicttype eq { begin @@ -2736,7 +2873,7 @@ drawopdict begin ( Output may be incorrect.\n) pdfformaterror currentdict /qTextSaveMatrix get setmatrix } if - setfillblend + setsmaskstate PDFfile fileposition exch % pos /Name % Bug #698226, Acrobat signals an error for recursive XObjects in a PDF file @@ -3043,7 +3180,7 @@ end } ifelse } ifelse } - { 0 setgray //true} ifelse + { //false } ifelse } bind executeonly def % Draw the border. Currently, we ignore requests for beveling, and we @@ -3051,17 +3188,20 @@ end /strokeborder { % <annot> <width> <dash> strokeborder - 1 index 0 ne { % do not draw if border width is 0 gsave - 2 index annotsetcolor - { +% 2 index annotsetcolor +% { 0 setdash dup setlinewidth - exch annotrect + exch dup annotrect + 5 -1 roll /RD knownoget { + applyRD + } if 2 { 4 index sub 4 1 roll } repeat 2 { 4 index 0.5 mul add 4 1 roll } repeat rectstroke pop grestore - } { - pop pop pop - } ifelse +% } { +% pop pop pop +% } ifelse } { pop pop pop }ifelse @@ -3094,12 +3234,16 @@ end % Scaling due to -dPDFFitPage is not undone, to keep the correct border width % compared to the size of the surrounding marks. //systemdict /NoUserUnit .knownget not { //false } if not - //systemdict /PDFFitPage known not and { % UserUnit is ignored if -dPDFFitPage + //systemdict /PDFFitPage known not and + % Don't apply USerUnit if we are passing it to the device + /PassUserUnit /GetDeviceParam .special_op {exch pop} {//false} ifelse not and + { % UserUnit is ignored if -dPDFFitPage Page /UserUnit knownoget { div } if } if {} 2 index /S knownoget { /D eq { 2 index /D knownoget not { {3} } if exch pop } if - } if 3 -1 roll pop strokeborder + } if + 3 -1 roll pop strokeborder } { dup 2 get exch dup length 3 gt { 3 get } { pop {} } ifelse @@ -3138,23 +3282,39 @@ end % Scaling due to -dPDFFitPage is not undone, to keep the correct border width % compared to the size of the surrounding marks. //systemdict /NoUserUnit .knownget not { //false } if not - //systemdict /PDFFitPage known not and { % UserUnit is ignored if -dPDFFitPage + //systemdict /PDFFitPage known not and + % Don't apply USerUnit if we are passing it to the device + /PassUserUnit /GetDeviceParam .special_op {exch pop} {//false} ifelse not and + { % UserUnit is ignored if -dPDFFitPage Page /UserUnit knownoget { div } if } if {} 2 index /S knownoget { /D eq { 2 index /D knownoget not { {3} } if exch pop } if } if - 3 index /CA knownoget {.setopacityalpha} if - 3 -1 roll pop 2 index annotsetcolor {0 setdash setlinewidth stroke} if + 3 index /CA knownoget {dup .setstrokeconstantalpha .setfillconstantalpha} if + 3 -1 roll pop +% 2 index annotsetcolor { + 0 setdash setlinewidth stroke +% } if } { dup 2 get - exch dup length 3 gt { 3 get } { pop {} } ifelse - 3 index /CA knownoget {.setopacityalpha} if - 2 index annotsetcolor {0 setdash setlinewidth stroke} if + % If element 3 of the /Border array is 0, then don't draw the border + dup 0 ne { + exch dup length 3 gt { 3 get } { pop {} } ifelse + 3 index /CA knownoget {dup .setstrokeconstantalpha .setfillconstantalpha} if +% 2 index annotsetcolor { + 0 setdash setlinewidth stroke +% } if + }{ + pop pop + } ifelse } ifelse } { - 3 index /CA knownoget {.setopacityalpha} if - 1 {} 2 index annotsetcolor {0 setdash setlinewidth stroke} if + dup /CA knownoget {dup .setstrokeconstantalpha .setfillconstantalpha} if + 1 {} +% 2 index annotsetcolor { + 0 setdash setlinewidth stroke +% } if } ifelse pop grestore @@ -3162,7 +3322,7 @@ end /fillborderpath { % <annot> fillborderpath - gsave - dup /ca knownoget {.setopacityalpha} if + dup /ca knownoget {dup .setstrokeconstantalpha .setfillconstantalpha} if annotsetinteriorcolor {fill} if grestore @@ -3241,12 +3401,24 @@ end 1 index /DA fget not { 1 index /V fget { <EFBBBF> anchorsearch { - pop /Helvetica findfont 12 scalefont setfont + pop /Helvetica findfont + 12 scalefont setfont } { <FEFF> anchorsearch { pop pop /FallBackFont /Identity-UTF16-H [/CIDFallBack] composefont 12 scalefont setfont } { - pop /Helvetica findfont 12 scalefont setfont + pop /Helvetica findfont + % re-encode the font to PDFDocEncoding + dup length dict begin + { + 1 index /FID ne 2 index /UniqueID ne and { def } { pop pop } ifelse + } forall + /Encoding /PDFDocEncoding /Encoding findresource def + /FontName /Helvetica-PDFDocEncoding def + currentdict + end + /Helvetica-PDFDocEncoding exch definefont + 12 scalefont setfont }ifelse }ifelse } if @@ -3318,109 +3490,151 @@ end % } if % } if - dup /AP knownoget { - dup /N known not { - ( **** Error: Appearance dictionary (AP) lacks the mandatory normal (N) appearance.\n) - pdfformaterror - ( Output may be incorrect.\n) pdfformaterror + % Acrobat doesn't draw Widget annotations unles they have both /FT + % (which is defined as required) and /T keys present. Annoyingly + % these can either be inherited from the Form Definition Field + % dictionary (via the AcroForm tree) or present directly in the + % annotation, so we need to check the annotation to make sure its + % a Widget, then follow any /Parent key up to the root node + % extracting and storing any FT or T keys as we go (we only care if + % these are present, their value is immaterial). If after all that + % both keys are not present, then we don't draw the annotation. + + dup /Subtype get /Widget eq { + dup /FT known 1 index /T known and not { + dup + { + dup /FT knownoget { + /FT exch 3 index 3 1 roll put + } if + dup /T knownoget { + /T exch 3 index 3 1 roll put + } if + /Parent knownoget not { + exit + } if + } loop } if - //false - [/N /R /D] { - % stack: scalex scaley annot appearance false key - 2 index exch knownogetdict { - exch not exit + dup /FT known 1 index /T known and { + //true + } { + ( **** Warning: A Widget annotation dictionary lacks either the FT or T key.\n) + pdfformaterror + ( Acrobat ignores such annotations, annotation will not be rendered.\n) + pdfformaterror + ( Output may not be as expected.\n) pdfformaterror + //false + } ifelse + } { + //true + }ifelse + + { + dup /AP knownoget { + dup /N known not { + ( **** Error: Appearance dictionary (AP) lacks the mandatory normal (N) appearance.\n) + pdfformaterror + ( Output may be incorrect.\n) pdfformaterror } if - } forall - % stack: scalex scaley annot appearance value true - % stack: scalex scaley annot appearance false - dup { - pop exch pop + //false + [/N /R /D] { + % stack: scalex scaley annot appearance false key + 2 index exch knownogetdict { + exch not exit + } if + } forall + % stack: scalex scaley annot appearance value true + % stack: scalex scaley annot appearance false + dup { + pop exch pop % Acrobat Distiller produces files in which this Form % XObject lacks Type and Subtype keys. This is illegal, % but Acrobat Reader accepts it. The only way we can % tell whether this is a Form or a set of sub-appearances % is by testing for the stream Length or File key. % If the stream lacks Length key, try File key. - dup /Length knownoget { type /integertype eq } { //false } ifelse - 1 index /File knownoget { type /filetype eq or } if { - % If this is a form then simply use it - //true - } { - 1 index /AS knownoget not { - % If we do not have AS then use any appearance - { exch pop oforce exit } forall //true + dup /Length knownoget { type /integertype eq } { //false } ifelse + 1 index /File knownoget { type /filetype eq or } if { + % If this is a form then simply use it + //true } { - % Stack: annot Ndict AS - % Get the specified appearance. If no appearance, then - % display nothing - set stack = false. - knownoget + 1 index /AS knownoget not { + % If we do not have AS then use any appearance + { exch pop oforce exit } forall //true + } { + % Stack: annot Ndict AS + % Get the specified appearance. If no appearance, then + % display nothing - set stack = false. + knownoget + } ifelse } ifelse + } { + exch pop % discard useless AP dictionary } ifelse - } { - exch pop % discard useless AP dictionary - } ifelse % Stack: scalex scaley annot appearance true % Stack: scalex scaley annot false - { - dup type /dicttype eq { + { + dup type /dicttype eq { % Draw appearance % Initialize graphic following "7.4.4 Appearance Streams" - q graphicsbeginpage textbeginpage - 1 index annotrect pop pop translate - 3 index 3 index scale % Apply scale factors - dup /BBox knownoget { - 1 index /Matrix knownoget not { {1 0 0 1 0 0} } if - .bbox_transform pop pop - % Compensate for non-zero origin of BBox - neg exch neg exch translate - } if - DoForm Q - } { - ( **** Error: Annotation's appearance is not a dictionary.\n) - pdfformaterror - ( Output may be incorrect.\n) pdfformaterror - } ifelse - } if - } { - dup /MK knownoget { % mk - dup /BG knownoget { % mk bg - dup length % mk bg len - //set_bc_color exch .knownget { - gsave - exec - 3 index 3 index scale - 1 index annotrect rectfill - grestore + q graphicsbeginpage textbeginpage + 1 index annotrect pop pop translate + 3 index 3 index scale % Apply scale factors + dup /BBox knownoget { + 1 index /Matrix knownoget not { {1 0 0 1 0 0} } if + .bbox_transform pop pop + % Compensate for non-zero origin of BBox + neg exch neg exch translate + } if + DoForm Q } { - pop + ( **** Error: Annotation's appearance is not a dictionary.\n) + pdfformaterror + ( Output may be incorrect.\n) pdfformaterror } ifelse } if - dup /BC knownoget { - dup length - //set_bc_color exch .knownget { - gsave - exec - 1 setlinewidth - 3 index 3 index scale - 1 index annotrect rectstroke - grestore - } { - pop - } ifelse + } { + dup /MK knownoget { % mk + dup /BG knownoget { % mk bg + dup length % mk bg len + //set_bc_color exch .knownget { + gsave + exec + 3 index 3 index scale + 1 index annotrect rectfill + grestore + } { + pop + } ifelse + } if + dup /BC knownoget { + dup length + //set_bc_color exch .knownget { + gsave + exec + 1 setlinewidth + 3 index 3 index scale + 1 index annotrect rectstroke + grestore + } { + pop + } ifelse + } if + pop } if - pop - } if - dup can-regenerate-ap { - make_tx_da - dup /UpdatedAP //true put - 3 copy drawwidget - } if - } ifelse + dup can-regenerate-ap { + make_tx_da + dup /UpdatedAP //true put + 3 copy drawwidget + } if + } ifelse + } if pop pop pop } bind executeonly def + currentdict /set_bc_color undef % For annotation object we have to determine the size of the output rectangle @@ -3471,6 +3685,23 @@ currentdict /set_bc_color undef } ifelse } bind executeonly def +/applyRD { + % x y w h [l t r b] + dup 0 get % x y w h [] l + 6 -1 roll add + 5 1 roll %x+l y w h [] + dup 1 get %x+l y w h [] b + 5 -1 roll add %x+l w h [] b+y + 4 1 roll %x+l y+b w h [] + aload pop %x+l y+b w h l t r b + exch %x+l y+b w h l t b r + 4 -1 roll add %x+l y+b w h t b r+l + 3 1 roll add %x+l y+b w h r+l t+b + 3 -1 roll exch sub %x+l y+b w r+l h-(t+b) + 3 1 roll sub %x+l y+b h-(t+b) w-(r+l) + exch +} bind executeonly def + % Draw an annotation. /drawannottypes 20 dict begin @@ -3568,17 +3799,31 @@ currentdict /set_bc_color undef annotsetinteriorcolor { gsave - dup /ca knownoget {.setopacityalpha} if - dup annotrect rectfill + dup /ca knownoget {dup .setstrokeconstantalpha .setfillconstantalpha} if + dup annotrect + 5 index /RD knownoget { + applyRD + } if + rectfill grestore - dup /CA knownoget {.setopacityalpha} if - drawborder + dup /CA knownoget {dup .setstrokeconstantalpha .setfillconstantalpha} if + dup annotsetcolor { + drawborder + } if //false }{ - pop + dup annotrect + 5 index /RD knownoget { + applyRD + } if + drawopdict /re get exec + dup annotsetcolor { + strokeborderpath + } if } ifelse //endannottransparency exec grestore + //false }ifelse } bind executeonly def @@ -3608,11 +3853,17 @@ currentdict /set_bc_color undef } { gsave //startannottransparency exec - dup annotrect 4 2 roll exch 3 index 2 div add exch 2 index 2 div add + dup annotrect + 5 index /RD knownoget { + applyRD + } if + 4 2 roll exch 3 index 2 div add exch 2 index 2 div add translate //drawellipse exec dup fillborderpath - strokeborderpath + dup annotsetcolor { + strokeborderpath + } if //endannottransparency exec grestore //false @@ -3657,12 +3908,18 @@ currentdict /set_bc_color undef { gsave - dup /ca knownoget {.setopacityalpha} if + dup /ca knownoget {dup .setstrokeconstantalpha .setfillconstantalpha} if fill grestore - dup /CA knownoget {.setopacityalpha} if - strokeborderpath - } if + dup /CA knownoget {dup .setstrokeconstantalpha .setfillconstantalpha} if + dup annotsetcolor { + strokeborderpath + } if + } { + dup annotsetcolor { + strokeborderpath + } if + } ifelse //endannottransparency exec //false grestore @@ -3690,7 +3947,7 @@ currentdict /set_bc_color undef dup 1 index exch lineto dup neg lineto closepath - 1 index /CA knownoget {.setopacityalpha} if + 1 index /CA knownoget {dup .setstrokeconstantalpha .setfillconstantalpha} if 1 index fillborderpath grestore 3 mul @@ -3716,7 +3973,7 @@ currentdict /set_bc_color undef 2.5 mul dup 0 moveto 0 0 3 -1 roll 0 360 arc - 1 index /CA knownoget {.setopacityalpha} if + 1 index /CA knownoget {dup .setstrokeconstantalpha .setfillconstantalpha} if 1 index fillborderpath grestore 3 mul dup @@ -3741,7 +3998,7 @@ currentdict /set_bc_color undef dup 0 exch lineto 0 lineto closepath - 1 index /CA knownoget {.setopacityalpha} if + 1 index /CA knownoget {dup .setstrokeconstantalpha .setfillconstantalpha} if 1 index fillborderpath grestore 3 mul @@ -3791,11 +4048,11 @@ currentdict /set_bc_color undef dup 2 div sub dup 8.4 mul neg 1 index 5.9 mul neg moveto dup 1.2 div neg 0 lineto dup 8.4 mul neg exch 5.9 mul lineto closepath - dup /CA knownoget {.setopacityalpha} if + dup /CA knownoget {dup .setstrokeconstantalpha .setfillconstantalpha} if fillborderpath grestore } bind executeonly def - /None {} bind executeonly def + /None {pop} bind executeonly def /Butt { dup /BS knownoget { @@ -3850,7 +4107,7 @@ currentdict /set_bc_color undef dup 2 div sub dup 8.4 mul neg 1 index 5.9 mul neg moveto dup 1.2 div neg 0 lineto dup 8.4 mul neg exch 5.9 mul lineto closepath - dup /CA knownoget {.setopacityalpha} if + dup /CA knownoget {dup .setstrokeconstantalpha .setfillconstantalpha} if fillborderpath grestore } bind executeonly def @@ -3880,36 +4137,50 @@ currentdict /set_bc_color undef } { gsave //startannottransparency exec - dup /L knownoget { - 1 index /LE knownoget { - gsave - 1 index aload pop % x1 y1 x2 y2 - 3 -1 roll sub % x1 x2 dy - 3 1 roll exch sub % dy dx - 2 copy translate - atan - rotate - dup 0 get dup //LineEnd_dict exch known not {pop /None} if //LineEnd_dict exch get 3 index exch exec - grestore - gsave - 1 index aload pop % x1 y1 x2 y2 - 3 -1 roll sub % x1 x2 dy - 3 1 roll exch sub % dy dx - 2 copy translate - atan 180 add - rotate - 1 get dup //LineEnd_dict exch known not {pop /None} if //LineEnd_dict exch get 3 index exch exec - grestore - }if - aload pop 4 2 roll - moveto lineto - strokeborderpath - }{ - ( **** Error: Invalid L array for Line, annotation has not been drawn.\n) - pdfformaterror - ( Output may be incorrect.\n) pdfformaterror - pop - } ifelse + dup annotsetcolor { + dup /L knownoget { + 1 index /LE knownoget { % <annot> [x1 y1 x2 y2] [LE1 LE2] + gsave + 1 index aload pop % <annot> [x1 y1 x2 y2] [LE1 LE2] x1 y1 x2 y2 + 3 -1 roll sub % <annot> [x1 y1 x2 y2] [LE1 LE2] x1 x2 dy + 3 1 roll exch sub % <annot> [x1 y1 x2 y2] [LE1 LE2] dy dx + 3 index aload pop 4 2 roll pop pop + translate + 0 0 moveto + {atan} stopped {pop pop 0} if % <annot> [x1 y1 x2 y2] [LE1 LE2] + rotate + dup 1 get % <annot> [x1 y1 x2 y2] [LE1 LE2] LE1 + dup //LineEnd_dict exch known not + { + pop /None + } if + //LineEnd_dict exch % <annot> [x1 y1 x2 y2] [LE1 LE2] <dict> LE1 + get % <annot> [x1 y1 x2 y2] [LE1 LE2] {} + 3 index exch % <annot> [x1 y1 x2 y2] [LE1 LE2] <annot> {} + exec + grestore + gsave + 1 index aload pop % x1 y1 x2 y2 + 3 -1 roll sub % x1 x2 dy + 3 1 roll exch sub % dy dx + 3 index aload pop pop pop + translate + 0 0 moveto + {atan} stopped {pop pop 0} if 180 add + rotate + 0 get dup //LineEnd_dict exch known not {pop /None} if //LineEnd_dict exch get 3 index exch exec + grestore + }if + aload pop 4 2 roll + moveto lineto + strokeborderpath + }{ + ( **** Error: Invalid L array for Line, annotation has not been drawn.\n) + pdfformaterror + ( Output may be incorrect.\n) pdfformaterror + pop + } ifelse + } if //endannottransparency exec //false grestore @@ -3923,15 +4194,16 @@ currentdict /set_bc_color undef } { gsave //startannottransparency exec + dup annotsetcolor pop dup /Vertices knownoget { 1 index /LE knownoget { gsave 1 index 0 4 getinterval aload pop 4 2 roll 2 copy translate 4 2 roll - 3 -1 roll sub % x1 x2 dy - 3 1 roll exch sub % dy dx - atan + 3 -1 roll exch sub % x1 x2 dy + 3 1 roll sub % dy dx + {atan} stopped {pop pop 0} if rotate dup 0 get dup //LineEnd_dict exch known not {pop /None} if //LineEnd_dict exch get 3 index exch exec grestore @@ -3941,7 +4213,7 @@ currentdict /set_bc_color undef 2 copy translate 3 -1 roll sub % x1 x2 dy 3 1 roll exch sub % dy dx - atan + {atan} stopped {pop pop 0} if rotate 1 get dup //LineEnd_dict exch known not {pop /None} if //LineEnd_dict exch get 3 index exch exec grestore @@ -3977,14 +4249,16 @@ currentdict /set_bc_color undef /Link { % <annot> -> <false> //startannottransparency exec - dup drawborder dup calc_annot_scale - 2 copy mul 0 ne - {3 -1 roll drawwidget //false} - { - pop pop - ( **** Error: ignoring annotation with scale factor of 0\n) pdfformaterror - ( Output may be incorrect.\n) pdfformaterror - }ifelse + dup annotsetcolor { + dup drawborder dup calc_annot_scale + 2 copy mul 0 ne + {3 -1 roll drawwidget //false} + { + pop pop + ( **** Error: ignoring annotation with scale factor of 0\n) pdfformaterror + ( Output may be incorrect.\n) pdfformaterror + }ifelse + } if //endannottransparency exec } bind executeonly def @@ -3998,7 +4272,8 @@ currentdict /set_bc_color undef 1 setlinewidth 1 setlinecap 1 setlinejoin - dup annotsetcolor { + dup annotsetcolor + { dup calc_annot_scale 2 copy mul 0 ne { @@ -4047,7 +4322,8 @@ currentdict /set_bc_color undef //true } { 0 setlinecap - dup annotsetcolor { + dup annotsetcolor + { dup calc_annot_scale 2 copy mul 0 ne { @@ -4087,7 +4363,8 @@ currentdict /set_bc_color undef //true } { 0 setlinecap - dup annotsetcolor { + dup annotsetcolor + { dup calc_annot_scale 2 copy mul 0 ne { @@ -4149,7 +4426,8 @@ currentdict /set_bc_color undef //true } { 0 setlinecap - dup annotsetcolor { + dup annotsetcolor + { /QuadPoints knownoget { aload length 8 idiv { 6 -2 roll @@ -4161,7 +4439,9 @@ currentdict /set_bc_color undef } repeat PDFusingtransparency { //emptydict - pathbbox 2 index add exch 3 index add exch .begintransparencygroup + % If we get an error, just emit an empty box + { pathbbox } stopped { 0 0 0 0 } if + 2 index add exch 3 index add exch .begintransparencygroup /Multiply .setblendmode fill .endtransparencygroup @@ -4182,7 +4462,8 @@ currentdict /set_bc_color undef //true } { //startannottransparency exec - dup annotsetcolor { + dup annotsetcolor + { dup calc_annot_scale 2 copy mul 0 ne { @@ -4291,11 +4572,11 @@ currentdict /set_bc_color undef dup annotrect rectclip dup /CA knownoget { - .setopacityalpha + dup .setstrokeconstantalpha .setfillconstantalpha } if dup /ca knownoget { - .setopacityalpha + dup .setstrokeconstantalpha .setfillconstantalpha } if dup /C knownoget { @@ -4323,18 +4604,37 @@ currentdict /set_bc_color undef }{ //false } ifelse - {dup annotrect - %% Somewhat horrifyingly, rectfill maps directly to the device fill_rectangle - %% method, which bypasses transparency (!!) So we construct the rectangle, - %% and fill it, manually instead.... - gsave 4 2 roll moveto 1 index 0 rlineto - 0 exch rlineto neg 0 rlineto closepath fill grestore + { + dup annotrect + 5 index /RD knownoget { + applyRD + } if + rectfill } if %% get and process the default appearance string, if we don't have one, use a default /DA_Action_Dict << - /Tf {exch dup /Helv eq {pop /Helvetica findfont exch scalefont setfont}{findfont exch scalefont setfont}ifelse} + /Tf + { + exch dup /Helv eq + { + pop /Helvetica dup findfont + } + {dup findfont}ifelse + + % re-encode the font to PDFDocEncoding + dup length dict begin + { + 1 index /FID ne 2 index /UniqueID ne and { def } { pop pop } ifelse + } forall + /Encoding /PDFDocEncoding /Encoding findresource def + /FontName /Helvetica-PDFDocEncoding def + currentdict + end + definefont + exch scalefont setfont + } /r {aload pop setrgbcolor} % Can't find this actually defined anywhere, but Acrobat seems to honour it :-( /rg {setrgbcolor} /RG {setrgbcolor} @@ -4380,27 +4680,108 @@ currentdict /set_bc_color undef {cleartomark pop} ifelse } { 0 setgray - /Helvetica findfont 12 scalefont setfont + /Helvetica findfont + % re-encode the font to PDFDocEncoding + dup length dict begin + { + 1 index /FID ne 2 index /UniqueID ne and { def } { pop pop } ifelse + } forall + /Encoding /PDFDocEncoding /Encoding findresource def + /FontName /Helvetica-PDFDocEncoding def + currentdict + end + /Helvetica-PDFDocEncoding exch definefont + 12 scalefont setfont }ifelse %% draw the border, if we don't have a border style dictionary, draw a default one. - dup /BS knownoget { + dup /BS knownoget + { pop dup drawborder }{ newpath 0 setgray 1 setlinewidth - dup annotrect 4 -1 roll 1 add 4 -1 roll 1 add 4 -1 roll 2 sub 4 -1 roll 2 sub - 4 2 roll moveto - currentpoint exch 3 index add exch lineto - currentpoint 2 index add lineto - exch currentpoint 3 1 roll exch sub exch lineto - currentpoint 3 -1 roll sub lineto stroke + dup annotrect + 5 index /RD knownoget { + applyRD + 4 -1 roll 4 -1 roll 4 -1 roll 4 -1 roll + 4 2 roll + } { + 4 -1 roll 1 add 4 -1 roll 1 add 4 -1 roll 2 sub 4 -1 roll 2 sub + 4 2 roll + }ifelse + moveto + currentpoint exch 3 index add exch + lineto + currentpoint 2 index add + lineto + exch currentpoint 3 1 roll exch sub exch + lineto + currentpoint 3 -1 roll sub + lineto stroke }ifelse + gsave % in case we rotate the contents %% Start the current point at the top left of the annotation Rect %% - dup annotrect 4 -1 roll 2 add 4 -1 roll 2 add 4 -1 roll 4 sub 4 -1 roll 4 sub - 3 -1 roll add 2 index exch moveto 1 index add + dup /Rotate knownoget + % x y w h - x' w' x' y' + { + dup 90 eq { + pop + dup annotrect + 5 index /RD knownoget { + applyRD + } if + exch pop 3 -1 roll 2 index + moveto 90 rotate + 1 index add + } { + dup 180 eq { + pop + dup annotrect + 5 index /RD knownoget { + applyRD + } if + pop 3 -1 roll 1 index add -1 mul exch 1 index -1 mul 4 -1 roll + moveto 180 rotate + 1 index add + }{ + 270 eq { + dup annotrect + 5 index /RD knownoget { + applyRD + } if + dup 4 -1 roll add 3 -1 roll 3 index add exch + moveto 270 rotate + exch pop currentpoint + pop dup 3 -1 roll add + }{ + dup annotrect + 5 index /RD knownoget { + applyRD + 3 -1 roll add 2 index exch + moveto 1 index add + }{ + 4 -1 roll 2 add 4 -1 roll 2 add 4 -1 roll 4 sub 4 -1 roll 4 sub + 3 -1 roll add 2 index exch + moveto 1 index add + } ifelse + } ifelse + } ifelse + } ifelse + }{ + dup annotrect + 5 index /RD knownoget { + applyRD + 3 -1 roll add 2 index exch + moveto 1 index add + }{ + 4 -1 roll 2 add 4 -1 roll 2 add 4 -1 roll 4 sub 4 -1 roll 4 sub + 3 -1 roll add 2 index exch + moveto 1 index add + } ifelse + } ifelse %% Get the Contents string, if we don't have one, we're done %% @@ -4439,7 +4820,6 @@ currentdict /set_bc_color undef %% and use it immediatley to start the text one line down %% currentpoint ..TextHeight sub moveto - %% Now we process each character code in the string. If we find %% a /r/ or /n then we drop a line. If the character would end up %% outside the Annot Rect, then we drop a line before showing it. @@ -4453,7 +4833,8 @@ currentdict /set_bc_color undef } { 1 string dup 0 4 -1 roll put dup %% llx urx (string) (int) (int) - stringwidth pop currentpoint pop add 3 index gt { + stringwidth pop currentpoint pop add 3 index + gt { currentpoint exch pop 4 index exch ..TextHeight sub moveto } if show @@ -4470,6 +4851,34 @@ currentdict /set_bc_color undef } ifelse } if pop pop + + grestore % in case the contents were rotated + dup /CL knownoget { + dup length 6 eq { + dup aload pop pop pop + } { + dup length 4 eq { + dup aload pop + } { + pop 0 + } ifelse + } ifelse + 4 2 roll + exch 4 -1 roll sub + 3 1 roll exch sub + atan exch + aload pop moveto lineto lineto + currentpoint +% stroke +% 0 1 0 setrgbcolor + moveto currentpoint translate 0 0 moveto + 360 exch sub rotate + currentpoint + -5 -8 rlineto + moveto + 5 -8 rlineto + stroke + } if //endannottransparency exec //false grestore @@ -4505,7 +4914,18 @@ currentdict /set_bc_color undef PDFusingtransparency { .begintransparencytextgroup } if - /Times-Bold findfont exch scalefont setfont % (text) y + /Times-Bold findfont + % re-encode the font to PDFDocEncoding + dup length dict begin + { + 1 index /FID ne 2 index /UniqueID ne and { def } { pop pop } ifelse + } forall + /Encoding /PDFDocEncoding /Encoding findresource def + /FontName /Times-Bold-PDFDocEncoding def + currentdict + end + /Times-Bold-PDFDocEncoding exch definefont + exch scalefont setfont % (text) y gsave 0 0 moveto 1 index //false charpath flattenpath pathbbox @@ -4668,7 +5088,18 @@ currentdict /set_bc_color undef .begintransparencytextgroup } if 0 setgray - /Helvetica findfont 9 scalefont setfont + /Helvetica findfont + % re-encode the font to PDFDocEncoding + dup length dict begin + { + 1 index /FID ne 2 index /UniqueID ne and { def } { pop pop } ifelse + } forall + /Encoding /PDFDocEncoding /Encoding findresource def + /FontName /Helvetica-PDFDocEncoding def + currentdict + end + /Helvetica-PDFDocEncoding exch definefont + 9 scalefont setfont 2 index aload pop 3 1 roll pop pop 30 sub exch 5 add exch moveto show PDFusingtransparency { @@ -4687,7 +5118,18 @@ currentdict /set_bc_color undef .begintransparencytextgroup } if 0 setgray - /Helvetica findfont 9 scalefont setfont + /Helvetica findfont + % re-encode the font to PDFDocEncoding + dup length dict begin + { + 1 index /FID ne 2 index /UniqueID ne and { def } { pop pop } ifelse + } forall + /Encoding /PDFDocEncoding /Encoding findresource def + /FontName /Helvetica-PDFDocEncoding def + currentdict + end + /Helvetica-PDFDocEncoding exch definefont + 9 scalefont setfont dup stringwidth pop 2 index aload pop pop exch pop exch sub exch sub 2 div 2 index aload pop 3 1 roll pop pop 11 sub 3 1 roll add exch moveto @@ -4748,6 +5190,25 @@ currentdict end readonly def ifelse } bind executeonly def +/.PDFPreserveAnnotType? +{ + //false exch + /PreserveAnnotTypes where + { + /PreserveAnnotTypes get + { + dup /* eq exch 2 index eq or + { + pop //true exch + exit + } if + } forall + pop + } + {pop pop //true} + ifelse +} bind executeonly def + /drawannot { % <annot> drawannot - dup annotvisible { gsave @@ -5050,7 +5511,7 @@ currentdict end readonly def gsave dup dup /Subtype knownoget { - dup //.PDFDrawAnnotType? exec + dup //.PDFPreserveAnnotType? exec { //preserveannottypes exch .knownget { exec } { //true } ifelse { @@ -5068,7 +5529,13 @@ currentdict end readonly def }ifelse } if } - {pop} ifelse + { + % Not preserving this type of annotation + % discard teh Subtype + pop + % copy the Annot dictionary and try drawing it instead + dup drawannot + } ifelse % type known } { pop diff --git a/Master/tlpkg/tlgs/Resource/Init/pdf_font.ps b/Master/tlpkg/tlgs/Resource/Init/pdf_font.ps index 81b7af13c7b..98a9e3d4fea 100644 --- a/Master/tlpkg/tlgs/Resource/Init/pdf_font.ps +++ b/Master/tlpkg/tlgs/Resource/Init/pdf_font.ps @@ -1,4 +1,4 @@ -% Copyright (C) 2001-2019 Artifex Software, Inc. +% Copyright (C) 2001-2020 Artifex Software, Inc. % All Rights Reserved. % % This software is provided AS-IS with no warranty, either express or @@ -857,176 +857,222 @@ setglobal /.pdfdfndict mark /defaultfontname /Helvetica .dicttomark readonly def -/pdffindfont { % <font-resource> <fontname> pdffindfont <font> - % If the font isn't available, synthesize one based on - % its descriptor. - dup /Font resourcestatus { - pop pop pdffindcachedfont - } { - 1 index /FontDescriptor knownoget { - % Stack: font-res fontname fontdesc - dup /Flags oget - dup 16#40 and -6 bitshift % 1, oblique/italic - 1 index 16#40000 and -17 bitshift add % 2, bold - exch 16#2 and 2 bitshift add % 8, serif - % We should look at the fixed flag, too. - % Stack: font-res fontname fontdesc properties - - % Even though /FontName is a required key in FontDescriptor dict - % (As of the PDF 1.4 Reference Manual), In the case of missing - % /FontName key, we substitue /BaseFont for the value of /FontName. - % Yet another case of broken PDF's that Adobe Reader accepts. - 1 index dup /FontName known { - /FontName oget - dup type /nametype ne { - ( **** Error: /FontName in FontDescriptor is not a name.\n) - pdfformaterror - ( Output may be incorrect.\n) pdfformaterror - cvn - } if - } { - ( **** Error: FontDescriptor missing required /FontName key. BaseFont name used.\n) - pdfformaterror - ( Output may be incorrect.\n) pdfformaterror - pop 2 index % grab the BaseFont from the stack. - } ifelse - .remove_font_name_prefix - exch - % Analyzes font name and extract "Bold" and "Narrow" properties - % which are not described by the FontDescriptor Flags. - % We also allow the font name analysis to override the Flags setting - % for Italic/Oblique as this gives us results more consistent with - % Acrobat. - 0 2 index //.fontnameproperties exec 7 and or - % Rebind the default font name to Helvetica so that - % fonts with no properties are handled correctly. - //.pdfdfndict begin .substitutefontname end - % Stack: font-res fontname fontdesc substname|null - Fontmap 1 index known - {//false} - { .buildnativefontmap pop NativeFontmap 1 index known not} ifelse - { - % No available good substitution, use the standard one. - pop 1 index .substitutefont - } if - dup 3 index ne { - QUIET not { - (Substituting font ) print dup =only - ( for ) print 2 index =only (.) = flush - } if - % Send a warning to the device, in case its pdfwrite and we are in PDF/A mode - % In that case the substituted font may not (probably doesn't) have glyphs which - % match the /Widths of the original font, and that will cause a fault with PDF/A - % so we need to let the device know. - /SubstitutedFont /EventInfo .special_op - } if - pdffindcachedfont - % Stack: font-res fontname fontdesc font +% This code attempts to use the FontName and FontDescriptor to find a +% 'better' match for a missing font than the default font. There +% are a list of fonts and mappings here (TTfonts) and in gs_font.ps +% (.substitutefaces) which we can use to map from a requested font +% family name to a substitute family. If that fails we check the +% FontDescriptor Flags to attempt a (very slightly) better match. +% We use Times-Roman for serif fonts and Helvetica for non-serif. +% This all seems pretty poor to me, but its long-standing, so we +% won't attempt to meddle with it. +/pdfsubstitutefont { + % Stack: font-res fontname fontdesc + + dup /Flags oget + dup 16#40 and -6 bitshift % 1, oblique/italic + 1 index 16#40000 and -17 bitshift add % 2, bold + exch 16#2 and 2 bitshift add % 8, serif + + % We should look at the fixed flag, too. + % Stack: font-res fontname fontdesc properties + + % Even though /FontName is a required key in FontDescriptor dict + % (As of the PDF 1.4 Reference Manual), In the case of missing + % /FontName key, we substitue /BaseFont for the value of /FontName. + % Yet another case of broken PDF's that Adobe Reader accepts. + 1 index dup /FontName known + { + /FontName oget + dup type /nametype ne + { + ( **** Error: /FontName in FontDescriptor is not a name.\n) + pdfformaterror + ( Output may be incorrect.\n) pdfformaterror + cvn + } if + } + { + ( **** Error: FontDescriptor missing required /FontName key. BaseFont name used.\n) + pdfformaterror + ( Output may be incorrect.\n) pdfformaterror + pop 2 index % grab the BaseFont from the stack. + } ifelse + .remove_font_name_prefix + exch + + % Analyzes font name and extract "Bold" and "Narrow" properties + % which are not described by the FontDescriptor Flags. + % We also allow the font name analysis to override the Flags setting + % for Italic/Oblique as this gives us results more consistent with + % Acrobat. + 0 2 index //.fontnameproperties exec 7 and or + + % Rebind the default font name to Helvetica so that + % fonts with no properties are handled correctly. + //.pdfdfndict begin .substitutefontname end + + % Stack: font-res fontname fontdesc substname|null + Fontmap 1 index known + {//false} + { .buildnativefontmap pop NativeFontmap 1 index known not} + ifelse - % Some non-compliant files are missing FirstChar/LastChar, - % despite referencing a non-base14 font - 3 index /FirstChar knownoget + { + % No available good substitution, use the standard one. + pop 1 index .substitutefont + } if + + dup 3 index ne + { + QUIET not + { + (Substituting font ) print dup =only + ( for ) print 2 index =only (.) = flush + } if + % Send a warning to the device, in case its pdfwrite and we are in PDF/A mode + % In that case the substituted font may not (probably doesn't) have glyphs which + % match the /Widths of the original font, and that will cause a fault with PDF/A + % so we need to let the device know. + /SubstitutedFont /EventInfo .special_op + } if + + pdffindcachedfont + % Stack: font-res fontname fontdesc font + + % Some non-compliant files are missing FirstChar/LastChar, + % despite referencing a non-base14 font + 3 index /FirstChar knownoget + { + 0 % push an initial value for accumating the Widths + 0 string % and an empty string to interrogate the font + 7 index /Widths knownoget + { + 0 1 2 index length 1 sub { - 0 % push an initial value for accumating the Widths - 0 string % and an empty string to interrogate the font - 7 index /Widths knownoget + dup 2 index exch get + dup type /packedarraytype eq {exec} if % Handle entries which are indirect references (seriously ? !!) + dup 0 gt % We ignore entries of zero in the widths array { - 0 1 2 index length 1 sub - { - dup 2 index exch get - dup type /packedarraytype eq {exec} if % Handle entries which are indirect references (seriously ? !!) - dup 0 gt % We ignore entries of zero in the widths array - { - exch 5 index add % add FirstChar to the idx to get a char code - dup 64 gt 1 index 91 lt and % we only want to consider A~Z and.... - 1 index 96 gt 2 index 123 lt and or % ... a~z - { - exch - 5 -1 roll add 4 1 roll % add the width to the accumulator on the stack - 1 string dup 0 4 -1 roll put - 3 -1 roll concatstrings exch % add the char code to the string - } - { - pop pop - } ifelse - } - { - pop pop - } ifelse - } for - pop % get rid of the Widths array - 3 -1 roll pop % get rid of the FirstChar value - dup length dup 0 gt + exch 5 index add % add FirstChar to the idx to get a char code + dup 64 gt 1 index 91 lt and % we only want to consider A~Z and.... + 1 index 96 gt 2 index 123 lt and or % ... a~z { - 3 -1 roll exch div % calculate an average width from the Widths array - - gsave - 2 index 10 scalefont setfont - exch dup length exch stringwidth - grestore - pop 100 mul exch div div - % Only make the font smaller/narrower, not larger/wider - dup 1.0 lt - { - 0 0 2 index 0 0 6 array astore - exch //true .copyfontdict - dup /FontMatrix get 3 -1 roll matrix concatmatrix - exch dup 3 -1 roll /FontMatrix exch put - % we don't need to definfont here, we can leave that to .completefont below - } - { - pop - } ifelse + exch + 5 -1 roll add 4 1 roll % add the width to the accumulator on the stack + 1 string dup 0 4 -1 roll put + 3 -1 roll concatstrings exch % add the char code to the string } { - % no suitable Widths entries - carry on and hope for the best...... - pop pop pop + pop pop } ifelse } { - % Broken file: no Widths array for non-base14 font - carry on and hope for the best...... - ( **** Warning: Widths array missing in FontDescriptor for non-base14 font\n) - pdfformatwarning - pop pop pop + pop pop + } ifelse + } for + pop % get rid of the Widths array + 3 -1 roll pop % get rid of the FirstChar value + dup length dup 0 gt + { + 3 -1 roll exch div % calculate an average width from the Widths array + gsave + 2 index 10 scalefont setfont + exch dup length exch stringwidth + grestore + pop 100 mul exch div div + % Only make the font smaller/narrower, not larger/wider + dup 1.0 lt + { + 0 0 2 index 0 0 6 array astore + exch //true .copyfontdict + dup /FontMatrix get 3 -1 roll matrix concatmatrix + exch dup 3 -1 roll /FontMatrix exch put + % we don't need to definfont here, we can leave that to .completefont below + } + { + pop } ifelse } { - ( **** Warning: FirstChar value missing in FontDescriptor for non-base14 font\n) - pdfformatwarning + % no suitable Widths entries - carry on and hope for the best...... + pop pop pop } ifelse - % Stack: font-res fontname fontdesc font - % If this is a small-caps font, replace the CharString - % entries for a..z. - - exch /Flags oget 16#20000 and 0 ne { - //true .copyfontdict - dup /CharStrings 2 copy get dup length dict .copydict - % stack: font-res fontname font font /CharStrings CharStringsdict - 5 index /FirstChar get 97 .max - 6 index /LastChar get 122 .min 1 exch { - % Stack: font-res fontname font' font' /CharStrings charstrings code - % Note that this only remaps a-z, not accented characters. - 6 index /Widths oget 1 index 8 index /FirstChar get sub oget - 1 string dup 0 5 -1 roll put - % Stack: font-res font' font' /CharStrings charstrings code - % width (x) - 2 index exch dup cvn exch - dup 0 2 copy get 32 sub put 4 -1 roll { - % Stack: operand (X) width - 0 setcharwidth exch pop - currentfont /FontMatrix get matrix invertmatrix concat - 0.7 dup scale 0 0 moveto show - } /exec cvx 4 packedarray cvx put - } for put - } if - dup /FontName get 2 index ne { - //true .copyfontdict - 2 copy exch /FontName exch put - } if - exch pop .completefont - } { - % No descriptor available, use the default algorithm. + } + { + % Broken file: no Widths array for non-base14 font - carry on and hope for the best...... + ( **** Warning: Widths array missing in FontDescriptor for non-base14 font\n) + pdfformatwarning + pop pop pop + } ifelse + } + { + ( **** Warning: FirstChar value missing in FontDescriptor for non-base14 font\n) + pdfformatwarning + } ifelse + % Stack: font-res fontname fontdesc font + + % If this is a small-caps font, replace the CharString + % entries for a..z. + exch /Flags oget 16#20000 and 0 ne + { + //true .copyfontdict + dup /CharStrings 2 copy get dup length dict .copydict + % stack: font-res fontname font font /CharStrings CharStringsdict + 5 index /FirstChar get 97 .max + 6 index /LastChar get 122 .min 1 exch + { + + % Stack: font-res fontname font' font' /CharStrings charstrings code + % Note that this only remaps a-z, not accented characters. + 6 index /Widths oget 1 index 8 index /FirstChar get sub oget + 1 string dup 0 5 -1 roll put + + % Stack: font-res font' font' /CharStrings charstrings code + % width (x) + 2 index exch dup cvn exch + dup 0 2 copy get 32 sub put 4 -1 roll + { + % Stack: operand (X) width + 0 setcharwidth exch pop + currentfont /FontMatrix get matrix invertmatrix concat + 0.7 dup scale 0 0 moveto show + } /exec cvx 4 packedarray cvx put + } for put + } if + + dup /FontName get 2 index ne + { + //true .copyfontdict + 2 copy exch /FontName exch put + } if + exch pop .completefont +} bind executeonly def + +/pdffindfont { % <font-resource> <fontname> pdffindfont <font> + % If the font isn't available, synthesize one based on + % its descriptor. + dup /Font resourcestatus + { + pop pop pdffindcachedfont + } + { + 1 index /FontDescriptor knownoget { + /SUBSTFONT where not + { + pdfsubstitutefont + } + { + % User has defined SUBSTFONT, use the defined substitute font, do not + % try to be clever + pop % the dictionary containing SUBSTFONT + pop % the FontDescriptor + pdffindcachedfont + }ifelse + } + { + % No descriptor available, use the default algorithm. pdffindcachedfont } ifelse } ifelse @@ -2376,9 +2422,25 @@ currentdict /CMap_read_dict undef } 2 bndef <01000401> % Type 1C - { exch pop - 1 index /Subtype knownoget dup { pop /CIDFontType0 eq } if { - readCIDFontType0C + { + exch pop + + 1 index /Subtype knownoget { + dup /CIDFontType2 eq{ + pop + ( **** Error: Subtype of a Type 1 CID font is not /CIDFontType0\n) pdfformaterror + ( Output may be incorrect.\n) pdfformaterror + 1 index /Subtype /CIDFontType0 put + readCIDFontType0C + } + { + /CIDFontType0 eq { + readCIDFontType0C + } + { + readType1C + } ifelse + } ifelse } { readType1C } ifelse @@ -2473,23 +2535,22 @@ currentdict /bndef undef % if the font was defined in-line, we won't have a object number dup /.gs.pdfobj# .knownget not { //null } if } { - dup /FontDescriptor knownoget { % if the font was defined in-line, we won't have a object number - dup /.gs.pdfobj# .knownget not { //null }if - dup //null eq { - exch pop - }{ - exch dup /FontFile knownoget not { - dup /FontFile2 knownoget not { - dup /FontFile3 knownoget not { - pop pop //null - } {pop pop}ifelse + dup /.gs.pdfobj# .knownget not { //null }if + dup //null eq not { + 1 index /FontDescriptor knownoget { + dup /FontFile knownoget not { + dup /FontFile2 knownoget not { + dup /FontFile3 knownoget not { + pop pop //null } {pop pop}ifelse - }{pop pop}ifelse - }ifelse - }{ - //null - } ifelse + } {pop pop}ifelse + }{pop pop}ifelse + } + { + pop //null + } ifelse + }if } ifelse 3 1 roll diff --git a/Master/tlpkg/tlgs/Resource/Init/pdf_main.ps b/Master/tlpkg/tlgs/Resource/Init/pdf_main.ps index 7690bae0f92..d7933700f73 100644 --- a/Master/tlpkg/tlgs/Resource/Init/pdf_main.ps +++ b/Master/tlpkg/tlgs/Resource/Init/pdf_main.ps @@ -1,4 +1,4 @@ -% Copyright (C) 2001-2019 Artifex Software, Inc. +% Copyright (C) 2001-2020 Artifex Software, Inc. % All Rights Reserved. % % This software is provided AS-IS with no warranty, either express or @@ -47,7 +47,7 @@ userdict /GS_PDF_ProcSet undef % PDF 1.1 operators /BX { /BXlevel BXlevel 1 add store } bind executeonly /EX { /BXlevel BXlevel 1 sub store } bind executeonly - /PS { cvx exec } bind executeonly + /PS { DOPS { cvx exec } { pop } ifelse } bind executeonly % PS disabled by default, as in pdf_draw.ps DoPS % PDF 1.2 operators /BMC { /BMClevel BMClevel 1 add store @@ -278,6 +278,16 @@ systemdict begin } bind odef currentdict /runpdfstring .undef +/DisablePageHandlerDevice +{ + systemdict /FirstPage known + systemdict /LastPage known or + systemdict /Pagelist known or + { + <</DisablePageHandler //true>> setpagedevice + } if +} bind def + /runpdfbegin { % <file> runpdfbegin - userdict begin % It turns out that the PDF interpreter uses memory more @@ -300,6 +310,8 @@ currentdict /runpdfstring .undef %% resources and needs this definition in place. <</MaxOpStack -1>> setuserparams + //DisablePageHandlerDevice exec + 0 setobjectformat /Page# //null def /Page //null def @@ -311,8 +323,9 @@ currentdict /runpdfstring .undef /CumulativePageCount currentpagedevice /PageCount get def } bind executeonly def +currentdict /DisablePageHandlerDevice undef + /runpdfpagerange { % - runpdfpagerange <firstpage#> <lastpage#> -<</DisablePageHandler //true>> setpagedevice /PortfolioPage where { pop PortfolioPage cvi dup pdfpagecount add % a b+1 @@ -321,8 +334,8 @@ currentdict /runpdfstring .undef dup 3 index exch cvs pop % a b+1 /P (b+1) store 1 sub % a b - /FirstPage where { pop FirstPage <</DisablePageHandler //true>> setpagedevice} { 1 } ifelse - /LastPage where { pop LastPage <</DisablePageHandler //true>> setpagedevice} {2000000000} ifelse % a b fp lp + /FirstPage where { pop FirstPage} { 1 } ifelse + /LastPage where { pop LastPage} {2000000000} ifelse % a b fp lp 2 index 2 index lt { % b < fp 1e10 } { @@ -395,7 +408,6 @@ currentdict /runpdfstring .undef pop } forall - <</DisablePageHandler //true>> setpagedevice /PDFPageList pdfpagecount 1 add array def { (,) search { @@ -477,7 +489,6 @@ currentdict /runpdfstring .undef 1 pdfpagecount }{ /FirstPage where { - <</DisablePageHandler //true>> setpagedevice pop FirstPage dup pdfpagecount gt { (\nRequested FirstPage is greater than the number of pages in the file: ) print pdfpagecount = flush @@ -485,7 +496,7 @@ currentdict /runpdfstring .undef } { 1 } ifelse - /LastPage where {<</DisablePageHandler //true>> setpagedevice pop LastPage pdfpagecount .min } { pdfpagecount } ifelse + /LastPage where {pop LastPage pdfpagecount .min } { pdfpagecount } ifelse 1 index 1 index gt { ( No pages will be processed \(FirstPage > LastPage\).) = flush } { @@ -513,7 +524,12 @@ currentdict /runpdfstring .undef { dup /Page# exch store QUIET not { (Page ) print dup //== exec flush } if - pdfgetpage pdfshowpage + pdfgetpage + dup //null ne { pdfshowpage } { + ( **** Error: Page #) pdfformaterror Page# 10 string cvs pdfformaterror + ( not found.\n) pdfformaterror + /dopdfpages cvx /syntaxerror signalerror + } ifelse }{ pop }ifelse @@ -538,6 +554,7 @@ currentdict /runpdfstring .undef PDFTopSave restore end % userdict 2 vmreclaim % couldn't hurt + <</DisablePageHandler //false>> setpagedevice } bind executeonly def % Copy stream to an external temporary file and @@ -1879,7 +1896,7 @@ currentdict /xref-char-dict undef parent_obj_get % not found -- check it's parent. } ifelse } { - pop pop pop 0 + pop pop 0 } ifelse } bind executeonly def @@ -2076,14 +2093,19 @@ currentdict /xref-char-dict undef /pdffindpageref { % <int> pdffindpage <objref> dup pdffindpage? % Stack: index countleft noderef - 1 index 1 ne { pop pop /pdffindpage cvx /rangecheck signalerror } if - exch pop - PageIndex 2 index 1 sub 65533 .min 2 index oforce put - PageNumbers 1 index oforce 3 index dup 65534 le - { put } - { pop pop pop } % don't store more than 65534 pagenumbers + dup //null ne { + 1 index 1 ne { pop pop /pdffindpage cvx /rangecheck signalerror } if + exch pop + PageIndex 2 index 1 sub 65533 .min 2 index oforce put + PageNumbers 1 index oforce 3 index dup 65534 le + { put } + { pop pop pop } % don't store more than 65534 pagenumbers + ifelse + } { + exch pop % return the //null + } ifelse - exch pop + exch pop % pop the page number, return the object or null } bind executeonly def /pdffindpage { % <int> pdffindpage <pagedict> pdffindpageref oforce @@ -2339,8 +2361,20 @@ end readonly def /get_media_box { % <pagedict> get_media_box <box> <bool> /MediaBox pget { - oforce_array //true - } { + oforce_array + dup length 4 eq { + //true + } + { + pop + ( **** Error: Page has an invalid /MediaBox attribute. Using the current page size.\n) + pdfformaterror + ( Output may be incorrect.\n) pdfformaterror + [ 0 0 currentpagedevice /PageSize get aload pop ] + //false + }ifelse + } + { ( **** Error: Page has no /MediaBox attribute. Using the current page size.\n) pdfformaterror ( Output may be incorrect.\n) pdfformaterror @@ -2493,9 +2527,26 @@ end readonly def 1 } { 1 index /UserUnit knownoget { - PDFDEBUG { (Scaling due to UserUnit by ) print dup = flush } if + /PassUserUnit /GetDeviceParam .special_op { + exch pop dup { + [ /UserUnit 4 -1 roll .pdfputparams pop pop 1 exch + } if + }{ + //false + }ifelse + + not { + PDFDEBUG { (Scaling due to UserUnit by ) print dup = flush } if + } if } { - 1 + /PassUserUnit /GetDeviceParam .special_op { + exch pop { + [ /UserUnit 1 .pdfputparams pop pop + } if + 1 + }{ + 1 + } ifelse } ifelse } ifelse } ifelse @@ -2573,8 +2624,23 @@ currentdict /PDF2PS_matrix_key undef % Set the page size. //systemdict /NoUserUnit .knownget not { //false } if not { 3 index /UserUnit knownoget { - dup 4 -1 roll mul 3 1 roll mul - } if + /PassUserUnit /GetDeviceParam .special_op { + exch pop dup { + [ /UserUnit 4 -1 roll .pdfputparams pop pop + } if + }{ + //false + }ifelse + not { + dup 4 -1 roll mul 3 1 roll mul + } if + } { + /PassUserUnit /GetDeviceParam .special_op { + exch pop { + [ /UserUnit 1 .pdfputparams pop pop + } if + }if + } ifelse } if } ifelse 2 array astore /PageSize exch def @@ -2707,7 +2773,7 @@ currentdict /PDF2PS_matrix_key undef dup /PDFusingtransparency exch def { % If the current device isn't CMYK, or if it is a device that (currently) supports transparency % we don't need the special handling of Overprint transparency, so disable the checking. - currentpagedevice dup /Colors get 4 lt + currentpagedevice dup /Colors get 4 lt 1 index /SimulateOverprint get not or exch /HaveTransparency .knownget not { //false } if or % device needs special Oveprint handling /setup_trans exch @@ -2740,7 +2806,7 @@ currentdict /PDF2PS_matrix_key undef .poppdf14devicefilter % NB: reset to DefaultQstate will also restore transfer function /DefaultQstate qstate store % device has changed -- reset DefaultQstate } { - /setup_trans { pop } def % no-op this if the page doesn't use transparency + /setup_trans { pop pop } def % no-op this if the page doesn't use transparency % NB: original will be restored from PDFsave showpagecontents } ifelse @@ -2856,7 +2922,20 @@ currentdict /PDF2PS_matrix_key undef % Draw the annotations //systemdict /ShowAnnots .knownget not { //true } if { /Annots knownoget { - { oforce + dup type /arraytype eq { + { + /AnnotDrawCheck exch % marker to clean up stack on error + {oforce} stopped + { + ( **** Error: Unable to draw an annotation.\n) pdfformaterror + ( Output may be incorrect.\n) pdfformaterror + count -1 0 { % make sure we don't go past the top of the stack + pop % remove the counter + /AnnotDrawCheck eq {exit} if % remove object and check if its the marker, exit if it is + } for + } + { + exch pop dup //null ne { .writepdfmarks %% @@ -2878,7 +2957,14 @@ currentdict /PDF2PS_matrix_key undef } { pop } ifelse + } ifelse } forall + } + { + ( **** Error: Annotation array is not an array, ignoring it.\n) pdfformaterror + ( Output may be incorrect.\n) pdfformaterror + pop + } ifelse } if } if //systemdict /ShowAcroForm .knownget { //true eq } { //false } ifelse { @@ -3062,36 +3148,56 @@ currentdict /PDF2PS_matrix_key undef /annotsusetransparency { % <page dict> annotsusetransparency <bool> //false exch % Assume no transparency /Annots knownoget { % Get Annots array + dup type /arraytype eq { + { + /AnnotTransparencyCheck exch % marker to clean up stack on error + {oforce} stopped + { + ( **** Error: Unable to check an annotation for use of transparency.\n) pdfformaterror + ( Output may be incorrect.\n) pdfformaterror + count -1 0 { % make sure we don't go past the top of the stack + pop % remove the counter + /AnnotTransparencyCheck eq {exit} if % remove object and check if its the marker, exit if it is + } for + } + { + exch pop % remove the 'on error' marker + dup //null ne { + dup /Subtype knownoget { + /Highlight eq { % Highlight annotation is always implemented + pop pop //true exit % as transparency. + } if + } if + dup /AP knownoget { % Get appearance dict for the annoation + /N knownogetdict { % Get the /N (i.e. normal) appearance stream + 4 dict exch resourceusestransparency { pop pop //true exit } if + } if + } if % If AP dict known + dup /BM knownoget { + pop pop pop //true exit + } if + dup /CA knownoget { + 1 le { + pop pop //true exit + } if + } if + /ca knownoget { + 1 le { + pop //true exit + } if + } if + } { + pop + } ifelse + } ifelse + } forall % For all annots on the page + } { - oforce - dup //null ne { - dup /Subtype knownoget { - /Highlight eq { % Highlight annotation is always implemented - pop pop //true exit % as transparency. - } if - } if - dup /AP knownoget { % Get appearance dict for the annoation - /N knownogetdict { % Get the /N (i.e. normal) appearance stream - 4 dict exch resourceusestransparency { pop pop //true exit } if - } if - } if % If AP dict known - dup /BM knownoget { - //true exit - } if - dup /CA knownoget { - 1 le { - pop pop //true exit - } if - } if - /ca knownoget { - 1 le { - pop //true exit - } if - } if - } { - pop - } ifelse - } forall % For all annots on the page + ( **** Error: Annotation array is not an array, ignoring it.\n) pdfformaterror + ( Output may be incorrect.\n) pdfformaterror + pop + } + ifelse } if } bind executeonly def @@ -3208,17 +3314,24 @@ currentdict /PDF2PS_matrix_key undef % <spotcolordict> <loopdict> <annotsarray> % annotsspotcolors <spotcolordict> <loopdict> /annotsspotcolors { - { oforce - dup //null ne { - /AP knownoget { % Get appearance dict for the annoation - /N knownogetdict { % Get the /N (i.e. normal) appearance stream - resourcespotcolors - } if % If normal appearance streamknown - } if % If AP dict known - } { - pop - } ifelse - } forall + dup type /arraytype eq { + { oforce + dup //null ne { + /AP knownoget { % Get appearance dict for the annoation + /N knownogetdict { % Get the /N (i.e. normal) appearance stream + resourcespotcolors + } if % If normal appearance streamknown + } if % If AP dict known + } { + pop + } ifelse + } forall + } + { + ( **** Error: Annotation array is not an array, ignoring it.\n) pdfformaterror + ( Output may be incorrect.\n) pdfformaterror + pop + } ifelse } bind executeonly def % Determine spot colors are used within a page. We are creating a dict to @@ -3242,6 +3355,7 @@ currentdict /PDF2PS_matrix_key undef { /Parent knownoget { + dup /Pages known not { pop exit } if % not a valid Page Tree ancestor dup 4 1 roll resourcespotcolors 3 -1 roll @@ -3534,6 +3648,43 @@ currentdict /PDF2PS_matrix_key undef } bind executeonly def end % pdfdict + + +systemdict /ALLOWPSTRANSPARENCY get +{ + /.setopacityalpha + { + /.setfillconstantalpha where + { + pop + ( **** WARNING: .setopacityalpha is deprecated (as of 9.53.0) and will be removed in a future release\n) print + ( **** See .setfillconstantalpha/.setalphaisshape for the improved solution\n) print flush + false .setalphaisshape + dup .setfillconstantalpha + .setstrokeconstantalpha + } + { + /.setopacityalpha /undefined cvx signalerror + } ifelse + } bind def + + /.setshapealpha + { + /.setfillconstantalpha where + { + pop + ( **** WARNING: .setshapealpha is deprecated (as of 9.53.0) and will be removed in a future release.\n) print + ( **** See .setfillconstantalpha/.setalphaisshape for the improved solution\n) print flush + true .setalphaisshape + dup .setfillconstantalpha + .setstrokeconstantalpha + } + { + /.setshapealpha /undefined cvx signalerror + } ifelse + } bind def +} if + .setglobal %% This list of operators are used internally by various parts of the Ghostscript PDF interpreter. @@ -3545,24 +3696,27 @@ end % pdfdict /.setfillcolor /.setfillcolorspace /.setstrokecolor /.setstrokecolorspace /.currentrenderingintent /.setrenderingintent /.currenttextrenderingmode /.settextspacing /.currenttextspacing /.settextleading /.currenttextleading /.settextrise /.currenttextrise /.setwordspacing /.currentwordspacing /.settexthscaling /.currenttexthscaling -/.settextlinematrix /.currenttextlinematrix /.currenttextmatrix /.settextmatrix /.currentblendmode -/.currentopacityalpha /.currentshapealpha /.currenttextknockout -/.pushextendedgstate /.popextendedgstate /.begintransparencytextgroup -/.endtransparencytextgroup /.begintransparencymaskgroup /.begintransparencymaskimage /.endtransparencymask /.image3x -/.abortpdf14devicefilter /.pdfinkpath /.pdfFormName /.setstrokeconstantalpha -/.setfillconstantalpha /.setalphaisshape /.currentalphaisshape -/.settextspacing /.currenttextspacing /.settextleading /.currenttextleading /.settextrise /.currenttextrise -/.setwordspacing /.currentwordspacing /.settexthscaling /.currenttexthscaling /.setPDFfontsize /.currentPDFfontsize -/.setdistillerparams - -% Used by our own test suite files -%/.pushpdf14devicefilter % transparency-example.ps -%/.poppdf14devicefilter % transparency-example.ps -%/.setopacityalpha % transparency-example.ps -%/.setshapealpha % transparency-example.ps -%/.endtransparencygroup % transparency-example.ps +/.settextlinematrix /.currenttextlinematrix /.currenttextmatrix /.settextmatrix /.pushextendedgstate +/.popextendedgstate + +/.pdfinkpath /.pdfFormName /.settextspacing /.currenttextspacing /.settextleading /.currenttextleading +/.settextrise /.currenttextrise /.setwordspacing /.currentwordspacing /.settexthscaling /.currenttexthscaling +/.setPDFfontsize /.currentPDFfontsize /.setdistillerparams % undefining these causes errors/incorrect output -%/.settextrenderingmode /.setblendmode /.begintransparencygroup /.settextknockout /.setstrokeoverprint /.setfilloverprint -%/.currentstrokeoverprint /.currentfilloverprint /.currentfillconstantalpha /.currentstrokeconstantalpha +%/.settextrenderingmode ] systemdict .undefinternalnames + +% The following are split out allowing control via ALLOWPSTRANSPARENCY command line param +% The examples/transparency_example.ps uses some of these (on the first line). +[ + /.pushpdf14devicefilter /.poppdf14devicefilter /.setstrokeconstantalpha /.setfillconstantalpha /.endtransparencygroup + /.currentblendmode /.currenttextknockout /.begintransparencytextgroup + /.endtransparencytextgroup /.begintransparencymaskgroup /.begintransparencymaskimage /.begintransparencypagegroup + /.endtransparencymask /.image3x /.abortpdf14devicefilter /.setstrokeconstantalpha /.setfillconstantalpha /.setalphaisshape /.currentalphaisshape + % undefining these causes errors/incorrect output + %/.setblendmode /.begintransparencygroup /.settextknockout /.setstrokeoverprint /.setfilloverprint + %/.currentstrokeoverprint /.currentfilloverprint /.currentfillconstantalpha /.currentstrokeconstantalpha + %/.setSMask /.currentSMask + +] systemdict dup /ALLOWPSTRANSPARENCY get {pop pop}{.undefinternalnames}ifelse diff --git a/Master/tlpkg/tlgs/Resource/Init/pdf_ops.ps b/Master/tlpkg/tlgs/Resource/Init/pdf_ops.ps index d594035c066..47ff512d927 100644 --- a/Master/tlpkg/tlgs/Resource/Init/pdf_ops.ps +++ b/Master/tlpkg/tlgs/Resource/Init/pdf_ops.ps @@ -1,4 +1,4 @@ -% Copyright (C) 2001-2019 Artifex Software, Inc. +% Copyright (C) 2001-2020 Artifex Software, Inc. % All Rights Reserved. % % This software is provided AS-IS with no warranty, either express or @@ -279,8 +279,8 @@ currentdict /gput_always_allow .undef /DeviceCMYK { [0 0 0 1] cvx } bind executeonly /CIEBasedA { 0 } bind executeonly /CIEBasedABC { [0 0 0] cvx } bind executeonly - /CalGray { pop /DeviceGray 0 } bind executeonly - /CalRGB { pop /DeviceRGB [0 0 0] cvx } bind executeonly + /CalGray { 0 } bind executeonly + /CalRGB { [0 0 0] cvx } bind executeonly /Lab {[0 0 0] cvx } bind executeonly /ICCBased { [ 1 index 1 oget /N get { 0 } repeat ] cvx } bind executeonly /Separation { 1 } bind executeonly @@ -304,7 +304,6 @@ currentdict /gput_always_allow .undef 4 2 roll //CSdict exch get exec exch .setfillcolorspace exec {.setfillcolor} stopped { - (error) == flush cleartomark [//null /DeviceGray //null /DeviceRGB /DeviceCMYK] exch {get} stopped @@ -483,19 +482,19 @@ currentdict /gput_always_allow .undef % ---------------- Color installation ---------------- % % Establish a given color (and color space) as current. -/.settransparencyparams { % <alpha> <smask> .settransparencyparams - +/.settransparencyparams { % <smask> .settransparencyparams - PDFusingtransparency { .currentalphaisshape { - 1 .setopacityalpha exch .setshapealpha 1 + 1 } { - 1 .setshapealpha exch .setopacityalpha 0 + 0 } ifelse % Set the soft mask by rendering the XObject. Doing this every time % is obviously very inefficient; we'll improve it later. .settransparencymask } { - pop pop + pop } ifelse } bind executeonly def /.settransparencymask { % <paramdict> <masknum> .settransparencymask - @@ -517,16 +516,7 @@ currentdict /gput_always_allow .undef } ifelse } ifelse } bind executeonly def -% (Non-mask) images must execute setfillblend. -/setfillblend { - .currentfillconstantalpha - .currentSMask .settransparencyparams -} bind executeonly def -/setfillstate { - setfillblend -} bind executeonly def -/setstrokestate { - .currentstrokeconstantalpha +/setsmaskstate { .currentSMask .settransparencyparams } bind executeonly def /Cdict 15 dict dup begin % <color...> <colorspace> -proc- - @@ -673,12 +663,12 @@ end def } ifelse } bind executeonly def -/OPsaveDstack 6 dict def % for GroupPushed, saveOP, saveSA, saveBM +/OPsaveDstack 6 dict def % for GroupPushed, saveOP, saveFillAlpha, saveBM //OPsaveDstack begin /GroupPushed //false def /ChangeBM //false def - /saveOA 1 def - /saveSA 1 def + /saveStrokeAlpha 1 def + /saveFillAlpha 1 def /saveBM /Normal def /previous 1 dict def % for nested setup_trans levels end @@ -694,14 +684,14 @@ end /okOPcs mark /DeviceGray 0 /DeviceCMYK 1 /DeviceN 2 /Separation 3 .dicttomark def % Take care of pushing a transparency group if we need it for SMask or for Overprint.. -% After pushing the group, we save the opacityalpha and shapealpha and change them +% After pushing the group, we save the ca and CA and change them % both to 1. For overprint if the colorspace is acceptable, also change to % CompatibleOverprint if the device needs it. % NB: setup_trans is defined as either setupOPtrans (for devices that can support % overprint, or as setupSMtrans which pushes a group for SMask. % Also see 'teardown_trans' that pops the group and resets the changed values. -/setupOPtrans % <fillop|strokeop> setup_trans +/setupOPtrans % [ pathbbox ] <fillop|strokeop> setup_trans { % Check OP and BM in case we need to push a group //OPsaveDstack begin //Dpush exec % push the current OPsaveDstack values into 'previous' @@ -719,52 +709,46 @@ end } ifelse .currentSMask //null ne or { % push a group for OP or SMask mark /Subtype /Group /Isolated .currentSMask //null ne .dicttomark - 1 index /stroke eq { - % BBox needs to include line width / line join expansion. - gsave strokepath pathbbox grestore - } { - pathbbox % fill/eofill cases - } ifelse + 2 index aload pop % pathbbox .begintransparencygroup - % After group pushed, set opacityalpha, shapealpha and blendmode - /saveOA .currentopacityalpha def - /saveSA .currentshapealpha def - 1 .setopacityalpha 1 .setshapealpha + % After group pushed, set alphas and blendmode + /saveStrokeAlpha .currentstrokeconstantalpha def + /saveFillAlpha .currentfillconstantalpha def + 1 .setfillconstantalpha 1 .setstrokeconstantalpha /GroupPushed //true def - } if + } { + /GroupPushed //false def + } ifelse % we may change to CompatibleOverprint even if we didn't push a group. ChangeBM { /saveBM .currentblendmode def /CompatibleOverprint .setblendmode } if pop % fillop/strokeop + pop % pathbbox array end % OPsaveDstack } bind executeonly def % Also see 'teardown_trans' that pops the group and resets the changed values. -/setupSMtrans % <fillop|strokeop> setup_trans +/setupSMtrans % [ pathbbox ] <fillop|strokeop> setup_trans { //OPsaveDstack begin //Dpush exec % push the current OPsaveDstack values into 'previous' .currentSMask //null ne 1 index /image ne and % only push for SMask if not from image { mark /Subtype /Group /Isolated //true .dicttomark - exch /stroke eq { - % BBox needs to include line width / line join expansion. - gsave strokepath pathbbox grestore - } { - pathbbox % fill/eofill cases - } ifelse + 2 index aload pop % pathbbox .begintransparencygroup - % After group pushed, set opacityalpha, shapealpha and blendmode - /saveOA .currentopacityalpha def - /saveSA .currentshapealpha def - 1 .setopacityalpha 1 .setshapealpha + % After group pushed, set alphas and blendmode + /saveStrokeAlpha .currentstrokeconstantalpha def + /saveFillAlpha .currentfillconstantalpha def + 1 .setfillconstantalpha 1 .setstrokeconstantalpha /GroupPushed //true def } { /GroupPushed //false def - pop % fillop/strokeop } ifelse end % OPsaveDstack + pop % fillop/strokeop + pop % pathbbox array } bind executeonly def % If a transparency group was pushed, pop it, and reset the settings. @@ -772,9 +756,9 @@ end /teardown_trans { //OPsaveDstack begin GroupPushed { - % pop the group, then restore the opacityalpha and shapealpha + % pop the group, then restore the alphas .endtransparencygroup % end the group - saveOA .setopacityalpha saveSA .setshapealpha + saveStrokeAlpha .setstrokeconstantalpha saveFillAlpha .setfillconstantalpha } if % Also, if we changed the BM, restore it (AFTER the group was popped) .currentblendmode /CompatibleOverprint eq { @@ -791,9 +775,23 @@ currentdict dup /Dpush .undef /Dpop .undef /fsexec % <fillop|strokeop> fsexec - { PDFusingtransparency { - dup setup_trans - cvx exec - teardown_trans + dup /stroke eq 1 index /.fillstroke eq or 1 index /.eofillstroke eq or { + % BBox needs to include line width / line join expansion. + % strokepath will return empty path (no currentpoint) if nothing is stroked + { gsave strokepath pathbbox } stopped grestore { + % If we get an error, just emit an empty box + 0 0 0 0 + } if + } { + % If we get an error, just emit an empty box + { pathbbox } stopped { 0 0 0 0 } if + } ifelse + % pathbbox valid -- proceed with drawing + 4 array astore % pathbbox + 1 index + setup_trans + cvx exec + teardown_trans } { cvx exec } ifelse @@ -896,7 +894,7 @@ currentdict dup /Dpush .undef /Dpop .undef /S { OFFlevels length 0 eq { - setstrokestate .swapcolors /stroke fsexec .swapcolors + setsmaskstate .swapcolors /stroke fsexec .swapcolors } { newpath } ifelse @@ -904,7 +902,7 @@ currentdict dup /Dpush .undef /Dpop .undef /f { OFFlevels length 0 eq { - setfillstate /fill fsexec + setsmaskstate /fill fsexec } { newpath } ifelse @@ -912,7 +910,7 @@ currentdict dup /Dpush .undef /Dpop .undef /f* { OFFlevels length 0 eq { - setfillstate /eofill fsexec + setsmaskstate /eofill fsexec } { newpath } ifelse @@ -924,23 +922,7 @@ currentdict dup /Dpush .undef /Dpop .undef /B { OFFlevels length 0 eq { - PDFusingtransparency { - % knockout trans group around the filled and stroked object - mark - /Isolated //true /Knockout //true - .dicttomark - % strokepath will return empty path (no currentpoint) if nothing is stroked - gsave { strokepath pathbbox } stopped grestore not { - 1 .setopacityalpha - .begintransparencygroup - gsave setfillstate fill grestore - setstrokestate .swapcolors /stroke fsexec .swapcolors - .endtransparencygroup - } { newpath pop } ifelse - } { - gsave setfillstate fill grestore - setstrokestate .swapcolors /stroke fsexec .swapcolors - } ifelse + setsmaskstate /.fillstroke fsexec } { newpath } ifelse @@ -950,23 +932,7 @@ currentdict dup /Dpush .undef /Dpop .undef /B* { OFFlevels length 0 eq { - PDFusingtransparency { - % knockout trans group around the filled and stroked object - mark - /Isolated //true /Knockout //true - .dicttomark - % strokepath will return empty path (no currentpoint) if nothing is stroked - gsave { strokepath pathbbox } stopped grestore not { - 1 .setopacityalpha - .begintransparencygroup - gsave setfillstate eofill grestore - setstrokestate .swapcolors /stroke fsexec .swapcolors - .endtransparencygroup - } { newpath pop } ifelse - } { - gsave setfillstate eofill grestore - setstrokestate .swapcolors /stroke fsexec .swapcolors - } ifelse + setsmaskstate /.eofillstroke fsexec } { newpath } ifelse @@ -977,54 +943,19 @@ currentdict dup /Dpush .undef /Dpop .undef % Clipping: /Wdict 8 dict dup begin -/S { OFFlevels length 0 eq { gsave setstrokestate .swapcolors stroke .swapcolors grestore } if n } bind executeonly def -/f { OFFlevels length 0 eq { gsave setfillstate fill grestore } if n } bind executeonly def -/f* { OFFlevels length 0 eq { gsave setfillstate eofill grestore } if n } bind executeonly def +/S { OFFlevels length 0 eq { gsave setsmaskstate .swapcolors stroke .swapcolors grestore } if n } bind executeonly def +/f { OFFlevels length 0 eq { gsave setsmaskstate fill grestore } if n } bind executeonly def +/f* { OFFlevels length 0 eq { gsave setsmaskstate eofill grestore } if n } bind executeonly def /B { OFFlevels length 0 eq { - PDFusingtransparency { - % knockout trans group around the filled and stroked object - mark - /Isolated //true /Knockout //true - .dicttomark - % strokepath will return empty path (no currentpoint) if nothing is stroked - gsave {strokepath pathbbox } stopped grestore not - { - 1 .setopacityalpha - .begintransparencygroup - gsave setfillstate fill grestore - setstrokestate .swapcolors /stroke fsexec .swapcolors - .endtransparencygroup - } { - newpath pop - } ifelse - } { - gsave setfillstate fill grestore - setstrokestate .swapcolors /stroke fsexec .swapcolors - } ifelse + .fillstroke } if n } bind executeonly def /b { closepath B } bind executeonly def /B* { OFFlevels length 0 eq { - PDFusingtransparency { - % knockout trans group around the filled and stroked object - mark - /Isolated //true /Knockout //true - .dicttomark - % strokepath will return empty path (no currentpoint) if nothing is stroked - gsave {strokepath pathbbox} stopped grestore not { - 1 .setopacityalpha - .begintransparencygroup - gsave setfillstate eofill grestore - setstrokestate .swapcolors /stroke fsexec .swapcolors - .endtransparencygroup - } { newpath pop } ifelse - } { - gsave setfillstate eofill grestore - setstrokestate .swapcolors /stroke fsexec .swapcolors - } ifelse + .eofillstroke } if n } bind executeonly def @@ -1213,15 +1144,25 @@ end readonly def %% can come into pdf_text_begin with an opacity not equal to 1. PDFusingtransparency .currenttextknockout and currentdict /illegal_BT get not and -{ + { .begintransparencytextgroup } if } bind executeonly def +/clip_if_required { + .currenttextrenderingmode 4 ge + {currentpoint} //.internalstopped exec + {//false} + {pop pop //true} + ifelse and + { .currentfilladjust2 0 dup .setfilladjust2 clip .setfilladjust2} if + newpath +} bind def + /ET_NO_TXT_KO { currentdict /TextSaveMatrix known { - .currenttextrenderingmode 4 ge { .currentfilladjust2 0 dup .setfilladjust2 clip .setfilladjust2 newpath} if + //clip_if_required exec TextSaveMatrix setmatrix currentdict /TextSaveMatrix undef @@ -1244,6 +1185,8 @@ end readonly def } if } bind executeonly def +currentdict /clip_if_required .undef + /ET { //ET_NO_TXT_KO exec % Group push occurred in pdf14_text_begin. @@ -1252,7 +1195,17 @@ end readonly def } if } bind executeonly def -/Tc { .settextspacing { showfirst } /Show gput } bind executeonly def +/Tc { + {.settextspacing} stopped + { + (\n **** Error: A ) pdfformaterror + $error /errorname get 256 string cvs pdfformaterror + ( error occured while setting the Text Character spacing to ) pdfformaterror + 256 string cvs pdfformaterror + (\n Output may be incorrect.\n) pdfformaterror + } if + { showfirst } /Show gput +} bind executeonly def /TL { .settextleading } bind executeonly def /Tr { .settextrenderingmode { showfirst } /Show gput } bind executeonly def /Ts { .settextrise settextstate } bind executeonly def @@ -1375,10 +1328,10 @@ end readonly def { % We add 1 to the length just in case the original % didn't have a FID. exch dup length 1 add dict exch - { % Stack: changed newfont key value - 1 index /FID eq - not { 3 copy put } if pop pop - } + { % Stack: changed newfont key value + 1 index /FID eq + not { 3 copy put } if pop pop + } forall exch } if pop @@ -1518,9 +1471,9 @@ end readonly def /pdfwrite_textrenderingprocs [ % Tr 0 - Fill - { setfillstate show } bind executeonly + { setsmaskstate show } bind executeonly % Tr 1 - Stroke - { currentlinewidth exch setstrokestate + { currentlinewidth exch setsmaskstate % Need to set the stroke width to a value which gives the correct % width under pdfwrite. Pdfwrite uses (in text mode) an identity % CTM, so we need to calculate the stroke width which would result @@ -1540,7 +1493,7 @@ end readonly def }ifelse setlinewidth show setlinewidth} bind executeonly % Tr 2 - Fill then Stroke - { currentlinewidth exch setstrokestate + { currentlinewidth exch setsmaskstate % Need to set the stroke width to a value which gives the correct % width under pdfwrite. Pdfwrite uses (in text mode) an identity % CTM, so we need to calculate the stroke width which would result @@ -1558,9 +1511,9 @@ end readonly def % we can ignore it. (wrong answer, but consistent) pop pop currentlinewidth }ifelse setlinewidth - setfillstate show setlinewidth} bind executeonly + setsmaskstate show setlinewidth} bind executeonly % Tr 3 - Neither fill nor stroke - { setfillstate show } bind executeonly + { setsmaskstate show } bind executeonly % % pdfwrite emits all text inside a gsave/grestore pair. As % a result we can't preserve any of the 'clip' modes, as the @@ -1569,7 +1522,7 @@ end readonly def % % Tr 4 - Fill, add to clip { gsave 0 .settextrenderingmode - setfillstate dup show grestore //true charpath } bind executeonly + setsmaskstate dup show grestore //true charpath } bind executeonly % Tr 5 - Stroke, add to clip { gsave 1 .settextrenderingmode currentlinewidth dup @@ -1581,7 +1534,7 @@ end readonly def % we can ignore it. (wrong answer, but consistent) pop pop currentlinewidth }ifelse setlinewidth - setstrokestate dup show grestore + setsmaskstate dup show grestore //true charpath} bind executeonly % Tr 6 - Fill, stroke, add to clip { gsave 2 .settextrenderingmode @@ -1598,7 +1551,7 @@ end readonly def % we can ignore it. (wrong answer, but consistent) pop pop currentlinewidth }ifelse setlinewidth - setstrokestate setfillstate dup show grestore + setsmaskstate dup show grestore //true charpath} bind executeonly % Tr 7 - Add to clip { //true charpath} bind executeonly @@ -1614,7 +1567,7 @@ end readonly def { .currenttextrenderingmode 1 eq .currenttextrenderingmode 2 eq or .currenttextrenderingmode 5 eq .currenttextrenderingmode 6 eq or or { - setstrokestate + setsmaskstate % Need to set the stroke width to a value which gives the correct % width under pdfwrite. Pdfwrite uses (in text mode) an identity % CTM, so we need to calculate the stroke width which would result @@ -1636,14 +1589,25 @@ end readonly def % conditionally set fillstate to avoid multiple operations during text operators /settextfillstate { - TextFillStateNeeded { setfillstate //false /TextFillStateNeeded gput } if + TextFillStateNeeded { setsmaskstate //false /TextFillStateNeeded gput } if } bind executeonly def % If current path is not known to be valid, use the clip path /TextTransSetup { % showarg path_valid TextTransSetup showarg % showarg path_valid false TextTransSetup showarg + gsave % NB: if 'show' is used, then we use the clippath, but a smaller bbox is preferred - not dup { gsave clippath } if //null setup_trans { grestore } if + { + % path was (probably) valid (CTM may not be invertable) + % Since TR mode may include stroking, expand for stroke + % If we get an error, just emit an empty box + { strokepath pathbbox } stopped { 0 0 0 0 } if + } { + clippath pathbbox stopped { 0 0 0 0 } if + } ifelse + grestore + 4 array astore //null + setup_trans } bind executeonly def /TextTransTeardown { @@ -1678,25 +1642,35 @@ end readonly def % operations when the CTM is singular. % Work around this here. { - matrix currentmatrix dup dup - dup 0 get 0 eq 1 index 1 get 0 eq and { - dup dup 2 get 0 eq { 0 }{ 1 } ifelse 1 put - } if - dup 2 get 0 eq 1 index 3 get 0 eq and { - dup dup 1 get 0 eq { 3 }{ 2 } ifelse 1 put - } if - setmatrix - currentpoint - % don't worry about transparency for invisible text - 4 index settextfillstate show % Tr was set to graphic state. - moveto - setmatrix - % now set the currentpoint using the original matrix - gsave - setmatrix - //false charpath currentpoint newpath - grestore - moveto + matrix currentmatrix + % Previously we tested specifically for a scale factor of 0, + % but bug #701875 has a CTM which is minute, but not zero. If + % we try to use that at anything except low resolution FreeType + % ends up trying to deal with glyph metrics where one dimension is 0 + % and it throws an error. So instead of looking for zero, we'll look + % for a really tiny CTM. + % We also used to patch up the CTM, and still use it, but frankly + % this is too much trouble. If the CTM is tiny then the displacement + % due to drawing the text will also be tiny. Negligible in fact. + % So if its that small then lets just ignore it. + dup 0 get abs 0.00001 lt 1 index 1 get 0.00001 abs lt and not { + dup 2 get abs 0.00001 lt 1 index 3 get abs 0.00001 lt and not { + pop + currentpoint + % don't worry about transparency for invisible text + 2 index settextfillstate show % Tr was set to graphic state. + moveto + % now set the currentpoint using the original matrix + gsave + //false charpath currentpoint newpath + grestore + moveto + } { + pop pop + }ifelse + } { + pop pop + }ifelse } } { { //false charpath textrenderingprocs .currenttextrenderingmode get exec } @@ -1812,7 +1786,7 @@ end readonly def % correctly. gsave .currenttextrenderingmode 4 sub .settextrenderingmode setstrokeforTrpreservation - setstrokestate settextfillstate //false TextTransSetup dup show grestore TextTransTeardown } if + setsmaskstate settextfillstate //false TextTransSetup dup show grestore TextTransTeardown } if //false charpath 3 copy 32 eq { add } { exch pop } ifelse % Stack: str wthis xorig yorig wword wchar ccode wextra @@ -1899,7 +1873,7 @@ end readonly def } { .currentPDFfontsize 0 eq not { - setstrokestate //true TextTransSetup + setsmaskstate //true TextTransSetup currentpoint //Tmatrix currentmatrix TextSaveMatrix setmatrix currentdict /qTextSaveMatrix known {qTextSaveMatrix setmatrix} if .swapcolors stroke TextTransTeardown .swapcolors @@ -1911,22 +1885,29 @@ end readonly def % Handle transparency the same as /B operator /tB { - PDFusingtransparency { - % knockout trans group around the filled and stroked object - mark - /Isolated //true /Knockout //true - .dicttomark - 1 .setopacityalpha - % While text will always have a currentpoint, strokepath seems to mess with it. - % we get the currentpoint, then use moveto to restore it for pathbbox - gsave currentpoint strokepath moveto pathbbox grestore - .begintransparencygroup - gsave tf grestore tS - .endtransparencygroup - } { - gsave tf grestore tS - } ifelse - //true /TextFillStateNeeded gput + % Type 3 fonts don't honour text rendering modes, see note on p401 of the 1.7 PDF Reference + currentfont /FontType get 3 eq + { + settextfillstate //true TextTransSetup currentpoint fill TextTransTeardown moveto + } + { + % Don't try to draw text when the point size is 0 + .currentPDFfontsize 0 eq not { + setsmaskstate settextfillstate + % While text will always have a currentpoint, strokepath seems to mess with it. + % we get the currentpoint, then use moveto to restore it. + currentpoint + + % For stroking characters, temporarily restore the graphics CTM so that + % the line width will be transformed properly. + //Tmatrix currentmatrix TextSaveMatrix setmatrix + currentdict /qTextSaveMatrix known {qTextSaveMatrix setmatrix} if + B + setmatrix + moveto + } if + } ifelse + //true /TextFillStateNeeded gput } bind executeonly def % This does the wrong thing if there have been multiple text operations diff --git a/Master/tlpkg/tlgs/Resource/Init/pdf_rbld.ps b/Master/tlpkg/tlgs/Resource/Init/pdf_rbld.ps index b018c5c73ae..037f10b723b 100644 --- a/Master/tlpkg/tlgs/Resource/Init/pdf_rbld.ps +++ b/Master/tlpkg/tlgs/Resource/Init/pdf_rbld.ps @@ -1,4 +1,4 @@ -% Copyright (C) 2001-2019 Artifex Software, Inc. +% Copyright (C) 2001-2020 Artifex Software, Inc. % All Rights Reserved. % % This software is provided AS-IS with no warranty, either express or @@ -444,7 +444,7 @@ pdfformaterror ( **** The file has been damaged. This may have been caused\n) pdfformaterror - ( **** by a problem while converting or transfering the file.\n) + ( **** by a problem while converting or transferring the file.\n) pdfformaterror ( **** Ghostscript will attempt to recover the data.\n) pdfformaterror diff --git a/Master/tlpkg/tlgs/Resource/Init/pdf_sec.ps b/Master/tlpkg/tlgs/Resource/Init/pdf_sec.ps index 0f77e556253..b6f2bfce556 100644 --- a/Master/tlpkg/tlgs/Resource/Init/pdf_sec.ps +++ b/Master/tlpkg/tlgs/Resource/Init/pdf_sec.ps @@ -1,4 +1,4 @@ -% Copyright (C) 2001-2019 Artifex Software, Inc. +% Copyright (C) 2001-2020 Artifex Software, Inc. % All Rights Reserved. % % This software is provided AS-IS with no warranty, either express or @@ -454,6 +454,63 @@ systemdict /check_r6_password .forceundef printProducer /pdf_process_Encrypt cvx /undefined signalerror } if + + % Bug 702598: We can have a trailer dictionary with an /Encrypt entry, and if the + % Encrypt dictionary is V 4 or greater we can (should ?) have StrF and stmF entries. + % + % The code below checks for the existence of StmF and StrF entries. Its possible + % that both may be /Identity (which means no encryption) in which case we don't need to check + % the password, as we won't need to decrypt any streams or strings. Note that the dict may still + % have a non-Identity /EFF (embedded files) key, but Ghostscript doesn't process embedded + % files so we don't have to worry about that. + Trailer /Encrypt oget dup + /V get 4 ge { + % NB: Entries in the Encrypt dictionary cannot be indirect references + dup /StmF .knownget { + /Identity eq not + } { + false % default StmF is Identity + }ifelse + 1 index /StrF .knownget { + /Identity eq not + } { + false % default StrF is Identity + }ifelse + or + % ...still in the V4 or above checking... + % Even if StmF and StrF are Identity, if the StdCF is missing AuthEvent + % or it is DocOpen, we require the password. Check for that. + 1 index /CF .knownget { + /StdCF .knownget { + /AuthEvent .knownget { + /DocOpen eq + or + } { + pop true % no AuthEvent, default is DocOpen, require password + } ifelse + } { + pop true % no StdCF, require password + } ifelse + } { + pop true % no CF, require password + } ifelse + exch pop % discard Encrypt dict + }{ + % Not V4 or later + pop true % discard Encrypt dict, require password + } ifelse + % If we were given a PDFPassword, check it anyway, even if the + % code above said we didn't need one. This will allow us to process + % PDF files with an initial CryptFilter which has StrF=StmF=Identity, + % but contains streams which themselves have non-Identity StmF or StrF. + /PDFPassword where { + pop true + } + { + false + } ifelse + or + { () pdf_check_password { /FileKey exch def @@ -504,13 +561,13 @@ systemdict /check_r6_password .forceundef /pdf_process_Encrypt cvx /invalidfileaccess signalerror } ifelse } ifelse - -% Trailer /Encrypt oget /P oget 4 and 0 eq #? and -% { ( ****This owner of this file has requested you do not print it.\n) -% pdfformaterror printProducer -% /pdf_process_Encrypt cvx /invalidfileaccess signalerror -% } -% if + } + { + ( **** This file has an Encryption dictionary, but both the StmF and StrF entries\n) pdfformatwarning + ( **** are /Identity, and AuthEvent allows the document to be opened. It is possible\n) pdfformatwarning + ( **** that embedded streams may still use encryption, if the file fails to process\n) pdfformatwarning + ( **** you may need to supply a User or Owner password by setting -sPDFPassword=\n) pdfformatwarning + } ifelse } bind executeonly def % Calculate the key used to decrypt an object (to pass to .decpdfrun or |