summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEirik Aavitsland <[email protected]>2022-06-02 16:40:05 +0200
committerEirik Aavitsland <[email protected]>2022-06-04 21:15:42 +0200
commitf67d89ebde22bdef6d82f7a613f7f0fac794dd45 (patch)
tree90a4e9a18e8ca3891b18db8fa5d355fdfe9c488c
parentf8c5f4b7b57afb3c808a1f3d061eda04960475d8 (diff)
Support cosmetic brush patterns in the pdf and opengl paint engines
This implements the recent functionality extension of painting cosmetic (untransformed) brush patterns, and the corresponding NonCosmeticBrushPatterns render hint, in the pdf and opengl paint engines. As part of the implementation it also fixes a couple of pre-existing bugs in the opengl engine, relating to updating the brush after changes in transformation or brush origin. As a driveby, it also includes a minor fix for the lance testing tool: request stencil buffer, as that is needed and not always provided by default. This echoes a recent fix done to tst_baseline_painting. Change-Id: Ia8811477e015eebeb40ed138bca96643ce1ab0dc Reviewed-by: Allan Sandfeld Jensen <[email protected]>
-rw-r--r--src/gui/painting/qpdf.cpp15
-rw-r--r--src/opengl/qopenglpaintengine.cpp25
-rw-r--r--tests/baseline/painting/scripts/pattern_xform.qps5
-rw-r--r--tests/baseline/painting/scripts/pattern_xform2.qps81
-rw-r--r--tests/manual/lance/main.cpp1
5 files changed, 116 insertions, 11 deletions
diff --git a/src/gui/painting/qpdf.cpp b/src/gui/painting/qpdf.cpp
index ddfec47c6f1..cfb9481ab3c 100644
--- a/src/gui/painting/qpdf.cpp
+++ b/src/gui/painting/qpdf.cpp
@@ -1081,6 +1081,9 @@ void QPdfEngine::updateState(const QPaintEngineState &state)
QPaintEngine::DirtyFlags flags = state.state();
+ if (flags & DirtyHints)
+ flags |= DirtyBrush;
+
if (flags & DirtyTransform)
d->stroker.matrix = state.transform();
@@ -2714,18 +2717,22 @@ int QPdfEnginePrivate::addBrushPattern(const QTransform &m, bool *specifyColor,
*specifyColor = true;
*gStateObject = 0;
- QTransform matrix = m;
+ const Qt::BrushStyle style = brush.style();
+ const bool isCosmetic = style >= Qt::Dense1Pattern && style <= Qt::DiagCrossPattern
+ && !q->painter()->testRenderHint(QPainter::NonCosmeticBrushPatterns);
+ QTransform matrix;
+ if (!isCosmetic)
+ matrix = m;
matrix.translate(brushOrigin.x(), brushOrigin.y());
matrix = matrix * pageMatrix();
- //qDebug() << brushOrigin << matrix;
- Qt::BrushStyle style = brush.style();
if (style == Qt::LinearGradientPattern || style == Qt::RadialGradientPattern) {// && style <= Qt::ConicalGradientPattern) {
*specifyColor = false;
return gradientBrush(brush, matrix, gStateObject);
}
- matrix = brush.transform() * matrix;
+ if (!isCosmetic)
+ matrix = brush.transform() * matrix;
if ((!brush.isOpaque() && brush.style() < Qt::LinearGradientPattern) || opacity != 1.0)
*gStateObject = addConstantAlphaObject(qRound(brush.color().alpha() * opacity),
diff --git a/src/opengl/qopenglpaintengine.cpp b/src/opengl/qopenglpaintengine.cpp
index 01241f19f06..1d9afc51911 100644
--- a/src/opengl/qopenglpaintengine.cpp
+++ b/src/opengl/qopenglpaintengine.cpp
@@ -304,6 +304,7 @@ void QOpenGL2PaintEngineExPrivate::updateBrushUniforms()
return;
QTransform brushQTransform = currentBrush.transform();
+ bool isCosmetic = false;
if (style == Qt::SolidPattern) {
QColor col = qt_premultiplyColor(currentBrush.color(), (GLfloat)q->state()->opacity);
@@ -320,6 +321,8 @@ void QOpenGL2PaintEngineExPrivate::updateBrushUniforms()
QVector2D halfViewportSize(width*0.5, height*0.5);
shaderManager->currentProgram()->setUniformValue(location(QOpenGLEngineShaderManager::HalfViewportSize), halfViewportSize);
+
+ isCosmetic = !q->painter()->testRenderHint(QPainter::NonCosmeticBrushPatterns);
}
else if (style == Qt::LinearGradientPattern) {
const QLinearGradient *g = static_cast<const QLinearGradient *>(currentBrush.gradient());
@@ -394,8 +397,12 @@ void QOpenGL2PaintEngineExPrivate::updateBrushUniforms()
qWarning("QOpenGL2PaintEngineEx: Unimplemented fill style");
const QPointF &brushOrigin = q->state()->brushOrigin;
- QTransform matrix = q->state()->matrix;
+ QTransform matrix;
+ if (!isCosmetic)
+ matrix = q->state()->matrix;
matrix.translate(brushOrigin.x(), brushOrigin.y());
+ if (!isCosmetic)
+ matrix = brushQTransform * matrix;
QTransform translate(1, 0, 0, 1, -translationPoint.x(), -translationPoint.y());
qreal m22 = -1;
@@ -405,7 +412,7 @@ void QOpenGL2PaintEngineExPrivate::updateBrushUniforms()
dy = 0;
}
QTransform gl_to_qt(1, 0, 0, m22, 0, dy);
- QTransform inv_matrix = gl_to_qt * (brushQTransform * matrix).inverted() * translate;
+ QTransform inv_matrix = gl_to_qt * matrix.inverted() * translate;
shaderManager->currentProgram()->setUniformValue(location(QOpenGLEngineShaderManager::BrushTransform), inv_matrix);
shaderManager->currentProgram()->setUniformValue(location(QOpenGLEngineShaderManager::BrushTexture), QT_BRUSH_TEXTURE_UNIT);
@@ -818,8 +825,11 @@ void QOpenGL2PaintEngineExPrivate::fill(const QVectorPath& path)
}
// Might need to call updateMatrix to re-calculate inverseScale
- if (matrixDirty)
+ if (matrixDirty) {
updateMatrix();
+ if (currentBrush.style() > Qt::SolidPattern)
+ brushUniformsDirty = true;
+ }
const bool supportsElementIndexUint = funcs.hasOpenGLExtension(QOpenGLExtensions::ElementIndexUint);
@@ -1419,7 +1429,12 @@ void QOpenGL2PaintEngineExPrivate::stroke(const QVectorPath &path, const QPen &p
void QOpenGL2PaintEngineEx::penChanged() { }
void QOpenGL2PaintEngineEx::brushChanged() { }
-void QOpenGL2PaintEngineEx::brushOriginChanged() { }
+
+void QOpenGL2PaintEngineEx::brushOriginChanged()
+{
+ Q_D(QOpenGL2PaintEngineEx);
+ d->brushUniformsDirty = true;
+}
void QOpenGL2PaintEngineEx::opacityChanged()
{
@@ -1462,7 +1477,7 @@ void QOpenGL2PaintEngineEx::renderHintsChanged()
d->lastTextureUsed = GLuint(-1);
d->brushTextureDirty = true;
-// qDebug("QOpenGL2PaintEngineEx::renderHintsChanged() not implemented!");
+ d->brushUniformsDirty = true;
}
void QOpenGL2PaintEngineEx::transformChanged()
diff --git a/tests/baseline/painting/scripts/pattern_xform.qps b/tests/baseline/painting/scripts/pattern_xform.qps
index a12ae05c72a..224969f1c7e 100644
--- a/tests/baseline/painting/scripts/pattern_xform.qps
+++ b/tests/baseline/painting/scripts/pattern_xform.qps
@@ -9,13 +9,14 @@ setBrush green Dense4Pattern
drawRect 0 0 40 40
setBrush green DiagCrossPattern
drawRect 40 0 40 40
-setBrush green VerPattern
+setBrush green HorPattern
brushRotate 30
drawRect 80 0 40 40
+fillRect 120 0 40 40
save
setPen brush 40 SolidLine FlatCap
setBrush NoBrush
-drawLine 120 20 160 20
+drawLine 160 20 200 20
restore
end_block
restore
diff --git a/tests/baseline/painting/scripts/pattern_xform2.qps b/tests/baseline/painting/scripts/pattern_xform2.qps
new file mode 100644
index 00000000000..4f9314272d4
--- /dev/null
+++ b/tests/baseline/painting/scripts/pattern_xform2.qps
@@ -0,0 +1,81 @@
+# Version: 1
+# CheckVsReference: 5%
+
+# 1: Check brush origin vs (non)cosmetic brush patterns
+
+setBrush blue CrossPattern
+begin_block blockName
+save
+setBrushOrigin 0 0
+fillRect 0 0 32 32
+translate 0 32
+setBrushOrigin 1 0
+fillRect 0 0 32 32
+translate 0 32
+setBrushOrigin 2 0
+fillRect 0 0 32 32
+translate 0 32
+setBrushOrigin 3 0
+fillRect 0 0 32 32
+translate 0 32
+setBrushOrigin 4 0
+fillRect 0 0 32 32
+translate 0 32
+setBrushOrigin 5 0
+fillRect 0 0 32 32
+translate 0 32
+setBrushOrigin 6 0
+fillRect 0 0 32 32
+translate 0 32
+setBrushOrigin 7 0
+fillRect 0 0 32 32
+translate 0 32
+setBrushOrigin 8 0
+fillRect 0 0 32 32
+restore
+end_block blockName
+
+save
+setBrush red CrossPattern
+scale 2 1
+repeat_block blockName
+restore
+
+save
+translate 0 300
+setRenderHint NonCosmeticBrushPatterns true
+setBrush blue CrossPattern
+repeat_block blockName
+setBrush red CrossPattern
+scale 2 1
+repeat_block blockName
+restore
+
+# 2: Check brush update after only xform or hint change
+translate 100 0
+
+save
+setPen NoPen
+setBrush blue DiagCrossPattern
+setRenderHint NonCosmeticBrushPatterns true
+drawRect 10 10 200 100
+scale 10 10
+drawRect 22 1 20 10
+drawRect 22 12 20 10
+setRenderHint NonCosmeticBrushPatterns false
+drawRect 1 12 20 10
+restore
+
+setBrush green DiagCrossPattern
+setPen brush 100 SolidLine FlatCap
+pen_setCosmetic true
+setBrush NoBrush
+translate 0 250
+setRenderHint NonCosmeticBrushPatterns true
+drawLine 10 60 210 60
+scale 10 10
+drawLine 22 6 42 6
+drawLine 22 17 42 17
+setRenderHint NonCosmeticBrushPatterns false
+drawLine 1 17 21 17
+
diff --git a/tests/manual/lance/main.cpp b/tests/manual/lance/main.cpp
index 53f094c5c6f..e6474b10c89 100644
--- a/tests/manual/lance/main.cpp
+++ b/tests/manual/lance/main.cpp
@@ -191,6 +191,7 @@ int main(int argc, char **argv)
DeviceType type = WidgetType;
QSurfaceFormat contextFormat;
+ contextFormat.setStencilBufferSize(8);
bool checkers_background = true;
QImage::Format imageFormat = QImage::Format_ARGB32_Premultiplied;