1 /* Copyright (C) 2001-2012 Artifex Software, Inc.
2    All Rights Reserved.
3 
4    This software is provided AS-IS with no warranty, either express or
5    implied.
6 
7    This software is distributed under license and may not be copied,
8    modified or distributed except as expressly authorized under the terms
9    of the license contained in the file LICENSE in this distribution.
10 
11    Refer to licensing information at http://www.artifex.com or contact
12    Artifex Software, Inc.,  7 Mt. Lassen Drive - Suite A-134, San Rafael,
13    CA  94903, U.S.A., +1(415)492-9861, for further information.
14 */
15 
16 
17 /* Color space operators and support */
18 #include "memory_.h"
19 #include "gx.h"
20 #include "gserrors.h"
21 #include "gsstruct.h"
22 #include "gsccolor.h"
23 #include "gsutil.h"		/* for gs_next_ids */
24 #include "gxcmap.h"
25 #include "gxcspace.h"
26 #include "gxistate.h"
27 #include "gsovrc.h"
28 #include "gsstate.h"
29 #include "gsdevice.h"
30 #include "gxdevcli.h"
31 #include "gzstate.h"
32 #include "stream.h"
33 #include "gsnamecl.h"  /* Custom color call back define */
34 #include "gsicc.h"
35 #include "gsicc_manage.h"
36 
37 static cs_proc_install_cspace(gx_install_DeviceGray);
38 static cs_proc_install_cspace(gx_install_DeviceRGB);
39 static cs_proc_install_cspace(gx_install_DeviceCMYK);
40 /*
41  * Define the standard color space types.  We include DeviceCMYK in the base
42  * build because it's too awkward to omit it, but we don't provide any of
43  * the PostScript operator procedures (setcmykcolor, etc.) for dealing with
44  * it.
45  */
46 static const gs_color_space_type gs_color_space_type_DeviceGray = {
47     gs_color_space_index_DeviceGray, true, true,
48     &st_base_color_space, gx_num_components_1,
49     gx_init_paint_1, gx_restrict01_paint_1,
50     gx_same_concrete_space,
51     gx_concretize_DeviceGray, gx_remap_concrete_DGray,
52     gx_remap_DeviceGray, gx_install_DeviceGray,
53     gx_spot_colors_set_overprint,
54     NULL, gx_no_adjust_color_count,
55     gx_serialize_cspace_type,
56     gx_cspace_is_linear_default
57 };
58 static const gs_color_space_type gs_color_space_type_DeviceRGB = {
59     gs_color_space_index_DeviceRGB, true, true,
60     &st_base_color_space, gx_num_components_3,
61     gx_init_paint_3, gx_restrict01_paint_3,
62     gx_same_concrete_space,
63     gx_concretize_DeviceRGB, gx_remap_concrete_DRGB,
64     gx_remap_DeviceRGB, gx_install_DeviceRGB,
65     gx_spot_colors_set_overprint,
66     NULL, gx_no_adjust_color_count,
67     gx_serialize_cspace_type,
68     gx_cspace_is_linear_default
69 };
70 
71 static cs_proc_set_overprint(gx_set_overprint_DeviceCMYK);
72 
73 static const gs_color_space_type gs_color_space_type_DeviceCMYK = {
74     gs_color_space_index_DeviceCMYK, true, true,
75     &st_base_color_space, gx_num_components_4,
76     gx_init_paint_4, gx_restrict01_paint_4,
77     gx_same_concrete_space,
78     gx_concretize_DeviceCMYK, gx_remap_concrete_DCMYK,
79     gx_remap_DeviceCMYK, gx_install_DeviceCMYK,
80     gx_set_overprint_DeviceCMYK,
81     NULL, gx_no_adjust_color_count,
82     gx_serialize_cspace_type,
83     gx_cspace_is_linear_default
84 };
85 
86 /* Structure descriptors */
87 public_st_color_space();
88 public_st_base_color_space();
89 
90 /* ------ Create/copy/destroy ------ */
91 
92 static void
gs_cspace_final(const gs_memory_t * cmem,void * vptr)93 gs_cspace_final(const gs_memory_t *cmem, void *vptr)
94 {
95     gs_color_space *pcs = (gs_color_space *)vptr;
96     (void)cmem; /* unused */
97 
98     if (pcs->type->final)
99         pcs->type->final(pcs);
100     if_debug2('c', "[c]cspace final %08x %d\n", pcs, pcs->id);
101     rc_decrement_only_cs(pcs->base_space, "gs_cspace_final");
102 
103     /* No need to decrement the ICC profile data.  It is handled
104        by the finalize of the ICC space which is called above using
105        pcs->type->final(pcs);  */
106 
107 }
108 
109 static gs_color_space *
gs_cspace_alloc_with_id(gs_memory_t * mem,ulong id,const gs_color_space_type * pcstype)110 gs_cspace_alloc_with_id(gs_memory_t *mem, ulong id,
111                    const gs_color_space_type *pcstype)
112 {
113     gs_color_space *pcs;
114 
115     rc_alloc_struct_1(pcs, gs_color_space, &st_color_space, mem, return NULL,
116                       "gs_cspace_alloc_with_id");
117     if_debug3('c', "[c]cspace alloc %08x %s %d\n",
118               pcs, pcstype->stype->sname, pcstype->index);
119     pcs->type = pcstype;
120     pcs->id = id;
121     pcs->base_space = NULL;
122     pcs->pclient_color_space_data = NULL;
123     pcs->cmm_icc_profile_data = NULL;
124     pcs->icc_equivalent = NULL;
125     return pcs;
126 }
127 
128 static cs_proc_install_cspace(gx_install_DeviceGray);
129 static cs_proc_install_cspace(gx_install_DeviceRGB);
130 static cs_proc_install_cspace(gx_install_DeviceCMYK);
131 
132 /*
133  * Generic allocation function for colorspace implementations. Return
134  * NULL on allocation failure.
135  */
136 gs_color_space *
gs_cspace_alloc(gs_memory_t * mem,const gs_color_space_type * pcstype)137 gs_cspace_alloc(gs_memory_t *mem, const gs_color_space_type *pcstype)
138 {
139     return gs_cspace_alloc_with_id(mem, gs_next_ids(mem, 1), pcstype);
140 }
141 
142 /* Constructors for simple device color spaces. */
143 
144 gs_color_space *
gs_cspace_new_DeviceGray(gs_memory_t * mem)145 gs_cspace_new_DeviceGray(gs_memory_t *mem)
146 {
147     return gs_cspace_alloc_with_id(mem, cs_DeviceGray_id,
148                                    &gs_color_space_type_DeviceGray);
149 }
150 
151 gs_color_space *
gs_cspace_new_DeviceRGB(gs_memory_t * mem)152 gs_cspace_new_DeviceRGB(gs_memory_t *mem)
153 {
154     return gs_cspace_alloc_with_id(mem, cs_DeviceRGB_id,
155                                    &gs_color_space_type_DeviceRGB);
156 }
157 gs_color_space *
gs_cspace_new_DeviceCMYK(gs_memory_t * mem)158 gs_cspace_new_DeviceCMYK(gs_memory_t *mem)
159 {
160     return gs_cspace_alloc_with_id(mem, cs_DeviceCMYK_id,
161                                    &gs_color_space_type_DeviceCMYK);
162 }
163 
164 /* For use in initializing ICC color spaces for XPS */
165 gs_color_space *
gs_cspace_new_ICC(gs_memory_t * pmem,gs_state * pgs,int components)166 gs_cspace_new_ICC(gs_memory_t *pmem, gs_state * pgs, int components)
167 {
168     gsicc_manager_t *icc_manage = pgs->icc_manager;
169     int code;
170     gs_color_space *pcspace = gs_cspace_alloc(pmem, &gs_color_space_type_ICC);
171 
172     switch (components) {
173         case -1: /* alpha case */
174             if (icc_manage->smask_profiles == NULL) {
175                 code = gsicc_initialize_iccsmask(icc_manage);
176             }
177             if (code == 0) {
178                 pcspace->cmm_icc_profile_data =
179                     icc_manage->smask_profiles->smask_gray;
180             } else {
181                 pcspace->cmm_icc_profile_data = icc_manage->default_gray;
182             }
183             break;
184         case -3: /* alpha case.  needs linear RGB */
185             if (icc_manage->smask_profiles == NULL) {
186                 code = gsicc_initialize_iccsmask(icc_manage);
187             }
188             if (code == 0) {
189                 pcspace->cmm_icc_profile_data =
190                     icc_manage->smask_profiles->smask_rgb;
191             } else {
192                 pcspace->cmm_icc_profile_data = icc_manage->default_rgb;
193             }
194             break;
195         case 1: pcspace->cmm_icc_profile_data = icc_manage->default_gray; break;
196         case 3: pcspace->cmm_icc_profile_data = icc_manage->default_rgb; break;
197         case 4: pcspace->cmm_icc_profile_data = icc_manage->default_cmyk; break;
198         default: rc_decrement(pcspace,"gs_cspace_new_ICC"); return NULL;
199     }
200     rc_increment(pcspace->cmm_icc_profile_data);
201     return pcspace;
202 }
203 
204 /* ------ Accessors ------ */
205 
206 /* Get the index of a color space. */
207 gs_color_space_index
gs_color_space_get_index(const gs_color_space * pcs)208 gs_color_space_get_index(const gs_color_space * pcs)
209 {
210     return pcs->type->index;
211 }
212 
213 /* See if the space is CIE based */
gs_color_space_is_CIE(const gs_color_space * pcs)214 bool gs_color_space_is_CIE(const gs_color_space * pcs)
215 {
216     switch(gs_color_space_get_index(pcs)){
217         case gs_color_space_index_CIEDEFG:
218         case gs_color_space_index_CIEDEF:
219         case gs_color_space_index_CIEABC:
220         case gs_color_space_index_CIEA:
221         case gs_color_space_index_ICC:
222             return true;
223         break;
224         default:
225             return false;
226     }
227 }
228 
229 /* See if the space is Postscript CIE based */
gs_color_space_is_PSCIE(const gs_color_space * pcs)230 bool gs_color_space_is_PSCIE(const gs_color_space * pcs)
231 {
232     switch(gs_color_space_get_index(pcs)){
233         case gs_color_space_index_CIEDEFG:
234         case gs_color_space_index_CIEDEF:
235         case gs_color_space_index_CIEABC:
236         case gs_color_space_index_CIEA:
237             return true;
238         break;
239         default:
240             return false;
241 }
242 }
243 
244 /* See if the space is ICC based */
gs_color_space_is_ICC(const gs_color_space * pcs)245 bool gs_color_space_is_ICC(const gs_color_space * pcs)
246 {
247     return(gs_color_space_get_index(pcs) == gs_color_space_index_ICC);
248 }
249 
250 /* Get the number of components in a color space. */
251 int
gs_color_space_num_components(const gs_color_space * pcs)252 gs_color_space_num_components(const gs_color_space * pcs)
253 {
254     return cs_num_components(pcs);
255 }
256 
257 /* Restrict a color to its legal range. */
258 void
gs_color_space_restrict_color(gs_client_color * pcc,const gs_color_space * pcs)259 gs_color_space_restrict_color(gs_client_color *pcc, const gs_color_space *pcs)
260 {
261     cs_restrict_color(pcc, pcs);
262 }
263 
264 /* Install a DeviceGray color space. */
265 static int
gx_install_DeviceGray(gs_color_space * pcs,gs_state * pgs)266 gx_install_DeviceGray(gs_color_space * pcs, gs_state * pgs)
267 {
268     /* If we already have profile data installed, nothing to do here. */
269     if (pcs->cmm_icc_profile_data != NULL)
270         return 0;
271 
272     /* If we haven't initialised the iccmanager, do it now. */
273     if (pgs->icc_manager->default_gray == NULL)
274         gsicc_init_iccmanager(pgs);
275 
276     /* pcs takes a reference to the default_gray profile data */
277     pcs->cmm_icc_profile_data = pgs->icc_manager->default_gray;
278     rc_increment(pgs->icc_manager->default_gray);
279     pcs->type = &gs_color_space_type_ICC;
280     return 0;
281 }
282 
283 int
gx_num_components_1(const gs_color_space * pcs)284 gx_num_components_1(const gs_color_space * pcs)
285 {
286     return 1;
287 }
288 int
gx_num_components_3(const gs_color_space * pcs)289 gx_num_components_3(const gs_color_space * pcs)
290 {
291     return 3;
292 }
293 int
gx_num_components_4(const gs_color_space * pcs)294 gx_num_components_4(const gs_color_space * pcs)
295 {
296     return 4;
297 }
298 
299 /*
300  * For color spaces that have a base or alternative color space, return that
301  * color space. Otherwise return null.
302  */
303 const gs_color_space *
gs_cspace_base_space(const gs_color_space * pcspace)304 gs_cspace_base_space(const gs_color_space * pcspace)
305 {
306     return pcspace->base_space;
307 }
308 
309 /* Abstract the reference counting for color spaces
310    so that we can also increment the ICC profile
311    if there is one associated with the color space */
312 
rc_increment_cs(gs_color_space * pcs)313 void rc_increment_cs(gs_color_space *pcs)
314 {
315     rc_increment(pcs);
316 }
317 
rc_decrement_cs(gs_color_space * pcs,const char * cname)318 void rc_decrement_cs(gs_color_space *pcs, const char *cname) {
319 
320     if (pcs) {
321         rc_decrement(pcs, cname);
322     }
323 }
324 
rc_decrement_only_cs(gs_color_space * pcs,const char * cname)325 void rc_decrement_only_cs(gs_color_space *pcs, const char *cname)
326 {
327     if (pcs) {
328         rc_decrement_only(pcs, cname);
329     }
330 }
331 
cs_adjust_counts_icc(gs_state * pgs,int delta)332 void cs_adjust_counts_icc(gs_state *pgs, int delta)
333 {
334     gs_color_space *pcs = gs_currentcolorspace_inline(pgs);
335 
336     if (pcs) {
337         cs_adjust_counts(pgs, delta);
338     }
339 }
340 
341 /* ------ Other implementation procedures ------ */
342 
343 /* Null color space installation procedure. */
344 int
gx_no_install_cspace(gs_color_space * pcs,gs_state * pgs)345 gx_no_install_cspace(gs_color_space * pcs, gs_state * pgs)
346 {
347     return 0;
348 }
349 
350 /* Install a DeviceRGB color space. */
351 static int
gx_install_DeviceRGB(gs_color_space * pcs,gs_state * pgs)352 gx_install_DeviceRGB(gs_color_space * pcs, gs_state * pgs)
353 {
354     /* If we already have profile_data, nothing to do here. */
355     if (pcs->cmm_icc_profile_data != NULL)
356         return 0;
357 
358     /* If the icc manager hasn't been set up yet, then set it up. */
359     if (pgs->icc_manager->default_rgb == NULL)
360         gsicc_init_iccmanager(pgs);
361 
362     /* pcs takes a reference to default_rgb */
363     pcs->cmm_icc_profile_data = pgs->icc_manager->default_rgb;
364     rc_increment(pcs->cmm_icc_profile_data);
365     pcs->type = &gs_color_space_type_ICC;
366     return 0;
367 }
368 
369 /* Install a DeviceCMYK color space. */
370 static int
gx_install_DeviceCMYK(gs_color_space * pcs,gs_state * pgs)371 gx_install_DeviceCMYK(gs_color_space * pcs, gs_state * pgs)
372 {
373     /* If we already have profile data, nothing to do here. */
374     if (pcs->cmm_icc_profile_data != NULL)
375         return 0;
376 
377     /* If the icc manager hasn't been set up yet, then set it up. */
378     if (pgs->icc_manager->default_cmyk == NULL)
379         gsicc_init_iccmanager(pgs);
380 
381     /* pcs takes a reference to default_cmyk */
382     pcs->cmm_icc_profile_data = pgs->icc_manager->default_cmyk;
383     rc_increment(pcs->cmm_icc_profile_data);
384     pcs->type = &gs_color_space_type_ICC;
385     return 0;
386 }
387 
388 /*
389  * Push an overprint compositor onto the current device indicating that,
390  * at most, the spot color parameters are to be preserved.
391  *
392  * This routine should be used for all Device, CIEBased, and ICCBased
393  * color spaces, except for DeviceCMKY. Also, it would not be used for
394  * DeviceRGB if we have simulated overprint turned on.
395  * These latter cases requires a
396  * special verson that supports overprint mode.
397  */
398 int
gx_spot_colors_set_overprint(const gs_color_space * pcs,gs_state * pgs)399 gx_spot_colors_set_overprint(const gs_color_space * pcs, gs_state * pgs)
400 {
401     gs_imager_state *       pis = (gs_imager_state *)pgs;
402     gs_overprint_params_t   params;
403 
404     if ((params.retain_any_comps = pis->overprint))
405         params.retain_spot_comps = true;
406     pgs->effective_overprint_mode = 0;
407     params.k_value = 0;
408     return gs_state_update_overprint(pgs, &params);
409 }
410 
411 static bool
check_single_comp(int comp,frac targ_val,int ncomps,const frac * pval)412 check_single_comp(int comp, frac targ_val, int ncomps, const frac * pval)
413 {
414     int     i;
415 
416     for (i = 0; i < ncomps; i++) {
417         if ( (i != comp && pval[i] != frac_0)  ||
418              (i == comp && pval[i] != targ_val)  )
419             return false;
420     }
421     return true;
422 }
423 
424 /*
425  * Determine if the current color model is a "DeviceCMYK" color model, and
426  * if so what are its process color components. This information is required
427  * when PLRM defines special rules for CMYK devices. This includes:
428  * 1. DeviceGray to CMYK color conversion
429  * 2. when overprint is true and overprint mode is set to 1.
430  *
431  * A color model is considered a "DeviceCMYK" color model if it supports the
432  * cyan, magenta, yellow, and black color components, and maps the DeviceCMYK
433  * color model components directly to these color components. Note that this
434  * does not require any particular component order, allows for additional
435  * spot color components, and does admit DeviceN color spaces if they have
436  * the requisite behavior.
437  *
438  * If the color model is a "DeviceCMYK" color model, return the set of
439  * process color components; otherwise return 0.
440  */
441 gx_color_index
check_cmyk_color_model_comps(gx_device * dev)442 check_cmyk_color_model_comps(gx_device * dev)
443 {
444     gx_device_color_info *          pcinfo = &dev->color_info;
445     int                             ncomps = pcinfo->num_components;
446     int                             cyan_c, magenta_c, yellow_c, black_c;
447     const gx_cm_color_map_procs *   pprocs;
448     cm_map_proc_cmyk((*map_cmyk));
449     frac                            frac_14 = frac_1 / 4;
450     frac                            out[GX_DEVICE_COLOR_MAX_COMPONENTS];
451     gx_color_index                  process_comps;
452 
453     /* check for the appropriate components */
454     if ( ncomps < 4                                       ||
455          (cyan_c = dev_proc(dev, get_color_comp_index)(
456                        dev,
457                        "Cyan",
458                        sizeof("Cyan") - 1,
459                        NO_COMP_NAME_TYPE )) < 0           ||
460          cyan_c == GX_DEVICE_COLOR_MAX_COMPONENTS         ||
461          (magenta_c = dev_proc(dev, get_color_comp_index)(
462                           dev,
463                           "Magenta",
464                           sizeof("Magenta") - 1,
465                           NO_COMP_NAME_TYPE )) < 0        ||
466          magenta_c == GX_DEVICE_COLOR_MAX_COMPONENTS      ||
467          (yellow_c = dev_proc(dev, get_color_comp_index)(
468                         dev,
469                         "Yellow",
470                         sizeof("Yellow") - 1,
471                         NO_COMP_NAME_TYPE )) < 0               ||
472          yellow_c == GX_DEVICE_COLOR_MAX_COMPONENTS       ||
473          (black_c = dev_proc(dev, get_color_comp_index)(
474                         dev,
475                         "Black",
476                         sizeof("Black") - 1,
477                         NO_COMP_NAME_TYPE )) < 0                         ||
478          black_c == GX_DEVICE_COLOR_MAX_COMPONENTS          )
479         return 0;
480 
481     /* check the mapping */
482     if ( (pprocs = dev_proc(dev, get_color_mapping_procs)(dev)) == 0 ||
483          (map_cmyk = pprocs->map_cmyk) == 0                            )
484         return 0;
485 
486     map_cmyk(dev, frac_14, frac_0, frac_0, frac_0, out);
487     if (!check_single_comp(cyan_c, frac_14, ncomps, out))
488         return 0;
489     map_cmyk(dev, frac_0, frac_14, frac_0, frac_0, out);
490     if (!check_single_comp(magenta_c, frac_14, ncomps, out))
491         return 0;
492     map_cmyk(dev, frac_0, frac_0, frac_14, frac_0, out);
493     if (!check_single_comp(yellow_c, frac_14, ncomps, out))
494         return false;
495     map_cmyk(dev, frac_0, frac_0, frac_0, frac_14, out);
496     if (!check_single_comp(black_c, frac_14, ncomps, out))
497         return 0;
498 
499     process_comps =  ((gx_color_index)1 << cyan_c)
500                    | ((gx_color_index)1 << magenta_c)
501                    | ((gx_color_index)1 << yellow_c)
502                    | ((gx_color_index)1 << black_c);
503     pcinfo->opmode = GX_CINFO_OPMODE;
504     pcinfo->process_comps = process_comps;
505     pcinfo->black_component = black_c;
506     return process_comps;
507 }
508 
509 /* This is used in the RGB simulation overprint case */
510 
511 gx_color_index
check_rgb_color_model_comps(gx_device * dev)512 check_rgb_color_model_comps(gx_device * dev)
513 {
514     gx_device_color_info *          pcinfo = &dev->color_info;
515     int                             ncomps = pcinfo->num_components;
516     int                             red_c, green_c, blue_c;
517     const gx_cm_color_map_procs *   pprocs;
518     cm_map_proc_rgb((*map_rgb));
519     frac                            frac_14 = frac_1 / 4;
520     frac                            out[GX_DEVICE_COLOR_MAX_COMPONENTS];
521     gx_color_index                  process_comps;
522 
523     /* check for the appropriate components */
524     if ( ncomps < 3                                       ||
525          (red_c = dev_proc(dev, get_color_comp_index)(
526                        dev,
527                        "Red",
528                        sizeof("Red") - 1,
529                        NO_COMP_NAME_TYPE )) < 0           ||
530          red_c == GX_DEVICE_COLOR_MAX_COMPONENTS         ||
531          (green_c = dev_proc(dev, get_color_comp_index)(
532                           dev,
533                           "Green",
534                           sizeof("Green") - 1,
535                           NO_COMP_NAME_TYPE )) < 0        ||
536          green_c == GX_DEVICE_COLOR_MAX_COMPONENTS      ||
537          (blue_c = dev_proc(dev, get_color_comp_index)(
538                         dev,
539                         "Blue",
540                         sizeof("Blue") - 1,
541                         NO_COMP_NAME_TYPE )) < 0               ||
542          blue_c == GX_DEVICE_COLOR_MAX_COMPONENTS        )
543         return 0;
544 
545     /* check the mapping */
546     if ( (pprocs = dev_proc(dev, get_color_mapping_procs)(dev)) == 0 ||
547          (map_rgb = pprocs->map_rgb) == 0                            )
548         return 0;
549 
550     map_rgb(dev, NULL, frac_14, frac_0, frac_0, out);
551     if (!check_single_comp(red_c, frac_14, ncomps, out))
552         return 0;
553     map_rgb(dev, NULL, frac_0, frac_14, frac_0, out);
554     if (!check_single_comp(green_c, frac_14, ncomps, out))
555         return 0;
556     map_rgb(dev, NULL, frac_0, frac_0, frac_14, out);
557     if (!check_single_comp(blue_c, frac_14, ncomps, out))
558         return 0;
559 
560     process_comps =  ((gx_color_index)1 << red_c)
561                    | ((gx_color_index)1 << green_c)
562                    | ((gx_color_index)1 << blue_c);
563     pcinfo->opmode = GC_CINFO_OPMODE_RGB_SET;
564     pcinfo->process_comps = process_comps;
565     return process_comps;
566 }
567 
568 /*
569  * This set_overprint method is unique. If overprint is true, overprint
570  * mode is set to 1, the process color model has DeviceCMYK behavior (see
571  * the comment ahead of gx_is_cmyk_color_model above), and the device
572  * color is set, the device color needs to be considered in setting up
573  * the set of drawn components.
574  */
575 static int
gx_set_overprint_DeviceCMYK(const gs_color_space * pcs,gs_state * pgs)576 gx_set_overprint_DeviceCMYK(const gs_color_space * pcs, gs_state * pgs)
577 {
578     gx_device *             dev = pgs->device;
579     gx_device_color_info *  pcinfo = (dev == 0 ? 0 : &dev->color_info);
580 
581     /* check if we require special handling */
582     if ( !pgs->overprint                      ||
583          pgs->overprint_mode != 1             ||
584          pcinfo == 0                          ||
585          pcinfo->opmode == GX_CINFO_OPMODE_NOT  )
586         return gx_spot_colors_set_overprint(pcs, pgs);
587     /* Share code with CMYK ICC case */
588     return gx_set_overprint_cmyk(pcs, pgs);
589 }
590 
591 /* A few comments about ICC profiles and overprint simulation.  In order
592    to do proper overprint simulation, the source ICC profile and the
593    destination ICC profile must be the same.  If they are not, then
594    we end up mapping the source CMYK data to a different CMYK value.  In
595    this case, the non-zero components, which with overprint mode = 1 specify
596    which are to be overprinted will not be correct to produce the proper
597    overprint simulation.  This is seen with AR when doing output preview,
598    overprint simulation enabled of the file overprint_icc.pdf (see our
599    test files) which has SWOP ICC based CMYK fills.  In AR, if we use a
600    simluation ICC profile that is different than the source profile,
601    overprinting is no longer previewed. We follow the same logic here.
602    If the source and destination ICC profiles do not match, then there is
603    effectively no overprinting enabled.  This is bug 692433 */
gx_set_overprint_cmyk(const gs_color_space * pcs,gs_state * pgs)604 int gx_set_overprint_cmyk(const gs_color_space * pcs, gs_state * pgs)
605 {
606     gx_device *             dev = pgs->device;
607     gx_device_color_info *  pcinfo = (dev == 0 ? 0 : &dev->color_info);
608     gx_color_index          drawn_comps = 0;
609     gs_overprint_params_t   params;
610     gx_device_color        *pdc;
611     cmm_dev_profile_t      *dev_profile;
612     cmm_profile_t          *output_profile;
613     int                     code;
614     bool                    profile_ok = false;
615     gsicc_rendering_intents_t rendering_intent;
616 
617     code = dev_proc(dev, get_profile)(dev, &dev_profile);
618     gsicc_extract_profile(dev->graphics_type_tag, dev_profile, &(output_profile),
619                           &rendering_intent);
620 
621     /* check if color model behavior must be determined */
622     if (pcinfo->opmode == GX_CINFO_OPMODE_UNKNOWN)
623         drawn_comps = check_cmyk_color_model_comps(dev);
624     else
625         drawn_comps = pcinfo->process_comps;
626     if (drawn_comps == 0)
627         return gx_spot_colors_set_overprint(pcs, pgs);
628 
629     /* correct for any zero'ed color components.  But only if profiles
630        match */
631     if (pcs->cmm_icc_profile_data != NULL && output_profile != NULL) {
632         if (output_profile->hashcode ==
633             pcs->cmm_icc_profile_data->hashcode) {
634             profile_ok = true;
635         }
636     }
637 
638     pgs->effective_overprint_mode = 1;
639     pdc = gs_currentdevicecolor_inline(pgs);
640     if (color_is_set(pdc) && profile_ok) {
641         gx_color_index  nz_comps, one, temp;
642         int             code;
643         int             num_colorant[4], k;
644         bool            colorant_ok;
645 
646         dev_color_proc_get_nonzero_comps((*procp));
647 
648         procp = pdc->type->get_nonzero_comps;
649         if (pdc->ccolor_valid) {
650             /* If we have the source colors, then use those in making the
651                decision as to which ones are non-zero.  Then we avoid
652                accidently looking at small values that get quantized to zero
653                Note that to get here in the code, the source color data color
654                space has to be CMYK. Trick is that we do need to worry about
655                the colorant order on the target device */
656             num_colorant[0] = (dev_proc(dev, get_color_comp_index))\
657                              (dev, "Cyan", strlen("Cyan"), NO_COMP_NAME_TYPE);
658             num_colorant[1] = (dev_proc(dev, get_color_comp_index))\
659                              (dev, "Magenta", strlen("Magenta"), NO_COMP_NAME_TYPE);
660             num_colorant[2] = (dev_proc(dev, get_color_comp_index))\
661                              (dev, "Yellow", strlen("Yellow"), NO_COMP_NAME_TYPE);
662             num_colorant[3] = (dev_proc(dev, get_color_comp_index))\
663                              (dev, "Black", strlen("Black"), NO_COMP_NAME_TYPE);
664             nz_comps = 0;
665             one = 1;
666             colorant_ok = true;
667             for (k = 0; k < 4; k++) {
668                 if (pdc->ccolor.paint.values[k] != 0) {
669                     if (num_colorant[k] == -1) {
670                         colorant_ok = false;
671                     } else {
672                         temp = one << num_colorant[k];
673                         nz_comps = nz_comps | temp;
674                     }
675                 }
676             }
677             /* For some reason we don't have one of the standard colorants */
678             if (!colorant_ok) {
679                 if ((code = procp(pdc, dev, &nz_comps)) < 0)
680                     return code;
681             }
682         } else {
683             if ((code = procp(pdc, dev, &nz_comps)) < 0)
684                 return code;
685         }
686         drawn_comps &= nz_comps;
687     }
688     params.retain_any_comps = true;
689     params.retain_spot_comps = false;
690     params.drawn_comps = drawn_comps;
691     params.k_value = 0;
692     return gs_state_update_overprint(pgs, &params);
693 }
694 
695 /* This is used for the case where we have an RGB based device, but we want
696    to simulate CMY overprinting.  Color management is pretty much thrown out
697    the window when doing this. */
698 
gx_set_overprint_rgb(const gs_color_space * pcs,gs_state * pgs)699 int gx_set_overprint_rgb(const gs_color_space * pcs, gs_state * pgs)
700 {
701     gx_device *             dev = pgs->device;
702     gx_device_color_info *  pcinfo = (dev == 0 ? 0 : &dev->color_info);
703     gx_color_index          drawn_comps = 0;
704     gs_overprint_params_t   params;
705     gx_device_color        *pdc;
706 
707     /* check if color model behavior must be determined.  This is why we
708        need the GX_CINFO_OPMODE_RGB and GX_CINFO_OPMODE_RGB_SET.
709        We only need to do this once */
710     if (pcinfo->opmode == GX_CINFO_OPMODE_RGB)
711         drawn_comps = check_rgb_color_model_comps(dev);
712     else
713         drawn_comps = pcinfo->process_comps;
714     if (drawn_comps == 0)
715         return gx_spot_colors_set_overprint(pcs, pgs);
716 
717     /* correct for any zero'ed color components.  Note that matching of
718        ICC profiles as a condition is not possible here, since the source
719        will be CMYK and the destination RGB */
720     pgs->effective_overprint_mode = 1;
721     pdc = gs_currentdevicecolor_inline(pgs);
722     params.k_value = 0;
723     if (color_is_set(pdc)) {
724         gx_color_index  nz_comps, one, temp;
725         int             code;
726         int             num_colorant[3], k;
727         bool            colorant_ok;
728 
729         dev_color_proc_get_nonzero_comps((*procp));
730 
731         procp = pdc->type->get_nonzero_comps;
732         if (pdc->ccolor_valid) {
733             /* If we have the source colors, then use those in making the
734                decision as to which ones are non-zero.  Then we avoid
735                accidently looking at small values that get quantized to zero
736                Note that to get here in the code, the source color data color
737                space has to be CMYK. Trick is that we do need to worry about
738                the RGB colorant order on the target device */
739             num_colorant[0] = (dev_proc(dev, get_color_comp_index))\
740                              (dev, "Red", strlen("Red"), NO_COMP_NAME_TYPE);
741             num_colorant[1] = (dev_proc(dev, get_color_comp_index))\
742                              (dev, "Green", strlen("Green"), NO_COMP_NAME_TYPE);
743             num_colorant[2] = (dev_proc(dev, get_color_comp_index))\
744                              (dev, "Blue", strlen("Blue"), NO_COMP_NAME_TYPE);
745             nz_comps = 0;
746             one = 1;
747             colorant_ok = true;
748             for (k = 0; k < 3; k++) {
749                 if (pdc->ccolor.paint.values[k] != 0) {
750                     if (num_colorant[k] == -1) {
751                         colorant_ok = false;
752                     } else {
753                         temp = one << num_colorant[k];
754                         nz_comps = nz_comps | temp;
755                     }
756                 }
757             }
758             /* Check for the case where we have a K component.  In this case
759                we need to fudge things a bit.  And we will end up needing
760                to do some special stuff in the overprint compositor's rect
761                fill to reduce the destination RGB values of the ones
762                that we are not blowing away with the source values.  Those
763                that have the source value will have already been reduced */
764             params.k_value = (unsigned short) (pdc->ccolor.paint.values[3] * 256);
765             /* For some reason we don't have one of the standard colorants */
766             if (!colorant_ok) {
767                 if ((code = procp(pdc, dev, &nz_comps)) < 0)
768                     return code;
769             }
770         } else {
771             if ((code = procp(pdc, dev, &nz_comps)) < 0)
772                 return code;
773         }
774         drawn_comps &= nz_comps;
775     }
776     params.retain_any_comps = true;
777     params.retain_spot_comps = false;
778     params.drawn_comps = drawn_comps;
779     return gs_state_update_overprint(pgs, &params);
780 }
781 
782 /* A stub for a color mapping linearity check, when it is inapplicable. */
783 int
gx_cspace_no_linear(const gs_color_space * cs,const gs_imager_state * pis,gx_device * dev,const gs_client_color * c0,const gs_client_color * c1,const gs_client_color * c2,const gs_client_color * c3,float smoothness,gsicc_link_t * icclink)784 gx_cspace_no_linear(const gs_color_space *cs, const gs_imager_state * pis,
785                 gx_device * dev,
786                 const gs_client_color *c0, const gs_client_color *c1,
787                 const gs_client_color *c2, const gs_client_color *c3,
788                 float smoothness, gsicc_link_t *icclink)
789 {
790     return_error(gs_error_rangecheck);
791 }
792 
793 static inline int
cc2dc(const gs_color_space * cs,const gs_imager_state * pis,gx_device * dev,gx_device_color * dc,const gs_client_color * cc)794 cc2dc(const gs_color_space *cs, const gs_imager_state * pis, gx_device *dev,
795             gx_device_color *dc, const gs_client_color *cc)
796 {
797     return cs->type->remap_color(cc, cs, dc, pis, dev, gs_color_select_texture);
798 }
799 
800 static inline void
interpolate_cc(gs_client_color * c,const gs_client_color * c0,const gs_client_color * c1,double t,int n)801 interpolate_cc(gs_client_color *c,
802         const gs_client_color *c0, const gs_client_color *c1, double t, int n)
803 {
804     int i;
805 
806     for (i = 0; i < n; i++)
807         c->paint.values[i] = c0->paint.values[i] * t + c1->paint.values[i] * (1 - t);
808 }
809 
810 static inline bool
is_dc_nearly_linear(const gx_device * dev,const gx_device_color * c,const gx_device_color * c0,const gx_device_color * c1,double t,int n,float smoothness)811 is_dc_nearly_linear(const gx_device *dev, const gx_device_color *c,
812         const gx_device_color *c0, const gx_device_color *c1,
813         double t, int n, float smoothness)
814 {
815 
816     if (c0->type == &gx_dc_type_data_pure) {
817         int i;
818         gx_color_index pure0 = c0->colors.pure;
819         gx_color_index pure1 = c1->colors.pure;
820         gx_color_index pure = c->colors.pure;
821 
822         for (i = 0; i < n; i++) {
823             int shift = dev->color_info.comp_shift[i];
824             int mask = (1 << dev->color_info.comp_bits[i]) - 1;
825             int max_color = (i == dev->color_info.gray_index ? dev->color_info.max_gray
826                                                              : dev->color_info.max_color);
827             float max_diff = max(1, max_color * smoothness);
828             int b0 = (pure0 >> shift) & mask, b1 = (pure1 >> shift) & mask;
829             int b = (pure >> shift) & mask;
830             double bb = b0 * t + b1 * (1 - t);
831 
832             if (any_abs(b - bb) > max_diff)
833                 return false;
834         }
835         return true;
836     } else {
837         /* Halftones must not paint with fill_linear_color_*. */
838         return false;
839     }
840 }
841 
842 /* Default color mapping linearity check, a 2-points case. */
843 static int
gx_cspace_is_linear_in_line(const gs_color_space * cs,const gs_imager_state * pis,gx_device * dev,const gs_client_color * c0,const gs_client_color * c1,float smoothness)844 gx_cspace_is_linear_in_line(const gs_color_space *cs, const gs_imager_state * pis,
845                 gx_device *dev,
846                 const gs_client_color *c0, const gs_client_color *c1,
847                 float smoothness)
848 {
849     gs_client_color c01a, c01b;
850     gx_device_color d[2], d01a, d01b;
851     int n = cs->type->num_components(cs);
852     int ndev = dev->color_info.num_components;
853     int code;
854 
855     code = cc2dc(cs, pis, dev, &d[0], c0);
856     if (code < 0)
857         return code;
858     code = cc2dc(cs, pis, dev, &d[1], c1);
859     if (code < 0)
860         return code;
861     interpolate_cc(&c01a, c0, c1, 0.3, n);
862     code = cc2dc(cs, pis, dev, &d01a, &c01a);
863     if (code < 0)
864         return code;
865     if (!is_dc_nearly_linear(dev, &d01a, &d[0], &d[1], 0.3, ndev, smoothness))
866         return 0;
867     interpolate_cc(&c01b, c0, c1, 0.7, n);
868     code = cc2dc(cs, pis, dev, &d01b, &c01b);
869     if (code < 0)
870         return code;
871     if (!is_dc_nearly_linear(dev, &d01b, &d[0], &d[1], 0.7, ndev, smoothness))
872         return 0;
873     return 1;
874 }
875 
876 /* Default color mapping linearity check, a triangle case. */
877 static int
gx_cspace_is_linear_in_triangle(const gs_color_space * cs,const gs_imager_state * pis,gx_device * dev,const gs_client_color * c0,const gs_client_color * c1,const gs_client_color * c2,float smoothness)878 gx_cspace_is_linear_in_triangle(const gs_color_space *cs, const gs_imager_state * pis,
879                 gx_device *dev,
880                 const gs_client_color *c0, const gs_client_color *c1,
881                 const gs_client_color *c2, float smoothness)
882 {
883     /* We check 4 points - the median center, and middle points of 3 sides.
884        Hopely this is enough for reasonable color spaces and color renderings.
885        Note it gives 7 points for a quadrangle. */
886     gs_client_color c01, c12, c20, c012;
887     gx_device_color d[3], d01, d12, d20, d012;
888 
889     /* Note that the device and the client color space
890        can have a different number of components */
891 
892     int n = cs->type->num_components(cs);
893     int ndev = dev->color_info.num_components;
894 
895     int code;
896 
897     code = cc2dc(cs, pis, dev, &d[0], c0);
898     if (code < 0)
899         return code;
900     code = cc2dc(cs, pis, dev, &d[1], c1);
901     if (code < 0)
902         return code;
903     code = cc2dc(cs, pis, dev, &d[2], c2);
904     if (code < 0)
905         return code;
906 
907     interpolate_cc(&c01, c0, c1, 0.5, n);
908     code = cc2dc(cs, pis, dev, &d01, &c01);
909     if (code < 0)
910         return code;
911     if (!is_dc_nearly_linear(dev, &d01, &d[0], &d[1], 0.5, ndev, smoothness))
912         return 0;
913 
914     interpolate_cc(&c012, c2, &c01, 2.0 / 3, n);
915     code = cc2dc(cs, pis, dev, &d012, &c012);
916     if (code < 0)
917         return code;
918     if (!is_dc_nearly_linear(dev, &d012, &d[2], &d01, 2.0 / 3, ndev, smoothness))
919         return 0;
920 
921     interpolate_cc(&c12, c1, c2, 0.5, n);
922     code = cc2dc(cs, pis, dev, &d12, &c12);
923     if (code < 0)
924         return code;
925     if (!is_dc_nearly_linear(dev, &d12, &d[1], &d[2], 0.5, ndev, smoothness))
926         return 0;
927 
928     interpolate_cc(&c20, c2, c0, 0.5, n);
929     code = cc2dc(cs, pis, dev, &d20, &c20);
930     if (code < 0)
931         return code;
932     if (!is_dc_nearly_linear(dev, &d20, &d[2], &d[0], 0.5, ndev, smoothness))
933         return 0;
934     return 1;
935 }
936 
937 /* Default color mapping linearity check. */
938 int
gx_cspace_is_linear_default(const gs_color_space * cs,const gs_imager_state * pis,gx_device * dev,const gs_client_color * c0,const gs_client_color * c1,const gs_client_color * c2,const gs_client_color * c3,float smoothness,gsicc_link_t * icclink)939 gx_cspace_is_linear_default(const gs_color_space *cs, const gs_imager_state * pis,
940                 gx_device *dev,
941                 const gs_client_color *c0, const gs_client_color *c1,
942                 const gs_client_color *c2, const gs_client_color *c3,
943                 float smoothness, gsicc_link_t *icclink)
944 {
945     /* Assuming 2 <= nc <= 4. We don't need other cases. */
946     /* With nc == 4 assuming a convex plain quadrangle in the client color space. */
947     int code;
948 
949     if (dev->color_info.separable_and_linear != GX_CINFO_SEP_LIN)
950         return_error(gs_error_rangecheck);
951     if (c2 == NULL)
952         return gx_cspace_is_linear_in_line(cs, pis, dev, c0, c1, smoothness);
953     code = gx_cspace_is_linear_in_triangle(cs, pis, dev, c0, c1, c2, smoothness);
954     if (code <= 0)
955         return code;
956     if (c3 == NULL)
957         return 1;
958     return gx_cspace_is_linear_in_triangle(cs, pis, dev, c1, c2, c3, smoothness);
959 }
960 
961 /* Serialization. */
962 int
gx_serialize_cspace_type(const gs_color_space * pcs,stream * s)963 gx_serialize_cspace_type(const gs_color_space * pcs, stream * s)
964 {
965     const gs_color_space_type * type = pcs->type;
966     uint n;
967     return sputs(s, (const byte *)&type->index, sizeof(type->index), &n);
968 }
969 
970 /* GC procedures */
971 
972 static
ENUM_PTRS_BEGIN_PROC(color_space_enum_ptrs)973 ENUM_PTRS_BEGIN_PROC(color_space_enum_ptrs)
974 {
975     EV_CONST gs_color_space *pcs = vptr;
976 
977     if (index == 0)
978         return ENUM_OBJ(pcs->base_space);
979     if (index == 1)
980         return ENUM_OBJ(pcs->pclient_color_space_data);
981     if (index == 2)
982         return ENUM_OBJ(pcs->icc_equivalent);
983     return ENUM_USING(*pcs->type->stype, vptr, size, index - 3);
984     ENUM_PTRS_END_PROC
985 }
986 static
RELOC_PTRS_WITH(color_space_reloc_ptrs,gs_color_space * pcs)987 RELOC_PTRS_WITH(color_space_reloc_ptrs, gs_color_space *pcs)
988 {
989     RELOC_VAR(pcs->base_space);
990     RELOC_VAR(pcs->pclient_color_space_data);
991     RELOC_VAR(pcs->icc_equivalent);
992     RELOC_USING(*pcs->type->stype, vptr, size);
993 }
994 RELOC_PTRS_END
995