diff options
author | Rhys Weatherley <rhys.weatherley@nokia.com> | 2010-02-22 22:46:27 (GMT) |
---|---|---|
committer | Rhys Weatherley <rhys.weatherley@nokia.com> | 2010-02-22 22:46:27 (GMT) |
commit | 8597e03495f54614e53c6063f1f13077a08109fd (patch) | |
tree | 293d00a4197d7f39b63f38144f5102a47783fef9 /src/openvg | |
parent | 341304328e0d1f0e6a3879f8592631078b6ec558 (diff) | |
download | Qt-8597e03495f54614e53c6063f1f13077a08109fd.zip Qt-8597e03495f54614e53c6063f1f13077a08109fd.tar.gz Qt-8597e03495f54614e53c6063f1f13077a08109fd.tar.bz2 |
Improve performance of VGPath creation by reusing the same path
The vgClearPath() function can be used to clear a path for reuse
more efficiently than destroying the path and creating a new one.
Task-number: QT-2974
Reviewed-by: Daniel Pope
Diffstat (limited to 'src/openvg')
-rw-r--r-- | src/openvg/qpaintengine_vg.cpp | 124 |
1 files changed, 67 insertions, 57 deletions
diff --git a/src/openvg/qpaintengine_vg.cpp b/src/openvg/qpaintengine_vg.cpp index da47f06..4192dbb 100644 --- a/src/openvg/qpaintengine_vg.cpp +++ b/src/openvg/qpaintengine_vg.cpp @@ -131,8 +131,9 @@ public: void draw(VGPath path, const QPen& pen, const QBrush& brush, VGint rule = VG_EVEN_ODD); void stroke(VGPath path, const QPen& pen); void fill(VGPath path, const QBrush& brush, VGint rule = VG_EVEN_ODD); - VGPath vectorPathToVGPath(const QVectorPath& path); - VGPath painterPathToVGPath(const QPainterPath& path); + inline void releasePath(VGPath path); + VGPath vectorPathToVGPath(const QVectorPath& path, bool forceNewPath = false); + VGPath painterPathToVGPath(const QPainterPath& path, bool forceNewPath = false); VGPath roundedRectPath(const QRectF &rect, qreal xRadius, qreal yRadius, Qt::SizeMode mode); VGPaintType setBrush (VGPaint paint, const QBrush& brush, VGMatrixMode mode, @@ -178,6 +179,8 @@ public: VGPath roundRectPath; // Cached path for quick drawing of rounded rects. #endif + VGPath reusablePath; // Reusable path for vectorPathToVGPath(), etc. + QTransform transform; // Currently active transform. bool simpleTransform; // True if the transform is simple (non-projective). qreal penScale; // Pen scaling factor from "transform". @@ -350,6 +353,8 @@ void QVGPaintEnginePrivate::init() roundRectPath = 0; #endif + reusablePath = 0; + simpleTransform = true; pathTransformSet = false; penScale = 1.0; @@ -446,6 +451,15 @@ void QVGPaintEnginePrivate::initObjects() VG_PATH_CAPABILITY_ALL); vgAppendPathData(linePath, 2, segments, coords); #endif + + // This path can be reused over and over by calling vgClearPath(). + reusablePath = vgCreatePath(VG_PATH_FORMAT_STANDARD, + VG_PATH_DATATYPE_F, + 1.0f, // scale + 0.0f, // bias + 32 + 1, // segmentCapacityHint + 32 * 2, // coordCapacityHint + VG_PATH_CAPABILITY_ALL); } void QVGPaintEnginePrivate::destroy() @@ -465,6 +479,8 @@ void QVGPaintEnginePrivate::destroy() if (roundRectPath) vgDestroyPath(roundRectPath); #endif + if (reusablePath) + vgDestroyPath(reusablePath); #if !defined(QVG_NO_DRAW_GLYPHS) QVGFontCache::Iterator it; @@ -541,19 +557,32 @@ void QVGPaintEnginePrivate::updateTransform(QPaintDevice *pdev) qt_scaleForTransform(transform, &penScale); } -VGPath QVGPaintEnginePrivate::vectorPathToVGPath(const QVectorPath& path) +inline void QVGPaintEnginePrivate::releasePath(VGPath path) +{ + if (path == reusablePath) + vgClearPath(path, VG_PATH_CAPABILITY_ALL); + else + vgDestroyPath(path); +} + +VGPath QVGPaintEnginePrivate::vectorPathToVGPath(const QVectorPath& path, bool forceNewPath) { int count = path.elementCount(); const qreal *points = path.points(); const QPainterPath::ElementType *elements = path.elements(); - VGPath vgpath = vgCreatePath(VG_PATH_FORMAT_STANDARD, - VG_PATH_DATATYPE_F, - 1.0f, // scale - 0.0f, // bias - count + 1, // segmentCapacityHint - count * 2, // coordCapacityHint - VG_PATH_CAPABILITY_ALL); + VGPath vgpath; + if (forceNewPath) { + vgpath = vgCreatePath(VG_PATH_FORMAT_STANDARD, + VG_PATH_DATATYPE_F, + 1.0f, // scale + 0.0f, // bias + count + 1, // segmentCapacityHint + count * 2, // coordCapacityHint + VG_PATH_CAPABILITY_ALL); + } else { + vgpath = reusablePath; + } // Size is sufficient segments for drawRoundedRect() paths. QVarLengthArray<VGubyte, 20> segments; @@ -725,17 +754,22 @@ VGPath QVGPaintEnginePrivate::vectorPathToVGPath(const QVectorPath& path) return vgpath; } -VGPath QVGPaintEnginePrivate::painterPathToVGPath(const QPainterPath& path) +VGPath QVGPaintEnginePrivate::painterPathToVGPath(const QPainterPath& path, bool forceNewPath) { int count = path.elementCount(); - VGPath vgpath = vgCreatePath(VG_PATH_FORMAT_STANDARD, - VG_PATH_DATATYPE_F, - 1.0f, // scale - 0.0f, // bias - count + 1, // segmentCapacityHint - count * 2, // coordCapacityHint - VG_PATH_CAPABILITY_ALL); + VGPath vgpath; + if (forceNewPath) { + vgpath = vgCreatePath(VG_PATH_FORMAT_STANDARD, + VG_PATH_DATATYPE_F, + 1.0f, // scale + 0.0f, // bias + count + 1, // segmentCapacityHint + count * 2, // coordCapacityHint + VG_PATH_CAPABILITY_ALL); + } else { + vgpath = reusablePath; + } if (count == 0) return vgpath; @@ -954,13 +988,7 @@ VGPath QVGPaintEnginePrivate::roundedRectPath(const QRectF &rect, qreal xRadius, vgModifyPathCoords(vgpath, 0, 9, pts); } #else - VGPath vgpath = vgCreatePath(VG_PATH_FORMAT_STANDARD, - VG_PATH_DATATYPE_F, - 1.0f, // scale - 0.0f, // bias - 10, // segmentCapacityHint - 17 * 2, // coordCapacityHint - VG_PATH_CAPABILITY_ALL); + VGPath vgpath = reusablePath; vgAppendPathData(vgpath, 10, roundedrect_types, pts); #endif @@ -1516,7 +1544,7 @@ void QVGPaintEngine::draw(const QVectorPath &path) d->draw(vgpath, s->pen, s->brush, VG_EVEN_ODD); else d->draw(vgpath, s->pen, s->brush, VG_NON_ZERO); - vgDestroyPath(vgpath); + d->releasePath(vgpath); } void QVGPaintEngine::fill(const QVectorPath &path, const QBrush &brush) @@ -1527,7 +1555,7 @@ void QVGPaintEngine::fill(const QVectorPath &path, const QBrush &brush) d->fill(vgpath, brush, VG_EVEN_ODD); else d->fill(vgpath, brush, VG_NON_ZERO); - vgDestroyPath(vgpath); + d->releasePath(vgpath); } void QVGPaintEngine::stroke(const QVectorPath &path, const QPen &pen) @@ -1535,7 +1563,7 @@ void QVGPaintEngine::stroke(const QVectorPath &path, const QPen &pen) Q_D(QVGPaintEngine); VGPath vgpath = d->vectorPathToVGPath(path); d->stroke(vgpath, pen); - vgDestroyPath(vgpath); + d->releasePath(vgpath); } // Determine if a co-ordinate transform is simple enough to allow @@ -1731,7 +1759,7 @@ void QVGPaintEngine::clip(const QVectorPath &path, Qt::ClipOperation op) default: break; } - vgDestroyPath(vgpath); + d->releasePath(vgpath); vgSeti(VG_MASKING, VG_TRUE); d->maskValid = true; @@ -2048,7 +2076,7 @@ void QVGPaintEngine::clip(const QPainterPath &path, Qt::ClipOperation op) default: break; } - vgDestroyPath(vgpath); + d->releasePath(vgpath); vgSeti(VG_MASKING, VG_TRUE); d->maskValid = true; @@ -2487,7 +2515,7 @@ void QVGPaintEngine::drawRoundedRect(const QRectF &rect, qreal xrad, qreal yrad, VGPath vgpath = d->roundedRectPath(rect, xrad, yrad, mode); d->draw(vgpath, s->pen, s->brush); #if defined(QVG_NO_MODIFY_PATH) - vgDestroyPath(vgpath); + d->releasePath(vgpath); #endif } else { QPaintEngineEx::drawRoundedRect(rect, xrad, yrad, mode); @@ -2636,13 +2664,7 @@ void QVGPaintEngine::drawEllipse(const QRectF &r) Q_D(QVGPaintEngine); if (d->simpleTransform) { QVGPainterState *s = state(); - VGPath path = vgCreatePath(VG_PATH_FORMAT_STANDARD, - VG_PATH_DATATYPE_F, - 1.0f, // scale - 0.0f, // bias - 4, // segmentCapacityHint - 12, // coordCapacityHint - VG_PATH_CAPABILITY_ALL); + VGPath path = d->reusablePath; static VGubyte segments[4] = { VG_MOVE_TO_ABS, VG_SCCWARC_TO_REL, @@ -2666,7 +2688,7 @@ void QVGPaintEngine::drawEllipse(const QRectF &r) coords[11] = 0.0f; vgAppendPathData(path, 4, segments, coords); d->draw(path, s->pen, s->brush); - vgDestroyPath(path); + d->releasePath(path); } else { // The projective transform version of an ellipse is difficult. // Generate a QVectorPath containing cubic curves and transform that. @@ -2690,7 +2712,7 @@ void QVGPaintEngine::drawPath(const QPainterPath &path) d->draw(vgpath, s->pen, s->brush, VG_EVEN_ODD); else d->draw(vgpath, s->pen, s->brush, VG_NON_ZERO); - vgDestroyPath(vgpath); + d->releasePath(vgpath); } void QVGPaintEngine::drawPoints(const QPointF *points, int pointCount) @@ -2765,13 +2787,7 @@ void QVGPaintEngine::drawPolygon(const QPointF *points, int pointCount, PolygonD { Q_D(QVGPaintEngine); QVGPainterState *s = state(); - VGPath path = vgCreatePath(VG_PATH_FORMAT_STANDARD, - VG_PATH_DATATYPE_F, - 1.0f, // scale - 0.0f, // bias - pointCount + 1, // segmentCapacityHint - pointCount * 2, // coordCapacityHint - VG_PATH_CAPABILITY_ALL); + VGPath path = d->reusablePath; QVarLengthArray<VGfloat, 16> coords; QVarLengthArray<VGubyte, 10> segments; for (int i = 0; i < pointCount; ++i, ++points) { @@ -2805,20 +2821,14 @@ void QVGPaintEngine::drawPolygon(const QPointF *points, int pointCount, PolygonD d->draw(path, s->pen, s->brush, VG_EVEN_ODD); break; } - vgDestroyPath(path); + d->releasePath(path); } void QVGPaintEngine::drawPolygon(const QPoint *points, int pointCount, PolygonDrawMode mode) { Q_D(QVGPaintEngine); QVGPainterState *s = state(); - VGPath path = vgCreatePath(VG_PATH_FORMAT_STANDARD, - VG_PATH_DATATYPE_F, - 1.0f, // scale - 0.0f, // bias - pointCount + 1, // segmentCapacityHint - pointCount * 2, // coordCapacityHint - VG_PATH_CAPABILITY_ALL); + VGPath path = d->reusablePath; QVarLengthArray<VGfloat, 16> coords; QVarLengthArray<VGubyte, 10> segments; for (int i = 0; i < pointCount; ++i, ++points) { @@ -2852,7 +2862,7 @@ void QVGPaintEngine::drawPolygon(const QPoint *points, int pointCount, PolygonDr d->draw(path, s->pen, s->brush, VG_EVEN_ODD); break; } - vgDestroyPath(path); + d->releasePath(path); } void QVGPaintEnginePrivate::setImageOptions() @@ -3251,7 +3261,7 @@ void QVGFontGlyphCache::cacheGlyphs ti.fontEngine->getUnscaledGlyph(glyph, &path, &metrics); VGPath vgPath; if (!path.isEmpty()) { - vgPath = d->painterPathToVGPath(path); + vgPath = d->painterPathToVGPath(path, true); } else { // Probably a "space" character with no visible outline. vgPath = VG_INVALID_HANDLE; |