Coverage Report

Created: 2025-08-28 07:06

/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
32.9k
{
64
32.9k
    pdf_obj *ref_space;
65
32.9k
    int code;
66
67
32.9k
    if (pdfi_name_is(name, "G")) {
68
0
        return 0;
69
32.9k
    } else if (pdfi_name_is(name, "RGB")) {
70
0
        return 0;
71
32.9k
    } else if (pdfi_name_is(name, "CMYK")) {
72
0
        return 0;
73
32.9k
    } else if (pdfi_name_is(name, "DeviceRGB")) {
74
26.7k
        return 0;
75
26.7k
    } else if (pdfi_name_is(name, "DeviceGray")) {
76
2.11k
        return 0;
77
4.09k
    } else if (pdfi_name_is(name, "DeviceCMYK")) {
78
3.58k
        return 0;
79
3.58k
    } else if (pdfi_name_is(name, "Pattern")) {
80
        /* TODO: I think this is fine... */
81
394
        return 0;
82
394
    } else {
83
116
        code = pdfi_find_resource(ctx, (unsigned char *)"ColorSpace", name, parent_dict, page_dict, &ref_space);
84
116
        if (code < 0)
85
112
            return code;
86
87
4
        if (pdfi_type_of(ref_space) == PDF_NAME) {
88
4
            if (pdfi_name_cmp(name, (pdf_name *)ref_space) == 0) {
89
4
                pdfi_set_error(ctx, gs_error_circular_reference, NULL, E_PDF_CIRCULARNAME, NULL, NULL);
90
4
                pdfi_countdown(ref_space);
91
4
                return_error(gs_error_circular_reference);
92
4
            }
93
4
        }
94
        /* recursion */
95
0
        return pdfi_check_ColorSpace_for_spots(ctx, ref_space, parent_dict, page_dict, spot_dict);
96
4
    }
97
0
    return 0;
98
32.9k
}
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
26.0k
{
103
26.0k
    pdf_name *space = NULL;
104
26.0k
    pdf_array *a = NULL;
105
26.0k
    int code = 0;
106
107
26.0k
    if (!spot_dict)
108
0
        return 0;
109
110
26.0k
    code = pdfi_array_get_type(ctx, color_array, 0, PDF_NAME, (pdf_obj **)&space);
111
26.0k
    if (code != 0)
112
22
        goto exit;
113
114
26.0k
    code = 0;
115
26.0k
    if (pdfi_name_is(space, "G")) {
116
0
        goto exit;
117
26.0k
    } else if (pdfi_name_is(space, "I") || pdfi_name_is(space, "Indexed")) {
118
3.79k
        pdf_obj *base_space;
119
120
3.79k
        code = pdfi_array_get(ctx, color_array, 1, &base_space);
121
3.79k
        if (code == 0) {
122
3.72k
            code = pdfi_check_ColorSpace_for_spots(ctx, base_space, parent_dict, page_dict, spot_dict);
123
3.72k
            (void)pdfi_countdown(base_space);
124
3.72k
        }
125
3.79k
        goto exit;
126
22.2k
    } else if (pdfi_name_is(space, "Pattern")) {
127
908
        pdf_obj *base_space = NULL;
128
908
        uint64_t size = pdfi_array_size(color_array);
129
130
        /* Array of size 1 "[ /Pattern ]" is okay, just do nothing. */
131
908
        if (size == 1)
132
612
            goto exit;
133
        /* Array of size > 2 we don't handle (shouldn't happen?) */
134
296
        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
296
        code = pdfi_array_get(ctx, color_array, 1, &base_space);
142
296
        if (code == 0) {
143
296
            code = pdfi_check_ColorSpace_for_spots(ctx, base_space, parent_dict, page_dict, spot_dict);
144
296
            (void)pdfi_countdown(base_space);
145
296
        }
146
296
        goto exit;
147
21.3k
    } else if (pdfi_name_is(space, "Lab")) {
148
254
        goto exit;
149
21.1k
    } else if (pdfi_name_is(space, "RGB")) {
150
0
        goto exit;
151
21.1k
    } else if (pdfi_name_is(space, "CMYK")) {
152
0
        goto exit;
153
21.1k
    } else if (pdfi_name_is(space, "CalRGB")) {
154
606
        goto exit;
155
20.5k
    } else if (pdfi_name_is(space, "CalGray")) {
156
72
        goto exit;
157
20.4k
    } else if (pdfi_name_is(space, "CalCMYK")) {
158
0
        goto exit;
159
20.4k
    } else if (pdfi_name_is(space, "ICCBased")) {
160
15.7k
        goto exit;
161
15.7k
    } else if (pdfi_name_is(space, "DeviceRGB")) {
162
2
        goto exit;
163
4.71k
    } else if (pdfi_name_is(space, "DeviceGray")) {
164
0
        goto exit;
165
4.71k
    } else if (pdfi_name_is(space, "DeviceCMYK")) {
166
0
        goto exit;
167
4.71k
    } else if (pdfi_name_is(space, "DeviceN")) {
168
2.26k
        bool known = false;
169
2.26k
        pdf_obj *dummy, *name;
170
2.26k
        int i;
171
172
2.26k
        pdfi_countdown(space);
173
2.26k
        code = pdfi_array_get_type(ctx, color_array, 1, PDF_ARRAY, (pdf_obj **)&space);
174
2.26k
        if (code != 0)
175
4
            goto exit;
176
177
5.89k
        for (i=0;i < pdfi_array_size((pdf_array *)space); i++) {
178
3.63k
            code = pdfi_array_get_type(ctx, (pdf_array *)space, (uint64_t)i, PDF_NAME, &name);
179
3.63k
            if (code < 0)
180
0
                goto exit;
181
182
3.63k
            if (pdfi_name_is((const pdf_name *)name, "Cyan") || pdfi_name_is((const pdf_name *)name, "Magenta") ||
183
3.63k
                pdfi_name_is((const pdf_name *)name, "Yellow") || pdfi_name_is((const pdf_name *)name, "Black") ||
184
3.63k
                pdfi_name_is((const pdf_name *)name, "None") || pdfi_name_is((const pdf_name *)name, "All")) {
185
186
2.95k
                pdfi_countdown(name);
187
2.95k
                continue;
188
2.95k
            }
189
190
678
            code = pdfi_dict_known_by_key(ctx, spot_dict, (pdf_name *)name, &known);
191
678
            if (code < 0) {
192
0
                pdfi_countdown(name);
193
0
                goto exit;
194
0
            }
195
678
            if (known) {
196
50
                pdfi_countdown(name);
197
50
                continue;
198
50
            }
199
200
628
            code = pdfi_object_alloc(ctx, PDF_INT, 0, &dummy);
201
628
            if (code < 0)
202
0
                goto exit;
203
204
628
            code = pdfi_dict_put_obj(ctx, spot_dict, name, dummy, true);
205
628
            pdfi_countdown(name);
206
628
            if (code < 0)
207
0
                break;
208
628
        }
209
2.26k
        goto exit;
210
2.44k
    } else if (pdfi_name_is(space, "Separation")) {
211
2.40k
        bool known = false;
212
2.40k
        pdf_obj *dummy;
213
214
2.40k
        pdfi_countdown(space);
215
2.40k
        code = pdfi_array_get_type(ctx, color_array, 1, PDF_NAME, (pdf_obj **)&space);
216
2.40k
        if (code != 0)
217
0
            goto exit;
218
219
2.40k
        if (pdfi_name_is((const pdf_name *)space, "Cyan") || pdfi_name_is((const pdf_name *)space, "Magenta") ||
220
2.40k
            pdfi_name_is((const pdf_name *)space, "Yellow") || pdfi_name_is((const pdf_name *)space, "Black") ||
221
2.40k
            pdfi_name_is((const pdf_name *)space, "None") || pdfi_name_is((const pdf_name *)space, "All"))
222
1.82k
            goto exit;
223
574
        code = pdfi_dict_known_by_key(ctx, spot_dict, space, &known);
224
574
        if (code < 0 || known)
225
160
            goto exit;
226
227
414
        code = pdfi_object_alloc(ctx, PDF_INT, 0, &dummy);
228
414
        if (code < 0)
229
0
            goto exit;
230
231
414
        code = pdfi_dict_put_obj(ctx, spot_dict, (pdf_obj *)space, dummy, true);
232
414
        goto exit;
233
414
    } else {
234
46
        code = pdfi_find_resource(ctx, (unsigned char *)"ColorSpace",
235
46
                                  space, parent_dict, page_dict, (pdf_obj **)&a);
236
46
        if (code < 0)
237
42
            goto exit;
238
239
4
        if (pdfi_type_of(a) != PDF_ARRAY) {
240
0
            code = gs_note_error(gs_error_typecheck);
241
0
            goto exit;
242
0
        }
243
4
        if (a == color_array) {
244
4
            code = gs_note_error(gs_error_circular_reference);
245
4
            goto exit;
246
4
        }
247
248
        /* recursion */
249
0
        code = pdfi_check_for_spots_by_array(ctx, a, parent_dict, page_dict, spot_dict);
250
0
    }
251
252
26.0k
 exit:
253
26.0k
    if (space)
254
26.0k
        pdfi_countdown(space);
255
26.0k
    if (a)
256
4
        pdfi_countdown(a);
257
26.0k
    return code;
258
26.0k
}
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
59.4k
{
263
59.4k
    int code;
264
265
59.4k
    if (!spot_dict)
266
0
        return 0;
267
268
59.4k
    code = pdfi_loop_detector_mark(ctx);
269
59.4k
    if (code < 0)
270
0
        return code;
271
272
59.4k
    switch(pdfi_type_of(space)) {
273
32.9k
        case PDF_NAME:
274
32.9k
            code = pdfi_check_for_spots_by_name(ctx, (pdf_name *)space, parent_dict, page_dict, spot_dict);
275
32.9k
            break;
276
26.0k
        case PDF_ARRAY:
277
26.0k
            code = pdfi_check_for_spots_by_array(ctx, (pdf_array *)space, parent_dict, page_dict, spot_dict);
278
26.0k
            break;
279
322
        default:
280
322
            pdfi_loop_detector_cleartomark(ctx);
281
322
            return 0;
282
59.4k
    }
283
284
59.0k
    (void)pdfi_loop_detector_cleartomark(ctx);
285
59.0k
    return code;
286
59.4k
}
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
177k
{
293
177k
    pdf_name *n;
294
177k
    int code;
295
296
177k
    if (pdfi_count_stack(ctx) < 1)
297
26.5k
        return_error(gs_error_stackunderflow);
298
299
150k
    if (pdfi_type_of(ctx->stack_top[-1]) != PDF_NAME) {
300
3.27k
        pdfi_pop(ctx, 1);
301
3.27k
        return_error(gs_error_typecheck);
302
3.27k
    }
303
147k
    n = (pdf_name *)ctx->stack_top[-1];
304
147k
    pdfi_countup(n);
305
147k
    pdfi_pop(ctx, 1);
306
147k
    code = pdfi_setrenderingintent(ctx, n);
307
147k
    pdfi_countdown(n);
308
147k
    return code;
309
150k
}
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
2.14M
{
326
2.14M
    gs_color_space *pcs = (gs_color_space *)cs;
327
2.14M
    pdf_obj *o = (pdf_obj *)pcs->interpreter_data;
328
2.14M
    pdf_context *ctx = NULL;
329
2.14M
    gs_function_t *pfn;
330
331
2.14M
    if (o == NULL)
332
77
        return;
333
334
2.14M
    ctx = o->ctx;
335
336
2.14M
    if (gs_color_space_get_index(pcs) == gs_color_space_index_Separation) {
337
        /* Handle cleanup of Separation functions if applicable */
338
56.1k
        pfn = gs_cspace_get_sepr_function(pcs);
339
56.1k
        if (pfn)
340
56.1k
            pdfi_free_function(ctx, pfn);
341
56.1k
    }
342
343
2.14M
    if (gs_color_space_get_index(pcs) == gs_color_space_index_DeviceN) {
344
        /* Handle cleanup of DeviceN functions if applicable */
345
22.0k
        pfn = gs_cspace_get_devn_function(pcs);
346
22.0k
        if (pfn)
347
22.0k
            pdfi_free_function(ctx, pfn);
348
22.0k
    }
349
2.14M
    if (pdfi_type_of(o) != PDF_CTX) {
350
71.3k
        pdfi_countdown(o);
351
71.3k
        pcs->interpreter_data = NULL;
352
71.3k
    }
353
2.14M
}
354
355
int pdfi_gs_setgray(pdf_context *ctx, double d)
356
1.68M
{
357
1.68M
    int code = 0;
358
1.68M
    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
1.68M
    if (ctx->text.inside_CharProc && ctx->text.CharProc_d_type != pdf_type3_d0) {
362
12.8k
        pdfi_log_info(ctx, "pdfi_gs_setgray", "colour operator in a CharProc, following a d1 ignored\n");
363
12.8k
        return 0;
364
12.8k
    }
365
366
1.67M
    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
1.67M
    } else {
381
1.67M
        code = gs_setgray(ctx->pgs, d);
382
1.67M
        if (code < 0)
383
12
            return code;
384
1.67M
    }
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
1.67M
    if (pcs != ctx->pgs->color[0].color_space)
389
802k
        pdfi_set_colour_callback(ctx->pgs->color[0].color_space, ctx, pdfi_cspace_free_callback);
390
1.67M
    return 0;
391
1.67M
}
392
393
int pdfi_gs_setrgbcolor(pdf_context *ctx, double r, double g, double b)
394
2.57M
{
395
2.57M
    int code = 0;
396
2.57M
    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
2.57M
    if (ctx->text.inside_CharProc && ctx->text.CharProc_d_type != pdf_type3_d0) {
400
340
        pdfi_log_info(ctx, "pdfi_gs_setrgbcolor", "colour operator in a CharProc, following a d1 ignored\n");
401
340
        return 0;
402
340
    }
403
404
2.57M
    if (ctx->page.DefaultRGB_cs != NULL) {
405
15.0k
        gs_client_color cc;
406
407
15.0k
        code = gs_setcolorspace(ctx->pgs, ctx->page.DefaultRGB_cs);
408
15.0k
        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
15.0k
        if (pcs != ctx->pgs->color[0].color_space)
414
5.33k
            pdfi_set_colour_callback(ctx->pgs->color[0].color_space, ctx, pdfi_cspace_free_callback);
415
15.0k
        cc.paint.values[0] = r;
416
15.0k
        cc.paint.values[1] = g;
417
15.0k
        cc.paint.values[2] = b;
418
15.0k
        cc.pattern = 0;
419
15.0k
        return gs_setcolor(ctx->pgs, &cc);
420
2.56M
    } else {
421
2.56M
        code = gs_setrgbcolor(ctx->pgs, r, g, b);
422
2.56M
        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
2.56M
        if (pcs != ctx->pgs->color[0].color_space)
428
796k
            pdfi_set_colour_callback(ctx->pgs->color[0].color_space, ctx, pdfi_cspace_free_callback);
429
2.56M
    }
430
2.56M
    return 0;
431
2.57M
}
432
433
static int pdfi_gs_setcmykcolor(pdf_context *ctx, double c, double m, double y, double k)
434
290k
{
435
290k
    int code = 0;
436
290k
    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
290k
    if (ctx->text.inside_CharProc && ctx->text.CharProc_d_type != pdf_type3_d0) {
440
48
        pdfi_log_info(ctx, "pdfi_gs_setcmykcolor", "colour operator in a CharProc, following a d1 ignored\n");
441
48
        return 0;
442
48
    }
443
444
290k
    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
290k
    } else {
462
290k
        code = gs_setcmykcolor(ctx->pgs, c, m, y, k);
463
290k
        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
290k
        if (pcs != ctx->pgs->color[0].color_space)
469
142k
            pdfi_set_colour_callback(ctx->pgs->color[0].color_space, ctx, pdfi_cspace_free_callback);
470
290k
    }
471
290k
    return 0;
472
290k
}
473
474
int pdfi_gs_setcolorspace(pdf_context *ctx, gs_color_space *pcs)
475
470k
{
476
470k
    gs_color_space *old_pcs = ctx->pgs->color[0].color_space;
477
470k
    int code = 0;
478
    /* If the target colour space is already the current colour space, don't
479
     * bother to do anything.
480
     */
481
470k
    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
440k
        if (ctx->text.inside_CharProc && ctx->text.CharProc_d_type != pdf_type3_d0) {
484
3
            pdfi_log_info(ctx, "pdfi_gs_setcolorspace", "colour operator in a CharProc, following a d1 ignored\n");
485
3
            return 0;
486
3
        }
487
488
440k
        code = gs_setcolorspace(ctx->pgs, pcs);
489
440k
        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
440k
        if (old_pcs != ctx->pgs->color[0].color_space)
495
440k
            pdfi_set_colour_callback(ctx->pgs->color[0].color_space, ctx, pdfi_cspace_free_callback);
496
440k
    }
