Coverage Report

Created: 2026-04-01 07:17

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.9k
{
65
18.9k
    pdf_obj *ref_space;
66
18.9k
    int code;
67
68
18.9k
    if (pdfi_name_is(name, "G")) {
69
0
        return 0;
70
18.9k
    } else if (pdfi_name_is(name, "RGB")) {
71
0
        return 0;
72
18.9k
    } else if (pdfi_name_is(name, "CMYK")) {
73
0
        return 0;
74
18.9k
    } else if (pdfi_name_is(name, "DeviceRGB")) {
75
15.8k
        return 0;
76
15.8k
    } else if (pdfi_name_is(name, "DeviceGray")) {
77
1.70k
        return 0;
78
1.70k
    } else if (pdfi_name_is(name, "DeviceCMYK")) {
79
1.09k
        return 0;
80
1.09k
    } else if (pdfi_name_is(name, "Pattern")) {
81
        /* TODO: I think this is fine... */
82
232
        return 0;
83
232
    } 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.9k
}
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
14.1k
{
104
14.1k
    pdf_name *space = NULL;
105
14.1k
    pdf_array *a = NULL;
106
14.1k
    int code = 0;
107
108
14.1k
    if (!spot_dict)
109
0
        return 0;
110
111
14.1k
    code = pdfi_array_get_type(ctx, color_array, 0, PDF_NAME, (pdf_obj **)&space);
112
14.1k
    if (code != 0)
113
24
        goto exit;
114
115
14.1k
    code = 0;
116
14.1k
    if (pdfi_name_is(space, "G")) {
117
0
        goto exit;
118
14.1k
    } else if (pdfi_name_is(space, "I") || pdfi_name_is(space, "Indexed")) {
119
2.89k
        pdf_obj *base_space;
120
121
2.89k
        code = pdfi_array_get(ctx, color_array, 1, &base_space);
122
2.89k
        if (code == 0) {
123
2.84k
            code = pdfi_check_ColorSpace_for_spots(ctx, base_space, parent_dict, page_dict, spot_dict);
124
2.84k
            (void)pdfi_countdown(base_space);
125
2.84k
        }
126
2.89k
        goto exit;
127
11.2k
    } else if (pdfi_name_is(space, "Pattern")) {
128
698
        pdf_obj *base_space = NULL;
129
698
        uint64_t size = pdfi_array_size(color_array);
130
131
        /* Array of size 1 "[ /Pattern ]" is okay, just do nothing. */
132
698
        if (size == 1)
133
462
            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
10.5k
    } else if (pdfi_name_is(space, "Lab")) {
149
232
        goto exit;
150
10.3k
    } else if (pdfi_name_is(space, "RGB")) {
151
0
        goto exit;
152
10.3k
    } else if (pdfi_name_is(space, "CMYK")) {
153
0
        goto exit;
154
10.3k
    } else if (pdfi_name_is(space, "CalRGB")) {
155
364
        goto exit;
156
9.95k
    } else if (pdfi_name_is(space, "CalGray")) {
157
68
        goto exit;
158
9.88k
    } else if (pdfi_name_is(space, "CalCMYK")) {
159
0
        goto exit;
160
9.88k
    } else if (pdfi_name_is(space, "ICCBased")) {
161
7.96k
        goto exit;
162
7.96k
    } else if (pdfi_name_is(space, "DeviceRGB")) {
163
2
        goto exit;
164
1.92k
    } else if (pdfi_name_is(space, "DeviceGray")) {
165
0
        goto exit;
166
1.92k
    } else if (pdfi_name_is(space, "DeviceCMYK")) {
167
0
        goto exit;
168
1.92k
    } else if (pdfi_name_is(space, "DeviceN")) {
169
512
        bool known = false;
170
512
        pdf_obj *dummy, *name;
171
512
        int i;
172
173
512
        pdfi_countdown(space);
174
512
        code = pdfi_array_get_type(ctx, color_array, 1, PDF_ARRAY, (pdf_obj **)&space);
175
512
        if (code != 0)
176
4
            goto exit;
177
178
1.67k
        for (i=0;i < pdfi_array_size((pdf_array *)space); i++) {
179
1.16k
            code = pdfi_array_get_type(ctx, (pdf_array *)space, (uint64_t)i, PDF_NAME, &name);
180
1.16k
            if (code < 0)
181
0
                goto exit;
182
183
1.16k
            if (pdfi_name_is((const pdf_name *)name, "Cyan") || pdfi_name_is((const pdf_name *)name, "Magenta") ||
184
964
                pdfi_name_is((const pdf_name *)name, "Yellow") || pdfi_name_is((const pdf_name *)name, "Black") ||
185
642
                pdfi_name_is((const pdf_name *)name, "None") || pdfi_name_is((const pdf_name *)name, "All")) {
186
187
536
                pdfi_countdown(name);
188
536
                continue;
189
536
            }
190
191
630
            code = pdfi_dict_known_by_key(ctx, spot_dict, (pdf_name *)name, &known);
192
630
            if (code < 0) {
193
0
                pdfi_countdown(name);
194
0
                goto exit;
195
0
            }
196
630
            if (known) {
197
50
                pdfi_countdown(name);
198
50
                continue;
199
50
            }
200
201
580
            code = pdfi_object_alloc(ctx, PDF_INT, 0, &dummy);
202
580
            if (code < 0)
203
0
                goto exit;
204
205
580
            code = pdfi_dict_put_obj(ctx, spot_dict, name, dummy, true);
206
580
            pdfi_countdown(name);
207
580
            if (code < 0)
208
0
                break;
209
580
        }
210
508
        goto exit;
211
1.40k
    } else if (pdfi_name_is(space, "Separation")) {
212
1.35k
        bool known = false;
213
1.35k
        pdf_obj *dummy;
214
215
1.35k
        pdfi_countdown(space);
216
1.35k
        code = pdfi_array_get_type(ctx, color_array, 1, PDF_NAME, (pdf_obj **)&space);
217
1.35k
        if (code != 0)
218
0
            goto exit;
219
220
1.35k
        if (pdfi_name_is((const pdf_name *)space, "Cyan") || pdfi_name_is((const pdf_name *)space, "Magenta") ||
221
1.35k
            pdfi_name_is((const pdf_name *)space, "Yellow") || pdfi_name_is((const pdf_name *)space, "Black") ||
222
344
            pdfi_name_is((const pdf_name *)space, "None") || pdfi_name_is((const pdf_name *)space, "All"))
223
1.01k
            goto exit;
224
344
        code = pdfi_dict_known_by_key(ctx, spot_dict, space, &known);
225
344
        if (code < 0 || known)
226
96
            goto exit;
227
228
248
        code = pdfi_object_alloc(ctx, PDF_INT, 0, &dummy);
229
248
        if (code < 0)
230
0
            goto exit;
231
232
248
        code = pdfi_dict_put_obj(ctx, spot_dict, (pdf_obj *)space, dummy, true);
233
248
        goto exit;
234
248
    } else {
235
54
        code = pdfi_find_resource(ctx, (unsigned char *)"ColorSpace",
236
54
                                  space, parent_dict, page_dict, (pdf_obj **)&a);
237
54
        if (code < 0)
238
50
            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
14.1k
 exit:
254
14.1k
    if (space)
255
14.1k
        pdfi_countdown(space);
256
14.1k
    if (a)
257
4
        pdfi_countdown(a);
258
14.1k
    return code;
259
14.1k
}
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
33.4k
{
264
33.4k
    int code;
265
266
33.4k
    if (!spot_dict)
267
0
        return 0;
268
269
33.4k
    code = pdfi_loop_detector_mark(ctx);
270
33.4k
    if (code < 0)
271
0
        return code;
272
273
33.4k
    switch(pdfi_type_of(space)) {
274
18.9k
        case PDF_NAME:
275
18.9k
            code = pdfi_check_for_spots_by_name(ctx, (pdf_name *)space, parent_dict, page_dict, spot_dict);
276
18.9k
            break;
277
14.1k
        case PDF_ARRAY:
278
14.1k
            code = pdfi_check_for_spots_by_array(ctx, (pdf_array *)space, parent_dict, page_dict, spot_dict);
279
14.1k
            break;
280
312
        default:
281
312
            pdfi_loop_detector_cleartomark(ctx);
282
312
            return 0;
283
33.4k
    }
284
285
33.1k
    (void)pdfi_loop_detector_cleartomark(ctx);
286
33.1k
    return code;
287
33.4k
}
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
83.2k
{
294
83.2k
    pdf_name *n;
295
83.2k
    int code;
296
297
83.2k
    if (pdfi_count_stack(ctx) < 1)
298
14.4k
        return_error(gs_error_stackunderflow);
299
300
68.7k
    if (pdfi_type_of(ctx->stack_top[-1]) != PDF_NAME) {
301
2.41k
        pdfi_pop(ctx, 1);
302
2.41k
        return_error(gs_error_typecheck);
303
2.41k
    }
304
66.3k
    n = (pdf_name *)ctx->stack_top[-1];
305
66.3k
    pdfi_countup(n);
306
66.3k
    pdfi_pop(ctx, 1);
307
66.3k
    code = pdfi_setrenderingintent(ctx, n);
308
66.3k
    pdfi_countdown(n);
309
66.3k
    return code;
310
68.7k
}
311
312
/*
313
 * Pattern lifetime management turns out to be more complex than we would ideally like. Although
314
 * Patterns are reference counted, and contain a client_data pointer, they don't have a gs_notify
315
 * setup. This means that there's no simlpe way for us to be informed when a Pattern is released
316
 * We could patch up the Pattern finalize() method, replacing it with one of our own which calls
317
 * the original finalize() but that seems like a really nasty hack.
318
 * For the time being we put code in pdfi_grestore() to check for Pattern colour spaces being
319
 * restored away, but we also need to check for Pattern spaces being replaced in the current
320
 * graphics state. We define 'pdfi' variants of several graphics library colour management
321
 * functions to 'wrap' these with code to check for replacement of Patterns.
322
 * This comment is duplicated in pdf_pattern.c
323
 */
324
325
static void pdfi_cspace_free_callback(gs_memory_t * mem, void *cs)
326
1.38M
{
327
1.38M
    gs_color_space *pcs = (gs_color_space *)cs;
328
1.38M
    pdf_obj *o = (pdf_obj *)pcs->interpreter_data;
329
1.38M
    pdf_context *ctx = NULL;
330
1.38M
    gs_function_t *pfn;
331
332
1.38M
    if (o == NULL)
333
78
        return;
334
335
1.38M
    ctx = o->ctx;
336
337
1.38M
    if (gs_color_space_get_index(pcs) == gs_color_space_index_Separation) {
338
        /* Handle cleanup of Separation functions if applicable */
339
24.7k
        pfn = gs_cspace_get_sepr_function(pcs);
340
24.7k
        if (pfn)
341
24.7k
            pdfi_free_function(ctx, pfn);
342
24.7k
    }
343
344
1.38M
    if (gs_color_space_get_index(pcs) == gs_color_space_index_DeviceN) {
345
        /* Handle cleanup of DeviceN functions if applicable */
346
3.06k
        pfn = gs_cspace_get_devn_function(pcs);
347
3.06k
        if (pfn)
348
3.06k
            pdfi_free_function(ctx, pfn);
349
3.06k
    }
350
1.38M
    if (pdfi_type_of(o) != PDF_CTX) {
351
45.5k
        pdfi_countdown(o);
352
45.5k
        pcs->interpreter_data = NULL;
353
45.5k
    }
354
1.38M
}
355
356
int pdfi_gs_setgray(pdf_context *ctx, double d)
357
1.28M
{
358
1.28M
    int code = 0;
359
1.28M
    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.28M
    if (ctx->text.inside_CharProc && ctx->text.CharProc_d_type != pdf_type3_d0) {
363
13.0k
        pdfi_log_info(ctx, "pdfi_gs_setgray", "colour operator in a CharProc, following a d1 ignored\n");
364
13.0k
        return 0;
365
13.0k
    }
366
367
1.27M
    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.27M
    } else {
382
1.27M
        code = gs_setgray(ctx->pgs, d);
383
1.27M
        if (code < 0)
384
12
            return code;
385
1.27M
    }
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.27M
    if (pcs != ctx->pgs->color[0].color_space)
390
551k
        pdfi_set_colour_callback(ctx->pgs->color[0].color_space, ctx, pdfi_cspace_free_callback);
391
1.27M
    return 0;
392
1.27M
}
393
394
int pdfi_gs_setrgbcolor(pdf_context *ctx, double r, double g, double b)
395
1.87M
{
396
1.87M
    int code = 0;
397
1.87M
    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.87M
    if (ctx->text.inside_CharProc && ctx->text.CharProc_d_type != pdf_type3_d0) {
401
309
        pdfi_log_info(ctx, "pdfi_gs_setrgbcolor", "colour operator in a CharProc, following a d1 ignored\n");
402
309
        return 0;
403
309
    }
404
405
1.87M
    if (ctx->page.DefaultRGB_cs != NULL) {
406
13.8k
        gs_client_color cc;
407
408
13.8k
        code = gs_setcolorspace(ctx->pgs, ctx->page.DefaultRGB_cs);
409
13.8k
        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
13.8k
        if (pcs != ctx->pgs->color[0].color_space)
415
4.77k
            pdfi_set_colour_callback(ctx->pgs->color[0].color_space, ctx, pdfi_cspace_free_callback);
416
13.8k
        cc.paint.values[0] = r;
417
13.8k
        cc.paint.values[1] = g;
418
13.8k
        cc.paint.values[2] = b;
419
13.8k
        cc.pattern = 0;
420
13.8k
        return gs_setcolor(ctx->pgs, &cc);
421
1.86M
    } else {
422
1.86M
        code = gs_setrgbcolor(ctx->pgs, r, g, b);
423
1.86M
        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.86M
        if (pcs != ctx->pgs->color[0].color_space)
429
550k
            pdfi_set_colour_callback(ctx->pgs->color[0].color_space, ctx, pdfi_cspace_free_callback);
430
1.86M
    }
431
1.86M
    return 0;
432
1.87M
}
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
68.0k
            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
253k
{
477
253k
    gs_color_space *old_pcs = ctx->pgs->color[0].color_space;
478
253k
    int code = 0;
479
    /* If the target colour space is already the current colour space, don't
480
     * bother to do anything.
481
     */
482
253k
    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
234k
        if (ctx->text.inside_CharProc && ctx->text.CharProc_d_type != pdf_type3_d0) {
485
2
            pdfi_log_info(ctx, "pdfi_gs_setcolorspace", "colour operator in a CharProc, following a d1 ignored\n");
486
2
            return 0;
487
2
        }
488
489
234k
        code = gs_setcolorspace(ctx->pgs, pcs);
490
234k
        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
234k
        if (old_pcs != ctx->pgs->color[0].color_space)
496
234k
            pdfi_set_colour_callback(ctx->pgs->color[0].color_space, ctx, pdfi_cspace_free_callback);
497
234k
    }
