Coverage Report

Created: 2022-10-31 07:00

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