Commit 4a78561a authored by Noah Davis's avatar Noah Davis 🌵
Browse files

Add shadow rendering helper functions

Summary:
This patch makes other helper functions reuse more code by calling these shadow rendering functions instead of defining their own shadows.

The shadows are perfectly shaped, tested up to 8x scaling.
Without this patch, the radius of the shadows for checkboxes is slighly too wide and there is a gap between the inside edge of the radio button shadow and the outside edge of the radio button.
Shadow rendering performance has also been improved a bit.

Test Plan:
run `QT_SCALE_FACTOR=8 oxygen-demo5` and examine the shadows. You can try higher scaling levels, but that's overkill.

8x scaling

before: {F7824689, size=full} {F7824691, size=full}

after: {F7824692, size=full} {F7824693, size=full}

Reviewers: #breeze, hpereiradacosta, #plasma

Reviewed By: hpereiradacosta

Subscribers: ngraham, plasma-devel

Tags: #plasma

Differential Revision: https://phabricator.kde.org/D26094
parent 2c8e7782
......@@ -641,12 +641,9 @@ namespace Breeze
frameRect.translate( 1, 1 );
} else if( shadow.isValid() ) {
} else {
const qreal shadowRadius = qMax( radius - 1, qreal( 0.0 ) );
painter->setPen( QPen( shadow, 2 ) );
painter->setBrush( Qt::NoBrush );
painter->drawRoundedRect( shadowRect( frameRect ), shadowRadius, shadowRadius );
renderRoundedRectShadow( painter, frameRect, shadow, radius );
}
......@@ -875,11 +872,7 @@ namespace Breeze
} else {
painter->setPen( QPen( shadow, 1 ) );
painter->setBrush( Qt::NoBrush );
const qreal shadowRadius( radius + 0.5 );
painter->drawRoundedRect( shadowRect( frameRect ).adjusted( -0.5, -0.5, 0.5, 0.5 ), shadowRadius, shadowRadius );
renderRoundedRectShadow( painter, frameRect, shadow, radius );
}
......@@ -982,9 +975,7 @@ namespace Breeze
} else {
painter->setPen( QPen( shadow, 1 ) );
painter->setBrush( Qt::NoBrush );
painter->drawEllipse( shadowRect( frameRect ).adjusted( -0.5, -0.5, 0.5, 0.5 ) );
renderEllipseShadow( painter, frameRect, shadow );
}
......@@ -1141,12 +1132,10 @@ namespace Breeze
frameRect.adjust( 1, 1, -1, -1 );
// shadow
if( shadow.isValid() && !sunken )
if( !sunken )
{
painter->setPen( QPen( shadow, 2 ) );
painter->setBrush( Qt::NoBrush );
painter->drawEllipse( shadowRect( frameRect ) );
renderEllipseShadow( painter, frameRect, shadow );
}
......@@ -1408,7 +1397,61 @@ namespace Breeze
painter->restore();
}
//______________________________________________________________________________
void Helper::renderRoundedRectShadow( QPainter* painter, const QRectF& rect, const QColor& color, qreal radius ) const
{
if( !color.isValid() ) return;
painter->save();
/* Clipping prevents shadows from being visible inside checkboxes.
* Clipping away unneeded parts here also improves performance by 40-60%
* versus using just an outline of a rectangle.
* Tested by looking at the paint analyser in GammaRay.
*/
// Right side
QRegion clip( rect.right() - std::ceil( radius ), rect.top(),
std::ceil( radius ) + 1, rect.height() );
// Bottom side
clip = clip.united( QRegion( rect.left(), rect.bottom() - std::ceil( radius ),
rect.width(), std::ceil( radius ) + 1 ) );
painter->setClipRegion( clip );
painter->setPen( color );
painter->setBrush( Qt::NoBrush );
painter->drawRoundedRect( rect.translated( 0.5, 0.5 ), radius, radius );
painter->restore();
}
//______________________________________________________________________________
void Helper::renderEllipseShadow( QPainter* painter, const QRectF& rect, const QColor& color ) const
{
if( !color.isValid() ) return;
painter->save();
// Clipping does not improve performance here
// 0.5 is subtracted because of the pen
qreal radius = rect.width() / 2 - 0.5;
/* The right side is offset by +0.5 for the visible part of the shadow.
* The other sides are offset by +0.5 or -0.5 because of the pen.
*/
QRectF shadowRect = rect.adjusted( 0.5, 0.5, 0.5, -0.5 );
painter->translate( rect.center() );
painter->rotate( 45 );
painter->translate( -rect.center() );
painter->setPen( color );
painter->setBrush( Qt::NoBrush );
painter->drawRoundedRect( shadowRect, radius, radius );
painter->restore();
}
//______________________________________________________________________________
bool Helper::isX11()
{
......@@ -1454,11 +1497,7 @@ namespace Breeze
qreal adjustment = 0.5 * penWidth;
return rect.adjusted( adjustment, adjustment, -adjustment, -adjustment );
}
//______________________________________________________________________________
QRectF Helper::shadowRect( const QRectF& rect ) const
{ return rect.adjusted( 0.5, 0.5, -0.5, -0.5 ).translated( 0.5, 0.5 ); }
//______________________________________________________________________________
QPainterPath Helper::roundedPath( const QRectF& rect, Corners corners, qreal radius ) const
{
......
......@@ -251,6 +251,12 @@ namespace Breeze
//* generic button (for mdi decorations, tabs and dock widgets)
void renderDecorationButton( QPainter*, const QRect&, const QColor&, ButtonType, bool inverted ) const;
//* generic shadow for rounded rectangles
void renderRoundedRectShadow ( QPainter*, const QRectF&, const QColor&, qreal radius = Metrics::Frame_FrameRadius - 0.5 ) const;
//* generic shadow for ellipses
void renderEllipseShadow( QPainter*, const QRectF&, const QColor& ) const;
//@}
//*@name compositing utilities
......@@ -319,9 +325,6 @@ namespace Breeze
//* initialize
void init();
//* return rectangle for widgets shadow, offset depending on light source
QRectF shadowRect( const QRectF& ) const;
//* return rounded path in a given rect, with only selected corners rounded, and for a given radius
QPainterPath roundedPath( const QRectF&, Corners, qreal ) const;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment