QskLinesNode derived from QskBasicLinesNode

This commit is contained in:
Uwe Rathmann 2023-11-23 15:47:08 +01:00
parent dc64f21901
commit e31c063937
12 changed files with 31 additions and 178 deletions

View File

@ -9,17 +9,9 @@
#include "QskStippledLineRenderer.h" #include "QskStippledLineRenderer.h"
#include "QskSGNode.h" #include "QskSGNode.h"
#include <qsgflatcolormaterial.h>
#include <qsgvertexcolormaterial.h>
#include <qtransform.h> #include <qtransform.h>
#include <qquickitem.h>
#include <qquickwindow.h>
#include <qline.h> #include <qline.h>
QSK_QT_PRIVATE_BEGIN
#include <private/qsgnode_p.h>
QSK_QT_PRIVATE_END
namespace namespace
{ {
inline qreal mapX( const QTransform& t, qreal x ) inline qreal mapX( const QTransform& t, qreal x )
@ -114,115 +106,14 @@ static QSGGeometry::Point2D* qskAddLines( const QTransform& transform,
return reinterpret_cast< QSGGeometry::Point2D* >( vlines ); return reinterpret_cast< QSGGeometry::Point2D* >( vlines );
} }
class QskLinesNodePrivate final : public QSGGeometryNodePrivate
{
public:
QskLinesNodePrivate()
: geometry( QSGGeometry::defaultAttributes_Point2D(), 0 )
{
geometry.setDrawingMode( QSGGeometry::DrawLines );
}
inline qreal round( bool isHorizontal, qreal v ) const
{
if ( !doRound )
return v;
const auto r2 = 2.0 * devicePixelRatio;
const qreal v0 = isHorizontal ? p0.x() : p0.y();
const int d = qRound( r2 * ( v + v0 ) );
const auto f = ( d % 2 ? d : d - 1 ) / r2;
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;
QSGFlatColorMaterial material;
// position of [0,0] in device coordinates
QPointF p0;
qreal devicePixelRatio = 1.0;
QskHashValue hash = 0.0;
bool dirty = true;
bool doRound = false;
};
QskLinesNode::QskLinesNode() QskLinesNode::QskLinesNode()
: QSGGeometryNode( *new QskLinesNodePrivate )
{ {
Q_D( QskLinesNode );
setGeometry( &d->geometry );
setMaterial( &d->material );
} }
QskLinesNode::~QskLinesNode() QskLinesNode::~QskLinesNode()
{ {
} }
void QskLinesNode::setGlobalPosition( const QQuickItem* item )
{
QPointF p0;
qreal devicePixelRatio = 1.0;
if ( item )
{
p0 = item->mapToGlobal( QPointF() );
if ( auto w = item->window() )
devicePixelRatio = w->devicePixelRatio();
}
setGlobalPosition( p0, devicePixelRatio );
}
void QskLinesNode::setGlobalPosition(
const QPointF& pos, qreal devicePixelRatio )
{
Q_D( QskLinesNode );
if ( d->doRound == false )
{
d->doRound = true;
d->dirty = true;
}
if ( pos != d->p0 || devicePixelRatio != d->devicePixelRatio )
{
d->p0 = pos;
d->devicePixelRatio = devicePixelRatio;
d->dirty = true;
}
}
void QskLinesNode::resetGlobalPosition()
{
Q_D( QskLinesNode );
if ( d->doRound == true )
{
d->doRound = false;
d->dirty = true;
}
}
void QskLinesNode::updateRect( const QColor& color, 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 )
@ -272,8 +163,6 @@ void QskLinesNode::updateLines( const QColor& color,
qreal lineWidth, const QskStippleMetrics& stippleMetrics, qreal lineWidth, const QskStippleMetrics& stippleMetrics,
const QTransform& transform, int count, const QLineF* lines ) const QTransform& transform, int count, const QLineF* lines )
{ {
Q_D( QskLinesNode );
if ( !stippleMetrics.isValid() || !color.isValid() if ( !stippleMetrics.isValid() || !color.isValid()
|| color.alpha() == 0 || count == 0 ) || color.alpha() == 0 || count == 0 )
{ {
@ -287,22 +176,18 @@ void QskLinesNode::updateLines( const QColor& color,
hash = qHash( transform, hash ); hash = qHash( transform, hash );
hash = qHashBits( lines, count * sizeof( QLineF ) ); hash = qHashBits( lines, count * sizeof( QLineF ) );
if ( hash != d->hash ) if ( hash != m_hash )
{ {
d->dirty = true; m_hash = hash;
d->hash = hash;
}
if( d->dirty )
{
updateGeometry( stippleMetrics, transform, count, lines ); updateGeometry( stippleMetrics, transform, count, lines );
d->geometry.markVertexDataDirty(); geometry()->markVertexDataDirty();
markDirty( QSGNode::DirtyGeometry ); markDirty( QSGNode::DirtyGeometry );
d->dirty = false;
} }
d->setLineAttributes( this, color, lineWidth ); setLineWidth( lineWidth );
setColor( color );
} }
void QskLinesNode::updateGrid( const QColor& color, void QskLinesNode::updateGrid( const QColor& color,
@ -310,8 +195,6 @@ void QskLinesNode::updateGrid( const QColor& color,
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 );
if ( !stippleMetrics.isValid() || !color.isValid() || color.alpha() == 0 ) if ( !stippleMetrics.isValid() || !color.isValid() || color.alpha() == 0 )
{ {
QskSGNode::resetGeometry( this ); QskSGNode::resetGeometry( this );
@ -326,30 +209,24 @@ void QskLinesNode::updateGrid( const QColor& color,
hash = qHash( xValues, hash ); hash = qHash( xValues, hash );
hash = qHash( yValues, hash ); hash = qHash( yValues, hash );
if ( hash != d->hash ) if ( hash != m_hash )
{ {
d->dirty = true; m_hash = hash;
d->hash = hash;
}
if( d->dirty )
{
updateGeometry( stippleMetrics, transform, rect, xValues, yValues ); updateGeometry( stippleMetrics, transform, rect, xValues, yValues );
d->geometry.markVertexDataDirty(); geometry()->markVertexDataDirty();
markDirty( QSGNode::DirtyGeometry ); markDirty( QSGNode::DirtyGeometry );
d->dirty = false;
} }
d->setLineAttributes( this, color, lineWidth ); setLineWidth( lineWidth );
setColor( color );
} }
void QskLinesNode::updateGeometry( const QskStippleMetrics& stippleMetrics, void QskLinesNode::updateGeometry( const QskStippleMetrics& stippleMetrics,
const QTransform& transform, int count, const QLineF* lines ) const QTransform& transform, int count, const QLineF* lines )
{ {
Q_D( QskLinesNode ); auto& geom = *geometry();
auto& geom = d->geometry;
QSGGeometry::Point2D* points = nullptr; QSGGeometry::Point2D* points = nullptr;
@ -382,8 +259,8 @@ void QskLinesNode::updateGeometry( const QskStippleMetrics& stippleMetrics,
lineCount += renderer.dashCount( p1, p2 ); lineCount += renderer.dashCount( p1, p2 );
} }
d->geometry.allocate( 2 * lineCount ); geometry()->allocate( 2 * lineCount );
points = d->geometry.vertexDataAsPoint2D(); points = geometry()->vertexDataAsPoint2D();
points = qskAddDashes( transform, points = qskAddDashes( transform,
count, lines, stippleMetrics, points ); count, lines, stippleMetrics, points );
@ -397,9 +274,7 @@ void QskLinesNode::updateGeometry(
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 ); auto& geom = *geometry();
auto& geom = d->geometry;
const auto y1 = mapY( transform, rect.top() ); const auto y1 = mapY( transform, rect.top() );
const auto y2 = mapY( transform, rect.bottom() ); const auto y2 = mapY( transform, rect.bottom() );
@ -430,8 +305,8 @@ void QskLinesNode::updateGeometry(
const auto countY = renderer.dashCount( 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; const auto count = xValues.count() * countX + yValues.count() * countY;
d->geometry.allocate( 2 * count ); geometry()->allocate( 2 * count );
points = d->geometry.vertexDataAsPoint2D(); points = geometry()->vertexDataAsPoint2D();
points = setStippledLines( Qt::Vertical, y1, y2, points = setStippledLines( Qt::Vertical, y1, y2,
transform, xValues.count(), xValues.constData(), transform, xValues.count(), xValues.constData(),
@ -450,8 +325,6 @@ QSGGeometry::Point2D* QskLinesNode::setStippledLines(
const QTransform& transform, int count, const qreal* values, const QTransform& transform, int count, const qreal* values,
const QskStippleMetrics& stippleMetrics, QSGGeometry::Point2D* points ) const const QskStippleMetrics& stippleMetrics, QSGGeometry::Point2D* points ) const
{ {
Q_D( const QskLinesNode );
if ( count <= 0 ) if ( count <= 0 )
return points; return points;
@ -464,16 +337,14 @@ QSGGeometry::Point2D* QskLinesNode::setStippledLines(
if ( orientation == Qt::Vertical ) if ( orientation == Qt::Vertical )
{ {
auto x = mapX( transform, values[0] ); const auto x = mapX( transform, values[0] );
x = d->round( true, x );
points = renderer.addDashes( points, x, v1, x, v2 ); points = renderer.addDashes( points, x, v1, x, v2 );
dashCount = points - line0; dashCount = points - line0;
} }
else else
{ {
auto y = mapY( transform, values[0] ); const auto y = mapY( transform, values[0] );
y = d->round( false, y );
points = renderer.addDashes( points, v1, y, v2, y ); points = renderer.addDashes( points, v1, y, v2, y );
dashCount = points - line0; dashCount = points - line0;
@ -485,8 +356,7 @@ QSGGeometry::Point2D* QskLinesNode::setStippledLines(
{ {
for ( int i = 1; i < count; i++ ) for ( int i = 1; i < count; i++ )
{ {
auto x = mapX( transform, values[i] ); const auto x = mapX( transform, values[i] );
x = d->round( true, x );
for ( int j = 0; j < dashCount; j++ ) for ( int j = 0; j < dashCount; j++ )
points++->set( x, line0[j].y ); points++->set( x, line0[j].y );
@ -496,8 +366,7 @@ QSGGeometry::Point2D* QskLinesNode::setStippledLines(
{ {
for ( int i = 1; i < count; i++ ) for ( int i = 1; i < count; i++ )
{ {
auto y = mapY( transform, values[i] ); const auto y = mapY( transform, values[i] );
y = d->round( false, y );
for ( int j = 0; j < dashCount; j++ ) for ( int j = 0; j < dashCount; j++ )
points++->set( line0[j].x, y ); points++->set( line0[j].x, y );
@ -512,8 +381,6 @@ QSGGeometry::Point2D* QskLinesNode::setSolidLines(
const QTransform& transform, int count, const qreal* values, const QTransform& transform, int count, const qreal* values,
QSGGeometry::Point2D* points ) const QSGGeometry::Point2D* points ) const
{ {
Q_D( const QskLinesNode );
if ( count <= 0 ) if ( count <= 0 )
return points; return points;
@ -523,9 +390,7 @@ QSGGeometry::Point2D* QskLinesNode::setSolidLines(
{ {
for ( int i = 0; i < count; i++ ) for ( int i = 0; i < count; i++ )
{ {
auto x = mapX( transform, values[i] ); const auto x = mapX( transform, values[i] );
x = d->round( true, x );
lines++->setVLine( x, v1, v2 ); lines++->setVLine( x, v1, v2 );
} }
} }
@ -533,9 +398,7 @@ QSGGeometry::Point2D* QskLinesNode::setSolidLines(
{ {
for ( int i = 0; i < count; i++ ) for ( int i = 0; i < count; i++ )
{ {
auto y = mapY( transform, values[i] ); const auto y = mapY( transform, values[i] );
y = d->round( false, y );
lines++->setHLine( v1, v2, y ); lines++->setHLine( v1, v2, y );
} }
} }
@ -552,13 +415,11 @@ void QskLinesNode::updatePolygon( const QColor& color, qreal lineWidth,
return; return;
} }
Q_D( QskLinesNode );
if ( true ) // for the moment we always update the geometry. TODO ... if ( true ) // for the moment we always update the geometry. TODO ...
{ {
d->geometry.allocate( polygon.count() + 1 ); geometry()->allocate( polygon.count() + 1 );
auto points = d->geometry.vertexDataAsPoint2D(); auto points = geometry()->vertexDataAsPoint2D();
if ( transform.isIdentity() ) if ( transform.isIdentity() )
{ {
@ -579,9 +440,10 @@ void QskLinesNode::updatePolygon( const QColor& color, qreal lineWidth,
points[ polygon.count() ] = points[0]; points[ polygon.count() ] = points[0];
d->geometry.markVertexDataDirty(); geometry()->markVertexDataDirty();
markDirty( QSGNode::DirtyGeometry ); markDirty( QSGNode::DirtyGeometry );
} }
d->setLineAttributes( this, color, lineWidth ); setLineWidth( lineWidth );
setColor( color );
} }

View File

@ -6,9 +6,7 @@
#ifndef QSK_LINES_NODE_H #ifndef QSK_LINES_NODE_H
#define QSK_LINES_NODE_H #define QSK_LINES_NODE_H
#include "QskGlobal.h" #include "QskBasicLinesNode.h"
#include <qsgnode.h>
#include <qvector.h> #include <qvector.h>
class QskIntervalF; class QskIntervalF;
@ -17,26 +15,19 @@ class QTransform;
class QPointF; class QPointF;
class QLineF; class QLineF;
class QPolygonF; class QPolygonF;
class QQuickItem;
class QskLinesNodePrivate;
/* /*
A node for stippled or solid lines. A node for stippled or solid lines.
For the moment limited to horizontal/vertical lines: TODO For the moment limited to horizontal/vertical lines: TODO
*/ */
class QSK_EXPORT QskLinesNode : public QSGGeometryNode class QSK_EXPORT QskLinesNode : public QskBasicLinesNode
{ {
using Inherited = QSGGeometryNode; using Inherited = QskBasicLinesNode;
public: public:
QskLinesNode(); QskLinesNode();
~QskLinesNode() override; ~QskLinesNode() override;
void setGlobalPosition( const QPointF&, qreal devicePixelRatio );
void setGlobalPosition( const QQuickItem* );
void resetGlobalPosition();
void updateGrid( 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 >& );
@ -80,7 +71,7 @@ class QSK_EXPORT QskLinesNode : public QSGGeometryNode
const QTransform&, int count, const qreal* values, const QTransform&, int count, const qreal* values,
const QskStippleMetrics&, QSGGeometry::Point2D* ) const; const QskStippleMetrics&, QSGGeometry::Point2D* ) const;
Q_DECLARE_PRIVATE( QskLinesNode ) QskHashValue m_hash = 0.0;
}; };
#endif #endif

Binary file not shown.

Binary file not shown.