155 lines
4.1 KiB
C++
155 lines
4.1 KiB
C++
/******************************************************************************
|
|
* QSkinny - Copyright (C) The authors
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*****************************************************************************/
|
|
|
|
#include "QskStippledLineRenderer.h"
|
|
|
|
QSK_QT_PRIVATE_BEGIN
|
|
#include <private/qstroker_p.h>
|
|
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
|
|
}
|