radiusX/radiusY to allow ellipsoid and circular radial gradients
This commit is contained in:
parent
877f4151bc
commit
76c8e41fcc
@ -86,7 +86,7 @@ namespace
|
||||
g->setFocalX( dir.x() );
|
||||
g->setFocalY( dir.y() );
|
||||
|
||||
g->setCenterRadius( dir.radius() );
|
||||
g->setCenterRadius( qMax( dir.radiusX(), dir.radiusY() ) );
|
||||
|
||||
shapeGradient = g;
|
||||
break;
|
||||
|
@ -53,7 +53,7 @@ namespace
|
||||
gradient.setSpreadMode( QskGradient::PadSpread );
|
||||
#endif
|
||||
#if 0
|
||||
gradient.setRadialDirection( 0.25, 0.75, 0.25 );
|
||||
gradient.setRadialDirection( 0.25, 0.75, 0.25, 0.0 );
|
||||
gradient.setSpreadMode( QskGradient::ReflectSpread );
|
||||
#endif
|
||||
#if 0
|
||||
|
@ -82,7 +82,7 @@ namespace
|
||||
shapeItem->setBorder( QskRgb::Indigo );
|
||||
|
||||
QskGradient gradient( QskRgb::LightYellow, QskRgb::MidnightBlue );
|
||||
gradient.setRadialDirection( QskRadialDirection() );
|
||||
gradient.setRadialDirection( QskRadialDirection( 0.7, 0.3, 0.25, 0.0 ) );
|
||||
gradient.setSpreadMode( QskGradient::PadSpread );
|
||||
|
||||
shapeItem->setGradient( gradient );
|
||||
|
@ -171,7 +171,7 @@ Qsk.Window
|
||||
|
||||
gradient:
|
||||
({
|
||||
radial: { x: 0.5, y: 0.5, radius: 0.5 },
|
||||
radial: { x: 0.7, y: 0.3, radiusX: 0.25, radiusY: 0.0 },
|
||||
|
||||
stops: [
|
||||
{ position: 0.0, color: "LightYellow" },
|
||||
@ -187,7 +187,7 @@ Qsk.Window
|
||||
|
||||
gradient:
|
||||
({
|
||||
radial: { x: 0.5, y: 0.5, radius: 0.5 },
|
||||
radial: { x: 0.5, y: 0.5, radiusX: 0.5, radiusY: 0.5 },
|
||||
spreadMode: Qsk.Gradient.PadSpread,
|
||||
|
||||
stops: [
|
||||
@ -212,7 +212,7 @@ Qsk.Window
|
||||
|
||||
gradient:
|
||||
({
|
||||
radial: { x: 0.5, y: 0.7, radius: 0.25 },
|
||||
radial: { x: 0.5, y: 0.7, radiusX: 0.25, radiusY: 0.25 },
|
||||
spreadMode: Qsk.Gradient.RepeatSpread,
|
||||
|
||||
// LilyMeadow
|
||||
@ -231,7 +231,7 @@ Qsk.Window
|
||||
|
||||
gradient:
|
||||
({
|
||||
radial: { x: 0.6, y: 0.4, radius: 0.1 },
|
||||
radial: { x: 0.6, y: 0.4, radiusX: 0.1, radiusY: 0.1 },
|
||||
spreadMode: Qsk.Gradient.ReflectSpread,
|
||||
|
||||
stops: [
|
||||
|
@ -105,7 +105,8 @@ namespace
|
||||
return QskRadialDirection(
|
||||
value.property( QStringLiteral( "x" ) ).toNumber(),
|
||||
value.property( QStringLiteral( "y" ) ).toNumber(),
|
||||
value.property( QStringLiteral( "radius" ) ).toNumber() );
|
||||
value.property( QStringLiteral( "radiusX" ) ).toNumber(),
|
||||
value.property( QStringLiteral( "radiusY" ) ).toNumber() );
|
||||
}
|
||||
|
||||
QskGradient toGradient( const QJSValue& value )
|
||||
|
@ -56,24 +56,14 @@ static inline bool qskCanBeInterpolated( const QskGradient& from, const QskGradi
|
||||
return from.type() == to.type();
|
||||
}
|
||||
|
||||
static inline QTransform qskTransformForRect( int stretch, const QRectF& rect )
|
||||
static inline QTransform qskTransformForRect( int, const QRectF& rect )
|
||||
{
|
||||
const qreal x = rect.x();
|
||||
const qreal y = rect.y();
|
||||
const qreal w = rect.width();
|
||||
const qreal h = rect.height();
|
||||
|
||||
switch( stretch )
|
||||
{
|
||||
case QskGradient::StretchToHeight:
|
||||
return QTransform( h, 0, 0, h, x, y );
|
||||
|
||||
case QskGradient::StretchToWidth:
|
||||
return QTransform( w, 0, 0, w, x, y );
|
||||
|
||||
default:
|
||||
return QTransform( w, 0, 0, h, x, y );
|
||||
}
|
||||
return QTransform( w, 0, 0, h, x, y );
|
||||
}
|
||||
|
||||
QskGradient::QskGradient( const QColor& color )
|
||||
@ -129,8 +119,7 @@ QskGradient::QskGradient( const QGradient& qGradient )
|
||||
|
||||
m_values[0] = g->focalPoint().x();
|
||||
m_values[1] = g->focalPoint().y();
|
||||
m_values[2] = g->focalRadius();
|
||||
m_values[3] = 0.0;
|
||||
m_values[3] = m_values[2] = g->focalRadius();
|
||||
|
||||
break;
|
||||
}
|
||||
@ -258,7 +247,7 @@ void QskGradient::updateStatusBits() const
|
||||
|
||||
case Radial:
|
||||
{
|
||||
m_isVisible = m_values[2] > 0.0; // radius
|
||||
m_isVisible = m_values[2] > 0.0 || m_values[3] > 0.0; // radius
|
||||
break;
|
||||
}
|
||||
|
||||
@ -425,9 +414,25 @@ void QskGradient::stretchTo( const QRectF& rect )
|
||||
{
|
||||
transform.map( m_values[0], m_values[1], &m_values[0], &m_values[1] );
|
||||
|
||||
#if 1
|
||||
m_values[2] *= qMin( rect.width(), rect.height() );
|
||||
#endif
|
||||
qreal rx = qMax( m_values[2], 0.0 );
|
||||
qreal ry = qMax( m_values[3], 0.0 );
|
||||
|
||||
if ( rx == 0.0 || ry == 0.0 )
|
||||
{
|
||||
/*
|
||||
It would be more logical if the scaling happens according
|
||||
the width, when rx is set ad v.v. But fitting the circle is
|
||||
probably, what most use cases need - and how to specify
|
||||
this. Maybe by introducing another stretchMode ... TODO
|
||||
*/
|
||||
const qreal r = qMin( rect.width(), rect.height() ) * qMax( rx, ry );
|
||||
m_values[2] = m_values[3] = r;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_values[2] = rx * rect.width();
|
||||
m_values[3] = ry * rect.height();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
@ -617,14 +622,18 @@ void QskGradient::setRadialDirection( const qreal x, qreal y, qreal radius )
|
||||
setRadialDirection( QskRadialDirection( x, y, radius ) );
|
||||
}
|
||||
|
||||
void QskGradient::setRadialDirection( const qreal x, qreal y,qreal radiusX, qreal radiusY )
|
||||
{
|
||||
setRadialDirection( QskRadialDirection( x, y, radiusX, radiusY ) );
|
||||
}
|
||||
void QskGradient::setRadialDirection( const QskRadialDirection& direction )
|
||||
{
|
||||
m_type = Radial;
|
||||
|
||||
m_values[0] = direction.center().x();
|
||||
m_values[1] = direction.center().y();
|
||||
m_values[2] = direction.radius();
|
||||
m_values[3] = 0.0;
|
||||
m_values[2] = direction.radiusX();
|
||||
m_values[3] = direction.radiusY();
|
||||
}
|
||||
|
||||
QskRadialDirection QskGradient::radialDirection() const
|
||||
@ -634,7 +643,7 @@ QskRadialDirection QskGradient::radialDirection() const
|
||||
if ( m_type != Radial )
|
||||
return QskRadialDirection( 0.5, 0.5, 0.0 );
|
||||
|
||||
return QskRadialDirection( m_values[0], m_values[1], m_values[2] );
|
||||
return QskRadialDirection( m_values[0], m_values[1], m_values[2], m_values[3] );
|
||||
}
|
||||
|
||||
void QskGradient::setConicDirection( qreal x, qreal y )
|
||||
@ -785,7 +794,7 @@ QDebug operator<<( QDebug debug, const QskGradient& gradient )
|
||||
const auto dir = gradient.radialDirection();
|
||||
|
||||
debug << dir.center().x() << "," << dir.center().y()
|
||||
<< "," << dir.radius() << ")";
|
||||
<< "," << dir.radiusX() << dir.radiusY() << ")";
|
||||
|
||||
break;
|
||||
}
|
||||
@ -831,19 +840,9 @@ QDebug operator<<( QDebug debug, const QskGradient& gradient )
|
||||
}
|
||||
}
|
||||
|
||||
switch( static_cast< int >( gradient.stretchMode() ) )
|
||||
if ( gradient.stretchMode() == QskGradient::StretchToSize )
|
||||
{
|
||||
case QskGradient::StretchToSize:
|
||||
debug << " SS";
|
||||
break;
|
||||
|
||||
case QskGradient::StretchToHeight:
|
||||
debug << " SH";
|
||||
break;
|
||||
|
||||
case QskGradient::StretchToWidth:
|
||||
debug << " SW";
|
||||
break;
|
||||
debug << " SS";
|
||||
}
|
||||
|
||||
switch( gradient.spreadMode() )
|
||||
|
@ -61,10 +61,6 @@ class QSK_EXPORT QskGradient
|
||||
enum StretchMode
|
||||
{
|
||||
NoStretch,
|
||||
|
||||
StretchToHeight,
|
||||
StretchToWidth,
|
||||
|
||||
StretchToSize
|
||||
};
|
||||
Q_ENUM( StretchMode )
|
||||
@ -98,6 +94,7 @@ class QSK_EXPORT QskGradient
|
||||
|
||||
void setRadialDirection( const QskRadialDirection& );
|
||||
void setRadialDirection( const qreal x, qreal y, qreal radius );
|
||||
void setRadialDirection( const qreal x, qreal y, qreal radiusX, qreal radiusY );
|
||||
QskRadialDirection radialDirection() const;
|
||||
|
||||
void setConicDirection( qreal, qreal );
|
||||
@ -174,7 +171,7 @@ class QSK_EXPORT QskGradient
|
||||
|
||||
/*
|
||||
Linear: x1, y1, x2, y2
|
||||
Radial: centerX, centerY, radius, n/a
|
||||
Radial: centerX, centerY, radiusX, radiusY
|
||||
Conic: centerX, centerY, startAngle, spanAngle
|
||||
*/
|
||||
qreal m_values[4] = {};
|
||||
|
@ -142,9 +142,25 @@ void QskRadialDirection::setY( qreal y ) noexcept
|
||||
m_y = y;
|
||||
}
|
||||
|
||||
void QskRadialDirection::setRadiusX( qreal radius ) noexcept
|
||||
{
|
||||
m_radiusX = radius;
|
||||
}
|
||||
|
||||
void QskRadialDirection::setRadiusY( qreal radius ) noexcept
|
||||
{
|
||||
m_radiusY = radius;
|
||||
}
|
||||
|
||||
void QskRadialDirection::setRadius( qreal radius ) noexcept
|
||||
{
|
||||
m_radius = radius;
|
||||
m_radiusX = m_radiusY = radius;
|
||||
}
|
||||
|
||||
void QskRadialDirection::setRadius( qreal radiusX, qreal radiusY ) noexcept
|
||||
{
|
||||
m_radiusX = radiusX;
|
||||
m_radiusY = radiusY;
|
||||
}
|
||||
|
||||
#include "moc_QskGradientDirection.cpp"
|
||||
|
@ -113,16 +113,18 @@ class QSK_EXPORT QskRadialDirection
|
||||
|
||||
Q_PROPERTY( qreal x READ x WRITE setX )
|
||||
Q_PROPERTY( qreal y READ y WRITE setY )
|
||||
Q_PROPERTY( qreal radius READ radius WRITE setRadius )
|
||||
Q_PROPERTY( qreal radiusX READ radiusX WRITE setRadiusX )
|
||||
Q_PROPERTY( qreal radiusY READ radiusY WRITE setRadiusY )
|
||||
|
||||
public:
|
||||
constexpr QskRadialDirection() noexcept = default;
|
||||
|
||||
constexpr QskRadialDirection( const QPointF& center, qreal radius ) noexcept;
|
||||
constexpr QskRadialDirection( qreal cx, qreal cy, qreal radius ) noexcept;
|
||||
constexpr QskRadialDirection( qreal cx, qreal cy, qreal radiusX, qreal radiusY ) noexcept;
|
||||
|
||||
constexpr QPointF center() const noexcept;
|
||||
void setCenter(const QPointF& center) noexcept;
|
||||
void setCenter(const QPointF& ) noexcept;
|
||||
void setCenter(qreal x, qreal y) noexcept;
|
||||
|
||||
void setX( qreal ) noexcept;
|
||||
@ -131,13 +133,20 @@ class QSK_EXPORT QskRadialDirection
|
||||
void setY( qreal ) noexcept;
|
||||
constexpr qreal y() const noexcept;
|
||||
|
||||
constexpr qreal radius() const noexcept;
|
||||
void setRadius( qreal radius ) noexcept;
|
||||
constexpr qreal radiusX() const noexcept;
|
||||
void setRadiusX( qreal ) noexcept;
|
||||
|
||||
constexpr qreal radiusY() const noexcept;
|
||||
void setRadiusY( qreal ) noexcept;
|
||||
|
||||
void setRadius( qreal ) noexcept;
|
||||
void setRadius( qreal, qreal ) noexcept;
|
||||
|
||||
private:
|
||||
qreal m_x = 0.5;
|
||||
qreal m_y = 0.5;
|
||||
qreal m_radius = 0.5;
|
||||
qreal m_radiusX = 0.5;
|
||||
qreal m_radiusY = 0.5;
|
||||
};
|
||||
|
||||
inline constexpr QskLinearDirection::QskLinearDirection(
|
||||
@ -270,7 +279,17 @@ inline constexpr QskRadialDirection::QskRadialDirection(
|
||||
qreal x, qreal y, qreal radius ) noexcept
|
||||
: m_x( x )
|
||||
, m_y( y )
|
||||
, m_radius( radius )
|
||||
, m_radiusX( radius )
|
||||
, m_radiusY( radius )
|
||||
{
|
||||
}
|
||||
|
||||
inline constexpr QskRadialDirection::QskRadialDirection(
|
||||
qreal x, qreal y, qreal radiusX, qreal radiusY ) noexcept
|
||||
: m_x( x )
|
||||
, m_y( y )
|
||||
, m_radiusX( radiusX )
|
||||
, m_radiusY( radiusY )
|
||||
{
|
||||
}
|
||||
|
||||
@ -295,9 +314,14 @@ inline constexpr qreal QskRadialDirection::y() const noexcept
|
||||
return m_y;
|
||||
}
|
||||
|
||||
inline constexpr qreal QskRadialDirection::radius() const noexcept
|
||||
inline constexpr qreal QskRadialDirection::radiusX() const noexcept
|
||||
{
|
||||
return m_radius;
|
||||
return m_radiusX;
|
||||
}
|
||||
|
||||
inline constexpr qreal QskRadialDirection::radiusY() const noexcept
|
||||
{
|
||||
return m_radiusY;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -70,7 +70,7 @@ namespace
|
||||
virtual QSGMaterialShader* createShader() const = 0;
|
||||
#endif
|
||||
|
||||
virtual bool setGradient( const QRectF&, const QskGradient& ) = 0;
|
||||
virtual bool setGradient( const QskGradient& ) = 0;
|
||||
};
|
||||
|
||||
#ifdef SHADER_GL
|
||||
@ -170,7 +170,7 @@ namespace
|
||||
{
|
||||
}
|
||||
|
||||
bool setGradient( const QRectF& rect, const QskGradient& gradient ) override
|
||||
bool setGradient( const QskGradient& gradient ) override
|
||||
{
|
||||
bool changed = false;
|
||||
|
||||
@ -194,11 +194,8 @@ namespace
|
||||
|
||||
const auto dir = gradient.linearDirection();
|
||||
|
||||
const QVector4D vector(
|
||||
rect.left() + dir.x1() * rect.width(),
|
||||
rect.top() + dir.y1() * rect.height(),
|
||||
( dir.x2() - dir.x1() ) * rect.width(),
|
||||
( dir.y2() - dir.y1() ) * rect.height() );
|
||||
const QVector4D vector( dir.x1(), dir.y1(),
|
||||
dir.x2() - dir.x1(), dir.y2() - dir.y1() );
|
||||
|
||||
if ( m_gradientVector != vector )
|
||||
{
|
||||
@ -333,7 +330,7 @@ namespace
|
||||
return &type;
|
||||
}
|
||||
|
||||
bool setGradient( const QRectF& rect, const QskGradient& gradient ) override
|
||||
bool setGradient( const QskGradient& gradient ) override
|
||||
{
|
||||
bool changed = false;
|
||||
|
||||
@ -351,12 +348,8 @@ namespace
|
||||
|
||||
const auto dir = gradient.radialDirection();
|
||||
|
||||
const QVector2D pos(
|
||||
rect.left() + dir.center().x() * rect.width(),
|
||||
rect.top() + dir.center().y() * rect.height() );
|
||||
|
||||
const QVector2D radius( dir.radius() * rect.width(),
|
||||
dir.radius() * rect.height() );
|
||||
const QVector2D pos( dir.x(), dir.y() );
|
||||
const QVector2D radius( dir.radiusX(), dir.radiusY() );
|
||||
|
||||
if ( ( pos != m_center ) || ( m_radius != radius ) )
|
||||
{
|
||||
@ -504,7 +497,7 @@ namespace
|
||||
return &type;
|
||||
}
|
||||
|
||||
bool setGradient( const QRectF& rect, const QskGradient& gradient ) override
|
||||
bool setGradient( const QskGradient& gradient ) override
|
||||
{
|
||||
bool changed = false;
|
||||
|
||||
@ -522,9 +515,7 @@ namespace
|
||||
|
||||
const auto dir = gradient.conicDirection();
|
||||
|
||||
const QVector2D center(
|
||||
rect.left() + dir.center().x() * rect.width(),
|
||||
rect.top() + dir.center().y() * rect.height() );
|
||||
const QVector2D center( dir.x(), dir.y() );
|
||||
|
||||
if ( center != m_center )
|
||||
{
|
||||
@ -715,7 +706,7 @@ bool QskGradientMaterial::updateGradient( const QRectF& rect, const QskGradient&
|
||||
case QskGradient::Conic:
|
||||
{
|
||||
auto material = static_cast< GradientMaterial* >( this );
|
||||
return material->setGradient( rect, gradient );
|
||||
return material->setGradient( gradient.stretchedTo( rect ) );
|
||||
}
|
||||
|
||||
default:
|
||||
|
Loading…
x
Reference in New Issue
Block a user