Coverage Report

Created: 2025-11-16 07:40

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ghostpdl/pdf/pdf_colour.c
Line
Count
Source
1
/* Copyright (C) 2018-2025 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
/* colour operations for the PDF interpreter */
17
18
#include "pdf_int.h"
19
#include "pdf_doc.h"
20
#include "pdf_colour.h"
21
#include "pdf_pattern.h"
22
#include "pdf_stack.h"
23
#include "pdf_array.h"
24
#include "pdf_misc.h"
25
#include "gsicc_manage.h"
26
#include "gsicc_profilecache.h"
27
#include "gsicc_cache.h"
28
29
#include "gsicc_create.h"
30
#include "gsptype2.h"
31
32
33
#include "pdf_file.h"
34
#include "pdf_dict.h"
35
#include "pdf_loop_detect.h"
36
#include "pdf_func.h"
37
#include "pdf_shading.h"
38
#include "gscsepr.h"
39
#include "stream.h"
40
#include "strmio.h"
41
#include "gscdevn.h"
42
#include "gxcdevn.h"
43
#include "gscolor.h"    /* For gs_setgray() and friends */
44
#include "gsicc.h"      /* For gs_cspace_build_ICC() */
45
#include "gsstate.h"    /* For gs_gdsvae() and gs_grestore() */
46
47
/* Forward definitions for a routine we need */
48
static int pdfi_create_colorspace_by_array(pdf_context *ctx, pdf_array *color_array, int index,
49
                                           pdf_dict *stream_dict, pdf_dict *page_dict,
50
                                           gs_color_space **ppcs, bool inline_image);
51
static int pdfi_create_colorspace_by_name(pdf_context *ctx, pdf_name *name,
52
                                          pdf_dict *stream_dict, pdf_dict *page_dict,
53
                                          gs_color_space **ppcs, bool inline_image);
54
55
/* This is used only from the page level interpreter code, we need to know the number
56
 * of spot colours in a PDF file, which we have to pass to the device for spot colour
57
 * rendering. We deal with it here because its colour related.
58
 * The PDF context has a page-level object which maintains a list of the spot colour
59
 * names seen so far, so we can ensure we don't end up with duplictaes.
60
 */
61
static int pdfi_check_for_spots_by_name(pdf_context *ctx, pdf_name *name,
62
                                        pdf_dict *parent_dict, pdf_dict *page_dict, pdf_dict *spot_dict)
63
45.6k
{
64
45.6k
    pdf_obj *ref_space;
65
45.6k
    int code;
66
67
45.6k
    if (pdfi_name_is(name, "G")) {
68
0
        return 0;
69
45.6k
    } else if (pdfi_name_is(name, "RGB")) {
70
0
        return 0;
71
45.6k
    } else if (pdfi_name_is(name, "CMYK")) {
72
0
        return 0;
73
45.6k
    } else if (pdfi_name_is(name, "DeviceRGB")) {
74
38.2k
        return 0;
75
38.2k
    } else if (pdfi_name_is(name, "DeviceGray")) {
76
2.58k
        return 0;
77
4.89k
    } else if (pdfi_name_is(name, "DeviceCMYK")) {
78
4.24k
        return 0;
79
4.24k
    } else if (pdfi_name_is(name, "Pattern")) {
80
        /* TODO: I think this is fine... */
81
426
        return 0;
82
426
    } else {
83
221
        code = pdfi_find_resource(ctx, (unsigned char *)"ColorSpace", name, parent_dict, page_dict, &ref_space);
84
221
        if (code < 0)
85
217
            return code;
86
87
4
        if (pdfi_type_of(ref_space) == PDF_NAME) {
88
4
            if (pdfi_name_cmp(name, (pdf_name *)ref_space) == 0) {
89
4
                pdfi_set_error(ctx, gs_error_circular_reference, NULL, E_PDF_CIRCULARNAME, NULL, NULL);
90
4
                pdfi_countdown(ref_space);
91
4
                return_error(gs_error_circular_reference);
92
4
            }
93
4
        }
94
        /* recursion */
95
0
        return pdfi_check_ColorSpace_for_spots(ctx, ref_space, parent_dict, page_dict, spot_dict);
96
4
    }
97
0
    return 0;
98
45.6k
}
99
100
static int pdfi_check_for_spots_by_array(pdf_context *ctx, pdf_array *color_array,
101
                                         pdf_dict *parent_dict, pdf_dict *page_dict, pdf_dict *spot_dict)
102
34.3k
{
103
34.3k
    pdf_name *space = NULL;
104
34.3k
    pdf_array *a = NULL;
105
34.3k
    int code = 0;
106
107
34.3k
    if (!spot_dict)
108
0
        return 0;
109
110
34.3k
    code = pdfi_array_get_type(ctx, color_array, 0, PDF_NAME, (pdf_obj **)&space);
111
34.3k
    if (code != 0)
112
30
        goto exit;
113
114
34.3k
    code = 0;
115
34.3k
    if (pdfi_name_is(space, "G")) {
116
0
        goto exit;
117
34.3k
    } else if (pdfi_name_is(space, "I") || pdfi_name_is(space, "Indexed")) {
118
4.48k
        pdf_obj *base_space;
119
120
4.48k
        code = pdfi_array_get(ctx, color_array, 1, &base_space);
121
4.48k
        if (code == 0) {
122
4.36k
            code = pdfi_check_ColorSpace_for_spots(ctx, base_space, parent_dict, page_dict, spot_dict);
123
4.36k
            (void)pdfi_countdown(base_space);
124
4.36k
        }
125
4.48k
        goto exit;
126
29.8k
    } else if (pdfi_name_is(space, "Pattern")) {
127
1.11k
        pdf_obj *base_space = NULL;
128
1.11k
        uint64_t size = pdfi_array_size(color_array);
129
130
        /* Array of size 1 "[ /Pattern ]" is okay, just do nothing. */
131
1.11k
        if (size == 1)
132
762
            goto exit;
133
        /* Array of size > 2 we don't handle (shouldn't happen?) */
134
354
        if (size != 2) {
135
0
            dbgmprintf1(ctx->memory,
136
0
                        "WARNING: checking Pattern for spots, expected array size 2, got %lu\n",
137
0
                        size);
138
0
            goto exit;
139
0
        }
140
        /* "[/Pattern base_space]" */
141
354
        code = pdfi_array_get(ctx, color_array, 1, &base_space);
142
354
        if (code == 0) {
143
354
            code = pdfi_check_ColorSpace_for_spots(ctx, base_space, parent_dict, page_dict, spot_dict);
144
354
            (void)pdfi_countdown(base_space);
145
354
        }
146
354
        goto exit;
147
28.7k
    } else if (pdfi_name_is(space, "Lab")) {
148
292
        goto exit;
149
28.4k
    } else if (pdfi_name_is(space, "RGB")) {
150
0
        goto exit;
151
28.4k
    } else if (pdfi_name_is(space, "CMYK")) {
152
0
        goto exit;
153
28.4k
    } else if (pdfi_name_is(space, "CalRGB")) {
154
729
        goto exit;
155
27.6k
    } else if (pdfi_name_is(space, "CalGray")) {
156
98
        goto exit;
157
27.5k
    } else if (pdfi_name_is(space, "CalCMYK")) {
158
0
        goto exit;
159
27.5k
    } else if (pdfi_name_is(space, "ICCBased")) {
160
21.5k
        goto exit;
161
21.5k
    } else if (pdfi_name_is(space, "DeviceRGB")) {
162
4
        goto exit;
163
6.05k
    } else if (pdfi_name_is(space, "DeviceGray")) {
164
0
        goto exit;
165
6.05k
    } else if (pdfi_name_is(space, "DeviceCMYK")) {
166
0
        goto exit;
167
6.05k
    } else if (pdfi_name_is(space, "DeviceN")) {
168
3.12k
        bool known = false;
169
3.12k
        pdf_obj *dummy, *name;
170
3.12k
        int i;
171
172
3.12k
        pdfi_countdown(space);
173
3.12k
        code = pdfi_array_get_type(ctx, color_array, 1, PDF_ARRAY, (pdf_obj **)&space);
174
3.12k
        if (code != 0)
175
4
            goto exit;
176
177
8.15k
        for (i=0;i < pdfi_array_size((pdf_array *)space); i++) {
178
5.02k
            code = pdfi_array_get_type(ctx, (pdf_array *)space, (uint64_t)i, PDF_NAME, &name);
179
5.02k
            if (code < 0)
180
0
                goto exit;
181
182
5.02k
            if (pdfi_name_is((const pdf_name *)name, "Cyan") || pdfi_name_is((const pdf_name *)name, "Magenta") ||
183
4.01k
                pdfi_name_is((const pdf_name *)name, "Yellow") || pdfi_name_is((const pdf_name *)name, "Black") ||
184
4.08k
                pdfi_name_is((const pdf_name *)name, "None") || pdfi_name_is((const pdf_name *)name, "All")) {
185
186
4.08k
                pdfi_countdown(name);
187
4.08k
                continue;
188
4.08k
            }
189
190
942
            code = pdfi_dict_known_by_key(ctx, spot_dict, (pdf_name *)name, &known);
191
942
            if (code < 0) {
192
0
                pdfi_countdown(name);
193
0
                goto exit;
194
0
            }
195
942
            if (known) {
196
148
                pdfi_countdown(name);
197
148
                continue;
198
148
            }
199
200
794
            code = pdfi_object_alloc(ctx, PDF_INT, 0, &dummy);
201
794
            if (code < 0)
202
0
                goto exit;
203
204
794
            code = pdfi_dict_put_obj(ctx, spot_dict, name, dummy, true);
205
794
            pdfi_countdown(name);
206
794
            if (code < 0)
207
0
                break;
208
794
        }
209
3.12k
        goto exit;
210
3.12k
    } else if (pdfi_name_is(space, "Separation")) {
211
2.85k
        bool known = false;
212
2.85k
        pdf_obj *dummy;
213
214
2.85k
        pdfi_countdown(space);
215
2.85k
        code = pdfi_array_get_type(ctx, color_array, 1, PDF_NAME, (pdf_obj **)&space);
216
2.85k
        if (code != 0)
217
0
            goto exit;
218
219
2.85k
        if (pdfi_name_is((const pdf_name *)space, "Cyan") || pdfi_name_is((const pdf_name *)space, "Magenta") ||
220
2.85k
            pdfi_name_is((const pdf_name *)space, "Yellow") || pdfi_name_is((const pdf_name *)space, "Black") ||
221
709
            pdfi_name_is((const pdf_name *)space, "None") || pdfi_name_is((const pdf_name *)space, "All"))
222
2.15k
            goto exit;
223
709
        code = pdfi_dict_known_by_key(ctx, spot_dict, space, &known);
224
709
        if (code < 0 || known)
225
196
            goto exit;
226
227
513
        code = pdfi_object_alloc(ctx, PDF_INT, 0, &dummy);
228
513
        if (code < 0)
229
0
            goto exit;
230
231
513
        code = pdfi_dict_put_obj(ctx, spot_dict, (pdf_obj *)space, dummy, true);
232
513
        goto exit;
233
513
    } else {
234
66
        code = pdfi_find_resource(ctx, (unsigned char *)"ColorSpace",
235
66
                                  space, parent_dict, page_dict, (pdf_obj **)&a);
236
66
        if (code < 0)
237
62
            goto exit;
238
239
4
        if (pdfi_type_of(a) != PDF_ARRAY) {
240
0
            code = gs_note_error(gs_error_typecheck);
241
0
            goto exit;
242
0
        }
243
4
        if (a == color_array) {
244
4
            code = gs_note_error(gs_error_circular_reference);
245
4
            goto exit;
246
4
        }
247
248
        /* recursion */
249
0
        code = pdfi_check_for_spots_by_array(ctx, a, parent_dict, page_dict, spot_dict);
250
0
    }
251
252
34.3k
 exit:
253
34.3k
    if (space)
254
34.3k
        pdfi_countdown(space);
255
34.3k
    if (a)
256
4
        pdfi_countdown(a);
257
34.3k
    return code;
258
34.3k
}
259
260
int pdfi_check_ColorSpace_for_spots(pdf_context *ctx, pdf_obj *space, pdf_dict *parent_dict,
261
                                    pdf_dict *page_dict, pdf_dict *spot_dict)
262
80.4k
{
263
80.4k
    int code;
264
265
80.4k
    if (!spot_dict)
266
0
        return 0;
267
268
80.4k
    code = pdfi_loop_detector_mark(ctx);
269
80.4k
    if (code < 0)
270
0
        return code;
271
272
80.4k
    switch(pdfi_type_of(space)) {
273
45.6k
        case PDF_NAME:
274
45.6k
            code = pdfi_check_for_spots_by_name(ctx, (pdf_name *)space, parent_dict, page_dict, spot_dict);
275
45.6k
            break;
276
34.3k
        case PDF_ARRAY:
277
34.3k
            code = pdfi_check_for_spots_by_array(ctx, (pdf_array *)space, parent_dict, page_dict, spot_dict);
278
34.3k
            break;
279
402
        default:
280
402
            pdfi_loop_detector_cleartomark(ctx);
281
402
            return 0;
282
80.4k
    }
283
284
80.0k
    (void)pdfi_loop_detector_cleartomark(ctx);
285
80.0k
    return code;
286
80.4k
}
287
288
/* Rendering intent is a bit of an oddity, but its clearly colour related, so we
289
 * deal with it here. Cover it first to get it out of the way.
290
 */
291
int pdfi_ri(pdf_context *ctx)
292
207k
{
293
207k
    pdf_name *n;
294
207k
    int code;
295
296
207k
    if (pdfi_count_stack(ctx) < 1)
297
33.9k
        return_error(gs_error_stackunderflow);
298
299
173k
    if (pdfi_type_of(ctx->stack_top[-1]) != PDF_NAME) {
300
3.64k
        pdfi_pop(ctx, 1);
301
3.64k
        return_error(gs_error_typecheck);
302
3.64k
    }
303
169k
    n = (pdf_name *)ctx->stack_top[-1];
304
169k
    pdfi_countup(n);
305
169k
    pdfi_pop(ctx, 1);
306
169k
    code = pdfi_setrenderingintent(ctx, n);
307
169k
    pdfi_countdown(n);
308
169k
    return code;
309
173k
}
310
311
/*
312
 * Pattern lifetime management turns out to be more complex than we would ideally like. Although
313
 * Patterns are reference counted, and contain a client_data pointer, they don't have a gs_notify
314
 * setup. This means that there's no simlpe way for us to be informed when a Pattern is released
315
 * We could patch up the Pattern finalize() method, replacing it with one of our own which calls
316
 * the original finalize() but that seems like a really nasty hack.
317
 * For the time being we put code in pdfi_grestore() to check for Pattern colour spaces being
318
 * restored away, but we also need to check for Pattern spaces being replaced in the current
319
 * graphics state. We define 'pdfi' variants of several graphics library colour management
320
 * functions to 'wrap' these with code to check for replacement of Patterns.
321
 * This comment is duplicated in pdf_pattern.c
322
 */
323
324
static void pdfi_cspace_free_callback(gs_memory_t * mem, void *cs)
325
2.58M
{
326
2.58M
    gs_color_space *pcs = (gs_color_space *)cs;
327
2.58M
    pdf_obj *o = (pdf_obj *)pcs->interpreter_data;
328
2.58M
    pdf_context *ctx = NULL;
329
2.58M
    gs_function_t *pfn;
330
331
2.58M
    if (o == NULL)
332
75
        return;
333
334
2.58M
    ctx = o->ctx;
335
336
2.58M
    if (gs_color_space_get_index(pcs) == gs_color_space_index_Separation) {
337
        /* Handle cleanup of Separation functions if applicable */
338
66.4k
        pfn = gs_cspace_get_sepr_function(pcs);
339
66.4k
        if (pfn)
340
66.4k
            pdfi_free_function(ctx, pfn);
341
66.4k
    }
342
343
2.58M
    if (gs_color_space_get_index(pcs) == gs_color_space_index_DeviceN) {
344
        /* Handle cleanup of DeviceN functions if applicable */
345
27.2k
        pfn = gs_cspace_get_devn_function(pcs);
346
27.2k
        if (pfn)
347
27.2k
            pdfi_free_function(ctx, pfn);
348
27.2k
    }
349
2.58M
    if (pdfi_type_of(o) != PDF_CTX) {
350
82.8k
        pdfi_countdown(o);
351
82.8k
        pcs->interpreter_data = NULL;
352
82.8k
    }
353
2.58M
}
354
355
int pdfi_gs_setgray(pdf_context *ctx, double d)
356
2.00M
{
357
2.00M
    int code = 0;
358
2.00M
    gs_color_space *pcs = ctx->pgs->color[0].color_space;
359
360
    /* PDF Reference 1.7 p423, any colour operators in a CharProc, following a d1, should be ignored */
361
2.00M
    if (ctx->text.inside_CharProc && ctx->text.CharProc_d_type != pdf_type3_d0) {
362
15.4k
        pdfi_log_info(ctx, "pdfi_gs_setgray", "colour operator in a CharProc, following a d1 ignored\n");
363
15.4k
        return 0;
364
15.4k
    }
365
366
1.98M
    if (ctx->page.DefaultGray_cs != NULL) {
367
0
        gs_client_color cc;
368
369
0
        code = gs_setcolorspace(ctx->pgs, ctx->page.DefaultGray_cs);
370
0
        if (code < 0)
371
0
            return code;
372
        /* If we didn't change the colour space in the graphics state, do not attempt to
373
         * set the callbacks, the current space might be inherited from PostScript.
374
         */
375
0
        if (pcs != ctx->pgs->color[0].color_space)
376
0
            pdfi_set_colour_callback(ctx->pgs->color[0].color_space, ctx, pdfi_cspace_free_callback);
377
0
        cc.paint.values[0] = d;
378
0
        cc.pattern = 0;
379
0
        return gs_setcolor(ctx->pgs, &cc);
380
1.98M
    } else {
381
1.98M
        code = gs_setgray(ctx->pgs, d);
382
1.98M
        if (code < 0)
383
12
            return code;
384
1.98M
    }
385
    /* If we didn't change the colour space in the graphics state, do not attempt to
386
     * set the callbacks, the current space might be inherited from PostScript.
387
     */
388
1.98M
    if (pcs != ctx->pgs->color[0].color_space)
389
970k
        pdfi_set_colour_callback(ctx->pgs->color[0].color_space, ctx, pdfi_cspace_free_callback);
390
1.98M
    return 0;
391
1.98M
}
392
393
int pdfi_gs_setrgbcolor(pdf_context *ctx, double r, double g, double b)
394
3.12M
{
395
3.12M
    int code = 0;
396
3.12M
    gs_color_space *pcs = ctx->pgs->color[0].color_space;
397
398
    /* PDF Reference 1.7 p423, any colour operators in a CharProc, following a d1, should be ignored */
399
3.12M
    if (ctx->text.inside_CharProc && ctx->text.CharProc_d_type != pdf_type3_d0) {
400
386
        pdfi_log_info(ctx, "pdfi_gs_setrgbcolor", "colour operator in a CharProc, following a d1 ignored\n");
401
386
        return 0;
402
386
    }
403
404
3.12M
    if (ctx->page.DefaultRGB_cs != NULL) {
405
16.6k
        gs_client_color cc;
406
407
16.6k
        code = gs_setcolorspace(ctx->pgs, ctx->page.DefaultRGB_cs);
408
16.6k
        if (code < 0)
409
0
            return code;
410
        /* If we didn't change the colour space in the graphics state, do not attempt to
411
         * set the callbacks, the current space might be inherited from PostScript.
412
         */
413
16.6k
        if (pcs != ctx->pgs->color[0].color_space)
414
5.92k
            pdfi_set_colour_callback(ctx->pgs->color[0].color_space, ctx, pdfi_cspace_free_callback);
415
16.6k
        cc.paint.values[0] = r;
416
16.6k
        cc.paint.values[1] = g;
417
16.6k
        cc.paint.values[2] = b;
418
16.6k
        cc.pattern = 0;
419
16.6k
        return gs_setcolor(ctx->pgs, &cc);
420
3.10M
    } else {
421
3.10M
        code = gs_setrgbcolor(ctx->pgs, r, g, b);
422
3.10M
        if (code < 0)
423
0
            return code;
424
        /* If we didn't change the colour space in the graphics state, do not attempt to
425
         * set the callbacks, the current space might be inherited from PostScript.
426
         */
427
3.10M
        if (pcs != ctx->pgs->color[0].color_space)
428
982k
            pdfi_set_colour_callback(ctx->pgs->color[0].color_space, ctx, pdfi_cspace_free_callback);
429
3.10M
    }
430
3.10M
    return 0;
431
3.12M
}
432
433
static int pdfi_gs_setcmykcolor(pdf_context *ctx, double c, double m, double y, double k)
434
313k
{
435
313k
    int code = 0;
436
313k
    gs_color_space *pcs = ctx->pgs->color[0].color_space;
437
438
    /* PDF Reference 1.7 p423, any colour operators in a CharProc, following a d1, should be ignored */
439
313k
    if (ctx->text.inside_CharProc && ctx->text.CharProc_d_type != pdf_type3_d0) {
440
48
        pdfi_log_info(ctx, "pdfi_gs_setcmykcolor", "colour operator in a CharProc, following a d1 ignored\n");
441
48
        return 0;
442
48
    }
443
444
313k
    if (ctx->page.DefaultCMYK_cs != NULL) {
445
0
        gs_client_color cc;
446
447
0
        code = gs_setcolorspace(ctx->pgs, ctx->page.DefaultCMYK_cs);
448
0
        if (code < 0)
449
0
            return code;
450
        /* If we didn't change the colour space in the graphics state, do not attempt to
451
         * set the callbacks, the current space might be inherited from PostScript.
452
         */
453
0
        if (pcs != ctx->pgs->color[0].color_space)
454
0
            pdfi_set_colour_callback(ctx->pgs->color[0].color_space, ctx, pdfi_cspace_free_callback);
455
0
        cc.paint.values[0] = c;
456
0
        cc.paint.values[1] = m;
457
0
        cc.paint.values[2] = y;
458
0
        cc.paint.values[3] = k;
459
0
        cc.pattern = 0;
460
0
        return gs_setcolor(ctx->pgs, &cc);
461
313k
    } else {
462
313k
        code = gs_setcmykcolor(ctx->pgs, c, m, y, k);
463
313k
        if (code < 0)
464
0
            return code;
465
        /* If we didn't change the colour space in the graphics state, do not attempt to
466
         * set the callbacks, the current space might be inherited from PostScript.
467
         */
468
313k
        if (pcs != ctx->pgs->color[0].color_space)
469
156k
            pdfi_set_colour_callback(ctx->pgs->color[0].color_space, ctx, pdfi_cspace_free_callback);
470
313k
    }
471
313k
    return 0;
472
313k
}
473
474
int pdfi_gs_setcolorspace(pdf_context *ctx, gs_color_space *pcs)
475
563k
{
476
563k
    gs_color_space *old_pcs = ctx->pgs->color[0].color_space;
477
563k
    int code = 0;
478
    /* If the target colour space is already the current colour space, don't
479
     * bother to do anything.
480
     */
481
563k
    if (ctx->pgs->color[0].color_space->id != pcs->id) {
482
        /* PDF Reference 1.7 p423, any colour operators in a CharProc, following a d1, should be ignored */
483
526k
        if (ctx->text.inside_CharProc && ctx->text.CharProc_d_type != pdf_type3_d0) {
484
7
            pdfi_log_info(ctx, "pdfi_gs_setcolorspace", "colour operator in a CharProc, following a d1 ignored\n");
485
7
            return 0;
486
7
        }
487
488
526k
        code = gs_setcolorspace(ctx->pgs, pcs);
489
526k
        if (code < 0)
490
0
            return code;
491
        /* If we didn't change the colour space in the graphics state, do not attempt to
492
         * set the callbacks, the current space might be inherited from PostScript.
493
         */
494
526k
        if (old_pcs != ctx->pgs->color[0].color_space)
495
526k
            pdfi_set_colour_callback(ctx->pgs->color[0].color_space, ctx, pdfi_cspace_free_callback);
496
526k
    }
497
563k
    return 0;
498
563k
}
499
500
/* Start with the simple cases, where we set the colour space and colour in a single operation */
501
int pdfi_setgraystroke(pdf_context *ctx)
502
843k
{
503
843k
    int code;
504
843k
    double d1;
505
506
843k
    code = pdfi_destack_real(ctx, &d1);
507
843k
    if (code < 0)
508
28.7k
        return code;
509
510
815k
    gs_swapcolors_quick(ctx->pgs);
511
815k
    code = pdfi_gs_setgray(ctx, d1);
512
815k
    gs_swapcolors_quick(ctx->pgs);
513
514
815k
    return code;
515
843k
}
516
517
int pdfi_setgrayfill(pdf_context *ctx)
518
1.17M
{
519
1.17M
    int code;
520
1.17M
    double d1;
521
522
1.17M
    code = pdfi_destack_real(ctx, &d1);
523
1.17M
    if (code < 0)
524
19.9k
        return code;
525
526
1.15M
    return pdfi_gs_setgray(ctx, d1);
527
1.17M
}
528
529
int pdfi_setrgbstroke(pdf_context *ctx)
530
1.33M
{
531
1.33M
    double Values[3];
532
1.33M
    int code;
533
534
1.33M
    code = pdfi_destack_reals(ctx, Values, 3);
535
1.33M
    if (code < 0)
536
65.5k
        return code;
537
538
1.27M
    gs_swapcolors_quick(ctx->pgs);
539
1.27M
    code = pdfi_gs_setrgbcolor(ctx, Values[0], Values[1], Values[2]);
540
1.27M
    gs_swapcolors_quick(ctx->pgs);
541
542
1.27M
    return code;
543
1.33M
}
544
545
/* Non-standard operator that is used in some annotation /DA
546
 * Expects stack to be [r g b]
547
 */