497
470k
    return 0;
498
470k
}
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
712k
{
503
712k
    int code;
504
712k
    double d1;
505
506
712k
    code = pdfi_destack_real(ctx, &d1);
507
712k
    if (code < 0)
508
27.1k
        return code;
509
510
685k
    gs_swapcolors_quick(ctx->pgs);
511
685k
    code = pdfi_gs_setgray(ctx, d1);
512
685k
    gs_swapcolors_quick(ctx->pgs);
513
514
685k
    return code;
515
712k
}
516
517
int pdfi_setgrayfill(pdf_context *ctx)
518
985k
{
519
985k
    int code;
520
985k
    double d1;
521
522
985k
    code = pdfi_destack_real(ctx, &d1);
523
985k
    if (code < 0)
524
16.4k
        return code;
525
526
969k
    return pdfi_gs_setgray(ctx, d1);
527
985k
}
528
529
int pdfi_setrgbstroke(pdf_context *ctx)
530
1.12M
{
531
1.12M
    double Values[3];
532
1.12M
    int code;
533
534
1.12M
    code = pdfi_destack_reals(ctx, Values, 3);
535
1.12M
    if (code < 0)
536
49.8k
        return code;
537
538
1.07M
    gs_swapcolors_quick(ctx->pgs);
539
1.07M
    code = pdfi_gs_setrgbcolor(ctx, Values[0], Values[1], Values[2]);
540
1.07M
    gs_swapcolors_quick(ctx->pgs);
541
542
1.07M
    return code;
543
1.12M
}
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
63.3k
{
550
63.3k
    int code;
551
63.3k
    pdf_array *array = NULL;
552
553
63.3k
    pdfi_set_warning(ctx, 0, NULL, W_PDF_NONSTANDARD_OP, "pdfi_setrgbfill_array", (char *)"WARNING: Non-standard 'r' operator");
554
555
63.3k
    if (pdfi_count_stack(ctx) < 1)
556
15.7k
        return_error(gs_error_stackunderflow);
557
558
47.5k
    array = (pdf_array *)ctx->stack_top[-1];
559
47.5k
    pdfi_countup(array);
560
47.5k
    pdfi_pop(ctx, 1);
561
47.5k
    if (pdfi_type_of(array) != PDF_ARRAY) {
562
47.5k
        code = gs_note_error(gs_error_typecheck);
563
47.5k
        goto exit;
564
47.5k
    }
565
566
51
    code = pdfi_setcolor_from_array(ctx, array);
567
47.5k
 exit:
568
47.5k
    pdfi_countdown(array);
569
47.5k
    return code;
570
51
}
571
572
int pdfi_setrgbfill(pdf_context *ctx)
573
1.49M
{
574
1.49M
    double Values[3];
575
1.49M
    int code;
576
577
1.49M
    code = pdfi_destack_reals(ctx, Values, 3);
578
1.49M
    if (code < 0)
579
40.5k
        return code;
580
581
1.45M
    return pdfi_gs_setrgbcolor(ctx, Values[0], Values[1], Values[2]);
582
1.49M
}
583
584
int pdfi_setcmykstroke(pdf_context *ctx)
585
63.0k
{
586
63.0k
    double Values[4];
587
63.0k
    int code;
588
589
63.0k
    code = pdfi_destack_reals(ctx, Values, 4);
590
63.0k
    if (code < 0)
591
10.0k
        return code;
592
593
53.0k
    gs_swapcolors_quick(ctx->pgs);
594
53.0k
    code = pdfi_gs_setcmykcolor(ctx, Values[0], Values[1], Values[2], Values[3]);
595
53.0k
    gs_swapcolors_quick(ctx->pgs);
596
597
53.0k
    return code;
598
63.0k
}
599
600
int pdfi_setcmykfill(pdf_context *ctx)
601
226k
{
602
226k
    double Values[4];
603
226k
    int code;
604
605
226k
    code = pdfi_destack_reals(ctx, Values, 4);
606
226k
    if (code < 0)
607
13.5k
        return code;
608
609
212k
    return pdfi_gs_setcmykcolor(ctx, Values[0], Values[1], Values[2], Values[3]);
610
226k
}
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
7.39k
{
618
7.39k
    int code = 0;
619
7.39k
    uint64_t size;
620
7.39k
    double values[4];
621
622
7.39k
    size = pdfi_array_size(array);
623
7.39k
    if (size != 1 && size != 3 && size != 4) {
624
56
        code = gs_note_error(gs_error_rangecheck);
625
56
        goto exit;
626
56
    }
627
628
7.33k
    code = pdfi_array_to_num_array(ctx, array, values, 0, size);
629
7.33k
    if (code < 0) goto exit;
630
631
7.30k
    switch (size) {
632
228
    case 1:
633
228
        code = pdfi_gs_setgray(ctx, values[0]);
634
228
        break;
635
7.06k
    case 3:
636
7.06k
        code = pdfi_gs_setrgbcolor(ctx, values[0], values[1], values[2]);
637
7.06k
        break;
638
13
    case 4:
639
13
        code = pdfi_gs_setcmykcolor(ctx, values[0], values[1], values[2], values[3]);
640
13
        break;
641
0
    default:
642
0
        break;
643
7.30k
    }
644
645
7.39k
 exit:
646
7.39k
    return code;
647
7.30k
}
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
453k
{
653
453k
    int i, code;
654
655
453k
    if (pdfi_count_stack(ctx) < ncomps) {
656
20.6k
        pdfi_clearstack(ctx);
657
20.6k
        return_error(gs_error_stackunderflow);
658
20.6k
    }
659
660
1.39M
    for (i = 0; i < ncomps; i++) {
661
969k
        code = pdfi_obj_to_float(ctx, ctx->stack_top[i - ncomps], &cc->paint.values[i]);
662
969k
        if (code < 0) {
663
12.7k
            pdfi_clearstack(ctx);
664
12.7k
            return code;
665
12.7k
        }
666
969k
    }
667
420k
    pdfi_pop(ctx, ncomps);
668
669
420k
    return 0;
670
432k
}
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
78.5k
{
682
78.5k
    const gs_color_space *  pcs;
683
78.5k
    int ncomps, code;
684
78.5k
    gs_client_color cc;
685
686
78.5k
    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
78.5k
    cc.pattern = 0;
697
78.5k
    gs_swapcolors_quick(ctx->pgs);
698
78.5k
    pcs = gs_currentcolorspace(ctx->pgs);
699
78.5k
    ncomps = cs_num_components(pcs);
700
78.5k
    if (ncomps < 1) {
701
2
        gs_swapcolors_quick(ctx->pgs);
702
2
        return_error(gs_error_syntaxerror);
703
2
    }
704
78.5k
    code = pdfi_get_color_from_stack(ctx, &cc, ncomps);
705
78.5k
    if (code == 0) {
706
75.8k
        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
75.8k
        code = gs_setcolor(ctx->pgs, &cc);
721
75.8k
    }
722
78.5k
    gs_swapcolors_quick(ctx->pgs);
723
78.5k
    return code;
724
78.5k
}
725
726
int pdfi_setfillcolor(pdf_context *ctx)
727
259k
{
728
259k
    const gs_color_space *  pcs = gs_currentcolorspace(ctx->pgs);
729
259k
    int ncomps, code;
730
259k
    gs_client_color cc;
731
732
259k
    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
259k
    cc.pattern = 0;
743
259k
    ncomps = cs_num_components(pcs);
744
259k
    if (ncomps < 1)
745
218
        return_error(gs_error_syntaxerror);
746
259k
    code = pdfi_get_color_from_stack(ctx, &cc, ncomps);
747
259k
    if (code == 0) {
748
249k
        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
129
            int index = (int)floor(cc.paint.values[0]);
757
758
129
            if(cc.paint.values[0] - index > 0.49999)
759
1
                index++;
760
129
            cc.paint.values[0] = (float)index;
761
129
        }
762
249k
        code = gs_setcolor(ctx->pgs, &cc);
763
249k
    }
764
259k
    return code;
765
259k
}
766
767
static inline bool
768
pattern_instance_uses_base_space(const gs_pattern_instance_t * pinst)
769
280
{
770
280
    return pinst->type->procs.uses_base_space(
771
280
                   pinst->type->procs.get_pattern(pinst) );
772
280
}
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
192k
{
780
192k
    gs_color_space *pcs;
781
192k
    gs_color_space *base_space = NULL;
782
192k
    int ncomps=0, code = 0;
783
192k
    gs_client_color cc;
784
192k
    bool is_pattern = false;
785
786
192k
    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
1
        pdfi_clearstack(ctx);
792
1
        pdfi_log_info(ctx, "pdfi_setcolorN", "colour operator in a CharProc, following a d1 ignored\n");
793
1
        return 0;
794
1
    }
795
796
192k
    if (!is_fill) {
797
23.0k
        gs_swapcolors_quick(ctx->pgs);
798
23.0k
    }
799
192k
    pcs = gs_currentcolorspace(ctx->pgs);
800
801
192k
    if (pdfi_count_stack(ctx) < 1) {
802
2.17k
        code = gs_note_error(gs_error_stackunderflow);
803
2.17k
        goto cleanupExit1;
804
2.17k
    }
805
806
190k
    memset(&cc, 0x00, sizeof(gs_client_color));
807
808
190k
    if (pcs->type == &gs_color_space_type_Pattern)
809
75.1k
        is_pattern = true;
810
190k
    if (is_pattern) {
811
75.1k
        pdf_name *n = NULL;
812
813
75.1k
        if (pdfi_type_of(ctx->stack_top[-1]) != PDF_NAME) {
814
118
            pdfi_clearstack(ctx);
815
118
            code = gs_note_error(gs_error_typecheck);
816
118
            goto cleanupExit0;
817
118
        }
818
75.0k
        n = (pdf_name *)ctx->stack_top[-1];
819
75.0k
        pdfi_countup(n);
820
75.0k
        pdfi_pop(ctx, 1);
821
822
75.0k
        base_space = pcs->base_space;
823
75.0k
        code = pdfi_pattern_set(ctx, stream_dict, page_dict, n, &cc);
824
75.0k
        pdfi_countdown(n);
825
75.0k
        if (code < 0) {
826
            /* Ignore the pattern if we failed to set it */
827
42.0k
            code = pdfi_set_warning_stop(ctx, code, NULL, W_PDF_BADPATTERN, "pdfi_setcolorN", (char *)"PATTERN: Error setting pattern");
828
42.0k
            goto cleanupExit1;
829
42.0k
        }
830
33.0k
        if (base_space && pattern_instance_uses_base_space(cc.pattern))
831
268
            ncomps = cs_num_components(base_space);
832
32.7k
        else
833
32.7k
            ncomps = 0;
834
33.0k
    } else
835
115k
        ncomps = cs_num_components(pcs);
836
837
148k
    if (ncomps > 0) {
838
115k
        code = pdfi_get_color_from_stack(ctx, &cc, ncomps);
839
115k
        if (code < 0)
840
20.8k
            goto cleanupExit1;
841
115k
    }
842
843
127k
    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
127k
    code = gs_setcolor(ctx->pgs, &cc);
869
870
192k
cleanupExit1:
871
192k
    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
192k
        rc_decrement(cc.pattern, "pdfi_setcolorN");
877
878
192k
cleanupExit0:
879
192k
    if (!is_fill)
880
23.0k
        gs_swapcolors_quick(ctx->pgs);
881
192k
    return code;
882
192k
}
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
40.7k
{
891
40.7k
    int                     code, k;
892
40.7k
    gs_color_space *        pcs;
893
40.7k
    cmm_profile_t           *picc_profile = NULL;
894
40.7k
    int                     i, expected = 0;
895
896
40.7k
    static const char *const icc_std_profile_names[] = {
897
40.7k
            GSICC_STANDARD_PROFILES
898
40.7k
        };
899
40.7k
    static const char *const icc_std_profile_keys[] = {
900
40.7k
            GSICC_STANDARD_PROFILES_KEYS
901
40.7k
        };
902
903
40.7k
    if (ppcs!= NULL)
904
40.7k
        *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
40.7k
    code = gs_cspace_build_ICC(&pcs, NULL, (gs_gstate_memory(ctx->pgs))->stable_memory);
911
40.7k
    if (code < 0)
912
0
        return code;
913
914
40.7k
    if (Name != NULL){
915
        /* Compare this to the standard profile names */
916
10.2k
        for (k = 0; k < GSICC_NUMBER_STANDARD_PROFILES; k++) {
917
10.2k
            if ( strcmp( Name, icc_std_profile_keys[k] ) == 0 ) {
918
5.41k
                picc_profile = gsicc_get_profile_handle_file(icc_std_profile_names[k],
919
5.41k
                    strlen(icc_std_profile_names[k]), gs_gstate_memory(ctx->pgs));
920
5.41k
                break;
921
5.41k
            }
922
10.2k
        }
923
35.3k
    } else {
924
35.3k
        if (s == NULL)
925
0
            return_error(gs_error_undefined);
926
927
35.3k
        picc_profile = gsicc_profile_new(s, gs_gstate_memory(ctx->pgs), NULL, 0);
928
35.3k
        if (picc_profile == NULL) {
929
7.65k
            rc_decrement(pcs,"pdfi_create_icc");
930
7.65k
            return gs_throw(gs_error_VMerror, "pdfi_create_icc Creation of ICC profile failed");
931
7.65k
        }
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
27.6k
        picc_profile->profile_handle =
935
27.6k
            gsicc_get_profile_handle_buffer(picc_profile->buffer,
936
27.6k
                                            picc_profile->buffer_size,
937
27.6k
                                            gs_gstate_memory(ctx->pgs));
938
27.6k
    }
939
940
33.0k
    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
4.17k
        rc_decrement(picc_profile,"pdfi_create_icc");
944
4.17k
        rc_decrement(pcs,"pdfi_create_icc");
945
4.17k
        return -1;
946
4.17k
    }
947
28.9k
    code = gsicc_set_gscs_profile(pcs, picc_profile, gs_gstate_memory(ctx->pgs));
948
28.9k
    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
28.9k
    picc_profile->data_cs =
955
28.9k
        gscms_get_profile_data_space(picc_profile->profile_handle,
956
28.9k
            picc_profile->memory);
957
28.9k
    switch (picc_profile->data_cs) {
958
0
        case gsCIEXYZ:
959
0
        case gsCIELAB:
960
17.6k
        case gsRGB:
961
17.6k
            expected = 3;
962
17.6k
            break;
963
10.9k
        case gsGRAY:
964
10.9k
            expected = 1;
965
10.9k
            break;
966
23
        case gsCMYK:
967
23
            expected = 4;
968
23
            break;
969
256
        case gsNCHANNEL:
970
256
        case gsNAMED:            /* Silence warnings */
971
256
        case gsUNDEFINED:        /* Silence warnings */
972
256
            break;
973
28.9k
    }
974
28.9k
    if (expected == 0) {
975
256
        rc_decrement(picc_profile,"pdfi_create_icc");
976
256
        rc_decrement(pcs,"pdfi_create_icc");
977
256
        return_error(gs_error_rangecheck);
978
256
    }
979
    /* Return the number of components the ICC profile has */
980
28.6k
    *icc_N = expected;
981
28.6k
    if (expected != ncomps) {
982
19
        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
19
        ncomps = expected;
985
19
    }
986
987
28.6k
    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
28.6k
    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
28.6k
    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
28.6k
    } else {
1019
92.7k
        for (i = 0; i < ncomps; i++) {
1020
64.0k
            picc_profile->Range.ranges[i].rmin = range_buff[2 * i];
1021
64.0k
            picc_profile->Range.ranges[i].rmax = range_buff[2 * i + 1];
1022
64.0k
        }
1023
28.6k
    }
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
28.6k
    if (gs_currentoverrideicc(ctx->pgs) && picc_profile->data_cs != gsCIELAB) {
1027
        /* Free up the profile structure */
1028
179
        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
179
            case gsGRAY:
1033
179
                pcs->cmm_icc_profile_data = ctx->pgs->icc_manager->default_gray;
1034
179
                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
179
        }
1041
        /* Have one increment from the color space.  Having these tied
1042
           together is not really correct.  Need to fix that.  ToDo.  MJV */
1043
179
        rc_adjust(picc_profile, -2, "pdfi_create_icc");
1044
179
        rc_increment(pcs->cmm_icc_profile_data);
1045
179
    }
1046
    /* Add the color space to the profile cache */
1047
28.6k
    if (dictkey != 0) {
1048
23.0k
        code = gsicc_add_cs(ctx->pgs, pcs, dictkey);
1049
23.0k
        if (code < 0)
1050
0
            goto exit;
1051
23.0k
    }
1052
1053
28.6k
    if (ppcs!= NULL){
1054
28.6k
        *ppcs = pcs;
1055
28.6k
        pdfi_set_colour_callback(pcs, ctx, pdfi_cspace_free_callback);
1056
28.6k
    } else {
1057
0
        code = pdfi_gs_setcolorspace(ctx, pcs);
1058
0
        rc_decrement_only_cs(pcs, "pdfi_create_icc");
1059
0
    }
