Coverage Report

Created: 2025-06-24 07:01

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