Coverage Report

Created: 2025-11-16 07:40

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