diff options
Diffstat (limited to 'src/gui/painting/qpainter.cpp')
-rw-r--r-- | src/gui/painting/qpainter.cpp | 153 |
1 files changed, 74 insertions, 79 deletions
diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index 731161eff3..f4b9741eed 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** 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> @@ -75,6 +39,7 @@ #include <private/qhexstring_p.h> #include <private/qguiapplication_p.h> #include <private/qrawfont_p.h> +#include <private/qfont_p.h> QT_BEGIN_NAMESPACE @@ -256,7 +221,7 @@ qreal QPainterPrivate::effectiveDevicePixelRatio() const if (device->devType() == QInternal::Printer) return qreal(1); - return qMax(qreal(1), device->devicePixelRatio()); + return device->devicePixelRatio(); } QTransform QPainterPrivate::hidpiScaleTransform() const @@ -416,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; @@ -1160,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 @@ -1448,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} */ @@ -1645,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; @@ -1797,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; } @@ -1854,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()); @@ -2507,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: { @@ -2674,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) @@ -3931,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); @@ -3993,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()); @@ -4034,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()); @@ -4121,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(); @@ -4183,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); @@ -4252,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(); @@ -5478,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); @@ -5618,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(); @@ -5673,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) @@ -5760,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) @@ -5879,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) @@ -6370,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; @@ -6535,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); @@ -6647,8 +6636,10 @@ 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 && !needsEmulation(brush)) { d->extended->fillRect(r, brush); @@ -6682,8 +6673,10 @@ 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 && !needsEmulation(brush)) { d->extended->fillRect(r, brush); @@ -6720,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); @@ -7160,7 +7155,7 @@ 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 == u'\r' || (singleline && chr == u'\n')) { text[offset] = u' '; |