1060
1061
28.6k
exit:
1062
    /* The context has taken a reference to the colorspace. We no longer need
1063
     * ours, so drop it. */
1064
28.6k
    rc_decrement(picc_profile, "pdfi_create_icc");
1065
28.6k
    return code;
1066
28.6k
}
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
201k
{
1071
201k
    pdf_c_stream *profile_stream = NULL;
1072
201k
    byte *profile_buffer;
1073
201k
    int code, code1;
1074
201k
    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
201k
    if (!gs_currentoverrideicc(ctx->pgs)) {
1083
201k
        if (ICC_obj->object_num != 0) {
1084
201k
            gs_color_space *pcs = NULL;
1085
1086
201k
            pcs = gsicc_find_cs(ICC_obj->object_num, ctx->pgs);
1087
201k
            if (pcs != NULL) {
1088
165k
                if (ppcs!= NULL){
1089
165k
                    *ppcs = pcs;
1090
165k
                } else {
1091
0
                    code = pdfi_gs_setcolorspace(ctx, pcs);
1092
0
                    rc_decrement_only_cs(pcs, "pdfi_create_iccprofile");
1093
0
                }
1094
165k
                *icc_N = gs_color_space_num_components(pcs);
1095
                /* We're passing back a new reference, increment the count */
1096
165k
                rc_adjust_only(pcs, 1, "pdfi_create_iccprofile, return cached ICC profile");
1097
165k
                return 0;
1098
165k
            }
1099
35.5k
            dictkey = ICC_obj->object_num;
1100
35.5k
        }
1101
201k
    }
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
35.7k
    code = pdfi_open_memory_stream_from_filtered_stream(ctx, ICC_obj, &profile_buffer, &profile_stream, true);
1111
35.7k
    if (code < 0) {
1112
376
        return code;
1113
376
    }
1114
1115
    /* Now, finally, we can call the code to create and set the profile */
1116
35.3k
    code = pdfi_create_icc(ctx, cname, profile_stream->s, (int)N, icc_N, range, dictkey, ppcs);
1117
1118
35.3k
    code1 = pdfi_close_memory_stream(ctx, profile_buffer, profile_stream);
1119
1120
35.3k
    if (code == 0)
1121
23.2k
        code = code1;
1122
1123
35.3k
    return code;
1124
35.7k
}
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
218k
{
1401
218k
    pdf_stream *ICC_obj = NULL;
1402
218k
    pdf_dict *dict; /* Alias to avoid tons of casting */
1403
218k
    pdf_array *a;
1404
218k
    int64_t Length, N;
1405
218k
    pdf_obj *Name = NULL, *Alt = NULL;
1406
218k
    char *cname = NULL;
1407
218k
    int code;
1408
218k
    bool known = true;
1409
218k
    float range[8];
1410
218k
    int icc_N;
1411
218k
    gs_color_space *pcs = NULL;
1412
1413
218k
    code = pdfi_array_get_type(ctx, color_array, index + 1, PDF_STREAM, (pdf_obj **)&ICC_obj);
1414
218k
    if (code < 0)
1415
14.4k
        return code;
1416
204k
    code = pdfi_dict_from_obj(ctx, (pdf_obj *)ICC_obj, &dict);
1417
204k
    if (code < 0)
1418
0
        return code;
1419
1420
204k
    Length = pdfi_stream_length(ctx, ICC_obj);
1421
204k
    code = pdfi_dict_get_int(ctx, dict, "N", &N);
1422
204k
    if (code < 0)
1423
1.19k
        goto done;
1424
203k
    if (N != 1 && N != 3 && N != 4) {
1425
1.70k
        code = gs_note_error(gs_error_rangecheck);
1426
1.70k
        goto done;
1427
1.70k
    }
1428
201k
    code = pdfi_dict_knownget(ctx, dict, "Name", &Name);
1429
201k
    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 + (size_t)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
201k
    if (code < 0)
1446
0
        goto done;
1447
1448
201k
    code = pdfi_dict_knownget_type(ctx, dict, "Range", PDF_ARRAY, (pdf_obj **)&a);
1449
201k
    if (code < 0)
1450
0
        goto done;
1451
201k
    if (code > 0) {
1452
159
        double dbl;
1453
159
        int i;
1454
1455
159
        if (pdfi_array_size(a) >= N * 2) {
1456
1.06k
            for (i = 0; i < N * 2;i++) {
1457
922
                code = pdfi_array_get_number(ctx, a, i, &dbl);
1458
922
                if (code < 0) {
1459
0
                    known = false;
1460
0
                    break;
1461
0
                }
1462
922
                range[i] = (float)dbl;
1463
922
            }
1464
146
        } else {
1465
13
            known = false;
1466
13
        }
1467
159
        pdfi_countdown(a);
1468
159
    } else
1469
201k
        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
201k
    if (!known) {
1477
201k
        int i;
1478
741k
        for (i = 0;i < N; i++) {
1479
539k
            range[i * 2] = 0;
1480
539k
            range[(i * 2) + 1] = 1;
1481
539k
        }
1482
201k
    }
1483
1484
201k
    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
201k
    if (code >= 0 && N != icc_N) {
1502
26
        gs_client_color cc;
1503
26
        int i;
1504
1505
26
        gs_gsave(ctx->pgs);
1506
26
        code = gs_setcolorspace(ctx->pgs, pcs);
1507
26
        if (code == 0) {
1508
26
            cc.pattern = 0;
1509
104
            for (i = 0;i < icc_N; i++)
1510
78
                cc.paint.values[i] = 0;
1511
26
            code = gs_setcolor(ctx->pgs, &cc);
1512
26
            if (code == 0)
1513
26
                code = gx_set_dev_color(ctx->pgs);
1514
26
        }
1515
26
        gs_grestore(ctx->pgs);
1516
26
    }
1517
1518
201k
    if (code < 0) {
1519
12.4k
        pdf_obj *Alternate = NULL;
1520
1521
12.4k
        if (pcs != NULL)
1522
12.4k
            rc_decrement(pcs,"pdfi_create_iccbased");
1523
1524
        /* Failed to set the ICCBased space, attempt to use the Alternate */
1525
12.4k
        code = pdfi_dict_knownget(ctx, dict, "Alternate", &Alternate);
1526
12.4k
        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
11.9k
            if (pdfi_type_of(Alternate) == PDF_NAME)
1529
11.9k
                code = pdfi_create_colorspace_by_name(ctx, (pdf_name *)Alternate, stream_dict,
1530
11.9k
                                                      page_dict, ppcs, inline_image);
1531
11.9k
            pdfi_countdown(Alternate);
1532
11.9k
            if (code == 0) {
1533
11.7k
                pdfi_set_warning(ctx, 0, NULL, W_PDF_BADICC_USE_ALT, "pdfi_create_iccbased", NULL);
1534
11.7k
                goto done;
1535
11.7k
            }
1536
11.9k
        }
1537
        /* Use the number of components *from the profile* to set a space.... */
1538
688
        pdfi_set_warning(ctx, 0, NULL, W_PDF_BADICC_USECOMPS, "pdfi_create_iccbased", NULL);
1539
688
        switch(N) {
1540
153
            case 1:
1541
153
                pcs = gs_cspace_new_DeviceGray(ctx->memory);
1542
153
                if (pcs == NULL)
1543
0
                    code = gs_note_error(gs_error_VMerror);
1544
153
                break;
1545
526
            case 3:
1546
526
                pcs = gs_cspace_new_DeviceRGB(ctx->memory);
1547
526
                if (pcs == NULL)
1548
0
                    code = gs_note_error(gs_error_VMerror);
1549
526
                break;
1550
9
            case 4:
1551
9
                pcs = gs_cspace_new_DeviceCMYK(ctx->memory);
1552
9
                if (pcs == NULL)
1553
0
                    code = gs_note_error(gs_error_VMerror);
1554
9
                break;
1555
0
            default:
1556
0
                code = gs_note_error(gs_error_undefined);
1557
0
                break;
1558
688
        }
1559
189k
    } else {
1560
189k
        if (pcs->ICC_Alternate_space == gs_ICC_Alternate_None) {
1561
25.2k
            code = pdfi_dict_knownget(ctx, dict, "Alternate", (pdf_obj **)&Alt);
1562
25.2k
            if (code >= 0) {
1563
25.2k
                switch(pdfi_type_of(Alt)) {
1564
21.6k
                    case PDF_NAME:
1565
                        /* Simple named spaces must be Gray, RGB or CMYK, we ignore /Indexed */
1566
21.6k
                        if (pdfi_name_is((const pdf_name *)Alt, "DeviceGray"))
1567
5.90k
                            pcs->ICC_Alternate_space = gs_ICC_Alternate_DeviceGray;
1568
15.7k
                        else if (pdfi_name_is((const pdf_name *)Alt, "DeviceRGB"))
1569
15.6k
                            pcs->ICC_Alternate_space = gs_ICC_Alternate_DeviceRGB;
1570
169
                        else if (pdfi_name_is((const pdf_name *)Alt, "DeviceCMYK"))
1571
23
                            pcs->ICC_Alternate_space = gs_ICC_Alternate_DeviceCMYK;
1572
21.6k
                        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
3.55k
                    default:
1610
                        /* Probably an error, but just ignore it */
1611
3.55k
                        break;
1612
25.2k
                }
1613
25.2k
                pdfi_countdown(Alt);
1614
25.2k
                Alt = NULL;
1615
25.2k
            }
1616
25.2k
        }
1617
189k
    }
1618
1619
189k
    if (ppcs!= NULL) {
1620
50.5k
        *ppcs = pcs;
1621
50.5k
        if (pcs != NULL)
1622
50.5k
            pdfi_set_colour_callback(pcs, ctx, pdfi_cspace_free_callback);
1623
50.5k
    }
1624
139k
    else {
1625
139k
        if (pcs != NULL) {
1626
139k
            code = pdfi_gs_setcolorspace(ctx, pcs);
1627
            /* release reference from construction */
1628
139k
            rc_decrement_only_cs(pcs, "setseparationspace");
1629
139k
        }
1630
139k
    }
1631
1632
1633
204k
done:
1634
204k
    if (cname)
1635
0
        gs_free_object(ctx->memory, cname, "pdfi_create_iccbased (profile name)");
1636
204k
    pdfi_countdown(Alt);
1637
204k
    pdfi_countdown(Name);
1638
204k
    pdfi_countdown(ICC_obj);
1639
204k
    return code;
1640
189k
}
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
1.31k
{
1650
1.31k
    int                     code;
1651
1.31k
    gs_color_space *        pcs;
1652
1.31k
    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
1.31k
    code = gs_cspace_build_ICC(&pcs, NULL, (gs_gstate_memory(ctx->pgs))->stable_memory);
1660
1.31k
    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
1.31k
    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
1.31k
    code = gsicc_set_gscs_profile(pcs, ctx->pgs->icc_manager->lab_profile, gs_gstate_memory(ctx->pgs));
1674
1.31k
    if (code < 0)
1675
0
        return code;
1676
1677
1.31k
    pcs->cmm_icc_profile_data->Range.ranges[0].rmin = 0.0;
1678
1.31k
    pcs->cmm_icc_profile_data->Range.ranges[0].rmax = 100.0;
1679
3.95k
    for (i = 1; i < 3; i++) {
1680
2.63k
        pcs->cmm_icc_profile_data->Range.ranges[i].rmin =
1681
2.63k
            range_buff[2 * (i-1)];
1682
2.63k
        pcs->cmm_icc_profile_data->Range.ranges[i].rmax =
1683
2.63k
            range_buff[2 * (i-1) + 1];
1684
2.63k
    }
1685
1.31k
    if (ppcs!= NULL){
1686
245
        *ppcs = pcs;
1687
245
        pdfi_set_colour_callback(pcs, ctx, pdfi_cspace_free_callback);
1688
1.07k
    } else {
1689
1.07k
        code = pdfi_gs_setcolorspace(ctx, pcs);
1690
1.07k
        rc_decrement_only_cs(pcs, "pdfi_seticc_lab");
1691
1.07k
    }
1692
1693
1.31k
    return code;
1694
1.31k
}
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
1.34k
{
1698
1.34k
    int code = 0, i;
1699
1.34k
    pdf_dict *Lab_dict = NULL;
1700
1.34k
    pdf_array *Range = NULL;
1701
1.34k
    float RangeBuf[4];
1702
1.34k
    double f;
1703
1.34k
    bool known = false;
1704
1705
1.34k
    code = pdfi_array_get_type(ctx, color_array, index + 1, PDF_DICT, (pdf_obj **)&Lab_dict);
1706
1.34k
    if (code < 0)
1707
18
        return code;
1708
1709
1.32k
    code = pdfi_dict_known(ctx, Lab_dict, "Range", &known);
1710
1.32k
    if (code < 0)
1711
0
        goto exit;
1712
1.32k
    if (known) {
1713
1.30k
        code = pdfi_dict_get_type(ctx, Lab_dict, "Range", PDF_ARRAY, (pdf_obj **)&Range);
1714
1.30k
        if (code < 0) {
1715
0
            goto exit;
1716
0
        }
1717
1.30k
        if (pdfi_array_size(Range) != 4){
1718
8
            code = gs_note_error(gs_error_rangecheck);
1719
8
            goto exit;
1720
8
        }
1721
1722
6.48k
        for (i=0; i < 4; i++) {
1723
5.19k
            code = pdfi_array_get_number(ctx, Range, (uint64_t)i, &f);
1724
5.19k
            if (code < 0)
1725
1
                goto exit;
1726
5.19k
            RangeBuf[i] = (float)f;
1727
5.19k
        }
1728
1.29k
    } else {
1729
21
        RangeBuf[0] = RangeBuf[2] = -100.0;
1730
21
        RangeBuf[1] = RangeBuf[3] = 100.0;
1731
21
    }
1732
1733
1.31k
    code = pdfi_seticc_lab(ctx, RangeBuf, ppcs);
1734
1735
1.32k
exit:
1736
1.32k
    pdfi_countdown(Lab_dict);
1737
1.32k
    pdfi_countdown(Range);
1738
1.32k
    return code;
1739
1.31k
}
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
3.28k
{
1746
3.28k
    int                     code = 0;
1747
3.28k
    gs_color_space *        pcs;
1748
3.28k
    int                     i;
1749
3.28k
    cmm_profile_t           *cal_profile;
1750
1751
    /* See if the color space is in the profile cache */
1752
3.28k
    pcs = gsicc_find_cs(dictkey, ctx->pgs);
1753
3.28k
    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
3.26k
        code = gs_cspace_build_ICC(&pcs, NULL, ctx->pgs->memory->stable_memory);
1759
3.26k
        if (code < 0)
1760
0
            return code;
1761
        /* There is no alternate for this.  Perhaps we should set DeviceRGB? */
1762
3.26k
        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
3.26k
        cal_profile = gsicc_create_from_cal(white, black, gamma, matrix,
1766
3.26k
                                            ctx->pgs->memory->stable_memory, num_colorants);
1767
3.26k
        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
3.26k
        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
3.26k
        rc_decrement(cal_profile, "seticc_cal");
1780
3.26k
        if (code < 0) {
1781
0
            rc_decrement(pcs, "seticc_cal");
1782
0
            return code;
1783
0
        }
1784
12.6k
        for (i = 0; i < num_colorants; i++) {
1785
9.40k
            pcs->cmm_icc_profile_data->Range.ranges[i].rmin = 0;
1786
9.40k
            pcs->cmm_icc_profile_data->Range.ranges[i].rmax = 1;
1787
9.40k
        }
1788
        /* Add the color space to the profile cache */
1789
3.26k
        gsicc_add_cs(ctx->pgs, pcs, dictkey);
1790
3.26k
    } else {
1791
        /* We're passing back a new reference, increment the count */
1792
27
        rc_adjust_only(pcs, 1, "pdfi_seticc_cal, return cached ICC profile");
1793
27
    }
1794
1795
3.28k
    if (ppcs!= NULL){
1796
280
        *ppcs = pcs;
1797
280
        pdfi_set_colour_callback(pcs, ctx, pdfi_cspace_free_callback);
1798
3.00k
    } else {
1799
3.00k
        code = pdfi_gs_setcolorspace(ctx, pcs);
1800
3.00k
        rc_decrement_only_cs(pcs, "pdfi_seticc_cal");
1801
3.00k
    }
1802
1803
3.28k
    return code;