548
int pdfi_setrgbfill_array(pdf_context *ctx)
549
73.2k
{
550
73.2k
    int code;
551
73.2k
    pdf_array *array = NULL;
552
553
73.2k
    pdfi_set_warning(ctx, 0, NULL, W_PDF_NONSTANDARD_OP, "pdfi_setrgbfill_array", (char *)"WARNING: Non-standard 'r' operator");
554
555
73.2k
    if (pdfi_count_stack(ctx) < 1)
556
17.7k
        return_error(gs_error_stackunderflow);
557
558
55.4k
    array = (pdf_array *)ctx->stack_top[-1];
559
55.4k
    pdfi_countup(array);
560
55.4k
    pdfi_pop(ctx, 1);
561
55.4k
    if (pdfi_type_of(array) != PDF_ARRAY) {
562
55.3k
        code = gs_note_error(gs_error_typecheck);
563
55.3k
        goto exit;
564
55.3k
    }
565
566
82
    code = pdfi_setcolor_from_array(ctx, array);
567
55.4k
 exit:
568
55.4k
    pdfi_countdown(array);
569
55.4k
    return code;
570
82
}
571
572
int pdfi_setrgbfill(pdf_context *ctx)
573
1.84M
{
574
1.84M
    double Values[3];
575
1.84M
    int code;
576
577
1.84M
    code = pdfi_destack_reals(ctx, Values, 3);
578
1.84M
    if (code < 0)
579
54.4k
        return code;
580
581
1.78M
    return pdfi_gs_setrgbcolor(ctx, Values[0], Values[1], Values[2]);
582
1.84M
}
583
584
int pdfi_setcmykstroke(pdf_context *ctx)
585
67.7k
{
586
67.7k
    double Values[4];
587
67.7k
    int code;
588
589
67.7k
    code = pdfi_destack_reals(ctx, Values, 4);
590
67.7k
    if (code < 0)
591
10.2k
        return code;
592
593
57.4k
    gs_swapcolors_quick(ctx->pgs);
594
57.4k
    code = pdfi_gs_setcmykcolor(ctx, Values[0], Values[1], Values[2], Values[3]);
595
57.4k
    gs_swapcolors_quick(ctx->pgs);
596
597
57.4k
    return code;
598
67.7k
}
599
600
int pdfi_setcmykfill(pdf_context *ctx)
601
241k
{
602
241k
    double Values[4];
603
241k
    int code;
604
605
241k
    code = pdfi_destack_reals(ctx, Values, 4);
606
241k
    if (code < 0)
607
15.7k
        return code;
608
609
225k
    return pdfi_gs_setcmykcolor(ctx, Values[0], Values[1], Values[2], Values[3]);
610
241k
}
611
612
/* Do a setcolor using values in an array
613
 * Will do gray, rgb, cmyk for sizes 1,3,4
614
 * Anything else is an error
615
 */
616
int pdfi_setcolor_from_array(pdf_context *ctx, pdf_array *array)
617
8.67k
{
618
8.67k
    int code = 0;
619
8.67k
    uint64_t size;
620
8.67k
    double values[4];
621
622
8.67k
    size = pdfi_array_size(array);
623
8.67k
    if (size != 1 && size != 3 && size != 4) {
624
77
        code = gs_note_error(gs_error_rangecheck);
625
77
        goto exit;
626
77
    }
627
628
8.59k
    code = pdfi_array_to_num_array(ctx, array, values, 0, size);
629
8.59k
    if (code < 0) goto exit;
630
631
8.55k
    switch (size) {
632
265
    case 1:
633
265
        code = pdfi_gs_setgray(ctx, values[0]);
634
265
        break;
635
8.27k
    case 3:
636
8.27k
        code = pdfi_gs_setrgbcolor(ctx, values[0], values[1], values[2]);
637
8.27k
        break;
638
13
    case 4:
639
13
        code = pdfi_gs_setcmykcolor(ctx, values[0], values[1], values[2], values[3]);
640
13
        break;
641
0
    default:
642
0
        break;
643
8.55k
    }
644
645
8.67k
 exit:
646
8.67k
    return code;
647
8.55k
}
648
649
/* Get colors from top of stack into a client color */
650
static int
651
pdfi_get_color_from_stack(pdf_context *ctx, gs_client_color *cc, int ncomps)
652
540k
{
653
540k
    int i, code;
654
655
540k
    if (pdfi_count_stack(ctx) < ncomps) {
656
24.0k
        pdfi_clearstack(ctx);
657
24.0k
        return_error(gs_error_stackunderflow);
658
24.0k
    }
659
660
1.66M
    for (i = 0; i < ncomps; i++) {
661
1.16M
        code = pdfi_obj_to_float(ctx, ctx->stack_top[i - ncomps], &cc->paint.values[i]);
662
1.16M
        if (code < 0) {
663
13.7k
            pdfi_clearstack(ctx);
664
13.7k
            return code;
665
13.7k
        }
666
1.16M
    }
667
502k
    pdfi_pop(ctx, ncomps);
668
669
502k
    return 0;
670
516k
}
671
672
/* Now deal with the case where we have to set the colour space separately from the
673
 * colour values. We'll start with the routines to set the colour, because setting
674
 * colour components is relatively easy.
675
 */
676
677
/* First up, the SC and sc operators. These set the colour for all spaces *except*
678
 * ICCBased, Pattern, Separation and DeviceN
679
 */
680
int pdfi_setstrokecolor(pdf_context *ctx)
681
96.7k
{
682
96.7k
    const gs_color_space *  pcs;
683
96.7k
    int ncomps, code;
684
96.7k
    gs_client_color cc;
685
686
96.7k
    if (ctx->text.inside_CharProc && ctx->text.CharProc_d_type != pdf_type3_d0) {
687
        /* There will have been a preceding operator to set the colour space, which we
688
         * will have ignored, so now we don't know how many components to expect!
689
         * Just clear the stack and hope for the best.
690
         */
691
0
        pdfi_clearstack(ctx);
692
0
        pdfi_log_info(ctx, "pdfi_setstrokecolor", "colour operator in a CharProc, following a d1 ignored\n");
693
0
        return 0;
694
0
    }
695
696
96.7k
    cc.pattern = 0;
697
96.7k
    gs_swapcolors_quick(ctx->pgs);
698
96.7k
    pcs = gs_currentcolorspace(ctx->pgs);
699
96.7k
    ncomps = cs_num_components(pcs);
700
96.7k
    if (ncomps < 1) {
701
3
        gs_swapcolors_quick(ctx->pgs);
702
3
        return_error(gs_error_syntaxerror);
703
3
    }
704
96.7k
    code = pdfi_get_color_from_stack(ctx, &cc, ncomps);
705
96.7k
    if (code == 0) {
706
93.7k
        if (pcs->type == &gs_color_space_type_Indexed) {
707
            /* Special handling for floating point colour values
708
             * PostScript doesn't specify what should happen with a float
709
             * lookup value. PDF says 'nearest integer' and round 0.5 up.
710
             * Doing this in the graphics library caused some (tiny) differences
711
             * in output files, so instead perform that check here.
712
             * The out of range clamping is already correct in the graphics library.
713
             */
714
0
            int index = (int)floor(cc.paint.values[0]);
715
716
0
            if(cc.paint.values[0] - index > 0.49999)
717
0
                index++;
718
0
            cc.paint.values[0] = (float)index;
719
0
        }
720
93.7k
        code = gs_setcolor(ctx->pgs, &cc);
721
93.7k
    }
722
96.7k
    gs_swapcolors_quick(ctx->pgs);
723
96.7k
    return code;
724
96.7k
}
725
726
int pdfi_setfillcolor(pdf_context *ctx)
727
309k
{
728
309k
    const gs_color_space *  pcs = gs_currentcolorspace(ctx->pgs);
729
309k
    int ncomps, code;
730
309k
    gs_client_color cc;
731
732
309k
    if (ctx->text.inside_CharProc && ctx->text.CharProc_d_type != pdf_type3_d0) {
733
        /* There will have been a preceding operator to set the colour space, which we
734
         * will have ignored, so now we don't know how many components to expect!
735
         * Just clear the stack and hope for the best.
736
         */
737
0
        pdfi_clearstack(ctx);
738
0
        pdfi_log_info(ctx, "pdfi_setfillcolor", "colour operator in a CharProc, following a d1 ignored\n");
739
0
        return 0;
740
0
    }
741
742
309k
    cc.pattern = 0;
743
309k
    ncomps = cs_num_components(pcs);
744
309k
    if (ncomps < 1)
745
224
        return_error(gs_error_syntaxerror);
746
309k
    code = pdfi_get_color_from_stack(ctx, &cc, ncomps);
747
309k
    if (code == 0) {
748
297k
        if (pcs->type == &gs_color_space_type_Indexed) {
749
            /* Special handling for floating point colour values
750
             * PostScript doesn't specify what should happen with a float
751
             * lookup value. PDF says 'nearest integer' and round 0.5 up.
752
             * Doing this in the graphics library caused some (tiny) differences
753
             * in output files, so instead perform that check here.
754
             * The out of range clamping is already correct in the graphics library.
755
             */
756
210
            int index = (int)floor(cc.paint.values[0]);
757
758
210
            if(cc.paint.values[0] - index > 0.49999)
759
7
                index++;
760
210
            cc.paint.values[0] = (float)index;
761
210
        }
762
297k
        code = gs_setcolor(ctx->pgs, &cc);
763
297k
    }
764
309k
    return code;
765
309k
}
766
767
static inline bool
768
pattern_instance_uses_base_space(const gs_pattern_instance_t * pinst)
769
342
{
770
342
    return pinst->type->procs.uses_base_space(
771
342
                   pinst->type->procs.get_pattern(pinst) );
772
342
}
773
774
/* Now the SCN and scn operators. These set the colour for special spaces;
775
 * ICCBased, Pattern, Separation and DeviceN
776
 */
777
int
778
pdfi_setcolorN(pdf_context *ctx, pdf_dict *stream_dict, pdf_dict *page_dict, bool is_fill)
779
220k
{
780
220k
    gs_color_space *pcs;
781
220k
    gs_color_space *base_space = NULL;
782
220k
    int ncomps=0, code = 0;
783
220k
    gs_client_color cc;
784
220k
    bool is_pattern = false;
785
786
220k
    if (ctx->text.inside_CharProc && ctx->text.CharProc_d_type != pdf_type3_d0) {
787
        /* There will have been a preceding operator to set the colour space, which we
788
         * will have ignored, so now we don't know how many components to expect!
789
         * Just clear the stack and hope for the best.
790
         */
791
7
        pdfi_clearstack(ctx);
792
7
        pdfi_log_info(ctx, "pdfi_setcolorN", "colour operator in a CharProc, following a d1 ignored\n");
793
7
        return 0;
794
7
    }
795
796
220k
    if (!is_fill) {
797
26.6k
        gs_swapcolors_quick(ctx->pgs);
798
26.6k
    }
799
220k
    pcs = gs_currentcolorspace(ctx->pgs);
800
801
220k
    if (pdfi_count_stack(ctx) < 1) {
802
2.59k
        code = gs_note_error(gs_error_stackunderflow);
803
2.59k
        goto cleanupExit1;
804
2.59k
    }
805
806
217k
    memset(&cc, 0x00, sizeof(gs_client_color));
807
808
217k
    if (pcs->type == &gs_color_space_type_Pattern)
809
84.1k
        is_pattern = true;
810
217k
    if (is_pattern) {
811
84.1k
        pdf_name *n = NULL;
812
813
84.1k
        if (pdfi_type_of(ctx->stack_top[-1]) != PDF_NAME) {
814
139
            pdfi_clearstack(ctx);
815
139
            code = gs_note_error(gs_error_typecheck);
816
139
            goto cleanupExit0;
817
139
        }
818
84.0k
        n = (pdf_name *)ctx->stack_top[-1];
819
84.0k
        pdfi_countup(n);
820
84.0k
        pdfi_pop(ctx, 1);
821
822
84.0k
        base_space = pcs->base_space;
823
84.0k
        code = pdfi_pattern_set(ctx, stream_dict, page_dict, n, &cc);
824
84.0k
        pdfi_countdown(n);
825
84.0k
        if (code < 0) {
826
            /* Ignore the pattern if we failed to set it */
827
44.5k
            code = pdfi_set_warning_stop(ctx, code, NULL, W_PDF_BADPATTERN, "pdfi_setcolorN", (char *)"PATTERN: Error setting pattern");
828
44.5k
            goto cleanupExit1;
829
44.5k
        }
830
39.4k
        if (base_space && pattern_instance_uses_base_space(cc.pattern))
831
326
            ncomps = cs_num_components(base_space);
832
39.1k
        else
833
39.1k
            ncomps = 0;
834
39.4k
    } else
835
133k
        ncomps = cs_num_components(pcs);
836
837
173k
    if (ncomps > 0) {
838
133k
        code = pdfi_get_color_from_stack(ctx, &cc, ncomps);
839
133k
        if (code < 0)
840
23.3k
            goto cleanupExit1;
841
133k
    }
842
843
149k
    if (pcs->type == &gs_color_space_type_Indexed) {
844
0
        if (ncomps <= 0)
845
0
        {
846
0
            code = gs_note_error(gs_error_rangecheck);
847
0
            goto cleanupExit1;
848
0
        }
849
0
        if (cc.paint.values[0] < 0)
850
0
            cc.paint.values[0] = 0.0;
851
0
        else
852
0
        {
853
0
            if (cc.paint.values[0] > pcs->params.indexed.hival)
854
0
                cc.paint.values[0] = (float)pcs->params.indexed.hival;
855
0
            else
856
0
            {
857
0
                if (cc.paint.values[0] != floor(cc.paint.values[0]))
858
0
                {
859
0
                    if (cc.paint.values[0] - floor(cc.paint.values[0]) < 0.5)
860
0
                        cc.paint.values[0] = floor(cc.paint.values[0]);
861
0
                    else
862
0
                        cc.paint.values[0] = ceil(cc.paint.values[0]);
863
0
                }
864
0
            }
865
0
        }
866
0
    }
867
868
149k
    code = gs_setcolor(ctx->pgs, &cc);
869
870
220k
cleanupExit1:
871
220k
    if (is_pattern)
872
        /* cc is a local scope variable, holding a reference to a pattern.
873
         * We need to count the refrence down before the variable goes out of scope
874
         * in order to prevent the pattern leaking.
875
         */
876
220k
        rc_decrement(cc.pattern, "pdfi_setcolorN");
877
878
220k
cleanupExit0:
879
220k
    if (!is_fill)
880
26.6k
        gs_swapcolors_quick(ctx->pgs);
881
220k
    return code;
882
220k
}
883
884
/* And now, the routines to set the colour space on its own. */
885
886
/* Starting with the ICCBased colour space */
887
888
/* This routine is mostly a copy of seticc() in zicc.c */
889
static int pdfi_create_icc(pdf_context *ctx, char *Name, stream *s, int ncomps, int *icc_N, float *range_buff, ulong dictkey, gs_color_space **ppcs)
890
44.5k
{
891
44.5k
    int                     code, k;
892
44.5k
    gs_color_space *        pcs;
893
44.5k
    cmm_profile_t           *picc_profile = NULL;
894
44.5k
    int                     i, expected = 0;
895
896
44.5k
    static const char *const icc_std_profile_names[] = {
897
44.5k
            GSICC_STANDARD_PROFILES
898
44.5k
        };
899
44.5k
    static const char *const icc_std_profile_keys[] = {
900
44.5k
            GSICC_STANDARD_PROFILES_KEYS
901
44.5k
        };
902
903
44.5k
    if (ppcs!= NULL)
904
44.5k
        *ppcs = NULL;
905
906
    /* We need to use the graphics state memory, and beyond that we need to use stable memory, because the
907
     * ICC cache can persist until the end of job, and so the profile (which is stored in teh cache)
908
     * must likewise persist.
909
     */
910
44.5k
    code = gs_cspace_build_ICC(&pcs, NULL, (gs_gstate_memory(ctx->pgs))->stable_memory);
911
44.5k
    if (code < 0)
912
0
        return code;
913
914
44.5k
    if (Name != NULL){
915
        /* Compare this to the standard profile names */
916
10.4k
        for (k = 0; k < GSICC_NUMBER_STANDARD_PROFILES; k++) {
917
10.4k
            if ( strcmp( Name, icc_std_profile_keys[k] ) == 0 ) {
918
5.57k
                picc_profile = gsicc_get_profile_handle_file(icc_std_profile_names[k],
919
5.57k
                    strlen(icc_std_profile_names[k]), gs_gstate_memory(ctx->pgs));
920
5.57k
                break;
921
5.57k
            }
922
10.4k
        }
923
38.9k
    } else {
924
38.9k
        if (s == NULL)
925
0
            return_error(gs_error_undefined);
926
927
38.9k
        picc_profile = gsicc_profile_new(s, gs_gstate_memory(ctx->pgs), NULL, 0);
928
38.9k
        if (picc_profile == NULL) {
929
8.09k
            rc_decrement(pcs,"pdfi_create_icc");
930
8.09k
            return gs_throw(gs_error_VMerror, "pdfi_create_icc Creation of ICC profile failed");
931
8.09k
        }
932
        /* We have to get the profile handle due to the fact that we need to know
933
           if it has a data space that is CIELAB */
934
30.8k
        picc_profile->profile_handle =
935
30.8k
            gsicc_get_profile_handle_buffer(picc_profile->buffer,
936
30.8k
                                            picc_profile->buffer_size,
937
30.8k
                                            gs_gstate_memory(ctx->pgs));
938
30.8k
    }
939
940
36.4k
    if (picc_profile == NULL || picc_profile->profile_handle == NULL) {
941
        /* Free up everything, the profile is not valid. We will end up going
942
           ahead and using a default based upon the number of components */
943
4.91k
        rc_decrement(picc_profile,"pdfi_create_icc");
944
4.91k
        rc_decrement(pcs,"pdfi_create_icc");
945
4.91k
        return -1;
946
4.91k
    }
947
31.5k
    code = gsicc_set_gscs_profile(pcs, picc_profile, gs_gstate_memory(ctx->pgs));
948
31.5k
    if (code < 0) {
949
0
        rc_decrement(picc_profile,"pdfi_create_icc");
950
0
        rc_decrement(pcs,"pdfi_create_icc");
951
0
        return code;
952
0
    }
953
954
31.5k
    picc_profile->data_cs =
955
31.5k
        gscms_get_profile_data_space(picc_profile->profile_handle,
956
31.5k
            picc_profile->memory);
957
31.5k
    switch (picc_profile->data_cs) {
958
0
        case gsCIEXYZ:
959
0
        case gsCIELAB:
960
19.3k
        case gsRGB:
961
19.3k
            expected = 3;
962
19.3k
            break;
963
11.8k
        case gsGRAY:
964
11.8k
            expected = 1;
965
11.8k
            break;
966
38
        case gsCMYK:
967
38
            expected = 4;
968
38
            break;
969
260
        case gsNCHANNEL:
970
260
        case gsNAMED:            /* Silence warnings */
971
260
        case gsUNDEFINED:        /* Silence warnings */
972
260
            break;
973
31.5k
    }
974
31.5k
    if (expected == 0) {
975
260
        rc_decrement(picc_profile,"pdfi_create_icc");
976
260
        rc_decrement(pcs,"pdfi_create_icc");
977
260
        return_error(gs_error_rangecheck);
978
260
    }
979
    /* Return the number of components the ICC profile has */
980
31.2k
    *icc_N = expected;
981
31.2k
    if (expected != ncomps) {
982
21
        if ((code = pdfi_set_error_stop(ctx, gs_note_error(gs_error_rangecheck), NULL, E_PDF_ICC_BAD_N, "pdfi_create_icc", "")) < 0)
983
0
            goto exit;
984
21
        ncomps = expected;
985
21
    }
986
987
31.2k
    picc_profile->num_comps = ncomps;
988
    /* Lets go ahead and get the hash code and check if we match one of the default spaces */
989
    /* Later we may want to delay this, but for now lets go ahead and do it */
990
31.2k
    gsicc_init_hash_cs(picc_profile, ctx->pgs);
991
992
    /* Set the range according to the data type that is associated with the
993
       ICC input color type.  Occasionally, we will run into CIELAB to CIELAB
994
       profiles for spot colors in PDF documents. These spot colors are typically described
995
       as separation colors with tint transforms that go from a tint value
996
       to a linear mapping between the CIELAB white point and the CIELAB tint
997
       color.  This results in a CIELAB value that we need to use to fill.  We
998
       need to detect this to make sure we do the proper scaling of the data.  For
999
       CIELAB images in PDF, the source is always normal 8 or 16 bit encoded data
1000
       in the range from 0 to 255 or 0 to 65535.  In that case, there should not
1001
       be any encoding and decoding to CIELAB.  The PDF content will not include
1002
       an ICC profile but will set the color space to \Lab.  In this case, we use
1003
       our seticc_lab operation to install the LAB to LAB profile, but we detect
1004
       that we did that through the use of the is_lab flag in the profile descriptor.
1005
       When then avoid the CIELAB encode and decode */
1006
31.2k
    if (picc_profile->data_cs == gsCIELAB) {
1007
    /* If the input space to this profile is CIELAB, then we need to adjust the limits */
1008
        /* See ICC spec ICC.1:2004-10 Section 6.3.4.2 and 6.4.  I don't believe we need to
1009
           worry about CIEXYZ profiles or any of the other odds ones.  Need to check that though
1010
           at some point. */
1011
0
        picc_profile->Range.ranges[0].rmin = 0.0;
1012
0
        picc_profile->Range.ranges[0].rmax = 100.0;
1013
0
        picc_profile->Range.ranges[1].rmin = -128.0;
1014
0
        picc_profile->Range.ranges[1].rmax = 127.0;
1015
0
        picc_profile->Range.ranges[2].rmin = -128.0;
1016
0
        picc_profile->Range.ranges[2].rmax = 127.0;
1017
0
        picc_profile->islab = true;
1018
31.2k
    } else {
1019
101k
        for (i = 0; i < ncomps; i++) {
1020
70.1k
            picc_profile->Range.ranges[i].rmin = range_buff[2 * i];
1021
70.1k
            picc_profile->Range.ranges[i].rmax = range_buff[2 * i + 1];
1022
70.1k
        }
1023
31.2k
    }
1024
    /* Now see if we are in an overide situation.  We have to wait until now
1025
       in case this is an LAB profile which we will not overide */
1026
31.2k
    if (gs_currentoverrideicc(ctx->pgs) && picc_profile->data_cs != gsCIELAB) {
1027
        /* Free up the profile structure */
1028
205
        switch( picc_profile->data_cs ) {
1029
0
            case gsRGB:
1030
0
                pcs->cmm_icc_profile_data = ctx->pgs->icc_manager->default_rgb;
1031
0
                break;
1032
205
            case gsGRAY:
1033
205
                pcs->cmm_icc_profile_data = ctx->pgs->icc_manager->default_gray;
1034
205
                break;
1035
0
            case gsCMYK:
1036
0
                pcs->cmm_icc_profile_data = ctx->pgs->icc_manager->default_cmyk;
1037
0
                break;
1038
0
            default:
1039
0
                break;
1040
205
        }
1041
        /* Have one increment from the color space.  Having these tied
1042
           together is not really correct.  Need to fix that.  ToDo.  MJV */
1043
205
        rc_adjust(picc_profile, -2, "pdfi_create_icc");
1044
205
        rc_increment(pcs->cmm_icc_profile_data);
1045
205
    }
1046
    /* Add the color space to the profile cache */
1047
31.2k
    if (dictkey != 0) {
1048
25.5k
        code = gsicc_add_cs(ctx->pgs, pcs, dictkey);
1049
25.5k
        if (code < 0)
1050
0
            goto exit;
1051
25.5k
    }
1052
1053
31.2k
    if (ppcs!= NULL){
1054
31.2k
        *ppcs = pcs;
1055
31.2k
        pdfi_set_colour_callback(pcs, ctx, pdfi_cspace_free_callback);
1056
31.2k
    } else {
1057
0
        code = pdfi_gs_setcolorspace(ctx, pcs);
1058
0
        rc_decrement_only_cs(pcs, "pdfi_create_icc");
1059
0
    }
1060
1061
31.2k
exit:
1062
    /* The context has taken a reference to the colorspace. We no longer need
1063
     * ours, so drop it. */
1064
31.2k
    rc_decrement(picc_profile, "pdfi_create_icc");
1065
31.2k
    return code;
1066
31.2k
}
1067
1068
static int pdfi_create_iccprofile(pdf_context *ctx, pdf_stream *ICC_obj, char *cname,
1069
                                  int64_t Length, int N, int *icc_N, float *range, gs_color_space **ppcs)
