ESPHome 2025.12.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 {
27namespace display {
28
79
127
133
140
141const int EDGES_TRIGON = 3;
142const int EDGES_TRIANGLE = 3;
143const int EDGES_TETRAGON = 4;
145const int EDGES_PENTAGON = 5;
146const int EDGES_HEXAGON = 6;
147const int EDGES_HEPTAGON = 7;
148const int EDGES_OCTAGON = 8;
149const int EDGES_NONAGON = 9;
150const int EDGES_ENNEAGON = 9;
151const int EDGES_DECAGON = 10;
152const int EDGES_HENDECAGON = 11;
153const int EDGES_DODECAGON = 12;
154const int EDGES_TRIDECAGON = 13;
155const int EDGES_TETRADECAGON = 14;
156const int EDGES_PENTADECAGON = 15;
157const int EDGES_HEXADECAGON = 16;
158
159const float ROTATION_0_DEGREES = 0.0;
160const float ROTATION_45_DEGREES = 45.0;
161const float ROTATION_90_DEGREES = 90.0;
162const float ROTATION_180_DEGREES = 180.0;
163const float ROTATION_270_DEGREES = 270.0;
164
169
174
175class Display;
176class DisplayPage;
177class DisplayOnPageChangeTrigger;
178
190template<typename T> class DisplayWriter {
191 public:
193
194 // For stateless lambdas (convertible to function pointer): use function pointer (4 bytes)
195 template<typename F>
196 DisplayWriter(F f) requires std::invocable<F, T &> && std::convertible_to<F, void (*)(T &)>
198 this->stateless_f_ = f; // Implicit conversion to function pointer
199 }
200
201 // For stateful lambdas and std::function (not convertible to function pointer): use std::function* (heap allocated)
202 // This handles backwards compatibility with external components
203 template<typename F>
204 DisplayWriter(F f) requires std::invocable<F, T &> &&(!std::convertible_to<F, void (*)(T &)>) : type_(LAMBDA) {
205 this->f_ = new std::function<void(T &)>(std::move(f));
206 }
207
208 // Copy constructor
209 DisplayWriter(const DisplayWriter &other) : type_(other.type_) {
210 if (type_ == LAMBDA) {
211 this->f_ = new std::function<void(T &)>(*other.f_);
212 } else if (type_ == STATELESS_LAMBDA) {
213 this->stateless_f_ = other.stateless_f_;
214 }
215 }
216
217 // Move constructor
218 DisplayWriter(DisplayWriter &&other) noexcept : type_(other.type_) {
219 if (type_ == LAMBDA) {
220 this->f_ = other.f_;
221 other.f_ = nullptr;
222 } else if (type_ == STATELESS_LAMBDA) {
223 this->stateless_f_ = other.stateless_f_;
224 }
225 other.type_ = NONE;
226 }
227
228 // Assignment operators
230 if (this != &other) {
231 this->~DisplayWriter();
232 new (this) DisplayWriter(other);
233 }
234 return *this;
235 }
236
238 if (this != &other) {
239 this->~DisplayWriter();
240 new (this) DisplayWriter(std::move(other));
241 }
242 return *this;
243 }
244
246 if (type_ == LAMBDA) {
247 delete this->f_;
248 }
249 // STATELESS_LAMBDA/NONE: no cleanup needed (function pointer or empty)
250 }
251
252 bool has_value() const { return this->type_ != NONE; }
253
254 void call(T &display) const {
255 switch (this->type_) {
256 case STATELESS_LAMBDA:
257 this->stateless_f_(display); // Direct function pointer call
258 break;
259 case LAMBDA:
260 (*this->f_)(display); // std::function call
261 break;
262 case NONE:
263 default:
264 break;
265 }
266 }
267
268 // Operator() for convenience
269 void operator()(T &display) const { this->call(display); }
270
271 // Operator* for backwards compatibility with (*writer_)(*this) pattern
272 DisplayWriter &operator*() { return *this; }
273 const DisplayWriter &operator*() const { return *this; }
274
275 protected:
276 enum : uint8_t {
280 } type_;
281
282 union {
283 std::function<void(T &)> *f_;
284 void (*stateless_f_)(T &);
285 };
286};
287
288// Type alias for Display writer - uses optimized DisplayWriter instead of std::function
290
291#define LOG_DISPLAY(prefix, type, obj) \
292 if ((obj) != nullptr) { \
293 ESP_LOGCONFIG(TAG, \
294 prefix type "\n" \
295 "%s Rotations: %d °\n" \
296 "%s Dimensions: %dpx x %dpx", \
297 prefix, (obj)->rotation_, prefix, (obj)->get_width(), (obj)->get_height()); \
298 }
299
301extern const Color COLOR_OFF;
303extern const Color COLOR_ON;
304
306 public:
307 virtual void draw(int x, int y, Display *display, Color color_on, Color color_off) = 0;
308 virtual int get_width() const = 0;
309 virtual int get_height() const = 0;
310};
311
312class BaseFont {
313 public:
314 virtual void print(int x, int y, Display *display, Color color, const char *text, Color background) = 0;
315 virtual void measure(const char *str, int *width, int *x_offset, int *baseline, int *height) = 0;
316};
317
318class Display : public PollingComponent {
319 public:
321 virtual void fill(Color color);
323 virtual void clear();
324
326 virtual int get_width() { return this->get_width_internal(); }
328 virtual int get_height() { return this->get_height_internal(); }
329
331 int get_native_width() { return this->get_width_internal(); }
333 int get_native_height() { return this->get_height_internal(); }
334
336 inline void draw_pixel_at(int x, int y) { this->draw_pixel_at(x, y, COLOR_ON); }
337
339 virtual void draw_pixel_at(int x, int y, Color color) = 0;
340
360 virtual void draw_pixels_at(int x_start, int y_start, int w, int h, const uint8_t *ptr, ColorOrder order,
361 ColorBitness bitness, bool big_endian, int x_offset, int y_offset, int x_pad);
362
364 void draw_pixels_at(int x_start, int y_start, int w, int h, const uint8_t *ptr, ColorOrder order,
365 ColorBitness bitness, bool big_endian) {
366 this->draw_pixels_at(x_start, y_start, w, h, ptr, order, bitness, big_endian, 0, 0, 0);
367 }
368
370 void line(int x1, int y1, int x2, int y2, Color color = COLOR_ON);
371
373 void line_at_angle(int x, int y, int angle, int length, Color color = COLOR_ON);
374
377 void line_at_angle(int x, int y, int angle, int start_radius, int stop_radius, Color color = COLOR_ON);
378
380 void horizontal_line(int x, int y, int width, Color color = COLOR_ON);
381
383 void vertical_line(int x, int y, int height, Color color = COLOR_ON);
384
387 void rectangle(int x1, int y1, int width, int height, Color color = COLOR_ON);
388
390 void filled_rectangle(int x1, int y1, int width, int height, Color color = COLOR_ON);
391
393 void circle(int center_x, int center_xy, int radius, Color color = COLOR_ON);
394
396 void filled_circle(int center_x, int center_y, int radius, Color color = COLOR_ON);
397
400 void filled_ring(int center_x, int center_y, int radius1, int radius2, Color color = COLOR_ON);
403 void filled_gauge(int center_x, int center_y, int radius1, int radius2, int progress, Color color = COLOR_ON);
404
406 void triangle(int x1, int y1, int x2, int y2, int x3, int y3, Color color = COLOR_ON);
407
409 void filled_triangle(int x1, int y1, int x2, int y2, int x3, int y3, Color color = COLOR_ON);
410
419 void get_regular_polygon_vertex(int vertex_id, int *vertex_x, int *vertex_y, int center_x, int center_y, int radius,
420 int edges, RegularPolygonVariation variation = VARIATION_POINTY_TOP,
421 float rotation_degrees = ROTATION_0_DEGREES);
422
429 void regular_polygon(int x, int y, int radius, int edges, RegularPolygonVariation variation = VARIATION_POINTY_TOP,
430 float rotation_degrees = ROTATION_0_DEGREES, Color color = COLOR_ON,
431 RegularPolygonDrawing drawing = DRAWING_OUTLINE);
432 void regular_polygon(int x, int y, int radius, int edges, RegularPolygonVariation variation, Color color,
433 RegularPolygonDrawing drawing = DRAWING_OUTLINE);
434 void regular_polygon(int x, int y, int radius, int edges, Color color,
435 RegularPolygonDrawing drawing = DRAWING_OUTLINE);
436
441 void filled_regular_polygon(int x, int y, int radius, int edges,
442 RegularPolygonVariation variation = VARIATION_POINTY_TOP,
443 float rotation_degrees = ROTATION_0_DEGREES, Color color = COLOR_ON);
444 void filled_regular_polygon(int x, int y, int radius, int edges, RegularPolygonVariation variation, Color color);
445 void filled_regular_polygon(int x, int y, int radius, int edges, Color color);
446
457 void print(int x, int y, BaseFont *font, Color color, TextAlign align, const char *text,
458 Color background = COLOR_OFF);
459
469 void print(int x, int y, BaseFont *font, Color color, const char *text, Color background = COLOR_OFF);
470
479 void print(int x, int y, BaseFont *font, TextAlign align, const char *text);
480
488 void print(int x, int y, BaseFont *font, const char *text);
489
501 void printf(int x, int y, BaseFont *font, Color color, Color background, TextAlign align, const char *format, ...)
502 __attribute__((format(printf, 8, 9)));
503
514 void printf(int x, int y, BaseFont *font, Color color, TextAlign align, const char *format, ...)
515 __attribute__((format(printf, 7, 8)));
516
526 void printf(int x, int y, BaseFont *font, Color color, const char *format, ...) __attribute__((format(printf, 6, 7)));
527
537 void printf(int x, int y, BaseFont *font, TextAlign align, const char *format, ...)
538 __attribute__((format(printf, 6, 7)));
539
548 void printf(int x, int y, BaseFont *font, const char *format, ...) __attribute__((format(printf, 5, 6)));
549
561 void strftime(int x, int y, BaseFont *font, Color color, Color background, TextAlign align, const char *format,
562 ESPTime time) __attribute__((format(strftime, 8, 0)));
563
574 void strftime(int x, int y, BaseFont *font, Color color, TextAlign align, const char *format, ESPTime time)
575 __attribute__((format(strftime, 7, 0)));
576
586 void strftime(int x, int y, BaseFont *font, Color color, const char *format, ESPTime time)
587 __attribute__((format(strftime, 6, 0)));
588
598 void strftime(int x, int y, BaseFont *font, TextAlign align, const char *format, ESPTime time)
599 __attribute__((format(strftime, 6, 0)));
600
609 void strftime(int x, int y, BaseFont *font, const char *format, ESPTime time) __attribute__((format(strftime, 5, 0)));
610
619 void image(int x, int y, BaseImage *image, Color color_on = COLOR_ON, Color color_off = COLOR_OFF);
620
630 void image(int x, int y, BaseImage *image, ImageAlign align, Color color_on = COLOR_ON, Color color_off = COLOR_OFF);
631
632#ifdef USE_GRAPH
640 void graph(int x, int y, graph::Graph *graph, Color color_on = COLOR_ON);
641
653 void legend(int x, int y, graph::Graph *graph, Color color_on = COLOR_ON);
654#endif // USE_GRAPH
655
656#ifdef USE_QR_CODE
664 void qr_code(int x, int y, qr_code::QrCode *qr_code, Color color_on = COLOR_ON, int scale = 1);
665#endif
666
667#ifdef USE_GRAPHICAL_DISPLAY_MENU
675 void menu(int x, int y, graphical_display_menu::GraphicalDisplayMenu *menu, int width, int height);
676#endif // USE_GRAPHICAL_DISPLAY_MENU
677
690 void get_text_bounds(int x, int y, const char *text, BaseFont *font, TextAlign align, int *x1, int *y1, int *width,
691 int *height);
692
694 void set_writer(display_writer_t &&writer);
695
696 void show_page(DisplayPage *page);
697 void show_next_page();
698 void show_prev_page();
699
700 void set_pages(std::vector<DisplayPage *> pages);
701
702 const DisplayPage *get_active_page() const { return this->page_; }
703
704 void add_on_page_change_trigger(DisplayOnPageChangeTrigger *t) { this->on_page_change_triggers_.push_back(t); }
705
707 void set_rotation(DisplayRotation rotation);
708
709 // Internal method to set display auto clearing.
710 void set_auto_clear(bool auto_clear_enabled) { this->auto_clear_enabled_ = auto_clear_enabled; }
711
712 DisplayRotation get_rotation() const { return this->rotation_; }
713
718
725 void start_clipping(Rect rect);
726 void start_clipping(int16_t left, int16_t top, int16_t right, int16_t bottom) {
727 start_clipping(Rect(left, top, right - left, bottom - top));
728 };
729
735 void extend_clipping(Rect rect);
736 void extend_clipping(int16_t left, int16_t top, int16_t right, int16_t bottom) {
737 this->extend_clipping(Rect(left, top, right - left, bottom - top));
738 };
739
745 void shrink_clipping(Rect rect);
746 void shrink_clipping(uint16_t left, uint16_t top, uint16_t right, uint16_t bottom) {
747 this->shrink_clipping(Rect(left, top, right - left, bottom - top));
748 };
749
752 void end_clipping();
753
758 Rect get_clipping() const;
759
760 bool is_clipping() const { return !this->clipping_rectangle_.empty(); }
761
764 bool clip(int x, int y);
765
766 void test_card();
767 void show_test_card() { this->show_test_card_ = true; }
768
769 protected:
770 bool clamp_x_(int x, int w, int &min_x, int &max_x);
771 bool clamp_y_(int y, int h, int &min_y, int &max_y);
772 void vprintf_(int x, int y, BaseFont *font, Color color, Color background, TextAlign align, const char *format,
773 va_list arg);
774
775 void do_update_();
776 void clear_clipping_();
777
778 virtual int get_height_internal() = 0;
779 virtual int get_width_internal() = 0;
780
787 void filled_flat_side_triangle_(int x1, int y1, int x2, int y2, int x3, int y3, Color color);
788 void sort_triangle_points_by_y_(int *x1, int *y1, int *x2, int *y2, int *x3, int *y3);
789
792 DisplayPage *page_{nullptr};
793 DisplayPage *previous_page_{nullptr};
794 std::vector<DisplayOnPageChangeTrigger *> on_page_change_triggers_;
795 bool auto_clear_enabled_{true};
796 std::vector<Rect> clipping_rectangle_;
797 bool show_test_card_{false};
798};
799
801 public:
803 void show();
804 void show_next();
805 void show_prev();
806 void set_parent(Display *parent);
807 void set_prev(DisplayPage *prev);
808 void set_next(DisplayPage *next);
809 const display_writer_t &get_writer() const;
810
811 protected:
814 DisplayPage *prev_{nullptr};
815 DisplayPage *next_{nullptr};
816};
817
818template<typename... Ts> class DisplayPageShowAction : public Action<Ts...> {
819 public:
821
822 void play(const Ts &...x) override {
823 auto *page = this->page_.value(x...);
824 if (page != nullptr) {
825 page->show();
826 }
827 }
828};
829
830template<typename... Ts> class DisplayPageShowNextAction : public Action<Ts...> {
831 public:
832 DisplayPageShowNextAction(Display *buffer) : buffer_(buffer) {}
833
834 void play(const Ts &...x) override { this->buffer_->show_next_page(); }
835
837};
838
839template<typename... Ts> class DisplayPageShowPrevAction : public Action<Ts...> {
840 public:
841 DisplayPageShowPrevAction(Display *buffer) : buffer_(buffer) {}
842
843 void play(const Ts &...x) override { this->buffer_->show_prev_page(); }
844
846};
847
848template<typename... Ts> class DisplayIsDisplayingPageCondition : public Condition<Ts...> {
849 public:
850 DisplayIsDisplayingPageCondition(Display *parent) : parent_(parent) {}
851
852 void set_page(DisplayPage *page) { this->page_ = page; }
853 bool check(const Ts &...x) override { return this->parent_->get_active_page() == this->page_; }
854
855 protected:
858};
859
860class DisplayOnPageChangeTrigger : public Trigger<DisplayPage *, DisplayPage *> {
861 public:
863 void process(DisplayPage *from, DisplayPage *to);
864 void set_from(DisplayPage *p) { this->from_ = p; }
865 void set_to(DisplayPage *p) { this->to_ = p; }
866
867 protected:
868 DisplayPage *from_{nullptr};
869 DisplayPage *to_{nullptr};
870};
871
872const LogString *text_align_to_string(TextAlign textalign);
873
874} // namespace display
875} // namespace esphome
uint8_t h
Definition bl0906.h:2
Base class for all automation conditions.
Definition automation.h:148
This class simplifies creating components that periodically check a state.
Definition component.h:437
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:746
bool is_clipping() const
Definition display.h:760
const DisplayPage * get_active_page() const
Definition display.h:702
int get_native_width()
Get the native (original) width of the display in pixels.
Definition display.h:331
virtual int get_height()
Get the calculated height of the display in pixels with rotation applied.
Definition display.h:328
void add_on_page_change_trigger(DisplayOnPageChangeTrigger *t)
Definition display.h:704
virtual int get_width()
Get the calculated width of the display in pixels with rotation applied.
Definition display.h:326
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:364
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:726
DisplayRotation get_rotation() const
Definition display.h:712
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:336
int get_native_height()
Get the native (original) height of the display in pixels.
Definition display.h:333
virtual int get_height_internal()=0
void set_auto_clear(bool auto_clear_enabled)
Definition display.h:710
std::vector< DisplayOnPageChangeTrigger * > on_page_change_triggers_
Definition display.h:794
void extend_clipping(int16_t left, int16_t top, int16_t right, int16_t bottom)
Definition display.h:736
std::vector< Rect > clipping_rectangle_
Definition display.h:796
display_writer_t writer_
Definition display.h:813
TEMPLATABLE_VALUE(DisplayPage *, page) void play(const Ts &...x) override
Definition display.h:820
void play(const Ts &...x) override
Definition display.h:834
void play(const Ts &...x) override
Definition display.h:843
Optimized display writer that uses function pointers for stateless lambdas.
Definition display.h:190
DisplayWriter(DisplayWriter &&other) noexcept
Definition display.h:218
std::function< void(T &)> * f_
Definition display.h:283
DisplayWriter & operator=(DisplayWriter &&other) noexcept
Definition display.h:237
void operator()(T &display) const
Definition display.h:269
enum esphome::display::DisplayWriter::@73 type_
DisplayWriter & operator=(const DisplayWriter &other)
Definition display.h:229
DisplayWriter(const DisplayWriter &other)
Definition display.h:209
const DisplayWriter & operator*() const
Definition display.h:273
DisplayWriter & operator*()
Definition display.h:272
void call(T &display) const
Definition display.h:254
struct @65::@66 __attribute__
@ DISPLAY_ROTATION_0_DEGREES
Definition display.h:135
@ DISPLAY_ROTATION_270_DEGREES
Definition display.h:138
@ DISPLAY_ROTATION_180_DEGREES
Definition display.h:137
@ DISPLAY_ROTATION_90_DEGREES
Definition display.h:136
const Color COLOR_ON(255, 255, 255, 255)
Turn the pixel ON.
Definition display.h:303
const int EDGES_TRIGON
Definition display.h:141
const int EDGES_PENTADECAGON
Definition display.h:156
const int EDGES_OCTAGON
Definition display.h:148
const int EDGES_HEXADECAGON
Definition display.h:157
const int EDGES_DODECAGON
Definition display.h:153
const int EDGES_PENTAGON
Definition display.h:145
const float ROTATION_45_DEGREES
Definition display.h:160
const int EDGES_TRIANGLE
Definition display.h:142
ImageAlign
ImageAlign is used to tell the display class how to position a image.
Definition display.h:103
const int EDGES_QUADRILATERAL
Definition display.h:144
const int EDGES_DECAGON
Definition display.h:151
const int EDGES_TETRADECAGON
Definition display.h:155
const float ROTATION_270_DEGREES
Definition display.h:163
const float ROTATION_180_DEGREES
Definition display.h:162
const int EDGES_HEPTAGON
Definition display.h:147
const int EDGES_HENDECAGON
Definition display.h:152
const int EDGES_TRIDECAGON
Definition display.h:154
TextAlign
TextAlign is used to tell the display class how to position a piece of text.
Definition display.h:53
const int EDGES_NONAGON
Definition display.h:149
const float ROTATION_90_DEGREES
Definition display.h:161
const int EDGES_ENNEAGON
Definition display.h:150
const Color COLOR_OFF(0, 0, 0, 0)
Turn the pixel OFF.
Definition display.h:301
const int EDGES_TETRAGON
Definition display.h:143
const int EDGES_HEXAGON
Definition display.h:146
const float ROTATION_0_DEGREES
Definition display.h:159
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7
A more user-friendly version of struct tm from time.h.
Definition time.h:15
std::string print()
uint16_t length
Definition tt21100.cpp:0
uint16_t x
Definition tt21100.cpp:5
uint16_t y
Definition tt21100.cpp:6