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