QSpanData: use isAffine() instead of rolling your own test
[profile/ivi/qtbase.git] / src / gui / painting / qpaintengine_raster.cpp
index 2119e30..0e9129f 100644 (file)
@@ -1,17 +1,18 @@
 /****************************************************************************
 **
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
+** 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$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the Technology Preview License Agreement accompanying
-** this package.
+** 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
 ** Alternatively, this file may be used under the terms of the GNU Lesser
 ** 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.
 **
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
-**
-**
-**
-**
-**
+** 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.
 **
 **
 ** $QT_END_LICENSE$
 #include <qpainterpath.h>
 #include <qdebug.h>
 #include <qhash.h>
-#include <qlabel.h>
 #include <qbitmap.h>
 #include <qmath.h>
 
-#if defined (Q_WS_X11)
-#  include <private/qfontengine_ft_p.h>
-#endif
-
 //   #include <private/qdatabuffer_p.h>
 //   #include <private/qpainter_p.h>
 #include <private/qmath_p.h>
 //   #include <private/qrasterizer_p.h>
 #include <private/qimage_p.h>
 #include <private/qstatictext_p.h>
+#include <private/qcosmeticstroker_p.h>
 #include "qmemrotate_p.h"
 
 #include "qpaintengine_raster_p.h"
 //   #include "qbezier_p.h"
 #include "qoutlinemapper_p.h"
 
-#if defined(Q_WS_WIN)
-#  include <qt_windows.h>
+#include <limits.h>
+
+#ifdef Q_OS_WIN
 #  include <qvarlengtharray.h>
 #  include <private/qfontengine_p.h>
-#  if defined(Q_OS_WINCE)
-#    include "qguifunctions_wince.h"
-#  endif
-#elif defined(Q_WS_MAC)
-#  include <private/qt_mac_p.h>
-#  include <private/qpixmap_mac_p.h>
-#  include <private/qpaintengine_mac_p.h>
-#elif defined(Q_WS_QWS)
-#  if !defined(QT_NO_FREETYPE)
-#    include <private/qfontengine_ft_p.h>
-#  endif
-#  if !defined(QT_NO_QWS_QPF2)
-#    include <private/qfontengine_qpf_p.h>
+#  include <qt_windows.h>
+#ifdef Q_OS_WIN64
+#    include <malloc.h>
 #  endif
-#  include <private/qabstractfontengine_p.h>
-#elif defined(Q_OS_SYMBIAN) && defined(QT_NO_FREETYPE)
-#  include <private/qfontengine_s60_p.h>
-#elif defined(Q_WS_QPA)
-#  include <private/qfontengine_ft_p.h>
-#endif
-
-#if defined(Q_WS_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))
@@ -126,13 +151,32 @@ void dumpClip(int width, int height, const QClipData *clip);
 // 4 pixels.
 #define int_dim(pos, dim) (int(pos+dim) - int(pos))
 
-#ifdef Q_WS_WIN
-extern bool qt_cleartype_enabled;
-#endif
+static const qreal aliasedCoordinateDelta = 0.5 - 0.015625;
+
+#ifdef Q_OS_WIN
 
-#ifdef Q_WS_MAC
-extern bool qt_applefontsmoothing_enabled;
+static inline bool winClearTypeFontsEnabled()
+{
+    UINT result = 0;
+#if !defined(SPI_GETFONTSMOOTHINGTYPE) // MinGW
+#    define SPI_GETFONTSMOOTHINGTYPE  0x200A
+#    define FE_FONTSMOOTHINGCLEARTYPE 0x002
 #endif
+    SystemParametersInfo(SPI_GETFONTSMOOTHINGTYPE, 0, &result, 0);
+    return result == FE_FONTSMOOTHINGCLEARTYPE;
+}
+
+/*!
+    \internal
+ */
+bool QRasterPaintEngine::clearTypeFontsEnabled()
+{
+    static const bool result = winClearTypeFontsEnabled();
+    return result;
+}
+
+#endif // Q_OS_WIN
+
 
 
 /********************************************************************************
@@ -141,7 +185,6 @@ extern bool qt_applefontsmoothing_enabled;
 static void qt_span_fill_clipRect(int count, const QSpan *spans, void *userData);
 static void qt_span_fill_clipped(int count, const QSpan *spans, void *userData);
 static void qt_span_clip(int count, const QSpan *spans, void *userData);
-static void qt_merge_clip(const QClipData *c1, const QClipData *c2, QClipData *result);
 
 struct ClipData
 {
@@ -156,16 +199,6 @@ enum LineDrawMode {
     LineDrawIncludeLastPixel
 };
 
-static void drawLine_midpoint_i(int x1, int y1, int x2, int y2, ProcessSpans span_func, QSpanData *data,
-                                LineDrawMode style, const QIntRect &rect);
-static void drawLine_midpoint_dashed_i(int x1, int y1, int x2, int y2,
-                                       QPen *pen, ProcessSpans span_func, QSpanData *data,
-                                       LineDrawMode style, const QIntRect &devRect,
-                                       int *patternOffset);
-// static void drawLine_midpoint_f(qreal x1, qreal y1, qreal x2, qreal y2,
-//                                 ProcessSpans span_func, QSpanData *data,
-//                                 LineDrawMode style, const QRect &devRect);
-
 static void drawEllipse_midpoint_i(const QRect &rect, const QRect &clip,
                                    ProcessSpans pen_func, ProcessSpans brush_func,
                                    QSpanData *pen_data, QSpanData *brush_data);
@@ -338,7 +371,7 @@ void QRasterPaintEngine::init()
     Q_D(QRasterPaintEngine);
 
 
-#ifdef Q_WS_WIN
+#ifdef Q_OS_WIN
     d->hdc = 0;
 #endif
 
@@ -384,11 +417,6 @@ void QRasterPaintEngine::init()
     case QInternal::Image:
         format = d->rasterBuffer->prepare(static_cast<QImage *>(d->device));
         break;
-#ifdef Q_WS_QWS
-    case QInternal::CustomRaster:
-        d->rasterBuffer->prepare(static_cast<QCustomRasterPaintDevice*>(d->device));
-        break;
-#endif
     default:
         qWarning("QRasterPaintEngine: unsupported target device %d\n", d->device->devType());
         d->device = 0;
@@ -442,8 +470,8 @@ bool QRasterPaintEngine::begin(QPaintDevice *device)
 
     if (device->devType() == QInternal::Pixmap) {
         QPixmap *pixmap = static_cast<QPixmap *>(device);
-        QPixmapData *pd = pixmap->pixmapData();
-        if (pd->classId() == QPixmapData::RasterClass || pd->classId() == QPixmapData::BlitterClass)
+        QPlatformPixmap *pd = pixmap->handle();
+        if (pd->classId() == QPlatformPixmap::RasterClass || pd->classId() == QPlatformPixmap::BlitterClass)
             d->device = pd->buffer();
     } else {
         d->device = device;
@@ -489,16 +517,10 @@ bool QRasterPaintEngine::begin(QPaintDevice *device)
     }
 #endif
 
-#if defined(Q_WS_WIN)
-    d->isPlain45DegreeRotation = true;
-#endif
-
     if (d->mono_surface)
         d->glyphCacheType = QFontEngineGlyphCache::Raster_Mono;
-#if defined(Q_WS_WIN)
-    else if (qt_cleartype_enabled)
-#elif defined (Q_WS_MAC)
-    else if (qt_applefontsmoothing_enabled)
+#if defined(Q_OS_WIN)
+    else if (clearTypeFontsEnabled())
 #else
     else if (false)
 #endif
@@ -596,33 +618,6 @@ void QRasterPaintEngine::updateMatrix(const QTransform &matrix)
     s->flags.tx_noshear = qt_scaleForTransform(s->matrix, &s->txscale);
 
     ensureOutlineMapper();
-
-#ifdef Q_WS_WIN
-    Q_D(QRasterPaintEngine);
-    d->isPlain45DegreeRotation = false;
-    if (txop >= QTransform::TxRotate) {
-        d->isPlain45DegreeRotation =
-            (qFuzzyIsNull(matrix.m11())
-             && qFuzzyIsNull(matrix.m12() - qreal(1))
-             && qFuzzyIsNull(matrix.m21() + qreal(1))
-             && qFuzzyIsNull(matrix.m22())
-                )
-            ||
-            (qFuzzyIsNull(matrix.m11() + qreal(1))
-             && qFuzzyIsNull(matrix.m12())
-             && qFuzzyIsNull(matrix.m21())
-             && qFuzzyIsNull(matrix.m22() + qreal(1))
-                )
-            ||
-            (qFuzzyIsNull(matrix.m11())
-             && qFuzzyIsNull(matrix.m12() + qreal(1))
-             && qFuzzyIsNull(matrix.m21() - qreal(1))
-             && qFuzzyIsNull(matrix.m22())
-                )
-            ;
-    }
-#endif
-
 }
 
 
@@ -649,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;
@@ -775,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...
@@ -789,14 +785,13 @@ void QRasterPaintEngine::updatePen(const QPen &pen)
         s->stroker = 0;
     }
 
+    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
-                  && !s->flags.antialiased
-                  && (penWidth == 0 || (penWidth <= 1
-                                        && (s->matrix.type() <= QTransform::TxTranslate
-                                            || pen.isCosmetic())));
+            && s->penData.blend
+            && ((cosmetic && penWidth <= 1)
+                || (!cosmetic && s->flags.tx_noshear && penWidth * s->txscale <= 1));
 
-    ensureState(); // needed because of tx_noshear...
     s->flags.non_complex_pen = qpen_capStyle(s->lastPen) <= Qt::SquareCap && s->flags.tx_noshear;
 
     s->strokeFlags = 0;
@@ -859,7 +854,7 @@ void QRasterPaintEngine::updateOutlineMapper()
     d->outlineMapper->setMatrix(state()->matrix);
 }
 
-void QRasterPaintEngine::updateState()
+void QRasterPaintEngine::updateRasterState()
 {
     QRasterPaintEngineState *s = state();
 
@@ -934,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;
@@ -986,13 +982,6 @@ void QRasterPaintEngine::clipEnabledChanged()
     }
 }
 
-#ifdef Q_WS_QWS
-void QRasterPaintEnginePrivate::prepare(QCustomRasterPaintDevice *device)
-{
-    rasterBuffer->prepare(device);
-}
-#endif
-
 void QRasterPaintEnginePrivate::drawImage(const QPointF &pt,
                                           const QImage &img,
                                           SrcOverBlendFunc func,
@@ -1083,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)
@@ -1201,8 +1192,7 @@ void QRasterPaintEngine::clip(const QVectorPath &path, Qt::ClipOperation op)
     const QPainterPath::ElementType *types = path.elements();
 
     // There are some cases that are not supported by clip(QRect)
-    if (op != Qt::UniteClip && (op != Qt::IntersectClip || !s->clip
-                                || s->clip->hasRectClip || s->clip->hasRegionClip)) {
+    if (op != Qt::IntersectClip || !s->clip || s->clip->hasRectClip || s->clip->hasRegionClip) {
         if (s->matrix.type() <= QTransform::TxScale
             && ((path.shape() == QVectorPath::RectangleHint)
                 || (isRect(points, path.elementCount())
@@ -1245,18 +1235,6 @@ void QRasterPaintEngine::clip(const QVectorPath &path, Qt::ClipOperation op)
 
         newClip->fixup();
 
-        if (op == Qt::UniteClip) {
-            // merge clips
-            QClipData *result = new QClipData(d->rasterBuffer->height());
-            QClipData *current = s->clip ? s->clip : new QClipData(d->rasterBuffer->height());
-            qt_merge_clip(current, newClip, result);
-            result->fixup();
-            delete newClip;
-            if (!s->clip)
-                delete current;
-            newClip = result;
-        }
-
         if (s->flags.has_clip_ownership)
             delete s->clip;
 
@@ -1282,7 +1260,7 @@ void QRasterPaintEngine::clip(const QRect &rect, Qt::ClipOperation op)
     if (op == Qt::NoClip) {
         qrasterpaintengine_state_setNoClip(s);
 
-    } else if (op == Qt::UniteClip || s->matrix.type() > QTransform::TxScale) {
+    } else if (s->matrix.type() > QTransform::TxScale) {
         QPaintEngineEx::clip(rect, op);
         return;
 
@@ -1367,7 +1345,6 @@ void QRasterPaintEngine::clip(const QRegion &region, Qt::ClipOperation op)
     if (op == Qt::NoClip) {
         qrasterpaintengine_state_setNoClip(s);
     } else if (s->matrix.type() > QTransform::TxScale
-               || op == Qt::UniteClip
                || (op == Qt::IntersectClip && !clip->hasRectClip && !clip->hasRegionClip)
                || (op == Qt::ReplaceClip && !baseClip->hasRectClip && !baseClip->hasRegionClip)) {
         QPaintEngineEx::clip(region, op);
@@ -1400,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)
@@ -1513,6 +1497,7 @@ void QRasterPaintEngine::drawRects(const QRect *rects, int rectCount)
     qDebug(" - QRasterPaintEngine::drawRect(), rectCount=%d", rectCount);
 #endif
     Q_D(QRasterPaintEngine);
+    ensureRasterState();
     QRasterPaintEngineState *s = state();
 
     // Fill
@@ -1541,32 +1526,15 @@ void QRasterPaintEngine::drawRects(const QRect *rects, int rectCount)
 
     ensurePen();
     if (s->penData.blend) {
-        if (s->flags.fast_pen && s->lastPen.brush().isOpaque()) {
-            const QRect *r = rects;
-            const QRect *lastRect = rects + rectCount;
-            while (r < lastRect) {
-                int left = r->x();
-                int right = r->x() + r->width();
-                int top = r->y();
-                int bottom = r->y() + r->height();
-
-#ifdef Q_WS_MAC
-                int pts[] = { top, left,
-                              top, right,
-                              bottom, right,
-                              bottom, left };
-#else
-                int pts[] = { left, top,
-                              right, top,
-                              right, bottom,
-                              left, bottom };
-#endif
-
-                strokePolygonCosmetic((QPoint *) pts, 4, WindingMode);
-                ++r;
+        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);
             }
         } else {
-            QRectVectorPath path;
             for (int i = 0; i < rectCount; ++i) {
                 path.set(rects[i]);
                 stroke(path, s->pen);
@@ -1581,13 +1549,13 @@ void QRasterPaintEngine::drawRects(const QRect *rects, int rectCount)
 void QRasterPaintEngine::drawRects(const QRectF *rects, int rectCount)
 {
 #ifdef QT_DEBUG_DRAW
-    qDebug(" - QRasterPaintEngine::drawRect(), rectCount=%d", rectCount);
+    qDebug(" - QRasterPaintEngine::drawRect(QRectF*), rectCount=%d", rectCount);
 #endif
 #ifdef QT_FAST_SPANS
     Q_D(QRasterPaintEngine);
+    ensureRasterState();
     QRasterPaintEngineState *s = state();
 
-    ensureState();
 
     if (s->flags.tx_noshear) {
         ensureBrush();
@@ -1605,59 +1573,18 @@ void QRasterPaintEngine::drawRects(const QRectF *rects, int rectCount)
 
         ensurePen();
         if (s->penData.blend) {
-            qreal width = s->pen.isCosmetic()
-                          ? (s->lastPen.widthF() == 0 ? 1 : s->lastPen.widthF())
-                          : s->lastPen.widthF() * s->txscale;
-
-            if (s->flags.fast_pen && s->lastPen.brush().isOpaque()) {
-                for (int i = 0; i < rectCount; ++i) {
-                    const QRectF &r = rects[i];
-                    qreal left = r.x();
-                    qreal right = r.x() + r.width();
-                    qreal top = r.y();
-                    qreal bottom = r.y() + r.height();
-                    qreal pts[] = { left, top,
-                                    right, top,
-                                    right, bottom,
-                                    left, bottom };
-                    strokePolygonCosmetic((QPointF *) pts, 4, WindingMode);
-                }
-            } else if (width <= 1 && qpen_style(s->lastPen) == Qt::SolidLine) {
-                d->initializeRasterizer(&s->penData);
-
+            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) {
-                    const QRectF &rect = rects[i].normalized();
-                    if (rect.isEmpty()) {
-                        qreal pts[] = { rect.left(), rect.top(), rect.right(), rect.bottom() };
-                        QVectorPath vp(pts, 2, 0, QVectorPath::LinesHint);
-                        QPaintEngineEx::stroke(vp, s->lastPen);
-                    } else {
-                        const QPointF tl = s->matrix.map(rect.topLeft());
-                        const QPointF tr = s->matrix.map(rect.topRight());
-                        const QPointF bl = s->matrix.map(rect.bottomLeft());
-                        const QPointF br = s->matrix.map(rect.bottomRight());
-                        const qreal w = width / (rect.width() * s->txscale);
-                        const qreal h = width / (rect.height() * s->txscale);
-                        d->rasterizer->rasterizeLine(tl, tr, w); // top
-                        d->rasterizer->rasterizeLine(bl, br, w); // bottom
-                        d->rasterizer->rasterizeLine(bl, tl, h); // left
-                        d->rasterizer->rasterizeLine(br, tr, h); // right
-                    }
+                    path.set(rects[i]);
+                    stroker.drawPath(path);
                 }
             } else {
                 for (int i = 0; i < rectCount; ++i) {
-                    const QRectF &r = rects[i];
-                    qreal left = r.x();
-                    qreal right = r.x() + r.width();
-                    qreal top = r.y();
-                    qreal bottom = r.y() + r.height();
-                    qreal pts[] = { left, top,
-                                    right, top,
-                                    right, bottom,
-                                    left, bottom,
-                                    left, top };
-                    QVectorPath vp(pts, 5, 0, QVectorPath::RectangleHint);
-                    QPaintEngineEx::stroke(vp, s->lastPen);
+                    path.set(rects[i]);
+                    QPaintEngineEx::stroke(path, s->lastPen);
                 }
             }
         }
@@ -1674,38 +1601,19 @@ void QRasterPaintEngine::drawRects(const QRectF *rects, int rectCount)
 */
 void QRasterPaintEngine::stroke(const QVectorPath &path, const QPen &pen)
 {
+    Q_D(QRasterPaintEngine);
     QRasterPaintEngineState *s = state();
+
     ensurePen(pen);
     if (!s->penData.blend)
         return;
 
-    if (s->flags.fast_pen && !path.isCurved()
-        && s->lastPen.brush().isOpaque()) {
-        int count = path.elementCount();
-        QPointF *points = (QPointF *) path.points();
-        const QPainterPath::ElementType *types = path.elements();
-        if (types) {
-            int first = 0;
-            int last;
-            while (first < count) {
-                while (first < count && types[first] != QPainterPath::MoveToElement) ++first;
-                last = first + 1;
-                while (last < count && types[last] == QPainterPath::LineToElement) ++last;
-                strokePolygonCosmetic(points + first, last - first,
-                                      path.hasImplicitClose() && last == count // only close last one..
-                                      ? WindingMode
-                                      : PolylineMode);
-                first = last;
-            }
-        } else {
-            strokePolygonCosmetic(points, count,
-                                  path.hasImplicitClose()
-                                  ? WindingMode
-                                  : PolylineMode);
-        }
-
+    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;
@@ -1758,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());
-    int y1 = qRound(rect.y());
-    int x2 = qRound(rect.right());
-    int y2 = qRound(rect.bottom());
+    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);
@@ -1803,7 +1715,7 @@ void QRasterPaintEngine::fill(const QVectorPath &path, const QBrush &brush)
             fillRect_normalized(toNormalizedFillRect(QRectF(tl, br)), &s->brushData, d);
             return;
         }
