QskBoxClipNode renamed to QskClipNode + more clip options added
This commit is contained in:
parent
1e383406e2
commit
109fc7d7f4
|
@ -6,7 +6,7 @@
|
||||||
#include "QskMaterial3SliderSkinlet.h"
|
#include "QskMaterial3SliderSkinlet.h"
|
||||||
|
|
||||||
#include <QskSlider.h>
|
#include <QskSlider.h>
|
||||||
#include <QskVertex.h>
|
#include <QskClipNode.h>
|
||||||
#include <QskSGNode.h>
|
#include <QskSGNode.h>
|
||||||
|
|
||||||
#include <qmath.h>
|
#include <qmath.h>
|
||||||
|
@ -43,45 +43,6 @@ static inline qreal qskTickValue( const QskSlider* slider, int index )
|
||||||
return slider->maximum();
|
return slider->maximum();
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
class ClipNode : public QSGClipNode
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ClipNode()
|
|
||||||
: m_geometry( QSGGeometry::defaultAttributes_Point2D(), 0 )
|
|
||||||
{
|
|
||||||
m_geometry.setDrawingMode( QSGGeometry::DrawTriangleStrip );
|
|
||||||
setGeometry( &m_geometry );
|
|
||||||
}
|
|
||||||
|
|
||||||
void setRegion( const QRectF& boundingRect, const QRectF& rect )
|
|
||||||
{
|
|
||||||
if ( ( rect == clipRect() ) && ( m_boundingRect == boundingRect ) )
|
|
||||||
return;
|
|
||||||
|
|
||||||
setIsRectangular( false );
|
|
||||||
setClipRect( rect );
|
|
||||||
|
|
||||||
m_geometry.allocate( 2 * 5 ); // 2 points per line
|
|
||||||
|
|
||||||
const auto l = reinterpret_cast< QskVertex::Line* >( m_geometry.vertexData() );
|
|
||||||
l[0].setLine( boundingRect.topLeft(), rect.topLeft() );
|
|
||||||
l[1].setLine( boundingRect.topRight(), rect.topRight() );
|
|
||||||
l[2].setLine( boundingRect.bottomRight(), rect.bottomRight() );
|
|
||||||
l[3].setLine( boundingRect.bottomLeft(), rect.bottomLeft() );
|
|
||||||
l[4] = l[0];
|
|
||||||
|
|
||||||
m_geometry.markVertexDataDirty();
|
|
||||||
markDirty( QSGNode::DirtyGeometry );
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
QRectF m_boundingRect;
|
|
||||||
QSGGeometry m_geometry;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
QskMaterial3SliderSkinlet::QskMaterial3SliderSkinlet( QskSkin* skin )
|
QskMaterial3SliderSkinlet::QskMaterial3SliderSkinlet( QskSkin* skin )
|
||||||
: Inherited( skin )
|
: Inherited( skin )
|
||||||
{
|
{
|
||||||
|
@ -128,12 +89,10 @@ QSGNode* QskMaterial3SliderSkinlet::updateSubNode(
|
||||||
{
|
{
|
||||||
const auto slider = static_cast< const QskSlider* >( skinnable );
|
const auto slider = static_cast< const QskSlider* >( skinnable );
|
||||||
|
|
||||||
auto clipNode = QskSGNode::ensureNode< ClipNode >( node );
|
auto clipNode = QskSGNode::ensureNode< QskClipNode >( node );
|
||||||
|
|
||||||
clipNode->setRegion(
|
clipNode->setRegion( slider->subControlRect( Q::Panel ),
|
||||||
slider->subControlRect( Q::Panel ),
|
slider->subControlRect( Q::Handle ) );
|
||||||
slider->subControlRect( Q::Handle )
|
|
||||||
);
|
|
||||||
|
|
||||||
QskSGNode::setNodeRole( clippedNode, nodeRole );
|
QskSGNode::setNodeRole( clippedNode, nodeRole );
|
||||||
QskSGNode::setParentNode( clippedNode, clipNode );
|
QskSGNode::setParentNode( clippedNode, clipNode );
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
#include <QskSkinlet.h>
|
#include <QskSkinlet.h>
|
||||||
|
|
||||||
#include <QskQuick.h>
|
#include <QskQuick.h>
|
||||||
#include <QskBoxClipNode.h>
|
#include <QskClipNode.h>
|
||||||
#include <QskBoxBorderMetrics.h>
|
#include <QskBoxBorderMetrics.h>
|
||||||
|
|
||||||
#include <qsgnode.h>
|
#include <qsgnode.h>
|
||||||
|
@ -315,7 +315,7 @@ void QskPlotView::updateNode( QSGNode* node )
|
||||||
if ( m_data->needsClipping() )
|
if ( m_data->needsClipping() )
|
||||||
{
|
{
|
||||||
if ( itemsNode == nullptr || itemsNode->type() != QSGNode::ClipNodeType )
|
if ( itemsNode == nullptr || itemsNode->type() != QSGNode::ClipNodeType )
|
||||||
itemsNode = new QskBoxClipNode();
|
itemsNode = new QskClipNode();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -105,13 +105,13 @@ list(APPEND HEADERS
|
||||||
nodes/QskArcRenderNode.h
|
nodes/QskArcRenderNode.h
|
||||||
nodes/QskBasicLinesNode.h
|
nodes/QskBasicLinesNode.h
|
||||||
nodes/QskBoxNode.h
|
nodes/QskBoxNode.h
|
||||||
nodes/QskBoxClipNode.h
|
|
||||||
nodes/QskBoxRectangleNode.h
|
nodes/QskBoxRectangleNode.h
|
||||||
nodes/QskBoxRenderer.h
|
nodes/QskBoxRenderer.h
|
||||||
nodes/QskBoxMetrics.h
|
nodes/QskBoxMetrics.h
|
||||||
nodes/QskBoxBasicStroker.h
|
nodes/QskBoxBasicStroker.h
|
||||||
nodes/QskBoxGradientStroker.h
|
nodes/QskBoxGradientStroker.h
|
||||||
nodes/QskBoxShadowNode.h
|
nodes/QskBoxShadowNode.h
|
||||||
|
nodes/QskClipNode.h
|
||||||
nodes/QskColorRamp.h
|
nodes/QskColorRamp.h
|
||||||
nodes/QskFillNode.h
|
nodes/QskFillNode.h
|
||||||
nodes/QskGraduationNode.h
|
nodes/QskGraduationNode.h
|
||||||
|
@ -145,13 +145,13 @@ list(APPEND SOURCES
|
||||||
nodes/QskArcRenderNode.cpp
|
nodes/QskArcRenderNode.cpp
|
||||||
nodes/QskBasicLinesNode.cpp
|
nodes/QskBasicLinesNode.cpp
|
||||||
nodes/QskBoxNode.cpp
|
nodes/QskBoxNode.cpp
|
||||||
nodes/QskBoxClipNode.cpp
|
|
||||||
nodes/QskBoxRectangleNode.cpp
|
nodes/QskBoxRectangleNode.cpp
|
||||||
nodes/QskBoxRenderer.cpp
|
nodes/QskBoxRenderer.cpp
|
||||||
nodes/QskBoxMetrics.cpp
|
nodes/QskBoxMetrics.cpp
|
||||||
nodes/QskBoxBasicStroker.cpp
|
nodes/QskBoxBasicStroker.cpp
|
||||||
nodes/QskBoxGradientStroker.cpp
|
nodes/QskBoxGradientStroker.cpp
|
||||||
nodes/QskBoxShadowNode.cpp
|
nodes/QskBoxShadowNode.cpp
|
||||||
|
nodes/QskClipNode.cpp
|
||||||
nodes/QskColorRamp.cpp
|
nodes/QskColorRamp.cpp
|
||||||
nodes/QskFillNode.cpp
|
nodes/QskFillNode.cpp
|
||||||
nodes/QskGraduationNode.cpp
|
nodes/QskGraduationNode.cpp
|
||||||
|
|
|
@ -11,10 +11,10 @@
|
||||||
#include "QskBoxBorderColors.h"
|
#include "QskBoxBorderColors.h"
|
||||||
#include "QskBoxBorderMetrics.h"
|
#include "QskBoxBorderMetrics.h"
|
||||||
#include "QskBoxNode.h"
|
#include "QskBoxNode.h"
|
||||||
#include "QskBoxClipNode.h"
|
|
||||||
#include "QskBoxRectangleNode.h"
|
#include "QskBoxRectangleNode.h"
|
||||||
#include "QskBoxShapeMetrics.h"
|
#include "QskBoxShapeMetrics.h"
|
||||||
#include "QskBoxHints.h"
|
#include "QskBoxHints.h"
|
||||||
|
#include "QskClipNode.h"
|
||||||
#include "QskColorFilter.h"
|
#include "QskColorFilter.h"
|
||||||
#include "QskControl.h"
|
#include "QskControl.h"
|
||||||
#include "QskFunctions.h"
|
#include "QskFunctions.h"
|
||||||
|
@ -641,15 +641,14 @@ QSGNode* QskSkinlet::updateBoxClipNode( const QskSkinnable* skinnable,
|
||||||
QSGNode* QskSkinlet::updateBoxClipNode( const QskSkinnable* skinnable,
|
QSGNode* QskSkinlet::updateBoxClipNode( const QskSkinnable* skinnable,
|
||||||
QSGNode* node, const QRectF& rect, QskAspect::Subcontrol subControl )
|
QSGNode* node, const QRectF& rect, QskAspect::Subcontrol subControl )
|
||||||
{
|
{
|
||||||
auto clipNode = QskSGNode::ensureNode< QskBoxClipNode >( node );
|
auto clipNode = QskSGNode::ensureNode< QskClipNode >( node );
|
||||||
|
|
||||||
const auto margins = skinnable->marginHint( subControl );
|
const auto margins = skinnable->marginHint( subControl );
|
||||||
|
|
||||||
const auto clipRect = rect.marginsRemoved( margins );
|
const auto clipRect = rect.marginsRemoved( margins );
|
||||||
if ( clipRect.isEmpty() )
|
if ( clipRect.isEmpty() )
|
||||||
{
|
{
|
||||||
clipNode->setIsRectangular( true );
|
clipNode->setRect( clipRect );
|
||||||
clipNode->setClipRect( clipRect );
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,85 +0,0 @@
|
||||||
/******************************************************************************
|
|
||||||
* QSkinny - Copyright (C) The authors
|
|
||||||
* SPDX-License-Identifier: BSD-3-Clause
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
#include "QskBoxClipNode.h"
|
|
||||||
#include "QskBoxBorderMetrics.h"
|
|
||||||
#include "QskBoxRenderer.h"
|
|
||||||
#include "QskBoxShapeMetrics.h"
|
|
||||||
#include "QskFunctions.h"
|
|
||||||
|
|
||||||
#include <qquickitem.h>
|
|
||||||
|
|
||||||
static inline QskHashValue qskMetricsHash(
|
|
||||||
const QskBoxShapeMetrics& shape, const QskBoxBorderMetrics& border )
|
|
||||||
{
|
|
||||||
QskHashValue hash = 13000;
|
|
||||||
|
|
||||||
hash = shape.hash( hash );
|
|
||||||
return border.hash( hash );
|
|
||||||
}
|
|
||||||
|
|
||||||
QskBoxClipNode::QskBoxClipNode()
|
|
||||||
: m_hash( 0 )
|
|
||||||
, m_geometry( QSGGeometry::defaultAttributes_Point2D(), 0 )
|
|
||||||
{
|
|
||||||
setGeometry( &m_geometry );
|
|
||||||
}
|
|
||||||
|
|
||||||
QskBoxClipNode::~QskBoxClipNode()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void QskBoxClipNode::setBox( const QQuickWindow* window, const QRectF& rect,
|
|
||||||
const QskBoxShapeMetrics& shape, const QskBoxBorderMetrics& border )
|
|
||||||
{
|
|
||||||
const auto hash = qskMetricsHash( shape, border );
|
|
||||||
if ( hash == m_hash && rect == m_rect )
|
|
||||||
return;
|
|
||||||
|
|
||||||
m_rect = rect;
|
|
||||||
m_hash = hash;
|
|
||||||
|
|
||||||
bool isRectangular = false;
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
/*
|
|
||||||
Depending on isRectangular the "renderer can use scissoring instead of stencil,
|
|
||||||
which is significantly faster."
|
|
||||||
|
|
||||||
However the batch renderer ( qsgbatchrenderer.cpp ) is rounding the clip rectangle
|
|
||||||
to integers and the clip might become too small/large.
|
|
||||||
|
|
||||||
So we always have to use stencil clipping - even if it might have a negative
|
|
||||||
impact on the performance. TODO ...
|
|
||||||
*/
|
|
||||||
|
|
||||||
if ( shape.isRectangle() )
|
|
||||||
isRectangular = true;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if ( isRectangular )
|
|
||||||
{
|
|
||||||
if ( m_geometry.vertexCount() > 0 )
|
|
||||||
m_geometry.allocate( 0 );
|
|
||||||
|
|
||||||
setIsRectangular( true );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
setIsRectangular( false );
|
|
||||||
|
|
||||||
QskBoxRenderer renderer( window );
|
|
||||||
renderer.setFillLines( rect, shape, border, m_geometry );
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Even in situations, where the clipping is not rectangular, it is
|
|
||||||
useful to know its bounding rectangle
|
|
||||||
*/
|
|
||||||
setClipRect( qskValidOrEmptyInnerRect( rect, border.widths() ) );
|
|
||||||
|
|
||||||
m_geometry.markVertexDataDirty();
|
|
||||||
markDirty( QSGNode::DirtyGeometry );
|
|
||||||
}
|
|
|
@ -0,0 +1,151 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* QSkinny - Copyright (C) The authors
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#include "QskClipNode.h"
|
||||||
|
#include "QskBoxBorderMetrics.h"
|
||||||
|
#include "QskBoxRenderer.h"
|
||||||
|
#include "QskBoxShapeMetrics.h"
|
||||||
|
#include "QskFunctions.h"
|
||||||
|
#include "QskVertex.h"
|
||||||
|
|
||||||
|
#include <qquickwindow.h>
|
||||||
|
|
||||||
|
static inline QskHashValue qskMetricsHash(
|
||||||
|
const QskBoxShapeMetrics& shape, const QskBoxBorderMetrics& border )
|
||||||
|
{
|
||||||
|
QskHashValue hash = 13000;
|
||||||
|
|
||||||
|
hash = shape.hash( hash );
|
||||||
|
return border.hash( hash );
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void qskSetBoundingRect( QSGClipNode* node, const QRectF& rect )
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Depending on isRectangular: the "scene graph renderer can use
|
||||||
|
scissoring instead of stencil, which is significantly faster."
|
||||||
|
|
||||||
|
However the batch renderer ( qsgbatchrenderer.cpp ) is rounding
|
||||||
|
the clip rectangle to integers and the clip might become too small/large.
|
||||||
|
So we always have to use stencil clipping - even if it might have a negative
|
||||||
|
impact on the performance.
|
||||||
|
|
||||||
|
When isRectangular is set to false the clipRect is not used from the
|
||||||
|
renderer and we use the memory for the storing the bounding rectangle.
|
||||||
|
*/
|
||||||
|
|
||||||
|
node->setIsRectangular( false );
|
||||||
|
node->setClipRect( rect );
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline QskVertex::Line* qskAllocateLines(
|
||||||
|
QSGGeometry& geometry, int lineCount )
|
||||||
|
{
|
||||||
|
geometry.allocate( 2 * lineCount ); // 2 points per line
|
||||||
|
return reinterpret_cast< QskVertex::Line* >( geometry.vertexData() );
|
||||||
|
}
|
||||||
|
|
||||||
|
QskClipNode::QskClipNode()
|
||||||
|
: m_hash( 0 )
|
||||||
|
, m_geometry( QSGGeometry::defaultAttributes_Point2D(), 0 )
|
||||||
|
{
|
||||||
|
setGeometry( &m_geometry );
|
||||||
|
}
|
||||||
|
|
||||||
|
QskClipNode::~QskClipNode()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void QskClipNode::setRect( const QRectF& rect )
|
||||||
|
{
|
||||||
|
setRegion( rect, QRectF() );
|
||||||
|
}
|
||||||
|
|
||||||
|
void QskClipNode::setRegion( const QRectF& rect, const QRectF& excludedRect )
|
||||||
|
{
|
||||||
|
if ( rect.isEmpty() )
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
what about rectangles having a width/height
|
||||||
|
of 0 ( f.e lines ) TODO ...
|
||||||
|
*/
|
||||||
|
reset();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto innerRect = excludedRect.isEmpty()
|
||||||
|
? QRectF() : excludedRect.intersected( rect );
|
||||||
|
|
||||||
|
const auto hash = qHashBits( &innerRect, sizeof( innerRect ), 1450 );
|
||||||
|
if ( ( hash == m_hash ) && ( rect == Inherited::clipRect() ) )
|
||||||
|
return;
|
||||||
|
|
||||||
|
qskSetBoundingRect( this, rect );
|
||||||
|
m_hash = hash;
|
||||||
|
|
||||||
|
m_geometry.setDrawingMode( QSGGeometry::DrawTriangleStrip );
|
||||||
|
|
||||||
|
if ( innerRect.isEmpty() )
|
||||||
|
{
|
||||||
|
const auto l = qskAllocateLines( m_geometry, 2 );
|
||||||
|
|
||||||
|
l[0].setLine( rect.topLeft(), rect.topRight() );
|
||||||
|
l[1].setLine( rect.bottomLeft(), rect.bottomRight() );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const auto l = qskAllocateLines( m_geometry, 5 );
|
||||||
|
|
||||||
|
l[0].setLine( rect.topLeft(), innerRect.topLeft() );
|
||||||
|
l[1].setLine( rect.topRight(), innerRect.topRight() );
|
||||||
|
l[2].setLine( rect.bottomRight(), innerRect.bottomRight() );
|
||||||
|
l[3].setLine( rect.bottomLeft(), innerRect.bottomLeft() );
|
||||||
|
l[4] = l[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
m_geometry.markVertexDataDirty();
|
||||||
|
markDirty( QSGNode::DirtyGeometry );
|
||||||
|
}
|
||||||
|
|
||||||
|
void QskClipNode::setBox( const QQuickWindow* window, const QRectF& rect,
|
||||||
|
const QskBoxShapeMetrics& shape, const QskBoxBorderMetrics& border )
|
||||||
|
{
|
||||||
|
if ( rect.isEmpty() )
|
||||||
|
{
|
||||||
|
reset();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto hash = qskMetricsHash( shape, border );
|
||||||
|
if ( hash == m_hash && rect == boundingRectangle() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
qskSetBoundingRect( this, rect );
|
||||||
|
m_hash = hash;
|
||||||
|
|
||||||
|
QskBoxRenderer renderer( window );
|
||||||
|
renderer.setFillLines( rect, shape, border, m_geometry );
|
||||||
|
|
||||||
|
m_geometry.markVertexDataDirty();
|
||||||
|
markDirty( QSGNode::DirtyGeometry );
|
||||||
|
}
|
||||||
|
|
||||||
|
void QskClipNode::reset()
|
||||||
|
{
|
||||||
|
Inherited::setIsRectangular( true );
|
||||||
|
Inherited::setClipRect( QRectF() );
|
||||||
|
|
||||||
|
if ( m_geometry.vertexData() )
|
||||||
|
{
|
||||||
|
m_geometry.allocate( 0 );
|
||||||
|
m_geometry.markVertexDataDirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( m_hash != 0 )
|
||||||
|
{
|
||||||
|
m_hash = 0;
|
||||||
|
markDirty( QSGNode::DirtyGeometry );
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,8 +3,8 @@
|
||||||
* SPDX-License-Identifier: BSD-3-Clause
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
#ifndef QSK_BOX_CLIP_NODE_H
|
#ifndef QSK_CLIP_NODE_H
|
||||||
#define QSK_BOX_CLIP_NODE_H
|
#define QSK_CLIP_NODE_H
|
||||||
|
|
||||||
#include "QskGlobal.h"
|
#include "QskGlobal.h"
|
||||||
#include <qsgnode.h>
|
#include <qsgnode.h>
|
||||||
|
@ -14,20 +14,36 @@ class QskBoxBorderMetrics;
|
||||||
|
|
||||||
class QQuickWindow;
|
class QQuickWindow;
|
||||||
|
|
||||||
class QSK_EXPORT QskBoxClipNode : public QSGClipNode
|
class QSK_EXPORT QskClipNode : public QSGClipNode
|
||||||
{
|
{
|
||||||
|
using Inherited = QSGClipNode;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
QskBoxClipNode();
|
QskClipNode();
|
||||||
~QskBoxClipNode() override;
|
~QskClipNode() override;
|
||||||
|
|
||||||
|
void setRect( const QRectF& );
|
||||||
|
void setRegion( const QRectF&, const QRectF& excludedRect );
|
||||||
|
|
||||||
void setBox( const QQuickWindow*, const QRectF&,
|
void setBox( const QQuickWindow*, const QRectF&,
|
||||||
const QskBoxShapeMetrics&, const QskBoxBorderMetrics& );
|
const QskBoxShapeMetrics&, const QskBoxBorderMetrics& );
|
||||||
|
|
||||||
private:
|
QRectF boundingRectangle() const;
|
||||||
QskHashValue m_hash;
|
|
||||||
QRectF m_rect;
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
void reset();
|
||||||
|
|
||||||
|
void setIsRectangular( bool ) = delete;
|
||||||
|
void setClipRect( const QRectF& ) = delete;
|
||||||
|
QRectF clipRect() const = delete;
|
||||||
|
|
||||||
|
QskHashValue m_hash;
|
||||||
QSGGeometry m_geometry;
|
QSGGeometry m_geometry;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline QRectF QskClipNode::boundingRectangle() const
|
||||||
|
{
|
||||||
|
return Inherited::clipRect();
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
Loading…
Reference in New Issue