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
psdf_setlinewidth(gx_device_vector * vdev,floatp width)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
psdf_setlinecap(gx_device_vector * vdev,gs_line_cap cap)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
psdf_setlinejoin(gx_device_vector * vdev,gs_line_join join)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
psdf_setmiterlimit(gx_device_vector * vdev,floatp limit)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
psdf_setdash(gx_device_vector * vdev,const float * pattern,uint count,floatp offset)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
psdf_setflat(gx_device_vector * vdev,floatp flatness)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
psdf_setlogop(gx_device_vector * vdev,gs_logical_operation_t lop,gs_logical_operation_t diff)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
psdf_dorect(gx_device_vector * vdev,fixed x0,fixed y0,fixed x1,fixed y1,gx_path_type_t type)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
psdf_beginpath(gx_device_vector * vdev,gx_path_type_t type)124 psdf_beginpath(gx_device_vector * vdev, gx_path_type_t type)
125 {
126 return 0;
127 }
128
129 int
psdf_moveto(gx_device_vector * vdev,floatp x0,floatp y0,floatp x,floatp y,gx_path_type_t type)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
psdf_lineto(gx_device_vector * vdev,floatp x0,floatp y0,floatp x,floatp y,gx_path_type_t type)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
psdf_curveto(gx_device_vector * vdev,floatp x0,floatp y0,floatp x1,floatp y1,floatp x2,floatp y2,floatp x3,floatp y3,gx_path_type_t type)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
psdf_closepath(gx_device_vector * vdev,floatp x0,floatp y0,floatp x_start,floatp y_start,gx_path_type_t type)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
psdf_adjust_color_index(gx_device_vector * vdev,gx_color_index color)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
psdf_round(double v,int precision,int radix)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
round_byte_color(gx_color_index cv)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
psdf_set_color(gx_device_vector * vdev,const gx_drawing_color * pdc,const psdf_set_color_commands_t * ppscc)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
psdf_begin_binary(gx_device_psdf * pdev,psdf_binary_writer * pbw)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
psdf_encode_binary(psdf_binary_writer * pbw,const stream_template * template,stream_state * ss)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
psdf_DCT_filter(gs_param_list * plist,stream_state * st,int Columns,int Rows,int Colors,psdf_binary_writer * pbw)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
psdf_CFE_binary(psdf_binary_writer * pbw,int w,int h,bool invert)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
psdf_end_binary(psdf_binary_writer * pbw)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
psdf_get_bits(gx_device * dev,int y,byte * data,byte ** actual_data)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
psdf_get_bits_rectangle(gx_device * dev,const gs_int_rect * prect,gs_get_bits_params_t * params,gs_int_rect ** unread)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
psdf_create_compositor(gx_device * dev,gx_device ** pcdev,const gs_composite_t * pct,gs_imager_state * pis,gs_memory_t * mem)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 }
461