diff --git a/kstyle/breezehelper.h b/kstyle/breezehelper.h --- a/kstyle/breezehelper.h +++ b/kstyle/breezehelper.h @@ -251,6 +251,12 @@ //* 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 controlRadius = 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 @@ //* 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; diff --git a/kstyle/breezehelper.cpp b/kstyle/breezehelper.cpp --- a/kstyle/breezehelper.cpp +++ b/kstyle/breezehelper.cpp @@ -641,12 +641,9 @@ 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 @@ } 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 @@ } 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 @@ 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,60 @@ 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; + + // right side is offset by +1 for the visible part of the shadow + // 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 +1496,7 @@ 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 {