diff options
Diffstat (limited to 'Build/source/libs/xpdf/xpdf-src/splash/SplashXPathScanner.cc')
-rw-r--r-- | Build/source/libs/xpdf/xpdf-src/splash/SplashXPathScanner.cc | 929 |
1 files changed, 491 insertions, 438 deletions
diff --git a/Build/source/libs/xpdf/xpdf-src/splash/SplashXPathScanner.cc b/Build/source/libs/xpdf/xpdf-src/splash/SplashXPathScanner.cc index aee60cce61e..3f167b8b311 100644 --- a/Build/source/libs/xpdf/xpdf-src/splash/SplashXPathScanner.cc +++ b/Build/source/libs/xpdf/xpdf-src/splash/SplashXPathScanner.cc @@ -18,6 +18,7 @@ #include <algorithm> #endif #include "gmem.h" +#include "gmempp.h" #include "GList.h" #include "SplashMath.h" #include "SplashXPath.h" @@ -25,543 +26,595 @@ //------------------------------------------------------------------------ -#define minVertStep 0.05 +#if ANTIALIAS_256 + +#define aaVert 15 +#define aaHoriz 17 + +#else + +#define aaVert 4 +#define aaHoriz 4 + +static Guchar map16to255[17] = { + 0, + 16, + 32, + 48, + 64, + 80, + 96, + 112, + 128, + 143, + 159, + 175, + 191, + 207, + 223, + 239, + 255 +}; + +#endif //------------------------------------------------------------------------ -SplashXPathScanner::SplashXPathScanner(SplashXPath *xPathA, GBool eoA, +SplashXPathScanner::SplashXPathScanner(SplashXPath *xPathA, GBool eo, int yMinA, int yMaxA) { xPath = xPathA; - eo = eoA; + eoMask = eo ? 1 : 0xffffffff; yMin = yMinA; yMax = yMaxA; + if (xPath->isRect) { + rectX0I = splashFloor(xPath->rectX0); + rectY0I = splashFloor(xPath->rectY0); + rectX1I = splashFloor(xPath->rectX1); + rectY1I = splashFloor(xPath->rectY1); + } - activeSegs = new GList(); - nextSeg = 0; - yNext = xPath->yMin; + pre = &preSeg; + post = &postSeg; + pre->mx = xPath->xMin - 1; + post->mx = xPath->xMax + 1; + + resetDone = gFalse; + resetAA = gFalse; } SplashXPathScanner::~SplashXPathScanner() { - delete activeSegs; } -void SplashXPathScanner::getSpan(Guchar *line, int y, int x0, int x1) { - SplashXPathSeg *seg, *seg0; - SplashCoord y0, y1, y1p; - GBool intersect, last; - int eoMask, state0, state1, count, i; +void SplashXPathScanner::insertSegmentBefore(SplashXPathSeg *s, + SplashXPathSeg *sNext) { + SplashXPathSeg *sPrev; - //--- clear the scan line buffer - memset(line + x0, 0, x1 - x0 + 1); + sPrev = sNext->prev; + sPrev->next = s; + s->prev = sPrev; + s->next = sNext; + sNext->prev = s; +} + +void SplashXPathScanner::removeSegment(SplashXPathSeg *s) { + SplashXPathSeg *sPrev, *sNext; + + sPrev = s->prev; + sNext = s->next; + sPrev->next = sNext; + sNext->prev = sPrev; + s->prev = s->next = NULL; +} - //--- reset the path - if (yNext != y) { - delete activeSegs; - activeSegs = new GList(); - nextSeg = 0; - while (nextSeg < xPath->length) { - seg = &xPath->segs[nextSeg]; - if (seg->y0 >= y) { - break; +void SplashXPathScanner::moveSegmentAfter(SplashXPathSeg *s, + SplashXPathSeg *sPrev) { + SplashXPathSeg *sNext; + + s->prev->next = s->next; + s->next->prev = s->prev; + + sNext = sPrev->next; + sPrev->next = s; + s->prev = sPrev; + s->next = sNext; + sNext->prev = s; +} + +void SplashXPathScanner::reset(GBool aa, GBool aaChanged) { + SplashXPathSeg *seg; + SplashCoord y; + int i; + + //--- initialize segment parameters + for (i = 0; i < xPath->length; ++i) { + seg = &xPath->segs[i]; + if (aa) { + if (aaChanged) { + seg->iy = splashFloor(seg->y0 * aaVert); } - if (seg->y0 != seg->y1 && seg->y1 > y) { - if (seg->y0 == y) { - seg->xCur0 = seg->x0; - } else { - seg->xCur0 = seg->x0 + ((SplashCoord)y - seg->y0) * seg->dxdy; - } - activeSegs->append(seg); + y = (SplashCoord)(seg->iy + 1) / (SplashCoord)aaVert; + } else { + if (aaChanged) { + seg->iy = splashFloor(seg->y0); } - ++nextSeg; + y = (SplashCoord)(seg->iy + 1); + } + seg->sx0 = seg->x0; + if (seg->y1 <= y) { + seg->sx1 = seg->x1; + } else { + seg->sx1 = seg->x0 + (y - seg->y0) * seg->dxdy; } - activeSegs->sort(&SplashXPathSeg::cmpXi); + seg->mx = (seg->sx0 <= seg->sx1) ? seg->sx0 : seg->sx1; + seg->prev = seg->next = NULL; } - //--- process the scan line - y0 = y; - while (y0 < y + 1) { + //--- sort the inactive segments by iy, mx + if (aaChanged) { +#if HAVE_STD_SORT + std::sort(xPath->segs, xPath->segs + xPath->length, &SplashXPathSeg::cmpMX); +#else + qsort(xPath->segs, xPath->length, sizeof(SplashXPathSeg), + &SplashXPathSeg::cmpMX); +#endif + } - //--- delete finished segs - i = 0; - while (i < activeSegs->getLength()) { - seg = (SplashXPathSeg *)activeSegs->get(i); - if (seg->y1 <= y0) { - activeSegs->del(i); - } else { - ++i; - } - } + //--- initialize the active list + pre->prev = NULL; + pre->next = post; + post->prev = pre; + post->next = NULL; - //--- check for bottom of path - if (!activeSegs->getLength() && nextSeg >= xPath->length) { - break; + //--- initialize the scan state + nextSeg = 0; + if (xPath->length) { + yBottomI = xPath->segs[0].iy; + if (aa) { + yBottomI -= yBottomI % aaVert; } + } else { + yBottomI = 0; + } + yTopI = yBottomI - 1; + if (aa) { + yTop = (SplashCoord)yTopI / (SplashCoord)aaVert; + yBottom = (SplashCoord)yBottomI / (SplashCoord)aaVert; + } else { + yTop = (SplashCoord)yTopI; + yBottom = (SplashCoord)yBottomI; + } + + resetDone = gTrue; + resetAA = aa; +} - //--- sort activeSegs - sortActiveSegs(); +void SplashXPathScanner::skip(int newYBottomI, GBool aa) { + SplashXPathSeg *s0, *s1,*s2; + int iy; + + yTopI = newYBottomI - 1; + yBottomI = newYBottomI; + if (aa) { + yTop = (SplashCoord)yTopI / (SplashCoord)aaVert; + yBottom = (SplashCoord)yBottomI / (SplashCoord)aaVert; + } else { + yTop = (SplashCoord)yTopI; + yBottom = (SplashCoord)yBottomI; + } - //--- add waiting segs - while (nextSeg < xPath->length) { - seg = &xPath->segs[nextSeg]; - if (seg->y0 > y0) { - break; + //--- remove finished segments; update sx0, sx1, mx for active segments + s0 = pre->next; + while (s0 != post) { + s1 = s0->next; + + // check for a finished segment + if (s0->y1 < yTop) { + removeSegment(s0); + + // compute sx0, sx1, mx + } else { + if (s0->y0 >= yTop) { + s0->sx0 = s0->x0; + } else { + s0->sx0 = s0->x0 + (yTop - s0->y0) * s0->dxdy; } - if (seg->y0 != seg->y1) { - seg->xCur0 = seg->x0; - insertActiveSeg(seg); + if (s0->y1 <= yBottom) { + s0->sx1 = s0->x1; + } else { + s0->sx1 = s0->x0 + (yBottom - s0->y0) * s0->dxdy; } - ++nextSeg; + s0->mx = (s0->sx0 <= s0->sx1) ? s0->sx0 : s0->sx1; } - //--- get the next "interesting" y value - y1 = y + 1; - if (nextSeg < xPath->length && xPath->segs[nextSeg].y0 < y1) { - y1 = xPath->segs[nextSeg].y0; - } - for (i = 0; i < activeSegs->getLength(); ++i) { - seg = (SplashXPathSeg *)activeSegs->get(i); - if (seg->y1 < y1) { - y1 = seg->y1; + s0 = s1; + } + + //--- check for intersections + s0 = pre->next; + if (s0 != post) { + s1 = s0->next; + while (s1 != post) { + if (s1->mx < s0->mx) { + for (s2 = s0->prev; s1->mx < s2->mx; s2 = s2->prev) ; + moveSegmentAfter(s1, s2); + } else { + s0 = s1; } + s1 = s0->next; } + } - //--- compute xCur1 values, check for intersections - seg0 = NULL; - intersect = gFalse; - for (i = 0; i < activeSegs->getLength(); ++i) { - seg = (SplashXPathSeg *)activeSegs->get(i); - if (seg->y1 == y1) { - seg->xCur1 = seg->x1; - } else { - seg->xCur1 = seg->x0 + (y1 - seg->y0) * seg->dxdy; + //--- insert new segments with a merge sort + // - this has to be done one (sub)scanline at a time, because the + // inactive list is bin-sorted by (sub)scanline + while (nextSeg < xPath->length && xPath->segs[nextSeg].iy <= yTopI) { + // the first inactive segment determines the next scanline to process + iy = xPath->segs[nextSeg].iy; + s0 = pre->next; + do { + s1 = &xPath->segs[nextSeg]; + ++nextSeg; + if (s1->y1 < yTop) { + continue; } - if (seg0 && seg0->xCur1 > seg->xCur1) { - intersect = gTrue; + if (s1->y0 >= yTop) { + s1->sx0 = s1->x0; + } else { + s1->sx0 = s1->x0 + (yTop - s1->y0) * s1->dxdy; } - seg0 = seg; - } - - //--- draw rectangles - if (intersect) { - for (; y0 < y1; y0 += minVertStep) { - if ((y1p = y0 + minVertStep) >= y1) { - y1p = y1; - last = gTrue; - } else { - last = gFalse; - } - state0 = state1 = count = 0; - seg0 = NULL; - eoMask = eo ? 1 : 0xffffffff; - for (i = 0; i < activeSegs->getLength(); ++i) { - seg = (SplashXPathSeg *)activeSegs->get(i); - if (last && seg->y1 == y1) { - seg->xCur1 = seg->x1; - } else { - seg->xCur1 = seg->x0 + (y1p - seg->y0) * seg->dxdy; - } - count += seg->count; - state1 = count & eoMask; - if (!state0 && state1) { - seg0 = seg; - } else if (state0 && !state1) { - drawRectangle(line, x0, x1, y0, y1p, seg0->xCur0, seg->xCur0); - } - state0 = state1; - } - for (i = 0; i < activeSegs->getLength(); ++i) { - seg = (SplashXPathSeg *)activeSegs->get(i); - seg->xCur0 = seg->xCur1; - } - sortActiveSegs(); + if (s1->y1 <= yBottom) { + s1->sx1 = s1->x1; + } else { + s1->sx1 = s1->x0 + (yBottom - s1->y0) * s1->dxdy; } + s1->mx = (s1->sx0 <= s1->sx1) ? s1->sx0 : s1->sx1; + insertSegmentBefore(s1, s0); + } while (nextSeg < xPath->length && xPath->segs[nextSeg].iy <= iy); + } +} - //--- draw trapezoids - } else { - state0 = state1 = count = 0; - seg0 = NULL; - eoMask = eo ? 1 : 0xffffffff; - for (i = 0; i < activeSegs->getLength(); ++i) { - seg = (SplashXPathSeg *)activeSegs->get(i); - count += seg->count; - state1 = count & eoMask; - if (!state0 && state1) { - seg0 = seg; - } else if (state0 && !state1) { - drawTrapezoid(line, x0, x1, y0, y1, - seg0->xCur0, seg0->xCur1, seg0->dydx, - seg->xCur0, seg->xCur1, seg->dydx); - } - state0 = state1; - } - for (i = 0; i < activeSegs->getLength(); ++i) { - seg = (SplashXPathSeg *)activeSegs->get(i); - seg->xCur0 = seg->xCur1; - } - } +void SplashXPathScanner::advance(GBool aa) { + SplashXPathSeg *s, *sNext, *s1; - //--- next slice - y0 = y1; + yTopI = yBottomI; + yTop = yBottom; + yBottomI = yTopI + 1; + if (aa) { + yBottom = (SplashCoord)yBottomI / (SplashCoord)aaVert; + } else { + yBottom = (SplashCoord)yBottomI; } - yNext = y + 1; -} + s = pre->next; + while (s != post) { + sNext = s->next; -void SplashXPathScanner::getSpanBinary(Guchar *line, int y, int x0, int x1) { - SplashXPathSeg *seg; - int xx0, xx1, xx; - int eoMask, state0, state1, count, i; + // check for a finished segment + if (s->y1 < yTop) { + removeSegment(s); - //--- clear the scan line buffer - memset(line + x0, 0, x1 - x0 + 1); + } else { - //--- reset the path - if (yNext != y) { - delete activeSegs; - activeSegs = new GList(); - nextSeg = 0; - while (nextSeg < xPath->length) { - seg = &xPath->segs[nextSeg]; - if (seg->y0 >= y) { - break; + // compute sx0, sx1, mx + s->sx0 = s->sx1; + if (s->y1 <= yBottom) { + s->sx1 = s->x1; + } else { + s->sx1 = s->x0 + (yBottom - s->y0) * s->dxdy; } - if (seg->y1 > y) { - if (seg->y0 == y) { - seg->xCur0 = seg->x0; - } else { - seg->xCur0 = seg->x0 + ((SplashCoord)y - seg->y0) * seg->dxdy; - } - activeSegs->append(seg); + s->mx = (s->sx0 <= s->sx1) ? s->sx0 : s->sx1; + + // check for intersection + if (s->mx < s->prev->mx) { + for (s1 = s->prev->prev; s->mx < s1->mx; s1 = s1->prev) ; + moveSegmentAfter(s, s1); } - ++nextSeg; } - activeSegs->sort(&SplashXPathSeg::cmpXi); - } - //--- delete finished segs - i = 0; - while (i < activeSegs->getLength()) { - seg = (SplashXPathSeg *)activeSegs->get(i); - if (seg->y1 <= y) { - activeSegs->del(i); - } else { - ++i; - } + s = sNext; } - //--- sort activeSegs - sortActiveSegs(); - - //--- add waiting segs - while (nextSeg < xPath->length) { - seg = &xPath->segs[nextSeg]; - if (seg->y0 >= y + 1) { - break; - } - seg->xCur0 = seg->x0; - insertActiveSeg(seg); + // insert new segments + s = pre->next; + while (nextSeg < xPath->length && xPath->segs[nextSeg].iy <= yTopI) { + s1 = &xPath->segs[nextSeg]; ++nextSeg; - } - - //--- compute xCur1 values - for (i = 0; i < activeSegs->getLength(); ++i) { - seg = (SplashXPathSeg *)activeSegs->get(i); - if (seg->y1 <= y + 1) { - seg->xCur1 = seg->x1; - } else { - seg->xCur1 = seg->x0 + ((SplashCoord)(y + 1) - seg->y0) * seg->dxdy; + while (s1->mx > s->mx) { + s = s->next; } + insertSegmentBefore(s1, s); } +} - //--- draw spans - state0 = state1 = count = 0; - eoMask = eo ? 1 : 0xffffffff; - xx0 = xx1 = 0; // make gcc happy - for (i = 0; i < activeSegs->getLength(); ++i) { - seg = (SplashXPathSeg *)activeSegs->get(i); - if (seg->y0 <= y && seg->y0 < seg->y1) { - count += seg->count; - state1 = count & eoMask; - } - if (state0) { - xx = splashCeil(seg->xCur0) - 1; - if (xx > xx1) { - xx1 = xx; - } - xx = splashFloor(seg->xCur1); - if (xx < xx0) { - xx0 = xx; - } - xx = splashCeil(seg->xCur1) - 1; - if (xx > xx1) { - xx1 = xx; - } - } else { - if (seg->xCur0 < seg->xCur1) { - xx0 = splashFloor(seg->xCur0); - xx1 = splashCeil(seg->xCur1) - 1; - } else { - xx0 = splashFloor(seg->xCur1); - xx1 = splashCeil(seg->xCur0) - 1; - } +void SplashXPathScanner::generatePixels(int x0, int x1, Guchar *line, + int *xMin, int *xMax) { + SplashXPathSeg *s; + int fillCount, x, xEnd, ix0, ix1, t; + + fillCount = 0; + x = x0 * aaHoriz; + xEnd = (x1 + 1) * aaHoriz; + for (s = pre->next; s != post && x < xEnd; s = s->next) { + ix0 = splashFloor(s->sx0 * aaHoriz); + ix1 = splashFloor(s->sx1 * aaHoriz); + if (ix0 > ix1) { + t = ix0; ix0 = ix1; ix1 = t; } - if (!state1) { - if (xx0 < x0) { - xx0 = x0; - } - if (xx1 > x1) { - xx1 = x1; - } - for (xx = xx0; xx <= xx1; ++xx) { - line[xx] = 0xff; + if (!(fillCount & eoMask)) { + if (ix0 > x) { + x = ix0; } } - state0 = state1; + if (ix1 >= xEnd) { + ix1 = xEnd - 1; + } + if (x / aaHoriz < *xMin) { + *xMin = x / aaHoriz; + } + if (ix1 / aaHoriz > *xMax) { + *xMax = ix1 / aaHoriz; + } + for (; x <= ix1; ++x) { + ++line[x / aaHoriz]; + } + if (s->y0 <= yTop && s->y1 > yTop) { + fillCount += s->count; + } } +} - //--- update xCur0 values - for (i = 0; i < activeSegs->getLength(); ++i) { - seg = (SplashXPathSeg *)activeSegs->get(i); - seg->xCur0 = seg->xCur1; +void SplashXPathScanner::generatePixelsBinary(int x0, int x1, Guchar *line, + int *xMin, int *xMax) { + SplashXPathSeg *s; + int fillCount, x, xEnd, ix0, ix1, t; + + fillCount = 0; + x = x0; + xEnd = x1 + 1; + for (s = pre->next; s != post && x < xEnd; s = s->next) { + ix0 = splashFloor(s->sx0); + ix1 = splashFloor(s->sx1); + if (ix0 > ix1) { + t = ix0; ix0 = ix1; ix1 = t; + } + if (!(fillCount & eoMask)) { + if (ix0 > x) { + x = ix0; + } + } + if (ix1 >= xEnd) { + ix1 = xEnd - 1; + } + if (x < *xMin) { + *xMin = x; + } + if (ix1 > *xMax) { + *xMax = ix1; + } + for (; x <= ix1; ++x) { + line[x] = 255; + } + if (s->y0 <= yTop && s->y1 > yTop) { + fillCount += s->count; + } } - - yNext = y + 1; } -inline void SplashXPathScanner::addArea(Guchar *line, int x, SplashCoord a) { - int a2, t; +void SplashXPathScanner::drawRectangleSpan(Guchar *line, int y, + int x0, int x1, + int *xMin, int *xMax) { + SplashCoord edge; + Guchar pix; + int xe, x; - a2 = splashRound(a * 255); - if (a2 <= 0) { + if (rectX0I > x1 || rectX1I < x0) { return; } - t = line[x] + a2; - if (t > 255) { - t = 255; - } - line[x] = t; -} -// Draw a trapezoid with edges: -// top: (xa0, y0) - (xb0, y0) -// left: (xa0, y0) - (xa1, y1) -// right: (xb0, y0) - (xb1, y1) -// bottom: (xa1, y1) - (xb1, y1) -void SplashXPathScanner::drawTrapezoid(Guchar *line, int xMin, int xMax, - SplashCoord y0, SplashCoord y1, - SplashCoord xa0, SplashCoord xa1, - SplashCoord dydxa, - SplashCoord xb0, SplashCoord xb1, - SplashCoord dydxb) { - SplashCoord a, dy; - int x0, x1, x2, x3, x; - - // check for a rectangle - if (dydxa == 0 && dydxb == 0 && xa0 >= xMin && xb0 <= xMax) { - x0 = splashFloor(xa0); - x3 = splashFloor(xb0); - dy = y1 - y0; - if (x0 == x3) { - addArea(line, x0, (xb0 - xa0) * dy); + *xMin = x0 <= rectX0I ? rectX0I : x0; + *xMax = rectX1I <= x1 ? rectX1I : x1; + + //--- upper edge + if (y == rectY0I) { + + // handle a rectangle less than one pixel high + if (rectY0I == rectY1I) { + edge = xPath->rectY1 - xPath->rectY0; + } else { + edge = (SplashCoord)1 - (xPath->rectY0 - rectY0I); + } + + // upper left corner + if (x0 <= rectX0I) { + pix = (Guchar)splashCeil(edge + * ((SplashCoord)1 - (xPath->rectX0 - rectX0I)) + * 255); + if (pix < 16) { + pix = 16; + } + line[rectX0I] = pix; + x = rectX0I + 1; } else { - addArea(line, x0, ((SplashCoord)1 - (xa0 - x0)) * dy); - for (x = x0 + 1; x <= x3 - 1; ++x) { - addArea(line, x, y1 - y0); + x = x0; + } + + // upper right corner + if (rectX1I <= x1) { + pix = (Guchar)splashCeil(edge * (xPath->rectX1 - rectX1I) * 255); + if (pix < 16) { + pix = 16; } - addArea(line, x3, (xb0 - x3) * (y1 - y0)); + line[rectX1I] = pix; + xe = rectX1I - 1; + } else { + xe = x1; } - return; - } - if (dydxa > 0) { - x0 = splashFloor(xa0); - x1 = splashFloor(xa1); - } else { - x0 = splashFloor(xa1); - x1 = splashFloor(xa0); - } - if (x0 < xMin) { - x0 = xMin; - } - if (dydxb > 0) { - x2 = splashFloor(xb0); - x3 = splashFloor(xb1); - } else { - x2 = splashFloor(xb1); - x3 = splashFloor(xb0); - } - if (x3 > xMax) { - x3 = xMax; - } - for (x = x0; x <= x3; ++x) { - a = y1 - y0; - if (x <= x1) { - a -= areaLeft(x, xa0, y0, xa1, y1, dydxa); + // upper edge + pix = (Guchar)splashCeil(edge * 255); + if (pix < 16) { + pix = 16; } - if (x >= x2) { - a -= areaRight(x, xb0, y0, xb1, y1, dydxb); + for (; x <= xe; ++x) { + line[x] = pix; } - addArea(line, x, a); - } -} -// Compute area within a pixel slice ((xp,y0)-(xp+1,y1)) to the left -// of a trapezoid edge ((x0,y0)-(x1,y1)). -SplashCoord SplashXPathScanner::areaLeft(int xp, - SplashCoord x0, SplashCoord y0, - SplashCoord x1, SplashCoord y1, - SplashCoord dydx) { - SplashCoord a, ya, yb; - - if (dydx >= 0) { - if (x0 >= xp) { - if (x1 <= xp + 1) { - a = ((x0 + x1) * 0.5 - xp) * (y1 - y0); - } else { - yb = y0 + ((SplashCoord)(xp + 1) - x0) * dydx; - a = (y1 - y0) - ((SplashCoord)(xp + 1) - x0) * (yb - y0) * 0.5; + //--- lower edge + } else if (y == rectY1I) { + edge = xPath->rectY1 - rectY1I; + + // lower left corner + if (x0 <= rectX0I) { + pix = (Guchar)splashCeil(edge + * ((SplashCoord)1 - (xPath->rectX0 - rectX0I)) + * 255); + if (pix < 16) { + pix = 16; } + line[rectX0I] = pix; + x = rectX0I + 1; } else { - if (x1 <= xp + 1) { - ya = y0 + ((SplashCoord)xp - x0) * dydx; - a = (x1 - xp) * (y1 - ya) * 0.5; - } else { - // ya = y1 - (x1 - xp - 0.5) * dydx; - // a = y1 - ya; - a = (x1 - xp - 0.5) * dydx; - } + x = x0; } - } else { - if (x0 <= xp + 1) { - if (x1 >= xp) { - a = ((x0 + x1) * 0.5 - xp) * (y1 - y0); - } else { - ya = y0 + ((SplashCoord)xp - x0) * dydx; - a = (x0 - xp) * (ya - y0) * 0.5; + + // lower right corner + if (rectX1I <= x1) { + pix = (Guchar)splashCeil(edge * (xPath->rectX1 - rectX1I) * 255); + if (pix < 16) { + pix = 16; } + line[rectX1I] = pix; + xe = rectX1I - 1; } else { - if (x1 >= xp) { - yb = y0 + ((SplashCoord)(xp + 1) - x0) * dydx; - a = (y1 - y0) - ((SplashCoord)(xp + 1) - x1) * (y1 - yb) * 0.5; - } else { - // ya = y0 + (xp - x0 + 0.5) * dydx; - // a = ya - y0; - a = ((SplashCoord)xp - x0 + 0.5) * dydx; - } + xe = x1; } - } - return a; -} -// Compute area within a pixel slice ((xp,y0)-(xp+1,y1)) to the left -// of a trapezoid edge ((x0,y0)-(x1,y1)). -SplashCoord SplashXPathScanner::areaRight(int xp, - SplashCoord x0, SplashCoord y0, - SplashCoord x1, SplashCoord y1, - SplashCoord dydx) { - SplashCoord a, ya, yb; - - if (dydx >= 0) { - if (x0 >= xp) { - if (x1 <= xp + 1) { - a = ((SplashCoord)(xp + 1) - (x0 + x1) * 0.5) * (y1 - y0); - } else { - yb = y0 + ((SplashCoord)(xp + 1) - x0) * dydx; - a = ((SplashCoord)(xp + 1) - x0) * (yb - y0) * 0.5; + // lower edge + pix = (Guchar)splashCeil(edge * 255); + if (pix < 16) { + pix = 16; + } + for (; x <= xe; ++x) { + line[x] = pix; + } + + //--- between the upper and lower edges + } else if (y > rectY0I && y < rectY1I) { + + // left edge + if (x0 <= rectX0I) { + pix = (Guchar)splashCeil(((SplashCoord)1 - (xPath->rectX0 - rectX0I)) + * 255); + if (pix < 16) { + pix = 16; } + line[rectX0I] = pix; + x = rectX0I + 1; } else { - if (x1 <= xp + 1) { - ya = y0 + ((SplashCoord)xp - x0) * dydx; - a = (y1 - y0) - (x1 - xp) * (y1 - ya) * 0.5; - } else { - // ya = y0 + (xp - x0 + 0.5) * dydx; - // a = ya - y0; - a = ((SplashCoord)xp + 0.5 - x0) * dydx; - } + x = x0; } - } else { - if (x0 <= xp + 1) { - if (x1 >= xp) { - a = ((SplashCoord)(xp + 1) - (x0 + x1) * 0.5) * (y1 - y0); - } else { - ya = y0 + ((SplashCoord)xp - x0) * dydx; - a = (y1 - y0) - (x0 - xp) * (ya - y0) * 0.5; + + // right edge + if (rectX1I <= x1) { + pix = (Guchar)splashCeil((xPath->rectX1 - rectX1I) * 255); + if (pix < 16) { + pix = 16; } + line[rectX1I] = pix; + xe = rectX1I - 1; } else { - if (x1 >= xp) { - yb = y0 + ((SplashCoord)(xp + 1) - x0) * dydx; - a = ((SplashCoord)(xp + 1) - x1) * (y1 - yb) * 0.5; - } else { - // ya = y1 - (x1 - xp - 0.5) * dydx; - // a = y1 - ya; - a = (x1 - xp - 0.5) * dydx; - } + xe = x1; + } + + // middle + for (; x <= xe; ++x) { + line[x] = 255; } } - return a; } -void SplashXPathScanner::drawRectangle(Guchar *line, int xMin, int xMax, - SplashCoord y0, SplashCoord y1, - SplashCoord x0, SplashCoord x1) { - SplashCoord dy, a; - int xx0, xx1, x; +void SplashXPathScanner::drawRectangleSpanBinary(Guchar *line, int y, + int x0, int x1, + int *xMin, int *xMax) { + int xe, x; - xx0 = splashFloor(x0); - if (xx0 < xMin) { - xx0 = xMin; - } - xx1 = splashFloor(x1); - if (xx1 > xMax) { - xx1 = xMax; - } - dy = y1 - y0; - for (x = xx0; x <= xx1; ++x) { - a = dy; - if ((SplashCoord)x < x0) { - a -= (x0 - x) * dy; + if (y >= rectY0I && y <= rectY1I) { + if (x0 <= rectX0I) { + x = rectX0I; + } else { + x = x0; } - if ((SplashCoord)(x + 1) > x1) { - a -= ((SplashCoord)(x + 1) - x1) * dy; + *xMin = x; + if (rectX1I <= x1) { + xe = rectX1I; + } else { + xe = x1; + } + *xMax = xe; + for (; x <= xe; ++x) { + line[x] = 255; } - addArea(line, x, a); } } -void SplashXPathScanner::sortActiveSegs() { - SplashXPathSeg *seg0, *seg1; - int i, j, k; +void SplashXPathScanner::getSpan(Guchar *line, int y, int x0, int x1, + int *xMin, int *xMax) { + int iy, x, k; - if (activeSegs->getLength() < 2) { + iy = y * aaVert; + if (!resetDone || !resetAA) { + reset(gTrue, gTrue); + } else if (yBottomI > iy) { + reset(gTrue, gFalse); + } + memset(line + x0, 0, x1 - x0 + 1); + + *xMin = x1 + 1; + *xMax = x0 - 1; + + if (xPath->isRect) { + drawRectangleSpan(line, y, x0, x1, xMin, xMax); return; } - seg0 = (SplashXPathSeg *)activeSegs->get(0); - for (i = 1; i < activeSegs->getLength(); ++i) { - seg1 = (SplashXPathSeg *)activeSegs->get(i); - if (SplashXPathSeg::cmpX(seg0, seg1) > 0) { - for (j = i - 1; j > 0; --j) { - if (SplashXPathSeg::cmpX((SplashXPathSeg *)activeSegs->get(j - 1), - seg1) <= 0) { - break; - } - } - for (k = i; k > j; --k) { - activeSegs->put(k, activeSegs->get(k-1)); - } - activeSegs->put(j, seg1); - } else { - seg0 = seg1; - } + + if (yBottomI < iy) { + skip(iy, gTrue); + } + for (k = 0; k < aaVert; ++k, ++iy) { + advance(gTrue); + generatePixels(x0, x1, line, xMin, xMax); + } + +#if !ANTIALIAS_256 + for (x = *xMin; x <= *xMax; ++x) { + line[x] = map16to255[line[x]]; } +#endif } -void SplashXPathScanner::insertActiveSeg(SplashXPathSeg *seg) { - int i; +void SplashXPathScanner::getSpanBinary(Guchar *line, int y, int x0, int x1, + int *xMin, int *xMax) { + int iy; - for (i = 0; i < activeSegs->getLength(); ++i) { - if (SplashXPathSeg::cmpX(seg, (SplashXPathSeg *)activeSegs->get(i)) < 0) { - break; - } + iy = y; + if (!resetDone || resetAA) { + reset(gFalse, gTrue); + } else if (yBottomI > iy) { + reset(gFalse, gFalse); + } + memset(line + x0, 0, x1 - x0 + 1); + + *xMin = x1 + 1; + *xMax = x0 - 1; + + if (xPath->isRect) { + drawRectangleSpanBinary(line, y, x0, x1, xMin, xMax); + return; + } + + if (yBottomI < iy) { + skip(iy, gFalse); } - activeSegs->insert(i, seg); + advance(gFalse); + generatePixelsBinary(x0, x1, line, xMin, xMax); } |