Make QPen default to 1-width non-cosmetic.
[profile/ivi/qtbase.git] / src / gui / painting / qpainter.cpp
index 0f5468d..090faf1 100644 (file)
@@ -1,38 +1,38 @@
 /****************************************************************************
 **
-** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
 **
 ** This file is part of the QtGui module of the Qt Toolkit.
 **
 ** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
 ** GNU Lesser General Public License Usage
-** This file may be used under the terms of the GNU Lesser General Public
-** License version 2.1 as published by the Free Software Foundation and
-** appearing in the file LICENSE.LGPL included in the packaging of this
-** file. Please review the following information to ensure the GNU Lesser
-** General Public License version 2.1 requirements will be met:
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 **
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 **
 ** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU General
-** Public License version 3.0 as published by the Free Software Foundation
-** and appearing in the file LICENSE.GPL included in the packaging of this
-** file. Please review the following information to ensure the GNU General
-** Public License version 3.0 requirements will be met:
-** http://www.gnu.org/copyleft/gpl.html.
-**
-** Other Usage
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**
-**
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
 **
 **
 ** $QT_END_LICENSE$
@@ -61,6 +61,8 @@
 #include "qstatictext.h"
 #include "qglyphrun.h"
 
+#include <qpa/qplatformtheme.h>
+
 #include <private/qfontengine_p.h>
 #include <private/qpaintengine_p.h>
 #include <private/qemulationpaintengine_p.h>
@@ -90,7 +92,7 @@ void qt_format_text(const QFont &font,
                     const QRectF &_r, int tf, const QTextOption *option, const QString& str, QRectF *brect,
                     int tabstops, int* tabarray, int tabarraylen,
                     QPainter *painter);
-static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const QFontEngine *fe,
+static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const QFontEngine *fe, QTextEngine *textEngine,
                                    QTextCharFormat::UnderlineStyle underlineStyle,
                                    QTextItem::RenderFlags flags, qreal width,
                                    const QTextCharFormat &charFormat);
@@ -895,26 +897,8 @@ void QPainterPrivate::updateState(QPainterState *newState)
 
     if (!newState) {
         engine->state = newState;
-
     } else if (newState->state() || engine->state!=newState) {
-        bool setNonCosmeticPen = (newState->renderHints & QPainter::NonCosmeticDefaultPen)
-                                 && newState->pen.widthF() == 0;
-        if (setNonCosmeticPen) {
-            // Override the default pen's cosmetic state if the
-            // NonCosmeticDefaultPen render hint is used.
-            QPen oldPen = newState->pen;
-            newState->pen.setWidth(1);
-            newState->pen.setCosmetic(false);
-            newState->dirtyFlags |= QPaintEngine::DirtyPen;
-
-            updateStateImpl(newState);
-
-            // Restore the state pen back to its default to preserve visible
-            // state.
-            newState->pen = oldPen;
-        } else {
-            updateStateImpl(newState);
-        }
+        updateStateImpl(newState);
     }
 }
 
@@ -924,6 +908,7 @@ void QPainterPrivate::updateState(QPainterState *newState)
     \brief The QPainter class performs low-level painting on widgets and
     other paint devices.
 
+    \inmodule QtGui
     \ingroup painting
 
     \reentrant
@@ -941,7 +926,7 @@ void QPainterPrivate::updateState(QPainterState *newState)
     painter. Then draw. Remember to destroy the QPainter object after
     drawing. For example:
 
-    \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 0
+    \snippet code/src_gui_painting_qpainter.cpp 0
 
     The core functionality of QPainter is drawing, but the class also
     provide several functions that allows you to customize QPainter's
@@ -970,10 +955,7 @@ void QPainterPrivate::updateState(QPainterState *newState)
 
     \warning When the paintdevice is a widget, QPainter can only be
     used inside a paintEvent() function or in a function called by
-    paintEvent(); that is unless the Qt::WA_PaintOutsidePaintEvent
-    widget attribute is set. On Mac OS X and Windows, you can only
-    paint in a paintEvent() function regardless of this attribute's
-    setting.
+    paintEvent().
 
     \tableofcontents
 
@@ -1417,9 +1399,13 @@ void QPainterPrivate::updateState(QPainterState *newState)
     indicating that the engine should use fragment programs and offscreen
     rendering for antialiasing.
 
-    \value NonCosmeticDefaultPen The engine should interpret pens with a width
-    of 0 (which otherwise enables QPen::isCosmetic()) as being a non-cosmetic
-    pen with a width of 1.
+    \value NonCosmeticDefaultPen This value is obsolete, the default for QPen
+    is now non-cosmetic.
+
+    \value Qt4CompatiblePainting Compatibility hint telling the engine to use the
+    same X11 based fill rules as in Qt 4, where aliased rendering is offset
+    by slightly less than half a pixel. Also will treat default constructed pens
+    as cosmetic. Potentially useful when porting a Qt 4 application to Qt 5.
 
     \sa renderHints(), setRenderHint(), {QPainter#Rendering
     Quality}{Rendering Quality}, {Concentric Circles Example}
@@ -1449,10 +1435,10 @@ QPainter::QPainter()
     automatically calls end().
 
     Here's an example using begin() and end():
-    \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 1
+    \snippet code/src_gui_painting_qpainter.cpp 1
 
     The same example using this constructor:
-    \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 2
+    \snippet code/src_gui_painting_qpainter.cpp 2
 
     Since the constructor cannot provide feedback when the initialization
     of the painter failed you should rather use begin() and end() to paint
@@ -1526,7 +1512,7 @@ bool QPainter::isActive() const
 
 /*!
     Initializes the painters pen, background and font to the same as
-    the given \a paint device.
+    the given \a device.
 
     \obsolete
 
@@ -1541,7 +1527,7 @@ void QPainter::initFrom(const QPaintDevice *device)
         return;
     }
 
-    device->init(this);
+    device->initPainter(this);
 
     if (d->extended) {
         d->extended->penChanged();
@@ -1670,7 +1656,7 @@ void QPainter::restore()
 
     The errors that can occur are serious problems, such as these:
 
-    \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 3
+    \snippet code/src_gui_painting_qpainter.cpp 3
 
     Note that most of the time, you can use one of the constructors
     instead of begin(), and that end() is automatically done at
@@ -1760,25 +1746,6 @@ bool QPainter::begin(QPaintDevice *pd)
         d->engine->state = d->state;
 
     switch (pd->devType()) {
-#if 0
-        // is this needed any more??
-        case QInternal::Widget:
-        {
-            const QWidget *widget = static_cast<const QWidget *>(pd);
-            Q_ASSERT(widget);
-
-            const bool paintOutsidePaintEvent = widget->testAttribute(Qt::WA_PaintOutsidePaintEvent);
-            const bool inPaintEvent = widget->testAttribute(Qt::WA_WState_InPaintEvent);
-
-            // Adjust offset for alien widgets painting outside the paint event.
-            if (!inPaintEvent && paintOutsidePaintEvent && !widget->internalWinId()
-                && widget->testAttribute(Qt::WA_WState_Created)) {
-                const QPoint offset = widget->mapTo(widget->nativeParentWidget(), QPoint());
-                d->state->redirectionMatrix.translate(offset.x(), offset.y());
-            }
-            break;
-        }
-#endif
         case QInternal::Pixmap:
         {
             QPixmap *pm = static_cast<QPixmap *>(pd);
@@ -1978,7 +1945,7 @@ QPaintEngine *QPainter::paintEngine() const
     default state by endNativePainting(). Here is an example that shows
     intermixing of painter commands and raw OpenGL commands:
 
-    \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 21
+    \snippet code/src_gui_painting_qpainter.cpp 21
 
     \sa endNativePainting()
 */
