Gamedev Framework (gf) 1.2.0
A C++17 framework for 2D games
Color.h
1/*
2 * Gamedev Framework (gf)
3 * Copyright (C) 2016-2022 Julien Bernard
4 *
5 * This software is provided 'as-is', without any express or implied
6 * warranty. In no event will the authors be held liable for any damages
7 * arising from the use of this software.
8 *
9 * Permission is granted to anyone to use this software for any purpose,
10 * including commercial applications, and to alter it and redistribute it
11 * freely, subject to the following restrictions:
12 *
13 * 1. The origin of this software must not be misrepresented; you must not
14 * claim that you wrote the original software. If you use this software
15 * in a product, an acknowledgment in the product documentation would be
16 * appreciated but is not required.
17 * 2. Altered source versions must be plainly marked as such, and must not be
18 * misrepresented as being the original software.
19 * 3. This notice may not be removed or altered from any source distribution.
20 */
21#ifndef GF_COLOR_H
22#define GF_COLOR_H
23
24#include <cassert>
25#include <cmath>
26#include <algorithm>
27#include <tuple>
28#include <type_traits>
29
30#include "Math.h"
31#include "Vector.h"
32
33namespace gf {
34#ifndef DOXYGEN_SHOULD_SKIP_THIS
35inline namespace v1 {
36#endif
37
55 template<typename T>
56 struct ColorBase {
57 static_assert(std::is_floating_point<T>::value, "T must be a floating point type.");
58
59 private:
60
64 struct HSV {
65 T h;
66 T s;
67 T v;
68 T a;
69 };
70
74 static constexpr HSV convertRgbToHsv(Color4<T> color) {
75 T min = 0;
76 T max = 1;
77 std::tie(min, max) = std::minmax({ color.r, color.g, color.b });
78
79 T hue = 0;
80
81 if ((max - min) > std::numeric_limits<T>::epsilon()) {
82 if (max == color.r) {
83 hue = std::fmod(T(60) * (color.g - color.b) / (max - min) + T(360), T(360));
84 } else if (max == color.g) {
85 hue = T(60) * (color.b - color.r) / (max - min) + T(120);
86 } else if (max == color.b) {
87 hue = T(60) * (color.r - color.g) / (max - min) + T(240);
88 } else {
89 assert(false);
90 }
91 }
92
93 T sat = (max < std::numeric_limits<T>::epsilon()) ? T(0) : (T(1) - min / max);
94 T val = max;
95
96 return { hue, sat, val, color.a };
97 }
98
102 static constexpr Color4<T> convertHsvToRgb(HSV hsv) {
103 T hue = hsv.h / T(60);
104 T sat = hsv.s;
105 T val = hsv.v;
106
107 int i = static_cast<int>(hue) % 6;
108 assert(0 <= i && i < 6);
109
110 T f = hue - static_cast<T>(i);
111
112 T x = val * (T(1) - sat);
113 T y = val * (T(1) - (f * sat));
114 T z = val * (T(1) - ((T(1) - f) * sat));
115
116 Color4<T> color = Zero;
117 color.a = hsv.a;
118
119 switch (i) {
120 case 0:
121 color.r = val;
122 color.g = z;
123 color.b = x;
124 break;
125 case 1:
126 color.r = y;
127 color.g = val;
128 color.b = x;
129 break;
130 case 2:
131 color.r = x;
132 color.g = val;
133 color.b = z;
134 break;
135 case 3:
136 color.r = x;
137 color.g = y;
138 color.b = val;
139 break;
140 case 4:
141 color.r = z;
142 color.g = x;
143 color.b = val;
144 break;
145 case 5:
146 color.r = val;
147 color.g = x;
148 color.b = y;
149 break;
150 default:
151 assert(false);
152 break;
153 }
154
155 return color;
156 }
157
158 public:
159
163 static constexpr Color4<T> Black{T(0), T(0), T(0), T(1)};
164
168 static constexpr Color4<T> White{T(1), T(1), T(1), T(1)};
169
173 static constexpr Color4<T> Red{T(1), T(0), T(0), T(1)};
174
178 static constexpr Color4<T> Green{T(0), T(1), T(0), T(1)};
179
183 static constexpr Color4<T> Blue{T(0), T(0), T(1), T(1)};
184
188 static constexpr Color4<T> Cyan{T(0), T(1), T(1), T(1)};
189
193 static constexpr Color4<T> Magenta{T(1), T(0), T(1), T(1)};
194
198 static constexpr Color4<T> Yellow{T(1), T(1), T(0), T(1)};
199
203 static constexpr Color4<T> Transparent{T(0), T(0), T(0), T(0)};
204
210 static constexpr Color4<T> Opaque(T value = T(0.5)) {
211 return { T(1), T(1), T(1), value };
212 }
213
219 static constexpr Color4<T> Gray(T value = T(0.5)) {
220 return { value, value, value, T(1) };
221 }
222
226 static constexpr Color4<T> Orange{T(1), T(0.5), T(0), T(1)};
227
231 static constexpr Color4<T> Rose{T(1), T(0), T(0.5), T(1)};
232
236 static constexpr Color4<T> Chartreuse{T(0.5), T(1), T(0), T(1)};
237
241 static constexpr Color4<T> Spring{T(0), T(1), T(0.5), T(1)};
242
246 static constexpr Color4<T> Violet{T(0.5), T(0), T(1), T(1)};
247
251 static constexpr Color4<T> Azure{T(0), T(0.5), T(1), T(1)};
252
253
264 static constexpr Color4<T> lighter(Color4<T> color, T percent = T(0.5)) {
265 assert(0.0f <= percent && percent <= 1.0f);
266 HSV hsv = convertRgbToHsv(color);
267 hsv.v += hsv.v * percent;
268
269 if (hsv.v > 1) {
270 hsv.s -= (hsv.v - 1);
271
272 if (hsv.s < 0) {
273 hsv.s = 0;
274 }
275
276 hsv.v = 1;
277 }
278
279 return convertHsvToRgb(hsv);
280 }
281
292 static constexpr Color4<T> darker(Color4<T> color, T percent = T(0.5)) {
293 assert(0.0f <= percent && percent <= 1.0f);
294 HSV hsv = convertRgbToHsv(color);
295 hsv.v -= hsv.v * percent;
296 return convertHsvToRgb(hsv);
297 }
298
307 static constexpr Color4<T> fromRgb(T r, T g, T b) {
308 return Color4<T>(r, g, b, T(1));
309 }
310
320 static constexpr Color4<T> fromRgba32(uint8_t r, uint8_t g, uint8_t b, uint8_t a = 255) {
321 return { r / T(255), g / T(255), b / T(255), a / T(255) };
322 }
323
330 static constexpr Color4<T> fromRgba32(uint32_t color) {
331 return fromRgba32(static_cast<uint8_t>(color >> 24), static_cast<uint8_t>(color >> 16), static_cast<uint8_t>(color >> 8), static_cast<uint8_t>(color));
332 }
333
340 static constexpr Color4<T> fromRgba32(Color4u color) {
341 return fromRgba32(color.r, color.g, color.b, color.a);
342 }
343
350 static constexpr Color4u toRgba32(Color4<T> color) {
351 return {
352 static_cast<uint8_t>(color.r * 255),
353 static_cast<uint8_t>(color.g * 255),
354 static_cast<uint8_t>(color.b * 255),
355 static_cast<uint8_t>(color.a * 255)
356 };
357 }
358 };
359
360#ifndef DOXYGEN_SHOULD_SKIP_THIS
361 template<typename T>
362 constexpr Color4<T> ColorBase<T>::Black;
363 template<typename T>
364 constexpr Color4<T> ColorBase<T>::White;
365
366 template<typename T>
367 constexpr Color4<T> ColorBase<T>::Red;
368 template<typename T>
369 constexpr Color4<T> ColorBase<T>::Green;
370 template<typename T>
371 constexpr Color4<T> ColorBase<T>::Blue;
372
373 template<typename T>
374 constexpr Color4<T> ColorBase<T>::Cyan;
375 template<typename T>
376 constexpr Color4<T> ColorBase<T>::Magenta;
377 template<typename T>
378 constexpr Color4<T> ColorBase<T>::Yellow;
379
380 template<typename T>
381 constexpr Color4<T> ColorBase<T>::Transparent;
382
383 template<typename T>
384 constexpr Color4<T> ColorBase<T>::Orange;
385 template<typename T>
386 constexpr Color4<T> ColorBase<T>::Rose;
387 template<typename T>
388 constexpr Color4<T> ColorBase<T>::Chartreuse;
389 template<typename T>
390 constexpr Color4<T> ColorBase<T>::Spring;
391 template<typename T>
392 constexpr Color4<T> ColorBase<T>::Violet;
393 template<typename T>
394 constexpr Color4<T> ColorBase<T>::Azure;
395#endif
396
402
408
415 using Color = ColorF;
416
417#ifndef DOXYGEN_SHOULD_SKIP_THIS
418}
419#endif
420}
421
422#endif // GF_COLOR_H
ColorBase< float > ColorF
Instantiation of ColoBase for float
Definition: Color.h:401
@ Transparent
The cell is transparent.
constexpr ZeroType Zero
Constant to represent "zero".
Definition: Types.h:93
The namespace for gf classes.
Predefined colors and utilities.
Definition: Color.h:56
static constexpr Color4< T > Violet
Violet predefined color.
Definition: Color.h:246
static constexpr Color4< T > Yellow
Yellow predefined color.
Definition: Color.h:198
static constexpr Color4< T > Transparent
Transparent (black) predefined color.
Definition: Color.h:203
static constexpr Color4< T > fromRgb(T r, T g, T b)
Get an opaque color from 3 RGB floats in .
Definition: Color.h:307
static constexpr Color4< T > Green
Green predefined color.
Definition: Color.h:178
static constexpr Color4< T > White
White predefined color.
Definition: Color.h:168
static constexpr Color4< T > fromRgba32(uint8_t r, uint8_t g, uint8_t b, uint8_t a=255)
Get a color from 4 8-bit channels.
Definition: Color.h:320
static constexpr Color4< T > Azure
Azure predefined color.
Definition: Color.h:251
static constexpr Color4< T > Gray(T value=T(0.5))
Gray predefined color.
Definition: Color.h:219
static constexpr Color4< T > Orange
Orange predefined color.
Definition: Color.h:226
static constexpr Color4< T > fromRgba32(Color4u color)
Get a color from a 32-bit color.
Definition: Color.h:340
static constexpr Color4< T > fromRgba32(uint32_t color)
Get a color from 32-bit value.
Definition: Color.h:330
static constexpr Color4< T > lighter(Color4< T > color, T percent=T(0.5))
Compute a lighter color.
Definition: Color.h:264
static constexpr Color4< T > Opaque(T value=T(0.5))
Opaque predefined color.
Definition: Color.h:210
static constexpr Color4u toRgba32(Color4< T > color)
Convert a color to a 32-bit color.
Definition: Color.h:350
static constexpr Color4< T > darker(Color4< T > color, T percent=T(0.5))
Compute a darker color.
Definition: Color.h:292
static constexpr Color4< T > Cyan
Cyan predefined color.
Definition: Color.h:188
static constexpr Color4< T > Red
Red predefined color.
Definition: Color.h:173
static constexpr Color4< T > Black
Black predefined color.
Definition: Color.h:163
static constexpr Color4< T > Blue
Blue predefined color.
Definition: Color.h:183
static constexpr Color4< T > Magenta
Magenta predefined color.
Definition: Color.h:193
static constexpr Color4< T > Chartreuse
Chartreuse predefined color.
Definition: Color.h:236
static constexpr Color4< T > Spring
Spring (green) predefined color.
Definition: Color.h:241
static constexpr Color4< T > Rose
Rose predefined color.
Definition: Color.h:231
A 4D vector.
Definition: Vector.h:852