Coverage Report

Created: 2025-06-24 07:01

/src/ghostpdl/base/gscscie.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2001-2023 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
/* CIE color space management */
18
#include "math_.h"
19
#include "gx.h"
20
#include "gserrors.h"
21
#include "gsstruct.h"
22
#include "gsmatrix.h"   /* for gscolor2.h */
23
#include "gxcspace.h"
24
#include "gscolor2.h"   /* for gs_set/currentcolorrendering */
25
#include "gsicc_manage.h" /* for gsicc_adjust_profile_rc */
26
#include "gxcie.h"
27
#include "gxarith.h"
28
#include "gxdevice.h"   /* for gxcmap.h */
29
#include "gxcmap.h"
30
#include "gzstate.h"
31
#include "stream.h"
32
33
/* ---------------- Color space definition ---------------- */
34
35
/* GC descriptors */
36
public_st_cie_common();
37
public_st_cie_common_elements();
38
private_st_cie_a();
39
private_st_cie_abc();
40
private_st_cie_def();
41
private_st_cie_defg();
42
43
/* Define the CIE color space types. */
44
45
/* CIEBasedDEFG */
46
gs_private_st_ptrs1(st_color_space_CIEDEFG, gs_color_space,
47
     "gs_color_space(CIEDEFG)", cs_CIEDEFG_enum_ptrs, cs_CIEDEFG_reloc_ptrs,
48
                    params.defg);
49
static cs_proc_final(gx_final_CIEDEFG);
50
static cs_proc_serialize(gx_serialize_CIEDEFG);
51
const gs_color_space_type gs_color_space_type_CIEDEFG = {
52
    gs_color_space_index_CIEDEFG, true, true,
53
    &st_color_space_CIEDEFG, gx_num_components_4,
54
    gx_init_CIE, gx_restrict_CIEDEFG,
55
    gx_concrete_space_CIE,
56
    gx_concretize_CIEDEFG, NULL,
57
    gx_remap_CIEDEFG,
58
    gx_install_CIE,
59
    gx_spot_colors_set_overprint,
60
    gx_final_CIEDEFG, gx_no_adjust_color_count,
61
    gx_serialize_CIEDEFG,
62
    gx_cspace_is_linear_default, gx_polarity_subtractive
63
};
64
65
/* CIEBasedDEF */
66
gs_private_st_ptrs1(st_color_space_CIEDEF, gs_color_space,
67
        "gs_color_space(CIEDEF)", cs_CIEDEF_enum_ptrs, cs_CIEDEF_reloc_ptrs,
68
                    params.def);
69
static cs_proc_final(gx_final_CIEDEF);
70
static cs_proc_serialize(gx_serialize_CIEDEF);
71
const gs_color_space_type gs_color_space_type_CIEDEF = {
72
    gs_color_space_index_CIEDEF, true, true,
73
    &st_color_space_CIEDEF, gx_num_components_3,
74
    gx_init_CIE, gx_restrict_CIEDEF,
75
    gx_concrete_space_CIE,
76
    gx_concretize_CIEDEF, NULL,
77
    gx_remap_CIEDEF,
78
    gx_install_CIE,
79
    gx_spot_colors_set_overprint,
80
    gx_final_CIEDEF, gx_no_adjust_color_count,
81
    gx_serialize_CIEDEF,
82
    gx_cspace_is_linear_default, gx_polarity_subtractive
83
};
84
85
/* CIEBasedABC */
86
gs_private_st_ptrs1(st_color_space_CIEABC, gs_color_space,
87
        "gs_color_space(CIEABC)", cs_CIEABC_enum_ptrs, cs_CIEABC_reloc_ptrs,
88
                    params.abc);
