TermOx
dynamic_colors.hpp
1 #ifndef TERMOX_PAINTER_DYNAMIC_COLORS_HPP
2 #define TERMOX_PAINTER_DYNAMIC_COLORS_HPP
3 #include <chrono>
4 #include <cmath>
5 #include <cstdint>
6 #include <random>
7 #include <utility>
8 
9 #include <termox/painter/color.hpp>
10 
11 namespace ox::dynamic {
12 
14 class Rainbow {
15  public:
17  Rainbow(std::uint8_t saturation, std::uint8_t lightness);
18 
19  public:
21  [[nodiscard]] auto operator()() -> True_color;
22 
23  private:
24  std::uint16_t hue_ = 0;
25  std::uint8_t const saturation_;
26  std::uint8_t const lightness_;
27 };
28 
30 [[nodiscard]] auto rainbow(
31  Dynamic_color::Period_t period = std::chrono::milliseconds{40},
32  std::uint8_t saturation = 75,
33  std::uint8_t lightness = 75) -> Dynamic_color;
34 
35 /* ---------------------------------------------------------------------------*/
36 
38  protected:
40 
41  explicit Modulation_base(unsigned resolution, unsigned offset = 0);
42 
43  protected:
45 
46  [[nodiscard]] auto get_next_ratio() -> double;
47 
48  private:
49  unsigned const step_total_;
50  unsigned step_;
51 
52  private:
54  [[nodiscard]] auto post_increment_step() -> int;
55 };
56 
57 template <typename Function>
58 class Invert : public Function {
59  public:
60  using Function::Function;
61 
62  public:
63  [[nodiscard]] auto operator()() -> double
64  {
65  return -1. * Function::operator()() + 1.;
66  }
67 };
68 
69 template <typename Function>
70 class Concave : public Function {
71  public:
72  using Function::Function;
73 
74  public:
75  [[nodiscard]] auto operator()() -> double
76  {
77  return std::pow(Function::operator()(), 2.);
78  }
79 };
80 
81 template <typename Function>
82 class Convex : public Function {
83  public:
84  using Function::Function;
85 
86  public:
87  [[nodiscard]] auto operator()() -> double
88  {
89  return std::sqrt(Function::operator()());
90  }
91 };
92 
93 class Triangle : private Modulation_base {
94  public:
96  Triangle(unsigned resolution);
97 
98  public:
100  [[nodiscard]] auto operator()() -> double;
101 };
102 
103 class Sine : private Modulation_base {
104  public:
106  Sine(unsigned resolution);
107 
108  public:
110  [[nodiscard]] auto operator()() -> double;
111 };
112 
113 class Sawtooth_up : private Modulation_base {
114  public:
116  Sawtooth_up(unsigned resolution);
117 
118  public:
120  [[nodiscard]] auto operator()() -> double;
121 };
122 
123 class Sawtooth_down : public Invert<Sawtooth_up> {
124  public:
125  using Invert::Invert;
126 };
127 
128 class Square : private Modulation_base {
129  public:
131  Square(unsigned resolution);
132 
133  public:
135  [[nodiscard]] auto operator()() -> double;
136 };
137 
138 class Random : private Modulation_base {
139  public:
141  Random(unsigned resolution);
142 
143  public:
145  [[nodiscard]] auto operator()() -> double;
146 
147  private:
148  std::mt19937 gen_{std::random_device{}()};
149  std::uniform_real_distribution<double> dist_{0., 1.};
150 };
151 
153 
154 template <typename Shape>
155 class Fade {
156  public:
158 
160  Fade(HSL const a, HSL const b, Shape&& shape_fn)
161  : base_{a},
162  distance_{find_distance(a, b)},
163  shape_fn_{std::forward<Shape>(shape_fn)}
164  {}
165 
166  public:
167  [[nodiscard]] auto operator()() -> True_color { return this->step(); }
168 
169  private:
171  struct HSL_diff {
172  int hue_diff;
173  int saturation_diff;
174  int lightness_diff;
175  };
176 
177  private:
178  HSL const base_;
179  HSL_diff const distance_;
180  Shape shape_fn_;
181 
182  private:
184  [[nodiscard]] auto step() -> HSL
185  {
186  double const ratio = shape_fn_();
187 
188  double const h = base_.hue + distance_.hue_diff * ratio;
189  double const s = base_.saturation + distance_.saturation_diff * ratio;
190  double const l = base_.lightness + distance_.lightness_diff * ratio;
191 
192  return narrow(h, s, l);
193  }
194 
195  private:
197  [[nodiscard]] static auto find_distance(HSL const a, HSL const b)
198  -> HSL_diff
199  {
200  return {b.hue - a.hue, b.saturation - a.saturation,
201  b.lightness - a.lightness};
202  }
203 
205  [[nodiscard]] static auto narrow(double const hue,
206  double const saturation,
207  double const lightness) -> HSL
208  {
209  return {static_cast<std::uint16_t>(hue),
210  static_cast<std::uint8_t>(saturation),
211  static_cast<std::uint8_t>(lightness)};
212  }
213 };
214 
216 template <typename Shape>
217 [[nodiscard]] auto fade(HSL const a,
218  HSL const b,
219  unsigned const resolution = 400,
220  Dynamic_color::Period_t const interval =
221  std::chrono::milliseconds{40}) -> Dynamic_color
222 {
223  return {interval, Fade{a, b, Shape{resolution}}};
224 }
225 
227 template <typename Shape>
228 [[nodiscard]] auto fade(True_color const a,
229  True_color const b,
230  unsigned const resolution = 400,
231  Dynamic_color::Period_t const interval =
232  std::chrono::milliseconds{40}) -> Dynamic_color
233 {
234  return fade<Shape>(esc::rgb_to_hsl({a.red, a.green, a.blue}),
235  esc::rgb_to_hsl({b.red, b.green, b.blue}), resolution,
236  interval);
237 }
238 
239 } // namespace ox::dynamic
240 #endif // TERMOX_PAINTER_DYNAMIC_COLORS_HPP
Definition: dynamic_colors.hpp:70
Definition: dynamic_colors.hpp:82
Dynamic_color type that fades between two HSL Colors.
Definition: dynamic_colors.hpp:155
Fade(HSL const a, HSL const b, Shape &&shape_fn)
Dynamic Color that cycles between a and b and back.
Definition: dynamic_colors.hpp:160
Definition: dynamic_colors.hpp:58
Definition: dynamic_colors.hpp:37
auto get_next_ratio() -> double
Finds the next ratio between from the current step and resolution.
Definition: dynamic_colors.cpp:47
Modulation_base(unsigned resolution, unsigned offset=0)
Resolution is the number of steps to complete a full cycle.
Definition: dynamic_colors.cpp:40
Dynamic_color type that cycles through every hue value in HSL color wheel.
Definition: dynamic_colors.hpp:14
Rainbow(std::uint8_t saturation, std::uint8_t lightness)
Creates a Rainbow Dynamic Color w/fixed saturation and lightness values.
Definition: dynamic_colors.cpp:24
auto operator()() -> True_color
Increment and return the next True_color.
Definition: dynamic_colors.cpp:28
Definition: dynamic_colors.hpp:138
Random(unsigned resolution)
Resolution is the number of steps to complete a full cycle.
Definition: dynamic_colors.cpp:85
auto operator()() -> double
Returns value in range [0.0, 1.0].
Definition: dynamic_colors.cpp:87
Definition: dynamic_colors.hpp:123
Definition: dynamic_colors.hpp:113
Sawtooth_up(unsigned resolution)
Resolution is the number of steps to complete a full cycle.
Definition: dynamic_colors.cpp:72
auto operator()() -> double
Returns value in range [0.0, 1.0].
Definition: dynamic_colors.cpp:76
Definition: dynamic_colors.hpp:103
auto operator()() -> double
Returns value in range [0.0, 1.0].
Definition: dynamic_colors.cpp:66
Sine(unsigned resolution)
Resolution is the number of steps to complete a full cycle.
Definition: dynamic_colors.cpp:64
Definition: dynamic_colors.hpp:128
Square(unsigned resolution)
Resolution is the number of steps to complete a full cycle.
Definition: dynamic_colors.cpp:78
auto operator()() -> double
Returns value in range [0.0, 1.0].
Definition: dynamic_colors.cpp:80
Definition: dynamic_colors.hpp:93
Triangle(unsigned resolution)
Resolution is the number of steps to complete a full cycle.
Definition: dynamic_colors.cpp:57
auto operator()() -> double
Returns value in range [0.0, 1.0].
Definition: dynamic_colors.cpp:59
Defines an animated color.
Definition: color.hpp:105