Coverage Report

Created: 2025-08-28 07:06

/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
659k
{
61
659k
    const int i = pdev->vgstack_depth;
62
63
659k
    if (pdev->vgstack_depth >= pdev->vgstack_size) {
64
4
        pdf_viewer_state *new_vgstack = (pdf_viewer_state *)gs_alloc_bytes(pdev->pdf_memory,
65
4
            (size_t)(pdev->vgstack_size + 5) * sizeof(pdf_viewer_state), "increase graphics state stack size");
66
4
        if (new_vgstack == 0)
67
0
            return_error(gs_error_VMerror);
68
4
        memset(new_vgstack, 0x00, (pdev->vgstack_size + 5) * sizeof(pdf_viewer_state));
69
4
        memcpy(new_vgstack, pdev->vgstack, pdev->vgstack_size * sizeof(pdf_viewer_state));
70
4
        gs_free_object(pdev->pdf_memory, pdev->vgstack, "resize graphics state stack, free old stack)");
71
4
        pdev->vgstack = new_vgstack;
72
4
        pdev->vgstack_size += 5;
73
4
    }
74
75
659k
    pdev->vgstack[i].transfer_ids[0] = pdev->transfer_ids[0];
76
659k
    pdev->vgstack[i].transfer_ids[1] = pdev->transfer_ids[1];
77
659k
    pdev->vgstack[i].transfer_ids[2] = pdev->transfer_ids[2];
78
659k
    pdev->vgstack[i].transfer_ids[3] = pdev->transfer_ids[3];
79
659k
    pdev->vgstack[i].transfer_not_identity = pdev->transfer_not_identity;
80
659k
    pdev->vgstack[i].strokeconstantalpha = pdev->state.strokeconstantalpha;
81
659k
    pdev->vgstack[i].fillconstantalpha = pdev->state.fillconstantalpha;
82
659k
    pdev->vgstack[i].alphaisshape = pdev->state.alphaisshape;
83
659k
    pdev->vgstack[i].blend_mode = pdev->state.blend_mode;
84
659k
    pdev->vgstack[i].halftone_id = pdev->halftone_id;
85
659k
    pdev->vgstack[i].black_generation_id = pdev->black_generation_id;
86
659k
    pdev->vgstack[i].undercolor_removal_id = pdev->undercolor_removal_id;
87
659k
    pdev->vgstack[i].overprint_mode = pdev->state.overprint_mode;
88
659k
    pdev->vgstack[i].smoothness = pdev->state.smoothness;
89
659k
    pdev->vgstack[i].flatness = pdev->state.flatness;
90
659k
    pdev->vgstack[i].text_knockout = pdev->state.text_knockout;
91
659k
    pdev->vgstack[i].fill_overprint = pdev->fill_overprint;
92
659k
    pdev->vgstack[i].stroke_overprint = pdev->stroke_overprint;
93
659k
    pdev->vgstack[i].stroke_adjust = pdev->state.stroke_adjust;
94
659k
    pdev->vgstack[i].fill_used_process_color = pdev->fill_used_process_color;
95
659k
    pdev->vgstack[i].stroke_used_process_color = pdev->stroke_used_process_color;
96
659k
    pdev->vgstack[i].saved_fill_color = pdev->saved_fill_color;
97
659k
    pdev->vgstack[i].saved_stroke_color = pdev->saved_stroke_color;
98
659k
    pdev->vgstack[i].line_params = pdev->state.line_params;
99
659k
    pdev->vgstack[i].line_params.dash.pattern = 0; /* Use pdev->dash_pattern instead. */
100
659k
    pdev->vgstack[i].soft_mask_id = pdev->state.soft_mask_id; /* Use pdev->dash_pattern instead. */
101
659k
    if (pdev->dash_pattern) {
102
18.5k
        if (pdev->vgstack[i].dash_pattern)
103
17.7k
            gs_free_object(pdev->memory->non_gc_memory, pdev->vgstack[i].dash_pattern, "free gstate copy dash");
104
18.5k
        pdev->vgstack[i].dash_pattern = (float *)gs_alloc_bytes(pdev->memory->non_gc_memory, (size_t)pdev->dash_pattern_size * sizeof(float), "gstate copy dash");
105
18.5k
        if (pdev->vgstack[i].dash_pattern == NULL)
106
0
            return_error(gs_error_VMerror);
107
18.5k
        memcpy(pdev->vgstack[i].dash_pattern, pdev->dash_pattern, pdev->dash_pattern_size * sizeof(float));
108
18.5k
        pdev->vgstack[i].dash_pattern_size = pdev->dash_pattern_size;
109
640k
    } else {
110
640k
        if (pdev->vgstack[i].dash_pattern) {
111
449
            gs_free_object(pdev->memory->non_gc_memory, pdev->vgstack[i].dash_pattern, "free gstate copy dash");
112
449
            pdev->vgstack[i].dash_pattern = 0;
113
449
            pdev->vgstack[i].dash_pattern_size = 0;
114
449
        }
115
640k
    }
116
659k
    pdev->vgstack_depth++;
117
659k
    if (s)
118
424k
        stream_puts(s, "q\n");
119
659k
    return 0;
120
659k
}
121
122
/* Load the viewer's graphic state. */
123
static int
124
pdf_load_viewer_state(gx_device_pdf *pdev, pdf_viewer_state *s)
125
1.18M
{
126
1.18M
    pdev->transfer_ids[0] = s->transfer_ids[0];
127
1.18M
    pdev->transfer_ids[1] = s->transfer_ids[1];
128
1.18M
    pdev->transfer_ids[2] = s->transfer_ids[2];
129
1.18M
    pdev->transfer_ids[3] = s->transfer_ids[3];
130
1.18M
    pdev->transfer_not_identity = s->transfer_not_identity;
131
1.18M
    pdev->state.strokeconstantalpha = s->strokeconstantalpha;
132
1.18M
    pdev->state.fillconstantalpha = s->fillconstantalpha;
133
1.18M
    pdev->state.alphaisshape = s->alphaisshape;
134
1.18M
    pdev->state.blend_mode = s->blend_mode;
135
1.18M
    pdev->halftone_id = s->halftone_id;
136
1.18M
    pdev->black_generation_id = s->black_generation_id;
137
1.18M
    pdev->undercolor_removal_id = s->undercolor_removal_id;
138
1.18M
    pdev->state.overprint_mode = s->overprint_mode;
139
1.18M
    pdev->state.smoothness = s->smoothness;
140
1.18M
    pdev->state.flatness = s->flatness;
141
1.18M
    pdev->state.text_knockout = s->text_knockout;
142
1.18M
    pdev->fill_overprint = s->fill_overprint;
143
1.18M
    pdev->stroke_overprint = s->stroke_overprint;
144
1.18M
    pdev->state.stroke_adjust = s->stroke_adjust;
145
1.18M
    pdev->fill_used_process_color = s->fill_used_process_color;
146
1.18M
    pdev->stroke_used_process_color = s->stroke_used_process_color;
147
1.18M
    pdev->saved_fill_color = s->saved_fill_color;
148
1.18M
    pdev->saved_stroke_color = s->saved_stroke_color;
149
1.18M
    pdev->state.line_params = s->line_params;
150
1.18M
    pdev->state.soft_mask_id = s->soft_mask_id;
151
1.18M
    if (s->dash_pattern) {
152
18.5k
        if (pdev->dash_pattern)
153
18.5k
            gs_free_object(pdev->memory->stable_memory, pdev->dash_pattern, "vector free dash pattern");
154
18.5k
        pdev->dash_pattern = (float *)gs_alloc_bytes(pdev->memory->stable_memory, (size_t)s->dash_pattern_size * sizeof(float), "vector allocate dash pattern");
155
18.5k
        if (pdev->dash_pattern == NULL)
156
0
            return_error(gs_error_VMerror);
157
18.5k
        memcpy(pdev->dash_pattern, s->dash_pattern, sizeof(float)*s->dash_pattern_size);
158
18.5k
        pdev->dash_pattern_size  = s->dash_pattern_size;
159
1.16M
    } else {
160
1.16M
        if (pdev->dash_pattern) {
161
4.02k
            gs_free_object(pdev->memory->stable_memory, pdev->dash_pattern, "vector free dash pattern");
162
4.02k
            pdev->dash_pattern = 0;
163
4.02k
            pdev->dash_pattern_size = 0;
164
4.02k
        }
165
1.16M
    }
166
1.18M
    return 0;
167
1.18M
}
168
169
/* Restore the viewer's graphic state. */
170
int
171
pdf_restore_viewer_state(gx_device_pdf *pdev, stream *s)
172
659k
{
173
659k
    const int i = --pdev->vgstack_depth;
174
175
659k
    if (i < pdev->vgstack_bottom || i < 0) {
176
10
        if ((pdev->ObjectFilter & FILTERIMAGE) == 0)
177
10
            return_error(gs_error_unregistered); /* Must not happen. */
178
0
        else
179
0
            return 0;
180
10
    }
181
659k
    if (s)
182
424k
        stream_puts(s, "Q\n");
183
659k
    return pdf_load_viewer_state(pdev, pdev->vgstack + i);
184
659k
}
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
100k
{
192
100k
    gx_device_color black;
193
194
100k
    pdev->black = gx_device_black((gx_device *)pdev);
195
100k
    pdev->white = gx_device_white((gx_device *)pdev);
196
100k
    set_nonclient_dev_color(&black, pdev->black);
197
100k
    gx_hld_save_color(NULL, &black, saved_fill_color);
198
100k
    gx_hld_save_color(NULL, &black, saved_stroke_color);
199
100k
    *fill_used_process_color = true;
200
100k
    *stroke_used_process_color = true;
201
100k
}
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
240k
{
207
240k
    pvs->transfer_not_identity =
208
240k
            (pgs->set_transfer.red   != NULL ? pgs->set_transfer.red->proc   != gs_identity_transfer : 0) * 1 +
209
240k
            (pgs->set_transfer.green != NULL ? pgs->set_transfer.green->proc != gs_identity_transfer : 0) * 2 +
210
240k
            (pgs->set_transfer.blue  != NULL ? pgs->set_transfer.blue->proc  != gs_identity_transfer : 0) * 4 +
211
240k
            (pgs->set_transfer.gray  != NULL ? pgs->set_transfer.gray->proc  != gs_identity_transfer : 0) * 8;
212
240k
    pvs->transfer_ids[0] = (pgs->set_transfer.red != NULL ? pgs->set_transfer.red->id : 0);
213
240k
    pvs->transfer_ids[1] = (pgs->set_transfer.green != NULL ? pgs->set_transfer.green->id : 0);
214
240k
    pvs->transfer_ids[2] = (pgs->set_transfer.blue != NULL ? pgs->set_transfer.blue->id : 0);
215
240k
    pvs->transfer_ids[3] = (pgs->set_transfer.gray != NULL ? pgs->set_transfer.gray->id : 0);
216
240k
    pvs->fillconstantalpha = pgs->fillconstantalpha;
217
240k
    pvs->strokeconstantalpha = pgs->strokeconstantalpha;
218
240k
    pvs->alphaisshape = pgs->alphaisshape;
219
240k
    pvs->blend_mode = pgs->blend_mode;
220
240k
    pvs->halftone_id = (pgs->dev_ht[HT_OBJTYPE_DEFAULT] != NULL ? pgs->dev_ht[HT_OBJTYPE_DEFAULT]->id : 0);
221
240k
    pvs->black_generation_id = (pgs->black_generation != NULL ? pgs->black_generation->id : 0);
222
240k
    pvs->undercolor_removal_id = (pgs->undercolor_removal != NULL ? pgs->undercolor_removal->id : 0);
223
240k
    pvs->overprint_mode = 0;
224
240k
    pvs->flatness = pgs->flatness;
225
240k
    pvs->smoothness = pgs->smoothness;
226
240k
    pvs->text_knockout = pgs->text_knockout;
227
240k
    pvs->fill_overprint = false;
228
240k
    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
240k
    pvs->stroke_adjust = -1;
237
240k
    pvs->line_params.half_width = 0.5;
238
240k
    pvs->line_params.start_cap = 0;
239
240k
    pvs->line_params.end_cap = 0;
240
240k
    pvs->line_params.dash_cap = 0;
241
240k
    pvs->line_params.join = 0;
242
240k
    pvs->line_params.curve_join = 0;
243
240k
    pvs->line_params.miter_limit = 10.0;
244
240k
    pvs->line_params.miter_check = 0;
245
240k
    pvs->line_params.dot_length = pgs->line_params.dot_length;
246
240k
    pvs->line_params.dot_length_absolute = pgs->line_params.dot_length_absolute;
247
240k
    pvs->line_params.dot_orientation = pgs->line_params.dot_orientation;
248
240k
    memset(&pvs->line_params.dash, 0 , sizeof(pvs->line_params.dash));
249
240k
    pvs->dash_pattern = 0;
250
240k
    pvs->dash_pattern_size = 0;
251
240k
    pvs->soft_mask_id = pgs->soft_mask_id;
252
240k
}
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
190k
{
259
190k
    pdf_viewer_state vs;
260
261
190k
    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
190k
    gx_hld_save_color(pgs, pdevc, &vs.saved_fill_color);
265
190k
    gx_hld_save_color(pgs, pdevc, &vs.saved_stroke_color);
266
190k
    vs.fill_used_process_color = 0;
267
190k
    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
190k
    (void)pdf_load_viewer_state(pdev, &vs);
271
190k
}
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
50.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
50.0k
    pdf_set_initial_color(pdev, &pdev->vg_initial.saved_fill_color, &pdev->vg_initial.saved_stroke_color,
285
50.0k
            &pdev->vg_initial.fill_used_process_color, &pdev->vg_initial.stroke_used_process_color);
286
50.0k
    pdf_viewer_state_from_gs_gstate_aux(&pdev->vg_initial, pgs);
