Coverage Report

Created: 2026-10-28 08:05

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
17.0k
{
65
17.0k
    pdf_obj *ref_space;
66
17.0k
    int code;
67
68
17.0k
    if (pdfi_name_is(name, "G")) {
69
0
        return 0;
70
17.0k
    } else if (pdfi_name_is(name, "RGB")) {
71
0
        return 0;
72
17.0k
    } else if (pdfi_name_is(name, "CMYK")) {
73
0
        return 0;
74
17.0k
    } else if (pdfi_name_is(name, "DeviceRGB")) {
75
14.2k
        return 0;
76
14.2k
    } else if (pdfi_name_is(name, "DeviceGray")) {
77
1.34k
        return 0;
78
1.41k
    } else if (pdfi_name_is(name, "DeviceCMYK")) {
79
1.12k
        return 0;
80
1.12k
    } else if (pdfi_name_is(name, "Pattern")) {
81
        /* TODO: I think this is fine... */
82
220
        return 0;
83
220
    } else {
84
74
        code = pdfi_find_resource(ctx, (unsigned char *)"ColorSpace", name, parent_dict, page_dict, &ref_space);
85
74
        if (code < 0)
86
70
            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
17.0k
}
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
12.3k
{
104
12.3k
    pdf_name *space = NULL;
105
12.3k
    pdf_array *a = NULL;
106
12.3k
    int code = 0;
107
108
12.3k
    if (!spot_dict)
109
0
        return 0;
110
111
12.3k
    code = pdfi_array_get_type(ctx, color_array, 0, PDF_NAME, (pdf_obj **)&space);
112
12.3k
    if (code != 0)
113
10
        goto exit;
114
115
12.3k
    code = 0;
116
12.3k
    if (pdfi_name_is(space, "G")) {
117
0
        goto exit;
118
12.3k
    } else if (pdfi_name_is(space, "I") || pdfi_name_is(space, "Indexed")) {
119
2.87k
        pdf_obj *base_space;
120
121
2.87k
        code = pdfi_array_get(ctx, color_array, 1, &base_space);
122
2.87k
        if (code == 0) {
123
2.82k
            code = pdfi_check_ColorSpace_for_spots(ctx, base_space, parent_dict, page_dict, spot_dict);
124
2.82k
            (void)pdfi_countdown(base_space);
125
2.82k
        }
126
2.87k
        goto exit;
127
9.44k
    } else if (pdfi_name_is(space, "Pattern")) {
128
363
        pdf_obj *base_space = NULL;
129
363
        uint64_t size = pdfi_array_size(color_array);
130
131
        /* Array of size 1 "[ /Pattern ]" is okay, just do nothing. */
132
363
        if (size == 1)
133
221
            goto exit;
134
        /* Array of size > 2 we don't handle (shouldn't happen?) */
135
142
        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
142
        code = pdfi_array_get(ctx, color_array, 1, &base_space);
143
142
        if (code == 0) {
144
142
            code = pdfi_check_ColorSpace_for_spots(ctx, base_space, parent_dict, page_dict, spot_dict);
145
142
            (void)pdfi_countdown(base_space);
146
142
        }
147
142
        goto exit;
148
9.08k
    } else if (pdfi_name_is(space, "Lab")) {
149
118
        goto exit;
150
8.96k
    } else if (pdfi_name_is(space, "RGB")) {
151
0
        goto exit;
152
8.96k
    } else if (pdfi_name_is(space, "CMYK")) {
153
0
        goto exit;
154
8.96k
    } else if (pdfi_name_is(space, "CalRGB")) {
155
284
        goto exit;
156
8.68k
    } else if (pdfi_name_is(space, "CalGray")) {
157
44
        goto exit;
158
8.64k
    } else if (pdfi_name_is(space, "CalCMYK")) {
159
0
        goto exit;
160
8.64k
    } else if (pdfi_name_is(space, "ICCBased")) {
161
6.96k
        goto exit;
162
6.96k
    } else if (pdfi_name_is(space, "DeviceRGB")) {
163
0
        goto exit;
164
1.67k
    } else if (pdfi_name_is(space, "DeviceGray")) {
165
0
        goto exit;
166
1.67k
    } else if (pdfi_name_is(space, "DeviceCMYK")) {
167
0
        goto exit;
168
1.67k
    } else if (pdfi_name_is(space, "DeviceN")) {
169
388
        bool known = false;
170
388
        pdf_obj *dummy, *name;
171
388
        int i;
172
173
388
        pdfi_countdown(space);
174
388
        code = pdfi_array_get_type(ctx, color_array, 1, PDF_ARRAY, (pdf_obj **)&space);
175
388
        if (code != 0)
176
2
            goto exit;
177
178
1.16k
        for (i=0;i < pdfi_array_size((pdf_array *)space); i++) {
179
774
            code = pdfi_array_get_type(ctx, (pdf_array *)space, (uint64_t)i, PDF_NAME, &name);
180
774
            if (code < 0)
181
0
                goto exit;
182
183
774
            if (pdfi_name_is((const pdf_name *)name, "Cyan") || pdfi_name_is((const pdf_name *)name, "Magenta") ||
184
624
                pdfi_name_is((const pdf_name *)name, "Yellow") || pdfi_name_is((const pdf_name *)name, "Black") ||
185
470
                pdfi_name_is((const pdf_name *)name, "None") || pdfi_name_is((const pdf_name *)name, "All")) {
186
187
470
                pdfi_countdown(name);
188
470
                continue;
189
470
            }
190
191
304
            code = pdfi_dict_known_by_key(ctx, spot_dict, (pdf_name *)name, &known);
192
304
            if (code < 0) {
193
0
                pdfi_countdown(name);
194
0
                goto exit;
195
0
            }
196
304
            if (known) {
197
24
                pdfi_countdown(name);
198
24
                continue;
199
24
            }
200
201
280
            code = pdfi_object_alloc(ctx, PDF_INT, 0, &dummy);
202
280
            if (code < 0)
203
0
                goto exit;
204
205
280
            code = pdfi_dict_put_obj(ctx, spot_dict, name, dummy, true);
206
280
            pdfi_countdown(name);
207
280
            if (code < 0)
208
0
                break;
209
280
        }
210
386
        goto exit;
211
1.29k
    } else if (pdfi_name_is(space, "Separation")) {
212
1.26k
        bool known = false;
213
1.26k
        pdf_obj *dummy;
214
215
1.26k
        pdfi_countdown(space);
216
1.26k
        code = pdfi_array_get_type(ctx, color_array, 1, PDF_NAME, (pdf_obj **)&space);
217
1.26k
        if (code != 0)
218
0
            goto exit;
219
220
1.26k
        if (pdfi_name_is((const pdf_name *)space, "Cyan") || pdfi_name_is((const pdf_name *)space, "Magenta") ||
221
1.26k
            pdfi_name_is((const pdf_name *)space, "Yellow") || pdfi_name_is((const pdf_name *)space, "Black") ||
222
292
            pdfi_name_is((const pdf_name *)space, "None") || pdfi_name_is((const pdf_name *)space, "All"))
223
968
            goto exit;
224
292
        code = pdfi_dict_known_by_key(ctx, spot_dict, space, &known);
225
292
        if (code < 0 || known)
226
80
            goto exit;
227
228
212
        code = pdfi_object_alloc(ctx, PDF_INT, 0, &dummy);
229
212
        if (code < 0)
230
0
            goto exit;
231
232
212
        code = pdfi_dict_put_obj(ctx, spot_dict, (pdf_obj *)space, dummy, true);
233
212
        goto exit;
234
212
    } else {
235
30
        code = pdfi_find_resource(ctx, (unsigned char *)"ColorSpace",
236
30
                                  space, parent_dict, page_dict, (pdf_obj **)&a);
237
30
        if (code < 0)
238
30
            goto exit;
239
240
0
        if (pdfi_type_of(a) != PDF_ARRAY) {
241
0
            code = gs_note_error(gs_error_typecheck);
242
0
            goto exit;
243
0
        }
244
0
        if (a == color_array) {
245
0
            code = gs_note_error(gs_error_circular_reference);
246
0
            goto exit;
247
0
        }
248
249
        /* recursion */
250
0
        code = pdfi_check_for_spots_by_array(ctx, a, parent_dict, page_dict, spot_dict);
251
0
    }
252
253
12.3k
 exit:
254
12.3k
    if (space)
255
12.3k
        pdfi_countdown(space);
256
12.3k
    if (a)
257
0
        pdfi_countdown(a);
258
12.3k
    return code;
259
12.3k
}
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
29.6k
{
264
29.6k
    int code;
265
266
29.6k
    if (!spot_dict)
267
0
        return 0;
268
269
29.6k
    code = pdfi_loop_detector_mark(ctx);
270
29.6k
    if (code < 0)
271
0
        return code;
272
273
29.6k
    switch(pdfi_type_of(space)) {
274
17.0k
        case PDF_NAME:
275
17.0k
            code = pdfi_check_for_spots_by_name(ctx, (pdf_name *)space, parent_dict, page_dict, spot_dict);
276
17.0k
            break;
277
12.3k
        case PDF_ARRAY:
278
12.3k
            code = pdfi_check_for_spots_by_array(ctx, (pdf_array *)space, parent_dict, page_dict, spot_dict);
279
12.3k
            break;
280
256
        default:
281
256
            pdfi_loop_detector_cleartomark(ctx);
282
256
            return 0;
283
29.6k
    }
284
285
29.3k
    (void)pdfi_loop_detector_cleartomark(ctx);
286
29.3k
    return code;
287
29.6k
}
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
92.1k
{
294
92.1k
    pdf_name *n;
295
92.1k
    int code;
296
297
92.1k
    if (pdfi_count_stack(ctx) < 1)
298
16.8k
        return_error(gs_error_stackunderflow);
299
300
75.2k
    if (pdfi_type_of(ctx->stack_top[-1]) != PDF_NAME) {
301
2.78k
        pdfi_pop(ctx, 1);
302
2.78k
        return_error(gs_error_typecheck);
303
2.78k
    }
304
72.4k
    n = (pdf_name *)ctx->stack_top[-1];
305
72.4k
    pdfi_countup(n);
306
72.4k
    pdfi_pop(ctx, 1);
307
72.4k
    code = pdfi_setrenderingintent(ctx, n);
308
72.4k
    pdfi_countdown(n);
309
72.4k
    return code;
310
75.2k
}
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.33M
{
327
1.33M
    gs_color_space *pcs = (gs_color_space *)cs;
328
1.33M
    pdf_obj *o = (pdf_obj *)pcs->interpreter_data;
329
1.33M
    pdf_context *ctx = NULL;
330
1.33M
    gs_function_t *pfn;
331
332
1.33M
    if (o == NULL)
333
63
        return;
334
335
1.33M
    ctx = o->ctx;
336
337
1.33M
    if (gs_color_space_get_index(pcs) == gs_color_space_index_Separation) {
338
        /* Handle cleanup of Separation functions if applicable */
339
27.3k
        pfn = gs_cspace_get_sepr_function(pcs);
340
27.3k
        if (pfn)
341
27.3k
            pdfi_free_function(ctx, pfn);
342
27.3k
    }
343
344
1.33M
    if (gs_color_space_get_index(pcs) == gs_color_space_index_DeviceN) {
345
        /* Handle cleanup of DeviceN functions if applicable */
346
4.32k
        pfn = gs_cspace_get_devn_function(pcs);
347
4.32k
        if (pfn)
348
4.32k
            pdfi_free_function(ctx, pfn);
349
4.32k
    }
350
1.33M
    if (pdfi_type_of(o) != PDF_CTX) {
351
45.8k
        pdfi_countdown(o);
352
45.8k
        pcs->interpreter_data = NULL;
353
45.8k
    }
354
1.33M
}
355
356
int pdfi_gs_setgray(pdf_context *ctx, double d)
357
1.11M
{
358
1.11M
    int code = 0;
359
1.11M
    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.11M
    if (ctx->text.inside_CharProc && ctx->text.CharProc_d_type != pdf_type3_d0) {
363
10.9k
        pdfi_log_info(ctx, "pdfi_gs_setgray", "colour operator in a CharProc, following a d1 ignored\n");
364
10.9k
        return 0;
365
10.9k
    }
366
367
1.10M
    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.10M
    } else {
382
1.10M
        code = gs_setgray(ctx->pgs, d);
383
1.10M
        if (code < 0)
384
12
            return code;
385
1.10M
    }
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.10M
    if (pcs != ctx->pgs->color[0].color_space)
390
478k
        pdfi_set_colour_callback(ctx->pgs->color[0].color_space, ctx, pdfi_cspace_free_callback);
391
1.10M
    return 0;
392
1.10M
}
393
394
int pdfi_gs_setrgbcolor(pdf_context *ctx, double r, double g, double b)
395
1.74M
{
396
1.74M
    int code = 0;
397
1.74M
    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.74M
    if (ctx->text.inside_CharProc && ctx->text.CharProc_d_type != pdf_type3_d0) {
401
311
        pdfi_log_info(ctx, "pdfi_gs_setrgbcolor", "colour operator in a CharProc, following a d1 ignored\n");
402
311
        return 0;
403
311
    }
404
405
1.74M
    if (ctx->page.DefaultRGB_cs != NULL) {
406
12.6k
        gs_client_color cc;
407
408
12.6k
        code = gs_setcolorspace(ctx->pgs, ctx->page.DefaultRGB_cs);
409
12.6k
        if (code < 0)
410
0
            return code;
411
        /* If we didn't change the colour space in the graphics state, do not attempt to
412
         * set the callbacks, the current space might be inherited from PostScript.
413
         */
414
12.6k
        if (pcs != ctx->pgs->color[0].color_space)
415
4.32k
            pdfi_set_colour_callback(ctx->pgs->color[0].color_space, ctx, pdfi_cspace_free_callback);
416
12.6k
        cc.paint.values[0] = r;
417
12.6k
        cc.paint.values[1] = g;
418
12.6k
        cc.paint.values[2] = b;
419
12.6k
        cc.pattern = 0;
420
12.6k
        return gs_setcolor(ctx->pgs, &cc);
421
1.73M
    } else {
422
1.73M
        code = gs_setrgbcolor(ctx->pgs, r, g, b);
423
1.73M
        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.73M
        if (pcs != ctx->pgs->color[0].color_space)
429
566k
            pdfi_set_colour_callback(ctx->pgs->color[0].color_space, ctx, pdfi_cspace_free_callback);
430
1.73M
    }
431
1.73M
    return 0;
432
1.74M
}
433
434
static int pdfi_gs_setcmykcolor(pdf_context *ctx, double c, double m, double y, double k)
435
185k
{
436
185k
    int code = 0;
437
185k
    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
185k
    if (ctx->text.inside_CharProc && ctx->text.CharProc_d_type != pdf_type3_d0) {
441
40
        pdfi_log_info(ctx, "pdfi_gs_setcmykcolor", "colour operator in a CharProc, following a d1 ignored\n");
442
40
        return 0;
443
40
    }
444
445
185k
    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
185k
    } else {
463
185k
        code = gs_setcmykcolor(ctx->pgs, c, m, y, k);
464
185k
        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
185k
        if (pcs != ctx->pgs->color[0].color_space)
470
76.6k
            pdfi_set_colour_callback(ctx->pgs->color[0].color_space, ctx, pdfi_cspace_free_callback);
471
185k
    }
472
185k
    return 0;