@@ -2339,6 +2306,23 @@ void QPainter::setBrushOrigin(const QPointF &p)
     where the source is AND'ed with the inverted destination pixels
     (src AND (NOT dst)).
 
+    \value RasterOp_NotSourceOrDestination Does a bitwise operation
+    where the source is inverted and then OR'ed with the destination
+    ((NOT src) OR dst).
+
+    \value RasterOp_ClearDestination The pixels in the destination are
+    cleared (set to 0) independent of the source.
+
+    \value RasterOp_SetDestination The pixels in the destination are
+    set (set to 1) independent of the source.
+
+    \value RasterOp_NotDestination Does a bitwise operation
+    where the destination pixels are inverted (NOT dst).
+
+    \value RasterOp_SourceOrNotDestination Does a bitwise operation
+    where the source is OR'ed with the inverted destination pixels
+    (src OR (NOT dst)).
+
     \sa compositionMode(), setCompositionMode(), {QPainter#Composition
     Modes}{Composition Modes}, {Image Composition Example}
 */
@@ -2893,7 +2877,7 @@ void QPainter::setClipRegion(const QRegion &r, Qt::ClipOperation op)
 
     They operate on the painter's worldMatrix() and are implemented like this:
 
-    \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 4
+    \snippet code/src_gui_painting_qpainter.cpp 4
 
     Note that when using setWorldMatrix() function you should always have
     \a combine be true when you are drawing into a QPicture. Otherwise
@@ -3107,8 +3091,7 @@ bool QPainter::matrixEnabled() const
 /*!
     Scales the coordinate system by (\a{sx}, \a{sy}).
 
-    \sa setWorldTransform() {QPainter#Coordinate Transformations}{Coordinate
-    Transformations}
+    \sa setWorldTransform(), {QPainter#Coordinate Transformations}{Coordinate Transformations}
 */
 
 void QPainter::scale(qreal sx, qreal sy)
