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