Coverage Report

Created: 2025-11-16 07:40

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ghostpdl/devices/vector/gdevpdfg.c
Line
Count
Source
1
/* Copyright (C) 2001-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
628k
{
61
628k
    const int i = pdev->vgstack_depth;
62
63
628k
    if (pdev->vgstack_depth >= pdev->vgstack_size) {
64
1
        pdf_viewer_state *new_vgstack = (pdf_viewer_state *)gs_alloc_bytes(pdev->pdf_memory,
65
1
            (size_t)(pdev->vgstack_size + 5) * sizeof(pdf_viewer_state), "increase graphics state stack size");
66
1
        if (new_vgstack == 0)
67
0
            return_error(gs_error_VMerror);
68
1
        memset(new_vgstack, 0x00, (pdev->vgstack_size + 5) * sizeof(pdf_viewer_state));
69
1
        memcpy(new_vgstack, pdev->vgstack, pdev->vgstack_size * sizeof(pdf_viewer_state));
70
1
        gs_free_object(pdev->pdf_memory, pdev->vgstack, "resize graphics state stack, free old stack)");
71
1
        pdev->vgstack = new_vgstack;
72
1
        pdev->vgstack_size += 5;
73
1
    }
74
75
628k
    pdev->vgstack[i].transfer_ids[0] = pdev->transfer_ids[0];
76
628k
    pdev->vgstack[i].transfer_ids[1] = pdev->transfer_ids[1];
77
628k
    pdev->vgstack[i].transfer_ids[2] = pdev->transfer_ids[2];
78
628k
    pdev->vgstack[i].transfer_ids[3] = pdev->transfer_ids[3];
79
628k
    pdev->vgstack[i].transfer_not_identity = pdev->transfer_not_identity;
80
628k
    pdev->vgstack[i].strokeconstantalpha = pdev->state.strokeconstantalpha;
81
628k
    pdev->vgstack[i].fillconstantalpha = pdev->state.fillconstantalpha;
82
628k
    pdev->vgstack[i].alphaisshape = pdev->state.alphaisshape;
83
628k
    pdev->vgstack[i].blend_mode = pdev->state.blend_mode;
84
628k
    pdev->vgstack[i].halftone_id = pdev->halftone_id;
85
628k
    pdev->vgstack[i].black_generation_id = pdev->black_generation_id;
86
628k
    pdev->vgstack[i].undercolor_removal_id = pdev->undercolor_removal_id;
87
628k
    pdev->vgstack[i].overprint_mode = pdev->state.overprint_mode;
88
628k
    pdev->vgstack[i].smoothness = pdev->state.smoothness;
89
628k
    pdev->vgstack[i].flatness = pdev->state.flatness;
90
628k
    pdev->vgstack[i].text_knockout = pdev->state.text_knockout;
91
628k
    pdev->vgstack[i].fill_overprint = pdev->fill_overprint;
92
628k
    pdev->vgstack[i].stroke_overprint = pdev->stroke_overprint;
93
628k
    pdev->vgstack[i].stroke_adjust = pdev->state.stroke_adjust;
94
628k
    pdev->vgstack[i].fill_used_process_color = pdev->fill_used_process_color;
95
628k
    pdev->vgstack[i].stroke_used_process_color = pdev->stroke_used_process_color;
96
628k
    pdev->vgstack[i].saved_fill_color = pdev->saved_fill_color;
97
628k
    pdev->vgstack[i].saved_stroke_color = pdev->saved_stroke_color;
98
628k
    pdev->vgstack[i].line_params = pdev->state.line_params;
99
628k
    pdev->vgstack[i].line_params.dash.pattern = 0; /* Use pdev->dash_pattern instead. */
100
628k
    pdev->vgstack[i].soft_mask_id = pdev->state.soft_mask_id; /* Use pdev->dash_pattern instead. */
101
628k
    if (pdev->dash_pattern) {
102
20.0k
        if (pdev->vgstack[i].dash_pattern)
103
19.1k
            gs_free_object(pdev->memory->non_gc_memory, pdev->vgstack[i].dash_pattern, "free gstate copy dash");
104
20.0k
        pdev->vgstack[i].dash_pattern = (float *)gs_alloc_bytes(pdev->memory->non_gc_memory, (size_t)pdev->dash_pattern_size * sizeof(float), "gstate copy dash");
105
20.0k
        if (pdev->vgstack[i].dash_pattern == NULL)
106
0
            return_error(gs_error_VMerror);
107
20.0k
        memcpy(pdev->vgstack[i].dash_pattern, pdev->dash_pattern, pdev->dash_pattern_size * sizeof(float));
108
20.0k
        pdev->vgstack[i].dash_pattern_size = pdev->dash_pattern_size;
109
608k
    } else {
110
608k
        if (pdev->vgstack[i].dash_pattern) {
111
488
            gs_free_object(pdev->memory->non_gc_memory, pdev->vgstack[i].dash_pattern, "free gstate copy dash");
112
488
            pdev->vgstack[i].dash_pattern = 0;
113
488
            pdev->vgstack[i].dash_pattern_size = 0;
114
488
        }
115
608k
    }
116
628k
    pdev->vgstack_depth++;
117
628k
    if (s)
118
439k
        stream_puts(s, "q\n");
119
628k
    return 0;
