summaryrefslogtreecommitdiff
path: root/gs/lib/gs_ll3.ps
diff options
context:
space:
mode:
Diffstat (limited to 'gs/lib/gs_ll3.ps')
-rw-r--r--gs/lib/gs_ll3.ps433
1 files changed, 238 insertions, 195 deletions
diff --git a/gs/lib/gs_ll3.ps b/gs/lib/gs_ll3.ps
index 08e0be77c..80ae53b9a 100644
--- a/gs/lib/gs_ll3.ps
+++ b/gs/lib/gs_ll3.ps
@@ -1,4 +1,4 @@
-% Copyright (C) 1997, 1998 Aladdin Enterprises. All rights reserved.
+% Copyright (C) 1997, 1998, 1999 Aladdin Enterprises. All rights reserved.
%
% This file is part of Aladdin Ghostscript.
%
@@ -17,7 +17,6 @@
% Initialization file for PostScript LanguageLevel 3 functions.
-% Essentially all of these are stubs right now.
% This file must be loaded after gs_lev2.ps and gs_res.ps.
% These definitions go into ll3dict or various ProcSets.
% NOTE: the interpreter creates ll3dict.
@@ -66,122 +65,114 @@ languagelevel dup 2 max .setlanguagelevel
} if
currentdict /.bindscratch .undef
-% ------ HalftoneTypes 6, 10, 16 ------ %
-
-% This code depends on one new operator:
-%
-% <dict> <Width> <Height> <Thresholds> <bits> <shift> .setstriphalftone -
-%
-% <dict> is the dictionary that will be returned by .currenthalftone.
-% The operator only looks at the TransferFunction entry.
-% Width, Height: as for HalftoneType 3.
-% Thresholds: a BigStringEncode filter holding the thresholds,
-% Width x Height x BitsPerSample / 8 bytes.
-% shift: the amount of X shift per Y repetition of the halftone,
-% 0 <= Shift < Width.
-% bits: bits per sample, 8 or 16.
-%
-% Eventually the code below will have to get hooked up to sethalftone
-% and currenthalftone....
-
-/.copybytes { % <source> <dest> <count> .copybytes -
- { 1 index read not { /sethalftone load /rangecheck signalerror exit } if
- 1 index exch write
- } repeat pop pop
+% ------ HalftoneTypes 6, 10, 16 and HalftoneMode ------ %
+
+% This code depends on an internal HalftoneType 7 with the following keys:
+% Width, Height, Width2, Height2, TransferFunction:
+% as for HalftoneType 16.
+% Thresholds: a string or bytestring holding the thresholds,
+% (Width x Height + Width2 x Height2) x BitsPerSample / 8 bytes,
+% as for HalftoneType 16 except that the samples may be either
+% 8 or 16 bits wide.
+% BitsPerSample: 8 or 16.
+
+% Note that this HalftoneType never appears in halftone dictionaries given
+% to sethalftone, only as a component in those given to .sethalftone5,
+% so its numeric value can be chosen ad lib as long as it differs from the
+% other values that are legal in component dictionaries for .sethalftone5
+% (currently only 1 and 3).
+
+/.makehalftone7 { % <dict> <dict> <source> <Width> <Height>
+ % (<Width2> <Height2> | null) <BPS> .makehalftone7
+ % <setdict> <dict5> { .sethalftone5 }
+ 8 dict begin
+ /HalftoneType 7 def
+ /BitsPerSample exch def
+ dup null eq {
+ pop 0
+ } {
+ /Height2 1 index def /Width2 2 index def mul
+ } ifelse 3 1 roll
+ /Height 1 index def
+ /Width 2 index def
+ mul add BitsPerSample 8 idiv mul .bigstring
+ % Stack: dict source str
+ dup type /stringtype eq { readstring } { .readbytestring } ifelse
+ not { /sethalftone load /rangecheck signalerror exit } if
+ readonly /Thresholds exch def
+ /TransferFunction .knownget { /TransferFunction exch def } if
+ % If the original Thresholds was a file, replace it with
+ % a new one.
+ 1 index /Thresholds get type /filetype eq {
+ dup /Thresholds [ Thresholds ] cvx 0 () .subfiledecode put
+ } if
+ mark /HalftoneType 5 /Default currentdict end .dicttomark
+ { .sethalftone5 }
} bind def
-/.copythresholds { % <dict> <Width> <Height> <bits> .copythresholds -
- dup 8 idiv 3 index mul 2 index mul
- dup /BigStringEncode filter 3 1 roll
- % Stack: dict width height dest bits nbytes
- 5 index /Thresholds get 3 index 3 -1 roll .copybytes
- 1 index closefile
- 0 .setstriphalftone
+/.bigstring { % <size> .bigstring <string|bytestring>
+ dup 65400 gt { .bytestring } { string } ifelse
} bind def
-/.sethalftone6 { % <dict> .sethalftone6 -
- % Keys: Width, Height, Thresholds, T'Function
- dup /Width get 1 index /Height get
- 8 .copythresholds
-} odef
-
-/.copythresholds2 { % <dict> <Width> <Height> <Width2> <Height2>
- % <bits> .copythresholds2 -
-% The block height B is gcd(Height, Height2).
- 3 index 2 index {
- 2 copy lt { exch } if dup 1 eq { pop exit } if exch 1 index mod
- } loop
-% The raster R is (Width * Height + Width2 * Height2) / B * bits/8.
- 5 index 5 index mul 4 index 4 index mul add 1 index idiv
- 2 index 8 idiv mul
-% Currently I don't know how to compute the stride.
-% ****** COMPUTE THE STRIDE SOMEHOW ******
-% Push additional arguments onto the stack.
- 1 index 1 index mul /BigStringEncode filter 4 1 roll
- 9 index /Thresholds get
- % Stack: dict width height width2 height2 bits
- % dest B R stride source
-% For the first rectangle, the number of blocks is Height / B;
-% the offset is 0.
- 5 copy 14 index 5 1 roll
- 14 index 5 index idiv 4 1 roll
- 0 exch .copyshifted
-% For the second rectangle, the number of blocks is Height2 / B;
-% the offset is Width.
- 5 copy 12 index 5 1 roll
- 12 index 4 index idiv 4 1 roll
- 16 index exch .copyshifted
- % Stack: dict width height width2 height2 bits
- % dest B R stride source
- % We want: dict R/(bits/8) B dest bits stride
- pop exch 4 index 8 idiv idiv 4 1 roll
- % R/(bits/8) dest B stride
- exch 3 1 roll 5 -1 roll exch
- 9 -4 roll 4 { pop } repeat
- .setstriphalftone
+/.readbytestring { % <source> <bytestring> .readbytestring
+ % <bytestring> <filled>
+ % Note that since bytestrings don't implement getinterval,
+ % if filled is false, there is no way to tell how much
+ % was read.
+ true exch 0 1 2 index length 1 sub {
+ % Stack: source true str index
+ 3 index read not { pop exch not exch exit } if
+ 3 copy put pop pop
+ } for 3 -1 roll pop exch
} bind def
-% Copy a shifted rectangular threshold array into a BigStringEncode filter.
-% Note that the width and shift are in bytes, not samples.
-/.copyshifted { % <dest> <width> <B> <N> <R> <stride> <offset>
- % <source> .copyshifted -
-% Copy N blocks of <width> x B bytes from <source>.
-% Row Y (0 <= Y < B) in group G (0 <= G < N) must get copied to byte position
-% Y * R + (G * stride + offset) mod R
-% in the destination.
- 1 index % Stack: ... rowstart
- 6 index { % iterate over rows within a block
- 5 index { % iterate over blocks
- 8 index 1 index setfileposition
- 1 index 9 index 9 index .copybytes
- 4 index add % + raster
- } repeat % end block
- 3 index add 4 index mod % + stride, mod raster
- } repeat % end row in block
- 9 { pop } repeat
+/.sethalftone6 { % <dict> <dict> .sethalftone6 <setdict> <dict5>
+ % { .sethalftone5 }
+ % Keys: Width, Height, Thresholds, T'Function
+ dup /Thresholds get
+ 1 index /Width get 2 index /Height get
+ null 8 .makehalftone7
} bind def
-/.sethalftone10 { % <dict> .sethalftone10 -
- % Keys: XSquare, YSquare, Thresholds, T'Function
-% ****** DOESN'T HANDLE STRING SOURCE ******
- dup /XSquare get dup 2 index /YSquare get dup
- 8 .copythresholds2
-} odef
+/.sethalftone10 { % <dict> <dict> .sethalftone10 <setdict> <dict5>
+ % { .sethalftone5 }
+ % Keys: Xsquare, Ysquare, Thresholds, T'Function
+ % Note that this is the only one of these three HalftoneTypes
+ % that allows either a file or a string for Thresholds.
+ dup /Thresholds get dup type /stringtype eq { 0 () .subfiledecode } if
+ 1 index /Xsquare get dup 3 index /Ysquare get dup
+ 8 .makehalftone7
+} bind def
-/.sethalftone16 { % <dict> .sethalftone16 -
+/.sethalftone16 { % <dict> <dict> .sethalftone16 <setdict> <dict5>
+ % { .sethalftone5 }
% Keys: Width, Height, Width2, Height2,
% Thresholds, T'Function
- dup /Width get 1 index /Height get
- 2 index /Width2 .knownget { % 2-rectangle case
- 3 index /Height2 get
- 16 .copythresholds2
+ dup /Thresholds get
+ 1 index /Width get 2 index /Height get
+ 3 index /Width2 .knownget { % 2-rectangle case
+ 4 index /Height2 get
} { % 1-rectangle case
- 16 .copythresholds
+ null
+ } ifelse 16 .makehalftone7
+} bind def
+
+.halftonetypes begin
+ 6 /.sethalftone6 load def
+ 10 /.sethalftone10 load def
+ 16 /.sethalftone16 load def
+end
+
+% Redefine sethalftone to recognize HalftoneMode.
+% We should redefine setscreen and setcolorscreen as well.
+/sethalftone {
+ /HalftoneMode getuserparam 0 eq {
+ //sethalftone
+ } {
+ pop .setdefaulthalftone
} ifelse
} odef
-{6 10 16} { dup /HalftoneType defineresource pop } forall
-
% ------ ImageTypes 3 and 4 (masked images) ------ %
.imagetypes
@@ -218,12 +209,22 @@ systemdict /.shadingtypes mark % not ll3dict
% The .buildshading operators use the current color space
% for ColorSpace.
dup /ShadingType get //.shadingtypes exch get
- 1 index /ColorSpace get gsave { setcolorspace exec } stopped
- grestore { stop } if
+ 1 index /ColorSpace get setcolorspace exec
} bind def
+
/.buildpattern2 { % <template> <matrix> .buildpattern2
% <template> <pattern>
- 1 index /Shading get .buildshading .buildshadingpattern
+ % We want to build the pattern without doing gsave/grestore,
+ % since we want it to load the CIE caches.
+ 1 index /Shading get
+ mark currentcolor currentcolorspace
+ counttomark 4 add -3 roll mark 4 1 roll
+ % Stack: -mark- ..color.. cspace -mark- template matrix shadingdict
+ { .buildshading } stopped {
+ cleartomark setcolorspace setcolor pop stop
+ } if
+ .buildshadingpattern
+ 3 -1 roll pop counttomark 1 add 2 roll setcolorspace setcolor pop
} bind def
.patterntypes
@@ -232,96 +233,15 @@ systemdict /.shadingtypes mark % not ll3dict
/shfill { % <shadingdict> shfill -
% Currently, .shfill requires that the color space
% in the pattern be the current color space.
- dup .buildshading
- 1 index /ColorSpace get
- gsave { setcolorspace .shfill } stopped grestore { stop } if
+ dup gsave { .buildshading .shfill } stopped grestore { stop } if
pop
} odef
% Establish an arbitrary initial smoothness value.
1 64 div setsmoothness
-% ------ Trapping ------ %
-
-% The PostScript-level trapping parameters are maintained in userdict,
-% and explicitly reinstalled upon restore.
-
-/Trapping mark
+% ------ ReusableStreamDecode filter ------ %
-/settrapparams dup { % <paramdict> settrapparams -
- /.trapparams .uservar dup length dict .copydict
- dup 2 index {
- % Stack: paramdict olddict olddict key value
- 2 index 2 index known { put dup } { pop pop } ifelse
- } forall pop
- dup .settrapparams % Let the operator check parameter validity.
- .userdict /.trapparams 3 -1 roll put pop
-} bind .makeoperator
-
-/.copyparams { % <obj> .copyparams <obj'>
- dup type /dicttype eq {
- dup length dict .copydict
- dup {
- .copyparams 3 copy put pop pop
- } forall
- } {
- dup type /arraytype eq {
- [ exch { .copyparams } forall ]
- } if
- } ifelse
-} odef
-
-/currenttrapparams dup { % - currenttrapparams <paramdict>
- /.trapparams .uservar .copyparams
-} bind .makeoperator
-
-/settrapzone dup { % - settrapzone -
- % ****** DUMMY ******
- newpath
-} bind .makeoperator
-
-% Define initial (dummy) trapping parameters.
-% These values are mostly complete guesses.
-userdict /.trapparams mark
- /BlackColorLimit 1.0
- /BlackDensityLimit 1.0
- /BlackWidth 1.0
- /ColorantZoneDetails 0 dict
- /Enabled true
- /HalftoneName null
- /ImageInternalTrapping false
- /ImageResolution 1
- /ImageToObjectTrapping true
- /ImageTrapPlacement /Center
- /SlidingTrapLimit 1.0
- /StepLimit 1.0
- /TrapColorScaling 0.0
- /TrapSetName null
- /TrapWidth 1.0
-.dicttomark readonly put
-
-.dicttomark /ProcSet defineresource pop
-
-% ------ Miscellaneous ------ %
-
-% Define additional user and system parameters.
-psuserparams begin
- /HalftoneMode 0 def
- /MaxSuperScreen 1016 def
-end
-pssystemparams begin % read-only, so use .forcedef
- /MaxDisplayAndSourceList 160000 .forcedef
-end
-
-% Define the IdiomSet, InkParams, and TrapParams resource categories.
-{ /IdiomSet /InkParams /TrapParams } {
- /Generic /Category findresource dup maxlength 3 add dict .copydict begin
- /InstanceType /dicttype def
- currentdict end /Category defineresource pop
-} forall
-
-% Define the ReusableStreamDecode filter.
-% ****** DOESN'T WORK FOR CONTENTS >64K ******
/.reusablestreamdecode { % <source> <dict> .reusablestreamdecode <file>
% <source> .reusablestreamdecode <file>
% Collect the filter parameters.
@@ -342,7 +262,7 @@ end
} {
4 index 2 index get dup null eq { pop } if
} ifelse
- 3 -1 roll pop filter
+ 3 -1 roll pop exch filter
exch pop true exch % set CloseSource for further filters
} for
% See if we can create the filter directly.
@@ -350,27 +270,150 @@ end
null 2 index { .reusablestream } .internalstopped {
pop pop
% No luck. Read the entire contents of the stream now.
+ dup type /filetype ne {
+ % Make a stream from a procedure or string data source.
+ 0 () .subfiledecode
+ } if
10 dict exch {
% Stack: dict filters parms CloseSource contdict file
dup 1000 string readstring
- 3 index dup length 4 -1 roll put not { break } if
+ 3 index dup length 4 -1 roll put not { exit } if
} loop pop
% Concatenate the contents into one big string.
% Stack: dict filters parms CloseSource contdict
- 0 1 index { length exch pop add } forall string
- exch {
+ 0 1 index { length exch pop add } forall
+ .bigstring exch {
% Stack: dict filters parms CloseSource string index substring
exch 1000 mul exch 2 index 3 1 roll putinterval
} forall
% Now create the stream on the string.
- null 3 -1 roll .reusablestream
+ null 2 index .reusablestream
} if
% We created the stream successfully: clean up.
4 { exch pop } repeat
- dup type /dicttype eq { pop } if pop
+ 1 index type /dicttype eq { exch pop } if exch pop
} odef
+
filterdict /ReusableStreamDecode /.reusablestreamdecode load put
+% ------ UseCIEColor ------ %
+
+% The library maintains and detects the UseCIEColor device parameter,
+% but it doesn't have access to the resource dictionaries. We also
+% want color space substitution to work in systems without a PostScript
+% interpreter. Therefore, we eagerly inform the library of changes in
+% the (effective) ColorSpace category that might affect the operation of
+% UseCIEColor. We must notice the following events:
+% 1) defineresource and undefineresource of the Default ColorSpaces.
+% 2) restore.
+% 3) Changes in current VM, which cause a different set of resources
+% to become visible.
+% #1 is rare. #2 is handled in C code. If checking the ColorSpace
+% category on #3 turns out to be expensive, we can cache more information
+% about whether these operations actually affect UseCIEColor.
+
+% This operator implements color space substitution in the library:
+% <index> <bool> .setsubstitutecolorspace -
+% <bool> = true means substitute the current color space for the one given
+% by <index>; <bool> = false means stop substituting. Substitution is not
+% affected by grestore/setgstate, but it is affected by restore.
+
+% ColorSpace defineresource and undefineresource for the Default keys
+% call .definedefaultcs and .undefinedefaultcs. See gs_res.ps.
+
+/.useciecolorkeydict mark
+ /UseCIEColor null
+.dicttomark readonly def
+/.definedefaultcs { % <index> <value> .definedefaultcs -
+ currentcolorspace
+ % Temporarily disable color substitution, in case the substitute
+ % color space is or mentions a color space that is currently
+ % being substituted.
+ currentdevice //.useciecolorkeydict .getdeviceparams exch pop exch pop
+ mark 5 -2 roll
+ % Stack: cspace UseCIEColor mark index value
+ { setcolorspace true .setsubstitutecolorspace }
+ stopped counttomark 1 add 1 roll cleartomark
+ % Stack: cspace UseCIEColor stopped?
+ 3 1 roll
+ currentdevice null true mark /UseCIEColor 6 -1 roll .putdeviceparams pop pop
+ setcolorspace { stop } if
+} bind def
+currentdict /.useciecolorkeydict undef
+
+/.undefinedefaultcs { % <index> .undefinedefaultcs -
+ false .setsubstitutecolorspace
+} bind def
+
+/.setdefaultcs { % <index> <value|null> .setdefaultcs -
+ dup null eq { pop .undefinedefaultcs } { .definedefaultcs } ifelse
+} bind def
+
+/.getdefaultcs { % <key> .getdefaultcs <value|null>
+ .GetInstance { 0 get } { null } ifelse
+} bind def
+
+/.setglobal { % <bool> .setglobal -
+ dup .currentglobal ne {
+ % We only want to change substitutions for color spaces
+ % whose definitions are actually changing.
+ /ColorSpace /Category findresource begin
+ % If there are no local definitions of the Default keys,
+ % changing VM can't affect the definition of any resource.
+ .LocalDefaults {
+ /DefaultGray .getdefaultcs
+ /DefaultRGB .getdefaultcs
+ /DefaultCMYK .getdefaultcs
+ end
+ 3 index .setglobal
+ /ColorSpace /Category findresource begin
+ /DefaultGray .getdefaultcs
+ /DefaultRGB .getdefaultcs
+ /DefaultCMYK .getdefaultcs
+ end
+ % Stack: bool oldgray oldrgb oldcmyk
+ % newgray newrgb newcmyk
+ dup 4 index ne { 2 exch .setdefaultcs } { pop } ifelse
+ dup 4 index ne { 1 exch .setdefaultcs } { pop } ifelse
+ dup 4 index ne { 0 exch .setdefaultcs } { pop } ifelse
+ pop pop pop pop
+ } {
+ end .setglobal
+ } ifelse
+ } {
+ .setglobal
+ } ifelse
+} .bind odef % bind in .setglobal
+
+% ------ DeviceN color space ------ %
+
+% This isn't quite right, because the ColorSpaceFamily resource will exist
+% even with languagelevel < 3, but it's close enough.
+
+/.setdevicenspace where {
+ pop colorspacedict /DeviceN {
+ dup 2 get setcolorspace dup .setdevicenspace
+ } bind put
+} if
+
+% ------ Miscellaneous ------ %
+
+% Define additional user and system parameters.
+psuserparams begin
+ /HalftoneMode 0 def
+ /MaxSuperScreen 1016 def
+end
+pssystemparams begin % read-only, so use .forcedef
+ /MaxDisplayAndSourceList 160000 .forcedef
+end
+
+% Define the IdiomSet and InkParams resource categories.
+{ /IdiomSet /InkParams } {
+ /Generic /Category findresource dup maxlength 3 add dict .copydict begin
+ /InstanceType /dicttype def
+ currentdict end /Category defineresource pop
+} forall
+
/languagelevel 3 def
% When running in LanguageLevel 3 mode, this interpreter is supposed to be
% compatible with Adobe version 3010.