Coverage Report

Created: 2025-06-10 07:27

/src/ghostpdl/pdf/pdf_colour.c
Line
Count
Source (jump to first uncovered line)
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
21.4k
{
64
21.4k
    pdf_obj *ref_space;
65
21.4k
    int code;
66
67
21.4k
    if (pdfi_name_is(name, "G")) {
68
0
        return 0;
69
21.4k
    } else if (pdfi_name_is(name, "RGB")) {
70
0
        return 0;
71
21.4k
    } else if (pdfi_name_is(name, "CMYK")) {
72
0
        return 0;
73
21.4k
    } else if (pdfi_name_is(name, "DeviceRGB")) {
74
17.2k
        return 0;
75
17.2k
    } else if (pdfi_name_is(name, "DeviceGray")) {
76
1.44k
        return 0;
77
2.81k
    } else if (pdfi_name_is(name, "DeviceCMYK")) {
78
2.49k
        return 0;
79
2.49k
    } else if (pdfi_name_is(name, "Pattern")) {
80
        /* TODO: I think this is fine... */
81
256
        return 0;
82
256
    } else {
83
66
        code = pdfi_find_resource(ctx, (unsigned char *)"ColorSpace", name, parent_dict, page_dict, &ref_space);
84
66
        if (code < 0)
85
62
            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
21.4k
}
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
19.5k
{
103
19.5k
    pdf_name *space = NULL;
104
19.5k
    pdf_array *a = NULL;
105
19.5k
    int code = 0;
106
107
19.5k
    if (!spot_dict)
108
0
        return 0;
109
110
19.5k
    code = pdfi_array_get_type(ctx, color_array, 0, PDF_NAME, (pdf_obj **)&space);
111
19.5k
    if (code != 0)
112
12
        goto exit;
113
114
19.5k
    code = 0;
115
19.5k
    if (pdfi_name_is(space, "G")) {
116
0
        goto exit;
117
19.5k
    } else if (pdfi_name_is(space, "I") || pdfi_name_is(space, "Indexed")) {
118
3.13k
        pdf_obj *base_space;
119
120
3.13k
        code = pdfi_array_get(ctx, color_array, 1, &base_space);
121
3.13k
        if (code == 0) {
122
3.08k
            code = pdfi_check_ColorSpace_for_spots(ctx, base_space, parent_dict, page_dict, spot_dict);
123
3.08k
            (void)pdfi_countdown(base_space);
124
3.08k
        }
125
3.13k
        goto exit;
126
16.3k
    } else if (pdfi_name_is(space, "Pattern")) {
127
429
        pdf_obj *base_space = NULL;
128
429
        uint64_t size = pdfi_array_size(color_array);
129
130
        /* Array of size 1 "[ /Pattern ]" is okay, just do nothing. */
131
429
        if (size == 1)
132
291
            goto exit;
133
        /* Array of size > 2 we don't handle (shouldn't happen?) */
134
138
        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
138
        code = pdfi_array_get(ctx, color_array, 1, &base_space);
142
138
        if (code == 0) {
143
138
            code = pdfi_check_ColorSpace_for_spots(ctx, base_space, parent_dict, page_dict, spot_dict);
144
138
            (void)pdfi_countdown(base_space);
145
138
        }
146
138
        goto exit;
147
15.9k
    } else if (pdfi_name_is(space, "Lab")) {
148
116
        goto exit;
149
15.8k
    } else if (pdfi_name_is(space, "RGB")) {
150
0
        goto exit;
151
15.8k
    } else if (pdfi_name_is(space, "CMYK")) {
152
0
        goto exit;
153
15.8k
    } else if (pdfi_name_is(space, "CalRGB")) {
154
430
        goto exit;
155
15.4k
    } else if (pdfi_name_is(space, "CalGray")) {
156
38
        goto exit;
157
15.3k
    } else if (pdfi_name_is(space, "CalCMYK")) {
158
0
        goto exit;
159
15.3k
    } else if (pdfi_name_is(space, "ICCBased")) {
160
11.8k
        goto exit;
161
11.8k
    } else if (pdfi_name_is(space, "DeviceRGB")) {
162
0
        goto exit;
163
3.55k
    } else if (pdfi_name_is(space, "DeviceGray")) {
164
0
        goto exit;
165
3.55k
    } else if (pdfi_name_is(space, "DeviceCMYK")) {
166
0
        goto exit;
167
3.55k
    } else if (pdfi_name_is(space, "DeviceN")) {
168
1.56k
        bool known = false;
169
1.56k
        pdf_obj *dummy, *name;
170
1.56k
        int i;
171
172
1.56k
        pdfi_countdown(space);
173
1.56k
        code = pdfi_array_get_type(ctx, color_array, 1, PDF_ARRAY, (pdf_obj **)&space);
174
1.56k
        if (code != 0)
175
0
            goto exit;
176
177
3.94k
        for (i=0;i < pdfi_array_size((pdf_array *)space); i++) {
178
2.37k
            code = pdfi_array_get_type(ctx, (pdf_array *)space, (uint64_t)i, PDF_NAME, &name);
179
2.37k
            if (code < 0)
180
0
                goto exit;
181
182
2.37k
            if (pdfi_name_is((const pdf_name *)name, "Cyan") || pdfi_name_is((const pdf_name *)name, "Magenta") ||
183
2.37k
                pdfi_name_is((const pdf_name *)name, "Yellow") || pdfi_name_is((const pdf_name *)name, "Black") ||
184
2.37k
                pdfi_name_is((const pdf_name *)name, "None") || pdfi_name_is((const pdf_name *)name, "All")) {
185
186
2.10k
                pdfi_countdown(name);
187
2.10k
                continue;
188
2.10k
            }
189
190
278
            code = pdfi_dict_known_by_key(ctx, spot_dict, (pdf_name *)name, &known);
191
278
            if (code < 0) {
192
0
                pdfi_countdown(name);
193
0
                goto exit;
194
0
            }
195
278
            if (known) {
196
30
                pdfi_countdown(name);
197
30
                continue;
198
30
            }
199
200
248
            code = pdfi_object_alloc(ctx, PDF_INT, 0, &dummy);
201
248
            if (code < 0)
202
0
                goto exit;
203
204
248
            code = pdfi_dict_put_obj(ctx, spot_dict, name, dummy, true);
205
248
            pdfi_countdown(name);
206
248
            if (code < 0)
207
0
                break;
208
248
        }
209
1.56k
        goto exit;
210
1.98k
    } else if (pdfi_name_is(space, "Separation")) {
211
1.95k
        bool known = false;
212
1.95k
        pdf_obj *dummy;
213
214
1.95k
        pdfi_countdown(space);
215
1.95k
        code = pdfi_array_get_type(ctx, color_array, 1, PDF_NAME, (pdf_obj **)&space);
216
1.95k
        if (code != 0)
217
0
            goto exit;
218
219
1.95k
        if (pdfi_name_is((const pdf_name *)space, "Cyan") || pdfi_name_is((const pdf_name *)space, "Magenta") ||
220
1.95k
            pdfi_name_is((const pdf_name *)space, "Yellow") || pdfi_name_is((const pdf_name *)space, "Black") ||
221
1.95k
            pdfi_name_is((const pdf_name *)space, "None") || pdfi_name_is((const pdf_name *)space, "All"))
222
1.55k
            goto exit;
223
398
        code = pdfi_dict_known_by_key(ctx, spot_dict, space, &known);
224
398
        if (code < 0 || known)
225
98
            goto exit;
226
227
300
        code = pdfi_object_alloc(ctx, PDF_INT, 0, &dummy);
228
300
        if (code < 0)
229
0
            goto exit;
230
231
300
        code = pdfi_dict_put_obj(ctx, spot_dict, (pdf_obj *)space, dummy, true);
232
300
        goto exit;
233
300
    } else {
234
28
        code = pdfi_find_resource(ctx, (unsigned char *)"ColorSpace",
235
28
                                  space, parent_dict, page_dict, (pdf_obj **)&a);
236
28
        if (code < 0)
237
28
            goto exit;
238
239
0
        if (pdfi_type_of(a) != PDF_ARRAY) {
240
0
            code = gs_note_error(gs_error_typecheck);
241
0
            goto exit;
242
0
        }
243
0
        if (a == color_array) {
244
0
            code = gs_note_error(gs_error_circular_reference);
245
0
            goto exit;
246
0
        }
247
248
        /* recursion */
249
0
        code = pdfi_check_for_spots_by_array(ctx, a, parent_dict, page_dict, spot_dict);
250
0
    }
251
252
19.5k
 exit:
253
19.5k
    if (space)
254
19.5k
        pdfi_countdown(space);
255
19.5k
    if (a)
256
0
        pdfi_countdown(a);
257
19.5k
    return code;
258
19.5k
}
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
41.2k
{
263
41.2k
    int code;
264
265
41.2k
    if (!spot_dict)
266
0
        return 0;
267
268
41.2k
    code = pdfi_loop_detector_mark(ctx);
269
41.2k
    if (code < 0)
270
0
        return code;
271
272
41.2k
    switch(pdfi_type_of(space)) {
273
21.4k
        case PDF_NAME:
274
21.4k
            code = pdfi_check_for_spots_by_name(ctx, (pdf_name *)space, parent_dict, page_dict, spot_dict);
275
21.4k
            break;
276
19.5k
        case PDF_ARRAY:
277
19.5k
            code = pdfi_check_for_spots_by_array(ctx, (pdf_array *)space, parent_dict, page_dict, spot_dict);
278
19.5k
            break;
279
252
        default:
280
252
            pdfi_loop_detector_cleartomark(ctx);
281
252
            return 0;
282
41.2k
    }
283
284
41.0k
    (void)pdfi_loop_detector_cleartomark(ctx);
285
41.0k
    return code;
286
41.2k
}
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
159k
{
293
159k
    pdf_name *n;
294
159k
    int code;
295
296
159k
    if (pdfi_count_stack(ctx) < 1)
297
20.2k
        return_error(gs_error_stackunderflow);
298
299
139k
    if (pdfi_type_of(ctx->stack_top[-1]) != PDF_NAME) {
300
2.58k
        pdfi_pop(ctx, 1);
301
2.58k
        return_error(gs_error_typecheck);
302
2.58k
    }
303
136k
    n = (pdf_name *)ctx->stack_top[-1];
304
136k
    pdfi_countup(n);
305
136k
    pdfi_pop(ctx, 1);
306
136k
    code = pdfi_setrenderingintent(ctx, n);
307
136k
    pdfi_countdown(n);
308
136k
    return code;
309
139k
}
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
1.81M
{
326
1.81M
    gs_color_space *pcs = (gs_color_space *)cs;
327
1.81M
    pdf_obj *o = (pdf_obj *)pcs->interpreter_data;
328
1.81M
    pdf_context *ctx = NULL;
329
1.81M
    gs_function_t *pfn;
330
331
1.81M
    if (o == NULL)
332
66
        return;
333
334
1.81M
    ctx = o->ctx;
335
336
1.81M
    if (gs_color_space_get_index(pcs) == gs_color_space_index_Separation) {
337
        /* Handle cleanup of Separation functions if applicable */
338
51.2k
        pfn = gs_cspace_get_sepr_function(pcs);
339
51.2k
        if (pfn)
340
51.2k
            pdfi_free_function(ctx, pfn);
341
51.2k
    }
342
343
1.81M
    if (gs_color_space_get_index(pcs) == gs_color_space_index_DeviceN) {
344
        /* Handle cleanup of DeviceN functions if applicable */
345
18.9k
        pfn = gs_cspace_get_devn_function(pcs);
346
18.9k
        if (pfn)
347
18.9k
            pdfi_free_function(ctx, pfn);
348
18.9k
    }
349
1.81M
    if (pdfi_type_of(o) != PDF_CTX) {
350
62.1k
        pdfi_countdown(o);
351
62.1k
        pcs->interpreter_data = NULL;
352
62.1k
    }
353
1.81M
}
354
355
int pdfi_gs_setgray(pdf_context *ctx, double d)
356
1.48M
{
357
1.48M
    int code = 0;
358
1.48M
    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
1.48M
    if (ctx->text.inside_CharProc && ctx->text.CharProc_d_type != pdf_type3_d0) {
362
11.9k
        pdfi_log_info(ctx, "pdfi_gs_setgray", "colour operator in a CharProc, following a d1 ignored\n");
363
11.9k
        return 0;
364
11.9k
    }
365
366
1.46M
    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.46M
    } else {
381
1.46M
        code = gs_setgray(ctx->pgs, d);
382
1.46M
        if (code < 0)
383
12
            return code;
384
1.46M
    }
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.46M
    if (pcs != ctx->pgs->color[0].color_space)
389
712k
        pdfi_set_colour_callback(ctx->pgs->color[0].color_space, ctx, pdfi_cspace_free_callback);
390
1.46M
    return 0;
391
1.46M
}
392
393
int pdfi_gs_setrgbcolor(pdf_context *ctx, double r, double g, double b)
394
2.24M
{
395
2.24M
    int code = 0;
396
2.24M
    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
2.24M
    if (ctx->text.inside_CharProc && ctx->text.CharProc_d_type != pdf_type3_d0) {
400
380
        pdfi_log_info(ctx, "pdfi_gs_setrgbcolor", "colour operator in a CharProc, following a d1 ignored\n");
401
380
        return 0;
402
380
    }
403
404
2.24M
    if (ctx->page.DefaultRGB_cs != NULL) {
405
12.3k
        gs_client_color cc;
406
407
12.3k
        code = gs_setcolorspace(ctx->pgs, ctx->page.DefaultRGB_cs);
408
12.3k
        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
12.3k
        if (pcs != ctx->pgs->color[0].color_space)
414
4.48k
            pdfi_set_colour_callback(ctx->pgs->color[0].color_space, ctx, pdfi_cspace_free_callback);
415
12.3k
        cc.paint.values[0] = r;
416
12.3k
        cc.paint.values[1] = g;
417
12.3k
        cc.paint.values[2] = b;
418
12.3k
        cc.pattern = 0;
419
12.3k
        return gs_setcolor(ctx->pgs, &cc);
420
2.23M
    } else {
421
2.23M
        code = gs_setrgbcolor(ctx->pgs, r, g, b);
422
2.23M
        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
2.23M
        if (pcs != ctx->pgs->color[0].color_space)
428
640k
            pdfi_set_colour_callback(ctx->pgs->color[0].color_space, ctx, pdfi_cspace_free_callback);
429
2.23M
    }
430
2.23M
    return 0;
431
2.24M
}
432
433
static int pdfi_gs_setcmykcolor(pdf_context *ctx, double c, double m, double y, double k)
434
182k
{
435
182k
    int code = 0;
436
182k
    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
182k
    if (ctx->text.inside_CharProc && ctx->text.CharProc_d_type != pdf_type3_d0) {
440
40
        pdfi_log_info(ctx, "pdfi_gs_setcmykcolor", "colour operator in a CharProc, following a d1 ignored\n");
441
40
        return 0;
442
40
    }
443
444
182k
    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
182k
    } else {
462
182k
        code = gs_setcmykcolor(ctx->pgs, c, m, y, k);
463
182k
        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
182k
        if (pcs != ctx->pgs->color[0].color_space)
469
101k
            pdfi_set_colour_callback(ctx->pgs->color[0].color_space, ctx, pdfi_cspace_free_callback);
470
182k
    }
471
182k
    return 0;
472
182k
}
473
474
int pdfi_gs_setcolorspace(pdf_context *ctx, gs_color_space *pcs)
475
433k
{
476
433k
    gs_color_space *old_pcs = ctx->pgs->color[0].color_space;
477
433k
    int code = 0;
478
    /* If the target colour space is already the current colour space, don't
479
     * bother to do anything.
480
     */
481
433k
    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
406k
        if (ctx->text.inside_CharProc && ctx->text.CharProc_d_type != pdf_type3_d0) {
484
2
            pdfi_log_info(ctx, "pdfi_gs_setcolorspace", "colour operator in a CharProc, following a d1 ignored\n");
485
2
            return 0;
486
2
        }
487
488
406k
        code = gs_setcolorspace(ctx->pgs, pcs);
489
406k
        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
406k
        if (old_pcs != ctx->pgs->color[0].color_space)
495
406k
            pdfi_set_colour_callback(ctx->pgs->color[0].color_space, ctx, pdfi_cspace_free_callback);
496
406k
    }
497
433k
    return 0;
