summaryrefslogtreecommitdiffstats
path: root/src/openvg
diff options
context:
space:
mode:
authorRhys Weatherley <rhys.weatherley@nokia.com>2009-10-13 06:00:22 (GMT)
committerRhys Weatherley <rhys.weatherley@nokia.com>2009-10-13 06:00:22 (GMT)
commit8f3c8e8585db2a621badbf7059076f513421bf8a (patch)
tree5e5a1a6b1fefcadad7fbf4e16f6e47ff733621d6 /src/openvg
parentf613b0170d0fe806378779472315d0bbdc1aada9 (diff)
downloadQt-8f3c8e8585db2a621badbf7059076f513421bf8a.zip
Qt-8f3c8e8585db2a621badbf7059076f513421bf8a.tar.gz
Qt-8f3c8e8585db2a621badbf7059076f513421bf8a.tar.bz2
Implement qDrawPixmaps for the OpenVG paint engine.
Best performance will be acheived with OpaqueHint and drawing the full pixmap rather than sub-regions. Reviewed-by: trustme
Diffstat (limited to 'src/openvg')
-rw-r--r--src/openvg/qpaintengine_vg.cpp115
-rw-r--r--src/openvg/qpaintengine_vg_p.h2
2 files changed, 117 insertions, 0 deletions
diff --git a/src/openvg/qpaintengine_vg.cpp b/src/openvg/qpaintengine_vg.cpp
index b129164..2a506bb 100644
--- a/src/openvg/qpaintengine_vg.cpp
+++ b/src/openvg/qpaintengine_vg.cpp
@@ -2949,6 +2949,121 @@ void QVGPaintEngine::drawTiledPixmap
fillRect(r, brush);
}
+// Best performance will be achieved with QDrawPixmaps::OpaqueHint
+// (i.e. no opacity), no rotation or scaling, and drawing the full
+// pixmap rather than parts of the pixmap. Even having just one of
+// these conditions will improve performance.
+void QVGPaintEngine::drawPixmaps
+ (const QDrawPixmaps::Data *drawingData, int dataCount,
+ const QPixmap &pixmap, QFlags<QDrawPixmaps::DrawingHint> hints)
+{
+#if !defined(QT_SHIVAVG)
+ Q_D(QVGPaintEngine);
+
+ // If the pixmap is not VG, or the transformation is projective,
+ // then fall back to the default implementation.
+ QPixmapData *pd = pixmap.pixmapData();
+ if (pd->classId() != QPixmapData::OpenVGClass || !d->simpleTransform) {
+ QPaintEngineEx::drawPixmaps(drawingData, dataCount, pixmap, hints);
+ return;
+ }
+
+ // Bail out if nothing to do.
+ if (dataCount <= 0)
+ return;
+
+ // Bail out if we don't have a usable VGImage for the pixmap.
+ QVGPixmapData *vgpd = static_cast<QVGPixmapData *>(pd);
+ if (!vgpd->isValid())
+ return;
+ VGImage vgImg = vgpd->toVGImage();
+ if (vgImg == VG_INVALID_HANDLE)
+ return;
+
+ // We cache the results of any vgChildImage() calls because the
+ // same child is very likely to be used over and over in particle
+ // systems. However, performance is even better if vgChildImage()
+ // isn't needed at all, so use full source rects where possible.
+ QVarLengthArray<VGImage> cachedImages;
+ QVarLengthArray<QRect> cachedSources;
+
+ // Select the opacity paint object.
+ if ((hints & QDrawPixmaps::OpaqueHint) != 0 && d->opacity == 1.0f) {
+ d->setImageMode(VG_DRAW_IMAGE_NORMAL);
+ } else {
+ hints = 0;
+ if (d->fillPaint != d->opacityPaint) {
+ vgSetPaint(d->opacityPaint, VG_FILL_PATH);
+ d->fillPaint = d->opacityPaint;
+ }
+ }
+
+ for (int i = 0; i < dataCount; ++i) {
+ QTransform transform(d->imageTransform);
+ transform.translate(drawingData[i].point.x(), drawingData[i].point.y());
+ transform.rotate(drawingData[i].rotation);
+
+ VGImage child;
+ QSize imageSize = vgpd->size();
+ QRectF sr = drawingData[i].source;
+ if (sr.topLeft().isNull() && sr.size() == imageSize) {
+ child = vgImg;
+ } else {
+ // Look for a previous child with the same source rectangle
+ // to avoid constantly calling vgChildImage()/vgDestroyImage().
+ QRect src = sr.toRect();
+ int j;
+ for (j = 0; j < cachedSources.size(); ++j) {
+ if (cachedSources[j] == src)
+ break;
+ }
+ if (j < cachedSources.size()) {
+ child = cachedImages[j];
+ } else {
+ child = vgChildImage
+ (vgImg, src.x(), src.y(), src.width(), src.height());
+ cachedImages.append(child);
+ cachedSources.append(src);
+ }
+ }
+
+ VGfloat scaleX = drawingData[i].scaleX;
+ VGfloat scaleY = drawingData[i].scaleY;
+ transform.translate(-0.5 * scaleX * sr.width(),
+ -0.5 * scaleY * sr.height());
+ transform.scale(scaleX, scaleY);
+ d->setTransform(VG_MATRIX_IMAGE_USER_TO_SURFACE, transform);
+
+ if ((hints & QDrawPixmaps::OpaqueHint) == 0) {
+ qreal opacity = d->opacity * drawingData[i].opacity;
+ if (opacity != 1.0f) {
+ if (d->paintOpacity != opacity) {
+ VGfloat values[4];
+ values[0] = 1.0f;
+ values[1] = 1.0f;
+ values[2] = 1.0f;
+ values[3] = opacity;
+ d->paintOpacity = opacity;
+ vgSetParameterfv
+ (d->opacityPaint, VG_PAINT_COLOR, 4, values);
+ }
+ d->setImageMode(VG_DRAW_IMAGE_MULTIPLY);
+ } else {
+ d->setImageMode(VG_DRAW_IMAGE_NORMAL);
+ }
+ }
+
+ vgDrawImage(child);
+ }
+
+ // Destroy the cached child sub-images.
+ for (int i = 0; i < cachedImages.size(); ++i)
+ vgDestroyImage(cachedImages[i]);
+#else
+ QPaintEngineEx::drawPixmaps(drawingData, dataCount, pixmap, hints);
+#endif
+}
+
QVGFontEngineCleaner::QVGFontEngineCleaner(QVGPaintEnginePrivate *d)
: QObject(), d_ptr(d)
{
diff --git a/src/openvg/qpaintengine_vg_p.h b/src/openvg/qpaintengine_vg_p.h
index a3487dc..1202b55 100644
--- a/src/openvg/qpaintengine_vg_p.h
+++ b/src/openvg/qpaintengine_vg_p.h
@@ -136,6 +136,8 @@ public:
void drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &s);
+ void drawPixmaps(const QDrawPixmaps::Data *drawingData, int dataCount, const QPixmap &pixmap, QFlags<QDrawPixmaps::DrawingHint> hints);
+
void drawTextItem(const QPointF &p, const QTextItem &textItem);
void setState(QPainterState *s);