xref: /plan9/sys/src/cmd/gs/src/gdevps.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
1 /* Copyright (C) 1997, 2000-2004 artofcode LLC. 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: gdevps.c,v 1.40 2004/10/07 05:18:34 ray Exp $ */
18 /* PostScript-writing driver */
19 #include "math_.h"
20 #include "memory_.h"
21 #include "string_.h"
22 #include "time_.h"
23 #include "gx.h"
24 #include "gserrors.h"
25 #include "gscdefs.h"
26 #include "gsmatrix.h"		/* for gsiparam.h */
27 #include "gsiparam.h"
28 #include "gsline.h"
29 #include "gsparam.h"
30 #include "gxdevice.h"
31 #include "gscspace.h"
32 #include "gxdcolor.h"
33 #include "gxpath.h"
34 #include "spprint.h"
35 #include "strimpl.h"
36 #include "sstring.h"
37 #include "sa85x.h"
38 #include "gdevpsdf.h"
39 #include "gdevpsu.h"
40 
41 /* Current ProcSet version */
42 #define PSWRITE_PROCSET_VERSION 1
43 
44 /* Guaranteed size of operand stack accoeding to PLRM */
45 #define MAXOPSTACK 500
46 
47 private int psw_open_printer(gx_device * dev);
48 private int psw_close_printer(gx_device * dev);
49 
50 /* ---------------- Device definition ---------------- */
51 
52 /* Device procedures */
53 private dev_proc_open_device(psw_open);
54 private dev_proc_output_page(psw_output_page);
55 private dev_proc_close_device(psw_close);
56 private dev_proc_fill_rectangle(psw_fill_rectangle);
57 private dev_proc_copy_mono(psw_copy_mono);
58 private dev_proc_copy_color(psw_copy_color);
59 private dev_proc_put_params(psw_put_params);
60 private dev_proc_get_params(psw_get_params);
61 private dev_proc_fill_path(psw_fill_path);
62 private dev_proc_stroke_path(psw_stroke_path);
63 private dev_proc_fill_mask(psw_fill_mask);
64 private dev_proc_begin_image(psw_begin_image);
65 
66 #define X_DPI 720
67 #define Y_DPI 720
68 
69 typedef struct psw_path_state_s {
70     int num_points;		/* # of points since last non-lineto */
71     int move;			/* 1 iff last non-lineto was moveto, else 0 */
72     gs_point dprev[2];		/* line deltas before previous point, */
73 				/* if num_points - move >= 2 */
74 } psw_path_state_t;
75 
76 typedef struct psw_image_params_s {
77     gx_bitmap_id id;
78     ushort width, height;
79 } psw_image_params_t;
80 
81 typedef struct gx_device_pswrite_s {
82     gx_device_psdf_common;
83     /* LanguageLevel in pswrite_common is settable. */
84     gx_device_pswrite_common_t pswrite_common;
85 #define LanguageLevel_default 2.0
86 #define psdf_version_default psdf_version_level2
87     /* End of parameters */
88     bool first_page;
89     psdf_binary_writer *image_writer;
90 #define image_stream image_writer->strm
91 #define image_cache_size 197
92 #define image_cache_reprobe_step 121
93     psw_image_params_t image_cache[image_cache_size];
94     bool cache_toggle;
95     struct pf_ {
96 	gs_int_rect rect;
97 	gx_color_index color;
98     } page_fill;
99     /* Temporary state while writing a path */
100     psw_path_state_t path_state;
101 } gx_device_pswrite;
102 
103 /* GC descriptor and procedures */
104 gs_private_st_suffix_add1_final(st_device_pswrite, gx_device_pswrite,
105 				"gx_device_pswrite", device_pswrite_enum_ptrs,
106 				device_pswrite_reloc_ptrs, gx_device_finalize,
107 				st_device_psdf, image_writer);
108 
109 #define psw_procs\
110 	{	psw_open,\
111 		gx_upright_get_initial_matrix,\
112 		NULL,			/* sync_output */\
113 		psw_output_page,\
114 		psw_close,\
115 		gx_default_rgb_map_rgb_color,\
116 		gx_default_rgb_map_color_rgb,\
117 		psw_fill_rectangle,\
118 		NULL,			/* tile_rectangle */\
119 		psw_copy_mono,\
120 		psw_copy_color,\
121 		NULL,			/* draw_line */\
122 		psdf_get_bits,\
123 		psw_get_params,\
124 		psw_put_params,\
125 		NULL,			/* map_cmyk_color */\
126 		NULL,			/* get_xfont_procs */\
127 		NULL,			/* get_xfont_device */\
128 		NULL,			/* map_rgb_alpha_color */\
129 		gx_page_device_get_page_device,\
130 		NULL,			/* get_alpha_bits */\
131 		NULL,			/* copy_alpha */\
132 		NULL,			/* get_band */\
133 		NULL,			/* copy_rop */\
134 		psw_fill_path,\
135 		psw_stroke_path,\
136 		psw_fill_mask,\
137 		gdev_vector_fill_trapezoid,\
138 		gdev_vector_fill_parallelogram,\
139 		gdev_vector_fill_triangle,\
140 		NULL /****** WRONG ******/,	/* draw_thin_line */\
141 		psw_begin_image,\
142 		NULL,			/* image_data */\
143 		NULL,			/* end_image */\
144 		NULL,			/* strip_tile_rectangle */\
145 		NULL,/******psw_strip_copy_rop******/\
146 		NULL,			/* get_clipping_box */\
147 		NULL,			/* begin_typed_image */\
148 		psdf_get_bits_rectangle,\
149 		NULL,			/* map_color_rgb_alpha */\
150 		psdf_create_compositor\
151 	}
152 
153 const gx_device_pswrite gs_pswrite_device = {
154     std_device_dci_type_body(gx_device_pswrite, 0, "pswrite",
155 			     &st_device_pswrite,
156 			     DEFAULT_WIDTH_10THS * X_DPI / 10,
157 			     DEFAULT_HEIGHT_10THS * Y_DPI / 10,
158 			     X_DPI, Y_DPI, 3, 24, 255, 255, 256, 256),
159     psw_procs,
160     psdf_initial_values(psdf_version_default, 1 /*true */ ),	/* (ASCII85EncodePages) */
161     PSWRITE_COMMON_VALUES(LanguageLevel_default, /* LanguageLevel */
162 			  0 /*false*/, /* ProduceEPS */
163 			  PSWRITE_PROCSET_VERSION /* ProcSet_version */)
164 };
165 
166 const gx_device_pswrite gs_epswrite_device = {
167     std_device_dci_type_body(gx_device_pswrite, 0, "epswrite",
168 			     &st_device_pswrite,
169 			     DEFAULT_WIDTH_10THS * X_DPI / 10,
170 			     DEFAULT_HEIGHT_10THS * Y_DPI / 10,
171 			     X_DPI, Y_DPI, 3, 24, 255, 255, 256, 256),
172     psw_procs,
173     psdf_initial_values(psdf_version_default, 1 /*true */ ),	/* (ASCII85EncodePages) */
174     PSWRITE_COMMON_VALUES(LanguageLevel_default, /* LanguageLevel */
175 			  1 /*true*/, /* ProduceEPS */
176 			  PSWRITE_PROCSET_VERSION /* ProcSet_version */)
177 };
178 
179 /* Vector device implementation */
180 private int
181     psw_beginpage(gx_device_vector * vdev),
182     psw_can_handle_hl_color(gx_device_vector * vdev, const gs_imager_state * pis,
183                   const gx_drawing_color * pdc),
184     psw_setcolors(gx_device_vector * vdev, const gs_imager_state * pis,
185                   const gx_drawing_color * pdc),
186     psw_dorect(gx_device_vector * vdev, fixed x0, fixed y0, fixed x1,
187 	       fixed y1, gx_path_type_t type),
188     psw_beginpath(gx_device_vector * vdev, gx_path_type_t type),
189     psw_moveto(gx_device_vector * vdev, floatp x0, floatp y0,
190 	       floatp x, floatp y, gx_path_type_t type),
191     psw_lineto(gx_device_vector * vdev, floatp x0, floatp y0,
192 	       floatp x, floatp y, gx_path_type_t type),
193     psw_curveto(gx_device_vector * vdev, floatp x0, floatp y0,
194 		floatp x1, floatp y1, floatp x2, floatp y2,
195 		floatp x3, floatp y3, gx_path_type_t type),
196     psw_closepath(gx_device_vector * vdev, floatp x0, floatp y0,
197 		  floatp x_start, floatp y_start, gx_path_type_t type),
198     psw_endpath(gx_device_vector * vdev, gx_path_type_t type);
199 private const gx_device_vector_procs psw_vector_procs = {
200 	/* Page management */
201     psw_beginpage,
202 	/* Imager state */
203     psdf_setlinewidth,
204     psdf_setlinecap,
205     psdf_setlinejoin,
206     psdf_setmiterlimit,
207     psdf_setdash,
208     psdf_setflat,
209     psdf_setlogop,
210 	/* Other state */
211     psw_can_handle_hl_color,
212     psw_setcolors,		/* fill & stroke colors are the same */
213     psw_setcolors,
214 	/* Paths */
215     psdf_dopath,
216     psw_dorect,
217     psw_beginpath,
218     psw_moveto,
219     psw_lineto,
220     psw_curveto,
221     psw_closepath,
222     psw_endpath
223 };
224 
225 /* ---------------- File header ---------------- */
226 
227 /*
228  * NOTE: Increment PSWRITE_PROCSET_VERSION (above) whenever the following
229  * definitions change.
230  */
231 
232 private const char *const psw_procset[] = {
233     "/!{bind def}bind def/#{load def}!/N/counttomark #",
234 	/* <rbyte> <gbyte> <bbyte> rG - */
235 	/* <graybyte> G - */
236  "/rG{3{3 -1 roll 255 div}repeat setrgbcolor}!/G{255 div setgray}!/K{0 G}!",
237 	/* <bbyte> <rgbyte> r6 - */
238 	/* <gbyte> <rbbyte> r5 - */
239 	/* <rbyte> <gbbyte> r3 - */
240     "/r6{dup 3 -1 roll rG}!/r5{dup 3 1 roll rG}!/r3{dup rG}!",
241     "/w/setlinewidth #/J/setlinecap #",
242     "/j/setlinejoin #/M/setmiterlimit #/d/setdash #/i/setflat #",
243     "/m/moveto #/l/lineto #/c/rcurveto #",
244 	/* <dx1> <dy1> ... <dxn> <dyn> p - */
245     "/p{N 2 idiv{N -2 roll rlineto}repeat}!",
246 	/* <x> <y> <dx1> <dy1> ... <dxn> <dyn> P - */
247     "/P{N 0 gt{N -2 roll moveto p}if}!",
248     "/h{p closepath}!/H{P closepath}!",
249 	/* <dx> lx - */
250 	/* <dy> ly - */
251 	/* <dx2> <dy2> <dx3> <dy3> v - */
252 	/* <dx1> <dy1> <dx2> <dy2> y - */
253     "/lx{0 rlineto}!/ly{0 exch rlineto}!/v{0 0 6 2 roll c}!/y{2 copy c}!",
254 	/* <x> <y> <dx> <dy> re - */
255     "/re{4 -2 roll m exch dup lx exch ly neg lx h}!",
256 	/* <x> <y> <a> <b> ^ <x> <y> <a> <b> <-x> <-y> */
257     "/^{3 index neg 3 index neg}!",
258     "/f{P fill}!/f*{P eofill}!/s{H stroke}!/S{P stroke}!",
259     "/q/gsave #/Q/grestore #/rf{re fill}!",
260     "/Y{P clip newpath}!/Y*{P eoclip newpath}!/rY{re Y}!",
261 	/* <w> <h> <name> <data> <?> |= <w> <h> <data> */
262     "/|={pop exch 4 1 roll 1 array astore cvx 3 array astore cvx exch 1 index def exec}!",
263 	/* <w> <h> <name> <length> <src> | <w> <h> <data> */
264     "/|{exch string readstring |=}!",
265 	/* <w> <?> <name> (<length>|) + <w> <?> <name> <length> */
266     "/+{dup type/nametype eq{2 index 7 add -3 bitshift 2 index mul}if}!",
267 	/* <w> <h> <name> (<length>|) $ <w> <h> <data> */
268     "/@/currentfile #/${+ @ |}!",
269 	/* <file> <nbytes> <ncomp> B <proc_1> ... <proc_ncomp> true */
270     "/B{{2 copy string{readstring pop}aload pop 4 array astore cvx",
271     "3 1 roll}repeat pop pop true}!",
272 	/* <x> <y> <w> <h> <bpc/inv> <src> Ix <w> <h> <bps/inv> <mtx> <src> */
273     "/Ix{[1 0 0 1 11 -2 roll exch neg exch neg]exch}!",
274 	/* <x> <y> <h> <src> , - */
275 	/* <x> <y> <h> <src> If - */
276 	/* <x> <y> <h> <src> I - */
277 "/,{true exch Ix imagemask}!/If{false exch Ix imagemask}!/I{exch Ix image}!",
278     0
279 };
280 
281 private const char *const psw_1_procset[] = {
282     0
283 };
284 
285 private const char *const psw_1_x_procset[] = {
286 	/* <w> <h> <name> <length> <src> |X <w> <h> <data> */
287 	/* <w> <h> <name> (<length>|) $X <w> <h> <data> */
288     "/|X{exch string readhexstring |=}!/$X{+ @ |X}!",
289 	/* - @X <hexsrc> */
290     "/@X{{currentfile ( ) readhexstring pop}}!",
291     0
292 };
293 
294 private const char *const psw_1_5_procset[] = {
295 	/* <x> <y> <w> <h> <src> <bpc> Ic - */
296     "/Ic{exch Ix false 3 colorimage}!",
297     0
298 };
299 
300 private const char *const psw_2_procset[] = {
301 	/* <src> <w> <h> -mark- ... F <g4src> */
302 	/* <src> <w> <h> FX <g4src> */
303     "/F{/Columns counttomark 3 add -2 roll/Rows exch/K -1/BlackIs1 true>>",
304     "/CCITTFaxDecode filter}!/FX{<</EndOfBlock false F}!",
305 	/* <src> X <a85src> */
306 	/* - @X <a85src> */
307 	/* <w> <h> <src> /&2 <w> <h> <src> <w> <h> */
308     "/X{/ASCII85Decode filter}!/@X{@ X}!/&2{2 index 2 index}!",
309 	/* <w> <h> @F <w> <h> <g4src> */
310 	/* <w> <h> @C <w> <h> <g4a85src> */
311     "/@F{@ &2<<F}!/@C{@X &2 FX}!",
312 	/* <w> <h> <name> (<length>|) $X <w> <h> <data> */
313 	/* <w> <h> <?> <?> <src> &4 <w> <h> <?> <?> <src> <w> <h> */
314 	/* <w> <h> <name> (<length>|) $F <w> <h> <data> */
315 	/* <w> <h> <name> (<length>|) $C <w> <h> <data> */
316     "/$X{+ @X |}!/&4{4 index 4 index}!/$F{+ @ &4<<F |}!/$C{+ @X &4 FX |}!",
317 	/* <w> <h> <bpc> <matrix> <decode> <interpolate> <src>IC - */
318     "/IC{3 1 roll 10 dict begin 1{/ImageType/Interpolate/Decode/DataSource",
319     "/ImageMatrix/BitsPerComponent/Height/Width}{exch def}forall",
320     "currentdict end image}!",
321     /* A hack for compatibility with interpreters, which don't consume
322        ASCII85Decode EOD when reader stops immediately before it : */
323     "/~{@ read {pop} if}!",
324     0
325 };
326 
327 /* ---------------- Utilities ---------------- */
328 
329 /*
330  * Output the file header.  This must write to a file, not a stream,
331  * because it may be called during finalization.
332  */
333 private int
psw_begin_file(gx_device_pswrite * pdev,const gs_rect * pbbox)334 psw_begin_file(gx_device_pswrite *pdev, const gs_rect *pbbox)
335 {
336     int code;
337     FILE *f = pdev->file;
338     char const * const *p1;
339     char const * const *p2;
340 
341     if (pdev->pswrite_common.LanguageLevel < 1.5) {
342 	p1 = psw_1_x_procset;
343 	p2 = psw_1_procset;
344     } else if (pdev->pswrite_common.LanguageLevel > 1.5) {
345 	p1 = psw_1_5_procset;
346 	p2 = psw_2_procset;
347     } else {
348 	p1 = psw_1_x_procset;
349 	p2 = psw_1_5_procset;
350     }
351 
352     if ((code = psw_begin_file_header(f, (gx_device *)pdev, pbbox,
353 			  &pdev->pswrite_common,
354 			  pdev->params.ASCII85EncodePages)) < 0 ||
355         (code = psw_print_lines(f, psw_procset)) < 0 ||
356         (code = psw_print_lines(f, p1)) < 0 ||
357         (code = psw_print_lines(f, p2)) < 0 ||
358         (code = psw_end_file_header(f)) < 0)
359         return code;
360     if(fflush(f) == EOF)
361         return_error(gs_error_ioerror);
362     return 0;
363 }
364 
365 /* Reset the image cache. */
366 private void
image_cache_reset(gx_device_pswrite * pdev)367 image_cache_reset(gx_device_pswrite * pdev)
368 {
369     int i;
370 
371     for (i = 0; i < image_cache_size; ++i)
372 	pdev->image_cache[i].id = gx_no_bitmap_id;
373     pdev->cache_toggle = false;
374 }
375 
376 /* Look up or enter image parameters in the cache. */
377 /* Return -1 if the key is not in the cache, or its index. */
378 /* If id is gx_no_bitmap_id or enter is false, do not enter it. */
379 private int
image_cache_lookup(gx_device_pswrite * pdev,gx_bitmap_id id,int width,int height,bool enter)380 image_cache_lookup(gx_device_pswrite * pdev, gx_bitmap_id id,
381 		   int width, int height, bool enter)
382 {
383     int i1, i2;
384     psw_image_params_t *pip1;
385     psw_image_params_t *pip2;
386 
387     if (id == gx_no_bitmap_id)
388 	return -1;
389     i1 = id % image_cache_size;
390     pip1 = &pdev->image_cache[i1];
391     if (pip1->id == id && pip1->width == width && pip1->height == height) {
392 	return i1;
393     }
394     i2 = (i1 + image_cache_reprobe_step) % image_cache_size;
395     pip2 = &pdev->image_cache[i2];
396     if (pip2->id == id && pip2->width == width && pip2->height == height) {
397 	return i2;
398     }
399     if (enter) {
400 	int i = ((pdev->cache_toggle = !pdev->cache_toggle) ? i2 : i1);
401 	psw_image_params_t *pip = &pdev->image_cache[i];
402 
403 	pip->id = id, pip->width = width, pip->height = height;
404 	return i;
405     }
406     return -1;
407 }
408 
409 /*
410  * Prepare the encoding stream for image data.
411  * Return 1 if using ASCII (Hex or 85) encoding, 0 if binary.
412  */
413 private int
psw_image_stream_setup(gx_device_pswrite * pdev,bool binary_ok)414 psw_image_stream_setup(gx_device_pswrite * pdev, bool binary_ok)
415 {
416     int code;
417     bool save = pdev->binary_ok;
418 
419     if (pdev->pswrite_common.LanguageLevel >= 2 || binary_ok) {
420 	pdev->binary_ok = binary_ok;
421 	code = psdf_begin_binary((gx_device_psdf *)pdev, pdev->image_writer);
422     } else {
423 	/* LanguageLevel 1, binary not OK.  Use ASCIIHex encoding. */
424 	pdev->binary_ok = true;
425 	code = psdf_begin_binary((gx_device_psdf *)pdev, pdev->image_writer);
426 	if (code >= 0) {
427 	    stream_state *st =
428 		s_alloc_state(pdev->v_memory, s_AXE_template.stype,
429 			      "psw_image_stream_setup");
430 
431 	    if (st == 0)
432 		code = gs_note_error(gs_error_VMerror);
433 	    else {
434 		code = psdf_encode_binary(pdev->image_writer,
435 					  &s_AXE_template, st);
436 		if (code >= 0)
437 		    ((stream_AXE_state *)st)->EndOfData = false; /* no > */
438 	    }
439 	}
440     }
441     pdev->binary_ok = save;
442     return (code < 0 ? code : !binary_ok);
443 }
444 
445 /* Clean up after writing an image. */
446 private int
psw_image_cleanup(gx_device_pswrite * pdev)447 psw_image_cleanup(gx_device_pswrite * pdev)
448 {
449     int code = 0;
450 
451     if (pdev->image_stream != 0) {
452 	code = psdf_end_binary(pdev->image_writer);
453 	memset(pdev->image_writer, 0, sizeof(*pdev->image_writer));
454     }
455     return code;
456 }
457 
458 /* Write data for an image.  Assumes width > 0, height > 0. */
459 private int
psw_put_bits(stream * s,const byte * data,int data_x_bit,uint raster,uint width_bits,int height)460 psw_put_bits(stream * s, const byte * data, int data_x_bit, uint raster,
461 	     uint width_bits, int height)
462 {
463     const byte *row = data + (data_x_bit >> 3);
464     int shift = data_x_bit & 7;
465     int y;
466 
467     for (y = 0; y < height; ++y, row += raster) {
468 	if (shift == 0)
469 	    stream_write(s, row, (width_bits + 7) >> 3);
470 	else {
471 	    const byte *src = row;
472 	    int wleft = width_bits;
473 	    int cshift = 8 - shift;
474 
475 	    for (; wleft + shift > 8; ++src, wleft -= 8)
476 		stream_putc(s, (byte)((*src << shift) + (src[1] >> cshift)));
477 	    if (wleft > 0)
478 		stream_putc(s, (byte)((*src << shift) & (byte)(0xff00 >> wleft)));
479 	}
480         if (s->end_status == ERRC)
481             return_error(gs_error_ioerror);
482     }
483     return 0;
484 }
485 private int
psw_put_image_bits(gx_device_pswrite * pdev,const char * op,const byte * data,int data_x,uint raster,int width,int height,int depth)486 psw_put_image_bits(gx_device_pswrite *pdev, const char *op,
487 		   const byte * data, int data_x, uint raster,
488 		   int width, int height, int depth)
489 {
490     int code;
491 
492     pprints1(pdev->strm, "%s\n", op);
493     code = psw_put_bits(pdev->image_stream, data, data_x * depth, raster,
494 		 width * depth, height);
495     if (code < 0)
496         return code;
497     psw_image_cleanup(pdev);
498     return 0;
499 }
500 private int
psw_put_image(gx_device_pswrite * pdev,const char * op,int encode,const byte * data,int data_x,uint raster,int width,int height,int depth)501 psw_put_image(gx_device_pswrite *pdev, const char *op, int encode,
502 	      const byte * data, int data_x, uint raster,
503 	      int width, int height, int depth)
504 {
505     int code = psw_image_stream_setup(pdev, !(encode & 1));
506 
507     if (code < 0)
508 	return code;
509     if (encode & 2) {
510 	code = psdf_CFE_binary(pdev->image_writer, width, height, false);
511 	if (code < 0)
512 	    return code;
513     }
514     return psw_put_image_bits(pdev, op, data, data_x, raster,
515 			      width, height, depth);
516 }
517 private int
psw_image_write(gx_device_pswrite * pdev,const char * imagestr,const byte * data,int data_x,uint raster,gx_bitmap_id id,int x,int y,int width,int height,int depth)518 psw_image_write(gx_device_pswrite * pdev, const char *imagestr,
519 		const byte * data, int data_x, uint raster, gx_bitmap_id id,
520 		int x, int y, int width, int height, int depth)
521 {
522     stream *s = gdev_vector_stream((gx_device_vector *) pdev);
523     uint width_bits = width * depth;
524     int index = image_cache_lookup(pdev, id, width_bits, height, false);
525     char str[40];
526     char endstr[20];
527     int code, encode;
528     const char *op;
529 
530     if (index >= 0) {
531 	sprintf(str, "%d%c", index / 26, index % 26 + 'A');
532 	pprintd2(s, "%d %d ", x, y);
533 	pprints2(s, "%s %s\n", str, imagestr);
534         if (s->end_status == ERRC)
535             return_error(gs_error_ioerror);
536 	return 0;
537     }
538     pprintd4(s, "%d %d %d %d ", x, y, width, height);
539     encode = !pdev->binary_ok;
540     if (depth == 1 && width > 16 && pdev->pswrite_common.LanguageLevel >= 2) {
541 	/*
542 	 * We should really look at the statistics of the image before
543 	 * committing to using G4 encoding....
544 	 */
545 	encode += 2;
546     }
547     if (id == gx_no_bitmap_id || width_bits * (ulong) height > 8000) {
548 	static const char *const uncached[4] = {
549 	    "@", "@X", "@F", "@C"
550 	};
551 
552 	stream_puts(s, uncached[encode]);
553 	op = imagestr;
554 	strcpy(endstr, "\n");
555     } else {
556 	static const char *const cached[4] = {
557 	    "$", "$X", "$F", "$C"
558 	};
559 
560 	index = image_cache_lookup(pdev, id, width_bits, height, true);
561 	sprintf(str, "/%d%c", index / 26, index % 26 + 'A');
562 	stream_puts(s, str);
563 	if (depth != 1)
564 	    pprintld1(s, " %ld", ((width_bits + 7) >> 3) * (ulong) height);
565 	op = cached[encode];
566 	sprintf(endstr, "\n%s\n", imagestr);
567     }
568     if (s->end_status == ERRC)
569         return_error(gs_error_ioerror);
570     /*
571      * In principle, we should put %%BeginData: / %%EndData around all data
572      * sections.  However, as long as the data are ASCII (not binary), they
573      * can't cause problems for a DSC parser as long as all lines are
574      * limited to 255 characters and there is no possibility that %% might
575      * occur at the beginning of a line.  ASCIIHexEncoded data can't contain
576      * % at all, and our implementation of ASCII85Encode also guarantees
577      * the desired property.  Therefore, we only bracket binary data.
578      */
579     if (encode & 1) {
580 	/* We're using ASCII encoding. */
581 	stream_putc(s, '\n');
582 	code = psw_put_image(pdev, op, encode, data, data_x, raster,
583 			     width, height, depth);
584 	if (code < 0)
585 	    return code;
586     } else {
587 	/*
588 	 * Do a pre-pass to compute the amount of binary data for the
589 	 * %%BeginData DSC comment.
590 	 */
591 	stream poss;
592 
593 	s_init(s, pdev->memory);
594 	swrite_position_only(&poss);
595 	pdev->strm = &poss;
596 	code = psw_put_image(pdev, op, encode, data, data_x, raster,
597 			     width, height, depth);
598 	pdev->strm = s;
599 	if (code < 0)
600 	    return code;
601 	pprintld1(s, "\n%%%%BeginData: %ld\n", stell(&poss));
602 	code = psw_put_image(pdev, op, encode, data, data_x, raster,
603 			     width, height, depth);
604 	if (code < 0)
605 	    return code;
606 	stream_puts(s, "\n%%EndData");
607     }
608     stream_puts(s, endstr);
609     if (s->end_status == ERRC)
610         return_error(gs_error_ioerror);
611     return 0;
612 }
613 
614 /* Print a matrix. */
615 private void
psw_put_matrix(stream * s,const gs_matrix * pmat)616 psw_put_matrix(stream * s, const gs_matrix * pmat)
617 {
618     pprintg6(s, "[%g %g %g %g %g %g]",
619 	     pmat->xx, pmat->xy, pmat->yx, pmat->yy, pmat->tx, pmat->ty);
620 }
621 
622 /* Check for a deferred erasepage. */
623 private int
psw_check_erasepage(gx_device_pswrite * pdev)624 psw_check_erasepage(gx_device_pswrite *pdev)
625 {
626     int code = 0;
627 
628     if (pdev->page_fill.color != gx_no_color_index) {
629 	if (pdev->page_fill.rect.p.x != pdev->page_fill.rect.q.x
630 	    && pdev->page_fill.rect.p.y != pdev->page_fill.rect.q.y)
631 	{
632 	    code = gdev_vector_fill_rectangle((gx_device *)pdev,
633 					      pdev->page_fill.rect.p.x,
634 					      pdev->page_fill.rect.p.y,
635 					      pdev->page_fill.rect.q.x -
636 						pdev->page_fill.rect.p.x,
637 					      pdev->page_fill.rect.q.y -
638 						pdev->page_fill.rect.p.y,
639 					      pdev->page_fill.color);
640 	}
641 	pdev->page_fill.color = gx_no_color_index;
642     }
643     return code;
644 }
645 #define CHECK_BEGIN_PAGE(pdev)\
646   BEGIN\
647     int code_ = psw_check_erasepage(pdev);\
648 \
649     if (code_ < 0)\
650       return code_;\
651   END
652 
653 /* Check if we write each page into separate file. */
654 private bool
psw_is_separate_pages(gx_device_vector * const vdev)655 psw_is_separate_pages(gx_device_vector *const vdev)
656 {
657     const char *fmt;
658     gs_parsed_file_name_t parsed;
659     int code = gx_parse_output_file_name(&parsed, &fmt, vdev->fname, strlen(vdev->fname));
660 
661     return (code >= 0 && fmt != 0);
662 }
663 
664 /* ---------------- Vector device implementation ---------------- */
665 
666 private int
psw_beginpage(gx_device_vector * vdev)667 psw_beginpage(gx_device_vector * vdev)
668 {
669     gx_device_pswrite *const pdev = (gx_device_pswrite *)vdev;
670     int code = psw_open_printer((gx_device *)vdev);
671 
672     stream *s = vdev->strm;
673 
674     if (code < 0)
675 	 return code;
676 
677     if (pdev->first_page) {
678 	code = psw_begin_file(pdev, NULL);
679         if (code < 0)
680 	     return code;
681     }
682 
683     code = psw_write_page_header(s, (gx_device *)vdev, &pdev->pswrite_common, true,
684                           (psw_is_separate_pages(vdev) ? 1 : vdev->PageCount + 1),
685                           image_cache_size);
686     if (code < 0)
687 	 return code;
688 
689     pdev->page_fill.color = gx_no_color_index;
690     return 0;
691 }
692 
693 
694 private int
psw_can_handle_hl_color(gx_device_vector * vdev,const gs_imager_state * pis1,const gx_drawing_color * pdc)695 psw_can_handle_hl_color(gx_device_vector * vdev, const gs_imager_state * pis1,
696               const gx_drawing_color * pdc)
697 {
698     return false; /* High level color is not implemented yet. */
699 }
700 
701 private int
psw_setcolors(gx_device_vector * vdev,const gs_imager_state * pis1,const gx_drawing_color * pdc)702 psw_setcolors(gx_device_vector * vdev, const gs_imager_state * pis1,
703               const gx_drawing_color * pdc)
704 {
705     const gs_imager_state * pis = NULL; /* High level color is not implemented yet. */
706     if (!gx_dc_is_pure(pdc))
707 	return_error(gs_error_rangecheck);
708     /* PostScript only keeps track of a single color. */
709     gx_hld_save_color(pis, pdc, &vdev->saved_fill_color);
710     gx_hld_save_color(pis, pdc, &vdev->saved_stroke_color);
711     {
712 	stream *s = gdev_vector_stream(vdev);
713 	gx_color_index color = gx_dc_pure_color(pdc);
714 	int r = color >> 16;
715 	int g = (color >> 8) & 0xff;
716 	int b = color & 0xff;
717 
718 	if (r == g && g == b) {
719 	    if (r == 0)
720 		stream_puts(s, "K\n");
721 	    else
722 		pprintd1(s, "%d G\n", r);
723 	} else if (r == g)
724 	    pprintd2(s, "%d %d r6\n", b, r);
725 	else if (g == b)
726 	    pprintd2(s, "%d %d r3\n", r, g);
727 	else if (r == b)
728 	    pprintd2(s, "%d %d r5\n", g, b);
729 	else
730 	    pprintd3(s, "%d %d %d rG\n", r, g, b);
731         if (s->end_status == ERRC)
732             return_error(gs_error_ioerror);
733     }
734     return 0;
735 }
736 
737 /* Redefine dorect to recognize rectangle fills. */
738 private int
psw_dorect(gx_device_vector * vdev,fixed x0,fixed y0,fixed x1,fixed y1,gx_path_type_t type)739 psw_dorect(gx_device_vector * vdev, fixed x0, fixed y0, fixed x1, fixed y1,
740 	   gx_path_type_t type)
741 {
742     if ((type & ~gx_path_type_rule) != gx_path_type_fill)
743 	return psdf_dorect(vdev, x0, y0, x1, y1, type);
744     pprintg4(gdev_vector_stream(vdev), "%g %g %g %g rf\n",
745 	     fixed2float(x0), fixed2float(y0),
746 	     fixed2float(x1 - x0), fixed2float(y1 - y0));
747     if ((gdev_vector_stream(vdev))->end_status == ERRC)
748         return_error(gs_error_ioerror);
749     return 0;
750 }
751 
752 /*
753  * We redefine path tracing to use a compact form for polygons; also,
754  * we only need to write coordinates with 2 decimals of precision,
755  * since this is 10 times more precise than any existing output device.
756  */
757 inline private double
round_coord2(floatp v)758 round_coord2(floatp v)
759 {
760     return floor(v * 100 + 0.5) / 100.0;
761 }
762 private void
print_coord2(stream * s,floatp x,floatp y,const char * str)763 print_coord2(stream * s, floatp x, floatp y, const char *str)
764 {
765     pprintg2(s, "%g %g ", round_coord2(x), round_coord2(y));
766     if (str != 0)
767 	stream_puts(s, str);
768 }
769 
770 private int
psw_beginpath(gx_device_vector * vdev,gx_path_type_t type)771 psw_beginpath(gx_device_vector * vdev, gx_path_type_t type)
772 {
773     gx_device_pswrite *const pdev = (gx_device_pswrite *)vdev;
774 
775     if (type & (gx_path_type_fill | gx_path_type_stroke)) {
776 	/*
777 	 * fill_path and stroke_path call CHECK_BEGIN_PAGE themselves:
778 	 * we do it here to handle polygons (trapezoid, parallelogram,
779 	 * triangle), which don't go through fill_path.
780 	 */
781 	CHECK_BEGIN_PAGE(pdev);
782     }
783     pdev->path_state.num_points = 0;
784     pdev->path_state.move = 0;
785     if (type & gx_path_type_clip) {
786 	/*
787 	 * This approach doesn't work for clip + fill or stroke, but that
788 	 * combination can't occur.
789 	 */
790 	stream *s = gdev_vector_stream(vdev);
791 
792 	stream_puts(s, "Q q\n");
793 	gdev_vector_reset(vdev);
794         if (s->end_status == ERRC)
795             return_error(gs_error_ioerror);
796     }
797     return 0;
798 }
799 
800 private int
psw_moveto(gx_device_vector * vdev,floatp x0,floatp y0,floatp x,floatp y,gx_path_type_t type)801 psw_moveto(gx_device_vector * vdev, floatp x0, floatp y0, floatp x, floatp y,
802 	   gx_path_type_t type)
803 {
804     stream *s = gdev_vector_stream(vdev);
805     gx_device_pswrite *const pdev = (gx_device_pswrite *)vdev;
806 
807     if (pdev->path_state.num_points > pdev->path_state.move)
808 	stream_puts(s, (pdev->path_state.move ? "P\n" : "p\n"));
809     else if (pdev->path_state.move) {
810 	/*
811 	 * Two consecutive movetos -- possible only if a zero-length line
812 	 * was discarded.
813 	 */
814 	stream_puts(s, "pop pop\n");
815     }
816     print_coord2(s, x, y, NULL);
817     pdev->path_state.num_points = 1;
818     pdev->path_state.move = 1;
819     if (s->end_status == ERRC)
820         return_error(gs_error_ioerror);
821     return 0;
822 }
823 
824 private int
psw_lineto(gx_device_vector * vdev,floatp x0,floatp y0,floatp x,floatp y,gx_path_type_t type)825 psw_lineto(gx_device_vector * vdev, floatp x0, floatp y0, floatp x, floatp y,
826 	   gx_path_type_t type)
827 {
828     double dx = x - x0, dy = y - y0;
829 
830     /*
831      * Omit null lines except when stroking (so that linecap works).
832      ****** MAYBE WRONG IF PATH CONSISTS ONLY OF NULL LINES. ******
833      */
834     if ((type & gx_path_type_stroke) || dx != 0 || dy != 0) {
835 	stream *s = gdev_vector_stream(vdev);
836 	gx_device_pswrite *const pdev = (gx_device_pswrite *)vdev;
837 
838 	if (pdev->path_state.num_points > MAXOPSTACK / 2 - 10) {
839  	    stream_puts(s, (pdev->path_state.move ? "P\n" : "p\n"));
840             pdev->path_state.num_points = 0;
841             pdev->path_state.move = 0;
842         }
843         else if (pdev->path_state.num_points > 0 &&
844 	    !(pdev->path_state.num_points & 7)
845 	    )
846 	    stream_putc(s, '\n');	/* limit line length for DSC compliance */
847 	if (pdev->path_state.num_points - pdev->path_state.move >= 2 &&
848 	    dx == -pdev->path_state.dprev[1].x &&
849 	    dy == -pdev->path_state.dprev[1].y
850 	    )
851 	    stream_puts(s, "^ ");
852 	else
853 	    print_coord2(s, dx, dy, NULL);
854 	pdev->path_state.num_points++;
855 	pdev->path_state.dprev[1] = pdev->path_state.dprev[0];
856 	pdev->path_state.dprev[0].x = dx;
857 	pdev->path_state.dprev[0].y = dy;
858         if (s->end_status == ERRC)
859             return_error(gs_error_ioerror);
860     }
861     return 0;
862 }
863 
864 private int
psw_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)865 psw_curveto(gx_device_vector * vdev, floatp x0, floatp y0,
866 	    floatp x1, floatp y1, floatp x2, floatp y2, floatp x3, floatp y3,
867 	    gx_path_type_t type)
868 {
869     stream *s = gdev_vector_stream(vdev);
870     double dx1 = x1 - x0, dy1 = y1 - y0;
871     double dx2 = x2 - x0, dy2 = y2 - y0;
872     double dx3 = x3 - x0, dy3 = y3 - y0;
873     gx_device_pswrite *const pdev = (gx_device_pswrite *)vdev;
874 
875     if (pdev->path_state.num_points > 0)
876 	stream_puts(s, (pdev->path_state.move ?
877 		  (pdev->path_state.num_points == 1 ? "m\n" : "P\n") :
878 		  "p\n"));
879     if (dx1 == 0 && dy1 == 0) {
880 	print_coord2(s, dx2, dy2, NULL);
881 	print_coord2(s, dx3, dy3, "v\n");
882     } else if (x3 == x2 && y3 == y2) {
883 	print_coord2(s, dx1, dy1, NULL);
884 	print_coord2(s, dx2, dy2, "y\n");
885     } else {
886 	print_coord2(s, dx1, dy1, NULL);
887 	print_coord2(s, dx2, dy2, NULL);
888 	print_coord2(s, dx3, dy3, "c\n");
889     }
890     pdev->path_state.num_points = 0;
891     pdev->path_state.move = 0;
892     if (s->end_status == ERRC)
893         return_error(gs_error_ioerror);
894     return 0;
895 }
896 
897 private int
psw_closepath(gx_device_vector * vdev,floatp x0,floatp y0,floatp x_start,floatp y_start,gx_path_type_t type)898 psw_closepath(gx_device_vector * vdev, floatp x0, floatp y0,
899 	      floatp x_start, floatp y_start, gx_path_type_t type)
900 {
901     gx_device_pswrite *const pdev = (gx_device_pswrite *)vdev;
902 
903     stream_puts(gdev_vector_stream(vdev),
904 	  (pdev->path_state.num_points > 0 && pdev->path_state.move ?
905 	   "H\n" : "h\n"));
906     pdev->path_state.num_points = 0;
907     pdev->path_state.move = 0;
908     if ((gdev_vector_stream(vdev))->end_status == ERRC)
909         return_error(gs_error_ioerror);
910     return 0;
911 }
912 
913 private int
psw_endpath(gx_device_vector * vdev,gx_path_type_t type)914 psw_endpath(gx_device_vector * vdev, gx_path_type_t type)
915 {
916     stream *s = vdev->strm;
917     const char *star = (type & gx_path_type_even_odd ? "*" : "");
918     gx_device_pswrite *const pdev = (gx_device_pswrite *)vdev;
919 
920     if (pdev->path_state.num_points > 0 && !pdev->path_state.move)
921 	stream_puts(s, "p ");
922     if (type & gx_path_type_fill) {
923 	if (type & (gx_path_type_stroke | gx_path_type_clip))
924 	    pprints1(s, "q f%s Q ", star);
925 	else
926 	    pprints1(s, "f%s\n", star);
927     }
928     if (type & gx_path_type_stroke) {
929 	if (type & gx_path_type_clip)
930 	    stream_puts(s, "q S Q ");
931 	else
932 	    stream_puts(s, "S\n");
933     }
934     if (type & gx_path_type_clip)
935 	pprints1(s, "Y%s\n", star);
936     if (s->end_status == ERRC)
937         return_error(gs_error_ioerror);
938     return 0;
939 }
940 
941 /* ---------------- Driver procedures ---------------- */
942 
943 /* ------ Open/close/page ------ */
944 
945 /* Open the device. */
946 private int
psw_open(gx_device * dev)947 psw_open(gx_device * dev)
948 {
949     gs_memory_t *mem = gs_memory_stable(dev->memory);
950     gx_device_vector *const vdev = (gx_device_vector *)dev;
951     gx_device_pswrite *const pdev = (gx_device_pswrite *)vdev;
952 
953     vdev->v_memory = mem;
954     vdev->vec_procs = &psw_vector_procs;
955 
956     gdev_vector_init(vdev);
957     vdev->fill_options = vdev->stroke_options = gx_path_type_optimize;
958     pdev->binary_ok = !pdev->params.ASCII85EncodePages;
959     pdev->image_writer = gs_alloc_struct(mem, psdf_binary_writer,
960 					 &st_psdf_binary_writer,
961 					 "psw_open(image_writer)");
962     memset(pdev->image_writer, 0, sizeof(*pdev->image_writer));  /* for GC */
963     image_cache_reset(pdev);
964 
965     pdev->strm = NULL;
966 
967     /* if (ppdev->OpenOutputFile) */
968     {
969 	int code = psw_open_printer(dev);
970 
971 	if (code < 0)
972 	    return code;
973     }
974 
975     return 0;
976 }
977 
978 /* Wrap up ("output") a page. */
979 private int
psw_output_page(gx_device * dev,int num_copies,int flush)980 psw_output_page(gx_device * dev, int num_copies, int flush)
981 {
982     int code;
983     gx_device_vector *const vdev = (gx_device_vector *)dev;
984     gx_device_pswrite *const pdev = (gx_device_pswrite *)vdev;
985     stream *s = gdev_vector_stream(vdev);
986 
987     /* Check for a legitimate empty page. */
988     CHECK_BEGIN_PAGE(pdev);
989     sflush(s);			/* sync stream and file */
990     code = psw_write_page_trailer(vdev->file, num_copies, flush);
991     if(code < 0)
992         return code;
993     vdev->in_page = false;
994     pdev->first_page = false;
995     gdev_vector_reset(vdev);
996     image_cache_reset(pdev);
997     if (ferror(vdev->file))
998 	return_error(gs_error_ioerror);
999 
1000     dev->PageCount ++;
1001     if (psw_is_separate_pages(vdev)) {
1002 	code = psw_close_printer(dev);
1003 
1004 	if (code < 0)
1005 	    return code;
1006     }
1007     return 0;
1008 }
1009 
1010 /* Close the device. */
1011 /* Note that if this is being called as a result of finalization, */
1012 /* the stream may have been finalized; but the file will still be open. */
1013 private int
psw_close(gx_device * dev)1014 psw_close(gx_device * dev)
1015 {
1016     gx_device_vector *const vdev = (gx_device_vector *)dev;
1017     gx_device_pswrite *const pdev = (gx_device_pswrite *)vdev;
1018 
1019     gs_free_object(pdev->v_memory, pdev->image_writer,
1020 		   "psw_close(image_writer)");
1021     pdev->image_writer = 0;
1022 
1023     if (vdev->strm != NULL) {
1024 	int code = psw_close_printer(dev);
1025 
1026 	if (code < 0)
1027 	    return code;
1028     }
1029 
1030     return 0;
1031 }
1032 
1033 /* ---------------- Get/put parameters ---------------- */
1034 
1035 /* Get parameters. */
1036 private int
psw_get_params(gx_device * dev,gs_param_list * plist)1037 psw_get_params(gx_device * dev, gs_param_list * plist)
1038 {
1039     gx_device_pswrite *const pdev = (gx_device_pswrite *)dev;
1040     int code = gdev_psdf_get_params(dev, plist);
1041     int ecode;
1042 
1043     if (code < 0)
1044 	return code;
1045     if ((ecode = param_write_float(plist, "LanguageLevel", &pdev->pswrite_common.LanguageLevel)) < 0)
1046 	return ecode;
1047     return code;
1048 }
1049 
1050 /* Put parameters. */
1051 private int
psw_put_params(gx_device * dev,gs_param_list * plist)1052 psw_put_params(gx_device * dev, gs_param_list * plist)
1053 {
1054     int ecode = 0;
1055     int code;
1056     gs_param_name param_name;
1057     gx_device_pswrite *const pdev = (gx_device_pswrite *)dev;
1058     float ll = pdev->pswrite_common.LanguageLevel;
1059     psdf_version save_version = pdev->version;
1060 
1061     switch (code = param_read_float(plist, (param_name = "LanguageLevel"), &ll)) {
1062 	case 0:
1063 	    if (ll == 1.0 || ll == 1.5 || ll == 2.0 || ll == 3.0)
1064 		break;
1065 	    code = gs_error_rangecheck;
1066 	default:
1067 	    ecode = code;
1068 	    param_signal_error(plist, param_name, ecode);
1069 	case 1:
1070 	    ;
1071     }
1072 
1073     if (ecode < 0)
1074 	return ecode;
1075     /*
1076      * We have to set version to the new value, because the set of
1077      * legal parameter values for psdf_put_params varies according to
1078      * the version.
1079      */
1080     {
1081 	static const psdf_version vv[3] =
1082 	{
1083 	    psdf_version_level1, psdf_version_level1_color,
1084 	    psdf_version_level2
1085 	};
1086 
1087 	pdev->version = vv[(int)(ll * 2) - 2];
1088     }
1089     code = gdev_psdf_put_params(dev, plist);
1090     if (code < 0) {
1091 	pdev->version = save_version;
1092 	return code;
1093     }
1094     pdev->pswrite_common.LanguageLevel = ll;
1095     return code;
1096 }
1097 
1098 /* ---------------- Rectangles ---------------- */
1099 
1100 private int
psw_fill_rectangle(gx_device * dev,int x,int y,int w,int h,gx_color_index color)1101 psw_fill_rectangle(gx_device * dev, int x, int y, int w, int h,
1102 		   gx_color_index color)
1103 {
1104     gx_device_pswrite *const pdev = (gx_device_pswrite *)dev;
1105 
1106     /*
1107      * If the transfer function doesn't map 1 setgray to device white,
1108      * the first rectangle fill on a page (from erasepage) will be with
1109      * some color other than white, which gdev_vector_fill_rectangle
1110      * won't handle correctly.  Note that this doesn't happen on the
1111      * very first page of a document.
1112      */
1113     if (!pdev->in_page && !pdev->first_page) {
1114 	if (pdev->page_fill.color == gx_no_color_index) {
1115 	    /* Save, but don't output, the erasepage. */
1116 	    pdev->page_fill.rect.p.x = x;
1117 	    pdev->page_fill.rect.p.y = y;
1118 	    pdev->page_fill.rect.q.x = x + w;
1119 	    pdev->page_fill.rect.q.y = y + h;
1120 	    pdev->page_fill.color = color;
1121 	    return 0;
1122 	}
1123     }
1124     return gdev_vector_fill_rectangle(dev, x, y, w, h, color);
1125 }
1126 
1127 /*
1128  * Open the printer's output file if necessary.
1129  */
1130 
1131 private int
psw_open_printer(gx_device * dev)1132 psw_open_printer(gx_device * dev)
1133 {
1134     gx_device_vector *const vdev = (gx_device_vector *)dev;
1135     gx_device_pswrite *const pdev = (gx_device_pswrite *)vdev;
1136 
1137     if (vdev->strm != 0) {
1138 	return 0;
1139     }
1140     {
1141 	int code = gdev_vector_open_file_options(vdev, 512,
1142 					VECTOR_OPEN_FILE_SEQUENTIAL_OK |
1143 					VECTOR_OPEN_FILE_BBOX);
1144 
1145 	if (code < 0)
1146 	    return code;
1147     }
1148 
1149     pdev->first_page = true;
1150 
1151     return 0;
1152 }
1153 
1154 /*
1155  * Close the printer's output file.
1156  */
1157 
1158 private int
psw_close_printer(gx_device * dev)1159 psw_close_printer(gx_device * dev)
1160 {
1161     int code;
1162     gx_device_vector *const vdev = (gx_device_vector *)dev;
1163     gx_device_pswrite *const pdev = (gx_device_pswrite *)vdev;
1164     FILE *f = vdev->file;
1165     gs_rect bbox;
1166 
1167     gx_device_bbox_bbox(vdev->bbox_device, &bbox);
1168     if (pdev->first_page & !vdev->in_page) {
1169 	/* Nothing has been written.  Write the file header now. */
1170 	code = psw_begin_file(pdev, &bbox);
1171         if (code < 0)
1172             return code;
1173     } else {
1174 	/* If there is an incomplete page, complete it now. */
1175 	if (vdev->in_page) {
1176 	    /*
1177 	     * Flush the stream after writing page trailer.
1178 	     */
1179 
1180 	    stream *s = vdev->strm;
1181 	    code = psw_write_page_trailer(vdev->file, 1, 1);
1182             if(code < 0)
1183                 return code;
1184 	    sflush(s);
1185 
1186 	    dev->PageCount++;
1187 	}
1188     }
1189     code = psw_end_file(f, dev, &pdev->pswrite_common, &bbox,
1190                  (psw_is_separate_pages(vdev) ? 1 : vdev->PageCount));
1191     if(code < 0)
1192         return code;
1193 
1194     return gdev_vector_close_file(vdev);
1195 }
1196 
1197 /* ---------------- Images ---------------- */
1198 
1199 /* Copy a monochrome bitmap. */
1200 private int
psw_copy_mono(gx_device * dev,const byte * data,int data_x,int raster,gx_bitmap_id id,int x,int y,int w,int h,gx_color_index zero,gx_color_index one)1201 psw_copy_mono(gx_device * dev, const byte * data,
1202 	int data_x, int raster, gx_bitmap_id id, int x, int y, int w, int h,
1203 	      gx_color_index zero, gx_color_index one)
1204 {
1205     gx_device_vector *const vdev = (gx_device_vector *)dev;
1206     gx_device_pswrite *const pdev = (gx_device_pswrite *)vdev;
1207     gx_drawing_color color;
1208     const char *op;
1209     int code = 0;
1210 
1211     CHECK_BEGIN_PAGE(pdev);
1212     if (w <= 0 || h <= 0)
1213 	return 0;
1214     (*dev_proc(vdev->bbox_device, copy_mono))
1215 	((gx_device *) vdev->bbox_device, data, data_x, raster, id,
1216 	 x, y, w, h, zero, one);
1217     if (one == gx_no_color_index) {
1218 	set_nonclient_dev_color(&color, zero);
1219 	code = gdev_vector_update_fill_color((gx_device_vector *) pdev,
1220 					     NULL, &color);
1221 	op = "If";
1222     } else if (zero == vdev->black && one == vdev->white)
1223 	op = "1 I";
1224     else {
1225 	if (zero != gx_no_color_index) {
1226 	    code = (*dev_proc(dev, fill_rectangle)) (dev, x, y, w, h, zero);
1227 	    if (code < 0)
1228 		return code;
1229 	}
1230 	set_nonclient_dev_color(&color, one);
1231 	code = gdev_vector_update_fill_color((gx_device_vector *) pdev,
1232 					     NULL, &color);
1233 	op = ",";
1234     }
1235     if (code < 0)
1236 	return 0;
1237     code = gdev_vector_update_clip_path(vdev, NULL);
1238     if (code < 0)
1239 	return code;
1240     return psw_image_write(pdev, op, data, data_x, raster, id,
1241 			   x, y, w, h, 1);
1242 }
1243 
1244 /* Copy a color bitmap. */
1245 private int
psw_copy_color(gx_device * dev,const byte * data,int data_x,int raster,gx_bitmap_id id,int x,int y,int w,int h)1246 psw_copy_color(gx_device * dev,
1247 	       const byte * data, int data_x, int raster, gx_bitmap_id id,
1248 	       int x, int y, int w, int h)
1249 {
1250     int depth = dev->color_info.depth;
1251     const byte *bits = data + data_x * 3;
1252     char op[6];
1253     int code;
1254     gx_device_vector *const vdev = (gx_device_vector *)dev;
1255     gx_device_pswrite *const pdev = (gx_device_pswrite *)vdev;
1256 
1257     CHECK_BEGIN_PAGE(pdev);
1258     if (w <= 0 || h <= 0)
1259 	return 0;
1260     (*dev_proc(vdev->bbox_device, copy_color))
1261 	((gx_device *) vdev->bbox_device, data, data_x, raster, id,
1262 	 x, y, w, h);
1263     /*
1264      * If this is a 1-pixel-high image, check for it being all the
1265      * same color, and if so, fill it as a rectangle.
1266      */
1267     if (h == 1 && !memcmp(bits, bits + 3, (w - 1) * 3)) {
1268 	return (*dev_proc(dev, fill_rectangle))
1269 	    (dev, x, y, w, h, (bits[0] << 16) + (bits[1] << 8) + bits[2]);
1270     }
1271     sprintf(op, "%d Ic", depth / 3);	/* RGB */
1272     code = gdev_vector_update_clip_path(vdev, NULL);
1273     if (code < 0)
1274 	return code;
1275     return psw_image_write(pdev, op, data, data_x, raster, id,
1276 			   x, y, w, h, depth);
1277 }
1278 
1279 /* Fill or stroke a path. */
1280 /* We redefine these to skip empty paths, and to allow optimization. */
1281 private int
psw_fill_path(gx_device * dev,const gs_imager_state * pis,gx_path * ppath,const gx_fill_params * params,const gx_device_color * pdevc,const gx_clip_path * pcpath)1282 psw_fill_path(gx_device * dev, const gs_imager_state * pis,
1283 	      gx_path * ppath, const gx_fill_params * params,
1284 	      const gx_device_color * pdevc, const gx_clip_path * pcpath)
1285 {
1286     CHECK_BEGIN_PAGE((gx_device_pswrite *)dev);
1287     if (gx_path_is_void(ppath))
1288 	return 0;
1289     /* Update the clipping path now. */
1290     gdev_vector_update_clip_path((gx_device_vector *)dev, pcpath);
1291     return gdev_vector_fill_path(dev, pis, ppath, params, pdevc, pcpath);
1292 }
1293 private int
psw_stroke_path(gx_device * dev,const gs_imager_state * pis,gx_path * ppath,const gx_stroke_params * params,const gx_device_color * pdcolor,const gx_clip_path * pcpath)1294 psw_stroke_path(gx_device * dev, const gs_imager_state * pis,
1295 		gx_path * ppath, const gx_stroke_params * params,
1296 		const gx_device_color * pdcolor, const gx_clip_path * pcpath)
1297 {
1298     gx_device_vector *const vdev = (gx_device_vector *)dev;
1299 
1300     CHECK_BEGIN_PAGE((gx_device_pswrite *)dev);
1301     if (gx_path_is_void(ppath) &&
1302 	(gx_path_is_null(ppath) ||
1303 	 gs_currentlinecap((const gs_state *)pis) != gs_cap_round)
1304 	)
1305 	return 0;
1306     /* Update the clipping path now. */
1307     gdev_vector_update_clip_path(vdev, pcpath);
1308     /* Do the right thing for oddly transformed coordinate systems.... */
1309     {
1310 	gx_device_pswrite *const pdev = (gx_device_pswrite *)vdev;
1311 	stream *s;
1312 	int code;
1313 	double scale;
1314 	bool set_ctm;
1315 	gs_matrix mat;
1316 
1317 	if (!gx_dc_is_pure(pdcolor))
1318 	    return gx_default_stroke_path(dev, pis, ppath, params, pdcolor,
1319 					  pcpath);
1320 	set_ctm = (bool)gdev_vector_stroke_scaling(vdev, pis, &scale, &mat);
1321 	gdev_vector_update_clip_path(vdev, pcpath);
1322 	gdev_vector_prepare_stroke((gx_device_vector *)pdev, pis, params,
1323 				   pdcolor, scale);
1324 	s = pdev->strm;
1325 	if (set_ctm) {
1326 	    stream_puts(s, "q");
1327 	    if (is_fzero2(mat.xy, mat.yx) && is_fzero2(mat.tx, mat.ty))
1328 		pprintg2(s, " %g %g scale\n", mat.xx, mat.yy);
1329 	    else {
1330 		psw_put_matrix(s, &mat);
1331 		stream_puts(s, "concat\n");
1332 	    }
1333             if (s->end_status == ERRC)
1334                 return_error(gs_error_ioerror);
1335         }
1336 	code = gdev_vector_dopath(vdev, ppath, gx_path_type_stroke,
1337 				  (set_ctm ? &mat : (const gs_matrix *)0));
1338 	if (code < 0)
1339 	    return code;
1340 	if (set_ctm)
1341 	    stream_puts(s, "Q\n");
1342     }
1343     /* We must merge in the bounding box explicitly. */
1344     return (vdev->bbox_device == 0 ? 0 :
1345 	    dev_proc(vdev->bbox_device, stroke_path)
1346 	      ((gx_device *)vdev->bbox_device, pis, ppath, params,
1347 	       pdcolor, pcpath));
1348 }
1349 
1350 /* Fill a mask. */
1351 private int
psw_fill_mask(gx_device * dev,const byte * data,int data_x,int raster,gx_bitmap_id id,int x,int y,int w,int h,const gx_drawing_color * pdcolor,int depth,gs_logical_operation_t lop,const gx_clip_path * pcpath)1352 psw_fill_mask(gx_device * dev,
1353 	      const byte * data, int data_x, int raster, gx_bitmap_id id,
1354 	      int x, int y, int w, int h,
1355 	      const gx_drawing_color * pdcolor, int depth,
1356 	      gs_logical_operation_t lop, const gx_clip_path * pcpath)
1357 {
1358     gx_device_vector *const vdev = (gx_device_vector *)dev;
1359     gx_device_pswrite *const pdev = (gx_device_pswrite *)vdev;
1360 
1361     CHECK_BEGIN_PAGE(pdev);
1362     if (w <= 0 || h <= 0)
1363 	return 0;
1364 
1365     /* gdev_vector_update_clip_path may output a grestore and gsave,
1366      * causing the setting of the color to be lost.  Therefore, we
1367      * must update the clip path first.
1368      */
1369     if (depth > 1 ||
1370 	gdev_vector_update_clip_path(vdev, pcpath) < 0 ||
1371 	gdev_vector_update_fill_color(vdev, NULL, pdcolor) < 0 ||
1372 	gdev_vector_update_log_op(vdev, lop) < 0
1373 	)
1374 	return gx_default_fill_mask(dev, data, data_x, raster, id,
1375 				    x, y, w, h, pdcolor, depth, lop, pcpath);
1376     (*dev_proc(vdev->bbox_device, fill_mask))
1377 	((gx_device *) vdev->bbox_device, data, data_x, raster, id,
1378 	 x, y, w, h, pdcolor, depth, lop, pcpath);
1379     /* Update the clipping path now. */
1380     gdev_vector_update_clip_path(vdev, pcpath);
1381     return psw_image_write(pdev, ",", data, data_x, raster, id,
1382 			   x, y, w, h, 1);
1383 }
1384 
1385 /* ---------------- High-level images ---------------- */
1386 
1387 private image_enum_proc_plane_data(psw_image_plane_data);
1388 private image_enum_proc_end_image(psw_image_end_image);
1389 private const gx_image_enum_procs_t psw_image_enum_procs = {
1390     psw_image_plane_data, psw_image_end_image
1391 };
1392 
1393 /* Start processing an image. */
1394 private int
psw_begin_image(gx_device * dev,const gs_imager_state * pis,const gs_image_t * pim,gs_image_format_t format,const gs_int_rect * prect,const gx_drawing_color * pdcolor,const gx_clip_path * pcpath,gs_memory_t * mem,gx_image_enum_common_t ** pinfo)1395 psw_begin_image(gx_device * dev,
1396 		const gs_imager_state * pis, const gs_image_t * pim,
1397 		gs_image_format_t format, const gs_int_rect * prect,
1398 	      const gx_drawing_color * pdcolor, const gx_clip_path * pcpath,
1399 		gs_memory_t * mem, gx_image_enum_common_t ** pinfo)
1400 {
1401     gx_device_vector *const vdev = (gx_device_vector *)dev;
1402     gx_device_pswrite *const pdev = (gx_device_pswrite *)vdev;
1403     gdev_vector_image_enum_t *pie;
1404     const gs_color_space *pcs = pim->ColorSpace;
1405     const gs_color_space *pbcs = pcs;
1406     const char *base_name = NULL;
1407     gs_color_space_index index;
1408     int num_components;
1409     bool binary = pdev->binary_ok;
1410     byte *buffer = 0;		/* image buffer if needed */
1411     stream *bs = 0;		/* buffer stream if needed */
1412 #define MAX_IMAGE_OP 10		/* imagemask\n */
1413     int code;
1414 
1415     CHECK_BEGIN_PAGE(pdev);
1416     pie = gs_alloc_struct(mem, gdev_vector_image_enum_t,
1417 			  &st_vector_image_enum, "psw_begin_image");
1418     if (pie == 0)
1419 	return_error(gs_error_VMerror);
1420     if (prect && !(prect->p.x == 0 && prect->p.y == 0 &&
1421 		   prect->q.x == pim->Width && prect->q.y == pim->Height)
1422 	)
1423 	goto fail;
1424     switch (pim->format) {
1425     case gs_image_format_chunky:
1426     case gs_image_format_component_planar:
1427 	break;
1428     default:
1429 	goto fail;
1430     }
1431     pie->memory = mem;
1432     pie->default_info = 0;	/* not used */
1433     if (pim->ImageMask) {
1434 	index = -1;		/* bogus, not used */
1435 	num_components = 1;
1436     } else {
1437 	index = gs_color_space_get_index(pcs);
1438 	num_components = gs_color_space_num_components(pcs);
1439 	if (pim->CombineWithColor)
1440 	    goto fail;
1441 	/*
1442 	 * We can only handle Device color spaces right now, or Indexed
1443 	 * color spaces over them, and only the default Decode [0 1 ...]
1444 	 * or [0 2^BPC-1] respectively.
1445 	 */
1446 	switch (index) {
1447 	case gs_color_space_index_Indexed: {
1448 	    if (pdev->pswrite_common.LanguageLevel < 2 || pcs->params.indexed.use_proc ||
1449 		pim->Decode[0] != 0 ||
1450 		pim->Decode[1] != (1 << pim->BitsPerComponent) - 1
1451 		) {
1452 		goto fail;
1453 	    }
1454 	    pbcs = (const gs_color_space *)&pcs->params.indexed.base_space;
1455 	    switch (gs_color_space_get_index(pbcs)) {
1456 	    case gs_color_space_index_DeviceGray:
1457 		base_name = "DeviceGray"; break;
1458 	    case gs_color_space_index_DeviceRGB:
1459 		base_name = "DeviceRGB"; break;
1460 	    case gs_color_space_index_DeviceCMYK:
1461 		base_name = "DeviceCMYK"; break;
1462 	    default:
1463 		goto fail;
1464 	    }
1465 	    break;
1466 	}
1467 	case gs_color_space_index_DeviceGray:
1468 	case gs_color_space_index_DeviceRGB:
1469 	case gs_color_space_index_DeviceCMYK: {
1470 	    int i;
1471 
1472 	    for (i = 0; i < num_components * 2; ++i)
1473 		if (pim->Decode[i] != (i & 1))
1474 		    goto fail;
1475 	    break;
1476 	}
1477 	default:
1478 	    goto fail;
1479 	}
1480     }
1481     if (pdev->pswrite_common.LanguageLevel < 2 && !pim->ImageMask) {
1482 	/*
1483 	 * Restrict ourselves to Level 1 images: bits per component <= 8,
1484 	 * not indexed.
1485 	 */
1486 	if (pim->BitsPerComponent > 8 || pbcs != pcs)
1487 	    goto fail;
1488     }
1489     if (gdev_vector_begin_image(vdev, pis, pim, format, prect, pdcolor,
1490 				pcpath, mem, &psw_image_enum_procs, pie) < 0)
1491 	goto fail;
1492     if (binary) {
1493 	/*
1494 	 * We need to buffer the entire image in memory.  Currently, the
1495 	 * only reason for this is the infamous "short image" problem: the
1496 	 * image may actually have fewer rows than its height specifies.  If
1497 	 * it weren't for that, we could know the size of the binary data in
1498 	 * advance.  However, this will change if we compress images.
1499 	 */
1500 	uint bsize = MAX_IMAGE_OP +
1501 	    ((pie->bits_per_row + 7) >> 3) * pie->height;
1502 
1503 	buffer = gs_alloc_bytes(mem, bsize, "psw_begin_image(buffer)");
1504 	bs = s_alloc(mem, "psw_begin_image(buffer stream)");
1505 	if (buffer && bs) {
1506 	    swrite_string(bs, buffer, bsize);
1507 	} else {
1508 	    /* An allocation failed. */
1509 	    gs_free_object(mem, bs, "psw_begin_image(buffer stream)");
1510 	    gs_free_object(mem, buffer, "psw_begin_image(buffer)");
1511 	    /*
1512 	     * Rather than returning VMerror, we fall back to an ASCII
1513 	     * encoding, which doesn't require a buffer stream.
1514 	     */
1515 	    buffer = 0;
1516 	    bs = 0;
1517 	    binary = false;
1518 	}
1519     }
1520     if (binary) {
1521 	/* Set up the image stream to write into the buffer. */
1522 	stream *save = pdev->strm;
1523 
1524 	pdev->strm = bs;
1525 	code = psw_image_stream_setup(pdev, true);
1526 	pdev->strm = save;
1527     } else {
1528 	code = psw_image_stream_setup(pdev, false);
1529     }
1530     if (code < 0)
1531 	goto fail;
1532     /* Update the clipping path now. */
1533     gdev_vector_update_clip_path(vdev, pcpath);
1534     /* Write the image/colorimage/imagemask preamble. */
1535     {
1536 	stream *s = gdev_vector_stream((gx_device_vector *) pdev);
1537 	const char *source = (code ? "@X" : "@");
1538 	gs_matrix imat;
1539 	const char *op;
1540 
1541 	stream_puts(s, "q");
1542 	(*dev_proc(dev, get_initial_matrix)) (dev, &imat);
1543 	gs_matrix_scale(&imat, 72.0 / dev->HWResolution[0],
1544 			72.0 / dev->HWResolution[1], &imat);
1545 	gs_matrix_invert(&imat, &imat);
1546 	gs_matrix_multiply(&ctm_only(pis), &imat, &imat);
1547 	psw_put_matrix(s, &imat);
1548 	pprintd2(s, "concat\n%d %d ", pie->width, pie->height);
1549 	if (pim->ImageMask) {
1550 	    stream_puts(s, (pim->Decode[0] == 0 ? "false" : "true"));
1551 	    psw_put_matrix(s, &pim->ImageMatrix);
1552 	    stream_puts(s, source);
1553 	    op = "imagemask";
1554 	} else {
1555 	    pprintd1(s, "%d", pim->BitsPerComponent);
1556 	    psw_put_matrix(s, &pim->ImageMatrix);
1557 	    if (pbcs != pcs) {
1558 		/* This is an Indexed color space. */
1559 		pprints1(s, "[/Indexed /%s ", base_name);
1560 		pprintd1(s, "%d\n", pcs->params.indexed.hival);
1561 		/*
1562 		 * Don't write the table in binary: it might interfere
1563 		 * with DSC parsing.
1564 		 */
1565 		s_write_ps_string(s, pcs->params.indexed.lookup.table.data,
1566 				  pcs->params.indexed.lookup.table.size,
1567 				  PRINT_ASCII85_OK);
1568 		pprintd1(s, "\n]setcolorspace[0 %d]", (int)pim->Decode[1]);
1569 		pprints2(s, "%s %s",
1570 			 (pim->Interpolate ? "true" : "false"), source);
1571 		op = "IC";
1572 	    } else if (index == gs_color_space_index_DeviceGray) {
1573 		stream_puts(s, source);
1574 		op = "image";
1575 	    } else {
1576 		if (format == gs_image_format_chunky)
1577 		    pprints1(s, "%s false", source);
1578 		else {
1579 		    /* We have to use procedures. */
1580 		    stream_puts(s, source);
1581 		    pprintd2(s, " %d %d B",
1582 			     (pim->Width * pim->BitsPerComponent + 7) >> 3,
1583 			     num_components);
1584 		}
1585 		pprintd1(s, " %d", num_components);
1586 		op = "colorimage";
1587 	    }
1588 	}
1589 	stream_putc(s, '\n');
1590 	pprints1((bs ? bs : s), "%s\n", op);
1591         if (s->end_status == ERRC) {
1592             gs_free_object(mem, bs, "psw_begin_image(buffer stream)");
1593             gs_free_object(mem, buffer, "psw_begin_image(buffer)");
1594             gs_free_object(mem, pie, "psw_begin_image");
1595             return_error(gs_error_ioerror);
1596         }
1597     }
1598     *pinfo = (gx_image_enum_common_t *) pie;
1599     return 0;
1600  fail:
1601     gs_free_object(mem, bs, "psw_begin_image(buffer stream)");
1602     gs_free_object(mem, buffer, "psw_begin_image(buffer)");
1603     gs_free_object(mem, pie, "psw_begin_image");
1604     return gx_default_begin_image(dev, pis, pim, format, prect,
1605 				  pdcolor, pcpath, mem, pinfo);
1606 }
1607 
1608 /* Process the next piece of an image. */
1609 private int
psw_image_plane_data(gx_image_enum_common_t * info,const gx_image_plane_t * planes,int height,int * rows_used)1610 psw_image_plane_data(gx_image_enum_common_t * info,
1611 		     const gx_image_plane_t * planes, int height,
1612 		     int *rows_used)
1613 {
1614     gx_device *dev = info->dev;
1615     gx_device_pswrite *const pdev = (gx_device_pswrite *)dev;
1616     gdev_vector_image_enum_t *pie = (gdev_vector_image_enum_t *) info;
1617     int code =
1618 	gx_image_plane_data_rows(pie->bbox_info, planes, height, rows_used);
1619     int pi;
1620 
1621     for (pi = 0; pi < pie->num_planes; ++pi) {
1622 	if (pie->bits_per_row != pie->width * info->plane_depths[pi])
1623 	    return_error(gs_error_rangecheck);
1624 	psw_put_bits(pdev->image_stream, planes[pi].data,
1625 		     planes[pi].data_x * info->plane_depths[pi],
1626 		     planes[pi].raster, pie->bits_per_row,
1627 		     *rows_used);
1628         if (pdev->image_stream->end_status == ERRC)
1629             return_error(gs_error_ioerror);
1630     }
1631     pie->y += *rows_used;
1632     return code;
1633 }
1634 
1635 /* Clean up by releasing the buffers. */
1636 private int
psw_image_end_image(gx_image_enum_common_t * info,bool draw_last)1637 psw_image_end_image(gx_image_enum_common_t * info, bool draw_last)
1638 {
1639     gx_device *dev = info->dev;
1640     gx_device_vector *const vdev = (gx_device_vector *)dev;
1641     gx_device_pswrite *const pdev = (gx_device_pswrite *)vdev;
1642     gdev_vector_image_enum_t *pie = (gdev_vector_image_enum_t *) info;
1643     int code;
1644 
1645     code = gdev_vector_end_image(vdev, pie, draw_last, pdev->white);
1646     if (code > 0) {
1647 	stream *s = pdev->strm;
1648 	stream *bs = pdev->image_stream;
1649 
1650 	/* If we were buffering a binary image, write it now. */
1651 	while (bs != s && bs->strm != 0)
1652 	    bs = bs->strm;
1653 	psw_image_cleanup(pdev);
1654 	if (bs != s) {
1655 	    /*
1656 	     * We were buffering a binary image.  Write it now, with the
1657 	     * DSC comments.
1658 	     */
1659 	    gs_memory_t *mem = bs->memory;
1660 	    byte *buffer = bs->cbuf;
1661 	    long len = stell(bs);
1662 	    uint ignore;
1663 
1664 	    pprintld1(s, "%%%%BeginData: %ld\n", len);
1665 	    sputs(s, buffer, (uint)len, &ignore);
1666 	    stream_puts(s, "\n%%EndData");
1667 	    /* Free the buffer and its stream. */
1668 	    gs_free_object(mem, bs, "psw_image_end_image(buffer stream)");
1669 	    gs_free_object(mem, buffer, "psw_image_end_image(buffer)");
1670 	}
1671 	stream_puts(s, "\nQ\n");
1672         if (s->end_status == ERRC)
1673             return_error(gs_error_ioerror);
1674     }
1675     return code;
1676 }
1677