120
628k
}
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
1.04M
{
126
1.04M
    pdev->transfer_ids[0] = s->transfer_ids[0];
127
1.04M
    pdev->transfer_ids[1] = s->transfer_ids[1];
128
1.04M
    pdev->transfer_ids[2] = s->transfer_ids[2];
129
1.04M
    pdev->transfer_ids[3] = s->transfer_ids[3];
130
1.04M
    pdev->transfer_not_identity = s->transfer_not_identity;
131
1.04M
    pdev->state.strokeconstantalpha = s->strokeconstantalpha;
132
1.04M
    pdev->state.fillconstantalpha = s->fillconstantalpha;
133
1.04M
    pdev->state.alphaisshape = s->alphaisshape;
134
1.04M
    pdev->state.blend_mode = s->blend_mode;
135
1.04M
    pdev->halftone_id = s->halftone_id;
136
1.04M
    pdev->black_generation_id = s->black_generation_id;
137
1.04M
    pdev->undercolor_removal_id = s->undercolor_removal_id;
138
1.04M
    pdev->state.overprint_mode = s->overprint_mode;
139
1.04M
    pdev->state.smoothness = s->smoothness;
140
1.04M
    pdev->state.flatness = s->flatness;
141
1.04M
    pdev->state.text_knockout = s->text_knockout;
142
1.04M
    pdev->fill_overprint = s->fill_overprint;
143
1.04M
    pdev->stroke_overprint = s->stroke_overprint;
144
1.04M
    pdev->state.stroke_adjust = s->stroke_adjust;
145
1.04M
    pdev->fill_used_process_color = s->fill_used_process_color;
146
1.04M
    pdev->stroke_used_process_color = s->stroke_used_process_color;
147
1.04M
    pdev->saved_fill_color = s->saved_fill_color;
148
1.04M
    pdev->saved_stroke_color = s->saved_stroke_color;
149
1.04M
    pdev->state.line_params = s->line_params;
150
1.04M
    pdev->state.soft_mask_id = s->soft_mask_id;
151
1.04M
    if (s->dash_pattern) {
152
20.0k
        if (pdev->dash_pattern)
153
20.0k
            gs_free_object(pdev->memory->stable_memory, pdev->dash_pattern, "vector free dash pattern");
154
20.0k
        pdev->dash_pattern = (float *)gs_alloc_bytes(pdev->memory->stable_memory, (size_t)s->dash_pattern_size * sizeof(float), "vector allocate dash pattern");
155
20.0k
        if (pdev->dash_pattern == NULL)
156
0
            return_error(gs_error_VMerror);
157
20.0k
        memcpy(pdev->dash_pattern, s->dash_pattern, sizeof(float)*s->dash_pattern_size);
158
20.0k
        pdev->dash_pattern_size  = s->dash_pattern_size;
159
1.02M
    } else {
160
1.02M
        if (pdev->dash_pattern) {
161
4.13k
            gs_free_object(pdev->memory->stable_memory, pdev->dash_pattern, "vector free dash pattern");
162
4.13k
            pdev->dash_pattern = 0;
163
4.13k
            pdev->dash_pattern_size = 0;
164
4.13k
        }
165
1.02M
    }
166
1.04M
    return 0;
167
1.04M
}
168
169
/* Restore the viewer's graphic state. */
170
int
171
pdf_restore_viewer_state(gx_device_pdf *pdev, stream *s)
172
628k
{
173
628k
    const int i = --pdev->vgstack_depth;
174
175
628k
    if (i < pdev->vgstack_bottom || i < 0) {
176
14
        if ((pdev->ObjectFilter & FILTERIMAGE) == 0)
177
14
            return_error(gs_error_unregistered); /* Must not happen. */
178
0
        else
179
0
            return 0;
180
14
    }
181
628k
    if (s)
182
439k
        stream_puts(s, "Q\n");
183
628k
    return pdf_load_viewer_state(pdev, pdev->vgstack + i);
184
628k
}
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
78.6k
{
192
78.6k
    gx_device_color black;
193
194
78.6k
    pdev->black = gx_device_black((gx_device *)pdev);
195
78.6k
    pdev->white = gx_device_white((gx_device *)pdev);
196
78.6k
    set_nonclient_dev_color(&black, pdev->black);
197
78.6k
    gx_hld_save_color(NULL, &black, saved_fill_color);
198
78.6k
    gx_hld_save_color(NULL, &black, saved_stroke_color);
199
78.6k
    *fill_used_process_color = true;
200
78.6k
    *stroke_used_process_color = true;
201
78.6k
}
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
198k
{
207
198k
    pvs->transfer_not_identity =
208
198k
            (pgs->set_transfer.red   != NULL ? pgs->set_transfer.red->proc   != gs_identity_transfer : 0) * 1 +
209
198k
            (pgs->set_transfer.green != NULL ? pgs->set_transfer.green->proc != gs_identity_transfer : 0) * 2 +
210
198k
            (pgs->set_transfer.blue  != NULL ? pgs->set_transfer.blue->proc  != gs_identity_transfer : 0) * 4 +
211
198k
            (pgs->set_transfer.gray  != NULL ? pgs->set_transfer.gray->proc  != gs_identity_transfer : 0) * 8;
212
198k
    pvs->transfer_ids[0] = (pgs->set_transfer.red != NULL ? pgs->set_transfer.red->id : 0);
213
198k
    pvs->transfer_ids[1] = (pgs->set_transfer.green != NULL ? pgs->set_transfer.green->id : 0);
214
198k
    pvs->transfer_ids[2] = (pgs->set_transfer.blue != NULL ? pgs->set_transfer.blue->id : 0);
215
198k
    pvs->transfer_ids[3] = (pgs->set_transfer.gray != NULL ? pgs->set_transfer.gray->id : 0);
216
198k
    pvs->fillconstantalpha = pgs->fillconstantalpha;
217
198k
    pvs->strokeconstantalpha = pgs->strokeconstantalpha;
218
198k
    pvs->alphaisshape = pgs->alphaisshape;
219
198k
    pvs->blend_mode = pgs->blend_mode;
220
198k
    pvs->halftone_id = (pgs->dev_ht[HT_OBJTYPE_DEFAULT] != NULL ? pgs->dev_ht[HT_OBJTYPE_DEFAULT]->id : 0);
221
198k
    pvs->black_generation_id = (pgs->black_generation != NULL ? pgs->black_generation->id : 0);
222
198k
    pvs->undercolor_removal_id = (pgs->undercolor_removal != NULL ? pgs->undercolor_removal->id : 0);
223
198k
    pvs->overprint_mode = 0;
224
198k
    pvs->flatness = pgs->flatness;
225
198k
    pvs->smoothness = pgs->smoothness;
226
198k
    pvs->text_knockout = pgs->text_knockout;
227
198k
    pvs->fill_overprint = false;
228
198k
    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
198k
    pvs->stroke_adjust = -1;
237
198k
    pvs->line_params.half_width = 0.5;
238
198k
    pvs->line_params.start_cap = 0;
239
198k
    pvs->line_params.end_cap = 0;
240
198k
    pvs->line_params.dash_cap = 0;
241
198k
    pvs->line_params.join = 0;
242
198k
    pvs->line_params.curve_join = 0;
243
198k
    pvs->line_params.miter_limit = 10.0;
244
198k
    pvs->line_params.miter_check = 0;
245
198k
    pvs->line_params.dot_length = pgs->line_params.dot_length;
246
198k
    pvs->line_params.dot_length_absolute = pgs->line_params.dot_length_absolute;
247
198k
    pvs->line_params.dot_orientation = pgs->line_params.dot_orientation;
248
198k
    memset(&pvs->line_params.dash, 0 , sizeof(pvs->line_params.dash));
249
198k
    pvs->dash_pattern = 0;
250
198k
    pvs->dash_pattern_size = 0;
251
198k
    pvs->soft_mask_id = pgs->soft_mask_id;
252
198k
}
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
159k
{
259
159k
    pdf_viewer_state vs;
260
261
159k
    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
159k
    gx_hld_save_color(pgs, pdevc, &vs.saved_fill_color);
265
159k
    gx_hld_save_color(pgs, pdevc, &vs.saved_stroke_color);
266
159k
    vs.fill_used_process_color = 0;
267
159k
    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
159k
    (void)pdf_load_viewer_state(pdev, &vs);
271
159k
}
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
39.3k
{
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
39.3k
    pdf_set_initial_color(pdev, &pdev->vg_initial.saved_fill_color, &pdev->vg_initial.saved_stroke_color,
285
39.3k
            &pdev->vg_initial.fill_used_process_color, &pdev->vg_initial.stroke_used_process_color);
286
39.3k
    pdf_viewer_state_from_gs_gstate_aux(&pdev->vg_initial, pgs);
287
39.3k
    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
39.3k
}
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
39.3k
{
300
301
39.3k
    pdf_set_initial_color(pdev, &pdev->saved_fill_color, &pdev->saved_stroke_color,
302
39.3k
                                &pdev->fill_used_process_color, &pdev->stroke_used_process_color);
303
39.3k
    pdev->state.flatness = -1;
304
39.3k
    {
305
39.3k
        static const gx_line_params lp_initial = {
306
39.3k
            gx_line_params_initial
307
39.3k
        };
308
309
39.3k
        pdev->state.line_params = lp_initial;
310
39.3k
    }
311
39.3k
    pdev->fill_overprint = false;
312
39.3k
    pdev->stroke_overprint = false;
313
39.3k
    pdev->remap_fill_color = false;
314
39.3k
    pdev->remap_stroke_color = false;
315
39.3k
    pdf_reset_text(pdev);
316
39.3k
}
317
318
/* Reset the graphics state parameters to initial values. */
319
void
320
pdf_reset_graphics(gx_device_pdf * pdev)
321
298k
{
322
298k
    int soft_mask_id = pdev->state.soft_mask_id;
323
324
298k
    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
259k
        (void)pdf_load_viewer_state(pdev, &pdev->vg_initial);
328
39.3k
    else
329
39.3k
        pdf_reset_graphics_old(pdev);
330
298k
    pdf_reset_text(pdev);
331
332
    /* Not obvious, we want to preserve any extant soft mask, not reset it */
333
298k
    pdev->state.soft_mask_id = soft_mask_id;
334
298k
}
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
815k
{
341
815k
    int i, n = gx_hld_get_number_color_components(pgs);
342
343
815k
    pprintg1(pdev->strm, "%g", psdf_round(pcc->paint.values[0], 255, 8));
344
2.06M
    for (i = 1; i < n; i++) {
345
1.24M
        pprintg1(pdev->strm, " %g", psdf_round(pcc->paint.values[i], 255, 8));
346
1.24M
    }
347
815k
    return 0;
348
815k
}
349
350
static inline bool
351
is_cspace_allowed_in_strategy(gx_device_pdf * pdev, gs_color_space_index csi)
352
12.6k
{
353
12.6k
    if (pdev->params.ColorConversionStrategy == ccs_CMYK &&
354
0
            csi != gs_color_space_index_DeviceCMYK &&
355
0
            csi != gs_color_space_index_DeviceGray)
356
0
        return false;
357
12.6k
    if (pdev->params.ColorConversionStrategy == ccs_sRGB &&
358
0
            csi != gs_color_space_index_DeviceRGB &&
359
0
            csi != gs_color_space_index_DeviceGray)
360
0
        return false;
361
12.6k
    if (pdev->params.ColorConversionStrategy == ccs_RGB &&
362
0
            csi != gs_color_space_index_DeviceRGB &&
363
0
            csi != gs_color_space_index_DeviceGray)
364
0
        return false;
365
12.6k
    if (pdev->params.ColorConversionStrategy == ccs_Gray &&
366
0
            csi != gs_color_space_index_DeviceGray)
367
0
        return false;
368
12.6k
    return true;
369
12.6k
}
370
371
static inline bool
372
is_pattern2_allowed_in_strategy(gx_device_pdf * pdev, const gx_drawing_color *pdc)
373
12.6k
{
374
12.6k
    const gs_color_space *pcs2 = gx_dc_pattern2_get_color_space(pdc);
375
12.6k
    gs_color_space_index csi = gs_color_space_get_index(pcs2);
376
377
12.6k
    if (csi == gs_color_space_index_ICC)
378
3.54k
        csi = gsicc_get_default_type(pcs2->cmm_icc_profile_data);
379
380
12.6k
    return is_cspace_allowed_in_strategy(pdev, csi);
381
12.6k
}
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
12
{
408
12
    unsigned short psrc[GS_CLIENT_COLOR_MAX_COMPONENTS];
409
12
    frac conc[GS_CLIENT_COLOR_MAX_COMPONENTS];
410
12
    gx_device_color dc;
411
12
    const gs_color_space *pcs = gs_currentcolorspace_inline(pgs);
412
12
    int code, i, color_index;
413
414
12
    color_index = pdev->pcm_color_info_index;
415
12
    pdf_set_process_color_model(pdev, 1);
416
48
    for (i=0;i<3;i++) {
417
36
        psrc[i] = (unsigned short) (pcc->paint.values[i]*65535.0);;
418
36
        conc[i] = ushort2frac(psrc[i]);
419
36
    }
420
12
    code = gx_remap_concrete_DRGB(pcs, (const frac *)&conc, &dc, pgs, (gx_device *)pdev, gs_color_select_texture, NULL);
421
12
    if (code < 0)
422
0
        return code;
423
424
12
    cc->paint.values[0] = ((dc.colors.pure & 0xff0000) >> 16) / 255.0;
425
12
    cc->paint.values[1] = ((dc.colors.pure & 0xff00) >> 8) / 255.0;
426
12
    cc->paint.values[2] = (dc.colors.pure & 0xff) / 255.0;
427
12
    pdf_set_process_color_model(pdev, color_index);
428
12
    return 0;
429
12
}
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
85.8k
{
461
85.8k
    int code, i;
462
85.8k
    unsigned char j;
463
85.8k
    frac conc[GS_CLIENT_COLOR_MAX_COMPONENTS];
464
85.8k
    gs_color_space_index csi, csi2;
465
85.8k
    gs_color_space *pcs2 = (gs_color_space *)pcs;
466
85.8k
    gx_drawing_color dc;
467
85.8k
    int num_des_comps;
468
85.8k
    cmm_dev_profile_t *dev_profile;
469
470
85.8k
    dc.type = gx_dc_type_pure;
471
85.8k
    dc.colors.pure = 0;
472
85.8k
    csi = gs_color_space_get_index(pcs);
473
474
85.8k
    if (csi == gs_color_space_index_ICC) {
475
85.8k
        csi = gsicc_get_default_type(pcs->cmm_icc_profile_data);
476
85.8k
    }
477
478
85.8k
    if (csi == gs_color_space_index_Indexed ||
479
85.8k
        csi == gs_color_space_index_DeviceN ||
480
85.8k
        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
85.8k
    } else {
537
85.8k
        if (csi >= gs_color_space_index_CIEDEFG &&
538
85.8k
            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
85.8k
        } else {
551
85.8k
            memset (&conc, 0x00, sizeof(frac) * GS_CLIENT_COLOR_MAX_COMPONENTS);
552
            /* Special case handling for Lab spaces */
553
85.8k
            if (pcs->cmm_icc_profile_data->data_cs == gsCIELAB || pcs->cmm_icc_profile_data->islab) {
554
300
                gs_client_color cc;
555
                /* Get the data in a form that is concrete for the CMM */
556
300
                cc.paint.values[0] = pcc->paint.values[0] / 100.0;
557
300
                cc.paint.values[1] = (pcc->paint.values[1]+128)/255.0;
558
300
                cc.paint.values[2] = (pcc->paint.values[2]+128)/255.0;
559
300
                pcs->type->concretize_color((const gs_client_color *)&cc, pcs, conc, pgs, (gx_device *)pdev);
560
85.5k
            } else {
561
85.5k
                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
85.5k
                } else {
576
85.5k
                    pcs->type->concretize_color(pcc, pcs, conc, pgs, (gx_device *)pdev);
577
85.5k
                }
578
85.5k
            }
579
85.8k
            code = dev_proc((gx_device *)pdev, get_profile)((gx_device *)pdev, &dev_profile);
580
85.8k
            if (code < 0)
581
0
                return code;
582
85.8k
            num_des_comps = gsicc_get_device_profile_comps(dev_profile);
583
343k
            for (i = 0;i < num_des_comps;i++)
584
257k
                dc.colors.pure = (dc.colors.pure << 8) + (int)(frac2float(conc[i]) * 255);
585
85.8k
            code = psdf_set_color((gx_device_vector *)pdev, &dc, ppscc);
586
85.8k
            return code;
587
85.8k
        }
588
85.8k
    }
589
85.8k
    return_error(gs_error_unknownerror);
