QskGraduationMetrics introduced

This commit is contained in:
Uwe Rathmann 2023-11-25 17:04:06 +01:00
parent 534ffb41e1
commit 24949074d4
8 changed files with 245 additions and 77 deletions

View File

@ -15,6 +15,7 @@ list(APPEND HEADERS
common/QskGradient.h
common/QskGradientDirection.h
common/QskGradientStop.h
common/QskGraduationMetrics.h
common/QskHctColor.h
common/QskIntervalF.h
common/QskLabelData.h
@ -48,6 +49,7 @@ list(APPEND SOURCES
common/QskGradient.cpp
common/QskGradientDirection.cpp
common/QskGradientStop.cpp
common/QskGraduationMetrics.cpp
common/QskHctColor.cpp
common/QskIntervalF.cpp
common/QskLabelData.cpp

View File

@ -72,7 +72,9 @@ class QSK_EXPORT QskAspect
Shadow,
Shape,
Border
Border,
Graduation
};
Q_ENUM( Primitive )

View File

@ -0,0 +1,58 @@
#include "QskGraduationMetrics.h"
#include <qvariant.h>
static void qskRegisterGraduationMetrics()
{
qRegisterMetaType< QskGraduationMetrics >();
#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
QMetaType::registerEqualsComparator< QskGraduationMetrics >();
#endif
}
Q_CONSTRUCTOR_FUNCTION( qskRegisterGraduationMetrics )
static inline qreal qskInterpolated( qreal from, qreal to, qreal ratio )
{
return from + ( to - from ) * ratio;
}
QskGraduationMetrics QskGraduationMetrics::interpolated(
const QskGraduationMetrics& to, const qreal ratio ) const noexcept
{
if ( ( *this == to ) )
return to;
return { qskInterpolated( m_tickLengths[0], to.m_tickLengths[0], ratio ),
qskInterpolated( m_tickLengths[1], to.m_tickLengths[1], ratio ),
qskInterpolated( m_tickLengths[2], to.m_tickLengths[2], ratio ) };
}
QVariant QskGraduationMetrics::interpolate(
const QskGraduationMetrics& from, const QskGraduationMetrics& to, const qreal progress )
{
return QVariant::fromValue( from.interpolated( to, progress ) );
}
#ifndef QT_NO_DEBUG_STREAM
#include <qdebug.h>
QDebug operator<<( QDebug debug, const QskGraduationMetrics& metrics )
{
const char s[] = ", ";
QDebugStateSaver saver( debug );
debug.nospace();
debug << "Graduation";
debug << '(';
debug << metrics.minorTickLength() << s << metrics.mediumTickLength()
<< s << metrics.majorTickLength();
debug << ')';
return debug;
}
#endif

View File

@ -0,0 +1,146 @@
/******************************************************************************
* QSkinny - Copyright (C) 2016 Uwe Rathmann
* SPDX-License-Identifier: BSD-3-Clause
*****************************************************************************/
#ifndef QSK_GRADUATION_METRICS_H
#define QSK_GRADUATION_METRICS_H
#include "QskScaleTickmarks.h"
#include "QskFunctions.h"
#include <algorithm>
#include <qmetatype.h>
class QSK_EXPORT QskGraduationMetrics
{
Q_GADGET
Q_PROPERTY( qreal majorTickLength READ majorTickLength WRITE setMajorTickLength )
Q_PROPERTY( qreal mediumTickLength READ mediumTickLength WRITE setMediumTickLength )
Q_PROPERTY( qreal minorTickLength READ minorTickLength WRITE setMinorTickLength )
public:
using TickType = QskScaleTickmarks::TickType;
constexpr QskGraduationMetrics() noexcept = default;
constexpr QskGraduationMetrics( qreal minorTickLength,
qreal mediumTickLength, qreal majorTickLength ) noexcept;
constexpr QskGraduationMetrics( const QskGraduationMetrics& ) noexcept = default;
constexpr QskGraduationMetrics( QskGraduationMetrics&& ) noexcept = default;
constexpr QskGraduationMetrics& operator=( const QskGraduationMetrics& ) noexcept = default;
constexpr QskGraduationMetrics& operator=( QskGraduationMetrics&& ) noexcept = default;
[[nodiscard]] constexpr bool operator==( const QskGraduationMetrics& rhs ) const noexcept;
[[nodiscard]] constexpr bool operator!=( const QskGraduationMetrics& rhs ) const noexcept;
constexpr void setTickLength( TickType, qreal ) noexcept;
[[nodiscard]] constexpr qreal tickLength( TickType ) const noexcept;
constexpr void setMinorTickLength( qreal ) noexcept;
[[nodiscard]] constexpr qreal minorTickLength() const noexcept;
constexpr void setMediumTickLength( qreal ) noexcept;
[[nodiscard]] constexpr qreal mediumTickLength() const noexcept;
constexpr void setMajorTickLength( qreal ) noexcept;
[[nodiscard]] constexpr qreal majorTickLength() const noexcept;
[[nodiscard]] QskGraduationMetrics interpolated(
const QskGraduationMetrics&, qreal progress ) const noexcept;
[[nodiscard]] static QVariant interpolate(
const QskGraduationMetrics&, const QskGraduationMetrics&, qreal progress );
[[nodiscard]] QskHashValue hash( QskHashValue seed = 0 ) const noexcept;
private:
static inline constexpr qreal constrainedLength( qreal length )
{
return std::max( 0.0, length );
}
qreal m_tickLengths[3] = {};
};
inline constexpr QskGraduationMetrics::QskGraduationMetrics(
qreal minorTickLength, qreal mediumTickLength, qreal majorTickLength ) noexcept
: m_tickLengths{ constrainedLength( minorTickLength ),
constrainedLength( mediumTickLength ), constrainedLength( majorTickLength ) }
{
}
inline constexpr qreal QskGraduationMetrics::majorTickLength() const noexcept
{
return tickLength( QskScaleTickmarks::MajorTick );
}
inline constexpr qreal QskGraduationMetrics::mediumTickLength() const noexcept
{
return tickLength( QskScaleTickmarks::MediumTick );
}
inline constexpr qreal QskGraduationMetrics::minorTickLength() const noexcept
{
return tickLength( QskScaleTickmarks::MinorTick );
}
inline constexpr void QskGraduationMetrics::setMajorTickLength( qreal length ) noexcept
{
setTickLength( QskScaleTickmarks::MajorTick, length );
}
inline constexpr void QskGraduationMetrics::setMediumTickLength( qreal length ) noexcept
{
setTickLength( QskScaleTickmarks::MediumTick, length );
}
inline constexpr void QskGraduationMetrics::setMinorTickLength( qreal length ) noexcept
{
setTickLength( QskScaleTickmarks::MinorTick, length );
}
inline constexpr bool QskGraduationMetrics::operator==(
const QskGraduationMetrics& other ) const noexcept
{
return qskFuzzyCompare( m_tickLengths[0], other.m_tickLengths[0] ) &&
qskFuzzyCompare( m_tickLengths[1], other.m_tickLengths[1] ) &&
qskFuzzyCompare( m_tickLengths[2], other.m_tickLengths[2] );
}
inline constexpr bool QskGraduationMetrics::operator!=(
const QskGraduationMetrics& rhs ) const noexcept
{
return !( *this == rhs );
}
inline constexpr qreal QskGraduationMetrics::tickLength(
const QskScaleTickmarks::TickType type ) const noexcept
{
return m_tickLengths[ type ];
}
inline constexpr void QskGraduationMetrics::setTickLength(
TickType type, qreal length ) noexcept
{
m_tickLengths[ type ] = constrainedLength( length );
}
inline QskHashValue QskGraduationMetrics::hash( const QskHashValue seed ) const noexcept
{
auto hash = qHash( m_tickLengths[0], seed );
hash = qHash( m_tickLengths[1], hash );
hash = qHash( m_tickLengths[2], hash );
return hash;
}
#ifndef QT_NO_DEBUG_STREAM
class QDebug;
QSK_EXPORT QDebug operator<<( QDebug, const QskGraduationMetrics& );
#endif
Q_DECLARE_TYPEINFO( QskGraduationMetrics, Q_MOVABLE_TYPE );
Q_DECLARE_METATYPE( QskGraduationMetrics )
#endif

View File

@ -10,6 +10,7 @@
#include "QskBoxShapeMetrics.h"
#include "QskShadowMetrics.h"
#include "QskStippleMetrics.h"
#include "QskGraduationMetrics.h"
#include "QskColorFilter.h"
#include "QskGradient.h"
#include "QskMargins.h"
@ -49,6 +50,7 @@ static void qskRegisterInterpolator()
qRegisterAnimationInterpolator< QskShadowMetrics >( QskShadowMetrics::interpolate );
qRegisterAnimationInterpolator< QskStippleMetrics >( QskStippleMetrics::interpolate );
qRegisterAnimationInterpolator< QskArcMetrics >( QskArcMetrics::interpolate );
qRegisterAnimationInterpolator< QskGraduationMetrics >( QskGraduationMetrics::interpolate );
}
Q_CONSTRUCTOR_FUNCTION( qskRegisterInterpolator )

