qskinny/src/common/QskGradient.h

263 lines
6.7 KiB
C
Raw Normal View History

2017-07-21 18:21:34 +02:00
/******************************************************************************
* QSkinny - Copyright (C) 2016 Uwe Rathmann
* This file may be used under the terms of the QSkinny License, Version 1.0
*****************************************************************************/
#ifndef QSK_GRADIENT_H
#define QSK_GRADIENT_H
2021-09-16 10:01:53 +02:00
#include "QskGradientStop.h"
2022-03-18 16:50:34 +01:00
#include <qbrush.h>
2018-08-03 08:15:28 +02:00
#include <qmetatype.h>
2017-07-21 18:21:34 +02:00
class QskLinearDirection;
class QskRadialDirection;
class QskConicDirection;
2022-10-31 14:42:08 +01:00
class QVariant;
2017-07-21 18:21:34 +02:00
/*
Don't use QskGradientStops for definitions seen by moc
Otherwise exporting these interfaces to QML does not work.
*/
2021-09-17 13:35:11 +02:00
2017-07-21 18:21:34 +02:00
class QSK_EXPORT QskGradient
{
Q_GADGET
Q_PROPERTY( Type type READ type )
Q_PROPERTY( QVector< QskGradientStop > stops READ stops WRITE setStops )
2017-07-21 18:21:34 +02:00
2019-05-10 08:09:48 +02:00
Q_PROPERTY( bool valid READ isValid )
Q_PROPERTY( bool visible READ isVisible )
Q_PROPERTY( bool monochrome READ isMonochrome )
2022-11-04 17:16:38 +01:00
Q_CLASSINFO( "DefaultProperty", "stops" )
2018-08-03 08:15:28 +02:00
public:
2022-10-31 14:42:08 +01:00
enum Type
2017-07-21 18:21:34 +02:00
{
2022-10-31 14:42:08 +01:00
Stops,
Linear,
Radial,
Conic
2017-07-21 18:21:34 +02:00
};
2022-10-31 14:42:08 +01:00
Q_ENUM( Type )
2017-07-21 18:21:34 +02:00
QskGradient() noexcept = default;
QskGradient( Qt::GlobalColor );
QskGradient( QRgb );
2017-07-21 18:21:34 +02:00
QskGradient( const QColor& );
2022-10-31 14:42:08 +01:00
QskGradient( const QColor&, const QColor& );
2022-03-18 16:50:34 +01:00
QskGradient( QGradient::Preset );
2022-10-31 14:42:08 +01:00
QskGradient( const QVector< QskGradientStop >& );
2022-10-31 14:42:08 +01:00
QskGradient( const QskGradient& ) noexcept;
2017-07-21 18:21:34 +02:00
~QskGradient();
2022-10-31 14:42:08 +01:00
QskGradient& operator=( const QskGradient& ) noexcept;
bool operator==( const QskGradient& ) const noexcept;
bool operator!=( const QskGradient& ) const noexcept;
2017-07-21 18:21:34 +02:00
2022-10-31 14:42:08 +01:00
QskGradient::Type type() const noexcept;
void setLinearDirection( const QskLinearDirection& );
void setLinearDirection( qreal, qreal, qreal, qreal );
void setLinearDirection( Qt::Orientation );
QskLinearDirection linearDirection() const;
void setRadialDirection( const QskRadialDirection& );
void setRadialDirection( const qreal x, qreal y, qreal radius );
void setRadialDirection();
QskRadialDirection radialDirection() const;
void setConicDirection( qreal, qreal );
void setConicDirection( qreal, qreal, qreal, qreal = 360.0 );
void setConicDirection( const QskConicDirection& );
QskConicDirection conicDirection() const;
void resetDirection();
bool isValid() const noexcept;
bool isMonochrome() const noexcept;
bool isVisible() const noexcept;
2017-07-21 18:21:34 +02:00
void setStops( const QVector< QskGradientStop >& );
const QVector< QskGradientStop >& stops() const noexcept;
2017-07-21 18:21:34 +02:00
2022-11-16 16:19:19 +01:00
void setStops( const QRgb );
void setStops( Qt::GlobalColor );
void setStops( const QColor& );
2022-11-16 16:19:19 +01:00
void setStops( const QColor&, const QColor& );
void setStops( QGradient::Preset );
void clearStops();
2017-07-21 18:21:34 +02:00
Q_INVOKABLE bool hasStopAt( qreal value ) const noexcept;
Q_INVOKABLE QColor startColor() const noexcept;
Q_INVOKABLE QColor endColor() const noexcept;
QRgb rgbStart() const;
QRgb rgbEnd() const;
void setAlpha( int alpha );
2017-07-21 18:21:34 +02:00
2022-10-31 14:42:08 +01:00
void setSpread( QGradient::Spread );
QGradient::Spread spread() const noexcept;
2020-07-31 12:42:36 +02:00
void reverse();
QskGradient reversed() const;
QskGradient interpolated( const QskGradient&, qreal value ) const;
static QVariant interpolate( const QskGradient&,
const QskGradient&, qreal progress );
2022-10-24 17:08:48 +02:00
// all stops between [from, to] with positions streched into [0,1]
QskGradient extracted( qreal from, qreal start ) const;
QskHashValue hash( QskHashValue seed ) const;
2022-10-24 16:40:47 +02:00
Q_INVOKABLE qreal stopAt( int index ) const noexcept;
Q_INVOKABLE QColor colorAt( int index ) const noexcept;
int stepCount() const noexcept;
2022-06-25 16:14:08 +02:00
2019-04-18 16:11:05 +02:00
private:
void updateStatusBits() const;
private:
#if 1
/*
Couldn't find a way how to assign a struct to another struct
that is used as proprty from QML without creating extra QObjects.
So for the moment we are using lists, that are more
error prone and less intuitive.
Maybe we can do something better using qmlRegisterCustomType, where we
can register our own QQmlCustomParser. TODO ...
*/
Q_PROPERTY( QVector< qreal > linear READ linearAsList WRITE setLinearAsList )
Q_PROPERTY( QVector< qreal > conic READ conicAsList WRITE setConicAsList )
Q_PROPERTY( QVector< qreal > radial READ radialAsList WRITE setRadialAsList )
QVector< qreal > linearAsList() const;
void setLinearAsList( const QVector< qreal >& );
QVector< qreal > radialAsList() const;
void setRadialAsList( const QVector< qreal >& );
QVector< qreal > conicAsList() const;
void setConicAsList( const QVector< qreal >& );
#endif
private:
QVector< QskGradientStop > m_stops;
2022-10-31 14:42:08 +01:00
/*
Linear: x1, y1, x2, y2
Radial: centerX, centerY, radius, n/a
Conic: centerX, centerY, startAngle, spanAngle
*/
qreal m_values[4] = {};
Type m_type = Stops;
QGradient::Spread m_spread = QGradient::PadSpread;
mutable bool m_isDirty = false;
mutable bool m_isValid = false;
mutable bool m_isMonchrome = true;
mutable bool m_isVisible = false;
2017-07-21 18:21:34 +02:00
};
2021-09-16 10:01:53 +02:00
Q_DECLARE_METATYPE( QskGradient )
2022-10-31 14:42:08 +01:00
inline QskGradient::QskGradient( Qt::GlobalColor color )
: QskGradient( QColor( color ) )
{
}
2022-10-31 14:42:08 +01:00
inline QskGradient::QskGradient( QRgb rgb )
: QskGradient( QColor::fromRgba( rgb ) )
{
}
2022-10-31 14:42:08 +01:00
inline bool QskGradient::operator!=( const QskGradient& other ) const noexcept
{
2022-10-31 14:42:08 +01:00
return !( *this == other );
}
2022-10-31 14:42:08 +01:00
inline QskGradient::Type QskGradient::type() const noexcept
{
2022-10-31 14:42:08 +01:00
return m_type;
}
inline const QskGradientStops& QskGradient::stops() const noexcept
{
#if 1
/*
Returning a const& so that it is possible to write:
for ( const auto& stop : qAsConst( gradient.stops() ) )
Once we have changed QskGradientStop from QColor to QRgb
we should check if there is a better solution possible
*/
#endif
return m_stops;
}
2022-11-16 16:19:19 +01:00
inline void QskGradient::setStops( QRgb rgb )
{
setStops( QColor::fromRgba( rgb ) );
}
inline void QskGradient::setStops( Qt::GlobalColor color )
{
setStops( QColor( color ) );
}
inline QColor QskGradient::startColor() const noexcept
2017-07-21 18:21:34 +02:00
{
return m_stops.isEmpty() ? QColor() : m_stops.first().color();
2017-07-21 18:21:34 +02:00
}
inline QColor QskGradient::endColor() const noexcept
2017-07-21 18:21:34 +02:00
{
return m_stops.isEmpty() ? QColor() : m_stops.last().color();
2017-07-21 18:21:34 +02:00
}
inline QRgb QskGradient::rgbStart() const
{
return m_stops.isEmpty() ? qRgba( 0, 0, 0, 255 ) : m_stops.first().rgb();
}
inline QRgb QskGradient::rgbEnd() const
{
return m_stops.isEmpty() ? qRgba( 0, 0, 0, 255 ) : m_stops.last().rgb();
}
2022-10-31 14:42:08 +01:00
inline QGradient::Spread QskGradient::spread() const noexcept
{
return m_spread;
}
2017-07-21 18:21:34 +02:00
#ifndef QT_NO_DEBUG_STREAM
2021-09-16 10:01:53 +02:00
class QDebug;
2017-07-21 18:21:34 +02:00
QSK_EXPORT QDebug operator<<( QDebug, const QskGradient& );
#endif
#endif