498
253k
    return 0;
499
253k
}
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
583k
{
504
583k
    int code;
505
583k
    double d1;
506
507
583k
    code = pdfi_destack_real(ctx, &d1);
508
583k
    if (code < 0)
509
24.6k
        return code;
510
511
558k
    gs_swapcolors_quick(ctx->pgs);
512
558k
    code = pdfi_gs_setgray(ctx, d1);
513
558k
    gs_swapcolors_quick(ctx->pgs);
514
515
558k
    return code;
516
583k
}
517
518
int pdfi_setgrayfill(pdf_context *ctx)
519
704k
{
520
704k
    int code;
521
704k
    double d1;
522
523
704k
    code = pdfi_destack_real(ctx, &d1);
524
704k
    if (code < 0)
525
11.6k
        return code;
526
527
693k
    return pdfi_gs_setgray(ctx, d1);
528
704k
}
529
530
int pdfi_setrgbstroke(pdf_context *ctx)
531
906k
{
532
906k
    double Values[3];
533
906k
    int code;
534
535
906k
    code = pdfi_destack_reals(ctx, Values, 3);
536
906k
    if (code < 0)
537
49.8k
        return code;
538
539
857k
    gs_swapcolors_quick(ctx->pgs);
540
857k
    code = pdfi_gs_setrgbcolor(ctx, Values[0], Values[1], Values[2]);
541
857k
    gs_swapcolors_quick(ctx->pgs);
542
543
857k
    return code;
544
906k
}
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
56.8k
{
551
56.8k
    int code;
552
56.8k
    pdf_array *array = NULL;
553
554
56.8k
    pdfi_set_warning(ctx, 0, NULL, W_PDF_NONSTANDARD_OP, "pdfi_setrgbfill_array", (char *)"WARNING: Non-standard 'r' operator");
555
556
56.8k
    if (pdfi_count_stack(ctx) < 1)
557
12.5k
        return_error(gs_error_stackunderflow);
558
559
44.2k
    array = (pdf_array *)ctx->stack_top[-1];
560
44.2k
    pdfi_countup(array);
561
44.2k
    pdfi_pop(ctx, 1);
562
44.2k
    if (pdfi_type_of(array) != PDF_ARRAY) {
563
44.1k
        code = gs_note_error(gs_error_typecheck);
564
44.1k
        goto exit;
565
44.1k
    }
566
567
63
    code = pdfi_setcolor_from_array(ctx, array);
568
44.2k
 exit:
569
44.2k
    pdfi_countdown(array);
570
44.2k
    return code;
571
63
}
572
573
int pdfi_setrgbfill(pdf_context *ctx)
574
1.03M
{
575
1.03M
    double Values[3];
576
1.03M
    int code;
577
578
1.03M
    code = pdfi_destack_reals(ctx, Values, 3);
579
1.03M
    if (code < 0)
580
36.7k
        return code;
581
582
995k
    return pdfi_gs_setrgbcolor(ctx, Values[0], Values[1], Values[2]);
583
1.03M
}
584
585
int pdfi_setcmykstroke(pdf_context *ctx)
586
41.1k
{
587
41.1k
    double Values[4];
588
41.1k
    int code;
589
590
41.1k
    code = pdfi_destack_reals(ctx, Values, 4);
591
41.1k
    if (code < 0)
592
8.99k
        return code;
593
594
32.1k
    gs_swapcolors_quick(ctx->pgs);
595
32.1k
    code = pdfi_gs_setcmykcolor(ctx, Values[0], Values[1], Values[2], Values[3]);
596
32.1k
    gs_swapcolors_quick(ctx->pgs);
597
598
32.1k
    return code;
599
41.1k
}
600
601
int pdfi_setcmykfill(pdf_context *ctx)
602
140k
{
603
140k
    double Values[4];
604
140k
    int code;
605
606
140k
    code = pdfi_destack_reals(ctx, Values, 4);
607
140k
    if (code < 0)
608
12.2k
        return code;
609
610
128k
    return pdfi_gs_setcmykcolor(ctx, Values[0], Values[1], Values[2], Values[3]);
611
140k
}
612
613
/* Do a setcolor using values in an array
614
 * Will do gray, rgb, cmyk for sizes 1,3,4
615
 * Anything else is an error
616
 */
617
int pdfi_setcolor_from_array(pdf_context *ctx, pdf_array *array)
618
6.80k
{
619
6.80k
    int code = 0;
620
6.80k
    uint64_t size;
621
6.80k
    double values[4];
622
623
6.80k
    size = pdfi_array_size(array);
624
6.80k
    if (size != 1 && size != 3 && size != 4) {
625
73
        code = gs_note_error(gs_error_rangecheck);
626
73
        goto exit;
627
73
    }
628
629
6.73k
    code = pdfi_array_to_num_array(ctx, array, values, 0, size);
630
6.73k
    if (code < 0) goto exit;
631
632
6.70k
    switch (size) {
633
261
    case 1:
634
261
        code = pdfi_gs_setgray(ctx, values[0]);
635
261
        break;
636
6.43k
    case 3:
637
6.43k
        code = pdfi_gs_setrgbcolor(ctx, values[0], values[1], values[2]);
638
6.43k
        break;
639
14
    case 4:
640
14
        code = pdfi_gs_setcmykcolor(ctx, values[0], values[1], values[2], values[3]);
641
14
        break;
642
0
    default:
643
0
        break;
644
6.70k
    }
645
646
6.80k
 exit:
647
6.80k
    return code;
648
6.70k
}
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
274k
{
654
274k
    int i, code;
655
656
274k
    if (pdfi_count_stack(ctx) < ncomps) {
657
17.5k
        pdfi_clearstack(ctx);
658
17.5k
        return_error(gs_error_stackunderflow);
659
17.5k
    }
660
661
785k
    for (i = 0; i < ncomps; i++) {
662
539k
        code = pdfi_obj_to_float(ctx, ctx->stack_top[i - ncomps], &cc->paint.values[i]);
663
539k
        if (code < 0) {
664
11.8k
            pdfi_clearstack(ctx);
665
11.8k
            return code;
666
11.8k
        }
667
539k
    }
668
245k
    pdfi_pop(ctx, ncomps);
669
670
245k
    return 0;
671
256k
}
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
34.4k
{
683
34.4k
    const gs_color_space *  pcs;
684
34.4k
    int ncomps, code;
685
34.4k
    gs_client_color cc;
686
687
34.4k
    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
34.4k
    cc.pattern = 0;
698
34.4k
    gs_swapcolors_quick(ctx->pgs);
699
34.4k
    pcs = gs_currentcolorspace(ctx->pgs);
700
34.4k
    ncomps = cs_num_components(pcs);
701
34.4k
    if (ncomps < 1) {
702
3
        gs_swapcolors_quick(ctx->pgs);
703
3
        return_error(gs_error_syntaxerror);
704
3
    }
705
34.4k
    code = pdfi_get_color_from_stack(ctx, &cc, ncomps);
706
34.4k
    if (code == 0) {
707
32.4k
        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
32.4k
        code = gs_setcolor(ctx->pgs, &cc);
722
32.4k
    }
723
34.4k
    gs_swapcolors_quick(ctx->pgs);
724
34.4k
    return code;
725
34.4k
}
726
727
int pdfi_setfillcolor(pdf_context *ctx)
728
155k
{
729
155k
    const gs_color_space *  pcs = gs_currentcolorspace(ctx->pgs);
730
155k
    int ncomps, code;
731
155k
    gs_client_color cc;
732
733
155k
    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
155k
    cc.pattern = 0;
744
155k
    ncomps = cs_num_components(pcs);
745
155k
    if (ncomps < 1)
746
219
        return_error(gs_error_syntaxerror);
747
154k
    code = pdfi_get_color_from_stack(ctx, &cc, ncomps);
748
154k
    if (code == 0) {
749
146k
        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
124
            int index = (int)floor(cc.paint.values[0]);
758
759
124
            if(cc.paint.values[0] - index > 0.49999)
760
2
                index++;
761
124
            cc.paint.values[0] = (float)index;
762
124
        }
763
146k
        code = gs_setcolor(ctx->pgs, &cc);
764
146k
    }
765
154k
    return code;
766
155k
}
767
768
static inline bool
769
pattern_instance_uses_base_space(const gs_pattern_instance_t * pinst)
770
280
{
771
280
    return pinst->type->procs.uses_base_space(
772
280
                   pinst->type->procs.get_pattern(pinst) );
773
280
}
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
146k
{
781
146k
    gs_color_space *pcs;
782
146k
    gs_color_space *base_space = NULL;
783
146k
    int ncomps=0, code = 0;
784
146k
    gs_client_color cc;
785
146k
    bool is_pattern = false;
786
787
146k
    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
146k
    if (!is_fill) {
798
12.9k
        gs_swapcolors_quick(ctx->pgs);
799
12.9k
    }
800
146k
    pcs = gs_currentcolorspace(ctx->pgs);
801
802
146k
    if (pdfi_count_stack(ctx) < 1) {
803
1.51k
        code = gs_note_error(gs_error_stackunderflow);
804
1.51k
        goto cleanupExit1;
805
1.51k
    }
806
807
145k
    memset(&cc, 0x00, sizeof(gs_client_color));
808
809
145k
    if (pcs->type == &gs_color_space_type_Pattern)
810
60.2k
        is_pattern = true;
811
145k
    if (is_pattern) {
812
60.2k
        pdf_name *n = NULL;
813
814
60.2k
        if (pdfi_type_of(ctx->stack_top[-1]) != PDF_NAME) {
815
106
            pdfi_clearstack(ctx);
816
106
            code = gs_note_error(gs_error_typecheck);
817
106
            goto cleanupExit0;
818
106
        }
819
60.1k
        n = (pdf_name *)ctx->stack_top[-1];
820
60.1k
        pdfi_countup(n);
821
60.1k
        pdfi_pop(ctx, 1);
822
823
60.1k
        base_space = pcs->base_space;
824
60.1k
        code = pdfi_pattern_set(ctx, stream_dict, page_dict, n, &cc);
825
60.1k
        pdfi_countdown(n);
826
60.1k
        if (code < 0) {
827
            /* Ignore the pattern if we failed to set it */
828
39.8k
            code = pdfi_set_warning_stop(ctx, code, NULL, W_PDF_BADPATTERN, "pdfi_setcolorN", (char *)"PATTERN: Error setting pattern");
829
39.8k
            goto cleanupExit1;
830
39.8k
        }
831
20.3k
        if (base_space && pattern_instance_uses_base_space(cc.pattern))
832
268
            ncomps = cs_num_components(base_space);
833
20.1k
        else
834
20.1k
            ncomps = 0;
835
20.3k
    } else
836
85.0k
        ncomps = cs_num_components(pcs);
837
838
105k
    if (ncomps > 0) {
839
85.3k
        code = pdfi_get_color_from_stack(ctx, &cc, ncomps);
840
85.3k
        if (code < 0)
841
18.5k
            goto cleanupExit1;
842
85.3k
    }
843
844
86.8k
    if (pcs->type == &gs_color_space_type_Indexed) {
845
0
        if (ncomps <= 0)
846
0
        {
847
0
            code = gs_note_error(gs_error_rangecheck);
848
0
            goto cleanupExit1;
849
0
        }
850
0
        if (cc.paint.values[0] < 0)
851
0
            cc.paint.values[0] = 0.0;
852
0
        else
853
0
        {
854
0
            if (cc.paint.values[0] > pcs->params.indexed.hival)
855
0
                cc.paint.values[0] = (float)pcs->params.indexed.hival;
856
0
            else
857
0
            {
858
0
                if (cc.paint.values[0] != floor(cc.paint.values[0]))
859
0
                {
860
0
                    if (cc.paint.values[0] - floor(cc.paint.values[0]) < 0.5)
861
0
                        cc.paint.values[0] = floor(cc.paint.values[0]);
862
0
                    else
863
0
                        cc.paint.values[0] = ceil(cc.paint.values[0]);
864
0
                }
865
0
            }
866
0
        }
867
0
    }
868
869
86.8k
    code = gs_setcolor(ctx->pgs, &cc);
870
871
146k
cleanupExit1:
872
146k
    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
146k
        rc_decrement(cc.pattern, "pdfi_setcolorN");
878
879
146k
cleanupExit0:
880
146k
    if (!is_fill)
881
12.9k
        gs_swapcolors_quick(ctx->pgs);
882
146k
    return code;
883
146k
}
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
29.4k
{
892
29.4k
    int                     code, k;
893
29.4k
    gs_color_space *        pcs;
894
29.4k
    cmm_profile_t           *picc_profile = NULL;
895
29.4k
    int                     i, expected = 0;
896
897
29.4k
    static const char *const icc_std_profile_names[] = {
898
29.4k
            GSICC_STANDARD_PROFILES
899
29.4k
        };
900
29.4k
    static const char *const icc_std_profile_keys[] = {
901
29.4k
            GSICC_STANDARD_PROFILES_KEYS
902
29.4k
        };
903
904
29.4k
    if (ppcs!= NULL)
905
29.4k
        *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
29.4k
    code = gs_cspace_build_ICC(&pcs, NULL, (gs_gstate_memory(ctx->pgs))->stable_memory);
912
29.4k
    if (code < 0)
913
0
        return code;
914
915
29.4k
    if (Name != NULL){
916
        /* Compare this to the standard profile names */
917
9.02k
        for (k = 0; k < GSICC_NUMBER_STANDARD_PROFILES; k++) {
918
9.02k
            if ( strcmp( Name, icc_std_profile_keys[k] ) == 0 ) {
919
4.77k
                picc_profile = gsicc_get_profile_handle_file(icc_std_profile_names[k],
920
4.77k
                    strlen(icc_std_profile_names[k]), gs_gstate_memory(ctx->pgs));
921
4.77k
                break;
922
4.77k
            }
923
9.02k
        }
924
24.6k
    } else {
925
24.6k
        if (s == NULL)
926
0
            return_error(gs_error_undefined);
927
928
24.6k
        picc_profile = gsicc_profile_new(s, gs_gstate_memory(ctx->pgs), NULL, 0);
929
24.6k
        if (picc_profile == NULL) {
930
4.65k
            rc_decrement(pcs,"pdfi_create_icc");
931
4.65k
            return gs_throw(gs_error_VMerror, "pdfi_create_icc Creation of ICC profile failed");
932
4.65k
        }
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
19.9k
        picc_profile->profile_handle =
936
19.9k
            gsicc_get_profile_handle_buffer(picc_profile->buffer,
937
19.9k
                                            picc_profile->buffer_size,
938
19.9k
                                            gs_gstate_memory(ctx->pgs));
939
19.9k
    }
940
941
24.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.61k
        rc_decrement(picc_profile,"pdfi_create_icc");
945
2.61k
        rc_decrement(pcs,"pdfi_create_icc");
946
2.61k
        return -1;
947
2.61k
    }
