Commit | Line | Data |
---|---|---|
7ec0f279 WJ |
1 | /* Copyright (C) 1989, 1992 Aladdin Enterprises. All rights reserved. |
2 | Distributed by Free Software Foundation, Inc. | |
3 | ||
4 | This file is part of Ghostscript. | |
5 | ||
6 | Ghostscript is distributed in the hope that it will be useful, but | |
7 | WITHOUT ANY WARRANTY. No author or distributor accepts responsibility | |
8 | to anyone for the consequences of using it or for whether it serves any | |
9 | particular purpose or works at all, unless he says so in writing. Refer | |
10 | to the Ghostscript General Public License for full details. | |
11 | ||
12 | Everyone is granted permission to copy, modify and redistribute | |
13 | Ghostscript, but only under the conditions described in the Ghostscript | |
14 | General Public License. A copy of this license is supposed to have been | |
15 | given to you along with Ghostscript so you can know your rights and | |
16 | responsibilities. It should be in a file named COPYING. Among other | |
17 | things, the copyright notice and this notice must be preserved on all | |
18 | copies. */ | |
19 | ||
20 | /* gzpath.h */ | |
21 | /* Private representation of paths for Ghostscript library */ | |
22 | /* Requires gxfixed.h */ | |
23 | #include "gxpath.h" | |
24 | ||
25 | /* Paths are represented as a linked list of line or curve segments, */ | |
26 | /* similar to what pathforall reports. */ | |
27 | ||
28 | /* Definition of a path segment: a segment start, a line, */ | |
29 | /* or a Bezier curve. */ | |
30 | typedef enum { | |
31 | s_start, | |
32 | s_line, | |
33 | s_line_close, | |
34 | s_curve | |
35 | } segment_type; | |
36 | #define segment_type_sizes\ | |
37 | sizeof(subpath), sizeof(line_segment), sizeof(line_close_segment),\ | |
38 | sizeof(curve_segment) | |
39 | #define segment_common\ | |
40 | struct segment_s *prev;\ | |
41 | struct segment_s *next;\ | |
42 | segment_type type;\ | |
43 | gs_fixed_point pt; /* initial point for starts, */\ | |
44 | /* final point for others */ | |
45 | /* A generic segment */ | |
46 | typedef struct segment_s { | |
47 | segment_common | |
48 | } segment; | |
49 | /* A start segment. This serves as the head of a subpath. */ | |
50 | typedef struct { | |
51 | segment_common | |
52 | segment *last; /* last segment of subpath, */ | |
53 | /* points back to here if empty */ | |
54 | int curve_count; /* # of curves */ | |
55 | char closed; /* true if subpath is closed */ | |
56 | } subpath; | |
57 | /* Line segments have no special data. */ | |
58 | typedef struct { | |
59 | segment_common | |
60 | } line_segment; | |
61 | /* Line_close segments are for the lines appended by closepath. */ | |
62 | /* They point back to the subpath being closed. */ | |
63 | typedef struct { | |
64 | segment_common | |
65 | subpath *sub; | |
66 | } line_close_segment; | |
67 | /* Curve segments store the control points, not the coefficients. */ | |
68 | /* We may want to change this someday. */ | |
69 | typedef struct { | |
70 | segment_common | |
71 | gs_fixed_point p1, p2; | |
72 | } curve_segment; | |
73 | ||
74 | /* Here is the actual structure of a path. */ | |
75 | struct gx_path_s { | |
76 | gs_memory_procs memory_procs; | |
77 | gs_fixed_rect bbox; /* bounding box (in device space) */ | |
78 | segment *box_last; /* bbox incorporates segments */ | |
79 | /* up to & including this one */ | |
80 | subpath *first_subpath; | |
81 | subpath *current_subpath; | |
82 | int subpath_count; | |
83 | int curve_count; | |
84 | gs_fixed_point position; /* current position */ | |
85 | char position_valid; | |
86 | char subpath_open; | |
87 | char shares_segments; /* if true, this path shares its */ | |
88 | /* segment storage with the one in */ | |
89 | /* the previous saved graphics state */ | |
90 | }; | |
91 | ||
92 | /* Macros equivalent to a few heavily used procedures. */ | |
93 | /* Be aware that these macros may evaluate arguments more than once. */ | |
94 | #define gx_path_current_point_inline(ppath,ppt)\ | |
95 | ( !ppath->position_valid ? gs_note_error(gs_error_nocurrentpoint) :\ | |
96 | ((ppt)->x = ppath->position.x, (ppt)->y = ppath->position.y, 0) ) | |
97 | /* ...rel_point rather than ...relative_point is because */ | |
98 | /* some compilers dislike identifiers of >31 characters. */ | |
99 | #define gx_path_add_rel_point_inline(ppath,dx,dy)\ | |
100 | ( !ppath->position_valid ? gs_note_error(gs_error_nocurrentpoint) :\ | |
101 | (ppath->position.x += dx, ppath->position.y += dy,\ | |
102 | ppath->subpath_open = 0) ) | |
103 | ||
104 | /* ------ Clipping paths ------ */ | |
105 | ||
106 | /* | |
107 | * For clipping, a path is represented as a list of rectangles. | |
108 | * Normally, a path is created as a list of segments; | |
109 | * installing it as a clipping path creates the rectangle list. | |
110 | * However, when the clipping path originates in some other way | |
111 | * (e.g., from initclip, or for clipping a cached character), | |
112 | * or if it is a non-trivial intersection of two paths, | |
113 | * the resulting clipping path exists only as a rectangle list; | |
114 | * clippath constructs the segment representation if needed. | |
115 | * Note that even if the path only exists as a rectangle list, | |
116 | * its bounding box (path.bbox) is still correct. | |
117 | */ | |
118 | ||
119 | /* | |
120 | * Rectangle list structure. | |
121 | * Consecutive gx_clip_rect entries either have the same Y values, | |
122 | * or ymin of this entry >= ymax of the previous entry. | |
123 | * Note that the contents are like a gs_int_rect, not a gs_fixed_rect. | |
124 | */ | |
125 | typedef struct gx_clip_rect_s gx_clip_rect; | |
126 | struct gx_clip_rect_s { | |
127 | gx_clip_rect *next, *prev; | |
128 | int ymin, ymax; /* ymax > ymin */ | |
129 | int xmin, xmax; /* xmax > xmin */ | |
130 | }; | |
131 | /* There is a dummy first entry with xmin = xmax */ | |
132 | /* to cover Y values starting at min_int, and a dummy last entry */ | |
133 | /* to cover Y values ending at max_int. */ | |
134 | /* This eliminates the need for end tests. */ | |
135 | /* We also preallocate just one internal entry, so that */ | |
136 | /* plain rectangular clipping regions don't need to allocate anything. */ | |
137 | struct gx_clip_list_s { | |
138 | gx_clip_rect first, sole, last; | |
139 | int count; /* # of rectangles not counting */ | |
140 | /* first or last */ | |
141 | }; | |
142 | #define clip_list_is_rectangle(clp) ((clp)->count <= 1) | |
143 | ||
144 | /* gx_clip_path is a 'subclass' of gx_path. */ | |
145 | struct gx_clip_path_s { | |
146 | gx_path path; | |
147 | gs_fixed_rect cbox; /* an inner clipping rectangle */ | |
148 | /* for a quick check */ | |
149 | gx_clip_list list; | |
150 | char segments_valid; /* segment representation is valid */ | |
151 | char shares_list; /* if true, this path shares its*/ | |
152 | /* clip list storage with the one in */ | |
153 | /* the previous saved graphics state */ | |
154 | }; | |
155 | #define gx_cpath_is_rectangle(pcpath, pbox)\ | |
156 | (clip_list_is_rectangle(&(pcpath)->list) ?\ | |
157 | (*(pbox) = (pcpath)->cbox, 1) : 0) |