You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
377 lines
12 KiB
377 lines
12 KiB
% Copyright (C) 2001-2023 Artifex Software, Inc.
|
|
% All Rights Reserved.
|
|
%
|
|
% This software is provided AS-IS with no warranty, either express or
|
|
% implied.
|
|
%
|
|
% This software is distributed under license and may not be copied,
|
|
% modified or distributed except as expressly authorized under the terms
|
|
% of the license contained in the file LICENSE in this distribution.
|
|
%
|
|
% Refer to licensing information at http://www.artifex.com or contact
|
|
% Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
|
|
% CA 94129, USA, for further information.
|
|
%
|
|
|
|
% Allow the interpreter to encapsulate EPS files, to recognize MS-DOS
|
|
% EPSF file headers, and skip to the PostScript section of the file.
|
|
|
|
% Encapsulate EPS files and optionally resize page or rescale image.
|
|
% To display an EPS file cropped to the bounding box:
|
|
% gs -dEPSCrop file.eps
|
|
% To display an EPS file scaled to fit the page:
|
|
% gs -dEPSFitPage file.eps
|
|
% To display a file without EPS encapsulation:
|
|
% gs -dNOEPS file.ps
|
|
|
|
% When starting to process an EPS file, state is 0.
|
|
% After %%BoundingBox processed, state is 1 if OK or 2 if cropped.
|
|
% After %%HiResBoundingBox processed, state is 3 if OK or 4 if cropped.
|
|
% After %%EndComments processed, state is 5.
|
|
/EPSBoundingBoxState 5 def
|
|
/EPSBoundingBoxString () def % set if either BoundingBox is seen (even if invalid)
|
|
/EPSBoundingBoxSetState {
|
|
//systemdict /EPSBoundingBoxState 3 -1 roll .forceput
|
|
} .forcebind odef % .forceput must be bound and hidden
|
|
|
|
% Parse 4 numbers for a bounding box
|
|
/EPSBoundingBoxParse { % (llx lly urx ury) -- llx lly urx ury true OR false
|
|
mark exch
|
|
token {exch token {exch token {exch token {exch pop} if} if} if} if
|
|
counttomark
|
|
4 eq {
|
|
5 -1 roll pop % remove mark
|
|
//true
|
|
} {
|
|
cleartomark //false
|
|
} ifelse
|
|
} .internalbind odef
|
|
|
|
% Crop the page to the BoundingBox
|
|
/EPSBoundingBoxCrop { % llx lly urx ury --
|
|
EPSDEBUG {
|
|
(gs_epsf.ps: Setting pagesize from EPS bounding box\n) print flush
|
|
} if
|
|
exch 3 index sub exch 2 index sub % stack: llx lly urx-llx ury-lly
|
|
<< /PageSize [ 5 -2 roll ] >> setpagedevice
|
|
neg exch neg exch translate
|
|
} .internalbind odef
|
|
|
|
% Rescale, translate and rotate to fit the BoundingBox on the page
|
|
/EPSBoundingBoxFitPage { % llx lly urx ury --
|
|
EPSDEBUG { (gs_epsf.ps: Rescaling EPS to fit page\n) print flush } if
|
|
clippath pathbbox newpath % ellx elly eurx eury pllx plly purx pury
|
|
EPSDEBUG {
|
|
(Page Coordinates: LLX: ) print 3 index =print (, LLY: ) print
|
|
2 index =print (, URX: ) print 1 index =print (, URY: ) print dup = flush
|
|
} if
|
|
% Convert box corners to coordinates of the center and box sizes
|
|
2 { % loop doing the page coordinates, the the EPS bbox coordinates
|
|
3 -1 roll exch % ... llx urx lly ury
|
|
2 { % loop doing Y then X coordnates
|
|
2 copy exch sub % ... llx urx lly ury ury-lly
|
|
3 1 roll % ... llx urx ury-lly lly ury
|
|
add 2 div % ... llx urx ury-lly (lly+ury)/2
|
|
4 2 roll % ... ury-lly (lly+ury)/2 llx urx
|
|
} repeat
|
|
8 4 roll
|
|
} repeat
|
|
% edx, edy = EPS dimension X and Y, ecx, ecy = EPS Center X and Y.
|
|
% pdx and pcx, etc, are for the Page values.
|
|
% edx ecx edy ecy pdx pcx pdy pcy
|
|
|
|
% Move the origin to the center of the printable area.
|
|
3 -1 roll exch % edx ecx edy ecy pdx pdy pcx pcy
|
|
translate % edx ecx edy ecy pdx pdy
|
|
|
|
% Find orientation of the best fit. Square pages or files don't rotate.
|
|
2 copy sub % edx ecx edy ecy pdx pdy pdx-pdy
|
|
EPSDEBUG {
|
|
(pdx: ) print 2 index =print (, pdy: ) print 1 index =print
|
|
(, pdx-pdy: ) print dup = flush
|
|
} if
|
|
6 index 5 index sub
|
|
EPSDEBUG {
|
|
(edx: ) print 7 index =print (, edy: ) print 5 index =print
|
|
(, edx-edy: ) print dup = flush
|
|
} if
|
|
mul % edx ecx edy ecy pdx pdy (pdx-pdy)*(edx-edy)
|
|
EPSDEBUG {
|
|
(product: ) print dup = flush
|
|
} if
|
|
0 lt {
|
|
90 rotate
|
|
exch
|
|
} if
|
|
|
|
% Scale to fit in the most restricting direction.
|
|
4 -1 roll div % edx ecx ecy pdx pdy/edy
|
|
exch 5 -1 roll div % ecx ecy pdy/edy pdx/edx
|
|
//.min exec
|
|
dup scale % ecx ecy
|
|
|
|
% Center the document
|
|
neg exch neg exch translate
|
|
|
|
} .internalbind odef
|
|
|
|
/EPSBoundingBoxProcess { % (llx lly urx ury) state --
|
|
% The following 'lt' check prioritzies HiResBoundingBox over BoundingBox
|
|
% even if HiResBoundingBox occurs first in the EPS file.
|
|
//systemdict /EPSBoundingBoxState get 1 index lt {
|
|
% save the BBoxString for possible FitPage when EndComments is seen
|
|
exch dup currentglobal //true setglobal exch
|
|
dup length string copy //systemdict /EPSBoundingBoxString 3 -1 roll .forceput
|
|
setglobal
|
|
EPSBoundingBoxParse
|
|
{
|
|
//systemdict /EPSCrop known {
|
|
EPSBoundingBoxCrop
|
|
} {
|
|
//systemdict /EPSFitPage known not {
|
|
% Warn if some of the EPS file will be clipped
|
|
clippath pathbbox newpath
|
|
{ % context for exit
|
|
5 -1 roll lt { 6 { pop } repeat //true exit } if
|
|
4 -1 roll lt { 4 { pop } repeat //true exit } if
|
|
3 -1 roll gt { 2 { pop } repeat //true exit } if
|
|
exch gt { //true exit } if
|
|
//false exit
|
|
} loop
|
|
QUIET not and /EPSBoundingBoxState .systemvar 1 and 1 eq and {
|
|
(\n **** Warning: Some of the BoundingBox for the EPS file will be clipped.) =
|
|
( Use -dEPSCrop or -dEPSFitPage to avoid clipping.\n) =
|
|
flush
|
|
1 add
|
|
} if
|
|
} {
|
|
pop pop pop pop
|
|
} ifelse
|
|
} ifelse
|
|
EPSBoundingBoxSetState
|
|
} {
|
|
% improperly formed BoundingBox string.
|
|
QUIET not {
|
|
(\n **** Warning: BoundingBox values are invalid and will be ignored: ') print
|
|
EPSBoundBoxString print (') = flush
|
|
} if
|
|
pop % state
|
|
} ifelse
|
|
} {
|
|
pop pop
|
|
} ifelse
|
|
} .internalbind odef
|
|
|
|
% Perform anchorsearch on the strings in the array until a match is found.
|
|
/anchorsearchforany { % haystack [needle1 ...] --> post needle true
|
|
% --> haystack false
|
|
false 3 1 roll % false haystack [...]
|
|
{ % false haystack needle
|
|
dup 3 1 roll % false needle haystack needle
|
|
anchorsearch {
|
|
% false needle post needle
|
|
pop % false needle post
|
|
3 1 roll % post false needle
|
|
exch not exch % post true needle
|
|
exit
|
|
} {
|
|
% false needle haystack
|
|
exch pop % false haystack
|
|
} ifelse
|
|
} forall
|
|
exch % haystack false | post needle true
|
|
} .internalbind def
|
|
|
|
/ProcessEPSComment { % file comment -- file comment
|
|
/EPSBoundingBoxState .systemvar 3 lt {
|
|
dup
|
|
(%%BoundingBox:) anchorsearch {
|
|
pop
|
|
EPSDEBUG { (gs_epsf.ps: found %%BoundingBox\n) print flush } if
|
|
1 EPSBoundingBoxProcess
|
|
} {
|
|
(%%HiResBoundingBox:) anchorsearch {
|
|
pop
|
|
EPSDEBUG { (gs_epsf.ps: found %%HiResBoundingBox\n) print flush } if
|
|
3 EPSBoundingBoxProcess
|
|
} {
|
|
pop % Not interested in this DSC comment
|
|
} ifelse
|
|
} ifelse
|
|
} if
|
|
/EPSBoundingBoxState .systemvar 5 lt {
|
|
dup (%%DocumentCustomColors:) anchorsearch {
|
|
pop
|
|
[ exch
|
|
{ {
|
|
token not { exit } if
|
|
dup type /stringtype ne { stop } if
|
|
dup (atend) eq { stop } if
|
|
exch
|
|
} loop
|
|
{
|
|
counttomark 2 add index
|
|
dup (123) .peekstring not { stop } if
|
|
(%%+) eq {
|
|
dup (123) readstring pop pop
|
|
256 string readline pop
|
|
cvx exec
|
|
} {
|
|
pop exit
|
|
} ifelse
|
|
} loop
|
|
} stopped {
|
|
cleartomark
|
|
} {
|
|
counttomark 0 gt {
|
|
currentpagedevice /MaxSeparations get 4 gt {
|
|
] << /SeparationColorNames 3 -1 roll >> setpagedevice
|
|
} {
|
|
cleartomark
|
|
} ifelse
|
|
} {
|
|
cleartomark
|
|
} ifelse
|
|
} ifelse
|
|
} {
|
|
{(%%EndComments) (%%BeginProlog) (%%BeginSetup)} anchorsearchforany {
|
|
EPSDEBUG { (EPSComment processing finished, encountered: ) print dup = } if
|
|
pop pop % discard the strings from the anchorsearch
|
|
% We may have seen BoundingBox or HiResBounfingBox. If so and if EPSFitPage
|
|
% is set, then we do the transformation here to scale and center the page,
|
|
% rotating if needed (and AllowFitPageRotation is true -- the default.)
|
|
//systemdict /EPSFitPage known
|
|
//systemdict /EPSBoundingBoxState get 0 gt
|
|
and {
|
|
EPSBoundingBoxString EPSBoundingBoxParse {
|
|
EPSBoundingBoxFitPage
|
|
} if
|
|
} if
|
|
% Ignore any following comments
|
|
5 EPSBoundingBoxSetState
|
|
} {
|
|
pop % Not %%EndComments -- ignore it
|
|
} ifelse
|
|
} ifelse
|
|
} if
|
|
} .internalbind def
|
|
|
|
% Install EPS handler for DSC comments, which we do later
|
|
/EPSBoundingBoxInit {
|
|
systemdict /NOEPS known not {
|
|
% Merge ProcessEPSComment with existing handler
|
|
//ProcessEPSComment /exec load
|
|
currentuserparams /ProcessDSCComment get
|
|
dup //null eq {pop {pop pop}} if /exec load
|
|
4 array astore cvx readonly
|
|
<< /ProcessDSCComment 3 -1 roll >> setuserparams
|
|
} if
|
|
} .internalbind odef
|
|
|
|
|
|
/.runNoEPS /run load def
|
|
|
|
/.runEPS { % file OR string --
|
|
.updatematrices
|
|
/runEPS_save save def
|
|
/runEPS_dict_count countdictstack def
|
|
/runEPS_op_count count 2 sub def
|
|
/runEPS_page_count .currentshowpagecount not {0} if def
|
|
0 EPSBoundingBoxSetState
|
|
//.runNoEPS
|
|
.currentshowpagecount not {0} if runEPS_page_count sub 0 eq
|
|
{ /showpage load exec } if
|
|
count runEPS_op_count sub {pop} repeat
|
|
countdictstack runEPS_dict_count sub {end} repeat
|
|
runEPS_save restore
|
|
} .internalbind odef
|
|
|
|
/run { % file OR string --
|
|
dup type /filetype ne { (r) file } if
|
|
dup (%!PS-Adobe-) .peekstring {
|
|
(%!PS-Adobe-) eq {
|
|
dup (%!PS-Adobe-X.X EPSF-X.X) .peekstring {
|
|
(EPSF) search {
|
|
pop pop pop
|
|
EPSDEBUG {(runEPS: Found EPS\n) print flush} if
|
|
systemdict /NOEPS known {
|
|
cvx //.runNoEPS
|
|
} {
|
|
cvx .runEPS
|
|
} ifelse
|
|
} {
|
|
EPSDEBUG {(runEPS: Normal DSC\n) print flush} if
|
|
pop
|
|
cvx //.runNoEPS
|
|
|
|
} ifelse
|
|
} {
|
|
EPSDEBUG {(runEPS: Short DSC\n) print flush} if
|
|
pop
|
|
cvx //.runNoEPS
|
|
} ifelse
|
|
} {
|
|
EPSDEBUG {(runEPS: Not DSC\n) print flush} if
|
|
cvx //.runNoEPS
|
|
} ifelse
|
|
} {
|
|
EPSDEBUG {(runEPS: Short non-DSC\n) print flush} if
|
|
pop
|
|
cvx //.runNoEPS
|
|
} ifelse
|
|
} .internalbind odef
|
|
|
|
% Handle DOS EPS files.
|
|
|
|
/.runnoepsf /run load def
|
|
/.epsfheader <C5D0D3C6> def
|
|
/run
|
|
{ dup type /filetype ne { (r) file } if
|
|
% Check for MS-DOS EPSF file (see Red Book p. 729).
|
|
dup ( ) .peekstring
|
|
{ .epsfheader eq { dup ( ) readstring exch pop } { //false } ifelse }
|
|
{ pop //false }
|
|
ifelse
|
|
% Stack: file true/false
|
|
{ % This block is executed if the file is MS-DOS EPSF.
|
|
% Build up the little-endian byte offset and length.
|
|
2
|
|
{ 1 0 4
|
|
{ 2 index read not { pop exit } if % if EOF, let error happen
|
|
2 index mul add exch 256 mul exch
|
|
}
|
|
repeat exch pop exch
|
|
}
|
|
repeat
|
|
% Stack: offset length file
|
|
% Use flushfile to skip quickly to the start of the
|
|
% PostScript section.
|
|
dup 4 -1 roll 12 sub () /SubFileDecode filter flushfile
|
|
% Now interpret the PostScript.
|
|
exch () /SubFileDecode filter cvx run
|
|
}
|
|
{ //.runnoepsf
|
|
}
|
|
ifelse
|
|
} odef
|
|
|
|
% rebind .runstdin to use redefined run
|
|
userdict begin
|
|
/.runstdin {
|
|
{ (%stdin) run } execute0
|
|
} .internalbind def
|
|
end
|
|
|
|
% undefine things defined in this file and not referenced elsewhere
|
|
[
|
|
/.runNoEPS
|
|
/.runnoepsf
|
|
/.runEPS
|
|
/EPSBoundingBoxSetState
|
|
/EPSBoundingBoxString
|
|
/EPSBoundingBoxCrop
|
|
/EPSBoundingBoxFitPage
|
|
/EPSBoundingBoxParse
|
|
/EPSBoundingBoxProcess
|
|
/ProcessEPSComment
|
|
] currentdict .undefinternalnames
|