590
85.8k
}
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
815k
{
598
815k
    gs_color_space_index csi, csi2;
599
815k
    int code, i;
600
815k
    const char *command = NULL;
601
815k
    gs_range_t *ranges = 0;
602
815k
    gs_client_color cc;
603
604
605
815k
    csi = csi2 = gs_color_space_get_index(pcs);
606
815k
    if (csi == gs_color_space_index_ICC) {
607
786k
        csi2 = gsicc_get_default_type(pcs->cmm_icc_profile_data);
608
786k
    }
609
610
815k
    switch (csi2) {
611
211k
        case gs_color_space_index_DeviceGray:
612
211k
            command = ppscc->setgray;
613
211k
            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
211k
            } else {
618
211k
                cc.paint.values[0] = pcc->paint.values[0];
619
211k
            }
620
211k
            code = pdf_write_ccolor(pdev, pgs, &cc);
621
211k
            if (code < 0)
622
0
                return code;
623
211k
            pprints1(pdev->strm, " %s\n", command);
624
211k
            break;
625
434k
        case gs_color_space_index_DeviceRGB:
626
434k
            command = ppscc->setrgbcolor;
627
434k
            if (pdev->params.TransferFunctionInfo == tfi_Apply) {
628
12
                code = apply_transfer_rgb(pdev, pgs, pcc, &cc);
629
12
                if (code < 0)
630
0
                    return_error(code);
631
434k
            } else {
632
1.73M
                for (i=0;i< 3;i++)
633
1.30M
                    cc.paint.values[i] = pcc->paint.values[i];
634
434k
            }
635
434k
            code = pdf_write_ccolor(pdev, pgs, &cc);
636
434k
            if (code < 0)
637
0
                return code;
638
434k
            pprints1(pdev->strm, " %s\n", command);
639
434k
            break;
640
110k
        case gs_color_space_index_DeviceCMYK:
641
110k
            command = ppscc->setcmykcolor;
642
110k
            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
110k
            } else {
647
554k
                for (i=0;i< 4;i++)
648
443k
                    cc.paint.values[i] = pcc->paint.values[i];
649
110k
            }
650
110k
            code = pdf_write_ccolor(pdev, pgs, &cc);
651
110k
            if (code < 0)
652
0
                return code;
653
110k
            pprints1(pdev->strm, " %s\n", command);
654
110k
            break;
655
57.9k
        default:
656
57.9k
            if (!gx_hld_saved_color_same_cspace(current, psc) || (csi2 >= gs_color_space_index_CIEDEFG && csi2 <= gs_color_space_index_CIEA)) {
657
38.5k
                cos_value_t cs_value;
658
659
38.5k
                code = pdf_color_space_named(pdev, pgs, &cs_value, (const gs_range_t **)&ranges, pcs,
660
38.5k
                                &pdf_color_space_names, true, NULL, 0, false);
661
                /* fixme : creates redundant PDF objects. */
662
38.5k
                if (code == gs_error_rangecheck) {
663
26
                    *used_process_color = true;
664
26
                    if (pdev->ForOPDFRead) {
665
                    /* The color space can't write to PDF. This should never happen */
666
26
                    code = psdf_set_color((gx_device_vector *)pdev, pdc, ppscc);
667
26
                    } else {
668
0
                    code = write_color_as_process(pdev, pgs, pcs, pdc, used_process_color, ppscc, pcc);
669
0
                    }
670
26
                    return code;
671
26
                }
672
38.5k
                if (code < 0)
673
0
                    return code;
674
38.5k
                code = cos_value_write(&cs_value, pdev);
675
38.5k
                if (code < 0)
676
0
                    return code;
677
38.5k
                pprints1(pdev->strm, " %s\n", ppscc->setcolorspace);
678
38.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
38.5k
                } else {
699
38.5k
                    code = pdf_write_ccolor(pdev, pgs, pcc);
700
38.5k
                }
701
38.5k
                *used_process_color = false;
702
38.5k
                if (code < 0)
703
0
                    return code;
704
38.5k
                pprints1(pdev->strm, " %s\n", ppscc->setcolorn);
705
38.5k
            } else if (*used_process_color) {
706
12
                    *used_process_color = true;
707
12
                    if (pdev->ForOPDFRead) {
708
                    /* The color space can't write to PDF. This should never happen */
709
12
                    code = psdf_set_color((gx_device_vector *)pdev, pdc, ppscc);
710
12
                    } else {
711
0
                    code = write_color_as_process(pdev, pgs, pcs, pdc, used_process_color, ppscc, pcc);
712
0
                    }
713
12
                    return code;
714
12
            }
715
19.3k
            else {
716
19.3k
                code = pdf_write_ccolor(pdev, pgs, pcc);
717
19.3k
                if (code < 0)
718
0
                    return code;
719
19.3k
                pprints1(pdev->strm, " %s\n", ppscc->setcolorn);
720
19.3k
            }
721
57.8k
            break;
722
815k
    }
723
815k
    *used_process_color = false;
724
725
815k
    return 0;
726
815k
}
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 * (size_t)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 (cascade < pcs->params.device_n.num_components && cc.paint.values[cascade] == 1) {
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.35M
{
1460
1.35M
    int code=0, code1=0;
1461
1.35M
    gx_hl_saved_color temp;
1462
1.35M
    gs_client_color *pcc; /* fixme: not needed due to gx_hld_get_color_component. */
1463
1.35M
    cos_value_t cs_value;
1464
1.35M
    gs_color_space_index csi;
1465
1.35M
    gs_color_space_index csi2;
1466
1.35M
    const gs_color_space *pcs, *pcs2;
1467
1468
1.35M
    if (pdev->skip_colors)
1469
0
        return 0;
1470
1471
    /* Get a copy of the current colour so we can examine it. */
1472
1.35M
    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.35M
    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.35M
    switch (gx_hld_get_color_space_and_ccolor(pgs, pdc, &pcs, (const gs_client_color **)&pcc)) {
1484
22.2k
        case pattern_color_space:
1485
22.2k
            {
1486
22.2k
                pdf_resource_t *pres;
1487
1488
22.2k
                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
7.57k
                    if (pdev->CompatibilityLevel < 1.2) {
1493
0
                        return_error(gs_error_undefined);
1494
0
                    }
1495
7.57k
                    code = pdf_put_colored_pattern(pdev, pdc, pcs,
1496
7.57k
                                ppscc, pgs, &pres);
1497
7.57k
                }
1498
14.6k
                else if (pdc->type == &gx_dc_pure_masked) {
1499
53
                    code = pdf_put_uncolored_pattern(pdev, pdc, pcs,
1500
53
                                ppscc, pgs, &pres);
1501
53
                    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
53
                    if (pgs->have_pattern_streams)
1510
53
                        code = pdf_write_ccolor(pdev, pgs, pcc);
1511
14.6k
                } else if (pdc->type == &gx_dc_pattern2) {
1512
14.6k
                    if (pdev->CompatibilityLevel <= 1.2)
1513
1.98k
                        return_error(gs_error_rangecheck);
1514
12.6k
                    if (!is_pattern2_allowed_in_strategy(pdev, pdc))
1515
0
                        return_error(gs_error_rangecheck);
1516
12.6k
                    code1 = pdf_put_pattern2(pdev, pgs, pdc, ppscc, &pres);
1517
12.6k
                    if (code1 < 0)
1518
0
                        return code1;
1519
12.6k
                } else
1520
0
                    return_error(gs_error_rangecheck);
1521
20.2k
                if (code < 0)
1522
0
                    return code;
1523
20.2k
                code = pdf_add_resource(pdev, pdev->substream_Resources, "/Pattern", pres);
1524
20.2k
                if (code >= 0) {
1525
20.2k
                    cos_value_write(cos_resource_value(&cs_value, pres->object), pdev);
1526
20.2k
                    pprints1(pdev->strm, " %s\n", ppscc->setcolorn);
1527
20.2k
                }
1528
0
                else {
1529
0
                    pres->where_used = 0;
1530
0
                    return code;
1531
0
                }
1532
20.2k
                *used_process_color = false;
1533
20.2k
            }
1534
0
            break;
1535
901k
        case non_pattern_color_space:
1536
901k
            pcs2 = pcs;
1537
901k
            csi = csi2 = gs_color_space_get_index(pcs);
1538
901k
            if (csi == gs_color_space_index_ICC) {
1539
872k
                csi2 = gsicc_get_default_type(pcs->cmm_icc_profile_data);
1540
872k
            }
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
901k
            if (pdev->CompatibilityLevel <= 1.2) {
1544
1545
                /* If we have an /Indexed space, we need to look at the base space */
1546
513k
                if (csi2 == gs_color_space_index_Indexed) {
1547
9
                    pcs2 = pcs->base_space;
1548
9
                    csi2 = gs_color_space_get_index(pcs2);
1549
9
                }
1550
1551
513k
                switch (csi2) {
1552
117k
                    case gs_color_space_index_DeviceGray:
1553
117k
                        if (pdev->params.ColorConversionStrategy == ccs_LeaveColorUnchanged ||
1554
0
                            pdev->params.ColorConversionStrategy == ccs_Gray)
1555
117k
                            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
117k
                        break;
1559
208k
                    case gs_color_space_index_DeviceRGB:
1560
208k
                        if (pdev->params.ColorConversionStrategy == ccs_LeaveColorUnchanged ||
1561
0
                            pdev->params.ColorConversionStrategy == ccs_RGB)
1562
208k
                            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
208k
                        break;
1566
82.2k
                    case gs_color_space_index_DeviceCMYK:
1567
82.2k
                        if (pdev->params.ColorConversionStrategy == ccs_LeaveColorUnchanged ||
1568
0
                            pdev->params.ColorConversionStrategy == ccs_CMYK)
1569
82.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
82.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
19.4k
                    case gs_color_space_index_Separation:
1598
19.4k
                        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
19.4k
                            case ccs_LeaveColorUnchanged:
1604
19.4k
                                pcs2 = pcs->base_space;
1605
19.4k
                                csi2 = gs_color_space_get_index(pcs2);
1606
19.4k
                                if (csi2 == gs_color_space_index_ICC) {
1607
19.4k
                                    csi2 = gsicc_get_default_type(pcs2->cmm_icc_profile_data);
1608
19.4k
                                }
1609
19.4k
                                if (csi2 == gs_color_space_index_ICC) {
1610
8.81k
                                    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
8.81k
                                        code = write_color_unchanged(pdev, pgs, pcc, &temp, psc, ppscc, used_process_color, pcs, pdc);
1632
8.81k
                                } else
1633
10.6k
                                    code = write_color_unchanged(pdev, pgs, pcc, &temp, psc, ppscc, used_process_color, pcs, pdc);
1634
19.4k
                                break;
1635
19.4k
                            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
19.4k
                        }
1643
19.4k
                        break;
1644
19.4k
                    case gs_color_space_index_DeviceN:
1645
38
                        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
38
                            case ccs_LeaveColorUnchanged:
1651
38
                                code = write_color_unchanged(pdev, pgs, pcc, &temp, psc, ppscc, used_process_color, pcs, pdc);
1652
38
                                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
38
                        }
1675
38
                        break;
1676
85.8k
                    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
85.8k
                        csi2 = gsicc_get_default_type(pcs2->cmm_icc_profile_data);
1685
1686
85.8k
                        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
85.8k
                            default:
1712
85.8k
                                break;
1713
85.8k
                        }
1714
                        /* Fall through if its not a device substitute, or not one we want to preserve */
1715
85.8k
                    case gs_color_space_index_DevicePixel:
1716
85.8k
                    case gs_color_space_index_Indexed:
1717
85.8k
                        code = write_color_as_process(pdev, pgs, pcs, pdc, used_process_color, ppscc, pcc);
1718
85.8k
                        break;
1719
0
                    default:
1720
0
                        return (gs_note_error(gs_error_rangecheck));
1721
0
                        break;
1722
513k
                }
