// // Copyright (c) 1993-2022 Robert McNeel & Associates. All rights reserved. // OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert // McNeel & Associates. // // THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. // ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF // MERCHANTABILITY ARE HEREBY DISCLAIMED. // // For complete openNURBS copyright information see . // //////////////////////////////////////////////////////////////// #if !defined(OPENNURBS_COLOR_INC_) #define OPENNURBS_COLOR_INC_ /////////////////////////////////////////////////////////////////////////////// // // Class ON_Color // class ON_CLASS ON_Color { public: ON_Color() = default; ~ON_Color() = default; ON_Color(const ON_Color&) = default; ON_Color& operator=(const ON_Color&) = default; static const ON_Color UnsetColor; // 0xFFFFFFFFu static const ON_Color Black; // 0x00000000u static const ON_Color White; // 0x00FFFFFFu on little endan, 0xFFFFFF00u on big endian static const ON_Color SaturatedRed; // 0x000000FFu on little endan, 0xFF000000u on big endian static const ON_Color SaturatedGreen; // 0x0000FF00u on little endan, 0x00FF0000u on big endian static const ON_Color SaturatedBlue; // 0x00FF0000u on little endan, 0x0000FF00u on big endian static const ON_Color SaturatedYellow; // 0x0000FFFFu on little endan, 0xFFFF0000u on big endian static const ON_Color SaturatedCyan; // 0x00FFFF00u on little endan, 0x00FFFF00u on big endian static const ON_Color SaturatedMagenta; // 0x00FF00FFu on little endan, 0xFF00FF00u on big endian static const ON_Color SaturatedGold; // 0x0000BFFFu on little endan, 0xFFBF0000u on big endian static const ON_Color Gray105; // R = G = B = 105 (medium dark) static const ON_Color Gray126; // R = G = B = 128 (medium) static const ON_Color Gray160; // R = G = B = 160 (medium light) static const ON_Color Gray230; // R = G = B = 230 (light) static const ON_Color Gray250; // R = G = B = 250 (lightest) // If you need to use byte indexing to convert RGBA components to and from // an unsigned int ON_Color value and want your code to work on both little // and big endian computers, then use the RGBA_byte_index enum. // // unsigned int u; // unsigned char* rgba = &y; // rbga[ON_Color::kRedByteIndex] = red value 0 to 255. // rbga[ON_Color::kGreenByteIndex] = green value 0 to 255. // rbga[ON_Color::kBlueByteIndex] = blue value 0 to 255. // rbga[ON_Color::kAlphaByteIndex] = alpha value 0 to 255. // ON_Color color = u; enum RGBA_byte_index : unsigned int { // same for both little and big endian computers. kRedByteIndex = 0, kGreenByteIndex = 1, kBlueByteIndex = 2, kAlphaByteIndex = 3 }; /// True if this color is not equal to ON_Color::Unset. bool IsSet() const; /// True if this color is equal to ON_Color::Unset. bool IsUnset() const; /* Returns: A random color. */ static const ON_Color RandomColor(); /* Parameters: seed - [in] hue_range - [in] range of hues. Use ON_Interval::ZeroToTwoPi for all hues. 0 = red, pi/3 = yellow, 2pi/3 = green, pi = cyan, 4pi/3 = blue, 5pi/3 = magenta, 2pi = red saturation_range - [in] range of saturations. Use ON_Interval::ZeroToOne for all saturations. value_range - [in] range of values. Use ON_Interval::ZeroToOne for all values. Returns: A color generated from seed. The color for a given seed will always be the same. */ static const ON_Color RandomColor( ON_Interval hue_range, ON_Interval saturation_range, ON_Interval value_range ); /* Returns: A color generated from seed. The color for a given seed will always be the same. */ static const ON_Color RandomColor( ON__UINT32 seed ); /* Parameters: seed - [in] hue_range - [in] range of hues. Use ON_Interval::ZeroToTwoPi for all hues. 0 = red, pi/3 = yellow, 2pi/3 = green, pi = cyan, 4pi/3 = blue, 5pi/3 = magenta, 2pi = red saturation_range - [in] range of saturations. Use ON_Interval::ZeroToOne for all saturations. value_range - [in] range of values. Use ON_Interval::ZeroToOne for all values. Returns: A color generated from seed. The color for a given seed will always be the same. */ static const ON_Color RandomColor( ON__UINT32 seed, ON_Interval hue_range, ON_Interval saturation_range, ON_Interval value_range ); /// /// Get the saturated color with the specified hue. /// /// /// 0 = red, pi/3 = yellow, 2pi/3 = green, pi = cyan, /// 4pi/3 = blue, 5pi/3 = magenta, 2pi = red /// /// /// A saturated color with the specified hue. /// static const ON_Color FromHueInRadians( double hue_in_radians ); // If you need to use shifting to convert RGBA components to and from // an unsigned int ON_COlor value and you want your code to work // on both little and big endian computers, use the RGBA_shift enum. // // unsigned int u = 0; // u |= ((((unsigned int)red) & 0xFFU) << ON_Color::RGBA_shift::kRedShift); // u |= ((((unsigned int)green) & 0xFFU) << ON_Color::RGBA_shift::kGreenShift); // u |= ((((unsigned int)blue) & 0xFFU) << ON_Color::RGBA_shift::kBlueShift); // u |= ((((unsigned int)alpha) & 0xFFU) << ON_Color::RGBA_shift::kAlphaShift); // ON_Color color = u; enum RGBA_shift : unsigned int { #if defined(ON_LITTLE_ENDIAN) kRedShift = 0, kGreenShift = 8, kBlueShift = 16, kAlphaShift = 24 #elif defined(ON_BIG_ENDIAN) kRedShift = 24, kGreenShift = 16, kBlueShift = 8, kAlphaShift = 0 #else #error unknown endian #endif }; // Sets A = 0 ON_Color( int red, // ( 0 to 255 ) int green, // ( 0 to 255 ) int blue // ( 0 to 255 ) ); ON_Color( int red, // ( 0 to 255 ) int green, // ( 0 to 255 ) int blue, // ( 0 to 255 ) int alpha // ( 0 to 255 ) (0 = opaque, 255 = transparent) ); /* Parameters: colorref - [in] Windows COLORREF in little endian RGBA order. */ ON_Color( unsigned int colorref ); // Conversion to Windows COLORREF in little endian RGBA order. operator unsigned int() const; /* Description: Call this function when the color is needed in a Windows COLORREF format with alpha = 0; Returns A Windows COLOREF with alpha = 0. */ unsigned int WindowsRGB() const; // < 0 if this < arg, 0 ir this==arg, > 0 if this > arg int Compare( const ON_Color& ) const; int Red() const; // ( 0 to 255 ) int Green() const; // ( 0 to 255 ) int Blue() const; // ( 0 to 255 ) int Alpha() const; // ( 0 to 255 ) (0 = opaque, 255 = transparent) double FractionRed() const; // ( 0.0 to 1.0 ) double FractionGreen() const; // ( 0.0 to 1.0 ) double FractionBlue() const; // ( 0.0 to 1.0 ) double FractionAlpha() const; // ( 0.0 to 1.0 ) (0.0 = opaque, 1.0 = transparent) void SetRGB( int red, // red in range 0 to 255 int green, // green in range 0 to 255 int blue // blue in range 0 to 255 ); void SetFractionalRGB( double red, // red in range 0.0 to 1.0 double green, // green in range 0.0 to 1.0 double blue // blue in range 0.0 to 1.0 ); void SetAlpha( int alpha // alpha in range 0 to 255 (0 = opaque, 255 = transparent) ); void SetFractionalAlpha( double alpha // alpha in range 0.0 to 1.0 (0.0 = opaque, 1.0 = transparent) ); void SetRGBA( int red, // red in range 0 to 255 int green, // green in range 0 to 255 int blue, // blue in range 0 to 255 int alpha // alpha in range 0 to 255 (0 = opaque, 255 = transparent) ); // input args void SetFractionalRGBA( double red, // red in range 0.0 to 1.0 double green, // green in range 0.0 to 1.0 double blue, // blue in range 0.0 to 1.0 double alpha // alpha in range 0.0 to 1.0 (0.0 = opaque, 1.0 = transparent) ); // Hue() returns an angle in radians in the range 0 to 2*pi. // 0 = red, pi/3 = yellow, 2pi/3 = green, pi = cyan, // 4pi/3 = blue, 5pi/3 = magenta, 2pi = red double Hue() const; // Returns 0.0 (gray) to 1.0 (saturated) double Saturation() const; // Returns 0.0 (black) to 1.0 (white) double Value() const; /// /// Specify a color using HSV (hue, saturation, value). /// /// /// hue in radians /// 0 = red, pi/3 = yellow, 2pi/3 = green, pi = cyan, /// 4pi/3 = blue, 5pi/3 = magenta, 2pi = red /// /// satuation 0.0 = gray, 1.0 = saturated /// value 0=black, 1.0 = bright void SetHSV( double h, double s, double v ); /// /// Formats used by ON_Color::ToText() and ON_Color::ToString(). /// enum class TextFormat: unsigned char { /// /// Indicates no format has been selected. Empty text is created. /// Unset = 0, /// /// red,green,blue as floating point values from 0.0 to 1.0. /// FractionalRGB = 1, /// /// red,green,blue as floating point values from 0.0 to 1.0. alpha is appended if it is not zero. /// FractionalRGBa = 2, /// /// red,green,blue,alpha as floating point values from 0.0 to 1.0. /// FractionalRGBA = 3, /// /// red,green,blue as decimal integers from 0 to 255. /// DecimalRGB = 4, /// /// red,green,blue as decimal integers from 0 to 255. alpha is appended if it is not zero. /// DecimalRGBa = 5, /// /// red,green,blue,alpha as decimal integers from 0 to 255. /// DecimalRGBA = 6, /// /// red,green,blue as hexadecimal integers from 0 to 255. /// HexadecimalRGB = 7, /// /// red,green,blue as hexadecimal integers from 0 to 255. alpha is appended if it is not zero. /// HexadecimalRGBa = 8, /// /// red,green,blue,alpha as hexadecimal integers from 0 to 255. /// HexadecimalRGBA = 9, /// /// hue (0 to 2pi), saturation (0 to 1), value (0 to 1) as floating point values. /// HSV = 10, /// /// hue (0 to 2pi), saturation (0 to 1), value (0 to 1) as floating point values. alpha (0 to 1) is appended if it is not zero. /// HSVa = 11, /// /// hue (0 to 2pi), saturation (0 to 1), value (0 to 1), alpha (0 to 1) as floating point values. /// HSVA = 12, /// /// red,green,blue as two hex digit hexadecimal numbers preceded with a hash. (#RRGGBB) /// HashRGB = 13, /// /// red,green,blue as two hex digit hexadecimal numbers preceded with a hash. alpha is appended if it is not zero. (#RRGGBBaa) /// HashRGBa = 14, /// /// red,green,blue,alpha as two hex digit hexadecimal numbers preceded with a hash. (#RRGGBBAA). /// HashRGBA = 15, }; /* Parameters: format - [in] separator - [in] Separarates the values. 0 to use UNICODE comma. (Ignored when the format is HashRGB*.) character to separate numbers (unicode code point - UTF-16 surrogate pairs not supported) pass 0 for default. bFormatUnsetColor - [in] If true, ON_Color::UnsetColor will return "UnsetColor". Otherwise ON_Color::UnsetColor will return the empty string. */ const ON_wString ToString( ON_Color::TextFormat format, wchar_t separator, bool bFormatUnsetColor ) const; /*MISTAKE - BUT IT SNUCK INTO THE SDK - IGNORE*/ const ON_wString ToString( ON_Color::TextFormat format, wchar_t separator, bool bFormatUnsetColor, class ON_TextLog& ignored_parameter ) const; /* Parameters: format - [in] If format is ON_Color::TextFormat::Unset, then text_log.ColorFormat is used. separator - [in] 0 to use UNICODE comma. (Ignored when the format is HashRGB*.) character to separate numbers (unicode code point - UTF-16 surrogate pairs not supported) pass 0 for default. bFormatUnsetColor - [in] If true, ON_Color::UnsetColor will return "UnsetColor". Otherwise ON_Color::UnsetColor will return the empty string. text_log - [in] destination of the text. */ void ToText( ON_Color::TextFormat format, wchar_t separator, bool bFormatUnsetColor, class ON_TextLog& text_log ) const; private: union { // On little endian (Intel) computers, m_color has the same byte order // as Windows COLORREF values. // On little endian computers, m_color = 0xaabbggrr as an unsigned int value. // On big endian computers, m_color = 0xrrggbbaa as an unsigned int value // rr = red component 0-255 // gg = grean component 0-255 // bb = blue component 0-255 // aa = alpha 0-255. 0 means opaque, 255 means transparent. unsigned int m_color = 0; // m_colorComponent is a 4 unsigned byte array in RGBA order // red component = m_RGBA[ON_Color::RGBA_byte::kRed] // grean component = m_RGBA[ON_Color::RGBA_byte::kGreen] // blue component = m_RGBA[ON_Color::RGBA_byte::kBlue] // alpha component = m_RGBA[ON_Color::RGBA_byte::kAlpha] unsigned char m_RGBA[4]; }; }; /////////////////////////////////////////////////////////////////////////////// // // Class ON_ColorStop // // Combination of a color and a single value. Typically used for defining // gradient fills over a series of colors. class ON_CLASS ON_ColorStop { public: ON_ColorStop() = default; ON_ColorStop(const ON_Color& color, double position); bool Write(class ON_BinaryArchive& archive) const; bool Read(class ON_BinaryArchive& archive); ON_Color m_color = ON_Color::UnsetColor; double m_position = 0; }; #if defined(ON_DLL_TEMPLATE) ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray; #endif class ON_CLASS ON_4fColor { public: ON_4fColor(); ~ON_4fColor() = default; ON_4fColor(int r, int g, int b, int a); ON_4fColor(float r, float g, float b, float a); ON_4fColor(const ON_4fColor&) = default; ON_4fColor& operator = (const ON_4fColor&) = default; static const ON_4fColor Unset; // Note that this function will set the alpha correctly from ON_Color's 'inverted' alpha. ON_4fColor(const ON_Color&); ON_4fColor& operator = (const ON_Color&); bool operator == (const ON_4fColor&); bool operator != (const ON_4fColor&); // Will invert the opacity alpha to transparency. operator ON_Color(void) const; float Red(void) const; void SetRed(float r); float Green(void) const; void SetGreen(float g); float Blue(void) const; void SetBlue(float b); // Alpha in ON_4fColor is OPACITY, not transparency as in ON_Color. float Alpha(void) const; void SetAlpha(float a); void SetRGBA(float r, float g, float b, float a); bool IsValid(class ON_TextLog* text_log = nullptr) const; // Returns: < 0 if (this < other), 0 if (this == other), > 0 if (this > other). int Compare(const ON_4fColor& other) const; // Blend this color to 'col' using 't' from 0.0 to 1.0. // Note: Does not clamp 't' or RGB result unless clampAlpha is true, in which case alpha is clamped. void BlendTo(float t, const ON_4fColor& col, bool clampAlpha=false); // Direct read/write access to array of four floats. // NOTE: If you access the array beyond the 4th element, the function may crash Rhino. float* FloatArray(void); // Direct read access to array of four floats. // NOTE: If you access the array beyond the 4th element, the function may crash Rhino. const float* FloatArray(void) const; private: float m_color[4]; }; #if defined(ON_DLL_TEMPLATE) ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray; #endif #endif