HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
color.hpp
Go to the documentation of this file.
1// Copyright Take Vos 2021-2022.
2// Distributed under the Boost Software License, Version 1.0.
3// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
4
9#pragma once
10
11#include "../SIMD/module.hpp"
12#include "../geometry/module.hpp"
13#include "../utility/module.hpp"
14#include "../concurrency/module.hpp"
15#include <string>
16#include <map>
17
18namespace hi { inline namespace v1 {
19
44class color {
45public:
46 constexpr color() noexcept = default;
47 constexpr color(color const&) noexcept = default;
48 constexpr color(color&&) noexcept = default;
49 constexpr color& operator=(color const&) noexcept = default;
50 constexpr color& operator=(color&&) noexcept = default;
51
52 [[nodiscard]] constexpr explicit color(f16x4 const& other) noexcept : _v(other)
53 {
54 hi_axiom(holds_invariant());
55 }
56
57 [[nodiscard]] constexpr explicit color(f32x4 const& other) noexcept : color(static_cast<f16x4>(other)) {}
58
59 [[nodiscard]] constexpr explicit operator f16x4() const noexcept
60 {
61 return _v;
62 }
63
64 [[nodiscard]] constexpr explicit operator f32x4() const noexcept
65 {
66 return static_cast<f32x4>(_v);
67 }
68
69 [[nodiscard]] constexpr color(float r, float g, float b, float a = 1.0f) noexcept : color(f32x4{r, g, b, a}) {}
70
73 [[nodiscard]] static inline std::vector<std::string> list() noexcept;
74
80 [[nodiscard]] static inline color *find(std::string const& name) noexcept;
81
82 [[nodiscard]] static inline color black() noexcept;
83 [[nodiscard]] static inline color silver() noexcept;
84 [[nodiscard]] static inline color gray() noexcept;
85 [[nodiscard]] static inline color white() noexcept;
86 [[nodiscard]] static inline color maroon() noexcept;
87 [[nodiscard]] static inline color red() noexcept;
88 [[nodiscard]] static inline color purple() noexcept;
89 [[nodiscard]] static inline color fuchsia() noexcept;
90 [[nodiscard]] static inline color green() noexcept;
91 [[nodiscard]] static inline color lime() noexcept;
92 [[nodiscard]] static inline color olive() noexcept;
93 [[nodiscard]] static inline color yellow() noexcept;
94 [[nodiscard]] static inline color navy() noexcept;
95 [[nodiscard]] static inline color blue() noexcept;
96 [[nodiscard]] static inline color teal() noexcept;
97 [[nodiscard]] static inline color aqua() noexcept;
98 [[nodiscard]] static inline color indigo() noexcept;
99 [[nodiscard]] static inline color orange() noexcept;
100 [[nodiscard]] static inline color pink() noexcept;
101 [[nodiscard]] static inline color background() noexcept;
102 [[nodiscard]] static inline color gray1() noexcept;
103 [[nodiscard]] static inline color gray2() noexcept;
104 [[nodiscard]] static inline color gray3() noexcept;
105 [[nodiscard]] static inline color gray4() noexcept;
106 [[nodiscard]] static inline color gray5() noexcept;
107 [[nodiscard]] static inline color gray6() noexcept;
108 [[nodiscard]] static inline color gray7() noexcept;
109 [[nodiscard]] static inline color gray8() noexcept;
110 [[nodiscard]] static inline color gray9() noexcept;
111 [[nodiscard]] static inline color foreground() noexcept;
112 [[nodiscard]] static inline color transparent() noexcept;
113
114 [[nodiscard]] size_t hash() const noexcept
115 {
116 return std::hash<uint64_t>{}(std::bit_cast<uint64_t>(_v));
117 }
118
119 [[nodiscard]] constexpr float16& r() noexcept
120 {
121 return _v.x();
122 }
123
124 [[nodiscard]] constexpr float16& g() noexcept
125 {
126 return _v.y();
127 }
128
129 [[nodiscard]] constexpr float16& b() noexcept
130 {
131 return _v.z();
132 }
133
134 [[nodiscard]] constexpr float16& a() noexcept
135 {
136 return _v.w();
137 }
138
139 [[nodiscard]] constexpr float16 r() const noexcept
140 {
141 return _v.x();
142 }
143
144 [[nodiscard]] constexpr float16 g() const noexcept
145 {
146 return _v.y();
147 }
148
149 [[nodiscard]] constexpr float16 b() const noexcept
150 {
151 return _v.z();
152 }
153
154 [[nodiscard]] constexpr float16 a() const noexcept
155 {
156 return _v.w();
157 }
158
159 [[nodiscard]] constexpr bool holds_invariant() const noexcept
160 {
161 return _v.w() >= 0.0 && _v.w() <= 1.0;
162 }
163
164 [[nodiscard]] constexpr friend bool operator==(color const& lhs, color const& rhs) noexcept
165 {
166 return equal(lhs._v, rhs._v);
167 }
168
169 [[nodiscard]] constexpr friend color operator*(color const& lhs, color const& rhs) noexcept
170 {
171 return color{lhs._v * rhs._v};
172 }
173
174 [[nodiscard]] constexpr friend color composit(color const& lhs, color const& rhs) noexcept
175 {
176 return color{composit(lhs._v, rhs._v)};
177 }
178
179 [[nodiscard]] constexpr friend color desaturate(color const& rhs) noexcept
180 {
181 hilet rhs_ = f32x4{rhs};
182
183 hilet Y = 0.2126f * rhs_.r() + 0.7152f * rhs_.g() + 0.0722f * rhs_.b();
184
185 return color{Y, Y, Y, rhs_.a()};
186 }
187
197 [[nodiscard]] constexpr friend color operator*(matrix3 const& lhs, color const& rhs) noexcept
198 {
199 hi_axiom(rhs.holds_invariant());
200 auto r = color{
201 get<0>(lhs) * static_cast<f32x4>(rhs).xxxx() + get<1>(lhs) * static_cast<f32x4>(rhs).yyyy() +
202 get<2>(lhs) * static_cast<f32x4>(rhs).zzzz() + get<3>(lhs)};
203
204 r.a() = rhs.a();
205 return r;
206 }
207
208 [[nodiscard]] constexpr friend color operator*(identity3 const& lhs, color const& rhs) noexcept
209 {
210 return rhs;
211 }
212
213 friend std::ostream &operator<<(std::ostream &lhs, color const &rhs)
214 {
215 return lhs << std::format("rgb({} {} {} {})", rhs.r(), rhs.g(), rhs.b(), rhs.a());
216 }
217
218private:
219 f16x4 _v = {};
220};
221
222namespace detail {
223
225public:
226 named_color_base(std::string name, hi::color color) noexcept : _color(color)
227 {
228 hilet lock = std::scoped_lock(_map_mutex);
229 _map[name] = this;
230 }
231
232 named_color_base(named_color_base const&) = delete;
234 named_color_base& operator=(named_color_base const&) = delete;
235 named_color_base& operator=(named_color_base&&) = delete;
236
237 hi::color const& operator*() const noexcept
238 {
239 return _color;
240 }
241
242 hi::color& operator*() noexcept
243 {
244 return _color;
245 }
246
247 operator hi::color() const noexcept
248 {
249 return _color;
250 }
251
252 [[nodiscard]] static std::vector<std::string> list() noexcept
253 {
254 auto r = std::vector<std::string>{};
255
256 hilet lock = std::scoped_lock(_map_mutex);
257 for (auto &item: _map) {
258 r.push_back(item.first);
259 }
260
261 return r;
262 }
263
264 [[nodiscard]] static named_color_base *find(std::string const& name) noexcept
265 {
266 hilet lock = std::scoped_lock(_map_mutex);
267 hilet it = _map.find(name);
268 if (it != _map.end()) {
269 return it->second;
270 } else {
271 return nullptr;
272 }
273 }
274
275private:
276 // The map is protected with a mutex because global variable initialization
277 // may be deferred and run on a different threads. However we can not
278 // use the deadlock detector as it will use a thread_local variable.
279 // The initialization order of static global variables and thread_local
280 // variables are undetermined.
282 inline static unfair_mutex_without_deadlock_detector _map_mutex;
283
284protected:
285 color _color;
286};
287
288template<fixed_string Tag>
290public:
291 named_color_type() noexcept : named_color_base(Tag, hi::color{}) {}
293
294 named_color_type& operator=(hi::color color) noexcept
295 {
296 _color = color;
297 }
298};
299
300} // namespace detail
301
302template<fixed_string Tag>
303inline auto named_color = detail::named_color_type<Tag>{};
304
305[[nodiscard]] inline std::vector<std::string> color::list() noexcept
306{
307 return detail::named_color_base::list();
308}
309
310[[nodiscard]] inline color *color::find(std::string const& name) noexcept
311{
312 if (auto named_color_ptr = detail::named_color_base::find(name)) {
313 return std::addressof(**named_color_ptr);
314 } else {
315 return nullptr;
316 }
317}
318
319// clang-format off
320
321template<> inline auto named_color<"black"> = detail::named_color_type<"black">{color{0, 0, 0}};
322template<> inline auto named_color<"silver"> = detail::named_color_type<"silver">{color{192, 192, 192}};
323template<> inline auto named_color<"gray"> = detail::named_color_type<"gray">{color{128, 128, 128}};
324template<> inline auto named_color<"white"> = detail::named_color_type<"white">{color{255, 255, 255}};
325template<> inline auto named_color<"maroon"> = detail::named_color_type<"maroon">{color{128, 0, 0}};
326template<> inline auto named_color<"red"> = detail::named_color_type<"red">{color{255, 0, 0}};
327template<> inline auto named_color<"purple"> = detail::named_color_type<"purple">{color{128, 0, 128}};
328template<> inline auto named_color<"fuchsia"> = detail::named_color_type<"fuchsia">{color{255, 0, 255}};
329template<> inline auto named_color<"green"> = detail::named_color_type<"green">{color{0, 128, 0}};
330template<> inline auto named_color<"lime"> = detail::named_color_type<"lime">{color{0, 255, 0}};
331template<> inline auto named_color<"olive"> = detail::named_color_type<"olive">{color{128, 128, 0}};
332template<> inline auto named_color<"yellow"> = detail::named_color_type<"yellow">{color{255, 255, 0}};
333template<> inline auto named_color<"navy"> = detail::named_color_type<"navy">{color{0, 0, 128}};
334template<> inline auto named_color<"blue"> = detail::named_color_type<"blue">{color{0, 0, 255}};
335template<> inline auto named_color<"teal"> = detail::named_color_type<"teal">{color{0, 128, 128}};
336template<> inline auto named_color<"aqua"> = detail::named_color_type<"aqua">{color{0, 255, 255}};
337template<> inline auto named_color<"indigo"> = detail::named_color_type<"indigo">{color{75, 0, 130}};
338template<> inline auto named_color<"orange"> = detail::named_color_type<"orange">{color{255, 165, 0}};
339template<> inline auto named_color<"pink"> = detail::named_color_type<"pink">{color{255, 192, 203}};
340template<> inline auto named_color<"background"> = detail::named_color_type<"background">{color{0, 0, 0}};
341template<> inline auto named_color<"gray1"> = detail::named_color_type<"gray1">{color{26, 26, 26}};
342template<> inline auto named_color<"gray2"> = detail::named_color_type<"gray2">{color{51, 51, 51}};
343template<> inline auto named_color<"gray3"> = detail::named_color_type<"gray3">{color{77, 77, 77}};
344template<> inline auto named_color<"gray4"> = detail::named_color_type<"gray4">{color{102, 102, 102}};
345template<> inline auto named_color<"gray5"> = detail::named_color_type<"gray5">{color{127, 127, 127}};
346template<> inline auto named_color<"gray6"> = detail::named_color_type<"gray6">{color{153, 153, 153}};
347template<> inline auto named_color<"gray7"> = detail::named_color_type<"gray7">{color{179, 179, 179}};
348template<> inline auto named_color<"gray8"> = detail::named_color_type<"gray8">{color{204, 204, 204}};
349template<> inline auto named_color<"gray9"> = detail::named_color_type<"gray9">{color{229, 229, 229}};
350template<> inline auto named_color<"foreground"> = detail::named_color_type<"foreground">{color{255, 255, 255}};
351template<> inline auto named_color<"transparent"> = detail::named_color_type<"transparent">{color{0, 0, 0, 0}};
352
353[[nodiscard]] inline color color::black() noexcept { return named_color<"black">; }
354[[nodiscard]] inline color color::silver() noexcept { return named_color<"silver">; }
355[[nodiscard]] inline color color::gray() noexcept { return named_color<"gray">; }
356[[nodiscard]] inline color color::white() noexcept { return named_color<"white">; }
357[[nodiscard]] inline color color::maroon() noexcept { return named_color<"maroon">; }
358[[nodiscard]] inline color color::red() noexcept { return named_color<"red">; }
359[[nodiscard]] inline color color::purple() noexcept { return named_color<"purple">; }
360[[nodiscard]] inline color color::fuchsia() noexcept { return named_color<"fuchsia">; }
361[[nodiscard]] inline color color::green() noexcept { return named_color<"green">; }
362[[nodiscard]] inline color color::lime() noexcept { return named_color<"lime">; }
363[[nodiscard]] inline color color::olive() noexcept { return named_color<"olive">; }
364[[nodiscard]] inline color color::yellow() noexcept { return named_color<"yellow">; }
365[[nodiscard]] inline color color::navy() noexcept { return named_color<"navy">; }
366[[nodiscard]] inline color color::blue() noexcept { return named_color<"blue">; }
367[[nodiscard]] inline color color::teal() noexcept { return named_color<"teal">; }
368[[nodiscard]] inline color color::aqua() noexcept { return named_color<"aqua">; }
369[[nodiscard]] inline color color::indigo() noexcept { return named_color<"indigo">; }
370[[nodiscard]] inline color color::orange() noexcept { return named_color<"orange">; }
371[[nodiscard]] inline color color::pink() noexcept { return named_color<"pink">; }
372[[nodiscard]] inline color color::background() noexcept { return named_color<"background">; }
373[[nodiscard]] inline color color::gray1() noexcept { return named_color<"gray1">; }
374[[nodiscard]] inline color color::gray2() noexcept { return named_color<"gray2">; }
375[[nodiscard]] inline color color::gray3() noexcept { return named_color<"gray3">; }
376[[nodiscard]] inline color color::gray4() noexcept { return named_color<"gray4">; }
377[[nodiscard]] inline color color::gray5() noexcept { return named_color<"gray5">; }
378[[nodiscard]] inline color color::gray6() noexcept { return named_color<"gray6">; }
379[[nodiscard]] inline color color::gray7() noexcept { return named_color<"gray7">; }
380[[nodiscard]] inline color color::gray8() noexcept { return named_color<"gray8">; }
381[[nodiscard]] inline color color::gray9() noexcept { return named_color<"gray9">; }
382[[nodiscard]] inline color color::foreground() noexcept { return named_color<"foreground">; }
383[[nodiscard]] inline color color::transparent() noexcept { return named_color<"transparent">; }
384// clang-format on
385
386}} // namespace hi::v1
387
388template<>
389struct std::hash<hi::color> {
390 [[nodiscard]] size_t operator()(hi::color const& rhs) const noexcept
391 {
392 return rhs.hash();
393 }
394};
395
396
#define hi_axiom(expression,...)
Specify an axiom; an expression that is true.
Definition assert.hpp:253
#define hilet
Invariant should be the default for variables.
Definition utility.hpp:23
@ other
The gui_event does not have associated data.
DOXYGEN BUG.
Definition algorithm.hpp:13
geometry/margins.hpp
Definition cache.hpp:11
This is a RGBA floating point color.
Definition color.hpp:44
static color * find(std::string const &name) noexcept
Find a color by name.
Definition color.hpp:310
static std::vector< std::string > list() noexcept
List color names.
Definition color.hpp:305
constexpr friend color operator*(matrix3 const &lhs, color const &rhs) noexcept
Transform a color by a color matrix.
Definition color.hpp:197
Definition color.hpp:224
Definition color.hpp:289
Identity transform.
Definition identity.hpp:20
A 2D or 3D homogenius matrix for transforming homogenious vectors and points.
Definition matrix.hpp:33
T addressof(T... args)
T operator()(T... args)