1070
242k
{
1071
242k
    pdf_c_stream *profile_stream = NULL;
1072
242k
    byte *profile_buffer;
1073
242k
    int code, code1;
1074
242k
    ulong dictkey = 0;
1075
1076
    /* See if the color space is in the profile cache */
1077
    /* NOTE! 0 indicates a named colour space for JPX images, do not attempt to
1078
     * find a cached space for this. Conveniently should we somehow manage to get
1079
     * here from an array or other object which is not an indirect reference then we will
1080
     * again not attempt to cache the space or lookup the cache.
1081
     */
1082
242k
    if (!gs_currentoverrideicc(ctx->pgs)) {
1083
242k
        if (ICC_obj->object_num != 0) {
1084
242k
            gs_color_space *pcs = NULL;
1085
1086
242k
            pcs = gsicc_find_cs(ICC_obj->object_num, ctx->pgs);
1087
242k
            if (pcs != NULL) {
1088
202k
                if (ppcs!= NULL){
1089
202k
                    *ppcs = pcs;
1090
202k
                } else {
1091
0
                    code = pdfi_gs_setcolorspace(ctx, pcs);
1092
0
                    rc_decrement_only_cs(pcs, "pdfi_create_iccprofile");
1093
0
                }
1094
202k
                *icc_N = gs_color_space_num_components(pcs);
1095
                /* We're passing back a new reference, increment the count */
1096
202k
                rc_adjust_only(pcs, 1, "pdfi_create_iccprofile, return cached ICC profile");
1097
202k
                return 0;
1098
202k
            }
1099
39.3k
            dictkey = ICC_obj->object_num;
1100
39.3k
        }
1101
242k
    }
1102
1103
    /* The ICC profile reading code (irritatingly) requires a seekable stream, because it
1104
     * rewinds it to the start, then seeks to the end to find the size, then rewinds the
1105
     * stream again.
1106
     * Ideally we would use a ReusableStreamDecode filter here, but that is largely
1107
     * implemented in PostScript (!) so we can't use it. What we can do is create a
1108
     * string sourced stream in memory, which is at least seekable.
1109
     */
1110
39.5k
    code = pdfi_open_memory_stream_from_filtered_stream(ctx, ICC_obj, &profile_buffer, &profile_stream, true);
1111
39.5k
    if (code < 0) {
1112
573
        return code;
1113
573
    }
1114
1115
    /* Now, finally, we can call the code to create and set the profile */
1116
38.9k
    code = pdfi_create_icc(ctx, cname, profile_stream->s, (int)N, icc_N, range, dictkey, ppcs);
1117
1118
38.9k
    code1 = pdfi_close_memory_stream(ctx, profile_buffer, profile_stream);
1119
1120
38.9k
    if (code == 0)
1121
25.7k
        code = code1;
1122
1123
38.9k
    return code;
1124
39.5k
}
1125
1126
static int pdfi_set_CalGray_params(pdf_context *ctx, gs_color_space *pcs, pdf_dict *ParamsDict)
1127
0
{
1128
0
    int code = 0, i;
1129
0
    double f;
1130
    /* The default values here are as per the PDF 1.7 specification, there is
1131
     * no default for the WhitePoint as it is a required entry.
1132
     */
1133
0
    float WhitePoint[3], BlackPoint[3] = {0.0f, 0.0f, 0.0f}, Gamma = 1.0f;
1134
0
    pdf_array *PDFArray = NULL;
1135
1136
0
    code = pdfi_dict_get_type(ctx, ParamsDict, "WhitePoint", PDF_ARRAY, (pdf_obj **)&PDFArray);
1137
0
    if (code < 0) {
1138
0
        pdfi_countdown(PDFArray);
1139
0
        goto exit;
1140
0
    }
1141
0
    if (pdfi_array_size(PDFArray) != 3){
1142
0
        code = gs_note_error(gs_error_rangecheck);
1143
0
        goto exit;
1144
0
    }
1145
1146
0
    for (i=0; i < 3; i++) {
1147
0
        code = pdfi_array_get_number(ctx, PDFArray, (uint64_t)i, &f);
1148
0
        if (code < 0)
1149
0
            goto exit;
1150
0
        WhitePoint[i] = (float)f;
1151
0
    }
1152
0
    pdfi_countdown(PDFArray);
1153
0
    PDFArray = NULL;
1154
1155
    /* Check the WhitePoint values, the PDF 1.7 reference states that
1156
     * Xw ad Zw must be positive and Yw must be 1.0
1157
     */
1158
0
    if (WhitePoint[0] < 0 || WhitePoint[2] < 0 || WhitePoint[1] != 1.0f) {
1159
0
        code = gs_note_error(gs_error_rangecheck);
1160
0
        goto exit;
1161
0
    }
1162
1163
0
    if (pdfi_dict_knownget_type(ctx, ParamsDict, "BlackPoint", PDF_ARRAY, (pdf_obj **)&PDFArray) > 0) {
1164
0
        if (pdfi_array_size(PDFArray) != 3){
1165
0
            code = gs_note_error(gs_error_rangecheck);
1166
0
            goto exit;
1167
0
        }
1168
0
        for (i=0; i < 3; i++) {
1169
0
            code = pdfi_array_get_number(ctx, PDFArray, (uint64_t)i, &f);
1170
0
            if (code < 0)
1171
0
                goto exit;
1172
            /* The PDF 1.7 reference states that all three components of the BlackPoint
1173
             * (if present) must be positive.
1174
             */
1175
0
            if (f < 0) {
1176
0
                code = gs_note_error(gs_error_rangecheck);
1177
0
                goto exit;
1178
0
            }
1179
0
            BlackPoint[i] = (float)f;
1180
0
        }
1181
0
        pdfi_countdown(PDFArray);
1182
0
        PDFArray = NULL;
1183
0
    }
1184
1185
0
    if (pdfi_dict_knownget_number(ctx, ParamsDict, "Gamma", &f) > 0)
1186
0
        Gamma = (float)f;
1187
    /* The PDF 1.7 reference states that Gamma
1188
     * (if present) must be positive.
1189
     */
1190
0
    if (Gamma < 0) {
1191
0
        code = gs_note_error(gs_error_rangecheck);
1192
0
        goto exit;
1193
0
    }
1194
0
    code = 0;
1195
1196
0
    for (i = 0;i < 3; i++) {
1197
0
        pcs->params.calgray.WhitePoint[i] = WhitePoint[i];
1198
0
        pcs->params.calgray.BlackPoint[i] = BlackPoint[i];
1199
0
    }
1200
0
    pcs->params.calgray.Gamma = Gamma;
1201
1202
0
exit:
1203
0
    pdfi_countdown(PDFArray);
1204
0
    return code;
1205
0
}
1206
1207
static int pdfi_set_CalRGB_params(pdf_context *ctx, gs_color_space *pcs, pdf_dict *ParamsDict)
1208
0
{
1209
0
    int code = 0, i;
1210
0
    pdf_array *PDFArray = NULL;
1211
    /* The default values here are as per the PDF 1.7 specification, there is
1212
     * no default for the WhitePoint as it is a required entry
1213
     */
1214
0
    float WhitePoint[3], BlackPoint[3] = {0.0f, 0.0f, 0.0f}, Gamma[3] = {1.0f, 1.0f, 1.0f};
1215
0
    float Matrix[9] = {1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f};
1216
0
    double f;
1217
1218
0
    code = pdfi_dict_get_type(ctx, ParamsDict, "WhitePoint", PDF_ARRAY, (pdf_obj **)&PDFArray);
1219
0
    if (code < 0) {
1220
0
        pdfi_countdown(PDFArray);
1221
0
        goto exit;
1222
0
    }
1223
0
    if (pdfi_array_size(PDFArray) != 3){
1224
0
        code = gs_note_error(gs_error_rangecheck);
1225
0
        goto exit;
1226
0
    }
1227
1228
0
    for (i=0; i < 3; i++) {
1229
0
        code = pdfi_array_get_number(ctx, PDFArray, (uint64_t)i, &f);
1230
0
        if (code < 0)
1231
0
            goto exit;
1232
0
        WhitePoint[i] = (float)f;
1233
0
    }
1234
0
    pdfi_countdown(PDFArray);
1235
0
    PDFArray = NULL;
1236
1237
    /* Check the WhitePoint values, the PDF 1.7 reference states that
1238
     * Xw ad Zw must be positive and Yw must be 1.0
1239
     */
1240
0
    if (WhitePoint[0] < 0 || WhitePoint[2] < 0 || WhitePoint[1] != 1.0f) {
1241
0
        code = gs_note_error(gs_error_rangecheck);
1242
0
        goto exit;
1243
0
    }
1244
1245
0
    if (pdfi_dict_knownget_type(ctx, ParamsDict, "BlackPoint", PDF_ARRAY, (pdf_obj **)&PDFArray) > 0) {
1246
0
        if (pdfi_array_size(PDFArray) != 3){
1247
0
            code = gs_note_error(gs_error_rangecheck);
1248
0
            goto exit;
1249
0
        }
1250
0
        for (i=0; i < 3; i++) {
1251
0
            code = pdfi_array_get_number(ctx, PDFArray, (uint64_t)i, &f);
1252
0
            if (code < 0)
1253
0
                goto exit;
1254
            /* The PDF 1.7 reference states that all three components of the BlackPoint
1255
             * (if present) must be positive.
1256
             */
1257
0
            if (f < 0) {
1258
0
                code = gs_note_error(gs_error_rangecheck);
1259
0
                goto exit;
1260
0
            }
1261
0
            BlackPoint[i] = (float)f;
1262
0
        }
1263
0
        pdfi_countdown(PDFArray);
1264
0
        PDFArray = NULL;
1265
0
    }
1266
1267
0
    if (pdfi_dict_knownget_type(ctx, ParamsDict, "Gamma", PDF_ARRAY, (pdf_obj **)&PDFArray) > 0) {
1268
0
        if (pdfi_array_size(PDFArray) != 3){
1269
0
            code = gs_note_error(gs_error_rangecheck);
1270
0
            goto exit;
1271
0
        }
1272
0
        for (i=0; i < 3; i++) {
1273
0
            code = pdfi_array_get_number(ctx, PDFArray, (uint64_t)i, &f);
1274
0
            if (code < 0)
1275
0
                goto exit;
1276
0
            Gamma[i] = (float)f;
1277
0
        }
1278
0
        pdfi_countdown(PDFArray);
1279
0
        PDFArray = NULL;
1280
0
    }
1281
1282
0
    if (pdfi_dict_knownget_type(ctx, ParamsDict, "Matrix", PDF_ARRAY, (pdf_obj **)&PDFArray) > 0) {
1283
0
        if (pdfi_array_size(PDFArray) != 9){
1284
0
            code = gs_note_error(gs_error_rangecheck);
1285
0
            goto exit;
1286
0
        }
1287
0
        for (i=0; i < 9; i++) {
1288
0
            code = pdfi_array_get_number(ctx, PDFArray, (uint64_t)i, &f);
1289
0
            if (code < 0)
1290
0
                goto exit;
1291
0
            Matrix[i] = (float)f;
1292
0
        }
1293
0
        pdfi_countdown(PDFArray);
1294
0
        PDFArray = NULL;
1295
0
    }
1296
0
    code = 0;
1297
1298
0
    for (i = 0;i < 3; i++) {
1299
0
        pcs->params.calrgb.WhitePoint[i] = WhitePoint[i];
1300
0
        pcs->params.calrgb.BlackPoint[i] = BlackPoint[i];
1301
0
        pcs->params.calrgb.Gamma[i] = Gamma[i];
1302
0
    }
1303
0
    for (i = 0;i < 9; i++)
1304
0
        pcs->params.calrgb.Matrix[i] = Matrix[i];
1305
1306
0
exit:
1307
0
    pdfi_countdown(PDFArray);
1308
0
    return code;
1309
0
}
1310
1311
static int pdfi_set_Lab_params(pdf_context *ctx, gs_color_space *pcs, pdf_dict *ParamsDict)
1312
0
{
1313
0
    int code = 0, i;
1314
0
    pdf_array *PDFArray = NULL;
1315
    /* The default values here are as per the PDF 1.7 specification, there is
1316
     * no default for the WhitePoint as it is a required entry
1317
     */
1318
0
    float WhitePoint[3], BlackPoint[3] = {0.0f, 0.0f, 0.0f}, Range[4] = {-100.0, 100.0, -100.0, 100.0};
1319
0
    double f;
1320
1321
0
    code = pdfi_dict_get_type(ctx, ParamsDict, "WhitePoint", PDF_ARRAY, (pdf_obj **)&PDFArray);
1322
0
    if (code < 0) {
1323
0
        pdfi_countdown(PDFArray);
1324
0
        goto exit;
1325
0
    }
1326
0
    if (pdfi_array_size(PDFArray) != 3){
1327
0
        code = gs_note_error(gs_error_rangecheck);
1328
0
        goto exit;
1329
0
    }
1330
1331
0
    for (i=0; i < 3; i++) {
1332
0
        code = pdfi_array_get_number(ctx, PDFArray, (uint64_t)i, &f);
1333
0
        if (code < 0)
1334
0
            goto exit;
1335
0
        WhitePoint[i] = (float)f;
1336
0
    }
1337
0
    pdfi_countdown(PDFArray);
1338
0
    PDFArray = NULL;
1339
1340
    /* Check the WhitePoint values, the PDF 1.7 reference states that
1341
     * Xw ad Zw must be positive and Yw must be 1.0
1342
     */
1343
0
    if (WhitePoint[0] < 0 || WhitePoint[2] < 0 || WhitePoint[1] != 1.0f) {
1344
0
        code = gs_note_error(gs_error_rangecheck);
1345
0
        goto exit;
1346
0
    }
1347
1348
0
    if (pdfi_dict_knownget_type(ctx, ParamsDict, "BlackPoint", PDF_ARRAY, (pdf_obj **)&PDFArray) > 0) {
1349
0
        if (pdfi_array_size(PDFArray) != 3){
1350
0
            code = gs_note_error(gs_error_rangecheck);
1351
0
            goto exit;
1352
0
        }
1353
0
        for (i=0; i < 3; i++) {
1354
0
            code = pdfi_array_get_number(ctx, PDFArray, (uint64_t)i, &f);
1355
0
            if (code < 0)
1356
0
                goto exit;
1357
            /* The PDF 1.7 reference states that all three components of the BlackPoint
1358
             * (if present) must be positive.
1359
             */
1360
0
            if (f < 0) {
1361
0
                code = gs_note_error(gs_error_rangecheck);
1362
0
                goto exit;
1363
0
            }
1364
0
            BlackPoint[i] = (float)f;
1365
0
        }
1366
0
        pdfi_countdown(PDFArray);
1367
0
        PDFArray = NULL;
1368
0
    }
1369
1370
0
    if (pdfi_dict_knownget_type(ctx, ParamsDict, "Range", PDF_ARRAY, (pdf_obj **)&PDFArray) > 0) {
1371
0
        if (pdfi_array_size(PDFArray) != 4){
1372
0
            code = gs_note_error(gs_error_rangecheck);
1373
0
            goto exit;
1374
0
        }
1375
1376
0
        for (i=0; i < 4; i++) {
1377
0
            code = pdfi_array_get_number(ctx, PDFArray, (uint64_t)i, &f);
1378
0
            if (code < 0)
1379
0
                goto exit;
1380
0
            Range[i] = f;
1381
0
        }
1382
0
        pdfi_countdown(PDFArray);
1383
0
        PDFArray = NULL;
1384
0
    }
1385
0
    code = 0;
1386
1387
0
    for (i = 0;i < 3; i++) {
1388
0
        pcs->params.lab.WhitePoint[i] = WhitePoint[i];
1389
0
        pcs->params.lab.BlackPoint[i] = BlackPoint[i];
1390
0
    }
1391
0
    for (i = 0;i < 4; i++)
1392
0
        pcs->params.lab.Range[i] = Range[i];
1393
1394
0
exit:
1395
0
    pdfi_countdown(PDFArray);
1396
0
    return code;
1397
0
}
1398
1399
static int pdfi_create_iccbased(pdf_context *ctx, pdf_array *color_array, int index, pdf_dict *stream_dict, pdf_dict *page_dict, gs_color_space **ppcs, bool inline_image)
1400
262k
{
1401
262k
    pdf_stream *ICC_obj = NULL;
1402
262k
    pdf_dict *dict; /* Alias to avoid tons of casting */
1403
262k
    pdf_array *a;
1404
262k
    int64_t Length, N;
1405
262k
    pdf_obj *Name = NULL, *Alt = NULL;
1406
262k
    char *cname = NULL;
1407
262k
    int code;
1408
262k
    bool known = true;
1409
262k
    float range[8];
1410
262k
    int icc_N;
1411
262k
    gs_color_space *pcs = NULL;
1412
1413
262k
    code = pdfi_array_get_type(ctx, color_array, index + 1, PDF_STREAM, (pdf_obj **)&ICC_obj);
1414
262k
    if (code < 0)
1415
16.8k
        return code;
1416
245k
    code = pdfi_dict_from_obj(ctx, (pdf_obj *)ICC_obj, &dict);
1417
245k
    if (code < 0)
1418
0
        return code;
1419
1420
245k
    Length = pdfi_stream_length(ctx, ICC_obj);
1421
245k
    code = pdfi_dict_get_int(ctx, dict, "N", &N);
1422
245k
    if (code < 0)
1423
1.28k
        goto done;
1424
244k
    if (N != 1 && N != 3 && N != 4) {
1425
1.84k
        code = gs_note_error(gs_error_rangecheck);
1426
1.84k
        goto done;
1427
1.84k
    }
1428
242k
    code = pdfi_dict_knownget(ctx, dict, "Name", &Name);
1429
242k
    if (code > 0) {
1430
0
        switch (pdfi_type_of(Name)) {
1431
0
            case PDF_STRING:
1432
0
            case PDF_NAME:
1433
0
                cname = (char *)gs_alloc_bytes(ctx->memory, ((pdf_name *)Name)->length + (size_t)1, "pdfi_create_iccbased (profile name)");
1434
0
                if (cname == NULL) {
1435
0
                    code = gs_note_error(gs_error_VMerror);
1436
0
                    goto done;
1437
0
                }
1438
0
                memset(cname, 0x00, ((pdf_name *)Name)->length + 1);
1439
0
                memcpy(cname, ((pdf_name *)Name)->data, ((pdf_name *)Name)->length);
1440
0
                break;
1441
0
            default:
1442
0
                break;
1443
0
        }
1444
0
    }
1445
242k
    if (code < 0)
1446
0
        goto done;
1447
1448
242k
    code = pdfi_dict_knownget_type(ctx, dict, "Range", PDF_ARRAY, (pdf_obj **)&a);
1449
242k
    if (code < 0)
1450
0
        goto done;
1451
242k
    if (code > 0) {
1452
174
        double dbl;
1453
174
        int i;
1454
1455
174
        if (pdfi_array_size(a) >= N * 2) {
1456
1.21k
            for (i = 0; i < N * 2;i++) {
1457
1.04k
                code = pdfi_array_get_number(ctx, a, i, &dbl);
1458
1.04k
                if (code < 0) {
1459
0
                    known = false;
1460
0
                    break;
1461
0
                }
1462
1.04k
                range[i] = (float)dbl;
1463
1.04k
            }
1464
162
        } else {
1465
12
            known = false;
1466
12
        }
1467
174
        pdfi_countdown(a);
1468
174
    } else
1469
242k
        known = false;
1470
1471
    /* We don't just use the final else clause above for setting the defaults
1472
     * because we also want to use these if there's a problem with the
1473
     * supplied data. In this case we also want to overwrite any partial
1474
     * data we might have read
1475
     */
1476
242k
    if (!known) {
1477
242k
        int i;
1478
892k
        for (i = 0;i < N; i++) {
1479
650k
            range[i * 2] = 0;
1480
650k
            range[(i * 2) + 1] = 1;
1481
650k
        }
1482
242k
    }
1483
1484
242k
    code = pdfi_create_iccprofile(ctx, ICC_obj, cname, Length, N, &icc_N, range, &pcs);
1485
1486
    /* This is just plain hackery for the benefit of Bug696690.pdf. The old PostScript PDF interpreter says:
1487
     * %% This section is to deal with the horrible pair of files in Bug #696690 and Bug #696120
1488
     * %% These files have ICCBased spaces where the value of /N and the number of components
1489
     * %% in the profile differ. In addition the profile in Bug #696690 is invalid. In the
1490
     * %% case of Bug #696690 the /N value is correct, and the profile is wrong, in the case
1491
     * %% of Bug #696120 the /N value is incorrect and the profile is correct.
1492
     * %% We 'suspect' that Acrobat uses the fact that Bug #696120 is a pure image to detect
1493
     * %% that the /N is incorrect, we can't be sure whether it uses the profile or just uses
1494
     * %% the /N to decide on a device space.
1495
     * We can't precisely duplicate the PostScript approach, but we now set the actual ICC profile
1496
     * and therefore use the number of components in the profile. However, we pass back the number
1497
     * of components in icc_N. We then check to see if N and icc_N are the same, if they are not we
1498
     * try to set a devcie colour using the profile. If that fails (bad profile) then we enter the fallback
1499
     * just as if we had failed to set the profile.
1500
     */
1501
242k
    if (code >= 0 && N != icc_N) {
1502
31
        gs_client_color cc;
1503
31
        int i;
1504
1505
31
        gs_gsave(ctx->pgs);
1506
31
        code = gs_setcolorspace(ctx->pgs, pcs);
1507
31
        if (code == 0) {
1508
31
            cc.pattern = 0;
1509
116
            for (i = 0;i < icc_N; i++)
1510
85
                cc.paint.values[i] = 0;
1511
31
            code = gs_setcolor(ctx->pgs, &cc);
1512
31
            if (code == 0)
1513
31
                code = gx_set_dev_color(ctx->pgs);
1514
31
        }
1515
31
        gs_grestore(ctx->pgs);
1516
31
    }
1517
1518
242k
    if (code < 0) {
1519
13.8k
        pdf_obj *Alternate = NULL;
1520
1521
13.8k
        if (pcs != NULL)
1522
13.8k
            rc_decrement(pcs,"pdfi_create_iccbased");
1523
1524
        /* Failed to set the ICCBased space, attempt to use the Alternate */
1525
13.8k
        code = pdfi_dict_knownget(ctx, dict, "Alternate", &Alternate);
1526
13.8k
        if (code > 0) {
1527
            /* The Alternate should be one of the device spaces, therefore a Name object. If its not, fallback to using /N */
1528
13.2k
            if (pdfi_type_of(Alternate) == PDF_NAME)
1529
13.2k
                code = pdfi_create_colorspace_by_name(ctx, (pdf_name *)Alternate, stream_dict,
1530
13.2k
                                                      page_dict, ppcs, inline_image);
1531
13.2k
            pdfi_countdown(Alternate);
1532
13.2k
            if (code == 0) {
1533
13.1k
                pdfi_set_warning(ctx, 0, NULL, W_PDF_BADICC_USE_ALT, "pdfi_create_iccbased", NULL);
1534
13.1k
                goto done;
1535
13.1k
            }
1536
13.2k
        }
1537
        /* Use the number of components *from the profile* to set a space.... */
1538
741
        pdfi_set_warning(ctx, 0, NULL, W_PDF_BADICC_USECOMPS, "pdfi_create_iccbased", NULL);
1539
741
        switch(N) {
1540
158
            case 1:
1541
158
                pcs = gs_cspace_new_DeviceGray(ctx->memory);
1542
158
                if (pcs == NULL)
1543
0
                    code = gs_note_error(gs_error_VMerror);
1544
158
                break;
1545
575
            case 3:
1546
575
                pcs = gs_cspace_new_DeviceRGB(ctx->memory);
1547
575
                if (pcs == NULL)
1548
0
                    code = gs_note_error(gs_error_VMerror);
1549
575
                break;
1550
8
            case 4:
1551
8
                pcs = gs_cspace_new_DeviceCMYK(ctx->memory);
1552
8
                if (pcs == NULL)
1553
0
                    code = gs_note_error(gs_error_VMerror);
1554
8
                break;
1555
0
            default:
1556
0
                code = gs_note_error(gs_error_undefined);
1557
0
                break;
1558
741
        }
1559
228k
    } else {
1560
228k
        if (pcs->ICC_Alternate_space == gs_ICC_Alternate_None) {
1561
28.1k
            code = pdfi_dict_knownget(ctx, dict, "Alternate", (pdf_obj **)&Alt);
1562
28.1k
            if (code >= 0) {
1563
28.1k
                switch(pdfi_type_of(Alt)) {
1564
23.8k
                    case PDF_NAME:
1565
                        /* Simple named spaces must be Gray, RGB or CMYK, we ignore /Indexed */
1566
23.8k
                        if (pdfi_name_is((const pdf_name *)Alt, "DeviceGray"))
1567
6.69k
                            pcs->ICC_Alternate_space = gs_ICC_Alternate_DeviceGray;
1568
17.1k
                        else if (pdfi_name_is((const pdf_name *)Alt, "DeviceRGB"))
1569
16.9k
                            pcs->ICC_Alternate_space = gs_ICC_Alternate_DeviceRGB;
1570
214
                        else if (pdfi_name_is((const pdf_name *)Alt, "DeviceCMYK"))
1571
38
                            pcs->ICC_Alternate_space = gs_ICC_Alternate_DeviceCMYK;
1572
23.8k
                        break;
1573
0
                    case PDF_ARRAY:
1574
0
                        {
1575
0
                            pdf_obj *AltName = NULL, *ParamsDict = NULL;
1576
1577
0
                            code = pdfi_array_get_type(ctx, (pdf_array *)Alt, 0, PDF_NAME, &AltName);
1578
0
                            if (code >= 0) {
1579
0
                                code = pdfi_array_get_type(ctx, (pdf_array *)Alt, 1, PDF_DICT, &ParamsDict);
1580
0
                                if (code >= 0) {
1581
0
                                    if (pdfi_name_is((const pdf_name *)AltName, "CalGray")) {
1582
0
                                        code = pdfi_set_CalGray_params(ctx, pcs, (pdf_dict *)ParamsDict);
1583
0
                                        if (code >= 0)
1584
0
                                            pcs->ICC_Alternate_space = gs_ICC_Alternate_CalGray;
1585
0
                                    } else {
1586
0
                                        if (pdfi_name_is((const pdf_name *)AltName, "CalRGB")) {
1587
0
                                            code = pdfi_set_CalRGB_params(ctx, pcs, (pdf_dict *)ParamsDict);
1588
0
                                            if (code >= 0)
1589
0
                                                pcs->ICC_Alternate_space = gs_ICC_Alternate_CalRGB;
1590
0
                                        } else {
1591
0
                                            if (pdfi_name_is((const pdf_name *)AltName, "CalCMYK")) {
1592
0
                                                pcs->ICC_Alternate_space = gs_ICC_Alternate_DeviceCMYK;
1593
0
                                            } else {
1594
0
                                                if (pdfi_name_is((const pdf_name *)AltName, "Lab")) {
1595
0
                                                    code = pdfi_set_Lab_params(ctx, pcs, (pdf_dict *)ParamsDict);
1596
0
                                                    if (code >= 0)
1597
0
                                                        pcs->ICC_Alternate_space = gs_ICC_Alternate_Lab;
1598
0
                                                }
1599
0
                                            }
1600
0
                                        }
1601
0
                                    }
1602
0
                                }
1603
0
                            }
1604
0
                            code = 0;
1605
0
                            pdfi_countdown(ParamsDict);
1606
0
                            pdfi_countdown(AltName);
1607
0
                        }
1608
0
                        break;
1609
4.28k
                    default:
1610
                        /* Probably an error, but just ignore it */
1611
4.28k
                        break;
1612
28.1k
                }
1613
28.1k
                pdfi_countdown(Alt);
1614
28.1k
                Alt = NULL;
1615
28.1k
            }
1616
28.1k
        }
1617
228k
    }
1618
1619
229k
    if (ppcs!= NULL) {
1620
60.2k
        *ppcs = pcs;
1621
60.2k
        if (pcs != NULL)
1622
60.2k
            pdfi_set_colour_callback(pcs, ctx, pdfi_cspace_free_callback);
1623
60.2k
    }
1624
168k
    else {
1625
168k
        if (pcs != NULL) {
1626
168k
            code = pdfi_gs_setcolorspace(ctx, pcs);
1627
            /* release reference from construction */
1628
168k
            rc_decrement_only_cs(pcs, "setseparationspace");
1629
168k
        }
1630
168k
    }
1631
1632
1633
245k
done:
1634
245k
    if (cname)
1635
0
        gs_free_object(ctx->memory, cname, "pdfi_create_iccbased (profile name)");
1636
245k
    pdfi_countdown(Alt);
1637
245k
    pdfi_countdown(Name);
1638
245k
    pdfi_countdown(ICC_obj);
1639
245k
    return code;
1640
229k
}
1641
1642
/*
1643
 * This, and pdfi_set_cal() below are copied from the similarly named routines
1644
 * in zicc.c
1645
 */
