/src/xpdf-4.04/splash/SplashXPathScanner.cc
Line | Count | Source (jump to first uncovered line) |
1 | | //======================================================================== |
2 | | // |
3 | | // SplashXPathScanner.cc |
4 | | // |
5 | | // Copyright 2003-2013 Glyph & Cog, LLC |
6 | | // |
7 | | //======================================================================== |
8 | | |
9 | | #include <aconf.h> |
10 | | |
11 | | #ifdef USE_GCC_PRAGMAS |
12 | | #pragma implementation |
13 | | #endif |
14 | | |
15 | | #include <stdlib.h> |
16 | | #include <string.h> |
17 | | #if HAVE_STD_SORT |
18 | | #include <algorithm> |
19 | | #endif |
20 | | #include "gmem.h" |
21 | | #include "gmempp.h" |
22 | | #include "GList.h" |
23 | | #include "SplashMath.h" |
24 | | #include "SplashXPath.h" |
25 | | #include "SplashXPathScanner.h" |
26 | | |
27 | | //------------------------------------------------------------------------ |
28 | | |
29 | | #if ANTIALIAS_256 |
30 | | |
31 | | #define aaVert 15 |
32 | | #define aaHoriz 17 |
33 | | |
34 | | #else |
35 | | |
36 | 0 | #define aaVert 4 |
37 | 0 | #define aaHoriz 4 |
38 | | |
39 | | static Guchar map16to255[17] = { |
40 | | 0, |
41 | | 16, |
42 | | 32, |
43 | | 48, |
44 | | 64, |
45 | | 80, |
46 | | 96, |
47 | | 112, |
48 | | 128, |
49 | | 143, |
50 | | 159, |
51 | | 175, |
52 | | 191, |
53 | | 207, |
54 | | 223, |
55 | | 239, |
56 | | 255 |
57 | | }; |
58 | | |
59 | | #endif |
60 | | |
61 | | //------------------------------------------------------------------------ |
62 | | |
63 | | SplashXPathScanner::SplashXPathScanner(SplashXPath *xPathA, GBool eo, |
64 | 0 | int yMinA, int yMaxA) { |
65 | 0 | xPath = xPathA; |
66 | 0 | eoMask = eo ? 1 : 0xffffffff; |
67 | 0 | yMin = yMinA; |
68 | 0 | yMax = yMaxA; |
69 | 0 | if (xPath->isRect) { |
70 | 0 | rectX0I = splashFloor(xPath->rectX0); |
71 | 0 | rectY0I = splashFloor(xPath->rectY0); |
72 | 0 | rectX1I = splashFloor(xPath->rectX1); |
73 | 0 | rectY1I = splashFloor(xPath->rectY1); |
74 | 0 | } |
75 | |
|
76 | 0 | pre = &preSeg; |
77 | 0 | post = &postSeg; |
78 | 0 | pre->mx = xPath->xMin - 1; |
79 | 0 | post->mx = xPath->xMax + 1; |
80 | |
|
81 | 0 | resetDone = gFalse; |
82 | 0 | resetAA = gFalse; |
83 | 0 | } |
84 | | |
85 | 0 | SplashXPathScanner::~SplashXPathScanner() { |
86 | 0 | } |
87 | | |
88 | | void SplashXPathScanner::insertSegmentBefore(SplashXPathSeg *s, |
89 | 0 | SplashXPathSeg *sNext) { |
90 | 0 | SplashXPathSeg *sPrev; |
91 | |
|
92 | 0 | sPrev = sNext->prev; |
93 | 0 | sPrev->next = s; |
94 | 0 | s->prev = sPrev; |
95 | 0 | s->next = sNext; |
96 | 0 | sNext->prev = s; |
97 | 0 | } |
98 | | |
99 | 0 | void SplashXPathScanner::removeSegment(SplashXPathSeg *s) { |
100 | 0 | SplashXPathSeg *sPrev, *sNext; |
101 | |
|
102 | 0 | sPrev = s->prev; |
103 | 0 | sNext = s->next; |
104 | 0 | sPrev->next = sNext; |
105 | 0 | sNext->prev = sPrev; |
106 | 0 | s->prev = s->next = NULL; |
107 | 0 | } |
108 | | |
109 | | void SplashXPathScanner::moveSegmentAfter(SplashXPathSeg *s, |
110 | 0 | SplashXPathSeg *sPrev) { |
111 | 0 | SplashXPathSeg *sNext; |
112 | |
|
113 | 0 | s->prev->next = s->next; |
114 | 0 | s->next->prev = s->prev; |
115 | |
|
116 | 0 | sNext = sPrev->next; |
117 | 0 | sPrev->next = s; |
118 | 0 | s->prev = sPrev; |
119 | 0 | s->next = sNext; |
120 | 0 | sNext->prev = s; |
121 | 0 | } |
122 | | |
123 | 0 | void SplashXPathScanner::reset(GBool aa, GBool aaChanged) { |
124 | 0 | SplashXPathSeg *seg; |
125 | 0 | SplashCoord y; |
126 | 0 | int i; |
127 | | |
128 | | //--- initialize segment parameters |
129 | 0 | for (i = 0; i < xPath->length; ++i) { |
130 | 0 | seg = &xPath->segs[i]; |
131 | 0 | if (aa) { |
132 | 0 | if (aaChanged) { |
133 | 0 | seg->iy = splashFloor(seg->y0 * aaVert); |
134 | 0 | } |
135 | 0 | y = (SplashCoord)(seg->iy + 1) / (SplashCoord)aaVert; |
136 | 0 | } else { |
137 | 0 | if (aaChanged) { |
138 | 0 | seg->iy = splashFloor(seg->y0); |
139 | 0 | } |
140 | 0 | y = (SplashCoord)(seg->iy + 1); |
141 | 0 | } |
142 | 0 | seg->sx0 = seg->x0; |
143 | 0 | if (seg->y1 <= y) { |
144 | 0 | seg->sx1 = seg->x1; |
145 | 0 | } else { |
146 | 0 | seg->sx1 = seg->x0 + (y - seg->y0) * seg->dxdy; |
147 | 0 | } |
148 | 0 | seg->mx = (seg->sx0 <= seg->sx1) ? seg->sx0 : seg->sx1; |
149 | 0 | seg->prev = seg->next = NULL; |
150 | 0 | } |
151 | | |
152 | | //--- sort the inactive segments by iy, mx |
153 | 0 | if (aaChanged) { |
154 | 0 | #if HAVE_STD_SORT |
155 | 0 | std::sort(xPath->segs, xPath->segs + xPath->length, &SplashXPathSeg::cmpMX); |
156 | | #else |
157 | | qsort(xPath->segs, xPath->length, sizeof(SplashXPathSeg), |
158 | | &SplashXPathSeg::cmpMX); |
159 | | #endif |
160 | 0 | } |
161 | | |
162 | | //--- initialize the active list |
163 | 0 | pre->prev = NULL; |
164 | 0 | pre->next = post; |
165 | 0 | post->prev = pre; |
166 | 0 | post->next = NULL; |
167 | | |
168 | | //--- initialize the scan state |
169 | 0 | nextSeg = 0; |
170 | 0 | if (xPath->length) { |
171 | 0 | yBottomI = xPath->segs[0].iy; |
172 | 0 | if (aa) { |
173 | 0 | yBottomI -= yBottomI % aaVert; |
174 | 0 | } |
175 | 0 | } else { |
176 | 0 | yBottomI = 0; |
177 | 0 | } |
178 | 0 | yTopI = yBottomI - 1; |
179 | 0 | if (aa) { |
180 | 0 | yTop = (SplashCoord)yTopI / (SplashCoord)aaVert; |
181 | 0 | yBottom = (SplashCoord)yBottomI / (SplashCoord)aaVert; |
182 | 0 | } else { |
183 | 0 | yTop = (SplashCoord)yTopI; |
184 | 0 | yBottom = (SplashCoord)yBottomI; |
185 | 0 | } |
186 | |
|
187 | 0 | resetDone = gTrue; |
188 | 0 | resetAA = aa; |
189 | 0 | } |
190 | | |
191 | 0 | void SplashXPathScanner::skip(int newYBottomI, GBool aa) { |
192 | 0 | SplashXPathSeg *s0, *s1,*s2; |
193 | 0 | int iy; |
194 | |
|
195 | 0 | yTopI = newYBottomI - 1; |
196 | 0 | yBottomI = newYBottomI; |
197 | 0 | if (aa) { |
198 | 0 | yTop = (SplashCoord)yTopI / (SplashCoord)aaVert; |
199 | 0 | yBottom = (SplashCoord)yBottomI / (SplashCoord)aaVert; |
200 | 0 | } else { |
201 | 0 | yTop = (SplashCoord)yTopI; |
202 | 0 | yBottom = (SplashCoord)yBottomI; |
203 | 0 | } |
204 | | |
205 | | //--- remove finished segments; update sx0, sx1, mx for active segments |
206 | 0 | s0 = pre->next; |
207 | 0 | while (s0 != post) { |
208 | 0 | s1 = s0->next; |
209 | | |
210 | | // check for a finished segment |
211 | 0 | if (s0->y1 < yTop) { |
212 | 0 | removeSegment(s0); |
213 | | |
214 | | // compute sx0, sx1, mx |
215 | 0 | } else { |
216 | 0 | if (s0->y0 >= yTop) { |
217 | 0 | s0->sx0 = s0->x0; |
218 | 0 | } else { |
219 | 0 | s0->sx0 = s0->x0 + (yTop - s0->y0) * s0->dxdy; |
220 | 0 | } |
221 | 0 | if (s0->y1 <= yBottom) { |
222 | 0 | s0->sx1 = s0->x1; |
223 | 0 | } else { |
224 | 0 | s0->sx1 = s0->x0 + (yBottom - s0->y0) * s0->dxdy; |
225 | 0 | } |
226 | 0 | s0->mx = (s0->sx0 <= s0->sx1) ? s0->sx0 : s0->sx1; |
227 | 0 | } |
228 | |
|
229 | 0 | s0 = s1; |
230 | 0 | } |
231 | | |
232 | | //--- check for intersections |
233 | 0 | s0 = pre->next; |
234 | 0 | if (s0 != post) { |
235 | 0 | s1 = s0->next; |
236 | 0 | while (s1 != post) { |
237 | 0 | if (s1->mx < s0->mx) { |
238 | 0 | for (s2 = s0->prev; s1->mx < s2->mx; s2 = s2->prev) ; |
239 | 0 | moveSegmentAfter(s1, s2); |
240 | 0 | } else { |
241 | 0 | s0 = s1; |
242 | 0 | } |
243 | 0 | s1 = s0->next; |
244 | 0 | } |
245 | 0 | } |
246 | | |
247 | | //--- insert new segments with a merge sort |
248 | | // - this has to be done one (sub)scanline at a time, because the |
249 | | // inactive list is bin-sorted by (sub)scanline |
250 | 0 | while (nextSeg < xPath->length && xPath->segs[nextSeg].iy <= yTopI) { |
251 | | // the first inactive segment determines the next scanline to process |
252 | 0 | iy = xPath->segs[nextSeg].iy; |
253 | 0 | s0 = pre->next; |
254 | 0 | do { |
255 | 0 | s1 = &xPath->segs[nextSeg]; |
256 | 0 | ++nextSeg; |
257 | 0 | if (s1->y1 < yTop) { |
258 | 0 | continue; |
259 | 0 | } |
260 | 0 | if (s1->y0 >= yTop) { |
261 | 0 | s1->sx0 = s1->x0; |
262 | 0 | } else { |
263 | 0 | s1->sx0 = s1->x0 + (yTop - s1->y0) * s1->dxdy; |
264 | 0 | } |
265 | 0 | if (s1->y1 <= yBottom) { |
266 | 0 | s1->sx1 = s1->x1; |
267 | 0 | } else { |
268 | 0 | s1->sx1 = s1->x0 + (yBottom - s1->y0) * s1->dxdy; |
269 | 0 | } |
270 | 0 | s1->mx = (s1->sx0 <= s1->sx1) ? s1->sx0 : s1->sx1; |
271 | 0 | insertSegmentBefore(s1, s0); |
272 | 0 | } while (nextSeg < xPath->length && xPath->segs[nextSeg].iy <= iy); |
273 | 0 | } |
274 | 0 | } |
275 | | |
276 | 0 | void SplashXPathScanner::advance(GBool aa) { |
277 | 0 | SplashXPathSeg *s, *sNext, *s1; |
278 | |
|
279 | 0 | yTopI = yBottomI; |
280 | 0 | yTop = yBottom; |
281 | 0 | yBottomI = yTopI + 1; |
282 | 0 | if (aa) { |
283 | 0 | yBottom = (SplashCoord)yBottomI / (SplashCoord)aaVert; |
284 | 0 | } else { |
285 | 0 | yBottom = (SplashCoord)yBottomI; |
286 | 0 | } |
287 | |
|
288 | 0 | s = pre->next; |
289 | 0 | while (s != post) { |
290 | 0 | sNext = s->next; |
291 | | |
292 | | // check for a finished segment |
293 | 0 | if (s->y1 < yTop) { |
294 | 0 | removeSegment(s); |
295 | |
|
296 | 0 | } else { |
297 | | |
298 | | // compute sx0, sx1, mx |
299 | 0 | s->sx0 = s->sx1; |
300 | 0 | if (s->y1 <= yBottom) { |
301 | 0 | s->sx1 = s->x1; |
302 | 0 | } else { |
303 | 0 | s->sx1 = s->x0 + (yBottom - s->y0) * s->dxdy; |
304 | 0 | } |
305 | 0 | s->mx = (s->sx0 <= s->sx1) ? s->sx0 : s->sx1; |
306 | | |
307 | | // check for intersection |
308 | 0 | if (s->mx < s->prev->mx) { |
309 | 0 | for (s1 = s->prev->prev; s->mx < s1->mx; s1 = s1->prev) ; |
310 | 0 | moveSegmentAfter(s, s1); |
311 | 0 | } |
312 | 0 | } |
313 | |
|
314 | 0 | s = sNext; |
315 | 0 | } |
316 | | |
317 | | // insert new segments |
318 | 0 | s = pre->next; |
319 | 0 | while (nextSeg < xPath->length && xPath->segs[nextSeg].iy <= yTopI) { |
320 | 0 | s1 = &xPath->segs[nextSeg]; |
321 | 0 | ++nextSeg; |
322 | 0 | while (s1->mx > s->mx) { |
323 | 0 | s = s->next; |
324 | 0 | } |
325 | 0 | insertSegmentBefore(s1, s); |
326 | 0 | } |
327 | 0 | } |
328 | | |
329 | | void SplashXPathScanner::generatePixels(int x0, int x1, Guchar *line, |
330 | 0 | int *xMin, int *xMax) { |
331 | 0 | SplashXPathSeg *s; |
332 | 0 | int fillCount, x, xEnd, ix0, ix1, t; |
333 | |
|
334 | 0 | fillCount = 0; |
335 | 0 | x = x0 * aaHoriz; |
336 | 0 | xEnd = (x1 + 1) * aaHoriz; |
337 | 0 | for (s = pre->next; s != post && x < xEnd; s = s->next) { |
338 | 0 | ix0 = splashFloor(s->sx0 * aaHoriz); |
339 | 0 | ix1 = splashFloor(s->sx1 * aaHoriz); |
340 | 0 | if (ix0 > ix1) { |
341 | 0 | t = ix0; ix0 = ix1; ix1 = t; |
342 | 0 | } |
343 | 0 | if (!(fillCount & eoMask)) { |
344 | 0 | if (ix0 > x) { |
345 | 0 | x = ix0; |
346 | 0 | } |
347 | 0 | } |
348 | 0 | if (ix1 >= xEnd) { |
349 | 0 | ix1 = xEnd - 1; |
350 | 0 | } |
351 | 0 | if (x / aaHoriz < *xMin) { |
352 | 0 | *xMin = x / aaHoriz; |
353 | 0 | } |
354 | 0 | if (ix1 / aaHoriz > *xMax) { |
355 | 0 | *xMax = ix1 / aaHoriz; |
356 | 0 | } |
357 | 0 | for (; x <= ix1; ++x) { |
358 | 0 | ++line[x / aaHoriz]; |
359 | 0 | } |
360 | 0 | if (s->y0 <= yTop && s->y1 > yTop) { |
361 | 0 | fillCount += s->count; |
362 | 0 | } |
363 | 0 | } |
364 | 0 | } |
365 | | |
366 | | void SplashXPathScanner::generatePixelsBinary(int x0, int x1, Guchar *line, |
367 | 0 | int *xMin, int *xMax) { |
368 | 0 | SplashXPathSeg *s; |
369 | 0 | int fillCount, x, xEnd, ix0, ix1, t; |
370 | |
|
371 | 0 | fillCount = 0; |
372 | 0 | x = x0; |
373 | 0 | xEnd = x1 + 1; |
374 | 0 | for (s = pre->next; s != post && x < xEnd; s = s->next) { |
375 | 0 | ix0 = splashFloor(s->sx0); |
376 | 0 | ix1 = splashFloor(s->sx1); |
377 | 0 | if (ix0 > ix1) { |
378 | 0 | t = ix0; ix0 = ix1; ix1 = t; |
379 | 0 | } |
380 | 0 | if (!(fillCount & eoMask)) { |
381 | 0 | if (ix0 > x) { |
382 | 0 | x = ix0; |
383 | 0 | } |
384 | 0 | } |
385 | 0 | if (ix1 >= xEnd) { |
386 | 0 | ix1 = xEnd - 1; |
387 | 0 | } |
388 | 0 | if (x < *xMin) { |
389 | 0 | *xMin = x; |
390 | 0 | } |
391 | 0 | if (ix1 > *xMax) { |
392 | 0 | *xMax = ix1; |
393 | 0 | } |
394 | 0 | for (; x <= ix1; ++x) { |
395 | 0 | line[x] = 255; |
396 | 0 | } |
397 | 0 | if (s->y0 <= yTop && s->y1 > yTop) { |
398 | 0 | fillCount += s->count; |
399 | 0 | } |
400 | 0 | } |
401 | 0 | } |
402 | | |
403 | | void SplashXPathScanner::drawRectangleSpan(Guchar *line, int y, |
404 | | int x0, int x1, |
405 | 0 | int *xMin, int *xMax) { |
406 | 0 | SplashCoord edge; |
407 | 0 | Guchar pix; |
408 | 0 | int xe, x; |
409 | |
|
410 | 0 | if (rectX0I > x1 || rectX1I < x0) { |
411 | 0 | return; |
412 | 0 | } |
413 | | |
414 | 0 | *xMin = x0 <= rectX0I ? rectX0I : x0; |
415 | 0 | *xMax = rectX1I <= x1 ? rectX1I : x1; |
416 | | |
417 | | //--- upper edge |
418 | 0 | if (y == rectY0I) { |
419 | | |
420 | | // handle a rectangle less than one pixel high |
421 | 0 | if (rectY0I == rectY1I) { |
422 | 0 | edge = xPath->rectY1 - xPath->rectY0; |
423 | 0 | } else { |
424 | 0 | edge = (SplashCoord)1 - (xPath->rectY0 - rectY0I); |
425 | 0 | } |
426 | | |
427 | | // upper left corner |
428 | 0 | if (x0 <= rectX0I) { |
429 | 0 | pix = (Guchar)splashCeil(edge |
430 | 0 | * ((SplashCoord)1 - (xPath->rectX0 - rectX0I)) |
431 | 0 | * 255); |
432 | 0 | if (pix < 16) { |
433 | 0 | pix = 16; |
434 | 0 | } |
435 | 0 | line[rectX0I] = pix; |
436 | 0 | x = rectX0I + 1; |
437 | 0 | } else { |
438 | 0 | x = x0; |
439 | 0 | } |
440 | | |
441 | | // upper right corner |
442 | 0 | if (rectX1I <= x1) { |
443 | 0 | pix = (Guchar)splashCeil(edge * (xPath->rectX1 - rectX1I) * 255); |
444 | 0 | if (pix < 16) { |
445 | 0 | pix = 16; |
446 | 0 | } |
447 | 0 | line[rectX1I] = pix; |
448 | 0 | xe = rectX1I - 1; |
449 | 0 | } else { |
450 | 0 | xe = x1; |
451 | 0 | } |
452 | | |
453 | | // upper edge |
454 | 0 | pix = (Guchar)splashCeil(edge * 255); |
455 | 0 | if (pix < 16) { |
456 | 0 | pix = 16; |
457 | 0 | } |
458 | 0 | for (; x <= xe; ++x) { |
459 | 0 | line[x] = pix; |
460 | 0 | } |
461 | | |
462 | | //--- lower edge |
463 | 0 | } else if (y == rectY1I) { |
464 | 0 | edge = xPath->rectY1 - rectY1I; |
465 | | |
466 | | // lower left corner |
467 | 0 | if (x0 <= rectX0I) { |
468 | 0 | pix = (Guchar)splashCeil(edge |
469 | 0 | * ((SplashCoord)1 - (xPath->rectX0 - rectX0I)) |
470 | 0 | * 255); |
471 | 0 | if (pix < 16) { |
472 | 0 | pix = 16; |
473 | 0 | } |
474 | 0 | line[rectX0I] = pix; |
475 | 0 | x = rectX0I + 1; |
476 | 0 | } else { |
477 | 0 | x = x0; |
478 | 0 | } |
479 | | |
480 | | // lower right corner |
481 | 0 | if (rectX1I <= x1) { |
482 | 0 | pix = (Guchar)splashCeil(edge * (xPath->rectX1 - rectX1I) * 255); |
483 | 0 | if (pix < 16) { |
484 | 0 | pix = 16; |
485 | 0 | } |
486 | 0 | line[rectX1I] = pix; |
487 | 0 | xe = rectX1I - 1; |
488 | 0 | } else { |
489 | 0 | xe = x1; |
490 | 0 | } |
491 | | |
492 | | // lower edge |
493 | 0 | pix = (Guchar)splashCeil(edge * 255); |
494 | 0 | if (pix < 16) { |
495 | 0 | pix = 16; |
496 | 0 | } |
497 | 0 | for (; x <= xe; ++x) { |
498 | 0 | line[x] = pix; |
499 | 0 | } |
500 | | |
501 | | //--- between the upper and lower edges |
502 | 0 | } else if (y > rectY0I && y < rectY1I) { |
503 | | |
504 | | // left edge |
505 | 0 | if (x0 <= rectX0I) { |
506 | 0 | pix = (Guchar)splashCeil(((SplashCoord)1 - (xPath->rectX0 - rectX0I)) |
507 | 0 | * 255); |
508 | 0 | if (pix < 16) { |
509 | 0 | pix = 16; |
510 | 0 | } |
511 | 0 | line[rectX0I] = pix; |
512 | 0 | x = rectX0I + 1; |
513 | 0 | } else { |
514 | 0 | x = x0; |
515 | 0 | } |
516 | | |
517 | | // right edge |
518 | 0 | if (rectX1I <= x1) { |
519 | 0 | pix = (Guchar)splashCeil((xPath->rectX1 - rectX1I) * 255); |
520 | 0 | if (pix < 16) { |
521 | 0 | pix = 16; |
522 | 0 | } |
523 | 0 | line[rectX1I] = pix; |
524 | 0 | xe = rectX1I - 1; |
525 | 0 | } else { |
526 | 0 | xe = x1; |
527 | 0 | } |
528 | | |
529 | | // middle |
530 | 0 | for (; x <= xe; ++x) { |
531 | 0 | line[x] = 255; |
532 | 0 | } |
533 | 0 | } |
534 | 0 | } |
535 | | |
536 | | void SplashXPathScanner::drawRectangleSpanBinary(Guchar *line, int y, |
537 | | int x0, int x1, |
538 | 0 | int *xMin, int *xMax) { |
539 | 0 | int xe, x; |
540 | |
|
541 | 0 | if (y >= rectY0I && y <= rectY1I) { |
542 | 0 | if (x0 <= rectX0I) { |
543 | 0 | x = rectX0I; |
544 | 0 | } else { |
545 | 0 | x = x0; |
546 | 0 | } |
547 | 0 | *xMin = x; |
548 | 0 | if (rectX1I <= x1) { |
549 | 0 | xe = rectX1I; |
550 | 0 | } else { |
551 | 0 | xe = x1; |
552 | 0 | } |
553 | 0 | *xMax = xe; |
554 | 0 | for (; x <= xe; ++x) { |
555 | 0 | line[x] = 255; |
556 | 0 | } |
557 | 0 | } |
558 | 0 | } |
559 | | |
560 | | void SplashXPathScanner::getSpan(Guchar *line, int y, int x0, int x1, |
561 | 0 | int *xMin, int *xMax) { |
562 | 0 | int iy, x, k; |
563 | |
|
564 | 0 | iy = y * aaVert; |
565 | 0 | if (!resetDone || !resetAA) { |
566 | 0 | reset(gTrue, gTrue); |
567 | 0 | } else if (yBottomI > iy) { |
568 | 0 | reset(gTrue, gFalse); |
569 | 0 | } |
570 | 0 | memset(line + x0, 0, x1 - x0 + 1); |
571 | |
|
572 | 0 | *xMin = x1 + 1; |
573 | 0 | *xMax = x0 - 1; |
574 | |
|
575 | 0 | if (xPath->isRect) { |
576 | 0 | drawRectangleSpan(line, y, x0, x1, xMin, xMax); |
577 | 0 | return; |
578 | 0 | } |
579 | | |
580 | 0 | if (yBottomI < iy) { |
581 | 0 | skip(iy, gTrue); |
582 | 0 | } |
583 | 0 | for (k = 0; k < aaVert; ++k, ++iy) { |
584 | 0 | advance(gTrue); |
585 | 0 | generatePixels(x0, x1, line, xMin, xMax); |
586 | 0 | } |
587 | |
|
588 | 0 | #if !ANTIALIAS_256 |
589 | 0 | for (x = *xMin; x <= *xMax; ++x) { |
590 | 0 | line[x] = map16to255[line[x]]; |
591 | 0 | } |
592 | 0 | #endif |
593 | 0 | } |
594 | | |
595 | | void SplashXPathScanner::getSpanBinary(Guchar *line, int y, int x0, int x1, |
596 | 0 | int *xMin, int *xMax) { |
597 | 0 | int iy; |
598 | |
|
599 | 0 | iy = y; |
600 | 0 | if (!resetDone || resetAA) { |
601 | 0 | reset(gFalse, gTrue); |
602 | 0 | } else if (yBottomI > iy) { |
603 | 0 | reset(gFalse, gFalse); |
604 | 0 | } |
605 | 0 | memset(line + x0, 0, x1 - x0 + 1); |
606 | |
|
607 | 0 | *xMin = x1 + 1; |
608 | 0 | *xMax = x0 - 1; |
609 | |
|
610 | 0 | if (xPath->isRect) { |
611 | 0 | drawRectangleSpanBinary(line, y, x0, x1, xMin, xMax); |
612 | 0 | return; |
613 | 0 | } |
614 | | |
615 | 0 | if (yBottomI < iy) { |
616 | 0 | skip(iy, gFalse); |
617 | 0 | } |
618 | 0 | advance(gFalse); |
619 | 0 | generatePixelsBinary(x0, x1, line, xMin, xMax); |
620 | 0 | } |