1723
513k
            } else {
1724
387k
                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
387k
                    case ccs_LeaveColorUnchanged:
1730
387k
                        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
387k
                        else
1773
387k
                            code = write_color_unchanged(pdev, pgs, pcc, &temp, psc, ppscc, used_process_color, pcs, pdc);
1774
387k
                        break;
1775
387k
                    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
387k
                }
2062
387k
            }
2063
901k
            break;
2064
901k
        default: /* must not happen. */
2065
429k
        case use_process_color:
2066
429k
            code = psdf_set_color((gx_device_vector *)pdev, pdc, ppscc);
2067
429k
            if (code < 0)
2068
15.4k
                return code;
2069
414k
            *used_process_color = true;
2070
414k
            break;
2071
1.35M
    }
2072
1.33M
    *psc = temp;
2073
1.33M
    return code;
2074
1.35M
}
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.9M
{
2083
11.9M
    gx_hl_saved_color temp;
2084
11.9M
    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.9M
    if (pdev->skip_colors)
2092
8.73k
        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.9M
        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
938k
    code = pdf_open_page(pdev, PDF_IN_STREAM);
2108
938k
    if (code < 0)
2109
0
        return code;
2110
2111
938k
    return pdf_reset_color(pdev, pgs, pdc, psc, used_process_color, ppscc);
2112
938k
}
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
544k
{
2119
544k
    gx_drawing_color dcolor;
2120
544k
    gx_hl_saved_color temp;
2121
544k
    int code;
2122
2123
544k
    set_nonclient_dev_color(&dcolor, color);
2124
2125
544k
    if (pdev->skip_colors)
2126
0
        return 0;
2127
544k
    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
544k
    if (gx_hld_saved_color_equal(&temp, psc))
2133
130k
        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
414k
    code = pdf_open_page(pdev, PDF_IN_STREAM);
2142
414k
    if (code < 0)
2143
0
        return code;
2144
2145
414k
    return pdf_reset_color(pdev, NULL, &dcolor, psc, used_process_color, ppscc);
2146
414k
}
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
8.77k
{
2155
8.77k
    byte *chars = gs_alloc_string(pdev->pdf_memory, len + 1,
2156
8.77k
                                  "pdf_string_to_cos_name");
2157
2158
8.77k
    if (chars == 0)
2159
0
        return_error(gs_error_VMerror);
2160
8.77k
    chars[0] = '/';
2161
8.77k
    memcpy(chars + 1, str, len);
2162
8.77k
    cos_string_value(pvalue, chars, len + 1);
2163
8.77k
    return 0;
2164
8.77k
}
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
28.2k
{
2185
28.2k
    const gx_transfer_map *map = (const gx_transfer_map *)psrc->data.str.data;
2186
28.2k
    uint i;
2187
2188
28.2k
    if (ptr)
2189
28.2k
        *ptr = buf;
2190
2.43M
    for (i = 0; i < length; ++i)
2191
2.40M
        buf[i] = frac2byte(map->values[(uint)start + i]);
2192
28.2k
    return 0;
2193
28.2k
}
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
27.9k
{
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
27.9k
    const gx_transfer_map *map = (const gx_transfer_map *)psrc->data.str.data;
2206
27.9k
    uint i;
2207
2208
27.9k
    *ptr = buf;
2209
2.41M
    for (i = 0; i < length; ++i)
2210
2.38M
        buf[i] = (byte)
2211
2.38M
            ((frac2float(map->values[(uint)start + i]) + 1) * 127);
2212
27.9k
    return 0;
2213
27.9k
}
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
45.7k
{
2219
45.7k
    gs_memory_t *mem = pdev->pdf_memory;
2220
45.7k
    gs_function_Sd_params_t params;
2221
45.7k
    static const float domain01[2] = { 0, 1 };
2222
45.7k
    static const int size = transfer_map_size;
2223
45.7k
    float range01[2], decode[2];
2224
45.7k
    gs_function_t *pfn;
2225
45.7k
    int64_t id;
2226
45.7k
    int code;
2227
2228
45.7k
    if (map == 0) {
2229
8.39k
        *ids = 0;   /* no map */
2230
8.39k
        return 1;
2231
8.39k
    }
2232
37.3k
    if (check_identity) {
2233
        /* Check for an identity map. */
2234
18.7k
        int i;
2235
2236
18.7k
        if (map->proc == gs_identity_transfer)
2237
18.6k
            i = transfer_map_size;
2238
88
        else
2239
176
            for (i = 0; i < transfer_map_size; ++i) {
2240
176
                fixed d = map->values[i] - bits2frac(i, log2_transfer_map_size);
2241
176
                if (any_abs(d) > fixed_epsilon) /* ignore small noise */
2242
88
                    break;
2243
176
            }
2244
18.7k
        if (i == transfer_map_size) {
2245
18.6k
            strcpy(ids, key);
2246
18.6k
            strcat(ids, "/Identity");
2247
18.6k
            return 1;
2248
18.6k
        }
2249
18.7k
    }
2250
18.7k
    params.m = 1;
2251
18.7k
    params.Domain = domain01;
2252
18.7k
    params.n = 1;
2253
18.7k
    range01[0] = (float)range0, range01[1] = 1.0;
2254
18.7k
    params.Range = range01;
2255
18.7k
    params.Order = 1;
2256
18.7k
    params.DataSource.access =
2257
18.7k
        (range0 < 0 ? transfer_map_access_signed : transfer_map_access);
2258
18.7k
    params.DataSource.data.str.data = (const byte *)map; /* bogus */
2259
    /* DataSource */
2260
18.7k
    params.BitsPerSample = 8; /* could be 16 */
2261
18.7k
    params.Encode = 0;
2262
18.7k
    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
9.31k
        int r0 = (int)( -range01[0] * ((1 << params.BitsPerSample) - 1)
2269
9.31k
                        / (range01[1] - range01[0]) ); /* Round down. */
2270
9.31k
        float r1 = r0 * range01[1] / -range01[0]; /* r0 + r1 <= (1 << params.BitsPerSample) - 1 */
2271
2272
9.31k
        decode[0] = range01[0];
2273
9.31k
        decode[1] = range01[0] + (range01[1] - range01[0]) * ((1 << params.BitsPerSample) - 1)
2274
9.31k
                                    / (r0 + r1);
2275
9.31k
        params.Decode = decode;
2276
9.31k
    } else
2277
9.40k
        params.Decode = 0;
2278
18.7k
    params.Size = &size;
2279
18.7k
    code = gs_function_Sd_init(&pfn, &params, mem);
2280
18.7k
    if (code < 0)
2281
0
        return code;
2282
18.7k
    code = pdf_write_function(pdev, pfn, &id);
2283
18.7k
    gs_function_free(pfn, false, mem);
2284
18.7k
    if (code < 0)
2285
0
        return code;
2286
18.7k
    gs_snprintf(ids, id_max, "%s%s%"PRId64" 0 R", key, (key[0] && key[0] != ' ' ? " " : ""), id);
2287
18.7k
    return 0;
2288
18.7k
}
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
27.0k
{
2293
27.0k
    return pdf_write_transfer_map(pdev, map, 0, true, key, ids, id_max);
2294
27.0k
}
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
372k
  static double name(double xd, double yd) {\
2306
372k
    float x = (float)xd, y = (float)yd;\
2307
372k
    return d2f(expr);\
2308
372k
  }
gdevpdfg.c:ht_EllipseA
Line
Count
Source
2305
20.7k
  static double name(double xd, double yd) {\
2306
20.7k
    float x = (float)xd, y = (float)yd;\
2307
20.7k
    return d2f(expr);\
2308
20.7k
  }
gdevpdfg.c:ht_InvertedEllipseA
Line
Count
Source
2305
20.7k
  static double name(double xd, double yd) {\
2306
20.7k
    float x = (float)xd, y = (float)yd;\
2307
20.7k
    return d2f(expr);\
2308
20.7k
  }
gdevpdfg.c:ht_EllipseB
Line
Count
Source
2305
20.7k
  static double name(double xd, double yd) {\
2306
20.7k
    float x = (float)xd, y = (float)yd;\
2307
20.7k
    return d2f(expr);\
2308
20.7k
  }
gdevpdfg.c:ht_EllipseC
Line
Count
Source
2305
20.7k
  static double name(double xd, double yd) {\
2306
20.7k
    float x = (float)xd, y = (float)yd;\
2307
20.7k
    return d2f(expr);\
2308
20.7k
  }
gdevpdfg.c:ht_InvertedEllipseC
Line
Count
Source
2305
20.7k
  static double name(double xd, double yd) {\
2306
20.7k
    float x = (float)xd, y = (float)yd;\
2307
20.7k
    return d2f(expr);\
2308
20.7k
  }
gdevpdfg.c:ht_Line
Line
Count
Source
2305
20.7k
  static double name(double xd, double yd) {\
2306
20.7k
    float x = (float)xd, y = (float)yd;\
2307
20.7k
    return d2f(expr);\
2308
20.7k
  }
gdevpdfg.c:ht_LineX
Line
Count
Source
2305
20.7k
  static double name(double xd, double yd) {\
2306
20.7k
    float x = (float)xd, y = (float)yd;\
2307
20.7k
    return d2f(expr);\
2308
20.7k
  }
gdevpdfg.c:ht_LineY
Line
Count
Source
2305
20.7k
  static double name(double xd, double yd) {\
2306
20.7k
    float x = (float)xd, y = (float)yd;\
2307
20.7k
    return d2f(expr);\
2308
20.7k
  }
gdevpdfg.c:ht_Square
Line
Count
Source
2305
20.7k
  static double name(double xd, double yd) {\
2306
20.7k
    float x = (float)xd, y = (float)yd;\
2307
41.4k
    return d2f(expr);\
2308
20.7k
  }
gdevpdfg.c:ht_Cross
Line
Count
Source
2305
20.7k
  static double name(double xd, double yd) {\
2306
20.7k
    float x = (float)xd, y = (float)yd;\
2307
41.4k
    return d2f(expr);\
2308
20.7k
  }
