summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gui/image/qpicture.cpp2
-rw-r--r--src/gui/painting/qdrawhelper.cpp12
-rw-r--r--src/gui/painting/qdrawhelper_p.h2
-rw-r--r--src/gui/painting/qpaintengine_raster.cpp19
-rw-r--r--src/gui/painting/qpaintengine_raster_p.h1
-rw-r--r--src/gui/painting/qpainter.cpp6
-rw-r--r--src/gui/painting/qpainter.h1
-rw-r--r--tests/baseline/painting/scripts/pattern_xform.qps78
-rw-r--r--tests/baseline/shared/paintcommands.cpp35
-rw-r--r--tests/baseline/shared/paintcommands.h1
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