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
);