Coverage Report

Created: 2026-02-14 07:09

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