Coverage Report

Created: 2022-04-16 11:23

/src/ghostpdl/base/gscspace.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2001-2021 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.,  1305 Grant Avenue - Suite 200, Novato,
13
   CA 94945, 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 "gxgstate.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
#include "string_.h"
37
#include "strmio.h"         /* needed for sfclose */
38
#include "gsicc_cache.h"    /* Needed for gsicc_get_icc_buff_hash */
39
40
static cs_proc_install_cspace(gx_install_DeviceGray);
41
static cs_proc_install_cspace(gx_install_DeviceRGB);
42
static cs_proc_install_cspace(gx_install_DeviceCMYK);
43
/*
44
 * Define the standard color space types.  We include DeviceCMYK in the base
45
 * build because it's too awkward to omit it, but we don't provide any of
46
 * the PostScript operator procedures (setcmykcolor, etc.) for dealing with
47
 * it.
48
 */
49
static const gs_color_space_type gs_color_space_type_DeviceGray = {
50
    gs_color_space_index_DeviceGray, true, true,
51
    &st_base_color_space, gx_num_components_1,
52
    gx_init_paint_1, gx_restrict01_paint_1,
53
    gx_same_concrete_space,
54
    gx_concretize_DeviceGray, gx_remap_concrete_DGray,
55
    gx_remap_DeviceGray, gx_install_DeviceGray,
56
    gx_spot_colors_set_overprint,
57
    NULL, gx_no_adjust_color_count,
58
    gx_serialize_cspace_type,
59
    gx_cspace_is_linear_default, gx_polarity_additive
60
};
61
static const gs_color_space_type gs_color_space_type_DeviceRGB = {
62
    gs_color_space_index_DeviceRGB, true, true,
63
    &st_base_color_space, gx_num_components_3,
64
    gx_init_paint_3, gx_restrict01_paint_3,
65
    gx_same_concrete_space,
66
    gx_concretize_DeviceRGB, gx_remap_concrete_DRGB,
67
    gx_remap_DeviceRGB, gx_install_DeviceRGB,
68
    gx_spot_colors_set_overprint,
69
    NULL, gx_no_adjust_color_count,
70
    gx_serialize_cspace_type,
71
    gx_cspace_is_linear_default, gx_polarity_additive
72
};
73
74
static cs_proc_set_overprint(gx_set_overprint_DeviceCMYK);
75
76
static const gs_color_space_type gs_color_space_type_DeviceCMYK = {
77
    gs_color_space_index_DeviceCMYK, true, true,
78
    &st_base_color_space, gx_num_components_4,
79
    gx_init_paint_4, gx_restrict01_paint_4,
80
    gx_same_concrete_space,
81
    gx_concretize_DeviceCMYK, gx_remap_concrete_DCMYK,
82
    gx_remap_DeviceCMYK, gx_install_DeviceCMYK,
83
    gx_set_overprint_DeviceCMYK,
84
    NULL, gx_no_adjust_color_count,
85
    gx_serialize_cspace_type,
86
    gx_cspace_is_linear_default, gx_polarity_subtractive
87
};
88
89
/* Structure descriptors */
90
public_st_color_space();
91
public_st_base_color_space();
92
93
/* ------ Create/copy/destroy ------ */
94
95
/* Ghostscript object finalizers can be called many times and hence
96
 * must be idempotent. */
97
static void
98
gs_cspace_final(const gs_memory_t *cmem, void *vptr)
99
642k
{
100
642k
    gs_color_space *pcs = (gs_color_space *)vptr;
101
642k
    (void)cmem; /* unused */
102
103
642k
    if (pcs->interpreter_free_cspace_proc != NULL) {
104
54.8k
        (*pcs->interpreter_free_cspace_proc) ((gs_memory_t *)cmem, pcs);
105
54.8k
        pcs->interpreter_free_cspace_proc = NULL;
106
54.8k
    }
107
642k
    if (pcs->type->final)
108
355k
        pcs->type->final(pcs);
109
642k
    if_debug2m('c', cmem, "[c]cspace final "PRI_INTPTR" %d\n", (intptr_t)pcs, (int)pcs->id);
110
642k
    rc_decrement_only_cs(pcs->base_space, "gs_cspace_final");
111
642k
    pcs->base_space = NULL;
112
642k
    if (pcs->params.device_n.devn_process_space != NULL) {
113
0
        rc_decrement_only_cs(pcs->params.device_n.devn_process_space, "gs_cspace_final");
114
0
        pcs->params.device_n.devn_process_space = NULL;
115
0
    }
116
    /* No need to decrement the ICC profile data.  It is handled
117
       by the finalize of the ICC space which is called above using
118
       pcs->type->final(pcs);  */
119
642k
}
120
121
static gs_color_space *
122
gs_cspace_alloc_with_id(gs_memory_t *mem, ulong id,
123
                   const gs_color_space_type *pcstype)
124
642k
{
125
642k
    gs_color_space *pcs;
126
127
642k
    rc_alloc_struct_1(pcs, gs_color_space, &st_color_space, mem, return NULL,
128
642k
                      "gs_cspace_alloc_with_id");
129
642k
    if_debug3m('c', mem, "[c]cspace alloc "PRI_INTPTR" %s %d\n",
130
642k
               (intptr_t)pcs, pcstype->stype->sname, pcstype->index);
131
642k
    pcs->type = pcstype;
132
642k
    pcs->id = id;
133
642k
    pcs->base_space = NULL;
134
642k
    pcs->pclient_color_space_data = NULL;
135
642k
    pcs->interpreter_data = NULL;
136
642k
    pcs->interpreter_free_cspace_proc = NULL;
137
642k
    pcs->cmm_icc_profile_data = NULL;
138
642k
    pcs->icc_equivalent = NULL;
139
642k
    pcs->params.device_n.devn_process_space = NULL;
140
642k
    return pcs;
141
642k
}
142
143
static cs_proc_install_cspace(gx_install_DeviceGray);
144
static cs_proc_install_cspace(gx_install_DeviceRGB);
145
static cs_proc_install_cspace(gx_install_DeviceCMYK);
146
147
/*
148
 * Generic allocation function for colorspace implementations. Return
149
 * NULL on allocation failure.
150
 */