473
185k
}
474
475
int pdfi_gs_setcolorspace(pdf_context *ctx, gs_color_space *pcs)
476
255k
{
477
255k
    gs_color_space *old_pcs = ctx->pgs->color[0].color_space;
478
255k
    int code = 0;
479
    /* If the target colour space is already the current colour space, don't
480
     * bother to do anything.
481
     */
482
255k
    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
237k
        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
237k
        code = gs_setcolorspace(ctx->pgs, pcs);
490
237k
        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
237k
        if (old_pcs != ctx->pgs->color[0].color_space)
496
237k
            pdfi_set_colour_callback(ctx->pgs->color[0].color_space, ctx, pdfi_cspace_free_callback);
497
237k
    }
498
255k
    return 0;
499
255k
}
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
508k
{
504
508k
    int code;
505
508k
    double d1;
506
507
508k
    code = pdfi_destack_real(ctx, &d1);
508
508k
    if (code < 0)
509
25.4k
        return code;
510
511
483k
    gs_swapcolors_quick(ctx->pgs);
512
483k
    code = pdfi_gs_setgray(ctx, d1);
513
483k
    gs_swapcolors_quick(ctx->pgs);
514
515
483k
    return code;
516
508k
}
517
518
int pdfi_setgrayfill(pdf_context *ctx)
519
616k
{
520
616k
    int code;
521
616k
    double d1;
522
523
616k
    code = pdfi_destack_real(ctx, &d1);
524
616k
    if (code < 0)
525
10.6k
        return code;
526
527
605k
    return pdfi_gs_setgray(ctx, d1);
528
616k
}
529
530
int pdfi_setrgbstroke(pdf_context *ctx)
531
860k
{
532
860k
    double Values[3];
533
860k
    int code;
534
535
860k
    code = pdfi_destack_reals(ctx, Values, 3);
536
860k
    if (code < 0)
537
43.0k
        return code;
538
539
817k
    gs_swapcolors_quick(ctx->pgs);
540
817k
    code = pdfi_gs_setrgbcolor(ctx, Values[0], Values[1], Values[2]);
541
817k
    gs_swapcolors_quick(ctx->pgs);
542
543
817k
    return code;
544
860k
}
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
53.2k
{
551
53.2k
    int code;
552
53.2k
    pdf_array *array = NULL;
553
554
53.2k
    pdfi_set_warning(ctx, 0, NULL, W_PDF_NONSTANDARD_OP, "pdfi_setrgbfill_array", (char *)"WARNING: Non-standard 'r' operator");
555
556
53.2k
    if (pdfi_count_stack(ctx) < 1)
557
13.2k
        return_error(gs_error_stackunderflow);
558
559
40.0k
    array = (pdf_array *)ctx->stack_top[-1];
560
40.0k
    pdfi_countup(array);
561
40.0k
    pdfi_pop(ctx, 1);
562
40.0k
    if (pdfi_type_of(array) != PDF_ARRAY) {
563
39.9k
        code = gs_note_error(gs_error_typecheck);
564
39.9k
        goto exit;
565
39.9k
    }
566
567
61
    code = pdfi_setcolor_from_array(ctx, array);
568
40.0k
 exit:
569
40.0k
    pdfi_countdown(array);
570
40.0k
    return code;
571
61
}
572
573
int pdfi_setrgbfill(pdf_context *ctx)
574
934k
{
575
934k
    double Values[3];
576
934k
    int code;
577
578
934k
    code = pdfi_destack_reals(ctx, Values, 3);
579
934k
    if (code < 0)
580
30.6k
        return code;
581
582
903k
    return pdfi_gs_setrgbcolor(ctx, Values[0], Values[1], Values[2]);
583
934k
}
584
585
int pdfi_setcmykstroke(pdf_context *ctx)
586
47.3k
{
587
47.3k
    double Values[4];
588
47.3k
    int code;
589
590
47.3k
    code = pdfi_destack_reals(ctx, Values, 4);
591
47.3k
    if (code < 0)
592
10.3k
        return code;
593
594
36.9k
    gs_swapcolors_quick(ctx->pgs);
595
36.9k
    code = pdfi_gs_setcmykcolor(ctx, Values[0], Values[1], Values[2], Values[3]);
596
36.9k
    gs_swapcolors_quick(ctx->pgs);
597
598
36.9k
    return code;
599
47.3k
}
600
601
int pdfi_setcmykfill(pdf_context *ctx)
602
147k
{
603
147k
    double Values[4];
604
147k
    int code;
605
606
147k
    code = pdfi_destack_reals(ctx, Values, 4);
607
147k
    if (code < 0)
608
4.88k
        return code;
609
610
142k
    return pdfi_gs_setcmykcolor(ctx, Values[0], Values[1], Values[2], Values[3]);
611
147k
}
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.42k
{
619
6.42k
    int code = 0;
620
6.42k
    uint64_t size;
621
6.42k
    double values[4];
622
623
6.42k
    size = pdfi_array_size(array);
624
6.42k
    if (size != 1 && size != 3 && size != 4) {
625
70
        code = gs_note_error(gs_error_rangecheck);
626
70
        goto exit;
627
70
    }
628
629
6.35k
    code = pdfi_array_to_num_array(ctx, array, values, 0, size);
630
6.35k
    if (code < 0) goto exit;
631
632
6.33k
    switch (size) {
633
136
    case 1:
634
136
        code = pdfi_gs_setgray(ctx, values[0]);
635
136
        break;
636
6.17k
    case 3:
637
6.17k
        code = pdfi_gs_setrgbcolor(ctx, values[0], values[1], values[2]);
638
6.17k
        break;
639
16
    case 4:
640
16
        code = pdfi_gs_setcmykcolor(ctx, values[0], values[1], values[2], values[3]);
641
16
        break;
642
0
    default:
643
0
        break;
644
6.33k
    }
645
646
6.42k
 exit:
647
6.42k
    return code;
648
6.33k
}
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
278k
{
654
278k
    int i, code;
655
656
278k
    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
802k
    for (i = 0; i < ncomps; i++) {
662
552k
        code = pdfi_obj_to_float(ctx, ctx->stack_top[i - ncomps], &cc->paint.values[i]);
663
552k
        if (code < 0) {
664
10.6k
            pdfi_clearstack(ctx);
665
10.6k
            return code;
666
10.6k
        }
667
552k
    }
668
250k
    pdfi_pop(ctx, ncomps);
669
670
250k
    return 0;
671
261k
}
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
37.2k
{
683
37.2k
    const gs_color_space *  pcs;
684
37.2k
    int ncomps, code;
685
37.2k
    gs_client_color cc;
686
687
37.2k
    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
37.2k
    cc.pattern = 0;
698
37.2k
    gs_swapcolors_quick(ctx->pgs);
699
37.2k
    pcs = gs_currentcolorspace(ctx->pgs);
700
37.2k
    ncomps = cs_num_components(pcs);
701
37.2k
    if (ncomps < 1) {
702
3
        gs_swapcolors_quick(ctx->pgs);
703
3
        return_error(gs_error_syntaxerror);
704
3
    }
705
37.2k
    code = pdfi_get_color_from_stack(ctx, &cc, ncomps);
706
37.2k
    if (code == 0) {
707
35.0k
        if (pcs->type == &gs_color_space_type_Indexed) {
708
            /* Special handling for floating point colour values
709
             * PostScript doesn't specify what should happen with a float
710
             * lookup value. PDF says 'nearest integer' and round 0.5 up.
711
             * Doing this in the graphics library caused some (tiny) differences
712
             * in output files, so instead perform that check here.
713
             * The out of range clamping is already correct in the graphics library.
714
             */
715
0
            int index = (int)floor(cc.paint.values[0]);
716
717
0
            if(cc.paint.values[0] - index > 0.49999)
718
0
                index++;
719
0
            cc.paint.values[0] = (float)index;
720
0
        }
721
35.0k
        code = gs_setcolor(ctx->pgs, &cc);
722
35.0k
    }
723
37.2k
    gs_swapcolors_quick(ctx->pgs);
724
37.2k
    return code;
725
37.2k
}
726
727
int pdfi_setfillcolor(pdf_context *ctx)
728
156k
{
729
156k
    const gs_color_space *  pcs = gs_currentcolorspace(ctx->pgs);
730
156k
    int ncomps, code;
731
156k
    gs_client_color cc;
732
733
156k
    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
156k
    cc.pattern = 0;
744
156k
    ncomps = cs_num_components(pcs);
745
156k
    if (ncomps < 1)
746
153
        return_error(gs_error_syntaxerror);
747
155k
    code = pdfi_get_color_from_stack(ctx, &cc, ncomps);
748
155k
    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
108
            int index = (int)floor(cc.paint.values[0]);
758
759
108
            if(cc.paint.values[0] - index > 0.49999)
760
0
                index++;
761
108
            cc.paint.values[0] = (float)index;
762
108
        }
763
146k
        code = gs_setcolor(ctx->pgs, &cc);
764
146k
    }
765
155k
    return code;
766
156k
}
767
768
static inline bool
769
pattern_instance_uses_base_space(const gs_pattern_instance_t * pinst)
770
256
{
771
256
    return pinst->type->procs.uses_base_space(
772
256
                   pinst->type->procs.get_pattern(pinst) );
773
256
}
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
137k
{
781
137k
    gs_color_space *pcs;
782
137k
    gs_color_space *base_space = NULL;
783
137k
    int ncomps=0, code = 0;
784
137k
    gs_client_color cc;
785
137k
    bool is_pattern = false;
786
787
137k
    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
1
        pdfi_clearstack(ctx);
793
1
        pdfi_log_info(ctx, "pdfi_setcolorN", "colour operator in a CharProc, following a d1 ignored\n");
794
1
        return 0;
795
1
    }
796
797
137k
    if (!is_fill) {
798
13.2k
        gs_swapcolors_quick(ctx->pgs);
799
13.2k
    }
800
137k
    pcs = gs_currentcolorspace(ctx->pgs);
801
802
137k
    if (pdfi_count_stack(ctx) < 1) {
803
1.31k
        code = gs_note_error(gs_error_stackunderflow);
804
1.31k
        goto cleanupExit1;
805
1.31k
    }
806
807
136k
    memset(&cc, 0x00, sizeof(gs_client_color));
808
809
136k
    if (pcs->type == &gs_color_space_type_Pattern)
810
51.1k
        is_pattern = true;
811
136k
    if (is_pattern) {
812
51.1k
        pdf_name *n = NULL;
813
814
51.1k
        if (pdfi_type_of(ctx->stack_top[-1]) != PDF_NAME) {
815
72
            pdfi_clearstack(ctx);
816
72
            code = gs_note_error(gs_error_typecheck);
817
72
            goto cleanupExit0;
818
72
        }
819
51.0k
        n = (pdf_name *)ctx->stack_top[-1];
820
51.0k
        pdfi_countup(n);
821
51.0k
        pdfi_pop(ctx, 1);
822
823
51.0k
        base_space = pcs->base_space;
824
51.0k
        code = pdfi_pattern_set(ctx, stream_dict, page_dict, n, &cc);
825
51.0k
        pdfi_countdown(n);
826
51.0k
        if (code < 0) {
827
            /* Ignore the pattern if we failed to set it */
828
32.6k
            code = pdfi_set_warning_stop(ctx, code, NULL, W_PDF_BADPATTERN, "pdfi_setcolorN", (char *)"PATTERN: Error setting pattern");
829
32.6k
            goto cleanupExit1;
830
32.6k
        }
831
18.3k
        if (base_space && pattern_instance_uses_base_space(cc.pattern))
832
247
            ncomps = cs_num_components(base_space);
833
18.1k
        else
834
18.1k
            ncomps = 0;
835
18.3k
    } else
836
85.1k
        ncomps = cs_num_components(pcs);
837
838
103k
    if (ncomps > 0) {
839
85.3k
        code = pdfi_get_color_from_stack(ctx, &cc, ncomps);
840
85.3k
        if (code < 0)
841
17.0k
            goto cleanupExit1;
842
85.3k
    }
843
844
86.4k
    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.4k
    code = gs_setcolor(ctx->pgs, &cc);
870
871
137k
cleanupExit1:
872
137k
    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
137k
        rc_decrement(cc.pattern, "pdfi_setcolorN");
878
879
137k
cleanupExit0:
880
137k
    if (!is_fill)
881
13.2k
        gs_swapcolors_quick(ctx->pgs);
882
137k
    return code;
883
137k
}
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
28.7k
{
892
28.7k
    int                     code, k;
893
28.7k
    gs_color_space *        pcs;
894
28.7k
    cmm_profile_t           *picc_profile = NULL;
895
28.7k
    int                     i, expected = 0;
896
897
28.7k
    static const char *const icc_std_profile_names[] = {
898
28.7k
            GSICC_STANDARD_PROFILES
899
28.7k
        };
900
28.7k
    static const char *const icc_std_profile_keys[] = {
901
28.7k
            GSICC_STANDARD_PROFILES_KEYS
902
28.7k
        };
903
904
28.7k
    if (ppcs!= NULL)
905
28.7k
        *ppcs = NULL;
906
907
    /* We need to use the graphics state memory, and beyond that we need to use stable memory, because the
908
     * ICC cache can persist until the end of job, and so the profile (which is stored in teh cache)
909
     * must likewise persist.
910
     */
911
28.7k
    code = gs_cspace_build_ICC(&pcs, NULL, (gs_gstate_memory(ctx->pgs))->stable_memory);
912
28.7k
    if (code < 0)
913
0
        return code;
914
915
28.7k
    if (Name != NULL){
916
        /* Compare this to the standard profile names */
917
8.20k
        for (k = 0; k < GSICC_NUMBER_STANDARD_PROFILES; k++) {
918
8.20k
            if ( strcmp( Name, icc_std_profile_keys[k] ) == 0 ) {
919
4.35k
                picc_profile = gsicc_get_profile_handle_file(icc_std_profile_names[k],
920
4.35k
                    strlen(icc_std_profile_names[k]), gs_gstate_memory(ctx->pgs));
921
4.35k
                break;
922
4.35k
            }
923
8.20k
        }
924
24.3k
    } else {
925
24.3k
        if (s == NULL)
926
0
            return_error(gs_error_undefined);
927
928
24.3k
        picc_profile = gsicc_profile_new(s, gs_gstate_memory(ctx->pgs), NULL, 0);
929
24.3k
        if (picc_profile == NULL) {
930
4.15k
            rc_decrement(pcs,"pdfi_create_icc");
931
4.15k
            return gs_throw(gs_error_VMerror, "pdfi_create_icc Creation of ICC profile failed");
932
4.15k
        }
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
20.2k
        picc_profile->profile_handle =
936
20.2k
            gsicc_get_profile_handle_buffer(picc_profile->buffer,
937
20.2k
                                            picc_profile->buffer_size,
938
20.2k
                                            gs_gstate_memory(ctx->pgs));
939
20.2k
    }
940
941
24.5k
    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.83k
        rc_decrement(picc_profile,"pdfi_create_icc");
945
2.83k
        rc_decrement(pcs,"pdfi_create_icc");
946
2.83k
        return -1;
947
2.83k
    }
948
21.7k
    code = gsicc_set_gscs_profile(pcs, picc_profile, gs_gstate_memory(ctx->pgs));
949
21.7k
    if (code < 0) {
950
0
        rc_decrement(picc_profile,"pdfi_create_icc");
951
0
        rc_decrement(pcs,"pdfi_create_icc");
952
0
        return code;
953
0
    }
954
955
21.7k
    picc_profile->data_cs =
956
21.7k
        gscms_get_profile_data_space(picc_profile->profile_handle,
957
21.7k
            picc_profile->memory);
958
21.7k
    switch (picc_profile->data_cs) {
959
0
        case gsCIEXYZ:
960
0
        case gsCIELAB:
961
13.4k
        case gsRGB:
962
13.4k
            expected = 3;
963
13.4k
            break;
964
8.00k
        case gsGRAY:
965
8.00k
            expected = 1;
966
8.00k
            break;
967
27
        case gsCMYK:
968
27
            expected = 4;
969
27
            break;
970
241
        case gsNCHANNEL:
971
241
        case gsNAMED:            /* Silence warnings */
972
241
        case gsUNDEFINED:        /* Silence warnings */
973
241
            break;
974
21.7k
    }