gdevpdfg.c:ht_Rhomboid
Line
Count
Source
2305
20.7k
  static double name(double xd, double yd) {\
2306
20.7k
    float x = (float)xd, y = (float)yd;\
2307
20.7k
    return d2f(expr);\
2308
20.7k
  }
gdevpdfg.c:ht_DoubleDot
Line
Count
Source
2305
20.7k
  static double name(double xd, double yd) {\
2306
20.7k
    float x = (float)xd, y = (float)yd;\
2307
20.7k
    return d2f(expr);\
2308
20.7k
  }
gdevpdfg.c:ht_InvertedDoubleDot
Line
Count
Source
2305
20.7k
  static double name(double xd, double yd) {\
2306
20.7k
    float x = (float)xd, y = (float)yd;\
2307
20.7k
    return d2f(expr);\
2308
20.7k
  }
gdevpdfg.c:ht_SimpleDot
Line
Count
Source
2305
20.7k
  static double name(double xd, double yd) {\
2306
20.7k
    float x = (float)xd, y = (float)yd;\
2307
20.7k
    return d2f(expr);\
2308
20.7k
  }
gdevpdfg.c:ht_InvertedSimpleDot
Line
Count
Source
2305
20.7k
  static double name(double xd, double yd) {\
2306
20.7k
    float x = (float)xd, y = (float)yd;\
2307
20.7k
    return d2f(expr);\
2308
20.7k
  }
gdevpdfg.c:ht_CosineDot
Line
Count
Source
2305
20.7k
  static double name(double xd, double yd) {\
2306
20.7k
    float x = (float)xd, y = (float)yd;\
2307
20.7k
    return d2f(expr);\
2308
20.7k
  }
gdevpdfg.c:ht_Double
Line
Count
Source
2305
20.7k
  static double name(double xd, double yd) {\
2306
20.7k
    float x = (float)xd, y = (float)yd;\
2307
20.7k
    return d2f(expr);\
2308
20.7k
  }
