Box renderer: Support border gradients (#158)

* QskBoxBorderColors: Use gradients instead of colors

* QskBoxBorderColors: rename API

* render gradients on borders

* boxes example: Also draw gradient borders

* calculate proper numbers of needed border colors

* fixup with example

* support rounded corners

* support more colors in rounded color gradients

I THINK WE DON'T REALLY NEED THIS COMMIT

* We don't need this commit either

* Revert "We don't need this commit either"

This reverts commit 2dc38064f7fee1d0505262fe5cebcf9e1fb16cea.

* Revert "support more colors in rounded color gradients"

This reverts commit 5754d2d0773d8273d42ae1775b53d40f5e6af26a.

* fix borders for rect ellipses

* play around a bit

* small fixes

* some helper stuff and missing stuff

* user border colors

* close to something working somehow

* works a bit better

* put it into an own function

* rearrange a bit

* something's off

* still off, but seems like we need an additional line

* works but hackish

* now it works

* bring back samples

* correction

* pimp up example

* fix normal rendering

* some more debugging etc.

* turn around gradients

* turn around rectangular gradients as well

* turn around easier

* more test cases

* fix fill case

* more test cases

* clean up a bit

* clean up example

* clean up some more

* incorporate feedback from Uwe

* fix bug when using horizontal gradients
This commit is contained in:
Peter Hartmann 2022-02-04 16:11:11 +01:00 committed by GitHub
parent 4c7c369477
commit ac8ef9cd5a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 496 additions and 180 deletions

View File

@ -80,23 +80,23 @@ void Box::setBorder( BorderType type, QskRgbPalette::Theme theme )
break; break;
case Flat: case Flat:
setBorderColor( mid ); setBorderGradient( mid );
break; break;
case Raised1: case Raised1:
setBorderColors( light, light, dark, dark ); setBorderGradients( light, light, dark, dark );
break; break;
case Sunken1: case Sunken1:
setBorderColors( dark, dark, light, light ); setBorderGradients( dark, dark, light, light );
break; break;
case Raised2: case Raised2:
setBorderColors( mid, light, mid, dark ); setBorderGradients( mid, light, mid, dark );
break; break;
case Sunken2: case Sunken2:
setBorderColors( mid, dark, mid, light ); setBorderGradients( mid, dark, mid, light );
break; break;
} }
} }
@ -117,16 +117,16 @@ void Box::setShape( qreal radiusX, qreal radiusY, Qt::SizeMode sizeMode )
QskBoxShapeMetrics( radiusX, radiusY, sizeMode ) ); QskBoxShapeMetrics( radiusX, radiusY, sizeMode ) );
} }
void Box::setBorderColors( const QColor& left, const QColor& top, void Box::setBorderGradients( const QskGradient& left, const QskGradient& top,
const QColor& right, const QColor& bottom ) const QskGradient& right, const QskGradient& bottom )
{ {
QskBoxBorderColors colors( left, top, right, bottom ); QskBoxBorderColors colors( left, top, right, bottom );
setBoxBorderColorsHint( QskBox::Panel, colors ); setBoxBorderColorsHint( QskBox::Panel, colors );
} }
void Box::setBorderColor( const QColor& color ) void Box::setBorderGradient( const QskGradient& gradient )
{ {
setBoxBorderColorsHint( QskBox::Panel, color ); setBoxBorderColorsHint( QskBox::Panel, gradient );
} }
void Box::setBorderWidth( qreal left, qreal top, qreal right, qreal bottom ) void Box::setBorderWidth( qreal left, qreal top, qreal right, qreal bottom )

View File

@ -39,9 +39,9 @@ class Box : public QskBox
void setShape( qreal radius, Qt::SizeMode ); void setShape( qreal radius, Qt::SizeMode );
void setShape( qreal radiusX, qreal radiusY, Qt::SizeMode ); void setShape( qreal radiusX, qreal radiusY, Qt::SizeMode );
void setBorderColor( const QColor& ); void setBorderGradient( const QskGradient& );
void setBorderColors( const QColor& left, const QColor& top, void setBorderGradients( const QskGradient& left, const QskGradient& top,
const QColor& right, const QColor& bottom ); const QskGradient& right, const QskGradient& bottom );
void setBorderWidth( int ); void setBorderWidth( int );
void setBorderWidth( qreal left, qreal top, qreal right, qreal bottom ); void setBorderWidth( qreal left, qreal top, qreal right, qreal bottom );

View File