975
21.7k
    if (expected == 0) {
976
241
        rc_decrement(picc_profile,"pdfi_create_icc");
977
241
        rc_decrement(pcs,"pdfi_create_icc");
978
241
        return_error(gs_error_rangecheck);
979
241
    }
980
    /* Return the number of components the ICC profile has */
981
21.4k
    *icc_N = expected;
982
21.4k
    if (expected != ncomps) {
983
16
        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
16
        ncomps = expected;
986
16
    }
987
988
21.4k
    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.4k
    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.4k
    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.4k
    } else {
1020
69.9k
        for (i = 0; i < ncomps; i++) {
1021
48.4k
            picc_profile->Range.ranges[i].rmin = range_buff[2 * i];
1022
48.4k
            picc_profile->Range.ranges[i].rmax = range_buff[2 * i + 1];
1023
48.4k
        }
1024
21.4k
    }
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.4k
    if (gs_currentoverrideicc(ctx->pgs) && picc_profile->data_cs != gsCIELAB) {
1028
        /* Free up the profile structure */
1029
32
        switch( picc_profile->data_cs ) {
1030
1
            case gsRGB:
1031
1
                pcs->cmm_icc_profile_data = ctx->pgs->icc_manager->default_rgb;
1032
1
                break;
1033
31
            case gsGRAY:
1034
31
                pcs->cmm_icc_profile_data = ctx->pgs->icc_manager->default_gray;
1035
31
                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
32
        }
1042
        /* Have one increment from the color space.  Having these tied
1043
           together is not really correct.  Need to fix that.  ToDo.  MJV */
1044
32
        rc_adjust(picc_profile, -2, "pdfi_create_icc");
1045
32
        rc_increment(pcs->cmm_icc_profile_data);
1046
32
    }
1047
    /* Add the color space to the profile cache */
1048
21.4k
    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.4k
    if (ppcs!= NULL){
1055
21.4k
        *ppcs = pcs;
1056
21.4k
        pdfi_set_colour_callback(pcs, ctx, pdfi_cspace_free_callback);
1057
21.4k
    } else {
1058
0
        code = pdfi_gs_setcolorspace(ctx, pcs);
1059
0
        rc_decrement_only_cs(pcs, "pdfi_create_icc");
1060
0
    }
1061
1062
21.4k
exit:
1063
    /* The context has taken a reference to the colorspace. We no longer need
1064
     * ours, so drop it. */
1065
21.4k
    rc_decrement(picc_profile, "pdfi_create_icc");
1066
21.4k
    return code;
1067
21.4k
}
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
109k
{
1072
109k
    pdf_c_stream *profile_stream = NULL;
1073
109k
    byte *profile_buffer;
1074
109k
    int code, code1;
1075
109k
    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
109k
    if (!gs_currentoverrideicc(ctx->pgs)) {
1084
109k
        if (ICC_obj->object_num != 0) {
1085
109k
            gs_color_space *pcs = NULL;
1086
1087
109k
            pcs = gsicc_find_cs(ICC_obj->object_num, ctx->pgs);
1088
109k
            if (pcs != NULL) {
1089
84.4k
                if (ppcs!= NULL){
1090
84.4k
                    *ppcs = pcs;
1091
84.4k
                } else {
1092
0
                    code = pdfi_gs_setcolorspace(ctx, pcs);
1093
0
                    rc_decrement_only_cs(pcs, "pdfi_create_iccprofile");
1094
0
                }
1095
84.4k
                *icc_N = gs_color_space_num_components(pcs);
1096
                /* We're passing back a new reference, increment the count */
1097
84.4k
                rc_adjust_only(pcs, 1, "pdfi_create_iccprofile, return cached ICC profile");
1098
84.4k
                return 0;
1099
84.4k
            }
1100
24.6k
            dictkey = ICC_obj->object_num;
1101
24.6k
        }
1102
109k
    }
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.6k
    code = pdfi_open_memory_stream_from_filtered_stream(ctx, ICC_obj, &profile_buffer, &profile_stream, true);
1112
24.6k
    if (code < 0) {
1113
272
        return code;
1114
272
    }
1115
1116
    /* Now, finally, we can call the code to create and set the profile */
1117
24.3k
    code = pdfi_create_icc(ctx, cname, profile_stream->s, (int)N, icc_N, range, dictkey, ppcs);
1118
1119
24.3k
    code1 = pdfi_close_memory_stream(ctx, profile_buffer, profile_stream);
1120
1121
24.3k
    if (code == 0)
1122
17.1k
        code = code1;
1123
1124
24.3k
    return code;
1125
24.6k
}
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
121k
{
1402
121k
    pdf_stream *ICC_obj = NULL;
1403
121k
    pdf_dict *dict; /* Alias to avoid tons of casting */
1404
121k
    pdf_array *a;
1405
121k
    int64_t Length, N;
1406
121k
    pdf_obj *Name = NULL, *Alt = NULL;
1407
121k
    char *cname = NULL;
1408
121k
    int code;
1409
121k
    bool known = true;
1410
121k
    float range[8];
1411
121k
    int icc_N;
1412
121k
    gs_color_space *pcs = NULL;
1413
1414
121k
    code = pdfi_array_get_type(ctx, color_array, index + 1, PDF_STREAM, (pdf_obj **)&ICC_obj);
1415
121k
    if (code < 0)
1416
10.5k
        return code;
1417
111k
    code = pdfi_dict_from_obj(ctx, (pdf_obj *)ICC_obj, &dict);
1418
111k
    if (code < 0)
1419
0
        return code;
1420
1421
111k
    Length = pdfi_stream_length(ctx, ICC_obj);
1422
111k
    code = pdfi_dict_get_int(ctx, dict, "N", &N);
1423
111k
    if (code < 0)
1424
968
        goto done;
1425
110k
    if (N != 1 && N != 3 && N != 4) {
1426
1.18k
        code = gs_note_error(gs_error_rangecheck);
1427
1.18k
        goto done;
1428
1.18k
    }
1429
109k
    code = pdfi_dict_knownget(ctx, dict, "Name", &Name);
1430
109k
    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
109k
    if (code < 0)
1447
0
        goto done;
1448
1449
109k
    code = pdfi_dict_knownget_type(ctx, dict, "Range", PDF_ARRAY, (pdf_obj **)&a);
1450
109k
    if (code < 0)
1451
0
        goto done;
1452
109k
    if (code > 0) {
1453
145
        double dbl;
1454
145
        int i;
1455
1456
145
        if (pdfi_array_size(a) >= N * 2) {
1457
981
            for (i = 0; i < N * 2;i++) {
1458
848
                code = pdfi_array_get_number(ctx, a, i, &dbl);
1459
848
                if (code < 0) {
1460
0
                    known = false;
1461
0
                    break;
1462
0
                }
1463
848
                range[i] = (float)dbl;
1464
848
            }
1465
133
        } else {
1466
12
            known = false;
1467
12
        }
1468
145
        pdfi_countdown(a);
1469
145
    } else
1470
108k
        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
109k
    if (!known) {
1478
108k
        int i;
1479
404k
        for (i = 0;i < N; i++) {
1480
295k
            range[i * 2] = 0;
1481
295k
            range[(i * 2) + 1] = 1;
1482
295k
        }
1483
108k
    }
1484
1485
109k
    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
109k
    if (code >= 0 && N != icc_N) {
1503
25
        gs_client_color cc;
1504
25
        int i;
1505
1506
25
        gs_gsave(ctx->pgs);
1507
25
        code = gs_setcolorspace(ctx->pgs, pcs);
1508
25
        if (code == 0) {
1509
25
            cc.pattern = 0;
1510
100
            for (i = 0;i < icc_N; i++)
1511
75
                cc.paint.values[i] = 0;
1512
25
            code = gs_setcolor(ctx->pgs, &cc);
1513
25
            if (code == 0)
1514
25
                code = gx_set_dev_color(ctx->pgs);
1515
25
        }
1516
25
        gs_grestore(ctx->pgs);
1517
25
    }
1518
1519
109k
    if (code < 0) {
1520
7.52k
        pdf_obj *Alternate = NULL;
1521
1522
7.52k
        if (pcs != NULL)
1523
7.52k
            rc_decrement(pcs,"pdfi_create_iccbased");
1524
1525
        /* Failed to set the ICCBased space, attempt to use the Alternate */
1526
7.52k
        code = pdfi_dict_knownget(ctx, dict, "Alternate", &Alternate);
1527
7.52k
        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.08k
            if (pdfi_type_of(Alternate) == PDF_NAME)
1530
7.08k
                code = pdfi_create_colorspace_by_name(ctx, (pdf_name *)Alternate, stream_dict,
1531
7.08k
                                                      page_dict, ppcs, inline_image);
1532
7.08k
            pdfi_countdown(Alternate);
1533
7.08k
            if (code == 0) {
1534
6.96k
                pdfi_set_warning(ctx, 0, NULL, W_PDF_BADICC_USE_ALT, "pdfi_create_iccbased", NULL);
1535
6.96k
                goto done;
1536
6.96k
            }
1537
7.08k
        }
1538
        /* Use the number of components *from the profile* to set a space.... */
1539
561
        pdfi_set_warning(ctx, 0, NULL, W_PDF_BADICC_USECOMPS, "pdfi_create_iccbased", NULL);
1540
561
        switch(N) {
1541
123
            case 1:
1542
123
                pcs = gs_cspace_new_DeviceGray(ctx->memory);
1543
123
                if (pcs == NULL)
1544
0
                    code = gs_note_error(gs_error_VMerror);
1545
123
                break;
1546
432
            case 3:
1547
432
                pcs = gs_cspace_new_DeviceRGB(ctx->memory);
1548
432
                if (pcs == NULL)
1549
0
                    code = gs_note_error(gs_error_VMerror);
1550
432
                break;
1551
6
            case 4:
1552
6
                pcs = gs_cspace_new_DeviceCMYK(ctx->memory);
1553
6
                if (pcs == NULL)
1554
0
                    code = gs_note_error(gs_error_VMerror);
1555
6
                break;
1556
0
            default:
1557
0
                code = gs_note_error(gs_error_undefined);
1558
0
                break;
1559
561
        }
1560
101k
    } else {
1561
101k
        if (pcs->ICC_Alternate_space == gs_ICC_Alternate_None) {
1562
18.7k
            code = pdfi_dict_knownget(ctx, dict, "Alternate", (pdf_obj **)&Alt);
1563
18.7k
            if (code >= 0) {
1564
18.7k
                switch(pdfi_type_of(Alt)) {
1565
15.8k
                    case PDF_NAME:
1566
                        /* Simple named spaces must be Gray, RGB or CMYK, we ignore /Indexed */
1567
15.8k
                        if (pdfi_name_is((const pdf_name *)Alt, "DeviceGray"))
1568
3.93k
                            pcs->ICC_Alternate_space = gs_ICC_Alternate_DeviceGray;
1569
11.8k
                        else if (pdfi_name_is((const pdf_name *)Alt, "DeviceRGB"))
1570
11.7k
                            pcs->ICC_Alternate_space = gs_ICC_Alternate_DeviceRGB;
1571
157
                        else if (pdfi_name_is((const pdf_name *)Alt, "DeviceCMYK"))
1572
27
                            pcs->ICC_Alternate_space = gs_ICC_Alternate_DeviceCMYK;
1573
15.8k
                        break;
1574
0
                    case PDF_ARRAY:
1575
0
                        {
1576
0
                            pdf_obj *AltName = NULL, *ParamsDict = NULL;
1577
1578
0
                            code = pdfi_array_get_type(ctx, (pdf_array *)Alt, 0, PDF_NAME, &AltName);
1579
0
                            if (code >= 0) {
1580
0
                                code = pdfi_array_get_type(ctx, (pdf_array *)Alt, 1, PDF_DICT, &ParamsDict);
1581
0
                                if (code >= 0) {
1582
0
                                    if (pdfi_name_is((const pdf_name *)AltName, "CalGray")) {
1583
0
                                        code = pdfi_set_CalGray_params(ctx, pcs, (pdf_dict *)ParamsDict);
1584
0
                                        if (code >= 0)
1585
0
                                            pcs->ICC_Alternate_space = gs_ICC_Alternate_CalGray;
1586
0
                                    } else {
1587
0
                                        if (pdfi_name_is((const pdf_name *)AltName, "CalRGB")) {
1588
0
                                            code = pdfi_set_CalRGB_params(ctx, pcs, (pdf_dict *)ParamsDict);
1589
0
                                            if (code >= 0)
1590
0
                                                pcs->ICC_Alternate_space = gs_ICC_Alternate_CalRGB;
1591
0
                                        } else {
1592
0
                                            if (pdfi_name_is((const pdf_name *)AltName, "CalCMYK")) {
1593
0
                                                pcs->ICC_Alternate_space = gs_ICC_Alternate_DeviceCMYK;
1594
0
                                            } else {
1595
0
                                                if (pdfi_name_is((const pdf_name *)AltName, "Lab")) {
1596
0
                                                    code = pdfi_set_Lab_params(ctx, pcs, (pdf_dict *)ParamsDict);
1597
0
                                                    if (code >= 0)
1598
0
                                                        pcs->ICC_Alternate_space = gs_ICC_Alternate_Lab;
1599
0
                                                }
1600
0
                                            }
1601
0
                                        }
1602
0
                                    }
1603
0
                                }
1604
0
                            }
1605
0
                            code = 0;
1606
0
                            pdfi_countdown(ParamsDict);
1607
0
                            pdfi_countdown(AltName);
1608
0
                        }
1609
0
                        break;
1610
2.97k
                    default:
1611
                        /* Probably an error, but just ignore it */
1612
2.97k
                        break;
1613
18.7k
                }
1614
18.7k
                pdfi_countdown(Alt);
1615
18.7k
                Alt = NULL;
1616
18.7k
            }
1617
18.7k
        }
1618
101k
    }
1619
1620
102k
    if (ppcs!= NULL) {
1621
29.6k
        *ppcs = pcs;
1622
29.6k
        if (pcs != NULL)
1623
29.6k
            pdfi_set_colour_callback(pcs, ctx, pdfi_cspace_free_callback);
1624
29.6k
    }
1625
72.5k
    else {
1626
72.5k
        if (pcs != NULL) {
1627
72.5k
            code = pdfi_gs_setcolorspace(ctx, pcs);
1628
            /* release reference from construction */
1629
72.5k
            rc_decrement_only_cs(pcs, "setseparationspace");
1630
72.5k
        }
1631
72.5k
    }
1632
1633
1634
111k
done:
1635
111k
    if (cname)
1636
0
        gs_free_object(ctx->memory, cname, "pdfi_create_iccbased (profile name)");
1637
111k
    pdfi_countdown(Alt);
1638
111k
    pdfi_countdown(Name);
1639
111k
    pdfi_countdown(ICC_obj);
1640
111k
    return code;
