new QskGradient

This commit is contained in:
Uwe Rathmann 2022-10-31 14:42:08 +01:00
parent 38bc3286cd
commit ad67d035f3
37 changed files with 730 additions and 574 deletions

View File

@ -10,6 +10,21 @@
#include <QskBoxShapeMetrics.h>
#include <QskHctColor.h>
#include <QskRgbValue.h>
#include <QskLinearGradient.h>
static inline void setStartStop( Box::FillType type, QskLinearGradient& gradient )
{
qreal x1 = 0.0, y1 = 0.0, x2 = 0.0, y2 = 0.0;
if ( type != Box::Horizontal )
y2 = 1.0;
if ( type != Box::Vertical )
x2 = 1.0;
gradient.setStart( x1, y1 );
gradient.setStop( x2, y2 );
}
Box::Box( QQuickItem* parentItem )
: QskBox( parentItem )
@ -20,67 +35,88 @@ Box::Box( QQuickItem* parentItem )
setBoxShapeHint( QskBox::Panel, QskBoxShapeMetrics() );
setBoxBorderMetricsHint( QskBox::Panel, QskBoxBorderMetrics() );
setBoxBorderColorsHint( QskBox::Panel, QskBoxBorderColors() );
setGradientHint( QskBox::Panel, QskGradient() );
setPanelGradient( QskGradient() );
}
void Box::setBackground( FillType type, QGradient::Preset preset, bool inverted )
void Box::setWebGradient( FillType type, QGradient::Preset preset, bool inverted )
{
if ( type == Unfilled )
{
setGradient( QskGradient() );
setPanelGradient( QskGradient() );
return;
}
QskGradient gradient( preset );
QskLinearGradient gradient( preset );
if ( type == Solid )
{
const auto color = QskRgb::interpolated(
gradient.startColor(), gradient.endColor(), 0.5 );
setGradient( QskGradient( color ) );
gradient.setStops( color );
}
else
{
const auto orientation =
static_cast< QskGradient::Orientation >( type - 2 );
gradient.setOrientation( orientation );
setStartStop( type, gradient );
if ( inverted )
gradient.reverse();
if ( inverted )
gradient.reverse();
setGradient( gradient );
}
setPanelGradient( gradient );
}
void Box::setBackground( FillType type, const QRgb base, bool inverted )
void Box::setTonalGradient( FillType type, const QRgb base, bool inverted )
{
if ( type == Unfilled )
{
setGradient( QskGradient() );
setPanelGradient( QskGradient() );
return;
}
const QskHctColor htcColor( base );
QskLinearGradient gradient;
const QskHctColor htcColor( base );
if ( type == Solid )
{
setGradient( htcColor.toned( 50 ).rgb() );
gradient.setStops( htcColor.toned( 50 ).rgb() );
}
else
else if ( type != Unfilled )
{
const auto dark = htcColor.toned( 40 ).rgb();
const auto light = htcColor.toned( 70 ).rgb();
const auto orientation =
static_cast< QskGradient::Orientation >( type - 2 );
if ( inverted )
setGradient( orientation, dark, light );
else
setGradient( orientation, light, dark );
gradient.setStops( htcColor.toned( 70 ).rgb(),
htcColor.toned( 40 ).rgb() );
}
setStartStop( type, gradient );
if ( inverted )
gradient.reverse();
setPanelGradient( gradient );
}
void Box::setTonalPalette( FillType type, const QRgb base )
{
if ( type == Unfilled || type == Solid )
{
setTonalGradient( type, base );
return;
}
QskLinearGradient gradient;
setStartStop( type, gradient );
{
const QskHctColor hctColor( base );
QVector< QRgb > colors;
colors.reserve( 10 );
for ( int i = 0; i < 10; i++ )
colors += hctColor.toned( 90 - i * 7 ).rgb();
gradient.setStops( qskBuildGradientStops( colors, true ) );
}
setPanelGradient( gradient );
}
void Box::setBorder( BorderType type, const QRgb base )
@ -165,26 +201,30 @@ void Box::setBorderWidth( int width )
void Box::setGradient( QRgb rgb )
{
setGradient( QskGradient( QColor::fromRgba( rgb ) ) );
setGradient( QColor::fromRgba( rgb ) );
}
void Box::setGradient( Qt::GlobalColor color )
{
setGradient( QskGradient( color ) );
setGradient( QColor( color ) );
}
void Box::setGradient( const QColor& color )
{
setGradient( QskGradient( color ) );
setPanelGradient( QskLinearGradient( color ) );
}
void Box::setGradient( QskGradient::Orientation orientation,
void Box::setGradient( FillType fillType,
const QColor& color1, const QColor& color2 )
{
setGradient( QskGradient( orientation, color1, color2 ) );
QskGradientStops stops;
stops += QskGradientStop( 0.0, color1 );
stops += QskGradientStop( 1.0, color2 );
setGradient( fillType, stops );
}
void Box::setGradient( QskGradient::Orientation orientation,
void Box::setGradient( FillType fillType,
const QColor& color1, const QColor& color2, const QColor& color3 )
{
QskGradientStops stops;
@ -192,24 +232,18 @@ void Box::setGradient( QskGradient::Orientation orientation,
stops += QskGradientStop( 0.5, color2 );
stops += QskGradientStop( 1.0, color3 );
setGradient( QskGradient( orientation, stops ) );
setGradient( fillType, stops );
}
void Box::setGradient( const QskGradient& gradient )
void Box::setGradient( FillType fillType, const QskGradientStops& stops )
{
QskLinearGradient gradient( stops );
setStartStop( fillType, gradient );
setPanelGradient( gradient );
}
void Box::setPanelGradient( const QskGradient& gradient )
{
setGradientHint( QskBox::Panel, gradient );
}
void Box::setGradient(
const QskGradient::Orientation orientation, const QRgb base )
{
const QskHctColor hctColor( base );
QVector< QRgb > colors;
colors.reserve( 10 );
for ( int i = 0; i < 10; i++ )
colors += hctColor.toned( 90 - i * 7 ).rgb();
setGradient( QskGradient( orientation, qskBuildGradientStops( colors, true ) ) );
}

View File

@ -31,9 +31,6 @@ class Box : public QskBox
Box( QQuickItem* parentItem = nullptr );
void setBackground( FillType, QRgb, bool inverted = false );
void setBackground( FillType, QGradient::Preset, bool inverted = false );
void setBorder( BorderType type, QRgb );
void setShape( const QskBoxShapeMetrics& );
@ -51,11 +48,15 @@ class Box : public QskBox
void setGradient( Qt::GlobalColor );
void setGradient( const QColor& );
void setGradient( QskGradient::Orientation, const QColor&, const QColor& );
void setGradient( FillType, const QColor&, const QColor& );
void setGradient( FillType, const QColor&, const QColor&, const QColor& );
void setGradient( FillType, const QskGradientStops& );
void setGradient( QskGradient::Orientation,
const QColor&, const QColor&, const QColor& );
void setTonalGradient( FillType, QRgb, bool inverted = false );
void setWebGradient( FillType, QGradient::Preset, bool inverted = false );
void setGradient( const QskGradient& );
void setGradient( const QskGradient::Orientation, QRgb );
void setTonalPalette( FillType, QRgb );
private:
void setPanelGradient( const QskGradient& );
};

View File

@ -14,7 +14,6 @@
#include <QskBoxBorderColors.h>
#include <QskBoxBorderMetrics.h>
#include <QskBoxShapeMetrics.h>
#include <QskGradient.h>
#include <QskRgbValue.h>
#include <QskObjectCounter.h>
@ -75,7 +74,7 @@ static void addTestRectangle( QskLinearBox* parent )
shape.setRadius( Qt::TopRightCorner, 70 );
box->setShape( shape );
box->setGradient( QskGradient::Diagonal, QskRgb::DodgerBlue );
box->setTonalPalette( Box::Diagonal, QskRgb::DodgerBlue );
}
static void addRectangles1( QskLinearBox* parent )
@ -84,7 +83,7 @@ static void addRectangles1( QskLinearBox* parent )
Box::Horizontal, Box::Vertical, Box::Diagonal } )
{
auto* rectangle = new MyRectangle( parent );
rectangle->setBackground( type, QskRgb::Teal );
rectangle->setTonalGradient( type, QskRgb::Teal );
}
}
@ -95,7 +94,7 @@ static void addRectangles2( QskLinearBox* parent )
{
auto* rectangle = new MyRectangle( parent );
rectangle->setBorder( Box::Flat, QskRgb::SaddleBrown );
rectangle->setBackground( type, QGradient::SunnyMorning );
rectangle->setWebGradient( type, QGradient::SunnyMorning );
}
}
@ -113,19 +112,19 @@ static void addRectangles3( QskLinearBox* parent )
box = new MyRectangle( parent );
box->setBorder( Box::Sunken1, borderTheme );
box->setGradient( QskGradient::Diagonal, Grey400, Grey500 );
box->setGradient( Box::Diagonal, Grey400, Grey500 );
box = new MyRectangle( parent );
box->setBorder( Box::Raised2, borderTheme );
box->setGradient( QskGradient::Vertical, Grey400, Grey500 );
box->setGradient( Box::Vertical, Grey400, Grey500 );
box = new MyRectangle( parent );
box->setBorder( Box::Raised2, borderTheme );
box->setBackground( Box::Vertical, QGradient::RiverCity, true );
box->setWebGradient( Box::Vertical, QGradient::RiverCity, true );
box = new MyRectangle( parent );
box->setBorder( Box::Sunken2, borderTheme );
box->setBackground( Box::Vertical, QGradient::RiverCity, false );
box->setWebGradient( Box::Vertical, QGradient::RiverCity, false );
}
static void addRectangles4( QskLinearBox* parent )
@ -134,7 +133,7 @@ static void addRectangles4( QskLinearBox* parent )
Box::Horizontal, Box::Vertical, Box::Diagonal } )
{
auto* box = new MyRoundedRectangle( parent );
box->setBackground( type, QskRgb::OrangeRed );
box->setTonalGradient( type, QskRgb::OrangeRed );
}
}
@ -145,7 +144,7 @@ static void addRectangles5( QskLinearBox* parent )
{
auto* box = new MyRoundedRectangle( parent );
box->setBorder( Box::Flat, QskRgb::RoyalBlue );
box->setBackground( type, QskRgb::DeepPink );
box->setTonalGradient( type, QskRgb::DeepPink );
}
}
@ -163,19 +162,19 @@ static void addRectangles6( QskLinearBox* parent )
box = new MyRoundedRectangle( parent );
box->setBorder( Box::Sunken1, borderTheme );
box->setGradient( QskGradient::Diagonal, Grey400, Grey500 );
box->setGradient( Box::Diagonal, Grey400, Grey500 );
box = new MyRoundedRectangle( parent );
box->setBorder( Box::Raised2, borderTheme );
box->setGradient( QskGradient::Vertical, Grey400, Grey500 );
box->setGradient( Box::Vertical, Grey400, Grey500 );
box = new MyRoundedRectangle( parent );
box->setBorder( Box::Raised2, borderTheme );
box->setGradient( QskGradient::Vertical, Lime300, Lime600 );
box->setGradient( Box::Vertical, Lime300, Lime600 );
box = new MyRoundedRectangle( parent );
box->setBorder( Box::Sunken2, borderTheme );
box->setGradient( QskGradient::Vertical, Lime600, Lime300 );
box->setGradient( Box::Vertical, Lime600, Lime300 );
}
static void addRectangles7( QskLinearBox* parent )
@ -184,7 +183,7 @@ static void addRectangles7( QskLinearBox* parent )
Box::Horizontal, Box::Vertical, Box::Diagonal } )
{
auto* box = new MyEllipse( parent );
box->setBackground( type, QskRgb::SlateGrey );
box->setTonalGradient( type, QskRgb::SlateGrey );
}
}
@ -195,7 +194,7 @@ static void addRectangles8( QskLinearBox* parent )
{
auto* box = new MyEllipse( parent );
box->setBorder( Box::Flat, QskRgb::RoyalBlue );
box->setBackground( type, QskRgb::FireBrick );
box->setTonalGradient( type, QskRgb::FireBrick );
}
}
@ -213,53 +212,60 @@ static void addRectangles9( QskLinearBox* parent )
box = new MyEllipse( parent );
box->setBorder( Box::Sunken1, borderTheme );
box->setGradient( QskGradient::Diagonal, Grey400, Grey500 );
box->setGradient( Box::Diagonal, Grey400, Grey500 );
box = new MyEllipse( parent );
box->setBorder( Box::Raised2, borderTheme );
box->setGradient( QskGradient::Vertical, Grey400, Grey500 );
box->setGradient( Box::Vertical, Grey400, Grey500 );
box = new MyEllipse( parent );
box->setBorder( Box::Raised2, borderTheme );
box->setGradient( QskGradient::Vertical, Lime200, Lime600 );
box->setGradient( Box::Vertical, Lime200, Lime600 );
box = new MyEllipse( parent );
box->setBorder( Box::Sunken2, borderTheme );
box->setGradient( QskGradient::Vertical, Lime600, Lime200 );
box->setGradient( Box::Vertical, Lime600, Lime200 );
}
static void addRectangles10( QskLinearBox* parent )
{
QColor borderTheme( "Indigo" );
using namespace QskRgb;
QColor borderTheme( Indigo );
// borderTheme.setAlpha( 100 );
QskGradientStops stops;
stops += QskGradientStop( 0.0, DeepPink );
stops += QskGradientStop( 0.5, DarkOrange );
stops += QskGradientStop( 1.0, HotPink );
Box* box;
box = new Box( parent );
box->setGradient( QskGradient::Horizontal, "DeepPink", "DarkOrange", "HotPink" );
box->setGradient( Box::Horizontal, stops );
box = new Box( parent );
box->setBorderWidth( 10 );
box->setBorderGradient( borderTheme );
box->setGradient( QskGradient::Diagonal, "DeepPink", "DarkOrange", "HotPink" );
box->setGradient( Box::Diagonal, stops );
box = new Box( parent );
box->setShape( 100, Qt::RelativeSize );
box->setBorderWidth( 5 );
box->setBorderGradient( borderTheme );
box->setGradient( QskGradient::Vertical, "DeepPink", "DarkOrange", "HotPink" );
box->setGradient( Box::Vertical, stops );
box = new Box( parent );
box->setShape( 100, Qt::RelativeSize );
box->setBorderWidth( 5 );
box->setBorderGradient( borderTheme );
box->setGradient( QskGradient::Diagonal, "DeepPink", "DarkOrange", "HotPink" );
box->setGradient( Box::Diagonal, stops );
box = new Box( parent );
box->setShape( 100, Qt::RelativeSize );
box->setBorderWidth( 5, 20, 30, 5 );
box->setBorderGradient( borderTheme );
box->setGradient( QskGradient::Vertical, "DeepPink", "DarkOrange", "HotPink" );
box->setGradient( Box::Vertical, stops );
}
static void addRectangles11( QskLinearBox* parent )
@ -279,111 +285,109 @@ static void addRectangles11( QskLinearBox* parent )
bw[ i - 1 ] = 0;
box->setBorderWidth( bw[ 0 ], bw[ 1 ], bw[ 2 ], bw[ 3 ] );
box->setBackground( fillType[ i ], QskRgb::Sienna, i >= 3 );
box->setTonalGradient( fillType[ i ], QskRgb::Sienna, i >= 3 );
}
}
static void addRectangles12( QskLinearBox* parent )
{
for ( auto orientation : { QskGradient::Vertical,
QskGradient::Horizontal, QskGradient::Diagonal } )
for ( auto fillType : { Box::Vertical, Box::Horizontal, Box::Diagonal } )
{
auto* box = new Box( parent );
box->setBorderWidth( 0 );
box->setGradient( orientation, QskRgb::LightSlateGray );
box->setTonalPalette( fillType, QskRgb::LightSlateGray );
}
for ( auto orientation : { QskGradient::Vertical, QskGradient::Diagonal } )
for ( auto fillType : { Box::Vertical, Box::Diagonal } )
{
auto* box = new Box( parent );
box->setBorder( Box::Flat, QskRgb::OrangeRed );
box->setGradient( orientation, QskRgb::DodgerBlue );
box->setTonalPalette( fillType, QskRgb::DodgerBlue );
}
for ( auto orientation : { QskGradient::Vertical,
QskGradient::Horizontal, QskGradient::Diagonal } )
for ( auto fillType : { Box::Vertical, Box::Horizontal, Box::Diagonal } )
{
auto* box = new Box( parent );
box->setBorderWidth( 0 );
box->setShape( 30, 40, Qt::RelativeSize );
box->setGradient( orientation, QskRgb::LightSlateGray );
box->setTonalPalette( fillType, QskRgb::LightSlateGray );
}
for ( auto orientation : { QskGradient::Vertical, QskGradient::Diagonal } )
for ( auto fillType : { Box::Vertical, Box::Diagonal } )
{
auto* box = new Box( parent );
box->setBorder( Box::Flat, QskRgb::OrangeRed );
box->setShape( 30, 40, Qt::RelativeSize );
box->setGradient( orientation, QskRgb::DodgerBlue );
box->setTonalPalette( fillType, QskRgb::DodgerBlue );
}
for ( auto orientation : { QskGradient::Vertical,
QskGradient::Horizontal, QskGradient::Diagonal } )
for ( auto fillType : { Box::Vertical, Box::Horizontal, Box::Diagonal } )
{
auto* box = new Box( parent );
box->setBorderWidth( 0 );
box->setShape( 100, 100, Qt::RelativeSize );
box->setGradient( orientation, QskRgb::LightSlateGray );
box->setTonalPalette( fillType, QskRgb::LightSlateGray );
}
for ( auto orientation : { QskGradient::Vertical, QskGradient::Diagonal } )
for ( auto fillType : { Box::Vertical, Box::Diagonal } )
{
auto* box = new Box( parent );
box->setBorder( Box::Flat, QskRgb::OrangeRed );
box->setShape( 100, 100, Qt::RelativeSize );
box->setGradient( orientation, QskRgb::DodgerBlue );
box->setTonalPalette( fillType, QskRgb::DodgerBlue );
}
}
static void addRectanglesRest( QskLinearBox* parent )
{
using namespace QskRgb;
Box* box;
box = new Box( parent );
box->setBorderWidth( 20, 0, 40, 0 );
box->setBorderGradient( { "DarkSeaGreen" } );
box->setBorderGradient( DarkSeaGreen );
box = new Box( parent );
box->setShape( 40, Qt::RelativeSize );
box->setBorderWidth( 20, 10, 30, 15 );
box->setBorderGradient( { "DarkOrange" } );
box->setGradient( QskGradient::Vertical, "LightSteelBlue", "SteelBlue" );
box->setBorderGradient( DarkOrange );
box->setGradient( Box::Vertical, LightSteelBlue, SteelBlue );
box = new Box( parent );
box->setBorderWidth( 20, 0, 10, 20 );
box->setBorderGradient( { "MediumSeaGreen" } );
box->setGradient( "DodgerBlue" );
box->setBorderGradient( MediumSeaGreen );
box->setGradient( DodgerBlue );
box = new Box( parent );
box->setShape( 20, Qt::AbsoluteSize );
box->setBorderWidth( 2, 10, 40, 2 );
box->setBorderGradient( { "Crimson" } );
box->setBorderGradient( Crimson );
box->setGradient( QskRgb::WhiteSmoke );
box = new Box( parent );
box->setShape( 100, Qt::RelativeSize );
box->setBorderWidth( 5, 20, 5, 0 );
box->setBorderGradient( { "CadetBlue" } );
box->setGradient( QskGradient::Vertical, "Gainsboro", "Seashell", "LightGray" );
box->setBorderGradient( { CadetBlue } );
box->setGradient( Box::Vertical, Gainsboro, Seashell, LightGray );
}
static void addColoredBorderRectangles1( QskLinearBox* parent, bool rounded, Box::FillType fillType )
{
auto* box = new Box( parent );
box->setBorderWidth( 20 );
QskGradient gradient1( Qt::Vertical, { { 0.0, Qt::blue },
{ 0.9, Qt::yellow },
{ 1.0, Qt::darkRed } } );
QskGradient gradient2( Qt::Vertical, { { 0.0, Qt::black },
{ 0.3, Qt::white },
{ 0.7, Qt::white },
{ 1.0, Qt::black } } );
QskGradient gradient3( Qt::green );
QskGradient gradient4( Qt::Vertical, Qt::magenta, Qt::cyan );
box->setBorderGradients( gradient1, gradient2, gradient3, gradient4 );
QskGradientStops stops[4];
stops[0] = { { 0.0, Qt::blue }, { 0.9, Qt::yellow }, { 1.0, Qt::darkRed } };
stops[1] = { { 0.0, Qt::black }, { 0.3, Qt::white }, { 0.7, Qt::white }, { 1.0, Qt::black } };
stops[2] = { { 0.0, Qt::green }, { 1.0, Qt::green } };
stops[3] = { { 0.0, Qt::magenta }, { 1.0, Qt::cyan } };
box->setBorderGradients( stops[0], stops[1], stops[2], stops[3] );
if( fillType != Box::Unfilled )
box->setBackground( fillType, QskRgb::CornflowerBlue );
box->setTonalGradient( fillType, QskRgb::CornflowerBlue );
if( rounded )
box->setShape( 30, Qt::AbsoluteSize );
@ -396,7 +400,7 @@ static void addColoredBorderRectangles2( QskLinearBox* parent, bool rounded, Box
box->setBorderGradients( Qt::red, Qt::green, Qt::blue, Qt::yellow );
if( fillType != Box::Unfilled )
box->setBackground( fillType, QskRgb::CornflowerBlue );
box->setTonalGradient( fillType, QskRgb::CornflowerBlue );
if( rounded )
box->setShape( 30, Qt::AbsoluteSize );
@ -406,26 +410,25 @@ static void addColoredBorderRectangles3( QskLinearBox* parent, bool rounded, Box
{
Box* box = new Box( parent );
box->setBorderWidth( 20 );
QskGradient gradient1( Qt::Vertical, { { 0.0, Qt::yellow },
{ 0.2, Qt::gray },
{ 0.6, Qt::magenta },
{ 1.0, Qt::green } } );
QskGradient gradient2( Qt::Vertical, { { 0.0, Qt::darkYellow },
{ 0.2, Qt::cyan },
{ 1.0, Qt::darkMagenta } } );
QskGradient gradient3( Qt::Vertical, { { 0.0, Qt::red },
{ 0.25, Qt::green },
{ 0.5, Qt::blue },
{ 0.75, Qt::magenta },
{ 1.0, Qt::cyan } } );
QskGradient gradient4( Qt::Vertical, { { 0.0, Qt::red },
{ 0.3, Qt::green },
{ 0.7, Qt::blue },
{ 1.0, Qt::cyan } } );
box->setBorderGradients( gradient3, gradient3, gradient3, gradient3 );
QskGradientStops stops[4];
stops[0] = { { 0.0, Qt::yellow }, { 0.2, Qt::gray },
{ 0.6, Qt::magenta }, { 1.0, Qt::green } };
stops[1] = { { 0.0, Qt::darkYellow }, { 0.2, Qt::cyan }, { 1.0, Qt::darkMagenta } };
stops[2] = { { 0.0, Qt::red }, { 0.25, Qt::green },
{ 0.5, Qt::blue }, { 0.75, Qt::magenta }, { 1.0, Qt::cyan } };
stops[3] = { { 0.0, Qt::red }, { 0.3, Qt::green },
{ 0.7, Qt::blue }, { 1.0, Qt::cyan } };
box->setBorderGradients( stops[0], stops[1], stops[2], stops[3] );
//box->setBorderGradients( stops[2], stops[2], stops[2], stops[2] );
if( fillType != Box::Unfilled )
box->setBackground( fillType, QskRgb::CornflowerBlue );
box->setTonalGradient( fillType, QskRgb::CornflowerBlue );
if( rounded )
box->setShape( 30, Qt::AbsoluteSize );
@ -435,11 +438,11 @@ static void addColoredBorderRectangles4( QskLinearBox* parent, bool rounded, Box
{
Box* box = new Box( parent );
box->setBorderWidth( 20 );
QskGradient gradient( Qt::Vertical, Qt::magenta, Qt::cyan );
box->setBorderGradients( gradient, gradient, gradient, gradient );
box->setBorderGradient( QskGradient( Qt::magenta, Qt::cyan ) );
if( fillType != Box::Unfilled )
box->setBackground( fillType, QskRgb::CornflowerBlue );
box->setTonalGradient( fillType, QskRgb::CornflowerBlue );
if( rounded )
box->setShape( 30, Qt::AbsoluteSize );
@ -449,14 +452,14 @@ static void addColoredBorderRectangles5( QskLinearBox* parent, bool rounded, Box
{
Box* box = new Box( parent );
box->setBorderWidth( 20 );
QskGradient gradient( Qt::Vertical, { { 0.0, Qt::black },
{ 0.3, Qt::white },
{ 0.7, Qt::white },
{ 1.0, Qt::black } } );
box->setBorderGradients( gradient, gradient, gradient, gradient );
const QskGradientStops stops = { { 0.0, Qt::black }, { 0.3, Qt::white },
{ 0.7, Qt::white }, { 1.0, Qt::black } };
box->setBorderGradient( stops );
if( fillType != Box::Unfilled )
box->setBackground( fillType, QskRgb::CornflowerBlue );
box->setTonalGradient( fillType, QskRgb::CornflowerBlue );
if( rounded )
box->setShape( { 10, 20, 20, 40 } );

View File

@ -7,13 +7,14 @@
#include <SkinnyShortcut.h>
#include <QskAspect.h>
#include <QskGradient.h>
#include <QskLinearGradient.h>
#include <QskGraphicLabel.h>
#include <QskObjectCounter.h>
#include <QskShortcutMap.h>
#include <QskSubWindow.h>
#include <QskSubWindowArea.h>
#include <QskWindow.h>
#include <QskRgbValue.h>
#include <QDebug>
#include <QGuiApplication>
@ -59,7 +60,7 @@ int main( int argc, char* argv[] )
QskSubWindowArea* area = new QskSubWindowArea();
area->setGradientHint( QskSubWindowArea::Panel,
QskGradient( QskGradient::Diagonal, "DarkSlateGray", "LightSlateGray" ) );
QskLinearGradient( 0.0, 0.0, 1.0, 1.0, QskRgb::DarkSlateGray, QskRgb::LightSlateGray ) );
QRectF windowRect( 0, 0, 250, 250 );

View File

@ -35,8 +35,7 @@ namespace
colors += hctColor.toned( 45 ).rgb();
colors += hctColor.toned( 30 ).rgb();
setBarGradient( QskGradient( orientation(),
qskBuildGradientStops( colors, true ) ) );
setBarGradient( qskBuildGradientStops( colors, true ) );
}
};
}

View File

@ -26,6 +26,7 @@
#include <QskBoxShapeMetrics.h>
#include <QskBoxBorderMetrics.h>
#include <QskBoxBorderColors.h>
#include <QskLinearGradient.h>
#include <QskFunctions.h>
#include <QskShadowMetrics.h>
#include <QskSkinHintTableEditor.h>
@ -111,11 +112,11 @@ void Skin::initHints( const Palette& palette )
ed.setColor( TopBarItem::Item3 | QskAspect::TextColor, 0xfff99055 );
ed.setColor( TopBarItem::Item4 | QskAspect::TextColor, 0xff6776ff );
// conical gradients are counterclockwise, so specify the 2nd color first:
ed.setHGradient( TopBarItem::Item1, 0xffff3122, 0xffff5c00 );
ed.setHGradient( TopBarItem::Item2, 0xff6100ff, 0xff6776ff );
ed.setHGradient( TopBarItem::Item3, 0xffff3122, 0xffffce50 );
ed.setHGradient( TopBarItem::Item4, 0xff6100ff, 0xff6776ff );
// arcs are counterclockwise, so specify the 2nd color first:
ed.setGradient( TopBarItem::Item1, 0xffff3122, 0xffff5c00 );
ed.setGradient( TopBarItem::Item2, 0xff6100ff, 0xff6776ff );
ed.setGradient( TopBarItem::Item3, 0xffff3122, 0xffffce50 );
ed.setGradient( TopBarItem::Item4, 0xff6100ff, 0xff6776ff );
// the bar gradient is defined through the top bar items above
ed.setArcMetrics( CircularProgressBar::Groove, { 8.53, 90, -360 } );
@ -141,8 +142,8 @@ void Skin::initHints( const Palette& palette )
{
ed.setBoxShape( subControl, 6 );
QskGradient normal( Qt::Vertical, 0xff6776ff, 0xff6100ff );
QskGradient bright( Qt::Vertical, 0xffff7d34, 0xffff3122 );
QskLinearGradient normal( Qt::Vertical, 0xff6776ff, 0xff6100ff );
QskLinearGradient bright( Qt::Vertical, 0xffff7d34, 0xffff3122 );
if ( subControl == RoundedIcon::PalePanel )
{
@ -197,9 +198,9 @@ void Skin::initHints( const Palette& palette )
ed.setBoxShape( LightDisplay::Panel, 100, Qt::RelativeSize );
ed.setArcMetrics( LightDisplay::ColdAndWarmArc, 8.785, 0, 180 );
QskGradient coldGradient( Qt::Horizontal,
{ { 0.0, 0xffff3122 }, { 0.2, 0xfffeeeb7 },
{ 0.3, 0xffa7b0ff }, { 0.5, 0xff6776ff }, { 1.0, Qt::black } } );
const QskGradient coldGradient(
{ { 0.0, 0xffff3122 }, { 0.2, 0xfffeeeb7 }, { 0.3, 0xffa7b0ff },
{ 0.5, 0xff6776ff }, { 1.0, Qt::black } } );
ed.setGradient( LightDisplay::ColdAndWarmArc, coldGradient );
ed.setMetric( LightDisplay::Tickmarks, 1 );
@ -250,7 +251,7 @@ Skin::Palette DaytimeSkin::palette() const
0xfff4f4f4,
Qt::black,
0xffe5e5e5,
{ Qt::Vertical, { { 0.0, 0xffc4c4c4 }, { 0.5, 0xfff8f8f8 }, { 1.0, 0xffc4c4c4 } } }
{ { { 0.0, 0xffc4c4c4 }, { 0.5, 0xfff8f8f8 }, { 1.0, 0xffc4c4c4 } } }
};
}
@ -264,6 +265,6 @@ Skin::Palette NighttimeSkin::palette() const
0xff0c0c0c,
Qt::white,
0xff1a1a1a,
{ Qt::Vertical, { { 0.0, 0xff666666 }, { 0.5, 0xff222222 }, { 1.0, 0xff333333 } } }
{ { { 0.0, 0xff666666 }, { 0.5, 0xff222222 }, { 1.0, 0xff333333 } } }
};
}

View File

@ -61,7 +61,7 @@ class GraphicLabel : public QskGraphicLabel
const int duration = 500;
const QskGradient oldGradient = background();
const auto oldGradient = background();
setGradientHint( Panel, gradient );
// finally setup a smooth transition manually

View File

@ -14,6 +14,7 @@
#include <QskSkin.h>
#include <QskPlatform.h>
#include <QskRgbValue.h>
#include <QskLinearGradient.h>
namespace
{
@ -57,7 +58,7 @@ namespace
ed.setStrutSize( Q::Knob, 30, 30 );
ed.setBoxShape( Q::Knob, 100, Qt::RelativeSize );
ed.setGradient( Q::Knob,
QskGradient( QskGradient::Diagonal, rgb2, rgb1 ) );
QskLinearGradient( 0.0, 0.0, 1.0, 1.0, rgb2, rgb1 ) );
ed.setMetric( Q::Needle | QskAspect::Size, 2 );
ed.setMetric( Q::Needle | QskAspect::Margin, 10 );

View File

@ -42,73 +42,6 @@ static inline qreal effectivePenWidth(
return width;
}
namespace
{
class ShapeNode : public QskShapeNode
{
public:
void updateShape( const QPainterPath& path,
const QTransform& transform, const QRectF& rect, const Gradient& gradient )
{
if ( gradient.isMonochrome() )
{
updateNode( path, transform, gradient.stops().first().color() );
return;
}
/*
Stupid code to map Gradient -> QGradient
Can be removed once Gradient has been merged into QskGradient.
*/
switch( static_cast<int>( gradient.type() ) )
{
case QGradient::LinearGradient:
{
const auto& g = gradient.asLinearGradient();
QLinearGradient qgradient( g.start(), g.stop() );
qgradient.setSpread( g.spread() );
qgradient.setStops( g.qtStops() );
updateNode( path, transform, rect, &qgradient );
break;
}
case QGradient::RadialGradient:
{
const auto& g = gradient.asRadialGradient();
QRadialGradient qgradient( g.center(), g.radius() );
qgradient.setSpread( g.spread() );
qgradient.setStops( g.qtStops() );
updateNode( path, transform, rect, &qgradient );
break;
}
case QGradient::ConicalGradient:
{
const auto& g = gradient.asConicGradient();
QConicalGradient qgradient( g.center(), g.startAngle() );
qgradient.setSpread( g.spread() );
qgradient.setStops( g.qtStops() );
/*
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;
}
}
}
};
}
ShapeItem::ShapeItem( QQuickItem* parent )
: QskControl( parent )
{
@ -134,7 +67,7 @@ QPen ShapeItem::pen() const
return m_pen;
}
void ShapeItem::setGradient( const Gradient& gradient )
void ShapeItem::setGradient( const QskGradient& gradient )
{
if ( gradient != m_gradient )
{
@ -143,7 +76,7 @@ void ShapeItem::setGradient( const Gradient& gradient )
}
}
const Gradient& ShapeItem::gradient() const
const QskGradient& ShapeItem::gradient() const
{
return m_gradient;
}
@ -173,7 +106,7 @@ void ShapeItem::updateNode( QSGNode* parentNode )
const auto rect = contentsRect();
const auto pathRect = m_path.controlPointRect();
auto fillNode = static_cast< ShapeNode* >(
auto fillNode = static_cast< QskShapeNode* >(
QskSGNode::findChildNode( parentNode, FillRole ) );
auto borderNode = static_cast< QskStrokeNode* >(
@ -191,7 +124,7 @@ void ShapeItem::updateNode( QSGNode* parentNode )
{
if ( fillNode == nullptr )
{
fillNode = new ShapeNode;
fillNode = new QskShapeNode;
QskSGNode::setNodeRole( fillNode, FillRole );
parentNode->prependChildNode( fillNode );
@ -205,7 +138,7 @@ void ShapeItem::updateNode( QSGNode* parentNode )
}
const auto transform = ::transformForRects( pathRect, fillRect );
fillNode->updateShape( m_path, transform, fillRect, m_gradient );
fillNode->updateNode( m_path, transform, fillRect, m_gradient );
}
else
{

View File

@ -5,13 +5,11 @@
#pragma once
#include "Gradient.h"
#include <QskGradient.h>
#include <QskControl.h>
#include <QPen>
#include <QPainterPath>
class Gradient;
class ShapeItem : public QskControl
{
Q_OBJECT
@ -23,8 +21,8 @@ class ShapeItem : public QskControl
void setPen( const QPen& );
QPen pen() const;
void setGradient( const Gradient& );
const Gradient& gradient() const;
void setGradient( const QskGradient& );
const QskGradient& gradient() const;
void setPath( const QPainterPath& );
QPainterPath path() const;
@ -36,6 +34,6 @@ class ShapeItem : public QskControl
QPainterPath scaledPath( const QRectF& ) const;
QPen m_pen;
Gradient m_gradient;
QskGradient m_gradient;
QPainterPath m_path;
};

View File

@ -4,13 +4,15 @@
*****************************************************************************/
#include "ShapeItem.h"
#include "Gradient.h"
#include <QskObjectCounter.h>
#include <QskWindow.h>
#include <QskRgbValue.h>
#include <QskLinearBox.h>
#include <QskTabView.h>
#include <QskLinearGradient.h>
#include <QskRadialGradient.h>
#include <QskConicGradient.h>
#include <SkinnyShortcut.h>
#include <SkinnyShapeFactory.h>
@ -63,9 +65,32 @@ namespace
shapeItem->setPath( path( SkinnyShapeFactory::Hexagon ) );
shapeItem->setPen( pen( QColorConstants::Svg::indigo ) );
LinearGradient gradient( 0.0, 0.0, 0.2, 0.5 );
QskLinearGradient gradient( 0.0, 0.0, 0.2, 0.5, QGradient::PhoenixStart );
gradient.setSpread( QGradient::ReflectSpread );
gradient.setStops( QGradient::PhoenixStart );
shapeItem->setGradient( gradient );
}
{
auto shapeItem = new ShapeItem( this );
shapeItem->setPath( path( SkinnyShapeFactory::Star ) );
const QVector< QskGradientStop > stops =
{ { 0.5, QskRgb::RoyalBlue }, { 0.5, QskRgb::LemonChiffon } };
QskLinearGradient gradient( 0.0, 0.0, 0.05, 0.1, stops );
gradient.setSpread( QGradient::RepeatSpread );
shapeItem->setGradient( gradient );
}
{
auto shapeItem = new ShapeItem( this );
shapeItem->setPath( path( SkinnyShapeFactory::Rectangle ) );
const QVector< QskGradientStop > stops =
{ { 0.5, QskRgb::MediumVioletRed }, { 0.5, QskRgb::Navy } };
QskLinearGradient gradient( 0.5, 0.0, 0.5, 0.5, stops );
shapeItem->setGradient( gradient );
}
@ -84,11 +109,9 @@ namespace
shapeItem->setPath( path( SkinnyShapeFactory::Rectangle ) );
shapeItem->setPen( pen( QColorConstants::Svg::indigo ) );
RadialGradient gradient( 0.5, 0.5, 0.5 );
QskRadialGradient gradient;
gradient.setStops( QskRgb::LightYellow, QskRgb::MidnightBlue );
gradient.setSpread( QGradient::PadSpread );
gradient.setStops( QColorConstants::Svg::lightyellow,
QColorConstants::Svg::midnightblue );
shapeItem->setGradient( gradient );
}
@ -97,23 +120,22 @@ namespace
shapeItem->setPath( path( SkinnyShapeFactory::Ellipse ) );
RadialGradient gradient( 0.5, 0.5, 0.5 );
gradient.setSpread( QGradient::PadSpread );
QVector< QskGradientStop > stops;
stops += QskGradientStop( 0.0, Qt::green );
stops += QskGradientStop( 0.2, Qt::green );
stops += QskGradientStop( 0.201, Qt::red );
stops += QskGradientStop( 0.2, Qt::red );
stops += QskGradientStop( 0.4, Qt::red );
stops += QskGradientStop( 0.401, Qt::yellow );
stops += QskGradientStop( 0.4, Qt::yellow );
stops += QskGradientStop( 0.6, Qt::yellow );
stops += QskGradientStop( 0.601, Qt::cyan );
stops += QskGradientStop( 0.6, Qt::cyan );
stops += QskGradientStop( 0.8, Qt::cyan );
stops += QskGradientStop( 0.801, Qt::darkCyan );
stops += QskGradientStop( 0.8, Qt::darkCyan );
stops += QskGradientStop( 1.0, Qt::darkCyan );
gradient.setStops( stops );
QskRadialGradient gradient( stops );
gradient.setSpread( QGradient::PadSpread );
shapeItem->setGradient( gradient );
}
@ -121,13 +143,10 @@ namespace
auto shapeItem = new ShapeItem( this );
shapeItem->setPath( path( SkinnyShapeFactory::Rectangle ) );
shapeItem->setPen( pen( QColorConstants::Svg::indigo ) );
RadialGradient gradient( 0.5, 0.5, 0.25 );
gradient.setCenter( 0.5, 0.7 );
shapeItem->setPen( pen( QskRgb::Indigo ) );
QskRadialGradient gradient( 0.5, 0.7, 0.25, QGradient::LilyMeadow );
gradient.setSpread( QGradient::RepeatSpread );
gradient.setStops( QGradient::LilyMeadow );
shapeItem->setGradient( gradient );
}
@ -135,12 +154,10 @@ namespace
auto shapeItem = new ShapeItem( this );
shapeItem->setPath( path( SkinnyShapeFactory::Rectangle ) );
shapeItem->setPen( pen( QColorConstants::Svg::indigo ) );
RadialGradient gradient( 0.6, 0.4, 0.1 );
shapeItem->setPen( pen( QskRgb::Indigo ) );
QskRadialGradient gradient( 0.6, 0.4, 0.1, Qt::red, Qt::blue );
gradient.setSpread( QGradient::ReflectSpread );
gradient.setStops( Qt::red, Qt::blue );
shapeItem->setGradient( gradient );
}
@ -158,7 +175,7 @@ namespace
shapeItem->setPath( path( SkinnyShapeFactory::Ellipse ) );
ConicGradient gradient( 0.5, 0.5, 30.0, 60.0 );
QskConicGradient gradient( 0.5, 0.5, 30.0, 60.0 );
gradient.setSpread( QGradient::ReflectSpread );
gradient.setStops( QGradient::JuicyPeach );
@ -169,7 +186,7 @@ namespace
shapeItem->setPath( path( SkinnyShapeFactory::TriangleUp ) );
ConicGradient gradient( 0.5, 0.5, 30.0, 60.0 );
QskConicGradient gradient( 0.5, 0.5, 30.0, 60.0 );
gradient.setSpread( QGradient::RepeatSpread );
gradient.setStops( QGradient::WinterNeva );
@ -180,7 +197,7 @@ namespace
shapeItem->setPath( path( SkinnyShapeFactory::Arc ) );
ConicGradient gradient( 0.5, 0.5, 300.0, -240.0 );
QskConicGradient gradient( 0.5, 0.5, 300.0, -240.0 );
gradient.setStops( QGradient::SpikyNaga );
shapeItem->setGradient( gradient );
@ -190,7 +207,7 @@ namespace
shapeItem->setPath( path( SkinnyShapeFactory::Diamond ) );
ConicGradient gradient( 0.5, 0.5, 45.0, 180.0 );
QskConicGradient gradient( 0.5, 0.5, 45.0, 180.0 );
gradient.setStops( QGradient::FabledSunset );
gradient.setSpread( QGradient::ReflectSpread );

View File

@ -1,10 +1,8 @@
CONFIG += qskexample
HEADERS += \
Gradient.h \
ShapeItem.h \
SOURCES += \
Gradient.cpp \
ShapeItem.cpp \
main.cpp

View File

@ -39,7 +39,7 @@
#include <QskBoxBorderMetrics.h>
#include <QskBoxShapeMetrics.h>
#include <QskPlatform.h>
#include <QskGradient.h>
#include <QskLinearGradient.h>
#include <QskMargins.h>
#include <QskNamespace.h>
#include <QskRgbValue.h>
@ -176,10 +176,10 @@ namespace
void Editor::setSeparator( QskAspect aspect )
{
QskGradient gradient( QskGradient::Vertical, m_pal.lighter110, m_pal.darker125 );
QskLinearGradient gradient( Qt::Vertical, m_pal.lighter110, m_pal.darker125 );
if ( aspect.placement() == QskAspect::Vertical )
gradient.setOrientation( QskGradient::Horizontal );
gradient.setOrientation( Qt::Horizontal );
setGradient( aspect, gradient );
setBoxShape( aspect, 0 );
@ -193,7 +193,7 @@ void Editor::setButton( QskAspect aspect, PanelStyle style, qreal border )
#endif
QskBoxBorderColors borderColors;
QskGradient gradient( QskGradient::Vertical );
QskLinearGradient gradient( Qt::Vertical );
switch ( style )
{
@ -637,8 +637,7 @@ void Editor::setupTabButton()
for ( auto placement : { A::Top, A::Bottom } )
{
setGradient( Q::Panel | placement,
QskGradient( Qt::Vertical, m_pal.lighter125, m_pal.lighter110 ) );
setVGradient( Q::Panel | placement, m_pal.lighter125, m_pal.lighter110 );
for ( const auto state : { Q::Checked | A::NoState, Q::Checked | Q::Pressed } )
{

View File

@ -6,7 +6,6 @@
#include "QskGradient.h"
#include "QskRgbValue.h"
#include <qhashfunctions.h>
#include <qvariant.h>
static void qskRegisterGradient()
@ -23,12 +22,6 @@ static void qskRegisterGradient()
Q_CONSTRUCTOR_FUNCTION( qskRegisterGradient )
static inline QskGradient::Orientation qskOrientation( Qt::Orientation o )
{
return ( o == Qt::Vertical )
? QskGradient::Vertical : QskGradient::Horizontal;
}
static inline bool qskIsGradientValid( const QskGradientStops& stops )
{
if ( stops.isEmpty() )
@ -57,66 +50,74 @@ static inline bool qskCanBeInterpolated( const QskGradient& from, const QskGradi
if ( from.isMonochrome() || to.isMonochrome() )
return true;
return from.orientation() == to.orientation();
}
QskGradient::QskGradient( Orientation orientation ) noexcept
: m_orientation( orientation )
, m_isDirty( false )
, m_isValid( false )
, m_isMonchrome( true )
, m_isVisible( false )
{
return from.type() == to.type();
}
QskGradient::QskGradient( const QColor& color )
: QskGradient( Vertical )
{
setStops( color );
}
QskGradient::QskGradient( Qt::Orientation orientation,
const QColor& startColor, const QColor& stopColor )
: QskGradient( qskOrientation( orientation ), startColor, stopColor )
QskGradient::QskGradient( const QColor& color1, const QColor& color2 )
{
setStops( color1, color2 );
}
QskGradient::QskGradient( Orientation orientation,
const QColor& startColor, const QColor& stopColor )
: QskGradient( orientation )
QskGradient::QskGradient( QGradient::Preset preset )
{
setStops( startColor, stopColor );
setStops( qskBuildGradientStops( QGradient( preset ).stops() ) );
}
QskGradient::QskGradient( Qt::Orientation orientation, const QskGradientStops& stops )
: QskGradient( qskOrientation( orientation ), stops )
{
}
QskGradient::QskGradient( Orientation orientation, const QskGradientStops& stops )
: QskGradient( orientation )
QskGradient::QskGradient( const QVector< QskGradientStop >& stops )
{
setStops( stops );
}
QskGradient::QskGradient( Qt::Orientation orientation, QGradient::Preset preset )
: QskGradient( qskOrientation( orientation ), preset )
QskGradient::QskGradient( const QskGradient& 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], }
, m_type( other.m_type )
, m_spread( other.m_spread )
, m_isDirty( other.m_isDirty )
, m_isValid( other.m_isValid )
, m_isMonchrome( other.m_isMonchrome )
, m_isVisible( other.m_isVisible )
{
}
QskGradient::QskGradient( Orientation orientation, QGradient::Preset preset )
: QskGradient( orientation )
{
setStops( qskBuildGradientStops( QGradient( preset ).stops() ) );
}
QskGradient::~QskGradient()
{
}
QskGradient& QskGradient::operator=( const QskGradient& other ) noexcept
{
m_type = other.m_type;
m_spread = other.m_spread;
m_stops = other.m_stops;
m_values[0] = other.m_values[0];
m_values[1] = other.m_values[1];
m_values[2] = other.m_values[2];
m_values[3] = other.m_values[3];
m_isDirty = other.m_isDirty;
m_isValid = other.m_isValid;
m_isMonchrome = other.m_isMonchrome;
m_isVisible = other.m_isVisible;
return *this;
}
bool QskGradient::operator==( const QskGradient& other ) const noexcept
{
return ( m_orientation == other.m_orientation ) && ( m_stops == other.m_stops );
return ( m_type == other.m_type )
&& ( m_spread == other.m_spread )
&& ( m_values[0] == other.m_values[0] )
&& ( m_values[1] == other.m_values[1] )
&& ( m_values[2] == other.m_values[2] )
&& ( m_values[3] == other.m_values[3] )
&& ( m_stops == other.m_stops );
}
void QskGradient::updateStatusBits() const
@ -162,17 +163,6 @@ bool QskGradient::isVisible() const noexcept
return m_isVisible;
}
void QskGradient::setOrientation( Qt::Orientation orientation ) noexcept
{
setOrientation( qskOrientation( orientation ) );
}
void QskGradient::setOrientation( Orientation orientation ) noexcept
{
// does not change m_isDirty
m_orientation = orientation;
}
void QskGradient::setStops( const QColor& color )
{
m_stops = { { 0.0, color }, { 1.0, color } };
@ -185,6 +175,12 @@ void QskGradient::setStops( const QColor& color1, const QColor& color2 )
m_isDirty = true;
}
void QskGradient::setStops( QGradient::Preset preset )
{
const auto stops = qskBuildGradientStops( QGradient( preset ).stops() );
setStops( stops );
}
void QskGradient::setStops( const QskGradientStops& stops )
{
if ( !stops.isEmpty() && !qskIsGradientValid( stops ) )
@ -262,6 +258,11 @@ void QskGradient::setAlpha( int alpha )
m_isDirty = true;
}
void QskGradient::setSpread( QGradient::Spread spread )
{
m_spread = spread;
}
void QskGradient::reverse()
{
if ( isMonochrome() )
@ -314,13 +315,16 @@ QskGradient QskGradient::interpolated( const QskGradient& to, qreal ratio ) cons
if ( qskCanBeInterpolated( *this, to ) )
{
// We simply interpolate stops
// We simply interpolate stops and values
gradient.setOrientation( to.orientation() );
gradient = to;
gradient.setStops( qskInterpolatedGradientStops(
m_stops, isMonochrome(),
to.m_stops, to.isMonochrome(), ratio ) );
for ( uint i = 0; i < sizeof( m_values ) / sizeof( m_values[0] ); i++ )
gradient.m_values[i] = m_values[i] + ratio * ( to.m_values[i] - m_values[i] );
}
else
{
@ -338,14 +342,14 @@ QskGradient QskGradient::interpolated( const QskGradient& to, qreal ratio ) cons
{
const auto r = 2.0 * ratio;
gradient.setOrientation( orientation() );
gradient = *this;
gradient.setStops( qskInterpolatedGradientStops( m_stops, c, r ) );
}
else
{
const auto r = 2.0 * ( ratio - 0.5 );
gradient.setOrientation( to.orientation() );
gradient = to;
gradient.setStops( qskInterpolatedGradientStops( c, to.m_stops, r ) );
}
}
@ -370,15 +374,57 @@ void QskGradient::clearStops()
QskHashValue QskGradient::hash( QskHashValue seed ) const
{
const auto o = orientation();
auto hash = qHashBits( &m_type, sizeof( m_type ), seed );
if ( m_type != Stops )
hash = qHashBits( m_values, sizeof( m_values ), seed );
auto hash = qHashBits( &o, sizeof( o ), seed );
for ( const auto& stop : m_stops )
hash = stop.hash( hash );
return hash;
}
#include "QskLinearGradient.h"
#include "QskRadialGradient.h"
#include "QskConicGradient.h"
QskLinearGradient& QskGradient::asLinearGradient()
{
assert( m_type == QskGradient::Linear );
return *reinterpret_cast< QskLinearGradient* >( this );
}
const QskLinearGradient& QskGradient::asLinearGradient() const
{
assert( m_type == QskGradient::Linear );
return *reinterpret_cast< const QskLinearGradient* >( this );
}
QskRadialGradient& QskGradient::asRadialGradient()
{
assert( m_type == QskGradient::Radial );
return *reinterpret_cast< QskRadialGradient* >( this );
}
const QskRadialGradient& QskGradient::asRadialGradient() const
{
assert( m_type == QskGradient::Radial );
return *reinterpret_cast< const QskRadialGradient* >( this );
}
QskConicGradient& QskGradient::asConicGradient()
{
assert( m_type == QskGradient::Conic );
return *reinterpret_cast< QskConicGradient* >( this );
}
const QskConicGradient& QskGradient::asConicGradient() const
{
assert( m_type == QskGradient::Conic );
return *reinterpret_cast< const QskConicGradient* >( this );
}
#ifndef QT_NO_DEBUG_STREAM
#include <qdebug.h>
@ -388,46 +434,96 @@ QDebug operator<<( QDebug debug, const QskGradient& gradient )
QDebugStateSaver saver( debug );
debug.nospace();
debug << "Gradient";
debug << "QskGradient( ";
if ( !gradient.isValid() )
switch ( gradient.type() )
{
debug << "()";
case QskGradient::Linear:
{
debug << "L(";
const auto& g = gradient.asLinearGradient();
debug << g.start().x() << "," << g.start().y()
<< "," << g.stop().x() << "," << g.stop().y() << ")";
break;
}
case QskGradient::Radial:
{
debug << "R(";
const auto& g = gradient.asRadialGradient();
debug << g.center().x() << "," << g.center().y()
<< "," << g.radius() << ")";
break;
}
case QskGradient::Conic:
{
debug << "C(";
const auto& g = gradient.asConicGradient();
debug << g.center().x() << "," << g.center().y()
<< ",[" << g.startAngle() << "," << g.spanAngle() << "])";
break;
}
case QskGradient::Stops:
{
debug << "S()";
break;
}
}
if ( gradient.stops().isEmpty() )
{
debug << " ()";
}
else
{
debug << "( ";
if ( gradient.isMonochrome() )
{
QskRgb::debugColor( debug, gradient.startColor() );
debug << ' ';
const auto color = gradient.stops().first().color();
QskRgb::debugColor( debug, color );
}
else
{
const char o[] = { 'H', 'V', 'D' };
debug << o[ gradient.orientation() ] << ", ";
debug << " ( ";
if ( gradient.stops().count() == 2 )
const auto& stops = gradient.stops();
for ( int i = 0; i < stops.count(); i++ )
{
QskRgb::debugColor( debug, gradient.startColor() );
debug << ", ";
QskRgb::debugColor( debug, gradient.endColor() );
}
else
{
const auto& stops = gradient.stops();
for ( int i = 0; i < stops.count(); i++ )
{
if ( i != 0 )
debug << ", ";
if ( i != 0 )
debug << ", ";
debug << stops[i];
}
debug << stops[i];
}
debug << " )";
}
debug << " )";
}
switch( gradient.spread() )
{
case QGradient::RepeatSpread:
debug << " RP";
break;
case QGradient::ReflectSpread:
debug << " RF";
break;
case QGradient::PadSpread:
break;
}
debug << " )";
return debug;
}

View File

@ -11,6 +11,10 @@
#include <qbrush.h>
#include <qmetatype.h>
class QskLinearGradient;
class QskRadialGradient;
class QskConicGradient;
class QVariant;
/*
@ -22,7 +26,6 @@ class QSK_EXPORT QskGradient
{
Q_GADGET
Q_PROPERTY( Orientation orientation READ orientation WRITE setOrientation )
Q_PROPERTY( QVector< QskGradientStop > stops READ stops WRITE setStops )
Q_PROPERTY( bool valid READ isValid )
@ -30,43 +33,35 @@ class QSK_EXPORT QskGradient
Q_PROPERTY( bool monochrome READ isMonochrome )
public:
// TODO: radial/canonical gradients + other diagonal linear gradients
enum Orientation
enum Type
{
Horizontal,
Vertical,
Diagonal
Stops,
Linear,
Radial,
Conic
};
Q_ENUM( Orientation )
Q_ENUM( Type )
QskGradient() noexcept = default;
QskGradient( Orientation ) noexcept;
QskGradient( Qt::GlobalColor );
QskGradient( QRgb );
QskGradient( const QColor& );
QskGradient( const QColor&, const QColor& );
QskGradient( QGradient::Preset );
QskGradient( const QVector< QskGradientStop >& );
QskGradient( Qt::Orientation, const QVector< QskGradientStop >& );
QskGradient( Qt::Orientation, const QColor&, const QColor& );
QskGradient( Qt::Orientation, QGradient::Preset );
QskGradient( Orientation, const QVector< QskGradientStop >& );
QskGradient( Orientation, const QColor&, const QColor& );
QskGradient( Orientation, QGradient::Preset );
QskGradient( const QskGradient& ) noexcept;
~QskGradient();
QskGradient& operator=( const QskGradient& ) noexcept;
bool operator==( const QskGradient& ) const noexcept;
bool operator!=( const QskGradient& ) const noexcept;
void setOrientation( Qt::Orientation ) noexcept;
void setOrientation( Orientation ) noexcept;
Orientation orientation() const noexcept;
bool isHorizontal() const noexcept;
bool isVertical() const noexcept;
bool isTilted() const noexcept;
QskGradient::Type type() const noexcept;
bool isValid() const noexcept;
bool isMonochrome() const noexcept;
@ -88,6 +83,9 @@ class QSK_EXPORT QskGradient
void setAlpha( int alpha );
void setSpread( QGradient::Spread );
QGradient::Spread spread() const noexcept;
void reverse();
QskGradient reversed() const;
@ -106,13 +104,37 @@ class QSK_EXPORT QskGradient
int stepCount() const noexcept;
QskLinearGradient& asLinearGradient();
const QskLinearGradient& asLinearGradient() const;
QskRadialGradient& asRadialGradient();
const QskRadialGradient& asRadialGradient() const;
QskConicGradient& asConicGradient();
const QskConicGradient& asConicGradient() const;
private:
friend class QskLinearGradient;
friend class QskRadialGradient;
friend class QskConicGradient;
QskGradient( Type ) noexcept;
QskGradient( Type, qreal, qreal, qreal, qreal ) noexcept;
void updateStatusBits() const;
private:
QVector< QskGradientStop > m_stops;
Orientation m_orientation = Vertical;
/*
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;
@ -122,6 +144,18 @@ class QSK_EXPORT QskGradient
Q_DECLARE_METATYPE( QskGradient )
inline QskGradient::QskGradient( QskGradient::Type type ) noexcept
: m_type( type )
{
}
inline QskGradient::QskGradient( QskGradient::Type type,
qreal v1, qreal v2, qreal v3, qreal v4 ) noexcept
: m_values{ v1, v2, v3, v4 }
, m_type( type )
{
}
inline QskGradient::QskGradient( Qt::GlobalColor color )
: QskGradient( QColor( color ) )
{
@ -132,34 +166,14 @@ inline QskGradient::QskGradient( QRgb rgb )
{
}
inline QskGradient::QskGradient( QGradient::Preset preset )
: QskGradient( Vertical, preset )
{
}
inline bool QskGradient::operator!=( const QskGradient& other ) const noexcept
{
return !( *this == other );
}
inline QskGradient::Orientation QskGradient::orientation() const noexcept
inline QskGradient::Type QskGradient::type() const noexcept
{
return m_orientation;
}
inline bool QskGradient::isHorizontal() const noexcept
{
return orientation() == Horizontal;
}
inline bool QskGradient::isVertical() const noexcept
{
return orientation() == Vertical;
}
inline bool QskGradient::isTilted() const noexcept
{
return orientation() == Diagonal;
return m_type;
}
inline const QskGradientStops& QskGradient::stops() const noexcept
@ -186,6 +200,11 @@ inline QColor QskGradient::endColor() const noexcept
return m_stops.isEmpty() ? QColor() : m_stops.last().color();
}
inline QGradient::Spread QskGradient::spread() const noexcept
{
return m_spread;
}
#ifndef QT_NO_DEBUG_STREAM
class QDebug;

View File

@ -6,7 +6,6 @@
#include "QskProgressBar.h"
#include "QskIntervalF.h"
#include "QskGradient.h"
#include "QskFunctions.h"
#include "QskAnimator.h"
#include "QskAspect.h"
@ -163,20 +162,12 @@ QskAspect::Placement QskProgressBar::effectivePlacement() const
void QskProgressBar::setBarGradient( const QskGradient& gradient )
{
// An API where we set the stops only would be more accurate TODO ...
auto g = gradient;
g.setOrientation( Qt::Horizontal );
setGradientHint( Bar | QskAspect::Horizontal, g );
g.setOrientation( Qt::Vertical );
setGradientHint( Bar | QskAspect::Vertical, g );
setGradientHint( Bar, gradient );
}
void QskProgressBar::resetBarGradient()
{
resetColor( Bar | QskAspect::Vertical );
resetColor( Bar | QskAspect::Horizontal );
resetColor( Bar );
}
QskGradient QskProgressBar::barGradient() const

View File

@ -7,6 +7,7 @@
#include "QskProgressBar.h"
#include "QskIntervalF.h"
#include "QskBoxBorderMetrics.h"
#include "QskLinearGradient.h"
#include <qeasingcurve.h>
#include <cmath>
@ -124,13 +125,26 @@ QSGNode* QskProgressBarSkinlet::updateBarNode(
if ( !gradient.isVisible() )
return nullptr;
gradient.setOrientation( bar->orientation() );
if ( !gradient.isMonochrome() )
if ( ( gradient.type() == QskGradient::Stops ) && !gradient.isMonochrome() )
{
const auto intv = qskBarInterval( bar );
gradient = gradient.extracted( intv.lowerBound(), intv.upperBound() );
/*
When having stops only we use a linear gradient,
where the colors are increasing in direction of the
progress value. We interprete the gradient as a
definition for the 100% situation and have to adjust
the stops for smaller bars.
For this situation it would be more convenient to
adjust the start/stop positions, but the box renderer is
not supporting this yet. TODO ...
*/
const auto intv = qskBarInterval( bar );
auto stops = qskExtractedGradientStops( gradient.stops(),
intv.lowerBound(), intv.upperBound() );
gradient = QskLinearGradient( bar->orientation(), stops );
if ( bar->orientation() == Qt::Vertical || bar->layoutMirroring() )
gradient.reverse();
}

View File

@ -12,7 +12,7 @@
#include "QskBoxBorderMetrics.h"
#include "QskBoxBorderColors.h"
#include "QskShadowMetrics.h"
#include "QskGradient.h"
#include "QskLinearGradient.h"
namespace
{
@ -225,7 +225,7 @@ void QskSkinHintTableEditor::setHGradient(
QskAspect aspect, const QColor& color1, const QColor& color2,
QskStateCombination combination )
{
const QskGradient gradient( QskGradient::Horizontal, color1, color2 );
const QskLinearGradient gradient( Qt::Horizontal, color1, color2 );
setGradient( aspect, gradient, combination );
}
@ -233,10 +233,18 @@ void QskSkinHintTableEditor::setVGradient(
QskAspect aspect, const QColor& color1, const QColor& color2,
QskStateCombination combination )
{
const QskGradient gradient( QskGradient::Vertical, color1, color2 );
const QskLinearGradient gradient( Qt::Vertical, color1, color2 );
setGradient( aspect, gradient, combination );
}
void QskSkinHintTableEditor::setGradient(
QskAspect aspect, const QColor& color1, const QColor& color2,
QskStateCombination combination )
{
const QskGradient gradient( color1, color2 );
setColorHint( aspect, gradient , combination );
}
void QskSkinHintTableEditor::setGradient(
QskAspect aspect, const QskGradient& gradient,
QskStateCombination combination )

View File

@ -118,6 +118,9 @@ class QSK_EXPORT QskSkinHintTableEditor
void setVGradient( QskAspect, const QColor&, const QColor&,
QskStateCombination = QskStateCombination() );
void setGradient( QskAspect, const QColor&, const QColor&,
QskStateCombination = QskStateCombination() );
void setGradient( QskAspect, const QskGradient&,
QskStateCombination = QskStateCombination() );

View File

@ -5,27 +5,30 @@
#include "QskArcRenderer.h"
#include "QskArcMetrics.h"
#include "QskGradient.h"
#include "QskLinearGradient.h"
#include <qpainter.h>
#include <qrect.h>
void QskArcRenderer::renderArc(const QRectF& rect,
const QskArcMetrics& metrics, const QskGradient& gradient,
QPainter* painter )
const QskArcMetrics& metrics, const QskGradient& gradient, QPainter* painter )
{
painter->setRenderHint( QPainter::Antialiasing, true );
bool isRadial = false;
/*
horizontal is interpreted as in direction of the arc,
while vertical means from the inner to the outer border
*/
if ( gradient.type() == QskGradient::Linear )
{
/*
Horizontal is interpreted as conic ( in direction of the arc ),
while Vertical means radial ( inner to outer border )
*/
isRadial = gradient.asLinearGradient().isVertical();
}
QBrush brush;
const auto qStops = qskToQGradientStops( gradient.stops() );
if( gradient.orientation() == QskGradient::Vertical )
if( isRadial )
{
QRadialGradient radial( rect.center(), qMin( rect.width(), rect.height() ) );
radial.setStops( qStops );
@ -40,6 +43,7 @@ void QskArcRenderer::renderArc(const QRectF& rect,
brush = conical;
}
painter->setRenderHint( QPainter::Antialiasing, true );
painter->setPen( QPen( brush, metrics.width(), Qt::SolidLine, Qt::FlatCap ) );
const int startAngle = qRound( metrics.startAngle() * 16 );

View File

@ -37,6 +37,66 @@ static inline QskHashValue qskColorsHash(
return fillGradient.hash( hash );
}
#if 1
#include "QskLinearGradient.h"
static inline QskLinearGradient qskEffectiveGradient( const QskGradient& gradient )
{
QskLinearGradient g;
if ( gradient.isVisible() )
{
if ( gradient.isMonochrome() )
{
g.setStops( gradient.startColor() );
}
else
{
switch( gradient.type() )
{
case QskGradient::Linear:
{
const auto& linearGradient = gradient.asLinearGradient();
if ( linearGradient.isVertical() )
{
g.setOrientation( Qt::Vertical );
}
else if ( linearGradient.isHorizontal() )
{
g.setOrientation( Qt::Horizontal );
}
else
{
g.setStart( 0.0, 0.0 );
g.setStop( 1.0, 1.0 );
}
g.setStops( gradient.stops() );
break;
}
case QskGradient::Radial:
case QskGradient::Conic:
{
qWarning() << "QskBoxNode does not support radial/conic gradients";
g.setStops( Qt::black );
break;
}
case QskGradient::Stops:
{
g.setStops( gradient.stops() );
break;
}
}
}
}
return g;
}
#endif
class QskBoxNodePrivate final : public QSGGeometryNodePrivate
{
public:
@ -79,13 +139,16 @@ void QskBoxNode::setBoxData( const QRectF& rect,
{
Q_D( QskBoxNode );
QskGradient fillGradient = gradient;
/*
QskBoxRenderer supports certain linear gradients only.
For everything else we would have to use a QskGradientMaterial instead.
As a temporary solution we simply "convert" gradient into a
simple QskLinearGradient so that at least something is happening.
TODO ...
*/
#if 1
// Renderer is buggy for monochrome gradients with stops. TODO ...
if ( fillGradient.stops().count() > 2 && fillGradient.isMonochrome() )
{
fillGradient.setStops( fillGradient.startColor() );
}
const auto fillGradient = qskEffectiveGradient( gradient );
#endif
const auto metricsHash = qskMetricsHash( shape, borderMetrics );

View File

@ -12,6 +12,7 @@
class QskBoxBorderMetrics;
class QskBoxBorderColors;
class QskLinearGradient;
class QskGradient;
class QSGGeometry;
@ -32,7 +33,7 @@ class QSK_EXPORT QskBoxRenderer
void renderBox( const QRectF&,
const QskBoxShapeMetrics&, const QskBoxBorderMetrics&,
const QskBoxBorderColors&, const QskGradient&, QSGGeometry& );
const QskBoxBorderColors&, const QskLinearGradient&, QSGGeometry& );
class Quad
{
@ -115,7 +116,7 @@ class QSK_EXPORT QskBoxRenderer
void renderRect( const QRectF&,
const QskBoxShapeMetrics&, const QskBoxBorderMetrics&,
const QskBoxBorderColors&, const QskGradient&, QSGGeometry& );
const QskBoxBorderColors&, const QskLinearGradient&, QSGGeometry& );
void renderRectellipseFill( const QRectF&,
const QskBoxShapeMetrics&, const QskBoxBorderMetrics&, QSGGeometry& );
@ -125,12 +126,12 @@ class QSK_EXPORT QskBoxRenderer
void renderRectellipse( const QRectF&,
const QskBoxShapeMetrics&, const QskBoxBorderMetrics&,
const QskBoxBorderColors&, const QskGradient&, QSGGeometry& );
const QskBoxBorderColors&, const QskLinearGradient&, QSGGeometry& );
void renderDiagonalFill( const Metrics&, const QskGradient&,
int lineCount, QskVertex::ColoredLine* );
void renderRectFill( const Quad&, const QskGradient&, QskVertex::ColoredLine* );
void renderRectFill( const Quad&, const QskLinearGradient&, QskVertex::ColoredLine* );
};
inline void QskBoxRenderer::renderBorder(
@ -155,7 +156,7 @@ inline void QskBoxRenderer::renderFill(
inline void QskBoxRenderer::renderBox( const QRectF& rect,
const QskBoxShapeMetrics& shape, const QskBoxBorderMetrics& border,
const QskBoxBorderColors& borderColors, const QskGradient& gradient,
const QskBoxBorderColors& borderColors, const QskLinearGradient& gradient,
QSGGeometry& geometry )
{
if ( shape.isRectangle() )

View File

@ -4,7 +4,7 @@
*****************************************************************************/
#include "QskBoxRenderer.h"
#include "QskGradient.h"
#include "QskLinearGradient.h"
#include "QskBoxBorderColors.h"
#include "QskBoxBorderMetrics.h"
@ -868,13 +868,13 @@ namespace
};
}
static inline Qt::Orientation qskQtOrientation( const QskGradient& gradient )
static inline Qt::Orientation qskQtOrientation( const QskLinearGradient& gradient )
{
return gradient.isVertical() ? Qt::Vertical : Qt::Horizontal;
}
static inline int qskFillLineCount(
const QskBoxRenderer::Metrics& metrics, const QskGradient& gradient )
const QskBoxRenderer::Metrics& metrics, const QskLinearGradient& gradient )
{
const int stepCount = metrics.corner[ 0 ].stepCount;
@ -1029,7 +1029,7 @@ static inline void qskRenderBorder( const QskBoxRenderer::Metrics& metrics,
static inline void qskRenderFillRandom(
const QskBoxRenderer::Metrics& metrics,
const QskGradient& gradient, ColoredLine* line )
const QskLinearGradient& gradient, ColoredLine* line )
{
const auto orientation = qskQtOrientation( gradient );
@ -1047,7 +1047,7 @@ static inline void qskRenderFillRandom(
static inline void qskRenderBoxRandom(
const QskBoxRenderer::Metrics& metrics, const QskBoxBorderColors& borderColors,
const QskGradient& gradient, ColoredLine* fillLine, ColoredLine* borderLine )
const QskLinearGradient& gradient, ColoredLine* fillLine, ColoredLine* borderLine )
{
const auto& bc = borderColors;
@ -1099,7 +1099,7 @@ static inline void qskRenderBoxRandom(
static inline void qskRenderFillOrdered(
const QskBoxRenderer::Metrics& metrics,
const QskGradient& gradient, ColoredLine* lines )
const QskLinearGradient& gradient, ColoredLine* lines )
{
const auto& r = metrics.innerQuad;
@ -1333,7 +1333,7 @@ void QskBoxRenderer::renderRectellipseFill(
void QskBoxRenderer::renderRectellipse( const QRectF& rect,
const QskBoxShapeMetrics& shape, const QskBoxBorderMetrics& border,
const QskBoxBorderColors& borderColors, const QskGradient& gradient,
const QskBoxBorderColors& borderColors, const QskLinearGradient& gradient,
QSGGeometry& geometry )
{
const Metrics metrics( rect, shape, border );

View File

@ -8,7 +8,7 @@
#include "QskBoxRenderer.h"
#include "QskBoxRendererColorMap.h"
#include "QskFunctions.h"
#include "QskGradient.h"
#include "QskLinearGradient.h"
#include "QskVertex.h"
using namespace QskVertex;
@ -343,7 +343,7 @@ namespace
}
static inline void qskCreateFillOrdered( const QskBoxRenderer::Quad& rect,
const QskGradient& gradient, ColoredLine* line )
const QskLinearGradient& gradient, ColoredLine* line )
{
if ( gradient.isHorizontal() )
{
@ -371,11 +371,10 @@ static inline void qskCreateFillOrdered( const QskBoxRenderer::Quad& rect,
}
template< class ColorMap, class Line >
static inline void qskCreateFillRandom(
QskGradient::Orientation orientation,
static inline void qskCreateFillRandom( Qt::Orientation orientation,
const QskBoxRenderer::Quad& r, const ColorMap& map, Line* line )
{
if ( orientation == QskGradient::Vertical )
if ( orientation == Qt::Vertical )
{
( line++ )->setLine( r.left, r.top, r.right, r.top, map.colorAt( 0.0 ) );
( line++ )->setLine( r.left, r.bottom, r.right, r.bottom, map.colorAt( 1.0 ) );
@ -549,15 +548,13 @@ void QskBoxRenderer::renderRectFill(
}
const auto line = allocateLines< Line >( geometry, 2 );
qskCreateFillRandom( QskGradient::Vertical,
in, ColorMapSolid( Color() ), line );
qskCreateFillRandom( Qt::Vertical, in, ColorMapSolid( Color() ), line );
}
void QskBoxRenderer::renderRect(
const QRectF& rect, const QskBoxShapeMetrics& shape,
const QskBoxBorderMetrics& border, const QskBoxBorderColors& borderColors,
const QskGradient& gradient, QSGGeometry& geometry )
const QskLinearGradient& gradient, QSGGeometry& geometry )
{
Q_UNUSED( shape )
@ -624,7 +621,7 @@ void QskBoxRenderer::renderRect(
if ( gd.isMonochrome() )
{
const ColorMapSolid colorMap( gd.startColor() );
qskCreateFillRandom( QskGradient::Vertical, in, colorMap, line );
qskCreateFillRandom( Qt::Vertical, in, colorMap, line );
}
else
{
@ -641,8 +638,10 @@ void QskBoxRenderer::renderRect(
if ( fillRandom )
{
const auto orientation = gd.isVertical() ? Qt::Vertical : Qt::Horizontal;
const ColorMapGradient colorMap( gd.startColor(), gd.endColor() );
qskCreateFillRandom( gd.orientation(), in, colorMap, line );
qskCreateFillRandom( orientation, in, colorMap, line );
}
else
{
@ -669,7 +668,7 @@ void QskBoxRenderer::renderRect(
}
void QskBoxRenderer::renderRectFill( const QskBoxRenderer::Quad& rect,
const QskGradient& gradient, QskVertex::ColoredLine* line )
const QskLinearGradient& gradient, QskVertex::ColoredLine* line )
{
qskCreateFillOrdered( rect, gradient, line );
}

View File

@ -7,7 +7,9 @@
#include "QskFunctions.h"
#include "QskRgbValue.h"
#include <qcoreapplication.h>
#include "QskLinearGradient.h"
#include "QskRadialGradient.h"
#include "QskConicGradient.h"
QSK_QT_PRIVATE_BEGIN
#include <private/qrhi_p.h>
@ -15,6 +17,7 @@ QSK_QT_PRIVATE_BEGIN
#include <private/qsgplaintexture_p.h>
QSK_QT_PRIVATE_END
#include <qcoreapplication.h>
#include <cmath>
// RHI shaders are supported by Qt 5.15 and Qt 6.x
@ -37,28 +40,15 @@ namespace
class GradientTexture : public QSGPlainTexture
{
public:
GradientTexture( const QGradientStops& stops, QGradient::Spread spread )
GradientTexture( const QskGradientStops& stops, QGradient::Spread spread )
{
#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 ) );
setImage( QskRgb::colorTable( 256, stops ) );
const auto wrapMode = this->wrapMode( spread );
@ -94,7 +84,7 @@ namespace
}
const void* rhi;
const QGradientStops stops;
const QskGradientStops stops;
const QGradient::Spread spread;
};
@ -103,7 +93,7 @@ namespace
size_t valus = seed + key.spread;
for ( const auto& stop : key.stops )
valus += stop.second.rgba();
valus += stop.rgb();
return valus;
}
@ -135,7 +125,7 @@ namespace
}
GradientTexture* texture( const void* rhi,
const QGradientStops& stops, QGradient::Spread spread )
const QskGradientStops& stops, QGradient::Spread spread )
{
const TextureHashKey key { rhi, stops, spread };
@ -197,7 +187,7 @@ namespace
class GradientMaterial : public QskGradientMaterial
{
public:
GradientMaterial( QGradient::Type type )
GradientMaterial( QskGradient::Type type )
: QskGradientMaterial( type )
{
setFlag( Blending | RequiresFullMatrix );
@ -323,11 +313,11 @@ namespace
{
public:
LinearMaterial()
: GradientMaterial( QGradient::LinearGradient )
: GradientMaterial( QskGradient::Linear )
{
}
bool setGradient( const QRectF& rect, const QLinearGradient& gradient )
bool setGradient( const QRectF& rect, const QskLinearGradient& gradient )
{
bool changed = false;
@ -350,8 +340,8 @@ namespace
const QVector4D vector(
rect.left() + gradient.start().x() * rect.width(),
rect.top() + gradient.start().y() * rect.height(),
gradient.finalStop().x() * rect.width(),
gradient.finalStop().y() * rect.height() );
gradient.stop().x() * rect.width(),
gradient.stop().y() * rect.height() );
if ( m_gradientVector != vector )
{
@ -476,7 +466,7 @@ namespace
{
public:
RadialMaterial()
: GradientMaterial( QGradient::RadialGradient )
: GradientMaterial( QskGradient::Radial )
{
}
@ -486,7 +476,7 @@ namespace
return &type;
}
bool setGradient( const QRectF& rect, const QRadialGradient& gradient )
bool setGradient( const QRectF& rect, const QskRadialGradient& gradient )
{
bool changed = false;
@ -647,7 +637,7 @@ namespace
{
public:
ConicMaterial()
: GradientMaterial( QGradient::ConicalGradient )
: GradientMaterial( QskGradient::Conic )
{
}
@ -657,7 +647,7 @@ namespace
return &type;
}
bool setGradient( const QRectF& rect, const QConicalGradient& gradient, qreal spanAngle )
bool setGradient( const QRectF& rect, const QskConicGradient& gradient )
{
bool changed = false;
@ -679,11 +669,11 @@ namespace
// Angles as ratio of a rotation
float start = fmod( gradient.angle(), 360.0 ) / 360.0;
float start = fmod( gradient.startAngle(), 360.0 ) / 360.0;
if ( start < 0.0)
start += 1.0;
const float span = fmod( spanAngle, 360.0 ) / 360.0;
const float span = fmod( gradient.spanAngle(), 360.0 ) / 360.0;
if ( center != m_center )
{
@ -826,7 +816,7 @@ namespace
}
}
QskGradientMaterial::QskGradientMaterial( QGradient::Type type )
QskGradientMaterial::QskGradientMaterial( QskGradient::Type type )
: m_gradientType( type )
{
}
@ -840,59 +830,54 @@ inline Material* qskEnsureMaterial( QskGradientMaterial* material )
return static_cast< Material* >( material );
}
bool QskGradientMaterial::updateGradient(
const QRectF& rect, const QGradient* g, qreal extraValue )
bool QskGradientMaterial::updateGradient( const QRectF& rect, const QskGradient& gradient )
{
Q_ASSERT( g );
if ( g == nullptr )
return false;
auto& gradient = *g;
Q_ASSERT( gradient.type() == m_gradientType );
if ( gradient.type() != m_gradientType )
return false;
switch ( static_cast< int >( gradient.type() ) )
switch ( gradient.type() )
{
case QGradient::LinearGradient:
case QskGradient::Linear:
{
auto material = static_cast< LinearMaterial* >( this );
return material->setGradient( rect,
*reinterpret_cast< const QLinearGradient* >( g ) );
return material->setGradient( rect, gradient.asLinearGradient() );
}
case QGradient::RadialGradient:
case QskGradient::Radial:
{
auto material = static_cast< RadialMaterial* >( this );
return material->setGradient( rect,
*reinterpret_cast< const QRadialGradient* >( g ) );
return material->setGradient( rect, gradient.asRadialGradient() );
}
case QGradient::ConicalGradient:
case QskGradient::Conic:
{
auto material = static_cast< ConicMaterial* >( this );
return material->setGradient( rect,
*reinterpret_cast< const QConicalGradient* >( g ), extraValue );
return material->setGradient( rect, gradient.asConicGradient() );
}
default:
{
qWarning( "Invalid gradient type" );
break;
}
}
return false;
}
QskGradientMaterial* QskGradientMaterial::createMaterial( QGradient::Type gradientType )
QskGradientMaterial* QskGradientMaterial::createMaterial( QskGradient::Type gradientType )
{
switch ( gradientType )
{
case QGradient::LinearGradient:
case QskGradient::Linear:
return new LinearMaterial();
case QGradient::RadialGradient:
case QskGradient::Radial:
return new RadialMaterial();
case QGradient::ConicalGradient:
case QskGradient::Conic:
return new ConicMaterial();
default:

View File

@ -7,39 +7,39 @@
#define QSK_GRADIENT_MATERIAL
#include "QskGlobal.h"
#include <qbrush.h>
#include "QskGradient.h"
#include <qsgmaterial.h>
class QSK_EXPORT QskGradientMaterial : public QSGMaterial
{
public:
static QskGradientMaterial* createMaterial( QGradient::Type );
static QskGradientMaterial* createMaterial( QskGradient::Type );
bool updateGradient( const QRectF&, const QGradient*, qreal );
QGradient::Type gradientType() const;
bool updateGradient( const QRectF&, const QskGradient& );
QskGradient::Type gradientType() const;
const QGradientStops& stops() const;
const QskGradientStops& stops() const;
QGradient::Spread spread() const;
protected:
QskGradientMaterial( QGradient::Type );
QskGradientMaterial( QskGradient::Type );
void setStops( const QGradientStops& );
void setStops( const QskGradientStops& );
void setSpread( QGradient::Spread );
private:
const QGradient::Type m_gradientType;
const QskGradient::Type m_gradientType;
QGradientStops m_stops;
QskGradientStops m_stops;
QGradient::Spread m_spread = QGradient::PadSpread;
};
inline QGradient::Type QskGradientMaterial::gradientType() const
inline QskGradient::Type QskGradientMaterial::gradientType() const
{
return m_gradientType;
}
inline void QskGradientMaterial::setStops( const QGradientStops& stops )
inline void QskGradientMaterial::setStops( const QskGradientStops& stops )
{
m_stops = stops;
}
@ -49,7 +49,7 @@ inline void QskGradientMaterial::setSpread( QGradient::Spread spread )
m_spread = spread;
}
inline const QGradientStops& QskGradientMaterial::stops() const
inline const QskGradientStops& QskGradientMaterial::stops() const
{
return m_stops;
}

View File

@ -5,8 +5,9 @@
#include "QskShapeNode.h"
#include "QskGradientMaterial.h"
#include "QskGradient.h"
#include "QskLinearGradient.h"
#include <qbrush.h>
#include <qsgflatcolormaterial.h>
QSK_QT_PRIVATE_BEGIN
@ -15,6 +16,14 @@ QSK_QT_PRIVATE_BEGIN
#include <private/qtriangulator_p.h>
QSK_QT_PRIVATE_END
static inline QskGradient qskEffectiveGradient( const QskGradient& gradient )
{
if ( gradient.type() == QskGradient::Stops )
return QskLinearGradient( Qt::Vertical, gradient.stops() );
return gradient;
}
static void qskUpdateGeometry( const QPainterPath& path,
const QTransform& transform, QSGGeometry& geometry )
{
@ -67,36 +76,6 @@ static inline void qskResetGeometry( QskShapeNode* node )
}
}
static inline bool qskIsGradientVisible( const QGradient* gradient )
{
if ( gradient && gradient->type() != QGradient::NoGradient )
{
for ( const auto& stop : gradient->stops() )
{
if ( stop.second.alpha() > 0 )
return true;
}
}
return false;
}
static inline bool qskIsGradientMonochrome( const QGradient* gradient )
{
if ( gradient && gradient->type() != QGradient::NoGradient )
{
const auto stops = gradient->stops();
for ( int i = 1; i < stops.count(); i++ )
{
if ( stops[i].second != stops[i - 1].second )
return false;
}
}
return true;
}
class QskShapeNodePrivate final : public QSGGeometryNodePrivate
{
public:
@ -107,7 +86,7 @@ class QskShapeNodePrivate final : public QSGGeometryNodePrivate
}
QSGGeometry geometry;
QGradient::Type gradientType = QGradient::NoGradient;
int gradientType = -1;
/*
Is there a better way to find out if the path has changed
@ -149,10 +128,10 @@ void QskShapeNode::updateNode( const QPainterPath& path,
markDirty( QSGNode::DirtyGeometry );
}
if ( material() == nullptr || d->gradientType != QGradient::NoGradient )
if ( material() == nullptr || d->gradientType >= 0 )
{
setMaterial( new QSGFlatColorMaterial() );
d->gradientType = QGradient::NoGradient;
d->gradientType = -1;
}
const auto c = color.toRgb();
@ -166,12 +145,11 @@ void QskShapeNode::updateNode( const QPainterPath& path,
}
void QskShapeNode::updateNode( const QPainterPath& path,
const QTransform& transform, const QRectF& rect,
const QGradient* gradient, qreal extraValue )
const QTransform& transform, const QRectF& rect, const QskGradient& gradient )
{
Q_D( QskShapeNode );
if ( path.isEmpty() || !qskIsGradientVisible( gradient ) )
if ( path.isEmpty() || !gradient.isVisible() )
{
d->path = QPainterPath();
qskResetGeometry( this );
@ -179,9 +157,9 @@ void QskShapeNode::updateNode( const QPainterPath& path,
return;
}
if ( qskIsGradientMonochrome( gradient ) )
if ( gradient.isMonochrome() )
{
updateNode( path, transform, gradient->stops().first().first );
updateNode( path, transform, gradient.stops().first().color() );
return;
}
@ -194,14 +172,18 @@ void QskShapeNode::updateNode( const QPainterPath& path,
markDirty( QSGNode::DirtyGeometry );
}
if ( ( material() == nullptr ) || ( gradient->type() != d->gradientType ) )
const auto effectiveGradient = qskEffectiveGradient( gradient );
const auto gradientType = effectiveGradient.type();
if ( ( material() == nullptr ) || ( gradientType != d->gradientType ) )
{
setMaterial( QskGradientMaterial::createMaterial( gradient->type() ) );
d->gradientType = gradient->type();
setMaterial( QskGradientMaterial::createMaterial( gradientType ) );
d->gradientType = gradientType;
}
auto gradientMaterial = static_cast< QskGradientMaterial* >( material() );
if ( gradientMaterial->updateGradient( rect, gradient, extraValue ) )
if ( gradientMaterial->updateGradient( rect, effectiveGradient ) )
markDirty( QSGNode::DirtyMaterial );
}

View File

@ -9,7 +9,7 @@
#include "QskGlobal.h"
#include <qsgnode.h>
class QGradient;
class QskGradient;
class QColor;
class QPainterPath;
@ -21,7 +21,7 @@ class QSK_EXPORT QskShapeNode : public QSGGeometryNode
QskShapeNode();
void updateNode( const QPainterPath&, const QTransform&,
const QRectF&, const QGradient*, qreal = 0.0 );
const QRectF&, const QskGradient& );
void updateNode( const QPainterPath&,
const QTransform&, const QColor& );

Binary file not shown.

Binary file not shown.

View File

@ -27,6 +27,9 @@ HEADERS += \
common/QskGlobal.h \
common/QskGradient.h \
common/QskGradientStop.h \
common/QskConicGradient.h \
common/QskLinearGradient.h \
common/QskRadialGradient.h \
common/QskHctColor.h \
common/QskIntervalF.h \
common/QskMargins.h \
@ -55,6 +58,9 @@ SOURCES += \
common/QskBoxHints.cpp \
common/QskFunctions.cpp \
common/QskGradient.cpp \
common/QskConicGradient.cpp \
common/QskLinearGradient.cpp \
common/QskRadialGradient.cpp \
common/QskGradientStop.cpp \
common/QskHctColor.cpp \
common/QskIntervalF.cpp \