ESPHome 2026.6.0-dev
Loading...
Searching...
No Matches
display.h
Go to the documentation of this file.
1#pragma once
2
3#include <cstdarg>
4#include <vector>
5
6#include "rect.h"
7
10#include "esphome/core/time.h"
11#include "esphome/core/log.h"
12#include "display_color_utils.h"
13
14#ifdef USE_GRAPH
16#endif
17
18#ifdef USE_QR_CODE
20#endif
21
22#ifdef USE_GRAPHICAL_DISPLAY_MENU
24#endif
25
26namespace esphome::display {
27
78
126
132
139
140const int EDGES_TRIGON = 3;
141const int EDGES_TRIANGLE = 3;
142const int EDGES_TETRAGON = 4;
144const int EDGES_PENTAGON = 5;
145const int EDGES_HEXAGON = 6;
146const int EDGES_HEPTAGON = 7;
147const int EDGES_OCTAGON = 8;
148const int EDGES_NONAGON = 9;
149const int EDGES_ENNEAGON = 9;
150const int EDGES_DECAGON = 10;
151const int EDGES_HENDECAGON = 11;
152const int EDGES_DODECAGON = 12;
153const int EDGES_TRIDECAGON = 13;
154const int EDGES_TETRADECAGON = 14;
155const int EDGES_PENTADECAGON = 15;
156const int EDGES_HEXADECAGON = 16;
157
158const float ROTATION_0_DEGREES = 0.0;
159const float ROTATION_45_DEGREES = 45.0;
160const float ROTATION_90_DEGREES = 90.0;
161const float ROTATION_180_DEGREES = 180.0;
162const float ROTATION_270_DEGREES = 270.0;
163
168
173
174class Display;
175class DisplayPage;
176class DisplayOnPageChangeTrigger;
177
189template<typename T> class DisplayWriter {
190 public:
192
193 // For stateless lambdas (convertible to function pointer): use function pointer (4 bytes)
194 template<typename F>
195 DisplayWriter(F f) requires std::invocable<F, T &> && std::convertible_to<F, void (*)(T &)>
197 this->stateless_f_ = f; // Implicit conversion to function pointer
198 }
199
200 // For stateful lambdas and std::function (not convertible to function pointer): use std::function* (heap allocated)
201 // This handles backwards compatibility with external components
202 template<typename F>
203 DisplayWriter(F f) requires std::invocable<F, T &> &&(!std::convertible_to<F, void (*)(T &)>) : type_(LAMBDA) {
204 this->f_ = new std::function<void(T &)>(std::move(f));
205 }
206
207 // Copy constructor
208 DisplayWriter(const DisplayWriter &other) : type_(other.type_) {
209 if (type_ == LAMBDA) {
210 this->f_ = new std::function<void(T &)>(*other.f_);
211 } else if (type_ == STATELESS_LAMBDA) {
212 this->stateless_f_ = other.stateless_f_;
213 }
214 }
215
216 // Move constructor
217 DisplayWriter(DisplayWriter &&other) noexcept : type_(other.type_) {
218 if (type_ == LAMBDA) {
219 this->f_ = other.f_;
220 other.f_ = nullptr;
221 } else if (type_ == STATELESS_LAMBDA) {
222 this->stateless_f_ = other.stateless_f_;
223 }
224 other.type_ = NONE;
225 }
226
227 // Assignment operators
229 if (this != &other) {
230 this->~DisplayWriter();
231 new (this) DisplayWriter(other);
232 }
233 return *this;
234 }
235
237 if (this != &other) {
238 this->~DisplayWriter();
239 new (this) DisplayWriter(std::move(other));
240 }
241 return *this;
242 }
243
245 if (type_ == LAMBDA) {
246 delete this->f_;
247 }
248 // STATELESS_LAMBDA/NONE: no cleanup needed (function pointer or empty)
249 }
250
251 bool has_value() const { return this->type_ != NONE; }
252
253 void call(T &display) const {
254 switch (this->type_) {
255 case STATELESS_LAMBDA:
256 this->stateless_f_(display); // Direct function pointer call
257 break;
258 case LAMBDA:
259 (*this->f_)(display); // std::function call
260 break;
261 case NONE:
262 default:
263 break;
264 }
265 }
266
267 // Operator() for convenience
268 void operator()(T &display) const { this->call(display); }
269
270 // Operator* for backwards compatibility with (*writer_)(*this) pattern
271 DisplayWriter &operator*() { return *this; }
272 const DisplayWriter &operator*() const { return *this; }
273
274 protected:
275 enum : uint8_t {
279 } type_;
280
281 union {
282 std::function<void(T &)> *f_;
283 void (*stateless_f_)(T &);
284 };
285};
286
287// Type alias for Display writer - uses optimized DisplayWriter instead of std::function
289
290#define LOG_DISPLAY(prefix, type, obj) \
291 if ((obj) != nullptr) { \
292 ESP_LOGCONFIG(TAG, \
293 prefix type "\n" \
294 "%s Rotations: %d °\n" \
295 "%s Dimensions: %dpx x %dpx", \
296 prefix, (obj)->rotation_, prefix, (obj)->get_width(), (obj)->get_height()); \
297 }
298
300inline constexpr Color COLOR_OFF(0, 0, 0, 0);
302inline constexpr Color COLOR_ON(255, 255, 255, 255);
303
305 public:
306 virtual void draw(int x, int y, Display *display, Color color_on, Color color_off) = 0;
307 virtual int get_width() const = 0;
308 virtual int get_height() const = 0;
309};
310
311class BaseFont {
312 public:
313 virtual void print(int x, int y, Display *display, Color color, const char *text, Color background) = 0;
314 virtual void measure(const char *str, int *width, int *x_offset, int *baseline, int *height) = 0;
315};
316
317class Display : public PollingComponent {
318 public:
320 virtual void fill(Color color);
322 virtual void clear();
323
325 virtual int get_width() { return this->get_width_internal(); }
327 virtual int get_height() { return this->get_height_internal(); }
328
330 int get_native_width() { return this->get_width_internal(); }
332 int get_native_height() { return this->get_height_internal(); }
333
335 inline void draw_pixel_at(int x, int y) { this->draw_pixel_at(x, y, COLOR_ON); }
336
338 virtual void draw_pixel_at(int x, int y, Color color) = 0;
339
359 virtual void draw_pixels_at(int x_start, int y_start, int w, int h, const uint8_t *ptr, ColorOrder order,
360 ColorBitness bitness, bool big_endian, int x_offset, int y_offset, int x_pad);
361
363 void draw_pixels_at(int x_start, int y_start, int w, int h, const uint8_t *ptr, ColorOrder order,
364 ColorBitness bitness, bool big_endian) {
365 this->draw_pixels_at(x_start, y_start, w, h, ptr, order, bitness, big_endian, 0, 0, 0);
366 }
367
369 void line(int x1, int y1, int x2, int y2, Color color = COLOR_ON);
370
372 void line_at_angle(int x, int y, int angle, int length, Color color = COLOR_ON);
373
376 void line_at_angle(int x, int y, int angle, int start_radius, int stop_radius, Color color = COLOR_ON);
377
379 void horizontal_line(int x, int y, int width, Color color = COLOR_ON);
380
382 void vertical_line(int x, int y, int height, Color color = COLOR_ON);
383
386 void rectangle(int x1, int y1, int width, int height, Color color = COLOR_ON);
387
389 void filled_rectangle(int x1, int y1, int width, int height, Color color = COLOR_ON);
390
392 void circle(int center_x, int center_xy, int radius, Color color = COLOR_ON);
393
395 void filled_circle(int center_x, int center_y, int radius, Color color = COLOR_ON);
396
399 void filled_ring(int center_x, int center_y, int radius1, int radius2, Color color = COLOR_ON);
402 void filled_gauge(int center_x, int center_y, int radius1, int radius2, int progress, Color color = COLOR_ON);
403
405 void triangle(int x1, int y1, int x2, int y2, int x3, int y3, Color color = COLOR_ON);
406
408 void filled_triangle(int x1, int y1, int x2, int y2, int x3, int y3, Color color = COLOR_ON);
409
418 void get_regular_polygon_vertex(int vertex_id, int *vertex_x, int *vertex_y, int center_x, int center_y, int radius,
419 int edges, RegularPolygonVariation variation = VARIATION_POINTY_TOP,
420 float rotation_degrees = ROTATION_0_DEGREES);
421
428 void regular_polygon(int x, int y, int radius, int edges, RegularPolygonVariation variation = VARIATION_POINTY_TOP,
429 float rotation_degrees = ROTATION_0_DEGREES, Color color = COLOR_ON,
430 RegularPolygonDrawing drawing = DRAWING_OUTLINE);
431 void regular_polygon(int x, int y, int radius, int edges, RegularPolygonVariation variation, Color color,
432 RegularPolygonDrawing drawing = DRAWING_OUTLINE);
433 void regular_polygon(int x, int y, int radius, int edges, Color color,
434 RegularPolygonDrawing drawing = DRAWING_OUTLINE);
435
440 void filled_regular_polygon(int x, int y, int radius, int edges,
441 RegularPolygonVariation variation = VARIATION_POINTY_TOP,
442 float rotation_degrees = ROTATION_0_DEGREES, Color color = COLOR_ON);
443 void filled_regular_polygon(int x, int y, int radius, int edges, RegularPolygonVariation variation, Color color);
444 void filled_regular_polygon(int x, int y, int radius, int edges, Color color);
445
456 void print(int x, int y, BaseFont *font, Color color, TextAlign align, const char *text,
457 Color background = COLOR_OFF);
458
468 void print(int x, int y, BaseFont *font, Color color, const char *text, Color background = COLOR_OFF);
469
478 void print(int x, int y, BaseFont *font, TextAlign align, const char *text);
479
487 void print(int x, int y, BaseFont *font, const char *text);
488
500 void printf(int x, int y, BaseFont *font, Color color, Color background, TextAlign align, const char *format, ...)
501 __attribute__((format(printf, 8, 9)));
502
513 void printf(int x, int y, BaseFont *font, Color color, TextAlign align, const char *format, ...)
514 __attribute__((format(printf, 7, 8)));
515
525 void printf(int x, int y, BaseFont *font, Color color, const char *format, ...) __attribute__((format(printf, 6, 7)));
526
536 void printf(int x, int y, BaseFont *font, TextAlign align, const char *format, ...)
537 __attribute__((format(printf, 6, 7)));
538
547 void printf(int x, int y, BaseFont *font, const char *format, ...) __attribute__((format(printf, 5, 6)));
548
560 void strftime(int x, int y, BaseFont *font, Color color, Color background, TextAlign align, const char *format,
561 ESPTime time) __attribute__((format(strftime, 8, 0)));
562
573 void strftime(int x, int y, BaseFont *font, Color color, TextAlign align, const char *format, ESPTime time)
574 __attribute__((format(strftime, 7, 0)));
575
585 void strftime(int x, int y, BaseFont *font, Color color, const char *format, ESPTime time)
586 __attribute__((format(strftime, 6, 0)));
587
597 void strftime(int x, int y, BaseFont *font, TextAlign align, const char *format, ESPTime time)
598 __attribute__((format(strftime, 6, 0)));
599
608 void strftime(int x, int y, BaseFont *font, const char *format, ESPTime time) __attribute__((format(strftime, 5, 0)));
609
618 void image(int x, int y, BaseImage *image, Color color_on = COLOR_ON, Color color_off = COLOR_OFF);
619
629 void image(int x, int y, BaseImage *image, ImageAlign align, Color color_on = COLOR_ON, Color color_off = COLOR_OFF);
630
631#ifdef USE_GRAPH
639 void graph(int x, int y, graph::Graph *graph, Color color_on = COLOR_ON);
640
652 void legend(int x, int y, graph::Graph *graph, Color color_on = COLOR_ON);
653#endif // USE_GRAPH
654
655#ifdef USE_QR_CODE
663 void qr_code(int x, int y, qr_code::QrCode *qr_code, Color color_on = COLOR_ON, int scale = 1);
664#endif
665
666#ifdef USE_GRAPHICAL_DISPLAY_MENU
674 void menu(int x, int y, graphical_display_menu::GraphicalDisplayMenu *menu, int width, int height);
675#endif // USE_GRAPHICAL_DISPLAY_MENU
676
689 void get_text_bounds(int x, int y, const char *text, BaseFont *font, TextAlign align, int *x1, int *y1, int *width,
690 int *height);
691
693 void set_writer(display_writer_t &&writer);
694
695 void show_page(DisplayPage *page);
696 void show_next_page();
697 void show_prev_page();
698
699 void set_pages(std::vector<DisplayPage *> pages);
700
701 const DisplayPage *get_active_page() const { return this->page_; }
702
703 void add_on_page_change_trigger(DisplayOnPageChangeTrigger *t) { this->on_page_change_triggers_.push_back(t); }
704
706 virtual void set_rotation(DisplayRotation rotation);
707
708 // Internal method to set display auto clearing.
709 void set_auto_clear(bool auto_clear_enabled) { this->auto_clear_enabled_ = auto_clear_enabled; }
710
711 DisplayRotation get_rotation() const { return this->rotation_; }
712
717
724 void start_clipping(Rect rect);
725 void start_clipping(int16_t left, int16_t top, int16_t right, int16_t bottom) {
726 start_clipping(Rect(left, top, right - left, bottom - top));
727 };
728
734 void extend_clipping(Rect rect);
735 void extend_clipping(int16_t left, int16_t top, int16_t right, int16_t bottom) {
736 this->extend_clipping(Rect(left, top, right - left, bottom - top));
737 };
738
744 void shrink_clipping(Rect rect);
745 void shrink_clipping(uint16_t left, uint16_t top, uint16_t right, uint16_t bottom) {
746 this->shrink_clipping(Rect(left, top, right - left, bottom - top));
747 };
748
751 void end_clipping();
752
757 Rect get_clipping() const;
758
759 bool is_clipping() const { return !this->clipping_rectangle_.empty(); }
760
763 bool clip(int x, int y);
764
765 void test_card();
766 void show_test_card() { this->show_test_card_ = true; }
767
768 protected:
769 bool clamp_x_(int x, int w, int &min_x, int &max_x);
770 bool clamp_y_(int y, int h, int &min_y, int &max_y);
771 void vprintf_(int x, int y, BaseFont *font, Color color, Color background, TextAlign align, const char *format,
772 va_list arg);
773
774 void do_update_();
775 void clear_clipping_();
776
777 virtual int get_height_internal() = 0;
778 virtual int get_width_internal() = 0;
779
786 void filled_flat_side_triangle_(int x1, int y1, int x2, int y2, int x3, int y3, Color color);
787 void sort_triangle_points_by_y_(int *x1, int *y1, int *x2, int *y2, int *x3, int *y3);
788
791 DisplayPage *page_{nullptr};
792 DisplayPage *previous_page_{nullptr};
793 std::vector<DisplayOnPageChangeTrigger *> on_page_change_triggers_;
794 bool auto_clear_enabled_{true};
795 std::vector<Rect> clipping_rectangle_;
796 bool show_test_card_{false};
797};
798
800 public:
802 void show();
803 void show_next();
804 void show_prev();
805 void set_parent(Display *parent);
806 void set_prev(DisplayPage *prev);
807 void set_next(DisplayPage *next);
808 const display_writer_t &get_writer() const;
809
810 protected:
813 DisplayPage *prev_{nullptr};
814 DisplayPage *next_{nullptr};
815};
816
817template<typename... Ts> class DisplayPageShowAction : public Action<Ts...> {
818 public:
820
821 void play(const Ts &...x) override {
822 auto *page = this->page_.value(x...);
823 if (page != nullptr) {
824 page->show();
825 }
826 }
827};
828
829template<typename... Ts> class DisplayPageShowNextAction : public Action<Ts...> {
830 public:
831 DisplayPageShowNextAction(Display *buffer) : buffer_(buffer) {}
832
833 void play(const Ts &...x) override { this->buffer_->show_next_page(); }
834
836};
837
838template<typename... Ts> class DisplayPageShowPrevAction : public Action<Ts...> {
839 public:
840 DisplayPageShowPrevAction(Display *buffer) : buffer_(buffer) {}
841
842 void play(const Ts &...x) override { this->buffer_->show_prev_page(); }
843
845};
846
847template<typename... Ts> class DisplayIsDisplayingPageCondition : public Condition<Ts...> {
848 public:
849 DisplayIsDisplayingPageCondition(Display *parent) : parent_(parent) {}
850
851 void set_page(DisplayPage *page) { this->page_ = page; }
852 bool check(const Ts &...x) override { return this->parent_->get_active_page() == this->page_; }
853
854 protected:
857};
858
859class DisplayOnPageChangeTrigger : public Trigger<DisplayPage *, DisplayPage *> {
860 public:
862 void process(DisplayPage *from, DisplayPage *to);
863 void set_from(DisplayPage *p) { this->from_ = p; }
864 void set_to(DisplayPage *p) { this->to_ = p; }
865
866 protected:
867 DisplayPage *from_{nullptr};
868 DisplayPage *to_{nullptr};
869};
870
871const LogString *text_align_to_string(TextAlign textalign);
872
873} // namespace esphome::display
uint8_t h
Definition bl0906.h:2
Base class for all automation conditions.
Definition automation.h:438
This class simplifies creating components that periodically check a state.
Definition component.h:585
virtual void measure(const char *str, int *width, int *x_offset, int *baseline, int *height)=0
virtual void print(int x, int y, Display *display, Color color, const char *text, Color background)=0
virtual int get_height() const =0
virtual int get_width() const =0
virtual void draw(int x, int y, Display *display, Color color_on, Color color_off)=0
void shrink_clipping(uint16_t left, uint16_t top, uint16_t right, uint16_t bottom)
Definition display.h:745
bool is_clipping() const
Definition display.h:759
const DisplayPage * get_active_page() const
Definition display.h:701
int get_native_width()
Get the native (original) width of the display in pixels.
Definition display.h:330
virtual int get_height()
Get the calculated height of the display in pixels with rotation applied.
Definition display.h:327
void add_on_page_change_trigger(DisplayOnPageChangeTrigger *t)
Definition display.h:703
virtual int get_width()
Get the calculated width of the display in pixels with rotation applied.
Definition display.h:325
virtual void draw_pixel_at(int x, int y, Color color)=0
Set a single pixel at the specified coordinates to the given color.
void draw_pixels_at(int x_start, int y_start, int w, int h, const uint8_t *ptr, ColorOrder order, ColorBitness bitness, bool big_endian)
Convenience overload for base case where the pixels are packed into the buffer with no gaps (e....
Definition display.h:363
virtual DisplayType get_display_type()=0
Get the type of display that the buffer corresponds to.
void start_clipping(int16_t left, int16_t top, int16_t right, int16_t bottom)
Definition display.h:725
DisplayRotation get_rotation() const
Definition display.h:711
virtual int get_width_internal()=0
void draw_pixel_at(int x, int y)
Set a single pixel at the specified coordinates to default color.
Definition display.h:335
int get_native_height()
Get the native (original) height of the display in pixels.
Definition display.h:332
virtual int get_height_internal()=0
void set_auto_clear(bool auto_clear_enabled)
Definition display.h:709
std::vector< DisplayOnPageChangeTrigger * > on_page_change_triggers_
Definition display.h:793
void extend_clipping(int16_t left, int16_t top, int16_t right, int16_t bottom)
Definition display.h:735
std::vector< Rect > clipping_rectangle_
Definition display.h:795
display_writer_t writer_
Definition display.h:812
TEMPLATABLE_VALUE(DisplayPage *, page) void play(const Ts &...x) override
Definition display.h:819
void play(const Ts &...x) override
Definition display.h:833
void play(const Ts &...x) override
Definition display.h:842
Optimized display writer that uses function pointers for stateless lambdas.
Definition display.h:189
DisplayWriter(DisplayWriter &&other) noexcept
Definition display.h:217
std::function< void(T &)> * f_
Definition display.h:282
DisplayWriter & operator=(DisplayWriter &&other) noexcept
Definition display.h:236
void operator()(T &display) const
Definition display.h:268
enum esphome::display::DisplayWriter::@73 type_
DisplayWriter & operator=(const DisplayWriter &other)
Definition display.h:228
DisplayWriter(const DisplayWriter &other)
Definition display.h:208
const DisplayWriter & operator*() const
Definition display.h:272
DisplayWriter & operator*()
Definition display.h:271
void call(T &display) const
Definition display.h:253
struct @65::@66 __attribute__
Wake the main loop task from an ISR. ISR-safe.
Definition main_task.h:32
@ DISPLAY_ROTATION_0_DEGREES
Definition display.h:134
@ DISPLAY_ROTATION_270_DEGREES
Definition display.h:137
@ DISPLAY_ROTATION_180_DEGREES
Definition display.h:136
@ DISPLAY_ROTATION_90_DEGREES
Definition display.h:135
constexpr Color COLOR_ON(255, 255, 255, 255)
Turn the pixel ON.
constexpr Color COLOR_OFF(0, 0, 0, 0)
Turn the pixel OFF.
const int EDGES_TRIGON
Definition display.h:140
const int EDGES_PENTADECAGON
Definition display.h:155
const int EDGES_OCTAGON
Definition display.h:147
const int EDGES_HEXADECAGON
Definition display.h:156
const int EDGES_DODECAGON
Definition display.h:152
const int EDGES_PENTAGON
Definition display.h:144
const float ROTATION_45_DEGREES
Definition display.h:159
const int EDGES_TRIANGLE
Definition display.h:141
ImageAlign
ImageAlign is used to tell the display class how to position a image.
Definition display.h:102
const int EDGES_QUADRILATERAL
Definition display.h:143
const int EDGES_DECAGON
Definition display.h:150
const int EDGES_TETRADECAGON
Definition display.h:154
const float ROTATION_270_DEGREES
Definition display.h:162
const float ROTATION_180_DEGREES
Definition display.h:161
const int EDGES_HEPTAGON
Definition display.h:146
const int EDGES_HENDECAGON
Definition display.h:151
const int EDGES_TRIDECAGON
Definition display.h:153
TextAlign
TextAlign is used to tell the display class how to position a piece of text.
Definition display.h:52
const int EDGES_NONAGON
Definition display.h:148
const float ROTATION_90_DEGREES
Definition display.h:160
const int EDGES_ENNEAGON
Definition display.h:149
const int EDGES_TETRAGON
Definition display.h:142
const int EDGES_HEXAGON
Definition display.h:145
const float ROTATION_0_DEGREES
Definition display.h:158
const char int line
Definition log.h:74
A more user-friendly version of struct tm from time.h.
Definition time.h:23
std::string print()
uint16_t length
Definition tt21100.cpp:0
uint16_t x
Definition tt21100.cpp:5
uint16_t y
Definition tt21100.cpp:6