1641
102k
}
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
966
{
1651
966
    int                     code;
1652
966
    gs_color_space *        pcs;
1653
966
    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
966
    code = gs_cspace_build_ICC(&pcs, NULL, (gs_gstate_memory(ctx->pgs))->stable_memory);
1661
966
    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
966
    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
966
    code = gsicc_set_gscs_profile(pcs, ctx->pgs->icc_manager->lab_profile, gs_gstate_memory(ctx->pgs));
1675
966
    if (code < 0)
1676
0
        return code;
1677
1678
966
    pcs->cmm_icc_profile_data->Range.ranges[0].rmin = 0.0;
1679
966
    pcs->cmm_icc_profile_data->Range.ranges[0].rmax = 100.0;
1680
2.89k
    for (i = 1; i < 3; i++) {
1681
1.93k
        pcs->cmm_icc_profile_data->Range.ranges[i].rmin =
1682
1.93k
            range_buff[2 * (i-1)];
1683
1.93k
        pcs->cmm_icc_profile_data->Range.ranges[i].rmax =
1684
1.93k
            range_buff[2 * (i-1) + 1];
1685
1.93k
    }
1686
966
    if (ppcs!= NULL){
1687
217
        *ppcs = pcs;
1688
217
        pdfi_set_colour_callback(pcs, ctx, pdfi_cspace_free_callback);
1689
749
    } else {
1690
749
        code = pdfi_gs_setcolorspace(ctx, pcs);
1691
749
        rc_decrement_only_cs(pcs, "pdfi_seticc_lab");
1692
749
    }
1693
1694
966
    return code;
1695
966
}
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
988
{
1699
988
    int code = 0, i;
1700
988
    pdf_dict *Lab_dict = NULL;
1701
988
    pdf_array *Range = NULL;
1702
988
    float RangeBuf[4];
1703
988
    double f;
1704
988
    bool known = false;
1705
1706
988
    code = pdfi_array_get_type(ctx, color_array, index + 1, PDF_DICT, (pdf_obj **)&Lab_dict);
1707
988
    if (code < 0)
1708
14
        return code;
1709
1710
974
    code = pdfi_dict_known(ctx, Lab_dict, "Range", &known);
1711
974
    if (code < 0)
1712
0
        goto exit;
1713
974
    if (known) {
1714
956
        code = pdfi_dict_get_type(ctx, Lab_dict, "Range", PDF_ARRAY, (pdf_obj **)&Range);
1715
956
        if (code < 0) {
1716
0
            goto exit;
1717
0
        }
1718
956
        if (pdfi_array_size(Range) != 4){
1719
8
            code = gs_note_error(gs_error_rangecheck);
1720
8
            goto exit;
1721
8
        }
1722
1723
4.74k
        for (i=0; i < 4; i++) {
1724
3.79k
            code = pdfi_array_get_number(ctx, Range, (uint64_t)i, &f);
1725
3.79k
            if (code < 0)
1726
0
                goto exit;
1727
3.79k
            RangeBuf[i] = (float)f;
1728
3.79k
        }
1729
948
    } else {
1730
18
        RangeBuf[0] = RangeBuf[2] = -100.0;
1731
18
        RangeBuf[1] = RangeBuf[3] = 100.0;
1732
18
    }
1733
1734
966
    code = pdfi_seticc_lab(ctx, RangeBuf, ppcs);
1735
1736
974
exit:
1737
974
    pdfi_countdown(Lab_dict);
1738
974
    pdfi_countdown(Range);
1739
974
    return code;
1740
966
}
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.59k
{
1747
2.59k
    int                     code = 0;
1748
2.59k
    gs_color_space *        pcs;
1749
2.59k
    int                     i;
1750
2.59k
    cmm_profile_t           *cal_profile;
1751
1752
    /* See if the color space is in the profile cache */
1753
2.59k
    pcs = gsicc_find_cs(dictkey, ctx->pgs);
1754
2.59k
    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.54k
        code = gs_cspace_build_ICC(&pcs, NULL, ctx->pgs->memory->stable_memory);
1760
2.54k
        if (code < 0)
1761
0
            return code;
1762
        /* There is no alternate for this.  Perhaps we should set DeviceRGB? */
1763
2.54k
        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.54k
        cal_profile = gsicc_create_from_cal(white, black, gamma, matrix,
1767
2.54k
                                            ctx->pgs->memory->stable_memory, num_colorants);
1768
2.54k
        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.54k
        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.54k
        rc_decrement(cal_profile, "seticc_cal");
1781
2.54k
        if (code < 0) {
1782
0
            rc_decrement(pcs, "seticc_cal");
1783
0
            return code;
1784
0
        }
1785
9.81k
        for (i = 0; i < num_colorants; i++) {
1786
7.26k
            pcs->cmm_icc_profile_data->Range.ranges[i].rmin = 0;
1787
7.26k
            pcs->cmm_icc_profile_data->Range.ranges[i].rmax = 1;
1788
7.26k
        }
1789
        /* Add the color space to the profile cache */
1790
2.54k
        gsicc_add_cs(ctx->pgs, pcs, dictkey);
1791
2.54k
    } else {
1792
        /* We're passing back a new reference, increment the count */
1793
46
        rc_adjust_only(pcs, 1, "pdfi_seticc_cal, return cached ICC profile");
1794
46
    }
1795
1796
2.59k
    if (ppcs!= NULL){
1797
256
        *ppcs = pcs;
1798
256
        pdfi_set_colour_callback(pcs, ctx, pdfi_cspace_free_callback);
1799
2.33k
    } else {
1800
2.33k
        code = pdfi_gs_setcolorspace(ctx, pcs);
1801
2.33k
        rc_decrement_only_cs(pcs, "pdfi_seticc_cal");
1802
2.33k
    }
1803
1804
2.59k
    return code;
1805
2.59k
}
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
579
{
1809
579
    int code = 0, i;
1810
579
    pdf_dict *CalGray_dict = NULL;
1811
579
    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
579
    float WhitePoint[3], BlackPoint[3] = {0.0f, 0.0f, 0.0f}, Gamma = 1.0f;
1818
579
    float Matrix[9] = {1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f};
1819
579
    double f;
1820
1821
579
    code = pdfi_array_get_type(ctx, color_array, index + 1, PDF_DICT, (pdf_obj **)&CalGray_dict);
1822
579
    if (code < 0)
1823
107
        return code;
1824
1825
472
    code = pdfi_dict_get_type(ctx, CalGray_dict, "WhitePoint", PDF_ARRAY, (pdf_obj **)&PDFArray);
1826
472
    if (code < 0) {
1827
21
        pdfi_countdown(PDFArray);
1828
21
        goto exit;
1829
21
    }
1830
451
    if (pdfi_array_size(PDFArray) != 3){
1831
0
        code = gs_note_error(gs_error_rangecheck);
1832
0
        goto exit;
1833
0
    }
1834
1835
1.76k
    for (i=0; i < 3; i++) {
1836
1.33k
        code = pdfi_array_get_number(ctx, PDFArray, (uint64_t)i, &f);
1837
1.33k
        if (code < 0)
1838
20
            goto exit;
1839
1.31k
        WhitePoint[i] = (float)f;
1840
1.31k
    }
1841
431
    pdfi_countdown(PDFArray);
1842
431
    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
431
    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
431
    if (pdfi_dict_knownget_type(ctx, CalGray_dict, "BlackPoint", PDF_ARRAY, (pdf_obj **)&PDFArray) > 0) {
1853
377
        if (pdfi_array_size(PDFArray) != 3){
1854
120
            code = gs_note_error(gs_error_rangecheck);
1855
120
            goto exit;
1856
120
        }
1857
908
        for (i=0; i < 3; i++) {
1858
771
            code = pdfi_array_get_number(ctx, PDFArray, (uint64_t)i, &f);
1859
771
            if (code < 0)
1860
120
                goto exit;
1861
            /* The PDF 1.7 reference states that all three components of the BlackPoint
1862
             * (if present) must be positive.
1863
             */
1864
651
            if (f < 0) {
1865
0
                code = gs_note_error(gs_error_rangecheck);
1866
0
                goto exit;
1867
0
            }
1868
651
            BlackPoint[i] = (float)f;
1869
651
        }
1870
137
        pdfi_countdown(PDFArray);
1871
137
        PDFArray = NULL;
1872
137
    }
1873
1874
191
    if (pdfi_dict_knownget_number(ctx, CalGray_dict, "Gamma", &f) > 0)
1875
190
        Gamma = (float)f;
1876
    /* The PDF 1.7 reference states that Gamma
1877
     * (if present) must be positive.
1878
     */
1879
191
    if (Gamma < 0) {
1880
0
        code = gs_note_error(gs_error_rangecheck);
1881
0
        goto exit;
1882
0
    }
1883
1884
191
    code = pdfi_seticc_cal(ctx, WhitePoint, BlackPoint, &Gamma, Matrix, 1, color_array->object_num, ppcs);
1885
1886
472
exit:
1887
472
    pdfi_countdown(PDFArray);
1888
472
    pdfi_countdown(CalGray_dict);
1889
472
    return code;
1890
191
}
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
29
        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.94k
    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
663
        if (pdfi_array_size(PDFArray) != 3){
1937
0
            code = gs_note_error(gs_error_rangecheck);
1938
0
            goto exit;
1939
0
        }
1940
2.49k
        for (i=0; i < 3; i++) {
1941
1.90k
            code = pdfi_array_get_number(ctx, PDFArray, (uint64_t)i, &f);
1942
1.90k
            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
1.90k
            if (f < 0) {
1948
80
                code = gs_note_error(gs_error_rangecheck);
1949
80
                goto exit;
1950
80
            }
1951
1.82k
            BlackPoint[i] = (float)f;
1952
1.82k
        }
1953
583
        pdfi_countdown(PDFArray);
1954
583
        PDFArray = NULL;
1955
583
    }
1956
1957
2.40k
    if (pdfi_dict_knownget_type(ctx, CalRGB_dict, "Gamma", PDF_ARRAY, (pdf_obj **)&PDFArray) > 0) {
1958
2.40k
        if (pdfi_array_size(PDFArray) != 3){
1959
0
            code = gs_note_error(gs_error_rangecheck);
1960
0
            goto exit;
1961
0
        }
1962
9.62k
        for (i=0; i < 3; i++) {
1963
7.22k
            code = pdfi_array_get_number(ctx, PDFArray, (uint64_t)i, &f);
1964
7.22k
            if (code < 0)
1965
0
                goto exit;
1966
7.22k
            Gamma[i] = (float)f;
1967
7.22k
        }
1968
2.40k
        pdfi_countdown(PDFArray);
1969
2.40k
        PDFArray = NULL;
1970
2.40k
    }
1971
1972
2.40k
    if (pdfi_dict_knownget_type(ctx, CalRGB_dict, "Matrix", PDF_ARRAY, (pdf_obj **)&PDFArray) > 0) {
1973
2.40k
        if (pdfi_array_size(PDFArray) != 9){
1974
4
            code = gs_note_error(gs_error_rangecheck);
1975
4
            goto exit;
1976
4
        }
1977
24.0k
        for (i=0; i < 9; i++) {
1978
21.6k
            code = pdfi_array_get_number(ctx, PDFArray, (uint64_t)i, &f);
1979
21.6k
            if (code < 0)
1980
3
                goto exit;
1981
21.6k
            Matrix[i] = (float)f;
1982
21.6k
        }
1983
2.39k
        pdfi_countdown(PDFArray);
1984
2.39k
        PDFArray = NULL;
1985
2.39k
    }
1986
2.40k
    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.40k
}
1993
1994
static int pdfi_create_Separation(pdf_context *ctx, pdf_array *color_array, int index, pdf_dict *stream_dict, pdf_dict *page_dict, gs_color_space **ppcs, bool inline_image)
1995
33.0k
{
1996
33.0k
    pdf_obj *o = NULL;
1997
33.0k
    pdf_name *name = NULL, *NamedAlternate = NULL;
1998
33.0k
    pdf_array *ArrayAlternate = NULL;
1999
33.0k
    pdf_obj *transform = NULL;
2000
33.0k
    int code;
2001
33.0k
    gs_color_space *pcs = NULL, *pcs_alt = NULL;
2002
33.0k
    gs_function_t * pfn = NULL;
2003
33.0k
    separation_type sep_type;
2004
2005
33.0k
    code = pdfi_array_get_type(ctx, color_array, index + 1, PDF_NAME, (pdf_obj **)&name);
2006
33.0k
    if (code < 0)
2007
0
        goto pdfi_separation_error;
2008
2009
33.0k
    sep_type = SEP_OTHER;
2010
33.0k
    if (pdfi_name_is(name, "None"))
2011
0
        sep_type = SEP_NONE;
2012
33.0k
    if (pdfi_name_is(name, "All"))
2013
0
        sep_type = SEP_ALL;
2014
2015
33.0k
    code = pdfi_array_get(ctx, color_array, index + 2, &o);
2016
33.0k
    if (code < 0)
2017
284
        goto pdfi_separation_error;
2018
2019
32.7k
    switch (pdfi_type_of(o)) {
2020
19.7k
        case PDF_NAME:
2021
19.7k
            NamedAlternate = (pdf_name *)o;
2022
19.7k
            code = pdfi_create_colorspace_by_name(ctx, NamedAlternate, stream_dict, page_dict, &pcs_alt, inline_image);
2023
19.7k
            if (code < 0)
2024
66
                goto pdfi_separation_error;
2025
19.7k
            break;
2026
19.7k
        case PDF_ARRAY:
2027
12.0k
            ArrayAlternate = (pdf_array *)o;
2028
12.0k
            code = pdfi_create_colorspace_by_array(ctx, ArrayAlternate, 0, stream_dict, page_dict, &pcs_alt, inline_image);
2029
12.0k
            if (code < 0)
2030
1.07k
                goto pdfi_separation_error;
2031
10.9k
            break;
2032
10.9k
        default:
2033
920
            pdfi_countdown(o);
2034
920
            code = gs_error_typecheck;
2035
920
            goto pdfi_separation_error;
2036
32.7k
    }
2037
2038
30.6k
    code = pdfi_array_get(ctx, color_array, index + 3, &transform);
2039
30.6k
    if (code < 0)
2040
1.03k
        goto pdfi_separation_error;
2041
2042
29.6k
    code = pdfi_build_function(ctx, &pfn, NULL, 1, transform, page_dict);
2043
29.6k
    if (code < 0)
2044
2.32k
        goto pdfi_separation_error;
2045
2046
27.3k
    if (pfn->params.m != 1 || pfn->params.n != cs_num_components(pcs_alt)) {
2047
18
        code = gs_note_error(gs_error_rangecheck);
2048
18
        goto pdfi_separation_error;
2049
18
    }
2050
2051
27.3k
    code = gs_cspace_new_Separation(&pcs, pcs_alt, ctx->memory);
2052
27.3k
    if (code < 0)
2053
0
        goto pdfi_separation_error;
2054
2055
27.3k
    rc_decrement(pcs_alt, "pdfi_create_Separation");
2056
27.3k
    pcs_alt = NULL;
2057
27.3k
    pcs->params.separation.mem = ctx->memory;
2058
27.3k
    pcs->params.separation.sep_type = sep_type;
2059
27.3k
    pcs->params.separation.sep_name = (char *)gs_alloc_bytes(ctx->memory->non_gc_memory, (size_t)name->length + 1, "pdfi_setseparationspace(ink)");
2060
27.3k
    if (pcs->params.separation.sep_name == NULL) {
2061
0
        code = gs_note_error(gs_error_VMerror);
2062
0
        goto pdfi_separation_error;
2063
0
    }
2064
27.3k
    memcpy(pcs->params.separation.sep_name, name->data, name->length);
2065
27.3k
    pcs->params.separation.sep_name[name->length] = 0x00;
2066
2067
27.3k
    code = gs_cspace_set_sepr_function(pcs, pfn);
2068
27.3k
    if (code < 0)
2069
0
        goto pdfi_separation_error;
2070
2071
27.3k
    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
181
        code = pdfi_gs_setcolorspace(ctx, pcs);
2078
181
        *ppcs = pcs;
2079
181
        pdfi_set_colour_callback(pcs, ctx, pdfi_cspace_free_callback);
2080
27.1k
    } else {
2081
27.1k
        code = pdfi_gs_setcolorspace(ctx, pcs);
2082
        /* release reference from construction */
2083
27.1k
        rc_decrement_only_cs(pcs, "setseparationspace");
2084
27.1k
    }
