1
//========================================================================
5
//========================================================================
10
#pragma implementation
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
//------------------------------------------------------------------------
25
//------------------------------------------------------------------------
27
#define splashClipEO 0x01 // use even-odd rule
29
//------------------------------------------------------------------------
31
//------------------------------------------------------------------------
33
SplashClip::SplashClip(SplashCoord x0, SplashCoord y0,
34
SplashCoord x1, SplashCoord y1,
36
antialias = antialiasA;
51
xMinI = splashFloor(xMin);
52
yMinI = splashFloor(yMin);
53
xMaxI = splashFloor(xMax);
54
yMaxI = splashFloor(yMax);
61
SplashClip::SplashClip(SplashClip *clip) {
64
antialias = clip->antialias;
73
length = clip->length;
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() {
89
for (i = 0; i < length; ++i) {
98
void SplashClip::grow(int nPaths) {
99
if (length + nPaths > size) {
103
while (size < length + nPaths) {
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) {
117
for (i = 0; i < length; ++i) {
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) {
154
xMinI = splashFloor(xMin);
158
xMaxI = splashFloor(xMax);
163
xMinI = splashFloor(xMin);
167
xMaxI = splashFloor(xMax);
173
yMinI = splashFloor(yMin);
177
yMaxI = splashFloor(yMax);
182
yMinI = splashFloor(yMin);
186
yMaxI = splashFloor(yMax);
192
SplashError SplashClip::clipToPath(SplashPath *path, SplashCoord *matrix,
193
SplashCoord flatness, GBool eo) {
196
xPath = new SplashXPath(path, matrix, flatness, gTrue);
198
// check for an empty path
199
if (xPath->length == 0) {
202
xMaxI = splashFloor(xMax);
203
yMaxI = splashFloor(yMax);
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);
242
paths[length] = xPath;
243
flags[length] = eo ? splashClipEO : 0;
244
scanners[length] = new SplashXPathScanner(xPath, eo);
251
GBool SplashClip::test(int x, int y) {
254
// check the rectangle
255
if (x < xMinI || x > xMaxI || y < yMinI || y > yMaxI) {
261
for (i = 0; i < length; ++i) {
262
if (!scanners[i]->test(x * splashAASize, y * splashAASize)) {
267
for (i = 0; i < length; ++i) {
268
if (!scanners[i]->test(x, y)) {
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)
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 &&
292
return splashClipAllInside;
294
return splashClipPartial;
297
SplashClipResult SplashClip::testSpan(int spanXMin, int spanXMax, int spanY) {
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)
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;
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;
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;
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();
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) {
350
*p &= 0xff >> (xx1 & 7);
353
*x0 = splashFloor(xMin);
356
// zero out pixels with x > xMax
357
xx0 = splashFloor(xMax * splashAASize) + 1;
361
xx1 = (*x1 + 1) * splashAASize;
363
for (yy = 0; yy < splashAASize; ++yy) {
364
p = aaBuf->getDataPtr() + yy * aaBuf->getRowSize() + (xx0 >> 3);
367
*p &= 0xff00 >> (xx & 7);
371
for (; xx < xx1; xx += 8) {
375
*x1 = splashFloor(xMax);
379
for (i = 0; i < length; ++i) {
380
scanners[i]->clipAALine(aaBuf, x0, x1, y);