% Copyright (C) 2001, 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_icc.ps,v 1.10 2003/07/14 19:32:17 ray Exp $
% ICCBased color space method dictionaries.
% This assumes gs_ciecs2.ps has already been processed.
%
% Note that the substitution procedure in this routine will dynamically
% check for support of ICCBased color space. If such support is not
% provided, the alternative color space will be used.
%
% The validation routine in dictionary (cs_validate) performs a more
% extensive validation than is done for other color spaces, because
% .seticcspace does less checking than most other color space setting
% operators.
%
.currentglobal true .setglobal
.cspace_util begin
%
% A dictionary for mapping the number of components of an ICCBased color
% space to the appropriate alternative color space. This is used only
% if an alternative color space is not specifically provided.
%
/icc_comp_map_dict
mark 1 /DeviceGray 3 /DeviceRGB 4 /DeviceCMYK .dicttomark
def
%
% <array1> get_icc_alternative_space <name | array2>
%
% Get the alternative color space for an ICCBased color space.
%
/get_icc_alternative_space
{
1 get dup /Alternate .knownget
{ exch pop }
{ /N get //icc_comp_map_dict exch get }
ifelse
}
bind def
colorspacedict
/ICCBased
mark
/cs_potential_indexed_base true
/cs_potential_pattern_base true
/cs_potential_alternate true
/cs_potential_icc_alternate false
/cs_get_ncomps { 1 get /N get } bind
/cs_get_range
{
1 get dup /Range .knownget
{ exch pop }
{ /N get 2 mul //dflt_range_4 exch 0 exch getinterval }
ifelse
}
bind
/cs_get_default_color { 1 get /N get { 0 } repeat } bind
%
% For generating a gray, RGB, or CMYK equivalent color, we will
% assume that the alternative color space provides reasonable
% mapping.
/cs_get_currentgray
{ //get_icc_alternative_space exec //.cs_get_currentgray exec }
bind
/cs_get_currentrgb
{ //get_icc_alternative_space exec //.cs_get_currentrgb exec }
bind
/cs_get_currentcmyk
{ //get_icc_alternative_space exec //.cs_get_currentcmyk exec }
bind
% a lot of validation is done by the cs_validate method
/cs_validate
{
//check_cie_cspace exec
dup 1 get
dup /N get
dup type /integertype ne
//setcspace_typecheck
if
//icc_comp_map_dict exch known not
//setcspace_rangecheck
if
dup /DataSource get
dup type dup /stringtype ne exch /filetype ne and
//setcspace_typecheck
if
rcheck not
//setcspace_invalidaccess
if
dup /Range .knownget
{
//check_array exec
{
type dup /integertype ne exch /realtype ne and
//setcspace_typecheck
if
}
forall
}
if
/Alternate .knownget
{
//.cs_validate exec
//.cs_potential_icc_alternate exec not
//setcspace_rangecheck
if
}
if
}
bind
% substitute the Alternate space, if appropriate
/cs_substitute
{
%
% A design problem in the Ghostscript graphic library color
% space code prevents an ICCBased color space from having an
% ICCBased alternative color space. This situation actually
% arises fairly frequently in PDF, as an ICCBased color space
% is used as the substitute color for a Device{Gray|RGB|CMYK}
% color space, which in turn are used as the alternative color
% space to another (or possibly even the same) ICCBased color
% space.
%
% This situation causes no fundamental problems, as
% Ghostscript nominally supports ICCBased color spaces, so the
% Alternate color space is not used. Where this is not true
% (primarily because the NOCIE option is selected), the code
% would (except for the design flaw noted above) select the
% Alternate of the Alternate color space.
%
% The code below works around this problem by suprressing
% color space substitution for alternative color spaces if
% the substituting space is an ICCBased color space.
%
dup //get_icc_alternative_space exec
//.cs_substitute exec
2 copy eq
1 index //.cs_potential_icc_alternate exec not
or
{ pop pop dup }
{
% retain just the new Alternate space
exch pop
% build all new structures in local VM
.currentglobal 3 1 roll //false .setglobal
% copy the original ICCBased color space array
1 index dup length array copy
% copy the ICCBased dictionary
dup 1 2 copy get dup length dict copy
% insert the new alterante color space
dup /Alternate 7 -1 roll put
% insert the new dictionary into the arra
put
% restore the VM mode
3 -1 roll .setglobal
}
ifelse
}
bind
%
% The current implementation of ICCBased color spaces requires the
% DataSource to be a file.
%
/cs_prepare
{
% make DataSource a file
dup 1 get /DataSource get type /stringtype eq
{
% build all new structures in local VM
.currentglobal exch //false .setglobal
% check if we need to copy the color space and dictionary
2 copy eq
{
dup length array copy
dup 1 2 copy get dup length dict copy put
}
if
% fetch DataSource, setting up stack for multiple puts
dup 1 2 copy get dup /DataSource 2 copy get
% convert the string into a file
/ReusableStreamDecode filter
% put the file into the dictioary, the dictionary into the array
put put
% restore the VM mode
exch .setglobal
}
if
}
bind
%
% Install the current color space.
%
% The current Ghostscript color space implementation requires that
% color spaces that provide a base or alternative color space set
% that base/alternative color space to be the current color space
% before attempting to set the original color space. This can cause
% difficulty if an ICCBased color space is being used as a substitute
% color space for a device-specific color space, and uses that same
% device-specific color space as an alternative space. For this
% reason, a special _setcolorspace_nosub operator is provided.
%
/cs_install
{
% set the alternative color space to be the current color space
dup //get_icc_alternative_space exec //_setcolorspace_nosub exec
% check for native support
/.seticcspace where
{ pop //false }
{ //true }
ifelse
NOCIE or
//pop_1 % do nothing
{
% Acrobat Reader silently ignores errors with ICC profiles
% and uses the alternate color space -- do the same.
mark exch 1 get
{ .seticcspace }
.internalstopped
cleartomark
}
ifelse
}
bind
% for now, the alternative spaces for an ICCBased color space do
% not require special preparation
/cs_prepare_color { dup 1 get /N get //check_num_stack exec pop } bind
/cs_complete_setcolor //pop_1
.dicttomark
put
end % .cspace_util
NOPSICC { (%END PSICC) .skipeof } if
% Now set up ICC profile loading for PostScript %%BeginICCProfile sections.
systemdict begin
/.ProcessICCcomment { % file comment -- file comment
dup
(%%BeginICCProfile) anchorsearch {
pop pop
DEBUG { (.ProcessICCcomment found %%BeginICCProfile) print flush } if
% load an ICC profile defined as comments (hex encoded).
% Ends with %%End at the start of a line. Read the data into
% a bytestring to allow seeking. This string can be used as a
% seekable ReusableStreamDecode filter source by the ICC logic.
%
% Since .bigstring needs to know the size, we first read an array of
% strings each 64000 max length.
%
% stack: --file-- (%%BeginICCProfile: ...)
1 index 0 (%%EndICCProfile) /SubFileDecode filter
[ { counttomark 1 add index
64000 string readhexstring
not { exit } if
} loop
] exch closefile
0 1 index { length add } forall
.bigstring
exch 0 exch {
% stack: --file-- (%%BeginICCProfile: ...) --bytestring-- cur_index --string--
2 copy length add % calculate next string start point
3 1 roll 3 index 3 1 roll putinterval
} forall
pop % discard length of bytestring
% make a seekable -file- out of the bytestring
mark /AsyncRead true .dicttomark /ReusableStreamDecode filter
% stack: --file-- (%%BeginICCProfile: ...) --icc_subfile--
/DeviceCMYK setcolorspace
<< /DataSource 3 -1 roll
/N 4 % Try CMYK first
>> { .seticcspace } stopped {
/DeviceRGB setcolorspace
dup /N 3 put { .seticcspace } stopped {
/DeviceGray setcolorspace
dup /N 1 put { .seticcspace } stopped { % last choice
QUIET not { ( *** Unable to load ICC profile from PostScript DSC comments ***) = flush } if
pop
} if
} if
} if
} {
pop % Not interested in this DSC comment
} ifelse
} bind def
% Merge ProcessICCcomment with existing handler
/.ProcessICCcomment load /exec load
currentuserparams /ProcessDSCComment get
dup null eq {pop {pop pop}} if /exec load
4 array astore cvx readonly
<< /ProcessDSCComment 3 -1 roll >> setuserparams
end % systemdict
%END PSICC
.setglobal
|