Bringing apdf from vendor into main branch.
[AROS-Contrib.git] / apdf / splash / SplashClip.cc
blob07f740715c2077b6d7a6e4150eec35b814eb911b
1 //========================================================================
2 //
3 // SplashClip.cc
4 //
5 //========================================================================
7 #include <aconf.h>
9 #ifdef USE_GCC_PRAGMAS
10 #pragma implementation
11 #endif
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"
23 //------------------------------------------------------------------------
24 // SplashClip.flags
25 //------------------------------------------------------------------------
27 #define splashClipEO 0x01 // use even-odd rule
29 //------------------------------------------------------------------------
30 // SplashClip
31 //------------------------------------------------------------------------
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);
42 if (y0 < y1) {
43 yMin = splashFloor(y0);
44 yMax = splashFloor(y1);
45 } else {
46 yMin = splashFloor(y1);
47 yMax = splashFloor(y0);
49 paths = NULL;
50 flags = NULL;
51 scanners = NULL;
52 length = size = 0;
55 SplashClip::SplashClip(SplashClip *clip) {
56 int i;
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);
75 SplashClip::~SplashClip() {
76 int i;
78 for (i = 0; i < length; ++i) {
79 delete paths[i];
80 delete scanners[i];
82 gfree(paths);
83 gfree(flags);
84 gfree(scanners);
87 void SplashClip::grow(int nPaths) {
88 if (length + nPaths > size) {
89 if (size == 0) {
90 size = 32;
92 while (size < length + nPaths) {
93 size *= 2;
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 *));
102 void SplashClip::resetToRect(SplashCoord x0, SplashCoord y0,
103 SplashCoord x1, SplashCoord y1) {
104 int i;
106 for (i = 0; i < length; ++i) {
107 delete paths[i];
108 delete scanners[i];
110 gfree(paths);
111 gfree(flags);
112 gfree(scanners);
113 paths = NULL;
114 flags = NULL;
115 scanners = NULL;
116 length = size = 0;
118 if (x0 < x1) {
119 xMin = splashFloor(x0);
120 xMax = splashFloor(x1);
121 } else {
122 xMin = splashFloor(x1);
123 xMax = splashFloor(x0);
125 if (y0 < y1) {
126 yMin = splashFloor(y0);
127 yMax = splashFloor(y1);
128 } else {
129 yMin = splashFloor(y1);
130 yMax = splashFloor(y0);
134 SplashError SplashClip::clipToRect(SplashCoord x0, SplashCoord y0,
135 SplashCoord x1, SplashCoord y1) {
136 int x0I, y0I, x1I, y1I;
138 if (x0 < x1) {
139 x0I = splashFloor(x0);
140 x1I = splashFloor(x1);
141 } else {
142 x0I = splashFloor(x1);
143 x1I = splashFloor(x0);
145 if (x0I > xMin) {
146 xMin = x0I;
148 if (x1I < xMax) {
149 xMax = x1I;
151 if (y0 < y1) {
152 y0I = splashFloor(y0);
153 y1I = splashFloor(y1);
154 } else {
155 y0I = splashFloor(y1);
156 y1I = splashFloor(y0);
158 if (y0I > yMin) {
159 yMin = y0I;
161 if (y1I < yMax) {
162 yMax = y1I;
164 return splashOk;
167 SplashError SplashClip::clipToPath(SplashPath *path, SplashCoord flatness,
168 GBool eo) {
169 SplashXPath *xPath;
171 xPath = new SplashXPath(path, flatness, gTrue);
173 // check for an empty path
174 if (xPath->length == 0) {
175 xMax = xMin - 1;
176 yMax = yMin - 1;
177 delete xPath;
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;
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;
218 return splashOk;
221 GBool SplashClip::test(int x, int y) {
222 int i;
224 // check the rectangle
225 if (x < xMin || x > xMax || y < yMin || y > yMax) {
226 return gFalse;
229 // check the paths
230 for (i = 0; i < length; ++i) {
231 if (!scanners[i]->test(x, y)) {
232 return gFalse;
236 return gTrue;
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;
245 if (rectXMin >= xMin && rectXMax <= xMax &&
246 rectYMin >= yMin && rectYMax <= yMax &&
247 length == 0) {
248 return splashClipAllInside;
250 return splashClipPartial;
253 SplashClipResult SplashClip::testSpan(int spanXMin, int spanXMax, int spanY) {
254 int i;
256 if (spanXMax < xMin || spanXMin > xMax ||
257 spanY < yMin || spanY > yMax) {
258 return splashClipAllOutside;
260 if (!(spanXMin >= xMin && spanXMax <= xMax &&
261 spanY >= yMin && spanY <= yMax)) {
262 return splashClipPartial;
264 for (i = 0; i < length; ++i) {
265 if (!scanners[i]->testSpan(xMin, xMax, spanY)) {
266 return splashClipPartial;
269 return splashClipAllInside;