@ -232,25 +232,25 @@ static void addRectangles10( QskLinearBox* parent )
box = new Box( parent ); box = new Box( parent );
box->setBorderWidth( 10 ); box->setBorderWidth( 10 );
box->setBorderColor( borderTheme ); box->setBorderGradient( borderTheme );
box->setGradient( QskGradient::Diagonal, "DeepPink", "DarkOrange", "HotPink" ); box->setGradient( QskGradient::Diagonal, "DeepPink", "DarkOrange", "HotPink" );
box = new Box( parent ); box = new Box( parent );
box->setShape( 100, Qt::RelativeSize ); box->setShape( 100, Qt::RelativeSize );
box->setBorderWidth( 5 ); box->setBorderWidth( 5 );
box->setBorderColor( borderTheme ); box->setBorderGradient( borderTheme );
box->setGradient( QskGradient::Vertical, "DeepPink", "DarkOrange", "HotPink" ); box->setGradient( QskGradient::Vertical, "DeepPink", "DarkOrange", "HotPink" );
box = new Box( parent ); box = new Box( parent );
box->setShape( 100, Qt::RelativeSize ); box->setShape( 100, Qt::RelativeSize );
box->setBorderWidth( 5 ); box->setBorderWidth( 5 );
box->setBorderColor( borderTheme ); box->setBorderGradient( borderTheme );
box->setGradient( QskGradient::Diagonal, "DeepPink", "DarkOrange", "HotPink" ); box->setGradient( QskGradient::Diagonal, "DeepPink", "DarkOrange", "HotPink" );
box = new Box( parent ); box = new Box( parent );
box->setShape( 100, Qt::RelativeSize ); box->setShape( 100, Qt::RelativeSize );
box->setBorderWidth( 5, 20, 30, 5 ); box->setBorderWidth( 5, 20, 30, 5 );
box->setBorderColor( borderTheme ); box->setBorderGradient( borderTheme );
box->setGradient( QskGradient::Vertical, "DeepPink", "DarkOrange", "HotPink" ); box->setGradient( QskGradient::Vertical, "DeepPink", "DarkOrange", "HotPink" );
} }
@ -333,32 +333,127 @@ static void addRectanglesRest( QskLinearBox* parent )
box = new Box( parent ); box = new Box( parent );
box->setBorderWidth( 20, 0, 40, 0 ); box->setBorderWidth( 20, 0, 40, 0 );
box->setBorderColor( "DarkSeaGreen" ); box->setBorderGradient( { "DarkSeaGreen" } );
box = new Box( parent ); box = new Box( parent );
box->setShape( 40, Qt::RelativeSize ); box->setShape( 40, Qt::RelativeSize );
box->setBorderWidth( 20, 10, 30, 15 ); box->setBorderWidth( 20, 10, 30, 15 );
box->setBorderColor( "DarkOrange" ); box->setBorderGradient( { "DarkOrange" } );
box->setGradient( QskGradient::Vertical, "LightSteelBlue", "SteelBlue" ); box->setGradient( QskGradient::Vertical, "LightSteelBlue", "SteelBlue" );
box = new Box( parent ); box = new Box( parent );
box->setBorderWidth( 20, 0, 10, 20 ); box->setBorderWidth( 20, 0, 10, 20 );
box->setBorderColor( "MediumSeaGreen" ); box->setBorderGradient( { "MediumSeaGreen" } );
box->setGradient( "DodgerBlue" ); box->setGradient( "DodgerBlue" );
box = new Box( parent ); box = new Box( parent );
box->setShape( 20, Qt::AbsoluteSize ); box->setShape( 20, Qt::AbsoluteSize );
box->setBorderWidth( 2, 10, 40, 2 ); box->setBorderWidth( 2, 10, 40, 2 );
box->setBorderColor( "Crimson" ); box->setBorderGradient( { "Crimson" } );
box->setGradient( QskRgb::WhiteSmoke ); box->setGradient( QskRgb::WhiteSmoke );
box = new Box( parent ); box = new Box( parent );
box->setShape( 100, Qt::RelativeSize ); box->setShape( 100, Qt::RelativeSize );
box->setBorderWidth( 5, 20, 5, 0 ); box->setBorderWidth( 5, 20, 5, 0 );
box->setBorderColor( "CadetBlue" ); box->setBorderGradient( { "CadetBlue" } );
box->setGradient( QskGradient::Vertical, "Gainsboro", "Seashell", "LightGray" ); box->setGradient( QskGradient::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 );
if( fillType != Box::Unfilled )
box->setBackground( fillType, QskRgbPalette::Indigo );
if( rounded )
box->setShape( 30, Qt::AbsoluteSize );
}
static void addColoredBorderRectangles2( QskLinearBox* parent, bool rounded, Box::FillType fillType )
{
Box* box = new Box( parent );
box->setBorderWidth( 20 );
box->setBorderGradients( Qt::red, Qt::green, Qt::blue, Qt::yellow );
if( fillType != Box::Unfilled )
box->setBackground( fillType, QskRgbPalette::Indigo );
if( rounded )
box->setShape( 30, Qt::AbsoluteSize );
}
static void addColoredBorderRectangles3( QskLinearBox* parent, bool rounded, Box::FillType fillType )
{
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 );
if( fillType != Box::Unfilled )
box->setBackground( fillType, QskRgbPalette::Indigo );
if( rounded )
box->setShape( 30, Qt::AbsoluteSize );
}
static void addColoredBorderRectangles4( QskLinearBox* parent, bool rounded, Box::FillType fillType )
{
Box* box = new Box( parent );
box->setBorderWidth( 20 );
QskGradient gradient( Qt::Vertical, Qt::magenta, Qt::cyan );
box->setBorderGradients( gradient, gradient, gradient, gradient );
if( fillType != Box::Unfilled )
box->setBackground( fillType, QskRgbPalette::Indigo );
if( rounded )
box->setShape( 30, Qt::AbsoluteSize );
}
static void addColoredBorderRectangles5( QskLinearBox* parent, bool rounded, Box::FillType fillType )
{
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 );
if( fillType != Box::Unfilled )
box->setBackground( fillType, QskRgbPalette::Indigo );
if( rounded )
box->setShape( { 10, 20, 20, 40 } );
}
class TabView : public QskTabView class TabView : public QskTabView
{ {
public: public:
@ -399,6 +494,45 @@ class TabView : public QskTabView
addTab( tab4 ); addTab( tab4 );
//setCurrentIndex( count() - 1 ); // setCurrentTab( tab4 ) -> TODO //setCurrentIndex( count() - 1 ); // setCurrentTab( tab4 ) -> TODO
#endif #endif
auto* tab5 = new QskLinearBox( Qt::Horizontal, 5 );
addColoredBorderRectangles1( tab5, false, Box::Unfilled );
addColoredBorderRectangles2( tab5, false, Box::Unfilled );
addColoredBorderRectangles3( tab5, false, Box::Unfilled );
addColoredBorderRectangles4( tab5, false, Box::Unfilled );
addColoredBorderRectangles5( tab5, false, Box::Unfilled );
addColoredBorderRectangles1( tab5, true, Box::Unfilled );
addColoredBorderRectangles2( tab5, true, Box::Unfilled );
addColoredBorderRectangles3( tab5, true, Box::Unfilled );
addColoredBorderRectangles4( tab5, true, Box::Unfilled );
addColoredBorderRectangles5( tab5, true, Box::Unfilled );
addColoredBorderRectangles1( tab5, false, Box::Horizontal );
addColoredBorderRectangles2( tab5, false, Box::Horizontal );
addColoredBorderRectangles3( tab5, false, Box::Horizontal );
addColoredBorderRectangles4( tab5, false, Box::Horizontal );
addColoredBorderRectangles5( tab5, false, Box::Horizontal );
addColoredBorderRectangles1( tab5, true, Box::Horizontal );
addColoredBorderRectangles2( tab5, true, Box::Horizontal );
addColoredBorderRectangles3( tab5, true, Box::Horizontal );
addColoredBorderRectangles4( tab5, true, Box::Horizontal );
addColoredBorderRectangles5( tab5, true, Box::Horizontal );
addColoredBorderRectangles1( tab5, false, Box::Vertical );
addColoredBorderRectangles2( tab5, false, Box::Vertical );
addColoredBorderRectangles3( tab5, false, Box::Vertical );
addColoredBorderRectangles4( tab5, false, Box::Vertical );
addColoredBorderRectangles5( tab5, false, Box::Vertical );
addColoredBorderRectangles1( tab5, true, Box::Vertical );
addColoredBorderRectangles2( tab5, true, Box::Vertical );
addColoredBorderRectangles3( tab5, true, Box::Vertical );
addColoredBorderRectangles4( tab5, true, Box::Vertical );
addColoredBorderRectangles5( tab5, true, Box::Vertical );
addTab( tab5 );
} }
private: private:

View File