151
gs_color_space *
152
gs_cspace_alloc(gs_memory_t *mem, const gs_color_space_type *pcstype)
153
67.3k
{
154
67.3k
    return gs_cspace_alloc_with_id(mem, gs_next_ids(mem, 1), pcstype);
155
67.3k
}
156
157
/* Constructors for simple device color spaces. */
158
159
gs_color_space *
160
gs_cspace_new_DeviceGray(gs_memory_t *mem)
161
371k
{
162
371k
    return gs_cspace_alloc_with_id(mem, cs_DeviceGray_id,
163
371k
                                   &gs_color_space_type_DeviceGray);
164
371k
}
165
166
gs_color_space *
167
gs_cspace_new_DeviceRGB(gs_memory_t *mem)
168
139k
{
169
139k
    return gs_cspace_alloc_with_id(mem, cs_DeviceRGB_id,
170
139k
                                   &gs_color_space_type_DeviceRGB);
171
139k
}
172
gs_color_space *
173
gs_cspace_new_DeviceCMYK(gs_memory_t *mem)
174
63.1k
{
175
63.1k
    return gs_cspace_alloc_with_id(mem, cs_DeviceCMYK_id,
176
63.1k
                                   &gs_color_space_type_DeviceCMYK);
177
63.1k
}
178
179
/* For use in initializing ICC color spaces for XPS */
180
gs_color_space *
181
gs_cspace_new_scrgb(gs_memory_t *pmem, gs_gstate * pgs)
182
0
{
183
0
    gs_color_space *pcspace = gs_cspace_alloc(pmem, &gs_color_space_type_ICC);
184
0
    cmm_profile_t *profile;
185
0
    stream *str;
186
0
    int code;
187
188
0
    if (pcspace == NULL)
189
0
        return pcspace;
190
191
0
    code = gsicc_open_search(SCRGB, strlen(SCRGB), pmem, pmem->gs_lib_ctx->profiledir,
192
0
        pmem->gs_lib_ctx->profiledir_len, &str);
193
194
0
    if (code < 0 || str == NULL) {
195
0
        rc_decrement(pcspace, "gs_cspace_new_scrgb");
196
0
        return NULL;
197
0
    }
198
199
0
    pcspace->cmm_icc_profile_data = gsicc_profile_new(str, pmem, SCRGB, strlen(SCRGB));
200
0
    code = sfclose(str);
201
0
    if (pcspace->cmm_icc_profile_data == NULL) {
202
0
        rc_decrement(pcspace, "gs_cspace_new_scrgb");
203
0
        return NULL;
204
0
    }
205
206
    /* Get the profile handle */
207
0
    pcspace->cmm_icc_profile_data->profile_handle =
208
0
        gsicc_get_profile_handle_buffer(pcspace->cmm_icc_profile_data->buffer,
209
0
            pcspace->cmm_icc_profile_data->buffer_size, pmem);
210
0
    if (!pcspace->cmm_icc_profile_data->profile_handle) {
211
0
        rc_decrement(pcspace, "gs_cspace_new_scrgb");
212
0
        return NULL;
213
0
    }
214
0
    profile = pcspace->cmm_icc_profile_data;
215
216
    /* Compute the hash code of the profile. Everything in the
217
    ICC manager will have it's hash code precomputed */
218
0
    gsicc_get_icc_buff_hash(profile->buffer, &(profile->hashcode),
219
0
        profile->buffer_size);
220
0
    profile->hash_is_valid = true;
221
0
    profile->num_comps =
222
0
        gscms_get_input_channel_count(profile->profile_handle, profile->memory);
223
0
    profile->num_comps_out =
224
0
        gscms_get_output_channel_count(profile->profile_handle, profile->memory);
225
0
    profile->data_cs =
226
0
        gscms_get_profile_data_space(profile->profile_handle, profile->memory);
227
0
    gsicc_set_icc_range(&profile);
228
0
    return pcspace;
229
0
}
230
231
gs_color_space *
232
gs_cspace_new_ICC(gs_memory_t *pmem, gs_gstate * pgs, int components)
233
10.0k
{
234
10.0k
    gsicc_manager_t *icc_manage = pgs->icc_manager;
235
10.0k
    int code = 0;
236
10.0k
    gs_color_space *pcspace = gs_cspace_alloc(pmem, &gs_color_space_type_ICC);
237
238
10.0k
    if (pcspace == NULL)
239
0
        return pcspace;
240
241
10.0k
    switch (components) {
242
0
        case -1: /* alpha case */
243
0
            if (icc_manage->smask_profiles == NULL) {
244
0
                code = gsicc_initialize_iccsmask(icc_manage);
245
0
            }
246
0
            if (code == 0) {
247
0
                pcspace->cmm_icc_profile_data =
248
0
                    icc_manage->smask_profiles->smask_gray;
249
0
            } else {
250
0
                pcspace->cmm_icc_profile_data = icc_manage->default_gray;
251
0
            }
252
0
            break;
253
0
        case -3: /* alpha case.  needs linear RGB */
254
0
            if (icc_manage->smask_profiles == NULL) {
255
0
                code = gsicc_initialize_iccsmask(icc_manage);
256
0
            }
257
0
            if (code == 0) {
258
0
                pcspace->cmm_icc_profile_data =
259
0
                    icc_manage->smask_profiles->smask_rgb;
260
0
            } else {
261
0
                pcspace->cmm_icc_profile_data = icc_manage->default_rgb;
262
0
            }
263
0
            break;
264
10.0k
        case 1: pcspace->cmm_icc_profile_data = icc_manage->default_gray; break;
265
0
        case 3: pcspace->cmm_icc_profile_data = icc_manage->default_rgb; break;
266
0
        case 4: pcspace->cmm_icc_profile_data = icc_manage->default_cmyk; break;
267
0
        default: rc_decrement(pcspace,"gs_cspace_new_ICC"); return NULL;
268
10.0k
    }
269
10.0k
    gsicc_adjust_profile_rc(pcspace->cmm_icc_profile_data, 1, "gs_cspace_new_ICC");
270
10.0k
    return pcspace;
271
10.0k
}
272
273
/* ------ Accessors ------ */
274
275
/* Get the index of a color space. */
276
gs_color_space_index
277
gs_color_space_get_index(const gs_color_space * pcs)
278
952k
{
279
952k
    return pcs->type->index;
280
952k
}
281
282
/* See if the space is CIE based */
283
bool gs_color_space_is_CIE(const gs_color_space * pcs)
284
4.36k
{
285
4.36k
    switch(gs_color_space_get_index(pcs)){
286
0
        case gs_color_space_index_CIEDEFG:
287
0
        case gs_color_space_index_CIEDEF:
288
0
        case gs_color_space_index_CIEABC:
289
0
        case gs_color_space_index_CIEA:
290
4.36k
        case gs_color_space_index_ICC:
291
4.36k
            return true;
292
0
        break;
293
0
        default:
294
0
            return false;
295
4.36k
    }
296
4.36k
}
297
298
/* See if the space is Postscript CIE based */
299
bool gs_color_space_is_PSCIE(const gs_color_space * pcs)
300
281k
{
301
281k
    switch(gs_color_space_get_index(pcs)){
302
0
        case gs_color_space_index_CIEDEFG:
303
0
        case gs_color_space_index_CIEDEF:
304
0
        case gs_color_space_index_CIEABC:
305
0
        case gs_color_space_index_CIEA:
306
0
            return true;
307
0
        break;
308
281k
        default:
309
281k
            return false;
310
281k
}
311
281k
}
312
313
/* See if the space is ICC based */
314
bool gs_color_space_is_ICC(const gs_color_space * pcs)
315
425k
{
316
425k
    return(gs_color_space_get_index(pcs) == gs_color_space_index_ICC);
317
425k
}
318
319
/* Get the number of components in a color space. */
320
int
321
gs_color_space_num_components(const gs_color_space * pcs)
322
115k
{
323
115k
    return cs_num_components(pcs);
324
115k
}
325
326
/* Restrict a color to its legal range. */
327
void
328
gs_color_space_restrict_color(gs_client_color *pcc, const gs_color_space *pcs)
329
0
{
330
0
    cs_restrict_color(pcc, pcs);
331
0
}
332
333
/* Install a DeviceGray color space. */
334
static int
335
gx_install_DeviceGray(gs_color_space * pcs, gs_gstate * pgs)
336
265k
{
337
    /* If we already have profile data installed, nothing to do here. */
338
265k
    if (pcs->cmm_icc_profile_data != NULL)
339
0
        return 0;
340
341
    /* If we haven't initialised the iccmanager, do it now. */
342
265k
    if (pgs->icc_manager->default_gray == NULL) {
343
56.5k
        int code = gsicc_init_iccmanager(pgs);
344
56.5k
        if (code < 0)
345
3
            return code;
346
56.5k
    }
347
348
    /* pcs takes a reference to the default_gray profile data */
349
265k
    pcs->cmm_icc_profile_data = pgs->icc_manager->default_gray;
350
265k
    gsicc_adjust_profile_rc(pgs->icc_manager->default_gray, 1, "gx_install_DeviceGray");
351
265k
    pcs->type = &gs_color_space_type_ICC;
352
265k
    return 0;
353
265k
}
354
355
int
356
gx_num_components_1(const gs_color_space * pcs)
357
147k
{
358
147k
    return 1;
359
147k
}
360
int
361
gx_num_components_3(const gs_color_space * pcs)
362
0
{
363
0
    return 3;
364
0
}
365
int
366
gx_num_components_4(const gs_color_space * pcs)
367
0
{
368
0
    return 4;
369
0
}
370
371
gx_color_polarity_t
372
gx_polarity_subtractive(const gs_color_space * pcs)
373
0
{
374
0
    return GX_CINFO_POLARITY_SUBTRACTIVE;
375
0
}
376
377
gx_color_polarity_t
378
gx_polarity_additive(const gs_color_space * pcs)
379
0
{
380
0
    return GX_CINFO_POLARITY_ADDITIVE;
381
0
}
382
383
gx_color_polarity_t
384
gx_polarity_unknown(const gs_color_space * pcs)
385
0
{
386
0
    return GX_CINFO_POLARITY_UNKNOWN;
387
0
}
388
389
/*
390
 * For color spaces that have a base or alternative color space, return that
391
 * color space. Otherwise return null.
392
 */
