Coverage Report

Created: 2025-06-10 07:27

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