2085
2086
27.3k
    pdfi_countdown(name);
2087
27.3k
    pdfi_countdown(NamedAlternate);
2088
27.3k
    pdfi_countdown(ArrayAlternate);
2089
27.3k
    pdfi_countdown(transform);
2090
27.3k
    return_error(0);
2091
2092
5.72k
pdfi_separation_error:
2093
5.72k
    pdfi_free_function(ctx, pfn);
2094
5.72k
    if (pcs_alt != NULL)
2095
3.37k
        rc_decrement_only_cs(pcs_alt, "setseparationspace");
2096
5.72k
    if(pcs != NULL)
2097
0
        rc_decrement_only_cs(pcs, "setseparationspace");
2098
5.72k
    pdfi_countdown(name);
2099
5.72k
    pdfi_countdown(NamedAlternate);
2100
5.72k
    pdfi_countdown(ArrayAlternate);
2101
5.72k
    pdfi_countdown(transform);
2102
5.72k
    return code;
2103
27.3k
}
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
5.74k
{
2107
5.74k
    pdf_obj *o = NULL;
2108
5.74k
    pdf_name *NamedAlternate = NULL;
2109
5.74k
    pdf_array *ArrayAlternate = NULL, *inks = NULL;
2110
5.74k
    pdf_obj *transform = NULL;
2111
5.74k
    pdf_dict *attributes = NULL;
2112
5.74k
    pdf_dict *Colorants = NULL, *Process = NULL;
2113
5.74k
    gs_color_space *process_space = NULL;
2114
5.74k
    int code;
2115
5.74k
    uint64_t ix;
2116
5.74k
    gs_color_space *pcs = NULL, *pcs_alt = NULL;
2117
5.74k
    gs_function_t * pfn = NULL;
2118
2119
    /* Start with the array of inks */
2120
5.74k
    code = pdfi_array_get_type(ctx, color_array, index + 1, PDF_ARRAY, (pdf_obj **)&inks);
2121
5.74k
    if (code < 0)
2122
8
        goto pdfi_devicen_error;
2123
2124
5.74k
    if (pdfi_array_size(inks) > GS_CLIENT_COLOR_MAX_COMPONENTS)
2125
0
            return_error(gs_error_limitcheck);
2126
2127
15.4k
    for (ix = 0;ix < pdfi_array_size(inks);ix++) {
2128
9.66k
        pdf_name *ink_name = NULL;
2129
2130
9.66k
        code = pdfi_array_get_type(ctx, inks, ix, PDF_NAME, (pdf_obj **)&ink_name);
2131
9.66k
        if (code < 0)
2132
0
            return code;
2133
2134
9.66k
        if (pdfi_name_is(ink_name, "All")) {
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.66k
        pdfi_countdown(ink_name);
2139
9.66k
        ink_name = NULL;
2140
9.66k
    }
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
5.74k
    if (pdfi_array_size(inks) == 1) {
2147
3.81k
        pdf_name *ink_name = NULL;
2148
3.81k
        pdf_array *sep_color_array = NULL;
2149
3.81k
        pdf_obj *obj = NULL;
2150
2151
3.81k
        code = pdfi_array_get_type(ctx, inks, 0, PDF_NAME, (pdf_obj **)&ink_name);
2152
3.81k
        if (code < 0)
2153
0
            goto pdfi_devicen_error;
2154
2155
3.81k
        if (pdfi_name_is(ink_name, "All")) {
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
3.81k
            pdfi_countdown(ink_name);
2200
3.81k
    }
2201
2202
    /* Deal with alternate space */
2203
5.74k
    code = pdfi_array_get(ctx, color_array, index + 2, &o);
2204
5.74k
    if (code < 0)
2205
81
        goto pdfi_devicen_error;
2206
2207
5.65k
    switch (pdfi_type_of(o)) {
2208
4.55k
        case PDF_NAME:
2209
4.55k
            NamedAlternate = (pdf_name *)o;
2210
4.55k
            code = pdfi_create_colorspace_by_name(ctx, NamedAlternate, stream_dict, page_dict, &pcs_alt, inline_image);
2211
4.55k
            if (code < 0)
2212
0
                goto pdfi_devicen_error;
2213
4.55k
            break;
2214
4.55k
        case PDF_ARRAY:
2215
1.09k
            ArrayAlternate = (pdf_array *)o;
2216
1.09k
            code = pdfi_create_colorspace_by_array(ctx, ArrayAlternate, 0, stream_dict, page_dict, &pcs_alt, inline_image);
2217
1.09k
            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
141
                goto pdfi_devicen_error;
2223
955
            break;
2224
955
        default:
2225
13
            code = gs_error_typecheck;
2226
13
            pdfi_countdown(o);
2227
13
            goto pdfi_devicen_error;
2228
5.65k
    }
2229
2230
    /* Now the tint transform */
2231
5.50k
    code = pdfi_array_get(ctx, color_array, index + 3, &transform);
2232
5.50k
    if (code < 0)
2233
582
        goto pdfi_devicen_error;
2234
2235
4.92k
    code = pdfi_build_function(ctx, &pfn, NULL, 1, transform, page_dict);
2236
4.92k
    if (code < 0)
2237
542
        goto pdfi_devicen_error;
2238
2239
4.38k
    if (pfn->params.m != pdfi_array_size(inks) || pfn->params.n != cs_num_components(pcs_alt)) {
2240
45
        code = gs_note_error(gs_error_rangecheck);
2241
45
        goto pdfi_devicen_error;
2242
45
    }
2243
2244
4.33k
    code = gs_cspace_new_DeviceN(&pcs, pdfi_array_size(inks), pcs_alt, ctx->memory);
2245
4.33k
    if (code < 0)
2246
0
        return code;
2247
2248
4.33k
    rc_decrement(pcs_alt, "pdfi_create_DeviceN");
2249
4.33k
    pcs_alt = NULL;
2250
4.33k
    pcs->params.device_n.mem = ctx->memory;
2251
2252
10.5k
    for (ix = 0;ix < pdfi_array_size(inks);ix++) {
2253
6.20k
        pdf_name *ink_name;
2254
2255
6.20k
        ink_name = NULL;
2256
6.20k
        code = pdfi_array_get_type(ctx, inks, ix, PDF_NAME, (pdf_obj **)&ink_name);
2257
6.20k
        if (code < 0)
2258
0
            goto pdfi_devicen_error;
2259
2260
6.20k
        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
6.20k
        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
6.20k
        memcpy(pcs->params.device_n.names[ix], ink_name->data, ink_name->length);
2266
6.20k
        pcs->params.device_n.names[ix][ink_name->length] = 0x00;
2267
6.20k
        pdfi_countdown(ink_name);
2268
6.20k
    }
2269
2270
4.33k
    code = gs_cspace_set_devn_function(pcs, pfn);
2271
4.33k
    if (code < 0)
2272
0
        goto pdfi_devicen_error;
2273
2274
4.33k
    if (pdfi_array_size(color_array) >= index + 5) {
2275
3.96k
        pdf_obj *ColorSpace = NULL;
2276
3.96k
        pdf_array *Components = NULL;
2277
3.96k
        pdf_obj *subtype = NULL;
2278
2279
3.96k
        code = pdfi_array_get_type(ctx, color_array, index + 4, PDF_DICT, (pdf_obj **)&attributes);
2280
3.96k
        if (code < 0)
2281
0
            goto pdfi_devicen_error;
2282
2283
3.96k
        code = pdfi_dict_knownget(ctx, attributes, "Subtype", (pdf_obj **)&subtype);
2284
3.96k
        if (code < 0)
2285
0
            goto pdfi_devicen_error;
2286
2287
3.96k
        if (code == 0) {
2288
44
            pcs->params.device_n.subtype = gs_devicen_DeviceN;
2289
3.92k
        } else {
2290
3.92k
            switch (pdfi_type_of(subtype)) {
2291
3.92k
                case PDF_NAME:
2292
3.92k
                case PDF_STRING:
2293
3.92k
                    if (memcmp(((pdf_name *)subtype)->data, "DeviceN", 7) == 0) {
2294
69
                        pcs->params.device_n.subtype = gs_devicen_DeviceN;
2295
3.85k
                    } else {
2296
3.85k
                        if (memcmp(((pdf_name *)subtype)->data, "NChannel", 8) == 0) {
2297
3.85k
                            pcs->params.device_n.subtype = gs_devicen_NChannel;
2298
3.85k
                        } else {
2299
0
                            pdfi_countdown(subtype);
2300
0
                            goto pdfi_devicen_error;
2301
0
                        }
2302
3.85k
                    }
2303
3.92k
                    pdfi_countdown(subtype);
2304
3.92k
                    break;
2305
0
                default:
2306
0
                    pdfi_countdown(subtype);
2307
0
                    goto pdfi_devicen_error;
2308
3.92k
            }
2309
3.92k
        }
2310
2311
3.96k
        code = pdfi_dict_knownget_type(ctx, attributes, "Process", PDF_DICT, (pdf_obj **)&Process);
2312
3.96k
        if (code < 0)
2313
5
            goto pdfi_devicen_error;
2314
2315
3.95k
        if (Process != NULL && pdfi_dict_entries(Process) != 0) {
2316
3.84k
            int ix = 0;
2317
3.84k
            pdf_obj *name;
2318
2319
3.84k
            code = pdfi_dict_get(ctx, Process, "ColorSpace", (pdf_obj **)&ColorSpace);
2320
3.84k
            if (code < 0)
2321
0
                goto pdfi_devicen_error;
2322
2323
3.84k
            code = pdfi_create_colorspace(ctx, ColorSpace, stream_dict, page_dict, &process_space, inline_image);
2324
3.84k
            pdfi_countdown(ColorSpace);
2325
3.84k
            if (code < 0)
2326
0
                goto pdfi_devicen_error;
2327
2328
3.84k
            pcs->params.device_n.devn_process_space = process_space;
2329
2330
3.84k
            code = pdfi_dict_get_type(ctx, Process, "Components", PDF_ARRAY, (pdf_obj **)&Components);
2331
3.84k
            if (code < 0)
2332
0
                goto pdfi_devicen_error;
2333
2334
3.84k
            pcs->params.device_n.num_process_names = pdfi_array_size(Components);
2335
3.84k
            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
3.84k
            if (pcs->params.device_n.process_names == NULL) {
2337
0
                code = gs_error_VMerror;
2338
0
                goto pdfi_devicen_error;
2339
0
            }
2340
3.84k
            memset(pcs->params.device_n.process_names, 0x00, pdfi_array_size(Components) * sizeof(char *));
2341
2342
19.2k
            for (ix = 0; ix < pcs->params.device_n.num_process_names; ix++) {
2343
15.3k
                code = pdfi_array_get(ctx, Components, ix, &name);
2344
15.3k
                if (code < 0) {
2345
0
                    pdfi_countdown(Components);
2346
0
                    goto pdfi_devicen_error;
2347
0
                }
2348
2349
15.3k
                switch (pdfi_type_of(name)) {
2350
15.3k
                    case PDF_NAME:
2351
15.3k
                    case PDF_STRING:
2352
15.3k
                        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
15.3k
                        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
15.3k
                        memcpy(pcs->params.device_n.process_names[ix], ((pdf_name *)name)->data, ((pdf_name *)name)->length);
2360
15.3k
                        pcs->params.device_n.process_names[ix][((pdf_name *)name)->length] = 0x00;
2361
15.3k
                        pdfi_countdown(name);
2362
15.3k
                        break;
2363
7
                    default:
2364
7
                        pdfi_countdown(Components);
2365
7
                        pdfi_countdown(name);
2366
7
                        goto pdfi_devicen_error;
2367
15.3k
                }
2368
15.3k
            }
2369
3.83k
            pdfi_countdown(Components);
2370
3.83k
        }
2371
2372
3.95k
        code = pdfi_dict_knownget_type(ctx, attributes, "Colorants", PDF_DICT, (pdf_obj **)&Colorants);
2373
3.95k
        if (code < 0)
2374
0
            goto pdfi_devicen_error;
2375
2376
3.95k
        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
3.95k
    }
2457
2458
4.32k
    if (ppcs!= NULL){
2459
136
        *ppcs = pcs;
2460
136
        pdfi_set_colour_callback(pcs, ctx, pdfi_cspace_free_callback);
2461
4.18k
    } else {
2462
4.18k
        code = pdfi_gs_setcolorspace(ctx, pcs);
2463
        /* release reference from construction */
2464
4.18k
        rc_decrement_only_cs(pcs, "setdevicenspace");
2465
4.18k
    }
2466
4.32k
    pdfi_countdown(Process);
2467
4.32k
    pdfi_countdown(Colorants);
2468
4.32k
    pdfi_countdown(attributes);
2469
4.32k
    pdfi_countdown(inks);
2470
4.32k
    pdfi_countdown(NamedAlternate);
2471
4.32k
    pdfi_countdown(ArrayAlternate);
2472
4.32k
    pdfi_countdown(transform);
2473
4.32k
    return_error(0);
2474
2475
1.42k
pdfi_devicen_error:
2476
1.42k
    pdfi_free_function(ctx, pfn);
2477
1.42k
    if (pcs_alt != NULL)
2478
1.16k
        rc_decrement_only_cs(pcs_alt, "setseparationspace");
2479
1.42k
    if(pcs != NULL)
2480
12
        rc_decrement_only_cs(pcs, "setseparationspace");
2481
1.42k
    pdfi_countdown(Process);
2482
1.42k
    pdfi_countdown(Colorants);
2483
1.42k
    pdfi_countdown(attributes);
2484
1.42k
    pdfi_countdown(inks);
2485
1.42k
    pdfi_countdown(NamedAlternate);
2486
1.42k
    pdfi_countdown(ArrayAlternate);
2487
1.42k
    pdfi_countdown(transform);
2488
1.42k
    return code;
2489
4.33k
}
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.7k
{
2498
10.7k
    pdf_obj *space=NULL, *lookup=NULL;
2499
10.7k
    int code;
2500
10.7k
    int64_t hival, lookup_length = 0;
2501
10.7k
    int num_values;
2502
10.7k
    gs_color_space *pcs=NULL, *pcs_base=NULL;
2503
10.7k
    gs_color_space_index base_type;
2504
10.7k
    byte *Buffer = NULL;
2505
2506
10.7k
    if (index != 0)
2507
0
        return_error(gs_error_syntaxerror);
2508
2509
10.7k
    code = pdfi_array_get_int(ctx, color_array, index + 2, &hival);
2510
10.7k
    if (code < 0)
2511
93
        return code;
2512
2513
10.6k
    if (hival > 255 || hival < 0)
2514
9
        return_error(gs_error_syntaxerror);
2515
2516
10.6k
    code = pdfi_array_get(ctx, color_array, index + 1, &space);
2517
10.6k
    if (code < 0)
2518
91
        goto exit;
2519
2520
10.5k
    code = pdfi_create_colorspace(ctx, space, stream_dict, page_dict, &pcs_base, inline_image);
2521
10.5k
    if (code < 0)
2522
255
        goto exit;
2523
2524
10.3k
    base_type = gs_color_space_get_index(pcs_base);
2525
10.3k
    if (base_type == gs_color_space_index_Pattern || base_type == gs_color_space_index_Indexed) {
2526
9
        code = gs_note_error(gs_error_typecheck);
2527
9
        goto exit;
2528
9
    }
2529
2530
10.3k
    (void)pcs_base->type->install_cspace(pcs_base, ctx->pgs);
2531
2532
10.3k
    code = pdfi_array_get(ctx, color_array, index + 3, &lookup);
2533
10.3k
    if (code < 0)
2534
174
        goto exit;
2535
2536
10.1k
    num_values = (hival+1) * cs_num_components(pcs_base);
2537
10.1k
    lookup_length = num_values;
2538
2539
10.1k
    switch (pdfi_type_of(lookup)) {
2540
5.51k
    case PDF_STREAM:
2541
5.51k
        code = pdfi_stream_to_buffer(ctx, (pdf_stream *)lookup, &Buffer, &lookup_length);
2542
5.51k
        if (code < 0)
2543
11
            goto exit;
2544
5.50k
        break;
2545
5.50k
    case PDF_STRING:
2546
4.62k
    {
2547
4.62k
        pdf_string *lookup_string = (pdf_string *)lookup; /* alias */
2548
2549
4.62k
        Buffer = gs_alloc_bytes(ctx->memory, lookup_string->length, "pdfi_create_indexed (lookup buffer)");
2550
4.62k
        if (Buffer == NULL) {
2551
0
            code = gs_note_error(gs_error_VMerror);
2552
0
            goto exit;
2553
0
        }
2554
2555
4.62k
        memcpy(Buffer, lookup_string->data, lookup_string->length);
2556
4.62k
        lookup_length = lookup_string->length;
2557
4.62k
        break;
2558
4.62k
    }
2559
12
    default:
2560
12
        code = gs_note_error(gs_error_typecheck);
2561
12
        goto exit;
2562
10.1k
    }
2563
2564
10.1k
    if (num_values > lookup_length) {
2565
        /* This is not legal, but Acrobat seems to accept it */
2566
129
        byte *SBuffer = NULL;
2567
2568
129
        code = pdfi_set_error_stop(ctx, gs_error_rangecheck, NULL, E_PDF_BAD_INDEXED_STRING, "pdfi_create_indexed", NULL);
2569
129
        if (code < 0)
2570
0
            goto exit;
2571
129
        SBuffer = gs_alloc_bytes(ctx->memory, num_values, "pdfi_create_indexed (lookup buffer)");
2572
129
        if (SBuffer == NULL) {
2573
0
            code = gs_note_error(gs_error_VMerror);
2574
0
            goto exit;
2575
0
        }
2576
129
        memcpy(SBuffer, Buffer, lookup_length);
2577
129
        memset(&SBuffer[lookup_length], 0x00, num_values - lookup_length);
2578
129
        gs_free_object(ctx->memory, Buffer, "pdfi_create_indexed (lookup buffer)");
2579
129
        Buffer = SBuffer;
2580
129
    }
2581
2582
    /* If we have a named color profile and the base space is DeviceN or
2583
       Separation use a different set of procedures to ensure the named
2584
       color remapping code is used */
2585
10.1k
    if (ctx->pgs->icc_manager->device_named != NULL &&
2586
0
        (base_type == gs_color_space_index_Separation ||
2587
0
         base_type == gs_color_space_index_DeviceN))
2588
0
        pcs = gs_cspace_alloc(ctx->memory, &gs_color_space_type_Indexed_Named);
2589
10.1k
    else
2590
10.1k
        pcs = gs_cspace_alloc(ctx->memory, &gs_color_space_type_Indexed);
2591
2592
10.1k
    if (pcs == NULL) {
2593
0
        code = gs_note_error(gs_error_VMerror);
2594
0
        goto exit;
2595
0
    }
2596
    /* NOTE: we don't need to increment the reference to pcs_base, since it is already 1 */
2597
10.1k
    pcs->base_space = pcs_base;
2598
2599
10.1k
    pcs->params.indexed.lookup.table.size = num_values;
2600
10.1k
    pcs->params.indexed.use_proc = 0;
2601
10.1k
    pcs->params.indexed.hival = hival;
2602
10.1k
    pcs->params.indexed.n_comps = cs_num_components(pcs_base);
2603
10.1k
    pcs->params.indexed.lookup.table.data = Buffer;
2604
10.1k
    Buffer = NULL;
2605
2606
10.1k
    if (ppcs != NULL) {
2607
10.0k
        *ppcs = pcs;
2608
10.0k
        pdfi_set_colour_callback(pcs, ctx, pdfi_cspace_free_callback);
2609
10.0k
    }
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.6k
 exit:
2617
10.6k
    if (code != 0)
2618
10.6k
        rc_decrement(pcs_base, "pdfi_create_indexed(pcs_base) error");
2619
10.6k
    if (Buffer)
2620
0
        gs_free_object(ctx->memory, Buffer, "pdfi_create_indexed (decompression buffer)");
2621
10.6k
    pdfi_countdown(space);
2622
10.6k
    pdfi_countdown(lookup);
2623
10.6k
    return code;
2624
10.1k
}
2625
2626
static int pdfi_create_DeviceGray(pdf_context *ctx, gs_color_space **ppcs)
2627
29.1k
{
2628
29.1k
    int code = 0;
2629
2630
29.1k
    if (ppcs != NULL) {
2631
        /* Bug 709017: Don't return DefaultGray_cs if we are within a softmask */
2632
25.8k
        if (ctx->page.DefaultGray_cs != NULL &&
2633
0
            (dev_proc(ctx->pgs->device, dev_spec_op)(ctx->pgs->device, gxdso_in_smask_construction, NULL, 0) <= 0)) {
2634
0
            *ppcs = ctx->page.DefaultGray_cs;
2635
0
            rc_increment(*ppcs);
2636
25.8k
        } else {
2637
25.8k
            *ppcs = gs_cspace_new_DeviceGray(ctx->memory);
2638
25.8k
            if (*ppcs == NULL)
2639
0
                code = gs_note_error(gs_error_VMerror);
2640
25.8k
            else {
2641
25.8k
                code = ((gs_color_space *)*ppcs)->type->install_cspace(*ppcs, ctx->pgs);
2642
25.8k
                if (code < 0) {
2643
0
                    rc_decrement_only_cs(*ppcs, "pdfi_create_DeviceGray");
2644
0
                    *ppcs = NULL;
2645
0
                }
2646
25.8k
            }
2647
25.8k
            if (*ppcs != NULL)
2648
25.8k
                pdfi_set_colour_callback(*ppcs, ctx, pdfi_cspace_free_callback);
2649
25.8k
        }
2650
25.8k
    } else {
2651
3.34k
        code = pdfi_gs_setgray(ctx, 0);
2652
3.34k
        pdfi_set_colour_callback(ctx->pgs->color[0].color_space, ctx, pdfi_cspace_free_callback);
2653
3.34k
    }
2654
29.1k
    return code;
2655
29.1k
}
2656
2657
static int pdfi_create_DeviceRGB(pdf_context *ctx, gs_color_space **ppcs)
2658
69.1k
{
2659
69.1k
    int code = 0;
2660
2661
69.1k
    if (ppcs != NULL) {
2662
        /* Bug 709017: Don't return DefaultRGB_cs if we are within a softmask */
2663
52.1k
        if (ctx->page.DefaultRGB_cs != NULL &&
2664
199
            (dev_proc(ctx->pgs->device, dev_spec_op)(ctx->pgs->device, gxdso_in_smask_construction, NULL, 0) <= 0)) {
2665
199
            *ppcs = ctx->page.DefaultRGB_cs;
2666
199
            rc_increment(*ppcs);
2667
51.9k
        } else {
2668
51.9k
            *ppcs = gs_cspace_new_DeviceRGB(ctx->memory);
2669
51.9k
            if (*ppcs == NULL)
2670
0
                code = gs_note_error(gs_error_VMerror);
2671
51.9k
            else {
2672
51.9k
                code = ((gs_color_space *)*ppcs)->type->install_cspace(*ppcs, ctx->pgs);
2673
51.9k
                if (code < 0) {
2674
0
                    rc_decrement_only_cs(*ppcs, "pdfi_create_DeviceRGB");
2675
0
                    *ppcs = NULL;
2676
0
                }
2677
51.9k
            }
2678
51.9k
            if (*ppcs != NULL)
2679
51.9k
                pdfi_set_colour_callback(*ppcs, ctx, pdfi_cspace_free_callback);
2680
51.9k
        }
2681
52.1k
    } else {
2682
16.9k
        code = pdfi_gs_setrgbcolor(ctx, 0, 0, 0);
2683
16.9k
    }
2684
69.1k
    return code;
2685
69.1k
}
2686
2687
static int pdfi_create_DeviceCMYK(pdf_context *ctx, gs_color_space **ppcs)
2688
26.2k
{
2689
26.2k
    int code = 0;
2690
2691
26.2k
    if (ppcs != NULL) {
2692
        /* Bug 709017: Don't return DefaultCMYK_cs if we are within a softmask */
2693
20.4k
        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
20.4k
        } else {
2698
20.4k
            *ppcs = gs_cspace_new_DeviceCMYK(ctx->memory);
2699
20.4k
            if (*ppcs == NULL)
2700
0
                code = gs_note_error(gs_error_VMerror);
2701
20.4k
            else {
2702
20.4k
                code = ((gs_color_space *)*ppcs)->type->install_cspace(*ppcs, ctx->pgs);
2703
20.4k
                if (code < 0) {
2704
0
                    rc_decrement_only_cs(*ppcs, "pdfi_create_DeviceCMYK");
2705
0
                    *ppcs = NULL;
2706
0
                }
2707
20.4k
            }
2708
20.4k
            if (*ppcs != NULL)
2709
20.4k
                pdfi_set_colour_callback(*ppcs, ctx, pdfi_cspace_free_callback);
2710
20.4k
        }
2711
20.4k
    } else {
2712
5.85k
        code = pdfi_gs_setcmykcolor(ctx, 0, 0, 0, 1);
2713
5.85k
        pdfi_set_colour_callback(ctx->pgs->color[0].color_space, ctx, pdfi_cspace_free_callback);
2714
5.85k
    }
2715
26.2k
    return code;
2716
26.2k
}
2717
2718
static int pdfi_create_JPX_space(pdf_context *ctx, const char *name, int num_components, gs_color_space **ppcs)
2719
4.35k
{
2720
4.35k
    int code, icc_N;
2721
4.35k
    float range_buff[6] = {0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f};
2722
2723
4.35k
    code = pdfi_create_icc(ctx, (char *)name, NULL, num_components, &icc_N, range_buff, 0, ppcs);
2724
4.35k
    return code;
2725
4.35k
}
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
178k
{
2739
178k
    int code;
2740
178k
    pdf_name *space = NULL;
2741
178k
    pdf_array *a = NULL;
2742
2743
178k
    code = pdfi_array_get_type(ctx, color_array, index, PDF_NAME, (pdf_obj **)&space);
2744
178k
    if (code != 0)
2745
182
        goto exit;
2746
2747
178k
    code = 0;
2748
178k
    if (pdfi_name_is(space, "G") || pdfi_name_is(space, "DeviceGray")) {
2749
10
        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
10
        code = pdfi_create_DeviceGray(ctx, ppcs);
2754
178k
    } else if (pdfi_name_is(space, "I") || pdfi_name_is(space, "Indexed")) {
2755
10.7k
        if (pdfi_name_is(space, "I") && !inline_image) {
2756
93
            pdfi_set_warning(ctx, 0, NULL, W_PDF_BAD_INLINECOLORSPACE, "pdfi_create_colorspace_by_array", NULL);
2757
93
            if (ctx->args.pdfstoponwarning)
2758
0
                return_error(gs_error_syntaxerror);
2759
93
        }
2760
10.7k
        code = pdfi_create_indexed(ctx, color_array, index, stream_dict, page_dict, ppcs, inline_image);
2761
167k
    } else if (pdfi_name_is(space, "Lab")) {
2762
988
        code = pdfi_create_Lab(ctx, color_array, index, stream_dict, page_dict, ppcs);
2763
166k
    } else if (pdfi_name_is(space, "RGB") || pdfi_name_is(space, "DeviceRGB")) {
2764
11
        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
11
        code = pdfi_create_DeviceRGB(ctx, ppcs);
2770
166k
    } 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
166k
    } else if (pdfi_name_is(space, "CalRGB")) {
2778
2.52k
        code = pdfi_create_CalRGB(ctx, color_array, index, stream_dict, page_dict, ppcs);
2779
163k
    } else if (pdfi_name_is(space, "CalGray")) {
2780
579
        code = pdfi_create_CalGray(ctx, color_array, index, stream_dict, page_dict, ppcs);
2781
163k
    } else if (pdfi_name_is(space, "Pattern")) {
2782
1.84k
        if (index != 0)
2783
0
            code = gs_note_error(gs_error_syntaxerror);
2784
1.84k
        else
2785
1.84k
            code = pdfi_pattern_create(ctx, color_array, stream_dict, page_dict, ppcs);
2786
161k
    } else if (pdfi_name_is(space, "DeviceN")) {
2787
5.74k
        code = pdfi_create_DeviceN(ctx, color_array, index, stream_dict, page_dict, ppcs, inline_image);
2788
155k
    } else if (pdfi_name_is(space, "ICCBased")) {
2789
121k
        code = pdfi_create_iccbased(ctx, color_array, index, stream_dict, page_dict, ppcs, inline_image);
2790
121k
    } else if (pdfi_name_is(space, "Separation")) {
2791
33.0k
        code = pdfi_create_Separation(ctx, color_array, index, stream_dict, page_dict, ppcs, inline_image);
2792
33.0k
    } else {
2793
799
        if (stream_dict == NULL)
2794
36
            code = gs_note_error(gs_error_syntaxerror);
2795
763
        else
2796
763
            code = pdfi_find_resource(ctx, (unsigned char *)"ColorSpace",
2797
763
                                  space, (pdf_dict *)stream_dict, page_dict, (pdf_obj **)&a);
2798
799
        if (code < 0)
2799
797
            goto exit;
2800
2801
2
        if (pdfi_type_of(a) != PDF_ARRAY) {
2802
0
            code = gs_note_error(gs_error_typecheck);
2803
0
            goto exit;
2804
0
        }
2805
2
        if (a == color_array) {
2806
2
            code = gs_note_error(gs_error_circular_reference);
2807
2
            goto exit;
2808
2
        }
2809
2810
        /* recursion */
2811
0
        code = pdfi_create_colorspace_by_array(ctx, a, 0, stream_dict, page_dict, ppcs, inline_image);
2812
0
    }
2813
2814
178k
 exit:
2815
178k
    pdfi_countdown(space);
2816
178k
    pdfi_countdown(a);
2817
178k
    return code;
2818
178k
}
2819
2820
static int
2821
pdfi_create_colorspace_by_name(pdf_context *ctx, pdf_name *name,
2822
                               pdf_dict *stream_dict, pdf_dict *page_dict,
2823
                               gs_color_space **ppcs, bool inline_image)