393
const gs_color_space *
394
gs_cspace_base_space(const gs_color_space * pcspace)
395
1.15k
{
396
1.15k
    return pcspace->base_space;
397
1.15k
}
398
399
const gs_color_space *
400
gs_cspace_devn_process_space(const gs_color_space * pcspace)
401
0
{
402
0
    return pcspace->params.device_n.devn_process_space;
403
0
}
404
405
/* Abstract the reference counting for color spaces
406
   so that we can also increment the ICC profile
407
   if there is one associated with the color space */
408
409
void rc_increment_cs(gs_color_space *pcs)
410
360k
{
411
360k
    rc_increment(pcs);
412
360k
}
413
414
132k
void rc_decrement_cs(gs_color_space *pcs, const char *cname) {
415
416
132k
    if (pcs) {
417
132k
        rc_decrement(pcs, cname);
418
132k
    }
419
132k
}
420
421
void rc_decrement_only_cs(gs_color_space *pcs, const char *cname)
422
1.23M
{
423
1.23M
    if (pcs) {
424
592k
        rc_decrement_only(pcs, cname);
425
592k
    }
426
1.23M
}
427
428
void cs_adjust_counts_icc(gs_gstate *pgs, int delta)
429
2.32M
{
430
2.32M
    gs_color_space *pcs = gs_currentcolorspace_inline(pgs);
431
432
2.32M
    if (pcs) {
433
1.55M
        cs_adjust_color_count(pgs, delta);
434
1.55M
        rc_adjust_const(pcs, delta, "cs_adjust_counts_icc");
435
1.55M
    }
436
2.32M
}
437
438
void cs_adjust_swappedcounts_icc(gs_gstate *pgs, int delta)
439
2.32M
{
440
2.32M
    gs_color_space *pcs = gs_swappedcolorspace_inline(pgs);
441
442
2.32M
    if (pcs) {
443
1.55M
        cs_adjust_swappedcolor_count(pgs, delta);
444
1.55M
        rc_adjust_const(pcs, delta, "cs_adjust_swappedcounts_icc");
445
1.55M
    }
446
2.32M
}
447
448
/* ------ Other implementation procedures ------ */
449
450
/* Null color space installation procedure. */
451
int
452
gx_no_install_cspace(gs_color_space * pcs, gs_gstate * pgs)
453
0
{
454
0
    return 0;
455
0
}
456
457
/* Install a DeviceRGB color space. */
458
static int
459
gx_install_DeviceRGB(gs_color_space * pcs, gs_gstate * pgs)
460
18.0k
{
461
    /* If we already have profile_data, nothing to do here. */
462
18.0k
    if (pcs->cmm_icc_profile_data != NULL)
463
0
        return 0;
464
465
    /* If the icc manager hasn't been set up yet, then set it up. */
466
18.0k
    if (pgs->icc_manager->default_rgb == NULL)
467
0
        gsicc_init_iccmanager(pgs);
468
469
    /* pcs takes a reference to default_rgb */
470
18.0k
    pcs->cmm_icc_profile_data = pgs->icc_manager->default_rgb;
471
18.0k
    gsicc_adjust_profile_rc(pcs->cmm_icc_profile_data, 1, "gx_install_DeviceRGB");
472
18.0k
    pcs->type = &gs_color_space_type_ICC;
473
18.0k
    return 0;
474
18.0k
}
475
476
/* Install a DeviceCMYK color space. */
477
static int
478
gx_install_DeviceCMYK(gs_color_space * pcs, gs_gstate * pgs)
479
4.00k
{
480
    /* If we already have profile data, nothing to do here. */
481
4.00k
    if (pcs->cmm_icc_profile_data != NULL)
482
0
        return 0;
483
484
    /* If the icc manager hasn't been set up yet, then set it up. */
485
4.00k
    if (pgs->icc_manager->default_cmyk == NULL)
486
0
        gsicc_init_iccmanager(pgs);
487
488
    /* pcs takes a reference to default_cmyk */
489
4.00k
    pcs->cmm_icc_profile_data = pgs->icc_manager->default_cmyk;
490
4.00k
    gsicc_adjust_profile_rc(pcs->cmm_icc_profile_data, 1, "gx_install_DeviceCMYK");
491
4.00k
    pcs->type = &gs_color_space_type_ICC;
492
4.00k
    return 0;
493
4.00k
}
494
495
/*
496
 * Communicate to the overprint compositor that this particular
497
 * state overprint is not enabled.  This could be due to a
498
 * mismatched color space, or that overprint is false or the
499
 * device does not support it.
500
 */
