Using our own gradient shaders ( no dependencies from quickshapes
anymore ). shapes/Gradient has not yet been merged into QskGradient and we still have some stupid conversions to QGradient in the way.
This commit is contained in:
parent
929c02fa0e
commit
51a7e4e589
|
@ -8,8 +8,8 @@
|
|||
|
||||
Gradient::Gradient( const Gradient& other ) noexcept
|
||||
: m_stops( other.m_stops )
|
||||
, m_values{ other.m_values[0], other.m_values[1], other.m_values[2],
|
||||
other.m_values[3], other.m_values[4], other.m_values[5] }
|
||||
, m_values{ other.m_values[0], other.m_values[1],
|
||||
other.m_values[2], other.m_values[3], }
|
||||
, m_type( other.m_type )
|
||||
, m_spread( other.m_spread )
|
||||
{
|
||||
|
@ -25,8 +25,6 @@ Gradient& Gradient::operator=( const Gradient& other ) noexcept
|
|||
m_values[1] = other.m_values[1];
|
||||
m_values[2] = other.m_values[2];
|
||||
m_values[3] = other.m_values[3];
|
||||
m_values[4] = other.m_values[4];
|
||||
m_values[5] = other.m_values[5];
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
@ -46,8 +44,6 @@ bool Gradient::operator==( const Gradient& other ) const noexcept
|
|||
&& ( m_values[1] == other.m_values[1] )
|
||||
&& ( m_values[2] == other.m_values[2] )
|
||||
&& ( m_values[3] == other.m_values[3] )
|
||||
&& ( m_values[4] == other.m_values[4] )
|
||||
&& ( m_values[5] == other.m_values[5] )
|
||||
&& ( m_stops == other.m_stops );
|
||||
}
|
||||
|
||||
|
@ -223,28 +219,11 @@ void RadialGradient::setCenter( qreal x, qreal y ) noexcept
|
|||
m_values[1] = y;
|
||||
}
|
||||
|
||||
void RadialGradient::setFocalPoint( const QPointF& focalPoint ) noexcept
|
||||
{
|
||||
m_values[3] = focalPoint.x();
|
||||
m_values[4] = focalPoint.y();
|
||||
}
|
||||
|
||||
void RadialGradient::setFocalPoint( qreal x, qreal y ) noexcept
|
||||
{
|
||||
m_values[3] = x;
|
||||
m_values[4] = y;
|
||||
}
|
||||
|
||||
void RadialGradient::setCenterRadius( qreal radius ) noexcept
|
||||
void RadialGradient::setRadius( qreal radius ) noexcept
|
||||
{
|
||||
m_values[2] = radius;
|
||||
}
|
||||
|
||||
void RadialGradient::setFocalRadius( qreal radius ) noexcept
|
||||
{
|
||||
m_values[5] = radius;
|
||||
}
|
||||
|
||||
void ConicGradient::setCenter( const QPointF& center ) noexcept
|
||||
{
|
||||
m_values[0] = center.x();
|
||||
|
@ -257,7 +236,12 @@ void ConicGradient::setCenter( qreal x, qreal y ) noexcept
|
|||
m_values[1] = y;
|
||||
}
|
||||
|
||||
void ConicGradient::setDegrees( qreal degrees ) noexcept
|
||||
void ConicGradient::setStartAngle( qreal degrees ) noexcept
|
||||
{
|
||||
m_values[2] = degrees;
|
||||
}
|
||||
|
||||
void ConicGradient::setSpanAngle( qreal degrees ) noexcept
|
||||
{
|
||||
m_values[3] = qBound( -360.0, degrees, 360.0 );
|
||||
}
|
||||
|
|
|
@ -37,8 +37,8 @@ class Gradient
|
|||
bool isMonochrome() const;
|
||||
bool isVisible() const;
|
||||
|
||||
void setStops( const QVector< QskGradientStop >& );
|
||||
const QVector< QskGradientStop >& stops() const noexcept;
|
||||
void setStops( const QskGradientStops& );
|
||||
const QskGradientStops& stops() const noexcept;
|
||||
|
||||
void setStops( QGradient::Preset );
|
||||
void setStops( const QGradientStops& );
|
||||
|
@ -63,22 +63,28 @@ class Gradient
|
|||
friend class ConicGradient;
|
||||
|
||||
Gradient( QGradient::Type ) noexcept;
|
||||
Gradient( QGradient::Type,
|
||||
qreal, qreal, qreal, qreal, qreal, qreal ) noexcept;
|
||||
Gradient( QGradient::Type, qreal, qreal, qreal, qreal ) noexcept;
|
||||
|
||||
QVector< QskGradientStop > m_stops;
|
||||
QskGradientStops m_stops;
|
||||
|
||||
/*
|
||||
Linear: x1, y1, x2, y2, n/a, n/a
|
||||
Radial: centerX, centerY, centerRadius, focalX, focalY, focalRadius
|
||||
Conic: centerX, centerY, degrees, n/a, n/a, n/a
|
||||
Linear: x1, y1, x2, y2
|
||||
Radial: centerX, centerY, radius, n/a
|
||||
Conic: centerX, centerY, startAngle, spanAngle
|
||||
*/
|
||||
qreal m_values[6] = {};
|
||||
qreal m_values[4] = {};
|
||||
|
||||
QGradient::Type m_type = QGradient::NoGradient;
|
||||
QGradient::Spread m_spread = QGradient::PadSpread;
|
||||
};
|
||||
|
||||
#ifndef QT_NO_DEBUG_STREAM
|
||||
|
||||
class QDebug;
|
||||
QDebug operator<<( QDebug, const QskGradient& );
|
||||
|
||||
#endif
|
||||
|
||||
class LinearGradient : public Gradient
|
||||
{
|
||||
public:
|
||||
|
@ -96,13 +102,6 @@ class LinearGradient : public Gradient
|
|||
QPointF stop() const noexcept;
|
||||
};
|
||||
|
||||
#ifndef QT_NO_DEBUG_STREAM
|
||||
|
||||
class QDebug;
|
||||
QDebug operator<<( QDebug, const Gradient& );
|
||||
|
||||
#endif
|
||||
|
||||
class RadialGradient : public Gradient
|
||||
{
|
||||
public:
|
||||
|
@ -111,40 +110,34 @@ class RadialGradient : public Gradient
|
|||
RadialGradient( const QPointF& center, qreal radius ) noexcept;
|
||||
RadialGradient( qreal cx, qreal cy, qreal radius ) noexcept;
|
||||
|
||||
RadialGradient( const QPointF& center, qreal centerRadius,
|
||||
const QPointF& focalPoint, qreal focalRadius = 0.0 ) noexcept;
|
||||
|
||||
RadialGradient(qreal cx, qreal cy, qreal centerRadius,
|
||||
qreal fx, qreal fy, qreal focalRadius = 0.0 ) noexcept;
|
||||
|
||||
QPointF center() const noexcept;
|
||||
void setCenter(const QPointF& center) noexcept;
|
||||
void setCenter(qreal x, qreal y) noexcept;
|
||||
|
||||
QPointF focalPoint() const noexcept;
|
||||
void setFocalPoint( const QPointF& focalPoint ) noexcept;
|
||||
void setFocalPoint( qreal x, qreal y ) noexcept;
|
||||
|
||||
qreal centerRadius() const noexcept;
|
||||
void setCenterRadius( qreal radius ) noexcept;
|
||||
|
||||
qreal focalRadius() const noexcept;
|
||||
void setFocalRadius( qreal radius ) noexcept;
|
||||
qreal radius() const noexcept;
|
||||
void setRadius( qreal radius ) noexcept;
|
||||
};
|
||||
|
||||
class ConicGradient : public Gradient
|
||||
{
|
||||
public:
|
||||
ConicGradient() noexcept;
|
||||
ConicGradient( const QPointF&, qreal degrees ) noexcept;
|
||||
ConicGradient( qreal cx, qreal cy, qreal degrees ) noexcept;
|
||||
|
||||
ConicGradient( const QPointF&,
|
||||
qreal startAngle = 0.0, qreal spanAngle = 360.0 ) noexcept;
|
||||
|
||||
ConicGradient( qreal cx, qreal cy,
|
||||
qreal startAngle = 0.0, qreal spanAngle = 360.0 ) noexcept;
|
||||
|
||||
QPointF center() const noexcept;
|
||||
void setCenter(const QPointF& center) noexcept;
|
||||
void setCenter(qreal x, qreal y) noexcept;
|
||||
|
||||
qreal degrees() const noexcept;
|
||||
void setDegrees(qreal ) noexcept;
|
||||
qreal startAngle() const noexcept;
|
||||
void setStartAngle( qreal ) noexcept;
|
||||
|
||||
qreal spanAngle() const noexcept;
|
||||
void setSpanAngle( qreal ) noexcept;
|
||||
};
|
||||
|
||||
inline Gradient::Gradient( QGradient::Type type ) noexcept
|
||||
|
@ -153,9 +146,8 @@ inline Gradient::Gradient( QGradient::Type type ) noexcept
|
|||
}
|
||||
|
||||
inline Gradient::Gradient( QGradient::Type type,
|
||||
qreal v1, qreal v2, qreal v3,
|
||||
qreal v4 = 0.0, qreal v5 = 0.0, qreal v6 = 0.0 ) noexcept
|
||||
: m_values{ v1, v2, v3, v4, v5, v6 }
|
||||
qreal v1, qreal v2, qreal v3, qreal v4 ) noexcept
|
||||
: m_values{ v1, v2, v3, v4 }
|
||||
, m_type( type )
|
||||
{
|
||||
}
|
||||
|
@ -175,7 +167,7 @@ inline bool Gradient::isValid() const noexcept
|
|||
return m_type != QGradient::NoGradient;
|
||||
}
|
||||
|
||||
inline const QVector< QskGradientStop >& Gradient::stops() const noexcept
|
||||
inline const QskGradientStops& Gradient::stops() const noexcept
|
||||
{
|
||||
return m_stops;
|
||||
}
|
||||
|
@ -213,15 +205,7 @@ inline QPointF LinearGradient::stop() const noexcept
|
|||
}
|
||||
|
||||
inline RadialGradient::RadialGradient() noexcept
|
||||
: Gradient( QGradient::RadialGradient, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0 )
|
||||
{
|
||||
}
|
||||
|
||||
inline RadialGradient::RadialGradient(
|
||||
const QPointF& center, qreal radius,
|
||||
const QPointF& focalPoint, qreal focalRadius ) noexcept
|
||||
: RadialGradient( center.x(), center.y(), radius,
|
||||
focalPoint.x(), focalPoint.y(), focalRadius )
|
||||
: Gradient( QGradient::RadialGradient, 0.5, 0.5, 0.5, 0.0 )
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -233,14 +217,7 @@ inline RadialGradient::RadialGradient(
|
|||
|
||||
inline RadialGradient::RadialGradient(
|
||||
qreal cx, qreal cy, qreal radius ) noexcept
|
||||
: RadialGradient( cx, cy, radius, cx, cy, 0.0 )
|
||||
{
|
||||
}
|
||||
|
||||
inline RadialGradient::RadialGradient(
|
||||
qreal cx, qreal cy, qreal radius,
|
||||
qreal fx, qreal fy, qreal focalRadius ) noexcept
|
||||
: Gradient( QGradient::RadialGradient, cx, cy, radius, fx, fy, focalRadius )
|
||||
: Gradient( QGradient::RadialGradient, cx, cy, radius, 0.0 )
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -249,35 +226,25 @@ inline QPointF RadialGradient::center() const noexcept
|
|||
return QPointF( m_values[0], m_values[1] );
|
||||
}
|
||||
|
||||
inline qreal RadialGradient::centerRadius() const noexcept
|
||||
inline qreal RadialGradient::radius() const noexcept
|
||||
{
|
||||
return m_values[2];
|
||||
}
|
||||
|
||||
inline QPointF RadialGradient::focalPoint() const noexcept
|
||||
{
|
||||
return QPointF( m_values[3], m_values[4] );
|
||||
}
|
||||
|
||||
inline qreal RadialGradient::focalRadius() const noexcept
|
||||
{
|
||||
return m_values[5];
|
||||
}
|
||||
|
||||
inline ConicGradient::ConicGradient() noexcept
|
||||
: Gradient( QGradient::ConicalGradient, 0.0, 0.0, 0.0 )
|
||||
: Gradient( QGradient::ConicalGradient, 0.0, 0.0, 0.0, 0.0 )
|
||||
{
|
||||
}
|
||||
|
||||
inline ConicGradient::ConicGradient(
|
||||
const QPointF& center, qreal degrees ) noexcept
|
||||
: ConicGradient( center.x(), center.y(), degrees )
|
||||
const QPointF& center, qreal startAngle, qreal spanAngle ) noexcept
|
||||
: ConicGradient( center.x(), center.y(), startAngle, spanAngle )
|
||||
{
|
||||
}
|
||||
|
||||
inline ConicGradient::ConicGradient(
|
||||
qreal cx, qreal cy, qreal degrees ) noexcept
|
||||
: Gradient( QGradient::ConicalGradient, cx, cy, degrees )
|
||||
qreal cx, qreal cy, qreal startAngle, qreal spanAngle ) noexcept
|
||||
: Gradient( QGradient::ConicalGradient, cx, cy, startAngle, spanAngle )
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -286,7 +253,12 @@ inline QPointF ConicGradient::center() const noexcept
|
|||
return QPointF( m_values[0], m_values[1] );
|
||||
}
|
||||
|
||||
inline qreal ConicGradient::degrees() const noexcept
|
||||
inline qreal ConicGradient::startAngle() const noexcept
|
||||
{
|
||||
return m_values[2];
|
||||
}
|
||||
|
||||
inline qreal ConicGradient::spanAngle() const noexcept
|
||||
{
|
||||
return m_values[3];
|
||||
}
|
||||
|
|
|
@ -67,20 +67,11 @@ namespace
|
|||
{
|
||||
const auto& g = gradient.asLinearGradient();
|
||||
|
||||
const qreal x1 = rect.left() + g.start().x() * rect.width();
|
||||
const qreal y1 = rect.top() + g.start().y() * rect.height();
|
||||
|
||||
const qreal x2 = rect.left() + g.stop().x() * rect.width();
|
||||
const qreal y2 = rect.top() + g.stop().y() * rect.height();
|
||||
|
||||
#if 0
|
||||
QTransform t2( rect.width(), 0, 0, rect.height(), rect.x(), rect.y());
|
||||
#endif
|
||||
QLinearGradient qgradient( x1, y1, x2, y2 );
|
||||
QLinearGradient qgradient( g.start(), g.stop() );
|
||||
qgradient.setSpread( g.spread() );
|
||||
qgradient.setStops( g.qtStops() );
|
||||
|
||||
updateNode( path, transform, &qgradient );
|
||||
updateNode( path, transform, rect, &qgradient );
|
||||
|
||||
break;
|
||||
}
|
||||
|
@ -88,19 +79,11 @@ namespace
|
|||
{
|
||||
const auto& g = gradient.asRadialGradient();
|
||||
|
||||
const qreal x = rect.left() + g.center().x() * rect.width();
|
||||
const qreal y = rect.top() + g.center().y() * rect.height();
|
||||
const qreal r = g.centerRadius() * qMin( rect.width(), rect.height() );
|
||||
|
||||
const qreal fx = rect.left() + g.focalPoint().x() * rect.width();
|
||||
const qreal fy = rect.top() + g.focalPoint().y() * rect.height();
|
||||
const qreal fr = g.focalRadius() * qMin( rect.width(), rect.height() );
|
||||
|
||||
QRadialGradient qgradient( x, y, r, fx, fy, fr );
|
||||
QRadialGradient qgradient( g.center(), g.radius() );
|
||||
qgradient.setSpread( g.spread() );
|
||||
qgradient.setStops( g.qtStops() );
|
||||
|
||||
updateNode( path, transform, &qgradient );
|
||||
updateNode( path, transform, rect, &qgradient );
|
||||
|
||||
break;
|
||||
}
|
||||
|
@ -108,14 +91,16 @@ namespace
|
|||
{
|
||||
const auto& g = gradient.asConicGradient();
|
||||
|
||||
const qreal x = rect.left() + g.center().x() * rect.width();
|
||||
const qreal y = rect.top() + g.center().y() * rect.height();
|
||||
|
||||
QConicalGradient qgradient( x, y, g.degrees() );
|
||||
//qgradient.setSpread( g.spread() );
|
||||
QConicalGradient qgradient( g.center(), g.startAngle() );
|
||||
qgradient.setSpread( g.spread() );
|
||||
qgradient.setStops( g.qtStops() );
|
||||
|
||||
updateNode( path, transform, &qgradient );
|
||||
/*
|
||||
Once ConicGradient has become QskConicGradient we do not
|
||||
need QConicalGradient anymore and passing the spanAngle
|
||||
as extra parameter can go away.
|
||||
*/
|
||||
updateNode( path, transform, rect, &qgradient, g.spanAngle() );
|
||||
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -4,57 +4,64 @@
|
|||
*****************************************************************************/
|
||||
|
||||
#include "ShapeItem.h"
|
||||
#include "Gradient.h"
|
||||
|
||||
#include <QskObjectCounter.h>
|
||||
#include <QskWindow.h>
|
||||
#include <QskRgbValue.h>
|
||||
#include <QskLinearBox.h>
|
||||
#include <QskTabView.h>
|
||||
|
||||
#include <SkinnyShortcut.h>
|
||||
#include <SkinnyShapeFactory.h>
|
||||
#include <QGuiApplication>
|
||||
#include <QBrush>
|
||||
|
||||
namespace
|
||||
{
|
||||
QPainterPath path( SkinnyShapeFactory::Shape shape )
|
||||
class Page : public QskLinearBox
|
||||
{
|
||||
public:
|
||||
Page( QQuickItem* parent = nullptr )
|
||||
: QskLinearBox( Qt::Horizontal, 2, parent )
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
static QPen pen( const QColor& color )
|
||||
{
|
||||
QPen p( color );
|
||||
#if 0
|
||||
p.setCosmetic( true );
|
||||
#endif
|
||||
|
||||
p.setWidth( p.isCosmetic() ? 8 : 2 );
|
||||
p.setJoinStyle( Qt::MiterJoin );
|
||||
|
||||
#if 0
|
||||
p.setStyle( Qt::DashLine );
|
||||
p.setColor( QskRgb::toTransparent( color(), alpha ) );
|
||||
#endif
|
||||
return p;
|
||||
}
|
||||
|
||||
static QPainterPath path( SkinnyShapeFactory::Shape shape )
|
||||
{
|
||||
return SkinnyShapeFactory::shapePath( shape, QSizeF( 50, 50 ) );
|
||||
}
|
||||
|
||||
class Pen : public QPen
|
||||
{
|
||||
public:
|
||||
Pen( const QColor& color )
|
||||
: QPen( color )
|
||||
{
|
||||
//setCosmetic( true );
|
||||
setWidth( isCosmetic() ? 8 : 2 );
|
||||
|
||||
setJoinStyle( Qt::MiterJoin );
|
||||
|
||||
//setStyle( Qt::NoPen );
|
||||
//setStyle( Qt::DashLine );
|
||||
|
||||
//setAlpha( 100 );
|
||||
}
|
||||
|
||||
void setAlpha( int alpha )
|
||||
{
|
||||
setColor( QskRgb::toTransparent( color(), alpha ) );
|
||||
}
|
||||
};
|
||||
|
||||
class Box : public QskLinearBox
|
||||
class LinearGradientPage : public Page
|
||||
{
|
||||
public:
|
||||
Box( QQuickItem* parent = nullptr )
|
||||
: QskLinearBox( Qt::Horizontal, 2, parent )
|
||||
LinearGradientPage( QQuickItem* parent = nullptr )
|
||||
: Page( parent )
|
||||
{
|
||||
{
|
||||
auto shapeItem = new ShapeItem( this );
|
||||
|
||||
shapeItem->setPath( path( SkinnyShapeFactory::Hexagon ) );
|
||||
shapeItem->setPen( Pen( QColorConstants::Svg::indigo ) );
|
||||
shapeItem->setPen( pen( QColorConstants::Svg::indigo ) );
|
||||
|
||||
LinearGradient gradient( 0.0, 0.0, 0.2, 0.5 );
|
||||
gradient.setSpread( QGradient::ReflectSpread );
|
||||
|
@ -62,14 +69,36 @@ namespace
|
|||
|
||||
shapeItem->setGradient( gradient );
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class RadialGradientPage : public Page
|
||||
{
|
||||
public:
|
||||
RadialGradientPage( QQuickItem* parent = nullptr )
|
||||
: Page( parent )
|
||||
{
|
||||
{
|
||||
auto shapeItem = new ShapeItem( this );
|
||||
|
||||
shapeItem->setPath( path( SkinnyShapeFactory::Rectangle ) );
|
||||
shapeItem->setPen( pen( QColorConstants::Svg::indigo ) );
|
||||
|
||||
RadialGradient gradient( 0.5, 0.5, 0.5 );
|
||||
|
||||
gradient.setSpread( QGradient::PadSpread );
|
||||
gradient.setStops( QColorConstants::Svg::lightyellow,
|
||||
QColorConstants::Svg::midnightblue );
|
||||
|
||||
shapeItem->setGradient( gradient );
|
||||
}
|
||||
{
|
||||
auto shapeItem = new ShapeItem( this );
|
||||
|
||||
shapeItem->setPath( path( SkinnyShapeFactory::Ellipse ) );
|
||||
|
||||
RadialGradient gradient( 0.5, 0.5, 0.5 );
|
||||
gradient.setSpread( QGradient::RepeatSpread );
|
||||
gradient.setSpread( QGradient::PadSpread );
|
||||
|
||||
QVector< QskGradientStop > stops;
|
||||
|
||||
|
@ -88,29 +117,101 @@ namespace
|
|||
|
||||
shapeItem->setGradient( gradient );
|
||||
}
|
||||
|
||||
{
|
||||
auto shapeItem = new ShapeItem( this );
|
||||
|
||||
shapeItem->setPath( path( SkinnyShapeFactory::Arc ) );
|
||||
shapeItem->setPath( path( SkinnyShapeFactory::Rectangle ) );
|
||||
shapeItem->setPen( pen( QColorConstants::Svg::indigo ) );
|
||||
|
||||
ConicGradient gradient( 0.5, 0.5, -60.0 );
|
||||
gradient.setStops( QGradient::BurningSpring );
|
||||
RadialGradient gradient( 0.5, 0.5, 0.25 );
|
||||
gradient.setCenter( 0.5, 0.7 );
|
||||
|
||||
gradient.setSpread( QGradient::RepeatSpread );
|
||||
gradient.setStops( QGradient::LilyMeadow );
|
||||
|
||||
shapeItem->setGradient( gradient );
|
||||
}
|
||||
{
|
||||
auto shapeItem = new ShapeItem( this );
|
||||
|
||||
shapeItem->setPath( path( SkinnyShapeFactory::Rectangle ) );
|
||||
shapeItem->setPen( pen( QColorConstants::Svg::indigo ) );
|
||||
|
||||
RadialGradient gradient( 0.6, 0.4, 0.1 );
|
||||
|
||||
gradient.setSpread( QGradient::ReflectSpread );
|
||||
gradient.setStops( Qt::red, Qt::blue );
|
||||
|
||||
shapeItem->setGradient( gradient );
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class ConicGradientPage : public Page
|
||||
{
|
||||
public:
|
||||
ConicGradientPage( QQuickItem* parent = nullptr )
|
||||
: Page( parent )
|
||||
{
|
||||
{
|
||||
auto shapeItem = new ShapeItem( this );
|
||||
|
||||
shapeItem->setPath( path( SkinnyShapeFactory::Ellipse ) );
|
||||
|
||||
RadialGradient gradient( 0.5, 0.5, 0.5 );
|
||||
gradient.setSpread( QGradient::RepeatSpread );
|
||||
gradient.setStops( QGradient::DirtyBeauty );
|
||||
ConicGradient gradient( 0.5, 0.5, 30.0, 60.0 );
|
||||
gradient.setSpread( QGradient::ReflectSpread );
|
||||
gradient.setStops( QGradient::JuicyPeach );
|
||||
|
||||
shapeItem->setGradient( gradient );
|
||||
}
|
||||
{
|
||||
auto shapeItem = new ShapeItem( this );
|
||||
|
||||
shapeItem->setPath( path( SkinnyShapeFactory::TriangleUp ) );
|
||||
|
||||
ConicGradient gradient( 0.5, 0.5, 30.0, 60.0 );
|
||||
gradient.setSpread( QGradient::RepeatSpread );
|
||||
gradient.setStops( QGradient::WinterNeva );
|
||||
|
||||
shapeItem->setGradient( gradient );
|
||||
}
|
||||
{
|
||||
auto shapeItem = new ShapeItem( this );
|
||||
|
||||
shapeItem->setPath( path( SkinnyShapeFactory::Arc ) );
|
||||
|
||||
ConicGradient gradient( 0.5, 0.5, 300.0, -240.0 );
|
||||
gradient.setStops( QGradient::SpikyNaga );
|
||||
|
||||
shapeItem->setGradient( gradient );
|
||||
}
|
||||
{
|
||||
auto shapeItem = new ShapeItem( this );
|
||||
|
||||
shapeItem->setPath( path( SkinnyShapeFactory::Diamond ) );
|
||||
|
||||
ConicGradient gradient( 0.5, 0.5, 45.0, 180.0 );
|
||||
gradient.setStops( QGradient::FabledSunset );
|
||||
gradient.setSpread( QGradient::ReflectSpread );
|
||||
|
||||
shapeItem->setGradient( gradient );
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class TabView : public QskTabView
|
||||
{
|
||||
public:
|
||||
TabView( QQuickItem* parentItem = nullptr )
|
||||
: QskTabView( parentItem )
|
||||
{
|
||||
setMargins( 10 );
|
||||
setAutoFitTabs( true );
|
||||
setTabBarEdge( Qt::TopEdge );
|
||||
|
||||
addTab( "Radial Gradients", new RadialGradientPage() );
|
||||
addTab( "Conic Gradients", new ConicGradientPage() );
|
||||
addTab( "Linear Gradients", new LinearGradientPage() );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -127,7 +228,7 @@ int main( int argc, char* argv[] )
|
|||
|
||||
QskWindow window;
|
||||
window.setColor( Qt::gray );
|
||||
window.addItem( new Box() );
|
||||
window.addItem( new TabView() );
|
||||
window.resize( 800, 600 );
|
||||
window.show();
|
||||
|
||||
|
|
|
@ -1,13 +1,22 @@
|
|||
/******************************************************************************
|
||||
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
||||
* This file may be used under the terms of the QSkinny License, Version 1.0
|
||||
*****************************************************************************/
|
||||
|
||||
#include "QskGradientMaterial.h"
|
||||
#include "QskFunctions.h"
|
||||
#include "QskRgbValue.h"
|
||||
|
||||
#include <qcoreapplication.h>
|
||||
|
||||
QSK_QT_PRIVATE_BEGIN
|
||||
#include <private/qrhi_p.h>
|
||||
#include <private/qdrawhelper_p.h>
|
||||
#include <private/qsgplaintexture_p.h>
|
||||
QSK_QT_PRIVATE_END
|
||||
|
||||
#include <cmath>
|
||||
|
||||
// RHI shaders are supported by Qt 5.15 and Qt 6.x
|
||||
#define SHADER_RHI
|
||||
|
||||
|
@ -23,106 +32,33 @@ QSK_QT_PRIVATE_END
|
|||
using RhiShader = QSGMaterialShader;
|
||||
#endif
|
||||
|
||||
/*
|
||||
The shaders for the gradient are implemented in the quickshapes module
|
||||
Beside them we do not need this module.
|
||||
*/
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
|
||||
|
||||
QSK_QT_PRIVATE_BEGIN
|
||||
#ifndef signals
|
||||
#define signals Q_SIGNALS
|
||||
#endif
|
||||
#include <private/qquickshape_p.h>
|
||||
QSK_QT_PRIVATE_END
|
||||
|
||||
static void QQuickShapes_initializeModule()
|
||||
{
|
||||
QQuickShapesModule::defineModule();
|
||||
}
|
||||
|
||||
#else
|
||||
extern void QQuickShapes_initializeModule();
|
||||
#endif
|
||||
|
||||
Q_CONSTRUCTOR_FUNCTION( QQuickShapes_initializeModule )
|
||||
|
||||
namespace
|
||||
{
|
||||
/*
|
||||
Qt offers QGradient compatible shaders in the quickshapes module.
|
||||
So why reimplementing the wheel ...
|
||||
|
||||
Those shaders ( f.e lineargradient.frag ) want to have a lookup table
|
||||
with the interpolated colors, being uploaded as a texture.
|
||||
A 1 dimensional 256x1 texture is how Chrome, Firefox, and Android render
|
||||
gradients - so let's do the same.
|
||||
*/
|
||||
class GradientImage : public QImage
|
||||
{
|
||||
public:
|
||||
GradientImage( const QGradientStops& stops )
|
||||
: QImage( 256, 1, QImage::Format_RGBA8888_Premultiplied )
|
||||
{
|
||||
constexpr int numColors = 256;
|
||||
auto colorTable = reinterpret_cast< uint* >( bits() );
|
||||
|
||||
int index1, index2;
|
||||
QRgb rgb1, rgb2;
|
||||
|
||||
index1 = index2 = qRound( stops[0].first * numColors );
|
||||
rgb1 = rgb2 = stops[0].second.rgba();
|
||||
|
||||
if ( index1 > 0 )
|
||||
{
|
||||
const auto v = value( rgb1 );
|
||||
|
||||
for ( int i = 0; i < index1; i++ )
|
||||
colorTable[i] = v;
|
||||
}
|
||||
|
||||
for ( int i = 1; i < stops.count(); i++ )
|
||||
{
|
||||
const auto& stop = stops[i];
|
||||
|
||||
index2 = qRound( stop.first * numColors );
|
||||
rgb2 = stop.second.rgba();
|
||||
|
||||
const auto n = index2 - index1;
|
||||
|
||||
for ( int j = 0; j < n; j++ )
|
||||
{
|
||||
const auto rgb = QskRgb::interpolated( rgb1, rgb2, qreal( j ) / n );
|
||||
colorTable[ index1 + j] = value( rgb );
|
||||
}
|
||||
|
||||
index1 = index2;
|
||||
rgb1 = rgb2;
|
||||
}
|
||||
|
||||
if ( index1 < numColors - 1 )
|
||||
{
|
||||
const auto v = value( rgb1 );
|
||||
|
||||
for ( int i = index1; i < numColors ; i++ )
|
||||
colorTable[i] = v;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
inline uint value( const QRgb rgb ) const
|
||||
{
|
||||
return ARGB2RGBA( qPremultiply( rgb ) );
|
||||
}
|
||||
};
|
||||
|
||||
class GradientTexture : public QSGPlainTexture
|
||||
{
|
||||
public:
|
||||
GradientTexture( const QGradientStops& stops, QGradient::Spread spread )
|
||||
{
|
||||
setImage( GradientImage( stops ) );
|
||||
#if 1
|
||||
/*
|
||||
Once we got rid of QGradient we will have QskGradientStops
|
||||
( like in the gradients branch ). For the moment we have to copy
|
||||
*/
|
||||
|
||||
QskGradientStops qskStops;
|
||||
qskStops.reserve( stops.size() );
|
||||
|
||||
for ( const auto& s : stops )
|
||||
qskStops += QskGradientStop( s.first, s.second );
|
||||
#endif
|
||||
/*
|
||||
Qt creates tables of 1024 colors, while Chrome, Firefox, and Android
|
||||
seem to use 256 colors only ( according to maybe outdated sources
|
||||
from the internet ),
|
||||
*/
|
||||
|
||||
|
||||
setImage( QskRgb::colorTable( 256, qskStops ) );
|
||||
|
||||
const auto wrapMode = this->wrapMode( spread );
|
||||
|
||||
|
@ -183,10 +119,9 @@ namespace
|
|||
s_instance = new TextureCache();
|
||||
|
||||
/*
|
||||
For OpenGL we coud fiddle around with QOpenGLSharedResource
|
||||
while with RHI we would have QRhi::addCleanupCallback
|
||||
|
||||
But let's keep things simple for the moment. TODO ...
|
||||
For RHI we have QRhi::addCleanupCallback, but with
|
||||
OpenGL we have to fiddle around with QOpenGLSharedResource
|
||||
So let's keep things simple for the moment. TODO ...
|
||||
*/
|
||||
qAddPostRoutine( cleanup );
|
||||
}
|
||||
|
@ -209,6 +144,17 @@ namespace
|
|||
{
|
||||
texture = new GradientTexture( stops, spread );
|
||||
m_hashTable[ key ] = texture;
|
||||
|
||||
if ( rhi != nullptr )
|
||||
{
|
||||
auto myrhi = ( QRhi* )rhi;
|
||||
|
||||
if ( !m_rhiTable.contains( myrhi ) )
|
||||
{
|
||||
myrhi->addCleanupCallback( TextureCache::cleanupRhi );
|
||||
m_rhiTable += myrhi;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return texture;
|
||||
|
@ -220,7 +166,29 @@ namespace
|
|||
delete instance();
|
||||
}
|
||||
|
||||
static void cleanupRhi( const QRhi *rhi )
|
||||
{
|
||||
auto cache = instance();
|
||||
|
||||
auto& table = cache->m_hashTable;
|
||||
for ( auto it = table.begin(); it != table.end(); )
|
||||
{
|
||||
if ( it.key().rhi == rhi )
|
||||
{
|
||||
delete it.value();
|
||||
it = table.erase( it );
|
||||
}
|
||||
else
|
||||
{
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
cache->m_rhiTable.removeAll( rhi );
|
||||
}
|
||||
|
||||
QHash< TextureHashKey, GradientTexture* > m_hashTable;
|
||||
QVector< const QRhi* > m_rhiTable;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -269,7 +237,7 @@ namespace
|
|||
public:
|
||||
void setShaderFiles( const char* name )
|
||||
{
|
||||
static const QString root( ":/qt-project.org/shapes/shaders/" );
|
||||
static const QString root( ":/qskinny/shaders/" );
|
||||
|
||||
setShaderSourceFile( QOpenGLShader::Vertex, root + name + ".vert" );
|
||||
setShaderSourceFile( QOpenGLShader::Fragment, root + name + ".frag" );
|
||||
|
@ -320,7 +288,7 @@ namespace
|
|||
public:
|
||||
void setShaderFiles( const char* name )
|
||||
{
|
||||
static const QString root( ":/qt-project.org/shapes/shaders_ng/" );
|
||||
static const QString root( ":/qskinny/shaders/" );
|
||||
|
||||
setShaderFileName( VertexStage, root + name + ".vert.qsb" );
|
||||
setShaderFileName( FragmentStage, root + name + ".frag.qsb" );
|
||||
|
@ -359,29 +327,35 @@ namespace
|
|||
{
|
||||
}
|
||||
|
||||
bool setGradient( const QLinearGradient* gradient )
|
||||
bool setGradient( const QRectF& rect, const QLinearGradient& gradient )
|
||||
{
|
||||
bool changed = false;
|
||||
|
||||
if ( gradient->stops() != stops() )
|
||||
if ( gradient.stops() != stops() )
|
||||
{
|
||||
setStops( gradient->stops() );
|
||||
setStops( gradient.stops() );
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if ( gradient->spread() != spread() )
|
||||
if ( gradient.spread() != spread() )
|
||||
{
|
||||
setSpread( gradient->spread() );
|
||||
setSpread( gradient.spread() );
|
||||
changed = true;
|
||||
}
|
||||
|
||||
const QVector2D start( gradient->start() );
|
||||
const QVector2D stop( gradient->finalStop() );
|
||||
#if 0
|
||||
QTransform transform( rect.width(), 0, 0, rect.height(), rect.x(), rect.y());
|
||||
#endif
|
||||
|
||||
if ( m_start != start || m_stop != stop )
|
||||
const QVector4D gradientRect(
|
||||
rect.left() + gradient.start().x() * rect.width(),
|
||||
rect.top() + gradient.start().y() * rect.height(),
|
||||
gradient.finalStop().x() * rect.width(),
|
||||
gradient.finalStop().y() * rect.height() );
|
||||
|
||||
if ( m_gradientRect != gradientRect )
|
||||
{
|
||||
m_start = start;
|
||||
m_stop = stop;
|
||||
m_gradientRect = gradientRect;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
|
@ -398,7 +372,7 @@ namespace
|
|||
{
|
||||
const auto mat = static_cast< const LinearMaterial* >( other );
|
||||
|
||||
if ( ( m_start != mat->m_start ) || ( m_stop != mat->m_stop ) )
|
||||
if ( m_gradientRect != mat->m_gradientRect )
|
||||
return QSGMaterial::compare( other );
|
||||
else
|
||||
return GradientMaterial::compare( other );
|
||||
|
@ -406,8 +380,7 @@ namespace
|
|||
|
||||
QSGMaterialShader* createShader() const override;
|
||||
|
||||
QVector2D m_start;
|
||||
QVector2D m_stop;
|
||||
QVector4D m_gradientRect;
|
||||
};
|
||||
|
||||
#ifdef SHADER_GL
|
||||
|
@ -416,28 +389,23 @@ namespace
|
|||
public:
|
||||
LinearShaderGL()
|
||||
{
|
||||
setShaderFiles( "lineargradient" );
|
||||
setShaderFiles( "gradientlinear" );
|
||||
}
|
||||
|
||||
void initialize() override
|
||||
{
|
||||
GradientShaderGL::initialize();
|
||||
|
||||
m_startId = program()->uniformLocation( "gradStart" );
|
||||
m_stopId = program()->uniformLocation( "gradEnd" );
|
||||
m_rectId = program()->uniformLocation( "rect" );
|
||||
}
|
||||
|
||||
void updateUniformValues( const GradientMaterial* newMaterial ) override
|
||||
{
|
||||
auto material = static_cast< const LinearMaterial* >( newMaterial );
|
||||
|
||||
program()->setUniformValue( m_startId, material->m_start );
|
||||
program()->setUniformValue( m_stopId, material->m_stop );
|
||||
program()->setUniformValue( m_rectId, material->m_gradientRect );
|
||||
}
|
||||
|
||||
private:
|
||||
int m_startId = -1;
|
||||
int m_stopId = -1;
|
||||
int m_rectId = -1;
|
||||
};
|
||||
#endif
|
||||
|
||||
|
@ -447,7 +415,7 @@ namespace
|
|||
public:
|
||||
LinearShaderRhi()
|
||||
{
|
||||
setShaderFiles( "lineargradient" );
|
||||
setShaderFiles( "gradientlinear" );
|
||||
}
|
||||
|
||||
bool updateUniformData( RenderState& state,
|
||||
|
@ -469,15 +437,9 @@ namespace
|
|||
changed = true;
|
||||
}
|
||||
|
||||
if ( matOld == nullptr || matNew->m_start != matOld->m_start )
|
||||
if ( matOld == nullptr || matNew->m_gradientRect != matOld->m_gradientRect )
|
||||
{
|
||||
memcpy( data + 64, &matNew->m_start, 8 );
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if ( matOld == nullptr || matNew->m_stop != matOld->m_stop )
|
||||
{
|
||||
memcpy( data + 72, &matNew->m_stop, 8 );
|
||||
memcpy( data + 64, &matNew->m_gradientRect, 16 );
|
||||
changed = true;
|
||||
}
|
||||
|
||||
|
@ -520,40 +482,35 @@ namespace
|
|||
return &type;
|
||||
}
|
||||
|
||||
bool setGradient( const QRadialGradient* gradient )
|
||||
bool setGradient( const QRectF& rect, const QRadialGradient& gradient )
|
||||
{
|
||||
bool changed = false;
|
||||
|
||||
if ( gradient->stops() != stops() )
|
||||
if ( gradient.stops() != stops() )
|
||||
{
|
||||
setStops( gradient->stops() );
|
||||
setStops( gradient.stops() );
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if ( gradient->spread() != spread() )
|
||||
if ( gradient.spread() != spread() )
|
||||
{
|
||||
setSpread( gradient->spread() );
|
||||
setSpread( gradient.spread() );
|
||||
changed = true;
|
||||
}
|
||||
|
||||
const QVector2D focalToCenter( gradient->center() - gradient->focalPoint() );
|
||||
const float centerRadius = gradient->centerRadius();
|
||||
const auto& center = gradient.center();
|
||||
const auto r = gradient.radius();
|
||||
|
||||
const QVector2D focalPoint( gradient->focalPoint() );
|
||||
const float focalRadius = gradient->focalRadius();
|
||||
const QVector2D pos(
|
||||
rect.left() + center.x() * rect.width(),
|
||||
rect.top() + center.y() * rect.height() );
|
||||
|
||||
if ( ( focalPoint != m_focalPoint ) || ( focalRadius != m_focalRadius ) )
|
||||
const QVector2D radius( r * rect.width(), r * rect.height() );
|
||||
|
||||
if ( ( pos != m_center ) || ( m_radius != radius ) )
|
||||
{
|
||||
m_focalPoint = focalPoint;
|
||||
m_focalRadius = focalRadius;
|
||||
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if ( ( focalToCenter != m_focalToCenter ) || ( m_centerRadius != centerRadius ) )
|
||||
{
|
||||
m_focalToCenter = focalToCenter;
|
||||
m_centerRadius = centerRadius;
|
||||
m_center = pos;
|
||||
m_radius = radius;
|
||||
|
||||
changed = true;
|
||||
}
|
||||
|
@ -565,10 +522,7 @@ namespace
|
|||
{
|
||||
const auto mat = static_cast< const RadialMaterial* >( other );
|
||||
|
||||
if ( ( m_focalPoint != mat->m_focalPoint )
|
||||
|| ( m_focalToCenter != mat->m_focalToCenter )
|
||||
|| qskFuzzyCompare( m_centerRadius, mat->m_centerRadius )
|
||||
|| qskFuzzyCompare( m_focalRadius, mat->m_focalRadius ) )
|
||||
if ( ( m_center != mat->m_center ) || ( m_radius != mat->m_radius ) )
|
||||
{
|
||||
return QSGMaterial::compare( other );
|
||||
}
|
||||
|
@ -580,10 +534,8 @@ namespace
|
|||
|
||||
QSGMaterialShader* createShader() const override;
|
||||
|
||||
QVector2D m_focalPoint;
|
||||
QVector2D m_focalToCenter;
|
||||
float m_centerRadius = 0.0;
|
||||
float m_focalRadius = 0.0;
|
||||
QVector2D m_center;
|
||||
QVector2D m_radius;
|
||||
};
|
||||
|
||||
#ifdef SHADER_GL
|
||||
|
@ -592,7 +544,7 @@ namespace
|
|||
public:
|
||||
RadialShaderGL()
|
||||
{
|
||||
setShaderFiles( "radialgradient" );
|
||||
setShaderFiles( "gradientradial" );
|
||||
}
|
||||
|
||||
void initialize() override
|
||||
|
@ -601,10 +553,8 @@ namespace
|
|||
|
||||
auto p = program();
|
||||
|
||||
m_focalPointId = p->uniformLocation( "translationPoint" );
|
||||
m_focalToCenterId = p->uniformLocation( "focalToCenter" );
|
||||
m_centerRadiusId = p->uniformLocation( "centerRadius" );
|
||||
m_focalRadiusId = p->uniformLocation( "focalRadius" );
|
||||
m_centerCoordId = p->uniformLocation( "centerCoord" );
|
||||
m_radiusId = p->uniformLocation( "radius" );
|
||||
}
|
||||
|
||||
void updateUniformValues( const GradientMaterial* newMaterial ) override
|
||||
|
@ -613,17 +563,13 @@ namespace
|
|||
|
||||
auto p = program();
|
||||
|
||||
p->setUniformValue( m_focalToCenterId, material->m_focalToCenter );
|
||||
p->setUniformValue( m_centerRadiusId, material->m_centerRadius);
|
||||
p->setUniformValue( m_focalRadiusId, material->m_focalRadius);
|
||||
p->setUniformValue( m_focalPointId, material->m_focalPoint);
|
||||
p->setUniformValue( m_centerCoordId, material->m_center );
|
||||
p->setUniformValue( m_radiusId, material->m_radius );
|
||||
}
|
||||
|
||||
private:
|
||||
int m_focalToCenterId = -1;
|
||||
int m_focalPointId = -1;
|
||||
int m_centerRadiusId = -1;
|
||||
int m_focalRadiusId = -1;
|
||||
int m_centerCoordId = -1;
|
||||
int m_radiusId = -1;
|
||||
};
|
||||
#endif
|
||||
|
||||
|
@ -633,7 +579,7 @@ namespace
|
|||
public:
|
||||
RadialShaderRhi()
|
||||
{
|
||||
setShaderFiles( "radialgradient" );
|
||||
setShaderFiles( "gradientradial" );
|
||||
}
|
||||
|
||||
bool updateUniformData( RenderState& state,
|
||||
|
@ -642,7 +588,7 @@ namespace
|
|||
auto matNew = static_cast< RadialMaterial* >( newMaterial );
|
||||
auto matOld = static_cast< RadialMaterial* >( oldMaterial );
|
||||
|
||||
Q_ASSERT( state.uniformData()->size() >= 92 );
|
||||
Q_ASSERT( state.uniformData()->size() >= 84 );
|
||||
|
||||
auto data = state.uniformData()->data();
|
||||
bool changed = false;
|
||||
|
@ -655,34 +601,22 @@ namespace
|
|||
changed = true;
|
||||
}
|
||||
|
||||
if ( matOld == nullptr || matNew->m_focalPoint != matOld->m_focalPoint )
|
||||
if ( matOld == nullptr || matNew->m_center != matOld->m_center )
|
||||
{
|
||||
memcpy( data + 64, &matNew->m_focalPoint, 8 );
|
||||
memcpy( data + 64, &matNew->m_center, 8 );
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if ( matOld == nullptr || matNew->m_focalToCenter != matOld->m_focalToCenter )
|
||||
if ( matOld == nullptr || matNew->m_radius != matOld->m_radius )
|
||||
{
|
||||
memcpy( data + 72, &matNew->m_focalToCenter, 8 );
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if ( matOld == nullptr || matNew->m_centerRadius != matOld->m_centerRadius )
|
||||
{
|
||||
memcpy( data + 80, &matNew->m_centerRadius, 4);
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if ( matOld == nullptr || matNew->m_focalRadius != matOld->m_focalRadius )
|
||||
{
|
||||
memcpy( data + 84, &matNew->m_focalRadius, 4 );
|
||||
memcpy( data + 72, &matNew->m_radius, 8 );
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if ( state.isOpacityDirty() )
|
||||
{
|
||||
const float opacity = state.opacity();
|
||||
memcpy( data + 88, &opacity, 4 );
|
||||
memcpy( data + 80, &opacity, 4 );
|
||||
|
||||
changed = true;
|
||||
}
|
||||
|
@ -719,23 +653,44 @@ namespace
|
|||
return &type;
|
||||
}
|
||||
|
||||
bool setGradient( const QConicalGradient* gradient )
|
||||
bool setGradient( const QRectF& rect, const QConicalGradient& gradient, qreal spanAngle )
|
||||
{
|
||||
bool changed = false;
|
||||
|
||||
if ( gradient->stops() != stops() )
|
||||
if ( gradient.stops() != stops() )
|
||||
{
|
||||
setStops( gradient->stops() );
|
||||
setStops( gradient.stops() );
|
||||
changed = true;
|
||||
}
|
||||
|
||||
const QVector2D center( gradient->center() );
|
||||
const float radians = -qDegreesToRadians( gradient->angle() );
|
||||
if ( gradient.spread() != spread() )
|
||||
{
|
||||
setSpread( gradient.spread() );
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if ( center != m_center || radians != m_radians )
|
||||
const QVector2D center(
|
||||
rect.left() + gradient.center().x() * rect.width(),
|
||||
rect.top() + gradient.center().y() * rect.height() );
|
||||
|
||||
// Angles as ratio of a rotation
|
||||
|
||||
float start = fmod( gradient.angle(), 360.0 ) / 360.0;
|
||||
if ( start < 0.0)
|
||||
start += 1.0;
|
||||
|
||||
const float span = fmod( spanAngle, 360.0 ) / 360.0;
|
||||
|
||||
if ( center != m_center )
|
||||
{
|
||||
m_center = center;
|
||||
m_radians = radians;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if ( ( start != m_start ) || ( span != m_span ) )
|
||||
{
|
||||
m_start = start;
|
||||
m_span = span;
|
||||
|
||||
changed = true;
|
||||
}
|
||||
|
@ -747,16 +702,21 @@ namespace
|
|||
{
|
||||
const auto mat = static_cast< const ConicMaterial* >( other );
|
||||
|
||||
if ( ( m_center != mat->m_center ) || qskFuzzyCompare( m_radians, mat->m_radians ) )
|
||||
if ( ( m_center != mat->m_center )
|
||||
|| qskFuzzyCompare( m_start, mat->m_start )
|
||||
|| qskFuzzyCompare( m_span, mat->m_span ) )
|
||||
{
|
||||
return QSGMaterial::compare( other );
|
||||
else
|
||||
}
|
||||
|
||||
return GradientMaterial::compare( other );
|
||||
}
|
||||
|
||||
QSGMaterialShader* createShader() const override;
|
||||
|
||||
QVector2D m_center;
|
||||
float m_radians = 0.0;
|
||||
float m_start = 0.0;
|
||||
float m_span = 1.0;
|
||||
};
|
||||
|
||||
#ifdef SHADER_GL
|
||||
|
@ -765,28 +725,31 @@ namespace
|
|||
public:
|
||||
ConicShaderGL()
|
||||
{
|
||||
setShaderFiles( "conicalgradient" );
|
||||
setShaderFiles( "gradientconic" );
|
||||
}
|
||||
|
||||
void initialize() override
|
||||
{
|
||||
GradientShaderGL::initialize();
|
||||
|
||||
m_radiansId = program()->uniformLocation( "angle" );
|
||||
m_centerPointId = program()->uniformLocation( "translationPoint" );
|
||||
m_centerCoordId = program()->uniformLocation( "centerCoord" );
|
||||
m_startId = program()->uniformLocation( "start" );
|
||||
m_spanId = program()->uniformLocation( "span" );
|
||||
}
|
||||
|
||||
void updateUniformValues( const GradientMaterial* newMaterial ) override
|
||||
{
|
||||
auto material = static_cast< const ConicMaterial* >( newMaterial );
|
||||
|
||||
program()->setUniformValue( m_radiansId, material->m_radians );
|
||||
program()->setUniformValue( m_centerPointId, material->m_center );
|
||||
program()->setUniformValue( m_centerCoordId, material->m_center );
|
||||
program()->setUniformValue( m_startId, material->m_start );
|
||||
program()->setUniformValue( m_spanId, material->m_span );
|
||||
}
|
||||
|
||||
private:
|
||||
int m_radiansId = -1;
|
||||
int m_centerPointId = -1;
|
||||
int m_centerCoordId = -1;
|
||||
int m_startId = -1;
|
||||
int m_spanId = -1;
|
||||
};
|
||||
#endif
|
||||
|
||||
|
@ -796,7 +759,7 @@ namespace
|
|||
public:
|
||||
ConicShaderRhi()
|
||||
{
|
||||
setShaderFiles( "conicalgradient" );
|
||||
setShaderFiles( "gradientconic" );
|
||||
}
|
||||
|
||||
bool updateUniformData( RenderState& state,
|
||||
|
@ -805,7 +768,7 @@ namespace
|
|||
auto matNew = static_cast< ConicMaterial* >( newMaterial );
|
||||
auto matOld = static_cast< ConicMaterial* >( oldMaterial );
|
||||
|
||||
Q_ASSERT( state.uniformData()->size() >= 80 );
|
||||
Q_ASSERT( state.uniformData()->size() >= 84 );
|
||||
|
||||
auto data = state.uniformData()->data();
|
||||
bool changed = false;
|
||||
|
@ -824,16 +787,22 @@ namespace
|
|||
changed = true;
|
||||
}
|
||||
|
||||
if ( matOld == nullptr || matNew->m_radians != matOld->m_radians )
|
||||
if ( matOld == nullptr || matNew->m_start != matOld->m_start )
|
||||
{
|
||||
memcpy( data + 72, &matNew->m_radians, 4 );
|
||||
memcpy( data + 72, &matNew->m_start, 4 );
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if ( matOld == nullptr || matNew->m_span != matOld->m_span )
|
||||
{
|
||||
memcpy( data + 76, &matNew->m_span, 4 );
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if ( state.isOpacityDirty() )
|
||||
{
|
||||
const float opacity = state.opacity();
|
||||
memcpy( data + 76, &opacity, 4 );
|
||||
memcpy( data + 80, &opacity, 4 );
|
||||
|
||||
changed = true;
|
||||
}
|
||||
|
@ -867,31 +836,42 @@ inline Material* qskEnsureMaterial( QskGradientMaterial* material )
|
|||
return static_cast< Material* >( material );
|
||||
}
|
||||
|
||||
bool QskGradientMaterial::updateGradient( const QGradient* gradient )
|
||||
bool QskGradientMaterial::updateGradient(
|
||||
const QRectF& rect, const QGradient* g, qreal extraValue )
|
||||
{
|
||||
Q_ASSERT( gradient && gradient->type() == m_gradientType );
|
||||
Q_ASSERT( g );
|
||||
|
||||
if ( gradient == nullptr || gradient->type() != m_gradientType )
|
||||
if ( g == nullptr )
|
||||
return false;
|
||||
|
||||
switch ( static_cast< int >( gradient->type() ) )
|
||||
auto& gradient = *g;
|
||||
|
||||
Q_ASSERT( gradient.type() == m_gradientType );
|
||||
|
||||
if ( gradient.type() != m_gradientType )
|
||||
return false;
|
||||
|
||||
switch ( static_cast< int >( gradient.type() ) )
|
||||
{
|
||||
case QGradient::LinearGradient:
|
||||
{
|
||||
auto material = static_cast< LinearMaterial* >( this );
|
||||
return material->setGradient( static_cast< const QLinearGradient* >( gradient ) );
|
||||
return material->setGradient( rect,
|
||||
*reinterpret_cast< const QLinearGradient* >( g ) );
|
||||
}
|
||||
|
||||
case QGradient::RadialGradient:
|
||||
{
|
||||
auto material = static_cast< RadialMaterial* >( this );
|
||||
return material->setGradient( static_cast< const QRadialGradient* >( gradient ) );
|
||||
return material->setGradient( rect,
|
||||
*reinterpret_cast< const QRadialGradient* >( g ) );
|
||||
}
|
||||
|
||||
case QGradient::ConicalGradient:
|
||||
{
|
||||
auto material = static_cast< ConicMaterial* >( this );
|
||||
return material->setGradient( static_cast< const QConicalGradient* >( gradient ) );
|
||||
return material->setGradient( rect,
|
||||
*reinterpret_cast< const QConicalGradient* >( g ), extraValue );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ class QSK_EXPORT QskGradientMaterial : public QSGMaterial
|
|||
public:
|
||||
static QskGradientMaterial* createMaterial( QGradient::Type );
|
||||
|
||||
bool updateGradient( const QGradient* );
|
||||
bool updateGradient( const QRectF&, const QGradient*, qreal );
|
||||
QGradient::Type gradientType() const;
|
||||
|
||||
const QGradientStops& stops() const;
|
||||
|
|
|
@ -71,7 +71,7 @@ static inline bool qskIsGradientVisible( const QGradient* gradient )
|
|||
{
|
||||
if ( gradient && gradient->type() != QGradient::NoGradient )
|
||||
{
|
||||
for ( const auto stop : gradient->stops() )
|
||||
for ( const auto& stop : gradient->stops() )
|
||||
{
|
||||
if ( stop.second.alpha() > 0 )
|
||||
return true;
|
||||
|
@ -166,7 +166,8 @@ void QskShapeNode::updateNode( const QPainterPath& path,
|
|||
}
|
||||
|
||||
void QskShapeNode::updateNode( const QPainterPath& path,
|
||||
const QTransform& transform, const QGradient* gradient )
|
||||
const QTransform& transform, const QRectF& rect,
|
||||
const QGradient* gradient, qreal extraValue )
|
||||
{
|
||||
Q_D( QskShapeNode );
|
||||
|
||||
|
@ -200,7 +201,7 @@ void QskShapeNode::updateNode( const QPainterPath& path,
|
|||
}
|
||||
|
||||
auto gradientMaterial = static_cast< QskGradientMaterial* >( material() );
|
||||
if ( gradientMaterial->updateGradient( gradient ) )
|
||||
if ( gradientMaterial->updateGradient( rect, gradient, extraValue ) )
|
||||
markDirty( QSGNode::DirtyMaterial );
|
||||
}
|
||||
|
||||
|
|
|
@ -20,8 +20,11 @@ class QSK_EXPORT QskShapeNode : public QSGGeometryNode
|
|||
public:
|
||||
QskShapeNode();
|
||||
|
||||
void updateNode( const QPainterPath&, const QTransform&, const QGradient* );
|
||||
void updateNode( const QPainterPath&, const QTransform&, const QColor& );
|
||||
void updateNode( const QPainterPath&, const QTransform&,
|
||||
const QRectF&, const QGradient*, qreal = 0.0 );
|
||||
|
||||
void updateNode( const QPainterPath&,
|
||||
const QTransform&, const QColor& );
|
||||
|
||||
private:
|
||||
Q_DECLARE_PRIVATE( QskShapeNode )
|
||||
|
|
|
@ -1,9 +1,26 @@
|
|||
<!DOCTYPE RCC>
|
||||
<RCC version="1.0">
|
||||
<qresource prefix="/qskinny/">
|
||||
|
||||
<file>shaders/boxshadow.vert.qsb</file>
|
||||
<file>shaders/boxshadow.frag.qsb</file>
|
||||
<file>shaders/boxshadow.vert</file>
|
||||
<file>shaders/boxshadow.frag</file>
|
||||
|
||||
<file>shaders/gradientconic.vert.qsb</file>
|
||||
<file>shaders/gradientconic.frag.qsb</file>
|
||||
<file>shaders/gradientconic.vert</file>
|
||||
<file>shaders/gradientconic.frag</file>
|
||||
|
||||
<file>shaders/gradientradial.vert.qsb</file>
|
||||
<file>shaders/gradientradial.frag.qsb</file>
|
||||
<file>shaders/gradientradial.vert</file>
|
||||
<file>shaders/gradientradial.frag</file>
|
||||
|
||||
<file>shaders/gradientlinear.vert.qsb</file>
|
||||
<file>shaders/gradientlinear.frag.qsb</file>
|
||||
<file>shaders/gradientlinear.vert</file>
|
||||
<file>shaders/gradientlinear.frag</file>
|
||||
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,32 @@
|
|||
#version 440
|
||||
|
||||
layout( location = 0 ) in vec2 coord;
|
||||
layout( location = 0 ) out vec4 fragColor;
|
||||
|
||||
layout( std140, binding = 0 ) uniform buf
|
||||
{
|
||||
mat4 matrix;
|
||||
vec2 centerCoord;
|
||||
float start;
|
||||
float span;
|
||||
float opacity;
|
||||
} ubuf;
|
||||
|
||||
layout( binding = 1 ) uniform sampler2D palette;
|
||||
|
||||
vec4 colorAt( highp float value )
|
||||
{
|
||||
return texture( palette, vec2( value, 0.0 ) );
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
/*
|
||||
angles as ratio of a rotation:
|
||||
start: [ 0.0, 1.0 [
|
||||
span: ] -1.0, 1.0 [
|
||||
*/
|
||||
|
||||
float v = sign( ubuf.span ) * ( atan( -coord.y, coord.x ) / 6.2831853 - ubuf.start );
|
||||
fragColor = colorAt( ( v - floor( v ) ) / abs( ubuf.span ) ) * ubuf.opacity;
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
#version 440
|
||||
|
||||
layout( location = 0 ) in vec4 vertexCoord;
|
||||
layout( location = 0 ) out vec2 coord;
|
||||
|
||||
layout( std140, binding = 0 ) uniform buf
|
||||
{
|
||||
mat4 matrix;
|
||||
vec2 centerCoord;
|
||||
float start;
|
||||
float span;
|
||||
float opacity;
|
||||
} ubuf;
|
||||
|
||||
out gl_PerVertex { vec4 gl_Position; };
|
||||
|
||||
void main()
|
||||
{
|
||||
coord = vertexCoord.xy - ubuf.centerCoord;
|
||||
gl_Position = ubuf.matrix * vertexCoord;
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
uniform sampler2D palette;
|
||||
uniform lowp float opacity;
|
||||
|
||||
uniform highp float start;
|
||||
uniform highp float span;
|
||||
|
||||
varying highp vec2 coord;
|
||||
|
||||
lowp vec4 colorAt( highp float value )
|
||||
{
|
||||
return texture2D( palette, vec2( value, 0.0 ) );
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
/*
|
||||
angles as ratio of a rotation:
|
||||
start: [ 0.0, 1.0 [
|
||||
span: ] -1.0, 1.0 [
|
||||
*/
|
||||
|
||||
highp float v = sign( span ) * ( atan( -coord.y, coord.x ) / 6.2831853 - start );
|
||||
gl_FragColor = colorAt( ( v - floor( v ) ) / abs( span ) ) * opacity;
|
||||
}
|
Binary file not shown.
|
@ -0,0 +1,12 @@
|
|||
attribute vec4 vertexCoord;
|
||||
|
||||
uniform mat4 matrix;
|
||||
uniform vec2 centerCoord;
|
||||
|
||||
varying vec2 coord;
|
||||
|
||||
void main()
|
||||
{
|
||||
coord = vertexCoord.xy - centerCoord;
|
||||
gl_Position = matrix * vertexCoord;
|
||||
}
|
Binary file not shown.
|
@ -0,0 +1,23 @@
|
|||
#version 440
|
||||
|
||||
layout( location = 0 ) in float colorIndex;
|
||||
layout( location = 0 ) out vec4 fragColor;
|
||||
|
||||
layout( std140, binding = 0 ) uniform buf
|
||||
{
|
||||
mat4 matrix;
|
||||
vec4 rect;
|
||||
float opacity;
|
||||
} ubuf;
|
||||
|
||||
layout( binding = 1 ) uniform sampler2D palette;
|
||||
|
||||
vec4 colorAt( float value )
|
||||
{
|
||||
return texture( palette, vec2( value, 0.0 ) );
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
fragColor = colorAt( colorIndex ) * ubuf.opacity;
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
#version 440
|
||||
|
||||
layout( location = 0 ) in vec4 vertexCoord;
|
||||
layout( location = 0 ) out float colorIndex;
|
||||
|
||||
layout( std140, binding = 0 ) uniform buf
|
||||
{
|
||||
mat4 matrix;
|
||||
vec4 rect;
|
||||
float opacity;
|
||||
} ubuf;
|
||||
|
||||
out gl_PerVertex { vec4 gl_Position; };
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 l = vertexCoord.xy - ubuf.rect.xy;
|
||||
vec2 size = ubuf.rect.zw;
|
||||
|
||||
colorIndex = dot( l, size ) / dot( size, size );
|
||||
gl_Position = ubuf.matrix * vertexCoord;
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
uniform sampler2D palette;
|
||||
uniform highp float opacity;
|
||||
|
||||
varying highp float colorIndex;
|
||||
|
||||
lowp vec4 colorAt( float value )
|
||||
{
|
||||
return texture2D( palette, vec2( value, 0.0 ) );
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_FragColor = colorAt( colorIndex ) * opacity;
|
||||
}
|
Binary file not shown.
|
@ -0,0 +1,15 @@
|
|||
attribute vec4 vertexCoord;
|
||||
|
||||
uniform mat4 matrix;
|
||||
uniform vec4 rect;
|
||||
|
||||
varying float colorIndex;
|
||||
|
||||
void main()
|
||||
{
|
||||
highp vec2 l = vertexCoord.xy - rect.xy;
|
||||
highp vec2 size = rect.zw;
|
||||
|
||||
colorIndex = dot( l, size ) / dot( size, size );
|
||||
gl_Position = matrix * vertexCoord;
|
||||
}
|
Binary file not shown.
|
@ -0,0 +1,24 @@
|
|||
#version 440
|
||||
|
||||
layout( location = 0 ) in vec2 coord;
|
||||
layout( location = 0 ) out vec4 fragColor;
|
||||
|
||||
layout( std140, binding = 0 ) uniform buf
|
||||
{
|
||||
mat4 matrix;
|
||||
vec2 centerCoord;
|
||||
vec2 radius;
|
||||
float opacity;
|
||||
} ubuf;
|
||||
|
||||
layout( binding = 1 ) uniform sampler2D palette;
|
||||
|
||||
vec4 colorAt( float value )
|
||||
{
|
||||
return texture( palette, vec2( value, 0.0 ) );
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
fragColor = colorAt( length( coord / ubuf.radius ) ) * ubuf.opacity;
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
#version 440
|
||||
|
||||
layout( location = 0 ) in vec4 vertexCoord;
|
||||
layout( location = 0 ) out vec2 coord;
|
||||
|
||||
layout( std140, binding = 0 ) uniform buf
|
||||
{
|
||||
mat4 matrix;
|
||||
vec2 centerCoord;
|
||||
vec2 radius;
|
||||
float opacity;
|
||||
} ubuf;
|
||||
|
||||
out gl_PerVertex { vec4 gl_Position; };
|
||||
|
||||
void main()
|
||||
{
|
||||
coord = vertexCoord.xy - ubuf.centerCoord;
|
||||
gl_Position = ubuf.matrix * vertexCoord;
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
uniform sampler2D palette;
|
||||
uniform lowp float opacity;
|
||||
|
||||
uniform highp vec2 radius;
|
||||
|
||||
varying highp vec2 coord;
|
||||
|
||||
lowp vec4 colorAt( highp float value )
|
||||
{
|
||||
return texture2D( palette, vec2( value, 0.0 ) );
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_FragColor = colorAt( length( coord / radius ) ) * opacity;
|
||||
}
|
Binary file not shown.
|
@ -0,0 +1,12 @@
|
|||
attribute vec4 vertexCoord;
|
||||
|
||||
uniform mat4 matrix;
|
||||
uniform vec2 centerCoord;
|
||||
|
||||
varying vec2 coord;
|
||||
|
||||
void main()
|
||||
{
|
||||
coord = vertexCoord.xy - centerCoord;
|
||||
gl_Position = matrix * vertexCoord;
|
||||
}
|
Binary file not shown.
|
@ -1,4 +1,18 @@
|
|||
#! /bin/sh
|
||||
|
||||
qsb --glsl 100es,120,150 --hlsl 50 --msl 12 -b -o boxshadow.vert.qsb boxshadow-vulkan.vert
|
||||
qsb --glsl 100es,120,150 --hlsl 50 --msl 12 -b -o boxshadow.frag.qsb boxshadow-vulkan.frag
|
||||
function qsbcompile {
|
||||
qsbfile=`echo $1 | sed 's/-vulkan//'`
|
||||
qsb --glsl 100es,120,150 --hlsl 50 --msl 12 -b -o ${qsbfile}.qsb $1
|
||||
}
|
||||
|
||||
qsbcompile boxshadow-vulkan.vert
|
||||
qsbcompile boxshadow-vulkan.frag
|
||||
|
||||
qsbcompile gradientconic-vulkan.vert
|
||||
qsbcompile gradientconic-vulkan.frag
|
||||
|
||||
qsbcompile gradientradial-vulkan.vert
|
||||
qsbcompile gradientradial-vulkan.frag
|
||||
|
||||
qsbcompile gradientlinear-vulkan.vert
|
||||
qsbcompile gradientlinear-vulkan.frag
|
||||
|
|
|
@ -3,12 +3,6 @@ TARGET = $$qskLibraryTarget(qskinny)
|
|||
|
||||
QT += quick quick-private
|
||||
|
||||
# We need quickshapes for the shaders for the gradients only,
|
||||
# As those shaders are more or less trivial # it might be better
|
||||
# to implement our own shaders to get rid of this extra module dependency
|
||||
|
||||
QT += quickshapes-private
|
||||
|
||||
greaterThan( QT_MAJOR_VERSION, 5 ) {
|
||||
QT += opengl-private
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue