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