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, ¶ms);
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, ¶ms);
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, ¶ms);
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