6#include "QskLinesNode.h"
8#include "QskStippleMetrics.h"
9#include "QskStippledLineRenderer.h"
11#include "QskRgbValue.h"
13#include <qtransform.h>
18 inline qreal mapX(
const QTransform& t, qreal x )
20 return t.dx() + t.m11() * x;
23 inline qreal mapY(
const QTransform& t, qreal y )
25 return t.dy() + t.m22() * y;
36 inline QSGGeometry::Point2D* addDashes( QSGGeometry::Point2D* points,
37 qreal x1, qreal y1, qreal x2, qreal y2 )
40 renderLine( x1, y1, x2, y2 );
45 void renderDash( qreal x1, qreal y1, qreal x2, qreal y2 )
override
47 m_points++->set( x1, y1 );
48 m_points++->set( x2, y2 );
51 QSGGeometry::Point2D* m_points;
55static QSGGeometry::Point2D* qskAddDashes(
const QTransform& transform,
57 QSGGeometry::Point2D* points )
62 const bool doTransform = !transform.isIdentity();
64 Renderer renderer( metrics );
66 for (
int i = 0; i < count; i++ )
68 auto p1 = lines[i].p1();
69 auto p2 = lines[i].p2();
73 p1 = transform.map( p1 );
74 p2 = transform.map( p2 );
77 points = renderer.addDashes( points, p1.x(), p1.y(), p2.x(), p2.y() );
83static QSGGeometry::Point2D* qskAddLines(
const QTransform& transform,
84 int count,
const QLineF* lines, QSGGeometry::Point2D* points )
89 const bool doTransform = !transform.isIdentity();
93 for (
int i = 0; i < count; i++ )
95 auto p1 = lines[i].p1();
96 auto p2 = lines[i].p2();
100 p1 = transform.map( p1 );
101 p2 = transform.map( p2 );
104 vlines++->setLine( p1.x(), p1.y(), p2.x(), p2.y() );
107 return reinterpret_cast< QSGGeometry::Point2D*
>( vlines );
110QskLinesNode::QskLinesNode()
114QskLinesNode::~QskLinesNode()
118void QskLinesNode::updateRect(
const QColor& color,
120 const QTransform& transform,
const QRectF& rect )
123 updateGrid( color, lineWidth, stippleMetrics, transform,
124 rect, { rect.left(), rect.right() }, { rect.top(), rect.bottom() } );
127void QskLinesNode::updateLine(
const QColor& color,
128 qreal lineWidth,
const QPointF& p1,
const QPointF& p2 )
133void QskLinesNode::updateLine(
const QColor& color,
135 const QTransform& transform,
const QPointF& p1,
const QPointF& p2 )
139 updateLines( color, lineWidth, stippleMetrics, transform, 0,
nullptr );
143 const QLineF line( p1, p2 );
144 updateLines( color, lineWidth, stippleMetrics, transform, 1, &line );
148void QskLinesNode::updateLines(
const QColor& color,
149 qreal lineWidth,
const QVector< QLineF >& lines )
152 QTransform(), lines.count(), lines.constData() );
155void QskLinesNode::updateLines(
const QColor& color,
157 const QTransform& transform,
const QVector< QLineF >& lines )
159 updateLines( color, lineWidth, stippleMetrics,
160 transform, lines.count(), lines.constData() );
163void QskLinesNode::updateLines(
const QColor& color,
165 const QTransform& transform,
int count,
const QLineF* lines )
167 if ( !stippleMetrics.isValid() || !QskRgb::isVisible( color ) || count == 0 )
169 QskSGNode::resetGeometry(
this );
173 QskHashValue hash = 9784;
175 hash = stippleMetrics.hash( hash );
176 hash = qHash( transform, hash );
177 hash = qHashBits( lines, count *
sizeof( QLineF ) );
179 if ( hash != m_hash )
183 updateGeometry( stippleMetrics, transform, count, lines );
185 geometry()->markVertexDataDirty();
186 markDirty( QSGNode::DirtyGeometry );
189 setLineWidth( lineWidth );
193void QskLinesNode::updateGrid(
const QColor& color,
195 const QTransform& transform,
const QRectF& rect,
196 const QVector< qreal >& xValues,
const QVector< qreal >& yValues )
198 if ( !stippleMetrics.isValid() || !QskRgb::isVisible( color ) )
200 QskSGNode::resetGeometry(
this );
204 QskHashValue hash = 9784;
206 hash = stippleMetrics.hash( hash );
207 hash = qHash( transform, hash );
208 hash = qHashBits( &rect,
sizeof( QRectF ), hash );
209 hash = qHash( xValues, hash );
210 hash = qHash( yValues, hash );
212 if ( hash != m_hash )
216 updateGeometry( stippleMetrics, transform, rect, xValues, yValues );
218 geometry()->markVertexDataDirty();
219 markDirty( QSGNode::DirtyGeometry );
222 setLineWidth( lineWidth );
227 const QTransform& transform,
int count,
const QLineF* lines )
229 auto& geom = *geometry();
231 QSGGeometry::Point2D* points =
nullptr;
233 if ( stippleMetrics.isSolid() )
235 using namespace QskVertex;
237 geom.allocate( 2 * count );
238 points = geom.vertexDataAsPoint2D();
240 points = qskAddLines( transform, count, lines, points );
244 const bool doTransform = !transform.isIdentity();
246 Renderer renderer( stippleMetrics );
249 for (
int i = 0; i < count; i++ )
251 auto p1 = lines[i].p1();
252 auto p2 = lines[i].p2();
256 p1 = transform.map( p1 );
257 p2 = transform.map( p2 );
259 lineCount += renderer.dashCount( p1, p2 );
262 geometry()->allocate( 2 * lineCount );
263 points = geometry()->vertexDataAsPoint2D();
265 points = qskAddDashes( transform,
266 count, lines, stippleMetrics, points );
269 Q_ASSERT( geom.vertexCount() == ( points - geom.vertexDataAsPoint2D() ) );
272void QskLinesNode::updateGeometry(
274 const QTransform& transform,
const QRectF& rect,
275 const QVector< qreal >& xValues,
const QVector< qreal >& yValues )
277 auto& geom = *geometry();
279 const auto y1 = mapY( transform, rect.top() );
280 const auto y2 = mapY( transform, rect.bottom() );
282 const auto x1 = mapX( transform, rect.left() );
283 const auto x2 = mapX( transform, rect.right() );
285 QSGGeometry::Point2D* points =
nullptr;
287 if ( stippleMetrics.isSolid() )
289 using namespace QskVertex;
291 geom.allocate( 2 * ( xValues.count() + yValues.count() ) );
292 points = geom.vertexDataAsPoint2D();
294 points = setSolidLines( Qt::Vertical, y1, y2,
295 transform, xValues.count(), xValues.constData(), points );
297 points = setSolidLines( Qt::Horizontal, x1, x2,
298 transform, yValues.count(), yValues.constData(), points );
302 Renderer renderer( stippleMetrics );
304 const auto countX = renderer.dashCount( 0.0, y1, 0.0, y2 );
305 const auto countY = renderer.dashCount( x1, 0.0, x2, 0.0 );
306 const auto count = xValues.count() * countX + yValues.count() * countY;
308 geometry()->allocate( 2 * count );
309 points = geometry()->vertexDataAsPoint2D();
311 points = setStippledLines( Qt::Vertical, y1, y2,
312 transform, xValues.count(), xValues.constData(),
313 stippleMetrics, points );
315 points = setStippledLines( Qt::Horizontal, x1, x2,
316 transform, yValues.count(), yValues.constData(),
317 stippleMetrics, points );
320 Q_ASSERT( geom.vertexCount() == ( points - geom.vertexDataAsPoint2D() ) );
323QSGGeometry::Point2D* QskLinesNode::setStippledLines(
324 Qt::Orientation orientation, qreal v1, qreal v2,
325 const QTransform& transform,
int count,
const qreal* values,
331 Renderer renderer( stippleMetrics );
335 const auto line0 = points;
338 if ( orientation == Qt::Vertical )
340 const auto x = mapX( transform, values[0] );
342 points = renderer.addDashes( points, x, v1, x, v2 );
343 dashCount = points - line0;
347 const auto y = mapY( transform, values[0] );
349 points = renderer.addDashes( points, v1, y, v2, y );
350 dashCount = points - line0;
355 if ( orientation == Qt::Vertical )
357 for (
int i = 1; i < count; i++ )
359 const auto x = mapX( transform, values[i] );
361 for (
int j = 0; j < dashCount; j++ )
362 points++->set( x, line0[j].y );
367 for (
int i = 1; i < count; i++ )
369 const auto y = mapY( transform, values[i] );
371 for (
int j = 0; j < dashCount; j++ )
372 points++->set( line0[j].x, y );
379QSGGeometry::Point2D* QskLinesNode::setSolidLines(
380 Qt::Orientation orientation, qreal v1, qreal v2,
381 const QTransform& transform,
int count,
const qreal* values,
382 QSGGeometry::Point2D* points )
const
389 if ( orientation == Qt::Vertical )
391 for (
int i = 0; i < count; i++ )
393 const auto x = mapX( transform, values[i] );
394 lines++->setVLine( x, v1, v2 );
399 for (
int i = 0; i < count; i++ )
401 const auto y = mapY( transform, values[i] );
402 lines++->setHLine( v1, v2, y );
406 return reinterpret_cast< QSGGeometry::Point2D*
>( lines );
409void QskLinesNode::updatePolygon(
const QColor& color, qreal lineWidth,
410 const QTransform& transform,
const QPolygonF& polygon )
412 if ( polygon.isEmpty() || !QskRgb::isVisible( color ) )
414 QskSGNode::resetGeometry(
this );
420 geometry()->allocate( polygon.count() + 1 );
422 auto points = geometry()->vertexDataAsPoint2D();
424 if ( transform.isIdentity() )
426 for (
int i = 0; i < polygon.count(); i++ )
428 const auto& pos = polygon[i];
429 points[i].set( pos.x(), pos.y() );
434 for (
int i = 0; i < polygon.count(); i++ )
436 const auto pos = transform.map( polygon[i] );
437 points[i].set( pos.x(), pos.y() );
441 points[ polygon.count() ] = points[0];
443 geometry()->markVertexDataDirty();
444 markDirty( QSGNode::DirtyGeometry );
447 setLineWidth( lineWidth );