10 static const char *
const TAG =
"display";
19 const int32_t dx = abs(x2 - x1), sx = x1 < x2 ? 1 : -1;
20 const int32_t dy = -abs(y2 - y1), sy = y1 < y2 ? 1 : -1;
21 int32_t err = dx + dy;
25 if (x1 == x2 && y1 == y2)
45 int x1 = (start_radius * cos(angle * M_PI / 180)) + x;
46 int y1 = (start_radius * sin(angle * M_PI / 180)) + y;
47 int x2 = (stop_radius * cos(angle * M_PI / 180)) + x;
48 int y2 = (stop_radius * sin(angle * M_PI / 180)) + y;
51 this->
line(x1, y1, x2, y2, color);
55 ColorBitness bitness,
bool big_endian,
int x_offset,
int y_offset,
int x_pad) {
56 size_t line_stride = x_offset + w + x_pad;
58 for (
int y = 0;
y !=
h;
y++) {
59 size_t source_idx = (y_offset +
y) * line_stride + x_offset;
60 size_t source_idx_mod;
61 for (
int x = 0;
x != w;
x++, source_idx++) {
64 color_value = ptr[source_idx];
67 source_idx_mod = source_idx * 2;
69 color_value = (ptr[source_idx_mod] << 8) + ptr[source_idx_mod + 1];
71 color_value = ptr[source_idx_mod] + (ptr[source_idx_mod + 1] << 8);
75 source_idx_mod = source_idx * 3;
77 color_value = (ptr[source_idx_mod + 0] << 16) + (ptr[source_idx_mod + 1] << 8) + ptr[source_idx_mod + 2];
79 color_value = ptr[source_idx_mod + 0] + (ptr[source_idx_mod + 1] << 8) + (ptr[source_idx_mod + 2] << 16);
90 for (
int i = x; i < x + width; i++)
95 for (
int i = y; i < y + height; i++)
106 for (
int i = y1; i < y1 + height; i++) {
113 int err = 2 - 2 * radius;
124 if (-dx == dy && e2 <= dx) {
134 int dx = -int32_t(radius);
136 int err = 2 - 2 * radius;
144 int hline_width = 2 * (-dx) + 1;
145 this->
horizontal_line(center_x + dx, center_y + dy, hline_width, color);
146 this->
horizontal_line(center_x + dx, center_y - dy, hline_width, color);
150 if (-dx == dy && e2 <= dx) {
160 this->
line(x1, y1, x2, y2, color);
161 this->
line(x1, y1, x3, y3, color);
162 this->
line(x2, y2, x3, y3, color);
166 int x_temp = *x1, y_temp = *y1;
167 *x1 = *x2, *y1 = *y2;
168 *x2 = x_temp, *y2 = y_temp;
171 int x_temp = *x1, y_temp = *y1;
172 *x1 = *x3, *y1 = *y3;
173 *x3 = x_temp, *y3 = y_temp;
176 int x_temp = *x2, y_temp = *y2;
177 *x2 = *x3, *y2 = *y3;
178 *x3 = x_temp, *y3 = y_temp;
185 int s1_current_x = x1;
186 int s1_current_y = y1;
187 bool s1_axis_swap =
false;
188 int s1_dx = abs(x2 - x1);
189 int s1_dy = abs(y2 - y1);
190 int s1_sign_x = ((x2 - x1) >= 0) ? 1 : -1;
191 int s1_sign_y = ((y2 - y1) >= 0) ? 1 : -1;
198 int s1_error = 2 * s1_dy - s1_dx;
201 int s2_current_x = x1;
202 int s2_current_y = y1;
203 bool s2_axis_swap =
false;
204 int s2_dx = abs(x3 - x1);
205 int s2_dy = abs(y3 - y1);
206 int s2_sign_x = ((x3 - x1) >= 0) ? 1 : -1;
207 int s2_sign_y = ((y3 - y1) >= 0) ? 1 : -1;
214 int s2_error = 2 * s2_dy - s2_dx;
217 for (
int i = 0; i <= s1_dx; i++) {
218 if (s1_current_x <= s2_current_x) {
219 this->
horizontal_line(s1_current_x, s1_current_y, s2_current_x - s1_current_x + 1, color);
221 this->
horizontal_line(s2_current_x, s2_current_y, s1_current_x - s2_current_x + 1, color);
226 while (s1_error >= 0) {
228 s1_current_x += s1_sign_x;
230 s1_current_y += s1_sign_y;
232 s1_error = s1_error - 2 * s1_dx;
235 s1_current_y += s1_sign_y;
237 s1_current_x += s1_sign_x;
239 s1_error = s1_error + 2 * s1_dy;
243 while (s2_current_y != s1_current_y) {
244 while (s2_error >= 0) {
246 s2_current_x += s2_sign_x;
248 s2_current_y += s2_sign_y;
250 s2_error = s2_error - 2 * s2_dx;
253 s2_current_y += s2_sign_y;
255 s2_current_x += s2_sign_x;
257 s2_error = s2_error + 2 * s2_dy;
267 }
else if (y1 == y2) {
270 int x_temp = (int) (x1 + ((
float) (y2 - y1) / (
float) (y3 - y1)) * (x3 - x1)), y_temp = y2;
277 float rotation_degrees) {
284 float rotation_radians = rotation_degrees * PI / 180;
292 float vertex_angle = ((float) vertex_id) / edges * 2 * PI + rotation_radians;
293 *vertex_x = (int) round(cos(vertex_angle) * radius) + center_x;
294 *vertex_y = (int) round(sin(vertex_angle) * radius) + center_y;
301 int previous_vertex_x, previous_vertex_y;
302 for (
int current_vertex_id = 0; current_vertex_id <= edges; current_vertex_id++) {
303 int current_vertex_x, current_vertex_y;
305 variation, rotation_degrees);
306 if (current_vertex_id > 0) {
308 this->
filled_triangle(x, y, previous_vertex_x, previous_vertex_y, current_vertex_x, current_vertex_y, color);
310 this->
line(previous_vertex_x, previous_vertex_y, current_vertex_x, current_vertex_y, color);
313 previous_vertex_x = current_vertex_x;
314 previous_vertex_y = current_vertex_y;
326 float rotation_degrees,
Color color) {
338 int x_start, y_start;
340 this->
get_text_bounds(x, y, text, font, align, &x_start, &y_start, &width, &height);
341 font->
print(x_start, y_start,
this, color, text, background);
347 int ret = vsnprintf(buffer,
sizeof(buffer), format, arg);
349 this->
print(x, y, font, color, align, buffer, background);
384 image->
draw(x, y,
this, color_on, color_off);
394 qr_code->
draw(
this, x, y, color_on, scale);
396 #endif // USE_QR_CODE 398 #ifdef USE_GRAPHICAL_DISPLAY_MENU 400 Rect rect(x, y, width, height);
401 menu->
draw(
this, &rect);
403 #endif // USE_GRAPHICAL_DISPLAY_MENU 406 int *width,
int *height) {
407 int x_offset, baseline;
408 font->
measure(text, width, &x_offset, &baseline, height);
410 auto x_align =
TextAlign(
int(align) & 0x18);
411 auto y_align =
TextAlign(
int(align) & 0x07);
418 *x1 = x - (*width) / 2;
435 *y1 = y - (*height) / 2;
447 this->
print(x, y, font, COLOR_ON, align, text);
455 va_start(arg, format);
456 this->
vprintf_(x, y, font, color, background, align, format, arg);
461 va_start(arg, format);
462 this->
vprintf_(x, y, font, color, COLOR_OFF, align, format, arg);
467 va_start(arg, format);
473 va_start(arg, format);
474 this->
vprintf_(x, y, font, COLOR_ON, COLOR_OFF, align, format, arg);
479 va_start(arg, format);
485 for (
auto *page : pages)
486 page->set_parent(
this);
488 for (uint32_t i = 0; i < pages.size() - 1; i++) {
489 pages[i]->set_next(pages[i + 1]);
490 pages[i + 1]->set_prev(pages[i]);
492 pages[0]->set_prev(pages[pages.size() - 1]);
493 pages[pages.size() - 1]->set_next(pages[0]);
512 }
else if (this->
page_ !=
nullptr) {
520 if ((this->from_ ==
nullptr || this->from_ == from) && (this->to_ ==
nullptr || this->to_ == to))
521 this->trigger(from, to);
525 size_t ret = time.
strftime(buffer,
sizeof(buffer), format);
527 this->
print(x, y, font, color, align, buffer);
533 this->
strftime(x, y, font, COLOR_ON, align, format, time);
548 ESP_LOGE(TAG,
"clear: Clipping is not set.");
555 ESP_LOGE(TAG,
"add: Clipping is not set.");
562 ESP_LOGE(TAG,
"add: Clipping is not set.");
583 min_x = std::max(x, 0);
584 max_x = std::min(x + w, this->
get_width());
591 min_x = std::max(min_x, (
int) rect.x);
592 max_x = std::min(max_x, (
int) rect.x2());
595 return min_x < max_x;
598 min_y = std::max(y, 0);
606 min_y = std::max(min_y, (
int) rect.y);
607 max_y = std::min(max_y, (
int) rect.y2());
610 return min_y < max_y;
613 const uint8_t TESTCARD_FONT[3][8]
PROGMEM = {{0x41, 0x7F, 0x7F, 0x09, 0x19, 0x7F, 0x66, 0x00},
614 {0x1C, 0x3E, 0x63, 0x41, 0x51, 0x73, 0x72, 0x00},
615 {0x41, 0x7F, 0x7F, 0x49, 0x49, 0x7F, 0x36, 0x00}};
622 Color r(255, 0, 0), g(0, 255, 0), b(0, 0, 255);
623 image_w = std::min(w - 20, 310);
624 image_h = std::min(
h - 20, 255);
626 int shift_x = (w - image_w) / 2;
627 int shift_y = (
h - image_h) / 2;
628 int line_w = (image_w - 6) / 6;
629 int image_c = image_w / 2;
630 for (
auto i = 0; i <= image_h; i++) {
631 int c = esp_scale(i, image_h);
632 this->
horizontal_line(shift_x + 0, shift_y + i, line_w, r.fade_to_white(c));
633 this->
horizontal_line(shift_x + line_w, shift_y + i, line_w, r.fade_to_black(c));
635 this->
horizontal_line(shift_x + image_c - line_w, shift_y + i, line_w, g.fade_to_white(c));
636 this->
horizontal_line(shift_x + image_c, shift_y + i, line_w, g.fade_to_black(c));
641 this->
rectangle(shift_x, shift_y, image_w, image_h,
Color(127, 127, 0));
643 uint16_t shift_r = shift_x + line_w - (8 * 3);
644 uint16_t shift_g = shift_x + image_c - (8 * 3);
645 uint16_t shift_b = shift_x + image_w - line_w - (8 * 3);
646 shift_y =
h / 2 - (8 * 3);
647 for (
auto i = 0; i < 8; i++) {
651 for (
auto k = 0; k < 8; k++) {
652 if ((ftr & (1 << k)) != 0) {
653 this->
filled_rectangle(shift_r + (i * 6), shift_y + (k * 6), 6, 6, COLOR_OFF);
655 if ((ftg & (1 << k)) != 0) {
656 this->
filled_rectangle(shift_g + (i * 6), shift_y + (k * 6), 6, 6, COLOR_OFF);
658 if ((ftb & (1 << k)) != 0) {
659 this->
filled_rectangle(shift_b + (i * 6), shift_y + (k * 6), 6, 6, COLOR_OFF);
681 return LOG_STR(
"TOP_LEFT");
683 return LOG_STR(
"TOP_CENTER");
685 return LOG_STR(
"TOP_RIGHT");
687 return LOG_STR(
"CENTER_LEFT");
689 return LOG_STR(
"CENTER");
691 return LOG_STR(
"CENTER_RIGHT");
693 return LOG_STR(
"BASELINE_LEFT");
695 return LOG_STR(
"BASELINE_CENTER");
697 return LOG_STR(
"BASELINE_RIGHT");
699 return LOG_STR(
"BOTTOM_LEFT");
701 return LOG_STR(
"BOTTOM_CENTER");
703 return LOG_STR(
"BOTTOM_RIGHT");
705 return LOG_STR(
"UNKNOWN");
void circle(int center_x, int center_xy, int radius, Color color=COLOR_ON)
Draw the outline of a circle centered around [center_x,center_y] with the radius radius with the give...
void horizontal_line(int x, int y, int width, Color color=COLOR_ON)
Draw a horizontal line from the point [x,y] to [x+width,y] with the given color.
optional< display_writer_t > writer_
std::vector< DisplayOnPageChangeTrigger * > on_page_change_triggers_
void set_pages(std::vector< DisplayPage *> pages)
bool clamp_x_(int x, int w, int &min_x, int &max_x)
void sort_triangle_points_by_y_(int *x1, int *y1, int *x2, int *y2, int *x3, int *y3)
size_t strftime(char *buffer, size_t buffer_len, const char *format)
Convert this ESPTime struct to a null-terminated c string buffer as specified by the format argument...
void get_text_bounds(int x, int y, const char *text, BaseFont *font, TextAlign align, int *x1, int *y1, int *width, int *height)
Get the text bounds of the given string.
void set_next(DisplayPage *next)
void set_parent(Display *parent)
Color fade_to_black(uint8_t amnt)
void filled_flat_side_triangle_(int x1, int y1, int x2, int y2, int x3, int y3, Color color)
This method fills a triangle using only integer variables by using a modified bresenham algorithm...
A more user-friendly version of struct tm from time.h.
void set_rotation(DisplayRotation rotation)
Internal method to set the display rotation with.
const uint8_t TESTCARD_FONT [3][8] PROGMEM
Color fade_to_white(uint8_t amnt)
const Color COLOR_OFF(0, 0, 0, 0)
Turn the pixel OFF.
void extend_clipping(Rect rect)
Add a rectangular region to the invalidation region.
void shrink_clipping(Rect rect)
substract a rectangular region to the invalidation region
void filled_circle(int center_x, int center_y, int radius, Color color=COLOR_ON)
Fill a circle centered around [center_x,center_y] with the radius radius with the given color...
void triangle(int x1, int y1, int x2, int y2, int x3, int y3, Color color=COLOR_ON)
Draw the outline of a triangle contained between the points [x1,y1], [x2,y2] and [x3,y3] with the given color.
void filled_rectangle(int x1, int y1, int width, int height, Color color=COLOR_ON)
Fill a rectangle with the top left point at [x1,y1] and the bottom right point at [x1+width...
virtual void fill(Color color)
Fill the entire screen with the given color.
DisplayPage(display_writer_t writer)
Rect get_clipping() const
Get the current the clipping rectangle.
void qr_code(int x, int y, qr_code::QrCode *qr_code, Color color_on=COLOR_ON, int scale=1)
Draw the qr_code with the top-left corner at [x,y] to the screen.
virtual int get_width()
Get the calculated width of the display in pixels with rotation applied.
const float ROTATION_270_DEGREES
bool clamp_y_(int y, int h, int &min_y, int &max_y)
virtual void draw(int x, int y, Display *display, Color color_on, Color color_off)=0
const display_writer_t & get_writer() const
void filled_triangle(int x1, int y1, int x2, int y2, int x3, int y3, Color color=COLOR_ON)
Fill a triangle contained between the points [x1,y1], [x2,y2] and [x3,y3] with the given color...
void rectangle(int x1, int y1, int width, int height, Color color=COLOR_ON)
Draw the outline of a rectangle with the top left point at [x1,y1] and the bottom right point at [x1+...
virtual void print(int x, int y, Display *display, Color color, const char *text, Color background)=0
TextAlign
TextAlign is used to tell the display class how to position a piece of text.
std::function< void(Display &)> display_writer_t
void process(DisplayPage *from, DisplayPage *to)
void start_clipping(Rect rect)
Set the clipping rectangle for further drawing.
ImageAlign
ImageAlign is used to tell the display class how to position a image.
void clear()
Clear the entire screen by filling it with OFF pixels.
void line_at_angle(int x, int y, int angle, int length, Color color=COLOR_ON)
Draw a straight line at the given angle based on the origin [x, y] for a specified length with the gi...
void print(int x, int y, BaseFont *font, Color color, TextAlign align, const char *text, Color background=COLOR_OFF)
Print text with the anchor point at [x,y] with font.
void draw_legend(display::Display *buff, uint16_t x_offset, uint16_t y_offset, Color color)
const float ROTATION_0_DEGREES
void line(int x1, int y1, int x2, int y2, Color color=COLOR_ON)
Draw a straight line from the point [x1,y1] to [x2,y2] with the given color.
void legend(int x, int y, graph::Graph *graph, Color color_on=COLOR_ON)
Draw the legend for graph with the top-left corner at [x,y] to the screen.
void menu(int x, int y, graphical_display_menu::GraphicalDisplayMenu *menu, int width, int height)
void draw(display::Display *buff, uint16_t x_offset, uint16_t y_offset, Color color, int scale)
void filled_regular_polygon(int x, int y, int radius, int edges, RegularPolygonVariation variation=VARIATION_POINTY_TOP, float rotation_degrees=ROTATION_0_DEGREES, Color color=COLOR_ON)
Fill a regular polygon inscribed in the circle centered on [x,y] with the given radius and color...
void vprintf_(int x, int y, BaseFont *font, Color color, Color background, TextAlign align, const char *format, va_list arg)
DisplayRotation rotation_
void end_clipping()
Reset the invalidation region.
virtual int get_height()
Get the calculated height of the display in pixels with rotation applied.
DisplayPage * previous_page_
void vertical_line(int x, int y, int height, Color color=COLOR_ON)
Draw a vertical line from the point [x,y] to [x,y+width] with the given color.
uint8_t progmem_read_byte(const uint8_t *addr)
const Color COLOR_ON(255, 255, 255, 255)
Turn the pixel ON.
const LogString * text_align_to_string(TextAlign textalign)
virtual DisplayType get_display_type()=0
Get the type of display that the buffer corresponds to.
virtual int get_width() const =0
bool clip(int x, int y)
Check if pixel is within region of display.
void void void void void void strftime(int x, int y, BaseFont *font, Color color, TextAlign align, const char *format, ESPTime time) __attribute__((format(strftime
Evaluate the strftime-format format and print the result with the anchor point at [x...
void draw_pixel_at(int x, int y)
Set a single pixel at the specified coordinates to default color.
void printf(int x, int y, BaseFont *font, Color color, Color background, TextAlign align, const char *format,...) __attribute__((format(printf
Evaluate the printf-format format and print the result with the anchor point at [x,y] with font.
Implementation of SPI Controller mode.
static Color to_color(uint32_t colorcode, ColorOrder color_order, ColorBitness color_bitness=ColorBitness::COLOR_BITNESS_888, bool right_bit_aligned=true)
void draw(display::Display *buff, uint16_t x_offset, uint16_t y_offset, Color color)
void get_regular_polygon_vertex(int vertex_id, int *vertex_x, int *vertex_y, int center_x, int center_y, int radius, int edges, RegularPolygonVariation variation=VARIATION_POINTY_TOP, float rotation_degrees=ROTATION_0_DEGREES)
Get the specified vertex (x,y) coordinates for the regular polygon inscribed in the circle centered o...
virtual void measure(const char *str, int *width, int *x_offset, int *baseline, int *height)=0
std::vector< Rect > clipping_rectangle_
void set_writer(display_writer_t &&writer)
Internal method to set the display writer lambda.
void graph(int x, int y, graph::Graph *graph, Color color_on=COLOR_ON)
Draw the graph with the top-left corner at [x,y] to the screen.
void void void void void void void void void void image(int x, int y, BaseImage *image, Color color_on=COLOR_ON, Color color_off=COLOR_OFF)
Draw the image with the top-left corner at [x,y] to the screen.
void show_page(DisplayPage *page)
void regular_polygon(int x, int y, int radius, int edges, RegularPolygonVariation variation=VARIATION_POINTY_TOP, float rotation_degrees=ROTATION_0_DEGREES, Color color=COLOR_ON, RegularPolygonDrawing drawing=DRAWING_OUTLINE)
Draw the outline of a regular polygon inscribed in the circle centered on [x,y] with the given radius...
virtual 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, int x_offset, int y_offset, int x_pad)
Given an array of pixels encoded in the nominated format, draw these into the display's buffer...
void set_prev(DisplayPage *prev)
virtual int get_height() const =0