1646
/* Install a ICC type color space and use the ICC LABLUT profile. */
1647
static int
1648
pdfi_seticc_lab(pdf_context *ctx, float *range_buff, gs_color_space **ppcs)
1649
1.28k
{
1650
1.28k
    int                     code;
1651
1.28k
    gs_color_space *        pcs;
1652
1.28k
    int                     i;
1653
1654
    /* build the color space object */
1655
    /* We need to use the graphics state memory, and beyond that we need to use stable memory, because the
1656
     * ICC cache can persist until the end of job, and so the profile (which is stored in teh cache)
1657
     * must likewise persist.
1658
     */
1659
1.28k
    code = gs_cspace_build_ICC(&pcs, NULL, (gs_gstate_memory(ctx->pgs))->stable_memory);
1660
1.28k
    if (code < 0)
1661
0
        return code;
1662
1663
    /* record the current space as the alternative color space */
1664
    /* Get the lab profile.  It may already be set in the icc manager.
1665
       If not then lets populate it.  */
1666
1.28k
    if (ctx->pgs->icc_manager->lab_profile == NULL ) {
1667
        /* This can't happen as the profile
1668
           should be initialized during the
1669
           setting of the user params */
1670
0
        return_error(gs_error_unknownerror);
1671
0
    }
1672
    /* Assign the LAB to LAB profile to this color space */
1673
1.28k
    code = gsicc_set_gscs_profile(pcs, ctx->pgs->icc_manager->lab_profile, gs_gstate_memory(ctx->pgs));
1674
1.28k
    if (code < 0)
1675
0
        return code;
1676
1677
1.28k
    pcs->cmm_icc_profile_data->Range.ranges[0].rmin = 0.0;
1678
1.28k
    pcs->cmm_icc_profile_data->Range.ranges[0].rmax = 100.0;
1679
3.85k
    for (i = 1; i < 3; i++) {
1680
2.56k
        pcs->cmm_icc_profile_data->Range.ranges[i].rmin =
1681
2.56k
            range_buff[2 * (i-1)];
1682
2.56k
        pcs->cmm_icc_profile_data->Range.ranges[i].rmax =
1683
2.56k
            range_buff[2 * (i-1) + 1];
1684
2.56k
    }
1685
1.28k
    if (ppcs!= NULL){
1686
263
        *ppcs = pcs;
1687
263
        pdfi_set_colour_callback(pcs, ctx, pdfi_cspace_free_callback);
1688
1.02k
    } else {
1689
1.02k
        code = pdfi_gs_setcolorspace(ctx, pcs);
1690
1.02k
        rc_decrement_only_cs(pcs, "pdfi_seticc_lab");
1691
1.02k
    }
1692
1693
1.28k
    return code;
1694
1.28k
}
1695
1696
static int pdfi_create_Lab(pdf_context *ctx, pdf_array *color_array, int index, pdf_dict *stream_dict, pdf_dict *page_dict, gs_color_space **ppcs)
1697
1.31k
{
1698
1.31k
    int code = 0, i;
1699
1.31k
    pdf_dict *Lab_dict = NULL;
1700
1.31k
    pdf_array *Range = NULL;
1701
1.31k
    float RangeBuf[4];
1702
1.31k
    double f;
1703
1.31k
    bool known = false;
1704
1705
1.31k
    code = pdfi_array_get_type(ctx, color_array, index + 1, PDF_DICT, (pdf_obj **)&Lab_dict);
1706
1.31k
    if (code < 0)
1707
18
        return code;
1708
1709
1.29k
    code = pdfi_dict_known(ctx, Lab_dict, "Range", &known);
1710
1.29k
    if (code < 0)
1711
0
        goto exit;
1712
1.29k
    if (known) {
1713
1.27k
        code = pdfi_dict_get_type(ctx, Lab_dict, "Range", PDF_ARRAY, (pdf_obj **)&Range);
1714
1.27k
        if (code < 0) {
1715
0
            goto exit;
1716
0
        }
1717
1.27k
        if (pdfi_array_size(Range) != 4){
1718
12
            code = gs_note_error(gs_error_rangecheck);
1719
12
            goto exit;
1720
12
        }
1721
1722
6.29k
        for (i=0; i < 4; i++) {
1723
5.03k
            code = pdfi_array_get_number(ctx, Range, (uint64_t)i, &f);
1724
5.03k
            if (code < 0)
1725
1
                goto exit;
1726
5.03k
            RangeBuf[i] = (float)f;
1727
5.03k
        }
1728
1.26k
    } else {
1729
25
        RangeBuf[0] = RangeBuf[2] = -100.0;
1730
25
        RangeBuf[1] = RangeBuf[3] = 100.0;
1731
25
    }
1732
1733
1.28k
    code = pdfi_seticc_lab(ctx, RangeBuf, ppcs);
1734
1735
1.29k
exit:
1736
1.29k
    pdfi_countdown(Lab_dict);
1737
1.29k
    pdfi_countdown(Range);
1738
1.29k
    return code;
1739
1.28k
}
1740
1741
/* Install an ICC space from the PDF CalRGB or CalGray types */
1742
static int
1743
pdfi_seticc_cal(pdf_context *ctx, float *white, float *black, float *gamma,
1744
           float *matrix, int num_colorants, ulong dictkey, gs_color_space **ppcs)
