codemoved to QskSGNode

This commit is contained in:
Uwe Rathmann 2020-11-22 15:27:58 +01:00
parent e8351e4496
commit 8fb18ab145
10 changed files with 263 additions and 180 deletions

View File

@ -10,7 +10,7 @@
#include <QskBoxNode.h>
#include <QskBoxShapeMetrics.h>
#include <QskGradient.h>
#include <QskSkinlet.h>
#include <QskSGNode.h>
static inline qreal effectiveRadius( const QRectF& rect, qreal percentage )
{
@ -100,7 +100,7 @@ void Frame::updateNode( QSGNode* parentNode )
const quint8 nodeRole = 0;
auto node = static_cast< QskBoxNode* >(
QskSkinlet::findNodeByRole( parentNode, nodeRole ) );
QskSGNode::findChildNode( parentNode, nodeRole ) );
const QRectF rect = contentsRect();
if ( rect.isEmpty() )
@ -112,7 +112,7 @@ void Frame::updateNode( QSGNode* parentNode )
if ( node == nullptr )
{
node = new QskBoxNode;
QskSkinlet::setNodeRole( node, nodeRole );
QskSGNode::setNodeRole( node, nodeRole );
}
updateFrameNode( rect, node );

View File

@ -8,6 +8,7 @@
#include "QskColorFilter.h"
#include "QskGraphic.h"
#include "QskSGNode.h"
#include <qmath.h>
#include <qsgnode.h>
@ -431,6 +432,8 @@ QSGTransformNode* QskListViewSkinlet::updateForegroundNode(
QSGNode* QskListViewSkinlet::updateCellNode( const QskListView* listView,
QSGNode* contentNode, const QRectF& rect, int row, int col ) const
{
using namespace QskSGNode;
QSGNode* newNode = nullptr;
#if 1

View File

@ -7,6 +7,7 @@
#include "QskPageIndicator.h"
#include "QskBoxNode.h"
#include "QskSGNode.h"
QskPageIndicatorSkinlet::QskPageIndicatorSkinlet( QskSkin* skin )
: QskSkinlet( skin )
@ -162,7 +163,7 @@ QSGNode* QskPageIndicatorSkinlet::updateBulletsNode(
}
// if count has decreased we need to remove superfluous nodes
removeTraillingNodes( node, bulletNode );
QskSGNode::removeAllChildNodesAfter( node, bulletNode );
return node;
}

View File

@ -8,6 +8,7 @@
#include "QskQuick.h"
#include "QskScrollViewSkinlet.h"
#include "QskBoxBorderMetrics.h"
#include "QskSGNode.h"
QSK_QT_PRIVATE_BEGIN
#include <private/qquickclipnode_p.h>
@ -322,7 +323,7 @@ namespace
{
auto node = const_cast< QSGNode* >( qskPaintNode( scrollArea() ) );
if ( node )
node = QskSkinlet::findNodeByRole( node, QskScrollViewSkinlet::ContentsRootRole );
node = QskSGNode::findChildNode( node, QskScrollViewSkinlet::ContentsRootRole );
if ( node && node->type() == QSGNode::ClipNodeType )
return static_cast< QSGClipNode* >( node );

View File

@ -8,6 +8,7 @@
#include "QskAspect.h"
#include "QskQuick.h"
#include "QskSGNode.h"
#include <qsgnode.h>
@ -129,8 +130,8 @@ QSGNode* QskScrollViewSkinlet::updateContentsRootNode(
if ( clipNode == nullptr )
return nullptr;
QSGNode* oldContentsNode = findNodeByRole( clipNode, ContentsRootRole );
QSGNode* contentsNode = updateContentsNode( scrollView, oldContentsNode );
auto oldContentsNode = QskSGNode::findChildNode( clipNode, ContentsRootRole );
auto contentsNode = updateContentsNode( scrollView, oldContentsNode );
if ( contentsNode )
{
@ -141,7 +142,7 @@ QSGNode* QskScrollViewSkinlet::updateContentsRootNode(
For those situations we need to set a node role, that we can decide
which child of the clip node needs to be replaced.
*/
setNodeRole( contentsNode, ContentsRootRole );
QskSGNode::setNodeRole( contentsNode, ContentsRootRole );
if ( contentsNode->parent() != clipNode )
clipNode->appendChildNode( contentsNode );
@ -169,7 +170,7 @@ QSGNode* QskScrollViewSkinlet::contentsNode( const QskScrollView* scrollView )
QSGNode* node = const_cast< QSGNode* >( qskPaintNode( scrollView ) );
if ( node )
{
node = findNodeByRole( node, ContentsRootRole );
node = QskSGNode::findChildNode( node, ContentsRootRole );
if ( node )
{
node = node->firstChild();

View File

@ -17,47 +17,14 @@
#include "QskGradient.h"
#include "QskGraphicNode.h"
#include "QskGraphic.h"
#include "QskSGNode.h"
#include "QskTextColors.h"
#include "QskTextNode.h"
#include "QskTextOptions.h"
#include <qguiapplication.h>
#include <qquickwindow.h>
#include <qsgsimplerectnode.h>
static const int qskBackgroundRole = 254;
static const int qskDebugRole = 253;
static inline QSGNode::Flags qskNodeFlags( quint8 nodeRole )
{
return static_cast< QSGNode::Flags >( ( nodeRole + 1 ) << 8 );
}
static inline quint8 qskRole( const QSGNode* node )
{
return static_cast< quint8 >( ( ( node->flags() & 0x0ffff ) >> 8 ) - 1 );
}
static inline void qskSetRole( quint8 nodeRole, QSGNode* node )
{
const QSGNode::Flags flags = qskNodeFlags( nodeRole );
node->setFlags( node->flags() | flags );
}
static inline QSGNode* qskFindNodeByFlag( QSGNode* parent, int nodeRole )
{
auto node = parent->firstChild();
while ( node )
{
if ( qskRole( node ) == nodeRole )
return node;
node = node->nextSibling();
}
return nullptr;
}
static inline QRectF qskSubControlRect( const QskSkinlet* skinlet,
const QskSkinnable* skinnable, QskAspect::Subcontrol subControl )
{
@ -200,6 +167,8 @@ const QVector< quint8 >& QskSkinlet::nodeRoles() const
void QskSkinlet::updateNode( QskSkinnable* skinnable, QSGNode* parentNode ) const
{
using namespace QskSGNode;
QSGNode* oldNode;
QSGNode* newNode;
@ -207,35 +176,35 @@ void QskSkinlet::updateNode( QskSkinnable* skinnable, QSGNode* parentNode ) cons
{
// background
oldNode = qskFindNodeByFlag( parentNode, qskBackgroundRole );
oldNode = findChildNode( parentNode, BackgroundRole );
newNode = nullptr;
if ( control->autoFillBackground() )
newNode = updateBackgroundNode( control, oldNode );
insertRemoveNodes( parentNode, oldNode, newNode, qskBackgroundRole );
replaceChildNode( BackgroundRole, parentNode, oldNode, newNode );
// debug
oldNode = qskFindNodeByFlag( parentNode, qskDebugRole );
oldNode = findChildNode( parentNode, DebugRole );
newNode = nullptr;
if ( control->testControlFlag( QskControl::DebugForceBackground ) )
newNode = updateDebugNode( control, oldNode );
insertRemoveNodes( parentNode, oldNode, newNode, qskDebugRole );
replaceChildNode( DebugRole, parentNode, oldNode, newNode );
}
for ( int i = 0; i < m_data->nodeRoles.size(); i++ )
{
const auto nodeRole = m_data->nodeRoles[ i ];
Q_ASSERT( nodeRole <= 245 ); // reserving 10 roles
Q_ASSERT( nodeRole < FirstReservedRole );
oldNode = qskFindNodeByFlag( parentNode, nodeRole );
oldNode = QskSGNode::findChildNode( parentNode, nodeRole );
newNode = updateSubNode( skinnable, nodeRole, oldNode );
insertRemoveNodes( parentNode, oldNode, newNode, nodeRole );
replaceChildNode( nodeRole, parentNode, oldNode, newNode );
}
}
@ -262,9 +231,7 @@ QSGNode* QskSkinlet::updateDebugNode(
const QskControl* control, QSGNode* node ) const
{
if ( control->size().isEmpty() )
{
return nullptr;
}
auto rectNode = static_cast< QSGSimpleRectNode* >( node );
if ( rectNode == nullptr )
@ -290,125 +257,24 @@ QSGNode* QskSkinlet::updateDebugNode(
rectNode->setColor( color );
}
const QRectF r = control->rect();
const auto r = control->rect();
if ( rectNode->rect() != r )
rectNode->setRect( r );
return rectNode;
}
void QskSkinlet::insertRemoveNodes( QSGNode* parentNode,
QSGNode* oldNode, QSGNode* newNode, quint8 nodeRole ) const
void QskSkinlet::replaceChildNode( quint8 role,
QSGNode* parentNode, QSGNode* oldNode, QSGNode* newNode ) const
{
if ( newNode && newNode->parent() != parentNode )
{
qskSetRole( nodeRole, newNode );
switch ( nodeRole )
{
case qskBackgroundRole:
{
parentNode->prependChildNode( newNode );
break;
}
case qskDebugRole:
{
QSGNode* firstNode = parentNode->firstChild();
if ( firstNode && ( qskRole( firstNode ) == qskBackgroundRole ) )
parentNode->insertChildNodeAfter( newNode, firstNode );
else
parentNode->prependChildNode( newNode );
break;
}
default:
{
insertNodeSorted( newNode, parentNode );
}
}
}
if ( oldNode && oldNode != newNode )
{
parentNode->removeChildNode( oldNode );
if ( oldNode->flags() & QSGNode::OwnedByParent )
delete oldNode;
}
}
void QskSkinlet::insertNodeSorted( QSGNode* node, QSGNode* parentNode ) const
{
QSGNode* sibling = nullptr;
if ( parentNode->childCount() > 0 )
{
const int nodePos = m_data->nodeRoles.indexOf( qskRole( node ) );
// in most cases we are appending, so let's start at the end
for ( QSGNode* childNode = parentNode->lastChild();
childNode != nullptr; childNode = childNode->previousSibling() )
{
const auto childNodeRole = qskRole( childNode );
if ( childNodeRole == qskBackgroundRole )
{
sibling = childNode;
}
else
{
/*
Imperformant implementation, but as the number of roles is
usually < 5 we don't introduce some sort of support for faster lookups
*/
const int index = m_data->nodeRoles.indexOf( qskRole( childNode ) );
if ( index >= 0 && index < nodePos )
sibling = childNode;
}
if ( sibling != nullptr )
break;
}
}
if ( sibling )
parentNode->insertChildNodeAfter( node, sibling );
else
parentNode->prependChildNode( node );
}
void QskSkinlet::removeTraillingNodes( QSGNode* node, QSGNode* child )
{
if ( node && child )
{
while ( auto sibling = child->nextSibling() )
{
node->removeChildNode( sibling );
delete sibling;
}
}
}
void QskSkinlet::setNodeRole( QSGNode* node, quint8 nodeRole )
{
qskSetRole( nodeRole, node );
}
quint8 QskSkinlet::nodeRole( const QSGNode* node )
{
return node ? qskRole( node ) : 0;
}
QSGNode* QskSkinlet::findNodeByRole( QSGNode* parent, quint8 nodeRole )
{
return qskFindNodeByFlag( parent, nodeRole );
QskSGNode::replaceChildNode(
m_data->nodeRoles, role, parentNode, oldNode, newNode );
}
QSGNode* QskSkinlet::updateBoxNode( const QskSkinnable* skinnable,
QSGNode* node, QskAspect::Subcontrol subControl ) const
{
const QRectF rect = qskSubControlRect( this, skinnable, subControl );
const auto rect = qskSubControlRect( this, skinnable, subControl );
return updateBoxNode( skinnable, node, rect, subControl );
}
@ -425,9 +291,9 @@ QSGNode* QskSkinlet::updateBoxNode( const QskSkinnable* skinnable,
{
using namespace QskAspect;
const QMarginsF margins = skinnable->marginsHint( subControl | Margin );
const auto margins = skinnable->marginsHint( subControl | Margin );
const QRectF boxRect = rect.marginsRemoved( margins );
const auto boxRect = rect.marginsRemoved( margins );
if ( boxRect.isEmpty() )
return nullptr;
@ -454,7 +320,7 @@ QSGNode* QskSkinlet::updateBoxNode( const QskSkinnable* skinnable,
QSGNode* QskSkinlet::updateBoxClipNode( const QskSkinnable* skinnable,
QSGNode* node, QskAspect::Subcontrol subControl ) const
{
const QRectF rect = qskSubControlRect( this, skinnable, subControl );
const auto rect = qskSubControlRect( this, skinnable, subControl );
return updateBoxClipNode( skinnable, node, rect, subControl );
}
@ -467,9 +333,9 @@ QSGNode* QskSkinlet::updateBoxClipNode( const QskSkinnable* skinnable,
if ( clipNode == nullptr )
clipNode = new QskBoxClipNode();
const QMarginsF margins = skinnable->marginsHint( subControl | Margin );
const auto margins = skinnable->marginsHint( subControl | Margin );
const QRectF clipRect = rect.marginsRemoved( margins );
const auto clipRect = rect.marginsRemoved( margins );
if ( clipRect.isEmpty() )
{
clipNode->setIsRectangular( true );
@ -502,7 +368,7 @@ QSGNode* QskSkinlet::updateTextNode(
if ( textNode == nullptr )
textNode = new QskTextNode();
auto colors = qskTextColors( skinnable, subControl );
const auto colors = qskTextColors( skinnable, subControl );
auto textStyle = Qsk::Normal;
if ( colors.styleColor.alpha() == 0 )
@ -542,7 +408,7 @@ QSGNode* QskSkinlet::updateTextNode(
const QString& text, const QskTextOptions& textOptions,
QskAspect::Subcontrol subControl ) const
{
const QRectF rect = qskSubControlRect( this, skinnable, subControl );
const auto rect = qskSubControlRect( this, skinnable, subControl );
const auto alignment = skinnable->flagHint< Qt::Alignment >(
QskAspect::Alignment | subControl, Qt::AlignLeft );
@ -555,9 +421,9 @@ QSGNode* QskSkinlet::updateGraphicNode(
const QskGraphic& graphic, QskAspect::Subcontrol subcontrol,
Qt::Orientations mirrored ) const
{
const QRectF rect = qskSubControlRect( this, skinnable, subcontrol );
const auto rect = qskSubControlRect( this, skinnable, subcontrol );
const Qt::Alignment alignment = skinnable->flagHint< Qt::Alignment >(
const auto alignment = skinnable->flagHint< Qt::Alignment >(
subcontrol | QskAspect::Alignment, Qt::AlignCenter );
const auto colorFilter = skinnable->effectiveGraphicFilter( subcontrol );
@ -574,10 +440,10 @@ QSGNode* QskSkinlet::updateGraphicNode(
if ( graphic.isNull() )
return nullptr;
const QSizeF size = graphic.defaultSize().scaled(
const auto size = graphic.defaultSize().scaled(
rect.size(), Qt::KeepAspectRatio );
const QRectF r = qskAlignedRectF( rect, size.width(), size.height(), alignment );
const auto r = qskAlignedRectF( rect, size.width(), size.height(), alignment );
return qskUpdateGraphicNode( skinnable, node, graphic, colorFilter, r, mirrored );
}

View File

@ -47,12 +47,6 @@ class QSK_EXPORT QskSkinlet
void setOwnedBySkinnable( bool on );
bool isOwnedBySkinnable() const;
static void setNodeRole( QSGNode* node, quint8 nodeRole );
static quint8 nodeRole( const QSGNode* node );
static void removeTraillingNodes( QSGNode* node, QSGNode* child );
static QSGNode* findNodeByRole( QSGNode* parent, quint8 nodeRole );
static QSGNode* updateBoxNode( const QskSkinnable*, QSGNode*,
const QRectF&, QskAspect::Subcontrol );
@ -102,12 +96,10 @@ class QSK_EXPORT QskSkinlet
const QskGraphic&, QskAspect::Subcontrol,
Qt::Orientations mirrored = Qt::Orientations() ) const;
void insertRemoveNodes( QSGNode* parentNode,
QSGNode* oldNode, QSGNode* newNode, quint8 nodeRole ) const;
void replaceChildNode( quint8 nodeRole, QSGNode* parentNode,
QSGNode* oldNode, QSGNode* newNode ) const;
private:
void insertNodeSorted( QSGNode* node, QSGNode* parentNode ) const;
class PrivateData;
std::unique_ptr< PrivateData > m_data;
};

140
src/nodes/QskSGNode.cpp Normal file
View File

@ -0,0 +1,140 @@
/******************************************************************************
* QSkinny - Copyright (C) 2016 Uwe Rathmann
* This file may be used under the terms of the QSkinny License, Version 1.0
*****************************************************************************/
#include "QskSGNode.h"
static inline void qskRemoveChildNode( QSGNode* parent, QSGNode* child )
{
parent->removeChildNode( child );
if ( child->flags() & QSGNode::OwnedByParent )
delete child;
}
static inline void qskRemoveAllChildNodesAfter( QSGNode* parent, QSGNode* child )
{
while ( auto sibling = parent->lastChild() )
{
if ( sibling == child )
return;
qskRemoveChildNode( parent, sibling );
}
}
static void qskInsertChildSorted( QSGNode* parent, QSGNode* child,
const QVector< quint8 >& roles )
{
QSGNode* sibling = nullptr;
if ( parent->childCount() > 0 )
{
using namespace QskSGNode;
const int nodePos = roles.indexOf( nodeRole( child ) );
// in most cases we are appending, so let's start at the end
for ( auto childNode = parent->lastChild();
childNode != nullptr; childNode = childNode->previousSibling() )
{
const auto childNodeRole = nodeRole( childNode );
if ( childNodeRole == BackgroundRole )
{
sibling = childNode;
}
else
{
/*
Imperformant implementation, but as the number of roles is
usually < 5 we don't introduce some sort of support for faster lookups
*/
const int index = roles.indexOf( nodeRole( childNode ) );
if ( index >= 0 && index < nodePos )
sibling = childNode;
}
if ( sibling != nullptr )
break;
}
}
if ( sibling )
parent->insertChildNodeAfter( child, sibling );
else
parent->prependChildNode( child );
}
QSGNode* QskSGNode::findChildNode( QSGNode* parent, quint8 role )
{
auto node = parent->firstChild();
while ( node )
{
if ( nodeRole( node ) == role )
return node;
node = node->nextSibling();
}
return nullptr;
}
void QskSGNode::removeAllChildNodesAfter( QSGNode* parent, QSGNode* child )
{
if ( parent && child && child->parent() == parent )
qskRemoveAllChildNodesAfter( parent, child );
}
void QskSGNode::removeAllChildNodesFrom( QSGNode* parent, QSGNode* child )
{
if ( parent && child && child->parent() == parent )
{
qskRemoveAllChildNodesAfter( parent, child );
qskRemoveChildNode( parent, child );
}
}
void QskSGNode::replaceChildNode(
const QVector< quint8 >& roles, quint8 role,
QSGNode* parentNode, QSGNode* oldNode, QSGNode* newNode )
{
if ( newNode && newNode->parent() != parentNode )
{
setNodeRole( newNode, role );
switch ( role )
{
case BackgroundRole:
{
parentNode->prependChildNode( newNode );
break;
}
case DebugRole:
{
auto firstNode = parentNode->firstChild();
if ( firstNode && ( nodeRole( firstNode ) == BackgroundRole ) )
parentNode->insertChildNodeAfter( newNode, firstNode );
else
parentNode->prependChildNode( newNode );
break;
}
default:
{
qskInsertChildSorted( parentNode, newNode, roles );
}
}
}
if ( oldNode && oldNode != newNode )
{
parentNode->removeChildNode( oldNode );
if ( oldNode->flags() & QSGNode::OwnedByParent )
delete oldNode;
}
}

77
src/nodes/QskSGNode.h Normal file
View File

@ -0,0 +1,77 @@
/******************************************************************************
* QSkinny - Copyright (C) 2016 Uwe Rathmann
* This file may be used under the terms of the QSkinny License, Version 1.0
*****************************************************************************/
#ifndef QSK_SG_NODE_H
#define QSK_SG_NODE_H
#include "QskGlobal.h"
#include <qsgnode.h>
namespace QskSGNode
{
enum Role : quint8
{
FirstReservedRole = 0xff - 10,
DebugRole = 0xff - 2,
BackgroundRole,
NoRole
};
inline QSGNode::Flags nodeRoleFlags( quint8 role )
{
return static_cast< QSGNode::Flags >( ( role + 1 ) << 8 );
}
inline quint8 nodeRole( QSGNode::Flags flags )
{
return static_cast< quint8 >( ( ( flags & 0x0ffff ) >> 8 ) - 1 );
}
inline quint8 nodeRole( const QSGNode* node )
{
return node ? nodeRole( node->flags() ) : 0xff;
}
inline void setNodeRole( QSGNode* node, quint8 role )
{
if ( node )
node->setFlags( node->flags() | nodeRoleFlags( role ) );
}
QSK_EXPORT QSGNode* findChildNode( QSGNode* parent, quint8 role );
// nodeRoles: sort order
QSK_EXPORT void replaceChildNode(
const QVector< quint8 >& roles, quint8 role,
QSGNode* parentNode, QSGNode* oldNode, QSGNode* newNode );
// without child
QSK_EXPORT void removeAllChildNodesAfter( QSGNode* parent, QSGNode* child );
// including child
QSK_EXPORT void removeAllChildNodesFrom( QSGNode* parent, QSGNode* child );
template< typename Node >
inline Node* createNode( quint8 role )
{
auto node = new Node();
setNodeRole( node, role );
return node;
}
template< typename Node >
inline Node* appendChildNode( QSGNode* parent, quint8 role )
{
auto node = createNode< Node >( role );
parent->appendChildNode( node );
return node;
}
}
#endif

View File

@ -92,6 +92,7 @@ HEADERS += \
nodes/QskPaintedNode.h \
nodes/QskPlainTextRenderer.h \
nodes/QskRichTextRenderer.h \
nodes/QskSGNode.h \
nodes/QskTextNode.h \
nodes/QskTextRenderer.h \
nodes/QskTextureNode.h \
@ -109,6 +110,7 @@ SOURCES += \
nodes/QskPaintedNode.cpp \
nodes/QskPlainTextRenderer.cpp \
nodes/QskRichTextRenderer.cpp \
nodes/QskSGNode.cpp \
nodes/QskTextNode.cpp \
nodes/QskTextRenderer.cpp \
nodes/QskTextureNode.cpp \