Coverage Report

Created: 2026-07-24 07:44

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ghostpdl/devices/vector/gdevpdfg.c
Line
Count
Source
1
/* Copyright (C) 2001-2026 Artifex Software, Inc.
2
   All Rights Reserved.
3
4
   This software is provided AS-IS with no warranty, either express or
5
   implied.
6
7
   This software is distributed under license and may not be copied,
8
   modified or distributed except as expressly authorized under the terms
9
   of the license contained in the file LICENSE in this distribution.
10
11
   Refer to licensing information at http://www.artifex.com or contact
12
   Artifex Software, Inc.,  39 Mesa Street, Suite 108A, San Francisco,
13
   CA 94129, USA, for further information.
14
*/
15
16
17
/* Graphics state management for pdfwrite driver */
18
#include "math_.h"
19
#include "string_.h"
20
#include "memory_.h"
21
#include "gx.h"
22
#include "gserrors.h"
23
#include "gsfunc0.h"
24
#include "gsstate.h"
25
#include "gxbitmap.h"   /* for gxhttile.h in gzht.h */
26
#include "gxdht.h"
27
#include "gxfarith.h"   /* for gs_sin/cos_degrees */
28
#include "gxfmap.h"
29
#include "gxht.h"
30
#include "gxgstate.h"
31
#include "gxdcolor.h"
32
#include "gxpcolor.h"
33
#include "gsptype2.h"
34
#include "gzht.h"
35
#include "gdevpdfx.h"
36
#include "gdevpdfg.h"
37
#include "gdevpdfo.h"
38
#include "gscspace.h"
39
#include "gsicc_manage.h"
40
#include "gsicc_cache.h"
41
#include "gsccolor.h"
42
#include "gxcdevn.h"
43
#include "gscie.h"
44
#include "gdevpdtx.h"
45
#include "gdevpdts.h"
46
47
/* ------ Exported by gdevpdfc.c for gdevpdfg.c ------ */
48
int pdf_make_sampled_base_space_function(gx_device_pdf *pdev, gs_function_t **pfn,
49
                                        int nSrcComp, int nDstComp, byte *data);
50
int pdf_delete_sampled_base_space_function(gx_device_pdf *pdev, gs_function_t *pfn);
51
int pdf_make_base_space_function(gx_device_pdf *pdev, gs_function_t **pfn,
52
                                        int ncomp, float *data_low, float *data_high);
53
int pdf_delete_base_space_function(gx_device_pdf *pdev, gs_function_t *pfn);
54
55
/* ---------------- Miscellaneous ---------------- */
56
57
/* Save the viewer's graphic state. */
58
int
59
pdf_save_viewer_state(gx_device_pdf *pdev, stream *s)
60
459k
{
61
459k
    const int i = pdev->vgstack_depth;
62
459k
    int code = 0;
63
64
459k
    if (pdev->vgstack_depth >= pdev->vgstack_size) {
65
2
        pdf_viewer_state *new_vgstack = (pdf_viewer_state *)gs_alloc_bytes(pdev->pdf_memory,
66
2
            (size_t)(pdev->vgstack_size + 5) * sizeof(pdf_viewer_state), "increase graphics state stack size");
67
2
        if (new_vgstack == 0)
68
0
            return_error(gs_error_VMerror);
69
2
        memset(new_vgstack, 0x00, (pdev->vgstack_size + 5) * sizeof(pdf_viewer_state));
70
2
        memcpy(new_vgstack, pdev->vgstack, pdev->vgstack_size * sizeof(pdf_viewer_state));
71
2
        gs_free_object(pdev->pdf_memory, pdev->vgstack, "resize graphics state stack, free old stack)");
72
2
        pdev->vgstack = new_vgstack;
73
2
        pdev->vgstack_size += 5;
74
2
    }
75
76
459k
    pdev->vgstack[i].transfer_ids[0] = pdev->transfer_ids[0];
77
459k
    pdev->vgstack[i].transfer_ids[1] = pdev->transfer_ids[1];
78
459k
    pdev->vgstack[i].transfer_ids[2] = pdev->transfer_ids[2];
79
459k
    pdev->vgstack[i].transfer_ids[3] = pdev->transfer_ids[3];
80
459k
    pdev->vgstack[i].transfer_not_identity = pdev->transfer_not_identity;
81
459k
    pdev->vgstack[i].strokeconstantalpha = pdev->state.strokeconstantalpha;
82
459k
    pdev->vgstack[i].fillconstantalpha = pdev->state.fillconstantalpha;
83
459k
    pdev->vgstack[i].alphaisshape = pdev->state.alphaisshape;
84
459k
    pdev->vgstack[i].blend_mode = pdev->state.blend_mode;
85
459k
    pdev->vgstack[i].halftone_id = pdev->halftone_id;
86
459k
    pdev->vgstack[i].black_generation_id = pdev->black_generation_id;
87
459k
    pdev->vgstack[i].undercolor_removal_id = pdev->undercolor_removal_id;
88
459k
    pdev->vgstack[i].overprint_mode = pdev->state.overprint_mode;
89
459k
    pdev->vgstack[i].smoothness = pdev->state.smoothness;
90
459k
    pdev->vgstack[i].flatness = pdev->state.flatness;
91
459k
    pdev->vgstack[i].text_knockout = pdev->state.text_knockout;
92
459k
    pdev->vgstack[i].fill_overprint = pdev->fill_overprint;
93
459k
    pdev->vgstack[i].stroke_overprint = pdev->stroke_overprint;
94
459k
    pdev->vgstack[i].stroke_adjust = pdev->state.stroke_adjust;
95
459k
    pdev->vgstack[i].fill_used_process_color = pdev->fill_used_process_color;
96
459k
    pdev->vgstack[i].stroke_used_process_color = pdev->stroke_used_process_color;
97
459k
    pdev->vgstack[i].saved_fill_color = pdev->saved_fill_color;
98
459k
    pdev->vgstack[i].saved_stroke_color = pdev->saved_stroke_color;
99
459k
    pdev->vgstack[i].line_params = pdev->state.line_params;
100
459k
    pdev->vgstack[i].line_params.dash.pattern = 0; /* Use pdev->dash_pattern instead. */
101
459k
    pdev->vgstack[i].soft_mask_id = pdev->state.soft_mask_id; /* Use pdev->dash_pattern instead. */
102
459k
    if (pdev->dash_pattern) {
103
8.19k
        if (pdev->vgstack[i].dash_pattern)
104
7.61k
            gs_free_object(pdev->memory->non_gc_memory, pdev->vgstack[i].dash_pattern, "free gstate copy dash");
105
8.19k
        pdev->vgstack[i].dash_pattern = (float *)gs_alloc_bytes(pdev->memory->non_gc_memory, (size_t)pdev->dash_pattern_size * sizeof(float), "gstate copy dash");
106
8.19k
        if (pdev->vgstack[i].dash_pattern == NULL)
107
0
            return_error(gs_error_VMerror);
108
8.19k
        memcpy(pdev->vgstack[i].dash_pattern, pdev->dash_pattern, pdev->dash_pattern_size * sizeof(float));
109
8.19k
        pdev->vgstack[i].dash_pattern_size = pdev->dash_pattern_size;
110
451k
    } else {
111
451k
        if (pdev->vgstack[i].dash_pattern) {
112
270
            gs_free_object(pdev->memory->non_gc_memory, pdev->vgstack[i].dash_pattern, "free gstate copy dash");
113
270
            pdev->vgstack[i].dash_pattern = 0;
114
270
            pdev->vgstack[i].dash_pattern_size = 0;
115
270
        }
116
451k
    }
117
459k
    if (pdev->clip_path != 0) {
118
31.6k
        if (pdev->vgstack[i].clip_path != 0)
119
27.3k
            gx_path_free(pdev->vgstack[i].clip_path, "pdf clip path");
120
121
31.6k
        pdev->vgstack[i].clip_path = gx_path_alloc(pdev->pdf_memory->non_gc_memory, "pdf clip path");
122
31.6k
        if (pdev->vgstack[i].clip_path == 0)
123
0
            return_error(gs_error_VMerror);
124
125
31.6k
        code = gx_path_copy(pdev->clip_path, pdev->vgstack[i].clip_path);
126
31.6k
        if (code < 0)
127
0
            return code;
128
129
31.6k
        pdev->vgstack[i].clip_path_id = pdev->clip_path_id;
130
427k
    } else {
131
427k
        if (pdev->vgstack[i].clip_path != 0) {
132
88
            gx_path_free(pdev->vgstack[i].clip_path, "pdf clip path");
133
88
            pdev->vgstack[i].clip_path = 0;
134
88
            pdev->vgstack[i].clip_path_id = 0;
135
88
        }
136
427k
    }
137
459k
    pdev->vgstack_depth++;
138
459k
    if (s)
139
312k
        stream_puts(s, "q\n");
140
459k
    return 0;
141
459k
}
142
143
/* Load the viewer's graphic state. */
144
static int
145
pdf_load_viewer_state(gx_device_pdf *pdev, pdf_viewer_state *s)
146
800k
{
147
800k
    int code = 0;
148
149
800k
    pdev->transfer_ids[0] = s->transfer_ids[0];
150
800k
    pdev->transfer_ids[1] = s->transfer_ids[1];
151
800k
    pdev->transfer_ids[2] = s->transfer_ids[2];
152
800k
    pdev->transfer_ids[3] = s->transfer_ids[3];
153
800k
    pdev->transfer_not_identity = s->transfer_not_identity;
154
800k
    pdev->state.strokeconstantalpha = s->strokeconstantalpha;
155
800k
    pdev->state.fillconstantalpha = s->fillconstantalpha;
156
800k
    pdev->state.alphaisshape = s->alphaisshape;
157
800k
    pdev->state.blend_mode = s->blend_mode;
158
800k
    pdev->halftone_id = s->halftone_id;
159
800k
    pdev->black_generation_id = s->black_generation_id;
160
800k
    pdev->undercolor_removal_id = s->undercolor_removal_id;
161
800k
    pdev->state.overprint_mode = s->overprint_mode;
162
800k
    pdev->state.smoothness = s->smoothness;
163
800k
    pdev->state.flatness = s->flatness;
164
800k
    pdev->state.text_knockout = s->text_knockout;
165
800k
    pdev->fill_overprint = s->fill_overprint;
166
800k
    pdev->stroke_overprint = s->stroke_overprint;
167
800k
    pdev->state.stroke_adjust = s->stroke_adjust;
168
800k
    pdev->fill_used_process_color = s->fill_used_process_color;
169
800k
    pdev->stroke_used_process_color = s->stroke_used_process_color;
170
800k
    pdev->saved_fill_color = s->saved_fill_color;
171
800k
    pdev->saved_stroke_color = s->saved_stroke_color;
172
800k
    pdev->state.line_params = s->line_params;
173
800k
    pdev->state.soft_mask_id = s->soft_mask_id;
174
800k
    if (s->dash_pattern) {
175
8.19k
        if (pdev->dash_pattern)
176
8.12k
            gs_free_object(pdev->memory->stable_memory, pdev->dash_pattern, "vector free dash pattern");
177
8.19k
        pdev->dash_pattern = (float *)gs_alloc_bytes(pdev->memory->stable_memory, (size_t)s->dash_pattern_size * sizeof(float), "vector allocate dash pattern");
178
8.19k
        if (pdev->dash_pattern == NULL)
179
0
            return_error(gs_error_VMerror);
180
8.19k
        memcpy(pdev->dash_pattern, s->dash_pattern, sizeof(float)*s->dash_pattern_size);
181
8.19k
        pdev->dash_pattern_size  = s->dash_pattern_size;
182
792k
    } else {
183
792k
        if (pdev->dash_pattern) {
184
3.26k
            gs_free_object(pdev->memory->stable_memory, pdev->dash_pattern, "vector free dash pattern");
185
3.26k
            pdev->dash_pattern = 0;
186
3.26k
            pdev->dash_pattern_size = 0;
187
3.26k
        }
188
792k
    }
189
190
800k
    if (pdev->clip_path != 0) {
191
145k
        gx_path_free(pdev->clip_path, "pdf clip path");
192
145k
        pdev->clip_path = 0;
193
145k
        pdev->clip_path_id = 0;
194
145k
    }
195
196
800k
    if (s->clip_path != 0) {
197
31.6k
        pdev->clip_path = gx_path_alloc(pdev->pdf_memory, "pdf clip path");
198
31.6k
        if (pdev->clip_path == 0)
199
0
            return_error(gs_error_VMerror);
200
201
31.6k
        code = gx_path_copy(s->clip_path, pdev->clip_path);
202
31.6k
        if (code < 0)
203
0
            return code;
204
205
31.6k
        pdev->clip_path_id = s->clip_path_id;
206
31.6k
    }
207
208
800k
    return 0;
209
800k
}
210
211
/* Restore the viewer's graphic state. */
212
int
213
pdf_restore_viewer_state(gx_device_pdf *pdev, stream *s)
214
459k
{
215
459k
    int i;
216
217
459k
    if (pdev->vgstack_depth == 0)
218
0
        return 0;
219
220
459k
    i = --pdev->vgstack_depth;
221
222
459k
    if (i < pdev->vgstack_bottom) {
223
11
        if ((pdev->ObjectFilter & FILTERIMAGE) == 0) {
224
11
            return_error(gs_error_unregistered); /* Must not happen. */
225
11
        }
226
0
        else
227
0
            return 0;
228
11
    }
229
459k
    if (s)
230
312k
        stream_puts(s, "Q\n");
231
459k
    return pdf_load_viewer_state(pdev, pdev->vgstack + i);
232
459k
}
233
234
/* Set initial color. */
235
void
236
pdf_set_initial_color(gx_device_pdf * pdev, gx_hl_saved_color *saved_fill_color,
237
                    gx_hl_saved_color *saved_stroke_color,
238
                    bool *fill_used_process_color, bool *stroke_used_process_color)
239
85.9k
{
240
85.9k
    gx_device_color black;
241
242
85.9k
    pdev->black = gx_device_black((gx_device *)pdev);
243
85.9k
    pdev->white = gx_device_white((gx_device *)pdev);
244
85.9k
    set_nonclient_dev_color(&black, pdev->black);
245
85.9k
    gx_hld_save_color(NULL, &black, saved_fill_color);
246
85.9k
    gx_hld_save_color(NULL, &black, saved_stroke_color);
247
85.9k
    *fill_used_process_color = true;
248
85.9k
    *stroke_used_process_color = true;
249
85.9k
}
250
251
/* Prepare intitial values for viewer's graphics state parameters. */
252
static void
253
pdf_viewer_state_from_gs_gstate_aux(pdf_viewer_state *pvs, const gs_gstate *pgs)
254
151k
{
255
151k
    pvs->transfer_not_identity =
256
151k
            (pgs->set_transfer.red   != NULL ? pgs->set_transfer.red->proc   != gs_identity_transfer : 0) * 1 +
257
151k
            (pgs->set_transfer.green != NULL ? pgs->set_transfer.green->proc != gs_identity_transfer : 0) * 2 +
258
151k
            (pgs->set_transfer.blue  != NULL ? pgs->set_transfer.blue->proc  != gs_identity_transfer : 0) * 4 +
259
151k
            (pgs->set_transfer.gray  != NULL ? pgs->set_transfer.gray->proc  != gs_identity_transfer : 0) * 8;
260
151k
    pvs->transfer_ids[0] = (pgs->set_transfer.red != NULL ? pgs->set_transfer.red->id : 0);
261
151k
    pvs->transfer_ids[1] = (pgs->set_transfer.green != NULL ? pgs->set_transfer.green->id : 0);
262
151k
    pvs->transfer_ids[2] = (pgs->set_transfer.blue != NULL ? pgs->set_transfer.blue->id : 0);
263
151k
    pvs->transfer_ids[3] = (pgs->set_transfer.gray != NULL ? pgs->set_transfer.gray->id : 0);
264
151k
    pvs->fillconstantalpha = pgs->fillconstantalpha;
265
151k
    pvs->strokeconstantalpha = pgs->strokeconstantalpha;
266
151k
    pvs->alphaisshape = pgs->alphaisshape;
267
151k
    pvs->blend_mode = pgs->blend_mode;
268
151k
    pvs->halftone_id = (pgs->dev_ht[HT_OBJTYPE_DEFAULT] != NULL ? pgs->dev_ht[HT_OBJTYPE_DEFAULT]->id : 0);
269
151k
    pvs->black_generation_id = (pgs->black_generation != NULL ? pgs->black_generation->id : 0);
270
151k
    pvs->undercolor_removal_id = (pgs->undercolor_removal != NULL ? pgs->undercolor_removal->id : 0);
271
151k
    pvs->overprint_mode = 0;
272
151k
    pvs->flatness = pgs->flatness;
273
151k
    pvs->smoothness = pgs->smoothness;
274
151k
    pvs->text_knockout = pgs->text_knockout;
275
151k
    pvs->fill_overprint = false;
276
151k
    pvs->stroke_overprint = false;
277
    /* The PDF Reference says that the default is 'false' but experiments show (bug #706407)
278
     * that Acrobat defaults to true. Also Ghostscript, at low resolution at least, defaults
279
     * to true as well. By setting the initial value to neither true nor false we can ensure
280
     * that any input file which sets it, whether true or false, will cause it not to match
281
     * the initial value, so we will write it out, thus preserving the value, no matter what
282
     * the default.
283
     */
284
151k
    pvs->stroke_adjust = -1;
285
151k
    pvs->line_params.half_width = 0.5;
286
151k
    pvs->line_params.start_cap = 0;
287
151k
    pvs->line_params.end_cap = 0;
288
151k
    pvs->line_params.dash_cap = 0;
289
151k
    pvs->line_params.join = 0;
290
151k
    pvs->line_params.curve_join = 0;
291
151k
    pvs->line_params.miter_limit = 10.0;
292
151k
    pvs->line_params.miter_check = 0;
293
151k
    pvs->line_params.dot_length = pgs->line_params.dot_length;
294
151k
    pvs->line_params.dot_length_absolute = pgs->line_params.dot_length_absolute;
295
151k
    pvs->line_params.dot_orientation = pgs->line_params.dot_orientation;
296
151k
    memset(&pvs->line_params.dash, 0 , sizeof(pvs->line_params.dash));
297
151k
    pvs->dash_pattern = 0;
298
151k
    pvs->dash_pattern_size = 0;
299
151k
    pvs->soft_mask_id = pgs->soft_mask_id;
300
151k
}
301
302
/* Copy viewer state from images state. */
303
void
304
pdf_viewer_state_from_gs_gstate(gx_device_pdf * pdev,
305
        const gs_gstate *pgs, const gx_device_color *pdevc)
306
108k
{
307
108k
    pdf_viewer_state vs;
308
309
108k
    pdf_viewer_state_from_gs_gstate_aux(&vs, pgs);
310
    /* pdf_viewer_state_from_gs_gstate_aux always returns
311
     * vs with a NULL dash pattern. */
312
108k
    gx_hld_save_color(pgs, pdevc, &vs.saved_fill_color);
313
108k
    gx_hld_save_color(pgs, pdevc, &vs.saved_stroke_color);
314
108k
    vs.fill_used_process_color = 0;
315
108k
    vs.stroke_used_process_color = 0;
316
108k
    vs.clip_path = 0;
317
108k
    vs.clip_path_id = 0;
318
    /* pdf_load_viewer_state should never fail, as vs has a NULL
319
     * dash pattern, and therefore will not allocate. */
320
108k
    (void)pdf_load_viewer_state(pdev, &vs);
321
108k
}
322
323
/* Prepare intitial values for viewer's graphics state parameters. */
324
void
325
pdf_prepare_initial_viewer_state(gx_device_pdf * pdev, const gs_gstate *pgs)
326
42.9k
{
327
    /* Parameter values, which are specified in PDF spec, are set here.
328
     * Parameter values, which are specified in PDF spec as "installation dependent",
329
     * are set here to intial values used with PS interpreter.
330
     * This allows to write differences to the output file
331
     * and skip initial values.
332
     */
333
334
42.9k
    pdf_set_initial_color(pdev, &pdev->vg_initial.saved_fill_color, &pdev->vg_initial.saved_stroke_color,
335
42.9k
            &pdev->vg_initial.fill_used_process_color, &pdev->vg_initial.stroke_used_process_color);
336
42.9k
    pdf_viewer_state_from_gs_gstate_aux(&pdev->vg_initial, pgs);
337
42.9k
    pdev->vg_initial_set = true;
338
    /*
339
     * Some parameters listed in PDF spec are missed here :
340
     * text state - it is initialized per page.
341
     * rendering intent - not sure why, fixme.
342
     */
343
42.9k
}
344
345
/* Reset the graphics state parameters to initial values. */
346
/* Used if pdf_prepare_initial_viewer_state was not callad. */
347
static void
348
pdf_reset_graphics_old(gx_device_pdf * pdev)
349
42.9k
{
350
351
42.9k
    pdf_set_initial_color(pdev, &pdev->saved_fill_color, &pdev->saved_stroke_color,
352
42.9k
                                &pdev->fill_used_process_color, &pdev->stroke_used_process_color);
353
42.9k
    pdev->state.flatness = -1;
354
42.9k
    {
355
42.9k
        static const gx_line_params lp_initial = {
356
42.9k
            gx_line_params_initial
357
42.9k
        };
358
359
42.9k
        pdev->state.line_params = lp_initial;
360
42.9k
    }
361
42.9k
    pdev->fill_overprint = false;
362
42.9k
    pdev->stroke_overprint = false;
363
42.9k
    pdev->remap_fill_color = false;
364
42.9k
    pdev->remap_stroke_color = false;
365
42.9k
    pdf_reset_text(pdev);
366
42.9k
}
367
368
/* Reset the graphics state parameters to initial values. */
369
void
370
pdf_reset_graphics(gx_device_pdf * pdev)
371
274k
{
372
274k
    int soft_mask_id = pdev->state.soft_mask_id;
373
374
274k
    if (pdev->vg_initial_set)
375
        /* The following call cannot fail as vg_initial has no
376
         * dash pattern, and so no allocations are required. */
377
231k
        (void)pdf_load_viewer_state(pdev, &pdev->vg_initial);
378
42.9k
    else
379
42.9k
        pdf_reset_graphics_old(pdev);
380
274k
    pdf_reset_text(pdev);
381
382
    /* Not obvious, we want to preserve any extant soft mask, not reset it */
383
274k
    pdev->state.soft_mask_id = soft_mask_id;
384
274k
}
385
386
/* Write client color. */
387
static int
388
pdf_write_ccolor(gx_device_pdf * pdev, const gs_gstate * pgs,
389
                const gs_client_color *pcc)
