diff options
Diffstat (limited to 'gs/lib/gs_ll3.ps')
-rw-r--r-- | gs/lib/gs_ll3.ps | 433 |
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. |