Coverage Report

Created: 2025-06-24 07:01

/src/ghostpdl/devices/vector/gdevpdfg.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2001-2025 Artifex Software, Inc.
2
   All Rights Reserved.
3
4
   This software is provided AS-IS with no warranty, either express or
5
   implied.
6
7
   This software is distributed under license and may not be copied,
8
   modified or distributed except as expressly authorized under the terms
9
   of the license contained in the file LICENSE in this distribution.
10
11
   Refer to licensing information at http://www.artifex.com or contact
12
   Artifex Software, Inc.,  39 Mesa Street, Suite 108A, San Francisco,
13
   CA 94129, USA, for further information.
14
*/
15
16
17
/* Graphics state management for pdfwrite driver */
18
#include "math_.h"
19
#include "string_.h"
20
#include "memory_.h"
21
#include "gx.h"
22
#include "gserrors.h"
23
#include "gsfunc0.h"
24
#include "gsstate.h"
25
#include "gxbitmap.h"   /* for gxhttile.h in gzht.h */
26
#include "gxdht.h"
27
#include "gxfarith.h"   /* for gs_sin/cos_degrees */
28
#include "gxfmap.h"
29
#include "gxht.h"
30
#include "gxgstate.h"
31
#include "gxdcolor.h"
32
#include "gxpcolor.h"
33
#include "gsptype2.h"
34
#include "gzht.h"
35
#include "gdevpdfx.h"
36
#include "gdevpdfg.h"
37
#include "gdevpdfo.h"
38
#include "gscspace.h"
39
#include "gsicc_manage.h"
40
#include "gsicc_cache.h"
41
#include "gsccolor.h"
42
#include "gxcdevn.h"
43
#include "gscie.h"
44
#include "gdevpdtx.h"
45
#include "gdevpdts.h"
46
47
/* ------ Exported by gdevpdfc.c for gdevpdfg.c ------ */
48
int pdf_make_sampled_base_space_function(gx_device_pdf *pdev, gs_function_t **pfn,
49
                                        int nSrcComp, int nDstComp, byte *data);
50
int pdf_delete_sampled_base_space_function(gx_device_pdf *pdev, gs_function_t *pfn);
51
int pdf_make_base_space_function(gx_device_pdf *pdev, gs_function_t **pfn,
52
                                        int ncomp, float *data_low, float *data_high);
53
int pdf_delete_base_space_function(gx_device_pdf *pdev, gs_function_t *pfn);
54
55
/* ---------------- Miscellaneous ---------------- */
56
57
/* Save the viewer's graphic state. */
58
int
59
pdf_save_viewer_state(gx_device_pdf *pdev, stream *s)
60
411k
{
61
411k
    const int i = pdev->vgstack_depth;
62
63
411k
    if (pdev->vgstack_depth >= pdev->vgstack_size) {
64
2
        pdf_viewer_state *new_vgstack = (pdf_viewer_state *)gs_alloc_bytes(pdev->pdf_memory,
65
2
            (pdev->vgstack_size + 5) * sizeof(pdf_viewer_state), "increase graphics state stack size");
66
2
        if (new_vgstack == 0)
67
0
            return_error(gs_error_VMerror);
68
2
        memset(new_vgstack, 0x00, (pdev->vgstack_size + 5) * sizeof(pdf_viewer_state));
69
2
        memcpy(new_vgstack, pdev->vgstack, pdev->vgstack_size * sizeof(pdf_viewer_state));
70
2
        gs_free_object(pdev->pdf_memory, pdev->vgstack, "resize graphics state stack, free old stack)");
71
2
        pdev->vgstack = new_vgstack;
72
2
        pdev->vgstack_size += 5;
73
2
    }
74
75
411k
    pdev->vgstack[i].transfer_ids[0] = pdev->transfer_ids[0];
76
411k
    pdev->vgstack[i].transfer_ids[1] = pdev->transfer_ids[1];
77
411k
    pdev->vgstack[i].transfer_ids[2] = pdev->transfer_ids[2];
78
411k
    pdev->vgstack[i].transfer_ids[3] = pdev->transfer_ids[3];
79
411k
    pdev->vgstack[i].transfer_not_identity = pdev->transfer_not_identity;
80
411k
    pdev->vgstack[i].strokeconstantalpha = pdev->state.strokeconstantalpha;
81
411k
    pdev->vgstack[i].fillconstantalpha = pdev->state.fillconstantalpha;
82
411k
    pdev->vgstack[i].alphaisshape = pdev->state.alphaisshape;
83
411k
    pdev->vgstack[i].blend_mode = pdev->state.blend_mode;
84
411k
    pdev->vgstack[i].halftone_id = pdev->halftone_id;
85
411k
    pdev->vgstack[i].black_generation_id = pdev->black_generation_id;
86
411k
    pdev->vgstack[i].undercolor_removal_id = pdev->undercolor_removal_id;
87
411k
    pdev->vgstack[i].overprint_mode = pdev->state.overprint_mode;
88
411k
    pdev->vgstack[i].smoothness = pdev->state.smoothness;
89
411k
    pdev->vgstack[i].flatness = pdev->state.flatness;
90
411k
    pdev->vgstack[i].text_knockout = pdev->state.text_knockout;
91
411k
    pdev->vgstack[i].fill_overprint = pdev->fill_overprint;
92
411k
    pdev->vgstack[i].stroke_overprint = pdev->stroke_overprint;
93
411k
    pdev->vgstack[i].stroke_adjust = pdev->state.stroke_adjust;
94
411k
    pdev->vgstack[i].fill_used_process_color = pdev->fill_used_process_color;
95
411k
    pdev->vgstack[i].stroke_used_process_color = pdev->stroke_used_process_color;
96
411k
    pdev->vgstack[i].saved_fill_color = pdev->saved_fill_color;
97
411k
    pdev->vgstack[i].saved_stroke_color = pdev->saved_stroke_color;
98
411k
    pdev->vgstack[i].line_params = pdev->state.line_params;
99
411k
    pdev->vgstack[i].line_params.dash.pattern = 0; /* Use pdev->dash_pattern instead. */
100
411k
    pdev->vgstack[i].soft_mask_id = pdev->state.soft_mask_id; /* Use pdev->dash_pattern instead. */
101
411k
    if (pdev->dash_pattern) {
102
14.5k
        if (pdev->vgstack[i].dash_pattern)
103
13.7k
            gs_free_object(pdev->memory->non_gc_memory, pdev->vgstack[i].dash_pattern, "free gstate copy dash");
104
14.5k
        pdev->vgstack[i].dash_pattern = (float *)gs_alloc_bytes(pdev->memory->non_gc_memory, pdev->dash_pattern_size * sizeof(float), "gstate copy dash");
105
14.5k
        if (pdev->vgstack[i].dash_pattern == NULL)
106
0
            return_error(gs_error_VMerror);
107
14.5k
        memcpy(pdev->vgstack[i].dash_pattern, pdev->dash_pattern, pdev->dash_pattern_size * sizeof(float));
108
14.5k
        pdev->vgstack[i].dash_pattern_size = pdev->dash_pattern_size;
109
397k
    } else {
110
397k
        if (pdev->vgstack[i].dash_pattern) {
111
427
            gs_free_object(pdev->memory->non_gc_memory, pdev->vgstack[i].dash_pattern, "free gstate copy dash");
112
427
            pdev->vgstack[i].dash_pattern = 0;
113
427
            pdev->vgstack[i].dash_pattern_size = 0;
114
427
        }
115
397k
    }
116
411k
    pdev->vgstack_depth++;
117
411k
    if (s)
118
274k
        stream_puts(s, "q\n");
119
411k
    return 0;
120
411k
}
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
725k
{
126
725k
    pdev->transfer_ids[0] = s->transfer_ids[0];
127
725k
    pdev->transfer_ids[1] = s->transfer_ids[1];
128
725k
    pdev->transfer_ids[2] = s->transfer_ids[2];
129
725k
    pdev->transfer_ids[3] = s->transfer_ids[3];
130
725k
    pdev->transfer_not_identity = s->transfer_not_identity;
131
725k
    pdev->state.strokeconstantalpha = s->strokeconstantalpha;
132
725k
    pdev->state.fillconstantalpha = s->fillconstantalpha;
133
725k
    pdev->state.alphaisshape = s->alphaisshape;
134
725k
    pdev->state.blend_mode = s->blend_mode;
135
725k
    pdev->halftone_id = s->halftone_id;
136
725k
    pdev->black_generation_id = s->black_generation_id;
137
725k
    pdev->undercolor_removal_id = s->undercolor_removal_id;
138
725k
    pdev->state.overprint_mode = s->overprint_mode;
139
725k
    pdev->state.smoothness = s->smoothness;
140
725k
    pdev->state.flatness = s->flatness;
141
725k
    pdev->state.text_knockout = s->text_knockout;
142
725k
    pdev->fill_overprint = s->fill_overprint;
143
725k
    pdev->stroke_overprint = s->stroke_overprint;
144
725k
    pdev->state.stroke_adjust = s->stroke_adjust;
145
725k
    pdev->fill_used_process_color = s->fill_used_process_color;
146
725k
    pdev->stroke_used_process_color = s->stroke_used_process_color;
147
725k
    pdev->saved_fill_color = s->saved_fill_color;
148
725k
    pdev->saved_stroke_color = s->saved_stroke_color;
149
725k
    pdev->state.line_params = s->line_params;
150
725k
    pdev->state.soft_mask_id = s->soft_mask_id;
151
725k
    if (s->dash_pattern) {
152
14.5k
        if (pdev->dash_pattern)
153
14.4k
            gs_free_object(pdev->memory->stable_memory, pdev->dash_pattern, "vector free dash pattern");
154
14.5k
        pdev->dash_pattern = (float *)gs_alloc_bytes(pdev->memory->stable_memory, s->dash_pattern_size * sizeof(float), "vector allocate dash pattern");
155
14.5k
        if (pdev->dash_pattern == NULL)
156
0
            return_error(gs_error_VMerror);
157
14.5k
        memcpy(pdev->dash_pattern, s->dash_pattern, sizeof(float)*s->dash_pattern_size);
158
14.5k
        pdev->dash_pattern_size  = s->dash_pattern_size;
159
710k
    } else {
160
710k
        if (pdev->dash_pattern) {
161
2.22k
            gs_free_object(pdev->memory->stable_memory, pdev->dash_pattern, "vector free dash pattern");
162
2.22k
            pdev->dash_pattern = 0;
163
2.22k
            pdev->dash_pattern_size = 0;
164
2.22k
        }
165
710k
    }
166
725k
    return 0;
167
725k
}
168
169
/* Restore the viewer's graphic state. */
170
int
171
pdf_restore_viewer_state(gx_device_pdf *pdev, stream *s)
172
411k
{
173
411k
    const int i = --pdev->vgstack_depth;
174
175
411k
    if (i < pdev->vgstack_bottom || i < 0) {
176
1
        if ((pdev->ObjectFilter & FILTERIMAGE) == 0)
177
1
            return_error(gs_error_unregistered); /* Must not happen. */
178
0
        else
179
0
            return 0;
180
1
    }
181
411k
    if (s)
182
274k
        stream_puts(s, "Q\n");
183
411k
    return pdf_load_viewer_state(pdev, pdev->vgstack + i);
184
411k
}
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
68.0k
{
192
68.0k
    gx_device_color black;
193
194
68.0k
    pdev->black = gx_device_black((gx_device *)pdev);
195
68.0k
    pdev->white = gx_device_white((gx_device *)pdev);
196
68.0k
    set_nonclient_dev_color(&black, pdev->black);
197
68.0k
    gx_hld_save_color(NULL, &black, saved_fill_color);
198
68.0k
    gx_hld_save_color(NULL, &black, saved_stroke_color);
199
68.0k
    *fill_used_process_color = true;
200
68.0k
    *stroke_used_process_color = true;
201
68.0k
}
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
132k
{
207
132k
    pvs->transfer_not_identity =
208
132k
            (pgs->set_transfer.red   != NULL ? pgs->set_transfer.red->proc   != gs_identity_transfer : 0) * 1 +
209
132k
            (pgs->set_transfer.green != NULL ? pgs->set_transfer.green->proc != gs_identity_transfer : 0) * 2 +
210
132k
            (pgs->set_transfer.blue  != NULL ? pgs->set_transfer.blue->proc  != gs_identity_transfer : 0) * 4 +
211
132k
            (pgs->set_transfer.gray  != NULL ? pgs->set_transfer.gray->proc  != gs_identity_transfer : 0) * 8;
212
132k
    pvs->transfer_ids[0] = (pgs->set_transfer.red != NULL ? pgs->set_transfer.red->id : 0);
213
132k
    pvs->transfer_ids[1] = (pgs->set_transfer.green != NULL ? pgs->set_transfer.green->id : 0);
214
132k
    pvs->transfer_ids[2] = (pgs->set_transfer.blue != NULL ? pgs->set_transfer.blue->id : 0);
215
132k
    pvs->transfer_ids[3] = (pgs->set_transfer.gray != NULL ? pgs->set_transfer.gray->id : 0);
216
132k
    pvs->fillconstantalpha = pgs->fillconstantalpha;
217
132k
    pvs->strokeconstantalpha = pgs->strokeconstantalpha;
218
132k
    pvs->alphaisshape = pgs->alphaisshape;
219
132k
    pvs->blend_mode = pgs->blend_mode;
220
132k
    pvs->halftone_id = (pgs->dev_ht[HT_OBJTYPE_DEFAULT] != NULL ? pgs->dev_ht[HT_OBJTYPE_DEFAULT]->id : 0);
221
132k
    pvs->black_generation_id = (pgs->black_generation != NULL ? pgs->black_generation->id : 0);
222
132k
    pvs->undercolor_removal_id = (pgs->undercolor_removal != NULL ? pgs->undercolor_removal->id : 0);
223
132k
    pvs->overprint_mode = 0;
224
132k
    pvs->flatness = pgs->flatness;
225
132k
    pvs->smoothness = pgs->smoothness;
226
132k
    pvs->text_knockout = pgs->text_knockout;
227
132k
    pvs->fill_overprint = false;
228
132k
    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
132k
    pvs->stroke_adjust = -1;
237
132k
    pvs->line_params.half_width = 0.5;
238
132k
    pvs->line_params.start_cap = 0;
239
132k
    pvs->line_params.end_cap = 0;
240
132k
    pvs->line_params.dash_cap = 0;
241
132k
    pvs->line_params.join = 0;
242
132k
    pvs->line_params.curve_join = 0;
243
132k
    pvs->line_params.miter_limit = 10.0;
244
132k
    pvs->line_params.miter_check = 0;
245
132k
    pvs->line_params.dot_length = pgs->line_params.dot_length;
246
132k
    pvs->line_params.dot_length_absolute = pgs->line_params.dot_length_absolute;
247
132k
    pvs->line_params.dot_orientation = pgs->line_params.dot_orientation;
248
132k
    memset(&pvs->line_params.dash, 0 , sizeof(pvs->line_params.dash));
249
132k
    pvs->dash_pattern = 0;
250
132k
    pvs->dash_pattern_size = 0;
251
132k
    pvs->soft_mask_id = pgs->soft_mask_id;
252
132k
}
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
98.7k
{
259
98.7k
    pdf_viewer_state vs;
260
261
98.7k
    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
98.7k
    gx_hld_save_color(pgs, pdevc, &vs.saved_fill_color);
265
98.7k
    gx_hld_save_color(pgs, pdevc, &vs.saved_stroke_color);
266
98.7k
    vs.fill_used_process_color = 0;
267
98.7k
    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
98.7k
    (void)pdf_load_viewer_state(pdev, &vs);
271
98.7k
}
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
34.0k
{
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
34.0k
    pdf_set_initial_color(pdev, &pdev->vg_initial.saved_fill_color, &pdev->vg_initial.saved_stroke_color,
285
34.0k
            &pdev->vg_initial.fill_used_process_color, &pdev->vg_initial.stroke_used_process_color);
286
34.0k
    pdf_viewer_state_from_gs_gstate_aux(&pdev->vg_initial, pgs);
287
34.0k
    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
34.0k
}
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
34.0k
{
300
301
34.0k
    pdf_set_initial_color(pdev, &pdev->saved_fill_color, &pdev->saved_stroke_color,
302
34.0k
                                &pdev->fill_used_process_color, &pdev->stroke_used_process_color);
303
34.0k
    pdev->state.flatness = -1;
304
34.0k
    {
305
34.0k
        static const gx_line_params lp_initial = {
306
34.0k
            gx_line_params_initial
307
34.0k
        };
308
309
34.0k
        pdev->state.line_params = lp_initial;
310
34.0k
    }
311
34.0k
    pdev->fill_overprint = false;
312
34.0k
    pdev->stroke_overprint = false;
313
34.0k
    pdev->remap_fill_color = false;
314
34.0k
    pdev->remap_stroke_color = false;
315
34.0k
    pdf_reset_text(pdev);
316
34.0k
}
317
318
/* Reset the graphics state parameters to initial values. */
319
void
320
pdf_reset_graphics(gx_device_pdf * pdev)
321
248k
{
322
248k
    int soft_mask_id = pdev->state.soft_mask_id;
323
324
248k
    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
214k
        (void)pdf_load_viewer_state(pdev, &pdev->vg_initial);
328
34.0k
    else
329
34.0k
        pdf_reset_graphics_old(pdev);
330
248k
    pdf_reset_text(pdev);
331
332
    /* Not obvious, we want to preserve any extant soft mask, not reset it */
333
248k
    pdev->state.soft_mask_id = soft_mask_id;
334
248k
}
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
828k
{
341
828k
    int i, n = gx_hld_get_number_color_components(pgs);
342
343
828k
    pprintg1(pdev->strm, "%g", psdf_round(pcc->paint.values[0], 255, 8));
344
1.97M
    for (i = 1; i < n; i++) {
345
1.14M
        pprintg1(pdev->strm, " %g", psdf_round(pcc->paint.values[i], 255, 8));
346
1.14M
    }
347
828k
    return 0;
348
828k
}
349
350
static inline bool
351
is_cspace_allowed_in_strategy(gx_device_pdf * pdev, gs_color_space_index csi)
352
8.76k
{
353
8.76k
    if (pdev->params.ColorConversionStrategy == ccs_CMYK &&
354
8.76k
            csi != gs_color_space_index_DeviceCMYK &&
355
8.76k
            csi != gs_color_space_index_DeviceGray)
356
0
        return false;
357
8.76k
    if (pdev->params.ColorConversionStrategy == ccs_sRGB &&
358
8.76k
            csi != gs_color_space_index_DeviceRGB &&
359
8.76k
            csi != gs_color_space_index_DeviceGray)
360
0
        return false;
361
8.76k
    if (pdev->params.ColorConversionStrategy == ccs_RGB &&
362
8.76k
            csi != gs_color_space_index_DeviceRGB &&
363
8.76k
            csi != gs_color_space_index_DeviceGray)
364
0
        return false;
365
8.76k
    if (pdev->params.ColorConversionStrategy == ccs_Gray &&
366
8.76k
            csi != gs_color_space_index_DeviceGray)
367
0
        return false;
368
8.76k
    return true;
369
8.76k
}
370
371
static inline bool
372
is_pattern2_allowed_in_strategy(gx_device_pdf * pdev, const gx_drawing_color *pdc)
373
8.76k
{
374
8.76k
    const gs_color_space *pcs2 = gx_dc_pattern2_get_color_space(pdc);
375
8.76k
    gs_color_space_index csi = gs_color_space_get_index(pcs2);
376
377
8.76k
    if (csi == gs_color_space_index_ICC)
378
631
        csi = gsicc_get_default_type(pcs2->cmm_icc_profile_data);
379
380
8.76k
    return is_cspace_allowed_in_strategy(pdev, csi);
381
8.76k
}
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
0
{
408
0
    unsigned short psrc[GS_CLIENT_COLOR_MAX_COMPONENTS];
409
0
    frac conc[GS_CLIENT_COLOR_MAX_COMPONENTS];
410
0
    gx_device_color dc;
411
0
    const gs_color_space *pcs = gs_currentcolorspace_inline(pgs);
412
0
    int code, i, color_index;
413
414
0
    color_index = pdev->pcm_color_info_index;
415
0
    pdf_set_process_color_model(pdev, 1);
416
0
    for (i=0;i<3;i++) {
417
0
        psrc[i] = (unsigned short) (pcc->paint.values[i]*65535.0);;
418
0
        conc[i] = ushort2frac(psrc[i]);
419
0
    }
420
0
    code = gx_remap_concrete_DRGB(pcs, (const frac *)&conc, &dc, pgs, (gx_device *)pdev, gs_color_select_texture, NULL);
421
0
    if (code < 0)
422
0
        return code;
423
424
0
    cc->paint.values[0] = ((dc.colors.pure & 0xff0000) >> 16) / 255.0;
425
0
    cc->paint.values[1] = ((dc.colors.pure & 0xff00) >> 8) / 255.0;
426
0
    cc->paint.values[2] = (dc.colors.pure & 0xff) / 255.0;
427
0
    pdf_set_process_color_model(pdev, color_index);
428
0
    return 0;
429
0
}
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
101k
{
461
101k
    int code, i;
462
101k
    unsigned char j;
463
101k
    frac conc[GS_CLIENT_COLOR_MAX_COMPONENTS];
464
101k
    gs_color_space_index csi, csi2;
465
101k
    gs_color_space *pcs2 = (gs_color_space *)pcs;
466
101k
    gx_drawing_color dc;
467
101k
    int num_des_comps;
468
101k
    cmm_dev_profile_t *dev_profile;
469
470
101k
    dc.type = gx_dc_type_pure;
471
101k
    dc.colors.pure = 0;
472
101k
    csi = gs_color_space_get_index(pcs);
473
474
101k
    if (csi == gs_color_space_index_ICC) {
475
101k
        csi = gsicc_get_default_type(pcs->cmm_icc_profile_data);
476
101k
    }
477
478
101k
    if (csi == gs_color_space_index_Indexed ||
479
101k
        csi == gs_color_space_index_DeviceN ||
480
101k
        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
101k
    } else {
537
101k
        if (csi >= gs_color_space_index_CIEDEFG &&
538
101k
            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
101k
        } else {
551
101k
            memset (&conc, 0x00, sizeof(frac) * GS_CLIENT_COLOR_MAX_COMPONENTS);
552
            /* Special case handling for Lab spaces */
553
101k
            if (pcs->cmm_icc_profile_data->data_cs == gsCIELAB || pcs->cmm_icc_profile_data->islab) {
554
192
                gs_client_color cc;
555
                /* Get the data in a form that is concrete for the CMM */
556
192
                cc.paint.values[0] = pcc->paint.values[0] / 100.0;
557
192
                cc.paint.values[1] = (pcc->paint.values[1]+128)/255.0;
558
192
                cc.paint.values[2] = (pcc->paint.values[2]+128)/255.0;
559
192
                pcs->type->concretize_color((const gs_client_color *)&cc, pcs, conc, pgs, (gx_device *)pdev);
560
101k
            } else {
561
101k
                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
101k
                } else {
576
101k
                    pcs->type->concretize_color(pcc, pcs, conc, pgs, (gx_device *)pdev);
577
101k
                }
578
101k
            }
579
101k
            code = dev_proc((gx_device *)pdev, get_profile)((gx_device *)pdev, &dev_profile);
580
101k
            if (code < 0)
581
0
                return code;
582
101k
            num_des_comps = gsicc_get_device_profile_comps(dev_profile);
583
407k
            for (i = 0;i < num_des_comps;i++)
584
305k
                dc.colors.pure = (dc.colors.pure << 8) + (int)(frac2float(conc[i]) * 255);
585
101k
            code = psdf_set_color((gx_device_vector *)pdev, &dc, ppscc);
586
101k
            return code;
587
101k
        }
588
101k
    }