1804
3.28k
}
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
608
{
1808
608
    int code = 0, i;
1809
608
    pdf_dict *CalGray_dict = NULL;
1810
608
    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
608
    float WhitePoint[3], BlackPoint[3] = {0.0f, 0.0f, 0.0f}, Gamma = 1.0f;
1817
608
    float Matrix[9] = {1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f};
1818
608
    double f;
1819
1820
608
    code = pdfi_array_get_type(ctx, color_array, index + 1, PDF_DICT, (pdf_obj **)&CalGray_dict);
1821
608
    if (code < 0)
1822
149
        return code;
1823
1824
459
    code = pdfi_dict_get_type(ctx, CalGray_dict, "WhitePoint", PDF_ARRAY, (pdf_obj **)&PDFArray);
1825
459
    if (code < 0) {
1826
0
        pdfi_countdown(PDFArray);
1827
0
        goto exit;
1828
0
    }
1829
459
    if (pdfi_array_size(PDFArray) != 3){
1830
0
        code = gs_note_error(gs_error_rangecheck);
1831
0
        goto exit;
1832
0
    }
1833
1834
1.83k
    for (i=0; i < 3; i++) {
1835
1.37k
        code = pdfi_array_get_number(ctx, PDFArray, (uint64_t)i, &f);
1836
1.37k
        if (code < 0)
1837
0
            goto exit;
1838
1.37k
        WhitePoint[i] = (float)f;
1839
1.37k
    }
1840
459
    pdfi_countdown(PDFArray);
1841
459
    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
459
    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
459
    if (pdfi_dict_knownget_type(ctx, CalGray_dict, "BlackPoint", PDF_ARRAY, (pdf_obj **)&PDFArray) > 0) {
1852
405
        if (pdfi_array_size(PDFArray) != 3){
1853
100
            code = gs_note_error(gs_error_rangecheck);
1854
100
            goto exit;
1855
100
        }
1856
1.06k
        for (i=0; i < 3; i++) {
1857
915
            code = pdfi_array_get_number(ctx, PDFArray, (uint64_t)i, &f);
1858
915
            if (code < 0)
1859
160
                goto exit;
1860
            /* The PDF 1.7 reference states that all three components of the BlackPoint
1861
             * (if present) must be positive.
1862
             */
1863
755
            if (f < 0) {
1864
0
                code = gs_note_error(gs_error_rangecheck);
1865
0
                goto exit;
1866
0
            }
1867
755
            BlackPoint[i] = (float)f;
1868
755
        }
1869
145
        pdfi_countdown(PDFArray);
1870
145
        PDFArray = NULL;
1871
145
    }
1872
1873
199
    if (pdfi_dict_knownget_number(ctx, CalGray_dict, "Gamma", &f) > 0)
1874
199
        Gamma = (float)f;
1875
    /* The PDF 1.7 reference states that Gamma
1876
     * (if present) must be positive.
1877
     */
1878
199
    if (Gamma < 0) {
1879
0
        code = gs_note_error(gs_error_rangecheck);
1880
0
        goto exit;
1881
0
    }
1882
1883
199
    code = pdfi_seticc_cal(ctx, WhitePoint, BlackPoint, &Gamma, Matrix, 1, color_array->object_num, ppcs);
1884
1885
459
exit:
1886
459
    pdfi_countdown(PDFArray);
1887
459
    pdfi_countdown(CalGray_dict);
1888
459
    return code;
1889
199
}
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
3.21k
{
1893
3.21k
    int code = 0, i;
1894
3.21k
    pdf_dict *CalRGB_dict = NULL;
1895
3.21k
    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
3.21k
    float WhitePoint[3], BlackPoint[3] = {0.0f, 0.0f, 0.0f}, Gamma[3] = {1.0f, 1.0f, 1.0f};
1900
3.21k
    float Matrix[9] = {1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f};
1901
3.21k
    double f;
1902
1903
3.21k
    code = pdfi_array_get_type(ctx, color_array, index + 1, PDF_DICT, (pdf_obj **)&CalRGB_dict);
1904
3.21k
    if (code < 0)
1905
34
        return code;
1906
1907
3.18k
    code = pdfi_dict_get_type(ctx, CalRGB_dict, "WhitePoint", PDF_ARRAY, (pdf_obj **)&PDFArray);
1908
3.18k
    if (code < 0) {
1909
5
        pdfi_countdown(PDFArray);
1910
5
        goto exit;
1911
5
    }
1912
3.17k
    if (pdfi_array_size(PDFArray) != 3){
1913
1
        code = gs_note_error(gs_error_rangecheck);
1914
1
        goto exit;
1915
1
    }
1916
1917
12.7k
    for (i=0; i < 3; i++) {
1918
9.53k
        code = pdfi_array_get_number(ctx, PDFArray, (uint64_t)i, &f);
1919
9.53k
        if (code < 0)
1920
0
            goto exit;
1921
9.53k
        WhitePoint[i] = (float)f;
1922
9.53k
    }
1923
3.17k
    pdfi_countdown(PDFArray);
1924
3.17k
    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
3.17k
    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
3.17k
    if (pdfi_dict_knownget_type(ctx, CalRGB_dict, "BlackPoint", PDF_ARRAY, (pdf_obj **)&PDFArray) > 0) {
1935
1.04k
        if (pdfi_array_size(PDFArray) != 3){
1936
0
            code = gs_note_error(gs_error_rangecheck);
1937
0
            goto exit;
1938
0
        }
1939
4.02k
        for (i=0; i < 3; i++) {
1940
3.06k
            code = pdfi_array_get_number(ctx, PDFArray, (uint64_t)i, &f);
1941
3.06k
            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
3.06k
            if (f < 0) {
1947
80
                code = gs_note_error(gs_error_rangecheck);
1948
80
                goto exit;
1949
80
            }
1950
2.98k
            BlackPoint[i] = (float)f;
1951
2.98k
        }
1952
967
        pdfi_countdown(PDFArray);
1953
967
        PDFArray = NULL;
1954
967
    }
1955
1956
3.09k
    if (pdfi_dict_knownget_type(ctx, CalRGB_dict, "Gamma", PDF_ARRAY, (pdf_obj **)&PDFArray) > 0) {
1957
3.09k
        if (pdfi_array_size(PDFArray) != 3){
1958
0
            code = gs_note_error(gs_error_rangecheck);
1959
0
            goto exit;
1960
0
        }
1961
12.3k
        for (i=0; i < 3; i++) {
1962
9.28k
            code = pdfi_array_get_number(ctx, PDFArray, (uint64_t)i, &f);
1963
9.28k
            if (code < 0)
1964
0
                goto exit;
1965
9.28k
            Gamma[i] = (float)f;
1966
9.28k
        }
1967
3.09k
        pdfi_countdown(PDFArray);
1968
3.09k
        PDFArray = NULL;
1969
3.09k
    }
1970
1971
3.09k
    if (pdfi_dict_knownget_type(ctx, CalRGB_dict, "Matrix", PDF_ARRAY, (pdf_obj **)&PDFArray) > 0) {
1972
3.09k
        if (pdfi_array_size(PDFArray) != 9){
1973
5
            code = gs_note_error(gs_error_rangecheck);
1974
5
            goto exit;
1975
5
        }
1976
30.9k
        for (i=0; i < 9; i++) {
1977
27.8k
            code = pdfi_array_get_number(ctx, PDFArray, (uint64_t)i, &f);
1978
27.8k
            if (code < 0)
1979
3
                goto exit;
1980
27.8k
            Matrix[i] = (float)f;
1981
27.8k
        }
1982
3.09k
        pdfi_countdown(PDFArray);
1983
3.09k
        PDFArray = NULL;
1984
3.09k
    }
1985
3.09k
    code = pdfi_seticc_cal(ctx, WhitePoint, BlackPoint, Gamma, Matrix, 3, color_array->object_num, ppcs);
1986
1987
3.18k
exit:
1988
3.18k
    pdfi_countdown(PDFArray);
1989
3.18k
    pdfi_countdown(CalRGB_dict);
1990
3.18k
    return code;
1991
3.09k
}
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
66.1k
{
1995
66.1k
    pdf_obj *o = NULL;
1996
66.1k
    pdf_name *name = NULL, *NamedAlternate = NULL;
1997
66.1k
    pdf_array *ArrayAlternate = NULL;
1998
66.1k
    pdf_obj *transform = NULL;
1999
66.1k
    int code;
2000
66.1k
    gs_color_space *pcs = NULL, *pcs_alt = NULL;
2001
66.1k
    gs_function_t * pfn = NULL;
2002
66.1k
    separation_type sep_type;
2003
2004
66.1k
    code = pdfi_array_get_type(ctx, color_array, index + 1, PDF_NAME, (pdf_obj **)&name);
2005
66.1k
    if (code < 0)
2006
0
        goto pdfi_separation_error;
2007
2008
66.1k
    sep_type = SEP_OTHER;
2009
66.1k
    if (name->length == 4 && memcmp(name->data, "None", 4) == 0)
2010
0
        sep_type = SEP_NONE;
2011
66.1k
    if (name->length == 3 && memcmp(name->data, "All", 3) == 0)
2012
0
        sep_type = SEP_ALL;
2013
2014
66.1k
    code = pdfi_array_get(ctx, color_array, index + 2, &o);
2015
66.1k
    if (code < 0)
2016
232
        goto pdfi_separation_error;
2017
2018
65.9k
    switch (pdfi_type_of(o)) {
2019
49.4k
        case PDF_NAME:
2020
49.4k
            NamedAlternate = (pdf_name *)o;
2021
49.4k
            code = pdfi_create_colorspace_by_name(ctx, NamedAlternate, stream_dict, page_dict, &pcs_alt, inline_image);
2022
49.4k
            if (code < 0)
2023
122
                goto pdfi_separation_error;
2024
49.3k
            break;
2025
49.3k
        case PDF_ARRAY:
2026
15.3k
            ArrayAlternate = (pdf_array *)o;
2027
15.3k
            code = pdfi_create_colorspace_by_array(ctx, ArrayAlternate, 0, stream_dict, page_dict, &pcs_alt, inline_image);
2028
15.3k
            if (code < 0)
2029
1.37k
                goto pdfi_separation_error;
2030
13.9k
            break;
2031
13.9k
        default:
2032
1.12k
            pdfi_countdown(o);
2033
1.12k
            code = gs_error_typecheck;
2034
1.12k
            goto pdfi_separation_error;
2035
65.9k
    }
2036
2037
63.3k
    code = pdfi_array_get(ctx, color_array, index + 3, &transform);
2038
63.3k
    if (code < 0)
2039
1.09k
        goto pdfi_separation_error;
2040
2041
62.2k
    code = pdfi_build_function(ctx, &pfn, NULL, 1, transform, page_dict);
2042
62.2k
    if (code < 0)
2043
6.03k
        goto pdfi_separation_error;
2044
2045
56.2k
    if (pfn->params.m != 1 || pfn->params.n != cs_num_components(pcs_alt)) {
2046
25
        code = gs_note_error(gs_error_rangecheck);
2047
25
        goto pdfi_separation_error;
2048
25
    }
2049
2050
56.1k
    code = gs_cspace_new_Separation(&pcs, pcs_alt, ctx->memory);
2051
56.1k
    if (code < 0)
2052
0
        goto pdfi_separation_error;
2053
2054
56.1k
    rc_decrement(pcs_alt, "pdfi_create_Separation");
2055
56.1k
    pcs_alt = NULL;
2056
56.1k
    pcs->params.separation.mem = ctx->memory;
2057
56.1k
    pcs->params.separation.sep_type = sep_type;
2058
56.1k
    pcs->params.separation.sep_name = (char *)gs_alloc_bytes(ctx->memory->non_gc_memory, (size_t)name->length + 1, "pdfi_setseparationspace(ink)");
2059
56.1k
    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
56.1k
    memcpy(pcs->params.separation.sep_name, name->data, name->length);
2064
56.1k
    pcs->params.separation.sep_name[name->length] = 0x00;
2065
2066
56.1k
    code = gs_cspace_set_sepr_function(pcs, pfn);
2067
56.1k
    if (code < 0)
2068
0
        goto pdfi_separation_error;
2069
2070
56.1k
    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
245
        code = pdfi_gs_setcolorspace(ctx, pcs);
2077
245
        *ppcs = pcs;
2078
245
        pdfi_set_colour_callback(pcs, ctx, pdfi_cspace_free_callback);
2079
55.9k
    } else {
2080
55.9k
        code = pdfi_gs_setcolorspace(ctx, pcs);
2081
        /* release reference from construction */
2082
55.9k
        rc_decrement_only_cs(pcs, "setseparationspace");
2083
55.9k
    }
2084
2085
56.1k
    pdfi_countdown(name);
2086
56.1k
    pdfi_countdown(NamedAlternate);
2087
56.1k
    pdfi_countdown(ArrayAlternate);
2088
56.1k
    pdfi_countdown(transform);
2089
56.1k
    return_error(0);
2090
2091
10.0k
pdfi_separation_error:
2092
10.0k
    pdfi_free_function(ctx, pfn);
2093
10.0k
    if (pcs_alt != NULL)
2094
7.15k
        rc_decrement_only_cs(pcs_alt, "setseparationspace");
2095
10.0k
    if(pcs != NULL)
2096
0
        rc_decrement_only_cs(pcs, "setseparationspace");
2097
10.0k
    pdfi_countdown(name);
2098
10.0k
    pdfi_countdown(NamedAlternate);
2099
10.0k
    pdfi_countdown(ArrayAlternate);
2100
10.0k
    pdfi_countdown(transform);
2101
10.0k
    return code;
2102
56.1k
}
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
24.9k
{
2106
24.9k
    pdf_obj *o = NULL;
2107
24.9k
    pdf_name *NamedAlternate = NULL;
2108
24.9k
    pdf_array *ArrayAlternate = NULL, *inks = NULL;
2109
24.9k
    pdf_obj *transform = NULL;
2110
24.9k
    pdf_dict *attributes = NULL;
2111
24.9k
    pdf_dict *Colorants = NULL, *Process = NULL;
2112
24.9k
    gs_color_space *process_space = NULL;
2113
24.9k
    int code;
2114
24.9k
    uint64_t ix;
2115
24.9k
    gs_color_space *pcs = NULL, *pcs_alt = NULL;
2116
24.9k
    gs_function_t * pfn = NULL;
2117
2118
    /* Start with the array of inks */
2119
24.9k
    code = pdfi_array_get_type(ctx, color_array, index + 1, PDF_ARRAY, (pdf_obj **)&inks);
2120
24.9k
    if (code < 0)
2121
8
        goto pdfi_devicen_error;
2122
2123
24.9k
    if (pdfi_array_size(inks) > GS_CLIENT_COLOR_MAX_COMPONENTS)
2124
0
            return_error(gs_error_limitcheck);
2125
2126
59.3k
    for (ix = 0;ix < pdfi_array_size(inks);ix++) {
2127
34.3k
        pdf_name *ink_name = NULL;
2128
2129
34.3k
        code = pdfi_array_get_type(ctx, inks, ix, PDF_NAME, (pdf_obj **)&ink_name);
2130
34.3k
        if (code < 0)
2131
4
            return code;
2132
2133
34.3k
        if (ink_name->length == 3 && memcmp(ink_name->data, "All", 3) == 0) {
2134
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)
2135
0
                return code;
2136
0
        }
2137
34.3k
        pdfi_countdown(ink_name);
2138
34.3k
        ink_name = NULL;
2139
34.3k
    }
2140
2141
    /* Sigh, Acrobat allows this, even though its contra the spec. Convert to
2142
     * a /Separation space, and then return. Actually Acrobat does not always permit this, see
2143
     * tests_private/comparefiles/Testform.v1.0.2.pdf.
2144
     */
2145
24.9k
    if (pdfi_array_size(inks) == 1) {
2146
20.2k
        pdf_name *ink_name = NULL;
2147
20.2k
        pdf_array *sep_color_array = NULL;
2148
20.2k
        pdf_obj *obj = NULL;
2149
2150
20.2k
        code = pdfi_array_get_type(ctx, inks, 0, PDF_NAME, (pdf_obj **)&ink_name);
2151
20.2k
        if (code < 0)
2152
0
            goto pdfi_devicen_error;
2153
2154
20.2k
        if (ink_name->length == 3 && memcmp(ink_name->data, "All", 3) == 0) {
2155
0
            code = pdfi_array_alloc(ctx, 4, &sep_color_array);
2156
0
            if (code < 0)
2157
0
                goto all_error;
2158
0
            pdfi_countup(sep_color_array);
2159
0
            code = pdfi_name_alloc(ctx, (byte *)"Separation", 10, &obj);
2160
0
            if (code < 0)
2161
0
                goto all_error;
2162
0
            pdfi_countup(obj);
2163
0
            code = pdfi_array_put(ctx, sep_color_array, 0, obj);
2164
0
            if (code < 0)
2165
0
                goto all_error;
2166
0
            pdfi_countdown(obj);
2167
0
            obj = NULL;
2168
0
            code = pdfi_array_put(ctx, sep_color_array, 1, (pdf_obj *)ink_name);
2169
0
            if (code < 0)
2170
0
                goto all_error;
2171
0
            code = pdfi_array_get(ctx, color_array, index + 2, &obj);
2172
0
            if (code < 0)
2173
0
                goto all_error;
2174
0
            code = pdfi_array_put(ctx, sep_color_array, 2, obj);
2175
0
            if (code < 0)
2176
0
                goto all_error;
2177
0
            pdfi_countdown(obj);
2178
0
            obj = NULL;
2179
0
            code = pdfi_array_get(ctx, color_array, index + 3, &obj);
2180
0
            if (code < 0)
2181
0
                goto all_error;
2182
0
            code = pdfi_array_put(ctx, sep_color_array, 3, obj);
2183
0
            if (code < 0)
2184
0
                goto all_error;
2185
0
            pdfi_countdown(obj);
2186
0
            obj = NULL;
2187
2188
0
            code = pdfi_create_Separation(ctx, sep_color_array, 0, stream_dict, page_dict, ppcs, inline_image);
2189
0
            if (code < 0)
2190
0
                goto all_error;
2191
0
all_error:
2192
0
            pdfi_countdown(ink_name);
2193
0
            pdfi_countdown(sep_color_array);
2194
0
            pdfi_countdown(obj);
2195
0
            pdfi_countdown(inks);
2196
0
            return code;
2197
0
        } else
2198
20.2k
            pdfi_countdown(ink_name);
2199
20.2k
    }