498
433k
}
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
642k
{
503
642k
    int code;
504
642k
    double d1;
505
506
642k
    code = pdfi_destack_real(ctx, &d1);
507
642k
    if (code < 0)
508
24.5k
        return code;
509
510
618k
    gs_swapcolors_quick(ctx->pgs);
511
618k
    code = pdfi_gs_setgray(ctx, d1);
512
618k
    gs_swapcolors_quick(ctx->pgs);
513
514
618k
    return code;
515
642k
}
516
517
int pdfi_setgrayfill(pdf_context *ctx)
518
848k
{
519
848k
    int code;
520
848k
    double d1;
521
522
848k
    code = pdfi_destack_real(ctx, &d1);
523
848k
    if (code < 0)
524
12.1k
        return code;
525
526
836k
    return pdfi_gs_setgray(ctx, d1);
527
848k
}
528
529
int pdfi_setrgbstroke(pdf_context *ctx)
530
940k
{
531
940k
    double Values[3];
532
940k
    int code;
533
534
940k
    code = pdfi_destack_reals(ctx, Values, 3);
535
940k
    if (code < 0)
536
46.4k
        return code;
537
538
893k
    gs_swapcolors_quick(ctx->pgs);
539
893k
    code = pdfi_gs_setrgbcolor(ctx, Values[0], Values[1], Values[2]);
540
893k
    gs_swapcolors_quick(ctx->pgs);
541
542
893k
    return code;
543
940k
}
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
50.3k
{
550
50.3k
    int code;
551
50.3k
    pdf_array *array = NULL;
552
553
50.3k
    pdfi_set_warning(ctx, 0, NULL, W_PDF_NONSTANDARD_OP, "pdfi_setrgbfill_array", (char *)"WARNING: Non-standard 'r' operator");
554
555
50.3k
    if (pdfi_count_stack(ctx) < 1)
556
11.6k
        return_error(gs_error_stackunderflow);
557
558
38.6k
    array = (pdf_array *)ctx->stack_top[-1];
559
38.6k
    pdfi_countup(array);
560
38.6k
    pdfi_pop(ctx, 1);
561
38.6k
    if (pdfi_type_of(array) != PDF_ARRAY) {
562
38.6k
        code = gs_note_error(gs_error_typecheck);
563
38.6k
        goto exit;
564
38.6k
    }
565
566
51
    code = pdfi_setcolor_from_array(ctx, array);
567
38.6k
 exit:
568
38.6k
    pdfi_countdown(array);
569
38.6k
    return code;
570
51
}
571
572
int pdfi_setrgbfill(pdf_context *ctx)
573
1.33M
{
574
1.33M
    double Values[3];
575
1.33M
    int code;
576
577
1.33M
    code = pdfi_destack_reals(ctx, Values, 3);
578
1.33M
    if (code < 0)
579
34.2k
        return code;
580
581
1.30M
    return pdfi_gs_setrgbcolor(ctx, Values[0], Values[1], Values[2]);
582
1.33M
}
583
584
int pdfi_setcmykstroke(pdf_context *ctx)
585
42.3k
{
586
42.3k
    double Values[4];
587
42.3k
    int code;
588
589
42.3k
    code = pdfi_destack_reals(ctx, Values, 4);
590
42.3k
    if (code < 0)
591
7.75k
        return code;
592
593
34.5k
    gs_swapcolors_quick(ctx->pgs);
594
34.5k
    code = pdfi_gs_setcmykcolor(ctx, Values[0], Values[1], Values[2], Values[3]);
595
34.5k
    gs_swapcolors_quick(ctx->pgs);
596
597
34.5k
    return code;
598
42.3k
}
599
600
int pdfi_setcmykfill(pdf_context *ctx)
601
134k
{
602
134k
    double Values[4];
603
134k
    int code;
604
605
134k
    code = pdfi_destack_reals(ctx, Values, 4);
606
134k
    if (code < 0)
607
7.15k
        return code;
608
609
127k
    return pdfi_gs_setcmykcolor(ctx, Values[0], Values[1], Values[2], Values[3]);
610
134k
}
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
6.23k
{
618
6.23k
    int code = 0;
619
6.23k
    uint64_t size;
620
6.23k
    double values[4];
621
622
6.23k
    size = pdfi_array_size(array);
623
6.23k
    if (size != 1 && size != 3 && size != 4) {
624
51
        code = gs_note_error(gs_error_rangecheck);
625
51
        goto exit;
626
51
    }
627
628
6.18k
    code = pdfi_array_to_num_array(ctx, array, values, 0, size);
629
6.18k
    if (code < 0) goto exit;
630
631
6.14k
    switch (size) {
632
165
    case 1:
633
165
        code = pdfi_gs_setgray(ctx, values[0]);
634
165
        break;
635
5.97k
    case 3:
636
5.97k
        code = pdfi_gs_setrgbcolor(ctx, values[0], values[1], values[2]);
637
5.97k
        break;
638
10
    case 4:
639
10
        code = pdfi_gs_setcmykcolor(ctx, values[0], values[1], values[2], values[3]);
640
10
        break;
641
0
    default:
642
0
        break;
643
6.14k
    }
644
645
6.23k
 exit:
646
6.23k
    return code;
647
6.14k
}
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
423k
{
653
423k
    int i, code;
654
655
423k
    if (pdfi_count_stack(ctx) < ncomps) {
656
15.9k
        pdfi_clearstack(ctx);
657
15.9k
        return_error(gs_error_stackunderflow);
658
15.9k
    }
659
660
1.31M
    for (i = 0; i < ncomps; i++) {
661
922k
        code = pdfi_obj_to_float(ctx, ctx->stack_top[i - ncomps], &cc->paint.values[i]);
662
922k
        if (code < 0) {
663
11.5k
            pdfi_clearstack(ctx);
664
11.5k
            return code;
665
11.5k
        }
666
922k
    }
667
395k
    pdfi_pop(ctx, ncomps);
668
669
395k
    return 0;
670
407k
}
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
78.8k
{
682
78.8k
    const gs_color_space *  pcs;
683
78.8k
    int ncomps, code;
684
78.8k
    gs_client_color cc;
685
686
78.8k
    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
78.8k
    cc.pattern = 0;
697
78.8k
    gs_swapcolors_quick(ctx->pgs);
698
78.8k
    pcs = gs_currentcolorspace(ctx->pgs);
699
78.8k
    ncomps = cs_num_components(pcs);
700
78.8k
    if (ncomps < 1) {
701
2
        gs_swapcolors_quick(ctx->pgs);
702
2
        return_error(gs_error_syntaxerror);
703
2
    }
704
78.8k
    code = pdfi_get_color_from_stack(ctx, &cc, ncomps);
705
78.8k
    if (code == 0) {
706
76.6k
        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
76.6k
        code = gs_setcolor(ctx->pgs, &cc);
721
76.6k
    }
722
78.8k
    gs_swapcolors_quick(ctx->pgs);
723
78.8k
    return code;
724
78.8k
}
725
726
int pdfi_setfillcolor(pdf_context *ctx)
727
242k
{
728
242k
    const gs_color_space *  pcs = gs_currentcolorspace(ctx->pgs);
729
242k
    int ncomps, code;
730
242k
    gs_client_color cc;
731
732
242k
    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
242k
    cc.pattern = 0;
743
242k
    ncomps = cs_num_components(pcs);
744
242k
    if (ncomps < 1)
745
167
        return_error(gs_error_syntaxerror);
746
241k
    code = pdfi_get_color_from_stack(ctx, &cc, ncomps);
747
241k
    if (code == 0) {
748
233k
        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
118
            int index = (int)floor(cc.paint.values[0]);
757
758
118
            if(cc.paint.values[0] - index > 0.49999)
759
0
                index++;
760
118
            cc.paint.values[0] = (float)index;
761
118
        }
762
233k
        code = gs_setcolor(ctx->pgs, &cc);
763
233k
    }
764
241k
    return code;
765
242k
}
766
767
static inline bool
768
pattern_instance_uses_base_space(const gs_pattern_instance_t * pinst)
769
249
{
770
249
    return pinst->type->procs.uses_base_space(
771
249
                   pinst->type->procs.get_pattern(pinst) );
772
249
}
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
172k
{
780
172k
    gs_color_space *pcs;
781
172k
    gs_color_space *base_space = NULL;
782
172k
    int ncomps=0, code = 0;
783
172k
    gs_client_color cc;
784
172k
    bool is_pattern = false;
785
786
172k
    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
1
        pdfi_clearstack(ctx);
792
1
        pdfi_log_info(ctx, "pdfi_setcolorN", "colour operator in a CharProc, following a d1 ignored\n");
793
1
        return 0;
794
1
    }
795
796
172k
    if (!is_fill) {
797
21.5k
        gs_swapcolors_quick(ctx->pgs);
798
21.5k
    }
799
172k
    pcs = gs_currentcolorspace(ctx->pgs);
800
801
172k
    if (pdfi_count_stack(ctx) < 1) {
802
1.93k
        code = gs_note_error(gs_error_stackunderflow);
803
1.93k
        goto cleanupExit1;
804
1.93k
    }
805
806
170k
    memset(&cc, 0x00, sizeof(gs_client_color));
807
808
170k
    if (pcs->type == &gs_color_space_type_Pattern)
809
67.8k
        is_pattern = true;
810
170k
    if (is_pattern) {
811
67.8k
        pdf_name *n = NULL;
812
813
67.8k
        if (pdfi_type_of(ctx->stack_top[-1]) != PDF_NAME) {
814
90
            pdfi_clearstack(ctx);
815
90
            code = gs_note_error(gs_error_typecheck);
816
90
            goto cleanupExit0;
817
90
        }
818
67.7k
        n = (pdf_name *)ctx->stack_top[-1];
819
67.7k
        pdfi_countup(n);
820
67.7k
        pdfi_pop(ctx, 1);
821
822
67.7k
        base_space = pcs->base_space;
823
67.7k
        code = pdfi_pattern_set(ctx, stream_dict, page_dict, n, &cc);
824
67.7k
        pdfi_countdown(n);
825
67.7k
        if (code < 0) {
826
            /* Ignore the pattern if we failed to set it */
827
36.6k
            code = pdfi_set_warning_stop(ctx, code, NULL, W_PDF_BADPATTERN, "pdfi_setcolorN", (char *)"PATTERN: Error setting pattern");
828
36.6k
            goto cleanupExit1;
829
36.6k
        }
830
31.1k
        if (base_space && pattern_instance_uses_base_space(cc.pattern))
831
235
            ncomps = cs_num_components(base_space);
832
30.8k
        else
833
30.8k
            ncomps = 0;
834
31.1k
    } else
835
102k
        ncomps = cs_num_components(pcs);
836
837
133k
    if (ncomps > 0) {
838
102k
        code = pdfi_get_color_from_stack(ctx, &cc, ncomps);
839
102k
        if (code < 0)
840
17.2k
            goto cleanupExit1;
841
102k
    }
842
843
116k
    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
116k
    code = gs_setcolor(ctx->pgs, &cc);
869
870
171k
cleanupExit1:
871
171k
    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
171k
        rc_decrement(cc.pattern, "pdfi_setcolorN");
877
878
172k
cleanupExit0:
879
172k
    if (!is_fill)
880
21.5k
        gs_swapcolors_quick(ctx->pgs);
881
172k
    return code;
882
171k
}
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
33.8k
{
891
33.8k
    int                     code, k;
892
33.8k
    gs_color_space *        pcs;
893
33.8k
    cmm_profile_t           *picc_profile = NULL;
894
33.8k
    int                     i, expected = 0;
895
896
33.8k
    static const char *const icc_std_profile_names[] = {
897
33.8k
            GSICC_STANDARD_PROFILES
898
33.8k
        };
899
33.8k
    static const char *const icc_std_profile_keys[] = {
900
33.8k
            GSICC_STANDARD_PROFILES_KEYS
901
33.8k
        };
902
903
33.8k
    if (ppcs!= NULL)
904
33.8k
        *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
33.8k
    code = gs_cspace_build_ICC(&pcs, NULL, (gs_gstate_memory(ctx->pgs))->stable_memory);
911
33.8k
    if (code < 0)
912
0
        return code;
913
914
33.8k
    if (Name != NULL){
915
        /* Compare this to the standard profile names */
916
9.01k
        for (k = 0; k < GSICC_NUMBER_STANDARD_PROFILES; k++) {
917
9.01k
            if ( strcmp( Name, icc_std_profile_keys[k] ) == 0 ) {
918
4.95k
                picc_profile = gsicc_get_profile_handle_file(icc_std_profile_names[k],
919
4.95k
                    strlen(icc_std_profile_names[k]), gs_gstate_memory(ctx->pgs));
920
4.95k
                break;
921
4.95k
            }
922
9.01k
        }
923
28.9k
    } else {
924
28.9k
        if (s == NULL)
925
0
            return_error(gs_error_undefined);
926
927
28.9k
        picc_profile = gsicc_profile_new(s, gs_gstate_memory(ctx->pgs), NULL, 0);
928
28.9k
        if (picc_profile == NULL) {
929
6.17k
            rc_decrement(pcs,"pdfi_create_icc");
930
6.17k
            return gs_throw(gs_error_VMerror, "pdfi_create_icc Creation of ICC profile failed");
931
6.17k
        }
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
22.7k
        picc_profile->profile_handle =
935
22.7k
            gsicc_get_profile_handle_buffer(picc_profile->buffer,
936
22.7k
                                            picc_profile->buffer_size,
937
22.7k
                                            gs_gstate_memory(ctx->pgs));
938
22.7k
    }
939
940
27.7k
    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
3.90k
        rc_decrement(picc_profile,"pdfi_create_icc");
944
3.90k
        rc_decrement(pcs,"pdfi_create_icc");
945
3.90k
        return -1;
946
3.90k
    }
947
23.8k
    code = gsicc_set_gscs_profile(pcs, picc_profile, gs_gstate_memory(ctx->pgs));
948
23.8k
    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
23.8k
    picc_profile->data_cs =
955
23.8k
        gscms_get_profile_data_space(picc_profile->profile_handle,
956
23.8k
            picc_profile->memory);
957
23.8k
    switch (picc_profile->data_cs) {
958
0
        case gsCIEXYZ:
959
0
        case gsCIELAB:
960
14.4k
        case gsRGB:
961
14.4k
            expected = 3;
962
14.4k
            break;
963
9.14k
        case gsGRAY:
964
9.14k
            expected = 1;
965
9.14k
            break;
966
19
        case gsCMYK:
967
19
            expected = 4;
968
19
            break;
969
183
        case gsNCHANNEL:
970
183
        case gsNAMED:            /* Silence warnings */
971
183
        case gsUNDEFINED:        /* Silence warnings */
972
183
            break;
973
23.8k
    }
974
23.8k
    if (expected == 0) {
975
183
        rc_decrement(picc_profile,"pdfi_create_icc");
976
183
        rc_decrement(pcs,"pdfi_create_icc");
977
183
        return_error(gs_error_rangecheck);
978
183
    }
979
    /* Return the number of components the ICC profile has */
980
23.6k
    *icc_N = expected;
981
23.6k
    if (expected != ncomps) {
982
13
        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
13
        ncomps = expected;
985
13
    }
986
987
23.6k
    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
23.6k
    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
23.6k
    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
23.6k
    } else {
1019
76.2k
        for (i = 0; i < ncomps; i++) {
1020
52.6k
            picc_profile->Range.ranges[i].rmin = range_buff[2 * i];
1021
52.6k
            picc_profile->Range.ranges[i].rmax = range_buff[2 * i + 1];
1022
52.6k
        }
1023
23.6k
    }
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
23.6k
    if (gs_currentoverrideicc(ctx->pgs) && picc_profile->data_cs != gsCIELAB) {
1027
        /* Free up the profile structure */
1028
166
        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
166
            case gsGRAY:
1033
166
                pcs->cmm_icc_profile_data = ctx->pgs->icc_manager->default_gray;
1034
166
                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
166
        }
1041
        /* Have one increment from the color space.  Having these tied
1042
           together is not really correct.  Need to fix that.  ToDo.  MJV */
1043
166
        rc_adjust(picc_profile, -2, "pdfi_create_icc");
1044
166
        rc_increment(pcs->cmm_icc_profile_data);
1045
166
    }
1046
    /* Add the color space to the profile cache */
1047
23.6k
    if (dictkey != 0) {
1048
18.5k
        code = gsicc_add_cs(ctx->pgs, pcs, dictkey);
1049
18.5k
        if (code < 0)
1050
0
            goto exit;
1051
18.5k
    }
1052
1053
23.6k
    if (ppcs!= NULL){
1054
23.6k
        *ppcs = pcs;
1055
23.6k
        pdfi_set_colour_callback(pcs, ctx, pdfi_cspace_free_callback);
1056
23.6k
    } else {
1057
0
        code = pdfi_gs_setcolorspace(ctx, pcs);
1058
0
        rc_decrement_only_cs(pcs, "pdfi_create_icc");
1059
0
    }
1060
1061
23.6k
exit:
1062
    /* The context has taken a reference to the colorspace. We no longer need
1063
     * ours, so drop it. */
1064
23.6k
    rc_decrement(picc_profile, "pdfi_create_icc");
