summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'Resource')
-rw-r--r--Resource/Init/gs_cidfm.ps11
-rw-r--r--Resource/Init/gs_fonts.ps21
-rw-r--r--Resource/Init/gs_init.ps47
-rw-r--r--Resource/Init/gs_lev2.ps2
-rw-r--r--Resource/Init/gs_pdfwr.ps2
-rw-r--r--Resource/Init/gs_res.ps2
-rw-r--r--Resource/Init/gs_ttf.ps8
-rw-r--r--Resource/Init/pdf_base.ps138
-rw-r--r--Resource/Init/pdf_draw.ps855
-rw-r--r--Resource/Init/pdf_font.ps387
-rw-r--r--Resource/Init/pdf_main.ps178
-rw-r--r--Resource/Init/pdf_ops.ps204
12 files changed, 1252 insertions, 603 deletions
diff --git a/Resource/Init/gs_cidfm.ps b/Resource/Init/gs_cidfm.ps
index 5eb25f00..e123bfc1 100644
--- a/Resource/Init/gs_cidfm.ps
+++ b/Resource/Init/gs_cidfm.ps
@@ -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/Resource/Init/gs_fonts.ps b/Resource/Init/gs_fonts.ps
index 8e361552..204e2832 100644
--- a/Resource/Init/gs_fonts.ps
+++ b/Resource/Init/gs_fonts.ps
@@ -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/Resource/Init/gs_init.ps b/Resource/Init/gs_init.ps
index 722b57c1..05d01c21 100644
--- a/Resource/Init/gs_init.ps
+++ b/Resource/Init/gs_init.ps
@@ -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
+952
% 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
@@ -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/Resource/Init/gs_lev2.ps b/Resource/Init/gs_lev2.ps
index 0fd41646..8c41aba0 100644
--- a/Resource/Init/gs_lev2.ps
+++ b/Resource/Init/gs_lev2.ps
@@ -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/Resource/Init/gs_pdfwr.ps b/Resource/Init/gs_pdfwr.ps
index 422e66e1..ed691b9d 100644
--- a/Resource/Init/gs_pdfwr.ps
+++ b/Resource/Init/gs_pdfwr.ps
@@ -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/Resource/Init/gs_res.ps b/Resource/Init/gs_res.ps
index 068514bf..5559e6a9 100644
--- a/Resource/Init/gs_res.ps
+++ b/Resource/Init/gs_res.ps
@@ -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/Resource/Init/gs_ttf.ps b/Resource/Init/gs_ttf.ps
index 74043d16..6be8fe99 100644
--- a/Resource/Init/gs_ttf.ps
+++ b/Resource/Init/gs_ttf.ps
@@ -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 ---------------- %
diff --git a/Resource/Init/pdf_base.ps b/Resource/Init/pdf_base.ps
index 02503eef..618e5e51 100644
--- a/Resource/Init/pdf_base.ps
+++ b/Resource/Init/pdf_base.ps
@@ -776,11 +776,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 +1251,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/Resource/Init/pdf_draw.ps b/Resource/Init/pdf_draw.ps
index a359a9c1..1deb0526 100644
--- a/Resource/Init/pdf_draw.ps
+++ b/Resource/Init/pdf_draw.ps
@@ -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
@@ -1066,6 +1121,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
} {
@@ -1423,8 +1480,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,21 +2271,15 @@ 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
@@ -2236,34 +2291,44 @@ currentdict /last-ditch-bpc-csp undef
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 .currentshapealpha .currentopacityalpha 5 -1 roll
+ 1 .setfillconstantalpha 1 .setstrokeconstantalpha
+ 1 .setopacityalpha 1 .setshapealpha
doimage
+ .setopacityalpha .setshapealpha .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 .currentshapealpha .currentopacityalpha 5 -1 roll
+ 1 .setopacityalpha 1 .setshapealpha
+ doimage
+ .setopacityalpha .setshapealpha .setfillconstantalpha .setstrokeconstantalpha
+ .endtransparencygroup
+ } {
+ doimage
+ } ifelse
+ } ifelse
} ifelse
} bind executeonly def
@@ -2315,6 +2380,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,7 +2404,12 @@ currentdict /last-ditch-bpc-csp undef
makemaskimage
} if
% Stack: datasource imagemask
- gsave 1 1 moveto 0 0 lineto /image setup_trans grestore
+ 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 setfillstate //true ValidateDecode { imagemask } }
{ ColorSpace setgcolorspace currentdict end setfillblend //false ValidateDecode { image } }
ifelse
@@ -2361,6 +2434,13 @@ 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
@@ -3043,7 +3123,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 +3131,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 +3177,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 +3225,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 -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 {.setopacityalpha} 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
+ 1 {}
+% 2 index annotsetcolor {
+ 0 setdash setlinewidth stroke
+% } if
} ifelse
pop
grestore
@@ -3241,12 +3344,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 +3433,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 +3628,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
@@ -3569,16 +3743,30 @@ currentdict /set_bc_color undef
{
gsave
dup /ca knownoget {.setopacityalpha} if
- dup annotrect rectfill
+ dup annotrect
+ 5 index /RD knownoget {
+ applyRD
+ } if
+ rectfill
grestore
dup /CA knownoget {.setopacityalpha} if
- drawborder
+ 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 +3796,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
@@ -3661,8 +3855,14 @@ currentdict /set_bc_color undef
fill
grestore
dup /CA knownoget {.setopacityalpha} if
- strokeborderpath
- } if
+ dup annotsetcolor {
+ strokeborderpath
+ } if
+ } {
+ dup annotsetcolor {
+ strokeborderpath
+ } if
+ } ifelse
//endannottransparency exec
//false
grestore
@@ -3795,7 +3995,7 @@ currentdict /set_bc_color undef
fillborderpath
grestore
} bind executeonly def
- /None {} bind executeonly def
+ /None {pop} bind executeonly def
/Butt {
dup
/BS knownoget {
@@ -3880,36 +4080,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 % <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 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
@@ -3977,14 +4191,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 +4214,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 +4264,8 @@ currentdict /set_bc_color undef
//true
} {
0 setlinecap
- dup annotsetcolor {
+ dup annotsetcolor
+ {
dup calc_annot_scale
2 copy mul 0 ne
{
@@ -4087,7 +4305,8 @@ currentdict /set_bc_color undef
//true
} {
0 setlinecap
- dup annotsetcolor {
+ dup annotsetcolor
+ {
dup calc_annot_scale
2 copy mul 0 ne
{
@@ -4149,7 +4368,8 @@ currentdict /set_bc_color undef
//true
} {
0 setlinecap
- dup annotsetcolor {
+ dup annotsetcolor
+ {
/QuadPoints knownoget {
aload length 8 idiv {
6 -2 roll
@@ -4161,7 +4381,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 +4404,8 @@ currentdict /set_bc_color undef
//true
} {
//startannottransparency exec
- dup annotsetcolor {
+ dup annotsetcolor
+ {
dup calc_annot_scale
2 copy mul 0 ne
{
@@ -4323,18 +4546,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 +4622,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 +4762,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 +4775,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 +4793,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 +4856,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 +5030,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 +5060,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 +5132,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 +5453,7 @@ currentdict end readonly def
gsave
dup dup /Subtype knownoget {
- dup //.PDFDrawAnnotType? exec
+ dup //.PDFPreserveAnnotType? exec
{
//preserveannottypes exch .knownget { exec } { //true } ifelse
{
@@ -5068,7 +5471,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/Resource/Init/pdf_font.ps b/Resource/Init/pdf_font.ps
index 81b7af13..60deb64e 100644
--- a/Resource/Init/pdf_font.ps
+++ b/Resource/Init/pdf_font.ps
@@ -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
- % Some non-compliant files are missing FirstChar/LastChar,
- % despite referencing a non-base14 font
- 3 index /FirstChar knownoget
+ % 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
+
+ % 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
+ 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
{
- 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
- {
- 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
@@ -2473,23 +2519,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/Resource/Init/pdf_main.ps b/Resource/Init/pdf_main.ps
index 7690bae0..5cd90556 100644
--- a/Resource/Init/pdf_main.ps
+++ b/Resource/Init/pdf_main.ps
@@ -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
@@ -2339,8 +2339,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 +2505,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 +2602,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
@@ -2740,7 +2784,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 +2900,19 @@ currentdict /PDF2PS_matrix_key undef
% Draw the annotations
//systemdict /ShowAnnots .knownget not { //true } if {
/Annots knownoget {
- { oforce
+ {
+ /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,6 +2934,7 @@ currentdict /PDF2PS_matrix_key undef
} {
pop
} ifelse
+ } ifelse
} forall
} if
} if
@@ -3063,33 +3120,45 @@ currentdict /PDF2PS_matrix_key undef
//false exch % Assume no transparency
/Annots knownoget { % Get Annots array
{
- oforce
- dup //null ne {
- dup /Subtype knownoget {
- /Highlight eq { % Highlight annotation is always implemented
- pop pop //true exit % as transparency.
+ /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
- } 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
+ 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
- } if % If AP dict known
- dup /BM knownoget {
- //true exit
- } if
- dup /CA knownoget {
- 1 le {
- pop pop //true exit
+ dup /CA knownoget {
+ 1 le {
+ pop pop //true exit
+ } if
} if
- } if
- /ca knownoget {
- 1 le {
- pop //true exit
+ /ca knownoget {
+ 1 le {
+ pop //true exit
+ } if
} if
- } if
- } {
- pop
+ } {
+ pop
+ } ifelse
} ifelse
} forall % For all annots on the page
} if
@@ -3545,24 +3614,33 @@ 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
+[
+ /.currentblendmode /.currentopacityalpha /.currentshapealpha /.currenttextknockout /.begintransparencytextgroup
+ /.endtransparencytextgroup /.begintransparencymaskgroup /.begintransparencymaskimage /.begintransparencypagegroup
+ /.endtransparencymask /.image3x /.abortpdf14devicefilter /.setfillconstantalpha /.setalphaisshape /.currentalphaisshape
+
+ % 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
+
+ % undefining these causes errors/incorrect output
+ %/.setblendmode /.begintransparencygroup /.settextknockout /.setstrokeoverprint /.setfilloverprint
+ %/.currentstrokeoverprint /.currentfilloverprint /.currentfillconstantalpha /.currentstrokeconstantalpha
+ %/.setstrokeconstantalpha /.setfillconstantalpha /.setSMask /.currentSMask
+
+] systemdict dup /ALLOWPSTRANSPARENCY get {pop pop}{.undefinternalnames}ifelse
diff --git a/Resource/Init/pdf_ops.ps b/Resource/Init/pdf_ops.ps
index d594035c..eb2168a5 100644
--- a/Resource/Init/pdf_ops.ps
+++ b/Resource/Init/pdf_ops.ps
@@ -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
@@ -701,7 +701,7 @@ end
% 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,41 +719,34 @@ 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
/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
@@ -762,9 +755,10 @@ end
/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.
@@ -791,9 +785,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
@@ -924,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 fill grestore
- setstrokestate .swapcolors /stroke fsexec .swapcolors
- .endtransparencygroup
- } { newpath pop } ifelse
- } {
- gsave setfillstate fill grestore
- setstrokestate .swapcolors /stroke fsexec .swapcolors
- } ifelse
+ setstrokestate setfillstate /.fillstroke fsexec
} {
newpath
} ifelse
@@ -950,23 +942,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
+ setstrokestate setfillstate /.eofillstroke fsexec
} {
newpath
} ifelse
@@ -982,49 +958,14 @@ currentdict dup /Dpush .undef /Dpop .undef
/f* { OFFlevels length 0 eq { gsave setfillstate 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
@@ -1219,9 +1160,19 @@ end readonly def
} 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 +1195,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.
@@ -1642,8 +1595,19 @@ end readonly 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 }
@@ -1919,7 +1893,9 @@ end readonly def
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
+ { gsave currentpoint strokepath moveto pathbbox } stopped grestore {
+ /tB cvx /undefinedresult signalerror
+ } if
.begintransparencygroup
gsave tf grestore tS
.endtransparencygroup