-        ensureState();
+        ensureRasterState();
         if (s->flags.tx_noshear) {
             d->initializeRasterizer(&s->brushData);
             // ### Is normalizing really necessary here?
@@ -1818,26 +1730,6 @@ void QRasterPaintEngine::fill(const QVectorPath &path, const QBrush &brush)
         }
     }
 
-    if (path.shape() == QVectorPath::EllipseHint) {
-        if (!s->flags.antialiased && s->matrix.type() <= QTransform::TxScale) {
-            const qreal *p = path.points();
-            QPointF tl = QPointF(p[0], p[1]) * s->matrix;
-            QPointF br = QPointF(p[4], p[5]) * s->matrix;
-            QRectF r = s->matrix.mapRect(QRectF(tl, br));
-
-            ProcessSpans penBlend = d->getPenFunc(r, &s->penData);
-            ProcessSpans brushBlend = d->getBrushFunc(r, &s->brushData);
-            const QRect brect = QRect(int(r.x()), int(r.y()),
-                                      int_dim(r.x(), r.width()),
-                                      int_dim(r.y(), r.height()));
-            if (brect == r) {
-                drawEllipse_midpoint_i(brect, d->deviceRect, penBlend, brushBlend,
-                                       &s->penData, &s->brushData);
-                return;
-            }
-        }
-    }
-
     // ### Optimize for non transformed ellipses and rectangles...
     QRectF cpRect = path.controlPointRect();
     const QRect deviceRect = s->matrix.mapRect(cpRect).toRect();
@@ -1880,7 +1772,7 @@ void QRasterPaintEngine::fillRect(const QRectF &r, QSpanData *data)
             return;
         }
     }
