Coverage Report

Created: 2026-02-14 07:09

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