]>
git.ipfire.org Git - thirdparty/cups.git/blob - pdftops/SplashXPathScanner.cxx
1 //========================================================================
3 // SplashXPathScanner.cc
5 //========================================================================
10 #pragma implementation
15 #include "SplashMath.h"
16 #include "SplashXPath.h"
17 #include "SplashXPathScanner.h"
19 //------------------------------------------------------------------------
21 struct SplashIntersect
{
22 int x0
, x1
; // intersection of segment with [y, y+1)
23 int count
; // EO/NZWN counter increment
26 static int cmpIntersect(const void *p0
, const void *p1
) {
27 return ((SplashIntersect
*)p0
)->x0
- ((SplashIntersect
*)p1
)->x0
;
30 //------------------------------------------------------------------------
32 //------------------------------------------------------------------------
34 SplashXPathScanner::SplashXPathScanner(SplashXPath
*xPathA
, GBool eoA
) {
36 SplashCoord xMinFP
, yMinFP
, xMaxFP
, yMaxFP
;
43 if (xPath
->length
== 0) {
47 seg
= &xPath
->segs
[0];
48 if (seg
->x0
<= seg
->x1
) {
55 if (seg
->flags
& splashXPathFlip
) {
62 for (i
= 1; i
< xPath
->length
; ++i
) {
63 seg
= &xPath
->segs
[i
];
64 if (seg
->x0
< xMinFP
) {
66 } else if (seg
->x0
> xMaxFP
) {
69 if (seg
->x1
< xMinFP
) {
71 } else if (seg
->x1
> xMaxFP
) {
74 if (seg
->flags
& splashXPathFlip
) {
75 if (seg
->y0
> yMaxFP
) {
79 if (seg
->y1
> yMaxFP
) {
84 xMin
= splashFloor(xMinFP
);
85 xMax
= splashFloor(xMaxFP
);
86 yMin
= splashFloor(yMinFP
);
87 yMax
= splashFloor(yMaxFP
);
93 interLen
= interSize
= 0;
96 SplashXPathScanner::~SplashXPathScanner() {
100 void SplashXPathScanner::getSpanBounds(int y
, int *spanXMin
, int *spanXMax
) {
102 computeIntersections(y
);
105 *spanXMin
= inter
[0].x0
;
106 *spanXMax
= inter
[interLen
- 1].x1
;
108 *spanXMin
= xMax
+ 1;
113 GBool
SplashXPathScanner::test(int x
, int y
) {
117 computeIntersections(y
);
120 for (i
= 0; i
< interLen
&& inter
[i
].x0
<= x
; ++i
) {
121 if (x
<= inter
[i
].x1
) {
124 count
+= inter
[i
].count
;
126 return eo
? (count
& 1) : (count
!= 0);
129 GBool
SplashXPathScanner::testSpan(int x0
, int x1
, int y
) {
133 computeIntersections(y
);
137 for (i
= 0; i
< interLen
&& inter
[i
].x1
< x0
; ++i
) {
138 count
+= inter
[i
].count
;
141 // invariant: the subspan [x0,xx1] is inside the path
147 if (inter
[i
].x0
> xx1
+ 1 &&
148 !(eo
? (count
& 1) : (count
!= 0))) {
151 if (inter
[i
].x1
> xx1
) {
154 count
+= inter
[i
].count
;
161 GBool
SplashXPathScanner::getNextSpan(int y
, int *x0
, int *x1
) {
165 computeIntersections(y
);
167 if (interIdx
>= interLen
) {
170 xx0
= inter
[interIdx
].x0
;
171 xx1
= inter
[interIdx
].x1
;
172 interCount
+= inter
[interIdx
].count
;
174 while (interIdx
< interLen
&&
175 (inter
[interIdx
].x0
<= xx1
||
176 (eo
? (interCount
& 1) : (interCount
!= 0)))) {
177 if (inter
[interIdx
].x1
> xx1
) {
178 xx1
= inter
[interIdx
].x1
;
180 interCount
+= inter
[interIdx
].count
;
188 void SplashXPathScanner::computeIntersections(int y
) {
189 SplashCoord xSegMin
, xSegMax
, ySegMin
, ySegMax
, xx0
, xx1
;
193 // find the first segment that intersects [y, y+1)
194 i
= (y
>= interY
) ? xPathIdx
: 0;
195 while (i
< xPath
->length
&&
196 xPath
->segs
[i
].y0
< y
&& xPath
->segs
[i
].y1
< y
) {
201 // find all of the segments that intersect [y, y+1) and create an
202 // Intersect element for each one
204 for (j
= i
; j
< xPath
->length
; ++j
) {
205 seg
= &xPath
->segs
[j
];
206 if (seg
->flags
& splashXPathFlip
) {
214 // ensure that: ySegMin < y+1
216 if (ySegMin
>= y
+ 1) {
223 if (interLen
== interSize
) {
224 if (interSize
== 0) {
229 inter
= (SplashIntersect
*)greallocn(inter
, interSize
,
230 sizeof(SplashIntersect
));
233 if (seg
->flags
& splashXPathHoriz
) {
236 } else if (seg
->flags
& splashXPathVert
) {
239 if (seg
->x0
< seg
->x1
) {
246 // intersection with top edge
247 xx0
= seg
->x0
+ ((SplashCoord
)y
- seg
->y0
) * seg
->dxdy
;
248 // intersection with bottom edge
249 xx1
= seg
->x0
+ ((SplashCoord
)y
+ 1 - seg
->y0
) * seg
->dxdy
;
250 // the segment may not actually extend to the top and/or bottom edges
253 } else if (xx0
> xSegMax
) {
258 } else if (xx1
> xSegMax
) {
263 inter
[interLen
].x0
= splashFloor(xx0
);
264 inter
[interLen
].x1
= splashFloor(xx1
);
266 inter
[interLen
].x0
= splashFloor(xx1
);
267 inter
[interLen
].x1
= splashFloor(xx0
);
270 (SplashCoord
)y
< ySegMax
&&
271 !(seg
->flags
& splashXPathHoriz
)) {
272 inter
[interLen
].count
= eo
? 1
273 : (seg
->flags
& splashXPathFlip
) ? 1 : -1;
275 inter
[interLen
].count
= 0;
280 qsort(inter
, interLen
, sizeof(SplashIntersect
), &cmpIntersect
);