//------------------------------------------------------------------------------
// emColor.h
//
// Copyright (C) 2001,2003-2008,2010,2014,2018,2022 Oliver Hamann.
//
// Homepage: http://eaglemode.sourceforge.net/
//
// This program is free software: you can redistribute it and/or modify it under
// the terms of the GNU General Public License version 3 as published by the
// Free Software Foundation.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU General Public License version 3 for
// more details.
//
// You should have received a copy of the GNU General Public License version 3
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//------------------------------------------------------------------------------
#ifndef emColor_h
#define emColor_h
#ifndef emStd2_h
#include <emCore/emStd2.h>
#endif
//==============================================================================
//================================== emColor ===================================
//==============================================================================
class emColor {
public:
// Class for a 32-bit color value. A color has four components, each of
// eight bits: red, green, blue and alpha. An alpha value of 255 means
// opaque, 0 means totally transparent. A here so called "packed color"
// is a 32-bit unsigned integer with:
// Bits 0-7 : Alpha component
// Bits 8-15 : Blue component
// Bits 16-23: Green component
// Bits 24-31: Red component
enum {
// Some predefined packed colors.
BLACK =0x000000ff,
WHITE =0xffffffff,
GRAY =0x808080ff,
RED =0xff0000ff,
GREEN =0x00ff00ff,
BLUE =0x0000ffff,
YELLOW =0xffff00ff,
CYAN =0x00ffffff,
MAGENTA=0xff00ffff
};
emColor();
// Performs no initialization! (emColor is a primitive type)
emColor(emUInt32 packed);
// Construct from a packed color.
emColor(emByte red, emByte green, emByte blue, emByte alpha=255);
// Construct from color components.
emColor(const emColor & color);
// Construct by copying a color.
emColor(const emColor & rgb, emByte alpha);
// Construct by copying a color, but override the alpha
// component.
void TryParse(const char * str);
// Try to set this color by interpreting the given string as a
// color. Throw an error message on failure. Currently, this
// tries to interpret only X11 color strings like "#f8a91c" or
// "Powder Blue". Future extension may even accept additional
// formats.
emColor & operator = (const emColor & color);
emColor & operator = (emUInt32 packed);
// Copy a color or a packed color.
operator emUInt32 () const;
emUInt32 Get() const;
// Convert this color to a packed color.
void Set(emUInt32 packed);
void Set(emByte red, emByte green, emByte blue, emByte alpha=255);
void Set(const emColor & color);
void Set(const emColor & rgb, emByte alpha);
// Like the constructors.
emByte GetRed() const;
emByte GetGreen() const;
emByte GetBlue() const;
emByte GetAlpha() const;
void SetRed(emByte red);
void SetGreen(emByte green);
void SetBlue(emByte blue);
void SetAlpha(emByte alpha);
// Get or set individual components.
bool IsTotallyTransparent() const;
// Ask whether the alpha component is 0.
bool IsOpaque() const;
// Ask whether the alpha component is 255.
bool IsGrey() const;
// Ask whether the red, green and blue components are equal.
emByte GetGrey() const;
void SetGrey(emByte grey, emByte alpha=255);
// Get or set in grey format.
float GetHue() const;
float GetSat() const;
float GetVal() const;
void SetHue(float hue);
void SetSat(float sat);
void SetVal(float val);
void SetHSVA(float hue, float sat, float val, emByte alpha=255);
// Get or set in Hue-Saturation-Value format. Hue is in degrees
// (0.0-360.0). Sat and val are in percent (0.0-100.0).
emColor GetBlended(const emColor & color, float weight) const;
// Return a blending of this color and a given color. The given
// weight of the given color is in percent.
emColor GetLighted(float light) const;
// Get a shaded or lighted version of this color. The light
// parameter ranges from -100.0 to 100.0. -100.0 means black
// (fully shaded), 0.0 means no change, 100.0 means white (fully
// highlighted).
emColor GetTransparented(float tp) const;
// Get a more opaque or transparent version of this color. The
// argument tp ranges from -100.0 to 100.0. -100.0 means fully
// opaque, 0.0 means no change, 100.0 means fully transparent.
bool operator == (const emColor & color) const;
bool operator != (const emColor & color) const;
bool operator == (emUInt32 packed) const;
bool operator != (emUInt32 packed) const;
friend bool operator == (emUInt32 packed, const emColor & color);
friend bool operator != (emUInt32 packed, const emColor & color);
// Compare colors.
private:
union {
emUInt32 Packed;
struct {
# if EM_BYTE_ORDER==4321
emByte Red, Green, Blue, Alpha;
# elif EM_BYTE_ORDER==1234
emByte Alpha, Blue, Green, Red;
# elif EM_BYTE_ORDER==3412
emByte Green, Red, Alpha, Blue;
# else
# error unexpected value for EM_BYTE_ORDER
# endif
} Components;
};
};
inline emColor::emColor()
{
}
inline emColor::emColor(emUInt32 packed)
{
Packed=packed;
}
inline emColor::emColor(emByte red, emByte green, emByte blue, emByte alpha)
{
Components.Red=red;
Components.Green=green;
Components.Blue=blue;
Components.Alpha=alpha;
}
inline emColor::emColor(const emColor & color)
{
Packed=color.Packed;
}
inline emColor::emColor(const emColor & rgb, emByte alpha)
{
// Did not work error-free with every compiler:
// Packed=rgb.Packed;
// Components.Alpha=alpha;
// Therefore:
Components.Red=rgb.Components.Red;
Components.Green=rgb.Components.Green;
Components.Blue=rgb.Components.Blue;
Components.Alpha=alpha;
}
inline emColor & emColor::operator = (const emColor & color)
{
Packed=color.Packed;
return *this;
}
inline emColor & emColor::operator = (emUInt32 packed)
{
Packed=packed;
return *this;
}
inline emColor::operator emUInt32 () const
{
return Packed;
}
inline emUInt32 emColor::Get() const
{
return Packed;
}
inline void emColor::Set(emUInt32 packed)
{
Packed=packed;
}
inline void emColor::Set(emByte red, emByte green, emByte blue, emByte alpha)
{
Components.Red=red;
Components.Green=green;
Components.Blue=blue;
Components.Alpha=alpha;
}
inline void emColor::Set(const emColor & color)
{
Packed=color.Packed;
}
inline void emColor::Set(const emColor & rgb, emByte alpha)
{
// Did not work error-free with every compiler:
// Packed=rgb.Packed;
// Components.Alpha=alpha;
// Therefore:
Components.Red=rgb.Components.Red;
Components.Green=rgb.Components.Green;
Components.Blue=rgb.Components.Blue;
Components.Alpha=alpha;
}
inline emByte emColor::GetRed() const
{
return Components.Red;
}
inline emByte emColor::GetGreen() const
{
return Components.Green;
}
inline emByte emColor::GetBlue() const
{
return Components.Blue;
}
inline emByte emColor::GetAlpha() const
{
return Components.Alpha;
}
inline void emColor::SetRed(emByte red)
{
Components.Red=red;
}
inline void emColor::SetGreen(emByte green)
{
Components.Green=green;
}
inline void emColor::SetBlue(emByte blue)
{
Components.Blue=blue;
}
inline void emColor::SetAlpha(emByte alpha)
{
Components.Alpha=alpha;
}
inline bool emColor::IsTotallyTransparent() const
{
return Components.Alpha==0;
}
inline bool emColor::IsOpaque() const
{
return Components.Alpha==255;
}
inline bool emColor::IsGrey() const
{
return
Components.Red==Components.Green &&
Components.Red==Components.Blue
;
}
inline emByte emColor::GetGrey() const
{
return (emByte)(
(
((int)Components.Red)+
((int)Components.Green)+
((int)Components.Blue)+
1
)/3
);
}
inline void emColor::SetGrey(emByte grey, emByte alpha)
{
Components.Red=grey;
Components.Green=grey;
Components.Blue=grey;
Components.Alpha=alpha;
}
inline void emColor::SetHue(float hue)
{
SetHSVA(hue,GetSat(),GetVal(),GetAlpha());
}
inline void emColor::SetSat(float sat)
{
SetHSVA(GetHue(),sat,GetVal(),GetAlpha());
}
inline void emColor::SetVal(float val)
{
SetHSVA(GetHue(),GetSat(),val,GetAlpha());
}
inline bool emColor::operator == (const emColor & color) const
{
return Packed==color.Packed;
}
inline bool emColor::operator != (const emColor & color) const
{
return Packed!=color.Packed;
}
inline bool emColor::operator == (emUInt32 packed) const
{
return Packed==packed;
}
inline bool emColor::operator != (emUInt32 packed) const
{
return Packed!=packed;
}
inline bool operator == (emUInt32 packed, const emColor & color)
{
return packed==color.Packed;
}
inline bool operator != (emUInt32 packed, const emColor & color)
{
return packed!=color.Packed;
}
#endif