1065
23.6k
    return code;
1066
23.6k
}
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
194k
{
1071
194k
    pdf_c_stream *profile_stream = NULL;
1072
194k
    byte *profile_buffer;
1073
194k
    int code, code1;
1074
194k
    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
194k
    if (!gs_currentoverrideicc(ctx->pgs)) {
1083
194k
        if (ICC_obj->object_num != 0) {
1084
194k
            gs_color_space *pcs = NULL;
1085
1086
194k
            pcs = gsicc_find_cs(ICC_obj->object_num, ctx->pgs);
1087
194k
            if (pcs != NULL) {
1088
165k
                if (ppcs!= NULL){
1089
165k
                    *ppcs = pcs;
1090
165k
                } else {
1091
0
                    code = pdfi_gs_setcolorspace(ctx, pcs);
1092
0
                    rc_decrement_only_cs(pcs, "pdfi_create_iccprofile");
1093
0
                }
1094
165k
                *icc_N = gs_color_space_num_components(pcs);
1095
                /* We're passing back a new reference, increment the count */
1096
165k
                rc_adjust_only(pcs, 1, "pdfi_create_iccprofile, return cached ICC profile");
1097
165k
                return 0;
1098
165k
            }
1099
29.0k
            dictkey = ICC_obj->object_num;
1100
29.0k
        }
1101
194k
    }
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
29.2k
    code = pdfi_open_memory_stream_from_filtered_stream(ctx, ICC_obj, &profile_buffer, &profile_stream, true);
1111
29.2k
    if (code < 0) {
1112
325
        return code;
1113
325
    }
1114
1115
    /* Now, finally, we can call the code to create and set the profile */
1116
28.9k
    code = pdfi_create_icc(ctx, cname, profile_stream->s, (int)N, icc_N, range, dictkey, ppcs);
1117
1118
28.9k
    code1 = pdfi_close_memory_stream(ctx, profile_buffer, profile_stream);
1119
1120
28.9k
    if (code == 0)
1121
18.6k
        code = code1;
1122
1123
28.9k
    return code;
1124
29.2k
}
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
208k
{
1401
208k
    pdf_stream *ICC_obj = NULL;
1402
208k
    pdf_dict *dict; /* Alias to avoid tons of casting */
1403
208k
    pdf_array *a;
1404
208k
    int64_t Length, N;
1405
208k
    pdf_obj *Name = NULL, *Alt = NULL;
1406
208k
    char *cname = NULL;
1407
208k
    int code;
1408
208k
    bool known = true;
1409
208k
    float range[8];
1410
208k
    int icc_N;
1411
208k
    gs_color_space *pcs = NULL;
1412
1413
208k
    code = pdfi_array_get_type(ctx, color_array, index + 1, PDF_STREAM, (pdf_obj **)&ICC_obj);
1414
208k
    if (code < 0)
1415
12.0k
        return code;
1416
196k
    code = pdfi_dict_from_obj(ctx, (pdf_obj *)ICC_obj, &dict);
1417
196k
    if (code < 0)
1418
0
        return code;
1419
1420
196k
    Length = pdfi_stream_length(ctx, ICC_obj);
1421
196k
    code = pdfi_dict_get_int(ctx, dict, "N", &N);
1422
196k
    if (code < 0)
1423
857
        goto done;
1424
195k
    if (N != 1 && N != 3 && N != 4) {
1425
1.42k
        code = gs_note_error(gs_error_rangecheck);
1426
1.42k
        goto done;
1427
1.42k
    }
1428
194k
    code = pdfi_dict_knownget(ctx, dict, "Name", &Name);
1429
194k
    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 + 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
194k
    if (code < 0)
1446
0
        goto done;
1447
1448
194k
    code = pdfi_dict_knownget_type(ctx, dict, "Range", PDF_ARRAY, (pdf_obj **)&a);
1449
194k
    if (code < 0)
1450
0
        goto done;
1451
194k
    if (code > 0) {
1452
151
        double dbl;
1453
151
        int i;
1454
1455
151
        if (pdfi_array_size(a) >= N * 2) {
1456
1.00k
            for (i = 0; i < N * 2;i++) {
1457
866
                code = pdfi_array_get_number(ctx, a, i, &dbl);
1458
866
                if (code < 0) {
1459
0
                    known = false;
1460
0
                    break;
1461
0
                }
1462
866
                range[i] = (float)dbl;
1463
866
            }
1464
138
        } else {
1465
13
            known = false;
1466
13
        }
1467
151
        pdfi_countdown(a);
1468
151
    } else
1469
194k
        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
194k
    if (!known) {
1477
194k
        int i;
1478
714k
        for (i = 0;i < N; i++) {
1479
519k
            range[i * 2] = 0;
1480
519k
            range[(i * 2) + 1] = 1;
1481
519k
        }
1482
194k
    }
1483
1484
194k
    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
194k
    if (code >= 0 && N != icc_N) {
1502
13
        gs_client_color cc;
1503
13
        int i;
1504
1505
13
        gs_gsave(ctx->pgs);
1506
13
        code = gs_setcolorspace(ctx->pgs, pcs);
1507
13
        if (code == 0) {
1508
13
            cc.pattern = 0;
1509
52
            for (i = 0;i < icc_N; i++)
1510
39
                cc.paint.values[i] = 0;
1511
13
            code = gs_setcolor(ctx->pgs, &cc);
1512
13
            if (code == 0)
1513
13
                code = gx_set_dev_color(ctx->pgs);
1514
13
        }
1515
13
        gs_grestore(ctx->pgs);
1516
13
    }
1517
1518
194k
    if (code < 0) {
1519
10.6k
        pdf_obj *Alternate = NULL;
1520
1521
10.6k
        if (pcs != NULL)
1522
10.6k
            rc_decrement(pcs,"pdfi_create_iccbased");
1523
1524
        /* Failed to set the ICCBased space, attempt to use the Alternate */
1525
10.6k
        code = pdfi_dict_knownget(ctx, dict, "Alternate", &Alternate);
1526
10.6k
        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
10.1k
            if (pdfi_type_of(Alternate) == PDF_NAME)
1529
10.1k
                code = pdfi_create_colorspace_by_name(ctx, (pdf_name *)Alternate, stream_dict,
1530
10.1k
                                                      page_dict, ppcs, inline_image);
1531
10.1k
            pdfi_countdown(Alternate);
1532
10.1k
            if (code == 0) {
1533
10.0k
                pdfi_set_warning(ctx, 0, NULL, W_PDF_BADICC_USE_ALT, "pdfi_create_iccbased", NULL);
1534
10.0k
                goto done;
1535
10.0k
            }
1536
10.1k
        }
1537
        /* Use the number of components *from the profile* to set a space.... */
1538
520
        pdfi_set_warning(ctx, 0, NULL, W_PDF_BADICC_USECOMPS, "pdfi_create_iccbased", NULL);
1539
520
        switch(N) {
1540
119
            case 1:
1541
119
                pcs = gs_cspace_new_DeviceGray(ctx->memory);
1542
119
                if (pcs == NULL)
1543
0
                    code = gs_note_error(gs_error_VMerror);
1544
119
                break;
1545
393
            case 3:
1546
393
                pcs = gs_cspace_new_DeviceRGB(ctx->memory);
1547
393
                if (pcs == NULL)
1548
0
                    code = gs_note_error(gs_error_VMerror);
1549
393
                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
520
        }
1559
183k
    } else {
1560
183k
        if (pcs->ICC_Alternate_space == gs_ICC_Alternate_None) {
1561
20.4k
            code = pdfi_dict_knownget(ctx, dict, "Alternate", (pdf_obj **)&Alt);
1562
20.4k
            if (code >= 0) {
1563
20.4k
                switch(pdfi_type_of(Alt)) {
1564
17.1k
                    case PDF_NAME:
1565
                        /* Simple named spaces must be Gray, RGB or CMYK, we ignore /Indexed */
1566
17.1k
                        if (pdfi_name_is((const pdf_name *)Alt, "DeviceGray"))
1567
4.83k
                            pcs->ICC_Alternate_space = gs_ICC_Alternate_DeviceGray;
1568
12.3k
                        else if (pdfi_name_is((const pdf_name *)Alt, "DeviceRGB"))
1569
12.2k
                            pcs->ICC_Alternate_space = gs_ICC_Alternate_DeviceRGB;
1570
124
                        else if (pdfi_name_is((const pdf_name *)Alt, "DeviceCMYK"))
1571
19
                            pcs->ICC_Alternate_space = gs_ICC_Alternate_DeviceCMYK;
1572
17.1k
                        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
3.30k
                    default:
1610
                        /* Probably an error, but just ignore it */
1611
3.30k
                        break;
1612
20.4k
                }
1613
20.4k
                pdfi_countdown(Alt);
1614
20.4k
                Alt = NULL;
1615
20.4k
            }
1616
20.4k
        }
1617
183k
    }
1618
1619
184k
    if (ppcs!= NULL) {
1620
49.2k
        *ppcs = pcs;
1621
49.2k
        if (pcs != NULL)
1622
49.2k
            pdfi_set_colour_callback(pcs, ctx, pdfi_cspace_free_callback);
1623
49.2k
    }
1624
135k
    else {
1625
135k
        if (pcs != NULL) {
1626
135k
            code = pdfi_gs_setcolorspace(ctx, pcs);
1627
            /* release reference from construction */
1628
135k
            rc_decrement_only_cs(pcs, "setseparationspace");
1629
135k
        }
1630
135k
    }
1631
1632
1633
196k
done:
1634
196k
    if (cname)
1635
0
        gs_free_object(ctx->memory, cname, "pdfi_create_iccbased (profile name)");
1636
196k
    pdfi_countdown(Alt);
1637
196k
    pdfi_countdown(Name);
1638
196k
    pdfi_countdown(ICC_obj);
1639
196k
    return code;
1640
184k
}
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
590
{
1650
590
    int                     code;
1651
590
    gs_color_space *        pcs;
1652
590
    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
590
    code = gs_cspace_build_ICC(&pcs, NULL, (gs_gstate_memory(ctx->pgs))->stable_memory);
1660
590
    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
590
    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
590
    code = gsicc_set_gscs_profile(pcs, ctx->pgs->icc_manager->lab_profile, gs_gstate_memory(ctx->pgs));
1674
590
    if (code < 0)
1675
0
        return code;
1676
1677
590
    pcs->cmm_icc_profile_data->Range.ranges[0].rmin = 0.0;
1678
590
    pcs->cmm_icc_profile_data->Range.ranges[0].rmax = 100.0;
1679
1.77k
    for (i = 1; i < 3; i++) {
1680
1.18k
        pcs->cmm_icc_profile_data->Range.ranges[i].rmin =
1681
1.18k
            range_buff[2 * (i-1)];
1682
1.18k
        pcs->cmm_icc_profile_data->Range.ranges[i].rmax =
1683
1.18k
            range_buff[2 * (i-1) + 1];
1684
1.18k
    }
1685
590
    if (ppcs!= NULL){
1686
200
        *ppcs = pcs;
1687
200
        pdfi_set_colour_callback(pcs, ctx, pdfi_cspace_free_callback);
1688
390
    } else {
1689
390
        code = pdfi_gs_setcolorspace(ctx, pcs);
1690
390
        rc_decrement_only_cs(pcs, "pdfi_seticc_lab");
1691
390
    }
1692
1693
590
    return code;
1694
590
}
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
611
{
1698
611
    int code = 0, i;
1699
611
    pdf_dict *Lab_dict = NULL;
1700
611
    pdf_array *Range = NULL;
1701
611
    float RangeBuf[4];
1702
611
    double f;
1703
611
    bool known = false;
1704
1705
611
    code = pdfi_array_get_type(ctx, color_array, index + 1, PDF_DICT, (pdf_obj **)&Lab_dict);
1706
611
    if (code < 0)
1707
14
        return code;
1708
1709
597
    code = pdfi_dict_known(ctx, Lab_dict, "Range", &known);
1710
597
    if (code < 0)
1711
0
        goto exit;
1712
597
    if (known) {
1713
579
        code = pdfi_dict_get_type(ctx, Lab_dict, "Range", PDF_ARRAY, (pdf_obj **)&Range);
1714
579
        if (code < 0) {
1715
0
            goto exit;
1716
0
        }
1717
579
        if (pdfi_array_size(Range) != 4){
1718
7
            code = gs_note_error(gs_error_rangecheck);
1719
7
            goto exit;
1720
7
        }
1721
1722
2.86k
        for (i=0; i < 4; i++) {
1723
2.28k
            code = pdfi_array_get_number(ctx, Range, (uint64_t)i, &f);
1724
2.28k
            if (code < 0)
1725
0
                goto exit;
1726
2.28k
            RangeBuf[i] = (float)f;
1727
2.28k
        }
1728
572
    } else {
1729
18
        RangeBuf[0] = RangeBuf[2] = -100.0;
1730
18
        RangeBuf[1] = RangeBuf[3] = 100.0;
1731
18
    }
1732
1733
590
    code = pdfi_seticc_lab(ctx, RangeBuf, ppcs);
1734
1735
597
exit:
1736
597
    pdfi_countdown(Lab_dict);
1737
597
    pdfi_countdown(Range);
1738
597
    return code;
1739
590
}
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
2.29k
{
1746
2.29k
    int                     code = 0;
1747
2.29k
    gs_color_space *        pcs;
1748
2.29k
    int                     i;
1749
2.29k
    cmm_profile_t           *cal_profile;
1750
1751
    /* See if the color space is in the profile cache */
1752
2.29k
    pcs = gsicc_find_cs(dictkey, ctx->pgs);
1753
2.29k
    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
2.26k
        code = gs_cspace_build_ICC(&pcs, NULL, ctx->pgs->memory->stable_memory);
1759
2.26k
        if (code < 0)
1760
0
            return code;
1761
        /* There is no alternate for this.  Perhaps we should set DeviceRGB? */
1762
2.26k
        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
2.26k
        cal_profile = gsicc_create_from_cal(white, black, gamma, matrix,
1766
2.26k
                                            ctx->pgs->memory->stable_memory, num_colorants);
1767
2.26k
        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
2.26k
        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
2.26k
        rc_decrement(cal_profile, "seticc_cal");
1780
2.26k
        if (code < 0) {
1781
0
            rc_decrement(pcs, "seticc_cal");
1782
0
            return code;
1783
0
        }
1784
8.74k
        for (i = 0; i < num_colorants; i++) {
1785
6.47k
            pcs->cmm_icc_profile_data->Range.ranges[i].rmin = 0;
1786
6.47k
            pcs->cmm_icc_profile_data->Range.ranges[i].rmax = 1;
1787
6.47k
        }
1788
        /* Add the color space to the profile cache */
1789
2.26k
        gsicc_add_cs(ctx->pgs, pcs, dictkey);
1790
2.26k
    } else {
1791
        /* We're passing back a new reference, increment the count */
1792
25
        rc_adjust_only(pcs, 1, "pdfi_seticc_cal, return cached ICC profile");
1793
25
    }
1794
1795
2.29k
    if (ppcs!= NULL){
1796
268
        *ppcs = pcs;
1797
268
        pdfi_set_colour_callback(pcs, ctx, pdfi_cspace_free_callback);
1798
2.02k
    } else {
1799
2.02k
        code = pdfi_gs_setcolorspace(ctx, pcs);
1800
2.02k
        rc_decrement_only_cs(pcs, "pdfi_seticc_cal");
1801
2.02k
    }
1802
1803
2.29k
    return code;