2824
380k
{
2825
380k
    int code = 0;
2826
380k
    gs_id oldid = 0;
2827
2828
380k
    if (pdfi_name_is(name, "G") || pdfi_name_is(name, "DeviceGray")) {
2829
29.1k
        if (pdfi_name_is(name, "G") && !inline_image) {
2830
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)
2831
0
                return code;
2832
20
        }
2833
29.1k
        code = pdfi_create_DeviceGray(ctx, ppcs);
2834
351k
    } else if (pdfi_name_is(name, "RGB") || pdfi_name_is(name, "DeviceRGB")) {
2835
69.1k
        if (pdfi_name_is(name, "RGB") && !inline_image) {
2836
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)
2837
0
                return code;
2838
0
        }
2839
69.1k
        code = pdfi_create_DeviceRGB(ctx, ppcs);
2840
282k
    } else if (pdfi_name_is(name, "CMYK") || pdfi_name_is(name, "DeviceCMYK") || pdfi_name_is(name, "CalCMYK")) {
2841
26.2k
        if (pdfi_name_is(name, "CMYK") && !inline_image) {
2842
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)
2843
0
                return code;
2844
0
        }
2845
26.2k
        code = pdfi_create_DeviceCMYK(ctx, ppcs);
2846
256k
    } else if (pdfi_name_is(name, "Pattern")) {
2847
44.3k
        code = pdfi_pattern_create(ctx, NULL, stream_dict, page_dict, ppcs);
2848
211k
    } else if (pdfi_name_is(name, "esRGBICC")) {                /* These 4 spaces are 'special' for JPX images          */
2849
0
        code = pdfi_create_JPX_space(ctx, "esrgb", 3, ppcs);    /* the names are non-standad and must match those in    */
2850
211k
    } else if (pdfi_name_is(name, "rommRGBICC")) {              /* pdfi_image_get_color() in pdf_image.c                */
2851
0
        code = pdfi_create_JPX_space(ctx, "rommrgb", 3, ppcs);  /* Note that the Lab space for JPX images does not use  */
2852
211k
    } else if (pdfi_name_is(name, "sRGBICC")) {                 /* a special space but simply constructs an appropriate */
2853
514
        code = pdfi_create_JPX_space(ctx, "srgb", 3, ppcs);     /* pdf_array object with the corerct contents for an    */
2854
211k
    } else if (pdfi_name_is(name, "sGrayICC")) {                /* Lab space with a D65 white point.                    */
2855
3.84k
        code = pdfi_create_JPX_space(ctx, "sgray", 1, ppcs);
2856
207k
    } else {
2857
207k
        pdf_obj *ref_space = NULL;
2858
2859
207k
        if (ppcs == NULL && check_same_current_space(ctx, name) == 1)
2860
53.8k
            return 0;
2861
2862
153k
        code = pdfi_find_resource(ctx, (unsigned char *)"ColorSpace", name, (pdf_dict *)stream_dict,
2863
153k
                                  page_dict, &ref_space);
2864
153k
        if (code < 0)
2865
30.4k
            return code;
2866
2867
123k
        if (pdfi_type_of(ref_space) == PDF_NAME) {
2868
136
            if (ref_space->object_num != 0 && ref_space->object_num == name->object_num) {
2869
0
                pdfi_countdown(ref_space);
2870
0
                return_error(gs_error_circular_reference);
2871
0
            }
2872
136
            if (((pdf_name *)ref_space)->length <= 0) {
2873
5
                pdfi_countdown(ref_space);
2874
5
                return_error(gs_error_syntaxerror);
2875
5
            }
2876
131
            if (pdfi_name_cmp((pdf_name *)ref_space, name) == 0) {
2877
4
                pdfi_countdown(ref_space);
2878
4
                return_error(gs_error_circular_reference);
2879
4
            }
2880
131
        }
2881
2882
123k
        oldid = ctx->pgs->color[0].color_space->id;
2883
        /* recursion */
2884
123k
        code = pdfi_create_colorspace(ctx, ref_space, stream_dict, page_dict, ppcs, inline_image);
2885
2886
123k
        if (code >= 0) {
2887
103k
            if (oldid != ctx->pgs->color[0].color_space->id) {
2888
102k
                if (ppcs != NULL)
2889
0
                    pdfi_set_colourspace_name(ctx, *ppcs, name);
2890
102k
                else
2891
102k
                    pdfi_set_colourspace_name(ctx, ctx->pgs->color[0].color_space, name);
2892
102k
            }
2893
103k
        }
2894
2895
123k
        pdfi_countdown(ref_space);
2896
123k
        return code;
2897
123k
    }
