1 //========================================================================
5 //========================================================================
10 #pragma implementation
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 //------------------------------------------------------------------------
25 //------------------------------------------------------------------------
27 #define splashClipEO 0x01 // use even-odd rule
29 //------------------------------------------------------------------------
31 //------------------------------------------------------------------------
33 SplashClip::SplashClip(SplashCoord x0
, SplashCoord y0
,
34 SplashCoord x1
, SplashCoord y1
) {
36 xMin
= splashFloor(x0
);
37 xMax
= splashFloor(x1
);
39 xMin
= splashFloor(x1
);
40 xMax
= splashFloor(x0
);
43 yMin
= splashFloor(y0
);
44 yMax
= splashFloor(y1
);
46 yMin
= splashFloor(y1
);
47 yMax
= splashFloor(y0
);
55 SplashClip::SplashClip(SplashClip
*clip
) {
62 length
= clip
->length
;
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() {
78 for (i
= 0; i
< length
; ++i
) {
87 void SplashClip::grow(int nPaths
) {
88 if (length
+ nPaths
> size
) {
92 while (size
< length
+ nPaths
) {
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
) {
106 for (i
= 0; i
< length
; ++i
) {
119 xMin
= splashFloor(x0
);
120 xMax
= splashFloor(x1
);
122 xMin
= splashFloor(x1
);
123 xMax
= splashFloor(x0
);
126 yMin
= splashFloor(y0
);
127 yMax
= splashFloor(y1
);
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
;
139 x0I
= splashFloor(x0
);
140 x1I
= splashFloor(x1
);
142 x0I
= splashFloor(x1
);
143 x1I
= splashFloor(x0
);
152 y0I
= splashFloor(y0
);
153 y1I
= splashFloor(y1
);
155 y0I
= splashFloor(y1
);
156 y1I
= splashFloor(y0
);
167 SplashError
SplashClip::clipToPath(SplashPath
*path
, SplashCoord flatness
,
171 xPath
= new SplashXPath(path
, flatness
, gTrue
);
173 // check for an empty path
174 if (xPath
->length
== 0) {
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
);
212 paths
[length
] = xPath
;
213 flags
[length
] = eo
? splashClipEO
: 0;
214 scanners
[length
] = new SplashXPathScanner(xPath
, eo
);
221 GBool
SplashClip::test(int x
, int y
) {
224 // check the rectangle
225 if (x
< xMin
|| x
> xMax
|| y
< yMin
|| y
> yMax
) {
230 for (i
= 0; i
< length
; ++i
) {
231 if (!scanners
[i
]->test(x
, y
)) {
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
&&
248 return splashClipAllInside
;
250 return splashClipPartial
;
253 SplashClipResult
SplashClip::testSpan(int spanXMin
, int spanXMax
, int spanY
) {
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
;