1804
2.29k
}
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
524
{
1808
524
    int code = 0, i;
1809
524
    pdf_dict *CalGray_dict = NULL;
1810
524
    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
524
    float WhitePoint[3], BlackPoint[3] = {0.0f, 0.0f, 0.0f}, Gamma = 1.0f;
1817
524
    float Matrix[9] = {1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f};
1818
524
    double f;
1819
1820
524
    code = pdfi_array_get_type(ctx, color_array, index + 1, PDF_DICT, (pdf_obj **)&CalGray_dict);
1821
524
    if (code < 0)
1822
135
        return code;
1823
1824
389
    code = pdfi_dict_get_type(ctx, CalGray_dict, "WhitePoint", PDF_ARRAY, (pdf_obj **)&PDFArray);
1825
389
    if (code < 0) {
1826
0
        pdfi_countdown(PDFArray);
1827
0
        goto exit;
1828
0
    }
1829
389
    if (pdfi_array_size(PDFArray) != 3){
1830
0
        code = gs_note_error(gs_error_rangecheck);
1831
0
        goto exit;
1832
0
    }
1833
1834
1.55k
    for (i=0; i < 3; i++) {
1835
1.16k
        code = pdfi_array_get_number(ctx, PDFArray, (uint64_t)i, &f);
1836
1.16k
        if (code < 0)
1837
0
            goto exit;
1838
1.16k
        WhitePoint[i] = (float)f;
1839
1.16k
    }
1840
389
    pdfi_countdown(PDFArray);
1841
389
    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
389
    if (WhitePoint[0] < 0 || WhitePoint[2] < 0 || WhitePoint[1] != 1.0f) {
1847
0
        code = gs_note_error(gs_error_rangecheck);
1848
0
        goto exit;
1849
0
    }
1850
1851
389
    if (pdfi_dict_knownget_type(ctx, CalGray_dict, "BlackPoint", PDF_ARRAY, (pdf_obj **)&PDFArray) > 0) {
1852
347
        if (pdfi_array_size(PDFArray) != 3){
1853
100
            code = gs_note_error(gs_error_rangecheck);
1854
100
            goto exit;
1855
100
        }
1856
868
        for (i=0; i < 3; i++) {
1857
741
            code = pdfi_array_get_number(ctx, PDFArray, (uint64_t)i, &f);
1858
741
            if (code < 0)
1859
120
                goto exit;
1860
            /* The PDF 1.7 reference states that all three components of the BlackPoint
1861
             * (if present) must be positive.
1862
             */
1863
621
            if (f < 0) {
1864
0
                code = gs_note_error(gs_error_rangecheck);
1865
0
                goto exit;
1866
0
            }
1867
621
            BlackPoint[i] = (float)f;
1868
621
        }
1869
127
        pdfi_countdown(PDFArray);
1870
127
        PDFArray = NULL;
1871
127
    }
1872
1873
169
    if (pdfi_dict_knownget_number(ctx, CalGray_dict, "Gamma", &f) > 0)
1874
169
        Gamma = (float)f;
1875
    /* The PDF 1.7 reference states that Gamma
1876
     * (if present) must be positive.
1877
     */
1878
169
    if (Gamma < 0) {
1879
0
        code = gs_note_error(gs_error_rangecheck);
1880
0
        goto exit;
1881
0
    }
1882
1883
169
    code = pdfi_seticc_cal(ctx, WhitePoint, BlackPoint, &Gamma, Matrix, 1, color_array->object_num, ppcs);
1884
1885
389
exit:
1886
389
    pdfi_countdown(PDFArray);
1887
389
    pdfi_countdown(CalGray_dict);
1888
389
    return code;
1889
169
}
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
2.24k
{
1893
2.24k
    int code = 0, i;
1894
2.24k
    pdf_dict *CalRGB_dict = NULL;
1895
2.24k
    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
2.24k
    float WhitePoint[3], BlackPoint[3] = {0.0f, 0.0f, 0.0f}, Gamma[3] = {1.0f, 1.0f, 1.0f};
1900
2.24k
    float Matrix[9] = {1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f};
1901
2.24k
    double f;
1902
1903
2.24k
    code = pdfi_array_get_type(ctx, color_array, index + 1, PDF_DICT, (pdf_obj **)&CalRGB_dict);
1904
2.24k
    if (code < 0)
1905
31
        return code;
1906
1907
2.21k
    code = pdfi_dict_get_type(ctx, CalRGB_dict, "WhitePoint", PDF_ARRAY, (pdf_obj **)&PDFArray);
1908
2.21k
    if (code < 0) {
1909
3
        pdfi_countdown(PDFArray);
1910
3
        goto exit;
1911
3
    }
1912
2.21k
    if (pdfi_array_size(PDFArray) != 3){
1913
1
        code = gs_note_error(gs_error_rangecheck);
1914
1
        goto exit;
1915
1
    }
1916
1917
8.84k
    for (i=0; i < 3; i++) {
1918
6.63k
        code = pdfi_array_get_number(ctx, PDFArray, (uint64_t)i, &f);
1919
6.63k
        if (code < 0)
1920
0
            goto exit;
1921
6.63k
        WhitePoint[i] = (float)f;
1922
6.63k
    }
1923
2.21k
    pdfi_countdown(PDFArray);
1924
2.21k
    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
2.21k
    if (WhitePoint[0] < 0 || WhitePoint[2] < 0 || WhitePoint[1] != 1.0f) {
1930
0
        code = gs_note_error(gs_error_rangecheck);
1931
0
        goto exit;
1932
0
    }
1933
1934
2.21k
    if (pdfi_dict_knownget_type(ctx, CalRGB_dict, "BlackPoint", PDF_ARRAY, (pdf_obj **)&PDFArray) > 0) {
1935
1.00k
        if (pdfi_array_size(PDFArray) != 3){
1936
0
            code = gs_note_error(gs_error_rangecheck);
1937
0
            goto exit;
1938
0
        }
1939
3.84k
        for (i=0; i < 3; i++) {
1940
2.92k
            code = pdfi_array_get_number(ctx, PDFArray, (uint64_t)i, &f);
1941
2.92k
            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
2.92k
            if (f < 0) {
1947
80
                code = gs_note_error(gs_error_rangecheck);
1948
80
                goto exit;
1949
80
            }
1950
2.84k
            BlackPoint[i] = (float)f;
1951
2.84k
        }
1952
920
        pdfi_countdown(PDFArray);
1953
920
        PDFArray = NULL;
1954
920
    }
1955
1956
2.13k
    if (pdfi_dict_knownget_type(ctx, CalRGB_dict, "Gamma", PDF_ARRAY, (pdf_obj **)&PDFArray) > 0) {
1957
2.12k
        if (pdfi_array_size(PDFArray) != 3){
1958
0
            code = gs_note_error(gs_error_rangecheck);
1959
0
            goto exit;
1960
0
        }
1961
8.48k
        for (i=0; i < 3; i++) {
1962
6.36k
            code = pdfi_array_get_number(ctx, PDFArray, (uint64_t)i, &f);
1963
6.36k
            if (code < 0)
1964
0
                goto exit;
1965
6.36k
            Gamma[i] = (float)f;
1966
6.36k
        }
1967
2.12k
        pdfi_countdown(PDFArray);
1968
2.12k
        PDFArray = NULL;
1969
2.12k
    }
1970
1971
2.13k
    if (pdfi_dict_knownget_type(ctx, CalRGB_dict, "Matrix", PDF_ARRAY, (pdf_obj **)&PDFArray) > 0) {
1972
2.13k
        if (pdfi_array_size(PDFArray) != 9){
1973
4
            code = gs_note_error(gs_error_rangecheck);
1974
4
            goto exit;
1975
4
        }
1976
21.2k
        for (i=0; i < 9; i++) {
1977
19.1k
            code = pdfi_array_get_number(ctx, PDFArray, (uint64_t)i, &f);
1978
19.1k
            if (code < 0)
1979
3
                goto exit;
1980
19.1k
            Matrix[i] = (float)f;
1981
19.1k
        }
1982
2.12k
        pdfi_countdown(PDFArray);
1983
2.12k
        PDFArray = NULL;
1984
2.12k
    }
1985
2.12k
    code = pdfi_seticc_cal(ctx, WhitePoint, BlackPoint, Gamma, Matrix, 3, color_array->object_num, ppcs);
1986
1987
2.21k
exit:
1988
2.21k
    pdfi_countdown(PDFArray);
1989
2.21k
    pdfi_countdown(CalRGB_dict);
1990
2.21k
    return code;
1991
2.12k
}
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
61.3k
{
1995
61.3k
    pdf_obj *o = NULL;
1996
61.3k
    pdf_name *name = NULL, *NamedAlternate = NULL;
1997
61.3k
    pdf_array *ArrayAlternate = NULL;
1998
61.3k
    pdf_obj *transform = NULL;
1999
61.3k
    int code;
2000
61.3k
    gs_color_space *pcs = NULL, *pcs_alt = NULL;
2001
61.3k
    gs_function_t * pfn = NULL;
2002
61.3k
    separation_type sep_type;
2003
2004
61.3k
    code = pdfi_array_get_type(ctx, color_array, index + 1, PDF_NAME, (pdf_obj **)&name);
2005
61.3k
    if (code < 0)
2006
0
        goto pdfi_separation_error;
2007
2008
61.3k
    sep_type = SEP_OTHER;
2009
61.3k
    if (name->length == 4 && memcmp(name->data, "None", 4) == 0)
2010
0
        sep_type = SEP_NONE;
2011
61.3k
    if (name->length == 3 && memcmp(name->data, "All", 3) == 0)
2012
0
        sep_type = SEP_ALL;
2013
2014
61.3k
    code = pdfi_array_get(ctx, color_array, index + 2, &o);
2015
61.3k
    if (code < 0)
2016
241
        goto pdfi_separation_error;
2017
2018
61.1k
    switch (pdfi_type_of(o)) {
2019
45.2k
        case PDF_NAME:
2020
45.2k
            NamedAlternate = (pdf_name *)o;
2021
45.2k
            code = pdfi_create_colorspace_by_name(ctx, NamedAlternate, stream_dict, page_dict, &pcs_alt, inline_image);
2022
45.2k
            if (code < 0)
2023
53
                goto pdfi_separation_error;
2024
45.2k
            break;
2025
45.2k
        case PDF_ARRAY:
2026
14.9k
            ArrayAlternate = (pdf_array *)o;
2027
14.9k
            code = pdfi_create_colorspace_by_array(ctx, ArrayAlternate, 0, stream_dict, page_dict, &pcs_alt, inline_image);
2028
14.9k
            if (code < 0)
2029
1.15k
                goto pdfi_separation_error;
2030
13.7k
            break;
2031
13.7k
        default:
2032
957
            pdfi_countdown(o);
2033
957
            code = gs_error_typecheck;
2034
957
            goto pdfi_separation_error;
2035
61.1k
    }
2036
2037
58.9k
    code = pdfi_array_get(ctx, color_array, index + 3, &transform);
2038
58.9k
    if (code < 0)
2039
1.09k
        goto pdfi_separation_error;
2040
2041
57.8k
    code = pdfi_build_function(ctx, &pfn, NULL, 1, transform, page_dict);
2042
57.8k
    if (code < 0)
2043
6.65k
        goto pdfi_separation_error;
2044
2045
51.2k
    if (pfn->params.m != 1 || pfn->params.n != cs_num_components(pcs_alt)) {
2046
16
        code = gs_note_error(gs_error_rangecheck);
2047
16
        goto pdfi_separation_error;
2048
16
    }
2049
2050
51.2k
    code = gs_cspace_new_Separation(&pcs, pcs_alt, ctx->memory);
2051
51.2k
    if (code < 0)
2052
0
        goto pdfi_separation_error;
2053
2054
51.2k
    rc_decrement(pcs_alt, "pdfi_create_Separation");
2055
51.2k
    pcs_alt = NULL;
2056
51.2k
    pcs->params.separation.mem = ctx->memory;
2057
51.2k
    pcs->params.separation.sep_type = sep_type;
2058
51.2k
    pcs->params.separation.sep_name = (char *)gs_alloc_bytes(ctx->memory->non_gc_memory, name->length + 1, "pdfi_setseparationspace(ink)");
2059
51.2k
    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
51.2k
    memcpy(pcs->params.separation.sep_name, name->data, name->length);
2064
51.2k
    pcs->params.separation.sep_name[name->length] = 0x00;
2065
2066
51.2k
    code = gs_cspace_set_sepr_function(pcs, pfn);
2067
51.2k
    if (code < 0)
2068
0
        goto pdfi_separation_error;
2069
2070
51.2k
    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
234
        code = pdfi_gs_setcolorspace(ctx, pcs);
2077
234
        *ppcs = pcs;
2078
234
        pdfi_set_colour_callback(pcs, ctx, pdfi_cspace_free_callback);
2079
50.9k
    } else {
2080
50.9k
        code = pdfi_gs_setcolorspace(ctx, pcs);
2081
        /* release reference from construction */
2082
50.9k
        rc_decrement_only_cs(pcs, "setseparationspace");
2083
50.9k
    }
2084
2085
51.2k
    pdfi_countdown(name);
2086
51.2k
    pdfi_countdown(NamedAlternate);
2087
51.2k
    pdfi_countdown(ArrayAlternate);
2088
51.2k
    pdfi_countdown(transform);
2089
51.2k
    return_error(0);
2090
2091
10.1k
pdfi_separation_error:
2092
10.1k
    pdfi_free_function(ctx, pfn);
2093
10.1k
    if (pcs_alt != NULL)
2094
7.76k
        rc_decrement_only_cs(pcs_alt, "setseparationspace");
2095
10.1k
    if(pcs != NULL)
2096
0
        rc_decrement_only_cs(pcs, "setseparationspace");
2097
10.1k
    pdfi_countdown(name);
2098
10.1k
    pdfi_countdown(NamedAlternate);
2099
10.1k
    pdfi_countdown(ArrayAlternate);
2100
10.1k
    pdfi_countdown(transform);
2101
10.1k
    return code;
2102
51.2k
}
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
21.6k
{
2106
21.6k
    pdf_obj *o = NULL;
2107
21.6k
    pdf_name *NamedAlternate = NULL;
2108
21.6k
    pdf_array *ArrayAlternate = NULL, *inks = NULL;
2109
21.6k
    pdf_obj *transform = NULL;
2110
21.6k
    pdf_dict *attributes = NULL;
2111
21.6k
    pdf_dict *Colorants = NULL, *Process = NULL;
2112
21.6k
    gs_color_space *process_space = NULL;
2113
21.6k
    int code;
2114
21.6k
    uint64_t ix;
2115
21.6k
    gs_color_space *pcs = NULL, *pcs_alt = NULL;
2116
21.6k
    gs_function_t * pfn = NULL;
2117
2118
    /* Start with the array of inks */
2119
21.6k
    code = pdfi_array_get_type(ctx, color_array, index + 1, PDF_ARRAY, (pdf_obj **)&inks);
2120
21.6k
    if (code < 0)
2121
4
        goto pdfi_devicen_error;
2122
2123
51.5k
    for (ix = 0;ix < pdfi_array_size(inks);ix++) {
2124
29.9k
        pdf_name *ink_name = NULL;
2125
2126
29.9k
        code = pdfi_array_get_type(ctx, inks, ix, PDF_NAME, (pdf_obj **)&ink_name);
2127
29.9k
        if (code < 0)
2128
0
            return code;
2129
2130
29.9k
        if (ink_name->length == 3 && memcmp(ink_name->data, "All", 3) == 0) {
2131
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)
2132
0
                return code;
2133
0
        }
2134
29.9k
        pdfi_countdown(ink_name);
2135
29.9k
        ink_name = NULL;
2136
29.9k
    }
2137
2138
    /* Sigh, Acrobat allows this, even though its contra the spec. Convert to
2139
     * a /Separation space, and then return. Actually Acrobat does not always permit this, see
2140
     * tests_private/comparefiles/Testform.v1.0.2.pdf.
2141
     */
2142
21.6k
    if (pdfi_array_size(inks) == 1) {
2143
17.4k
        pdf_name *ink_name = NULL;
2144
17.4k
        pdf_array *sep_color_array = NULL;
2145
17.4k
        pdf_obj *obj = NULL;
2146
2147
17.4k
        code = pdfi_array_get_type(ctx, inks, 0, PDF_NAME, (pdf_obj **)&ink_name);
2148
17.4k
        if (code < 0)
2149
0
            goto pdfi_devicen_error;
2150
2151
17.4k
        if (ink_name->length == 3 && memcmp(ink_name->data, "All", 3) == 0) {
2152
0
            code = pdfi_array_alloc(ctx, 4, &sep_color_array);
2153
0
            if (code < 0)
2154
0
                goto all_error;
2155
0
            pdfi_countup(sep_color_array);
2156
0
            code = pdfi_name_alloc(ctx, (byte *)"Separation", 10, &obj);
2157
0
            if (code < 0)
2158
0
                goto all_error;
2159
0
            pdfi_countup(obj);
2160
0
            code = pdfi_array_put(ctx, sep_color_array, 0, obj);
2161
0
            if (code < 0)
2162
0
                goto all_error;
2163
0
            pdfi_countdown(obj);
2164
0
            obj = NULL;
2165
0
            code = pdfi_array_put(ctx, sep_color_array, 1, (pdf_obj *)ink_name);
2166
0
            if (code < 0)
2167
0
                goto all_error;
2168
0
            code = pdfi_array_get(ctx, color_array, index + 2, &obj);
2169
0
            if (code < 0)
2170
0
                goto all_error;
2171
0
            code = pdfi_array_put(ctx, sep_color_array, 2, obj);
2172
0
            if (code < 0)
2173
0
                goto all_error;
2174
0
            pdfi_countdown(obj);
2175
0
            obj = NULL;
2176
0
            code = pdfi_array_get(ctx, color_array, index + 3, &obj);
2177
0
            if (code < 0)
2178
0
                goto all_error;
2179
0
            code = pdfi_array_put(ctx, sep_color_array, 3, obj);
2180
0
            if (code < 0)
2181
0
                goto all_error;
2182
0
            pdfi_countdown(obj);
2183
0
            obj = NULL;
2184
2185
0
            code = pdfi_create_Separation(ctx, sep_color_array, 0, stream_dict, page_dict, ppcs, inline_image);
2186
0
            if (code < 0)
2187
0
                goto all_error;
2188
0
all_error:
2189
0
            pdfi_countdown(ink_name);
2190
0
            pdfi_countdown(sep_color_array);
2191
0
            pdfi_countdown(obj);
2192
0
            pdfi_countdown(inks);
2193
0
            return code;
2194
0
        } else
2195
17.4k
            pdfi_countdown(ink_name);
2196
17.4k
    }