589
101k
    return_error(gs_error_unknownerror);
590
101k
}
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
828k
{
598
828k
    gs_color_space_index csi, csi2;
599
828k
    int code, i;
600
828k
    const char *command = NULL;
601
828k
    gs_range_t *ranges = 0;
602
828k
    gs_client_color cc;
603
604
605
828k
    csi = csi2 = gs_color_space_get_index(pcs);
606
828k
    if (csi == gs_color_space_index_ICC) {
607
802k
        csi2 = gsicc_get_default_type(pcs->cmm_icc_profile_data);
608
802k
    }
609
610
828k
    switch (csi2) {
611
266k
        case gs_color_space_index_DeviceGray:
612
266k
            command = ppscc->setgray;
613
266k
            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
266k
            } else {
618
266k
                cc.paint.values[0] = pcc->paint.values[0];
619
266k
            }
620
266k
            code = pdf_write_ccolor(pdev, pgs, &cc);
621
266k
            if (code < 0)
622
0
                return code;
623
266k
            pprints1(pdev->strm, " %s\n", command);
624
266k
            break;
625
450k
        case gs_color_space_index_DeviceRGB:
626
450k
            command = ppscc->setrgbcolor;
627
450k
            if (pdev->params.TransferFunctionInfo == tfi_Apply) {
628
0
                code = apply_transfer_rgb(pdev, pgs, pcc, &cc);
629
0
                if (code < 0)
630
0
                    return_error(code);
631
450k
            } else {
632
1.80M
                for (i=0;i< 3;i++)
633
1.35M
                    cc.paint.values[i] = pcc->paint.values[i];
634
450k
            }
635
450k
            code = pdf_write_ccolor(pdev, pgs, &cc);
636
450k
            if (code < 0)
637
0
                return code;
638
450k
            pprints1(pdev->strm, " %s\n", command);
639
450k
            break;
640
74.3k
        case gs_color_space_index_DeviceCMYK:
641
74.3k
            command = ppscc->setcmykcolor;
642
74.3k
            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
74.3k
            } else {
647
371k
                for (i=0;i< 4;i++)
648
297k
                    cc.paint.values[i] = pcc->paint.values[i];
649
74.3k
            }
650
74.3k
            code = pdf_write_ccolor(pdev, pgs, &cc);
651
74.3k
            if (code < 0)
652
0
                return code;
653
74.3k
            pprints1(pdev->strm, " %s\n", command);
654
74.3k
            break;
655
36.9k
        default:
656
36.9k
            if (!gx_hld_saved_color_same_cspace(current, psc) || (csi2 >= gs_color_space_index_CIEDEFG && csi2 <= gs_color_space_index_CIEA)) {
657
26.0k
                cos_value_t cs_value;
658
659
26.0k
                code = pdf_color_space_named(pdev, pgs, &cs_value, (const gs_range_t **)&ranges, pcs,
660
26.0k
                                &pdf_color_space_names, true, NULL, 0, false);
661
                /* fixme : creates redundant PDF objects. */
662
26.0k
                if (code == gs_error_rangecheck) {
663
54
                    *used_process_color = true;
664
54
                    if (pdev->ForOPDFRead) {
665
                    /* The color space can't write to PDF. This should never happen */
666
54
                    code = psdf_set_color((gx_device_vector *)pdev, pdc, ppscc);
667
54
                    } else {
668
0
                    code = write_color_as_process(pdev, pgs, pcs, pdc, used_process_color, ppscc, pcc);
669
0
                    }
670
54
                    return code;
671
54
                }
672
26.0k
                if (code < 0)
673
0
                    return code;
674
26.0k
                code = cos_value_write(&cs_value, pdev);
675
26.0k
                if (code < 0)
676
0
                    return code;
677
26.0k
                pprints1(pdev->strm, " %s\n", ppscc->setcolorspace);
678
26.0k
                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
26.0k
                } else {
699
26.0k
                    code = pdf_write_ccolor(pdev, pgs, pcc);
700
26.0k
                }
701
26.0k
                *used_process_color = false;
702
26.0k
                if (code < 0)
703
0
                    return code;
704
26.0k
                pprints1(pdev->strm, " %s\n", ppscc->setcolorn);
705
26.0k
            } else if (*used_process_color) {
706
18
                    *used_process_color = true;
707
18
                    if (pdev->ForOPDFRead) {
708
                    /* The color space can't write to PDF. This should never happen */
709
18
                    code = psdf_set_color((gx_device_vector *)pdev, pdc, ppscc);
710
18
                    } else {
711
0
                    code = write_color_as_process(pdev, pgs, pcs, pdc, used_process_color, ppscc, pcc);
712
0
                    }
713
18
                    return code;
714
18
            }
715
10.8k
            else {
716
10.8k
                code = pdf_write_ccolor(pdev, pgs, pcc);
717
10.8k
                if (code < 0)
718
0
                    return code;
719
10.8k
                pprints1(pdev->strm, " %s\n", ppscc->setcolorn);
720
10.8k
            }
721
36.8k
            break;
722
828k
    }
723
828k
    *used_process_color = false;
724
725
828k
    return 0;
726
828k
}
727
728
static int write_color_as_process_ICC(gx_device_pdf * pdev, const gs_gstate * pgs, const gs_color_space *pcs,
729
                        const gx_drawing_color *pdc, gx_hl_saved_color * psc, bool *used_process_color,
730
                        const psdf_set_color_commands_t *ppscc, gs_client_color *pcc,
731
                        gx_hl_saved_color *current)
732
0
{
733
0
    int i, code;
734
0
    cos_value_t cs_value;
735
736
0
    if (!gx_hld_saved_color_same_cspace(current, psc)) {
737
0
        code = pdf_color_space_named(pdev, pgs, &cs_value, NULL, pcs,
738
0
                        &pdf_color_space_names, true, NULL, 0, true);
739
        /* fixme : creates redundant PDF objects. */
740
0
        if (code == gs_error_rangecheck) {
741
            /* The color space can't write to PDF. This should never happen */
742
0
            return write_color_as_process(pdev, pgs, pcs, pdc, used_process_color, ppscc, pcc);
743
0
        }
744
0
        if (code < 0)
745
0
            return code;
746
0
        code = cos_value_write(&cs_value, pdev);
747
0
        if (code < 0)
748
0
            return code;
749
0
        pprints1(pdev->strm, " %s\n", ppscc->setcolorspace);
750
0
        *used_process_color = false;
751
0
        pprintg1(pdev->strm, "%g", psdf_round(pcc->paint.values[0], 255, 8));
752
0
        for (i = 1; i < pcs->type->num_components(pcs); i++) {
753
0
            pprintg1(pdev->strm, " %g", psdf_round(pcc->paint.values[i], 255, 8));
754
0
        }
755
0
        pprints1(pdev->strm, " %s\n", ppscc->setcolorn);
756
0
    } else {
757
0
        *used_process_color = false;
758
0
        pprintg1(pdev->strm, "%g", psdf_round(pcc->paint.values[0], 255, 8));
759
0
        for (i = 1; i < pcs->type->num_components(pcs); i++) {
760
0
            pprintg1(pdev->strm, " %g", psdf_round(pcc->paint.values[i], 255, 8));
761
0
        }
762
0
        pprints1(pdev->strm, " %s\n", ppscc->setcolorn);
763
0
    }
764
0
    return 0;
765
0
}
766
767
int convert_DeviceN_alternate(gx_device_pdf * pdev, const gs_gstate * pgs, const gs_color_space *pcs,
768
                        const gx_drawing_color *pdc, bool *used_process_color,
769
                        const psdf_set_color_commands_t *ppscc, gs_client_color *pcc, cos_value_t *pvalue, bool by_name)
