1 /* Copyright (C) 2001-2019 Artifex Software, Inc. 2 All Rights Reserved. 3 4 This software is provided AS-IS with no warranty, either express or 5 implied. 6 7 This software is distributed under license and may not be copied, 8 modified or distributed except as expressly authorized under the terms 9 of the license contained in the file LICENSE in this distribution. 10 11 Refer to licensing information at http://www.artifex.com or contact 12 Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato, 13 CA 94945, U.S.A., +1(415)492-9861, for further information. 14 */ 15 16 17 /* Definitions for clipping lists and devices */ 18 /* Requires gxdevice.h */ 19 20 #ifndef gxcpath_INCLUDED 21 # define gxcpath_INCLUDED 22 23 #include "gxdevcli.h" 24 25 /* We expose the implementation of clipping lists so that clients */ 26 /* can allocate clipping lists or devices on the stack. */ 27 28 /* 29 * For clipping, a path is represented as a list of rectangles. 30 * Normally, a path is created as a list of segments; 31 * installing it as a clipping path creates the rectangle list. 32 * However, when the clipping path originates in some other way 33 * (e.g., from initclip, or for clipping a cached character), 34 * or if it is a non-trivial intersection of two paths, 35 * the resulting clipping path exists only as a rectangle list; 36 * clippath constructs the segment representation if needed. 37 * Note that even if the path only exists as a rectangle list, 38 * its bounding box (path.bbox) is still correct. 39 */ 40 41 /* 42 * Rectangle list structure. 43 * Consecutive gx_clip_rect entries either have the same Y values, 44 * or ymin of this entry >= ymax of the previous entry. 45 */ 46 typedef struct gx_clip_rect_s gx_clip_rect; 47 struct gx_clip_rect_s { 48 gx_clip_rect *next, *prev; 49 int ymin, ymax; /* ymax > ymin */ 50 int xmin, xmax; /* xmax > xmin */ 51 byte to_visit; /* bookkeeping for gs_clippath */ 52 }; 53 54 /* The descriptor is public only for gxacpath.c. */ 55 extern_st(st_clip_rect); 56 #define public_st_clip_rect() /* in gxcpath.c */\ 57 gs_public_st_ptrs2(st_clip_rect, gx_clip_rect, "clip_rect",\ 58 clip_rect_enum_ptrs, clip_rect_reloc_ptrs, next, prev) 59 #define st_clip_rect_max_ptrs 2 60 61 /* 62 * A clip list may consist either of a single rectangle, 63 * with null head and tail, or a list of rectangles. In the latter case, 64 * there is a dummy head entry with p.x = q.x to cover Y values 65 * starting at min_int, and a dummy tail entry to cover Y values 66 * ending at max_int. This eliminates the need for end tests. 67 */ 68 struct gx_clip_list_s { 69 gx_clip_rect single; /* (has next = prev = 0) */ 70 gx_clip_rect *head; 71 gx_clip_rect *tail; 72 gx_clip_rect *insert; 73 int xmin, xmax; /* min and max X over all but head/tail */ 74 int count; /* # of rectangles not counting */ 75 /* head or tail */ 76 bool transpose; /* Transpose x / y */ 77 }; 78 79 #define public_st_clip_list() /* in gxcpath.c */\ 80 gs_public_st_ptrs2(st_clip_list, gx_clip_list, "clip_list",\ 81 clip_list_enum_ptrs, clip_list_reloc_ptrs, head, tail) 82 #define st_clip_list_max_ptrs 2 /* head, tail */ 83 #define clip_list_is_rectangle(clp) ((clp)->count <= 1) 84 85 /* 86 * Clipping devices provide for translation before clipping. 87 * This ability, a late addition, currently is used only in a few 88 * situations that require breaking up a transfer into pieces, 89 * but we suspect it could be used more widely. 90 * 91 * Note that clipping devices cache their clipping box, so the target's 92 * clipping box and the clip list must be const after the clipping device 93 * is opened. 94 */ 95 typedef struct gx_device_clip_s gx_device_clip; 96 struct gx_device_clip_s { 97 gx_device_forward_common; /* target is set by client */ 98 gx_clip_list list; /* set by client */ 99 gx_clip_rect *current; /* cursor in list */ 100 gs_int_point translation; 101 gs_fixed_rect clipping_box; 102 bool clipping_box_set; 103 const gx_clip_path *cpath; 104 }; 105 106 extern_st(st_device_clip); 107 #define public_st_device_clip() /* in gxcpath.c */\ 108 gs_public_st_composite_use_final(st_device_clip, gx_device_clip,\ 109 "gx_device_clip", device_clip_enum_ptrs, device_clip_reloc_ptrs,\ 110 gx_device_finalize) 111 void gx_make_clip_device_on_stack(gx_device_clip * dev, const gx_clip_path *pcpath, gx_device *target); 112 void gx_destroy_clip_device_on_stack(gx_device_clip * dev); 113 gx_device *gx_make_clip_device_on_stack_if_needed(gx_device_clip * dev, const gx_clip_path *pcpath, gx_device *target, gs_fixed_rect *rect); 114 void gx_make_clip_device_in_heap(gx_device_clip * dev, const gx_clip_path *pcpath, gx_device *target, 115 gs_memory_t *mem); 116 117 #define clip_rect_print(ch, str, ar)\ 118 if_debug7(ch, "[%c]%s 0x%lx: (%d,%d),(%d,%d)\n", ch, str, (ulong)ar,\ 119 (ar)->xmin, (ar)->ymin, (ar)->xmax, (ar)->ymax) 120 121 /* Exported by gxcpath.c for gxacpath.c */ 122 123 /* Initialize a clip list. */ 124 void gx_clip_list_init(gx_clip_list *); 125 126 /* Free a clip list. */ 127 void gx_clip_list_free(gx_clip_list *, gs_memory_t *); 128 129 /* Set the outer box for a clipping path from its bounding box. */ 130 void gx_cpath_set_outer_box(gx_clip_path *); 131 132 /* Exported by gxcpath.c for gxclip.c */ 133 134 /* Return the rectangle list of a clipping path (for local use only). */ 135 const gx_clip_list *gx_cpath_list(const gx_clip_path *pcpath); 136 137 #endif /* gxcpath_INCLUDED */ 138