HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
color_intf.hpp
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
8
9#pragma once
10
11#include "../geometry/geometry.hpp"
12#include "../utility/utility.hpp"
13#include "../macros.hpp"
14#include <hikocpu/hikocpu.hpp>
15#include <string>
16#include <map>
17#include <mutex>
18#include <format>
19
20hi_export_module(hikogui.color : color_intf);
21
22hi_export namespace hi {
23inline namespace v1 {
24
49class color {
50public:
51 constexpr color() noexcept = default;
52 constexpr color(color const&) noexcept = default;
53 constexpr color(color&&) noexcept = default;
54 constexpr color& operator=(color const&) noexcept = default;
55 constexpr color& operator=(color&&) noexcept = default;
56
57 [[nodiscard]] constexpr explicit color(f16x4 const& other) noexcept : _v(other)
58 {
59 hi_axiom(holds_invariant());
60 }
61
62 [[nodiscard]] constexpr explicit color(f32x4 const& other) noexcept : color(static_cast<f16x4>(other)) {}
63
64 [[nodiscard]] constexpr explicit operator f16x4() const noexcept
65 {
66 return _v;
67 }
68
69 [[nodiscard]] constexpr explicit operator f32x4() const noexcept
70 {
71 return static_cast<f32x4>(_v);
72 }
73
74 [[nodiscard]] constexpr color(float r, float g, float b, float a = 1.0f) noexcept : color(f32x4{r, g, b, a}) {}
75
78 [[nodiscard]] static inline std::vector<std::string> list() noexcept;
79
85 [[nodiscard]] static inline color* find(std::string const& name) noexcept;
86
87 [[nodiscard]] static inline color black() noexcept;
88 [[nodiscard]] static inline color silver() noexcept;
89 [[nodiscard]] static inline color gray() noexcept;
90 [[nodiscard]] static inline color white() noexcept;
91 [[nodiscard]] static inline color maroon() noexcept;
92 [[nodiscard]] static inline color red() noexcept;
93 [[nodiscard]] static inline color purple() noexcept;
94 [[nodiscard]] static inline color fuchsia() noexcept;
95 [[nodiscard]] static inline color green() noexcept;
96 [[nodiscard]] static inline color lime() noexcept;
97 [[nodiscard]] static inline color olive() noexcept;
98 [[nodiscard]] static inline color yellow() noexcept;
99 [[nodiscard]] static inline color navy() noexcept;
100 [[nodiscard]] static inline color blue() noexcept;
101 [[nodiscard]] static inline color teal() noexcept;
102 [[nodiscard]] static inline color aqua() noexcept;
103 [[nodiscard]] static inline color indigo() noexcept;
104 [[nodiscard]] static inline color orange() noexcept;
105 [[nodiscard]] static inline color pink() noexcept;
106 [[nodiscard]] static inline color gray0() noexcept;
107 [[nodiscard]] static inline color gray1() noexcept;
108 [[nodiscard]] static inline color gray2() noexcept;
109 [[nodiscard]] static inline color gray3() noexcept;
110 [[nodiscard]] static inline color gray4() noexcept;
111 [[nodiscard]] static inline color gray5() noexcept;
112 [[nodiscard]] static inline color gray6() noexcept;
113 [[nodiscard]] static inline color gray7() noexcept;
114 [[nodiscard]] static inline color gray8() noexcept;
115 [[nodiscard]] static inline color gray9() noexcept;
116 [[nodiscard]] static inline color gray10() noexcept;
117 [[nodiscard]] static inline color transparent() noexcept;
118
119 [[nodiscard]] size_t hash() const noexcept
120 {
121 return std::hash<uint64_t>{}(std::bit_cast<uint64_t>(_v));
122 }
123
124 [[nodiscard]] constexpr half& r() noexcept
125 {
126 return _v.x();
127 }
128
129 [[nodiscard]] constexpr half& g() noexcept
130 {
131 return _v.y();
132 }
133
134 [[nodiscard]] constexpr half& b() noexcept
135 {
136 return _v.z();
137 }
138
139 [[nodiscard]] constexpr half& a() noexcept
140 {
141 return _v.w();
142 }
143
144 [[nodiscard]] constexpr half r() const noexcept
145 {
146 return _v.x();
147 }
148
149 [[nodiscard]] constexpr half g() const noexcept
150 {
151 return _v.y();
152 }
153
154 [[nodiscard]] constexpr half b() const noexcept
155 {
156 return _v.z();
157 }
158
159 [[nodiscard]] constexpr half a() const noexcept
160 {
161 return _v.w();
162 }
163
164 [[nodiscard]] constexpr bool holds_invariant() const noexcept
165 {
166 return _v.w() >= 0.0 && _v.w() <= 1.0;
167 }
168
169 [[nodiscard]] constexpr friend bool operator==(color const& lhs, color const& rhs) noexcept
170 {
171 return equal(lhs._v, rhs._v);
172 }
173
174 [[nodiscard]] constexpr friend color operator*(color const& lhs, color const& rhs) noexcept
175 {
176 return color{lhs._v * rhs._v};
177 }
178
188 [[nodiscard]] constexpr friend color operator*(matrix3 const& lhs, color const& rhs) noexcept
189 {
190 hi_axiom(rhs.holds_invariant());
191
192 auto const rhs_ = static_cast<f32x4>(rhs);
193
194 auto r = color{get<0>(lhs) * rhs_.xxxx() + get<1>(lhs) * rhs_.yyyy() + get<2>(lhs) * rhs_.zzzz() + get<3>(lhs)};
195
196 r.a() = rhs.a();
197 return r;
198 }
199
200 friend std::ostream& operator<<(std::ostream& lhs, color const& rhs)
201 {
202 return lhs << std::format("rgb({} {} {} {})", rhs.r(), rhs.g(), rhs.b(), rhs.a());
203 }
204
205private:
206 f16x4 _v = {};
207};
208
209namespace detail {
210
211class named_color_base {
212public:
213 named_color_base(std::string name, hi::color color) noexcept : _color(color)
214 {
215 auto const lock = std::scoped_lock(_map_mutex);
216 _map[name] = this;
217 }
218
219 named_color_base(named_color_base const&) = delete;
220 named_color_base(named_color_base&&) = delete;
221 named_color_base& operator=(named_color_base const&) = delete;
222 named_color_base& operator=(named_color_base&&) = delete;
223
224 hi::color const& operator*() const noexcept
225 {
226 return _color;
227 }
228
229 hi::color& operator*() noexcept
230 {
231 return _color;
232 }
233
234 operator hi::color() const noexcept
235 {
236 return _color;
237 }
238
239 [[nodiscard]] static std::vector<std::string> list() noexcept
240 {
241 auto r = std::vector<std::string>{};
242
243 auto const lock = std::scoped_lock(_map_mutex);
244 for (auto& item : _map) {
245 r.push_back(item.first);
246 }
247
248 return r;
249 }
250
251 [[nodiscard]] static named_color_base* find(std::string const& name) noexcept
252 {
253 auto const lock = std::scoped_lock(_map_mutex);
254 auto const it = _map.find(name);
255 if (it != _map.end()) {
256 return it->second;
257 } else {
258 return nullptr;
259 }
260 }
261
262private:
263 // The map is protected with a mutex because global variable initialization
264 // may be deferred and run on a different threads. However we can not
265 // use the deadlock detector as it will use a thread_local variable.
266 // The initialization order of static global variables and thread_local
267 // variables are undetermined.
269 inline static std::mutex _map_mutex;
270
271protected:
272 color _color;
273};
274
275template<fixed_string Tag>
276class named_color_type : public named_color_base {
277public:
278 named_color_type() noexcept : named_color_base(Tag, hi::color{}) {}
279 named_color_type(hi::color color) noexcept : named_color_base(Tag, color) {}
280
281 named_color_type& operator=(hi::color color) noexcept
282 {
283 _color = color;
284 return *this;
285 }
286};
287
288} // namespace detail
289
290template<fixed_string Tag>
291inline auto named_color = detail::named_color_type<Tag>{};
292
293[[nodiscard]] inline std::vector<std::string> color::list() noexcept
294{
295 return detail::named_color_base::list();
296}
297
298[[nodiscard]] inline color* color::find(std::string const& name) noexcept
299{
300 if (auto named_color_ptr = detail::named_color_base::find(name)) {
301 return std::addressof(**named_color_ptr);
302 } else {
303 return nullptr;
304 }
305}
306
307// clang-format off
308
309template<> inline auto named_color<"black"> = detail::named_color_type<"black">{color{0, 0, 0}};
310template<> inline auto named_color<"silver"> = detail::named_color_type<"silver">{color{192, 192, 192}};
311template<> inline auto named_color<"gray"> = detail::named_color_type<"gray">{color{128, 128, 128}};
312template<> inline auto named_color<"white"> = detail::named_color_type<"white">{color{255, 255, 255}};
313template<> inline auto named_color<"maroon"> = detail::named_color_type<"maroon">{color{128, 0, 0}};
314template<> inline auto named_color<"red"> = detail::named_color_type<"red">{color{255, 0, 0}};
315template<> inline auto named_color<"purple"> = detail::named_color_type<"purple">{color{128, 0, 128}};
316template<> inline auto named_color<"fuchsia"> = detail::named_color_type<"fuchsia">{color{255, 0, 255}};
317template<> inline auto named_color<"green"> = detail::named_color_type<"green">{color{0, 128, 0}};
318template<> inline auto named_color<"lime"> = detail::named_color_type<"lime">{color{0, 255, 0}};
319template<> inline auto named_color<"olive"> = detail::named_color_type<"olive">{color{128, 128, 0}};
320template<> inline auto named_color<"yellow"> = detail::named_color_type<"yellow">{color{255, 255, 0}};
321template<> inline auto named_color<"navy"> = detail::named_color_type<"navy">{color{0, 0, 128}};
322template<> inline auto named_color<"blue"> = detail::named_color_type<"blue">{color{0, 0, 255}};
323template<> inline auto named_color<"teal"> = detail::named_color_type<"teal">{color{0, 128, 128}};
324template<> inline auto named_color<"aqua"> = detail::named_color_type<"aqua">{color{0, 255, 255}};
325template<> inline auto named_color<"indigo"> = detail::named_color_type<"indigo">{color{75, 0, 130}};
326template<> inline auto named_color<"orange"> = detail::named_color_type<"orange">{color{255, 165, 0}};
327template<> inline auto named_color<"pink"> = detail::named_color_type<"pink">{color{255, 192, 203}};
328template<> inline auto named_color<"gray0"> = detail::named_color_type<"gray0">{color{0, 0, 0}};
329template<> inline auto named_color<"gray1"> = detail::named_color_type<"gray1">{color{26, 26, 26}};
330template<> inline auto named_color<"gray2"> = detail::named_color_type<"gray2">{color{51, 51, 51}};
331template<> inline auto named_color<"gray3"> = detail::named_color_type<"gray3">{color{77, 77, 77}};
332template<> inline auto named_color<"gray4"> = detail::named_color_type<"gray4">{color{102, 102, 102}};
333template<> inline auto named_color<"gray5"> = detail::named_color_type<"gray5">{color{127, 127, 127}};
334template<> inline auto named_color<"gray6"> = detail::named_color_type<"gray6">{color{153, 153, 153}};
335template<> inline auto named_color<"gray7"> = detail::named_color_type<"gray7">{color{179, 179, 179}};
336template<> inline auto named_color<"gray8"> = detail::named_color_type<"gray8">{color{204, 204, 204}};
337template<> inline auto named_color<"gray9"> = detail::named_color_type<"gray9">{color{229, 229, 229}};
338template<> inline auto named_color<"gray10"> = detail::named_color_type<"gray10">{color{255, 255, 255}};
339template<> inline auto named_color<"transparent"> = detail::named_color_type<"transparent">{color{0, 0, 0, 0}};
340
341[[nodiscard]] inline color color::black() noexcept { return named_color<"black">; }
342[[nodiscard]] inline color color::silver() noexcept { return named_color<"silver">; }
343[[nodiscard]] inline color color::gray() noexcept { return named_color<"gray5">; }
344[[nodiscard]] inline color color::white() noexcept { return named_color<"white">; }
345[[nodiscard]] inline color color::maroon() noexcept { return named_color<"maroon">; }
346[[nodiscard]] inline color color::red() noexcept { return named_color<"red">; }
347[[nodiscard]] inline color color::purple() noexcept { return named_color<"purple">; }
348[[nodiscard]] inline color color::fuchsia() noexcept { return named_color<"fuchsia">; }
349[[nodiscard]] inline color color::green() noexcept { return named_color<"green">; }
350[[nodiscard]] inline color color::lime() noexcept { return named_color<"lime">; }
351[[nodiscard]] inline color color::olive() noexcept { return named_color<"olive">; }
352[[nodiscard]] inline color color::yellow() noexcept { return named_color<"yellow">; }
353[[nodiscard]] inline color color::navy() noexcept { return named_color<"navy">; }
354[[nodiscard]] inline color color::blue() noexcept { return named_color<"blue">; }
355[[nodiscard]] inline color color::teal() noexcept { return named_color<"teal">; }
356[[nodiscard]] inline color color::aqua() noexcept { return named_color<"aqua">; }
357[[nodiscard]] inline color color::indigo() noexcept { return named_color<"indigo">; }
358[[nodiscard]] inline color color::orange() noexcept { return named_color<"orange">; }
359[[nodiscard]] inline color color::pink() noexcept { return named_color<"pink">; }
360[[nodiscard]] inline color color::gray0() noexcept { return named_color<"gray0">; }
361[[nodiscard]] inline color color::gray1() noexcept { return named_color<"gray1">; }
362[[nodiscard]] inline color color::gray2() noexcept { return named_color<"gray2">; }
363[[nodiscard]] inline color color::gray3() noexcept { return named_color<"gray3">; }
364[[nodiscard]] inline color color::gray4() noexcept { return named_color<"gray4">; }
365[[nodiscard]] inline color color::gray5() noexcept { return named_color<"gray5">; }
366[[nodiscard]] inline color color::gray6() noexcept { return named_color<"gray6">; }
367[[nodiscard]] inline color color::gray7() noexcept { return named_color<"gray7">; }
368[[nodiscard]] inline color color::gray8() noexcept { return named_color<"gray8">; }
369[[nodiscard]] inline color color::gray9() noexcept { return named_color<"gray9">; }
370[[nodiscard]] inline color color::gray10() noexcept { return named_color<"gray10">; }
371[[nodiscard]] inline color color::transparent() noexcept { return named_color<"transparent">; }
372// clang-format on
373
374} // namespace v1
375} // namespace hi::v1
376
377template<>
378struct std::hash<hi::color> {
379 [[nodiscard]] size_t operator()(hi::color const& rhs) const noexcept
380 {
381 return rhs.hash();
382 }
383};
384
385// XXX #617 MSVC bug does not handle partial specialization in modules.
386hi_export template<>
387struct std::formatter<hi::color, char> : std::formatter<std::string, char> {
388 auto format(hi::color const& t, auto& fc) const
389 {
390 return std::formatter<std::string, char>::format(std::format("rgba({}, {}, {}, {})", t.r(), t.g(), t.b(), t.a()), fc);
391 }
392};
@ other
The gui_event does not have associated data.
Definition gui_event_variant.hpp:24
The HikoGUI namespace.
Definition array_generic.hpp:21
The HikoGUI API version 1.
Definition array_generic.hpp:22
@ color
A color value was modified.
Definition style_modify_mask.hpp:27
constexpr matrix2 operator*(matrix2 const &lhs, matrix2 const &rhs) noexcept
Matrix/Matrix multiplication.
Definition transform.hpp:69
Definition half.hpp:27
This is a RGBA floating point color.
Definition color_intf.hpp:49
static color * find(std::string const &name) noexcept
Find a color by name.
Definition color_intf.hpp:298
static std::vector< std::string > list() noexcept
List color names.
Definition color_intf.hpp:293
constexpr friend color operator*(matrix3 const &lhs, color const &rhs) noexcept
Transform a color by a color matrix.
Definition color_intf.hpp:188
Definition color_intf.hpp:276
A 2D or 3D homogenius matrix for transforming homogenious vectors and points.
Definition matrix3.hpp:36
T addressof(T... args)
T operator()(T... args)