770
0
{
771
0
    gs_color_space_index csi;
772
0
    gs_function_t *new_pfn = 0;
773
0
    int code, i, samples=0, loop;
774
0
    cos_array_t *pca, *pca1;
775
0
    cos_value_t v;
776
0
    byte *data_buff;
777
0
    pdf_resource_t *pres = NULL;
778
0
    gs_color_space *pcs_save = NULL;
779
780
0
    csi = gs_color_space_get_index(pcs);
781
0
    if (csi == gs_color_space_index_Indexed) {
782
0
        pcs_save = (gs_color_space *)pcs;
783
0
        pcs = pcs->base_space;
784
0
    }
785
786
0
    pca = cos_array_alloc(pdev, "pdf_color_space");
787
0
    if (pca == 0)
788
0
        return_error(gs_error_VMerror);
789
790
0
    samples = (unsigned int)pow(2, pcs->params.device_n.num_components);
791
0
    data_buff = gs_alloc_bytes(pdev->memory, (unsigned int)pdev->color_info.num_components * samples, "Convert DeviceN");
792
0
    if (data_buff == 0) {
793
0
        COS_FREE(pca, "convert DeviceN");
794
0
        return_error(gs_error_VMerror);
795
0
    }
796
0
    memset(data_buff, 0x00, (unsigned int)pdev->color_info.num_components * samples);
797
798
0
    {
799
0
        frac conc[GS_CLIENT_COLOR_MAX_COMPONENTS];
800
0
        gs_client_color cc, cc1;
801
0
        unsigned char j;
802
0
        gs_color_space *icc_space = (gs_color_space *)pcs;
803
0
        gs_color_space *devicen_space = (gs_color_space *)pcs;
804
0
        gs_color_space_index csi2;
805
806
0
        csi = gs_color_space_get_index(pcs);
807
0
        if (csi == gs_color_space_index_Indexed)
808
0
            devicen_space = pcs->base_space;
809
810
0
        do{
811
0
            icc_space = icc_space->base_space;
812
0
            csi2 = gs_color_space_get_index(icc_space);
813
0
        } while(csi2 != gs_color_space_index_ICC && icc_space->base_space);
814
815
0
        memset(&cc.paint.values, 0x00, GS_CLIENT_COLOR_MAX_COMPONENTS);
816
817
0
        devicen_space->params.device_n.use_alt_cspace = true;
818
819
0
        for (loop=0;loop < samples;loop++) {
820
0
            if (loop > 0) {
821
0
                if (cc.paint.values[0] == 0)
822
0
                    cc.paint.values[0] = 1;
823
0
                else {
824
0
                    int cascade = 0;
825
0
                    while (cc.paint.values[cascade] == 1 && cascade < samples) {
826
0
                        cc.paint.values[cascade++] = 0;
827
0
                    }
828
0
                    cc.paint.values[cascade] = 1;
829
0
                }
830
0
            }
831
832
833
0
            memset (&conc, 0x00, sizeof(frac) * GS_CLIENT_COLOR_MAX_COMPONENTS);
834
0
            devicen_space->type->concretize_color(&cc, devicen_space, conc, pgs, (gx_device *)pdev);
835
836
0
            for (i = 0;i < pdev->color_info.num_components;i++)
837
0
                cc1.paint.values[i] = frac2float(conc[i]);
838
839
0
            if (pdev->params.TransferFunctionInfo == tfi_Apply) {
840
0
                switch (pdev->params.ColorConversionStrategy) {
841
0
                    case ccs_Gray:
842
0
                        code = apply_transfer_gray(pdev, pgs, &cc1, &cc1);
843
0
                        break;
844
0
                    case ccs_sRGB:
845
0
                    case ccs_RGB:
846
0
                        code = apply_transfer_rgb(pdev, pgs, &cc1, &cc1);
847
0
                        break;
848
0
                    case ccs_CMYK:
849
0
                        code = apply_transfer_cmyk(pdev, pgs, &cc1, &cc1);
850
0
                        break;
851
0
                    default:
852
0
                        code = gs_error_rangecheck;
853
0
                        break;
854
0
                }
855
0
                if (code < 0) {
856
0
                    COS_FREE(pca, "pdf_color_space");
857
0
                    return code;
858
0
                }
859
0
            }
860
0
            for (j = 0;j < pdev->color_info.num_components;j++)
861
0
                data_buff[(loop * pdev->color_info.num_components) + j] = (int)(cc1.paint.values[j] * 255);
862
0
        }
863
0
    }
864
865
0
    switch(pdev->params.ColorConversionStrategy) {
866
0
        case ccs_Gray:
867
0
            code = pdf_make_sampled_base_space_function(pdev, &new_pfn, pcs->params.device_n.num_components, 1, data_buff);
868
0
            break;
869
0
        case ccs_sRGB:
870
0
        case ccs_RGB:
871
0
            code = pdf_make_sampled_base_space_function(pdev, &new_pfn, pcs->params.device_n.num_components, 3, data_buff);
872
0
            break;
873
0
        case ccs_CMYK:
874
0
            code = pdf_make_sampled_base_space_function(pdev, &new_pfn, pcs->params.device_n.num_components, 4, data_buff);
875
0
            break;
876
0
        default:
877
0
            code = gs_error_rangecheck;
878
0
            break;
879
0
    }
880
0
    gs_free_object(pdev->memory, data_buff, "Convert DeviceN");
881
0
    if (code < 0) {
882
0
        COS_FREE(pca, "convert DeviceN");
883
0
        return code;
884
0
    }
885
886
0
    code = cos_array_add(pca, cos_c_string_value(&v, "/DeviceN"));
887
0
    if (code < 0) {
888
0
        COS_FREE(pca, "pdf_color_space");
889
0
        return code;
890
0
    }
891
892
0
    if (code >= 0) {
893
0
        byte *name_string;
894
0
        uint name_string_length;
895
0
        cos_value_t v_attriburtes, *va = NULL;
896
0
        cos_array_t *psna =
897
0
                cos_array_alloc(pdev, "pdf_color_space(DeviceN)");
898
899
0
        if (psna == 0) {
900
0
            COS_FREE(pca, "convert DeviceN");
901
0
            return_error(gs_error_VMerror);
902
0
        }
903
904
0
        for (i = 0; i < pcs->params.device_n.num_components; ++i) {
905
0
            name_string = (byte *)pcs->params.device_n.names[i];
906
0
            name_string_length = strlen(pcs->params.device_n.names[i]);
907
0
            code = pdf_string_to_cos_name(pdev, name_string,
908
0
                              name_string_length, &v);
909
0
            if (code < 0) {
910
0
                COS_FREE(pca, "convert DeviceN");
911
0
                return code;
912
0
            }
913
0
            code = cos_array_add(psna, &v);
914
0
            if (code < 0) {
915
0
                COS_FREE(pca, "convert DeviceN");
916
0
                return code;
917
0
            }
918
0
        }
919
0
        COS_OBJECT_VALUE(&v, psna);
920
0
        code = cos_array_add(pca, &v);
921
0
        if (code <0) {
922
0
            COS_FREE(pca, "convert DeviceN");
923
0
            return_error(gs_error_VMerror);
924
0
        }
925
926
0
        switch(pdev->params.ColorConversionStrategy) {
927
0
            case ccs_Gray:
928
0
                cos_c_string_value(&v, (const char *)pdf_color_space_names.DeviceGray);
929
0
                break;
930
0
            case ccs_sRGB:
931
0
            case ccs_RGB:
932
0
                cos_c_string_value(&v, (const char *)pdf_color_space_names.DeviceRGB);
933
0
                break;
934
0
            case ccs_CMYK:
935
0
                cos_c_string_value(&v, (const char *)pdf_color_space_names.DeviceCMYK);
936
0
                break;
937
0
            default:
938
0
                break;
939
0
        }
940
0
        code = cos_array_add(pca, &v);
941
0
        if (code >= 0) {
942
0
            code = pdf_function_scaled(pdev, new_pfn, 0x00, &v);
943
0
            if (code >= 0)
944
0
                code = cos_array_add(pca, &v);
945
0
            else {
946
0
                COS_FREE(pca, "convert DeviceN");
947
0
                return code;
948
0
            }
949
0
        }
950
951
0
        if (pcs->params.device_n.colorants != NULL) {
952
0
            cos_dict_t *colorants  = cos_dict_alloc(pdev, "pdf_color_space(DeviceN)");
953
0
            cos_value_t v_colorants, v_separation, v_colorant_name;
954
0
            const gs_device_n_colorant *csa;
955
0
            pdf_resource_t *pres_attributes;
956
957
0
            if (colorants == NULL)
958
0
                return_error(gs_error_VMerror);
959
0
            code = pdf_alloc_resource(pdev, resourceOther, 0, &pres_attributes, -1);
960
0
            if (code < 0) {
961
0
                COS_FREE(pca, "convert DeviceN");
962
0
                return code;
963
0
            }
964
0
            cos_become(pres_attributes->object, cos_type_dict);
965
0
            COS_OBJECT_VALUE(&v_colorants, colorants);
966
0
            code = cos_dict_put((cos_dict_t *)pres_attributes->object,
967
0
                (const byte *)"/Colorants", 10, &v_colorants);
968
0
            if (code < 0){
969
0
                COS_FREE(pca, "convert DeviceN");
970
0
                return code;
971
0
            }
972
0
            for (csa = pcs->params.device_n.colorants; csa != NULL; csa = csa->next) {
973
0
                name_string = (byte *)csa->colorant_name;
974
0
                name_string_length = strlen((const char *)name_string);
975
0
                code = pdf_color_space_named(pdev, pgs, &v_separation, NULL, csa->cspace, &pdf_color_space_names, false, NULL, 0, false);
976
0
                if (code < 0) {
977
0
                    COS_FREE(pca, "convert DeviceN");
978
0
                    return code;
979
0
                }
980
0
                code = pdf_string_to_cos_name(pdev, name_string, name_string_length, &v_colorant_name);
981
0
                if (code < 0) {
982
0
                    COS_FREE(pca, "convert DeviceN");
983
0
                    return code;
984
0
                }
985
0
                code = cos_dict_put(colorants, v_colorant_name.contents.chars.data,
986
0
                                    v_colorant_name.contents.chars.size, &v_separation);
987
0
                if (code < 0) {
988
0
                    COS_FREE(pca, "convert DeviceN");
989
0
                    return code;
990
0
                }
991
0
            }
992
0
            code = pdf_string_to_cos_name(pdev, (byte *)"DeviceN",
993
0
                              7, &v);
994
0
            if (code < 0) {
995
0
                COS_FREE(pca, "convert DeviceN");
996
0
                return code;
997
0
            }
998
999
0
            code = cos_dict_put((cos_dict_t *)pres_attributes->object,
1000
0
                (const byte *)"/Subtype", 8, &v);
1001
0
            if (code < 0) {
1002
0
                COS_FREE(pca, "convert DeviceN");
1003
0
                return code;
1004
0
            }
1005
1006
0
            code = pdf_substitute_resource(pdev, &pres_attributes, resourceOther, NULL, true);
1007
0
            if (code < 0) {
1008
0
                COS_FREE(pca, "convert DeviceN");
1009
0
                return code;
1010
0
            }
1011
0
            pres_attributes->where_used |= pdev->used_mask;
1012
0
            va = &v_attriburtes;
1013
0
            COS_OBJECT_VALUE(va, pres_attributes->object);
1014
0
            code = cos_array_add(pca, va);
1015
0
            if (code < 0) {
1016
0
                COS_FREE(pca, "convert DeviceN");
1017
0
                return code;
1018
0
            }
1019
0
        }
1020
1021
0
    }
1022
0
    pdf_delete_sampled_base_space_function(pdev, new_pfn);
1023
1024
    /*
1025
     * Register the color space as a resource, since it must be referenced
1026
     * by name rather than directly.
1027
     */
1028
0
    {
1029
0
        pdf_color_space_t *ppcs;
1030
1031
0
        if (code < 0 ||
1032
0
            (code = pdf_alloc_resource(pdev, resourceColorSpace, pcs->id,
1033
0
                                       &pres, -1)) < 0
1034
0
            ) {
1035
0
            COS_FREE(pca, "pdf_color_space");
1036
0
            return code;
1037
0
        }
1038
0
        pdf_reserve_object_id(pdev, pres, 0);
1039
0
        ppcs = (pdf_color_space_t *)pres;
1040
0
        ppcs->serialized = NULL;
1041
0
        ppcs->serialized_size = 0;
1042
1043
0
        ppcs->ranges = 0;
1044
0
        pca->id = pres->object->id;
1045
0
        COS_FREE(pres->object, "pdf_color_space");
1046
0
        pres->object = (cos_object_t *)pca;
1047
0
        cos_write_object(COS_OBJECT(pca), pdev, resourceColorSpace);
1048
0
        if (pcs_save == NULL && ppscc != NULL)
1049
0
            pprints1(pdev->strm, "/%s", ppcs->rname);
1050
0
    }
1051
0
    pres->where_used |= pdev->used_mask;
1052
0
    code = pdf_add_resource(pdev, pdev->substream_Resources, "/ColorSpace", pres);
1053
0
    if (code < 0)
1054
0
        return code;
1055
1056
0
    if (pcs_save != NULL) {
1057
0
        cos_value_t value;
1058
1059
0
        pcs = pcs_save;
1060
0
        discard(COS_OBJECT_VALUE(&value, pca));
1061
0
        pca1 = cos_array_alloc(pdev, "pdf_color_space");
1062
0
        if (pca1 == NULL)
1063
0
            return_error(gs_error_VMerror);
1064
1065
0
        code = pdf_indexed_color_space(pdev, pgs, &value, pcs, pca1, (cos_value_t *)&value);
1066
0
        pca = pca1;
1067
1068
        /*
1069
         * Register the color space as a resource, since it must be referenced
1070
         * by name rather than directly.
1071
         */
1072
0
        {
1073
0
            pdf_color_space_t *ppcs;
1074
1075
0
            if (code < 0 ||
1076
0
                (code = pdf_alloc_resource(pdev, resourceColorSpace, pcs->id,
1077
0
                                           &pres, -1)) < 0
1078
0
                ) {
1079
0
                COS_FREE(pca, "pdf_color_space");
1080
0
                return code;
1081
0
            }
1082
0
            pdf_reserve_object_id(pdev, pres, 0);
1083
0
            ppcs = (pdf_color_space_t *)pres;
1084
0
            ppcs->serialized = NULL;
1085
0
            ppcs->serialized_size = 0;
1086
1087
0
            ppcs->ranges = 0;
1088
0
            pca->id = pres->object->id;
1089
0
            COS_FREE(pres->object, "pdf_color_space");
1090
0
            pres->object = (cos_object_t *)pca;
1091
0
            cos_write_object(COS_OBJECT(pca), pdev, resourceColorSpace);
1092
0
            if (ppscc != NULL)
1093
0
                pprints1(pdev->strm, "/%s", ppcs->rname);
1094
0
        }
1095
0
        pres->where_used |= pdev->used_mask;
1096
0
        code = pdf_add_resource(pdev, pdev->substream_Resources, "/ColorSpace", pres);
1097
0
        if (code < 0)
1098
0
            return code;
1099
0
    }
1100
1101
0
    if (ppscc != NULL) {
1102
0
        pprints1(pdev->strm, " %s\n", ppscc->setcolorspace);
1103
0
        *used_process_color = false;
1104
0
        if (pcs_save == NULL) {
1105
0
            for (i = 0; i < pcs->params.device_n.num_components; ++i)
1106
0
                pprintg1(pdev->strm, "%g ", psdf_round(pcc->paint.values[i], 255, 8));
1107
0
        } else
1108
0
            pprintg1(pdev->strm, "%g ", psdf_round(pcc->paint.values[0], 255, 8));
1109
0
        pprints1(pdev->strm, "%s\n", ppscc->setcolorn);
1110
0
    }
1111
0
    if (pvalue != NULL) {
1112
0
        if (by_name) {
1113
            /* Return a resource name rather than an object reference. */
1114
0
            discard(COS_RESOURCE_VALUE(pvalue, pca));
1115
0
        } else
1116
0
            discard(COS_OBJECT_VALUE(pvalue, pca));
1117
0
    }
1118
0
    return 0;
1119
0
}
1120
1121
int convert_separation_alternate(gx_device_pdf * pdev, const gs_gstate * pgs, const gs_color_space *pcs,
1122
                        const gx_drawing_color *pdc, bool *used_process_color,
1123
                        const psdf_set_color_commands_t *ppscc, gs_client_color *pcc, cos_value_t *pvalue, bool by_name)