2197
2198
    /* Deal with alternate space */
2199
21.6k
    code = pdfi_array_get(ctx, color_array, index + 2, &o);
2200
21.6k
    if (code < 0)
2201
72
        goto pdfi_devicen_error;
2202
2203
21.5k
    switch (pdfi_type_of(o)) {
2204
20.4k
        case PDF_NAME:
2205
20.4k
            NamedAlternate = (pdf_name *)o;
2206
20.4k
            code = pdfi_create_colorspace_by_name(ctx, NamedAlternate, stream_dict, page_dict, &pcs_alt, inline_image);
2207
20.4k
            if (code < 0)
2208
0
                goto pdfi_devicen_error;
2209
20.4k
            break;
2210
20.4k
        case PDF_ARRAY:
2211
1.10k
            ArrayAlternate = (pdf_array *)o;
2212
1.10k
            code = pdfi_create_colorspace_by_array(ctx, ArrayAlternate, 0, stream_dict, page_dict, &pcs_alt, inline_image);
2213
1.10k
            if (code < 0)
2214
                /* OSS-fuzz error 42973; we don't need to count down 'o' here because
2215
                 * we have assigned it to ArrayAlternate and both the success and error
2216
                 * paths count down ArrayAlternate.
2217
                 */
2218
129
                goto pdfi_devicen_error;
2219
974
            break;
2220
974
        default:
2221
9
            code = gs_error_typecheck;
2222
9
            pdfi_countdown(o);
2223
9
            goto pdfi_devicen_error;
2224
21.5k
    }
2225
2226
    /* Now the tint transform */
2227
21.4k
    code = pdfi_array_get(ctx, color_array, index + 3, &transform);
2228
21.4k
    if (code < 0)
2229
1.86k
        goto pdfi_devicen_error;
2230
2231
19.5k
    code = pdfi_build_function(ctx, &pfn, NULL, 1, transform, page_dict);
2232
19.5k
    if (code < 0)
2233
561
        goto pdfi_devicen_error;
2234
2235
18.9k
    if (pfn->params.m != pdfi_array_size(inks) || pfn->params.n != cs_num_components(pcs_alt)) {
2236
33
        code = gs_note_error(gs_error_rangecheck);
2237
33
        goto pdfi_devicen_error;
2238
33
    }
2239
2240
18.9k
    code = gs_cspace_new_DeviceN(&pcs, pdfi_array_size(inks), pcs_alt, ctx->memory);
2241
18.9k
    if (code < 0)
2242
0
        return code;
2243
2244
18.9k
    rc_decrement(pcs_alt, "pdfi_create_DeviceN");
2245
18.9k
    pcs_alt = NULL;
2246
18.9k
    pcs->params.device_n.mem = ctx->memory;
2247
2248
43.8k
    for (ix = 0;ix < pdfi_array_size(inks);ix++) {
2249
24.9k
        pdf_name *ink_name;
2250
2251
24.9k
        ink_name = NULL;
2252
24.9k
        code = pdfi_array_get_type(ctx, inks, ix, PDF_NAME, (pdf_obj **)&ink_name);
2253
24.9k
        if (code < 0)
2254
0
            goto pdfi_devicen_error;
2255
2256
24.9k
        pcs->params.device_n.names[ix] = (char *)gs_alloc_bytes(ctx->memory->non_gc_memory, ink_name->length + 1, "pdfi_setdevicenspace(ink)");
2257
24.9k
        if (pcs->params.device_n.names[ix] == NULL) {
2258
0
            code = gs_note_error(gs_error_VMerror);
2259
0
            goto pdfi_devicen_error;
2260
0
        }
2261
24.9k
        memcpy(pcs->params.device_n.names[ix], ink_name->data, ink_name->length);
2262
24.9k
        pcs->params.device_n.names[ix][ink_name->length] = 0x00;
2263
24.9k
        pdfi_countdown(ink_name);
2264
24.9k
    }
2265
2266
18.9k
    code = gs_cspace_set_devn_function(pcs, pfn);
2267
18.9k
    if (code < 0)
2268
0
        goto pdfi_devicen_error;
2269
2270
18.9k
    if (pdfi_array_size(color_array) >= index + 5) {
2271
18.0k
        pdf_obj *ColorSpace = NULL;
2272
18.0k
        pdf_array *Components = NULL;
2273
18.0k
        pdf_obj *subtype = NULL;
2274
2275
18.0k
        code = pdfi_array_get_type(ctx, color_array, index + 4, PDF_DICT, (pdf_obj **)&attributes);
2276
18.0k
        if (code < 0)
2277
0
            goto pdfi_devicen_error;
2278
2279
18.0k
        code = pdfi_dict_knownget(ctx, attributes, "Subtype", (pdf_obj **)&subtype);
2280
18.0k
        if (code < 0)
2281
0
            goto pdfi_devicen_error;
2282
2283
18.0k
        if (code == 0) {
2284
36
            pcs->params.device_n.subtype = gs_devicen_DeviceN;
2285
18.0k
        } else {
2286
18.0k
            switch (pdfi_type_of(subtype)) {
2287
18.0k
                case PDF_NAME:
2288
18.0k
                case PDF_STRING:
2289
18.0k
                    if (memcmp(((pdf_name *)subtype)->data, "DeviceN", 7) == 0) {
2290
89
                        pcs->params.device_n.subtype = gs_devicen_DeviceN;
2291
17.9k
                    } else {
2292
17.9k
                        if (memcmp(((pdf_name *)subtype)->data, "NChannel", 8) == 0) {
2293
17.9k
                            pcs->params.device_n.subtype = gs_devicen_NChannel;
2294
17.9k
                        } else {
2295
0
                            pdfi_countdown(subtype);
2296
0
                            goto pdfi_devicen_error;
2297
0
                        }
2298
17.9k
                    }
2299
18.0k
                    pdfi_countdown(subtype);
2300
18.0k
                    break;
2301
0
                default:
2302
0
                    pdfi_countdown(subtype);
2303
0
                    goto pdfi_devicen_error;
2304
18.0k
            }
2305
18.0k
        }
2306
2307
18.0k
        code = pdfi_dict_knownget_type(ctx, attributes, "Process", PDF_DICT, (pdf_obj **)&Process);
2308
18.0k
        if (code < 0)
2309
3
            goto pdfi_devicen_error;
2310
2311
18.0k
        if (Process != NULL && pdfi_dict_entries(Process) != 0) {
2312
17.9k
            int ix = 0;
2313
17.9k
            pdf_obj *name;
2314
2315
17.9k
            code = pdfi_dict_get(ctx, Process, "ColorSpace", (pdf_obj **)&ColorSpace);
2316
17.9k
            if (code < 0)
2317
0
                goto pdfi_devicen_error;
2318
2319
17.9k
            code = pdfi_create_colorspace(ctx, ColorSpace, stream_dict, page_dict, &process_space, inline_image);
2320
17.9k
            pdfi_countdown(ColorSpace);
2321
17.9k
            if (code < 0)
2322
0
                goto pdfi_devicen_error;
2323
2324
17.9k
            pcs->params.device_n.devn_process_space = process_space;
2325
2326
17.9k
            code = pdfi_dict_get_type(ctx, Process, "Components", PDF_ARRAY, (pdf_obj **)&Components);
2327
17.9k
            if (code < 0)
2328
0
                goto pdfi_devicen_error;
2329
2330
17.9k
            pcs->params.device_n.num_process_names = pdfi_array_size(Components);
2331
17.9k
            pcs->params.device_n.process_names = (char **)gs_alloc_bytes(pcs->params.device_n.mem->non_gc_memory, pdfi_array_size(Components) * sizeof(char *), "pdfi_devicen(Processnames)");
2332
17.9k
            if (pcs->params.device_n.process_names == NULL) {
2333
0
                code = gs_error_VMerror;
2334
0
                goto pdfi_devicen_error;
2335
0
            }
2336
17.9k
            memset(pcs->params.device_n.process_names, 0x00, pdfi_array_size(Components) * sizeof(char *));
2337
2338
89.5k
            for (ix = 0; ix < pcs->params.device_n.num_process_names; ix++) {
2339
71.6k
                code = pdfi_array_get(ctx, Components, ix, &name);
2340
71.6k
                if (code < 0) {
2341
0
                    pdfi_countdown(Components);
2342
0
                    goto pdfi_devicen_error;
2343
0
                }
2344
2345
71.6k
                switch (pdfi_type_of(name)) {
2346
71.6k
                    case PDF_NAME:
2347
71.6k
                    case PDF_STRING:
2348
71.6k
                        pcs->params.device_n.process_names[ix] = (char *)gs_alloc_bytes(pcs->params.device_n.mem->non_gc_memory, ((pdf_name *)name)->length + 1, "pdfi_devicen(Processnames)");
2349
71.6k
                        if (pcs->params.device_n.process_names[ix] == NULL) {
2350
0
                            pdfi_countdown(Components);
2351
0
                            pdfi_countdown(name);
2352
0
                            code = gs_error_VMerror;
2353
0
                            goto pdfi_devicen_error;
2354
0
                        }
2355
71.6k
                        memcpy(pcs->params.device_n.process_names[ix], ((pdf_name *)name)->data, ((pdf_name *)name)->length);
2356
71.6k
                        pcs->params.device_n.process_names[ix][((pdf_name *)name)->length] = 0x00;
2357
71.6k
                        pdfi_countdown(name);
2358
71.6k
                        break;
2359
4
                    default:
2360
4
                        pdfi_countdown(Components);
2361
4
                        pdfi_countdown(name);
2362
4
                        goto pdfi_devicen_error;
2363
71.6k
                }
2364
71.6k
            }
2365
17.9k
            pdfi_countdown(Components);
2366
17.9k
        }
2367
2368
18.0k
        code = pdfi_dict_knownget_type(ctx, attributes, "Colorants", PDF_DICT, (pdf_obj **)&Colorants);
2369
18.0k
        if (code < 0)
2370
0
            goto pdfi_devicen_error;
2371
2372
18.0k
        if (Colorants != NULL && pdfi_dict_entries(Colorants) != 0) {
2373
0
            uint64_t ix = 0;
2374
0
            pdf_obj *Colorant = NULL, *Space = NULL;
2375
0
            char *colorant_name;
2376
0
            gs_color_space *colorant_space = NULL;
2377
2378
0
            code = pdfi_dict_first(ctx, Colorants, &Colorant, &Space, &ix);
2379
0
            if (code < 0)
2380
0
                goto pdfi_devicen_error;
2381
2382
0
            do {
2383
0
                switch (pdfi_type_of(Space)) {
2384
0
                    case PDF_STRING:
2385
0
                    case PDF_NAME:
2386
0
                    case PDF_ARRAY:
2387
0
                        break;
2388
0
                    default:
2389
0
                        pdfi_countdown(Space);
2390
0
                        pdfi_countdown(Colorant);
2391
0
                        code = gs_note_error(gs_error_typecheck);
2392
0
                        goto pdfi_devicen_error;
2393
0
                }
2394
0
                switch (pdfi_type_of(Colorant)) {
2395
0
                    case PDF_STRING:
2396
0
                    case PDF_NAME:
2397
0
                        break;
2398
0
                    default:
2399
0
                        pdfi_countdown(Space);
2400
0
                        pdfi_countdown(Colorant);
2401
0
                        code = gs_note_error(gs_error_typecheck);
2402
0
                        goto pdfi_devicen_error;
2403
0
                }
2404
2405
0
                code = pdfi_create_colorspace(ctx, Space, stream_dict, page_dict, &colorant_space, inline_image);
2406
0
                if (code < 0) {
2407
0
                    pdfi_countdown(Space);
2408
0
                    pdfi_countdown(Colorant);
2409
0
                    goto pdfi_devicen_error;
2410
0
                }
2411
2412
0
                colorant_name = (char *)gs_alloc_bytes(pcs->params.device_n.mem->non_gc_memory, ((pdf_name *)Colorant)->length + 1, "pdfi_devicen(colorant)");
2413
0
                if (colorant_name == NULL) {
2414
0
                    rc_decrement_cs(colorant_space, "pdfi_devicen(colorant)");
2415
0
                    pdfi_countdown(Space);
2416
0
                    pdfi_countdown(Colorant);
2417
0
                    code = gs_note_error(gs_error_VMerror);
2418
0
                    goto pdfi_devicen_error;
2419
0
                }
2420
0
                memcpy(colorant_name, ((pdf_name *)Colorant)->data, ((pdf_name *)Colorant)->length);
2421
0
                colorant_name[((pdf_name *)Colorant)->length] = 0x00;
2422
2423
0
                code = gs_attach_colorant_to_space(colorant_name, pcs, colorant_space, pcs->params.device_n.mem->non_gc_memory);
2424
0
                if (code < 0) {
2425
0
                    gs_free_object(pcs->params.device_n.mem->non_gc_memory, colorant_name, "pdfi_devicen(colorant)");
2426
0
                    rc_decrement_cs(colorant_space, "pdfi_devicen(colorant)");
2427
0
                    pdfi_countdown(Space);
2428
0
                    pdfi_countdown(Colorant);
2429
0
                    code = gs_note_error(gs_error_VMerror);
2430
0
                    goto pdfi_devicen_error;
2431
0
                }
2432
2433
                /* We've attached the colorant colour space to the DeviceN space, we no longer need this
2434
                 * reference to it, so discard it.
2435
                 */
2436
0
                rc_decrement_cs(colorant_space, "pdfi_devicen(colorant)");
2437
0
                pdfi_countdown(Space);
2438
0
                pdfi_countdown(Colorant);
2439
0
                Space = Colorant = NULL;
2440
2441
0
                code = pdfi_dict_next(ctx, Colorants, &Colorant, &Space, &ix);
2442
0
                if (code == gs_error_undefined)
2443
0
                    break;
2444
2445
0
                if (code < 0) {
2446
0
                    pdfi_countdown(Space);
2447
0
                    pdfi_countdown(Colorant);
2448
0
                    goto pdfi_devicen_error;
2449
0
                }
2450
0
            }while (1);
2451
0
        }
2452
18.0k
    }
2453
2454
18.9k
    if (ppcs!= NULL){
2455
125
        *ppcs = pcs;
2456
125
        pdfi_set_colour_callback(pcs, ctx, pdfi_cspace_free_callback);
2457
18.8k
    } else {
2458
18.8k
        code = pdfi_gs_setcolorspace(ctx, pcs);
2459
        /* release reference from construction */
2460
18.8k
        rc_decrement_only_cs(pcs, "setdevicenspace");
2461
18.8k
    }
2462
18.9k
    pdfi_countdown(Process);
2463
18.9k
    pdfi_countdown(Colorants);
2464
18.9k
    pdfi_countdown(attributes);
2465
18.9k
    pdfi_countdown(inks);
2466
18.9k
    pdfi_countdown(NamedAlternate);
2467
18.9k
    pdfi_countdown(ArrayAlternate);
2468
18.9k
    pdfi_countdown(transform);
2469
18.9k
    return_error(0);
2470
2471
2.68k
pdfi_devicen_error:
2472
2.68k
    pdfi_free_function(ctx, pfn);
2473
2.68k
    if (pcs_alt != NULL)
2474
2.45k
        rc_decrement_only_cs(pcs_alt, "setseparationspace");
2475
2.68k
    if(pcs != NULL)
2476
7
        rc_decrement_only_cs(pcs, "setseparationspace");
2477
2.68k
    pdfi_countdown(Process);
2478
2.68k
    pdfi_countdown(Colorants);
2479
2.68k
    pdfi_countdown(attributes);
2480
2.68k
    pdfi_countdown(inks);
2481
2.68k
    pdfi_countdown(NamedAlternate);
2482
2.68k
    pdfi_countdown(ArrayAlternate);
2483
2.68k
    pdfi_countdown(transform);
2484
2.68k
    return code;
2485
18.9k
}
2486
2487
/* Now /Indexed spaces, essentially we just need to set the underlying space(s) and then set
2488
 * /Indexed.
2489
 */
2490
static int
2491
pdfi_create_indexed(pdf_context *ctx, pdf_array *color_array, int index,
2492
                    pdf_dict *stream_dict, pdf_dict *page_dict, gs_color_space **ppcs, bool inline_image)
