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 QskBoxBorderColors borderColors( c1, c1, c2, c2 );
|
||||||
const qreal radius = effectiveRadius( rect, m_radius );
|
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"
|
#include "moc_Frame.cpp"
|
||||||
|
|
|
||||||
|
|
@ -173,7 +173,7 @@ QSGNode* DiagramSkinlet::updateChartNode( const Diagram* diagram, QSGNode* node
|
||||||
color = diagram->color( barSubcontrol );
|
color = diagram->color( barSubcontrol );
|
||||||
|
|
||||||
const auto shape = diagram->boxShapeHint( barSubcontrol );
|
const auto shape = diagram->boxShapeHint( barSubcontrol );
|
||||||
barNode->updateNode( barRect, shape, {}, {}, color );
|
barNode->updateFilling( barRect, shape, color );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,6 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <QskPaintedNode.h>
|
#include <QskPaintedNode.h>
|
||||||
#include <QskBoxFillNode.h>
|
|
||||||
#include <QskBoxRectangleNode.h>
|
#include <QskBoxRectangleNode.h>
|
||||||
#include <QskGradient.h>
|
#include <QskGradient.h>
|
||||||
#include <QskGradientDirection.h>
|
#include <QskGradientDirection.h>
|
||||||
|
|
@ -165,15 +164,17 @@ QSGNode* GradientView::updatePaintNode(
|
||||||
}
|
}
|
||||||
case BoxFill:
|
case BoxFill:
|
||||||
{
|
{
|
||||||
auto node = gradientNode< QskBoxFillNode >( oldNode );
|
auto node = gradientNode< QskBoxRectangleNode >( oldNode );
|
||||||
node->updateNode( rect, m_gradient );
|
node->setHint( QskFillNode::PreferColoredGeometry, false );
|
||||||
|
node->updateFilling( rect, shape, m_gradient );
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
case BoxRectangle:
|
case BoxRectangle:
|
||||||
{
|
{
|
||||||
auto node = gradientNode< QskBoxRectangleNode >( oldNode );
|
auto node = gradientNode< QskBoxRectangleNode >( oldNode );
|
||||||
node->updateNode( rect, shape, m_gradient );
|
node->setHint( QskFillNode::PreferColoredGeometry, true );
|
||||||
|
node->updateFilling( rect, shape, m_gradient );
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -107,7 +107,6 @@ list(APPEND HEADERS
|
||||||
nodes/QskBasicLinesNode.h
|
nodes/QskBasicLinesNode.h
|
||||||
nodes/QskBoxNode.h
|
nodes/QskBoxNode.h
|
||||||
nodes/QskBoxClipNode.h
|
nodes/QskBoxClipNode.h
|
||||||
nodes/QskBoxFillNode.h
|
|
||||||
nodes/QskBoxRectangleNode.h
|
nodes/QskBoxRectangleNode.h
|
||||||
nodes/QskBoxRenderer.h
|
nodes/QskBoxRenderer.h
|
||||||
nodes/QskBoxMetrics.h
|
nodes/QskBoxMetrics.h
|
||||||
|
|
@ -149,7 +148,6 @@ list(APPEND SOURCES
|
||||||
nodes/QskBasicLinesNode.cpp
|
nodes/QskBasicLinesNode.cpp
|
||||||
nodes/QskBoxNode.cpp
|
nodes/QskBoxNode.cpp
|
||||||
nodes/QskBoxClipNode.cpp
|
nodes/QskBoxClipNode.cpp
|
||||||
nodes/QskBoxFillNode.cpp
|
|
||||||
nodes/QskBoxRectangleNode.cpp
|
nodes/QskBoxRectangleNode.cpp
|
||||||
nodes/QskBoxRenderer.cpp
|
nodes/QskBoxRenderer.cpp
|
||||||
nodes/QskBoxMetrics.cpp
|
nodes/QskBoxMetrics.cpp
|
||||||
|
|
@ -164,7 +162,6 @@ list(APPEND SOURCES
|
||||||
nodes/QskLinesNode.cpp
|
nodes/QskLinesNode.cpp
|
||||||
nodes/QskPaintedNode.cpp
|
nodes/QskPaintedNode.cpp
|
||||||
nodes/QskPlainTextRenderer.cpp
|
nodes/QskPlainTextRenderer.cpp
|
||||||
nodes/QskRectangleNode.cpp
|
|
||||||
nodes/QskRichTextRenderer.cpp
|
nodes/QskRichTextRenderer.cpp
|
||||||
nodes/QskSceneTexture.cpp
|
nodes/QskSceneTexture.cpp
|
||||||
nodes/QskSGNode.cpp
|
nodes/QskSGNode.cpp
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,6 @@
|
||||||
#include "QskGraphicNode.h"
|
#include "QskGraphicNode.h"
|
||||||
#include "QskGraphic.h"
|
#include "QskGraphic.h"
|
||||||
#include "QskLinesNode.h"
|
#include "QskLinesNode.h"
|
||||||
#include "QskRectangleNode.h"
|
|
||||||
#include "QskSGNode.h"
|
#include "QskSGNode.h"
|
||||||
#include "QskStippleMetrics.h"
|
#include "QskStippleMetrics.h"
|
||||||
#include "QskTextColors.h"
|
#include "QskTextColors.h"
|
||||||
|
|
@ -373,8 +372,9 @@ QSGNode* QskSkinlet::updateBackgroundNode(
|
||||||
if ( !gradient.isValid() )
|
if ( !gradient.isValid() )
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
auto rectNode = QskSGNode::ensureNode< QskRectangleNode >( node );
|
auto rectNode = QskSGNode::ensureNode< QskBoxRectangleNode >( node );
|
||||||
rectNode->updateNode( rect, gradient );
|
rectNode->updateFilling( rect, QskBoxShapeMetrics(),
|
||||||
|
QskBoxBorderMetrics(), gradient );
|
||||||
|
|
||||||
return rectNode;
|
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 "QskBoxNode.h"
|
||||||
#include "QskBoxFillNode.h"
|
|
||||||
#include "QskBoxShadowNode.h"
|
#include "QskBoxShadowNode.h"
|
||||||
#include "QskBoxRectangleNode.h"
|
#include "QskBoxRectangleNode.h"
|
||||||
#include "QskBoxRenderer.h"
|
|
||||||
#include "QskSGNode.h"
|
#include "QskSGNode.h"
|
||||||
|
|
||||||
#include "QskGradient.h"
|
#include "QskGradient.h"
|
||||||
|
|
@ -67,7 +65,7 @@ void QskBoxNode::updateNode( const QRectF& rect,
|
||||||
|
|
||||||
QskBoxShadowNode* shadowNode = nullptr;
|
QskBoxShadowNode* shadowNode = nullptr;
|
||||||
QskBoxRectangleNode* rectNode = nullptr;
|
QskBoxRectangleNode* rectNode = nullptr;
|
||||||
QskBoxFillNode* fillNode = nullptr;
|
QskBoxRectangleNode* fillNode = nullptr;
|
||||||
|
|
||||||
if ( !shadowMetrics.isNull()
|
if ( !shadowMetrics.isNull()
|
||||||
&& shadowColor.isValid() && shadowColor.alpha() != 0 )
|
&& shadowColor.isValid() && shadowColor.alpha() != 0 )
|
||||||
|
|
@ -77,29 +75,23 @@ void QskBoxNode::updateNode( const QRectF& rect,
|
||||||
shape, shadowMetrics.blurRadius(), shadowColor );
|
shape, shadowMetrics.blurRadius(), shadowColor );
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
if ( QskBoxRectangleNode::isCombinedGeometrySupported( gradient ) )
|
||||||
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 ) )
|
|
||||||
{
|
{
|
||||||
rectNode = qskNode< QskBoxRectangleNode >( this, BoxRole );
|
rectNode = qskNode< QskBoxRectangleNode >( this, BoxRole );
|
||||||
rectNode->updateNode( rect, shape, borderMetrics, borderColors, gradient );
|
rectNode->updateBox( rect, shape, borderMetrics, borderColors, gradient );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ( !borderMetrics.isNull() && borderColors.isVisible() )
|
if ( !borderMetrics.isNull() && borderColors.isVisible() )
|
||||||
{
|
{
|
||||||
rectNode = qskNode< QskBoxRectangleNode >( this, BoxRole );
|
rectNode = qskNode< QskBoxRectangleNode >( this, BoxRole );
|
||||||
rectNode->updateNode( rect, shape, borderMetrics, borderColors, QskGradient() );
|
rectNode->updateBorder( rect, shape, borderMetrics, borderColors );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( gradient.isVisible() )
|
if ( gradient.isVisible() )
|
||||||
{
|
{
|
||||||
fillNode = qskNode< QskBoxFillNode >( this, FillRole );
|
fillNode = qskNode< QskBoxRectangleNode >( this, FillRole );
|
||||||
fillNode->updateNode( rect, shape, borderMetrics, gradient );
|
fillNode->updateFilling( rect, shape, borderMetrics, gradient );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,46 +12,55 @@
|
||||||
#include "QskGradientDirection.h"
|
#include "QskGradientDirection.h"
|
||||||
#include "QskFillNodePrivate.h"
|
#include "QskFillNodePrivate.h"
|
||||||
|
|
||||||
static inline QskHashValue qskMetricsHash(
|
class QskBoxRectangleNodePrivate final : public QskFillNodePrivate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
inline void resetNode( QskBoxRectangleNode* node )
|
||||||
|
{
|
||||||
|
m_metricsHash = m_colorsHash = 0;
|
||||||
|
node->resetGeometry();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool updateMetrics( const QRectF& rect,
|
||||||
const QskBoxShapeMetrics& shape, const QskBoxBorderMetrics& borderMetrics )
|
const QskBoxShapeMetrics& shape, const QskBoxBorderMetrics& borderMetrics )
|
||||||
{
|
{
|
||||||
QskHashValue hash = 13000;
|
QskHashValue hash = 13000;
|
||||||
|
|
||||||
|
hash = qHashBits( &rect, sizeof( rect ), hash );
|
||||||
hash = shape.hash( hash );
|
hash = shape.hash( hash );
|
||||||
return borderMetrics.hash( hash );
|
hash = borderMetrics.hash( hash );
|
||||||
|
|
||||||
|
return updateValue( m_metricsHash, hash );
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline QskHashValue qskColorsHash(
|
bool updateColors( const QskBoxBorderColors& borderColors, const QskGradient& gradient )
|
||||||
const QskBoxBorderColors& borderColors, const QskGradient& fillGradient )
|
|
||||||
{
|
{
|
||||||
QskHashValue hash = 13000;
|
QskHashValue hash = 13000;
|
||||||
|
|
||||||
|
if ( borderColors.isVisible() )
|
||||||
hash = borderColors.hash( hash );
|
hash = borderColors.hash( hash );
|
||||||
return fillGradient.hash( hash );
|
|
||||||
|
if ( gradient.isVisible() )
|
||||||
|
hash = gradient.hash( hash );
|
||||||
|
|
||||||
|
return updateValue( m_colorsHash, hash );
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 1
|
private:
|
||||||
|
inline bool updateValue( QskHashValue& value, const QskHashValue newValue ) const
|
||||||
static inline QskGradient qskEffectiveGradient( const QskGradient& gradient )
|
|
||||||
{
|
{
|
||||||
auto g = gradient.effectiveGradient();
|
if ( newValue != value )
|
||||||
|
|
||||||
if ( g.type() != QskGradient::Linear )
|
|
||||||
{
|
{
|
||||||
qWarning() << "QskBoxRectangleNode does not support radial/conic gradients";
|
value = newValue;
|
||||||
g.setDirection( QskGradient::Linear );
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return g;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
class QskBoxRectangleNodePrivate final : public QskFillNodePrivate
|
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
QskHashValue metricsHash = 0;
|
QskHashValue m_metricsHash = 0;
|
||||||
QskHashValue colorsHash = 0;
|
QskHashValue m_colorsHash = 0;
|
||||||
QRectF rect;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
QskBoxRectangleNode::QskBoxRectangleNode()
|
QskBoxRectangleNode::QskBoxRectangleNode()
|
||||||
|
|
@ -63,132 +72,163 @@ QskBoxRectangleNode::~QskBoxRectangleNode()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void QskBoxRectangleNode::updateNode(
|
void QskBoxRectangleNode::updateFilling(
|
||||||
const QRectF& rect, const QskGradient& fillGradient )
|
const QRectF& rect, const QskGradient& gradient )
|
||||||
{
|
{
|
||||||
updateNode( rect, QskBoxShapeMetrics(), QskBoxBorderMetrics(),
|
updateFilling( rect, QskBoxShapeMetrics(), QskBoxBorderMetrics(), gradient );
|
||||||
QskBoxBorderColors(), fillGradient );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void QskBoxRectangleNode::updateNode( const QRectF& rect,
|
void QskBoxRectangleNode::updateFilling( const QRectF& rect,
|
||||||
const QskBoxShapeMetrics& shape, const QskGradient& fillGradient )
|
const QskBoxShapeMetrics& shape, const QskGradient& gradient )
|
||||||
{
|
{
|
||||||
updateNode( rect, shape, QskBoxBorderMetrics(),
|
updateFilling( rect, shape, QskBoxBorderMetrics(), gradient );
|
||||||
QskBoxBorderColors(), fillGradient );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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 QskBoxShapeMetrics& shape, const QskBoxBorderMetrics& borderMetrics,
|
||||||
const QskBoxBorderColors& borderColors, const QskGradient& gradient )
|
const QskBoxBorderColors& borderColors, const QskGradient& gradient )
|
||||||
{
|
{
|
||||||
Q_D( QskBoxRectangleNode );
|
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() )
|
if ( rect.isEmpty() )
|
||||||
{
|
{
|
||||||
resetGeometry();
|
d->resetNode( this );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasFill = fillGradient.isVisible();
|
const bool hasFill = gradient.isVisible();
|
||||||
|
const bool hasBorder = !borderMetrics.isNull() && borderColors.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;
|
|
||||||
|
|
||||||
if ( hasFill && hasBorder )
|
if ( hasFill && hasBorder )
|
||||||
{
|
{
|
||||||
if ( isFillMonochrome && isBorderMonochrome )
|
const bool dirtyMetrics = d->updateMetrics( rect, shape, borderMetrics );
|
||||||
{
|
const bool dirtyColors = d->updateColors( borderColors, gradient );
|
||||||
if ( borderColors.left().rgbStart() == fillGradient.rgbStart() )
|
|
||||||
{
|
|
||||||
// we can draw border and background in one
|
|
||||||
hasBorder = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto coloring = QskFillNode::Polychrome;
|
if ( dirtyMetrics || dirtyColors )
|
||||||
|
{
|
||||||
#if 0
|
|
||||||
/*
|
/*
|
||||||
Always using the same material result in a better batching
|
For monochrome border/fiiling with the same color we might be
|
||||||
but wastes some memory. when we have a solid color.
|
able to do QskFillNode::Monochrome. However this is not implemeted in
|
||||||
Maybe its worth to introduce a flag to control the behaviour,
|
QskBoxRenderer yet. TODO ...
|
||||||
but for the moment we go with performance.
|
|
||||||
*/
|
*/
|
||||||
|
setColoring( QskFillNode::Polychrome );
|
||||||
|
|
||||||
if ( !( hasFill && hasBorder ) )
|
auto fillGradient = gradient.effectiveGradient();
|
||||||
|
if ( !QskBoxRenderer::isGradientSupported( fillGradient ) )
|
||||||
{
|
{
|
||||||
if ( ( hasFill && isFillMonochrome )
|
qWarning() << "QskBoxRenderer does not support radial/conic gradients";
|
||||||
|| ( hasBorder && !isBorderMonochrome )
|
fillGradient.setDirection( QskGradient::Linear );
|
||||||
{
|
}
|
||||||
coloring = QskFillNode::Monochrome;
|
|
||||||
|
QskBoxRenderer::renderBox( rect, shape, borderMetrics,
|
||||||
|
borderColors, fillGradient, *geometry() );
|
||||||
|
|
||||||
|
markDirty( QSGNode::DirtyGeometry );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
else if ( hasFill )
|
||||||
|
|
||||||
auto& geometry = *this->geometry();
|
|
||||||
|
|
||||||
if ( coloring == QskFillNode::Polychrome )
|
|
||||||
{
|
{
|
||||||
setColoring( coloring );
|
updateFilling( rect, shape, borderMetrics, gradient );
|
||||||
|
}
|
||||||
QskBoxRenderer::renderBox( d->rect, shape, borderMetrics,
|
else if ( hasBorder )
|
||||||
borderColors, fillGradient, geometry );
|
{
|
||||||
|
updateBorder( rect, shape, borderMetrics, borderColors );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ( hasFill )
|
d->resetNode( this );
|
||||||
{
|
|
||||||
setColoring( fillGradient.rgbStart() );
|
|
||||||
QskBoxRenderer::renderFillGeometry(
|
|
||||||
d->rect, shape, QskBoxBorderMetrics(), geometry );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
setColoring( borderColors.left().rgbStart() );
|
|
||||||
QskBoxRenderer::renderBorderGeometry(
|
|
||||||
d->rect, shape, borderMetrics, geometry );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
geometry.markVertexDataDirty();
|
bool QskBoxRectangleNode::isCombinedGeometrySupported( const QskGradient& gradient )
|
||||||
|
{
|
||||||
|
return QskBoxRenderer::isGradientSupported( gradient );
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,15 +24,29 @@ class QSK_EXPORT QskBoxRectangleNode : public QskFillNode
|
||||||
QskBoxRectangleNode();
|
QskBoxRectangleNode();
|
||||||
~QskBoxRectangleNode() override;
|
~QskBoxRectangleNode() override;
|
||||||
|
|
||||||
void updateNode( const QRectF&,
|
void updateBox( const QRectF&,
|
||||||
const QskBoxShapeMetrics&, const QskBoxBorderMetrics&,
|
const QskBoxShapeMetrics&, const QskBoxBorderMetrics&,
|
||||||
const QskBoxBorderColors&, const QskGradient& );
|
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& );
|
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:
|
private:
|
||||||
Q_DECLARE_PRIVATE( QskBoxRectangleNode )
|
Q_DECLARE_PRIVATE( QskBoxRectangleNode )
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,9 @@ static inline QskVertex::ColoredLine* qskAllocateColoredLines(
|
||||||
static inline QskGradient qskEffectiveGradient(
|
static inline QskGradient qskEffectiveGradient(
|
||||||
const QRectF& rect, const QskGradient& gradient )
|
const QRectF& rect, const QskGradient& gradient )
|
||||||
{
|
{
|
||||||
|
if ( !gradient.isVisible() )
|
||||||
|
return gradient;
|
||||||
|
|
||||||
const auto dir = gradient.linearDirection();
|
const auto dir = gradient.linearDirection();
|
||||||
|
|
||||||
auto g = gradient;
|
auto g = gradient;
|
||||||
|
|
@ -111,6 +114,7 @@ void QskBoxRenderer::renderBorderGeometry(
|
||||||
const QskBoxBorderMetrics& border, QSGGeometry& geometry )
|
const QskBoxBorderMetrics& border, QSGGeometry& geometry )
|
||||||
{
|
{
|
||||||
geometry.setDrawingMode( QSGGeometry::DrawTriangleStrip );
|
geometry.setDrawingMode( QSGGeometry::DrawTriangleStrip );
|
||||||
|
geometry.markVertexDataDirty();
|
||||||
|
|
||||||
const QskBoxMetrics metrics( rect, shape, border );
|
const QskBoxMetrics metrics( rect, shape, border );
|
||||||
const QskBoxBasicStroker stroker( metrics );
|
const QskBoxBasicStroker stroker( metrics );
|
||||||
|
|
@ -131,6 +135,7 @@ void QskBoxRenderer::renderFillGeometry(
|
||||||
const QskBoxBorderMetrics& border, QSGGeometry& geometry )
|
const QskBoxBorderMetrics& border, QSGGeometry& geometry )
|
||||||
{
|
{
|
||||||
geometry.setDrawingMode( QSGGeometry::DrawTriangleStrip );
|
geometry.setDrawingMode( QSGGeometry::DrawTriangleStrip );
|
||||||
|
geometry.markVertexDataDirty();
|
||||||
|
|
||||||
const QskBoxMetrics metrics( rect, shape, border );
|
const QskBoxMetrics metrics( rect, shape, border );
|
||||||
QskBoxBasicStroker stroker( metrics );
|
QskBoxBasicStroker stroker( metrics );
|
||||||
|
|
@ -153,6 +158,7 @@ void QskBoxRenderer::renderBox( const QRectF& rect,
|
||||||
QSGGeometry& geometry )
|
QSGGeometry& geometry )
|
||||||
{
|
{
|
||||||
geometry.setDrawingMode( QSGGeometry::DrawTriangleStrip );
|
geometry.setDrawingMode( QSGGeometry::DrawTriangleStrip );
|
||||||
|
geometry.markVertexDataDirty();
|
||||||
|
|
||||||
const QskBoxMetrics metrics( rect, shape, border );
|
const QskBoxMetrics metrics( rect, shape, border );
|
||||||
const auto effectiveGradient = qskEffectiveGradient( metrics.innerRect, gradient );
|
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