qskinny/src/nodes/QskBoxNode.cpp
2023-04-06 09:23:37 +02:00

112 lines
3.1 KiB
C++

/******************************************************************************
* QSkinny - Copyright (C) 2016 Uwe Rathmann
* SPDX-License-Identifier: BSD-3-Clause
*****************************************************************************/
#include "QskBoxNode.h"
#include "QskBoxFillNode.h"
#include "QskBoxShadowNode.h"
#include "QskBoxRectangleNode.h"
#include "QskBoxRenderer.h"
#include "QskSGNode.h"
#include "QskGradient.h"
#include "QskGradientDirection.h"
#include "QskShadowMetrics.h"
#include "QskBoxBorderMetrics.h"
#include "QskBoxBorderColors.h"
namespace
{
enum Role
{
ShadowRole,
BoxRole,
FillRole
};
}
static void qskUpdateChildren( QSGNode* parentNode, quint8 role, QSGNode* node )
{
static const QVector< quint8 > roles = { ShadowRole, BoxRole, FillRole };
auto oldNode = QskSGNode::findChildNode( parentNode, role );
QskSGNode::replaceChildNode( roles, role, parentNode, oldNode, node );
}
template< typename Node >
inline Node* qskNode( QSGNode* parentNode, quint8 role )
{
using namespace QskSGNode;
auto node = static_cast< Node* > ( findChildNode( parentNode, role ) );
if ( node == nullptr )
{
node = new Node();
setNodeRole( node, role );
}
return node;
}
QskBoxNode::QskBoxNode()
{
}
QskBoxNode::~QskBoxNode()
{
}
void QskBoxNode::updateNode( const QRectF& rect,
const QskBoxShapeMetrics& shape, const QskBoxBorderMetrics& borderMetrics,
const QskBoxBorderColors& borderColors, const QskGradient& gradient,
const QskShadowMetrics& shadowMetrics, const QColor& shadowColor )
{
using namespace QskSGNode;
QskBoxShadowNode* shadowNode = nullptr;
QskBoxRectangleNode* rectNode = nullptr;
QskBoxFillNode* fillNode = nullptr;
if ( !shadowMetrics.isNull()
&& shadowColor.isValid() && shadowColor.alpha() != 0 )
{
shadowNode = qskNode< QskBoxShadowNode >( this, ShadowRole );
shadowNode->setShadowData( shadowMetrics.shadowRect( rect ),
shape, shadowMetrics.blurRadius(), shadowColor );
}
/*
QskBoxRectangleNode supports vertical/horizontal and many tilted
linear gradients. If our gradient doesn't fall into this category
we use a QskBoxFillNode.
However the border is always done with a QskBoxRectangleNode
*/
if ( QskBox::isGradientSupported( shape, gradient ) )
{
rectNode = qskNode< QskBoxRectangleNode >( this, BoxRole );
rectNode->updateNode( rect, shape, borderMetrics, borderColors, gradient );
}
else
{
if ( !borderMetrics.isNull() && borderColors.isVisible() )
{
rectNode = qskNode< QskBoxRectangleNode >( this, BoxRole );
rectNode->updateNode( rect, shape, borderMetrics, borderColors, QskGradient() );
}
if ( gradient.isVisible() )
{
fillNode = qskNode< QskBoxFillNode >( this, FillRole );
fillNode->updateNode( rect, shape, borderMetrics, gradient );
}
}
qskUpdateChildren( this, ShadowRole, shadowNode );
qskUpdateChildren( this, BoxRole, rectNode );
qskUpdateChildren( this, FillRole, fillNode );
}