xref: /plan9/sys/src/cmd/gs/src/gdevp14.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
1 /*
2   Copyright (C) 2001-2004 artofcode LLC.
3 
4   This software is provided AS-IS with no warranty, either express or
5   implied.
6 
7   This software is distributed under license and may not be copied,
8   modified or distributed except as expressly authorized under the terms
9   of the license contained in the file LICENSE in this distribution.
10 
11   For more information about licensing, please refer to
12   http://www.ghostscript.com/licensing/. For information on
13   commercial licensing, go to http://www.artifex.com/licensing/ or
14   contact Artifex Software, Inc., 101 Lucas Valley Road #110,
15   San Rafael, CA  94903, U.S.A., +1(415)492-9861.
16 
17   Author: Raph Levien <raph@artofcode.com>
18 */
19 /* $Id: gdevp14.c,v 1.35 2005/10/10 18:58:18 leonardo Exp $	*/
20 /* Compositing devices for implementing	PDF 1.4	imaging	model */
21 
22 #include "math_.h"
23 #include "memory_.h"
24 #include "gx.h"
25 #include "gserrors.h"
26 #include "gscdefs.h"
27 #include "gxdevice.h"
28 #include "gsdevice.h"
29 #include "gsstruct.h"
30 #include "gxistate.h"
31 #include "gxdcolor.h"
32 #include "gxiparam.h"
33 #include "gstparam.h"
34 #include "gxblend.h"
35 #include "gxtext.h"
36 #include "gsdfilt.h"
37 #include "gsimage.h"
38 #include "gsrect.h"
39 #include "gzstate.h"
40 #include "gdevp14.h"
41 #include "gsovrc.h"
42 #include "gxcmap.h"
43 #include "gscolor1.h"
44 #include "gstrans.h"
45 #include "gsutil.h"
46 #include "gxcldev.h"
47 
48 /* #define DUMP_TO_PNG */
49 
50 #ifdef DUMP_TO_PNG
51 #include "png_.h"
52 #endif
53 
54 # define INCR(v) DO_NOTHING
55 
56 /* Buffer stack	data structure */
57 
58 #define	PDF14_MAX_PLANES 16
59 
60 /* GC procedures for buffer stack */
61 
62 private
63 ENUM_PTRS_WITH(pdf14_buf_enum_ptrs, pdf14_buf *buf)
64     return 0;
65     case 0: return ENUM_OBJ(buf->saved);
66     case 1: return ENUM_OBJ(buf->data);
67     case 2: return ENUM_OBJ(buf->transfer_fn);
68 ENUM_PTRS_END
69 
70 private
RELOC_PTRS_WITH(pdf14_buf_reloc_ptrs,pdf14_buf * buf)71 RELOC_PTRS_WITH(pdf14_buf_reloc_ptrs, pdf14_buf	*buf)
72 {
73     RELOC_VAR(buf->saved);
74     RELOC_VAR(buf->data);
75     RELOC_VAR(buf->transfer_fn);
76 }
77 RELOC_PTRS_END
78 
79 gs_private_st_composite(st_pdf14_buf, pdf14_buf, "pdf14_buf",
80 			pdf14_buf_enum_ptrs, pdf14_buf_reloc_ptrs);
81 
82 gs_private_st_ptrs2(st_pdf14_ctx, pdf14_ctx, "pdf14_ctx",
83 		    pdf14_ctx_enum_ptrs, pdf14_ctx_reloc_ptrs,
84 		    stack, maskbuf);
85 
86 /* ------ The device descriptors ------	*/
87 
88 /*
89  * Default X and Y resolution.
90  */
91 #define	X_DPI 72
92 #define	Y_DPI 72
93 
94 private	int pdf14_open(gx_device * pdev);
95 private	dev_proc_close_device(pdf14_close);
96 private	int pdf14_output_page(gx_device	* pdev,	int num_copies,	int flush);
97 private	dev_proc_put_params(pdf14_put_params);
98 private	dev_proc_encode_color(pdf14_encode_color);
99 private	dev_proc_decode_color(pdf14_decode_color);
100 private	dev_proc_fill_rectangle(pdf14_fill_rectangle);
101 private	dev_proc_fill_rectangle(pdf14_mark_fill_rectangle);
102 private	dev_proc_fill_rectangle(pdf14_mark_fill_rectangle_ko_simple);
103 private	dev_proc_fill_path(pdf14_fill_path);
104 private	dev_proc_stroke_path(pdf14_stroke_path);
105 private	dev_proc_begin_typed_image(pdf14_begin_typed_image);
106 private	dev_proc_text_begin(pdf14_text_begin);
107 private	dev_proc_create_compositor(pdf14_create_compositor);
108 private	dev_proc_create_compositor(pdf14_forward_create_compositor);
109 private	dev_proc_begin_transparency_group(pdf14_begin_transparency_group);
110 private	dev_proc_end_transparency_group(pdf14_end_transparency_group);
111 private	dev_proc_begin_transparency_mask(pdf14_begin_transparency_mask);
112 private	dev_proc_end_transparency_mask(pdf14_end_transparency_mask);
113 
114 private	const gx_color_map_procs *
115     pdf14_get_cmap_procs(const gs_imager_state *, const gx_device *);
116 
117 #define	XSIZE (int)(8.5	* X_DPI)	/* 8.5 x 11 inch page, by default */
118 #define	YSIZE (int)(11 * Y_DPI)
119 
120 /* 24-bit color. */
121 
122 #define	pdf14_procs(get_color_mapping_procs, get_color_comp_index) \
123 {\
124 	pdf14_open,			/* open */\
125 	NULL,				/* get_initial_matrix */\
126 	NULL,				/* sync_output */\
127 	pdf14_output_page,		/* output_page */\
128 	pdf14_close,			/* close */\
129 	pdf14_encode_color,		/* rgb_map_rgb_color */\
130 	pdf14_decode_color,		/* gx_default_rgb_map_color_rgb */\
131 	pdf14_fill_rectangle,		/* fill_rectangle */\
132 	NULL,				/* tile_rectangle */\
133 	NULL,				/* copy_mono */\
134 	NULL,				/* copy_color */\
135 	NULL,				/* draw_line */\
136 	NULL,				/* get_bits */\
137 	NULL,				/* get_params */\
138 	pdf14_put_params,		/* put_params */\
139 	NULL,				/* map_cmyk_color */\
140 	NULL,				/* get_xfont_procs */\
141 	NULL,				/* get_xfont_device */\
142 	NULL,				/* map_rgb_alpha_color */\
143 	NULL,				/* get_page_device */\
144 	NULL,				/* get_alpha_bits */\
145 	NULL,				/* copy_alpha */\
146 	NULL,				/* get_band */\
147 	NULL,				/* copy_rop */\
148 	pdf14_fill_path,		/* fill_path */\
149 	pdf14_stroke_path,		/* stroke_path */\
150 	NULL,				/* fill_mask */\
151 	NULL,				/* fill_trapezoid */\
152 	NULL,				/* fill_parallelogram */\
153 	NULL,				/* fill_triangle */\
154 	NULL,				/* draw_thin_line */\
155 	NULL,				/* begin_image */\
156 	NULL,				/* image_data */\
157 	NULL,				/* end_image */\
158 	NULL,				/* strip_tile_rectangle */\
159 	NULL,				/* strip_copy_rop, */\
160 	NULL,				/* get_clipping_box */\
161 	pdf14_begin_typed_image,	/* begin_typed_image */\
162 	NULL,				/* get_bits_rectangle */\
163 	NULL,				/* map_color_rgb_alpha */\
164 	pdf14_create_compositor,	/* create_compositor */\
165 	NULL,				/* get_hardware_params */\
166 	pdf14_text_begin,		/* text_begin */\
167 	NULL,				/* finish_copydevice */\
168 	pdf14_begin_transparency_group,\
169 	pdf14_end_transparency_group,\
170 	pdf14_begin_transparency_mask,\
171 	pdf14_end_transparency_mask,\
172 	NULL,				/* discard_transparency_layer */\
173 	get_color_mapping_procs,	/* get_color_mapping_procs */\
174 	get_color_comp_index,		/* get_color_comp_index */\
175 	pdf14_encode_color,		/* encode_color */\
176 	pdf14_decode_color		/* decode_color */\
177 }
178 
179 private	const gx_device_procs pdf14_Gray_procs =
180 	pdf14_procs(gx_default_DevGray_get_color_mapping_procs,
181 			gx_default_DevGray_get_color_comp_index);
182 
183 private	const gx_device_procs pdf14_RGB_procs =
184 	pdf14_procs(gx_default_DevRGB_get_color_mapping_procs,
185 			gx_default_DevRGB_get_color_comp_index);
186 
187 private	const gx_device_procs pdf14_CMYK_procs =
188 	pdf14_procs(gx_default_DevCMYK_get_color_mapping_procs,
189 			gx_default_DevCMYK_get_color_comp_index);
190 
191 gs_private_st_composite_use_final(st_pdf14_device, pdf14_device, "pdf14_device",
192 				  pdf14_device_enum_ptrs, pdf14_device_reloc_ptrs,
193 			  gx_device_finalize);
194 
195 const pdf14_device gs_pdf14_Gray_device	= {
196     std_device_color_stype_body(pdf14_device, &pdf14_Gray_procs, "pdf14gray",
197 				&st_pdf14_device,
198 				XSIZE, YSIZE, X_DPI, Y_DPI, 8, 255, 256),
199     { 0 }
200 };
201 
202 const pdf14_device gs_pdf14_RGB_device = {
203     std_device_color_stype_body(pdf14_device, &pdf14_RGB_procs, "pdf14RGB",
204 				&st_pdf14_device,
205 				XSIZE, YSIZE, X_DPI, Y_DPI, 24, 255, 256),
206     { 0 }
207 };
208 
209 const pdf14_device gs_pdf14_CMYK_device	= {
210     std_device_std_color_full_body_type(pdf14_device, &pdf14_CMYK_procs,
211 	"PDF14cmyk", &st_pdf14_device, XSIZE, YSIZE, X_DPI, Y_DPI, 32,
212 	0, 0, 0, 0, 0, 0),
213     { 0 }
214 };
215 
216 /* GC procedures */
217 private
218 ENUM_PTRS_WITH(pdf14_device_enum_ptrs, pdf14_device *pdev) return 0;
219 case 0:	return ENUM_OBJ(pdev->ctx);
220 case 1:	ENUM_RETURN(gx_device_enum_ptr(pdev->target));
221 ENUM_PTRS_END
RELOC_PTRS_WITH(pdf14_device_reloc_ptrs,pdf14_device * pdev)222 private	RELOC_PTRS_WITH(pdf14_device_reloc_ptrs, pdf14_device *pdev)
223 {
224     RELOC_VAR(pdev->ctx);
225     pdev->target = gx_device_reloc_ptr(pdev->target, gcst);
226 }
227 RELOC_PTRS_END
228 
229 /* ------ Private definitions ------ */
230 
231 /**
232  * pdf14_buf_new: Allocate a new PDF 1.4 buffer.
233  * @n_chan: Number of pixel channels including alpha.
234  *
235  * Return value: Newly allocated buffer, or NULL on failure.
236  **/
237 private	pdf14_buf *
pdf14_buf_new(gs_int_rect * rect,bool has_alpha_g,bool has_shape,int n_chan,gs_memory_t * memory)238 pdf14_buf_new(gs_int_rect *rect, bool has_alpha_g, bool	has_shape,
239 	       int n_chan,
240 	       gs_memory_t *memory)
241 {
242     pdf14_buf *result;
243     int rowstride = (rect->q.x - rect->p.x + 3) & -4;
244     int height = (rect->q.y - rect->p.y);
245     int n_planes = n_chan + (has_shape ? 1 : 0) + (has_alpha_g ? 1 : 0);
246     int planestride;
247     double dsize = (((double) rowstride) * height) * n_planes;
248 
249     if (dsize > (double)max_uint)
250       return NULL;
251 
252     result = gs_alloc_struct(memory, pdf14_buf, &st_pdf14_buf,
253 			     "pdf14_buf_new");
254     if (result == NULL)
255 	return result;
256 
257     result->isolated = false;
258     result->knockout = false;
259     result->has_alpha_g = has_alpha_g;
260     result->has_shape = has_shape;
261     result->rect = *rect;
262     result->n_chan = n_chan;
263     result->n_planes = n_planes;
264     result->rowstride = rowstride;
265     result->transfer_fn = NULL;
266 
267     if (height < 0) {
268 	/* Empty clipping - will skip all drawings. */
269 	result->planestride = 0;
270 	result->data = 0;
271     } else {
272 	planestride = rowstride * height;
273 	result->planestride = planestride;
274 	result->data = gs_alloc_bytes(memory, planestride * n_planes,
275 					"pdf14_buf_new");
276 	if (result->data == NULL) {
277 	    gs_free_object(memory, result, "pdf_buf_new");
278 	    return NULL;
279 	}
280 	if (has_alpha_g) {
281 	    int alpha_g_plane = n_chan + (has_shape ? 1 : 0);
282 	    memset (result->data + alpha_g_plane * planestride, 0, planestride);
283 	}
284     }
285     result->bbox.p.x = max_int;
286     result->bbox.p.y = max_int;
287     result->bbox.q.x = min_int;
288     result->bbox.q.y = min_int;
289     return result;
290 }
291 
292 private	void
pdf14_buf_free(pdf14_buf * buf,gs_memory_t * memory)293 pdf14_buf_free(pdf14_buf *buf, gs_memory_t *memory)
294 {
295     gs_free_object(memory, buf->transfer_fn, "pdf14_buf_free");
296     gs_free_object(memory, buf->data, "pdf14_buf_free");
297     gs_free_object(memory, buf, "pdf14_buf_free");
298 }
299 
300 private	pdf14_ctx *
pdf14_ctx_new(gs_int_rect * rect,int n_chan,bool additive,gs_memory_t * memory)301 pdf14_ctx_new(gs_int_rect *rect, int n_chan, bool additive, gs_memory_t	*memory)
302 {
303     pdf14_ctx *result;
304     pdf14_buf *buf;
305 
306     result = gs_alloc_struct(memory, pdf14_ctx, &st_pdf14_ctx,
307 			     "pdf14_ctx_new");
308     if (result == NULL)
309 	return result;
310 
311     buf = pdf14_buf_new(rect, false, false, n_chan, memory);
312     if (buf == NULL) {
313 	gs_free_object(memory, result, "pdf14_ctx_new");
314 	return NULL;
315     }
316     if_debug3('v', "[v]base buf: %d x %d, %d channels\n",
317 	      buf->rect.q.x, buf->rect.q.y, buf->n_chan);
318     memset(buf->data, 0, buf->planestride * buf->n_planes);
319     buf->saved = NULL;
320     result->stack = buf;
321     result->maskbuf = NULL;
322     result->n_chan = n_chan;
323     result->memory = memory;
324     result->rect = *rect;
325     result->additive = additive;
326     return result;
327 }
328 
329 private	void
pdf14_ctx_free(pdf14_ctx * ctx)330 pdf14_ctx_free(pdf14_ctx *ctx)
331 {
332     pdf14_buf *buf, *next;
333 
334     for (buf = ctx->stack; buf != NULL; buf = next) {
335 	next = buf->saved;
336 	pdf14_buf_free(buf, ctx->memory);
337     }
338     gs_free_object (ctx->memory, ctx, "pdf14_ctx_free");
339 }
340 
341 /**
342  * pdf14_find_backdrop_buf: Find backdrop buffer.
343  *
344  * Return value: Backdrop buffer for current group operation, or NULL
345  * if backdrop is fully transparent.
346  **/
347 private	pdf14_buf *
pdf14_find_backdrop_buf(pdf14_ctx * ctx)348 pdf14_find_backdrop_buf(pdf14_ctx *ctx)
349 {
350     pdf14_buf *buf = ctx->stack;
351 
352     while (buf != NULL) {
353 	if (buf->isolated) return NULL;
354 	if (!buf->knockout) return buf->saved;
355 	buf = buf->saved;
356     }
357     /* this really shouldn't happen, as bottom-most buf should be
358        non-knockout */
359     return NULL;
360 }
361 
362 private	int
pdf14_push_transparency_group(pdf14_ctx * ctx,gs_int_rect * rect,bool isolated,bool knockout,byte alpha,byte shape,gs_blend_mode_t blend_mode)363 pdf14_push_transparency_group(pdf14_ctx	*ctx, gs_int_rect *rect,
364 			      bool isolated, bool knockout,
365 			      byte alpha, byte shape,
366 			      gs_blend_mode_t blend_mode)
367 {
368     pdf14_buf *tos = ctx->stack;
369     pdf14_buf *buf, *backdrop;
370     bool has_shape;
371 
372     /* todo: fix this hack, which makes all knockout groups isolated.
373        For the vast majority of files, there won't be any visible
374        effects, but it still isn't correct. The pixel compositing code
375        for non-isolated knockout groups gets pretty hairy, which is
376        why this is here. */
377     if (knockout)
378 	isolated = true;
379 
380     has_shape = tos->has_shape || tos->knockout;
381 
382     buf = pdf14_buf_new(rect, !isolated, has_shape, ctx->n_chan, ctx->memory);
383     if_debug3('v', "[v]push buf: %d x %d, %d channels\n", buf->rect.p.x, buf->rect.p.y, buf->n_chan);
384     if (buf == NULL)
385 	return_error(gs_error_VMerror);
386     buf->isolated = isolated;
387     buf->knockout = knockout;
388     buf->alpha = alpha;
389     buf->shape = shape;
390     buf->blend_mode = blend_mode;
391 
392     buf->saved = tos;
393     ctx->stack = buf;
394 
395     backdrop = pdf14_find_backdrop_buf(ctx);
396     if (backdrop == NULL) {
397 	memset(buf->data, 0, buf->planestride * (buf->n_chan +
398 						 (buf->has_shape ? 1 : 0)));
399     } else {
400 	/* make copy of backdrop for compositing */
401 	byte *buf_plane = buf->data;
402 	byte *tos_plane = tos->data + buf->rect.p.x - tos->rect.p.x +
403 	    (buf->rect.p.y - tos->rect.p.y) * tos->rowstride;
404 	int width = buf->rect.q.x - buf->rect.p.x;
405 	int y0 = buf->rect.p.y;
406 	int y1 = buf->rect.q.y;
407 	int i;
408 	int n_chan_copy = buf->n_chan + (tos->has_shape ? 1 : 0);
409 
410 	for (i = 0; i < n_chan_copy; i++) {
411 	    byte *buf_ptr = buf_plane;
412 	    byte *tos_ptr = tos_plane;
413 	    int y;
414 
415 	    for (y = y0; y < y1; ++y) {
416 		memcpy (buf_ptr, tos_ptr, width);
417 		buf_ptr += buf->rowstride;
418 		tos_ptr += tos->rowstride;
419 	    }
420 	    buf_plane += buf->planestride;
421 	    tos_plane += tos->planestride;
422 	}
423 	if (has_shape && !tos->has_shape)
424 	    memset (buf_plane, 0, buf->planestride);
425     }
426 
427     return 0;
428 }
429 
430 private	int
pdf14_pop_transparency_group(pdf14_ctx * ctx)431 pdf14_pop_transparency_group(pdf14_ctx *ctx)
432 {
433     pdf14_buf *tos = ctx->stack;
434     pdf14_buf *nos = tos->saved;
435     pdf14_buf *maskbuf = ctx->maskbuf;
436     int y0 = tos->rect.p.y;
437     int y1 = tos->rect.q.y;
438     if (y0 < y1) {
439 	int x0 = tos->rect.p.x;
440 	int x1 = tos->rect.q.x;
441 	int n_chan = ctx->n_chan;
442 	int num_comp = n_chan - 1;
443 	byte alpha = tos->alpha;
444 	byte shape = tos->shape;
445 	byte blend_mode = tos->blend_mode;
446 	byte *tos_ptr = tos->data;
447 	byte *nos_ptr = nos->data + x0 - nos->rect.p.x +
448 	    (y0 - nos->rect.p.y) * nos->rowstride;
449 	byte *mask_ptr = NULL;
450 	int tos_planestride = tos->planestride;
451 	int nos_planestride = nos->planestride;
452 	int mask_planestride = 0x0badf00d; /* Quiet compiler. */
453 	byte mask_bg_alpha = 0; /* Quiet compiler. */
454 	int width = x1 - x0;
455 	int x, y;
456 	int i;
457 	byte tos_pixel[PDF14_MAX_PLANES];
458 	byte nos_pixel[PDF14_MAX_PLANES];
459 	bool tos_isolated = tos->isolated;
460 	bool nos_knockout = nos->knockout;
461 	byte *nos_alpha_g_ptr;
462 	int tos_shape_offset = n_chan * tos_planestride;
463 	int tos_alpha_g_offset = tos_shape_offset +
464 	(tos->has_shape ? tos_planestride : 0);
465 	int nos_shape_offset = n_chan * nos_planestride;
466 	bool nos_has_shape = nos->has_shape;
467 	byte *mask_tr_fn = NULL; /* Quiet compiler. */
468 	bool additive = ctx->additive;
469 
470 	if (nos == NULL)
471 	    return_error(gs_error_rangecheck);
472 
473 	rect_merge(nos->bbox, tos->bbox);
474 
475 	if_debug6('v', "pdf14_pop_transparency_group y0 = %d, y1 = %d, w = %d, alpha = %d, shape = %d, bm = %d\n",
476 			    y0, y1, width, alpha, shape, blend_mode);
477 	if (nos->has_alpha_g)
478 	    nos_alpha_g_ptr = nos_ptr + n_chan * nos_planestride;
479 	else
480 	    nos_alpha_g_ptr = NULL;
481 
482 	if (maskbuf != NULL) {
483 	    mask_ptr = maskbuf->data + x0 - maskbuf->rect.p.x +
484 		    (y0 - maskbuf->rect.p.y) * maskbuf->rowstride;
485 	    mask_planestride = maskbuf->planestride;
486 	    mask_bg_alpha = maskbuf->alpha;
487 	    mask_tr_fn = maskbuf->transfer_fn;
488 	}
489 
490 	for (y = y0; y < y1; ++y) {
491 	    for (x = 0; x < width; ++x) {
492 		byte pix_alpha = alpha;
493 
494 		/* Complement the components for subtractive color spaces */
495 		if (additive) {
496 		    for (i = 0; i < n_chan; ++i) {
497 			tos_pixel[i] = tos_ptr[x + i * tos_planestride];
498 			nos_pixel[i] = nos_ptr[x + i * nos_planestride];
499 		    }
500 		} else {
501 		    for (i = 0; i < num_comp; ++i) {
502 			tos_pixel[i] = 255 - tos_ptr[x + i * tos_planestride];
503 			nos_pixel[i] = 255 - nos_ptr[x + i * nos_planestride];
504 		    }
505 		    tos_pixel[num_comp] = tos_ptr[x + num_comp * tos_planestride];
506 		    nos_pixel[num_comp] = nos_ptr[x + num_comp * nos_planestride];
507 		}
508 
509 		if (mask_ptr != NULL) {
510 		    int mask_alpha = mask_ptr[x + num_comp * mask_planestride];
511 		    int tmp;
512 		    byte mask;
513 
514 			/*
515 			* The mask data is really monochrome.  Thus for additive (RGB)
516 			* we use the R channel for alpha since R = G = B.  For
517 			* subtractive (CMYK) we use the K channel.
518 			*/
519 		    if (mask_alpha == 255) {
520 			/* todo: rgba->mask */
521 			mask = additive ? mask_ptr[x]
522 					: 255 - mask_ptr[x + 3 * mask_planestride];
523 		    } else if (mask_alpha == 0)
524 			mask = mask_bg_alpha;
525 		    else {
526 			int t2 = additive ? mask_ptr[x]
527 					: 255 - mask_ptr[x + 3 * mask_planestride];
528 
529 			t2 = (t2 - mask_bg_alpha) * mask_alpha + 0x80;
530 			mask = mask_bg_alpha + ((t2 + (t2 >> 8)) >> 8);
531 		    }
532 		    mask = mask_tr_fn[mask];
533 		    tmp = pix_alpha * mask + 0x80;
534 		    pix_alpha = (tmp + (tmp >> 8)) >> 8;
535 		}
536 
537 		if (nos_knockout) {
538 		    byte *nos_shape_ptr = nos_has_shape ?
539 			&nos_ptr[x + nos_shape_offset] : NULL;
540 		    byte tos_shape = tos_ptr[x + tos_shape_offset];
541 
542 		    art_pdf_composite_knockout_isolated_8(nos_pixel,
543 							nos_shape_ptr,
544 							tos_pixel,
545 							n_chan - 1,
546 							tos_shape,
547 							pix_alpha, shape);
548 		} else if (tos_isolated) {
549 		    art_pdf_composite_group_8(nos_pixel, nos_alpha_g_ptr,
550 						tos_pixel,
551 						n_chan - 1,
552 						pix_alpha, blend_mode);
553 		} else {
554 		    byte tos_alpha_g = tos_ptr[x + tos_alpha_g_offset];
555 		    art_pdf_recomposite_group_8(nos_pixel, nos_alpha_g_ptr,
556 						tos_pixel, tos_alpha_g,
557 						n_chan - 1,
558 						pix_alpha, blend_mode);
559 		}
560 		if (nos_has_shape) {
561 		    nos_ptr[x + nos_shape_offset] =
562 			art_pdf_union_mul_8 (nos_ptr[x + nos_shape_offset],
563 						tos_ptr[x + tos_shape_offset],
564 						shape);
565 		}
566 
567 		/* Complement the results for subtractive color spaces */
568 		if (additive) {
569 		    for (i = 0; i < n_chan; ++i) {
570 			nos_ptr[x + i * nos_planestride] = nos_pixel[i];
571 		    }
572 		} else {
573 		    for (i = 0; i < num_comp; ++i)
574 			nos_ptr[x + i * nos_planestride] = 255 - nos_pixel[i];
575 		    nos_ptr[x + num_comp * nos_planestride] = nos_pixel[num_comp];
576 		}
577 		if (nos_alpha_g_ptr != NULL)
578 		    ++nos_alpha_g_ptr;
579 	    }
580 	    tos_ptr += tos->rowstride;
581 	    nos_ptr += nos->rowstride;
582 	    if (nos_alpha_g_ptr != NULL)
583 		nos_alpha_g_ptr += nos->rowstride - width;
584 	    if (mask_ptr != NULL)
585 		mask_ptr += maskbuf->rowstride;
586 	}
587     }
588 
589     ctx->stack = nos;
590     if_debug0('v', "[v]pop buf\n");
591     pdf14_buf_free(tos, ctx->memory);
592     if (maskbuf != NULL) {
593 	pdf14_buf_free(maskbuf, ctx->memory);
594 	ctx->maskbuf = NULL;
595     }
596     return 0;
597 }
598 
599 private	int
pdf14_push_transparency_mask(pdf14_ctx * ctx,gs_int_rect * rect,byte bg_alpha,byte * transfer_fn)600 pdf14_push_transparency_mask(pdf14_ctx *ctx, gs_int_rect *rect,	byte bg_alpha,
601 			     byte *transfer_fn)
602 {
603     pdf14_buf *buf;
604 
605     if_debug0('v', "[v]pdf_push_transparency_mask\n");
606     buf = pdf14_buf_new(rect, false, false, ctx->n_chan, ctx->memory);
607     if (buf == NULL)
608 	return_error(gs_error_VMerror);
609 
610     /* fill in, but these values aren't really used */
611     buf->isolated = true;
612     buf->knockout = false;
613     buf->alpha = bg_alpha;
614     buf->shape = 0xff;
615     buf->blend_mode = BLEND_MODE_Normal;
616     buf->transfer_fn = transfer_fn;
617 
618     buf->saved = ctx->stack;
619     ctx->stack = buf;
620     memset(buf->data, 0, buf->planestride * buf->n_chan);
621     return 0;
622 }
623 
624 private	int
pdf14_pop_transparency_mask(pdf14_ctx * ctx)625 pdf14_pop_transparency_mask(pdf14_ctx *ctx)
626 {
627     pdf14_buf *tos = ctx->stack;
628 
629     ctx->stack = tos->saved;
630     ctx->maskbuf = tos;
631     return 0;
632 }
633 
634 private	int
pdf14_open(gx_device * dev)635 pdf14_open(gx_device *dev)
636 {
637     pdf14_device *pdev = (pdf14_device *)dev;
638     gs_int_rect rect;
639 
640     if_debug2('v', "[v]pdf14_open: width = %d, height = %d\n",
641 	     dev->width, dev->height);
642 
643     rect.p.x = 0;
644     rect.p.y = 0;
645     rect.q.x = dev->width;
646     rect.q.y = dev->height;
647     pdev->ctx = pdf14_ctx_new(&rect, dev->color_info.num_components + 1,
648 	pdev->color_info.polarity != GX_CINFO_POLARITY_SUBTRACTIVE, dev->memory);
649     if (pdev->ctx == NULL)
650 	return_error(gs_error_VMerror);
651     return 0;
652 }
653 
654 /*
655  * Encode a list of colorant values into a gx_color_index_value.
656  */
657 private	gx_color_index
pdf14_encode_color(gx_device * dev,const gx_color_value colors[])658 pdf14_encode_color(gx_device *dev, const gx_color_value	colors[])
659 {
660     int drop = sizeof(gx_color_value) * 8 - 8;
661     gx_color_index color = 0;
662     int i;
663     int ncomp = dev->color_info.num_components;
664 
665     for (i = 0; i < ncomp; i++) {
666 	color <<= 8;
667 	color |= (colors[i] >> drop);
668     }
669     return (color == gx_no_color_index ? color ^ 1 : color);
670 }
671 
672 /*
673  * Decode a gx_color_index value back to a list of colorant values.
674  */
675 private	int
pdf14_decode_color(gx_device * dev,gx_color_index color,gx_color_value * out)676 pdf14_decode_color(gx_device * dev, gx_color_index color, gx_color_value * out)
677 {
678     int i;
679     int ncomp = dev->color_info.num_components;
680 
681     for (i = 0; i < ncomp; i++) {
682 	out[ncomp - i - 1] = (gx_color_value) ((color & 0xff) * 0x101);
683 	color >>= 8;
684     }
685     return 0;
686 }
687 
688 #ifdef DUMP_TO_PNG
689 /* Dumps a planar RGBA image to	a PNG file. */
690 private	int
dump_planar_rgba(gs_memory_t * mem,const byte * buf,int width,int height,int rowstride,int planestride)691 dump_planar_rgba(gs_memory_t *mem,
692 		 const byte *buf, int width, int height, int rowstride, int planestride)
693 {
694     int rowbytes = width << 2;
695     byte *row = gs_malloc(mem, rowbytes, 1, "png raster buffer");
696     png_struct *png_ptr =
697     png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
698     png_info *info_ptr =
699     png_create_info_struct(png_ptr);
700     const char *software_key = "Software";
701     char software_text[256];
702     png_text text_png;
703     const byte *buf_ptr = buf;
704     FILE *file;
705     int code;
706     int y;
707 
708 	file = fopen ("c:\\temp\\tmp.png", "wb");
709 
710     if_debug0('v', "[v]pnga_output_page\n");
711 
712     if (row == 0 || png_ptr == 0 || info_ptr == 0) {
713 	code = gs_note_error(gs_error_VMerror);
714 	goto done;
715     }
716     /* set error handling */
717     if (setjmp(png_ptr->jmpbuf)) {
718 	/* If we get here, we had a problem reading the file */
719 	code = gs_note_error(gs_error_VMerror);
720 	goto done;
721     }
722 
723     code = 0;			/* for normal path */
724     /* set up the output control */
725     png_init_io(png_ptr, file);
726 
727     /* set the file information here */
728     info_ptr->width = width;
729     info_ptr->height = height;
730     /* resolution is in pixels per meter vs. dpi */
731     info_ptr->x_pixels_per_unit =
732 	(png_uint_32) (96.0 * (100.0 / 2.54));
733     info_ptr->y_pixels_per_unit =
734 	(png_uint_32) (96.0 * (100.0 / 2.54));
735     info_ptr->phys_unit_type = PNG_RESOLUTION_METER;
736     info_ptr->valid |= PNG_INFO_pHYs;
737 
738     /* At present, only supporting 32-bit rgba */
739     info_ptr->bit_depth = 8;
740     info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
741 
742     /* add comment */
743     sprintf(software_text, "%s %d.%02d", gs_product,
744 	    (int)(gs_revision / 100), (int)(gs_revision % 100));
745     text_png.compression = -1;	/* uncompressed */
746     text_png.key = (char *)software_key;	/* not const, unfortunately */
747     text_png.text = software_text;
748     text_png.text_length = strlen(software_text);
749     info_ptr->text = &text_png;
750     info_ptr->num_text = 1;
751 
752     /* write the file information */
753     png_write_info(png_ptr, info_ptr);
754 
755     /* don't write the comments twice */
756     info_ptr->num_text = 0;
757     info_ptr->text = NULL;
758 
759     /* Write the contents of the image. */
760     for (y = 0; y < height; ++y) {
761 	int x;
762 
763 	for (x = 0; x < width; ++x) {
764 	    row[(x << 2)] = buf_ptr[x];
765 	    row[(x << 2) + 1] = buf_ptr[x + planestride];
766 	    row[(x << 2) + 2] = buf_ptr[x + planestride * 2];
767 	    row[(x << 2) + 3] = buf_ptr[x + planestride * 3];
768 	}
769 	png_write_row(png_ptr, row);
770 	buf_ptr += rowstride;
771     }
772 
773     /* write the rest of the file */
774     png_write_end(png_ptr, info_ptr);
775 
776   done:
777     /* free the structures */
778     png_destroy_write_struct(&png_ptr, &info_ptr);
779     gs_free(mem, row, rowbytes, 1, "png raster buffer");
780 
781     fclose (file);
782     return code;
783 }
784 #endif
785 
786 
787 /**
788  * pdf14_put_image: Put rendered image to target device.
789  * @pdev: The PDF 1.4 rendering device.
790  * @pgs: State for image draw operation.
791  * @target: The target device.
792  *
793  * Puts the rendered image in @pdev's buffer to @target. This is called
794  * as part of the sequence of popping the PDF 1.4 device filter.
795  *
796  * Return code: negative on error.
797  **/
798 private	int
pdf14_put_image(pdf14_device * pdev,gs_imager_state * pis,gx_device * target)799 pdf14_put_image(pdf14_device *pdev, gs_imager_state *pis, gx_device *target)
800 {
801     int code;
802     gs_image1_t image;
803     gs_matrix pmat;
804     gx_image_enum_common_t *info;
805     int width = pdev->width;
806     int height = pdev->height;
807     int y;
808     pdf14_buf *buf = pdev->ctx->stack;
809     int planestride = buf->planestride;
810     int num_comp = buf->n_chan - 1;
811     byte *buf_ptr = buf->data;
812     byte *linebuf;
813     gs_color_space cs;
814     const byte bg = pdev->ctx->additive ? 255 : 0;
815 
816 #ifdef DUMP_TO_PNG
817     dump_planar_rgba(pdev->memory, buf_ptr, width, height,
818 		     buf->rowstride, buf->planestride);
819 #endif
820 
821 #if 0
822     /* Set graphics state device to target, so that image can set up
823        the color mapping properly. */
824     rc_increment(pdev);
825     gs_setdevice_no_init(pgs, target);
826 #endif
827 
828     if_debug0('v', "[v]pdf14_put_image\n");
829     /*
830      * Set color space to either Gray, RGB, or CMYK in preparation for sending
831      * an image.
832      */
833     switch (num_comp) {
834 	case 1:				/* DeviceGray */
835 	    gs_cspace_init_DeviceGray(pis->memory, &cs);
836 	    break;
837 	case 3:				/* DeviceRGB */
838 	    gs_cspace_init_DeviceRGB(pis->memory, &cs);
839 	    break;
840 	case 4:				/* DeviceCMYK */
841 	    gs_cspace_init_DeviceCMYK(pis->memory, &cs);
842 	    break;
843 	default:			/* Should never occur */
844 	    return_error(gs_error_rangecheck);
845 	    break;
846     }
847     gs_image_t_init_adjust(&image, &cs, false);
848     image.ImageMatrix.xx = (float)width;
849     image.ImageMatrix.yy = (float)height;
850     image.Width = width;
851     image.Height = height;
852     image.BitsPerComponent = 8;
853     pmat.xx = (float)width;
854     pmat.xy = 0;
855     pmat.yx = 0;
856     pmat.yy = (float)height;
857     pmat.tx = 0;
858     pmat.ty = 0;
859     code = dev_proc(target, begin_typed_image) (target,
860 						pis, &pmat,
861 						(gs_image_common_t *)&image,
862 						NULL, NULL, NULL,
863 						pis->memory, &info);
864     if (code < 0)
865 	return code;
866 
867     linebuf = gs_alloc_bytes(pdev->memory, width * num_comp, "pdf14_put_image");
868     for (y = 0; y < height; y++) {
869 	gx_image_plane_t planes;
870 	int x;
871 	int rows_used;
872 
873 	for (x = 0; x < width; x++) {
874 	    byte comp, a;
875 	    int tmp, comp_num;
876 
877 	    /* composite RGBA (or CMYKA, etc.) pixel with over solid background */
878 	    a = buf_ptr[x + planestride * num_comp];
879 
880 	    if ((a + 1) & 0xfe) {
881 		a ^= 0xff;
882 		for (comp_num = 0; comp_num < num_comp; comp_num++) {
883 		    comp  = buf_ptr[x + planestride * comp_num];
884 		    tmp = ((bg - comp) * a) + 0x80;
885 		    comp += (tmp + (tmp >> 8)) >> 8;
886 		    linebuf[x * num_comp + comp_num] = comp;
887 		}
888 	    } else if (a == 0) {
889 		for (comp_num = 0; comp_num < num_comp; comp_num++) {
890 		    linebuf[x * num_comp + comp_num] = bg;
891 		}
892 	    } else {
893 		for (comp_num = 0; comp_num < num_comp; comp_num++) {
894 		    comp = buf_ptr[x + planestride * comp_num];
895 		    linebuf[x * num_comp + comp_num] = comp;
896 		}
897 	    }
898 	}
899 
900 	planes.data = linebuf;
901 	planes.data_x = 0;
902 	planes.raster = width * num_comp;
903 	info->procs->plane_data(info, &planes, 1, &rows_used);
904 	/* todo: check return value */
905 
906 	buf_ptr += buf->rowstride;
907     }
908     gs_free_object(pdev->memory, linebuf, "pdf14_put_image");
909 
910     info->procs->end_image(info, true);
911 
912 #if 0
913     /* Restore device in graphics state.*/
914     gs_setdevice_no_init(pgs, (gx_device*) pdev);
915     rc_decrement_only(pdev, "pdf_14_put_image");
916 #endif
917 
918     return code;
919 }
920 
921 private	int
pdf14_close(gx_device * dev)922 pdf14_close(gx_device *dev)
923 {
924     pdf14_device *pdev = (pdf14_device *)dev;
925 
926     if (pdev->ctx) {
927 	pdf14_ctx_free(pdev->ctx);
928 	pdev->ctx = NULL;
929     }
930     return 0;
931 }
932 
933 private	int
pdf14_output_page(gx_device * dev,int num_copies,int flush)934 pdf14_output_page(gx_device * dev, int num_copies, int flush)
935 {
936     pdf14_device * pdev = (pdf14_device *)dev;
937 
938     if (pdev->target != NULL)
939 	return (*dev_proc(pdev->target, output_page)) (pdev->target, num_copies, flush);
940     return 0;
941 }
942 
943 #define	COPY_PARAM(p) dev->p = target->p
944 #define	COPY_ARRAY_PARAM(p) memcpy(dev->p, target->p, sizeof(dev->p))
945 
946 /*
947  * Copy device parameters back from a target.  This copies all standard
948  * parameters related to page size and resolution, but not any of the
949  * color-related parameters, as the pdf14 device retains its own color
950  * handling. This routine is parallel to gx_device_copy_params().
951  */
952 private	void
gs_pdf14_device_copy_params(gx_device * dev,const gx_device * target)953 gs_pdf14_device_copy_params(gx_device *dev, const gx_device *target)
954 {
955 	COPY_PARAM(width);
956 	COPY_PARAM(height);
957 	COPY_ARRAY_PARAM(MediaSize);
958 	COPY_ARRAY_PARAM(ImagingBBox);
959 	COPY_PARAM(ImagingBBox_set);
960 	COPY_ARRAY_PARAM(HWResolution);
961 	COPY_ARRAY_PARAM(MarginsHWResolution);
962 	COPY_ARRAY_PARAM(Margins);
963 	COPY_ARRAY_PARAM(HWMargins);
964 	COPY_PARAM(PageCount);
965 #undef COPY_ARRAY_PARAM
966 #undef COPY_PARAM
967 }
968 
969 /*
970  * This is a forwarding version of the put_params device proc.  It is only
971  * used when the PDF 1.4 compositor devices are closed.  The routine will
972  * check if the target device has closed and, if so, close itself.  The routine
973  * also sync the device parameters.
974  */
975 private	int
pdf14_forward_put_params(gx_device * dev,gs_param_list * plist)976 pdf14_forward_put_params(gx_device * dev, gs_param_list	* plist)
977 {
978     pdf14_device * pdev = (pdf14_device *)dev;
979     gx_device * tdev = pdev->target;
980     int code = 0;
981 
982     if (tdev != 0 && (code = dev_proc(tdev, put_params)(tdev, plist)) >= 0) {
983 	gx_device_decache_colors(dev);
984 	if (!tdev->is_open)
985 	    code = gs_closedevice(dev);
986 	gx_device_copy_params(dev, tdev);
987     }
988     return code;
989 }
990 
991 /*
992  * The put_params method for the PDF 1.4 device will check if the
993  * target device has closed and, if so, close itself.  Note:  This routine is
994  * currently being used by both the pdf14_clist_device and the pdf_device.
995  * Please make sure that any changes are either applicable to both devices
996  * or clone the routine for each device.
997  */
998 private	int
pdf14_put_params(gx_device * dev,gs_param_list * plist)999 pdf14_put_params(gx_device * dev, gs_param_list	* plist)
1000 {
1001     pdf14_device * pdev = (pdf14_device *)dev;
1002     gx_device * tdev = pdev->target;
1003     int code = 0;
1004 
1005     if (tdev != 0 && (code = dev_proc(tdev, put_params)(tdev, plist)) >= 0) {
1006 	gx_device_decache_colors(dev);
1007 	if (!tdev->is_open)
1008 	    code = gs_closedevice(dev);
1009 	gs_pdf14_device_copy_params(dev, tdev);
1010     }
1011     return code;
1012 }
1013 
1014 /*
1015  * Copy marking related parameters into the PDF 1.4 device structure for use
1016  * by pdf14_fill_rrectangle.
1017  */
1018 private	void
pdf14_set_marking_params(gx_device * dev,const gs_imager_state * pis)1019 pdf14_set_marking_params(gx_device *dev, const gs_imager_state *pis)
1020 {
1021     pdf14_device * pdev = (pdf14_device *)dev;
1022 
1023     pdev->opacity = pis->opacity.alpha;
1024     pdev->shape = pis->shape.alpha;
1025     pdev->alpha = pis->opacity.alpha * pis->shape.alpha;
1026     pdev->blend_mode = pis->blend_mode;
1027     if_debug3('v', "[v]set_marking_params, opacity = %g, shape = %g, bm = %d\n",
1028 	      pdev->opacity, pdev->shape, pis->blend_mode);
1029 }
1030 
1031 private	int
pdf14_fill_path(gx_device * dev,const gs_imager_state * pis,gx_path * ppath,const gx_fill_params * params,const gx_drawing_color * pdcolor,const gx_clip_path * pcpath)1032 pdf14_fill_path(gx_device *dev,	const gs_imager_state *pis,
1033 			   gx_path *ppath, const gx_fill_params *params,
1034 			   const gx_drawing_color *pdcolor,
1035 			   const gx_clip_path *pcpath)
1036 {
1037     gs_imager_state new_is = *pis;
1038 
1039     /*
1040      * The blend operations are not idempotent.  Force non-idempotent
1041      * filling and stroking operations.
1042      */
1043     new_is.log_op |= lop_pdf14;
1044     pdf14_set_marking_params(dev, pis);
1045     return gx_default_fill_path(dev, &new_is, ppath, params, pdcolor, pcpath);
1046 }
1047 
1048 private	int
pdf14_stroke_path(gx_device * dev,const gs_imager_state * pis,gx_path * ppath,const gx_stroke_params * params,const gx_drawing_color * pdcolor,const gx_clip_path * pcpath)1049 pdf14_stroke_path(gx_device *dev, const	gs_imager_state	*pis,
1050 			     gx_path *ppath, const gx_stroke_params *params,
1051 			     const gx_drawing_color *pdcolor,
1052 			     const gx_clip_path *pcpath)
1053 {
1054     gs_imager_state new_is = *pis;
1055 
1056     /*
1057      * The blend operations are not idempotent.  Force non-idempotent
1058      * filling and stroking operations.
1059      */
1060     new_is.log_op |= lop_pdf14;
1061     pdf14_set_marking_params(dev, pis);
1062     return gx_default_stroke_path(dev, &new_is, ppath, params, pdcolor,
1063 				  pcpath);
1064 }
1065 
1066 private	int
pdf14_begin_typed_image(gx_device * dev,const gs_imager_state * pis,const gs_matrix * pmat,const gs_image_common_t * pic,const gs_int_rect * prect,const gx_drawing_color * pdcolor,const gx_clip_path * pcpath,gs_memory_t * mem,gx_image_enum_common_t ** pinfo)1067 pdf14_begin_typed_image(gx_device * dev, const gs_imager_state * pis,
1068 			   const gs_matrix *pmat, const gs_image_common_t *pic,
1069 			   const gs_int_rect * prect,
1070 			   const gx_drawing_color * pdcolor,
1071 			   const gx_clip_path * pcpath, gs_memory_t * mem,
1072 			   gx_image_enum_common_t ** pinfo)
1073 {
1074     pdf14_set_marking_params(dev, pis);
1075     return gx_default_begin_typed_image(dev, pis, pmat, pic, prect, pdcolor,
1076 					pcpath, mem, pinfo);
1077 }
1078 
1079 private	void
pdf14_set_params(gs_imager_state * pis,gx_device * dev,const gs_pdf14trans_params_t * pparams)1080 pdf14_set_params(gs_imager_state * pis,	gx_device * dev,
1081 				const gs_pdf14trans_params_t * pparams)
1082 {
1083     if (pparams->changed & PDF14_SET_BLEND_MODE)
1084 	pis->blend_mode = pparams->blend_mode;
1085     if (pparams->changed & PDF14_SET_TEXT_KNOCKOUT)
1086 	pis->text_knockout = pparams->text_knockout;
1087     if (pparams->changed & PDF14_SET_SHAPE_ALPHA)
1088 	pis->shape.alpha = pparams->shape.alpha;
1089     if (pparams->changed & PDF14_SET_OPACITY_ALPHA)
1090 	pis->opacity.alpha = pparams->opacity.alpha;
1091     pdf14_set_marking_params(dev, pis);
1092 }
1093 
1094 /*
1095  * This open_device method for the PDF 1.4 compositor devices is only used
1096  * when these devices are disabled.  This routine is about as close to
1097  * a pure "forwarding" open_device operation as is possible. Its only
1098  * significant function is to ensure that the is_open field of the
1099  * PDF 1.4 compositor devices matches that of the target device.
1100  *
1101  * We assume this procedure is called only if the device is not already
1102  * open, and that gs_opendevice will take care of the is_open flag.
1103  */
1104 private	int
pdf14_forward_open_device(gx_device * dev)1105 pdf14_forward_open_device(gx_device * dev)
1106 {
1107     gx_device_forward * pdev = (gx_device_forward *)dev;
1108     gx_device * tdev = pdev->target;
1109     int code = 0;
1110 
1111     /* The PDF 1.4 compositing devices must have a target */
1112     if (tdev == 0)
1113 	return_error(gs_error_unknownerror);
1114     if ((code = gs_opendevice(tdev)) >= 0)
1115 	gx_device_copy_params(dev, tdev);
1116     return code;
1117 }
1118 
1119 /*
1120  * Convert all device procs to be 'forwarding'.  The caller is responsible
1121  * for setting any device procs that should not be forwarded.
1122  */
1123 private	void
pdf14_forward_device_procs(gx_device * dev)1124 pdf14_forward_device_procs(gx_device * dev)
1125 {
1126     gx_device_forward * pdev = (gx_device_forward *)dev;
1127 
1128     /*
1129      * We are using gx_device_forward_fill_in_procs to set the various procs.
1130      * This will ensure that any new device procs are also set.  However that
1131      * routine only changes procs which are NULL.  Thus we start by setting all
1132      * procs to NULL.
1133      */
1134     memset(&(pdev->procs), 0, size_of(pdev->procs));
1135     gx_device_forward_fill_in_procs(pdev);
1136     /*
1137      * gx_device_forward_fill_in_procs does not forward all procs.
1138      * Set the remainding procs to also forward.
1139      */
1140     set_dev_proc(dev, close_device, gx_forward_close_device);
1141     set_dev_proc(dev, fill_rectangle, gx_forward_fill_rectangle);
1142     set_dev_proc(dev, tile_rectangle, gx_forward_tile_rectangle);
1143     set_dev_proc(dev, copy_mono, gx_forward_copy_mono);
1144     set_dev_proc(dev, copy_color, gx_forward_copy_color);
1145     set_dev_proc(dev, get_page_device, gx_forward_get_page_device);
1146     set_dev_proc(dev, strip_tile_rectangle, gx_forward_strip_tile_rectangle);
1147     set_dev_proc(dev, copy_alpha, gx_forward_copy_alpha);
1148     /* These are forwarding devices with minor tweaks. */
1149     set_dev_proc(dev, open_device, pdf14_forward_open_device);
1150     set_dev_proc(dev, put_params, pdf14_forward_put_params);
1151 }
1152 
1153 /*
1154  * Disable the PDF 1.4 compositor device.  Once created, the PDF 1.4
1155  * compositor device is never removed.  (We do not have a remove compositor
1156  * method.)  However it is no-op'ed when the PDF 1.4 device is popped.  This
1157  * routine implements that action.
1158  */
1159 private	int
pdf14_disable_device(gx_device * dev)1160 pdf14_disable_device(gx_device * dev)
1161 {
1162     gx_device_forward * pdev = (gx_device_forward *)dev;
1163 
1164     if_debug0('v', "[v]pdf14_disable_device\n");
1165     dev->color_info = pdev->target->color_info;
1166     pdf14_forward_device_procs(dev);
1167     set_dev_proc(dev, create_compositor, pdf14_forward_create_compositor);
1168     return 0;
1169 }
1170 
1171 /*
1172  * The default color space for PDF 1.4 blend modes is based upon the process
1173  * color model of the output device.
1174  */
1175 private	pdf14_default_colorspace_t
pdf14_determine_default_blend_cs(gx_device * pdev)1176 pdf14_determine_default_blend_cs(gx_device * pdev)
1177 {
1178     if (pdev->color_info.polarity == GX_CINFO_POLARITY_SUBTRACTIVE)
1179 	/* Use DeviceCMYK for all subrtactive process color models. */
1180 	return DeviceCMYK;
1181     else {
1182 	/*
1183 	 * Note:  We do not allow the SeparationOrder device parameter for
1184 	 * additive devices.  Thus we always have 1 colorant for DeviceGray
1185 	 * and 3 colorants for DeviceRGB.  We do not currently support
1186 	 * blending in a DeviceGray color space.  Thus we oniy use DeviceRGB.
1187 	 */
1188 	return DeviceRGB;
1189     }
1190 }
1191 
1192 /*
1193  * the PDF 1.4 transparency spec says that color space for blending
1194  * operations can be based upon either a color space specified in the
1195  * group or a default value based upon the output device.  We are
1196  * currently only using a color space based upon the device.
1197  */
1198 private	int
get_pdf14_device_proto(gx_device * dev,const pdf14_device ** pdevproto)1199 get_pdf14_device_proto(gx_device * dev,
1200 		const pdf14_device ** pdevproto)
1201 {
1202     pdf14_default_colorspace_t dev_cs =
1203 		pdf14_determine_default_blend_cs(dev);
1204 
1205     switch (dev_cs) {
1206 	case DeviceGray:
1207 	    *pdevproto = &gs_pdf14_Gray_device;
1208 	    break;
1209 	case DeviceRGB:
1210 	    *pdevproto = &gs_pdf14_RGB_device;
1211 	    break;
1212 	case DeviceCMYK:
1213 	    *pdevproto = &gs_pdf14_CMYK_device;
1214 	    break;
1215 	default:			/* Should not occur */
1216 	    return_error(gs_error_rangecheck);
1217     }
1218     return 0;
1219 }
1220 
1221 /*
1222  * Recreate the PDF 1.4 compositor device.  Once created, the PDF 1.4
1223  * compositor device is never removed.  (We do not have a remove compositor
1224  * method.)  However it is no-op'ed when the PDF 1.4 device is popped.  This
1225  * routine will re-enable the compositor if the PDF 1.4 device is pushed
1226  * again.
1227  */
1228 private	int
pdf14_recreate_device(gs_memory_t * mem,gs_imager_state * pis,gx_device * dev)1229 pdf14_recreate_device(gs_memory_t *mem,	gs_imager_state	* pis,
1230 				gx_device * dev)
1231 {
1232     pdf14_device * pdev = (pdf14_device *)dev;
1233     gx_device * target = pdev->target;
1234     const pdf14_device * dev_proto;
1235     int code;
1236 
1237     if_debug0('v', "[v]pdf14_recreate_device\n");
1238 
1239     /*
1240      * We will not use the entire prototype device but we will set the
1241      * color related info and the device procs to match the prototype.
1242      */
1243     code = get_pdf14_device_proto(target, &dev_proto);
1244     if (code < 0)
1245 	return code;
1246     pdev->color_info = dev_proto->color_info;
1247     pdev->procs = dev_proto->procs;
1248     gx_device_fill_in_procs(dev);
1249     check_device_separable((gx_device *)pdev);
1250 
1251     return code;
1252 }
1253 
1254 /*
1255  * Implement the various operations that can be specified via the PDF 1.4
1256  * create compositor request.
1257  */
1258 private	int
gx_update_pdf14_compositor(gx_device * pdev,gs_imager_state * pis,const gs_pdf14trans_t * pdf14pct,gs_memory_t * mem)1259 gx_update_pdf14_compositor(gx_device * pdev, gs_imager_state * pis,
1260     const gs_pdf14trans_t * pdf14pct, gs_memory_t * mem )
1261 {
1262     pdf14_device *p14dev = (pdf14_device *)pdev;
1263     int code = 0;
1264 
1265     switch (pdf14pct->params.pdf14_op) {
1266 	default:			/* Should not occur. */
1267 	    break;
1268 	case PDF14_PUSH_DEVICE:
1269 	    p14dev->blend_mode = 0;
1270 	    p14dev->opacity = p14dev->shape = 0.0;
1271 	    pdf14_recreate_device(mem, pis, pdev);
1272 	    break;
1273 	case PDF14_POP_DEVICE:
1274 	    pis->get_cmap_procs = p14dev->save_get_cmap_procs;
1275 	    gx_set_cmap_procs(pis, p14dev->target);
1276 	    code = pdf14_put_image(p14dev, pis, p14dev->target);
1277 	    pdf14_disable_device(pdev);
1278 	    pdf14_close(pdev);
1279 	    break;
1280 	case PDF14_BEGIN_TRANS_GROUP:
1281 	    code = gx_begin_transparency_group(pis, pdev, &pdf14pct->params);
1282 	    break;
1283 	case PDF14_END_TRANS_GROUP:
1284 	    code = gx_end_transparency_group(pis, pdev);
1285 	    break;
1286 	case PDF14_INIT_TRANS_MASK:
1287 	    code = gx_init_transparency_mask(pis, &pdf14pct->params);
1288 	    break;
1289 	case PDF14_BEGIN_TRANS_MASK:
1290 	    code = gx_begin_transparency_mask(pis, pdev, &pdf14pct->params);
1291 	    break;
1292 	case PDF14_END_TRANS_MASK:
1293 	    code = gx_end_transparency_mask(pis, pdev, &pdf14pct->params);
1294 	    break;
1295 	case PDF14_SET_BLEND_PARAMS:
1296 	    pdf14_set_params(pis, pdev, &pdf14pct->params);
1297 	    break;
1298     }
1299     return code;
1300 }
1301 
1302 /*
1303  * The PDF 1.4 compositor is never removed.  (We do not have a 'remove
1304  * compositor' method.  However the compositor is disabled when we are not
1305  * doing a page which uses PDF 1.4 transparency.  This routine is only active
1306  * when the PDF 1.4 compositor is 'disabled'.  It checks for reenabling the
1307  * PDF 1.4 compositor.  Otherwise it simply passes create compositor requests
1308  * to the targer.
1309  */
1310 private	int
pdf14_forward_create_compositor(gx_device * dev,gx_device ** pcdev,const gs_composite_t * pct,gs_imager_state * pis,gs_memory_t * mem)1311 pdf14_forward_create_compositor(gx_device * dev, gx_device * * pcdev,
1312 	const gs_composite_t * pct, gs_imager_state * pis,
1313 	gs_memory_t * mem)
1314 {
1315     pdf14_device *pdev = (pdf14_device *)dev;
1316     gx_device * tdev = pdev->target;
1317     gx_device * ndev;
1318     int code = 0;
1319 
1320     *pcdev = dev;
1321     if (gs_is_pdf14trans_compositor(pct)) {
1322 	const gs_pdf14trans_t * pdf14pct = (const gs_pdf14trans_t *) pct;
1323 
1324 	if (pdf14pct->params.pdf14_op == PDF14_PUSH_DEVICE)
1325 	    return gx_update_pdf14_compositor(dev, pis, pdf14pct, mem);
1326 	return 0;
1327     }
1328     code = dev_proc(tdev, create_compositor)(tdev, &ndev, pct, pis, mem);
1329     if (code < 0)
1330 	return code;
1331     pdev->target = ndev;
1332     return 0;
1333 }
1334 
1335 /*
1336  * The PDF 1.4 compositor can be handled directly, so just set *pcdev = dev
1337  * and return. Since the gs_pdf14_device only supports the high-level routines
1338  * of the interface, don't bother trying to handle any other compositor.
1339  */
1340 private	int
pdf14_create_compositor(gx_device * dev,gx_device ** pcdev,const gs_composite_t * pct,gs_imager_state * pis,gs_memory_t * mem)1341 pdf14_create_compositor(gx_device * dev, gx_device * * pcdev,
1342 	const gs_composite_t * pct, gs_imager_state * pis,
1343 	gs_memory_t * mem)
1344 {
1345     if (gs_is_pdf14trans_compositor(pct)) {
1346 	const gs_pdf14trans_t * pdf14pct = (const gs_pdf14trans_t *) pct;
1347 
1348 	*pcdev = dev;
1349 	return gx_update_pdf14_compositor(dev, pis, pdf14pct, mem);
1350     } else if (gs_is_overprint_compositor(pct)) {
1351 	*pcdev = dev;
1352 	return 0;
1353     } else
1354 	return gx_no_create_compositor(dev, pcdev, pct, pis, mem);
1355 }
1356 
1357 private	int
pdf14_text_begin(gx_device * dev,gs_imager_state * pis,const gs_text_params_t * text,gs_font * font,gx_path * path,const gx_device_color * pdcolor,const gx_clip_path * pcpath,gs_memory_t * memory,gs_text_enum_t ** ppenum)1358 pdf14_text_begin(gx_device * dev, gs_imager_state * pis,
1359 		 const gs_text_params_t * text, gs_font * font,
1360 		 gx_path * path, const gx_device_color * pdcolor,
1361 		 const gx_clip_path * pcpath, gs_memory_t * memory,
1362 		 gs_text_enum_t ** ppenum)
1363 {
1364     int code;
1365     gs_text_enum_t *penum;
1366 
1367     if_debug0('v', "[v]pdf14_text_begin\n");
1368     pdf14_set_marking_params(dev, pis);
1369     code = gx_default_text_begin(dev, pis, text, font, path, pdcolor, pcpath,
1370 				 memory, &penum);
1371     if (code < 0)
1372 	return code;
1373     *ppenum = (gs_text_enum_t *)penum;
1374     return code;
1375 }
1376 
1377 private	int
pdf14_fill_rectangle(gx_device * dev,int x,int y,int w,int h,gx_color_index color)1378 pdf14_fill_rectangle(gx_device * dev,
1379 		    int x, int y, int w, int h, gx_color_index color)
1380 {
1381     pdf14_device *pdev = (pdf14_device *)dev;
1382     pdf14_buf *buf = pdev->ctx->stack;
1383 
1384     fit_fill_xywh(dev, x, y, w, h);
1385     if (w <= 0 || h <= 0)
1386 	return 0;
1387     if (buf->knockout)
1388 	return pdf14_mark_fill_rectangle_ko_simple(dev, x, y, w, h, color);
1389     else
1390 	return pdf14_mark_fill_rectangle(dev, x, y, w, h, color);
1391 }
1392 
1393 private	int
pdf14_begin_transparency_group(gx_device * dev,const gs_transparency_group_params_t * ptgp,const gs_rect * pbbox,gs_imager_state * pis,gs_transparency_state_t ** ppts,gs_memory_t * mem)1394 pdf14_begin_transparency_group(gx_device *dev,
1395 			      const gs_transparency_group_params_t *ptgp,
1396 			      const gs_rect *pbbox,
1397 			      gs_imager_state *pis,
1398 			      gs_transparency_state_t **ppts,
1399 			      gs_memory_t *mem)
1400 {
1401     pdf14_device *pdev = (pdf14_device *)dev;
1402     double alpha = pis->opacity.alpha * pis->shape.alpha;
1403     gs_rect dev_bbox;
1404     gs_int_rect rect;
1405     int code;
1406 
1407     code = gs_bbox_transform(pbbox, &ctm_only(pis), &dev_bbox);
1408     if (code < 0)
1409 	return code;
1410     rect.p.x = (int)floor(dev_bbox.p.x);
1411     rect.p.y = (int)floor(dev_bbox.p.y);
1412     rect.q.x = (int)ceil(dev_bbox.q.x);
1413     rect.q.y = (int)ceil(dev_bbox.q.y);
1414     rect_intersect(rect, pdev->ctx->rect);
1415     if_debug4('v', "[v]begin_transparency_group, I = %d, K = %d, alpha = %g, bm = %d\n",
1416 	      ptgp->Isolated, ptgp->Knockout, alpha, pis->blend_mode);
1417     code = pdf14_push_transparency_group(pdev->ctx, &rect,
1418 					 ptgp->Isolated, ptgp->Knockout,
1419 					 (byte)floor (255 * alpha + 0.5),
1420 					 (byte)floor (255 * pis->shape.alpha + 0.5),
1421 					 pis->blend_mode);
1422     return code;
1423 }
1424 
1425 private	int
pdf14_end_transparency_group(gx_device * dev,gs_imager_state * pis,gs_transparency_state_t ** ppts)1426 pdf14_end_transparency_group(gx_device *dev,
1427 			      gs_imager_state *pis,
1428 			      gs_transparency_state_t **ppts)
1429 {
1430     pdf14_device *pdev = (pdf14_device *)dev;
1431     int code;
1432 
1433     if_debug0('v', "[v]end_transparency_group\n");
1434     code = pdf14_pop_transparency_group(pdev->ctx);
1435     return code;
1436 }
1437 
1438 private	int
pdf14_begin_transparency_mask(gx_device * dev,const gx_transparency_mask_params_t * ptmp,const gs_rect * pbbox,gs_imager_state * pis,gs_transparency_state_t ** ppts,gs_memory_t * mem)1439 pdf14_begin_transparency_mask(gx_device	*dev,
1440 			      const gx_transparency_mask_params_t *ptmp,
1441 			      const gs_rect *pbbox,
1442 			      gs_imager_state *pis,
1443 			      gs_transparency_state_t **ppts,
1444 			      gs_memory_t *mem)
1445 {
1446     pdf14_device *pdev = (pdf14_device *)dev;
1447     byte bg_alpha = 0;
1448     byte *transfer_fn = (byte *)gs_alloc_bytes(pdev->ctx->memory, 256,
1449 					       "pdf14_push_transparency_mask");
1450 
1451     if (ptmp->Background_components)
1452 	bg_alpha = (int)(255 * ptmp->Background[0] + 0.5);
1453     if_debug1('v', "begin transparency mask, bg_alpha = %d\n", bg_alpha);
1454     memcpy(transfer_fn, ptmp->transfer_fn, size_of(ptmp->transfer_fn));
1455     return pdf14_push_transparency_mask(pdev->ctx, &pdev->ctx->rect, bg_alpha,
1456 					transfer_fn);
1457 }
1458 
1459 private	int
pdf14_end_transparency_mask(gx_device * dev,gs_transparency_mask_t ** pptm)1460 pdf14_end_transparency_mask(gx_device *dev,
1461 			  gs_transparency_mask_t **pptm)
1462 {
1463     pdf14_device *pdev = (pdf14_device *)dev;
1464 
1465     if_debug0('v', "end transparency mask!\n");
1466     return pdf14_pop_transparency_mask(pdev->ctx);
1467 }
1468 
1469 private	int
pdf14_mark_fill_rectangle(gx_device * dev,int x,int y,int w,int h,gx_color_index color)1470 pdf14_mark_fill_rectangle(gx_device * dev,
1471 			 int x, int y, int w, int h, gx_color_index color)
1472 {
1473     pdf14_device *pdev = (pdf14_device *)dev;
1474     pdf14_buf *buf = pdev->ctx->stack;
1475     int i, j, k;
1476     byte *line, *dst_ptr;
1477     byte src[PDF14_MAX_PLANES];
1478     byte dst[PDF14_MAX_PLANES];
1479     gs_blend_mode_t blend_mode = pdev->blend_mode;
1480     bool additive = pdev->ctx->additive;
1481     int rowstride = buf->rowstride;
1482     int planestride = buf->planestride;
1483     bool has_alpha_g = buf->has_alpha_g;
1484     bool has_shape = buf->has_shape;
1485     int num_chan = buf->n_chan;
1486     int num_comp = num_chan - 1;
1487     int shape_off = num_chan * planestride;
1488     int alpha_g_off = shape_off + (has_shape ? planestride : 0);
1489     byte shape = 0; /* Quiet compiler. */
1490     byte src_alpha;
1491 
1492     if_debug7('v', "[v]pdf14_mark_fill_rectangle, (%d, %d), %d x %d color = %lx  bm %d, nc %d,\n", x, y, w, h, color, blend_mode, num_chan);
1493 
1494     /* Complement the components for subtractive color spaces */
1495     if (additive) {
1496 	for (i = num_comp - 1; i >= 0; i--) {
1497 	    src[i] = (byte)(color & 0xff);
1498 	    color >>= 8;
1499 	}
1500     }
1501     else {
1502 	for (i = num_comp - 1; i >= 0; i--) {
1503 	    src[i] = (byte)(0xff - (color & 0xff));
1504 	    color >>= 8;
1505 	}
1506     }
1507     src_alpha = src[num_comp] = (byte)floor (255 * pdev->alpha + 0.5);
1508     if (has_shape)
1509 	shape = (byte)floor (255 * pdev->shape + 0.5);
1510 
1511     if (x < buf->rect.p.x) x = buf->rect.p.x;
1512     if (y < buf->rect.p.y) y = buf->rect.p.y;
1513     if (x + w > buf->rect.q.x) w = buf->rect.q.x - x;
1514     if (y + h > buf->rect.q.y) h = buf->rect.q.y - y;
1515 
1516     if (x < buf->bbox.p.x) buf->bbox.p.x = x;
1517     if (y < buf->bbox.p.y) buf->bbox.p.y = y;
1518     if (x + w > buf->bbox.q.x) buf->bbox.q.x = x + w;
1519     if (y + h > buf->bbox.q.y) buf->bbox.q.y = y + h;
1520 
1521     line = buf->data + (x - buf->rect.p.x) + (y - buf->rect.p.y) * rowstride;
1522 
1523     for (j = 0; j < h; ++j) {
1524 	dst_ptr = line;
1525 	for (i = 0; i < w; ++i) {
1526 	    /* Complement the components for subtractive color spaces */
1527 	    if (additive) {
1528 		for (k = 0; k < num_chan; ++k)
1529 		    dst[k] = dst_ptr[k * planestride];
1530 	    }
1531 	    else { /* Complement the components for subtractive color spaces */
1532 		for (k = 0; k < num_comp; ++k)
1533 		    dst[k] = 255 - dst_ptr[k * planestride];
1534 		dst[num_comp] = dst_ptr[num_comp * planestride];
1535 	    }
1536 	    art_pdf_composite_pixel_alpha_8(dst, src, num_comp, blend_mode);
1537 	    /* Complement the results for subtractive color spaces */
1538 	    if (additive) {
1539 		for (k = 0; k < num_chan; ++k)
1540 		    dst_ptr[k * planestride] = dst[k];
1541 	    }
1542 	    else {
1543 		for (k = 0; k < num_comp; ++k)
1544 		    dst_ptr[k * planestride] = 255 - dst[k];
1545 		dst_ptr[num_comp * planestride] = dst[num_comp];
1546 	    }
1547 	    if (has_alpha_g) {
1548 		int tmp = (255 - dst_ptr[alpha_g_off]) * (255 - src_alpha) + 0x80;
1549 		dst_ptr[alpha_g_off] = 255 - ((tmp + (tmp >> 8)) >> 8);
1550 	    }
1551 	    if (has_shape) {
1552 		int tmp = (255 - dst_ptr[shape_off]) * (255 - shape) + 0x80;
1553 		dst_ptr[shape_off] = 255 - ((tmp + (tmp >> 8)) >> 8);
1554 	    }
1555 	    ++dst_ptr;
1556 	}
1557 	line += rowstride;
1558     }
1559     return 0;
1560 }
1561 
1562 private	int
pdf14_mark_fill_rectangle_ko_simple(gx_device * dev,int x,int y,int w,int h,gx_color_index color)1563 pdf14_mark_fill_rectangle_ko_simple(gx_device *	dev,
1564 				   int x, int y, int w, int h, gx_color_index color)
1565 {
1566     pdf14_device *pdev = (pdf14_device *)dev;
1567     pdf14_buf *buf = pdev->ctx->stack;
1568     int i, j, k;
1569     byte *line, *dst_ptr;
1570     byte src[PDF14_MAX_PLANES];
1571     byte dst[PDF14_MAX_PLANES];
1572     int rowstride = buf->rowstride;
1573     int planestride = buf->planestride;
1574     int num_chan = buf->n_chan;
1575     int num_comp = num_chan - 1;
1576     int shape_off = num_chan * planestride;
1577     bool has_shape = buf->has_shape;
1578     byte opacity;
1579     bool additive = pdev->ctx->additive;
1580 
1581     if_debug6('v', "[v]pdf14_mark_fill_rectangle_ko_simple, (%d, %d), %d x %d color = %lx  bm %d, nc %d,\n", x, y, w, h, color, num_chan);
1582 
1583     /* Complement the components for subtractive color spaces */
1584     if (additive) {
1585 	for (i = num_comp - 1; i >= 0; i--) {
1586 	    src[i] = (byte)(color & 0xff);
1587 	    color >>= 8;
1588 	}
1589     }
1590     else {
1591 	for (i = num_comp - 1; i >= 0; i--) {
1592 	    src[i] = (byte)(0xff - (color & 0xff));
1593 	    color >>= 8;
1594 	}
1595     }
1596     src[num_comp] = (byte)floor (255 * pdev->alpha + 0.5);
1597     opacity = (byte)floor (255 * pdev->opacity + 0.5);
1598 
1599     if (x < buf->rect.p.x) x = buf->rect.p.x;
1600     if (y < buf->rect.p.y) y = buf->rect.p.y;
1601     if (x + w > buf->rect.q.x) w = buf->rect.q.x - x;
1602     if (y + h > buf->rect.q.y) h = buf->rect.q.y - y;
1603 
1604     if (x < buf->bbox.p.x) buf->bbox.p.x = x;
1605     if (y < buf->bbox.p.y) buf->bbox.p.y = y;
1606     if (x + w > buf->bbox.q.x) buf->bbox.q.x = x + w;
1607     if (y + h > buf->bbox.q.y) buf->bbox.q.y = y + h;
1608 
1609     line = buf->data + (x - buf->rect.p.x) + (y - buf->rect.p.y) * rowstride;
1610 
1611     for (j = 0; j < h; ++j) {
1612 	dst_ptr = line;
1613 	for (i = 0; i < w; ++i) {
1614 	    /* Complement the components for subtractive color spaces */
1615 	    if (additive) {
1616 		for (k = 0; k < num_chan; ++k)
1617 		    dst[k] = dst_ptr[k * planestride];
1618 	    }
1619 	    else {
1620 		for (k = 0; k < num_comp; ++k)
1621 		    dst[k] = 255 - dst_ptr[k * planestride];
1622 		dst[num_comp] = dst_ptr[num_comp * planestride];
1623 	    }
1624 	    art_pdf_composite_knockout_simple_8(dst,
1625 		has_shape ? dst_ptr + shape_off : NULL, src, num_comp, opacity);
1626 	    /* Complement the results for subtractive color spaces */
1627 	    if (additive) {
1628 		for (k = 0; k < num_chan; ++k)
1629 		    dst_ptr[k * planestride] = dst[k];
1630 	    }
1631 	    else {
1632 		for (k = 0; k < num_comp; ++k)
1633 		    dst_ptr[k * planestride] = 255 - dst[k];
1634 		dst_ptr[num_comp * planestride] = dst[num_comp];
1635 	    }
1636 	    ++dst_ptr;
1637 	}
1638 	line += rowstride;
1639     }
1640     return 0;
1641 }
1642 
1643 /**
1644  * Here we have logic to override the cmap_procs with versions that
1645  * do not apply the transfer function. These copies should track the
1646  * versions in gxcmap.c.
1647  **/
1648 
1649 private	cmap_proc_gray(pdf14_cmap_gray_direct);
1650 private	cmap_proc_rgb(pdf14_cmap_rgb_direct);
1651 private	cmap_proc_cmyk(pdf14_cmap_cmyk_direct);
1652 private	cmap_proc_rgb_alpha(pdf14_cmap_rgb_alpha_direct);
1653 private	cmap_proc_separation(pdf14_cmap_separation_direct);
1654 private	cmap_proc_devicen(pdf14_cmap_devicen_direct);
1655 private	cmap_proc_is_halftoned(pdf14_cmap_is_halftoned);
1656 
1657 private	const gx_color_map_procs pdf14_cmap_many = {
1658      pdf14_cmap_gray_direct,
1659      pdf14_cmap_rgb_direct,
1660      pdf14_cmap_cmyk_direct,
1661      pdf14_cmap_rgb_alpha_direct,
1662      pdf14_cmap_separation_direct,
1663      pdf14_cmap_devicen_direct,
1664      pdf14_cmap_is_halftoned
1665     };
1666 
1667 /**
1668  * Note: copied from gxcmap.c because it's inlined.
1669  **/
1670 private	inline void
map_components_to_colorants(const frac * pcc,const gs_devicen_color_map * pcolor_component_map,frac * plist)1671 map_components_to_colorants(const frac * pcc,
1672 	const gs_devicen_color_map * pcolor_component_map, frac * plist)
1673 {
1674     int i = pcolor_component_map->num_colorants - 1;
1675     int pos;
1676 
1677     /* Clear all output colorants first */
1678     for (; i >= 0; i--) {
1679 	plist[i] = frac_0;
1680     }
1681 
1682     /* Map color components into output list */
1683     for (i = pcolor_component_map->num_components - 1; i >= 0; i--) {
1684 	pos = pcolor_component_map->color_map[i];
1685 	if (pos >= 0)
1686 	    plist[pos] = pcc[i];
1687     }
1688 }
1689 
1690 private	void
pdf14_cmap_gray_direct(frac gray,gx_device_color * pdc,const gs_imager_state * pis,gx_device * dev,gs_color_select_t select)1691 pdf14_cmap_gray_direct(frac gray, gx_device_color * pdc, const gs_imager_state * pis,
1692 		 gx_device * dev, gs_color_select_t select)
1693 {
1694     int i, ncomps = dev->color_info.num_components;
1695     frac cm_comps[GX_DEVICE_COLOR_MAX_COMPONENTS];
1696     gx_color_value cv[GX_DEVICE_COLOR_MAX_COMPONENTS];
1697     gx_color_index color;
1698 
1699     /* map to the color model */
1700     dev_proc(dev, get_color_mapping_procs)(dev)->map_gray(dev, gray, cm_comps);
1701 
1702     for (i = 0; i < ncomps; i++)
1703 	cv[i] = frac2cv(cm_comps[i]);
1704 
1705     /* encode as a color index */
1706     color = dev_proc(dev, encode_color)(dev, cv);
1707 
1708     /* check if the encoding was successful; we presume failure is rare */
1709     if (color != gx_no_color_index)
1710 	color_set_pure(pdc, color);
1711 }
1712 
1713 
1714 private	void
pdf14_cmap_rgb_direct(frac r,frac g,frac b,gx_device_color * pdc,const gs_imager_state * pis,gx_device * dev,gs_color_select_t select)1715 pdf14_cmap_rgb_direct(frac r, frac g, frac b, gx_device_color *	pdc,
1716      const gs_imager_state * pis, gx_device * dev, gs_color_select_t select)
1717 {
1718     int i, ncomps = dev->color_info.num_components;
1719     frac cm_comps[GX_DEVICE_COLOR_MAX_COMPONENTS];
1720     gx_color_value cv[GX_DEVICE_COLOR_MAX_COMPONENTS];
1721     gx_color_index color;
1722 
1723     /* map to the color model */
1724     dev_proc(dev, get_color_mapping_procs)(dev)->map_rgb(dev, pis, r, g, b, cm_comps);
1725 
1726     for (i = 0; i < ncomps; i++)
1727 	cv[i] = frac2cv(cm_comps[i]);
1728 
1729     /* encode as a color index */
1730     color = dev_proc(dev, encode_color)(dev, cv);
1731 
1732     /* check if the encoding was successful; we presume failure is rare */
1733     if (color != gx_no_color_index)
1734 	color_set_pure(pdc, color);
1735 }
1736 
1737 private	void
pdf14_cmap_cmyk_direct(frac c,frac m,frac y,frac k,gx_device_color * pdc,const gs_imager_state * pis,gx_device * dev,gs_color_select_t select)1738 pdf14_cmap_cmyk_direct(frac c, frac m, frac y, frac k, gx_device_color * pdc,
1739      const gs_imager_state * pis, gx_device * dev, gs_color_select_t select)
1740 {
1741     int i, ncomps = dev->color_info.num_components;
1742     frac cm_comps[GX_DEVICE_COLOR_MAX_COMPONENTS];
1743     gx_color_value cv[GX_DEVICE_COLOR_MAX_COMPONENTS];
1744     gx_color_index color;
1745 
1746     /* map to the color model */
1747     dev_proc(dev, get_color_mapping_procs)(dev)->map_cmyk(dev, c, m, y, k, cm_comps);
1748 
1749     for (i = 0; i < ncomps; i++)
1750 	cv[i] = frac2cv(cm_comps[i]);
1751 
1752     color = dev_proc(dev, encode_color)(dev, cv);
1753     if (color != gx_no_color_index)
1754 	color_set_pure(pdc, color);
1755 }
1756 
1757 private	void
pdf14_cmap_rgb_alpha_direct(frac r,frac g,frac b,frac alpha,gx_device_color * pdc,const gs_imager_state * pis,gx_device * dev,gs_color_select_t select)1758 pdf14_cmap_rgb_alpha_direct(frac r, frac g, frac b, frac alpha,	gx_device_color	* pdc,
1759      const gs_imager_state * pis, gx_device * dev, gs_color_select_t select)
1760 {
1761     int i, ncomps = dev->color_info.num_components;
1762     frac cm_comps[GX_DEVICE_COLOR_MAX_COMPONENTS];
1763     gx_color_value cv_alpha, cv[GX_DEVICE_COLOR_MAX_COMPONENTS];
1764     gx_color_index color;
1765 
1766     /* map to the color model */
1767     dev_proc(dev, get_color_mapping_procs)(dev)->map_rgb(dev, pis, r, g, b, cm_comps);
1768 
1769     /* pre-multiply to account for the alpha weighting */
1770     if (alpha != frac_1) {
1771 #ifdef PREMULTIPLY_TOWARDS_WHITE
1772 	frac alpha_bias = frac_1 - alpha;
1773 #else
1774 	frac alpha_bias = 0;
1775 #endif
1776 
1777 	for (i = 0; i < ncomps; i++)
1778 	    cm_comps[i] = (frac)((long)cm_comps[i] * alpha) / frac_1 + alpha_bias;
1779     }
1780 
1781     for (i = 0; i < ncomps; i++)
1782 	cv[i] = frac2cv(cm_comps[i]);
1783 
1784     /* encode as a color index */
1785     if (dev_proc(dev, map_rgb_alpha_color) != gx_default_map_rgb_alpha_color &&
1786 	 (cv_alpha = frac2cv(alpha)) != gx_max_color_value)
1787 	color = dev_proc(dev, map_rgb_alpha_color)(dev, cv[0], cv[1], cv[2], cv_alpha);
1788     else
1789 	color = dev_proc(dev, encode_color)(dev, cv);
1790 
1791     /* check if the encoding was successful; we presume failure is rare */
1792     if (color != gx_no_color_index)
1793 	color_set_pure(pdc, color);
1794 }
1795 
1796 
1797 private	void
pdf14_cmap_separation_direct(frac all,gx_device_color * pdc,const gs_imager_state * pis,gx_device * dev,gs_color_select_t select)1798 pdf14_cmap_separation_direct(frac all, gx_device_color * pdc, const gs_imager_state * pis,
1799 		 gx_device * dev, gs_color_select_t select)
1800 {
1801     int i, ncomps = dev->color_info.num_components;
1802     bool additive = dev->color_info.polarity == GX_CINFO_POLARITY_ADDITIVE;
1803     frac comp_value = all;
1804     frac cm_comps[GX_DEVICE_COLOR_MAX_COMPONENTS];
1805     gx_color_value cv[GX_DEVICE_COLOR_MAX_COMPONENTS];
1806     gx_color_index color;
1807 
1808     if (pis->color_component_map.sep_type == SEP_ALL) {
1809 	/*
1810 	 * Invert the photometric interpretation for additive
1811 	 * color spaces because separations are always subtractive.
1812 	 */
1813 	if (additive)
1814 	    comp_value = frac_1 - comp_value;
1815 
1816 	/* Use the "all" value for all components */
1817 	i = pis->color_component_map.num_colorants - 1;
1818 	for (; i >= 0; i--)
1819 	    cm_comps[i] = comp_value;
1820     }
1821     else {
1822 	/* map to the color model */
1823 	map_components_to_colorants(&comp_value, &(pis->color_component_map), cm_comps);
1824     }
1825 
1826     /* apply the transfer function(s); convert to color values */
1827     if (additive)
1828 	for (i = 0; i < ncomps; i++)
1829 	    cv[i] = frac2cv(gx_map_color_frac(pis,
1830 				cm_comps[i], effective_transfer[i]));
1831     else
1832 	for (i = 0; i < ncomps; i++)
1833 	    cv[i] = frac2cv(frac_1 - gx_map_color_frac(pis,
1834 			(frac)(frac_1 - cm_comps[i]), effective_transfer[i]));
1835 
1836     /* encode as a color index */
1837     color = dev_proc(dev, encode_color)(dev, cv);
1838 
1839     /* check if the encoding was successful; we presume failure is rare */
1840     if (color != gx_no_color_index)
1841 	color_set_pure(pdc, color);
1842 }
1843 
1844 
1845 private	void
pdf14_cmap_devicen_direct(const frac * pcc,gx_device_color * pdc,const gs_imager_state * pis,gx_device * dev,gs_color_select_t select)1846 pdf14_cmap_devicen_direct(const	frac * pcc,
1847     gx_device_color * pdc, const gs_imager_state * pis, gx_device * dev,
1848     gs_color_select_t select)
1849 {
1850     int i, ncomps = dev->color_info.num_components;
1851     frac cm_comps[GX_DEVICE_COLOR_MAX_COMPONENTS];
1852     gx_color_value cv[GX_DEVICE_COLOR_MAX_COMPONENTS];
1853     gx_color_index color;
1854 
1855     /* map to the color model */
1856     map_components_to_colorants(pcc, &(pis->color_component_map), cm_comps);;
1857 
1858     /* apply the transfer function(s); convert to color values */
1859     if (dev->color_info.polarity == GX_CINFO_POLARITY_ADDITIVE)
1860 	for (i = 0; i < ncomps; i++)
1861 	    cv[i] = frac2cv(gx_map_color_frac(pis,
1862 				cm_comps[i], effective_transfer[i]));
1863     else
1864 	for (i = 0; i < ncomps; i++)
1865 	    cv[i] = frac2cv(frac_1 - gx_map_color_frac(pis,
1866 			(frac)(frac_1 - cm_comps[i]), effective_transfer[i]));
1867 
1868     /* encode as a color index */
1869     color = dev_proc(dev, encode_color)(dev, cv);
1870 
1871     /* check if the encoding was successful; we presume failure is rare */
1872     if (color != gx_no_color_index)
1873 	color_set_pure(pdc, color);
1874 }
1875 
1876 private	bool
pdf14_cmap_is_halftoned(const gs_imager_state * pis,gx_device * dev)1877 pdf14_cmap_is_halftoned(const gs_imager_state *	pis, gx_device * dev)
1878 {
1879     return false;
1880 }
1881 
1882 private	const gx_color_map_procs *
pdf14_get_cmap_procs(const gs_imager_state * pis,const gx_device * dev)1883 pdf14_get_cmap_procs(const gs_imager_state *pis, const gx_device * dev)
1884 {
1885     /* The pdf14 marking device itself is always continuous tone. */
1886     return &pdf14_cmap_many;
1887 }
1888 
1889 
1890 int
gs_pdf14_device_push(gs_memory_t * mem,gs_imager_state * pis,gx_device ** pdev,gx_device * target)1891 gs_pdf14_device_push(gs_memory_t *mem, gs_imager_state * pis,
1892 				gx_device ** pdev, gx_device * target)
1893 {
1894     const pdf14_device * dev_proto;
1895     pdf14_device *p14dev;
1896     int code;
1897 
1898     if_debug0('v', "[v]gs_pdf14_device_push\n");
1899 
1900     code = get_pdf14_device_proto(target, &dev_proto);
1901     if (code < 0)
1902 	return code;
1903     code = gs_copydevice((gx_device **) &p14dev,
1904 			 (const gx_device *) dev_proto, mem);
1905     if (code < 0)
1906 	return code;
1907 
1908     check_device_separable((gx_device *)p14dev);
1909     gx_device_fill_in_procs((gx_device *)p14dev);
1910 
1911     gs_pdf14_device_copy_params((gx_device *)p14dev, target);
1912 
1913     rc_assign(p14dev->target, target, "gs_pdf14_device_push");
1914 
1915     p14dev->save_get_cmap_procs = pis->get_cmap_procs;
1916     pis->get_cmap_procs = pdf14_get_cmap_procs;
1917     gx_set_cmap_procs(pis, (gx_device *)p14dev);
1918 
1919     code = dev_proc((gx_device *) p14dev, open_device) ((gx_device *) p14dev);
1920     *pdev = (gx_device *) p14dev;
1921     pdf14_set_marking_params((gx_device *)p14dev, pis);
1922     return code;
1923 }
1924 
1925 /*
1926  * In a modest violation of good coding practice, the gs_composite_common
1927  * fields are "known" to be simple (contain no pointers to garbage
1928  * collected memory), and we also know the gs_pdf14trans_params_t structure
1929  * to be simple, so we just create a trivial structure descriptor for the
1930  * entire gs_pdf14trans_s structure.
1931  */
1932 #define	private_st_gs_pdf14trans_t()\
1933   gs_private_st_ptrs1(st_pdf14trans, gs_pdf14trans_t, "gs_pdf14trans_t",\
1934       st_pdf14trans_enum_ptrs, st_pdf14trans_reloc_ptrs, params.transfer_function)
1935 
1936 /* GC descriptor for gs_pdf14trans_t */
1937 private_st_gs_pdf14trans_t();
1938 
1939 /*
1940  * Check for equality of two PDF 1.4 transparency compositor objects.
1941  *
1942  * We are currently always indicating that PDF 1.4 transparency compositors are
1943  * equal.  Two transparency compositors may have teh same data but still
1944  * represent separate actions.  (E.g. two PDF14_BEGIN_TRANS_GROUP compositor
1945  * operations in a row mean that we are creating a group inside of a group.
1946  */
1947 private	bool
c_pdf14trans_equal(const gs_composite_t * pct0,const gs_composite_t * pct1)1948 c_pdf14trans_equal(const gs_composite_t	* pct0,	const gs_composite_t * pct1)
1949 {
1950     return false;
1951 }
1952 
1953 #ifdef DEBUG
1954 static char * pdf14_opcode_names[] = PDF14_OPCODE_NAMES;
1955 #endif
1956 
1957 #define	put_value(dp, value)\
1958     memcpy(dp, &value, sizeof(value));\
1959     dp += sizeof(value)
1960 
1961 /*
1962  * Convert a PDF 1.4 transparency compositor to string form for use by the command
1963  * list device.
1964  */
1965 private	int
c_pdf14trans_write(const gs_composite_t * pct,byte * data,uint * psize)1966 c_pdf14trans_write(const gs_composite_t	* pct, byte * data, uint * psize)
1967 {
1968     const gs_pdf14trans_params_t * pparams = &((const gs_pdf14trans_t *)pct)->params;
1969     int need, avail = *psize;
1970 	/* Must be large enough for largest data struct */
1971     byte buf[21 + sizeof(pparams->Background)
1972 		+ sizeof(pparams->GrayBackground) + sizeof(pparams->bbox)];
1973     byte * pbuf = buf;
1974     int opcode = pparams->pdf14_op;
1975     int mask_size = 0;
1976 
1977     /* Write PDF 1.4 compositor data into the clist */
1978 
1979     *pbuf++ = opcode;			/* 1 byte */
1980     switch (opcode) {
1981 	default:			/* Should not occur. */
1982 	    break;
1983 	case PDF14_PUSH_DEVICE:
1984 	case PDF14_POP_DEVICE:
1985 	case PDF14_END_TRANS_GROUP:
1986 	case PDF14_END_TRANS_MASK:
1987 	    break;			/* No data */
1988 	case PDF14_BEGIN_TRANS_GROUP:
1989 	    /*
1990 	     * The bbox data is floating point.  We are not currently using it.
1991 	     * So we are not currently putting it into the clist.  We are also
1992 	     * not using the color space.
1993 	     */
1994 	    *pbuf++ = (pparams->Isolated & 1) + ((pparams->Knockout & 1) << 1);
1995 	    *pbuf++ = pparams->blend_mode;
1996 	    put_value(pbuf, pparams->opacity.alpha);
1997 	    put_value(pbuf, pparams->shape.alpha);
1998 	    put_value(pbuf, pparams->bbox);
1999 	    break;
2000 	case PDF14_INIT_TRANS_MASK:
2001 	    *pbuf++ = pparams->csel;
2002 	    break;
2003 	case PDF14_BEGIN_TRANS_MASK:
2004 	    put_value(pbuf, pparams->subtype);
2005 	    *pbuf++ = pparams->function_is_identity;
2006 	    *pbuf++ = pparams->Background_components;
2007 	    if (pparams->Background_components) {
2008 		const int l = sizeof(pparams->Background[0]) * pparams->Background_components;
2009 
2010 		memcpy(pbuf, pparams->Background, l);
2011 		pbuf += l;
2012 		memcpy(pbuf, &pparams->GrayBackground, sizeof(pparams->GrayBackground));
2013 		pbuf += sizeof(pparams->GrayBackground);
2014 	    }
2015 	    if (!pparams->function_is_identity)
2016 		mask_size = sizeof(pparams->transfer_fn);
2017 	    break;
2018 	case PDF14_SET_BLEND_PARAMS:
2019 	    *pbuf++ = pparams->changed;
2020 	    if (pparams->changed & PDF14_SET_BLEND_MODE)
2021 		*pbuf++ = pparams->blend_mode;
2022 	    if (pparams->changed & PDF14_SET_TEXT_KNOCKOUT)
2023 		*pbuf++ = pparams->text_knockout;
2024 	    if (pparams->changed & PDF14_SET_OPACITY_ALPHA)
2025 		put_value(pbuf, pparams->opacity.alpha);
2026 	    if (pparams->changed & PDF14_SET_SHAPE_ALPHA)
2027 		put_value(pbuf, pparams->shape.alpha);
2028 	    break;
2029     }
2030 #undef put_value
2031 
2032     /* check for fit */
2033     need = (pbuf - buf) + mask_size;
2034     *psize = need;
2035     if (need > avail)
2036 	return_error(gs_error_rangecheck);
2037     /* Copy our serialzed data into the output buffer */
2038     memcpy(data, buf, need - mask_size);
2039     if (mask_size)	/* Include the transfer mask data if present */
2040 	memcpy(data + need - mask_size, pparams->transfer_fn, mask_size);
2041     if_debug2('v', "[v] c_pdf14trans_write: opcode = %s need = %d\n",
2042 				pdf14_opcode_names[opcode], need);
2043     return 0;
2044 }
2045 
2046 /* Function prototypes */
2047 int gs_create_pdf14trans( gs_composite_t ** ppct,
2048 		const gs_pdf14trans_params_t * pparams,
2049 		gs_memory_t * mem );
2050 
2051 #define	read_value(dp, value)\
2052     memcpy(&value, dp, sizeof(value));\
2053     dp += sizeof(value)
2054 
2055 /*
2056  * Convert the string representation of the PDF 1.4 tranparency  parameter
2057  * into the full compositor.
2058  */
2059 private	int
c_pdf14trans_read(gs_composite_t ** ppct,const byte * data,uint size,gs_memory_t * mem)2060 c_pdf14trans_read(gs_composite_t * * ppct, const byte *	data,
2061 				uint size, gs_memory_t * mem )
2062 {
2063     gs_pdf14trans_params_t params = {0};
2064     const byte * start = data;
2065     int used, code = 0;
2066 
2067     if (size < 1)
2068 	return_error(gs_error_rangecheck);
2069 
2070     /* Read PDF 1.4 compositor data from the clist */
2071     params.pdf14_op = *data++;
2072     if_debug2('v', "[v] c_pdf14trans_read: opcode = %s  avail = %d",
2073 				pdf14_opcode_names[params.pdf14_op], size);
2074     switch (params.pdf14_op) {
2075 	default:			/* Should not occur. */
2076 	    break;
2077 	case PDF14_PUSH_DEVICE:
2078 	case PDF14_POP_DEVICE:
2079 	case PDF14_END_TRANS_GROUP:
2080 	    break;			/* No data */
2081 	case PDF14_BEGIN_TRANS_GROUP:
2082 	    /*
2083 	     * We are currently not using the bbox or the colorspace so they were
2084 	     * not placed in the clist
2085 	     */
2086 	    params.Isolated = (*data) & 1;
2087 	    params.Knockout = (*data++ >> 1) & 1;
2088 	    params.blend_mode = *data++;
2089 	    read_value(data, params.opacity.alpha);
2090 	    read_value(data, params.shape.alpha);
2091 	    read_value(data, params.bbox);
2092 	    break;
2093 	case PDF14_INIT_TRANS_MASK:
2094 	    params.csel = *data++;
2095 	    break;
2096 	case PDF14_BEGIN_TRANS_MASK:
2097 	    read_value(data, params.subtype);
2098 	    params.function_is_identity = *data++;
2099 	    params.Background_components = *data++;
2100 	    if (params.Background_components) {
2101 		const int l = sizeof(params.Background[0]) * params.Background_components;
2102 
2103 		memcpy(params.Background, data, l);
2104 		data += l;
2105 		memcpy(&params.GrayBackground, data, sizeof(params.GrayBackground));
2106 		data += sizeof(params.GrayBackground);
2107 	    }
2108 	    if (params.function_is_identity) {
2109 		int i;
2110 
2111 		for (i = 0; i < MASK_TRANSFER_FUNCTION_SIZE; i++) {
2112 		    params.transfer_fn[i] = (byte)floor(i *
2113 			(255.0 / (MASK_TRANSFER_FUNCTION_SIZE - 1)) + 0.5);
2114 		}
2115 	    } else {
2116 		read_value(data, params.transfer_fn);
2117 	    }
2118 	    break;
2119 	case PDF14_END_TRANS_MASK:
2120 	    break;			/* No data */
2121 	case PDF14_SET_BLEND_PARAMS:
2122 	    params.changed = *data++;
2123 	    if (params.changed & PDF14_SET_BLEND_MODE)
2124 		params.blend_mode = *data++;
2125 	    if (params.changed & PDF14_SET_TEXT_KNOCKOUT)
2126 		params.text_knockout = *data++;
2127 	    if (params.changed & PDF14_SET_OPACITY_ALPHA)
2128 		read_value(data, params.opacity.alpha);
2129 	    if (params.changed & PDF14_SET_SHAPE_ALPHA)
2130 		read_value(data, params.shape.alpha);
2131 	    break;
2132     }
2133     code = gs_create_pdf14trans(ppct, &params, mem);
2134     if (code < 0)
2135 	return code;
2136     used = data - start;
2137     if_debug1('v', "  used = %d\n", used);
2138     return used;
2139 }
2140 
2141 /*
2142  * Create a PDF 1.4 transparency compositor.
2143  *
2144  * Note that this routine will be called only if the device is not already
2145  * a PDF 1.4 transparency compositor.
2146  */
2147 private	int
c_pdf14trans_create_default_compositor(const gs_composite_t * pct,gx_device ** pp14dev,gx_device * tdev,gs_imager_state * pis,gs_memory_t * mem)2148 c_pdf14trans_create_default_compositor(const gs_composite_t * pct,
2149     gx_device ** pp14dev, gx_device * tdev, gs_imager_state * pis,
2150     gs_memory_t * mem)
2151 {
2152     const gs_pdf14trans_t * pdf14pct = (const gs_pdf14trans_t *) pct;
2153     gx_device * p14dev = NULL;
2154     int code = 0;
2155 
2156     /*
2157      * We only handle the push operation.  All other operations are ignored.
2158      */
2159     switch (pdf14pct->params.pdf14_op) {
2160 	case PDF14_PUSH_DEVICE:
2161 	    code = gs_pdf14_device_push(mem, pis, &p14dev, tdev);
2162 	    *pp14dev = p14dev;
2163 	    break;
2164 	default:
2165 	    *pp14dev = tdev;
2166 	    break;
2167     }
2168     return code;
2169 }
2170 
2171 private	composite_clist_write_update(c_pdf14trans_clist_write_update);
2172 private	composite_clist_read_update(c_pdf14trans_clist_read_update);
2173 
2174 /*
2175  * Methods for the PDF 1.4 transparency compositor
2176  *
2177  * Note:  We have two set of methods.  They are the same except for the
2178  * composite_clist_write_update method.  Once the clist write device is created,
2179  * we use the second set of procedures.  This prevents the creation of multiple
2180  * PDF 1.4 clist write compositor devices being chained together.
2181  */
2182 const gs_composite_type_t   gs_composite_pdf14trans_type = {
2183     GX_COMPOSITOR_PDF14_TRANS,
2184     {
2185 	c_pdf14trans_create_default_compositor, /* procs.create_default_compositor */
2186 	c_pdf14trans_equal,                      /* procs.equal */
2187 	c_pdf14trans_write,                      /* procs.write */
2188 	c_pdf14trans_read,                       /* procs.read */
2189 		/* Create a PDF 1.4 clist write device */
2190 	c_pdf14trans_clist_write_update,   /* procs.composite_clist_write_update */
2191 	c_pdf14trans_clist_read_update	   /* procs.composite_clist_reade_update */
2192     }                                            /* procs */
2193 };
2194 
2195 const gs_composite_type_t   gs_composite_pdf14trans_no_clist_writer_type = {
2196     GX_COMPOSITOR_PDF14_TRANS,
2197     {
2198 	c_pdf14trans_create_default_compositor, /* procs.create_default_compositor */
2199 	c_pdf14trans_equal,                      /* procs.equal */
2200 	c_pdf14trans_write,                      /* procs.write */
2201 	c_pdf14trans_read,                       /* procs.read */
2202 		/* The PDF 1.4 clist writer already exists, Do not create it. */
2203 	gx_default_composite_clist_write_update, /* procs.composite_clist_write_update */
2204 	c_pdf14trans_clist_read_update	   /* procs.composite_clist_reade_update */
2205     }                                            /* procs */
2206 };
2207 
2208 /*
2209  * Verify that a compositor data structure is for the PDF 1.4 compositor.
2210  */
2211 int
gs_is_pdf14trans_compositor(const gs_composite_t * pct)2212 gs_is_pdf14trans_compositor(const gs_composite_t * pct)
2213 {
2214     return (pct->type == &gs_composite_pdf14trans_type
2215 		|| pct->type == &gs_composite_pdf14trans_no_clist_writer_type);
2216 }
2217 
2218 /*
2219  * Create a PDF 1.4 transparency compositor data structure.
2220  */
2221 int
gs_create_pdf14trans(gs_composite_t ** ppct,const gs_pdf14trans_params_t * pparams,gs_memory_t * mem)2222 gs_create_pdf14trans(
2223     gs_composite_t **               ppct,
2224     const gs_pdf14trans_params_t *  pparams,
2225     gs_memory_t *                   mem )
2226 {
2227     gs_pdf14trans_t *                pct;
2228 
2229     rc_alloc_struct_0( pct,
2230 		       gs_pdf14trans_t,
2231 		       &st_pdf14trans,
2232 		       mem,
2233 		       return_error(gs_error_VMerror),
2234 		       "gs_create_pdf14trans" );
2235     pct->type = &gs_composite_pdf14trans_type;
2236     pct->id = gs_next_ids(mem, 1);
2237     pct->params = *pparams;
2238     *ppct = (gs_composite_t *)pct;
2239     return 0;
2240 }
2241 
2242 /*
2243  * Send a PDF 1.4 transparency compositor action to the specified device.
2244  */
2245 int
send_pdf14trans(gs_imager_state * pis,gx_device * dev,gx_device ** pcdev,gs_pdf14trans_params_t * pparams,gs_memory_t * mem)2246 send_pdf14trans(gs_imager_state	* pis, gx_device * dev,
2247     gx_device * * pcdev, gs_pdf14trans_params_t * pparams, gs_memory_t * mem)
2248 {
2249     gs_composite_t * pct = NULL;
2250     int code;
2251 
2252     code = gs_create_pdf14trans(&pct, pparams, mem);
2253     if (code < 0)
2254 	return code;
2255     code = dev_proc(dev, create_compositor) (dev, pcdev, pct, pis, mem);
2256 
2257     gs_free_object(pis->memory, pct, "send_pdf14trans");
2258 
2259     return code;
2260 }
2261 
2262 /* ------------- PDF 1.4 transparency device for clist writing ------------- */
2263 
2264 /*
2265  * The PDF 1.4 transparency compositor device may have a different process
2266  * color model than the output device.  If we are banding then we need to
2267  * create two compositor devices.  The output side (clist reader) needs a
2268  * compositor to actually composite the output.  We also need a compositor
2269  * device before the clist writer.  This is needed to provide a process color
2270  * model which matches the PDF 1.4 blending space.
2271  *
2272  * This section provides support for this device.
2273  */
2274 
2275 /* Define the default alpha-compositing	device.	*/
2276 typedef	struct pdf14_clist_device_s {
2277     gx_device_forward_common;
2278     const gx_color_map_procs *(*save_get_cmap_procs)(const gs_imager_state *,
2279 						     const gx_device *);
2280     gx_device_color_info saved_target_color_info;
2281     float opacity;
2282     float shape;
2283     gs_blend_mode_t blend_mode;
2284     bool text_knockout;
2285 } pdf14_clist_device;
2286 
2287 gs_private_st_suffix_add0_final(st_pdf14_clist_device,
2288     pdf14_clist_device, "pdf14_clist_device",
2289     device_c_pdf14_clist_enum_ptrs, device_c_pdf14_clist_reloc_ptrs,
2290     gx_device_finalize, st_device_forward);
2291 
2292 #define	pdf14_clist_procs(get_color_mapping_procs, get_color_comp_index,\
2293 						encode_color, decode_color) \
2294 {\
2295 	NULL,				/* open */\
2296 	gx_forward_get_initial_matrix,	/* get_initial_matrix */\
2297 	gx_forward_sync_output,		/* sync_output */\
2298 	gx_forward_output_page,		/* output_page */\
2299 	gx_forward_close_device,	/* close_device */\
2300 	encode_color,			/* rgb_map_rgb_color */\
2301 	decode_color,			/* map_color_rgb */\
2302 	gx_forward_fill_rectangle,	/* fill_rectangle */\
2303 	gx_forward_tile_rectangle,	/* tile_rectangle */\
2304 	gx_forward_copy_mono,		/* copy_mono */\
2305 	gx_forward_copy_color,		/* copy_color */\
2306 	NULL		,		/* draw_line - obsolete */\
2307 	gx_forward_get_bits,		/* get_bits */\
2308 	gx_forward_get_params,		/* get_params */\
2309 	pdf14_put_params,		/* put_params */\
2310 	encode_color,			/* map_cmyk_color */\
2311 	gx_forward_get_xfont_procs,	/* get_xfont_procs */\
2312 	gx_forward_get_xfont_device,	/* get_xfont_device */\
2313 	NULL,				/* map_rgb_alpha_color */\
2314 	gx_forward_get_page_device,	/* get_page_device */\
2315 	gx_forward_get_alpha_bits,	/* get_alpha_bits */\
2316 	NULL,				/* copy_alpha */\
2317 	gx_forward_get_band,		/* get_band */\
2318 	gx_forward_copy_rop,		/* copy_rop */\
2319 	pdf14_clist_fill_path,		/* fill_path */\
2320 	pdf14_clist_stroke_path,		/* stroke_path */\
2321 	gx_forward_fill_mask,		/* fill_mask */\
2322 	gx_forward_fill_trapezoid,	/* fill_trapezoid */\
2323 	gx_forward_fill_parallelogram,	/* fill_parallelogram */\
2324 	gx_forward_fill_triangle,	/* fill_triangle */\
2325 	gx_forward_draw_thin_line,	/* draw_thin_line */\
2326 	pdf14_clist_begin_image,	/* begin_image */\
2327 	gx_forward_image_data,		/* image_data */\
2328 	gx_forward_end_image,		/* end_image */\
2329 	gx_forward_strip_tile_rectangle, /* strip_tile_rectangle */\
2330 	gx_forward_strip_copy_rop,	/* strip_copy_rop, */\
2331 	gx_forward_get_clipping_box,	/* get_clipping_box */\
2332 	pdf14_clist_begin_typed_image,	/* begin_typed_image */\
2333 	gx_forward_get_bits_rectangle,	/* get_bits_rectangle */\
2334 	NULL,				/* map_color_rgb_alpha */\
2335 	pdf14_clist_create_compositor,	/* create_compositor */\
2336 	gx_forward_get_hardware_params,	/* get_hardware_params */\
2337 	pdf14_clist_text_begin,		/* text_begin */\
2338 	NULL,				/* finish_copydevice */\
2339 	pdf14_begin_transparency_group,\
2340 	pdf14_end_transparency_group,\
2341 	pdf14_begin_transparency_mask,\
2342 	pdf14_end_transparency_mask,\
2343 	NULL,				/* discard_transparency_layer */\
2344 	get_color_mapping_procs,	/* get_color_mapping_procs */\
2345 	get_color_comp_index,		/* get_color_comp_index */\
2346 	encode_color,			/* encode_color */\
2347 	decode_color			/* decode_color */\
2348 }
2349 
2350 private	dev_proc_create_compositor(pdf14_clist_create_compositor);
2351 private	dev_proc_create_compositor(pdf14_clist_forward_create_compositor);
2352 private	dev_proc_fill_path(pdf14_clist_fill_path);
2353 private	dev_proc_stroke_path(pdf14_clist_stroke_path);
2354 private	dev_proc_text_begin(pdf14_clist_text_begin);
2355 private	dev_proc_begin_image(pdf14_clist_begin_image);
2356 private	dev_proc_begin_typed_image(pdf14_clist_begin_typed_image);
2357 
2358 private	const gx_device_procs pdf14_clist_Gray_procs =
2359 	pdf14_clist_procs(gx_default_DevGray_get_color_mapping_procs,
2360 			gx_default_DevGray_get_color_comp_index,
2361 			gx_default_8bit_map_gray_color,
2362 			gx_default_8bit_map_color_gray);
2363 
2364 private	const gx_device_procs pdf14_clist_RGB_procs =
2365 	pdf14_clist_procs(gx_default_DevRGB_get_color_mapping_procs,
2366 			gx_default_DevRGB_get_color_comp_index,
2367 			gx_default_rgb_map_rgb_color,
2368 			gx_default_rgb_map_color_rgb);
2369 
2370 private	const gx_device_procs pdf14_clist_CMYK_procs =
2371 	pdf14_clist_procs(gx_default_DevCMYK_get_color_mapping_procs,
2372 			gx_default_DevCMYK_get_color_comp_index,
2373 			cmyk_8bit_map_cmyk_color, cmyk_8bit_map_color_cmyk);
2374 
2375 const pdf14_clist_device pdf14_clist_Gray_device = {
2376     std_device_color_stype_body(pdf14_clist_device, &pdf14_clist_Gray_procs,
2377 			"pdf14clistgray", &st_pdf14_clist_device,
2378 			XSIZE, YSIZE, X_DPI, Y_DPI, 8, 255, 256),
2379     { 0 }
2380 };
2381 
2382 const pdf14_clist_device pdf14_clist_RGB_device	= {
2383     std_device_color_stype_body(pdf14_clist_device, &pdf14_clist_RGB_procs,
2384 			"pdf14clistRGB", &st_pdf14_clist_device,
2385 			XSIZE, YSIZE, X_DPI, Y_DPI, 24, 255, 256),
2386     { 0 }
2387 };
2388 
2389 const pdf14_clist_device pdf14_clist_CMYK_device = {
2390     std_device_std_color_full_body_type(pdf14_clist_device,
2391 			&pdf14_clist_CMYK_procs, "PDF14clistcmyk",
2392 			&st_pdf14_clist_device, XSIZE, YSIZE, X_DPI, Y_DPI, 32,
2393 			0, 0, 0, 0, 0, 0),
2394     { 0 }
2395 };
2396 
2397 /*
2398  * the PDF 1.4 transparency spec says that color space for blending
2399  * operations can be based upon either a color space specified in the
2400  * group or a default value based upon the output device.  We are
2401  * currently only using a color space based upon the device.
2402  */
2403 private	int
get_pdf14_clist_device_proto(gx_device * dev,const pdf14_clist_device ** pdevproto)2404 get_pdf14_clist_device_proto(gx_device * dev,
2405 		const pdf14_clist_device ** pdevproto)
2406 {
2407     pdf14_default_colorspace_t dev_cs =
2408 		pdf14_determine_default_blend_cs(dev);
2409 
2410     switch (dev_cs) {
2411 	case DeviceGray:
2412 	    *pdevproto = &pdf14_clist_Gray_device;
2413 	    break;
2414 	case DeviceRGB:
2415 	    *pdevproto = &pdf14_clist_RGB_device;
2416 	    break;
2417 	case DeviceCMYK:
2418 	    *pdevproto = &pdf14_clist_CMYK_device;
2419 	    break;
2420 	default:			/* Should not occur */
2421 	    return_error(gs_error_rangecheck);
2422     }
2423     return 0;
2424 }
2425 
2426 private	int
pdf14_create_clist_device(gs_memory_t * mem,gs_imager_state * pis,gx_device ** ppdev,gx_device * target)2427 pdf14_create_clist_device(gs_memory_t *mem, gs_imager_state * pis,
2428 				gx_device ** ppdev, gx_device * target)
2429 {
2430     const pdf14_clist_device * dev_proto;
2431     pdf14_clist_device *pdev;
2432     int code;
2433 
2434     if_debug0('v', "[v]pdf14_create_clist_device\n");
2435 
2436     code = get_pdf14_clist_device_proto(target, &dev_proto);
2437     if (code < 0)
2438 	return code;
2439 
2440     code = gs_copydevice((gx_device **) &pdev,
2441 			 (const gx_device *) dev_proto, mem);
2442     if (code < 0)
2443 	return code;
2444 
2445     check_device_separable((gx_device *)pdev);
2446     gx_device_fill_in_procs((gx_device *)pdev);
2447 
2448     gs_pdf14_device_copy_params((gx_device *)pdev, target);
2449 
2450     rc_assign(pdev->target, target, "pdf14_create_clist_device");
2451 
2452     code = dev_proc((gx_device *) pdev, open_device) ((gx_device *) pdev);
2453     *ppdev = (gx_device *) pdev;
2454     return code;
2455 }
2456 
2457 /*
2458  * Disable the PDF 1.4 clist compositor device.  Once created, the PDF 1.4
2459  * compositor device is never removed.  (We do not have a remove compositor
2460  * method.)  However it is no-op'ed when the PDF 1.4 device is popped.  This
2461  * routine implements that action.
2462  */
2463 private	int
pdf14_disable_clist_device(gs_memory_t * mem,gs_imager_state * pis,gx_device * dev)2464 pdf14_disable_clist_device(gs_memory_t *mem, gs_imager_state * pis,
2465 				gx_device * dev)
2466 {
2467     gx_device_forward * pdev = (gx_device_forward *)dev;
2468     gx_device * target = pdev->target;
2469 
2470     if_debug0('v', "[v]pdf14_disable_clist_device\n");
2471 
2472     /*
2473      * To disable the action of this device, we forward all device
2474      * procedures to the target except the create_compositor and copy
2475      * the target's color_info.
2476      */
2477     dev->color_info = target->color_info;
2478     pdf14_forward_device_procs(dev);
2479     set_dev_proc(dev, create_compositor, pdf14_clist_forward_create_compositor);
2480     return 0;
2481 }
2482 
2483 /*
2484  * Recreate the PDF 1.4 clist compositor device.  Once created, the PDF 1.4
2485  * compositor device is never removed.  (We do not have a remove compositor
2486  * method.)  However it is no-op'ed when the PDF 1.4 device is popped.  This
2487  * routine will re-enable the compositor if the PDF 1.4 device is pushed
2488  * again.
2489  */
2490 private	int
pdf14_recreate_clist_device(gs_memory_t * mem,gs_imager_state * pis,gx_device * dev)2491 pdf14_recreate_clist_device(gs_memory_t	*mem, gs_imager_state *	pis,
2492 				gx_device * dev)
2493 {
2494     pdf14_clist_device * pdev = (pdf14_clist_device *)dev;
2495     gx_device * target = pdev->target;
2496     const pdf14_clist_device * dev_proto;
2497     int code;
2498 
2499     if_debug0('v', "[v]pdf14_recreate_clist_device\n");
2500 
2501     /*
2502      * We will not use the entire prototype device but we will set the
2503      * color related info to match the prototype.
2504      */
2505     code = get_pdf14_clist_device_proto(target, &dev_proto);
2506     if (code < 0)
2507 	return code;
2508     pdev->color_info = dev_proto->color_info;
2509     pdev->procs = dev_proto->procs;
2510     gx_device_fill_in_procs(dev);
2511     check_device_separable((gx_device *)pdev);
2512 
2513     return code;
2514 }
2515 
2516 /*
2517  * When we are banding, we have two PDF 1.4 compositor devices.  One for
2518  * when we are creating the clist.  The second is for imaging the data from
2519  * the clist.  This routine is part of the clist writing PDF 1.4 device.
2520  * This routine is only called once the PDF 1.4 clist write compositor already
2521  * exists.
2522  */
2523 private	int
pdf14_clist_create_compositor(gx_device * dev,gx_device ** pcdev,const gs_composite_t * pct,gs_imager_state * pis,gs_memory_t * mem)2524 pdf14_clist_create_compositor(gx_device	* dev, gx_device ** pcdev,
2525     const gs_composite_t * pct, gs_imager_state * pis, gs_memory_t * mem)
2526 {
2527     pdf14_clist_device * pdev = (pdf14_clist_device *)dev;
2528     int code;
2529 
2530     /* We only handle a few PDF 1.4 transparency operations 4 */
2531     if (gs_is_pdf14trans_compositor(pct)) {
2532 	const gs_pdf14trans_t * pdf14pct = (const gs_pdf14trans_t *) pct;
2533 
2534 	switch (pdf14pct->params.pdf14_op) {
2535 	    case PDF14_PUSH_DEVICE:
2536 		/* Re-activate the PDF 1.4 compositor */
2537 		pdev->saved_target_color_info = pdev->target->color_info;
2538 		pdev->target->color_info = pdev->color_info;
2539 		pdev->save_get_cmap_procs = pis->get_cmap_procs;
2540 		pis->get_cmap_procs = pdf14_get_cmap_procs;
2541 		gx_set_cmap_procs(pis, dev);
2542 		code = pdf14_recreate_clist_device(mem, pis, dev);
2543 		pdev->blend_mode = pdev->text_knockout = 0;
2544 		pdev->opacity = pdev->shape = 0.0;
2545 		if (code < 0)
2546 		    return code;
2547 		/*
2548 		 * This routine is part of the PDF 1.4 clist write device.
2549 		 * Change the compositor procs to not create another since we
2550 		 * do not need to create a chain of identical devices.
2551 		 */
2552 		{
2553 		    gs_composite_t pctemp = *pct;
2554 
2555 		    pctemp.type = &gs_composite_pdf14trans_no_clist_writer_type;
2556 		    code = dev_proc(pdev->target, create_compositor)
2557 				(pdev->target, pcdev, &pctemp, pis, mem);
2558 		    *pcdev = dev;
2559 		    return code;
2560 		}
2561 	    case PDF14_POP_DEVICE:
2562 		/* Restore the color_info for the clist device */
2563 		pdev->target->color_info = pdev->saved_target_color_info;
2564 		pis->get_cmap_procs = pdev->save_get_cmap_procs;
2565 		gx_set_cmap_procs(pis, pdev->target);
2566 		/* Disable the PDF 1.4 compositor */
2567 		pdf14_disable_clist_device(mem, pis, dev);
2568 		/*
2569 		 * Make sure that the transfer funtions, etc. are current.
2570 		 */
2571 		code = cmd_put_color_mapping(
2572 			(gx_device_clist_writer *)(pdev->target), pis);
2573 		if (code < 0)
2574 		    return code;
2575 		break;
2576 	    case PDF14_BEGIN_TRANS_GROUP:
2577 		/*
2578 		 * Keep track of any changes made in the blending parameters.
2579 		 */
2580 		pdev->text_knockout = pdf14pct->params.Knockout;
2581 		pdev->blend_mode = pdf14pct->params.blend_mode;
2582 		pdev->opacity = pdf14pct->params.opacity.alpha;
2583 		pdev->shape = pdf14pct->params.shape.alpha;
2584 		{
2585 		    const gs_pdf14trans_params_t * pparams = &((const gs_pdf14trans_t *)pct)->params;
2586 
2587 		    if (pparams->Background_components != 0 &&
2588 			pparams->Background_components != pdev->color_info.num_components)
2589 			return_error(gs_error_rangecheck);
2590 		}
2591 		break;
2592 	    default:
2593 		break;		/* Pass remaining ops to target */
2594 	}
2595     }
2596     code = dev_proc(pdev->target, create_compositor)
2597 			(pdev->target, pcdev, pct, pis, mem);
2598     if (*pcdev != pdev->target)
2599 	rc_assign(pdev->target, *pcdev, "pdf14_clist_create_compositor");
2600     *pcdev = dev;
2601     return code;
2602 }
2603 
2604 /*
2605  * The PDF 1.4 clist compositor is never removed.  (We do not have a 'remove
2606  * compositor' method.  However the compositor is disabled when we are not
2607  * doing a page which uses PDF 1.4 transparency.  This routine is only active
2608  * when the PDF 1.4 compositor is 'disabled'.  It checks for reenabling the
2609  * PDF 1.4 compositor.  Otherwise it simply passes create compositor requests
2610  * to the targer.
2611  */
2612 private	int
pdf14_clist_forward_create_compositor(gx_device * dev,gx_device ** pcdev,const gs_composite_t * pct,gs_imager_state * pis,gs_memory_t * mem)2613 pdf14_clist_forward_create_compositor(gx_device	* dev, gx_device * * pcdev,
2614 	const gs_composite_t * pct, gs_imager_state * pis,
2615 	gs_memory_t * mem)
2616 {
2617     pdf14_device *pdev = (pdf14_device *)dev;
2618     gx_device * tdev = pdev->target;
2619     gx_device * ndev;
2620     int code = 0;
2621 
2622     *pcdev = dev;
2623     if (gs_is_pdf14trans_compositor(pct)) {
2624 	const gs_pdf14trans_t * pdf14pct = (const gs_pdf14trans_t *) pct;
2625 
2626 	if (pdf14pct->params.pdf14_op == PDF14_PUSH_DEVICE)
2627 	    return pdf14_clist_create_compositor(dev, &ndev, pct, pis, mem);
2628 	return 0;
2629     }
2630     code = dev_proc(tdev, create_compositor)(tdev, &ndev, pct, pis, mem);
2631     if (code < 0)
2632 	return code;
2633     pdev->target = ndev;
2634     return 0;
2635 }
2636 
2637 /*
2638  * If any of the PDF 1.4 transparency blending parameters have changed, we
2639  * need to send them to the PDF 1.4 compositor on the output side of the clist.
2640  */
2641 private	int
pdf14_clist_update_params(pdf14_clist_device * pdev,const gs_imager_state * pis)2642 pdf14_clist_update_params(pdf14_clist_device * pdev, const gs_imager_state * pis)
2643 {
2644     gs_pdf14trans_params_t params = { 0 };
2645     gx_device * pcdev;
2646     int changed = 0;
2647     int code = 0;
2648 
2649     params.pdf14_op = PDF14_SET_BLEND_PARAMS;
2650     if (pis->blend_mode != pdev->blend_mode) {
2651 	changed |= PDF14_SET_BLEND_MODE;
2652 	params.blend_mode = pdev->blend_mode = pis->blend_mode;
2653     }
2654     if (pis->text_knockout != pdev->text_knockout) {
2655 	changed |= PDF14_SET_TEXT_KNOCKOUT;
2656 	params.text_knockout = pdev->text_knockout = pis->text_knockout;
2657     }
2658     if (pis->shape.alpha != pdev->shape) {
2659 	changed |= PDF14_SET_SHAPE_ALPHA;
2660 	params.shape.alpha = pdev->shape = pis->shape.alpha;
2661     }
2662     if (pis->opacity.alpha != pdev->opacity) {
2663 	changed |= PDF14_SET_OPACITY_ALPHA;
2664 	params.opacity.alpha = pdev->opacity = pis->opacity.alpha;
2665     }
2666     /*
2667      * Put parameters into a compositor parameter and then call the
2668      * create_compositor.  This will pass the data through the clist
2669      * to the PDF 1.4 transparency output device.  Note:  This action
2670      * never creates a new PDF 1.4 compositor and it does not change
2671      * the imager state.
2672      */
2673     if (changed != 0) {
2674 	params.changed = changed;
2675 	code = send_pdf14trans((gs_imager_state *)pis, (gx_device *)pdev,
2676 					&pcdev, &params, pis->memory);
2677     }
2678     return code;
2679 }
2680 
2681 /*
2682  * fill_path routine for the PDF 1.4 transaprency compositor device for
2683  * writing the clist.
2684  */
2685 private	int
pdf14_clist_fill_path(gx_device * dev,const gs_imager_state * pis,gx_path * ppath,const gx_fill_params * params,const gx_drawing_color * pdcolor,const gx_clip_path * pcpath)2686 pdf14_clist_fill_path(gx_device	*dev, const gs_imager_state *pis,
2687 			   gx_path *ppath, const gx_fill_params *params,
2688 			   const gx_drawing_color *pdcolor,
2689 			   const gx_clip_path *pcpath)
2690 {
2691     pdf14_clist_device * pdev = (pdf14_clist_device *)dev;
2692     gs_imager_state new_is = *pis;
2693     int code;
2694 
2695     /*
2696      * Ensure that that the PDF 1.4 reading compositor will have the current
2697      * blending parameters.  This is needed since the fill_rectangle routines
2698      * do not have access to the imager state.  Thus we have to pass any
2699      * changes explictly.
2700      */
2701     code = pdf14_clist_update_params(pdev, pis);
2702     if (code < 0)
2703 	return code;
2704     /*
2705      * The blend operations are not idempotent.  Force non-idempotent
2706      * filling and stroking operations.
2707      */
2708     new_is.log_op |= lop_pdf14;
2709     return gx_default_fill_path(dev, &new_is, ppath, params, pdcolor, pcpath);
2710 }
2711 
2712 /*
2713  * stroke_path routine for the PDF 1.4 transaprency compositor device for
2714  * writing the clist.
2715  */
2716 private	int
pdf14_clist_stroke_path(gx_device * dev,const gs_imager_state * pis,gx_path * ppath,const gx_stroke_params * params,const gx_drawing_color * pdcolor,const gx_clip_path * pcpath)2717 pdf14_clist_stroke_path(gx_device *dev,	const gs_imager_state *pis,
2718 			     gx_path *ppath, const gx_stroke_params *params,
2719 			     const gx_drawing_color *pdcolor,
2720 			     const gx_clip_path *pcpath)
2721 {
2722     pdf14_clist_device * pdev = (pdf14_clist_device *)dev;
2723     gs_imager_state new_is = *pis;
2724     int code;
2725 
2726     /*
2727      * Ensure that that the PDF 1.4 reading compositor will have the current
2728      * blending parameters.  This is needed since the fill_rectangle routines
2729      * do not have access to the imager state.  Thus we have to pass any
2730      * changes explictly.
2731      */
2732     code = pdf14_clist_update_params(pdev, pis);
2733     if (code < 0)
2734 	return code;
2735     /*
2736      * The blend operations are not idempotent.  Force non-idempotent
2737      * filling and stroking operations.
2738      */
2739     new_is.log_op |= lop_pdf14;
2740     return gx_default_stroke_path(dev, &new_is, ppath, params, pdcolor, pcpath);
2741 }
2742 
2743 /*
2744  * text_begin routine for the PDF 1.4 transaprency compositor device for
2745  * writing the clist.
2746  */
2747 private	int
pdf14_clist_text_begin(gx_device * dev,gs_imager_state * pis,const gs_text_params_t * text,gs_font * font,gx_path * path,const gx_device_color * pdcolor,const gx_clip_path * pcpath,gs_memory_t * memory,gs_text_enum_t ** ppenum)2748 pdf14_clist_text_begin(gx_device * dev,	gs_imager_state	* pis,
2749 		 const gs_text_params_t * text, gs_font * font,
2750 		 gx_path * path, const gx_device_color * pdcolor,
2751 		 const gx_clip_path * pcpath, gs_memory_t * memory,
2752 		 gs_text_enum_t ** ppenum)
2753 {
2754     pdf14_clist_device * pdev = (pdf14_clist_device *)dev;
2755     gs_text_enum_t *penum;
2756     int code;
2757 
2758     /*
2759      * Ensure that that the PDF 1.4 reading compositor will have the current
2760      * blending parameters.  This is needed since the fill_rectangle routines
2761      * do not have access to the imager state.  Thus we have to pass any
2762      * changes explictly.
2763      */
2764     code = pdf14_clist_update_params(pdev, pis);
2765     if (code < 0)
2766 	return code;
2767     /* Pass text_begin to the target */
2768     code = gx_default_text_begin(dev, pis, text, font, path,
2769 				pdcolor, pcpath, memory, &penum);
2770     if (code < 0)
2771 	return code;
2772     *ppenum = (gs_text_enum_t *)penum;
2773     return code;
2774 }
2775 
2776 private	int
pdf14_clist_begin_image(gx_device * dev,const gs_imager_state * pis,const gs_image_t * pim,gs_image_format_t format,const gs_int_rect * prect,const gx_drawing_color * pdcolor,const gx_clip_path * pcpath,gs_memory_t * memory,gx_image_enum_common_t ** pinfo)2777 pdf14_clist_begin_image(gx_device * dev,
2778 		       const gs_imager_state * pis, const gs_image_t * pim,
2779 		       gs_image_format_t format, const gs_int_rect * prect,
2780 		       const gx_drawing_color * pdcolor,
2781 		       const gx_clip_path * pcpath,
2782 		       gs_memory_t * memory, gx_image_enum_common_t ** pinfo)
2783 {
2784     pdf14_clist_device * pdev = (pdf14_clist_device *)dev;
2785     int code;
2786 
2787     /*
2788      * Ensure that that the PDF 1.4 reading compositor will have the current
2789      * blending parameters.  This is needed since the fill_rectangle routines
2790      * do not have access to the imager state.  Thus we have to pass any
2791      * changes explictly.
2792      */
2793     code = pdf14_clist_update_params(pdev, pis);
2794     if (code < 0)
2795 	return code;
2796     /* Pass image to the target */
2797     return gx_default_begin_image(dev, pis, pim, format, prect,
2798 					pdcolor, pcpath, memory, pinfo);
2799 }
2800 
2801 private	int
pdf14_clist_begin_typed_image(gx_device * dev,const gs_imager_state * pis,const gs_matrix * pmat,const gs_image_common_t * pic,const gs_int_rect * prect,const gx_drawing_color * pdcolor,const gx_clip_path * pcpath,gs_memory_t * mem,gx_image_enum_common_t ** pinfo)2802 pdf14_clist_begin_typed_image(gx_device	* dev, const gs_imager_state * pis,
2803 			   const gs_matrix *pmat, const gs_image_common_t *pic,
2804 			   const gs_int_rect * prect,
2805 			   const gx_drawing_color * pdcolor,
2806 			   const gx_clip_path * pcpath, gs_memory_t * mem,
2807 			   gx_image_enum_common_t ** pinfo)
2808 {
2809     pdf14_clist_device * pdev = (pdf14_clist_device *)dev;
2810     int code;
2811 
2812     /*
2813      * Ensure that that the PDF 1.4 reading compositor will have the current
2814      * blending parameters.  This is needed since the fill_rectangle routines
2815      * do not have access to the imager state.  Thus we have to pass any
2816      * changes explictly.
2817      */
2818     code = pdf14_clist_update_params(pdev, pis);
2819     if (code < 0)
2820 	return code;
2821     /* Pass image to the target */
2822     return gx_default_begin_typed_image(dev, pis, pmat,
2823 			    pic, prect, pdcolor, pcpath, mem, pinfo);
2824 }
2825 
2826 /*
2827  * When we push a PDF 1.4 transparency compositor onto the clist, we also need
2828  * to create a compositing device for clist writing.  The primary purpose of
2829  * this device is to provide support for the process color model in which
2830  * the PDF 1.4 transparency is done.  (This may differ from the process color
2831  * model of the output device.)  The actual work of compositing the image is
2832  * done on the output (reader) side of the clist.
2833  */
2834 private	int
c_pdf14trans_clist_write_update(const gs_composite_t * pcte,gx_device * dev,gx_device ** pcdev,gs_imager_state * pis,gs_memory_t * mem)2835 c_pdf14trans_clist_write_update(const gs_composite_t * pcte, gx_device * dev,
2836 		gx_device ** pcdev, gs_imager_state * pis, gs_memory_t * mem)
2837 {
2838     const gs_pdf14trans_t * pdf14pct = (const gs_pdf14trans_t *) pcte;
2839     pdf14_clist_device * p14dev;
2840     int code = 0;
2841 
2842     /* We only handle the push/pop operations */
2843     switch (pdf14pct->params.pdf14_op) {
2844 	case PDF14_PUSH_DEVICE:
2845 	    code = pdf14_create_clist_device(mem, pis, pcdev, dev);
2846 	    /*
2847 	     * Set the color_info of the clist device to match the compositing
2848 	     * device.  We will restore it when the compositor is popped.
2849 	     * See pdf14_clist_create_compositor for the restore.  Do the same
2850 	     * with the imager state's get_cmap_procs.  We do not want the
2851 	     * imager state to use transfer functions on our color values.  The
2852 	     * transfer functions will be applied at the end after we have done
2853 	     * our PDF 1.4 blend operations.
2854 	     */
2855 	    p14dev = (pdf14_clist_device *)(*pcdev);
2856 	    p14dev->saved_target_color_info = dev->color_info;
2857 	    dev->color_info = (*pcdev)->color_info;
2858 	    p14dev->save_get_cmap_procs = pis->get_cmap_procs;
2859 	    pis->get_cmap_procs = pdf14_get_cmap_procs;
2860 	    gx_set_cmap_procs(pis, dev);
2861 	    return code;
2862 	case PDF14_POP_DEVICE:
2863 	    /*
2864 	     * Ensure that the tranfer functions, etc.  are current before we
2865 	     * dump our transparency image to the output device.
2866 	     */
2867 	    code = cmd_put_halftone((gx_device_clist_writer *)
2868 			(((pdf14_clist_device *)dev)->target), pis->dev_ht);
2869 	    break;
2870 	default:
2871 	    break;		/* do nothing for remaining ops */
2872     }
2873     *pcdev = dev;
2874     return code;
2875 }
2876 
2877 /*
2878  * When we push a PDF 1.4 transparency compositor, we need to make the clist
2879  * device color_info data match the compositing device.  We need to do this
2880  * since the PDF 1.4 transparency compositing device may use a different
2881  * process color model than the output device.  We do not need to modify the
2882  * color related device procs since the compositing device has its own.  We
2883  * restore the color_info data when the transparency device is popped.
2884  */
2885 private	int
c_pdf14trans_clist_read_update(gs_composite_t * pcte,gx_device * cdev,gx_device * tdev,gs_imager_state * pis,gs_memory_t * mem)2886 c_pdf14trans_clist_read_update(gs_composite_t *	pcte, gx_device	* cdev,
2887 		gx_device * tdev, gs_imager_state * pis, gs_memory_t * mem)
2888 {
2889     pdf14_device * p14dev = (pdf14_device *)tdev;
2890     gs_pdf14trans_t * pdf14pct = (gs_pdf14trans_t *) pcte;
2891 
2892     /*
2893      * We only handle the push/pop operations. Save and restore the color_info
2894      * field for the clist device.  (This is needed since the process color
2895      * model of the clist device needs to match the PDF 1.4 compositing
2896      * device.
2897      */
2898     switch (pdf14pct->params.pdf14_op) {
2899 	case PDF14_PUSH_DEVICE:
2900 	    p14dev->saved_clist_color_info = cdev->color_info;
2901 	    cdev->color_info = p14dev->color_info;
2902 	    break;
2903 	case PDF14_POP_DEVICE:
2904 	    cdev->color_info = p14dev->saved_clist_color_info;
2905 	    break;
2906 	default:
2907 	    break;		/* do nothing for remaining ops */
2908     }
2909     return 0;
2910 }
2911