1 /* Copyright (C) 1997, 1998, 1999, 2000 artofcode LLC.  All rights reserved.
2 
3   This program is free software; you can redistribute it and/or modify it
4   under the terms of the GNU General Public License as published by the
5   Free Software Foundation; either version 2 of the License, or (at your
6   option) any later version.
7 
8   This program is distributed in the hope that it will be useful, but
9   WITHOUT ANY WARRANTY; without even the implied warranty of
10   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11   General Public License for more details.
12 
13   You should have received a copy of the GNU General Public License along
14   with this program; if not, write to the Free Software Foundation, Inc.,
15   59 Temple Place, Suite 330, Boston, MA, 02111-1307.
16 
17 */
18 
19 /*$Id: gdevvec.h,v 1.7.2.1.2.1 2003/01/17 00:49:01 giles 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_optimize = 16,	/* OK to optimize paths by merging seg.s */
93     gx_path_type_always_close = 32, /* include final closepath even if not stroke */
94     gx_path_type_rule = gx_path_type_winding_number | gx_path_type_even_odd
95 } gx_path_type_t;
96 typedef enum {
97     gx_rect_x_first,
98     gx_rect_y_first
99 } gx_rect_direction_t;
100 typedef struct gx_device_vector_procs_s {
101     /* Page management */
102     int (*beginpage) (P1(gx_device_vector * vdev));
103     /* Imager state */
104     int (*setlinewidth) (P2(gx_device_vector * vdev, floatp width));
105     int (*setlinecap) (P2(gx_device_vector * vdev, gs_line_cap cap));
106     int (*setlinejoin) (P2(gx_device_vector * vdev, gs_line_join join));
107     int (*setmiterlimit) (P2(gx_device_vector * vdev, floatp limit));
108     int (*setdash) (P4(gx_device_vector * vdev, const float *pattern,
109 		       uint count, floatp offset));
110     int (*setflat) (P2(gx_device_vector * vdev, floatp flatness));
111     int (*setlogop) (P3(gx_device_vector * vdev, gs_logical_operation_t lop,
112 			gs_logical_operation_t diff));
113     /* Other state */
114     int (*setfillcolor) (P2(gx_device_vector * vdev, const gx_drawing_color * pdc));
115     int (*setstrokecolor) (P2(gx_device_vector * vdev, const gx_drawing_color * pdc));
116     /* Paths */
117     /* dopath and dorect are normally defaulted */
118     int (*dopath) (P4(gx_device_vector * vdev, const gx_path * ppath,
119 		      gx_path_type_t type, const gs_matrix *pmat));
120     int (*dorect) (P6(gx_device_vector * vdev, fixed x0, fixed y0, fixed x1,
121 		      fixed y1, gx_path_type_t type));
122     int (*beginpath) (P2(gx_device_vector * vdev, gx_path_type_t type));
123     int (*moveto) (P6(gx_device_vector * vdev, floatp x0, floatp y0,
124 		      floatp x, floatp y, gx_path_type_t type));
125     int (*lineto) (P6(gx_device_vector * vdev, floatp x0, floatp y0,
126 		      floatp x, floatp y, gx_path_type_t type));
127     int (*curveto) (P10(gx_device_vector * vdev, floatp x0, floatp y0,
128 			floatp x1, floatp y1, floatp x2, floatp y2,
129 			floatp x3, floatp y3, gx_path_type_t type));
130     int (*closepath) (P6(gx_device_vector * vdev, floatp x0, floatp y0,
131 		      floatp x_start, floatp y_start, gx_path_type_t type));
132     int (*endpath) (P2(gx_device_vector * vdev, gx_path_type_t type));
133 } gx_device_vector_procs;
134 
135 /* Default implementations of procedures */
136 /* setflat does nothing */
137 int gdev_vector_setflat(P2(gx_device_vector * vdev, floatp flatness));
138 
139 /* dopath may call dorect, beginpath, moveto/lineto/curveto/closepath, */
140 /* endpath */
141 int gdev_vector_dopath(P4(gx_device_vector * vdev, const gx_path * ppath,
142 			  gx_path_type_t type, const gs_matrix *pmat));
143 
144 /* dorect may call beginpath, moveto, lineto, closepath */
145 int gdev_vector_dorect(P6(gx_device_vector * vdev, fixed x0, fixed y0,
146 			  fixed x1, fixed y1, gx_path_type_t type));
147 
148 /* Finally, define the extended device structure. */
149 #define gx_device_vector_common\
150 	gx_device_common;\
151 	gs_memory_t *v_memory;\
152 		/* Output element writing procedures */\
153 	const gx_device_vector_procs *vec_procs;\
154 		/* Output file */\
155 	char fname[fname_size + 1];\
156 	FILE *file;\
157 	stream *strm;\
158 	byte *strmbuf;\
159 	uint strmbuf_size;\
160 	int open_options;	/* see below */\
161 		/* Graphics state */\
162 	gs_imager_state state;\
163 	float dash_pattern[max_dash];\
164 	gx_drawing_color fill_color, stroke_color;\
165 	gs_id no_clip_path_id;	/* indicates no clipping */\
166 	gs_id clip_path_id;\
167 		/* Other state */\
168 	gx_path_type_t fill_options, stroke_options;  /* optimize */\
169 	gs_point scale;		/* device coords / scale => output coords */\
170 	bool in_page;		/* true if any marks on this page */\
171 	gx_device_bbox *bbox_device;	/* for tracking bounding box */\
172 		/* Cached values */\
173 	gx_color_index black, white
174 #define vdev_proc(vdev, p) ((vdev)->vec_procs->p)
175 
176 #define vector_initial_values\
177 	0,		/* v_memory */\
178 	0,		/* vec_procs */\
179 	 { 0 },		/* fname */\
180 	0,		/* file */\
181 	0,		/* strm */\
182 	0,		/* strmbuf */\
183 	0,		/* strmbuf_size */\
184 	0,		/* open_options */\
185 	 { 0 },		/* state */\
186 	 { 0 },		/* dash_pattern */\
187 	 { 0 },		/* fill_color ****** WRONG ****** */\
188 	 { 0 },		/* stroke_color ****** WRONG ****** */\
189 	gs_no_id,	/* clip_path_id */\
190 	gs_no_id,	/* no_clip_path_id */\
191 	0, 0,		/* fill/stroke_options */\
192 	 { X_DPI/72.0, Y_DPI/72.0 },	/* scale */\
193 	0/*false*/,	/* in_page */\
194 	0,		/* bbox_device */\
195 	gx_no_color_index,	/* black */\
196 	gx_no_color_index	/* white */
197 
198 struct gx_device_vector_s {
199     gx_device_vector_common;
200 };
201 
202 /* st_device_vector is never instantiated per se, but we still need to */
203 /* extern its descriptor for the sake of subclasses. */
204 extern_st(st_device_vector);
205 #define public_st_device_vector()	/* in gdevvec.c */\
206   gs_public_st_suffix_add3_final(st_device_vector, gx_device_vector,\
207     "gx_device_vector", device_vector_enum_ptrs,\
208     device_vector_reloc_ptrs, gx_device_finalize, st_device, strm, strmbuf,\
209     bbox_device)
210 #define st_device_vector_max_ptrs (st_device_max_ptrs + 3)
211 
212 /* ================ Utility procedures ================ */
213 
214 /* Initialize the state. */
215 void gdev_vector_init(P1(gx_device_vector * vdev));
216 
217 /* Reset the remembered graphics state. */
218 void gdev_vector_reset(P1(gx_device_vector * vdev));
219 
220 /*
221  * Open the output file and stream, with optional bbox tracking.
222  * The options must be defined so that 0 is always the default.
223  */
224 #define VECTOR_OPEN_FILE_ASCII 1	/* open file as text, not binary */
225 #define VECTOR_OPEN_FILE_SEQUENTIAL 2	/* open as non-seekable */
226 #define VECTOR_OPEN_FILE_SEQUENTIAL_OK 4  /* open as non-seekable if */
227 					/* open as seekable fails */
228 #define VECTOR_OPEN_FILE_BBOX 8		/* also open bbox device */
229 int gdev_vector_open_file_options(P3(gx_device_vector * vdev,
230 				     uint strmbuf_size, int open_options));
231 #define gdev_vector_open_file_bbox(vdev, bufsize, bbox)\
232   gdev_vector_open_file_options(vdev, bufsize,\
233 				(bbox ? VECTOR_OPEN_FILE_BBOX : 0))
234 #define gdev_vector_open_file(vdev, strmbuf_size)\
235   gdev_vector_open_file_bbox(vdev, strmbuf_size, false)
236 
237 /* Get the current stream, calling beginpage if in_page is false. */
238 stream *gdev_vector_stream(P1(gx_device_vector * vdev));
239 
240 /* Bring the logical operation up to date. */
241 /* May call setlogop. */
242 int gdev_vector_update_log_op(P2(gx_device_vector * vdev,
243 				 gs_logical_operation_t lop));
244 
245 /* Bring the fill color up to date. */
246 /* May call setfillcolor. */
247 int gdev_vector_update_fill_color(P2(gx_device_vector * vdev,
248 				     const gx_drawing_color * pdcolor));
249 
250 /* Bring state up to date for filling. */
251 /* May call setflat, setfillcolor, setlogop. */
252 int gdev_vector_prepare_fill(P4(gx_device_vector * vdev,
253 				const gs_imager_state * pis,
254 				const gx_fill_params * params,
255 				const gx_drawing_color * pdcolor));
256 
257 /* Bring state up to date for stroking.  Note that we pass the scale */
258 /* for the line width and dash offset explicitly. */
259 /* May call setlinewidth, setlinecap, setlinejoin, setmiterlimit, */
260 /* setdash, setflat, setstrokecolor, setlogop. */
261 /* Any of pis, params, and pdcolor may be NULL. */
262 int gdev_vector_prepare_stroke(P5(gx_device_vector * vdev,
263 				  const gs_imager_state * pis,
264 				  const gx_stroke_params * params,
265 				  const gx_drawing_color * pdcolor,
266 				  floatp scale));
267 
268 /*
269  * Compute the scale for transforming the line width and dash pattern for a
270  * stroke operation, and, if necessary to handle anisotropic scaling, a full
271  * transformation matrix to be inverse-applied to the path elements as well.
272  * Return 0 if only scaling, 1 if a full matrix is needed.
273  */
274 int gdev_vector_stroke_scaling(P4(const gx_device_vector *vdev,
275 				  const gs_imager_state *pis,
276 				  double *pscale, gs_matrix *pmat));
277 
278 /* Prepare to write a path using the default implementation. */
279 typedef struct gdev_vector_dopath_state_s {
280     /* Initialized by _init */
281     gx_device_vector *vdev;
282     gx_path_type_t type;
283     bool first;
284     gs_matrix scale_mat;
285     /* Change dynamically */
286     gs_point start;
287     gs_point prev;
288 } gdev_vector_dopath_state_t;
289 void gdev_vector_dopath_init(P4(gdev_vector_dopath_state_t *state,
290 				gx_device_vector *vdev,
291 				gx_path_type_t type, const gs_matrix *pmat));
292 
293 /* Write a segment of a path using the default implementation. */
294 int gdev_vector_dopath_segment(P3(gdev_vector_dopath_state_t *state, int pe_op,
295 				  gs_fixed_point vs[3]));
296 
297 /* Write a polygon as part of a path (type = gx_path_type_none) */
298 /* or as a path. */
299 /* May call moveto, lineto, closepath (if close); */
300 /* may call beginpath & endpath if type != none. */
301 int gdev_vector_write_polygon(P5(gx_device_vector * vdev,
302 				 const gs_fixed_point * points, uint count,
303 				 bool close, gx_path_type_t type));
304 
305 /* Write a rectangle.  This is just a special case of write_polygon. */
306 int gdev_vector_write_rectangle(P7(gx_device_vector * vdev,
307 				   fixed x0, fixed y0, fixed x1, fixed y1,
308 				   bool close, gx_rect_direction_t dir));
309 
310 /* Write a clipping path by calling the path procedures. */
311 /* May call the same procedures as writepath. */
312 int gdev_vector_write_clip_path(P2(gx_device_vector * vdev,
313 				   const gx_clip_path * pcpath));
314 
315 /* Bring the clipping state up to date. */
316 /* May call write_rectangle (q.v.), write_clip_path (q.v.). */
317 int gdev_vector_update_clip_path(P2(gx_device_vector * vdev,
318 				    const gx_clip_path * pcpath));
319 
320 /* Close the output file and stream. */
321 int gdev_vector_close_file(P1(gx_device_vector * vdev));
322 
323 /* ---------------- Image enumeration ---------------- */
324 
325 /* Define a common set of state parameters for enumerating images. */
326 #define gdev_vector_image_enum_common\
327 	gx_image_enum_common;\
328 		/* Set by begin_image */\
329 	gs_memory_t *memory;	/* from begin_image */\
330 	gx_image_enum_common_t *default_info;	/* non-0 iff using default implementation */\
331 	gx_image_enum_common_t *bbox_info;	/* non-0 iff passing image data to bbox dev */\
332 	int width, height;\
333 	int bits_per_pixel;	/* (per plane) */\
334 	uint bits_per_row;	/* (per plane) */\
335 		/* Updated dynamically by image_data */\
336 	int y			/* 0 <= y < height */
337 typedef struct gdev_vector_image_enum_s {
338     gdev_vector_image_enum_common;
339 } gdev_vector_image_enum_t;
340 
341 extern_st(st_vector_image_enum);
342 #define public_st_vector_image_enum()	/* in gdevvec.c */\
343   gs_public_st_ptrs2(st_vector_image_enum, gdev_vector_image_enum_t,\
344     "gdev_vector_image_enum_t", vector_image_enum_enum_ptrs,\
345     vector_image_enum_reloc_ptrs, default_info, bbox_info)
346 
347 /*
348  * Initialize for enumerating an image.  Note that the last argument is an
349  * already-allocated enumerator, not a pointer to the place to store the
350  * enumerator.
351  */
352 int gdev_vector_begin_image(P10(gx_device_vector * vdev,
353 			const gs_imager_state * pis, const gs_image_t * pim,
354 			gs_image_format_t format, const gs_int_rect * prect,
355 	      const gx_drawing_color * pdcolor, const gx_clip_path * pcpath,
356 		    gs_memory_t * mem, const gx_image_enum_procs_t * pprocs,
357 				gdev_vector_image_enum_t * pie));
358 
359 /* End an image, optionally supplying any necessary blank padding rows. */
360 /* Return 0 if we used the default implementation, 1 if not. */
361 int gdev_vector_end_image(P4(gx_device_vector * vdev,
362        gdev_vector_image_enum_t * pie, bool draw_last, gx_color_index pad));
363 
364 /* ================ Device procedures ================ */
365 
366 /* Redefine get/put_params to handle OutputFile. */
367 dev_proc_put_params(gdev_vector_put_params);
368 dev_proc_get_params(gdev_vector_get_params);
369 
370 /* ---------------- Defaults ---------------- */
371 
372 /* fill_rectangle may call setfillcolor, dorect. */
373 dev_proc_fill_rectangle(gdev_vector_fill_rectangle);
374 /* fill_path may call prepare_fill, writepath, write_clip_path. */
375 dev_proc_fill_path(gdev_vector_fill_path);
376 /* stroke_path may call prepare_stroke, write_path, write_clip_path. */
377 dev_proc_stroke_path(gdev_vector_stroke_path);
378 /* fill_trapezoid, fill_parallelogram, and fill_triangle may call */
379 /* setfillcolor, setlogop, beginpath, moveto, lineto, endpath. */
380 dev_proc_fill_trapezoid(gdev_vector_fill_trapezoid);
381 dev_proc_fill_parallelogram(gdev_vector_fill_parallelogram);
382 dev_proc_fill_triangle(gdev_vector_fill_triangle);
383 
384 #endif /* gdevvec_INCLUDED */
385