roo_display
API Documentation for roo_display
Loading...
Searching...
No Matches
gradient.cpp
Go to the documentation of this file.
2
4
5namespace roo_display {
6
8 : gradient_(std::move(gradient)),
9 boundary_(boundary),
10 transparency_mode_(TransparencyMode::kNone),
11 inv_period_(1.0f / (gradient_.back().value - gradient_.front().value)) {
12 for (const Node& n : gradient_) {
13 uint8_t a = n.color.a();
14 if (a != 255) {
15 if (a != 0) {
16 transparency_mode_ = TransparencyMode::kFull;
17 break;
18 }
19 transparency_mode_ = TransparencyMode::kCrude;
20 }
21 }
22}
23
24Color ColorGradient::getColor(float value) const {
25 // Adjust the value, handling the boundary type.
26 switch (boundary_) {
28 break;
29 }
31 if (value < gradient_.front().value) {
32 float diff = gradient_.front().value - value;
33 if (diff >= 1) return color::Transparent;
34 return gradient_.front().color.withA(255 * diff);
35 }
36 if (value > gradient_.back().value) {
37 float diff = value - gradient_.back().value;
38 if (diff >= 1) return color::Transparent;
39 return gradient_.back().color.withA(255 * diff);
40 }
41 break;
42 }
44 if (value < gradient_.front().value || value > gradient_.back().value) {
45 float adj = value - gradient_.front().value;
46 float period = gradient_.back().value - gradient_.front().value;
47 value =
48 adj - period * floorf(adj * inv_period_) + gradient_.front().value;
49 }
50 break;
51 }
52 }
53 // First, find the matching interval.
55 while (right_bound < gradient_.size() &&
56 gradient_[right_bound].value < value) {
58 }
59 if (right_bound == 0) {
60 return gradient_[0].color;
61 } else if (right_bound >= gradient_.size()) {
62 return gradient_.back().color;
63 } else {
64 // Interpolate.
65 float left_temp = gradient_[right_bound - 1].value;
66 float right_temp = gradient_[right_bound].value;
67 float f_a = (value - left_temp) / (right_temp - left_temp);
68 int16_t if_a = (int16_t)(256 * f_a);
69 Color left = gradient_[right_bound - 1].color;
70 Color right = gradient_[right_bound].color;
71 return InterpolateColors(left, right, if_a);
72 // uint32_t a =
73 // ((uint16_t)left.a() * (256 - if_a) + (uint16_t)right.a() * if_a) /
74 // 256;
75 // int16_t if_c;
76 // if (left.a() == right.a()) {
77 // // Common case, e.g. both colors opaque.
78 // if_c = if_a;
79 // } else if (left.a() == 0) {
80 // if_c = 256;
81 // } else if (right.a() == 0) {
82 // if_c = 0;
83 // } else {
84 // float f_c = f_a * right.a() / ((1 - f_a) * left.a() + f_a * right.a());
85 // if_c = (int16_t)(256 * f_c);
86 // }
87 // uint32_t r =
88 // ((uint16_t)left.r() * (256 - if_c) + (uint16_t)right.r() * if_c) /
89 // 256;
90 // uint32_t g =
91 // ((uint16_t)left.g() * (256 - if_c) + (uint16_t)right.g() * if_c) /
92 // 256;
93 // uint32_t b =
94 // ((uint16_t)left.b() * (256 - if_c) + (uint16_t)right.b() * if_c) /
95 // 256;
96 // return Color(a << 24 | r << 16 | g << 8 | b);
97 }
98}
99
101 Box extents)
102 : cx_(center.x),
103 cy_(center.y),
104 gradient_(std::move(gradient)),
105 extents_(extents) {}
106
108 uint32_t count, Color* result) const {
109 while (count-- > 0) {
110 float dx = *x - cx_;
111 float dy = *y - cy_;
112 float r = sqrtf(dx * dx + dy * dy);
113 Color c = gradient_.getColor(r);
114 *result++ = c;
115 ++x;
116 ++y;
117 }
118}
119
121 Box extents)
122 : cx_(center.x),
123 cy_(center.y),
124 gradient_(std::move(gradient)),
125 extents_(extents) {}
126
128 uint32_t count, Color* result) const {
129 while (count-- > 0) {
130 int16_t dx = *x - cx_;
131 int16_t dy = *y - cy_;
132 uint32_t r = dx * dx + dy * dy;
133 Color c = gradient_.getColor(r);
134 *result++ = c;
135 ++x;
136 ++y;
137 }
138}
139
141 ColorGradient gradient, Box extents)
142 : cx_(origin.x),
143 cy_(origin.y),
144 dx_(dx),
145 dy_(dy),
146 gradient_(std::move(gradient)),
147 extents_(extents) {}
148
150 uint32_t count, Color* result) const {
151 if (dx_ == 0.0f) {
152 if (dy_ == 1.0f) {
153 while (count-- > 0) {
154 *result++ = gradient_.getColor(*y++ - cy_);
155 }
156 } else {
157 while (count-- > 0) {
158 *result++ = gradient_.getColor((*y++ - cy_) * dy_);
159 }
160 }
161 } else if (dy_ == 0.0f) {
162 if (dx_ == 1.0f) {
163 while (count-- > 0) {
164 *result++ = gradient_.getColor(*x++ - cx_);
165 }
166 } else {
167 while (count-- > 0) {
168 *result++ = gradient_.getColor((*x++ - cx_) * dx_);
169 }
170 }
171 } else {
172 while (count-- > 0) {
173 *result++ = gradient_.getColor((*x++ - cx_) * dx_ + (*y++ - cy_) * dy_);
174 }
175 }
176}
177
179 int16_t yMax, Color* result) const {
180 int16_t width = xMax - xMin + 1;
181 if (dx_ == 0.0f) {
182 if (dy_ == 1.0f) {
183 for (int16_t y = yMin; y <= yMax; ++y) {
184 FillColor(result, width, gradient_.getColor(y - cy_));
185 result += width;
186 }
187 } else {
188 for (int16_t y = yMin; y <= yMax; ++y) {
189 FillColor(result, width, gradient_.getColor((y - cy_) * dy_));
190 result += width;
191 }
192 }
193 } else if (dy_ == 0.0f) {
194 if (dx_ == 1.0f) {
195 const Color* start = result;
196 for (int16_t x = xMin; x <= xMax; ++x) {
197 *result++ = gradient_.getColor(x - cx_);
198 }
199 for (int16_t y = yMin + 1; y <= yMax; ++y) {
200 memcpy(result, start, width * sizeof(Color));
201 result += width;
202 }
203 } else {
204 const Color* start = result;
205 for (int16_t x = xMin; x <= xMax; ++x) {
206 *result++ = gradient_.getColor((x - cx_) * dx_);
207 }
208 for (int16_t y = yMin + 1; y <= yMax; ++y) {
209 memcpy(result, start, width * sizeof(Color));
210 result += width;
211 }
212 }
213 } else {
214 for (int16_t y = yMin; y <= yMax; ++y) {
215 for (int16_t x = xMin; x <= xMax; ++x) {
216 *result++ = gradient_.getColor((x - cx_) * dx_ + (y - cy_) * dy_);
217 }
218 }
219 }
220 return false;
221}
222
224 Box extents)
225 : cx_(center.x),
226 cy_(center.y),
227 gradient_(std::move(gradient)),
228 extents_(extents) {}
229
231 uint32_t count, Color* result) const {
232 while (count-- > 0) {
233 *result++ = gradient_.getColor(atan2f(*x++ - cx_, cy_ - *y++));
234 }
235}
236
237roo_logging::Stream& operator<<(roo_logging::Stream& os, ColorGradient::Boundary boundary) {
238 switch (boundary) {
240 os << "ColorGradient::Boundary::kExtended";
241 break;
243 os << "ColorGradient::Boundary::kTruncated";
244 break;
246 os << "ColorGradient::Boundary::kPeriodic";
247 break;
248 default:
249 os << "ColorGradient::Boundary::(unknown)";
250 break;
251 }
252 return os;
253}
254
255} // namespace roo_display
void readColors(const int16_t *x, const int16_t *y, uint32_t count, Color *result) const override
Read colors for the given points.
Definition gradient.cpp:230
AngularGradient(FpPoint center, ColorGradient gradient, Box extents=Box::MaximumBox())
Create an angular gradient.
Definition gradient.cpp:223
Axis-aligned integer rectangle.
Definition box.h:12
Multi-point gradient specification.
Definition gradient.h:19
Color getColor(float value) const
Return the color for a given value.
Definition gradient.cpp:24
Boundary
Boundary behavior outside gradient range.
Definition gradient.h:28
ColorGradient(std::vector< Node > gradient, Boundary boundary=Boundary::kExtended)
Create a gradient specification.
Definition gradient.cpp:7
ARGB8888 color stored as a 32-bit unsigned integer.
Definition color.h:16
void readColors(const int16_t *x, const int16_t *y, uint32_t count, Color *result) const override
Read colors for the given points.
Definition gradient.cpp:149
LinearGradient(Point origin, float dx, float dy, ColorGradient gradient, Box extents=Box::MaximumBox())
Create a linear gradient.
Definition gradient.cpp:140
bool readColorRect(int16_t xMin, int16_t yMin, int16_t xMax, int16_t yMax, Color *result) const override
Read colors for a rectangle.
Definition gradient.cpp:178
RadialGradientSq(Point center, ColorGradient gradient, Box extents=Box::MaximumBox())
Create a radial gradient using squared distance.
Definition gradient.cpp:120
void readColors(const int16_t *x, const int16_t *y, uint32_t count, Color *result) const override
Read colors for the given points.
Definition gradient.cpp:127
void readColors(const int16_t *x, const int16_t *y, uint32_t count, Color *result) const override
Read colors for the given points.
Definition gradient.cpp:107
RadialGradient(FpPoint center, ColorGradient gradient, Box extents=Box::MaximumBox())
Create a radial gradient.
Definition gradient.cpp:100
Defines 140 opaque HTML named colors.
TransparencyMode
Transparency information for a stream or color mode.
Definition blending.h:103
@ kNone
All colors are fully opaque.
@ kCrude
Colors are either fully opaque or fully transparent.
@ kFull
Colors may include partial transparency (alpha channel).
roo_logging::Stream & operator<<(roo_logging::Stream &os, BlendingMode mode)
Definition blending.cpp:54
void FillColor(Color *buf, uint32_t count, Color color)
Fill an array with a single color.
Definition color.h:109
Color InterpolateColors(Color c1, Color c2, int16_t fraction)
Interpolate between two colors with fraction in [0, 256].
float r
Definition smooth.cpp:474
A single node in the gradient.
Definition gradient.h:22
Floating-point point.
Definition point.h:12
Integer point.
Definition point.h:6