287
50.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
50.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
50.0k
{
300
301
50.0k
    pdf_set_initial_color(pdev, &pdev->saved_fill_color, &pdev->saved_stroke_color,
302
50.0k
                                &pdev->fill_used_process_color, &pdev->stroke_used_process_color);
303
50.0k
    pdev->state.flatness = -1;
304
50.0k
    {
305
50.0k
        static const gx_line_params lp_initial = {
306
50.0k
            gx_line_params_initial
307
50.0k
        };
308
309
50.0k
        pdev->state.line_params = lp_initial;
310
50.0k
    }
311
50.0k
    pdev->fill_overprint = false;
312
50.0k
    pdev->stroke_overprint = false;
313
50.0k
    pdev->remap_fill_color = false;
314
50.0k
    pdev->remap_stroke_color = false;
315
50.0k
    pdf_reset_text(pdev);
316
50.0k
}
317
318
/* Reset the graphics state parameters to initial values. */
319
void
320
pdf_reset_graphics(gx_device_pdf * pdev)
321
380k
{
322
380k
    int soft_mask_id = pdev->state.soft_mask_id;
323
324
380k
    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
330k
        (void)pdf_load_viewer_state(pdev, &pdev->vg_initial);
328
50.0k
    else
329
50.0k
        pdf_reset_graphics_old(pdev);
330
380k
    pdf_reset_text(pdev);
331
332
    /* Not obvious, we want to preserve any extant soft mask, not reset it */
333
380k
    pdev->state.soft_mask_id = soft_mask_id;
334
380k
}
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
1.35M
{
341
1.35M
    int i, n = gx_hld_get_number_color_components(pgs);
342
343
1.35M
    pprintg1(pdev->strm, "%g", psdf_round(pcc->paint.values[0], 255, 8));
344
3.43M
    for (i = 1; i < n; i++) {
345
2.08M
        pprintg1(pdev->strm, " %g", psdf_round(pcc->paint.values[i], 255, 8));
346
2.08M
    }
347
1.35M
    return 0;
348
1.35M
}
349
350
static inline bool
351
is_cspace_allowed_in_strategy(gx_device_pdf * pdev, gs_color_space_index csi)
352
11.7k
{
353
11.7k
    if (pdev->params.ColorConversionStrategy == ccs_CMYK &&
354
11.7k
            csi != gs_color_space_index_DeviceCMYK &&
355
11.7k
            csi != gs_color_space_index_DeviceGray)
356
0
        return false;
357
11.7k
    if (pdev->params.ColorConversionStrategy == ccs_sRGB &&
358
11.7k
            csi != gs_color_space_index_DeviceRGB &&
359
11.7k
            csi != gs_color_space_index_DeviceGray)
360
0
        return false;
361
11.7k
    if (pdev->params.ColorConversionStrategy == ccs_RGB &&
362
11.7k
            csi != gs_color_space_index_DeviceRGB &&
363
11.7k
            csi != gs_color_space_index_DeviceGray)
364
0
        return false;
365
11.7k
    if (pdev->params.ColorConversionStrategy == ccs_Gray &&
366
11.7k
            csi != gs_color_space_index_DeviceGray)
367
0
        return false;
368
11.7k
    return true;
369
11.7k
}
370
371
static inline bool
372
is_pattern2_allowed_in_strategy(gx_device_pdf * pdev, const gx_drawing_color *pdc)
373
11.7k
{
374
11.7k
    const gs_color_space *pcs2 = gx_dc_pattern2_get_color_space(pdc);
375
11.7k
    gs_color_space_index csi = gs_color_space_get_index(pcs2);
376
377
11.7k
    if (csi == gs_color_space_index_ICC)
378
2.75k
        csi = gsicc_get_default_type(pcs2->cmm_icc_profile_data);
379
380
11.7k
    return is_cspace_allowed_in_strategy(pdev, csi);
381
11.7k
}
382
383
384
static int apply_transfer_gray(gx_device_pdf * pdev, const gs_gstate * pgs, gs_client_color *pcc, gs_client_color *cc)
385
0
{
386
0
    unsigned short psrc[GS_CLIENT_COLOR_MAX_COMPONENTS];
387
0
    frac conc[GS_CLIENT_COLOR_MAX_COMPONENTS];
388
0
    gx_device_color dc;
389
0
    const gs_color_space *pcs = gs_currentcolorspace_inline(pgs);
390
0
    int code, color_index;
391
392
0
    color_index = pdev->pcm_color_info_index;
393
0
    pdf_set_process_color_model(pdev, 0);
394
0
    psrc[0] = (unsigned short) (pcc->paint.values[0]*65535.0);;
395
0
    conc[0] = ushort2frac(psrc[0]);
396
397
0
    code = gx_remap_concrete_DGray(pcs, (const frac *)&conc, &dc, pgs, (gx_device *)pdev, gs_color_select_texture, NULL);
398
0
    if (code < 0)
399
0
        return code;
400
401
0
    cc->paint.values[0] = (dc.colors.pure & 0xff) / 255.0;
402
0
    pdf_set_process_color_model(pdev, color_index);
403
0
    return 0;
404
0
}
405
406
static int apply_transfer_rgb(gx_device_pdf * pdev, const gs_gstate * pgs, gs_client_color *pcc, gs_client_color *cc)
407
12
{
408
12
    unsigned short psrc[GS_CLIENT_COLOR_MAX_COMPONENTS];
409
12
    frac conc[GS_CLIENT_COLOR_MAX_COMPONENTS];
410
12
    gx_device_color dc;
411
12
    const gs_color_space *pcs = gs_currentcolorspace_inline(pgs);
412
12
    int code, i, color_index;
413
414
12
    color_index = pdev->pcm_color_info_index;
415
12
    pdf_set_process_color_model(pdev, 1);
416
48
    for (i=0;i<3;i++) {
417
36
        psrc[i] = (unsigned short) (pcc->paint.values[i]*65535.0);;
418
36
        conc[i] = ushort2frac(psrc[i]);
419
36
    }
420
12
    code = gx_remap_concrete_DRGB(pcs, (const frac *)&conc, &dc, pgs, (gx_device *)pdev, gs_color_select_texture, NULL);
421
12
    if (code < 0)
422
0
        return code;
423
424
12
    cc->paint.values[0] = ((dc.colors.pure & 0xff0000) >> 16) / 255.0;
425
12
    cc->paint.values[1] = ((dc.colors.pure & 0xff00) >> 8) / 255.0;
426
12
    cc->paint.values[2] = (dc.colors.pure & 0xff) / 255.0;
427
12
    pdf_set_process_color_model(pdev, color_index);
428
12
    return 0;
429
12
}
430
431
static int apply_transfer_cmyk(gx_device_pdf * pdev, const gs_gstate * pgs, gs_client_color *pcc, gs_client_color *cc)
432
0
{
433
0
    unsigned short psrc[GS_CLIENT_COLOR_MAX_COMPONENTS];
434
0
    frac conc[GS_CLIENT_COLOR_MAX_COMPONENTS];
435
0
    gx_device_color dc;
436
0
    const gs_color_space *pcs = gs_currentcolorspace_inline(pgs);
437
0
    int code, i, color_index;
438
439
0
    color_index = pdev->pcm_color_info_index;
440
0
    pdf_set_process_color_model(pdev, 2);
441
0
    for (i=0;i<4;i++) {
442
0
        psrc[i] = (unsigned short) (pcc->paint.values[i]*65535.0);;
443
0
        conc[i] = ushort2frac(psrc[i]);
444
0
    }
445
0
    code = gx_remap_concrete_DCMYK(pcs, (const frac *)&conc, &dc, pgs, (gx_device *)pdev, gs_color_select_texture, NULL);
446
0
    if (code < 0)
447
0
        return code;
448
449
0
    cc->paint.values[0] = ((dc.colors.pure & 0xff000000) >> 24) / 255.0;
450
0
    cc->paint.values[1] = ((dc.colors.pure & 0xff0000) >> 16) / 255.0;
451
0
    cc->paint.values[2] = ((dc.colors.pure & 0xff00) >> 8) / 255.0;
452
0
    cc->paint.values[3] = (dc.colors.pure & 0xff) / 255.0;
453
0
    pdf_set_process_color_model(pdev, color_index);
454
0
    return 0;
455
0
}
456
457
static int write_color_as_process(gx_device_pdf * pdev, const gs_gstate * pgs, const gs_color_space *pcs,
458
                        const gx_drawing_color *pdc, bool *used_process_color,
459
                        const psdf_set_color_commands_t *ppscc, gs_client_color *pcc)
460
86.8k
{
461
86.8k
    int code, i;
462
86.8k
    unsigned char j;
463
86.8k
    frac conc[GS_CLIENT_COLOR_MAX_COMPONENTS];
464
86.8k
    gs_color_space_index csi, csi2;
465
86.8k
    gs_color_space *pcs2 = (gs_color_space *)pcs;
466
86.8k
    gx_drawing_color dc;
467
86.8k
    int num_des_comps;
468
86.8k
    cmm_dev_profile_t *dev_profile;
469
470
86.8k
    dc.type = gx_dc_type_pure;
471
86.8k
    dc.colors.pure = 0;
472
86.8k
    csi = gs_color_space_get_index(pcs);
473
474
86.8k
    if (csi == gs_color_space_index_ICC) {
475
86.8k
        csi = gsicc_get_default_type(pcs->cmm_icc_profile_data);
476
86.8k
    }
477
478
86.8k
    if (csi == gs_color_space_index_Indexed ||
479
86.8k
        csi == gs_color_space_index_DeviceN ||
480
86.8k
        csi == gs_color_space_index_Separation) {
481
0
        const char *command = NULL;
482
483
0
        *used_process_color = true;
484
485
0
        memset (&conc, 0x00, sizeof(frac) * GS_CLIENT_COLOR_MAX_COMPONENTS);
486
0
        pcs->type->concretize_color(pcc, pcs, conc, pgs, (gx_device *)pdev);
487
488
0
        do{
489
0
            pcs2 = pcs2->base_space;
490
0
            csi2 = gs_color_space_get_index(pcs2);
491
0
        } while(csi2 != gs_color_space_index_ICC && pcs2->base_space);
492
0
        csi2 = gs_color_space_get_index(pcs2);
493
494
0
        switch (csi2) {
495
0
            case gs_color_space_index_DeviceGray:
496
0
            case gs_color_space_index_DeviceRGB:
497
0
            case gs_color_space_index_DeviceCMYK:
498
0
                switch (pdev->color_info.num_components) {
499
0
                    case 1:
500
0
                        command = ppscc->setgray;
501
0
                        break;
502
0
                    case 3:
503
0
                        command = ppscc->setrgbcolor;
504
0
                        break;
505
0
                    case 4:
506
0
                        command = ppscc->setcmykcolor;
507
0
                        break;
508
0
                    default:
509
                        /* Can't happen since we already check the colour space */
510
0
          return_error(gs_error_rangecheck);
511
0
                }
512
0
                pprintg1(pdev->strm, "%g", psdf_round(frac2float(conc[0]), 255, 8));
513
0
                for (j = 1; j < pdev->color_info.num_components; j++) {
514
0
                    pprintg1(pdev->strm, " %g", psdf_round(frac2float(conc[j]), 255, 8));
515
0
                }
516
0
                pprints1(pdev->strm, " %s\n", command);
517
0
                return 0;
518
0
                break;
519
0
            case gs_color_space_index_CIEDEFG:
520
0
            case gs_color_space_index_CIEDEF:
521
0
            case gs_color_space_index_CIEABC:
522
0
            case gs_color_space_index_CIEA:
523
0
            case gs_color_space_index_ICC:
524
0
                code = dev_proc((gx_device *)pdev, get_profile)((gx_device *)pdev, &dev_profile);
525
0
                if (code < 0)
526
0
                    return code;
527
0
                num_des_comps = gsicc_get_device_profile_comps(dev_profile);
528
0
                for (i = 0;i < num_des_comps;i++)
529
0
                    dc.colors.pure = (dc.colors.pure << 8) + (int)(frac2float(conc[i]) * 255);
530
0
                code = psdf_set_color((gx_device_vector *)pdev, &dc, ppscc);
531
0
                return code;
532
0
                break;
533
0
            default:    /* can't happen, simply silences compiler warnings */
534
0
                break;
535
0
        }
536
86.8k
    } else {
537
86.8k
        if (csi >= gs_color_space_index_CIEDEFG &&
538
86.8k
            csi <= gs_color_space_index_CIEA) {
539
0
                memset (&conc, 0x00, sizeof(frac) * GS_CLIENT_COLOR_MAX_COMPONENTS);
540
0
                pcs->type->concretize_color(pcc, pcs, conc, pgs, (gx_device *)pdev);
541
0
                code = dev_proc((gx_device *)pdev, get_profile)((gx_device *)pdev, &dev_profile);
542
0
                if (code < 0)
543
0
                    return code;
544
0
                num_des_comps = gsicc_get_device_profile_comps(dev_profile);
545
0
                for (i = 0;i < num_des_comps;i++)
546
0
                    dc.colors.pure = (dc.colors.pure << 8) + (int)(frac2float(conc[i]) * 255);
547
0
                code = psdf_set_color((gx_device_vector *)pdev, &dc, ppscc);
548
0
                *used_process_color = true;
549
0
                return code;
550
86.8k
        } else {
551
86.8k
            memset (&conc, 0x00, sizeof(frac) * GS_CLIENT_COLOR_MAX_COMPONENTS);
552
            /* Special case handling for Lab spaces */
553
86.8k
            if (pcs->cmm_icc_profile_data->data_cs == gsCIELAB || pcs->cmm_icc_profile_data->islab) {
554
334
                gs_client_color cc;
555
                /* Get the data in a form that is concrete for the CMM */
556
334
                cc.paint.values[0] = pcc->paint.values[0] / 100.0;
557
334
                cc.paint.values[1] = (pcc->paint.values[1]+128)/255.0;
558
334
                cc.paint.values[2] = (pcc->paint.values[2]+128)/255.0;
559
334
                pcs->type->concretize_color((const gs_client_color *)&cc, pcs, conc, pgs, (gx_device *)pdev);
560
86.5k
            } else {
561
86.5k
                if (pdev->params.TransferFunctionInfo == tfi_Apply) {
562
                    /* Apply transfer functions */
563
0
                    switch(csi) {
564
0
                        case gs_color_space_index_DeviceGray:
565
0
                        case gs_color_space_index_DeviceRGB:
566
0
                        case gs_color_space_index_DeviceCMYK:
567
0
                            (*pcs->type->remap_color)((const gs_client_color *)pcc, pcs, (gx_drawing_color *)pdc, pgs, (gx_device *)pdev, 0);
568
0
                            code = psdf_set_color((gx_device_vector *)pdev, pdc, ppscc);
569
0
                            return code;
570
0
                            break;
571
0
                        default:
572
0
                            pcs->type->concretize_color(pcc, pcs, conc, pgs, (gx_device *)pdev);
573
0
                            break;
574
0
                    }
575
86.5k
                } else {
576
86.5k
                    pcs->type->concretize_color(pcc, pcs, conc, pgs, (gx_device *)pdev);
577
86.5k
                }
578
86.5k
            }
579
86.8k
            code = dev_proc((gx_device *)pdev, get_profile)((gx_device *)pdev, &dev_profile);
580
86.8k
            if (code < 0)
581
0
                return code;
582
86.8k
            num_des_comps = gsicc_get_device_profile_comps(dev_profile);
583
347k
            for (i = 0;i < num_des_comps;i++)
584
260k
                dc.colors.pure = (dc.colors.pure << 8) + (int)(frac2float(conc[i]) * 255);
585
86.8k
            code = psdf_set_color((gx_device_vector *)pdev, &dc, ppscc);
586
86.8k
            return code;
587
86.8k
        }
588
86.8k
    }
589
86.8k
    return_error(gs_error_unknownerror);
590
86.8k
}
591
592
static int write_color_unchanged(gx_device_pdf * pdev, const gs_gstate * pgs,
593
                          gs_client_color *pcc, gx_hl_saved_color *current,
594
                          gx_hl_saved_color * psc, const psdf_set_color_commands_t *ppscc,
595
                          bool *used_process_color, const gs_color_space *pcs,
596
                          const gx_drawing_color *pdc)