501
int
502
gx_set_no_overprint(gs_gstate* pgs)
503
82
{
504
82
    gs_overprint_params_t   params = { 0 };
505
506
82
    params.retain_any_comps = false;
507
82
    params.op_state = OP_STATE_NONE;
508
82
    params.is_fill_color = pgs->is_fill_color;
509
82
    params.effective_opm = pgs->color[0].effective_opm = 0;
510
511
82
    return gs_gstate_update_overprint(pgs, &params);
512
82
}
513
514
/* Retain all the spot colorants and not the process
515
   colorants.  This occurs if we have a process color
516
   mismatch between the source and the destination but
517
   the output device supports spot colors */
518
int
519
gx_set_spot_only_overprint(gs_gstate* pgs)
520
0
{
521
0
    gs_overprint_params_t   params = { 0 };
522
0
    gx_device* dev = pgs->device;
523
0
    gx_color_index drawn_comps = dev == NULL ? 0 : gx_get_process_comps(dev);
524
525
0
    params.retain_any_comps = true;
526
0
    params.op_state = OP_STATE_NONE;
527
0
    params.is_fill_color = pgs->is_fill_color;
528
0
    params.effective_opm = pgs->color[0].effective_opm = 0;
529
0
    params.drawn_comps = drawn_comps;
530
531
0
    return gs_gstate_update_overprint(pgs, &params);
532
0
}
533
534
/*
535
 * Push an overprint compositor onto the current device indicating that,
536
 * at most, the spot color parameters are to be preserved.
537
 *
538
 * This routine should be used for all Device, CIEBased, and ICCBased
539
 * color spaces, except for DeviceCMKY.
540
 */
541
int
542
gx_spot_colors_set_overprint(const gs_color_space * pcs, gs_gstate * pgs)
543
0
{
544
0
    gs_overprint_params_t   params = {0};
545
0
    bool op = pgs->is_fill_color ? pgs->overprint : pgs->stroke_overprint;
546
547
0
    if (!op)
548
0
        params.retain_any_comps = false;
549
0
    else
550
0
        params.retain_any_comps = true;
551
552
0
    params.is_fill_color = pgs->is_fill_color;
553
0
    params.op_state = OP_STATE_NONE;
554
555
    /* Only DeviceCMYK case can have overprint mode set to true */
556
0
    params.effective_opm = pgs->color[0].effective_opm = 0;
557
0
    return gs_gstate_update_overprint(pgs, &params);
558
0
}
559
560
static bool
561
check_single_comp(int comp, frac targ_val, int ncomps, const frac * pval)
562
0
{
563
0
    int     i;
564
565
0
    for (i = 0; i < ncomps; i++) {
566
0
        if ( (i != comp && pval[i] != frac_0)  ||
567
0
             (i == comp && pval[i] != targ_val)  )
568
0
            return false;
569
0
    }
570
0
    return true;
571
0
}
572
573
/*
574
 * Determine if the current color model is a "DeviceCMYK" color model, and
575
 * if so what are its process color components. This information is required
576
 * when PLRM defines special rules for CMYK devices. This includes:
577
 * 1. DeviceGray to CMYK color conversion
578
 * 2. when overprint is true and overprint mode is set to 1.
579
 *
580
 * A color model is considered a "DeviceCMYK" color model if it supports the
581
 * cyan, magenta, yellow, and black color components, and maps the DeviceCMYK
582
 * color model components directly to these color components. Note that this
583
 * does not require any particular component order, allows for additional
584
 * spot color components, and does admit DeviceN color spaces if they have
585
 * the requisite behavior.
586
 *
587
 * If the color model is a "DeviceCMYK" color model, return the set of
588
 * process color components; otherwise return 0.
589
 */
