2022-12-05 11:34:08 +00:00
|
|
|
/******************************************************************************
|
|
|
|
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
2023-04-06 07:23:37 +00:00
|
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
2022-12-05 11:34:08 +00:00
|
|
|
*****************************************************************************/
|
|
|
|
|
|
|
|
#include "QskBoxRectangleNode.h"
|
|
|
|
#include "QskBoxBorderColors.h"
|
|
|
|
#include "QskBoxBorderMetrics.h"
|
|
|
|
#include "QskBoxRenderer.h"
|
|
|
|
#include "QskBoxShapeMetrics.h"
|
|
|
|
#include "QskGradient.h"
|
|
|
|
#include "QskGradientDirection.h"
|
2023-11-15 10:47:56 +00:00
|
|
|
#include "QskFillNodePrivate.h"
|
2022-12-05 11:34:08 +00:00
|
|
|
|
|
|
|
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 )
|
|
|
|
{
|
2022-12-22 19:13:45 +00:00
|
|
|
auto g = gradient.effectiveGradient();
|
2022-12-05 11:34:08 +00:00
|
|
|
|
2022-12-28 18:39:08 +00:00
|
|
|
if ( g.type() != QskGradient::Linear )
|
2022-12-22 19:27:17 +00:00
|
|
|
{
|
|
|
|
qWarning() << "QskBoxRectangleNode does not support radial/conic gradients";
|
|
|
|
g.setDirection( QskGradient::Linear );
|
|
|
|
}
|
2022-12-05 11:34:08 +00:00
|
|
|
|
|
|
|
return g;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
2023-11-15 10:47:56 +00:00
|
|
|
class QskBoxRectangleNodePrivate final : public QskFillNodePrivate
|
2022-12-05 11:34:08 +00:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
QskHashValue metricsHash = 0;
|
|
|
|
QskHashValue colorsHash = 0;
|
|
|
|
QRectF rect;
|
|
|
|
};
|
|
|
|
|
|
|
|
QskBoxRectangleNode::QskBoxRectangleNode()
|
2023-11-15 10:47:56 +00:00
|
|
|
: QskFillNode( *new QskBoxRectangleNodePrivate )
|
2022-12-05 11:34:08 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
QskBoxRectangleNode::~QskBoxRectangleNode()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskBoxRectangleNode::updateNode(
|
|
|
|
const QRectF& rect, const QskGradient& fillGradient )
|
|
|
|
{
|
|
|
|
updateNode( rect, QskBoxShapeMetrics(), QskBoxBorderMetrics(),
|
|
|
|
QskBoxBorderColors(), fillGradient );
|
|
|
|
}
|
|
|
|
|
2022-12-30 09:27:18 +00:00
|
|
|
void QskBoxRectangleNode::updateNode( const QRectF& rect,
|
|
|
|
const QskBoxShapeMetrics& shape, const QskGradient& fillGradient )
|
|
|
|
{
|
|
|
|
updateNode( rect, shape, QskBoxBorderMetrics(),
|
|
|
|
QskBoxBorderColors(), fillGradient );
|
|
|
|
}
|
|
|
|
|
2022-12-05 11:34:08 +00:00
|
|
|
void QskBoxRectangleNode::updateNode( const QRectF& rect,
|
|
|
|
const QskBoxShapeMetrics& shape, const QskBoxBorderMetrics& borderMetrics,
|
|
|
|
const QskBoxBorderColors& borderColors, const QskGradient& gradient )
|
|
|
|
{
|
|
|
|
Q_D( QskBoxRectangleNode );
|
|
|
|
|
|
|
|
/*
|
2022-12-06 11:12:54 +00:00
|
|
|
We supports certain linear gradients only.
|
|
|
|
Everything else has to be done using QskRectangleNode
|
2022-12-05 11:34:08 +00:00
|
|
|
*/
|
|
|
|
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() )
|
|
|
|
{
|
2023-11-15 10:47:56 +00:00
|
|
|
resetGeometry();
|
2022-12-05 11:34:08 +00:00
|
|
|
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 )
|
|
|
|
{
|
2023-11-15 10:47:56 +00:00
|
|
|
resetGeometry();
|
2022-12-05 11:34:08 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const bool isFillMonochrome = hasFill ? fillGradient.isMonochrome() : true;
|
|
|
|
const bool isBorderMonochrome = hasBorder ? borderColors.isMonochrome() : true;
|
|
|
|
|
|
|
|
if ( hasFill && hasBorder )
|
|
|
|
{
|
|
|
|
if ( isFillMonochrome && isBorderMonochrome )
|
|
|
|
{
|
|
|
|
if ( borderColors.left().rgbStart() == fillGradient.rgbStart() )
|
|
|
|
{
|
|
|
|
// we can draw border and background in one
|
|
|
|
hasBorder = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-11-15 10:47:56 +00:00
|
|
|
auto coloring = QskFillNode::Polychrome;
|
|
|
|
|
2022-12-05 11:34:08 +00:00
|
|
|
#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.
|
|
|
|
*/
|
|
|
|
|
2023-11-15 10:47:56 +00:00
|
|
|
if ( !( hasFill && hasBorder ) )
|
2022-12-05 11:34:08 +00:00
|
|
|
{
|
2023-11-15 10:47:56 +00:00
|
|
|
if ( ( hasFill && isFillMonochrome )
|
|
|
|
|| ( hasBorder && !isBorderMonochrome )
|
2022-12-05 11:34:08 +00:00
|
|
|
{
|
2023-11-15 10:47:56 +00:00
|
|
|
coloring = QskFillNode::Monochrome;
|
2022-12-05 11:34:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2023-11-15 10:47:56 +00:00
|
|
|
auto& geometry = *this->geometry();
|
|
|
|
|
|
|
|
if ( coloring == QskFillNode::Polychrome )
|
2022-12-05 11:34:08 +00:00
|
|
|
{
|
2023-11-15 10:47:56 +00:00
|
|
|
setColoring( coloring );
|
2022-12-05 11:34:08 +00:00
|
|
|
|
2023-02-08 16:58:09 +00:00
|
|
|
QskBox::renderBox( d->rect, shape, borderMetrics,
|
2023-11-15 10:47:56 +00:00
|
|
|
borderColors, fillGradient, geometry );
|
2022-12-05 11:34:08 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ( hasFill )
|
|
|
|
{
|
2023-11-15 10:47:56 +00:00
|
|
|
setColoring( fillGradient.rgbStart() );
|
2023-02-08 16:58:09 +00:00
|
|
|
QskBox::renderFillGeometry(
|
2023-11-15 10:47:56 +00:00
|
|
|
d->rect, shape, QskBoxBorderMetrics(), geometry );
|
2022-12-05 11:34:08 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2023-11-15 10:47:56 +00:00
|
|
|
setColoring( borderColors.left().rgbStart() );
|
2023-02-08 16:58:09 +00:00
|
|
|
QskBox::renderBorderGeometry(
|
2023-11-15 10:47:56 +00:00
|
|
|
d->rect, shape, borderMetrics, geometry );
|
2022-12-05 11:34:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-11-15 10:47:56 +00:00
|
|
|
geometry.markVertexDataDirty();
|
2022-12-05 11:34:08 +00:00
|
|
|
}
|