1124
0
{
1125
0
    gs_color_space_index csi;
1126
0
    gs_function_t *new_pfn = 0;
1127
0
    float out_low[4];
1128
0
    float out_high[4];
1129
0
    int code;
1130
0
    cos_array_t *pca, *pca1;
1131
0
    cos_value_t v;
1132
0
    byte *name_string;
1133
0
    uint name_string_length;
1134
0
    pdf_resource_t *pres = NULL;
1135
1136
0
    pca = cos_array_alloc(pdev, "pdf_color_space");
1137
0
    if (pca == 0)
1138
0
        return_error(gs_error_VMerror);
1139
1140
0
    {
1141
0
        frac conc[GS_CLIENT_COLOR_MAX_COMPONENTS];
1142
0
        gs_client_color cc;
1143
0
        unsigned char i;
1144
0
        gs_color_space *icc_space = (gs_color_space *)pcs;
1145
0
        gs_color_space *sep_space = (gs_color_space *)pcs;
1146
0
        gs_color_space_index csi2;
1147
0
        bool save_use_alt = 0;
1148
0
        separation_type save_type = SEP_OTHER;
1149
1150
0
        csi = gs_color_space_get_index(pcs);
1151
0
        if (csi == gs_color_space_index_Indexed)
1152
0
            sep_space = pcs->base_space;
1153
1154
0
        do{
1155
0
            icc_space = icc_space->base_space;
1156
0
            csi2 = gs_color_space_get_index(icc_space);
1157
0
        } while(csi2 != gs_color_space_index_ICC && icc_space->base_space);
1158
1159
0
        memset(&cc.paint.values, 0x00, GS_CLIENT_COLOR_MAX_COMPONENTS);
1160
0
        cc.paint.values[0] = 0;
1161
1162
0
        save_use_alt = sep_space->params.separation.use_alt_cspace;
1163
0
        sep_space->params.separation.use_alt_cspace = true;
1164
1165
0
        sep_space->type->concretize_color(&cc, sep_space, conc, pgs, (gx_device *)pdev);
1166
1167
0
        for (i = 0;i < pdev->color_info.num_components;i++)
1168
0
            cc.paint.values[i] = frac2float(conc[i]);
1169
1170
0
        if (pdev->params.TransferFunctionInfo == tfi_Apply) {
1171
0
            switch (pdev->params.ColorConversionStrategy) {
1172
0
                case ccs_Gray:
1173
0
                    code = apply_transfer_gray(pdev, pgs, &cc, &cc);
1174
0
                    break;
1175
0
                case ccs_sRGB:
1176
0
                case ccs_RGB:
1177
0
                    code = apply_transfer_rgb(pdev, pgs, &cc, &cc);
1178
0
                    break;
1179
0
                case ccs_CMYK:
1180
0
                    code = apply_transfer_cmyk(pdev, pgs, &cc, &cc);
1181
0
                    break;
1182
0
                default:
1183
0
                    code = gs_error_rangecheck;
1184
0
                    break;
1185
0
            }
1186
0
            if (code < 0) {
1187
0
                COS_FREE(pca, "pdf_color_space");
1188
0
                return code;
1189
0
            }
1190
0
        }
1191
0
        for (i = 0;i < pdev->color_info.num_components;i++)
1192
0
            out_low[i] = cc.paint.values[i];
1193
1194
0
        memset (&conc, 0x00, sizeof(frac) * GS_CLIENT_COLOR_MAX_COMPONENTS);
1195
        /* Force the colour management code to use the tint transform and
1196
         * give us the values in the Alternate space. Otherwise, for
1197
         * SEP_NONE or SEP_ALL it gives us the wrong answer. For SEP_NONE
1198
         * it always returns 0 and for SEP_ALL it sets the first component
1199
         * (only!) of the space to the tint value.
1200
         */
1201
0
        if (sep_space->params.separation.sep_type == SEP_ALL || sep_space->params.separation.sep_type == SEP_NONE) {
1202
0
            save_type = sep_space->params.separation.sep_type;
1203
0
            sep_space->params.separation.sep_type = SEP_OTHER;
1204
0
        }
1205
1206
0
        cc.paint.values[0] = 1;
1207
0
        memset (&conc, 0x00, sizeof(frac) * GS_CLIENT_COLOR_MAX_COMPONENTS);
1208
0
        sep_space->type->concretize_color(&cc, sep_space, conc, pgs, (gx_device *)pdev);
1209
1210
0
        for (i = 0;i < pdev->color_info.num_components;i++)
1211
0
            cc.paint.values[i] = frac2float(conc[i]);
1212
1213
0
        if (pdev->params.TransferFunctionInfo == tfi_Apply) {
1214
0
            switch (pdev->params.ColorConversionStrategy) {
1215
0
                case ccs_Gray:
1216
0
                    code = apply_transfer_gray(pdev, pgs, &cc, &cc);
1217
0
                    break;
1218
0
                case ccs_sRGB:
1219
0
                case ccs_RGB:
1220
0
                    code = apply_transfer_rgb(pdev, pgs, &cc, &cc);
1221
0
                    break;
1222
0
                case ccs_CMYK:
1223
0
                    code = apply_transfer_cmyk(pdev, pgs, &cc, &cc);
1224
0
                    break;
1225
0
                default:
1226
0
                    code = gs_error_rangecheck;
1227
0
                    break;
1228
0
            }
1229
0
            if (code < 0) {
1230
0
                COS_FREE(pca, "pdf_color_space");
1231
0
                return code;
1232
0
            }
1233
0
        }
1234
0
        for (i = 0;i < pdev->color_info.num_components;i++)
1235
0
            out_high[i] = cc.paint.values[i];
1236
1237
        /* Put back the values we hacked in order to force the colour management code
1238
         * to do what we want.
1239
         */
1240
0
        sep_space->params.separation.use_alt_cspace = save_use_alt;
1241
0
        if (save_type == SEP_ALL || save_type == SEP_NONE) {
1242
0
            sep_space->params.separation.sep_type = save_type;
1243
0
        }
1244
0
    }
1245
1246
0
    switch(pdev->params.ColorConversionStrategy) {
1247
0
        case ccs_Gray:
1248
0
            code = pdf_make_base_space_function(pdev, &new_pfn, 1, out_low, out_high);
1249
0
            break;
1250
0
        case ccs_sRGB:
1251
0
        case ccs_RGB:
1252
0
            code = pdf_make_base_space_function(pdev, &new_pfn, 3, out_low, out_high);
1253
0
            break;
1254
0
        case ccs_CMYK:
1255
0
            code = pdf_make_base_space_function(pdev, &new_pfn, 4, out_low, out_high);
1256
0
            break;
1257
0
        default:
1258
0
            code = gs_error_rangecheck;
1259
0
            break;
1260
0
    }
1261
1262
0
    if (code < 0) {
1263
0
        COS_FREE(pca, "pdf_color_space");
1264
0
        return code;
1265
0
    }
1266
1267
0
    code = cos_array_add(pca, cos_c_string_value(&v, "/Separation"));
1268
0
    if (code < 0) {
1269
0
        COS_FREE(pca, "pdf_color_space");
1270
0
        return code;
1271
0
    }
1272
1273
0
    if (code >= 0) {
1274
0
        csi = gs_color_space_get_index(pcs);
1275
0
        if (csi == gs_color_space_index_Indexed) {
1276
0
            name_string = (byte *)pcs->base_space->params.separation.sep_name;
1277
0
            name_string_length = strlen(pcs->base_space->params.separation.sep_name);
1278
0
        }
1279
0
        else {
1280
0
            name_string = (byte *)pcs->params.separation.sep_name;
1281
0
            name_string_length = strlen(pcs->params.separation.sep_name);
1282
0
        }
1283
0
        code = pdf_string_to_cos_name(pdev, name_string,
1284
0
                              name_string_length, &v);
1285
0
        if (code < 0) {
1286
0
            COS_FREE(pca, "pdf_color_space");
1287
0
            return code;
1288
0
        }
1289
1290
0
        code = cos_array_add(pca, &v);
1291
0
        if (code < 0) {
1292
0
            COS_FREE(pca, "pdf_color_space");
1293
0
            return code;
1294
0
        }
1295
0
        if (code >= 0) {
1296
0
            switch(pdev->params.ColorConversionStrategy) {
1297
0
                case ccs_Gray:
1298
0
                    cos_c_string_value(&v, (const char *)pdf_color_space_names.DeviceGray);
1299
0
                    break;
1300
0
                case ccs_RGB:
1301
0
                case ccs_sRGB:
1302
0
                    cos_c_string_value(&v, (const char *)pdf_color_space_names.DeviceRGB);
1303
0
                    break;
1304
0
                case ccs_CMYK:
1305
0
                    cos_c_string_value(&v, (const char *)pdf_color_space_names.DeviceCMYK);
1306
0
                    break;
1307
0
                default:
1308
0
                    break;
1309
0
            }
1310
0
            code = cos_array_add(pca, &v);
1311
0
            if (code >= 0) {
1312
0
                code = pdf_function_scaled(pdev, new_pfn, 0x00, &v);
1313
0
                if (code >= 0) {
1314
0
                    code = cos_array_add(pca, &v);
1315
0
                }
1316
0
            }
1317
0
        }
1318
0
    }
1319
0
    pdf_delete_base_space_function(pdev, new_pfn);
1320
1321
    /*
1322
     * Register the color space as a resource, since it must be referenced
1323
     * by name rather than directly.
1324
     */
1325
0
    {
1326
0
        pdf_color_space_t *ppcs;
1327
1328
0
        if (code < 0 ||
1329
0
            (code = pdf_alloc_resource(pdev, resourceColorSpace, pcs->id,
1330
0
                                       &pres, -1)) < 0
1331
0
            ) {
1332
0
            COS_FREE(pca, "pdf_color_space");
1333
0
            return code;
1334
0
        }
1335
0
        pdf_reserve_object_id(pdev, pres, 0);
1336
0
        ppcs = (pdf_color_space_t *)pres;
1337
0
        ppcs->serialized = NULL;
1338
0
        ppcs->serialized_size = 0;
1339
1340
0
        ppcs->ranges = 0;
1341
0
        pca->id = pres->object->id;
1342
0
        COS_FREE(pres->object, "pdf_color_space");
1343
0
        pres->object = (cos_object_t *)pca;
1344
0
        cos_write_object(COS_OBJECT(pca), pdev, resourceColorSpace);
1345
0
        csi = gs_color_space_get_index(pcs);
1346
0
        if (csi != gs_color_space_index_Indexed && ppscc != NULL)
1347
0
            pprints1(pdev->strm, "/%s", ppcs->rname);
1348
0
    }
1349
0
    pres->where_used |= pdev->used_mask;
1350
0
    code = pdf_add_resource(pdev, pdev->substream_Resources, "/ColorSpace", pres);
1351
0
    if (code < 0)
1352
0
        return code;
1353
1354
0
    csi = gs_color_space_get_index(pcs);
1355
0
    if (csi == gs_color_space_index_Indexed) {
1356
0
        cos_value_t value;
1357
1358
0
        discard(COS_OBJECT_VALUE(&value, pca));
1359
0
        pca1 = cos_array_alloc(pdev, "pdf_color_space");
1360
0
        if (pca1 == NULL)
1361
0
            return_error(gs_error_VMerror);
1362
1363
0
        code = pdf_indexed_color_space(pdev, pgs, &value, pcs, pca1, (cos_value_t *)&value);
1364
0
        pca = pca1;
1365
1366
        /*
1367
         * Register the color space as a resource, since it must be referenced
1368
         * by name rather than directly.
1369
         */
1370
0
        {
1371
0
            pdf_color_space_t *ppcs;
1372
1373
0
            if (code < 0 ||
1374
0
                (code = pdf_alloc_resource(pdev, resourceColorSpace, pcs->id,
1375
0
                                           &pres, -1)) < 0
1376
0
                ) {
1377
0
                COS_FREE(pca, "pdf_color_space");
1378
0
                return code;
1379
0
            }
1380
0
            pdf_reserve_object_id(pdev, pres, 0);
1381
0
            ppcs = (pdf_color_space_t *)pres;
1382
0
            ppcs->serialized = NULL;
1383
0
            ppcs->serialized_size = 0;
1384
1385
0
            ppcs->ranges = 0;
1386
0
            pca->id = pres->object->id;
1387
0
            COS_FREE(pres->object, "pdf_color_space");
1388
0
            pres->object = (cos_object_t *)pca;
1389
0
            cos_write_object(COS_OBJECT(pca), pdev, resourceColorSpace);
1390
0
            if (ppscc != NULL)
1391
0
                pprints1(pdev->strm, "/%s", ppcs->rname);
1392
0
        }
1393
0
        pres->where_used |= pdev->used_mask;
1394
0
        code = pdf_add_resource(pdev, pdev->substream_Resources, "/ColorSpace", pres);
1395
0
        if (code < 0)
1396
0
            return code;
1397
0
    }
1398
1399
0
    if (ppscc != NULL) {
1400
0
        pprints1(pdev->strm, " %s\n", ppscc->setcolorspace);
1401
0
        *used_process_color = false;
1402
0
        pprintg1(pdev->strm, "%g", psdf_round(pcc->paint.values[0], 255, 8));
1403
0
        pprints1(pdev->strm, " %s\n", ppscc->setcolorn);
1404
0
    }
1405
0
    if (pvalue != NULL) {
1406
0
        if (by_name) {
1407
            /* Return a resource name rather than an object reference. */
1408
0
            discard(COS_RESOURCE_VALUE(pvalue, pca));
1409
0
        } else
1410
0
            discard(COS_OBJECT_VALUE(pvalue, pca));
1411
0
    }
1412
0
    return 0;
1413
0
}
1414
1415
void
1416
rescale_cie_color(gs_range_t *ranges, int num_colorants,
1417
                    const gs_client_color *src, gs_client_color *des)
