Coverage Report

Created: 2025-06-10 07:27

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