390
854k
{
391
854k
    int i, n = gx_hld_get_number_color_components(pgs);
392
393
854k
    pprintg1(pdev->strm, "%g", psdf_round(pcc->paint.values[0], 255, 8));
394
2.03M
    for (i = 1; i < n; i++) {
395
1.18M
        pprintg1(pdev->strm, " %g", psdf_round(pcc->paint.values[i], 255, 8));
396
1.18M
    }
397
854k
    return 0;
398
854k
}
399
400
static inline bool
401
is_cspace_allowed_in_strategy(gx_device_pdf * pdev, gs_color_space_index csi)
402
6.91k
{
403
6.91k
    if (pdev->params.ColorConversionStrategy == ccs_CMYK &&
404
0
            csi != gs_color_space_index_DeviceCMYK &&
405
0
            csi != gs_color_space_index_DeviceGray)
406
0
        return false;
407
6.91k
    if (pdev->params.ColorConversionStrategy == ccs_sRGB &&
408
0
            csi != gs_color_space_index_DeviceRGB &&
409
0
            csi != gs_color_space_index_DeviceGray)
410
0
        return false;
411
6.91k
    if (pdev->params.ColorConversionStrategy == ccs_RGB &&
412
0
            csi != gs_color_space_index_DeviceRGB &&
413
0
            csi != gs_color_space_index_DeviceGray)
414
0
        return false;
415
6.91k
    if (pdev->params.ColorConversionStrategy == ccs_Gray &&
416
0
            csi != gs_color_space_index_DeviceGray)
417
0
        return false;
418
6.91k
    return true;
419
6.91k
}
420
421
static inline bool
422
is_pattern2_allowed_in_strategy(gx_device_pdf * pdev, const gx_drawing_color *pdc)
423
6.91k
{
424
6.91k
    const gs_color_space *pcs2 = gx_dc_pattern2_get_color_space(pdc);
425
6.91k
    gs_color_space_index csi = gs_color_space_get_index(pcs2);
426
427
6.91k
    if (csi == gs_color_space_index_ICC)
428
2.63k
        csi = gsicc_get_default_type(pcs2->cmm_icc_profile_data);
429
430
6.91k
    return is_cspace_allowed_in_strategy(pdev, csi);
431
6.91k
}
432
433
434
static int apply_transfer_gray(gx_device_pdf * pdev, const gs_gstate * pgs, gs_client_color *pcc, gs_client_color *cc)
435
0
{
436
0
    unsigned short psrc[GS_CLIENT_COLOR_MAX_COMPONENTS];
437
0
    frac conc[GS_CLIENT_COLOR_MAX_COMPONENTS];
438
0
    gx_device_color dc;
439
0
    const gs_color_space *pcs = gs_currentcolorspace_inline(pgs);
440
0
    int code, color_index;
441
442
0
    color_index = pdev->pcm_color_info_index;
443
0
    pdf_set_process_color_model(pdev, 0);
444
0
    psrc[0] = (unsigned short) (pcc->paint.values[0]*65535.0);;
445
0
    conc[0] = ushort2frac(psrc[0]);
446
447
0
    code = gx_remap_concrete_DGray(pcs, (const frac *)&conc, &dc, pgs, (gx_device *)pdev, gs_color_select_texture, NULL);
448
0
    if (code < 0)
449
0
        return code;
450
451
0
    cc->paint.values[0] = (dc.colors.pure & 0xff) / 255.0;
452
0
    pdf_set_process_color_model(pdev, color_index);
453
0
    return 0;
454
0
}
455
456
static int apply_transfer_rgb(gx_device_pdf * pdev, const gs_gstate * pgs, gs_client_color *pcc, gs_client_color *cc)
457
6
{
458
6
    unsigned short psrc[GS_CLIENT_COLOR_MAX_COMPONENTS];
459
6
    frac conc[GS_CLIENT_COLOR_MAX_COMPONENTS];
460
6
    gx_device_color dc;
461
6
    const gs_color_space *pcs = gs_currentcolorspace_inline(pgs);
462
6
    int code, i, color_index;
463
464
6
    color_index = pdev->pcm_color_info_index;
465
6
    pdf_set_process_color_model(pdev, 1);
466
24
    for (i=0;i<3;i++) {
467
18
        psrc[i] = (unsigned short) (pcc->paint.values[i]*65535.0);;
468
18
        conc[i] = ushort2frac(psrc[i]);
469
18
    }
470
6
    code = gx_remap_concrete_DRGB(pcs, (const frac *)&conc, &dc, pgs, (gx_device *)pdev, gs_color_select_texture, NULL);
471
6
    if (code < 0)
472
0
        return code;
473
474
6
    cc->paint.values[0] = ((dc.colors.pure & 0xff0000) >> 16) / 255.0;
475
6
    cc->paint.values[1] = ((dc.colors.pure & 0xff00) >> 8) / 255.0;
476
6
    cc->paint.values[2] = (dc.colors.pure & 0xff) / 255.0;
477
6
    pdf_set_process_color_model(pdev, color_index);
478
6
    return 0;
479
6
}
480
481
static int apply_transfer_cmyk(gx_device_pdf * pdev, const gs_gstate * pgs, gs_client_color *pcc, gs_client_color *cc)
482
0
{
483
0
    unsigned short psrc[GS_CLIENT_COLOR_MAX_COMPONENTS];
484
0
    frac conc[GS_CLIENT_COLOR_MAX_COMPONENTS];
485
0
    gx_device_color dc;
486
0
    const gs_color_space *pcs = gs_currentcolorspace_inline(pgs);
487
0
    int code, i, color_index;
488
489
0
    color_index = pdev->pcm_color_info_index;
490
0
    pdf_set_process_color_model(pdev, 2);
491
0
    for (i=0;i<4;i++) {
492
0
        psrc[i] = (unsigned short) (pcc->paint.values[i]*65535.0);;
493
0
        conc[i] = ushort2frac(psrc[i]);
494
0
    }
495
0
    code = gx_remap_concrete_DCMYK(pcs, (const frac *)&conc, &dc, pgs, (gx_device *)pdev, gs_color_select_texture, NULL);
496
0
    if (code < 0)
497
0
        return code;
498
499
0
    cc->paint.values[0] = ((dc.colors.pure & 0xff000000) >> 24) / 255.0;
500
0
    cc->paint.values[1] = ((dc.colors.pure & 0xff0000) >> 16) / 255.0;
501
0
    cc->paint.values[2] = ((dc.colors.pure & 0xff00) >> 8) / 255.0;
502
0
    cc->paint.values[3] = (dc.colors.pure & 0xff) / 255.0;
503
0
    pdf_set_process_color_model(pdev, color_index);
504
0
    return 0;
505
0
}
506
507
static int write_color_as_process(gx_device_pdf * pdev, const gs_gstate * pgs, const gs_color_space *pcs,
508
                        const gx_drawing_color *pdc, bool *used_process_color,
509
                        const psdf_set_color_commands_t *ppscc, gs_client_color *pcc)
510
34.0k
{
511
34.0k
    int code, i;
512
34.0k
    unsigned char j;
513
34.0k
    frac conc[GS_CLIENT_COLOR_MAX_COMPONENTS];
514
34.0k
    gs_color_space_index csi, csi2;
515
34.0k
    gs_color_space *pcs2 = (gs_color_space *)pcs;
516
34.0k
    gx_drawing_color dc;
517
34.0k
    int num_des_comps;
518
34.0k
    cmm_dev_profile_t *dev_profile;
519
520
34.0k
    dc.type = gx_dc_type_pure;
521
34.0k
    dc.colors.pure = 0;
522
34.0k
    csi = gs_color_space_get_index(pcs);
523
524
34.0k
    if (csi == gs_color_space_index_ICC) {
525
34.0k
        csi = gsicc_get_default_type(pcs->cmm_icc_profile_data);
526
34.0k
    }
527
528
34.0k
    if (csi == gs_color_space_index_Indexed ||
529
34.0k
        csi == gs_color_space_index_DeviceN ||
530
34.0k
        csi == gs_color_space_index_Separation) {
531
0
        const char *command = NULL;
532
533
0
        *used_process_color = true;
534
535
0
        memset (&conc, 0x00, sizeof(frac) * GS_CLIENT_COLOR_MAX_COMPONENTS);
536
0
        pcs->type->concretize_color(pcc, pcs, conc, pgs, (gx_device *)pdev);
537
538
0
        do{
539
0
            pcs2 = pcs2->base_space;
540
0
            csi2 = gs_color_space_get_index(pcs2);
541
0
        } while(csi2 != gs_color_space_index_ICC && pcs2->base_space);
542
0
        csi2 = gs_color_space_get_index(pcs2);
543
544
0
        switch (csi2) {
545
0
            case gs_color_space_index_DeviceGray:
546
0
            case gs_color_space_index_DeviceRGB:
547
0
            case gs_color_space_index_DeviceCMYK:
548
0
                switch (pdev->color_info.num_components) {
549
0
                    case 1:
550
0
                        command = ppscc->setgray;
551
0
                        break;
552
0
                    case 3:
553
0
                        command = ppscc->setrgbcolor;
554
0
                        break;
555
0
                    case 4:
556
0
                        command = ppscc->setcmykcolor;
557
0
                        break;
558
0
                    default:
559
                        /* Can't happen since we already check the colour space */
560
0
          return_error(gs_error_rangecheck);
561
0
                }
562
0
                pprintg1(pdev->strm, "%g", psdf_round(frac2float(conc[0]), 255, 8));
563
0
                for (j = 1; j < pdev->color_info.num_components; j++) {
564
0
                    pprintg1(pdev->strm, " %g", psdf_round(frac2float(conc[j]), 255, 8));
565
0
                }
566
0
                pprints1(pdev->strm, " %s\n", command);
567
0
                return 0;
568
0
                break;
569
0
            case gs_color_space_index_CIEDEFG:
570
0
            case gs_color_space_index_CIEDEF:
571
0
            case gs_color_space_index_CIEABC:
572
0
            case gs_color_space_index_CIEA:
573
0
            case gs_color_space_index_ICC:
574
0
                code = dev_proc((gx_device *)pdev, get_profile)((gx_device *)pdev, &dev_profile);
575
0
                if (code < 0)
576
0
                    return code;
577
0
                num_des_comps = gsicc_get_device_profile_comps(dev_profile);
578
0
                for (i = 0;i < num_des_comps;i++)
579
0
                    dc.colors.pure = (dc.colors.pure << 8) + (int)(frac2float(conc[i]) * 255);
580
0
                code = psdf_set_color((gx_device_vector *)pdev, &dc, ppscc);
581
0
                return code;
582
0
                break;
583
0
            default:    /* can't happen, simply silences compiler warnings */
584
0
                break;
585
0
        }
586
34.0k
    } else {
587
34.0k
        if (csi >= gs_color_space_index_CIEDEFG &&
588
34.0k
            csi <= gs_color_space_index_CIEA) {
589
0
                memset (&conc, 0x00, sizeof(frac) * GS_CLIENT_COLOR_MAX_COMPONENTS);
590
0
                pcs->type->concretize_color(pcc, pcs, conc, pgs, (gx_device *)pdev);
591
0
                code = dev_proc((gx_device *)pdev, get_profile)((gx_device *)pdev, &dev_profile);
592
0
                if (code < 0)
593
0
                    return code;
594
0
                num_des_comps = gsicc_get_device_profile_comps(dev_profile);
595
0
                for (i = 0;i < num_des_comps;i++)
596
0
                    dc.colors.pure = (dc.colors.pure << 8) + (int)(frac2float(conc[i]) * 255);
597
0
                code = psdf_set_color((gx_device_vector *)pdev, &dc, ppscc);
598
0
                *used_process_color = true;
599
0
                return code;
600
34.0k
        } else {
601
34.0k
            memset (&conc, 0x00, sizeof(frac) * GS_CLIENT_COLOR_MAX_COMPONENTS);
602
            /* Special case handling for Lab spaces */
603
34.0k
            if (pcs->cmm_icc_profile_data->data_cs == gsCIELAB || pcs->cmm_icc_profile_data->islab) {
604
244
                gs_client_color cc;
605
                /* Get the data in a form that is concrete for the CMM */
606
244
                cc.paint.values[0] = pcc->paint.values[0] / 100.0;
607
244
                cc.paint.values[1] = (pcc->paint.values[1]+128)/255.0;
608
244
                cc.paint.values[2] = (pcc->paint.values[2]+128)/255.0;
609
244
                pcs->type->concretize_color((const gs_client_color *)&cc, pcs, conc, pgs, (gx_device *)pdev);
610
33.8k
            } else {
611
33.8k
                if (pdev->params.TransferFunctionInfo == tfi_Apply) {
612
                    /* Apply transfer functions */
613
0
                    switch(csi) {
614
0
                        case gs_color_space_index_DeviceGray:
615
0
                        case gs_color_space_index_DeviceRGB:
616
0
                        case gs_color_space_index_DeviceCMYK:
617
0
                            (*pcs->type->remap_color)((const gs_client_color *)pcc, pcs, (gx_drawing_color *)pdc, pgs, (gx_device *)pdev, 0);
618
0
                            code = psdf_set_color((gx_device_vector *)pdev, pdc, ppscc);
619
0
                            return code;
620
0
                            break;
621
0
                        default:
622
0
                            pcs->type->concretize_color(pcc, pcs, conc, pgs, (gx_device *)pdev);
623
0
                            break;
624
0
                    }
625
33.8k
                } else {
626
33.8k
                    pcs->type->concretize_color(pcc, pcs, conc, pgs, (gx_device *)pdev);
627
33.8k
                }
628
33.8k
            }
629
34.0k
            code = dev_proc((gx_device *)pdev, get_profile)((gx_device *)pdev, &dev_profile);
630
34.0k
            if (code < 0)
631
0
                return code;
632
34.0k
            num_des_comps = gsicc_get_device_profile_comps(dev_profile);
633
136k
            for (i = 0;i < num_des_comps;i++)
634
102k
                dc.colors.pure = (dc.colors.pure << 8) + (int)(frac2float(conc[i]) * 255);
635
34.0k
            code = psdf_set_color((gx_device_vector *)pdev, &dc, ppscc);
636
34.0k
            return code;
637
34.0k
        }
638
34.0k
    }
639
34.0k
    return_error(gs_error_unknownerror);
640
34.0k
}
641
642
static int write_color_unchanged(gx_device_pdf * pdev, const gs_gstate * pgs,
643
                          gs_client_color *pcc, gx_hl_saved_color *current,
644
                          gx_hl_saved_color * psc, const psdf_set_color_commands_t *ppscc,
645
                          bool *used_process_color, const gs_color_space *pcs,
646
                          const gx_drawing_color *pdc)
647
854k
{
648
854k
    gs_color_space_index csi, csi2;
649
854k
    int code, i;
650
854k
    const char *command = NULL;
651
854k
    gs_range_t *ranges = 0;
652
854k
    gs_client_color cc;
653
654
655
854k
    csi = csi2 = gs_color_space_get_index(pcs);
656
854k
    if (csi == gs_color_space_index_ICC) {
657
835k
        csi2 = gsicc_get_default_type(pcs->cmm_icc_profile_data);
658
835k
    }
659
660
854k
    switch (csi2) {
661
274k
        case gs_color_space_index_DeviceGray:
662
274k
            command = ppscc->setgray;
663
274k
            if (pdev->params.TransferFunctionInfo == tfi_Apply) {
664
0
                code = apply_transfer_gray(pdev, pgs, pcc, &cc);
665
0
                if (code < 0)
666
0
                    return_error(code);
667
274k
            } else {
668
274k
                cc.paint.values[0] = pcc->paint.values[0];
669
274k
            }
670
274k
            code = pdf_write_ccolor(pdev, pgs, &cc);
671
274k
            if (code < 0)
672
0
                return code;
673
274k
            pprints1(pdev->strm, " %s\n", command);
674
274k
            break;
675
470k
        case gs_color_space_index_DeviceRGB:
676
470k
            command = ppscc->setrgbcolor;
677
470k
            if (pdev->params.TransferFunctionInfo == tfi_Apply) {
678
6
                code = apply_transfer_rgb(pdev, pgs, pcc, &cc);
679
6
                if (code < 0)
680
0
                    return_error(code);
681
470k
            } else {
682
1.88M
                for (i=0;i< 3;i++)
683
1.41M
                    cc.paint.values[i] = pcc->paint.values[i];
684
470k
            }
685
470k
            code = pdf_write_ccolor(pdev, pgs, &cc);
686
470k
            if (code < 0)
687
0
                return code;
688
470k
            pprints1(pdev->strm, " %s\n", command);
689
470k
            break;
690
66.2k
        case gs_color_space_index_DeviceCMYK:
691
66.2k
            command = ppscc->setcmykcolor;
692
66.2k
            if (pdev->params.TransferFunctionInfo == tfi_Apply) {
693
0
                code = apply_transfer_cmyk(pdev, pgs, pcc, &cc);
694
0
                if (code < 0)
695
0
                    return_error(code);
696
66.2k
            } else {
697
331k
                for (i=0;i< 4;i++)
698
265k
                    cc.paint.values[i] = pcc->paint.values[i];
699
66.2k
            }
700
66.2k
            code = pdf_write_ccolor(pdev, pgs, &cc);
701
66.2k
            if (code < 0)
702
0
                return code;
703
66.2k
            pprints1(pdev->strm, " %s\n", command);
704
66.2k
            break;
705
43.9k
        default:
706
43.9k
            if (!gx_hld_saved_color_same_cspace(current, psc) || (csi2 >= gs_color_space_index_CIEDEFG && csi2 <= gs_color_space_index_CIEA)) {
707
28.9k
                cos_value_t cs_value;
708
709
28.9k
                code = pdf_color_space_named(pdev, pgs, &cs_value, (const gs_range_t **)&ranges, pcs,
710
28.9k
                                &pdf_color_space_names, true, NULL, 0, false);
711
                /* fixme : creates redundant PDF objects. */
712
28.9k
                if (code == gs_error_rangecheck) {
713
50
                    *used_process_color = true;
714
50
                    if (pdev->ForOPDFRead) {
715
                    /* The color space can't write to PDF. This should never happen */
716
50
                    code = psdf_set_color((gx_device_vector *)pdev, pdc, ppscc);
717
50
                    } else {
718
0
                    code = write_color_as_process(pdev, pgs, pcs, pdc, used_process_color, ppscc, pcc);
719
0
                    }
720
50
                    return code;
721
50
                }
722
28.9k
                if (code < 0)
723
0
                    return code;
724
28.9k
                code = cos_value_write(&cs_value, pdev);
725
28.9k
                if (code < 0)
726
0
                    return code;
727
28.9k
                pprints1(pdev->strm, " %s\n", ppscc->setcolorspace);
728
28.9k
                if (ranges && (csi2 >= gs_color_space_index_CIEDEFG && csi2 <= gs_color_space_index_CIEA)) {
729
0
                    gs_client_color dcc = *pcc;
730
0
                    switch (csi2) {
731
0
                        case gs_color_space_index_CIEDEFG:
732
0
                            rescale_cie_color(ranges, 4, pcc, &dcc);
733
0
                            break;
734
0
                        case gs_color_space_index_CIEDEF:
735
0
                            rescale_cie_color(ranges, 3, pcc, &dcc);
736
0
                            break;
737
0
                        case gs_color_space_index_CIEABC:
738
0
                            rescale_cie_color(ranges, 3, pcc, &dcc);
739
0
                            break;
740
0
                        case gs_color_space_index_CIEA:
741
0
                            rescale_cie_color(ranges, 1, pcc, &dcc);
742
0
                            break;
743
0
                        default:
744
                            /* can't happen but silences compiler warnings */
745
0
                            break;
746
0
                    }
747
0
                    code = pdf_write_ccolor(pdev, pgs, &dcc);
748
28.9k
                } else {
749
28.9k
                    code = pdf_write_ccolor(pdev, pgs, pcc);
750
28.9k
                }
751
28.9k
                *used_process_color = false;
752
28.9k
                if (code < 0)
753
0
                    return code;
754
28.9k
                pprints1(pdev->strm, " %s\n", ppscc->setcolorn);
755
28.9k
            } else if (*used_process_color) {
756
18
                    *used_process_color = true;
757
18
                    if (pdev->ForOPDFRead) {
758
                    /* The color space can't write to PDF. This should never happen */
759
18
                    code = psdf_set_color((gx_device_vector *)pdev, pdc, ppscc);
760
18
                    } else {
761
0
                    code = write_color_as_process(pdev, pgs, pcs, pdc, used_process_color, ppscc, pcc);
762
0
                    }
763
18
                    return code;
764
18
            }
765
14.9k
            else {
766
14.9k
                code = pdf_write_ccolor(pdev, pgs, pcc);
767
14.9k
                if (code < 0)
768
0
                    return code;
769
14.9k
                pprints1(pdev->strm, " %s\n", ppscc->setcolorn);
770
14.9k
            }
771
43.9k
            break;
772
854k
    }
773
854k
    *used_process_color = false;
774
775
854k
    return 0;
776
854k
}
777
778
static int write_color_as_process_ICC(gx_device_pdf * pdev, const gs_gstate * pgs, const gs_color_space *pcs,
779
                        const gx_drawing_color *pdc, gx_hl_saved_color * psc, bool *used_process_color,
780
                        const psdf_set_color_commands_t *ppscc, gs_client_color *pcc,
781
                        gx_hl_saved_color *current)
782
0
{
783
0
    int i, code;
784
0
    cos_value_t cs_value;
785
786
0
    if (!gx_hld_saved_color_same_cspace(current, psc)) {
787
0
        code = pdf_color_space_named(pdev, pgs, &cs_value, NULL, pcs,
788
0
                        &pdf_color_space_names, true, NULL, 0, true);
789
        /* fixme : creates redundant PDF objects. */
790
0
        if (code == gs_error_rangecheck) {
791
            /* The color space can't write to PDF. This should never happen */
792
0
            return write_color_as_process(pdev, pgs, pcs, pdc, used_process_color, ppscc, pcc);
793
0
        }
794
0
        if (code < 0)
795
0
            return code;
796
0
        code = cos_value_write(&cs_value, pdev);
797
0
        if (code < 0)
798
0
            return code;
799
0
        pprints1(pdev->strm, " %s\n", ppscc->setcolorspace);
800
0
        *used_process_color = false;
801
0
        pprintg1(pdev->strm, "%g", psdf_round(pcc->paint.values[0], 255, 8));
802
0
        for (i = 1; i < pcs->type->num_components(pcs); i++) {
803
0
            pprintg1(pdev->strm, " %g", psdf_round(pcc->paint.values[i], 255, 8));
804
0
        }
805
0
        pprints1(pdev->strm, " %s\n", ppscc->setcolorn);
806
0
    } else {
807
0
        *used_process_color = false;
808
0
        pprintg1(pdev->strm, "%g", psdf_round(pcc->paint.values[0], 255, 8));
809
0
        for (i = 1; i < pcs->type->num_components(pcs); i++) {
810
0
            pprintg1(pdev->strm, " %g", psdf_round(pcc->paint.values[i], 255, 8));
811
0
        }
812
0
        pprints1(pdev->strm, " %s\n", ppscc->setcolorn);
813
0
    }
814
0
    return 0;
815
0
}
816
817
int convert_DeviceN_alternate(gx_device_pdf * pdev, const gs_gstate * pgs, const gs_color_space *pcs,
818
                        const gx_drawing_color *pdc, bool *used_process_color,
819
                        const psdf_set_color_commands_t *ppscc, gs_client_color *pcc, cos_value_t *pvalue, bool by_name)
