1 //========================================================================
5 //========================================================================
7 //========================================================================
9 // Modified under the Poppler project - http://poppler.freedesktop.org
11 // All changes made under the Poppler project to this file are licensed
12 // under GPL version 2 or later
14 // Copyright (C) 2010 Albert Astals Cid <aacid@kde.org>
15 // Copyright (C) 2013 Thomas Freitag <Thomas.Freitag@alfa.de>
17 // To see a description of the changes please see the Changelog file that
18 // came with your tarball or type make ChangeLog if you are building from git
20 //========================================================================
24 #ifdef USE_GCC_PRAGMAS
25 #pragma implementation
31 #include "SplashErrorCodes.h"
32 #include "SplashPath.h"
33 #include "SplashXPath.h"
34 #include "SplashXPathScanner.h"
35 #include "SplashBitmap.h"
36 #include "SplashClip.h"
38 //------------------------------------------------------------------------
40 //------------------------------------------------------------------------
42 #define splashClipEO 0x01 // use even-odd rule
44 //------------------------------------------------------------------------
46 //------------------------------------------------------------------------
48 SplashClip::SplashClip(SplashCoord x0
, SplashCoord y0
,
49 SplashCoord x1
, SplashCoord y1
,
51 antialias
= antialiasA
;
66 xMinI
= splashFloor(xMin
);
67 yMinI
= splashFloor(yMin
);
68 xMaxI
= splashCeil(xMax
) - 1;
69 yMaxI
= splashCeil(yMax
) - 1;
76 SplashClip::SplashClip(SplashClip
*clip
) {
80 antialias
= clip
->antialias
;
89 length
= clip
->length
;
91 paths
= (SplashXPath
**)gmallocn(size
, sizeof(SplashXPath
*));
92 flags
= (Guchar
*)gmallocn(size
, sizeof(Guchar
));
93 scanners
= (SplashXPathScanner
**)
94 gmallocn(size
, sizeof(SplashXPathScanner
*));
95 for (i
= 0; i
< length
; ++i
) {
96 paths
[i
] = clip
->paths
[i
]->copy();
97 flags
[i
] = clip
->flags
[i
];
99 yMinAA
= yMinI
* splashAASize
;
100 yMaxAA
= (yMaxI
+ 1) * splashAASize
- 1;
105 scanners
[i
] = new SplashXPathScanner(paths
[i
], flags
[i
] & splashClipEO
,
110 SplashClip::~SplashClip() {
113 for (i
= 0; i
< length
; ++i
) {
122 void SplashClip::grow(int nPaths
) {
123 if (length
+ nPaths
> size
) {
127 while (size
< length
+ nPaths
) {
130 paths
= (SplashXPath
**)greallocn(paths
, size
, sizeof(SplashXPath
*));
131 flags
= (Guchar
*)greallocn(flags
, size
, sizeof(Guchar
));
132 scanners
= (SplashXPathScanner
**)
133 greallocn(scanners
, size
, sizeof(SplashXPathScanner
*));
137 void SplashClip::resetToRect(SplashCoord x0
, SplashCoord y0
,
138 SplashCoord x1
, SplashCoord y1
) {
141 for (i
= 0; i
< length
; ++i
) {
167 xMinI
= splashFloor(xMin
);
168 yMinI
= splashFloor(yMin
);
169 xMaxI
= splashCeil(xMax
) - 1;
170 yMaxI
= splashCeil(yMax
) - 1;
173 SplashError
SplashClip::clipToRect(SplashCoord x0
, SplashCoord y0
,
174 SplashCoord x1
, SplashCoord y1
) {
178 xMinI
= splashFloor(xMin
);
182 xMaxI
= splashCeil(xMax
) - 1;
187 xMinI
= splashFloor(xMin
);
191 xMaxI
= splashCeil(xMax
) - 1;
197 yMinI
= splashFloor(yMin
);
201 yMaxI
= splashCeil(yMax
) - 1;
206 yMinI
= splashFloor(yMin
);
210 yMaxI
= splashCeil(yMax
) - 1;
216 SplashError
SplashClip::clipToPath(SplashPath
*path
, SplashCoord
*matrix
,
217 SplashCoord flatness
, GBool eo
) {
221 xPath
= new SplashXPath(path
, matrix
, flatness
, gTrue
);
223 // check for an empty path
224 if (xPath
->length
== 0) {
227 xMaxI
= splashCeil(xMax
) - 1;
228 yMaxI
= splashCeil(yMax
) - 1;
231 // check for a rectangle
232 } else if (xPath
->length
== 4 &&
233 ((xPath
->segs
[0].x0
== xPath
->segs
[0].x1
&&
234 xPath
->segs
[0].x0
== xPath
->segs
[1].x0
&&
235 xPath
->segs
[0].x0
== xPath
->segs
[3].x1
&&
236 xPath
->segs
[2].x0
== xPath
->segs
[2].x1
&&
237 xPath
->segs
[2].x0
== xPath
->segs
[1].x1
&&
238 xPath
->segs
[2].x0
== xPath
->segs
[3].x0
&&
239 xPath
->segs
[1].y0
== xPath
->segs
[1].y1
&&
240 xPath
->segs
[1].y0
== xPath
->segs
[0].y1
&&
241 xPath
->segs
[1].y0
== xPath
->segs
[2].y0
&&
242 xPath
->segs
[3].y0
== xPath
->segs
[3].y1
&&
243 xPath
->segs
[3].y0
== xPath
->segs
[0].y0
&&
244 xPath
->segs
[3].y0
== xPath
->segs
[2].y1
) ||
245 (xPath
->segs
[0].y0
== xPath
->segs
[0].y1
&&
246 xPath
->segs
[0].y0
== xPath
->segs
[1].y0
&&
247 xPath
->segs
[0].y0
== xPath
->segs
[3].y1
&&
248 xPath
->segs
[2].y0
== xPath
->segs
[2].y1
&&
249 xPath
->segs
[2].y0
== xPath
->segs
[1].y1
&&
250 xPath
->segs
[2].y0
== xPath
->segs
[3].y0
&&
251 xPath
->segs
[1].x0
== xPath
->segs
[1].x1
&&
252 xPath
->segs
[1].x0
== xPath
->segs
[0].x1
&&
253 xPath
->segs
[1].x0
== xPath
->segs
[2].x0
&&
254 xPath
->segs
[3].x0
== xPath
->segs
[3].x1
&&
255 xPath
->segs
[3].x0
== xPath
->segs
[0].x0
&&
256 xPath
->segs
[3].x0
== xPath
->segs
[2].x1
))) {
257 clipToRect(xPath
->segs
[0].x0
, xPath
->segs
[0].y0
,
258 xPath
->segs
[2].x0
, xPath
->segs
[2].y0
);
267 paths
[length
] = xPath
;
268 flags
[length
] = eo
? splashClipEO
: 0;
270 yMinAA
= yMinI
* splashAASize
;
271 yMaxAA
= (yMaxI
+ 1) * splashAASize
- 1;
276 scanners
[length
] = new SplashXPathScanner(xPath
, eo
, yMinAA
, yMaxAA
);
283 SplashClipResult
SplashClip::testRect(int rectXMin
, int rectYMin
,
284 int rectXMax
, int rectYMax
) {
285 // This tests the rectangle:
286 // x = [rectXMin, rectXMax + 1) (note: rect coords are ints)
287 // y = [rectYMin, rectYMax + 1)
288 // against the clipping region:
289 // x = [xMin, xMax) (note: clipping coords are fp)
291 if ((SplashCoord
)(rectXMax
+ 1) <= xMin
|| (SplashCoord
)rectXMin
>= xMax
||
292 (SplashCoord
)(rectYMax
+ 1) <= yMin
|| (SplashCoord
)rectYMin
>= yMax
) {
293 return splashClipAllOutside
;
295 if ((SplashCoord
)rectXMin
>= xMin
&& (SplashCoord
)(rectXMax
+ 1) <= xMax
&&
296 (SplashCoord
)rectYMin
>= yMin
&& (SplashCoord
)(rectYMax
+ 1) <= yMax
&&
298 return splashClipAllInside
;
300 return splashClipPartial
;
303 SplashClipResult
SplashClip::testSpan(int spanXMin
, int spanXMax
, int spanY
) {
306 // This tests the rectangle:
307 // x = [spanXMin, spanXMax + 1) (note: span coords are ints)
308 // y = [spanY, spanY + 1)
309 // against the clipping region:
310 // x = [xMin, xMax) (note: clipping coords are fp)
312 if ((SplashCoord
)(spanXMax
+ 1) <= xMin
|| (SplashCoord
)spanXMin
>= xMax
||
313 (SplashCoord
)(spanY
+ 1) <= yMin
|| (SplashCoord
)spanY
>= yMax
) {
314 return splashClipAllOutside
;
316 if (!((SplashCoord
)spanXMin
>= xMin
&& (SplashCoord
)(spanXMax
+ 1) <= xMax
&&
317 (SplashCoord
)spanY
>= yMin
&& (SplashCoord
)(spanY
+ 1) <= yMax
)) {
318 return splashClipPartial
;
321 for (i
= 0; i
< length
; ++i
) {
322 if (!scanners
[i
]->testSpan(spanXMin
* splashAASize
,
323 spanXMax
* splashAASize
+ (splashAASize
- 1),
324 spanY
* splashAASize
)) {
325 return splashClipPartial
;
329 for (i
= 0; i
< length
; ++i
) {
330 if (!scanners
[i
]->testSpan(spanXMin
, spanXMax
, spanY
)) {
331 return splashClipPartial
;
335 return splashClipAllInside
;
338 void SplashClip::clipAALine(SplashBitmap
*aaBuf
, int *x0
, int *x1
, int y
, GBool adjustVertLine
) {
339 int xx0
, xx1
, xx
, yy
, i
;
342 // zero out pixels with x < xMin
343 xx0
= *x0
* splashAASize
;
344 xx1
= splashFloor(xMin
* splashAASize
);
345 if (xx1
> aaBuf
->getWidth()) {
346 xx1
= aaBuf
->getWidth();
350 for (yy
= 0; yy
< splashAASize
; ++yy
) {
351 p
= aaBuf
->getDataPtr() + yy
* aaBuf
->getRowSize() + (xx0
>> 3);
352 for (xx
= xx0
; xx
+ 7 < xx1
; xx
+= 8) {
355 if (xx
< xx1
&& !adjustVertLine
) {
356 *p
&= 0xff >> (xx1
& 7);
359 *x0
= splashFloor(xMin
);
362 // zero out pixels with x > xMax
363 xx0
= splashFloor(xMax
* splashAASize
) + 1;
367 xx1
= (*x1
+ 1) * splashAASize
;
368 if (xx0
< xx1
&& !adjustVertLine
) {
369 for (yy
= 0; yy
< splashAASize
; ++yy
) {
370 p
= aaBuf
->getDataPtr() + yy
* aaBuf
->getRowSize() + (xx0
>> 3);
373 *p
&= 0xff00 >> (xx
& 7);
377 for (; xx
< xx1
; xx
+= 8) {
381 *x1
= splashFloor(xMax
);
385 for (i
= 0; i
< length
; ++i
) {
386 scanners
[i
]->clipAALine(aaBuf
, x0
, x1
, y
);
394 if ((*x0
>>1) >= aaBuf
->getRowSize()) {
396 *x0
= (aaBuf
->getRowSize() - 1) << 1;
404 if ((*x1
>>1) >= aaBuf
->getRowSize()) {
406 *x1
= (aaBuf
->getRowSize() - 1) << 1;