2493
12.2k
{
2494
12.2k
    pdf_obj *space=NULL, *lookup=NULL;
2495
12.2k
    int code;
2496
12.2k
    int64_t hival, lookup_length = 0;
2497
12.2k
    int num_values;
2498
12.2k
    gs_color_space *pcs=NULL, *pcs_base=NULL;
2499
12.2k
    gs_color_space_index base_type;
2500
12.2k
    byte *Buffer = NULL;
2501
2502
12.2k
    if (index != 0)
2503
0
        return_error(gs_error_syntaxerror);
2504
2505
12.2k
    code = pdfi_array_get_int(ctx, color_array, index + 2, &hival);
2506
12.2k
    if (code < 0)
2507
65
        return code;
2508
2509
12.2k
    if (hival > 255 || hival < 0)
2510
11
        return_error(gs_error_syntaxerror);
2511
2512
12.2k
    code = pdfi_array_get(ctx, color_array, index + 1, &space);
2513
12.2k
    if (code < 0)
2514
76
        goto exit;
2515
2516
12.1k
    code = pdfi_create_colorspace(ctx, space, stream_dict, page_dict, &pcs_base, inline_image);
2517
12.1k
    if (code < 0)
2518
318
        goto exit;
2519
2520
11.8k
    base_type = gs_color_space_get_index(pcs_base);
2521
11.8k
    if (base_type == gs_color_space_index_Pattern || base_type == gs_color_space_index_Indexed) {
2522
6
        code = gs_note_error(gs_error_typecheck);
2523
6
        goto exit;
2524
6
    }
2525
2526
11.8k
    (void)pcs_base->type->install_cspace(pcs_base, ctx->pgs);
2527
2528
11.8k
    code = pdfi_array_get(ctx, color_array, index + 3, &lookup);
2529
11.8k
    if (code < 0)
2530
175
        goto exit;
2531
2532
11.6k
    num_values = (hival+1) * cs_num_components(pcs_base);
2533
11.6k
    lookup_length = num_values;
2534
2535
11.6k
    switch (pdfi_type_of(lookup)) {
2536
6.91k
    case PDF_STREAM:
2537
6.91k
        code = pdfi_stream_to_buffer(ctx, (pdf_stream *)lookup, &Buffer, &lookup_length);
2538
6.91k
        if (code < 0)
2539
7
            goto exit;
2540
6.90k
        break;
2541
6.90k
    case PDF_STRING:
2542
4.72k
    {
2543
4.72k
        pdf_string *lookup_string = (pdf_string *)lookup; /* alias */
2544
2545
4.72k
        Buffer = gs_alloc_bytes(ctx->memory, lookup_string->length, "pdfi_create_indexed (lookup buffer)");
2546
4.72k
        if (Buffer == NULL) {
2547
0
            code = gs_note_error(gs_error_VMerror);
2548
0
            goto exit;
2549
0
        }
2550
2551
4.72k
        memcpy(Buffer, lookup_string->data, lookup_string->length);
2552
4.72k
        lookup_length = lookup_string->length;
2553
4.72k
        break;
2554
4.72k
    }
2555
11
    default:
2556
11
        code = gs_note_error(gs_error_typecheck);
2557
11
        goto exit;
2558
11.6k
    }
2559
2560
11.6k
    if (num_values > lookup_length) {
2561
        /* This is not legal, but Acrobat seems to accept it */
2562
130
        byte *SBuffer = NULL;
2563
2564
130
        code = pdfi_set_error_stop(ctx, gs_error_rangecheck, NULL, E_PDF_BAD_INDEXED_STRING, "pdfi_create_indexed", NULL);
2565
130
        if (code < 0)
2566
0
            goto exit;
2567
130
        SBuffer = gs_alloc_bytes(ctx->memory, num_values, "pdfi_create_indexed (lookup buffer)");
2568
130
        if (SBuffer == NULL) {
2569
0
            code = gs_note_error(gs_error_VMerror);
2570
0
            goto exit;
2571
0
        }
2572
130
        memcpy(SBuffer, Buffer, lookup_length);
2573
130
        memset(&SBuffer[lookup_length], 0x00, num_values - lookup_length);
2574
130
        gs_free_object(ctx->memory, Buffer, "pdfi_create_indexed (lookup buffer)");
2575
130
        Buffer = SBuffer;
2576
130
    }
2577
2578
    /* If we have a named color profile and the base space is DeviceN or
2579
       Separation use a different set of procedures to ensure the named
2580
       color remapping code is used */
2581
11.6k
    if (ctx->pgs->icc_manager->device_named != NULL &&
2582
11.6k
        (base_type == gs_color_space_index_Separation ||
2583
0
         base_type == gs_color_space_index_DeviceN))
2584
0
        pcs = gs_cspace_alloc(ctx->memory, &gs_color_space_type_Indexed_Named);
2585
11.6k
    else
2586
11.6k
        pcs = gs_cspace_alloc(ctx->memory, &gs_color_space_type_Indexed);
2587
2588
11.6k
    if (pcs == NULL) {
2589
0
        code = gs_note_error(gs_error_VMerror);
2590
0
        goto exit;
2591
0
    }
2592
    /* NOTE: we don't need to increment the reference to pcs_base, since it is already 1 */
2593
11.6k
    pcs->base_space = pcs_base;
2594
2595
11.6k
    pcs->params.indexed.lookup.table.size = num_values;
2596
11.6k
    pcs->params.indexed.use_proc = 0;
2597
11.6k
    pcs->params.indexed.hival = hival;
2598
11.6k
    pcs->params.indexed.n_comps = cs_num_components(pcs_base);
2599
11.6k
    pcs->params.indexed.lookup.table.data = Buffer;
2600
11.6k
    Buffer = NULL;
2601
2602
11.6k
    if (ppcs != NULL) {
2603
11.5k
        *ppcs = pcs;
2604
11.5k
        pdfi_set_colour_callback(pcs, ctx, pdfi_cspace_free_callback);
2605
11.5k
    }
2606
69
    else {
2607
69
        code = pdfi_gs_setcolorspace(ctx, pcs);
2608
        /* release reference from construction */
2609
69
        rc_decrement_only_cs(pcs, "setindexedspace");
2610
69
    }
2611
2612
12.2k
 exit:
2613
12.2k
    if (code != 0)
2614
12.2k
        rc_decrement(pcs_base, "pdfi_create_indexed(pcs_base) error");
2615
12.2k
    if (Buffer)
2616
0
        gs_free_object(ctx->memory, Buffer, "pdfi_create_indexed (decompression buffer)");
2617
12.2k
    pdfi_countdown(space);
2618
12.2k
    pdfi_countdown(lookup);
2619
12.2k
    return code;
2620
11.6k
}
2621
2622
static int pdfi_create_DeviceGray(pdf_context *ctx, gs_color_space **ppcs)
2623
50.0k
{
2624
50.0k
    int code = 0;
2625
2626
50.0k
    if (ppcs != NULL) {
2627
45.8k
        if (ctx->page.DefaultGray_cs != NULL) {
2628
0
            *ppcs = ctx->page.DefaultGray_cs;
2629
0
            rc_increment(*ppcs);
2630
45.8k
        } else {
2631
45.8k
            *ppcs = gs_cspace_new_DeviceGray(ctx->memory);
2632
45.8k
            if (*ppcs == NULL)
2633
0
                code = gs_note_error(gs_error_VMerror);
2634
45.8k
            else {
2635
45.8k
                code = ((gs_color_space *)*ppcs)->type->install_cspace(*ppcs, ctx->pgs);
2636
45.8k
                if (code < 0) {
2637
0
                    rc_decrement_only_cs(*ppcs, "pdfi_create_DeviceGray");
2638
0
                    *ppcs = NULL;
2639
0
                }
2640
45.8k
            }
2641
45.8k
            if (*ppcs != NULL)
2642
45.8k
                pdfi_set_colour_callback(*ppcs, ctx, pdfi_cspace_free_callback);
2643
45.8k
        }
2644
45.8k
    } else {
2645
4.19k
        code = pdfi_gs_setgray(ctx, 0);
2646
4.19k
        pdfi_set_colour_callback(ctx->pgs->color[0].color_space, ctx, pdfi_cspace_free_callback);
2647
4.19k
    }
2648
50.0k
    return code;
2649
50.0k
}
2650
2651
static int pdfi_create_DeviceRGB(pdf_context *ctx, gs_color_space **ppcs)
2652
108k
{
2653
108k
    int code = 0;
2654
2655
108k
    if (ppcs != NULL) {
2656
66.1k
        if (ctx->page.DefaultRGB_cs != NULL) {
2657
183
            *ppcs = ctx->page.DefaultRGB_cs;
2658
183
            rc_increment(*ppcs);
2659
65.9k
        } else {
2660
65.9k
            *ppcs = gs_cspace_new_DeviceRGB(ctx->memory);
2661
65.9k
            if (*ppcs == NULL)
2662
0
                code = gs_note_error(gs_error_VMerror);
2663
65.9k
            else {
2664
65.9k
                code = ((gs_color_space *)*ppcs)->type->install_cspace(*ppcs, ctx->pgs);
2665
65.9k
                if (code < 0) {
2666
0
                    rc_decrement_only_cs(*ppcs, "pdfi_create_DeviceRGB");
2667
0
                    *ppcs = NULL;
2668
0
                }
2669
65.9k
            }
2670
65.9k
            if (*ppcs != NULL)
2671
65.9k
                pdfi_set_colour_callback(*ppcs, ctx, pdfi_cspace_free_callback);
2672
65.9k
        }
2673
66.1k
    } else {
2674
42.0k
        code = pdfi_gs_setrgbcolor(ctx, 0, 0, 0);
2675
42.0k
    }
2676
108k
    return code;
2677
108k
}
2678
2679
static int pdfi_create_DeviceCMYK(pdf_context *ctx, gs_color_space **ppcs)
2680
93.1k
{
2681
93.1k
    int code = 0;
2682
2683
93.1k
    if (ppcs != NULL) {
2684
72.3k
        if (ctx->page.DefaultCMYK_cs != NULL) {
2685
0
            *ppcs = ctx->page.DefaultCMYK_cs;
2686
0
            rc_increment(*ppcs);
2687
72.3k
        } else {
2688
72.3k
            *ppcs = gs_cspace_new_DeviceCMYK(ctx->memory);
2689
72.3k
            if (*ppcs == NULL)
2690
0
                code = gs_note_error(gs_error_VMerror);
2691
72.3k
            else {
2692
72.3k
                code = ((gs_color_space *)*ppcs)->type->install_cspace(*ppcs, ctx->pgs);
2693
72.3k
                if (code < 0) {
2694
0
                    rc_decrement_only_cs(*ppcs, "pdfi_create_DeviceCMYK");
2695
0
                    *ppcs = NULL;
2696
0
                }
2697
72.3k
            }
2698
72.3k
            if (*ppcs != NULL)
2699
72.3k
                pdfi_set_colour_callback(*ppcs, ctx, pdfi_cspace_free_callback);
2700
72.3k
        }
2701
72.3k
    } else {
2702
20.8k
        code = pdfi_gs_setcmykcolor(ctx, 0, 0, 0, 1);
2703
20.8k
        pdfi_set_colour_callback(ctx->pgs->color[0].color_space, ctx, pdfi_cspace_free_callback);
2704
20.8k
    }
2705
93.1k
    return code;
2706
93.1k
}
2707
2708
static int pdfi_create_JPX_space(pdf_context *ctx, const char *name, int num_components, gs_color_space **ppcs)
2709
4.95k
{
2710
4.95k
    int code, icc_N;
2711
4.95k
    float range_buff[6] = {0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f};
2712
2713
4.95k
    code = pdfi_create_icc(ctx, (char *)name, NULL, num_components, &icc_N, range_buff, 0, ppcs);
2714
4.95k
    return code;
2715
4.95k
}
2716
2717
/* These next routines allow us to use recursion to set up colour spaces. We can set
2718
 * colour space starting from a name (which can be a named resource) or an array.
2719
 * If we get a name, and its a named resource we dereference it and go round again.
2720
 * If its an array we select the correct handler (above) for that space. The space
2721
 * handler will call pdfi_create_colorspace() to set the underlying space(s) which
2722
 * may mean calling pdfi_create_colorspace again....
2723
 */
2724
static int
2725
pdfi_create_colorspace_by_array(pdf_context *ctx, pdf_array *color_array, int index,
2726
                                pdf_dict *stream_dict, pdf_dict *page_dict, gs_color_space **ppcs,
2727
                                bool inline_image)
2728
310k
{
2729
310k
    int code;
2730
310k
    pdf_name *space = NULL;
2731
310k
    pdf_array *a = NULL;
2732
2733
310k
    code = pdfi_array_get_type(ctx, color_array, index, PDF_NAME, (pdf_obj **)&space);
2734
310k
    if (code != 0)
2735
258
        goto exit;
2736
2737
310k
    code = 0;
2738
310k
    if (pdfi_name_is(space, "G") || pdfi_name_is(space, "DeviceGray")) {
2739
0
        if (pdfi_name_is(space, "G") && !inline_image) {
2740
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)
2741
0
                return code;
2742
0
        }
2743
0
        code = pdfi_create_DeviceGray(ctx, ppcs);
2744
310k
    } else if (pdfi_name_is(space, "I") || pdfi_name_is(space, "Indexed")) {
2745
12.2k
        if (pdfi_name_is(space, "I") && !inline_image) {
2746
65
            pdfi_set_warning(ctx, 0, NULL, W_PDF_BAD_INLINECOLORSPACE, "pdfi_create_colorspace_by_array", NULL);
2747
65
            if (ctx->args.pdfstoponwarning)
2748
0
                return_error(gs_error_syntaxerror);
2749
65
        }
2750
12.2k
        code = pdfi_create_indexed(ctx, color_array, index, stream_dict, page_dict, ppcs, inline_image);
2751
297k
    } else if (pdfi_name_is(space, "Lab")) {
2752
611
        code = pdfi_create_Lab(ctx, color_array, index, stream_dict, page_dict, ppcs);
2753
297k
    } else if (pdfi_name_is(space, "RGB") || pdfi_name_is(space, "DeviceRGB")) {
2754
2
        if (pdfi_name_is(space, "RGB") && !inline_image) {
2755
0
            pdfi_set_warning(ctx, 0, NULL, W_PDF_BAD_INLINECOLORSPACE, "pdfi_create_colorspace_by_array", NULL);
2756
0
            if (ctx->args.pdfstoponwarning)
2757
0
                return_error(gs_error_syntaxerror);
2758
0
        }
2759
2
        code = pdfi_create_DeviceRGB(ctx, ppcs);
2760
297k
    } else if (pdfi_name_is(space, "CMYK") || pdfi_name_is(space, "DeviceCMYK") || pdfi_name_is(space, "CalCMYK")) {
2761
0
        if (pdfi_name_is(space, "CMYK") && !inline_image) {
2762
0
            pdfi_set_warning(ctx, 0, NULL, W_PDF_BAD_INLINECOLORSPACE, "pdfi_create_colorspace_by_array", NULL);
2763
0
            if (ctx->args.pdfstoponwarning)
2764
0
                return_error(gs_error_syntaxerror);
2765
0
        }
2766
0
        code = pdfi_create_DeviceCMYK(ctx, ppcs);
2767
297k
    } else if (pdfi_name_is(space, "CalRGB")) {
2768
2.24k
        code = pdfi_create_CalRGB(ctx, color_array, index, stream_dict, page_dict, ppcs);
2769
294k
    } else if (pdfi_name_is(space, "CalGray")) {
2770
524
        code = pdfi_create_CalGray(ctx, color_array, index, stream_dict, page_dict, ppcs);
2771
294k
    } else if (pdfi_name_is(space, "Pattern")) {
2772
2.05k
        if (index != 0)
2773
0
            code = gs_note_error(gs_error_syntaxerror);
2774
2.05k
        else
2775
2.05k
            code = pdfi_pattern_create(ctx, color_array, stream_dict, page_dict, ppcs);
2776
292k
    } else if (pdfi_name_is(space, "DeviceN")) {
2777
21.6k
        code = pdfi_create_DeviceN(ctx, color_array, index, stream_dict, page_dict, ppcs, inline_image);
2778
270k
    } else if (pdfi_name_is(space, "ICCBased")) {
2779
208k
        code = pdfi_create_iccbased(ctx, color_array, index, stream_dict, page_dict, ppcs, inline_image);
2780
208k
    } else if (pdfi_name_is(space, "Separation")) {
2781
61.3k
        code = pdfi_create_Separation(ctx, color_array, index, stream_dict, page_dict, ppcs, inline_image);
2782
61.3k
    } else {
2783
558
        if (stream_dict == NULL)
2784
26
            code = gs_note_error(gs_error_syntaxerror);
2785
532
        else
2786
532
            code = pdfi_find_resource(ctx, (unsigned char *)"ColorSpace",
2787
532
                                  space, (pdf_dict *)stream_dict, page_dict, (pdf_obj **)&a);
2788
558
        if (code < 0)
2789
558
            goto exit;
2790
2791
0
        if (pdfi_type_of(a) != PDF_ARRAY) {
2792
0
            code = gs_note_error(gs_error_typecheck);
2793
0
            goto exit;
2794
0
        }
2795
2796
        /* recursion */
2797
0
        code = pdfi_create_colorspace_by_array(ctx, a, 0, stream_dict, page_dict, ppcs, inline_image);
2798
0
    }