820
0
{
821
0
    gs_color_space_index csi;
822
0
    gs_function_t *new_pfn = 0;
823
0
    int code, i, samples=0, loop;
824
0
    cos_array_t *pca, *pca1;
825
0
    cos_value_t v;
826
0
    byte *data_buff;
827
0
    pdf_resource_t *pres = NULL;
828
0
    gs_color_space *pcs_save = NULL;
829
830
0
    csi = gs_color_space_get_index(pcs);
831
0
    if (csi == gs_color_space_index_Indexed) {
832
0
        pcs_save = (gs_color_space *)pcs;
833
0
        pcs = pcs->base_space;
834
0
    }
835
836
0
    if (pdev->PDFA != 0) {
837
0
        for (i = 0; i < pcs->params.device_n.num_components; ++i) {
838
0
            if (utf8_check((unsigned char *)pcs->params.device_n.names[i]) != NULL) {
839
0
                switch(pdev->PDFACompatibilityPolicy) {
840
0
                    case 0:
841
0
                        emprintf(pdev->memory,
842
0
                             "Ink name in Separation space not valid UTF-8, reverting to normal PDF output.\n");
843
0
                        pdev->AbortPDFAX = true;
844
0
                        pdev->PDFA = 0;
845
0
                        break;
846
0
                    case 1:
847
0
                        emprintf(pdev->memory,
848
0
                             "Ink name in Separation space not valid UTF-8, reverting to normal PDF output.\n");
849
0
                        pdev->AbortPDFAX = true;
850
0
                        pdev->PDFA = 0;
851
0
                        break;
852
0
                    default:
853
0
                    case 2:
854
0
                        emprintf(pdev->memory,
855
0
                             "Ink name in Separation space not valid UTF-8, aborting.\n");
856
0
                        return_error(gs_error_limitcheck);
857
0
                        break;
858
0
                }
859
0
                break;
860
0
            }
861
0
        }
862
0
    }
863
0
    pca = cos_array_alloc(pdev, "pdf_color_space");
864
0
    if (pca == 0)
865
0
        return_error(gs_error_VMerror);
866
867
0
    samples = (unsigned int)pow(2, pcs->params.device_n.num_components);
868
0
    data_buff = gs_alloc_bytes(pdev->memory, (unsigned int)pdev->color_info.num_components * (size_t)samples, "Convert DeviceN");
869
0
    if (data_buff == 0) {
870
0
        COS_FREE(pca, "convert DeviceN");
871
0
        return_error(gs_error_VMerror);
872
0
    }
873
0
    memset(data_buff, 0x00, (unsigned int)pdev->color_info.num_components * samples);
874
875
0
    {
876
0
        frac conc[GS_CLIENT_COLOR_MAX_COMPONENTS];
877
0
        gs_client_color cc, cc1;
878
0
        unsigned char j;
879
0
        gs_color_space *icc_space = (gs_color_space *)pcs;
880
0
        gs_color_space *devicen_space = (gs_color_space *)pcs;
881
0
        gs_color_space_index csi2;
882
883
0
        csi = gs_color_space_get_index(pcs);
884
0
        if (csi == gs_color_space_index_Indexed)
885
0
            devicen_space = pcs->base_space;
886
887
0
        do{
888
0
            icc_space = icc_space->base_space;
889
0
            csi2 = gs_color_space_get_index(icc_space);
890
0
        } while(csi2 != gs_color_space_index_ICC && icc_space->base_space);
891
892
0
        memset(&cc.paint.values, 0x00, GS_CLIENT_COLOR_MAX_COMPONENTS);
893
894
0
        devicen_space->params.device_n.use_alt_cspace = true;
895
896
0
        for (loop=0;loop < samples;loop++) {
897
0
            if (loop > 0) {
898
0
                if (cc.paint.values[0] == 0)
899
0
                    cc.paint.values[0] = 1;
900
0
                else {
901
0
                    int cascade = 0;
902
0
                    while (cascade < pcs->params.device_n.num_components && cc.paint.values[cascade] == 1) {
903
0
                        cc.paint.values[cascade++] = 0;
904
0
                    }
905
0
                    cc.paint.values[cascade] = 1;
906
0
                }
907
0
            }
908
909
910
0
            memset (&conc, 0x00, sizeof(frac) * GS_CLIENT_COLOR_MAX_COMPONENTS);
911
0
            devicen_space->type->concretize_color(&cc, devicen_space, conc, pgs, (gx_device *)pdev);
912
913
0
            for (i = 0;i < pdev->color_info.num_components;i++)
914
0
                cc1.paint.values[i] = frac2float(conc[i]);
915
916
0
            if (pdev->params.TransferFunctionInfo == tfi_Apply) {
917
0
                switch (pdev->params.ColorConversionStrategy) {
918
0
                    case ccs_Gray:
919
0
                        code = apply_transfer_gray(pdev, pgs, &cc1, &cc1);
920
0
                        break;
921
0
                    case ccs_sRGB:
922
0
                    case ccs_RGB:
923
0
                        code = apply_transfer_rgb(pdev, pgs, &cc1, &cc1);
924
0
                        break;
925
0
                    case ccs_CMYK:
926
0
                        code = apply_transfer_cmyk(pdev, pgs, &cc1, &cc1);
927
0
                        break;
928
0
                    default:
929
0
                        code = gs_error_rangecheck;
930
0
                        break;
931
0
                }
932
0
                if (code < 0) {
933
0
                    COS_FREE(pca, "pdf_color_space");
934
0
                    return code;
935
0
                }
936
0
            }
937
0
            for (j = 0;j < pdev->color_info.num_components;j++)
938
0
                data_buff[(loop * pdev->color_info.num_components) + j] = (int)(cc1.paint.values[j] * 255);
939
0
        }
940
0
    }
941
942
0
    switch(pdev->params.ColorConversionStrategy) {
943
0
        case ccs_Gray:
944
0
            code = pdf_make_sampled_base_space_function(pdev, &new_pfn, pcs->params.device_n.num_components, 1, data_buff);
945
0
            break;
946
0
        case ccs_sRGB:
947
0
        case ccs_RGB:
948
0
            code = pdf_make_sampled_base_space_function(pdev, &new_pfn, pcs->params.device_n.num_components, 3, data_buff);
949
0
            break;
950
0
        case ccs_CMYK:
951
0
            code = pdf_make_sampled_base_space_function(pdev, &new_pfn, pcs->params.device_n.num_components, 4, data_buff);
952
0
            break;
953
0
        default:
954
0
            code = gs_error_rangecheck;
955
0
            break;
956
0
    }
957
0
    gs_free_object(pdev->memory, data_buff, "Convert DeviceN");
958
0
    if (code < 0) {
959
0
        COS_FREE(pca, "convert DeviceN");
960
0
        return code;
961
0
    }
962
963
0
    code = cos_array_add(pca, cos_c_string_value(&v, "/DeviceN"));
964
0
    if (code < 0) {
965
0
        COS_FREE(pca, "pdf_color_space");
966
0
        return code;
967
0
    }
968
969
0
    if (code >= 0) {
970
0
        byte *name_string;
971
0
        uint name_string_length;
972
0
        cos_value_t v_attriburtes, *va = NULL;
973
0
        cos_array_t *psna =
974
0
                cos_array_alloc(pdev, "pdf_color_space(DeviceN)");
975
976
0
        if (psna == 0) {
977
0
            COS_FREE(pca, "convert DeviceN");
978
0
            return_error(gs_error_VMerror);
979
0
        }
980
981
0
        for (i = 0; i < pcs->params.device_n.num_components; ++i) {
982
0
            name_string = (byte *)pcs->params.device_n.names[i];
983
0
            name_string_length = strlen(pcs->params.device_n.names[i]);
984
0
            code = pdf_string_to_cos_name(pdev, name_string,
985
0
                              name_string_length, &v);
986
0
            if (code < 0) {
987
0
                COS_FREE(pca, "convert DeviceN");
988
0
                return code;
989
0
            }
990
0
            code = cos_array_add(psna, &v);
991
0
            if (code < 0) {
992
0
                COS_FREE(pca, "convert DeviceN");
993
0
                return code;
994
0
            }
995
0
        }
996
0
        COS_OBJECT_VALUE(&v, psna);
997
0
        code = cos_array_add(pca, &v);
998
0
        if (code <0) {
999
0
            COS_FREE(pca, "convert DeviceN");
1000
0
            return_error(gs_error_VMerror);
1001
0
        }
1002
1003
0
        switch(pdev->params.ColorConversionStrategy) {
1004
0
            case ccs_Gray:
1005
0
                cos_c_string_value(&v, (const char *)pdf_color_space_names.DeviceGray);
1006
0
                break;
1007
0
            case ccs_sRGB:
1008
0
            case ccs_RGB:
1009
0
                cos_c_string_value(&v, (const char *)pdf_color_space_names.DeviceRGB);
1010
0
                break;
1011
0
            case ccs_CMYK:
1012
0
                cos_c_string_value(&v, (const char *)pdf_color_space_names.DeviceCMYK);
1013
0
                break;
1014
0
            default:
1015
0
                break;
1016
0
        }
1017
0
        code = cos_array_add(pca, &v);
1018
0
        if (code >= 0) {
1019
0
            code = pdf_function_scaled(pdev, new_pfn, 0x00, &v);
1020
0
            if (code >= 0)
1021
0
                code = cos_array_add(pca, &v);
1022
0
            else {
1023
0
                COS_FREE(pca, "convert DeviceN");
1024
0
                return code;
1025
0
            }
1026
0
        }
1027
1028
0
        if (pcs->params.device_n.colorants != NULL) {
1029
0
            cos_dict_t *colorants  = cos_dict_alloc(pdev, "pdf_color_space(DeviceN)");
1030
0
            cos_value_t v_colorants, v_separation, v_colorant_name;
1031
0
            const gs_device_n_colorant *csa;
1032
0
            pdf_resource_t *pres_attributes;
1033
1034
0
            if (colorants == NULL)
1035
0
                return_error(gs_error_VMerror);
1036
0
            code = pdf_alloc_resource(pdev, resourceOther, 0, &pres_attributes, -1);
1037
0
            if (code < 0) {
1038
0
                COS_FREE(pca, "convert DeviceN");
1039
0
                return code;
1040
0
            }
1041
0
            cos_become(pres_attributes->object, cos_type_dict);
1042
0
            COS_OBJECT_VALUE(&v_colorants, colorants);
1043
0
            code = cos_dict_put((cos_dict_t *)pres_attributes->object,
1044
0
                (const byte *)"/Colorants", 10, &v_colorants);
1045
0
            if (code < 0){
1046
0
                COS_FREE(pca, "convert DeviceN");
1047
0
                return code;
1048
0
            }
1049
0
            for (csa = pcs->params.device_n.colorants; csa != NULL; csa = csa->next) {
1050
0
                name_string = (byte *)csa->colorant_name;
1051
0
                name_string_length = strlen((const char *)name_string);
1052
0
                code = pdf_color_space_named(pdev, pgs, &v_separation, NULL, csa->cspace, &pdf_color_space_names, false, NULL, 0, false);
1053
0
                if (code < 0) {
1054
0
                    COS_FREE(pca, "convert DeviceN");
1055
0
                    return code;
1056
0
                }
1057
0
                code = pdf_string_to_cos_name(pdev, name_string, name_string_length, &v_colorant_name);
1058
0
                if (code < 0) {
1059
0
                    COS_FREE(pca, "convert DeviceN");
1060
0
                    return code;
1061
0
                }
1062
0
                code = cos_dict_put(colorants, v_colorant_name.contents.chars.data,
1063
0
                                    v_colorant_name.contents.chars.size, &v_separation);
1064
0
                if (code < 0) {
1065
0
                    COS_FREE(pca, "convert DeviceN");
1066
0
                    return code;
1067
0
                }
1068
0
            }
1069
0
            code = pdf_string_to_cos_name(pdev, (byte *)"DeviceN",
1070
0
                              7, &v);
1071
0
            if (code < 0) {
1072
0
                COS_FREE(pca, "convert DeviceN");
1073
0
                return code;
1074
0
            }
1075
1076
0
            code = cos_dict_put((cos_dict_t *)pres_attributes->object,
1077
0
                (const byte *)"/Subtype", 8, &v);
1078
0
            if (code < 0) {
1079
0
                COS_FREE(pca, "convert DeviceN");
1080
0
                return code;
1081
0
            }
1082
1083
0
            code = pdf_substitute_resource(pdev, &pres_attributes, resourceOther, NULL, true);
1084
0
            if (code < 0) {
1085
0
                COS_FREE(pca, "convert DeviceN");
1086
0
                return code;
1087
0
            }
1088
0
            pres_attributes->where_used |= pdev->used_mask;
1089
0
            va = &v_attriburtes;
1090
0
            COS_OBJECT_VALUE(va, pres_attributes->object);
1091
0
            code = cos_array_add(pca, va);
1092
0
            if (code < 0) {
1093
0
                COS_FREE(pca, "convert DeviceN");
1094
0
                return code;
1095
0
            }
1096
0
        }
1097
1098
0
    }
1099
0
    pdf_delete_sampled_base_space_function(pdev, new_pfn);
1100
1101
    /*
1102
     * Register the color space as a resource, since it must be referenced
1103
     * by name rather than directly.
1104
     */
1105
0
    {
1106
0
        pdf_color_space_t *ppcs;
1107
1108
0
        if (code < 0 ||
1109
0
            (code = pdf_alloc_resource(pdev, resourceColorSpace, pcs->id,
1110
0
                                       &pres, -1)) < 0
1111
0
            ) {
1112
0
            COS_FREE(pca, "pdf_color_space");
1113
0
            return code;
1114
0
        }
1115
0
        pdf_reserve_object_id(pdev, pres, 0);
1116
0
        ppcs = (pdf_color_space_t *)pres;
1117
0
        ppcs->serialized = NULL;
1118
0
        ppcs->serialized_size = 0;
1119
1120
0
        ppcs->ranges = 0;
1121
0
        pca->id = pres->object->id;
1122
0
        COS_FREE(pres->object, "pdf_color_space");
1123
0
        pres->object = (cos_object_t *)pca;
1124
0
        cos_write_object(COS_OBJECT(pca), pdev, resourceColorSpace);
1125
0
        if (pcs_save == NULL && ppscc != NULL)
1126
0
            pprints1(pdev->strm, "/%s", ppcs->rname);
1127
0
    }
1128
0
    pres->where_used |= pdev->used_mask;
1129
0
    code = pdf_add_resource(pdev, pdev->substream_Resources, "/ColorSpace", pres);
1130
0
    if (code < 0)
1131
0
        return code;
1132
1133
0
    if (pcs_save != NULL) {
1134
0
        cos_value_t value;
1135
1136
0
        pcs = pcs_save;
1137
0
        discard(COS_OBJECT_VALUE(&value, pca));
1138
0
        pca1 = cos_array_alloc(pdev, "pdf_color_space");
1139
0
        if (pca1 == NULL)
1140
0
            return_error(gs_error_VMerror);
1141
1142
0
        code = pdf_indexed_color_space(pdev, pgs, &value, pcs, pca1, (cos_value_t *)&value);
1143
0
        pca = pca1;
1144
1145
        /*
1146
         * Register the color space as a resource, since it must be referenced
1147
         * by name rather than directly.
1148
         */
1149
0
        {
1150
0
            pdf_color_space_t *ppcs;
1151
1152
0
            if (code < 0 ||
1153
0
                (code = pdf_alloc_resource(pdev, resourceColorSpace, pcs->id,
1154
0
                                           &pres, -1)) < 0
1155
0
                ) {
1156
0
                COS_FREE(pca, "pdf_color_space");
1157
0
                return code;
1158
0
            }
1159
0
            pdf_reserve_object_id(pdev, pres, 0);
1160
0
            ppcs = (pdf_color_space_t *)pres;
1161
0
            ppcs->serialized = NULL;
1162
0
            ppcs->serialized_size = 0;
1163
1164
0
            ppcs->ranges = 0;
1165
0
            pca->id = pres->object->id;
1166
0
            COS_FREE(pres->object, "pdf_color_space");
1167
0
            pres->object = (cos_object_t *)pca;
1168
0
            cos_write_object(COS_OBJECT(pca), pdev, resourceColorSpace);
1169
0
            if (ppscc != NULL)
1170
0
                pprints1(pdev->strm, "/%s", ppcs->rname);
1171
0
        }
1172
0
        pres->where_used |= pdev->used_mask;
1173
0
        code = pdf_add_resource(pdev, pdev->substream_Resources, "/ColorSpace", pres);
1174
0
        if (code < 0)
1175
0
            return code;
1176
0
    }
1177
1178
0
    if (ppscc != NULL) {
1179
0
        pprints1(pdev->strm, " %s\n", ppscc->setcolorspace);
1180
0
        *used_process_color = false;
1181
0
        if (pcs_save == NULL) {
1182
0
            for (i = 0; i < pcs->params.device_n.num_components; ++i)
1183
0
                pprintg1(pdev->strm, "%g ", psdf_round(pcc->paint.values[i], 255, 8));
1184
0
        } else
1185
0
            pprintg1(pdev->strm, "%g ", psdf_round(pcc->paint.values[0], 255, 8));
1186
0
        pprints1(pdev->strm, "%s\n", ppscc->setcolorn);
1187
0
    }
1188
0
    if (pvalue != NULL) {
1189
0
        if (by_name) {
1190
            /* Return a resource name rather than an object reference. */
1191
0
            discard(COS_RESOURCE_VALUE(pvalue, pca));
1192
0
        } else
1193
0
            discard(COS_OBJECT_VALUE(pvalue, pca));
1194
0
    }
1195
0
    return 0;
1196
0
}
1197
1198
int convert_separation_alternate(gx_device_pdf * pdev, const gs_gstate * pgs, const gs_color_space *pcs,
1199
                        const gx_drawing_color *pdc, bool *used_process_color,
1200
                        const psdf_set_color_commands_t *ppscc, gs_client_color *pcc, cos_value_t *pvalue, bool by_name)
1201
0
{
1202
0
    gs_color_space_index csi;
1203
0
    gs_function_t *new_pfn = 0;
1204
0
    float out_low[4];
1205
0
    float out_high[4];
1206
0
    int code;
1207
0
    cos_array_t *pca, *pca1;
1208
0
    cos_value_t v;
1209
0
    byte *name_string;
1210
0
    uint name_string_length;
1211
0
    pdf_resource_t *pres = NULL;
1212
1213
0
    pca = cos_array_alloc(pdev, "pdf_color_space");
1214
0
    if (pca == 0)
1215
0
        return_error(gs_error_VMerror);
1216
1217
0
    if (pdev->PDFA != 0 && utf8_check((unsigned char *)pcs->params.separation.sep_name) != NULL) {
1218
0
        switch(pdev->PDFACompatibilityPolicy) {
1219
0
            case 0:
1220
0
                emprintf(pdev->memory,
1221
0
                     "Ink name in Separation space not valid UTF-8, reverting to normal PDF output.\n");
1222
0
                pdev->AbortPDFAX = true;
1223
0
                pdev->PDFA = 0;
1224
0
                break;
1225
0
            case 1:
1226
0
                emprintf(pdev->memory,
1227
0
                     "Ink name in Separation space not valid UTF-8, reverting to normal PDF output.\n");
1228
0
                pdev->AbortPDFAX = true;
1229
0
                pdev->PDFA = 0;
1230
0
                break;
1231
0
            default:
1232
0
            case 2:
1233
0
                emprintf(pdev->memory,
1234
0
                     "Ink name in Separation space not valid UTF-8, aborting.\n");
1235
0
                return_error(gs_error_limitcheck);
1236
0
                break;
1237
0
        }
1238
0
    }
1239
1240
0
    {
1241
0
        frac conc[GS_CLIENT_COLOR_MAX_COMPONENTS];
1242
0
        gs_client_color cc;
1243
0
        unsigned char i;
1244
0
        gs_color_space *icc_space = (gs_color_space *)pcs;
1245
0
        gs_color_space *sep_space = (gs_color_space *)pcs;
1246
0
        gs_color_space_index csi2;
1247
0
        bool save_use_alt = 0;
1248
0
        separation_type save_type = SEP_OTHER;
1249
1250
0
        csi = gs_color_space_get_index(pcs);
1251
0
        if (csi == gs_color_space_index_Indexed)
1252
0
            sep_space = pcs->base_space;
1253
1254
0
        do{
1255
0
            icc_space = icc_space->base_space;
1256
0
            csi2 = gs_color_space_get_index(icc_space);
1257
0
        } while(csi2 != gs_color_space_index_ICC && icc_space->base_space);
1258
1259
0
        memset(&cc.paint.values, 0x00, GS_CLIENT_COLOR_MAX_COMPONENTS * sizeof(float));
1260
0
        cc.paint.values[0] = 0;
1261
1262
0
        save_use_alt = sep_space->params.separation.use_alt_cspace;
1263
0
        sep_space->params.separation.use_alt_cspace = true;
1264
1265
        /* Force the colour management code to use the tint transform and
1266
         * give us the values in the Alternate space. Otherwise, for
1267
         * SEP_NONE or SEP_ALL it gives us the wrong answer. For SEP_NONE
1268
         * it always returns 0 and for SEP_ALL it sets the first component
1269
         * (only!) of the space to the tint value.
1270
         */
1271
0
        if (sep_space->params.separation.sep_type == SEP_ALL || sep_space->params.separation.sep_type == SEP_NONE) {
1272
0
            save_type = sep_space->params.separation.sep_type;
1273
0
            sep_space->params.separation.sep_type = SEP_OTHER;
1274
0
        }
1275
1276
0
        sep_space->type->concretize_color(&cc, sep_space, conc, pgs, (gx_device *)pdev);
1277
1278
0
        if (save_type == SEP_ALL || save_type == SEP_NONE)
1279
0
            sep_space->params.separation.sep_type = save_type;
1280
1281
0
        for (i = 0;i < pdev->color_info.num_components;i++)
1282
0
            cc.paint.values[i] = frac2float(conc[i]);
1283
1284
0
        if (pdev->params.TransferFunctionInfo == tfi_Apply) {
1285
0
            switch (pdev->params.ColorConversionStrategy) {
1286
0
                case ccs_Gray:
1287
0
                    code = apply_transfer_gray(pdev, pgs, &cc, &cc);
1288
0
                    break;
1289
0
                case ccs_sRGB:
1290
0
                case ccs_RGB:
1291
0
                    code = apply_transfer_rgb(pdev, pgs, &cc, &cc);
1292
0
                    break;
1293
0
                case ccs_CMYK:
1294
0
                    code = apply_transfer_cmyk(pdev, pgs, &cc, &cc);
1295
0
                    break;
1296
0
                default:
1297
0
                    code = gs_error_rangecheck;
1298
0
                    break;
1299
0
            }
1300
0
            if (code < 0) {
1301
0
                COS_FREE(pca, "pdf_color_space");
1302
0
                return code;
1303
0
            }
1304
0
        }
1305
0
        for (i = 0;i < pdev->color_info.num_components;i++)
1306
0
            out_low[i] = cc.paint.values[i];
1307
1308
0
        memset (&conc, 0x00, sizeof(frac) * GS_CLIENT_COLOR_MAX_COMPONENTS);
1309
        /* Force the colour management code to use the tint transform and
1310
         * give us the values in the Alternate space. Otherwise, for
1311
         * SEP_NONE or SEP_ALL it gives us the wrong answer. For SEP_NONE
1312
         * it always returns 0 and for SEP_ALL it sets the first component
1313
         * (only!) of the space to the tint value.
1314
         */
1315
0
        if (sep_space->params.separation.sep_type == SEP_ALL || sep_space->params.separation.sep_type == SEP_NONE) {
1316
0
            save_type = sep_space->params.separation.sep_type;
1317
0
            sep_space->params.separation.sep_type = SEP_OTHER;
1318
0
        }
1319
1320
0
        cc.paint.values[0] = 1;
1321
0
        memset (&conc, 0x00, sizeof(frac) * GS_CLIENT_COLOR_MAX_COMPONENTS);
1322
0
        sep_space->type->concretize_color(&cc, sep_space, conc, pgs, (gx_device *)pdev);
1323
1324
        /* Put back the values we hacked in order to force the colour management code
1325
         * to do what we want.
1326
         */
1327
0
        sep_space->params.separation.use_alt_cspace = save_use_alt;
1328
0
        if (save_type == SEP_ALL || save_type == SEP_NONE)
1329
0
            sep_space->params.separation.sep_type = save_type;
1330
1331
0
        for (i = 0;i < pdev->color_info.num_components;i++)
1332
0
            cc.paint.values[i] = frac2float(conc[i]);
1333
1334
0
        if (pdev->params.TransferFunctionInfo == tfi_Apply) {
1335
0
            switch (pdev->params.ColorConversionStrategy) {
1336
0
                case ccs_Gray:
1337
0
                    code = apply_transfer_gray(pdev, pgs, &cc, &cc);
1338
0
                    break;
1339
0
                case ccs_sRGB:
1340
0
                case ccs_RGB:
1341
0
                    code = apply_transfer_rgb(pdev, pgs, &cc, &cc);
1342
0
                    break;
1343
0
                case ccs_CMYK:
1344
0
                    code = apply_transfer_cmyk(pdev, pgs, &cc, &cc);
1345
0
                    break;
1346
0
                default:
1347
0
                    code = gs_error_rangecheck;
1348
0
                    break;
1349
0
            }
1350
0
            if (code < 0) {
1351
0
                COS_FREE(pca, "pdf_color_space");
1352
0
                return code;
1353
0
            }
1354
0
        }
1355
0
        for (i = 0;i < pdev->color_info.num_components;i++)
1356
0
            out_high[i] = cc.paint.values[i];
1357
0
    }
1358
1359
0
    switch(pdev->params.ColorConversionStrategy) {
1360
0
        case ccs_Gray:
1361
0
            code = pdf_make_base_space_function(pdev, &new_pfn, 1, out_low, out_high);
1362
0
            break;
1363
0
        case ccs_sRGB:
1364
0
        case ccs_RGB:
1365
0
            code = pdf_make_base_space_function(pdev, &new_pfn, 3, out_low, out_high);
1366
0
            break;
1367
0
        case ccs_CMYK:
1368
0
            code = pdf_make_base_space_function(pdev, &new_pfn, 4, out_low, out_high);
1369
0
            break;
1370
0
        default:
1371
0
            code = gs_error_rangecheck;
1372
0
            break;
1373
0
    }
1374
1375
0
    if (code < 0) {
1376
0
        COS_FREE(pca, "pdf_color_space");
1377
0
        return code;
1378
0
    }
1379
1380
0
    code = cos_array_add(pca, cos_c_string_value(&v, "/Separation"));
1381
0
    if (code < 0) {
1382
0
        COS_FREE(pca, "pdf_color_space");
1383
0
        return code;
1384
0
    }
1385
1386
0
    if (code >= 0) {
1387
0
        csi = gs_color_space_get_index(pcs);
1388
0
        if (csi == gs_color_space_index_Indexed) {
1389
0
            name_string = (byte *)pcs->base_space->params.separation.sep_name;
1390
0
            name_string_length = strlen(pcs->base_space->params.separation.sep_name);
1391
0
        }
1392
0
        else {
1393
0
            name_string = (byte *)pcs->params.separation.sep_name;
1394
0
            name_string_length = strlen(pcs->params.separation.sep_name);
1395
0
        }
1396
0
        code = pdf_string_to_cos_name(pdev, name_string,
1397
0
                              name_string_length, &v);
1398
0
        if (code < 0) {
1399
0
            COS_FREE(pca, "pdf_color_space");
1400
0
            return code;
1401
0
        }
1402
1403
0
        code = cos_array_add(pca, &v);
1404
0
        if (code < 0) {
1405
0
            COS_FREE(pca, "pdf_color_space");
1406
0
            return code;
1407
0
        }
1408
0
        if (code >= 0) {
1409
0
            switch(pdev->params.ColorConversionStrategy) {
1410
0
                case ccs_Gray:
1411
0
                    cos_c_string_value(&v, (const char *)pdf_color_space_names.DeviceGray);
1412
0
                    break;
1413
0
                case ccs_RGB:
1414
0
                case ccs_sRGB:
1415
0
                    cos_c_string_value(&v, (const char *)pdf_color_space_names.DeviceRGB);
1416
0
                    break;
1417
0
                case ccs_CMYK:
1418
0
                    cos_c_string_value(&v, (const char *)pdf_color_space_names.DeviceCMYK);
1419
0
                    break;
1420
0
                default:
1421
0
                    break;
1422
0
            }
1423
0
            code = cos_array_add(pca, &v);
1424
0
            if (code >= 0) {
1425
0
                code = pdf_function_scaled(pdev, new_pfn, 0x00, &v);
1426
0
                if (code >= 0) {
1427
0
                    code = cos_array_add(pca, &v);
1428
0
                }
1429
0
            }
1430
0
        }
1431
0
    }
1432
0
    pdf_delete_base_space_function(pdev, new_pfn);
1433
1434
    /*
1435
     * Register the color space as a resource, since it must be referenced
1436
     * by name rather than directly.
1437
     */
1438
0
    {
1439
0
        pdf_color_space_t *ppcs;
1440
1441
0
        if (code < 0 ||
1442
0
            (code = pdf_alloc_resource(pdev, resourceColorSpace, pcs->id,
1443
0
                                       &pres, -1)) < 0
1444
0
            ) {
1445
0
            COS_FREE(pca, "pdf_color_space");
1446
0
            return code;
1447
0
        }
1448
0
        pdf_reserve_object_id(pdev, pres, 0);
1449
0
        ppcs = (pdf_color_space_t *)pres;
1450
0
        ppcs->serialized = NULL;
1451
0
        ppcs->serialized_size = 0;
1452
1453
0
        ppcs->ranges = 0;
1454
0
        pca->id = pres->object->id;
1455
0
        COS_FREE(pres->object, "pdf_color_space");
1456
0
        pres->object = (cos_object_t *)pca;
1457
0
        cos_write_object(COS_OBJECT(pca), pdev, resourceColorSpace);
1458
0
        csi = gs_color_space_get_index(pcs);
1459
0
        if (csi != gs_color_space_index_Indexed && ppscc != NULL)
1460
0
            pprints1(pdev->strm, "/%s", ppcs->rname);
1461
0
    }
1462
0
    pres->where_used |= pdev->used_mask;
1463
0
    code = pdf_add_resource(pdev, pdev->substream_Resources, "/ColorSpace", pres);
1464
0
    if (code < 0)
1465
0
        return code;
1466
1467
0
    csi = gs_color_space_get_index(pcs);
1468
0
    if (csi == gs_color_space_index_Indexed) {
1469
0
        cos_value_t value;
1470
1471
0
        discard(COS_OBJECT_VALUE(&value, pca));
1472
0
        pca1 = cos_array_alloc(pdev, "pdf_color_space");
1473
0
        if (pca1 == NULL)
1474
0
            return_error(gs_error_VMerror);
1475
1476
0
        code = pdf_indexed_color_space(pdev, pgs, &value, pcs, pca1, (cos_value_t *)&value);
1477
0
        pca = pca1;
1478
1479
        /*
1480
         * Register the color space as a resource, since it must be referenced
1481
         * by name rather than directly.
1482
         */
1483
0
        {
1484
0
            pdf_color_space_t *ppcs;
1485
1486
0
            if (code < 0 ||
1487
0
                (code = pdf_alloc_resource(pdev, resourceColorSpace, pcs->id,
1488
0
                                           &pres, -1)) < 0
1489
0
                ) {
1490
0
                COS_FREE(pca, "pdf_color_space");
1491
0
                return code;
1492
0
            }
1493
0
            pdf_reserve_object_id(pdev, pres, 0);
1494
0
            ppcs = (pdf_color_space_t *)pres;
1495
0
            ppcs->serialized = NULL;
1496
0
            ppcs->serialized_size = 0;
1497
1498
0
            ppcs->ranges = 0;
1499
0
            pca->id = pres->object->id;
1500
0
            COS_FREE(pres->object, "pdf_color_space");
1501
0
            pres->object = (cos_object_t *)pca;
1502
0
            cos_write_object(COS_OBJECT(pca), pdev, resourceColorSpace);
1503
0
            if (ppscc != NULL)
1504
0
                pprints1(pdev->strm, "/%s", ppcs->rname);
1505
0
        }
1506
0
        pres->where_used |= pdev->used_mask;
1507
0
        code = pdf_add_resource(pdev, pdev->substream_Resources, "/ColorSpace", pres);
1508
0
        if (code < 0)
1509
0
            return code;
1510
0
    }
1511
1512
0
    if (ppscc != NULL) {
1513
0
        pprints1(pdev->strm, " %s\n", ppscc->setcolorspace);
1514
0
        *used_process_color = false;
1515
0
        pprintg1(pdev->strm, "%g", psdf_round(pcc->paint.values[0], 255, 8));
1516
0
        pprints1(pdev->strm, " %s\n", ppscc->setcolorn);
1517
0
    }
1518
0
    if (pvalue != NULL) {
1519
0
        if (by_name) {
1520
            /* Return a resource name rather than an object reference. */
1521
0
            discard(COS_RESOURCE_VALUE(pvalue, pca));
1522
0
        } else
1523
0
            discard(COS_OBJECT_VALUE(pvalue, pca));
1524
0
    }
1525
0
    return 0;
1526
0
}
1527
1528
void
1529
rescale_cie_color(gs_range_t *ranges, int num_colorants,
1530
                    const gs_client_color *src, gs_client_color *des)
