implementation of QskStippleMetrics completed
This commit is contained in:
parent
5d3cba5650
commit
d84e75a3d1
@ -116,6 +116,7 @@ list(APPEND HEADERS
|
||||
nodes/QskScaleRenderer.h
|
||||
nodes/QskSGNode.h
|
||||
nodes/QskStrokeNode.h
|
||||
nodes/QskStippledLineRenderer.h
|
||||
nodes/QskShapeNode.h
|
||||
nodes/QskGradientMaterial.h
|
||||
nodes/QskTextNode.h
|
||||
@ -146,6 +147,7 @@ list(APPEND SOURCES
|
||||
nodes/QskScaleRenderer.cpp
|
||||
nodes/QskSGNode.cpp
|
||||
nodes/QskStrokeNode.cpp
|
||||
nodes/QskStippledLineRenderer.cpp
|
||||
nodes/QskShapeNode.cpp
|
||||
nodes/QskGradientMaterial.cpp
|
||||
nodes/QskTextNode.cpp
|
||||
|
@ -16,11 +16,19 @@ static void qskRegisterStippleMetrics()
|
||||
#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
|
||||
QMetaType::registerEqualsComparator< QskStippleMetrics >();
|
||||
#endif
|
||||
|
||||
QMetaType::registerConverter< QPen, QskStippleMetrics >(
|
||||
[]( const QPen& pen ) { return QskStippleMetrics( pen ); } );
|
||||
|
||||
QMetaType::registerConverter< Qt::PenStyle, QskStippleMetrics >(
|
||||
[]( Qt::PenStyle style ) { return QskStippleMetrics( style ); } );
|
||||
}
|
||||
|
||||
static inline QVector< qreal > qskDashPattern( const Qt::PenStyle& style )
|
||||
Q_CONSTRUCTOR_FUNCTION( qskRegisterStippleMetrics )
|
||||
|
||||
QVector< qreal > qskDashPattern( Qt::PenStyle style )
|
||||
{
|
||||
static QVector< qreal > pattern[] =
|
||||
static const QVector< qreal > pattern[] =
|
||||
{
|
||||
{}, { 1 }, { 4, 2 }, { 1, 2 },
|
||||
{ 4, 2, 1, 2 }, { 4, 2, 1, 2, 1, 2 }, {}
|
||||
@ -29,7 +37,22 @@ static inline QVector< qreal > qskDashPattern( const Qt::PenStyle& style )
|
||||
return pattern[ style ];
|
||||
}
|
||||
|
||||
Q_CONSTRUCTOR_FUNCTION( qskRegisterStippleMetrics )
|
||||
static inline qreal qskInterpolated( qreal from, qreal to, qreal ratio )
|
||||
{
|
||||
return from + ( to - from ) * ratio;
|
||||
}
|
||||
|
||||
static inline QVector< qreal > qskInterpolatedSpaces(
|
||||
const QVector< qreal >& pattern, qreal progress )
|
||||
{
|
||||
QVector< qreal > interpolated;
|
||||
interpolated.reserve( pattern.count() );
|
||||
|
||||
for ( int i = 1; i < pattern.count(); i += 2 )
|
||||
interpolated[i] = progress * pattern[i];
|
||||
|
||||
return interpolated;
|
||||
}
|
||||
|
||||
QskStippleMetrics::QskStippleMetrics( Qt::PenStyle penStyle )
|
||||
: m_pattern( qskDashPattern( penStyle ) )
|
||||
@ -56,6 +79,47 @@ void QskStippleMetrics::setOffset( qreal offset ) noexcept
|
||||
m_offset = offset;
|
||||
}
|
||||
|
||||
QskStippleMetrics QskStippleMetrics::interpolated(
|
||||
const QskStippleMetrics& to, qreal progress ) const
|
||||
{
|
||||
if ( *this == to )
|
||||
return to;
|
||||
|
||||
const auto offset = qskInterpolated( m_offset, to.m_offset, progress );
|
||||
|
||||
QVector< qreal > pattern;
|
||||
|
||||
if ( isSolid() )
|
||||
{
|
||||
pattern = qskInterpolatedSpaces( to.m_pattern, progress );
|
||||
}
|
||||
else if ( to.isSolid() )
|
||||
{
|
||||
pattern = qskInterpolatedSpaces( m_pattern, 1.0 - progress );
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto count = qMax( m_pattern.count(), to.m_pattern.count() );
|
||||
pattern.reserve( count );
|
||||
|
||||
for ( int i = 0; i < count; i++ )
|
||||
{
|
||||
const auto v1 = m_pattern.value( i, 0.0 );
|
||||
const auto v2 = to.m_pattern.value( i, 0.0 );
|
||||
|
||||
pattern += qskInterpolated( v1, v2, progress );
|
||||
}
|
||||
}
|
||||
|
||||
return QskStippleMetrics( pattern, offset );
|
||||
}
|
||||
|
||||
QVariant QskStippleMetrics::interpolate(
|
||||
const QskStippleMetrics& from, const QskStippleMetrics& to, qreal progress )
|
||||
{
|
||||
return QVariant::fromValue( from.interpolated( to, progress ) );
|
||||
}
|
||||
|
||||
QskHashValue QskStippleMetrics::hash( QskHashValue seed ) const noexcept
|
||||
{
|
||||
auto hash = qHash( m_offset, seed );
|
||||
|
@ -38,6 +38,12 @@ class QSK_EXPORT QskStippleMetrics
|
||||
void setPattern( const QVector< qreal >& );
|
||||
QVector< qreal > pattern() const;
|
||||
|
||||
QskStippleMetrics interpolated(
|
||||
const QskStippleMetrics&, qreal value ) const;
|
||||
|
||||
static QVariant interpolate( const QskStippleMetrics&,
|
||||
const QskStippleMetrics&, qreal progress );
|
||||
|
||||
QskHashValue hash( QskHashValue seed = 0 ) const noexcept;
|
||||
|
||||
private:
|
||||
@ -85,6 +91,8 @@ inline bool QskStippleMetrics::isSolid() const noexcept
|
||||
return m_pattern.count() == 1;
|
||||
}
|
||||
|
||||
QSK_EXPORT QVector< qreal > qskDashPattern( Qt::PenStyle );
|
||||
|
||||
#ifndef QT_NO_DEBUG_STREAM
|
||||
|
||||
class QDebug;
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "QskBoxBorderMetrics.h"
|
||||
#include "QskBoxBorderColors.h"
|
||||
#include "QskShadowMetrics.h"
|
||||
#include "QskStippleMetrics.h"
|
||||
#include "QskGraphic.h"
|
||||
|
||||
namespace
|
||||
@ -130,6 +131,11 @@ namespace
|
||||
{
|
||||
return aspect | QskAspect::Symbol;
|
||||
}
|
||||
|
||||
inline QskAspect aspectStipple( QskAspect aspect )
|
||||
{
|
||||
return aspect | QskAspect::Style;
|
||||
}
|
||||
}
|
||||
|
||||
QskSkinHintTableEditor::QskSkinHintTableEditor( QskSkinHintTable* table )
|
||||
@ -583,8 +589,8 @@ void QskSkinHintTableEditor::setArcMetrics( QskAspect aspect,
|
||||
setMetricHint( aspectShape( aspect ), arcMetrics, combination );
|
||||
}
|
||||
|
||||
bool QskSkinHintTableEditor::removeArcMetrics( QskAspect aspect,
|
||||
QskStateCombination combination )
|
||||
bool QskSkinHintTableEditor::removeArcMetrics(
|
||||
QskAspect aspect, QskStateCombination combination )
|
||||
{
|
||||
return removeMetricHint( aspectShape( aspect ), combination );
|
||||
}
|
||||
@ -594,6 +600,35 @@ QskArcMetrics QskSkinHintTableEditor::arcMetrics( QskAspect aspect ) const
|
||||
return metricHint< QskArcMetrics >( aspectShape( aspect ) );
|
||||
}
|
||||
|
||||
void QskSkinHintTableEditor::setStippleMetrics( QskAspect aspect,
|
||||
Qt::PenStyle penStyle, QskStateCombination combination )
|
||||
{
|
||||
setStippleMetrics( aspect, QskStippleMetrics( penStyle ), combination );
|
||||
}
|
||||
|
||||
void QskSkinHintTableEditor::setStippleMetrics( QskAspect aspect,
|
||||
const QVector< qreal >& dashPattern, QskStateCombination combination )
|
||||
{
|
||||
setStippleMetrics( aspect, QskStippleMetrics( dashPattern ), combination );
|
||||
}
|
||||
|
||||
void QskSkinHintTableEditor::setStippleMetrics( QskAspect aspect,
|
||||
const QskStippleMetrics& metrics, QskStateCombination combination )
|
||||
{
|
||||
setMetricHint( aspectStipple( aspect ), metrics, combination );
|
||||
}
|
||||
|
||||
bool QskSkinHintTableEditor::removeStippleMetrics(
|
||||
QskAspect aspect, QskStateCombination combination )
|
||||
{
|
||||
return removeMetricHint( aspectStipple( aspect ), combination );
|
||||
}
|
||||
|
||||
QskStippleMetrics QskSkinHintTableEditor::stippleMetrics( QskAspect aspect ) const
|
||||
{
|
||||
return metricHint< QskStippleMetrics >( aspectStipple( aspect ) );
|
||||
}
|
||||
|
||||
void QskSkinHintTableEditor::setTextOptions( QskAspect aspect,
|
||||
Qt::TextElideMode elideMode, QskTextOptions::WrapMode wrapMode,
|
||||
QskStateCombination combination )
|
||||
|
@ -14,6 +14,7 @@
|
||||
|
||||
#include <qcolor.h>
|
||||
#include <qvariant.h>
|
||||
#include <qvector.h>
|
||||
|
||||
class QskArcMetrics;
|
||||
class QskMargins;
|
||||
@ -22,6 +23,7 @@ class QskBoxShapeMetrics;
|
||||
class QskBoxBorderMetrics;
|
||||
class QskBoxBorderColors;
|
||||
class QskShadowMetrics;
|
||||
class QskStippleMetrics;
|
||||
class QskGraphic;
|
||||
|
||||
class QSK_EXPORT QskSkinHintTableEditor
|
||||
@ -265,6 +267,21 @@ class QSK_EXPORT QskSkinHintTableEditor
|
||||
|
||||
QskArcMetrics arcMetrics( QskAspect ) const;
|
||||
|
||||
// lines
|
||||
|
||||
void setStippleMetrics( QskAspect, Qt::PenStyle,
|
||||
QskStateCombination = QskStateCombination() );
|
||||
|
||||
void setStippleMetrics( QskAspect, const QVector< qreal >&,
|
||||
QskStateCombination = QskStateCombination() );
|
||||
|
||||
void setStippleMetrics( QskAspect, const QskStippleMetrics&,
|
||||
QskStateCombination = QskStateCombination() );
|
||||
|
||||
bool removeStippleMetrics( QskAspect, QskStateCombination = QskStateCombination() );
|
||||
|
||||
QskStippleMetrics stippleMetrics( QskAspect ) const;
|
||||
|
||||
// text options flag
|
||||
|
||||
void setTextOptions( QskAspect,
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "QskBoxBorderMetrics.h"
|
||||
#include "QskBoxBorderColors.h"
|
||||
#include "QskShadowMetrics.h"
|
||||
#include "QskStippleMetrics.h"
|
||||
#include "QskBoxHints.h"
|
||||
#include "QskGradient.h"
|
||||
#include "QskTextOptions.h"
|
||||
@ -638,6 +639,24 @@ QskArcMetrics QskSkinnable::arcMetricsHint(
|
||||
this, aspect | QskAspect::Shape, status );
|
||||
}
|
||||
|
||||
bool QskSkinnable::setStippleMetricsHint(
|
||||
QskAspect aspect, const QskStippleMetrics& metrics )
|
||||
{
|
||||
return qskSetMetric( this, aspect | QskAspect::Style, metrics );
|
||||
}
|
||||
|
||||
bool QskSkinnable::resetStippleMetricsHint( QskAspect aspect )
|
||||
{
|
||||
return resetMetric( aspect | QskAspect::Style );
|
||||
}
|
||||
|
||||
QskStippleMetrics QskSkinnable::stippleMetricsHint(
|
||||
QskAspect aspect, QskSkinHintStatus* status ) const
|
||||
{
|
||||
return qskMetric< QskStippleMetrics >(
|
||||
this, aspect | QskAspect::Style, status );
|
||||
}
|
||||
|
||||
bool QskSkinnable::setSpacingHint( const QskAspect aspect, qreal spacing )
|
||||
{
|
||||
return qskSetMetric( this, aspect | QskAspect::Spacing, spacing );
|
||||
|
@ -30,6 +30,7 @@ class QskBoxShapeMetrics;
|
||||
class QskBoxBorderMetrics;
|
||||
class QskBoxBorderColors;
|
||||
class QskShadowMetrics;
|
||||
class QskStippleMetrics;
|
||||
class QskTextOptions;
|
||||
class QskBoxHints;
|
||||
class QskGradient;
|
||||
@ -228,6 +229,10 @@ class QSK_EXPORT QskSkinnable
|
||||
bool resetArcMetricsHint( QskAspect );
|
||||
QskArcMetrics arcMetricsHint( QskAspect, QskSkinHintStatus* = nullptr ) const;
|
||||
|
||||
bool setStippleMetricsHint( QskAspect, const QskStippleMetrics& );
|
||||
bool resetStippleMetricsHint( QskAspect );
|
||||
QskStippleMetrics stippleMetricsHint( QskAspect, QskSkinHintStatus* = nullptr ) const;
|
||||
|
||||
bool setSpacingHint( QskAspect, qreal );
|
||||
bool resetSpacingHint( QskAspect );
|
||||
qreal spacingHint( QskAspect, QskSkinHintStatus* = nullptr ) const;
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "QskBoxBorderMetrics.h"
|
||||
#include "QskBoxShapeMetrics.h"
|
||||
#include "QskShadowMetrics.h"
|
||||
#include "QskStippleMetrics.h"
|
||||
#include "QskColorFilter.h"
|
||||
#include "QskGradient.h"
|
||||
#include "QskMargins.h"
|
||||
@ -46,6 +47,7 @@ static void qskRegisterInterpolator()
|
||||
qRegisterAnimationInterpolator< QskBoxBorderColors >( QskBoxBorderColors::interpolate );
|
||||
qRegisterAnimationInterpolator< QskTextColors >( QskTextColors::interpolate );
|
||||
qRegisterAnimationInterpolator< QskShadowMetrics >( QskShadowMetrics::interpolate );
|
||||
qRegisterAnimationInterpolator< QskStippleMetrics >( QskStippleMetrics::interpolate );
|
||||
qRegisterAnimationInterpolator< QskArcMetrics >( QskArcMetrics::interpolate );
|
||||
}
|
||||
|
||||
|
154
src/nodes/QskStippledLineRenderer.cpp
Normal file
154
src/nodes/QskStippledLineRenderer.cpp
Normal file
@ -0,0 +1,154 @@
|
||||
/******************************************************************************
|
||||
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
||||
* 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
|
||||
}
|
47
src/nodes/QskStippledLineRenderer.h
Normal file
47
src/nodes/QskStippledLineRenderer.h
Normal file
@ -0,0 +1,47 @@
|
||||
/******************************************************************************
|
||||
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef QSK_STIPPLED_LINE_RENDERER_H
|
||||
#define QSK_STIPPLED_LINE_RENDERER_H
|
||||
|
||||
#include "QskStippleMetrics.h"
|
||||
|
||||
class QLineF;
|
||||
class QPointF;
|
||||
|
||||
/*
|
||||
A wrapper for the non public QDashStroker class, tailored for
|
||||
splitting lines into dashes/dots. It is faster than QPainterPathStroker
|
||||
( no QPainterPath involved ), but supports simple lines only.
|
||||
*/
|
||||
class QskStippledLineRenderer
|
||||
{
|
||||
public:
|
||||
QskStippledLineRenderer( const QskStippleMetrics& );
|
||||
virtual ~QskStippledLineRenderer();
|
||||
|
||||
qsizetype dashCount( qreal x1, qreal y1, qreal x2, qreal y2 ) const;
|
||||
qsizetype dashCount( const QPointF&, const QPointF& ) const;
|
||||
qsizetype dashCount( const QLineF& ) const;
|
||||
|
||||
void renderLine( qreal x1, qreal y1, qreal x2, qreal y2 );
|
||||
void renderLine( const QPointF&, const QPointF& );
|
||||
void renderLine( const QLineF& );
|
||||
|
||||
const QskStippleMetrics& metrics() const;
|
||||
|
||||
// nop: to be overloaded
|
||||
virtual void renderDash( qreal x1, qreal y1, qreal x2, qreal y2 );
|
||||
|
||||
private:
|
||||
const QskStippleMetrics m_metrics;
|
||||
};
|
||||
|
||||
inline const QskStippleMetrics& QskStippledLineRenderer::metrics() const
|
||||
{
|
||||
return m_metrics;
|
||||
}
|
||||
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user