590
gx_color_index
591
check_cmyk_color_model_comps(gx_device * dev)
592
13
{
593
13
    gx_device_color_info *          pcinfo = &dev->color_info;
594
13
    uchar                           ncomps = pcinfo->num_components;
595
13
    int                             cyan_c, magenta_c, yellow_c, black_c;
596
13
    frac                            frac_14 = frac_1 / 4;
597
13
    frac                            out[GX_DEVICE_COLOR_MAX_COMPONENTS];
598
13
    gx_color_index                  process_comps;
599
13
    const gx_cm_color_map_procs    *cmprocs;
600
13
    const gx_device                *cmdev;
601
602
603
13
    if (pcinfo->num_components < 4                     ||
604
13
        pcinfo->polarity == GX_CINFO_POLARITY_ADDITIVE ||
605
13
        pcinfo->gray_index == GX_CINFO_COMP_NO_INDEX) {
606
13
        pcinfo->opmsupported = GX_CINFO_OPMSUPPORTED_NOT;
607
13
        return 0;
608
13
    }
609
610
    /* check for the appropriate components */
611
0
    if ( ncomps < 4                                       ||
612
0
         (cyan_c = dev_proc(dev, get_color_comp_index)(
613
0
                       dev,
614
0
                       "Cyan",
615
0
                       sizeof("Cyan") - 1,
616
0
                       NO_COMP_NAME_TYPE_OP)) < 0           ||
617
0
         cyan_c == GX_DEVICE_COLOR_MAX_COMPONENTS         ||
618
0
         (magenta_c = dev_proc(dev, get_color_comp_index)(
619
0
                          dev,
620
0
                          "Magenta",
621
0
                          sizeof("Magenta") - 1,
622
0
                          NO_COMP_NAME_TYPE_OP)) < 0        ||
623
0
         magenta_c == GX_DEVICE_COLOR_MAX_COMPONENTS      ||
624
0
         (yellow_c = dev_proc(dev, get_color_comp_index)(
625
0
                        dev,
626
0
                        "Yellow",
627
0
                        sizeof("Yellow") - 1,
628
0
                        NO_COMP_NAME_TYPE_OP)) < 0               ||
629
0
         yellow_c == GX_DEVICE_COLOR_MAX_COMPONENTS       ||
630
0
         (black_c = dev_proc(dev, get_color_comp_index)(
631
0
                        dev,
632
0
                        "Black",
633
0
                        sizeof("Black") - 1,
634
0
                        NO_COMP_NAME_TYPE_OP)) < 0                         ||
635
0
         black_c == GX_DEVICE_COLOR_MAX_COMPONENTS          )
636
0
        return 0;
637
638
    /* check the mapping */
639
0
    cmprocs = dev_proc(dev, get_color_mapping_procs)(dev, &cmdev);
640
641
0
    cmprocs->map_cmyk(cmdev, frac_14, frac_0, frac_0, frac_0, out);
642
0
    if (!check_single_comp(cyan_c, frac_14, ncomps, out)) {
643
0
        pcinfo->opmsupported = GX_CINFO_OPMSUPPORTED_NOT;
644
0
        return 0;
645
0
    }
646
0
    cmprocs->map_cmyk(cmdev, frac_0, frac_14, frac_0, frac_0, out);
647
0
    if (!check_single_comp(magenta_c, frac_14, ncomps, out)) {
648
0
        pcinfo->opmsupported = GX_CINFO_OPMSUPPORTED_NOT;
649
0
        return 0;
650
0
    }
651
0
    cmprocs->map_cmyk(cmdev, frac_0, frac_0, frac_14, frac_0, out);
652
0
    if (!check_single_comp(yellow_c, frac_14, ncomps, out)) {
653
0
        pcinfo->opmsupported = GX_CINFO_OPMSUPPORTED_NOT;
654
0
        return 0;
655
0
    }
656
0
    cmprocs->map_cmyk(cmdev, frac_0, frac_0, frac_0, frac_14, out);
657
0
    if (!check_single_comp(black_c, frac_14, ncomps, out)) {
658
0
        pcinfo->opmsupported = GX_CINFO_OPMSUPPORTED_NOT;
659
0
        return 0;
660
0
    }
661
662
0
    process_comps =  ((gx_color_index)1 << cyan_c)
663
0
                   | ((gx_color_index)1 << magenta_c)
664
0
                   | ((gx_color_index)1 << yellow_c)
665
0
                   | ((gx_color_index)1 << black_c);
666
0
    pcinfo->opmsupported = GX_CINFO_OPMSUPPORTED;
667
0
    pcinfo->process_comps = process_comps;
668
0
    pcinfo->black_component = black_c;
669
0
    return process_comps;
670
0
}
671
672
/*
673
 * This set_overprint method is unique. If overprint is true, overprint
674
 * mode is set to 1, the process color model has DeviceCMYK behavior (see
675
 * the comment ahead of gx_is_cmyk_color_model above), and the device
676
 * color is set, the device color needs to be considered in setting up
677
 * the set of drawn components.
678
 */
