summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAriya Hidayat <ariya.hidayat@nokia.com>2009-09-01 14:54:09 (GMT)
committerAriya Hidayat <ariya.hidayat@nokia.com>2009-09-01 15:46:21 (GMT)
commit928ee7059f42f7e5157dd25295bd6b9eea686f29 (patch)
tree8b35b7da5bae2f9e5a1e35789bc690a79cc10e9d /src
parent8fab695b7987856da4ebb6b36410dd05aa48c13d (diff)
downloadQt-928ee7059f42f7e5157dd25295bd6b9eea686f29.zip
Qt-928ee7059f42f7e5157dd25295bd6b9eea686f29.tar.gz
Qt-928ee7059f42f7e5157dd25295bd6b9eea686f29.tar.bz2
Speed-up parsing of SVG path data.
Instead of using operations that shuffle the array of numbers, just use pointer to iterate the numbers. This reduced the amount of memory operations during the parsing. In addition, parse the numbers to QVarLengthArray instead of QVector. This works well because usually a path element is typically followed by a short list of numbers. Loading tiger.svg (tests/benchmarks/qsvgrenderer) is now 8% faster, mostly due to the time spent in parsePathDataFast is reduced from 26.1 millions instructions to just 20.5 millions (27% speed-up). Reviewed-by: Kim
Diffstat (limited to 'src')
-rw-r--r--src/svg/qsvghandler.cpp244
1 files changed, 127 insertions, 117 deletions
diff --git a/src/svg/qsvghandler.cpp b/src/svg/qsvghandler.cpp
index 27de011..9683efd 100644
--- a/src/svg/qsvghandler.cpp
+++ b/src/svg/qsvghandler.cpp
@@ -1414,24 +1414,29 @@ static bool parsePathDataFast(const QStringRef &dataStr, QPainterPath &path)
QChar pathElem = *str;
++str;
QChar endc = *end;
- *const_cast<QChar *>(end) = 0; // parseNumbersList requires 0-termination that QStringRef cannot guarantee
- QVector<qreal> arg = parseNumbersList(str);
+ *const_cast<QChar *>(end) = 0; // parseNumbersArray requires 0-termination that QStringRef cannot guarantee
+ QVarLengthArray<qreal, 8> arg;
+ parseNumbersArray(str, arg);
*const_cast<QChar *>(end) = endc;
if (pathElem == QLatin1Char('z') || pathElem == QLatin1Char('Z'))
arg.append(0);//dummy
- while (!arg.isEmpty()) {
+ const qreal *num = arg.constData();
+ int count = arg.count();
+ while (count > 0) {
qreal offsetX = x; // correction offsets
qreal offsetY = y; // for relative commands
switch (pathElem.unicode()) {
case 'm': {
- if (arg.count() < 2) {
- arg.pop_front();
+ if (count < 2) {
+ num++;
+ count--;
break;
}
- x = x0 = arg[0] + offsetX;
- y = y0 = arg[1] + offsetY;
+ x = x0 = num[0] + offsetX;
+ y = y0 = num[1] + offsetY;
+ num += 2;
+ count -= 2;
path.moveTo(x0, y0);
- arg.pop_front(); arg.pop_front();
// As per 1.2 spec 8.3.2 The "moveto" commands
// If a 'moveto' is followed by multiple pairs of coordinates without explicit commands,
@@ -1440,15 +1445,16 @@ static bool parsePathDataFast(const QStringRef &dataStr, QPainterPath &path)
}
break;
case 'M': {
- if (arg.count() < 2) {
- arg.pop_front();
+ if (count < 2) {
+ num++;
+ count--;
break;
}
- x = x0 = arg[0];
- y = y0 = arg[1];
-
+ x = x0 = num[0];
+ y = y0 = num[1];
+ num += 2;
+ count -= 2;
path.moveTo(x0, y0);
- arg.pop_front(); arg.pop_front();
// As per 1.2 spec 8.3.2 The "moveto" commands
// If a 'moveto' is followed by multiple pairs of coordinates without explicit commands,
@@ -1460,96 +1466,104 @@ static bool parsePathDataFast(const QStringRef &dataStr, QPainterPath &path)
case 'Z': {
x = x0;
y = y0;
+ count--; // skip dummy
+ num++;
path.closeSubpath();
- arg.pop_front();//pop dummy
}
break;
case 'l': {
- if (arg.count() < 2) {
- arg.pop_front();
+ if (count < 2) {
+ num++;
+ count--;
break;
}
- x = arg.front() + offsetX;
- arg.pop_front();
- y = arg.front() + offsetY;
- arg.pop_front();
+ x = x0 = num[0] + offsetX;
+ y = y0 = num[1] + offsetY;
+ num += 2;
+ count -= 2;
path.lineTo(x, y);
}
break;
case 'L': {
- if (arg.count() < 2) {
- arg.pop_front();
+ if (count < 2) {
+ num++;
+ count--;
break;
}
- x = arg.front(); arg.pop_front();
- y = arg.front(); arg.pop_front();
+ x = x0 = num[0];
+ y = y0 = num[1];
+ num += 2;
+ count -= 2;
path.lineTo(x, y);
}
break;
case 'h': {
- x = arg.front() + offsetX; arg.pop_front();
+ x = num[0] + offsetX;
+ num++;
+ count--;
path.lineTo(x, y);
}
break;
case 'H': {
- x = arg[0];
+ x = num[0];
+ num++;
+ count--;
path.lineTo(x, y);
- arg.pop_front();
}
break;
case 'v': {
- y = arg[0] + offsetY;
+ y = num[0] + offsetY;
+ num++;
+ count--;
path.lineTo(x, y);
- arg.pop_front();
}
break;
case 'V': {
- y = arg[0];
+ y = num[0];
+ num++;
+ count--;
path.lineTo(x, y);
- arg.pop_front();
}
break;
case 'c': {
- if (arg.count() < 6) {
- while (arg.count())
- arg.pop_front();
+ if (count < 6) {
+ num += count;
+ count = 0;
break;
}
- QPointF c1(arg[0]+offsetX, arg[1]+offsetY);
- QPointF c2(arg[2]+offsetX, arg[3]+offsetY);
- QPointF e(arg[4]+offsetX, arg[5]+offsetY);
+ QPointF c1(num[0] + offsetX, num[1] + offsetY);
+ QPointF c2(num[2] + offsetX, num[3] + offsetY);
+ QPointF e(num[4] + offsetX, num[5] + offsetY);
+ num += 6;
+ count -= 6;
path.cubicTo(c1, c2, e);
ctrlPt = c2;
x = e.x();
y = e.y();
- arg.pop_front(); arg.pop_front();
- arg.pop_front(); arg.pop_front();
- arg.pop_front(); arg.pop_front();
break;
}
case 'C': {
- if (arg.count() < 6) {
- while (arg.count())
- arg.pop_front();
+ if (count < 6) {
+ num += count;
+ count = 0;
break;
}
- QPointF c1(arg[0], arg[1]);
- QPointF c2(arg[2], arg[3]);
- QPointF e(arg[4], arg[5]);
+ QPointF c1(num[0], num[1]);
+ QPointF c2(num[2], num[3]);
+ QPointF e(num[4], num[5]);
+ num += 6;
+ count -= 6;
path.cubicTo(c1, c2, e);
ctrlPt = c2;
x = e.x();
y = e.y();
- arg.pop_front(); arg.pop_front();
- arg.pop_front(); arg.pop_front();
- arg.pop_front(); arg.pop_front();
break;
}
case 's': {
- if (arg.count() < 4) {
- while (arg.count())
- arg.pop_front();
+ if (count < 4) {
+ num += count;
+ count = 0;
break;
}
QPointF c1;
@@ -1558,20 +1572,20 @@ static bool parsePathDataFast(const QStringRef &dataStr, QPainterPath &path)
c1 = QPointF(2*x-ctrlPt.x(), 2*y-ctrlPt.y());
else
c1 = QPointF(x, y);
- QPointF c2(arg[0]+offsetX, arg[1]+offsetY);
- QPointF e(arg[2]+offsetX, arg[3]+offsetY);
+ QPointF c2(num[0] + offsetX, num[1] + offsetY);
+ QPointF e(num[2] + offsetX, num[3] + offsetY);
+ num += 4;
+ count -= 4;
path.cubicTo(c1, c2, e);
ctrlPt = c2;
x = e.x();
y = e.y();
- arg.pop_front(); arg.pop_front();
- arg.pop_front(); arg.pop_front();
break;
}
case 'S': {
- if (arg.count() < 4) {
- while (arg.count())
- arg.pop_front();
+ if (count < 4) {
+ num += count;
+ count = 0;
break;
}
QPointF c1;
@@ -1580,55 +1594,57 @@ static bool parsePathDataFast(const QStringRef &dataStr, QPainterPath &path)
c1 = QPointF(2*x-ctrlPt.x(), 2*y-ctrlPt.y());
else
c1 = QPointF(x, y);
- QPointF c2(arg[0], arg[1]);
- QPointF e(arg[2], arg[3]);
+ QPointF c2(num[0], num[1]);
+ QPointF e(num[2], num[3]);
+ num += 4;
+ count -= 4;
path.cubicTo(c1, c2, e);
ctrlPt = c2;
x = e.x();
y = e.y();
- arg.pop_front(); arg.pop_front();
- arg.pop_front(); arg.pop_front();
break;
}
case 'q': {
- if (arg.count() < 4) {
- while (arg.count())
- arg.pop_front();
+ if (count < 4) {
+ num += count;
+ count = 0;
break;
}
- QPointF c(arg[0]+offsetX, arg[1]+offsetY);
- QPointF e(arg[2]+offsetX, arg[3]+offsetY);
+ QPointF c(num[0] + offsetX, num[1] + offsetY);
+ QPointF e(num[2] + offsetX, num[3] + offsetY);
+ num += 4;
+ count -= 4;
path.quadTo(c, e);
ctrlPt = c;
x = e.x();
y = e.y();
- arg.pop_front(); arg.pop_front();
- arg.pop_front(); arg.pop_front();
break;
}
case 'Q': {
- if (arg.count() < 4) {
- while (arg.count())
- arg.pop_front();
+ if (count < 4) {
+ num += count;
+ count = 0;
break;
}
- QPointF c(arg[0], arg[1]);
- QPointF e(arg[2], arg[3]);
+ QPointF c(num[0], num[1]);
+ QPointF e(num[2], num[3]);
+ num += 4;
+ count -= 4;
path.quadTo(c, e);
ctrlPt = c;
x = e.x();
y = e.y();
- arg.pop_front(); arg.pop_front();
- arg.pop_front(); arg.pop_front();
break;
}
case 't': {
- if (arg.count() < 2) {
- while (arg.count())
- arg.pop_front();
+ if (count < 2) {
+ num += count;
+ count = 0;
break;
}
- QPointF e(arg[0]+offsetX, arg[1]+offsetY);
+ QPointF e(num[0] + offsetX, num[1] + offsetY);
+ num += 2;
+ count -= 2;
QPointF c;
if (lastMode == 'q' || lastMode == 'Q' ||
lastMode == 't' || lastMode == 'T')
@@ -1639,16 +1655,17 @@ static bool parsePathDataFast(const QStringRef &dataStr, QPainterPath &path)
ctrlPt = c;
x = e.x();
y = e.y();
- arg.pop_front(); arg.pop_front();
break;
}
case 'T': {
- if (arg.count() < 2) {
- while (arg.count())
- arg.pop_front();
+ if (count < 2) {
+ num += count;
+ count = 0;
break;
}
- QPointF e(arg[0], arg[1]);
+ QPointF e(num[0], num[1]);
+ num += 2;
+ count -= 2;
QPointF c;
if (lastMode == 'q' || lastMode == 'Q' ||
lastMode == 't' || lastMode == 'T')
@@ -1659,22 +1676,22 @@ static bool parsePathDataFast(const QStringRef &dataStr, QPainterPath &path)
ctrlPt = c;
x = e.x();
y = e.y();
- arg.pop_front(); arg.pop_front();
break;
}
case 'a': {
- if (arg.count() < 7) {
- while (arg.count())
- arg.pop_front();
+ if (count < 7) {
+ num += count;
+ count = 0;
break;
}
- qreal rx = arg[0];
- qreal ry = arg[1];
- qreal xAxisRotation = arg[2];
- qreal largeArcFlag = arg[3];
- qreal sweepFlag = arg[4];
- qreal ex = arg[5] + offsetX;
- qreal ey = arg[6] + offsetY;
+ qreal rx = (*num++);
+ qreal ry = (*num++);
+ qreal xAxisRotation = (*num++);
+ qreal largeArcFlag = (*num++);
+ qreal sweepFlag = (*num++);
+ qreal ex = (*num++) + offsetX;
+ qreal ey = (*num++) + offsetY;
+ count -= 7;
qreal curx = x;
qreal cury = y;
pathArc(path, rx, ry, xAxisRotation, int(largeArcFlag),
@@ -1682,36 +1699,29 @@ static bool parsePathDataFast(const QStringRef &dataStr, QPainterPath &path)
x = ex;
y = ey;
-
- arg.pop_front(); arg.pop_front();
- arg.pop_front(); arg.pop_front();
- arg.pop_front(); arg.pop_front();
- arg.pop_front();
}
break;
case 'A': {
- if (arg.count() < 7) {
- while (arg.count())
- arg.pop_front();
+ if (count < 7) {
+ num += count;
+ count = 0;
break;
}
- qreal rx = arg[0];
- qreal ry = arg[1];
- qreal xAxisRotation = arg[2];
- qreal largeArcFlag = arg[3];
- qreal sweepFlag = arg[4];
- qreal ex = arg[5];
- qreal ey = arg[6];
+ qreal rx = (*num++);
+ qreal ry = (*num++);
+ qreal xAxisRotation = (*num++);
+ qreal largeArcFlag = (*num++);
+ qreal sweepFlag = (*num++);
+ qreal ex = (*num++);
+ qreal ey = (*num++);
+ count -= 7;
qreal curx = x;
qreal cury = y;
pathArc(path, rx, ry, xAxisRotation, int(largeArcFlag),
int(sweepFlag), ex, ey, curx, cury);
+
x = ex;
y = ey;
- arg.pop_front(); arg.pop_front();
- arg.pop_front(); arg.pop_front();
- arg.pop_front(); arg.pop_front();
- arg.pop_front();
}
break;
default: