summaryrefslogtreecommitdiffstats
path: root/src/openvg/qpaintengine_vg.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/openvg/qpaintengine_vg.cpp')
-rw-r--r--src/openvg/qpaintengine_vg.cpp128
1 files changed, 69 insertions, 59 deletions
diff --git a/src/openvg/qpaintengine_vg.cpp b/src/openvg/qpaintengine_vg.cpp
index bc9f0c9..35f552e 100644
--- a/src/openvg/qpaintengine_vg.cpp
+++ b/src/openvg/qpaintengine_vg.cpp
@@ -130,8 +130,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,
@@ -177,6 +178,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".
@@ -349,6 +352,8 @@ void QVGPaintEnginePrivate::init()
roundRectPath = 0;
#endif
+ reusablePath = 0;
+
simpleTransform = true;
pathTransformSet = false;
penScale = 1.0;
@@ -445,6 +450,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()
@@ -464,6 +478,8 @@ void QVGPaintEnginePrivate::destroy()
if (roundRectPath)
vgDestroyPath(roundRectPath);
#endif
+ if (reusablePath)
+ vgDestroyPath(reusablePath);
#if !defined(QVG_NO_DRAW_GLYPHS)
QVGFontCache::Iterator it;
@@ -540,19 +556,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;
@@ -724,17 +753,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;
@@ -953,13 +987,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
@@ -1512,7 +1540,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)
@@ -1523,7 +1551,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)
@@ -1531,7 +1559,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
@@ -1727,7 +1755,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;
@@ -2044,7 +2072,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;
@@ -2395,7 +2423,7 @@ void QVGPaintEngine::fillRect(const QRectF &rect, const QBrush &brush)
return;
// Check to see if we can use vgClear() for faster filling.
- if (brush.style() == Qt::SolidPattern &&
+ if (brush.style() == Qt::SolidPattern && brush.isOpaque() &&
clipTransformIsSimple(d->transform) && d->opacity == 1.0f &&
clearRect(rect, brush.color())) {
return;
@@ -2438,7 +2466,7 @@ void QVGPaintEngine::fillRect(const QRectF &rect, const QColor &color)
Q_D(QVGPaintEngine);
// Check to see if we can use vgClear() for faster filling.
- if (clipTransformIsSimple(d->transform) && d->opacity == 1.0f &&
+ if (clipTransformIsSimple(d->transform) && d->opacity == 1.0f && color.alpha() == 255 &&
clearRect(rect, color)) {
return;
}
@@ -2483,7 +2511,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);
@@ -2632,13 +2660,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,
@@ -2662,7 +2684,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.
@@ -2686,7 +2708,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)
@@ -2761,13 +2783,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) {
@@ -2801,20 +2817,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) {
@@ -2848,7 +2858,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()
@@ -3245,7 +3255,7 @@ void QVGFontGlyphCache::cacheGlyphs(QVGPaintEnginePrivate *d,
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;