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