948
22.1k
    code = gsicc_set_gscs_profile(pcs, picc_profile, gs_gstate_memory(ctx->pgs));
949
22.1k
    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
22.1k
    picc_profile->data_cs =
956
22.1k
        gscms_get_profile_data_space(picc_profile->profile_handle,
957
22.1k
            picc_profile->memory);
958
22.1k
    switch (picc_profile->data_cs) {
959
0
        case gsCIEXYZ:
960
0
        case gsCIELAB:
961
13.5k
        case gsRGB:
962
13.5k
            expected = 3;
963
13.5k
            break;
964
8.36k
        case gsGRAY:
965
8.36k
            expected = 1;
966
8.36k
            break;
967
27
        case gsCMYK:
968
27
            expected = 4;
969
27
            break;
970
202
        case gsNCHANNEL:
971
202
        case gsNAMED:            /* Silence warnings */
972
202
        case gsUNDEFINED:        /* Silence warnings */
973
202
            break;
974
22.1k
    }
975
22.1k
    if (expected == 0) {
976
202
        rc_decrement(picc_profile,"pdfi_create_icc");
977
202
        rc_decrement(pcs,"pdfi_create_icc");
978
202
        return_error(gs_error_rangecheck);
979
202
    }
980
    /* Return the number of components the ICC profile has */
981
21.9k
    *icc_N = expected;
982
21.9k
    if (expected != ncomps) {
983
18
        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
18
        ncomps = expected;
986
18
    }
987
988
21.9k
    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
21.9k
    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
21.9k
    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
21.9k
    } else {
1020
71.0k
        for (i = 0; i < ncomps; i++) {
1021
49.0k
            picc_profile->Range.ranges[i].rmin = range_buff[2 * i];
1022
49.0k
            picc_profile->Range.ranges[i].rmax = range_buff[2 * i + 1];
1023
49.0k
        }
1024
21.9k
    }
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
21.9k
    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
21.9k
    if (dictkey != 0) {
1049
17.1k
        code = gsicc_add_cs(ctx->pgs, pcs, dictkey);
1050
17.1k
        if (code < 0)
1051
0
            goto exit;
1052
17.1k
    }
1053
1054
21.9k
    if (ppcs!= NULL){
1055
21.9k
        *ppcs = pcs;
1056
21.9k
        pdfi_set_colour_callback(pcs, ctx, pdfi_cspace_free_callback);
1057
21.9k
    } else {
1058
0
        code = pdfi_gs_setcolorspace(ctx, pcs);
1059
0
        rc_decrement_only_cs(pcs, "pdfi_create_icc");
1060
0
    }
1061
1062
21.9k
exit:
1063
    /* The context has taken a reference to the colorspace. We no longer need
1064
     * ours, so drop it. */
1065
21.9k
    rc_decrement(picc_profile, "pdfi_create_icc");
1066
21.9k
    return code;
1067
21.9k
}
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
99.8k
{
1072
99.8k
    pdf_c_stream *profile_stream = NULL;
1073
99.8k
    byte *profile_buffer;
1074
99.8k
    int code, code1;
1075
99.8k
    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
99.8k
    if (!gs_currentoverrideicc(ctx->pgs)) {
1084
99.8k
        if (ICC_obj->object_num != 0) {
1085
99.8k
            gs_color_space *pcs = NULL;
1086
1087
99.8k
            pcs = gsicc_find_cs(ICC_obj->object_num, ctx->pgs);
1088
99.8k
            if (pcs != NULL) {
1089
74.9k
                if (ppcs!= NULL){
1090
74.9k
                    *ppcs = pcs;
1091
74.9k
                } else {
1092
0
                    code = pdfi_gs_setcolorspace(ctx, pcs);
1093
0
                    rc_decrement_only_cs(pcs, "pdfi_create_iccprofile");
1094
0
                }
1095
74.9k
                *icc_N = gs_color_space_num_components(pcs);
1096
                /* We're passing back a new reference, increment the count */
1097
74.9k
                rc_adjust_only(pcs, 1, "pdfi_create_iccprofile, return cached ICC profile");
1098
74.9k
                return 0;
1099
74.9k
            }
1100
24.8k
            dictkey = ICC_obj->object_num;
1101
24.8k
        }
1102
99.8k
    }
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
24.8k
    code = pdfi_open_memory_stream_from_filtered_stream(ctx, ICC_obj, &profile_buffer, &profile_stream, true);
1112
24.8k
    if (code < 0) {
1113
255
        return code;
1114
255
    }
1115
1116
    /* Now, finally, we can call the code to create and set the profile */
1117
24.6k
    code = pdfi_create_icc(ctx, cname, profile_stream->s, (int)N, icc_N, range, dictkey, ppcs);
1118
1119
24.6k
    code1 = pdfi_close_memory_stream(ctx, profile_buffer, profile_stream);
1120
1121
24.6k
    if (code == 0)
1122
17.1k
        code = code1;
1123
1124
24.6k
    return code;
1125
24.8k
}
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
112k
{
1402
112k
    pdf_stream *ICC_obj = NULL;
1403
112k
    pdf_dict *dict; /* Alias to avoid tons of casting */
1404
112k
    pdf_array *a;
1405
112k
    int64_t Length, N;
1406
112k
    pdf_obj *Name = NULL, *Alt = NULL;
1407
112k
    char *cname = NULL;
1408
112k
    int code;
1409
112k
    bool known = true;
1410
112k
    float range[8];
1411
112k
    int icc_N;
1412
112k
    gs_color_space *pcs = NULL;
1413
1414
112k
    code = pdfi_array_get_type(ctx, color_array, index + 1, PDF_STREAM, (pdf_obj **)&ICC_obj);
1415
112k
    if (code < 0)
1416
10.7k
        return code;
1417
101k
    code = pdfi_dict_from_obj(ctx, (pdf_obj *)ICC_obj, &dict);
1418
101k
    if (code < 0)
1419
0
        return code;
1420
1421
101k
    Length = pdfi_stream_length(ctx, ICC_obj);
1422
101k
    code = pdfi_dict_get_int(ctx, dict, "N", &N);
1423
101k
    if (code < 0)
1424
1.04k
        goto done;
1425
100k
    if (N != 1 && N != 3 && N != 4) {
1426
1.11k
        code = gs_note_error(gs_error_rangecheck);
1427
1.11k
        goto done;
1428
1.11k
    }
1429
99.8k
    code = pdfi_dict_knownget(ctx, dict, "Name", &Name);
1430
99.8k
    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
99.8k
    if (code < 0)
1447
0
        goto done;
1448
1449
99.8k
    code = pdfi_dict_knownget_type(ctx, dict, "Range", PDF_ARRAY, (pdf_obj **)&a);
1450
99.8k
    if (code < 0)
1451
0
        goto done;
1452
99.8k
    if (code > 0) {
1453
154
        double dbl;
1454
154
        int i;
1455
1456
154
        if (pdfi_array_size(a) >= N * 2) {
1457
1.04k
            for (i = 0; i < N * 2;i++) {
1458
906
                code = pdfi_array_get_number(ctx, a, i, &dbl);
1459
906
                if (code < 0) {
1460
0
                    known = false;
1461
0
                    break;
1462
0
                }
1463
906
                range[i] = (float)dbl;
1464
906
            }
1465
142
        } else {
1466
12
            known = false;
1467
12
        }
1468
154
        pdfi_countdown(a);
1469
154
    } else
1470
99.6k
        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
99.8k
    if (!known) {
1478
99.6k
        int i;
1479
369k
        for (i = 0;i < N; i++) {
1480
269k
            range[i * 2] = 0;
1481
269k
            range[(i * 2) + 1] = 1;
1482
269k
        }
1483
99.6k
    }
1484
1485
99.8k
    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
99.8k
    if (code >= 0 && N != icc_N) {
1503
26
        gs_client_color cc;
1504
26
        int i;
1505
1506
26
        gs_gsave(ctx->pgs);
1507
26
        code = gs_setcolorspace(ctx->pgs, pcs);
1508
26
        if (code == 0) {
1509
26
            cc.pattern = 0;
1510
104
            for (i = 0;i < icc_N; i++)
1511
78
                cc.paint.values[i] = 0;
1512
26
            code = gs_setcolor(ctx->pgs, &cc);
1513
26
            if (code == 0)
1514
26
                code = gx_set_dev_color(ctx->pgs);
1515
26
        }
1516
26
        gs_grestore(ctx->pgs);
1517
26
    }
1518
1519
99.8k
    if (code < 0) {
1520
7.73k
        pdf_obj *Alternate = NULL;
1521
1522
7.73k
        if (pcs != NULL)
1523
7.73k
            rc_decrement(pcs,"pdfi_create_iccbased");
1524
1525
        /* Failed to set the ICCBased space, attempt to use the Alternate */
1526
7.73k
        code = pdfi_dict_knownget(ctx, dict, "Alternate", &Alternate);
1527
7.73k
        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.25k
            if (pdfi_type_of(Alternate) == PDF_NAME)
1530
7.25k
                code = pdfi_create_colorspace_by_name(ctx, (pdf_name *)Alternate, stream_dict,
1531
7.25k
                                                      page_dict, ppcs, inline_image);
1532
7.25k
            pdfi_countdown(Alternate);
1533
7.25k
            if (code == 0) {
1534
7.14k
                pdfi_set_warning(ctx, 0, NULL, W_PDF_BADICC_USE_ALT, "pdfi_create_iccbased", NULL);
1535
7.14k
                goto done;
1536
7.14k
            }
1537
7.25k
        }
1538
        /* Use the number of components *from the profile* to set a space.... */
1539
595
        pdfi_set_warning(ctx, 0, NULL, W_PDF_BADICC_USECOMPS, "pdfi_create_iccbased", NULL);
1540
595
        switch(N) {
1541
133
            case 1:
1542
133
                pcs = gs_cspace_new_DeviceGray(ctx->memory);
1543
133
                if (pcs == NULL)
1544
0
                    code = gs_note_error(gs_error_VMerror);
1545
133
                break;
1546
454
            case 3:
1547
454
                pcs = gs_cspace_new_DeviceRGB(ctx->memory);
1548
454
                if (pcs == NULL)
1549
0
                    code = gs_note_error(gs_error_VMerror);
1550
454
                break;
1551
8
            case 4:
1552
8
                pcs = gs_cspace_new_DeviceCMYK(ctx->memory);
1553
8
                if (pcs == NULL)
1554
0
                    code = gs_note_error(gs_error_VMerror);
1555
8
                break;
1556
0
            default:
1557
0
                code = gs_note_error(gs_error_undefined);
1558
0
                break;
1559
595
        }
1560
92.0k
    } else {
1561
92.0k
        if (pcs->ICC_Alternate_space == gs_ICC_Alternate_None) {
1562
18.9k
            code = pdfi_dict_knownget(ctx, dict, "Alternate", (pdf_obj **)&Alt);
1563
18.9k
            if (code >= 0) {
1564
18.9k
                switch(pdfi_type_of(Alt)) {
1565
15.7k
                    case PDF_NAME:
1566
                        /* Simple named spaces must be Gray, RGB or CMYK, we ignore /Indexed */
1567
15.7k
                        if (pdfi_name_is((const pdf_name *)Alt, "DeviceGray"))
1568
3.85k
                            pcs->ICC_Alternate_space = gs_ICC_Alternate_DeviceGray;
1569
11.8k
                        else if (pdfi_name_is((const pdf_name *)Alt, "DeviceRGB"))
1570
11.6k
                            pcs->ICC_Alternate_space = gs_ICC_Alternate_DeviceRGB;
1571
167
                        else if (pdfi_name_is((const pdf_name *)Alt, "DeviceCMYK"))
1572
27
                            pcs->ICC_Alternate_space = gs_ICC_Alternate_DeviceCMYK;
1573
15.7k
                        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.19k
                    default:
1611
                        /* Probably an error, but just ignore it */
1612
3.19k
                        break;
1613
18.9k
                }
1614
18.9k
                pdfi_countdown(Alt);
1615
18.9k
                Alt = NULL;
1616
18.9k
            }
1617
18.9k
        }
1618
92.0k
    }
1619
1620
92.6k
    if (ppcs!= NULL) {
1621
27.2k
        *ppcs = pcs;
1622
27.2k
        if (pcs != NULL)
1623
27.2k
            pdfi_set_colour_callback(pcs, ctx, pdfi_cspace_free_callback);
1624
27.2k
    }
1625
65.4k
    else {
1626
65.4k
        if (pcs != NULL) {
1627
65.4k
            code = pdfi_gs_setcolorspace(ctx, pcs);
1628
            /* release reference from construction */
1629
65.4k
            rc_decrement_only_cs(pcs, "setseparationspace");
1630
65.4k
        }
1631
65.4k
    }
1632
1633
1634
101k
done:
1635
101k
    if (cname)
1636
0
        gs_free_object(ctx->memory, cname, "pdfi_create_iccbased (profile name)");
1637
101k
    pdfi_countdown(Alt);
1638
101k
    pdfi_countdown(Name);
1639
101k
    pdfi_countdown(ICC_obj);
1640
101k
    return code;