@ -602,7 +602,7 @@ void Editor::setupTabButton()
QskBoxBorderColors borderColors( QskRgb::White ); QskBoxBorderColors borderColors( QskRgb::White );
setBoxBorderColors( aspect, borderColors ); setBoxBorderColors( aspect, borderColors );
borderColors.setColorsAt( edge, m_pal.accentColor ); borderColors.setGradientAt( edge, m_pal.accentColor );
for ( auto state : { Q::Checked, Q::Pressed, Q::Hovered } ) for ( auto state : { Q::Checked, Q::Pressed, Q::Hovered } )
setBoxBorderColors( aspect | state, borderColors ); setBoxBorderColors( aspect | state, borderColors );
} }
@ -750,8 +750,8 @@ void Editor::setupSubWindow()
setGradient( Q::Panel, m_pal.baseColor ); setGradient( Q::Panel, m_pal.baseColor );
QskBoxBorderColors colors; QskBoxBorderColors colors;
colors.setColorsAt( Qt::TopEdge | Qt::LeftEdge, m_pal.lighter125 ); colors.setGradientAt( Qt::TopEdge | Qt::LeftEdge, m_pal.lighter125 );
colors.setColorsAt( Qt::RightEdge | Qt::BottomEdge, m_pal.darker200 ); colors.setGradientAt( Qt::RightEdge | Qt::BottomEdge, m_pal.darker200 );
setBoxBorderColors( Q::Panel, colors ); setBoxBorderColors( Q::Panel, colors );

View File