1418
0
{
1419
0
    int k;
1420
1421
0
    for (k = 0; k < num_colorants; k++) {
1422
0
        des->paint.values[k] =
1423
0
            (src->paint.values[k]-ranges[k].rmin)/
1424
0
            (ranges[k].rmax-ranges[k].rmin);
1425
0
    }
1426
0
}
1427
1428
static int check_colorants_for_pdfx4(const gs_color_space *pcs)
1429
0
{
1430
0
    int comp, all_present = 1;
1431
0
    char *ink;
1432
0
    gs_device_n_colorant *colorant = NULL;
1433
1434
0
    if (pcs->params.device_n.colorants == NULL) {
1435
0
        return 0;
1436
0
    } else {
1437
0
        for (comp = 0; comp < pcs->params.device_n.num_components;comp++){
1438
0
            colorant = pcs->params.device_n.colorants;
1439
0
            ink = pcs->params.device_n.names[comp];
1440
0
            do {
1441
0
                if (memcmp(colorant->colorant_name, ink, strlen(ink)) == 0)
1442
0
                    break;
1443
0
                colorant = colorant->next;
1444
0
            }while(colorant);
1445
0
            if (!colorant) {
1446
0
                all_present = 0;
1447
0
                break;
1448
0
            }
1449
0
        }
1450
0
    }
1451
0
    return all_present;
1452
0
}
1453
1454
/* Set the fill or stroke color. */
1455
int pdf_reset_color(gx_device_pdf * pdev, const gs_gstate * pgs,
1456
                const gx_drawing_color *pdc, gx_hl_saved_color * psc,
1457
                bool *used_process_color,
1458
                const psdf_set_color_commands_t *ppscc)
1459
1.71M
{
1460
1.71M
    int code=0, code1=0;
1461
1.71M
    gx_hl_saved_color temp;
1462
1.71M
    gs_client_color *pcc; /* fixme: not needed due to gx_hld_get_color_component. */
1463
1.71M
    cos_value_t cs_value;
1464
1.71M
    gs_color_space_index csi;
1465
1.71M
    gs_color_space_index csi2;
1466
1.71M
    const gs_color_space *pcs, *pcs2;
1467
1468
1.71M
    if (pdev->skip_colors)
1469
0
        return 0;
1470
1471
    /* Get a copy of the current colour so we can examine it. */
1472
1.71M
    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.71M
    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.71M
    switch (gx_hld_get_color_space_and_ccolor(pgs, pdc, &pcs, (const gs_client_color **)&pcc)) {
1484
18.7k
        case pattern_color_space:
1485
18.7k
            {
1486
18.7k
                pdf_resource_t *pres;
1487
1488
18.7k
                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
5.86k
                    if (pdev->CompatibilityLevel < 1.2) {
1493
0
                        return_error(gs_error_undefined);
1494
0
                    }
1495
5.86k
                    code = pdf_put_colored_pattern(pdev, pdc, pcs,
1496
5.86k
                                ppscc, pgs, &pres);
1497
5.86k
                }
1498
12.8k
                else if (pdc->type == &gx_dc_pure_masked) {
1499
92
                    code = pdf_put_uncolored_pattern(pdev, pdc, pcs,
1500
92
                                ppscc, pgs, &pres);
1501
92
                    if (code < 0 || pres == 0) {
1502
                        /* replaced a pattern with a flat fill, but we still
1503
                         * need to change the 'saved' colour or we will
1504
                         * get out of step with the PDF content.
1505
                         */
1506
0
                        *psc = temp;
1507
0
                        return code;
1508
0
                    }
1509
92
                    if (pgs->have_pattern_streams)
1510
92
                        code = pdf_write_ccolor(pdev, pgs, pcc);
1511
12.8k
                } else if (pdc->type == &gx_dc_pattern2) {
1512
12.8k
                    if (pdev->CompatibilityLevel <= 1.2)
1513
4.03k
                        return_error(gs_error_rangecheck);
1514
8.76k
                    if (!is_pattern2_allowed_in_strategy(pdev, pdc))
1515
0
                        return_error(gs_error_rangecheck);
1516
8.76k
                    code1 = pdf_put_pattern2(pdev, pgs, pdc, ppscc, &pres);
1517
8.76k
                    if (code1 < 0)
1518
0
                        return code1;
1519
8.76k
                } else
1520
0
                    return_error(gs_error_rangecheck);
1521
14.7k
                if (code < 0)
1522
0
                    return code;
1523
14.7k
                code = pdf_add_resource(pdev, pdev->substream_Resources, "/Pattern", pres);
1524
14.7k
                if (code >= 0) {
1525
14.7k
                    cos_value_write(cos_resource_value(&cs_value, pres->object), pdev);
1526
14.7k
                    pprints1(pdev->strm, " %s\n", ppscc->setcolorn);
1527
14.7k
                }
1528
0
                else {
1529
0
                    pres->where_used = 0;
1530
0
                    return code;
1531
0
                }
1532
14.7k
                *used_process_color = false;
1533
14.7k
            }
1534
0
            break;
1535
930k
        case non_pattern_color_space:
1536
930k
            pcs2 = pcs;
1537
930k
            csi = csi2 = gs_color_space_get_index(pcs);
1538
930k
            if (csi == gs_color_space_index_ICC) {
1539
904k
                csi2 = gsicc_get_default_type(pcs->cmm_icc_profile_data);
1540
904k
            }
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
930k
            if (pdev->CompatibilityLevel <= 1.2) {
1544
1545
                /* If we have an /Indexed space, we need to look at the base space */
1546
684k
                if (csi2 == gs_color_space_index_Indexed) {
1547
29
                    pcs2 = pcs->base_space;
1548
29
                    csi2 = gs_color_space_get_index(pcs2);
1549
29
                }
1550
1551
684k
                switch (csi2) {
1552
211k
                    case gs_color_space_index_DeviceGray:
1553
211k
                        if (pdev->params.ColorConversionStrategy == ccs_LeaveColorUnchanged ||
1554
211k
                            pdev->params.ColorConversionStrategy == ccs_Gray)
1555
211k
                            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
211k
                        break;
1559
279k
                    case gs_color_space_index_DeviceRGB:
1560
279k
                        if (pdev->params.ColorConversionStrategy == ccs_LeaveColorUnchanged ||
1561
279k
                            pdev->params.ColorConversionStrategy == ccs_RGB)
1562
279k
                            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
279k
                        break;
1566
71.0k
                    case gs_color_space_index_DeviceCMYK:
1567
71.0k
                        if (pdev->params.ColorConversionStrategy == ccs_LeaveColorUnchanged ||
1568
71.0k
                            pdev->params.ColorConversionStrategy == ccs_CMYK)
1569
71.0k
                            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
71.0k
                        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
20.2k
                    case gs_color_space_index_Separation:
1598
20.2k
                        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
20.2k
                            case ccs_LeaveColorUnchanged:
1604
20.2k
                                pcs2 = pcs->base_space;
1605
20.2k
                                csi2 = gs_color_space_get_index(pcs2);
1606
20.2k
                                if (csi2 == gs_color_space_index_ICC) {
1607
20.2k
                                    csi2 = gsicc_get_default_type(pcs2->cmm_icc_profile_data);
1608
20.2k
                                }
1609
20.2k
                                if (csi2 == gs_color_space_index_ICC) {
1610
8.59k
                                    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.59k
                                        code = write_color_unchanged(pdev, pgs, pcc, &temp, psc, ppscc, used_process_color, pcs, pdc);
1632
8.59k
                                } else
1633
11.6k
                                    code = write_color_unchanged(pdev, pgs, pcc, &temp, psc, ppscc, used_process_color, pcs, pdc);
1634
20.2k
                                break;
1635
20.2k
                            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
20.2k
                        }
1643
20.2k
                        break;
1644
20.2k
                    case gs_color_space_index_DeviceN:
1645
72
                        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
72
                            case ccs_LeaveColorUnchanged:
1651
72
                                code = write_color_unchanged(pdev, pgs, pcc, &temp, psc, ppscc, used_process_color, pcs, pdc);
1652
72
                                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
72
                        }
1675
72
                        break;
1676
101k
                    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
101k
                        csi2 = gsicc_get_default_type(pcs2->cmm_icc_profile_data);
1685
1686
101k
                        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
101k
                            default:
1712
101k
                                break;
1713
101k
                        }
1714
                        /* Fall through if its not a device substitute, or not one we want to preserve */
1715
101k
                    case gs_color_space_index_DevicePixel:
1716
101k
                    case gs_color_space_index_Indexed:
1717
101k
                        code = write_color_as_process(pdev, pgs, pcs, pdc, used_process_color, ppscc, pcc);
1718
101k
                        break;
1719
0
                    default:
1720
0
                        return (gs_note_error(gs_error_rangecheck));
1721
0
                        break;
1722
684k
                }
1723
684k
            } else {
1724
245k
                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
245k
                    case ccs_LeaveColorUnchanged:
1730
245k
                        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
245k
                        else
1773
245k
                            code = write_color_unchanged(pdev, pgs, pcc, &temp, psc, ppscc, used_process_color, pcs, pdc);
1774
245k
                        break;
1775
245k
                    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
245k
                }
2062
245k
            }
2063
930k
            break;
2064
930k
        default: /* must not happen. */
2065
767k
        case use_process_color:
2066
767k
            code = psdf_set_color((gx_device_vector *)pdev, pdc, ppscc);
2067
767k
            if (code < 0)
2068
10.8k
                return code;
2069
756k
            *used_process_color = true;
2070
756k
            break;
2071
1.71M
    }
2072
1.70M
    *psc = temp;
2073
1.70M
    return code;
2074
1.71M
}
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.1M
{
2083
11.1M
    gx_hl_saved_color temp;
2084
11.1M
    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.1M
    if (pdev->skip_colors)
2092
9.29k
        return 0;
2093
11.1M
    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.1M
    if (gx_hld_saved_color_equal(&temp, psc))
2099
10.2M
        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
959k
    code = pdf_open_page(pdev, PDF_IN_STREAM);
2108
959k
    if (code < 0)
2109
0
        return code;
2110
2111
959k
    return pdf_reset_color(pdev, pgs, pdc, psc, used_process_color, ppscc);
2112
959k
}
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
960k
{
2119
960k
    gx_drawing_color dcolor;
2120
960k
    gx_hl_saved_color temp;
2121
960k
    int code;
2122
2123
960k
    set_nonclient_dev_color(&dcolor, color);
2124
2125
960k
    if (pdev->skip_colors)
2126
0
        return 0;
2127
960k
    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
960k
    if (gx_hld_saved_color_equal(&temp, psc))
2133
203k
        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
756k
    code = pdf_open_page(pdev, PDF_IN_STREAM);
2142
756k
    if (code < 0)
2143
0
        return code;
2144
2145
756k
    return pdf_reset_color(pdev, NULL, &dcolor, psc, used_process_color, ppscc);
2146
756k
}
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
6.34k
{
2155
6.34k
    byte *chars = gs_alloc_string(pdev->pdf_memory, len + 1,
2156
6.34k
                                  "pdf_string_to_cos_name");
2157
2158
6.34k
    if (chars == 0)
2159
0
        return_error(gs_error_VMerror);
2160
6.34k
    chars[0] = '/';
2161
6.34k
    memcpy(chars + 1, str, len);
2162
6.34k
    cos_string_value(pvalue, chars, len + 1);
2163
6.34k
    return 0;
2164
6.34k
}
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
11.5k
{
2185
11.5k
    const gx_transfer_map *map = (const gx_transfer_map *)psrc->data.str.data;
2186
11.5k
    uint i;
2187
2188
11.5k
    if (ptr)
2189
11.5k
        *ptr = buf;
2190
994k
    for (i = 0; i < length; ++i)
2191
982k
        buf[i] = frac2byte(map->values[(uint)start + i]);
2192
11.5k
    return 0;
2193
11.5k
}
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
11.1k
{
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
11.1k
    const gx_transfer_map *map = (const gx_transfer_map *)psrc->data.str.data;
2206
11.1k
    uint i;
2207
2208
11.1k
    *ptr = buf;
2209
964k
    for (i = 0; i < length; ++i)
2210
953k
        buf[i] = (byte)
2211
953k
            ((frac2float(map->values[(uint)start + i]) + 1) * 127);
2212
11.1k
    return 0;
2213
11.1k
}
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
26.2k
{
2219
26.2k
    gs_memory_t *mem = pdev->pdf_memory;
2220
26.2k
    gs_function_Sd_params_t params;
2221
26.2k
    static const float domain01[2] = { 0, 1 };
2222
26.2k
    static const int size = transfer_map_size;
2223
26.2k
    float range01[2], decode[2];
2224
26.2k
    gs_function_t *pfn;
2225
26.2k
    int64_t id;
2226
26.2k
    int code;
2227
2228
26.2k
    if (map == 0) {
2229
6.29k
        *ids = 0;   /* no map */
2230
6.29k
        return 1;
2231
6.29k
    }
2232
19.9k
    if (check_identity) {
2233
        /* Check for an identity map. */
2234
12.5k
        int i;
2235
2236
12.5k
        if (map->proc == gs_identity_transfer)
2237
12.4k
            i = transfer_map_size;
2238
104
        else
2239
208
            for (i = 0; i < transfer_map_size; ++i) {
2240
208
                fixed d = map->values[i] - bits2frac(i, log2_transfer_map_size);
2241
208
                if (any_abs(d) > fixed_epsilon) /* ignore small noise */
2242
104
                    break;
2243
208
            }
2244
12.5k
        if (i == transfer_map_size) {
2245
12.4k
            strcpy(ids, key);
2246
12.4k
            strcat(ids, "/Identity");
2247
12.4k
            return 1;
2248
12.4k
        }
2249
12.5k
    }
2250
7.56k
    params.m = 1;
2251
7.56k
    params.Domain = domain01;
2252
7.56k
    params.n = 1;
2253
7.56k
    range01[0] = (float)range0, range01[1] = 1.0;
2254
7.56k
    params.Range = range01;
2255
7.56k
    params.Order = 1;
2256
7.56k
    params.DataSource.access =
2257
7.56k
        (range0 < 0 ? transfer_map_access_signed : transfer_map_access);
2258
7.56k
    params.DataSource.data.str.data = (const byte *)map; /* bogus */
2259
    /* DataSource */
2260
7.56k
    params.BitsPerSample = 8; /* could be 16 */
2261
7.56k
    params.Encode = 0;
2262
7.56k
    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
3.72k
        int r0 = (int)( -range01[0] * ((1 << params.BitsPerSample) - 1)
2269
3.72k
                        / (range01[1] - range01[0]) ); /* Round down. */
2270
3.72k
        float r1 = r0 * range01[1] / -range01[0]; /* r0 + r1 <= (1 << params.BitsPerSample) - 1 */
2271
2272
3.72k
        decode[0] = range01[0];
2273
3.72k
        decode[1] = range01[0] + (range01[1] - range01[0]) * ((1 << params.BitsPerSample) - 1)
2274
3.72k
                                    / (r0 + r1);
2275
3.72k
        params.Decode = decode;
2276
3.72k
    } else
2277
3.83k
        params.Decode = 0;
2278
7.56k
    params.Size = &size;
2279
7.56k
    code = gs_function_Sd_init(&pfn, &params, mem);
2280
7.56k
    if (code < 0)
2281
0
        return code;
2282
7.56k
    code = pdf_write_function(pdev, pfn, &id);
2283
7.56k
    gs_function_free(pfn, false, mem);
2284
7.56k
    if (code < 0)
2285
0
        return code;
2286
7.56k
    gs_snprintf(ids, id_max, "%s%s%"PRId64" 0 R", key, (key[0] && key[0] != ' ' ? " " : ""), id);
2287
7.56k
    return 0;
2288
7.56k
}
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
18.7k
{
2293
18.7k
    return pdf_write_transfer_map(pdev, map, 0, true, key, ids, id_max);
2294
18.7k
}
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
353k
  static double name(double xd, double yd) {\
2306
353k
    float x = (float)xd, y = (float)yd;\
2307
353k
    return d2f(expr);\
2308
353k
  }
gdevpdfg.c:ht_EllipseA
Line
Count
Source
2305
27.4k
  static double name(double xd, double yd) {\
2306
27.4k
    float x = (float)xd, y = (float)yd;\
2307
27.4k
    return d2f(expr);\
2308
27.4k
  }
