QSpanData: use isAffine() instead of rolling your own test
[profile/ivi/qtbase.git] / src / gui / painting / qpaintengine_raster.cpp
index 4a1a1f0..0e9129f 100644 (file)
@@ -1,38 +1,38 @@
 /****************************************************************************
 **
-** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
 **
 ** This file is part of the QtGui module of the Qt Toolkit.
 **
 ** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
 ** GNU Lesser General Public License Usage
-** This file may be used under the terms of the GNU Lesser General Public
-** License version 2.1 as published by the Free Software Foundation and
-** appearing in the file LICENSE.LGPL included in the packaging of this
-** file. Please review the following information to ensure the GNU Lesser
-** General Public License version 2.1 requirements will be met:
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 **
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 **
 ** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU General
-** Public License version 3.0 as published by the Free Software Foundation
-** and appearing in the file LICENSE.GPL included in the packaging of this
-** file. Please review the following information to ensure the GNU General
-** Public License version 3.0 requirements will be met:
-** http://www.gnu.org/copyleft/gpl.html.
-**
-** Other Usage
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**
-**
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
 **
 **
 ** $QT_END_LICENSE$
 //   #include "qbezier_p.h"
 #include "qoutlinemapper_p.h"
 
-#if defined(Q_OS_WIN)
-#  include <qt_windows.h>
+#include <limits.h>
+
+#ifdef Q_OS_WIN
 #  include <qvarlengtharray.h>
 #  include <private/qfontengine_p.h>
+#  include <qt_windows.h>
+#ifdef Q_OS_WIN64
+#    include <malloc.h>
+#  endif
 #endif
 
-#if defined(Q_OS_WIN64)
-#  include <malloc.h>
-#endif
-#include <limits.h>
-
 QT_BEGIN_NAMESPACE
 
+class QRectVectorPath : public QVectorPath {
+public:
+    inline void set(const QRect &r) {
+        qreal left = r.x();
+        qreal right = r.x() + r.width();
+        qreal top = r.y();
+        qreal bottom = r.y() + r.height();
+        pts[0] = left;
+        pts[1] = top;
+        pts[2] = right;
+        pts[3] = top;
+        pts[4] = right;
+        pts[5] = bottom;
+        pts[6] = left;
+        pts[7] = bottom;
+    }
+
+    inline void set(const QRectF &r) {
+        qreal left = r.x();
+        qreal right = r.x() + r.width();
+        qreal top = r.y();
+        qreal bottom = r.y() + r.height();
+        pts[0] = left;
+        pts[1] = top;
+        pts[2] = right;
+        pts[3] = top;
+        pts[4] = right;
+        pts[5] = bottom;
+        pts[6] = left;
+        pts[7] = bottom;
+    }
+    inline QRectVectorPath(const QRect &r)
+        : QVectorPath(pts, 4, 0, QVectorPath::RectangleHint | QVectorPath::ImplicitClose)
+    {
+        set(r);
+    }
+    inline QRectVectorPath(const QRectF &r)
+        : QVectorPath(pts, 4, 0, QVectorPath::RectangleHint | QVectorPath::ImplicitClose)
+    {
+        set(r);
+    }
+    inline QRectVectorPath()
+        : QVectorPath(pts, 4, 0, QVectorPath::RectangleHint | QVectorPath::ImplicitClose)
+    { }
+
+    qreal pts[8];
+};
+
 Q_GUI_EXPORT extern bool qt_scaleForTransform(const QTransform &transform, qreal *scale); // qtransform.cpp
 
 #define qreal_to_fixed_26_6(f) (int(f * 64))
@@ -118,6 +166,9 @@ static inline bool winClearTypeFontsEnabled()
     return result == FE_FONTSMOOTHINGCLEARTYPE;
 }
 
+/*!
+    \internal
+ */
 bool QRasterPaintEngine::clearTypeFontsEnabled()
 {
     static const bool result = winClearTypeFontsEnabled();
@@ -593,6 +644,7 @@ QRasterPaintEngineState::QRasterPaintEngineState()
     flags.fast_pen = true;
     flags.antialiased = false;
     flags.bilinear = false;
+    flags.legacy_rounding = false;
     flags.fast_text = true;
     flags.int_xform = true;
     flags.tx_noshear = true;
@@ -719,7 +771,7 @@ void QRasterPaintEngine::updatePen(const QPen &pen)
     } else if (pen_style != Qt::NoPen) {
         if (!d->dashStroker)
             d->dashStroker.reset(new QDashStroker(&d->basicStroker));
-        if (pen.isCosmetic()) {
+        if (qt_pen_is_cosmetic(pen, s->renderHints)) {
             d->dashStroker->setClipRect(d->deviceRect);
         } else {
             // ### I've seen this inverted devrect multiple places now...
@@ -734,10 +786,11 @@ void QRasterPaintEngine::updatePen(const QPen &pen)
     }
 
     ensureRasterState(); // needed because of tx_noshear...
+    bool cosmetic = qt_pen_is_cosmetic(pen, s->renderHints);
     s->flags.fast_pen = pen_style > Qt::NoPen
             && s->penData.blend
-            && ((pen.isCosmetic() && penWidth <= 1)
-                || (s->flags.tx_noshear && penWidth * s->txscale <= 1));
+            && ((cosmetic && penWidth <= 1)
+                || (!cosmetic && s->flags.tx_noshear && penWidth * s->txscale <= 1));
 
     s->flags.non_complex_pen = qpen_capStyle(s->lastPen) <= Qt::SquareCap && s->flags.tx_noshear;
 
@@ -876,6 +929,7 @@ void QRasterPaintEngine::renderHintsChanged()
 
     s->flags.antialiased = bool(s->renderHints & QPainter::Antialiasing);
     s->flags.bilinear = bool(s->renderHints & QPainter::SmoothPixmapTransform);
+    s->flags.legacy_rounding = !bool(s->renderHints & QPainter::Antialiasing) && bool(s->renderHints & QPainter::Qt4CompatiblePainting);
 
     if (was_aa != s->flags.antialiased)
         s->strokeFlags |= DirtyHints;
@@ -1018,9 +1072,11 @@ void QRasterPaintEnginePrivate::systemStateChanged()
     exDeviceRect = deviceRect;
 
     Q_Q(QRasterPaintEngine);
-    q->state()->strokeFlags |= QPaintEngine::DirtyClipRegion;
-    q->state()->fillFlags |= QPaintEngine::DirtyClipRegion;
-    q->state()->pixmapFlags |= QPaintEngine::DirtyClipRegion;
+    if (q->state()) {
+        q->state()->strokeFlags |= QPaintEngine::DirtyClipRegion;
+        q->state()->fillFlags |= QPaintEngine::DirtyClipRegion;
+        q->state()->pixmapFlags |= QPaintEngine::DirtyClipRegion;
+    }
 }
 
 void QRasterPaintEnginePrivate::updateMatrixData(QSpanData *spanData, const QBrush &b, const QTransform &m)
@@ -1321,6 +1377,13 @@ void QRasterPaintEngine::clip(const QRegion &region, Qt::ClipOperation op)
 }
 
 /*!
+ \fn const QClipData *QRasterPaintEngine::clipData() const
+
+ \internal
+*/
+
+
+/*!
     \internal
 */
 void QRasterPaintEngine::fillPath(const QPainterPath &path, QSpanData *fillData)
