]>
Commit | Line | Data |
---|---|---|
ef416fc2 | 1 | //======================================================================== |
2 | // | |
3 | // SplashClip.cc | |
4 | // | |
5 | //======================================================================== | |
6 | ||
7 | #include <config.h> | |
8 | ||
9 | #ifdef USE_GCC_PRAGMAS | |
10 | #pragma implementation | |
11 | #endif | |
12 | ||
13 | #include <stdlib.h> | |
14 | #include <string.h> | |
15 | #include "gmem.h" | |
16 | #include "SplashErrorCodes.h" | |
17 | #include "SplashMath.h" | |
18 | #include "SplashPath.h" | |
19 | #include "SplashXPath.h" | |
20 | #include "SplashXPathScanner.h" | |
21 | #include "SplashClip.h" | |
22 | ||
23 | //------------------------------------------------------------------------ | |
24 | // SplashClip.flags | |
25 | //------------------------------------------------------------------------ | |
26 | ||
27 | #define splashClipEO 0x01 // use even-odd rule | |
28 | ||
29 | //------------------------------------------------------------------------ | |
30 | // SplashClip | |
31 | //------------------------------------------------------------------------ | |
32 | ||
33 | SplashClip::SplashClip(SplashCoord x0, SplashCoord y0, | |
34 | SplashCoord x1, SplashCoord y1) { | |
35 | if (x0 < x1) { | |
36 | xMin = splashFloor(x0); | |
37 | xMax = splashFloor(x1); | |
38 | } else { | |
39 | xMin = splashFloor(x1); | |
40 | xMax = splashFloor(x0); | |
41 | } | |
42 | if (y0 < y1) { | |
43 | yMin = splashFloor(y0); | |
44 | yMax = splashFloor(y1); | |
45 | } else { | |
46 | yMin = splashFloor(y1); | |
47 | yMax = splashFloor(y0); | |
48 | } | |
49 | paths = NULL; | |
50 | flags = NULL; | |
51 | scanners = NULL; | |
52 | length = size = 0; | |
53 | } | |
54 | ||
55 | SplashClip::SplashClip(SplashClip *clip) { | |
56 | int i; | |
57 | ||
58 | xMin = clip->xMin; | |
59 | yMin = clip->yMin; | |
60 | xMax = clip->xMax; | |
61 | yMax = clip->yMax; | |
62 | length = clip->length; | |
63 | size = clip->size; | |
64 | paths = (SplashXPath **)gmallocn(size, sizeof(SplashXPath *)); | |
65 | flags = (Guchar *)gmallocn(size, sizeof(Guchar)); | |
66 | scanners = (SplashXPathScanner **) | |
67 | gmallocn(size, sizeof(SplashXPathScanner *)); | |
68 | for (i = 0; i < length; ++i) { | |
69 | paths[i] = clip->paths[i]->copy(); | |
70 | flags[i] = clip->flags[i]; | |
71 | scanners[i] = new SplashXPathScanner(paths[i], flags[i] & splashClipEO); | |
72 | } | |
73 | } | |
74 | ||
75 | SplashClip::~SplashClip() { | |
76 | int i; | |
77 | ||
78 | for (i = 0; i < length; ++i) { | |
79 | delete paths[i]; | |
80 | delete scanners[i]; | |
81 | } | |
82 | gfree(paths); | |
83 | gfree(flags); | |
84 | gfree(scanners); | |
85 | } | |
86 | ||
87 | void SplashClip::grow(int nPaths) { | |
88 | if (length + nPaths > size) { | |
89 | if (size == 0) { | |
90 | size = 32; | |
91 | } | |
92 | while (size < length + nPaths) { | |
93 | size *= 2; | |
94 | } | |
95 | paths = (SplashXPath **)greallocn(paths, size, sizeof(SplashXPath *)); | |
96 | flags = (Guchar *)greallocn(flags, size, sizeof(Guchar)); | |
97 | scanners = (SplashXPathScanner **) | |
98 | greallocn(scanners, size, sizeof(SplashXPathScanner *)); | |
99 | } | |
100 | } | |
101 | ||
102 | void SplashClip::resetToRect(SplashCoord x0, SplashCoord y0, | |
103 | SplashCoord x1, SplashCoord y1) { | |
104 | int i; | |
105 | ||
106 | for (i = 0; i < length; ++i) { | |
107 | delete paths[i]; | |
108 | delete scanners[i]; | |
109 | } | |
110 | gfree(paths); | |
111 | gfree(flags); | |
112 | gfree(scanners); | |
113 | paths = NULL; | |
114 | flags = NULL; | |
115 | scanners = NULL; | |
116 | length = size = 0; | |
117 | ||
118 | if (x0 < x1) { | |
119 | xMin = splashFloor(x0); | |
120 | xMax = splashFloor(x1); | |
121 | } else { | |
122 | xMin = splashFloor(x1); | |
123 | xMax = splashFloor(x0); | |
124 | } | |
125 | if (y0 < y1) { | |
126 | yMin = splashFloor(y0); | |
127 | yMax = splashFloor(y1); | |
128 | } else { | |
129 | yMin = splashFloor(y1); | |
130 | yMax = splashFloor(y0); | |
131 | } | |
132 | } | |
133 | ||
134 | SplashError SplashClip::clipToRect(SplashCoord x0, SplashCoord y0, | |
135 | SplashCoord x1, SplashCoord y1) { | |
136 | int x0I, y0I, x1I, y1I; | |
137 | ||
138 | if (x0 < x1) { | |
139 | x0I = splashFloor(x0); | |
140 | x1I = splashFloor(x1); | |
141 | } else { | |
142 | x0I = splashFloor(x1); | |
143 | x1I = splashFloor(x0); | |
144 | } | |
145 | if (x0I > xMin) { | |
146 | xMin = x0I; | |
147 | } | |
148 | if (x1I < xMax) { | |
149 | xMax = x1I; | |
150 | } | |
151 | if (y0 < y1) { | |
152 | y0I = splashFloor(y0); | |
153 | y1I = splashFloor(y1); | |
154 | } else { | |
155 | y0I = splashFloor(y1); | |
156 | y1I = splashFloor(y0); | |
157 | } | |
158 | if (y0I > yMin) { | |
159 | yMin = y0I; | |
160 | } | |
161 | if (y1I < yMax) { | |
162 | yMax = y1I; | |
163 | } | |
164 | return splashOk; | |
165 | } | |
166 | ||
167 | SplashError SplashClip::clipToPath(SplashPath *path, SplashCoord flatness, | |
168 | GBool eo) { | |
169 | SplashXPath *xPath; | |
170 | ||
171 | xPath = new SplashXPath(path, flatness, gTrue); | |
172 | ||
173 | // check for an empty path | |
174 | if (xPath->length == 0) { | |
175 | xMax = xMin - 1; | |
176 | yMax = yMin - 1; | |
177 | delete xPath; | |
178 | ||
179 | // check for a rectangle | |
180 | } else if (xPath->length == 4 && | |
181 | ((xPath->segs[0].x0 == xPath->segs[0].x1 && | |
182 | xPath->segs[0].x0 == xPath->segs[1].x0 && | |
183 | xPath->segs[0].x0 == xPath->segs[3].x1 && | |
184 | xPath->segs[2].x0 == xPath->segs[2].x1 && | |
185 | xPath->segs[2].x0 == xPath->segs[1].x1 && | |
186 | xPath->segs[2].x0 == xPath->segs[3].x0 && | |
187 | xPath->segs[1].y0 == xPath->segs[1].y1 && | |
188 | xPath->segs[1].y0 == xPath->segs[0].y1 && | |
189 | xPath->segs[1].y0 == xPath->segs[2].y0 && | |
190 | xPath->segs[3].y0 == xPath->segs[3].y1 && | |
191 | xPath->segs[3].y0 == xPath->segs[0].y0 && | |
192 | xPath->segs[3].y0 == xPath->segs[2].y1) || | |
193 | (xPath->segs[0].y0 == xPath->segs[0].y1 && | |
194 | xPath->segs[0].y0 == xPath->segs[1].y0 && | |
195 | xPath->segs[0].y0 == xPath->segs[3].y1 && | |
196 | xPath->segs[2].y0 == xPath->segs[2].y1 && | |
197 | xPath->segs[2].y0 == xPath->segs[1].y1 && | |
198 | xPath->segs[2].y0 == xPath->segs[3].y0 && | |
199 | xPath->segs[1].x0 == xPath->segs[1].x1 && | |
200 | xPath->segs[1].x0 == xPath->segs[0].x1 && | |
201 | xPath->segs[1].x0 == xPath->segs[2].x0 && | |
202 | xPath->segs[3].x0 == xPath->segs[3].x1 && | |
203 | xPath->segs[3].x0 == xPath->segs[0].x0 && | |
204 | xPath->segs[3].x0 == xPath->segs[2].x1))) { | |
205 | clipToRect(xPath->segs[0].x0, xPath->segs[0].y0, | |
206 | xPath->segs[2].x0, xPath->segs[2].y0); | |
207 | delete xPath; | |
208 | ||
209 | } else { | |
210 | grow(1); | |
211 | xPath->sort(); | |
212 | paths[length] = xPath; | |
213 | flags[length] = eo ? splashClipEO : 0; | |
214 | scanners[length] = new SplashXPathScanner(xPath, eo); | |
215 | ++length; | |
216 | } | |
217 | ||
218 | return splashOk; | |
219 | } | |
220 | ||
221 | GBool SplashClip::test(int x, int y) { | |
222 | int i; | |
223 | ||
224 | // check the rectangle | |
225 | if (x < xMin || x > xMax || y < yMin || y > yMax) { | |
226 | return gFalse; | |
227 | } | |
228 | ||
229 | // check the paths | |
230 | for (i = 0; i < length; ++i) { | |
231 | if (!scanners[i]->test(x, y)) { | |
232 | return gFalse; | |
233 | } | |
234 | } | |
235 | ||
236 | return gTrue; | |
237 | } | |
238 | ||
239 | SplashClipResult SplashClip::testRect(int rectXMin, int rectYMin, | |
240 | int rectXMax, int rectYMax) { | |
241 | if (rectXMax < xMin || rectXMin > xMax || | |
242 | rectYMax < yMin || rectYMin > yMax) { | |
243 | return splashClipAllOutside; | |
244 | } | |
245 | if (rectXMin >= xMin && rectXMax <= xMax && | |
246 | rectYMin >= yMin && rectYMax <= yMax && | |
247 | length == 0) { | |
248 | return splashClipAllInside; | |
249 | } | |
250 | return splashClipPartial; | |
251 | } | |
252 | ||
253 | SplashClipResult SplashClip::testSpan(int spanXMin, int spanXMax, int spanY) { | |
254 | int i; | |
255 | ||
256 | if (spanXMax < xMin || spanXMin > xMax || | |
257 | spanY < yMin || spanY > yMax) { | |
258 | return splashClipAllOutside; | |
259 | } | |
260 | if (!(spanXMin >= xMin && spanXMax <= xMax && | |
261 | spanY >= yMin && spanY <= yMax)) { | |
262 | return splashClipPartial; | |
263 | } | |
264 | for (i = 0; i < length; ++i) { | |
265 | if (!scanners[i]->testSpan(xMin, xMax, spanY)) { | |
266 | return splashClipPartial; | |
267 | } | |
268 | } | |
269 | return splashClipAllInside; | |
270 | } |