2200
2201
    /* Deal with alternate space */
2202
24.9k
    code = pdfi_array_get(ctx, color_array, index + 2, &o);
2203
24.9k
    if (code < 0)
2204
97
        goto pdfi_devicen_error;
2205
2206
24.8k
    switch (pdfi_type_of(o)) {
2207
23.5k
        case PDF_NAME:
2208
23.5k
            NamedAlternate = (pdf_name *)o;
2209
23.5k
            code = pdfi_create_colorspace_by_name(ctx, NamedAlternate, stream_dict, page_dict, &pcs_alt, inline_image);
2210
23.5k
            if (code < 0)
2211
0
                goto pdfi_devicen_error;
2212
23.5k
            break;
2213
23.5k
        case PDF_ARRAY:
2214
1.28k
            ArrayAlternate = (pdf_array *)o;
2215
1.28k
            code = pdfi_create_colorspace_by_array(ctx, ArrayAlternate, 0, stream_dict, page_dict, &pcs_alt, inline_image);
2216
1.28k
            if (code < 0)
2217
                /* OSS-fuzz error 42973; we don't need to count down 'o' here because
2218
                 * we have assigned it to ArrayAlternate and both the success and error
2219
                 * paths count down ArrayAlternate.
2220
                 */
2221
152
                goto pdfi_devicen_error;
2222
1.13k
            break;
2223
1.13k
        default:
2224
9
            code = gs_error_typecheck;
2225
9
            pdfi_countdown(o);
2226
9
            goto pdfi_devicen_error;
2227
24.8k
    }
2228
2229
    /* Now the tint transform */
2230
24.6k
    code = pdfi_array_get(ctx, color_array, index + 3, &transform);
2231
24.6k
    if (code < 0)
2232
1.89k
        goto pdfi_devicen_error;
2233
2234
22.7k
    code = pdfi_build_function(ctx, &pfn, NULL, 1, transform, page_dict);
2235
22.7k
    if (code < 0)
2236
663
        goto pdfi_devicen_error;
2237
2238
22.1k
    if (pfn->params.m != pdfi_array_size(inks) || pfn->params.n != cs_num_components(pcs_alt)) {
2239
42
        code = gs_note_error(gs_error_rangecheck);
2240
42
        goto pdfi_devicen_error;
2241
42
    }
2242
2243
22.0k
    code = gs_cspace_new_DeviceN(&pcs, pdfi_array_size(inks), pcs_alt, ctx->memory);
2244
22.0k
    if (code < 0)
2245
0
        return code;
2246
2247
22.0k
    rc_decrement(pcs_alt, "pdfi_create_DeviceN");
2248
22.0k
    pcs_alt = NULL;
2249
22.0k
    pcs->params.device_n.mem = ctx->memory;
2250
2251
50.8k
    for (ix = 0;ix < pdfi_array_size(inks);ix++) {
2252
28.7k
        pdf_name *ink_name;
2253
2254
28.7k
        ink_name = NULL;
2255
28.7k
        code = pdfi_array_get_type(ctx, inks, ix, PDF_NAME, (pdf_obj **)&ink_name);
2256
28.7k
        if (code < 0)
2257
0
            goto pdfi_devicen_error;
2258
2259
28.7k
        pcs->params.device_n.names[ix] = (char *)gs_alloc_bytes(ctx->memory->non_gc_memory, (size_t)ink_name->length + 1, "pdfi_setdevicenspace(ink)");
2260
28.7k
        if (pcs->params.device_n.names[ix] == NULL) {
2261
0
            code = gs_note_error(gs_error_VMerror);
2262
0
            goto pdfi_devicen_error;
2263
0
        }
2264
28.7k
        memcpy(pcs->params.device_n.names[ix], ink_name->data, ink_name->length);
2265
28.7k
        pcs->params.device_n.names[ix][ink_name->length] = 0x00;
2266
28.7k
        pdfi_countdown(ink_name);
2267
28.7k
    }
2268
2269
22.0k
    code = gs_cspace_set_devn_function(pcs, pfn);
2270
22.0k
    if (code < 0)
2271
0
        goto pdfi_devicen_error;
2272
2273
22.0k
    if (pdfi_array_size(color_array) >= index + 5) {
2274
21.1k
        pdf_obj *ColorSpace = NULL;
2275
21.1k
        pdf_array *Components = NULL;
2276
21.1k
        pdf_obj *subtype = NULL;
2277
2278
21.1k
        code = pdfi_array_get_type(ctx, color_array, index + 4, PDF_DICT, (pdf_obj **)&attributes);
2279
21.1k
        if (code < 0)
2280
0
            goto pdfi_devicen_error;
2281
2282
21.1k
        code = pdfi_dict_knownget(ctx, attributes, "Subtype", (pdf_obj **)&subtype);
2283
21.1k
        if (code < 0)
2284
0
            goto pdfi_devicen_error;
2285
2286
21.1k
        if (code == 0) {
2287
37
            pcs->params.device_n.subtype = gs_devicen_DeviceN;
2288
21.1k
        } else {
2289
21.1k
            switch (pdfi_type_of(subtype)) {
2290
21.1k
                case PDF_NAME:
2291
21.1k
                case PDF_STRING:
2292
21.1k
                    if (memcmp(((pdf_name *)subtype)->data, "DeviceN", 7) == 0) {
2293
92
                        pcs->params.device_n.subtype = gs_devicen_DeviceN;
2294
21.0k
                    } else {
2295
21.0k
                        if (memcmp(((pdf_name *)subtype)->data, "NChannel", 8) == 0) {
2296
21.0k
                            pcs->params.device_n.subtype = gs_devicen_NChannel;
2297
21.0k
                        } else {
2298
0
                            pdfi_countdown(subtype);
2299
0
                            goto pdfi_devicen_error;
2300
0
                        }
2301
21.0k
                    }
2302
21.1k
                    pdfi_countdown(subtype);
2303
21.1k
                    break;
2304
0
                default:
2305
0
                    pdfi_countdown(subtype);
2306
0
                    goto pdfi_devicen_error;
2307
21.1k
            }
2308
21.1k
        }
2309
2310
21.1k
        code = pdfi_dict_knownget_type(ctx, attributes, "Process", PDF_DICT, (pdf_obj **)&Process);
2311
21.1k
        if (code < 0)
2312
6
            goto pdfi_devicen_error;
2313
2314
21.1k
        if (Process != NULL && pdfi_dict_entries(Process) != 0) {
2315
21.0k
            int ix = 0;
2316
21.0k
            pdf_obj *name;
2317
2318
21.0k
            code = pdfi_dict_get(ctx, Process, "ColorSpace", (pdf_obj **)&ColorSpace);
2319
21.0k
            if (code < 0)
2320
0
                goto pdfi_devicen_error;
2321
2322
21.0k
            code = pdfi_create_colorspace(ctx, ColorSpace, stream_dict, page_dict, &process_space, inline_image);
2323
21.0k
            pdfi_countdown(ColorSpace);
2324
21.0k
            if (code < 0)
2325
0
                goto pdfi_devicen_error;
2326
2327
21.0k
            pcs->params.device_n.devn_process_space = process_space;
2328
2329
21.0k
            code = pdfi_dict_get_type(ctx, Process, "Components", PDF_ARRAY, (pdf_obj **)&Components);
2330
21.0k
            if (code < 0)
2331
0
                goto pdfi_devicen_error;
2332
2333
21.0k
            pcs->params.device_n.num_process_names = pdfi_array_size(Components);
2334
21.0k
            pcs->params.device_n.process_names = (char **)gs_alloc_bytes(pcs->params.device_n.mem->non_gc_memory, (size_t)pdfi_array_size(Components) * sizeof(char *), "pdfi_devicen(Processnames)");
2335
21.0k
            if (pcs->params.device_n.process_names == NULL) {
2336
0
                code = gs_error_VMerror;
2337
0
                goto pdfi_devicen_error;
2338
0
            }
2339
21.0k
            memset(pcs->params.device_n.process_names, 0x00, pdfi_array_size(Components) * sizeof(char *));
2340
2341
105k
            for (ix = 0; ix < pcs->params.device_n.num_process_names; ix++) {
2342
84.0k
                code = pdfi_array_get(ctx, Components, ix, &name);
2343
84.0k
                if (code < 0) {
2344
0
                    pdfi_countdown(Components);
2345
0
                    goto pdfi_devicen_error;
2346
0
                }
2347
2348
84.0k
                switch (pdfi_type_of(name)) {
2349
84.0k
                    case PDF_NAME:
2350
84.0k
                    case PDF_STRING:
2351
84.0k
                        pcs->params.device_n.process_names[ix] = (char *)gs_alloc_bytes(pcs->params.device_n.mem->non_gc_memory, ((pdf_name *)name)->length + (size_t)1, "pdfi_devicen(Processnames)");
2352
84.0k
                        if (pcs->params.device_n.process_names[ix] == NULL) {
2353
0
                            pdfi_countdown(Components);
2354
0
                            pdfi_countdown(name);
2355
0
                            code = gs_error_VMerror;
2356
0
                            goto pdfi_devicen_error;
2357
0
                        }
2358
84.0k
                        memcpy(pcs->params.device_n.process_names[ix], ((pdf_name *)name)->data, ((pdf_name *)name)->length);
2359
84.0k
                        pcs->params.device_n.process_names[ix][((pdf_name *)name)->length] = 0x00;
2360
84.0k
                        pdfi_countdown(name);
2361
84.0k
                        break;
2362
6
                    default:
2363
6
                        pdfi_countdown(Components);
2364
6
                        pdfi_countdown(name);
2365
6
                        goto pdfi_devicen_error;
2366
84.0k
                }
2367
84.0k
            }
2368
21.0k
            pdfi_countdown(Components);
2369
21.0k
        }
2370
2371
21.1k
        code = pdfi_dict_knownget_type(ctx, attributes, "Colorants", PDF_DICT, (pdf_obj **)&Colorants);
2372
21.1k
        if (code < 0)
2373
0
            goto pdfi_devicen_error;
2374
2375
21.1k
        if (Colorants != NULL && pdfi_dict_entries(Colorants) != 0) {
2376
0
            uint64_t ix = 0;
2377
0
            pdf_obj *Colorant = NULL, *Space = NULL;
2378
0
            char *colorant_name;
2379
0
            gs_color_space *colorant_space = NULL;
2380
2381
0
            code = pdfi_dict_first(ctx, Colorants, &Colorant, &Space, &ix);
2382
0
            if (code < 0)
2383
0
                goto pdfi_devicen_error;
2384
2385
0
            do {
2386
0
                switch (pdfi_type_of(Space)) {
2387
0
                    case PDF_STRING:
2388
0
                    case PDF_NAME:
2389
0
                    case PDF_ARRAY:
2390
0
                        break;
2391
0
                    default:
2392
0
                        pdfi_countdown(Space);
2393
0
                        pdfi_countdown(Colorant);
2394
0
                        code = gs_note_error(gs_error_typecheck);
2395
0
                        goto pdfi_devicen_error;
2396
0
                }
2397
0
                switch (pdfi_type_of(Colorant)) {
2398
0
                    case PDF_STRING:
2399
0
                    case PDF_NAME:
2400
0
                        break;
2401
0
                    default:
2402
0
                        pdfi_countdown(Space);
2403
0
                        pdfi_countdown(Colorant);
2404
0
                        code = gs_note_error(gs_error_typecheck);
2405
0
                        goto pdfi_devicen_error;
2406
0
                }
2407
2408
0
                code = pdfi_create_colorspace(ctx, Space, stream_dict, page_dict, &colorant_space, inline_image);
2409
0
                if (code < 0) {
2410
0
                    pdfi_countdown(Space);
2411
0
                    pdfi_countdown(Colorant);
2412
0
                    goto pdfi_devicen_error;
2413
0
                }
2414
2415
0
                colorant_name = (char *)gs_alloc_bytes(pcs->params.device_n.mem->non_gc_memory, ((pdf_name *)Colorant)->length + (size_t)1, "pdfi_devicen(colorant)");
2416
0
                if (colorant_name == NULL) {
2417
0
                    rc_decrement_cs(colorant_space, "pdfi_devicen(colorant)");
2418
0
                    pdfi_countdown(Space);
2419
0
                    pdfi_countdown(Colorant);
2420
0
                    code = gs_note_error(gs_error_VMerror);
2421
0
                    goto pdfi_devicen_error;
2422
0
                }
2423
0
                memcpy(colorant_name, ((pdf_name *)Colorant)->data, ((pdf_name *)Colorant)->length);
2424
0
                colorant_name[((pdf_name *)Colorant)->length] = 0x00;
2425
2426
0
                code = gs_attach_colorant_to_space(colorant_name, pcs, colorant_space, pcs->params.device_n.mem->non_gc_memory);
2427
0
                if (code < 0) {
2428
0
                    gs_free_object(pcs->params.device_n.mem->non_gc_memory, colorant_name, "pdfi_devicen(colorant)");
2429
0
                    rc_decrement_cs(colorant_space, "pdfi_devicen(colorant)");
2430
0
                    pdfi_countdown(Space);
2431
0
                    pdfi_countdown(Colorant);
2432
0
                    code = gs_note_error(gs_error_VMerror);
2433
0
                    goto pdfi_devicen_error;
2434
0
                }
2435
2436
                /* We've attached the colorant colour space to the DeviceN space, we no longer need this
2437
                 * reference to it, so discard it.
2438
                 */
2439
0
                rc_decrement_cs(colorant_space, "pdfi_devicen(colorant)");
2440
0
                pdfi_countdown(Space);
2441
0
                pdfi_countdown(Colorant);
2442
0
                Space = Colorant = NULL;
2443
2444
0
                code = pdfi_dict_next(ctx, Colorants, &Colorant, &Space, &ix);
2445
0
                if (code == gs_error_undefined)
2446
0
                    break;
2447
2448
0
                if (code < 0) {
2449
0
                    pdfi_countdown(Space);
2450
0
                    pdfi_countdown(Colorant);
2451
0
                    goto pdfi_devicen_error;
2452
0
                }
2453
0
            }while (1);
2454
0
        }
2455
21.1k
    }
2456
2457
22.0k
    if (ppcs!= NULL){
2458
142
        *ppcs = pcs;
2459
142
        pdfi_set_colour_callback(pcs, ctx, pdfi_cspace_free_callback);
2460
21.9k
    } else {
2461
21.9k
        code = pdfi_gs_setcolorspace(ctx, pcs);
2462
        /* release reference from construction */
2463
21.9k
        rc_decrement_only_cs(pcs, "setdevicenspace");
2464
21.9k
    }
2465
22.0k
    pdfi_countdown(Process);
2466
22.0k
    pdfi_countdown(Colorants);
2467
22.0k
    pdfi_countdown(attributes);
2468
22.0k
    pdfi_countdown(inks);
2469
22.0k
    pdfi_countdown(NamedAlternate);
2470
22.0k
    pdfi_countdown(ArrayAlternate);
2471
22.0k
    pdfi_countdown(transform);
2472
22.0k
    return_error(0);
2473
2474
2.88k
pdfi_devicen_error:
2475
2.88k
    pdfi_free_function(ctx, pfn);
2476
2.88k
    if (pcs_alt != NULL)
2477
2.60k
        rc_decrement_only_cs(pcs_alt, "setseparationspace");
2478
2.88k
    if(pcs != NULL)
2479
12
        rc_decrement_only_cs(pcs, "setseparationspace");
2480
2.88k
    pdfi_countdown(Process);
2481
2.88k
    pdfi_countdown(Colorants);
2482
2.88k
    pdfi_countdown(attributes);
2483
2.88k
    pdfi_countdown(inks);
2484
2.88k
    pdfi_countdown(NamedAlternate);
2485
2.88k
    pdfi_countdown(ArrayAlternate);
