roo_display
API Documentation for roo_display
Loading...
Searching...
No Matches
basic.cpp
Go to the documentation of this file.
1
3
4namespace roo_display {
5
6template <typename HLineFiller>
8 int16_t y1, bool flip_diag) {
9 int16_t dx = x1 - x0, dy = y1 - y0;
10 int16_t err = dx >> 1, xs = x0, dlen = 0;
11 int16_t y = flip_diag ? y1 : y0;
12 int16_t ystep = flip_diag ? -1 : 1;
13
14 for (; x0 <= x1; x0++) {
15 dlen++;
16 err -= dy;
17 if (err < 0) {
18 err += dx;
19 drawer->fillHLine(xs, y, x0);
20 dlen = 0;
21 y += ystep;
22 xs = x0 + 1;
23 }
24 }
25 if (dlen > 0) drawer->fillHLine(xs, y, x1);
26}
27
28template <typename VLineFiller>
30 int16_t y1, bool flip_diag) {
31 int16_t dy = y1 - y0, dx = x1 - x0;
32 int16_t err = dy >> 1, ys = y0, dlen = 0;
33 int16_t x = flip_diag ? x1 : x0;
34 int16_t xstep = flip_diag ? -1 : 1;
35
36 for (; y0 <= y1; y0++) {
37 dlen++;
38 err -= dx;
39 if (err < 0) {
40 err += dy;
41 drawer->fillVLine(x, ys, y0);
42 dlen = 0;
43 x += xstep;
44 ys = y0 + 1;
45 }
46 }
47 if (dlen > 0) drawer->fillVLine(x, ys, y1);
48}
49
51 Color color, const Box &clip_box, BlendingMode mode) {
52 if (x0 > clip_box.xMax() || x1 < clip_box.xMin() || y0 > clip_box.yMax() ||
53 y0 < clip_box.yMin() || x1 < x0) {
54 return;
55 }
56
57 if (x0 < clip_box.xMin()) x0 = clip_box.xMin();
58 if (x1 > clip_box.xMax()) x1 = clip_box.xMax();
59
60 device.fillRects(mode, color, &x0, &y0, &x1, &y0, 1);
61}
62
64 Color color, const Box &clip_box, BlendingMode mode) {
65 if (x0 > clip_box.xMax() || x0 < clip_box.xMin() || y0 > clip_box.yMax() ||
66 y1 < clip_box.yMin() || y1 < y0) {
67 return;
68 }
69
70 if (y0 < clip_box.yMin()) y0 = clip_box.yMin();
71 if (y1 > clip_box.yMax()) y1 = clip_box.yMax();
72
73 device.fillRects(mode, color, &x0, &y0, &x0, &y1, 1);
74}
75
76void Line::drawTo(const Surface &s) const {
77 int16_t x0 = x0_ + s.dx(), y0 = y0_ + s.dy();
78 int16_t x1 = x1_ + s.dx(), y1 = y1_ + s.dy();
79 Color color = AlphaBlend(s.bgcolor(), this->color());
80 if (x0 == x1) {
81 drawVLine(s.out(), x0, y0, y1, color, s.clip_box(), s.blending_mode());
82 } else if (y0_ == y1_) {
83 drawHLine(s.out(), x0, y0, x1, color, s.clip_box(), s.blending_mode());
84 } else {
85 bool preclipped = s.clip_box().contains(Box(x0, y0, x1, y1));
86 if (steep()) {
87 if (preclipped) {
88 BufferedVLineFiller drawer(s.out(), color, s.blending_mode());
89 drawSteepLine(&drawer, x0, y0, x1, y1, diag_);
90 } else {
91 ClippingBufferedVLineFiller drawer(s.out(), color, s.clip_box(),
92 s.blending_mode());
93 drawSteepLine(&drawer, x0, y0, x1, y1, diag_);
94 }
95 } else {
96 if (preclipped) {
97 BufferedHLineFiller drawer(s.out(), color, s.blending_mode());
98 drawNonSteepLine(&drawer, x0, y0, x1, y1, diag_);
99 } else {
100 ClippingBufferedHLineFiller drawer(s.out(), color, s.clip_box(),
101 s.blending_mode());
102 drawNonSteepLine(&drawer, x0, y0, x1, y1, diag_);
103 }
104 }
105 }
106}
107
108void Rect::drawTo(const Surface &s) const {
109 if (x1_ < x0_ || y1_ < y0_) return;
110 int16_t x0 = x0_ + s.dx();
111 int16_t y0 = y0_ + s.dy();
112 int16_t x1 = x1_ + s.dx();
113 int16_t y1 = y1_ + s.dy();
114 Color color = AlphaBlend(s.bgcolor(), this->color());
115 ClippingBufferedRectFiller filler(s.out(), color, s.clip_box(),
116 s.blending_mode());
117 filler.fillHLine(x0, y0, x1);
118 filler.fillHLine(x0, y1, x1);
119 filler.fillVLine(x0, y0 + 1, y1 - 1);
120 filler.fillVLine(x1, y0 + 1, y1 - 1);
121 if (s.fill_mode() == FillMode::kExtents && x1 - x0 >= 2 && y1 - y0 >= 2) {
122 s.out().fillRect(BlendingMode::kSource, Box(x0 + 1, y0 + 1, x1 - 1, y1 - 1),
123 s.bgcolor());
124 }
125}
126
127void Border::drawTo(const Surface &s) const {
128 if (x1_ < x0_ || y1_ < y0_) return;
129 int16_t x0 = x0_ + s.dx();
130 int16_t y0 = y0_ + s.dy();
131 int16_t x1 = x1_ + s.dx();
132 int16_t y1 = y1_ + s.dy();
133 Color color = AlphaBlend(s.bgcolor(), this->color());
134 ClippingBufferedRectFiller filler(s.out(), color, s.clip_box(),
135 s.blending_mode());
136 if (left_ > 0) {
137 filler.fillRect(x0, y0, x0 + left_ - 1, y1);
138 x0 += left_;
139 }
140 if (top_ > 0) {
141 filler.fillRect(x0, y0, x1, y0 + top_ - 1);
142 y0 += top_;
143 }
144 if (right_ > 0) {
145 filler.fillRect(x1 - right_ + 1, y0, x1, y1);
146 x1 -= right_;
147 }
148 if (bottom_ > 0) {
149 filler.fillRect(x0, y1 - bottom_ + 1, x1, y1);
150 }
151}
152
153void FilledRect::drawTo(const Surface &s) const {
154 if (x1_ < x0_ || y1_ < y0_) return;
155 int16_t x0 = x0_ + s.dx();
156 int16_t y0 = y0_ + s.dy();
157 int16_t x1 = x1_ + s.dx();
158 int16_t y1 = y1_ + s.dy();
159 Color color = AlphaBlend(s.bgcolor(), this->color());
160 Box box(x0, y0, x1, y1);
161 if (box.clip(s.clip_box()) != Box::ClipResult::kEmpty) {
162 s.out().fillRect(s.blending_mode(), box, color);
163 }
164}
165
167 public:
168 FilledRectStream(Color color) : color_(color) {}
169
170 void Read(Color *buf, uint16_t count) override {
171 FillColor(buf, count, color_);
172 }
173
174 void Skip(uint32_t count) override {}
175
176 private:
177 Color color_;
178};
179
180std::unique_ptr<PixelStream> FilledRect::createStream() const {
181 return std::unique_ptr<PixelStream>(new FilledRectStream(color()));
182}
183
184std::unique_ptr<PixelStream> FilledRect::createStream(const Box &bounds) const {
185 return std::unique_ptr<PixelStream>(new FilledRectStream(color()));
186}
187
188// Also used to draw regular circles.
189template <typename RectFiller>
191 int y1, int16_t r) {
192 int32_t f = 2 - r;
193 int32_t ddF_y = -2 * r;
194 int32_t ddF_x = 1;
195 int32_t xe = 0;
196
197 while (f < 0) {
198 ++xe;
199 f += (ddF_x += 2);
200 }
201 f += (ddF_y += 2);
202 filler.fillHLine(x0 - xe, y1 + r, x1 + xe);
203 filler.fillHLine(x0 - xe, y0 - r, x1 + xe);
204 filler.fillVLine(x1 + r, y0 - xe, y1 + xe);
205 filler.fillVLine(x0 - r, y0 - xe, y1 + xe);
206
207 while (xe < --r) {
208 int32_t xs = xe + 1;
209 while (f < 0) {
210 ++xe;
211 f += (ddF_x += 2);
212 }
213 f += (ddF_y += 2);
214
215 filler.fillHLine(x0 - xe, y1 + r, x0 - xs);
216 filler.fillHLine(x0 - xe, y0 - r, x0 - xs);
217 filler.fillHLine(x1 + xs, y0 - r, x1 + xe);
218 filler.fillHLine(x1 + xs, y1 + r, x1 + xe);
219
220 filler.fillVLine(x1 + r, y1 + xs, y1 + xe);
221 filler.fillVLine(x1 + r, y0 - xe, y0 - xs);
222 filler.fillVLine(x0 - r, y0 - xe, y0 - xs);
223 filler.fillVLine(x0 - r, y1 + xs, y1 + xe);
224 }
225}
226
227template <typename HlineFiller>
229 int y1, int16_t r) {
230 // Optimized midpoint circle algorithm.
231 int16_t x = 0;
232 int16_t y = r;
233 int16_t dx = 1;
234 int16_t dy = r + r;
235 int16_t p = -(r >> 1);
236
237 while (x < y) {
238 if (p >= 0) {
239 dy -= 2;
240 p -= dy;
241 y--;
242 }
243
244 dx += 2;
245 p += dx;
246
247 x++;
248
249 filler->fillHLine(x0 - y, y1 + x, x1 + y);
250 filler->fillHLine(x0 - y, y0 - x, x1 + y);
251 if (p >= 0 && x + 1 < y) {
252 filler->fillHLine(x0 - x, y1 + y, x1 + x);
253 filler->fillHLine(x0 - x, y0 - y, x1 + x);
254 }
255 }
256}
257
258template <typename HlineFiller>
260 int x1, int y1, int16_t r) {
261 // Optimized midpoint circle algorithm.
262 int16_t x = 0;
263 int16_t y = r;
264 int16_t dx = 1;
265 int16_t dy = r + r;
266 int16_t p = -(r >> 1);
267
268 while (x < y) {
269 if (p >= 0) {
270 dy -= 2;
271 p -= dy;
272 y--;
273 }
274
275 dx += 2;
276 p += dx;
277
278 x++;
279 if (y < r) {
280 filler->fillHLine(x0 - r, y1 + x, x0 - y - 1);
281 filler->fillHLine(x1 + y + 1, y1 + x, x1 + r);
282 filler->fillHLine(x0 - r, y0 - x, x0 - y - 1);
283 filler->fillHLine(x1 + y + 1, y0 - x, x1 + r);
284 }
285 if (p >= 0 && x + 1 < y) {
286 filler->fillHLine(x0 - r, y1 + y, x0 - x - 1);
287 filler->fillHLine(x1 + x + 1, y1 + y, x1 + r);
288 filler->fillHLine(x0 - r, y0 - y, x0 - x - 1);
289 filler->fillHLine(x1 + x + 1, y0 - y, x1 + r);
290 }
291 }
292}
293
294// Also used to draw circles, in a special case when radius is half of the box
295// length.
296void drawRoundRect(DisplayOutput &output, const Box &bbox, int16_t radius,
297 const Box &clip_box, Color color, BlendingMode mode) {
298 if (Box::Intersect(clip_box, bbox).empty()) return;
299 int16_t x0 = bbox.xMin() + radius;
300 int16_t y0 = bbox.yMin() + radius;
301 int16_t x1 = bbox.xMax() - radius;
302 int16_t y1 = bbox.yMax() - radius;
303 if (clip_box.contains(bbox)) {
304 BufferedRectFiller filler(output, color, mode);
305 drawRoundRectTmpl(filler, x0, y0, x1, y1, radius);
306 } else {
307 ClippingBufferedRectFiller filler(output, color, clip_box, mode);
308 drawRoundRectTmpl(filler, x0, y0, x1, y1, radius);
309 }
310}
311
312void RoundRect::drawInteriorTo(const Surface &s) const {
313 Box extents(x0_ + s.dx(), y0_ + s.dy(), x1_ + s.dx(), y1_ + s.dy());
314 drawRoundRect(s.out(), extents, radius_, s.clip_box(),
315 AlphaBlend(s.bgcolor(), this->color()), s.blending_mode());
316}
317
318void Circle::drawInteriorTo(const Surface &s) const {
319 Box extents(x0_ + s.dx(), y0_ + s.dy(), x0_ + diameter_ - 1 + s.dx(),
320 y0_ + diameter_ - 1 + s.dy());
321 drawRoundRect(s.out(), extents, diameter_ >> 1, s.clip_box(),
322 AlphaBlend(s.bgcolor(), this->color()), s.blending_mode());
323}
324
325// Also used to draw circles, in a special case when radius is half of the box
326// length.
327void fillRoundRect(DisplayOutput &output, const Box &bbox, int16_t radius,
328 const Box &clip_box, Color color, BlendingMode mode) {
329 if (Box::Intersect(clip_box, bbox).empty()) return;
330 int16_t x0 = bbox.xMin() + radius;
331 int16_t y0 = bbox.yMin() + radius;
332 int16_t x1 = bbox.xMax() - radius;
333 int16_t y1 = bbox.yMax() - radius;
334 if (clip_box.contains(bbox)) {
335 BufferedRectFiller filler(output, color, mode);
336 if (y0 <= y1) filler.fillRect(bbox.xMin(), y0, bbox.xMax(), y1);
337 fillRoundRectCorners(&filler, x0, y0, x1, y1, radius);
338 } else {
339 ClippingBufferedRectFiller filler(output, color, clip_box, mode);
340 if (y0 <= y1) filler.fillRect(bbox.xMin(), y0, bbox.xMax(), y1);
341 fillRoundRectCorners(&filler, x0, y0, x1, y1, radius);
342 }
343}
344
345void fillRoundRectBg(DisplayOutput &output, const Box &bbox, int16_t radius,
346 const Box &clip_box, Color bgcolor, BlendingMode mode) {
347 if (Box::Intersect(clip_box, bbox).empty()) return;
348 int16_t x0 = bbox.xMin() + radius;
349 int16_t y0 = bbox.yMin() + radius;
350 int16_t x1 = bbox.xMax() - radius;
351 int16_t y1 = bbox.yMax() - radius;
352 if (clip_box.contains(bbox)) {
353 BufferedRectFiller filler(output, bgcolor, mode);
354 fillRoundRectOutsideCorners(&filler, x0, y0, x1, y1, radius);
355 } else {
356 ClippingBufferedRectFiller filler(output, bgcolor, clip_box, mode);
357 fillRoundRectOutsideCorners(&filler, x0, y0, x1, y1, radius);
358 }
359}
360
361void FilledRoundRect::drawTo(const Surface &s) const {
362 Box extents(x0_ + s.dx(), y0_ + s.dy(), x1_ + s.dx(), y1_ + s.dy());
363 fillRoundRect(s.out(), extents, radius_, s.clip_box(),
364 AlphaBlend(s.bgcolor(), this->color()), s.blending_mode());
365 if (s.fill_mode() == FillMode::kExtents) {
366 fillRoundRectBg(s.out(), extents, radius_, s.clip_box(), s.bgcolor(),
367 s.blending_mode());
368 }
369}
370
371void FilledCircle::drawTo(const Surface &s) const {
372 Box extents(x0_ + s.dx(), y0_ + s.dy(), x0_ + diameter_ - 1 + s.dx(),
373 y0_ + diameter_ - 1 + s.dy());
374 fillRoundRect(s.out(), extents, diameter_ >> 1, s.clip_box(),
375 AlphaBlend(s.bgcolor(), this->color()), s.blending_mode());
376 if (s.fill_mode() == FillMode::kExtents) {
377 fillRoundRectBg(s.out(), extents, diameter_ >> 1, s.clip_box(), s.bgcolor(),
378 s.blending_mode());
379 }
380}
381
382template <typename PixelFiller>
384 int16_t ry) {
385 int32_t x, y;
386 int32_t rx2 = rx * rx;
387 int32_t ry2 = ry * ry;
388 int32_t fx2 = 4 * rx2;
389 int32_t fy2 = 4 * ry2;
390 int32_t s;
391
392 for (x = 0, y = ry, s = 2 * ry2 + rx2 * (1 - 2 * ry); ry2 * x <= rx2 * y;
393 x++) {
394 // These are ordered to minimise coordinate changes in x or y
395 // drawPixel can then send fewer bounding box commands
396 drawer->fillPixel(x0 + x, y0 + y);
397 drawer->fillPixel(x0 - x, y0 + y);
398 drawer->fillPixel(x0 - x, y0 - y);
399 drawer->fillPixel(x0 + x, y0 - y);
400 if (s >= 0) {
401 s += fx2 * (1 - y);
402 y--;
403 }
404 s += ry2 * ((4 * x) + 6);
405 }
406
407 for (x = rx, y = 0, s = 2 * rx2 + ry2 * (1 - 2 * rx); rx2 * y <= ry2 * x;
408 y++) {
409 // These are ordered to minimise coordinate changes in x or y
410 // drawPixel can then send fewer bounding box commands
411 drawer->fillPixel(x0 + x, y0 + y);
412 drawer->fillPixel(x0 - x, y0 + y);
413 drawer->fillPixel(x0 - x, y0 - y);
414 drawer->fillPixel(x0 + x, y0 - y);
415 if (s >= 0) {
416 s += fy2 * (1 - x);
417 x--;
418 }
419 s += rx2 * ((4 * y) + 6);
420 }
421}
422
423// Coordinates must be sorted by Y order (y2 >= y1 >= y0)
424template <typename HLineFiller>
426 int16_t y1, int16_t x2, int16_t y2) {
427 int16_t a, b, y, last;
428
429 if (y0 == y2) { // Handle awkward all-on-same-line case as its own thing
430 a = b = x0;
431 if (x1 < a) {
432 a = x1;
433 } else if (x1 > b) {
434 b = x1;
435 }
436 if (x2 < a) {
437 a = x2;
438 } else if (x2 > b) {
439 b = x2;
440 }
441 drawer->fillHLine(a, y0, b);
442 return;
443 }
444
445 int16_t dx01 = x1 - x0, dy01 = y1 - y0, dx02 = x2 - x0, dy02 = y2 - y0,
446 dx12 = x2 - x1, dy12 = y2 - y1;
447 int32_t sa = 0, sb = 0;
448
449 // For upper part of triangle, find scanline crossings for segments
450 // 0-1 and 0-2. If y1=y2 (flat-bottomed triangle), the scanline y1
451 // is included here (and second loop will be skipped, avoiding a /0
452 // error there), otherwise scanline y1 is skipped here and handled
453 // in the second loop...which also avoids a /0 error here if y0=y1
454 // (flat-topped triangle).
455 if (y1 == y2) {
456 last = y1; // Include y1 scanline
457 } else {
458 last = y1 - 1; // Skip it
459 }
460
461 for (y = y0; y <= last; y++) {
462 a = x0 + sa / dy01;
463 b = x0 + sb / dy02;
464 sa += dx01;
465 sb += dx02;
466 /* longhand:
467 a = x0 + (x1 - x0) * (y - y0) / (y1 - y0);
468 b = x0 + (x2 - x0) * (y - y0) / (y2 - y0);
469 */
470 if (a > b) std::swap(a, b);
471 drawer->fillHLine(a, y, b);
472 }
473
474 // For lower part of triangle, find scanline crossings for segments
475 // 0-2 and 1-2. This loop is skipped if y1=y2.
476 sa = (int32_t)dx12 * (y - y1);
477 sb = (int32_t)dx02 * (y - y0);
478 for (; y <= y2; y++) {
479 a = x1 + sa / dy12;
480 b = x0 + sb / dy02;
481 sa += dx12;
482 sb += dx02;
483 /* longhand:
484 a = x1 + (x2 - x1) * (y - y1) / (y2 - y1);
485 b = x0 + (x2 - x0) * (y - y0) / (y2 - y0);
486 */
487 if (a > b) std::swap(a, b);
488 drawer->fillHLine(a, y, b);
489 }
490}
491
492void Triangle::drawInteriorTo(const Surface &s) const {
493 Color color = AlphaBlend(s.bgcolor(), this->color());
494 s.drawObject(Line(x0_, y0_, x1_, y1_, color));
495 s.drawObject(Line(x1_, y1_, x2_, y2_, color));
496 s.drawObject(Line(x0_, y0_, x2_, y2_, color));
497}
498
499void FilledTriangle::drawInteriorTo(const Surface &s) const {
500 Box box = extents().translate(s.dx(), s.dy());
501 Color color = AlphaBlend(s.bgcolor(), this->color());
502 int16_t x0 = x0_ + s.dx();
503 int16_t y0 = y0_ + s.dy();
504 int16_t x1 = x1_ + s.dx();
505 int16_t y1 = y1_ + s.dy();
506 int16_t x2 = x2_ + s.dx();
507 int16_t y2 = y2_ + s.dy();
508 if (s.clip_box().contains(box)) {
509 BufferedHLineFiller drawer(s.out(), color, s.blending_mode());
510 fillTriangle(&drawer, x0, y0, x1, y1, x2, y2);
511 } else {
512 ClippingBufferedHLineFiller drawer(s.out(), color, s.clip_box(),
513 s.blending_mode());
514 fillTriangle(&drawer, x0, y0, x1, y1, x2, y2);
515 }
516}
517
518} // namespace roo_display
Color color() const
Return the shape color.
Definition basic.h:14
Axis-aligned integer rectangle.
Definition box.h:12
int16_t xMin() const
Minimum x (inclusive).
Definition box.h:65
int16_t xMax() const
Maximum x (inclusive).
Definition box.h:71
Box translate(int16_t x_offset, int16_t y_offset) const
Return a translated copy of this box.
Definition box.h:127
bool contains(int16_t x, int16_t y) const
Return whether the point (x, y) lies within the box.
Definition box.h:86
int16_t yMax() const
Maximum y (inclusive).
Definition box.h:74
static Box Intersect(const Box &a, const Box &b)
Return the intersection of two boxes (may be empty).
Definition box.h:25
int16_t yMin() const
Minimum y (inclusive).
Definition box.h:68
Box extents() const override
Return the bounding box encompassing all pixels that need to be drawn.
Definition basic.h:207
ARGB8888 color stored as a 32-bit unsigned integer.
Definition color.h:16
The abstraction for drawing to a display.
Definition device.h:15
virtual void fillRects(BlendingMode blending_mode, Color color, int16_t *x0, int16_t *y0, int16_t *x1, int16_t *y1, uint16_t count)=0
Draw the specified rectangles using the same color. Invalidates the address window.
FilledRectStream(Color color)
Definition basic.cpp:168
void Read(Color *buf, uint16_t count) override
Read up to size pixels into buf.
Definition basic.cpp:170
void Skip(uint32_t count) override
Skip count pixels.
Definition basic.cpp:174
std::unique_ptr< PixelStream > createStream() const override
Create a stream covering the full extents().
Definition basic.cpp:180
Stream of pixels in row-major order.
Definition streamable.h:12
Box extents() const override
Return the bounding box encompassing all pixels that need to be drawn.
Definition basic.h:172
Box extents() const override
Return the bounding box encompassing all pixels that need to be drawn.
Definition basic.h:348
Defines 140 opaque HTML named colors.
void fillRoundRectCorners(HlineFiller *filler, int16_t x0, int16_t y0, int x1, int y1, int16_t r)
Definition basic.cpp:228
void fillRoundRect(DisplayOutput &output, const Box &bbox, int16_t radius, const Box &clip_box, Color color, BlendingMode mode)
Definition basic.cpp:327
BlendingMode
Porter-Duff style blending modes.
Definition blending.h:17
@ kSource
The new ARGB8888 value completely replaces the old one.
void drawRoundRect(DisplayOutput &output, const Box &bbox, int16_t radius, const Box &clip_box, Color color, BlendingMode mode)
Definition basic.cpp:296
void drawEllipse(PixelFiller *drawer, int16_t x0, int16_t y0, int16_t rx, int16_t ry)
Definition basic.cpp:383
void drawSteepLine(VLineFiller *drawer, int16_t x0, int16_t y0, int16_t x1, int16_t y1, bool flip_diag)
Definition basic.cpp:29
Color AlphaBlend(Color bgc, Color fgc)
Definition blending.h:598
void drawHLine(DisplayOutput &device, int16_t x0, int16_t y0, int16_t x1, Color color, const Box &clip_box, BlendingMode mode)
Definition basic.cpp:50
void drawVLine(DisplayOutput &device, int16_t x0, int16_t y0, int16_t y1, Color color, const Box &clip_box, BlendingMode mode)
Definition basic.cpp:63
void drawRoundRectTmpl(RectFiller &filler, int16_t x0, int16_t y0, int x1, int y1, int16_t r)
Definition basic.cpp:190
void FillColor(Color *buf, uint32_t count, Color color)
Fill an array with a single color.
Definition color.h:109
void drawNonSteepLine(HLineFiller *drawer, int16_t x0, int16_t y0, int16_t x1, int16_t y1, bool flip_diag)
Definition basic.cpp:7
@ kExtents
Fill the entire extents box (possibly with fully transparent pixels).
void fillRoundRectOutsideCorners(HlineFiller *filler, int16_t x0, int16_t y0, int x1, int y1, int16_t r)
Definition basic.cpp:259
void fillRoundRectBg(DisplayOutput &output, const Box &bbox, int16_t radius, const Box &clip_box, Color bgcolor, BlendingMode mode)
Definition basic.cpp:345
void fillTriangle(HLineFiller *drawer, int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2)
Definition basic.cpp:425
Color bgcolor
Definition smooth.cpp:889
float r
Definition smooth.cpp:474