89
static cs_proc_final(gx_final_CIEABC);
90
static cs_proc_serialize(gx_serialize_CIEABC);
91
const gs_color_space_type gs_color_space_type_CIEABC = {
92
    gs_color_space_index_CIEABC, true, true,
93
    &st_color_space_CIEABC, gx_num_components_3,
94
    gx_init_CIE, gx_restrict_CIEABC,
95
    gx_concrete_space_CIE,
96
    gx_concretize_CIEABC, NULL,
97
    gx_remap_CIEABC, gx_install_CIE,
98
    gx_spot_colors_set_overprint,
99
    gx_final_CIEABC, gx_no_adjust_color_count,
100
    gx_serialize_CIEABC,
101
    gx_cspace_is_linear_default, gx_polarity_additive
102
};
103
104
/* CIEBasedA */
105
gs_private_st_ptrs1(st_color_space_CIEA, gs_color_space,
106
              "gs_color_space(CIEA)", cs_CIEA_enum_ptrs, cs_CIEA_reloc_ptrs,
107
                    params.a);
108
static cs_proc_final(gx_final_CIEA);
109
static cs_proc_serialize(gx_serialize_CIEA);
110
const gs_color_space_type gs_color_space_type_CIEA = {
111
    gs_color_space_index_CIEA, true, true,
112
    &st_color_space_CIEA, gx_num_components_1,
113
    gx_init_CIE, gx_restrict_CIEA,
114
    gx_concrete_space_CIE,
115
    gx_concretize_CIEA, NULL,
116
    gx_remap_CIEA,
117
    gx_install_CIE,
118
    gx_spot_colors_set_overprint,
119
    gx_final_CIEA, gx_no_adjust_color_count,
120
    gx_serialize_CIEA,
121
    gx_cspace_is_linear_default, gx_polarity_additive
122
};
123
124
/* Determine the concrete space underlying a CIEBased space. */
125
const gs_color_space *
126
gx_concrete_space_CIE(const gs_color_space * pcs, const gs_gstate * pgs)
127
0
{
128
0
    const gs_cie_render *pcie = pgs->cie_render;
129
130
0
    if (pcie == 0 || pcie->RenderTable.lookup.table == 0 ||
131
0
        pcie->RenderTable.lookup.m == 3
132
0
        ) {
133
0
        return pgs->devicergb_cs;
134
0
    } else {     /* pcie->RenderTable.lookup.m == 4 */
135
0
        return pgs->devicecmyk_cs;
136
0
    }
137
0
}
138
139
/* Install a CIE space in the graphics state. */
140
/* We go through an extra level of procedure so that */
141
/* interpreters can substitute their own installer. */
142
/* This procedure is exported for the benefit of gsicc.c */
143
int
144
gx_install_CIE(gs_color_space * pcs, gs_gstate * pgs)
145
0
{
146
0
    return (*pcs->params.a->common.install_cspace) (pcs, pgs);
147
0
}
148
149
/* Free params for a CIE color space */
150
static void
151
gx_final_CIEDEFG(gs_color_space * pcs)
152
0
{
153
0
    if (pcs->icc_equivalent != NULL) {
154
0
        rc_decrement(pcs->icc_equivalent, "gx_final_CIEDEFG");
155
0
        pcs->icc_equivalent = NULL;
156
0
    }
157
0
    if (pcs->cmm_icc_profile_data != NULL) {
158
0
        gsicc_adjust_profile_rc(pcs->cmm_icc_profile_data, -1, "gx_final_CIEDEFG");
159
0
        pcs->cmm_icc_profile_data = NULL;
160
0
    }
161
0
    rc_decrement(pcs->params.defg, "gx_final_CIEDEFG");
162
0
    pcs->params.defg = NULL;
163
0
}
164
165
static void
166
gx_final_CIEDEF(gs_color_space * pcs)
167
0
{
168
0
    if (pcs->icc_equivalent != NULL) {
169
0
        rc_decrement(pcs->icc_equivalent,"gx_final_CIEDEF");
170
0
        pcs->icc_equivalent = NULL;
171
0
    }
172
0
    if (pcs->cmm_icc_profile_data != NULL) {
173
0
        gsicc_adjust_profile_rc(pcs->cmm_icc_profile_data, -1, "gx_final_CIEDEF");
174
0
        pcs->cmm_icc_profile_data = NULL;
175
0
    }
176
0
    rc_decrement(pcs->params.def, "gx_final_CIEDEF");
177
0
    pcs->params.def = NULL;
178
0
}
179
180
static void
181
gx_final_CIEABC(gs_color_space * pcs)
182
0
{
183
0
    if (pcs->icc_equivalent != NULL) {
184
0
        rc_decrement(pcs->icc_equivalent,"gx_final_CIEABC");
185
0
        pcs->icc_equivalent = NULL;
186
0
    }
187
0
    if (pcs->cmm_icc_profile_data != NULL) {
188
0
        gsicc_adjust_profile_rc(pcs->cmm_icc_profile_data, -1, "gx_final_CIEABC");
189
0
        pcs->cmm_icc_profile_data = NULL;
190
0
    }
191
0
    rc_decrement(pcs->params.abc, "gx_final_CIEABC");
192
0
    pcs->params.abc = NULL;
193
0
}
194
195
static void
196
gx_final_CIEA(gs_color_space * pcs)
197
0
{
198
0
    if (pcs->icc_equivalent != NULL) {
199
0
        rc_decrement(pcs->icc_equivalent,"gx_final_CIEA");
200
0
        pcs->icc_equivalent = NULL;
201
0
    }
202
0
    if (pcs->cmm_icc_profile_data != NULL) {
203
0
        gsicc_adjust_profile_rc(pcs->cmm_icc_profile_data, -1, "gx_final_CIEA");
204
0
        pcs->cmm_icc_profile_data = NULL;
205
0
    }
206
0
    rc_decrement(pcs->params.a, "gx_adjust_cspace_CIEA");
207
0
    pcs->params.a = NULL;
208
0
}
209
210
/* ---------------- Procedures ---------------- */
211
212
/* ------ Internal initializers ------ */
213
214
/*
215
 * Set up the default values for the CIE parameters that are common to
216
 * all CIE color spaces.
217
 *
218
 * There is no default for the white point, so it is set equal to the
219
 * black point. If anyone actually uses the color space in that form,
220
 * the results are likely to be unsatisfactory.
221
 *
222
 * This procedure is exported for the benefit of gsicc.c.
223
 */