2486
2.88k
    pdfi_countdown(transform);
2487
2.88k
    return code;
2488
22.0k
}
2489
2490
/* Now /Indexed spaces, essentially we just need to set the underlying space(s) and then set
2491
 * /Indexed.
2492
 */
2493
static int
2494
pdfi_create_indexed(pdf_context *ctx, pdf_array *color_array, int index,
2495
                    pdf_dict *stream_dict, pdf_dict *page_dict, gs_color_space **ppcs, bool inline_image)
2496
13.9k
{
2497
13.9k
    pdf_obj *space=NULL, *lookup=NULL;
2498
13.9k
    int code;
2499
13.9k
    int64_t hival, lookup_length = 0;
2500
13.9k
    int num_values;
2501
13.9k
    gs_color_space *pcs=NULL, *pcs_base=NULL;
2502
13.9k
    gs_color_space_index base_type;
2503
13.9k
    byte *Buffer = NULL;
2504
2505
13.9k
    if (index != 0)
2506
0
        return_error(gs_error_syntaxerror);
2507
2508
13.9k
    code = pdfi_array_get_int(ctx, color_array, index + 2, &hival);
2509
13.9k
    if (code < 0)
2510
100
        return code;
2511
2512
13.8k
    if (hival > 255 || hival < 0)
2513
19
        return_error(gs_error_syntaxerror);
2514
2515
13.7k
    code = pdfi_array_get(ctx, color_array, index + 1, &space);
2516
13.7k
    if (code < 0)
2517
80
        goto exit;
2518
2519
13.7k
    code = pdfi_create_colorspace(ctx, space, stream_dict, page_dict, &pcs_base, inline_image);
2520
13.7k
    if (code < 0)
2521
391
        goto exit;
2522
2523
13.3k
    base_type = gs_color_space_get_index(pcs_base);
2524
13.3k
    if (base_type == gs_color_space_index_Pattern || base_type == gs_color_space_index_Indexed) {
2525
9
        code = gs_note_error(gs_error_typecheck);
2526
9
        goto exit;
2527
9
    }
2528
2529
13.3k
    (void)pcs_base->type->install_cspace(pcs_base, ctx->pgs);
2530
2531
13.3k
    code = pdfi_array_get(ctx, color_array, index + 3, &lookup);
2532
13.3k
    if (code < 0)
2533
209
        goto exit;
2534
2535
13.1k
    num_values = (hival+1) * cs_num_components(pcs_base);
2536
13.1k
    lookup_length = num_values;
2537
2538
13.1k
    switch (pdfi_type_of(lookup)) {
2539
7.28k
    case PDF_STREAM:
2540
7.28k
        code = pdfi_stream_to_buffer(ctx, (pdf_stream *)lookup, &Buffer, &lookup_length);
2541
7.28k
        if (code < 0)
2542
9
            goto exit;
2543
7.27k
        break;
2544
7.27k
    case PDF_STRING:
2545
5.71k
    {
2546
5.71k
        pdf_string *lookup_string = (pdf_string *)lookup; /* alias */
2547
2548
5.71k
        Buffer = gs_alloc_bytes(ctx->memory, lookup_string->length, "pdfi_create_indexed (lookup buffer)");
2549
5.71k
        if (Buffer == NULL) {
2550
0
            code = gs_note_error(gs_error_VMerror);
2551
0
            goto exit;
2552
0
        }
2553
2554
5.71k
        memcpy(Buffer, lookup_string->data, lookup_string->length);
2555
5.71k
        lookup_length = lookup_string->length;
2556
5.71k
        break;
2557
5.71k
    }
2558
109
    default:
2559
109
        code = gs_note_error(gs_error_typecheck);
2560
109
        goto exit;
2561
13.1k
    }
2562
2563
12.9k
    if (num_values > lookup_length) {
2564
        /* This is not legal, but Acrobat seems to accept it */
2565
146
        byte *SBuffer = NULL;
2566
2567
146
        code = pdfi_set_error_stop(ctx, gs_error_rangecheck, NULL, E_PDF_BAD_INDEXED_STRING, "pdfi_create_indexed", NULL);
2568
146
        if (code < 0)
2569
0
            goto exit;
2570
146
        SBuffer = gs_alloc_bytes(ctx->memory, num_values, "pdfi_create_indexed (lookup buffer)");
2571
146
        if (SBuffer == NULL) {
2572
0
            code = gs_note_error(gs_error_VMerror);
2573
0
            goto exit;
2574
0
        }
2575
146
        memcpy(SBuffer, Buffer, lookup_length);
2576
146
        memset(&SBuffer[lookup_length], 0x00, num_values - lookup_length);
2577
146
        gs_free_object(ctx->memory, Buffer, "pdfi_create_indexed (lookup buffer)");
2578
146
        Buffer = SBuffer;
2579
146
    }
2580
2581
    /* If we have a named color profile and the base space is DeviceN or
2582
       Separation use a different set of procedures to ensure the named
2583
       color remapping code is used */
2584
12.9k
    if (ctx->pgs->icc_manager->device_named != NULL &&
2585
12.9k
        (base_type == gs_color_space_index_Separation ||
2586
0
         base_type == gs_color_space_index_DeviceN))
2587
0
        pcs = gs_cspace_alloc(ctx->memory, &gs_color_space_type_Indexed_Named);
2588
12.9k
    else
2589
12.9k
        pcs = gs_cspace_alloc(ctx->memory, &gs_color_space_type_Indexed);
2590
2591
12.9k
    if (pcs == NULL) {
2592
0
        code = gs_note_error(gs_error_VMerror);
2593
0
        goto exit;
2594
0
    }
2595
    /* NOTE: we don't need to increment the reference to pcs_base, since it is already 1 */
2596
12.9k
    pcs->base_space = pcs_base;
2597
2598
12.9k
    pcs->params.indexed.lookup.table.size = num_values;
2599
12.9k
    pcs->params.indexed.use_proc = 0;
2600
12.9k
    pcs->params.indexed.hival = hival;
2601
12.9k
    pcs->params.indexed.n_comps = cs_num_components(pcs_base);
2602
12.9k
    pcs->params.indexed.lookup.table.data = Buffer;
2603
12.9k
    Buffer = NULL;
2604
2605
12.9k
    if (ppcs != NULL) {
2606
12.9k
        *ppcs = pcs;
2607
12.9k
        pdfi_set_colour_callback(pcs, ctx, pdfi_cspace_free_callback);
2608
12.9k
    }
2609
74
    else {
2610
74
        code = pdfi_gs_setcolorspace(ctx, pcs);
2611
        /* release reference from construction */
2612
74
        rc_decrement_only_cs(pcs, "setindexedspace");
2613
74
    }
2614
2615
13.7k
 exit:
2616
13.7k
    if (code != 0)
2617
13.7k
        rc_decrement(pcs_base, "pdfi_create_indexed(pcs_base) error");
2618
13.7k
    if (Buffer)
2619
0
        gs_free_object(ctx->memory, Buffer, "pdfi_create_indexed (decompression buffer)");
2620
13.7k
    pdfi_countdown(space);
2621
13.7k
    pdfi_countdown(lookup);
2622
13.7k
    return code;
2623
12.9k
}
2624
2625
static int pdfi_create_DeviceGray(pdf_context *ctx, gs_color_space **ppcs)
2626
54.5k
{
2627
54.5k
    int code = 0;
2628
2629
54.5k
    if (ppcs != NULL) {
2630
49.6k
        if (ctx->page.DefaultGray_cs != NULL) {
2631
0
            *ppcs = ctx->page.DefaultGray_cs;
2632
0
            rc_increment(*ppcs);
2633
49.6k
        } else {
2634
49.6k
            *ppcs = gs_cspace_new_DeviceGray(ctx->memory);
2635
49.6k
            if (*ppcs == NULL)
2636
0
                code = gs_note_error(gs_error_VMerror);
2637
49.6k
            else {
2638
49.6k
                code = ((gs_color_space *)*ppcs)->type->install_cspace(*ppcs, ctx->pgs);
2639
49.6k
                if (code < 0) {
2640
0
                    rc_decrement_only_cs(*ppcs, "pdfi_create_DeviceGray");
2641
0
                    *ppcs = NULL;
2642
0
                }
2643
49.6k
            }
2644
49.6k
            if (*ppcs != NULL)
2645
49.6k
                pdfi_set_colour_callback(*ppcs, ctx, pdfi_cspace_free_callback);
2646
49.6k
        }
2647
49.6k
    } else {
2648
4.91k
        code = pdfi_gs_setgray(ctx, 0);
2649
4.91k
        pdfi_set_colour_callback(ctx->pgs->color[0].color_space, ctx, pdfi_cspace_free_callback);
2650
4.91k
    }
2651
54.5k
    return code;
2652
54.5k
}
2653
2654
static int pdfi_create_DeviceRGB(pdf_context *ctx, gs_color_space **ppcs)
2655
122k
{
2656
122k
    int code = 0;
2657
2658
122k
    if (ppcs != NULL) {
2659
75.6k
        if (ctx->page.DefaultRGB_cs != NULL) {
2660
224
            *ppcs = ctx->page.DefaultRGB_cs;
2661
224
            rc_increment(*ppcs);
2662
75.4k
        } else {
2663
75.4k
            *ppcs = gs_cspace_new_DeviceRGB(ctx->memory);
2664
75.4k
            if (*ppcs == NULL)
2665
0
                code = gs_note_error(gs_error_VMerror);
2666
75.4k
            else {
2667
75.4k
                code = ((gs_color_space *)*ppcs)->type->install_cspace(*ppcs, ctx->pgs);
2668
75.4k
                if (code < 0) {
2669
0
                    rc_decrement_only_cs(*ppcs, "pdfi_create_DeviceRGB");
2670
0
                    *ppcs = NULL;
2671
0
                }
2672
75.4k
            }
2673
75.4k
            if (*ppcs != NULL)
2674
75.4k
                pdfi_set_colour_callback(*ppcs, ctx, pdfi_cspace_free_callback);
2675
75.4k
        }
2676
75.6k
    } else {
2677
47.1k
        code = pdfi_gs_setrgbcolor(ctx, 0, 0, 0);
2678
47.1k
    }
2679
122k
    return code;
2680
122k
}
2681
2682
static int pdfi_create_DeviceCMYK(pdf_context *ctx, gs_color_space **ppcs)
2683
106k
{
2684
106k
    int code = 0;
2685
2686
106k
    if (ppcs != NULL) {
2687
82.2k
        if (ctx->page.DefaultCMYK_cs != NULL) {
2688
0
            *ppcs = ctx->page.DefaultCMYK_cs;
2689
0
            rc_increment(*ppcs);
2690
82.2k
        } else {
2691
82.2k
            *ppcs = gs_cspace_new_DeviceCMYK(ctx->memory);
2692
82.2k
            if (*ppcs == NULL)
2693
0
                code = gs_note_error(gs_error_VMerror);
2694
82.2k
            else {
2695
82.2k
                code = ((gs_color_space *)*ppcs)->type->install_cspace(*ppcs, ctx->pgs);
2696
82.2k
                if (code < 0) {
2697
0
                    rc_decrement_only_cs(*ppcs, "pdfi_create_DeviceCMYK");
2698
0
                    *ppcs = NULL;
2699
0
                }
2700
82.2k
            }
2701
82.2k
            if (*ppcs != NULL)
2702
82.2k
                pdfi_set_colour_callback(*ppcs, ctx, pdfi_cspace_free_callback);
2703
82.2k
        }
2704
82.2k
    } else {
2705
24.3k
        code = pdfi_gs_setcmykcolor(ctx, 0, 0, 0, 1);
2706
24.3k
        pdfi_set_colour_callback(ctx->pgs->color[0].color_space, ctx, pdfi_cspace_free_callback);
2707
24.3k
    }
2708
106k
    return code;
2709
106k
}
2710
2711
static int pdfi_create_JPX_space(pdf_context *ctx, const char *name, int num_components, gs_color_space **ppcs)
2712
5.41k
{
2713
5.41k
    int code, icc_N;
2714
5.41k
    float range_buff[6] = {0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f};
2715
2716
5.41k
    code = pdfi_create_icc(ctx, (char *)name, NULL, num_components, &icc_N, range_buff, 0, ppcs);
2717
5.41k
    return code;
2718
5.41k
}
2719
2720
/* These next routines allow us to use recursion to set up colour spaces. We can set
2721
 * colour space starting from a name (which can be a named resource) or an array.
2722
 * If we get a name, and its a named resource we dereference it and go round again.
2723
 * If its an array we select the correct handler (above) for that space. The space
2724
 * handler will call pdfi_create_colorspace() to set the underlying space(s) which
2725
 * may mean calling pdfi_create_colorspace again....
2726
 */
2727
static int
2728
pdfi_create_colorspace_by_array(pdf_context *ctx, pdf_array *color_array, int index,
2729
                                pdf_dict *stream_dict, pdf_dict *page_dict, gs_color_space **ppcs,
2730
                                bool inline_image)
2731
332k
{
2732
332k
    int code;
2733
332k
    pdf_name *space = NULL;
2734
332k
    pdf_array *a = NULL;
2735
2736
332k
    code = pdfi_array_get_type(ctx, color_array, index, PDF_NAME, (pdf_obj **)&space);
2737
332k
    if (code != 0)
2738
316
        goto exit;
2739
2740
332k
    code = 0;
2741
332k
    if (pdfi_name_is(space, "G") || pdfi_name_is(space, "DeviceGray")) {
2742
4
        if (pdfi_name_is(space, "G") && !inline_image) {
2743
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)
2744
0
                return code;
2745
0
        }
2746
4
        code = pdfi_create_DeviceGray(ctx, ppcs);
2747
332k
    } else if (pdfi_name_is(space, "I") || pdfi_name_is(space, "Indexed")) {
2748
13.9k
        if (pdfi_name_is(space, "I") && !inline_image) {
2749
100
            pdfi_set_warning(ctx, 0, NULL, W_PDF_BAD_INLINECOLORSPACE, "pdfi_create_colorspace_by_array", NULL);
2750
100
            if (ctx->args.pdfstoponwarning)
2751
0
                return_error(gs_error_syntaxerror);
2752
100
        }
2753
13.9k
        code = pdfi_create_indexed(ctx, color_array, index, stream_dict, page_dict, ppcs, inline_image);
2754
318k
    } else if (pdfi_name_is(space, "Lab")) {
2755
1.34k
        code = pdfi_create_Lab(ctx, color_array, index, stream_dict, page_dict, ppcs);
2756
316k
    } else if (pdfi_name_is(space, "RGB") || pdfi_name_is(space, "DeviceRGB")) {
2757
5
        if (pdfi_name_is(space, "RGB") && !inline_image) {
2758
0
            pdfi_set_warning(ctx, 0, NULL, W_PDF_BAD_INLINECOLORSPACE, "pdfi_create_colorspace_by_array", NULL);
2759
0
            if (ctx->args.pdfstoponwarning)
2760
0
                return_error(gs_error_syntaxerror);
2761
0
        }
2762
5
        code = pdfi_create_DeviceRGB(ctx, ppcs);
2763
316k
    } else if (pdfi_name_is(space, "CMYK") || pdfi_name_is(space, "DeviceCMYK") || pdfi_name_is(space, "CalCMYK")) {
2764
0
        if (pdfi_name_is(space, "CMYK") && !inline_image) {
2765
0
            pdfi_set_warning(ctx, 0, NULL, W_PDF_BAD_INLINECOLORSPACE, "pdfi_create_colorspace_by_array", NULL);
2766
0
            if (ctx->args.pdfstoponwarning)
2767
0
                return_error(gs_error_syntaxerror);
2768
0
        }
2769
0
        code = pdfi_create_DeviceCMYK(ctx, ppcs);
2770
316k
    } else if (pdfi_name_is(space, "CalRGB")) {
2771
3.21k
        code = pdfi_create_CalRGB(ctx, color_array, index, stream_dict, page_dict, ppcs);
2772
313k
    } else if (pdfi_name_is(space, "CalGray")) {
2773
608
        code = pdfi_create_CalGray(ctx, color_array, index, stream_dict, page_dict, ppcs);
2774
313k
    } else if (pdfi_name_is(space, "Pattern")) {
2775
2.35k
        if (index != 0)
2776
0
            code = gs_note_error(gs_error_syntaxerror);
2777
2.35k
        else
2778
2.35k
            code = pdfi_pattern_create(ctx, color_array, stream_dict, page_dict, ppcs);
2779
310k
    } else if (pdfi_name_is(space, "DeviceN")) {
2780
24.9k
        code = pdfi_create_DeviceN(ctx, color_array, index, stream_dict, page_dict, ppcs, inline_image);
2781
285k
    } else if (pdfi_name_is(space, "ICCBased")) {
2782
218k
        code = pdfi_create_iccbased(ctx, color_array, index, stream_dict, page_dict, ppcs, inline_image);
2783
218k
    } else if (pdfi_name_is(space, "Separation")) {
2784
66.1k
        code = pdfi_create_Separation(ctx, color_array, index, stream_dict, page_dict, ppcs, inline_image);
2785
66.1k
    } else {
2786
719
        if (stream_dict == NULL)
2787
29
            code = gs_note_error(gs_error_syntaxerror);
2788
690
        else
2789
690
            code = pdfi_find_resource(ctx, (unsigned char *)"ColorSpace",
2790
690
                                  space, (pdf_dict *)stream_dict, page_dict, (pdf_obj **)&a);
2791
719
        if (code < 0)
2792
719
            goto exit;
2793
2794
0
        if (pdfi_type_of(a) != PDF_ARRAY) {
2795
0
            code = gs_note_error(gs_error_typecheck);
2796
0
            goto exit;
2797
0
        }
2798
2799
        /* recursion */
2800
0
        code = pdfi_create_colorspace_by_array(ctx, a, 0, stream_dict, page_dict, ppcs, inline_image);
2801
0
    }
