Coverage Report

Created: 2026-04-09 07:06

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