gdevpdfg.c:ht_InvertedEllipseA
Line
Count
Source
2305
27.4k
  static double name(double xd, double yd) {\
2306
27.4k
    float x = (float)xd, y = (float)yd;\
2307
27.4k
    return d2f(expr);\
2308
27.4k
  }
gdevpdfg.c:ht_EllipseB
Line
Count
Source
2305
27.4k
  static double name(double xd, double yd) {\
2306
27.4k
    float x = (float)xd, y = (float)yd;\
2307
27.4k
    return d2f(expr);\
2308
27.4k
  }
gdevpdfg.c:ht_EllipseC
Line
Count
Source
2305
27.4k
  static double name(double xd, double yd) {\
2306
27.4k
    float x = (float)xd, y = (float)yd;\
2307
27.4k
    return d2f(expr);\
2308
27.4k
  }
gdevpdfg.c:ht_InvertedEllipseC
Line
Count
Source
2305
27.4k
  static double name(double xd, double yd) {\
2306
27.4k
    float x = (float)xd, y = (float)yd;\
2307
27.4k
    return d2f(expr);\
2308
27.4k
  }
gdevpdfg.c:ht_Line
Line
Count
Source
2305
27.4k
  static double name(double xd, double yd) {\
2306
27.4k
    float x = (float)xd, y = (float)yd;\
2307
27.4k
    return d2f(expr);\
2308
27.4k
  }
gdevpdfg.c:ht_LineX
Line
Count
Source
2305
15.7k
  static double name(double xd, double yd) {\
2306
15.7k
    float x = (float)xd, y = (float)yd;\
2307
15.7k
    return d2f(expr);\
2308
15.7k
  }
gdevpdfg.c:ht_LineY
Line
Count
Source
2305
15.7k
  static double name(double xd, double yd) {\
2306
15.7k
    float x = (float)xd, y = (float)yd;\
2307
15.7k
    return d2f(expr);\
2308
15.7k
  }
gdevpdfg.c:ht_Square
Line
Count
Source
2305
15.7k
  static double name(double xd, double yd) {\
2306
15.7k
    float x = (float)xd, y = (float)yd;\
2307
31.5k
    return d2f(expr);\
2308
15.7k
  }
gdevpdfg.c:ht_Cross
Line
Count
Source
2305
15.7k
  static double name(double xd, double yd) {\
2306
15.7k
    float x = (float)xd, y = (float)yd;\
2307
31.5k
    return d2f(expr);\
2308
15.7k
  }
gdevpdfg.c:ht_Rhomboid
Line
Count
Source
2305
15.7k
  static double name(double xd, double yd) {\
2306
15.7k
    float x = (float)xd, y = (float)yd;\
2307
15.7k
    return d2f(expr);\
2308
15.7k
  }
gdevpdfg.c:ht_DoubleDot
Line
Count
Source
2305
15.7k
  static double name(double xd, double yd) {\
2306
15.7k
    float x = (float)xd, y = (float)yd;\
2307
15.7k
    return d2f(expr);\
2308
15.7k
  }
gdevpdfg.c:ht_InvertedDoubleDot
Line
Count
Source
2305
15.7k
  static double name(double xd, double yd) {\
2306
15.7k
    float x = (float)xd, y = (float)yd;\
2307
15.7k
    return d2f(expr);\
2308
15.7k
  }
gdevpdfg.c:ht_SimpleDot
Line
Count
Source
2305
15.7k
  static double name(double xd, double yd) {\
2306
15.7k
    float x = (float)xd, y = (float)yd;\
2307
15.7k
    return d2f(expr);\
2308
15.7k
  }
gdevpdfg.c:ht_InvertedSimpleDot
Line
Count
Source
2305
15.7k
  static double name(double xd, double yd) {\
2306
15.7k
    float x = (float)xd, y = (float)yd;\
2307
15.7k
    return d2f(expr);\
2308
15.7k
  }
gdevpdfg.c:ht_CosineDot
Line
Count
Source
2305
15.7k
  static double name(double xd, double yd) {\
2306
15.7k
    float x = (float)xd, y = (float)yd;\
2307
15.7k
    return d2f(expr);\
2308
15.7k
  }
gdevpdfg.c:ht_Double
Line
Count
Source
2305
15.7k
  static double name(double xd, double yd) {\
2306
15.7k
    float x = (float)xd, y = (float)yd;\
2307
15.7k
    return d2f(expr);\
2308
15.7k
  }
gdevpdfg.c:ht_InvertedDouble
Line
Count
Source
2305
15.7k
  static double name(double xd, double yd) {\
2306
15.7k
    float x = (float)xd, y = (float)yd;\
2307
15.7k
    return d2f(expr);\
2308
15.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.48M
{
2318
1.48M
    float f = (float)d;
2319
1.48M
    return f;
2320
1.48M
}
2321
static double
2322
ht_Round(double xf, double yf)
2323
70.5k
{
2324
70.5k
    float x = (float)xf, y = (float)yf;
2325
70.5k
    float xabs = fabs(x), yabs = fabs(y);
2326
2327
70.5k
    if (d2f(xabs + yabs) <= 1)
2328
35.2k
        return d2f(1 - d2f(d2f(x * x) + d2f(y * y)));
2329
35.2k
    xabs -= 1, yabs -= 1;
2330
35.2k
    return d2f(d2f(d2f(xabs * xabs) + d2f(yabs * yabs)) - 1);
2331
70.5k
}
2332
static double
2333
ht_Diamond(double xf, double yf)
2334
27.4k
{
2335
27.4k
    float x = (float)xf, y = (float)yf;
2336
27.4k
    float xabs = fabs(x), yabs = fabs(y);
2337
2338
27.4k
    if (d2f(xabs + yabs) <= 0.75)
2339
11.1k
        return d2f(1 - d2f(d2f(x * x) + d2f(y * y)));
2340
16.2k
    if (d2f(xabs + yabs) <= d2f(1.23))
2341
5.06k
        return d2f(1 - d2f(d2f(d2f(0.85) * xabs) + yabs));
2342
11.1k
    xabs -= 1, yabs -= 1;
2343
11.1k
    return d2f(d2f(d2f(xabs * xabs) + d2f(yabs * yabs)) - 1);
2344
16.2k
}
2345
static double
2346
ht_Ellipse(double xf, double yf)
2347
27.4k
{
2348
27.4k
    float x = (float)xf, y = (float)yf;
2349
27.4k
    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
27.4k
    float w = (float)(d2f(d2f(3 * xabs) + d2f(4 * yabs)) - 3);
2356
2357
27.4k
    if (w < 0) {
2358
12.2k
        yabs /= 0.75;
2359
12.2k
        return d2f(1 - d2f((d2f(x * x) + d2f(yabs * yabs)) / 4));
2360
12.2k
    }
2361
15.2k
    if (w > 1) {
2362
12.2k
        xabs = 1 - xabs, yabs = d2f(1 - yabs) / 0.75;
2363
12.2k
        return d2f(d2f((d2f(xabs * xabs) + d2f(yabs * yabs)) / 4) - 1);
2364
12.2k
    }
2365
2.97k
    return d2f(0.5 - w);
2366
15.2k
}
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
126k
d2fsin_d(double x) {
2373
126k
    return d2f(gs_sin_degrees(d2f(x)));
2374
126k
}
2375
static float
2376
31.5k
d2fcos_d(double x) {
2377
31.5k
    return d2f(gs_cos_degrees(d2f(x)));
2378
31.5k
}
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
875
{
2430
    /****** DOESN'T HANDLE STRIP HALFTONES ******/
2431
875
    int w = porder->width, h = porder->height;
2432
875
    uint num_bits = porder->num_bits;
2433
875
    gs_function_Sd_params_t params;
2434
875
    static const float domain_spot[4] = { -1, 1, -1, 1 };
2435
875
    static const float range_spot[4] = { -1, 1 };
2436
875
    int size[2];
2437
875
    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
875
    byte *values;
2443
875
    gs_function_t *pfn;
2444
875
    uint i;
2445
875
    int code = 0;
2446
2447
875
    params.array_size = 0;
2448
875
    params.m = 2;
2449
875
    params.Domain = domain_spot;
2450
875
    params.n = 1;
2451
875
    params.Range = range_spot;
2452
875
    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
875
    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
875
    params.BitsPerSample = 16;
2465
875
    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
875
    params.Decode = 0;
2472
875
    size[0] = w;
2473
875
    size[1] = h;
2474
875
    params.Size = size;
2475
    /* Create the (temporary) threshold array. */
2476
875
    values = gs_alloc_byte_array(mem, num_bits, 2, "pdf_write_spot_function");
2477
875
    if (values == 0)
2478
0
        return_error(gs_error_VMerror);
2479
32.3k
    for (i = 0; i < num_bits; ++i) {
2480
31.5k
        gs_int_point pt;
2481
31.5k
        int value;
2482
2483
31.5k
        if ((code = porder->procs->bit_index(porder, i, &pt)) < 0)
2484
0
            break;
2485
31.5k
        value = pt.y * w + pt.x;
2486
        /* Always store the values in big-endian order. */
2487
31.5k
        values[i * 2] = (byte)(value >> 8);
2488
31.5k
        values[i * 2 + 1] = (byte)value;
2489
31.5k
    }
2490
875
    data_source_init_bytes(&params.DataSource, (const byte *)values,
2491
875
                           sizeof(*values) * num_bits);
2492
875
    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
875
        (code = gs_function_Sd_init(&pfn, &params, mem)) >= 0
2497
875
        ) {
2498
875
        code = pdf_write_function(pdev, pfn, pid);
2499
875
        gs_function_free(pfn, false, mem);
2500
875
    }
2501
875
    gs_free_object(mem, values, "pdf_write_spot_function");
2502
875
    return code;
2503
875
}
2504
2505
/* if (memcmp(order.levels, porder->levels, order.num_levels * sizeof(*order.levels))) */
2506
static int
2507
24.0k
compare_gx_ht_order_levels(const gx_ht_order *order1, const gx_ht_order *order2) {
2508
24.0k
  int i;
2509
503k
  for (i=0;  i<order1->num_levels;  i++) {
2510
478k
    if (order1->levels[i] != order2->levels[i])
2511
0
      return(1);
2512
478k
  }
2513
24.0k
  return(0);
2514
24.0k
}
2515
2516
static int
2517
pdf_write_spot_halftone(gx_device_pdf *pdev, const gs_spot_halftone *psht,
2518
                        const gx_ht_order *porder, long *pid)