2898
2899
    /* If we got here, it's a recursion base case, and ppcs should have been set if requested */
2900
173k
    if (ppcs != NULL && *ppcs == NULL)
2901
0
        code = gs_note_error(gs_error_VMerror);
2902
173k
    return code;
2903
380k
}
2904
2905
/*
2906
 * Gets icc profile data from the provided stream.
2907
 * Position in the stream is NOT preserved.
2908
 * This is raw data, not filtered, so no need to worry about compression.
2909
 * (Used for JPXDecode images)
2910
 */
2911
int
2912
pdfi_create_icc_colorspace_from_stream(pdf_context *ctx, pdf_c_stream *stream, gs_offset_t offset,
2913
                                       unsigned int length, int comps, int *icc_N, ulong dictkey, gs_color_space **ppcs)
2914
0
{
2915
0
    pdf_c_stream *profile_stream = NULL;
2916
0
    byte *profile_buffer;
2917
0
    int code, code1;
2918
0
    float range[8] = {0,1,0,1,0,1,0,1};
2919
2920
    /* Move to the start of the profile data */
2921
0
    pdfi_seek(ctx, stream, offset, SEEK_SET);
2922
2923
    /* The ICC profile reading code (irritatingly) requires a seekable stream, because it
2924
     * rewinds it to the start, then seeks to the end to find the size, then rewinds the
2925
     * stream again.
2926
     * Ideally we would use a ReusableStreamDecode filter here, but that is largely
2927
     * implemented in PostScript (!) so we can't use it. What we can do is create a
2928
     * string sourced stream in memory, which is at least seekable.
2929
     */
2930
0
    code = pdfi_open_memory_stream_from_stream(ctx, length, &profile_buffer, stream, &profile_stream, true);
2931
0
    if (code < 0) {
2932
0
        return code;
2933
0
    }
2934
2935
    /* Now, finally, we can call the code to create and set the profile */
2936
0
    code = pdfi_create_icc(ctx, NULL, profile_stream->s, comps, icc_N, range, dictkey, ppcs);
2937
2938
0
    code1 = pdfi_close_memory_stream(ctx, profile_buffer, profile_stream);
2939
2940
0
    if (code == 0)
2941
0
        code = code1;
2942
2943
0
    return code;
2944
0
}
2945
2946
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)
2947
518k
{
2948
518k
    int code;
2949
2950
518k
    code = pdfi_loop_detector_mark(ctx);
2951
518k
    if (code < 0)
2952
0
        return code;
2953
2954
518k
    switch (pdfi_type_of(space)) {
2955
349k
    case PDF_NAME:
2956
349k
        code = pdfi_create_colorspace_by_name(ctx, (pdf_name *)space, stream_dict, page_dict, ppcs, inline_image);
2957
349k
        break;
2958
165k
    case PDF_ARRAY:
2959
165k
        code = pdfi_create_colorspace_by_array(ctx, (pdf_array *)space, 0, stream_dict, page_dict, ppcs, inline_image);
2960
165k
        break;
2961
3.41k
    default:
2962
3.41k
        pdfi_loop_detector_cleartomark(ctx);
2963
3.41k
        return_error(gs_error_typecheck);
2964
518k
    }
2965
514k
    if (code >= 0 && ppcs && *ppcs)
2966
107k
        (void)(*ppcs)->type->install_cspace(*ppcs, ctx->pgs);
2967
2968
514k
    (void)pdfi_loop_detector_cleartomark(ctx);
2969
514k
    return code;
2970
518k
}
2971
2972
int pdfi_setcolorspace(pdf_context *ctx, pdf_obj *space, pdf_dict *stream_dict, pdf_dict *page_dict)
2973
284k
{
2974
284k
    return pdfi_create_colorspace(ctx, space, stream_dict, page_dict, NULL, false);
2975
284k
}
2976
2977
/* And finally, the implementation of the actual PDF operators CS and cs */
2978
int pdfi_setstrokecolor_space(pdf_context *ctx, pdf_dict *stream_dict, pdf_dict *page_dict)
2979
30.0k
{
2980
30.0k
    int code;
2981
30.0k
    pdf_obj *n = NULL;
2982
2983
30.0k
    if (pdfi_count_stack(ctx) < 1)
2984
849
        return_error(gs_error_stackunderflow);
2985
2986
29.2k
    if (ctx->text.inside_CharProc && ctx->text.CharProc_d_type != pdf_type3_d0) {
2987
0
        pdfi_pop(ctx, 1);
2988
0
        pdfi_log_info(ctx, "pdfi_setstrokecolor_space", "colour operator in a CharProc, following a d1 ignored\n");
2989
0
        return 0;
2990
0
    }
2991
2992
29.2k
    if (pdfi_type_of(ctx->stack_top[-1]) != PDF_NAME) {
2993
951
        pdfi_pop(ctx, 1);
2994
951
        return_error(gs_error_typecheck);
2995
951
    }
2996
28.2k
    n = ctx->stack_top[-1];
2997
28.2k
    pdfi_countup(n);
2998
28.2k
    pdfi_pop(ctx, 1);
2999
3000
28.2k
    gs_swapcolors_quick(ctx->pgs);
3001
28.2k
    code = pdfi_setcolorspace(ctx, n, stream_dict, page_dict);
3002
28.2k
    gs_swapcolors_quick(ctx->pgs);
3003
3004
28.2k
    pdfi_countdown(n);
3005
28.2k
    return code;
3006
29.2k
}
3007
3008
int pdfi_setfillcolor_space(pdf_context *ctx, pdf_dict *stream_dict, pdf_dict *page_dict)
3009
235k
{
3010
235k
    int code;
3011
235k
    pdf_obj *n = NULL;
3012
3013
235k
    if (pdfi_count_stack(ctx) < 1)
3014
3.87k
        return_error(gs_error_stackunderflow);
3015
3016
231k
    if (ctx->text.inside_CharProc && ctx->text.CharProc_d_type != pdf_type3_d0) {
3017
1
        pdfi_pop(ctx, 1);
3018
1
        pdfi_log_info(ctx, "pdfi_setfillcolor_space", "colour operator in a CharProc, following a d1 ignored\n");
3019
1
        return 0;
3020
1
    }
3021
3022
231k
    if (pdfi_type_of(ctx->stack_top[-1]) != PDF_NAME) {
3023
6.74k
        pdfi_pop(ctx, 1);
3024
6.74k
        return_error(gs_error_typecheck);
3025
6.74k
    }
3026
225k
    n = ctx->stack_top[-1];
3027
225k
    pdfi_countup(n);
3028
225k
    pdfi_pop(ctx, 1);
3029
3030
225k
    code = pdfi_setcolorspace(ctx, n, stream_dict, page_dict);
3031
3032
225k
    pdfi_countdown(n);
3033
225k
    return code;
3034
231k
}
3035
3036
3037
/*
3038
 * Set device outputintent from stream
3039
 * see zicc.c/zset_outputintent()
3040
 */
3041
static int pdfi_device_setoutputintent(pdf_context *ctx, pdf_dict *profile_dict, stream *stream)
3042
0
{
3043
0
    int code = 0;
3044
0
    gs_gstate *pgs = ctx->pgs;
3045
0
    gx_device *dev = gs_currentdevice(pgs);
3046
0
    cmm_dev_profile_t *dev_profile;
3047
0
    int64_t N;
3048
0
    int ncomps, dev_comps;
3049
0
    int expected = 0;
3050
0
    cmm_profile_t *picc_profile = NULL;
3051
0
    cmm_profile_t *source_profile = NULL;
3052
0
    gsicc_manager_t *icc_manager = pgs->icc_manager;
3053
0
    gs_color_space_index index;
3054
3055
0
    if_debug0m(gs_debug_flag_icc, ctx->memory, "[icc] Using OutputIntent\n");
3056
3057
    /* get dev_profile and try initing it if fail first time */
3058
0
    code = dev_proc(dev, get_profile)(dev, &dev_profile);
3059
0
    if (code < 0)
3060
0
        return code;
3061
3062
0
    if (dev_profile == NULL) {
3063
0
        code = gsicc_init_device_profile_struct(dev, NULL, 0);
3064
0
        if (code < 0)
3065
0
            return code;
3066
0
        code = dev_proc(dev, get_profile)(dev, &dev_profile);
3067
0
        if (code < 0)
3068
0
            return code;
3069
0
    }
3070
0
    if (dev_profile->oi_profile != NULL) {
3071
0
        return 0;  /* Allow only one setting of this object */
3072
0
    }
3073
3074
0
    code = pdfi_dict_get_int(ctx, profile_dict, "N", &N);
3075
0
    if (code < 0)
3076
0
        goto exit;
3077
0
    ncomps = (int)N;
3078
0
    if (ncomps > ICC_MAX_CHANNELS)
3079
0
        return_error(gs_error_rangecheck);
3080
3081
0
    picc_profile = gsicc_profile_new(stream, gs_gstate_memory(pgs), NULL, 0);
3082
0
    if (picc_profile == NULL) {
3083
0
        code = gs_note_error(gs_error_VMerror);
3084
0
        goto exit;
3085
0
    }
3086
0
    picc_profile->num_comps = ncomps;
3087
0
    picc_profile->profile_handle =
3088
0
        gsicc_get_profile_handle_buffer(picc_profile->buffer,
3089
0
                                        picc_profile->buffer_size,
3090
0
                                        gs_gstate_memory(pgs));
3091
0
    if (picc_profile->profile_handle == NULL) {
3092
0
        code = gs_note_error(gs_error_VMerror);
3093
0
        goto exit;
3094
0
    }
3095
3096
0
    picc_profile->data_cs =
3097
0
        gscms_get_profile_data_space(picc_profile->profile_handle,
3098
0
            picc_profile->memory);
3099
0
    switch (picc_profile->data_cs) {
3100
0
        case gsCIEXYZ:
3101
0
        case gsCIELAB:
3102
0
        case gsRGB:
3103
0
            expected = 3;
3104
0
            source_profile = icc_manager->default_rgb;
3105
0
            break;
3106
0
        case gsGRAY:
3107
0
            expected = 1;
3108
0
            source_profile = icc_manager->default_gray;
3109
0
            break;
3110
0
        case gsCMYK:
3111
0
            expected = 4;
3112
0
            source_profile = icc_manager->default_cmyk;
3113
0
            break;
3114
0
        case gsNCHANNEL:
3115
0
            expected = 0;
3116
0
            break;
3117
0
        case gsNAMED:
3118
0
        case gsUNDEFINED:
3119
0
            break;
3120
0
    }
3121
0
    if (expected && ncomps != expected) {
3122
0
        code = gs_note_error(gs_error_rangecheck);
3123
0
        goto exit;
3124
0
    }
3125
0
    gsicc_init_hash_cs(picc_profile, pgs);
3126
3127
    /* All is well with the profile.  Lets set the stuff that needs to be set */
3128
0
    dev_profile->oi_profile = picc_profile;
3129
0
    rc_increment(picc_profile);
3130
0
    picc_profile->name = (char *) gs_alloc_bytes(picc_profile->memory,
3131
0
                                                 MAX_DEFAULT_ICC_LENGTH,
3132
0
                                                 "pdfi_color_setoutputintent");
3133
0
    if (picc_profile->name == NULL) {
3134
0
        code = gs_note_error(gs_error_VMerror);
3135
0
        goto exit;
3136
0
    }
3137
0
    strncpy(picc_profile->name, OI_PROFILE, strlen(OI_PROFILE));
3138
0
    picc_profile->name[strlen(OI_PROFILE)] = 0;
3139
0
    picc_profile->name_length = strlen(OI_PROFILE);
3140
    /* Set the range of the profile */
3141
0
    gsicc_set_icc_range(&picc_profile);
3142
3143
    /* If the output device has a different number of components, then we are
3144
       going to set the output intent as the proofing profile, unless the
3145
       proofing profile has already been set.
3146
3147
       If the device has the same number of components (and color model) then as
3148
       the profile we will use this as the output profile, unless someone has
3149
       explicitly set the output profile.
3150
3151
       Finally, we will use the output intent profile for the default profile
3152
       of the proper Device profile in the icc manager, again, unless someone
3153
       has explicitly set this default profile.
3154
3155
       All of this is skipped if we are forcing oveprint simulation with
3156
       the output intent set, in which case we will push the pdf14 device
3157
       to render directly to the the output intent color space and then
3158
       do a final transform to the target color space.
3159
    */
3160
0
    dev_comps = dev_profile->device_profile[GS_DEFAULT_DEVICE_PROFILE]->num_comps;
3161
0
    index = gsicc_get_default_type(dev_profile->device_profile[GS_DEFAULT_DEVICE_PROFILE]);
3162
3163
    /* If we are doing simulate overprint and the output intent is different than
3164
       what the device profile is the we will end up pushing the pdf14 device
3165
       and doing a rendering to the output intent color space.  Keep the device
3166
       profile as is, and do not do a proofing profile */
3167
3168
0
    if (!(ctx->pgs->device->icc_struct->overprint_control == gs_overprint_control_simulate &&
3169
0
        !gsicc_profiles_equal(dev_profile->oi_profile, dev_profile->device_profile[GS_DEFAULT_DEVICE_PROFILE]))) {
3170
0
        if (ncomps == dev_comps && index < gs_color_space_index_DevicePixel) {
3171
            /* The OI profile is the same type as the profile for the device and a
3172
               "default" profile for the device was not externally set. So we go
3173
               ahead and use the OI profile as the device profile.  Care needs to be
3174
               taken here to keep from screwing up any device parameters.   We will
3175
               use a keyword of OIProfile for the user/device parameter to indicate
3176
               its usage.  Also, note conflicts if one is setting object dependent
3177
               color management */
3178
0
            dev_profile->device_profile[GS_DEFAULT_DEVICE_PROFILE] = picc_profile;
3179
0
            rc_increment(picc_profile);
3180
0
            if_debug0m(gs_debug_flag_icc, ctx->memory, "[icc] OutputIntent used for device profile\n");
3181
0
        } else {
3182
0
            if (dev_profile->proof_profile == NULL) {
3183
                /* This means that we should use the OI profile as the proofing
3184
                   profile.  Note that if someone already has specified a
3185
                   proofing profile it is unclear what they are trying to do
3186
                   with the output intent.  In this case, we will use it
3187
                   just for the source data below */
3188
0
                dev_profile->proof_profile = picc_profile;
3189
0
                rc_increment(picc_profile);
3190
0
                if_debug0m(gs_debug_flag_icc, ctx->memory, "[icc] OutputIntent used for proof profile\n");
3191
0
            }
3192
0
        }
3193
0
    }
3194
3195
    /* Now the source colors.  See which source color space needs to use the
3196
       output intent ICC profile */
3197
0
    index = gsicc_get_default_type(source_profile);
3198
0
    if (index < gs_color_space_index_DevicePixel) {
3199
        /* source_profile is currently the default.  Set it to the OI profile */
3200
0
        switch (picc_profile->data_cs) {
3201
0
            case gsGRAY:
3202
0
                if_debug0m(gs_debug_flag_icc, ctx->memory, "[icc] OutputIntent used source Gray\n");
3203
0
                icc_manager->default_gray = picc_profile;
3204
0
                rc_increment(picc_profile);
3205
0
                break;
3206
0
            case gsRGB:
3207
0
                if_debug0m(gs_debug_flag_icc, ctx->memory, "[icc] OutputIntent used source RGB\n");
3208
0
                icc_manager->default_rgb = picc_profile;
3209
0
                rc_increment(picc_profile);
3210
0
                break;
3211
0
            case gsCMYK:
3212
0
                if_debug0m(gs_debug_flag_icc, ctx->memory, "[icc] OutputIntent used source CMYK\n");
3213
0
                icc_manager->default_cmyk = picc_profile;
3214
0
                rc_increment(picc_profile);
3215
0
                break;
3216
0
            default:
3217
0
                break;
3218
0
        }
3219
0
    }
3220
3221
0
 exit:
3222
0
    if (picc_profile != NULL)
3223
0
        rc_decrement(picc_profile, "pdfi_color_setoutputintent");
3224
0
    return code;
3225
0
}
3226
3227
/*
3228
 * intent_dict -- the outputintent dictionary
3229
 * profile -- the color profile (a stream)
3230
 *
3231
 */
