[poppler] 3 commits - splash/Splash.cc splash/SplashXPathScanner.cc splash/SplashXPathScanner.h
GitLab Mirror
gitlab-mirror at kemper.freedesktop.org
Fri Oct 5 22:35:24 UTC 2018
splash/Splash.cc | 9 -
splash/SplashXPathScanner.cc | 271 +++++++++++++++++++------------------------
splash/SplashXPathScanner.h | 46 ++++---
3 files changed, 157 insertions(+), 169 deletions(-)
New commits:
commit 0118e221548303b71c2b40a878526d017ef64db5
Author: Stefan Brüns <stefan.bruens at rwth-aachen.de>
Date: Mon Aug 27 02:12:08 2018 +0200
SplashXPathScanner: Reduce complexity of sorting spans
For complex paths, a significant amount of time is spent in
SplashXPathScanner::computeIntersections, more specifically with
sorting the spans in y/x order.
Instead of using one large array for all spans, use a 2-dimensional
structure. As the number of y positions is known upfront, it is
possible to create an array for the y dimension and insert the spans
directly at the appropriate position.
For Y rows with X spans per row, this reduces the complexity for sorting
from O( Y*X log Y*X) to O( Y * X log X), i.e. a reduction by log Y.
For the documents from #57 (fdo#96728) and #24 (fdo#78728), the
runtime/memory is significantly reduced (according to /usr/bin/time -v):
(1) $> pdftoppm -r 18 -aa no runsforever-poppler.pdf
(2) $> pdftoppm surf-types.pdf
Before/After
runsforever-poppler | surf-types
User time (seconds): 2979.80 / 2348.08 | 9.45 / 7.76
Maximum resident set size (kbytes): 51208 / 46288 | 18084 / 14076
diff --git a/splash/SplashXPathScanner.cc b/splash/SplashXPathScanner.cc
index 41600122..b1121693 100644
--- a/splash/SplashXPathScanner.cc
+++ b/splash/SplashXPathScanner.cc
@@ -37,17 +37,6 @@
//------------------------------------------------------------------------
-struct SplashIntersect {
- int y;
- int x0, x1; // intersection of segment with [y, y+1)
- int count; // EO/NZWN counter increment
-};
-
-struct cmpIntersectFunctor {
- bool operator()(const SplashIntersect &i0, const SplashIntersect &i1) {
- return (i0.y != i1.y) ? (i0.y < i1.y) : (i0.x0 < i1.x0);
- }
-};
//------------------------------------------------------------------------
// SplashXPathScanner
@@ -119,14 +108,10 @@ SplashXPathScanner::SplashXPathScanner(SplashXPath *xPathA, GBool eoA,
}
}
- allInter = nullptr;
- inter = nullptr;
computeIntersections();
}
SplashXPathScanner::~SplashXPathScanner() {
- gfree(inter);
- gfree(allInter);
}
void SplashXPathScanner::getBBoxAA(int *xMinA, int *yMinA,
@@ -138,20 +123,18 @@ void SplashXPathScanner::getBBoxAA(int *xMinA, int *yMinA,
}
void SplashXPathScanner::getSpanBounds(int y, int *spanXMin, int *spanXMax) {
- int interBegin, interEnd, xx, i;
-
if (y < yMin || y > yMax) {
- interBegin = interEnd = 0;
- } else {
- interBegin = inter[y - yMin];
- interEnd = inter[y - yMin + 1];
+ *spanXMin = xMax + 1;
+ *spanXMax = xMax;
+ return;
}
- if (interBegin < interEnd) {
- *spanXMin = allInter[interBegin].x0;
- xx = allInter[interBegin].x1;
- for (i = interBegin + 1; i < interEnd; ++i) {
- if (allInter[i].x1 > xx) {
- xx = allInter[i].x1;
+ const auto& line = allIntersections[y - yMin];
+ if (!line.empty()) {
+ *spanXMin = line[0].x0;
+ int xx = line[0].x1;
+ for (unsigned int i = 1; i < line.size(); ++i) {
+ if (line[i].x1 > xx) {
+ xx = line[i].x1;
}
}
*spanXMax = xx;
@@ -162,50 +145,46 @@ void SplashXPathScanner::getSpanBounds(int y, int *spanXMin, int *spanXMax) {
}
GBool SplashXPathScanner::test(int x, int y) {
- int interBegin, interEnd, count, i;
-
if (y < yMin || y > yMax) {
return gFalse;
}
- interBegin = inter[y - yMin];
- interEnd = inter[y - yMin + 1];
- count = 0;
- for (i = interBegin; i < interEnd && allInter[i].x0 <= x; ++i) {
- if (x <= allInter[i].x1) {
+ const auto& line = allIntersections[y - yMin];
+ int count = 0;
+ for (unsigned int i = 0; i < line.size() && line[i].x0 <= x; ++i) {
+ if (x <= line[i].x1) {
return gTrue;
}
- count += allInter[i].count;
+ count += line[i].count;
}
return eo ? (count & 1) : (count != 0);
}
GBool SplashXPathScanner::testSpan(int x0, int x1, int y) {
- int interBegin, interEnd, count, xx1, i;
+ unsigned int i;
if (y < yMin || y > yMax) {
return gFalse;
}
- interBegin = inter[y - yMin];
- interEnd = inter[y - yMin + 1];
- count = 0;
- for (i = interBegin; i < interEnd && allInter[i].x1 < x0; ++i) {
- count += allInter[i].count;
+ const auto& line = allIntersections[y - yMin];
+ int count = 0;
+ for (i = 0; i < line.size() && line[i].x1 < x0; ++i) {
+ count += line[i].count;
}
// invariant: the subspan [x0,xx1] is inside the path
- xx1 = x0 - 1;
+ int xx1 = x0 - 1;
while (xx1 < x1) {
- if (i >= interEnd) {
+ if (i >= line.size()) {
return gFalse;
}
- if (allInter[i].x0 > xx1 + 1 &&
+ if (line[i].x0 > xx1 + 1 &&
!(eo ? (count & 1) : (count != 0))) {
return gFalse;
}
- if (allInter[i].x1 > xx1) {
- xx1 = allInter[i].x1;
+ if (line[i].x1 > xx1) {
+ xx1 = line[i].x1;
}
- count += allInter[i].count;
+ count += line[i].count;
++i;
}
@@ -215,20 +194,20 @@ GBool SplashXPathScanner::testSpan(int x0, int x1, int y) {
GBool SplashXPathScanIterator::getNextSpan(int *x0, int *x1) {
int xx0, xx1;
- if (interIdx >= interEnd) {
+ if (interIdx >= line.size()) {
return gFalse;
}
- xx0 = allInter[interIdx].x0;
- xx1 = allInter[interIdx].x1;
- interCount += allInter[interIdx].count;
+ xx0 = line[interIdx].x0;
+ xx1 = line[interIdx].x1;
+ interCount += line[interIdx].count;
++interIdx;
- while (interIdx < interEnd &&
- (allInter[interIdx].x0 <= xx1 ||
+ while (interIdx < line.size() &&
+ (line[interIdx].x0 <= xx1 ||
(eo ? (interCount & 1) : (interCount != 0)))) {
- if (allInter[interIdx].x1 > xx1) {
- xx1 = allInter[interIdx].x1;
+ if (line[interIdx].x1 > xx1) {
+ xx1 = line[interIdx].x1;
}
- interCount += allInter[interIdx].count;
+ interCount += line[interIdx].count;
++interIdx;
}
*x0 = xx0;
@@ -236,22 +215,20 @@ GBool SplashXPathScanIterator::getNextSpan(int *x0, int *x1) {
return gTrue;
}
-SplashXPathScanIterator::SplashXPathScanIterator(const SplashXPathScanner &scanner, int y) {
- allInter(nullptr),
+SplashXPathScanIterator::SplashXPathScanIterator(const SplashXPathScanner &scanner, int y) :
+ line(
+ (y < scanner.yMin || y > scanner.yMax) ?
+ scanner.allIntersections[0] :
+ scanner.allIntersections[y - scanner.yMin]
+ ),
interIdx(0),
- interEnd(0),
interCount(0),
eo(scanner.eo)
{
if (y < scanner.yMin || y > scanner.yMax) {
- return;
+ // set index to line end
+ interIdx = line.size();
}
-
- allInter = scanner.allInter;
- interIdx = scanner.inter[y - scanner.yMin];
- // no special handling for last row needed,
- // last inter entry contains sentinel value, allInterLen
- interEnd = scanner.inter[y - scanner.yMin + 1];
}
void SplashXPathScanner::computeIntersections() {
@@ -264,10 +241,8 @@ void SplashXPathScanner::computeIntersections() {
}
// build the list of all intersections
- allInterLen = 0;
- allInterSize = 16;
- allInter = (SplashIntersect *)gmallocn(allInterSize,
- sizeof(SplashIntersect));
+ allIntersections.resize(yMax - yMin + 1);
+
for (i = 0; i < xPath->length; ++i) {
seg = &xPath->segs[i];
if (seg->flags & splashXPathFlip) {
@@ -337,56 +312,48 @@ void SplashXPathScanner::computeIntersections() {
}
}
}
- std::sort(allInter, allInter + allInterLen, cmpIntersectFunctor());
-
- // build the list of y pointers
- inter = (int *)gmallocn(yMax - yMin + 2, sizeof(int));
- i = 0;
- for (y = yMin; y <= yMax; ++y) {
- inter[y - yMin] = i;
- while (i < allInterLen && allInter[i].y <= y) {
- ++i;
- }
+ for (auto& line : allIntersections) {
+ std::sort(line.begin(), line.end(),
+ [](const SplashIntersect &i0, const SplashIntersect &i1) {
+ return i0.x0 < i1.x0;
+ });
}
- inter[yMax - yMin + 1] = i;
}
GBool SplashXPathScanner::addIntersection(double segYMin, double segYMax,
Guint segFlags,
int y, int x0, int x1) {
- if (allInterLen == allInterSize) {
- unsigned int newInterSize = ((unsigned int) allInterSize * 2 > INT_MAX / sizeof(SplashIntersect)) ? allInterSize + 32768 : allInterSize * 2;
- if (newInterSize >= INT_MAX / sizeof(SplashIntersect)) {
- error(errInternal, -1, "Bogus memory allocation size in SplashXPathScanner::addIntersection {0:d}", newInterSize);
- return gFalse;
- }
- allInterSize = newInterSize;
- allInter = (SplashIntersect *)greallocn(allInter, newInterSize,
- sizeof(SplashIntersect));
- }
- allInter[allInterLen].y = y;
+ SplashIntersect intersect;
+ intersect.y = y;
if (x0 < x1) {
- allInter[allInterLen].x0 = x0;
- allInter[allInterLen].x1 = x1;
+ intersect.x0 = x0;
+ intersect.x1 = x1;
} else {
- allInter[allInterLen].x0 = x1;
- allInter[allInterLen].x1 = x0;
+ intersect.x0 = x1;
+ intersect.x1 = x0;
}
if (segYMin <= y &&
(SplashCoord)y < segYMax &&
!(segFlags & splashXPathHoriz)) {
- allInter[allInterLen].count = eo ? 1
- : (segFlags & splashXPathFlip) ? 1 : -1;
+ intersect.count = eo ? 1
+ : (segFlags & splashXPathFlip) ? 1 : -1;
} else {
- allInter[allInterLen].count = 0;
+ intersect.count = 0;
+ }
+
+ auto& line = allIntersections[y - yMin];
+ if (line.empty()) {
+ line.reserve(4);
}
- ++allInterLen;
+ line.push_back(intersect);
+
return gTrue;
}
void SplashXPathScanner::renderAALine(SplashBitmap *aaBuf,
int *x0, int *x1, int y, GBool adjustVertLine) {
- int xx0, xx1, xx, xxMin, xxMax, yy, yyMax, interEnd, interIdx, interCount;
+ int xx0, xx1, xx, xxMin, xxMax, yy, yyMax, interCount;
+ size_t interIdx;
Guchar mask;
SplashColorPtr p;
@@ -403,23 +370,23 @@ void SplashXPathScanner::renderAALine(SplashBitmap *aaBuf,
if (yyMax + splashAASize * y > yMax) {
yyMax = yMax - splashAASize * y;
}
- interIdx = inter[splashAASize * y + yy - yMin];
for (; yy <= yyMax; ++yy) {
- interEnd = inter[splashAASize * y + yy - yMin + 1];
+ const auto& line = allIntersections[splashAASize * y + yy - yMin];
+ interIdx = 0;
interCount = 0;
- while (interIdx < interEnd) {
- xx0 = allInter[interIdx].x0;
- xx1 = allInter[interIdx].x1;
- interCount += allInter[interIdx].count;
+ while (interIdx < line.size()) {
+ xx0 = line[interIdx].x0;
+ xx1 = line[interIdx].x1;
+ interCount += line[interIdx].count;
++interIdx;
- while (interIdx < interEnd &&
- (allInter[interIdx].x0 <= xx1 ||
+ while (interIdx < line.size() &&
+ (line[interIdx].x0 <= xx1 ||
(eo ? (interCount & 1) : (interCount != 0)))) {
- if (allInter[interIdx].x1 > xx1) {
- xx1 = allInter[interIdx].x1;
+ if (line[interIdx].x1 > xx1) {
+ xx1 = line[interIdx].x1;
}
- interCount += allInter[interIdx].count;
+ interCount += line[interIdx].count;
++interIdx;
}
if (xx0 < 0) {
@@ -466,7 +433,8 @@ void SplashXPathScanner::renderAALine(SplashBitmap *aaBuf,
void SplashXPathScanner::clipAALine(SplashBitmap *aaBuf,
int *x0, int *x1, int y) {
- int xx0, xx1, xx, yy, yyMin, yyMax, interEnd, interIdx, interCount;
+ int xx0, xx1, xx, yy, yyMin, yyMax, interCount;
+ size_t interIdx;
Guchar mask;
SplashColorPtr p;
@@ -482,21 +450,21 @@ void SplashXPathScanner::clipAALine(SplashBitmap *aaBuf,
for (yy = 0; yy < splashAASize; ++yy) {
xx = *x0 * splashAASize;
if (yy >= yyMin && yy <= yyMax) {
- interIdx = inter[splashAASize * y + yy - yMin];
- interEnd = inter[splashAASize * y + yy - yMin + 1];
+ const auto& line = allIntersections[splashAASize * y + yy - yMin];
+ interIdx = 0;
interCount = 0;
- while (interIdx < interEnd && xx < (*x1 + 1) * splashAASize) {
- xx0 = allInter[interIdx].x0;
- xx1 = allInter[interIdx].x1;
- interCount += allInter[interIdx].count;
+ while (interIdx < line.size() && xx < (*x1 + 1) * splashAASize) {
+ xx0 = line[interIdx].x0;
+ xx1 = line[interIdx].x1;
+ interCount += line[interIdx].count;
++interIdx;
- while (interIdx < interEnd &&
- (allInter[interIdx].x0 <= xx1 ||
+ while (interIdx < line.size() &&
+ (line[interIdx].x0 <= xx1 ||
(eo ? (interCount & 1) : (interCount != 0)))) {
- if (allInter[interIdx].x1 > xx1) {
- xx1 = allInter[interIdx].x1;
+ if (line[interIdx].x1 > xx1) {
+ xx1 = line[interIdx].x1;
}
- interCount += allInter[interIdx].count;
+ interCount += line[interIdx].count;
++interIdx;
}
if (xx0 > aaBuf->getWidth()) {
diff --git a/splash/SplashXPathScanner.h b/splash/SplashXPathScanner.h
index d815878a..427448af 100644
--- a/splash/SplashXPathScanner.h
+++ b/splash/SplashXPathScanner.h
@@ -28,9 +28,16 @@
#include "SplashTypes.h"
+#include <vector>
+
class SplashXPath;
class SplashBitmap;
-struct SplashIntersect;
+
+struct SplashIntersect {
+ int y;
+ int x0, x1; // intersection of segment with [y, y+1)
+ int count; // EO/NZWN counter increment
+};
//------------------------------------------------------------------------
// SplashXPathScanner
@@ -91,10 +98,8 @@ private:
int xMin, yMin, xMax, yMax;
GBool partialClip;
- SplashIntersect *allInter; // array of intersections
- int allInterLen; // number of intersections in <allInter>
- int allInterSize; // size of the <allInter> array
- int *inter; // indexes into <allInter> for each y value
+ typedef std::vector<SplashIntersect> IntersectionLine;
+ std::vector<IntersectionLine> allIntersections;
friend class SplashXPathScanIterator;
};
@@ -108,9 +113,10 @@ public:
GBool getNextSpan(int *x0, int *x1);
private:
- const SplashIntersect *allInter;
- int interIdx; // current index into <allInter>
- int interEnd; // last index into <allInter>, noninclusive
+ typedef std::vector<SplashIntersect> IntersectionLine;
+ const IntersectionLine &line;
+
+ size_t interIdx; // current index into <line>
int interCount; // current EO/NZWN counter
const GBool eo;
};
commit 7ef04b5643c6bad8cd4b6f6fc4aa9b800c49406f
Author: Stefan Brüns <stefan.bruens at rwth-aachen.de>
Date: Fri Aug 24 00:50:26 2018 +0200
SplashXPathScanner: Clamp y range to yMin/yMax outside the loop
Instead of implicitly clamping by setting interIdx == interEnd, calculate
the first and last y position outside the loop, and use these as loop
bounds.
diff --git a/splash/SplashXPathScanner.cc b/splash/SplashXPathScanner.cc
index b41245a7..41600122 100644
--- a/splash/SplashXPathScanner.cc
+++ b/splash/SplashXPathScanner.cc
@@ -386,7 +386,7 @@ GBool SplashXPathScanner::addIntersection(double segYMin, double segYMax,
void SplashXPathScanner::renderAALine(SplashBitmap *aaBuf,
int *x0, int *x1, int y, GBool adjustVertLine) {
- int xx0, xx1, xx, xxMin, xxMax, yy, interEnd, interIdx, interCount;
+ int xx0, xx1, xx, xxMin, xxMax, yy, yyMax, interEnd, interIdx, interCount;
Guchar mask;
SplashColorPtr p;
@@ -394,21 +394,19 @@ void SplashXPathScanner::renderAALine(SplashBitmap *aaBuf,
xxMin = aaBuf->getWidth();
xxMax = -1;
if (yMin <= yMax) {
- if (splashAASize * y < yMin) {
- interIdx = inter[0];
- } else if (splashAASize * y > yMax) {
- interIdx = inter[yMax - yMin + 1];
- } else {
- interIdx = inter[splashAASize * y - yMin];
+ yy = 0;
+ yyMax = splashAASize - 1;
+ // clamp start and end position
+ if (yMin > splashAASize * y) {
+ yy = yMin - splashAASize * y;
}
- for (yy = 0; yy < splashAASize; ++yy) {
- if (splashAASize * y + yy < yMin) {
- interEnd = inter[0];
- } else if (splashAASize * y + yy > yMax) {
- interEnd = inter[yMax - yMin + 1];
- } else {
- interEnd = inter[splashAASize * y + yy - yMin + 1];
- }
+ if (yyMax + splashAASize * y > yMax) {
+ yyMax = yMax - splashAASize * y;
+ }
+ interIdx = inter[splashAASize * y + yy - yMin];
+
+ for (; yy <= yyMax; ++yy) {
+ interEnd = inter[splashAASize * y + yy - yMin + 1];
interCount = 0;
while (interIdx < interEnd) {
xx0 = allInter[interIdx].x0;
@@ -468,25 +466,24 @@ void SplashXPathScanner::renderAALine(SplashBitmap *aaBuf,
void SplashXPathScanner::clipAALine(SplashBitmap *aaBuf,
int *x0, int *x1, int y) {
- int xx0, xx1, xx, yy, interEnd, interIdx, interCount;
+ int xx0, xx1, xx, yy, yyMin, yyMax, interEnd, interIdx, interCount;
Guchar mask;
SplashColorPtr p;
+ yyMin = 0;
+ yyMax = splashAASize - 1;
+ // clamp start and end position
+ if (yMin > splashAASize * y) {
+ yyMin = yMin - splashAASize * y;
+ }
+ if (yyMax + splashAASize * y > yMax) {
+ yyMax = yMax - splashAASize * y;
+ }
for (yy = 0; yy < splashAASize; ++yy) {
xx = *x0 * splashAASize;
- if (yMin <= yMax) {
- if (splashAASize * y + yy < yMin) {
- interIdx = interEnd = inter[0];
- } else if (splashAASize * y + yy > yMax) {
- interIdx = interEnd = inter[yMax - yMin + 1];
- } else {
- interIdx = inter[splashAASize * y + yy - yMin];
- if (splashAASize * y + yy > yMax) {
- interEnd = inter[yMax - yMin + 1];
- } else {
- interEnd = inter[splashAASize * y + yy - yMin + 1];
- }
- }
+ if (yy >= yyMin && yy <= yyMax) {
+ interIdx = inter[splashAASize * y + yy - yMin];
+ interEnd = inter[splashAASize * y + yy - yMin + 1];
interCount = 0;
while (interIdx < interEnd && xx < (*x1 + 1) * splashAASize) {
xx0 = allInter[interIdx].x0;
commit 68fdbfd0b159e8cf146c480f0d14f5d7adfd5806
Author: Stefan Brüns <stefan.bruens at rwth-aachen.de>
Date: Sat May 26 19:51:21 2018 +0200
SplashXPathScanner: Move state out of SplashXPathScanner for iterating spans
Iterating through spans is independent of the spans itself. Moving the
iteration to a seperate class allows to keep the iteration state out
of SplashXPathScanner, and also allows to move invariant code out of
getNextSpan(...).
diff --git a/splash/Splash.cc b/splash/Splash.cc
index e8b76ec0..187b99a7 100644
--- a/splash/Splash.cc
+++ b/splash/Splash.cc
@@ -2607,7 +2607,8 @@ SplashError Splash::fillWithPattern(SplashPath *path, GBool eo,
}
} else {
for (y = yMinI; y <= yMaxI; ++y) {
- while (scanner->getNextSpan(y, &x0, &x1)) {
+ SplashXPathScanIterator iterator(*scanner, y);
+ while (iterator.getNextSpan(&x0, &x1)) {
if (clipRes == splashClipAllInside) {
drawSpan(&pipe, x0, x1, y, gTrue);
} else {
@@ -2729,7 +2730,8 @@ SplashError Splash::xorFill(SplashPath *path, GBool eo) {
// draw the spans
for (y = yMinI; y <= yMaxI; ++y) {
- while (scanner->getNextSpan(y, &x0, &x1)) {
+ SplashXPathScanIterator iterator(*scanner, y);
+ while (iterator.getNextSpan(&x0, &x1)) {
if (clipRes == splashClipAllInside) {
drawSpan(&pipe, x0, x1, y, gTrue);
} else {
@@ -6491,7 +6493,8 @@ SplashError Splash::shadedFill(SplashPath *path, GBool hasBBox,
} else {
SplashClipResult clipRes2;
for (y = yMinI; y <= yMaxI; ++y) {
- while (scanner->getNextSpan(y, &x0, &x1)) {
+ SplashXPathScanIterator iterator(*scanner, y);
+ while (iterator.getNextSpan(&x0, &x1)) {
if (clipRes == splashClipAllInside) {
drawSpan(&pipe, x0, x1, y, gTrue);
} else {
diff --git a/splash/SplashXPathScanner.cc b/splash/SplashXPathScanner.cc
index 1e48e90b..b41245a7 100644
--- a/splash/SplashXPathScanner.cc
+++ b/splash/SplashXPathScanner.cc
@@ -122,7 +122,6 @@ SplashXPathScanner::SplashXPathScanner(SplashXPath *xPathA, GBool eoA,
allInter = nullptr;
inter = nullptr;
computeIntersections();
- interY = yMin - 1;
}
SplashXPathScanner::~SplashXPathScanner() {
@@ -213,18 +212,9 @@ GBool SplashXPathScanner::testSpan(int x0, int x1, int y) {
return gTrue;
}
-GBool SplashXPathScanner::getNextSpan(int y, int *x0, int *x1) {
- int interEnd, xx0, xx1;
+GBool SplashXPathScanIterator::getNextSpan(int *x0, int *x1) {
+ int xx0, xx1;
- if (y < yMin || y > yMax) {
- return gFalse;
- }
- if (interY != y) {
- interY = y;
- interIdx = inter[y - yMin];
- interCount = 0;
- }
- interEnd = inter[y - yMin + 1];
if (interIdx >= interEnd) {
return gFalse;
}
@@ -246,6 +236,24 @@ GBool SplashXPathScanner::getNextSpan(int y, int *x0, int *x1) {
return gTrue;
}
+SplashXPathScanIterator::SplashXPathScanIterator(const SplashXPathScanner &scanner, int y) {
+ allInter(nullptr),
+ interIdx(0),
+ interEnd(0),
+ interCount(0),
+ eo(scanner.eo)
+{
+ if (y < scanner.yMin || y > scanner.yMax) {
+ return;
+ }
+
+ allInter = scanner.allInter;
+ interIdx = scanner.inter[y - scanner.yMin];
+ // no special handling for last row needed,
+ // last inter entry contains sentinel value, allInterLen
+ interEnd = scanner.inter[y - scanner.yMin + 1];
+}
+
void SplashXPathScanner::computeIntersections() {
SplashXPathSeg *seg;
SplashCoord segXMin, segXMax, segYMin, segYMax, xx0, xx1;
@@ -378,7 +386,7 @@ GBool SplashXPathScanner::addIntersection(double segYMin, double segYMax,
void SplashXPathScanner::renderAALine(SplashBitmap *aaBuf,
int *x0, int *x1, int y, GBool adjustVertLine) {
- int xx0, xx1, xx, xxMin, xxMax, yy, interEnd;
+ int xx0, xx1, xx, xxMin, xxMax, yy, interEnd, interIdx, interCount;
Guchar mask;
SplashColorPtr p;
@@ -460,7 +468,7 @@ void SplashXPathScanner::renderAALine(SplashBitmap *aaBuf,
void SplashXPathScanner::clipAALine(SplashBitmap *aaBuf,
int *x0, int *x1, int y) {
- int xx0, xx1, xx, yy, interEnd;
+ int xx0, xx1, xx, yy, interEnd, interIdx, interCount;
Guchar mask;
SplashColorPtr p;
diff --git a/splash/SplashXPathScanner.h b/splash/SplashXPathScanner.h
index b6c358d9..d815878a 100644
--- a/splash/SplashXPathScanner.h
+++ b/splash/SplashXPathScanner.h
@@ -69,13 +69,6 @@ public:
// path.
GBool testSpan(int x0, int x1, int y);
- // Returns the next span inside the path at <y>. If <y> is
- // different than the previous call to getNextSpan, this returns the
- // first span at <y>; otherwise it returns the next span (relative
- // to the previous call to getNextSpan). Returns false if there are
- // no more spans at <y>.
- GBool getNextSpan(int y, int *x0, int *x1);
-
// Renders one anti-aliased line into <aaBuf>. Returns the min and
// max x coordinates with non-zero pixels in <x0> and <x1>.
void renderAALine(SplashBitmap *aaBuf, int *x0, int *x1, int y,
@@ -102,11 +95,24 @@ private:
int allInterLen; // number of intersections in <allInter>
int allInterSize; // size of the <allInter> array
int *inter; // indexes into <allInter> for each y value
- int interY; // current y value - used by getNextSpan
- int interIdx; // current index into <inter> - used by
- // getNextSpan
- int interCount; // current EO/NZWN counter - used by
- // getNextSpan
+
+ friend class SplashXPathScanIterator;
+};
+
+class SplashXPathScanIterator {
+public:
+ SplashXPathScanIterator(const SplashXPathScanner &scanner, int y);
+
+ // Returns the next span inside the path at the current y position
+ // Returns false if there are no more spans.
+ GBool getNextSpan(int *x0, int *x1);
+
+private:
+ const SplashIntersect *allInter;
+ int interIdx; // current index into <allInter>
+ int interEnd; // last index into <allInter>, noninclusive
+ int interCount; // current EO/NZWN counter
+ const GBool eo;
};
#endif
More information about the poppler
mailing list