QskLinesNode improvements
This commit is contained in:
parent
3c62809308
commit
587183993b
|
@ -21,8 +21,10 @@
|
||||||
#include "QskGradient.h"
|
#include "QskGradient.h"
|
||||||
#include "QskGraphicNode.h"
|
#include "QskGraphicNode.h"
|
||||||
#include "QskGraphic.h"
|
#include "QskGraphic.h"
|
||||||
|
#include "QskLinesNode.h"
|
||||||
#include "QskRectangleNode.h"
|
#include "QskRectangleNode.h"
|
||||||
#include "QskSGNode.h"
|
#include "QskSGNode.h"
|
||||||
|
#include "QskStippleMetrics.h"
|
||||||
#include "QskTextColors.h"
|
#include "QskTextColors.h"
|
||||||
#include "QskTextNode.h"
|
#include "QskTextNode.h"
|
||||||
#include "QskTextOptions.h"
|
#include "QskTextOptions.h"
|
||||||
|
@ -161,6 +163,11 @@ static inline bool qskIsArcVisible( const QskArcMetrics& arcMetrics,
|
||||||
return gradient.isVisible();
|
return gradient.isVisible();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool qskIsLineVisible( const QColor& lineColor, qreal lineWidth )
|
||||||
|
{
|
||||||
|
return ( lineWidth > 0.0 ) && lineColor.isValid() && ( lineColor.alpha() > 0 );
|
||||||
|
}
|
||||||
|
|
||||||
static inline QskTextColors qskTextColors(
|
static inline QskTextColors qskTextColors(
|
||||||
const QskSkinnable* skinnable, QskAspect::Subcontrol subControl )
|
const QskSkinnable* skinnable, QskAspect::Subcontrol subControl )
|
||||||
{
|
{
|
||||||
|
@ -199,13 +206,10 @@ static inline QSGNode* qskUpdateBoxNode(
|
||||||
|
|
||||||
if ( qskIsBoxVisible( absoluteMetrics, borderColors, gradient ) )
|
if ( qskIsBoxVisible( absoluteMetrics, borderColors, gradient ) )
|
||||||
{
|
{
|
||||||
auto boxNode = static_cast< QskBoxNode* >( node );
|
|
||||||
if ( boxNode == nullptr )
|
|
||||||
boxNode = new QskBoxNode();
|
|
||||||
|
|
||||||
const auto absoluteShape = shape.toAbsolute( size );
|
const auto absoluteShape = shape.toAbsolute( size );
|
||||||
const auto absoluteShadowMetrics = shadowMetrics.toAbsolute( size );
|
const auto absoluteShadowMetrics = shadowMetrics.toAbsolute( size );
|
||||||
|
|
||||||
|
auto boxNode = QskSGNode::ensureNode< QskBoxNode >( node );
|
||||||
boxNode->updateNode( rect, absoluteShape, absoluteMetrics,
|
boxNode->updateNode( rect, absoluteShape, absoluteMetrics,
|
||||||
borderColors, gradient, absoluteShadowMetrics, shadowColor );
|
borderColors, gradient, absoluteShadowMetrics, shadowColor );
|
||||||
|
|
||||||
|
@ -226,15 +230,46 @@ static inline QSGNode* qskUpdateArcNode(
|
||||||
if ( !qskIsArcVisible( metrics, borderWidth, borderColor, gradient ) )
|
if ( !qskIsArcVisible( metrics, borderWidth, borderColor, gradient ) )
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
auto arcNode = static_cast< QskArcNode* >( node );
|
auto arcNode = QskSGNode::ensureNode< QskArcNode >( node );
|
||||||
if ( arcNode == nullptr )
|
|
||||||
arcNode = new QskArcNode();
|
|
||||||
|
|
||||||
arcNode->setArcData( rect, metrics, borderWidth, borderColor, gradient );
|
arcNode->setArcData( rect, metrics, borderWidth, borderColor, gradient );
|
||||||
|
|
||||||
return arcNode;
|
return arcNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline QSGNode* qskUpdateLineNode(
|
||||||
|
const QskSkinnable*, QSGNode* node, const QColor& lineColor,
|
||||||
|
qreal lineWidth, QskStippleMetrics& lineStipple, const QLineF& line )
|
||||||
|
{
|
||||||
|
if ( line.isNull() )
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
if ( !qskIsLineVisible( lineColor, lineWidth ) )
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
auto linesNode = QskSGNode::ensureNode< QskLinesNode >( node );
|
||||||
|
linesNode->updateLine( lineColor, lineWidth, lineStipple,
|
||||||
|
QTransform(), line.p1(), line.p2() );
|
||||||
|
|
||||||
|
return linesNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline QSGNode* qskUpdateLinesNode(
|
||||||
|
const QskSkinnable*, QSGNode* node, const QColor& lineColor,
|
||||||
|
qreal lineWidth, QskStippleMetrics& lineStipple, const QVector< QLineF >& lines )
|
||||||
|
{
|
||||||
|
if ( lines.isEmpty() )
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
if ( !qskIsLineVisible( lineColor, lineWidth ) )
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
auto linesNode = QskSGNode::ensureNode< QskLinesNode >( node );
|
||||||
|
linesNode->updateLines( lineColor, lineWidth, lineStipple,
|
||||||
|
QTransform(), lines );
|
||||||
|
|
||||||
|
return linesNode;
|
||||||
|
}
|
||||||
|
|
||||||
class QskSkinlet::PrivateData
|
class QskSkinlet::PrivateData
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -575,6 +610,34 @@ QSGNode* QskSkinlet::updateArcNode( const QskSkinnable* skinnable,
|
||||||
borderWidth, borderColor, fillGradient, arcMetrics );
|
borderWidth, borderColor, fillGradient, arcMetrics );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QSGNode* QskSkinlet::updateLineNode( const QskSkinnable* skinnable,
|
||||||
|
QSGNode* node, const QLineF& line, QskAspect::Subcontrol subControl )
|
||||||
|
{
|
||||||
|
auto lineStipple = skinnable->stippleMetricsHint( subControl );
|
||||||
|
if ( !lineStipple.isValid() )
|
||||||
|
lineStipple = Qt::SolidLine;
|
||||||
|
|
||||||
|
const auto lineWidth = skinnable->metric( subControl | QskAspect::Size );
|
||||||
|
const auto lineColor = skinnable->color( subControl );
|
||||||
|
|
||||||
|
return qskUpdateLineNode( skinnable, node,
|
||||||
|
lineColor, lineWidth, lineStipple, line );
|
||||||
|
}
|
||||||
|
|
||||||
|
QSGNode* QskSkinlet::updateLinesNode( const QskSkinnable* skinnable,
|
||||||
|
QSGNode* node, const QVector< QLineF >& lines, QskAspect::Subcontrol subControl )
|
||||||
|
{
|
||||||
|
auto lineStipple = skinnable->stippleMetricsHint( subControl );
|
||||||
|
if ( !lineStipple.isValid() )
|
||||||
|
lineStipple = Qt::SolidLine;
|
||||||
|
|
||||||
|
const auto lineWidth = skinnable->metric( subControl | QskAspect::Size );
|
||||||
|
const auto lineColor = skinnable->color( subControl );
|
||||||
|
|
||||||
|
return qskUpdateLinesNode( skinnable, node,
|
||||||
|
lineColor, lineWidth, lineStipple, lines );
|
||||||
|
}
|
||||||
|
|
||||||
QSGNode* QskSkinlet::updateBoxClipNode( const QskSkinnable* skinnable,
|
QSGNode* QskSkinlet::updateBoxClipNode( const QskSkinnable* skinnable,
|
||||||
QSGNode* node, QskAspect::Subcontrol subControl ) const
|
QSGNode* node, QskAspect::Subcontrol subControl ) const
|
||||||
{
|
{
|
||||||
|
|
|
@ -111,6 +111,12 @@ class QSK_EXPORT QskSkinlet
|
||||||
const QRectF&, const QskGradient&, qreal startAngle, qreal spanAngle,
|
const QRectF&, const QskGradient&, qreal startAngle, qreal spanAngle,
|
||||||
QskAspect::Subcontrol );
|
QskAspect::Subcontrol );
|
||||||
|
|
||||||
|
static QSGNode* updateLineNode( const QskSkinnable*, QSGNode*,
|
||||||
|
const QLineF&, QskAspect::Subcontrol );
|
||||||
|
|
||||||
|
static QSGNode* updateLinesNode( const QskSkinnable*,
|
||||||
|
QSGNode*, const QVector< QLineF >&, QskAspect::Subcontrol );
|
||||||
|
|
||||||
static QSGNode* updateTextNode( const QskSkinnable*, QSGNode*,
|
static QSGNode* updateTextNode( const QskSkinnable*, QSGNode*,
|
||||||
const QRectF&, Qt::Alignment, const QString&, QskAspect::Subcontrol );
|
const QRectF&, Qt::Alignment, const QString&, QskAspect::Subcontrol );
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include "QskLinesNode.h"
|
#include "QskLinesNode.h"
|
||||||
#include "QskVertex.h"
|
#include "QskVertex.h"
|
||||||
#include "QskStippleMetrics.h"
|
#include "QskStippleMetrics.h"
|
||||||
|
#include "QskStippledLineRenderer.h"
|
||||||
#include "QskSGNode.h"
|
#include "QskSGNode.h"
|
||||||
|
|
||||||
#include <qsgflatcolormaterial.h>
|
#include <qsgflatcolormaterial.h>
|
||||||
|
@ -13,10 +14,10 @@
|
||||||
#include <qtransform.h>
|
#include <qtransform.h>
|
||||||
#include <qquickitem.h>
|
#include <qquickitem.h>
|
||||||
#include <qquickwindow.h>
|
#include <qquickwindow.h>
|
||||||
|
#include <qline.h>
|
||||||
|
|
||||||
QSK_QT_PRIVATE_BEGIN
|
QSK_QT_PRIVATE_BEGIN
|
||||||
#include <private/qsgnode_p.h>
|
#include <private/qsgnode_p.h>
|
||||||
#include <private/qstroker_p.h>
|
|
||||||
QSK_QT_PRIVATE_END
|
QSK_QT_PRIVATE_END
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
|
@ -31,85 +32,88 @@ namespace
|
||||||
return t.dy() + t.m22() * y;
|
return t.dy() + t.m22() * y;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
class Renderer : public QskStippledLineRenderer
|
||||||
Thanks to the hooks of the stroker classes we can make use
|
|
||||||
of QDashStroker without having to deal with the overhead of
|
|
||||||
QPainterPaths. But it might be worth to check if this could
|
|
||||||
be done in a shader. TODO ...
|
|
||||||
*/
|
|
||||||
class DashStroker : public QDashStroker
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
DashStroker( const QskStippleMetrics& metrics )
|
inline Renderer( const QskStippleMetrics& metrics )
|
||||||
: QDashStroker( nullptr )
|
: QskStippledLineRenderer( metrics )
|
||||||
{
|
{
|
||||||
setDashOffset( metrics.offset() );
|
|
||||||
setDashPattern( metrics.pattern() );
|
|
||||||
|
|
||||||
m_elements.reserve( 2 );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QSGGeometry::Point2D* addDashes( QSGGeometry::Point2D* points,
|
inline QSGGeometry::Point2D* addDashes( QSGGeometry::Point2D* points,
|
||||||
qreal x1, qreal y1, qreal x2, qreal y2 )
|
qreal x1, qreal y1, qreal x2, qreal y2 )
|
||||||
{
|
{
|
||||||
setMoveToHook( addPoint );
|
|
||||||
setLineToHook( addPoint );
|
|
||||||
|
|
||||||
m_points = points;
|
m_points = points;
|
||||||
|
renderLine( x1, y1, x2, y2 );
|
||||||
begin( this );
|
|
||||||
|
|
||||||
m_elements.add( { QPainterPath::MoveToElement, x1, y1 } );
|
|
||||||
m_elements.add( { QPainterPath::LineToElement, x2, y2 } );
|
|
||||||
|
|
||||||
processCurrentSubpath();
|
|
||||||
|
|
||||||
end();
|
|
||||||
|
|
||||||
return m_points;
|
return m_points;
|
||||||
}
|
}
|
||||||
|
|
||||||
int pointCount( qreal x1, qreal y1, qreal x2, qreal y2 )
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
There should be a faster way to calculate the
|
|
||||||
number of points. TODO ...
|
|
||||||
*/
|
|
||||||
setMoveToHook( countPoint );
|
|
||||||
setLineToHook( countPoint );
|
|
||||||
|
|
||||||
m_count = 0;
|
|
||||||
|
|
||||||
begin( this );
|
|
||||||
|
|
||||||
m_elements.add( { QPainterPath::MoveToElement, x1, y1 } );
|
|
||||||
m_elements.add( { QPainterPath::LineToElement, x2, y2 } );
|
|
||||||
|
|
||||||
processCurrentSubpath();
|
|
||||||
|
|
||||||
end();
|
|
||||||
|
|
||||||
return m_count;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void addPoint( qfixed x, qfixed y, void* data )
|
void renderDash( qreal x1, qreal y1, qreal x2, qreal y2 ) override
|
||||||
{
|
{
|
||||||
auto stroker = reinterpret_cast< DashStroker* >( data );
|
m_points++->set( x1, y1 );
|
||||||
( stroker->m_points++ )->set( x, y );
|
m_points++->set( x2, y2 );
|
||||||
}
|
}
|
||||||
|
|
||||||
static void countPoint( qfixed, qfixed, void* data )
|
|
||||||
{
|
|
||||||
auto stroker = reinterpret_cast< DashStroker* >( data );
|
|
||||||
stroker->m_count++;
|
|
||||||
}
|
|
||||||
|
|
||||||
int m_count = 0;
|
|
||||||
QSGGeometry::Point2D* m_points;
|
QSGGeometry::Point2D* m_points;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static QSGGeometry::Point2D* qskAddDashes( const QTransform& transform,
|
||||||
|
int count, const QLineF* lines, const QskStippleMetrics& metrics,
|
||||||
|
QSGGeometry::Point2D* points )
|
||||||
|
{
|
||||||
|
if ( count <= 0 )
|
||||||
|
return points;
|
||||||
|
|
||||||
|
const bool doTransform = !transform.isIdentity();
|
||||||
|
|
||||||
|
Renderer renderer( metrics );
|
||||||
|
|
||||||
|
for ( int i = 0; i < count; i++ )
|
||||||
|
{
|
||||||
|
auto p1 = lines[i].p1();
|
||||||
|
auto p2 = lines[i].p2();
|
||||||
|
|
||||||
|
if ( doTransform )
|
||||||
|
{
|
||||||
|
p1 = transform.map( p1 );
|
||||||
|
p2 = transform.map( p2 );
|
||||||
|
}
|
||||||
|
|
||||||
|
points = renderer.addDashes( points, p1.x(), p1.y(), p2.x(), p2.y() );
|
||||||
|
}
|
||||||
|
|
||||||
|
return points;
|
||||||
|
}
|
||||||
|
|
||||||
|
static QSGGeometry::Point2D* qskAddLines( const QTransform& transform,
|
||||||
|
int count, const QLineF* lines, QSGGeometry::Point2D* points )
|
||||||
|
{
|
||||||
|
if ( count <= 0 )
|
||||||
|
return points;
|
||||||
|
|
||||||
|
const bool doTransform = !transform.isIdentity();
|
||||||
|
|
||||||
|
auto vlines = reinterpret_cast< QskVertex::Line* >( points );
|
||||||
|
|
||||||
|
for ( int i = 0; i < count; i++ )
|
||||||
|
{
|
||||||
|
auto p1 = lines[i].p1();
|
||||||
|
auto p2 = lines[i].p2();
|
||||||
|
|
||||||
|
if ( doTransform )
|
||||||
|
{
|
||||||
|
p1 = transform.map( p1 );
|
||||||
|
p2 = transform.map( p2 );
|
||||||
|
}
|
||||||
|
|
||||||
|
vlines++->setLine( p1.x(), p1.y(), p2.x(), p2.y() );
|
||||||
|
}
|
||||||
|
|
||||||
|
return reinterpret_cast< QSGGeometry::Point2D* >( vlines );
|
||||||
|
}
|
||||||
|
|
||||||
class QskLinesNodePrivate final : public QSGGeometryNodePrivate
|
class QskLinesNodePrivate final : public QSGGeometryNodePrivate
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -122,6 +126,9 @@ class QskLinesNodePrivate final : public QSGGeometryNodePrivate
|
||||||
|
|
||||||
inline qreal round( bool isHorizontal, qreal v ) const
|
inline qreal round( bool isHorizontal, qreal v ) const
|
||||||
{
|
{
|
||||||
|
if ( !doRound )
|
||||||
|
return v;
|
||||||
|
|
||||||
const auto r2 = 2.0 * devicePixelRatio;
|
const auto r2 = 2.0 * devicePixelRatio;
|
||||||
const qreal v0 = isHorizontal ? p0.x() : p0.y();
|
const qreal v0 = isHorizontal ? p0.x() : p0.y();
|
||||||
|
|
||||||
|
@ -131,6 +138,19 @@ class QskLinesNodePrivate final : public QSGGeometryNodePrivate
|
||||||
return f / devicePixelRatio - v0;
|
return f / devicePixelRatio - v0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void setLineAttributes( QskLinesNode* node,
|
||||||
|
const QColor& color, float lineWidth )
|
||||||
|
{
|
||||||
|
if ( color != material.color() )
|
||||||
|
{
|
||||||
|
material.setColor( color );
|
||||||
|
node->markDirty( QSGNode::DirtyMaterial );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( lineWidth != geometry.lineWidth() )
|
||||||
|
geometry.setLineWidth( lineWidth );
|
||||||
|
}
|
||||||
|
|
||||||
QSGGeometry geometry;
|
QSGGeometry geometry;
|
||||||
QSGFlatColorMaterial material;
|
QSGFlatColorMaterial material;
|
||||||
|
|
||||||
|
@ -139,7 +159,9 @@ class QskLinesNodePrivate final : public QSGGeometryNodePrivate
|
||||||
qreal devicePixelRatio = 1.0;
|
qreal devicePixelRatio = 1.0;
|
||||||
|
|
||||||
QskHashValue hash = 0.0;
|
QskHashValue hash = 0.0;
|
||||||
|
|
||||||
bool dirty = true;
|
bool dirty = true;
|
||||||
|
bool doRound = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
QskLinesNode::QskLinesNode()
|
QskLinesNode::QskLinesNode()
|
||||||
|
@ -176,6 +198,12 @@ void QskLinesNode::setGlobalPosition(
|
||||||
{
|
{
|
||||||
Q_D( QskLinesNode );
|
Q_D( QskLinesNode );
|
||||||
|
|
||||||
|
if ( d->doRound == false )
|
||||||
|
{
|
||||||
|
d->doRound = true;
|
||||||
|
d->dirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
if ( pos != d->p0 || devicePixelRatio != d->devicePixelRatio )
|
if ( pos != d->p0 || devicePixelRatio != d->devicePixelRatio )
|
||||||
{
|
{
|
||||||
d->p0 = pos;
|
d->p0 = pos;
|
||||||
|
@ -185,26 +213,96 @@ void QskLinesNode::setGlobalPosition(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QskLinesNode::updateLines( const QColor& color,
|
void QskLinesNode::resetGlobalPosition()
|
||||||
|
{
|
||||||
|
Q_D( QskLinesNode );
|
||||||
|
|
||||||
|
if ( d->doRound == true )
|
||||||
|
{
|
||||||
|
d->doRound = false;
|
||||||
|
d->dirty = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QskLinesNode::updateRect( const QColor& color,
|
||||||
qreal lineWidth, const QskStippleMetrics& stippleMetrics,
|
qreal lineWidth, const QskStippleMetrics& stippleMetrics,
|
||||||
const QTransform& transform, const QRectF& rect )
|
const QTransform& transform, const QRectF& rect )
|
||||||
{
|
{
|
||||||
// using QVarLengthArray instead. TODO ...
|
// using QVarLengthArray instead. TODO ...
|
||||||
updateLines( color, lineWidth, stippleMetrics, transform,
|
updateGrid( color, lineWidth, stippleMetrics, transform,
|
||||||
rect, { rect.left(), rect.right() }, { rect.top(), rect.bottom() } );
|
rect, { rect.left(), rect.right() }, { rect.top(), rect.bottom() } );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QskLinesNode::updateLine( const QColor& color,
|
||||||
|
qreal lineWidth, const QskStippleMetrics& stippleMetrics,
|
||||||
|
const QTransform& transform, const QPointF& p1, const QPointF& p2 )
|
||||||
|
{
|
||||||
|
if ( p1 == p2 )
|
||||||
|
{
|
||||||
|
updateLines( color, lineWidth, stippleMetrics, transform, 0, nullptr );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const QLineF line( p1, p2 );
|
||||||
|
updateLines( color, lineWidth, stippleMetrics, transform, 1, &line );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void QskLinesNode::updateLines( const QColor& color,
|
void QskLinesNode::updateLines( const QColor& color,
|
||||||
|
qreal lineWidth, const QskStippleMetrics& stippleMetrics,
|
||||||
|
const QTransform& transform, const QVector< QLineF >& lines )
|
||||||
|
{
|
||||||
|
updateLines( color, lineWidth, stippleMetrics,
|
||||||
|
transform, lines.count(), lines.constData() );
|
||||||
|
}
|
||||||
|
|
||||||
|
void QskLinesNode::updateLines( const QColor& color,
|
||||||
|
qreal lineWidth, const QskStippleMetrics& stippleMetrics,
|
||||||
|
const QTransform& transform, int count, const QLineF* lines )
|
||||||
|
{
|
||||||
|
Q_D( QskLinesNode );
|
||||||
|
|
||||||
|
if ( !stippleMetrics.isValid() || !color.isValid()
|
||||||
|
|| color.alpha() == 0 || count == 0 )
|
||||||
|
{
|
||||||
|
QskSGNode::resetGeometry( this );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QskHashValue hash = 9784;
|
||||||
|
|
||||||
|
hash = stippleMetrics.hash( hash );
|
||||||
|
hash = qHash( transform, hash );
|
||||||
|
hash = qHashBits( lines, count * sizeof( QLineF ) );
|
||||||
|
|
||||||
|
if ( hash != d->hash )
|
||||||
|
{
|
||||||
|
d->dirty = true;
|
||||||
|
d->hash = hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( d->dirty )
|
||||||
|
{
|
||||||
|
updateGeometry( stippleMetrics, transform, count, lines );
|
||||||
|
|
||||||
|
markDirty( QSGNode::DirtyGeometry );
|
||||||
|
d->dirty = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
d->setLineAttributes( this, color, lineWidth );
|
||||||
|
}
|
||||||
|
|
||||||
|
void QskLinesNode::updateGrid( const QColor& color,
|
||||||
qreal lineWidth, const QskStippleMetrics& stippleMetrics,
|
qreal lineWidth, const QskStippleMetrics& stippleMetrics,
|
||||||
const QTransform& transform, const QRectF& rect,
|
const QTransform& transform, const QRectF& rect,
|
||||||
const QVector< qreal >& xValues, const QVector< qreal >& yValues )
|
const QVector< qreal >& xValues, const QVector< qreal >& yValues )
|
||||||
{
|
{
|
||||||
Q_D( QskLinesNode );
|
Q_D( QskLinesNode );
|
||||||
|
|
||||||
if ( color != d->material.color() )
|
if ( !stippleMetrics.isValid() || !color.isValid() || color.alpha() == 0 )
|
||||||
{
|
{
|
||||||
d->material.setColor( color );
|
QskSGNode::resetGeometry( this );
|
||||||
markDirty( QSGNode::DirtyMaterial );
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QskHashValue hash = 9784;
|
QskHashValue hash = 9784;
|
||||||
|
@ -223,24 +321,62 @@ void QskLinesNode::updateLines( const QColor& color,
|
||||||
|
|
||||||
if( d->dirty )
|
if( d->dirty )
|
||||||
{
|
{
|
||||||
if ( rect.isEmpty() || !stippleMetrics.isValid()
|
updateGeometry( stippleMetrics, transform, rect, xValues, yValues );
|
||||||
|| !color.isValid() || color.alpha() == 0 )
|
|
||||||
{
|
|
||||||
QskSGNode::resetGeometry( this );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
updateGeometry( stippleMetrics,
|
|
||||||
transform, rect, xValues, yValues );
|
|
||||||
}
|
|
||||||
|
|
||||||
markDirty( QSGNode::DirtyGeometry );
|
markDirty( QSGNode::DirtyGeometry );
|
||||||
d->dirty = false;
|
d->dirty = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const float lineWidthF = lineWidth;
|
d->setLineAttributes( this, color, lineWidth );
|
||||||
if( lineWidthF != d->geometry.lineWidth() )
|
}
|
||||||
d->geometry.setLineWidth( lineWidthF );
|
|
||||||
|
void QskLinesNode::updateGeometry( const QskStippleMetrics& stippleMetrics,
|
||||||
|
const QTransform& transform, int count, const QLineF* lines )
|
||||||
|
{
|
||||||
|
Q_D( QskLinesNode );
|
||||||
|
|
||||||
|
auto& geom = d->geometry;
|
||||||
|
|
||||||
|
QSGGeometry::Point2D* points = nullptr;
|
||||||
|
|
||||||
|
if ( stippleMetrics.isSolid() )
|
||||||
|
{
|
||||||
|
using namespace QskVertex;
|
||||||
|
|
||||||
|
geom.allocate( 2 * count );
|
||||||
|
points = geom.vertexDataAsPoint2D();
|
||||||
|
|
||||||
|
points = qskAddLines( transform, count, lines, points );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const bool doTransform = !transform.isIdentity();
|
||||||
|
|
||||||
|
Renderer renderer( stippleMetrics );
|
||||||
|
|
||||||
|
int lineCount = 0;
|
||||||
|
for ( int i = 0; i < count; i++ )
|
||||||
|
{
|
||||||
|
auto p1 = lines[i].p1();
|
||||||
|
auto p2 = lines[i].p2();
|
||||||
|
|
||||||
|
if ( doTransform )
|
||||||
|
{
|
||||||
|
p1 = transform.map( p1 );
|
||||||
|
p2 = transform.map( p2 );
|
||||||
|
}
|
||||||
|
lineCount += renderer.dashCount( p1, p2 );
|
||||||
|
}
|
||||||
|
|
||||||
|
d->geometry.allocate( 2 * lineCount );
|
||||||
|
points = d->geometry.vertexDataAsPoint2D();
|
||||||
|
|
||||||
|
points = qskAddDashes( transform,
|
||||||
|
count, lines, stippleMetrics, points );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Q_ASSERT( geom.vertexCount() == ( points - geom.vertexDataAsPoint2D() ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
void QskLinesNode::updateGeometry(
|
void QskLinesNode::updateGeometry(
|
||||||
|
@ -275,12 +411,13 @@ void QskLinesNode::updateGeometry(
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DashStroker stroker( stippleMetrics );
|
Renderer renderer( stippleMetrics );
|
||||||
|
|
||||||
const int countX = stroker.pointCount( 0.0, y1, 0.0, y2 );
|
const auto countX = renderer.dashCount( 0.0, y1, 0.0, y2 );
|
||||||
const int countY = stroker.pointCount( x1, 0.0, x2, 0.0 );
|
const auto countY = renderer.dashCount( x1, 0.0, x2, 0.0 );
|
||||||
|
const auto count = xValues.count() * countX + yValues.count() * countY;
|
||||||
|
|
||||||
d->geometry.allocate( xValues.count() * countX + yValues.count() * countY );
|
d->geometry.allocate( 2 * count );
|
||||||
points = d->geometry.vertexDataAsPoint2D();
|
points = d->geometry.vertexDataAsPoint2D();
|
||||||
|
|
||||||
points = setStippledLines( Qt::Vertical, y1, y2,
|
points = setStippledLines( Qt::Vertical, y1, y2,
|
||||||
|
@ -305,7 +442,7 @@ QSGGeometry::Point2D* QskLinesNode::setStippledLines(
|
||||||
if ( count <= 0 )
|
if ( count <= 0 )
|
||||||
return points;
|
return points;
|
||||||
|
|
||||||
DashStroker stroker( stippleMetrics );
|
Renderer renderer( stippleMetrics );
|
||||||
|
|
||||||
// Calculating the dashes for the first line
|
// Calculating the dashes for the first line
|
||||||
|
|
||||||
|
@ -317,7 +454,7 @@ QSGGeometry::Point2D* QskLinesNode::setStippledLines(
|
||||||
auto x = mapX( transform, values[0] );
|
auto x = mapX( transform, values[0] );
|
||||||
x = d->round( true, x );
|
x = d->round( true, x );
|
||||||
|
|
||||||
points = stroker.addDashes( points, x, v1, x, v2 );
|
points = renderer.addDashes( points, x, v1, x, v2 );
|
||||||
dashCount = points - line0;
|
dashCount = points - line0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -325,7 +462,7 @@ QSGGeometry::Point2D* QskLinesNode::setStippledLines(
|
||||||
auto y = mapY( transform, values[0] );
|
auto y = mapY( transform, values[0] );
|
||||||
y = d->round( false, y );
|
y = d->round( false, y );
|
||||||
|
|
||||||
points = stroker.addDashes( points, v1, y, v2, y );
|
points = renderer.addDashes( points, v1, y, v2, y );
|
||||||
dashCount = points - line0;
|
dashCount = points - line0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@ class QskIntervalF;
|
||||||
class QskStippleMetrics;
|
class QskStippleMetrics;
|
||||||
class QTransform;
|
class QTransform;
|
||||||
class QPointF;
|
class QPointF;
|
||||||
|
class QLineF;
|
||||||
class QQuickItem;
|
class QQuickItem;
|
||||||
|
|
||||||
class QskLinesNodePrivate;
|
class QskLinesNodePrivate;
|
||||||
|
@ -31,15 +32,29 @@ class QSK_EXPORT QskLinesNode : public QSGGeometryNode
|
||||||
|
|
||||||
void setGlobalPosition( const QPointF&, qreal devicePixelRatio );
|
void setGlobalPosition( const QPointF&, qreal devicePixelRatio );
|
||||||
void setGlobalPosition( const QQuickItem* );
|
void setGlobalPosition( const QQuickItem* );
|
||||||
|
void resetGlobalPosition();
|
||||||
|
|
||||||
void updateLines( const QColor&, qreal lineWidth,
|
void updateGrid( const QColor&, qreal lineWidth,
|
||||||
const QskStippleMetrics&, const QTransform&, const QRectF&,
|
const QskStippleMetrics&, const QTransform&, const QRectF&,
|
||||||
const QVector< qreal >&, const QVector< qreal >& );
|
const QVector< qreal >&, const QVector< qreal >& );
|
||||||
|
|
||||||
void updateLines( const QColor&, qreal lineWidth,
|
void updateRect( const QColor&, qreal lineWidth,
|
||||||
const QskStippleMetrics&, const QTransform&, const QRectF& );
|
const QskStippleMetrics&, const QTransform&, const QRectF& );
|
||||||
|
|
||||||
|
void updateLine( const QColor&, qreal lineWidth,
|
||||||
|
const QskStippleMetrics&, const QTransform&,
|
||||||
|
const QPointF&, const QPointF& );
|
||||||
|
|
||||||
|
void updateLines( const QColor&, qreal lineWidth,
|
||||||
|
const QskStippleMetrics&, const QTransform&, const QVector< QLineF >& );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void updateLines( const QColor&, qreal lineWidth, const QskStippleMetrics&,
|
||||||
|
const QTransform&, int count, const QLineF* );
|
||||||
|
|
||||||
|
void updateGeometry( const QskStippleMetrics&, const QTransform&,
|
||||||
|
int count, const QLineF* );
|
||||||
|
|
||||||
void updateGeometry(
|
void updateGeometry(
|
||||||
const QskStippleMetrics&, const QTransform&, const QRectF&,
|
const QskStippleMetrics&, const QTransform&, const QRectF&,
|
||||||
const QVector< qreal >&, const QVector< qreal >& );
|
const QVector< qreal >&, const QVector< qreal >& );
|
||||||
|
|
Loading…
Reference in New Issue