3232
int pdfi_color_setoutputintent(pdf_context *ctx, pdf_dict *intent_dict, pdf_stream *profile)
3233
0
{
3234
0
    pdf_c_stream *profile_stream = NULL;
3235
0
    byte *profile_buffer;
3236
0
    int code, code1;
3237
0
    pdf_dict *profile_dict;
3238
3239
0
    code = pdfi_dict_from_obj(ctx, (pdf_obj *)profile, &profile_dict);
3240
0
    if (code < 0)
3241
0
        return code;
3242
3243
    /* The ICC profile reading code (irritatingly) requires a seekable stream, because it
3244
     * rewinds it to the start, then seeks to the end to find the size, then rewinds the
3245
     * stream again.
3246
     * Ideally we would use a ReusableStreamDecode filter here, but that is largely
3247
     * implemented in PostScript (!) so we can't use it. What we can do is create a
3248
     * string sourced stream in memory, which is at least seekable.
3249
     */
3250
0
    code = pdfi_open_memory_stream_from_filtered_stream(ctx, profile, &profile_buffer, &profile_stream, true);
3251
0
    if (code < 0)
3252
0
        goto exit;
3253
3254
    /* Create and set the device profile */
3255
0
    code = pdfi_device_setoutputintent(ctx, profile_dict, profile_stream->s);
3256
3257
0
    code1 = pdfi_close_memory_stream(ctx, profile_buffer, profile_stream);
3258
3259
0
    if (code == 0)
3260
0
        code = code1;
3261
3262
0
 exit:
3263
0
    return code;
3264
0
}
3265
3266
static int Check_Default_Space(pdf_context *ctx, pdf_obj *space, pdf_dict *source_dict, int num_components)
3267
754
{
3268
754
    pdf_obj *primary = NULL;
3269
754
    pdf_obj *ref_space = NULL;
3270
754
    int code = 0;
3271
3272
754
    if (pdfi_type_of(space) == PDF_NAME)
3273
0
    {
3274
0
        if (pdfi_name_is((const pdf_name *)space, "DeviceGray"))
3275
0
            return (num_components == 1 ? 0 : gs_error_rangecheck);
3276
0
        if (pdfi_name_is((const pdf_name *)space, "DeviceCMYK"))
3277
0
            return (num_components == 4 ? 0 : gs_error_rangecheck);
3278
0
        if (pdfi_name_is((const pdf_name *)space, "DeviceRGB"))
3279
0
            return (num_components == 3 ? 0 : gs_error_rangecheck);
3280
3281
0
        code = pdfi_find_resource(ctx, (unsigned char *)"ColorSpace", (pdf_name *)space, (pdf_dict *)source_dict,
3282
0
                                  NULL, &ref_space);
3283
0
        if (code < 0)
3284
0
            return code;
3285
3286
0
        if (pdfi_type_of(ref_space) == PDF_NAME) {
3287
0
            if (ref_space->object_num != 0 && ref_space->object_num == space->object_num) {
3288
0
                pdfi_countdown(ref_space);
3289
0
                return_error(gs_error_circular_reference);
3290
0
            }
3291
0
            if (pdfi_name_is((const pdf_name *)ref_space, "DeviceGray")) {
3292
0
                pdfi_countdown(ref_space);
3293
0
                return (num_components == 1 ? 0 : gs_error_rangecheck);
3294
0
            }
3295
0
            if (pdfi_name_is((const pdf_name *)ref_space, "DeviceCMYK")) {
3296
0
                pdfi_countdown(ref_space);
3297
0
                return (num_components == 4 ? 0 : gs_error_rangecheck);
3298
0
            }
3299
0
            if (pdfi_name_is((const pdf_name *)ref_space, "DeviceRGB")) {
3300
0
                pdfi_countdown(ref_space);
3301
0
                return (num_components == 3 ? 0 : gs_error_rangecheck);
3302
0
            }
3303
0
            pdfi_countdown(ref_space);
3304
0
            return_error(gs_error_typecheck);
3305
0
        }
3306
0
        space = ref_space;
3307
0
    }
3308
3309
754
    if (pdfi_type_of(space) == PDF_ARRAY) {
3310
735
        code = pdfi_array_get(ctx, (pdf_array *)space, 0, &primary);
3311
735
        if (code < 0)
3312
0
            goto exit;
3313
3314
735
        if (pdfi_type_of(primary) == PDF_NAME) {
3315
735
            if (pdfi_name_is((pdf_name *)primary, "Lab")) {
3316
0
                code = gs_note_error(gs_error_typecheck);
3317
0
                goto exit;
3318
0
            }
3319
735
            if (pdfi_name_is((pdf_name *)primary, "Pattern")) {
3320
4
                code = gs_note_error(gs_error_typecheck);
3321
4
                goto exit;
3322
4
            }
3323
731
            if (pdfi_name_is((pdf_name *)primary, "Indexed")) {
3324
0
                code = gs_note_error(gs_error_typecheck);
3325
0
                goto exit;
3326
0
            }
3327
731
        }
3328
735
    } else
3329
19
        code = gs_note_error(gs_error_typecheck);
3330
3331
754
exit:
3332
754
    pdfi_countdown(primary);
3333
754
    pdfi_countdown(ref_space);
3334
754
    return code;
3335
754
}
3336
3337
int pdfi_setup_DefaultSpaces(pdf_context *ctx, pdf_dict *source_dict)
3338
406k
{
3339
406k
    int code = 0;
3340
406k
    pdf_dict *resources_dict = NULL, *colorspaces_dict = NULL;
3341
406k
    pdf_obj *DefaultSpace = NULL;
3342
3343
406k
    if (ctx->args.NOSUBSTDEVICECOLORS)
3344
0
        return 0;
3345
3346
    /* Create any required DefaultGray, DefaultRGB or DefaultCMYK
3347
     * spaces.
3348
     */
3349
406k
    code = pdfi_dict_knownget(ctx, source_dict, "Resources", (pdf_obj **)&resources_dict);
3350
406k
    if (code > 0) {
3351
340k
        code = pdfi_dict_knownget(ctx, resources_dict, "ColorSpace", (pdf_obj **)&colorspaces_dict);
3352
340k
        if (code > 0) {
3353
37.8k
            code = pdfi_dict_knownget(ctx, colorspaces_dict, "DefaultGray", &DefaultSpace);
3354
37.8k
            if (code > 0) {
3355
0
                gs_color_space *pcs;
3356
3357
0
                code = Check_Default_Space(ctx, DefaultSpace, source_dict, 1);
3358
0
                if (code >= 0) {
3359
0
                    code = pdfi_create_colorspace(ctx, DefaultSpace, NULL, source_dict, &pcs, false);
3360
                    /* If any given Default* space fails simply ignore it, we wil then use the Device
3361
                     * space instead, this is as per the spec.
3362
                     */
3363
0
                    if (code >= 0) {
3364
0
                        if (gs_color_space_num_components(pcs) == 1) {
3365
0
                            ctx->page.DefaultGray_cs = pcs;
3366
0
                            pdfi_set_colour_callback(pcs, ctx, NULL);
3367
0
                        } else {
3368
0
                            rc_decrement(pcs, "setup_DefautSpaces");
3369
0
                            if ((code = pdfi_set_warning_stop(ctx, gs_note_error(gs_error_syntaxerror), NULL, W_PDF_INVALID_DEFAULTSPACE, "pdfi_setup_DefaultSpaces", NULL)) < 0)
3370
0
                                return code;
3371
0
                        }
3372
0
                    }
3373
0
                } else {
3374
0
                    if ((code = pdfi_set_warning_stop(ctx, gs_note_error(gs_error_syntaxerror), NULL, W_PDF_INVALID_DEFAULTSPACE, "pdfi_setup_DefaultSpaces", NULL)) < 0)
3375
0
                        return code;
3376
0
                }
3377
0
            }
3378
37.8k
            pdfi_countdown(DefaultSpace);
3379
37.8k
            DefaultSpace = NULL;
3380
37.8k
            code = pdfi_dict_knownget(ctx, colorspaces_dict, "DefaultRGB", &DefaultSpace);
3381
37.8k
            if (code > 0) {
3382
727
                gs_color_space *pcs;
3383
3384
727
                code = Check_Default_Space(ctx, DefaultSpace, source_dict, 1);
3385
727
                if (code >= 0) {
3386
704
                    code = pdfi_create_colorspace(ctx, DefaultSpace, NULL, source_dict, &pcs, false);
3387
                    /* If any given Default* space fails simply ignore it, we wil then use the Device
3388
                     * space instead, this is as per the spec.
3389
                     */
3390
704
                    if (code >= 0) {
3391
604
                        if (gs_color_space_num_components(pcs) == 3) {
3392
604
                            ctx->page.DefaultRGB_cs = pcs;
3393
604
                            pdfi_set_colour_callback(pcs, ctx, NULL);
3394
604
                        } else {
3395
0
                            rc_decrement(pcs, "setup_DefautSpaces");
3396
0
                            if ((code = pdfi_set_warning_stop(ctx, gs_note_error(gs_error_syntaxerror), NULL, W_PDF_INVALID_DEFAULTSPACE, "pdfi_setup_DefaultSpaces", NULL)) < 0)
3397
0
                                return code;
3398
0
                        }
3399
604
                    }
3400
704
                } else {
3401
23
                    if ((code = pdfi_set_warning_stop(ctx, gs_note_error(gs_error_syntaxerror), NULL, W_PDF_INVALID_DEFAULTSPACE, "pdfi_setup_DefaultSpaces", NULL)) < 0)
3402
0
                        return code;
3403
23
                }
3404
727
            }
3405
37.8k
            pdfi_countdown(DefaultSpace);
3406
37.8k
            DefaultSpace = NULL;
3407
37.8k
            code = pdfi_dict_knownget(ctx, colorspaces_dict, "DefaultCMYK", &DefaultSpace);
3408
37.8k
            if (code > 0) {
3409
27
                gs_color_space *pcs;
3410
3411
27
                code = Check_Default_Space(ctx, DefaultSpace, source_dict, 1);
3412
27
                if (code >= 0) {
3413
27
                    code = pdfi_create_colorspace(ctx, DefaultSpace, NULL, source_dict, &pcs, false);
3414
                    /* If any given Default* space fails simply ignore it, we wil then use the Device
3415
                     * space instead, this is as per the spec.
3416
                     */
3417
27
                    if (code >= 0) {
3418
27
                        if (gs_color_space_num_components(pcs) == 4) {
3419
27
                            ctx->page.DefaultCMYK_cs = pcs;
3420
27
                            pdfi_set_colour_callback(pcs, ctx, NULL);
3421
27
                        } else {
3422
0
                            rc_decrement(pcs, "setup_DefautSpaces");
3423
0
                            if ((code = pdfi_set_warning_stop(ctx, gs_note_error(gs_error_syntaxerror), NULL, W_PDF_INVALID_DEFAULTSPACE, "pdfi_setup_DefaultSpaces", NULL)) < 0)
3424
0
                                return code;
3425
0
                        }
3426
27
                    }
3427
27
                } else {
3428
0
                    if ((code = pdfi_set_warning_stop(ctx, gs_note_error(gs_error_syntaxerror), NULL, W_PDF_INVALID_DEFAULTSPACE, "pdfi_setup_DefaultSpaces", NULL)) < 0)
3429
0
                        return code;
3430
0
                }
3431
27
            }
3432
37.8k
            pdfi_countdown(DefaultSpace);
3433
37.8k
            DefaultSpace = NULL;
3434
37.8k
        }
3435
340k
    }
3436
3437
406k
    pdfi_countdown(DefaultSpace);
3438
406k
    pdfi_countdown(resources_dict);
3439
406k
    pdfi_countdown(colorspaces_dict);
3440
406k
    return 0;
3441
406k
}