1641
92.6k
}
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
973
{
1651
973
    int                     code;
1652
973
    gs_color_space *        pcs;
1653
973
    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
973
    code = gs_cspace_build_ICC(&pcs, NULL, (gs_gstate_memory(ctx->pgs))->stable_memory);
1661
973
    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
973
    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
973
    code = gsicc_set_gscs_profile(pcs, ctx->pgs->icc_manager->lab_profile, gs_gstate_memory(ctx->pgs));
1675
973
    if (code < 0)
1676
0
        return code;
1677
1678
973
    pcs->cmm_icc_profile_data->Range.ranges[0].rmin = 0.0;
1679
973
    pcs->cmm_icc_profile_data->Range.ranges[0].rmax = 100.0;
1680
2.91k
    for (i = 1; i < 3; i++) {
1681
1.94k
        pcs->cmm_icc_profile_data->Range.ranges[i].rmin =
1682
1.94k
            range_buff[2 * (i-1)];
1683
1.94k
        pcs->cmm_icc_profile_data->Range.ranges[i].rmax =
1684
1.94k
            range_buff[2 * (i-1) + 1];
1685
1.94k
    }
1686
973
    if (ppcs!= NULL){
1687
240
        *ppcs = pcs;
1688
240
        pdfi_set_colour_callback(pcs, ctx, pdfi_cspace_free_callback);
1689
733
    } else {
1690
733
        code = pdfi_gs_setcolorspace(ctx, pcs);
1691
733
        rc_decrement_only_cs(pcs, "pdfi_seticc_lab");
1692
733
    }
1693
1694
973
    return code;
1695
973
}
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.00k
{
1699
1.00k
    int code = 0, i;
1700
1.00k
    pdf_dict *Lab_dict = NULL;
1701
1.00k
    pdf_array *Range = NULL;
1702
1.00k
    float RangeBuf[4];
1703
1.00k
    double f;
1704
1.00k
    bool known = false;
1705
1706
1.00k
    code = pdfi_array_get_type(ctx, color_array, index + 1, PDF_DICT, (pdf_obj **)&Lab_dict);
1707
1.00k
    if (code < 0)
1708
18
        return code;
1709
1710
984
    code = pdfi_dict_known(ctx, Lab_dict, "Range", &known);
1711
984
    if (code < 0)
1712
0
        goto exit;
1713
984
    if (known) {
1714
963
        code = pdfi_dict_get_type(ctx, Lab_dict, "Range", PDF_ARRAY, (pdf_obj **)&Range);
1715
963
        if (code < 0) {
1716
0
            goto exit;
1717
0
        }
1718
963
        if (pdfi_array_size(Range) != 4){
1719
10
            code = gs_note_error(gs_error_rangecheck);
1720
10
            goto exit;
1721
10
        }
1722
1723
4.76k
        for (i=0; i < 4; i++) {
1724
3.81k
            code = pdfi_array_get_number(ctx, Range, (uint64_t)i, &f);
1725
3.81k
            if (code < 0)
1726
1
                goto exit;
1727
3.81k
            RangeBuf[i] = (float)f;
1728
3.81k
        }
1729
953
    } else {
1730
21
        RangeBuf[0] = RangeBuf[2] = -100.0;
1731
21
        RangeBuf[1] = RangeBuf[3] = 100.0;
1732
21
    }
1733
1734
973
    code = pdfi_seticc_lab(ctx, RangeBuf, ppcs);
1735
1736
984
exit:
1737
984
    pdfi_countdown(Lab_dict);
1738
984
    pdfi_countdown(Range);
1739
984
    return code;
1740
973
}
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.51k
{
1747
2.51k
    int                     code = 0;
1748
2.51k
    gs_color_space *        pcs;
1749
2.51k
    int                     i;
1750
2.51k
    cmm_profile_t           *cal_profile;
1751
1752
    /* See if the color space is in the profile cache */
1753
2.51k
    pcs = gsicc_find_cs(dictkey, ctx->pgs);
1754
2.51k
    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.48k
        code = gs_cspace_build_ICC(&pcs, NULL, ctx->pgs->memory->stable_memory);
1760
2.48k
        if (code < 0)
1761
0
            return code;
1762
        /* There is no alternate for this.  Perhaps we should set DeviceRGB? */
1763
2.48k
        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.48k
        cal_profile = gsicc_create_from_cal(white, black, gamma, matrix,
1767
2.48k
                                            ctx->pgs->memory->stable_memory, num_colorants);
1768
2.48k
        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.48k
        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.48k
        rc_decrement(cal_profile, "seticc_cal");
1781
2.48k
        if (code < 0) {
1782
0
            rc_decrement(pcs, "seticc_cal");
1783
0
            return code;
1784
0
        }
1785
9.55k
        for (i = 0; i < num_colorants; i++) {
1786
7.07k
            pcs->cmm_icc_profile_data->Range.ranges[i].rmin = 0;
1787
7.07k
            pcs->cmm_icc_profile_data->Range.ranges[i].rmax = 1;
1788
7.07k
        }
1789
        /* Add the color space to the profile cache */
1790
2.48k
        gsicc_add_cs(ctx->pgs, pcs, dictkey);
1791
2.48k
    } else {
1792
        /* We're passing back a new reference, increment the count */
1793
27
        rc_adjust_only(pcs, 1, "pdfi_seticc_cal, return cached ICC profile");
1794
27
    }
1795
1796
2.51k
    if (ppcs!= NULL){
1797
272
        *ppcs = pcs;
1798
272
        pdfi_set_colour_callback(pcs, ctx, pdfi_cspace_free_callback);
1799
2.23k
    } else {
1800
2.23k
        code = pdfi_gs_setcolorspace(ctx, pcs);
1801
2.23k
        rc_decrement_only_cs(pcs, "pdfi_seticc_cal");
1802
2.23k
    }
1803
1804
2.51k
    return code;
1805
2.51k
}
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
659
{
1809
659
    int code = 0, i;
1810
659
    pdf_dict *CalGray_dict = NULL;
1811
659
    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
659
    float WhitePoint[3], BlackPoint[3] = {0.0f, 0.0f, 0.0f}, Gamma = 1.0f;
1818
659
    float Matrix[9] = {1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f};
1819
659
    double f;
1820
1821
659
    code = pdfi_array_get_type(ctx, color_array, index + 1, PDF_DICT, (pdf_obj **)&CalGray_dict);
1822
659
    if (code < 0)
1823
123
        return code;
1824
1825
536
    code = pdfi_dict_get_type(ctx, CalGray_dict, "WhitePoint", PDF_ARRAY, (pdf_obj **)&PDFArray);
1826
536
    if (code < 0) {
1827
21
        pdfi_countdown(PDFArray);
1828
21
        goto exit;
1829
21
    }
1830
515
    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.54k
        code = pdfi_array_get_number(ctx, PDFArray, (uint64_t)i, &f);
1837
1.54k
        if (code < 0)
1838
0
            goto exit;
1839
1.54k
        WhitePoint[i] = (float)f;
1840
1.54k
    }
1841
515
    pdfi_countdown(PDFArray);
1842
515
    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
515
    if (WhitePoint[0] < 0 || WhitePoint[2] < 0 || WhitePoint[1] != 1.0f) {
1848
0
        code = gs_note_error(gs_error_rangecheck);
1849
0
        goto exit;
1850
0
    }
1851
1852
515
    if (pdfi_dict_knownget_type(ctx, CalGray_dict, "BlackPoint", PDF_ARRAY, (pdf_obj **)&PDFArray) > 0) {
1853
462
        if (pdfi_array_size(PDFArray) != 3){
1854
140
            code = gs_note_error(gs_error_rangecheck);
1855
140
            goto exit;
1856
140
        }
1857
1.10k
        for (i=0; i < 3; i++) {
1858
966
            code = pdfi_array_get_number(ctx, PDFArray, (uint64_t)i, &f);
1859
966
            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
786
            if (f < 0) {
1865
0
                code = gs_note_error(gs_error_rangecheck);
1866
0
                goto exit;
1867
0
            }
1868
786
            BlackPoint[i] = (float)f;
1869
786
        }
1870
142
        pdfi_countdown(PDFArray);
1871
142
        PDFArray = NULL;
1872
142
    }
1873
1874
195
    if (pdfi_dict_knownget_number(ctx, CalGray_dict, "Gamma", &f) > 0)
1875
195
        Gamma = (float)f;
1876
    /* The PDF 1.7 reference states that Gamma
1877
     * (if present) must be positive.
1878
     */
1879
195
    if (Gamma < 0) {
1880
0
        code = gs_note_error(gs_error_rangecheck);
1881
0
        goto exit;
1882
0
    }
1883
1884
195
    code = pdfi_seticc_cal(ctx, WhitePoint, BlackPoint, &Gamma, Matrix, 1, color_array->object_num, ppcs);
1885
1886
536
exit:
1887
536
    pdfi_countdown(PDFArray);
1888
536
    pdfi_countdown(CalGray_dict);
1889
536
    return code;
1890
195
}
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.52k
{
1894
2.52k
    int code = 0, i;
1895
2.52k
    pdf_dict *CalRGB_dict = NULL;
1896
2.52k
    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.52k
    float WhitePoint[3], BlackPoint[3] = {0.0f, 0.0f, 0.0f}, Gamma[3] = {1.0f, 1.0f, 1.0f};
1901
2.52k
    float Matrix[9] = {1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f};
1902
2.52k
    double f;
1903
1904
2.52k
    code = pdfi_array_get_type(ctx, color_array, index + 1, PDF_DICT, (pdf_obj **)&CalRGB_dict);
1905
2.52k
    if (code < 0)
1906
27
        return code;
1907
1908
2.49k
    code = pdfi_dict_get_type(ctx, CalRGB_dict, "WhitePoint", PDF_ARRAY, (pdf_obj **)&PDFArray);
1909
2.49k
    if (code < 0) {
1910
4
        pdfi_countdown(PDFArray);
1911
4
        goto exit;
1912
4
    }
1913
2.49k
    if (pdfi_array_size(PDFArray) != 3){
1914
3
        code = gs_note_error(gs_error_rangecheck);
1915
3
        goto exit;
1916
3
    }
1917
1918
9.95k
    for (i=0; i < 3; i++) {
1919
7.46k
        code = pdfi_array_get_number(ctx, PDFArray, (uint64_t)i, &f);
1920
7.46k
        if (code < 0)
1921
0
            goto exit;
1922
7.46k
        WhitePoint[i] = (float)f;
1923
7.46k
    }
1924
2.48k
    pdfi_countdown(PDFArray);
1925
2.48k
    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.48k
    if (WhitePoint[0] < 0 || WhitePoint[2] < 0 || WhitePoint[1] != 1.0f) {
1931
0
        code = gs_note_error(gs_error_rangecheck);
1932
0
        goto exit;
1933
0
    }
1934
1935
2.48k
    if (pdfi_dict_knownget_type(ctx, CalRGB_dict, "BlackPoint", PDF_ARRAY, (pdf_obj **)&PDFArray) > 0) {
1936
769
        if (pdfi_array_size(PDFArray) != 3){
1937
0
            code = gs_note_error(gs_error_rangecheck);
1938
0
            goto exit;
1939
0
        }
1940
2.75k
        for (i=0; i < 3; i++) {
1941
2.14k
            code = pdfi_array_get_number(ctx, PDFArray, (uint64_t)i, &f);
1942
2.14k
            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.14k
            if (f < 0) {
1948
160
                code = gs_note_error(gs_error_rangecheck);
1949
160
                goto exit;
1950
160
            }
1951
1.98k
            BlackPoint[i] = (float)f;
1952
1.98k
        }
1953
609
        pdfi_countdown(PDFArray);
1954
609
        PDFArray = NULL;
1955
609
    }
1956
1957
2.32k
    if (pdfi_dict_knownget_type(ctx, CalRGB_dict, "Gamma", PDF_ARRAY, (pdf_obj **)&PDFArray) > 0) {
1958
2.32k
        if (pdfi_array_size(PDFArray) != 3){
1959
0
            code = gs_note_error(gs_error_rangecheck);
1960
0
            goto exit;
1961
0
        }
1962
9.30k
        for (i=0; i < 3; i++) {
1963
6.97k
            code = pdfi_array_get_number(ctx, PDFArray, (uint64_t)i, &f);
1964
6.97k
            if (code < 0)
1965
0
                goto exit;
1966
6.97k
            Gamma[i] = (float)f;
1967
6.97k
        }
1968
2.32k
        pdfi_countdown(PDFArray);
1969
2.32k
        PDFArray = NULL;
1970
2.32k
    }
1971
1972
2.32k
    if (pdfi_dict_knownget_type(ctx, CalRGB_dict, "Matrix", PDF_ARRAY, (pdf_obj **)&PDFArray) > 0) {
1973
2.32k
        if (pdfi_array_size(PDFArray) != 9){
1974
6
            code = gs_note_error(gs_error_rangecheck);
1975
6
            goto exit;
1976
6
        }
1977
23.1k
        for (i=0; i < 9; i++) {
1978
20.8k
            code = pdfi_array_get_number(ctx, PDFArray, (uint64_t)i, &f);
1979
20.8k
            if (code < 0)
1980
6
                goto exit;
1981
20.8k
            Matrix[i] = (float)f;
1982
20.8k
        }
1983
2.31k
        pdfi_countdown(PDFArray);
1984
2.31k
        PDFArray = NULL;
1985
2.31k
    }
1986
2.31k
    code = pdfi_seticc_cal(ctx, WhitePoint, BlackPoint, Gamma, Matrix, 3, color_array->object_num, ppcs);
1987
1988
2.49k
exit:
1989
2.49k
    pdfi_countdown(PDFArray);
1990
2.49k
    pdfi_countdown(CalRGB_dict);
1991
2.49k
    return code;
1992
2.31k
}
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
31.3k
{
1996
31.3k
    pdf_obj *o = NULL;
1997
31.3k
    pdf_name *name = NULL, *NamedAlternate = NULL;
1998
31.3k
    pdf_array *ArrayAlternate = NULL;
1999
31.3k
    pdf_obj *transform = NULL;
2000
31.3k
    int code;
2001
31.3k
    gs_color_space *pcs = NULL, *pcs_alt = NULL;
2002
31.3k
    gs_function_t * pfn = NULL;
2003
31.3k
    separation_type sep_type;
2004
2005
31.3k
    code = pdfi_array_get_type(ctx, color_array, index + 1, PDF_NAME, (pdf_obj **)&name);
2006
31.3k
    if (code < 0)
2007
0
        goto pdfi_separation_error;
2008
2009
31.3k
    sep_type = SEP_OTHER;
2010
31.3k
    if (name->length == 4 && memcmp(name->data, "None", 4) == 0)
2011
0
        sep_type = SEP_NONE;
2012
31.3k
    if (name->length == 3 && memcmp(name->data, "All", 3) == 0)
2013
0
        sep_type = SEP_ALL;
2014
2015
31.3k
    code = pdfi_array_get(ctx, color_array, index + 2, &o);
2016
31.3k
    if (code < 0)
2017
265
        goto pdfi_separation_error;
2018
2019
31.1k
    switch (pdfi_type_of(o)) {
2020
18.7k
        case PDF_NAME:
2021
18.7k
            NamedAlternate = (pdf_name *)o;
2022
18.7k
            code = pdfi_create_colorspace_by_name(ctx, NamedAlternate, stream_dict, page_dict, &pcs_alt, inline_image);
2023
18.7k
            if (code < 0)
2024
87
                goto pdfi_separation_error;
2025
18.6k
            break;
2026
18.6k
        case PDF_ARRAY:
2027
11.4k
            ArrayAlternate = (pdf_array *)o;
2028
11.4k
            code = pdfi_create_colorspace_by_array(ctx, ArrayAlternate, 0, stream_dict, page_dict, &pcs_alt, inline_image);
2029
11.4k
            if (code < 0)
2030
1.10k
                goto pdfi_separation_error;
2031
10.3k
            break;
2032
10.3k
        default:
2033
936
            pdfi_countdown(o);
2034
936
            code = gs_error_typecheck;
2035
936
            goto pdfi_separation_error;
2036
31.1k
    }
2037
2038
28.9k
    code = pdfi_array_get(ctx, color_array, index + 3, &transform);
2039
28.9k
    if (code < 0)
2040
905
        goto pdfi_separation_error;
2041
2042
28.0k
    code = pdfi_build_function(ctx, &pfn, NULL, 1, transform, page_dict);
2043
28.0k
    if (code < 0)
2044
3.30k
        goto pdfi_separation_error;
2045
2046
24.7k
    if (pfn->params.m != 1 || pfn->params.n != cs_num_components(pcs_alt)) {
2047
23
        code = gs_note_error(gs_error_rangecheck);
2048
23
        goto pdfi_separation_error;
2049
23
    }
2050
2051
24.7k
    code = gs_cspace_new_Separation(&pcs, pcs_alt, ctx->memory);
2052
24.7k
    if (code < 0)
2053
0
        goto pdfi_separation_error;
2054
2055
24.7k
    rc_decrement(pcs_alt, "pdfi_create_Separation");
2056
24.7k
    pcs_alt = NULL;
2057
24.7k
    pcs->params.separation.mem = ctx->memory;
2058
24.7k
    pcs->params.separation.sep_type = sep_type;
2059
24.7k
    pcs->params.separation.sep_name = (char *)gs_alloc_bytes(ctx->memory->non_gc_memory, (size_t)name->length + 1, "pdfi_setseparationspace(ink)");
2060
24.7k
    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
24.7k
    memcpy(pcs->params.separation.sep_name, name->data, name->length);
2065
24.7k
    pcs->params.separation.sep_name[name->length] = 0x00;
2066
2067
24.7k
    code = gs_cspace_set_sepr_function(pcs, pfn);
2068
24.7k
    if (code < 0)
2069
0
        goto pdfi_separation_error;
2070
2071
24.7k
    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
198
        code = pdfi_gs_setcolorspace(ctx, pcs);
2078
198
        *ppcs = pcs;
2079
198
        pdfi_set_colour_callback(pcs, ctx, pdfi_cspace_free_callback);
2080
24.5k
    } else {
2081
24.5k
        code = pdfi_gs_setcolorspace(ctx, pcs);
2082
        /* release reference from construction */
2083
24.5k
        rc_decrement_only_cs(pcs, "setseparationspace");
2084
24.5k
    }
