Logo ROOT   6.18/05
Reference Guide
RColor.hxx
Go to the documentation of this file.
1/// \file ROOT/RColor.hxx
2/// \ingroup Gpad ROOT7
3/// \author Axel Naumann <axel@cern.ch>
4/// \date 2017-09-26
5/// \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback
6/// is welcome!
7
8/*************************************************************************
9 * Copyright (C) 1995-2017, Rene Brun and Fons Rademakers. *
10 * All rights reserved. *
11 * *
12 * For the licensing terms see $ROOTSYS/LICENSE. *
13 * For the list of contributors see $ROOTSYS/README/CREDITS. *
14 *************************************************************************/
15
16#ifndef ROOT7_RColor
17#define ROOT7_RColor
18
19#include <array>
20#include <vector>
21
22namespace ROOT {
23namespace Experimental {
24
25/** \class ROOT::Experimental::RColor
26 A color: Red|Green|Blue|Alpha, or a position in a RPalette
27 */
28class RColor {
29public:
30 /** \class ROOT::Experimental::RColor::TAlpha
31 The alpha value of a color: 0 is completely transparent, 1 is completely opaque.
32 */
33 struct Alpha {
34 float fVal;
35 explicit operator float() const { return fVal; }
36 };
37 /// An opaque color.
38 static constexpr Alpha kOpaque{1.};
39 /// A completely transparent color.
40 static constexpr Alpha kTransparent{0.};
41
42 enum class EKind {
43 kRGBA, ///< The color is defined as specific RGBA values.
44 kPalettePos, ///< The color is defined as a value in the `RFrame`'s `RPalette`.
45 kAuto ///< The color will be set upon drawing the canvas choosing a `RPalette` color, see `RColor(Auto_t)`
46 };
47
48private:
49 // TODO: use a `variant` here!
50 /// The "R" in RGBA (0 <= R <= 1), or the palette pos if fKind is `kPalettePos`.
51 float fRedOrPalettePos = 0.;
52
53 /// The "G" in RGBA (0 <= G <= 1). Unused if `fKind != kRGBA`.
54 float fGreen = 0.;
55
56 /// The "B" in RGBA (0 <= B <= 1). Unused if `fKind != kRGBA`.
57 float fBlue = 0.;
58
59 /// The "A" in RGBA (0 <= A <= 1). Unused if `fKind != kRGBA`. `fAlpha == 0` means so transparent it's invisible,
60 /// `fAlpha == 1` means completely opaque.
61 float fAlpha = 1.;
62
63 /// How the color is defined.
65
66 /// throw an exception if the color isn't specified as `kRGBA` or `kAuto`, the two cases where
67 /// asking for RBGA members makes sense.
68 bool AssertNotPalettePos() const;
69
70public:
71 using RGBA = std::array<float, 4>;
72
73 // Default constructor: good old solid black.
74 constexpr RColor() = default;
75
76 /// Initialize a RColor with red, green, blue and alpha component.
77 constexpr RColor(float r, float g, float b, float alpha): fRedOrPalettePos(r), fGreen(g), fBlue(b), fAlpha(alpha) {}
78
79 /// Initialize a RColor with red, green, blue and alpha component.
80 constexpr RColor(float r, float g, float b, Alpha alpha = kOpaque): RColor(r, g, b, alpha.fVal) {}
81
82 /// Initialize a RColor with red, green, blue and alpha component as an array.
83 constexpr RColor(const RGBA &rgba): RColor(rgba[0], rgba[1], rgba[2], rgba[3]) {}
84
85 /// Initialize a `RColor` with a `RPalette` ordinal. The actual color is determined from the pad's
86 /// (or rather its `RFrame`'s) `RPalette`
87 constexpr RColor(float paletteOrdinal): fRedOrPalettePos(paletteOrdinal), fKind(EKind::kPalettePos) {}
88
89 /**\class AutoTag
90 Used to signal that this color shall be automatically chosen by the drawing routines, by picking a color
91 from the `RPad`'s (or rather its `RFrame`'s) current `RPalette`.
92 */
93 class AutoTag {};
94
95 /// Constructs an automatically assigned color. Call as `RColor col(RColor::kAuto)`.
96 constexpr RColor(AutoTag): fKind(EKind::kAuto) {}
97
98 /// Determine whether this RColor is storing RGBA (in contrast to an ordinal of a RPalette).
99 bool IsRGBA() const { return fKind == EKind::kRGBA; }
100
101 /// Determine whether this `RColor` is storing an ordinal of a RPalette (in contrast to RGBA).
102 bool IsPaletteOrdinal() const { return fKind == EKind::kPalettePos; }
103
104 /// Determine whether this `RColor` will be assigned a actual color upon drawing.
105 bool IsAuto() const { return fKind == EKind::kAuto; }
106
107 /// If this is an ordinal in a palette, resolve the
108 float GetPaletteOrdinal() const;
109
110 friend bool operator==(const RColor &lhs, const RColor &rhs)
111 {
112 if (lhs.fKind != rhs.fKind)
113 return false;
114 switch (lhs.fKind) {
116 return lhs.fRedOrPalettePos == rhs.fRedOrPalettePos;
117 case EKind::kRGBA:
118 return lhs.fRedOrPalettePos == rhs.fRedOrPalettePos && lhs.fGreen == rhs.fGreen && lhs.fBlue == rhs.fBlue &&
119 lhs.fAlpha == rhs.fAlpha;
120 case EKind::kAuto:
121 return true; // is that what we need?
122 }
123 return false;
124 }
125
126 /// For RGBA or auto colors, get the red component (0..1).
127 float GetRed() const {
129 return fRedOrPalettePos;
130 return 0.;
131 }
132
133 /// For RGBA or auto colors, get the green component (0..1).
134 float GetGreen() const {
136 return fGreen;
137 return 0.;
138 }
139
140 /// For RGBA or auto colors, get the blue component (0..1).
141 float GetBlue() const {
143 return fBlue;
144 return 0.;
145 }
146
147 /// For RGBA or auto colors, get the alpha component (0..1).
148 float GetAlpha() const {
150 return fAlpha;
151 return 0.;
152 }
153
154 /// For RGBA or auto colors, set the red component.
155 void SetRed(float r) {
158 }
159
160 /// For RGBA or auto colors, set the green component.
161 void SetGreen(float g) {
163 fGreen = g;
164 }
165
166 /// For RGBA or auto colors, set the blue component.
167 void SetBlue(float b) {
169 fBlue = b;
170 }
171
172 /// For RGBA or auto colors, set the alpha component.
173 void SetAlpha(float a) {
175 fAlpha = a;
176 }
177
178 /// For RGBA or auto colors, set the alpha component.
181 fAlpha = (float)a;
182 }
183
184 /// Return the Hue, Light, Saturation (HLS) definition of this RColor
185 void GetHLS(float &hue, float &light, float &satur) {
186 hue = light = satur = 0.;
187 if (AssertNotPalettePos()) {
188 float rnorm, gnorm, bnorm, minval, maxval, msum, mdiff;
189 minval = maxval =0 ;
190
191 minval = fRedOrPalettePos;
192 if (fGreen < minval) minval = fGreen;
193 if (fBlue < minval) minval = fBlue;
194 maxval = fRedOrPalettePos;
195 if (fGreen > maxval) maxval = fGreen;
196 if (fBlue > maxval) maxval = fBlue;
197
198 rnorm = gnorm = bnorm = 0;
199 mdiff = maxval - minval;
200 msum = maxval + minval;
201 light = 0.5 * msum;
202 if (maxval != minval) {
203 rnorm = (maxval - fRedOrPalettePos)/mdiff;
204 gnorm = (maxval - fGreen)/mdiff;
205 bnorm = (maxval - fBlue)/mdiff;
206 } else {
207 satur = hue = 0;
208 return;
209 }
210
211 if (light < 0.5) satur = mdiff/msum;
212 else satur = mdiff/(2.0 - msum);
213
214 if (fRedOrPalettePos == maxval) hue = 60.0 * (6.0 + bnorm - gnorm);
215 else if (fGreen == maxval) hue = 60.0 * (2.0 + rnorm - bnorm);
216 else hue = 60.0 * (4.0 + gnorm - rnorm);
217
218 if (hue > 360) hue = hue - 360;
219 }
220 }
221
222 /// Set the Red Green and Blue (RGB) values from the Hue, Light, Saturation (HLS).
223 void SetRGBFromHLS(float hue, float light, float satur) {
224 if (AssertNotPalettePos()) {
225 float rh, rl, rs, rm1, rm2;
226 rh = rl = rs = 0;
227 if (hue > 0) { rh = hue; if (rh > 360) rh = 360; }
228 if (light > 0) { rl = light; if (rl > 1) rl = 1; }
229 if (satur > 0) { rs = satur; if (rs > 1) rs = 1; }
230
231 if (rl <= 0.5) rm2 = rl*(1.0 + rs);
232 else rm2 = rl + rs - rl*rs;
233 rm1 = 2.0*rl - rm2;
234
235 if (!rs) { fRedOrPalettePos = fGreen = fBlue = rl; return; }
236
237 auto toRGB = [rm1, rm2] (float h) {
238 if (h > 360) h = h - 360;
239 if (h < 0) h = h + 360;
240 if (h < 60 ) return rm1 + (rm2-rm1)*h/60;
241 if (h < 180) return rm2;
242 if (h < 240) return rm1 + (rm2-rm1)*(240-h)/60;
243 return rm1;
244 };
245
246 fRedOrPalettePos = toRGB(rh+120);
247 fGreen = toRGB(rh);
248 fBlue = toRGB(rh-120);
249 }
250 }
251
252 ///\{
253 ///\name Default colors
254 static constexpr RGBA kRed{{1., 0., 0., 1.}};
255 static constexpr RGBA kGreen{{0., 1., 0., 1.}};
256 static constexpr RGBA kBlue{{0., 0, 1., 1.}};
257 static constexpr RGBA kWhite{{1., 1, 1., 1.}};
258 static constexpr RGBA kBlack{{0., 0., 0., 1.}};
259 static constexpr RGBA kInvisible{{0., 0., 0., 0.}};
260 static constexpr AutoTag kAuto{};
261 ///\}
262};
263
264// TODO: see also imagemagick's C++ interface for RColor operations!
265// https://www.imagemagick.org/api/magick++-classes.php
266
267RColor FromAttributeString(const std::string &str, const std::string &name, RColor*);
268std::string ToAttributeString(const RColor& val);
269
270} // namespace Experimental
271} // namespace ROOT
272
273#endif
ROOT::R::TRInterface & r
Definition: Object.C:4
#define b(i)
Definition: RSha256.hxx:100
#define g(i)
Definition: RSha256.hxx:105
#define h(i)
Definition: RSha256.hxx:106
char name[80]
Definition: TGX11.cxx:109
Used to signal that this color shall be automatically chosen by the drawing routines,...
Definition: RColor.hxx:93
A color: Red|Green|Blue|Alpha, or a position in a RPalette.
Definition: RColor.hxx:28
constexpr RColor(const RGBA &rgba)
Initialize a RColor with red, green, blue and alpha component as an array.
Definition: RColor.hxx:83
friend bool operator==(const RColor &lhs, const RColor &rhs)
Definition: RColor.hxx:110
static constexpr RGBA kInvisible
Definition: RColor.hxx:259
bool AssertNotPalettePos() const
throw an exception if the color isn't specified as kRGBA or kAuto, the two cases where asking for RBG...
Definition: RColor.cxx:49
void SetAlpha(Alpha a)
For RGBA or auto colors, set the alpha component.
Definition: RColor.hxx:179
void SetRed(float r)
For RGBA or auto colors, set the red component.
Definition: RColor.hxx:155
void SetAlpha(float a)
For RGBA or auto colors, set the alpha component.
Definition: RColor.hxx:173
float GetAlpha() const
For RGBA or auto colors, get the alpha component (0..1).
Definition: RColor.hxx:148
@ kAuto
The color will be set upon drawing the canvas choosing a RPalette color, see RColor(Auto_t)
@ kRGBA
The color is defined as specific RGBA values.
@ kPalettePos
The color is defined as a value in the RFrame's RPalette.
bool IsAuto() const
Determine whether this RColor will be assigned a actual color upon drawing.
Definition: RColor.hxx:105
bool IsRGBA() const
Determine whether this RColor is storing RGBA (in contrast to an ordinal of a RPalette).
Definition: RColor.hxx:99
float GetRed() const
For RGBA or auto colors, get the red component (0..1).
Definition: RColor.hxx:127
static constexpr AutoTag kAuto
Definition: RColor.hxx:260
static constexpr Alpha kOpaque
An opaque color.
Definition: RColor.hxx:38
float GetBlue() const
For RGBA or auto colors, get the blue component (0..1).
Definition: RColor.hxx:141
static constexpr Alpha kTransparent
A completely transparent color.
Definition: RColor.hxx:40
constexpr RColor(AutoTag)
Constructs an automatically assigned color. Call as RColor col(RColor::kAuto).
Definition: RColor.hxx:96
EKind fKind
How the color is defined.
Definition: RColor.hxx:64
void SetRGBFromHLS(float hue, float light, float satur)
Set the Red Green and Blue (RGB) values from the Hue, Light, Saturation (HLS).
Definition: RColor.hxx:223
void SetBlue(float b)
For RGBA or auto colors, set the blue component.
Definition: RColor.hxx:167
float GetPaletteOrdinal() const
If this is an ordinal in a palette, resolve the.
Definition: RColor.cxx:42
std::array< float, 4 > RGBA
Definition: RColor.hxx:71
static constexpr RGBA kWhite
Definition: RColor.hxx:257
float GetGreen() const
For RGBA or auto colors, get the green component (0..1).
Definition: RColor.hxx:134
static constexpr RGBA kBlue
Definition: RColor.hxx:256
bool IsPaletteOrdinal() const
Determine whether this RColor is storing an ordinal of a RPalette (in contrast to RGBA).
Definition: RColor.hxx:102
constexpr RColor(float r, float g, float b, float alpha)
Initialize a RColor with red, green, blue and alpha component.
Definition: RColor.hxx:77
static constexpr RGBA kGreen
Definition: RColor.hxx:255
float fBlue
The "B" in RGBA (0 <= B <= 1). Unused if fKind != kRGBA.
Definition: RColor.hxx:57
static constexpr RGBA kBlack
Definition: RColor.hxx:258
constexpr RColor()=default
static constexpr RGBA kRed
Definition: RColor.hxx:254
float fGreen
The "G" in RGBA (0 <= G <= 1). Unused if fKind != kRGBA.
Definition: RColor.hxx:54
float fRedOrPalettePos
The "R" in RGBA (0 <= R <= 1), or the palette pos if fKind is kPalettePos.
Definition: RColor.hxx:51
constexpr RColor(float paletteOrdinal)
Initialize a RColor with a RPalette ordinal.
Definition: RColor.hxx:87
constexpr RColor(float r, float g, float b, Alpha alpha=kOpaque)
Initialize a RColor with red, green, blue and alpha component.
Definition: RColor.hxx:80
void GetHLS(float &hue, float &light, float &satur)
Return the Hue, Light, Saturation (HLS) definition of this RColor.
Definition: RColor.hxx:185
float fAlpha
The "A" in RGBA (0 <= A <= 1).
Definition: RColor.hxx:61
void SetGreen(float g)
For RGBA or auto colors, set the green component.
Definition: RColor.hxx:161
std::string ToAttributeString(const RColor &val)
Return a std::string representation of a RColor, suitable as input to ColorFromString().
Definition: RColor.cxx:144
RColor FromAttributeString(const std::string &str, const std::string &name, RColor *)
Initialize a RColor from a string value.
Definition: RColor.cxx:132
Namespace for new ROOT classes and functions.
Definition: StringConv.hxx:21
auto * a
Definition: textangle.C:12