diff options
-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 | ||||
-rw-r--r-- | tests/baseline/painting/scripts/pattern_xform.qps | 78 | ||||
-rw-r--r-- | tests/baseline/shared/paintcommands.cpp | 35 | ||||
-rw-r--r-- | tests/baseline/shared/paintcommands.h | 1 |
10 files changed, 134 insertions, 23 deletions
diff --git a/src/gui/image/qpicture.cpp b/src/gui/image/qpicture.cpp index 3f4dec37d5f..da8c5ef1e54 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 6e498bc2e30..35c44b82864 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 cad0fa9fa3a..5b6f5ce2165 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 a5acd6a3246..4192a0fa071 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 abd1a16ade6..c6d723e0c30 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 a38d42c5041..6995f7d1800 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 ce3d1fabdbe..7bcacb4bcaa 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) diff --git a/tests/baseline/painting/scripts/pattern_xform.qps b/tests/baseline/painting/scripts/pattern_xform.qps new file mode 100644 index 00000000000..a12ae05c72a --- /dev/null +++ b/tests/baseline/painting/scripts/pattern_xform.qps @@ -0,0 +1,78 @@ +# Version: 1 +# CheckVsReference: 5% + +#define basic block off screen +save +translate -1000 -1000 +begin_block drawrects +setBrush green Dense4Pattern +drawRect 0 0 40 40 +setBrush green DiagCrossPattern +drawRect 40 0 40 40 +setBrush green VerPattern +brushRotate 30 +drawRect 80 0 40 40 +save +setPen brush 40 SolidLine FlatCap +setBrush NoBrush +drawLine 120 20 160 20 +restore +end_block +restore + +begin_block hintsuite +save +setRenderHint NonCosmeticBrushPatterns false +setRenderHint SmoothPixmapTransform false +translate 10 10 +repeat_block drawrects + +setRenderHint NonCosmeticBrushPatterns false +setRenderHint SmoothPixmapTransform true +translate 0 50 +repeat_block drawrects + +setRenderHint NonCosmeticBrushPatterns true +setRenderHint SmoothPixmapTransform false +translate 0 50 +repeat_block drawrects + +setRenderHint NonCosmeticBrushPatterns true +setRenderHint SmoothPixmapTransform true +translate 0 50 +repeat_block drawrects +restore +end_block + +save +translate 0 200 +scale 2 2 +repeat_block hintsuite +restore + +save +translate 500 0 +scale 1.5 2.5 +rotate_y 60 +repeat_block hintsuite +restore + + +translate 0 650 +setBrush blue CrossPattern +setPen red +setRenderHint NonCosmeticBrushPatterns false + +begin_block dots +save +drawRect 0 0 50 50 +setBrushOrigin 12 0 +drawRect 50 0 50 50 +scale 2 1 +drawRect 50 0 50 50 +restore +end_block dots + +setRenderHint NonCosmeticBrushPatterns true +translate 0 60 +repeat_block dots diff --git a/tests/baseline/shared/paintcommands.cpp b/tests/baseline/shared/paintcommands.cpp index daf58a7c2ea..4a3de0168b9 100644 --- a/tests/baseline/shared/paintcommands.cpp +++ b/tests/baseline/shared/paintcommands.cpp @@ -175,6 +175,12 @@ const char *PaintCommands::imageFormatTable[] = { "RGBA32FPx4_Premultiplied", }; +const char *PaintCommands::renderHintTable[] = { + "Antialiasing", + "SmoothPixmapTransform", + "NonCosmeticBrushPatterns" +}; + int PaintCommands::translateEnum(const char *table[], const QString &pattern, int limit) { QByteArray p = pattern.toLatin1().toLower(); @@ -313,7 +319,7 @@ void PaintCommands::staticInit() "pen_setCosmetic true"); DECL_PAINTCOMMAND("setRenderHint", command_setRenderHint, "^setRenderHint\\s+([\\w_0-9]*)\\s*(\\w*)$", - "setRenderHint <Antialiasing|SmoothPixmapTransform> <true|false>", + "setRenderHint <hint> <true|false>", "setRenderHint Antialiasing true"); DECL_PAINTCOMMAND("clearRenderHint", command_clearRenderHint, "^clearRenderHint$", @@ -665,6 +671,7 @@ void PaintCommands::staticInit() ADD_ENUMLIST("image formats", imageFormatTable); ADD_ENUMLIST("coordinate modes", coordinateMethodTable); ADD_ENUMLIST("size modes", sizeModeTable); + ADD_ENUMLIST("render hints", renderHintTable); } #undef DECL_PAINTCOMMAND @@ -2240,18 +2247,27 @@ void PaintCommands::command_setPen2(QRegularExpressionMatch re) void PaintCommands::command_setRenderHint(QRegularExpressionMatch re) { QString hintString = re.captured(1).toLower(); - bool on = re.captured(2).isEmpty() || re.captured(2).toLower() == "true"; - if (hintString.contains("antialiasing")) { - if (m_verboseMode) - printf(" -(lance) setRenderHint Antialiasing\n"); + QString setting = re.captured(2).toLower(); - m_painter->setRenderHint(QPainter::Antialiasing, on); + bool on = setting.isEmpty() || setting == "true" || setting == "on"; + QPainter::RenderHint hint; + int hintIdx = -1; + if (hintString.contains("antialiasing")) { + hintIdx = 0; + hint = QPainter::Antialiasing; } else if (hintString.contains("smoothpixmaptransform")) { + hintIdx = 1; + hint = QPainter::SmoothPixmapTransform; + } else if (hintString.contains("noncosmeticbrushpatterns")) { + hintIdx = 2; + hint = QPainter::NonCosmeticBrushPatterns; + } + if (hintIdx >= 0) { if (m_verboseMode) - printf(" -(lance) setRenderHint SmoothPixmapTransform\n"); - m_painter->setRenderHint(QPainter::SmoothPixmapTransform, on); + printf(" -(lance) setRenderHint %s %s\n", renderHintTable[hintIdx], on ? "true" : "false"); + m_painter->setRenderHint(hint, on); } else { - fprintf(stderr, "ERROR(setRenderHint): unknown hint '%s'\n", qPrintable(hintString)); + fprintf(stderr, "ERROR(setRenderHint): unknown hint '%s'\n", qPrintable(re.captured(1))); } } @@ -2260,6 +2276,7 @@ void PaintCommands::command_clearRenderHint(QRegularExpressionMatch /*re*/) { m_painter->setRenderHint(QPainter::Antialiasing, false); m_painter->setRenderHint(QPainter::SmoothPixmapTransform, false); + m_painter->setRenderHint(QPainter::NonCosmeticBrushPatterns, false); if (m_verboseMode) printf(" -(lance) clearRenderHint\n"); } diff --git a/tests/baseline/shared/paintcommands.h b/tests/baseline/shared/paintcommands.h index 75f48d3eb7c..0d8044fc470 100644 --- a/tests/baseline/shared/paintcommands.h +++ b/tests/baseline/shared/paintcommands.h @@ -280,6 +280,7 @@ private: static const char *compositionModeTable[]; static const char *imageFormatTable[]; static const char *sizeModeTable[]; + static const char *renderHintTable[]; static int translateEnum(const char *table[], const QString &pattern, int limit); // utility |