Gamedev Framework (gf)  0.19.0
A C++17 framework for 2D games
Color.h
1 /*
2  * Gamedev Framework (gf)
3  * Copyright (C) 2016-2021 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 
33 namespace gf {
34 #ifndef DOXYGEN_SHOULD_SKIP_THIS
35 inline 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>
377  template<typename T>
379 
380  template<typename T>
382 
383  template<typename T>
385  template<typename T>
386  constexpr Color4<T> ColorBase<T>::Rose;
387  template<typename T>
389  template<typename T>
391  template<typename T>
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
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 > Gray(T value=T(0.5))
Gray predefined color.
Definition: Color.h:219
T a
Fourth coordinate in the (r,g,b,a) representation.
Definition: Vector.h:1107
ColorBase< float > ColorF
Instantiation of ColoBase for float
Definition: Color.h:401
static constexpr Color4< T > fromRgba32(uint32_t color)
Get a color from 32-bit value.
Definition: Color.h:330
The namespace for gf classes.
Definition: Action.h:35
T g
Second coordinate in the (r,g,b,a) representation.
Definition: Vector.h:1091
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
A 4D vector.
Definition: Vector.h:852
static constexpr Color4u toRgba32(Color4< T > color)
Convert a color to a 32-bit color.
Definition: Color.h:350
Predefined colors and utilities.
Definition: Color.h:56
T b
Third coordinate in the (r,g,b,a) representation.
Definition: Vector.h:1099
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 > Opaque(T value=T(0.5))
Opaque predefined color.
Definition: Color.h:210
static constexpr Color4< T > darker(Color4< T > color, T percent=T(0.5))
Compute a darker color.
Definition: Color.h:292
T r
First coordinate in the (r,g,b,a) representation.
Definition: Vector.h:1083
The cell is transparent.
static constexpr Color4< T > fromRgba32(Color4u color)
Get a color from a 32-bit color.
Definition: Color.h:340