1 /* Copyright (C) 1997, 1998, 1999, 2000 Aladdin Enterprises. All rights reserved. 2 3 This file is part of AFPL Ghostscript. 4 5 AFPL Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author or 6 distributor accepts any responsibility for the consequences of using it, or 7 for whether it serves any particular purpose or works at all, unless he or 8 she says so in writing. Refer to the Aladdin Free Public License (the 9 "License") for full details. 10 11 Every copy of AFPL Ghostscript must include a copy of the License, normally 12 in a plain ASCII text file named PUBLIC. The License grants you the right 13 to copy, modify and redistribute AFPL Ghostscript, but only under certain 14 conditions described in the License. Among other things, the License 15 requires that the copyright notice and this notice be preserved on all 16 copies. 17 */ 18 19 /*$Id: gdevvec.h,v 1.7 2001/07/12 03:28:02 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_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