QskArcMetrics::isProprtional added

This commit is contained in:
Uwe Rathmann 2024-05-21 17:19:24 +02:00
parent 16c9ea2161
commit a327084c3f
4 changed files with 67 additions and 29 deletions

View File

@ -27,7 +27,7 @@ CircularChart::CircularChart( QQuickItem* parentItem )
setGradientHint( Panel, QskGradient() );
setBoxBorderMetricsHint( Panel, 0 );
setArcMetricsHint( Arc, { 90.0, -360.0, 100.0, Qt::RelativeSize } );
setArcMetricsHint( Arc, { 90.0, -360.0, 100.0, Qt::RelativeSize, true } );
setGradientHint( Arc, QskRgb::toTransparent( QskRgb::LightGray, 100 ) );
setColor( Arc | QskAspect::Border, QskRgb::LightGray );

View File

@ -334,8 +334,7 @@ QSGNode* CircularChartSkinlet::updateSampleNode( const QskSkinnable* skinnable,
return nullptr;
}
QSGNode* CircularChartSkinlet::updateArcSegmentNode(
const QskSkinnable* skinnable,
QSGNode* CircularChartSkinlet::updateArcSegmentNode( const QskSkinnable* skinnable,
QSGNode* node, qreal borderWidth, const QColor& borderColor,
const QskGradient& gradient, const QskArcMetrics& metrics ) const
{

View File

@ -48,7 +48,12 @@ void QskArcMetrics::setSpanAngle( qreal spanAngle ) noexcept
void QskArcMetrics::setSizeMode( Qt::SizeMode sizeMode ) noexcept
{
m_sizeMode = sizeMode;
m_relativeSize = ( sizeMode == Qt::RelativeSize );
}
void QskArcMetrics::setProportional( bool on ) noexcept
{
m_proportional = on;
}
bool QskArcMetrics::isClosed() const
@ -79,7 +84,7 @@ bool QskArcMetrics::containsAngle( qreal angle ) const
QskArcMetrics QskArcMetrics::interpolated(
const QskArcMetrics& to, qreal ratio ) const noexcept
{
if ( ( *this == to ) || ( m_sizeMode != to.m_sizeMode ) )
if ( ( *this == to ) || ( m_relativeSize != to.m_relativeSize ) )
return to;
const qreal thickness = qskInterpolated( m_thickness, to.m_thickness, ratio );
@ -87,7 +92,7 @@ QskArcMetrics QskArcMetrics::interpolated(
const qreal s1 = qskInterpolated( m_startAngle, to.m_startAngle, ratio );
const qreal s2 = qskInterpolated( endAngle(), to.endAngle(), ratio );
return QskArcMetrics( s1, s2 - s1, thickness, m_sizeMode );
return QskArcMetrics( s1, s2 - s1, thickness, sizeMode(), to.isProportional() );
}
QVariant QskArcMetrics::interpolate(
@ -110,26 +115,37 @@ QskArcMetrics QskArcMetrics::toAbsolute( qreal radiusX, qreal radiusY ) const no
QskArcMetrics QskArcMetrics::toAbsolute( qreal radius ) const noexcept
{
if ( m_sizeMode != Qt::RelativeSize )
if ( !m_relativeSize )
return *this;
const qreal t = qskEffectiveThickness( radius, m_thickness );
return QskArcMetrics( m_startAngle, m_spanAngle, t, Qt::AbsoluteSize );
return QskArcMetrics( m_startAngle, m_spanAngle, t,
Qt::AbsoluteSize, m_proportional );
}
QPainterPath QskArcMetrics::painterPath( const QRectF& ellipseRect ) const
{
const auto sz = qMin( ellipseRect.width(), ellipseRect.height() );
qreal t = m_thickness;
if ( m_sizeMode == Qt::RelativeSize )
if ( m_relativeSize )
{
const auto sz = qMin( ellipseRect.width(), ellipseRect.height() );
t = qskEffectiveThickness( 0.5 * sz, t );
}
if ( t <= 0.0 || qFuzzyIsNull( m_spanAngle ) )
return QPainterPath();
const auto tx = t * ellipseRect.width() / sz;
const auto ty = t * ellipseRect.height() / sz;
auto tx = t;
auto ty = t;
if ( m_proportional )
{
const auto sz = qMin( ellipseRect.width(), ellipseRect.height() );
tx *= ellipseRect.width() / sz;
ty *= ellipseRect.height() / sz;
}
const auto innerRect = ellipseRect.adjusted( tx, ty, -tx, -ty );
@ -211,9 +227,9 @@ QskHashValue QskArcMetrics::hash( QskHashValue seed ) const noexcept
auto hash = qHash( m_thickness, seed );
hash = qHash( m_startAngle, hash );
hash = qHash( m_spanAngle, hash );
hash = qHash( m_relativeSize, hash );
const int mode = m_sizeMode;
return qHashBits( &mode, sizeof( mode ), hash );
return qHash( m_proportional, hash );
}
#ifndef QT_NO_DEBUG_STREAM
@ -226,7 +242,8 @@ QDebug operator<<( QDebug debug, const QskArcMetrics& metrics )
debug.nospace();
debug << "QskArcMetrics" << '(';
debug << metrics.thickness() << ',' << metrics.sizeMode();
debug << metrics.thickness() << ',' << metrics.sizeMode() << ','
<< metrics.isProportional();
debug << ",[" << metrics.startAngle() << ',' << metrics.spanAngle() << ']';
debug << ')';

View File

@ -22,15 +22,16 @@ class QSK_EXPORT QskArcMetrics
Q_PROPERTY( qreal thickness READ thickness WRITE setThickness )
Q_PROPERTY( Qt::SizeMode sizeMode READ sizeMode WRITE setSizeMode )
Q_PROPERTY( bool proportional READ isProportional WRITE setProportional )
public:
constexpr QskArcMetrics() noexcept = default;
constexpr QskArcMetrics( qreal thickness,
Qt::SizeMode = Qt::AbsoluteSize ) noexcept;
Qt::SizeMode = Qt::AbsoluteSize, bool proportional = false ) noexcept;
constexpr QskArcMetrics( qreal startAngle, qreal spanAngle,
qreal thickness, Qt::SizeMode = Qt::AbsoluteSize ) noexcept;
constexpr QskArcMetrics( qreal startAngle, qreal spanAngle, qreal thickness,
Qt::SizeMode = Qt::AbsoluteSize, bool proportional = false ) noexcept;
bool operator==( const QskArcMetrics& ) const noexcept;
bool operator!=( const QskArcMetrics& ) const noexcept;
@ -52,6 +53,19 @@ class QSK_EXPORT QskArcMetrics
void setThickness( qreal ) noexcept;
constexpr qreal thickness() const noexcept;
/*
A proportional arc scales the thickness of the arc according to the
aspect ratio of the target rectangle. F.e when having a 20x10 rectangle
the thickness in west/east direction is doubled, while for a
10x20 rectangle the thickness in north/south direction is doubled.
This matches the lines that result from a filling with a conic gradient.
A non proportional arc will have a fixed thickness regardless of
the aspect ratio.
*/
void setProportional( bool ) noexcept;
constexpr bool isProportional() const noexcept;
void setSizeMode( Qt::SizeMode ) noexcept;
constexpr Qt::SizeMode sizeMode() const noexcept;
@ -76,32 +90,35 @@ class QSK_EXPORT QskArcMetrics
qreal m_spanAngle = 0.0;
qreal m_thickness = 0.0;
Qt::SizeMode m_sizeMode = Qt::AbsoluteSize;
bool m_relativeSize = false;
bool m_proportional = false;
};
inline constexpr QskArcMetrics::QskArcMetrics(
qreal thickness, Qt::SizeMode sizeMode ) noexcept
: QskArcMetrics( 0.0, 360.0, thickness, sizeMode )
qreal thickness, Qt::SizeMode sizeMode, bool proportional ) noexcept
: QskArcMetrics( 0.0, 360.0, thickness, sizeMode, proportional )
{
}
inline constexpr QskArcMetrics::QskArcMetrics(
qreal startAngle, qreal spanAngle,
qreal thickness, Qt::SizeMode sizeMode ) noexcept
inline constexpr QskArcMetrics::QskArcMetrics( qreal startAngle, qreal spanAngle,
qreal thickness, Qt::SizeMode sizeMode, bool proportional ) noexcept
: m_startAngle( startAngle )
, m_spanAngle( spanAngle )
, m_thickness( thickness )
, m_sizeMode( sizeMode )
, m_relativeSize( sizeMode == Qt::RelativeSize )
, m_proportional( proportional )
{
}
inline bool QskArcMetrics::operator==(
const QskArcMetrics& other ) const noexcept
{
return ( qskFuzzyCompare( m_thickness, other.m_thickness )
return qskFuzzyCompare( m_thickness, other.m_thickness )
&& qskFuzzyCompare( m_startAngle, other.m_startAngle )
&& qskFuzzyCompare( m_spanAngle, other.m_spanAngle )
&& m_sizeMode == other.m_sizeMode );
&& ( m_relativeSize == other.m_relativeSize )
&& ( m_proportional == other.m_proportional );
}
inline bool QskArcMetrics::operator!=(
@ -142,7 +159,12 @@ inline constexpr qreal QskArcMetrics::angleAtRatio( qreal ratio ) const noexcept
inline constexpr Qt::SizeMode QskArcMetrics::sizeMode() const noexcept
{
return m_sizeMode;
return m_relativeSize ? Qt::RelativeSize : Qt::AbsoluteSize;
}
inline constexpr bool QskArcMetrics::isProportional() const noexcept
{
return m_proportional;
}
#ifndef QT_NO_DEBUG_STREAM