679
static int
680
gx_set_overprint_DeviceCMYK(const gs_color_space * pcs, gs_gstate * pgs)
681
0
{
682
0
    gx_device *             dev = pgs->device;
683
0
    gx_device_color_info *  pcinfo = (dev == 0 ? 0 : &dev->color_info);
684
685
    /* check if we require special handling */
686
0
    if ( !pgs->overprint                      ||
687
0
         pgs->overprint_mode != 1             ||
688
0
         pcinfo == 0                          ||
689
0
         pcinfo->opmsupported == GX_CINFO_OPMSUPPORTED_NOT)
690
0
        return gx_spot_colors_set_overprint(pcs, pgs);
691
    /* Share code with CMYK ICC case */
692
0
    return gx_set_overprint_cmyk(pcs, pgs);
693
0
}
694
695
/* A few comments about ICC profiles and overprint simulation.  In order
696
   to do proper overprint simulation, the source ICC profile and the
697
   destination ICC profile must be the same.  If they are not, then
698
   we end up mapping the source CMYK data to a different CMYK value.  In
699
   this case, the non-zero components, which with overprint mode = 1 specify
700
   which are to be overprinted will not be correct to produce the proper
701
   overprint simulation.  This is seen with AR when doing output preview,
702
   overprint simulation enabled of the file overprint_icc.pdf (see our
703
   test files) which has SWOP ICC based CMYK fills.  In AR, if we use a
704
   simulation ICC profile that is different than the source profile,
705
   overprinting is no longer previewed. We follow the same logic here.
706
   If the source and destination ICC profiles do not match, then there is
707
   effectively no overprinting enabled.  This is bug 692433.  However,
708
   even with the mismatch, if the device supports spot colorants, those
709
   colors should be maintained. This is bug 702725. */
710
int gx_set_overprint_cmyk(const gs_color_space * pcs, gs_gstate * pgs)
711
0
{
712
0
    gx_device *             dev = pgs->device;
713
0
    gx_color_index          drawn_comps = 0;
714
0
    gs_overprint_params_t   params = { 0 };
715
0
    gx_device_color        *pdc;
716
0
    cmm_dev_profile_t      *dev_profile;
717
0
    cmm_profile_t          *output_profile = 0;
718
0
    int                     code;
719
0
    bool                    profile_ok = false;
720
0
    gsicc_rendering_param_t        render_cond;
721
0
    bool                    eop;
722
723
0
    if_debug0m(gs_debug_flag_overprint, pgs->memory,
724
0
        "[overprint] gx_set_overprint_cmyk\n");
725
726
0
    if (dev) {
727
0
        code = dev_proc(dev, get_profile)(dev, &dev_profile);
728
0
        if (code < 0)
729
0
            return code;
730
731
0
        gsicc_extract_profile(dev->graphics_type_tag, dev_profile, &(output_profile),
732
0
                              &render_cond);
733
734
0
        drawn_comps = gx_get_process_comps(dev);
735
0
    }
736
737
0
    if_debug1m(gs_debug_flag_overprint, pgs->memory,
738
0
        "[overprint] gx_set_overprint_cmyk. drawn_comps = 0x%x\n", (uint)drawn_comps);
739
740
0
    if (drawn_comps == 0)
741
0
        return gx_spot_colors_set_overprint(pcs, pgs);
742
743
    /* correct for any zero'ed color components.  But only if profiles
744
       match AND pgs->overprint_mode is true */
745
0
    if (pcs->cmm_icc_profile_data != NULL && output_profile != NULL) {
746
0
        if (gsicc_profiles_equal(output_profile, pcs->cmm_icc_profile_data)) {
747
0
            profile_ok = true;
748
0
        }
749
0
    }
750
751
0
    eop = gs_currentcolor_eopm(pgs);
752
753
0
    if_debug3m(gs_debug_flag_overprint, pgs->memory,
754
0
        "[overprint] gx_set_overprint_cmyk. is_fill_color = %d, pgs->color[0].effective_opm = %d pgs->color[1].effective_opm = %d\n",
755
0
        pgs->is_fill_color, pgs->color[0].effective_opm, pgs->color[1].effective_opm);
756
757
0
    if (profile_ok && eop) {
758
0
        gx_color_index  nz_comps, one, temp;
759
0
        int             code;
760
0
        int             num_colorant[4], k;
761
0
        bool            colorant_ok;
762
0
        dev_color_proc_get_nonzero_comps((*procp));
763
764
0
        if_debug0m(gs_debug_flag_overprint, pgs->memory,
765
0
            "[overprint] gx_set_overprint_cmyk. color_is_set, profile_ok and eop\n");
766
767
0
        code = gx_set_dev_color(pgs);
768
0
        if (code < 0)
769
0
            return code;
770
0
        pdc = gs_currentdevicecolor_inline(pgs);
771
0
        procp = pdc->type->get_nonzero_comps;
772
0
        if (pdc->ccolor_valid) {
773
            /* If we have the source colors, then use those in making the
774
               decision as to which ones are non-zero.  Then we avoid
775
               accidently looking at small values that get quantized to zero
776
               Note that to get here in the code, the source color data color
777
               space has to be CMYK. Trick is that we do need to worry about
778
               the colorant order on the target device */
779
0
            num_colorant[0] = (dev_proc(dev, get_color_comp_index))\
780
0
                             (dev, "Cyan", strlen("Cyan"), NO_COMP_NAME_TYPE_OP);
781
0
            num_colorant[1] = (dev_proc(dev, get_color_comp_index))\
782
0
                             (dev, "Magenta", strlen("Magenta"), NO_COMP_NAME_TYPE_OP);
783
0
            num_colorant[2] = (dev_proc(dev, get_color_comp_index))\
784
0
                             (dev, "Yellow", strlen("Yellow"), NO_COMP_NAME_TYPE_OP);
785
0
            num_colorant[3] = (dev_proc(dev, get_color_comp_index))\
786
0
                             (dev, "Black", strlen("Black"), NO_COMP_NAME_TYPE_OP);
787
0
            nz_comps = 0;
788
0
            one = 1;
789
0
            colorant_ok = true;
790
0
            for (k = 0; k < 4; k++) {
791
                /* Note: AR assumes the value is zero if it
792
                   is less than 0.5 out of 255 */
793
0
                if (pdc->ccolor.paint.values[k] > (0.5 / 255.0)) {
794
0
                    if (num_colorant[k] == -1) {
795
0
                        colorant_ok = false;
796
0
                    } else {
797
0
                        temp = one << num_colorant[k];
798
0
                        nz_comps = nz_comps | temp;
799
0
                    }
800
0
                }
801
0
            }
802
            /* For some reason we don't have one of the standard colorants */
803
0
            if (!colorant_ok) {
804
0
                if ((code = procp(pdc, dev, &nz_comps)) < 0)
805
0
                    return code;
806
0
            }
807
0
        } else {
808
0
            if ((code = procp(pdc, dev, &nz_comps)) < 0)
809
0
                return code;
810
0
        }
811
0
        drawn_comps &= nz_comps;
812
0
    }
813
0
    params.is_fill_color = pgs->is_fill_color;
814
0
    params.retain_any_comps = true;
815
0
    params.drawn_comps = drawn_comps;
816
0
    params.op_state = OP_STATE_NONE;
817
818
0
    if_debug2m(gs_debug_flag_overprint, pgs->memory,
819
0
        "[overprint] gx_set_overprint_cmyk. retain_any_comps = %d, drawn_comps = 0x%x\n",
820
0
        params.retain_any_comps, (uint)(params.drawn_comps));
821
822
    /* We are in CMYK, the profiles match and overprint is true.  Set effective
823
       overprint mode to overprint mode but only if effective has not already
824
       been set to 0 */
825
0
    params.effective_opm = pgs->color[0].effective_opm =
826
0
        pgs->overprint_mode && gs_currentcolor_eopm(pgs);
827
0
    return gs_gstate_update_overprint(pgs, &params);
828
0
}
829
830
/* A stub for a color mapping linearity check, when it is inapplicable. */
831
int
832
gx_cspace_no_linear(const gs_color_space *cs, const gs_gstate * pgs,
833
                gx_device * dev,
834
                const gs_client_color *c0, const gs_client_color *c1,
835
                const gs_client_color *c2, const gs_client_color *c3,
836
                float smoothness, gsicc_link_t *icclink)