2085
2086
24.7k
    pdfi_countdown(name);
2087
24.7k
    pdfi_countdown(NamedAlternate);
2088
24.7k
    pdfi_countdown(ArrayAlternate);
2089
24.7k
    pdfi_countdown(transform);
2090
24.7k
    return_error(0);
2091
2092
6.62k
pdfi_separation_error:
2093
6.62k
    pdfi_free_function(ctx, pfn);
2094
6.62k
    if (pcs_alt != NULL)
2095
4.23k
        rc_decrement_only_cs(pcs_alt, "setseparationspace");
2096
6.62k
    if(pcs != NULL)
2097
0
        rc_decrement_only_cs(pcs, "setseparationspace");
2098
6.62k
    pdfi_countdown(name);
2099
6.62k
    pdfi_countdown(NamedAlternate);
2100
6.62k
    pdfi_countdown(ArrayAlternate);
2101
6.62k
    pdfi_countdown(transform);
2102
6.62k
    return code;
2103
24.7k
}
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.92k
{
2107
4.92k
    pdf_obj *o = NULL;
2108
4.92k
    pdf_name *NamedAlternate = NULL;
2109
4.92k
    pdf_array *ArrayAlternate = NULL, *inks = NULL;
2110
4.92k
    pdf_obj *transform = NULL;
2111
4.92k
    pdf_dict *attributes = NULL;
2112
4.92k
    pdf_dict *Colorants = NULL, *Process = NULL;
2113
4.92k
    gs_color_space *process_space = NULL;
2114
4.92k
    int code;
2115
4.92k
    uint64_t ix;
2116
4.92k
    gs_color_space *pcs = NULL, *pcs_alt = NULL;
2117
4.92k
    gs_function_t * pfn = NULL;
2118
2119
    /* Start with the array of inks */
2120
4.92k
    code = pdfi_array_get_type(ctx, color_array, index + 1, PDF_ARRAY, (pdf_obj **)&inks);
2121
4.92k
    if (code < 0)
2122
8
        goto pdfi_devicen_error;
2123
2124
4.91k
    if (pdfi_array_size(inks) > GS_CLIENT_COLOR_MAX_COMPONENTS)
2125
0
            return_error(gs_error_limitcheck);
2126
2127
13.9k
    for (ix = 0;ix < pdfi_array_size(inks);ix++) {
2128
9.07k
        pdf_name *ink_name = NULL;
2129
2130
9.07k
        code = pdfi_array_get_type(ctx, inks, ix, PDF_NAME, (pdf_obj **)&ink_name);
2131
9.07k
        if (code < 0)
2132
2
            return code;
2133
2134
9.07k
        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
9.07k
        pdfi_countdown(ink_name);
2139
9.07k
        ink_name = NULL;
2140
9.07k
    }
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.91k
    if (pdfi_array_size(inks) == 1) {
2147
2.86k
        pdf_name *ink_name = NULL;
2148
2.86k
        pdf_array *sep_color_array = NULL;
2149
2.86k
        pdf_obj *obj = NULL;
2150
2151
2.86k
        code = pdfi_array_get_type(ctx, inks, 0, PDF_NAME, (pdf_obj **)&ink_name);
2152
2.86k
        if (code < 0)
2153
0
            goto pdfi_devicen_error;
2154
2155
2.86k
        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
2.86k
            pdfi_countdown(ink_name);
2200
2.86k
    }
2201
2202
    /* Deal with alternate space */
2203
4.91k
    code = pdfi_array_get(ctx, color_array, index + 2, &o);
2204
4.91k
    if (code < 0)
2205
85
        goto pdfi_devicen_error;
2206
2207
4.83k
    switch (pdfi_type_of(o)) {
2208
3.53k
        case PDF_NAME:
2209
3.53k
            NamedAlternate = (pdf_name *)o;
2210
3.53k
            code = pdfi_create_colorspace_by_name(ctx, NamedAlternate, stream_dict, page_dict, &pcs_alt, inline_image);
2211
3.53k
            if (code < 0)
2212
0
                goto pdfi_devicen_error;
2213
3.53k
            break;
2214
3.53k
        case PDF_ARRAY:
2215
1.28k
            ArrayAlternate = (pdf_array *)o;
2216
1.28k
            code = pdfi_create_colorspace_by_array(ctx, ArrayAlternate, 0, stream_dict, page_dict, &pcs_alt, inline_image);
2217
1.28k
            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
152
                goto pdfi_devicen_error;
2223
1.13k
            break;
2224
1.13k
        default:
2225
14
            code = gs_error_typecheck;
2226
14
            pdfi_countdown(o);
2227
14
            goto pdfi_devicen_error;
2228
4.83k
    }
2229
2230
    /* Now the tint transform */
2231
4.66k
    code = pdfi_array_get(ctx, color_array, index + 3, &transform);
2232
4.66k
    if (code < 0)
2233
886
        goto pdfi_devicen_error;
2234
2235
3.77k
    code = pdfi_build_function(ctx, &pfn, NULL, 1, transform, page_dict);
2236
3.77k
    if (code < 0)
2237
660
        goto pdfi_devicen_error;
2238
2239
3.11k
    if (pfn->params.m != pdfi_array_size(inks) || pfn->params.n != cs_num_components(pcs_alt)) {
2240
42
        code = gs_note_error(gs_error_rangecheck);
2241
42
        goto pdfi_devicen_error;
2242
42
    }
2243
2244
3.07k
    code = gs_cspace_new_DeviceN(&pcs, pdfi_array_size(inks), pcs_alt, ctx->memory);
2245
3.07k
    if (code < 0)
2246
0
        return code;
2247
2248
3.07k
    rc_decrement(pcs_alt, "pdfi_create_DeviceN");
2249
3.07k
    pcs_alt = NULL;
2250
3.07k
    pcs->params.device_n.mem = ctx->memory;
2251
2252
7.87k
    for (ix = 0;ix < pdfi_array_size(inks);ix++) {
2253
4.80k
        pdf_name *ink_name;
2254
2255
4.80k
        ink_name = NULL;
2256
4.80k
        code = pdfi_array_get_type(ctx, inks, ix, PDF_NAME, (pdf_obj **)&ink_name);
2257
4.80k
        if (code < 0)
2258
0
            goto pdfi_devicen_error;
2259
2260
4.80k
        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
4.80k
        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
4.80k
        memcpy(pcs->params.device_n.names[ix], ink_name->data, ink_name->length);
2266
4.80k
        pcs->params.device_n.names[ix][ink_name->length] = 0x00;
2267
4.80k
        pdfi_countdown(ink_name);
2268
4.80k
    }
2269
2270
3.07k
    code = gs_cspace_set_devn_function(pcs, pfn);
2271
3.07k
    if (code < 0)
2272
0
        goto pdfi_devicen_error;
2273
2274
3.07k
    if (pdfi_array_size(color_array) >= index + 5) {
2275
2.65k
        pdf_obj *ColorSpace = NULL;
2276
2.65k
        pdf_array *Components = NULL;
2277
2.65k
        pdf_obj *subtype = NULL;
2278
2279
2.65k
        code = pdfi_array_get_type(ctx, color_array, index + 4, PDF_DICT, (pdf_obj **)&attributes);
2280
2.65k
        if (code < 0)
2281
0
            goto pdfi_devicen_error;
2282
2283
2.65k
        code = pdfi_dict_knownget(ctx, attributes, "Subtype", (pdf_obj **)&subtype);
2284
2.65k
        if (code < 0)
2285
0
            goto pdfi_devicen_error;
2286
2287
2.65k
        if (code == 0) {
2288
35
            pcs->params.device_n.subtype = gs_devicen_DeviceN;
2289
2.61k
        } else {
2290
2.61k
            switch (pdfi_type_of(subtype)) {
2291
2.61k
                case PDF_NAME:
2292
2.61k
                case PDF_STRING:
2293
2.61k
                    if (memcmp(((pdf_name *)subtype)->data, "DeviceN", 7) == 0) {
2294
83
                        pcs->params.device_n.subtype = gs_devicen_DeviceN;
2295
2.53k
                    } else {
2296
2.53k
                        if (memcmp(((pdf_name *)subtype)->data, "NChannel", 8) == 0) {
2297
2.53k
                            pcs->params.device_n.subtype = gs_devicen_NChannel;
2298
2.53k
                        } else {
2299
0
                            pdfi_countdown(subtype);
2300
0
                            goto pdfi_devicen_error;
2301
0
                        }
2302
2.53k
                    }
2303
2.61k
                    pdfi_countdown(subtype);
2304
2.61k
                    break;
2305
0
                default:
2306
0
                    pdfi_countdown(subtype);
2307
0
                    goto pdfi_devicen_error;
2308
2.61k
            }
2309
2.61k
        }
2310
2311
2.65k
        code = pdfi_dict_knownget_type(ctx, attributes, "Process", PDF_DICT, (pdf_obj **)&Process);
2312
2.65k
        if (code < 0)
2313
6
            goto pdfi_devicen_error;
2314
2315
2.64k
        if (Process != NULL && pdfi_dict_entries(Process) != 0) {
2316
2.53k
            int ix = 0;
2317
2.53k
            pdf_obj *name;
2318
2319
2.53k
            code = pdfi_dict_get(ctx, Process, "ColorSpace", (pdf_obj **)&ColorSpace);
2320
2.53k
            if (code < 0)
2321
0
                goto pdfi_devicen_error;
2322
2323
2.53k
            code = pdfi_create_colorspace(ctx, ColorSpace, stream_dict, page_dict, &process_space, inline_image);
2324
2.53k
            pdfi_countdown(ColorSpace);
2325
2.53k
            if (code < 0)
2326
0
                goto pdfi_devicen_error;
2327
2328
2.53k
            pcs->params.device_n.devn_process_space = process_space;
2329
2330
2.53k
            code = pdfi_dict_get_type(ctx, Process, "Components", PDF_ARRAY, (pdf_obj **)&Components);
2331
2.53k
            if (code < 0)
2332
0
                goto pdfi_devicen_error;
2333
2334
2.53k
            pcs->params.device_n.num_process_names = pdfi_array_size(Components);
2335
2.53k
            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
2.53k
            if (pcs->params.device_n.process_names == NULL) {
2337
0
                code = gs_error_VMerror;
2338
0
                goto pdfi_devicen_error;
2339
0
            }
2340
2.53k
            memset(pcs->params.device_n.process_names, 0x00, pdfi_array_size(Components) * sizeof(char *));
2341
2342
12.6k
            for (ix = 0; ix < pcs->params.device_n.num_process_names; ix++) {
2343
10.1k
                code = pdfi_array_get(ctx, Components, ix, &name);
2344
10.1k
                if (code < 0) {
2345
0
                    pdfi_countdown(Components);
2346
0
                    goto pdfi_devicen_error;
2347
0
                }
2348
2349
10.1k
                switch (pdfi_type_of(name)) {
2350
10.1k
                    case PDF_NAME:
2351
10.1k
                    case PDF_STRING:
2352
10.1k
                        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
10.1k
                        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
10.1k
                        memcpy(pcs->params.device_n.process_names[ix], ((pdf_name *)name)->data, ((pdf_name *)name)->length);
2360
10.1k
                        pcs->params.device_n.process_names[ix][((pdf_name *)name)->length] = 0x00;
2361
10.1k
                        pdfi_countdown(name);
2362
10.1k
                        break;
2363
6
                    default:
2364
6
                        pdfi_countdown(Components);
2365
6
                        pdfi_countdown(name);
2366
6
                        goto pdfi_devicen_error;
2367
10.1k
                }
2368
10.1k
            }
2369
2.52k
            pdfi_countdown(Components);
2370
2.52k
        }
2371
2372
2.64k
        code = pdfi_dict_knownget_type(ctx, attributes, "Colorants", PDF_DICT, (pdf_obj **)&Colorants);
2373
2.64k
        if (code < 0)
2374
0
            goto pdfi_devicen_error;
2375
2376
2.64k
        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
2.64k
    }
2457
2458
3.06k
    if (ppcs!= NULL){
2459
124
        *ppcs = pcs;
2460
124
        pdfi_set_colour_callback(pcs, ctx, pdfi_cspace_free_callback);
2461
2.94k
    } else {
2462
2.94k
        code = pdfi_gs_setcolorspace(ctx, pcs);
2463
        /* release reference from construction */
2464
2.94k
        rc_decrement_only_cs(pcs, "setdevicenspace");
2465
2.94k
    }
2466
3.06k
    pdfi_countdown(Process);
2467
3.06k
    pdfi_countdown(Colorants);
2468
3.06k
    pdfi_countdown(attributes);
2469
3.06k
    pdfi_countdown(inks);
2470
3.06k
    pdfi_countdown(NamedAlternate);
2471
3.06k
    pdfi_countdown(ArrayAlternate);
2472
3.06k
    pdfi_countdown(transform);
2473
3.06k
    return_error(0);
2474
2475
1.85k
pdfi_devicen_error:
2476
1.85k
    pdfi_free_function(ctx, pfn);
2477
1.85k
    if (pcs_alt != NULL)
2478
1.58k
        rc_decrement_only_cs(pcs_alt, "setseparationspace");
2479
1.85k
    if(pcs != NULL)
2480
12
        rc_decrement_only_cs(pcs, "setseparationspace");
2481
1.85k
    pdfi_countdown(Process);
2482
1.85k
    pdfi_countdown(Colorants);
2483
1.85k
    pdfi_countdown(attributes);
2484
1.85k
    pdfi_countdown(inks);
2485
1.85k
    pdfi_countdown(NamedAlternate);
2486
1.85k
    pdfi_countdown(ArrayAlternate);
2487
1.85k
    pdfi_countdown(transform);
2488
1.85k
    return code;
2489
3.07k
}
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
10.6k
{
2498
10.6k
    pdf_obj *space=NULL, *lookup=NULL;
2499
10.6k
    int code;
2500
10.6k
    int64_t hival, lookup_length = 0;
2501
10.6k
    int num_values;
2502
10.6k
    gs_color_space *pcs=NULL, *pcs_base=NULL;
2503
10.6k
    gs_color_space_index base_type;
2504
10.6k
    byte *Buffer = NULL;
2505
2506
10.6k
    if (index != 0)
2507
0
        return_error(gs_error_syntaxerror);
2508
2509
10.6k
    code = pdfi_array_get_int(ctx, color_array, index + 2, &hival);
2510
10.6k
    if (code < 0)
2511
95
        return code;
2512
2513
10.5k
    if (hival > 255 || hival < 0)
2514
12
        return_error(gs_error_syntaxerror);
2515
2516
10.5k
    code = pdfi_array_get(ctx, color_array, index + 1, &space);
2517
10.5k
    if (code < 0)
2518
78
        goto exit;
2519
2520
10.4k
    code = pdfi_create_colorspace(ctx, space, stream_dict, page_dict, &pcs_base, inline_image);
2521
10.4k
    if (code < 0)
2522
307
        goto exit;
2523
2524
10.1k
    base_type = gs_color_space_get_index(pcs_base);
2525
10.1k
    if (base_type == gs_color_space_index_Pattern || base_type == gs_color_space_index_Indexed) {
2526
10
        code = gs_note_error(gs_error_typecheck);
2527
10
        goto exit;
2528
10
    }
2529
2530
10.1k
    (void)pcs_base->type->install_cspace(pcs_base, ctx->pgs);
2531
2532
10.1k
    code = pdfi_array_get(ctx, color_array, index + 3, &lookup);
2533
10.1k
    if (code < 0)
2534
187
        goto exit;
2535
2536
9.95k
    num_values = (hival+1) * cs_num_components(pcs_base);
2537
9.95k
    lookup_length = num_values;
2538
2539
9.95k
    switch (pdfi_type_of(lookup)) {
2540
5.24k
    case PDF_STREAM:
2541
5.24k
        code = pdfi_stream_to_buffer(ctx, (pdf_stream *)lookup, &Buffer, &lookup_length);
2542
5.24k
        if (code < 0)
2543
10
            goto exit;
2544
5.23k
        break;
2545
5.23k
    case PDF_STRING:
2546
4.69k
    {
2547
4.69k
        pdf_string *lookup_string = (pdf_string *)lookup; /* alias */
2548
2549
4.69k
        Buffer = gs_alloc_bytes(ctx->memory, lookup_string->length, "pdfi_create_indexed (lookup buffer)");
2550
4.69k
        if (Buffer == NULL) {
2551
0
            code = gs_note_error(gs_error_VMerror);
2552
0
            goto exit;
2553
0
        }
2554
2555
4.69k
        memcpy(Buffer, lookup_string->data, lookup_string->length);
2556
4.69k
        lookup_length = lookup_string->length;
2557
4.69k
        break;
2558
4.69k
    }
2559
12
    default:
2560
12
        code = gs_note_error(gs_error_typecheck);
2561
12
        goto exit;
2562
9.95k
    }
2563
2564
9.92k
    if (num_values > lookup_length) {
2565
        /* This is not legal, but Acrobat seems to accept it */
2566
136
        byte *SBuffer = NULL;
2567
2568
136
        code = pdfi_set_error_stop(ctx, gs_error_rangecheck, NULL, E_PDF_BAD_INDEXED_STRING, "pdfi_create_indexed", NULL);
2569
136
        if (code < 0)
2570
0
            goto exit;
2571
136
        SBuffer = gs_alloc_bytes(ctx->memory, num_values, "pdfi_create_indexed (lookup buffer)");
2572
136
        if (SBuffer == NULL) {
2573
0
            code = gs_note_error(gs_error_VMerror);
2574
0
            goto exit;
2575
0
        }
2576
136
        memcpy(SBuffer, Buffer, lookup_length);
2577
136
        memset(&SBuffer[lookup_length], 0x00, num_values - lookup_length);
2578
136
        gs_free_object(ctx->memory, Buffer, "pdfi_create_indexed (lookup buffer)");
2579
136
        Buffer = SBuffer;
2580
136
    }
2581
2582
    /* If we have a named color profile and the base space is DeviceN or
2583
       Separation use a different set of procedures to ensure the named
2584
       color remapping code is used */
2585
9.92k
    if (ctx->pgs->icc_manager->device_named != NULL &&
2586
0
        (base_type == gs_color_space_index_Separation ||
2587
0
         base_type == gs_color_space_index_DeviceN))
2588
0
        pcs = gs_cspace_alloc(ctx->memory, &gs_color_space_type_Indexed_Named);
2589
9.92k
    else
2590
9.92k
        pcs = gs_cspace_alloc(ctx->memory, &gs_color_space_type_Indexed);
2591
2592
9.92k
    if (pcs == NULL) {
2593
0
        code = gs_note_error(gs_error_VMerror);
2594
0
        goto exit;
2595
0
    }
2596
    /* NOTE: we don't need to increment the reference to pcs_base, since it is already 1 */
2597
9.92k
    pcs->base_space = pcs_base;
2598
2599
9.92k
    pcs->params.indexed.lookup.table.size = num_values;
2600
9.92k
    pcs->params.indexed.use_proc = 0;
2601
9.92k
    pcs->params.indexed.hival = hival;
2602
9.92k
    pcs->params.indexed.n_comps = cs_num_components(pcs_base);
2603
9.92k
    pcs->params.indexed.lookup.table.data = Buffer;
2604
9.92k
    Buffer = NULL;
2605
2606
9.92k
    if (ppcs != NULL) {
2607
9.87k
        *ppcs = pcs;
2608
9.87k
        pdfi_set_colour_callback(pcs, ctx, pdfi_cspace_free_callback);
2609
9.87k
    }
2610
58
    else {
2611
58
        code = pdfi_gs_setcolorspace(ctx, pcs);
2612
        /* release reference from construction */
2613
58
        rc_decrement_only_cs(pcs, "setindexedspace");
2614
58
    }
2615
2616
10.5k
 exit:
2617
10.5k
    if (code != 0)
2618
10.5k
        rc_decrement(pcs_base, "pdfi_create_indexed(pcs_base) error");
2619
10.5k
    if (Buffer)
2620
0
        gs_free_object(ctx->memory, Buffer, "pdfi_create_indexed (decompression buffer)");
2621
10.5k
    pdfi_countdown(space);
2622
10.5k
    pdfi_countdown(lookup);
2623
10.5k
    return code;
2624
9.92k
}
2625
2626
static int pdfi_create_DeviceGray(pdf_context *ctx, gs_color_space **ppcs)
2627
29.5k
{
2628
29.5k
    int code = 0;
2629
2630
29.5k
    if (ppcs != NULL) {
2631
        /* Bug 709017: Don't return DefaultGray_cs if we are within a softmask */
2632
26.0k
        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
26.0k
        } else {
2637
26.0k
            *ppcs = gs_cspace_new_DeviceGray(ctx->memory);
2638
26.0k
            if (*ppcs == NULL)
2639
0
                code = gs_note_error(gs_error_VMerror);
2640
26.0k
            else {
2641
26.0k
                code = ((gs_color_space *)*ppcs)->type->install_cspace(*ppcs, ctx->pgs);
2642
26.0k
                if (code < 0) {
2643
0
                    rc_decrement_only_cs(*ppcs, "pdfi_create_DeviceGray");
2644
0
                    *ppcs = NULL;
2645
0
                }
2646
26.0k
            }
2647
26.0k
            if (*ppcs != NULL)
2648
26.0k
                pdfi_set_colour_callback(*ppcs, ctx, pdfi_cspace_free_callback);
2649
26.0k
        }
2650
26.0k
    } else {
2651
3.51k
        code = pdfi_gs_setgray(ctx, 0);
2652
3.51k
        pdfi_set_colour_callback(ctx->pgs->color[0].color_space, ctx, pdfi_cspace_free_callback);
2653
3.51k
    }