1531
0
{
1532
0
    int k;
1533
1534
0
    for (k = 0; k < num_colorants; k++) {
1535
0
        des->paint.values[k] =
1536
0
            (src->paint.values[k]-ranges[k].rmin)/
1537
0
            (ranges[k].rmax-ranges[k].rmin);
1538
0
    }
1539
0
}
1540
1541
static int check_colorants_for_pdfx4(const gs_color_space *pcs)
1542
0
{
1543
0
    int comp, all_present = 1;
1544
0
    char *ink;
1545
0
    gs_device_n_colorant *colorant = NULL;
1546
1547
0
    if (pcs->params.device_n.colorants == NULL) {
1548
0
        return 0;
1549
0
    } else {
1550
0
        for (comp = 0; comp < pcs->params.device_n.num_components;comp++){
1551
0
            colorant = pcs->params.device_n.colorants;
1552
0
            ink = pcs->params.device_n.names[comp];
1553
0
            do {
1554
0
                if (memcmp(colorant->colorant_name, ink, strlen(ink)) == 0)
1555
0
                    break;
1556
0
                colorant = colorant->next;
1557
0
            }while(colorant);
1558
0
            if (!colorant) {
1559
0
                all_present = 0;
1560
0
                break;
1561
0
            }
1562
0
        }
1563
0
    }
1564
0
    return all_present;
1565
0
}
1566
1567
/* Set the fill or stroke color. */
1568
int pdf_reset_color(gx_device_pdf * pdev, const gs_gstate * pgs,
1569
                const gx_drawing_color *pdc, gx_hl_saved_color * psc,
1570
                bool *used_process_color,
1571
                const psdf_set_color_commands_t *ppscc)
1572
1.57M
{
1573
1.57M
    int code=0, code1=0;
1574
1.57M
    gx_hl_saved_color temp;
1575
1.57M
    gs_client_color *pcc; /* fixme: not needed due to gx_hld_get_color_component. */
1576
1.57M
    cos_value_t cs_value;
1577
1.57M
    gs_color_space_index csi;
1578
1.57M
    gs_color_space_index csi2;
1579
1.57M
    const gs_color_space *pcs, *pcs2;
1580
1581
1.57M
    if (pdev->skip_colors)
1582
0
        return 0;
1583
1584
    /* Get a copy of the current colour so we can examine it. */
1585
1.57M
    gx_hld_save_color(pgs, pdc, &temp);
1586
1587
    /* Since pdfwrite never applies halftones and patterns, but monitors
1588
     * halftone/pattern IDs separately, we don't need to compare
1589
     * halftone/pattern bodies here.
1590
     */
1591
1.57M
    if (gx_hld_saved_color_equal(&temp, psc))
1592
        /* New colour (and space) same as old colour, no need to do anything */
1593
0
        return 0;
1594
1595
    /* Do we have a Pattern colour space ? */
1596
1.57M
    switch (gx_hld_get_color_space_and_ccolor(pgs, pdc, &pcs, (const gs_client_color **)&pcc)) {
1597
17.6k
        case pattern_color_space:
1598
17.6k
            {
1599
17.6k
                pdf_resource_t *pres;
1600
1601
17.6k
                if (pdc->type == gx_dc_type_pattern) {
1602
                    /* Can't handle tiling patterns in levels 1.0 and 1.1, and
1603
                     * unlike shading patterns we have no fallback.
1604
                     */
1605
8.03k
                    if (pdev->CompatibilityLevel < 1.2) {
1606
0
                        return_error(gs_error_undefined);
1607
0
                    }
1608
8.03k
                    code = pdf_put_colored_pattern(pdev, pdc, pcs,
1609
8.03k
                                ppscc, pgs, &pres);
1610
8.03k
                }
1611
9.64k
                else if (pdc->type == &gx_dc_pure_masked) {
1612
84
                    code = pdf_put_uncolored_pattern(pdev, pdc, pcs,
1613
84
                                ppscc, pgs, &pres);
1614
84
                    if (code < 0 || pres == 0) {
1615
                        /* replaced a pattern with a flat fill, but we still
1616
                         * need to change the 'saved' colour or we will
1617
                         * get out of step with the PDF content.
1618
                         */
1619
0
                        *psc = temp;
1620
0
                        return code;
1621
0
                    }
1622
84
                    if (pgs->have_pattern_streams)
1623
84
                        code = pdf_write_ccolor(pdev, pgs, pcc);
1624
9.55k
                } else if (pdc->type == &gx_dc_pattern2) {
1625
9.55k
                    if (pdev->CompatibilityLevel <= 1.2)
1626
2.63k
                        return_error(gs_error_rangecheck);
1627
6.91k
                    if (!is_pattern2_allowed_in_strategy(pdev, pdc))
1628
0
                        return_error(gs_error_rangecheck);
1629
6.91k
                    code1 = pdf_put_pattern2(pdev, pgs, pdc, ppscc, &pres);
1630
6.91k
                    if (code1 < 0)
1631
0
                        return code1;
1632
6.91k
                } else
1633
0
                    return_error(gs_error_rangecheck);
1634
15.0k
                if (code < 0)
1635
0
                    return code;
1636
15.0k
                code = pdf_add_resource(pdev, pdev->substream_Resources, "/Pattern", pres);
1637
15.0k
                if (code >= 0) {
1638
15.0k
                    cos_value_write(cos_resource_value(&cs_value, pres->object), pdev);
1639
15.0k
                    pprints1(pdev->strm, " %s\n", ppscc->setcolorn);
1640
15.0k
                }
1641
0
                else {
1642
0
                    pres->where_used = 0;
1643
0
                    return code;
1644
0
                }
1645
15.0k
                *used_process_color = false;
1646
15.0k
            }
1647
0
            break;
1648
888k
        case non_pattern_color_space:
1649
888k
            pcs2 = pcs;
1650
888k
            csi = csi2 = gs_color_space_get_index(pcs);
1651
888k
            if (csi == gs_color_space_index_ICC) {
1652
869k
                csi2 = gsicc_get_default_type(pcs->cmm_icc_profile_data);
1653
869k
            }
1654
            /* Figure out what to do if we are outputting to really ancient versions of PDF */
1655
            /* NB ps2write sets CompatibilityLevel to 1.2 so we cater for it here */
1656
888k
            if (pdev->CompatibilityLevel <= 1.2) {
1657
1658
                /* If we have an /Indexed space, we need to look at the base space */
1659
603k
                if (csi2 == gs_color_space_index_Indexed) {
1660
23
                    pcs2 = pcs->base_space;
1661
23
                    csi2 = gs_color_space_get_index(pcs2);
1662
23
                }
1663
1664
603k
                switch (csi2) {
1665
191k
                    case gs_color_space_index_DeviceGray:
1666
191k
                        if (pdev->params.ColorConversionStrategy == ccs_LeaveColorUnchanged ||
1667
0
                            pdev->params.ColorConversionStrategy == ccs_Gray)
1668
191k
                            code = write_color_unchanged(pdev, pgs, pcc, &temp, psc, ppscc, used_process_color, pcs, pdc);
1669
0
                        else
1670
0
                            code = write_color_as_process(pdev, pgs, pcs, pdc, used_process_color, ppscc, pcc);
1671
191k
                        break;
1672
320k
                    case gs_color_space_index_DeviceRGB:
1673
320k
                        if (pdev->params.ColorConversionStrategy == ccs_LeaveColorUnchanged ||
1674
0
                            pdev->params.ColorConversionStrategy == ccs_RGB)
1675
320k
                            code = write_color_unchanged(pdev, pgs, pcc, &temp, psc, ppscc, used_process_color, pcs, pdc);
1676
0
                        else
1677
0
                            code = write_color_as_process(pdev, pgs, pcs, pdc, used_process_color, ppscc, pcc);
1678
320k
                        break;
1679
47.2k
                    case gs_color_space_index_DeviceCMYK:
1680
47.2k
                        if (pdev->params.ColorConversionStrategy == ccs_LeaveColorUnchanged ||
1681
0
                            pdev->params.ColorConversionStrategy == ccs_CMYK)
1682
47.2k
                            code = write_color_unchanged(pdev, pgs, pcc, &temp, psc, ppscc, used_process_color, pcs, pdc);
1683
0
                        else
1684
0
                            code = write_color_as_process(pdev, pgs, pcs, pdc, used_process_color, ppscc, pcc);
1685
47.2k
                        break;
1686
4
                    case gs_color_space_index_CIEA:
1687
6
                    case gs_color_space_index_CIEABC:
1688
6
                    case gs_color_space_index_CIEDEF:
1689
6
                    case gs_color_space_index_CIEDEFG:
1690
6
                        if (pdev->ForOPDFRead) {
1691
6
                            switch (pdev->params.ColorConversionStrategy) {
1692
0
                                case ccs_ByObjectType:
1693
                                    /* Object type not implemented yet */
1694
0
                                case ccs_UseDeviceIndependentColorForImages:
1695
                                    /* If only correcting images, then leave unchanged */
1696
6
                                case ccs_LeaveColorUnchanged:
1697
6
                                    if (pdev->transfer_not_identity && pdev->params.TransferFunctionInfo == tfi_Apply)
1698
0
                                        code = write_color_as_process(pdev, pgs, pcs, pdc, used_process_color, ppscc, pcc);
1699
6
                                    else
1700
6
                                        code = write_color_unchanged(pdev, pgs, pcc, &temp, psc, ppscc, used_process_color, pcs, pdc);
1701
6
                                    break;
1702
0
                                default:
1703
0
                                    code = write_color_as_process(pdev, pgs, pcs, pdc, used_process_color, ppscc, pcc);
1704
0
                                    break;
1705
6
                            }
1706
6
                        }
1707
0
                        else
1708
0
                            code = write_color_as_process(pdev, pgs, pcs, pdc, used_process_color, ppscc, pcc);
1709
6
                        break;
1710
10.5k
                    case gs_color_space_index_Separation:
1711
10.5k
                        switch (pdev->params.ColorConversionStrategy) {
1712
0
                            case ccs_ByObjectType:
1713
                                /* Object type not implemented yet */
1714
0
                            case ccs_UseDeviceIndependentColorForImages:
1715
                                /* If only correcting images, then leave unchanged */
1716
10.5k
                            case ccs_LeaveColorUnchanged:
1717
10.5k
                                pcs2 = pcs->base_space;
1718
10.5k
                                csi2 = gs_color_space_get_index(pcs2);
1719
10.5k
                                if (csi2 == gs_color_space_index_ICC) {
1720
10.5k
                                    csi2 = gsicc_get_default_type(pcs2->cmm_icc_profile_data);
1721
10.5k
                                }
1722
10.5k
                                if (csi2 == gs_color_space_index_ICC) {
1723
3.93k
                                    if (pcs2->cmm_icc_profile_data->islab && pdev->PreserveSeparation) {
1724
0
                                        if (pdev->ForOPDFRead) {
1725
0
                                            int saved_ccs = pdev->params.ColorConversionStrategy;
1726
0
                                            switch(pdev->pcm_color_info_index) {
1727
0
                                                case 0:
1728
0
                                                    pdev->params.ColorConversionStrategy = ccs_Gray;
1729
0
                                                    break;
1730
0
                                                case 1:
1731
0
                                                    pdev->params.ColorConversionStrategy = ccs_RGB;
1732
0
                                                    break;
1733
0
                                                case 2:
1734
0
                                                    pdev->params.ColorConversionStrategy = ccs_CMYK;
1735
0
                                                    break;
1736
0
                                                default:
1737
0
                                                    pdev->params.ColorConversionStrategy = saved_ccs;
1738
0
                                                    return_error(gs_error_rangecheck);
1739
0
                                            }
1740
0
                                            code = convert_separation_alternate(pdev, pgs, pcs, pdc, used_process_color, ppscc, pcc, NULL, false);
1741
0
                                            pdev->params.ColorConversionStrategy = saved_ccs;
1742
0
                                        }
1743
0
                                    } else
1744
3.93k
                                        code = write_color_unchanged(pdev, pgs, pcc, &temp, psc, ppscc, used_process_color, pcs, pdc);
1745
3.93k
                                } else
1746
6.64k
                                    code = write_color_unchanged(pdev, pgs, pcc, &temp, psc, ppscc, used_process_color, pcs, pdc);
1747
10.5k
                                break;
1748
10.5k
                            case ccs_UseDeviceIndependentColor:
1749
0
                                code = write_color_as_process(pdev, pgs, pcs, pdc, used_process_color, ppscc, pcc);
1750
0
                                break;
1751
0
                            case ccs_sRGB:
1752
0
                            default:
1753
0
                                code = convert_separation_alternate(pdev, pgs, pcs, pdc, used_process_color, ppscc, pcc, NULL, false);
1754
0
                                break;
1755
10.5k
                        }
1756
10.5k
                        break;
1757
10.5k
                    case gs_color_space_index_DeviceN:
1758
66
                        switch (pdev->params.ColorConversionStrategy) {
1759
0
                            case ccs_ByObjectType:
1760
                                /* Object type not implemented yet */
1761
0
                            case ccs_UseDeviceIndependentColorForImages:
1762
                                /* If only correcting images, then leave unchanged */
1763
66
                            case ccs_LeaveColorUnchanged:
1764
66
                                code = write_color_unchanged(pdev, pgs, pcc, &temp, psc, ppscc, used_process_color, pcs, pdc);
1765
66
                                break;
1766
0
                            case ccs_UseDeviceIndependentColor:
1767
0
                                code = write_color_as_process(pdev, pgs, pcs, pdc, used_process_color, ppscc, pcc);
1768
0
                                break;
1769
0
                            case ccs_sRGB:
1770
0
                            default:
1771
0
                                if (pdev->PDFX > 0) {
1772
0
                                    if (pdev->PDFX >= 4) {
1773
0
                                        if (check_colorants_for_pdfx4(pcs)) {
1774
0
                                            if (csi != gs_color_space_index_DeviceCMYK)
1775
0
                                                code = convert_DeviceN_alternate(pdev, pgs, pcs, pdc, used_process_color, ppscc, pcc, NULL, false);
1776
0
                                            else
1777
0
                                                code = write_color_unchanged(pdev, pgs, pcc, &temp, psc, ppscc, used_process_color, pcs, pdc);
1778
0
                                        } else
1779
0
                                            code = write_color_as_process(pdev, pgs, pcs, pdc, used_process_color, ppscc, pcc);
1780
0
                                    } else
1781
0
                                        code = write_color_as_process(pdev, pgs, pcs, pdc, used_process_color, ppscc, pcc);
1782
0
                                }
1783
0
                                else {
1784
0
                                    code = convert_DeviceN_alternate(pdev, pgs, pcs, pdc, used_process_color, ppscc, pcc, NULL, false);
1785
0
                                }
1786
0
                                break;
1787
66
                        }
1788
66
                        break;
1789
34.0k
                    case gs_color_space_index_ICC:
1790
                        /* Note that if csi is ICC, check to see if this was one of
1791
                           the default substitutes that we introduced for DeviceGray,
1792
                           DeviceRGB or DeviceCMYK.  If it is, then just write
1793
                           the default color.  Depending upon the flavor of PDF,
1794
                           or other options, we may want to actually have all
1795
                           the colors defined by ICC profiles and not do the following
1796
                           substituion of the Device space. */
1797
34.0k
                        csi2 = gsicc_get_default_type(pcs2->cmm_icc_profile_data);
1798
1799
34.0k
                        switch (csi2) {
1800
0
                            case gs_color_space_index_DeviceGray:
1801
0
                                if (pdev->params.ColorConversionStrategy == ccs_Gray ||
1802
0
                                    pdev->params.ColorConversionStrategy == ccs_LeaveColorUnchanged) {
1803
0
                                    code = write_color_unchanged(pdev, pgs, pcc, &temp, psc, ppscc, used_process_color, pcs, pdc);
1804
0
                                    *psc = temp;
1805
0
                                    return code;
1806
0
                                }
1807
0
                                break;
1808
0
                            case gs_color_space_index_DeviceRGB:
1809
0
                                if (pdev->params.ColorConversionStrategy == ccs_RGB ||
1810
0
                                    pdev->params.ColorConversionStrategy == ccs_LeaveColorUnchanged) {
1811
0
                                    code = write_color_unchanged(pdev, pgs, pcc, &temp, psc, ppscc, used_process_color, pcs, pdc);
1812
0
                                    *psc = temp;
1813
0
                                    return code;
1814
0
                                }
1815
0
                                break;
1816
0
                            case gs_color_space_index_DeviceCMYK:
1817
0
                                if (pdev->params.ColorConversionStrategy == ccs_CMYK ||
1818
0
                                    pdev->params.ColorConversionStrategy == ccs_LeaveColorUnchanged) {
1819
0
                                    code = write_color_unchanged(pdev, pgs, pcc, &temp, psc, ppscc, used_process_color, pcs, pdc);
1820
0
                                    *psc = temp;
1821
0
                                    return code;
1822
0
                                }
1823
0
                                break;
1824
34.0k
                            default:
1825
34.0k
                                break;
1826
34.0k
                        }
1827
                        /* Fall through if its not a device substitute, or not one we want to preserve */
1828
34.0k
                    case gs_color_space_index_DevicePixel:
1829
34.0k
                    case gs_color_space_index_Indexed:
1830
34.0k
                        code = write_color_as_process(pdev, pgs, pcs, pdc, used_process_color, ppscc, pcc);
1831
34.0k
                        break;
1832
0
                    default:
1833
0
                        return (gs_note_error(gs_error_rangecheck));
1834
0
                        break;
1835
603k
                }
1836
603k
            } else {
1837
285k
                switch(pdev->params.ColorConversionStrategy) {
1838
0
                    case ccs_ByObjectType:
1839
                        /* Object type not implemented yet */
1840
0
                    case ccs_UseDeviceIndependentColorForImages:
1841
                        /* If only correcting images, then leave unchanged */
1842
285k
                    case ccs_LeaveColorUnchanged:
1843
285k
                        if (pdev->transfer_not_identity && pdev->params.TransferFunctionInfo == tfi_Apply) {
1844
1845
0
                            if (csi2 == gs_color_space_index_Separation || csi2 == gs_color_space_index_DeviceN) {
1846
0
                                int force_process = 0, csi3 = gs_color_space_get_index(pcs->base_space);
1847
0
                                if (csi3 == gs_color_space_index_ICC) {
1848
0
                                    csi3 = gsicc_get_default_type(pcs->base_space->cmm_icc_profile_data);
1849
0
                                }
1850
0
                                switch (csi3) {
1851
0
                                    case gs_color_space_index_DeviceGray:
1852
0
                                        pdev->params.ColorConversionStrategy = ccs_Gray;
1853
0
                                        break;
1854
0
                                    case gs_color_space_index_DeviceRGB:
1855
0
                                        pdev->params.ColorConversionStrategy = ccs_RGB;
1856
0
                                        break;
1857
0
                                    case gs_color_space_index_DeviceCMYK:
1858
0
                                        pdev->params.ColorConversionStrategy = ccs_CMYK;
1859
0
                                        break;
1860
0
                                    default:
1861
0
                                        force_process = 1;
1862
0
                                        break;
1863
0
                                }
1864
1865
0
                                if (!force_process && csi2 == gs_color_space_index_Separation){
1866
0
                                    code = convert_separation_alternate(pdev, pgs, pcs, pdc, used_process_color, ppscc, pcc, NULL, false);
1867
0
                                } else if (!force_process && csi2 == gs_color_space_index_DeviceN){
1868
0
                                    if (pdev->PDFX > 0) {
1869
0
                                        if (pdev->PDFX >= 4) {
1870
0
                                            if (check_colorants_for_pdfx4(pcs)) {
1871
0
                                                code = write_color_unchanged(pdev, pgs, pcc, &temp, psc, ppscc, used_process_color, pcs, pdc);
1872
0
                                            } else
1873
0
                                                code = write_color_as_process(pdev, pgs, pcs, pdc, used_process_color, ppscc, pcc);
1874
0
                                        } else
1875
0
                                            code = write_color_as_process(pdev, pgs, pcs, pdc, used_process_color, ppscc, pcc);
1876
0
                                    }
1877
0
                                    else
1878
0
                                        code = convert_DeviceN_alternate(pdev, pgs, pcs, pdc, used_process_color, ppscc, pcc, NULL, false);
1879
0
                                } else
1880
0
                                    code = write_color_as_process(pdev, pgs, pcs, pdc, used_process_color, ppscc, pcc);
1881
0
                                pdev->params.ColorConversionStrategy = ccs_LeaveColorUnchanged;
1882
0
                            } else
1883
0
                                code = write_color_as_process(pdev, pgs, pcs, pdc, used_process_color, ppscc, pcc);
1884
0
                        }
1885
285k
                        else
1886
285k
                            code = write_color_unchanged(pdev, pgs, pcc, &temp, psc, ppscc, used_process_color, pcs, pdc);
1887
285k
                        break;
1888
285k
                    case ccs_UseDeviceIndependentColor:
1889
0
                            code = write_color_as_process_ICC(pdev, pgs, pcs, pdc, psc, used_process_color, ppscc, pcc, &temp);
1890
0
                        break;
1891
0
                    case ccs_CMYK:
1892
0
                        switch(csi2) {
1893
0
                            case gs_color_space_index_DeviceGray:
1894
0
                            case gs_color_space_index_DeviceCMYK:
1895
0
                                code = write_color_unchanged(pdev, pgs, pcc, &temp, psc, ppscc, used_process_color, pcs, pdc);
1896
0
                                break;
1897
0
                            case gs_color_space_index_Separation:
1898
0
                                pcs2 = pcs2->base_space;
1899
0
                                csi = gs_color_space_get_index(pcs2);
1900
0
                                if (csi == gs_color_space_index_ICC)
1901
0
                                    csi = gsicc_get_default_type(pcs2->cmm_icc_profile_data);
1902
0
                                if (csi != gs_color_space_index_DeviceCMYK)
1903
0
                                    code = convert_separation_alternate(pdev, pgs, pcs, pdc, used_process_color, ppscc, pcc, NULL, false);
1904
0
                                else
1905
0
                                    code = write_color_unchanged(pdev, pgs, pcc, &temp, psc, ppscc, used_process_color, pcs, pdc);
1906
0
                                break;
1907
0
                            case gs_color_space_index_DeviceN:
1908
0
                                pcs2 = pcs2->base_space;
1909
0
                                csi = gs_color_space_get_index(pcs2);
1910
0
                                if (csi == gs_color_space_index_ICC)
1911
0
                                    csi = gsicc_get_default_type(pcs2->cmm_icc_profile_data);
1912
0
                                if (pdev->PDFX > 0) {
1913
0
                                    if (pdev->PDFX >= 4) {
1914
0
                                        if (check_colorants_for_pdfx4(pcs)) {
1915
0
                                            if (csi != gs_color_space_index_DeviceCMYK)
1916
0
                                                code = convert_DeviceN_alternate(pdev, pgs, pcs, pdc, used_process_color, ppscc, pcc, NULL, false);
1917
0
                                            else
1918
0
                                                code = write_color_unchanged(pdev, pgs, pcc, &temp, psc, ppscc, used_process_color, pcs, pdc);
1919
0
                                        } else
1920
0
                                            code = write_color_as_process(pdev, pgs, pcs, pdc, used_process_color, ppscc, pcc);
1921
0
                                    } else
1922
0
                                        code = write_color_as_process(pdev, pgs, pcs, pdc, used_process_color, ppscc, pcc);
1923
0
                                }
1924
0
                                else {
1925
0
                                    if (csi != gs_color_space_index_DeviceCMYK)
1926
0
                                        code = convert_DeviceN_alternate(pdev, pgs, pcs, pdc, used_process_color, ppscc, pcc, NULL, false);
1927
0
                                    else
1928
0
                                        code = write_color_unchanged(pdev, pgs, pcc, &temp, psc, ppscc, used_process_color, pcs, pdc);
1929
0
                                }
1930
0
                                break;
1931
0
                            case gs_color_space_index_Indexed:
1932
0
                                pcs2 = pcs->base_space;
1933
0
                                csi = gs_color_space_get_index(pcs2);
1934
0
                                if (csi == gs_color_space_index_ICC)
1935
0
                                    csi = gsicc_get_default_type(pcs2->cmm_icc_profile_data);
1936
0
                                switch(csi) {
1937
0
                                    case gs_color_space_index_DeviceGray:
1938
0
                                    case gs_color_space_index_DeviceCMYK:
1939
0
                                        code = write_color_unchanged(pdev, pgs, pcc, &temp, psc, ppscc, used_process_color, pcs, pdc);
1940
0
                                        break;
1941
0
                                    case gs_color_space_index_Separation:
1942
0
                                        pcs2 = pcs2->base_space;
1943
0
                                        csi = gs_color_space_get_index(pcs2);
1944
0
                                        if (csi == gs_color_space_index_ICC)
1945
0
                                            csi = gsicc_get_default_type(pcs2->cmm_icc_profile_data);
1946
0
                                        if (csi != gs_color_space_index_DeviceCMYK)
1947
0
                                            code = convert_separation_alternate(pdev, pgs, pcs, pdc, used_process_color, ppscc, pcc, NULL, false);
1948
0
                                        else
1949
0
                                            code = write_color_unchanged(pdev, pgs, pcc, &temp, psc, ppscc, used_process_color, pcs, pdc);
1950
0
                                        break;
1951
0
                                    case gs_color_space_index_DeviceN:
1952
0
                                        pcs2 = pcs2->base_space;
1953
0
                                        csi = gs_color_space_get_index(pcs2);
1954
0
                                        if (csi == gs_color_space_index_ICC)
1955
0
                                            csi = gsicc_get_default_type(pcs2->cmm_icc_profile_data);
1956
0
                                        if (pdev->PDFX > 0) {
1957
0
                                            if (pdev->PDFX >= 4) {
1958
0
                                                if (check_colorants_for_pdfx4(pcs)) {
1959
0
                                                    if (csi != gs_color_space_index_DeviceCMYK)
1960
0
                                                        code = convert_DeviceN_alternate(pdev, pgs, pcs, pdc, used_process_color, ppscc, pcc, NULL, false);
1961
0
                                                    else
1962
0
                                                        code = write_color_unchanged(pdev, pgs, pcc, &temp, psc, ppscc, used_process_color, pcs, pdc);
1963
0
                                                } else
1964
0
                                                    code = write_color_as_process(pdev, pgs, pcs, pdc, used_process_color, ppscc, pcc);
1965
0
                                            } else
1966
0
                                                code = write_color_as_process(pdev, pgs, pcs, pdc, used_process_color, ppscc, pcc);
1967
0
                                        }
1968
0
                                        else {
1969
0
                                            if (csi != gs_color_space_index_DeviceCMYK)
1970
0
                                                code = convert_DeviceN_alternate(pdev, pgs, pcs, pdc, used_process_color, ppscc, pcc, NULL, false);
1971
0
                                            else
1972
0
                                                code = write_color_unchanged(pdev, pgs, pcc, &temp, psc, ppscc, used_process_color, pcs, pdc);
1973
0
                                        }
1974
0
                                        break;
1975
0
                                    default:
1976
0
                                        code = write_color_as_process(pdev, pgs, pcs, pdc, used_process_color, ppscc, pcc);
1977
0
                                        break;
1978
0
                                }
1979
0
                                break;
1980
0
                            default:
1981
0
                                code = write_color_as_process(pdev, pgs, pcs, pdc, used_process_color, ppscc, pcc);
1982
0
                                break;
1983
0
                        }
1984
0
                        break;
1985
0
                    case ccs_Gray:
1986
0
                        switch(csi2) {
1987
0
                            case gs_color_space_index_DeviceGray:
1988
0
                                code = write_color_unchanged(pdev, pgs, pcc, &temp, psc, ppscc, used_process_color, pcs, pdc);
1989
0
                                break;
1990
0
                            case gs_color_space_index_Separation:
1991
0
                                pcs2 = pcs2->base_space;
1992
0
                                csi = gs_color_space_get_index(pcs2);
1993
0
                                if (csi == gs_color_space_index_ICC)
1994
0
                                    csi = gsicc_get_default_type(pcs2->cmm_icc_profile_data);
1995
0
                                if (csi != gs_color_space_index_DeviceGray)
1996
0
                                    code = convert_separation_alternate(pdev, pgs, pcs, pdc, used_process_color, ppscc, pcc, NULL, false);
1997
0
                                else
1998
0
                                    code = write_color_unchanged(pdev, pgs, pcc, &temp, psc, ppscc, used_process_color, pcs, pdc);
1999
0
                                break;
2000
0
                            case gs_color_space_index_DeviceN:
2001
0
                                pcs2 = pcs2->base_space;
2002
0
                                csi = gs_color_space_get_index(pcs2);
2003
0
                                if (csi == gs_color_space_index_ICC)
2004
0
                                    csi = gsicc_get_default_type(pcs2->cmm_icc_profile_data);
2005
0
                                if (pdev->PDFX > 0) {
2006
0
                                    if (pdev->PDFX >= 4) {
2007
0
                                        if (check_colorants_for_pdfx4(pcs)) {
2008
0
                                            if (csi != gs_color_space_index_DeviceGray)
2009
0
                                                code = convert_DeviceN_alternate(pdev, pgs, pcs, pdc, used_process_color, ppscc, pcc, NULL, false);
2010
0
                                            else
2011
0
                                                code = write_color_unchanged(pdev, pgs, pcc, &temp, psc, ppscc, used_process_color, pcs, pdc);
2012
0
                                        } else
2013
0
                                            code = write_color_as_process(pdev, pgs, pcs, pdc, used_process_color, ppscc, pcc);
2014
0
                                    } else
2015
0
                                        code = write_color_as_process(pdev, pgs, pcs, pdc, used_process_color, ppscc, pcc);
2016
0
                                }
2017
0
                                else {
2018
0
                                    if (csi != gs_color_space_index_DeviceGray)
2019
0
                                        code = convert_DeviceN_alternate(pdev, pgs, pcs, pdc, used_process_color, ppscc, pcc, NULL, false);
2020
0
                                    else
2021
0
                                        code = write_color_unchanged(pdev, pgs, pcc, &temp, psc, ppscc, used_process_color, pcs, pdc);
2022
0
                                }
2023
0
                                break;
2024
0
                            case gs_color_space_index_Indexed:
2025
0
                                pcs2 = pcs->base_space;
2026
0
                                csi = gs_color_space_get_index(pcs2);
2027
0
                                if (csi == gs_color_space_index_ICC)
2028
0
                                    csi = gsicc_get_default_type(pcs2->cmm_icc_profile_data);
2029
0
                                switch(csi) {
2030
0
                                    case gs_color_space_index_DeviceGray:
2031
0
                                        code = write_color_unchanged(pdev, pgs, pcc, &temp, psc, ppscc, used_process_color, pcs, pdc);
2032
0
                                        break;
2033
0
                                    case gs_color_space_index_Separation:
2034
0
                                        pcs2 = pcs2->base_space;
2035
0
                                        csi = gs_color_space_get_index(pcs2);
2036
0
                                        if (csi == gs_color_space_index_ICC)
2037
0
                                            csi = gsicc_get_default_type(pcs2->cmm_icc_profile_data);
2038
0
                                        if (csi != gs_color_space_index_DeviceGray)
2039
0
                                            code = convert_separation_alternate(pdev, pgs, pcs, pdc, used_process_color, ppscc, pcc, NULL, false);
2040
0
                                        else
2041
0
                                            code = write_color_unchanged(pdev, pgs, pcc, &temp, psc, ppscc, used_process_color, pcs, pdc);
2042
0
                                        break;
2043
0
                                    case gs_color_space_index_DeviceN:
2044
0
                                        pcs2 = pcs2->base_space;
2045
0
                                        csi = gs_color_space_get_index(pcs2);
2046
0
                                        if (csi == gs_color_space_index_ICC)
2047
0
                                            csi = gsicc_get_default_type(pcs2->cmm_icc_profile_data);
2048
0
                                        if (pdev->PDFX > 0) {
2049
0
                                            if (pdev->PDFX >= 4) {
2050
0
                                                if (check_colorants_for_pdfx4(pcs)) {
2051
0
                                                    if (csi != gs_color_space_index_DeviceGray)
2052
0
                                                        code = convert_DeviceN_alternate(pdev, pgs, pcs, pdc, used_process_color, ppscc, pcc, NULL, false);
2053
0
                                                    else
2054
0
                                                        code = write_color_unchanged(pdev, pgs, pcc, &temp, psc, ppscc, used_process_color, pcs, pdc);
2055
0
                                                } else
2056
0
                                                    code = write_color_as_process(pdev, pgs, pcs, pdc, used_process_color, ppscc, pcc);
2057
0
                                            } else
2058
0
                                                code = write_color_as_process(pdev, pgs, pcs, pdc, used_process_color, ppscc, pcc);
2059
0
                                        }
2060
0
                                        else {
2061
0
                                            if (csi != gs_color_space_index_DeviceGray)
2062
0
                                                code = convert_DeviceN_alternate(pdev, pgs, pcs, pdc, used_process_color, ppscc, pcc, NULL, false);
2063
0
                                            else
2064
0
                                                code = write_color_unchanged(pdev, pgs, pcc, &temp, psc, ppscc, used_process_color, pcs, pdc);
2065
0
                                        }
2066
0
                                        break;
2067
0
                                    default:
2068
0
                                        code = write_color_as_process(pdev, pgs, pcs, pdc, used_process_color, ppscc, pcc);
2069
0
                                        break;
2070
0
                                }
2071
0
                                break;
2072
0
                            default:
2073
0
                                code = write_color_as_process(pdev, pgs, pcs, pdc, used_process_color, ppscc, pcc);
2074
0
                                break;
2075
0
                        }
2076
0
                        break;
2077
0
                    case ccs_sRGB:
2078
0
                    case ccs_RGB:
2079
0
                        switch(csi2) {
2080
0
                            case gs_color_space_index_DeviceGray:
2081
0
                            case gs_color_space_index_DeviceRGB:
2082
0
                                code = write_color_unchanged(pdev, pgs, pcc, &temp, psc, ppscc, used_process_color, pcs, pdc);
2083
0
                                break;
2084
0
                            case gs_color_space_index_Separation:
2085
0
                                pcs2 = pcs2->base_space;
2086
0
                                csi = gs_color_space_get_index(pcs2);
2087
0
                                if (csi == gs_color_space_index_ICC)
2088
0
                                    csi = gsicc_get_default_type(pcs2->cmm_icc_profile_data);
2089
0
                                if (csi != gs_color_space_index_DeviceRGB)
2090
0
                                    code = convert_separation_alternate(pdev, pgs, pcs, pdc, used_process_color, ppscc, pcc, NULL, false);
2091
0
                                else
2092
0
                                    code = write_color_unchanged(pdev, pgs, pcc, &temp, psc, ppscc, used_process_color, pcs, pdc);
2093
0
                                break;
2094
0
                            case gs_color_space_index_DeviceN:
2095
0
                                pcs2 = pcs2->base_space;
2096
0
                                csi = gs_color_space_get_index(pcs2);
2097
0
                                if (csi == gs_color_space_index_ICC)
2098
0
                                    csi = gsicc_get_default_type(pcs2->cmm_icc_profile_data);
2099
0
                                if (pdev->PDFX > 0) {
2100
0
                                    if (pdev->PDFX >= 4) {
2101
0
                                        if (check_colorants_for_pdfx4(pcs)) {
2102
0
                                            if (csi != gs_color_space_index_DeviceRGB)
2103
0
                                                code = convert_DeviceN_alternate(pdev, pgs, pcs, pdc, used_process_color, ppscc, pcc, NULL, false);
2104
0
                                            else
2105
0
                                                code = write_color_unchanged(pdev, pgs, pcc, &temp, psc, ppscc, used_process_color, pcs, pdc);
2106
0
                                        } else
2107
0
                                            code = write_color_as_process(pdev, pgs, pcs, pdc, used_process_color, ppscc, pcc);
2108
0
                                    } else
2109
0
                                        code = write_color_as_process(pdev, pgs, pcs, pdc, used_process_color, ppscc, pcc);
2110
0
                                }
2111
0
                                else {
2112
0
                                    if (csi != gs_color_space_index_DeviceRGB)
2113
0
                                        code = convert_DeviceN_alternate(pdev, pgs, pcs, pdc, used_process_color, ppscc, pcc, NULL, false);
2114
0
                                    else
2115
0
                                        code = write_color_unchanged(pdev, pgs, pcc, &temp, psc, ppscc, used_process_color, pcs, pdc);
2116
0
                                }
2117
0
                                break;
2118
0
                            case gs_color_space_index_Indexed:
2119
0
                                pcs2 = pcs->base_space;
2120
0
                                csi = gs_color_space_get_index(pcs2);
2121
0
                                if (csi == gs_color_space_index_ICC)
2122
0
                                    csi = gsicc_get_default_type(pcs2->cmm_icc_profile_data);
2123
0
                                switch(csi) {
2124
0
                                    case gs_color_space_index_DeviceGray:
2125
0
                                    case gs_color_space_index_DeviceRGB:
2126
0
                                        code = write_color_unchanged(pdev, pgs, pcc, &temp, psc, ppscc, used_process_color, pcs, pdc);
2127
0
                                        break;
2128
0
                                    case gs_color_space_index_Separation:
2129
0
                                        pcs2 = pcs2->base_space;
2130
0
                                        csi = gs_color_space_get_index(pcs2);
2131
0
                                        if (csi == gs_color_space_index_ICC)
2132
0
                                            csi = gsicc_get_default_type(pcs2->cmm_icc_profile_data);
2133
0
                                        if (csi != gs_color_space_index_DeviceRGB)
2134
0
                                            code = convert_separation_alternate(pdev, pgs, pcs, pdc, used_process_color, ppscc, pcc, NULL, false);
2135
0
                                        else
2136
0
                                            code = write_color_unchanged(pdev, pgs, pcc, &temp, psc, ppscc, used_process_color, pcs, pdc);
2137
0
                                        break;
2138
0
                                    case gs_color_space_index_DeviceN:
2139
0
                                        pcs2 = pcs2->base_space;
2140
0
                                        csi = gs_color_space_get_index(pcs2);
2141
0
                                        if (csi == gs_color_space_index_ICC)
2142
0
                                            csi = gsicc_get_default_type(pcs2->cmm_icc_profile_data);
2143
0
                                        if (pdev->PDFX > 0) {
2144
0
                                            if (pdev->PDFX >= 4) {
2145
0
                                                if (check_colorants_for_pdfx4(pcs)) {
2146
0
                                                    if (csi != gs_color_space_index_DeviceRGB)
2147
0
                                                        code = convert_DeviceN_alternate(pdev, pgs, pcs, pdc, used_process_color, ppscc, pcc, NULL, false);
2148
0
                                                    else
2149
0
                                                        code = write_color_unchanged(pdev, pgs, pcc, &temp, psc, ppscc, used_process_color, pcs, pdc);
2150
0
                                                } else
2151
0
                                                    code = write_color_as_process(pdev, pgs, pcs, pdc, used_process_color, ppscc, pcc);
2152
0
                                            } else
2153
0
                                                code = write_color_as_process(pdev, pgs, pcs, pdc, used_process_color, ppscc, pcc);
2154
0
                                        }
2155
0
                                        else {
2156
0
                                            if (csi != gs_color_space_index_DeviceRGB)
2157
0
                                                code = convert_DeviceN_alternate(pdev, pgs, pcs, pdc, used_process_color, ppscc, pcc, NULL, false);
2158
0
                                            else
2159
0
                                                code = write_color_unchanged(pdev, pgs, pcc, &temp, psc, ppscc, used_process_color, pcs, pdc);
2160
0
                                        }
2161
0
                                        break;
2162
0
                                    default:
2163
0
                                        code = write_color_as_process(pdev, pgs, pcs, pdc, used_process_color, ppscc, pcc);
2164
0
                                        break;
2165
0
                                }
2166
0
                                break;
2167
0
                            default:
2168
0
                                code = write_color_as_process(pdev, pgs, pcs, pdc, used_process_color, ppscc, pcc);
2169
0
                                break;
2170
0
                        }
2171
0
                        break;
2172
0
                    default:
2173
0
                        break;
2174
285k
                }
2175
285k
            }
2176
888k
            break;
2177
888k
        default: /* must not happen. */
2178
670k
        case use_process_color:
2179
670k
            code = psdf_set_color((gx_device_vector *)pdev, pdc, ppscc);
2180
670k
            if (code < 0)
2181
552k
                return code;
2182
117k
            *used_process_color = true;
2183
117k
            break;
2184
1.57M
    }
2185
1.02M
    *psc = temp;
2186
1.02M
    return code;
2187
1.57M
}
2188
2189
int
2190
pdf_set_drawing_color(gx_device_pdf * pdev, const gs_gstate * pgs,
2191
                      const gx_drawing_color *pdc,
2192
                      gx_hl_saved_color * psc,
2193
                      bool *used_process_color,
2194
                      const psdf_set_color_commands_t *ppscc)
