xref: /plan9/sys/src/cmd/gs/src/gsequivc.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
1*593dc095SDavid du Colombier /* Copyright (C) 2004 Artifex Software Inc., artofcode LLC.  All rights reserved.
2*593dc095SDavid du Colombier 
3*593dc095SDavid du Colombier   This software is provided AS-IS with no warranty, either express or
4*593dc095SDavid du Colombier   implied.
5*593dc095SDavid du Colombier 
6*593dc095SDavid du Colombier   This software is distributed under license and may not be copied,
7*593dc095SDavid du Colombier   modified or distributed except as expressly authorized under the terms
8*593dc095SDavid du Colombier   of the license contained in the file LICENSE in this distribution.
9*593dc095SDavid du Colombier 
10*593dc095SDavid du Colombier   For more information about licensing, please refer to
11*593dc095SDavid du Colombier   http://www.ghostscript.com/licensing/. For information on
12*593dc095SDavid du Colombier   commercial licensing, go to http://www.artifex.com/licensing/ or
13*593dc095SDavid du Colombier   contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14*593dc095SDavid du Colombier   San Rafael, CA  94903, U.S.A., +1(415)492-9861.
15*593dc095SDavid du Colombier */
16*593dc095SDavid du Colombier 
17*593dc095SDavid du Colombier /*$Id: gsequivc.c,v 1.6 2005/07/08 22:04:31 dan Exp $ */
18*593dc095SDavid du Colombier /* Routines for determining equivalent color for spot colors */
19*593dc095SDavid du Colombier 
20*593dc095SDavid du Colombier #include "math_.h"
21*593dc095SDavid du Colombier #include "gdevprn.h"
22*593dc095SDavid du Colombier #include "gsparam.h"
23*593dc095SDavid du Colombier #include "gstypes.h"
24*593dc095SDavid du Colombier #include "gxdcconv.h"
25*593dc095SDavid du Colombier #include "gdevdevn.h"
26*593dc095SDavid du Colombier #include "gsequivc.h"
27*593dc095SDavid du Colombier #include "gzstate.h"
28*593dc095SDavid du Colombier #include "gsstate.h"
29*593dc095SDavid du Colombier #include "gscspace.h"
30*593dc095SDavid du Colombier #include "gxcspace.h"
31*593dc095SDavid du Colombier 
32*593dc095SDavid du Colombier /*
33*593dc095SDavid du Colombier  * These routines are part of the logic for determining an equivalent
34*593dc095SDavid du Colombier  * process color model color for a spot color.  The definition of a
35*593dc095SDavid du Colombier  * Separation or DeviceN color space include a tint transform function.
36*593dc095SDavid du Colombier  * This tint transform function is used if the specified spot or separation
37*593dc095SDavid du Colombier  * colorant is not present.  We want to be able to display the spot colors
38*593dc095SDavid du Colombier  * on our RGB or CMYK display.  We are using the tint transform function
39*593dc095SDavid du Colombier  * to determine a CMYK equivalent to the spot color.  Current only CMYK
40*593dc095SDavid du Colombier  * equivalent colors are supported.  This is because the CMYK is the only
41*593dc095SDavid du Colombier  * standard subtractive color space.
42*593dc095SDavid du Colombier  *
43*593dc095SDavid du Colombier  * This process consists of the following steps:
44*593dc095SDavid du Colombier  *
45*593dc095SDavid du Colombier  * 1.  Whenever new spot colors are found, set status flags indicating
46*593dc095SDavid du Colombier  * that we have one or more spot colors for which we need to determine an
47*593dc095SDavid du Colombier  * equivalent color.  New spot colors can either be explicitly specified by
48*593dc095SDavid du Colombier  * the SeparationColorNames device parameter or they may be detected by the
49*593dc095SDavid du Colombier  * device's get_color_comp_index routine.
50*593dc095SDavid du Colombier  *
51*593dc095SDavid du Colombier  * 2.  Whenever a Separation or DeviceN color space is installed, the
52*593dc095SDavid du Colombier  * update_spot_equivalent_colors device proc is called.  This allows the
53*593dc095SDavid du Colombier  * device to check if the color space contains a spot color for which the
54*593dc095SDavid du Colombier  * device does not know the equivalent CMYK color.  The routine
55*593dc095SDavid du Colombier  * update_spot_equivalent_cmyk_colors is provided for this task (and the
56*593dc095SDavid du Colombier  * next item).
57*593dc095SDavid du Colombier  *
58*593dc095SDavid du Colombier  * 3.  For each spot color for which an equivalent color is not known, we
59*593dc095SDavid du Colombier  * do the following:
60*593dc095SDavid du Colombier  *   a.  Create a copy of the color space and change the copy so that it
61*593dc095SDavid du Colombier  *       uses its alternate colorspace.
62*593dc095SDavid du Colombier  *   b.  Create a copy of the current imager state and modify its color
63*593dc095SDavid du Colombier  *       mapping (cmap) procs to use a special set of 'capture' procs.
64*593dc095SDavid du Colombier  *   c.  Based upon the type of color space (Separation or DeviceN) create
65*593dc095SDavid du Colombier  *       a 'color' which consists of the desired spot color set to 100% and
66*593dc095SDavid du Colombier  *       and other components set to zero.
67*593dc095SDavid du Colombier  *   d.  Call the remap_color routine using our modified color space and
68*593dc095SDavid du Colombier  *       state structures.  Since we have forced the use of the alternate
69*593dc095SDavid du Colombier  *       color space, we will eventually execute one of the 'capture' color
70*593dc095SDavid du Colombier  *       space mapping procs.  This will give us either a gray, RGB, or
71*593dc095SDavid du Colombier  *       CMYK color which is equivalent to the original spot color.  If the
72*593dc095SDavid du Colombier  *       color is gray or RGB we convert it to CMYK.
73*593dc095SDavid du Colombier  *   e.  Save the equivalent CMYK color in the device structure.
74*593dc095SDavid du Colombier  *
75*593dc095SDavid du Colombier  * 4.  When a page is to be displayed or a file created, the saved equivalent
76*593dc095SDavid du Colombier  * color is used as desired.  It can be written into the output file.  It
77*593dc095SDavid du Colombier  * may also be used to provide color values which can be combined with the
78*593dc095SDavid du Colombier  * process color model components for a pixel, to correctly display spot
79*593dc095SDavid du Colombier  * colors on a monitor.  (Note:  Overprinting effects with spot colors are
80*593dc095SDavid du Colombier  * not correctly displayed on an RGB monitor if the device simply uses an RGB
81*593dc095SDavid du Colombier  * process color model.  Instead it is necessary to use a subtractive process
82*593dc095SDavid du Colombier  * color model and save both process color and spot color data and then
83*593dc095SDavid du Colombier  * convert the overall result to RGB for display.)
84*593dc095SDavid du Colombier  *
85*593dc095SDavid du Colombier  * For this process to work properly, the following changes need to made to
86*593dc095SDavid du Colombier  * the device.
87*593dc095SDavid du Colombier  *
88*593dc095SDavid du Colombier  * 1.  The device source module needs to include gsequivc.c for a definition
89*593dc095SDavid du Colombier  *     of the relevant structures and routines.  An equivalent_cmyk_color_params
90*593dc095SDavid du Colombier  *     structure needs to be added to the device's structure definition and
91*593dc095SDavid du Colombier  *     it needs to be initialized.  For examples see the definition of the
92*593dc095SDavid du Colombier  *     psd_device structure in src/gdevpsd.c and the definitions of the
93*593dc095SDavid du Colombier  *     gs_psdrgb_device and gs_psdcmyk_devices devices in the same module.
94*593dc095SDavid du Colombier  * 2.  Logic needs to be added to the device's get_color_comp_index and
95*593dc095SDavid du Colombier  *     put_param routines to check if any separations have been added to the
96*593dc095SDavid du Colombier  *     device.  For examples see code fragments in psd_get_color_comp_index and
97*593dc095SDavid du Colombier  *     psd_put_params in src/gdevpsd.c.
98*593dc095SDavid du Colombier  * 3.  The device needs to have its own version of the
99*593dc095SDavid du Colombier  *     update_spot_equivalent_colors routine.  For examples see the definition
100*593dc095SDavid du Colombier  *     of the device_procs macro and the psd_update_spot_equivalent_colors
101*593dc095SDavid du Colombier  *     routine in src/gdevpsd.c.
102*593dc095SDavid du Colombier  * 4.  The device then uses the saved equivalent color values when its output
103*593dc095SDavid du Colombier  *     is created.  For example see the psd_write_header routine in
104*593dc095SDavid du Colombier  *     src/gdevpsd.c.
105*593dc095SDavid du Colombier  */
106*593dc095SDavid du Colombier 
107*593dc095SDavid du Colombier /* Function protypes */
108*593dc095SDavid du Colombier private void capture_spot_equivalent_cmyk_colors(gx_device * pdev,
109*593dc095SDavid du Colombier 		    const gs_state * pgs, const gs_client_color * pcc,
110*593dc095SDavid du Colombier 		    const gs_color_space * pcs, int sep_num,
111*593dc095SDavid du Colombier 		    equivalent_cmyk_color_params * pparams);
112*593dc095SDavid du Colombier 
113*593dc095SDavid du Colombier #define compare_color_names(name, name_size, str, str_size) \
114*593dc095SDavid du Colombier     (name_size == str_size && \
115*593dc095SDavid du Colombier 	(strncmp((const char *)name, (const char *)str, name_size) == 0))
116*593dc095SDavid du Colombier 
117*593dc095SDavid du Colombier private void
update_Separation_spot_equivalent_cmyk_colors(gx_device * pdev,const gs_state * pgs,const gs_color_space * pcs,gs_devn_params * pdevn_params,equivalent_cmyk_color_params * pparams)118*593dc095SDavid du Colombier update_Separation_spot_equivalent_cmyk_colors(gx_device * pdev,
119*593dc095SDavid du Colombier 		    const gs_state * pgs, const gs_color_space * pcs,
120*593dc095SDavid du Colombier 		    gs_devn_params * pdevn_params,
121*593dc095SDavid du Colombier 		    equivalent_cmyk_color_params * pparams)
122*593dc095SDavid du Colombier {
123*593dc095SDavid du Colombier     int i;
124*593dc095SDavid du Colombier 
125*593dc095SDavid du Colombier     /*
126*593dc095SDavid du Colombier      * Check if the color space's separation name matches any of the
127*593dc095SDavid du Colombier      * separations for which we need an equivalent CMYK color.
128*593dc095SDavid du Colombier      */
129*593dc095SDavid du Colombier     for (i = 0; i < pdevn_params->separations.num_separations; i++) {
130*593dc095SDavid du Colombier 	if (pparams->color[i].color_info_valid == false) {
131*593dc095SDavid du Colombier 	    const devn_separation_name * dev_sep_name =
132*593dc095SDavid du Colombier 			    &(pdevn_params->separations.names[i]);
133*593dc095SDavid du Colombier 	    unsigned int cs_sep_name_size;
134*593dc095SDavid du Colombier 	    unsigned char * pcs_sep_name;
135*593dc095SDavid du Colombier 
136*593dc095SDavid du Colombier 	    pcs->params.separation.get_colorname_string
137*593dc095SDavid du Colombier 		(pdev->memory, pcs->params.separation.sep_name, &pcs_sep_name,
138*593dc095SDavid du Colombier 		 &cs_sep_name_size);
139*593dc095SDavid du Colombier 	    if (compare_color_names(dev_sep_name->data, dev_sep_name->size,
140*593dc095SDavid du Colombier 			    pcs_sep_name, cs_sep_name_size)) {
141*593dc095SDavid du Colombier 		gs_color_space temp_cs = *pcs;
142*593dc095SDavid du Colombier 		gs_client_color client_color;
143*593dc095SDavid du Colombier 
144*593dc095SDavid du Colombier 		/*
145*593dc095SDavid du Colombier 	         * Create a copy of the color space and then modify it
146*593dc095SDavid du Colombier 		 * to force the use of the alternate color space.
147*593dc095SDavid du Colombier 	         */
148*593dc095SDavid du Colombier 		temp_cs.params.separation.use_alt_cspace = true;
149*593dc095SDavid du Colombier 		client_color.paint.values[0] = 1.0;
150*593dc095SDavid du Colombier 		capture_spot_equivalent_cmyk_colors(pdev, pgs, &client_color,
151*593dc095SDavid du Colombier 					    &temp_cs, i, pparams);
152*593dc095SDavid du Colombier 		break;
153*593dc095SDavid du Colombier 	    }
154*593dc095SDavid du Colombier 	}
155*593dc095SDavid du Colombier     }
156*593dc095SDavid du Colombier }
157*593dc095SDavid du Colombier 
158*593dc095SDavid du Colombier private void
update_DeviceN_spot_equivalent_cmyk_colors(gx_device * pdev,const gs_state * pgs,const gs_color_space * pcs,gs_devn_params * pdevn_params,equivalent_cmyk_color_params * pparams)159*593dc095SDavid du Colombier update_DeviceN_spot_equivalent_cmyk_colors(gx_device * pdev,
160*593dc095SDavid du Colombier 		    const gs_state * pgs, const gs_color_space * pcs,
161*593dc095SDavid du Colombier 		    gs_devn_params * pdevn_params,
162*593dc095SDavid du Colombier 		    equivalent_cmyk_color_params * pparams)
163*593dc095SDavid du Colombier {
164*593dc095SDavid du Colombier     int i;
165*593dc095SDavid du Colombier     unsigned int j;
166*593dc095SDavid du Colombier     unsigned int cs_sep_name_size;
167*593dc095SDavid du Colombier     unsigned char * pcs_sep_name;
168*593dc095SDavid du Colombier 
169*593dc095SDavid du Colombier     /*
170*593dc095SDavid du Colombier      * Check if the color space contains components named 'None'.  If so then
171*593dc095SDavid du Colombier      * our capture logic does not work properly.  When present, the 'None'
172*593dc095SDavid du Colombier      * components contain alternate color information.  However this info is
173*593dc095SDavid du Colombier      * specified as part of the 'color' and not part of the color space.  Thus
174*593dc095SDavid du Colombier      * we do not have this data when this routine is called.  See the
175*593dc095SDavid du Colombier      * description of DeviceN color spaces in section 4.5 of the PDF spec.
176*593dc095SDavid du Colombier      * In this situation we exit rather than produce invalid values.
177*593dc095SDavid du Colombier      */
178*593dc095SDavid du Colombier      for (j = 0; j < pcs->params.device_n.num_components; j++) {
179*593dc095SDavid du Colombier 	pcs->params.device_n.get_colorname_string
180*593dc095SDavid du Colombier 	    (pdev->memory, pcs->params.device_n.names[j],
181*593dc095SDavid du Colombier 	     &pcs_sep_name, &cs_sep_name_size);
182*593dc095SDavid du Colombier 	if (compare_color_names("None", 4, pcs_sep_name, cs_sep_name_size))
183*593dc095SDavid du Colombier 	    return;
184*593dc095SDavid du Colombier     }
185*593dc095SDavid du Colombier 
186*593dc095SDavid du Colombier     /*
187*593dc095SDavid du Colombier      * Check if the color space's separation names matches any of the
188*593dc095SDavid du Colombier      * separations for which we need an equivalent CMYK color.
189*593dc095SDavid du Colombier      */
190*593dc095SDavid du Colombier     for (i = 0; i < pdevn_params->separations.num_separations; i++) {
191*593dc095SDavid du Colombier 	if (pparams->color[i].color_info_valid == false) {
192*593dc095SDavid du Colombier 	    const devn_separation_name * dev_sep_name =
193*593dc095SDavid du Colombier 			    &(pdevn_params->separations.names[i]);
194*593dc095SDavid du Colombier 
195*593dc095SDavid du Colombier 	    for (j = 0; j < pcs->params.device_n.num_components; j++) {
196*593dc095SDavid du Colombier 	        pcs->params.device_n.get_colorname_string
197*593dc095SDavid du Colombier 		    (pdev->memory, pcs->params.device_n.names[j], &pcs_sep_name,
198*593dc095SDavid du Colombier 		     &cs_sep_name_size);
199*593dc095SDavid du Colombier 	        if (compare_color_names(dev_sep_name->data, dev_sep_name->size,
200*593dc095SDavid du Colombier 			    pcs_sep_name, cs_sep_name_size)) {
201*593dc095SDavid du Colombier 		    gs_color_space temp_cs = *pcs;
202*593dc095SDavid du Colombier 		    gs_client_color client_color;
203*593dc095SDavid du Colombier 
204*593dc095SDavid du Colombier 		    /*
205*593dc095SDavid du Colombier 	             * Create a copy of the color space and then modify it
206*593dc095SDavid du Colombier 		     * to force the use of the alternate color space.
207*593dc095SDavid du Colombier 	             */
208*593dc095SDavid du Colombier 		    memset(&client_color, 0, sizeof(client_color));
209*593dc095SDavid du Colombier 		    temp_cs.params.device_n.use_alt_cspace = true;
210*593dc095SDavid du Colombier 		    client_color.paint.values[j] = 1.0;
211*593dc095SDavid du Colombier 		    capture_spot_equivalent_cmyk_colors(pdev, pgs, &client_color,
212*593dc095SDavid du Colombier 					    &temp_cs, i, pparams);
213*593dc095SDavid du Colombier 		    break;
214*593dc095SDavid du Colombier 	        }
215*593dc095SDavid du Colombier 	    }
216*593dc095SDavid du Colombier 	}
217*593dc095SDavid du Colombier     }
218*593dc095SDavid du Colombier }
219*593dc095SDavid du Colombier 
check_all_colors_known(int num_spot,equivalent_cmyk_color_params * pparams)220*593dc095SDavid du Colombier private bool check_all_colors_known(int num_spot,
221*593dc095SDavid du Colombier 		equivalent_cmyk_color_params * pparams)
222*593dc095SDavid du Colombier {
223*593dc095SDavid du Colombier     for (num_spot--; num_spot >= 0; num_spot--)
224*593dc095SDavid du Colombier 	if (pparams->color[num_spot].color_info_valid == false)
225*593dc095SDavid du Colombier 	    return false;
226*593dc095SDavid du Colombier     return true;
227*593dc095SDavid du Colombier }
228*593dc095SDavid du Colombier 
229*593dc095SDavid du Colombier /* If possible, update the equivalent CMYK color for a spot color */
230*593dc095SDavid du Colombier void
update_spot_equivalent_cmyk_colors(gx_device * pdev,const gs_state * pgs,gs_devn_params * pdevn_params,equivalent_cmyk_color_params * pparams)231*593dc095SDavid du Colombier update_spot_equivalent_cmyk_colors(gx_device * pdev, const gs_state * pgs,
232*593dc095SDavid du Colombier     gs_devn_params * pdevn_params, equivalent_cmyk_color_params * pparams)
233*593dc095SDavid du Colombier {
234*593dc095SDavid du Colombier     const gs_color_space * pcs;
235*593dc095SDavid du Colombier 
236*593dc095SDavid du Colombier     /* If all of the color_info is valid then there is nothing to do. */
237*593dc095SDavid du Colombier     if (pparams->all_color_info_valid)
238*593dc095SDavid du Colombier 	return;
239*593dc095SDavid du Colombier 
240*593dc095SDavid du Colombier     /* Verify that we really have some separations. */
241*593dc095SDavid du Colombier     if (pdevn_params->separations.num_separations == 0) {
242*593dc095SDavid du Colombier 	pparams->all_color_info_valid = true;
243*593dc095SDavid du Colombier 	return;
244*593dc095SDavid du Colombier     }
245*593dc095SDavid du Colombier     /*
246*593dc095SDavid du Colombier      * Verify that the given color space is a Separation or a DeviceN color
247*593dc095SDavid du Colombier      * space.  If so then when check if the color space contains a separation
248*593dc095SDavid du Colombier      * color for which we need a CMYK equivalent.
249*593dc095SDavid du Colombier      */
250*593dc095SDavid du Colombier     pcs = pgs->color_space;
251*593dc095SDavid du Colombier     if (pcs != NULL) {
252*593dc095SDavid du Colombier 	if (pcs->type->index == gs_color_space_index_Separation) {
253*593dc095SDavid du Colombier 	    update_Separation_spot_equivalent_cmyk_colors(pdev, pgs, pcs,
254*593dc095SDavid du Colombier 						pdevn_params, pparams);
255*593dc095SDavid du Colombier 	    pparams->all_color_info_valid = check_all_colors_known
256*593dc095SDavid du Colombier 		    (pdevn_params->separations.num_separations, pparams);
257*593dc095SDavid du Colombier 	}
258*593dc095SDavid du Colombier 	else if (pcs->type->index == gs_color_space_index_DeviceN) {
259*593dc095SDavid du Colombier 	    update_DeviceN_spot_equivalent_cmyk_colors(pdev, pgs, pcs,
260*593dc095SDavid du Colombier 						pdevn_params, pparams);
261*593dc095SDavid du Colombier 	    pparams->all_color_info_valid = check_all_colors_known
262*593dc095SDavid du Colombier 		    (pdevn_params->separations.num_separations, pparams);
263*593dc095SDavid du Colombier 	}
264*593dc095SDavid du Colombier     }
265*593dc095SDavid du Colombier }
266*593dc095SDavid du Colombier 
267*593dc095SDavid du Colombier private void
save_spot_equivalent_cmyk_color(int sep_num,equivalent_cmyk_color_params * pparams,frac cmyk[4])268*593dc095SDavid du Colombier save_spot_equivalent_cmyk_color(int sep_num,
269*593dc095SDavid du Colombier 		equivalent_cmyk_color_params * pparams, frac cmyk[4])
270*593dc095SDavid du Colombier {
271*593dc095SDavid du Colombier     pparams->color[sep_num].c = cmyk[0];
272*593dc095SDavid du Colombier     pparams->color[sep_num].m = cmyk[1];
273*593dc095SDavid du Colombier     pparams->color[sep_num].y = cmyk[2];
274*593dc095SDavid du Colombier     pparams->color[sep_num].k = cmyk[3];
275*593dc095SDavid du Colombier     pparams->color[sep_num].color_info_valid = true;
276*593dc095SDavid du Colombier }
277*593dc095SDavid du Colombier 
278*593dc095SDavid du Colombier /*
279*593dc095SDavid du Colombier  * A structure definition for a device for capturing equivalent colors
280*593dc095SDavid du Colombier  */
281*593dc095SDavid du Colombier typedef struct color_capture_device_s {
282*593dc095SDavid du Colombier     gx_device_common;
283*593dc095SDavid du Colombier     gx_prn_device_common;
284*593dc095SDavid du Colombier     /*        ... device-specific parameters ... */
285*593dc095SDavid du Colombier     /* The following values are needed by the cmap procs for saving data */
286*593dc095SDavid du Colombier     int sep_num;	/* Number of the separation being captured */
287*593dc095SDavid du Colombier     /* Pointer to original device's equivalent CMYK colors */
288*593dc095SDavid du Colombier     equivalent_cmyk_color_params * pequiv_cmyk_colors;
289*593dc095SDavid du Colombier } color_capture_device;
290*593dc095SDavid du Colombier 
291*593dc095SDavid du Colombier /*
292*593dc095SDavid du Colombier  * Replacement routines for the cmap procs.  These routines will capture the
293*593dc095SDavid du Colombier  * equivalent color.
294*593dc095SDavid du Colombier  */
295*593dc095SDavid du Colombier private cmap_proc_gray(cmap_gray_capture_cmyk_color);
296*593dc095SDavid du Colombier private cmap_proc_rgb(cmap_rgb_capture_cmyk_color);
297*593dc095SDavid du Colombier private cmap_proc_cmyk(cmap_cmyk_capture_cmyk_color);
298*593dc095SDavid du Colombier private cmap_proc_rgb_alpha(cmap_rgb_alpha_capture_cmyk_color);
299*593dc095SDavid du Colombier private cmap_proc_separation(cmap_separation_capture_cmyk_color);
300*593dc095SDavid du Colombier private cmap_proc_devicen(cmap_devicen_capture_cmyk_color);
301*593dc095SDavid du Colombier 
302*593dc095SDavid du Colombier private const gx_color_map_procs cmap_capture_cmyk_color = {
303*593dc095SDavid du Colombier     cmap_gray_capture_cmyk_color,
304*593dc095SDavid du Colombier     cmap_rgb_capture_cmyk_color,
305*593dc095SDavid du Colombier     cmap_cmyk_capture_cmyk_color,
306*593dc095SDavid du Colombier     cmap_rgb_alpha_capture_cmyk_color,
307*593dc095SDavid du Colombier     cmap_separation_capture_cmyk_color,
308*593dc095SDavid du Colombier     cmap_devicen_capture_cmyk_color
309*593dc095SDavid du Colombier };
310*593dc095SDavid du Colombier 
311*593dc095SDavid du Colombier private void
cmap_gray_capture_cmyk_color(frac gray,gx_device_color * pdc,const gs_imager_state * pis,gx_device * dev,gs_color_select_t select)312*593dc095SDavid du Colombier cmap_gray_capture_cmyk_color(frac gray, gx_device_color * pdc,
313*593dc095SDavid du Colombier 	const gs_imager_state * pis, gx_device * dev, gs_color_select_t select)
314*593dc095SDavid du Colombier {
315*593dc095SDavid du Colombier     equivalent_cmyk_color_params * pparams =
316*593dc095SDavid du Colombier 	    ((color_capture_device *)dev)->pequiv_cmyk_colors;
317*593dc095SDavid du Colombier     int sep_num = ((color_capture_device *)dev)->sep_num;
318*593dc095SDavid du Colombier     frac cmyk[4];
319*593dc095SDavid du Colombier 
320*593dc095SDavid du Colombier     cmyk[0] = cmyk[1] = cmyk[2] = frac_0;
321*593dc095SDavid du Colombier     cmyk[3] = frac_1 - gray;
322*593dc095SDavid du Colombier     save_spot_equivalent_cmyk_color(sep_num, pparams, cmyk);
323*593dc095SDavid du Colombier }
324*593dc095SDavid du Colombier 
325*593dc095SDavid du Colombier private void
cmap_rgb_capture_cmyk_color(frac r,frac g,frac b,gx_device_color * pdc,const gs_imager_state * pis,gx_device * dev,gs_color_select_t select)326*593dc095SDavid du Colombier cmap_rgb_capture_cmyk_color(frac r, frac g, frac b, gx_device_color * pdc,
327*593dc095SDavid du Colombier      const gs_imager_state * pis, gx_device * dev, gs_color_select_t select)
328*593dc095SDavid du Colombier {
329*593dc095SDavid du Colombier     equivalent_cmyk_color_params * pparams =
330*593dc095SDavid du Colombier 	    ((color_capture_device *)dev)->pequiv_cmyk_colors;
331*593dc095SDavid du Colombier     int sep_num = ((color_capture_device *)dev)->sep_num;
332*593dc095SDavid du Colombier     frac cmyk[4];
333*593dc095SDavid du Colombier 
334*593dc095SDavid du Colombier     color_rgb_to_cmyk(r, g, b, pis, cmyk);
335*593dc095SDavid du Colombier     save_spot_equivalent_cmyk_color(sep_num, pparams, cmyk);
336*593dc095SDavid du Colombier }
337*593dc095SDavid du Colombier 
338*593dc095SDavid du Colombier private void
cmap_cmyk_capture_cmyk_color(frac c,frac m,frac y,frac k,gx_device_color * pdc,const gs_imager_state * pis,gx_device * dev,gs_color_select_t select)339*593dc095SDavid du Colombier cmap_cmyk_capture_cmyk_color(frac c, frac m, frac y, frac k, gx_device_color * pdc,
340*593dc095SDavid du Colombier      const gs_imager_state * pis, gx_device * dev, gs_color_select_t select)
341*593dc095SDavid du Colombier {
342*593dc095SDavid du Colombier     equivalent_cmyk_color_params * pparams =
343*593dc095SDavid du Colombier 	    ((color_capture_device *)dev)->pequiv_cmyk_colors;
344*593dc095SDavid du Colombier     int sep_num = ((color_capture_device *)dev)->sep_num;
345*593dc095SDavid du Colombier     frac cmyk[4];
346*593dc095SDavid du Colombier 
347*593dc095SDavid du Colombier     cmyk[0] = c;
348*593dc095SDavid du Colombier     cmyk[1] = m;
349*593dc095SDavid du Colombier     cmyk[2] = y;
350*593dc095SDavid du Colombier     cmyk[3] = k;
351*593dc095SDavid du Colombier     save_spot_equivalent_cmyk_color(sep_num, pparams, cmyk);
352*593dc095SDavid du Colombier }
353*593dc095SDavid du Colombier 
354*593dc095SDavid du Colombier private void
cmap_rgb_alpha_capture_cmyk_color(frac r,frac g,frac b,frac alpha,gx_device_color * pdc,const gs_imager_state * pis,gx_device * dev,gs_color_select_t select)355*593dc095SDavid du Colombier cmap_rgb_alpha_capture_cmyk_color(frac r, frac g, frac b, frac alpha,
356*593dc095SDavid du Colombier 	gx_device_color * pdc, const gs_imager_state * pis, gx_device * dev,
357*593dc095SDavid du Colombier 			 gs_color_select_t select)
358*593dc095SDavid du Colombier {
359*593dc095SDavid du Colombier     cmap_rgb_capture_cmyk_color(r, g, b, pdc, pis, dev, select);
360*593dc095SDavid du Colombier }
361*593dc095SDavid du Colombier 
362*593dc095SDavid du Colombier private void
cmap_separation_capture_cmyk_color(frac all,gx_device_color * pdc,const gs_imager_state * pis,gx_device * dev,gs_color_select_t select)363*593dc095SDavid du Colombier cmap_separation_capture_cmyk_color(frac all, gx_device_color * pdc,
364*593dc095SDavid du Colombier      const gs_imager_state * pis, gx_device * dev, gs_color_select_t select)
365*593dc095SDavid du Colombier {
366*593dc095SDavid du Colombier     dprintf("cmap_separation_capture_cmyk_color - this routine should not be executed\n");
367*593dc095SDavid du Colombier }
368*593dc095SDavid du Colombier 
369*593dc095SDavid du Colombier private void
cmap_devicen_capture_cmyk_color(const frac * pcc,gx_device_color * pdc,const gs_imager_state * pis,gx_device * dev,gs_color_select_t select)370*593dc095SDavid du Colombier cmap_devicen_capture_cmyk_color(const frac * pcc, gx_device_color * pdc,
371*593dc095SDavid du Colombier      const gs_imager_state * pis, gx_device * dev, gs_color_select_t select)
372*593dc095SDavid du Colombier {
373*593dc095SDavid du Colombier     dprintf("cmap_devicen_capture_cmyk_color - this routine should not be executed\n");
374*593dc095SDavid du Colombier }
375*593dc095SDavid du Colombier 
376*593dc095SDavid du Colombier /*
377*593dc095SDavid du Colombier  * Note:  The color space (pcs) has already been modified to use the
378*593dc095SDavid du Colombier  * alternate color space.
379*593dc095SDavid du Colombier  */
380*593dc095SDavid du Colombier private void
capture_spot_equivalent_cmyk_colors(gx_device * pdev,const gs_state * pgs,const gs_client_color * pcc,const gs_color_space * pcs,int sep_num,equivalent_cmyk_color_params * pparams)381*593dc095SDavid du Colombier capture_spot_equivalent_cmyk_colors(gx_device * pdev, const gs_state * pgs,
382*593dc095SDavid du Colombier     const gs_client_color * pcc, const gs_color_space * pcs,
383*593dc095SDavid du Colombier     int sep_num, equivalent_cmyk_color_params * pparams)
384*593dc095SDavid du Colombier {
385*593dc095SDavid du Colombier     gs_imager_state temp_state = *((const gs_imager_state *)pgs);
386*593dc095SDavid du Colombier     color_capture_device temp_device = { 0 };
387*593dc095SDavid du Colombier     gx_device_color dev_color;
388*593dc095SDavid du Colombier 
389*593dc095SDavid du Colombier     /*
390*593dc095SDavid du Colombier      * Create a temp device.  The primary purpose of this device is pass the
391*593dc095SDavid du Colombier      * separation number and a pointer to the original device's equivalent
392*593dc095SDavid du Colombier      * color parameters.  Since we only using this device for a very specific
393*593dc095SDavid du Colombier      * purpose, we only set up the color_info structure and and our data.
394*593dc095SDavid du Colombier      */
395*593dc095SDavid du Colombier     temp_device.color_info = pdev->color_info;
396*593dc095SDavid du Colombier     temp_device.sep_num = sep_num;
397*593dc095SDavid du Colombier     temp_device.pequiv_cmyk_colors = pparams;
398*593dc095SDavid du Colombier     /*
399*593dc095SDavid du Colombier      * Create a temp copy of the imager state.  We do this so that we
400*593dc095SDavid du Colombier      * can modify the color space mapping (cmap) procs.  We use our
401*593dc095SDavid du Colombier      * replacment procs to capture the color.  The installation of a
402*593dc095SDavid du Colombier      * Separation or DeviceN color space also sets a use_alt_cspace flag
403*593dc095SDavid du Colombier      * in the state.  We also need to set this to use the alternate space.
404*593dc095SDavid du Colombier      */
405*593dc095SDavid du Colombier     temp_state.cmap_procs = &cmap_capture_cmyk_color;
406*593dc095SDavid du Colombier     temp_state.color_component_map.use_alt_cspace = true;
407*593dc095SDavid du Colombier 
408*593dc095SDavid du Colombier     /* Now capture the color */
409*593dc095SDavid du Colombier     pcs->type->remap_color (pcc, pcs, &dev_color, &temp_state,
410*593dc095SDavid du Colombier 		    (gx_device *)&temp_device, gs_color_select_texture);
411*593dc095SDavid du Colombier }
412