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