QskBoxNode renamed to QskBoxRectangleNode, QskShadedBoxNode renamed to QskBoxNode
This commit is contained in:
parent
c1e194b464
commit
125fe1e9f4
@ -7,7 +7,7 @@
|
||||
|
||||
#include <QskBoxBorderColors.h>
|
||||
#include <QskBoxBorderMetrics.h>
|
||||
#include <QskBoxNode.h>
|
||||
#include <QskBoxRectangleNode.h>
|
||||
#include <QskBoxShapeMetrics.h>
|
||||
#include <QskSGNode.h>
|
||||
|
||||
@ -98,7 +98,7 @@ void Frame::updateNode( QSGNode* parentNode )
|
||||
|
||||
const quint8 nodeRole = 0;
|
||||
|
||||
auto node = static_cast< QskBoxNode* >(
|
||||
auto node = static_cast< QskBoxRectangleNode* >(
|
||||
QskSGNode::findChildNode( parentNode, nodeRole ) );
|
||||
|
||||
const QRectF rect = contentsRect();
|
||||
@ -110,7 +110,7 @@ void Frame::updateNode( QSGNode* parentNode )
|
||||
|
||||
if ( node == nullptr )
|
||||
{
|
||||
node = new QskBoxNode;
|
||||
node = new QskBoxRectangleNode;
|
||||
QskSGNode::setNodeRole( node, nodeRole );
|
||||
}
|
||||
|
||||
@ -120,7 +120,7 @@ void Frame::updateNode( QSGNode* parentNode )
|
||||
parentNode->appendChildNode( node );
|
||||
}
|
||||
|
||||
void Frame::updateFrameNode( const QRectF& rect, QskBoxNode* node )
|
||||
void Frame::updateFrameNode( const QRectF& rect, QskBoxRectangleNode* node )
|
||||
{
|
||||
const QColor dark = m_color.darker( 150 );
|
||||
const QColor light = m_color.lighter( 150 );
|
||||
@ -150,7 +150,7 @@ void Frame::updateFrameNode( const QRectF& rect, QskBoxNode* node )
|
||||
const QskBoxBorderColors borderColors( c1, c1, c2, c2 );
|
||||
const qreal radius = effectiveRadius( rect, m_radius );
|
||||
|
||||
node->setBoxData( rect, radius, m_frameWidth, borderColors, m_color );
|
||||
node->updateNode( rect, radius, m_frameWidth, borderColors, m_color );
|
||||
}
|
||||
|
||||
#include "moc_Frame.cpp"
|
||||
|
@ -7,7 +7,7 @@
|
||||
|
||||
#include "QskControl.h"
|
||||
|
||||
class QskBoxNode;
|
||||
class QskBoxRectangleNode;
|
||||
|
||||
class Frame : public QskControl
|
||||
{
|
||||
@ -62,7 +62,7 @@ class Frame : public QskControl
|
||||
void updateNode( QSGNode* ) override;
|
||||
|
||||
private:
|
||||
void updateFrameNode( const QRectF&, QskBoxNode* );
|
||||
void updateFrameNode( const QRectF&, QskBoxRectangleNode* );
|
||||
|
||||
Style m_style;
|
||||
QColor m_color;
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
#include <QskBoxBorderColors.h>
|
||||
#include <QskBoxBorderMetrics.h>
|
||||
#include <QskBoxNode.h>
|
||||
#include <QskBoxRectangleNode.h>
|
||||
#include <QskBoxShapeMetrics.h>
|
||||
|
||||
namespace
|
||||
@ -142,15 +142,15 @@ QSGNode* DiagramSkinlet::updateChartNode( const Diagram* diagram, QSGNode* node
|
||||
|
||||
for( int k = 0; k < dataPoints.size(); ++k )
|
||||
{
|
||||
QskBoxNode* barNode;
|
||||
QskBoxRectangleNode* barNode;
|
||||
|
||||
if( barsNode->childCount() > k )
|
||||
{
|
||||
barNode = static_cast< QskBoxNode* >( barsNode->childAtIndex( k ) );
|
||||
barNode = static_cast< QskBoxRectangleNode* >( barsNode->childAtIndex( k ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
barNode = new QskBoxNode;
|
||||
barNode = new QskBoxRectangleNode;
|
||||
barsNode->appendChildNode( barNode );
|
||||
}
|
||||
|
||||
@ -172,7 +172,7 @@ QSGNode* DiagramSkinlet::updateChartNode( const Diagram* diagram, QSGNode* node
|
||||
color = diagram->color( barSubcontrol );
|
||||
|
||||
const auto shape = diagram->boxShapeHint( barSubcontrol );
|
||||
barNode->setBoxData( barRect, shape, {}, {}, color );
|
||||
barNode->updateNode( barRect, shape, {}, {}, color );
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -8,7 +8,6 @@
|
||||
|
||||
#include <QskBoxBorderColors.h>
|
||||
#include <QskBoxBorderMetrics.h>
|
||||
#include <QskBoxNode.h>
|
||||
#include <QskBoxShapeMetrics.h>
|
||||
#include <QskTextColors.h>
|
||||
#include <QskTextOptions.h>
|
||||
|
@ -6,7 +6,6 @@
|
||||
#include "QskMenuSkinlet.h"
|
||||
#include "QskMenu.h"
|
||||
|
||||
#include "QskBoxNode.h"
|
||||
#include "QskGraphic.h"
|
||||
#include "QskColorFilter.h"
|
||||
#include "QskTextOptions.h"
|
||||
|
@ -6,7 +6,6 @@
|
||||
#include "QskPageIndicatorSkinlet.h"
|
||||
#include "QskPageIndicator.h"
|
||||
|
||||
#include "QskBoxNode.h"
|
||||
#include "QskSGNode.h"
|
||||
#include "QskFunctions.h"
|
||||
|
||||
|
@ -10,9 +10,9 @@
|
||||
#include "QskArcMetrics.h"
|
||||
#include "QskBoxBorderColors.h"
|
||||
#include "QskBoxBorderMetrics.h"
|
||||
#include "QskBoxClipNode.h"
|
||||
#include "QskBoxNode.h"
|
||||
#include "QskShadedBoxNode.h"
|
||||
#include "QskBoxClipNode.h"
|
||||
#include "QskBoxRectangleNode.h"
|
||||
#include "QskBoxShapeMetrics.h"
|
||||
#include "QskBoxHints.h"
|
||||
#include "QskColorFilter.h"
|
||||
@ -175,7 +175,7 @@ static inline QskTextColors qskTextColors(
|
||||
return c;
|
||||
}
|
||||
|
||||
static inline QSGNode* qskUpdateShadedBoxNode(
|
||||
static inline QSGNode* qskUpdateBoxNode(
|
||||
const QskSkinnable*, QSGNode* node, const QRectF& rect,
|
||||
const QskBoxShapeMetrics& shape, const QskBoxBorderMetrics& borderMetrics,
|
||||
const QskBoxBorderColors& borderColors, const QskGradient& gradient,
|
||||
@ -190,14 +190,14 @@ static inline QSGNode* qskUpdateShadedBoxNode(
|
||||
|
||||
if ( qskIsBoxVisible( absoluteMetrics, borderColors, gradient ) )
|
||||
{
|
||||
auto boxNode = static_cast< QskShadedBoxNode* >( node );
|
||||
auto boxNode = static_cast< QskBoxNode* >( node );
|
||||
if ( boxNode == nullptr )
|
||||
boxNode = new QskShadedBoxNode();
|
||||
boxNode = new QskBoxNode();
|
||||
|
||||
const auto absoluteShape = shape.toAbsolute( size );
|
||||
const auto absoluteShadowMetrics = shadowMetrics.toAbsolute( size );
|
||||
|
||||
boxNode->setBoxData( rect, absoluteShape, absoluteMetrics,
|
||||
boxNode->updateNode( rect, absoluteShape, absoluteMetrics,
|
||||
borderColors, gradient, absoluteShadowMetrics, shadowColor );
|
||||
|
||||
return boxNode;
|
||||
@ -350,12 +350,12 @@ QSGNode* QskSkinlet::updateBackgroundNode(
|
||||
if ( !gradient.isValid() )
|
||||
return nullptr;
|
||||
|
||||
auto boxNode = static_cast< QskBoxNode* >( node );
|
||||
if ( boxNode == nullptr )
|
||||
boxNode = new QskBoxNode();
|
||||
auto rectNode = static_cast< QskBoxRectangleNode* >( node );
|
||||
if ( rectNode == nullptr )
|
||||
rectNode = new QskBoxRectangleNode();
|
||||
|
||||
boxNode->setBoxData( rect, gradient );
|
||||
return boxNode;
|
||||
rectNode->updateNode( rect, gradient );
|
||||
return rectNode;
|
||||
}
|
||||
|
||||
QSGNode* QskSkinlet::updateDebugNode(
|
||||
@ -432,7 +432,7 @@ QSGNode* QskSkinlet::updateBoxNode( const QskSkinnable* skinnable,
|
||||
const auto shadowMetrics = skinnable->shadowMetricsHint( subControl );
|
||||
const auto shadowColor = skinnable->shadowColorHint( subControl );
|
||||
|
||||
return qskUpdateShadedBoxNode( skinnable, node,
|
||||
return qskUpdateBoxNode( skinnable, node,
|
||||
boxRect, shape, borderMetrics, borderColors, fillGradient,
|
||||
shadowMetrics, shadowColor );
|
||||
}
|
||||
@ -442,7 +442,7 @@ QSGNode* QskSkinlet::updateBoxNode(
|
||||
const QskBoxShapeMetrics& shape, const QskBoxBorderMetrics& borderMetrics,
|
||||
const QskBoxBorderColors& borderColors, const QskGradient& fillGradient )
|
||||
{
|
||||
return qskUpdateShadedBoxNode( skinnable, node,
|
||||
return qskUpdateBoxNode( skinnable, node,
|
||||
rect, shape, borderMetrics, borderColors, fillGradient,
|
||||
QskShadowMetrics(), QColor() );
|
||||
}
|
||||
@ -450,7 +450,7 @@ QSGNode* QskSkinlet::updateBoxNode(
|
||||
QSGNode* QskSkinlet::updateBoxNode( const QskSkinnable* skinnable,
|
||||
QSGNode* node, const QRectF& rect, const QskBoxHints& hints )
|
||||
{
|
||||
return qskUpdateShadedBoxNode( skinnable, node, rect,
|
||||
return qskUpdateBoxNode( skinnable, node, rect,
|
||||
hints.shape, hints.borderMetrics, hints.borderColors, hints.gradient,
|
||||
hints.shadowMetrics, hints.shadowColor );
|
||||
}
|
||||
|
@ -4,283 +4,136 @@
|
||||
*****************************************************************************/
|
||||
|
||||
#include "QskBoxNode.h"
|
||||
#include "QskBoxBorderColors.h"
|
||||
#include "QskBoxBorderMetrics.h"
|
||||
#include "QskBoxRenderer.h"
|
||||
#include "QskBoxShapeMetrics.h"
|
||||
#include "QskBoxFillNode.h"
|
||||
#include "QskBoxShadowNode.h"
|
||||
#include "QskBoxRectangleNode.h"
|
||||
#include "QskSGNode.h"
|
||||
|
||||
#include "QskGradient.h"
|
||||
#include "QskGradientDirection.h"
|
||||
#include "QskShadowMetrics.h"
|
||||
#include "QskBoxBorderMetrics.h"
|
||||
#include "QskBoxBorderColors.h"
|
||||
|
||||
#include <qglobalstatic.h>
|
||||
#include <qsgflatcolormaterial.h>
|
||||
#include <qsgvertexcolormaterial.h>
|
||||
|
||||
QSK_QT_PRIVATE_BEGIN
|
||||
#include <private/qsgnode_p.h>
|
||||
QSK_QT_PRIVATE_END
|
||||
|
||||
Q_GLOBAL_STATIC( QSGVertexColorMaterial, qskMaterialVertex )
|
||||
|
||||
static inline QskHashValue qskMetricsHash(
|
||||
const QskBoxShapeMetrics& shape, const QskBoxBorderMetrics& borderMetrics )
|
||||
namespace
|
||||
{
|
||||
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 )
|
||||
{
|
||||
QskGradient g;
|
||||
|
||||
if ( gradient.isVisible() )
|
||||
enum Role
|
||||
{
|
||||
if ( gradient.isMonochrome() )
|
||||
{
|
||||
g.setLinearDirection( Qt::Vertical );
|
||||
g.setStops( gradient.rgbStart() );
|
||||
}
|
||||
else
|
||||
{
|
||||
ShadowRole,
|
||||
BoxRole,
|
||||
FillRole
|
||||
};
|
||||
}
|
||||
|
||||
switch( gradient.type() )
|
||||
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;
|
||||
}
|
||||
|
||||
static inline bool qskIsBoxGradient( const QskGradient& gradient )
|
||||
{
|
||||
if ( !gradient.isVisible() || gradient.isMonochrome() )
|
||||
return true;
|
||||
|
||||
switch( gradient.type() )
|
||||
{
|
||||
case QskGradient::Linear:
|
||||
{
|
||||
auto dir = gradient.linearDirection();
|
||||
|
||||
if ( dir.isTilted() )
|
||||
{
|
||||
case QskGradient::Linear:
|
||||
{
|
||||
auto dir = gradient.linearDirection();
|
||||
|
||||
if ( dir.isTilted() )
|
||||
{
|
||||
dir.setStart( 0.0, 0.0 );
|
||||
dir.setStop( 1.0, 1.0 );
|
||||
}
|
||||
|
||||
g.setLinearDirection( dir );
|
||||
|
||||
break;
|
||||
}
|
||||
case QskGradient::Radial:
|
||||
case QskGradient::Conic:
|
||||
{
|
||||
qWarning() << "QskBoxNode does not support radial/conic gradients";
|
||||
g.setLinearDirection( Qt::Vertical );
|
||||
|
||||
break;
|
||||
}
|
||||
case QskGradient::Stops:
|
||||
{
|
||||
g.setLinearDirection( Qt::Vertical );
|
||||
break;
|
||||
}
|
||||
// only diagonal from topLeft to bottomRight
|
||||
return ( dir.x1() == dir.x2() ) && ( dir.y1() == dir.y2() );
|
||||
}
|
||||
|
||||
g.setStops( gradient.stops() );
|
||||
return true;
|
||||
}
|
||||
case QskGradient::Radial:
|
||||
case QskGradient::Conic:
|
||||
{
|
||||
return false;
|
||||
}
|
||||
default:
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return g;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
class QskBoxNodePrivate final : public QSGGeometryNodePrivate
|
||||
{
|
||||
public:
|
||||
QskBoxNodePrivate()
|
||||
: geometry( QSGGeometry::defaultAttributes_ColoredPoint2D(), 0 )
|
||||
{
|
||||
}
|
||||
|
||||
QskHashValue metricsHash = 0;
|
||||
QskHashValue colorsHash = 0;
|
||||
QRectF rect;
|
||||
|
||||
QSGGeometry geometry;
|
||||
};
|
||||
|
||||
QskBoxNode::QskBoxNode()
|
||||
: QSGGeometryNode( *new QskBoxNodePrivate )
|
||||
{
|
||||
Q_D( QskBoxNode );
|
||||
|
||||
setMaterial( qskMaterialVertex );
|
||||
setGeometry( &d->geometry );
|
||||
}
|
||||
|
||||
QskBoxNode::~QskBoxNode()
|
||||
{
|
||||
if ( material() != qskMaterialVertex )
|
||||
delete material();
|
||||
}
|
||||
|
||||
void QskBoxNode::setBoxData( const QRectF& rect, const QskGradient& fillGradient )
|
||||
{
|
||||
setBoxData( rect, QskBoxShapeMetrics(), QskBoxBorderMetrics(),
|
||||
QskBoxBorderColors(), fillGradient );
|
||||
}
|
||||
|
||||
void QskBoxNode::setBoxData( const QRectF& rect,
|
||||
void QskBoxNode::updateNode( const QRectF& rect,
|
||||
const QskBoxShapeMetrics& shape, const QskBoxBorderMetrics& borderMetrics,
|
||||
const QskBoxBorderColors& borderColors, const QskGradient& gradient )
|
||||
const QskBoxBorderColors& borderColors, const QskGradient& gradient,
|
||||
const QskShadowMetrics& shadowMetrics, const QColor& shadowColor )
|
||||
{
|
||||
Q_D( QskBoxNode );
|
||||
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 );
|
||||
}
|
||||
|
||||
/*
|
||||
QskBoxRenderer supports certain linear gradients only.
|
||||
For everything else we would have to use a QskGradientMaterial instead.
|
||||
|
||||
As a temporary solution we simply "convert" gradient into a
|
||||
simple QskLinearGradient so that at least something is happening.
|
||||
TODO ...
|
||||
*/
|
||||
#if 1
|
||||
const auto fillGradient = qskEffectiveGradient( gradient );
|
||||
#endif
|
||||
|
||||
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() )
|
||||
{
|
||||
d->geometry.allocate( 0 );
|
||||
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 )
|
||||
{
|
||||
d->geometry.allocate( 0 );
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#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.
|
||||
QskBoxRectangleNode supports vertical/horizontal/diagonal gradients only.
|
||||
If our gradient doesn't fall into this category we use a QskBoxFillNode.
|
||||
However the border is always done with a QskBoxRectangleNode
|
||||
*/
|
||||
|
||||
bool maybeFlat = true;
|
||||
|
||||
if ( maybeFlat )
|
||||
if ( qskIsBoxGradient( gradient ) )
|
||||
{
|
||||
if ( ( hasFill && hasBorder ) ||
|
||||
( hasFill && !isFillMonochrome ) ||
|
||||
( hasBorder && !isBorderMonochrome ) )
|
||||
{
|
||||
maybeFlat = false;
|
||||
}
|
||||
}
|
||||
#else
|
||||
bool maybeFlat = false;
|
||||
#endif
|
||||
|
||||
QskBoxRenderer renderer;
|
||||
|
||||
if ( !maybeFlat )
|
||||
{
|
||||
setMonochrome( false );
|
||||
|
||||
renderer.renderBox( d->rect, shape, borderMetrics,
|
||||
borderColors, fillGradient, *geometry() );
|
||||
rectNode = qskNode< QskBoxRectangleNode >( this, BoxRole );
|
||||
rectNode->updateNode( rect, shape, borderMetrics, borderColors, gradient );
|
||||
}
|
||||
else
|
||||
{
|
||||
// all is done with one color
|
||||
setMonochrome( true );
|
||||
|
||||
auto* flatMaterial = static_cast< QSGFlatColorMaterial* >( material() );
|
||||
|
||||
if ( hasFill )
|
||||
if ( !borderMetrics.isNull() && borderColors.isVisible() )
|
||||
{
|
||||
flatMaterial->setColor( fillGradient.rgbStart() );
|
||||
renderer.renderFill( d->rect, shape, QskBoxBorderMetrics(), *geometry() );
|
||||
rectNode = qskNode< QskBoxRectangleNode >( this, BoxRole );
|
||||
rectNode->updateNode( rect, shape, borderMetrics, borderColors, QskGradient() );
|
||||
}
|
||||
else
|
||||
|
||||
if ( gradient.isVisible() )
|
||||
{
|
||||
flatMaterial->setColor( borderColors.left().rgbStart() );
|
||||
renderer.renderBorder( d->rect, shape, borderMetrics, *geometry() );
|
||||
fillNode = qskNode< QskBoxFillNode >( this, FillRole );
|
||||
fillNode->updateNode( rect, shape, borderMetrics, gradient );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QskBoxNode::setMonochrome( bool on )
|
||||
{
|
||||
const auto material = this->material();
|
||||
|
||||
if ( on == ( material != qskMaterialVertex ) )
|
||||
return;
|
||||
|
||||
Q_D( QskBoxNode );
|
||||
|
||||
d->geometry.allocate( 0 );
|
||||
|
||||
if ( on )
|
||||
{
|
||||
setMaterial( new QSGFlatColorMaterial() );
|
||||
|
||||
const QSGGeometry g( QSGGeometry::defaultAttributes_Point2D(), 0 );
|
||||
memcpy( ( void* ) &d->geometry, ( void* ) &g, sizeof( QSGGeometry ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
setMaterial( qskMaterialVertex );
|
||||
delete material;
|
||||
|
||||
const QSGGeometry g( QSGGeometry::defaultAttributes_ColoredPoint2D(), 0 );
|
||||
memcpy( ( void* ) &d->geometry, ( void* ) &g, sizeof( QSGGeometry ) );
|
||||
}
|
||||
|
||||
qskUpdateChildren( this, ShadowRole, shadowNode );
|
||||
qskUpdateChildren( this, BoxRole, rectNode );
|
||||
qskUpdateChildren( this, FillRole, fillNode );
|
||||
}
|
||||
|
@ -9,30 +9,24 @@
|
||||
#include "QskGlobal.h"
|
||||
#include <qsgnode.h>
|
||||
|
||||
class QskShadowMetrics;
|
||||
class QskBoxShapeMetrics;
|
||||
class QskBoxBorderMetrics;
|
||||
class QskBoxBorderColors;
|
||||
class QskGradient;
|
||||
class QskShadowMetrics;
|
||||
class QColor;
|
||||
|
||||
class QskBoxNodePrivate;
|
||||
|
||||
class QSK_EXPORT QskBoxNode : public QSGGeometryNode
|
||||
class QSK_EXPORT QskBoxNode : public QSGNode
|
||||
{
|
||||
public:
|
||||
QskBoxNode();
|
||||
~QskBoxNode() override;
|
||||
|
||||
void setBoxData( const QRectF&,
|
||||
void updateNode( const QRectF&,
|
||||
const QskBoxShapeMetrics&, const QskBoxBorderMetrics&,
|
||||
const QskBoxBorderColors&, const QskGradient& );
|
||||
|
||||
void setBoxData( const QRectF& rect, const QskGradient& );
|
||||
|
||||
private:
|
||||
void setMonochrome( bool on );
|
||||
|
||||
Q_DECLARE_PRIVATE( QskBoxNode )
|
||||
|
||||
const QskBoxBorderColors&, const QskGradient&,
|
||||
const QskShadowMetrics&, const QColor& shadowColor );
|
||||
};
|
||||
|
||||
#endif
|
||||
|
287
src/nodes/QskBoxRectangleNode.cpp
Normal file
287
src/nodes/QskBoxRectangleNode.cpp
Normal file
@ -0,0 +1,287 @@
|
||||
/******************************************************************************
|
||||
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
||||
* This file may be used under the terms of the QSkinny License, Version 1.0
|
||||
*****************************************************************************/
|
||||
|
||||
#include "QskBoxRectangleNode.h"
|
||||
#include "QskBoxBorderColors.h"
|
||||
#include "QskBoxBorderMetrics.h"
|
||||
#include "QskBoxRenderer.h"
|
||||
#include "QskBoxShapeMetrics.h"
|
||||
#include "QskGradient.h"
|
||||
#include "QskGradientDirection.h"
|
||||
|
||||
#include <qglobalstatic.h>
|
||||
#include <qsgflatcolormaterial.h>
|
||||
#include <qsgvertexcolormaterial.h>
|
||||
|
||||
QSK_QT_PRIVATE_BEGIN
|
||||
#include <private/qsgnode_p.h>
|
||||
QSK_QT_PRIVATE_END
|
||||
|
||||
Q_GLOBAL_STATIC( QSGVertexColorMaterial, qskMaterialVertex )
|
||||
|
||||
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 )
|
||||
{
|
||||
QskGradient g;
|
||||
|
||||
if ( gradient.isVisible() )
|
||||
{
|
||||
if ( gradient.isMonochrome() )
|
||||
{
|
||||
g.setLinearDirection( Qt::Vertical );
|
||||
g.setStops( gradient.rgbStart() );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
switch( gradient.type() )
|
||||
{
|
||||
case QskGradient::Linear:
|
||||
{
|
||||
auto dir = gradient.linearDirection();
|
||||
|
||||
if ( dir.isTilted() )
|
||||
{
|
||||
dir.setStart( 0.0, 0.0 );
|
||||
dir.setStop( 1.0, 1.0 );
|
||||
}
|
||||
|
||||
g.setLinearDirection( dir );
|
||||
|
||||
break;
|
||||
}
|
||||
case QskGradient::Radial:
|
||||
case QskGradient::Conic:
|
||||
{
|
||||
qWarning() << "QskBoxRectangleNode does not support radial/conic gradients";
|
||||
g.setLinearDirection( Qt::Vertical );
|
||||
|
||||
break;
|
||||
}
|
||||
case QskGradient::Stops:
|
||||
{
|
||||
g.setLinearDirection( Qt::Vertical );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
g.setStops( gradient.stops() );
|
||||
}
|
||||
}
|
||||
|
||||
return g;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
class QskBoxRectangleNodePrivate final : public QSGGeometryNodePrivate
|
||||
{
|
||||
public:
|
||||
QskBoxRectangleNodePrivate()
|
||||
: geometry( QSGGeometry::defaultAttributes_ColoredPoint2D(), 0 )
|
||||
{
|
||||
}
|
||||
|
||||
QskHashValue metricsHash = 0;
|
||||
QskHashValue colorsHash = 0;
|
||||
QRectF rect;
|
||||
|
||||
QSGGeometry geometry;
|
||||
};
|
||||
|
||||
QskBoxRectangleNode::QskBoxRectangleNode()
|
||||
: QSGGeometryNode( *new QskBoxRectangleNodePrivate )
|
||||
{
|
||||
Q_D( QskBoxRectangleNode );
|
||||
|
||||
setMaterial( qskMaterialVertex );
|
||||
setGeometry( &d->geometry );
|
||||
}
|
||||
|
||||
QskBoxRectangleNode::~QskBoxRectangleNode()
|
||||
{
|
||||
if ( material() != qskMaterialVertex )
|
||||
delete material();
|
||||
}
|
||||
|
||||
void QskBoxRectangleNode::updateNode(
|
||||
const QRectF& rect, const QskGradient& fillGradient )
|
||||
{
|
||||
updateNode( rect, QskBoxShapeMetrics(), QskBoxBorderMetrics(),
|
||||
QskBoxBorderColors(), fillGradient );
|
||||
}
|
||||
|
||||
void QskBoxRectangleNode::updateNode( const QRectF& rect,
|
||||
const QskBoxShapeMetrics& shape, const QskBoxBorderMetrics& borderMetrics,
|
||||
const QskBoxBorderColors& borderColors, const QskGradient& gradient )
|
||||
{
|
||||
Q_D( QskBoxRectangleNode );
|
||||
|
||||
/*
|
||||
QskBoxRenderer supports certain linear gradients only.
|
||||
For everything else we would have to use a QskGradientMaterial instead.
|
||||
|
||||
As a temporary solution we simply "convert" gradient into a
|
||||
simple QskLinearGradient so that at least something is happening.
|
||||
TODO ...
|
||||
*/
|
||||
#if 1
|
||||
const auto fillGradient = qskEffectiveGradient( gradient );
|
||||
#endif
|
||||
|
||||
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() )
|
||||
{
|
||||
d->geometry.allocate( 0 );
|
||||
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 )
|
||||
{
|
||||
d->geometry.allocate( 0 );
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#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.
|
||||
*/
|
||||
|
||||
bool maybeFlat = true;
|
||||
|
||||
if ( maybeFlat )
|
||||
{
|
||||
if ( ( hasFill && hasBorder ) ||
|
||||
( hasFill && !isFillMonochrome ) ||
|
||||
( hasBorder && !isBorderMonochrome ) )
|
||||
{
|
||||
maybeFlat = false;
|
||||
}
|
||||
}
|
||||
#else
|
||||
bool maybeFlat = false;
|
||||
#endif
|
||||
|
||||
QskBoxRenderer renderer;
|
||||
|
||||
if ( !maybeFlat )
|
||||
{
|
||||
setMonochrome( false );
|
||||
|
||||
renderer.renderBox( d->rect, shape, borderMetrics,
|
||||
borderColors, fillGradient, *geometry() );
|
||||
}
|
||||
else
|
||||
{
|
||||
// all is done with one color
|
||||
setMonochrome( true );
|
||||
|
||||
auto* flatMaterial = static_cast< QSGFlatColorMaterial* >( material() );
|
||||
|
||||
if ( hasFill )
|
||||
{
|
||||
flatMaterial->setColor( fillGradient.rgbStart() );
|
||||
renderer.renderFill( d->rect, shape, QskBoxBorderMetrics(), *geometry() );
|
||||
}
|
||||
else
|
||||
{
|
||||
flatMaterial->setColor( borderColors.left().rgbStart() );
|
||||
renderer.renderBorder( d->rect, shape, borderMetrics, *geometry() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QskBoxRectangleNode::setMonochrome( bool on )
|
||||
{
|
||||
const auto material = this->material();
|
||||
|
||||
if ( on == ( material != qskMaterialVertex ) )
|
||||
return;
|
||||
|
||||
Q_D( QskBoxRectangleNode );
|
||||
|
||||
d->geometry.allocate( 0 );
|
||||
|
||||
if ( on )
|
||||
{
|
||||
setMaterial( new QSGFlatColorMaterial() );
|
||||
|
||||
const QSGGeometry g( QSGGeometry::defaultAttributes_Point2D(), 0 );
|
||||
memcpy( ( void* ) &d->geometry, ( void* ) &g, sizeof( QSGGeometry ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
setMaterial( qskMaterialVertex );
|
||||
delete material;
|
||||
|
||||
const QSGGeometry g( QSGGeometry::defaultAttributes_ColoredPoint2D(), 0 );
|
||||
memcpy( ( void* ) &d->geometry, ( void* ) &g, sizeof( QSGGeometry ) );
|
||||
}
|
||||
}
|
@ -3,30 +3,36 @@
|
||||
* This file may be used under the terms of the QSkinny License, Version 1.0
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef QSK_SHADED_BOX_NODE_H
|
||||
#define QSK_SHADED_BOX_NODE_H
|
||||
#ifndef QSK_BOX_RECTANGLE_NODE_H
|
||||
#define QSK_BOX_RECTANGLE_NODE_H
|
||||
|
||||
#include "QskGlobal.h"
|
||||
#include <qsgnode.h>
|
||||
|
||||
class QskShadowMetrics;
|
||||
class QskBoxShapeMetrics;
|
||||
class QskBoxBorderMetrics;
|
||||
class QskBoxBorderColors;
|
||||
class QskGradient;
|
||||
class QskShadowMetrics;
|
||||
class QColor;
|
||||
|
||||
class QSK_EXPORT QskShadedBoxNode : public QSGNode
|
||||
class QskBoxRectangleNodePrivate;
|
||||
|
||||
class QSK_EXPORT QskBoxRectangleNode : public QSGGeometryNode
|
||||
{
|
||||
public:
|
||||
QskShadedBoxNode();
|
||||
~QskShadedBoxNode() override;
|
||||
QskBoxRectangleNode();
|
||||
~QskBoxRectangleNode() override;
|
||||
|
||||
void setBoxData( const QRectF&,
|
||||
void updateNode( const QRectF&,
|
||||
const QskBoxShapeMetrics&, const QskBoxBorderMetrics&,
|
||||
const QskBoxBorderColors&, const QskGradient&,
|
||||
const QskShadowMetrics&, const QColor& shadowColor );
|
||||
const QskBoxBorderColors&, const QskGradient& );
|
||||
|
||||
void updateNode( const QRectF& rect, const QskGradient& );
|
||||
|
||||
private:
|
||||
void setMonochrome( bool on );
|
||||
|
||||
Q_DECLARE_PRIVATE( QskBoxRectangleNode )
|
||||
|
||||
};
|
||||
|
||||
#endif
|
@ -1,139 +0,0 @@
|
||||
/******************************************************************************
|
||||
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
||||
* This file may be used under the terms of the QSkinny License, Version 1.0
|
||||
*****************************************************************************/
|
||||
|
||||
#include "QskShadedBoxNode.h"
|
||||
#include "QskBoxFillNode.h"
|
||||
#include "QskBoxShadowNode.h"
|
||||
#include "QskBoxNode.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
|
||||
};
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static inline bool qskIsBoxGradient( const QskGradient& gradient )
|
||||
{
|
||||
if ( !gradient.isVisible() || gradient.isMonochrome() )
|
||||
return true;
|
||||
|
||||
switch( gradient.type() )
|
||||
{
|
||||
case QskGradient::Linear:
|
||||
{
|
||||
auto dir = gradient.linearDirection();
|
||||
|
||||
if ( dir.isTilted() )
|
||||
{
|
||||
// only diagonal from topLeft to bottomRight
|
||||
return ( dir.x1() == dir.x2() ) && ( dir.y1() == dir.y2() );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
case QskGradient::Radial:
|
||||
case QskGradient::Conic:
|
||||
{
|
||||
return false;
|
||||
}
|
||||
default:
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QskShadedBoxNode::QskShadedBoxNode()
|
||||
{
|
||||
}
|
||||
|
||||
QskShadedBoxNode::~QskShadedBoxNode()
|
||||
{
|
||||
}
|
||||
|
||||
void QskShadedBoxNode::setBoxData( 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;
|
||||
QskBoxNode* boxNode = 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 );
|
||||
}
|
||||
|
||||
/*
|
||||
QskBoxNode supports vertical/horizontal/diagonal gradients only.
|
||||
If our gradient doesn't fall into this category we use a QskBoxFillNode.
|
||||
However the border is always done with a QskBoxNode
|
||||
*/
|
||||
|
||||
if ( qskIsBoxGradient( gradient ) )
|
||||
{
|
||||
boxNode = qskNode< QskBoxNode >( this, BoxRole );
|
||||
boxNode->setBoxData( rect, shape, borderMetrics, borderColors, gradient );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( !borderMetrics.isNull() && borderColors.isVisible() )
|
||||
{
|
||||
boxNode = qskNode< QskBoxNode >( this, BoxRole );
|
||||
boxNode->setBoxData( 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, boxNode );
|
||||
qskUpdateChildren( this, FillRole, fillNode );
|
||||
}
|
@ -104,6 +104,7 @@ HEADERS += \
|
||||
nodes/QskBoxNode.h \
|
||||
nodes/QskBoxClipNode.h \
|
||||
nodes/QskBoxFillNode.h \
|
||||
nodes/QskBoxRectangleNode.h \
|
||||
nodes/QskBoxRenderer.h \
|
||||
nodes/QskBoxRendererColorMap.h \
|
||||
nodes/QskBoxShadowNode.h \
|
||||
@ -114,7 +115,6 @@ HEADERS += \
|
||||
nodes/QskRichTextRenderer.h \
|
||||
nodes/QskScaleRenderer.h \
|
||||
nodes/QskSGNode.h \
|
||||
nodes/QskShadedBoxNode.h \
|
||||
nodes/QskStrokeNode.h \
|
||||
nodes/QskShapeNode.h \
|
||||
nodes/QskGradientMaterial.h \
|
||||
@ -130,6 +130,7 @@ SOURCES += \
|
||||
nodes/QskBoxNode.cpp \
|
||||
nodes/QskBoxClipNode.cpp \
|
||||
nodes/QskBoxFillNode.cpp \
|
||||
nodes/QskBoxRectangleNode.cpp \
|
||||
nodes/QskBoxRendererRect.cpp \
|
||||
nodes/QskBoxRendererEllipse.cpp \
|
||||
nodes/QskBoxRendererDEllipse.cpp \
|
||||
@ -141,7 +142,6 @@ SOURCES += \
|
||||
nodes/QskRichTextRenderer.cpp \
|
||||
nodes/QskScaleRenderer.cpp \
|
||||
nodes/QskSGNode.cpp \
|
||||
nodes/QskShadedBoxNode.cpp \
|
||||
nodes/QskStrokeNode.cpp \
|
||||
nodes/QskShapeNode.cpp \
|
||||
nodes/QskGradientMaterial.cpp \
|
||||
|
Loading…
x
Reference in New Issue
Block a user