2799
2800
310k
 exit:
2801
310k
    pdfi_countdown(space);
2802
310k
    pdfi_countdown(a);
2803
310k
    return code;
2804
310k
}
2805
2806
static int
2807
pdfi_create_colorspace_by_name(pdf_context *ctx, pdf_name *name,
2808
                               pdf_dict *stream_dict, pdf_dict *page_dict,
2809
                               gs_color_space **ppcs, bool inline_image)
2810
647k
{
2811
647k
    int code = 0;
2812
647k
    gs_id oldid = 0;
2813
2814
647k
    if (pdfi_name_is(name, "G") || pdfi_name_is(name, "DeviceGray")) {
2815
50.0k
        if (pdfi_name_is(name, "G") && !inline_image) {
2816
21
            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)
2817
0
                return code;
2818
21
        }
2819
50.0k
        code = pdfi_create_DeviceGray(ctx, ppcs);
2820
597k
    } else if (pdfi_name_is(name, "RGB") || pdfi_name_is(name, "DeviceRGB")) {
2821
108k
        if (pdfi_name_is(name, "RGB") && !inline_image) {
2822
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)
2823
0
                return code;
2824
0
        }
2825
108k
        code = pdfi_create_DeviceRGB(ctx, ppcs);
2826
489k
    } else if (pdfi_name_is(name, "CMYK") || pdfi_name_is(name, "DeviceCMYK") || pdfi_name_is(name, "CalCMYK")) {
2827
93.1k
        if (pdfi_name_is(name, "CMYK") && !inline_image) {
2828
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)
2829
0
                return code;
2830
0
        }
2831
93.1k
        code = pdfi_create_DeviceCMYK(ctx, ppcs);
2832
395k
    } else if (pdfi_name_is(name, "Pattern")) {
2833
61.8k
        code = pdfi_pattern_create(ctx, NULL, stream_dict, page_dict, ppcs);
2834
334k
    } else if (pdfi_name_is(name, "esRGBICC")) {                /* These 4 spaces are 'special' for JPX images          */
2835
0
        code = pdfi_create_JPX_space(ctx, "esrgb", 3, ppcs);    /* the names are non-standad and must match those in    */
2836
334k
    } else if (pdfi_name_is(name, "rommRGBICC")) {              /* pdfi_image_get_color() in pdf_image.c                */
2837
0
        code = pdfi_create_JPX_space(ctx, "rommrgb", 3, ppcs);  /* Note that the Lab space for JPX images does not use  */
2838
334k
    } else if (pdfi_name_is(name, "sRGBICC")) {                 /* a special space but simply constructs an appropriate */
2839
904
        code = pdfi_create_JPX_space(ctx, "srgb", 3, ppcs);     /* pdf_array object with the corerct contents for an    */
2840
333k
    } else if (pdfi_name_is(name, "sGrayICC")) {                /* Lab space with a D65 white point.                    */
2841
4.05k
        code = pdfi_create_JPX_space(ctx, "sgray", 1, ppcs);
2842
329k
    } else {
2843
329k
        pdf_obj *ref_space = NULL;
2844
2845
329k
        if (ppcs == NULL && check_same_current_space(ctx, name) == 1)
2846
94.0k
            return 0;
2847
2848
235k
        code = pdfi_find_resource(ctx, (unsigned char *)"ColorSpace", name, (pdf_dict *)stream_dict,
2849
235k
                                  page_dict, &ref_space);
2850
235k
        if (code < 0)
2851
34.5k
            return code;
2852
2853
200k
        if (pdfi_type_of(ref_space) == PDF_NAME) {
2854
109
            if (ref_space->object_num != 0 && ref_space->object_num == name->object_num) {
2855
0
                pdfi_countdown(ref_space);
2856
0
                return_error(gs_error_circular_reference);
2857
0
            }
2858
109
            if (((pdf_name *)ref_space)->length <= 0) {
2859
2
                pdfi_countdown(ref_space);
2860
2
                return_error(gs_error_syntaxerror);
2861
2
            }
2862
107
            if (((pdf_name *)ref_space)->length == name->length && memcmp(((pdf_name *)ref_space)->data, name->data, name->length) == 0) {
2863
2
                pdfi_countdown(ref_space);
2864
2
                return_error(gs_error_circular_reference);
2865
2
            }
2866
107
        }
2867
2868
200k
        oldid = ctx->pgs->color[0].color_space->id;
2869
        /* recursion */
2870
200k
        code = pdfi_create_colorspace(ctx, ref_space, stream_dict, page_dict, ppcs, inline_image);
2871
2872
200k
        if (code >= 0) {
2873
179k
            if (oldid != ctx->pgs->color[0].color_space->id) {
2874
178k
                if (ppcs != NULL)
2875
0
                    pdfi_set_colourspace_name(ctx, *ppcs, name);
2876
178k
                else
2877
178k
                    pdfi_set_colourspace_name(ctx, ctx->pgs->color[0].color_space, name);
2878
178k
            }
2879
179k
        }
2880
2881
200k
        pdfi_countdown(ref_space);
2882
200k
        return code;
2883
200k
    }
2884
2885
    /* If we got here, it's a recursion base case, and ppcs should have been set if requested */
2886
318k
    if (ppcs != NULL && *ppcs == NULL)
2887
0
        code = gs_note_error(gs_error_VMerror);
2888
318k
    return code;
2889
647k
}
2890
2891
/*
2892
 * Gets icc profile data from the provided stream.
2893
 * Position in the stream is NOT preserved.
2894
 * This is raw data, not filtered, so no need to worry about compression.
2895
 * (Used for JPXDecode images)
2896
 */
2897
int
2898
pdfi_create_icc_colorspace_from_stream(pdf_context *ctx, pdf_c_stream *stream, gs_offset_t offset,
2899
                                       unsigned int length, int comps, int *icc_N, ulong dictkey, gs_color_space **ppcs)
2900
0
{
2901
0
    pdf_c_stream *profile_stream = NULL;
2902
0
    byte *profile_buffer;
2903
0
    int code, code1;
2904
0
    float range[8] = {0,1,0,1,0,1,0,1};
2905
2906
    /* Move to the start of the profile data */
2907
0
    pdfi_seek(ctx, stream, offset, SEEK_SET);
2908
2909
    /* The ICC profile reading code (irritatingly) requires a seekable stream, because it
2910
     * rewinds it to the start, then seeks to the end to find the size, then rewinds the
2911
     * stream again.
2912
     * Ideally we would use a ReusableStreamDecode filter here, but that is largely
2913
     * implemented in PostScript (!) so we can't use it. What we can do is create a
2914
     * string sourced stream in memory, which is at least seekable.
2915
     */
2916
0
    code = pdfi_open_memory_stream_from_stream(ctx, length, &profile_buffer, stream, &profile_stream, true);
2917
0
    if (code < 0) {
2918
0
        return code;
2919
0
    }
2920
2921
    /* Now, finally, we can call the code to create and set the profile */
2922
0
    code = pdfi_create_icc(ctx, NULL, profile_stream->s, comps, icc_N, range, dictkey, ppcs);
2923
2924
0
    code1 = pdfi_close_memory_stream(ctx, profile_buffer, profile_stream);
2925
2926
0
    if (code == 0)
2927
0
        code = code1;
2928
2929
0
    return code;
2930
0
}
2931
2932
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)
2933
869k
{
2934
869k
    int code;
2935
2936
869k
    code = pdfi_loop_detector_mark(ctx);
2937
869k
    if (code < 0)
2938
0
        return code;
2939
2940
869k
    switch (pdfi_type_of(space)) {
2941
571k
    case PDF_NAME:
2942
571k
        code = pdfi_create_colorspace_by_name(ctx, (pdf_name *)space, stream_dict, page_dict, ppcs, inline_image);
2943
571k
        break;
2944
294k
    case PDF_ARRAY:
2945
294k
        code = pdfi_create_colorspace_by_array(ctx, (pdf_array *)space, 0, stream_dict, page_dict, ppcs, inline_image);
2946
294k
        break;
2947
4.19k
    default:
2948
4.19k
        pdfi_loop_detector_cleartomark(ctx);
2949
4.19k
        return_error(gs_error_typecheck);
2950
869k
    }
2951
865k
    if (code >= 0 && ppcs && *ppcs)
2952
170k
        (void)(*ppcs)->type->install_cspace(*ppcs, ctx->pgs);
2953
2954
865k
    (void)pdfi_loop_detector_cleartomark(ctx);
2955
865k
    return code;
2956
869k
}
2957
2958
int pdfi_setcolorspace(pdf_context *ctx, pdf_obj *space, pdf_dict *stream_dict, pdf_dict *page_dict)
2959
494k
{
2960
494k
    return pdfi_create_colorspace(ctx, space, stream_dict, page_dict, NULL, false);
2961
494k
}
2962
2963
/* And finally, the implementation of the actual PDF operators CS and cs */
2964
int pdfi_setstrokecolor_space(pdf_context *ctx, pdf_dict *stream_dict, pdf_dict *page_dict)
2965
64.3k
{
2966
64.3k
    int code;
2967
64.3k
    pdf_obj *n = NULL;
2968
2969
64.3k
    if (pdfi_count_stack(ctx) < 1)
2970
803
        return_error(gs_error_stackunderflow);
2971
2972
63.5k
    if (ctx->text.inside_CharProc && ctx->text.CharProc_d_type != pdf_type3_d0) {
2973
0
        pdfi_pop(ctx, 1);
2974
0
        pdfi_log_info(ctx, "pdfi_setstrokecolor_space", "colour operator in a CharProc, following a d1 ignored\n");
2975
0
        return 0;
2976
0
    }
2977
2978
63.5k
    if (pdfi_type_of(ctx->stack_top[-1]) != PDF_NAME) {
2979
1.16k
        pdfi_pop(ctx, 1);
2980
1.16k
        return_error(gs_error_typecheck);
2981
1.16k
    }
2982
62.3k
    n = ctx->stack_top[-1];
2983
62.3k
    pdfi_countup(n);
2984
62.3k
    pdfi_pop(ctx, 1);
2985
2986
62.3k
    gs_swapcolors_quick(ctx->pgs);
2987
62.3k
    code = pdfi_setcolorspace(ctx, n, stream_dict, page_dict);
2988
62.3k
    gs_swapcolors_quick(ctx->pgs);
2989
2990
62.3k
    pdfi_countdown(n);
2991
62.3k
    return code;
2992
63.5k
}
2993
2994
int pdfi_setfillcolor_space(pdf_context *ctx, pdf_dict *stream_dict, pdf_dict *page_dict)
2995
338k
{
2996
338k
    int code;
2997
338k
    pdf_obj *n = NULL;
2998
2999
338k
    if (pdfi_count_stack(ctx) < 1)
3000
3.40k
        return_error(gs_error_stackunderflow);
3001
3002
335k
    if (ctx->text.inside_CharProc && ctx->text.CharProc_d_type != pdf_type3_d0) {
3003
1
        pdfi_pop(ctx, 1);
3004
1
        pdfi_log_info(ctx, "pdfi_setfillcolor_space", "colour operator in a CharProc, following a d1 ignored\n");
3005
1
        return 0;
3006
1
    }
3007
3008
335k
    if (pdfi_type_of(ctx->stack_top[-1]) != PDF_NAME) {
3009
5.61k
        pdfi_pop(ctx, 1);
3010
5.61k
        return_error(gs_error_typecheck);
3011
5.61k
    }
3012
329k
    n = ctx->stack_top[-1];
3013
329k
    pdfi_countup(n);
3014
329k
    pdfi_pop(ctx, 1);
3015
3016
329k
    code = pdfi_setcolorspace(ctx, n, stream_dict, page_dict);
3017
3018
329k
    pdfi_countdown(n);
3019
329k
    return code;
3020
335k
}
3021
3022
3023
/*
3024
 * Set device outputintent from stream
3025
 * see zicc.c/zset_outputintent()
3026
 */