1745
3.71k
{
1746
3.71k
    int                     code = 0;
1747
3.71k
    gs_color_space *        pcs;
1748
3.71k
    int                     i;
1749
3.71k
    cmm_profile_t           *cal_profile;
1750
1751
    /* See if the color space is in the profile cache */
1752
3.71k
    pcs = gsicc_find_cs(dictkey, ctx->pgs);
1753
3.71k
    if (pcs == NULL ) {
1754
        /* build the color space object.  Since this is cached
1755
           in the profile cache which is a member variable
1756
           of the graphic state, we will want to use stable
1757
           memory here */
1758
3.68k
        code = gs_cspace_build_ICC(&pcs, NULL, ctx->pgs->memory->stable_memory);
1759
3.68k
        if (code < 0)
1760
0
            return code;
1761
        /* There is no alternate for this.  Perhaps we should set DeviceRGB? */
1762
3.68k
        pcs->base_space = NULL;
1763
        /* Create the ICC profile from the CalRGB or CalGray parameters */
1764
        /* We need to use the graphics state memory, in case we are running under Ghostscript. */
1765
3.68k
        cal_profile = gsicc_create_from_cal(white, black, gamma, matrix,
1766
3.68k
                                            ctx->pgs->memory->stable_memory, num_colorants);
1767
3.68k
        if (cal_profile == NULL) {
1768
0
            rc_decrement(pcs, "seticc_cal");
1769
0
            return_error(gs_error_VMerror);
1770
0
        }
1771
        /* Assign the profile to this color space */
1772
        /* Apparently the memory pointer passed here here is not actually used, but we will supply
1773
         * the graphics state memory allocator, because that's what the colour space should be using.
1774
         */
1775
3.68k
        code = gsicc_set_gscs_profile(pcs, cal_profile, ctx->pgs->memory);
1776
        /* profile is created with ref count of 1, gsicc_set_gscs_profile()
1777
         * increments the ref count, so we need to decrement it here.
1778
         */
1779
3.68k
        rc_decrement(cal_profile, "seticc_cal");
1780
3.68k
        if (code < 0) {
1781
0
            rc_decrement(pcs, "seticc_cal");
1782
0
            return code;
1783
0
        }
1784
14.2k
        for (i = 0; i < num_colorants; i++) {
1785
10.6k
            pcs->cmm_icc_profile_data->Range.ranges[i].rmin = 0;
1786
10.6k
            pcs->cmm_icc_profile_data->Range.ranges[i].rmax = 1;
1787
10.6k
        }
1788
        /* Add the color space to the profile cache */
1789
3.68k
        gsicc_add_cs(ctx->pgs, pcs, dictkey);
1790
3.68k
    } else {
1791
        /* We're passing back a new reference, increment the count */
1792
34
        rc_adjust_only(pcs, 1, "pdfi_seticc_cal, return cached ICC profile");
1793
34
    }
1794
1795
3.71k
    if (ppcs!= NULL){
1796
439
        *ppcs = pcs;
1797
439
        pdfi_set_colour_callback(pcs, ctx, pdfi_cspace_free_callback);
1798
3.28k
    } else {
1799
3.28k
        code = pdfi_gs_setcolorspace(ctx, pcs);
1800
3.28k
        rc_decrement_only_cs(pcs, "pdfi_seticc_cal");
1801
3.28k
    }
1802
1803
3.71k
    return code;
1804
3.71k
}
1805
1806
static int pdfi_create_CalGray(pdf_context *ctx, pdf_array *color_array, int index, pdf_dict *stream_dict, pdf_dict *page_dict, gs_color_space **ppcs)
1807
822
{
1808
822
    int code = 0, i;
1809
822
    pdf_dict *CalGray_dict = NULL;
1810
822
    pdf_array *PDFArray = NULL;
1811
    /* The default values here are as per the PDF 1.7 specification, there is
1812
     * no default for the WhitePoint as it is a required entry. The Matrix is
1813
     * not specified for CalGray, but we need it for the general 'pdfi_set_icc'
1814
     * routine, so we use the same default as CalRGB.
1815
     */
1816
822
    float WhitePoint[3], BlackPoint[3] = {0.0f, 0.0f, 0.0f}, Gamma = 1.0f;
1817
822
    float Matrix[9] = {1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f};
1818
822
    double f;
1819
1820
822
    code = pdfi_array_get_type(ctx, color_array, index + 1, PDF_DICT, (pdf_obj **)&CalGray_dict);
1821
822
    if (code < 0)
1822
167
        return code;
1823
1824
655
    code = pdfi_dict_get_type(ctx, CalGray_dict, "WhitePoint", PDF_ARRAY, (pdf_obj **)&PDFArray);
1825
655
    if (code < 0) {
1826
62
        pdfi_countdown(PDFArray);
1827
62
        goto exit;
1828
62
    }
1829
593
    if (pdfi_array_size(PDFArray) != 3){
1830
0
        code = gs_note_error(gs_error_rangecheck);
1831
0
        goto exit;
1832
0
    }
1833
1834
2.37k
    for (i=0; i < 3; i++) {
1835
1.77k
        code = pdfi_array_get_number(ctx, PDFArray, (uint64_t)i, &f);
1836
1.77k
        if (code < 0)
1837
0
            goto exit;
1838
1.77k
        WhitePoint[i] = (float)f;
1839
1.77k
    }
1840
593
    pdfi_countdown(PDFArray);
1841
593
    PDFArray = NULL;
1842
1843
    /* Check the WhitePoint values, the PDF 1.7 reference states that
1844
     * Xw ad Zw must be positive and Yw must be 1.0
1845
     */
1846
593
    if (WhitePoint[0] < 0 || WhitePoint[2] < 0 || WhitePoint[1] != 1.0f) {
1847
60
        code = gs_note_error(gs_error_rangecheck);
1848
60
        goto exit;
1849
60
    }
1850
1851
533
    if (pdfi_dict_knownget_type(ctx, CalGray_dict, "BlackPoint", PDF_ARRAY, (pdf_obj **)&PDFArray) > 0) {
1852
454
        if (pdfi_array_size(PDFArray) != 3){
1853
120
            code = gs_note_error(gs_error_rangecheck);
1854
120
            goto exit;
1855
120
        }
1856
1.15k
        for (i=0; i < 3; i++) {
1857
1.00k
            code = pdfi_array_get_number(ctx, PDFArray, (uint64_t)i, &f);
1858
1.00k
            if (code < 0)
1859
180
                goto exit;
1860
            /* The PDF 1.7 reference states that all three components of the BlackPoint
1861
             * (if present) must be positive.
1862
             */
1863
822
            if (f < 0) {
1864
0
                code = gs_note_error(gs_error_rangecheck);
1865
0
                goto exit;
1866
0
            }
1867
822
            BlackPoint[i] = (float)f;
1868
822
        }
1869
154
        pdfi_countdown(PDFArray);
1870
154
        PDFArray = NULL;
1871
154
    }
1872
1873
233
    if (pdfi_dict_knownget_number(ctx, CalGray_dict, "Gamma", &f) > 0)
1874
233
        Gamma = (float)f;
1875
    /* The PDF 1.7 reference states that Gamma
1876
     * (if present) must be positive.
1877
     */
1878
233
    if (Gamma < 0) {
1879
0
        code = gs_note_error(gs_error_rangecheck);
1880
0
        goto exit;
1881
0
    }
1882
1883
233
    code = pdfi_seticc_cal(ctx, WhitePoint, BlackPoint, &Gamma, Matrix, 1, color_array->object_num, ppcs);
1884
1885
655
exit:
1886
655
    pdfi_countdown(PDFArray);
1887
655
    pdfi_countdown(CalGray_dict);
1888
655
    return code;
1889
233
}
1890
1891
static int pdfi_create_CalRGB(pdf_context *ctx, pdf_array *color_array, int index, pdf_dict *stream_dict, pdf_dict *page_dict, gs_color_space **ppcs)
1892
3.80k
{
1893
3.80k
    int code = 0, i;
1894
3.80k
    pdf_dict *CalRGB_dict = NULL;
1895
3.80k
    pdf_array *PDFArray = NULL;
1896
    /* The default values here are as per the PDF 1.7 specification, there is
1897
     * no default for the WhitePoint as it is a required entry
1898
     */
1899
3.80k
    float WhitePoint[3], BlackPoint[3] = {0.0f, 0.0f, 0.0f}, Gamma[3] = {1.0f, 1.0f, 1.0f};
1900
3.80k
    float Matrix[9] = {1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f};
1901
3.80k
    double f;
1902
1903
3.80k
    code = pdfi_array_get_type(ctx, color_array, index + 1, PDF_DICT, (pdf_obj **)&CalRGB_dict);
1904
3.80k
    if (code < 0)
1905
34
        return code;
1906
1907
3.76k
    code = pdfi_dict_get_type(ctx, CalRGB_dict, "WhitePoint", PDF_ARRAY, (pdf_obj **)&PDFArray);
1908
3.76k
    if (code < 0) {
1909
8
        pdfi_countdown(PDFArray);
1910
8
        goto exit;
1911
8
    }
1912
3.76k
    if (pdfi_array_size(PDFArray) != 3){
1913
3
        code = gs_note_error(gs_error_rangecheck);
1914
3
        goto exit;
1915
3
    }
1916
1917
15.0k
    for (i=0; i < 3; i++) {
1918
11.2k
        code = pdfi_array_get_number(ctx, PDFArray, (uint64_t)i, &f);
1919
11.2k
        if (code < 0)
1920
0
            goto exit;
1921
11.2k
        WhitePoint[i] = (float)f;
1922
11.2k
    }
1923
3.75k
    pdfi_countdown(PDFArray);
1924
3.75k
    PDFArray = NULL;
1925
1926
    /* Check the WhitePoint values, the PDF 1.7 reference states that
1927
     * Xw ad Zw must be positive and Yw must be 1.0
1928
     */
1929
3.75k
    if (WhitePoint[0] < 0 || WhitePoint[2] < 0 || WhitePoint[1] != 1.0f) {
1930
2
        code = gs_note_error(gs_error_rangecheck);
1931
2
        goto exit;
1932
2
    }
1933
1934
3.75k
    if (pdfi_dict_knownget_type(ctx, CalRGB_dict, "BlackPoint", PDF_ARRAY, (pdf_obj **)&PDFArray) > 0) {
1935
1.34k
        if (pdfi_array_size(PDFArray) != 3){
1936
0
            code = gs_note_error(gs_error_rangecheck);
1937
0
            goto exit;
1938
0
        }
1939
4.91k
        for (i=0; i < 3; i++) {
1940
3.80k
            code = pdfi_array_get_number(ctx, PDFArray, (uint64_t)i, &f);
1941
3.80k
            if (code < 0)
1942
0
                goto exit;
1943
            /* The PDF 1.7 reference states that all three components of the BlackPoint
1944
             * (if present) must be positive.
1945
             */
1946
3.80k
            if (f < 0) {
1947
240
                code = gs_note_error(gs_error_rangecheck);
1948
240
                goto exit;
1949
240
            }
1950
3.56k
            BlackPoint[i] = (float)f;
1951
3.56k
        }
1952
1.10k
        pdfi_countdown(PDFArray);
1953
1.10k
        PDFArray = NULL;
1954
1.10k
    }
1955
1956
3.51k
    if (pdfi_dict_knownget_type(ctx, CalRGB_dict, "Gamma", PDF_ARRAY, (pdf_obj **)&PDFArray) > 0) {
1957
3.50k
        if (pdfi_array_size(PDFArray) != 3){
1958
8
            code = gs_note_error(gs_error_rangecheck);
1959
8
            goto exit;
1960
8
        }
1961
13.9k
        for (i=0; i < 3; i++) {
1962
10.4k
            code = pdfi_array_get_number(ctx, PDFArray, (uint64_t)i, &f);
1963
10.4k
            if (code < 0)
1964
0
                goto exit;
1965
10.4k
            Gamma[i] = (float)f;
1966
10.4k
        }
1967
3.49k
        pdfi_countdown(PDFArray);
1968
3.49k
        PDFArray = NULL;
1969
3.49k
    }
1970
1971
3.50k
    if (pdfi_dict_knownget_type(ctx, CalRGB_dict, "Matrix", PDF_ARRAY, (pdf_obj **)&PDFArray) > 0) {
1972
3.50k
        if (pdfi_array_size(PDFArray) != 9){
1973
10
            code = gs_note_error(gs_error_rangecheck);
1974
10
            goto exit;
1975
10
        }
1976
34.9k
        for (i=0; i < 9; i++) {
1977
31.4k
            code = pdfi_array_get_number(ctx, PDFArray, (uint64_t)i, &f);
1978
31.4k
            if (code < 0)
1979
11
                goto exit;
1980
31.4k
            Matrix[i] = (float)f;
1981
31.4k
        }
1982
3.48k
        pdfi_countdown(PDFArray);
1983
3.48k
        PDFArray = NULL;
1984
3.48k
    }
1985
3.48k
    code = pdfi_seticc_cal(ctx, WhitePoint, BlackPoint, Gamma, Matrix, 3, color_array->object_num, ppcs);
1986
1987
3.76k
exit:
1988
3.76k
    pdfi_countdown(PDFArray);
1989
3.76k
    pdfi_countdown(CalRGB_dict);
1990
3.76k
    return code;
1991
3.48k
}
1992
1993
static int pdfi_create_Separation(pdf_context *ctx, pdf_array *color_array, int index, pdf_dict *stream_dict, pdf_dict *page_dict, gs_color_space **ppcs, bool inline_image)
1994
77.8k
{
1995
77.8k
    pdf_obj *o = NULL;
1996
77.8k
    pdf_name *name = NULL, *NamedAlternate = NULL;
1997
77.8k
    pdf_array *ArrayAlternate = NULL;
1998
77.8k
    pdf_obj *transform = NULL;
1999
77.8k
    int code;
2000
77.8k
    gs_color_space *pcs = NULL, *pcs_alt = NULL;
2001
77.8k
    gs_function_t * pfn = NULL;
2002
77.8k
    separation_type sep_type;
2003
2004
77.8k
    code = pdfi_array_get_type(ctx, color_array, index + 1, PDF_NAME, (pdf_obj **)&name);
2005
77.8k
    if (code < 0)
2006
0
        goto pdfi_separation_error;
2007
2008
77.8k
    sep_type = SEP_OTHER;
2009
77.8k
    if (name->length == 4 && memcmp(name->data, "None", 4) == 0)
2010
0
        sep_type = SEP_NONE;
2011
77.8k
    if (name->length == 3 && memcmp(name->data, "All", 3) == 0)
2012
0
        sep_type = SEP_ALL;
2013
2014
77.8k
    code = pdfi_array_get(ctx, color_array, index + 2, &o);
2015
77.8k
    if (code < 0)
2016
417
        goto pdfi_separation_error;
2017
2018
77.4k
    switch (pdfi_type_of(o)) {
2019
58.9k
        case PDF_NAME:
2020
58.9k
            NamedAlternate = (pdf_name *)o;
2021
58.9k
            code = pdfi_create_colorspace_by_name(ctx, NamedAlternate, stream_dict, page_dict, &pcs_alt, inline_image);
2022
58.9k
            if (code < 0)
2023
125
                goto pdfi_separation_error;
2024
58.7k
            break;
2025
58.7k
        case PDF_ARRAY:
2026
17.4k
            ArrayAlternate = (pdf_array *)o;
2027
17.4k
            code = pdfi_create_colorspace_by_array(ctx, ArrayAlternate, 0, stream_dict, page_dict, &pcs_alt, inline_image);
2028
17.4k
            if (code < 0)
2029
1.49k
                goto pdfi_separation_error;
2030
15.9k
            break;
2031
15.9k
        default:
2032
1.12k
            pdfi_countdown(o);
2033
1.12k
            code = gs_error_typecheck;
2034
1.12k
            goto pdfi_separation_error;
2035
77.4k
    }
2036
2037
74.7k
    code = pdfi_array_get(ctx, color_array, index + 3, &transform);
2038
74.7k
    if (code < 0)
2039
1.32k
        goto pdfi_separation_error;
2040
2041
73.4k
    code = pdfi_build_function(ctx, &pfn, NULL, 1, transform, page_dict);
2042
73.4k
    if (code < 0)
2043
6.97k
        goto pdfi_separation_error;
2044
2045
66.4k
    if (pfn->params.m != 1 || pfn->params.n != cs_num_components(pcs_alt)) {
2046
25
        code = gs_note_error(gs_error_rangecheck);
2047
25
        goto pdfi_separation_error;
2048
25
    }
2049
2050
66.4k
    code = gs_cspace_new_Separation(&pcs, pcs_alt, ctx->memory);
2051
66.4k
    if (code < 0)
2052
0
        goto pdfi_separation_error;
2053
2054
66.4k
    rc_decrement(pcs_alt, "pdfi_create_Separation");
2055
66.4k
    pcs_alt = NULL;
2056
66.4k
    pcs->params.separation.mem = ctx->memory;
2057
66.4k
    pcs->params.separation.sep_type = sep_type;
2058
66.4k
    pcs->params.separation.sep_name = (char *)gs_alloc_bytes(ctx->memory->non_gc_memory, (size_t)name->length + 1, "pdfi_setseparationspace(ink)");
2059
66.4k
    if (pcs->params.separation.sep_name == NULL) {
2060
0
        code = gs_note_error(gs_error_VMerror);
2061
0
        goto pdfi_separation_error;
2062
0
    }
2063
66.4k
    memcpy(pcs->params.separation.sep_name, name->data, name->length);
2064
66.4k
    pcs->params.separation.sep_name[name->length] = 0x00;
2065
2066
66.4k
    code = gs_cspace_set_sepr_function(pcs, pfn);
2067
66.4k
    if (code < 0)
2068
0
        goto pdfi_separation_error;
2069
2070
66.4k
    if (ppcs!= NULL){
2071
        /* FIXME
2072
         * I can see no justification for this whatever, but if I don't do this then some
2073
         * files with images in a /Separation colour space come out incorrectly. Even surrounding
2074
         * this with a gsave/grestore pair causes differences.
2075
         */
2076
259
        code = pdfi_gs_setcolorspace(ctx, pcs);
2077
259
        *ppcs = pcs;
2078
259
        pdfi_set_colour_callback(pcs, ctx, pdfi_cspace_free_callback);
2079
66.1k
    } else {
2080
66.1k
        code = pdfi_gs_setcolorspace(ctx, pcs);
2081
        /* release reference from construction */
2082
66.1k
        rc_decrement_only_cs(pcs, "setseparationspace");
2083
66.1k
    }
2084
2085
66.4k
    pdfi_countdown(name);
2086
66.4k
    pdfi_countdown(NamedAlternate);
2087
66.4k
    pdfi_countdown(ArrayAlternate);
2088
66.4k
    pdfi_countdown(transform);
2089
66.4k
    return_error(0);
2090
2091
11.4k
pdfi_separation_error:
2092
11.4k
    pdfi_free_function(ctx, pfn);
2093
11.4k
    if (pcs_alt != NULL)
2094
8.32k
        rc_decrement_only_cs(pcs_alt, "setseparationspace");
2095
11.4k
    if(pcs != NULL)
2096
0
        rc_decrement_only_cs(pcs, "setseparationspace");
2097
11.4k
    pdfi_countdown(name);
2098
11.4k
    pdfi_countdown(NamedAlternate);
2099
11.4k
    pdfi_countdown(ArrayAlternate);
2100
11.4k
    pdfi_countdown(transform);
2101
11.4k
    return code;
2102
66.4k
}
2103
2104
static int pdfi_create_DeviceN(pdf_context *ctx, pdf_array *color_array, int index, pdf_dict *stream_dict, pdf_dict *page_dict, gs_color_space **ppcs, bool inline_image)
2105
30.7k
{
2106
30.7k
    pdf_obj *o = NULL;
2107
30.7k
    pdf_name *NamedAlternate = NULL;
2108
30.7k
    pdf_array *ArrayAlternate = NULL, *inks = NULL;
2109
30.7k
    pdf_obj *transform = NULL;
2110
30.7k
    pdf_dict *attributes = NULL;
2111
30.7k
    pdf_dict *Colorants = NULL, *Process = NULL;
2112
30.7k
    gs_color_space *process_space = NULL;
2113
30.7k
    int code;
2114
30.7k
    uint64_t ix;
2115
30.7k
    gs_color_space *pcs = NULL, *pcs_alt = NULL;
2116
30.7k
    gs_function_t * pfn = NULL;
2117
2118
    /* Start with the array of inks */
2119
30.7k
    code = pdfi_array_get_type(ctx, color_array, index + 1, PDF_ARRAY, (pdf_obj **)&inks);
2120
30.7k
    if (code < 0)
2121
6
        goto pdfi_devicen_error;
2122
2123
30.7k
    if (pdfi_array_size(inks) > GS_CLIENT_COLOR_MAX_COMPONENTS)
2124
0
            return_error(gs_error_limitcheck);
2125
2126
72.6k
    for (ix = 0;ix < pdfi_array_size(inks);ix++) {
2127
41.9k
        pdf_name *ink_name = NULL;
2128
2129
41.9k
        code = pdfi_array_get_type(ctx, inks, ix, PDF_NAME, (pdf_obj **)&ink_name);
2130
41.9k
        if (code < 0)
2131
4
            return code;
2132
2133
41.9k
        if (ink_name->length == 3 && memcmp(ink_name->data, "All", 3) == 0) {
2134
0
            if ((code = pdfi_set_warning_stop(ctx, gs_note_error(gs_error_rangecheck), NULL, W_PDF_DEVICEN_USES_ALL, "pdfi_create_DeviceN", (char *)"WARNING: DeviceN space using /All ink name")) < 0)
2135
0
                return code;
2136
0
        }
2137
41.9k
        pdfi_countdown(ink_name);
2138
41.9k
        ink_name = NULL;
2139
41.9k
    }
2140
2141
    /* Sigh, Acrobat allows this, even though its contra the spec. Convert to
2142
     * a /Separation space, and then return. Actually Acrobat does not always permit this, see
2143
     * tests_private/comparefiles/Testform.v1.0.2.pdf.
2144
     */
2145
30.7k
    if (pdfi_array_size(inks) == 1) {
2146
25.2k
        pdf_name *ink_name = NULL;
2147
25.2k
        pdf_array *sep_color_array = NULL;
2148
25.2k
        pdf_obj *obj = NULL;
2149
2150
25.2k
        code = pdfi_array_get_type(ctx, inks, 0, PDF_NAME, (pdf_obj **)&ink_name);
2151
25.2k
        if (code < 0)
2152
0
            goto pdfi_devicen_error;
2153
2154
25.2k
        if (ink_name->length == 3 && memcmp(ink_name->data, "All", 3) == 0) {
2155
0
            code = pdfi_array_alloc(ctx, 4, &sep_color_array);
2156
0
            if (code < 0)
2157
0
                goto all_error;
2158
0
            pdfi_countup(sep_color_array);
2159
0
            code = pdfi_name_alloc(ctx, (byte *)"Separation", 10, &obj);
2160
0
            if (code < 0)
2161
0
                goto all_error;
2162
0
            pdfi_countup(obj);
2163
0
            code = pdfi_array_put(ctx, sep_color_array, 0, obj);
2164
0
            if (code < 0)
2165
0
                goto all_error;
2166
0
            pdfi_countdown(obj);
2167
0
            obj = NULL;
2168
0
            code = pdfi_array_put(ctx, sep_color_array, 1, (pdf_obj *)ink_name);
2169
0
            if (code < 0)
2170
0
                goto all_error;
2171
0
            code = pdfi_array_get(ctx, color_array, index + 2, &obj);
2172
0
            if (code < 0)
2173
0
                goto all_error;
2174
0
            code = pdfi_array_put(ctx, sep_color_array, 2, obj);
2175
0
            if (code < 0)
2176
0
                goto all_error;
2177
0
            pdfi_countdown(obj);
2178
0
            obj = NULL;
2179
0
            code = pdfi_array_get(ctx, color_array, index + 3, &obj);
2180
0
            if (code < 0)
2181
0
                goto all_error;
2182
0
            code = pdfi_array_put(ctx, sep_color_array, 3, obj);
2183
0
            if (code < 0)
2184
0
                goto all_error;
2185
0
            pdfi_countdown(obj);
2186
0
            obj = NULL;
2187
2188
0
            code = pdfi_create_Separation(ctx, sep_color_array, 0, stream_dict, page_dict, ppcs, inline_image);
2189
0
            if (code < 0)
2190
0
                goto all_error;
2191
0
all_error:
2192
0
            pdfi_countdown(ink_name);
2193
0
            pdfi_countdown(sep_color_array);
2194
0
            pdfi_countdown(obj);
2195
0
            pdfi_countdown(inks);
2196
0
            return code;
2197
0
        } else
2198
25.2k
            pdfi_countdown(ink_name);
2199
25.2k
    }
2200
2201
    /* Deal with alternate space */
2202
30.7k
    code = pdfi_array_get(ctx, color_array, index + 2, &o);
2203
30.7k
    if (code < 0)
2204
97
        goto pdfi_devicen_error;
2205
2206
30.6k
    switch (pdfi_type_of(o)) {
2207
29.2k
        case PDF_NAME:
2208
29.2k
            NamedAlternate = (pdf_name *)o;
2209
29.2k
            code = pdfi_create_colorspace_by_name(ctx, NamedAlternate, stream_dict, page_dict, &pcs_alt, inline_image);
2210
29.2k
            if (code < 0)
2211
2
                goto pdfi_devicen_error;
2212
29.2k
            break;
2213
29.2k
        case PDF_ARRAY:
2214
1.41k
            ArrayAlternate = (pdf_array *)o;
2215
1.41k
            code = pdfi_create_colorspace_by_array(ctx, ArrayAlternate, 0, stream_dict, page_dict, &pcs_alt, inline_image);
2216
1.41k
            if (code < 0)
2217
                /* OSS-fuzz error 42973; we don't need to count down 'o' here because
2218
                 * we have assigned it to ArrayAlternate and both the success and error
2219
                 * paths count down ArrayAlternate.
2220
                 */
2221
164
                goto pdfi_devicen_error;
2222
1.25k
            break;
2223
1.25k
        default:
2224
21
            code = gs_error_typecheck;
2225
21
            pdfi_countdown(o);
2226
21
            goto pdfi_devicen_error;
2227
30.6k
    }
2228
2229
    /* Now the tint transform */
2230
30.4k
    code = pdfi_array_get(ctx, color_array, index + 3, &transform);
2231
30.4k
    if (code < 0)
2232
2.41k
        goto pdfi_devicen_error;
2233
2234
28.0k
    code = pdfi_build_function(ctx, &pfn, NULL, 1, transform, page_dict);
2235
28.0k
    if (code < 0)
2236
741
        goto pdfi_devicen_error;
2237
2238
27.3k
    if (pfn->params.m != pdfi_array_size(inks) || pfn->params.n != cs_num_components(pcs_alt)) {
2239
47
        code = gs_note_error(gs_error_rangecheck);
2240
47
        goto pdfi_devicen_error;
2241
47
    }
2242
2243
27.2k
    code = gs_cspace_new_DeviceN(&pcs, pdfi_array_size(inks), pcs_alt, ctx->memory);
2244
27.2k
    if (code < 0)
2245
0
        return code;
2246
2247
27.2k
    rc_decrement(pcs_alt, "pdfi_create_DeviceN");
2248
27.2k
    pcs_alt = NULL;
2249
27.2k
    pcs->params.device_n.mem = ctx->memory;
2250
2251
62.5k
    for (ix = 0;ix < pdfi_array_size(inks);ix++) {
2252
35.3k
        pdf_name *ink_name;
2253
2254
35.3k
        ink_name = NULL;
2255
35.3k
        code = pdfi_array_get_type(ctx, inks, ix, PDF_NAME, (pdf_obj **)&ink_name);
2256
35.3k
        if (code < 0)
2257
0
            goto pdfi_devicen_error;
2258
2259
35.3k
        pcs->params.device_n.names[ix] = (char *)gs_alloc_bytes(ctx->memory->non_gc_memory, (size_t)ink_name->length + 1, "pdfi_setdevicenspace(ink)");
2260
35.3k
        if (pcs->params.device_n.names[ix] == NULL) {
2261
0
            code = gs_note_error(gs_error_VMerror);
2262
0
            goto pdfi_devicen_error;
2263
0
        }
2264
35.3k
        memcpy(pcs->params.device_n.names[ix], ink_name->data, ink_name->length);
2265
35.3k
        pcs->params.device_n.names[ix][ink_name->length] = 0x00;
2266
35.3k
        pdfi_countdown(ink_name);
2267
35.3k
    }
2268
2269
27.2k
    code = gs_cspace_set_devn_function(pcs, pfn);
2270
27.2k
    if (code < 0)
2271
0
        goto pdfi_devicen_error;
2272
2273
27.2k
    if (pdfi_array_size(color_array) >= index + 5) {
2274
26.2k
        pdf_obj *ColorSpace = NULL;
2275
26.2k
        pdf_array *Components = NULL;
2276
26.2k
        pdf_obj *subtype = NULL;
2277
2278
26.2k
        code = pdfi_array_get_type(ctx, color_array, index + 4, PDF_DICT, (pdf_obj **)&attributes);
2279
26.2k
        if (code < 0)
2280
2
            goto pdfi_devicen_error;
2281
2282
26.2k
        code = pdfi_dict_knownget(ctx, attributes, "Subtype", (pdf_obj **)&subtype);
2283
26.2k
        if (code < 0)
2284
0
            goto pdfi_devicen_error;
2285
2286
26.2k
        if (code == 0) {
2287
48
            pcs->params.device_n.subtype = gs_devicen_DeviceN;
2288
26.2k
        } else {
2289
26.2k
            switch (pdfi_type_of(subtype)) {
2290
26.2k
                case PDF_NAME:
2291
26.2k
                case PDF_STRING:
2292
26.2k
                    if (memcmp(((pdf_name *)subtype)->data, "DeviceN", 7) == 0) {
2293
152
                        pcs->params.device_n.subtype = gs_devicen_DeviceN;
2294
26.0k
                    } else {
2295
26.0k
                        if (memcmp(((pdf_name *)subtype)->data, "NChannel", 8) == 0) {
2296
26.0k
                            pcs->params.device_n.subtype = gs_devicen_NChannel;
2297
26.0k
                        } else {
2298
0
                            pdfi_countdown(subtype);
2299
0
                            goto pdfi_devicen_error;
2300
0
                        }
2301
26.0k
                    }
2302
26.2k
                    pdfi_countdown(subtype);
2303
26.2k
                    break;
2304
0
                default:
2305
0
                    pdfi_countdown(subtype);
2306
0
                    goto pdfi_devicen_error;
2307
26.2k
            }
2308
26.2k
        }
2309
2310
26.2k
        code = pdfi_dict_knownget_type(ctx, attributes, "Process", PDF_DICT, (pdf_obj **)&Process);
2311
26.2k
        if (code < 0)
2312
5
            goto pdfi_devicen_error;
2313
2314
26.2k
        if (Process != NULL && pdfi_dict_entries(Process) != 0) {
2315
26.0k
            int ix = 0;
2316
26.0k
            pdf_obj *name;
2317
2318
26.0k
            code = pdfi_dict_get(ctx, Process, "ColorSpace", (pdf_obj **)&ColorSpace);
2319
26.0k
            if (code < 0)
2320
0
                goto pdfi_devicen_error;
2321
2322
26.0k
            code = pdfi_create_colorspace(ctx, ColorSpace, stream_dict, page_dict, &process_space, inline_image);
2323
26.0k
            pdfi_countdown(ColorSpace);
2324
26.0k
            if (code < 0)
2325
0
                goto pdfi_devicen_error;
2326
2327
26.0k
            pcs->params.device_n.devn_process_space = process_space;
2328
2329
26.0k
            code = pdfi_dict_get_type(ctx, Process, "Components", PDF_ARRAY, (pdf_obj **)&Components);
2330
26.0k
            if (code < 0)
2331
0
                goto pdfi_devicen_error;
2332
2333
26.0k
            pcs->params.device_n.num_process_names = pdfi_array_size(Components);
2334
26.0k
            pcs->params.device_n.process_names = (char **)gs_alloc_bytes(pcs->params.device_n.mem->non_gc_memory, (size_t)pdfi_array_size(Components) * sizeof(char *), "pdfi_devicen(Processnames)");
2335
26.0k
            if (pcs->params.device_n.process_names == NULL) {
2336
0
                code = gs_error_VMerror;
2337
0
                goto pdfi_devicen_error;
2338
0
            }
2339
26.0k
            memset(pcs->params.device_n.process_names, 0x00, pdfi_array_size(Components) * sizeof(char *));
2340
2341
130k
            for (ix = 0; ix < pcs->params.device_n.num_process_names; ix++) {
2342
104k
                code = pdfi_array_get(ctx, Components, ix, &name);
2343
104k
                if (code < 0) {
2344
0
                    pdfi_countdown(Components);
2345
0
                    goto pdfi_devicen_error;
2346
0
                }
2347
2348
104k
                switch (pdfi_type_of(name)) {
2349
104k
                    case PDF_NAME:
2350
104k
                    case PDF_STRING:
2351
104k
                        pcs->params.device_n.process_names[ix] = (char *)gs_alloc_bytes(pcs->params.device_n.mem->non_gc_memory, ((pdf_name *)name)->length + (size_t)1, "pdfi_devicen(Processnames)");
2352
104k
                        if (pcs->params.device_n.process_names[ix] == NULL) {
2353
0
                            pdfi_countdown(Components);
2354
0
                            pdfi_countdown(name);
2355
0
                            code = gs_error_VMerror;
2356
0
                            goto pdfi_devicen_error;
2357
0
                        }
2358
104k
                        memcpy(pcs->params.device_n.process_names[ix], ((pdf_name *)name)->data, ((pdf_name *)name)->length);
2359
104k
                        pcs->params.device_n.process_names[ix][((pdf_name *)name)->length] = 0x00;
2360
104k
                        pdfi_countdown(name);
2361
104k
                        break;
2362
6
                    default:
2363
6
                        pdfi_countdown(Components);
2364
6
                        pdfi_countdown(name);
2365
6
                        goto pdfi_devicen_error;
2366
104k
                }
2367
104k
            }
2368
26.0k
            pdfi_countdown(Components);
2369
26.0k
        }
2370
2371
26.2k
        code = pdfi_dict_knownget_type(ctx, attributes, "Colorants", PDF_DICT, (pdf_obj **)&Colorants);
2372
26.2k
        if (code < 0)
2373
0
            goto pdfi_devicen_error;
2374
2375
26.2k
        if (Colorants != NULL && pdfi_dict_entries(Colorants) != 0) {
2376
0
            uint64_t ix = 0;
2377
0
            pdf_obj *Colorant = NULL, *Space = NULL;
2378
0
            char *colorant_name;
2379
0
            gs_color_space *colorant_space = NULL;
2380
2381
0
            code = pdfi_dict_first(ctx, Colorants, &Colorant, &Space, &ix);
2382
0
            if (code < 0)
2383
0
                goto pdfi_devicen_error;
2384
2385
0
            do {
2386
0
                switch (pdfi_type_of(Space)) {
2387
0
                    case PDF_STRING:
2388
0
                    case PDF_NAME:
2389
0
                    case PDF_ARRAY:
2390
0
                        break;
2391
0
                    default:
2392
0
                        pdfi_countdown(Space);
2393
0
                        pdfi_countdown(Colorant);
2394
0
                        code = gs_note_error(gs_error_typecheck);
2395
0
                        goto pdfi_devicen_error;
2396
0
                }
2397
0
                switch (pdfi_type_of(Colorant)) {
2398
0
                    case PDF_STRING:
2399
0
                    case PDF_NAME:
2400
0
                        break;
2401
0
                    default:
2402
0
                        pdfi_countdown(Space);
2403
0
                        pdfi_countdown(Colorant);
2404
0
                        code = gs_note_error(gs_error_typecheck);
2405
0
                        goto pdfi_devicen_error;
2406
0
                }
2407
2408
0
                code = pdfi_create_colorspace(ctx, Space, stream_dict, page_dict, &colorant_space, inline_image);
2409
0
                if (code < 0) {
2410
0
                    pdfi_countdown(Space);
2411
0
                    pdfi_countdown(Colorant);
2412
0
                    goto pdfi_devicen_error;
2413
0
                }
2414
2415
0
                colorant_name = (char *)gs_alloc_bytes(pcs->params.device_n.mem->non_gc_memory, ((pdf_name *)Colorant)->length + (size_t)1, "pdfi_devicen(colorant)");
2416
0
                if (colorant_name == NULL) {
2417
0
                    rc_decrement_cs(colorant_space, "pdfi_devicen(colorant)");
2418
0
                    pdfi_countdown(Space);
2419
0
                    pdfi_countdown(Colorant);
2420
0
                    code = gs_note_error(gs_error_VMerror);
2421
0
                    goto pdfi_devicen_error;
2422
0
                }
2423
0
                memcpy(colorant_name, ((pdf_name *)Colorant)->data, ((pdf_name *)Colorant)->length);
2424
0
                colorant_name[((pdf_name *)Colorant)->length] = 0x00;
2425
2426
0
                code = gs_attach_colorant_to_space(colorant_name, pcs, colorant_space, pcs->params.device_n.mem->non_gc_memory);
2427
0
                if (code < 0) {
2428
0
                    gs_free_object(pcs->params.device_n.mem->non_gc_memory, colorant_name, "pdfi_devicen(colorant)");
2429
0
                    rc_decrement_cs(colorant_space, "pdfi_devicen(colorant)");
2430
0
                    pdfi_countdown(Space);
2431
0
                    pdfi_countdown(Colorant);
2432
0
                    code = gs_note_error(gs_error_VMerror);
2433
0
                    goto pdfi_devicen_error;
2434
0
                }
2435
2436
                /* We've attached the colorant colour space to the DeviceN space, we no longer need this
2437
                 * reference to it, so discard it.
2438
                 */
2439
0
                rc_decrement_cs(colorant_space, "pdfi_devicen(colorant)");
2440
0
                pdfi_countdown(Space);
2441
0
                pdfi_countdown(Colorant);
2442
0
                Space = Colorant = NULL;
2443
2444
0
                code = pdfi_dict_next(ctx, Colorants, &Colorant, &Space, &ix);
2445
0
                if (code == gs_error_undefined)
2446
0
                    break;
2447
2448
0
                if (code < 0) {
2449
0
                    pdfi_countdown(Space);
2450
0
                    pdfi_countdown(Colorant);
2451
0
                    goto pdfi_devicen_error;
2452
0
                }
2453
0
            }while (1);
2454
0
        }
2455
26.2k
    }
2456
2457
27.2k
    if (ppcs!= NULL){
2458
196
        *ppcs = pcs;
2459
196
        pdfi_set_colour_callback(pcs, ctx, pdfi_cspace_free_callback);
2460
27.0k
    } else {
2461
27.0k
        code = pdfi_gs_setcolorspace(ctx, pcs);
2462
        /* release reference from construction */
2463
27.0k
        rc_decrement_only_cs(pcs, "setdevicenspace");
2464
27.0k
    }
2465
27.2k
    pdfi_countdown(Process);
2466
27.2k
    pdfi_countdown(Colorants);
2467
27.2k
    pdfi_countdown(attributes);
2468
27.2k
    pdfi_countdown(inks);
2469
27.2k
    pdfi_countdown(NamedAlternate);
2470
27.2k
    pdfi_countdown(ArrayAlternate);
2471
27.2k
    pdfi_countdown(transform);
2472
27.2k
    return_error(0);
2473
2474
3.50k
pdfi_devicen_error:
2475
3.50k
    pdfi_free_function(ctx, pfn);
2476
3.50k
    if (pcs_alt != NULL)
2477
3.20k
        rc_decrement_only_cs(pcs_alt, "setseparationspace");
2478
3.50k
    if(pcs != NULL)
2479
13
        rc_decrement_only_cs(pcs, "setseparationspace");
2480
3.50k
    pdfi_countdown(Process);
2481
3.50k
    pdfi_countdown(Colorants);
2482
3.50k
    pdfi_countdown(attributes);
2483
3.50k
    pdfi_countdown(inks);
2484
3.50k
    pdfi_countdown(NamedAlternate);
2485
3.50k
    pdfi_countdown(ArrayAlternate);
2486
3.50k
    pdfi_countdown(transform);
2487
3.50k
    return code;
2488
27.2k
}
2489
2490
/* Now /Indexed spaces, essentially we just need to set the underlying space(s) and then set
2491
 * /Indexed.
2492
 */
