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