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, ¶ms, 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(¶ms.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, ¶ms, 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