Gamedev Framework (gf)  0.17.0
A C++14 framework for 2D games
Color.h
1 /*
2  * Gamedev Framework (gf)
3  * Copyright (C) 2016-2019 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 "Portability.h"
32 #include "Vector.h"
33 
34 namespace gf {
35 #ifndef DOXYGEN_SHOULD_SKIP_THIS
36 inline namespace v1 {
37 #endif
38 
56  template<typename T>
57  struct ColorBase {
58  static_assert(std::is_floating_point<T>::value, "T must be a floating point type.");
59 
60  private:
61 
65  struct HSV {
66  T h;
67  T s;
68  T v;
69  T a;
70  };
71 
75  static constexpr HSV convertRgbToHsv(Color4<T> color) {
76  T min = 0;
77  T max = 1;
78  std::tie(min, max) = std::minmax({ color.r, color.g, color.b });
79 
80  T hue = 0;
81 
82  if ((max - min) > std::numeric_limits<T>::epsilon()) {
83  if (max == color.r) {
84  hue = std::fmod(60 * (color.g - color.b) / (max - min) + 360, 360);
85  } else if (max == color.g) {
86  hue = 60 * (color.b - color.r) / (max - min) + 120;
87  } else if (max == color.b) {
88  hue = 60 * (color.r - color.g) / (max - min) + 240;
89  } else {
90  assert(false);
91  }
92  }
93 
94  T sat = (max < std::numeric_limits<T>::epsilon()) ? 0 : (1 - min / max);
95  T val = max;
96 
97  return { hue, sat, val, color.a };
98  }
99 
103  static constexpr Color4<T> convertHsvToRgb(HSV hsv) {
104  T hue = hsv.h / 60;
105  T sat = hsv.s;
106  T val = hsv.v;
107 
108  int i = static_cast<int>(hue) % 6;
109  assert(0 <= i && i < 6);
110 
111  T f = hue - i;
112 
113  T x = val * (1 - sat);
114  T y = val * (1 - (f * sat));
115  T z = val * (1 - ((1 - f) * sat));
116 
117  Color4<T> color = Zero;
118  color.a = hsv.a;
119 
120  switch (i) {
121  case 0:
122  color.r = val;
123  color.g = z;
124  color.b = x;
125  break;
126  case 1:
127  color.r = y;
128  color.g = val;
129  color.b = x;
130  break;
131  case 2:
132  color.r = x;
133  color.g = val;
134  color.b = z;
135  break;
136  case 3:
137  color.r = x;
138  color.g = y;
139  color.b = val;
140  break;
141  case 4:
142  color.r = z;
143  color.g = x;
144  color.b = val;
145  break;
146  case 5:
147  color.r = val;
148  color.g = x;
149  color.b = y;
150  break;
151  default:
152  assert(false);
153  break;
154  }
155 
156  return color;
157  }
158 
159  public:
160 
164  static constexpr Color4<T> Black{T(0), T(0), T(0), T(1)};
165 
169  static constexpr Color4<T> White{T(1), T(1), T(1), T(1)};
170 
174  static constexpr Color4<T> Red{T(1), T(0), T(0), T(1)};
175 
179  static constexpr Color4<T> Green{T(0), T(1), T(0), T(1)};
180 
184  static constexpr Color4<T> Blue{T(0), T(0), T(1), T(1)};
185 
189  static constexpr Color4<T> Cyan{T(0), T(1), T(1), T(1)};
190 
194  static constexpr Color4<T> Magenta{T(1), T(0), T(1), T(1)};
195 
199  static constexpr Color4<T> Yellow{T(1), T(1), T(0), T(1)};
200 
204  static constexpr Color4<T> Transparent{T(0), T(0), T(0), T(0)};
205 
211  static constexpr Color4<T> Opaque(T value = T(0.5)) {
212  return { T(1), T(1), T(1), value };
213  }
214 
220  static constexpr Color4<T> Gray(T value = T(0.5)) {
221  return { value, value, value, T(1) };
222  }
223 
227  static constexpr Color4<T> Orange{T(1), T(0.5), T(0), T(1)};
228 
232  static constexpr Color4<T> Rose{T(1), T(0), T(0.5), T(1)};
233 
237  static constexpr Color4<T> Chartreuse{T(0.5), T(1), T(0), T(1)};
238 
242  static constexpr Color4<T> Spring{T(0), T(1), T(0.5), T(1)};
243 
247  static constexpr Color4<T> Violet{T(0.5), T(0), T(1), T(1)};
248 
252  static constexpr Color4<T> Azure{T(0), T(0.5), T(1), T(1)};
253 
254 
265  static constexpr Color4<T> lighter(Color4<T> color, T percent = T(0.5)) {
266  assert(0.0f <= percent && percent <= 1.0f);
267  HSV hsv = convertRgbToHsv(color);
268  hsv.v += hsv.v * percent;
269 
270  if (hsv.v > 1) {
271  hsv.s -= (hsv.v - 1);
272 
273  if (hsv.s < 0) {
274  hsv.s = 0;
275  }
276 
277  hsv.v = 1;
278  }
279 
280  return convertHsvToRgb(hsv);
281  }
282 
293  static constexpr Color4<T> darker(Color4<T> color, T percent = T(0.5)) {
294  assert(0.0f <= percent && percent <= 1.0f);
295  HSV hsv = convertRgbToHsv(color);
296  hsv.v -= hsv.v * percent;
297  return convertHsvToRgb(hsv);
298  }
299 
308  static constexpr Color4<T> fromRgb(T r, T g, T b) {
309  return Color4<T>(r, g, b, T(1));
310  }
311 
321  static constexpr Color4<T> fromRgba32(uint8_t r, uint8_t g, uint8_t b, uint8_t a = 255) {
322  return { r / T(255), g / T(255), b / T(255), a / T(255) };
323  }
324 
331  static constexpr Color4<T> fromRgba32(uint32_t color) {
332  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));
333  }
334 
341  static constexpr Color4<T> fromRgba32(Color4u color) {
342  return fromRgba32(color.r, color.g, color.b, color.a);
343  }
344 
351  static constexpr Color4u toRgba32(Color4<T> color) {
352  return {
353  static_cast<uint8_t>(color.r * 255),
354  static_cast<uint8_t>(color.g * 255),
355  static_cast<uint8_t>(color.b * 255),
356  static_cast<uint8_t>(color.a * 255)
357  };
358  }
359  };
360 
361 #ifndef DOXYGEN_SHOULD_SKIP_THIS
362  template<typename T>
363  constexpr Color4<T> ColorBase<T>::Black;
364  template<typename T>
365  constexpr Color4<T> ColorBase<T>::White;
366 
367  template<typename T>
368  constexpr Color4<T> ColorBase<T>::Red;
369  template<typename T>
370  constexpr Color4<T> ColorBase<T>::Green;
371  template<typename T>
372  constexpr Color4<T> ColorBase<T>::Blue;
373 
374  template<typename T>
375  constexpr Color4<T> ColorBase<T>::Cyan;
376  template<typename T>
378  template<typename T>
380 
381  template<typename T>
383 
384  template<typename T>
386  template<typename T>
387  constexpr Color4<T> ColorBase<T>::Rose;
388  template<typename T>
390  template<typename T>
392  template<typename T>
394  template<typename T>
395  constexpr Color4<T> ColorBase<T>::Azure;
396 #endif
397 
403 
409 
416  using Color = ColorF;
417 
418 #ifndef DOXYGEN_SHOULD_SKIP_THIS
419 }
420 #endif
421 }
422 
423 #endif // GF_COLOR_H
ColorBase< float > ColorF
Instantiation of ColoBase for float
Definition: Color.h:402
static constexpr Color4< T > lighter(Color4< T > color, T percent=T(0.5))
Compute a lighter color.
Definition: Color.h:265
static constexpr Color4< T > Gray(T value=T(0.5))
Gray predefined color.
Definition: Color.h:220
T a
Fourth coordinate in the (r,g,b,a) representation.
Definition: Vector.h:1107
A red and gray style.
static constexpr Color4< T > fromRgba32(uint32_t color)
Get a color from 32-bit value.
Definition: Color.h:331
The namespace for gf classes.
Definition: Action.h:35
A blue and light gray style.
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:321
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:351
Predefined colors and utilities.
Definition: Color.h:57
T b
Third coordinate in the (r,g,b,a) representation.
Definition: Vector.h:1099
A light gray style.
static constexpr Color4< T > fromRgb(T r, T g, T b)
Get an opaque color from 3 RGB floats in .
Definition: Color.h:308
static constexpr Color4< T > Opaque(T value=T(0.5))
Opaque predefined color.
Definition: Color.h:211
static constexpr Color4< T > darker(Color4< T > color, T percent=T(0.5))
Compute a darker color.
Definition: Color.h:293
The cell is transparent.
T r
First coordinate in the (r,g,b,a) representation.
Definition: Vector.h:1083
static constexpr Color4< T > fromRgba32(Color4u color)
Get a color from a 32-bit color.
Definition: Color.h:341