dow/firmware/dow.cpp

249 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 += tby;
y += round((double)h / 2);
break;
}
case ITEM_ALIGN_START:
{
y += 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;
}
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());
}