2493
static int
2494
pdfi_create_indexed(pdf_context *ctx, pdf_array *color_array, int index,
2495
                    pdf_dict *stream_dict, pdf_dict *page_dict, gs_color_space **ppcs, bool inline_image)
2496
16.2k
{
2497
16.2k
    pdf_obj *space=NULL, *lookup=NULL;
2498
16.2k
    int code;
2499
16.2k
    int64_t hival, lookup_length = 0;
2500
16.2k
    int num_values;
2501
16.2k
    gs_color_space *pcs=NULL, *pcs_base=NULL;
2502
16.2k
    gs_color_space_index base_type;
2503
16.2k
    byte *Buffer = NULL;
2504
2505
16.2k
    if (index != 0)
2506
0
        return_error(gs_error_syntaxerror);
2507
2508
16.2k
    code = pdfi_array_get_int(ctx, color_array, index + 2, &hival);
2509
16.2k
    if (code < 0)
2510
109
        return code;
2511
2512
16.1k
    if (hival > 255 || hival < 0)
2513
17
        return_error(gs_error_syntaxerror);
2514
2515
16.1k
    code = pdfi_array_get(ctx, color_array, index + 1, &space);
2516
16.1k
    if (code < 0)
2517
111
        goto exit;
2518
2519
15.9k
    code = pdfi_create_colorspace(ctx, space, stream_dict, page_dict, &pcs_base, inline_image);
2520
15.9k
    if (code < 0)
2521
470
        goto exit;
2522
2523
15.5k
    base_type = gs_color_space_get_index(pcs_base);
2524
15.5k
    if (base_type == gs_color_space_index_Pattern || base_type == gs_color_space_index_Indexed) {
2525
9
        code = gs_note_error(gs_error_typecheck);
2526
9
        goto exit;
2527
9
    }
2528
2529
15.5k
    (void)pcs_base->type->install_cspace(pcs_base, ctx->pgs);
2530
2531
15.5k
    code = pdfi_array_get(ctx, color_array, index + 3, &lookup);
2532
15.5k
    if (code < 0)
2533
225
        goto exit;
2534
2535
15.2k
    num_values = (hival+1) * cs_num_components(pcs_base);
2536
15.2k
    lookup_length = num_values;
2537
2538
15.2k
    switch (pdfi_type_of(lookup)) {
2539
8.43k
    case PDF_STREAM:
2540
8.43k
        code = pdfi_stream_to_buffer(ctx, (pdf_stream *)lookup, &Buffer, &lookup_length);
2541
8.43k
        if (code < 0)
2542
11
            goto exit;
2543
8.42k
        break;
2544
8.42k
    case PDF_STRING:
2545
6.73k
    {
2546
6.73k
        pdf_string *lookup_string = (pdf_string *)lookup; /* alias */
2547
2548
6.73k
        Buffer = gs_alloc_bytes(ctx->memory, lookup_string->length, "pdfi_create_indexed (lookup buffer)");
2549
6.73k
        if (Buffer == NULL) {
2550
0
            code = gs_note_error(gs_error_VMerror);
2551
0
            goto exit;
2552
0
        }
2553
2554
6.73k
        memcpy(Buffer, lookup_string->data, lookup_string->length);
2555
6.73k
        lookup_length = lookup_string->length;
2556
6.73k
        break;
2557
6.73k
    }
2558
115
    default:
2559
115
        code = gs_note_error(gs_error_typecheck);
2560
115
        goto exit;
2561
15.2k
    }
2562
2563
15.1k
    if (num_values > lookup_length) {
2564
        /* This is not legal, but Acrobat seems to accept it */
2565
166
        byte *SBuffer = NULL;
2566
2567
166
        code = pdfi_set_error_stop(ctx, gs_error_rangecheck, NULL, E_PDF_BAD_INDEXED_STRING, "pdfi_create_indexed", NULL);
2568
166
        if (code < 0)
2569
0
            goto exit;
2570
166
        SBuffer = gs_alloc_bytes(ctx->memory, num_values, "pdfi_create_indexed (lookup buffer)");
2571
166
        if (SBuffer == NULL) {
2572
0
            code = gs_note_error(gs_error_VMerror);
2573
0
            goto exit;
2574
0
        }
2575
166
        memcpy(SBuffer, Buffer, lookup_length);
2576
166
        memset(&SBuffer[lookup_length], 0x00, num_values - lookup_length);
2577
166
        gs_free_object(ctx->memory, Buffer, "pdfi_create_indexed (lookup buffer)");
2578
166
        Buffer = SBuffer;
2579
166
    }
2580
2581
    /* If we have a named color profile and the base space is DeviceN or
2582
       Separation use a different set of procedures to ensure the named
2583
       color remapping code is used */
2584
15.1k
    if (ctx->pgs->icc_manager->device_named != NULL &&
2585
0
        (base_type == gs_color_space_index_Separation ||
2586
0
         base_type == gs_color_space_index_DeviceN))
2587
0
        pcs = gs_cspace_alloc(ctx->memory, &gs_color_space_type_Indexed_Named);
2588
15.1k
    else
2589
15.1k
        pcs = gs_cspace_alloc(ctx->memory, &gs_color_space_type_Indexed);
2590
2591
15.1k
    if (pcs == NULL) {
2592
0
        code = gs_note_error(gs_error_VMerror);
2593
0
        goto exit;
2594
0
    }
2595
    /* NOTE: we don't need to increment the reference to pcs_base, since it is already 1 */
2596
15.1k
    pcs->base_space = pcs_base;
2597
2598
15.1k
    pcs->params.indexed.lookup.table.size = num_values;
2599
15.1k
    pcs->params.indexed.use_proc = 0;
2600
15.1k
    pcs->params.indexed.hival = hival;
2601
15.1k
    pcs->params.indexed.n_comps = cs_num_components(pcs_base);
2602
15.1k
    pcs->params.indexed.lookup.table.data = Buffer;
2603
15.1k
    Buffer = NULL;
2604
2605
15.1k
    if (ppcs != NULL) {
2606
15.0k
        *ppcs = pcs;
2607
15.0k
        pdfi_set_colour_callback(pcs, ctx, pdfi_cspace_free_callback);
2608
15.0k
    }
2609
90
    else {
2610
90
        code = pdfi_gs_setcolorspace(ctx, pcs);
2611
        /* release reference from construction */
2612
90
        rc_decrement_only_cs(pcs, "setindexedspace");
2613
90
    }
2614
2615
16.1k
 exit:
2616
16.1k
    if (code != 0)
2617
16.1k
        rc_decrement(pcs_base, "pdfi_create_indexed(pcs_base) error");
2618
16.1k
    if (Buffer)
2619
0
        gs_free_object(ctx->memory, Buffer, "pdfi_create_indexed (decompression buffer)");
2620
16.1k
    pdfi_countdown(space);
2621
16.1k
    pdfi_countdown(lookup);
2622
16.1k
    return code;
2623
15.1k
}
2624
2625
static int pdfi_create_DeviceGray(pdf_context *ctx, gs_color_space **ppcs)
2626
66.9k
{
2627
66.9k
    int code = 0;
2628
2629
66.9k
    if (ppcs != NULL) {
2630
61.4k
        if (ctx->page.DefaultGray_cs != NULL) {
2631
0
            *ppcs = ctx->page.DefaultGray_cs;
2632
0
            rc_increment(*ppcs);
2633
61.4k
        } else {
2634
61.4k
            *ppcs = gs_cspace_new_DeviceGray(ctx->memory);
2635
61.4k
            if (*ppcs == NULL)
2636
0
                code = gs_note_error(gs_error_VMerror);
2637
61.4k
            else {
2638
61.4k
                code = ((gs_color_space *)*ppcs)->type->install_cspace(*ppcs, ctx->pgs);
2639
61.4k
                if (code < 0) {
2640
0
                    rc_decrement_only_cs(*ppcs, "pdfi_create_DeviceGray");
2641
0
                    *ppcs = NULL;
2642
0
                }
2643
61.4k
            }
2644
61.4k
            if (*ppcs != NULL)
2645
61.4k
                pdfi_set_colour_callback(*ppcs, ctx, pdfi_cspace_free_callback);
2646
61.4k
        }
2647
61.4k
    } else {
2648
5.50k
        code = pdfi_gs_setgray(ctx, 0);
2649
5.50k
        pdfi_set_colour_callback(ctx->pgs->color[0].color_space, ctx, pdfi_cspace_free_callback);
2650
5.50k
    }
2651
66.9k
    return code;
2652
66.9k
}
2653
2654
static int pdfi_create_DeviceRGB(pdf_context *ctx, gs_color_space **ppcs)
2655
150k
{
2656
150k
    int code = 0;
2657
2658
150k
    if (ppcs != NULL) {
2659
92.8k
        if (ctx->page.DefaultRGB_cs != NULL) {
2660
244
            *ppcs = ctx->page.DefaultRGB_cs;
2661
244
            rc_increment(*ppcs);
2662
92.5k
        } else {
2663
92.5k
            *ppcs = gs_cspace_new_DeviceRGB(ctx->memory);
2664
92.5k
            if (*ppcs == NULL)
2665
0
                code = gs_note_error(gs_error_VMerror);
2666
92.5k
            else {
2667
92.5k
                code = ((gs_color_space *)*ppcs)->type->install_cspace(*ppcs, ctx->pgs);
2668
92.5k
                if (code < 0) {
2669
0
                    rc_decrement_only_cs(*ppcs, "pdfi_create_DeviceRGB");
2670
0
                    *ppcs = NULL;
2671
0
                }
2672
92.5k
            }
2673
92.5k
            if (*ppcs != NULL)
2674
92.5k
                pdfi_set_colour_callback(*ppcs, ctx, pdfi_cspace_free_callback);
2675
92.5k
        }
2676
92.8k
    } else {
2677
57.8k
        code = pdfi_gs_setrgbcolor(ctx, 0, 0, 0);
2678
57.8k
    }
2679
150k
    return code;
2680
150k
}
2681
2682
static int pdfi_create_DeviceCMYK(pdf_context *ctx, gs_color_space **ppcs)
2683
127k
{
2684
127k
    int code = 0;
2685
2686
127k
    if (ppcs != NULL) {
2687
97.2k
        if (ctx->page.DefaultCMYK_cs != NULL) {
2688
0
            *ppcs = ctx->page.DefaultCMYK_cs;
2689
0
            rc_increment(*ppcs);
2690
97.2k
        } else {
2691
97.2k
            *ppcs = gs_cspace_new_DeviceCMYK(ctx->memory);
2692
97.2k
            if (*ppcs == NULL)
2693
0
                code = gs_note_error(gs_error_VMerror);
2694
97.2k
            else {
2695
97.2k
                code = ((gs_color_space *)*ppcs)->type->install_cspace(*ppcs, ctx->pgs);
2696
97.2k
                if (code < 0) {
2697
0
                    rc_decrement_only_cs(*ppcs, "pdfi_create_DeviceCMYK");
2698
0
                    *ppcs = NULL;
2699
0
                }
2700
97.2k
            }
2701
97.2k
            if (*ppcs != NULL)
2702
97.2k
                pdfi_set_colour_callback(*ppcs, ctx, pdfi_cspace_free_callback);
2703
97.2k
        }
2704
97.2k
    } else {
2705
30.2k
        code = pdfi_gs_setcmykcolor(ctx, 0, 0, 0, 1);
2706
30.2k
        pdfi_set_colour_callback(ctx->pgs->color[0].color_space, ctx, pdfi_cspace_free_callback);
2707
30.2k
    }
2708
127k
    return code;
2709
127k
}
2710
2711
static int pdfi_create_JPX_space(pdf_context *ctx, const char *name, int num_components, gs_color_space **ppcs)
2712
5.57k
{
2713
5.57k
    int code, icc_N;
2714
5.57k
    float range_buff[6] = {0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f};
2715
2716
5.57k
    code = pdfi_create_icc(ctx, (char *)name, NULL, num_components, &icc_N, range_buff, 0, ppcs);
2717
5.57k
    return code;
2718
5.57k
}
2719
2720
/* These next routines allow us to use recursion to set up colour spaces. We can set
2721
 * colour space starting from a name (which can be a named resource) or an array.
2722
 * If we get a name, and its a named resource we dereference it and go round again.
2723
 * If its an array we select the correct handler (above) for that space. The space
2724
 * handler will call pdfi_create_colorspace() to set the underlying space(s) which
2725
 * may mean calling pdfi_create_colorspace again....
2726
 */