224
void
225
gx_set_common_cie_defaults(gs_cie_common * pcommon, void *client_data)
226
0
{
227
0
    pcommon->RangeLMN = Range3_default;
228
0
    pcommon->DecodeLMN = DecodeLMN_default;
229
0
    pcommon->MatrixLMN = Matrix3_default;
230
0
    pcommon->points.WhitePoint = BlackPoint_default;
231
0
    pcommon->points.BlackPoint = BlackPoint_default;
232
0
    pcommon->client_data = client_data;
233
0
}
234
235
/*
236
 * Set defaults for a CIEBasedABC color space.  This is also used for
237
 * CIEBasedDEF and CIEBasedDEFG color spaces.
238
 */
239
static void
240
set_cie_abc_defaults(gs_cie_abc * pabc, void *client_data)
241
0
{
242
0
    gx_set_common_cie_defaults(&pabc->common, client_data);
243
0
    pabc->RangeABC = Range3_default;
244
0
    pabc->DecodeABC = DecodeABC_default;
245
0
    pabc->MatrixABC = Matrix3_default;
246
0
}
247
248
/*
249
 * Set up a default color lookup table for a CIEBasedDEF[G] space. There is
250
 * no specified default for this structure, so the values used here (aside
251
 * from the input and output component numbers) are intended only to make
252
 * the system fail in a predictable manner.
253
 */
254
static void
255
set_ctbl_defaults(gx_color_lookup_table * plktblp, int num_comps)
256
0
{
257
0
    int i;
258
259
0
    plktblp->n = num_comps;
260
0
    plktblp->m = 3;   /* always output CIE ABC */
261
0
    for (i = 0; i < countof(plktblp->dims); i++)
262
0
        plktblp->dims[i] = 0;
263
0
    plktblp->table = 0;
264
0
}
265
266
/*
267
 * Allocate a color space and its parameter structure.
268
 * Return 0 if VMerror, otherwise the parameter structure.
269
 *
270
 * This is exported for the benefit of gsicc.c
271
 */
