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

0001 #ifndef oxygenrgba_h
0002 #define oxygenrgba_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 *
0007 * inspired notably from kdelibs/kdeui/color/kcolorutils.h
0008 * SPDX-FileCopyrightText: 2007 Matthew Woehlke <mw_triad@users.sourceforge.net>
0009 * SPDX-FileCopyrightText: 2007 Thomas Zander <zander@kde.org>
0010 * SPDX-FileCopyrightText: 2007 Zack Rusin <zack@kde.org>
0011 *
0012 * SPDX-License-Identifier: LGPL-2.0-or-later
0013 */
0014 
0015 #include <climits>
0016 #include <iostream>
0017 #include <iomanip>
0018 #include <sstream>
0019 #include <string>
0020 #include <vector>
0021 #include <gdk/gdk.h>
0022 
0023 namespace Oxygen
0024 {
0025 
0026     namespace ColorUtils
0027     {
0028 
0029         //! stores rgba representation of a color
0030         /*! all values must be between 0 and 1 */
0031         class Rgba
0032         {
0033 
0034             private:
0035             typedef unsigned short color_t;
0036 
0037             public:
0038 
0039             //! constructor
0040             Rgba( void ):
0041                 _red(0),
0042                 _green(0),
0043                 _blue(0),
0044                 _alpha(USHRT_MAX),
0045                 _mask(0)
0046             {}
0047 
0048             //! constructor
0049             Rgba( double r, double g, double b, double a = 1 ):
0050                 _red( (color_t) (r*USHRT_MAX) ),
0051                 _green( (color_t) (g*USHRT_MAX) ),
0052                 _blue( (color_t) (b*USHRT_MAX) ),
0053                 _alpha( (color_t) (a*USHRT_MAX) ),
0054                 _mask( RGBA )
0055             {}
0056 
0057             //! equal to operator
0058             /*! TODO: check why alpha channel is not used in the comparison */
0059             bool operator == (const Rgba& other ) const
0060             {
0061                 return
0062                     _mask == other._mask &&
0063                     _red == other._red &&
0064                     _green == other._green &&
0065                     _blue == other._blue;
0066             }
0067 
0068             // convert to integer
0069             guint32 toInt( void ) const
0070             {
0071                 return
0072                     (guint32( _red >> 8 ) << 24) |
0073                     (guint32( _green >> 8 ) << 16) |
0074                     (guint32( _green >> 8 ) << 8) |
0075                     guint32( _alpha >> 8 );
0076             }
0077 
0078             // convert to string
0079             operator std::string ( void ) const
0080             {
0081                 std::ostringstream out;
0082                 out
0083                     << "\"#"
0084                     << std::hex
0085                     << std::setw( 2 ) << std::setfill( '0' ) << guint32( _red >> 8 )
0086                     << std::setw( 2 ) << std::setfill( '0' ) << guint32( _green >> 8 )
0087                     << std::setw( 2 ) << std::setfill( '0' ) << guint32( _blue >> 8 )
0088                     << "\"";
0089                 return out.str();
0090             }
0091 
0092             //! make color lighter
0093             /*! Copied from QColor. Amount must be > 100. */
0094             Rgba light( int amount ) const;
0095 
0096             //! make color darker
0097             /*! Copied from QColor. Amount must be > 100. */
0098             Rgba dark( int amount ) const;
0099 
0100             //!@name access colors
0101             //@{
0102 
0103             double red( void ) const
0104             { return double(_red)/USHRT_MAX; }
0105 
0106             double green( void ) const
0107             { return double(_green)/USHRT_MAX; }
0108 
0109             double blue( void ) const
0110             { return double(_blue)/USHRT_MAX; }
0111 
0112             double alpha( void ) const
0113             { return double(_alpha)/USHRT_MAX; }
0114 
0115             //! value (in HSV colorspace)
0116             double value( void ) const
0117             { return std::max( red(), std::max( green(), blue() ) ); }
0118 
0119             //@}
0120 
0121             //!@name set colors
0122             //@{
0123 
0124             Rgba& setRed( double value )
0125             {
0126                 _red = (color_t)(value*USHRT_MAX);
0127                 _mask |= R;
0128                 return *this;
0129             }
0130 
0131             Rgba& setGreen( double value )
0132             {
0133                 _green = (color_t)(value*USHRT_MAX);
0134                 _mask |= G;
0135                 return *this;
0136             }
0137 
0138             Rgba& setBlue( double value )
0139             {
0140                 _blue = (color_t)(value*USHRT_MAX);
0141                 _mask |= B;
0142                 return *this;
0143             }
0144 
0145             Rgba& setAlpha( double value )
0146             {
0147                 _alpha = (color_t)(value*USHRT_MAX);
0148                 _mask |= A;
0149                 return *this;
0150             }
0151 
0152             //@}
0153 
0154             //! convert to hsv
0155             void toHsv( double&, double&, double& ) const;
0156 
0157             //! convert from hsv
0158             Rgba& fromHsv( double, double, double );
0159 
0160             //! validity
0161             bool isValid( void ) const
0162             { return (_mask & RGB ) == RGB; }
0163 
0164             //! utilities
0165             static Rgba fromKdeOption( std::string );
0166 
0167             //!@name predefined colors
0168             //@{
0169             static Rgba black( void ) { return Rgba( 0, 0, 0, 1 ); }
0170             static Rgba white( void ) { return Rgba( 1, 1, 1, 1 ); }
0171             static Rgba transparent( const ColorUtils::Rgba& base = black()  )
0172             { return Rgba( base ).setAlpha(0); }
0173 
0174             //@}
0175 
0176             private:
0177 
0178             enum ColorBit
0179             {
0180                 R = 1<<0,
0181                 G = 1<<1,
0182                 B = 1<<2,
0183                 A = 1<<3,
0184                 RGB = R|G|B,
0185                 RGBA = RGB|A
0186             };
0187 
0188             color_t _red;
0189             color_t _green;
0190             color_t _blue;
0191             color_t _alpha;
0192 
0193             unsigned int _mask;
0194 
0195             friend std::ostream& operator << ( std::ostream& out, const Rgba& rgba )
0196             { return out << ( rgba._red >> 8 ) << "," << ( rgba._green >> 8 ) << "," << ( rgba._blue >> 8 ) << "," << (rgba._alpha >> 8); }
0197 
0198         };
0199 
0200     }
0201 }
0202 
0203 #endif