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(¶ms.GrayBackground, data, sizeof(params.GrayBackground));
|
|
|
2106 |
data += sizeof(params.GrayBackground);
|
|
|
2107 |
}
|
|
|
2108 |
if (params.function_is_identity) {
|
|
|
2109 |
int i;
|
|
|
2110 |
|
|
|
2111 |
for (i = 0; i < MASK_TRANSFER_FUNCTION_SIZE; i++) {
|
|
|
2112 |
params.transfer_fn[i] = (byte)floor(i *
|
|
|
2113 |
(255.0 / (MASK_TRANSFER_FUNCTION_SIZE - 1)) + 0.5);
|
|
|
2114 |
}
|
|
|
2115 |
} else {
|
|
|
2116 |
read_value(data, params.transfer_fn);
|
|
|
2117 |
}
|
|
|
2118 |
break;
|
|
|
2119 |
case PDF14_END_TRANS_MASK:
|
|
|
2120 |
break; /* No data */
|
|
|
2121 |
case PDF14_SET_BLEND_PARAMS:
|
|
|
2122 |
params.changed = *data++;
|
|
|
2123 |
if (params.changed & PDF14_SET_BLEND_MODE)
|
|
|
2124 |
params.blend_mode = *data++;
|
|
|
2125 |
if (params.changed & PDF14_SET_TEXT_KNOCKOUT)
|
|
|
2126 |
params.text_knockout = *data++;
|
|
|
2127 |
if (params.changed & PDF14_SET_OPACITY_ALPHA)
|
|
|
2128 |
read_value(data, params.opacity.alpha);
|
|
|
2129 |
if (params.changed & PDF14_SET_SHAPE_ALPHA)
|
|
|
2130 |
read_value(data, params.shape.alpha);
|
|
|
2131 |
break;
|
|
|
2132 |
}
|
|
|
2133 |
code = gs_create_pdf14trans(ppct, ¶ms, mem);
|
|
|
2134 |
if (code < 0)
|
|
|
2135 |
return code;
|
|
|
2136 |
used = data - start;
|
|
|
2137 |
if_debug1('v', " used = %d\n", used);
|
|
|
2138 |
return used;
|
|
|
2139 |
}
|
|
|
2140 |
|
|
|
2141 |
/*
|
|
|
2142 |
* Create a PDF 1.4 transparency compositor.
|
|
|
2143 |
*
|
|
|
2144 |
* Note that this routine will be called only if the device is not already
|
|
|
2145 |
* a PDF 1.4 transparency compositor.
|
|
|
2146 |
*/
|
|
|
2147 |
private int
|
|
|
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, ¶ms, pis->memory);
|
|
|
2677 |
}
|
|
|
2678 |
return code;
|
|
|
2679 |
}
|
|
|
2680 |
|
|
|
2681 |
/*
|
|
|
2682 |
* fill_path routine for the PDF 1.4 transaprency compositor device for
|
|
|
2683 |
* writing the clist.
|
|
|
2684 |
*/
|
|
|
2685 |
private int
|
|
|
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 |
}
|