/****************************************************************************** * QSkinny - Copyright (C) 2016 Uwe Rathmann * SPDX-License-Identifier: BSD-3-Clause *****************************************************************************/ #include "QskStippledLineRenderer.h" QSK_QT_PRIVATE_BEGIN #include QSK_QT_PRIVATE_END namespace { /* 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: DashStroker( QskStippledLineRenderer* renderer ) : QDashStroker( nullptr ) , m_renderer( renderer ) { setDashOffset( renderer->metrics().offset() ); setDashPattern( renderer->metrics().pattern() ); m_elements.reserve( 2 ); } void renderDashes( qreal x1, qreal y1, qreal x2, qreal y2 ) { if ( ( x1 == x2 ) && ( y1 == y2 ) ) return; setMoveToHook( moveTo ); setLineToHook( lineTo ); begin( this ); m_elements.add( { QPainterPath::MoveToElement, x1, y1 } ); m_elements.add( { QPainterPath::LineToElement, x2, y2 } ); processCurrentSubpath(); end(); } qsizetype dashCount( qreal x1, qreal y1, qreal x2, qreal y2 ) { if ( ( x1 == x2 ) && ( y1 == y2 ) ) return 0; /* There should be a faster way to calculate the number of points. TODO ... */ setMoveToHook( countMoveTo ); setLineToHook( countLineTo ); 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: static void moveTo( qfixed x, qfixed y, void* data ) { auto stroker = reinterpret_cast< DashStroker* >( data ); stroker->m_x = x; stroker->m_y = y; } static void lineTo( qfixed x, qfixed y, void* data ) { auto stroker = reinterpret_cast< DashStroker* >( data ); stroker->m_renderer->renderDash( stroker->m_x, stroker->m_y, x, y ); } static void countMoveTo( qfixed, qfixed, void* ) { } static void countLineTo( qfixed, qfixed, void* data ) { auto stroker = reinterpret_cast< DashStroker* >( data ); stroker->m_count++; } QskStippledLineRenderer* m_renderer; qsizetype m_count = 0; qreal m_x, m_y; }; } QskStippledLineRenderer::QskStippledLineRenderer( const QskStippleMetrics& metrics ) : m_metrics( metrics ) { } QskStippledLineRenderer::~QskStippledLineRenderer() { } qsizetype QskStippledLineRenderer::dashCount( const QPointF& p1, const QPointF& p2 ) const { return dashCount( p1.x(), p1.y(), p2.x(), p2.y() ); } qsizetype QskStippledLineRenderer::dashCount( const QLineF& line ) const { return dashCount( line.x1(), line.y1(), line.x2(), line.y2() ); } qsizetype QskStippledLineRenderer::dashCount( qreal x1, qreal y1, qreal x2, qreal y2 ) const { auto that = const_cast< QskStippledLineRenderer* >( this ); return DashStroker( that ).dashCount( x1, y1, x2, y2 ); } void QskStippledLineRenderer::renderLine( const QPointF& p1, const QPointF& p2 ) { renderLine( p1.x(), p1.y(), p2.x(), p2.y() ); } void QskStippledLineRenderer::renderLine( const QLineF& line ) { renderLine( line.x1(), line.y1(), line.x2(), line.y2() ); } void QskStippledLineRenderer::renderLine( qreal x1, qreal y1, qreal x2, qreal y2 ) { DashStroker( this ).renderDashes( x1, y1, x2, y2 ); } void QskStippledLineRenderer::renderDash( qreal, qreal, qreal, qreal ) { // nop }