Coverage Report

Created: 2022-10-31 07:00

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