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