272
void *
273
gx_build_cie_space(gs_color_space ** ppcspace,
274
                const gs_color_space_type * pcstype,
275
                gs_memory_type_ptr_t stype, gs_memory_t * pmem)
276
0
{
277
0
    gs_color_space *pcspace = gs_cspace_alloc(pmem, pcstype);
278
0
    gs_cie_common_elements_t *pdata;
279
280
0
    if (pcspace == NULL)
281
0
        return NULL;
282
0
    rc_alloc_struct_1(pdata, gs_cie_common_elements_t, stype, pmem,
283
0
                      {
284
0
                      gs_free_object(pmem, pcspace, "gx_build_cie_space");
285
0
                      return 0;
286
0
                      }
287
0
                      ,
288
0
                      "gx_build_cie_space(data)");
289
0
    *ppcspace = pcspace;
290
0
    return (void *)pdata;
291
0
}
292
293
/* ------ Constructors ------ */
294
295
int
296
gs_cspace_build_CIEA(gs_color_space ** ppcspace, void *client_data,
297
                     gs_memory_t * pmem)
298
0
{
299
0
    gs_cie_a *pciea =
300
0
    gx_build_cie_space(ppcspace, &gs_color_space_type_CIEA, &st_cie_a, pmem);
301
302
0
    if (pciea == 0)
303
0
        return_error(gs_error_VMerror);
304
305
0
    gx_set_common_cie_defaults(&pciea->common, client_data);
306
0
    pciea->common.install_cspace = gx_install_CIEA;
307
0
    pciea->RangeA = RangeA_default;
308
0
    pciea->DecodeA = DecodeA_default;
309
0
    pciea->MatrixA = MatrixA_default;
310
311
0
    (*ppcspace)->params.a = pciea;
312
0
    return 0;
313
0
}
314
315
int
316
gs_cspace_build_CIEABC(gs_color_space ** ppcspace, void *client_data,
317
                       gs_memory_t * pmem)
318
0
{
319
0
    gs_cie_abc *pabc =
320
0
    gx_build_cie_space(ppcspace, &gs_color_space_type_CIEABC, &st_cie_abc,
321
0
                       pmem);
322
323
0
    if (pabc == 0)
324
0
        return_error(gs_error_VMerror);
325
326
0
    set_cie_abc_defaults(pabc, client_data);
327
0
    pabc->common.install_cspace = gx_install_CIEABC;
328
329
0
    (*ppcspace)->params.abc = pabc;
330
0
    return 0;
331
0
}
332
333
int
334
gs_cspace_build_CIEDEF(gs_color_space ** ppcspace, void *client_data,
335
                       gs_memory_t * pmem)
336
0
{
337
0
    gs_cie_def *pdef =
338
0
    gx_build_cie_space(ppcspace, &gs_color_space_type_CIEDEF, &st_cie_def,
339
0
                       pmem);
340
341
0
    if (pdef == 0)
342
0
        return_error(gs_error_VMerror);
343
344
0
    set_cie_abc_defaults((gs_cie_abc *) pdef, client_data);
345
0
    pdef->common.install_cspace = gx_install_CIEDEF;
346
0
    pdef->RangeDEF = Range3_default;
347
0
    pdef->DecodeDEF = DecodeDEF_default;
348
0
    pdef->RangeHIJ = Range3_default;
349
0
    set_ctbl_defaults(&pdef->Table, 3);
350
351
0
    (*ppcspace)->params.def = pdef;
352
0
    return 0;
353
0
}
354
355
int
356
gs_cspace_build_CIEDEFG(gs_color_space ** ppcspace, void *client_data,
357
                        gs_memory_t * pmem)
358
0
{
359
0
    gs_cie_defg *pdefg =
360
0
    gx_build_cie_space(ppcspace, &gs_color_space_type_CIEDEFG, &st_cie_defg,
361
0
                       pmem);
362
363
0
    if (pdefg == 0)
364
0
        return_error(gs_error_VMerror);
365
366
0
    set_cie_abc_defaults((gs_cie_abc *) pdefg, client_data);
367
0
    pdefg->common.install_cspace = gx_install_CIEDEFG;
368
0
    pdefg->RangeDEFG = Range4_default;
369
0
    pdefg->DecodeDEFG = DecodeDEFG_default;
370
0
    pdefg->RangeHIJK = Range4_default;
371
0
    set_ctbl_defaults(&pdefg->Table, 4);
372
373
0
    (*ppcspace)->params.defg = pdefg;
374
0
    return 0;
375
0
}
376
377
/* ------ Accessors ------ */
378
379
int
380
gs_cie_defx_set_lookup_table(gs_color_space * pcspace, int *pdims,
381
                             const gs_const_string * ptable)