2195
9.82M
{
2196
9.82M
    gx_hl_saved_color temp;
2197
9.82M
    int code;
2198
2199
    /* This section of code was in pdf_reset_color above, but was moved into this
2200
     * routine (and below) in order to isolate the switch to a stream context. This
2201
     * now allows us the opportunity to write colours in any context, in particular
2202
     * when in a text context, by using pdf_reset_color.
2203
     */
2204
9.82M
    if (pdev->skip_colors)
2205
10.3k
        return 0;
2206
9.81M
    gx_hld_save_color(pgs, pdc, &temp);
2207
    /* Since pdfwrite never applies halftones and patterns, but monitors
2208
     * halftone/pattern IDs separately, we don't need to compare
2209
     * halftone/pattern bodies here.
2210
     */
2211
9.81M
    if (gx_hld_saved_color_equal(&temp, psc))
2212
8.35M
        return 0;
2213
    /*
2214
     * In principle, we can set colors in either stream or text
2215
     * context.  However, since we currently enclose all text
2216
     * strings inside a gsave/grestore, this causes us to lose
2217
     * track of the color when we leave text context.  Therefore,
2218
     * we require stream context for setting colors.
2219
     */
2220
1.45M
    code = pdf_open_page(pdev, PDF_IN_STREAM);
2221
1.45M
    if (code < 0)
2222
0
        return code;
2223
2224
1.45M
    return pdf_reset_color(pdev, pgs, pdc, psc, used_process_color, ppscc);
2225
1.45M
}
2226
int
2227
pdf_set_pure_color(gx_device_pdf * pdev, gx_color_index color,
2228
                   gx_hl_saved_color * psc,
2229
                   bool *used_process_color,
2230
                   const psdf_set_color_commands_t *ppscc)
2231
135k
{
2232
135k
    gx_drawing_color dcolor;
2233
135k
    gx_hl_saved_color temp;
2234
135k
    int code;
2235
2236
135k
    set_nonclient_dev_color(&dcolor, color);
2237
2238
135k
    if (pdev->skip_colors)
2239
0
        return 0;
2240
135k
    gx_hld_save_color(NULL, &dcolor, &temp);
2241
    /* Since pdfwrite never applies halftones and patterns, but monitors
2242
     * halftone/pattern IDs separately, we don't need to compare
2243
     * halftone/pattern bodies here.
2244
     */
2245
135k
    if (gx_hld_saved_color_equal(&temp, psc))
2246
17.6k
        return 0;
2247
    /*
2248
     * In principle, we can set colors in either stream or text
2249
     * context.  However, since we currently enclose all text
2250
     * strings inside a gsave/grestore, this causes us to lose
2251
     * track of the color when we leave text context.  Therefore,
2252
     * we require stream context for setting colors.
2253
     */
2254
117k
    code = pdf_open_page(pdev, PDF_IN_STREAM);
2255
117k
    if (code < 0)
2256
0
        return code;
2257
2258
117k
    return pdf_reset_color(pdev, NULL, &dcolor, psc, used_process_color, ppscc);
2259
117k
}
2260
2261
/*
2262
 * Convert a string into cos name.
2263
 */
2264
int
2265
pdf_string_to_cos_name(gx_device_pdf *pdev, const byte *str, uint len,
2266
                       cos_value_t *pvalue)
2267
6.57k
{
2268
6.57k
    byte *chars = gs_alloc_string(pdev->pdf_memory, len + 1,
2269
6.57k
                                  "pdf_string_to_cos_name");
2270
2271
6.57k
    if (chars == 0)
2272
0
        return_error(gs_error_VMerror);
2273
6.57k
    chars[0] = '/';
2274
6.57k
    memcpy(chars + 1, str, len);
2275
6.57k
    cos_string_value(pvalue, chars, len + 1);
2276
6.57k
    return 0;
2277
6.57k
}
2278
2279
/* ---------------- Graphics state updating ---------------- */
2280
2281
/* ------ Functions ------ */
2282
2283
/* Define the maximum size of a Function reference. */
2284
#define MAX_FN_NAME_CHARS 9 /* /Default, /Identity */
2285
0
#define MAX_FN_CHARS max(MAX_REF_CHARS + 4, MAX_FN_NAME_CHARS)
2286
2287
/*
2288
 * Create and write a Function for a gx_transfer_map.  We use this for
2289
 * transfer, BG, and UCR functions.  If check_identity is true, check for
2290
 * an identity map.  Return 1 if the map is the identity map, otherwise
2291
 * return 0.
2292
 */
2293
static data_source_proc_access(transfer_map_access); /* check prototype */
2294
static int
2295
transfer_map_access(const gs_data_source_t *psrc, ulong start, uint length,
2296
                    byte *buf, const byte **ptr)
2297
16.8k
{
2298
16.8k
    const gx_transfer_map *map = (const gx_transfer_map *)psrc->data.str.data;
2299
16.8k
    uint i;
2300
2301
16.8k
    if (ptr)
2302
16.8k
        *ptr = buf;
2303
1.45M
    for (i = 0; i < length; ++i)
2304
1.43M
        buf[i] = frac2byte(map->values[(uint)start + i]);
2305
16.8k
    return 0;
2306
16.8k
}
2307
static int
2308
transfer_map_access_signed(const gs_data_source_t *psrc,
2309
                           ulong start, uint length,
2310
                           byte *buf, const byte **ptr)