2654
29.5k
    return code;
2655
29.5k
}
2656
2657
static int pdfi_create_DeviceRGB(pdf_context *ctx, gs_color_space **ppcs)
2658
74.3k
{
2659
74.3k
    int code = 0;
2660
2661
74.3k
    if (ppcs != NULL) {
2662
        /* Bug 709017: Don't return DefaultRGB_cs if we are within a softmask */
2663
55.1k
        if (ctx->page.DefaultRGB_cs != NULL &&
2664
202
            (dev_proc(ctx->pgs->device, dev_spec_op)(ctx->pgs->device, gxdso_in_smask_construction, NULL, 0) <= 0)) {
2665
202
            *ppcs = ctx->page.DefaultRGB_cs;
2666
202
            rc_increment(*ppcs);
2667
54.9k
        } else {
2668
54.9k
            *ppcs = gs_cspace_new_DeviceRGB(ctx->memory);
2669
54.9k
            if (*ppcs == NULL)
2670
0
                code = gs_note_error(gs_error_VMerror);
2671
54.9k
            else {
2672
54.9k
                code = ((gs_color_space *)*ppcs)->type->install_cspace(*ppcs, ctx->pgs);
2673
54.9k
                if (code < 0) {
2674
0
                    rc_decrement_only_cs(*ppcs, "pdfi_create_DeviceRGB");
2675
0
                    *ppcs = NULL;
2676
0
                }
2677
54.9k
            }
2678
54.9k
            if (*ppcs != NULL)
2679
54.9k
                pdfi_set_colour_callback(*ppcs, ctx, pdfi_cspace_free_callback);
2680
54.9k
        }
2681
55.1k
    } else {
2682
19.1k
        code = pdfi_gs_setrgbcolor(ctx, 0, 0, 0);
2683
19.1k
    }
2684
74.3k
    return code;
2685
74.3k
}
2686
2687
static int pdfi_create_DeviceCMYK(pdf_context *ctx, gs_color_space **ppcs)
2688
20.3k
{
2689
20.3k
    int code = 0;
2690
2691
20.3k
    if (ppcs != NULL) {
2692
        /* Bug 709017: Don't return DefaultCMYK_cs if we are within a softmask */
2693
16.0k
        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.0k
        } else {
2698
16.0k
            *ppcs = gs_cspace_new_DeviceCMYK(ctx->memory);
2699
16.0k
            if (*ppcs == NULL)
2700
0
                code = gs_note_error(gs_error_VMerror);
2701
16.0k
            else {
2702
16.0k
                code = ((gs_color_space *)*ppcs)->type->install_cspace(*ppcs, ctx->pgs);
2703
16.0k
                if (code < 0) {
2704
0
                    rc_decrement_only_cs(*ppcs, "pdfi_create_DeviceCMYK");
2705
0
                    *ppcs = NULL;
2706
0
                }
2707
16.0k
            }
2708
16.0k
            if (*ppcs != NULL)
2709
16.0k
                pdfi_set_colour_callback(*ppcs, ctx, pdfi_cspace_free_callback);
2710
16.0k
        }
2711
16.0k
    } else {
2712
4.33k
        code = pdfi_gs_setcmykcolor(ctx, 0, 0, 0, 1);
2713
4.33k
        pdfi_set_colour_callback(ctx->pgs->color[0].color_space, ctx, pdfi_cspace_free_callback);
2714
4.33k
    }
2715
20.3k
    return code;
2716
20.3k
}
2717
2718
static int pdfi_create_JPX_space(pdf_context *ctx, const char *name, int num_components, gs_color_space **ppcs)
2719
4.77k
{
2720
4.77k
    int code, icc_N;
2721
4.77k
    float range_buff[6] = {0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f};
2722
2723
4.77k
    code = pdfi_create_icc(ctx, (char *)name, NULL, num_components, &icc_N, range_buff, 0, ppcs);
2724
4.77k
    return code;
2725
4.77k
}
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
167k
{
2739
167k
    int code;
2740
167k
    pdf_name *space = NULL;
2741
167k
    pdf_array *a = NULL;
2742
2743
167k
    code = pdfi_array_get_type(ctx, color_array, index, PDF_NAME, (pdf_obj **)&space);
2744
167k
    if (code != 0)
2745
227
        goto exit;
2746
2747
166k
    code = 0;
2748
166k
    if (pdfi_name_is(space, "G") || pdfi_name_is(space, "DeviceGray")) {
2749
2
        if (pdfi_name_is(space, "G") && !inline_image) {
2750
0
            if ((code = pdfi_set_warning_stop(ctx, gs_note_error(gs_error_syntaxerror), NULL, W_PDF_BAD_INLINECOLORSPACE, "pdfi_create_colorspace_by_array", NULL)) < 0)
2751
0
                return code;
2752
0
        }
2753
2
        code = pdfi_create_DeviceGray(ctx, ppcs);
2754
166k
    } else if (pdfi_name_is(space, "I") || pdfi_name_is(space, "Indexed")) {
2755
10.6k
        if (pdfi_name_is(space, "I") && !inline_image) {
2756
95
            pdfi_set_warning(ctx, 0, NULL, W_PDF_BAD_INLINECOLORSPACE, "pdfi_create_colorspace_by_array", NULL);
2757
95
            if (ctx->args.pdfstoponwarning)
2758
0
                return_error(gs_error_syntaxerror);
2759
95
        }
2760
10.6k
        code = pdfi_create_indexed(ctx, color_array, index, stream_dict, page_dict, ppcs, inline_image);
2761
156k
    } else if (pdfi_name_is(space, "Lab")) {
2762
1.00k
        code = pdfi_create_Lab(ctx, color_array, index, stream_dict, page_dict, ppcs);
2763
155k
    } else if (pdfi_name_is(space, "RGB") || pdfi_name_is(space, "DeviceRGB")) {
2764
4
        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
4
        code = pdfi_create_DeviceRGB(ctx, ppcs);
2770
155k
    } 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
155k
    } else if (pdfi_name_is(space, "CalRGB")) {
2778
2.52k
        code = pdfi_create_CalRGB(ctx, color_array, index, stream_dict, page_dict, ppcs);
2779
152k
    } else if (pdfi_name_is(space, "CalGray")) {
2780
659
        code = pdfi_create_CalGray(ctx, color_array, index, stream_dict, page_dict, ppcs);
2781
152k
    } else if (pdfi_name_is(space, "Pattern")) {
2782
2.09k
        if (index != 0)
2783
0
            code = gs_note_error(gs_error_syntaxerror);
2784
2.09k
        else
2785
2.09k
            code = pdfi_pattern_create(ctx, color_array, stream_dict, page_dict, ppcs);
2786
149k
    } else if (pdfi_name_is(space, "DeviceN")) {
2787
4.92k
        code = pdfi_create_DeviceN(ctx, color_array, index, stream_dict, page_dict, ppcs, inline_image);
2788
144k
    } else if (pdfi_name_is(space, "ICCBased")) {
2789
112k
        code = pdfi_create_iccbased(ctx, color_array, index, stream_dict, page_dict, ppcs, inline_image);
2790
112k
    } else if (pdfi_name_is(space, "Separation")) {
2791
31.3k
        code = pdfi_create_Separation(ctx, color_array, index, stream_dict, page_dict, ppcs, inline_image);
2792
31.3k
    } else {
2793
869
        if (stream_dict == NULL)
2794
32
            code = gs_note_error(gs_error_syntaxerror);
2795
837
        else
2796
837
            code = pdfi_find_resource(ctx, (unsigned char *)"ColorSpace",
2797
837
                                  space, (pdf_dict *)stream_dict, page_dict, (pdf_obj **)&a);
2798
869
        if (code < 0)
2799
869
            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
167k
 exit:
2811
167k
    pdfi_countdown(space);
2812
167k
    pdfi_countdown(a);
2813
167k
    return code;
2814
166k
}
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
387k
{
2821
387k
    int code = 0;
2822
387k
    gs_id oldid = 0;
2823
2824
387k
    if (pdfi_name_is(name, "G") || pdfi_name_is(name, "DeviceGray")) {
2825
29.5k
        if (pdfi_name_is(name, "G") && !inline_image) {
2826
20
            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
20
        }
2829
29.5k
        code = pdfi_create_DeviceGray(ctx, ppcs);
2830
357k
    } else if (pdfi_name_is(name, "RGB") || pdfi_name_is(name, "DeviceRGB")) {
2831
74.3k
        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
74.3k
        code = pdfi_create_DeviceRGB(ctx, ppcs);
2836
283k
    } else if (pdfi_name_is(name, "CMYK") || pdfi_name_is(name, "DeviceCMYK") || pdfi_name_is(name, "CalCMYK")) {
2837
20.3k
        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.3k
        code = pdfi_create_DeviceCMYK(ctx, ppcs);
2842
263k
    } else if (pdfi_name_is(name, "Pattern")) {
2843
52.4k
        code = pdfi_pattern_create(ctx, NULL, stream_dict, page_dict, ppcs);
2844
210k
    } 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
210k
    } 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