View File

@ -7,6 +7,7 @@
#include "QskScaleTickmarks.h"
#include "QskSkinlet.h"
#include "QskSGNode.h"
#include "QskGraduationMetrics.h"
#include "QskTickmarksNode.h"
#include "QskTextOptions.h"
#include "QskTextColors.h"
@ -230,7 +231,7 @@ QSGNode* QskScaleRenderer::updateTicksNode(
ticksNode->update( m_data->tickColor, rect, m_data->boundaries,
m_data->tickmarks, tickWidth, m_data->orientation,
m_data->alignment );
m_data->alignment, {});
return ticksNode;
}

View File

@ -1,48 +1,17 @@
/******************************************************************************
* QSkinny - Copyright (C) 2016 Uwe Rathmann
* SPDX-License-Identifier: BSD-3-Clause
*****************************************************************************/
#include "QskTickmarksNode.h"
#include "QskScaleTickmarks.h"
#include "QskGraduationMetrics.h"
#include <QSGFlatColorMaterial>
#include <QSGGeometryNode>
#include <QRectF>
QSK_QT_PRIVATE_BEGIN
#include <private/qsgnode_p.h>
QSK_QT_PRIVATE_END
static constexpr inline qreal qskTickFactor( QskScaleTickmarks::TickType type )
{
using TM = QskScaleTickmarks;
return type == TM::MinorTick ? 0.7 : ( type == TM::MediumTick ? 0.85 : 1.0 );
}
class QskTickmarksNodePrivate final : public QSGGeometryNodePrivate
{
public:
QskTickmarksNodePrivate()
: geometry( QSGGeometry::defaultAttributes_Point2D(), 0 )
{
geometry.setDrawingMode( QSGGeometry::DrawLines );
}
QSGGeometry geometry;
QSGFlatColorMaterial material;
QskIntervalF boundaries;
QskScaleTickmarks tickmarks;
QRectF rect;
int lineWidth = 0;
QskHashValue hash = 0;
};
#include <qrect.h>
#include <qhashfunctions.h>
QskTickmarksNode::QskTickmarksNode()
: QSGGeometryNode( *new QskTickmarksNodePrivate )
{
Q_D( QskTickmarksNode );
setGeometry( &d->geometry );
setMaterial( &d->material );
}
QskTickmarksNode::~QskTickmarksNode()
@ -52,27 +21,24 @@ QskTickmarksNode::~QskTickmarksNode()
void QskTickmarksNode::update(
const QColor& color, const QRectF& rect,
const QskIntervalF& boundaries, const QskScaleTickmarks& tickmarks,
int lineWidth, Qt::Orientation orientation, Qt::Alignment alignment )
int lineWidth, Qt::Orientation orientation, Qt::Alignment alignment,
const QskGraduationMetrics& graduationMetrics )
{
Q_D( QskTickmarksNode );
setLineWidth( lineWidth );
if( lineWidth != d->lineWidth )
auto hash = tickmarks.hash( 17435 );
hash = graduationMetrics.hash( hash );
hash = qHashBits( &boundaries, sizeof( boundaries ), hash );
hash = qHashBits( &rect, sizeof( rect ), hash );
hash = qHash( orientation, hash );
hash = qHash( alignment, hash );
if ( hash != m_hash )
{
d->lineWidth = lineWidth;
d->geometry.setLineWidth( lineWidth );
m_hash = hash;
markDirty( QSGNode::DirtyGeometry );
}
const auto hash = tickmarks.hash( 17435 );
if( ( hash != d->hash ) || ( rect != d->rect ) )
{
d->hash = hash;
d->rect = rect;
d->geometry.allocate( tickmarks.tickCount() * 2 );
auto vertexData = d->geometry.vertexDataAsPoint2D();
geometry()->allocate( tickmarks.tickCount() * 2 );
auto vertexData = geometry()->vertexDataAsPoint2D();
const qreal min = boundaries.lowerBound();
const qreal range = boundaries.width();
@ -82,12 +48,13 @@ void QskTickmarksNode::update(
for( int i = TM::MinorTick; i <= TM::MajorTick; i++ )
{
const auto tickType = static_cast< TM::TickType >( i );
const auto ticks = tickmarks.ticks( tickType );
const float len = graduationMetrics.tickLength( tickType );
if ( orientation == Qt::Horizontal )
{
const qreal ratio = rect.width() / range;
const float len = rect.height() * qskTickFactor( tickType );
for( const auto tick : ticks )
{
@ -120,7 +87,6 @@ void QskTickmarksNode::update(
else
{
const qreal ratio = rect.height() / range;
const float len = rect.width() * qskTickFactor( tickType );
for( const auto tick : ticks )
{
@ -152,13 +118,9 @@ void QskTickmarksNode::update(
}
}
d->geometry.markVertexDataDirty();
geometry()->markVertexDataDirty();
markDirty( QSGNode::DirtyGeometry );
}
if ( color != d->material.color() )
{
d->material.setColor( color );
markDirty( QSGNode::DirtyMaterial );
}
setColor( color );
}

View File

@ -6,19 +6,14 @@
#ifndef QSK_TICKMARKS_NODE_H
#define QSK_TICKMARKS_NODE_H
#include "QskGlobal.h"
#include "QskBasicLinesNode.h"
#include <qsgnode.h>
#include <qnamespace.h>
class QColor;
class QRectF;
class QskIntervalF;
class QskScaleTickmarks;
class QskGraduationMetrics;
class QRectF;
class QskTickmarksNodePrivate;
class QSK_EXPORT QskTickmarksNode : public QSGGeometryNode
class QSK_EXPORT QskTickmarksNode : public QskBasicLinesNode
{
public:
QskTickmarksNode();
@ -26,10 +21,10 @@ class QSK_EXPORT QskTickmarksNode : public QSGGeometryNode
void update(const QColor&, const QRectF&, const QskIntervalF&,
const QskScaleTickmarks&, int tickLineWidth, Qt::Orientation,
Qt::Alignment );
Qt::Alignment, const QskGraduationMetrics& );
private:
Q_DECLARE_PRIVATE( QskTickmarksNode )
QskHashValue m_hash = 0;
};
#endif