2802
2803
332k
 exit:
2804
332k
    pdfi_countdown(space);
2805
332k
    pdfi_countdown(a);
2806
332k
    return code;
2807
332k
}
2808
2809
static int
2810
pdfi_create_colorspace_by_name(pdf_context *ctx, pdf_name *name,
2811
                               pdf_dict *stream_dict, pdf_dict *page_dict,
2812
                               gs_color_space **ppcs, bool inline_image)
2813
707k
{
2814
707k
    int code = 0;
2815
707k
    gs_id oldid = 0;
2816
2817
707k
    if (pdfi_name_is(name, "G") || pdfi_name_is(name, "DeviceGray")) {
2818
54.5k
        if (pdfi_name_is(name, "G") && !inline_image) {
2819
25
            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)
2820
0
                return code;
2821
25
        }
2822
54.5k
        code = pdfi_create_DeviceGray(ctx, ppcs);
2823
653k
    } else if (pdfi_name_is(name, "RGB") || pdfi_name_is(name, "DeviceRGB")) {
2824
122k
        if (pdfi_name_is(name, "RGB") && !inline_image) {
2825
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)
2826
0
                return code;
2827
0
        }
2828
122k
        code = pdfi_create_DeviceRGB(ctx, ppcs);
2829
530k
    } else if (pdfi_name_is(name, "CMYK") || pdfi_name_is(name, "DeviceCMYK") || pdfi_name_is(name, "CalCMYK")) {
2830
106k
        if (pdfi_name_is(name, "CMYK") && !inline_image) {
2831
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)
2832
0
                return code;
2833
0
        }
2834
106k
        code = pdfi_create_DeviceCMYK(ctx, ppcs);
2835
423k
    } else if (pdfi_name_is(name, "Pattern")) {
2836
67.8k
        code = pdfi_pattern_create(ctx, NULL, stream_dict, page_dict, ppcs);
2837
356k
    } else if (pdfi_name_is(name, "esRGBICC")) {                /* These 4 spaces are 'special' for JPX images          */
2838
0
        code = pdfi_create_JPX_space(ctx, "esrgb", 3, ppcs);    /* the names are non-standad and must match those in    */
2839
356k
    } else if (pdfi_name_is(name, "rommRGBICC")) {              /* pdfi_image_get_color() in pdf_image.c                */
2840
0
        code = pdfi_create_JPX_space(ctx, "rommrgb", 3, ppcs);  /* Note that the Lab space for JPX images does not use  */
2841
356k
    } else if (pdfi_name_is(name, "sRGBICC")) {                 /* a special space but simply constructs an appropriate */
2842
617
        code = pdfi_create_JPX_space(ctx, "srgb", 3, ppcs);     /* pdf_array object with the corerct contents for an    */
2843
355k
    } else if (pdfi_name_is(name, "sGrayICC")) {                /* Lab space with a D65 white point.                    */
2844
4.79k
        code = pdfi_create_JPX_space(ctx, "sgray", 1, ppcs);
2845
350k
    } else {
2846
350k
        pdf_obj *ref_space = NULL;
2847
2848
350k
        if (ppcs == NULL && check_same_current_space(ctx, name) == 1)
2849
96.7k
            return 0;
2850
2851
253k
        code = pdfi_find_resource(ctx, (unsigned char *)"ColorSpace", name, (pdf_dict *)stream_dict,
2852
253k
                                  page_dict, &ref_space);
2853
253k
        if (code < 0)
2854
38.7k
            return code;
2855
2856
215k
        if (pdfi_type_of(ref_space) == PDF_NAME) {
2857
194
            if (ref_space->object_num != 0 && ref_space->object_num == name->object_num) {
2858
0
                pdfi_countdown(ref_space);
2859
0
                return_error(gs_error_circular_reference);
2860
0
            }
2861
194
            if (((pdf_name *)ref_space)->length <= 0) {
2862
8
                pdfi_countdown(ref_space);
2863
8
                return_error(gs_error_syntaxerror);
2864
8
            }
2865
186
            if (((pdf_name *)ref_space)->length == name->length && memcmp(((pdf_name *)ref_space)->data, name->data, name->length) == 0) {
2866
3
                pdfi_countdown(ref_space);
2867
3
                return_error(gs_error_circular_reference);
2868
3
            }
2869
186
        }
2870
2871
215k
        oldid = ctx->pgs->color[0].color_space->id;
2872
        /* recursion */
2873
215k
        code = pdfi_create_colorspace(ctx, ref_space, stream_dict, page_dict, ppcs, inline_image);
2874
2875
215k
        if (code >= 0) {
2876
189k
            if (oldid != ctx->pgs->color[0].color_space->id) {
2877
188k
                if (ppcs != NULL)
2878
0
                    pdfi_set_colourspace_name(ctx, *ppcs, name);
2879
188k
                else
2880
188k
                    pdfi_set_colourspace_name(ctx, ctx->pgs->color[0].color_space, name);
2881
188k
            }
2882
189k
        }
2883
2884
215k
        pdfi_countdown(ref_space);
2885
215k
        return code;
2886
215k
    }
2887
2888
    /* If we got here, it's a recursion base case, and ppcs should have been set if requested */
2889
357k
    if (ppcs != NULL && *ppcs == NULL)
2890
0
        code = gs_note_error(gs_error_VMerror);
2891
357k
    return code;
2892
707k
}
2893
2894
/*
2895
 * Gets icc profile data from the provided stream.
2896
 * Position in the stream is NOT preserved.
2897
 * This is raw data, not filtered, so no need to worry about compression.
2898
 * (Used for JPXDecode images)
2899
 */
2900
int
2901
pdfi_create_icc_colorspace_from_stream(pdf_context *ctx, pdf_c_stream *stream, gs_offset_t offset,
2902
                                       unsigned int length, int comps, int *icc_N, ulong dictkey, gs_color_space **ppcs)
2903
0
{
2904
0
    pdf_c_stream *profile_stream = NULL;
2905
0
    byte *profile_buffer;
2906
0
    int code, code1;
2907
0
    float range[8] = {0,1,0,1,0,1,0,1};
2908
2909
    /* Move to the start of the profile data */
2910
0
    pdfi_seek(ctx, stream, offset, SEEK_SET);
2911
2912
    /* The ICC profile reading code (irritatingly) requires a seekable stream, because it
2913
     * rewinds it to the start, then seeks to the end to find the size, then rewinds the
2914
     * stream again.
2915
     * Ideally we would use a ReusableStreamDecode filter here, but that is largely
2916
     * implemented in PostScript (!) so we can't use it. What we can do is create a
2917
     * string sourced stream in memory, which is at least seekable.
2918
     */
2919
0
    code = pdfi_open_memory_stream_from_stream(ctx, length, &profile_buffer, stream, &profile_stream, true);
2920
0
    if (code < 0) {
2921
0
        return code;
2922
0
    }
2923
2924
    /* Now, finally, we can call the code to create and set the profile */
2925
0
    code = pdfi_create_icc(ctx, NULL, profile_stream->s, comps, icc_N, range, dictkey, ppcs);
2926
2927
0
    code1 = pdfi_close_memory_stream(ctx, profile_buffer, profile_stream);
2928
2929
0
    if (code == 0)
2930
0
        code = code1;
2931
2932
0
    return code;
2933
0
}
2934
2935
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)
2936
943k
{
2937
943k
    int code;
2938
2939
943k
    code = pdfi_loop_detector_mark(ctx);
2940
943k
    if (code < 0)
2941
0
        return code;
2942
2943
943k
    switch (pdfi_type_of(space)) {
2944
622k
    case PDF_NAME:
2945
622k
        code = pdfi_create_colorspace_by_name(ctx, (pdf_name *)space, stream_dict, page_dict, ppcs, inline_image);
2946
622k
        break;
2947
315k
    case PDF_ARRAY:
2948
315k
        code = pdfi_create_colorspace_by_array(ctx, (pdf_array *)space, 0, stream_dict, page_dict, ppcs, inline_image);
2949
315k
        break;
2950
4.77k
    default:
2951
4.77k
        pdfi_loop_detector_cleartomark(ctx);
2952
4.77k
        return_error(gs_error_typecheck);
2953
943k
    }
2954
938k
    if (code >= 0 && ppcs && *ppcs)
2955
189k
        (void)(*ppcs)->type->install_cspace(*ppcs, ctx->pgs);
2956
2957
938k
    (void)pdfi_loop_detector_cleartomark(ctx);
2958
938k
    return code;
2959
943k
}
2960
2961
int pdfi_setcolorspace(pdf_context *ctx, pdf_obj *space, pdf_dict *stream_dict, pdf_dict *page_dict)
2962
533k
{
2963
533k
    return pdfi_create_colorspace(ctx, space, stream_dict, page_dict, NULL, false);
2964
533k
}
2965
2966
/* And finally, the implementation of the actual PDF operators CS and cs */
2967
int pdfi_setstrokecolor_space(pdf_context *ctx, pdf_dict *stream_dict, pdf_dict *page_dict)
2968
65.3k
{
2969
65.3k
    int code;
2970
65.3k
    pdf_obj *n = NULL;
2971
2972
65.3k
    if (pdfi_count_stack(ctx) < 1)
2973
916
        return_error(gs_error_stackunderflow);
2974
2975
64.4k
    if (ctx->text.inside_CharProc && ctx->text.CharProc_d_type != pdf_type3_d0) {
2976
0
        pdfi_pop(ctx, 1);
2977
0
        pdfi_log_info(ctx, "pdfi_setstrokecolor_space", "colour operator in a CharProc, following a d1 ignored\n");
2978
0
        return 0;
2979
0
    }
2980
2981
64.4k
    if (pdfi_type_of(ctx->stack_top[-1]) != PDF_NAME) {
2982
1.32k
        pdfi_pop(ctx, 1);
2983
1.32k
        return_error(gs_error_typecheck);
2984
1.32k
    }
2985
63.0k
    n = ctx->stack_top[-1];
2986
63.0k
    pdfi_countup(n);
2987
63.0k
    pdfi_pop(ctx, 1);
2988
2989
63.0k
    gs_swapcolors_quick(ctx->pgs);
2990
63.0k
    code = pdfi_setcolorspace(ctx, n, stream_dict, page_dict);
2991
63.0k
    gs_swapcolors_quick(ctx->pgs);
2992
2993
63.0k
    pdfi_countdown(n);
2994
63.0k
    return code;
2995
64.4k
}
2996
2997
int pdfi_setfillcolor_space(pdf_context *ctx, pdf_dict *stream_dict, pdf_dict *page_dict)
2998
369k
{
2999
369k
    int code;
3000
369k
    pdf_obj *n = NULL;
3001
3002
369k
    if (pdfi_count_stack(ctx) < 1)
3003
4.83k
        return_error(gs_error_stackunderflow);
3004
3005
365k
    if (ctx->text.inside_CharProc && ctx->text.CharProc_d_type != pdf_type3_d0) {
3006
1
        pdfi_pop(ctx, 1);
3007
1
        pdfi_log_info(ctx, "pdfi_setfillcolor_space", "colour operator in a CharProc, following a d1 ignored\n");
3008
1
        return 0;
3009
1
    }
3010
3011
365k
    if (pdfi_type_of(ctx->stack_top[-1]) != PDF_NAME) {
3012
8.30k
        pdfi_pop(ctx, 1);
3013
8.30k
        return_error(gs_error_typecheck);
3014
8.30k
    }
3015
356k
    n = ctx->stack_top[-1];
3016
356k
    pdfi_countup(n);
3017
356k
    pdfi_pop(ctx, 1);
3018
3019
356k
    code = pdfi_setcolorspace(ctx, n, stream_dict, page_dict);
3020
3021
356k
    pdfi_countdown(n);
3022
356k
    return code;
3023
365k
}
3024
3025
3026
/*
3027
 * Set device outputintent from stream
3028
 * see zicc.c/zset_outputintent()
3029
 */