2727
static int
2728
pdfi_create_colorspace_by_array(pdf_context *ctx, pdf_array *color_array, int index,
2729
                                pdf_dict *stream_dict, pdf_dict *page_dict, gs_color_space **ppcs,
2730
                                bool inline_image)
2731
397k
{
2732
397k
    int code;
2733
397k
    pdf_name *space = NULL;
2734
397k
    pdf_array *a = NULL;
2735
2736
397k
    code = pdfi_array_get_type(ctx, color_array, index, PDF_NAME, (pdf_obj **)&space);
2737
397k
    if (code != 0)
2738
387
        goto exit;
2739
2740
396k
    code = 0;
2741
396k
    if (pdfi_name_is(space, "G") || pdfi_name_is(space, "DeviceGray")) {
2742
21
        if (pdfi_name_is(space, "G") && !inline_image) {
2743
0
            if ((code = pdfi_set_warning_stop(ctx, gs_note_error(gs_error_syntaxerror), NULL, W_PDF_BAD_INLINECOLORSPACE, "pdfi_create_colorspace_by_array", NULL)) < 0)
2744
0
                return code;
2745
0
        }
2746
21
        code = pdfi_create_DeviceGray(ctx, ppcs);
2747
396k
    } else if (pdfi_name_is(space, "I") || pdfi_name_is(space, "Indexed")) {
2748
16.2k
        if (pdfi_name_is(space, "I") && !inline_image) {
2749
109
            pdfi_set_warning(ctx, 0, NULL, W_PDF_BAD_INLINECOLORSPACE, "pdfi_create_colorspace_by_array", NULL);
2750
109
            if (ctx->args.pdfstoponwarning)
2751
0
                return_error(gs_error_syntaxerror);
2752
109
        }
2753
16.2k
        code = pdfi_create_indexed(ctx, color_array, index, stream_dict, page_dict, ppcs, inline_image);
2754
380k
    } else if (pdfi_name_is(space, "Lab")) {
2755
1.31k
        code = pdfi_create_Lab(ctx, color_array, index, stream_dict, page_dict, ppcs);
2756
379k
    } else if (pdfi_name_is(space, "RGB") || pdfi_name_is(space, "DeviceRGB")) {
2757
17
        if (pdfi_name_is(space, "RGB") && !inline_image) {
2758
0
            pdfi_set_warning(ctx, 0, NULL, W_PDF_BAD_INLINECOLORSPACE, "pdfi_create_colorspace_by_array", NULL);
2759
0
            if (ctx->args.pdfstoponwarning)
2760
0
                return_error(gs_error_syntaxerror);
2761
0
        }
2762
17
        code = pdfi_create_DeviceRGB(ctx, ppcs);
2763
379k
    } else if (pdfi_name_is(space, "CMYK") || pdfi_name_is(space, "DeviceCMYK") || pdfi_name_is(space, "CalCMYK")) {
2764
0
        if (pdfi_name_is(space, "CMYK") && !inline_image) {
2765
0
            pdfi_set_warning(ctx, 0, NULL, W_PDF_BAD_INLINECOLORSPACE, "pdfi_create_colorspace_by_array", NULL);
2766
0
            if (ctx->args.pdfstoponwarning)
2767
0
                return_error(gs_error_syntaxerror);
2768
0
        }
2769
0
        code = pdfi_create_DeviceCMYK(ctx, ppcs);
2770
379k
    } else if (pdfi_name_is(space, "CalRGB")) {
2771
3.80k
        code = pdfi_create_CalRGB(ctx, color_array, index, stream_dict, page_dict, ppcs);
2772
375k
    } else if (pdfi_name_is(space, "CalGray")) {
2773
822
        code = pdfi_create_CalGray(ctx, color_array, index, stream_dict, page_dict, ppcs);
2774
374k
    } else if (pdfi_name_is(space, "Pattern")) {
2775
2.71k
        if (index != 0)
2776
0
            code = gs_note_error(gs_error_syntaxerror);
2777
2.71k
        else
2778
2.71k
            code = pdfi_pattern_create(ctx, color_array, stream_dict, page_dict, ppcs);
2779
371k
    } else if (pdfi_name_is(space, "DeviceN")) {
2780
30.7k
        code = pdfi_create_DeviceN(ctx, color_array, index, stream_dict, page_dict, ppcs, inline_image);
2781
341k
    } else if (pdfi_name_is(space, "ICCBased")) {
2782
262k
        code = pdfi_create_iccbased(ctx, color_array, index, stream_dict, page_dict, ppcs, inline_image);
2783
262k
    } else if (pdfi_name_is(space, "Separation")) {
2784
77.8k
        code = pdfi_create_Separation(ctx, color_array, index, stream_dict, page_dict, ppcs, inline_image);
2785
77.8k
    } else {
2786
905
        if (stream_dict == NULL)
2787
42
            code = gs_note_error(gs_error_syntaxerror);
2788
863
        else
2789
863
            code = pdfi_find_resource(ctx, (unsigned char *)"ColorSpace",
2790
863
                                  space, (pdf_dict *)stream_dict, page_dict, (pdf_obj **)&a);
2791
905
        if (code < 0)
2792
905
            goto exit;
2793
2794
0
        if (pdfi_type_of(a) != PDF_ARRAY) {
2795
0
            code = gs_note_error(gs_error_typecheck);
2796
0
            goto exit;
2797
0
        }
2798
2799
        /* recursion */
2800
0
        code = pdfi_create_colorspace_by_array(ctx, a, 0, stream_dict, page_dict, ppcs, inline_image);
2801
0
    }
2802
2803
397k
 exit:
2804
397k
    pdfi_countdown(space);
2805
397k
    pdfi_countdown(a);
2806
397k
    return code;
2807
396k
}
2808
2809
static int
2810
pdfi_create_colorspace_by_name(pdf_context *ctx, pdf_name *name,
2811
                               pdf_dict *stream_dict, pdf_dict *page_dict,
2812
                               gs_color_space **ppcs, bool inline_image)
2813
851k
{
2814
851k
    int code = 0;
2815
851k
    gs_id oldid = 0;
2816
2817
851k
    if (pdfi_name_is(name, "G") || pdfi_name_is(name, "DeviceGray")) {
2818
66.9k
        if (pdfi_name_is(name, "G") && !inline_image) {
2819
30
            if ((code = pdfi_set_warning_stop(ctx, gs_note_error(gs_error_syntaxerror), NULL, W_PDF_BAD_INLINECOLORSPACE, "pdfi_create_colorspace_by_name", NULL)) < 0)
2820
0
                return code;
2821
30
        }
2822
66.9k
        code = pdfi_create_DeviceGray(ctx, ppcs);
2823
784k
    } else if (pdfi_name_is(name, "RGB") || pdfi_name_is(name, "DeviceRGB")) {
2824
150k
        if (pdfi_name_is(name, "RGB") && !inline_image) {
2825
0
            if ((code = pdfi_set_warning_stop(ctx, gs_note_error(gs_error_syntaxerror), NULL, W_PDF_BAD_INLINECOLORSPACE, "pdfi_create_colorspace_by_name", NULL)) < 0)
2826
0
                return code;
2827
0
        }
2828
150k
        code = pdfi_create_DeviceRGB(ctx, ppcs);
2829
634k
    } else if (pdfi_name_is(name, "CMYK") || pdfi_name_is(name, "DeviceCMYK") || pdfi_name_is(name, "CalCMYK")) {
2830
127k
        if (pdfi_name_is(name, "CMYK") && !inline_image) {
2831
0
            if ((code = pdfi_set_warning_stop(ctx, gs_note_error(gs_error_syntaxerror), NULL, W_PDF_BAD_INLINECOLORSPACE, "pdfi_create_colorspace_by_name", NULL)) < 0)
2832
0
                return code;
2833
0
        }
2834
127k
        code = pdfi_create_DeviceCMYK(ctx, ppcs);
2835
506k
    } else if (pdfi_name_is(name, "Pattern")) {
2836
77.0k
        code = pdfi_pattern_create(ctx, NULL, stream_dict, page_dict, ppcs);
2837
429k
    } else if (pdfi_name_is(name, "esRGBICC")) {                /* These 4 spaces are 'special' for JPX images          */
2838
0
        code = pdfi_create_JPX_space(ctx, "esrgb", 3, ppcs);    /* the names are non-standad and must match those in    */
2839
429k
    } else if (pdfi_name_is(name, "rommRGBICC")) {              /* pdfi_image_get_color() in pdf_image.c                */
2840
0
        code = pdfi_create_JPX_space(ctx, "rommrgb", 3, ppcs);  /* Note that the Lab space for JPX images does not use  */
2841
429k
    } else if (pdfi_name_is(name, "sRGBICC")) {                 /* a special space but simply constructs an appropriate */
2842
670
        code = pdfi_create_JPX_space(ctx, "srgb", 3, ppcs);     /* pdf_array object with the corerct contents for an    */
2843
429k
    } else if (pdfi_name_is(name, "sGrayICC")) {                /* Lab space with a D65 white point.                    */
2844
4.90k
        code = pdfi_create_JPX_space(ctx, "sgray", 1, ppcs);
2845
424k
    } else {
2846
424k
        pdf_obj *ref_space = NULL;
2847
2848
424k
        if (ppcs == NULL && check_same_current_space(ctx, name) == 1)
2849
121k
            return 0;
2850
2851
302k
        code = pdfi_find_resource(ctx, (unsigned char *)"ColorSpace", name, (pdf_dict *)stream_dict,
2852
302k
                                  page_dict, &ref_space);
2853
302k
        if (code < 0)
2854
45.7k
            return code;
2855
2856
256k
        if (pdfi_type_of(ref_space) == PDF_NAME) {
2857
291
            if (ref_space->object_num != 0 && ref_space->object_num == name->object_num) {
2858
0
                pdfi_countdown(ref_space);
2859
0
                return_error(gs_error_circular_reference);
2860
0
            }
2861
291
            if (((pdf_name *)ref_space)->length <= 0) {
2862
13
                pdfi_countdown(ref_space);
2863
13
                return_error(gs_error_syntaxerror);
2864
13
            }
2865
278
            if (((pdf_name *)ref_space)->length == name->length && memcmp(((pdf_name *)ref_space)->data, name->data, name->length) == 0) {
2866
4
                pdfi_countdown(ref_space);
2867
4
                return_error(gs_error_circular_reference);
2868
4
            }
2869
278
        }
2870
2871
256k
        oldid = ctx->pgs->color[0].color_space->id;
2872
        /* recursion */
2873
256k
        code = pdfi_create_colorspace(ctx, ref_space, stream_dict, page_dict, ppcs, inline_image);
2874
2875
256k
        if (code >= 0) {
2876
227k
            if (oldid != ctx->pgs->color[0].color_space->id) {
2877
225k
                if (ppcs != NULL)
2878
0
                    pdfi_set_colourspace_name(ctx, *ppcs, name);
2879
225k
                else
2880
225k
                    pdfi_set_colourspace_name(ctx, ctx->pgs->color[0].color_space, name);
2881
225k
            }
2882
227k
        }
2883
2884
256k
        pdfi_countdown(ref_space);
2885
256k
        return code;
2886
256k
    }
2887
2888
    /* If we got here, it's a recursion base case, and ppcs should have been set if requested */
2889
427k
    if (ppcs != NULL && *ppcs == NULL)
2890
0
        code = gs_note_error(gs_error_VMerror);
2891
427k
    return code;
2892
851k
}
2893
2894
/*
2895
 * Gets icc profile data from the provided stream.
2896
 * Position in the stream is NOT preserved.
2897
 * This is raw data, not filtered, so no need to worry about compression.
2898
 * (Used for JPXDecode images)
2899
 */
2900
int
2901
pdfi_create_icc_colorspace_from_stream(pdf_context *ctx, pdf_c_stream *stream, gs_offset_t offset,
2902
                                       unsigned int length, int comps, int *icc_N, ulong dictkey, gs_color_space **ppcs)
2903
0
{
2904
0
    pdf_c_stream *profile_stream = NULL;
2905
0
    byte *profile_buffer;
2906
0
    int code, code1;
2907
0
    float range[8] = {0,1,0,1,0,1,0,1};
2908
2909
    /* Move to the start of the profile data */
2910
0
    pdfi_seek(ctx, stream, offset, SEEK_SET);
2911
2912
    /* The ICC profile reading code (irritatingly) requires a seekable stream, because it
2913
     * rewinds it to the start, then seeks to the end to find the size, then rewinds the
2914
     * stream again.
2915
     * Ideally we would use a ReusableStreamDecode filter here, but that is largely
2916
     * implemented in PostScript (!) so we can't use it. What we can do is create a
2917
     * string sourced stream in memory, which is at least seekable.
2918
     */
2919
0
    code = pdfi_open_memory_stream_from_stream(ctx, length, &profile_buffer, stream, &profile_stream, true);
2920
0
    if (code < 0) {
2921
0
        return code;
2922
0
    }
2923
2924
    /* Now, finally, we can call the code to create and set the profile */
2925
0
    code = pdfi_create_icc(ctx, NULL, profile_stream->s, comps, icc_N, range, dictkey, ppcs);
2926
2927
0
    code1 = pdfi_close_memory_stream(ctx, profile_buffer, profile_stream);
2928
2929
0
    if (code == 0)
2930
0
        code = code1;
2931
2932
0
    return code;
2933
0
}
2934
2935
int pdfi_create_colorspace(pdf_context *ctx, pdf_obj *space, pdf_dict *stream_dict, pdf_dict *page_dict, gs_color_space **ppcs, bool inline_image)
2936
1.13M
{
2937
1.13M
    int code;
2938
2939
1.13M
    code = pdfi_loop_detector_mark(ctx);
2940
1.13M
    if (code < 0)
2941
0
        return code;
2942
2943
1.13M
    switch (pdfi_type_of(space)) {
2944
750k
    case PDF_NAME:
2945
750k
        code = pdfi_create_colorspace_by_name(ctx, (pdf_name *)space, stream_dict, page_dict, ppcs, inline_image);
2946
750k
        break;
2947
378k
    case PDF_ARRAY:
2948
378k
        code = pdfi_create_colorspace_by_array(ctx, (pdf_array *)space, 0, stream_dict, page_dict, ppcs, inline_image);
2949
378k
        break;
2950
5.43k
    default:
2951
5.43k
        pdfi_loop_detector_cleartomark(ctx);
2952
5.43k
        return_error(gs_error_typecheck);
2953
1.13M
    }
2954
1.12M
    if (code >= 0 && ppcs && *ppcs)
2955
228k
        (void)(*ppcs)->type->install_cspace(*ppcs, ctx->pgs);
2956
2957
1.12M
    (void)pdfi_loop_detector_cleartomark(ctx);
2958
1.12M
    return code;
2959
1.13M
}
2960
2961
int pdfi_setcolorspace(pdf_context *ctx, pdf_obj *space, pdf_dict *stream_dict, pdf_dict *page_dict)
2962
642k
{
2963
642k
    return pdfi_create_colorspace(ctx, space, stream_dict, page_dict, NULL, false);
2964
642k
}
2965
2966
/* And finally, the implementation of the actual PDF operators CS and cs */
2967
int pdfi_setstrokecolor_space(pdf_context *ctx, pdf_dict *stream_dict, pdf_dict *page_dict)
2968
82.4k
{
2969
82.4k
    int code;
2970
82.4k
    pdf_obj *n = NULL;
2971
2972
82.4k
    if (pdfi_count_stack(ctx) < 1)
2973
945
        return_error(gs_error_stackunderflow);
2974
2975
81.4k
    if (ctx->text.inside_CharProc && ctx->text.CharProc_d_type != pdf_type3_d0) {
2976
0
        pdfi_pop(ctx, 1);
2977
0
        pdfi_log_info(ctx, "pdfi_setstrokecolor_space", "colour operator in a CharProc, following a d1 ignored\n");
2978
0
        return 0;
2979
0
    }
2980
2981
81.4k
    if (pdfi_type_of(ctx->stack_top[-1]) != PDF_NAME) {
2982
1.44k
        pdfi_pop(ctx, 1);
2983
1.44k
        return_error(gs_error_typecheck);
2984
1.44k
    }
2985
80.0k
    n = ctx->stack_top[-1];
2986
80.0k
    pdfi_countup(n);
2987
80.0k
    pdfi_pop(ctx, 1);
2988
2989
80.0k
    gs_swapcolors_quick(ctx->pgs);
2990
80.0k
    code = pdfi_setcolorspace(ctx, n, stream_dict, page_dict);
2991
80.0k
    gs_swapcolors_quick(ctx->pgs);
2992
2993
80.0k
    pdfi_countdown(n);
2994
80.0k
    return code;
2995
81.4k
}
2996
2997
int pdfi_setfillcolor_space(pdf_context *ctx, pdf_dict *stream_dict, pdf_dict *page_dict)
2998
436k
{
2999
436k
    int code;
3000
436k
    pdf_obj *n = NULL;
3001
3002
436k
    if (pdfi_count_stack(ctx) < 1)
3003
5.31k
        return_error(gs_error_stackunderflow);
3004
3005
431k
    if (ctx->text.inside_CharProc && ctx->text.CharProc_d_type != pdf_type3_d0) {
3006
7
        pdfi_pop(ctx, 1);
3007
7
        pdfi_log_info(ctx, "pdfi_setfillcolor_space", "colour operator in a CharProc, following a d1 ignored\n");
3008
7
        return 0;
3009
7
    }
3010
3011
431k
    if (pdfi_type_of(ctx->stack_top[-1]) != PDF_NAME) {
3012
9.18k
        pdfi_pop(ctx, 1);
3013
9.18k
        return_error(gs_error_typecheck);
3014
9.18k
    }
3015
422k
    n = ctx->stack_top[-1];
3016
422k
    pdfi_countup(n);
3017
422k
    pdfi_pop(ctx, 1);
3018
3019
422k
    code = pdfi_setcolorspace(ctx, n, stream_dict, page_dict);
3020
3021
422k
    pdfi_countdown(n);
3022
422k
    return code;
3023
431k
}
3024
3025
3026
/*
3027
 * Set device outputintent from stream
3028
 * see zicc.c/zset_outputintent()
3029
 */