@@ -1466,6 +1529,7 @@ void QRasterPaintEngine::drawRects(const QRect *rects, int rectCount)
         QRectVectorPath path;
         if (s->flags.fast_pen) {
             QCosmeticStroker stroker(s, d->deviceRect);
+            stroker.setLegacyRoundingEnabled(s->flags.legacy_rounding);
             for (int i = 0; i < rectCount; ++i) {
                 path.set(rects[i]);
                 stroker.drawPath(path);
@@ -1512,6 +1576,7 @@ void QRasterPaintEngine::drawRects(const QRectF *rects, int rectCount)
             QRectVectorPath path;
             if (s->flags.fast_pen) {
                 QCosmeticStroker stroker(s, d->deviceRect);
+                stroker.setLegacyRoundingEnabled(s->flags.legacy_rounding);
                 for (int i = 0; i < rectCount; ++i) {
                     path.set(rects[i]);
                     stroker.drawPath(path);
@@ -1545,9 +1610,10 @@ void QRasterPaintEngine::stroke(const QVectorPath &path, const QPen &pen)
 
     if (s->flags.fast_pen) {
         QCosmeticStroker stroker(s, d->deviceRect);
+        stroker.setLegacyRoundingEnabled(s->flags.legacy_rounding);
         stroker.drawPath(path);
     } else if (s->flags.non_complex_pen && path.shape() == QVectorPath::LinesHint) {
-        qreal width = s->lastPen.isCosmetic()
+        qreal width = qt_pen_is_cosmetic(s->lastPen, s->renderHints)
                       ? (qpen_widthf(s->lastPen) == 0 ? 1 : qpen_widthf(s->lastPen))
                       : qpen_widthf(s->lastPen) * s->txscale;
         int dashIndex = 0;
@@ -1600,12 +1666,16 @@ void QRasterPaintEngine::stroke(const QVectorPath &path, const QPen &pen)
         QPaintEngineEx::stroke(path, pen);
 }
 
-static inline QRect toNormalizedFillRect(const QRectF &rect)
+QRect QRasterPaintEngine::toNormalizedFillRect(const QRectF &rect)
 {
-    int x1 = qRound(rect.x() + aliasedCoordinateDelta);
-    int y1 = qRound(rect.y() + aliasedCoordinateDelta);
-    int x2 = qRound(rect.right() + aliasedCoordinateDelta);
-    int y2 = qRound(rect.bottom() + aliasedCoordinateDelta);
+    QRasterPaintEngineState *s = state();
+
+    qreal delta = s->flags.legacy_rounding ? aliasedCoordinateDelta : qreal(0);
+
+    int x1 = qRound(rect.x() + delta);
+    int y1 = qRound(rect.y() + delta);
+    int x2 = qRound(rect.right() + delta);
+    int y2 = qRound(rect.bottom() + delta);
 
     if (x2 < x1)
         qSwap(x1, x2);
@@ -1874,11 +1944,8 @@ void QRasterPaintEngine::drawPolygon(const QPointF *points, int pointCount, Poly
     if (mode != PolylineMode) {
         // Do the fill...
         ensureBrush();
-        if (s->brushData.blend) {
-            d->outlineMapper->setCoordinateRounding(s->penData.blend && s->flags.fast_pen && s->lastPen.brush().isOpaque());
+        if (s->brushData.blend)
             fillPolygon(points, pointCount, mode);
-            d->outlineMapper->setCoordinateRounding(false);
-        }
     }
 
     // Do the outline...
@@ -1886,6 +1953,7 @@ void QRasterPaintEngine::drawPolygon(const QPointF *points, int pointCount, Poly
         QVectorPath vp((qreal *) points, pointCount, 0, QVectorPath::polygonFlags(mode));
         if (s->flags.fast_pen) {
             QCosmeticStroker stroker(s, d->deviceRect);
+            stroker.setLegacyRoundingEnabled(s->flags.legacy_rounding);
             stroker.drawPath(vp);
         } else {
             QPaintEngineEx::stroke(vp, s->lastPen);
@@ -1924,7 +1992,6 @@ void QRasterPaintEngine::drawPolygon(const QPoint *points, int pointCount, Polyg
         if (s->brushData.blend) {
             // Compose polygon fill..,
             ensureOutlineMapper();
-            d->outlineMapper->setCoordinateRounding(s->penData.blend != 0);
             d->outlineMapper->beginOutline(mode == WindingMode ? Qt::WindingFill : Qt::OddEvenFill);
             d->outlineMapper->moveTo(*points);
             const QPoint *p = points;
@@ -1938,7 +2005,6 @@ void QRasterPaintEngine::drawPolygon(const QPoint *points, int pointCount, Polyg
             ProcessSpans brushBlend = d->getBrushFunc(d->outlineMapper->controlPointRect,
                                                       &s->brushData);
             d->rasterize(d->outlineMapper->outline(), brushBlend, &s->brushData, d->rasterBuffer.data());
-            d->outlineMapper->setCoordinateRounding(false);
         }
     }
 
@@ -1952,6 +2018,7 @@ void QRasterPaintEngine::drawPolygon(const QPoint *points, int pointCount, Polyg
 
         if (s->flags.fast_pen) {
             QCosmeticStroker stroker(s, d->deviceRect);
+            stroker.setLegacyRoundingEnabled(s->flags.legacy_rounding);
             stroker.drawPath(vp);
         } else {
             QPaintEngineEx::stroke(vp, s->lastPen);
@@ -2049,17 +2116,6 @@ void QRasterPaintEngine::drawPixmap(const QRectF &r, const QPixmap &pixmap, cons
     }
 }
 
-// assumes that rect has positive width and height
-static inline const QRect toRect_normalized(const QRectF &rect)
-{
-    const int x = qRound(rect.x());
-    const int y = qRound(rect.y());
-    const int w = int(rect.width() + qreal(0.5));
-    const int h = int(rect.height() + qreal(0.5));
-
-    return QRect(x, y, w, h);
-}
-
 static inline int fast_ceil_positive(const qreal &v)
 {
     const int iv = int(v);
@@ -2089,9 +2145,10 @@ void QRasterPaintEngine::drawImage(const QPointF &p, const QImage &img)
 
     Q_D(QRasterPaintEngine);
     QRasterPaintEngineState *s = state();
+    qreal scale = img.devicePixelRatio();
 
-    if (s->matrix.type() > QTransform::TxTranslate) {
-        drawImage(QRectF(p.x(), p.y(), img.width(), img.height()),
+    if (scale > 1.0 ||  s->matrix.type() > QTransform::TxTranslate) {
+        drawImage(QRectF(p.x(), p.y(), img.width() / scale, img.height() / scale),
                   img,
                   QRectF(0, 0, img.width(), img.height()));
     } else {
@@ -2191,7 +2248,9 @@ void QRasterPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRe
         // as fillRect will apply the aliased coordinate delta we need to
         // subtract it here as we don't use it for image drawing
         QTransform old = s->matrix;
-        s->matrix = s->matrix * QTransform::fromTranslate(-aliasedCoordinateDelta, -aliasedCoordinateDelta);
+
+        if (s->flags.legacy_rounding)
+            s->matrix = s->matrix * QTransform::fromTranslate(-aliasedCoordinateDelta, -aliasedCoordinateDelta);
 
         // Do whatever fillRect() does, but without premultiplying the color if it's already premultiplied.
         QRgb color = img.pixel(sr_l, sr_t);
@@ -2293,6 +2352,22 @@ void QRasterPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRe
                     return;
                 }
             } else {
+                // Test for optimized high-dpi case: 2x source on 2x target. (Could be generalized to nX.)
+                bool sourceRect2x = r.width() * 2 == sr.width() && r.height() * 2 == sr.height();
+                bool scale2x = (s->matrix.m11() == qreal(2)) && (s->matrix.m22() == qreal(2));
+                if (s->matrix.type() == QTransform::TxScale && sourceRect2x && scale2x) {
+                    SrcOverBlendFunc func = qBlendFunctions[d->rasterBuffer->format][img.format()];
+                    if (func) {
+                        QPointF pt(r.x() * 2 + s->matrix.dx(), r.y() * 2 + s->matrix.dy());
+                        if (!clip) {
+                            d->drawImage(pt, img, func, d->deviceRect, s->intOpacity, sr.toRect());
+                            return;
+                        } else if (clip->hasRectClip) {
+                            d->drawImage(pt, img, func, clip->clipRect, s->intOpacity, sr.toRect());
+                            return;
+                        }
+                    }
+                }
                 SrcOverScaleFunc func = qScaleFunctions[d->rasterBuffer->format][img.format()];
                 if (func && (!clip || clip->hasRectClip)) {
                     func(d->rasterBuffer->buffer(), d->rasterBuffer->bytesPerLine(),
@@ -2334,8 +2409,9 @@ void QRasterPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRe
         if (s->flags.tx_noshear || s->matrix.type() == QTransform::TxScale) {
             d->initializeRasterizer(&d->image_filler_xform);
             d->rasterizer->setAntialiased(s->flags.antialiased);
+            d->rasterizer->setLegacyRoundingEnabled(s->flags.legacy_rounding);
 
-            const QPointF offs = s->flags.antialiased ? QPointF() : QPointF(aliasedCoordinateDelta, aliasedCoordinateDelta);
+            const QPointF offs = s->flags.legacy_rounding ? QPointF(aliasedCoordinateDelta, aliasedCoordinateDelta) : QPointF();
 
             const QRectF &rect = r.normalized();
             const QPointF a = s->matrix.map((rect.topLeft() + rect.bottomLeft()) * 0.5f) - offs;
@@ -2348,7 +2424,7 @@ void QRasterPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRe
             return;
         }
 #endif
-        const qreal offs = s->flags.antialiased ? qreal(0) : aliasedCoordinateDelta;
+        const qreal offs = s->flags.legacy_rounding ? aliasedCoordinateDelta : qreal(0);
         QPainterPath path;
         path.addRect(r);
         QTransform m = s->matrix;
@@ -2429,6 +2505,7 @@ void QRasterPaintEngine::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap,
         if (s->flags.tx_noshear || s->matrix.type() == QTransform::TxScale) {
             d->initializeRasterizer(&d->image_filler_xform);
             d->rasterizer->setAntialiased(s->flags.antialiased);
+            d->rasterizer->setLegacyRoundingEnabled(s->flags.legacy_rounding);
 
             const QRectF &rect = r.normalized();
             const QPointF a = s->matrix.map((rect.topLeft() + rect.bottomLeft()) * 0.5f);
@@ -2467,6 +2544,15 @@ static inline bool monoVal(const uchar* s, int x)
 
 /*!
     \internal
+ */
+QRasterBuffer *QRasterPaintEngine::rasterBuffer()
+{
+    Q_D(QRasterPaintEngine);
+    return d->rasterBuffer.data();
+}
+
+/*!
+    \internal
 */
 void QRasterPaintEngine::alphaPenBlt(const void* src, int bpl, int depth, int rx,int ry,int w,int h)
 {
@@ -2691,6 +2777,9 @@ void QRasterPaintEngine::alphaPenBlt(const void* src, int bpl, int depth, int rx
         blend(current, spans, &s->penData);
 }
 
+/*!
+    \internal
+*/
 bool QRasterPaintEngine::drawCachedGlyphs(int numGlyphs, const glyph_t *glyphs,
                                           const QFixedPoint *positions, QFontEngine *fontEngine)
 {
@@ -2717,7 +2806,7 @@ bool QRasterPaintEngine::drawCachedGlyphs(int numGlyphs, const glyph_t *glyphs,
 
             alphaPenBlt(alphaMap->bits(), alphaMap->bytesPerLine(), alphaMap->depth(),
                         qFloor(positions[i].x) + offset.x(),
-                        qFloor(positions[i].y) + offset.y(),
+                        qRound(positions[i].y) + offset.y(),
                         alphaMap->width(), alphaMap->height());
 
             fontEngine->unlockAlphaMapForGlyph();
@@ -2748,7 +2837,6 @@ bool QRasterPaintEngine::drawCachedGlyphs(int numGlyphs, const glyph_t *glyphs,
             rightShift = 3; // divide by 8
 
         int margin = fontEngine->glyphMargin(glyphType);
-        const QFixed offs = QFixed::fromReal(aliasedCoordinateDelta);
         const uchar *bits = image.bits();
         for (int i=0; i<numGlyphs; ++i) {
 
@@ -2759,7 +2847,7 @@ bool QRasterPaintEngine::drawCachedGlyphs(int numGlyphs, const glyph_t *glyphs,
                 continue;
 
             int x = qFloor(positions[i].x) + c.baseLineX - margin;
-            int y = qFloor(positions[i].y + offs) - c.baseLineY - margin;
+            int y = qRound(positions[i].y) - c.baseLineY - margin;
 
             // printf("drawing [%d %d %d %d] baseline [%d %d], glyph: %d, to: %d %d, pos: %d %d\n",
             //        c.x, c.y,
@@ -2923,7 +3011,7 @@ void QRasterPaintEngine::drawStaticTextItem(QStaticTextItem *textItem)
     ensureRasterState();
 
     QFontEngine *fontEngine = textItem->fontEngine();
-    if (shouldDrawCachedGlyphs(fontEngine->fontDef.pixelSize, state()->matrix)) {
+    if (!supportsTransformations(fontEngine)) {
         drawCachedGlyphs(textItem->numGlyphs, textItem->glyphs, textItem->glyphPositions,
                          fontEngine);
     } else if (state()->matrix.type() < QTransform::TxProject) {
@@ -3024,6 +3112,7 @@ void QRasterPaintEngine::drawPoints(const QPointF *points, int pointCount)
     }
 
     QCosmeticStroker stroker(s, d->deviceRect);
+    stroker.setLegacyRoundingEnabled(s->flags.legacy_rounding);
     stroker.drawPoints(points, pointCount);
 }
 
@@ -3043,6 +3132,7 @@ void QRasterPaintEngine::drawPoints(const QPoint *points, int pointCount)
     }
 
     QCosmeticStroker stroker(s, d->deviceRect);
+    stroker.setLegacyRoundingEnabled(s->flags.legacy_rounding);
     stroker.drawPoints(points, pointCount);
 }
 
@@ -3063,6 +3153,7 @@ void QRasterPaintEngine::drawLines(const QLine *lines, int lineCount)
 
     if (s->flags.fast_pen) {
         QCosmeticStroker stroker(s, d->deviceRect);
+        stroker.setLegacyRoundingEnabled(s->flags.legacy_rounding);
         for (int i=0; i<lineCount; ++i) {
             const QLine &l = lines[i];
             stroker.drawLine(l.p1(), l.p2());
@@ -3134,6 +3225,7 @@ void QRasterPaintEngine::drawLines(const QLineF *lines, int lineCount)
         return;
     if (s->flags.fast_pen) {
         QCosmeticStroker stroker(s, d->deviceRect);
+        stroker.setLegacyRoundingEnabled(s->flags.legacy_rounding);
         for (int i=0; i<lineCount; ++i) {
             QLineF line = lines[i];
             stroker.drawLine(line.p1(), line.p2());
@@ -3176,9 +3268,6 @@ void QRasterPaintEngine::drawEllipse(const QRectF &rect)
     QPaintEngineEx::drawEllipse(rect);
 }
 
-/*!
-    \internal
-*/
 
 #ifdef Q_OS_WIN
 /*!
@@ -3207,18 +3296,24 @@ void QRasterPaintEngine::releaseDC(HDC) const
 
 #endif
 
-bool QRasterPaintEngine::supportsTransformations(const QFontEngine *fontEngine) const
+/*!
+    \internal
+*/
+bool QRasterPaintEngine::supportsTransformations(QFontEngine *fontEngine) const
 {
     const QTransform &m = state()->matrix;
-    return supportsTransformations(fontEngine->fontDef.pixelSize, m);
+    return supportsTransformations(fontEngine, m);
 }
 
-bool QRasterPaintEngine::supportsTransformations(qreal pixelSize, const QTransform &m) const
+/*!
+    \internal
+*/
+bool QRasterPaintEngine::supportsTransformations(QFontEngine *fontEngine, const QTransform &m) const
 {
-    if (m.type() >= QTransform::TxProject)
+    if (fontEngine->supportsTransformations(m))
         return true;
 
-    return !shouldDrawCachedGlyphs(pixelSize, m);
+    return !shouldDrawCachedGlyphs(fontEngine, m);
 }
 
 /*!
@@ -3363,6 +3458,7 @@ void QRasterPaintEnginePrivate::initializeRasterizer(QSpanData *data)
     QRasterPaintEngineState *s = q->state();
 
     rasterizer->setAntialiased(s->flags.antialiased);
+    rasterizer->setLegacyRoundingEnabled(s->flags.legacy_rounding);
 
     QRect clipRect(deviceRect);
     ProcessSpans blend;
@@ -3427,6 +3523,7 @@ void QRasterPaintEnginePrivate::rasterize(QT_FT_Outline *outline,
 
     if (!s->flags.antialiased) {
         rasterizer->setAntialiased(s->flags.antialiased);
+        rasterizer->setLegacyRoundingEnabled(s->flags.legacy_rounding);
         rasterizer->setClipRect(deviceRect);
         rasterizer->initialize(callback, userData);
 
@@ -4491,7 +4588,7 @@ void QSpanData::setupMatrix(const QTransform &matrix, int bilin)
     txop = inv.type();
     bilinear = bilin;
 
-    const bool affine = !m13 && !m23;
+    const bool affine = inv.isAffine();
     fast_matrix = affine
         && m11 * m11 + m21 * m21 < 1e4
         && m12 * m12 + m22 * m22 < 1e4
@@ -4668,20 +4765,9 @@ static void drawEllipse_midpoint_i(const QRect &rect, const QRect &clip,
 /*!
     \fn void QRasterPaintEngine::drawPoints(const QPoint *points, int pointCount)
     \overload
-
-    Draws the first \a pointCount points in the buffer \a points
-
-    The default implementation converts the first \a pointCount QPoints in \a points
-    to QPointFs and calls the floating point version of drawPoints.
+    \reimp
 */
 
-/*!
-    \fn void QRasterPaintEngine::drawEllipse(const QRect &rect)
-    \overload
-
-    Reimplement this function to draw the largest ellipse that can be
-    contained within rectangle \a rect.
-*/
 
 #ifdef QT_DEBUG_DRAW
 void dumpClip(int width, int height, const QClipData *clip)