1 /* Copyright (C) 1989, 1995, 1996, 1997, 1998, 1999 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: gxpath.h,v 1.16 2005/08/22 14:29:18 igor Exp $ */ 18 /* Fixed-point path procedures */ 19 /* Requires gxfixed.h */ 20 21 #ifndef gxpath_INCLUDED 22 # define gxpath_INCLUDED 23 24 #include "gscpm.h" 25 #include "gslparam.h" 26 #include "gspenum.h" 27 #include "gsrect.h" 28 29 /* The routines and types in this interface use */ 30 /* device, rather than user, coordinates, and fixed-point, */ 31 /* rather than floating, representation. */ 32 33 /* Opaque type for a path */ 34 #ifndef gx_path_DEFINED 35 # define gx_path_DEFINED 36 typedef struct gx_path_s gx_path; 37 #endif 38 39 /* Define the two insideness rules */ 40 #define gx_rule_winding_number (-1) 41 #define gx_rule_even_odd 1 42 43 /* Define 'notes' that describe the role of a path segment. */ 44 /* These are only for internal use; a normal segment's notes are 0. */ 45 typedef enum { 46 sn_none = 0, 47 sn_not_first = 1, /* segment is in curve/arc and not first */ 48 sn_from_arc = 2 /* segment is part of an arc */ 49 } segment_notes; 50 51 /* Debugging routines */ 52 #ifdef DEBUG 53 void gx_dump_path(const gx_path *, const char *); 54 void gx_path_print(const gx_path *); 55 #endif 56 57 /* Path memory management */ 58 59 /* 60 * Path memory management is unfortunately a little tricky. The 61 * implementation details are in gzpath.h: we only present the API here. 62 * 63 * Path objects per se may be allocated in 3 different ways: on the 64 * C stack, as separate objects in the heap, or (for the graphics state 65 * only) contained in a larger heap-allocated object. 66 * 67 * Any number of paths may share segments. The segments are stored in 68 * their own, reference-counted object, and are freed when there are no 69 * more references to that object. 70 */ 71 72 /* 73 * Allocate a path on the heap, and initialize it. If shared is NULL, 74 * allocate a segments object; if shared is an existing path, share its 75 * segments. 76 */ 77 gx_path *gx_path_alloc_shared(const gx_path * shared, gs_memory_t * mem, 78 client_name_t cname); 79 80 #define gx_path_alloc(mem, cname)\ 81 gx_path_alloc_shared(NULL, mem, cname) 82 /* 83 * Initialize a path contained in an already-heap-allocated object, 84 * optionally allocating its segments. 85 */ 86 int gx_path_init_contained_shared(gx_path * ppath, const gx_path * shared, 87 gs_memory_t * mem, client_name_t cname); 88 89 #define gx_path_alloc_contained(ppath, mem, cname)\ 90 gx_path_init_contained_shared(ppath, NULL, mem, cname) 91 /* 92 * Initialize a stack-allocated path. This doesn't allocate anything, 93 * but may still share the segments. Note that it returns an error if 94 * asked to share the segments of another local path. 95 */ 96 int gx_path_init_local_shared(gx_path * ppath, const gx_path * shared, 97 gs_memory_t * mem); 98 99 #define gx_path_init_local(ppath, mem)\ 100 (void)gx_path_init_local_shared(ppath, NULL, mem) /* can't fail */ 101 102 /* 103 * Initialize a stack-allocated pseudo-path for computing a bbox 104 * for a dynamic path. 105 */ 106 void gx_path_init_bbox_accumulator(gx_path * ppath); 107 108 /* 109 * Ensure that a path owns its segments, by copying the segments if 110 * they currently have multiple references. 111 */ 112 int gx_path_unshare(gx_path * ppath); 113 114 /* 115 * Free a path by releasing its segments if they have no more references. 116 * This also frees the path object iff it was allocated by gx_path_alloc. 117 */ 118 void gx_path_free(gx_path * ppath, client_name_t cname); 119 120 /* 121 * Assign one path to another, adjusting reference counts appropriately. 122 * Note that this requires that segments of the two paths (but not the path 123 * objects themselves) were allocated with the same allocator. Note also 124 * that if ppfrom is stack-allocated, ppto is not, and ppto's segments are 125 * currently shared, gx_path_assign must do the equivalent of a 126 * gx_path_new(ppto), which allocates a new segments object for ppto. 127 */ 128 int gx_path_assign_preserve(gx_path * ppto, gx_path * ppfrom); 129 130 /* 131 * Assign one path to another and free the first path at the same time. 132 * (This may do less work than assign_preserve + free.) 133 */ 134 int gx_path_assign_free(gx_path * ppto, gx_path * ppfrom); 135 136 /* Path constructors */ 137 /* Note that all path constructors have an implicit initial gx_path_unshare. */ 138 139 int gx_path_new(gx_path *), 140 gx_path_add_point(gx_path *, fixed, fixed), 141 gx_path_add_relative_point(gx_path *, fixed, fixed), 142 gx_path_add_line_notes(gx_path *, fixed, fixed, segment_notes), 143 gx_path_add_lines_notes(gx_path *, const gs_fixed_point *, int, segment_notes), 144 gx_path_add_rectangle(gx_path *, fixed, fixed, fixed, fixed), 145 gx_path_add_char_path(gx_path *, gx_path *, gs_char_path_mode), 146 gx_path_add_curve_notes(gx_path *, fixed, fixed, fixed, fixed, fixed, fixed, segment_notes), 147 gx_path_add_partial_arc_notes(gx_path *, fixed, fixed, fixed, fixed, floatp, segment_notes), 148 gx_path_add_path(gx_path *, gx_path *), 149 gx_path_close_subpath_notes(gx_path *, segment_notes), 150 /* We have to remove the 'subpath' from the following name */ 151 /* to keep it unique in the first 23 characters. */ 152 gx_path_pop_close_notes(gx_path *, segment_notes); 153 154 /* Access path state flags */ 155 byte gx_path_get_state_flags(gx_path *ppath); 156 void gx_path_set_state_flags(gx_path *ppath, byte flags); 157 bool gx_path_is_drawing(gx_path *ppath); 158 159 /* 160 * The last argument to gx_path_add_partial_arc is a fraction for computing 161 * the curve parameters. Here is the correct value for quarter-circles. 162 * (stroke uses this to draw round caps and joins.) 163 */ 164 #define quarter_arc_fraction 0.55228474983079334 165 /* 166 * Backward-compatible constructors that don't take a notes argument. 167 */ 168 #define gx_path_add_line(ppath, x, y)\ 169 gx_path_add_line_notes(ppath, x, y, sn_none) 170 #define gx_path_add_lines(ppath, pts, count)\ 171 gx_path_add_lines_notes(ppath, pts, count, sn_none) 172 #define gx_path_add_curve(ppath, x1, y1, x2, y2, x3, y3)\ 173 gx_path_add_curve_notes(ppath, x1, y1, x2, y2, x3, y3, sn_none) 174 #define gx_path_add_partial_arc(ppath, x3, y3, xt, yt, fraction)\ 175 gx_path_add_partial_arc_notes(ppath, x3, y3, xt, yt, fraction, sn_none) 176 #define gx_path_close_subpath(ppath)\ 177 gx_path_close_subpath_notes(ppath, sn_none) 178 #define gx_path_pop_close_subpath(ppath)\ 179 gx_path_pop_close_notes(ppath, sn_none) 180 181 typedef enum { 182 pco_none = 0, 183 pco_monotonize = 1, /* make curves monotonic */ 184 pco_accurate = 2, /* flatten with accurate tangents at ends */ 185 pco_for_stroke = 4, /* flatten taking line width into account */ 186 pco_small_curves = 8 /* make curves small */ 187 } gx_path_copy_options; 188 189 /* Path accessors */ 190 191 gx_path *gx_current_path(const gs_state *); 192 int gx_path_current_point(const gx_path *, gs_fixed_point *), 193 gx_path_bbox(gx_path *, gs_fixed_rect *), 194 gx_path_bbox_set(gx_path *, gs_fixed_rect *); 195 int gx_path_subpath_start_point(const gx_path *, gs_fixed_point *); 196 bool gx_path_has_curves(const gx_path *), 197 gx_path_is_void(const gx_path *), /* no segments */ 198 gx_path_is_null(const gx_path *), /* nothing at all */ 199 gx_path__check_curves(const gx_path * ppath, gx_path_copy_options options, fixed fixed_flat); 200 typedef enum { 201 prt_none = 0, 202 prt_open = 1, /* only 3 sides */ 203 prt_fake_closed = 2, /* 4 lines, no closepath */ 204 prt_closed = 3 /* 3 or 4 lines + closepath */ 205 } gx_path_rectangular_type; 206 207 gx_path_rectangular_type 208 gx_path_is_rectangular(const gx_path *, gs_fixed_rect *); 209 210 #define gx_path_is_rectangle(ppath, pbox)\ 211 (gx_path_is_rectangular(ppath, pbox) != prt_none) 212 /* Inline versions of the above */ 213 #define gx_path_is_null_inline(ppath)\ 214 (gx_path_is_void(ppath) && !path_position_valid(ppath)) 215 216 /* Path transformers */ 217 218 /* The imager state is only needed when flattening for stroke. */ 219 #ifndef gs_imager_state_DEFINED 220 # define gs_imager_state_DEFINED 221 typedef struct gs_imager_state_s gs_imager_state; 222 #endif 223 int gx_path_copy_reducing(const gx_path * ppath_old, gx_path * ppath_new, 224 fixed fixed_flatness, const gs_imager_state *pis, 225 gx_path_copy_options options); 226 227 #define gx_path_copy(old, new)\ 228 gx_path_copy_reducing(old, new, max_fixed, NULL, pco_none) 229 #define gx_path_add_flattened(old, new, flatness)\ 230 gx_path_copy_reducing(old, new, float2fixed(flatness), NULL, pco_none) 231 #define gx_path_add_flattened_accurate(old, new, flatness, accurate)\ 232 gx_path_copy_reducing(old, new, float2fixed(flatness), NULL,\ 233 (accurate ? pco_accurate : pco_none)) 234 #define gx_path_add_flattened_for_stroke(old, new, flatness, pis)\ 235 gx_path_copy_reducing(old, new, float2fixed(flatness), pis,\ 236 (pis->accurate_curves ?\ 237 pco_accurate | pco_for_stroke : pco_for_stroke)) 238 #define gx_path_add_monotonized(old, new)\ 239 gx_path_copy_reducing(old, new, max_fixed, NULL, pco_monotonize) 240 int gx_path_add_dash_expansion(const gx_path * /*old*/, gx_path * /*new*/, 241 const gs_imager_state *), 242 gx_path_copy_reversed(const gx_path * /*old*/, gx_path * /*new*/), 243 gx_path_translate(gx_path *, fixed, fixed), 244 gx_path_scale_exp2_shared(gx_path *ppath, int log2_scale_x, 245 int log2_scale_y, bool segments_shared); 246 void gx_point_scale_exp2(gs_fixed_point *, int, int), 247 gx_rect_scale_exp2(gs_fixed_rect *, int, int); 248 249 /* Path enumerator */ 250 251 /* This interface does not make a copy of the path. */ 252 /* Do not use gs_path_enum_cleanup with this interface! */ 253 int gx_path_enum_init(gs_path_enum *, const gx_path *); 254 int gx_path_enum_next(gs_path_enum *, gs_fixed_point[3]); /* 0 when done */ 255 256 segment_notes 257 gx_path_enum_notes(const gs_path_enum *); 258 bool gx_path_enum_backup(gs_path_enum *); 259 260 /* An auxiliary function to add a path point with a specified transformation. */ 261 int gs_moveto_aux(gs_imager_state *pis, gx_path *ppath, floatp x, floatp y); 262 int gx_setcurrentpoint_from_path(gs_imager_state *pis, gx_path *path); 263 264 /* Path optimization for the filling algorithm. */ 265 266 int gx_path_merge_contacting_contours(gx_path *ppath); 267 268 /* ------ Clipping paths ------ */ 269 270 /* Opaque type for a clipping path */ 271 #ifndef gx_clip_path_DEFINED 272 # define gx_clip_path_DEFINED 273 typedef struct gx_clip_path_s gx_clip_path; 274 #endif 275 276 /* Graphics state clipping */ 277 int gx_clip_to_rectangle(gs_state *, gs_fixed_rect *); 278 int gx_clip_to_path(gs_state *); 279 int gx_default_clip_box(const gs_state *, gs_fixed_rect *); 280 int gx_effective_clip_path(gs_state *, gx_clip_path **); 281 282 /* Opaque type for a clip list. */ 283 #ifndef gx_clip_list_DEFINED 284 # define gx_clip_list_DEFINED 285 typedef struct gx_clip_list_s gx_clip_list; 286 #endif 287 288 /* Opaque type for a clipping path enumerator. */ 289 typedef struct gs_cpath_enum_s gs_cpath_enum; 290 291 /* 292 * Provide similar memory management for clip paths to what we have for 293 * paths (see above for details). 294 */ 295 gx_clip_path *gx_cpath_alloc_shared(const gx_clip_path * shared, 296 gs_memory_t * mem, client_name_t cname); 297 298 #define gx_cpath_alloc(mem, cname)\ 299 gx_cpath_alloc_shared(NULL, mem, cname) 300 int gx_cpath_init_contained_shared(gx_clip_path * pcpath, 301 const gx_clip_path * shared, 302 gs_memory_t * mem, 303 client_name_t cname); 304 305 #define gx_cpath_alloc_contained(pcpath, mem, cname)\ 306 gx_cpath_init_contained_shared(pcpath, NULL, mem, cname) 307 int gx_cpath_init_local_shared(gx_clip_path * pcpath, 308 const gx_clip_path * shared, 309 gs_memory_t * mem); 310 311 #define gx_cpath_init_local(pcpath, mem)\ 312 (void)gx_cpath_init_local_shared(pcpath, NULL, mem) /* can't fail */ 313 int gx_cpath_unshare(gx_clip_path * pcpath); 314 void gx_cpath_free(gx_clip_path * pcpath, client_name_t cname); 315 int gx_cpath_assign_preserve(gx_clip_path * pcpto, gx_clip_path * pcpfrom); 316 int gx_cpath_assign_free(gx_clip_path * pcpto, gx_clip_path * pcpfrom); 317 318 /* Clip path constructors and accessors */ 319 320 int 321 gx_cpath_reset(gx_clip_path *), /* from_rectangle ((0,0),(0,0)) */ 322 gx_cpath_from_rectangle(gx_clip_path *, gs_fixed_rect *), 323 gx_cpath_clip(gs_state *, gx_clip_path *, /*const*/ gx_path *, int), 324 gx_cpath_intersect(gx_clip_path *, /*const*/ gx_path *, int, 325 gs_imager_state *), 326 gx_cpath_scale_exp2_shared(gx_clip_path *pcpath, int log2_scale_x, 327 int log2_scale_y, bool list_shared, 328 bool segments_shared), 329 gx_cpath_to_path(gx_clip_path *, gx_path *); 330 bool 331 gx_cpath_inner_box(const gx_clip_path *, gs_fixed_rect *), 332 gx_cpath_outer_box(const gx_clip_path *, gs_fixed_rect *), 333 gx_cpath_includes_rectangle(const gx_clip_path *, fixed, fixed, 334 fixed, fixed); 335 const gs_fixed_rect *cpath_is_rectangle(const gx_clip_path * pcpath); 336 337 /* Enumerate a clipping path. This interface does not copy the path. */ 338 /* However, it does write into the path's "visited" flags. */ 339 int gx_cpath_enum_init(gs_cpath_enum *, gx_clip_path *); 340 int gx_cpath_enum_next(gs_cpath_enum *, gs_fixed_point[3]); /* 0 when done */ 341 342 segment_notes 343 gx_cpath_enum_notes(const gs_cpath_enum *); 344 345 #ifdef DEBUG 346 void gx_cpath_print(const gx_clip_path *); 347 #endif 348 349 350 #endif /* gxpath_INCLUDED */ 351