File indexing completed on 2024-04-28 05:32:22

0001 #ifndef oxygenshadow_h
0002 #define oxygenshadow_h
0003 /*
0004 * this file is part of the oxygen gtk engine
0005 * SPDX-FileCopyrightText: 2010 Hugo Pereira Da Costa <hugo.pereira@free.fr>
0006 * SPDX-FileCopyrightText: 2010 Ruslan Kabatsayev <b7.10110111@gmail.com>
0007 *
0008 * SPDX-License-Identifier: LGPL-2.0-or-later
0009 */
0010 
0011 #include "oxygencairocontext.h"
0012 #include "oxygenqtsettings.h"
0013 #include "oxygenstylehelper.h"
0014 #include "oxygenwindecooptions.h"
0015 #include "oxygenshadowconfiguration.h"
0016 #include <cmath>
0017 
0018 namespace Oxygen
0019 {
0020     class WindowShadow
0021     {
0022 
0023         // TODO: implement opacity
0024         public:
0025 
0026         //! constructor
0027         WindowShadow( const QtSettings& settings, StyleHelper& helper ):
0028             _settings( settings ),
0029             _helper(helper),
0030             inactiveShadowConfiguration_(settings.shadowConfiguration(Palette::Inactive)),
0031             activeShadowConfiguration_(settings.shadowConfiguration(Palette::Active))
0032         {}
0033 
0034         //! destructor
0035         virtual ~WindowShadow()
0036         {}
0037 
0038         void render(cairo_t*, gint x, gint y, gint w, gint h);
0039 
0040         // shadow tiles
0041         const TileSet& tileSet(const ColorUtils::Rgba& color, WindowShadowKey) const;
0042 
0043         void setWindowState(WinDeco::Options wopt)
0044         { _wopt=wopt; }
0045 
0046         //! shadow size
0047         double shadowSize() const
0048         {
0049             double activeSize( activeShadowConfiguration_.isEnabled() ? activeShadowConfiguration_.shadowSize() : 0 );
0050             double inactiveSize( inactiveShadowConfiguration_.isEnabled() ? inactiveShadowConfiguration_.shadowSize() : 0 );
0051             double size( std::max( activeSize, inactiveSize ) );
0052 
0053             // even if shadows are disabled,
0054             // you need a minimum size to allow corner rendering
0055             return std::max(size,5.0);
0056         }
0057 
0058         //! overlap between shadow pixmap and contents body
0059         enum { Overlap = 4 };
0060 
0061         protected:
0062 
0063         //! simple pixmap
0064         Cairo::Surface shadowPixmap(const ColorUtils::Rgba& color, const WindowShadowKey& ) const;
0065 
0066         //! settings
0067         const QtSettings& settings( void ) const
0068         { return _settings; }
0069 
0070         //! helper
0071         StyleHelper& helper( void ) const
0072         { return _helper; }
0073 
0074         //! square utility function
0075         static double square(double x)
0076         { return x*x; }
0077 
0078         //! functions used to draw shadows
0079         class Parabolic
0080         {
0081             public:
0082 
0083             //! constructor
0084             Parabolic( double amplitude, double width ):
0085                 amplitude_( amplitude ),
0086                 width_( width )
0087             {}
0088 
0089             //! destructor
0090             virtual ~Parabolic( void )
0091             {}
0092 
0093             //! value
0094             virtual double operator() ( double x ) const
0095             { return std::max( 0.0, amplitude_*(1.0 - square(x/width_) ) ); }
0096 
0097             private:
0098 
0099             double amplitude_;
0100             double width_;
0101 
0102         };
0103 
0104         //! functions used to draw shadows
0105         class Gaussian
0106         {
0107             public:
0108 
0109             //! constructor
0110             Gaussian( double amplitude, double width ):
0111                 amplitude_( amplitude ),
0112                 width_( width )
0113             {}
0114 
0115             //! destructor
0116             virtual ~Gaussian( void )
0117             {}
0118 
0119             //! value
0120             virtual double operator() ( double x ) const
0121             { return std::max( 0.0, amplitude_*(std::exp( -square(x/width_) -0.05 ) ) ); }
0122 
0123             private:
0124 
0125             double amplitude_;
0126             double width_;
0127 
0128         };
0129 
0130         private:
0131 
0132         //! draw gradient into rect
0133         /*! a separate method is used in order to properly account for corners */
0134         void renderGradient(cairo_t*,const GdkRectangle&,cairo_pattern_t*, bool hasTopBorder=true, bool hasBottomBorder = true ) const;
0135 
0136         //! settings
0137         const QtSettings& _settings;
0138 
0139         //! helper
0140         StyleHelper& _helper;
0141 
0142         //! window state
0143         WinDeco::Options _wopt;
0144 
0145         //! inactive shadow configuration
0146         ShadowConfiguration inactiveShadowConfiguration_;
0147 
0148         //! active shadow configuration
0149         ShadowConfiguration activeShadowConfiguration_;
0150 
0151     };
0152 
0153 }
0154 
0155 #endif