functionality of QskBoxFillNode/QskRectangleNode moved into QskBoxRectangleNode
This commit is contained in:
parent
58344c0c4e
commit
6c391b831d
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
#endif
|
||||
|
||||
#include <QskPaintedNode.h>
|
||||
#include <QskBoxFillNode.h>
|
||||
#include <QskBoxRectangleNode.h>
|
||||
#include <QskGradient.h>
|
||||
#include <QskGradientDirection.h>
|
||||
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
|
|
@ -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 )
|
||||
};
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
Loading…
Reference in New Issue