gdevpdfg.c:ht_InvertedDouble
Line
Count
Source
2305
20.7k
  static double name(double xd, double yd) {\
2306
20.7k
    float x = (float)xd, y = (float)yd;\
2307
20.7k
    return d2f(expr);\
2308
20.7k
  }
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.58M
{
2318
1.58M
    float f = (float)d;
2319
1.58M
    return f;
2320
1.58M
}
2321
static double
2322
ht_Round(double xf, double yf)
2323
78.6k
{
2324
78.6k
    float x = (float)xf, y = (float)yf;
2325
78.6k
    float xabs = fabs(x), yabs = fabs(y);
2326
2327
78.6k
    if (d2f(xabs + yabs) <= 1)
2328
39.3k
        return d2f(1 - d2f(d2f(x * x) + d2f(y * y)));
2329
39.3k
    xabs -= 1, yabs -= 1;
2330
39.3k
    return d2f(d2f(d2f(xabs * xabs) + d2f(yabs * yabs)) - 1);
2331
78.6k
}
2332
static double
2333
ht_Diamond(double xf, double yf)
2334
20.7k
{
2335
20.7k
    float x = (float)xf, y = (float)yf;
2336
20.7k
    float xabs = fabs(x), yabs = fabs(y);
2337
2338
20.7k
    if (d2f(xabs + yabs) <= 0.75)
2339
10.3k
        return d2f(1 - d2f(d2f(x * x) + d2f(y * y)));
2340
10.3k
    if (d2f(xabs + yabs) <= d2f(1.23))
2341
0
        return d2f(1 - d2f(d2f(d2f(0.85) * xabs) + yabs));
2342
10.3k
    xabs -= 1, yabs -= 1;
2343
10.3k
    return d2f(d2f(d2f(xabs * xabs) + d2f(yabs * yabs)) - 1);
2344
10.3k
}
2345
static double
2346
ht_Ellipse(double xf, double yf)
2347
20.7k
{
2348
20.7k
    float x = (float)xf, y = (float)yf;
2349
20.7k
    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
20.7k
    float w = (float)(d2f(d2f(3 * xabs) + d2f(4 * yabs)) - 3);
2356
2357
20.7k
    if (w < 0) {
2358
10.3k
        yabs /= 0.75;
2359
10.3k
        return d2f(1 - d2f((d2f(x * x) + d2f(yabs * yabs)) / 4));
2360
10.3k
    }
2361
10.3k
    if (w > 1) {
2362
10.3k
        xabs = 1 - xabs, yabs = d2f(1 - yabs) / 0.75;
2363
10.3k
        return d2f(d2f((d2f(xabs * xabs) + d2f(yabs * yabs)) / 4) - 1);
2364
10.3k
    }
2365
0
    return d2f(0.5 - w);
2366
10.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
165k
d2fsin_d(double x) {
2373
165k
    return d2f(gs_sin_degrees(d2f(x)));
2374
165k
}
2375
static float
2376
41.4k
d2fcos_d(double x) {
2377
41.4k
    return d2f(gs_cos_degrees(d2f(x)));
2378
41.4k
}
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
1.15k
{
2430
    /****** DOESN'T HANDLE STRIP HALFTONES ******/
2431
1.15k
    int w = porder->width, h = porder->height;
2432
1.15k
    uint num_bits = porder->num_bits;
2433
1.15k
    gs_function_Sd_params_t params;
2434
1.15k
    static const float domain_spot[4] = { -1, 1, -1, 1 };
2435
1.15k
    static const float range_spot[4] = { -1, 1 };
2436
1.15k
    int size[2];
2437
1.15k
    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
1.15k
    byte *values;
2443
1.15k
    gs_function_t *pfn;
2444
1.15k
    uint i;
2445
1.15k
    int code = 0;
2446
2447
1.15k
    params.array_size = 0;
2448
1.15k
    params.m = 2;
2449
1.15k
    params.Domain = domain_spot;
2450
1.15k
    params.n = 1;
2451
1.15k
    params.Range = range_spot;
2452
1.15k
    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
1.15k
    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
1.15k
    params.BitsPerSample = 16;
2465
1.15k
    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
1.15k
    params.Decode = 0;
2472
1.15k
    size[0] = w;
2473
1.15k
    size[1] = h;
2474
1.15k
    params.Size = size;
2475
    /* Create the (temporary) threshold array. */
2476
1.15k
    values = gs_alloc_byte_array(mem, num_bits, 2, "pdf_write_spot_function");
2477
1.15k
    if (values == 0)
2478
0
        return_error(gs_error_VMerror);
2479
42.5k
    for (i = 0; i < num_bits; ++i) {
2480
41.4k
        gs_int_point pt;
2481
41.4k
        int value;
2482
2483
41.4k
        if ((code = porder->procs->bit_index(porder, i, &pt)) < 0)
2484
0
            break;
2485
41.4k
        value = pt.y * w + pt.x;
2486
        /* Always store the values in big-endian order. */
2487
41.4k
        values[i * 2] = (byte)(value >> 8);
2488
41.4k
        values[i * 2 + 1] = (byte)value;
2489
41.4k
    }
2490
1.15k
    data_source_init_bytes(&params.DataSource, (const byte *)values,
2491
1.15k
                           sizeof(*values) * num_bits);
2492
1.15k
    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
1.15k
        (code = gs_function_Sd_init(&pfn, &params, mem)) >= 0
2497
1.15k
        ) {
2498
1.15k
        code = pdf_write_function(pdev, pfn, pid);
2499
1.15k
        gs_function_free(pfn, false, mem);
2500
1.15k
    }
2501
1.15k
    gs_free_object(mem, values, "pdf_write_spot_function");
2502
1.15k
    return code;
2503
1.15k
}
2504
2505
/* if (memcmp(order.levels, porder->levels, order.num_levels * sizeof(*order.levels))) */
2506
static int
2507
31.3k
compare_gx_ht_order_levels(const gx_ht_order *order1, const gx_ht_order *order2) {
2508
31.3k
  int i;
2509
524k
  for (i=0;  i<order1->num_levels;  i++) {
2510
492k
    if (order1->levels[i] != order2->levels[i])
2511
0
      return(1);
2512
492k
  }
2513
31.3k
  return(0);
2514
31.3k
}
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
8.39k
{
2520
8.39k
    char trs[17 + MAX_FN_CHARS + 1];
2521
8.39k
    int code;
2522
8.39k
    int64_t spot_id;
2523
8.39k
    stream *s;
2524
8.39k
    int i = countof(ht_functions);
2525
8.39k
    gs_memory_t *mem = pdev->pdf_memory;
2526
2527
8.39k
    if (pdev->CompatibilityLevel <= 1.7) {
2528
8.39k
        code = pdf_write_transfer(pdev, porder->transfer, "/TransferFunction",
2529
8.39k
                                  trs, sizeof(trs));
2530
8.39k
        if (code < 0)
2531
0
            return code;
2532
8.39k
    }
2533
    /*
2534
     * See if we can recognize the spot function, by comparing its sampled
2535
     * values against those in the order.
2536
     */
2537
8.39k
    { gs_screen_enum senum;
2538
8.39k
        gx_ht_order order;
2539
8.39k
        int code;
2540
2541
8.39k
        order = *porder;
2542
8.39k
        code = gs_screen_order_alloc(&order, mem);
2543
8.39k
        if (code < 0)
2544
0
            goto notrec;
2545
32.5k
        for (i = 0; i < countof(ht_functions); ++i) {
2546
31.3k
            double (*spot_proc)(double, double) = ht_functions[i].proc;
2547
31.3k
            gs_point pt;
2548
2549
31.3k
            gs_screen_enum_init_memory(&senum, &order, NULL, &psht->screen,
2550
31.3k
                                       mem);
2551
524k
            while ((code = gs_screen_currentpoint(&senum, &pt)) == 0 &&
2552
492k
                   gs_screen_next(&senum, spot_proc(pt.x, pt.y)) >= 0)
2553
492k
                DO_NOTHING;
2554
31.3k
            if (code < 0)
2555
0
                continue;
2556
            /* Compare the bits and levels arrays. */
2557
31.3k
            if (compare_gx_ht_order_levels(&order,porder))
2558
0
                continue;
2559
31.3k
            if (memcmp(order.bit_data, porder->bit_data,
2560
31.3k
                       (size_t)order.num_bits *
2561
31.3k
                                      porder->procs->bit_data_elt_size))
2562
24.1k
                continue;
2563
            /* We have a match. */
2564
7.24k
            break;
2565
31.3k
        }
2566
8.39k
        gx_ht_order_release(&order, mem, false);
2567
8.39k
    }
2568
8.39k
 notrec:
2569
8.39k
    if (i == countof(ht_functions)) {
2570
        /* Create and write a Function for the spot function. */
2571
1.15k
        code = pdf_write_spot_function(pdev, porder, &spot_id);
2572
1.15k
        if (code < 0)
2573
0
            return code;
2574
1.15k
    }
2575
8.39k
    *pid = pdf_begin_separate(pdev, resourceHalftone);
2576
8.39k
    s = pdev->strm;
2577
    /* Use the original, requested frequency and angle. */
2578
8.39k
    pprintg2(s, "<</Type/Halftone/HalftoneType 1/Frequency %g/Angle %g",
2579
8.39k
             psht->screen.frequency, psht->screen.angle);
2580
8.39k
    if (i < countof(ht_functions))
2581
7.24k
        pprints1(s, "/SpotFunction/%s", ht_functions[i].fname);
2582
1.15k
    else
2583
1.15k
        pprinti64d1(s, "/SpotFunction %"PRId64" 0 R", spot_id);
2584
8.39k
    if (pdev->CompatibilityLevel <= 1.7)
2585
8.39k
        stream_puts(s, trs);
2586
8.39k
    if (psht->accurate_screens)
2587
0
        stream_puts(s, "/AccurateScreens true");
2588
8.39k
    stream_puts(s, ">>\n");
2589
8.39k
    return pdf_end_separate(pdev, resourceHalftone);
2590
8.39k
}
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
1.15k
{
2595
1.15k
    gs_spot_halftone spot;
2596
2597
1.15k
    spot.screen = *psht;
2598
1.15k
    spot.accurate_screens = false;
2599
1.15k
    spot.transfer = 0;
2600
1.15k
    spot.transfer_closure.proc = 0;
2601
1.15k
    return pdf_write_spot_halftone(pdev, &spot, porder, pid);
2602
1.15k
}
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
43.4k
{
2728
43.4k
    int j;
2729
2730
86.8k
    for (j = 0; j < pmht->num_comp; j++)
2731
43.4k
        if (pmht->components[j].comp_number == dht_index)
2732
0
            break;
2733
43.4k
    if (j == pmht->num_comp) {
2734
        /* Look for Default. */
2735
43.4k
        for (j = 0; j < pmht->num_comp; j++)
2736
43.4k
            if (pmht->components[j].comp_number == GX_DEVICE_COLOR_MAX_COMPONENTS)
2737
43.4k
                break;
2738
43.4k
        if (j == pmht->num_comp)
2739
0
            return_error(gs_error_undefined);
2740
43.4k
    }
2741
43.4k
    return j;
2742
43.4k
}
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
7.24k
{
2748
7.24k
    stream *s;
2749
7.24k
    int i, code, last_comp = 0;
2750
7.24k
    gs_memory_t *mem = pdev->pdf_memory;
2751
7.24k
    long *ids;
2752
7.24k
    bool done_Default = false;
2753
2754
7.24k
    ids = (long *)gs_alloc_byte_array(mem, pmht->num_comp, sizeof(long),
2755
7.24k
                                      "pdf_write_multiple_halftone");
2756
7.24k
    if (ids == 0)
2757
0
        return_error(gs_error_VMerror);
2758
28.9k
    for (i = 0; i < pdht->num_comp; ++i) {
2759
21.7k
        const gs_halftone_component *phtc;
2760
21.7k
        const gx_ht_order *porder;
2761
2762
21.7k
        code = pdf_get_halftone_component_index(pmht, pdht, i);
2763
21.7k
        if (code < 0)
2764
0
            return code;
2765
21.7k
        if (pmht->components[code].comp_number == GX_DEVICE_COLOR_MAX_COMPONENTS) {
2766
21.7k
            if (done_Default)
2767
14.4k
                continue;
2768
7.24k
            done_Default = true;
2769
7.24k
        }
2770
7.24k
        phtc = &pmht->components[code];
2771
7.24k
        porder = (pdht->components == 0 ? &pdht->order :
2772
7.24k
                       &pdht->components[i].corder);
2773
7.24k
        switch (phtc->type) {
2774
7.24k
        case ht_type_spot:
2775
7.24k
            code = pdf_write_spot_halftone(pdev, &phtc->params.spot,
2776
7.24k
                                           porder, &ids[i]);
2777
7.24k
            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
7.24k
        }
2790
7.24k
        if (code < 0) {
2791
0
            gs_free_object(mem, ids, "pdf_write_multiple_halftone");
2792
0
            return code;
2793
0
        }
2794
7.24k
    }
2795
7.24k
    *pid = pdf_begin_separate(pdev, resourceHalftone);
2796
7.24k
    s = pdev->strm;
2797
7.24k
    stream_puts(s, "<</Type/Halftone/HalftoneType 5\n");
2798
7.24k
    done_Default = false;
2799
28.9k
    for (i = 0; i < pdht->num_comp; ++i) {
2800
21.7k
        const gs_halftone_component *phtc;
2801
21.7k
        byte *str;
2802
21.7k
        uint len;
2803
21.7k
        cos_value_t value;
2804
2805
21.7k
        code = pdf_get_halftone_component_index(pmht, pdht, i);
2806
21.7k
        if (code < 0)
2807
0
            return code;
2808
21.7k
        if (pmht->components[code].comp_number == GX_DEVICE_COLOR_MAX_COMPONENTS) {
2809
21.7k
            if (done_Default)
2810
14.4k
                continue;
2811
7.24k
            done_Default = true;
2812
7.24k
        }
2813
7.24k
        phtc = &pmht->components[code];
2814
7.24k
        if ((code = pmht->get_colorname_string(pgs, phtc->cname, &str, &len)) < 0 ||
2815
7.24k
            (code = pdf_string_to_cos_name(pdev, str, len, &value)) < 0)
2816
0
            return code;
2817
7.24k
        cos_value_write(&value, pdev);
2818
7.24k
        gs_free_string(mem, value.contents.chars.data,
2819
7.24k
                       value.contents.chars.size,
2820
7.24k
                       "pdf_write_multiple_halftone");
2821
7.24k
        pprintld1(s, " %ld 0 R\n", ids[i]);
2822
7.24k
        last_comp = i;
2823
7.24k
    }
2824
7.24k
    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
7.24k
    stream_puts(s, ">>\n");
2834
7.24k
    gs_free_object(mem, ids, "pdf_write_multiple_halftone");
2835
7.24k
    return pdf_end_separate(pdev, resourceHalftone);
2836
7.24k
}
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
8.39k
{
2846
8.39k
    const gs_halftone *pht = pgs->halftone;
2847
8.39k
    const gx_device_halftone *pdht = pgs->dev_ht[HT_OBJTYPE_DEFAULT];
2848
8.39k
    int code;
2849
8.39k
    long id;
2850
2851
8.39k
    switch (pht->type) {
2852
1.15k
    case ht_type_screen:
2853
1.15k
        code = pdf_write_screen_halftone(pdev, &pht->params.screen,
2854
1.15k
                                         &pdht->components[0].corder, &id);
2855
1.15k
        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
7.24k
    case ht_type_multiple:
2873
7.24k
    case ht_type_multiple_colorscreen:
2874
7.24k
        code = pdf_write_multiple_halftone(pdev, (gs_gstate *)pgs, &pht->params.multiple,
2875
7.24k
                                           pdht, &id);
2876
7.24k
        break;
2877
0
    default:
2878
0
        return_error(gs_error_rangecheck);
2879
8.39k
    }
2880
8.39k
    if (code < 0)
2881
0
        return code;
2882
8.39k
    gs_snprintf(hts, hts_max, "%ld 0 R", id);
2883
8.39k
    pdev->halftone_id = pgs->dev_ht[HT_OBJTYPE_DEFAULT]->id;
2884
8.39k
    return code;
2885
8.39k
}
2886
2887
/* ------ Graphics state updating ------ */
2888
2889
static inline cos_dict_t *
2890
resource_dict(pdf_resource_t *pres)
2891
191k
{
2892
191k
    return (cos_dict_t *)pres->object;
2893
191k
}
2894
2895
/* Open an ExtGState. */
2896
static int
2897
pdf_open_gstate(gx_device_pdf *pdev, pdf_resource_t **ppres)
2898
92.8k
{
2899
92.8k
    int code;
2900
2901
92.8k
    if (*ppres)
2902
7.69k
        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
85.1k
    if (pdev->context != PDF_IN_STREAM) {
2909
        /* We apparently use gs_error_interrupt as a request to change context. */
2910
6.10k
      return_error(gs_error_interrupt);
2911
6.10k
    }
2912
79.0k
    code = pdf_alloc_resource(pdev, resourceExtGState, gs_no_id, ppres, -1L);
2913
79.0k
    if (code < 0)
2914
0
        return code;
2915
79.0k
    cos_become((*ppres)->object, cos_type_dict);
2916
79.0k
    code = cos_dict_put_c_key_string(resource_dict(*ppres), "/Type", (const byte *)"/ExtGState", 10);
2917
79.0k
    if (code < 0)
2918
0
        return code;
2919
79.0k
    return 0;
2920
79.0k
}
2921
2922
/* Finish writing an ExtGState. */
2923
int
2924
pdf_end_gstate(gx_device_pdf *pdev, pdf_resource_t *pres)
2925
9.10M
{
2926
9.10M
    if (pres) {
2927
79.0k
        int code = pdf_substitute_resource(pdev, &pres, resourceExtGState, NULL, true);
2928
2929
79.0k
        if (code < 0)
2930
0
            return code;
2931
79.0k
        pres->where_used |= pdev->used_mask;
2932
79.0k
        code = pdf_open_page(pdev, PDF_IN_STREAM);
2933
79.0k
        if (code < 0)
2934
0
            return code;
2935
79.0k
        code = pdf_add_resource(pdev, pdev->substream_Resources, "/ExtGState", pres);
2936
79.0k
        if (code < 0)
2937
0
            return code;
2938
79.0k
        pprinti64d1(pdev->strm, "/R%"PRId64" gs\n", pdf_resource_id(pres));
2939
79.0k
        pres->where_used |= pdev->used_mask;
2940
79.0k
    }
2941
9.10M
    return 0;
2942
9.10M
}
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.95M
{
2952
8.95M
    int i, pi = -1;
2953
8.95M
    bool multiple = false, update = false;
2954
8.95M
    gs_id transfer_ids[4];
2955
8.95M
    int code = 0;
2956
8.95M
    const gx_transfer_map *tm[4];
2957
2958
8.95M
    tm[0] = pgs->set_transfer.red;
2959
8.95M
    tm[1] = pgs->set_transfer.green;
2960
8.95M
    tm[2] = pgs->set_transfer.blue;
2961
8.95M
    tm[3] = pgs->set_transfer.gray;
2962
44.7M
    for (i = 0; i < 4; ++i)
2963
35.8M
        if (tm[i] != NULL) {
2964
8.95M
            transfer_ids[i] = tm[i]->id;
2965
8.95M
            if (pdev->transfer_ids[i] != tm[i]->id)
2966
18.7k
                update = true;
2967
8.95M
            if (pi != -1 && transfer_ids[i] != transfer_ids[pi])
2968
399
                multiple = true;
2969
8.95M
            pi = i;
2970
8.95M
        } else
2971
26.8M
            transfer_ids[i] = -1;
2972
8.95M
    if (update) {
2973
18.6k
        int mask;
2974
2975
18.6k
        if (!multiple) {
2976
18.6k
            code = pdf_write_transfer(pdev, tm[pi], "", trs, trs_max);
2977
18.6k
            if (code < 0)
2978
0
                return code;
2979
18.6k
            mask = code == 0;
2980
18.6k
        } else {
2981
22
            strcpy(trs, "[");
2982
22
            mask = 0;
2983
110
            for (i = 0; i < 4; ++i)
2984
88
                if (tm[i] != NULL) {
2985
88
                    int len = (int)strlen(trs);
2986
88
                    code = pdf_write_transfer_map(pdev,
2987
88
                                                  tm[i],
2988
88
                                                  0, true, " ", trs + len, trs_max - len);
2989
88
                    if (code < 0)
2990
0
                        return code;
2991
88
                    mask |= (code == 0) << i;
2992
88
                }
2993
22
            strcat(trs, "]");
2994
22
        }
2995
18.6k
        memcpy(pdev->transfer_ids, transfer_ids, sizeof(pdev->transfer_ids));
2996
18.6k
        pdev->transfer_not_identity = mask;
2997
18.6k
    }
2998
8.95M
    return code;
2999
8.95M
}
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
4.78M
{
3010
4.78M
    int code;
3011
3012
4.78M
    if (pdev->state.soft_mask_id != pgs->soft_mask_id) {
3013
416
        char buf[20];
3014
3015
416
        if (pgs->soft_mask_id == 0) {
3016
90
            code = pdf_open_contents(pdev, PDF_IN_STREAM);
3017
90
            if (code < 0)
3018
0
                return code;
3019
90
            if (pdev->vgstack_depth > pdev->vgstack_bottom) {
3020
89
                code = pdf_restore_viewer_state(pdev, pdev->strm);
3021
89
                if (code < 0)
3022
0
                    return code;
3023
89
            }
3024
90
        }
3025
326
        else{
3026
326
            gs_snprintf(buf, sizeof(buf), "%ld 0 R", pgs->soft_mask_id);
3027
326
            code = pdf_open_gstate(pdev, ppres);
3028
326
            if (code < 0)
3029
0
                return code;
3030
326
            code = cos_dict_put_c_key_string(resource_dict(*ppres),
3031
326
                        "/SMask", (byte *)buf, strlen(buf));
3032
326
            if (code < 0)
3033
0
                return code;
3034
326
            code = pdf_save_viewer_state(pdev, pdev->strm);
3035
326
            if (code < 0)
3036
0
                return code;
3037
326
        }
3038
416
        pdev->state.soft_mask_id = pgs->soft_mask_id;
3039
416
    }
3040
3041
4.78M
    if (pdev->state.alphaisshape != pgs->alphaisshape ||
3042
4.77M
        pdev->state.strokeconstantalpha != pgs->strokeconstantalpha ||
3043
4.77M
        pdev->state.fillconstantalpha != pgs->fillconstantalpha) {
3044
3045
4.77k
        code = pdf_open_gstate(pdev, ppres);
3046
4.77k
        if (code < 0)
3047
591
            return code;
3048
3049
4.17k
        code = cos_dict_put_c_key_bool(resource_dict(*ppres), "/AIS", pgs->alphaisshape);
3050
4.17k
        if (code < 0)
3051
0
            return code;
3052
4.17k
        pdev->state.alphaisshape = pgs->alphaisshape;
3053
4.17k
        code = cos_dict_put_c_key_real(resource_dict(*ppres), "/CA", pgs->strokeconstantalpha);
3054
4.17k
        if (code < 0)
3055
0
            return code;
3056
4.17k
        pdev->state.strokeconstantalpha = pgs->strokeconstantalpha;
3057
4.17k
        code = cos_dict_put_c_key_real(resource_dict(*ppres), "/ca", pgs->fillconstantalpha);
3058
4.17k
        if (code < 0)
3059
0
            return code;
3060
4.17k
        pdev->state.fillconstantalpha = pgs->fillconstantalpha;
3061
4.17k
    }
3062
4.78M
    return 0;
3063
4.78M
}
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
9.11M
{
3072
9.11M
    int code = 0;
3073
9.11M
    int bottom;
3074
3075
9.11M
    if (pdev->CompatibilityLevel >= 1.4) {
3076
4.78M
        code = pdf_update_alpha(pdev, pgs, ppres, for_text);
3077
4.78M
        if (code < 0)
3078
591
            return code;
3079
4.78M
        if (pdev->state.blend_mode != pgs->blend_mode) {
3080
3.06k
            static const char *const bm_names[] = { GS_BLEND_MODE_NAMES };
3081
3.06k
            char buf[20];
3082
3083
3.06k
            code = pdf_open_gstate(pdev, ppres);
3084
3.06k
            if (code < 0)
3085
45
                return code;
3086
3.02k
            buf[0] = '/';
3087
3.02k
            strncpy(buf + 1, bm_names[pgs->blend_mode], sizeof(buf) - 2);
3088
3.02k
            code = cos_dict_put_string_copy(resource_dict(*ppres), "/BM", buf);
3089
3.02k
            if (code < 0)
3090
0
                return code;
3091
3.02k
            pdev->state.blend_mode = pgs->blend_mode;
3092
3.02k
        }
3093
4.78M
    } 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.33M
        if (pgs->strokeconstantalpha != 1 ||
3099
4.32M
            pgs->fillconstantalpha != 1)
3100
7.49k
            return_error(gs_error_rangecheck);
3101
4.33M
    }
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
9.10M
    bottom = (pdev->ResourcesBeforeUsage ? 1 : 0);