2311
16.3k
{
2312
    /* To prevent numeric errors, we need to map 0 to an integer.
2313
     * We can't apply a general expression, because Decode isn't accessible here.
2314
     * Assuming this works for UCR only.
2315
     * Assuming the range of UCR is always [-1, 1].
2316
     * Assuming BitsPerSample = 8.
2317
     */
2318
16.3k
    const gx_transfer_map *map = (const gx_transfer_map *)psrc->data.str.data;
2319
16.3k
    uint i;
2320
2321
16.3k
    *ptr = buf;
2322
1.41M
    for (i = 0; i < length; ++i)
2323
1.39M
        buf[i] = (byte)
2324
1.39M
            ((frac2float(map->values[(uint)start + i]) + 1) * 127);
2325
16.3k
    return 0;
2326
16.3k
}
2327
static int
2328
pdf_write_transfer_map(gx_device_pdf *pdev, const gx_transfer_map *map,
2329
                       int range0, bool check_identity,
2330
                       const char *key, char *ids, int id_max)
2331
27.2k
{
2332
27.2k
    gs_memory_t *mem = pdev->pdf_memory;
2333
27.2k
    gs_function_Sd_params_t params;
2334
27.2k
    static const float domain01[2] = { 0, 1 };
2335
27.2k
    static const int size = transfer_map_size;
2336
27.2k
    float range01[2], decode[2];
2337
27.2k
    gs_function_t *pfn;
2338
27.2k
    int64_t id;
2339
27.2k
    int code;
2340
2341
27.2k
    if (map == 0) {
2342
5.94k
        *ids = 0;   /* no map */
2343
5.94k
        return 1;
2344
5.94k
    }
2345
21.3k
    if (check_identity) {
2346
        /* Check for an identity map. */
2347
10.3k
        int i;
2348
2349
10.3k
        if (map->proc == gs_identity_transfer)
2350
10.2k
            i = transfer_map_size;
2351
128
        else
2352
240
            for (i = 0; i < transfer_map_size; ++i) {
2353
240
                fixed d = map->values[i] - bits2frac(i, log2_transfer_map_size);
2354
240
                if (any_abs(d) > fixed_epsilon) /* ignore small noise */
2355
128
                    break;
2356
240
            }
2357
10.3k
        if (i == transfer_map_size) {
2358
10.2k
            strcpy(ids, key);
2359
10.2k
            strcat(ids, "/Identity");
2360
10.2k
            return 1;
2361
10.2k
        }
2362
10.3k
    }
2363
11.0k
    params.m = 1;
2364
11.0k
    params.Domain = domain01;
2365
11.0k
    params.n = 1;
2366
11.0k
    range01[0] = (float)range0, range01[1] = 1.0;
2367
11.0k
    params.Range = range01;
2368
11.0k
    params.Order = 1;
2369
11.0k
    params.DataSource.access =
2370
11.0k
        (range0 < 0 ? transfer_map_access_signed : transfer_map_access);
2371
11.0k
    params.DataSource.data.str.data = (const byte *)map; /* bogus */
2372
    /* DataSource */
2373
11.0k
    params.BitsPerSample = 8; /* could be 16 */
2374
11.0k
    params.Encode = 0;
2375
11.0k
    if (range01[0] < 0 && range01[1] > 0) {
2376
        /* This works for UCR only.
2377
         * Map 0 to an integer.
2378
         * Rather the range of UCR is always [-1, 1],
2379
         * we prefer a general expression.
2380
         */
2381
5.46k
        int r0 = (int)( -range01[0] * ((1 << params.BitsPerSample) - 1)
2382
5.46k
                        / (range01[1] - range01[0]) ); /* Round down. */
2383
5.46k
        float r1 = r0 * range01[1] / -range01[0]; /* r0 + r1 <= (1 << params.BitsPerSample) - 1 */
2384
2385
5.46k
        decode[0] = range01[0];
2386
5.46k
        decode[1] = range01[0] + (range01[1] - range01[0]) * ((1 << params.BitsPerSample) - 1)
2387
5.46k
                                    / (r0 + r1);
2388
5.46k
        params.Decode = decode;
2389
5.46k
    } else
2390
5.60k
        params.Decode = 0;
2391
11.0k
    params.Size = &size;
2392
11.0k
    code = gs_function_Sd_init(&pfn, &params, mem);
2393
11.0k
    if (code < 0)
2394
0
        return code;
2395
11.0k
    code = pdf_write_function(pdev, pfn, &id);
2396
11.0k
    gs_function_free(pfn, false, mem);
2397
11.0k
    if (code < 0)
2398
0
        return code;
2399
11.0k
    gs_snprintf(ids, id_max, "%s%s%"PRId64" 0 R", key, (key[0] && key[0] != ' ' ? " " : ""), id);
2400
11.0k
    return 0;
2401
11.0k
}
2402
static int
2403
pdf_write_transfer(gx_device_pdf *pdev, const gx_transfer_map *map,
2404
                   const char *key, char *ids, int id_max)
2405
16.1k
{
2406
16.1k
    return pdf_write_transfer_map(pdev, map, 0, true, key, ids, id_max);
2407
16.1k
}
2408
2409
/* ------ Halftones ------ */
2410
2411
/*
2412
 * Recognize the predefined PDF halftone functions.  Note that because the
2413
 * corresponding PostScript functions use single-precision floats, the
2414
 * functions used for testing must do the same in order to get identical
2415
 * results.  Currently we only do this for a few of the functions.
2416
 */
2417
#define HT_FUNC(name, expr)\
2418
348k
  static double name(double xd, double yd) {\
2419
348k
    float x = (float)xd, y = (float)yd;\
2420
348k
    return d2f(expr);\
2421
348k
  }
gdevpdfg.c:ht_EllipseA
Line
Count
Source
2418
27.1k
  static double name(double xd, double yd) {\
2419
27.1k
    float x = (float)xd, y = (float)yd;\
2420
27.1k
    return d2f(expr);\
2421
27.1k
  }
gdevpdfg.c:ht_InvertedEllipseA
Line
Count
Source
2418
27.1k
  static double name(double xd, double yd) {\
2419
27.1k
    float x = (float)xd, y = (float)yd;\
2420
27.1k
    return d2f(expr);\
2421
27.1k
  }
gdevpdfg.c:ht_EllipseB
Line
Count
Source
2418
27.1k
  static double name(double xd, double yd) {\
2419
27.1k
    float x = (float)xd, y = (float)yd;\
2420
27.1k
    return d2f(expr);\
2421
27.1k
  }
gdevpdfg.c:ht_EllipseC
Line
Count
Source
2418
27.1k
  static double name(double xd, double yd) {\
2419
27.1k
    float x = (float)xd, y = (float)yd;\
2420
27.1k
    return d2f(expr);\
2421
27.1k
  }
gdevpdfg.c:ht_InvertedEllipseC
Line
Count
Source
2418
27.1k
  static double name(double xd, double yd) {\
2419
27.1k
    float x = (float)xd, y = (float)yd;\
2420
27.1k
    return d2f(expr);\
2421
27.1k
  }
gdevpdfg.c:ht_Line
Line
Count
Source
2418
27.1k
  static double name(double xd, double yd) {\
2419
27.1k
    float x = (float)xd, y = (float)yd;\
2420
27.1k
    return d2f(expr);\
2421
27.1k
  }
gdevpdfg.c:ht_LineX
Line
Count
Source
2418
15.4k
  static double name(double xd, double yd) {\
2419
15.4k
    float x = (float)xd, y = (float)yd;\
2420
15.4k
    return d2f(expr);\
2421
15.4k
  }
gdevpdfg.c:ht_LineY
Line
Count
Source
2418
15.4k
  static double name(double xd, double yd) {\
2419
15.4k
    float x = (float)xd, y = (float)yd;\
2420
15.4k
    return d2f(expr);\
2421
15.4k
  }
gdevpdfg.c:ht_Square
Line
Count
Source
2418
15.4k
  static double name(double xd, double yd) {\
2419
15.4k
    float x = (float)xd, y = (float)yd;\
2420
30.8k
    return d2f(expr);\
2421
15.4k
  }
gdevpdfg.c:ht_Cross
Line
Count
Source
2418
15.4k
  static double name(double xd, double yd) {\
2419
15.4k
    float x = (float)xd, y = (float)yd;\
2420
30.8k
    return d2f(expr);\
2421
15.4k
  }
gdevpdfg.c:ht_Rhomboid
Line
Count
Source
2418
15.4k
  static double name(double xd, double yd) {\
2419
15.4k
    float x = (float)xd, y = (float)yd;\
2420
15.4k
    return d2f(expr);\
2421
15.4k
  }
gdevpdfg.c:ht_DoubleDot
Line
Count
Source
2418
15.4k
  static double name(double xd, double yd) {\
2419
15.4k
    float x = (float)xd, y = (float)yd;\
2420
15.4k
    return d2f(expr);\
2421
15.4k
  }
gdevpdfg.c:ht_InvertedDoubleDot
Line
Count
Source
2418
15.4k
  static double name(double xd, double yd) {\
2419
15.4k
    float x = (float)xd, y = (float)yd;\
2420
15.4k
    return d2f(expr);\
2421
15.4k
  }
gdevpdfg.c:ht_SimpleDot
Line
Count
Source
2418
15.4k
  static double name(double xd, double yd) {\
2419
15.4k
    float x = (float)xd, y = (float)yd;\
2420
15.4k
    return d2f(expr);\
2421
15.4k
  }
gdevpdfg.c:ht_InvertedSimpleDot
Line
Count
Source
2418
15.4k
  static double name(double xd, double yd) {\
2419
15.4k
    float x = (float)xd, y = (float)yd;\
2420
15.4k
    return d2f(expr);\
2421
15.4k
  }
gdevpdfg.c:ht_CosineDot
Line
Count
Source
2418
15.4k
  static double name(double xd, double yd) {\
2419
15.4k
    float x = (float)xd, y = (float)yd;\
2420
15.4k
    return d2f(expr);\
2421
15.4k
  }
gdevpdfg.c:ht_Double
Line
Count
Source
2418
15.4k
  static double name(double xd, double yd) {\
2419
15.4k
    float x = (float)xd, y = (float)yd;\
2420
15.4k
    return d2f(expr);\
2421
15.4k
  }
gdevpdfg.c:ht_InvertedDouble
Line
Count
Source
2418
15.4k
  static double name(double xd, double yd) {\
2419
15.4k
    float x = (float)xd, y = (float)yd;\
2420
15.4k
    return d2f(expr);\
2421
15.4k
  }
2422
2423
/*
2424
 * In most versions of gcc (e.g., 2.7.2.3, 2.95.4), return (float)xxx
2425
 * doesn't actually do the coercion.  Force this here.  Note that if we
2426
 * use 'inline', it doesn't work.
2427
 */
2428
static float
2429
d2f(double d)
2430
1.44M
{
2431
1.44M
    float f = (float)d;
2432
1.44M
    return f;
2433
1.44M
}
2434
static double
2435
ht_Round(double xf, double yf)
2436
67.5k
{
2437
67.5k
    float x = (float)xf, y = (float)yf;
2438
67.5k
    float xabs = fabs(x), yabs = fabs(y);
2439
2440
67.5k
    if (d2f(xabs + yabs) <= 1)
2441
33.7k
        return d2f(1 - d2f(d2f(x * x) + d2f(y * y)));
2442
33.7k
    xabs -= 1, yabs -= 1;
2443
33.7k
    return d2f(d2f(d2f(xabs * xabs) + d2f(yabs * yabs)) - 1);
2444
67.5k
}
2445
static double
2446
ht_Diamond(double xf, double yf)
2447
27.1k
{
2448
27.1k
    float x = (float)xf, y = (float)yf;
2449
27.1k
    float xabs = fabs(x), yabs = fabs(y);
2450
2451
27.1k
    if (d2f(xabs + yabs) <= 0.75)
2452
11.0k
        return d2f(1 - d2f(d2f(x * x) + d2f(y * y)));
2453
16.0k
    if (d2f(xabs + yabs) <= d2f(1.23))
2454
5.06k
        return d2f(1 - d2f(d2f(d2f(0.85) * xabs) + yabs));
2455
11.0k
    xabs -= 1, yabs -= 1;
2456
11.0k
    return d2f(d2f(d2f(xabs * xabs) + d2f(yabs * yabs)) - 1);
2457
16.0k
}
2458
static double
2459
ht_Ellipse(double xf, double yf)
2460
27.1k
{
2461
27.1k
    float x = (float)xf, y = (float)yf;
2462
27.1k
    float xabs = fabs(x), yabs = fabs(y);
2463
    /*
2464
     * The PDF Reference, 2nd edition, incorrectly specifies the
2465
     * computation w = 4 * |x| + 3 * |y| - 3.  The PostScript code in the
2466
     * same book correctly implements w = 3 * |x| + 4 * |y| - 3.
2467
     */
2468
27.1k
    float w = (float)(d2f(d2f(3 * xabs) + d2f(4 * yabs)) - 3);
2469
2470
27.1k
    if (w < 0) {
2471
12.0k
        yabs /= 0.75;
2472
12.0k
        return d2f(1 - d2f((d2f(x * x) + d2f(yabs * yabs)) / 4));
2473
12.0k
    }
2474
15.0k
    if (w > 1) {
2475
12.0k
        xabs = 1 - xabs, yabs = d2f(1 - yabs) / 0.75;
2476
12.0k
        return d2f(d2f((d2f(xabs * xabs) + d2f(yabs * yabs)) / 4) - 1);
2477
12.0k
    }
2478
2.97k
    return d2f(0.5 - w);
2479
15.0k
}
2480
/*
2481
 * Most of these are recognized properly even without d2f.  We've only
2482
 * added d2f where it apparently makes a difference.
2483
 */
2484
static float
2485
123k
d2fsin_d(double x) {
2486
123k
    return d2f(gs_sin_degrees(d2f(x)));
2487
123k
}
2488
static float
2489
30.8k
d2fcos_d(double x) {
2490
30.8k
    return d2f(gs_cos_degrees(d2f(x)));
2491
30.8k
}
2492
HT_FUNC(ht_EllipseA, 1 - (x * x + 0.9 * y * y))
2493
HT_FUNC(ht_InvertedEllipseA, x * x + 0.9 * y * y - 1)
2494
HT_FUNC(ht_EllipseB, 1 - sqrt(x * x + 0.625 * y * y))
2495
HT_FUNC(ht_EllipseC, 1 - (0.9 * x * x + y * y))
2496
HT_FUNC(ht_InvertedEllipseC, 0.9 * x * x + y * y - 1)
2497
HT_FUNC(ht_Line, -fabs((x - x) + y)) /* quiet compiler (unused variable x) */
2498
HT_FUNC(ht_LineX, (y - y) + x) /* quiet compiler (unused variable y) */
2499
HT_FUNC(ht_LineY, (x - x) + y) /* quiet compiler (unused variable x) */
2500
HT_FUNC(ht_Square, -max(fabs(x), fabs(y)))
2501
HT_FUNC(ht_Cross, -min(fabs(x), fabs(y)))
2502
HT_FUNC(ht_Rhomboid, (0.9 * fabs(x) + fabs(y)) / 2)
2503
HT_FUNC(ht_DoubleDot, (d2fsin_d(x * 360) + d2fsin_d(y * 360)) / 2)
2504
HT_FUNC(ht_InvertedDoubleDot, -(d2fsin_d(x * 360) + d2fsin_d(y * 360)) / 2)
2505
HT_FUNC(ht_SimpleDot, 1 - d2f(d2f(x * x) + d2f(y * y)))
2506
HT_FUNC(ht_InvertedSimpleDot, d2f(d2f(x * x) + d2f(y * y)) - 1)
2507
HT_FUNC(ht_CosineDot, (d2fcos_d(x * 180) + d2fcos_d(y * 180)) / 2)
2508
HT_FUNC(ht_Double, (d2fsin_d(x * 180) + d2fsin_d(y * 360)) / 2)
2509
HT_FUNC(ht_InvertedDouble, -(d2fsin_d(x * 180) + d2fsin_d(y * 360)) / 2)
2510
typedef struct ht_function_s {
2511
    const char *fname;
2512
    double (*proc)(double, double);
2513
} ht_function_t;
2514
static const ht_function_t ht_functions[] = {
2515
    {"Round", ht_Round},
2516
    {"Diamond", ht_Diamond},
2517
    {"Ellipse", ht_Ellipse},
2518
    {"EllipseA", ht_EllipseA},
2519
    {"InvertedEllipseA", ht_InvertedEllipseA},
2520
    {"EllipseB", ht_EllipseB},
2521
    {"EllipseC", ht_EllipseC},
2522
    {"InvertedEllipseC", ht_InvertedEllipseC},
2523
    {"Line", ht_Line},
2524
    {"LineX", ht_LineX},
2525
    {"LineY", ht_LineY},
2526
    {"Square", ht_Square},
2527
    {"Cross", ht_Cross},
2528
    {"Rhomboid", ht_Rhomboid},
2529
    {"DoubleDot", ht_DoubleDot},
2530
    {"InvertedDoubleDot", ht_InvertedDoubleDot},
2531
    {"SimpleDot", ht_SimpleDot},
2532
    {"InvertedSimpleDot", ht_InvertedSimpleDot},
2533
    {"CosineDot", ht_CosineDot},
2534
    {"Double", ht_Double},
2535
    {"InvertedDouble", ht_InvertedDouble}
2536
};
2537
2538
/* Write each kind of halftone. */
2539
static int
2540
pdf_write_spot_function(gx_device_pdf *pdev, const gx_ht_order *porder,
2541
                        int64_t *pid)
2542
858
{
2543
    /****** DOESN'T HANDLE STRIP HALFTONES ******/
2544
858
    int w = porder->width, h = porder->height;
2545
858
    uint num_bits = porder->num_bits;
2546
858
    gs_function_Sd_params_t params;
2547
858
    static const float domain_spot[4] = { -1, 1, -1, 1 };
2548
858
    static const float range_spot[4] = { -1, 1 };
2549
858
    int size[2];
2550
858
    gs_memory_t *mem = pdev->pdf_memory;
2551
    /*
2552
     * Even though the values are logically ushort, we must always store
2553
     * them in big-endian order, so we access them as bytes.
2554
     */
2555
858
    byte *values;
2556
858
    gs_function_t *pfn;
2557
858
    uint i;
2558
858
    int code = 0;
2559
2560
858
    params.array_size = 0;
2561
858
    params.m = 2;
2562
858
    params.Domain = domain_spot;
2563
858
    params.n = 1;
2564
858
    params.Range = range_spot;
2565
858
    params.Order = 0;   /* default */
2566
    /*
2567
     * We could use 8, 16, or 32 bits per sample to save space, but for
2568
     * simplicity, we always use 16.
2569
     */
2570
858
    if (num_bits > 0x10000)
2571
        /* rangecheck is a 'special case' in gdev_pdf_fill_path, if this error is encountered
2572
         * then it 'falls back' to a different method assuming its handling transparency in an
2573
         * old PDF output version. But if we fail to write the halftone, we want to abort
2574
         * so use limitcheck instead.
2575
         */
2576
0
        return_error(gs_error_limitcheck);
2577
858
    params.BitsPerSample = 16;
2578
858
    params.Encode = 0;
2579
    /*
2580
     * The default Decode array maps the actual data values [1 .. w*h] to a
2581
     * sub-interval of the Range, but that's OK, since all that matters is
2582
     * the relative values, not the absolute values.
2583
     */
2584
858
    params.Decode = 0;
2585
858
    size[0] = w;
2586
858
    size[1] = h;
2587
858
    params.Size = size;
2588
    /* Create the (temporary) threshold array. */
2589
858
    values = gs_alloc_byte_array(mem, num_bits, 2, "pdf_write_spot_function");
2590
858
    if (values == 0)
2591
0
        return_error(gs_error_VMerror);
2592
31.7k
    for (i = 0; i < num_bits; ++i) {
2593
30.8k
        gs_int_point pt;
2594
30.8k
        int value;
2595
2596
30.8k
        if ((code = porder->procs->bit_index(porder, i, &pt)) < 0)
2597
0
            break;
2598
30.8k
        value = pt.y * w + pt.x;
2599
        /* Always store the values in big-endian order. */
2600
30.8k
        values[i * 2] = (byte)(value >> 8);
2601
30.8k
        values[i * 2 + 1] = (byte)value;
2602
30.8k
    }
2603
858
    data_source_init_bytes(&params.DataSource, (const byte *)values,
2604
858
                           sizeof(*values) * num_bits);
2605
858
    if (code >= 0 &&
2606
    /* Warning from COverity that params.array_size is uninitialised. Correct */
2607
    /* but immeidiately after copying the data Sd_init sets the copied value  */
2608
    /* to zero, so it is not actually used uninitialised. */
2609
858
        (code = gs_function_Sd_init(&pfn, &params, mem)) >= 0
2610
858
        ) {
2611
858
        code = pdf_write_function(pdev, pfn, pid);
2612
858
        gs_function_free(pfn, false, mem);
2613
858
    }
2614
858
    gs_free_object(mem, values, "pdf_write_spot_function");
2615
858
    return code;
2616
858
}
2617
2618
/* if (memcmp(order.levels, porder->levels, order.num_levels * sizeof(*order.levels))) */
2619
static int
2620
23.3k
compare_gx_ht_order_levels(const gx_ht_order *order1, const gx_ht_order *order2) {
2621
23.3k
  int i;
2622
493k
  for (i=0;  i<order1->num_levels;  i++) {
2623
469k
    if (order1->levels[i] != order2->levels[i])
2624
0
      return(1);
2625
469k
  }
2626
23.3k
  return(0);
2627
23.3k
}
2628
2629
static int
2630
pdf_write_spot_halftone(gx_device_pdf *pdev, const gs_spot_halftone *psht,
2631
                        const gx_ht_order *porder, long *pid)
2632
5.94k
{
2633
5.94k
    char trs[17 + MAX_FN_CHARS + 1];
2634
5.94k
    int code;
2635
5.94k
    int64_t spot_id;
2636
5.94k
    stream *s;
2637
5.94k
    int i = countof(ht_functions);
2638
5.94k
    gs_memory_t *mem = pdev->pdf_memory;
2639
2640
5.94k
    if (pdev->CompatibilityLevel <= 1.7) {
2641
5.94k
        code = pdf_write_transfer(pdev, porder->transfer, "/TransferFunction",
2642
5.94k
                                  trs, sizeof(trs));
2643
5.94k
        if (code < 0)
2644
0
            return code;
2645
5.94k
    }
2646
    /*
2647
     * See if we can recognize the spot function, by comparing its sampled
2648
     * values against those in the order.
2649
     */
2650
5.94k
    { gs_screen_enum senum;
2651
5.94k
        gx_ht_order order;
2652
5.94k
        int code;
2653
2654
5.94k
        order = *porder;
2655
5.94k
        code = gs_screen_order_alloc(&order, mem);
2656
5.94k
        if (code < 0)
2657
0
            goto notrec;
2658
24.1k
        for (i = 0; i < countof(ht_functions); ++i) {
2659
23.3k
            double (*spot_proc)(double, double) = ht_functions[i].proc;
2660
23.3k
            gs_point pt;
2661
2662
23.3k
            gs_screen_enum_init_memory(&senum, &order, NULL, &psht->screen,
2663
23.3k
                                       mem);
2664
493k
            while ((code = gs_screen_currentpoint(&senum, &pt)) == 0 &&
2665
469k
                   gs_screen_next(&senum, spot_proc(pt.x, pt.y)) >= 0)
2666
469k
                DO_NOTHING;
2667
23.3k
            if (code < 0)
2668
0
                continue;
2669
            /* Compare the bits and levels arrays. */
2670
23.3k
            if (compare_gx_ht_order_levels(&order,porder))
2671
0
                continue;
2672
23.3k
            if (memcmp(order.bit_data, porder->bit_data,
2673
23.3k
                       (size_t)order.num_bits *
2674
23.3k
                                      porder->procs->bit_data_elt_size))
2675
18.2k
                continue;
2676
            /* We have a match. */
2677
5.08k
            break;
2678
23.3k
        }
2679
5.94k
        gx_ht_order_release(&order, mem, false);
2680
5.94k
    }
2681
5.94k
 notrec:
2682
5.94k
    if (i == countof(ht_functions)) {
2683
        /* Create and write a Function for the spot function. */
2684
858
        code = pdf_write_spot_function(pdev, porder, &spot_id);
2685
858
        if (code < 0)
2686
0
            return code;
2687
858
    }
2688
5.94k
    *pid = pdf_begin_separate(pdev, resourceHalftone);
2689
5.94k
    s = pdev->strm;
2690
    /* Use the original, requested frequency and angle. */
2691
5.94k
    pprintg2(s, "<</Type/Halftone/HalftoneType 1/Frequency %g/Angle %g",
2692
5.94k
             psht->screen.frequency, psht->screen.angle);
2693
5.94k
    if (i < countof(ht_functions))
2694
5.08k
        pprints1(s, "/SpotFunction/%s", ht_functions[i].fname);
2695
858
    else
2696
858
        pprinti64d1(s, "/SpotFunction %"PRId64" 0 R", spot_id);
2697
5.94k
    if (pdev->CompatibilityLevel <= 1.7)
2698
5.94k
        stream_puts(s, trs);
2699
5.94k
    if (psht->accurate_screens)
2700
0
        stream_puts(s, "/AccurateScreens true");
2701
5.94k
    stream_puts(s, ">>\n");
2702
5.94k
    return pdf_end_separate(pdev, resourceHalftone);
2703
5.94k
}
2704
static int
2705
pdf_write_screen_halftone(gx_device_pdf *pdev, const gs_screen_halftone *psht,
2706
                          const gx_ht_order *porder, long *pid)