@ -198,23 +198,23 @@ void Editor::setButton( QskAspect aspect, PanelStyle style, qreal border )
{ {
case Raised: case Raised:
{ {
borderColors.setColorsAt( Qt::TopEdge | Qt::LeftEdge, m_pal.lighter135 ); borderColors.setGradientAt( Qt::TopEdge | Qt::LeftEdge, m_pal.lighter135 );
borderColors.setColorsAt( Qt::RightEdge | Qt::BottomEdge, m_pal.darker200 ); borderColors.setGradientAt( Qt::RightEdge | Qt::BottomEdge, m_pal.darker200 );
gradient.setColors( m_pal.lighter125, m_pal.lighter110 ); gradient.setColors( m_pal.lighter125, m_pal.lighter110 );
break; break;
} }
case Sunken: case Sunken:
{ {
borderColors.setColorsAt( Qt::TopEdge | Qt::LeftEdge, m_pal.darker200 ); borderColors.setGradientAt( Qt::TopEdge | Qt::LeftEdge, m_pal.darker200 );
borderColors.setColorsAt( Qt::RightEdge | Qt::BottomEdge, m_pal.lighter135 ); borderColors.setGradientAt( Qt::RightEdge | Qt::BottomEdge, m_pal.lighter135 );
gradient.setColors( m_pal.lighter110, m_pal.lighter125 ); gradient.setColors( m_pal.lighter110, m_pal.lighter125 );
break; break;
} }
case Plain: case Plain:
{ {
borderColors.setColors( m_pal.darker125 ); borderColors.setGradients( m_pal.darker125 );
gradient.setColor( m_pal.lighter125 ); gradient.setColor( m_pal.lighter125 );
break; break;
@ -225,7 +225,7 @@ void Editor::setButton( QskAspect aspect, PanelStyle style, qreal border )
QColor noColor( m_pal.theme ); QColor noColor( m_pal.theme );
noColor.setAlpha( 0 ); noColor.setAlpha( 0 );
borderColors.setColors( noColor ); borderColors.setGradients( noColor );
gradient.setColor( noColor ); gradient.setColor( noColor );
if ( style == NoPanel ) if ( style == NoPanel )
@ -859,8 +859,8 @@ void Editor::setupSubWindow()
setBoxShape( Q::Panel, radius, radius, 0, 0, Qt::AbsoluteSize ); setBoxShape( Q::Panel, radius, radius, 0, 0, Qt::AbsoluteSize );
QskBoxBorderColors borderColors; QskBoxBorderColors borderColors;
borderColors.setColorsAt( Qt::TopEdge | Qt::LeftEdge, m_pal.lighter125 ); borderColors.setGradientAt( Qt::TopEdge | Qt::LeftEdge, m_pal.lighter125 );
borderColors.setColorsAt( Qt::RightEdge | Qt::BottomEdge, m_pal.darker200 ); borderColors.setGradientAt( Qt::RightEdge | Qt::BottomEdge, m_pal.darker200 );
setBoxBorderColors( Q::Panel, borderColors ); setBoxBorderColors( Q::Panel, borderColors );
setGradient( Q::Panel, m_pal.lighter135 ); setGradient( Q::Panel, m_pal.lighter135 );

View File

@ -15,28 +15,26 @@ static void qskRegisterBoxBorderColors()
QMetaType::registerConverter< QColor, QskBoxBorderColors >( QMetaType::registerConverter< QColor, QskBoxBorderColors >(
[]( const QColor& color ) { return QskBoxBorderColors( color ); } ); []( const QColor& color ) { return QskBoxBorderColors( color ); } );
QMetaType::registerConverter< QskGradient, QskBoxBorderColors >(
[]( const QskGradient& gradient ) { return QskBoxBorderColors( gradient ); } );
} }
Q_CONSTRUCTOR_FUNCTION( qskRegisterBoxBorderColors ) Q_CONSTRUCTOR_FUNCTION( qskRegisterBoxBorderColors )
static inline bool qskIsVisble( const QColor& c ) static inline void qskSetGradients( const QskGradient& gradient, QskGradient* gradients )
{ {
return c.isValid() && ( c.alpha() > 0 ); gradients[ 0 ] = gradients[ 1 ] = gradients[ 2 ] = gradients[ 3 ] = gradient;
} }
static inline void qskSetColors( const QColor& c, QColor* colors ) static inline void qskSetGradients(
const QskGradient& left, const QskGradient& top,
const QskGradient& right, const QskGradient& bottom, QskGradient* gradients )
{ {
colors[ 0 ] = colors[ 1 ] = colors[ 2 ] = colors[ 3 ] = c.toRgb(); gradients[ Qsk::Left ] = left;
} gradients[ Qsk::Top ] = top;
gradients[ Qsk::Right ] = right;
static inline void qskSetColors( gradients[ Qsk::Bottom ] = bottom;
const QColor& left, const QColor& top,
const QColor& right, const QColor& bottom, QColor* colors )
{
colors[ Qsk::Left ] = left.toRgb();
colors[ Qsk::Top ] = top.toRgb();
colors[ Qsk::Right ] = right.toRgb();
colors[ Qsk::Bottom ] = bottom.toRgb();
} }
QskBoxBorderColors::QskBoxBorderColors() QskBoxBorderColors::QskBoxBorderColors()
@ -44,15 +42,20 @@ QskBoxBorderColors::QskBoxBorderColors()
} }
QskBoxBorderColors::QskBoxBorderColors( QskBoxBorderColors::QskBoxBorderColors(
const QColor& left, const QColor& top, const QskGradient& left, const QskGradient& top,
const QColor& right, const QColor& bottom ) const QskGradient& right, const QskGradient& bottom )
{ {
qskSetColors( left, top, right, bottom, m_colors ); qskSetGradients( left, top, right, bottom, m_gradients );
} }
QskBoxBorderColors::QskBoxBorderColors( const QColor& color ) QskBoxBorderColors::QskBoxBorderColors( const QColor& color )
{ {
qskSetColors( color, m_colors ); qskSetGradients( color, m_gradients );
}
QskBoxBorderColors::QskBoxBorderColors( const QskGradient& gradient )
{
qskSetGradients( gradient, m_gradients );
} }
QskBoxBorderColors::~QskBoxBorderColors() QskBoxBorderColors::~QskBoxBorderColors()
@ -61,88 +64,85 @@ QskBoxBorderColors::~QskBoxBorderColors()
bool QskBoxBorderColors::operator==( const QskBoxBorderColors& other ) const bool QskBoxBorderColors::operator==( const QskBoxBorderColors& other ) const
{ {
return ( m_colors[ 0 ] == other.m_colors[ 0 ] ) && return ( m_gradients[ 0 ] == other.m_gradients[ 0 ] ) &&
( m_colors[ 1 ] == other.m_colors[ 1 ] ) && ( m_gradients[ 1 ] == other.m_gradients[ 1 ] ) &&
( m_colors[ 2 ] == other.m_colors[ 2 ] ) && ( m_gradients[ 2 ] == other.m_gradients[ 2 ] ) &&
( m_colors[ 3 ] == other.m_colors[ 3 ] ); ( m_gradients[ 3 ] == other.m_gradients[ 3 ] );
} }
void QskBoxBorderColors::setAlpha( int alpha ) void QskBoxBorderColors::setAlpha( int alpha )
{ {
for ( int i = 0; i < 4; i++ ) for ( int i = 0; i < 4; i++ )
{ {
if ( m_colors[ i ].isValid() && m_colors[ i ].alpha() ) if ( m_gradients[ i ].isValid() )
m_colors[ i ].setAlpha( alpha ); m_gradients[ i ].setAlpha( alpha );
} }
} }
void QskBoxBorderColors::setColors( const QColor& color ) void QskBoxBorderColors::setGradients( const QskGradient& gradient )
{ {
qskSetColors( color, m_colors ); qskSetGradients( gradient, m_gradients );
} }
void QskBoxBorderColors::setColors( void QskBoxBorderColors::setGradients( const QskGradient& left, const QskGradient& top,
const QColor& left, const QColor& top, const QskGradient& right, const QskGradient& bottom )
const QColor& right, const QColor& bottom )
{ {
qskSetColors( left, top, right, bottom, m_colors ); qskSetGradients( left, top, right, bottom, m_gradients );
} }
void QskBoxBorderColors::setColor( void QskBoxBorderColors::setGradient( Qsk::Position position, const QskGradient& gradient )
Qsk::Position position, const QColor& color )
{ {
m_colors[ position ] = color.toRgb(); m_gradients[ position ] = gradient;
} }
void QskBoxBorderColors::setColorsAt( Qt::Edges edges, const QColor& color ) void QskBoxBorderColors::setGradientAt( Qt::Edges edges, const QskGradient& gradient )
{ {
const QColor c = color.toRgb();
if ( edges & Qt::TopEdge ) if ( edges & Qt::TopEdge )
m_colors[ Qsk::Top ] = c; m_gradients[ Qsk::Top ] = gradient;
if ( edges & Qt::LeftEdge ) if ( edges & Qt::LeftEdge )
m_colors[ Qsk::Left ] = c; m_gradients[ Qsk::Left ] = gradient;
if ( edges & Qt::RightEdge ) if ( edges & Qt::RightEdge )
m_colors[ Qsk::Right ] = c; m_gradients[ Qsk::Right ] = gradient;
if ( edges & Qt::BottomEdge ) if ( edges & Qt::BottomEdge )
m_colors[ Qsk::Bottom ] = c; m_gradients[ Qsk::Bottom ] = gradient;
} }
QColor QskBoxBorderColors::colorAt( Qt::Edge edge ) const const QskGradient& QskBoxBorderColors::gradientAt( Qt::Edge edge ) const
{ {
switch ( edge ) switch ( edge )
{ {
case Qt::TopEdge: case Qt::TopEdge:
return m_colors[ Qsk::Top ]; return m_gradients[ Qsk::Top ];
case Qt::LeftEdge: case Qt::LeftEdge:
return m_colors[ Qsk::Left ]; return m_gradients[ Qsk::Left ];
case Qt::RightEdge: case Qt::RightEdge:
return m_colors[ Qsk::Right ]; return m_gradients[ Qsk::Right ];
case Qt::BottomEdge: case Qt::BottomEdge:
return m_colors[ Qsk::Bottom ]; return m_gradients[ Qsk::Bottom ];
} }
return QColor(); static QskGradient noGradient;
return noGradient;
} }
bool QskBoxBorderColors::isVisible() const bool QskBoxBorderColors::isVisible() const
{ {
if ( qskIsVisble( m_colors[ 0 ] ) ) if ( m_gradients[ 0 ].isVisible() )
return true; return true;
if ( qskIsVisble( m_colors[ 1 ] ) ) if ( m_gradients[ 1 ].isVisible() )
return true; return true;
if ( qskIsVisble( m_colors[ 2 ] ) ) if ( m_gradients[ 2 ].isVisible() )
return true; return true;
if ( qskIsVisble( m_colors[ 3 ] ) ) if ( m_gradients[ 3 ].isVisible() )
return true; return true;
return false; return false;
@ -150,16 +150,19 @@ bool QskBoxBorderColors::isVisible() const
bool QskBoxBorderColors::isMonochrome() const bool QskBoxBorderColors::isMonochrome() const
{ {
if ( m_colors[ 1 ] != m_colors[ 0 ] ) if ( m_gradients[ 1 ] != m_gradients[ 0 ] )
return false; return false;
if ( m_colors[ 2 ] != m_colors[ 1 ] ) if ( m_gradients[ 2 ] != m_gradients[ 1 ] )
return false; return false;
if ( m_colors[ 3 ] != m_colors[ 2 ] ) if ( m_gradients[ 3 ] != m_gradients[ 2 ] )
return false; return false;
return true; return m_gradients[ 0 ].isMonochrome()
&& m_gradients[ 1 ].isMonochrome()
&& m_gradients[ 2 ].isMonochrome()
&& m_gradients[ 3 ].isMonochrome();
} }
QskBoxBorderColors QskBoxBorderColors::interpolated( QskBoxBorderColors QskBoxBorderColors::interpolated(
@ -169,8 +172,8 @@ QskBoxBorderColors QskBoxBorderColors::interpolated(
for ( size_t i = 0; i < 4; i++ ) for ( size_t i = 0; i < 4; i++ )
{ {
colors.m_colors[ i ] = QskRgb::interpolated( colors.m_gradients[ i ] = colors.m_gradients[ i ].interpolated(
m_colors[ i ], to.m_colors[ i ], ratio ); to.m_gradients[ i ], ratio );
} }
return colors; return colors;
@ -184,30 +187,18 @@ QVariant QskBoxBorderColors::interpolate(
uint QskBoxBorderColors::hash( uint seed ) const uint QskBoxBorderColors::hash( uint seed ) const
{ {
const QRgb rgb[] = uint h = m_gradients[ 0 ].hash( seed );
{ h = m_gradients[ 1 ].hash( h );
m_colors[ 0 ].rgba(), h = m_gradients[ 2 ].hash( h );
m_colors[ 1 ].rgba(), h = m_gradients[ 3 ].hash( h );
m_colors[ 2 ].rgba(),
m_colors[ 3 ].rgba(),
};
return qHashBits( rgb, sizeof( rgb ), seed ); return h;
} }
#ifndef QT_NO_DEBUG_STREAM #ifndef QT_NO_DEBUG_STREAM
#include <qdebug.h> #include <qdebug.h>
static inline void qskDebugColor( QDebug debug, const QColor& c )
{
debug << '('
<< c.red() << ','
<< c.green() << ','
<< c.blue() << ','
<< c.alpha() << ')';
}
QDebug operator<<( QDebug debug, const QskBoxBorderColors& colors ) QDebug operator<<( QDebug debug, const QskBoxBorderColors& colors )
{ {
QDebugStateSaver saver( debug ); QDebugStateSaver saver( debug );
@ -215,17 +206,13 @@ QDebug operator<<( QDebug debug, const QskBoxBorderColors& colors )
debug << "BoxBorderColors" << '('; debug << "BoxBorderColors" << '(';
debug << " L"; debug << " L" << colors.gradient( Qsk::Left );
qskDebugColor( debug, colors.color( Qsk::Left ) );
debug << ", T"; debug << ", T" << colors.gradient( Qsk::Top );
qskDebugColor( debug, colors.color( Qsk::Top ) );
debug << ", R"; debug << ", R" << colors.gradient( Qsk::Right );
qskDebugColor( debug, colors.color( Qsk::Right ) );
debug << ", B"; debug << ", B" << colors.gradient( Qsk::Bottom );
qskDebugColor( debug, colors.color( Qsk::Bottom ) );
debug << " )"; debug << " )";

View File

@ -6,6 +6,7 @@
#ifndef QSK_BOX_BORDER_COLORS_H #ifndef QSK_BOX_BORDER_COLORS_H
#define QSK_BOX_BORDER_COLORS_H #define QSK_BOX_BORDER_COLORS_H
#include "QskGradient.h"
#include "QskNamespace.h" #include "QskNamespace.h"
#include <qcolor.h> #include <qcolor.h>
@ -18,12 +19,13 @@ class QSK_EXPORT QskBoxBorderColors
public: public:
QskBoxBorderColors(); QskBoxBorderColors();
QskBoxBorderColors( const QColor& left, const QColor& top, QskBoxBorderColors( const QskGradient& left, const QskGradient& top,
const QColor& right, const QColor& bottom ); const QskGradient& right, const QskGradient& bottom );
QskBoxBorderColors( Qt::GlobalColor ); QskBoxBorderColors( Qt::GlobalColor );
QskBoxBorderColors( QRgb ); QskBoxBorderColors( QRgb );
QskBoxBorderColors( const QColor& ); QskBoxBorderColors( const QColor& );
QskBoxBorderColors( const QskGradient& );
~QskBoxBorderColors(); ~QskBoxBorderColors();
@ -32,17 +34,15 @@ class QSK_EXPORT QskBoxBorderColors
void setAlpha( int alpha ); void setAlpha( int alpha );
void setColors( const QColor& ); void setGradients( const QskGradient& );
void setColors( const QColor& left, const QColor& top, void setGradients( const QskGradient& left, const QskGradient& top,
const QColor& right, const QColor& bottom ); const QskGradient& right, const QskGradient& bottom );
void setColor( Qsk::Position, const QColor& ); void setGradient( Qsk::Position, const QskGradient& );
QColor color( Qsk::Position ) const; QskGradient gradient( Qsk::Position ) const;
void setColorsAt( Qt::Edges, const QColor& ); void setGradientAt( Qt::Edges, const QskGradient& );
QColor colorAt( Qt::Edge ) const; const QskGradient& gradientAt( Qt::Edge ) const;
QRgb rgb( Qsk::Position ) const;
QskBoxBorderColors interpolated( const QskBoxBorderColors&, qreal value ) const; QskBoxBorderColors interpolated( const QskBoxBorderColors&, qreal value ) const;
@ -55,8 +55,7 @@ class QSK_EXPORT QskBoxBorderColors
bool isVisible() const; bool isVisible() const;
private: private:
// should be stored as QRgb QskGradient m_gradients[ 4 ];
QColor m_colors[ 4 ];
}; };
inline QskBoxBorderColors::QskBoxBorderColors( Qt::GlobalColor color ) inline QskBoxBorderColors::QskBoxBorderColors( Qt::GlobalColor color )
@ -74,14 +73,9 @@ inline bool QskBoxBorderColors::operator!=( const QskBoxBorderColors& other ) co
return !( *this == other ); return !( *this == other );
} }
inline QColor QskBoxBorderColors::color( Qsk::Position position ) const inline QskGradient QskBoxBorderColors::gradient( Qsk::Position position ) const
{ {
return m_colors[ position ]; return m_gradients[ position ];
}
inline QRgb QskBoxBorderColors::rgb( Qsk::Position position ) const
{
return m_colors[ position ].rgba();
} }
#ifndef QT_NO_DEBUG_STREAM #ifndef QT_NO_DEBUG_STREAM

View File

@ -471,9 +471,9 @@ void QskSkinHintTableEditor::setBoxBorderColors(
setColorHint( aspectBorder( aspect ), borderColors, combination ); setColorHint( aspectBorder( aspect ), borderColors, combination );
} }
void QskSkinHintTableEditor::setBoxBorderColors( QskAspect aspect, void QskSkinHintTableEditor::setBoxBorderColors(QskAspect aspect,
const QColor& left, const QColor& top, const QColor& right, const QColor& bottom, const QskGradient& left, const QskGradient& top, const QskGradient& right,
QskStateCombination combination ) const QskGradient& bottom, QskStateCombination combination )
{ {
setColorHint( aspectBorder( aspect ), setColorHint( aspectBorder( aspect ),
QskBoxBorderColors( left, top, right, bottom ), QskBoxBorderColors( left, top, right, bottom ),

View File

@ -227,7 +227,8 @@ class QSK_EXPORT QskSkinHintTableEditor
const QskBoxBorderColors&, QskStateCombination = QskStateCombination() ); const QskBoxBorderColors&, QskStateCombination = QskStateCombination() );
void setBoxBorderColors( QskAspect, void setBoxBorderColors( QskAspect,
const QColor& left, const QColor& top, const QColor& right, const QColor& bottom, const QskGradient& left, const QskGradient& top,
const QskGradient& right, const QskGradient& bottom,
QskStateCombination = QskStateCombination() ); QskStateCombination = QskStateCombination() );
void removeBoxBorderColors( QskAspect, QskStateCombination = QskStateCombination() ); void removeBoxBorderColors( QskAspect, QskStateCombination = QskStateCombination() );

View File

@ -117,7 +117,8 @@ void QskBoxNode::setBoxData( const QRectF& rect,
{ {
if ( isFillMonochrome && isBorderMonochrome ) if ( isFillMonochrome && isBorderMonochrome )
{ {
if ( borderColors.color( Qsk::Left ) == fillGradient.startColor() ) if ( borderColors.gradient( Qsk::Left ).startColor()
== fillGradient.startColor() )
{ {
// we can draw border and background in one // we can draw border and background in one
hasBorder = false; hasBorder = false;
@ -171,7 +172,7 @@ void QskBoxNode::setBoxData( const QRectF& rect,
} }
else else
{ {
flatMaterial->setColor( borderColors.color( Qsk::Left ).rgba() ); flatMaterial->setColor( borderColors.gradient( Qsk::Left ).startColor().rgba() );
renderer.renderBorder( m_rect, shape, borderMetrics, *geometry() ); renderer.renderBorder( m_rect, shape, borderMetrics, *geometry() );
} }
} }

View File

@ -97,6 +97,26 @@ namespace
int m_stepCount; int m_stepCount;
bool m_inverted; bool m_inverted;
}; };
int additionalGradientStops( const QskGradient& gradient )
{
return qMax( 0, gradient.stops().count() - 2 );
}
static inline QRgb qskRgbGradientStart( const QskGradient& gradient )
{
return gradient.startColor().rgba();
}
static inline QRgb qskRgbGradientEnd( const QskGradient& gradient )
{
return gradient.endColor().rgba();
}
static inline QRgb qskRgbBorder( const QskBoxBorderColors& borderColors )
{
return qskRgbGradientStart( borderColors.gradient( Qsk::Left ) );
}
} }
namespace namespace
@ -488,6 +508,7 @@ namespace
{ {
public: public:
static inline constexpr Color colorAt( int ) { return Color(); } static inline constexpr Color colorAt( int ) { return Color(); }
inline QskGradient gradient() const { return QskGradient(); }
}; };
class BorderMapSolid class BorderMapSolid
@ -499,6 +520,7 @@ namespace
} }
inline Color colorAt( int ) const { return m_color; } inline Color colorAt( int ) const { return m_color; }
inline QskGradient gradient() const { return QskGradient(); }
const Color m_color; const Color m_color;
}; };
@ -506,10 +528,11 @@ namespace
class BorderMapGradient class BorderMapGradient
{ {
public: public:
inline BorderMapGradient( int stepCount, QRgb rgb1, QRgb rgb2 ) inline BorderMapGradient( int stepCount, QRgb rgb1, QRgb rgb2, const QskGradient& gradient )
: m_stepCount( stepCount ) : m_stepCount( stepCount )
, m_color1( rgb1 ) , m_color1( rgb1 )
, m_color2( rgb2 ) , m_color2( rgb2 )
, m_gradient( gradient )
{ {
} }
@ -518,9 +541,15 @@ namespace
return m_color1.interpolatedTo( m_color2, step / m_stepCount ); return m_color1.interpolatedTo( m_color2, step / m_stepCount );
} }
inline QskGradient gradient() const
{
return m_gradient;
}
private: private:
const qreal m_stepCount; const qreal m_stepCount;
const Color m_color1, m_color2; const Color m_color1, m_color2;
const QskGradient m_gradient;
}; };
template< class Line, class BorderValues > template< class Line, class BorderValues >
@ -532,6 +561,27 @@ namespace
{ {
} }
void addAdditionalLines( float x11, float y11, float x12, float y12, // start line
float x21,float y21, float x22, float y22, // end line
const QskGradient& gradient, Line* lines )
{
int additionalStopCount = additionalGradientStops( gradient );
auto s = gradient.stops();
for( int i = 1; i <= additionalStopCount; ++i )
{
auto p = ( 1 - s.at( i ).position() );
float xStart = x11 + p * ( x21 - x11 ),
yStart = y11 + p * ( y21 - y11 ),
xEnd = x12 + p * ( x22 - x12 ),
yEnd = y12 + p * ( y22 - y12 );
lines[ additionalStopCount - i + 1 ].setLine( xStart, yStart,
xEnd, yEnd, s.at( i ).color() );
}
}
template< class BorderMap, class FillMap > template< class BorderMap, class FillMap >
inline void createLines( Qt::Orientation orientation, Line* borderLines, inline void createLines( Qt::Orientation orientation, Line* borderLines,
const BorderMap& borderMapTL, const BorderMap& borderMapTR, const BorderMap& borderMapTL, const BorderMap& borderMapTR,
@ -555,9 +605,12 @@ namespace
if ( borderLines ) if ( borderLines )
{ {
linesBR = borderLines; linesBR = borderLines;
linesTR = linesBR + numCornerLines; linesTR = linesBR + numCornerLines
linesTL = linesTR + numCornerLines; + additionalGradientStops( borderMapBR.gradient() );
linesBL = linesTL + numCornerLines; linesTL = linesTR + numCornerLines
+ additionalGradientStops( borderMapTR.gradient() );
linesBL = linesTL + numCornerLines
+ additionalGradientStops( borderMapTL.gradient() );
} }
if ( fillLines ) if ( fillLines )
@ -571,9 +624,12 @@ namespace
if ( borderLines ) if ( borderLines )
{ {
linesTR = borderLines + 1; linesTR = borderLines + 1;
linesTL = linesTR + numCornerLines; linesTL = linesTR + numCornerLines
linesBL = linesTL + numCornerLines; + additionalGradientStops( borderMapTR.gradient() );
linesBR = linesBL + numCornerLines; linesBL = linesTL + numCornerLines
+ additionalGradientStops( borderMapTL.gradient() );
linesBR = linesBL + numCornerLines
+ additionalGradientStops( borderMapBL.gradient() );
} }
if ( fillLines ) if ( fillLines )
@ -641,6 +697,83 @@ namespace
c[ corner ].centerY + v.dy2( corner ), c[ corner ].centerY + v.dy2( corner ),
borderMapBR.colorAt( j ) ); borderMapBR.colorAt( j ) );
} }
// at the beginning and end of the loop we can add
// additional lines for border gradients:
if( j == 0 )
{
if( additionalGradientStops( borderMapTR.gradient() ) > 0 )
{
float x1TR = c[ TopRight ].centerX + v.dx1( TopRight ),
y1TR = c[ TopRight ].centerY - v.dy1( TopRight ),
x2TR = c[ TopRight ].centerX + v.dx2( TopRight ),
y2TR = c[ TopRight ].centerY - v.dy2( TopRight ),
x1TL = c[ TopLeft ].centerX - v.dx1( TopLeft ),
y1TL = c[ TopLeft ].centerY - v.dy1( TopLeft ),
x2TL = c[ TopLeft ].centerX - v.dx2( TopLeft ),
y2TL = c[ TopLeft ].centerY - v.dy2( TopLeft );
addAdditionalLines( x1TR, y1TR, x2TR, y2TR,
x1TL, y1TL, x2TL, y2TL,
borderMapTR.gradient(), linesTR + k );
}
if( additionalGradientStops( borderMapBL.gradient() ) > 0 )
{
float x1BL = c[ BottomLeft ].centerX - v.dx1( BottomLeft ),
y1BL = c[ BottomLeft ].centerY + v.dy1( BottomLeft ),
x2BL = c[ BottomLeft ].centerX - v.dx2( BottomLeft ),
y2BL = c[ BottomLeft ].centerY + v.dy2( BottomLeft ),
x1BR = c[ BottomRight ].centerX + v.dx1( BottomRight ),
y1BR = c[ BottomRight ].centerY + v.dy1( BottomRight ),
x2BR = c[ BottomRight ].centerX + v.dx2( BottomRight ),
y2BR = c[ BottomRight ].centerY + v.dy2( BottomRight );
addAdditionalLines( x1BL, y1BL, x2BL, y2BL,
x1BR, y1BR, x2BR, y2BR,
borderMapBL.gradient(), linesBL + k );
}
}
if( j == numCornerLines - 1 )
{
if( additionalGradientStops( borderMapTL.gradient() ) > 0 )
{
float x1TL = c[ TopLeft ].centerX - v.dx1( TopLeft ),
y1TL = c[ TopLeft ].centerY - v.dy1( TopLeft ),
x2TL = c[ TopLeft ].centerX - v.dx2( TopLeft ),
y2TL = c[ TopLeft ].centerY - v.dy2( TopLeft ),
x1BL = c[ BottomLeft ].centerX - v.dx1( BottomLeft ),
y1BL = c[ BottomLeft ].centerY + v.dy1( BottomLeft ),
x2BL = c[ BottomLeft ].centerX - v.dx2( BottomLeft ),
y2BL = c[ BottomLeft ].centerY + v.dy2( BottomLeft );
addAdditionalLines( x1TL, y1TL, x2TL, y2TL,
x1BL, y1BL, x2BL, y2BL,
borderMapTL.gradient(), linesTL + j );
}
if( additionalGradientStops( borderMapBR.gradient() ) > 0 )
{
float x1BR = c[ BottomRight ].centerX + v.dx1( BottomRight ),
y1BR = c[ BottomRight ].centerY + v.dy1( BottomRight ),
x2BR = c[ BottomRight ].centerX + v.dx2( BottomRight ),
y2BR = c[ BottomRight ].centerY + v.dy2( BottomRight ),
x1TR = c[ TopRight ].centerX + v.dx1( TopRight ),
y1TR = c[ TopRight ].centerY - v.dy1( TopRight ),
x2TR = c[ TopRight ].centerX + v.dx2( TopRight ),
y2TR = c[ TopRight ].centerY - v.dy2( TopRight );
addAdditionalLines( x1BR, y1BR, x2BR, y2BR,
x1TR, y1TR, x2TR, y2TR,
borderMapBR.gradient(), linesBR + j );
}
}
} }
if ( fillLines ) if ( fillLines )
@ -689,7 +822,12 @@ namespace
#if 1 #if 1
if ( borderLines ) if ( borderLines )
{ {
const int k = 4 * numCornerLines; const int additionalStops =
additionalGradientStops( borderMapBR.gradient() )
+ additionalGradientStops( borderMapTR.gradient() )
+ additionalGradientStops( borderMapTL.gradient() )
+ additionalGradientStops( borderMapBL.gradient() );
const int k = 4 * numCornerLines + additionalStops;
if ( orientation == Qt::Vertical ) if ( orientation == Qt::Vertical )
borderLines[ k ] = borderLines[ 0 ]; borderLines[ k ] = borderLines[ 0 ];
@ -859,17 +997,24 @@ static inline void qskRenderBorder( const QskBoxRenderer::Metrics& metrics,
if ( colors.isMonochrome() ) if ( colors.isMonochrome() )
{ {
qskRenderBorderLines( metrics, orientation, line, BorderMapSolid( c.rgb( Qsk::Left ) ) ); qskRenderBorderLines( metrics, orientation, line, BorderMapSolid( qskRgbBorder( c ) ) );
} }
else else
{ {
const int stepCount = metrics.corner[ 0 ].stepCount; const int stepCount = metrics.corner[ 0 ].stepCount;
auto left = c.gradient( Qsk::Left ), top = c.gradient( Qsk::Top ),
right = c.gradient( Qsk::Right ), bottom = c.gradient( Qsk::Bottom );
qskRenderBorderLines( metrics, orientation, line, qskRenderBorderLines( metrics, orientation, line,
BorderMapGradient( stepCount, c.rgb( Qsk::Top ), c.rgb( Qsk::Left ) ), BorderMapGradient( stepCount, qskRgbGradientStart( top ),
BorderMapGradient( stepCount, c.rgb( Qsk::Right ), c.rgb( Qsk::Top ) ), qskRgbGradientEnd( left ), left ),
BorderMapGradient( stepCount, c.rgb( Qsk::Left ), c.rgb( Qsk::Bottom ) ), BorderMapGradient( stepCount, qskRgbGradientStart( right ),
BorderMapGradient( stepCount, c.rgb( Qsk::Bottom ), c.rgb( Qsk::Right ) ) ); qskRgbGradientEnd( top ), top ),
BorderMapGradient( stepCount, qskRgbGradientStart( left ),
qskRgbGradientEnd( bottom ), bottom ),
BorderMapGradient( stepCount, qskRgbGradientStart( bottom ),
qskRgbGradientEnd( right ), right ) );
} }
} }
@ -899,7 +1044,7 @@ static inline void qskRenderBoxRandom(
if ( bc.isMonochrome() ) if ( bc.isMonochrome() )
{ {
const BorderMapSolid borderMap( bc.rgb( Qsk::Left ) ); const BorderMapSolid borderMap( qskRgbBorder( bc.gradient( Qsk::Left ) ) );
if ( gradient.isMonochrome() ) if ( gradient.isMonochrome() )
{ {
@ -918,10 +1063,17 @@ static inline void qskRenderBoxRandom(
{ {
const int n = metrics.corner[ 0 ].stepCount; const int n = metrics.corner[ 0 ].stepCount;
const BorderMapGradient tl( n, bc.rgb( Qsk::Top ), bc.rgb( Qsk::Left ) ); auto left = bc.gradient( Qsk::Left ), top = bc.gradient( Qsk::Top ),
const BorderMapGradient tr( n, bc.rgb( Qsk::Right ), bc.rgb( Qsk::Top ) ); right = bc.gradient( Qsk::Right ), bottom = bc.gradient( Qsk::Bottom );
const BorderMapGradient bl( n, bc.rgb( Qsk::Left ), bc.rgb( Qsk::Bottom ) );
const BorderMapGradient br( n, bc.rgb( Qsk::Bottom ), bc.rgb( Qsk::Right ) ); const BorderMapGradient tl( n, qskRgbGradientStart( top.startColor() ),
qskRgbGradientEnd( left.endColor() ), left );
const BorderMapGradient tr( n, qskRgbGradientStart( right ),
qskRgbGradientEnd( top ), top );
const BorderMapGradient bl( n, qskRgbGradientStart( left ),
qskRgbGradientEnd( bottom ), bottom );
const BorderMapGradient br( n, qskRgbGradientStart( bottom ),
qskRgbGradientEnd( right ), right );
if ( gradient.isMonochrome() ) if ( gradient.isMonochrome() )
{ {
@ -1207,9 +1359,20 @@ void QskBoxRenderer::renderRectellipse( const QRectF& rect,
const int stepCount = metrics.corner[ 0 ].stepCount; const int stepCount = metrics.corner[ 0 ].stepCount;
int borderLineCount = 0; int borderLineCount = 0;
if ( borderColors.isVisible() && metrics.innerQuad != metrics.outerQuad ) if ( borderColors.isVisible() && metrics.innerQuad != metrics.outerQuad )
{
borderLineCount = 4 * ( stepCount + 1 ) + 1; borderLineCount = 4 * ( stepCount + 1 ) + 1;
const int additionalLines =
additionalGradientStops( borderColors.gradient( Qsk::Left ) )
+ additionalGradientStops( borderColors.gradient( Qsk::Top ) )
+ additionalGradientStops( borderColors.gradient( Qsk::Right ) )
+ additionalGradientStops( borderColors.gradient( Qsk::Bottom ) );
borderLineCount += additionalLines;
}
int lineCount = borderLineCount + fillLineCount; int lineCount = borderLineCount + fillLineCount;
bool extraLine = false; bool extraLine = false;

View File

@ -422,28 +422,63 @@ static inline void qskCreateBorder(
const QskBoxRenderer::Quad& out, const QskBoxRenderer::Quad& in, const QskBoxRenderer::Quad& out, const QskBoxRenderer::Quad& in,
const QskBoxBorderColors& colors, Line* line ) const QskBoxBorderColors& colors, Line* line )
{ {
const Color colorLeft = colors.rgb( Qsk::Left ); const QskGradient gradientLeft = colors.gradient( Qsk::Left );
const Color colorRight = colors.rgb( Qsk::Right ); const QskGradient gradientRight = colors.gradient( Qsk::Right );
const Color colorTop = colors.rgb( Qsk::Top ); const QskGradient gradientTop = colors.gradient( Qsk::Top );
const Color colorBottom = colors.rgb( Qsk::Bottom ); const QskGradient gradientBottom = colors.gradient( Qsk::Bottom );
( line++ )->setLine( in.right, in.bottom, out.right, out.bottom, colorBottom ); // qdebug
( line++ )->setLine( in.left, in.bottom, out.left, out.bottom, colorBottom );
if ( colorLeft != colorBottom ) const qreal dx1 = in.right - in.left;
( line++ )->setLine( in.left, in.bottom, out.left, out.bottom, colorLeft ); const qreal dx2 = out.right - out.left;
const qreal dy1 = in.top - in.bottom;
const qreal dy2 = out.top - out.bottom;
( line++ )->setLine( in.left, in.top, out.left, out.top, colorLeft ); for( const auto& stop : gradientBottom.stops() )
{
const Color c( stop.color() );
const qreal x1 = in.right - stop.position() * dx1;
const qreal x2 = out.right - stop.position() * dx2;
const qreal y1 = in.bottom;
const qreal y2 = out.bottom;
if ( colorTop != colorLeft ) ( line++ )->setLine( x1, y1, x2, y2, c );
( line++ )->setLine( in.left, in.top, out.left, out.top, colorTop ); }
( line++ )->setLine( in.right, in.top, out.right, out.top, colorTop ); for( const auto& stop : gradientLeft.stops() )
{
const Color c( stop.color() );
const qreal x1 = in.left;
const qreal x2 = out.left;
const qreal y1 = in.bottom + stop.position() * dy1;
const qreal y2 = out.bottom + stop.position() * dy2;
if ( colorRight != colorTop ) ( line++ )->setLine( x1, y1, x2, y2, c );
( line++ )->setLine( in.right, in.top, out.right, out.top, colorRight ); }
( line++ )->setLine( in.right, in.bottom, out.right, out.bottom, colorRight ); for( const auto& stop : gradientTop.stops() )
{
const Color c( stop.color() );
const qreal x1 = in.left + stop.position() * dx1;
const qreal x2 = out.left + stop.position() * dx2;
const qreal y1 = in.top;
const qreal y2 = out.top;
( line++ )->setLine( x1, y1, x2, y2, c );
}
for( const auto& stop : gradientRight.stops() )
{
const Color c( stop.color() );
const qreal x1 = in.right;
const qreal x2 = out.right;
// ( 1 - stop.position() ) because we want to make the gradients go
// around the border clock-wise:
const qreal y1 = in.bottom + ( 1 - stop.position() ) * dy1;
const qreal y2 = out.bottom + ( 1 - stop.position() ) * dy2;
( line++ )->setLine( x1, y1, x2, y2, c );
}
} }
void QskBoxRenderer::renderRectBorder( void QskBoxRenderer::renderRectBorder(
@ -533,14 +568,15 @@ void QskBoxRenderer::renderRect(
// we might need extra lines to separate colors // we might need extra lines to separate colors
// at the non closing corners // at the non closing corners
if ( bc.color( Qsk::Left ) != bc.color( Qsk::Bottom ) ) // ### As an optimization we could check orientation and colors
borderLineCount++; // to test whether colors are the same
const int additionalLines = -1
+ bc.gradient( Qsk::Left ).stops().count() - 1
+ bc.gradient( Qsk::Top ).stops().count() - 1
+ bc.gradient( Qsk::Right ).stops().count() - 1
+ bc.gradient( Qsk::Bottom ).stops().count() - 1;
if ( bc.color( Qsk::Top ) != bc.color( Qsk::Left ) ) borderLineCount += qMax( additionalLines, 0 );
borderLineCount++;
if ( bc.color( Qsk::Right ) != bc.color( Qsk::Top ) )
borderLineCount++;
} }
} }
} }
@ -587,7 +623,7 @@ void QskBoxRenderer::renderRect(
auto fillLines = line + fillLineCount; auto fillLines = line + fillLineCount;
if ( bc.isMonochrome() ) if ( bc.isMonochrome() )
qskCreateBorderMonochrome( rect, in, bc.rgb( Qsk::Left ), fillLines ); qskCreateBorderMonochrome( rect, in, bc.gradient( Qsk::Left ).startColor().rgba(), fillLines );
else else
qskCreateBorder( rect, in, bc, fillLines ); qskCreateBorder( rect, in, bc, fillLines );
} }