Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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
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
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 *
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
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 *
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
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 *
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 *
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
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
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
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
2060
c_pdf14trans_read(gs_composite_t * * ppct, const byte *	data,
2061
				uint size, gs_memory_t * mem )
2062
{
2063
    gs_pdf14trans_params_t params = {0};
2064
    const byte * start = data;
2065
    int used, code = 0;
2066
 
2067
    if (size < 1)
2068
	return_error(gs_error_rangecheck);
2069
 
2070
    /* Read PDF 1.4 compositor data from the clist */
2071
    params.pdf14_op = *data++;
2072
    if_debug2('v', "[v] c_pdf14trans_read: opcode = %s  avail = %d",
2073
				pdf14_opcode_names[params.pdf14_op], size);
2074
    switch (params.pdf14_op) {
2075
	default:			/* Should not occur. */
2076
	    break;
2077
	case PDF14_PUSH_DEVICE:
2078
	case PDF14_POP_DEVICE:
2079
	case PDF14_END_TRANS_GROUP:
2080
	    break;			/* No data */
2081
	case PDF14_BEGIN_TRANS_GROUP:
2082
	    /*
2083
	     * We are currently not using the bbox or the colorspace so they were
2084
	     * not placed in the clist
2085
	     */
2086
	    params.Isolated = (*data) & 1;
2087
	    params.Knockout = (*data++ >> 1) & 1;
2088
	    params.blend_mode = *data++;
2089
	    read_value(data, params.opacity.alpha);
2090
	    read_value(data, params.shape.alpha);
2091
	    read_value(data, params.bbox);
2092
	    break;
2093
	case PDF14_INIT_TRANS_MASK:
2094
	    params.csel = *data++;
2095
	    break;
2096
	case PDF14_BEGIN_TRANS_MASK:
2097
	    read_value(data, params.subtype);
2098
	    params.function_is_identity = *data++;
2099
	    params.Background_components = *data++;
2100
	    if (params.Background_components) {
2101
		const int l = sizeof(params.Background[0]) * params.Background_components;
2102
 
2103
		memcpy(params.Background, data, l);
2104
		data += l;
2105
		memcpy(&params.GrayBackground, data, sizeof(params.GrayBackground));
2106
		data += sizeof(params.GrayBackground);
2107
	    }
2108
	    if (params.function_is_identity) {
2109
		int i;
2110
 
2111
		for (i = 0; i < MASK_TRANSFER_FUNCTION_SIZE; i++) {
2112
		    params.transfer_fn[i] = (byte)floor(i *
2113
			(255.0 / (MASK_TRANSFER_FUNCTION_SIZE - 1)) + 0.5);
2114
		}
2115
	    } else {
2116
		read_value(data, params.transfer_fn);
2117
	    }
2118
	    break;
2119
	case PDF14_END_TRANS_MASK:
2120
	    break;			/* No data */
2121
	case PDF14_SET_BLEND_PARAMS:
2122
	    params.changed = *data++;
2123
	    if (params.changed & PDF14_SET_BLEND_MODE)
2124
		params.blend_mode = *data++;
2125
	    if (params.changed & PDF14_SET_TEXT_KNOCKOUT)
2126
		params.text_knockout = *data++;
2127
	    if (params.changed & PDF14_SET_OPACITY_ALPHA)
2128
		read_value(data, params.opacity.alpha);
2129
	    if (params.changed & PDF14_SET_SHAPE_ALPHA)
2130
		read_value(data, params.shape.alpha);
2131
	    break;
2132
    }
2133
    code = gs_create_pdf14trans(ppct, &params, mem);
2134
    if (code < 0)
2135
	return code;
2136
    used = data - start;
2137
    if_debug1('v', "  used = %d\n", used);
2138
    return used;
2139
}
2140
 
2141
/*
2142
 * Create a PDF 1.4 transparency compositor.
2143
 *
2144
 * Note that this routine will be called only if the device is not already
2145
 * a PDF 1.4 transparency compositor.
2146
 */
2147
private	int
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
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
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
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
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
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
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
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
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
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
2642
pdf14_clist_update_params(pdf14_clist_device * pdev, const gs_imager_state * pis)
2643
{
2644
    gs_pdf14trans_params_t params = { 0 };
2645
    gx_device * pcdev;
2646
    int changed = 0;
2647
    int code = 0;
2648
 
2649
    params.pdf14_op = PDF14_SET_BLEND_PARAMS;
2650
    if (pis->blend_mode != pdev->blend_mode) {
2651
	changed |= PDF14_SET_BLEND_MODE;
2652
	params.blend_mode = pdev->blend_mode = pis->blend_mode;
2653
    }
2654
    if (pis->text_knockout != pdev->text_knockout) {
2655
	changed |= PDF14_SET_TEXT_KNOCKOUT;
2656
	params.text_knockout = pdev->text_knockout = pis->text_knockout;
2657
    }
2658
    if (pis->shape.alpha != pdev->shape) {
2659
	changed |= PDF14_SET_SHAPE_ALPHA;
2660
	params.shape.alpha = pdev->shape = pis->shape.alpha;
2661
    }
2662
    if (pis->opacity.alpha != pdev->opacity) {
2663
	changed |= PDF14_SET_OPACITY_ALPHA;
2664
	params.opacity.alpha = pdev->opacity = pis->opacity.alpha;
2665
    }
2666
    /*
2667
     * Put parameters into a compositor parameter and then call the
2668
     * create_compositor.  This will pass the data through the clist
2669
     * to the PDF 1.4 transparency output device.  Note:  This action
2670
     * never creates a new PDF 1.4 compositor and it does not change
2671
     * the imager state.
2672
     */
2673
    if (changed != 0) {
2674
	params.changed = changed;
2675
	code = send_pdf14trans((gs_imager_state *)pis, (gx_device *)pdev,
2676
					&pcdev, &params, pis->memory);
2677
    }
2678
    return code;
2679
}
2680
 
2681
/*
2682
 * fill_path routine for the PDF 1.4 transaprency compositor device for
2683
 * writing the clist.
2684
 */
2685
private	int
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
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
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
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
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
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
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
}