diff options
author | Eirik Aavitsland <eirik.aavitsland@qt.io> | 2022-05-20 16:47:42 +0200 |
---|---|---|
committer | Eirik Aavitsland <eirik.aavitsland@qt.io> | 2022-05-31 21:20:41 +0200 |
commit | 5adaa8d868b6718e07035152351b14449cea95d3 (patch) | |
tree | 3b08ac3e7db2c9c0850c8026dcad0a53a4dc33bf /src | |
parent | 5e48a51608485cbc87b68498fd54ab36f001d584 (diff) |
Add painter render hint for brush pattern transformation
[ChangeLog][QtGui][QPainter] In Qt 5, the predefined brush patterns
would always be transformed along with the object being painted. In Qt
6.0 onwards, they would or would not, depending on the
SmoothPixmapTransformation render hint. Instead of this somewhat
surprising behavior, make the default be untransformed
(i.e. cosmetic), which makes sense when it comes to dpr scaling. For
the cases where one wants scaling, a new render hint is introduced to
enable that: NonCosmeticPatternBrushes.
Change-Id: I2208c7a28af9056d7ab97a529b66bf2d502c3c4f
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'src')
-rw-r--r-- | src/gui/image/qpicture.cpp | 2 | ||||
-rw-r--r-- | src/gui/painting/qdrawhelper.cpp | 12 | ||||
-rw-r--r-- | src/gui/painting/qdrawhelper_p.h | 2 | ||||
-rw-r--r-- | src/gui/painting/qpaintengine_raster.cpp | 19 | ||||
-rw-r--r-- | src/gui/painting/qpaintengine_raster_p.h | 1 | ||||
-rw-r--r-- | src/gui/painting/qpainter.cpp | 6 | ||||
-rw-r--r-- | src/gui/painting/qpainter.h | 1 |
7 files changed, 29 insertions, 14 deletions
diff --git a/src/gui/image/qpicture.cpp b/src/gui/image/qpicture.cpp index 3f4dec37d5..da8c5ef1e5 100644 --- a/src/gui/image/qpicture.cpp +++ b/src/gui/image/qpicture.cpp @@ -814,6 +814,8 @@ bool QPicture::exec(QPainter *painter, QDataStream &s, int nrecords) bool(ul & QPainter::Antialiasing)); painter->setRenderHint(QPainter::SmoothPixmapTransform, bool(ul & QPainter::SmoothPixmapTransform)); + painter->setRenderHint(QPainter::NonCosmeticBrushPatterns, + bool(ul & QPainter::NonCosmeticBrushPatterns)); break; case QPicturePrivate::PdcSetCompositionMode: s >> ul; diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index 6e498bc2e3..35c44b8286 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -3581,20 +3581,20 @@ static const CompositionFunctionFP *functionForModeFP = qt_functionForModeFP_C; static TextureBlendType getBlendType(const QSpanData *data) { TextureBlendType ft; - if (data->txop <= QTransform::TxTranslate) - if (data->texture.type == QTextureData::Tiled || data->texture.type == QTextureData::Pattern) + if (data->texture.type == QTextureData::Pattern) + ft = BlendTiled; + else if (data->txop <= QTransform::TxTranslate) + if (data->texture.type == QTextureData::Tiled) ft = BlendTiled; else ft = BlendUntransformed; else if (data->bilinear) - if (data->texture.type == QTextureData::Tiled || data->texture.type == QTextureData::Pattern) + if (data->texture.type == QTextureData::Tiled) ft = BlendTransformedBilinearTiled; else ft = BlendTransformedBilinear; else - if (data->texture.type == QTextureData::Pattern) - ft = BlendTiled; - else if (data->texture.type == QTextureData::Tiled) + if (data->texture.type == QTextureData::Tiled) ft = BlendTransformedTiled; else ft = BlendTransformed; diff --git a/src/gui/painting/qdrawhelper_p.h b/src/gui/painting/qdrawhelper_p.h index cad0fa9fa3..5b6f5ce216 100644 --- a/src/gui/painting/qdrawhelper_p.h +++ b/src/gui/painting/qdrawhelper_p.h @@ -345,7 +345,7 @@ struct QSpanData void init(QRasterBuffer *rb, const QRasterPaintEngine *pe); - void setup(const QBrush &brush, int alpha, QPainter::CompositionMode compositionMode); + void setup(const QBrush &brush, int alpha, QPainter::CompositionMode compositionMode, bool isCosmetic); void setupMatrix(const QTransform &matrix, int bilinear); void initTexture(const QImage *image, int alpha, QTextureData::Type = QTextureData::Plain, const QRect &sourceRect = QRect()); void adjustSpanMethods(); diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index a5acd6a324..4192a0fa07 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -426,12 +426,12 @@ bool QRasterPaintEngine::begin(QPaintDevice *device) d->rasterizer->setClipRect(d->deviceRect); s->penData.init(d->rasterBuffer.data(), this); - s->penData.setup(s->pen.brush(), s->intOpacity, s->composition_mode); + s->penData.setup(s->pen.brush(), s->intOpacity, s->composition_mode, s->flags.cosmetic_brush); s->stroker = &d->basicStroker; d->basicStroker.setClipRect(d->deviceRect); s->brushData.init(d->rasterBuffer.data(), this); - s->brushData.setup(s->brush, s->intOpacity, s->composition_mode); + s->brushData.setup(s->brush, s->intOpacity, s->composition_mode, s->flags.cosmetic_brush); d->rasterBuffer->compositionMode = QPainter::CompositionMode_SourceOver; @@ -523,6 +523,7 @@ QRasterPaintEngineState::QRasterPaintEngineState() flags.fast_text = true; flags.tx_noshear = true; flags.fast_images = true; + flags.cosmetic_brush = true; clip = nullptr; flags.has_clip_ownership = false; @@ -621,7 +622,8 @@ void QRasterPaintEngine::updatePen(const QPen &pen) s->strokeFlags = 0; s->penData.clip = d->clip(); - s->penData.setup(pen_style == Qt::NoPen ? QBrush() : pen.brush(), s->intOpacity, s->composition_mode); + s->penData.setup(pen_style == Qt::NoPen ? QBrush() : pen.brush(), s->intOpacity, + s->composition_mode, s->flags.cosmetic_brush); if (s->strokeFlags & QRasterPaintEngine::DirtyTransform || pen.brush().transform().type() >= QTransform::TxNone) { @@ -720,7 +722,7 @@ void QRasterPaintEngine::updateBrush(const QBrush &brush) QRasterPaintEngineState *s = state(); // must set clip prior to setup, as setup uses it... s->brushData.clip = d->clip(); - s->brushData.setup(brush, s->intOpacity, s->composition_mode); + s->brushData.setup(brush, s->intOpacity, s->composition_mode, s->flags.cosmetic_brush); if (s->fillFlags & DirtyTransform || brush.transform().type() >= QTransform::TxNone) d_func()->updateMatrixData(&s->brushData, brush, d->brushMatrix()); @@ -807,14 +809,16 @@ void QRasterPaintEngine::renderHintsChanged() bool was_aa = s->flags.antialiased; bool was_bilinear = s->flags.bilinear; + bool was_cosmetic_brush = s->flags.cosmetic_brush; s->flags.antialiased = bool(s->renderHints & QPainter::Antialiasing); s->flags.bilinear = bool(s->renderHints & QPainter::SmoothPixmapTransform); + s->flags.cosmetic_brush = !bool(s->renderHints & QPainter::NonCosmeticBrushPatterns); if (was_aa != s->flags.antialiased) s->strokeFlags |= DirtyHints; - if (was_bilinear != s->flags.bilinear) { + if (was_bilinear != s->flags.bilinear || was_cosmetic_brush != s->flags.cosmetic_brush) { s->strokeFlags |= DirtyPen; s->fillFlags |= DirtyBrush; } @@ -4472,7 +4476,8 @@ void QSpanData::init(QRasterBuffer *rb, const QRasterPaintEngine *pe) Q_GUI_EXPORT extern QImage qt_imageForBrush(int brushStyle, bool invert); -void QSpanData::setup(const QBrush &brush, int alpha, QPainter::CompositionMode compositionMode) +void QSpanData::setup(const QBrush &brush, int alpha, QPainter::CompositionMode compositionMode, + bool isCosmetic) { Qt::BrushStyle brushStyle = qbrush_style(brush); cachedGradient.reset(); @@ -4579,7 +4584,7 @@ void QSpanData::setup(const QBrush &brush, int alpha, QPainter::CompositionMode if (!tempImage) tempImage = new QImage(); *tempImage = rasterBuffer->colorizeBitmap(qt_imageForBrush(brushStyle, true), brush.color()); - initTexture(tempImage, alpha, QTextureData::Pattern); + initTexture(tempImage, alpha, isCosmetic ? QTextureData::Pattern : QTextureData::Tiled); break; case Qt::TexturePattern: type = Texture; diff --git a/src/gui/painting/qpaintengine_raster_p.h b/src/gui/painting/qpaintengine_raster_p.h index abd1a16ade..c6d723e0c3 100644 --- a/src/gui/painting/qpaintengine_raster_p.h +++ b/src/gui/painting/qpaintengine_raster_p.h @@ -76,6 +76,7 @@ public: uint fast_text : 1; uint tx_noshear : 1; uint fast_images : 1; + uint cosmetic_brush : 1; }; union { diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index a38d42c504..6995f7d180 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -1412,6 +1412,12 @@ 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} diff --git a/src/gui/painting/qpainter.h b/src/gui/painting/qpainter.h index ce3d1fabdb..7bcacb4bca 100644 --- a/src/gui/painting/qpainter.h +++ b/src/gui/painting/qpainter.h @@ -54,6 +54,7 @@ public: SmoothPixmapTransform = 0x04, VerticalSubpixelPositioning = 0x08, LosslessImageRendering = 0x40, + NonCosmeticBrushPatterns = 0x80 }; Q_ENUM(RenderHint) |