#include "dow.h" bool firstRender = true; uint16_t reRenders = 0; int16_t tbx, tby; uint16_t tbw, tbh; const GFXfont* DOW_FONTS[] = { &FreeSans12pt7b, &FreeSans24pt7b, &FiraCode_Bold62pt7b, &FreeSans9pt7b }; void dow_apply_font(GxEPD2_BW &display, uint8_t font) { if (font > 3) { font = 3; } display.setFont(DOW_FONTS[font]); } void dow_get_text_item_rect(GxEPD2_BW &display, dow_item_t *item, bool forText, int *rx, int *ry, int *rw, int *rh) { dow_apply_font(display, item->font); display.getTextBounds(item->contents, 0, 0, &tbx, &tby, &tbw, &tbh); // bool debug = item->contents.equals("Srazky"); int x = item->x; int y = item->y; int w = tbw; int h = tbh; switch (item->horizontalAlign) { case ITEM_ALIGN_CENTER: { x -= round((double)w / 2); break; } case ITEM_ALIGN_END: { x -= w; break; } } switch (item->verticalAlign) { case ITEM_ALIGN_CENTER: { y -= (h + tby); y += round((double)h / 2); break; } case ITEM_ALIGN_START: { y -= (h + tby); y += h; break; } } if (!forText) { display.getTextBounds(item->contents, x, y, &tbx, &tby, &tbw, &tbh); *rx = tbx; *ry = tby; *rw = tbw; *rh = tbh; return; } *rx = x; *ry = y; *rw = w; *rh = h; /* if (debug) { Serial.print(x); Serial.print(", "); Serial.print(y); Serial.print(", "); Serial.print(w); Serial.print(", "); Serial.print(h); Serial.print(", tbx:"); Serial.print(tbx); Serial.print(", tby:"); Serial.print(tby); Serial.print(", tbw:"); Serial.print(tbw); Serial.print(", tbh:"); Serial.println(tbh); } */ } void dow_get_item_rect(GxEPD2_BW &display, dow_item_t *item, int *rx, int *ry, int *rw, int *rh) { switch (item->type) { case ITEM_TYPE_TEXT: { dow_get_text_item_rect(display, item, false, rx, ry, rw, rh); break; } case ITEM_TYPE_LINE: { int minX = min(item->x, item->x2); int minY = min(item->y, item->y2); int maxX = max(item->x, item->x2); int maxY = max(item->y, item->y2); *rx = minX; *ry = minY; *rw = (maxX - minX); *rh = (maxY - minY); break; } case ITEM_TYPE_CIRCLE: { *rx = item->x - item->radius; *ry = item->y - item->radius; *rw = item->radius * 2; *rh = item->radius * 2; break; } case ITEM_TYPE_CIRCLE_FILL: { *rx = item->x - item->radius; *ry = item->y - item->radius; *rw = item->radius * 2; *rh = item->radius * 2; break; } case ITEM_TYPE_RECT: { *rx = item->x; *ry = item->y; *rw = item->x2; *rh = item->y2; break; } case ITEM_TYPE_RECT_FILL: { *rx = item->x; *ry = item->y; *rw = item->x2; *rh = item->y2; break; } } } void dow_render_text_item(GxEPD2_BW &display, dow_item_t *item) { int x, y, w, h; dow_get_text_item_rect(display, item, true, &x, &y, &w, &h); display.setCursor(x, y); display.print(item->contents); } void dow_render_rectangle_item(GxEPD2_BW &display, dow_item_t *item) { display.drawRect(item->x, item->y, item->x2, item->y2, GxEPD_BLACK); } void dow_render_filled_rectangle_item(GxEPD2_BW &display, dow_item_t *item) { display.fillRect(item->x, item->y, item->x2, item->y2, GxEPD_BLACK); } void dow_render_circle_item(GxEPD2_BW &display, dow_item_t *item) { display.drawCircle(item->x, item->y, item->radius, GxEPD_BLACK); } void dow_render_filled_circle_item(GxEPD2_BW &display, dow_item_t *item) { display.fillCircle(item->x, item->y, item->radius, GxEPD_BLACK); } void dow_render_line_item(GxEPD2_BW &display, dow_item_t *item) { display.drawLine(item->x, item->y, item->x2, item->y2, GxEPD_BLACK); } void dow_render(GxEPD2_BW &display, std::vector &data) { bool needsFullRender = reRenders > 5*60*6; if (needsFullRender || firstRender) { display.setFullWindow(); display.setRotation(0); display.setTextColor(GxEPD_BLACK); display.firstPage(); reRenders = 0; firstRender = false; } else { display.setPartialWindow(0, 0, display.width(), display.height()); display.setRotation(0); display.firstPage(); reRenders++; } do { display.fillScreen(GxEPD_WHITE); display.setTextColor(GxEPD_BLACK); for (int i = 0; i < data.size(); i++) { dow_item_t *item = &data[i]; switch (item->type) { case ITEM_TYPE_TEXT: { dow_render_text_item(display, item); break; } case ITEM_TYPE_CIRCLE: { dow_render_circle_item(display, item); break; } case ITEM_TYPE_CIRCLE_FILL: { dow_render_filled_circle_item(display, item); break; } case ITEM_TYPE_RECT: { dow_render_rectangle_item(display, item); break; } case ITEM_TYPE_RECT_FILL: { dow_render_filled_rectangle_item(display, item); break; } case ITEM_TYPE_LINE: { dow_render_line_item(display, item); break; } } /* DEBUG: Draw bounding box int x1, y1, w1, h1; dow_get_text_item_rect(display, item, false, &x1, &y1, &w1, &h1); display.drawRect(x1, y1, w1, h1, GxEPD_BLACK); */ } } while (display.nextPage()); }