2 |
- |
1 |
/* Copyright (C) 1997, 2000 Aladdin Enterprises. All rights reserved.
|
|
|
2 |
|
|
|
3 |
This software is provided AS-IS with no warranty, either express or
|
|
|
4 |
implied.
|
|
|
5 |
|
|
|
6 |
This software is distributed under license and may not be copied,
|
|
|
7 |
modified or distributed except as expressly authorized under the terms
|
|
|
8 |
of the license contained in the file LICENSE in this distribution.
|
|
|
9 |
|
|
|
10 |
For more information about licensing, please refer to
|
|
|
11 |
http://www.ghostscript.com/licensing/. For information on
|
|
|
12 |
commercial licensing, go to http://www.artifex.com/licensing/ or
|
|
|
13 |
contact Artifex Software, Inc., 101 Lucas Valley Road #110,
|
|
|
14 |
San Rafael, CA 94903, U.S.A., +1(415)492-9861.
|
|
|
15 |
*/
|
|
|
16 |
|
|
|
17 |
/* $Id: gdevpsdu.c,v 1.23 2005/03/14 18:08:36 dan Exp $ */
|
|
|
18 |
/* Common utilities for PostScript and PDF writers */
|
|
|
19 |
#include "stdio_.h" /* for FILE for jpeglib.h */
|
|
|
20 |
#include "jpeglib_.h" /* for sdct.h */
|
|
|
21 |
#include "memory_.h"
|
|
|
22 |
#include "gx.h"
|
|
|
23 |
#include "gserrors.h"
|
|
|
24 |
#include "gdevpsdf.h"
|
|
|
25 |
#include "strimpl.h"
|
|
|
26 |
#include "sa85x.h"
|
|
|
27 |
#include "scfx.h"
|
|
|
28 |
#include "sdct.h"
|
|
|
29 |
#include "sjpeg.h"
|
|
|
30 |
#include "spprint.h"
|
|
|
31 |
#include "sstring.h"
|
|
|
32 |
#include "gsovrc.h"
|
|
|
33 |
|
|
|
34 |
/* Structure descriptors */
|
|
|
35 |
public_st_device_psdf();
|
|
|
36 |
public_st_psdf_binary_writer();
|
|
|
37 |
|
|
|
38 |
/* Standard color command names. */
|
|
|
39 |
const psdf_set_color_commands_t psdf_set_fill_color_commands = {
|
|
|
40 |
"g", "rg", "k", "cs", "sc", "scn"
|
|
|
41 |
};
|
|
|
42 |
const psdf_set_color_commands_t psdf_set_stroke_color_commands = {
|
|
|
43 |
"G", "RG", "K", "CS", "SC", "SCN"
|
|
|
44 |
};
|
|
|
45 |
|
|
|
46 |
|
|
|
47 |
/* Define parameter-setting procedures. */
|
|
|
48 |
extern stream_state_proc_put_params(s_DCTE_put_params, stream_DCT_state);
|
|
|
49 |
|
|
|
50 |
/* ---------------- Vector implementation procedures ---------------- */
|
|
|
51 |
|
|
|
52 |
int
|
|
|
53 |
psdf_setlinewidth(gx_device_vector * vdev, floatp width)
|
|
|
54 |
{
|
|
|
55 |
pprintg1(gdev_vector_stream(vdev), "%g w\n", width);
|
|
|
56 |
return 0;
|
|
|
57 |
}
|
|
|
58 |
|
|
|
59 |
int
|
|
|
60 |
psdf_setlinecap(gx_device_vector * vdev, gs_line_cap cap)
|
|
|
61 |
{
|
|
|
62 |
pprintd1(gdev_vector_stream(vdev), "%d J\n", cap);
|
|
|
63 |
return 0;
|
|
|
64 |
}
|
|
|
65 |
|
|
|
66 |
int
|
|
|
67 |
psdf_setlinejoin(gx_device_vector * vdev, gs_line_join join)
|
|
|
68 |
{
|
|
|
69 |
pprintd1(gdev_vector_stream(vdev), "%d j\n", join);
|
|
|
70 |
return 0;
|
|
|
71 |
}
|
|
|
72 |
|
|
|
73 |
int
|
|
|
74 |
psdf_setmiterlimit(gx_device_vector * vdev, floatp limit)
|
|
|
75 |
{
|
|
|
76 |
pprintg1(gdev_vector_stream(vdev), "%g M\n", limit);
|
|
|
77 |
return 0;
|
|
|
78 |
}
|
|
|
79 |
|
|
|
80 |
int
|
|
|
81 |
psdf_setdash(gx_device_vector * vdev, const float *pattern, uint count,
|
|
|
82 |
floatp offset)
|
|
|
83 |
{
|
|
|
84 |
stream *s = gdev_vector_stream(vdev);
|
|
|
85 |
int i;
|
|
|
86 |
|
|
|
87 |
stream_puts(s, "[ ");
|
|
|
88 |
for (i = 0; i < count; ++i)
|
|
|
89 |
pprintg1(s, "%g ", pattern[i]);
|
|
|
90 |
pprintg1(s, "] %g d\n", offset);
|
|
|
91 |
return 0;
|
|
|
92 |
}
|
|
|
93 |
|
|
|
94 |
int
|
|
|
95 |
psdf_setflat(gx_device_vector * vdev, floatp flatness)
|
|
|
96 |
{
|
|
|
97 |
pprintg1(gdev_vector_stream(vdev), "%g i\n", flatness);
|
|
|
98 |
return 0;
|
|
|
99 |
}
|
|
|
100 |
|
|
|
101 |
int
|
|
|
102 |
psdf_setlogop(gx_device_vector * vdev, gs_logical_operation_t lop,
|
|
|
103 |
gs_logical_operation_t diff)
|
|
|
104 |
{
|
|
|
105 |
/****** SHOULD AT LEAST DETECT SET-0 & SET-1 ******/
|
|
|
106 |
return 0;
|
|
|
107 |
}
|
|
|
108 |
|
|
|
109 |
int
|
|
|
110 |
psdf_dorect(gx_device_vector * vdev, fixed x0, fixed y0, fixed x1, fixed y1,
|
|
|
111 |
gx_path_type_t type)
|
|
|
112 |
{
|
|
|
113 |
int code = (*vdev_proc(vdev, beginpath)) (vdev, type);
|
|
|
114 |
|
|
|
115 |
if (code < 0)
|
|
|
116 |
return code;
|
|
|
117 |
pprintg4(gdev_vector_stream(vdev), "%g %g %g %g re\n",
|
|
|
118 |
fixed2float(x0), fixed2float(y0),
|
|
|
119 |
fixed2float(x1 - x0), fixed2float(y1 - y0));
|
|
|
120 |
return (*vdev_proc(vdev, endpath)) (vdev, type);
|
|
|
121 |
}
|
|
|
122 |
|
|
|
123 |
int
|
|
|
124 |
psdf_beginpath(gx_device_vector * vdev, gx_path_type_t type)
|
|
|
125 |
{
|
|
|
126 |
return 0;
|
|
|
127 |
}
|
|
|
128 |
|
|
|
129 |
int
|
|
|
130 |
psdf_moveto(gx_device_vector * vdev, floatp x0, floatp y0, floatp x, floatp y,
|
|
|
131 |
gx_path_type_t type)
|
|
|
132 |
{
|
|
|
133 |
pprintg2(gdev_vector_stream(vdev), "%g %g m\n", x, y);
|
|
|
134 |
return 0;
|
|
|
135 |
}
|
|
|
136 |
|
|
|
137 |
int
|
|
|
138 |
psdf_lineto(gx_device_vector * vdev, floatp x0, floatp y0, floatp x, floatp y,
|
|
|
139 |
gx_path_type_t type)
|
|
|
140 |
{
|
|
|
141 |
pprintg2(gdev_vector_stream(vdev), "%g %g l\n", x, y);
|
|
|
142 |
return 0;
|
|
|
143 |
}
|
|
|
144 |
|
|
|
145 |
int
|
|
|
146 |
psdf_curveto(gx_device_vector * vdev, floatp x0, floatp y0,
|
|
|
147 |
floatp x1, floatp y1, floatp x2, floatp y2, floatp x3, floatp y3,
|
|
|
148 |
gx_path_type_t type)
|
|
|
149 |
{
|
|
|
150 |
if (x1 == x0 && y1 == y0 && x2 == x3 && y2 == y3)
|
|
|
151 |
pprintg2(gdev_vector_stream(vdev), "%g %g l\n", x3, y3);
|
|
|
152 |
else if (x1 == x0 && y1 == y0)
|
|
|
153 |
pprintg4(gdev_vector_stream(vdev), "%g %g %g %g v\n",
|
|
|
154 |
x2, y2, x3, y3);
|
|
|
155 |
else if (x3 == x2 && y3 == y2)
|
|
|
156 |
pprintg4(gdev_vector_stream(vdev), "%g %g %g %g y\n",
|
|
|
157 |
x1, y1, x2, y2);
|
|
|
158 |
else
|
|
|
159 |
pprintg6(gdev_vector_stream(vdev), "%g %g %g %g %g %g c\n",
|
|
|
160 |
x1, y1, x2, y2, x3, y3);
|
|
|
161 |
return 0;
|
|
|
162 |
}
|
|
|
163 |
|
|
|
164 |
int
|
|
|
165 |
psdf_closepath(gx_device_vector * vdev, floatp x0, floatp y0,
|
|
|
166 |
floatp x_start, floatp y_start, gx_path_type_t type)
|
|
|
167 |
{
|
|
|
168 |
stream_puts(gdev_vector_stream(vdev), "h\n");
|
|
|
169 |
return 0;
|
|
|
170 |
}
|
|
|
171 |
|
|
|
172 |
/* endpath is deliberately omitted. */
|
|
|
173 |
|
|
|
174 |
/* ---------------- Utilities ---------------- */
|
|
|
175 |
|
|
|
176 |
gx_color_index
|
|
|
177 |
psdf_adjust_color_index(gx_device_vector *vdev, gx_color_index color)
|
|
|
178 |
{
|
|
|
179 |
/*
|
|
|
180 |
* Since gx_no_color_index is all 1's, we can't represent
|
|
|
181 |
* a CMYK color consisting of full ink in all 4 components.
|
|
|
182 |
* However, this color must be available for registration marks.
|
|
|
183 |
* gxcmap.c fudges this by changing the K component to 254;
|
|
|
184 |
* undo this fudge here.
|
|
|
185 |
*/
|
|
|
186 |
return (color == (gx_no_color_index ^ 1) ? gx_no_color_index : color);
|
|
|
187 |
}
|
|
|
188 |
|
|
|
189 |
/* Round a double value to a specified precision. */
|
|
|
190 |
double
|
|
|
191 |
psdf_round(double v, int precision, int radix)
|
|
|
192 |
{
|
|
|
193 |
double mul = 1;
|
|
|
194 |
double w = v;
|
|
|
195 |
|
|
|
196 |
if (w <= 0)
|
|
|
197 |
return w;
|
|
|
198 |
while (w < precision) {
|
|
|
199 |
w *= radix;
|
|
|
200 |
mul *= radix;
|
|
|
201 |
}
|
|
|
202 |
return (int)(w + 0.5) / mul;
|
|
|
203 |
}
|
|
|
204 |
|
|
|
205 |
/*
|
|
|
206 |
* Since we only have 8 bits of color to start with, round the
|
|
|
207 |
* values to 3 digits for more compact output.
|
|
|
208 |
*/
|
|
|
209 |
private inline double
|
|
|
210 |
round_byte_color(gx_color_index cv)
|
|
|
211 |
{
|
|
|
212 |
return (int)((uint)cv * (1000.0 / 255.0) + 0.5) / 1000.0;
|
|
|
213 |
}
|
|
|
214 |
int
|
|
|
215 |
psdf_set_color(gx_device_vector * vdev, const gx_drawing_color * pdc,
|
|
|
216 |
const psdf_set_color_commands_t *ppscc)
|
|
|
217 |
{
|
|
|
218 |
const char *setcolor;
|
|
|
219 |
|
|
|
220 |
if (!gx_dc_is_pure(pdc))
|
|
|
221 |
return_error(gs_error_rangecheck);
|
|
|
222 |
{
|
|
|
223 |
stream *s = gdev_vector_stream(vdev);
|
|
|
224 |
gx_color_index color =
|
|
|
225 |
psdf_adjust_color_index(vdev, gx_dc_pure_color(pdc));
|
|
|
226 |
/*
|
|
|
227 |
* Normally we would precompute all of v0 .. v3, but gcc 2.7.2.3
|
|
|
228 |
* generates incorrect code for Intel CPUs if we do this. The code
|
|
|
229 |
* below is longer, but does less computation in some cases.
|
|
|
230 |
*/
|
|
|
231 |
double v3 = round_byte_color(color & 0xff);
|
|
|
232 |
|
|
|
233 |
switch (vdev->color_info.num_components) {
|
|
|
234 |
case 4:
|
|
|
235 |
/* if (v0 == 0 && v1 == 0 && v2 == 0 && ...) */
|
|
|
236 |
if ((color & 0xffffff00) == 0 && ppscc->setgray != 0) {
|
|
|
237 |
v3 = 1.0 - v3;
|
|
|
238 |
goto g;
|
|
|
239 |
}
|
|
|
240 |
pprintg4(s, "%g %g %g %g", round_byte_color(color >> 24),
|
|
|
241 |
round_byte_color((color >> 16) & 0xff),
|
|
|
242 |
round_byte_color((color >> 8) & 0xff), v3);
|
|
|
243 |
setcolor = ppscc->setcmykcolor;
|
|
|
244 |
break;
|
|
|
245 |
case 3:
|
|
|
246 |
/* if (v1 == v2 && v2 == v3 && ...) */
|
|
|
247 |
if (!((color ^ (color >> 8)) & 0xffff) && ppscc->setgray != 0)
|
|
|
248 |
goto g;
|
|
|
249 |
pprintg3(s, "%g %g %g", round_byte_color((color >> 16) & 0xff),
|
|
|
250 |
round_byte_color((color >> 8) & 0xff), v3);
|
|
|
251 |
setcolor = ppscc->setrgbcolor;
|
|
|
252 |
break;
|
|
|
253 |
case 1:
|
|
|
254 |
g:
|
|
|
255 |
pprintg1(s, "%g", v3);
|
|
|
256 |
setcolor = ppscc->setgray;
|
|
|
257 |
break;
|
|
|
258 |
default: /* can't happen */
|
|
|
259 |
return_error(gs_error_rangecheck);
|
|
|
260 |
}
|
|
|
261 |
if (setcolor)
|
|
|
262 |
pprints1(s, " %s\n", setcolor);
|
|
|
263 |
}
|
|
|
264 |
return 0;
|
|
|
265 |
}
|
|
|
266 |
|
|
|
267 |
/* ---------------- Binary data writing ---------------- */
|
|
|
268 |
|
|
|
269 |
/* Begin writing binary data. */
|
|
|
270 |
int
|
|
|
271 |
psdf_begin_binary(gx_device_psdf * pdev, psdf_binary_writer * pbw)
|
|
|
272 |
{
|
|
|
273 |
gs_memory_t *mem = pbw->memory = pdev->v_memory;
|
|
|
274 |
|
|
|
275 |
pbw->target = pdev->strm;
|
|
|
276 |
pbw->dev = pdev;
|
|
|
277 |
pbw->strm = 0; /* for GC in case of failure */
|
|
|
278 |
/* If not binary, set up the encoding stream. */
|
|
|
279 |
if (!pdev->binary_ok) {
|
|
|
280 |
#define BUF_SIZE 100 /* arbitrary */
|
|
|
281 |
byte *buf = gs_alloc_bytes(mem, BUF_SIZE, "psdf_begin_binary(buf)");
|
|
|
282 |
stream_A85E_state *ss = (stream_A85E_state *)
|
|
|
283 |
s_alloc_state(mem, s_A85E_template.stype,
|
|
|
284 |
"psdf_begin_binary(stream_state)");
|
|
|
285 |
stream *s = s_alloc(mem, "psdf_begin_binary(stream)");
|
|
|
286 |
|
|
|
287 |
if (buf == 0 || ss == 0 || s == 0) {
|
|
|
288 |
gs_free_object(mem, s, "psdf_begin_binary(stream)");
|
|
|
289 |
gs_free_object(mem, ss, "psdf_begin_binary(stream_state)");
|
|
|
290 |
gs_free_object(mem, buf, "psdf_begin_binary(buf)");
|
|
|
291 |
return_error(gs_error_VMerror);
|
|
|
292 |
}
|
|
|
293 |
ss->template = &s_A85E_template;
|
|
|
294 |
s_init_filter(s, (stream_state *)ss, buf, BUF_SIZE, pdev->strm);
|
|
|
295 |
#undef BUF_SIZE
|
|
|
296 |
pbw->strm = s;
|
|
|
297 |
} else {
|
|
|
298 |
pbw->strm = pdev->strm;
|
|
|
299 |
}
|
|
|
300 |
return 0;
|
|
|
301 |
}
|
|
|
302 |
|
|
|
303 |
/* Add an encoding filter. The client must have allocated the stream state, */
|
|
|
304 |
/* if any, using pdev->v_memory. */
|
|
|
305 |
int
|
|
|
306 |
psdf_encode_binary(psdf_binary_writer * pbw, const stream_template * template,
|
|
|
307 |
stream_state * ss)
|
|
|
308 |
{
|
|
|
309 |
return (s_add_filter(&pbw->strm, template, ss, pbw->memory) == 0 ?
|
|
|
310 |
gs_note_error(gs_error_VMerror) : 0);
|
|
|
311 |
}
|
|
|
312 |
|
|
|
313 |
/*
|
|
|
314 |
* Acquire parameters, and optionally set up the filter for, a DCTEncode
|
|
|
315 |
* filter. This is a separate procedure so it can be used to validate
|
|
|
316 |
* filter parameters when they are set, rather than waiting until they are
|
|
|
317 |
* used. pbw = NULL means just set up the stream state.
|
|
|
318 |
*/
|
|
|
319 |
int
|
|
|
320 |
psdf_DCT_filter(gs_param_list *plist /* may be NULL */,
|
|
|
321 |
stream_state /*stream_DCTE_state*/ *st,
|
|
|
322 |
int Columns, int Rows, int Colors,
|
|
|
323 |
psdf_binary_writer *pbw /* may be NULL */)
|
|
|
324 |
{
|
|
|
325 |
stream_DCT_state *const ss = (stream_DCT_state *) st;
|
|
|
326 |
gs_memory_t *mem = st->memory;
|
|
|
327 |
jpeg_compress_data *jcdp;
|
|
|
328 |
gs_c_param_list rcc_list;
|
|
|
329 |
int code;
|
|
|
330 |
|
|
|
331 |
/*
|
|
|
332 |
* "Wrap" the actual Dict or ACSDict parameter list in one that
|
|
|
333 |
* sets Rows, Columns, and Colors.
|
|
|
334 |
*/
|
|
|
335 |
gs_c_param_list_write(&rcc_list, mem);
|
|
|
336 |
if ((code = param_write_int((gs_param_list *)&rcc_list, "Rows",
|
|
|
337 |
&Rows)) < 0 ||
|
|
|
338 |
(code = param_write_int((gs_param_list *)&rcc_list, "Columns",
|
|
|
339 |
&Columns)) < 0 ||
|
|
|
340 |
(code = param_write_int((gs_param_list *)&rcc_list, "Colors",
|
|
|
341 |
&Colors)) < 0
|
|
|
342 |
) {
|
|
|
343 |
goto rcc_fail;
|
|
|
344 |
}
|
|
|
345 |
gs_c_param_list_read(&rcc_list);
|
|
|
346 |
if (plist)
|
|
|
347 |
gs_c_param_list_set_target(&rcc_list, plist);
|
|
|
348 |
/* Allocate space for IJG parameters. */
|
|
|
349 |
jcdp = gs_alloc_struct_immovable(mem, jpeg_compress_data,
|
|
|
350 |
&st_jpeg_compress_data, "zDCTE");
|
|
|
351 |
if (jcdp == 0)
|
|
|
352 |
return_error(gs_error_VMerror);
|
|
|
353 |
ss->data.compress = jcdp;
|
|
|
354 |
jcdp->memory = ss->jpeg_memory = mem; /* set now for allocation */
|
|
|
355 |
if ((code = gs_jpeg_create_compress(ss)) < 0)
|
|
|
356 |
goto dcte_fail; /* correct to do jpeg_destroy here */
|
|
|
357 |
/* Read parameters from dictionary */
|
|
|
358 |
s_DCTE_put_params((gs_param_list *)&rcc_list, ss); /* ignore errors */
|
|
|
359 |
/* Create the filter. */
|
|
|
360 |
jcdp->template = s_DCTE_template;
|
|
|
361 |
/* Make sure we get at least a full scan line of input. */
|
|
|
362 |
ss->scan_line_size = jcdp->cinfo.input_components *
|
|
|
363 |
jcdp->cinfo.image_width;
|
|
|
364 |
jcdp->template.min_in_size =
|
|
|
365 |
max(s_DCTE_template.min_in_size, ss->scan_line_size);
|
|
|
366 |
/* Make sure we can write the user markers in a single go. */
|
|
|
367 |
jcdp->template.min_out_size =
|
|
|
368 |
max(s_DCTE_template.min_out_size, ss->Markers.size);
|
|
|
369 |
if (pbw)
|
|
|
370 |
code = psdf_encode_binary(pbw, &jcdp->template, st);
|
|
|
371 |
if (code >= 0) {
|
|
|
372 |
gs_c_param_list_release(&rcc_list);
|
|
|
373 |
return 0;
|
|
|
374 |
}
|
|
|
375 |
dcte_fail:
|
|
|
376 |
gs_jpeg_destroy(ss);
|
|
|
377 |
gs_free_object(mem, jcdp, "setup_image_compression");
|
|
|
378 |
rcc_fail:
|
|
|
379 |
gs_c_param_list_release(&rcc_list);
|
|
|
380 |
return code;
|
|
|
381 |
}
|
|
|
382 |
|
|
|
383 |
/* Add a 2-D CCITTFax encoding filter. */
|
|
|
384 |
/* Set EndOfBlock iff the stream is not ASCII85 encoded. */
|
|
|
385 |
int
|
|
|
386 |
psdf_CFE_binary(psdf_binary_writer * pbw, int w, int h, bool invert)
|
|
|
387 |
{
|
|
|
388 |
gs_memory_t *mem = pbw->memory;
|
|
|
389 |
const stream_template *template = &s_CFE_template;
|
|
|
390 |
stream_CFE_state *st =
|
|
|
391 |
gs_alloc_struct(mem, stream_CFE_state, template->stype,
|
|
|
392 |
"psdf_CFE_binary");
|
|
|
393 |
int code;
|
|
|
394 |
|
|
|
395 |
if (st == 0)
|
|
|
396 |
return_error(gs_error_VMerror);
|
|
|
397 |
(*template->set_defaults) ((stream_state *) st);
|
|
|
398 |
st->K = -1;
|
|
|
399 |
st->Columns = w;
|
|
|
400 |
st->Rows = 0;
|
|
|
401 |
st->BlackIs1 = !invert;
|
|
|
402 |
st->EndOfBlock = pbw->strm->state->template != &s_A85E_template;
|
|
|
403 |
code = psdf_encode_binary(pbw, template, (stream_state *) st);
|
|
|
404 |
if (code < 0)
|
|
|
405 |
gs_free_object(mem, st, "psdf_CFE_binary");
|
|
|
406 |
return code;
|
|
|
407 |
}
|
|
|
408 |
|
|
|
409 |
/* Finish writing binary data. */
|
|
|
410 |
int
|
|
|
411 |
psdf_end_binary(psdf_binary_writer * pbw)
|
|
|
412 |
{
|
|
|
413 |
int status = s_close_filters(&pbw->strm, pbw->target);
|
|
|
414 |
|
|
|
415 |
return (status >= 0 ? 0 : gs_note_error(gs_error_ioerror));
|
|
|
416 |
}
|
|
|
417 |
|
|
|
418 |
/* ---------------- Overprint, Get Bits ---------------- */
|
|
|
419 |
|
|
|
420 |
/*
|
|
|
421 |
* High level devices cannot perform get_bits or get_bits_rectangle
|
|
|
422 |
* operations, for obvious reasons.
|
|
|
423 |
*/
|
|
|
424 |
int
|
|
|
425 |
psdf_get_bits(gx_device * dev, int y, byte * data, byte ** actual_data)
|
|
|
426 |
{
|
|
|
427 |
return_error(gs_error_unregistered);
|
|
|
428 |
}
|
|
|
429 |
|
|
|
430 |
int
|
|
|
431 |
psdf_get_bits_rectangle(
|
|
|
432 |
gx_device * dev,
|
|
|
433 |
const gs_int_rect * prect,
|
|
|
434 |
gs_get_bits_params_t * params,
|
|
|
435 |
gs_int_rect ** unread )
|
|
|
436 |
{
|
|
|
437 |
return_error(gs_error_unregistered);
|
|
|
438 |
}
|
|
|
439 |
|
|
|
440 |
/*
|
|
|
441 |
* Create compositor procedure for PostScript/PDF writer. Since these
|
|
|
442 |
* devices directly support overprint (and have access to the imager
|
|
|
443 |
* state), no compositor is required for overprint support. Hence, this
|
|
|
444 |
* routine just recognizes and discards invocations of the overprint
|
|
|
445 |
* compositor.
|
|
|
446 |
*/
|
|
|
447 |
int
|
|
|
448 |
psdf_create_compositor(
|
|
|
449 |
gx_device * dev,
|
|
|
450 |
gx_device ** pcdev,
|
|
|
451 |
const gs_composite_t * pct,
|
|
|
452 |
gs_imager_state * pis,
|
|
|
453 |
gs_memory_t * mem )
|
|
|
454 |
{
|
|
|
455 |
if (gs_is_overprint_compositor(pct)) {
|
|
|
456 |
*pcdev = dev;
|
|
|
457 |
return 0;
|
|
|
458 |
} else
|
|
|
459 |
return gx_default_create_compositor(dev, pcdev, pct, pis, mem);
|
|
|
460 |
}
|