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(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;