2519
6.29k
{
2520
6.29k
    char trs[17 + MAX_FN_CHARS + 1];
2521
6.29k
    int code;
2522
6.29k
    int64_t spot_id;
2523
6.29k
    stream *s;
2524
6.29k
    int i = countof(ht_functions);
2525
6.29k
    gs_memory_t *mem = pdev->pdf_memory;
2526
2527
6.29k
    if (pdev->CompatibilityLevel <= 1.7) {
2528
6.29k
        code = pdf_write_transfer(pdev, porder->transfer, "/TransferFunction",
2529
6.29k
                                  trs, sizeof(trs));
2530
6.29k
        if (code < 0)
2531
0
            return code;
2532
6.29k
    }
2533
    /*
2534
     * See if we can recognize the spot function, by comparing its sampled
2535
     * values against those in the order.
2536
     */
2537
6.29k
    { gs_screen_enum senum;
2538
6.29k
        gx_ht_order order;
2539
6.29k
        int code;
2540
2541
6.29k
        order = *porder;
2542
6.29k
        code = gs_screen_order_alloc(&order, mem);
2543
6.29k
        if (code < 0)
2544
0
            goto notrec;
2545
24.8k
        for (i = 0; i < countof(ht_functions); ++i) {
2546
24.0k
            double (*spot_proc)(double, double) = ht_functions[i].proc;
2547
24.0k
            gs_point pt;
2548
2549
24.0k
            gs_screen_enum_init_memory(&senum, &order, NULL, &psht->screen,
2550
24.0k
                                       mem);
2551
503k
            while ((code = gs_screen_currentpoint(&senum, &pt)) == 0 &&
2552
503k
                   gs_screen_next(&senum, spot_proc(pt.x, pt.y)) >= 0)
2553
478k
                DO_NOTHING;
2554
24.0k
            if (code < 0)
2555
0
                continue;
2556
            /* Compare the bits and levels arrays. */
2557
24.0k
            if (compare_gx_ht_order_levels(&order,porder))
2558
0
                continue;
2559
24.0k
            if (memcmp(order.bit_data, porder->bit_data,
2560
24.0k
                       (size_t)order.num_bits *
2561
24.0k
                                      porder->procs->bit_data_elt_size))
2562
18.6k
                continue;
2563
            /* We have a match. */
2564
5.41k
            break;
2565
24.0k
        }
2566
6.29k
        gx_ht_order_release(&order, mem, false);
2567
6.29k
    }
2568
6.29k
 notrec:
2569
6.29k
    if (i == countof(ht_functions)) {
2570
        /* Create and write a Function for the spot function. */
2571
875
        code = pdf_write_spot_function(pdev, porder, &spot_id);
2572
875
        if (code < 0)
2573
0
            return code;
2574
875
    }
2575
6.29k
    *pid = pdf_begin_separate(pdev, resourceHalftone);
2576
6.29k
    s = pdev->strm;
2577
    /* Use the original, requested frequency and angle. */
2578
6.29k
    pprintg2(s, "<</Type/Halftone/HalftoneType 1/Frequency %g/Angle %g",
2579
6.29k
             psht->screen.frequency, psht->screen.angle);
2580
6.29k
    if (i < countof(ht_functions))
2581
5.41k
        pprints1(s, "/SpotFunction/%s", ht_functions[i].fname);
2582
875
    else
2583
875
        pprinti64d1(s, "/SpotFunction %"PRId64" 0 R", spot_id);
2584
6.29k
    if (pdev->CompatibilityLevel <= 1.7)
2585
6.29k
        stream_puts(s, trs);
2586
6.29k
    if (psht->accurate_screens)
2587
0
        stream_puts(s, "/AccurateScreens true");
2588
6.29k
    stream_puts(s, ">>\n");
2589
6.29k
    return pdf_end_separate(pdev, resourceHalftone);
2590
6.29k
}
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
904
{
2595
904
    gs_spot_halftone spot;
2596
2597
904
    spot.screen = *psht;
2598
904
    spot.accurate_screens = false;
2599
904
    spot.transfer = 0;
2600
904
    spot.transfer_closure.proc = 0;
2601
904
    return pdf_write_spot_halftone(pdev, &spot, porder, pid);
2602
904
}
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
32.3k
{
2728
32.3k
    int j;
2729
2730
64.6k
    for (j = 0; j < pmht->num_comp; j++)
2731
32.3k
        if (pmht->components[j].comp_number == dht_index)
2732
0
            break;
2733
32.3k
    if (j == pmht->num_comp) {
2734
        /* Look for Default. */
2735
32.3k
        for (j = 0; j < pmht->num_comp; j++)
2736
32.3k
            if (pmht->components[j].comp_number == GX_DEVICE_COLOR_MAX_COMPONENTS)
2737
32.3k
                break;
2738
32.3k
        if (j == pmht->num_comp)
2739
0
            return_error(gs_error_undefined);
2740
32.3k
    }
2741
32.3k
    return j;
2742
32.3k
}
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
5.38k
{
2748
5.38k
    stream *s;
2749
5.38k
    int i, code, last_comp = 0;
2750
5.38k
    gs_memory_t *mem = pdev->pdf_memory;
2751
5.38k
    long *ids;
2752
5.38k
    bool done_Default = false;
2753
2754
5.38k
    ids = (long *)gs_alloc_byte_array(mem, pmht->num_comp, sizeof(long),
2755
5.38k
                                      "pdf_write_multiple_halftone");
2756
5.38k
    if (ids == 0)
2757
0
        return_error(gs_error_VMerror);
2758
21.5k
    for (i = 0; i < pdht->num_comp; ++i) {
2759
16.1k
        const gs_halftone_component *phtc;
2760
16.1k
        const gx_ht_order *porder;
2761
2762
16.1k
        code = pdf_get_halftone_component_index(pmht, pdht, i);
2763
16.1k
        if (code < 0)
2764
0
            return code;
2765
16.1k
        if (pmht->components[code].comp_number == GX_DEVICE_COLOR_MAX_COMPONENTS) {
2766
16.1k
            if (done_Default)
2767
10.7k
                continue;
2768
5.38k
            done_Default = true;
2769
5.38k
        }
2770
5.38k
        phtc = &pmht->components[code];
2771
5.38k
        porder = (pdht->components == 0 ? &pdht->order :
2772
5.38k
                       &pdht->components[i].corder);
2773
5.38k
        switch (phtc->type) {
2774
5.38k
        case ht_type_spot:
2775
5.38k
            code = pdf_write_spot_halftone(pdev, &phtc->params.spot,
2776
5.38k
                                           porder, &ids[i]);
2777
5.38k
            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
5.38k
        }
2790
5.38k
        if (code < 0) {
2791
0
            gs_free_object(mem, ids, "pdf_write_multiple_halftone");
2792
0
            return code;
2793
0
        }
2794
5.38k
    }
2795
5.38k
    *pid = pdf_begin_separate(pdev, resourceHalftone);
2796
5.38k
    s = pdev->strm;
2797
5.38k
    stream_puts(s, "<</Type/Halftone/HalftoneType 5\n");
2798
5.38k
    done_Default = false;
2799
21.5k
    for (i = 0; i < pdht->num_comp; ++i) {
2800
16.1k
        const gs_halftone_component *phtc;
2801
16.1k
        byte *str;
2802
16.1k
        uint len;
2803
16.1k
        cos_value_t value;
2804
2805
16.1k
        code = pdf_get_halftone_component_index(pmht, pdht, i);
2806
16.1k
        if (code < 0)
2807
0
            return code;
2808
16.1k
        if (pmht->components[code].comp_number == GX_DEVICE_COLOR_MAX_COMPONENTS) {
2809
16.1k
            if (done_Default)
2810
10.7k
                continue;
2811
5.38k
            done_Default = true;
2812
5.38k
        }
2813
5.38k
        phtc = &pmht->components[code];
2814
5.38k
        if ((code = pmht->get_colorname_string(pgs, phtc->cname, &str, &len)) < 0 ||
2815
5.38k
            (code = pdf_string_to_cos_name(pdev, str, len, &value)) < 0)
2816
0
            return code;
2817
5.38k
        cos_value_write(&value, pdev);
2818
5.38k
        gs_free_string(mem, value.contents.chars.data,
2819
5.38k
                       value.contents.chars.size,
2820
5.38k
                       "pdf_write_multiple_halftone");
2821
5.38k
        pprintld1(s, " %ld 0 R\n", ids[i]);
2822
5.38k
        last_comp = i;
2823
5.38k
    }
2824
5.38k
    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
5.38k
    stream_puts(s, ">>\n");
2834
5.38k
    gs_free_object(mem, ids, "pdf_write_multiple_halftone");
2835
5.38k
    return pdf_end_separate(pdev, resourceHalftone);
2836
5.38k
}
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
6.29k
{
2846
6.29k
    const gs_halftone *pht = pgs->halftone;
2847
6.29k
    const gx_device_halftone *pdht = pgs->dev_ht[HT_OBJTYPE_DEFAULT];
2848
6.29k
    int code;
2849
6.29k
    long id;
2850
2851
6.29k
    switch (pht->type) {
2852
904
    case ht_type_screen:
2853
904
        code = pdf_write_screen_halftone(pdev, &pht->params.screen,
2854
904
                                         &pdht->components[0].corder, &id);
2855
904
        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
5.38k
    case ht_type_multiple:
2873
5.38k
    case ht_type_multiple_colorscreen:
2874
5.38k
        code = pdf_write_multiple_halftone(pdev, (gs_gstate *)pgs, &pht->params.multiple,
2875
5.38k
                                           pdht, &id);
2876
5.38k
        break;
2877
0
    default:
2878
0
        return_error(gs_error_rangecheck);
2879
6.29k
    }
2880
6.29k
    if (code < 0)
2881
0
        return code;
2882
6.29k
    gs_snprintf(hts, hts_max, "%ld 0 R", id);
2883
6.29k
    pdev->halftone_id = pgs->dev_ht[HT_OBJTYPE_DEFAULT]->id;
2884
6.29k
    return code;
2885
6.29k
}
2886
2887
/* ------ Graphics state updating ------ */
2888
2889
static inline cos_dict_t *
2890
resource_dict(pdf_resource_t *pres)
2891
85.4k
{
2892
85.4k
    return (cos_dict_t *)pres->object;
2893
85.4k
}
2894
2895
/* Open an ExtGState. */
2896
static int
2897
pdf_open_gstate(gx_device_pdf *pdev, pdf_resource_t **ppres)
2898
42.6k
{
2899
42.6k
    int code;
2900
2901
42.6k
    if (*ppres)
2902
2.44k
        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
40.1k
    if (pdev->context != PDF_IN_STREAM) {
2909
        /* We apparently use gs_error_interrupt as a request to change context. */
2910
4.10k
      return_error(gs_error_interrupt);
2911
4.10k
    }
2912
36.0k
    code = pdf_alloc_resource(pdev, resourceExtGState, gs_no_id, ppres, -1L);
2913
36.0k
    if (code < 0)
2914
0
        return code;
2915
36.0k
    cos_become((*ppres)->object, cos_type_dict);
2916
36.0k
    code = cos_dict_put_c_key_string(resource_dict(*ppres), "/Type", (const byte *)"/ExtGState", 10);
2917
36.0k
    if (code < 0)
2918
0
        return code;
2919
36.0k
    return 0;
2920
36.0k
}
2921
2922
/* Finish writing an ExtGState. */
2923
int
2924
pdf_end_gstate(gx_device_pdf *pdev, pdf_resource_t *pres)
2925
7.19M
{
2926
7.19M
    if (pres) {
2927
36.0k
        int code = pdf_substitute_resource(pdev, &pres, resourceExtGState, NULL, true);
2928
2929
36.0k
        if (code < 0)
2930
0
            return code;
2931
36.0k
        pres->where_used |= pdev->used_mask;
2932
36.0k
        code = pdf_open_page(pdev, PDF_IN_STREAM);
2933
36.0k
        if (code < 0)
2934
0
            return code;
2935
36.0k
        code = pdf_add_resource(pdev, pdev->substream_Resources, "/ExtGState", pres);
2936
36.0k
        if (code < 0)
2937
0
            return code;
2938
36.0k
        pprinti64d1(pdev->strm, "/R%"PRId64" gs\n", pdf_resource_id(pres));
2939
36.0k
        pres->where_used |= pdev->used_mask;
2940
36.0k
    }
2941
7.19M
    return 0;
2942
7.19M
}
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
7.16M
{
2952
7.16M
    int i, pi = -1;
2953
7.16M
    bool multiple = false, update = false;
2954
7.16M
    gs_id transfer_ids[4];
2955
7.16M
    int code = 0;
2956
7.16M
    const gx_transfer_map *tm[4];
2957
2958
7.16M
    tm[0] = pgs->set_transfer.red;
2959
7.16M
    tm[1] = pgs->set_transfer.green;
2960
7.16M
    tm[2] = pgs->set_transfer.blue;
2961
7.16M
    tm[3] = pgs->set_transfer.gray;
2962
35.8M
    for (i = 0; i < 4; ++i)
2963
28.6M
        if (tm[i] != NULL) {
2964
7.16M
            transfer_ids[i] = tm[i]->id;
2965
7.16M
            if (pdev->transfer_ids[i] != tm[i]->id)
2966
12.5k
                update = true;
2967
7.16M
            if (pi != -1 && transfer_ids[i] != transfer_ids[pi])
2968
576
                multiple = true;
2969
7.16M
            pi = i;
2970
7.16M
        } else
2971
21.4M
            transfer_ids[i] = -1;
2972
7.16M
    if (update) {
2973
12.4k
        int mask;
2974
2975
12.4k
        if (!multiple) {
2976
12.4k
            code = pdf_write_transfer(pdev, tm[pi], "", trs, trs_max);
2977
12.4k
            if (code < 0)
2978
0
                return code;
2979
12.4k
            mask = code == 0;
2980
12.4k
        } else {
2981
26
            strcpy(trs, "[");
2982
26
            mask = 0;
2983
130
            for (i = 0; i < 4; ++i)
2984
104
                if (tm[i] != NULL) {
2985
104
                    int len = (int)strlen(trs);
2986
104
                    code = pdf_write_transfer_map(pdev,
2987
104
                                                  tm[i],
2988
104
                                                  0, true, " ", trs + len, trs_max - len);
2989
104
                    if (code < 0)
2990
0
                        return code;
2991
104
                    mask |= (code == 0) << i;
2992
104
                }
2993
26
            strcat(trs, "]");
2994
26
        }
2995
12.4k
        memcpy(pdev->transfer_ids, transfer_ids, sizeof(pdev->transfer_ids));
2996
12.4k
        pdev->transfer_not_identity = mask;
2997
12.4k
    }
2998
7.16M
    return code;
2999
7.16M
}
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
1.64M
{
3010
1.64M
    int code;
3011
3012
1.64M
    if (pdev->state.soft_mask_id != pgs->soft_mask_id) {
3013
137
        char buf[20];
3014
3015
137
        if (pgs->soft_mask_id == 0) {
3016
22
            code = pdf_open_contents(pdev, PDF_IN_STREAM);
3017
22
            if (code < 0)
3018
0
                return code;
3019
22
            if (pdev->vgstack_depth > pdev->vgstack_bottom) {
3020
20
                code = pdf_restore_viewer_state(pdev, pdev->strm);
3021
20
                if (code < 0)
3022
0
                    return code;
3023
20
            }
3024
22
        }
3025
115
        else{
3026
115
            gs_snprintf(buf, sizeof(buf), "%ld 0 R", pgs->soft_mask_id);
3027
115
            code = pdf_open_gstate(pdev, ppres);
3028
115
            if (code < 0)
3029
0
                return code;
3030
115
            code = cos_dict_put_c_key_string(resource_dict(*ppres),
3031
115
                        "/SMask", (byte *)buf, strlen(buf));
3032
115
            if (code < 0)
3033
0
                return code;
3034
115
            code = pdf_save_viewer_state(pdev, pdev->strm);
3035
115
            if (code < 0)
3036
0
                return code;
3037
115
        }
3038
137
        pdev->state.soft_mask_id = pgs->soft_mask_id;
3039
137
    }
3040
3041
1.64M
    if (pdev->state.alphaisshape != pgs->alphaisshape ||
3042
1.64M
        pdev->state.strokeconstantalpha != pgs->strokeconstantalpha ||
3043
1.64M
        pdev->state.fillconstantalpha != pgs->fillconstantalpha) {
3044
3045
1.72k
        code = pdf_open_gstate(pdev, ppres);
3046
1.72k
        if (code < 0)
3047
356
            return code;
3048
3049
1.36k
        code = cos_dict_put_c_key_bool(resource_dict(*ppres), "/AIS", pgs->alphaisshape);
3050
1.36k
        if (code < 0)
3051
0
            return code;
3052
1.36k
        pdev->state.alphaisshape = pgs->alphaisshape;
3053
1.36k
        code = cos_dict_put_c_key_real(resource_dict(*ppres), "/CA", pgs->strokeconstantalpha);
3054
1.36k
        if (code < 0)
3055
0
            return code;
3056
1.36k
        pdev->state.strokeconstantalpha = pgs->strokeconstantalpha;
3057
1.36k
        code = cos_dict_put_c_key_real(resource_dict(*ppres), "/ca", pgs->fillconstantalpha);
3058
1.36k
        if (code < 0)
3059
0
            return code;
3060
1.36k
        pdev->state.fillconstantalpha = pgs->fillconstantalpha;
3061
1.36k
    }
3062
1.64M
    return 0;
3063
1.64M
}
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
7.20M
{
3072
7.20M
    int code = 0;
3073
7.20M
    int bottom;
3074
3075
7.20M
    if (pdev->CompatibilityLevel >= 1.4) {
3076
1.64M
        code = pdf_update_alpha(pdev, pgs, ppres, for_text);
3077
1.64M
        if (code < 0)
3078
356
            return code;
3079
1.64M
        if (pdev->state.blend_mode != pgs->blend_mode) {
3080
1.48k
            static const char *const bm_names[] = { GS_BLEND_MODE_NAMES };
3081
1.48k
            char buf[20];
3082
3083
1.48k
            code = pdf_open_gstate(pdev, ppres);
3084
1.48k
            if (code < 0)
3085
9
                return code;
3086
1.47k
            buf[0] = '/';
3087
1.47k
            strncpy(buf + 1, bm_names[pgs->blend_mode], sizeof(buf) - 2);
3088
1.47k
            code = cos_dict_put_string_copy(resource_dict(*ppres), "/BM", buf);
3089
1.47k
            if (code < 0)
3090
0
                return code;
3091
1.47k
            pdev->state.blend_mode = pgs->blend_mode;
3092
1.47k
        }
3093
5.55M
    } else {
3094
        /*
3095
         * If the graphics state calls for any transparency functions,
3096
         * we can't represent them, so return a rangecheck.
3097
         */
3098
5.55M
        if (pgs->strokeconstantalpha != 1 ||
3099
5.55M
            pgs->fillconstantalpha != 1)
3100
9.70k
            return_error(gs_error_rangecheck);
3101
5.55M
    }
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
7.19M
    bottom = (pdev->ResourcesBeforeUsage ? 1 : 0);
3112
    /* When ResourcesBeforeUsage != 0, one sbstack element
3113
       appears from the page contents stream. */
3114
7.19M
    if (pdev->sbstack_depth == bottom) {
3115
7.16M
        gs_int_point phase, dev_phase;
3116
7.16M
        char hts[5 + MAX_FN_CHARS + 1],
3117
7.16M
            trs[5 + MAX_FN_CHARS * 4 + 6 + 1],
3118
7.16M
            bgs[5 + MAX_FN_CHARS + 1],
3119
7.16M
            ucrs[6 + MAX_FN_CHARS + 1];
3120
3121
7.16M
        hts[0] = trs[0] = bgs[0] = ucrs[0] = 0;
3122
7.16M
        if (pdev->params.PreserveHalftoneInfo &&
3123
7.16M
            pdev->halftone_id != pgs->dev_ht[HT_OBJTYPE_DEFAULT]->id &&
3124
7.16M
            pdev->PDFX == 0
3125
7.16M
            ) {
3126
6.29k
            code = pdf_update_halftone(pdev, pgs, hts, sizeof(hts));
3127
6.29k
            if (code < 0)
3128
0
                return code;
3129
6.29k
        }
3130
7.16M
        if (pdev->params.TransferFunctionInfo != tfi_Remove &&
3131
7.16M
            pdev->PDFX == 0 && pdev->PDFA == 0
3132
7.16M
            ) {
3133
7.16M
            code = pdf_update_transfer(pdev, pgs, trs, sizeof(trs));
3134
7.16M
            if (code < 0)
3135
0
                return code;
3136
7.16M
        }
3137
7.16M
        if (pdev->params.UCRandBGInfo == ucrbg_Preserve) {
3138
7.16M
            if (pgs->black_generation && pdev->black_generation_id != pgs->black_generation->id) {
3139
3.73k
                code = pdf_write_transfer_map(pdev, pgs->black_generation,
3140
3.73k
                                              0, false, "", bgs, sizeof(bgs));
3141
3.73k
                if (code < 0)
3142
0
                    return code;
3143
3.73k
                pdev->black_generation_id = pgs->black_generation->id;
3144
3.73k
            }
3145
7.16M
            if (pgs->undercolor_removal && pdev->undercolor_removal_id != pgs->undercolor_removal->id) {
3146
3.72k
                code = pdf_write_transfer_map(pdev, pgs->undercolor_removal,
3147
3.72k
                                              -1, false, "", ucrs, sizeof(ucrs));
3148
3.72k
                if (code < 0)
3149
0
                    return code;
3150
3.72k
                pdev->undercolor_removal_id = pgs->undercolor_removal->id;
3151
3.72k
            }
3152
7.16M
        }
3153
7.16M
        if (hts[0] || trs[0] || bgs[0] || ucrs[0]) {
3154
19.0k
            code = pdf_open_gstate(pdev, ppres);
3155
19.0k
            if (code < 0)
3156
1.83k
                return code;
3157
19.0k
        }
3158
7.16M
        if (hts[0]) {
3159
6.29k
            code = cos_dict_put_string_copy(resource_dict(*ppres), "/HT", hts);
3160
6.29k
            if (code < 0)
3161
0
                return code;
3162
6.29k
        }
3163
7.16M
        if (pdev->CompatibilityLevel <= 1.7 && trs[0] && pdev->params.TransferFunctionInfo == tfi_Preserve) {
3164
10.6k
            code = cos_dict_put_string_copy(resource_dict(*ppres), "/TR", trs);
3165
10.6k
            if (code < 0)
3166
0
                return code;
3167
10.6k
        }
3168
7.16M
        if (bgs[0]) {
3169
3.65k
            code = cos_dict_put_string_copy(resource_dict(*ppres), "/BG", bgs);
3170
3.65k
            if (code < 0)
3171
0
                return code;
3172
3.65k
        }
3173
7.16M
        if (ucrs[0]) {
3174
3.64k
            code = cos_dict_put_string_copy(resource_dict(*ppres), "/UCR", ucrs);
3175
3.64k
            if (code < 0)
3176
0
                return code;
3177
3.64k
        }
3178
7.16M
        if (pdev->PDFX == 0) {
3179
7.16M
            gs_currentscreenphase(pgs, &phase, 0);
3180
7.16M
            gs_currentscreenphase(&pdev->state, &dev_phase, 0);
3181
7.16M
            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
7.16M
            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
7.16M
        }
3226
7.16M
    }
3227
7.19M
    if (pdev->state.overprint_mode != pdev->params.OPM) {
3228
281
        if (pdev->params.OPM != pgs->overprint_mode)
3229
90
            ((gs_gstate *)pgs)->overprint_mode = pdev->params.OPM;
3230
281
    }
3231
7.19M
    if (pdev->CompatibilityLevel >= 1.3 /*&& pdev->sbstack_depth == bottom */) {
3232
1.64M
        if (pdev->state.overprint_mode != pgs->overprint_mode) {
3233
3.25k
            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
3.25k
            if (pdev->state.overprint_mode != pgs->overprint_mode) {
3261
3.25k
                code = pdf_open_gstate(pdev, ppres);
3262
3.25k
                if (code < 0)
3263
269
                    return code;
3264
2.98k
                code = cos_dict_put_c_key_int(resource_dict(*ppres), "/OPM", pgs->overprint_mode);
3265
2.98k
                if (code < 0)
3266
0
                    return code;
3267
2.98k
                pdev->params.OPM = pdev->state.overprint_mode = pgs->overprint_mode;
3268
2.98k
            }
3269
3.25k
        }
3270
1.64M
        if (pdev->state.smoothness != pgs->smoothness) {
3271
50
            code = pdf_open_gstate(pdev, ppres);
3272
50
            if (code < 0)
3273
12
                return code;
3274
38
            code = cos_dict_put_c_key_real(resource_dict(*ppres), "/SM", pgs->smoothness);
3275
38
            if (code < 0)
3276
0
                return code;
3277
38
            pdev->state.smoothness = pgs->smoothness;
3278
38
        }
3279
1.64M
        if (pdev->CompatibilityLevel >= 1.4) {
3280
1.64M
            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
1.64M
        }
3290
1.64M
    }
3291
7.19M
    return code;
3292
7.19M
}
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
6.53M
{
3298
6.53M
    pdf_resource_t *pres = 0;
3299
6.53M
    int code = pdf_prepare_drawing(pdev, pgs, &pres, for_text);
3300
3301
6.53M
    if (code < 0)
3302
10.7k
        return code;
3303
6.52M
    if (pdev->rendering_intent != pgs->renderingintent && !pdev->ForOPDFRead) {
3304
5.92k
        static const char *const ri_names[] = { "Perceptual", "RelativeColorimetric", "Saturation", "AbsoluteColorimetric" };
3305
5.92k
        char buf[32];
3306
3307
5.92k
        code = pdf_open_gstate(pdev, &pres);
3308
5.92k
        if (code < 0)
3309
103
            return code;
3310
3311
5.82k
        buf[0] = '/';
3312
5.82k
        strncpy(buf + 1, ri_names[pgs->renderingintent], sizeof(buf) - 2);
3313
5.82k
        code = cos_dict_put_string_copy(resource_dict(pres), "/RI", buf);
3314
5.82k
        if (code < 0)
3315
0
            return code;
3316
5.82k
        pdev->rendering_intent = pgs->renderingintent;
3317
5.82k
    }
3318
3319
    /* Update overprint. */
3320
6.52M
    if (pdev->params.PreserveOverprintSettings &&
3321
6.52M
        (pdev->fill_overprint != pgs->overprint ||
3322
6.52M
        pdev->font3) &&  !pdev->skip_colors
3323
6.52M
        ) {
3324
9.43k
        if (pres == 0)
3325
8.39k
            code = pdf_open_gstate(pdev, &pres);
3326
9.43k
        if (code < 0)
3327
1.44k
            return code;
3328
        /* PDF 1.2 only has a single overprint setting. */
3329
7.99k
        if (pdev->CompatibilityLevel < 1.3) {
3330
3.26k
            code = cos_dict_put_c_key_bool(resource_dict(pres), "/OP", pgs->overprint);
3331
3.26k
            if (code < 0)
3332
0
                return code;
3333
3.26k
            pdev->stroke_overprint = pgs->overprint;
3334
4.72k
        } else {
3335
4.72k
            code = cos_dict_put_c_key_bool(resource_dict(pres), "/op", pgs->overprint);
3336
4.72k
            if (code < 0)
3337
0
                return code;
3338
4.72k
        }
3339
7.99k
        pdev->fill_overprint = pgs->overprint;
3340
7.99k
    }
3341
6.52M
    return pdf_end_gstate(pdev, pres);
3342
6.52M
}
3343
int
3344
pdf_prepare_fill(gx_device_pdf *pdev, const gs_gstate *pgs, bool for_text)
3345
6.52M
{
3346
6.52M
    int code;
3347
3348
6.52M
    if (pdev->context != PDF_IN_STREAM) {
3349
4.96M
        code = pdf_try_prepare_fill(pdev, pgs, for_text);
3350
4.96M
        if (code != gs_error_interrupt) /* See pdf_open_gstate */
3351
4.96M
            return code;
3352
3.68k
        code = pdf_open_contents(pdev, PDF_IN_STREAM);
3353
3.68k
        if (code < 0)
3354
0
            return code;
3355
3.68k
    }
3356
1.56M
    return pdf_try_prepare_fill(pdev, pgs, for_text);
3357
6.52M
}
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
665k
{
3363
665k
    pdf_resource_t *pres = 0;
3364
665k
    int code = pdf_prepare_drawing(pdev, pgs, &pres, for_text);
3365
3366
665k
    if (code < 0)
3367
1.13k
        return code;
3368
663k
    if (pdev->rendering_intent != pgs->renderingintent && !pdev->ForOPDFRead) {
3369
92
        static const char *const ri_names[] = { "Perceptual", "RelativeColorimetric", "Saturation", "AbsoluteColorimetric" };
3370
92
        char buf[32];
3371
3372
92
        code = pdf_open_gstate(pdev, &pres);
3373
92
        if (code < 0)
3374
0
            return code;
3375
3376
92
        buf[0] = '/';
3377
92
        strncpy(buf + 1, ri_names[pgs->renderingintent], sizeof(buf) - 2);
3378
92
        code = cos_dict_put_string_copy(resource_dict(pres), "/RI", buf);
3379
92
        if (code < 0)
3380
0
            return code;
3381
92
        pdev->rendering_intent = pgs->renderingintent;
3382
92
    }
3383
    /* Update overprint, stroke adjustment. */
3384
663k
    if (pdev->params.PreserveOverprintSettings &&
3385
663k
        pdev->stroke_overprint != pgs->stroke_overprint &&
3386
663k
        !pdev->skip_colors
3387
663k
        ) {
3388
341
        if (pres == 0)
3389
267
            code = pdf_open_gstate(pdev, &pres);
3390
341
        if (code < 0)
3391
0
            return code;
3392
341
        code = cos_dict_put_c_key_bool(resource_dict(pres), "/OP", pgs->stroke_overprint);
3393
341
        if (code < 0)
3394
0
            return code;
3395
341
        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
341
        pdev->fill_overprint = pgs->stroke_overprint;
3401
341
    }
3402
663k
    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
9.91k
        if (!pdev->ForOPDFRead) {
3414
1.61k
            code = pdf_open_gstate(pdev, &pres);
3415
1.61k
            if (code < 0)
3416
0
                return code;
3417
1.61k
            code = cos_dict_put_c_key_bool(resource_dict(pres), "/SA", pgs->stroke_adjust);
3418
1.61k
            if (code < 0)
3419
0
                return code;
3420
1.61k
            pdev->state.stroke_adjust = pgs->stroke_adjust;
3421
8.30k
        } else {
3422
8.30k
            if (pgs->stroke_adjust)
3423
696
                stream_puts(gdev_vector_stream((gx_device_vector *)pdev), "true setstrokeadjust\n");
3424
7.61k
            else
3425
7.61k
                stream_puts(gdev_vector_stream((gx_device_vector *)pdev), "false setstrokeadjust\n");
3426
8.30k
            pdev->state.stroke_adjust = pgs->stroke_adjust;
3427
8.30k
        }
3428
3429
9.91k
    }
