From 6c391b831d73d67af8ac5c02c839a508219e57c1 Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Tue, 17 Sep 2024 13:57:10 +0200 Subject: [PATCH] functionality of QskBoxFillNode/QskRectangleNode moved into QskBoxRectangleNode --- examples/frames/Frame.cpp | 2 +- examples/iotdashboard/DiagramSkinlet.cpp | 2 +- playground/gradients/GradientView.cpp | 9 +- src/CMakeLists.txt | 3 - src/controls/QskSkinlet.cpp | 6 +- src/nodes/QskBoxFillNode.cpp | 95 ------- src/nodes/QskBoxFillNode.h | 35 --- src/nodes/QskBoxNode.cpp | 20 +- src/nodes/QskBoxRectangleNode.cpp | 308 +++++++++++++---------- src/nodes/QskBoxRectangleNode.h | 20 +- src/nodes/QskBoxRenderer.cpp | 6 + src/nodes/QskRectangleNode.cpp | 105 -------- src/nodes/QskRectangleNode.h | 34 --- 13 files changed, 213 insertions(+), 432 deletions(-) delete mode 100644 src/nodes/QskBoxFillNode.cpp delete mode 100644 src/nodes/QskBoxFillNode.h delete mode 100644 src/nodes/QskRectangleNode.cpp delete mode 100644 src/nodes/QskRectangleNode.h diff --git a/examples/frames/Frame.cpp b/examples/frames/Frame.cpp index ecbfcb1f..4c89f3d3 100644 --- a/examples/frames/Frame.cpp +++ b/examples/frames/Frame.cpp @@ -150,7 +150,7 @@ void Frame::updateFrameNode( const QRectF& rect, QskBoxRectangleNode* node ) const QskBoxBorderColors borderColors( c1, c1, c2, c2 ); const qreal radius = effectiveRadius( rect, m_radius ); - node->updateNode( rect, radius, m_frameWidth, borderColors, m_color ); + node->updateBox( rect, radius, m_frameWidth, borderColors, m_color ); } #include "moc_Frame.cpp" diff --git a/examples/iotdashboard/DiagramSkinlet.cpp b/examples/iotdashboard/DiagramSkinlet.cpp index 964013e2..5e2ab79f 100644 --- a/examples/iotdashboard/DiagramSkinlet.cpp +++ b/examples/iotdashboard/DiagramSkinlet.cpp @@ -173,7 +173,7 @@ QSGNode* DiagramSkinlet::updateChartNode( const Diagram* diagram, QSGNode* node color = diagram->color( barSubcontrol ); const auto shape = diagram->boxShapeHint( barSubcontrol ); - barNode->updateNode( barRect, shape, {}, {}, color ); + barNode->updateFilling( barRect, shape, color ); } } else diff --git a/playground/gradients/GradientView.cpp b/playground/gradients/GradientView.cpp index ad37ca25..78d90fed 100644 --- a/playground/gradients/GradientView.cpp +++ b/playground/gradients/GradientView.cpp @@ -10,7 +10,6 @@ #endif #include -#include #include #include #include @@ -165,15 +164,17 @@ QSGNode* GradientView::updatePaintNode( } case BoxFill: { - auto node = gradientNode< QskBoxFillNode >( oldNode ); - node->updateNode( rect, m_gradient ); + auto node = gradientNode< QskBoxRectangleNode >( oldNode ); + node->setHint( QskFillNode::PreferColoredGeometry, false ); + node->updateFilling( rect, shape, m_gradient ); return node; } case BoxRectangle: { auto node = gradientNode< QskBoxRectangleNode >( oldNode ); - node->updateNode( rect, shape, m_gradient ); + node->setHint( QskFillNode::PreferColoredGeometry, true ); + node->updateFilling( rect, shape, m_gradient ); return node; } diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0b774c94..44198f79 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -107,7 +107,6 @@ list(APPEND HEADERS nodes/QskBasicLinesNode.h nodes/QskBoxNode.h nodes/QskBoxClipNode.h - nodes/QskBoxFillNode.h nodes/QskBoxRectangleNode.h nodes/QskBoxRenderer.h nodes/QskBoxMetrics.h @@ -149,7 +148,6 @@ list(APPEND SOURCES nodes/QskBasicLinesNode.cpp nodes/QskBoxNode.cpp nodes/QskBoxClipNode.cpp - nodes/QskBoxFillNode.cpp nodes/QskBoxRectangleNode.cpp nodes/QskBoxRenderer.cpp nodes/QskBoxMetrics.cpp @@ -164,7 +162,6 @@ list(APPEND SOURCES nodes/QskLinesNode.cpp nodes/QskPaintedNode.cpp nodes/QskPlainTextRenderer.cpp - nodes/QskRectangleNode.cpp nodes/QskRichTextRenderer.cpp nodes/QskSceneTexture.cpp nodes/QskSGNode.cpp diff --git a/src/controls/QskSkinlet.cpp b/src/controls/QskSkinlet.cpp index 48c456a9..a9d74074 100644 --- a/src/controls/QskSkinlet.cpp +++ b/src/controls/QskSkinlet.cpp @@ -22,7 +22,6 @@ #include "QskGraphicNode.h" #include "QskGraphic.h" #include "QskLinesNode.h" -#include "QskRectangleNode.h" #include "QskSGNode.h" #include "QskStippleMetrics.h" #include "QskTextColors.h" @@ -373,8 +372,9 @@ QSGNode* QskSkinlet::updateBackgroundNode( if ( !gradient.isValid() ) return nullptr; - auto rectNode = QskSGNode::ensureNode< QskRectangleNode >( node ); - rectNode->updateNode( rect, gradient ); + auto rectNode = QskSGNode::ensureNode< QskBoxRectangleNode >( node ); + rectNode->updateFilling( rect, QskBoxShapeMetrics(), + QskBoxBorderMetrics(), gradient ); return rectNode; } diff --git a/src/nodes/QskBoxFillNode.cpp b/src/nodes/QskBoxFillNode.cpp deleted file mode 100644 index 7332dbf7..00000000 --- a/src/nodes/QskBoxFillNode.cpp +++ /dev/null @@ -1,95 +0,0 @@ -/****************************************************************************** - * QSkinny - Copyright (C) The authors - * SPDX-License-Identifier: BSD-3-Clause - *****************************************************************************/ - -#include "QskBoxFillNode.h" -#include "QskGradientMaterial.h" -#include "QskGradient.h" -#include "QskGradientDirection.h" -#include "QskBoxShapeMetrics.h" -#include "QskBoxBorderMetrics.h" -#include "QskBoxRenderer.h" -#include "QskFillNodePrivate.h" - -static inline QskHashValue qskMetricsHash( - const QskBoxShapeMetrics& shape, const QskBoxBorderMetrics& borderMetrics ) -{ - QskHashValue hash = 13000; - - hash = shape.hash( hash ); - return borderMetrics.hash( hash ); -} - -class QskBoxFillNodePrivate final : public QskFillNodePrivate -{ - public: - inline void resetValues() - { - rect = QRectF(); - gradientHash = 0; - metricsHash = 0; - } - - QRectF rect; - - QskHashValue gradientHash = 0; - QskHashValue metricsHash = 0; -}; - -QskBoxFillNode::QskBoxFillNode() - : QskFillNode( *new QskBoxFillNodePrivate ) -{ -} - -void QskBoxFillNode::updateNode( const QRectF& rect, const QskGradient& gradient ) -{ - updateNode( rect, QskBoxShapeMetrics(), QskBoxBorderMetrics(), gradient ); -} - -void QskBoxFillNode::updateNode( - const QRectF& rect, const QskBoxShapeMetrics& shapeMetrics, - const QskBoxBorderMetrics& borderMetrics, const QskGradient& gradient ) -{ - Q_D( QskBoxFillNode ); - - if ( rect.isEmpty() || !gradient.isVisible() ) - { - d->resetValues(); - resetGeometry(); - - return; - } - - const auto metricsHash = qskMetricsHash( shapeMetrics, borderMetrics ); - const auto gradientHash = gradient.hash( 22879 ); - - const bool dirtyColors = gradientHash != d->gradientHash; - const bool dirtyMetrics = ( metricsHash != d->metricsHash ) || ( rect != d->rect ); - - d->metricsHash = metricsHash; - d->gradientHash = gradientHash; - d->rect = rect; - - if ( gradient.isMonochrome() ) - { - if ( dirtyColors ) - setColoring( gradient.startColor().toRgb() ); - } - else - { - // dirtyMetrics: the shader also depends on the target rectangle ! - - if ( dirtyColors || dirtyMetrics ) - setColoring( rect, gradient.effectiveGradient() ); - } - - if ( dirtyMetrics ) - { - QskBoxRenderer::renderFillGeometry( - rect, shapeMetrics, borderMetrics, *geometry() ); - - markDirty( QSGNode::DirtyGeometry ); - geometry()->markVertexDataDirty(); - } -} diff --git a/src/nodes/QskBoxFillNode.h b/src/nodes/QskBoxFillNode.h deleted file mode 100644 index d43b82d7..00000000 --- a/src/nodes/QskBoxFillNode.h +++ /dev/null @@ -1,35 +0,0 @@ -/****************************************************************************** - * QSkinny - Copyright (C) The authors - * SPDX-License-Identifier: BSD-3-Clause - *****************************************************************************/ - -#ifndef QSK_BOX_FILL_NODE_H -#define QSK_BOX_FILL_NODE_H - -#include "QskGlobal.h" -#include "QskFillNode.h" - -class QskGradient; -class QskBoxShapeMetrics; -class QskBoxBorderMetrics; - -class QskBoxFillNodePrivate; - -class QSK_EXPORT QskBoxFillNode : public QskFillNode -{ - using Inherited = QskFillNode; - - public: - QskBoxFillNode(); - - void updateNode( const QRectF&, - const QskBoxShapeMetrics&, const QskBoxBorderMetrics&, - const QskGradient& ); - - void updateNode( const QRectF&, const QskGradient& ); - - private: - Q_DECLARE_PRIVATE( QskBoxFillNode ) -}; - -#endif diff --git a/src/nodes/QskBoxNode.cpp b/src/nodes/QskBoxNode.cpp index d2b85a70..5ed2a0cd 100644 --- a/src/nodes/QskBoxNode.cpp +++ b/src/nodes/QskBoxNode.cpp @@ -4,10 +4,8 @@ *****************************************************************************/ #include "QskBoxNode.h" -#include "QskBoxFillNode.h" #include "QskBoxShadowNode.h" #include "QskBoxRectangleNode.h" -#include "QskBoxRenderer.h" #include "QskSGNode.h" #include "QskGradient.h" @@ -67,7 +65,7 @@ void QskBoxNode::updateNode( const QRectF& rect, QskBoxShadowNode* shadowNode = nullptr; QskBoxRectangleNode* rectNode = nullptr; - QskBoxFillNode* fillNode = nullptr; + QskBoxRectangleNode* fillNode = nullptr; if ( !shadowMetrics.isNull() && shadowColor.isValid() && shadowColor.alpha() != 0 ) @@ -77,29 +75,23 @@ void QskBoxNode::updateNode( const QRectF& rect, shape, shadowMetrics.blurRadius(), shadowColor ); } - /* - QskBoxRectangleNode is more efficient and creates batchable geometries. - So we prefer using it where possible. - Note, that the border is always done with a QskBoxRectangleNode - */ - - if ( QskBoxRenderer::isGradientSupported( gradient ) ) + if ( QskBoxRectangleNode::isCombinedGeometrySupported( gradient ) ) { rectNode = qskNode< QskBoxRectangleNode >( this, BoxRole ); - rectNode->updateNode( rect, shape, borderMetrics, borderColors, gradient ); + rectNode->updateBox( rect, shape, borderMetrics, borderColors, gradient ); } else { if ( !borderMetrics.isNull() && borderColors.isVisible() ) { rectNode = qskNode< QskBoxRectangleNode >( this, BoxRole ); - rectNode->updateNode( rect, shape, borderMetrics, borderColors, QskGradient() ); + rectNode->updateBorder( rect, shape, borderMetrics, borderColors ); } if ( gradient.isVisible() ) { - fillNode = qskNode< QskBoxFillNode >( this, FillRole ); - fillNode->updateNode( rect, shape, borderMetrics, gradient ); + fillNode = qskNode< QskBoxRectangleNode >( this, FillRole ); + fillNode->updateFilling( rect, shape, borderMetrics, gradient ); } } diff --git a/src/nodes/QskBoxRectangleNode.cpp b/src/nodes/QskBoxRectangleNode.cpp index da7c8a97..dd5c7fb0 100644 --- a/src/nodes/QskBoxRectangleNode.cpp +++ b/src/nodes/QskBoxRectangleNode.cpp @@ -12,46 +12,55 @@ #include "QskGradientDirection.h" #include "QskFillNodePrivate.h" -static inline QskHashValue qskMetricsHash( - const QskBoxShapeMetrics& shape, const QskBoxBorderMetrics& borderMetrics ) -{ - QskHashValue hash = 13000; - - hash = shape.hash( hash ); - return borderMetrics.hash( hash ); -} - -static inline QskHashValue qskColorsHash( - const QskBoxBorderColors& borderColors, const QskGradient& fillGradient ) -{ - QskHashValue hash = 13000; - hash = borderColors.hash( hash ); - return fillGradient.hash( hash ); -} - -#if 1 - -static inline QskGradient qskEffectiveGradient( const QskGradient& gradient ) -{ - auto g = gradient.effectiveGradient(); - - if ( g.type() != QskGradient::Linear ) - { - qWarning() << "QskBoxRectangleNode does not support radial/conic gradients"; - g.setDirection( QskGradient::Linear ); - } - - return g; -} - -#endif - class QskBoxRectangleNodePrivate final : public QskFillNodePrivate { public: - QskHashValue metricsHash = 0; - QskHashValue colorsHash = 0; - QRectF rect; + inline void resetNode( QskBoxRectangleNode* node ) + { + m_metricsHash = m_colorsHash = 0; + node->resetGeometry(); + } + + bool updateMetrics( const QRectF& rect, + const QskBoxShapeMetrics& shape, const QskBoxBorderMetrics& borderMetrics ) + { + QskHashValue hash = 13000; + + hash = qHashBits( &rect, sizeof( rect ), hash ); + hash = shape.hash( hash ); + hash = borderMetrics.hash( hash ); + + return updateValue( m_metricsHash, hash ); + } + + bool updateColors( const QskBoxBorderColors& borderColors, const QskGradient& gradient ) + { + QskHashValue hash = 13000; + + if ( borderColors.isVisible() ) + hash = borderColors.hash( hash ); + + if ( gradient.isVisible() ) + hash = gradient.hash( hash ); + + return updateValue( m_colorsHash, hash ); + } + + private: + inline bool updateValue( QskHashValue& value, const QskHashValue newValue ) const + { + if ( newValue != value ) + { + value = newValue; + return true; + } + + return false; + } + + public: + QskHashValue m_metricsHash = 0; + QskHashValue m_colorsHash = 0; }; QskBoxRectangleNode::QskBoxRectangleNode() @@ -63,132 +72,163 @@ QskBoxRectangleNode::~QskBoxRectangleNode() { } -void QskBoxRectangleNode::updateNode( - const QRectF& rect, const QskGradient& fillGradient ) +void QskBoxRectangleNode::updateFilling( + const QRectF& rect, const QskGradient& gradient ) { - updateNode( rect, QskBoxShapeMetrics(), QskBoxBorderMetrics(), - QskBoxBorderColors(), fillGradient ); + updateFilling( rect, QskBoxShapeMetrics(), QskBoxBorderMetrics(), gradient ); } -void QskBoxRectangleNode::updateNode( const QRectF& rect, - const QskBoxShapeMetrics& shape, const QskGradient& fillGradient ) +void QskBoxRectangleNode::updateFilling( const QRectF& rect, + const QskBoxShapeMetrics& shape, const QskGradient& gradient ) { - updateNode( rect, shape, QskBoxBorderMetrics(), - QskBoxBorderColors(), fillGradient ); + updateFilling( rect, shape, QskBoxBorderMetrics(), gradient ); } -void QskBoxRectangleNode::updateNode( const QRectF& rect, +void QskBoxRectangleNode::updateFilling( const QRectF& rect, + const QskBoxShapeMetrics& shapeMetrics, const QskBoxBorderMetrics& borderMetrics, + const QskGradient& gradient ) +{ + Q_D( QskBoxRectangleNode ); + + if ( rect.isEmpty() || !gradient.isVisible() ) + { + d->resetNode( this ); + return; + } + + const auto fillGradient = gradient.effectiveGradient(); + const auto shape = shapeMetrics.toAbsolute( rect.size() ); + + const bool coloredGeometry = hasHint( PreferColoredGeometry ) + && QskBoxRenderer::isGradientSupported( fillGradient ); + + const bool dirtyMetrics = d->updateMetrics( rect, shape, borderMetrics ); + const bool dirtyColors = d->updateColors( QskBoxBorderColors(), fillGradient ) + && ( coloredGeometry == isGeometryColored() ); + + if ( dirtyMetrics || dirtyColors ) + { + if ( coloredGeometry ) + { + setColoring( QskFillNode::Polychrome ); + + QskBoxRenderer::renderBox( rect, shape, + borderMetrics, QskBoxBorderColors(), fillGradient, *geometry() ); + + markDirty( QSGNode::DirtyGeometry ); + } + else + { + if ( fillGradient.isMonochrome() ) + { + if ( dirtyColors ) + setColoring( fillGradient.rgbStart() ); + } + else + { + // dirtyMetrics: the shader also depends on rect ! + setColoring( rect, fillGradient ); + } + + if ( dirtyMetrics ) + { + QskBoxRenderer::renderFillGeometry( + rect, shape, borderMetrics, *geometry() ); + + markDirty( QSGNode::DirtyGeometry ); + } + } + } +} + +void QskBoxRectangleNode::updateBorder( const QRectF& rect, + const QskBoxShapeMetrics& shape, const QskBoxBorderMetrics& borderMetrics, + const QskBoxBorderColors& borderColors ) +{ + Q_D( QskBoxRectangleNode ); + + if ( rect.isEmpty() || borderMetrics.isNull() || !borderColors.isVisible() ) + { + d->resetNode( this ); + return; + } + + const bool dirtyMetrics = d->updateMetrics( rect, shape, borderMetrics ); + const bool dirtyColors = d->updateColors( borderColors, QskGradient() ); + + if ( dirtyMetrics || dirtyColors ) + { + const auto coloring = QskFillNode::Polychrome; + + if ( coloring == QskFillNode::Polychrome ) + setColoring( coloring ); + else + setColoring( borderColors.left().rgbStart() ); + + QskBoxRenderer::renderBox( rect, shape, borderMetrics, + borderColors, QskGradient(), *this->geometry() ); + + markDirty( QSGNode::DirtyGeometry ); + } +} + +void QskBoxRectangleNode::updateBox( const QRectF& rect, const QskBoxShapeMetrics& shape, const QskBoxBorderMetrics& borderMetrics, const QskBoxBorderColors& borderColors, const QskGradient& gradient ) { Q_D( QskBoxRectangleNode ); - /* - We supports certain linear gradients only. - Everything else has to be done using QskRectangleNode - */ - const auto fillGradient = qskEffectiveGradient( gradient ); - - const auto metricsHash = qskMetricsHash( shape, borderMetrics ); - const auto colorsHash = qskColorsHash( borderColors, fillGradient ); - - if ( ( metricsHash == d->metricsHash ) && - ( colorsHash == d->colorsHash ) && ( rect == d->rect ) ) - { - return; - } - - d->metricsHash = metricsHash; - d->colorsHash = colorsHash; - d->rect = rect; - - markDirty( QSGNode::DirtyMaterial ); - markDirty( QSGNode::DirtyGeometry ); - if ( rect.isEmpty() ) { - resetGeometry(); + d->resetNode( this ); return; } - bool hasFill = fillGradient.isVisible(); - - bool hasBorder = !borderMetrics.isNull(); - if ( hasBorder ) - { - /* - Wrong as the border width should have an - effect - even if not being visible. TODO ... - */ - - hasBorder = borderColors.isVisible(); - } - - if ( !hasBorder && !hasFill ) - { - resetGeometry(); - return; - } - - const bool isFillMonochrome = hasFill ? fillGradient.isMonochrome() : true; - const bool isBorderMonochrome = hasBorder ? borderColors.isMonochrome() : true; + const bool hasFill = gradient.isVisible(); + const bool hasBorder = !borderMetrics.isNull() && borderColors.isVisible(); if ( hasFill && hasBorder ) { - if ( isFillMonochrome && isBorderMonochrome ) + const bool dirtyMetrics = d->updateMetrics( rect, shape, borderMetrics ); + const bool dirtyColors = d->updateColors( borderColors, gradient ); + + if ( dirtyMetrics || dirtyColors ) { - if ( borderColors.left().rgbStart() == fillGradient.rgbStart() ) + /* + For monochrome border/fiiling with the same color we might be + able to do QskFillNode::Monochrome. However this is not implemeted in + QskBoxRenderer yet. TODO ... + */ + setColoring( QskFillNode::Polychrome ); + + auto fillGradient = gradient.effectiveGradient(); + if ( !QskBoxRenderer::isGradientSupported( fillGradient ) ) { - // we can draw border and background in one - hasBorder = false; + qWarning() << "QskBoxRenderer does not support radial/conic gradients"; + fillGradient.setDirection( QskGradient::Linear ); } + + QskBoxRenderer::renderBox( rect, shape, borderMetrics, + borderColors, fillGradient, *geometry() ); + + markDirty( QSGNode::DirtyGeometry ); } } - - auto coloring = QskFillNode::Polychrome; - -#if 0 - /* - Always using the same material result in a better batching - but wastes some memory. when we have a solid color. - Maybe its worth to introduce a flag to control the behaviour, - but for the moment we go with performance. - */ - - if ( !( hasFill && hasBorder ) ) + else if ( hasFill ) { - if ( ( hasFill && isFillMonochrome ) - || ( hasBorder && !isBorderMonochrome ) - { - coloring = QskFillNode::Monochrome; - } + updateFilling( rect, shape, borderMetrics, gradient ); } -#endif - - auto& geometry = *this->geometry(); - - if ( coloring == QskFillNode::Polychrome ) + else if ( hasBorder ) { - setColoring( coloring ); - - QskBoxRenderer::renderBox( d->rect, shape, borderMetrics, - borderColors, fillGradient, geometry ); + updateBorder( rect, shape, borderMetrics, borderColors ); } else { - if ( hasFill ) - { - setColoring( fillGradient.rgbStart() ); - QskBoxRenderer::renderFillGeometry( - d->rect, shape, QskBoxBorderMetrics(), geometry ); - } - else - { - setColoring( borderColors.left().rgbStart() ); - QskBoxRenderer::renderBorderGeometry( - d->rect, shape, borderMetrics, geometry ); - } + d->resetNode( this ); } - - geometry.markVertexDataDirty(); +} + +bool QskBoxRectangleNode::isCombinedGeometrySupported( const QskGradient& gradient ) +{ + return QskBoxRenderer::isGradientSupported( gradient ); } diff --git a/src/nodes/QskBoxRectangleNode.h b/src/nodes/QskBoxRectangleNode.h index cae20aab..362f1afe 100644 --- a/src/nodes/QskBoxRectangleNode.h +++ b/src/nodes/QskBoxRectangleNode.h @@ -24,15 +24,29 @@ class QSK_EXPORT QskBoxRectangleNode : public QskFillNode QskBoxRectangleNode(); ~QskBoxRectangleNode() override; - void updateNode( const QRectF&, + void updateBox( const QRectF&, const QskBoxShapeMetrics&, const QskBoxBorderMetrics&, const QskBoxBorderColors&, const QskGradient& ); - void updateNode( const QRectF& rect, const QskGradient& ); + void updateBorder( const QRectF&, + const QskBoxShapeMetrics&, const QskBoxBorderMetrics&, + const QskBoxBorderColors& ); - void updateNode( const QRectF& rect, + void updateFilling( const QRectF& rect, const QskGradient& ); + + void updateFilling( const QRectF& rect, const QskBoxShapeMetrics&, const QskGradient& ); + void updateFilling( const QRectF& rect, const QskBoxShapeMetrics&, + const QskBoxBorderMetrics&, const QskGradient& ); + + /* + If true border/filling can be rendered together into the same geometry. + This should not make much difference as the scene graph batches geometries + for the same material anyway. + */ + static bool isCombinedGeometrySupported( const QskGradient& ); + private: Q_DECLARE_PRIVATE( QskBoxRectangleNode ) }; diff --git a/src/nodes/QskBoxRenderer.cpp b/src/nodes/QskBoxRenderer.cpp index 25851170..a1e95e9f 100644 --- a/src/nodes/QskBoxRenderer.cpp +++ b/src/nodes/QskBoxRenderer.cpp @@ -34,6 +34,9 @@ static inline QskVertex::ColoredLine* qskAllocateColoredLines( static inline QskGradient qskEffectiveGradient( const QRectF& rect, const QskGradient& gradient ) { + if ( !gradient.isVisible() ) + return gradient; + const auto dir = gradient.linearDirection(); auto g = gradient; @@ -111,6 +114,7 @@ void QskBoxRenderer::renderBorderGeometry( const QskBoxBorderMetrics& border, QSGGeometry& geometry ) { geometry.setDrawingMode( QSGGeometry::DrawTriangleStrip ); + geometry.markVertexDataDirty(); const QskBoxMetrics metrics( rect, shape, border ); const QskBoxBasicStroker stroker( metrics ); @@ -131,6 +135,7 @@ void QskBoxRenderer::renderFillGeometry( const QskBoxBorderMetrics& border, QSGGeometry& geometry ) { geometry.setDrawingMode( QSGGeometry::DrawTriangleStrip ); + geometry.markVertexDataDirty(); const QskBoxMetrics metrics( rect, shape, border ); QskBoxBasicStroker stroker( metrics ); @@ -153,6 +158,7 @@ void QskBoxRenderer::renderBox( const QRectF& rect, QSGGeometry& geometry ) { geometry.setDrawingMode( QSGGeometry::DrawTriangleStrip ); + geometry.markVertexDataDirty(); const QskBoxMetrics metrics( rect, shape, border ); const auto effectiveGradient = qskEffectiveGradient( metrics.innerRect, gradient ); diff --git a/src/nodes/QskRectangleNode.cpp b/src/nodes/QskRectangleNode.cpp deleted file mode 100644 index ce523b2c..00000000 --- a/src/nodes/QskRectangleNode.cpp +++ /dev/null @@ -1,105 +0,0 @@ -/****************************************************************************** - * QSkinny - Copyright (C) The authors - * SPDX-License-Identifier: BSD-3-Clause - *****************************************************************************/ - -#include "QskRectangleNode.h" -#include "QskGradient.h" -#include "QskBoxRenderer.h" -#include "QskBoxShapeMetrics.h" -#include "QskFillNodePrivate.h" - -class QskRectangleNodePrivate final : public QskFillNodePrivate -{ - public: - inline void resetValues() - { - rect = QRectF(); - shape = QskBoxShapeMetrics(); - gradientHash = 0; - metricsHash = 0; - } - - QRectF rect; - QskBoxShapeMetrics shape; - - QskHashValue gradientHash = 0; - QskHashValue metricsHash = 0; -}; - -QskRectangleNode::QskRectangleNode() - : QskFillNode( *new QskRectangleNodePrivate ) -{ -} - -QskRectangleNode::~QskRectangleNode() -{ -} - -void QskRectangleNode::updateNode( - const QRectF& rect, const QskGradient& gradient ) -{ - updateNode( rect, QskBoxShapeMetrics(), gradient ); -} - -void QskRectangleNode::updateNode( - const QRectF& rect, const QskBoxShapeMetrics& shape, const QskGradient& gradient ) -{ - Q_D( QskRectangleNode ); - - if ( rect.isEmpty() || !gradient.isVisible() ) - { - d->resetValues(); - resetGeometry(); - - return; - } - - const auto effectiveGradient = gradient.effectiveGradient(); - const auto effectiveShape = shape.toAbsolute( rect.size() ); - - const auto gradientHash = effectiveGradient.hash( 54228 ); - const auto metricsHash = effectiveShape.hash( 44564 ); - - const bool dirtyColors = gradientHash != d->gradientHash; - const bool dirtyMetrics = ( rect != d->rect ) || ( metricsHash != d->metricsHash ); - - if ( !( dirtyColors || dirtyMetrics ) ) - return; - - d->gradientHash = gradientHash; - d->metricsHash = metricsHash; - d->rect = rect; - d->shape = effectiveShape; - - if ( QskBoxRenderer::isGradientSupported( effectiveGradient ) ) - { - setColoring( Polychrome ); - - /* - Colors are added to the vertices, while the material does - not depend on the gradient at all - */ - if ( dirtyMetrics || dirtyColors ) - { - QskBoxRenderer::renderBox( rect, - effectiveShape, effectiveGradient, *geometry() ); - - geometry()->markVertexDataDirty(); - markDirty( QSGNode::DirtyGeometry ); - } - } - else - { - if ( dirtyColors || dirtyMetrics ) - setColoring( rect, effectiveGradient ); - - if ( dirtyMetrics ) - { - QskBoxRenderer::renderFillGeometry( rect, effectiveShape, *geometry() ); - - geometry()->markVertexDataDirty(); - markDirty( QSGNode::DirtyGeometry ); - } - } -} diff --git a/src/nodes/QskRectangleNode.h b/src/nodes/QskRectangleNode.h deleted file mode 100644 index 5f2993be..00000000 --- a/src/nodes/QskRectangleNode.h +++ /dev/null @@ -1,34 +0,0 @@ -/****************************************************************************** - * QSkinny - Copyright (C) The authors - * SPDX-License-Identifier: BSD-3-Clause - *****************************************************************************/ - -#ifndef QSK_RECTANGLE_NODE_H -#define QSK_RECTANGLE_NODE_H - -#include "QskGlobal.h" -#include "QskFillNode.h" - -class QskGradient; -class QskBoxShapeMetrics; -class QskRectangleNodePrivate; - -/* - QskRectangleNode is for rounded rectangles without a border. - */ -class QSK_EXPORT QskRectangleNode : public QskFillNode -{ - using Inherited = QskFillNode; - - public: - QskRectangleNode(); - ~QskRectangleNode() override; - - void updateNode( const QRectF&, const QskGradient& ); - void updateNode( const QRectF&, const QskBoxShapeMetrics&, const QskGradient& ); - - private: - Q_DECLARE_PRIVATE( QskRectangleNode ) -}; - -#endif