Gamedev Framework (gf)  0.17.0
A C++14 framework for 2D games
ColorRamp.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_RAMP_H
22 #define GF_COLOR_RAMP_H
23 
24 #include <cassert>
25 #include <map>
26 #include <type_traits>
27 #include <utility>
28 
29 #include "Color.h"
30 #include "Portability.h"
31 #include "Vector.h"
32 #include "VectorOps.h"
33 
34 namespace gf {
35 #ifndef DOXYGEN_SHOULD_SKIP_THIS
36 inline namespace v1 {
37 #endif
38 
48  template<typename T>
49  struct ColorRampBase {
50  static_assert(std::is_floating_point<T>::value, "T must be a floating point type.");
51  public:
57  bool isEmpty() const {
58  return m_map.empty();
59  }
60 
67  void addColorStop(T offset, const Color4<T>& color) {
68  if (isEmpty()) {
69  m_min = m_max = offset;
70  } else {
71  if (offset < m_min) {
72  m_min = offset;
73  }
74 
75  if (offset > m_max) {
76  m_max = offset;
77  }
78  }
79 
80  m_map.insert(std::make_pair(offset, color));
81  }
82 
89  Color4<T> computeColor(T offset) const {
90  if (m_map.empty()) {
91  return ColorBase<T>::White;
92  }
93 
94  if (offset < m_min) {
95  return m_map.begin()->second;
96  }
97 
98  if (offset > m_max) {
99  return m_map.rbegin()->second;
100  }
101 
102  auto it = m_map.lower_bound(offset);
103  assert(it != m_map.end());
104 
105  T t2 = it->first;
106  Color4<T> c2 = it->second;
107 
108  if (it == m_map.begin()) {
109  return c2;
110  }
111 
112  --it;
113  T t1 = it->first;
114  Color4<T> c1 = it->second;
115 
116  return gf::lerp(c1, c2, (offset - t1) / (t2 - t1));
117  }
118 
119  private:
120  T m_min;
121  T m_max;
122  std::map<T, Color4<T>> m_map;
123  };
124 
130 
136 
142 
143 // MSVC does not like extern template
144 #ifndef _MSC_VER
145  extern template struct GF_API ColorRampBase<float>;
146  extern template struct GF_API ColorRampBase<double>;
147 #endif
148 
149 #ifndef DOXYGEN_SHOULD_SKIP_THIS
150 }
151 #endif
152 }
153 
154 #endif // GF_COLOR_RAMP_H
bool isEmpty() const
Check if the color ramp is empty.
Definition: ColorRamp.h:57
constexpr T lerp(T lhs, T rhs, U t)
Linear interpolation function.
Definition: Math.h:268
void addColorStop(T offset, const Color4< T > &color)
Add a color stop.
Definition: ColorRamp.h:67
ColorRampBase< float > ColorRampF
Instantiation of ColoRampBase for float
Definition: ColorRamp.h:129
Color4< T > computeColor(T offset) const
Compute a color from an offset.
Definition: ColorRamp.h:89
The namespace for gf classes.
Definition: Action.h:35
A 4D vector.
Definition: Vector.h:852
Predefined colors and utilities.
Definition: Color.h:57
A color ramp.
Definition: ColorRamp.h:49