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
76 [[nodiscard]] static inline color *find(std::string const& name) noexcept;
77
78 [[nodiscard]] static inline color black() noexcept;
79 [[nodiscard]] static inline color silver() noexcept;
80 [[nodiscard]] static inline color gray() noexcept;
81 [[nodiscard]] static inline color white() noexcept;
82 [[nodiscard]] static inline color maroon() noexcept;
83 [[nodiscard]] static inline color red() noexcept;
84 [[nodiscard]] static inline color purple() noexcept;
85 [[nodiscard]] static inline color fuchsia() noexcept;
86 [[nodiscard]] static inline color green() noexcept;
87 [[nodiscard]] static inline color lime() noexcept;
88 [[nodiscard]] static inline color olive() noexcept;
89 [[nodiscard]] static inline color yellow() noexcept;
90 [[nodiscard]] static inline color navy() noexcept;
91 [[nodiscard]] static inline color blue() noexcept;
92 [[nodiscard]] static inline color teal() noexcept;
93 [[nodiscard]] static inline color aqua() noexcept;
94 [[nodiscard]] static inline color indigo() noexcept;
95 [[nodiscard]] static inline color orange() noexcept;
96 [[nodiscard]] static inline color pink() noexcept;
97 [[nodiscard]] static inline color background() noexcept;
98 [[nodiscard]] static inline color gray1() noexcept;
99 [[nodiscard]] static inline color gray2() noexcept;
100 [[nodiscard]] static inline color gray3() noexcept;
101 [[nodiscard]] static inline color gray4() noexcept;
102 [[nodiscard]] static inline color gray5() noexcept;
103 [[nodiscard]] static inline color gray6() noexcept;
104 [[nodiscard]] static inline color gray7() noexcept;
105 [[nodiscard]] static inline color gray8() noexcept;
106 [[nodiscard]] static inline color gray9() noexcept;
107 [[nodiscard]] static inline color foreground() noexcept;
108 [[nodiscard]] static inline color transparent() noexcept;
109
110 [[nodiscard]] size_t hash() const noexcept
111 {
112 return std::hash<uint64_t>{}(std::bit_cast<uint64_t>(_v));
113 }
114
115 [[nodiscard]] constexpr float16& r() noexcept
116 {
117 return _v.x();
118 }
119
120 [[nodiscard]] constexpr float16& g() noexcept
121 {
122 return _v.y();
123 }
124
125 [[nodiscard]] constexpr float16& b() noexcept
126 {
127 return _v.z();
128 }
129
130 [[nodiscard]] constexpr float16& a() noexcept
131 {
132 return _v.w();
133 }
134
135 [[nodiscard]] constexpr float16 r() const noexcept
136 {
137 return _v.x();
138 }
139
140 [[nodiscard]] constexpr float16 g() const noexcept
141 {
142 return _v.y();
143 }
144
145 [[nodiscard]] constexpr float16 b() const noexcept
146 {
147 return _v.z();
148 }
149
150 [[nodiscard]] constexpr float16 a() const noexcept
151 {
152 return _v.w();
153 }
154
155 [[nodiscard]] constexpr bool holds_invariant() const noexcept
156 {
157 return _v.w() >= 0.0 && _v.w() <= 1.0;
158 }
159
160 [[nodiscard]] constexpr friend bool operator==(color const& lhs, color const& rhs) noexcept
161 {
162 return equal(lhs._v, rhs._v);
163 }
164
165 [[nodiscard]] constexpr friend color operator*(color const& lhs, color const& rhs) noexcept
166 {
167 return color{lhs._v * rhs._v};
168 }
169
170 [[nodiscard]] constexpr friend color composit(color const& lhs, color const& rhs) noexcept
171 {
172 return color{composit(lhs._v, rhs._v)};
173 }
174
175 [[nodiscard]] constexpr friend color desaturate(color const& rhs) noexcept
176 {
177 hilet rhs_ = f32x4{rhs};
178
179 hilet Y = 0.2126f * rhs_.r() + 0.7152f * rhs_.g() + 0.0722f * rhs_.b();
180
181 return color{Y, Y, Y, rhs_.a()};
182 }
183
193 [[nodiscard]] constexpr friend color operator*(matrix3 const& lhs, color const& rhs) noexcept
194 {
195 hi_axiom(rhs.holds_invariant());
196 auto r = color{
197 get<0>(lhs) * static_cast<f32x4>(rhs).xxxx() + get<1>(lhs) * static_cast<f32x4>(rhs).yyyy() +
198 get<2>(lhs) * static_cast<f32x4>(rhs).zzzz() + get<3>(lhs)};
199
200 r.a() = rhs.a();
201 return r;
202 }
203
204 [[nodiscard]] constexpr friend color operator*(identity3 const& lhs, color const& rhs) noexcept
205 {
206 return rhs;
207 }
208
209 friend std::ostream &operator<<(std::ostream &lhs, color const &rhs)
210 {
211 return lhs << std::format("rgb({} {} {} {})", rhs.r(), rhs.g(), rhs.b(), rhs.a());
212 }
213
214private:
215 f16x4 _v = {};
216};
217
218namespace detail {
219
221public:
222 named_color_base(std::string name, hi::color color) noexcept : _color(color)
223 {
224 hilet lock = std::scoped_lock(_map_mutex);
225 _map[name] = this;
226 }
227
228 named_color_base(named_color_base const&) = delete;
230 named_color_base& operator=(named_color_base const&) = delete;
231 named_color_base& operator=(named_color_base&&) = delete;
232
233 hi::color const& operator*() const noexcept
234 {
235 return _color;
236 }
237
238 hi::color& operator*() noexcept
239 {
240 return _color;
241 }
242
243 operator hi::color() const noexcept
244 {
245 return _color;
246 }
247
248 inline static named_color_base *find(std::string const& name) noexcept
249 {
250 hilet lock = std::scoped_lock(_map_mutex);
251 hilet it = _map.find(name);
252 if (it != _map.end()) {
253 return it->second;
254 } else {
255 return nullptr;
256 }
257 }
258
259private:
261 inline static unfair_mutex _map_mutex;
262
263protected:
264 color _color;
265};
266
267template<fixed_string Tag>
269public:
270 named_color_type() noexcept : named_color_base(Tag, hi::color{}) {}
272
273 named_color_type& operator=(hi::color color) noexcept
274 {
275 _color = color;
276 }
277};
278
279} // namespace detail
280
281template<fixed_string Tag>
282inline auto named_color = detail::named_color_type<Tag>{};
283
284[[nodiscard]] inline color *color::find(std::string const& name) noexcept
285{
286 if (auto named_color_ptr = detail::named_color_base::find(name)) {
287 return std::addressof(**named_color_ptr);
288 } else {
289 return nullptr;
290 }
291}
292
293// clang-format off
294
295template<> inline auto named_color<"black"> = detail::named_color_type<"black">{color{0, 0, 0}};
296template<> inline auto named_color<"silver"> = detail::named_color_type<"silver">{color{192, 192, 192}};
297template<> inline auto named_color<"gray"> = detail::named_color_type<"gray">{color{128, 128, 128}};
298template<> inline auto named_color<"white"> = detail::named_color_type<"white">{color{255, 255, 255}};
299template<> inline auto named_color<"maroon"> = detail::named_color_type<"maroon">{color{128, 0, 0}};
300template<> inline auto named_color<"red"> = detail::named_color_type<"red">{color{255, 0, 0}};
301template<> inline auto named_color<"purple"> = detail::named_color_type<"purple">{color{128, 0, 128}};
302template<> inline auto named_color<"fuchsia"> = detail::named_color_type<"fuchsia">{color{255, 0, 255}};
303template<> inline auto named_color<"green"> = detail::named_color_type<"green">{color{0, 128, 0}};
304template<> inline auto named_color<"lime"> = detail::named_color_type<"lime">{color{0, 255, 0}};
305template<> inline auto named_color<"olive"> = detail::named_color_type<"olive">{color{128, 128, 0}};
306template<> inline auto named_color<"yellow"> = detail::named_color_type<"yellow">{color{255, 255, 0}};
307template<> inline auto named_color<"navy"> = detail::named_color_type<"navy">{color{0, 0, 128}};
308template<> inline auto named_color<"blue"> = detail::named_color_type<"blue">{color{0, 0, 255}};
309template<> inline auto named_color<"teal"> = detail::named_color_type<"teal">{color{0, 128, 128}};
310template<> inline auto named_color<"aqua"> = detail::named_color_type<"aqua">{color{0, 255, 255}};
311template<> inline auto named_color<"indigo"> = detail::named_color_type<"indigo">{color{75, 0, 130}};
312template<> inline auto named_color<"orange"> = detail::named_color_type<"orange">{color{255, 165, 0}};
313template<> inline auto named_color<"pink"> = detail::named_color_type<"pink">{color{255, 192, 203}};
314template<> inline auto named_color<"background"> = detail::named_color_type<"background">{color{0, 0, 0}};
315template<> inline auto named_color<"gray1"> = detail::named_color_type<"gray1">{color{26, 26, 26}};
316template<> inline auto named_color<"gray2"> = detail::named_color_type<"gray2">{color{51, 51, 51}};
317template<> inline auto named_color<"gray3"> = detail::named_color_type<"gray3">{color{77, 77, 77}};
318template<> inline auto named_color<"gray4"> = detail::named_color_type<"gray4">{color{102, 102, 102}};
319template<> inline auto named_color<"gray5"> = detail::named_color_type<"gray5">{color{127, 127, 127}};
320template<> inline auto named_color<"gray6"> = detail::named_color_type<"gray6">{color{153, 153, 153}};
321template<> inline auto named_color<"gray7"> = detail::named_color_type<"gray7">{color{179, 179, 179}};
322template<> inline auto named_color<"gray8"> = detail::named_color_type<"gray8">{color{204, 204, 204}};
323template<> inline auto named_color<"gray9"> = detail::named_color_type<"gray9">{color{229, 229, 229}};
324template<> inline auto named_color<"foreground"> = detail::named_color_type<"foreground">{color{255, 255, 255}};
325template<> inline auto named_color<"transparent"> = detail::named_color_type<"transparent">{color{0, 0, 0, 0}};
326
327[[nodiscard]] inline color color::black() noexcept { return named_color<"black">; }
328[[nodiscard]] inline color color::silver() noexcept { return named_color<"silver">; }
329[[nodiscard]] inline color color::gray() noexcept { return named_color<"gray">; }
330[[nodiscard]] inline color color::white() noexcept { return named_color<"white">; }
331[[nodiscard]] inline color color::maroon() noexcept { return named_color<"maroon">; }
332[[nodiscard]] inline color color::red() noexcept { return named_color<"red">; }
333[[nodiscard]] inline color color::purple() noexcept { return named_color<"purple">; }
334[[nodiscard]] inline color color::fuchsia() noexcept { return named_color<"fuchsia">; }
335[[nodiscard]] inline color color::green() noexcept { return named_color<"green">; }
336[[nodiscard]] inline color color::lime() noexcept { return named_color<"lime">; }
337[[nodiscard]] inline color color::olive() noexcept { return named_color<"olive">; }
338[[nodiscard]] inline color color::yellow() noexcept { return named_color<"yellow">; }
339[[nodiscard]] inline color color::navy() noexcept { return named_color<"navy">; }
340[[nodiscard]] inline color color::blue() noexcept { return named_color<"blue">; }
341[[nodiscard]] inline color color::teal() noexcept { return named_color<"teal">; }
342[[nodiscard]] inline color color::aqua() noexcept { return named_color<"aqua">; }
343[[nodiscard]] inline color color::indigo() noexcept { return named_color<"indigo">; }
344[[nodiscard]] inline color color::orange() noexcept { return named_color<"orange">; }
345[[nodiscard]] inline color color::pink() noexcept { return named_color<"pink">; }
346[[nodiscard]] inline color color::background() noexcept { return named_color<"background">; }
347[[nodiscard]] inline color color::gray1() noexcept { return named_color<"gray1">; }
348[[nodiscard]] inline color color::gray2() noexcept { return named_color<"gray2">; }
349[[nodiscard]] inline color color::gray3() noexcept { return named_color<"gray3">; }
350[[nodiscard]] inline color color::gray4() noexcept { return named_color<"gray4">; }
351[[nodiscard]] inline color color::gray5() noexcept { return named_color<"gray5">; }
352[[nodiscard]] inline color color::gray6() noexcept { return named_color<"gray6">; }
353[[nodiscard]] inline color color::gray7() noexcept { return named_color<"gray7">; }
354[[nodiscard]] inline color color::gray8() noexcept { return named_color<"gray8">; }
355[[nodiscard]] inline color color::gray9() noexcept { return named_color<"gray9">; }
356[[nodiscard]] inline color color::foreground() noexcept { return named_color<"foreground">; }
357[[nodiscard]] inline color color::transparent() noexcept { return named_color<"transparent">; }
358// clang-format on
359
360}} // namespace hi::v1
361
362template<>
363struct std::hash<hi::color> {
364 [[nodiscard]] size_t operator()(hi::color const& rhs) const noexcept
365 {
366 return rhs.hash();
367 }
368};
369
370
#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:284
constexpr friend color operator*(matrix3 const &lhs, color const &rhs) noexcept
Transform a color by a color matrix.
Definition color.hpp:193
Definition color.hpp:220
Definition color.hpp:268
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)