247 lines
5.3 KiB
C++
247 lines
5.3 KiB
C++
|
|
#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<GxEPD2_583_GDEQ0583T31, GxEPD2_583_GDEQ0583T31::HEIGHT> &display, uint8_t font)
|
||
|
|
{
|
||
|
|
if (font > 3) {
|
||
|
|
font = 3;
|
||
|
|
}
|
||
|
|
|
||
|
|
display.setFont(DOW_FONTS[font]);
|
||
|
|
}
|
||
|
|
|
||
|
|
void dow_get_text_item_rect(GxEPD2_BW<GxEPD2_583_GDEQ0583T31, GxEPD2_583_GDEQ0583T31::HEIGHT> &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);
|
||
|
|
|
||
|
|
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 += round((double)h / 2);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
|
||
|
|
case ITEM_ALIGN_START:
|
||
|
|
{
|
||
|
|
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;
|
||
|
|
}
|
||
|
|
|
||
|
|
void dow_get_item_rect(GxEPD2_BW<GxEPD2_583_GDEQ0583T31, GxEPD2_583_GDEQ0583T31::HEIGHT> &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<GxEPD2_583_GDEQ0583T31, GxEPD2_583_GDEQ0583T31::HEIGHT> &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<GxEPD2_583_GDEQ0583T31, GxEPD2_583_GDEQ0583T31::HEIGHT> &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<GxEPD2_583_GDEQ0583T31, GxEPD2_583_GDEQ0583T31::HEIGHT> &display, dow_item_t *item)
|
||
|
|
{
|
||
|
|
display.fillRect(item->x, item->y, item->x2, item->y2, GxEPD_BLACK);
|
||
|
|
}
|
||
|
|
|
||
|
|
void dow_render_circle_item(GxEPD2_BW<GxEPD2_583_GDEQ0583T31, GxEPD2_583_GDEQ0583T31::HEIGHT> &display, dow_item_t *item)
|
||
|
|
{
|
||
|
|
display.drawCircle(item->x, item->y, item->radius, GxEPD_BLACK);
|
||
|
|
}
|
||
|
|
|
||
|
|
void dow_render_filled_circle_item(GxEPD2_BW<GxEPD2_583_GDEQ0583T31, GxEPD2_583_GDEQ0583T31::HEIGHT> &display, dow_item_t *item)
|
||
|
|
{
|
||
|
|
display.fillCircle(item->x, item->y, item->radius, GxEPD_BLACK);
|
||
|
|
}
|
||
|
|
|
||
|
|
void dow_render_line_item(GxEPD2_BW<GxEPD2_583_GDEQ0583T31, GxEPD2_583_GDEQ0583T31::HEIGHT> &display, dow_item_t *item)
|
||
|
|
{
|
||
|
|
display.drawLine(item->x, item->y, item->x2, item->y2, GxEPD_BLACK);
|
||
|
|
}
|
||
|
|
|
||
|
|
void dow_render(GxEPD2_BW<GxEPD2_583_GDEQ0583T31, GxEPD2_583_GDEQ0583T31::HEIGHT> &display, std::vector<dow_item_t> &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());
|
||
|
|
}
|