3030
static int pdfi_device_setoutputintent(pdf_context *ctx, pdf_dict *profile_dict, stream *stream)
3031
0
{
3032
0
    int code = 0;
3033
0
    gs_gstate *pgs = ctx->pgs;
3034
0
    gx_device *dev = gs_currentdevice(pgs);
3035
0
    cmm_dev_profile_t *dev_profile;
3036
0
    int64_t N;
3037
0
    int ncomps, dev_comps;
3038
0
    int expected = 0;
3039
0
    cmm_profile_t *picc_profile = NULL;
3040
0
    cmm_profile_t *source_profile = NULL;
3041
0
    gsicc_manager_t *icc_manager = pgs->icc_manager;
3042
0
    gs_color_space_index index;
3043
3044
0
    if_debug0m(gs_debug_flag_icc, ctx->memory, "[icc] Using OutputIntent\n");
3045
3046
    /* get dev_profile and try initing it if fail first time */
3047
0
    code = dev_proc(dev, get_profile)(dev, &dev_profile);
3048
0
    if (code < 0)
3049
0
        return code;
3050
3051
0
    if (dev_profile == NULL) {
3052
0
        code = gsicc_init_device_profile_struct(dev, NULL, 0);
3053
0
        if (code < 0)
3054
0
            return code;
3055
0
        code = dev_proc(dev, get_profile)(dev, &dev_profile);
3056
0
        if (code < 0)
3057
0
            return code;
3058
0
    }
3059
0
    if (dev_profile->oi_profile != NULL) {
3060
0
        return 0;  /* Allow only one setting of this object */
3061
0
    }
3062
3063
0
    code = pdfi_dict_get_int(ctx, profile_dict, "N", &N);
3064
0
    if (code < 0)
3065
0
        goto exit;
3066
0
    ncomps = (int)N;
3067
3068
0
    picc_profile = gsicc_profile_new(stream, gs_gstate_memory(pgs), NULL, 0);
3069
0
    if (picc_profile == NULL) {
3070
0
        code = gs_note_error(gs_error_VMerror);
3071
0
        goto exit;
3072
0
    }
3073
0
    picc_profile->num_comps = ncomps;
3074
0
    picc_profile->profile_handle =
3075
0
        gsicc_get_profile_handle_buffer(picc_profile->buffer,
3076
0
                                        picc_profile->buffer_size,
3077
0
                                        gs_gstate_memory(pgs));
3078
0
    if (picc_profile->profile_handle == NULL) {
3079
0
        code = gs_note_error(gs_error_VMerror);
3080
0
        goto exit;
3081
0
    }
3082
3083
0
    picc_profile->data_cs =
3084
0
        gscms_get_profile_data_space(picc_profile->profile_handle,
3085
0
            picc_profile->memory);
3086
0
    switch (picc_profile->data_cs) {
3087
0
        case gsCIEXYZ:
3088
0
        case gsCIELAB:
3089
0
        case gsRGB:
3090
0
            expected = 3;
3091
0
            source_profile = icc_manager->default_rgb;
3092
0
            break;
3093
0
        case gsGRAY:
3094
0
            expected = 1;
3095
0
            source_profile = icc_manager->default_gray;
3096
0
            break;
3097
0
        case gsCMYK:
3098
0
            expected = 4;
3099
0
            source_profile = icc_manager->default_cmyk;
3100
0
            break;
3101
0
        case gsNCHANNEL:
3102
0
            expected = 0;
3103
0
            break;
3104
0
        case gsNAMED:
3105
0
        case gsUNDEFINED:
3106
0
            break;
3107
0
    }
3108
0
    if (expected && ncomps != expected) {
3109
0
        code = gs_note_error(gs_error_rangecheck);
3110
0
        goto exit;
3111
0
    }
3112
0
    gsicc_init_hash_cs(picc_profile, pgs);
3113
3114
    /* All is well with the profile.  Lets set the stuff that needs to be set */
3115
0
    dev_profile->oi_profile = picc_profile;
3116
0
    rc_increment(picc_profile);
3117
0
    picc_profile->name = (char *) gs_alloc_bytes(picc_profile->memory,
3118
0
                                                 MAX_DEFAULT_ICC_LENGTH,
3119
0
                                                 "pdfi_color_setoutputintent");
3120
0
    if (picc_profile->name == NULL) {
3121
0
        code = gs_note_error(gs_error_VMerror);
3122
0
        goto exit;
3123
0
    }
3124
0
    strncpy(picc_profile->name, OI_PROFILE, strlen(OI_PROFILE));
3125
0
    picc_profile->name[strlen(OI_PROFILE)] = 0;
3126
0
    picc_profile->name_length = strlen(OI_PROFILE);
3127
    /* Set the range of the profile */
3128
0
    gsicc_set_icc_range(&picc_profile);
3129
3130
    /* If the output device has a different number of components, then we are
3131
       going to set the output intent as the proofing profile, unless the
3132
       proofing profile has already been set.
3133
3134
       If the device has the same number of components (and color model) then as
3135
       the profile we will use this as the output profile, unless someone has
3136
       explicitly set the output profile.
3137
3138
       Finally, we will use the output intent profile for the default profile
3139
       of the proper Device profile in the icc manager, again, unless someone
3140
       has explicitly set this default profile.
3141
3142
       All of this is skipped if we are forcing oveprint simulation with
3143
       the output intent set, in which case we will push the pdf14 device
3144
       to render directly to the the output intent color space and then
3145
       do a final transform to the target color space.
3146
    */
3147
0
    dev_comps = dev_profile->device_profile[GS_DEFAULT_DEVICE_PROFILE]->num_comps;
3148
0
    index = gsicc_get_default_type(dev_profile->device_profile[GS_DEFAULT_DEVICE_PROFILE]);
3149
3150
    /* If we are doing simulate overprint and the output intent is different than
3151
       what the device profile is the we will end up pushing the pdf14 device
3152
       and doing a rendering to the output intent color space.  Keep the device
3153
       profile as is, and do not do a proofing profile */
3154
3155
0
    if (!(ctx->pgs->device->icc_struct->overprint_control == gs_overprint_control_simulate &&
3156
0
        !gsicc_profiles_equal(dev_profile->oi_profile, dev_profile->device_profile[GS_DEFAULT_DEVICE_PROFILE]))) {
3157
0
        if (ncomps == dev_comps && index < gs_color_space_index_DevicePixel) {
3158
            /* The OI profile is the same type as the profile for the device and a
3159
               "default" profile for the device was not externally set. So we go
3160
               ahead and use the OI profile as the device profile.  Care needs to be
3161
               taken here to keep from screwing up any device parameters.   We will
3162
               use a keyword of OIProfile for the user/device parameter to indicate
3163
               its usage.  Also, note conflicts if one is setting object dependent
3164
               color management */
3165
0
            dev_profile->device_profile[GS_DEFAULT_DEVICE_PROFILE] = picc_profile;
3166
0
            rc_increment(picc_profile);
3167
0
            if_debug0m(gs_debug_flag_icc, ctx->memory, "[icc] OutputIntent used for device profile\n");
3168
0
        } else {
3169
0
            if (dev_profile->proof_profile == NULL) {
3170
                /* This means that we should use the OI profile as the proofing
3171
                   profile.  Note that if someone already has specified a
3172
                   proofing profile it is unclear what they are trying to do
3173
                   with the output intent.  In this case, we will use it
3174
                   just for the source data below */
3175
0
                dev_profile->proof_profile = picc_profile;
3176
0
                rc_increment(picc_profile);
3177
0
                if_debug0m(gs_debug_flag_icc, ctx->memory, "[icc] OutputIntent used for proof profile\n");
3178
0
            }
3179
0
        }
3180
0
    }
3181
3182
    /* Now the source colors.  See which source color space needs to use the
3183
       output intent ICC profile */
3184
0
    index = gsicc_get_default_type(source_profile);
3185
0
    if (index < gs_color_space_index_DevicePixel) {
3186
        /* source_profile is currently the default.  Set it to the OI profile */
3187
0
        switch (picc_profile->data_cs) {
3188
0
            case gsGRAY:
3189
0
                if_debug0m(gs_debug_flag_icc, ctx->memory, "[icc] OutputIntent used source Gray\n");
3190
0
                icc_manager->default_gray = picc_profile;
3191
0
                rc_increment(picc_profile);
3192
0
                break;
3193
0
            case gsRGB:
3194
0
                if_debug0m(gs_debug_flag_icc, ctx->memory, "[icc] OutputIntent used source RGB\n");
3195
0
                icc_manager->default_rgb = picc_profile;
3196
0
                rc_increment(picc_profile);
3197
0
                break;
3198
0
            case gsCMYK:
3199
0
                if_debug0m(gs_debug_flag_icc, ctx->memory, "[icc] OutputIntent used source CMYK\n");
3200
0
                icc_manager->default_cmyk = picc_profile;
3201
0
                rc_increment(picc_profile);
3202
0
                break;
3203
0
            default:
3204
0
                break;
3205
0
        }
3206
0
    }
3207
3208
0
 exit:
3209
0
    if (picc_profile != NULL)
3210
0
        rc_decrement(picc_profile, "pdfi_color_setoutputintent");
3211
0
    return code;
3212
0
}
3213
3214
/*
3215
 * intent_dict -- the outputintent dictionary
3216
 * profile -- the color profile (a stream)
3217
 *
3218
 */
3219
int pdfi_color_setoutputintent(pdf_context *ctx, pdf_dict *intent_dict, pdf_stream *profile)
3220
0
{
3221
0
    pdf_c_stream *profile_stream = NULL;
3222
0
    byte *profile_buffer;
3223
0
    int code, code1;
3224
0
    pdf_dict *profile_dict;
3225
3226
0
    code = pdfi_dict_from_obj(ctx, (pdf_obj *)profile, &profile_dict);
3227
0
    if (code < 0)
3228
0
        return code;
3229
3230
    /* The ICC profile reading code (irritatingly) requires a seekable stream, because it
3231
     * rewinds it to the start, then seeks to the end to find the size, then rewinds the
3232
     * stream again.
3233
     * Ideally we would use a ReusableStreamDecode filter here, but that is largely
3234
     * implemented in PostScript (!) so we can't use it. What we can do is create a
3235
     * string sourced stream in memory, which is at least seekable.
3236
     */
3237
0
    code = pdfi_open_memory_stream_from_filtered_stream(ctx, profile, &profile_buffer, &profile_stream, true);
3238
0
    if (code < 0)
3239
0
        goto exit;
3240
3241
    /* Create and set the device profile */
3242
0
    code = pdfi_device_setoutputintent(ctx, profile_dict, profile_stream->s);
3243
3244
0
    code1 = pdfi_close_memory_stream(ctx, profile_buffer, profile_stream);
3245
3246
0
    if (code == 0)
3247
0
        code = code1;
3248
3249
0
 exit:
3250
0
    return code;
3251
0
}
3252
3253
static int Check_Default_Space(pdf_context *ctx, pdf_obj *space, pdf_dict *source_dict, int num_components)
3254
1.08k
{
3255
1.08k
    pdf_obj *primary = NULL;
3256
1.08k
    pdf_obj *ref_space = NULL;
3257
1.08k
    int code = 0;
3258
3259
1.08k
    if (pdfi_type_of(space) == PDF_NAME)
3260
0
    {
3261
0
        if (pdfi_name_is((const pdf_name *)space, "DeviceGray"))
3262
0
            return (num_components == 1 ? 0 : gs_error_rangecheck);
3263
0
        if (pdfi_name_is((const pdf_name *)space, "DeviceCMYK"))
3264
0
            return (num_components == 4 ? 0 : gs_error_rangecheck);
3265
0
        if (pdfi_name_is((const pdf_name *)space, "DeviceRGB"))
3266
0
            return (num_components == 3 ? 0 : gs_error_rangecheck);
3267
3268
0
        code = pdfi_find_resource(ctx, (unsigned char *)"ColorSpace", (pdf_name *)space, (pdf_dict *)source_dict,
3269
0
                                  NULL, &ref_space);
3270
0
        if (code < 0)
3271
0
            return code;
3272
3273
0
        if (pdfi_type_of(ref_space) == PDF_NAME) {
3274
0
            if (ref_space->object_num != 0 && ref_space->object_num == space->object_num) {
3275
0
                pdfi_countdown(ref_space);
3276
0
                return_error(gs_error_circular_reference);
3277
0
            }
3278
0
            if (pdfi_name_is((const pdf_name *)ref_space, "DeviceGray")) {
3279
0
                pdfi_countdown(ref_space);
3280
0
                return (num_components == 1 ? 0 : gs_error_rangecheck);
3281
0
            }
3282
0
            if (pdfi_name_is((const pdf_name *)ref_space, "DeviceCMYK")) {
3283
0
                pdfi_countdown(ref_space);
3284
0
                return (num_components == 4 ? 0 : gs_error_rangecheck);
3285
0
            }
3286
0
            if (pdfi_name_is((const pdf_name *)ref_space, "DeviceRGB")) {
3287
0
                pdfi_countdown(ref_space);
3288
0
                return (num_components == 3 ? 0 : gs_error_rangecheck);
3289
0
            }
3290
0
            pdfi_countdown(ref_space);
3291
0
            return_error(gs_error_typecheck);
3292
0
        }
3293
0
        space = ref_space;
3294
0
    }
3295
3296
1.08k
    if (pdfi_type_of(space) == PDF_ARRAY) {
3297
1.05k
        code = pdfi_array_get(ctx, (pdf_array *)space, 0, &primary);
3298
1.05k
        if (code < 0)
3299
0
            goto exit;
3300
3301
1.05k
        if (pdfi_type_of(primary) == PDF_NAME) {
3302
1.05k
            if (pdfi_name_is((pdf_name *)primary, "Lab")) {
3303
0
                code = gs_note_error(gs_error_typecheck);
3304
0
                goto exit;
3305
0
            }
3306
1.05k
            if (pdfi_name_is((pdf_name *)primary, "Pattern")) {
3307
5
                code = gs_note_error(gs_error_typecheck);
3308
5
                goto exit;
3309
5
            }
3310
1.05k
            if (pdfi_name_is((pdf_name *)primary, "Indexed")) {
3311
0
                code = gs_note_error(gs_error_typecheck);
3312
0
                goto exit;
3313
0
            }
3314
1.05k
        }
3315
1.05k
    } else
3316
30
        code = gs_note_error(gs_error_typecheck);
3317
3318
1.08k
exit:
3319
1.08k
    pdfi_countdown(primary);
3320
1.08k
    pdfi_countdown(ref_space);
3321
1.08k
    return code;
3322
1.08k
}
3323
3324
int pdfi_setup_DefaultSpaces(pdf_context *ctx, pdf_dict *source_dict)
3325
582k
{
3326
582k
    int code = 0;
3327
582k
    pdf_dict *resources_dict = NULL, *colorspaces_dict = NULL;
3328
582k
    pdf_obj *DefaultSpace = NULL;
3329
3330
582k
    if (ctx->args.NOSUBSTDEVICECOLORS)
3331
0
        return 0;
3332
3333
    /* Create any required DefaultGray, DefaultRGB or DefaultCMYK
3334
     * spaces.
3335
     */
3336
582k
    code = pdfi_dict_knownget(ctx, source_dict, "Resources", (pdf_obj **)&resources_dict);
3337
582k
    if (code > 0) {
3338
482k
        code = pdfi_dict_knownget(ctx, resources_dict, "ColorSpace", (pdf_obj **)&colorspaces_dict);
3339
482k
        if (code > 0) {
3340
54.7k
            code = pdfi_dict_knownget(ctx, colorspaces_dict, "DefaultGray", &DefaultSpace);
3341
54.7k
            if (code > 0) {
3342
0
                gs_color_space *pcs;
3343
3344
0
                code = Check_Default_Space(ctx, DefaultSpace, source_dict, 1);
3345
0
                if (code >= 0) {
3346
0
                    code = pdfi_create_colorspace(ctx, DefaultSpace, NULL, source_dict, &pcs, false);
3347
                    /* If any given Default* space fails simply ignore it, we wil then use the Device
3348
                     * space instead, this is as per the spec.
3349
                     */
3350
0
                    if (code >= 0) {
3351
0
                        if (gs_color_space_num_components(pcs) == 1) {
3352
0
                            ctx->page.DefaultGray_cs = pcs;
3353
0
                            pdfi_set_colour_callback(pcs, ctx, NULL);
3354
0
                        } else {
3355
0
                            rc_decrement(pcs, "setup_DefautSpaces");
3356
0
                            if ((code = pdfi_set_warning_stop(ctx, gs_note_error(gs_error_syntaxerror), NULL, W_PDF_INVALID_DEFAULTSPACE, "pdfi_setup_DefaultSpaces", NULL)) < 0)
3357
0
                                return code;
3358
0
                        }
3359
0
                    }
3360
0
                } else {
3361
0
                    if ((code = pdfi_set_warning_stop(ctx, gs_note_error(gs_error_syntaxerror), NULL, W_PDF_INVALID_DEFAULTSPACE, "pdfi_setup_DefaultSpaces", NULL)) < 0)
3362
0
                        return code;
3363
0
                }
3364
0
            }
3365
54.7k
            pdfi_countdown(DefaultSpace);
3366
54.7k
            DefaultSpace = NULL;
3367
54.7k
            code = pdfi_dict_knownget(ctx, colorspaces_dict, "DefaultRGB", &DefaultSpace);
3368
54.7k
            if (code > 0) {
3369
1.04k
                gs_color_space *pcs;
3370
3371
1.04k
                code = Check_Default_Space(ctx, DefaultSpace, source_dict, 1);
3372
1.04k
                if (code >= 0) {
3373
1.01k
                    code = pdfi_create_colorspace(ctx, DefaultSpace, NULL, source_dict, &pcs, false);
3374
                    /* If any given Default* space fails simply ignore it, we wil then use the Device
3375
                     * space instead, this is as per the spec.
3376
                     */
3377
1.01k
                    if (code >= 0) {
3378
899
                        if (gs_color_space_num_components(pcs) == 3) {
3379
899
                            ctx->page.DefaultRGB_cs = pcs;
3380
899
                            pdfi_set_colour_callback(pcs, ctx, NULL);
3381
899
                        } else {
3382
0
                            rc_decrement(pcs, "setup_DefautSpaces");
3383
0
                            if ((code = pdfi_set_warning_stop(ctx, gs_note_error(gs_error_syntaxerror), NULL, W_PDF_INVALID_DEFAULTSPACE, "pdfi_setup_DefaultSpaces", NULL)) < 0)
3384
0
                                return code;
3385
0
                        }
3386
899
                    }
3387
1.01k
                } else {
3388
35
                    if ((code = pdfi_set_warning_stop(ctx, gs_note_error(gs_error_syntaxerror), NULL, W_PDF_INVALID_DEFAULTSPACE, "pdfi_setup_DefaultSpaces", NULL)) < 0)
3389
0
                        return code;
3390
35
                }
3391
1.04k
            }
3392
54.7k
            pdfi_countdown(DefaultSpace);
3393
54.7k
            DefaultSpace = NULL;
3394
54.7k
            code = pdfi_dict_knownget(ctx, colorspaces_dict, "DefaultCMYK", &DefaultSpace);
3395
54.7k
            if (code > 0) {
3396
40
                gs_color_space *pcs;
3397
3398
40
                code = Check_Default_Space(ctx, DefaultSpace, source_dict, 1);
3399
40
                if (code >= 0) {
3400
40
                    code = pdfi_create_colorspace(ctx, DefaultSpace, NULL, source_dict, &pcs, false);
3401
                    /* If any given Default* space fails simply ignore it, we wil then use the Device
3402
                     * space instead, this is as per the spec.
3403
                     */
3404
40
                    if (code >= 0) {
3405
38
                        if (gs_color_space_num_components(pcs) == 4) {
3406
38
                            ctx->page.DefaultCMYK_cs = pcs;
3407
38
                            pdfi_set_colour_callback(pcs, ctx, NULL);
3408
38
                        } else {
3409
0
                            rc_decrement(pcs, "setup_DefautSpaces");
3410
0
                            if ((code = pdfi_set_warning_stop(ctx, gs_note_error(gs_error_syntaxerror), NULL, W_PDF_INVALID_DEFAULTSPACE, "pdfi_setup_DefaultSpaces", NULL)) < 0)
3411
0
                                return code;
3412
0
                        }
3413
38
                    }
3414
40
                } else {
3415
0
                    if ((code = pdfi_set_warning_stop(ctx, gs_note_error(gs_error_syntaxerror), NULL, W_PDF_INVALID_DEFAULTSPACE, "pdfi_setup_DefaultSpaces", NULL)) < 0)
3416
0
                        return code;
3417
0
                }
3418
40
            }
3419
54.7k
            pdfi_countdown(DefaultSpace);
3420
54.7k
            DefaultSpace = NULL;
3421
54.7k
        }
3422
482k
    }
3423
3424
582k
    pdfi_countdown(DefaultSpace);
3425
582k
    pdfi_countdown(resources_dict);
3426
582k
    pdfi_countdown(colorspaces_dict);
3427
582k
    return 0;
3428
582k
}