xref: /plan9/sys/src/cmd/gs/src/gdevvec.h (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
1 /* Copyright (C) 1997, 1998, 1999, 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: gdevvec.h,v 1.16 2005/01/28 19:11:07 igor Exp $ */
18 /* Common definitions for "vector" devices */
19 
20 #ifndef gdevvec_INCLUDED
21 #  define gdevvec_INCLUDED
22 
23 #include "gp.h"			/* for gp_file_name_sizeof */
24 #include "gsropt.h"
25 #include "gxdevice.h"
26 #include "gdevbbox.h"
27 #include "gxiparam.h"
28 #include "gxistate.h"
29 #include "gxhldevc.h"
30 #include "stream.h"
31 
32 /*
33  * "Vector" devices produce a stream of higher-level drawing commands rather
34  * than a raster image.  (We don't like the term "vector", since the command
35  * vocabulary typically includes text and raster images as well as actual
36  * vectors, but it's widely used in the industry, and we weren't able to
37  * find one that read better.)  Some examples of "vector" formats are PDF,
38  * PostScript, PCL XL, HP-GL/2 + RTL, CGM, Windows Metafile, and Macintosh
39  * PICT.
40  *
41  * This file extends the basic driver structure with elements likely to be
42  * useful to vector devices.  These include:
43  *
44  *      - Tracking whether any marks have been made on the page;
45  *
46  *      - Keeping track of the page bounding box;
47  *
48  *      - A copy of the most recently written current graphics state
49  *      parameters;
50  *
51  *      - An output stream (for drivers that compress or otherwise filter
52  *      their output);
53  *
54  *      - A vector of procedures for writing changes to the graphics state.
55  *
56  *      - The ability to work with scaled output coordinate systems.
57  *
58  * We expect to add more elements and procedures as we gain more experience
59  * with this kind of driver.
60  */
61 
62 /* ================ Types and structures ================ */
63 
64 /* Define the abstract type for a vector device. */
65 typedef struct gx_device_vector_s gx_device_vector;
66 
67 /* Define the maximum size of the output file name. */
68 #define fname_size (gp_file_name_sizeof - 1)
69 
70 /* Define the longest dash pattern we can remember. */
71 #define max_dash 11
72 
73 /*
74  * Define procedures for writing common output elements.  Not all devices
75  * will support all of these elements.  Note that these procedures normally
76  * only write out commands, and don't update the driver state itself.  All
77  * of them are optional, called only as indicated under the utility
78  * procedures below.
79  */
80 typedef enum {
81     gx_path_type_none = 0,
82     /*
83      * All combinations of flags are legal.  Multiple commands are
84      * executed in the order fill, stroke, clip.
85      */
86     gx_path_type_fill = 1,
87     gx_path_type_stroke = 2,
88     gx_path_type_clip = 4,
89     gx_path_type_winding_number = 0,
90     gx_path_type_even_odd = 8,
91     gx_path_type_optimize = 16,	/* OK to optimize paths by merging seg.s */
92     gx_path_type_always_close = 32, /* include final closepath even if not stroke */
93     gx_path_type_rule = gx_path_type_winding_number | gx_path_type_even_odd
94 } gx_path_type_t;
95 typedef enum {
96     gx_rect_x_first,
97     gx_rect_y_first
98 } gx_rect_direction_t;
99 typedef struct gx_device_vector_procs_s {
100     /* Page management */
101     int (*beginpage) (gx_device_vector * vdev);
102     /* Imager state */
103     int (*setlinewidth) (gx_device_vector * vdev, floatp width);
104     int (*setlinecap) (gx_device_vector * vdev, gs_line_cap cap);
105     int (*setlinejoin) (gx_device_vector * vdev, gs_line_join join);
106     int (*setmiterlimit) (gx_device_vector * vdev, floatp limit);
107     int (*setdash) (gx_device_vector * vdev, const float *pattern,
108 		    uint count, floatp offset);
109     int (*setflat) (gx_device_vector * vdev, floatp flatness);
110     int (*setlogop) (gx_device_vector * vdev, gs_logical_operation_t lop,
111 		     gs_logical_operation_t diff);
112     /* Other state */
113     bool (*can_handle_hl_color) (gx_device_vector * vdev, const gs_imager_state * pis,
114                          const gx_drawing_color * pdc);
115     int (*setfillcolor) (gx_device_vector * vdev, const gs_imager_state * pis,
116                          const gx_drawing_color * pdc);
117     int (*setstrokecolor) (gx_device_vector * vdev, const gs_imager_state * pis,
118                            const gx_drawing_color * pdc);
119     /* Paths */
120     /* dopath and dorect are normally defaulted */
121     int (*dopath) (gx_device_vector * vdev, const gx_path * ppath,
122 		   gx_path_type_t type, const gs_matrix *pmat);
123     int (*dorect) (gx_device_vector * vdev, fixed x0, fixed y0, fixed x1,
124 		   fixed y1, gx_path_type_t type);
125     int (*beginpath) (gx_device_vector * vdev, gx_path_type_t type);
126     int (*moveto) (gx_device_vector * vdev, floatp x0, floatp y0,
127 		   floatp x, floatp y, gx_path_type_t type);
128     int (*lineto) (gx_device_vector * vdev, floatp x0, floatp y0,
129 		   floatp x, floatp y, gx_path_type_t type);
130     int (*curveto) (gx_device_vector * vdev, floatp x0, floatp y0,
131 		    floatp x1, floatp y1, floatp x2, floatp y2,
132 		    floatp x3, floatp y3, gx_path_type_t type);
133     int (*closepath) (gx_device_vector * vdev, floatp x0, floatp y0,
134 		      floatp x_start, floatp y_start, gx_path_type_t type);
135     int (*endpath) (gx_device_vector * vdev, gx_path_type_t type);
136 } gx_device_vector_procs;
137 
138 /* Default implementations of procedures */
139 /* setflat does nothing */
140 int gdev_vector_setflat(gx_device_vector * vdev, floatp flatness);
141 
142 /* dopath may call dorect, beginpath, moveto/lineto/curveto/closepath, */
143 /* endpath */
144 int gdev_vector_dopath(gx_device_vector * vdev, const gx_path * ppath,
145 		       gx_path_type_t type, const gs_matrix *pmat);
146 
147 /* dorect may call beginpath, moveto, lineto, closepath */
148 int gdev_vector_dorect(gx_device_vector * vdev, fixed x0, fixed y0,
149 		       fixed x1, fixed y1, gx_path_type_t type);
150 
151 /* Finally, define the extended device structure. */
152 #define gx_device_vector_common\
153 	gx_device_common;\
154 	gs_memory_t *v_memory;\
155 		/* Output element writing procedures */\
156 	const gx_device_vector_procs *vec_procs;\
157 		/* Output file */\
158 	char fname[fname_size + 1];\
159 	FILE *file;\
160 	stream *strm;\
161 	byte *strmbuf;\
162 	uint strmbuf_size;\
163 	int open_options;	/* see below */\
164 		/* Graphics state */\
165 	gs_imager_state state;\
166 	float dash_pattern[max_dash];\
167 	bool fill_used_process_color;\
168 	bool stroke_used_process_color;\
169 	gx_hl_saved_color saved_fill_color;\
170 	gx_hl_saved_color saved_stroke_color;\
171 	gs_id no_clip_path_id;	/* indicates no clipping */\
172 	gs_id clip_path_id;\
173 		/* Other state */\
174 	gx_path_type_t fill_options, stroke_options;  /* optimize */\
175 	gs_point scale;		/* device coords / scale => output coords */\
176 	bool in_page;		/* true if any marks on this page */\
177 	gx_device_bbox *bbox_device;	/* for tracking bounding box */\
178 		/* Cached values */\
179 	gx_color_index black, white
180 #define vdev_proc(vdev, p) ((vdev)->vec_procs->p)
181 
182 #define vector_initial_values\
183 	0,		/* v_memory */\
184 	0,		/* vec_procs */\
185 	 { 0 },		/* fname */\
186 	0,		/* file */\
187 	0,		/* strm */\
188 	0,		/* strmbuf */\
189 	0,		/* strmbuf_size */\
190 	0,		/* open_options */\
191 	 { 0 },		/* state */\
192 	 { 0 },		/* dash_pattern */\
193 	true,		/* fill_used_process_color */\
194 	true,		/* stroke_used_process_color */\
195 	 { 0 },		/* fill_color ****** WRONG ****** */\
196 	 { 0 },		/* stroke_color ****** WRONG ****** */\
197 	gs_no_id,	/* clip_path_id */\
198 	gs_no_id,	/* no_clip_path_id */\
199 	0, 0,		/* fill/stroke_options */\
200 	 { X_DPI/72.0, Y_DPI/72.0 },	/* scale */\
201 	0/*false*/,	/* in_page */\
202 	0,		/* bbox_device */\
203 	gx_no_color_index,	/* black */\
204 	gx_no_color_index	/* white */
205 
206 struct gx_device_vector_s {
207     gx_device_vector_common;
208 };
209 
210 /* st_device_vector is never instantiated per se, but we still need to */
211 /* extern its descriptor for the sake of subclasses. */
212 extern_st(st_device_vector);
213 #define public_st_device_vector()	/* in gdevvec.c */\
214   gs_public_st_suffix_add3_final(st_device_vector, gx_device_vector,\
215     "gx_device_vector", device_vector_enum_ptrs,\
216     device_vector_reloc_ptrs, gx_device_finalize, st_device, strm, strmbuf,\
217     bbox_device)
218 #define st_device_vector_max_ptrs (st_device_max_ptrs + 3)
219 
220 /* ================ Utility procedures ================ */
221 
222 /* Initialize the state. */
223 void gdev_vector_init(gx_device_vector * vdev);
224 
225 /* Reset the remembered graphics state. */
226 void gdev_vector_reset(gx_device_vector * vdev);
227 
228 /*
229  * Open the output file and stream, with optional bbox tracking.
230  * The options must be defined so that 0 is always the default.
231  */
232 #define VECTOR_OPEN_FILE_ASCII 1	/* open file as text, not binary */
233 #define VECTOR_OPEN_FILE_SEQUENTIAL 2	/* open as non-seekable */
234 #define VECTOR_OPEN_FILE_SEQUENTIAL_OK 4  /* open as non-seekable if */
235 					/* open as seekable fails */
236 #define VECTOR_OPEN_FILE_BBOX 8		/* also open bbox device */
237 int gdev_vector_open_file_options(gx_device_vector * vdev,
238 				  uint strmbuf_size, int open_options);
239 #define gdev_vector_open_file_bbox(vdev, bufsize, bbox)\
240   gdev_vector_open_file_options(vdev, bufsize,\
241 				(bbox ? VECTOR_OPEN_FILE_BBOX : 0))
242 #define gdev_vector_open_file(vdev, strmbuf_size)\
243   gdev_vector_open_file_bbox(vdev, strmbuf_size, false)
244 
245 /* Get the current stream, calling beginpage if in_page is false. */
246 stream *gdev_vector_stream(gx_device_vector * vdev);
247 
248 /* Bring the logical operation up to date. */
249 /* May call setlogop. */
250 int gdev_vector_update_log_op(gx_device_vector * vdev,
251 			      gs_logical_operation_t lop);
252 
253 /* Bring the fill color up to date. */
254 /* May call setfillcolor. */
255 int gdev_vector_update_fill_color(gx_device_vector * vdev,
256 				  const gs_imager_state * pis,
257 				  const gx_drawing_color * pdcolor);
258 
259 /* Bring state up to date for filling. */
260 /* May call setflat, setfillcolor, setlogop. */
261 int gdev_vector_prepare_fill(gx_device_vector * vdev,
262 			     const gs_imager_state * pis,
263 			     const gx_fill_params * params,
264 			     const gx_drawing_color * pdcolor);
265 
266 /* Bring state up to date for stroking.  Note that we pass the scale */
267 /* for the line width and dash offset explicitly. */
268 /* May call setlinewidth, setlinecap, setlinejoin, setmiterlimit, */
269 /* setdash, setflat, setstrokecolor, setlogop. */
270 /* Any of pis, params, and pdcolor may be NULL. */
271 int gdev_vector_prepare_stroke(gx_device_vector * vdev,
272 			       const gs_imager_state * pis,
273 			       const gx_stroke_params * params,
274 			       const gx_drawing_color * pdcolor,
275 			       floatp scale);
276 
277 /*
278  * Compute the scale for transforming the line width and dash pattern for a
279  * stroke operation, and, if necessary to handle anisotropic scaling, a full
280  * transformation matrix to be inverse-applied to the path elements as well.
281  * Return 0 if only scaling, 1 if a full matrix is needed.
282  */
283 int gdev_vector_stroke_scaling(const gx_device_vector *vdev,
284 			       const gs_imager_state *pis,
285 			       double *pscale, gs_matrix *pmat);
286 
287 /* Prepare to write a path using the default implementation. */
288 typedef struct gdev_vector_dopath_state_s {
289     /* Initialized by _init */
290     gx_device_vector *vdev;
291     gx_path_type_t type;
292     bool first;
293     gs_matrix scale_mat;
294     /* Change dynamically */
295     gs_point start;
296     gs_point prev;
297 } gdev_vector_dopath_state_t;
298 void gdev_vector_dopath_init(gdev_vector_dopath_state_t *state,
299 			     gx_device_vector *vdev,
300 			     gx_path_type_t type, const gs_matrix *pmat);
301 
302 /* Write a segment of a path using the default implementation. */
303 int gdev_vector_dopath_segment(gdev_vector_dopath_state_t *state, int pe_op,
304 			       gs_fixed_point vs[3]);
305 
306 /* Write a polygon as part of a path (type = gx_path_type_none) */
307 /* or as a path. */
308 /* May call moveto, lineto, closepath (if close); */
309 /* may call beginpath & endpath if type != none. */
310 int gdev_vector_write_polygon(gx_device_vector * vdev,
311 			      const gs_fixed_point * points, uint count,
312 			      bool close, gx_path_type_t type);
313 
314 /* Write a rectangle.  This is just a special case of write_polygon. */
315 int gdev_vector_write_rectangle(gx_device_vector * vdev,
316 				fixed x0, fixed y0, fixed x1, fixed y1,
317 				bool close, gx_rect_direction_t dir);
318 
319 /* Write a clipping path by calling the path procedures. */
320 /* May call the same procedures as writepath. */
321 int gdev_vector_write_clip_path(gx_device_vector * vdev,
322 				const gx_clip_path * pcpath);
323 
324 /* Bring the clipping state up to date. */
325 /* May call write_rectangle (q.v.), write_clip_path (q.v.). */
326 int gdev_vector_update_clip_path(gx_device_vector * vdev,
327 				 const gx_clip_path * pcpath);
328 
329 /* Close the output file and stream. */
330 int gdev_vector_close_file(gx_device_vector * vdev);
331 
332 /* ---------------- Image enumeration ---------------- */
333 
334 /* Define a common set of state parameters for enumerating images. */
335 #define gdev_vector_image_enum_common\
336 	gx_image_enum_common;\
337 		/* Set by begin_image */\
338 	gs_memory_t *memory;	/* from begin_image */\
339 	gx_image_enum_common_t *default_info;	/* non-0 iff using default implementation */\
340 	gx_image_enum_common_t *bbox_info;	/* non-0 iff passing image data to bbox dev */\
341 	int width, height;\
342 	int bits_per_pixel;	/* (per plane) */\
343 	uint bits_per_row;	/* (per plane) */\
344 		/* Updated dynamically by image_data */\
345 	int y			/* 0 <= y < height */
346 typedef struct gdev_vector_image_enum_s {
347     gdev_vector_image_enum_common;
348 } gdev_vector_image_enum_t;
349 
350 extern_st(st_vector_image_enum);
351 #define public_st_vector_image_enum()	/* in gdevvec.c */\
352   gs_public_st_ptrs2(st_vector_image_enum, gdev_vector_image_enum_t,\
353     "gdev_vector_image_enum_t", vector_image_enum_enum_ptrs,\
354     vector_image_enum_reloc_ptrs, default_info, bbox_info)
355 
356 /*
357  * Initialize for enumerating an image.  Note that the last argument is an
358  * already-allocated enumerator, not a pointer to the place to store the
359  * enumerator.
360  */
361 int gdev_vector_begin_image(gx_device_vector * vdev,
362 			const gs_imager_state * pis, const gs_image_t * pim,
363 			gs_image_format_t format, const gs_int_rect * prect,
364 	      const gx_drawing_color * pdcolor, const gx_clip_path * pcpath,
365 		    gs_memory_t * mem, const gx_image_enum_procs_t * pprocs,
366 			    gdev_vector_image_enum_t * pie);
367 
368 /* End an image, optionally supplying any necessary blank padding rows. */
369 /* Return 0 if we used the default implementation, 1 if not. */
370 int gdev_vector_end_image(gx_device_vector * vdev,
371        gdev_vector_image_enum_t * pie, bool draw_last, gx_color_index pad);
372 
373 /* ================ Device procedures ================ */
374 
375 /* Redefine get/put_params to handle OutputFile. */
376 dev_proc_put_params(gdev_vector_put_params);
377 dev_proc_get_params(gdev_vector_get_params);
378 
379 /* ---------------- Defaults ---------------- */
380 
381 /* fill_rectangle may call setfillcolor, dorect. */
382 dev_proc_fill_rectangle(gdev_vector_fill_rectangle);
383 /* fill_path may call prepare_fill, writepath, write_clip_path. */
384 dev_proc_fill_path(gdev_vector_fill_path);
385 /* stroke_path may call prepare_stroke, write_path, write_clip_path. */
386 dev_proc_stroke_path(gdev_vector_stroke_path);
387 /* fill_trapezoid, fill_parallelogram, and fill_triangle may call */
388 /* setfillcolor, setlogop, beginpath, moveto, lineto, endpath. */
389 dev_proc_fill_trapezoid(gdev_vector_fill_trapezoid);
390 dev_proc_fill_parallelogram(gdev_vector_fill_parallelogram);
391 dev_proc_fill_triangle(gdev_vector_fill_triangle);
392 
393 #endif /* gdevvec_INCLUDED */
394