QskBoxFillNode introduced
This commit is contained in:
parent
3b6967615c
commit
68cca6a53c
@ -108,6 +108,7 @@ list(APPEND HEADERS
|
||||
nodes/QskBoxColorMap.h
|
||||
nodes/QskBoxShadowNode.h
|
||||
nodes/QskColorRamp.h
|
||||
nodes/QskFillNode.h
|
||||
nodes/QskGraphicNode.h
|
||||
nodes/QskLinesNode.h
|
||||
nodes/QskPaintedNode.h
|
||||
@ -126,6 +127,10 @@ list(APPEND HEADERS
|
||||
nodes/QskVertex.h
|
||||
)
|
||||
|
||||
list(APPEND PRIVATE_HEADERS
|
||||
nodes/QskFillNodePrivate.h
|
||||
)
|
||||
|
||||
list(APPEND SOURCES
|
||||
nodes/QskArcNode.cpp
|
||||
nodes/QskBoxNode.cpp
|
||||
@ -138,6 +143,7 @@ list(APPEND SOURCES
|
||||
nodes/QskBoxGradientStroker.cpp
|
||||
nodes/QskBoxShadowNode.cpp
|
||||
nodes/QskColorRamp.cpp
|
||||
nodes/QskFillNode.cpp
|
||||
nodes/QskGraphicNode.cpp
|
||||
nodes/QskLinesNode.cpp
|
||||
nodes/QskPaintedNode.cpp
|
||||
|
@ -76,5 +76,6 @@ void QskBoxClipNode::setBox( const QRectF& rect,
|
||||
*/
|
||||
setClipRect( qskValidOrEmptyInnerRect( rect, border.widths() ) );
|
||||
|
||||
m_geometry.markVertexDataDirty();
|
||||
markDirty( QSGNode::DirtyGeometry );
|
||||
}
|
||||
|
@ -10,13 +10,7 @@
|
||||
#include "QskBoxShapeMetrics.h"
|
||||
#include "QskBoxBorderMetrics.h"
|
||||
#include "QskBoxRenderer.h"
|
||||
#include "QskSGNode.h"
|
||||
|
||||
#include <qsgflatcolormaterial.h>
|
||||
|
||||
QSK_QT_PRIVATE_BEGIN
|
||||
#include <private/qsgnode_p.h>
|
||||
QSK_QT_PRIVATE_END
|
||||
#include "QskFillNodePrivate.h"
|
||||
|
||||
static inline QskHashValue qskMetricsHash(
|
||||
const QskBoxShapeMetrics& shape, const QskBoxBorderMetrics& borderMetrics )
|
||||
@ -27,14 +21,9 @@ static inline QskHashValue qskMetricsHash(
|
||||
return borderMetrics.hash( hash );
|
||||
}
|
||||
|
||||
class QskBoxFillNodePrivate final : public QSGGeometryNodePrivate
|
||||
class QskBoxFillNodePrivate final : public QskFillNodePrivate
|
||||
{
|
||||
public:
|
||||
QskBoxFillNodePrivate()
|
||||
: geometry( QSGGeometry::defaultAttributes_Point2D(), 0 )
|
||||
{
|
||||
}
|
||||
|
||||
inline void resetValues()
|
||||
{
|
||||
rect = QRectF();
|
||||
@ -46,19 +35,11 @@ class QskBoxFillNodePrivate final : public QSGGeometryNodePrivate
|
||||
|
||||
QskHashValue gradientHash = 0;
|
||||
QskHashValue metricsHash = 0;
|
||||
|
||||
QSGGeometry geometry;
|
||||
int gradientType = -1;
|
||||
};
|
||||
|
||||
QskBoxFillNode::QskBoxFillNode()
|
||||
: QSGGeometryNode( *new QskBoxFillNodePrivate )
|
||||
: QskFillNode( *new QskBoxFillNodePrivate )
|
||||
{
|
||||
Q_D( QskBoxFillNode );
|
||||
|
||||
setGeometry( &d->geometry );
|
||||
setMaterial( new QSGFlatColorMaterial() );
|
||||
setFlag( QSGNode::OwnsMaterial, true );
|
||||
}
|
||||
|
||||
void QskBoxFillNode::updateNode( const QRectF& rect, const QskGradient& gradient )
|
||||
@ -75,7 +56,7 @@ void QskBoxFillNode::updateNode(
|
||||
if ( rect.isEmpty() || !gradient.isVisible() )
|
||||
{
|
||||
d->resetValues();
|
||||
QskSGNode::resetGeometry( this );
|
||||
resetGeometry();
|
||||
|
||||
return;
|
||||
}
|
||||
@ -92,48 +73,22 @@ void QskBoxFillNode::updateNode(
|
||||
|
||||
if ( dirtyMetrics )
|
||||
{
|
||||
QskBox::renderFillGeometry( rect, shapeMetrics, borderMetrics, d->geometry );
|
||||
QskBox::renderFillGeometry( rect, shapeMetrics, borderMetrics, *geometry() );
|
||||
|
||||
markDirty( QSGNode::DirtyGeometry );
|
||||
geometry()->markVertexDataDirty();
|
||||
}
|
||||
|
||||
if ( gradient.isMonochrome() )
|
||||
{
|
||||
if ( dirtyColors )
|
||||
{
|
||||
if ( material() == nullptr || d->gradientType >= 0 )
|
||||
{
|
||||
setMaterial( new QSGFlatColorMaterial() );
|
||||
d->gradientType = -1;
|
||||
}
|
||||
|
||||
const auto color = gradient.startColor().toRgb();
|
||||
|
||||
auto mat = static_cast< QSGFlatColorMaterial* >( material() );
|
||||
if ( mat->color() != color )
|
||||
{
|
||||
mat->setColor( color );
|
||||
markDirty( QSGNode::DirtyMaterial );
|
||||
}
|
||||
}
|
||||
setColoring( gradient.startColor().toRgb() );
|
||||
}
|
||||
else
|
||||
{
|
||||
// dirtyMetrics: the shader also depends on the target rectangle !
|
||||
|
||||
if ( dirtyColors || dirtyMetrics )
|
||||
{
|
||||
const auto effectiveGradient = gradient.effectiveGradient();
|
||||
const auto gradientType = effectiveGradient.type();
|
||||
|
||||
if ( ( material() == nullptr ) || ( gradientType != d->gradientType ) )
|
||||
{
|
||||
setMaterial( QskGradientMaterial::createMaterial( gradientType ) );
|
||||
d->gradientType = gradientType;
|
||||
}
|
||||
|
||||
auto mat = static_cast< QskGradientMaterial* >( material() );
|
||||
if ( mat->updateGradient( rect, effectiveGradient ) )
|
||||
markDirty( QSGNode::DirtyMaterial );
|
||||
}
|
||||
setColoring( rect, gradient.effectiveGradient() );
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,7 @@
|
||||
#define QSK_BOX_FILL_NODE_H
|
||||
|
||||
#include "QskGlobal.h"
|
||||
#include <qsgnode.h>
|
||||
#include "QskFillNode.h"
|
||||
|
||||
class QskGradient;
|
||||
class QskBoxShapeMetrics;
|
||||
@ -15,8 +15,10 @@ class QskBoxBorderMetrics;
|
||||
|
||||
class QskBoxFillNodePrivate;
|
||||
|
||||
class QSK_EXPORT QskBoxFillNode : public QSGGeometryNode
|
||||
class QSK_EXPORT QskBoxFillNode : public QskFillNode
|
||||
{
|
||||
using Inherited = QskFillNode;
|
||||
|
||||
public:
|
||||
QskBoxFillNode();
|
||||
|
||||
|
@ -10,16 +10,7 @@
|
||||
#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, qskMaterialColorVertex )
|
||||
#include "QskFillNodePrivate.h"
|
||||
|
||||
static inline QskHashValue qskMetricsHash(
|
||||
const QskBoxShapeMetrics& shape, const QskBoxBorderMetrics& borderMetrics )
|
||||
@ -55,34 +46,21 @@ static inline QskGradient qskEffectiveGradient( const QskGradient& gradient )
|
||||
|
||||
#endif
|
||||
|
||||
class QskBoxRectangleNodePrivate final : public QSGGeometryNodePrivate
|
||||
class QskBoxRectangleNodePrivate final : public QskFillNodePrivate
|
||||
{
|
||||
public:
|
||||
QskBoxRectangleNodePrivate()
|
||||
: geometry( QSGGeometry::defaultAttributes_ColoredPoint2D(), 0 )
|
||||
{
|
||||
}
|
||||
|
||||
QskHashValue metricsHash = 0;
|
||||
QskHashValue colorsHash = 0;
|
||||
QRectF rect;
|
||||
|
||||
QSGGeometry geometry;
|
||||
};
|
||||
|
||||
QskBoxRectangleNode::QskBoxRectangleNode()
|
||||
: QSGGeometryNode( *new QskBoxRectangleNodePrivate )
|
||||
: QskFillNode( *new QskBoxRectangleNodePrivate )
|
||||
{
|
||||
Q_D( QskBoxRectangleNode );
|
||||
|
||||
setMaterial( qskMaterialColorVertex );
|
||||
setGeometry( &d->geometry );
|
||||
}
|
||||
|
||||
QskBoxRectangleNode::~QskBoxRectangleNode()
|
||||
{
|
||||
if ( material() != qskMaterialColorVertex )
|
||||
delete material();
|
||||
}
|
||||
|
||||
void QskBoxRectangleNode::updateNode(
|
||||
@ -129,7 +107,7 @@ void QskBoxRectangleNode::updateNode( const QRectF& rect,
|
||||
|
||||
if ( rect.isEmpty() )
|
||||
{
|
||||
d->geometry.allocate( 0 );
|
||||
resetGeometry();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -148,7 +126,7 @@ void QskBoxRectangleNode::updateNode( const QRectF& rect,
|
||||
|
||||
if ( !hasBorder && !hasFill )
|
||||
{
|
||||
d->geometry.allocate( 0 );
|
||||
resetGeometry();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -167,6 +145,8 @@ void QskBoxRectangleNode::updateNode( const QRectF& rect,
|
||||
}
|
||||
}
|
||||
|
||||
auto coloring = QskFillNode::Polychrome;
|
||||
|
||||
#if 0
|
||||
/*
|
||||
Always using the same material result in a better batching
|
||||
@ -175,74 +155,40 @@ void QskBoxRectangleNode::updateNode( const QRectF& rect,
|
||||
but for the moment we go with performance.
|
||||
*/
|
||||
|
||||
bool maybeFlat = true;
|
||||
|
||||
if ( maybeFlat )
|
||||
if ( !( hasFill && hasBorder ) )
|
||||
{
|
||||
if ( ( hasFill && hasBorder ) ||
|
||||
( hasFill && !isFillMonochrome ) ||
|
||||
( hasBorder && !isBorderMonochrome ) )
|
||||
if ( ( hasFill && isFillMonochrome )
|
||||
|| ( hasBorder && !isBorderMonochrome )
|
||||
{
|
||||
maybeFlat = false;
|
||||
coloring = QskFillNode::Monochrome;
|
||||
}
|
||||
}
|
||||
#else
|
||||
bool maybeFlat = false;
|
||||
#endif
|
||||
|
||||
if ( !maybeFlat )
|
||||
auto& geometry = *this->geometry();
|
||||
|
||||
if ( coloring == QskFillNode::Polychrome )
|
||||
{
|
||||
setMonochrome( false );
|
||||
setColoring( coloring );
|
||||
|
||||
QskBox::renderBox( d->rect, shape, borderMetrics,
|
||||
borderColors, fillGradient, *geometry() );
|
||||
borderColors, fillGradient, geometry );
|
||||
}
|
||||
else
|
||||
{
|
||||
// all is done with one color
|
||||
setMonochrome( true );
|
||||
|
||||
auto* flatMaterial = static_cast< QSGFlatColorMaterial* >( material() );
|
||||
|
||||
if ( hasFill )
|
||||
{
|
||||
flatMaterial->setColor( fillGradient.rgbStart() );
|
||||
setColoring( fillGradient.rgbStart() );
|
||||
QskBox::renderFillGeometry(
|
||||
d->rect, shape, QskBoxBorderMetrics(), *geometry() );
|
||||
d->rect, shape, QskBoxBorderMetrics(), geometry );
|
||||
}
|
||||
else
|
||||
{
|
||||
flatMaterial->setColor( borderColors.left().rgbStart() );
|
||||
setColoring( borderColors.left().rgbStart() );
|
||||
QskBox::renderBorderGeometry(
|
||||
d->rect, shape, borderMetrics, *geometry() );
|
||||
d->rect, shape, borderMetrics, geometry );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QskBoxRectangleNode::setMonochrome( bool on )
|
||||
{
|
||||
const auto material = this->material();
|
||||
|
||||
if ( on == ( material != qskMaterialColorVertex ) )
|
||||
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( qskMaterialColorVertex );
|
||||
delete material;
|
||||
|
||||
const QSGGeometry g( QSGGeometry::defaultAttributes_ColoredPoint2D(), 0 );
|
||||
memcpy( ( void* ) &d->geometry, ( void* ) &g, sizeof( QSGGeometry ) );
|
||||
}
|
||||
|
||||
geometry.markVertexDataDirty();
|
||||
}
|
||||
|
@ -7,7 +7,7 @@
|
||||
#define QSK_BOX_RECTANGLE_NODE_H
|
||||
|
||||
#include "QskGlobal.h"
|
||||
#include <qsgnode.h>
|
||||
#include "QskFillNode.h"
|
||||
|
||||
class QskBoxShapeMetrics;
|
||||
class QskBoxBorderMetrics;
|
||||
@ -16,8 +16,10 @@ class QskGradient;
|
||||
|
||||
class QskBoxRectangleNodePrivate;
|
||||
|
||||
class QSK_EXPORT QskBoxRectangleNode : public QSGGeometryNode
|
||||
class QSK_EXPORT QskBoxRectangleNode : public QskFillNode
|
||||
{
|
||||
using Inherited = QskFillNode;
|
||||
|
||||
public:
|
||||
QskBoxRectangleNode();
|
||||
~QskBoxRectangleNode() override;
|
||||
@ -32,8 +34,6 @@ class QSK_EXPORT QskBoxRectangleNode : public QSGGeometryNode
|
||||
const QskBoxShapeMetrics&, const QskGradient& );
|
||||
|
||||
private:
|
||||
void setMonochrome( bool on );
|
||||
|
||||
Q_DECLARE_PRIVATE( QskBoxRectangleNode )
|
||||
};
|
||||
|
||||
|
@ -281,6 +281,7 @@ void QskBoxShadowNode::setShadowData(
|
||||
QSGGeometry::updateTexturedRectGeometry(
|
||||
&d->geometry, d->rect, QRectF( -0.5, -0.5, 1.0, 1.0 ) );
|
||||
|
||||
d->geometry.markVertexDataDirty();
|
||||
markDirty( QSGNode::DirtyGeometry );
|
||||
|
||||
QVector2D aspect( 1.0, 1.0 );
|
||||
|
153
src/nodes/QskFillNode.cpp
Normal file
153
src/nodes/QskFillNode.cpp
Normal file
@ -0,0 +1,153 @@
|
||||
/******************************************************************************
|
||||
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*****************************************************************************/
|
||||
|
||||
#include "QskFillNode.h"
|
||||
#include "QskGradientMaterial.h"
|
||||
#include "QskFillNodePrivate.h"
|
||||
#include "QskSGNode.h"
|
||||
|
||||
#include <qsgflatcolormaterial.h>
|
||||
#include <qsgvertexcolormaterial.h>
|
||||
#include <qglobalstatic.h>
|
||||
|
||||
Q_GLOBAL_STATIC( QSGVertexColorMaterial, qskMaterialColorVertex )
|
||||
|
||||
static inline QskGradient::Type qskGradientType( QskFillNode::Coloring coloring )
|
||||
{
|
||||
const auto type = QskGradient::Linear + coloring - QskFillNode::Linear;
|
||||
return static_cast< QskGradient::Type >( type );
|
||||
}
|
||||
|
||||
static inline QskFillNode::Coloring qskColoring( QskGradient::Type type )
|
||||
{
|
||||
const auto coloring = QskFillNode::Linear + type - QskGradient::Linear;
|
||||
return static_cast< QskFillNode::Coloring >( coloring );
|
||||
}
|
||||
|
||||
QskFillNode::QskFillNode()
|
||||
: QskFillNode( *new QskFillNodePrivate )
|
||||
{
|
||||
}
|
||||
|
||||
QskFillNode::QskFillNode( QskFillNodePrivate& dd )
|
||||
: QSGGeometryNode( dd )
|
||||
{
|
||||
setGeometry( &dd.geometry );
|
||||
|
||||
setMaterial( qskMaterialColorVertex );
|
||||
setFlag( QSGNode::OwnsMaterial, false );
|
||||
}
|
||||
|
||||
QskFillNode::~QskFillNode()
|
||||
{
|
||||
}
|
||||
|
||||
void QskFillNode::resetGeometry()
|
||||
{
|
||||
QskSGNode::resetGeometry( this );
|
||||
}
|
||||
|
||||
void QskFillNode::setColoring( Coloring coloring )
|
||||
{
|
||||
Q_D( QskFillNode );
|
||||
|
||||
if ( coloring == d->coloring )
|
||||
return;
|
||||
|
||||
d->coloring = coloring;
|
||||
|
||||
switch( coloring )
|
||||
{
|
||||
case Monochrome:
|
||||
{
|
||||
setMaterial( new QSGFlatColorMaterial() );
|
||||
break;
|
||||
}
|
||||
|
||||
case Polychrome:
|
||||
{
|
||||
setMaterial( qskMaterialColorVertex );
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
QSGDefaultInternalRectangleNode is using QSGSmoothColorMaterial.
|
||||
Can we do something useful with it too ? TODO ...
|
||||
*/
|
||||
|
||||
default:
|
||||
{
|
||||
const auto gradientType = qskGradientType( coloring );
|
||||
setMaterial( QskGradientMaterial::createMaterial( gradientType ) );
|
||||
}
|
||||
}
|
||||
|
||||
if ( material() == qskMaterialColorVertex )
|
||||
{
|
||||
/*
|
||||
All color information is stored in the geometry and we can share
|
||||
the material regardless of the specific colors.
|
||||
|
||||
As nodes with the same material can be batched it might make sense
|
||||
to use this type of coloring for monochrome fillings: memory vs. performance.
|
||||
*/
|
||||
setFlag( QSGNode::OwnsMaterial, false ); // shared: do not delete
|
||||
|
||||
if ( !isGeometryColored() )
|
||||
{
|
||||
const QSGGeometry g( QSGGeometry::defaultAttributes_ColoredPoint2D(), 0 );
|
||||
memcpy( ( void* ) &d->geometry, ( void* ) &g, sizeof( QSGGeometry ) );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
setFlag( QSGNode::OwnsMaterial, true );
|
||||
|
||||
if ( isGeometryColored() )
|
||||
{
|
||||
const QSGGeometry g( QSGGeometry::defaultAttributes_Point2D(), 0 );
|
||||
memcpy( ( void* ) &d->geometry, ( void* ) &g, sizeof( QSGGeometry ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QskFillNode::Coloring QskFillNode::coloring() const
|
||||
{
|
||||
return d_func()->coloring;
|
||||
}
|
||||
|
||||
void QskFillNode::setColoring( const QColor& color )
|
||||
{
|
||||
setColoring( Monochrome );
|
||||
|
||||
auto mat = static_cast< QSGFlatColorMaterial* >( material() );
|
||||
if ( mat->color() != color )
|
||||
{
|
||||
mat->setColor( color );
|
||||
markDirty( QSGNode::DirtyMaterial );
|
||||
}
|
||||
}
|
||||
|
||||
void QskFillNode::setColoring( const QRectF& rect, const QskGradient& gradient )
|
||||
{
|
||||
if ( gradient.isMonochrome() )
|
||||
{
|
||||
setColoring( gradient.startColor().toRgb() );
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto effectiveGradient = gradient.effectiveGradient();
|
||||
setColoring( qskColoring( effectiveGradient.type() ) );
|
||||
|
||||
auto mat = static_cast< QskGradientMaterial* >( material() );
|
||||
if ( mat->updateGradient( rect, effectiveGradient ) )
|
||||
markDirty( QSGNode::DirtyMaterial );
|
||||
}
|
||||
}
|
||||
|
||||
bool QskFillNode::isGeometryColored() const
|
||||
{
|
||||
return d_func()->geometry.attributeCount() != 1;
|
||||
}
|
50
src/nodes/QskFillNode.h
Normal file
50
src/nodes/QskFillNode.h
Normal file
@ -0,0 +1,50 @@
|
||||
/******************************************************************************
|
||||
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef QSK_FILL_NODE_H
|
||||
#define QSK_FILL_NODE_H
|
||||
|
||||
#include "QskGlobal.h"
|
||||
#include <qsgnode.h>
|
||||
|
||||
class QskFillNodePrivate;
|
||||
class QskGradient;
|
||||
|
||||
class QSK_EXPORT QskFillNode : public QSGGeometryNode
|
||||
{
|
||||
using Inherited = QSGGeometryNode;
|
||||
|
||||
public:
|
||||
enum Coloring
|
||||
{
|
||||
Monochrome,
|
||||
Polychrome,
|
||||
|
||||
Linear,
|
||||
Radial,
|
||||
Conic
|
||||
};
|
||||
|
||||
QskFillNode();
|
||||
~QskFillNode() override;
|
||||
|
||||
void resetGeometry();
|
||||
|
||||
void setColoring( Coloring );
|
||||
Coloring coloring() const;
|
||||
|
||||
void setColoring( const QColor& );
|
||||
void setColoring( const QRectF&, const QskGradient& );
|
||||
|
||||
bool isGeometryColored() const;
|
||||
|
||||
protected:
|
||||
QskFillNode( QskFillNodePrivate& );
|
||||
|
||||
private:
|
||||
Q_DECLARE_PRIVATE( QskFillNode )
|
||||
};
|
||||
|
||||
#endif
|
32
src/nodes/QskFillNodePrivate.h
Normal file
32
src/nodes/QskFillNodePrivate.h
Normal file
@ -0,0 +1,32 @@
|
||||
/******************************************************************************
|
||||
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef QSK_FILL_NODE_PRIVATE_H
|
||||
#define QSK_FILL_NODE_PRIVATE_H
|
||||
|
||||
#include "QskGlobal.h"
|
||||
|
||||
QSK_QT_PRIVATE_BEGIN
|
||||
#include <private/qsgnode_p.h>
|
||||
QSK_QT_PRIVATE_END
|
||||
|
||||
class QskFillNode;
|
||||
|
||||
class QskFillNodePrivate : public QSGGeometryNodePrivate
|
||||
{
|
||||
public:
|
||||
inline QskFillNodePrivate()
|
||||
: geometry( QSGGeometry::defaultAttributes_ColoredPoint2D(), 0 )
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
friend class QskFillNode;
|
||||
|
||||
QSGGeometry geometry;
|
||||
QskFillNode::Coloring coloring = QskFillNode::Polychrome;
|
||||
};
|
||||
|
||||
#endif
|
@ -121,7 +121,6 @@ class QskLinesNodePrivate final : public QSGGeometryNodePrivate
|
||||
: geometry( QSGGeometry::defaultAttributes_Point2D(), 0 )
|
||||
{
|
||||
geometry.setDrawingMode( QSGGeometry::DrawLines );
|
||||
geometry.setVertexDataPattern( QSGGeometry::StaticPattern );
|
||||
}
|
||||
|
||||
inline qreal round( bool isHorizontal, qreal v ) const
|
||||
@ -298,6 +297,7 @@ void QskLinesNode::updateLines( const QColor& color,
|
||||
{
|
||||
updateGeometry( stippleMetrics, transform, count, lines );
|
||||
|
||||
d->geometry.markVertexDataDirty();
|
||||
markDirty( QSGNode::DirtyGeometry );
|
||||
d->dirty = false;
|
||||
}
|
||||
@ -336,6 +336,7 @@ void QskLinesNode::updateGrid( const QColor& color,
|
||||
{
|
||||
updateGeometry( stippleMetrics, transform, rect, xValues, yValues );
|
||||
|
||||
d->geometry.markVertexDataDirty();
|
||||
markDirty( QSGNode::DirtyGeometry );
|
||||
d->dirty = false;
|
||||
}
|
||||
@ -388,7 +389,6 @@ void QskLinesNode::updateGeometry( const QskStippleMetrics& stippleMetrics,
|
||||
count, lines, stippleMetrics, points );
|
||||
|
||||
}
|
||||
|
||||
Q_ASSERT( geom.vertexCount() == ( points - geom.vertexDataAsPoint2D() ) );
|
||||
}
|
||||
|
||||
@ -542,3 +542,46 @@ QSGGeometry::Point2D* QskLinesNode::setSolidLines(
|
||||
|
||||
return reinterpret_cast< QSGGeometry::Point2D* >( lines );
|
||||
}
|
||||
|
||||
void QskLinesNode::updatePolygon( const QColor& color, qreal lineWidth,
|
||||
const QTransform& transform, const QPolygonF& polygon )
|
||||
{
|
||||
if ( polygon.isEmpty() || !color.isValid() || ( color.alpha() == 0 ) )
|
||||
{
|
||||
QskSGNode::resetGeometry( this );
|
||||
return;
|
||||
}
|
||||
|
||||
Q_D( QskLinesNode );
|
||||
|
||||
if ( true ) // for the moment we always update the geometry. TODO ...
|
||||
{
|
||||
d->geometry.allocate( polygon.count() + 1 );
|
||||
|
||||
auto points = d->geometry.vertexDataAsPoint2D();
|
||||
|
||||
if ( transform.isIdentity() )
|
||||
{
|
||||
for ( int i = 0; i < polygon.count(); i++ )
|
||||
{
|
||||
const auto& pos = polygon[i];
|
||||
points[i].set( pos.x(), pos.y() );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for ( int i = 0; i < polygon.count(); i++ )
|
||||
{
|
||||
const auto pos = transform.map( polygon[i] );
|
||||
points[i].set( pos.x(), pos.y() );
|
||||
}
|
||||
}
|
||||
|
||||
points[ polygon.count() ] = points[0];
|
||||
|
||||
d->geometry.markVertexDataDirty();
|
||||
markDirty( QSGNode::DirtyGeometry );
|
||||
}
|
||||
|
||||
d->setLineAttributes( this, color, lineWidth );
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ class QskStippleMetrics;
|
||||
class QTransform;
|
||||
class QPointF;
|
||||
class QLineF;
|
||||
class QPolygonF;
|
||||
class QQuickItem;
|
||||
|
||||
class QskLinesNodePrivate;
|
||||
@ -26,6 +27,8 @@ class QskLinesNodePrivate;
|
||||
*/
|
||||
class QSK_EXPORT QskLinesNode : public QSGGeometryNode
|
||||
{
|
||||
using Inherited = QSGGeometryNode;
|
||||
|
||||
public:
|
||||
QskLinesNode();
|
||||
~QskLinesNode() override;
|
||||
@ -53,6 +56,9 @@ class QSK_EXPORT QskLinesNode : public QSGGeometryNode
|
||||
void updateLines( const QColor&, qreal lineWidth,
|
||||
const QskStippleMetrics&, const QTransform&, const QVector< QLineF >& );
|
||||
|
||||
void updatePolygon( const QColor&, qreal lineWidth,
|
||||
const QTransform&, const QPolygonF& );
|
||||
|
||||
private:
|
||||
void updateLines( const QColor&, qreal lineWidth, const QskStippleMetrics&,
|
||||
const QTransform&, int count, const QLineF* );
|
||||
|
@ -5,28 +5,13 @@
|
||||
|
||||
#include "QskRectangleNode.h"
|
||||
#include "QskGradient.h"
|
||||
#include "QskSGNode.h"
|
||||
#include "QskBoxRenderer.h"
|
||||
#include "QskBoxShapeMetrics.h"
|
||||
#include "QskGradientMaterial.h"
|
||||
#include "QskFillNodePrivate.h"
|
||||
|
||||
#include <qglobalstatic.h>
|
||||
#include <qsgvertexcolormaterial.h>
|
||||
|
||||
QSK_QT_PRIVATE_BEGIN
|
||||
#include <private/qsgnode_p.h>
|
||||
QSK_QT_PRIVATE_END
|
||||
|
||||
Q_GLOBAL_STATIC( QSGVertexColorMaterial, qskMaterialColorVertex )
|
||||
|
||||
class QskRectangleNodePrivate final : public QSGGeometryNodePrivate
|
||||
class QskRectangleNodePrivate final : public QskFillNodePrivate
|
||||
{
|
||||
public:
|
||||
QskRectangleNodePrivate()
|
||||
: geometry( QSGGeometry::defaultAttributes_ColoredPoint2D(), 0 )
|
||||
{
|
||||
}
|
||||
|
||||
inline void resetValues()
|
||||
{
|
||||
rect = QRectF();
|
||||
@ -35,24 +20,16 @@ class QskRectangleNodePrivate final : public QSGGeometryNodePrivate
|
||||
metricsHash = 0;
|
||||
}
|
||||
|
||||
QSGGeometry geometry;
|
||||
|
||||
QRectF rect;
|
||||
QskBoxShapeMetrics shape;
|
||||
|
||||
QskHashValue gradientHash = 0;
|
||||
QskHashValue metricsHash = 0;
|
||||
|
||||
int gradientType = -1;
|
||||
};
|
||||
|
||||
QskRectangleNode::QskRectangleNode()
|
||||
: QSGGeometryNode( *new QskRectangleNodePrivate )
|
||||
: QskFillNode( *new QskRectangleNodePrivate )
|
||||
{
|
||||
Q_D( QskRectangleNode );
|
||||
|
||||
setFlag( OwnsMaterial, true );
|
||||
setGeometry( &d->geometry );
|
||||
}
|
||||
|
||||
QskRectangleNode::~QskRectangleNode()
|
||||
@ -73,7 +50,7 @@ void QskRectangleNode::updateNode(
|
||||
if ( rect.isEmpty() || !gradient.isVisible() )
|
||||
{
|
||||
d->resetValues();
|
||||
QskSGNode::resetGeometry( this );
|
||||
resetGeometry();
|
||||
|
||||
return;
|
||||
}
|
||||
@ -97,39 +74,8 @@ void QskRectangleNode::updateNode(
|
||||
|
||||
if ( QskBox::isGradientSupported( effectiveShape, effectiveGradient ) )
|
||||
{
|
||||
if ( material() != qskMaterialColorVertex )
|
||||
{
|
||||
setMaterial( qskMaterialColorVertex );
|
||||
setFlag( OwnsMaterial, false );
|
||||
setColoring( Polychrome );
|
||||
|
||||
d->gradientType = -1;
|
||||
}
|
||||
|
||||
if ( d->geometry.attributeCount() == 1 )
|
||||
{
|
||||
const QSGGeometry g( QSGGeometry::defaultAttributes_ColoredPoint2D(), 0 );
|
||||
memcpy( ( void* ) &d->geometry, ( void* ) &g, sizeof( QSGGeometry ) );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( material() == qskMaterialColorVertex )
|
||||
{
|
||||
setMaterial( nullptr );
|
||||
setFlag( OwnsMaterial, true );
|
||||
|
||||
d->gradientType = -1;
|
||||
}
|
||||
|
||||
if ( d->geometry.attributeCount() != 1 )
|
||||
{
|
||||
const QSGGeometry g( QSGGeometry::defaultAttributes_Point2D(), 0 );
|
||||
memcpy( ( void* ) &d->geometry, ( void* ) &g, sizeof( QSGGeometry ) );
|
||||
}
|
||||
}
|
||||
|
||||
if ( material() == qskMaterialColorVertex )
|
||||
{
|
||||
/*
|
||||
Colors are added to the vertices, while the material does
|
||||
not depend on the gradient at all
|
||||
@ -137,39 +83,23 @@ void QskRectangleNode::updateNode(
|
||||
if ( dirtyMetrics || dirtyColors )
|
||||
{
|
||||
QskBox::renderBox( rect,
|
||||
effectiveShape, effectiveGradient, d->geometry );
|
||||
effectiveShape, effectiveGradient, *geometry() );
|
||||
|
||||
geometry()->markVertexDataDirty();
|
||||
markDirty( QSGNode::DirtyGeometry );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
Colors are added by the shaders
|
||||
if ( dirtyColors || dirtyMetrics )
|
||||
setColoring( rect, effectiveGradient );
|
||||
|
||||
Monochrome gradients or QskGradient::Stops are supported by the
|
||||
QskBoxRenderer. So we don't need to handle them here.
|
||||
*/
|
||||
if ( dirtyMetrics )
|
||||
{
|
||||
QskBox::renderFillGeometry( rect, effectiveShape, d->geometry );
|
||||
QskBox::renderFillGeometry( rect, effectiveShape, *geometry() );
|
||||
|
||||
geometry()->markVertexDataDirty();
|
||||
markDirty( QSGNode::DirtyGeometry );
|
||||
}
|
||||
|
||||
// dirtyMetrics: the shader also depends on the target rectangle !
|
||||
if ( dirtyColors || dirtyMetrics )
|
||||
{
|
||||
const auto gradientType = effectiveGradient.type();
|
||||
|
||||
if ( gradientType != d->gradientType )
|
||||
{
|
||||
setMaterial( QskGradientMaterial::createMaterial( gradientType ) );
|
||||
d->gradientType = gradientType;
|
||||
}
|
||||
|
||||
auto mat = static_cast< QskGradientMaterial* >( material() );
|
||||
if ( mat->updateGradient( rect, effectiveGradient ) )
|
||||
markDirty( QSGNode::DirtyMaterial );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,7 @@
|
||||
#define QSK_RECTANGLE_NODE_H
|
||||
|
||||
#include "QskGlobal.h"
|
||||
#include <qsgnode.h>
|
||||
#include "QskFillNode.h"
|
||||
|
||||
class QskGradient;
|
||||
class QskBoxShapeMetrics;
|
||||
@ -15,11 +15,11 @@ class QskRectangleNodePrivate;
|
||||
|
||||
/*
|
||||
QskRectangleNode is for rounded rectangles without a border.
|
||||
Depending on the type of gradient it uses a different
|
||||
material/geometry combination.
|
||||
*/
|
||||
class QSK_EXPORT QskRectangleNode : public QSGGeometryNode
|
||||
class QSK_EXPORT QskRectangleNode : public QskFillNode
|
||||
{
|
||||
using Inherited = QskFillNode;
|
||||
|
||||
public:
|
||||
QskRectangleNode();
|
||||
~QskRectangleNode() override;
|
||||
|
@ -173,9 +173,19 @@ void QskSGNode::resetGeometry( QSGGeometryNode* node )
|
||||
{
|
||||
if ( auto g = node->geometry() )
|
||||
{
|
||||
if ( g->vertexCount() > 0 || g->indexCount() > 0 )
|
||||
const bool hasVertices = g->vertexCount() > 0;
|
||||
const bool hasIndexes = g->indexCount() > 0;
|
||||
|
||||
if ( hasVertices || hasIndexes )
|
||||
{
|
||||
g->allocate( 0, 0 );
|
||||
|
||||
if ( hasVertices )
|
||||
g->markVertexDataDirty();
|
||||
|
||||
if ( hasIndexes )
|
||||
g->markIndexDataDirty();
|
||||
|
||||
node->markDirty( QSGNode::DirtyGeometry );
|
||||
}
|
||||
}
|
||||
|
@ -4,15 +4,11 @@
|
||||
*****************************************************************************/
|
||||
|
||||
#include "QskShapeNode.h"
|
||||
#include "QskGradientMaterial.h"
|
||||
#include "QskGradient.h"
|
||||
#include "QskGradientDirection.h"
|
||||
#include "QskSGNode.h"
|
||||
|
||||
#include <qsgflatcolormaterial.h>
|
||||
#include "QskFillNodePrivate.h"
|
||||
|
||||
QSK_QT_PRIVATE_BEGIN
|
||||
#include <private/qsgnode_p.h>
|
||||
#include <private/qvectorpath_p.h>
|
||||
#include <private/qtriangulator_p.h>
|
||||
QSK_QT_PRIVATE_END
|
||||
@ -59,18 +55,9 @@ static void qskUpdateGeometry( const QPainterPath& path,
|
||||
#endif
|
||||
}
|
||||
|
||||
class QskShapeNodePrivate final : public QSGGeometryNodePrivate
|
||||
class QskShapeNodePrivate final : public QskFillNodePrivate
|
||||
{
|
||||
public:
|
||||
QskShapeNodePrivate()
|
||||
: geometry( QSGGeometry::defaultAttributes_Point2D(), 0 )
|
||||
{
|
||||
geometry.setDrawingMode( QSGGeometry::DrawTriangles );
|
||||
}
|
||||
|
||||
QSGGeometry geometry;
|
||||
int gradientType = -1;
|
||||
|
||||
/*
|
||||
Is there a better way to find out if the path has changed
|
||||
beside storing a copy ( even, when internally with Copy On Write ) ?
|
||||
@ -80,13 +67,10 @@ class QskShapeNodePrivate final : public QSGGeometryNodePrivate
|
||||
};
|
||||
|
||||
QskShapeNode::QskShapeNode()
|
||||
: QSGGeometryNode( *new QskShapeNodePrivate )
|
||||
: QskFillNode( *new QskShapeNodePrivate )
|
||||
{
|
||||
Q_D( QskShapeNode );
|
||||
|
||||
setGeometry( &d->geometry );
|
||||
setMaterial( new QSGFlatColorMaterial() );
|
||||
setFlag( QSGNode::OwnsMaterial, true );
|
||||
setColoring( Monochrome );
|
||||
geometry()->setDrawingMode( QSGGeometry::DrawTriangles );
|
||||
}
|
||||
|
||||
QskShapeNode::~QskShapeNode()
|
||||
@ -102,58 +86,21 @@ void QskShapeNode::updateNode( const QPainterPath& path,
|
||||
{
|
||||
d->path = QPainterPath();
|
||||
d->transform = QTransform();
|
||||
QskSGNode::resetGeometry( this );
|
||||
resetGeometry();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
setColoring( rect, gradient );
|
||||
|
||||
if ( ( transform != d->transform ) || ( path != d->path ) )
|
||||
{
|
||||
d->path = path;
|
||||
d->transform = transform;
|
||||
|
||||
qskUpdateGeometry( path, transform, d->geometry );
|
||||
qskUpdateGeometry( path, transform, *geometry() );
|
||||
|
||||
geometry()->markVertexDataDirty();
|
||||
markDirty( QSGNode::DirtyGeometry );
|
||||
}
|
||||
|
||||
if ( gradient.isMonochrome() )
|
||||
{
|
||||
if ( material() == nullptr || d->gradientType >= 0 )
|
||||
{
|
||||
setMaterial( new QSGFlatColorMaterial() );
|
||||
d->gradientType = -1;
|
||||
}
|
||||
|
||||
const auto color = gradient.startColor().toRgb();
|
||||
|
||||
/*
|
||||
We might want to use QSGVertexColorMaterial to improve the "batchability"
|
||||
as this material does not depend on the specific colors. It could even be
|
||||
batched with QskBoxNodes, that are usually using QSGVertexColorMaterial as well.
|
||||
|
||||
However we would have to store the color information for each vertex.
|
||||
For the moment we prefer less memory over better "batchability".
|
||||
*/
|
||||
auto mat = static_cast< QSGFlatColorMaterial* >( material() );
|
||||
if ( mat->color() != color )
|
||||
{
|
||||
mat->setColor( color );
|
||||
markDirty( QSGNode::DirtyMaterial );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto effectiveGradient = gradient.effectiveGradient();
|
||||
const auto gradientType = effectiveGradient.type();
|
||||
|
||||
if ( ( material() == nullptr ) || ( gradientType != d->gradientType ) )
|
||||
{
|
||||
setMaterial( QskGradientMaterial::createMaterial( gradientType ) );
|
||||
d->gradientType = gradientType;
|
||||
}
|
||||
|
||||
auto mat = static_cast< QskGradientMaterial* >( material() );
|
||||
if ( mat->updateGradient( rect, effectiveGradient ) )
|
||||
markDirty( QSGNode::DirtyMaterial );
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,7 @@
|
||||
#define QSK_SHAPE_NODE_H
|
||||
|
||||
#include "QskGlobal.h"
|
||||
#include <qsgnode.h>
|
||||
#include "QskFillNode.h"
|
||||
|
||||
class QskGradient;
|
||||
class QColor;
|
||||
@ -15,8 +15,10 @@ class QPainterPath;
|
||||
|
||||
class QskShapeNodePrivate;
|
||||
|
||||
class QSK_EXPORT QskShapeNode : public QSGGeometryNode
|
||||
class QSK_EXPORT QskShapeNode : public QskFillNode
|
||||
{
|
||||
using Inherited = QskFillNode;
|
||||
|
||||
public:
|
||||
QskShapeNode();
|
||||
~QskShapeNode() override;
|
||||
|
@ -5,145 +5,64 @@
|
||||
|
||||
#include "QskStrokeNode.h"
|
||||
#include "QskVertex.h"
|
||||
#include "QskGradient.h"
|
||||
|
||||
#include <qsgflatcolormaterial.h>
|
||||
#include <qsgvertexcolormaterial.h>
|
||||
#include <qpainterpath.h>
|
||||
#include <qpolygon.h>
|
||||
|
||||
QSK_QT_PRIVATE_BEGIN
|
||||
#include <private/qsgnode_p.h>
|
||||
#include <private/qtriangulatingstroker_p.h>
|
||||
QSK_QT_PRIVATE_END
|
||||
|
||||
Q_GLOBAL_STATIC( QSGVertexColorMaterial, qskMaterialColorVertex )
|
||||
|
||||
static inline void qskMapPolygon( const QPolygonF& polygon,
|
||||
const QTransform& transform, const QColor& color, QSGGeometry& geometry )
|
||||
static inline bool qskIsPenVisible( const QPen& pen )
|
||||
{
|
||||
const QskVertex::Color c( color );
|
||||
if ( pen.style() == Qt::NoPen )
|
||||
return false;
|
||||
|
||||
auto p = geometry.vertexDataAsColoredPoint2D();
|
||||
|
||||
if ( transform.isIdentity() )
|
||||
if ( pen.brush().gradient() )
|
||||
{
|
||||
for ( int i = 0; i < polygon.count(); i++ )
|
||||
{
|
||||
const auto& pos = polygon[i];
|
||||
p[i].set( pos.x(), pos.y(), c.r, c.g, c.b, c.a );
|
||||
}
|
||||
// TODO ...
|
||||
}
|
||||
else
|
||||
{
|
||||
for ( int i = 0; i < polygon.count(); i++ )
|
||||
{
|
||||
const auto pos = transform.map( polygon[i] );
|
||||
p[i].set( pos.x(), pos.y(), c.r, c.g, c.b, c.a );
|
||||
}
|
||||
if ( pen.color().isValid() || ( pen.color().alpha() == 0 ) )
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void qskMapPolygon( const QPolygonF& polygon,
|
||||
const QTransform& transform, QSGGeometry& geometry )
|
||||
{
|
||||
auto p = geometry.vertexDataAsPoint2D();
|
||||
|
||||
if ( transform.isIdentity() )
|
||||
{
|
||||
for ( int i = 0; i < polygon.count(); i++ )
|
||||
{
|
||||
const auto& pos = polygon[i];
|
||||
p[i].set( pos.x(), pos.y() );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for ( int i = 0; i < polygon.count(); i++ )
|
||||
{
|
||||
const auto pos = transform.map( polygon[i] );
|
||||
p[i].set( pos.x(), pos.y() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class QskStrokeNodePrivate final : public QSGGeometryNodePrivate
|
||||
{
|
||||
public:
|
||||
QskStrokeNodePrivate()
|
||||
: geometry( QSGGeometry::defaultAttributes_ColoredPoint2D(), 0 )
|
||||
{
|
||||
}
|
||||
|
||||
QSGGeometry geometry;
|
||||
};
|
||||
|
||||
QskStrokeNode::QskStrokeNode()
|
||||
: QSGGeometryNode( *new QskStrokeNodePrivate )
|
||||
{
|
||||
Q_D( QskStrokeNode );
|
||||
|
||||
setGeometry( &d->geometry );
|
||||
setMaterial( qskMaterialColorVertex );
|
||||
}
|
||||
|
||||
QskStrokeNode::~QskStrokeNode() = default;
|
||||
|
||||
void QskStrokeNode::setRenderHint( RenderHint renderHint )
|
||||
{
|
||||
Q_D( QskStrokeNode );
|
||||
|
||||
const auto material = this->material();
|
||||
|
||||
if ( renderHint == Colored )
|
||||
{
|
||||
if ( material != qskMaterialColorVertex )
|
||||
{
|
||||
setMaterial( qskMaterialColorVertex );
|
||||
delete material;
|
||||
|
||||
const QSGGeometry g( QSGGeometry::defaultAttributes_ColoredPoint2D(), 0 );
|
||||
memcpy( ( void* ) &d->geometry, ( void* ) &g, sizeof( QSGGeometry ) );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( material == qskMaterialColorVertex )
|
||||
{
|
||||
setMaterial( new QSGFlatColorMaterial() );
|
||||
|
||||
const QSGGeometry g( QSGGeometry::defaultAttributes_Point2D(), 0 );
|
||||
memcpy( ( void* ) &d->geometry, ( void* ) &g, sizeof( QSGGeometry ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QskStrokeNode::RenderHint QskStrokeNode::renderHint() const
|
||||
{
|
||||
return ( material() == qskMaterialColorVertex ) ? Colored : Flat;
|
||||
}
|
||||
|
||||
void QskStrokeNode::updateNode( const QPainterPath& path, const QPen& pen )
|
||||
{
|
||||
updateNode( path, QTransform(), pen );
|
||||
}
|
||||
|
||||
void QskStrokeNode::updateNode(
|
||||
const QPainterPath& path, const QTransform& transform, const QPen& pen )
|
||||
const QPainterPath& path, const QTransform& transform, const QPen& pen )
|
||||
{
|
||||
Q_D( QskStrokeNode );
|
||||
|
||||
if ( path.isEmpty() || ( pen.style() == Qt::NoPen ) ||
|
||||
!pen.color().isValid() || ( pen.color().alpha() == 0 ) )
|
||||
if ( path.isEmpty() || !qskIsPenVisible( pen ) )
|
||||
{
|
||||
if ( d->geometry.vertexCount() > 0 )
|
||||
{
|
||||
d->geometry.allocate( 0 );
|
||||
markDirty( QSGNode::DirtyGeometry );
|
||||
}
|
||||
|
||||
resetGeometry();
|
||||
return;
|
||||
}
|
||||
|
||||
if ( auto qGradient = pen.brush().gradient() )
|
||||
{
|
||||
const auto r = transform.mapRect( path.boundingRect() );
|
||||
|
||||
QskGradient gradient( *qGradient );
|
||||
gradient.setStretchMode( QskGradient::StretchToSize );
|
||||
|
||||
setColoring( r, gradient );
|
||||
}
|
||||
else
|
||||
setColoring( pen.color() );
|
||||
|
||||
if ( true ) // For the moment we always update the geometry. TODO ...
|
||||
{
|
||||
/*
|
||||
@ -176,7 +95,8 @@ void QskStrokeNode::updateNode(
|
||||
constexpr QRectF clipRect; // empty rect: no clipping
|
||||
|
||||
QDashedStrokeProcessor dashStroker;
|
||||
dashStroker.process( qtVectorPathForPath( scaledPath ), effectivePen, clipRect, {} );
|
||||
dashStroker.process( qtVectorPathForPath( scaledPath ),
|
||||
effectivePen, clipRect, {} );
|
||||
|
||||
const QVectorPath dashedVectorPath( dashStroker.points(),
|
||||
dashStroker.elementCount(), dashStroker.elementTypes(), 0 );
|
||||
@ -184,18 +104,20 @@ void QskStrokeNode::updateNode(
|
||||
stroker.process( dashedVectorPath, effectivePen, {}, {} );
|
||||
}
|
||||
|
||||
// 2 vertices for each point
|
||||
d->geometry.setDrawingMode( QSGGeometry::DrawTriangleStrip );
|
||||
d->geometry.allocate( stroker.vertexCount() / 2 );
|
||||
auto& geometry = *this->geometry();
|
||||
|
||||
if ( material() == qskMaterialColorVertex )
|
||||
// 2 vertices for each point
|
||||
geometry.setDrawingMode( QSGGeometry::DrawTriangleStrip );
|
||||
geometry.allocate( stroker.vertexCount() / 2 );
|
||||
|
||||
if ( isGeometryColored() )
|
||||
{
|
||||
const QskVertex::Color c( pen.color() );
|
||||
|
||||
const auto v = stroker.vertices();
|
||||
auto points = d->geometry.vertexDataAsColoredPoint2D();
|
||||
auto points = geometry.vertexDataAsColoredPoint2D();
|
||||
|
||||
for ( int i = 0; i < d->geometry.vertexCount(); i++ )
|
||||
for ( int i = 0; i < geometry.vertexCount(); i++ )
|
||||
{
|
||||
const auto j = 2 * i;
|
||||
points[i].set( v[j], v[j + 1], c.r, c.g, c.b, c.a );
|
||||
@ -203,80 +125,11 @@ void QskStrokeNode::updateNode(
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy( d->geometry.vertexData(), stroker.vertices(),
|
||||
memcpy( geometry.vertexData(), stroker.vertices(),
|
||||
stroker.vertexCount() * sizeof( float ) );
|
||||
}
|
||||
|
||||
geometry.markVertexDataDirty();
|
||||
markDirty( QSGNode::DirtyGeometry );
|
||||
}
|
||||
|
||||
if ( material() != qskMaterialColorVertex )
|
||||
{
|
||||
const auto color = pen.color().toRgb();
|
||||
|
||||
auto flatMaterial = static_cast< QSGFlatColorMaterial* >( material() );
|
||||
if ( flatMaterial->color() != color )
|
||||
{
|
||||
flatMaterial->setColor( color );
|
||||
markDirty( QSGNode::DirtyMaterial );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QskStrokeNode::updateNode( const QPolygonF& polygon,
|
||||
qreal lineWidth, const QColor& color )
|
||||
{
|
||||
updateNode( polygon, QTransform(), lineWidth, color );
|
||||
}
|
||||
|
||||
/*
|
||||
For polygons with a small lineWidth ( < 2 ) or a line without
|
||||
connections we might get away with a simple and fast implementation
|
||||
using DrawLineStrip/DrawLineLoop
|
||||
*/
|
||||
void QskStrokeNode::updateNode( const QPolygonF& polygon,
|
||||
const QTransform& transform, qreal lineWidth, const QColor& color )
|
||||
{
|
||||
Q_D( QskStrokeNode );
|
||||
|
||||
if ( polygon.isEmpty() || !color.isValid() || ( color.alpha() == 0 ) )
|
||||
{
|
||||
if ( d->geometry.vertexCount() > 0 )
|
||||
{
|
||||
d->geometry.allocate( 0 );
|
||||
markDirty( QSGNode::DirtyGeometry );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
d->geometry.setDrawingMode( QSGGeometry::DrawLineStrip );
|
||||
|
||||
const float lineWidthF = lineWidth;
|
||||
|
||||
if( lineWidthF != d->geometry.lineWidth() )
|
||||
d->geometry.setLineWidth( lineWidthF );
|
||||
|
||||
if ( true ) // TODO
|
||||
{
|
||||
d->geometry.allocate( polygon.count() );
|
||||
|
||||
if ( material() == qskMaterialColorVertex )
|
||||
{
|
||||
qskMapPolygon( polygon, transform, color, d->geometry );
|
||||
markDirty( QSGNode::DirtyGeometry );
|
||||
}
|
||||
else
|
||||
{
|
||||
qskMapPolygon( polygon, transform, d->geometry );
|
||||
markDirty( QSGNode::DirtyGeometry );
|
||||
|
||||
auto flatMaterial = static_cast< QSGFlatColorMaterial* >( material() );
|
||||
if ( flatMaterial->color() != color )
|
||||
{
|
||||
flatMaterial->setColor( color );
|
||||
markDirty( QSGNode::DirtyMaterial );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,44 +7,26 @@
|
||||
#define QSK_STROKE_NODE_H
|
||||
|
||||
#include "QskGlobal.h"
|
||||
#include <qsgnode.h>
|
||||
#include "QskFillNode.h"
|
||||
|
||||
class QPen;
|
||||
class QPainterPath;
|
||||
class QPolygonF;
|
||||
|
||||
class QskStrokeNodePrivate;
|
||||
|
||||
class QSK_EXPORT QskStrokeNode : public QSGGeometryNode
|
||||
class QSK_EXPORT QskStrokeNode : public QskFillNode
|
||||
{
|
||||
using Inherited = QskFillNode;
|
||||
|
||||
public:
|
||||
QskStrokeNode();
|
||||
~QskStrokeNode() override;
|
||||
|
||||
/*
|
||||
We only support monochrome pens ( QPen::color() ) and using a
|
||||
QSGFlatColorMaterial is good enough. However QSGVertexColorMaterial
|
||||
usually allows better batching. So Flat vs. Colored is a tradeoff
|
||||
between memory and performance.
|
||||
*/
|
||||
enum RenderHint
|
||||
{
|
||||
Flat,
|
||||
Colored
|
||||
};
|
||||
|
||||
void setRenderHint( RenderHint );
|
||||
RenderHint renderHint() const;
|
||||
|
||||
void updateNode( const QPainterPath&, const QPen& );
|
||||
void updateNode( const QPainterPath&, const QTransform&, const QPen& );
|
||||
|
||||
void updateNode( const QPolygonF&, qreal lineWidth, const QColor& );
|
||||
void updateNode( const QPolygonF&, const QTransform&,
|
||||
void updateNode0( const QPolygonF&, qreal lineWidth, const QColor& );
|
||||
void updateNode0( const QPolygonF&, const QTransform&,
|
||||
qreal lineWidth, const QColor& );
|
||||
|
||||
private:
|
||||
Q_DECLARE_PRIVATE( QskStrokeNode )
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -22,7 +22,6 @@ class QskTickmarksNodePrivate final : public QSGGeometryNodePrivate
|
||||
: geometry( QSGGeometry::defaultAttributes_Point2D(), 0 )
|
||||
{
|
||||
geometry.setDrawingMode( QSGGeometry::DrawLines );
|
||||
geometry.setVertexDataPattern( QSGGeometry::StaticPattern );
|
||||
}
|
||||
|
||||
QSGGeometry geometry;
|
||||
|
Loading…
x
Reference in New Issue
Block a user