3112
    /* When ResourcesBeforeUsage != 0, one sbstack element
3113
       appears from the page contents stream. */
3114
9.10M
    if (pdev->sbstack_depth == bottom) {
3115
8.95M
        gs_int_point phase, dev_phase;
3116
8.95M
        char hts[5 + MAX_FN_CHARS + 1],
3117
8.95M
            trs[5 + MAX_FN_CHARS * 4 + 6 + 1],
3118
8.95M
            bgs[5 + MAX_FN_CHARS + 1],
3119
8.95M
            ucrs[6 + MAX_FN_CHARS + 1];
3120
3121
8.95M
        hts[0] = trs[0] = bgs[0] = ucrs[0] = 0;
3122
8.95M
        if (pdev->params.PreserveHalftoneInfo &&
3123
4.32M
            pdev->halftone_id != pgs->dev_ht[HT_OBJTYPE_DEFAULT]->id &&
3124
8.39k
            pdev->PDFX == 0
3125
8.95M
            ) {
3126
8.39k
            code = pdf_update_halftone(pdev, pgs, hts, sizeof(hts));
3127
8.39k
            if (code < 0)
3128
0
                return code;
3129
8.39k
        }
3130
8.95M
        if (pdev->params.TransferFunctionInfo != tfi_Remove &&
3131
8.95M
            pdev->PDFX == 0 && pdev->PDFA == 0
3132
8.95M
            ) {
3133
8.95M
            code = pdf_update_transfer(pdev, pgs, trs, sizeof(trs));
3134
8.95M
            if (code < 0)
3135
0
                return code;
3136
8.95M
        }
3137
8.95M
        if (pdev->params.UCRandBGInfo == ucrbg_Preserve) {
3138
8.95M
            if (pgs->black_generation && pdev->black_generation_id != pgs->black_generation->id) {
3139
9.32k
                code = pdf_write_transfer_map(pdev, pgs->black_generation,
3140
9.32k
                                              0, false, "", bgs, sizeof(bgs));
3141
9.32k
                if (code < 0)
3142
0
                    return code;
3143
9.32k
                pdev->black_generation_id = pgs->black_generation->id;
3144
9.32k
            }
3145
8.95M
            if (pgs->undercolor_removal && pdev->undercolor_removal_id != pgs->undercolor_removal->id) {
3146
9.31k
                code = pdf_write_transfer_map(pdev, pgs->undercolor_removal,
3147
9.31k
                                              -1, false, "", ucrs, sizeof(ucrs));
3148
9.31k
                if (code < 0)
3149
0
                    return code;
3150
9.31k
                pdev->undercolor_removal_id = pgs->undercolor_removal->id;
3151
9.31k
            }
3152
8.95M
        }
3153
8.95M
        if (hts[0] || trs[0] || bgs[0] || ucrs[0]) {
3154
29.8k
            code = pdf_open_gstate(pdev, ppres);
3155
29.8k
            if (code < 0)
3156
2.36k
                return code;
3157
29.8k
        }
3158
8.95M
        if (hts[0]) {
3159
8.39k
            code = cos_dict_put_string_copy(resource_dict(*ppres), "/HT", hts);
3160
8.39k
            if (code < 0)
3161
0
                return code;
3162
8.39k
        }
3163
8.95M
        if (pdev->CompatibilityLevel <= 1.7 && trs[0] && pdev->params.TransferFunctionInfo == tfi_Preserve) {
3164
16.2k
            code = cos_dict_put_string_copy(resource_dict(*ppres), "/TR", trs);
3165
16.2k
            if (code < 0)
3166
0
                return code;
3167
16.2k
        }
3168
8.95M
        if (bgs[0]) {
3169
9.24k
            code = cos_dict_put_string_copy(resource_dict(*ppres), "/BG", bgs);
3170
9.24k
            if (code < 0)
3171
0
                return code;
3172
9.24k
        }
3173
8.95M
        if (ucrs[0]) {
3174
9.23k
            code = cos_dict_put_string_copy(resource_dict(*ppres), "/UCR", ucrs);
3175
9.23k
            if (code < 0)
3176
0
                return code;
3177
9.23k
        }
3178
8.95M
        if (pdev->PDFX == 0) {
3179
8.95M
            gs_currentscreenphase(pgs, &phase, 0);
3180
8.95M
            gs_currentscreenphase(&pdev->state, &dev_phase, 0);
3181
8.95M
            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.95M
            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.95M
        }
3226
8.95M
    }
3227
9.10M
    if (pdev->state.overprint_mode != pdev->params.OPM) {
3228
2.48k
        if (pdev->params.OPM != pgs->overprint_mode)
3229
1.21k
            ((gs_gstate *)pgs)->overprint_mode = pdev->params.OPM;
3230
2.48k
    }
3231
9.10M
    if (pdev->CompatibilityLevel >= 1.3 /*&& pdev->sbstack_depth == bottom */) {
3232
4.78M
        if (pdev->state.overprint_mode != pgs->overprint_mode) {
3233
11.7k
            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
11.7k
            if (pdev->state.overprint_mode != pgs->overprint_mode) {
3261
11.7k
                code = pdf_open_gstate(pdev, ppres);
3262
11.7k
                if (code < 0)
3263
621
                    return code;
3264
11.1k
                code = cos_dict_put_c_key_int(resource_dict(*ppres), "/OPM", pgs->overprint_mode);
3265
11.1k
                if (code < 0)
3266
0
                    return code;
3267
11.1k
                pdev->params.OPM = pdev->state.overprint_mode = pgs->overprint_mode;
3268
11.1k
            }
3269
11.7k
        }
3270
4.77M
        if (pdev->state.smoothness != pgs->smoothness) {
3271
124
            code = pdf_open_gstate(pdev, ppres);
3272
124
            if (code < 0)
3273
18
                return code;
3274
106
            code = cos_dict_put_c_key_real(resource_dict(*ppres), "/SM", pgs->smoothness);
3275
106
            if (code < 0)
3276
0
                return code;
3277
106
            pdev->state.smoothness = pgs->smoothness;
3278
106
        }
3279
4.77M
        if (pdev->CompatibilityLevel >= 1.4) {
3280
4.77M
            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
4.77M
        }
3290
4.77M
    }