597
1.35M
{
598
1.35M
    gs_color_space_index csi, csi2;
599
1.35M
    int code, i;
600
1.35M
    const char *command = NULL;
601
1.35M
    gs_range_t *ranges = 0;
602
1.35M
    gs_client_color cc;
603
604
605
1.35M
    csi = csi2 = gs_color_space_get_index(pcs);
606
1.35M
    if (csi == gs_color_space_index_ICC) {
607
1.32M
        csi2 = gsicc_get_default_type(pcs->cmm_icc_profile_data);
608
1.32M
    }
609
610
1.35M
    switch (csi2) {
611
331k
        case gs_color_space_index_DeviceGray:
612
331k
            command = ppscc->setgray;
613
331k
            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
331k
            } else {
618
331k
                cc.paint.values[0] = pcc->paint.values[0];
619
331k
            }
620
331k
            code = pdf_write_ccolor(pdev, pgs, &cc);
621
331k
            if (code < 0)
622
0
                return code;
623
331k
            pprints1(pdev->strm, " %s\n", command);
624
331k
            break;
625
844k
        case gs_color_space_index_DeviceRGB:
626
844k
            command = ppscc->setrgbcolor;
627
844k
            if (pdev->params.TransferFunctionInfo == tfi_Apply) {
628
12
                code = apply_transfer_rgb(pdev, pgs, pcc, &cc);
629
12
                if (code < 0)
630
0
                    return_error(code);
631
844k
            } else {
632
3.37M
                for (i=0;i< 3;i++)
633
2.53M
                    cc.paint.values[i] = pcc->paint.values[i];
634
844k
            }
635
844k
            code = pdf_write_ccolor(pdev, pgs, &cc);
636
844k
            if (code < 0)
637
0
                return code;
638
844k
            pprints1(pdev->strm, " %s\n", command);
639
844k
            break;
640
118k
        case gs_color_space_index_DeviceCMYK:
641
118k
            command = ppscc->setcmykcolor;
642
118k
            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
118k
            } else {
647
591k
                for (i=0;i< 4;i++)
648
473k
                    cc.paint.values[i] = pcc->paint.values[i];
649
118k
            }
650
118k
            code = pdf_write_ccolor(pdev, pgs, &cc);
651
118k
            if (code < 0)
652
0
                return code;
653
118k
            pprints1(pdev->strm, " %s\n", command);
654
118k
            break;
655
56.0k
        default:
656
56.0k
            if (!gx_hld_saved_color_same_cspace(current, psc) || (csi2 >= gs_color_space_index_CIEDEFG && csi2 <= gs_color_space_index_CIEA)) {
657
35.9k
                cos_value_t cs_value;
658
659
35.9k
                code = pdf_color_space_named(pdev, pgs, &cs_value, (const gs_range_t **)&ranges, pcs,
660
35.9k
                                &pdf_color_space_names, true, NULL, 0, false);
661
                /* fixme : creates redundant PDF objects. */
662
35.9k
                if (code == gs_error_rangecheck) {
663
48
                    *used_process_color = true;
664
48
                    if (pdev->ForOPDFRead) {
665
                    /* The color space can't write to PDF. This should never happen */
666
48
                    code = psdf_set_color((gx_device_vector *)pdev, pdc, ppscc);
667
48
                    } else {
668
0
                    code = write_color_as_process(pdev, pgs, pcs, pdc, used_process_color, ppscc, pcc);
669
0
                    }
670
48
                    return code;
671
48
                }
672
35.9k
                if (code < 0)
673
0
                    return code;
674
35.9k
                code = cos_value_write(&cs_value, pdev);
675
35.9k
                if (code < 0)
676
0
                    return code;
677
35.9k
                pprints1(pdev->strm, " %s\n", ppscc->setcolorspace);
678
35.9k
                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
35.9k
                } else {
699
35.9k
                    code = pdf_write_ccolor(pdev, pgs, pcc);
700
35.9k
                }
701
35.9k
                *used_process_color = false;
702
35.9k
                if (code < 0)
703
0
                    return code;
704
35.9k
                pprints1(pdev->strm, " %s\n", ppscc->setcolorn);
705
35.9k
            } 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
20.0k
            else {
716
20.0k
                code = pdf_write_ccolor(pdev, pgs, pcc);
717
20.0k
                if (code < 0)
718
0
                    return code;
719
20.0k
                pprints1(pdev->strm, " %s\n", ppscc->setcolorn);
720
20.0k
            }
721
55.9k
            break;
722
1.35M
    }
723
1.35M
    *used_process_color = false;
724
725
1.35M
    return 0;
726
1.35M
}
727
728
static int write_color_as_process_ICC(gx_device_pdf * pdev, const gs_gstate * pgs, const gs_color_space *pcs,
729
                        const gx_drawing_color *pdc, gx_hl_saved_color * psc, bool *used_process_color,
730
                        const psdf_set_color_commands_t *ppscc, gs_client_color *pcc,
731
                        gx_hl_saved_color *current)
732
0
{
733
0
    int i, code;
734
0
    cos_value_t cs_value;
735
736
0
    if (!gx_hld_saved_color_same_cspace(current, psc)) {
737
0
        code = pdf_color_space_named(pdev, pgs, &cs_value, NULL, pcs,
738
0
                        &pdf_color_space_names, true, NULL, 0, true);
739
        /* fixme : creates redundant PDF objects. */
740
0
        if (code == gs_error_rangecheck) {
741
            /* The color space can't write to PDF. This should never happen */
742
0
            return write_color_as_process(pdev, pgs, pcs, pdc, used_process_color, ppscc, pcc);
743
0
        }
744
0
        if (code < 0)
745
0
            return code;
746
0
        code = cos_value_write(&cs_value, pdev);
747
0
        if (code < 0)
748
0
            return code;
749
0
        pprints1(pdev->strm, " %s\n", ppscc->setcolorspace);
750
0
        *used_process_color = false;
751
0
        pprintg1(pdev->strm, "%g", psdf_round(pcc->paint.values[0], 255, 8));
752
0
        for (i = 1; i < pcs->type->num_components(pcs); i++) {
753
0
            pprintg1(pdev->strm, " %g", psdf_round(pcc->paint.values[i], 255, 8));
754
0
        }
755
0
        pprints1(pdev->strm, " %s\n", ppscc->setcolorn);
756
0
    } else {
757
0
        *used_process_color = false;
758
0
        pprintg1(pdev->strm, "%g", psdf_round(pcc->paint.values[0], 255, 8));
759
0
        for (i = 1; i < pcs->type->num_components(pcs); i++) {
760
0
            pprintg1(pdev->strm, " %g", psdf_round(pcc->paint.values[i], 255, 8));
761
0
        }
762
0
        pprints1(pdev->strm, " %s\n", ppscc->setcolorn);
763
0
    }
764
0
    return 0;
765
0
}
766
767
int convert_DeviceN_alternate(gx_device_pdf * pdev, const gs_gstate * pgs, const gs_color_space *pcs,
768
                        const gx_drawing_color *pdc, bool *used_process_color,
769
                        const psdf_set_color_commands_t *ppscc, gs_client_color *pcc, cos_value_t *pvalue, bool by_name)
