fix remapping behavior. Remapping is only necessary if we are rendering on the workbe...
[AROS-Contrib.git] / arospdf / splash / SplashClip.cc
blobef8acbabdc29d61be5c72f1f06fad6fa4a8ab164
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 "SplashPath.h"
18 #include "SplashXPath.h"
19 #include "SplashXPathScanner.h"
20 #include "SplashBitmap.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 GBool antialiasA) {
36 antialias = antialiasA;
37 if (x0 < x1) {
38 xMin = x0;
39 xMax = x1;
40 } else {
41 xMin = x1;
42 xMax = x0;
44 if (y0 < y1) {
45 yMin = y0;
46 yMax = y1;
47 } else {
48 yMin = y1;
49 yMax = y0;
51 xMinI = splashFloor(xMin);
52 yMinI = splashFloor(yMin);
53 xMaxI = splashFloor(xMax);
54 yMaxI = splashFloor(yMax);
55 paths = NULL;
56 flags = NULL;
57 scanners = NULL;
58 length = size = 0;
61 SplashClip::SplashClip(SplashClip *clip) {
62 int i;
64 antialias = clip->antialias;
65 xMin = clip->xMin;
66 yMin = clip->yMin;
67 xMax = clip->xMax;
68 yMax = clip->yMax;
69 xMinI = clip->xMinI;
70 yMinI = clip->yMinI;
71 xMaxI = clip->xMaxI;
72 yMaxI = clip->yMaxI;
73 length = clip->length;
74 size = clip->size;
75 paths = (SplashXPath **)gmallocn(size, sizeof(SplashXPath *));
76 flags = (Guchar *)gmallocn(size, sizeof(Guchar));
77 scanners = (SplashXPathScanner **)
78 gmallocn(size, sizeof(SplashXPathScanner *));
79 for (i = 0; i < length; ++i) {
80 paths[i] = clip->paths[i]->copy();
81 flags[i] = clip->flags[i];
82 scanners[i] = new SplashXPathScanner(paths[i], flags[i] & splashClipEO);
86 SplashClip::~SplashClip() {
87 int i;
89 for (i = 0; i < length; ++i) {
90 delete paths[i];
91 delete scanners[i];
93 gfree(paths);
94 gfree(flags);
95 gfree(scanners);
98 void SplashClip::grow(int nPaths) {
99 if (length + nPaths > size) {
100 if (size == 0) {
101 size = 32;
103 while (size < length + nPaths) {
104 size *= 2;
106 paths = (SplashXPath **)greallocn(paths, size, sizeof(SplashXPath *));
107 flags = (Guchar *)greallocn(flags, size, sizeof(Guchar));
108 scanners = (SplashXPathScanner **)
109 greallocn(scanners, size, sizeof(SplashXPathScanner *));
113 void SplashClip::resetToRect(SplashCoord x0, SplashCoord y0,
114 SplashCoord x1, SplashCoord y1) {
115 int i;
117 for (i = 0; i < length; ++i) {
118 delete paths[i];
119 delete scanners[i];
121 gfree(paths);
122 gfree(flags);
123 gfree(scanners);
124 paths = NULL;
125 flags = NULL;
126 scanners = NULL;
127 length = size = 0;
129 if (x0 < x1) {
130 xMin = x0;
131 xMax = x1;
132 } else {
133 xMin = x1;
134 xMax = x0;
136 if (y0 < y1) {
137 yMin = y0;
138 yMax = y1;
139 } else {
140 yMin = y1;
141 yMax = y0;
143 xMinI = splashFloor(xMin);
144 yMinI = splashFloor(yMin);
145 xMaxI = splashFloor(xMax);
146 yMaxI = splashFloor(yMax);
149 SplashError SplashClip::clipToRect(SplashCoord x0, SplashCoord y0,
150 SplashCoord x1, SplashCoord y1) {
151 if (x0 < x1) {
152 if (x0 > xMin) {
153 xMin = x0;
154 xMinI = splashFloor(xMin);
156 if (x1 < xMax) {
157 xMax = x1;
158 xMaxI = splashFloor(xMax);
160 } else {
161 if (x1 > xMin) {
162 xMin = x1;
163 xMinI = splashFloor(xMin);
165 if (x0 < xMax) {
166 xMax = x0;
167 xMaxI = splashFloor(xMax);
170 if (y0 < y1) {
171 if (y0 > yMin) {
172 yMin = y0;
173 yMinI = splashFloor(yMin);
175 if (y1 < yMax) {
176 yMax = y1;
177 yMaxI = splashFloor(yMax);
179 } else {
180 if (y1 > yMin) {
181 yMin = y1;
182 yMinI = splashFloor(yMin);
184 if (y0 < yMax) {
185 yMax = y0;
186 yMaxI = splashFloor(yMax);
189 return splashOk;
192 SplashError SplashClip::clipToPath(SplashPath *path, SplashCoord *matrix,
193 SplashCoord flatness, GBool eo) {
194 SplashXPath *xPath;
196 xPath = new SplashXPath(path, matrix, flatness, gTrue);
198 // check for an empty path
199 if (xPath->length == 0) {
200 xMax = xMin - 1;
201 yMax = yMin - 1;
202 xMaxI = splashFloor(xMax);
203 yMaxI = splashFloor(yMax);
204 delete xPath;
206 // check for a rectangle
207 } else if (xPath->length == 4 &&
208 ((xPath->segs[0].x0 == xPath->segs[0].x1 &&
209 xPath->segs[0].x0 == xPath->segs[1].x0 &&
210 xPath->segs[0].x0 == xPath->segs[3].x1 &&
211 xPath->segs[2].x0 == xPath->segs[2].x1 &&
212 xPath->segs[2].x0 == xPath->segs[1].x1 &&
213 xPath->segs[2].x0 == xPath->segs[3].x0 &&
214 xPath->segs[1].y0 == xPath->segs[1].y1 &&
215 xPath->segs[1].y0 == xPath->segs[0].y1 &&
216 xPath->segs[1].y0 == xPath->segs[2].y0 &&
217 xPath->segs[3].y0 == xPath->segs[3].y1 &&
218 xPath->segs[3].y0 == xPath->segs[0].y0 &&
219 xPath->segs[3].y0 == xPath->segs[2].y1) ||
220 (xPath->segs[0].y0 == xPath->segs[0].y1 &&
221 xPath->segs[0].y0 == xPath->segs[1].y0 &&
222 xPath->segs[0].y0 == xPath->segs[3].y1 &&
223 xPath->segs[2].y0 == xPath->segs[2].y1 &&
224 xPath->segs[2].y0 == xPath->segs[1].y1 &&
225 xPath->segs[2].y0 == xPath->segs[3].y0 &&
226 xPath->segs[1].x0 == xPath->segs[1].x1 &&
227 xPath->segs[1].x0 == xPath->segs[0].x1 &&
228 xPath->segs[1].x0 == xPath->segs[2].x0 &&
229 xPath->segs[3].x0 == xPath->segs[3].x1 &&
230 xPath->segs[3].x0 == xPath->segs[0].x0 &&
231 xPath->segs[3].x0 == xPath->segs[2].x1))) {
232 clipToRect(xPath->segs[0].x0, xPath->segs[0].y0,
233 xPath->segs[2].x0, xPath->segs[2].y0);
234 delete xPath;
236 } else {
237 grow(1);
238 if (antialias) {
239 xPath->aaScale();
241 xPath->sort();
242 paths[length] = xPath;
243 flags[length] = eo ? splashClipEO : 0;
244 scanners[length] = new SplashXPathScanner(xPath, eo);
245 ++length;
248 return splashOk;
251 GBool SplashClip::test(int x, int y) {
252 int i;
254 // check the rectangle
255 if (x < xMinI || x > xMaxI || y < yMinI || y > yMaxI) {
256 return gFalse;
259 // check the paths
260 if (antialias) {
261 for (i = 0; i < length; ++i) {
262 if (!scanners[i]->test(x * splashAASize, y * splashAASize)) {
263 return gFalse;
266 } else {
267 for (i = 0; i < length; ++i) {
268 if (!scanners[i]->test(x, y)) {
269 return gFalse;
274 return gTrue;
277 SplashClipResult SplashClip::testRect(int rectXMin, int rectYMin,
278 int rectXMax, int rectYMax) {
279 // This tests the rectangle:
280 // x = [rectXMin, rectXMax + 1) (note: rect coords are ints)
281 // y = [rectYMin, rectYMax + 1)
282 // against the clipping region:
283 // x = [xMin, xMax] (note: clipping coords are fp)
284 // y = [yMin, yMax]
285 if ((SplashCoord)(rectXMax + 1) <= xMin || (SplashCoord)rectXMin > xMax ||
286 (SplashCoord)(rectYMax + 1) <= yMin || (SplashCoord)rectYMin > yMax) {
287 return splashClipAllOutside;
289 if ((SplashCoord)rectXMin >= xMin && (SplashCoord)(rectXMax + 1) <= xMax &&
290 (SplashCoord)rectYMin >= yMin && (SplashCoord)(rectYMax + 1) <= yMax &&
291 length == 0) {
292 return splashClipAllInside;
294 return splashClipPartial;
297 SplashClipResult SplashClip::testSpan(int spanXMin, int spanXMax, int spanY) {
298 int i;
300 // This tests the rectangle:
301 // x = [spanXMin, spanXMax + 1) (note: span coords are ints)
302 // y = [spanY, spanY + 1)
303 // against the clipping region:
304 // x = [xMin, xMax] (note: clipping coords are fp)
305 // y = [yMin, yMax]
306 if ((SplashCoord)(spanXMax + 1) <= xMin || (SplashCoord)spanXMin > xMax ||
307 (SplashCoord)(spanY + 1) <= yMin || (SplashCoord)spanY > yMax) {
308 return splashClipAllOutside;
310 if (!((SplashCoord)spanXMin >= xMin && (SplashCoord)(spanXMax + 1) <= xMax &&
311 (SplashCoord)spanY >= yMin && (SplashCoord)(spanY + 1) <= yMax)) {
312 return splashClipPartial;
314 if (antialias) {
315 for (i = 0; i < length; ++i) {
316 if (!scanners[i]->testSpan(spanXMin * splashAASize,
317 spanXMax * splashAASize + (splashAASize - 1),
318 spanY * splashAASize)) {
319 return splashClipPartial;
322 } else {
323 for (i = 0; i < length; ++i) {
324 if (!scanners[i]->testSpan(spanXMin, spanXMax, spanY)) {
325 return splashClipPartial;
329 return splashClipAllInside;
332 void SplashClip::clipAALine(SplashBitmap *aaBuf, int *x0, int *x1, int y) {
333 int xx0, xx1, xx, yy, i;
334 SplashColorPtr p;
336 // zero out pixels with x < xMin
337 xx0 = *x0 * splashAASize;
338 xx1 = splashFloor(xMin * splashAASize);
339 if (xx1 > aaBuf->getWidth()) {
340 xx1 = aaBuf->getWidth();
342 if (xx0 < xx1) {
343 xx0 &= ~7;
344 for (yy = 0; yy < splashAASize; ++yy) {
345 p = aaBuf->getDataPtr() + yy * aaBuf->getRowSize() + (xx0 >> 3);
346 for (xx = xx0; xx + 7 < xx1; xx += 8) {
347 *p++ = 0;
349 if (xx < xx1) {
350 *p &= 0xff >> (xx1 & 7);
353 *x0 = splashFloor(xMin);
356 // zero out pixels with x > xMax
357 xx0 = splashFloor(xMax * splashAASize) + 1;
358 if (xx0 < 0) {
359 xx0 = 0;
361 xx1 = (*x1 + 1) * splashAASize;
362 if (xx0 < xx1) {
363 for (yy = 0; yy < splashAASize; ++yy) {
364 p = aaBuf->getDataPtr() + yy * aaBuf->getRowSize() + (xx0 >> 3);
365 xx = xx0;
366 if (xx & 7) {
367 *p &= 0xff00 >> (xx & 7);
368 xx = (xx & ~7) + 8;
369 ++p;
371 for (; xx < xx1; xx += 8) {
372 *p++ = 0;
375 *x1 = splashFloor(xMax);
378 // check the paths
379 for (i = 0; i < length; ++i) {
380 scanners[i]->clipAALine(aaBuf, x0, x1, y);