3030
static int pdfi_device_setoutputintent(pdf_context *ctx, pdf_dict *profile_dict, stream *stream)
3031
0
{
3032
0
    int code = 0;
3033
0
    gs_gstate *pgs = ctx->pgs;
3034
0
    gx_device *dev = gs_currentdevice(pgs);
3035
0
    cmm_dev_profile_t *dev_profile;
3036
0
    int64_t N;
3037
0
    int ncomps, dev_comps;
3038
0
    int expected = 0;
3039
0
    cmm_profile_t *picc_profile = NULL;
3040
0
    cmm_profile_t *source_profile = NULL;
3041
0
    gsicc_manager_t *icc_manager = pgs->icc_manager;
3042
0
    gs_color_space_index index;
3043
3044
0
    if_debug0m(gs_debug_flag_icc, ctx->memory, "[icc] Using OutputIntent\n");
3045
3046
    /* get dev_profile and try initing it if fail first time */
3047
0
    code = dev_proc(dev, get_profile)(dev, &dev_profile);
3048
0
    if (code < 0)
3049
0
        return code;
3050
3051
0
    if (dev_profile == NULL) {
3052
0
        code = gsicc_init_device_profile_struct(dev, NULL, 0);
3053
0
        if (code < 0)
3054
0
            return code;
3055
0
        code = dev_proc(dev, get_profile)(dev, &dev_profile);
3056
0
        if (code < 0)
3057
0
            return code;
3058
0
    }
3059
0
    if (dev_profile->oi_profile != NULL) {
3060
0
        return 0;  /* Allow only one setting of this object */
3061
0
    }
3062
3063
0
    code = pdfi_dict_get_int(ctx, profile_dict, "N", &N);
3064
0
    if (code < 0)
3065
0
        goto exit;
3066
0
    ncomps = (int)N;
3067
3068
0
    picc_profile = gsicc_profile_new(stream, gs_gstate_memory(pgs), NULL, 0);
3069
0
    if (picc_profile == NULL) {
3070
0
        code = gs_note_error(gs_error_VMerror);
3071
0
        goto exit;
3072
0
    }
3073
0
    picc_profile->num_comps = ncomps;
3074
0
    picc_profile->profile_handle =
3075
0
        gsicc_get_profile_handle_buffer(picc_profile->buffer,
3076
0
                                        picc_profile->buffer_size,
3077
0
                                        gs_gstate_memory(pgs));
3078
0
    if (picc_profile->profile_handle == NULL) {
3079
0
        code = gs_note_error(gs_error_VMerror);
3080
0
        goto exit;
3081
0
    }
3082
3083
0
    picc_profile->data_cs =
3084
0
        gscms_get_profile_data_space(picc_profile->profile_handle,
3085
0
            picc_profile->memory);
3086
0
    switch (picc_profile->data_cs) {
3087
0
        case gsCIEXYZ:
3088
0
        case gsCIELAB:
3089
0
        case gsRGB:
3090
0
            expected = 3;
3091
0
            source_profile = icc_manager->default_rgb;
3092
0
            break;
3093
0
        case gsGRAY:
3094
0
            expected = 1;
3095
0
            source_profile = icc_manager->default_gray;
3096
0
            break;
3097
0
        case gsCMYK:
3098
0
            expected = 4;
3099
0
            source_profile = icc_manager->default_cmyk;
3100
0
            break;
3101
0
        case gsNCHANNEL:
3102
0
            expected = 0;
3103
0
            break;
3104
0
        case gsNAMED:
3105
0
        case gsUNDEFINED:
3106
0
            break;
3107
0
    }
3108
0
    if (expected && ncomps != expected) {
3109
0
        code = gs_note_error(gs_error_rangecheck);
3110
0
        goto exit;
3111
0
    }
3112
0
    gsicc_init_hash_cs(picc_profile, pgs);
3113
3114
    /* All is well with the profile.  Lets set the stuff that needs to be set */
3115
0
    dev_profile->oi_profile = picc_profile;
3116
0
    rc_increment(picc_profile);
3117
0
    picc_profile->name = (char *) gs_alloc_bytes(picc_profile->memory,
3118
0
                                                 MAX_DEFAULT_ICC_LENGTH,
3119
0
                                                 "pdfi_color_setoutputintent");
3120
0
    if (picc_profile->name == NULL) {
3121
0
        code = gs_note_error(gs_error_VMerror);
3122
0
        goto exit;
3123
0
    }
3124
0
    strncpy(picc_profile->name, OI_PROFILE, strlen(OI_PROFILE));
3125
0
    picc_profile->name[strlen(OI_PROFILE)] = 0;
3126
0
    picc_profile->name_length = strlen(OI_PROFILE);
3127
    /* Set the range of the profile */
3128
0
    gsicc_set_icc_range(&picc_profile);
3129
3130
    /* If the output device has a different number of components, then we are
3131
       going to set the output intent as the proofing profile, unless the
3132
       proofing profile has already been set.
3133
3134
       If the device has the same number of components (and color model) then as
3135
       the profile we will use this as the output profile, unless someone has
3136
       explicitly set the output profile.
3137
3138
       Finally, we will use the output intent profile for the default profile
3139
       of the proper Device profile in the icc manager, again, unless someone
3140
       has explicitly set this default profile.
3141
3142
       All of this is skipped if we are forcing oveprint simulation with
3143
       the output intent set, in which case we will push the pdf14 device
3144
       to render directly to the the output intent color space and then
3145
       do a final transform to the target color space.
3146
    */
3147
0
    dev_comps = dev_profile->device_profile[GS_DEFAULT_DEVICE_PROFILE]->num_comps;
3148
0
    index = gsicc_get_default_type(dev_profile->device_profile[GS_DEFAULT_DEVICE_PROFILE]);
3149
3150
    /* If we are doing simulate overprint and the output intent is different than
3151
       what the device profile is the we will end up pushing the pdf14 device
3152
       and doing a rendering to the output intent color space.  Keep the device
3153
       profile as is, and do not do a proofing profile */
3154
3155
0
    if (!(ctx->pgs->device->icc_struct->overprint_control == gs_overprint_control_simulate &&
3156
0
        !gsicc_profiles_equal(dev_profile->oi_profile, dev_profile->device_profile[GS_DEFAULT_DEVICE_PROFILE]))) {
3157
0
        if (ncomps == dev_comps && index < gs_color_space_index_DevicePixel) {
3158
            /* The OI profile is the same type as the profile for the device and a
3159
               "default" profile for the device was not externally set. So we go
3160
               ahead and use the OI profile as the device profile.  Care needs to be
3161
               taken here to keep from screwing up any device parameters.   We will
3162
               use a keyword of OIProfile for the user/device parameter to indicate
3163
               its usage.  Also, note conflicts if one is setting object dependent
3164
               color management */
3165
0
            dev_profile->device_profile[GS_DEFAULT_DEVICE_PROFILE] = picc_profile;
3166
0
            rc_increment(picc_profile);
3167
0
            if_debug0m(gs_debug_flag_icc, ctx->memory, "[icc] OutputIntent used for device profile\n");
3168
0
        } else {
3169
0
            if (dev_profile->proof_profile == NULL) {
3170
                /* This means that we should use the OI profile as the proofing
3171
                   profile.  Note that if someone already has specified a
3172
                   proofing profile it is unclear what they are trying to do
3173
                   with the output intent.  In this case, we will use it
3174
                   just for the source data below */
3175
0
                dev_profile->proof_profile = picc_profile;
3176
0
                rc_increment(picc_profile);
3177
0
                if_debug0m(gs_debug_flag_icc, ctx->memory, "[icc] OutputIntent used for proof profile\n");
3178
0
            }
3179
0
        }
3180
0
    }
3181
3182
    /* Now the source colors.  See which source color space needs to use the
3183
       output intent ICC profile */
3184
0
    index = gsicc_get_default_type(source_profile);
3185
0
    if (index < gs_color_space_index_DevicePixel) {
3186
        /* source_profile is currently the default.  Set it to the OI profile */
3187
0
        switch (picc_profile->data_cs) {
3188
0
            case gsGRAY:
3189
0
                if_debug0m(gs_debug_flag_icc, ctx->memory, "[icc] OutputIntent used source Gray\n");
3190
0
                icc_manager->default_gray = picc_profile;
3191
0
                rc_increment(picc_profile);
3192
0
                break;
3193
0
            case gsRGB:
3194
0
                if_debug0m(gs_debug_flag_icc, ctx->memory, "[icc] OutputIntent used source RGB\n");
3195
0
                icc_manager->default_rgb = picc_profile;
3196
0
                rc_increment(picc_profile);
3197
0
                break;
3198
0
            case gsCMYK:
3199
0
                if_debug0m(gs_debug_flag_icc, ctx->memory, "[icc] OutputIntent used source CMYK\n");
3200
0
                icc_manager->default_cmyk = picc_profile;
3201
0
                rc_increment(picc_profile);
3202
0
                break;
3203
0
            default:
3204
0
                break;
3205
0
        }
3206
0
    }
3207
3208
0
 exit:
3209
0
    if (picc_profile != NULL)
3210
0
        rc_decrement(picc_profile, "pdfi_color_setoutputintent");
3211
0
    return code;
3212
0
}
3213
3214
/*
3215
 * intent_dict -- the outputintent dictionary
3216
 * profile -- the color profile (a stream)
3217
 *
3218
 */
3219
int pdfi_color_setoutputintent(pdf_context *ctx, pdf_dict *intent_dict, pdf_stream *profile)
3220
0
{
3221
0
    pdf_c_stream *profile_stream = NULL;
3222
0
    byte *profile_buffer;
3223
0
    int code, code1;
3224
0
    pdf_dict *profile_dict;
3225
3226
0
    code = pdfi_dict_from_obj(ctx, (pdf_obj *)profile, &profile_dict);
3227
0
    if (code < 0)
3228
0
        return code;
3229
3230
    /* The ICC profile reading code (irritatingly) requires a seekable stream, because it
3231
     * rewinds it to the start, then seeks to the end to find the size, then rewinds the
3232
     * stream again.
3233
     * Ideally we would use a ReusableStreamDecode filter here, but that is largely
3234
     * implemented in PostScript (!) so we can't use it. What we can do is create a
3235
     * string sourced stream in memory, which is at least seekable.
3236
     */
3237
0
    code = pdfi_open_memory_stream_from_filtered_stream(ctx, profile, &profile_buffer, &profile_stream, true);
3238
0
    if (code < 0)
3239
0
        goto exit;
3240
3241
    /* Create and set the device profile */
3242
0
    code = pdfi_device_setoutputintent(ctx, profile_dict, profile_stream->s);
3243
3244
0
    code1 = pdfi_close_memory_stream(ctx, profile_buffer, profile_stream);
3245
3246
0
    if (code == 0)
3247
0
        code = code1;
3248
3249
0
 exit:
3250
0
    return code;
3251
0
}
3252
3253
static int Check_Default_Space(pdf_context *ctx, pdf_obj *space, pdf_dict *source_dict, int num_components)
3254
870
{
3255
870
    pdf_obj *primary = NULL;
3256
870
    pdf_obj *ref_space = NULL;
3257
870
    int code = 0;
3258
3259
870
    if (pdfi_type_of(space) == PDF_NAME)
3260
0
    {
3261
0
        if (pdfi_name_is((const pdf_name *)space, "DeviceGray"))
3262
0
            return (num_components == 1 ? 0 : gs_error_rangecheck);
3263
0
        if (pdfi_name_is((const pdf_name *)space, "DeviceCMYK"))
3264
0
            return (num_components == 4 ? 0 : gs_error_rangecheck);
3265
0
        if (pdfi_name_is((const pdf_name *)space, "DeviceRGB"))
3266
0
            return (num_components == 3 ? 0 : gs_error_rangecheck);
3267
3268
0
        code = pdfi_find_resource(ctx, (unsigned char *)"ColorSpace", (pdf_name *)space, (pdf_dict *)source_dict,
3269
0
                                  NULL, &ref_space);
3270
0
        if (code < 0)
3271
0
            return code;
3272
3273
0
        if (pdfi_type_of(ref_space) == PDF_NAME) {
3274
0
            if (ref_space->object_num != 0 && ref_space->object_num == space->object_num) {
3275
0
                pdfi_countdown(ref_space);
3276
0
                return_error(gs_error_circular_reference);
3277
0
            }
3278
0
            if (pdfi_name_is((const pdf_name *)ref_space, "DeviceGray")) {
3279
0
                pdfi_countdown(ref_space);
3280
0
                return (num_components == 1 ? 0 : gs_error_rangecheck);
3281
0
            }
3282
0
            if (pdfi_name_is((const pdf_name *)ref_space, "DeviceCMYK")) {
3283
0
                pdfi_countdown(ref_space);
3284
0
                return (num_components == 4 ? 0 : gs_error_rangecheck);
3285
0
            }
3286
0
            if (pdfi_name_is((const pdf_name *)ref_space, "DeviceRGB")) {
3287
0
                pdfi_countdown(ref_space);
3288
0
                return (num_components == 3 ? 0 : gs_error_rangecheck);
3289
0
            }
3290
0
            pdfi_countdown(ref_space);
3291
0
            return_error(gs_error_typecheck);
3292
0
        }
3293
0
        space = ref_space;
3294
0
    }
3295
3296
870
    if (pdfi_type_of(space) == PDF_ARRAY) {
3297
855
        code = pdfi_array_get(ctx, (pdf_array *)space, 0, &primary);
3298
855
        if (code < 0)
3299
0
            goto exit;
3300
3301
855
        if (pdfi_type_of(primary) == PDF_NAME) {
3302
855
            if (pdfi_name_is((pdf_name *)primary, "Lab")) {
3303
0
                code = gs_note_error(gs_error_typecheck);
3304
0
                goto exit;
3305
0
            }
3306
855
            if (pdfi_name_is((pdf_name *)primary, "Pattern")) {
3307
4
                code = gs_note_error(gs_error_typecheck);
3308
4
                goto exit;
3309
4
            }
3310
851
            if (pdfi_name_is((pdf_name *)primary, "Indexed")) {
3311
0
                code = gs_note_error(gs_error_typecheck);
3312
0
                goto exit;
3313
0
            }
3314
851
        }
3315
855
    } else
3316
15
        code = gs_note_error(gs_error_typecheck);
3317
3318
870
exit:
3319
870
    pdfi_countdown(primary);
3320
870
    pdfi_countdown(ref_space);
3321
870
    return code;
3322
870
}
3323
3324
int pdfi_setup_DefaultSpaces(pdf_context *ctx, pdf_dict *source_dict)
3325
525k
{
3326
525k
    int code = 0;
3327
525k
    pdf_dict *resources_dict = NULL, *colorspaces_dict = NULL;
3328
525k
    pdf_obj *DefaultSpace = NULL;
3329
3330
525k
    if (ctx->args.NOSUBSTDEVICECOLORS)
3331
0
        return 0;
3332
3333
    /* Create any required DefaultGray, DefaultRGB or DefaultCMYK
3334
     * spaces.
3335
     */
3336
525k
    code = pdfi_dict_knownget(ctx, source_dict, "Resources", (pdf_obj **)&resources_dict);
3337
525k
    if (code > 0) {
3338
438k
        code = pdfi_dict_knownget(ctx, resources_dict, "ColorSpace", (pdf_obj **)&colorspaces_dict);
3339
438k
        if (code > 0) {
3340
50.3k
            code = pdfi_dict_knownget(ctx, colorspaces_dict, "DefaultGray", &DefaultSpace);
3341
50.3k
            if (code > 0) {
3342
0
                gs_color_space *pcs;
3343
3344
0
                code = Check_Default_Space(ctx, DefaultSpace, source_dict, 1);
3345
0
                if (code >= 0) {
3346
0
                    code = pdfi_create_colorspace(ctx, DefaultSpace, NULL, source_dict, &pcs, false);
3347
                    /* If any given Default* space fails simply ignore it, we wil then use the Device
3348
                     * space instead, this is as per the spec.
3349
                     */
3350
0
                    if (code >= 0) {
3351
0
                        if (gs_color_space_num_components(pcs) == 1) {
3352
0
                            ctx->page.DefaultGray_cs = pcs;
3353
0
                            pdfi_set_colour_callback(pcs, ctx, NULL);
3354
0
                        } else {
3355
0
                            rc_decrement(pcs, "setup_DefautSpaces");
3356
0
                            if ((code = pdfi_set_warning_stop(ctx, gs_note_error(gs_error_syntaxerror), NULL, W_PDF_INVALID_DEFAULTSPACE, "pdfi_setup_DefaultSpaces", NULL)) < 0)
3357
0
                                return code;
3358
0
                        }
3359
0
                    }
3360
0
                } else {
3361
0
                    if ((code = pdfi_set_warning_stop(ctx, gs_note_error(gs_error_syntaxerror), NULL, W_PDF_INVALID_DEFAULTSPACE, "pdfi_setup_DefaultSpaces", NULL)) < 0)
3362
0
                        return code;
3363
0
                }
3364
0
            }
3365
50.3k
            pdfi_countdown(DefaultSpace);
3366
50.3k
            DefaultSpace = NULL;
3367
50.3k
            code = pdfi_dict_knownget(ctx, colorspaces_dict, "DefaultRGB", &DefaultSpace);
3368
50.3k
            if (code > 0) {
3369
847
                gs_color_space *pcs;
3370
3371
847
                code = Check_Default_Space(ctx, DefaultSpace, source_dict, 1);
3372
847
                if (code >= 0) {
3373
828
                    code = pdfi_create_colorspace(ctx, DefaultSpace, NULL, source_dict, &pcs, false);
3374
                    /* If any given Default* space fails simply ignore it, we wil then use the Device
3375
                     * space instead, this is as per the spec.
3376
                     */
3377
828
                    if (code >= 0) {
3378
723
                        if (gs_color_space_num_components(pcs) == 3) {
3379
723
                            ctx->page.DefaultRGB_cs = pcs;
3380
723
                            pdfi_set_colour_callback(pcs, ctx, NULL);
3381
723
                        } else {
3382
0
                            rc_decrement(pcs, "setup_DefautSpaces");
3383
0
                            if ((code = pdfi_set_warning_stop(ctx, gs_note_error(gs_error_syntaxerror), NULL, W_PDF_INVALID_DEFAULTSPACE, "pdfi_setup_DefaultSpaces", NULL)) < 0)
3384
0
                                return code;
3385
0
                        }
3386
723
                    }
3387
828
                } else {
3388
19
                    if ((code = pdfi_set_warning_stop(ctx, gs_note_error(gs_error_syntaxerror), NULL, W_PDF_INVALID_DEFAULTSPACE, "pdfi_setup_DefaultSpaces", NULL)) < 0)
3389
0
                        return code;
3390
19
                }
3391
847
            }
3392
50.3k
            pdfi_countdown(DefaultSpace);
3393
50.3k
            DefaultSpace = NULL;
3394
50.3k
            code = pdfi_dict_knownget(ctx, colorspaces_dict, "DefaultCMYK", &DefaultSpace);
3395
50.3k
            if (code > 0) {
3396
23
                gs_color_space *pcs;
3397
3398
23
                code = Check_Default_Space(ctx, DefaultSpace, source_dict, 1);
3399
23
                if (code >= 0) {
3400
23
                    code = pdfi_create_colorspace(ctx, DefaultSpace, NULL, source_dict, &pcs, false);
3401
                    /* If any given Default* space fails simply ignore it, we wil then use the Device
3402
                     * space instead, this is as per the spec.
3403
                     */
3404
23
                    if (code >= 0) {
3405
23
                        if (gs_color_space_num_components(pcs) == 4) {
3406
23
                            ctx->page.DefaultCMYK_cs = pcs;
3407
23
                            pdfi_set_colour_callback(pcs, ctx, NULL);
3408
23
                        } else {
3409
0
                            rc_decrement(pcs, "setup_DefautSpaces");
3410
0
                            if ((code = pdfi_set_warning_stop(ctx, gs_note_error(gs_error_syntaxerror), NULL, W_PDF_INVALID_DEFAULTSPACE, "pdfi_setup_DefaultSpaces", NULL)) < 0)
3411
0
                                return code;
3412
0
                        }
3413
23
                    }
3414
23
                } else {
3415
0
                    if ((code = pdfi_set_warning_stop(ctx, gs_note_error(gs_error_syntaxerror), NULL, W_PDF_INVALID_DEFAULTSPACE, "pdfi_setup_DefaultSpaces", NULL)) < 0)
3416
0
                        return code;
3417
0
                }
3418
23
            }
3419
50.3k
            pdfi_countdown(DefaultSpace);
3420
50.3k
            DefaultSpace = NULL;
3421
50.3k
        }
3422
438k
    }
3423
3424
525k
    pdfi_countdown(DefaultSpace);
3425
525k
    pdfi_countdown(resources_dict);
3426
525k
    pdfi_countdown(colorspaces_dict);
3427
525k
    return 0;
3428
525k
}