382
0
{
383
0
    gx_color_lookup_table *plktblp;
384
385
0
    switch (gs_color_space_get_index(pcspace)) {
386
0
        case gs_color_space_index_CIEDEF:
387
0
            plktblp = &pcspace->params.def->Table;
388
0
            break;
389
0
        case gs_color_space_index_CIEDEFG:
390
0
            plktblp = &pcspace->params.defg->Table;
391
0
            plktblp->dims[3] = pdims[3];
392
0
            break;
393
0
        default:
394
0
            return_error(gs_error_rangecheck);
395
0
    }
396
397
0
    plktblp->dims[0] = pdims[0];
398
0
    plktblp->dims[1] = pdims[1];
399
0
    plktblp->dims[2] = pdims[2];
400
0
    plktblp->table = ptable;
401
0
    return 0;
402
0
}
403
404
/* ---------------- Serialization. -------------------------------- */
405
406
static int
407
gx_serialize_cie_cache(const cie_cache_floats *c, stream * s)
408
0
{ /* p->DecodeA : */
409
0
    const uint cache_size = count_of(c->values);
410
0
    uint n;
411
0
    int code;
412
413
0
    code = sputs(s, (const byte *)&c->params.is_identity, sizeof(c->params.is_identity), &n);
414
0
    if (code < 0)
415
0
        return_error(gs_error_ioerror);
416
0
    if (c->params.is_identity)
417
0
        return 0;
418
0
    code = sputs(s, (const byte *)&cache_size, sizeof(cache_size), &n);
419
0
    if (code < 0)
420
0
        return code;
421
0
    return sputs(s, (const byte *)c->values, sizeof(c->values), &n);
422
0
}
423
424
int
425
gx_serialize_cie_common_elements(const gs_color_space * pcs, stream * s)
426
0
{
427
0
    const gs_cie_a * p = pcs->params.a;
428
0
    uint n, k;
429
0
    int code = gx_serialize_cspace_type(pcs, s);
430
431
0
    if (code < 0)
432
0
        return code;
433
0
    code = sputs(s, (const byte *)&p->common.RangeLMN,
434
0
                        sizeof(p->common.RangeLMN), &n);
435
0
    if (code < 0)
436
0
        return code;
437
0
    for (k = 0; k < 3 && code >= 0; k++)
438
0
        code = gx_serialize_cie_cache(&p->common.caches.DecodeLMN[k].floats, s);
439
0
    if (code < 0)
440
0
        return code;
441
0
    code = sputs(s, (const byte *)&p->common.MatrixLMN,
442
0
                        sizeof(p->common.MatrixLMN), &n);
443
0
    if (code < 0)
444
0
        return code;
445
0
    return sputs(s, (const byte *)&p->common.points,
446
0
                        sizeof(p->common.points), &n);
447
0
}
448
449
static int
450
gx_serialize_CIEA(const gs_color_space * pcs, stream * s)
451
0
{
452
0
    const gs_cie_a * p = pcs->params.a;
453
0
    uint n;
454
0
    int code = gx_serialize_cie_common_elements(pcs, s);
455
456
0
    if (code < 0)
457
0
        return code;
458
0
    code = sputs(s, (const byte *)&p->RangeA, sizeof(p->RangeA), &n);
459
0
    if (code < 0)
460
0
        return code;
461
0
    code = gx_serialize_cie_cache(&p->caches.DecodeA.floats, s);
462
0
    if (code < 0)
463
0
        return code;
464
0
    return sputs(s, (const byte *)&p->MatrixA, sizeof(p->MatrixA), &n);
465
0
}
466
467
static int
468
gx_serialize_CIEABC(const gs_color_space * pcs, stream * s)
469
0
{
470
0
    const gs_cie_abc * p = pcs->params.abc;
471
0
    uint n, k;
472
0
    int code = gx_serialize_cie_common_elements(pcs, s);
473
474
0
    if (code < 0)
475
0
        return code;
476
0
    code = sputs(s, (const byte *)&p->RangeABC, sizeof(p->RangeABC), &n);
477
0
    if (code < 0)
478
0
        return code;
479
0
    code = sputs(s, (const byte *)&p->caches.skipABC, sizeof(p->caches.skipABC), &n);
480
0
    if (code < 0)
481
0
        return code;
482
0
    if (p->caches.skipABC)
483
0
        return 0;
484
0
    for (k = 0; k < 3 && code >= 0; k++)
485
0
        code = gx_serialize_cie_cache(&p->caches.DecodeABC.caches[k].floats, s);
486
0
    if (code < 0)
487
0
        return code;
488
0
    return sputs(s, (const byte *)&p->MatrixABC, sizeof(p->MatrixABC), &n);
489
0
}
490
491
static int
492
gx_serialize_lookup_table(const gx_color_lookup_table * t, stream * s)
493
0
{
494
0
    uint n;
495
0
    int code = sputs(s, (const byte *)&t->n, sizeof(t->n), &n);
496
497
0
    if (code < 0)
498
0
        return code;
499
0
    code = sputs(s, (const byte *)&t->dims[0], sizeof(t->dims[0]) * t->n, &n);
500
0
    if (code < 0)
501
0
        return code;
502
0
    code = sputs(s, (const byte *)&t->m, sizeof(t->m), &n);
503
0
    if (code < 0)
504
0
        return code;
505
0
    code = sputs(s, (const byte *)&t->table->size, sizeof(t->table->size), &n);
506
0
    if (code < 0)
507
0
        return code;
508
0
    return sputs(s, (const byte *)t->table->data, t->table->size, &n);
509
0
}
510
511
static int
512
gx_serialize_CIEDEF(const gs_color_space * pcs, stream * s)
513
0
{
514
0
    const gs_cie_def * p = pcs->params.def;
515
0
    uint n, k;
516
0
    int code = gx_serialize_cie_common_elements(pcs, s);
517
518
0
    if (code < 0)
519
0
        return code;
520
0
    code = sputs(s, (const byte *)&p->RangeDEF, sizeof(p->RangeDEF), &n);
521
0
    if (code < 0)
522
0
        return code;
523
0
    for (k = 0; k < 3 && code >= 0; k++)
524
0
        code = gx_serialize_cie_cache(&p->caches_def.DecodeDEF[k].floats, s);
525
0
    if (code < 0)
526
0
        return code;
527
0
    code = sputs(s, (const byte *)&p->RangeHIJ, sizeof(p->RangeHIJ), &n);
528
0
    if (code < 0)
529
0
        return code;
530
0
    return gx_serialize_lookup_table(&p->Table, s);
531
0
}
532
533
static int
534
gx_serialize_CIEDEFG(const gs_color_space * pcs, stream * s)
535
0
{
536
0
    const gs_cie_defg * p = pcs->params.defg;
537
0
    uint n, k;
538
0
    int code = gx_serialize_cie_common_elements(pcs, s);
539
540
0
    if (code < 0)
541
0
        return code;
542
0
    code = sputs(s, (const byte *)&p->RangeDEFG, sizeof(p->RangeDEFG), &n);
543
0
    if (code < 0)
544
0
        return code;
545
0
    for (k = 0; k < 3 && code >= 0; k++)
546
0
        code = gx_serialize_cie_cache(&p->caches_defg.DecodeDEFG[k].floats, s);
547
0
    if (code < 0)
548
0
        return code;
549
0
    code = sputs(s, (const byte *)&p->RangeHIJK, sizeof(p->RangeHIJK), &n);
550
0
    if (code < 0)
551
0
        return code;
552
0
    return gx_serialize_lookup_table(&p->Table, s);
553
0
}