summaryrefslogtreecommitdiffstats
path: root/src/gui/painting/qpainter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/painting/qpainter.cpp')
-rw-r--r--src/gui/painting/qpainter.cpp978
1 files changed, 278 insertions, 700 deletions
diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp
index b0553a1ff9..f4b9741eed 100644
--- a/src/gui/painting/qpainter.cpp
+++ b/src/gui/painting/qpainter.cpp
@@ -1,43 +1,8 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** 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 The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
// QtCore
+#include <memory>
#include <qdebug.h>
#include <qmath.h>
#include <qmutex.h>
@@ -74,9 +39,15 @@
#include <private/qhexstring_p.h>
#include <private/qguiapplication_p.h>
#include <private/qrawfont_p.h>
+#include <private/qfont_p.h>
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
+// We changed the type from QScopedPointer to unique_ptr, make sure it's binary compatible:
+static_assert(sizeof(QScopedPointer<QPainterPrivate>) == sizeof(std::unique_ptr<QPainterPrivate>));
+
#define QGradient_StretchToDevice 0x10000000
#define QPaintEngine_OpaqueBackground 0x40000000
@@ -96,10 +67,15 @@ static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const
QTextItem::RenderFlags flags, qreal width,
const QTextCharFormat &charFormat);
// Helper function to calculate left most position, width and flags for decoration drawing
-Q_GUI_EXPORT void qt_draw_decoration_for_glyphs(QPainter *painter, const glyph_t *glyphArray,
- const QFixedPoint *positions, int glyphCount,
- QFontEngine *fontEngine, const QFont &font,
- const QTextCharFormat &charFormat);
+static void qt_draw_decoration_for_glyphs(QPainter *painter,
+ const QPointF &decorationPosition,
+ const glyph_t *glyphArray,
+ const QFixedPoint *positions,
+ int glyphCount,
+ QFontEngine *fontEngine,
+ bool underline,
+ bool overline,
+ bool strikeOut);
static inline QGradient::CoordinateMode coordinateMode(const QBrush &brush)
{
@@ -175,6 +151,23 @@ static bool qt_painter_thread_test(int devType, int engineType, const char *what
}
#endif
+static bool needsEmulation(const QBrush &brush)
+{
+ bool res = false;
+
+ const QGradient *bg = brush.gradient();
+ if (bg) {
+ res = (bg->coordinateMode() > QGradient::LogicalMode);
+ } else if (brush.style() == Qt::TexturePattern) {
+ if (qHasPixmapTexture(brush))
+ res = !qFuzzyCompare(brush.texture().devicePixelRatio(), qreal(1.0));
+ else
+ res = !qFuzzyCompare(brush.textureImage().devicePixelRatio(), qreal(1.0));
+ }
+
+ return res;
+}
+
void QPainterPrivate::checkEmulation()
{
Q_ASSERT(extended);
@@ -182,44 +175,34 @@ void QPainterPrivate::checkEmulation()
if (state->bgMode == Qt::OpaqueMode)
doEmulation = true;
- const QGradient *bg = state->brush.gradient();
- if (bg && bg->coordinateMode() > QGradient::LogicalMode)
+ if (needsEmulation(state->brush))
doEmulation = true;
- const QGradient *pg = qpen_brush(state->pen).gradient();
- if (pg && pg->coordinateMode() > QGradient::LogicalMode)
+ if (needsEmulation(qpen_brush(state->pen)))
doEmulation = true;
- if (state->brush.style() == Qt::TexturePattern) {
- if (qHasPixmapTexture(state->brush))
- doEmulation |= !qFuzzyCompare(state->brush.texture().devicePixelRatioF(), 1.0);
- else
- doEmulation |= !qFuzzyCompare(state->brush.textureImage().devicePixelRatioF(), 1.0);
- }
-
if (doEmulation && extended->flags() & QPaintEngineEx::DoNotEmulate)
return;
if (doEmulation) {
- if (extended != emulationEngine) {
+ if (extended != emulationEngine.get()) {
if (!emulationEngine)
- emulationEngine = new QEmulationPaintEngine(extended);
- extended = emulationEngine;
- extended->setState(state);
+ emulationEngine = std::make_unique<QEmulationPaintEngine>(extended);
+ extended = emulationEngine.get();
+ extended->setState(state.get());
}
- } else if (emulationEngine == extended) {
+ } else if (emulationEngine.get() == extended) {
extended = emulationEngine->real_engine;
}
}
-
-QPainterPrivate::~QPainterPrivate()
+QPainterPrivate::QPainterPrivate(QPainter *painter)
+ : q_ptr(painter), txinv(0), inDestructor(false)
{
- delete emulationEngine;
- qDeleteAll(states);
- delete dummyState;
}
+QPainterPrivate::~QPainterPrivate()
+ = default;
QTransform QPainterPrivate::viewTransform() const
{
@@ -238,7 +221,7 @@ qreal QPainterPrivate::effectiveDevicePixelRatio() const
if (device->devType() == QInternal::Printer)
return qreal(1);
- return qMax(qreal(1), device->devicePixelRatioF());
+ return device->devicePixelRatio();
}
QTransform QPainterPrivate::hidpiScaleTransform() const
@@ -263,22 +246,10 @@ bool QPainterPrivate::attachPainterPrivate(QPainter *q, QPaintDevice *pdev)
// Save the current state of the shared painter and assign
// the current d_ptr to the shared painter's d_ptr.
sp->save();
- if (!sp->d_ptr->d_ptrs) {
- // Allocate space for 4 d-pointers (enough for up to 4 sub-sequent
- // redirections within the same paintEvent(), which should be enough
- // in 99% of all cases). E.g: A renders B which renders C which renders D.
- sp->d_ptr->d_ptrs_size = 4;
- sp->d_ptr->d_ptrs = (QPainterPrivate **)malloc(4 * sizeof(QPainterPrivate *));
- Q_CHECK_PTR(sp->d_ptr->d_ptrs);
- } else if (sp->d_ptr->refcount - 1 == sp->d_ptr->d_ptrs_size) {
- // However, to support corner cases we grow the array dynamically if needed.
- sp->d_ptr->d_ptrs_size <<= 1;
- const int newSize = sp->d_ptr->d_ptrs_size * sizeof(QPainterPrivate *);
- sp->d_ptr->d_ptrs = q_check_ptr((QPainterPrivate **)realloc(sp->d_ptr->d_ptrs, newSize));
- }
- sp->d_ptr->d_ptrs[++sp->d_ptr->refcount - 2] = q->d_ptr.data();
- q->d_ptr.take();
- q->d_ptr.reset(sp->d_ptr.data());
+ ++sp->d_ptr->refcount;
+ sp->d_ptr->d_ptrs.push_back(q->d_ptr.get());
+ Q_UNUSED(q->d_ptr.release());
+ q->d_ptr.reset(sp->d_ptr.get());
Q_ASSERT(q->d_ptr->state);
@@ -321,7 +292,9 @@ void QPainterPrivate::detachPainterPrivate(QPainter *q)
Q_ASSERT(refcount > 1);
Q_ASSERT(q);
- QPainterPrivate *original = d_ptrs[--refcount - 1];
+ --refcount;
+ QPainterPrivate *original = d_ptrs.back();
+ d_ptrs.pop_back();
if (inDestructor) {
inDestructor = false;
if (original)
@@ -330,14 +303,12 @@ void QPainterPrivate::detachPainterPrivate(QPainter *q)
original = new QPainterPrivate(q);
}
- d_ptrs[refcount - 1] = nullptr;
q->restore();
- q->d_ptr.take();
+ Q_UNUSED(q->d_ptr.release());
q->d_ptr.reset(original);
if (emulationEngine) {
extended = emulationEngine->real_engine;
- delete emulationEngine;
emulationEngine = nullptr;
}
}
@@ -410,7 +381,7 @@ void QPainterPrivate::draw_helper(const QPainterPath &originalPath, DrawOperatio
if (q->hasClipping()) {
bool hasPerspectiveTransform = false;
- for (const QPainterClipInfo &info : qAsConst(state->clipInfo)) {
+ for (const QPainterClipInfo &info : std::as_const(state->clipInfo)) {
if (info.matrix.type() == QTransform::TxProject) {
hasPerspectiveTransform = true;
break;
@@ -1154,24 +1125,22 @@ void QPainterPrivate::updateState(QPainterState *newState)
The QPainter class also provides a means of controlling the
rendering quality through its RenderHint enum and the support for
floating point precision: All the functions for drawing primitives
- has a floating point version. These are often used in combination
+ have floating point versions.
+
+ \snippet code/src_gui_painting_qpainter.cpp floatBased
+
+ These are often used in combination
with the \l {RenderHint}{QPainter::Antialiasing} render hint.
+ \snippet code/src_gui_painting_qpainter.cpp renderHint
+
\table 100%
\row
+ \li Comparing concentric circles with int and float, and with or without
+ anti-aliased rendering. Using the floating point precision versions
+ produces evenly spaced rings. Anti-aliased rendering results in
+ smooth circles.
\li \inlineimage qpainter-concentriccircles.png
- \li
- \b {Concentric Circles Example}
-
- The \l {painting/concentriccircles}{Concentric Circles} example
- shows the improved rendering quality that can be obtained using
- floating point precision and anti-aliasing when drawing custom
- widgets.
-
- The application's main window displays several widgets which are
- drawn using the various combinations of precision and
- anti-aliasing.
-
\endtable
The RenderHint enum specifies flags to QPainter that may or may
@@ -1231,7 +1200,7 @@ void QPainterPrivate::updateState(QPainterState *newState)
\li \inlineimage qpainter-affinetransformations.png
\endtable
- All the tranformation operations operate on the transformation
+ All the transformation operations operate on the transformation
worldTransform(). A matrix transforms a point in the plane to another
point. For more information about the transformation matrix, see
the \l {Coordinate System} and QTransform documentation.
@@ -1425,16 +1394,15 @@ void QPainterPrivate::updateState(QPainterState *newState)
a smooth pixmap transformation algorithm (such as bilinear) rather
than nearest neighbor.
- \value HighQualityAntialiasing This value is obsolete and will be ignored,
- use the Antialiasing render hint instead.
-
- \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.
+ \value VerticalSubpixelPositioning Allow text to be positioned at fractions
+ of pixels vertically as well as horizontally, if this is supported by the
+ font engine. This is currently supported by Freetype on all platforms when
+ the hinting preference is QFont::PreferNoHinting, and also on macOS. For
+ most use cases this will not improve visual quality, but may increase memory
+ consumption and some reduction in text rendering performance. Therefore, enabling
+ this is not recommended unless the use case requires it. One such use case could
+ be aligning glyphs with other visual primitives.
+ This value was added in Qt 6.1.
\value LosslessImageRendering Use a lossless image rendering, whenever possible.
Currently, this hint is only used when QPainter is employed to output a PDF
@@ -1443,8 +1411,14 @@ void QPainterPrivate::updateState(QPainterState *newState)
JPEG compression.
This value was added in Qt 5.13.
+ \value NonCosmeticBrushPatterns When painting with a brush with one of the predefined pattern
+ styles, transform the pattern too, along with the object being painted. The default is to treat
+ the pattern as cosmetic, so that the pattern pixels will map directly to device pixels,
+ independently of any active transformations.
+ This value was added in Qt 6.4.
+
\sa renderHints(), setRenderHint(), {QPainter#Rendering
- Quality}{Rendering Quality}, {Concentric Circles Example}
+ Quality}{Rendering Quality}
*/
@@ -1513,8 +1487,6 @@ QPainter::~QPainter()
Q_ASSERT(d_ptr->inDestructor);
d_ptr->inDestructor = false;
Q_ASSERT(d_ptr->refcount == 1);
- if (d_ptr->d_ptrs)
- free(d_ptr->d_ptrs);
}
}
@@ -1543,25 +1515,8 @@ QPaintDevice *QPainter::device() const
bool QPainter::isActive() const
{
Q_D(const QPainter);
- return d->engine;
-}
-
-#if QT_DEPRECATED_SINCE(5, 13)
-/*!
- Initializes the painters pen, background and font to the same as
- the given \a device.
-
- \obsolete
-
- \sa begin(), {QPainter#Settings}{Settings}
-*/
-void QPainter::initFrom(const QPaintDevice *device)
-{
- Q_ASSERT_X(device, "QPainter::initFrom(const QPaintDevice *device)", "QPaintDevice cannot be 0");
- Q_D(QPainter);
- d->initFrom(device);
+ return d->engine != nullptr;
}
-#endif
void QPainterPrivate::initFrom(const QPaintDevice *device)
{
@@ -1602,15 +1557,19 @@ void QPainter::save()
return;
}
+ std::unique_ptr<QPainterState> prev;
if (d->extended) {
- d->state = d->extended->createState(d->states.back());
- d->extended->setState(d->state);
+ // separate the creation of a new state from the update of d->state, since some
+ // engines access d->state directly (not via createState()'s argument)
+ std::unique_ptr<QPainterState> next(d->extended->createState(d->state.get()));
+ prev = std::exchange(d->state, std::move(next));
+ d->extended->setState(d->state.get());
} else {
d->updateState(d->state);
- d->state = new QPainterState(d->states.back());
- d->engine->state = d->state;
+ prev = std::exchange(d->state, std::make_unique<QPainterState>(d->state.get()));
+ d->engine->state = d->state.get();
}
- d->states.push_back(d->state);
+ d->savedStates.push(std::move(prev));
}
/*!
@@ -1627,7 +1586,7 @@ void QPainter::restore()
printf("QPainter::restore()\n");
#endif
Q_D(QPainter);
- if (d->states.size()<=1) {
+ if (d->savedStates.empty()) {
qWarning("QPainter::restore: Unbalanced save/restore");
return;
} else if (!d->engine) {
@@ -1635,15 +1594,13 @@ void QPainter::restore()
return;
}
- QPainterState *tmp = d->state;
- d->states.pop_back();
- d->state = d->states.back();
+ const auto tmp = std::exchange(d->state, std::move(d->savedStates.top()));
+ d->savedStates.pop();
d->txinv = false;
if (d->extended) {
d->checkEmulation();
- d->extended->setState(d->state);
- delete tmp;
+ d->extended->setState(d->state.get());
return;
}
@@ -1657,9 +1614,8 @@ void QPainter::restore()
tmp->clipPath = QPainterPath();
d->engine->updateState(*tmp);
// replay the list of clip states,
- for (const QPainterClipInfo &info : qAsConst(d->state->clipInfo)) {
+ for (const QPainterClipInfo &info : std::as_const(d->state->clipInfo)) {
tmp->matrix = info.matrix;
- tmp->matrix *= d->state->redirectionMatrix;
tmp->clipOperation = info.operation;
if (info.clipType == QPainterClipInfo::RectClip) {
tmp->dirtyFlags = QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyTransform;
@@ -1681,8 +1637,7 @@ void QPainter::restore()
tmp->changeFlags |= QPaintEngine::DirtyTransform;
}
- d->updateState(d->state);
- delete tmp;
+ d->updateState(d->state.get());
}
@@ -1715,8 +1670,7 @@ void QPainter::restore()
static inline void qt_cleanup_painter_state(QPainterPrivate *d)
{
- qDeleteAll(d->states);
- d->states.clear();
+ d->savedStates.clear();
d->state = nullptr;
d->engine = nullptr;
d->device = nullptr;
@@ -1759,7 +1713,7 @@ bool QPainter::begin(QPaintDevice *pd)
else if (pd->devType() == QInternal::Image)
static_cast<QImage *>(pd)->detach();
- d->engine = pd->paintEngine();
+ d->engine.reset(pd->paintEngine());
if (!d->engine) {
qWarning("QPainter::begin: Paint device returned engine == 0, type: %d", pd->devType());
@@ -1768,24 +1722,23 @@ bool QPainter::begin(QPaintDevice *pd)
d->device = pd;
- d->extended = d->engine->isExtended() ? static_cast<QPaintEngineEx *>(d->engine) : nullptr;
+ d->extended = d->engine->isExtended() ? static_cast<QPaintEngineEx *>(d->engine.get()) : nullptr;
if (d->emulationEngine)
d->emulationEngine->real_engine = d->extended;
// Setup new state...
Q_ASSERT(!d->state);
- d->state = d->extended ? d->extended->createState(nullptr) : new QPainterState;
+ d->state.reset(d->extended ? d->extended->createState(nullptr) : new QPainterState);
d->state->painter = this;
- d->states.push_back(d->state);
d->state->redirectionMatrix.translate(-redirectionOffset.x(), -redirectionOffset.y());
d->state->brushOrigin = QPointF();
// Slip a painter state into the engine before we do any other operations
if (d->extended)
- d->extended->setState(d->state);
+ d->extended->setState(d->state.get());
else
- d->engine->state = d->state;
+ d->engine->state = d->state.get();
switch (pd->devType()) {
case QInternal::Pixmap:
@@ -1812,9 +1765,12 @@ bool QPainter::begin(QPaintDevice *pd)
qWarning("QPainter::begin: Cannot paint on a null image");
qt_cleanup_painter_state(d);
return false;
- } else if (img->format() == QImage::Format_Indexed8) {
- // Painting on indexed8 images is not supported.
- qWarning("QPainter::begin: Cannot paint on an image with the QImage::Format_Indexed8 format");
+ } else if (img->format() == QImage::Format_Indexed8 ||
+ img->format() == QImage::Format_CMYK8888) {
+ // Painting on these formats is not supported.
+ qWarning() << "QPainter::begin: Cannot paint on an image with the"
+ << img->format()
+ << "format";
qt_cleanup_painter_state(d);
return false;
}
@@ -1869,7 +1825,7 @@ bool QPainter::begin(QPaintDevice *pd)
Q_ASSERT(d->engine->isActive());
- if (!d->state->redirectionMatrix.isIdentity() || d->effectiveDevicePixelRatio() > 1)
+ if (!d->state->redirectionMatrix.isIdentity() || !qFuzzyCompare(d->effectiveDevicePixelRatio(), qreal(1.0)))
d->updateMatrix();
Q_ASSERT(d->engine->isActive());
@@ -1923,23 +1879,13 @@ bool QPainter::end()
}
}
- if (d->states.size() > 1) {
- qWarning("QPainter::end: Painter ended with %d saved states",
- d->states.size());
- }
-
- if (d->engine->autoDestruct()) {
- delete d->engine;
- }
-
- if (d->emulationEngine) {
- delete d->emulationEngine;
- d->emulationEngine = nullptr;
+ if (d->savedStates.size() > 0) {
+ qWarning("QPainter::end: Painter ended with %d saved states", int(d->savedStates.size()));
}
- if (d->extended) {
- d->extended = nullptr;
- }
+ d->engine.reset();
+ d->emulationEngine = nullptr;
+ d->extended = nullptr;
qt_cleanup_painter_state(d);
@@ -1956,7 +1902,7 @@ bool QPainter::end()
QPaintEngine *QPainter::paintEngine() const
{
Q_D(const QPainter);
- return d->engine;
+ return d->engine.get();
}
/*!
@@ -2532,7 +2478,7 @@ QRegion QPainter::clipRegion() const
const_cast<QPainter *>(this)->d_ptr->updateInvMatrix();
// ### Falcon: Use QPainterPath
- for (const QPainterClipInfo &info : qAsConst(d->state->clipInfo)) {
+ for (const QPainterClipInfo &info : std::as_const(d->state->clipInfo)) {
switch (info.clipType) {
case QPainterClipInfo::RegionClip: {
@@ -2699,7 +2645,7 @@ QRectF QPainter::clipBoundingRect() const
// fast.
QRectF bounds;
bool first = true;
- for (const QPainterClipInfo &info : qAsConst(d->state->clipInfo)) {
+ for (const QPainterClipInfo &info : std::as_const(d->state->clipInfo)) {
QRectF r;
if (info.clipType == QPainterClipInfo::RectClip)
@@ -2891,175 +2837,6 @@ void QPainter::setClipRegion(const QRegion &r, Qt::ClipOperation op)
d->updateState(d->state);
}
-#if QT_DEPRECATED_SINCE(5, 13)
-/*!
- \since 4.2
- \obsolete
-
- Sets the transformation matrix to \a matrix and enables transformations.
-
- \note It is advisable to use setWorldTransform() instead of this function to
- preserve the properties of perspective transformations.
-
- If \a combine is true, then \a matrix is combined with the current
- transformation matrix; otherwise \a matrix replaces the current
- transformation matrix.
-
- If \a matrix is the identity matrix and \a combine is false, this
- function calls setWorldMatrixEnabled(false). (The identity matrix is the
- matrix where QMatrix::m11() and QMatrix::m22() are 1.0 and the
- rest are 0.0.)
-
- The following functions can transform the coordinate system without using
- a QMatrix:
- \list
- \li translate()
- \li scale()
- \li shear()
- \li rotate()
- \endlist
-
- They operate on the painter's worldMatrix() and are implemented like this:
-
- \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
- it may not be possible to replay the picture with additional
- transformations; using the translate(), scale(), etc. convenience
- functions is safe.
-
- For more information about the coordinate system, transformations
- and window-viewport conversion, see \l {Coordinate System}.
-
- \sa setWorldTransform(), QTransform
-*/
-
-void QPainter::setWorldMatrix(const QMatrix &matrix, bool combine)
-{
- setWorldTransform(QTransform(matrix), combine);
-}
-
-/*!
- \since 4.2
- \obsolete
-
- Returns the world transformation matrix.
-
- It is advisable to use worldTransform() because worldMatrix() does not
- preserve the properties of perspective transformations.
-
- \sa {QPainter#Coordinate Transformations}{Coordinate Transformations},
- {Coordinate System}
-*/
-
-const QMatrix &QPainter::worldMatrix() const
-{
- Q_D(const QPainter);
- if (!d->engine) {
- qWarning("QPainter::worldMatrix: Painter not active");
- return d->fakeState()->transform.toAffine();
- }
- return d->state->worldMatrix.toAffine();
-}
-
-/*!
- \obsolete
-
- Use setWorldTransform() instead.
-
- \sa setWorldTransform()
-*/
-
-void QPainter::setMatrix(const QMatrix &matrix, bool combine)
-{
- setWorldTransform(QTransform(matrix), combine);
-}
-
-/*!
- \obsolete
-
- Use worldTransform() instead.
-
- \sa worldTransform()
-*/
-
-const QMatrix &QPainter::matrix() const
-{
-QT_WARNING_PUSH
-QT_WARNING_DISABLE_DEPRECATED
- return worldMatrix();
-QT_WARNING_POP
-}
-
-
-/*!
- \since 4.2
- \obsolete
-
- Returns the transformation matrix combining the current
- window/viewport and world transformation.
-
- It is advisable to use combinedTransform() instead of this
- function to preserve the properties of perspective transformations.
-
- \sa setWorldTransform(), setWindow(), setViewport()
-*/
-QMatrix QPainter::combinedMatrix() const
-{
- return combinedTransform().toAffine();
-}
-
-
-/*!
- \obsolete
-
- Returns the matrix that transforms from logical coordinates to
- device coordinates of the platform dependent paint device.
-
- \note It is advisable to use deviceTransform() instead of this
- function to preserve the properties of perspective transformations.
-
- This function is \e only needed when using platform painting
- commands on the platform dependent handle (Qt::HANDLE), and the
- platform does not do transformations nativly.
-
- The QPaintEngine::PaintEngineFeature enum can be queried to
- determine whether the platform performs the transformations or
- not.
-
- \sa worldMatrix(), QPaintEngine::hasFeature(),
-*/
-const QMatrix &QPainter::deviceMatrix() const
-{
- Q_D(const QPainter);
- if (!d->engine) {
- qWarning("QPainter::deviceMatrix: Painter not active");
- return d->fakeState()->transform.toAffine();
- }
- return d->state->matrix.toAffine();
-}
-
-/*!
- \obsolete
-
- Resets any transformations that were made using translate(), scale(),
- shear(), rotate(), setWorldMatrix(), setViewport() and
- setWindow().
-
- It is advisable to use resetTransform() instead of this function
- to preserve the properties of perspective transformations.
-
- \sa {QPainter#Coordinate Transformations}{Coordinate
- Transformations}
-*/
-
-void QPainter::resetMatrix()
-{
- resetTransform();
-}
-#endif
-
/*!
\since 4.2
@@ -3109,34 +2886,6 @@ bool QPainter::worldMatrixEnabled() const
return d->state->WxF;
}
-#if QT_DEPRECATED_SINCE(5, 13)
-/*!
- \obsolete
-
- Use setWorldMatrixEnabled() instead.
-
- \sa setWorldMatrixEnabled()
-*/
-
-void QPainter::setMatrixEnabled(bool enable)
-{
- setWorldMatrixEnabled(enable);
-}
-
-/*!
- \obsolete
-
- Use worldMatrixEnabled() instead
-
- \sa worldMatrixEnabled()
-*/
-
-bool QPainter::matrixEnabled() const
-{
- return worldMatrixEnabled();
-}
-#endif
-
/*!
Scales the coordinate system by (\a{sx}, \a{sy}).
@@ -3275,7 +3024,8 @@ void QPainter::setClipPath(const QPainterPath &path, Qt::ClipOperation op)
return;
}
- if ((!d->state->clipEnabled && op != Qt::NoClip))
+ bool simplifyClipOp = (paintEngine()->type() != QPaintEngine::Picture);
+ if (simplifyClipOp && (!d->state->clipEnabled && op != Qt::NoClip))
op = Qt::ReplaceClip;
if (d->extended) {
@@ -3288,7 +3038,7 @@ void QPainter::setClipPath(const QPainterPath &path, Qt::ClipOperation op)
return;
}
- if (d->state->clipOperation == Qt::NoClip && op == Qt::IntersectClip)
+ if (simplifyClipOp && d->state->clipOperation == Qt::NoClip && op == Qt::IntersectClip)
op = Qt::ReplaceClip;
d->state->clipPath = path;
@@ -3319,12 +3069,9 @@ void QPainter::strokePath(const QPainterPath &path, const QPen &pen)
if (path.isEmpty())
return;
- if (d->extended) {
- const QGradient *g = qpen_brush(pen).gradient();
- if (!g || g->coordinateMode() == QGradient::LogicalMode) {
- d->extended->stroke(qtVectorPathForPath(path), pen);
- return;
- }
+ if (d->extended && !needsEmulation(pen.brush())) {
+ d->extended->stroke(qtVectorPathForPath(path), pen);
+ return;
}
QBrush oldBrush = d->state->brush;
@@ -3362,12 +3109,9 @@ void QPainter::fillPath(const QPainterPath &path, const QBrush &brush)
if (path.isEmpty())
return;
- if (d->extended) {
- const QGradient *g = brush.gradient();
- if (!g || g->coordinateMode() == QGradient::LogicalMode) {
- d->extended->fill(qtVectorPathForPath(path), brush);
- return;
- }
+ if (d->extended && !needsEmulation(brush)) {
+ d->extended->fill(qtVectorPathForPath(path), brush);
+ return;
}
QBrush oldBrush = d->state->brush;
@@ -3629,14 +3373,14 @@ void QPainter::drawRects(const QRect *rects, int rectCount)
}
/*!
- \fn void QPainter::drawRects(const QVector<QRectF> &rectangles)
+ \fn void QPainter::drawRects(const QList<QRectF> &rectangles)
\overload
Draws the given \a rectangles using the current pen and brush.
*/
/*!
- \fn void QPainter::drawRects(const QVector<QRect> &rectangles)
+ \fn void QPainter::drawRects(const QList<QRect> &rectangles)
\overload
@@ -3795,7 +3539,7 @@ void QPainter::drawPoints(const QPoint *points, int pointCount)
\overload
- Draws the points in the vector \a points.
+ Draws the points in the vector \a points.
*/
/*!
@@ -3803,7 +3547,7 @@ void QPainter::drawPoints(const QPoint *points, int pointCount)
\overload
- Draws the points in the vector \a points.
+ Draws the points in the vector \a points.
*/
/*!
@@ -4098,7 +3842,7 @@ void QPainter::setFont(const QFont &font)
#ifdef QT_DEBUG_DRAW
if (qt_show_painter_debug_output)
- printf("QPainter::setFont(), family=%s, pointSize=%d\n", font.family().toLatin1().constData(), font.pointSize());
+ printf("QPainter::setFont(), family=%s, pointSize=%d\n", font.families().first().toLatin1().constData(), font.pointSize());
#endif
if (!d->engine) {
@@ -4158,8 +3902,10 @@ void QPainter::drawRoundedRect(const QRectF &rect, qreal xRadius, qreal yRadius,
#endif
Q_D(QPainter);
- if (!d->engine)
+ if (!d->engine) {
+ qWarning("QPainter::drawRoundedRect: Painter not active");
return;
+ }
if (xRadius <= 0 || yRadius <= 0) { // draw normal rectangle
drawRect(rect);
@@ -4194,54 +3940,6 @@ void QPainter::drawRoundedRect(const QRectF &rect, qreal xRadius, qreal yRadius,
Draws the given rectangle \a x, \a y, \a w, \a h with rounded corners.
*/
-#if QT_DEPRECATED_SINCE(5, 13)
-/*!
- \obsolete
-
- Draws a rectangle \a r with rounded corners.
-
- The \a xRnd and \a yRnd arguments specify how rounded the corners
- should be. 0 is angled corners, 99 is maximum roundedness.
-
- A filled rectangle has a size of r.size(). A stroked rectangle
- has a size of r.size() plus the pen width.
-
- \sa drawRoundedRect()
-*/
-void QPainter::drawRoundRect(const QRectF &r, int xRnd, int yRnd)
-{
- drawRoundedRect(r, xRnd, yRnd, Qt::RelativeSize);
-}
-
-
-/*!
- \fn void QPainter::drawRoundRect(const QRect &r, int xRnd = 25, int yRnd = 25)
-
- \overload
- \obsolete
-
- Draws the rectangle \a r with rounded corners.
-*/
-void QPainter::drawRoundRect(const QRect &rect, int xRnd, int yRnd)
-{
- drawRoundedRect(QRectF(rect), xRnd, yRnd, Qt::RelativeSize);
-}
-
-/*!
- \obsolete
-
- \fn QPainter::drawRoundRect(int x, int y, int w, int h, int xRnd, int yRnd)
-
- \overload
-
- Draws the rectangle \a x, \a y, \a w, \a h with rounded corners.
-*/
-void QPainter::drawRoundRect(int x, int y, int w, int h, int xRnd, int yRnd)
-{
- drawRoundedRect(QRectF(x, y, w, h), xRnd, yRnd, Qt::RelativeSize);
-}
-#endif
-
/*!
\fn void QPainter::drawEllipse(const QRectF &rectangle)
@@ -4268,8 +3966,10 @@ void QPainter::drawEllipse(const QRectF &r)
#endif
Q_D(QPainter);
- if (!d->engine)
+ if (!d->engine) {
+ qWarning("QPainter::drawEllipse: Painter not active");
return;
+ }
QRectF rect(r.normalized());
@@ -4309,8 +4009,10 @@ void QPainter::drawEllipse(const QRect &r)
#endif
Q_D(QPainter);
- if (!d->engine)
+ if (!d->engine) {
+ qWarning("QPainter::drawEllipse: Painter not active");
return;
+ }
QRect rect(r.normalized());
@@ -4396,8 +4098,10 @@ void QPainter::drawArc(const QRectF &r, int a, int alen)
#endif
Q_D(QPainter);
- if (!d->engine)
+ if (!d->engine) {
+ qWarning("QPainter::drawArc: Painter not active");
return;
+ }
QRectF rect = r.normalized();
@@ -4458,8 +4162,10 @@ void QPainter::drawPie(const QRectF &r, int a, int alen)
#endif
Q_D(QPainter);
- if (!d->engine)
+ if (!d->engine) {
+ qWarning("QPainter::drawPie: Painter not active");
return;
+ }
if (a > (360*16)) {
a = a % (360*16);
@@ -4527,8 +4233,10 @@ void QPainter::drawChord(const QRectF &r, int a, int alen)
#endif
Q_D(QPainter);
- if (!d->engine)
+ if (!d->engine) {
+ qWarning("QPainter::drawChord: Painter not active");
return;
+ }
QRectF rect = r.normalized();
@@ -4686,7 +4394,7 @@ void QPainter::drawLines(const QPoint *pointPairs, int lineCount)
/*!
- \fn void QPainter::drawLines(const QVector<QPointF> &pointPairs)
+ \fn void QPainter::drawLines(const QList<QPointF> &pointPairs)
\overload
Draws a line for each pair of points in the vector \a pointPairs
@@ -4695,7 +4403,7 @@ void QPainter::drawLines(const QPoint *pointPairs, int lineCount)
*/
/*!
- \fn void QPainter::drawLines(const QVector<QPoint> &pointPairs)
+ \fn void QPainter::drawLines(const QList<QPoint> &pointPairs)
\overload
Draws a line for each pair of points in the vector \a pointPairs
@@ -4703,7 +4411,7 @@ void QPainter::drawLines(const QPoint *pointPairs, int lineCount)
*/
/*!
- \fn void QPainter::drawLines(const QVector<QLineF> &lines)
+ \fn void QPainter::drawLines(const QList<QLineF> &lines)
\overload
Draws the set of lines defined by the list \a lines using the
@@ -4711,7 +4419,7 @@ void QPainter::drawLines(const QPoint *pointPairs, int lineCount)
*/
/*!
- \fn void QPainter::drawLines(const QVector<QLine> &lines)
+ \fn void QPainter::drawLines(const QList<QLine> &lines)
\overload
Draws the set of lines defined by the list \a lines using the
@@ -5607,40 +5315,31 @@ void QPainter::drawGlyphRun(const QPointF &position, const QGlyphRun &glyphRun)
fixedPointPositions[i] = QFixedPoint::fromPointF(processedPosition);
}
- d->drawGlyphs(glyphIndexes, fixedPointPositions.data(), count, fontD->fontEngine,
- glyphRun.overline(), glyphRun.underline(), glyphRun.strikeOut());
+ d->drawGlyphs(engineRequiresPretransformedGlyphPositions
+ ? d->state->transform().map(position)
+ : position,
+ glyphIndexes,
+ fixedPointPositions.data(),
+ count,
+ fontD->fontEngine,
+ glyphRun.overline(),
+ glyphRun.underline(),
+ glyphRun.strikeOut());
}
-void QPainterPrivate::drawGlyphs(const quint32 *glyphArray, QFixedPoint *positions,
+void QPainterPrivate::drawGlyphs(const QPointF &decorationPosition,
+ const quint32 *glyphArray,
+ QFixedPoint *positions,
int glyphCount,
- QFontEngine *fontEngine, bool overline, bool underline,
+ QFontEngine *fontEngine,
+ bool overline,
+ bool underline,
bool strikeOut)
{
Q_Q(QPainter);
updateState(state);
- QFixed leftMost;
- QFixed rightMost;
- QFixed baseLine;
- for (int i=0; i<glyphCount; ++i) {
- glyph_metrics_t gm = fontEngine->boundingBox(glyphArray[i]);
- if (i == 0 || leftMost > positions[i].x)
- leftMost = positions[i].x;
-
- // 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.
- if (i == 0 || baseLine < positions[i].y)
- baseLine = positions[i].y;
-
- // We use the advance rather than the actual bounds to match the algorithm in drawText()
- if (i == 0 || rightMost < positions[i].x + gm.xoff)
- rightMost = positions[i].x + gm.xoff;
- }
-
- QFixed width = rightMost - leftMost;
-
if (extended != nullptr && state->matrix.isAffine()) {
QStaticTextItem staticTextItem;
staticTextItem.color = state->pen.color();
@@ -5674,21 +5373,15 @@ void QPainterPrivate::drawGlyphs(const quint32 *glyphArray, QFixedPoint *positio
engine->drawTextItem(QPointF(0, 0), textItem);
}
- QTextItemInt::RenderFlags flags;
- if (underline)
- flags |= QTextItemInt::Underline;
- if (overline)
- flags |= QTextItemInt::Overline;
- if (strikeOut)
- flags |= QTextItemInt::StrikeOut;
-
- drawTextItemDecoration(q, QPointF(leftMost.toReal(), baseLine.toReal()),
- fontEngine,
- nullptr, // textEngine
- (underline
- ? QTextCharFormat::SingleUnderline
- : QTextCharFormat::NoUnderline),
- flags, width.toReal(), QTextCharFormat());
+ qt_draw_decoration_for_glyphs(q,
+ decorationPosition,
+ glyphArray,
+ positions,
+ glyphCount,
+ fontEngine,
+ underline,
+ overline,
+ strikeOut);
}
#endif // QT_NO_RAWFONT
@@ -5768,9 +5461,13 @@ void QPainter::drawStaticText(const QPointF &topLeftPosition, const QStaticText
QStaticTextPrivate *staticText_d =
const_cast<QStaticTextPrivate *>(QStaticTextPrivate::get(&staticText));
- if (font() != staticText_d->font) {
+ QFontPrivate *fp = QFontPrivate::get(font());
+ QFontPrivate *stfp = QFontPrivate::get(staticText_d->font);
+ if (font() != staticText_d->font || fp == nullptr || stfp == nullptr || fp->dpi != stfp->dpi) {
staticText_d->font = font();
staticText_d->needsRelayout = true;
+ } else if (stfp->engineData == nullptr || stfp->engineData->fontCacheId != QFontCache::instance()->id()) {
+ staticText_d->needsRelayout = true;
}
QFontEngine *fe = staticText_d->font.d->engineForScript(QChar::Script_Common);
@@ -5868,9 +5565,15 @@ void QPainter::drawStaticText(const QPointF &topLeftPosition, const QStaticText
}
d->extended->drawStaticTextItem(item);
- qt_draw_decoration_for_glyphs(this, item->glyphs, item->glyphPositions,
- item->numGlyphs, item->fontEngine(), staticText_d->font,
- QTextCharFormat());
+ qt_draw_decoration_for_glyphs(this,
+ topLeftPosition,
+ item->glyphs,
+ item->glyphPositions,
+ item->numGlyphs,
+ item->fontEngine(),
+ staticText_d->font.underline(),
+ staticText_d->font.overline(),
+ staticText_d->font.strikeOut());
}
if (currentColor != oldPen.color())
setPen(oldPen);
@@ -5894,22 +5597,6 @@ void QPainter::drawText(const QPointF &p, const QString &str, int tf, int justif
if (!d->engine || str.isEmpty() || pen().style() == Qt::NoPen)
return;
-#if QT_DEPRECATED_SINCE(5, 11) && QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
- if (tf & Qt::TextBypassShaping) {
- // Skip complex shaping, shape using glyph advances only
- int len = str.length();
- int numGlyphs = len;
- QVarLengthGlyphLayoutArray glyphs(len);
- QFontEngine *fontEngine = d->state->font.d->engineForScript(QChar::Script_Common);
- if (!fontEngine->stringToCMap(str.data(), len, &glyphs, &numGlyphs, { }))
- Q_UNREACHABLE();
-
- QTextItemInt gf(glyphs, &d->state->font, str.data(), len, fontEngine);
- drawTextItem(p, gf);
- return;
- }
-#endif
-
QStackTextEngine engine(str, d->state->font);
engine.option.setTextDirection(d->state->layoutDirection);
if (tf & (Qt::TextForceLeftToRight|Qt::TextForceRightToLeft)) {
@@ -5918,7 +5605,7 @@ void QPainter::drawText(const QPointF &p, const QString &str, int tf, int justif
}
engine.itemize();
QScriptLine line;
- line.length = str.length();
+ line.length = str.size();
engine.shapeLine(line);
int nItems = engine.layoutData->items.size();
@@ -5973,7 +5660,7 @@ void QPainter::drawText(const QRect &r, int flags, const QString &str, QRect *br
Q_D(QPainter);
- if (!d->engine || str.length() == 0 || pen().style() == Qt::NoPen)
+ if (!d->engine || str.size() == 0 || pen().style() == Qt::NoPen)
return;
if (!d->extended)
@@ -6060,7 +5747,7 @@ void QPainter::drawText(const QRectF &r, int flags, const QString &str, QRectF *
Q_D(QPainter);
- if (!d->engine || str.length() == 0 || pen().style() == Qt::NoPen)
+ if (!d->engine || str.size() == 0 || pen().style() == Qt::NoPen)
return;
if (!d->extended)
@@ -6160,7 +5847,8 @@ void QPainter::drawText(const QRectF &r, int flags, const QString &str, QRectF *
\overload
Draws the given \a text in the \a rectangle specified using the \a option
- to control its positioning and orientation.
+ to control its positioning, direction, and orientation. The options given
+ in \a option override those set on the QPainter object itself.
By default, QPainter draws text anti-aliased.
@@ -6178,7 +5866,7 @@ void QPainter::drawText(const QRectF &r, const QString &text, const QTextOption
Q_D(QPainter);
- if (!d->engine || text.length() == 0 || pen().style() == Qt::NoPen)
+ if (!d->engine || text.size() == 0 || pen().style() == Qt::NoPen)
return;
if (!d->extended)
@@ -6218,7 +5906,7 @@ void QPainter::drawText(const QRectF &r, const QString &text, const QTextOption
It ignores the font set on the painter as the text item has one of its own.
The underline and strikeout parameters of the text items font are
- ignored aswell. You'll need to pass in the correct flags to get
+ ignored as well. You'll need to pass in the correct flags to get
underlining and strikeout.
*/
@@ -6226,7 +5914,7 @@ static QPixmap generateWavyPixmap(qreal maxRadius, const QPen &pen)
{
const qreal radiusBase = qMax(qreal(1), maxRadius);
- QString key = QLatin1String("WaveUnderline-")
+ QString key = "WaveUnderline-"_L1
% pen.color().name()
% HexString<qreal>(radiusBase)
% HexString<qreal>(pen.widthF());
@@ -6293,12 +5981,6 @@ static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const
QLineF line(qFloor(pos.x()), pos.y(), qFloor(pos.x() + width), pos.y());
- bool wasCompatiblePainting = painter->renderHints()
- & QPainter::Qt4CompatiblePainting;
-
- if (wasCompatiblePainting)
- painter->setRenderHint(QPainter::Qt4CompatiblePainting, false);
-
const qreal underlineOffset = fe->underlinePosition().toReal();
if (underlineStyle == QTextCharFormat::SpellCheckUnderline) {
@@ -6351,6 +6033,9 @@ static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const
if (flags & QTextItem::StrikeOut) {
QLineF strikeOutLine = line;
strikeOutLine.translate(0., - fe->ascent().toReal() / 3.);
+ QColor uc = charFormat.underlineColor();
+ if (uc.isValid())
+ pen.setColor(uc);
painter->setPen(pen);
if (textEngine)
textEngine->addStrikeOut(painter, strikeOutLine);
@@ -6361,6 +6046,9 @@ static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const
if (flags & QTextItem::Overline) {
QLineF overline = line;
overline.translate(0., - fe->ascent().toReal());
+ QColor uc = charFormat.underlineColor();
+ if (uc.isValid())
+ pen.setColor(uc);
painter->setPen(pen);
if (textEngine)
textEngine->addOverline(painter, overline);
@@ -6370,54 +6058,46 @@ static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const
painter->setPen(oldPen);
painter->setBrush(oldBrush);
-
- if (wasCompatiblePainting)
- painter->setRenderHint(QPainter::Qt4CompatiblePainting);
}
-Q_GUI_EXPORT void qt_draw_decoration_for_glyphs(QPainter *painter, const glyph_t *glyphArray,
- const QFixedPoint *positions, int glyphCount,
- QFontEngine *fontEngine, const QFont &font,
- const QTextCharFormat &charFormat)
+static void qt_draw_decoration_for_glyphs(QPainter *painter,
+ const QPointF &decorationPosition,
+ const glyph_t *glyphArray,
+ const QFixedPoint *positions,
+ int glyphCount,
+ QFontEngine *fontEngine,
+ bool underline,
+ bool overline,
+ bool strikeOut)
{
- if (!(font.underline() || font.strikeOut() || font.overline()))
+ if (!underline && !overline && !strikeOut)
return;
- QFixed leftMost;
- QFixed rightMost;
- QFixed baseLine;
- for (int i=0; i<glyphCount; ++i) {
- glyph_metrics_t gm = fontEngine->boundingBox(glyphArray[i]);
- if (i == 0 || leftMost > positions[i].x)
- leftMost = positions[i].x;
-
- // 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 drawTextItemDecoration call per cluster.
- if (i == 0 || baseLine < positions[i].y)
- baseLine = positions[i].y;
-
- // We use the advance rather than the actual bounds to match the algorithm in drawText()
- if (i == 0 || rightMost < positions[i].x + gm.xoff)
- rightMost = positions[i].x + gm.xoff;
- }
-
- QFixed width = rightMost - leftMost;
QTextItem::RenderFlags flags;
-
- if (font.underline())
+ if (underline)
flags |= QTextItem::Underline;
- if (font.overline())
+ if (overline)
flags |= QTextItem::Overline;
- if (font.strikeOut())
+ if (strikeOut)
flags |= QTextItem::StrikeOut;
- drawTextItemDecoration(painter, QPointF(leftMost.toReal(), baseLine.toReal()),
+ bool rtl = positions[glyphCount - 1].x < positions[0].x;
+ QFixed baseline = positions[0].y;
+ glyph_metrics_t gm = fontEngine->boundingBox(glyphArray[rtl ? 0 : glyphCount - 1]);
+
+ qreal width = rtl
+ ? (positions[0].x + gm.xoff - positions[glyphCount - 1].x).toReal()
+ : (positions[glyphCount - 1].x + gm.xoff - positions[0].x).toReal();
+
+ drawTextItemDecoration(painter,
+ QPointF(decorationPosition.x(), baseline.toReal()),
fontEngine,
nullptr, // textEngine
- font.underline() ? QTextCharFormat::SingleUnderline
- : QTextCharFormat::NoUnderline, flags,
- width.toReal(), charFormat);
+ underline ? QTextCharFormat::SingleUnderline
+ : QTextCharFormat::NoUnderline,
+ flags,
+ width,
+ QTextCharFormat());
}
void QPainter::drawTextItem(const QPointF &p, const QTextItem &ti)
@@ -6677,7 +6357,7 @@ QRectF QPainter::boundingRect(const QRectF &r, const QString &text, const QTextO
{
Q_D(QPainter);
- if (!d->engine || text.length() == 0)
+ if (!d->engine || text.size() == 0)
return QRectF(r.x(),r.y(), 0,0);
QRectF br;
@@ -6825,7 +6505,9 @@ void QPainter::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPo
painted on a widget or pixmap can also be stored in a picture.
This function does exactly the same as QPicture::play() when
- called with \a point = QPoint(0, 0).
+ called with \a point = QPointF(0, 0).
+
+ \note The state of the painter is preserved by this function.
\table 100%
\row
@@ -6840,8 +6522,10 @@ void QPainter::drawPicture(const QPointF &p, const QPicture &picture)
{
Q_D(QPainter);
- if (!d->engine)
+ if (!d->engine) {
+ qWarning("QPainter::drawPicture: Painter not active");
return;
+ }
if (!d->extended)
d->updateState(d->state);
@@ -6952,15 +6636,14 @@ void QPainter::fillRect(const QRectF &r, const QBrush &brush)
{
Q_D(QPainter);
- if (!d->engine)
+ if (!d->engine) {
+ qWarning("QPainter::fillRect: Painter not active");
return;
+ }
- if (d->extended) {
- const QGradient *g = brush.gradient();
- if (!g || g->coordinateMode() == QGradient::LogicalMode) {
- d->extended->fillRect(r, brush);
- return;
- }
+ if (d->extended && !needsEmulation(brush)) {
+ d->extended->fillRect(r, brush);
+ return;
}
QPen oldPen = pen();
@@ -6990,15 +6673,14 @@ void QPainter::fillRect(const QRect &r, const QBrush &brush)
{
Q_D(QPainter);
- if (!d->engine)
+ if (!d->engine) {
+ qWarning("QPainter::fillRect: Painter not active");
return;
+ }
- if (d->extended) {
- const QGradient *g = brush.gradient();
- if (!g || g->coordinateMode() == QGradient::LogicalMode) {
- d->extended->fillRect(r, brush);
- return;
- }
+ if (d->extended && !needsEmulation(brush)) {
+ d->extended->fillRect(r, brush);
+ return;
}
QPen oldPen = pen();
@@ -7031,8 +6713,10 @@ void QPainter::fillRect(const QRect &r, const QColor &color)
{
Q_D(QPainter);
- if (!d->engine)
+ if (!d->engine) {
+ qWarning("QPainter::fillRect: Painter not active");
return;
+ }
if (d->extended) {
d->extended->fillRect(r, color);
@@ -7400,89 +7084,6 @@ void QPainter::setViewTransformEnabled(bool enable)
d->updateMatrix();
}
-#if QT_DEPRECATED_SINCE(5, 13)
-/*!
- \threadsafe
-
- \obsolete
-
- Please use QWidget::render() instead.
-
- Redirects all paint commands for the given paint \a device, to the
- \a replacement device. The optional point \a offset defines an
- offset within the source device.
-
- The redirection will not be effective until the begin() function
- has been called; make sure to call end() for the given \a
- device's painter (if any) before redirecting. Call
- restoreRedirected() to restore the previous redirection.
-
- \warning Making use of redirections in the QPainter API implies
- that QPainter::begin() and QPaintDevice destructors need to hold
- a mutex for a short period. This can impact performance. Use of
- QWidget::render is strongly encouraged.
-
- \sa redirected(), restoreRedirected()
-*/
-void QPainter::setRedirected(const QPaintDevice *device,
- QPaintDevice *replacement,
- const QPoint &offset)
-{
- Q_ASSERT(device != nullptr);
- Q_UNUSED(device)
- Q_UNUSED(replacement)
- Q_UNUSED(offset)
- qWarning("QPainter::setRedirected(): ignoring call to deprecated function, use QWidget::render() instead");
-}
-
-/*!
- \threadsafe
-
- \obsolete
-
- Using QWidget::render() obsoletes the use of this function.
-
- Restores the previous redirection for the given \a device after a
- call to setRedirected().
-
- \warning Making use of redirections in the QPainter API implies
- that QPainter::begin() and QPaintDevice destructors need to hold
- a mutex for a short period. This can impact performance. Use of
- QWidget::render is strongly encouraged.
-
- \sa redirected()
- */
-void QPainter::restoreRedirected(const QPaintDevice *device)
-{
- Q_UNUSED(device)
- qWarning("QPainter::restoreRedirected(): ignoring call to deprecated function, use QWidget::render() instead");
-}
-
-/*!
- \threadsafe
-
- \obsolete
-
- Using QWidget::render() obsoletes the use of this function.
-
- Returns the replacement for given \a device. The optional out
- parameter \a offset returns the offset within the replaced device.
-
- \warning Making use of redirections in the QPainter API implies
- that QPainter::begin() and QPaintDevice destructors need to hold
- a mutex for a short period. This can impact performance. Use of
- QWidget::render is strongly encouraged.
-
- \sa setRedirected(), restoreRedirected()
-*/
-QPaintDevice *QPainter::redirected(const QPaintDevice *device, QPoint *offset)
-{
- Q_UNUSED(device)
- Q_UNUSED(offset)
- return nullptr;
-}
-#endif
-
void qt_format_text(const QFont &fnt, const QRectF &_r,
int tf, const QString& str, QRectF *brect,
int tabstops, int *ta, int tabarraylen,
@@ -7554,28 +7155,28 @@ start_lengthVariant:
// compatible behaviour to the old implementation. Replace
// tabs by spaces
int old_offset = offset;
- for (; offset < text.length(); offset++) {
+ for (; offset < text.size(); offset++) {
QChar chr = text.at(offset);
- if (chr == QLatin1Char('\r') || (singleline && chr == QLatin1Char('\n'))) {
- text[offset] = QLatin1Char(' ');
- } else if (chr == QLatin1Char('\n')) {
+ if (chr == u'\r' || (singleline && chr == u'\n')) {
+ text[offset] = u' ';
+ } else if (chr == u'\n') {
text[offset] = QChar::LineSeparator;
- } else if (chr == QLatin1Char('&')) {
+ } else if (chr == u'&') {
++maxUnderlines;
- } else if (chr == QLatin1Char('\t')) {
+ } else if (chr == u'\t') {
if (!expandtabs) {
- text[offset] = QLatin1Char(' ');
+ text[offset] = u' ';
} else if (!tabarraylen && !tabstops) {
- tabstops = qRound(fm.horizontalAdvance(QLatin1Char('x'))*8);
+ tabstops = qRound(fm.horizontalAdvance(u'x')*8);
}
- } else if (chr == QChar(ushort(0x9c))) {
+ } else if (chr == u'\x9c') {
// string with multiple length variants
hasMoreLengthVariants = true;
break;
}
}
- QVector<QTextLayout::FormatRange> underlineFormats;
+ QList<QTextLayout::FormatRange> underlineFormats;
int length = offset - old_offset;
if ((hidemnmemonic || showmnemonic) && maxUnderlines > 0) {
QChar *cout = text.data() + old_offset;
@@ -7583,13 +7184,13 @@ start_lengthVariant:
QChar *cin = cout;
int l = length;
while (l) {
- if (*cin == QLatin1Char('&')) {
+ if (*cin == u'&') {
++cin;
--length;
--l;
if (!l)
break;
- if (*cin != QLatin1Char('&') && !hidemnmemonic && !(tf & Qt::TextDontPrint)) {
+ if (*cin != u'&' && !hidemnmemonic && !(tf & Qt::TextDontPrint)) {
QTextLayout::FormatRange range;
range.start = cout - cout0;
range.length = 1;
@@ -7597,9 +7198,9 @@ start_lengthVariant:
underlineFormats.append(range);
}
#ifdef Q_OS_MAC
- } else if (hidemnmemonic && *cin == QLatin1Char('(') && l >= 4 &&
- cin[1] == QLatin1Char('&') && cin[2] != QLatin1Char('&') &&
- cin[3] == QLatin1Char(')')) {
+ } else if (hidemnmemonic && *cin == u'(' && l >= 4 &&
+ cin[1] == u'&' && cin[2] != u'&' &&
+ cin[3] == u')') {
int n = 0;
while ((cout - n) > cout0 && (cout - n - 1)->isSpace())
++n;
@@ -7660,7 +7261,7 @@ start_lengthVariant:
qreal lineWidth = 0x01000000;
if (wordwrap || (tf & Qt::TextJustificationForced))
lineWidth = qMax<qreal>(0, r.width());
- if(!wordwrap)
+ if (!wordwrap)
tf |= Qt::TextIncludeTrailingSpaces;
textLayout.beginLayout();
@@ -8084,31 +7685,6 @@ QFont QPaintEngineState::font() const
return static_cast<const QPainterState *>(this)->font;
}
-#if QT_DEPRECATED_SINCE(5, 13)
-/*!
- \since 4.2
- \obsolete
-
- Returns the matrix in the current paint engine
- state.
-
- \note It is advisable to use transform() instead of this function to
- preserve the properties of perspective transformations.
-
- This variable should only be used when the state() returns a
- combination which includes the QPaintEngine::DirtyTransform flag.
-
- \sa state(), QPaintEngine::updateState()
-*/
-
-QMatrix QPaintEngineState::matrix() const
-{
- const QPainterState *st = static_cast<const QPainterState *>(this);
-
- return st->matrix.toAffine();
-}
-#endif
-
/*!
\since 4.3
@@ -8589,3 +8165,5 @@ void qt_draw_helper(QPainterPrivate *p, const QPainterPath &path, QPainterPrivat
}
QT_END_NAMESPACE
+
+#include "moc_qpainter.cpp"