@@ -3131,8 +3114,7 @@ void QPainter::scale(qreal sx, qreal sy)
 /*!
     Shears the coordinate system by (\a{sh}, \a{sv}).
 
-    \sa setWorldTransform(), {QPainter#Coordinate Transformations}{Coordinate
-    Transformations}
+    \sa setWorldTransform(), {QPainter#Coordinate Transformations}{Coordinate Transformations}
 */
 
 void QPainter::shear(qreal sh, qreal sv)
@@ -3155,10 +3137,9 @@ void QPainter::shear(qreal sh, qreal sv)
 /*!
     \fn void QPainter::rotate(qreal angle)
 
-    Rotates the coordinate system the given \a angle clockwise.
+    Rotates the coordinate system clockwise. The given \a angle parameter uses degree unit.
 
-    \sa setWorldTransform(), {QPainter#Coordinate Transformations}{Coordinate
-    Transformations}
+    \sa setWorldTransform(), {QPainter#Coordinate Transformations}{Coordinate Transformations}
 */
 
 void QPainter::rotate(qreal a)
@@ -3182,8 +3163,7 @@ void QPainter::rotate(qreal a)
     Translates the coordinate system by the given \a offset; i.e. the
     given \a offset is added to points.
 
-    \sa setWorldTransform(), {QPainter#Coordinate Transformations}{Coordinate
-    Transformations}
+    \sa setWorldTransform(), {QPainter#Coordinate Transformations}{Coordinate Transformations}
 */
 void QPainter::translate(const QPointF &offset)
 {
@@ -3362,7 +3342,7 @@ void QPainter::fillPath(const QPainterPath &path, const QBrush &brush)
     \row
     \li \inlineimage qpainter-path.png
     \li
-    \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 5
+    \snippet code/src_gui_painting_qpainter.cpp 5
     \endtable
 
     \sa {painting/painterpaths}{the Painter Paths
@@ -3407,7 +3387,7 @@ void QPainter::drawPath(const QPainterPath &path)
     \row
     \li \inlineimage qpainter-line.png
     \li
-    \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 6
+    \snippet code/src_gui_painting_qpainter.cpp 6
     \endtable
 
     \sa drawLines(), drawPolyline(), {Coordinate System}
@@ -3454,7 +3434,7 @@ void QPainter::drawPath(const QPainterPath &path)
     \row
     \li \inlineimage qpainter-rectangle.png
     \li
-    \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 7
+    \snippet code/src_gui_painting_qpainter.cpp 7
     \endtable
 
     \sa drawRects(), drawPolygon(), {Coordinate System}
@@ -3850,13 +3830,10 @@ void QPainter::setPen(const QColor &color)
         return;
     }
 
-    if (d->state->pen.style() == Qt::SolidLine
-        && d->state->pen.widthF() == 0
-        && d->state->pen.isSolid()
-        && d->state->pen.color() == color)
-        return;
+    QPen pen(color.isValid() ? color : QColor(Qt::black));
 
-    QPen pen(color.isValid() ? color : QColor(Qt::black), 0, Qt::SolidLine);
+    if (d->state->pen == pen)
+        return;
 
     d->state->pen = pen;
     if (d->extended)
@@ -3905,7 +3882,7 @@ void QPainter::setPen(const QPen &pen)
 /*!
     \overload
 
-    Sets the painter's pen to have the given \a style, width 0 and
+    Sets the painter's pen to have the given \a style, width 1 and
     black color.
 */
 
@@ -3917,15 +3894,12 @@ void QPainter::setPen(Qt::PenStyle style)
         return;
     }
 
-    if (d->state->pen.style() == style
-        && (style == Qt::NoPen || (d->state->pen.widthF() == 0
-                                   && d->state->pen.isSolid()
-                                   && d->state->pen.color() == QColor(Qt::black))))
+    QPen pen = QPen(style);
+
+    if (d->state->pen == pen)
         return;
 
-    // QPen(Qt::NoPen) is to avoid creating QPenData, including its brush (from the color)
-    // Note that this works well as long as QPen(Qt::NoPen) returns a black, zero-width pen
-    d->state->pen = (style == Qt::NoPen) ? QPen(Qt::NoPen) : QPen(Qt::black, 0, style);
+    d->state->pen = pen;
 
     if (d->extended)
         d->extended->penChanged();
@@ -4123,7 +4097,7 @@ const QFont &QPainter::font() const
     \row
     \li \inlineimage qpainter-roundrect.png
     \li
-    \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 8
+    \snippet code/src_gui_painting_qpainter.cpp 8
     \endtable
 
     \sa drawRect(), QPen
@@ -4223,7 +4197,7 @@ void QPainter::drawRoundRect(const QRectF &r, int xRnd, int yRnd)
     \row
     \li \inlineimage qpainter-ellipse.png
     \li
-    \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 9
+    \snippet code/src_gui_painting_qpainter.cpp 9
     \endtable
 
     \sa drawPie(), {Coordinate System}
@@ -4349,7 +4323,7 @@ void QPainter::drawEllipse(const QRect &r)
     \row
     \li \inlineimage qpainter-arc.png
     \li
-    \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 10
+    \snippet code/src_gui_painting_qpainter.cpp 10
     \endtable
 
     \sa drawPie(), drawChord(), {Coordinate System}
@@ -4398,8 +4372,7 @@ void QPainter::drawArc(const QRectF &r, int a, int alen)
 /*!
     \fn void QPainter::drawPie(const QRectF &rectangle, int startAngle, int spanAngle)
 
-    Draws a pie defined by the given \a rectangle, \a startAngle and
-    and \a spanAngle.
+    Draws a pie defined by the given \a rectangle, \a startAngle and \a spanAngle.
 
     The pie is filled with the current brush().
 
@@ -4413,7 +4386,7 @@ void QPainter::drawArc(const QRectF &r, int a, int alen)
     \row
     \li \inlineimage qpainter-pie.png
     \li
-    \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 11
+    \snippet code/src_gui_painting_qpainter.cpp 11
     \endtable
 
     \sa drawEllipse(), drawChord(), {Coordinate System}
@@ -4482,7 +4455,7 @@ void QPainter::drawPie(const QRectF &r, int a, int alen)
     \row
     \li \inlineimage qpainter-chord.png
     \li
-    \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 12
+    \snippet code/src_gui_painting_qpainter.cpp 12
     \endtable
 
     \sa drawArc(), drawPie(), {Coordinate System}
@@ -4697,7 +4670,7 @@ void QPainter::drawLines(const QPoint *pointPairs, int lineCount)
     \table 100%
     \row
     \li
-    \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 13
+    \snippet code/src_gui_painting_qpainter.cpp 13
     \endtable
 
     \sa drawLines(), drawPolygon(), {Coordinate System}
@@ -4804,7 +4777,7 @@ void QPainter::drawPolyline(const QPoint *points, int pointCount)
     \row
     \li \inlineimage qpainter-polygon.png
     \li
-    \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 14
+    \snippet code/src_gui_painting_qpainter.cpp 14
     \endtable
 
     The first point is implicitly connected to the last point, and the
@@ -4816,7 +4789,7 @@ void QPainter::drawPolyline(const QPoint *points, int pointCount)
     \l{Qt::FillRule} for a more detailed description of these fill
     rules.
 
-    \sa  drawConvexPolygon(), drawPolyline(), {Coordinate System}
+    \sa drawConvexPolygon(), drawPolyline(), {Coordinate System}
 */
 void QPainter::drawPolygon(const QPointF *points, int pointCount, Qt::FillRule fillRule)
 {
@@ -4917,7 +4890,7 @@ void QPainter::drawPolygon(const QPoint *points, int pointCount, Qt::FillRule fi
     \row
     \li \inlineimage qpainter-polygon.png
     \li
-    \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 15
+    \snippet code/src_gui_painting_qpainter.cpp 15
     \endtable
 
     The first point is implicitly connected to the last point, and the
@@ -5040,7 +5013,7 @@ static inline QPointF roundInDeviceCoordinates(const QPointF &p, const QTransfor
     \table 100%
     \row
     \li
-    \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 16
+    \snippet code/src_gui_painting_qpainter.cpp 16
     \endtable
 
     If \a pixmap is a QBitmap it is drawn with the bits that are "set"
@@ -5551,14 +5524,9 @@ void QPainter::drawGlyphRun(const QPointF &position, const QGlyphRun &glyphRun)
     QVarLengthArray<QFixedPoint, 128> fixedPointPositions(count);
 
     QRawFontPrivate *fontD = QRawFontPrivate::get(font);
-    bool supportsTransformations;
-    if (d->extended != 0) {
-        supportsTransformations = d->extended->supportsTransformations(fontD->fontEngine->fontDef.pixelSize,
-                                                                       d->state->matrix);
-    } else {
-        supportsTransformations = d->engine->type() == QPaintEngine::CoreGraphics
-                                  || d->state->matrix.isAffine();
-    }
+    bool supportsTransformations = d->extended
+        ? d->extended->supportsTransformations(fontD->fontEngine, d->state->matrix)
+        : d->engine->type() == QPaintEngine::CoreGraphics || d->state->matrix.isAffine();
 
     for (int i=0; i<count; ++i) {
         QPointF processedPosition = position + glyphPositions[i];
@@ -5621,9 +5589,9 @@ void QPainterPrivate::drawGlyphs(const quint32 *glyphArray, QFixedPoint *positio
         QVarLengthArray<QFixed, 128> advances(glyphCount);
         QVarLengthArray<QGlyphJustification, 128> glyphJustifications(glyphCount);
         QVarLengthArray<HB_GlyphAttributes, 128> glyphAttributes(glyphCount);
-        qMemSet(glyphAttributes.data(), 0, glyphAttributes.size() * sizeof(HB_GlyphAttributes));
-        qMemSet(advances.data(), 0, advances.size() * sizeof(QFixed));
-        qMemSet(glyphJustifications.data(), 0, glyphJustifications.size() * sizeof(QGlyphJustification));
+        memset(glyphAttributes.data(), 0, glyphAttributes.size() * sizeof(HB_GlyphAttributes));
+        memset(advances.data(), 0, advances.size() * sizeof(QFixed));
+        memset(glyphJustifications.data(), 0, glyphJustifications.size() * sizeof(QGlyphJustification));
 
         textItem.glyphs.numGlyphs = glyphCount;
         textItem.glyphs.glyphs = reinterpret_cast<HB_Glyph *>(const_cast<quint32 *>(glyphArray));
@@ -5646,6 +5614,7 @@ void QPainterPrivate::drawGlyphs(const quint32 *glyphArray, QFixedPoint *positio
 
     drawTextItemDecoration(q, QPointF(leftMost.toReal(), baseLine.toReal()),
                            fontEngine,
+                           0, // textEngine
                            (underline
                               ? QTextCharFormat::SingleUnderline
                               : QTextCharFormat::NoUnderline),
@@ -5681,7 +5650,7 @@ void QPainterPrivate::drawGlyphs(const quint32 *glyphArray, QFixedPoint *positio
     Draws the given \a text with the currently defined text direction,
     beginning at the given \a position.
 
-    This function does not handle the newline character (\n), as it cannot
+    This function does not handle the newline character (\\n), as it cannot
     break text into multiple lines, and it cannot display the newline character.
     Use the QPainter::drawText() overload that takes a rectangle instead
     if you want to draw multiple lines of text with the newline character, or
@@ -5690,6 +5659,8 @@ void QPainterPrivate::drawGlyphs(const quint32 *glyphArray, QFixedPoint *positio
     By default, QPainter draws text anti-aliased.
 
     \note The y-position is used as the baseline of the font.
+
+    \sa setFont(), setPen()
 */
 
 void QPainter::drawText(const QPointF &p, const QString &str)
@@ -5739,7 +5710,10 @@ void QPainter::drawStaticText(const QPointF &topLeftPosition, const QStaticText
         return;
     }
 
-    bool supportsTransformations = d->extended->supportsTransformations(staticText_d->font.pixelSize(),
+    QFontEngine *fe = staticText_d->font.d->engineForScript(QUnicodeTables::Common);
+    if (fe->type() == QFontEngine::Multi)
+        fe = static_cast<QFontEngineMulti *>(fe)->engine(0);
+    bool supportsTransformations = d->extended->supportsTransformations(fe,
                                                                         d->state->matrix);
     if (supportsTransformations && !staticText_d->untransformedCoordinates) {
         staticText_d->untransformedCoordinates = true;
@@ -5942,6 +5916,7 @@ void QPainter::drawText(const QRect &r, int flags, const QString &str, QRect *br
 
     \note The y-position is used as the baseline of the font.
 
+    \sa setFont(), setPen()
 */
 
 /*!
@@ -5949,12 +5924,13 @@ void QPainter::drawText(const QRect &r, int flags, const QString &str, QRect *br
     \overload
 
     Draws the given \a text within the provided \a rectangle.
+    The \a rectangle along with alignment \a flags defines the anchors for the \a text.
 
     \table 100%
     \row
     \li \inlineimage qpainter-text.png
     \li
-    \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 17
+    \snippet code/src_gui_painting_qpainter.cpp 17
     \endtable
 
     The \a boundingRect (if not null) is set to the what the bounding rectangle
@@ -6014,6 +5990,8 @@ void QPainter::drawText(const QRectF &r, int flags, const QString &str, QRectF *
     By default, QPainter draws text anti-aliased.
 
     \note The y-coordinate of \a rectangle is used as the top of the font.
+
+    \sa setFont(), setPen()
 */
 
 /*!
@@ -6028,6 +6006,7 @@ void QPainter::drawText(const QRectF &r, int flags, const QString &str, QRectF *
 
     \note The y-position is used as the baseline of the font.
 
+    \sa setFont(), setPen()
 */
 
 /*!
@@ -6062,7 +6041,7 @@ void QPainter::drawText(const QRectF &r, int flags, const QString &str, QRectF *
 
     \note The y-position is used as the top of the font.
 
-    \sa Qt::AlignmentFlag, Qt::TextFlag
+    \sa Qt::AlignmentFlag, Qt::TextFlag, setFont(), setPen()
 */
 
 /*!
@@ -6076,6 +6055,8 @@ void QPainter::drawText(const QRectF &r, int flags, const QString &str, QRectF *
     By default, QPainter draws text anti-aliased.
 
     \note The y-coordinate of \a rectangle is used as the top of the font.
+
+    \sa setFont(), setPen()
 */
 void QPainter::drawText(const QRectF &r, const QString &text, const QTextOption &o)
 {
@@ -6135,7 +6116,7 @@ static QPixmap generateWavyPixmap(qreal maxRadius, const QPen &pen)
 {
     const qreal radiusBase = qMax(qreal(1), maxRadius);
 
-    QString key = QLatin1Literal("WaveUnderline-")
+    QString key = QLatin1String("WaveUnderline-")
                   % pen.color().name()
                   % HexString<qreal>(radiusBase);
 
@@ -6182,7 +6163,7 @@ static QPixmap generateWavyPixmap(qreal maxRadius, const QPen &pen)
     return pixmap;
 }
 
-static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const QFontEngine *fe,
+static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const QFontEngine *fe, QTextEngine *textEngine,
                                    QTextCharFormat::UnderlineStyle underlineStyle,
                                    QTextItem::RenderFlags flags, qreal width,
                                    const QTextCharFormat &charFormat)
@@ -6204,11 +6185,12 @@ static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const
     const qreal underlineOffset = fe->underlinePosition().toReal();
     // deliberately ceil the offset to avoid the underline coming too close to
     // the text above it.
-    const qreal aliasedCoordinateDelta = 0.5 - 0.015625;
-    const qreal underlinePos = pos.y() + qCeil(underlineOffset) - aliasedCoordinateDelta;
+    const qreal underlinePos = pos.y() + qCeil(underlineOffset);
 
     if (underlineStyle == QTextCharFormat::SpellCheckUnderline) {
-        underlineStyle = QTextCharFormat::SpellCheckUnderline; // ### Qt5 QTextCharFormat::UnderlineStyle(QApplication::style()->styleHint(QStyle::SH_SpellCheckUnderlineStyle));
+        QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme();
+        if (theme)
+            underlineStyle = QTextCharFormat::UnderlineStyle(theme->themeHint(QPlatformTheme::SpellCheckUnderlineStyle).toInt());
     }
 
     if (underlineStyle == QTextCharFormat::WaveUnderline) {
@@ -6227,15 +6209,17 @@ static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const
         painter->fillRect(pos.x(), 0, qCeil(width), qMin(wave.height(), descent), wave);
         painter->restore();
     } else if (underlineStyle != QTextCharFormat::NoUnderline) {
-        QLineF underLine(line.x1(), underlinePos, line.x2(), underlinePos);
-
         QColor uc = charFormat.underlineColor();
         if (uc.isValid())
             pen.setColor(uc);
 
         pen.setStyle((Qt::PenStyle)(underlineStyle));
         painter->setPen(pen);
-        painter->drawLine(underLine);
+        QLineF underline(line.x1(), underlinePos, line.x2(), underlinePos);
+        if (textEngine)
+            textEngine->addUnderline(painter, underline);
+        else
+            painter->drawLine(underline);
     }
 
     pen.setStyle(Qt::SolidLine);
@@ -6245,14 +6229,20 @@ static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const
         QLineF strikeOutLine = line;
         strikeOutLine.translate(0., - fe->ascent().toReal() / 3.);
         painter->setPen(pen);
-        painter->drawLine(strikeOutLine);
+        if (textEngine)
+            textEngine->addStrikeOut(painter, strikeOutLine);
+        else
+            painter->drawLine(strikeOutLine);
     }
 
     if (flags & QTextItem::Overline) {
-        QLineF overLine = line;
-        overLine.translate(0., - fe->ascent().toReal());
+        QLineF overline = line;
+        overline.translate(0., - fe->ascent().toReal());
         painter->setPen(pen);
-        painter->drawLine(overLine);
+        if (textEngine)
+            textEngine->addOverline(painter, overline);
+        else
+            painter->drawLine(overline);
     }
 
     painter->setPen(oldPen);
@@ -6277,7 +6267,7 @@ Q_GUI_EXPORT void qt_draw_decoration_for_glyphs(QPainter *painter, const glyph_t
 
         // We don't support glyphs that do not share a common baseline. If this turns out to
         // be a relevant use case, then we need to find clusters of glyphs that share a baseline
-        // and do a drawTextItemDecorations call per cluster.
+        // and do a drawTextItemDecoration call per cluster.
         if (i == 0 || baseLine < positions[i].y)
             baseLine = positions[i].y;
 
@@ -6298,12 +6288,20 @@ Q_GUI_EXPORT void qt_draw_decoration_for_glyphs(QPainter *painter, const glyph_t
 
     drawTextItemDecoration(painter, QPointF(leftMost.toReal(), baseLine.toReal()),
                            fontEngine,
+                           0, // textEngine
                            font.underline() ? QTextCharFormat::SingleUnderline
                                             : QTextCharFormat::NoUnderline, flags,
                            width.toReal(), charFormat);
 }
 
-void QPainter::drawTextItem(const QPointF &p, const QTextItem &_ti)
+void QPainter::drawTextItem(const QPointF &p, const QTextItem &ti)
+{
+    Q_D(QPainter);
+
+    d->drawTextItem(p, ti, static_cast<QTextEngine *>(0));
+}
+
+void QPainterPrivate::drawTextItem(const QPointF &p, const QTextItem &_ti, QTextEngine *textEngine)
 {
 #ifdef QT_DEBUG_DRAW
     if (qt_show_painter_debug_output)
@@ -6311,35 +6309,35 @@ void QPainter::drawTextItem(const QPointF &p, const QTextItem &_ti)
                p.x(), p.y(), qPrintable(_ti.text()));
 #endif
 
-    Q_D(QPainter);
+    Q_Q(QPainter);
 
-    if (!d->engine)
+    if (!engine)
         return;
 
 #ifndef QT_NO_DEBUG
-    qt_painter_thread_test(d->device->devType(),
+    qt_painter_thread_test(device->devType(),
                            "text and fonts",
                            QFontDatabase::supportsThreadedFontRendering());
 #endif
 
     QTextItemInt &ti = const_cast<QTextItemInt &>(static_cast<const QTextItemInt &>(_ti));
 
-    if (!d->extended && d->state->bgMode == Qt::OpaqueMode) {
+    if (!extended && state->bgMode == Qt::OpaqueMode) {
         QRectF rect(p.x(), p.y() - ti.ascent.toReal(), ti.width.toReal(), (ti.ascent + ti.descent + 1).toReal());
-        fillRect(rect, d->state->bgBrush);
+        q->fillRect(rect, state->bgBrush);
     }
 
-    if (pen().style() == Qt::NoPen)
+    if (q->pen().style() == Qt::NoPen)
         return;
 
-    const RenderHints oldRenderHints = d->state->renderHints;
-    if (!d->state->renderHints & QPainter::Antialiasing && d->state->matrix.type() >= QTransform::TxScale) {
+    const QPainter::RenderHints oldRenderHints = state->renderHints;
+    if (!state->renderHints & QPainter::Antialiasing && state->matrix.type() >= QTransform::TxScale) {
         // draw antialias decoration (underline/overline/strikeout) with
         // transformed text
 
         bool aa = true;
-        const QTransform &m = d->state->matrix;
-        if (d->state->matrix.type() < QTransform::TxShear) {
+        const QTransform &m = state->matrix;
+        if (state->matrix.type() < QTransform::TxShear) {
             bool isPlain90DegreeRotation =
                 (qFuzzyIsNull(m.m11())
                  && qFuzzyIsNull(m.m12() - qreal(1))
@@ -6362,11 +6360,11 @@ void QPainter::drawTextItem(const QPointF &p, const QTextItem &_ti)
             aa = !isPlain90DegreeRotation;
         }
         if (aa)
-            setRenderHint(QPainter::Antialiasing, true);
+            q->setRenderHint(QPainter::Antialiasing, true);
     }
 
-    if (!d->extended)
-        d->updateState(d->state);
+    if (!extended)
+        updateState(state);
 
     if (!ti.glyphs.numGlyphs) {
         // nothing to do
@@ -6402,7 +6400,7 @@ void QPainter::drawTextItem(const QPointF &p, const QTextItem &_ti)
             if (rtl)
                 x -= ti2.width.toReal();
 
-            d->engine->drawTextItem(QPointF(x, y), ti2);
+            engine->drawTextItem(QPointF(x, y), ti2);
 
             if (!rtl)
                 x += ti2.width.toReal();
@@ -6429,10 +6427,10 @@ void QPainter::drawTextItem(const QPointF &p, const QTextItem &_ti)
         if (rtl)
             x -= ti2.width.toReal();
 
-        if (d->extended)
-            d->extended->drawTextItem(QPointF(x, y), ti2);
+        if (extended)
+            extended->drawTextItem(QPointF(x, y), ti2);
         else
-            d->engine->drawTextItem(QPointF(x,y), ti2);
+            engine->drawTextItem(QPointF(x,y), ti2);
 
         // reset the high byte for all glyphs
         const int hi = which << 24;
@@ -6440,20 +6438,20 @@ void QPainter::drawTextItem(const QPointF &p, const QTextItem &_ti)
             glyphs.glyphs[i] = hi | glyphs.glyphs[i];
 
     } else {
-        if (d->extended)
-            d->extended->drawTextItem(p, ti);
+        if (extended)
+            extended->drawTextItem(p, ti);
         else
-            d->engine->drawTextItem(p, ti);
+            engine->drawTextItem(p, ti);
     }
-    drawTextItemDecoration(this, p, ti.fontEngine, ti.underlineStyle, ti.flags, ti.width.toReal(),
-                           ti.charFormat);
+    drawTextItemDecoration(q, p, ti.fontEngine, textEngine, ti.underlineStyle,
+                           ti.flags, ti.width.toReal(), ti.charFormat);
 
-    if (d->state->renderHints != oldRenderHints) {
-        d->state->renderHints = oldRenderHints;
-        if (d->extended)
-            d->extended->renderHintsChanged();
+    if (state->renderHints != oldRenderHints) {
+        state->renderHints = oldRenderHints;
+        if (extended)
+            extended->renderHintsChanged();
         else
-            d->state->dirtyFlags |= QPaintEngine::DirtyHints;
+            state->dirtyFlags |= QPaintEngine::DirtyHints;
     }
 }
 
@@ -6692,7 +6690,7 @@ void QPainter::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPo
     \table 100%
     \row
     \li
-    \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 18
+    \snippet code/src_gui_painting_qpainter.cpp 18
     \endtable
 
     \sa QPicture::play()
@@ -6735,7 +6733,7 @@ void QPainter::drawPicture(const QPointF &p, const QPicture &picture)
 
     Erases the area inside the given \a rectangle. Equivalent to
     calling
-    \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 19
+    \snippet code/src_gui_painting_qpainter.cpp 19
 
     \sa fillRect()
 */
@@ -7150,7 +7148,7 @@ QRect QPainter::window() const
     The default viewport rectangle is the same as the device's
     rectangle.
 
-    \sa viewport(), viewTransformEnabled() {Coordinate
+    \sa viewport(), viewTransformEnabled(), {Coordinate
     System#Window-Viewport Conversion}{Window-Viewport Conversion}
 */
 
@@ -7258,6 +7256,7 @@ void QPainter::setRedirected(const QPaintDevice *device,
                              const QPoint &offset)
 {
     Q_ASSERT(device != 0);
+    Q_UNUSED(device)
     Q_UNUSED(replacement)
     Q_UNUSED(offset)
     qWarning("QPainter::setRedirected(): ignoring call to deprecated function, use QWidget::render() instead");
@@ -7550,11 +7549,12 @@ start_lengthVariant:
 
         for (int i = 0; i < textLayout.lineCount(); i++) {
             QTextLine line = textLayout.lineAt(i);
+            QTextEngine *eng = textLayout.engine();
+            eng->enableDelayDecorations();
 
             qreal advance = line.horizontalAdvance();
             xoff = 0;
             if (tf & Qt::AlignRight) {
-                QTextEngine *eng = textLayout.engine();
                 xoff = r.width() - advance -
                     eng->leadingSpaceWidth(eng->lines[line.lineNumber()]).toReal();
             }
@@ -7562,6 +7562,7 @@ start_lengthVariant:
                 xoff = (r.width() - advance) / 2;
 
             line.draw(painter, QPointF(r.x() + xoff, r.y() + yoff));
+            eng->drawDecorations(painter);
         }
 
         if (restore) {
@@ -7676,7 +7677,7 @@ void QPainterState::init(QPainter *p) {
     \table 100%
     \row
     \li
-    \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 20
+    \snippet code/src_gui_painting_qpainter.cpp 20
     \endtable
 
     \sa drawPixmap()
@@ -7769,6 +7770,7 @@ void QPainterState::init(QPainter *p) {
 /*!
     \class QPaintEngineState
     \since 4.1
+    \inmodule QtGui
 
     \brief The QPaintEngineState class provides information about the
     active paint engine's current state.
@@ -8109,7 +8111,7 @@ qreal QPaintEngineState::opacity() const
     If \a combine is true, the specified \a transform is combined with
     the current matrix; otherwise it replaces the current matrix.
 
-    \sa transform() setWorldTransform()
+    \sa transform(), setWorldTransform()
 */
 
 void QPainter::setTransform(const QTransform &transform, bool combine )
@@ -8311,6 +8313,7 @@ void QPainter::drawPixmapFragments(const PixmapFragment *fragments, int fragment
 /*!
     \since 4.7
     \class QPainter::PixmapFragment
+    \inmodule QtGui
 
     \brief This class is used in conjunction with the
     QPainter::drawPixmapFragments() function to specify how a pixmap, or