qskinny/src/common/QskStippleMetrics.cpp

148 lines
3.6 KiB
C++

/******************************************************************************
* QSkinny - Copyright (C) 2016 Uwe Rathmann
* SPDX-License-Identifier: BSD-3-Clause
*****************************************************************************/
#include "QskStippleMetrics.h"
#include <qhashfunctions.h>
#include <qpen.h>
#include <qvariant.h>
static void qskRegisterStippleMetrics()
{
qRegisterMetaType< QskStippleMetrics >();
#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 ); } );
}
Q_CONSTRUCTOR_FUNCTION( qskRegisterStippleMetrics )
QVector< qreal > qskDashPattern( Qt::PenStyle style )
{
static const QVector< qreal > pattern[] =
{
{}, { 1 }, { 4, 2 }, { 1, 2 },
{ 4, 2, 1, 2 }, { 4, 2, 1, 2, 1, 2 }, {}
};
return pattern[ style ];
}
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 ) )
{
}
QskStippleMetrics::QskStippleMetrics( const QPen& pen )
: QskStippleMetrics( pen.style() )
{
if ( pen.style() == Qt::CustomDashLine )
{
m_offset = pen.dashOffset();
m_pattern = pen.dashPattern();
}
}
void QskStippleMetrics::setPattern( const QVector< qreal >& pattern )
{
m_pattern = pattern;
}
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 );
return qHash( m_pattern, hash );
}
#ifndef QT_NO_DEBUG_STREAM
#include <qdebug.h>
QDebug operator<<( QDebug debug, const QskStippleMetrics& metrics )
{
QDebugStateSaver saver( debug );
debug.nospace();
debug << "QskStippleMetrics" << '(';
debug << metrics.offset() << ',' << metrics.pattern();
debug << ')';
return debug;
}
#endif
#include "moc_QskStippleMetrics.cpp"