summaryrefslogtreecommitdiffstats
path: root/src/gui/painting
diff options
context:
space:
mode:
authorSamuel Rødal <samuel.rodal@nokia.com>2010-06-07 15:23:44 (GMT)
committerSamuel Rødal <samuel.rodal@nokia.com>2010-06-10 08:32:35 (GMT)
commit39e11b3f49fdc01155575f6d909efd92e435d5a6 (patch)
tree5d34935996e0c3617cacfbb92ae463be8d1dc7a8 /src/gui/painting
parentd0721276513102902fbfd839bf1af24dc0a4b1d7 (diff)
downloadQt-39e11b3f49fdc01155575f6d909efd92e435d5a6.zip
Qt-39e11b3f49fdc01155575f6d909efd92e435d5a6.tar.gz
Qt-39e11b3f49fdc01155575f6d909efd92e435d5a6.tar.bz2
Optimized 90-, 180-, and 270- rotated blits in raster paint engine.
Blitting a 90-degree rotated RGB16 image now takes 40 % of the time it used to on the N900. Task-number: QT-3057 Reviewed-by: Kim
Diffstat (limited to 'src/gui/painting')
-rw-r--r--src/gui/painting/qpaintengine_raster.cpp105
1 files changed, 105 insertions, 0 deletions
diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp
index 48974e8..08e14fb 100644
--- a/src/gui/painting/qpaintengine_raster.cpp
+++ b/src/gui/painting/qpaintengine_raster.cpp
@@ -68,6 +68,7 @@
// #include <private/qrasterizer_p.h>
#include <private/qimage_p.h>
#include <private/qstatictext_p.h>
+#include "qmemrotate_p.h"
#include "qpaintengine_raster_p.h"
// #include "qbezier_p.h"
@@ -2521,6 +2522,58 @@ QRectF qt_mapRect_non_normalizing(const QRectF &r, const QTransform &t)
return QRectF(r.topLeft() * t, r.bottomRight() * t);
}
+namespace {
+ enum RotationType {
+ Rotation90,
+ Rotation180,
+ Rotation270,
+ NoRotation
+ };
+
+ inline RotationType qRotationType(const QTransform &transform)
+ {
+ QTransform::TransformationType type = transform.type();
+
+ if (type > QTransform::TxRotate)
+ return NoRotation;
+
+ if (type == QTransform::TxRotate && qFuzzyIsNull(transform.m11()) && qFuzzyCompare(transform.m12(), qreal(-1))
+ && qFuzzyCompare(transform.m21(), qreal(1)) && qFuzzyIsNull(transform.m22()))
+ return Rotation90;
+
+ if (type == QTransform::TxScale && qFuzzyCompare(transform.m11(), qreal(-1)) && qFuzzyIsNull(transform.m12())
+ && qFuzzyIsNull(transform.m21()) && qFuzzyCompare(transform.m22(), qreal(-1)))
+ return Rotation180;
+
+ if (type == QTransform::TxRotate && qFuzzyIsNull(transform.m11()) && qFuzzyCompare(transform.m12(), qreal(1))
+ && qFuzzyCompare(transform.m21(), qreal(-1)) && qFuzzyIsNull(transform.m22()))
+ return Rotation270;
+
+ return NoRotation;
+ }
+
+ template <typename T> void memRotate(RotationType type, const T *srcBase, int w, int h, int sbpl, T *dstBase, int dbpl)
+ {
+ switch (type) {
+ case Rotation90:
+ qt_memrotate90(srcBase, w, h, sbpl, dstBase, dbpl);
+ break;
+ case Rotation180:
+ qt_memrotate180(srcBase, w, h, sbpl, dstBase, dbpl);
+ break;
+ case Rotation270:
+ qt_memrotate270(srcBase, w, h, sbpl, dstBase, dbpl);
+ break;
+ case NoRotation:
+ break;
+ }
+ }
+
+ inline bool isPixelAligned(const QRectF &rect) {
+ return QRectF(rect.toRect()) == rect;
+ }
+}
+
/*!
\reimp
*/
@@ -2582,6 +2635,58 @@ void QRasterPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRe
const QClipData *clip = d->clip();
+ if (s->matrix.type() > QTransform::TxTranslate
+ && !stretch_sr
+ && (!clip || clip->hasRectClip)
+ && s->intOpacity == 256
+ && (d->rasterBuffer->compositionMode == QPainter::CompositionMode_SourceOver
+ || d->rasterBuffer->compositionMode == QPainter::CompositionMode_Source)
+ && d->rasterBuffer->format == img.format()
+ && (d->rasterBuffer->format == QImage::Format_RGB16
+ || d->rasterBuffer->format == QImage::Format_RGB32
+ || (d->rasterBuffer->format == QImage::Format_ARGB32_Premultiplied
+ && d->rasterBuffer->compositionMode == QPainter::CompositionMode_Source)))
+ {
+ RotationType rotationType = qRotationType(s->matrix);
+
+ if (rotationType != NoRotation && img.rect().contains(sr.toAlignedRect())) {
+ QRectF transformedTargetRect = s->matrix.mapRect(r);
+
+ if ((!(s->renderHints & QPainter::SmoothPixmapTransform) && !(s->renderHints & QPainter::Antialiasing))
+ || (isPixelAligned(transformedTargetRect) && isPixelAligned(sr)))
+ {
+ QRect clippedTransformedTargetRect = transformedTargetRect.toRect().intersected(clip ? clip->clipRect : d->deviceRect);
+ if (clippedTransformedTargetRect.isNull())
+ return;
+
+ QRectF clippedTargetRect = s->matrix.inverted().mapRect(QRectF(clippedTransformedTargetRect));
+
+ QRect clippedSourceRect
+ = QRectF(sr.x() + clippedTargetRect.x() - r.x(), sr.y() + clippedTargetRect.y() - r.y(),
+ clippedTargetRect.width(), clippedTargetRect.height()).toRect();
+
+ uint dbpl = d->rasterBuffer->bytesPerLine();
+ uint sbpl = img.bytesPerLine();
+
+ uchar *dst = d->rasterBuffer->buffer();
+ uint bpp = img.depth() >> 3;
+
+ const uchar *srcBase = img.bits() + clippedSourceRect.y() * sbpl + clippedSourceRect.x() * bpp;
+ uchar *dstBase = dst + clippedTransformedTargetRect.y() * dbpl + clippedTransformedTargetRect.x() * bpp;
+
+ uint cw = clippedSourceRect.width();
+ uint ch = clippedSourceRect.height();
+
+ if (d->rasterBuffer->format == QImage::Format_RGB16)
+ memRotate(rotationType, (quint16 *)srcBase, cw, ch, sbpl, (quint16 *)dstBase, dbpl);
+ else
+ memRotate(rotationType, (quint32 *)srcBase, cw, ch, sbpl, (quint32 *)dstBase, dbpl);
+
+ return;
+ }
+ }
+ }
+
if (s->matrix.type() > QTransform::TxTranslate || stretch_sr) {
if (s->flags.fast_images) {