1 /* Copyright (C) 1999, 2000, 2001 Aladdin Enterprises. All rights reserved.
2
3 This software is provided AS-IS with no warranty, either express or
4 implied.
5
6 This software is distributed under license and may not be copied,
7 modified or distributed except as expressly authorized under the terms
8 of the license contained in the file LICENSE in this distribution.
9
10 For more information about licensing, please refer to
11 http://www.ghostscript.com/licensing/. For information on
12 commercial licensing, go to http://www.artifex.com/licensing/ or
13 contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14 San Rafael, CA 94903, U.S.A., +1(415)492-9861.
15 */
16
17 /* $Id: gdevpdfg.c,v 1.68 2005/09/12 11:34:50 leonardo Exp $ */
18 /* Graphics state management for pdfwrite driver */
19 #include "math_.h"
20 #include "string_.h"
21 #include "memory_.h"
22 #include "gx.h"
23 #include "gserrors.h"
24 #include "gsfunc0.h"
25 #include "gsstate.h"
26 #include "gxbitmap.h" /* for gxhttile.h in gzht.h */
27 #include "gxdht.h"
28 #include "gxfarith.h" /* for gs_sin/cos_degrees */
29 #include "gxfmap.h"
30 #include "gxht.h"
31 #include "gxistate.h"
32 #include "gxdcolor.h"
33 #include "gxpcolor.h"
34 #include "gsptype2.h"
35 #include "gzht.h"
36 #include "gdevpdfx.h"
37 #include "gdevpdfg.h"
38 #include "gdevpdfo.h"
39 #include "szlibx.h"
40
41 /* ---------------- Miscellaneous ---------------- */
42
43 /* Save the viewer's graphic state. */
44 int
pdf_save_viewer_state(gx_device_pdf * pdev,stream * s)45 pdf_save_viewer_state(gx_device_pdf *pdev, stream *s)
46 {
47 const int i = pdev->vgstack_depth;
48
49 if (pdev->vgstack_depth >= count_of(pdev->vgstack))
50 return_error(gs_error_unregistered); /* Must not happen. */
51 pdev->vgstack[i].transfer_ids[0] = pdev->transfer_ids[0];
52 pdev->vgstack[i].transfer_ids[1] = pdev->transfer_ids[1];
53 pdev->vgstack[i].transfer_ids[2] = pdev->transfer_ids[2];
54 pdev->vgstack[i].transfer_ids[3] = pdev->transfer_ids[3];
55 pdev->vgstack[i].transfer_not_identity = pdev->transfer_not_identity;
56 pdev->vgstack[i].opacity_alpha = pdev->state.opacity.alpha;
57 pdev->vgstack[i].shape_alpha = pdev->state.shape.alpha;
58 pdev->vgstack[i].blend_mode = pdev->state.blend_mode;
59 pdev->vgstack[i].halftone_id = pdev->halftone_id;
60 pdev->vgstack[i].black_generation_id = pdev->black_generation_id;
61 pdev->vgstack[i].undercolor_removal_id = pdev->undercolor_removal_id;
62 pdev->vgstack[i].overprint_mode = pdev->overprint_mode;
63 pdev->vgstack[i].smoothness = pdev->state.smoothness;
64 pdev->vgstack[i].flatness = pdev->state.flatness;
65 pdev->vgstack[i].text_knockout = pdev->state.text_knockout;
66 pdev->vgstack[i].fill_overprint = pdev->fill_overprint;
67 pdev->vgstack[i].stroke_overprint = pdev->stroke_overprint;
68 pdev->vgstack[i].stroke_adjust = pdev->state.stroke_adjust;
69 pdev->vgstack[i].fill_used_process_color = pdev->fill_used_process_color;
70 pdev->vgstack[i].stroke_used_process_color = pdev->stroke_used_process_color;
71 pdev->vgstack[i].saved_fill_color = pdev->saved_fill_color;
72 pdev->vgstack[i].saved_stroke_color = pdev->saved_stroke_color;
73 pdev->vgstack[i].line_params = pdev->state.line_params;
74 pdev->vgstack[i].line_params.dash.pattern = 0; /* Use pdev->dash_pattern instead. */
75 memcpy(pdev->vgstack[i].dash_pattern, pdev->dash_pattern,
76 sizeof(pdev->vgstack[i].dash_pattern));
77 pdev->vgstack_depth++;
78 if (s)
79 stream_puts(s, "q\n");
80 return 0;
81 }
82
83 /* Load the viewer's graphic state. */
84 private void
pdf_load_viewer_state(gx_device_pdf * pdev,pdf_viewer_state * s)85 pdf_load_viewer_state(gx_device_pdf *pdev, pdf_viewer_state *s)
86 {
87 pdev->transfer_ids[0] = s->transfer_ids[0];
88 pdev->transfer_ids[1] = s->transfer_ids[1];
89 pdev->transfer_ids[2] = s->transfer_ids[2];
90 pdev->transfer_ids[3] = s->transfer_ids[3];
91 pdev->transfer_not_identity = s->transfer_not_identity;
92 pdev->state.opacity.alpha = s->opacity_alpha;
93 pdev->state.shape.alpha = s->shape_alpha;
94 pdev->state.blend_mode = s->blend_mode;
95 pdev->halftone_id = s->halftone_id;
96 pdev->black_generation_id = s->black_generation_id;
97 pdev->undercolor_removal_id = s->undercolor_removal_id;
98 pdev->overprint_mode = s->overprint_mode;
99 pdev->state.smoothness = s->smoothness;
100 pdev->state.flatness = s->flatness;
101 pdev->state.text_knockout = s->text_knockout;
102 pdev->fill_overprint = s->fill_overprint;
103 pdev->stroke_overprint = s->stroke_overprint;
104 pdev->state.stroke_adjust = s->stroke_adjust;
105 pdev->fill_used_process_color = s->fill_used_process_color;
106 pdev->stroke_used_process_color = s->stroke_used_process_color;
107 pdev->saved_fill_color = s->saved_fill_color;
108 pdev->saved_stroke_color = s->saved_stroke_color;
109 pdev->state.line_params = s->line_params;
110 memcpy(pdev->dash_pattern, s->dash_pattern,
111 sizeof(s->dash_pattern));
112 }
113
114
115 /* Restore the viewer's graphic state. */
116 int
pdf_restore_viewer_state(gx_device_pdf * pdev,stream * s)117 pdf_restore_viewer_state(gx_device_pdf *pdev, stream *s)
118 { const int i = --pdev->vgstack_depth;
119
120 if (i < pdev->vgstack_bottom || i < 0)
121 return_error(gs_error_unregistered); /* Must not happen. */
122 if (s)
123 stream_puts(s, "Q\n");
124 pdf_load_viewer_state(pdev, pdev->vgstack + i);
125 return 0;
126 }
127
128 /* Set initial color. */
129 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)130 pdf_set_initial_color(gx_device_pdf * pdev, gx_hl_saved_color *saved_fill_color,
131 gx_hl_saved_color *saved_stroke_color,
132 bool *fill_used_process_color, bool *stroke_used_process_color)
133 {
134 gx_device_color black;
135
136 pdev->black = gx_device_black((gx_device *)pdev);
137 pdev->white = gx_device_white((gx_device *)pdev);
138 set_nonclient_dev_color(&black, pdev->black);
139 gx_hld_save_color(NULL, &black, saved_fill_color);
140 gx_hld_save_color(NULL, &black, saved_stroke_color);
141 *fill_used_process_color = true;
142 *stroke_used_process_color = true;
143 }
144
145 /* Prepare intitial values for viewer's graphics state parameters. */
146 private void
pdf_viewer_state_from_imager_state_aux(pdf_viewer_state * pvs,const gs_imager_state * pis)147 pdf_viewer_state_from_imager_state_aux(pdf_viewer_state *pvs, const gs_imager_state *pis)
148 {
149 pvs->transfer_not_identity =
150 (pis->set_transfer.red != NULL ? pis->set_transfer.red->proc != gs_identity_transfer : 0) * 1 +
151 (pis->set_transfer.green != NULL ? pis->set_transfer.green->proc != gs_identity_transfer : 0) * 2 +
152 (pis->set_transfer.blue != NULL ? pis->set_transfer.blue->proc != gs_identity_transfer : 0) * 4 +
153 (pis->set_transfer.gray != NULL ? pis->set_transfer.gray->proc != gs_identity_transfer : 0) * 8;
154 pvs->transfer_ids[0] = (pis->set_transfer.red != NULL ? pis->set_transfer.red->id : 0);
155 pvs->transfer_ids[1] = (pis->set_transfer.green != NULL ? pis->set_transfer.green->id : 0);
156 pvs->transfer_ids[2] = (pis->set_transfer.blue != NULL ? pis->set_transfer.blue->id : 0);
157 pvs->transfer_ids[3] = (pis->set_transfer.gray != NULL ? pis->set_transfer.gray->id : 0);
158 pvs->opacity_alpha = pis->opacity.alpha;
159 pvs->shape_alpha = pis->shape.alpha;
160 pvs->blend_mode = pis->blend_mode;
161 pvs->halftone_id = (pis->dev_ht != 0 ? pis->dev_ht->id : 0);
162 pvs->black_generation_id = (pis->black_generation != 0 ? pis->black_generation->id : 0);
163 pvs->undercolor_removal_id = (pis->undercolor_removal != 0 ? pis->undercolor_removal->id : 0);
164 pvs->overprint_mode = 0;
165 pvs->smoothness = pis->smoothness;
166 pvs->text_knockout = pis->text_knockout;
167 pvs->fill_overprint = false;
168 pvs->stroke_overprint = false;
169 pvs->stroke_adjust = false;
170 pvs->line_params.half_width = 0.5;
171 pvs->line_params.cap = 0;
172 pvs->line_params.join = 0;
173 pvs->line_params.curve_join = 0;
174 pvs->line_params.miter_limit = 10.0;
175 pvs->line_params.miter_check = 0;
176 pvs->line_params.dot_length = pis->line_params.dot_length;
177 pvs->line_params.dot_length_absolute = pis->line_params.dot_length_absolute;
178 pvs->line_params.dot_orientation = pis->line_params.dot_orientation;
179 memset(&pvs->line_params.dash, 0 , sizeof(pvs->line_params.dash));
180 memset(pvs->dash_pattern, 0, sizeof(pvs->dash_pattern));
181 }
182
183 /* Copy viewer state from images state. */
184 void
pdf_viewer_state_from_imager_state(gx_device_pdf * pdev,const gs_imager_state * pis,const gx_device_color * pdevc)185 pdf_viewer_state_from_imager_state(gx_device_pdf * pdev,
186 const gs_imager_state *pis, const gx_device_color *pdevc)
187 {
188 pdf_viewer_state vs;
189
190 pdf_viewer_state_from_imager_state_aux(&vs, pis);
191 gx_hld_save_color(pis, pdevc, &vs.saved_fill_color);
192 gx_hld_save_color(pis, pdevc, &vs.saved_stroke_color);
193 pdf_load_viewer_state(pdev, &vs);
194 }
195
196 /* Prepare intitial values for viewer's graphics state parameters. */
197 void
pdf_prepare_initial_viewer_state(gx_device_pdf * pdev,const gs_imager_state * pis)198 pdf_prepare_initial_viewer_state(gx_device_pdf * pdev, const gs_imager_state *pis)
199 {
200 /* Parameter values, which are specified in PDF spec, are set here.
201 * Parameter values, which are specified in PDF spec as "installation dependent",
202 * are set here to intial values used with PS interpreter.
203 * This allows to write differences to the output file
204 * and skip initial values.
205 */
206
207 pdf_set_initial_color(pdev, &pdev->vg_initial.saved_fill_color, &pdev->vg_initial.saved_stroke_color,
208 &pdev->vg_initial.fill_used_process_color, &pdev->vg_initial.stroke_used_process_color);
209 pdf_viewer_state_from_imager_state_aux(&pdev->vg_initial, pis);
210 pdev->vg_initial_set = true;
211 /*
212 * Some parameters listed in PDF spec are missed here :
213 * text state - it is initialized per page.
214 * rendering intent - not sure why, fixme.
215 */
216 }
217
218 /* Reset the graphics state parameters to initial values. */
219 /* Used if pdf_prepare_initial_viewer_state was not callad. */
220 private void
pdf_reset_graphics_old(gx_device_pdf * pdev)221 pdf_reset_graphics_old(gx_device_pdf * pdev)
222 {
223
224 pdf_set_initial_color(pdev, &pdev->saved_fill_color, &pdev->saved_stroke_color,
225 &pdev->fill_used_process_color, &pdev->stroke_used_process_color);
226 pdev->state.flatness = -1;
227 {
228 static const gx_line_params lp_initial = {
229 gx_line_params_initial
230 };
231
232 pdev->state.line_params = lp_initial;
233 }
234 pdev->fill_overprint = false;
235 pdev->stroke_overprint = false;
236 pdf_reset_text(pdev);
237 }
238
239 /* Reset the graphics state parameters to initial values. */
240 void
pdf_reset_graphics(gx_device_pdf * pdev)241 pdf_reset_graphics(gx_device_pdf * pdev)
242 {
243 if (pdev->vg_initial_set)
244 pdf_load_viewer_state(pdev, &pdev->vg_initial);
245 else
246 pdf_reset_graphics_old(pdev);
247 pdf_reset_text(pdev);
248 }
249
250 /* Write client color. */
251 private int
pdf_write_ccolor(gx_device_pdf * pdev,const gs_imager_state * pis,const gs_client_color * pcc)252 pdf_write_ccolor(gx_device_pdf * pdev, const gs_imager_state * pis,
253 const gs_client_color *pcc)
254 {
255 int i, n = gx_hld_get_number_color_components(pis);
256
257 pprintg1(pdev->strm, "%g", psdf_round(pcc->paint.values[0], 255, 8));
258 for (i = 1; i < n; i++) {
259 pprintg1(pdev->strm, " %g", psdf_round(pcc->paint.values[i], 255, 8));
260 }
261 return 0;
262 }
263
264
265 /* Set the fill or stroke color. */
266 private int
pdf_reset_color(gx_device_pdf * pdev,const gs_imager_state * pis,const gx_drawing_color * pdc,gx_hl_saved_color * psc,bool * used_process_color,const psdf_set_color_commands_t * ppscc)267 pdf_reset_color(gx_device_pdf * pdev, const gs_imager_state * pis,
268 const gx_drawing_color *pdc, gx_hl_saved_color * psc,
269 bool *used_process_color,
270 const psdf_set_color_commands_t *ppscc)
271 {
272 int code;
273 gx_hl_saved_color temp;
274 bool process_color;
275 const gs_color_space *pcs, *pcs2;
276 const gs_client_color *pcc; /* fixme: not needed due to gx_hld_get_color_component. */
277 cos_value_t cs_value;
278 const char *command;
279 int code1 = 0;
280 gs_color_space_index csi;
281
282 if (pdev->skip_colors)
283 return 0;
284 process_color = !gx_hld_save_color(pis, pdc, &temp);
285 /* Since pdfwrite never applies halftones and patterns, but monitors
286 * halftone/pattern IDs separately, we don't need to compare
287 * halftone/pattern bodies here.
288 */
289 if (gx_hld_saved_color_equal(&temp, psc))
290 return 0;
291 /*
292 * In principle, we can set colors in either stream or text
293 * context. However, since we currently enclose all text
294 * strings inside a gsave/grestore, this causes us to lose
295 * track of the color when we leave text context. Therefore,
296 * we require stream context for setting colors.
297 */
298 code = pdf_open_page(pdev, PDF_IN_STREAM);
299 if (code < 0)
300 return code;
301 switch (gx_hld_get_color_space_and_ccolor(pis, pdc, &pcs, &pcc)) {
302 case non_pattern_color_space:
303 switch (gs_color_space_get_index(pcs)) {
304 case gs_color_space_index_DeviceGray:
305 command = ppscc->setgray;
306 break;
307 case gs_color_space_index_DeviceRGB:
308 command = ppscc->setrgbcolor;
309 break;
310 case gs_color_space_index_DeviceCMYK:
311 command = ppscc->setcmykcolor;
312 break;
313 case gs_color_space_index_Indexed:
314 if (pdev->CompatibilityLevel <= 1.2) {
315 pcs2 = (const gs_color_space *)&pcs->params.indexed.base_space;
316 csi = gs_color_space_get_index(pcs2);
317 if (csi == gs_color_space_index_Separation) {
318 pcs2 = (const gs_color_space *)&pcs2->params.separation.alt_space;
319 goto check_pcs2;
320 }
321 goto check_pcs2;
322 }
323 goto scn;
324 case gs_color_space_index_Separation:
325 if (pdev->CompatibilityLevel <= 1.2) {
326 pcs2 = (const gs_color_space *)&pcs->params.separation.alt_space;
327 check_pcs2:
328 csi = gs_color_space_get_index(pcs2);
329 switch(gs_color_space_get_index(pcs2)) {
330 case gs_color_space_index_DevicePixel :
331 case gs_color_space_index_DeviceN:
332 case gs_color_space_index_CIEICC:
333 goto write_process_color;
334 default:
335 DO_NOTHING;
336 }
337 }
338 goto scn;
339 case gs_color_space_index_CIEICC:
340 case gs_color_space_index_DevicePixel:
341 case gs_color_space_index_DeviceN:
342 if (pdev->CompatibilityLevel <= 1.2)
343 goto write_process_color;
344 goto scn;
345 default :
346 scn:
347 command = ppscc->setcolorn;
348 if (!gx_hld_saved_color_same_cspace(&temp, psc)) {
349 code = pdf_color_space(pdev, &cs_value, NULL, pcs,
350 &pdf_color_space_names, true);
351 /* fixme : creates redundant PDF objects. */
352 if (code == gs_error_rangecheck) {
353 /* The color space can't write to PDF. */
354 goto write_process_color;
355 }
356 if (code < 0)
357 return code;
358 code = cos_value_write(&cs_value, pdev);
359 if (code < 0)
360 return code;
361 pprints1(pdev->strm, " %s\n", ppscc->setcolorspace);
362 } else if (*used_process_color)
363 goto write_process_color;
364 break;
365 }
366 *used_process_color = false;
367 code = pdf_write_ccolor(pdev, pis, pcc);
368 if (code < 0)
369 return code;
370 pprints1(pdev->strm, " %s\n", command);
371 break;
372 case pattern_color_sapce:
373 { pdf_resource_t *pres;
374
375 if (pdc->type == gx_dc_type_pattern)
376 code = pdf_put_colored_pattern(pdev, pdc, pcs,
377 ppscc, pis->have_pattern_streams, &pres);
378 else if (pdc->type == &gx_dc_pure_masked) {
379 code = pdf_put_uncolored_pattern(pdev, pdc, pcs,
380 ppscc, pis->have_pattern_streams, &pres);
381 if (code < 0 || pres == 0)
382 return code;
383 if (pis->have_pattern_streams)
384 code = pdf_write_ccolor(pdev, pis, pcc);
385 } else if (pdc->type == &gx_dc_pattern2) {
386 if (pdev->CompatibilityLevel <= 1.2)
387 return_error(gs_error_rangecheck);
388 code1 = pdf_put_pattern2(pdev, pdc, ppscc, &pres);
389 } else
390 return_error(gs_error_rangecheck);
391 if (code < 0)
392 return code;
393 cos_value_write(cos_resource_value(&cs_value, pres->object), pdev);
394 pprints1(pdev->strm, " %s\n", ppscc->setcolorn);
395 code = pdf_add_resource(pdev, pdev->substream_Resources, "/Pattern", pres);
396 if (code < 0)
397 return code;
398 }
399 *used_process_color = false;
400 break;
401 default: /* must not happen. */
402 case use_process_color:
403 write_process_color:
404 code = psdf_set_color((gx_device_vector *)pdev, pdc, ppscc);
405 if (code < 0)
406 return code;
407 *used_process_color = true;
408 }
409 *psc = temp;
410 return code1;
411 }
412 int
pdf_set_drawing_color(gx_device_pdf * pdev,const gs_imager_state * pis,const gx_drawing_color * pdc,gx_hl_saved_color * psc,bool * used_process_color,const psdf_set_color_commands_t * ppscc)413 pdf_set_drawing_color(gx_device_pdf * pdev, const gs_imager_state * pis,
414 const gx_drawing_color *pdc,
415 gx_hl_saved_color * psc,
416 bool *used_process_color,
417 const psdf_set_color_commands_t *ppscc)
418 {
419 return pdf_reset_color(pdev, pis, pdc, psc, used_process_color, ppscc);
420 }
421 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)422 pdf_set_pure_color(gx_device_pdf * pdev, gx_color_index color,
423 gx_hl_saved_color * psc,
424 bool *used_process_color,
425 const psdf_set_color_commands_t *ppscc)
426 {
427 gx_drawing_color dcolor;
428
429 set_nonclient_dev_color(&dcolor, color);
430 return pdf_reset_color(pdev, NULL, &dcolor, psc, used_process_color, ppscc);
431 }
432
433 /*
434 * Convert a string into cos name.
435 */
436 int
pdf_string_to_cos_name(gx_device_pdf * pdev,const byte * str,uint len,cos_value_t * pvalue)437 pdf_string_to_cos_name(gx_device_pdf *pdev, const byte *str, uint len,
438 cos_value_t *pvalue)
439 {
440 byte *chars = gs_alloc_string(pdev->pdf_memory, len + 1,
441 "pdf_string_to_cos_name");
442
443 if (chars == 0)
444 return_error(gs_error_VMerror);
445 chars[0] = '/';
446 memcpy(chars + 1, str, len);
447 cos_string_value(pvalue, chars, len + 1);
448 return 0;
449 }
450
451 /* ---------------- Graphics state updating ---------------- */
452
453 /* ------ Functions ------ */
454
455 /* Define the maximum size of a Function reference. */
456 #define MAX_FN_NAME_CHARS 9 /* /Default, /Identity */
457 #define MAX_FN_CHARS max(MAX_REF_CHARS + 4, MAX_FN_NAME_CHARS)
458
459 /*
460 * Create and write a Function for a gx_transfer_map. We use this for
461 * transfer, BG, and UCR functions. If check_identity is true, check for
462 * an identity map. Return 1 if the map is the identity map, otherwise
463 * return 0.
464 */
465 private data_source_proc_access(transfer_map_access); /* check prototype */
466 private int
transfer_map_access(const gs_data_source_t * psrc,ulong start,uint length,byte * buf,const byte ** ptr)467 transfer_map_access(const gs_data_source_t *psrc, ulong start, uint length,
468 byte *buf, const byte **ptr)
469 {
470 const gx_transfer_map *map = (const gx_transfer_map *)psrc->data.str.data;
471 uint i;
472
473 if (ptr)
474 *ptr = buf;
475 for (i = 0; i < length; ++i)
476 buf[i] = frac2byte(map->values[(uint)start + i]);
477 return 0;
478 }
479 private int
transfer_map_access_signed(const gs_data_source_t * psrc,ulong start,uint length,byte * buf,const byte ** ptr)480 transfer_map_access_signed(const gs_data_source_t *psrc,
481 ulong start, uint length,
482 byte *buf, const byte **ptr)
483 {
484 /* To prevent numeric errors, we need to map 0 to an integer.
485 * We can't apply a general expression, because Decode isn't accessible here.
486 * Assuming this works for UCR only.
487 * Assuming the range of UCR is always [-1, 1].
488 * Assuming BitsPerSample = 8.
489 */
490 const gx_transfer_map *map = (const gx_transfer_map *)psrc->data.str.data;
491 uint i;
492
493 *ptr = buf;
494 for (i = 0; i < length; ++i)
495 buf[i] = (byte)
496 ((frac2float(map->values[(uint)start + i]) + 1) * 127);
497 return 0;
498 }
499 private int
pdf_write_transfer_map(gx_device_pdf * pdev,const gx_transfer_map * map,int range0,bool check_identity,const char * key,char * ids)500 pdf_write_transfer_map(gx_device_pdf *pdev, const gx_transfer_map *map,
501 int range0, bool check_identity,
502 const char *key, char *ids)
503 {
504 gs_memory_t *mem = pdev->pdf_memory;
505 gs_function_Sd_params_t params;
506 static const float domain01[2] = { 0, 1 };
507 static const int size = transfer_map_size;
508 float range01[2], decode[2];
509 gs_function_t *pfn;
510 long id;
511 int code;
512
513 if (map == 0) {
514 *ids = 0; /* no map */
515 return 1;
516 }
517 if (check_identity) {
518 /* Check for an identity map. */
519 int i;
520
521 if (map->proc == gs_identity_transfer)
522 i = transfer_map_size;
523 else
524 for (i = 0; i < transfer_map_size; ++i) {
525 fixed d = map->values[i] - bits2frac(i, log2_transfer_map_size);
526 if (any_abs(d) > fixed_epsilon) /* ignore small noise */
527 break;
528 }
529 if (i == transfer_map_size) {
530 strcpy(ids, key);
531 strcat(ids, "/Identity");
532 return 1;
533 }
534 }
535 params.m = 1;
536 params.Domain = domain01;
537 params.n = 1;
538 range01[0] = (float)range0, range01[1] = 1.0;
539 params.Range = range01;
540 params.Order = 1;
541 params.DataSource.access =
542 (range0 < 0 ? transfer_map_access_signed : transfer_map_access);
543 params.DataSource.data.str.data = (const byte *)map; /* bogus */
544 /* DataSource */
545 params.BitsPerSample = 8; /* could be 16 */
546 params.Encode = 0;
547 if (range01[0] < 0 && range01[1] > 0) {
548 /* This works for UCR only.
549 * Map 0 to an integer.
550 * Rather the range of UCR is always [-1, 1],
551 * we prefer a general expression.
552 */
553 int r0 = (int)( -range01[0] * ((1 << params.BitsPerSample) - 1)
554 / (range01[1] - range01[0]) ); /* Round down. */
555 float r1 = r0 * range01[1] / -range01[0]; /* r0 + r1 <= (1 << params.BitsPerSample) - 1 */
556
557 decode[0] = range01[0];
558 decode[1] = range01[0] + (range01[1] - range01[0]) * ((1 << params.BitsPerSample) - 1)
559 / (r0 + r1);
560 params.Decode = decode;
561 } else
562 params.Decode = 0;
563 params.Size = &size;
564 code = gs_function_Sd_init(&pfn, ¶ms, mem);
565 if (code < 0)
566 return code;
567 code = pdf_write_function(pdev, pfn, &id);
568 gs_function_free(pfn, false, mem);
569 if (code < 0)
570 return code;
571 sprintf(ids, "%s%s%ld 0 R", key, (key[0] && key[0] != ' ' ? " " : ""), id);
572 return 0;
573 }
574 private int
pdf_write_transfer(gx_device_pdf * pdev,const gx_transfer_map * map,const char * key,char * ids)575 pdf_write_transfer(gx_device_pdf *pdev, const gx_transfer_map *map,
576 const char *key, char *ids)
577 {
578 return pdf_write_transfer_map(pdev, map, 0, true, key, ids);
579 }
580
581 /* ------ Halftones ------ */
582
583 /*
584 * Recognize the predefined PDF halftone functions. Note that because the
585 * corresponding PostScript functions use single-precision floats, the
586 * functions used for testing must do the same in order to get identical
587 * results. Currently we only do this for a few of the functions.
588 */
589 #define HT_FUNC(name, expr)\
590 private floatp name(floatp xd, floatp yd) {\
591 float x = (float)xd, y = (float)yd;\
592 return d2f(expr);\
593 }
594
595 /*
596 * In most versions of gcc (e.g., 2.7.2.3, 2.95.4), return (float)xxx
597 * doesn't actually do the coercion. Force this here. Note that if we
598 * use 'inline', it doesn't work.
599 */
600 private float
d2f(floatp d)601 d2f(floatp d)
602 {
603 float f = (float)d;
604 return f;
605 }
606 private floatp
ht_Round(floatp xf,floatp yf)607 ht_Round(floatp xf, floatp yf)
608 {
609 float x = (float)xf, y = (float)yf;
610 float xabs = fabs(x), yabs = fabs(y);
611
612 if (d2f(xabs + yabs) <= 1)
613 return d2f(1 - d2f(d2f(x * x) + d2f(y * y)));
614 xabs -= 1, yabs -= 1;
615 return d2f(d2f(d2f(xabs * xabs) + d2f(yabs * yabs)) - 1);
616 }
617 private floatp
ht_Diamond(floatp xf,floatp yf)618 ht_Diamond(floatp xf, floatp yf)
619 {
620 float x = (float)xf, y = (float)yf;
621 float xabs = fabs(x), yabs = fabs(y);
622
623 if (d2f(xabs + yabs) <= 0.75)
624 return d2f(1 - d2f(d2f(x * x) + d2f(y * y)));
625 if (d2f(xabs + yabs) <= d2f(1.23))
626 return d2f(1 - d2f(d2f(d2f(0.85) * xabs) + yabs));
627 xabs -= 1, yabs -= 1;
628 return d2f(d2f(d2f(xabs * xabs) + d2f(yabs * yabs)) - 1);
629 }
630 private floatp
ht_Ellipse(floatp xf,floatp yf)631 ht_Ellipse(floatp xf, floatp yf)
632 {
633 float x = (float)xf, y = (float)yf;
634 float xabs = fabs(x), yabs = fabs(y);
635 /*
636 * The PDF Reference, 2nd edition, incorrectly specifies the
637 * computation w = 4 * |x| + 3 * |y| - 3. The PostScript code in the
638 * same book correctly implements w = 3 * |x| + 4 * |y| - 3.
639 */
640 float w = (float)(d2f(d2f(3 * xabs) + d2f(4 * yabs)) - 3);
641
642 if (w < 0) {
643 yabs /= 0.75;
644 return d2f(1 - d2f((d2f(x * x) + d2f(yabs * yabs)) / 4));
645 }
646 if (w > 1) {
647 xabs = 1 - xabs, yabs = d2f(1 - yabs) / 0.75;
648 return d2f(d2f((d2f(xabs * xabs) + d2f(yabs * yabs)) / 4) - 1);
649 }
650 return d2f(0.5 - w);
651 }
652 /*
653 * Most of these are recognized properly even without d2f. We've only
654 * added d2f where it apparently makes a difference.
655 */
656 private float
d2fsin_d(double x)657 d2fsin_d(double x) {
658 return d2f(gs_sin_degrees(d2f(x)));
659 }
660 private float
d2fcos_d(double x)661 d2fcos_d(double x) {
662 return d2f(gs_cos_degrees(d2f(x)));
663 }
664 HT_FUNC(ht_EllipseA, 1 - (x * x + 0.9 * y * y))
665 HT_FUNC(ht_InvertedEllipseA, x * x + 0.9 * y * y - 1)
666 HT_FUNC(ht_EllipseB, 1 - sqrt(x * x + 0.625 * y * y))
667 HT_FUNC(ht_EllipseC, 1 - (0.9 * x * x + y * y))
668 HT_FUNC(ht_InvertedEllipseC, 0.9 * x * x + y * y - 1)
669 HT_FUNC(ht_Line, -fabs((x - x) + y)) /* quiet compiler (unused variable x) */
670 HT_FUNC(ht_LineX, (y - y) + x) /* quiet compiler (unused variable y) */
671 HT_FUNC(ht_LineY, (x - x) + y) /* quiet compiler (unused variable x) */
672 HT_FUNC(ht_Square, -max(fabs(x), fabs(y)))
673 HT_FUNC(ht_Cross, -min(fabs(x), fabs(y)))
674 HT_FUNC(ht_Rhomboid, (0.9 * fabs(x) + fabs(y)) / 2)
675 HT_FUNC(ht_DoubleDot, (d2fsin_d(x * 360) + d2fsin_d(y * 360)) / 2)
676 HT_FUNC(ht_InvertedDoubleDot, -(d2fsin_d(x * 360) + d2fsin_d(y * 360)) / 2)
677 HT_FUNC(ht_SimpleDot, 1 - d2f(d2f(x * x) + d2f(y * y)))
678 HT_FUNC(ht_InvertedSimpleDot, d2f(d2f(x * x) + d2f(y * y)) - 1)
679 HT_FUNC(ht_CosineDot, (d2fcos_d(x * 180) + d2fcos_d(y * 180)) / 2)
680 HT_FUNC(ht_Double, (d2fsin_d(x * 180) + d2fsin_d(y * 360)) / 2)
681 HT_FUNC(ht_InvertedDouble, -(d2fsin_d(x * 180) + d2fsin_d(y * 360)) / 2)
682 typedef struct ht_function_s {
683 const char *fname;
684 floatp (*proc)(floatp, floatp);
685 } ht_function_t;
686 private const ht_function_t ht_functions[] = {
687 {"Round", ht_Round},
688 {"Diamond", ht_Diamond},
689 {"Ellipse", ht_Ellipse},
690 {"EllipseA", ht_EllipseA},
691 {"InvertedEllipseA", ht_InvertedEllipseA},
692 {"EllipseB", ht_EllipseB},
693 {"EllipseC", ht_EllipseC},
694 {"InvertedEllipseC", ht_InvertedEllipseC},
695 {"Line", ht_Line},
696 {"LineX", ht_LineX},
697 {"LineY", ht_LineY},
698 {"Square", ht_Square},
699 {"Cross", ht_Cross},
700 {"Rhomboid", ht_Rhomboid},
701 {"DoubleDot", ht_DoubleDot},
702 {"InvertedDoubleDot", ht_InvertedDoubleDot},
703 {"SimpleDot", ht_SimpleDot},
704 {"InvertedSimpleDot", ht_InvertedSimpleDot},
705 {"CosineDot", ht_CosineDot},
706 {"Double", ht_Double},
707 {"InvertedDouble", ht_InvertedDouble}
708 };
709
710 /* Write each kind of halftone. */
711 private int
pdf_write_spot_function(gx_device_pdf * pdev,const gx_ht_order * porder,long * pid)712 pdf_write_spot_function(gx_device_pdf *pdev, const gx_ht_order *porder,
713 long *pid)
714 {
715 /****** DOESN'T HANDLE STRIP HALFTONES ******/
716 int w = porder->width, h = porder->height;
717 uint num_bits = porder->num_bits;
718 gs_function_Sd_params_t params;
719 static const float domain_spot[4] = { -1, 1, -1, 1 };
720 static const float range_spot[4] = { -1, 1 };
721 int size[2];
722 gs_memory_t *mem = pdev->pdf_memory;
723 /*
724 * Even though the values are logically ushort, we must always store
725 * them in big-endian order, so we access them as bytes.
726 */
727 byte *values;
728 gs_function_t *pfn;
729 uint i;
730 int code = 0;
731
732 params.m = 2;
733 params.Domain = domain_spot;
734 params.n = 1;
735 params.Range = range_spot;
736 params.Order = 0; /* default */
737 /*
738 * We could use 8, 16, or 32 bits per sample to save space, but for
739 * simplicity, we always use 16.
740 */
741 if (num_bits > 0x10000)
742 return_error(gs_error_rangecheck);
743 params.BitsPerSample = 16;
744 params.Encode = 0;
745 /*
746 * The default Decode array maps the actual data values [1 .. w*h] to a
747 * sub-interval of the Range, but that's OK, since all that matters is
748 * the relative values, not the absolute values.
749 */
750 params.Decode = 0;
751 size[0] = w;
752 size[1] = h;
753 params.Size = size;
754 /* Create the (temporary) threshold array. */
755 values = gs_alloc_byte_array(mem, num_bits, 2, "pdf_write_spot_function");
756 if (values == 0)
757 return_error(gs_error_VMerror);
758 for (i = 0; i < num_bits; ++i) {
759 gs_int_point pt;
760 int value;
761
762 if ((code = porder->procs->bit_index(porder, i, &pt)) < 0)
763 break;
764 value = pt.y * w + pt.x;
765 /* Always store the values in big-endian order. */
766 values[i * 2] = (byte)(value >> 8);
767 values[i * 2 + 1] = (byte)value;
768 }
769 data_source_init_bytes(¶ms.DataSource, (const byte *)values,
770 sizeof(*values) * num_bits);
771 if (code >= 0 &&
772 (code = gs_function_Sd_init(&pfn, ¶ms, mem)) >= 0
773 ) {
774 code = pdf_write_function(pdev, pfn, pid);
775 gs_function_free(pfn, false, mem);
776 }
777 gs_free_object(mem, values, "pdf_write_spot_function");
778 return code;
779 }
780 private int
pdf_write_spot_halftone(gx_device_pdf * pdev,const gs_spot_halftone * psht,const gx_ht_order * porder,long * pid)781 pdf_write_spot_halftone(gx_device_pdf *pdev, const gs_spot_halftone *psht,
782 const gx_ht_order *porder, long *pid)
783 {
784 char trs[17 + MAX_FN_CHARS + 1];
785 int code = pdf_write_transfer(pdev, porder->transfer, "/TransferFunction",
786 trs);
787 long id, spot_id;
788 stream *s;
789 int i = countof(ht_functions);
790 gs_memory_t *mem = pdev->pdf_memory;
791
792 if (code < 0)
793 return code;
794 /*
795 * See if we can recognize the spot function, by comparing its sampled
796 * values against those in the order.
797 */
798 { gs_screen_enum senum;
799 gx_ht_order order;
800 int code;
801
802 order = *porder;
803 code = gs_screen_order_alloc(&order, mem);
804 if (code < 0)
805 goto notrec;
806 for (i = 0; i < countof(ht_functions); ++i) {
807 floatp (*spot_proc)(floatp, floatp) = ht_functions[i].proc;
808 gs_point pt;
809
810 gs_screen_enum_init_memory(&senum, &order, NULL, &psht->screen,
811 mem);
812 while ((code = gs_screen_currentpoint(&senum, &pt)) == 0 &&
813 gs_screen_next(&senum, spot_proc(pt.x, pt.y)) >= 0)
814 DO_NOTHING;
815 if (code < 0)
816 continue;
817 /* Compare the bits and levels arrays. */
818 if (memcmp(order.levels, porder->levels,
819 order.num_levels * sizeof(*order.levels)))
820 continue;
821 if (memcmp(order.bit_data, porder->bit_data,
822 order.num_bits * porder->procs->bit_data_elt_size))
823 continue;
824 /* We have a match. */
825 break;
826 }
827 gx_ht_order_release(&order, mem, false);
828 }
829 notrec:
830 if (i == countof(ht_functions)) {
831 /* Create and write a Function for the spot function. */
832 pdf_write_spot_function(pdev, porder, &spot_id);
833 }
834 *pid = id = pdf_begin_separate(pdev);
835 s = pdev->strm;
836 /* Use the original, requested frequency and angle. */
837 pprintg2(s, "<</Type/Halftone/HalftoneType 1/Frequency %g/Angle %g",
838 psht->screen.frequency, psht->screen.angle);
839 if (i < countof(ht_functions))
840 pprints1(s, "/SpotFunction/%s", ht_functions[i].fname);
841 else
842 pprintld1(s, "/SpotFunction %ld 0 R", spot_id);
843 stream_puts(s, trs);
844 if (psht->accurate_screens)
845 stream_puts(s, "/AccurateScreens true");
846 stream_puts(s, ">>\n");
847 return pdf_end_separate(pdev);
848 }
849 private int
pdf_write_screen_halftone(gx_device_pdf * pdev,const gs_screen_halftone * psht,const gx_ht_order * porder,long * pid)850 pdf_write_screen_halftone(gx_device_pdf *pdev, const gs_screen_halftone *psht,
851 const gx_ht_order *porder, long *pid)
852 {
853 gs_spot_halftone spot;
854
855 spot.screen = *psht;
856 spot.accurate_screens = false;
857 spot.transfer = 0;
858 spot.transfer_closure.proc = 0;
859 return pdf_write_spot_halftone(pdev, &spot, porder, pid);
860 }
861 private int
pdf_write_colorscreen_halftone(gx_device_pdf * pdev,const gs_colorscreen_halftone * pcsht,const gx_device_halftone * pdht,long * pid)862 pdf_write_colorscreen_halftone(gx_device_pdf *pdev,
863 const gs_colorscreen_halftone *pcsht,
864 const gx_device_halftone *pdht, long *pid)
865 {
866 int i;
867 stream *s;
868 long ht_ids[4];
869
870 for (i = 0; i < pdht->num_comp ; ++i) {
871 int code = pdf_write_screen_halftone(pdev, &pcsht->screens.indexed[i],
872 &pdht->components[i].corder,
873 &ht_ids[i]);
874 if (code < 0)
875 return code;
876 }
877 *pid = pdf_begin_separate(pdev);
878 s = pdev->strm;
879 /* Use Black, Gray as the Default unless we are in RGB colormodel */
880 /* (num_comp < 4) in which case we use Green (arbitrarily) */
881 pprintld1(s, "<</Type/Halftone/HalftoneType 5/Default %ld 0 R\n",
882 pdht->num_comp > 3 ? ht_ids[3] : ht_ids[1]);
883 pprintld2(s, "/Red %ld 0 R/Cyan %ld 0 R", ht_ids[0], ht_ids[0]);
884 pprintld2(s, "/Green %ld 0 R/Magenta %ld 0 R", ht_ids[1], ht_ids[1]);
885 pprintld2(s, "/Blue %ld 0 R/Yellow %ld 0 R", ht_ids[2], ht_ids[2]);
886 if (pdht->num_comp > 3)
887 pprintld2(s, "/Gray %ld 0 R/Black %ld 0 R", ht_ids[3], ht_ids[3]);
888 stream_puts(s, ">>\n");
889 return pdf_end_separate(pdev);
890 }
891
892 #define CHECK(expr)\
893 BEGIN if ((code = (expr)) < 0) return code; END
894
895 private int
pdf_write_threshold_halftone(gx_device_pdf * pdev,const gs_threshold_halftone * ptht,const gx_ht_order * porder,long * pid)896 pdf_write_threshold_halftone(gx_device_pdf *pdev,
897 const gs_threshold_halftone *ptht,
898 const gx_ht_order *porder, long *pid)
899 {
900 char trs[17 + MAX_FN_CHARS + 1];
901 stream *s;
902 pdf_data_writer_t writer;
903 int code = pdf_write_transfer(pdev, porder->transfer, "",
904 trs);
905
906 if (code < 0)
907 return code;
908 CHECK(pdf_begin_data(pdev, &writer));
909 s = pdev->strm;
910 *pid = writer.pres->object->id;
911 CHECK(cos_dict_put_c_strings((cos_dict_t *)writer.pres->object,
912 "/Type", "/Halftone"));
913 CHECK(cos_dict_put_c_strings((cos_dict_t *)writer.pres->object,
914 "/HalftoneType", "6"));
915 CHECK(cos_dict_put_c_key_int((cos_dict_t *)writer.pres->object,
916 "/Width", ptht->width));
917 CHECK(cos_dict_put_c_key_int((cos_dict_t *)writer.pres->object,
918 "/Height", ptht->height));
919 if (*trs != 0)
920 CHECK(cos_dict_put_c_strings((cos_dict_t *)writer.pres->object,
921 "/TransferFunction", trs));
922 stream_write(writer.binary.strm, ptht->thresholds.data, ptht->thresholds.size);
923 return pdf_end_data(&writer);
924 }
925 private int
pdf_write_threshold2_halftone(gx_device_pdf * pdev,const gs_threshold2_halftone * ptht,const gx_ht_order * porder,long * pid)926 pdf_write_threshold2_halftone(gx_device_pdf *pdev,
927 const gs_threshold2_halftone *ptht,
928 const gx_ht_order *porder, long *pid)
929 {
930 char trs[17 + MAX_FN_CHARS + 1];
931 stream *s;
932 pdf_data_writer_t writer;
933 int code = pdf_write_transfer(pdev, porder->transfer, "/TransferFunction",
934 trs);
935
936 if (code < 0)
937 return code;
938 CHECK(pdf_begin_data(pdev, &writer));
939 s = pdev->strm;
940 *pid = writer.pres->object->id;
941 CHECK(cos_dict_put_c_strings((cos_dict_t *)writer.pres->object,
942 "/Type", "/Halftone"));
943 CHECK(cos_dict_put_c_strings((cos_dict_t *)writer.pres->object,
944 "/HalftoneType", "16"));
945 CHECK(cos_dict_put_c_key_int((cos_dict_t *)writer.pres->object,
946 "/Width", ptht->width));
947 CHECK(cos_dict_put_c_key_int((cos_dict_t *)writer.pres->object,
948 "/Height", ptht->height));
949 if (ptht->width2 && ptht->height2) {
950 CHECK(cos_dict_put_c_key_int((cos_dict_t *)writer.pres->object,
951 "/Width2", ptht->width2));
952 CHECK(cos_dict_put_c_key_int((cos_dict_t *)writer.pres->object,
953 "/Height2", ptht->height2));
954 }
955 if (*trs != 0)
956 CHECK(cos_dict_put_c_strings((cos_dict_t *)writer.pres->object,
957 "/TransferFunction", trs));
958 s = writer.binary.strm;
959 if (ptht->bytes_per_sample == 2)
960 stream_write(s, ptht->thresholds.data, ptht->thresholds.size);
961 else {
962 /* Expand 1-byte to 2-byte samples. */
963 int i;
964
965 for (i = 0; i < ptht->thresholds.size; ++i) {
966 byte b = ptht->thresholds.data[i];
967
968 stream_putc(s, b);
969 stream_putc(s, b);
970 }
971 }
972 return pdf_end_data(&writer);
973 }
974 private int
pdf_get_halftone_component_index(const gs_multiple_halftone * pmht,const gx_device_halftone * pdht,int dht_index)975 pdf_get_halftone_component_index(const gs_multiple_halftone *pmht,
976 const gx_device_halftone *pdht,
977 int dht_index)
978 {
979 int j;
980
981 for (j = 0; j < pmht->num_comp; j++)
982 if (pmht->components[j].comp_number == dht_index)
983 break;
984 if (j == pmht->num_comp) {
985 /* Look for Default. */
986 for (j = 0; j < pmht->num_comp; j++)
987 if (pmht->components[j].comp_number == GX_DEVICE_COLOR_MAX_COMPONENTS)
988 break;
989 if (j == pmht->num_comp)
990 return_error(gs_error_undefined);
991 }
992 return j;
993 }
994 private int
pdf_write_multiple_halftone(gx_device_pdf * pdev,const gs_multiple_halftone * pmht,const gx_device_halftone * pdht,long * pid)995 pdf_write_multiple_halftone(gx_device_pdf *pdev,
996 const gs_multiple_halftone *pmht,
997 const gx_device_halftone *pdht, long *pid)
998 {
999 stream *s;
1000 int i, code, last_comp = 0;
1001 gs_memory_t *mem = pdev->pdf_memory;
1002 long *ids;
1003 bool done_Default = false;
1004
1005 ids = (long *)gs_alloc_byte_array(mem, pmht->num_comp, sizeof(long),
1006 "pdf_write_multiple_halftone");
1007 if (ids == 0)
1008 return_error(gs_error_VMerror);
1009 for (i = 0; i < pdht->num_comp; ++i) {
1010 const gs_halftone_component *phtc;
1011 const gx_ht_order *porder;
1012
1013 code = pdf_get_halftone_component_index(pmht, pdht, i);
1014 if (code < 0)
1015 return code;
1016 if (pmht->components[code].comp_number == GX_DEVICE_COLOR_MAX_COMPONENTS) {
1017 if (done_Default)
1018 continue;
1019 done_Default = true;
1020 }
1021 phtc = &pmht->components[code];
1022 porder = (pdht->components == 0 ? &pdht->order :
1023 &pdht->components[i].corder);
1024 switch (phtc->type) {
1025 case ht_type_spot:
1026 code = pdf_write_spot_halftone(pdev, &phtc->params.spot,
1027 porder, &ids[i]);
1028 break;
1029 case ht_type_threshold:
1030 code = pdf_write_threshold_halftone(pdev, &phtc->params.threshold,
1031 porder, &ids[i]);
1032 break;
1033 case ht_type_threshold2:
1034 code = pdf_write_threshold2_halftone(pdev,
1035 &phtc->params.threshold2,
1036 porder, &ids[i]);
1037 break;
1038 default:
1039 code = gs_note_error(gs_error_rangecheck);
1040 }
1041 if (code < 0) {
1042 gs_free_object(mem, ids, "pdf_write_multiple_halftone");
1043 return code;
1044 }
1045 }
1046 *pid = pdf_begin_separate(pdev);
1047 s = pdev->strm;
1048 stream_puts(s, "<</Type/Halftone/HalftoneType 5\n");
1049 done_Default = false;
1050 for (i = 0; i < pdht->num_comp; ++i) {
1051 const gs_halftone_component *phtc;
1052 byte *str;
1053 uint len;
1054 cos_value_t value;
1055
1056 code = pdf_get_halftone_component_index(pmht, pdht, i);
1057 if (code < 0)
1058 return code;
1059 if (pmht->components[code].comp_number == GX_DEVICE_COLOR_MAX_COMPONENTS) {
1060 if (done_Default)
1061 continue;
1062 done_Default = true;
1063 }
1064 phtc = &pmht->components[code];
1065 if ((code = pmht->get_colorname_string(pdev->memory, phtc->cname, &str, &len)) < 0 ||
1066 (code = pdf_string_to_cos_name(pdev, str, len, &value)) < 0)
1067 return code;
1068 cos_value_write(&value, pdev);
1069 gs_free_string(mem, value.contents.chars.data,
1070 value.contents.chars.size,
1071 "pdf_write_multiple_halftone");
1072 pprintld1(s, " %ld 0 R\n", ids[i]);
1073 last_comp = i;
1074 }
1075 if (!done_Default) {
1076 /*
1077 * BOGUS: Type 5 halftones must contain Default component.
1078 * Perhaps we have no way to obtain it,
1079 * because pdht contains ProcessColorModel components only.
1080 * We copy the last component as Default one.
1081 */
1082 pprintld1(s, " /Default %ld 0 R\n", ids[last_comp]);
1083 }
1084 stream_puts(s, ">>\n");
1085 gs_free_object(mem, ids, "pdf_write_multiple_halftone");
1086 return pdf_end_separate(pdev);
1087 }
1088
1089 /*
1090 * Update the halftone. This is a separate procedure only for
1091 * readability.
1092 */
1093 private int
pdf_update_halftone(gx_device_pdf * pdev,const gs_imager_state * pis,char * hts)1094 pdf_update_halftone(gx_device_pdf *pdev, const gs_imager_state *pis,
1095 char *hts)
1096 {
1097 const gs_halftone *pht = pis->halftone;
1098 const gx_device_halftone *pdht = pis->dev_ht;
1099 int code;
1100 long id;
1101
1102 switch (pht->type) {
1103 case ht_type_screen:
1104 code = pdf_write_screen_halftone(pdev, &pht->params.screen,
1105 &pdht->components[0].corder, &id);
1106 break;
1107 case ht_type_colorscreen:
1108 code = pdf_write_colorscreen_halftone(pdev, &pht->params.colorscreen,
1109 pdht, &id);
1110 break;
1111 case ht_type_spot:
1112 code = pdf_write_spot_halftone(pdev, &pht->params.spot,
1113 &pdht->components[0].corder, &id);
1114 break;
1115 case ht_type_threshold:
1116 code = pdf_write_threshold_halftone(pdev, &pht->params.threshold,
1117 &pdht->components[0].corder, &id);
1118 break;
1119 case ht_type_threshold2:
1120 code = pdf_write_threshold2_halftone(pdev, &pht->params.threshold2,
1121 &pdht->components[0].corder, &id);
1122 break;
1123 case ht_type_multiple:
1124 case ht_type_multiple_colorscreen:
1125 code = pdf_write_multiple_halftone(pdev, &pht->params.multiple,
1126 pdht, &id);
1127 break;
1128 default:
1129 return_error(gs_error_rangecheck);
1130 }
1131 if (code < 0)
1132 return code;
1133 sprintf(hts, "%ld 0 R", id);
1134 pdev->halftone_id = pis->dev_ht->id;
1135 return code;
1136 }
1137
1138 /* ------ Graphics state updating ------ */
1139
1140 private inline cos_dict_t *
resource_dict(pdf_resource_t * pres)1141 resource_dict(pdf_resource_t *pres)
1142 {
1143 return (cos_dict_t *)pres->object;
1144 }
1145
1146 /* Open an ExtGState. */
1147 private int
pdf_open_gstate(gx_device_pdf * pdev,pdf_resource_t ** ppres)1148 pdf_open_gstate(gx_device_pdf *pdev, pdf_resource_t **ppres)
1149 {
1150 int code;
1151
1152 if (*ppres)
1153 return 0;
1154 /*
1155 * We write gs command only in stream context.
1156 * If we are clipped, and the clip path is about to change,
1157 * the old clipping must be undone before writing gs.
1158 */
1159 if (pdev->context != PDF_IN_STREAM) {
1160 /* We apparently use gs_error_interrupt as a request to change context. */
1161 return gs_error_interrupt;
1162 }
1163 code = pdf_alloc_resource(pdev, resourceExtGState, gs_no_id, ppres, -1L);
1164 if (code < 0)
1165 return code;
1166 cos_become((*ppres)->object, cos_type_dict);
1167 code = cos_dict_put_c_key_string(resource_dict(*ppres), "/Type", (const byte *)"/ExtGState", 10);
1168 if (code < 0)
1169 return code;
1170 return 0;
1171 }
1172
1173 /* Finish writing an ExtGState. */
1174 int
pdf_end_gstate(gx_device_pdf * pdev,pdf_resource_t * pres)1175 pdf_end_gstate(gx_device_pdf *pdev, pdf_resource_t *pres)
1176 {
1177 if (pres) {
1178 int code = pdf_substitute_resource(pdev, &pres, resourceExtGState, NULL, true);
1179
1180 if (code < 0)
1181 return code;
1182 code = pdf_open_page(pdev, PDF_IN_STREAM);
1183 if (code < 0)
1184 return code;
1185 code = pdf_add_resource(pdev, pdev->substream_Resources, "/ExtGState", pres);
1186 if (code < 0)
1187 return code;
1188 pprintld1(pdev->strm, "/R%ld gs\n", pdf_resource_id(pres));
1189 pres->where_used |= pdev->used_mask;
1190 }
1191 return 0;
1192 }
1193
1194 /*
1195 * Update the transfer functions(s). This is a separate procedure only
1196 * for readability.
1197 */
1198 private int
pdf_update_transfer(gx_device_pdf * pdev,const gs_imager_state * pis,char * trs)1199 pdf_update_transfer(gx_device_pdf *pdev, const gs_imager_state *pis,
1200 char *trs)
1201 {
1202 int i, pi = -1;
1203 bool multiple = false, update = false;
1204 gs_id transfer_ids[4];
1205 int code = 0;
1206 const gx_transfer_map *tm[4];
1207
1208 tm[0] = pis->set_transfer.red;
1209 tm[1] = pis->set_transfer.green;
1210 tm[2] = pis->set_transfer.blue;
1211 tm[3] = pis->set_transfer.gray;
1212 for (i = 0; i < 4; ++i)
1213 if (tm[i] != NULL) {
1214 transfer_ids[i] = tm[i]->id;
1215 if (pdev->transfer_ids[i] != tm[i]->id)
1216 update = true;
1217 if (pi != -1 && transfer_ids[i] != transfer_ids[pi])
1218 multiple = true;
1219 pi = i;
1220 } else
1221 transfer_ids[i] = -1;
1222 if (update) {
1223 int mask;
1224
1225 if (!multiple) {
1226 code = pdf_write_transfer(pdev, tm[pi], "", trs);
1227 if (code < 0)
1228 return code;
1229 mask = code == 0;
1230 } else {
1231 strcpy(trs, "[");
1232 mask = 0;
1233 for (i = 0; i < 4; ++i)
1234 if (tm[i] != NULL) {
1235 code = pdf_write_transfer_map(pdev,
1236 tm[i],
1237 0, true, " ", trs + strlen(trs));
1238 if (code < 0)
1239 return code;
1240 mask |= (code == 0) << i;
1241 }
1242 strcat(trs, "]");
1243 }
1244 memcpy(pdev->transfer_ids, transfer_ids, sizeof(pdev->transfer_ids));
1245 pdev->transfer_not_identity = mask;
1246 }
1247 return code;
1248 }
1249
1250 /*
1251 * Update the current alpha if necessary. Note that because Ghostscript
1252 * stores separate opacity and shape alpha, a rangecheck will occur if
1253 * both are different from the current setting.
1254 */
1255 private int
pdf_update_alpha(gx_device_pdf * pdev,const gs_imager_state * pis,pdf_resource_t ** ppres)1256 pdf_update_alpha(gx_device_pdf *pdev, const gs_imager_state *pis,
1257 pdf_resource_t **ppres)
1258 {
1259 bool ais;
1260 floatp alpha;
1261 int code;
1262
1263 if (pdev->state.soft_mask_id != pis->soft_mask_id) {
1264 char buf[20];
1265
1266 sprintf(buf, "%ld 0 R", pis->soft_mask_id);
1267 code = pdf_open_gstate(pdev, ppres);
1268 if (code < 0)
1269 return code;
1270 code = cos_dict_put_c_key_string(resource_dict(*ppres),
1271 "/SMask", (byte *)buf, strlen(buf));
1272 if (code < 0)
1273 return code;
1274 pdev->state.soft_mask_id = pis->soft_mask_id;
1275 }
1276 if (pdev->state.opacity.alpha != pis->opacity.alpha) {
1277 if (pdev->state.shape.alpha != pis->shape.alpha)
1278 return_error(gs_error_rangecheck);
1279 ais = false;
1280 alpha = pdev->state.opacity.alpha = pis->opacity.alpha;
1281 } else if (pdev->state.shape.alpha != pis->shape.alpha) {
1282 ais = true;
1283 alpha = pdev->state.shape.alpha = pis->shape.alpha;
1284 } else
1285 return 0;
1286 code = pdf_open_gstate(pdev, ppres);
1287 if (code < 0)
1288 return code;
1289 code = cos_dict_put_c_key_bool(resource_dict(*ppres), "/AIS", ais);
1290 if (code < 0)
1291 return code;
1292 /* we never do the 'both' operations (b, B, b*, B*) so we set both */
1293 /* CA and ca the same so that we stay in sync with state.*.alpha */
1294 code = cos_dict_put_c_key_real(resource_dict(*ppres), "/CA", alpha);
1295 if (code < 0)
1296 return code;
1297 return cos_dict_put_c_key_real(resource_dict(*ppres), "/ca", alpha);
1298 }
1299
1300 /*
1301 * Update the graphics subset common to all high-level drawing operations.
1302 */
1303 int
pdf_prepare_drawing(gx_device_pdf * pdev,const gs_imager_state * pis,pdf_resource_t ** ppres)1304 pdf_prepare_drawing(gx_device_pdf *pdev, const gs_imager_state *pis,
1305 pdf_resource_t **ppres)
1306 {
1307 int code = 0;
1308 int bottom;
1309
1310 if (pdev->CompatibilityLevel >= 1.4) {
1311 if (pdev->state.blend_mode != pis->blend_mode) {
1312 static const char *const bm_names[] = { GS_BLEND_MODE_NAMES };
1313 char buf[20];
1314
1315 code = pdf_open_gstate(pdev, ppres);
1316 if (code < 0)
1317 return code;
1318 buf[0] = '/';
1319 strncpy(buf + 1, bm_names[pis->blend_mode], sizeof(buf) - 2);
1320 code = cos_dict_put_string_copy(resource_dict(*ppres), "/BM", buf);
1321 if (code < 0)
1322 return code;
1323 pdev->state.blend_mode = pis->blend_mode;
1324 }
1325 code = pdf_update_alpha(pdev, pis, ppres);
1326 if (code < 0)
1327 return code;
1328 } else {
1329 /*
1330 * If the graphics state calls for any transparency functions,
1331 * we can't represent them, so return a rangecheck.
1332 */
1333 if (pis->opacity.alpha != 1 || pis->opacity.mask != 0 ||
1334 pis->shape.alpha != 1 || pis->shape.mask != 0 ||
1335 pis->transparency_stack != 0
1336 )
1337 return_error(gs_error_rangecheck);
1338 }
1339 /*
1340 * We originally thought the remaining items were only needed for
1341 * fill and stroke, but in fact they are needed for images as well.
1342 */
1343 /*
1344 * Update halftone, transfer function, black generation, undercolor
1345 * removal, halftone phase, overprint mode, smoothness, blend mode, text
1346 * knockout.
1347 */
1348 bottom = (pdev->ResourcesBeforeUsage ? 1 : 0);
1349 /* When ResourcesBeforeUsage != 0, one sbstack element
1350 appears from the page contents stream. */
1351 if (pdev->sbstack_depth == bottom) {
1352 gs_int_point phase, dev_phase;
1353 char hts[5 + MAX_FN_CHARS + 1],
1354 trs[5 + MAX_FN_CHARS * 4 + 6 + 1],
1355 bgs[5 + MAX_FN_CHARS + 1],
1356 ucrs[6 + MAX_FN_CHARS + 1];
1357
1358 hts[0] = trs[0] = bgs[0] = ucrs[0] = 0;
1359 if (pdev->params.PreserveHalftoneInfo &&
1360 pdev->halftone_id != pis->dev_ht->id &&
1361 !pdev->PDFX
1362 ) {
1363 code = pdf_update_halftone(pdev, pis, hts);
1364 if (code < 0)
1365 return code;
1366 }
1367 if (pdev->params.TransferFunctionInfo == tfi_Preserve &&
1368 !pdev->PDFX
1369 ) {
1370 code = pdf_update_transfer(pdev, pis, trs);
1371 if (code < 0)
1372 return code;
1373 }
1374 if (pdev->params.UCRandBGInfo == ucrbg_Preserve) {
1375 if (pdev->black_generation_id != pis->black_generation->id) {
1376 code = pdf_write_transfer_map(pdev, pis->black_generation,
1377 0, false, "", bgs);
1378 if (code < 0)
1379 return code;
1380 pdev->black_generation_id = pis->black_generation->id;
1381 }
1382 if (pdev->undercolor_removal_id != pis->undercolor_removal->id) {
1383 code = pdf_write_transfer_map(pdev, pis->undercolor_removal,
1384 -1, false, "", ucrs);
1385 if (code < 0)
1386 return code;
1387 pdev->undercolor_removal_id = pis->undercolor_removal->id;
1388 }
1389 }
1390 if (hts[0] || trs[0] || bgs[0] || ucrs[0]) {
1391 code = pdf_open_gstate(pdev, ppres);
1392 if (code < 0)
1393 return code;
1394 }
1395 if (hts[0]) {
1396 code = cos_dict_put_string_copy(resource_dict(*ppres), "/HT", hts);
1397 if (code < 0)
1398 return code;
1399 }
1400 if (trs[0]) {
1401 code = cos_dict_put_string_copy(resource_dict(*ppres), "/TR", trs);
1402 if (code < 0)
1403 return code;
1404 }
1405 if (bgs[0]) {
1406 code = cos_dict_put_string_copy(resource_dict(*ppres), "/BG", bgs);
1407 if (code < 0)
1408 return code;
1409 }
1410 if (ucrs[0]) {
1411 code = cos_dict_put_string_copy(resource_dict(*ppres), "/UCR", ucrs);
1412 if (code < 0)
1413 return code;
1414 }
1415 if (!pdev->PDFX) {
1416 gs_currentscreenphase_pis(pis, &phase, 0);
1417 gs_currentscreenphase_pis(&pdev->state, &dev_phase, 0);
1418 if (dev_phase.x != phase.x || dev_phase.y != phase.y) {
1419 char buf[sizeof(int) * 3 + 5];
1420
1421 code = pdf_open_gstate(pdev, ppres);
1422 if (code < 0)
1423 return code;
1424 sprintf(buf, "[%d %d]", phase.x, phase.y);
1425 code = cos_dict_put_string_copy(resource_dict(*ppres), "/HTP", buf);
1426 if (code < 0)
1427 return code;
1428 gx_imager_setscreenphase(&pdev->state, phase.x, phase.y,
1429 gs_color_select_all);
1430 }
1431 }
1432 }
1433 if (pdev->CompatibilityLevel >= 1.3 && pdev->sbstack_depth == bottom) {
1434 if (pdev->overprint_mode != pdev->params.OPM) {
1435 code = pdf_open_gstate(pdev, ppres);
1436 if (code < 0)
1437 return code;
1438 code = cos_dict_put_c_key_int(resource_dict(*ppres), "/OPM", pdev->params.OPM);
1439 if (code < 0)
1440 return code;
1441 pdev->overprint_mode = pdev->params.OPM;
1442 }
1443 if (pdev->state.smoothness != pis->smoothness) {
1444 code = pdf_open_gstate(pdev, ppres);
1445 if (code < 0)
1446 return code;
1447 code = cos_dict_put_c_key_real(resource_dict(*ppres), "/SM", pis->smoothness);
1448 if (code < 0)
1449 return code;
1450 pdev->state.smoothness = pis->smoothness;
1451 }
1452 if (pdev->CompatibilityLevel >= 1.4) {
1453 if (pdev->state.text_knockout != pis->text_knockout) {
1454 code = pdf_open_gstate(pdev, ppres);
1455 if (code < 0)
1456 return code;
1457 code = cos_dict_put_c_key_bool(resource_dict(*ppres), "/TK", pis->text_knockout);
1458 if (code < 0)
1459 return code;
1460 pdev->state.text_knockout = pis->text_knockout;
1461 }
1462 }
1463 }
1464 return code;
1465 }
1466
1467 /* Update the graphics state for filling. */
1468 int
pdf_try_prepare_fill(gx_device_pdf * pdev,const gs_imager_state * pis)1469 pdf_try_prepare_fill(gx_device_pdf *pdev, const gs_imager_state *pis)
1470 {
1471 pdf_resource_t *pres = 0;
1472 int code = pdf_prepare_drawing(pdev, pis, &pres);
1473
1474 if (code < 0)
1475 return code;
1476 /* Update overprint. */
1477 if (pdev->params.PreserveOverprintSettings &&
1478 pdev->fill_overprint != pis->overprint &&
1479 !pdev->skip_colors
1480 ) {
1481 code = pdf_open_gstate(pdev, &pres);
1482 if (code < 0)
1483 return code;
1484 /* PDF 1.2 only has a single overprint setting. */
1485 if (pdev->CompatibilityLevel < 1.3) {
1486 code = cos_dict_put_c_key_bool(resource_dict(pres), "/OP", pis->overprint);
1487 if (code < 0)
1488 return code;
1489 pdev->stroke_overprint = pis->overprint;
1490 } else {
1491 code = cos_dict_put_c_key_bool(resource_dict(pres), "/op", pis->overprint);
1492 if (code < 0)
1493 return code;
1494 }
1495 pdev->fill_overprint = pis->overprint;
1496 }
1497 return pdf_end_gstate(pdev, pres);
1498 }
1499 int
pdf_prepare_fill(gx_device_pdf * pdev,const gs_imager_state * pis)1500 pdf_prepare_fill(gx_device_pdf *pdev, const gs_imager_state *pis)
1501 {
1502 int code;
1503
1504 if (pdev->context != PDF_IN_STREAM) {
1505 code = pdf_try_prepare_fill(pdev, pis);
1506 if (code != gs_error_interrupt) /* See pdf_open_gstate */
1507 return code;
1508 code = pdf_open_contents(pdev, PDF_IN_STREAM);
1509 if (code < 0)
1510 return code;
1511 }
1512 return pdf_try_prepare_fill(pdev, pis);
1513 }
1514
1515 /* Update the graphics state for stroking. */
1516 private int
pdf_try_prepare_stroke(gx_device_pdf * pdev,const gs_imager_state * pis)1517 pdf_try_prepare_stroke(gx_device_pdf *pdev, const gs_imager_state *pis)
1518 {
1519 pdf_resource_t *pres = 0;
1520 int code = pdf_prepare_drawing(pdev, pis, &pres);
1521
1522 if (code < 0)
1523 return code;
1524 /* Update overprint, stroke adjustment. */
1525 if (pdev->params.PreserveOverprintSettings &&
1526 pdev->stroke_overprint != pis->overprint &&
1527 !pdev->skip_colors
1528 ) {
1529 code = pdf_open_gstate(pdev, &pres);
1530 if (code < 0)
1531 return code;
1532 code = cos_dict_put_c_key_bool(resource_dict(pres), "/OP", pis->overprint);
1533 if (code < 0)
1534 return code;
1535 pdev->stroke_overprint = pis->overprint;
1536 if (pdev->CompatibilityLevel < 1.3) {
1537 /* PDF 1.2 only has a single overprint setting. */
1538 pdev->fill_overprint = pis->overprint;
1539 } else {
1540 /* According to PDF>=1.3 spec, OP also sets op,
1541 if there is no /op in same garphic state object.
1542 We don't write /op, so monitor the viewer's state here : */
1543 pdev->fill_overprint = pis->overprint;
1544 }
1545 }
1546 if (pdev->state.stroke_adjust != pis->stroke_adjust) {
1547 code = pdf_open_gstate(pdev, &pres);
1548 if (code < 0)
1549 return code;
1550 code = cos_dict_put_c_key_bool(resource_dict(pres), "/SA", pis->stroke_adjust);
1551 if (code < 0)
1552 return code;
1553 pdev->state.stroke_adjust = pis->stroke_adjust;
1554 }
1555 return pdf_end_gstate(pdev, pres);
1556 }
1557 int
pdf_prepare_stroke(gx_device_pdf * pdev,const gs_imager_state * pis)1558 pdf_prepare_stroke(gx_device_pdf *pdev, const gs_imager_state *pis)
1559 {
1560 int code;
1561
1562 if (pdev->context != PDF_IN_STREAM) {
1563 code = pdf_try_prepare_stroke(pdev, pis);
1564 if (code != gs_error_interrupt) /* See pdf_open_gstate */
1565 return code;
1566 code = pdf_open_contents(pdev, PDF_IN_STREAM);
1567 if (code < 0)
1568 return code;
1569 }
1570 return pdf_try_prepare_stroke(pdev, pis);
1571 }
1572
1573 /* Update the graphics state for an image other than an ImageType 1 mask. */
1574 int
pdf_prepare_image(gx_device_pdf * pdev,const gs_imager_state * pis)1575 pdf_prepare_image(gx_device_pdf *pdev, const gs_imager_state *pis)
1576 {
1577 /*
1578 * As it turns out, this requires updating the same parameters as for
1579 * filling.
1580 */
1581 return pdf_prepare_fill(pdev, pis);
1582 }
1583
1584 /* Update the graphics state for an ImageType 1 mask. */
1585 int
pdf_prepare_imagemask(gx_device_pdf * pdev,const gs_imager_state * pis,const gx_drawing_color * pdcolor)1586 pdf_prepare_imagemask(gx_device_pdf *pdev, const gs_imager_state *pis,
1587 const gx_drawing_color *pdcolor)
1588 {
1589 int code = pdf_prepare_image(pdev, pis);
1590
1591 if (code < 0)
1592 return code;
1593 return pdf_set_drawing_color(pdev, pis, pdcolor, &pdev->saved_fill_color,
1594 &pdev->fill_used_process_color,
1595 &psdf_set_fill_color_commands);
1596 }
1597
1598