837
0
{
838
0
    return_error(gs_error_rangecheck);
839
0
}
840
841
static inline int
842
cc2dc(const gs_color_space *cs, const gs_gstate * pgs, gx_device *dev,
843
            gx_device_color *dc, const gs_client_color *cc)
844
0
{
845
0
    return cs->type->remap_color(cc, cs, dc, pgs, dev, gs_color_select_texture);
846
0
}
847
848
static inline void
849
interpolate_cc(gs_client_color *c,
850
        const gs_client_color *c0, const gs_client_color *c1, double t, int n)
851
0
{
852
0
    int i;
853
854
0
    for (i = 0; i < n; i++)
855
0
        c->paint.values[i] = c0->paint.values[i] * t + c1->paint.values[i] * (1 - t);
856
0
}
857
858
static inline bool
859
is_dc_nearly_linear(const gx_device *dev, const gx_device_color *c,
860
        const gx_device_color *c0, const gx_device_color *c1,
861
        double t, uchar n, float smoothness)
862
0
{
863
0
    uchar i;
864
865
0
    if (c0->type == &gx_dc_type_data_pure) {
866
0
        gx_color_index pure0 = c0->colors.pure;
867
0
        gx_color_index pure1 = c1->colors.pure;
868
0
        gx_color_index pure = c->colors.pure;
869
870
0
        for (i = 0; i < n; i++) {
871
0
            int shift = dev->color_info.comp_shift[i];
872
0
            int mask = (1 << dev->color_info.comp_bits[i]) - 1;
873
0
            int max_color = (i == dev->color_info.gray_index ? dev->color_info.max_gray
874
0
                                                             : dev->color_info.max_color);
875
0
            float max_diff = max(1, max_color * smoothness);
876
0
            int b0 = (pure0 >> shift) & mask, b1 = (pure1 >> shift) & mask;
877
0
            int b = (pure >> shift) & mask;
878
0
            double bb = b0 * t + b1 * (1 - t);
879
880
0
            if (any_abs(b - bb) > max_diff)
881
0
                return false;
882
0
        }
883
0
        return true;
884
0
    } else if (c0->type == &gx_dc_type_data_devn) {
885
0
        for (i = 0; i < n; i++) {
886
0
            int max_color = (i == dev->color_info.gray_index ? dev->color_info.max_gray
887
0
                : dev->color_info.max_color);
888
0
            double max_diff = max(1, max_color * smoothness);
889
            /* Color values are 16 bit.  We are basing the smoothness on the
890
               device bit depth.  So make sure to adjust the above max diff
891
               based upon our device bit depth */
892
0
            double ratio = (double)max_color / (double)gx_max_color_value;
893
0
            double b0 = (c0->colors.devn.values[i]) * ratio;
894
0
            double b1 = (c1->colors.devn.values[i]) * ratio;
895
0
            double b = (c->colors.devn.values[i]) * ratio;
896
0
            double bb = b0 * t + b1 * (1 - t);
897
0
            if (any_abs(b - bb) > max_diff)
898
0
                return false;
899
0
        }
900
0
        return true;
901
0
    } else {
902
        /* Halftones must not paint with fill_linear_color_*. */
903
0
        return false;
904
0
    }
905
0
}
906
907
/* Default color mapping linearity check, a 2-points case. */
908
static int
909
gx_cspace_is_linear_in_line(const gs_color_space *cs, const gs_gstate * pgs,
910
                gx_device *dev,
911
                const gs_client_color *c0, const gs_client_color *c1,
912
                float smoothness)
913
0
{
914
0
    gs_client_color c01a, c01b;
915
0
    gx_device_color d[2], d01a, d01b;
916
0
    int n = cs->type->num_components(cs);
917
0
    uchar ndev = dev->color_info.num_components;
918
0
    int code;
919
920
0
    code = cc2dc(cs, pgs, dev, &d[0], c0);
921
0
    if (code < 0)
922
0
        return code;
923
0
    code = cc2dc(cs, pgs, dev, &d[1], c1);
924
0
    if (code < 0)
925
0
        return code;
926
0
    interpolate_cc(&c01a, c0, c1, 0.3, n);
927
0
    code = cc2dc(cs, pgs, dev, &d01a, &c01a);
928
0
    if (code < 0)
929
0
        return code;
930
0
    if (!is_dc_nearly_linear(dev, &d01a, &d[0], &d[1], 0.3, ndev, smoothness))
931
0
        return 0;
932
0
    interpolate_cc(&c01b, c0, c1, 0.7, n);
933
0
    code = cc2dc(cs, pgs, dev, &d01b, &c01b);
934
0
    if (code < 0)
935
0
        return code;
936
0
    if (!is_dc_nearly_linear(dev, &d01b, &d[0], &d[1], 0.7, ndev, smoothness))
937
0
        return 0;
938
0
    return 1;
939
0
}
940
941
/* Default color mapping linearity check, a triangle case. */
942
static int
943
gx_cspace_is_linear_in_triangle(const gs_color_space *cs, const gs_gstate * pgs,
944
                gx_device *dev,
945
                const gs_client_color *c0, const gs_client_color *c1,
946
                const gs_client_color *c2, float smoothness)
