xref: /plan9/sys/src/cmd/gs/src/gdevpdfg.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
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, &params, 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(&params.DataSource, (const byte *)values,
770 			   sizeof(*values) * num_bits);
771     if (code >= 0 &&
772 	(code = gs_function_Sd_init(&pfn, &params, 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