210k
    } else if (pdfi_name_is(name, "sRGBICC")) {                 /* a special space but simply constructs an appropriate */
2849
518
        code = pdfi_create_JPX_space(ctx, "srgb", 3, ppcs);     /* pdf_array object with the corerct contents for an    */
2850
210k
    } else if (pdfi_name_is(name, "sGrayICC")) {                /* Lab space with a D65 white point.                    */
2851
4.25k
        code = pdfi_create_JPX_space(ctx, "sgray", 1, ppcs);
2852
205k
    } else {
2853
205k
        pdf_obj *ref_space = NULL;
2854
2855
205k
        if (ppcs == NULL && check_same_current_space(ctx, name) == 1)
2856
56.4k
            return 0;
2857
2858
149k
        code = pdfi_find_resource(ctx, (unsigned char *)"ColorSpace", name, (pdf_dict *)stream_dict,
2859
149k
                                  page_dict, &ref_space);
2860
149k
        if (code < 0)
2861
31.5k
            return code;
2862
2863
117k
        if (pdfi_type_of(ref_space) == PDF_NAME) {
2864
131
            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
131
            if (((pdf_name *)ref_space)->length <= 0) {
2869
8
                pdfi_countdown(ref_space);
2870
8
                return_error(gs_error_syntaxerror);
2871
8
            }
2872
123
            if (((pdf_name *)ref_space)->length == name->length && memcmp(((pdf_name *)ref_space)->data, name->data, name->length) == 0) {
2873
3
                pdfi_countdown(ref_space);
2874
3
                return_error(gs_error_circular_reference);
2875
3
            }
2876
123
        }
2877
2878
117k
        oldid = ctx->pgs->color[0].color_space->id;
2879
        /* recursion */
2880
117k
        code = pdfi_create_colorspace(ctx, ref_space, stream_dict, page_dict, ppcs, inline_image);
2881
2882
117k
        if (code >= 0) {
2883
96.9k
            if (oldid != ctx->pgs->color[0].color_space->id) {
2884
95.8k
                if (ppcs != NULL)
2885
0
                    pdfi_set_colourspace_name(ctx, *ppcs, name);
2886
95.8k
                else
2887
95.8k
                    pdfi_set_colourspace_name(ctx, ctx->pgs->color[0].color_space, name);
2888
95.8k
            }
2889
96.9k
        }
2890
2891
117k
        pdfi_countdown(ref_space);
2892
117k
        return code;
2893
117k
    }
2894
2895
    /* If we got here, it's a recursion base case, and ppcs should have been set if requested */
2896
181k
    if (ppcs != NULL && *ppcs == NULL)
2897
0
        code = gs_note_error(gs_error_VMerror);
2898
181k
    return code;
2899
387k
}
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
515k
{
2944
515k
    int code;
2945
2946
515k
    code = pdfi_loop_detector_mark(ctx);
2947
515k
    if (code < 0)
2948
0
        return code;
2949
2950
515k
    switch (pdfi_type_of(space)) {
2951
357k
    case PDF_NAME:
2952
357k
        code = pdfi_create_colorspace_by_name(ctx, (pdf_name *)space, stream_dict, page_dict, ppcs, inline_image);
2953
357k
        break;
2954
154k
    case PDF_ARRAY:
2955
154k
        code = pdfi_create_colorspace_by_array(ctx, (pdf_array *)space, 0, stream_dict, page_dict, ppcs, inline_image);
2956
154k
        break;
2957
3.70k
    default:
2958
3.70k
        pdfi_loop_detector_cleartomark(ctx);
2959
3.70k
        return_error(gs_error_typecheck);
2960
515k
    }
2961
512k
    if (code >= 0 && ppcs && *ppcs)
2962
106k
        (void)(*ppcs)->type->install_cspace(*ppcs, ctx->pgs);
2963
2964
512k
    (void)pdfi_loop_detector_cleartomark(ctx);
2965
512k
    return code;
2966
515k
}
2967
2968
int pdfi_setcolorspace(pdf_context *ctx, pdf_obj *space, pdf_dict *stream_dict, pdf_dict *page_dict)
2969
288k
{
2970
288k
    return pdfi_create_colorspace(ctx, space, stream_dict, page_dict, NULL, false);
2971
288k
}
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.0k
{
2976
28.0k
    int code;
2977
28.0k
    pdf_obj *n = NULL;
2978
2979
28.0k
    if (pdfi_count_stack(ctx) < 1)
2980
812
        return_error(gs_error_stackunderflow);
2981
2982
27.2k
    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
27.2k
    if (pdfi_type_of(ctx->stack_top[-1]) != PDF_NAME) {
2989
978
        pdfi_pop(ctx, 1);
2990
978
        return_error(gs_error_typecheck);
2991
978
    }
2992
26.2k
    n = ctx->stack_top[-1];
2993
26.2k
    pdfi_countup(n);
2994
26.2k
    pdfi_pop(ctx, 1);
2995
2996
26.2k
    gs_swapcolors_quick(ctx->pgs);
2997
26.2k
    code = pdfi_setcolorspace(ctx, n, stream_dict, page_dict);
2998
26.2k
    gs_swapcolors_quick(ctx->pgs);
2999
3000
26.2k
    pdfi_countdown(n);
3001
26.2k
    return code;
3002
27.2k
}
3003
3004
int pdfi_setfillcolor_space(pdf_context *ctx, pdf_dict *stream_dict, pdf_dict *page_dict)
3005
244k
{
3006
244k
    int code;
3007
244k
    pdf_obj *n = NULL;
3008
3009
244k
    if (pdfi_count_stack(ctx) < 1)
3010
4.39k
        return_error(gs_error_stackunderflow);
3011
3012
240k
    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
240k
    if (pdfi_type_of(ctx->stack_top[-1]) != PDF_NAME) {
3019
6.49k
        pdfi_pop(ctx, 1);
3020
6.49k
        return_error(gs_error_typecheck);
3021
6.49k
    }
3022
233k
    n = ctx->stack_top[-1];
3023
233k
    pdfi_countup(n);
3024
233k
    pdfi_pop(ctx, 1);
3025
3026
233k
    code = pdfi_setcolorspace(ctx, n, stream_dict, page_dict);
3027
3028
233k
    pdfi_countdown(n);
3029
233k
    return code;
3030
240k
}
3031
3032
3033
/*
3034
 * Set device outputintent from stream
3035
 * see zicc.c/zset_outputintent()
3036
 */
3037
static int pdfi_device_setoutputintent(pdf_context *ctx, pdf_dict *profile_dict, stream *stream)
3038
0
{
3039
0
    int code = 0;
3040
0
    gs_gstate *pgs = ctx->pgs;
3041
0
    gx_device *dev = gs_currentdevice(pgs);
3042
0
    cmm_dev_profile_t *dev_profile;
3043
0
    int64_t N;
3044
0
    int ncomps, dev_comps;
3045
0
    int expected = 0;
3046
0
    cmm_profile_t *picc_profile = NULL;
3047
0
    cmm_profile_t *source_profile = NULL;
3048
0
    gsicc_manager_t *icc_manager = pgs->icc_manager;
3049
0
    gs_color_space_index index;
3050
3051
0
    if_debug0m(gs_debug_flag_icc, ctx->memory, "[icc] Using OutputIntent\n");
3052
3053
    /* get dev_profile and try initing it if fail first time */
3054
0
    code = dev_proc(dev, get_profile)(dev, &dev_profile);
3055
0
    if (code < 0)
3056
0
        return code;
3057
3058
0
    if (dev_profile == NULL) {
3059
0
        code = gsicc_init_device_profile_struct(dev, NULL, 0);
3060
0
        if (code < 0)
3061
0
            return code;
3062
0
        code = dev_proc(dev, get_profile)(dev, &dev_profile);
3063
0
        if (code < 0)
3064
0
            return code;
3065
0
    }
3066
0
    if (dev_profile->oi_profile != NULL) {
3067
0
        return 0;  /* Allow only one setting of this object */
3068
0
    }
3069
3070
0
    code = pdfi_dict_get_int(ctx, profile_dict, "N", &N);
3071
0
    if (code < 0)
3072
0
        goto exit;
3073
0
    ncomps = (int)N;
3074
0
    if (ncomps > ICC_MAX_CHANNELS)
3075
0
        return_error(gs_error_rangecheck);
3076
3077
0
    picc_profile = gsicc_profile_new(stream, gs_gstate_memory(pgs), NULL, 0);
3078
0
    if (picc_profile == NULL) {
3079
0
        code = gs_note_error(gs_error_VMerror);
3080
0
        goto exit;
3081
0
    }
3082
0
    picc_profile->num_comps = ncomps;
3083
0
    picc_profile->profile_handle =
3084
0
        gsicc_get_profile_handle_buffer(picc_profile->buffer,
3085
0
                                        picc_profile->buffer_size,
3086
0
                                        gs_gstate_memory(pgs));
3087
0
    if (picc_profile->profile_handle == NULL) {
3088
0
        code = gs_note_error(gs_error_VMerror);
3089
0
        goto exit;
3090
0
    }
3091
3092
0
    picc_profile->data_cs =
3093
0
        gscms_get_profile_data_space(picc_profile->profile_handle,
3094
0
            picc_profile->memory);
3095
0
    switch (picc_profile->data_cs) {
3096
0
        case gsCIEXYZ:
3097
0
        case gsCIELAB:
3098
0
        case gsRGB:
3099
0
            expected = 3;
3100
0
            source_profile = icc_manager->default_rgb;
3101
0
            break;
3102
0
        case gsGRAY:
3103
0
            expected = 1;
3104
0
            source_profile = icc_manager->default_gray;
3105
0
            break;
3106
0
        case gsCMYK:
3107
0
            expected = 4;
3108
0
            source_profile = icc_manager->default_cmyk;
3109
0
            break;
3110
0
        case gsNCHANNEL:
3111
0
            expected = 0;
3112
0
            break;
3113
0
        case gsNAMED:
3114
0
        case gsUNDEFINED:
3115
0
            break;
3116
0
    }
3117
0
    if (expected && ncomps != expected) {
3118
0
        code = gs_note_error(gs_error_rangecheck);
3119
0
        goto exit;
3120
0
    }
3121
0
    gsicc_init_hash_cs(picc_profile, pgs);
3122
3123
    /* All is well with the profile.  Lets set the stuff that needs to be set */
3124
0
    dev_profile->oi_profile = picc_profile;
3125
0
    rc_increment(picc_profile);
3126
0
    picc_profile->name = (char *) gs_alloc_bytes(picc_profile->memory,
3127
0
                                                 MAX_DEFAULT_ICC_LENGTH,
3128
0
                                                 "pdfi_color_setoutputintent");
3129
0
    if (picc_profile->name == NULL) {
3130
0
        code = gs_note_error(gs_error_VMerror);
3131
0
        goto exit;
3132
0
    }
3133
0
    strncpy(picc_profile->name, OI_PROFILE, strlen(OI_PROFILE));
3134
0
    picc_profile->name[strlen(OI_PROFILE)] = 0;
3135
0
    picc_profile->name_length = strlen(OI_PROFILE);
3136
    /* Set the range of the profile */
3137
0
    gsicc_set_icc_range(&picc_profile);
3138
3139
    /* If the output device has a different number of components, then we are
3140
       going to set the output intent as the proofing profile, unless the
3141
       proofing profile has already been set.
3142
3143
       If the device has the same number of components (and color model) then as
3144
       the profile we will use this as the output profile, unless someone has
3145
       explicitly set the output profile.
3146
3147
       Finally, we will use the output intent profile for the default profile
3148
       of the proper Device profile in the icc manager, again, unless someone
3149
       has explicitly set this default profile.
3150
3151
       All of this is skipped if we are forcing oveprint simulation with
3152
       the output intent set, in which case we will push the pdf14 device
3153
       to render directly to the the output intent color space and then
3154
       do a final transform to the target color space.
3155
    */
3156
0
    dev_comps = dev_profile->device_profile[GS_DEFAULT_DEVICE_PROFILE]->num_comps;
3157
0
    index = gsicc_get_default_type(dev_profile->device_profile[GS_DEFAULT_DEVICE_PROFILE]);
3158
3159
    /* If we are doing simulate overprint and the output intent is different than
3160
       what the device profile is the we will end up pushing the pdf14 device
3161
       and doing a rendering to the output intent color space.  Keep the device
3162
       profile as is, and do not do a proofing profile */
3163
3164
0
    if (!(ctx->pgs->device->icc_struct->overprint_control == gs_overprint_control_simulate &&
3165
0
        !gsicc_profiles_equal(dev_profile->oi_profile, dev_profile->device_profile[GS_DEFAULT_DEVICE_PROFILE]))) {
3166
0
        if (ncomps == dev_comps && index < gs_color_space_index_DevicePixel) {
3167
            /* The OI profile is the same type as the profile for the device and a
3168
               "default" profile for the device was not externally set. So we go
3169
               ahead and use the OI profile as the device profile.  Care needs to be
3170
               taken here to keep from screwing up any device parameters.   We will
3171
               use a keyword of OIProfile for the user/device parameter to indicate
3172
               its usage.  Also, note conflicts if one is setting object dependent
3173
               color management */
3174
0
            dev_profile->device_profile[GS_DEFAULT_DEVICE_PROFILE] = picc_profile;
3175
0
            rc_increment(picc_profile);
3176
0
            if_debug0m(gs_debug_flag_icc, ctx->memory, "[icc] OutputIntent used for device profile\n");
3177
0
        } else {
3178
0
            if (dev_profile->proof_profile == NULL) {
3179
                /* This means that we should use the OI profile as the proofing
3180
                   profile.  Note that if someone already has specified a
3181
                   proofing profile it is unclear what they are trying to do
3182
                   with the output intent.  In this case, we will use it
3183
                   just for the source data below */
3184
0
                dev_profile->proof_profile = picc_profile;
3185
0
                rc_increment(picc_profile);
3186
0
                if_debug0m(gs_debug_flag_icc, ctx->memory, "[icc] OutputIntent used for proof profile\n");
3187
0
            }
3188
0
        }
3189
0
    }
3190
3191
    /* Now the source colors.  See which source color space needs to use the
3192
       output intent ICC profile */
3193
0
    index = gsicc_get_default_type(source_profile);
3194
0
    if (index < gs_color_space_index_DevicePixel) {
3195
        /* source_profile is currently the default.  Set it to the OI profile */
3196
0
        switch (picc_profile->data_cs) {
3197
0
            case gsGRAY:
3198
0
                if_debug0m(gs_debug_flag_icc, ctx->memory, "[icc] OutputIntent used source Gray\n");
3199
0
                icc_manager->default_gray = picc_profile;
3200
0
                rc_increment(picc_profile);
3201
0
                break;
3202
0
            case gsRGB:
3203
0
                if_debug0m(gs_debug_flag_icc, ctx->memory, "[icc] OutputIntent used source RGB\n");
3204
0
                icc_manager->default_rgb = picc_profile;
3205
0
                rc_increment(picc_profile);
3206
0
                break;
3207
0
            case gsCMYK:
3208
0
                if_debug0m(gs_debug_flag_icc, ctx->memory, "[icc] OutputIntent used source CMYK\n");
3209
0
                icc_manager->default_cmyk = picc_profile;
3210
0
                rc_increment(picc_profile);
3211
0
                break;
3212
0
            default:
3213
0
                break;
3214
0
        }
3215
0
    }
3216
3217
0
 exit:
3218
0
    if (picc_profile != NULL)
3219
0
        rc_decrement(picc_profile, "pdfi_color_setoutputintent");
3220
0
    return code;
3221
0
}
3222
3223
/*
3224
 * intent_dict -- the outputintent dictionary
3225
 * profile -- the color profile (a stream)
3226
 *
3227
 */