3291
9.10M
    return code;
3292
9.10M
}
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
8.15M
{
3298
8.15M
    pdf_resource_t *pres = 0;
3299
8.15M
    int code = pdf_prepare_drawing(pdev, pgs, &pres, for_text);
3300
3301
8.15M
    if (code < 0)
3302
10.1k
        return code;
3303
8.14M
    if (pdev->rendering_intent != pgs->renderingintent && !pdev->ForOPDFRead) {
3304
9.65k
        static const char *const ri_names[] = { "Perceptual", "RelativeColorimetric", "Saturation", "AbsoluteColorimetric" };
3305
9.65k
        char buf[32];
3306
3307
9.65k
        code = pdf_open_gstate(pdev, &pres);
3308
9.65k
        if (code < 0)
3309
171
            return code;
3310
3311
9.48k
        buf[0] = '/';
3312
9.48k
        strncpy(buf + 1, ri_names[pgs->renderingintent], sizeof(buf) - 2);
3313
9.48k
        code = cos_dict_put_string_copy(resource_dict(pres), "/RI", buf);
3314
9.48k
        if (code < 0)
3315
0
            return code;
3316
9.48k
        pdev->rendering_intent = pgs->renderingintent;
3317
9.48k
    }
3318
3319
    /* Update overprint. */
3320
8.14M
    if (pdev->params.PreserveOverprintSettings &&
3321
8.14M
        (pdev->fill_overprint != pgs->overprint ||
3322
8.13M
        pdev->font3) && !pdev->skip_colors
3323
8.14M
        ) {
3324
15.3k
        if (pres == 0)
3325
13.5k
            code = pdf_open_gstate(pdev, &pres);
3326
15.3k
        if (code < 0)
3327
2.12k
            return code;
3328
        /* PDF 1.2 only has a single overprint setting. */
3329
13.1k
        if (pdev->CompatibilityLevel < 1.3) {
3330
3.12k
            code = cos_dict_put_c_key_bool(resource_dict(pres), "/OP", pgs->overprint);
3331
3.12k
            if (code < 0)
3332
0
                return code;
3333
3.12k
            pdev->stroke_overprint = pgs->overprint;
3334
10.0k
        } else {
3335
10.0k
            code = cos_dict_put_c_key_bool(resource_dict(pres), "/op", pgs->overprint);
3336
10.0k
            if (code < 0)
3337
0
                return code;
3338
10.0k
        }
3339
13.1k
        pdev->fill_overprint = pgs->overprint;
3340
13.1k
    }
3341
8.13M
    return pdf_end_gstate(pdev, pres);
3342
8.14M
}
3343
int
3344
pdf_prepare_fill(gx_device_pdf *pdev, const gs_gstate *pgs, bool for_text)
3345
8.14M
{
3346
8.14M
    int code;
3347
3348
8.14M
    if (pdev->context != PDF_IN_STREAM) {
3349
6.35M
        code = pdf_try_prepare_fill(pdev, pgs, for_text);
3350
6.35M
        if (code != gs_error_interrupt) /* See pdf_open_gstate */
3351
6.35M
            return code;
3352
5.36k
        code = pdf_open_contents(pdev, PDF_IN_STREAM);
3353
5.36k
        if (code < 0)
3354
0
            return code;
3355
5.36k
    }
3356
1.79M
    return pdf_try_prepare_fill(pdev, pgs, for_text);
3357
8.14M
}
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
946k
{
3363
946k
    pdf_resource_t *pres = 0;
3364
946k
    int code = pdf_prepare_drawing(pdev, pgs, &pres, for_text);
3365
3366
946k
    if (code < 0)
3367
401
        return code;
3368
945k
    if (pdev->rendering_intent != pgs->renderingintent && !pdev->ForOPDFRead) {
3369
157
        static const char *const ri_names[] = { "Perceptual", "RelativeColorimetric", "Saturation", "AbsoluteColorimetric" };
3370
157
        char buf[32];
3371
3372
157
        code = pdf_open_gstate(pdev, &pres);
3373
157
        if (code < 0)
3374
0
            return code;
3375
3376
157
        buf[0] = '/';
3377
157
        strncpy(buf + 1, ri_names[pgs->renderingintent], sizeof(buf) - 2);
3378
157
        code = cos_dict_put_string_copy(resource_dict(pres), "/RI", buf);
3379
157
        if (code < 0)
3380
0
            return code;
3381
157
        pdev->rendering_intent = pgs->renderingintent;
3382
157
    }
3383
    /* Update overprint, stroke adjustment. */
3384
945k
    if (pdev->params.PreserveOverprintSettings &&
3385
945k
        pdev->stroke_overprint != pgs->stroke_overprint &&
3386
887
        !pdev->skip_colors
3387
945k
        ) {
3388
887
        if (pres == 0)
3389
800
            code = pdf_open_gstate(pdev, &pres);
3390
887
        if (code < 0)
3391
0
            return code;
3392
887
        code = cos_dict_put_c_key_bool(resource_dict(pres), "/OP", pgs->stroke_overprint);
3393
887
        if (code < 0)
3394
0
            return code;
3395
887
        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
887
        pdev->fill_overprint = pgs->stroke_overprint;
3401
887
    }
3402
945k
    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
25.1k
        if (!pdev->ForOPDFRead) {
3414
16.6k
            code = pdf_open_gstate(pdev, &pres);
3415
16.6k
            if (code < 0)
3416
0
                return code;
3417
16.6k
            code = cos_dict_put_c_key_bool(resource_dict(pres), "/SA", pgs->stroke_adjust);
3418
16.6k
            if (code < 0)
3419
0
                return code;
3420
16.6k
            pdev->state.stroke_adjust = pgs->stroke_adjust;
3421
16.6k
        } else {
3422
8.48k
            if (pgs->stroke_adjust)
3423
1.03k
                stream_puts(gdev_vector_stream((gx_device_vector *)pdev), "true setstrokeadjust\n");
3424
7.45k
            else
3425
7.45k
                stream_puts(gdev_vector_stream((gx_device_vector *)pdev), "false setstrokeadjust\n");
3426
8.48k
            pdev->state.stroke_adjust = pgs->stroke_adjust;
3427
8.48k
        }
3428
3429
25.1k
    }
3430
945k
    return pdf_end_gstate(pdev, pres);
3431
945k
}
3432
int
3433
pdf_prepare_stroke(gx_device_pdf *pdev, const gs_gstate *pgs, bool for_text)
3434
946k
{
3435
946k
    int code;
3436
3437
946k
    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
946k
    return pdf_try_prepare_stroke(pdev, pgs, for_text);
3446
946k
}
3447
3448
static int
3449
pdf_try_prepare_fill_stroke(gx_device_pdf *pdev, const gs_gstate *pgs, bool for_text)
3450
12.0k
{
3451
12.0k
    pdf_resource_t *pres = 0;
3452
12.0k
    int code = pdf_prepare_drawing(pdev, pgs, &pres, for_text);
3453
3454
12.0k
    if (code < 0)
3455
4
        return code;
3456
    /* Update overprint. */
3457
12.0k
    if (pdev->params.PreserveOverprintSettings &&
3458
12.0k
        (pdev->fill_overprint != pgs->overprint ||
3459
12.0k
         pdev->stroke_overprint != pgs->stroke_overprint ||
3460
12.0k
         pdev->font3) && !pdev->skip_colors
3461
12.0k
        ) {
3462
51
        code = pdf_open_gstate(pdev, &pres);
3463
51
        if (code < 0)
3464
4
            return code;
3465
        /* PDF 1.2 only has a single overprint setting. */
3466
47
        if (pdev->CompatibilityLevel < 1.3) {
3467
4
            code = cos_dict_put_c_key_bool(resource_dict(pres), "/OP", pgs->overprint);
3468
4
            if (code < 0)
3469
0
                return code;
3470
4
            pdev->stroke_overprint = pgs->overprint;
3471
43
        } else {
3472
43
            code = cos_dict_put_c_key_bool(resource_dict(pres), "/op", pgs->overprint);
3473
43
            if (code < 0)
3474
0
                return code;
3475
43
        }
3476
47
        pdev->fill_overprint = pgs->overprint;
3477
47
    }
3478
    /* Update overprint, stroke adjustment. */
3479
12.0k
    if (pdev->params.PreserveOverprintSettings &&
3480
12.0k
        pdev->stroke_overprint != pgs->stroke_overprint &&
3481
5
        !pdev->skip_colors
3482
12.0k
        ) {
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
12.0k
    if (pdev->state.stroke_adjust != pgs->stroke_adjust) {
3501
2.07k
        code = pdf_open_gstate(pdev, &pres);
3502
2.07k
        if (code < 0)
3503
166
            return code;
3504
1.91k
        code = cos_dict_put_c_key_bool(resource_dict(pres), "/SA", pgs->stroke_adjust);
3505
1.91k
        if (code < 0)
3506
0
            return code;
3507
1.91k
        pdev->state.stroke_adjust = pgs->stroke_adjust;
3508
1.91k
    }
3509
11.8k
    return pdf_end_gstate(pdev, pres);
3510
12.0k
}
3511
3512
int
3513
pdf_prepare_fill_stroke(gx_device_pdf *pdev, const gs_gstate *pgs, bool for_text)
3514
11.8k
{
3515
11.8k
    int code;
3516
3517
11.8k
    if (pdev->context != PDF_IN_STREAM) {
3518
1.24k
        code = pdf_try_prepare_fill_stroke(pdev, pgs, for_text);
3519
1.24k
        if (code != gs_error_interrupt) /* See pdf_open_gstate */
3520
1.07k
            return code;
3521
174
        code = pdf_open_contents(pdev, PDF_IN_STREAM);
3522
174
        if (code < 0)
3523
0
            return code;
3524
174
    }
3525
10.7k
    return pdf_try_prepare_fill_stroke(pdev, pgs, for_text);
3526
11.8k
}
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
81.1k
{
3532
    /*
3533
     * As it turns out, this requires updating the same parameters as for
3534
     * filling.
3535
     */
3536
81.1k
    return pdf_prepare_fill(pdev, pgs, false);
3537
81.1k
}
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
56.0k
{
3544
56.0k
    int code = pdf_prepare_image(pdev, pgs);
3545
3546
56.0k
    if (code < 0)
3547
0
        return code;
3548
56.0k
    return pdf_set_drawing_color(pdev, pgs, pdcolor, &pdev->saved_fill_color,
3549
56.0k
                                 &pdev->fill_used_process_color,
3550
56.0k
                                 &psdf_set_fill_color_commands);
3551
56.0k
}