-    ensureState();
+    ensureRasterState();
     if (s->flags.tx_noshear) {
         d->initializeRasterizer(data);
         QRectF nr = r.normalized();
@@ -2032,6 +1924,7 @@ void QRasterPaintEngine::fillPolygon(const QPointF *points, int pointCount, Poly
 */
 void QRasterPaintEngine::drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode)
 {
+    Q_D(QRasterPaintEngine);
     QRasterPaintEngineState *s = state();
 
 #ifdef QT_DEBUG_DRAW
@@ -2048,20 +1941,21 @@ void QRasterPaintEngine::drawPolygon(const QPointF *points, int pointCount, Poly
     }
 
     ensurePen();
-    ensureBrush();
     if (mode != PolylineMode) {
         // Do the fill...
-        if (s->brushData.blend) {
+        ensureBrush();
+        if (s->brushData.blend)
             fillPolygon(points, pointCount, mode);
-        }
     }
 
     // Do the outline...
     if (s->penData.blend) {
-        if (s->flags.fast_pen && s->lastPen.brush().isOpaque())
-            strokePolygonCosmetic(points, pointCount, mode);
-        else {
-            QVectorPath vp((qreal *) points, pointCount, 0, QVectorPath::polygonFlags(mode));
+        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);
         }
     }
@@ -2090,13 +1984,7 @@ void QRasterPaintEngine::drawPolygon(const QPoint *points, int pointCount, Polyg
         return;
     }
 
-    ensureState();
     ensurePen();
-    if (!(s->flags.int_xform && s->flags.fast_pen && (!s->penData.blend || s->pen.brush().isOpaque()))) {
-        // this calls the float version
-        QPaintEngineEx::drawPolygon(points, pointCount, mode);
-        return;
-    }
 
     // Do the fill
     if (mode != PolylineMode) {
@@ -2122,230 +2010,18 @@ void QRasterPaintEngine::drawPolygon(const QPoint *points, int pointCount, Polyg
 
     // Do the outline...
     if (s->penData.blend) {
-        if (s->flags.fast_pen && s->lastPen.brush().isOpaque())
-            strokePolygonCosmetic(points, pointCount, mode);
-        else {
-            int count = pointCount * 2;
-            QVarLengthArray<qreal> fpoints(count);
-#ifdef Q_WS_MAC
-            for (int i=0; i<count; i+=2) {
-                fpoints[i] = ((int *) points)[i+1];
-                fpoints[i+1] = ((int *) points)[i];
-            }
-#else
-            for (int i=0; i<count; ++i)
-                fpoints[i] = ((int *) points)[i];
-#endif
-            QVectorPath vp((qreal *) fpoints.data(), pointCount, 0, QVectorPath::polygonFlags(mode));
-            QPaintEngineEx::stroke(vp, s->lastPen);
-        }
-    }
-}
-
-/*!
-    \internal
-*/
-void QRasterPaintEngine::strokePolygonCosmetic(const QPointF *points, int pointCount, PolygonDrawMode mode)
-{
-    Q_D(QRasterPaintEngine);
-    QRasterPaintEngineState *s = state();
-
-    Q_ASSERT(s->penData.blend);
-    Q_ASSERT(s->flags.fast_pen);
-
-    bool needs_closing = mode != PolylineMode && points[0] != points[pointCount-1];
-
-    // Use fast path for 0 width /  trivial pens.
-    QIntRect devRect;
-    devRect.set(d->deviceRect);
-
-    LineDrawMode mode_for_last = (s->lastPen.capStyle() != Qt::FlatCap
-                                  ? LineDrawIncludeLastPixel
-                                  : LineDrawNormal);
-    int dashOffset = int(s->lastPen.dashOffset());
-
-    // Draw all the line segments.
-    for (int i=1; i<pointCount; ++i) {
-
-        QPointF lp1 = points[i-1] * s->matrix;
-        QPointF lp2 = points[i] * s->matrix;
-
-        const QRectF brect(lp1, lp2);
-        ProcessSpans penBlend = d->getPenFunc(brect, &s->penData);
-        if (qpen_style(s->lastPen) == Qt::SolidLine) {
-            drawLine_midpoint_i(qFloor(lp1.x()), qFloor(lp1.y()),
-                                qFloor(lp2.x()), qFloor(lp2.y()),
-                                penBlend, &s->penData,
-                                i == pointCount - 1 ? mode_for_last : LineDrawIncludeLastPixel,
-                                devRect);
-        } else {
-            drawLine_midpoint_dashed_i(qFloor(lp1.x()), qFloor(lp1.y()),
-                                       qFloor(lp2.x()), qFloor(lp2.y()),
-                                       &s->lastPen,
-                                       penBlend, &s->penData,
-                                       i == pointCount - 1 ? mode_for_last : LineDrawIncludeLastPixel,
-                                       devRect, &dashOffset);
-        }
-    }
-
-    // Polygons are implicitly closed.
-    if (needs_closing) {
-        QPointF lp1 = points[pointCount-1] * s->matrix;
-        QPointF lp2 = points[0] * s->matrix;
-
-        const QRectF brect(lp1, lp2);
-        ProcessSpans penBlend = d->getPenFunc(brect, &s->penData);
-        if (qpen_style(s->lastPen) == Qt::SolidLine) {
-            drawLine_midpoint_i(qFloor(lp1.x()), qFloor(lp1.y()),
-                                qFloor(lp2.x()), qFloor(lp2.y()),
-                                penBlend, &s->penData,
-                                LineDrawIncludeLastPixel,
-                                devRect);
+        int count = pointCount * 2;
+        QVarLengthArray<qreal> fpoints(count);
+        for (int i=0; i<count; ++i)
+            fpoints[i] = ((int *) points)[i];
+        QVectorPath vp((qreal *) fpoints.data(), 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 {
-            drawLine_midpoint_dashed_i(qFloor(lp1.x()), qFloor(lp1.y()),
-                                       qFloor(lp2.x()), qFloor(lp2.y()),
-                                       &s->lastPen,
-                                       penBlend, &s->penData,
-                                       LineDrawIncludeLastPixel,
-                                       devRect, &dashOffset);
-        }
-    }
-
-}
-
-/*!
-    \internal
-*/
-void QRasterPaintEngine::strokePolygonCosmetic(const QPoint *points, int pointCount, PolygonDrawMode mode)
-{
-    Q_D(QRasterPaintEngine);
-    QRasterPaintEngineState *s = state();
-
-    // We assert here because this function is called from drawRects
-    // and drawPolygon and they already do ensurePen(), so we skip that
-    // here to avoid duplicate checks..
-    Q_ASSERT(s->penData.blend);
-
-    bool needs_closing = mode != PolylineMode && points[0] != points[pointCount-1];
-
-    QIntRect devRect;
-    devRect.set(d->deviceRect);
-
-    LineDrawMode mode_for_last = (s->lastPen.capStyle() != Qt::FlatCap
-                                  ? LineDrawIncludeLastPixel
-                                  : LineDrawNormal);
-
-    int m11 = int(s->matrix.m11());
-    int m22 = int(s->matrix.m22());
-    int dx = int(s->matrix.dx());
-    int dy = int(s->matrix.dy());
-    int m13 = int(s->matrix.m13());
-    int m23 = int(s->matrix.m23());
-    bool affine = !m13 && !m23;
-
-    int dashOffset = int(s->lastPen.dashOffset());
-
-    if (affine) {
-        // Draw all the line segments.
-        for (int i=1; i<pointCount; ++i) {
-            const QPoint lp1 = points[i-1] * s->matrix;
-            const QPoint lp2 = points[i] * s->matrix;
-            const QRect brect(lp1, lp2);
-            ProcessSpans penBlend = d->getPenFunc(brect, &s->penData);
-
-            if (qpen_style(s->lastPen) == Qt::SolidLine)
-                drawLine_midpoint_i(lp1.x(), lp1.y(),
-                                    lp2.x(), lp2.y(),
-                                    penBlend, &s->penData,
-                                    i == pointCount - 1 ? mode_for_last : LineDrawIncludeLastPixel,
-                                    devRect);
-            else
-                drawLine_midpoint_dashed_i(lp1.x(), lp1.y(),
-                                           lp2.x(), lp2.y(),
-                                           &s->lastPen,
-                                           penBlend, &s->penData,
-                                           i == pointCount - 1 ? mode_for_last : LineDrawIncludeLastPixel,
-                                           devRect, &dashOffset);
-
-        }
-
-        // Polygons are implicitly closed.
-        if (needs_closing) {
-            const QPoint lp1 = points[pointCount - 1] * s->matrix;
-            const QPoint lp2 = points[0] * s->matrix;
-            const QRect brect(lp1, lp2);
-            ProcessSpans penBlend = d->getPenFunc(brect, &s->penData);
-
-            if (qpen_style(s->lastPen) == Qt::SolidLine)
-                drawLine_midpoint_i(lp1.x(), lp1.y(),
-                                    lp2.x(), lp2.y(),
-                                    penBlend, &s->penData, LineDrawIncludeLastPixel,
-                                    devRect);
-            else
-                drawLine_midpoint_dashed_i(lp1.x(), lp1.y(),
-                                           lp2.x(), lp2.y(),
-                                           &s->lastPen,
-                                           penBlend, &s->penData, LineDrawIncludeLastPixel,
-                                           devRect, &dashOffset);
-        }
-    } else {
-        // Draw all the line segments.
-        for (int i=1; i<pointCount; ++i) {
-            int x1 = points[i-1].x() * m11 + dx;
-            int y1 = points[i-1].y() * m22 + dy;
-            qreal w = m13*points[i-1].x() + m23*points[i-1].y() + 1.;
-            w = 1/w;
-            x1 = int(x1*w);
-            y1 = int(y1*w);
-            int x2 = points[i].x() * m11 + dx;
-            int y2 = points[i].y() * m22 + dy;
-            w = m13*points[i].x() + m23*points[i].y() + 1.;
-            w = 1/w;
-            x2 = int(x2*w);
-            y2 = int(y2*w);
-
-            const QRect brect(x1, y1, x2 - x1 + 1, y2 - y1 + 1);
-            ProcessSpans penBlend = d->getPenFunc(brect, &s->penData);
-            if (qpen_style(s->lastPen) == Qt::SolidLine)
-                drawLine_midpoint_i(x1, y1, x2, y2,
-                                    penBlend, &s->penData,
-                                    i == pointCount - 1 ? mode_for_last : LineDrawIncludeLastPixel,
-                                    devRect);
-            else
-                drawLine_midpoint_dashed_i(x1, y1, x2, y2,
-                                           &s->lastPen,
-                                           penBlend, &s->penData,
-                                           i == pointCount - 1 ? mode_for_last : LineDrawIncludeLastPixel,
-                                           devRect, &dashOffset);
-
-        }
-
-        int x1 = points[pointCount-1].x() * m11 + dx;
-        int y1 = points[pointCount-1].y() * m22 + dy;
-        qreal w = m13*points[pointCount-1].x() + m23*points[pointCount-1].y() + 1.;
-        w = 1/w;
-        x1 = int(x1*w);
-        y1 = int(y1*w);
-        int x2 = points[0].x() * m11 + dx;
-        int y2 = points[0].y() * m22 + dy;
-        w = m13*points[0].x() + m23*points[0].y() + 1.;
-        w = 1/w;
-        x2 = int(x2 * w);
-        y2 = int(y2 * w);
-        // Polygons are implicitly closed.
-
-        if (needs_closing) {
-            const QRect brect(x1, y1, x2 - x1 + 1, y2 - y1 + 1);
-            ProcessSpans penBlend = d->getPenFunc(brect, &s->penData);
-            if (qpen_style(s->lastPen) == Qt::SolidLine)
-                drawLine_midpoint_i(x1, y1, x2, y2,
-                                    penBlend, &s->penData, LineDrawIncludeLastPixel,
-                                    devRect);
-            else
-                drawLine_midpoint_dashed_i(x1, y1, x2, y2,
-                                           &s->lastPen,
-                                           penBlend, &s->penData, LineDrawIncludeLastPixel,
-                                           devRect, &dashOffset);
+            QPaintEngineEx::stroke(vp, s->lastPen);
         }
     }
 }
@@ -2359,9 +2035,9 @@ void QRasterPaintEngine::drawPixmap(const QPointF &pos, const QPixmap &pixmap)
     qDebug() << " - QRasterPaintEngine::drawPixmap(), pos=" << pos << " pixmap=" << pixmap.size() << "depth=" << pixmap.depth();
 #endif
 
-    QPixmapData *pd = pixmap.pixmapData();
-    if (pd->classId() == QPixmapData::RasterClass) {
-        const QImage &image = static_cast<QRasterPixmapData *>(pd)->image;
+    QPlatformPixmap *pd = pixmap.handle();
+    if (pd->classId() == QPlatformPixmap::RasterClass) {
+        const QImage &image = static_cast<QRasterPlatformPixmap *>(pd)->image;
         if (image.depth() == 1) {
             Q_D(QRasterPaintEngine);
             QRasterPaintEngineState *s = state();
@@ -2400,9 +2076,9 @@ void QRasterPaintEngine::drawPixmap(const QRectF &r, const QPixmap &pixmap, cons
     qDebug() << " - QRasterPaintEngine::drawPixmap(), r=" << r << " sr=" << sr << " pixmap=" << pixmap.size() << "depth=" << pixmap.depth();
 #endif
 
-    QPixmapData* pd = pixmap.pixmapData();
-    if (pd->classId() == QPixmapData::RasterClass) {
-        const QImage &image = static_cast<QRasterPixmapData *>(pd)->image;
+    QPlatformPixmap* pd = pixmap.handle();
+    if (pd->classId() == QPlatformPixmap::RasterClass) {
+        const QImage &image = static_cast<QRasterPlatformPixmap *>(pd)->image;
         if (image.depth() == 1) {
             Q_D(QRasterPaintEngine);
             QRasterPaintEngineState *s = state();
@@ -2440,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);
@@ -2480,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 {
@@ -2579,8 +2245,13 @@ void QRasterPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRe
     int sr_b = qCeil(sr.bottom()) - 1;
 
     if (s->matrix.type() <= QTransform::TxScale && !s->flags.antialiased && sr_l == sr_r && sr_t == sr_b) {
+        // 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;
 
+        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);
         switch (img.format()) {
@@ -2681,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(),
@@ -2718,14 +2405,17 @@ void QRasterPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRe
         }
 
 #ifdef QT_FAST_SPANS
-        ensureState();
+        ensureRasterState();
         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.legacy_rounding ? QPointF(aliasedCoordinateDelta, aliasedCoordinateDelta) : QPointF();
 
             const QRectF &rect = r.normalized();
-            const QPointF a = s->matrix.map((rect.topLeft() + rect.bottomLeft()) * 0.5f);
-            const QPointF b = s->matrix.map((rect.topRight() + rect.bottomRight()) * 0.5f);
+            const QPointF a = s->matrix.map((rect.topLeft() + rect.bottomLeft()) * 0.5f) - offs;
+            const QPointF b = s->matrix.map((rect.topRight() + rect.bottomRight()) * 0.5f) - offs;
 
             if (s->flags.tx_noshear)
                 d->rasterizer->rasterizeLine(a, b, rect.height() / rect.width());
@@ -2734,12 +2424,13 @@ void QRasterPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRe
             return;
         }
 #endif
+        const qreal offs = s->flags.legacy_rounding ? aliasedCoordinateDelta : qreal(0);
         QPainterPath path;
         path.addRect(r);
         QTransform m = s->matrix;
         s->matrix = QTransform(m.m11(), m.m12(), m.m13(),
                                m.m21(), m.m22(), m.m23(),
-                               m.m31(), m.m32(), m.m33());
+                               m.m31() - offs, m.m32() - offs, m.m33());
         fillPath(path, &d->image_filler_xform);
         s->matrix = m;
     } else {
@@ -2789,9 +2480,9 @@ void QRasterPaintEngine::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap,
 
     QImage image;
 
-    QPixmapData *pd = pixmap.pixmapData();
-    if (pd->classId() == QPixmapData::RasterClass) {
-        image = static_cast<QRasterPixmapData *>(pd)->image;
+    QPlatformPixmap *pd = pixmap.handle();
+    if (pd->classId() == QPlatformPixmap::RasterClass) {
+        image = static_cast<QRasterPlatformPixmap *>(pd)->image;
     } else {
         image = pixmap.toImage();
     }
@@ -2810,10 +2501,11 @@ void QRasterPaintEngine::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap,
         d->image_filler_xform.setupMatrix(copy, s->flags.bilinear);
 
 #ifdef QT_FAST_SPANS
-        ensureState();
+        ensureRasterState();
         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);
@@ -2852,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)
 {
@@ -3076,97 +2777,42 @@ 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)
 {
     Q_D(QRasterPaintEngine);
     QRasterPaintEngineState *s = state();
 
-#if !defined(QT_NO_FREETYPE)
-    if (fontEngine->type() == QFontEngine::Freetype) {
-        QFontEngineFT *fe = static_cast<QFontEngineFT *>(fontEngine);
-        QFontEngineFT::GlyphFormat neededFormat =
+    if (fontEngine->hasInternalCaching()) {
+        QFontEngine::GlyphFormat neededFormat =
             painter()->device()->devType() == QInternal::Widget
-            ? fe->defaultGlyphFormat()
-            : QFontEngineFT::Format_A8;
-
-        if (d_func()->mono_surface
-            || fe->isBitmapFont() // alphaPenBlt can handle mono, too
-            )
-            neededFormat = QFontEngineFT::Format_Mono;
-
-        if (neededFormat == QFontEngineFT::Format_None)
-            neededFormat = QFontEngineFT::Format_A8;
-
-        QFontEngineFT::QGlyphSet *gset = fe->defaultGlyphs();
-        if (s->matrix.type() >= QTransform::TxScale) {
-            if (s->matrix.isAffine())
-                gset = fe->loadTransformedGlyphSet(s->matrix);
-            else
-                gset = 0;
-        }
-
-        if (!gset || gset->outline_drawing
-            || !fe->loadGlyphs(gset, glyphs, numGlyphs, positions, neededFormat))
-            return false;
-
-        FT_Face lockedFace = 0;
+            ? QFontEngine::Format_None
+            : QFontEngine::Format_A8;
 
-        int depth;
-        switch (neededFormat) {
-        case QFontEngineFT::Format_Mono:
-            depth = 1;
-            break;
-        case QFontEngineFT::Format_A8:
-            depth = 8;
-            break;
-        case QFontEngineFT::Format_A32:
-            depth = 32;
-            break;
-        default:
-            Q_ASSERT(false);
-            depth = 0;
-        };
+        if (d_func()->mono_surface) // alphaPenBlt can handle mono, too
+            neededFormat = QFontEngine::Format_Mono;
 
         for (int i = 0; i < numGlyphs; i++) {
-            QFixed spp = fe->subPixelPositionForX(positions[i].x);
-            QFontEngineFT::Glyph *glyph = gset->getGlyph(glyphs[i], spp);
-
-            if (!glyph || glyph->format != neededFormat) {
-                if (!lockedFace)
-                    lockedFace = fe->lockFace();
-                glyph = fe->loadGlyph(gset, glyphs[i], spp, neededFormat);
-            }
+            QFixed spp = fontEngine->subPixelPositionForX(positions[i].x);
 
-            if (!glyph || !glyph->data)
+            QPoint offset;
+            QImage *alphaMap = fontEngine->lockedAlphaMapForGlyph(glyphs[i], spp, neededFormat, s->matrix,
+                                                                  &offset);
+            if (alphaMap == 0 || alphaMap->isNull())
                 continue;
 
-            int pitch;
-            switch (neededFormat) {
-            case QFontEngineFT::Format_Mono:
-                pitch = ((glyph->width + 31) & ~31) >> 3;
-                break;
-            case QFontEngineFT::Format_A8:
-                pitch = (glyph->width + 3) & ~3;
-                break;
-            case QFontEngineFT::Format_A32:
-                pitch = glyph->width * 4;
-                break;
-            default:
-                Q_ASSERT(false);
-                pitch = 0;
-            };
-
-            alphaPenBlt(glyph->data, pitch, depth,
-                        qFloor(positions[i].x) + glyph->x,
-                        qFloor(positions[i].y) - glyph->y,
-                        glyph->width, glyph->height);
+            alphaPenBlt(alphaMap->bits(), alphaMap->bytesPerLine(), alphaMap->depth(),
+                        qFloor(positions[i].x) + offset.x(),
+                        qRound(positions[i].y) + offset.y(),
+                        alphaMap->width(), alphaMap->height());
+
+            fontEngine->unlockAlphaMapForGlyph();
         }
-        if (lockedFace)
-            fe->unlockFace();
-    } else
-#endif
-    {
+
+    } else {
         QFontEngineGlyphCache::Type glyphType = fontEngine->glyphFormat >= 0 ? QFontEngineGlyphCache::Type(fontEngine->glyphFormat) : d->glyphCacheType;
 
         QImageTextureGlyphCache *cache =
@@ -3190,18 +2836,18 @@ bool QRasterPaintEngine::drawCachedGlyphs(int numGlyphs, const glyph_t *glyphs,
         else if (depth == 1)
             rightShift = 3; // divide by 8
 
-        int margin = cache->glyphMargin();
+        int margin = fontEngine->glyphMargin(glyphType);
         const uchar *bits = image.bits();
         for (int i=0; i<numGlyphs; ++i) {
 
-            QFixed subPixelPosition = cache->subPixelPositionForX(positions[i].x);
+            QFixed subPixelPosition = fontEngine->subPixelPositionForX(positions[i].x);
             QTextureGlyphCache::GlyphAndSubPixelPosition glyph(glyphs[i], subPixelPosition);
             const QTextureGlyphCache::Coord &c = cache->coords[glyph];
             if (c.isNull())
                 continue;
 
             int x = qFloor(positions[i].x) + c.baseLineX - margin;
-            int y = qFloor(positions[i].y) - 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,
@@ -3217,44 +2863,6 @@ bool QRasterPaintEngine::drawCachedGlyphs(int numGlyphs, const glyph_t *glyphs,
     return true;
 }
 
-#if defined(Q_OS_SYMBIAN) && defined(QT_NO_FREETYPE)
-void QRasterPaintEngine::drawGlyphsS60(const QPointF &p, const QTextItemInt &ti)
-{
-    Q_D(QRasterPaintEngine);
-    QRasterPaintEngineState *s = state();
-
-    QFontEngine *fontEngine = ti.fontEngine;
-    if (fontEngine->type() != QFontEngine::S60FontEngine) {
-        QPaintEngineEx::drawTextItem(p, ti);
-        return;
-    }
-
-    QFontEngineS60 *fe = static_cast<QFontEngineS60 *>(fontEngine);
-
-    QVarLengthArray<QFixedPoint> positions;
-    QVarLengthArray<glyph_t> glyphs;
-    QTransform matrix = s->matrix;
-    matrix.translate(p.x(), p.y());
-    if (matrix.type() == QTransform::TxScale)
-        fe->setFontScale(matrix.m11());
-    ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions);
-
-    for (int i=0; i<glyphs.size(); ++i) {
-        TOpenFontCharMetrics tmetrics;
-        const TUint8 *glyphBitmapBytes;
-        TSize glyphBitmapSize;
-        fe->getCharacterData(glyphs[i], tmetrics, glyphBitmapBytes, glyphBitmapSize);
-        const int x = qFloor(positions[i].x + tmetrics.HorizBearingX());
-        const int y = qFloor(positions[i].y - tmetrics.HorizBearingY());
-        alphaPenBlt(glyphBitmapBytes, glyphBitmapSize.iWidth, 8, x, y, glyphBitmapSize.iWidth, glyphBitmapSize.iHeight);
-    }
-
-    if (matrix.type() == QTransform::TxScale)
-        fe->setFontScale(1.0);
-
-    return;
-}
-#endif // Q_OS_SYMBIAN && QT_NO_FREETYPE
 
 /*!
  * Returns true if the rectangle is completely within the current clip
@@ -3346,7 +2954,7 @@ QRasterPaintEnginePrivate::getBrushFunc(const QRectF &rect,
 }
 
 inline ProcessSpans
-QRasterPaintEnginePrivate::getPenFunc(const QRect &rect,
+QRasterPaintEnginePrivate::getPenFunc(const QRectF &rect,
                                       const QSpanData *data) const
 {
     Q_Q(const QRasterPaintEngine);
@@ -3354,21 +2962,41 @@ QRasterPaintEnginePrivate::getPenFunc(const QRect &rect,
 
     if (!s->flags.fast_pen && s->matrix.type() > QTransform::TxTranslate)
         return data->blend;
-    const int penWidth = s->flags.fast_pen ? 1 : qCeil(s->pen.widthF());
+    const int penWidth = s->flags.fast_pen ? 1 : qCeil(s->lastPen.widthF());
     return isUnclipped(rect, penWidth) ? data->unclipped_blend : data->blend;
 }
 
-inline ProcessSpans
-QRasterPaintEnginePrivate::getPenFunc(const QRectF &rect,
-                                      const QSpanData *data) const
+static QPair<int, int> visibleGlyphRange(const QRectF &clip, QFontEngine *fontEngine,
+                                         glyph_t *glyphs, QFixedPoint *positions, int numGlyphs)
 {
-    Q_Q(const QRasterPaintEngine);
-    const QRasterPaintEngineState *s = q->state();
+    QFixed clipLeft = QFixed::fromReal(clip.left());
+    QFixed clipRight = QFixed::fromReal(clip.right());
+    QFixed clipTop = QFixed::fromReal(clip.top());
+    QFixed clipBottom = QFixed::fromReal(clip.bottom());
 
-    if (!s->flags.fast_pen && s->matrix.type() > QTransform::TxTranslate)
-        return data->blend;
-    const int penWidth = s->flags.fast_pen ? 1 : qCeil(s->lastPen.widthF());
-    return isUnclipped(rect, penWidth) ? data->unclipped_blend : data->blend;
+    int first = 0;
+    while (first < numGlyphs) {
+        glyph_metrics_t metrics = fontEngine->boundingBox(glyphs[first]);
+        QFixed left = metrics.x + positions[first].x;
+        QFixed top = metrics.y + positions[first].y;
+        QFixed right = left + metrics.width;
+        QFixed bottom = top + metrics.height;
+        if (left < clipRight && right > clipLeft && top < clipBottom && bottom > clipTop)
+            break;
+        ++first;
+    }
+    int last = numGlyphs - 1;
+    while (last > first) {
+        glyph_metrics_t metrics = fontEngine->boundingBox(glyphs[last]);
+        QFixed left = metrics.x + positions[last].x;
+        QFixed top = metrics.y + positions[last].y;
+        QFixed right = left + metrics.width;
+        QFixed bottom = top + metrics.height;
+        if (left < clipRight && right > clipLeft && top < clipBottom && bottom > clipTop)
+            break;
+        --last;
+    }
+    return QPair<int, int>(first, last + 1);
 }
 
 /*!
@@ -3376,11 +3004,33 @@ QRasterPaintEnginePrivate::getPenFunc(const QRectF &rect,
 */
 void QRasterPaintEngine::drawStaticTextItem(QStaticTextItem *textItem)
 {
+    if (textItem->numGlyphs == 0)
+        return;
+
     ensurePen();
-    ensureState();
+    ensureRasterState();
+
+    QFontEngine *fontEngine = textItem->fontEngine();
+    if (!supportsTransformations(fontEngine)) {
+        drawCachedGlyphs(textItem->numGlyphs, textItem->glyphs, textItem->glyphPositions,
+                         fontEngine);
+    } else if (state()->matrix.type() < QTransform::TxProject) {
+        bool invertible;
+        QTransform invMat = state()->matrix.inverted(&invertible);
+        if (!invertible)
+            return;
 
-    drawCachedGlyphs(textItem->numGlyphs, textItem->glyphs, textItem->glyphPositions,
-                     textItem->fontEngine());
+        QPair<int, int> range = visibleGlyphRange(invMat.mapRect(clipBoundingRect()),
+                                                  textItem->fontEngine(), textItem->glyphs,
+                                                  textItem->glyphPositions, textItem->numGlyphs);
+        QStaticTextItem copy = *textItem;
+        copy.glyphs += range.first;
+        copy.glyphPositions += range.first;
+        copy.numGlyphs = range.second - range.first;
+        QPaintEngineEx::drawStaticTextItem(&copy);
+    } else {
+        QPaintEngineEx::drawStaticTextItem(textItem);
+    }
 }
 
 /*!
@@ -3389,7 +3039,6 @@ void QRasterPaintEngine::drawStaticTextItem(QStaticTextItem *textItem)
 void QRasterPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textItem)
 {
     const QTextItemInt &ti = static_cast<const QTextItemInt &>(textItem);
-    QRasterPaintEngineState *s = state();
 
 #ifdef QT_DEBUG_DRAW
     Q_D(QRasterPaintEngine);
@@ -3398,141 +3047,51 @@ void QRasterPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textIte
            d->glyphCacheType);
 #endif
 
+    if (ti.glyphs.numGlyphs == 0)
+        return;
     ensurePen();
-    ensureState();
-
-#if defined (Q_WS_WIN) || defined(Q_WS_MAC)
-
-    bool drawCached = true;
-
-    if (s->matrix.type() >= QTransform::TxProject)
-        drawCached = false;
-
-    // don't try to cache huge fonts
-    const qreal pixelSize = ti.fontEngine->fontDef.pixelSize;
-    if (pixelSize * pixelSize * qAbs(s->matrix.determinant()) >= 64 * 64)
-        drawCached = false;
+    ensureRasterState();
 
-    // ### Remove the TestFontEngine and Box engine crap, in these
-    // ### cases we should delegate painting to the font engine
-    // ### directly...
-
-#if defined(Q_WS_WIN) && !defined(Q_WS_WINCE)
-    QFontEngine::Type fontEngineType = ti.fontEngine->type();
-    // qDebug() << "type" << fontEngineType << s->matrix.type();
-    if ((fontEngineType == QFontEngine::Win && !((QFontEngineWin *) ti.fontEngine)->ttf && s->matrix.type() > QTransform::TxTranslate)
-        || (s->matrix.type() <= QTransform::TxTranslate
-            && (fontEngineType == QFontEngine::TestFontEngine
-                || fontEngineType == QFontEngine::Box))) {
-            drawCached = false;
-    }
-#else
-    if (s->matrix.type() > QTransform::TxTranslate)
-        drawCached = false;
-#endif
-    if (drawCached) {
-        QRasterPaintEngineState *s = state();
+    QRasterPaintEngineState *s = state();
+    QTransform matrix = s->matrix;
 
+    if (!supportsTransformations(ti.fontEngine)) {
         QVarLengthArray<QFixedPoint> positions;
         QVarLengthArray<glyph_t> glyphs;
 
-        QTransform matrix = s->matrix;
         matrix.translate(p.x(), p.y());
-
         ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions);
 
         drawCachedGlyphs(glyphs.size(), glyphs.constData(), positions.constData(), ti.fontEngine);
-        return;
-    }
+    } else if (matrix.type() < QTransform::TxProject) {
+        bool invertible;
+        QTransform invMat = matrix.inverted(&invertible);
+        if (!invertible)
+            return;
 
-#elif defined (Q_OS_SYMBIAN) && defined(QT_NO_FREETYPE) // Q_WS_WIN || Q_WS_MAC
-    if (s->matrix.type() <= QTransform::TxTranslate
-        || (s->matrix.type() == QTransform::TxScale
-                && (qFuzzyCompare(s->matrix.m11(), s->matrix.m22())))) {
-        drawGlyphsS60(p, ti);
-        return;
-    }
-#else // Q_WS_WIN || Q_WS_MAC
+        QVarLengthArray<QFixedPoint> positions;
+        QVarLengthArray<glyph_t> glyphs;
 
-    QFontEngine *fontEngine = ti.fontEngine;
+        ti.fontEngine->getGlyphPositions(ti.glyphs, QTransform::fromTranslate(p.x(), p.y()),
+                                         ti.flags, glyphs, positions);
+        QPair<int, int> range = visibleGlyphRange(invMat.mapRect(clipBoundingRect()),
+                                                  ti.fontEngine, glyphs.data(), positions.data(),
+                                                  glyphs.size());
 
-#if defined(Q_WS_QWS)
-    if (fontEngine->type() == QFontEngine::Box) {
-        fontEngine->draw(this, qFloor(p.x()), qFloor(p.y()), ti);
-        return;
-    }
-
-    if (s->matrix.type() < QTransform::TxScale
-        && (fontEngine->type() == QFontEngine::QPF1 || fontEngine->type() == QFontEngine::QPF2
-            || (fontEngine->type() == QFontEngine::Proxy
-                && !(static_cast<QProxyFontEngine *>(fontEngine)->drawAsOutline()))
-            )) {
-        fontEngine->draw(this, qFloor(p.x()), qFloor(p.y()), ti);
-        return;
-    }
-#endif // Q_WS_QWS
-
-#ifdef Q_WS_QPA
-    if (s->matrix.type() < QTransform::TxScale) {
-
-        QVarLengthArray<QFixedPoint> positions;
-        QVarLengthArray<glyph_t> glyphs;
-        QTransform matrix = state()->transform();
-
-        qreal _x = qFloor(p.x());
-        qreal _y = qFloor(p.y());
-        matrix.translate(_x, _y);
-
-        fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions);
-        if (glyphs.size() == 0)
+        if (range.first >= range.second)
             return;
 
-        for(int i = 0; i < glyphs.size(); i++) {
-            QImage img = fontEngine->alphaMapForGlyph(glyphs[i]);
-            glyph_metrics_t metrics = fontEngine->boundingBox(glyphs[i]);
-            alphaPenBlt(img.bits(), img.bytesPerLine(), img.depth(),
-                                         qRound(positions[i].x + metrics.x),
-                                         qRound(positions[i].y + metrics.y),
-                                         img.width(), img.height());
-        }
-        return;
-    }
-#endif //Q_WS_QPA
-
-#if (defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)) && !defined(QT_NO_FREETYPE)
-
-#if defined(Q_WS_QWS) && !defined(QT_NO_QWS_QPF2)
-    if (fontEngine->type() == QFontEngine::QPF2) {
-        QFontEngine *renderingEngine = static_cast<QFontEngineQPF *>(fontEngine)->renderingEngine();
-        if (renderingEngine)
-            fontEngine = renderingEngine;
-    }
-#endif
-
-    if (fontEngine->type() != QFontEngine::Freetype) {
+        QStaticTextItem staticTextItem;
+        staticTextItem.color = s->pen.color();
+        staticTextItem.font = s->font;
+        staticTextItem.setFontEngine(ti.fontEngine);
+        staticTextItem.numGlyphs = range.second - range.first;
+        staticTextItem.glyphs = glyphs.data() + range.first;
+        staticTextItem.glyphPositions = positions.data() + range.first;
+        QPaintEngineEx::drawStaticTextItem(&staticTextItem);
+    } else {
         QPaintEngineEx::drawTextItem(p, ti);
-        return;
     }
-
-    QFontEngineFT *fe = static_cast<QFontEngineFT *>(fontEngine);
-
-    QTransform matrix = s->matrix;
-    matrix.translate(p.x(), p.y());
-
-    QVarLengthArray<QFixedPoint> positions;
-    QVarLengthArray<glyph_t> glyphs;
-    fe->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions);
-    if (glyphs.size() == 0)
-        return;
-
-    if (!drawCachedGlyphs(glyphs.size(), glyphs.constData(), positions.constData(), fontEngine))
-        QPaintEngine::drawTextItem(p, ti);
-
-    return;
-#endif
-#endif
-
-    QPaintEngineEx::drawTextItem(p, ti);
 }
 
 /*!
@@ -3544,48 +3103,17 @@ void QRasterPaintEngine::drawPoints(const QPointF *points, int pointCount)
     QRasterPaintEngineState *s = state();
 
     ensurePen();
-    qreal pw = s->lastPen.widthF();
-    if (!s->flags.fast_pen && (s->matrix.type() > QTransform::TxTranslate || pw > 1)) {
-        QPaintEngineEx::drawPoints(points, pointCount);
-
-    } else {
-        if (!s->penData.blend)
-            return;
-
-        QVarLengthArray<QT_FT_Span, 4096> array(pointCount);
-        QT_FT_Span span = { 0, 1, 0, 255 };
-        const QPointF *end = points + pointCount;
-        qreal trans_x, trans_y;
-        int x, y;
-        int left = d->deviceRect.x();
-        int right = left + d->deviceRect.width();
-        int top = d->deviceRect.y();
-        int bottom = top + d->deviceRect.height();
-        int count = 0;
-        while (points < end) {
-            s->matrix.map(points->x(), points->y(), &trans_x, &trans_y);
-            x = qFloor(trans_x);
-            y = qFloor(trans_y);
-            if (x >= left && x < right && y >= top && y < bottom) {
-                if (count > 0) {
-                    const QT_FT_Span &last = array[count - 1];
-                    // spans must be sorted on y (primary) and x (secondary)
-                    if (y < last.y || (y == last.y && x < last.x)) {
-                        s->penData.blend(count, array.constData(), &s->penData);
-                        count = 0;
-                    }
-                }
-
-                span.x = x;
-                span.y = y;
-                array[count++] = span;
-            }
-            ++points;
-        }
+    if (!s->penData.blend)
+        return;
 
-        if (count > 0)
-            s->penData.blend(count, array.constData(), &s->penData);
+    if (!s->flags.fast_pen) {
+        QPaintEngineEx::drawPoints(points, pointCount);
+        return;
     }
+
+    QCosmeticStroker stroker(s, d->deviceRect);
+    stroker.setLegacyRoundingEnabled(s->flags.legacy_rounding);
+    stroker.drawPoints(points, pointCount);
 }
 
 
@@ -3595,48 +3123,17 @@ void QRasterPaintEngine::drawPoints(const QPoint *points, int pointCount)
     QRasterPaintEngineState *s = state();
 
     ensurePen();
-    double pw = s->lastPen.widthF();
-    if (!s->flags.fast_pen && (s->matrix.type() > QTransform::TxTranslate || pw > 1)) {
-        QPaintEngineEx::drawPoints(points, pointCount);
-
-    } else {
-        if (!s->penData.blend)
-            return;
-
-        QVarLengthArray<QT_FT_Span, 4096> array(pointCount);
-        QT_FT_Span span = { 0, 1, 0, 255 };
-        const QPoint *end = points + pointCount;
-        qreal trans_x, trans_y;
-        int x, y;
-        int left = d->deviceRect.x();
-        int right = left + d->deviceRect.width();
-        int top = d->deviceRect.y();
-        int bottom = top + d->deviceRect.height();
-        int count = 0;
-        while (points < end) {
-            s->matrix.map(points->x(), points->y(), &trans_x, &trans_y);
-            x = qFloor(trans_x);
-            y = qFloor(trans_y);
-            if (x >= left && x < right && y >= top && y < bottom) {
-                if (count > 0) {
-                    const QT_FT_Span &last = array[count - 1];
-                    // spans must be sorted on y (primary) and x (secondary)
-                    if (y < last.y || (y == last.y && x < last.x)) {
-                        s->penData.blend(count, array.constData(), &s->penData);
-                        count = 0;
-                    }
-                }
-
-                span.x = x;
-                span.y = y;
-                array[count++] = span;
-            }
-            ++points;
-        }
+    if (!s->penData.blend)
+        return;
 
-        if (count > 0)
-            s->penData.blend(count, array.constData(), &s->penData);
+    if (!s->flags.fast_pen) {
+        QPaintEngineEx::drawPoints(points, pointCount);
+        return;
     }
+
+    QCosmeticStroker stroker(s, d->deviceRect);
+    stroker.setLegacyRoundingEnabled(s->flags.legacy_rounding);
+    stroker.drawPoints(points, pointCount);
 }
 
 /*!
@@ -3645,59 +3142,23 @@ void QRasterPaintEngine::drawPoints(const QPoint *points, int pointCount)
 void QRasterPaintEngine::drawLines(const QLine *lines, int lineCount)
 {
 #ifdef QT_DEBUG_DRAW
-    qDebug() << " - QRasterPaintEngine::drawLine()";
+    qDebug() << " - QRasterPaintEngine::drawLines(QLine*)" << lineCount;
 #endif
     Q_D(QRasterPaintEngine);
     QRasterPaintEngineState *s = state();
 
     ensurePen();
+    if (!s->penData.blend)
+        return;
+
     if (s->flags.fast_pen) {
-        QIntRect bounds; bounds.set(d->deviceRect);
-        LineDrawMode mode = s->lastPen.capStyle() == Qt::FlatCap
-                            ? LineDrawNormal
-                            : LineDrawIncludeLastPixel;
-
-        int m11 = int(s->matrix.m11());
-        int m22 = int(s->matrix.m22());
-        int dx = qFloor(s->matrix.dx());
-        int dy = qFloor(s->matrix.dy());
+        QCosmeticStroker stroker(s, d->deviceRect);
+        stroker.setLegacyRoundingEnabled(s->flags.legacy_rounding);
         for (int i=0; i<lineCount; ++i) {
-            int dashOffset = int(s->lastPen.dashOffset());
-            if (s->flags.int_xform) {
-                const QLine &l = lines[i];
-                int x1 = l.x1() * m11 + dx;
-                int y1 = l.y1() * m22 + dy;
-                int x2 = l.x2() * m11 + dx;
-                int y2 = l.y2() * m22 + dy;
-
-                const QRect brect(QPoint(x1, y1), QPoint(x2, y2));
-                ProcessSpans penBlend = d->getPenFunc(brect, &s->penData);
-                if (qpen_style(s->lastPen) == Qt::SolidLine)
-                    drawLine_midpoint_i(x1, y1, x2, y2,
-                                        penBlend, &s->penData, mode, bounds);
-                else
-                    drawLine_midpoint_dashed_i(x1, y1, x2, y2,
-                                               &s->lastPen, penBlend,
-                                               &s->penData, mode, bounds,
-                                               &dashOffset);
-            } else {
-                QLineF line = lines[i] * s->matrix;
-                const QRectF brect(QPointF(line.x1(), line.y1()),
-                                   QPointF(line.x2(), line.y2()));
-                ProcessSpans penBlend = d->getPenFunc(brect, &s->penData);
-                if (qpen_style(s->lastPen) == Qt::SolidLine)
-                    drawLine_midpoint_i(int(line.x1()), int(line.y1()),
-                                        int(line.x2()), int(line.y2()),
-                                        penBlend, &s->penData, mode, bounds);
-                else
-                    drawLine_midpoint_dashed_i(int(line.x1()), int(line.y1()),
-                                               int(line.x2()), int(line.y2()),
-                                               &s->lastPen, penBlend,
-                                               &s->penData, mode, bounds,
-                                               &dashOffset);
-            }
+            const QLine &l = lines[i];
+            stroker.drawLine(l.p1(), l.p2());
         }
-    } else if (s->penData.blend) {
+    } else {
         QPaintEngineEx::drawLines(lines, lineCount);
     }
 }
@@ -3754,7 +3215,7 @@ void QRasterPaintEnginePrivate::rasterizeLine_dashed(QLineF line,
 void QRasterPaintEngine::drawLines(const QLineF *lines, int lineCount)
 {
 #ifdef QT_DEBUG_DRAW
-    qDebug() << " - QRasterPaintEngine::drawLine()";
+    qDebug() << " - QRasterPaintEngine::drawLines(QLineF *)" << lineCount;
 #endif
     Q_D(QRasterPaintEngine);
     QRasterPaintEngineState *s = state();
@@ -3763,28 +3224,11 @@ void QRasterPaintEngine::drawLines(const QLineF *lines, int lineCount)
     if (!s->penData.blend)
         return;
     if (s->flags.fast_pen) {
-        QIntRect bounds;
-        bounds.set(d->deviceRect);
-        LineDrawMode mode = s->lastPen.capStyle() == Qt::FlatCap
-                            ? LineDrawNormal
-                            : LineDrawIncludeLastPixel;
-
+        QCosmeticStroker stroker(s, d->deviceRect);
+        stroker.setLegacyRoundingEnabled(s->flags.legacy_rounding);
         for (int i=0; i<lineCount; ++i) {
-            int dashOffset = int(s->lastPen.dashOffset());
-            QLineF line = lines[i] * s->matrix;
-            const QRectF brect(QPointF(line.x1(), line.y1()),
-                               QPointF(line.x2(), line.y2()));
-            ProcessSpans penBlend = d->getPenFunc(brect, &s->penData);
-            if (qpen_style(s->lastPen) == Qt::SolidLine)
-                drawLine_midpoint_i(int(line.x1()), int(line.y1()),
-                                    int(line.x2()), int(line.y2()),
-                                    penBlend, &s->penData, mode, bounds);
-            else
-                drawLine_midpoint_dashed_i(int(line.x1()), int(line.y1()),
-                                           int(line.x2()), int(line.y2()),
-                                           &s->lastPen,
-                                           penBlend, &s->penData, mode,
-                                           bounds, &dashOffset);
+            QLineF line = lines[i];
+            stroker.drawLine(line.p1(), line.p2());
         }
     } else {
         QPaintEngineEx::drawLines(lines, lineCount);
@@ -3802,7 +3246,8 @@ void QRasterPaintEngine::drawEllipse(const QRectF &rect)
 
     ensurePen();
     if (((qpen_style(s->lastPen) == Qt::SolidLine && s->flags.fast_pen)
-         || (qpen_style(s->lastPen) == Qt::NoPen && !s->flags.antialiased))
+           || (qpen_style(s->lastPen) == Qt::NoPen))
+        && !s->flags.antialiased
         && qMax(rect.width(), rect.height()) < QT_RASTER_COORD_LIMIT
         && !rect.isEmpty()
         && s->matrix.type() <= QTransform::TxScale) // no shear
@@ -3823,27 +3268,8 @@ void QRasterPaintEngine::drawEllipse(const QRectF &rect)
     QPaintEngineEx::drawEllipse(rect);
 }
 
-/*!
-    \internal
-*/
-#ifdef Q_WS_MAC
-void QRasterPaintEngine::setCGContext(CGContextRef ctx)
-{
-    Q_D(QRasterPaintEngine);
-    d->cgContext = ctx;
-}
-
-/*!
-    \internal
-*/
-CGContextRef QRasterPaintEngine::getCGContext() const
-{
-    Q_D(const QRasterPaintEngine);
-    return d->cgContext;
-}
-#endif
 
-#ifdef Q_WS_WIN
+#ifdef Q_OS_WIN
 /*!
     \internal
 */
@@ -3873,63 +3299,30 @@ void QRasterPaintEngine::releaseDC(HDC) const
 /*!
     \internal
 */
-QPoint QRasterPaintEngine::coordinateOffset() const
+bool QRasterPaintEngine::supportsTransformations(QFontEngine *fontEngine) const
 {
-    return QPoint(0, 0);
+    const QTransform &m = state()->matrix;
+    return supportsTransformations(fontEngine, m);
 }
 
 /*!
-    Draws the given color \a spans with the specified \a color. The \a
-    count parameter specifies the number of spans.
-
-    The default implementation does nothing; reimplement this function
-    to draw the given color \a spans with the specified \a color. Note
-    that this function \e must be reimplemented if the framebuffer is
-    not memory-mapped.
-
-    \sa drawBufferSpan()
+    \internal
 */
-#if defined(Q_WS_QWS) && !defined(QT_NO_RASTERCALLBACKS)
-void QRasterPaintEngine::drawColorSpans(const QSpan *spans, int count, uint color)
+bool QRasterPaintEngine::supportsTransformations(QFontEngine *fontEngine, const QTransform &m) const
 {
-    Q_UNUSED(spans);
-    Q_UNUSED(count);
-    Q_UNUSED(color);
-    qFatal("QRasterPaintEngine::drawColorSpans must be reimplemented on "
-           "a non memory-mapped device");
+    if (fontEngine->supportsTransformations(m))
+        return true;
+
+    return !shouldDrawCachedGlyphs(fontEngine, m);
 }
 
 /*!
-    \fn void QRasterPaintEngine::drawBufferSpan(const uint *buffer, int size, int x, int y, int length, uint alpha)
-
-    Draws the given \a buffer.
-
-    The default implementation does nothing; reimplement this function
-    to draw a buffer that contains more than one color. Note that this
-    function \e must be reimplemented if the framebuffer is not
-    memory-mapped.
-
-    The \a size parameter specifies the total size of the given \a
-    buffer, while the \a length parameter specifies the number of
-    pixels to draw. The buffer's position is given by (\a x, \a
-    y). The provided \a alpha value is added to each pixel in the
-    buffer when drawing.
-
-    \sa drawColorSpans()
+    \internal
 */
-void QRasterPaintEngine::drawBufferSpan(const uint *buffer, int bufsize,
-                                        int x, int y, int length, uint const_alpha)
+QPoint QRasterPaintEngine::coordinateOffset() const
 {
-    Q_UNUSED(buffer);
-    Q_UNUSED(bufsize);
-    Q_UNUSED(x);
-    Q_UNUSED(y);
-    Q_UNUSED(length);
-    Q_UNUSED(const_alpha);
-    qFatal("QRasterPaintEngine::drawBufferSpan must be reimplemented on "
-           "a non memory-mapped device");
+    return QPoint(0, 0);
 }
-#endif // Q_WS_QWS
 
 void QRasterPaintEngine::drawBitmap(const QPointF &pos, const QImage &image, QSpanData *fg)
 {
@@ -3970,7 +3363,7 @@ void QRasterPaintEngine::drawBitmap(const QPointF &pos, const QImage &image, QSp
                     spans[n].y = y;
                     spans[n].coverage = 255;
                     int len = 1;
-                    while (src_x < w-1 && src[(src_x+1) >> 3] & (0x1 << ((src_x+1) & 7))) {
+                    while (src_x+1 < w && src[(src_x+1) >> 3] & (0x1 << ((src_x+1) & 7))) {
                         ++src_x;
                         ++len;
                     }
@@ -3996,7 +3389,7 @@ void QRasterPaintEngine::drawBitmap(const QPointF &pos, const QImage &image, QSp
                     spans[n].y = y;
                     spans[n].coverage = 255;
                     int len = 1;
-                    while (src_x < w-1 && src[(src_x+1) >> 3] & (0x80 >> ((src_x+1) & 7))) {
+                    while (src_x+1 < w && src[(src_x+1) >> 3] & (0x80 >> ((src_x+1) & 7))) {
                         ++src_x;
                         ++len;
                     }
@@ -4059,82 +3452,13 @@ QRect QRasterPaintEngine::clipBoundingRect() const
     return QRect(clip->xmin, clip->ymin, clip->xmax - clip->xmin, clip->ymax - clip->ymin);
 }
 
-static void qt_merge_clip(const QClipData *c1, const QClipData *c2, QClipData *result)
-{
-    Q_ASSERT(c1->clipSpanHeight == c2->clipSpanHeight && c1->clipSpanHeight == result->clipSpanHeight);
-
-    QVarLengthArray<short, 4096> buffer;
-
-    QClipData::ClipLine *c1ClipLines = const_cast<QClipData *>(c1)->clipLines();
-    QClipData::ClipLine *c2ClipLines = const_cast<QClipData *>(c2)->clipLines();
-    result->initialize();
-
-    for (int y = 0; y < c1->clipSpanHeight; ++y) {
-        const QSpan *c1_spans = c1ClipLines[y].spans;
-        int c1_count = c1ClipLines[y].count;
-        const QSpan *c2_spans = c2ClipLines[y].spans;
-        int c2_count = c2ClipLines[y].count;
-
-        if (c1_count == 0 && c2_count == 0)
-            continue;
-        if (c1_count == 0) {
-            result->appendSpans(c2_spans, c2_count);
-            continue;
-        } else if (c2_count == 0) {
-            result->appendSpans(c1_spans, c1_count);
-            continue;
-        }
-
-        // we need to merge the two
-
-        // find required length
-        int max = qMax(c1_spans[c1_count - 1].x + c1_spans[c1_count - 1].len,
-                c2_spans[c2_count - 1].x + c2_spans[c2_count - 1].len);
-        buffer.resize(max);
-        memset(buffer.data(), 0, buffer.size() * sizeof(short));
-
-        // Fill with old spans.
-        for (int i = 0; i < c1_count; ++i) {
-            const QSpan *cs = c1_spans + i;
-            for (int j=cs->x; j<cs->x + cs->len; ++j)
-                buffer[j] = cs->coverage;
-        }
-
-        // Fill with new spans
-        for (int i = 0; i < c2_count; ++i) {
-            const QSpan *cs = c2_spans + i;
-            for (int j = cs->x; j < cs->x + cs->len; ++j) {
-                buffer[j] += cs->coverage;
-                if (buffer[j] > 255)
-                    buffer[j] = 255;
-            }
-        }
-
-        int x = 0;
-        while (x<max) {
-
-            // Skip to next span
-            while (x < max && buffer[x] == 0) ++x;
-            if (x >= max) break;
-
-            int sx = x;
-            int coverage = buffer[x];
-
-            // Find length of span
-            while (x < max && buffer[x] == coverage)
-                ++x;
-
-            result->appendSpan(sx, x - sx, y, coverage);
-        }
-    }
-}
-
 void QRasterPaintEnginePrivate::initializeRasterizer(QSpanData *data)
 {
     Q_Q(QRasterPaintEngine);
     QRasterPaintEngineState *s = q->state();
 
     rasterizer->setAntialiased(s->flags.antialiased);
+    rasterizer->setLegacyRoundingEnabled(s->flags.legacy_rounding);
 
     QRect clipRect(deviceRect);
     ProcessSpans blend;
@@ -4182,6 +3506,11 @@ extern "C" {
     int q_gray_rendered_spans(QT_FT_Raster raster);
 }
 
+static inline uchar *alignAddress(uchar *address, quintptr alignmentMask)
+{
+    return (uchar *)(((quintptr)address + alignmentMask) & ~alignmentMask);
+}
+
 void QRasterPaintEnginePrivate::rasterize(QT_FT_Outline *outline,
                                           ProcessSpans callback,
                                           void *userData, QRasterBuffer *)
@@ -4194,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);
 
@@ -4209,19 +3539,10 @@ void QRasterPaintEnginePrivate::rasterize(QT_FT_Outline *outline,
     // minimize memory reallocations. However if initial size for
     // raster pool is changed for lower value, reallocations will
     // occur normally.
-    const int rasterPoolInitialSize = MINIMUM_POOL_SIZE;
-    int rasterPoolSize = rasterPoolInitialSize;
-    unsigned char *rasterPoolBase;
-#if defined(Q_WS_WIN64)
-    rasterPoolBase =
-        // We make use of setjmp and longjmp in qgrayraster.c which requires
-        // 16-byte alignment, hence we hardcode this requirement here..
-        (unsigned char *) _aligned_malloc(rasterPoolSize, sizeof(void*) * 2);
-#else
-    unsigned char rasterPoolOnStack[rasterPoolInitialSize];
-    rasterPoolBase = rasterPoolOnStack;
-#endif
-    Q_CHECK_PTR(rasterPoolBase);
+    int rasterPoolSize = MINIMUM_POOL_SIZE;
+    uchar rasterPoolOnStack[MINIMUM_POOL_SIZE + 0xf];
+    uchar *rasterPoolBase = alignAddress(rasterPoolOnStack, 0xf);
+    uchar *rasterPoolOnHeap = 0;
 
     qt_ft_grays_raster.raster_reset(*grayRaster.data(), rasterPoolBase, rasterPoolSize);
 
@@ -4257,31 +3578,20 @@ void QRasterPaintEnginePrivate::rasterize(QT_FT_Outline *outline,
 
         // Out of memory, reallocate some more and try again...
         if (error == -6) { // ErrRaster_OutOfMemory from qgrayraster.c
-            int new_size = rasterPoolSize * 2;
-            if (new_size > 1024 * 1024) {
+            rasterPoolSize *= 2;
+            if (rasterPoolSize > 1024 * 1024) {
                 qWarning("QPainter: Rasterization of primitive failed");
                 break;
             }
 
             rendered_spans += q_gray_rendered_spans(*grayRaster.data());
 
-#if defined(Q_WS_WIN64)
-            _aligned_free(rasterPoolBase);
-#else
-            if (rasterPoolBase != rasterPoolOnStack) // initially on the stack
-                free(rasterPoolBase);
-#endif
+            free(rasterPoolOnHeap);
+            rasterPoolOnHeap = (uchar *)malloc(rasterPoolSize + 0xf);
 
-            rasterPoolSize = new_size;
-            rasterPoolBase =
-#if defined(Q_WS_WIN64)
-                // We make use of setjmp and longjmp in qgrayraster.c which requires
-                // 16-byte alignment, hence we hardcode this requirement here..
-                (unsigned char *) _aligned_malloc(rasterPoolSize, sizeof(void*) * 2);
-#else
-                (unsigned char *) malloc(rasterPoolSize);
-#endif
-            Q_CHECK_PTR(rasterPoolBase); // note: we just freed the old rasterPoolBase. I hope it's not fatal.
+            Q_CHECK_PTR(rasterPoolOnHeap); // note: we just freed the old rasterPoolBase. I hope it's not fatal.
+
+            rasterPoolBase = alignAddress(rasterPoolOnHeap, 0xf);
 
             qt_ft_grays_raster.raster_done(*grayRaster.data());
             qt_ft_grays_raster.raster_new(grayRaster.data());
@@ -4291,12 +3601,7 @@ void QRasterPaintEnginePrivate::rasterize(QT_FT_Outline *outline,
         }
     }
 
-#if defined(Q_WS_WIN64)
-    _aligned_free(rasterPoolBase);
-#else
-    if (rasterPoolBase != rasterPoolOnStack) // initially on the stack
-        free(rasterPoolBase);
-#endif
+    free(rasterPoolOnHeap);
 }
 
 void QRasterPaintEnginePrivate::recalculateFastImages()
@@ -4378,127 +3683,6 @@ void QRasterBuffer::resetBuffer(int val)
     memset(m_buffer, val, m_height*bytes_per_line);
 }
 
-
-#if defined(Q_WS_QWS)
-void QRasterBuffer::prepare(QCustomRasterPaintDevice *device)
-{
-    m_buffer = reinterpret_cast<uchar*>(device->memory());
-    m_width = qMin(QT_RASTER_COORD_LIMIT, device->width());
-    m_height = qMin(QT_RASTER_COORD_LIMIT, device->height());
-    bytes_per_pixel = device->depth() / 8;
-    bytes_per_line = device->bytesPerLine();
-    format = device->format();
-#ifndef QT_NO_RASTERCALLBACKS
-    if (!m_buffer)
-        drawHelper = qDrawHelperCallback + format;
-    else
-#endif
-        drawHelper = qDrawHelper + format;
-}
-
-int QCustomRasterPaintDevice::metric(PaintDeviceMetric m) const
-{
-    switch (m) {
-    case PdmWidth:
-        return widget->frameGeometry().width();
-    case PdmHeight:
-        return widget->frameGeometry().height();
-    default:
-        break;
-    }
-
-    return qt_paint_device_metric(widget, m);
-}
-
-int QCustomRasterPaintDevice::bytesPerLine() const
-{
-    return (width() * depth() + 7) / 8;
-}
-
-#elif defined(Q_OS_SYMBIAN)
-
-void QRasterBuffer::prepareBuffer(int /* width */, int /* height */)
-{
-}
-
-#endif // Q_OS_SYMBIAN
-
-/*!
-    \class QCustomRasterPaintDevice
-    \preliminary
-    \ingroup qws
-    \since 4.2
-
-    \brief The QCustomRasterPaintDevice class is provided to activate
-    hardware accelerated paint engines in Qt for Embedded Linux.
-
-    Note that this class is only available in \l{Qt for Embedded Linux}.
-
-    In \l{Qt for Embedded Linux}, painting is a pure software
-    implementation. But starting with Qt 4.2, it is
-    possible to add an accelerated graphics driver to take advantage
-    of available hardware resources.
-
-    Hardware acceleration is accomplished by creating a custom screen
-    driver, accelerating the copying from memory to the screen, and
-    implementing a custom paint engine accelerating the various
-    painting operations. Then a custom paint device (derived from the
-    QCustomRasterPaintDevice class) and a custom window surface
-    (derived from QWSWindowSurface) must be implemented to make
-    \l{Qt for Embedded Linux} aware of the accelerated driver.
-
-    See the \l {Adding an Accelerated Graphics Driver to Qt for Embedded Linux}
-    documentation for details.
-
-    \sa QRasterPaintEngine, QPaintDevice
-*/
-
-/*!
-    \fn QCustomRasterPaintDevice::QCustomRasterPaintDevice(QWidget *widget)
-
-    Constructs a custom raster based paint device for the given
-    top-level \a widget.
-*/
-
-/*!
-    \fn int QCustomRasterPaintDevice::bytesPerLine() const
-
-    Returns the number of bytes per line in the framebuffer. Note that
-    this number might be larger than the framebuffer width.
-*/
-
-/*!
-    \fn int QCustomRasterPaintDevice::devType() const
-    \internal
-*/
-
-/*!
-    \fn QImage::Format QCustomRasterPaintDevice::format() const
-
-    Returns the format of the device's memory buffet.
-
-    The default format is QImage::Format_ARGB32_Premultiplied. The
-    only other valid format is QImage::Format_RGB16.
-*/
-
-/*!
-    \fn void * QCustomRasterPaintDevice::memory () const
-
-    Returns a pointer to the paint device's memory buffer, or 0 if no
-    such buffer exists.
-*/
-
-/*!
-    \fn int QCustomRasterPaintDevice::metric ( PaintDeviceMetric m ) const
-    \reimp
-*/
-
-/*!
-    \fn QSize QCustomRasterPaintDevice::size () const
-    \internal
-*/
-
-
 QClipData::QClipData(int height)
 {
     clipSpanHeight = height;
@@ -4821,7 +4005,7 @@ static void qt_span_fill_clipped(int spanCount, const QSpan *spans, void *userDa
     while (spans < end) {
         QSpan *clipped = cspans;
         spans = qt_intersect_spans(fillData->clip, &currentClip, spans, end, &clipped, NSPANS);
-//         qDebug() << "processed " << processed << "clipped" << clipped-cspans
+//         qDebug() << "processed " << spanCount - (end - spans) << "clipped" << clipped-cspans
 //                  << "span:" << cspans->x << cspans->y << cspans->len << spans->coverage;
 
         if (clipped - cspans)
@@ -4915,7 +4099,6 @@ static void qt_span_clip(int count, const QSpan *spans, void *userData)
         }
         break;
 
-    case Qt::UniteClip:
     case Qt::ReplaceClip:
         clipData->newClip->appendSpans(spans, count);
         break;
@@ -5223,9 +4406,6 @@ Q_GLOBAL_STATIC(QGradientCache, qt_gradient_cache)
 void QSpanData::init(QRasterBuffer *rb, const QRasterPaintEngine *pe)
 {
     rasterBuffer = rb;
-#ifdef Q_WS_QWS
-    rasterEngine = const_cast<QRasterPaintEngine *>(pe);
-#endif
     type = None;
     txop = 0;
     bilinear = false;
@@ -5371,16 +4551,7 @@ void QSpanData::adjustSpanMethods()
         unclipped_blend = rasterBuffer->drawHelper->blendGradient;
         break;
     case Texture:
-#ifdef Q_WS_QWS
-#ifndef QT_NO_RASTERCALLBACKS
-        if (!rasterBuffer->buffer())
-            unclipped_blend = qBlendTextureCallback;
-        else
-#endif
-            unclipped_blend = qBlendTexture;
-#else
         unclipped_blend = qBlendTexture;
-#endif
         if (!texture.imageData)
             unclipped_blend = 0;
 
@@ -5417,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
@@ -5427,8 +4598,6 @@ void QSpanData::setupMatrix(const QTransform &matrix, int bilin)
     adjustSpanMethods();
 }
 
-extern const QVector<QRgb> *qt_image_colortable(const QImage &image);
-
 void QSpanData::initTexture(const QImage *image, int alpha, QTextureData::Type _type, const QRect &sourceRect)
 {
     const QImageData *d = const_cast<QImage *>(image)->data_ptr();
@@ -5473,759 +4642,6 @@ void QSpanData::initTexture(const QImage *image, int alpha, QTextureData::Type _
     adjustSpanMethods();
 }
 
-#ifdef Q_WS_WIN
-
-
-#endif
-
-
-/*!
-    \internal
-
-    Draws a line using the floating point midpoint algorithm. The line
-    \a line is already in device coords at this point.
-*/
-
-static void drawLine_midpoint_i(int x1, int y1, int x2, int y2, ProcessSpans span_func, QSpanData *data,
-                                LineDrawMode style, const QIntRect &devRect)
-{
-#ifdef QT_DEBUG_DRAW
-    qDebug() << "   - drawLine_midpoint_i" << QLine(QPoint(x1, y1), QPoint(x2, y2));
-#endif
-
-    int x, y;
-    int dx, dy, d, incrE, incrNE;
-
-    dx = x2 - x1;
-    dy = y2 - y1;
-
-    const int NSPANS = 256;
-    QT_FT_Span spans[NSPANS];
-    int current = 0;
-    bool ordered = true;
-
-    if (dy == 0) {
-        // specialcase horizontal lines
-        if (y1 >= devRect.y1 && y1 < devRect.y2) {
-            int start = qMax(devRect.x1, qMin(x1, x2));
-            int stop = qMax(x1, x2) + 1;
-            int stop_clipped = qMin(devRect.x2, stop);
-            int len = stop_clipped - start;
-            if (style == LineDrawNormal && stop == stop_clipped)
-                len--;
-            if (len > 0) {
-                spans[0].x = ushort(start);
-                spans[0].len = ushort(len);
-                spans[0].y = y1;
-                spans[0].coverage = 255;
-                span_func(1, spans, data);
-            }
-        }
-        return;
-    } else if (dx == 0) {
-        // specialcase vertical lines
-        if (x1 >= devRect.x1 && x1 < devRect.x2) {
-            int start = qMax(devRect.y1, qMin(y1, y2));
-            int stop = qMax(y1, y2) + 1;
-            int stop_clipped = qMin(devRect.y2, stop);
-            int len = stop_clipped - start;
-            if (style == LineDrawNormal && stop == stop_clipped)
-                len--;
-            // hw: create spans directly instead to possibly avoid clipping
-            if (len > 0)
-                fillRect_normalized(QRect(x1, start, 1, len).normalized(), data, 0);
-        }
-        return;
-    }
-
-
-    if (qAbs(dx) >= qAbs(dy)) {       /* if x is the major axis: */
-
-        if (x2 < x1) {  /* if coordinates are out of order */
-            qt_swap_int(x1, x2);
-            dx = -dx;
-
-            qt_swap_int(y1, y2);
-            dy = -dy;
-        }
-
-        int x_lower_limit = - 128;
-        if (x1 < x_lower_limit) {
-            int cy = dy * (x_lower_limit - x1) / dx + y1;
-            drawLine_midpoint_i(x_lower_limit, cy, x2, y2, span_func, data, style, devRect);
-            return;
-        }
-
-        if (style == LineDrawNormal)
-            --x2;
-
-        // In the loops below we increment before call the span function so
-        // we need to stop one pixel before
-        x2 = qMin(x2, devRect.x2 - 1);
-
-        // completely clipped, so abort
-        if (x2 <= x1) {
-            return;
-        }
-
-        int x = x1;
-        int y = y1;
-
-        if (y2 <= y1)
-            ordered = false;
-
-        {
-            const int index = (ordered ? current : NSPANS - 1 - current);
-            spans[index].coverage = 255;
-            spans[index].x = x;
-            spans[index].y = y;
-
-            if (x >= devRect.x1 && y >= devRect.y1 && y < devRect.y2)
-                spans[index].len = 1;
-            else
-                spans[index].len = 0;
-        }
-
-        if (y2 > y1) { // 315 -> 360 and 135 -> 180 (unit circle degrees)
-            y2 = qMin(y2, devRect.y2 - 1);
-
-            incrE = dy * 2;
-            d = incrE - dx;
-            incrNE = (dy - dx) * 2;
-
-            if (y > y2)
-                goto flush_and_return;
-
-            while (x < x2) {
-                ++x;
-                if (d > 0) {
-                    if (spans[current].len > 0)
-                        ++current;
-                    if (current == NSPANS) {
-                        span_func(NSPANS, spans, data);
-                        current = 0;
-                    }
-
-                    ++y;
-                    d += incrNE;
-                    if (y > y2)
-                        goto flush_and_return;
-
-                    spans[current].len = 0;
-                    spans[current].coverage = 255;
-                    spans[current].x = x;
-                    spans[current].y = y;
-                } else {
-                    d += incrE;
-                    if (x == devRect.x1)
-                        spans[current].x = devRect.x1;
-                }
-
-                if (x < devRect.x1 || y < devRect.y1)
-                    continue;
-
-                Q_ASSERT(x<devRect.x2);
-                Q_ASSERT(y<devRect.y2);
-                Q_ASSERT(spans[current].y == y);
-                spans[current].len++;
-            }
-            if (spans[current].len > 0) {
-                ++current;
-            }
-        } else {  // 0-45 and 180->225 (unit circle degrees)
-
-            y1 = qMin(y1, devRect.y2 - 1);
-
-            incrE = dy * 2;
-            d = incrE + dx;
-            incrNE = (dy + dx) * 2;
-
-            if (y < devRect.y1)
-                goto flush_and_return;
-
-            while (x < x2) {
-                ++x;
-                if (d < 0) {
-                    if (spans[NSPANS - 1 - current].len > 0)
-                        ++current;
-                    if (current == NSPANS) {
-                        span_func(NSPANS, spans, data);
-                        current = 0;
-                    }
-
-                    --y;
-                    d += incrNE;
-                    if (y < devRect.y1)
-                        goto flush_and_return;
-
-                    const int index = NSPANS - 1 - current;
-                    spans[index].len = 0;
-                    spans[index].coverage = 255;
-                    spans[index].x = x;
-                    spans[index].y = y;
-                } else {
-                    d += incrE;
-                    if (x == devRect.x1)
-                        spans[NSPANS - 1 - current].x = devRect.x1;
-                }
-
-                if (x < devRect.x1 || y > y1)
-                    continue;
-
-                Q_ASSERT(x<devRect.x2 && y<devRect.y2);
-                Q_ASSERT(spans[NSPANS - 1 - current].y == y);
-                spans[NSPANS - 1 - current].len++;
-            }
-            if (spans[NSPANS - 1 - current].len > 0) {
-                ++current;
-            }
-        }
-
-    } else {
-
-        // if y is the major axis:
-
-        if (y2 < y1) {      /* if coordinates are out of order */
-            qt_swap_int(y1, y2);
-            dy = -dy;
-
-            qt_swap_int(x1, x2);
-            dx = -dx;
-        }
-
-        int y_lower_limit = - 128;
-        if (y1 < y_lower_limit) {
-            int cx = dx * (y_lower_limit - y1) / dy + x1;
-            drawLine_midpoint_i(cx, y_lower_limit, x2, y2, span_func, data, style, devRect);
-            return;
-        }
-
-        if (style == LineDrawNormal)
-            --y2;
-
-        // In the loops below we increment before call the span function so
-        // we need to stop one pixel before
-        y2 = qMin(y2, devRect.y2 - 1);
-
-        // completely clipped, so abort
-        if (y2 <= y1) {
-            return;
-        }
-
-        x = x1;
-        y = y1;
-
-        if (x>=devRect.x1 && y>=devRect.y1 && x < devRect.x2) {
-            Q_ASSERT(x >= devRect.x1 && y >= devRect.y1 && x < devRect.x2 && y < devRect.y2);
-            if (current == NSPANS) {
-                span_func(NSPANS, spans, data);
-                current = 0;
-            }
-            spans[current].len = 1;
-            spans[current].coverage = 255;
-            spans[current].x = x;
-            spans[current].y = y;
-            ++current;
-        }
-
-        if (x2 > x1) { // 90 -> 135 and 270 -> 315 (unit circle degrees)
-            x2 = qMin(x2, devRect.x2 - 1);
-            incrE = dx * 2;
-            d = incrE - dy;
-            incrNE = (dx - dy) * 2;
-
-            if (x > x2)
-                goto flush_and_return;
-
-            while (y < y2) {
-                if (d > 0) {
-                    ++x;
-                    d += incrNE;
-                    if (x > x2)
-                        goto flush_and_return;
-                } else {
-                    d += incrE;
-                }
-                ++y;
-                if (x < devRect.x1 || y < devRect.y1)
-                    continue;
-                Q_ASSERT(x<devRect.x2 && y<devRect.y2);
-                if (current == NSPANS) {
-                    span_func(NSPANS, spans, data);
-                    current = 0;
-                }
-                spans[current].len = 1;
-                spans[current].coverage = 255;
-                spans[current].x = x;
-                spans[current].y = y;
-                ++current;
-            }
-        } else { // 45 -> 90 and 225 -> 270 (unit circle degrees)
-            x1 = qMin(x1, devRect.x2 - 1);
-            incrE = dx * 2;
-            d = incrE + dy;
-            incrNE = (dx + dy) * 2;
-
-            if (x < devRect.x1)
-                goto flush_and_return;
-
-            while (y < y2) {
-                if (d < 0) {
-                    --x;
-                    d += incrNE;
-                    if (x < devRect.x1)
-                        goto flush_and_return;
-                } else {
-                    d += incrE;
-                }
-                ++y;
-                if (y < devRect.y1 || x > x1)
-                    continue;
-                Q_ASSERT(x>=devRect.x1 && x<devRect.x2 && y>=devRect.y1 && y<devRect.y2);
-                if (current == NSPANS) {
-                    span_func(NSPANS, spans, data);
-                    current = 0;
-                }
-                spans[current].len = 1;
-                spans[current].coverage = 255;
-                spans[current].x = x;
-                spans[current].y = y;
-                ++current;
-            }
-        }
-    }
-flush_and_return:
-    if (current > 0)
-        span_func(current, ordered ? spans : spans + (NSPANS - current), data);
-}
-
-static void offset_pattern(int offset, bool *inDash, int *dashIndex, int *currentOffset, const QVarLengthArray<qreal> &pattern)
-{
-    while (offset--) {
-        if (--*currentOffset == 0) {
-            *inDash = !*inDash;
-            *dashIndex = ((*dashIndex + 1) % pattern.size());
-            *currentOffset = int(pattern[*dashIndex]);
-        }
-    }
-}
-
-static void drawLine_midpoint_dashed_i(int x1, int y1, int x2, int y2,
-                                       QPen *pen,
-                                       ProcessSpans span_func, QSpanData *data,
-                                       LineDrawMode style, const QIntRect &devRect,
-                                       int *patternOffset)
-{
-#ifdef QT_DEBUG_DRAW
-    qDebug() << "   - drawLine_midpoint_dashed_i" << x1 << y1 << x2 << y2 << *patternOffset;
-#endif
-
-    int x, y;
-    int dx, dy, d, incrE, incrNE;
-
-    dx = x2 - x1;
-    dy = y2 - y1;
-
-    Q_ASSERT(*patternOffset >= 0);
-
-    const QVector<qreal> penPattern = pen->dashPattern();
-    QVarLengthArray<qreal> pattern(penPattern.size());
-
-    int patternLength = 0;
-    for (int i = 0; i < penPattern.size(); ++i)
-        patternLength += qMax<qreal>(1.0, (penPattern.at(i)));
-
-    // pattern must be reversed if coordinates are out of order
-    int reverseLength = -1;
-    if (dy == 0 && x1 > x2)
-        reverseLength = x1 - x2;
-    else if (dx == 0 && y1 > y2)
-        reverseLength = y1 - y2;
-    else if (qAbs(dx) >= qAbs(dy) && x2 < x1) // x major axis
-        reverseLength = qAbs(dx);
-    else if (qAbs(dy) >= qAbs(dx) && y2 < y1) // y major axis
-        reverseLength = qAbs(dy);
-
-    const bool reversed = (reverseLength > -1);
-    if (reversed) { // reverse pattern
-        for (int i = 0; i < penPattern.size(); ++i)
-            pattern[penPattern.size() - 1 - i] = qMax<qreal>(1.0, penPattern.at(i));
-
-        *patternOffset = (patternLength - 1 - *patternOffset);
-        *patternOffset += patternLength - (reverseLength % patternLength);
-        *patternOffset = *patternOffset % patternLength;
-    } else {
-        for (int i = 0; i < penPattern.size(); ++i)
-            pattern[i] = qMax<qreal>(1.0, penPattern.at(i));
-    }
-
-    int dashIndex = 0;
-    bool inDash = !reversed;
-    int currPattern = int(pattern[dashIndex]);
-
-    // adjust pattern for offset
-    offset_pattern(*patternOffset, &inDash, &dashIndex, &currPattern, pattern);
-
-    const int NSPANS = 256;
-    QT_FT_Span spans[NSPANS];
-    int current = 0;
-    bool ordered = true;
-
-    if (dy == 0) {
-        // specialcase horizontal lines
-        if (y1 >= devRect.y1 && y1 < devRect.y2) {
-            int start_unclipped = qMin(x1, x2);
-            int start = qMax(devRect.x1, start_unclipped);
-            int stop = qMax(x1, x2) + 1;
-            int stop_clipped = qMin(devRect.x2, stop);
-            int len = stop_clipped - start;
-            if (style == LineDrawNormal && stop == stop_clipped)
-                len--;
-
-            // adjust pattern for starting offset
-            offset_pattern(start - start_unclipped, &inDash, &dashIndex, &currPattern, pattern);
-
-            if (len > 0) {
-                int x = start;
-                while (x < stop_clipped) {
-                    if (current == NSPANS) {
-                        span_func(NSPANS, spans, data);
-                        current = 0;
-                    }
-                    const int dash = qMin(currPattern, stop_clipped - x);
-                    if (inDash) {
-                        spans[current].x = ushort(x);
-                        spans[current].len = ushort(dash);
-                        spans[current].y = y1;
-                        spans[current].coverage = 255;
-                        ++current;
-                    }
-                    if (dash < currPattern) {
-                        currPattern -= dash;
-                    } else {
-                        dashIndex = (dashIndex + 1) % pattern.size();
-                        currPattern = int(pattern[dashIndex]);
-                        inDash = !inDash;
-                    }
-                    x += dash;
-                }
-            }
-        }
-        goto flush_and_return;
-    } else if (dx == 0) {
-        if (x1 >= devRect.x1 && x1 < devRect.x2) {
-            int start_unclipped = qMin(y1, y2);
-            int start = qMax(devRect.y1, start_unclipped);
-            int stop = qMax(y1, y2) + 1;
-            int stop_clipped = qMin(devRect.y2, stop);
-            if (style == LineDrawNormal && stop == stop_clipped)
-                --stop;
-            else
-                stop = stop_clipped;
-
-            // adjust pattern for starting offset
-            offset_pattern(start - start_unclipped, &inDash, &dashIndex, &currPattern, pattern);
-
-            // loop over dashes
-            int y = start;
-            while (y < stop) {
-                const int dash = qMin(currPattern, stop - y);
-                if (inDash) {
-                    for (int i = 0; i < dash; ++i) {
-                        if (current == NSPANS) {
-                            span_func(NSPANS, spans, data);
-                            current = 0;
-                        }
-                        spans[current].x = x1;
-                        spans[current].len = 1;
-                        spans[current].coverage = 255;
-                        spans[current].y = ushort(y + i);
-                        ++current;
-                    }
-                }
-                if (dash < currPattern) {
-                    currPattern -= dash;
-                } else {
-                    dashIndex = (dashIndex + 1) % pattern.size();
-                    currPattern = int(pattern[dashIndex]);
-                    inDash = !inDash;
-                }
-                y += dash;
-            }
-        }
-        goto flush_and_return;
-    }
-
-    if (qAbs(dx) >= qAbs(dy)) {       /* if x is the major axis: */
-
-        if (x2 < x1) {  /* if coordinates are out of order */
-            qt_swap_int(x1, x2);
-            dx = -dx;
-
-            qt_swap_int(y1, y2);
-            dy = -dy;
-        }
-
-        if (style == LineDrawNormal)
-            --x2;
-
-        // In the loops below we increment before call the span function so
-        // we need to stop one pixel before
-        x2 = qMin(x2, devRect.x2 - 1);
-
-        // completely clipped, so abort
-        if (x2 <= x1)
-            goto flush_and_return;
-
-        int x = x1;
-        int y = y1;
-
-        if (x >= devRect.x1 && y >= devRect.y1 && y < devRect.y2) {
-            Q_ASSERT(x < devRect.x2);
-            if (inDash) {
-                if (current == NSPANS) {
-                    span_func(NSPANS, spans, data);
-                    current = 0;
-                }
-                spans[current].len = 1;
-                spans[current].coverage = 255;
-                spans[current].x = x;
-                spans[current].y = y;
-                ++current;
-            }
-            if (--currPattern <= 0) {
-                inDash = !inDash;
-                dashIndex = (dashIndex + 1) % pattern.size();
-                currPattern = int(pattern[dashIndex]);
-            }
-        }
-
-        if (y2 > y1) { // 315 -> 360 and 135 -> 180 (unit circle degrees)
-            y2 = qMin(y2, devRect.y2 - 1);
-
-            incrE = dy * 2;
-            d = incrE - dx;
-            incrNE = (dy - dx) * 2;
-
-            if (y > y2)
-                goto flush_and_return;
-
-            while (x < x2) {
-                if (d > 0) {
-                    ++y;
-                    d += incrNE;
-                    if (y > y2)
-                        goto flush_and_return;
-                } else {
-                    d += incrE;
-                }
-                ++x;
-
-                const bool skip = x < devRect.x1 || y < devRect.y1;
-                Q_ASSERT(skip || (x < devRect.x2 && y < devRect.y2));
-                if (inDash && !skip) {
-                    if (current == NSPANS) {
-                        span_func(NSPANS, spans, data);
-                        current = 0;
-                    }
-                    spans[current].len = 1;
-                    spans[current].coverage = 255;
-                    spans[current].x = x;
-                    spans[current].y = y;
-                    ++current;
-                }
-                if (--currPattern <= 0) {
-                    inDash = !inDash;
-                    dashIndex = (dashIndex + 1) % pattern.size();
-                    currPattern = int(pattern[dashIndex]);
-                }
-            }
-        } else {  // 0-45 and 180->225 (unit circle degrees)
-            y1 = qMin(y1, devRect.y2 - 1);
-
-            incrE = dy * 2;
-            d = incrE + dx;
-            incrNE = (dy + dx) * 2;
-
-            if (y < devRect.y1)
-                goto flush_and_return;
-
-            while (x < x2) {
-                if (d < 0) {
-                    if (current > 0) {
-                        span_func(current, spans, data);
-                        current = 0;
-                    }
-
-                    --y;
-                    d += incrNE;
-                    if (y < devRect.y1)
-                        goto flush_and_return;
-                } else {
-                    d += incrE;
-                }
-                ++x;
-
-                const bool skip = x < devRect.x1 || y > y1;
-                Q_ASSERT(skip || (x < devRect.x2 && y < devRect.y2));
-                if (inDash && !skip) {
-                    if (current == NSPANS) {
-                        span_func(NSPANS, spans, data);
-                        current = 0;
-                    }
-                    spans[current].len = 1;
-                    spans[current].coverage = 255;
-                    spans[current].x = x;
-                    spans[current].y = y;
-                    ++current;
-                }
-                if (--currPattern <= 0) {
-                    inDash = !inDash;
-                    dashIndex = (dashIndex + 1) % pattern.size();
-                    currPattern = int(pattern[dashIndex]);
-                }
-            }
-        }
-    } else {
-
-        // if y is the major axis:
-
-        if (y2 < y1) {      /* if coordinates are out of order */
-            qt_swap_int(y1, y2);
-            dy = -dy;
-
-            qt_swap_int(x1, x2);
-            dx = -dx;
-        }
-
-        if (style == LineDrawNormal)
-            --y2;
-
-        // In the loops below we increment before call the span function so
-        // we need to stop one pixel before
-        y2 = qMin(y2, devRect.y2 - 1);
-
-        // completely clipped, so abort
-        if (y2 <= y1)
-            goto flush_and_return;
-
-        x = x1;
-        y = y1;
-
-        if (x>=devRect.x1 && y>=devRect.y1 && x < devRect.x2) {
-            Q_ASSERT(x < devRect.x2);
-            if (inDash) {
-                if (current == NSPANS) {
-                    span_func(NSPANS, spans, data);
-                    current = 0;
-                }
-                spans[current].len = 1;
-                spans[current].coverage = 255;
-                spans[current].x = x;
-                spans[current].y = y;
-                ++current;
-            }
-            if (--currPattern <= 0) {
-                inDash = !inDash;
-                dashIndex = (dashIndex + 1) % pattern.size();
-                currPattern = int(pattern[dashIndex]);
-            }
-        }
-
-        if (x2 > x1) { // 90 -> 135 and 270 -> 315 (unit circle degrees)
-            x2 = qMin(x2, devRect.x2 - 1);
-            incrE = dx * 2;
-            d = incrE - dy;
-            incrNE = (dx - dy) * 2;
-
-            if (x > x2)
-                goto flush_and_return;
-
-            while (y < y2) {
-                if (d > 0) {
-                    ++x;
-                    d += incrNE;
-                    if (x > x2)
-                        goto flush_and_return;
-                } else {
-                    d += incrE;
-                }
-                ++y;
-                const bool skip = x < devRect.x1 || y < devRect.y1;
-                Q_ASSERT(skip || (x < devRect.x2 && y < devRect.y2));
-                if (inDash && !skip) {
-                    if (current == NSPANS) {
-                        span_func(NSPANS, spans, data);
-                        current = 0;
-                    }
-                    spans[current].len = 1;
-                    spans[current].coverage = 255;
-                    spans[current].x = x;
-                    spans[current].y = y;
-                    ++current;
-                }
-                if (--currPattern <= 0) {
-                    inDash = !inDash;
-                    dashIndex = (dashIndex + 1) % pattern.size();
-                    currPattern = int(pattern[dashIndex]);
-                }
-            }
-        } else { // 45 -> 90 and 225 -> 270 (unit circle degrees)
-            x1 = qMin(x1, devRect.x2 - 1);
-            incrE = dx * 2;
-            d = incrE + dy;
-            incrNE = (dx + dy) * 2;
-
-            if (x < devRect.x1)
-                goto flush_and_return;
-
-            while (y < y2) {
-                if (d < 0) {
-                    --x;
-                    d += incrNE;
-                    if (x < devRect.x1)
-                        goto flush_and_return;
-                } else {
-                    d += incrE;
-                }
-                ++y;
-                const bool skip = y < devRect.y1 || x > x1;
-                Q_ASSERT(skip || (x >= devRect.x1 && x < devRect.x2 && y < devRect.y2));
-                if (inDash && !skip) {
-                    if (current == NSPANS) {
-                        span_func(NSPANS, spans, data);
-                        current = 0;
-                    }
-                    spans[current].len = 1;
-                    spans[current].coverage = 255;
-                    spans[current].x = x;
-                    spans[current].y = y;
-                    ++current;
-                }
-                if (--currPattern <= 0) {
-                    inDash = !inDash;
-                    dashIndex = (dashIndex + 1) % pattern.size();
-                    currPattern = int(pattern[dashIndex]);
-                }
-            }
-        }
-    }
-flush_and_return:
-    if (current > 0)
-        span_func(current, ordered ? spans : spans + (NSPANS - current), data);
-
-    // adjust offset
-    if (reversed) {
-        *patternOffset = (patternLength - 1 - *patternOffset);
-    } else {
-        *patternOffset = 0;
-        for (int i = 0; i <= dashIndex; ++i)
-            *patternOffset += int(pattern[i]);
-        *patternOffset += patternLength - currPattern - 1;
-        *patternOffset = (*patternOffset % patternLength);
-    }
-}
-
 /*!
     \internal
     \a x and \a y is relative to the midpoint of \a rect.
@@ -6349,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)