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