Coverage Report

Created: 2025-12-31 07:31

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