3027
static int pdfi_device_setoutputintent(pdf_context *ctx, pdf_dict *profile_dict, stream *stream)
3028
0
{
3029
0
    int code = 0;
3030
0
    gs_gstate *pgs = ctx->pgs;
3031
0
    gx_device *dev = gs_currentdevice(pgs);
3032
0
    cmm_dev_profile_t *dev_profile;
3033
0
    int64_t N;
3034
0
    int ncomps, dev_comps;
3035
0
    int expected = 0;
3036
0
    cmm_profile_t *picc_profile = NULL;
3037
0
    cmm_profile_t *source_profile = NULL;
3038
0
    gsicc_manager_t *icc_manager = pgs->icc_manager;
3039
0
    gs_color_space_index index;
3040
3041
0
    if_debug0m(gs_debug_flag_icc, ctx->memory, "[icc] Using OutputIntent\n");
3042
3043
    /* get dev_profile and try initing it if fail first time */
3044
0
    code = dev_proc(dev, get_profile)(dev, &dev_profile);
3045
0
    if (code < 0)
3046
0
        return code;
3047
3048
0
    if (dev_profile == NULL) {
3049
0
        code = gsicc_init_device_profile_struct(dev, NULL, 0);
3050
0
        if (code < 0)
3051
0
            return code;
3052
0
        code = dev_proc(dev, get_profile)(dev, &dev_profile);
3053
0
        if (code < 0)
3054
0
            return code;
3055
0
    }
3056
0
    if (dev_profile->oi_profile != NULL) {
3057
0
        return 0;  /* Allow only one setting of this object */
3058
0
    }
3059
3060
0
    code = pdfi_dict_get_int(ctx, profile_dict, "N", &N);
3061
0
    if (code < 0)
3062
0
        goto exit;
3063
0
    ncomps = (int)N;
3064
3065
0
    picc_profile = gsicc_profile_new(stream, gs_gstate_memory(pgs), NULL, 0);
3066
0
    if (picc_profile == NULL) {
3067
0
        code = gs_note_error(gs_error_VMerror);
3068
0
        goto exit;
3069
0
    }
3070
0
    picc_profile->num_comps = ncomps;
3071
0
    picc_profile->profile_handle =
3072
0
        gsicc_get_profile_handle_buffer(picc_profile->buffer,
3073
0
                                        picc_profile->buffer_size,
3074
0
                                        gs_gstate_memory(pgs));
3075
0
    if (picc_profile->profile_handle == NULL) {
3076
0
        code = gs_note_error(gs_error_VMerror);
3077
0
        goto exit;
3078
0
    }
3079
3080
0
    picc_profile->data_cs =
3081
0
        gscms_get_profile_data_space(picc_profile->profile_handle,
3082
0
            picc_profile->memory);
3083
0
    switch (picc_profile->data_cs) {
3084
0
        case gsCIEXYZ:
3085
0
        case gsCIELAB:
3086
0
        case gsRGB:
3087
0
            expected = 3;
3088
0
            source_profile = icc_manager->default_rgb;
3089
0
            break;
3090
0
        case gsGRAY:
3091
0
            expected = 1;
3092
0
            source_profile = icc_manager->default_gray;
3093
0
            break;
3094
0
        case gsCMYK:
3095
0
            expected = 4;
3096
0
            source_profile = icc_manager->default_cmyk;
3097
0
            break;
3098
0
        case gsNCHANNEL:
3099
0
            expected = 0;
3100
0
            break;
3101
0
        case gsNAMED:
3102
0
        case gsUNDEFINED:
3103
0
            break;
3104
0
    }
3105
0
    if (expected && ncomps != expected) {
3106
0
        code = gs_note_error(gs_error_rangecheck);
3107
0
        goto exit;
3108
0
    }
3109
0
    gsicc_init_hash_cs(picc_profile, pgs);
3110
3111
    /* All is well with the profile.  Lets set the stuff that needs to be set */
3112
0
    dev_profile->oi_profile = picc_profile;
3113
0
    rc_increment(picc_profile);
3114
0
    picc_profile->name = (char *) gs_alloc_bytes(picc_profile->memory,
3115
0
                                                 MAX_DEFAULT_ICC_LENGTH,
3116
0
                                                 "pdfi_color_setoutputintent");
3117
0
    if (picc_profile->name == NULL) {
3118
0
        code = gs_note_error(gs_error_VMerror);
3119
0
        goto exit;
3120
0
    }
3121
0
    strncpy(picc_profile->name, OI_PROFILE, strlen(OI_PROFILE));
3122
0
    picc_profile->name[strlen(OI_PROFILE)] = 0;
3123
0
    picc_profile->name_length = strlen(OI_PROFILE);
3124
    /* Set the range of the profile */
3125
0
    gsicc_set_icc_range(&picc_profile);
3126
3127
    /* If the output device has a different number of components, then we are
3128
       going to set the output intent as the proofing profile, unless the
3129
       proofing profile has already been set.
3130
3131
       If the device has the same number of components (and color model) then as
3132
       the profile we will use this as the output profile, unless someone has
3133
       explicitly set the output profile.
3134
3135
       Finally, we will use the output intent profile for the default profile
3136
       of the proper Device profile in the icc manager, again, unless someone
3137
       has explicitly set this default profile.
3138
3139
       All of this is skipped if we are forcing oveprint simulation with
3140
       the output intent set, in which case we will push the pdf14 device
3141
       to render directly to the the output intent color space and then
3142
       do a final transform to the target color space.
3143
    */
3144
0
    dev_comps = dev_profile->device_profile[GS_DEFAULT_DEVICE_PROFILE]->num_comps;
3145
0
    index = gsicc_get_default_type(dev_profile->device_profile[GS_DEFAULT_DEVICE_PROFILE]);
3146
3147
    /* If we are doing simulate overprint and the output intent is different than
3148
       what the device profile is the we will end up pushing the pdf14 device
3149
       and doing a rendering to the output intent color space.  Keep the device
3150
       profile as is, and do not do a proofing profile */
3151
3152
0
    if (!(ctx->pgs->device->icc_struct->overprint_control == gs_overprint_control_simulate &&
3153
0
        !gsicc_profiles_equal(dev_profile->oi_profile, dev_profile->device_profile[GS_DEFAULT_DEVICE_PROFILE]))) {
3154
0
        if (ncomps == dev_comps && index < gs_color_space_index_DevicePixel) {
3155
            /* The OI profile is the same type as the profile for the device and a
3156
               "default" profile for the device was not externally set. So we go
3157
               ahead and use the OI profile as the device profile.  Care needs to be
3158
               taken here to keep from screwing up any device parameters.   We will
3159
               use a keyword of OIProfile for the user/device parameter to indicate
3160
               its usage.  Also, note conflicts if one is setting object dependent
3161
               color management */
3162
0
            dev_profile->device_profile[GS_DEFAULT_DEVICE_PROFILE] = picc_profile;
3163
0
            rc_increment(picc_profile);
3164
0
            if_debug0m(gs_debug_flag_icc, ctx->memory, "[icc] OutputIntent used for device profile\n");
3165
0
        } else {
3166
0
            if (dev_profile->proof_profile == NULL) {
3167
                /* This means that we should use the OI profile as the proofing
3168
                   profile.  Note that if someone already has specified a
3169
                   proofing profile it is unclear what they are trying to do
3170
                   with the output intent.  In this case, we will use it
3171
                   just for the source data below */
3172
0
                dev_profile->proof_profile = picc_profile;
3173
0
                rc_increment(picc_profile);
3174
0
                if_debug0m(gs_debug_flag_icc, ctx->memory, "[icc] OutputIntent used for proof profile\n");
3175
0
            }
3176
0
        }
3177
0
    }
3178
3179
    /* Now the source colors.  See which source color space needs to use the
3180
       output intent ICC profile */
3181
0
    index = gsicc_get_default_type(source_profile);
3182
0
    if (index < gs_color_space_index_DevicePixel) {
3183
        /* source_profile is currently the default.  Set it to the OI profile */
3184
0
        switch (picc_profile->data_cs) {
3185
0
            case gsGRAY:
3186
0
                if_debug0m(gs_debug_flag_icc, ctx->memory, "[icc] OutputIntent used source Gray\n");
3187
0
                icc_manager->default_gray = picc_profile;
3188
0
                rc_increment(picc_profile);
3189
0
                break;
3190
0
            case gsRGB:
3191
0
                if_debug0m(gs_debug_flag_icc, ctx->memory, "[icc] OutputIntent used source RGB\n");
3192
0
                icc_manager->default_rgb = picc_profile;
3193
0
                rc_increment(picc_profile);
3194
0
                break;
3195
0
            case gsCMYK:
3196
0
                if_debug0m(gs_debug_flag_icc, ctx->memory, "[icc] OutputIntent used source CMYK\n");
3197
0
                icc_manager->default_cmyk = picc_profile;
3198
0
                rc_increment(picc_profile);
3199
0
                break;
3200
0
            default:
3201
0
                break;
3202
0
        }
3203
0
    }
3204
3205
0
 exit:
3206
0
    if (picc_profile != NULL)
3207
0
        rc_decrement(picc_profile, "pdfi_color_setoutputintent");
3208
0
    return code;
3209
0
}
3210
3211
/*
3212
 * intent_dict -- the outputintent dictionary
3213
 * profile -- the color profile (a stream)
3214
 *
3215
 */
3216
int pdfi_color_setoutputintent(pdf_context *ctx, pdf_dict *intent_dict, pdf_stream *profile)
3217
0
{
3218
0
    pdf_c_stream *profile_stream = NULL;
3219
0
    byte *profile_buffer;
3220
0
    int code, code1;
3221
0
    pdf_dict *profile_dict;
3222
3223
0
    code = pdfi_dict_from_obj(ctx, (pdf_obj *)profile, &profile_dict);
3224
0
    if (code < 0)
3225
0
        return code;
3226
3227
    /* The ICC profile reading code (irritatingly) requires a seekable stream, because it
3228
     * rewinds it to the start, then seeks to the end to find the size, then rewinds the
3229
     * stream again.
3230
     * Ideally we would use a ReusableStreamDecode filter here, but that is largely
3231
     * implemented in PostScript (!) so we can't use it. What we can do is create a
3232
     * string sourced stream in memory, which is at least seekable.
3233
     */
3234
0
    code = pdfi_open_memory_stream_from_filtered_stream(ctx, profile, &profile_buffer, &profile_stream, true);
3235
0
    if (code < 0)
3236
0
        goto exit;
3237
3238
    /* Create and set the device profile */
3239
0
    code = pdfi_device_setoutputintent(ctx, profile_dict, profile_stream->s);
3240
3241
0
    code1 = pdfi_close_memory_stream(ctx, profile_buffer, profile_stream);
3242
3243
0
    if (code == 0)
3244
0
        code = code1;
3245
3246
0
 exit:
3247
0
    return code;
3248
0
}
3249
3250
static int Check_Default_Space(pdf_context *ctx, pdf_obj *space, pdf_dict *source_dict, int num_components)
3251
786
{
3252
786
    pdf_obj *primary = NULL;
3253
786
    pdf_obj *ref_space = NULL;
3254
786
    int code = 0;
3255
3256
786
    if (pdfi_type_of(space) == PDF_NAME)
3257
0
    {
3258
0
        if (pdfi_name_is((const pdf_name *)space, "DeviceGray"))
3259
0
            return (num_components == 1 ? 0 : gs_error_rangecheck);
3260
0
        if (pdfi_name_is((const pdf_name *)space, "DeviceCMYK"))
3261
0
            return (num_components == 4 ? 0 : gs_error_rangecheck);
3262
0
        if (pdfi_name_is((const pdf_name *)space, "DeviceRGB"))
3263
0
            return (num_components == 3 ? 0 : gs_error_rangecheck);
3264
3265
0
        code = pdfi_find_resource(ctx, (unsigned char *)"ColorSpace", (pdf_name *)space, (pdf_dict *)source_dict,
3266
0
                                  NULL, &ref_space);
3267
0
        if (code < 0)
3268
0
            return code;
3269
3270
0
        if (pdfi_type_of(ref_space) == PDF_NAME) {
3271
0
            if (ref_space->object_num != 0 && ref_space->object_num == space->object_num) {
3272
0
                pdfi_countdown(ref_space);
3273
0
                return_error(gs_error_circular_reference);
3274
0
            }
3275
0
            if (pdfi_name_is((const pdf_name *)ref_space, "DeviceGray")) {
3276
0
                pdfi_countdown(ref_space);
3277
0
                return (num_components == 1 ? 0 : gs_error_rangecheck);
3278
0
            }
3279
0
            if (pdfi_name_is((const pdf_name *)ref_space, "DeviceCMYK")) {
3280
0
                pdfi_countdown(ref_space);
3281
0
                return (num_components == 4 ? 0 : gs_error_rangecheck);
3282
0
            }
3283
0
            if (pdfi_name_is((const pdf_name *)ref_space, "DeviceRGB")) {
3284
0
                pdfi_countdown(ref_space);
3285
0
                return (num_components == 3 ? 0 : gs_error_rangecheck);
3286
0
            }
3287
0
            pdfi_countdown(ref_space);
3288
0
            return_error(gs_error_typecheck);
3289
0
        }
3290
0
        space = ref_space;
3291
0
    }
3292
3293
786
    if (pdfi_type_of(space) == PDF_ARRAY) {
3294
772
        code = pdfi_array_get(ctx, (pdf_array *)space, 0, &primary);
3295
772
        if (code < 0)
3296
0
            goto exit;
3297
3298
772
        if (pdfi_type_of(primary) == PDF_NAME) {
3299
772
            if (pdfi_name_is((pdf_name *)primary, "Lab")) {
3300
0
                code = gs_note_error(gs_error_typecheck);
3301
0
                goto exit;
3302
0
            }
3303
772
            if (pdfi_name_is((pdf_name *)primary, "Pattern")) {
3304
3
                code = gs_note_error(gs_error_typecheck);
3305
3
                goto exit;
3306
3
            }
3307
769
            if (pdfi_name_is((pdf_name *)primary, "Indexed")) {
3308
0
                code = gs_note_error(gs_error_typecheck);
3309
0
                goto exit;
3310
0
            }
3311
769
        }
3312
772
    } else
3313
14
        code = gs_note_error(gs_error_typecheck);
3314
3315
786
exit:
3316
786
    pdfi_countdown(primary);
3317
786
    pdfi_countdown(ref_space);
3318
786
    return code;
3319
786
}
3320
3321
int pdfi_setup_DefaultSpaces(pdf_context *ctx, pdf_dict *source_dict)
3322
389k
{
3323
389k
    int code = 0;
3324
389k
    pdf_dict *resources_dict = NULL, *colorspaces_dict = NULL;
3325
389k
    pdf_obj *DefaultSpace = NULL;
3326
3327
389k
    if (ctx->args.NOSUBSTDEVICECOLORS)
3328
0
        return 0;
3329
3330
    /* Create any required DefaultGray, DefaultRGB or DefaultCMYK
3331
     * spaces.
3332
     */
3333
389k
    code = pdfi_dict_knownget(ctx, source_dict, "Resources", (pdf_obj **)&resources_dict);
3334
389k
    if (code > 0) {
3335
309k
        code = pdfi_dict_knownget(ctx, resources_dict, "ColorSpace", (pdf_obj **)&colorspaces_dict);
3336
309k
        if (code > 0) {
3337
39.6k
            code = pdfi_dict_knownget(ctx, colorspaces_dict, "DefaultGray", &DefaultSpace);
3338
39.6k
            if (code > 0) {
3339
0
                gs_color_space *pcs;
3340
3341
0
                code = Check_Default_Space(ctx, DefaultSpace, source_dict, 1);
3342
0
                if (code >= 0) {
3343
0
                    code = pdfi_create_colorspace(ctx, DefaultSpace, NULL, source_dict, &pcs, false);
3344
                    /* If any given Default* space fails simply ignore it, we wil then use the Device
3345
                     * space instead, this is as per the spec.
3346
                     */
3347
0
                    if (code >= 0) {
3348
0
                        if (gs_color_space_num_components(pcs) == 1) {
3349
0
                            ctx->page.DefaultGray_cs = pcs;
3350
0
                            pdfi_set_colour_callback(pcs, ctx, NULL);
3351
0
                        } else {
3352
0
                            rc_decrement(pcs, "setup_DefautSpaces");
3353
0
                            if ((code = pdfi_set_warning_stop(ctx, gs_note_error(gs_error_syntaxerror), NULL, W_PDF_INVALID_DEFAULTSPACE, "pdfi_setup_DefaultSpaces", NULL)) < 0)
3354
0
                                return code;
3355
0
                        }
3356
0
                    }
3357
0
                } else {
3358
0
                    if ((code = pdfi_set_warning_stop(ctx, gs_note_error(gs_error_syntaxerror), NULL, W_PDF_INVALID_DEFAULTSPACE, "pdfi_setup_DefaultSpaces", NULL)) < 0)
3359
0
                        return code;
3360
0
                }
3361
0
            }
3362
39.6k
            pdfi_countdown(DefaultSpace);
3363
39.6k
            DefaultSpace = NULL;
3364
39.6k
            code = pdfi_dict_knownget(ctx, colorspaces_dict, "DefaultRGB", &DefaultSpace);
3365
39.6k
            if (code > 0) {
3366
767
                gs_color_space *pcs;
3367
3368
767
                code = Check_Default_Space(ctx, DefaultSpace, source_dict, 1);
3369
767
                if (code >= 0) {
3370
750
                    code = pdfi_create_colorspace(ctx, DefaultSpace, NULL, source_dict, &pcs, false);
3371
                    /* If any given Default* space fails simply ignore it, we wil then use the Device
3372
                     * space instead, this is as per the spec.
3373
                     */
3374
750
                    if (code >= 0) {
3375
658
                        if (gs_color_space_num_components(pcs) == 3) {
3376
658
                            ctx->page.DefaultRGB_cs = pcs;
3377
658
                            pdfi_set_colour_callback(pcs, ctx, NULL);
3378
658
                        } else {
3379
0
                            rc_decrement(pcs, "setup_DefautSpaces");
3380
0
                            if ((code = pdfi_set_warning_stop(ctx, gs_note_error(gs_error_syntaxerror), NULL, W_PDF_INVALID_DEFAULTSPACE, "pdfi_setup_DefaultSpaces", NULL)) < 0)
3381
0
                                return code;
3382
0
                        }
3383
658
                    }
3384
750
                } else {
3385
17
                    if ((code = pdfi_set_warning_stop(ctx, gs_note_error(gs_error_syntaxerror), NULL, W_PDF_INVALID_DEFAULTSPACE, "pdfi_setup_DefaultSpaces", NULL)) < 0)
3386
0
                        return code;
3387
17
                }
3388
767
            }
3389
39.6k
            pdfi_countdown(DefaultSpace);
3390
39.6k
            DefaultSpace = NULL;
3391
39.6k
            code = pdfi_dict_knownget(ctx, colorspaces_dict, "DefaultCMYK", &DefaultSpace);
3392
39.6k
            if (code > 0) {
3393
19
                gs_color_space *pcs;
3394
3395
19
                code = Check_Default_Space(ctx, DefaultSpace, source_dict, 1);
3396
19
                if (code >= 0) {
3397
19
                    code = pdfi_create_colorspace(ctx, DefaultSpace, NULL, source_dict, &pcs, false);
3398
                    /* If any given Default* space fails simply ignore it, we wil then use the Device
3399
                     * space instead, this is as per the spec.
3400
                     */
3401
19
                    if (code >= 0) {
3402
19
                        if (gs_color_space_num_components(pcs) == 4) {
3403
19
                            ctx->page.DefaultCMYK_cs = pcs;
3404
19
                            pdfi_set_colour_callback(pcs, ctx, NULL);
3405
19
                        } else {
3406
0
                            rc_decrement(pcs, "setup_DefautSpaces");
3407
0
                            if ((code = pdfi_set_warning_stop(ctx, gs_note_error(gs_error_syntaxerror), NULL, W_PDF_INVALID_DEFAULTSPACE, "pdfi_setup_DefaultSpaces", NULL)) < 0)
3408
0
                                return code;
3409
0
                        }
3410
19
                    }
3411
19
                } else {
3412
0
                    if ((code = pdfi_set_warning_stop(ctx, gs_note_error(gs_error_syntaxerror), NULL, W_PDF_INVALID_DEFAULTSPACE, "pdfi_setup_DefaultSpaces", NULL)) < 0)
3413
0
                        return code;
3414
0
                }
3415
19
            }
3416
39.6k
            pdfi_countdown(DefaultSpace);
3417
39.6k
            DefaultSpace = NULL;
3418
39.6k
        }
3419
309k
    }
3420
3421
389k
    pdfi_countdown(DefaultSpace);
3422
389k
    pdfi_countdown(resources_dict);
3423
389k
    pdfi_countdown(colorspaces_dict);
3424
389k
    return 0;
3425
389k
}