770
0
{
771
0
    gs_color_space_index csi;
772
0
    gs_function_t *new_pfn = 0;
773
0
    int code, i, samples=0, loop;
774
0
    cos_array_t *pca, *pca1;
775
0
    cos_value_t v;
776
0
    byte *data_buff;
777
0
    pdf_resource_t *pres = NULL;
778
0
    gs_color_space *pcs_save = NULL;
779
780
0
    csi = gs_color_space_get_index(pcs);
781
0
    if (csi == gs_color_space_index_Indexed) {
782
0
        pcs_save = (gs_color_space *)pcs;
783
0
        pcs = pcs->base_space;
784
0
    }
785
786
0
    pca = cos_array_alloc(pdev, "pdf_color_space");
787
0
    if (pca == 0)
788
0
        return_error(gs_error_VMerror);
789
790
0
    samples = (unsigned int)pow(2, pcs->params.device_n.num_components);
791
0
    data_buff = gs_alloc_bytes(pdev->memory, (unsigned int)pdev->color_info.num_components * (size_t)samples, "Convert DeviceN");
792
0
    if (data_buff == 0) {
793
0
        COS_FREE(pca, "convert DeviceN");
794
0
        return_error(gs_error_VMerror);
795
0
    }
796
0
    memset(data_buff, 0x00, (unsigned int)pdev->color_info.num_components * samples);
797
798
0
    {
799
0
        frac conc[GS_CLIENT_COLOR_MAX_COMPONENTS];
800
0
        gs_client_color cc, cc1;
801
0
        unsigned char j;
802
0
        gs_color_space *icc_space = (gs_color_space *)pcs;
803
0
        gs_color_space *devicen_space = (gs_color_space *)pcs;
804
0
        gs_color_space_index csi2;
805
806
0
        csi = gs_color_space_get_index(pcs);
807
0
        if (csi == gs_color_space_index_Indexed)
808
0
            devicen_space = pcs->base_space;
809
810
0
        do{
811
0
            icc_space = icc_space->base_space;
812
0
            csi2 = gs_color_space_get_index(icc_space);
813
0
        } while(csi2 != gs_color_space_index_ICC && icc_space->base_space);
814
815
0
        memset(&cc.paint.values, 0x00, GS_CLIENT_COLOR_MAX_COMPONENTS);
816
817
0
        devicen_space->params.device_n.use_alt_cspace = true;
818
819
0
        for (loop=0;loop < samples;loop++) {
820
0
            if (loop > 0) {
821
0
                if (cc.paint.values[0] == 0)
822
0
                    cc.paint.values[0] = 1;
823
0
                else {
824
0
                    int cascade = 0;
825
0
                    while (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
2.14M
{
1460
2.14M
    int code=0, code1=0;
1461
2.14M
    gx_hl_saved_color temp;
1462
2.14M
    gs_client_color *pcc; /* fixme: not needed due to gx_hld_get_color_component. */
1463
2.14M
    cos_value_t cs_value;
1464
2.14M
    gs_color_space_index csi;
1465
2.14M
    gs_color_space_index csi2;
1466
2.14M
    const gs_color_space *pcs, *pcs2;
1467
1468
2.14M
    if (pdev->skip_colors)
1469
0
        return 0;
1470
1471
    /* Get a copy of the current colour so we can examine it. */
1472
2.14M
    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
2.14M
    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
2.14M
    switch (gx_hld_get_color_space_and_ccolor(pgs, pdc, &pcs, (const gs_client_color **)&pcc)) {
1484
23.0k
        case pattern_color_space:
1485
23.0k
            {
1486
23.0k
                pdf_resource_t *pres;
1487
1488
23.0k
                if (pdc->type == gx_dc_type_pattern) {
1489
                    /* Can't handle tiling patterns in levels 1.0 and 1.1, and
1490
                     * unlike shading patterns we have no fallback.
1491
                     */
1492
7.92k
                    if (pdev->CompatibilityLevel < 1.2) {
1493
0
                        return_error(gs_error_undefined);
1494
0
                    }
1495
7.92k
                    code = pdf_put_colored_pattern(pdev, pdc, pcs,
1496
7.92k
                                ppscc, pgs, &pres);
1497
7.92k
                }
1498
15.1k
                else if (pdc->type == &gx_dc_pure_masked) {
1499
85
                    code = pdf_put_uncolored_pattern(pdev, pdc, pcs,
1500
85
                                ppscc, pgs, &pres);
1501
85
                    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
85
                    if (pgs->have_pattern_streams)
1510
85
                        code = pdf_write_ccolor(pdev, pgs, pcc);
1511
15.0k
                } else if (pdc->type == &gx_dc_pattern2) {
1512
15.0k
                    if (pdev->CompatibilityLevel <= 1.2)
1513
3.31k
                        return_error(gs_error_rangecheck);
1514
11.7k
                    if (!is_pattern2_allowed_in_strategy(pdev, pdc))
1515
0
                        return_error(gs_error_rangecheck);
1516
11.7k
                    code1 = pdf_put_pattern2(pdev, pgs, pdc, ppscc, &pres);
1517
11.7k
                    if (code1 < 0)
1518
0
                        return code1;
1519
11.7k
                } else
1520
0
                    return_error(gs_error_rangecheck);
1521
19.7k
                if (code < 0)
1522
0
                    return code;
1523
19.7k
                code = pdf_add_resource(pdev, pdev->substream_Resources, "/Pattern", pres);
1524
19.7k
                if (code >= 0) {
1525
19.7k
                    cos_value_write(cos_resource_value(&cs_value, pres->object), pdev);
1526
19.7k
                    pprints1(pdev->strm, " %s\n", ppscc->setcolorn);
1527
19.7k
                }
1528
0
                else {
1529
0
                    pres->where_used = 0;
1530
0
                    return code;
1531
0
                }
1532
19.7k
                *used_process_color = false;
1533
19.7k
            }
1534
0
            break;
1535
1.43M
        case non_pattern_color_space:
1536
1.43M
            pcs2 = pcs;
1537
1.43M
            csi = csi2 = gs_color_space_get_index(pcs);
1538
1.43M
            if (csi == gs_color_space_index_ICC) {
1539
1.40M
                csi2 = gsicc_get_default_type(pcs->cmm_icc_profile_data);
1540
1.40M
            }
1541
            /* Figure out what to do if we are outputting to really ancient versions of PDF */
1542
            /* NB ps2write sets CompatibilityLevel to 1.2 so we cater for it here */
1543
1.43M
            if (pdev->CompatibilityLevel <= 1.2) {
1544
1545
                /* If we have an /Indexed space, we need to look at the base space */
1546
1.06M
                if (csi2 == gs_color_space_index_Indexed) {
1547
26
                    pcs2 = pcs->base_space;
1548
26
                    csi2 = gs_color_space_get_index(pcs2);
1549
26
                }
1550
1551
1.06M
                switch (csi2) {
1552
238k
                    case gs_color_space_index_DeviceGray:
1553
238k
                        if (pdev->params.ColorConversionStrategy == ccs_LeaveColorUnchanged ||
1554
238k
                            pdev->params.ColorConversionStrategy == ccs_Gray)
1555
238k
                            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
238k
                        break;
1559
628k
                    case gs_color_space_index_DeviceRGB:
1560
628k
                        if (pdev->params.ColorConversionStrategy == ccs_LeaveColorUnchanged ||
1561
628k
                            pdev->params.ColorConversionStrategy == ccs_RGB)
1562
628k
                            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
628k
                        break;
1566
89.2k
                    case gs_color_space_index_DeviceCMYK:
1567
89.2k
                        if (pdev->params.ColorConversionStrategy == ccs_LeaveColorUnchanged ||
1568
89.2k
                            pdev->params.ColorConversionStrategy == ccs_CMYK)
1569
89.2k
                            code = write_color_unchanged(pdev, pgs, pcc, &temp, psc, ppscc, used_process_color, pcs, pdc);
1570
0
                        else
1571
0
                            code = write_color_as_process(pdev, pgs, pcs, pdc, used_process_color, ppscc, pcc);
1572
89.2k
                        break;
1573
0
                    case gs_color_space_index_CIEA:
1574
0
                    case gs_color_space_index_CIEABC:
1575
0
                    case gs_color_space_index_CIEDEF:
1576
0
                    case gs_color_space_index_CIEDEFG:
1577
0
                        if (pdev->ForOPDFRead) {
1578
0
                            switch (pdev->params.ColorConversionStrategy) {
1579
0
                                case ccs_ByObjectType:
1580
                                    /* Object type not implemented yet */
1581
0
                                case ccs_UseDeviceIndependentColorForImages:
1582
                                    /* If only correcting images, then leave unchanged */
1583
0
                                case ccs_LeaveColorUnchanged:
1584
0
                                    if (pdev->transfer_not_identity && pdev->params.TransferFunctionInfo == tfi_Apply)
1585
0
                                        code = write_color_as_process(pdev, pgs, pcs, pdc, used_process_color, ppscc, pcc);
1586
0
                                    else
1587
0
                                        code = write_color_unchanged(pdev, pgs, pcc, &temp, psc, ppscc, used_process_color, pcs, pdc);
1588
0
                                    break;
1589
0
                                default:
1590
0
                                    code = write_color_as_process(pdev, pgs, pcs, pdc, used_process_color, ppscc, pcc);
1591
0
                                    break;
1592
0
                            }
1593
0
                        }
1594
0
                        else
1595
0
                            code = write_color_as_process(pdev, pgs, pcs, pdc, used_process_color, ppscc, pcc);
1596
0
                        break;
1597
21.1k
                    case gs_color_space_index_Separation:
1598
21.1k
                        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
21.1k
                            case ccs_LeaveColorUnchanged:
1604
21.1k
                                pcs2 = pcs->base_space;
1605
21.1k
                                csi2 = gs_color_space_get_index(pcs2);
1606
21.1k
                                if (csi2 == gs_color_space_index_ICC) {
1607
21.1k
                                    csi2 = gsicc_get_default_type(pcs2->cmm_icc_profile_data);
1608
21.1k
                                }
1609
21.1k
                                if (csi2 == gs_color_space_index_ICC) {
1610
8.83k
                                    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.83k
                                        code = write_color_unchanged(pdev, pgs, pcc, &temp, psc, ppscc, used_process_color, pcs, pdc);
1632
8.83k
                                } else
1633
12.3k
                                    code = write_color_unchanged(pdev, pgs, pcc, &temp, psc, ppscc, used_process_color, pcs, pdc);
1634
21.1k
                                break;
1635
21.1k
                            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
21.1k
                        }
1643
21.1k
                        break;
1644
21.1k
                    case gs_color_space_index_DeviceN:
1645
66
                        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
66
                            case ccs_LeaveColorUnchanged:
1651
66
                                code = write_color_unchanged(pdev, pgs, pcc, &temp, psc, ppscc, used_process_color, pcs, pdc);
1652
66
                                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
66
                        }
1675
66
                        break;
1676
86.8k
                    case gs_color_space_index_ICC:
1677
                        /* Note that if csi is ICC, check to see if this was one of
1678
                           the default substitutes that we introduced for DeviceGray,
1679
                           DeviceRGB or DeviceCMYK.  If it is, then just write
1680
                           the default color.  Depending upon the flavor of PDF,
1681
                           or other options, we may want to actually have all
1682
                           the colors defined by ICC profiles and not do the following
1683
                           substituion of the Device space. */
1684
86.8k
                        csi2 = gsicc_get_default_type(pcs2->cmm_icc_profile_data);
1685
1686
86.8k
                        switch (csi2) {
1687
0
                            case gs_color_space_index_DeviceGray:
1688
0
                                if (pdev->params.ColorConversionStrategy == ccs_Gray ||
1689
0
                                    pdev->params.ColorConversionStrategy == ccs_LeaveColorUnchanged) {
1690
0
                                    code = write_color_unchanged(pdev, pgs, pcc, &temp, psc, ppscc, used_process_color, pcs, pdc);
1691
0
                                    *psc = temp;
1692
0
                                    return code;
1693
0
                                }
1694
0
                                break;
1695
0
                            case gs_color_space_index_DeviceRGB:
1696
0
                                if (pdev->params.ColorConversionStrategy == ccs_RGB ||
1697
0
                                    pdev->params.ColorConversionStrategy == ccs_LeaveColorUnchanged) {
1698
0
                                    code = write_color_unchanged(pdev, pgs, pcc, &temp, psc, ppscc, used_process_color, pcs, pdc);
1699
0
                                    *psc = temp;
1700
0
                                    return code;
1701
0
                                }
1702
0
                                break;
1703
0
                            case gs_color_space_index_DeviceCMYK:
1704
0
                                if (pdev->params.ColorConversionStrategy == ccs_CMYK ||
1705
0
                                    pdev->params.ColorConversionStrategy == ccs_LeaveColorUnchanged) {
1706
0
                                    code = write_color_unchanged(pdev, pgs, pcc, &temp, psc, ppscc, used_process_color, pcs, pdc);
1707
0
                                    *psc = temp;
1708
0
                                    return code;
1709
0
                                }
1710
0
                                break;
1711
86.8k
                            default:
1712
86.8k
                                break;
1713
86.8k
                        }
1714
                        /* Fall through if its not a device substitute, or not one we want to preserve */
1715
86.8k
                    case gs_color_space_index_DevicePixel:
1716
86.8k
                    case gs_color_space_index_Indexed:
1717
86.8k
                        code = write_color_as_process(pdev, pgs, pcs, pdc, used_process_color, ppscc, pcc);
1718
86.8k
                        break;
1719
0
                    default:
1720
0
                        return (gs_note_error(gs_error_rangecheck));
1721
0
                        break;
1722
1.06M
                }
1723
1.06M
            } else {
1724
373k
                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
373k
                    case ccs_LeaveColorUnchanged:
1730
373k
                        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
373k
                        else
1773
373k
                            code = write_color_unchanged(pdev, pgs, pcc, &temp, psc, ppscc, used_process_color, pcs, pdc);
1774
373k
                        break;
1775
373k
                    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
373k
                }
2062
373k
            }
2063
1.43M
            break;
2064
1.43M
        default: /* must not happen. */
2065
689k
        case use_process_color:
2066
689k
            code = psdf_set_color((gx_device_vector *)pdev, pdc, ppscc);
2067
689k
            if (code < 0)
2068
19.3k
                return code;
2069
670k
            *used_process_color = true;
2070
670k
            break;
2071
2.14M
    }
2072
2.12M
    *psc = temp;
2073
2.12M
    return code;
2074
2.14M
}
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
13.2M
{
2083
13.2M
    gx_hl_saved_color temp;
2084
13.2M
    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
13.2M
    if (pdev->skip_colors)
2092
11.0k
        return 0;
2093
13.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
13.1M
    if (gx_hld_saved_color_equal(&temp, psc))
2099
11.7M
        return 0;
2100
    /*
2101
     * In principle, we can set colors in either stream or text
2102
     * context.  However, since we currently enclose all text
2103
     * strings inside a gsave/grestore, this causes us to lose
2104
     * track of the color when we leave text context.  Therefore,
2105
     * we require stream context for setting colors.
2106
     */
2107
1.47M
    code = pdf_open_page(pdev, PDF_IN_STREAM);
2108
1.47M
    if (code < 0)
2109
0
        return code;
2110
2111
1.47M
    return pdf_reset_color(pdev, pgs, pdc, psc, used_process_color, ppscc);
2112
1.47M
}
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
889k
{
2119
889k
    gx_drawing_color dcolor;
2120
889k
    gx_hl_saved_color temp;
2121
889k
    int code;
2122
2123
889k
    set_nonclient_dev_color(&dcolor, color);
2124
2125
889k
    if (pdev->skip_colors)
2126
0
        return 0;
2127
889k
    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
889k
    if (gx_hld_saved_color_equal(&temp, psc))
2133
219k
        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
670k
    code = pdf_open_page(pdev, PDF_IN_STREAM);
2142
670k
    if (code < 0)
2143
0
        return code;
2144
2145
670k
    return pdf_reset_color(pdev, NULL, &dcolor, psc, used_process_color, ppscc);
2146
670k
}
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
9.03k
{
2155
9.03k
    byte *chars = gs_alloc_string(pdev->pdf_memory, len + 1,
2156
9.03k
                                  "pdf_string_to_cos_name");
2157
2158
9.03k
    if (chars == 0)
2159
0
        return_error(gs_error_VMerror);
2160
9.03k
    chars[0] = '/';
2161
9.03k
    memcpy(chars + 1, str, len);
2162
9.03k
    cos_string_value(pvalue, chars, len + 1);
2163
9.03k
    return 0;
2164
9.03k
}
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
27.4k
{
2185
27.4k
    const gx_transfer_map *map = (const gx_transfer_map *)psrc->data.str.data;
2186
27.4k
    uint i;
2187
2188
27.4k
    if (ptr)
2189
27.4k
        *ptr = buf;
2190
2.37M
    for (i = 0; i < length; ++i)
2191
2.34M
        buf[i] = frac2byte(map->values[(uint)start + i]);
2192
27.4k
    return 0;
2193
27.4k
}
2194
static int
2195
transfer_map_access_signed(const gs_data_source_t *psrc,
2196
                           ulong start, uint length,
2197
                           byte *buf, const byte **ptr)
2198
27.0k
{
2199
    /* To prevent numeric errors, we need to map 0 to an integer.
2200
     * We can't apply a general expression, because Decode isn't accessible here.
2201
     * Assuming this works for UCR only.
2202
     * Assuming the range of UCR is always [-1, 1].
2203
     * Assuming BitsPerSample = 8.
2204
     */
2205
27.0k
    const gx_transfer_map *map = (const gx_transfer_map *)psrc->data.str.data;
2206
27.0k
    uint i;
2207
2208
27.0k
    *ptr = buf;
2209
2.33M
    for (i = 0; i < length; ++i)
2210
2.30M
        buf[i] = (byte)
2211
2.30M
            ((frac2float(map->values[(uint)start + i]) + 1) * 127);
2212
27.0k
    return 0;
2213
27.0k
}
2214
static int
2215
pdf_write_transfer_map(gx_device_pdf *pdev, const gx_transfer_map *map,
2216
                       int range0, bool check_identity,
2217
                       const char *key, char *ids, int id_max)
2218
43.4k
{
2219
43.4k
    gs_memory_t *mem = pdev->pdf_memory;
2220
43.4k
    gs_function_Sd_params_t params;
2221
43.4k
    static const float domain01[2] = { 0, 1 };
2222
43.4k
    static const int size = transfer_map_size;
2223
43.4k
    float range01[2], decode[2];
2224
43.4k
    gs_function_t *pfn;
2225
43.4k
    int64_t id;
2226
43.4k
    int code;
2227
2228
43.4k
    if (map == 0) {
2229
8.53k
        *ids = 0;   /* no map */
2230
8.53k
        return 1;
2231
8.53k
    }
2232
34.8k
    if (check_identity) {
2233
        /* Check for an identity map. */
2234
16.8k
        int i;
2235
2236
16.8k
        if (map->proc == gs_identity_transfer)
2237
16.7k
            i = transfer_map_size;
2238
124
        else
2239
248
            for (i = 0; i < transfer_map_size; ++i) {
2240
248
                fixed d = map->values[i] - bits2frac(i, log2_transfer_map_size);
2241
248
                if (any_abs(d) > fixed_epsilon) /* ignore small noise */
2242
124
                    break;
2243
248
            }
2244
16.8k
        if (i == transfer_map_size) {
2245
16.7k
            strcpy(ids, key);
2246
16.7k
            strcat(ids, "/Identity");
2247
16.7k
            return 1;
2248
16.7k
        }
2249
16.8k
    }
2250
18.1k
    params.m = 1;
2251
18.1k
    params.Domain = domain01;
2252
18.1k
    params.n = 1;
2253
18.1k
    range01[0] = (float)range0, range01[1] = 1.0;
2254
18.1k
    params.Range = range01;
2255
18.1k
    params.Order = 1;
2256
18.1k
    params.DataSource.access =
2257
18.1k
        (range0 < 0 ? transfer_map_access_signed : transfer_map_access);
2258
18.1k
    params.DataSource.data.str.data = (const byte *)map; /* bogus */
2259
    /* DataSource */
2260
18.1k
    params.BitsPerSample = 8; /* could be 16 */
2261
18.1k
    params.Encode = 0;
2262
18.1k
    if (range01[0] < 0 && range01[1] > 0) {
2263
        /* This works for UCR only.
2264
         * Map 0 to an integer.
2265
         * Rather the range of UCR is always [-1, 1],
2266
         * we prefer a general expression.
2267
         */
2268
9.01k
        int r0 = (int)( -range01[0] * ((1 << params.BitsPerSample) - 1)
2269
9.01k
                        / (range01[1] - range01[0]) ); /* Round down. */
2270
9.01k
        float r1 = r0 * range01[1] / -range01[0]; /* r0 + r1 <= (1 << params.BitsPerSample) - 1 */
2271
2272
9.01k
        decode[0] = range01[0];
2273
9.01k
        decode[1] = range01[0] + (range01[1] - range01[0]) * ((1 << params.BitsPerSample) - 1)
2274
9.01k
                                    / (r0 + r1);
2275
9.01k
        params.Decode = decode;
2276
9.01k
    } else
2277
9.15k
        params.Decode = 0;
2278
18.1k
    params.Size = &size;
2279
18.1k
    code = gs_function_Sd_init(&pfn, &params, mem);
2280
18.1k
    if (code < 0)
2281
0
        return code;
2282
18.1k
    code = pdf_write_function(pdev, pfn, &id);
2283
18.1k
    gs_function_free(pfn, false, mem);
2284
18.1k
    if (code < 0)
2285
0
        return code;
2286
18.1k
    gs_snprintf(ids, id_max, "%s%s%"PRId64" 0 R", key, (key[0] && key[0] != ' ' ? " " : ""), id);
2287
18.1k
    return 0;
2288
18.1k
}
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
25.2k
{
2293
25.2k
    return pdf_write_transfer_map(pdev, map, 0, true, key, ids, id_max);
2294
25.2k
}
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
450k
  static double name(double xd, double yd) {\
2306
450k
    float x = (float)xd, y = (float)yd;\
2307
450k
    return d2f(expr);\
2308
450k
  }
gdevpdfg.c:ht_EllipseA
Line
Count
Source
2305
33.1k
  static double name(double xd, double yd) {\
2306
33.1k
    float x = (float)xd, y = (float)yd;\
2307
33.1k
    return d2f(expr);\
2308
33.1k
  }
gdevpdfg.c:ht_InvertedEllipseA
Line
Count
Source
2305
33.1k
  static double name(double xd, double yd) {\
2306
33.1k
    float x = (float)xd, y = (float)yd;\
2307
33.1k
    return d2f(expr);\
2308
33.1k
  }
gdevpdfg.c:ht_EllipseB
Line
Count
Source
2305
33.1k
  static double name(double xd, double yd) {\
2306
33.1k
    float x = (float)xd, y = (float)yd;\
2307
33.1k
    return d2f(expr);\
2308
33.1k
  }
gdevpdfg.c:ht_EllipseC
Line
Count
Source
2305
33.1k
  static double name(double xd, double yd) {\
2306
33.1k
    float x = (float)xd, y = (float)yd;\
2307
33.1k
    return d2f(expr);\
2308
33.1k
  }
gdevpdfg.c:ht_InvertedEllipseC
Line
Count
Source
2305
33.1k
  static double name(double xd, double yd) {\
2306
33.1k
    float x = (float)xd, y = (float)yd;\
2307
33.1k
    return d2f(expr);\
2308
33.1k
  }
gdevpdfg.c:ht_Line
Line
Count
Source
2305
33.1k
  static double name(double xd, double yd) {\
2306
33.1k
    float x = (float)xd, y = (float)yd;\
2307
33.1k
    return d2f(expr);\
2308
33.1k
  }
gdevpdfg.c:ht_LineX
Line
Count
Source
2305
20.9k
  static double name(double xd, double yd) {\
2306
20.9k
    float x = (float)xd, y = (float)yd;\
2307
20.9k
    return d2f(expr);\
2308
20.9k
  }
gdevpdfg.c:ht_LineY
Line
Count
Source
2305
20.9k
  static double name(double xd, double yd) {\
2306
20.9k
    float x = (float)xd, y = (float)yd;\
2307
20.9k
    return d2f(expr);\
2308
20.9k
  }
gdevpdfg.c:ht_Square
Line
Count
Source
2305
20.9k
  static double name(double xd, double yd) {\
2306
20.9k
    float x = (float)xd, y = (float)yd;\
2307
41.9k
    return d2f(expr);\
2308
20.9k
  }
gdevpdfg.c:ht_Cross
Line
Count
Source
2305
20.9k
  static double name(double xd, double yd) {\
2306
20.9k
    float x = (float)xd, y = (float)yd;\
2307
41.9k
    return d2f(expr);\
2308
20.9k
  }
gdevpdfg.c:ht_Rhomboid
Line
Count
Source
2305
20.9k
  static double name(double xd, double yd) {\
2306
20.9k
    float x = (float)xd, y = (float)yd;\
2307
20.9k
    return d2f(expr);\
2308
20.9k
  }
gdevpdfg.c:ht_DoubleDot
Line
Count
Source
2305
20.9k
  static double name(double xd, double yd) {\
2306
20.9k
    float x = (float)xd, y = (float)yd;\
2307
20.9k
    return d2f(expr);\
2308
20.9k
  }
gdevpdfg.c:ht_InvertedDoubleDot
Line
Count
Source
2305
20.9k
  static double name(double xd, double yd) {\
2306
20.9k
    float x = (float)xd, y = (float)yd;\
2307
20.9k
    return d2f(expr);\
2308
20.9k
  }
gdevpdfg.c:ht_SimpleDot
Line
Count
Source
2305
20.9k
  static double name(double xd, double yd) {\
2306
20.9k
    float x = (float)xd, y = (float)yd;\
2307
20.9k
    return d2f(expr);\
2308
20.9k
  }
gdevpdfg.c:ht_InvertedSimpleDot
Line
Count
Source
2305
20.9k
  static double name(double xd, double yd) {\
2306
20.9k
    float x = (float)xd, y = (float)yd;\
2307
20.9k
    return d2f(expr);\
2308
20.9k
  }
gdevpdfg.c:ht_CosineDot
Line
Count
Source
2305
20.9k
  static double name(double xd, double yd) {\
2306
20.9k
    float x = (float)xd, y = (float)yd;\
2307
20.9k
    return d2f(expr);\
2308
20.9k
  }
gdevpdfg.c:ht_Double
Line
Count
Source
2305
20.9k
  static double name(double xd, double yd) {\
2306
20.9k
    float x = (float)xd, y = (float)yd;\
2307
20.9k
    return d2f(expr);\
2308
20.9k
  }
gdevpdfg.c:ht_InvertedDouble
Line
Count
Source
2305
20.9k
  static double name(double xd, double yd) {\
2306
20.9k
    float x = (float)xd, y = (float)yd;\
2307
20.9k
    return d2f(expr);\
2308
20.9k
  }
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.89M
{
2318
1.89M
    float f = (float)d;
2319
1.89M
    return f;
2320
1.89M
}
2321
static double
2322
ht_Round(double xf, double yf)
2323
91.8k
{
2324
91.8k
    float x = (float)xf, y = (float)yf;
2325
91.8k
    float xabs = fabs(x), yabs = fabs(y);
2326
2327
91.8k
    if (d2f(xabs + yabs) <= 1)
2328
45.9k
        return d2f(1 - d2f(d2f(x * x) + d2f(y * y)));
2329
45.9k
    xabs -= 1, yabs -= 1;
2330
45.9k
    return d2f(d2f(d2f(xabs * xabs) + d2f(yabs * yabs)) - 1);
2331
91.8k
}
2332
static double
2333
ht_Diamond(double xf, double yf)
2334
33.1k
{
2335
33.1k
    float x = (float)xf, y = (float)yf;
2336
33.1k
    float xabs = fabs(x), yabs = fabs(y);
2337
2338
33.1k
    if (d2f(xabs + yabs) <= 0.75)
2339
13.9k
        return d2f(1 - d2f(d2f(x * x) + d2f(y * y)));
2340
19.2k
    if (d2f(xabs + yabs) <= d2f(1.23))
2341
5.29k
        return d2f(1 - d2f(d2f(d2f(0.85) * xabs) + yabs));
2342
13.9k
    xabs -= 1, yabs -= 1;
2343
13.9k
    return d2f(d2f(d2f(xabs * xabs) + d2f(yabs * yabs)) - 1);
2344
19.2k
}
2345
static double
2346
ht_Ellipse(double xf, double yf)
2347
33.1k
{
2348
33.1k
    float x = (float)xf, y = (float)yf;
2349
33.1k
    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
33.1k
    float w = (float)(d2f(d2f(3 * xabs) + d2f(4 * yabs)) - 3);
2356
2357
33.1k
    if (w < 0) {
2358
15.0k
        yabs /= 0.75;
2359
15.0k
        return d2f(1 - d2f((d2f(x * x) + d2f(yabs * yabs)) / 4));
2360
15.0k
    }
2361
18.1k
    if (w > 1) {
2362
15.0k
        xabs = 1 - xabs, yabs = d2f(1 - yabs) / 0.75;
2363
15.0k
        return d2f(d2f((d2f(xabs * xabs) + d2f(yabs * yabs)) / 4) - 1);
2364
15.0k
    }
2365
3.10k
    return d2f(0.5 - w);
2366
18.1k
}
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
167k
d2fsin_d(double x) {
2373
167k
    return d2f(gs_sin_degrees(d2f(x)));
2374
167k
}
2375
static float
2376
41.9k
d2fcos_d(double x) {
2377
41.9k
    return d2f(gs_cos_degrees(d2f(x)));
2378
41.9k
}
2379
HT_FUNC(ht_EllipseA, 1 - (x * x + 0.9 * y * y))
2380
HT_FUNC(ht_InvertedEllipseA, x * x + 0.9 * y * y - 1)
2381
HT_FUNC(ht_EllipseB, 1 - sqrt(x * x + 0.625 * y * y))
2382
HT_FUNC(ht_EllipseC, 1 - (0.9 * x * x + y * y))
2383
HT_FUNC(ht_InvertedEllipseC, 0.9 * x * x + y * y - 1)
2384
HT_FUNC(ht_Line, -fabs((x - x) + y)) /* quiet compiler (unused variable x) */
2385
HT_FUNC(ht_LineX, (y - y) + x) /* quiet compiler (unused variable y) */
2386
HT_FUNC(ht_LineY, (x - x) + y) /* quiet compiler (unused variable x) */
2387
HT_FUNC(ht_Square, -max(fabs(x), fabs(y)))
2388
HT_FUNC(ht_Cross, -min(fabs(x), fabs(y)))
2389
HT_FUNC(ht_Rhomboid, (0.9 * fabs(x) + fabs(y)) / 2)
2390
HT_FUNC(ht_DoubleDot, (d2fsin_d(x * 360) + d2fsin_d(y * 360)) / 2)
2391
HT_FUNC(ht_InvertedDoubleDot, -(d2fsin_d(x * 360) + d2fsin_d(y * 360)) / 2)
2392
HT_FUNC(ht_SimpleDot, 1 - d2f(d2f(x * x) + d2f(y * y)))
2393
HT_FUNC(ht_InvertedSimpleDot, d2f(d2f(x * x) + d2f(y * y)) - 1)
2394
HT_FUNC(ht_CosineDot, (d2fcos_d(x * 180) + d2fcos_d(y * 180)) / 2)
2395
HT_FUNC(ht_Double, (d2fsin_d(x * 180) + d2fsin_d(y * 360)) / 2)
2396
HT_FUNC(ht_InvertedDouble, -(d2fsin_d(x * 180) + d2fsin_d(y * 360)) / 2)
2397
typedef struct ht_function_s {
2398
    const char *fname;
2399
    double (*proc)(double, double);
2400
} ht_function_t;
2401
static const ht_function_t ht_functions[] = {
2402
    {"Round", ht_Round},
2403
    {"Diamond", ht_Diamond},
2404
    {"Ellipse", ht_Ellipse},
2405
    {"EllipseA", ht_EllipseA},
2406
    {"InvertedEllipseA", ht_InvertedEllipseA},
2407
    {"EllipseB", ht_EllipseB},
2408
    {"EllipseC", ht_EllipseC},
2409
    {"InvertedEllipseC", ht_InvertedEllipseC},
2410
    {"Line", ht_Line},
2411
    {"LineX", ht_LineX},
2412
    {"LineY", ht_LineY},
2413
    {"Square", ht_Square},
2414
    {"Cross", ht_Cross},
2415
    {"Rhomboid", ht_Rhomboid},
2416
    {"DoubleDot", ht_DoubleDot},
2417
    {"InvertedDoubleDot", ht_InvertedDoubleDot},
2418
    {"SimpleDot", ht_SimpleDot},
2419
    {"InvertedSimpleDot", ht_InvertedSimpleDot},
2420
    {"CosineDot", ht_CosineDot},
2421
    {"Double", ht_Double},
2422
    {"InvertedDouble", ht_InvertedDouble}
2423
};
2424
2425
/* Write each kind of halftone. */
2426
static int
2427
pdf_write_spot_function(gx_device_pdf *pdev, const gx_ht_order *porder,
2428
                        int64_t *pid)
2429
1.16k
{
2430
    /****** DOESN'T HANDLE STRIP HALFTONES ******/
2431
1.16k
    int w = porder->width, h = porder->height;
2432
1.16k
    uint num_bits = porder->num_bits;
2433
1.16k
    gs_function_Sd_params_t params;
2434
1.16k
    static const float domain_spot[4] = { -1, 1, -1, 1 };
2435
1.16k
    static const float range_spot[4] = { -1, 1 };
2436
1.16k
    int size[2];
2437
1.16k
    gs_memory_t *mem = pdev->pdf_memory;
2438
    /*
2439
     * Even though the values are logically ushort, we must always store
2440
     * them in big-endian order, so we access them as bytes.
2441
     */
2442
1.16k
    byte *values;
2443
1.16k
    gs_function_t *pfn;
2444
1.16k
    uint i;
2445
1.16k
    int code = 0;
2446
2447
1.16k
    params.array_size = 0;
2448
1.16k
    params.m = 2;
2449
1.16k
    params.Domain = domain_spot;
2450
1.16k
    params.n = 1;
2451
1.16k
    params.Range = range_spot;
2452
1.16k
    params.Order = 0;   /* default */
2453
    /*
2454
     * We could use 8, 16, or 32 bits per sample to save space, but for
2455
     * simplicity, we always use 16.
2456
     */
2457
1.16k
    if (num_bits > 0x10000)
2458
        /* rangecheck is a 'special case' in gdev_pdf_fill_path, if this error is encountered
2459
         * then it 'falls back' to a different method assuming its handling transparency in an
2460
         * old PDF output version. But if we fail to write the halftone, we want to abort
2461
         * so use limitcheck instead.
2462
         */
2463
0
        return_error(gs_error_limitcheck);
2464
1.16k
    params.BitsPerSample = 16;
2465
1.16k
    params.Encode = 0;
2466
    /*
2467
     * The default Decode array maps the actual data values [1 .. w*h] to a
2468
     * sub-interval of the Range, but that's OK, since all that matters is
2469
     * the relative values, not the absolute values.
2470
     */
2471
1.16k
    params.Decode = 0;
2472
1.16k
    size[0] = w;
2473
1.16k
    size[1] = h;
2474
1.16k
    params.Size = size;
2475
    /* Create the (temporary) threshold array. */
2476
1.16k
    values = gs_alloc_byte_array(mem, num_bits, 2, "pdf_write_spot_function");
2477
1.16k
    if (values == 0)
2478
0
        return_error(gs_error_VMerror);
2479
43.1k
    for (i = 0; i < num_bits; ++i) {
2480
41.9k
        gs_int_point pt;
2481
41.9k
        int value;
2482
2483
41.9k
        if ((code = porder->procs->bit_index(porder, i, &pt)) < 0)
2484
0
            break;
2485
41.9k
        value = pt.y * w + pt.x;
2486
        /* Always store the values in big-endian order. */
2487
41.9k
        values[i * 2] = (byte)(value >> 8);
2488
41.9k
        values[i * 2 + 1] = (byte)value;
2489
41.9k
    }
2490
1.16k
    data_source_init_bytes(&params.DataSource, (const byte *)values,
2491
1.16k
                           sizeof(*values) * num_bits);
2492
1.16k
    if (code >= 0 &&
2493
    /* Warning from COverity that params.array_size is uninitialised. Correct */
2494
    /* but immeidiately after copying the data Sd_init sets the copied value  */
2495
    /* to zero, so it is not actually used uninitialised. */
2496
1.16k
        (code = gs_function_Sd_init(&pfn, &params, mem)) >= 0
2497
1.16k
        ) {
2498
1.16k
        code = pdf_write_function(pdev, pfn, pid);
2499
1.16k
        gs_function_free(pfn, false, mem);
2500
1.16k
    }
2501
1.16k
    gs_free_object(mem, values, "pdf_write_spot_function");
2502
1.16k
    return code;
2503
1.16k
}
2504
2505
/* if (memcmp(order.levels, porder->levels, order.num_levels * sizeof(*order.levels))) */
2506
static int
2507
32.0k
compare_gx_ht_order_levels(const gx_ht_order *order1, const gx_ht_order *order2) {
2508
32.0k
  int i;
2509
640k
  for (i=0;  i<order1->num_levels;  i++) {
2510
608k
    if (order1->levels[i] != order2->levels[i])
2511
0
      return(1);
2512
608k
  }
2513
32.0k
  return(0);
2514
32.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
8.53k
{
2520
8.53k
    char trs[17 + MAX_FN_CHARS + 1];
2521
8.53k
    int code;
2522
8.53k
    int64_t spot_id;
2523
8.53k
    stream *s;
2524
8.53k
    int i = countof(ht_functions);
2525
8.53k
    gs_memory_t *mem = pdev->pdf_memory;
2526
2527
8.53k
    if (pdev->CompatibilityLevel <= 1.7) {
2528
8.53k
        code = pdf_write_transfer(pdev, porder->transfer, "/TransferFunction",
2529
8.53k
                                  trs, sizeof(trs));
2530
8.53k
        if (code < 0)
2531
0
            return code;
2532
8.53k
    }
2533
    /*
2534
     * See if we can recognize the spot function, by comparing its sampled
2535
     * values against those in the order.
2536
     */
2537
8.53k
    { gs_screen_enum senum;
2538
8.53k
        gx_ht_order order;
2539
8.53k
        int code;
2540
2541
8.53k
        order = *porder;
2542
8.53k
        code = gs_screen_order_alloc(&order, mem);
2543
8.53k
        if (code < 0)
2544
0
            goto notrec;
2545
33.2k
        for (i = 0; i < countof(ht_functions); ++i) {
2546
32.0k
            double (*spot_proc)(double, double) = ht_functions[i].proc;
2547
32.0k
            gs_point pt;
2548
2549
32.0k
            gs_screen_enum_init_memory(&senum, &order, NULL, &psht->screen,
2550
32.0k
                                       mem);
2551
640k
            while ((code = gs_screen_currentpoint(&senum, &pt)) == 0 &&
2552
640k
                   gs_screen_next(&senum, spot_proc(pt.x, pt.y)) >= 0)
2553
608k
                DO_NOTHING;
2554
32.0k
            if (code < 0)
2555
0
                continue;
2556
            /* Compare the bits and levels arrays. */
2557
32.0k
            if (compare_gx_ht_order_levels(&order,porder))
2558
0
                continue;
2559
32.0k
            if (memcmp(order.bit_data, porder->bit_data,
2560
32.0k
                       (size_t)order.num_bits *
2561
32.0k
                                      porder->procs->bit_data_elt_size))
2562
24.7k
                continue;
2563
            /* We have a match. */
2564
7.36k
            break;
2565
32.0k
        }
2566
8.53k
        gx_ht_order_release(&order, mem, false);
2567
8.53k
    }
2568
8.53k
 notrec:
2569
8.53k
    if (i == countof(ht_functions)) {
2570
        /* Create and write a Function for the spot function. */
2571
1.16k
        code = pdf_write_spot_function(pdev, porder, &spot_id);
2572
1.16k
        if (code < 0)
2573
0
            return code;
2574
1.16k
    }
2575
8.53k
    *pid = pdf_begin_separate(pdev, resourceHalftone);
2576
8.53k
    s = pdev->strm;
2577
    /* Use the original, requested frequency and angle. */
2578
8.53k
    pprintg2(s, "<</Type/Halftone/HalftoneType 1/Frequency %g/Angle %g",
2579
8.53k
             psht->screen.frequency, psht->screen.angle);
2580
8.53k
    if (i < countof(ht_functions))
2581
7.36k
        pprints1(s, "/SpotFunction/%s", ht_functions[i].fname);
2582
1.16k
    else
2583
1.16k
        pprinti64d1(s, "/SpotFunction %"PRId64" 0 R", spot_id);
2584
8.53k
    if (pdev->CompatibilityLevel <= 1.7)
2585
8.53k
        stream_puts(s, trs);
2586
8.53k
    if (psht->accurate_screens)
2587
0
        stream_puts(s, "/AccurateScreens true");
2588
8.53k
    stream_puts(s, ">>\n");
2589
8.53k
    return pdf_end_separate(pdev, resourceHalftone);
2590
8.53k
}
2591
static int
2592
pdf_write_screen_halftone(gx_device_pdf *pdev, const gs_screen_halftone *psht,
2593
                          const gx_ht_order *porder, long *pid)
2594
1.19k
{
2595
1.19k
    gs_spot_halftone spot;
2596
2597
1.19k
    spot.screen = *psht;
2598
1.19k
    spot.accurate_screens = false;
2599
1.19k
    spot.transfer = 0;
2600
1.19k
    spot.transfer_closure.proc = 0;
2601
1.19k
    return pdf_write_spot_halftone(pdev, &spot, porder, pid);
2602
1.19k
}
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
44.0k
{
2728
44.0k
    int j;
2729
2730
88.0k
    for (j = 0; j < pmht->num_comp; j++)
2731
44.0k
        if (pmht->components[j].comp_number == dht_index)
2732
0
            break;
2733
44.0k
    if (j == pmht->num_comp) {
2734
        /* Look for Default. */
2735
44.0k
        for (j = 0; j < pmht->num_comp; j++)
2736
44.0k
            if (pmht->components[j].comp_number == GX_DEVICE_COLOR_MAX_COMPONENTS)
2737
44.0k
                break;
2738
44.0k
        if (j == pmht->num_comp)
2739
0
            return_error(gs_error_undefined);
2740
44.0k
    }
2741
44.0k
    return j;
2742
44.0k
}
2743
static int
2744
pdf_write_multiple_halftone(gx_device_pdf *pdev, gs_gstate *pgs,
2745
                            const gs_multiple_halftone *pmht,
2746
                            const gx_device_halftone *pdht, long *pid)
2747
7.33k
{
2748
7.33k
    stream *s;
2749
7.33k
    int i, code, last_comp = 0;
2750
7.33k
    gs_memory_t *mem = pdev->pdf_memory;
2751
7.33k
    long *ids;
2752
7.33k
    bool done_Default = false;
2753
2754
7.33k
    ids = (long *)gs_alloc_byte_array(mem, pmht->num_comp, sizeof(long),
2755
7.33k
                                      "pdf_write_multiple_halftone");
2756
7.33k
    if (ids == 0)
2757
0
        return_error(gs_error_VMerror);
2758
29.3k
    for (i = 0; i < pdht->num_comp; ++i) {
2759
22.0k
        const gs_halftone_component *phtc;
2760
22.0k
        const gx_ht_order *porder;
2761
2762
22.0k
        code = pdf_get_halftone_component_index(pmht, pdht, i);
2763
22.0k
        if (code < 0)
2764
0
            return code;
2765
22.0k
        if (pmht->components[code].comp_number == GX_DEVICE_COLOR_MAX_COMPONENTS) {
2766
22.0k
            if (done_Default)
2767
14.6k
                continue;
2768
7.33k
            done_Default = true;
2769
7.33k
        }
2770
7.33k
        phtc = &pmht->components[code];
2771
7.33k
        porder = (pdht->components == 0 ? &pdht->order :
2772
7.33k
                       &pdht->components[i].corder);
2773
7.33k
        switch (phtc->type) {
2774
7.33k
        case ht_type_spot:
2775
7.33k
            code = pdf_write_spot_halftone(pdev, &phtc->params.spot,
2776
7.33k
                                           porder, &ids[i]);
2777
7.33k
            break;
2778
0
        case ht_type_threshold:
2779
0
            code = pdf_write_threshold_halftone(pdev, &phtc->params.threshold,
2780
0
                                                porder, &ids[i]);
2781
0
            break;
2782
0
        case ht_type_threshold2:
2783
0
            code = pdf_write_threshold2_halftone(pdev,
2784
0
                                                 &phtc->params.threshold2,
2785
0
                                                 porder, &ids[i]);
2786
0
            break;
2787
0
        default:
2788
0
            code = gs_note_error(gs_error_rangecheck);
2789
7.33k
        }
2790
7.33k
        if (code < 0) {
2791
0
            gs_free_object(mem, ids, "pdf_write_multiple_halftone");
2792
0
            return code;
2793
0
        }
2794
7.33k
    }
2795
7.33k
    *pid = pdf_begin_separate(pdev, resourceHalftone);
2796
7.33k
    s = pdev->strm;
2797
7.33k
    stream_puts(s, "<</Type/Halftone/HalftoneType 5\n");
2798
7.33k
    done_Default = false;
2799
29.3k
    for (i = 0; i < pdht->num_comp; ++i) {
2800
22.0k
        const gs_halftone_component *phtc;
2801
22.0k
        byte *str;
2802
22.0k
        uint len;
2803
22.0k
        cos_value_t value;
2804
2805
22.0k
        code = pdf_get_halftone_component_index(pmht, pdht, i);
2806
22.0k
        if (code < 0)
2807
0
            return code;
2808
22.0k
        if (pmht->components[code].comp_number == GX_DEVICE_COLOR_MAX_COMPONENTS) {
2809
22.0k
            if (done_Default)
2810
14.6k
                continue;
2811
7.33k
            done_Default = true;
2812
7.33k
        }
2813
7.33k
        phtc = &pmht->components[code];
2814
7.33k
        if ((code = pmht->get_colorname_string(pgs, phtc->cname, &str, &len)) < 0 ||
2815
7.33k
            (code = pdf_string_to_cos_name(pdev, str, len, &value)) < 0)
2816
0
            return code;
2817
7.33k
        cos_value_write(&value, pdev);
2818
7.33k
        gs_free_string(mem, value.contents.chars.data,
2819
7.33k
                       value.contents.chars.size,
2820
7.33k
                       "pdf_write_multiple_halftone");
2821
7.33k
        pprintld1(s, " %ld 0 R\n", ids[i]);
2822
7.33k
        last_comp = i;
2823
7.33k
    }
2824
7.33k
    if (!done_Default) {
2825
        /*
2826
         * BOGUS: Type 5 halftones must contain Default component.
2827
         * Perhaps we have no way to obtain it,
2828
         * because pdht contains ProcessColorModel components only.
2829
         * We copy the last component as Default one.
2830
         */
2831
0
        pprintld1(s, " /Default %ld 0 R\n", ids[last_comp]);
2832
0
    }
2833
7.33k
    stream_puts(s, ">>\n");
2834
7.33k
    gs_free_object(mem, ids, "pdf_write_multiple_halftone");
2835
7.33k
    return pdf_end_separate(pdev, resourceHalftone);
2836
7.33k
}
2837
2838
/*
2839
 * Update the halftone.  This is a separate procedure only for
2840
 * readability.
2841
 */
2842
static int
2843
pdf_update_halftone(gx_device_pdf *pdev, const gs_gstate *pgs,
2844
                    char *hts, int hts_max)
2845
8.53k
{
2846
8.53k
    const gs_halftone *pht = pgs->halftone;
2847
8.53k
    const gx_device_halftone *pdht = pgs->dev_ht[HT_OBJTYPE_DEFAULT];
2848
8.53k
    int code;
2849
8.53k
    long id;
2850
2851
8.53k
    switch (pht->type) {
2852
1.19k
    case ht_type_screen:
2853
1.19k
        code = pdf_write_screen_halftone(pdev, &pht->params.screen,
2854
1.19k
                                         &pdht->components[0].corder, &id);
2855
1.19k
        break;
2856
0
    case ht_type_colorscreen:
2857
0
        code = pdf_write_colorscreen_halftone(pdev, &pht->params.colorscreen,
2858
0
                                              pdht, &id);
2859
0
        break;
2860
0
    case ht_type_spot:
2861
0
        code = pdf_write_spot_halftone(pdev, &pht->params.spot,
2862
0
                                       &pdht->components[0].corder, &id);
2863
0
        break;
2864
0
    case ht_type_threshold:
2865
0
        code = pdf_write_threshold_halftone(pdev, &pht->params.threshold,
2866
0
                                            &pdht->components[0].corder, &id);
2867
0
        break;
2868
0
    case ht_type_threshold2:
2869
0
        code = pdf_write_threshold2_halftone(pdev, &pht->params.threshold2,
2870
0
                                             &pdht->components[0].corder, &id);
2871
0
        break;
2872
7.33k
    case ht_type_multiple:
2873
7.33k
    case ht_type_multiple_colorscreen:
2874
7.33k
        code = pdf_write_multiple_halftone(pdev, (gs_gstate *)pgs, &pht->params.multiple,
2875
7.33k
                                           pdht, &id);
2876
7.33k
        break;
2877
0
    default:
2878
0
        return_error(gs_error_rangecheck);
2879
8.53k
    }
2880
8.53k
    if (code < 0)
2881
0
        return code;
2882
8.53k
    gs_snprintf(hts, hts_max, "%ld 0 R", id);
2883
8.53k
    pdev->halftone_id = pgs->dev_ht[HT_OBJTYPE_DEFAULT]->id;
2884
8.53k
    return code;
2885
8.53k
}
2886
2887
/* ------ Graphics state updating ------ */
2888
2889
static inline cos_dict_t *
2890
resource_dict(pdf_resource_t *pres)
2891
180k
{
2892
180k
    return (cos_dict_t *)pres->object;
2893
180k
}
2894
2895
/* Open an ExtGState. */
2896
static int
2897
pdf_open_gstate(gx_device_pdf *pdev, pdf_resource_t **ppres)
2898
86.7k
{
2899
86.7k
    int code;
2900
2901
86.7k
    if (*ppres)
2902
7.01k
        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
79.7k
    if (pdev->context != PDF_IN_STREAM) {
2909
        /* We apparently use gs_error_interrupt as a request to change context. */
2910
5.53k
      return_error(gs_error_interrupt);
2911
5.53k
    }
2912
74.2k
    code = pdf_alloc_resource(pdev, resourceExtGState, gs_no_id, ppres, -1L);
2913
74.2k
    if (code < 0)
2914
0
        return code;
2915
74.2k
    cos_become((*ppres)->object, cos_type_dict);
2916
74.2k
    code = cos_dict_put_c_key_string(resource_dict(*ppres), "/Type", (const byte *)"/ExtGState", 10);
2917
74.2k
    if (code < 0)
2918
0
        return code;
2919
74.2k
    return 0;
2920
74.2k
}
2921
2922
/* Finish writing an ExtGState. */
2923
int
2924
pdf_end_gstate(gx_device_pdf *pdev, pdf_resource_t *pres)
2925
9.57M
{
2926
9.57M
    if (pres) {
2927
74.2k
        int code = pdf_substitute_resource(pdev, &pres, resourceExtGState, NULL, true);
2928
2929
74.2k
        if (code < 0)
2930
0
            return code;
2931
74.2k
        pres->where_used |= pdev->used_mask;
2932
74.2k
        code = pdf_open_page(pdev, PDF_IN_STREAM);
2933
74.2k
        if (code < 0)
2934
0
            return code;
2935
74.2k
        code = pdf_add_resource(pdev, pdev->substream_Resources, "/ExtGState", pres);
2936
74.2k
        if (code < 0)
2937
0
            return code;
2938
74.2k
        pprinti64d1(pdev->strm, "/R%"PRId64" gs\n", pdf_resource_id(pres));
2939
74.2k
        pres->where_used |= pdev->used_mask;
2940
74.2k
    }
2941
9.57M
    return 0;
2942
9.57M
}
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
9.42M
{
2952
9.42M
    int i, pi = -1;
2953
9.42M
    bool multiple = false, update = false;
2954
9.42M
    gs_id transfer_ids[4];
2955
9.42M
    int code = 0;
2956
9.42M
    const gx_transfer_map *tm[4];
2957
2958
9.42M
    tm[0] = pgs->set_transfer.red;
2959
9.42M
    tm[1] = pgs->set_transfer.green;
2960
9.42M
    tm[2] = pgs->set_transfer.blue;
2961
9.42M
    tm[3] = pgs->set_transfer.gray;
2962
47.1M
    for (i = 0; i < 4; ++i)
2963
37.7M
        if (tm[i] != NULL) {
2964
9.42M
            transfer_ids[i] = tm[i]->id;
2965
9.42M
            if (pdev->transfer_ids[i] != tm[i]->id)
2966
16.8k
                update = true;
2967
9.42M
            if (pi != -1 && transfer_ids[i] != transfer_ids[pi])
2968
675
                multiple = true;
2969
9.42M
            pi = i;
2970
9.42M
        } else
2971
28.2M
            transfer_ids[i] = -1;
2972
9.42M
    if (update) {
2973
16.7k
        int mask;
2974
2975
16.7k
        if (!multiple) {
2976
16.7k
            code = pdf_write_transfer(pdev, tm[pi], "", trs, trs_max);
2977
16.7k
            if (code < 0)
2978
0
                return code;
2979
16.7k
            mask = code == 0;
2980
16.7k
        } else {
2981
31
            strcpy(trs, "[");
2982
31
            mask = 0;
2983
155
            for (i = 0; i < 4; ++i)
2984
124
                if (tm[i] != NULL) {
2985
124
                    int len = (int)strlen(trs);
2986
124
                    code = pdf_write_transfer_map(pdev,
2987
124
                                                  tm[i],
2988
124
                                                  0, true, " ", trs + len, trs_max - len);
2989
124
                    if (code < 0)
2990
0
                        return code;
2991
124
                    mask |= (code == 0) << i;
2992
124
                }
2993
31
            strcat(trs, "]");
2994
31
        }
2995
16.7k
        memcpy(pdev->transfer_ids, transfer_ids, sizeof(pdev->transfer_ids));
2996
16.7k
        pdev->transfer_not_identity = mask;
2997
16.7k
    }
2998
9.42M
    return code;
2999
9.42M
}
3000
3001
/*
3002
 * Update the current alpha if necessary.  Note that because Ghostscript
3003
 * stores separate opacity and shape alpha, a rangecheck will occur if
3004
 * both are different from the current setting.
3005
 */
3006
static int
3007
pdf_update_alpha(gx_device_pdf *pdev, const gs_gstate *pgs,
3008
                 pdf_resource_t **ppres, bool for_text)
3009
4.18M
{
3010
4.18M
    int code;
3011
3012
4.18M
    if (pdev->state.soft_mask_id != pgs->soft_mask_id) {
3013
351
        char buf[20];
3014
3015
351
        if (pgs->soft_mask_id == 0) {
3016
67
            code = pdf_open_contents(pdev, PDF_IN_STREAM);
3017
67
            if (code < 0)
3018
0
                return code;
3019
67
            if (pdev->vgstack_depth > pdev->vgstack_bottom) {
3020
65
                code = pdf_restore_viewer_state(pdev, pdev->strm);
3021
65
                if (code < 0)
3022
0
                    return code;
3023
65
            }
3024
67
        }
3025
284
        else{
3026
284
            gs_snprintf(buf, sizeof(buf), "%ld 0 R", pgs->soft_mask_id);
3027
284
            code = pdf_open_gstate(pdev, ppres);
3028
284
            if (code < 0)
3029
0
                return code;
3030
284
            code = cos_dict_put_c_key_string(resource_dict(*ppres),
3031
284
                        "/SMask", (byte *)buf, strlen(buf));
3032
284
            if (code < 0)
3033
0
                return code;
3034
284
            code = pdf_save_viewer_state(pdev, pdev->strm);
3035
284
            if (code < 0)
3036
0
                return code;
3037
284
        }
3038
351
        pdev->state.soft_mask_id = pgs->soft_mask_id;
3039
351
    }
3040
3041
4.18M
    if (pdev->state.alphaisshape != pgs->alphaisshape ||
3042
4.18M
        pdev->state.strokeconstantalpha != pgs->strokeconstantalpha ||
3043
4.18M
        pdev->state.fillconstantalpha != pgs->fillconstantalpha) {
3044
3045
4.26k
        code = pdf_open_gstate(pdev, ppres);
3046
4.26k
        if (code < 0)
3047
527
            return code;
3048
3049
3.73k
        code = cos_dict_put_c_key_bool(resource_dict(*ppres), "/AIS", pgs->alphaisshape);
3050
3.73k
        if (code < 0)
3051
0
            return code;
3052
3.73k
        pdev->state.alphaisshape = pgs->alphaisshape;
3053
3.73k
        code = cos_dict_put_c_key_real(resource_dict(*ppres), "/CA", pgs->strokeconstantalpha);
3054
3.73k
        if (code < 0)
3055
0
            return code;
3056
3.73k
        pdev->state.strokeconstantalpha = pgs->strokeconstantalpha;
3057
3.73k
        code = cos_dict_put_c_key_real(resource_dict(*ppres), "/ca", pgs->fillconstantalpha);
3058
3.73k
        if (code < 0)
3059
0
            return code;
3060
3.73k
        pdev->state.fillconstantalpha = pgs->fillconstantalpha;
3061
3.73k
    }
3062
4.17M
    return 0;
3063
4.18M
}
3064
3065
/*
3066
 * Update the graphics subset common to all high-level drawing operations.
3067
 */
3068
int
3069
pdf_prepare_drawing(gx_device_pdf *pdev, const gs_gstate *pgs,
3070
                    pdf_resource_t **ppres, bool for_text)
3071
9.59M
{
3072
9.59M
    int code = 0;
3073
9.59M
    int bottom;
3074
3075
9.59M
    if (pdev->CompatibilityLevel >= 1.4) {
3076
4.18M
        code = pdf_update_alpha(pdev, pgs, ppres, for_text);
3077
4.18M
        if (code < 0)
3078
527
            return code;
3079
4.17M
        if (pdev->state.blend_mode != pgs->blend_mode) {
3080
2.74k
            static const char *const bm_names[] = { GS_BLEND_MODE_NAMES };
3081
2.74k
            char buf[20];
3082
3083
2.74k
            code = pdf_open_gstate(pdev, ppres);
3084
2.74k
            if (code < 0)
3085
45
                return code;
3086
2.70k
            buf[0] = '/';
3087
2.70k
            strncpy(buf + 1, bm_names[pgs->blend_mode], sizeof(buf) - 2);
3088
2.70k
            code = cos_dict_put_string_copy(resource_dict(*ppres), "/BM", buf);
3089
2.70k
            if (code < 0)
3090
0
                return code;
3091
2.70k
            pdev->state.blend_mode = pgs->blend_mode;
3092
2.70k
        }
3093
5.41M
    } 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.41M
        if (pgs->strokeconstantalpha != 1 ||
3099
5.41M
            pgs->fillconstantalpha != 1)
3100
11.1k
            return_error(gs_error_rangecheck);
3101
5.41M
    }
3102
    /*
3103
     * We originally thought the remaining items were only needed for
3104
     * fill and stroke, but in fact they are needed for images as well.
3105
     */
3106
    /*
3107
     * Update halftone, transfer function, black generation, undercolor
3108
     * removal, halftone phase, overprint mode, smoothness, blend mode, text
3109
     * knockout.
3110
     */
3111
9.58M
    bottom = (pdev->ResourcesBeforeUsage ? 1 : 0);
3112
    /* When ResourcesBeforeUsage != 0, one sbstack element
3113
       appears from the page contents stream. */
3114
9.58M
    if (pdev->sbstack_depth == bottom) {
3115
9.42M
        gs_int_point phase, dev_phase;
3116
9.42M
        char hts[5 + MAX_FN_CHARS + 1],
3117
9.42M
            trs[5 + MAX_FN_CHARS * 4 + 6 + 1],
3118
9.42M
            bgs[5 + MAX_FN_CHARS + 1],
3119
9.42M
            ucrs[6 + MAX_FN_CHARS + 1];
3120
3121
9.42M
        hts[0] = trs[0] = bgs[0] = ucrs[0] = 0;
3122
9.42M
        if (pdev->params.PreserveHalftoneInfo &&
3123
9.42M
            pdev->halftone_id != pgs->dev_ht[HT_OBJTYPE_DEFAULT]->id &&
3124
9.42M
            pdev->PDFX == 0
3125
9.42M
            ) {
3126
8.53k
            code = pdf_update_halftone(pdev, pgs, hts, sizeof(hts));
3127
8.53k
            if (code < 0)
3128
0
                return code;
3129
8.53k
        }
3130
9.42M
        if (pdev->params.TransferFunctionInfo != tfi_Remove &&
3131
9.42M
            pdev->PDFX == 0 && pdev->PDFA == 0
3132
9.42M
            ) {
3133
9.42M
            code = pdf_update_transfer(pdev, pgs, trs, sizeof(trs));
3134
9.42M
            if (code < 0)
3135
0
                return code;
3136
9.42M
        }
3137
9.42M
        if (pdev->params.UCRandBGInfo == ucrbg_Preserve) {
3138
9.42M
            if (pgs->black_generation && pdev->black_generation_id != pgs->black_generation->id) {
3139
9.02k
                code = pdf_write_transfer_map(pdev, pgs->black_generation,
3140
9.02k
                                              0, false, "", bgs, sizeof(bgs));
3141
9.02k
                if (code < 0)
3142
0
                    return code;
3143
9.02k
                pdev->black_generation_id = pgs->black_generation->id;
3144
9.02k
            }
3145
9.42M
            if (pgs->undercolor_removal && pdev->undercolor_removal_id != pgs->undercolor_removal->id) {
3146
9.01k
                code = pdf_write_transfer_map(pdev, pgs->undercolor_removal,
3147
9.01k
                                              -1, false, "", ucrs, sizeof(ucrs));
3148
9.01k
                if (code < 0)
3149
0
                    return code;
3150
9.01k
                pdev->undercolor_removal_id = pgs->undercolor_removal->id;
3151
9.01k
            }
3152
9.42M
        }
3153
9.42M
        if (hts[0] || trs[0] || bgs[0] || ucrs[0]) {
3154
27.5k
            code = pdf_open_gstate(pdev, ppres);
3155
27.5k
            if (code < 0)
3156
1.93k
                return code;
3157
27.5k
        }
3158
9.42M
        if (hts[0]) {
3159
8.53k
            code = cos_dict_put_string_copy(resource_dict(*ppres), "/HT", hts);
3160
8.53k
            if (code < 0)
3161
0
                return code;
3162
8.53k
        }
3163
9.42M
        if (pdev->CompatibilityLevel <= 1.7 && trs[0] && pdev->params.TransferFunctionInfo == tfi_Preserve) {
3164
14.8k
            code = cos_dict_put_string_copy(resource_dict(*ppres), "/TR", trs);
3165
14.8k
            if (code < 0)
3166
0
                return code;
3167
14.8k
        }
3168
9.42M
        if (bgs[0]) {
3169
8.92k
            code = cos_dict_put_string_copy(resource_dict(*ppres), "/BG", bgs);
3170
8.92k
            if (code < 0)
3171
0
                return code;
3172
8.92k
        }
3173
9.42M
        if (ucrs[0]) {
3174
8.90k
            code = cos_dict_put_string_copy(resource_dict(*ppres), "/UCR", ucrs);
3175
8.90k
            if (code < 0)
3176
0
                return code;
3177
8.90k
        }
3178
9.42M
        if (pdev->PDFX == 0) {
3179
9.42M
            gs_currentscreenphase(pgs, &phase, 0);
3180
9.42M
            gs_currentscreenphase(&pdev->state, &dev_phase, 0);
3181
9.42M
            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
9.42M
            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
9.42M
        }
3226
9.42M
    }
3227
9.58M
    if (pdev->state.overprint_mode != pdev->params.OPM) {
3228
2.41k
        if (pdev->params.OPM != pgs->overprint_mode)
3229
1.19k
            ((gs_gstate *)pgs)->overprint_mode = pdev->params.OPM;
3230
2.41k
    }
3231
9.58M
    if (pdev->CompatibilityLevel >= 1.3 /*&& pdev->sbstack_depth == bottom */) {
3232
4.17M
        if (pdev->state.overprint_mode != pgs->overprint_mode) {
3233
11.0k
            if (pgs->overprint_mode == 1 && pdev->PDFA == 2) {
3234
0
                switch (pdev->PDFACompatibilityPolicy) {
3235
0
                    case 0:
3236
0
                        emprintf(pdev->memory,
3237
0
                             "Setting Overprint Mode to 1\n not permitted in PDF/A-2, reverting to normal PDF output\n");
3238
0
                        pdev->AbortPDFAX = true;
3239
0
                        pdev->PDFA = 0;
3240
0
                        break;
3241
0
                    case 1:
3242
0
                        emprintf(pdev->memory,
3243
0
                             "Setting Overprint Mode to 1\n not permitted in PDF/A-2, overprint mode not set\n\n");
3244
                        /* Deliberately breaking const here in order to force the graphics state overprint mode to be unchanged */
3245
0
                        ((gs_gstate *)pgs)->overprint_mode = pdev->state.overprint_mode;
3246
0
                        break;
3247
0
                    case 2:
3248
0
                        emprintf(pdev->memory,
3249
0
                             "Setting Overprint Mode to 1\n not permitted in PDF/A-2, aborting conversion\n");
3250
0
                        return_error(gs_error_undefined);
3251
0
                        break;
3252
0
                    default:
3253
0
                        emprintf(pdev->memory,
3254
0
                             "Setting Overprint Mode to 1\n not permitted in PDF/A-2, unrecognised PDFACompatibilityLevel,\nreverting to normal PDF output\n");
3255
0
                        pdev->AbortPDFAX = true;
3256
0
                        pdev->PDFA = 0;
3257
0
                        break;
3258
0
                }
3259
0
            }
3260
11.0k
            if (pdev->state.overprint_mode != pgs->overprint_mode) {
3261
11.0k
                code = pdf_open_gstate(pdev, ppres);
3262
11.0k
                if (code < 0)
3263
575
                    return code;
3264
10.4k
                code = cos_dict_put_c_key_int(resource_dict(*ppres), "/OPM", pgs->overprint_mode);
3265
10.4k
                if (code < 0)
3266
0
                    return code;
3267
10.4k
                pdev->params.OPM = pdev->state.overprint_mode = pgs->overprint_mode;
3268
10.4k
            }
3269
11.0k
        }
3270
4.17M
        if (pdev->state.smoothness != pgs->smoothness) {
3271
83
            code = pdf_open_gstate(pdev, ppres);
3272
83
            if (code < 0)
3273
9
                return code;
3274
74
            code = cos_dict_put_c_key_real(resource_dict(*ppres), "/SM", pgs->smoothness);
3275
74
            if (code < 0)
3276
0
                return code;
3277
74
            pdev->state.smoothness = pgs->smoothness;
3278
74
        }
3279
4.17M
        if (pdev->CompatibilityLevel >= 1.4) {
3280
4.17M
            if (pdev->state.text_knockout != pgs->text_knockout) {
3281
0
                code = pdf_open_gstate(pdev, ppres);
3282
0
                if (code < 0)
3283
0
                    return code;
3284
0
                code = cos_dict_put_c_key_bool(resource_dict(*ppres), "/TK", pgs->text_knockout);
3285
0
                if (code < 0)
3286
0
                    return code;
3287
0
                pdev->state.text_knockout = pgs->text_knockout;
3288
0
            }
3289
4.17M
        }
3290
4.17M
    }
3291
9.58M
    return code;
3292
9.58M
}
3293
3294
/* Update the graphics state for filling. */
3295
int
3296
pdf_try_prepare_fill(gx_device_pdf *pdev, const gs_gstate *pgs, bool for_text)
3297
8.63M
{
3298
8.63M
    pdf_resource_t *pres = 0;
3299
8.63M
    int code = pdf_prepare_drawing(pdev, pgs, &pres, for_text);
3300
3301
8.63M
    if (code < 0)
3302
12.0k
        return code;
3303
8.61M
    if (pdev->rendering_intent != pgs->renderingintent && !pdev->ForOPDFRead) {
3304
8.74k
        static const char *const ri_names[] = { "Perceptual", "RelativeColorimetric", "Saturation", "AbsoluteColorimetric" };
3305
8.74k
        char buf[32];
3306
3307
8.74k
        code = pdf_open_gstate(pdev, &pres);
3308
8.74k
        if (code < 0)
3309
171
            return code;
3310
3311
8.56k
        buf[0] = '/';
3312
8.56k
        strncpy(buf + 1, ri_names[pgs->renderingintent], sizeof(buf) - 2);
3313
8.56k
        code = cos_dict_put_string_copy(resource_dict(pres), "/RI", buf);
3314
8.56k
        if (code < 0)
3315
0
            return code;
3316
8.56k
        pdev->rendering_intent = pgs->renderingintent;
3317
8.56k
    }
3318
3319
    /* Update overprint. */
3320
8.61M
    if (pdev->params.PreserveOverprintSettings &&
3321
8.61M
        (pdev->fill_overprint != pgs->overprint ||
3322
8.61M
        pdev->font3) &&  !pdev->skip_colors
3323
8.61M
        ) {
3324
13.7k
        if (pres == 0)
3325
12.1k
            code = pdf_open_gstate(pdev, &pres);
3326
13.7k
        if (code < 0)
3327
2.10k
            return code;
3328
        /* PDF 1.2 only has a single overprint setting. */
3329
11.6k
        if (pdev->CompatibilityLevel < 1.3) {
3330
3.41k
            code = cos_dict_put_c_key_bool(resource_dict(pres), "/OP", pgs->overprint);
3331
3.41k
            if (code < 0)
3332
0
                return code;
3333
3.41k
            pdev->stroke_overprint = pgs->overprint;
3334
8.19k
        } else {
3335
8.19k
            code = cos_dict_put_c_key_bool(resource_dict(pres), "/op", pgs->overprint);
3336
8.19k
            if (code < 0)
3337
0
                return code;
3338
8.19k
        }
3339
11.6k
        pdev->fill_overprint = pgs->overprint;
3340
11.6k
    }
3341
8.61M
    return pdf_end_gstate(pdev, pres);
3342
8.61M
}
3343
int
3344
pdf_prepare_fill(gx_device_pdf *pdev, const gs_gstate *pgs, bool for_text)
3345
8.62M
{
3346
8.62M
    int code;
3347
3348
8.62M
    if (pdev->context != PDF_IN_STREAM) {
3349
6.22M
        code = pdf_try_prepare_fill(pdev, pgs, for_text);
3350
6.22M
        if (code != gs_error_interrupt) /* See pdf_open_gstate */
3351
6.22M
            return code;
3352
4.85k
        code = pdf_open_contents(pdev, PDF_IN_STREAM);
3353
4.85k
        if (code < 0)
3354
0
            return code;
3355
4.85k
    }
3356
2.40M
    return pdf_try_prepare_fill(pdev, pgs, for_text);
3357
8.62M
}
3358
3359
/* Update the graphics state for stroking. */
3360
static int
3361
pdf_try_prepare_stroke(gx_device_pdf *pdev, const gs_gstate *pgs, bool for_text)
3362
946k
{
3363
946k
    pdf_resource_t *pres = 0;
3364
946k
    int code = pdf_prepare_drawing(pdev, pgs, &pres, for_text);
3365
3366
946k
    if (code < 0)
3367
1.66k
        return code;
3368
944k
    if (pdev->rendering_intent != pgs->renderingintent && !pdev->ForOPDFRead) {
3369
135
        static const char *const ri_names[] = { "Perceptual", "RelativeColorimetric", "Saturation", "AbsoluteColorimetric" };
3370
135
        char buf[32];
3371
3372
135
        code = pdf_open_gstate(pdev, &pres);
3373
135
        if (code < 0)
3374
0
            return code;
3375
3376
135
        buf[0] = '/';
3377
135
        strncpy(buf + 1, ri_names[pgs->renderingintent], sizeof(buf) - 2);
3378
135
        code = cos_dict_put_string_copy(resource_dict(pres), "/RI", buf);
3379
135
        if (code < 0)
3380
0
            return code;
3381
135
        pdev->rendering_intent = pgs->renderingintent;
3382
135
    }
3383
    /* Update overprint, stroke adjustment. */
3384
944k
    if (pdev->params.PreserveOverprintSettings &&
3385
944k
        pdev->stroke_overprint != pgs->stroke_overprint &&
3386
944k
        !pdev->skip_colors
3387
944k
        ) {
3388
908
        if (pres == 0)
3389
823
            code = pdf_open_gstate(pdev, &pres);
3390
908
        if (code < 0)
3391
0
            return code;
3392
908
        code = cos_dict_put_c_key_bool(resource_dict(pres), "/OP", pgs->stroke_overprint);
3393
908
        if (code < 0)
3394
0
            return code;
3395
908
        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
908
        pdev->fill_overprint = pgs->stroke_overprint;
3401
908
    }
3402
944k
    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
26.4k
        if (!pdev->ForOPDFRead) {
3414
16.8k
            code = pdf_open_gstate(pdev, &pres);
3415
16.8k
            if (code < 0)
3416
0
                return code;
3417
16.8k
            code = cos_dict_put_c_key_bool(resource_dict(pres), "/SA", pgs->stroke_adjust);
3418
16.8k
            if (code < 0)
3419
0
                return code;
3420
16.8k
            pdev->state.stroke_adjust = pgs->stroke_adjust;
3421
16.8k
        } else {
3422
9.55k
            if (pgs->stroke_adjust)
3423
1.06k
                stream_puts(gdev_vector_stream((gx_device_vector *)pdev), "true setstrokeadjust\n");
3424
8.49k
            else
3425
8.49k
                stream_puts(gdev_vector_stream((gx_device_vector *)pdev), "false setstrokeadjust\n");
3426
9.55k
            pdev->state.stroke_adjust = pgs->stroke_adjust;
3427
9.55k
        }
3428
3429
26.4k
    }
3430
944k
    return pdf_end_gstate(pdev, pres);
3431
944k
}
3432
int
3433
pdf_prepare_stroke(gx_device_pdf *pdev, const gs_gstate *pgs, bool for_text)
3434
946k
{
3435
946k
    int code;
3436
3437
946k
    if (pdev->context != PDF_IN_STREAM) {
3438
0
        code = pdf_try_prepare_stroke(pdev, pgs, for_text);
3439
0
        if (code != gs_error_interrupt) /* See pdf_open_gstate */
3440
0
            return code;
3441
0
        code = pdf_open_contents(pdev, PDF_IN_STREAM);
3442
0
        if (code < 0)
3443
0
            return code;
3444
0
    }
3445
946k
    return pdf_try_prepare_stroke(pdev, pgs, for_text);
3446
946k
}
3447
3448
static int
3449
pdf_try_prepare_fill_stroke(gx_device_pdf *pdev, const gs_gstate *pgs, bool for_text)
3450
11.3k
{
3451
11.3k
    pdf_resource_t *pres = 0;
3452
11.3k
    int code = pdf_prepare_drawing(pdev, pgs, &pres, for_text);
3453
3454
11.3k
    if (code < 0)
3455
4
        return code;
3456
    /* Update overprint. */
3457
11.2k
    if (pdev->params.PreserveOverprintSettings &&
3458
11.2k
        (pdev->fill_overprint != pgs->overprint ||
3459
11.2k
         pdev->stroke_overprint != pgs->stroke_overprint ||
3460
11.2k
         pdev->font3) && !pdev->skip_colors
3461
11.2k
        ) {
3462
27
        code = pdf_open_gstate(pdev, &pres);
3463
27
        if (code < 0)
3464
4
            return code;
3465
        /* PDF 1.2 only has a single overprint setting. */
3466
23
        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
13
        } else {
3472
13
            code = cos_dict_put_c_key_bool(resource_dict(pres), "/op", pgs->overprint);
3473
13
            if (code < 0)
3474
0
                return code;
3475
13
        }
3476
23
        pdev->fill_overprint = pgs->overprint;
3477
23
    }
3478
    /* Update overprint, stroke adjustment. */
3479
11.2k
    if (pdev->params.PreserveOverprintSettings &&
3480
11.2k
        pdev->stroke_overprint != pgs->stroke_overprint &&
3481
11.2k
        !pdev->skip_colors
3482
11.2k
        ) {
3483
5
        code = pdf_open_gstate(pdev, &pres);
3484
5
        if (code < 0)
3485
0
            return code;
3486
5
        code = cos_dict_put_c_key_bool(resource_dict(pres), "/OP", pgs->stroke_overprint);
3487
5
        if (code < 0)
3488
0
            return code;
3489
5
        pdev->stroke_overprint = pgs->stroke_overprint;
3490
5
        if (pdev->CompatibilityLevel < 1.3) {
3491
            /* PDF 1.2 only has a single overprint setting. */
3492
0
            pdev->fill_overprint = pgs->stroke_overprint;
3493
5
        } else {
3494
            /* According to PDF>=1.3 spec, OP also sets op,
3495
               if there is no /op in same garphic state object.
3496
               We don't write /op, so monitor the viewer's state here : */
3497
5
            pdev->fill_overprint = pgs->overprint;
3498
5
        }
3499
5
    }
3500
11.2k
    if (pdev->state.stroke_adjust != pgs->stroke_adjust) {
3501
2.03k
        code = pdf_open_gstate(pdev, &pres);
3502
2.03k
        if (code < 0)
3503
164
            return code;
3504
1.87k
        code = cos_dict_put_c_key_bool(resource_dict(pres), "/SA", pgs->stroke_adjust);
3505
1.87k
        if (code < 0)
3506
0
            return code;
3507
1.87k
        pdev->state.stroke_adjust = pgs->stroke_adjust;
3508
1.87k
    }
3509
11.1k
    return pdf_end_gstate(pdev, pres);
3510
11.2k
}
3511
3512
int
3513
pdf_prepare_fill_stroke(gx_device_pdf *pdev, const gs_gstate *pgs, bool for_text)
3514
11.1k
{
3515
11.1k
    int code;
3516
3517
11.1k
    if (pdev->context != PDF_IN_STREAM) {
3518
1.23k
        code = pdf_try_prepare_fill_stroke(pdev, pgs, for_text);
3519
1.23k
        if (code != gs_error_interrupt) /* See pdf_open_gstate */
3520
1.06k
            return code;
3521
172
        code = pdf_open_contents(pdev, PDF_IN_STREAM);
3522
172
        if (code < 0)
3523
0
            return code;
3524
172
    }
3525
10.0k
    return pdf_try_prepare_fill_stroke(pdev, pgs, for_text);
3526
11.1k
}
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
102k
{
3532
    /*
3533
     * As it turns out, this requires updating the same parameters as for
3534
     * filling.
3535
     */
3536
102k
    return pdf_prepare_fill(pdev, pgs, false);
3537
102k
}
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
78.4k
{
3544
78.4k
    int code = pdf_prepare_image(pdev, pgs);
3545
3546
78.4k
    if (code < 0)
3547
0
        return code;
3548
78.4k
    return pdf_set_drawing_color(pdev, pgs, pdcolor, &pdev->saved_fill_color,
3549
78.4k
                                 &pdev->fill_used_process_color,
3550
78.4k
                                 &psdf_set_fill_color_commands);
3551
78.4k
}