2707
889
{
2708
889
    gs_spot_halftone spot;
2709
2710
889
    spot.screen = *psht;
2711
889
    spot.accurate_screens = false;
2712
889
    spot.transfer = 0;
2713
889
    spot.transfer_closure.proc = 0;
2714
889
    return pdf_write_spot_halftone(pdev, &spot, porder, pid);
2715
889
}
2716
static int
2717
pdf_write_colorscreen_halftone(gx_device_pdf *pdev,
2718
                               const gs_colorscreen_halftone *pcsht,
2719
                               const gx_device_halftone *pdht, long *pid)
2720
0
{
2721
0
    int i;
2722
0
    stream *s;
2723
0
    long ht_ids[4];
2724
2725
0
    for (i = 0; i < pdht->num_comp ; ++i) {
2726
0
        int code = pdf_write_screen_halftone(pdev, &pcsht->screens.indexed[i],
2727
0
                                             &pdht->components[i].corder,
2728
0
                                             &ht_ids[i]);
2729
0
        if (code < 0)
2730
0
            return code;
2731
0
    }
2732
0
    *pid = pdf_begin_separate(pdev, resourceHalftone);
2733
0
    s = pdev->strm;
2734
    /* Use Black, Gray as the Default unless we are in RGB colormodel */
2735
    /* (num_comp < 4) in which case we use Green (arbitrarily) */
2736
0
    pprintld1(s, "<</Type/Halftone/HalftoneType 5/Default %ld 0 R\n",
2737
0
              pdht->num_comp > 3 ? ht_ids[3] : ht_ids[1]);
2738
0
    pprintld2(s, "/Red %ld 0 R/Cyan %ld 0 R", ht_ids[0], ht_ids[0]);
2739
0
    pprintld2(s, "/Green %ld 0 R/Magenta %ld 0 R", ht_ids[1], ht_ids[1]);
2740
0
    pprintld2(s, "/Blue %ld 0 R/Yellow %ld 0 R", ht_ids[2], ht_ids[2]);
2741
0
    if (pdht->num_comp > 3)
2742
0
    pprintld2(s, "/Gray %ld 0 R/Black %ld 0 R", ht_ids[3], ht_ids[3]);
2743
0
    stream_puts(s, ">>\n");
2744
0
    return pdf_end_separate(pdev, resourceHalftone);
2745
0
}
2746
2747
#define CHECK(expr)\
2748
0
  BEGIN if ((code = (expr)) < 0) return code; END
2749
2750
static int
2751
pdf_write_threshold_halftone(gx_device_pdf *pdev,
2752
                             const gs_threshold_halftone *ptht,
2753
                             const gx_ht_order *porder, long *pid)
2754
0
{
2755
0
    char trs[17 + MAX_FN_CHARS + 1];
2756
0
    pdf_data_writer_t writer;
2757
0
    int code;
2758
2759
0
    memset(trs, 0x00, 17 + MAX_FN_CHARS + 1);
2760
0
    if (pdev->CompatibilityLevel <= 1.7) {
2761
0
        code = pdf_write_transfer(pdev, porder->transfer, "",
2762
0
                                  trs, sizeof(trs));
2763
2764
0
        if (code < 0)
2765
0
            return code;
2766
0
    }
2767
0
    CHECK(pdf_begin_data(pdev, &writer));
2768
0
    *pid = writer.pres->object->id;
2769
0
    CHECK(cos_dict_put_c_strings((cos_dict_t *)writer.pres->object,
2770
0
        "/Type", "/Halftone"));
2771
0
    CHECK(cos_dict_put_c_strings((cos_dict_t *)writer.pres->object,
2772
0
        "/HalftoneType", "6"));
2773
0
    CHECK(cos_dict_put_c_key_int((cos_dict_t *)writer.pres->object,
2774
0
        "/Width", ptht->width));
2775
0
    CHECK(cos_dict_put_c_key_int((cos_dict_t *)writer.pres->object,
2776
0
        "/Height", ptht->height));
2777
0
    if (pdev->CompatibilityLevel <= 1.7 && trs[0] != 0)
2778
0
        CHECK(cos_dict_put_c_strings((cos_dict_t *)writer.pres->object,
2779
0
            "/TransferFunction", trs));
2780
0
    stream_write(writer.binary.strm, ptht->thresholds.data, ptht->thresholds.size);
2781
0
    return pdf_end_data(&writer);
2782
0
}
2783
static int
2784
pdf_write_threshold2_halftone(gx_device_pdf *pdev,
2785
                              const gs_threshold2_halftone *ptht,
2786
                              const gx_ht_order *porder, long *pid)
2787
0
{
2788
0
    char trs[17 + MAX_FN_CHARS + 1];
2789
0
    stream *s;
2790
0
    pdf_data_writer_t writer;
2791
0
    int code;
2792
2793
0
    memset(trs, 0x00, 17 + MAX_FN_CHARS + 1);
2794
0
    if (pdev->CompatibilityLevel <= 1.7) {
2795
0
        code = pdf_write_transfer(pdev, porder->transfer, "",
2796
0
                                  trs, sizeof(trs));
2797
2798
0
        if (code < 0)
2799
0
            return code;
2800
0
    }
2801
0
    CHECK(pdf_begin_data(pdev, &writer));
2802
0
    *pid = writer.pres->object->id;
2803
0
    CHECK(cos_dict_put_c_strings((cos_dict_t *)writer.pres->object,
2804
0
        "/Type", "/Halftone"));
2805
0
    CHECK(cos_dict_put_c_strings((cos_dict_t *)writer.pres->object,
2806
0
        "/HalftoneType", "16"));
2807
0
    CHECK(cos_dict_put_c_key_int((cos_dict_t *)writer.pres->object,
2808
0
        "/Width", ptht->width));
2809
0
    CHECK(cos_dict_put_c_key_int((cos_dict_t *)writer.pres->object,
2810
0
        "/Height", ptht->height));
2811
0
    if (ptht->width2 && ptht->height2) {
2812
0
        CHECK(cos_dict_put_c_key_int((cos_dict_t *)writer.pres->object,
2813
0
            "/Width2", ptht->width2));
2814
0
        CHECK(cos_dict_put_c_key_int((cos_dict_t *)writer.pres->object,
2815
0
            "/Height2", ptht->height2));
2816
0
    }
2817
0
    if (pdev->CompatibilityLevel <= 1.7 && trs[0] != 0)
2818
0
        CHECK(cos_dict_put_c_strings((cos_dict_t *)writer.pres->object,
2819
0
            "/TransferFunction", trs));
2820
0
    s = writer.binary.strm;
2821
0
    if (ptht->bytes_per_sample == 2)
2822
0
        stream_write(s, ptht->thresholds.data, ptht->thresholds.size);
2823
0
    else {
2824
        /* Expand 1-byte to 2-byte samples. */
2825
0
        int i;
2826
2827
0
        for (i = 0; i < ptht->thresholds.size; ++i) {
2828
0
            byte b = ptht->thresholds.data[i];
2829
2830
0
            stream_putc(s, b);
2831
0
            stream_putc(s, b);
2832
0
        }
2833
0
    }
2834
0
    return pdf_end_data(&writer);
2835
0
}
2836
static int
2837
pdf_get_halftone_component_index(const gs_multiple_halftone *pmht,
2838
                                 const gx_device_halftone *pdht,
2839
                                 int dht_index)
2840
30.3k
{
2841
30.3k
    int j;
2842
2843
60.6k
    for (j = 0; j < pmht->num_comp; j++)
2844
30.3k
        if (pmht->components[j].comp_number == dht_index)
2845
0
            break;
2846
30.3k
    if (j == pmht->num_comp) {
2847
        /* Look for Default. */
2848
30.3k
        for (j = 0; j < pmht->num_comp; j++)
2849
30.3k
            if (pmht->components[j].comp_number == GX_DEVICE_COLOR_MAX_COMPONENTS)
2850
30.3k
                break;
2851
30.3k
        if (j == pmht->num_comp)
2852
0
            return_error(gs_error_undefined);
2853
30.3k
    }
2854
30.3k
    return j;
2855
30.3k
}
2856
static int
2857
pdf_write_multiple_halftone(gx_device_pdf *pdev, gs_gstate *pgs,
2858
                            const gs_multiple_halftone *pmht,
2859
                            const gx_device_halftone *pdht, long *pid)
2860
5.05k
{
2861
5.05k
    stream *s;
2862
5.05k
    int i, code, last_comp = 0;
2863
5.05k
    gs_memory_t *mem = pdev->pdf_memory;
2864
5.05k
    long *ids;
2865
5.05k
    bool done_Default = false;
2866
2867
5.05k
    ids = (long *)gs_alloc_byte_array(mem, pmht->num_comp, sizeof(long),
2868
5.05k
                                      "pdf_write_multiple_halftone");
2869
5.05k
    if (ids == 0)
2870
0
        return_error(gs_error_VMerror);
2871
20.2k
    for (i = 0; i < pdht->num_comp; ++i) {
2872
15.1k
        const gs_halftone_component *phtc;
2873
15.1k
        const gx_ht_order *porder;
2874
2875
15.1k
        code = pdf_get_halftone_component_index(pmht, pdht, i);
2876
15.1k
        if (code < 0)
2877
0
            return code;
2878
15.1k
        if (pmht->components[code].comp_number == GX_DEVICE_COLOR_MAX_COMPONENTS) {
2879
15.1k
            if (done_Default)
2880
10.1k
                continue;
2881
5.05k
            done_Default = true;
2882
5.05k
        }
2883
5.05k
        phtc = &pmht->components[code];
2884
5.05k
        porder = (pdht->components == 0 ? &pdht->order :
2885
5.05k
                       &pdht->components[i].corder);
2886
5.05k
        switch (phtc->type) {
2887
5.05k
        case ht_type_spot:
2888
5.05k
            code = pdf_write_spot_halftone(pdev, &phtc->params.spot,
2889
5.05k
                                           porder, &ids[i]);
2890
5.05k
            break;
2891
0
        case ht_type_threshold:
2892
0
            code = pdf_write_threshold_halftone(pdev, &phtc->params.threshold,
2893
0
                                                porder, &ids[i]);
2894
0
            break;
2895
0
        case ht_type_threshold2:
2896
0
            code = pdf_write_threshold2_halftone(pdev,
2897
0
                                                 &phtc->params.threshold2,
2898
0
                                                 porder, &ids[i]);
2899
0
            break;
2900
0
        default:
2901
0
            code = gs_note_error(gs_error_rangecheck);
2902
5.05k
        }
2903
5.05k
        if (code < 0) {
2904
0
            gs_free_object(mem, ids, "pdf_write_multiple_halftone");
2905
0
            return code;
2906
0
        }
2907
5.05k
    }
2908
5.05k
    *pid = pdf_begin_separate(pdev, resourceHalftone);
2909
5.05k
    s = pdev->strm;
2910
5.05k
    stream_puts(s, "<</Type/Halftone/HalftoneType 5\n");
2911
5.05k
    done_Default = false;
2912
20.2k
    for (i = 0; i < pdht->num_comp; ++i) {
2913
15.1k
        const gs_halftone_component *phtc;
2914
15.1k
        byte *str;
2915
15.1k
        uint len;
2916
15.1k
        cos_value_t value;
2917
2918
15.1k
        code = pdf_get_halftone_component_index(pmht, pdht, i);
2919
15.1k
        if (code < 0)
2920
0
            return code;
2921
15.1k
        if (pmht->components[code].comp_number == GX_DEVICE_COLOR_MAX_COMPONENTS) {
2922
15.1k
            if (done_Default)
2923
10.1k
                continue;
2924
5.05k
            done_Default = true;
2925
5.05k
        }
2926
5.05k
        phtc = &pmht->components[code];
2927
5.05k
        if ((code = pmht->get_colorname_string(pgs, phtc->cname, &str, &len)) < 0 ||
2928
5.05k
            (code = pdf_string_to_cos_name(pdev, str, len, &value)) < 0)
2929
0
            return code;
2930
5.05k
        cos_value_write(&value, pdev);
2931
5.05k
        gs_free_string(mem, value.contents.chars.data,
2932
5.05k
                       value.contents.chars.size,
2933
5.05k
                       "pdf_write_multiple_halftone");
2934
5.05k
        pprintld1(s, " %ld 0 R\n", ids[i]);
2935
5.05k
        last_comp = i;
2936
5.05k
    }
2937
5.05k
    if (!done_Default) {
2938
        /*
2939
         * BOGUS: Type 5 halftones must contain Default component.
2940
         * Perhaps we have no way to obtain it,
2941
         * because pdht contains ProcessColorModel components only.
2942
         * We copy the last component as Default one.
2943
         */
2944
0
        pprintld1(s, " /Default %ld 0 R\n", ids[last_comp]);
2945
0
    }
2946
5.05k
    stream_puts(s, ">>\n");
2947
5.05k
    gs_free_object(mem, ids, "pdf_write_multiple_halftone");
2948
5.05k
    return pdf_end_separate(pdev, resourceHalftone);
2949
5.05k
}
2950
2951
/*
2952
 * Update the halftone.  This is a separate procedure only for
2953
 * readability.
2954
 */
2955
static int
2956
pdf_update_halftone(gx_device_pdf *pdev, const gs_gstate *pgs,
2957
                    char *hts, int hts_max)
2958
5.94k
{
2959
5.94k
    const gs_halftone *pht = pgs->halftone;
2960
5.94k
    const gx_device_halftone *pdht = pgs->dev_ht[HT_OBJTYPE_DEFAULT];
2961
5.94k
    int code;
2962
5.94k
    long id;
2963
2964
5.94k
    switch (pht->type) {
2965
889
    case ht_type_screen:
2966
889
        code = pdf_write_screen_halftone(pdev, &pht->params.screen,
2967
889
                                         &pdht->components[0].corder, &id);
2968
889
        break;
2969
0
    case ht_type_colorscreen:
2970
0
        code = pdf_write_colorscreen_halftone(pdev, &pht->params.colorscreen,
2971
0
                                              pdht, &id);
2972
0
        break;
2973
0
    case ht_type_spot:
2974
0
        code = pdf_write_spot_halftone(pdev, &pht->params.spot,
2975
0
                                       &pdht->components[0].corder, &id);
2976
0
        break;
2977
0
    case ht_type_threshold:
2978
0
        code = pdf_write_threshold_halftone(pdev, &pht->params.threshold,
2979
0
                                            &pdht->components[0].corder, &id);
2980
0
        break;
2981
0
    case ht_type_threshold2:
2982
0
        code = pdf_write_threshold2_halftone(pdev, &pht->params.threshold2,
2983
0
                                             &pdht->components[0].corder, &id);
2984
0
        break;
2985
5.05k
    case ht_type_multiple:
2986
5.05k
    case ht_type_multiple_colorscreen:
2987
5.05k
        code = pdf_write_multiple_halftone(pdev, (gs_gstate *)pgs, &pht->params.multiple,
2988
5.05k
                                           pdht, &id);
2989
5.05k
        break;
2990
0
    default:
2991
0
        return_error(gs_error_rangecheck);
2992
5.94k
    }
2993
5.94k
    if (code < 0)
2994
0
        return code;
2995
5.94k
    gs_snprintf(hts, hts_max, "%ld 0 R", id);
2996
5.94k
    pdev->halftone_id = pgs->dev_ht[HT_OBJTYPE_DEFAULT]->id;
2997
5.94k
    return code;
2998
5.94k
}
2999
3000
/* ------ Graphics state updating ------ */
3001
3002
static inline cos_dict_t *
3003
resource_dict(pdf_resource_t *pres)
3004
145k
{
3005
145k
    return (cos_dict_t *)pres->object;
3006
145k
}
3007
3008
/* Open an ExtGState. */
3009
static int
3010
pdf_open_gstate(gx_device_pdf *pdev, pdf_resource_t **ppres)
3011
70.0k
{
3012
70.0k
    int code;
3013
3014
70.0k
    if (*ppres)
3015
6.48k
        return 0;
3016
    /*
3017
     * We write gs command only in stream context.
3018
     * If we are clipped, and the clip path is about to change,
3019
     * the old clipping must be undone before writing gs.
3020
     */
3021
63.5k
    if (pdev->context != PDF_IN_STREAM) {
3022
        /* We apparently use gs_error_interrupt as a request to change context. */
3023
4.03k
      return_error(gs_error_interrupt);
3024
4.03k
    }
3025
59.4k
    code = pdf_alloc_resource(pdev, resourceExtGState, gs_no_id, ppres, -1L);
3026
59.4k
    if (code < 0)
3027
0
        return code;
3028
59.4k
    cos_become((*ppres)->object, cos_type_dict);
3029
59.4k
    code = cos_dict_put_c_key_string(resource_dict(*ppres), "/Type", (const byte *)"/ExtGState", 10);
3030
59.4k
    if (code < 0)
3031
0
        return code;
3032
59.4k
    return 0;
3033
59.4k
}
3034
3035
/* Finish writing an ExtGState. */
3036
int
3037
pdf_end_gstate(gx_device_pdf *pdev, pdf_resource_t *pres)
3038
8.20M
{
3039
8.20M
    if (pres) {
3040
59.4k
        int code = pdf_substitute_resource(pdev, &pres, resourceExtGState, NULL, true);
3041
3042
59.4k
        if (code < 0)
3043
0
            return code;
3044
59.4k
        pres->where_used |= pdev->used_mask;
3045
59.4k
        code = pdf_open_page(pdev, PDF_IN_STREAM);
3046
59.4k
        if (code < 0)
3047
0
            return code;
3048
59.4k
        code = pdf_add_resource(pdev, pdev->substream_Resources, "/ExtGState", pres);
3049
59.4k
        if (code < 0)
3050
0
            return code;
3051
59.4k
        pprinti64d1(pdev->strm, "/R%"PRId64" gs\n", pdf_resource_id(pres));
3052
59.4k
        pres->where_used |= pdev->used_mask;
3053
59.4k
    }
3054
8.20M
    return 0;
3055
8.20M
}
3056
3057
/*
3058
 * Update the transfer functions(s).  This is a separate procedure only
3059
 * for readability.
3060
 */
3061
static int
3062
pdf_update_transfer(gx_device_pdf *pdev, const gs_gstate *pgs,
3063
                    char *trs, int trs_max)
3064
8.09M
{
3065
8.09M
    int i, pi = -1;
3066
8.09M
    bool multiple = false, update = false;
3067
8.09M
    gs_id transfer_ids[4];
3068
8.09M
    int code = 0;
3069
8.09M
    const gx_transfer_map *tm[4];
3070
3071
8.09M
    tm[0] = pgs->set_transfer.red;
3072
8.09M
    tm[1] = pgs->set_transfer.green;
3073
8.09M
    tm[2] = pgs->set_transfer.blue;
3074
8.09M
    tm[3] = pgs->set_transfer.gray;
3075
40.4M
    for (i = 0; i < 4; ++i)
3076
32.3M
        if (tm[i] != NULL) {
3077
8.09M
            transfer_ids[i] = tm[i]->id;
3078
8.09M
            if (pdev->transfer_ids[i] != tm[i]->id)
3079
10.3k
                update = true;
3080
8.09M
            if (pi != -1 && transfer_ids[i] != transfer_ids[pi])
3081
687
                multiple = true;
3082
8.09M
            pi = i;
3083
8.09M
        } else
3084
24.2M
            transfer_ids[i] = -1;
3085
8.09M
    if (update) {
3086
10.2k
        int mask;
3087
3088
10.2k
        if (!multiple) {
3089
10.2k
            code = pdf_write_transfer(pdev, tm[pi], "", trs, trs_max);
3090
10.2k
            if (code < 0)
3091
0
                return code;
3092
10.2k
            mask = code == 0;
3093
10.2k
        } else {
3094
32
            strcpy(trs, "[");
3095
32
            mask = 0;
3096
160
            for (i = 0; i < 4; ++i)
3097
128
                if (tm[i] != NULL) {
3098
128
                    int len = (int)strlen(trs);
3099
128
                    code = pdf_write_transfer_map(pdev,
3100
128
                                                  tm[i],
3101
128
                                                  0, true, " ", trs + len, trs_max - len);
3102
128
                    if (code < 0)
3103
0
                        return code;
3104
128
                    mask |= (code == 0) << i;
3105
128
                }
3106
32
            strcat(trs, "]");
3107
32
        }
3108
10.2k
        memcpy(pdev->transfer_ids, transfer_ids, sizeof(pdev->transfer_ids));
3109
10.2k
        pdev->transfer_not_identity = mask;
3110
10.2k
    }
3111
8.09M
    return code;
3112
8.09M
}
3113
3114
/*
3115
 * Update the current alpha if necessary.  Note that because Ghostscript
3116
 * stores separate opacity and shape alpha, a rangecheck will occur if
3117
 * both are different from the current setting.
3118
 */
3119
static int
3120
pdf_update_alpha(gx_device_pdf *pdev, const gs_gstate *pgs,
3121
                 pdf_resource_t **ppres, bool for_text)
3122
5.36M
{
3123
5.36M
    int code;
3124
3125
5.36M
    if (pdev->state.soft_mask_id != pgs->soft_mask_id) {
3126
404
        char buf[20];
3127
3128
404
        if (pgs->soft_mask_id == 0) {
3129
117
            char buf[256];
3130
3131
117
            code = pdf_open_contents(pdev, PDF_IN_STREAM);
3132
117
            if (code < 0)
3133
0
                return code;
3134
117
            if (pdev->vgstack_depth > pdev->vgstack_bottom) {
3135
30
                code = pdf_restore_viewer_state(pdev, pdev->strm);
3136
30
                if (code < 0)
3137
0
                    return code;
3138
30
            }
3139
117
            if (pdev->state.soft_mask_id != 0) {
3140
99
                gs_snprintf(buf, sizeof(buf), "/None");
3141
99
                code = pdf_open_gstate(pdev, ppres);
3142
99
                if (code < 0)
3143
0
                    return code;
3144
99
                code = cos_dict_put_c_key_string(resource_dict(*ppres),
3145
99
                            "/SMask", (byte *)buf, strlen(buf));
3146
99
                if (code < 0)
3147
0
                    return code;
3148
99
            }
3149
117
        }
3150
287
        else{
3151
287
            gs_snprintf(buf, sizeof(buf), "%ld 0 R", pgs->soft_mask_id);
3152
287
            code = pdf_open_gstate(pdev, ppres);
3153
287
            if (code < 0)
3154
0
                return code;
3155
287
            code = cos_dict_put_c_key_string(resource_dict(*ppres),
3156
287
                        "/SMask", (byte *)buf, strlen(buf));
3157
287
            if (code < 0)
3158
0
                return code;
3159
287
        }
3160
404
        pdev->state.soft_mask_id = pgs->soft_mask_id;
3161
404
    }
3162
3163
5.36M
    if (pdev->state.alphaisshape != pgs->alphaisshape ||
3164
5.36M
        pdev->state.strokeconstantalpha != pgs->strokeconstantalpha ||
3165
5.36M
        pdev->state.fillconstantalpha != pgs->fillconstantalpha) {
3166
3167
4.54k
        code = pdf_open_gstate(pdev, ppres);
3168
4.54k
        if (code < 0)
3169
601
            return code;
3170
3171
3.94k
        code = cos_dict_put_c_key_bool(resource_dict(*ppres), "/AIS", pgs->alphaisshape);
3172
3.94k
        if (code < 0)
3173
0
            return code;
3174
3.94k
        pdev->state.alphaisshape = pgs->alphaisshape;
3175
3.94k
        code = cos_dict_put_c_key_real(resource_dict(*ppres), "/CA", pgs->strokeconstantalpha);
3176
3.94k
        if (code < 0)
3177
0
            return code;
3178
3.94k
        pdev->state.strokeconstantalpha = pgs->strokeconstantalpha;
3179
3.94k
        code = cos_dict_put_c_key_real(resource_dict(*ppres), "/ca", pgs->fillconstantalpha);
3180
3.94k
        if (code < 0)
3181
0
            return code;
3182
3.94k
        pdev->state.fillconstantalpha = pgs->fillconstantalpha;
3183
3.94k
    }
3184
5.36M
    return 0;
3185
5.36M
}
3186
3187
/*
3188
 * Update the graphics subset common to all high-level drawing operations.
3189
 */
3190
int
3191
pdf_prepare_drawing(gx_device_pdf *pdev, const gs_gstate *pgs,
3192
                    pdf_resource_t **ppres, bool for_text)