3430
663k
    return pdf_end_gstate(pdev, pres);
3431
663k
}
3432
int
3433
pdf_prepare_stroke(gx_device_pdf *pdev, const gs_gstate *pgs, bool for_text)
3434
665k
{
3435
665k
    int code;
3436
3437
665k
    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
665k
    return pdf_try_prepare_stroke(pdev, pgs, for_text);
3446
665k
}
3447
3448
static int
3449
pdf_try_prepare_fill_stroke(gx_device_pdf *pdev, const gs_gstate *pgs, bool for_text)
3450
5.39k
{
3451
5.39k
    pdf_resource_t *pres = 0;
3452
5.39k
    int code = pdf_prepare_drawing(pdev, pgs, &pres, for_text);
3453
3454
5.39k
    if (code < 0)
3455
0
        return code;
3456
    /* Update overprint. */
3457
5.39k
    if (pdev->params.PreserveOverprintSettings &&
3458
5.39k
        (pdev->fill_overprint != pgs->overprint ||
3459
5.39k
         pdev->stroke_overprint != pgs->stroke_overprint ||
3460
5.39k
         pdev->font3) && !pdev->skip_colors
3461
5.39k
        ) {
3462
18
        code = pdf_open_gstate(pdev, &pres);
3463
18
        if (code < 0)
3464
3
            return code;
3465
        /* PDF 1.2 only has a single overprint setting. */
3466
15
        if (pdev->CompatibilityLevel < 1.3) {
3467
10
            code = cos_dict_put_c_key_bool(resource_dict(pres), "/OP", pgs->overprint);
3468
10
            if (code < 0)
3469
0
                return code;
3470
10
            pdev->stroke_overprint = pgs->overprint;
3471
10
        } else {
3472
5
            code = cos_dict_put_c_key_bool(resource_dict(pres), "/op", pgs->overprint);
3473
5
            if (code < 0)
3474
0
                return code;
3475
5
        }
3476
15
        pdev->fill_overprint = pgs->overprint;
3477
15
    }
3478
    /* Update overprint, stroke adjustment. */
3479
5.38k
    if (pdev->params.PreserveOverprintSettings &&
3480
5.38k
        pdev->stroke_overprint != pgs->stroke_overprint &&
3481
5.38k
        !pdev->skip_colors
3482
5.38k
        ) {
3483
4
        code = pdf_open_gstate(pdev, &pres);
3484
4
        if (code < 0)
3485
0
            return code;
3486
4
        code = cos_dict_put_c_key_bool(resource_dict(pres), "/OP", pgs->stroke_overprint);
3487
4
        if (code < 0)
3488
0
            return code;
3489
4
        pdev->stroke_overprint = pgs->stroke_overprint;
3490
4
        if (pdev->CompatibilityLevel < 1.3) {
3491
            /* PDF 1.2 only has a single overprint setting. */
3492
0
            pdev->fill_overprint = pgs->stroke_overprint;
3493
4
        } 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
4
            pdev->fill_overprint = pgs->overprint;
3498
4
        }
3499
4
    }
3500
5.38k
    if (pdev->state.stroke_adjust != pgs->stroke_adjust) {
3501
665
        code = pdf_open_gstate(pdev, &pres);
3502
665
        if (code < 0)
3503
77
            return code;
3504
588
        code = cos_dict_put_c_key_bool(resource_dict(pres), "/SA", pgs->stroke_adjust);
3505
588
        if (code < 0)
3506
0
            return code;
3507
588
        pdev->state.stroke_adjust = pgs->stroke_adjust;
3508
588
    }
3509
5.31k
    return pdf_end_gstate(pdev, pres);
3510
5.38k
}
3511
3512
int
3513
pdf_prepare_fill_stroke(gx_device_pdf *pdev, const gs_gstate *pgs, bool for_text)
3514
5.31k
{
3515
5.31k
    int code;
3516
3517
5.31k
    if (pdev->context != PDF_IN_STREAM) {
3518
481
        code = pdf_try_prepare_fill_stroke(pdev, pgs, for_text);
3519
481
        if (code != gs_error_interrupt) /* See pdf_open_gstate */
3520
401
            return code;
3521
80
        code = pdf_open_contents(pdev, PDF_IN_STREAM);
3522
80
        if (code < 0)
3523
0
            return code;
3524
80
    }
3525
4.91k
    return pdf_try_prepare_fill_stroke(pdev, pgs, for_text);
3526
5.31k
}
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
72.4k
{
3532
    /*
3533
     * As it turns out, this requires updating the same parameters as for
3534
     * filling.
3535
     */
3536
72.4k
    return pdf_prepare_fill(pdev, pgs, false);
3537
72.4k
}
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.2k
{
3544
56.2k
    int code = pdf_prepare_image(pdev, pgs);
3545
3546
56.2k
    if (code < 0)
3547
0
        return code;
3548
56.2k
    return pdf_set_drawing_color(pdev, pgs, pdcolor, &pdev->saved_fill_color,
3549
56.2k
                                 &pdev->fill_used_process_color,
3550
56.2k
                                 &psdf_set_fill_color_commands);
3551
56.2k
}