123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984 |
- % Copyright (C) 2002 Aladdin Enterprises. 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.
- %
- % For more information about licensing, please refer to
- % http://www.ghostscript.com/licensing/. For information on
- % commercial licensing, go to http://www.artifex.com/licensing/ or
- % contact Artifex Software, Inc., 101 Lucas Valley Road #110,
- % San Rafael, CA 94903, U.S.A., +1(415)492-9861.
- % $Id: gs_cspace.ps,v 1.6 2003/06/26 22:42:33 dan Exp $
- % basic colorspace mechanism
- %
- % This new implementation of color spaces extends the color space
- % formalism to all PostScript levels. Level specific features and
- % operators continue to be accessible only in the appropriate level,
- % but the colorspace concept and associated mechanisms are used
- % throughout.
- %
- % The color space mechanism is built around two dictionaries:
- %
- % .cspace_util
- % A dictionary in global VM that is accessible in userdict only
- % during initialization. This dictionary is intended for various
- % utility procedures that are used in implementing the individual
- % color spaces.
- %
- % colorspacedict
- % A dictionary of methods for each color space type. The keys
- % in this dictionary are color space type names (e.g.: /DeviceGray,
- % /Separation, etc.), and the values are dictionaries of methods.
- % The set of methods is the same for each color space type, and
- % provides a complete implementation for the corresponding color
- % space type. This dictionary is in global VM.
- %
- % The information specific to a color space type is created in a file
- % for that type or group of types (e.g.: gs_csdev.ps, gs_csindx.ps,
- % etc.). These files will generally adhere to the template:
- %
- % .currentglobal true .setglobal
- % <level-specific dictionary> begin
- % ...
- % .cspace_util begin
- % colorspacedict
- % /<color space type name>
- % mark
- % /cs_validate
- % {
- % ...
- % }
- % bind
- % ...
- % .dicttomark
- % put
- % end % .cspace_util
- % end ... % level-specific dictionary
- % .setglobal
- %
- % The methods associated with a color space are listed below (along with
- % their stack handling), followed by descriptions.
- %
- % - cs_potential_indexed_base <bool>
- %
- % - cs_potential_pattern_base <bool>
- %
- % - cs_potential_alternate <bool>
- %
- % - cs_potential_icc_alternate <bool>
- %
- %
- % <name | array> cs_get_ncomps <int>
- %
- % <name | array> cs_get_range <range_array>
- %
- % <name | array> cs_get_default_color <c1> ... <cn>
- %
- %
- % <c1> ... <cn> <name | array> cs_get_currentgray <gray>
- %
- % <c1> ... <cn> <name | array> cs_get_currentrgb <red> <green> <blue>
- %
- % <c1> ... <cn> <name | array> cs_get_currentcmyk
- % <cyan> <magenta> <yellow> <black>
- %
- %
- % <name | array> cs_validate <name | array>
- %
- % <name1 | array1> cs_substitute <name1 | array1> <array2>
- %
- % <name1 | array1> <array2> cs_prepare <name1 | array1> <array2>
- %
- % <name | array> cs_install -
- %
- %
- % <c1> ... <cn> <array> cs_verify_color <c1> ... <cn>
- %
- % <array> cs_complete_color -
- %
- %
- % cs_potential_indexed_base, cs_potential_pattern_base,
- % cs_potential_alternate, cs_potential_icc_alternate
- % These are booleans rather than procedures. They indicate if the color
- % space can be a base space of an Indexed color space (anything except
- % Indexed and Pattern), a Pattern color space (anything except Pattern),
- % the alternative color space of a Separation or DeviceN color space, or
- % the alternative color space of an ICCBased color space. The two
- % parameters are distinct only because of a Ghostscript-specific
- % implementation problem; in principle, there is nothing special about
- % ICCBased color spaces in this regard.
- %
- % cs_get_ncomps
- % Return the number of color components for the color spaces. For Pattern
- % color spaces, the value is -1 if there is no base space, or -(n + 1) if
- % the base space has n components.
- %
- % cs_get_range
- % Return the input Range array appropriate for this color space. This is
- % defined for all color spaces, though it is of interest primarily for
- % CIEBased and ICCBased color spaces. For Indexed color spaces this is
- % [ 0 hival ], where hival is the maximum support index value. For all
- % other non-CIEBased, non-ICCBased color spaces, the range is an array
- % of ncomps elements, all of which are [ 0 1 ], where ncomps is the
- % number of color space components.
- %
- % cs_get_default_color
- % Generates the default color for the current color space. Under normal
- % circumstances this is done internally. It is provided in PostScript
- % only to support an optimization that doesn't change the current color
- % space more often than necessary.
- %
- % cs_get_currentgray, cs_get_currentrgb, cs_get_currentcmyk
- % These procedures are used to implement the currentgray, currentrgb,
- % and currentcmyk operators (which are pseudo-operators in the current
- % implementation).
- %
- % cs_validate
- % Validate the operand color space. Because color spaces are extensively
- % manipulated in PostScript in this implementation, error handling can
- % become burdensome. To make the code somewhat simpler, it is useful to
- % be able to validate a color space prior to manipulation, so as to
- % ensure that errors are not discovered in awkward places.
- %
- % cs_substitute
- % Substitute a device-independent color space for device specific color
- % space. This applies directly to the device-specific color spaces
- % (DeviceGray, DeviceRGB, DeviceCMYK), and indirectly when these color
- % spaces are used as base/alternative color spaces. The mechanism for
- % color substitution is included in all language levels, though it may
- % only be accessed for Language Level 3.
- %
- % The substituted color space is the topmost of the operands pushed.
- % this may or may not be the same as the original color space, which
- % is immediately below it on the operand stack. If the two differ,
- % the substituted space will always be in local VM (and will be
- % writable).
- %
- % Substitution is applied recursively to the base/alternate color
- % space of ICCBased, Indexed, Separation, DeviceN, or Pattern
- % color spaces. Because Ghostscript currently requires that any
- % base or alternative color space be the current color space when
- % the enclosing color space is set, this substitution effectively
- % occurs twice: once in the original color space, and once when the
- % base/alternative color space is made the current color space.
- % We retain the first substitution as we would eventually like to
- % remove the restriction on making the base/alternative color space
- % the current color space.
- %
- % cs_prepare
- % Perform any operations required on the color space for installation.
- % This method exists primarily to allow conversion of PostScript
- % procedures to functions for CIEBased color spaces. Two operands are
- % provided: the original and the substituted color space. If the two
- % differ and the latter is writable, required modifications can
- % be made "in place". Otherwise, a new instance of the second color
- % space must be built.
- %
- % Currently, cs_prepare is not explicitly recursive. Because
- % Ghostscript requires a base/alternate color space to be installed
- % as the current color space prior to installing the enclosing color
- % space, the cs_prepare method will implicitly be called recursively.
- % The reason for not making this explicit is that color space
- % preparation may involve a considerable amount of work, which could
- % be avoided if, for example, an alternative color space will not
- % be used because the enclosing Separation/DeviceN color space is
- % supported in native mode by the process color model. We would
- % eventually like to remove the need to prepare color spaces that
- % will not be used.
- %
- % cs_install
- % This method actually installs the color space in the graphic state.
- % Only the substituted/prepared space (which may be the same as the
- % original space) is passed as an operand; the original space is handled
- % directly by the .setcolorspace operator.
- %
- % The provision of a separate method for this tasks reflects the
- % historical implementation of color spaces in the Ghostscript
- % interpreter. This implementation provides a unique operator for each
- % color space type.
- %
- % cs_prepare_color
- % Modify a set of color operands as required by a color space. This
- % is used primarily to verify the color operands, as this is most
- % conveniently done in PostScript.
- %
- % cs_complete_setcolor
- % This method is invoked immediately after a (successful) invocation
- % of setcolor. Ii is provided as a separate method for compatibility
- % with Adobe implementations. These implementations invoke the lookup
- % (Indexed) or tint procedure each time setcolor is invoked (only if
- % the alternative color space is used in the case of the tint
- % transform). Because Ghostscript may convert these procedures to
- % functions (or pre-sample them), the procedures may not always be
- % called when expected. There are applications that depend on this
- % behavior (e.g.: Adobe PhotoShop 5+), so this method provides a way
- % to emulate it.
- %
- % In principle, a cs_complete_setcolor procedure for an Indexed color
- % space whose base space should invoke cs_complete_setcolor on its
- % base space. Currently we don't do this, because it has not been
- % shown to be necessary. It would be simple to add if it is every
- % needed.
- %
- % All of these methods are procedures.
- %
- % For each of these methods, there is a procedure in .cspace_util with
- % a dot ('.') prefix that will invoke the appropriate procedure for the
- % operand array.
- %
- .currentglobal true .setglobal
- userdict /.cspace_util 80 dict put
- .cspace_util begin
- %
- % Colorspacedict is initially in .cspace_util; it is copied to level2dict
- % in the Level 2 initialization code to retain compatibility with
- % earlier implementations.
- %
- /colorspacedict 20 dict def
- %
- % <obj> make_array1 <array>
- %
- % procedure for conditionally converting a named color space to a
- % 1-element array. Since names are always global, the array will be
- % as well.
- %
- /make_array1
- {
- dup type /nametype eq
- { currentglobal true setglobal exch 1 array astore exch setglobal }
- if
- }
- bind def
- %
- % <name|array> .get_cspace_type name
- %
- % Provide generic routine for retrieving the color space type.
- %
- /.get_cspace_type
- {
- dup type dup /arraytype eq exch /packedarraytype eq or
- { 0 get }
- if
- }
- bind def
- %
- % <name|array> .get_method_dict <dict>
- %
- % Get the method dictionary for a specific color space. Note that the
- % color space is left on the stack.
- %
- /.get_method_dict
- { //colorspacedict exch //.get_cspace_type exec get }
- bind def
- %
- % <name|array> <proc_name> .get_method <name|array> <proc | bool>
- %
- % Get the named method for the operand color space.
- %
- /.get_method
- { exch //.get_method_dict exec exch get }
- bind def
- %
- % <name_array> .cs_potential_indexed_base <bool>
- % <name_array> .cs_potential_pattern_base <bool>
- % <name_array> .cs_potential_alternate <bool>
- % <name_array> .cs_potential_icc_alternate <bool>
- % <name | array> .cs_get_ncomps <int>
- % <name | array> .cs_get_range <range_array>
- % <name | array> .cs_get_default_color <c1> ... <cn>
- % <c1> ... <cn> <name | array> .cs_get_currentgray <gray>
- % <c1> ... <cn> <name | array> .cs_get_currentrgb <r> <g> <b>
- % <c1> ... <cn> <name | array> .cs_get_currentcmyk <c> <m> <y> <k>
- % <name | array> .cs_validate <name | array>
- % <name1 | array1> .cs_substitute <name1 | array1> <array2>
- % <name1 | array1> <array2> .cs_prepare <name1 | array1> <array2>
- % <name | array> .cs_install -
- % <c1> ... <cn> <array> .cs_prepare_color <c1> ... <cn>
- % <array> .cs_complete_setcolor -
- %
- % These procedures provide access to the corresponding methods of the
- % operand color space.
- %
- /.cs_potential_indexed_base
- { /cs_potential_indexed_base //.get_method exec }
- bind def
- /.cs_potential_pattern_base
- { /cs_potential_pattern_base //.get_method exec }
- bind def
- /.cs_potential_alternate
- { /cs_potential_alternate //.get_method exec }
- bind def
- /.cs_potential_icc_alternate
- { /cs_potential_icc_alternate //.get_method exec }
- bind def
- /.cs_get_ncomps
- { dup /cs_get_ncomps //.get_method exec exec }
- bind def
- /.cs_get_range
- { dup /cs_get_range //.get_method exec exec }
- bind def
- /.cs_get_default_color
- { dup /cs_get_default_color //.get_method exec exec }
- bind def
- /.cs_get_currentgray
- { dup /cs_get_currentgray //.get_method exec exec }
- bind def
- /.cs_get_currentrgb
- { dup /cs_get_currentrgb //.get_method exec exec }
- bind def
- /.cs_get_currentcmyk
- { dup /cs_get_currentcmyk //.get_method exec exec }
- bind def
- /.cs_validate
- { dup /cs_validate //.get_method exec exec }
- bind def
- /.cs_substitute
- { dup /cs_substitute //.get_method exec exec }
- bind def
- /.cs_prepare
- { dup /cs_prepare //.get_method exec exec }
- bind def
- /.cs_install
- { dup /cs_install //.get_method exec exec }
- bind def
- /.cs_prepare_color
- { dup /cs_prepare_color //.get_method exec exec }
- bind def
- /.cs_complete_setcolor
- { dup /cs_complete_setcolor //.get_method exec exec }
- bind def
- %
- % Make sure we have an interpreter color space before redefining
- % setcolorspace. The interpreter internal code only sets the effective
- % color space; the interpreters color spaces begins as a null object.
- %
- % NB: This should come prior to the redefinition of setcolorspace, and
- % must use an array operand.
- %
- [ /DeviceGray ] setcolorspace
- %
- % <c1> ... <cn> setcolor -
- %
- % As with setcolorspace, setcolor is initially placed in .cspace_util,
- % and is copied to level2dict by the Level 2 initialization code. The
- % internal definition of setcolor is removed from systemdict as soon
- % as this procedure is defined.
- %
- /setcolor
- {
- {
- currentcolorspace //.cs_prepare_color exec //setcolor
- currentcolorspace //.cs_complete_setcolor exec
- }
- stopped
- { //.cspace_util /setcolor get $error /errorname get signalerror }
- if
- }
- bind odef
- systemdict /setcolor .undef
- %
- % <name|array> <bool> _setcolorspace -
- % <name|array> _setcolorspace_nosub -
- %
- % <name|array> setcolorspace -
- % <name|array> forcesetcolorspace -
- %
- % setcolorspace is initially placed in .cspace_util. It is copied to
- % level2dict by the Level 2 initialization code. The internal
- % setcolorspace operator is removed from systemdict as soon as this
- % procedure is defined.
- %
- % Because some jobs, in particular PDF jobs, repeatedly set the same
- % color space, this procedure will check if the operand and current
- % color spaces are the same. The check is absolute for parameterless
- % color spaces, conservative for others. For PostScript, this
- % optimization can only be employed if color space substitution is
- % disabled, as otherwise there is no way to account for possible changes
- % in the /Default* instances of the ColorSpace resource category. For PDF
- % jobs, resource category instances can only be changed at very specific
- % times (typically page boundaries), so the "operand color space is the
- % same as current color space" optimization may be used even if color
- % space substitution is in effect. The optimization is also highly
- % desirable in such cases, as it greatly improves performance.
- %
- % In certain situations, it is critical that a color space be set,
- % even if it is the same as the current color space. This is the case
- % when a CIEBased color space is used as a base or alternative color
- % space, due to some long-standing problems with the graphics libraries
- % handling of sampled information from the procedures in CIE color
- % spaces and the color rendering dictionary. The forcesetcolorspace
- % operator is provided for those situations.
- %
- % Note also that, if the current color space is not reset, at least
- % the current color must be reset to its default value.
- %
- % Another problem arises in the case of ICCBased color spaces. These
- % color spaces may be used to substitute for a DeviceGray/DeviceRGB/
- % DeviceCMYK color space, and may themselves require such a color
- % space as an alternate. Obviously, when this is the case the normal
- % setcolorspace mechanism would encounter and infinite loop if the
- % alternate colro space needed to be used. For this particular case,
- % the special _setcolorspace_nosub is provided, which suppresses
- % color space substitution. This routine does not bother to check if
- % the operand and current color space are the same.
- %
- /_setcolorspace
- {
- {
- % see if the operand space is the same as the current space
- currentcolorspace dup length 1 eq
- {
- 0 get
- 2 index dup type dup /arraytype eq exch /packedarraytype eq or
- {
- dup length 1 eq
- { 0 get }
- if
- }
- if
- }
- { 2 index }
- ifelse
- eq and dup
- {
- %
- % If PDFfile is defined on the dictionary stack, this is a
- % PDF job. No additional check is required in this case (see
- % comment above).
- %
- /PDFfile where
- { pop }
- { .getuseciecolor not and } % check that UseCIEColor is off
- ifelse
- }
- if
- { //.cs_get_default_color exec setcolor }
- {
- //.cs_validate exec
- //.cs_substitute exec
- //.cs_prepare exec
- //.cs_install exec
- //make_array1 exec //setcolorspace
- }
- ifelse
- }
- stopped
- { //.cspace_util /setcolorspace get $error /errorname get signalerror }
- if
- }
- bind def
- /_setcolorspace_nosub
- {
- {
- //.cs_validate exec
- dup
- //.cs_prepare exec
- //.cs_install exec
- //make_array1 exec //setcolorspace
- }
- stopped
- { //.cspace_util /setcolorspace get $error /errorname get signalerror }
- if
- }
- bind def
- /setcolorspace { //true //_setcolorspace exec } bind odef
- /forcesetcolorspace { //false //_setcolorspace exec } bind odef
- %
- % - initgraphics -
- %
- % The initgraphics operator must be redefined create a real color space.
- % Previously this was unnecessary, as .currentcolorspace could return
- % an integer.
- %
- %
- /initgraphics
- { initgraphics { /DeviceGray } cvlit forcesetcolorspace }
- .bind systemdict begin odef end
- systemdict /setcolorspace .undef
- %
- % <gray> setgray -
- %
- % <r> <g> <b> setrgbcolor -
- %
- % <c> <m> <y> <b> setcmykcolor -
- %
- % The Level 1 color setting operators. setcmykcolor is created only if
- % setcolorscreen is present. These operators are always defined in
- % systemdict.
- %
- /setgray
- {
- { { /DeviceGray } cvlit //setcolorspace //setcolor }
- stopped
- { /setgray load $error /errorname get signalerror }
- if
- }
- bind systemdict begin odef end
- /setrgbcolor
- {
- { { /DeviceRGB } cvlit //setcolorspace //setcolor }
- stopped
- { /setrgbcolor load $error /errorname get signalerror }
- if
- }
- bind systemdict begin odef end
- /setcolorscreen where
- {
- pop
- /setcmykcolor
- {
- { { /DeviceCMYK } cvlit //setcolorspace //setcolor }
- stopped
- { /setcmykcolor load $error /errorname get signalerror }
- if
- }
- bind systemdict begin odef end
- }
- if
- %
- % - currentgray <gray>
- %
- % - currentrgbcolor <r> <g> <b>
- %
- % - currentcmykcolor <c> <m> <y> <k>
- %
- % Return the current color, mapped to a DeviceGray, DeviceRGB, or
- % DeviceCMYK color space. The latter is only created if setcolorscreen
- % is present.
- /currentgray
- { currentcolor currentcolorspace //.cs_get_currentgray exec }
- bind systemdict begin odef end
- /currentrgbcolor
- { currentcolor currentcolorspace //.cs_get_currentrgb exec }
- bind systemdict begin odef end
- /setcolorscreen where
- {
- pop
- /currentcmykcolor
- { currentcolor currentcolorspace //.cs_get_currentcmyk exec }
- bind systemdict begin odef end
- }
- if
- %
- % Add some generically useful structures and procedures to .cspace_util.
- %
- %
- % Some common errors. The command for these errors will normally be
- % overwritten by the invoking operator. We cannot "load" the secolorspace
- % or setcolor operators, as they are not present in Level 1 systems.
- %
- /setcspace_typecheck
- { /setcolorspace cvx /typecheck signalerror }
- bind def
- /setcspace_rangecheck
- { /setcolorspace cvx /rangecheck signalerror }
- bind def
- /setcspace_invalidaccess
- { /setcolorspace cvx /invalidaccess signalerror }
- bind def
- /setcspace_undefined
- { /setcolorspace cvx /undefined signalerror }
- bind def
- /setcolor_typecheck
- { /setcolor cvx /typecheck signalerror }
- bind def
- /setcolor_invalidaccess
- { /setcolor cvx /invalidaccess signalerror }
- bind def
- %
- % <obj> check_array <obj>
- %
- % Check that an object is an array. Currently we don't check for
- % readability, as a failing get or length operator should generate
- % the appropriate invalidaccess error.
- /check_array
- {
- dup type dup /arraytype ne exch /packedarraytype ne and
- { /setcolorspace cvx /typecheck signalerror }
- if
- }
- bind def
- % pre-defined procedures for cs_ncomps and cs_get_range
- /ncomps_1 { pop 1 } bind def
- /ncomps_3 { pop 3 } bind def
- /ncomps_4 { pop 4 } bind def
- /dflt_range_4 [ 0 1 0 1 0 1 0 1 ] readonly def
- /dflt_range_3 dflt_range_4 0 6 getinterval def
- /dflt_range_1 dflt_range_4 0 2 getinterval def
- % <obj> get_range_[1|3|4] <range>
- /get_range_1 { pop //dflt_range_1 } bind def
- /get_range_3 { pop //dflt_range_3 } bind def
- /get_range_4 { pop //dflt_range_4 } bind def
- %
- % <c1> ... <cn> <name | array> <n>
- % check_num_stack
- % <c1> ... <cn> <array | array>
- %
- % <c1> <array> validate_color_1 <c1>
- % <c1> <c2> <c3> <arraY> validate_color_3 <c1> <c2> <c3>
- % <c1> <c2> <c3> <c4> <arraY> validate_color_4 <c1> <c2> <c3> <c4>
- %
- % check_num_stack verifies that the stack consists of a color space array and
- % n numbers. This is used by most of the cs_prepare_color procedures. The
- % validate_color_[1|3|4] procedures can be used as the cs_prepare_color
- % procedure for Device specific, CIEBased, and Indexed color spaces.
- %
- % Note that the pseudo-operator that (indirectly) invokes this routine will
- % handle resetting the stacks.
- %
- /check_num_stack
- {
- dup 2 add copy exch pop
- {
- type dup /integertype ne exch /realtype ne and
- //setcolor_typecheck
- if
- }
- repeat
- pop % remove the extra op_count
- }
- bind def
- % <c1> <array> validate_1 <c1>
- /validate_1 { 1 //check_num_stack exec pop } bind def
- % <c1> <c2> <c3> <array> validate_3 <c1> <c2> <c3>
- /validate_3 { 3 //check_num_stack exec pop } bind def
- % <c1> <c2> <c3> <c4> <array> validate_4 <c1> <c2> <c3> <c4>
- /validate_4 { 4 //check_num_stack exec pop } bind def
- %
- % <obj> pop_1 -
- %
- % This is a procedure form of pop. It may be used where a procedure is
- % expected, but the function of the procedure is the same as the pop
- % operator.
- /pop_1 { pop } bind def
- %
- % <obj> dup_1 <obj> <obj>
- %
- % An analog to pop_1, this one for dup.
- %
- /dup_1 { dup } bind def
- %
- % <obj1> ... <objn> <n> clear_n_objs -
- %
- % Clear n objects from the operand stack.
- %
- /clear_n_objs { //pop_1 repeat } bind def
- %
- % <obj1> ... <objn> <array> clear_setcolor_operands -
- %
- % Clear the setcolor operands for a color space.
- %
- /clear_setcolor_operands
- { //.cs_get_ncomps exec //clear_n_objs exec }
- bind def
- %
- % Return 1, 3, or 4 zeros. These routines are used primarily for the
- % CIEBased color spaces, for which currentgray and currentrgb
- % should return 0 for all components, and currentcmyk should return
- % 0 0 0 1.0 (this varies from Adobe's documentation but is consistent
- % with their impelementations).
- %
- /no_currentgray { //.cs_get_ncomps exec //clear_n_objs exec 0 } bind def
- /no_currentrgb { //.cs_get_ncomps exec //clear_n_objs exec 0 0 0 } bind def
- /no_currentcmyk { //.cs_get_ncomps exec //clear_n_objs exec 0 0 0 1.0 } bind def
- %
- % <num> bound_0_1 <num>
- %
- % Bound a number to the range [0, 1]
- %
- /bound_0_1
- {
- dup 0 lt
- { pop 0 }
- {
- dup 1 gt
- { pop 1 }
- if
- }
- ifelse
- }
- bind def
- %
- % Provide pseudo-operators for sethsbcolor and currenthsbcolor. These are
- % alternate versions of the setrgbcolor and currentrgbcolor operators, which
- % make use of a hue/staturation/brightness color description.
- %
- %
- % <num_1> ... <num_n> n max_n <num>
- % <num_1> ... <num_n> n min_n <num>
- %
- % Find the maximum and minum of 3 color component intensities.
- %
- /max_n
- {
- 1 sub
- { 2 copy lt { exch } if pop }
- repeat
- }
- bind def
- /min_n
- {
- 1 sub
- { 2 copy gt { exch } if pop }
- repeat
- }
- bind def
- %
- % <r> <g> <b> .rgb_2_hsb <h> <s> <br>
- % <h> <s> <br> .hsb_2_rgb <r> <g> <b>
- %
- % Convert between RGB and HSB colors, using the hexcone approach (see
- % Rogers, David, "Procedureal Elements For Computer Graphics",
- % (McGraw-Hill, 1985), pp. 402 - 3).
- %
- % The rgb ==> hsb calculation is:
- %
- % br = max(r, g, b)
- %
- % if (br == 0)
- % h = 0, s = 0;
- % else {
- % v = min(r, g, b)
- % diff = br - v;
- % sat = diff / br;
- % if (r == br)
- % h = (g - b) / (6 * diff) + (b > g ? 1 : 0);
- % else if (g == br)
- % h = 1/3 + (b - r) / (6 * diff);
- % else /* b == br */
- % h = 2/3 + (r - g) / (6 * diff);
- % }
- %
- % The hsb ==> rgb conversion is:
- %
- % mn = (1 - s) * br, md = 6 * s * br;
- %
- % switch ((int)floor(6 * h)) {
- % case 0: /* r >= g >= b */
- % r = br;
- % g = mn + h * md;
- % b = mn;
- % break;
- %
- % case 1: /* g >= r >= b */
- % r = mn + md * (1/3 - h);
- % g = br;
- % b = mn;
- % break;
- %
- % case 2: /* g >= b >= r */
- % r = mn;
- % g = br;
- % b = mn + (h - 1/3) * md;
- % break;
- %
- % case 3: /* b >= g >= r */
- % r = mn;
- % g = mn + (2/3 - h) * md;
- % b = br;
- % break;
- %
- % case 4: /* b >= r >= g */
- % r = mn + (h - 2/3) * md;
- % g = mn;
- % b = br;
- % break;
- %
- % case 5: /* r >= b >= g */
- % r = br;
- % g = mn;
- % b = mn + (1 - h) * md;
- % break;
- %
- % case 6: /* We have wrapped around the hexcone. Thus this case is
- % the same as case 0 with h = 0 */
- % h = 0;
- % r = br;
- % g = mn + h * md = mn;
- % b = mn;
- % break;
- % }
- %
- /.rgb_2_hsb
- {
- % find the largest and smallest components
- 3 copy 3 //max_n exec dup 5 1 roll
- dup 0 eq
- { pop pop pop pop 0 0 }
- {
- 4 copy pop 3 //min_n exec 1 index exch sub
- dup 2 index div 7 1 roll
- dup 0 eq
- { 5 { pop } repeat 0 3 1 roll }
- {
- 6 mul 5 1 roll
- 2 copy eq % blue == brightness
- { pop pop sub exch div .666667 add }
- {
- 2 index eq % green == brightness
- { exch pop exch sub exch div .3333333 add }
- {
- % red == brightness
- sub exch pop exch div
- dup 0 lt
- { 1 add }
- if
- }
- ifelse
- }
- ifelse
- 3 1 roll
- }
- ifelse
- }
- ifelse
- }
- bind def
- /.hsb_2_rgb
- {
- 3 { 0 max 1 min 3 1 roll } repeat
- 1 2 index sub 1 index mul % (1 - s) * br
- 3 -1 roll 2 index mul 6 mul % 6 * s * br
- 4 -1 roll % stack: <br> <(1 - s) * br> <6 * s * br> <h>
- % array of procedures for the 7 hue cases
- {
- % 0 ==> r >= g >= b
- { mul 1 index add exch }
- % 1 ==> g >= r >= b
- { 0.333333 exch sub mul 1 index add 3 1 roll }
- % 2 ==> g >= b >= r
- { 0.333333 sub mul 1 index add 3 1 roll exch 3 -1 roll }
- % 3 ==> b >= g >= r
- { 0.666667 exch sub mul 1 index add 3 -1 roll }
- % 4 ==> b >= r >= g
- { 0.666667 sub mul 1 index add 3 1 roll exch }
- % 5 ==> r >= b >= g
- { 1 exch sub mul 1 index add }
- % 6 ==> r = br, g = b = mn
- % Case 6 is the same as case 0 with h = 0. This also simplifies
- % the calculations.
- { pop pop dup }
- }
- 1 index 6 mul cvi % (int)(6 * h)
- get exec
- }
- bind def
- %
- % <hue> <saturation> <brightness sethsbcolor -
- %
- % - currenthsbcolor <hue> <saturation> <brightness>
- %
- /sethsbcolor
- {
- { //.hsb_2_rgb exec setrgbcolor }
- stopped
- { /sethsbcolor load $error /errorname get signalerror }
- if
- }
- bind systemdict begin odef end
- /currenthsbcolor
- {
- { currentrgbcolor //.rgb_2_hsb exec }
- stopped
- { /currenthsbcolor load $error /errorname get signalerror }
- if
- }
- bind systemdict begin odef end
- end % .cspace_util
- .setglobal
|