Shfill
Shfill
%----------------------------------------------------------------------------
% Proc: output_mesh
% Stack: colorspace datasource output_mesh -
% Desc: outputs mesh fill on Level3 device using Coons patch shading dictionary
%----------------------------------------------------------------------------
/output_mesh
{
% create shading dictionary
10 dict
begin
/ShadingType 6 def
/ColorSpace ShadingColorSpace set_shading_colorspace def
/DataSource ShadingDataSource def
currentdict
end
shfill
} bd
%----------------------------------------------------------------------------
% Proc: set_shading_colorspace
% Stack: colorspace set_shading_colorspace -
% Desc: sets shading colorspace according to global separation settings
%----------------------------------------------------------------------------
/set_shading_colorspace
{
SeparationMode /OnHost eq
{
pop
SeparateInColor
{
DocCmykSpace
}
{
DocGrayScaleSpace
} ifelse
} if
} bd
%----------------------------------------------------------------------------
% Proc: set_shading_color
% Stack: colorspec set_shading_color colorants
% colorspec - colorspec for shading vertex color
% colorants - colorant values for shading vertex
% Desc: sets shading vertex color in format compatible with shading dictionary
%----------------------------------------------------------------------------
/set_shading_color
{
SeparationMode /OnHost eq
{
/separate_color dexec
{
% there is separation, get colorant values
begin
color aload pop
end
}
{
% no separation, leave CMYK( 0 0 0 0) or Gray(1) on stack
pop
SeparateInColor
{
0 0 0 0
}
{
1
} ifelse
} ifelse
}
{
begin
color aload pop
end
} ifelse
} bd
%----------------------------------------------------------------------------
% Proc: set_linear_gradient_parameters
% Stack: - set_radial_gradient_parameters
% Desc: performs linear-fill calculations
%----------------------------------------------------------------------------
/set_linear_gradient_parameters
{
flattenpath % necessary for proper coords
pathbbox % get rotation-adjusted bbox
$x1 $pdw sub /$x1 xd % recalc x's and y's for padding -
sub from the right
$x0 $pdw add /$x0 xd % , and add to the left
/Coords [$x1 $y1 $x0 $y0] % set the coords for this fill
} def
%----------------------------------------------------------------------------
% Proc: set_radial_square_gradient_parameters
% Stack: - set_radial_square_gradient_parameters
% Desc: performs radial-fill or square-fill calculations
%----------------------------------------------------------------------------
/set_radial_square_gradient_parameters
{
flattenpath % necessary for proper coords
pathbbox % get rotation-adjusted bbox
/$y1 xd
/$x1 xd % lower left: (x0, y0)
/$y0 xd % upper right: (x1, y1)
/$x0 xd
1 $pad 2 mul sub mul % factor the padding into the radius
/$rad0 xd % rad0 is outer radius
} def
%----------------------------------------------------------------------------
% Proc: set_radial_gradient_parameters
% Stack: - set_radial_gradient_parameters
% Desc: performs radial-fill calculations
%----------------------------------------------------------------------------
/set_radial_gradient_parameters
{
% calculate dimensions and radii
set_radial_square_gradient_parameters
% set the coords for this fill
/Coords [$x0 $y0 $rad0 $x1 $y1 $rad1]
} def
%----------------------------------------------------------------------------
% Proc: set_square_gradient_parameters
% Stack: - set_square_gradient_parameters
% Desc: performs square-fill calculations
%----------------------------------------------------------------------------
/set_square_gradient_parameters
{
% calculate dimensions and radii
set_radial_square_gradient_parameters
% our calculations produce fills that match the older model in output, but do
not
% match the screen display.
% This is an approximate adjustment factor to make the output more screen-
like
% $rad0 0.77 mul /$rad0 xd
} def
%----------------------------------------------------------------------------
% Proc: create_gradient_shading_dict
% Stack: - create_gradient_shading_dict -
% Desc: creates Level3 shading dictionary for gradient fill
%----------------------------------------------------------------------------
/create_gradient_shading_dict
{
<<
/ShadingType $fty 2 add % shading type 2 -
linear, 3 -radial, 4 square ( free-form Gouraud-shaded triangle meshes )
/Domain [0 1]
$fty 0 eq
% set up parametrs for the fill
{
set_linear_gradient_parameters
}
{
$fty 1 eq
{
set_radial_gradient_parameters
}
{
$fty 3 eq
{
set_square_gradient_parameters
}if
}ifelse
}ifelse
/Function
% set up shading funciton
<<
/FunctionType 3
/Domain [0 1]
/Functions
% set up stitching functions
[
/dMidPointPS
% calculate midpoint
0.5 log $fmp 100 div log div
def
1 1 $fsc 1 sub
{
/nColor exch def
% store color index
<<
/FunctionType 2
/Domain [0 1]
/N dMidPointPS
/C0
% set gradient band starting color
[ $fsa nColor 1 sub 2 mul get % get color value
from gradient parameters
set_shading_color ]
/C1
% set gradient band ending color
[ $fsa nColor 2 mul get % get
color value from gradient parameters
set_shading_color ]
>>
}for
]
/Encode [ $fsc 1 sub {0 1} repeat ] % create encoding array
/Bounds
% create stitch bounds array
[
$fsc 2 gt
{
1 1 $fsc 2 sub
{
/nColor exch def
% store color index
/nBandPos 0 def
% position of the color band ( from 0.0 to 1.0 )
0 1 nColor
{
dup
nColor le
{
$fsa exch 2 mul
1 add get nBandPos add % $fsa
contains a pair of color and width ( in steps ) for each color band
/nBandPos exch def
% add all steps to calculate step position of current band
}if
}for
nBandPos $fst div
% normalize band position to 1.0 and leave on stack
}for
}if
]
>>
$pad 0 gt
{
/Extend [true true]
}
{
/Extend [false false]
}ifelse
>>
}bd
%----------------------------------------------------------------------------
% Proc: output_shading_gradient
% Stack: - output_shading_gradient -
% Desc: outputs gradient using shading dictionary
%----------------------------------------------------------------------------
/output_shading_gradient
{
$ctm setmatrix wclip
@gs % save
graphics state, path will be consumed by F (fill) function, will need to restore it
$fty 3 eq $pad 0 gt and % if square fill and pad is non-zero, have to
fill object with start gradient color
{
% can not do padding by means of shading dictionary for square fills (can for
radial and axial ones )
$fsa 0 get % get first gradient color
set_solid_fill % set fill color
F
}if
@gr %
restore path by restoring graphics state
FillOverprint safe_setoverprint
shfill
% do actual output of a gradient fill
} bd