summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'Resource/Init/pdf_main.ps')
-rw-r--r--Resource/Init/pdf_main.ps520
1 files changed, 418 insertions, 102 deletions
diff --git a/Resource/Init/pdf_main.ps b/Resource/Init/pdf_main.ps
index d7933700..ded2782a 100644
--- a/Resource/Init/pdf_main.ps
+++ b/Resource/Init/pdf_main.ps
@@ -1,4 +1,4 @@
-% Copyright (C) 2001-2020 Artifex Software, Inc.
+% Copyright (C) 2001-2021 Artifex Software, Inc.
% All Rights Reserved.
%
% This software is provided AS-IS with no warranty, either express or
@@ -26,10 +26,12 @@ userdict /GS_PDF_ProcSet undef
/#? //false def
% Test whether the current output device handles pdfmark.
-/.writepdfmarkdict 1 dict dup /pdfmark //null put readonly def
/.writepdfmarks { % - .writepdfmarks <bool>
- currentdevice //.writepdfmarkdict .getdeviceparams
- mark eq { //false } { pop pop //true } ifelse
+ /PdfmarkCapable /GetDeviceParam .special_op {
+ exch pop
+ }{
+ //false
+ }ifelse
systemdict /DOPDFMARKS known or
} bind executeonly def
@@ -282,12 +284,22 @@ currentdict /runpdfstring .undef
{
systemdict /FirstPage known
systemdict /LastPage known or
- systemdict /Pagelist known or
+ systemdict /PageList known or
{
<</DisablePageHandler //true>> setpagedevice
} if
} bind def
+/EnablePageHandlerDevice
+{
+ systemdict /FirstPage known
+ systemdict /LastPage known or
+ systemdict /PageList known or
+ {
+ <</DisablePageHandler //false>> setpagedevice
+ } if
+} bind def
+
/runpdfbegin { % <file> runpdfbegin -
userdict begin
% It turns out that the PDF interpreter uses memory more
@@ -295,20 +307,22 @@ currentdict /runpdfstring .undef
% This is counter-intuitive, and we don't understand why it happens,
% but the improvement is significant.
/PDFTopSave save def
- <</ProcessDSCComment //null>> setuserparams
- <</ProcessComment //null>> setuserparams
- %% Bug #696487, allow dict stack to grow without limit, as these PDF
- %% files have stupidly deep gsave nesting and we need a dictionary per gsave
- %% at the moment.
- %% Remove ths if bug #696511 is ever completed (move ExtGstate parameters into gstate)
- <</MaxDictStack -1>> setuserparams
- %% Bug #696567, same customer as above. Ths time they have a file with a page whch has
- %% 447000 ExtGState references (all of hwch contain no gstate!) Because we allocate
- %% these on the stack, allow the stack to grow indefinitely in order to accomodate
- %% such stupid files. Also move these lines from the end of the routine, so that
- %% the increases are in place before we call odfopen, which will build the
- %% resources and needs this definition in place.
- <</MaxOpStack -1>> setuserparams
+ <<
+ /ProcessDSCComment //null
+ /ProcessComment //null
+ %% Bug #696487, allow dict stack to grow without limit, as these PDF
+ %% files have stupidly deep gsave nesting and we need a dictionary per gsave
+ %% at the moment.
+ %% Remove ths if bug #696511 is ever completed (move ExtGstate parameters into gstate)
+ /MaxDictStack -1
+ %% Bug #696567, same customer as above. Ths time they have a file with a page whch has
+ %% 447000 ExtGState references (all of which contain no gstate!) Because we allocate
+ %% these on the stack, allow the stack to grow indefinitely in order to accomodate
+ %% such stupid files. Also move these lines from the end of the routine, so that
+ %% the increases are in place before we call odfopen, which will build the
+ %% resources and needs this definition in place.
+ /MaxOpStack -1
+ >> setuserparams
//DisablePageHandlerDevice exec
@@ -323,7 +337,6 @@ currentdict /runpdfstring .undef
/CumulativePageCount currentpagedevice /PageCount get def
} bind executeonly def
-currentdict /DisablePageHandlerDevice undef
/runpdfpagerange { % - runpdfpagerange <firstpage#> <lastpage#>
/PortfolioPage where {
@@ -375,9 +388,8 @@ currentdict /DisablePageHandlerDevice undef
2 2 pdfpagecount {
PDFPageList exch 1 put
} for
- 1 pdfpagecount
QUIET not {
- (Processing even-numbered pages\n) print
+ (Processing even-numbered pages\n) print (1 through ) print pdfpagecount =only
(.) = flush
} if
} {
@@ -389,9 +401,8 @@ currentdict /DisablePageHandlerDevice undef
1 2 pdfpagecount {
PDFPageList exch 1 put
} for
- 1 pdfpagecount
QUIET not {
- (Processing odd-numbered pages\n) print 1 index =only ( through ) print dup =only
+ (Processing odd-numbered pages\n) print (1 through ) print pdfpagecount =only
(.) = flush
} if
} {
@@ -525,10 +536,16 @@ currentdict /DisablePageHandlerDevice undef
dup /Page# exch store
QUIET not { (Page ) print dup //== exec flush } if
pdfgetpage
- dup //null ne { pdfshowpage } {
- ( **** Error: Page #) pdfformaterror Page# 10 string cvs pdfformaterror
- ( not found.\n) pdfformaterror
- /dopdfpages cvx /syntaxerror signalerror
+ dup //null ne {
+ pdfshowpage
+ } {
+ PDFSTOPONERROR {
+ /dopdfpages cvx /syntaxerror signalerror
+ } {
+ pop
+ ( **** Error: Page #) pdfformaterror Page# 10 string cvs pdfformaterror
+ ( not found.\n) pdfformaterror
+ } ifelse
} ifelse
}{
pop
@@ -554,9 +571,12 @@ currentdict /DisablePageHandlerDevice undef
PDFTopSave restore
end % userdict
2 vmreclaim % couldn't hurt
- <</DisablePageHandler //false>> setpagedevice
+ //EnablePageHandlerDevice exec
} bind executeonly def
+currentdict /DisablePageHandlerDevice undef
+currentdict /EnablePageHandlerDevice undef
+
% Copy stream to an external temporary file and
% return the file name as PS name.
/copy_embedded_file {
@@ -890,7 +910,25 @@ pdfdict begin
{ % xref line tag was not /n
/f ne % verify that the tag was /f
{ /setxrefentry cvx /syntaxerror signalerror
- } if
+ } {
+ % Bug #703214 has a invalid initial xref table. The table entries are correct
+ % but the subsection begins 1 7 instead of 0 7, which means the initial entry is
+ % declared as object 1 instead of object 0. The file is incrementally updated
+ % many times and every object *except* object 1 is redefined. Object 1 is
+ % therefore defined as free and having an offset of 0. Acrobat can open this
+ % without complaint! Because the PDF header is a comment line it is skipped
+ % so Acrobat must simply be ignoring the free flag. We can't easily detect
+ % this, but we can check for the generation number being the canonical
+ % head of the free list. If it is, and the object number we have is not
+ % zero, then pretend its not free.......
+ dup 65535 eq {
+ 2 index 0 ne {
+ 0 3 1 roll
+ //false setxrefentry
+ 3 -1 roll pop
+ } if
+ }if
+ }ifelse
} ifelse
pop pop % pop <obj location> and <gen num>
% stack: <err count> <obj num>
@@ -1254,26 +1292,26 @@ currentdict /xref-char-dict undef
% to the parent field.
Trailer /Root knownoget {
/AcroForm knownoget {
- %% If we don't have a NeedAppearances entry, treat as if true.
- %% We know Acrobat always regenerates all annotait
- dup /NeedAppearances knownoget not { //true } if {
- /NeedAppearances //true def
- dup
- /Fields knownoget {
- { oforce
- %% Make sure the entry from the Fields array is a dictionary
- %% Bug #692447.pdf has an array of nulls.
- dup type /dicttype eq {
- link_widget_annots
- }if
- pop
- } forall
- } if
- pop
- } {
- pop
- } ifelse
- } if
+ %% If we don't have a NeedAppearances entry, treat as if true.
+ %% We know Acrobat always regenerates all annotations.
+ dup /NeedAppearances knownoget not { //true } if {
+ /NeedAppearances //true def
+ dup
+ /Fields knownoget {
+ { oforce
+ %% Make sure the entry from the Fields array is a dictionary
+ %% Bug #692447.pdf has an array of nulls.
+ dup type /dicttype eq {
+ link_widget_annots
+ }if
+ pop
+ } forall
+ } if
+ pop
+ } {
+ pop
+ } ifelse
+ } if
} if
% Use OutputIntent ICC profile
@@ -1427,14 +1465,15 @@ currentdict /xref-char-dict undef
% Guess whether the output device is a printer.
/Printed currentpagedevice /OutputFile known def
} ifelse
- currentpagedevice /OutputFile known {
- currentpagedevice /OutputFile get (%d) search {
- pop pop pop
+ % If the file name has an odd number of '%', it is either a request for
+ % separate pages, or is invalid. In either case some marks can be omitted.
+ currentpagedevice /OutputFile .knownget {
+ //false exch {
+ 37 eq xor
+ } forall {
/NO_PDFMARK_OUTLINES //true def
/NO_PDFMARK_DESTS //true def
- } {
- pop
- }ifelse
+ } if
} if
/PSLevel1 where { pop } { /PSLevel1 //false def } ifelse
% NB: PDFfile is used outside of the PDF code to determine that a
@@ -1579,10 +1618,9 @@ currentdict /xref-char-dict undef
% Check for recursion in the page tree. Bug 689954, MOAB-06-01-2007
% Make sure that the operand stack is cleaned up in case there's
% an error and we ignore it (bug #700953)
- mark
+ /StackMarkVerifyPageTree
verify_page_tree
- cleartomark
-
+ /StackMarkVerifyPageTree ClearToKey
currentdict end
} bind executeonly def
@@ -1923,7 +1961,6 @@ currentdict /xref-char-dict undef
}ifelse
}{
% No Page Resources, recursively try ParentResources as a last resort
- pop % page Resources
LocalResources parent_obj_get
} ifelse
} {
@@ -1971,7 +2008,8 @@ currentdict /xref-char-dict undef
% Get the total number of pages in the document.
/pdfpagecount % - pdfpagecount <int>
- { Trailer /Root knownoget {
+ {
+ Trailer /Root knownoget {
/Pages knownoget {
dup /Count knownoget {
dup type /integertype eq { dup 0 le } { //true } ifelse {
@@ -2078,10 +2116,20 @@ currentdict /xref-char-dict undef
exch pop //null
0 1 3 index length 1 sub {
2 index exch get
- dup oforce dup /Kids known { /Count oget } { pop 1 } ifelse
+ dup oforce
+ dup //null eq {
+ PDFSTOPONERROR {
+ /pdffindpage? cvx /syntaxerror signalerror
+ } {
+ ( **** Error: Ignoring a null node in the Page tree.\n) pdfformaterror
+ pop pop
+ } ifelse
+ } {
+ dup /Kids known { /Count oget } { pop 1 } ifelse
% Stack: index kids null noderef count
- dup 5 index ge { pop exch pop exit } if
- 5 -1 roll exch sub 4 1 roll pop
+ dup 5 index ge { pop exch pop exit } if
+ 5 -1 roll exch sub 4 1 roll pop
+ } ifelse
} for exch pop
% Stack: index null|noderef
dup //null eq { pop pop 1 //null exit } if
@@ -2511,7 +2559,7 @@ end readonly def
2 index sub exch 3 index sub exch 4 2 roll pop pop
% stack: savedCTM <pdfpagedict> [Box] XImageable YImageable
2 index aload pop 2 index sub exch 3 index sub exch 4 2 roll pop pop
- 5 index /Rotate pget not { 0 } if 90 cvi idiv 1 and 0 ne { exch } if
+ 5 index /Rotate pget not { 0 } if cvi 90 idiv 1 and 0 ne { exch } if
% stack: savedCTM <pdfpagedict> [Box] XImageable YImageable XBox YBox
4 copy
3 -1 roll exch div 3 1 roll div .min
@@ -2647,7 +2695,11 @@ currentdict /PDF2PS_matrix_key undef
% Determine the number of spot colors used on the page. Note: This searches
% the pages resources. It may be high if a spot color is in a resource but
% is not actually used on the page.
- currentpagedevice /PageSpotColors known { /PageSpotColors 2 index countspotcolors def } if
+ currentpagedevice /PageSpotColors known {
+ /PageSpotColors 2 index countspotcolors
+ userdict /PageSpotColors 2 index put
+ def
+ } if
% If the user told us to use a named OutputIntent
systemdict /UseOutputIntent .knownget {
@@ -2701,6 +2753,30 @@ currentdict /PDF2PS_matrix_key undef
% Stack: pagedict currentpagedict installproc
/Install exch def
% Stack: pagedict currentpagedict
+ % If the Overprint device flag is not /disable, check usage of OP/op
+ /PageUsesOverprint //false def % assume we don't need OP simulation
+ dup /Overprint get /disable ne
+ % If the device suppports SpotColors (DeviceN device) we don't need simulation
+ 1 index /PageSpotColors known
+ not and
+ /HighLevelDevice /GetDeviceParam .special_op {
+ exch pop
+ }{
+ //false
+ }ifelse
+ not and % Only if not HighLevelDevice
+ {
+ % Overprint is /enable, so the device might need the overprint compositor
+ % if it does not support spot colors, thus check if overprint is used so
+ % overprint simulation can be done with the pdf14 compositor
+ 1 index countspotcolors userdict exch /PageSpotColors exch put % save it in a known place
+ 1 index pageusesoverprint
+ 1 index /ProcessColorModel get /DeviceCMYK eq {
+ PageSpotColors 0 gt % count of colorants NOT including CMYK
+ and
+ } if
+ /PageUsesOverprint exch def % the page needs OP simulation so set device param.
+ } if
pop currentdict end setpagedevice
} bind executeonly def
@@ -2769,18 +2845,46 @@ currentdict /PDF2PS_matrix_key undef
% and the result was set in the pagedevice dictionary. Use it rather than
% scanning again IF it is present. If the pdfshowpage_setup was not called
% (eg GSView 5) then it will not be present, so we must rescan.
- currentpagedevice /PageUsesTransparency .knownget not {dup pageusestransparency} if
+ currentdict /PageUsesTransparency .knownget not {dup pageusestransparency} if
dup /PDFusingtransparency exch def {
- % If the current device isn't CMYK, or if it is a device that (currently) supports transparency
+ % If the current device isn't CMYK, or if it is a device that supports transparency
% we don't need the special handling of Overprint transparency, so disable the checking.
- currentpagedevice dup /Colors get 4 lt 1 index /SimulateOverprint get not or
- exch /HaveTransparency .knownget not { //false } if or
- % device needs special Oveprint handling
+
+ 4 dict begin % working directory to simplify
+ currentpagedevice dup /Colors get
+ /devColors exch def % put into our convenience dict
+ dup /HaveTransparency .knownget not { //false } if
+ /devSupportsTrans exch def % put into our convenience dict
+ dup /Overprint get
+ /SimOP exch def % put into our convenience dict
+ SimOP /simulate eq
+ exch /PageUsesOverprint .knownget not { //false } if
+ and % both Overprint==/simulate and PageUsesOverprint
+ {
+ % Determine if the device needs the special pdf14 compositor push
+ devColors 4 eq PageSpotColors 0 gt and % CMYK device, but device has spot colors
+ devColors 4 lt % RGB or Gray device
+ or
+ } {
+ //false % Overprint is not /simulate or PageUseOverprint is false
+ } ifelse
+ % Determine if the device needs SMask for Overprint
+ SimOP /simulate eq {
+ //true % we will need setupOPrtans for Compatible BM
+ } {
+ SimOP /enable eq
+ devColors 4 ge % CMYK device
+ and
+ } ifelse
+ devSupportsTrans not and % If device supports transparency (e.g. pdfwrite) then no setupOPtrans
+ end % pop the convenience dict
/setup_trans exch
- { /setupSMtrans } { /setupOPtrans } ifelse
+ { /setupOPtrans } { /setupSMtrans } ifelse
load def
+
% Show the page within a PDF 1.4 device filter.
- 0 .pushpdf14devicefilter {
+ { -1 } { 0 } ifelse
+ .pushpdf14devicefilter {
/DefaultQstate qstate store % device has changed -- reset DefaultQstate
% If the page has a Group, enclose contents in transparency group.
% (Adobe Tech Note 5407, sec 9.2)
@@ -2808,7 +2912,31 @@ currentdict /PDF2PS_matrix_key undef
} {
/setup_trans { pop pop } def % no-op this if the page doesn't use transparency
% NB: original will be restored from PDFsave
- showpagecontents
+ % The page doesn't use transparency, but if Overprint is /simulate, we may need to
+ % push a pdf14devicefilter to handle the overprint simulation using the pdf14 device.
+ currentpagedevice
+ dup /Overprint get /simulate eq
+ 1 index /PageSpotColors known
+ not and
+ exch /PageUsesOverprint .knownget not { //false } if
+ and
+ {
+ % Show the page within a PDF 1.4 device filter for overprint_simulation.
+ -1 .pushpdf14devicefilter {
+ /DefaultQstate qstate store % device has changed -- reset DefaultQstate
+ showpagecontents
+ } stopped {
+ % abort the transparency device
+ .abortpdf14devicefilter
+ /DefaultQstate qstate store % device has changed -- reset DefaultQstate
+ stop
+ } if
+ { } settransfer % identity transfer during popdevice (put_image)
+ .poppdf14devicefilter % NB: reset to DefaultQstate will also restore transfer function
+ /DefaultQstate qstate store % device has changed -- reset DefaultQstate
+ } {
+ showpagecontents
+ } ifelse
} ifelse
.free_page_resources
% todo: mixing drawing ops outside the device filter could cause
@@ -2967,7 +3095,8 @@ currentdict /PDF2PS_matrix_key undef
} ifelse
} if
} if
- //systemdict /ShowAcroForm .knownget { //true eq } { //false } ifelse {
+ % default AcroForm to true to match Acrobat.
+ //systemdict /ShowAcroForm .knownget { //true eq } { //true } ifelse {
Trailer /Root oget /AcroForm knownoget { draw_acro_form } if
} if
} bind executeonly def
@@ -2980,6 +3109,112 @@ currentdict /PDF2PS_matrix_key undef
dup { setcolorspace } //.internalstopped exec { pop /DeviceRGB } if
} bind executeonly def
+% returns true if OP or op is true in an ExtGState
+/pageusesoverprint { % <pagedict> pageusesoverprint <bool>
+ dup //false exch {
+ 4 dict 1 index resourceusesoverprint { pop not exit } if
+ %% Check the current dictionary and its Parent (if any) to see
+ %% if they both have stored object numbers. If they do then
+ %% check the numbers, don't allow self-references.
+ dup /Parent knownoget not { pop exit }
+ {
+ exch /.gs.pdfobj# .knownget
+ {
+ 1 index /.gs.pdfobj# .knownget {
+ eq {
+ pop exit
+ }if
+ }{
+ pop
+ }ifelse
+ }if
+ } ifelse
+ } loop
+ % Also check for transparency in the annotation (if not in resources).
+ { pop //true } { annotsuseoverprint } ifelse
+} bind def
+
+% Check if Overprint (OP/op) is specified in an ExtGState dict
+/extgstateusesoverprint { % <gstate dict> extgstateusesoverprint <bool>
+ //false exch % Assume no overprint
+ dup //null eq {
+ pop % bug 692050
+ } {
+ { % establish loop context
+ dup /OP knownoget { { pop not exit } if } if
+ dup /op knownoget { { pop not exit } if } if
+ pop exit
+ } loop
+ } ifelse
+} bind def
+
+% Check if overprint is used in a Pattern
+/patternusesoverprint { % <Pattern dict> patternusesoverprint <bool>
+ //false exch % Assume no overprint
+ {
+ 4 dict 1 index resourceusesoverprint { pop not exit } if
+ dup /ExtGState knownoget { extgstateusesoverprint { pop not exit } if } if
+ pop exit
+ } loop
+} bind def
+
+% Check the Resources of a page or Form. Check for loops in the resource chain.
+/resourceusesoverprint { % <dict> <dict> resourceusesoverprint <bool>
+ { % Use loop to provide an exitable context.
+ /Resources knownoget not { 0 dict } if
+ 2 copy .knownget {
+ { % Some circular references may be missed because scanning stops
+ % when the 1st overprint is found.
+ ( **** File has circular references in resource dictionaries.\n)
+ pdfformaterror
+ } if
+ pop //false exit
+ } if
+ 2 copy //true put % In the current chain.
+ dup /ExtGState knownoget {
+ //false exch
+ { exch pop oforce extgstateusesoverprint { pop //true exit } if
+ } forall
+ { pop //true exit } if
+ } if
+ dup /Pattern knownoget {
+ //false exch
+ { exch pop oforce patternusesoverprint { pop //true exit } if
+ } forall
+ { pop //true exit } if
+ } if
+ 2 copy //false put % Visited but not in the current chain.
+ pop //false exit
+ } loop
+ exch pop
+} bind def
+
+% Check if the annotations on a page use overprint
+/annotsuseoverprint { % <page dict> annotsuseoverprint <bool>
+ //false exch % Assume no overprint
+ /Annots knownoget { % Get Annots array
+ 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
+ 4 dict exch resourceusesoverprint { pop pop //true exit } if
+ } if
+ } if % If AP dict known
+ } {
+ 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 def
+
% ------ Transparency support ------ %
% Determine whether a page might invoke any transparency features:
@@ -3162,31 +3397,37 @@ currentdict /PDF2PS_matrix_key undef
}
{
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.
+ dup type /dicttype eq {
+ 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 {
+ pop pop pop //true exit
} if
- } if % If AP dict known
- dup /BM knownoget {
- pop pop pop //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
+ } ifelse
} {
+ ( **** Error: Annotation entry is not a dictionary, ignoring it.\n) pdfformaterror
+ ( Output may be incorrect.\n) pdfformaterror
pop
} ifelse
} ifelse
@@ -3213,21 +3454,32 @@ currentdict /PDF2PS_matrix_key undef
% Thus it may include Cyan, Magenta, Yellow, and Black.
% <colorspace> <spotcolordict> colorspacespotcolors -
/colorspacespotcolors {
- exch dup type /arraytype eq {
+ % Make sure we have an array, and that it is has enough info
+ exch dup type /arraytype eq
+ {
% If we have an Indexed color space then get the base space.
dup 0 oget % <<>> [csp] /Type
dup /Indexed eq {
pop 1 oget % <<>> [base]
2 copy exch colorspacespotcolors
} {
- % Stack: <spotcolordict> <colorspace> <colorspacetype>
- dup /Separation eq exch /DeviceN eq or {
- dup 1 oget dup type /arraytype eq {
- { oforce 2 index putspotcolor } forall
+ dup /Pattern eq {
+ 1 index length 1 gt { % only uncolored patterns have colorspace
+ pop 1 oget % <<>> [base]
+ 2 copy exch colorspacespotcolors
} {
- 2 index putspotcolor
+ pop
} ifelse
- } if
+ } {
+ % Stack: <spotcolordict> <colorspace> <colorspacetype>
+ dup /Separation eq exch /DeviceN eq or {
+ dup 1 oget dup type /arraytype eq {
+ { oforce 2 index putspotcolor } forall
+ } {
+ 2 index putspotcolor
+ } ifelse
+ } if
+ } ifelse
} ifelse
} if
pop pop
@@ -3647,6 +3899,70 @@ currentdict /PDF2PS_matrix_key undef
} if
} bind executeonly def
+% These functions can be used in error handling. It is not always possible to
+% use the PostScript sequence 'mark ..... cleartomark' to clean up behind a
+% sequence of operations, because processing the PDF might leave a mark
+% object on the stack. There are a number of ways to address that problem; one
+% is to count the objects on the stack at the time and store that value in a
+% convenient dictionary, presented here is an alternative. Instead of using a
+% mark object, we can use a specific name object as if it were a mark object
+% and use the two routines below to count the number of objects on the stack
+% up to a specific key, and to clear the stack back to a named key.
+
+%
+% /key CountToKey false | int true
+%
+% Counts the operand stack backwards until it encounters
+% a specific name key on the stack. Returns true and the count
+% of objects on the stack after that key, or false if the key
+% was not found on the stack. Consumes the key passed
+% to CountToKey. Throws a typecheck if the operand is not
+% a name type.
+%
+/CountToKey
+{
+ dup type /nametype eq {
+ //false
+ 0 1 count 5 sub
+ {
+ dup 3 add index
+ 3 index eq
+ {
+ 3 1 roll pop pop //true exit
+ }
+ {pop} ifelse
+ } for
+
+ {
+ //true
+ }
+ {
+ pop //false
+ } ifelse
+ }
+ {
+ /CountToKey cvx /typecheck signalerror
+ }ifelse
+}bind readonly def
+
+%
+% /key ClearToKey -
+%
+% Clears the operand stack backwards until it encounters
+% the name object passed as an operand. If the name object
+% is not present on the stack then it will clear the entire
+% stack. Like cleartomark this removes the 'key' from the stack.
+%
+/ClearToKey
+{
+ 0 1 count 4 sub
+ {
+ pop
+ dup 3 1 roll eq {exit} if
+ } for
+ pop
+}bind readonly def
+
end % pdfdict