947
0
{
948
    /* We check 4 points - the median center, and middle points of 3 sides.
949
       Hopely this is enough for reasonable color spaces and color renderings.
950
       Note it gives 7 points for a quadrangle. */
951
0
    gs_client_color c01, c12, c20, c012;
952
0
    gx_device_color d[3], d01, d12, d20, d012;
953
954
    /* Note that the device and the client color space
955
       can have a different number of components */
956
957
0
    int n = cs->type->num_components(cs);
958
0
    uchar ndev = dev->color_info.num_components;
959
960
0
    int code;
961
962
0
    code = cc2dc(cs, pgs, dev, &d[0], c0);
963
0
    if (code < 0)
964
0
        return code;
965
0
    code = cc2dc(cs, pgs, dev, &d[1], c1);
966
0
    if (code < 0)
967
0
        return code;
968
0
    code = cc2dc(cs, pgs, dev, &d[2], c2);
969
0
    if (code < 0)
970
0
        return code;
971
972
0
    interpolate_cc(&c01, c0, c1, 0.5, n);
973
0
    code = cc2dc(cs, pgs, dev, &d01, &c01);
974
0
    if (code < 0)
975
0
        return code;
976
0
    if (!is_dc_nearly_linear(dev, &d01, &d[0], &d[1], 0.5, ndev, smoothness))
977
0
        return 0;
978
979
0
    interpolate_cc(&c012, c2, &c01, 2.0 / 3, n);
980
0
    code = cc2dc(cs, pgs, dev, &d012, &c012);
981
0
    if (code < 0)
982
0
        return code;
983
0
    if (!is_dc_nearly_linear(dev, &d012, &d[2], &d01, 2.0 / 3, ndev, smoothness))
984
0
        return 0;
985
986
0
    interpolate_cc(&c12, c1, c2, 0.5, n);
987
0
    code = cc2dc(cs, pgs, dev, &d12, &c12);
988
0
    if (code < 0)
989
0
        return code;
990
0
    if (!is_dc_nearly_linear(dev, &d12, &d[1], &d[2], 0.5, ndev, smoothness))
991
0
        return 0;
992
993
0
    interpolate_cc(&c20, c2, c0, 0.5, n);
994
0
    code = cc2dc(cs, pgs, dev, &d20, &c20);
995
0
    if (code < 0)
996
0
        return code;
997
0
    if (!is_dc_nearly_linear(dev, &d20, &d[2], &d[0], 0.5, ndev, smoothness))
998
0
        return 0;
999
0
    return 1;
1000
0
}
1001
1002
/* Default color mapping linearity check. */
1003
int
1004
gx_cspace_is_linear_default(const gs_color_space *cs, const gs_gstate * pgs,
1005
                gx_device *dev,
1006
                const gs_client_color *c0, const gs_client_color *c1,
1007
                const gs_client_color *c2, const gs_client_color *c3,
1008
                float smoothness, gsicc_link_t *icclink)
1009
0
{
1010
    /* Assuming 2 <= nc <= 4. We don't need other cases. */
1011
    /* With nc == 4 assuming a convex plain quadrangle in the client color space. */
1012
0
    int code;
1013
1014
0
    if (!colors_are_separable_and_linear(&dev->color_info))
1015
0
        return_error(gs_error_rangecheck);
1016
0
    if (c2 == NULL)
1017
0
        return gx_cspace_is_linear_in_line(cs, pgs, dev, c0, c1, smoothness);
1018
0
    code = gx_cspace_is_linear_in_triangle(cs, pgs, dev, c0, c1, c2, smoothness);
1019
0
    if (code <= 0)
1020
0
        return code;
1021
0
    if (c3 == NULL)
1022
0
        return 1;
1023
0
    return gx_cspace_is_linear_in_triangle(cs, pgs, dev, c1, c2, c3, smoothness);
1024
0
}
1025
1026
/* Serialization. */
1027
int
1028
gx_serialize_cspace_type(const gs_color_space * pcs, stream * s)
1029
0
{
1030
0
    const gs_color_space_type * type = pcs->type;
1031
0
    uint n;
1032
0
    return sputs(s, (const byte *)&type->index, sizeof(type->index), &n);
1033
0
}
1034
1035
/* GC procedures */
1036
1037
static
1038
ENUM_PTRS_BEGIN_PROC(color_space_enum_ptrs)
1039
28.1k
{
1040
28.1k
    EV_CONST gs_color_space *pcs = vptr;
1041
1042
28.1k
    if (index == 0)
1043
5.63k
        return ENUM_OBJ(pcs->base_space);
1044
22.5k
    if (index == 1)
1045
5.63k
        return ENUM_OBJ(pcs->pclient_color_space_data);
1046
16.9k
    if (index == 2)
1047
5.63k
        return ENUM_OBJ(pcs->icc_equivalent);
1048
11.2k
    if (index == 3)
1049
5.63k
        return ENUM_OBJ(pcs->params.device_n.devn_process_space);
1050
5.63k
    return ENUM_USING(*pcs->type->stype, vptr, size, index - 4);
1051
11.2k
    ENUM_PTRS_END_PROC
1052
11.2k
}
1053
static
1054
5.63k
RELOC_PTRS_WITH(color_space_reloc_ptrs, gs_color_space *pcs)
1055
5.63k
{
1056
5.63k
    RELOC_VAR(pcs->base_space);
1057
5.63k
    RELOC_VAR(pcs->pclient_color_space_data);
1058
5.63k
    RELOC_VAR(pcs->icc_equivalent);
1059
5.63k
    RELOC_VAR(pcs->params.device_n.devn_process_space);
1060
5.63k
    RELOC_USING(*pcs->type->stype, vptr, size);
1061
5.63k
}
1062
5.63k
RELOC_PTRS_END