3228
int pdfi_color_setoutputintent(pdf_context *ctx, pdf_dict *intent_dict, pdf_stream *profile)
3229
0
{
3230
0
    pdf_c_stream *profile_stream = NULL;
3231
0
    byte *profile_buffer;
3232
0
    int code, code1;
3233
0
    pdf_dict *profile_dict;
3234
3235
0
    code = pdfi_dict_from_obj(ctx, (pdf_obj *)profile, &profile_dict);
3236
0
    if (code < 0)
3237
0
        return code;
3238
3239
    /* The ICC profile reading code (irritatingly) requires a seekable stream, because it
3240
     * rewinds it to the start, then seeks to the end to find the size, then rewinds the
3241
     * stream again.
3242
     * Ideally we would use a ReusableStreamDecode filter here, but that is largely
3243
     * implemented in PostScript (!) so we can't use it. What we can do is create a
3244
     * string sourced stream in memory, which is at least seekable.
3245
     */
3246
0
    code = pdfi_open_memory_stream_from_filtered_stream(ctx, profile, &profile_buffer, &profile_stream, true);
3247
0
    if (code < 0)
3248
0
        goto exit;
3249
3250
    /* Create and set the device profile */
3251
0
    code = pdfi_device_setoutputintent(ctx, profile_dict, profile_stream->s);
3252
3253
0
    code1 = pdfi_close_memory_stream(ctx, profile_buffer, profile_stream);
3254
3255
0
    if (code == 0)
3256
0
        code = code1;
3257
3258
0
 exit:
3259
0
    return code;
3260
0
}
3261
3262
static int Check_Default_Space(pdf_context *ctx, pdf_obj *space, pdf_dict *source_dict, int num_components)
3263
794
{
3264
794
    pdf_obj *primary = NULL;
3265
794
    pdf_obj *ref_space = NULL;
3266
794
    int code = 0;
3267
3268
794
    if (pdfi_type_of(space) == PDF_NAME)
3269
0
    {
3270
0
        if (pdfi_name_is((const pdf_name *)space, "DeviceGray"))
3271
0
            return (num_components == 1 ? 0 : gs_error_rangecheck);
3272
0
        if (pdfi_name_is((const pdf_name *)space, "DeviceCMYK"))
3273
0
            return (num_components == 4 ? 0 : gs_error_rangecheck);
3274
0
        if (pdfi_name_is((const pdf_name *)space, "DeviceRGB"))
3275
0
            return (num_components == 3 ? 0 : gs_error_rangecheck);
3276
3277
0
        code = pdfi_find_resource(ctx, (unsigned char *)"ColorSpace", (pdf_name *)space, (pdf_dict *)source_dict,
3278
0
                                  NULL, &ref_space);
3279
0
        if (code < 0)
3280
0
            return code;
3281
3282
0
        if (pdfi_type_of(ref_space) == PDF_NAME) {
3283
0
            if (ref_space->object_num != 0 && ref_space->object_num == space->object_num) {
3284
0
                pdfi_countdown(ref_space);
3285
0
                return_error(gs_error_circular_reference);
3286
0
            }
3287
0
            if (pdfi_name_is((const pdf_name *)ref_space, "DeviceGray")) {
3288
0
                pdfi_countdown(ref_space);
3289
0
                return (num_components == 1 ? 0 : gs_error_rangecheck);
3290
0
            }
3291
0
            if (pdfi_name_is((const pdf_name *)ref_space, "DeviceCMYK")) {
3292
0
                pdfi_countdown(ref_space);
3293
0
                return (num_components == 4 ? 0 : gs_error_rangecheck);
3294
0
            }
3295
0
            if (pdfi_name_is((const pdf_name *)ref_space, "DeviceRGB")) {
3296
0
                pdfi_countdown(ref_space);
3297
0
                return (num_components == 3 ? 0 : gs_error_rangecheck);
3298
0
            }
3299
0
            pdfi_countdown(ref_space);
3300
0
            return_error(gs_error_typecheck);
3301
0
        }
3302
0
        space = ref_space;
3303
0
    }
3304
3305
794
    if (pdfi_type_of(space) == PDF_ARRAY) {
3306
776
        code = pdfi_array_get(ctx, (pdf_array *)space, 0, &primary);
3307
776
        if (code < 0)
3308
0
            goto exit;
3309
3310
776
        if (pdfi_type_of(primary) == PDF_NAME) {
3311
776
            if (pdfi_name_is((pdf_name *)primary, "Lab")) {
3312
0
                code = gs_note_error(gs_error_typecheck);
3313
0
                goto exit;
3314
0
            }
3315
776
            if (pdfi_name_is((pdf_name *)primary, "Pattern")) {
3316
4
                code = gs_note_error(gs_error_typecheck);
3317
4
                goto exit;
3318
4
            }
3319
772
            if (pdfi_name_is((pdf_name *)primary, "Indexed")) {
3320
0
                code = gs_note_error(gs_error_typecheck);
3321
0
                goto exit;
3322
0
            }
3323
772
        }
3324
776
    } else
3325
18
        code = gs_note_error(gs_error_typecheck);
3326
3327
794
exit:
3328
794
    pdfi_countdown(primary);
3329
794
    pdfi_countdown(ref_space);
3330
794
    return code;
3331
794
}
3332
3333
int pdfi_setup_DefaultSpaces(pdf_context *ctx, pdf_dict *source_dict)
3334
398k
{
3335
398k
    int code = 0;
3336
398k
    pdf_dict *resources_dict = NULL, *colorspaces_dict = NULL;
3337
398k
    pdf_obj *DefaultSpace = NULL;
3338
3339
398k
    if (ctx->args.NOSUBSTDEVICECOLORS)
3340
0
        return 0;
3341
3342
    /* Create any required DefaultGray, DefaultRGB or DefaultCMYK
3343
     * spaces.
3344
     */
3345
398k
    code = pdfi_dict_knownget(ctx, source_dict, "Resources", (pdf_obj **)&resources_dict);
3346
398k
    if (code > 0) {
3347
327k
        code = pdfi_dict_knownget(ctx, resources_dict, "ColorSpace", (pdf_obj **)&colorspaces_dict);
3348
327k
        if (code > 0) {
3349
37.9k
            code = pdfi_dict_knownget(ctx, colorspaces_dict, "DefaultGray", &DefaultSpace);
3350
37.9k
            if (code > 0) {
3351
0
                gs_color_space *pcs;
3352
3353
0
                code = Check_Default_Space(ctx, DefaultSpace, source_dict, 1);
3354
0
                if (code >= 0) {
3355
0
                    code = pdfi_create_colorspace(ctx, DefaultSpace, NULL, source_dict, &pcs, false);
3356
                    /* If any given Default* space fails simply ignore it, we wil then use the Device
3357
                     * space instead, this is as per the spec.
3358
                     */
3359
0
                    if (code >= 0) {
3360
0
                        if (gs_color_space_num_components(pcs) == 1) {
3361
0
                            ctx->page.DefaultGray_cs = pcs;
3362
0
                            pdfi_set_colour_callback(pcs, ctx, NULL);
3363
0
                        } else {
3364
0
                            rc_decrement(pcs, "setup_DefautSpaces");
3365
0
                            if ((code = pdfi_set_warning_stop(ctx, gs_note_error(gs_error_syntaxerror), NULL, W_PDF_INVALID_DEFAULTSPACE, "pdfi_setup_DefaultSpaces", NULL)) < 0)
3366
0
                                return code;
3367
0
                        }
3368
0
                    }
3369
0
                } else {
3370
0
                    if ((code = pdfi_set_warning_stop(ctx, gs_note_error(gs_error_syntaxerror), NULL, W_PDF_INVALID_DEFAULTSPACE, "pdfi_setup_DefaultSpaces", NULL)) < 0)
3371
0
                        return code;
3372
0
                }
3373
0
            }
3374
37.9k
            pdfi_countdown(DefaultSpace);
3375
37.9k
            DefaultSpace = NULL;
3376
37.9k
            code = pdfi_dict_knownget(ctx, colorspaces_dict, "DefaultRGB", &DefaultSpace);
3377
37.9k
            if (code > 0) {
3378
767
                gs_color_space *pcs;
3379
3380
767
                code = Check_Default_Space(ctx, DefaultSpace, source_dict, 1);
3381
767
                if (code >= 0) {
3382
745
                    code = pdfi_create_colorspace(ctx, DefaultSpace, NULL, source_dict, &pcs, false);
3383
                    /* If any given Default* space fails simply ignore it, we wil then use the Device
3384
                     * space instead, this is as per the spec.
3385
                     */
3386
745
                    if (code >= 0) {
3387
645
                        if (gs_color_space_num_components(pcs) == 3) {
3388
645
                            ctx->page.DefaultRGB_cs = pcs;
3389
645
                            pdfi_set_colour_callback(pcs, ctx, NULL);
3390
645
                        } else {
3391
0
                            rc_decrement(pcs, "setup_DefautSpaces");
3392
0
                            if ((code = pdfi_set_warning_stop(ctx, gs_note_error(gs_error_syntaxerror), NULL, W_PDF_INVALID_DEFAULTSPACE, "pdfi_setup_DefaultSpaces", NULL)) < 0)
3393
0
                                return code;
3394
0
                        }
3395
645
                    }
3396
745
                } else {
3397
22
                    if ((code = pdfi_set_warning_stop(ctx, gs_note_error(gs_error_syntaxerror), NULL, W_PDF_INVALID_DEFAULTSPACE, "pdfi_setup_DefaultSpaces", NULL)) < 0)
3398
0
                        return code;
3399
22
                }
3400
767
            }
3401
37.9k
            pdfi_countdown(DefaultSpace);
3402
37.9k
            DefaultSpace = NULL;
3403
37.9k
            code = pdfi_dict_knownget(ctx, colorspaces_dict, "DefaultCMYK", &DefaultSpace);
3404
37.9k
            if (code > 0) {
3405
27
                gs_color_space *pcs;
3406
3407
27
                code = Check_Default_Space(ctx, DefaultSpace, source_dict, 1);
3408
27
                if (code >= 0) {
3409
27
                    code = pdfi_create_colorspace(ctx, DefaultSpace, NULL, source_dict, &pcs, false);
3410
                    /* If any given Default* space fails simply ignore it, we wil then use the Device
3411
                     * space instead, this is as per the spec.
3412
                     */
3413
27
                    if (code >= 0) {
3414
27
                        if (gs_color_space_num_components(pcs) == 4) {
3415
27
                            ctx->page.DefaultCMYK_cs = pcs;
3416
27
                            pdfi_set_colour_callback(pcs, ctx, NULL);
3417
27
                        } else {
3418
0
                            rc_decrement(pcs, "setup_DefautSpaces");
3419
0
                            if ((code = pdfi_set_warning_stop(ctx, gs_note_error(gs_error_syntaxerror), NULL, W_PDF_INVALID_DEFAULTSPACE, "pdfi_setup_DefaultSpaces", NULL)) < 0)
3420
0
                                return code;
3421
0
                        }
3422
27
                    }
3423
27
                } else {
3424
0
                    if ((code = pdfi_set_warning_stop(ctx, gs_note_error(gs_error_syntaxerror), NULL, W_PDF_INVALID_DEFAULTSPACE, "pdfi_setup_DefaultSpaces", NULL)) < 0)
3425
0
                        return code;
3426
0
                }
3427
27
            }
3428
37.9k
            pdfi_countdown(DefaultSpace);
3429
37.9k
            DefaultSpace = NULL;
3430
37.9k
        }
3431
327k
    }
3432
3433
398k
    pdfi_countdown(DefaultSpace);
3434
398k
    pdfi_countdown(resources_dict);
3435
398k
    pdfi_countdown(colorspaces_dict);
3436
398k
    return 0;
3437
398k
}