3193
8.21M
{
3194
8.21M
    int code = 0;
3195
8.21M
    int bottom;
3196
3197
8.21M
    if (pdev->CompatibilityLevel >= 1.4) {
3198
5.36M
        code = pdf_update_alpha(pdev, pgs, ppres, for_text);
3199
5.36M
        if (code < 0)
3200
601
            return code;
3201
5.36M
        if (pdev->state.blend_mode != pgs->blend_mode) {
3202
2.88k
            static const char *const bm_names[] = { GS_BLEND_MODE_NAMES };
3203
2.88k
            char buf[20];
3204
3205
2.88k
            code = pdf_open_gstate(pdev, ppres);
3206
2.88k
            if (code < 0)
3207
43
                return code;
3208
2.84k
            buf[0] = '/';
3209
2.84k
            strncpy(buf + 1, bm_names[pgs->blend_mode], sizeof(buf) - 2);
3210
2.84k
            code = cos_dict_put_string_copy(resource_dict(*ppres), "/BM", buf);
3211
2.84k
            if (code < 0)
3212
0
                return code;
3213
2.84k
            pdev->state.blend_mode = pgs->blend_mode;
3214
2.84k
        }
3215
5.36M
    } else {
3216
        /*
3217
         * If the graphics state calls for any transparency functions,
3218
         * we can't represent them, so return a rangecheck.
3219
         */
3220
2.84M
        if (pgs->strokeconstantalpha != 1 ||
3221
2.83M
            pgs->fillconstantalpha != 1)
3222
7.49k
            return_error(gs_error_rangecheck);
3223
2.84M
    }
3224
    /*
3225
     * We originally thought the remaining items were only needed for
3226
     * fill and stroke, but in fact they are needed for images as well.
3227
     */
3228
    /*
3229
     * Update halftone, transfer function, black generation, undercolor
3230
     * removal, halftone phase, overprint mode, smoothness, blend mode, text
3231
     * knockout.
3232
     */
3233
8.20M
    bottom = (pdev->ResourcesBeforeUsage ? 1 : 0);
3234
    /* When ResourcesBeforeUsage != 0, one sbstack element
3235
       appears from the page contents stream. */
3236
8.20M
    if (pdev->sbstack_depth == bottom) {
3237
8.09M
        gs_int_point phase, dev_phase;
3238
8.09M
        char hts[5 + MAX_FN_CHARS + 1],
3239
8.09M
            trs[5 + MAX_FN_CHARS * 4 + 6 + 1],
3240
8.09M
            bgs[5 + MAX_FN_CHARS + 1],
3241
8.09M
            ucrs[6 + MAX_FN_CHARS + 1];
3242
3243
8.09M
        hts[0] = trs[0] = bgs[0] = ucrs[0] = 0;
3244
8.09M
        if (pdev->params.PreserveHalftoneInfo &&
3245
2.82M
            pdev->halftone_id != pgs->dev_ht[HT_OBJTYPE_DEFAULT]->id &&
3246
5.94k
            pdev->PDFX == 0
3247
8.09M
            ) {
3248
5.94k
            code = pdf_update_halftone(pdev, pgs, hts, sizeof(hts));
3249
5.94k
            if (code < 0)
3250
0
                return code;
3251
5.94k
        }
3252
8.09M
        if (pdev->params.TransferFunctionInfo != tfi_Remove &&
3253
8.09M
            pdev->PDFX == 0 && pdev->PDFA == 0
3254
8.09M
            ) {
3255
8.09M
            code = pdf_update_transfer(pdev, pgs, trs, sizeof(trs));
3256
8.09M
            if (code < 0)
3257
0
                return code;
3258
8.09M
        }
3259
8.09M
        if (pdev->params.UCRandBGInfo == ucrbg_Preserve) {
3260
8.09M
            if (pgs->black_generation && pdev->black_generation_id != pgs->black_generation->id) {
3261
5.47k
                code = pdf_write_transfer_map(pdev, pgs->black_generation,
3262
5.47k
                                              0, false, "", bgs, sizeof(bgs));
3263
5.47k
                if (code < 0)
3264
0
                    return code;
3265
5.47k
                pdev->black_generation_id = pgs->black_generation->id;
3266
5.47k
            }
3267
8.09M
            if (pgs->undercolor_removal && pdev->undercolor_removal_id != pgs->undercolor_removal->id) {
3268
5.46k
                code = pdf_write_transfer_map(pdev, pgs->undercolor_removal,
3269
5.46k
                                              -1, false, "", ucrs, sizeof(ucrs));
3270
5.46k
                if (code < 0)
3271
0
                    return code;
3272
5.46k
                pdev->undercolor_removal_id = pgs->undercolor_removal->id;
3273
5.46k
            }
3274
8.09M
        }
3275
8.09M
        if (hts[0] || trs[0] || bgs[0] || ucrs[0]) {
3276
16.1k
            code = pdf_open_gstate(pdev, ppres);
3277
16.1k
            if (code < 0)
3278
915
                return code;
3279
16.1k
        }
3280
8.09M
        if (hts[0]) {
3281
5.94k
            code = cos_dict_put_string_copy(resource_dict(*ppres), "/HT", hts);
3282
5.94k
            if (code < 0)
3283
0
                return code;
3284
5.94k
        }
3285
8.09M
        if (pdev->CompatibilityLevel <= 1.7 && trs[0] && pdev->params.TransferFunctionInfo == tfi_Preserve) {
3286
9.36k
            code = cos_dict_put_string_copy(resource_dict(*ppres), "/TR", trs);
3287
9.36k
            if (code < 0)
3288
0
                return code;
3289
9.36k
        }
3290
8.09M
        if (bgs[0]) {
3291
5.36k
            code = cos_dict_put_string_copy(resource_dict(*ppres), "/BG", bgs);
3292
5.36k
            if (code < 0)
3293
0
                return code;
3294
5.36k
        }
3295
8.09M
        if (ucrs[0]) {
3296
5.35k
            code = cos_dict_put_string_copy(resource_dict(*ppres), "/UCR", ucrs);
3297
5.35k
            if (code < 0)
3298
0
                return code;
3299
5.35k
        }
3300
8.09M
        if (pdev->PDFX == 0) {
3301
8.09M
            gs_currentscreenphase(pgs, &phase, 0);
3302
8.09M
            gs_currentscreenphase(&pdev->state, &dev_phase, 0);
3303
8.09M
            if ((dev_phase.x != phase.x || dev_phase.y != phase.y) && pdev->PDFA != 0) {
3304
0
                switch (pdev->PDFACompatibilityPolicy) {
3305
0
                    case 0:
3306
0
                        emprintf(pdev->memory,
3307
0
                             "\nSetting Halftone Phase or Halftone Offset\n not permitted in PDF/A, reverting to normal PDF output\n");
3308
0
                        pdev->AbortPDFAX = true;
3309
0
                        pdev->PDFA = 0;
3310
0
                        break;
3311
0
                    case 1:
3312
0
                        emprintf(pdev->memory,
3313
0
                             "\nSetting Halftone Phase or Halftone Offset\n not permitted in PDF/A, values not set\n\n");
3314
                        /* Deliberately breaking const here in order to force the graphics state overprint mode to be unchanged */
3315
0
                        dev_phase.x = phase.x;
3316
0
                        dev_phase.y = phase.y;
3317
0
                        break;
3318
0
                    case 2:
3319
0
                        emprintf(pdev->memory,
3320
0
                             "\nSetting Halftone Phase or Halftone Offset\n not permitted in PDF/A, aborting conversion\n");
3321
0
                        return_error(gs_error_undefined);
3322
0
                        break;
3323
0
                    default:
3324
0
                        emprintf(pdev->memory,
3325
0
                             "\nSetting Halftone Phase or Halftone Offset\n not permitted in PDF/A, unrecognised PDFACompatibilityLevel,\nreverting to normal PDF output\n");
3326
0
                        pdev->AbortPDFAX = true;
3327
0
                        pdev->PDFA = 0;
3328
0
                        break;
3329
0
                }
3330
0
            }
3331
8.09M
            if (dev_phase.x != phase.x || dev_phase.y != phase.y) {
3332
0
                char buf[sizeof(int) * 3 + 5];
3333
3334
0
                code = pdf_open_gstate(pdev, ppres);
3335
0
                if (code < 0)
3336
0
                    return code;
3337
0
                gs_snprintf(buf, sizeof(buf), "[%d %d]", phase.x, phase.y);
3338
0
                if (pdev->CompatibilityLevel >= 1.999)
3339
0
                    code = cos_dict_put_string_copy(resource_dict(*ppres), "/HTO", buf);
3340
0
                else
3341
0
                    code = cos_dict_put_string_copy(resource_dict(*ppres), "/HTP", buf);
3342
0
                if (code < 0)
3343
0
                    return code;
3344
0
                gx_gstate_setscreenphase(&pdev->state, phase.x, phase.y,
3345
0
                                         gs_color_select_all);
3346
0
            }
3347
8.09M
        }
3348
8.09M
    }
3349
8.20M
    if (pdev->state.overprint_mode != pdev->params.OPM) {
3350
1.97k
        if (pdev->params.OPM != pgs->overprint_mode)
3351
948
            ((gs_gstate *)pgs)->overprint_mode = pdev->params.OPM;
3352
1.97k
    }
3353
8.20M
    if (pdev->CompatibilityLevel >= 1.3 /*&& pdev->sbstack_depth == bottom */) {
3354
5.36M
        if (pdev->state.overprint_mode != pgs->overprint_mode) {
3355
10.0k
            if (pgs->overprint_mode == 1 && pdev->PDFA == 2) {
3356
0
                switch (pdev->PDFACompatibilityPolicy) {
3357
0
                    case 0:
3358
0
                        emprintf(pdev->memory,
3359
0
                             "Setting Overprint Mode to 1\n not permitted in PDF/A-2, reverting to normal PDF output\n");
3360
0
                        pdev->AbortPDFAX = true;
3361
0
                        pdev->PDFA = 0;
3362
0
                        break;
3363
0
                    case 1:
3364
0
                        emprintf(pdev->memory,
3365
0
                             "Setting Overprint Mode to 1\n not permitted in PDF/A-2, overprint mode not set\n\n");
3366
                        /* Deliberately breaking const here in order to force the graphics state overprint mode to be unchanged */
3367
0
                        ((gs_gstate *)pgs)->overprint_mode = pdev->state.overprint_mode;
3368
0
                        break;
3369
0
                    case 2:
3370
0
                        emprintf(pdev->memory,
3371
0
                             "Setting Overprint Mode to 1\n not permitted in PDF/A-2, aborting conversion\n");
3372
0
                        return_error(gs_error_undefined);
3373
0
                        break;
3374
0
                    default:
3375
0
                        emprintf(pdev->memory,
3376
0
                             "Setting Overprint Mode to 1\n not permitted in PDF/A-2, unrecognised PDFACompatibilityLevel,\nreverting to normal PDF output\n");
3377
0
                        pdev->AbortPDFAX = true;
3378
0
                        pdev->PDFA = 0;
3379
0
                        break;
3380
0
                }
3381
0
            }
3382
10.0k
            if (pdev->state.overprint_mode != pgs->overprint_mode) {
3383
10.0k
                code = pdf_open_gstate(pdev, ppres);
3384
10.0k
                if (code < 0)
3385
598
                    return code;
3386
9.49k
                code = cos_dict_put_c_key_int(resource_dict(*ppres), "/OPM", pgs->overprint_mode);
3387
9.49k
                if (code < 0)
3388
0
                    return code;
3389
9.49k
                pdev->params.OPM = pdev->state.overprint_mode = pgs->overprint_mode;
3390
9.49k
            }
3391
10.0k
        }
3392
5.36M
        if (pdev->state.smoothness != pgs->smoothness) {
3393
45
            code = pdf_open_gstate(pdev, ppres);
3394
45
            if (code < 0)
3395
3
                return code;
3396
42
            code = cos_dict_put_c_key_real(resource_dict(*ppres), "/SM", pgs->smoothness);
3397
42
            if (code < 0)
3398
0
                return code;
3399
42
            pdev->state.smoothness = pgs->smoothness;
3400
42
        }
3401
5.36M
        if (pdev->CompatibilityLevel >= 1.4) {
3402
5.36M
            if (pdev->state.text_knockout != pgs->text_knockout) {
3403
0
                code = pdf_open_gstate(pdev, ppres);
3404
0
                if (code < 0)
3405
0
                    return code;
3406
0
                code = cos_dict_put_c_key_bool(resource_dict(*ppres), "/TK", pgs->text_knockout);
3407
0
                if (code < 0)
3408
0
                    return code;
3409
0
                pdev->state.text_knockout = pgs->text_knockout;
3410
0
            }
3411
5.36M
        }
3412
5.36M
    }
3413
8.20M
    return code;
3414
8.20M
}
3415
3416
/* Update the graphics state for filling. */
3417
int
3418
pdf_try_prepare_fill(gx_device_pdf *pdev, const gs_gstate *pgs, bool for_text)
3419
7.56M
{
3420
7.56M
    pdf_resource_t *pres = 0;
3421
7.56M
    int code = pdf_prepare_drawing(pdev, pgs, &pres, for_text);
3422
3423
7.56M
    if (code < 0)
3424
8.14k
        return code;
3425
7.55M
    if (pdev->rendering_intent != pgs->renderingintent && !pdev->ForOPDFRead) {
3426
8.08k
        static const char *const ri_names[] = { "Perceptual", "RelativeColorimetric", "Saturation", "AbsoluteColorimetric" };
3427
8.08k
        char buf[32];
3428
3429
8.08k
        code = pdf_open_gstate(pdev, &pres);
3430
8.08k
        if (code < 0)
3431
135
            return code;
3432
3433
7.94k
        buf[0] = '/';
3434
7.94k
        strncpy(buf + 1, ri_names[pgs->renderingintent], sizeof(buf) - 2);
3435
7.94k
        code = cos_dict_put_string_copy(resource_dict(pres), "/RI", buf);
3436
7.94k
        if (code < 0)
3437
0
            return code;
3438
7.94k
        pdev->rendering_intent = pgs->renderingintent;
3439
7.94k
    }
3440
3441
    /* Update overprint. */
3442
7.55M
    if (pdev->params.PreserveOverprintSettings &&
3443
7.55M
        (pdev->fill_overprint != pgs->overprint ||
3444
7.54M
        pdev->font3) && !pdev->skip_colors
3445
7.55M
        ) {
3446
14.0k
        if (pres == 0)
3447
12.3k
            code = pdf_open_gstate(pdev, &pres);
3448
14.0k
        if (code < 0)
3449
1.57k
            return code;
3450
        /* PDF 1.2 only has a single overprint setting. */
3451
12.5k
        if (pdev->CompatibilityLevel < 1.3) {
3452
3.07k
            code = cos_dict_put_c_key_bool(resource_dict(pres), "/OP", pgs->overprint);
3453
3.07k
            if (code < 0)
3454
0
                return code;
3455
3.07k
            pdev->stroke_overprint = pgs->overprint;
3456
9.43k
        } else {
3457
9.43k
            code = cos_dict_put_c_key_bool(resource_dict(pres), "/op", pgs->overprint);
3458
9.43k
            if (code < 0)
3459
0
                return code;
3460
9.43k
        }
3461
12.5k
        pdev->fill_overprint = pgs->overprint;
3462
12.5k
    }
3463
7.55M
    return pdf_end_gstate(pdev, pres);
3464
7.55M
}
3465
int
3466
pdf_prepare_fill(gx_device_pdf *pdev, const gs_gstate *pgs, bool for_text)
3467
7.56M
{
3468
7.56M
    int code;
3469
3470
7.56M
    if (pdev->context != PDF_IN_STREAM) {
3471
5.45M
        code = pdf_try_prepare_fill(pdev, pgs, for_text);
3472
5.45M
        if (code != gs_error_interrupt) /* See pdf_open_gstate */
3473
5.44M
            return code;
3474
3.28k
        code = pdf_open_contents(pdev, PDF_IN_STREAM);
3475
3.28k
        if (code < 0)
3476
0
            return code;
3477
3.28k
    }
3478
2.11M
    return pdf_try_prepare_fill(pdev, pgs, for_text);
3479
7.56M
}
3480
3481
/* Update the graphics state for stroking. */
3482
static int
3483
pdf_try_prepare_stroke(gx_device_pdf *pdev, const gs_gstate *pgs, bool for_text)
3484
626k
{
3485
626k
    pdf_resource_t *pres = 0;
3486
626k
    int code = pdf_prepare_drawing(pdev, pgs, &pres, for_text);
3487
3488
626k
    if (code < 0)
3489
933
        return code;
3490
626k
    if (pdev->rendering_intent != pgs->renderingintent && !pdev->ForOPDFRead) {
3491
143
        static const char *const ri_names[] = { "Perceptual", "RelativeColorimetric", "Saturation", "AbsoluteColorimetric" };
3492
143
        char buf[32];
3493
3494
143
        code = pdf_open_gstate(pdev, &pres);
3495
143
        if (code < 0)
3496
0
            return code;
3497
3498
143
        buf[0] = '/';
3499
143
        strncpy(buf + 1, ri_names[pgs->renderingintent], sizeof(buf) - 2);
3500
143
        code = cos_dict_put_string_copy(resource_dict(pres), "/RI", buf);
3501
143
        if (code < 0)
3502
0
            return code;
3503
143
        pdev->rendering_intent = pgs->renderingintent;
3504
143
    }
3505
    /* Update overprint, stroke adjustment. */
3506
626k
    if (pdev->params.PreserveOverprintSettings &&
3507
626k
        pdev->stroke_overprint != pgs->stroke_overprint &&
3508
550
        !pdev->skip_colors
3509
626k
        ) {
3510
550
        if (pres == 0)
3511
473
            code = pdf_open_gstate(pdev, &pres);
3512
550
        if (code < 0)
3513
0
            return code;
3514
550
        code = cos_dict_put_c_key_bool(resource_dict(pres), "/OP", pgs->stroke_overprint);
3515
550
        if (code < 0)
3516
0
            return code;
3517
550
        pdev->stroke_overprint = pgs->stroke_overprint;
3518
3519
        /* According to PDF>=1.3 spec, OP also sets op,
3520
           if there is no /op in same graphic state object.
3521
           We don't write /op, so monitor the viewer's state here : */
3522
550
        pdev->fill_overprint = pgs->stroke_overprint;
3523
550
    }
3524
626k
    if (pdev->state.stroke_adjust != pgs->stroke_adjust) {
3525
        /* Frankly this is awfully hacky. There is a problem with ps2write and type 3 fonts, for
3526
         * reasons best known to itself it does not seem to collect all the /Resources required
3527
         * for CharProcs when we meddle with the stroke adjustment. This 'seems' to be because it
3528
         * only collects them when it runs the BuildChar, if we use the existing CharProc in a
3529
         * different font then it can miss the Resources needed for the ExtGState.
3530
         * This does not happen with pdfwrite!
3531
         * Since ps2write doesn't require us to store teh staroke adjustment in an ExtGState
3532
         * anyway, just emit it directly.
3533
         * File exhibiting this is tests_private/comparefiles/Bug688967.ps
3534
         */
3535
19.7k
        if (!pdev->ForOPDFRead) {
3536
12.9k
            code = pdf_open_gstate(pdev, &pres);
3537
12.9k
            if (code < 0)
3538
0
                return code;
3539
12.9k
            code = cos_dict_put_c_key_bool(resource_dict(pres), "/SA", pgs->stroke_adjust);
3540
12.9k
            if (code < 0)
3541
0
                return code;
3542
12.9k
            pdev->state.stroke_adjust = pgs->stroke_adjust;
3543
12.9k
        } else {
3544
6.83k
            if (pgs->stroke_adjust)
3545
725
                stream_puts(gdev_vector_stream((gx_device_vector *)pdev), "true setstrokeadjust\n");
3546
6.10k
            else
3547
6.10k
                stream_puts(gdev_vector_stream((gx_device_vector *)pdev), "false setstrokeadjust\n");
3548
6.83k
            pdev->state.stroke_adjust = pgs->stroke_adjust;
3549
6.83k
        }
3550
3551
19.7k
    }
3552
626k
    return pdf_end_gstate(pdev, pres);
3553
626k
}
3554
int
3555
pdf_prepare_stroke(gx_device_pdf *pdev, const gs_gstate *pgs, bool for_text)
3556
626k
{
3557
626k
    int code;
3558
3559
626k
    if (pdev->context != PDF_IN_STREAM) {
3560
0
        code = pdf_try_prepare_stroke(pdev, pgs, for_text);
3561
0
        if (code != gs_error_interrupt) /* See pdf_open_gstate */
3562
0
            return code;
3563
0
        code = pdf_open_contents(pdev, PDF_IN_STREAM);
3564
0
        if (code < 0)
3565
0
            return code;
3566
0
    }
3567
626k
    return pdf_try_prepare_stroke(pdev, pgs, for_text);
3568
626k
}
3569
3570
static int
3571
pdf_try_prepare_fill_stroke(gx_device_pdf *pdev, const gs_gstate *pgs, bool for_text)
3572
10.9k
{
3573
10.9k
    pdf_resource_t *pres = 0;
3574
10.9k
    int code = pdf_prepare_drawing(pdev, pgs, &pres, for_text);
3575
3576
10.9k
    if (code < 0)
3577
1
        return code;
3578
    /* Update overprint. */
3579
10.9k
    if (pdev->params.PreserveOverprintSettings &&
3580
10.9k
        (pdev->fill_overprint != pgs->overprint ||
3581
10.9k
         pdev->stroke_overprint != pgs->stroke_overprint ||
3582
10.9k
         pdev->font3) && !pdev->skip_colors
3583
10.9k
        ) {
3584
80
        code = pdf_open_gstate(pdev, &pres);
3585
80
        if (code < 0)
3586
5
            return code;
3587
        /* PDF 1.2 only has a single overprint setting. */
3588
75
        if (pdev->CompatibilityLevel < 1.3) {
3589
10
            code = cos_dict_put_c_key_bool(resource_dict(pres), "/OP", pgs->overprint);
3590
10
            if (code < 0)
3591
0
                return code;
3592
10
            pdev->stroke_overprint = pgs->overprint;
3593
65
        } else {
3594
65
            code = cos_dict_put_c_key_bool(resource_dict(pres), "/op", pgs->overprint);
3595
65
            if (code < 0)
3596
0
                return code;
3597
65
        }
3598
75
        pdev->fill_overprint = pgs->overprint;
3599
75
    }
3600
    /* Update overprint, stroke adjustment. */
3601
10.9k
    if (pdev->params.PreserveOverprintSettings &&
3602
10.9k
        pdev->stroke_overprint != pgs->stroke_overprint &&
3603
5
        !pdev->skip_colors
3604
10.9k
        ) {
3605
5
        code = pdf_open_gstate(pdev, &pres);
3606
5
        if (code < 0)
3607
0
            return code;
3608
5
        code = cos_dict_put_c_key_bool(resource_dict(pres), "/OP", pgs->stroke_overprint);
3609
5
        if (code < 0)
3610
0
            return code;
3611
5
        pdev->stroke_overprint = pgs->stroke_overprint;
3612
5
        if (pdev->CompatibilityLevel < 1.3) {
3613
            /* PDF 1.2 only has a single overprint setting. */
3614
0
            pdev->fill_overprint = pgs->stroke_overprint;
3615
5
        } else {
3616
            /* According to PDF>=1.3 spec, OP also sets op,
3617
               if there is no /op in same garphic state object.
3618
               We don't write /op, so monitor the viewer's state here : */
3619
5
            pdev->fill_overprint = pgs->overprint;
3620
5
        }
3621
5
    }
3622
10.9k
    if (pdev->state.stroke_adjust != pgs->stroke_adjust) {
3623
1.79k
        code = pdf_open_gstate(pdev, &pres);
3624
1.79k
        if (code < 0)
3625
157
            return code;
3626
1.63k
        code = cos_dict_put_c_key_bool(resource_dict(pres), "/SA", pgs->stroke_adjust);
3627
1.63k
        if (code < 0)
3628
0
            return code;
3629
1.63k
        pdev->state.stroke_adjust = pgs->stroke_adjust;
3630
1.63k
    }
3631
10.7k
    return pdf_end_gstate(pdev, pres);
3632
10.9k
}
3633
3634
int
3635
pdf_prepare_fill_stroke(gx_device_pdf *pdev, const gs_gstate *pgs, bool for_text)
3636
10.6k
{
3637
10.6k
    int code;
3638
3639
10.6k
    if (pdev->context != PDF_IN_STREAM) {
3640
352
        code = pdf_try_prepare_fill_stroke(pdev, pgs, for_text);
3641
352
        if (code < 0 && code != gs_error_interrupt) /* See pdf_open_gstate */
3642
0
            return code;
3643
352
        code = pdf_open_contents(pdev, PDF_IN_STREAM);
3644
352
        if (code < 0)
3645
0
            return code;
3646
352
    }
3647
10.6k
    return pdf_try_prepare_fill_stroke(pdev, pgs, for_text);
3648
10.6k
}
3649
3650
/* Update the graphics state for an image other than an ImageType 1 mask. */
3651
int
3652
pdf_prepare_image(gx_device_pdf *pdev, const gs_gstate *pgs)
3653
89.9k
{
3654
    /*
3655
     * As it turns out, this requires updating the same parameters as for
3656
     * filling.
3657
     */
3658
89.9k
    return pdf_prepare_fill(pdev, pgs, false);
3659
89.9k
}
3660
3661
/* Update the graphics state for an ImageType 1 mask. */
3662
int
3663
pdf_prepare_imagemask(gx_device_pdf *pdev, const gs_gstate *pgs,
3664
                      const gx_drawing_color *pdcolor)
3665
71.3k
{
3666
71.3k
    int code = pdf_prepare_image(pdev, pgs);
3667
3668
71.3k
    if (code < 0)
3669
0
        return code;
3670
71.3k
    return pdf_set_drawing_color(pdev, pgs, pdcolor, &pdev->saved_fill_color,
3671
71.3k
                                 &pdev->fill_used_process_color,
3672
71.3k
                                 &psdf_set_fill_color_commands);
3673
71.3k
}