Use new fontrenderer

This commit is contained in:
2023-01-12 23:21:21 +01:00
parent 98fb5746c6
commit c7bba7daa1
14 changed files with 114 additions and 255 deletions

View File

@ -47,8 +47,6 @@ set(headers
src/textinterface.h
src/textwithvaluehelper.h
src/tftcolors.h
src/tftespiimpl.h
src/tftinterface.h
src/titleinterface.h
src/visibleinterface.h
src/widgets/graph.h
@ -98,6 +96,8 @@ set(dependencies
espwifistack
fmt
TFT_eSPI
esptftlib
espfontlib
)
idf_component_register(

View File

@ -2,6 +2,7 @@
// 3rdparty lib includes
#include <fmt/core.h>
#include <fontrenderer.h>
// local includes
#include "tftinterface.h"
@ -12,21 +13,23 @@ void ChangeValueDisplayInterface::initScreen(TftInterface &tft)
{
Base::initScreen(tft);
FontRenderer fontRenderer{tft};
tft.drawRoundRect(35, 65, 190, 65, 8, TFT_WHITE);
m_valueLabel.start(tft);
if (espgui::isLandscape(tft))
{
tft.drawString("Change value and press", 10, 152, TFT_WHITE, TFT_BLACK, 4);
tft.drawString("button to confirm and", 10, 177, TFT_WHITE, TFT_BLACK, 4);
tft.drawString("go back", 10, 202, TFT_WHITE, TFT_BLACK, 4);
fontRenderer.drawString("Change value and press", 10, 152, TFT_WHITE, TFT_BLACK, 4);
fontRenderer.drawString("button to confirm and", 10, 177, TFT_WHITE, TFT_BLACK, 4);
fontRenderer.drawString("go back", 10, 202, TFT_WHITE, TFT_BLACK, 4);
}
else
{
tft.drawString("Change value and", 10, 160, TFT_WHITE, TFT_BLACK, 4);
tft.drawString("press button to", 10, 185, TFT_WHITE, TFT_BLACK, 4);
tft.drawString("confirm and go", 10, 210, TFT_WHITE, TFT_BLACK, 4);
tft.drawString("back.", 10, 235, TFT_WHITE, TFT_BLACK, 4);
fontRenderer.drawString("Change value and", 10, 160, TFT_WHITE, TFT_BLACK, 4);
fontRenderer.drawString("press button to", 10, 185, TFT_WHITE, TFT_BLACK, 4);
fontRenderer.drawString("confirm and go", 10, 210, TFT_WHITE, TFT_BLACK, 4);
fontRenderer.drawString("back.", 10, 235, TFT_WHITE, TFT_BLACK, 4);
}
}

View File

@ -5,6 +5,7 @@
// 3rdparty lib includes
#include <espchrono.h>
#include <fontrenderer.h>
// local includes
#include "changevaluedisplay.h"
@ -60,21 +61,23 @@ void ChangeValueDisplayChrono<T>::initScreen(TftInterface &tft)
{
Base::initScreen(tft);
FontRenderer fontRenderer{tft};
tft.drawRoundRect(32, 65, 190, 34, 8, TFT_WHITE);
m_valueLabel.start(tft);
if (espgui::isLandscape(tft))
{
tft.drawString("Change value and press", 10, 152, TFT_WHITE, TFT_BLACK, 4);
tft.drawString("button to confirm and", 10, 177, TFT_WHITE, TFT_BLACK, 4);
tft.drawString("go back", 10, 202, TFT_WHITE, TFT_BLACK, 4);
fontRenderer.drawString("Change value and press", 10, 152, TFT_WHITE, TFT_BLACK, 4);
fontRenderer.drawString("button to confirm and", 10, 177, TFT_WHITE, TFT_BLACK, 4);
fontRenderer.drawString("go back", 10, 202, TFT_WHITE, TFT_BLACK, 4);
}
else
{
tft.drawString("Change value and", 10, 160, TFT_WHITE, TFT_BLACK, 4);
tft.drawString("press button to", 10, 185, TFT_WHITE, TFT_BLACK, 4);
tft.drawString("confirm and go", 10, 210, TFT_WHITE, TFT_BLACK, 4);
tft.drawString("back.", 10, 235, TFT_WHITE, TFT_BLACK, 4);
fontRenderer.drawString("Change value and", 10, 160, TFT_WHITE, TFT_BLACK, 4);
fontRenderer.drawString("press button to", 10, 185, TFT_WHITE, TFT_BLACK, 4);
fontRenderer.drawString("confirm and go", 10, 210, TFT_WHITE, TFT_BLACK, 4);
fontRenderer.drawString("back.", 10, 235, TFT_WHITE, TFT_BLACK, 4);
}
}

View File

@ -1,5 +1,8 @@
#include "changevaluedisplay_ip_address_t.h"
// 3rdparty lib includes
#include <fontrenderer.h>
// local includes
#include "tftinterface.h"
#include "tftcolors.h"
@ -19,7 +22,9 @@ void ChangeValueDisplay<wifi_stack::ip_address_t>::initScreen(TftInterface &tft)
{
Base::initScreen(tft);
tft.drawString("Change IP Address", 0, 50, TFT_WHITE, TFT_BLACK, 4);
FontRenderer fontRenderer{tft};
fontRenderer.drawString("Change IP Address", 0, 50, TFT_WHITE, TFT_BLACK, 4);
for(int i = 0; i <= 3; i++)
{
@ -30,9 +35,9 @@ void ChangeValueDisplay<wifi_stack::ip_address_t>::initScreen(TftInterface &tft)
for (auto &label : m_labels)
label.start(tft);
tft.drawString(".", spacing+boxWidth+spacing/4, y, TFT_WHITE, TFT_BLACK, 4);
tft.drawString(".", spacing*2+boxWidth*2+spacing/4, y, TFT_WHITE, TFT_BLACK, 4);
tft.drawString(".", spacing*3+boxWidth*3+spacing/4, y, TFT_WHITE, TFT_BLACK, 4);
fontRenderer.drawString(".", spacing+boxWidth+spacing/4, y, TFT_WHITE, TFT_BLACK, 4);
fontRenderer.drawString(".", spacing*2+boxWidth*2+spacing/4, y, TFT_WHITE, TFT_BLACK, 4);
fontRenderer.drawString(".", spacing*3+boxWidth*3+spacing/4, y, TFT_WHITE, TFT_BLACK, 4);
drawRect(tft, m_currentIndex, 1, TFT_YELLOW);
drawRect(tft, m_currentIndex, 2, TFT_YELLOW);

View File

@ -2,6 +2,7 @@
// 3rdparty lib includes
#include <espchrono.h>
#include <fontrenderer.h>
// local includes
#include "tftinterface.h"
@ -41,21 +42,23 @@ void espgui::ChangeValueDisplay<std::string>::redraw(TftInterface &tft)
{
Base::redraw(tft);
FontRenderer fontRenderer{tft};
const auto now_ts = espchrono::millis_clock::now().time_since_epoch();
const auto char_width = tft.textWidth(m_value, 4) / ((!m_value.empty()) ? m_value.size() : 1);
const auto char_width = fontRenderer.textWidth(m_value, 4) / ((!m_value.empty()) ? m_value.size() : 1);
const auto maxChars = (tft.width() - 40) / char_width;
const auto substr_from = std::max(0U, m_value.size() < maxChars ? 0 : static_cast<int>(m_value.size()) - maxChars);
const auto string = m_value.substr(substr_from);
if (m_needsClear)
{
tft.drawRect(m_valueLabel.x() + tft.textWidth(*m_needsClear, 4) + 3, m_valueLabel.y(), 2, tft.fontHeight(4), TFT_BLACK);
tft.drawRect(m_valueLabel.x() + fontRenderer.textWidth(*m_needsClear, 4) + 3, m_valueLabel.y(), 2, fontRenderer.fontHeight(4), TFT_BLACK);
m_needsClear = std::nullopt;
}
m_valueLabel.redraw(tft, string, TFT_WHITE, TFT_BLACK, 4);
tft.drawRect(m_valueLabel.x() + tft.textWidth(string, 4) + 3, m_valueLabel.y(), 2, tft.fontHeight(4), (now_ts % 1000ms < 500ms) ? TFT_WHITE : TFT_BLACK);
tft.drawRect(m_valueLabel.x() + fontRenderer.textWidth(string, 4) + 3, m_valueLabel.y(), 2, fontRenderer.fontHeight(4), (now_ts % 1000ms < 500ms) ? TFT_WHITE : TFT_BLACK);
m_keyboard.redraw(tft);

View File

@ -6,6 +6,7 @@
// 3rdparty lib includes
#include <fmt/core.h>
#include <strutils.h>
#include <fontrenderer.h>
// local includes
#include "tftinterface.h"
@ -122,6 +123,8 @@ void Keyboard<TDisplay>::nextScreen()
template<typename TDisplay>
void Keyboard<TDisplay>::drawKeyboard(TftInterface &tft, bool dont_draw_string)
{
FontRenderer fontRenderer{tft};
constexpr const int FONT = 4;
size_t char_index{0};
@ -140,7 +143,7 @@ void Keyboard<TDisplay>::drawKeyboard(TftInterface &tft, bool dont_draw_string)
for (size_t i = 0; i < keyboard_lines.size(); i++)
{
const int32_t y = m_keyboard_start_y + (i * tft.fontHeight(FONT) + 9);
const int32_t y = m_keyboard_start_y + (i * fontRenderer.fontHeight(FONT) + 9);
std::string line = keyboard_lines[i];
const int16_t x = tft.width() / (line.size() + 1);
for (size_t j = 0; j < line.size(); j++)
@ -149,8 +152,8 @@ void Keyboard<TDisplay>::drawKeyboard(TftInterface &tft, bool dont_draw_string)
const int32_t x_pos = x * (j + 1);
const int32_t y_pos = y;
const auto width = tft.textWidth(_char, FONT) + 2;
const auto height = tft.fontHeight(FONT) + 4;
const auto width = fontRenderer.textWidth(_char, FONT) + 2;
const auto height = fontRenderer.fontHeight(FONT) + 4;
tft.drawRoundRect(x_pos-width/2-1, y_pos-height/2, width+2, height-4, 3, espgui::TFT_BLACK);
@ -159,61 +162,61 @@ void Keyboard<TDisplay>::drawKeyboard(TftInterface &tft, bool dont_draw_string)
if (!dont_draw_string || char_index == m_char_index || char_index == m_last_char_index)
{
tft.drawString(_char, x_pos, y_pos, (char_index == m_char_index ? espgui::TFT_WHITE : espgui::TFT_GREY), espgui::TFT_BLACK, FONT, 4); // 4 = center
fontRenderer.drawString(_char, x_pos, y_pos, (char_index == m_char_index ? espgui::TFT_WHITE : espgui::TFT_GREY), espgui::TFT_BLACK, FONT, 4); // 4 = center
}
char_index++;
}
}
// draw 3 extra buttons, back, space and enter (x=10, x=tft.width()/2, x=tft.width()-10)
const int32_t y = m_keyboard_start_y + (keyboard_lines.size() * tft.fontHeight(FONT));
const int32_t y = m_keyboard_start_y + (keyboard_lines.size() * fontRenderer.fontHeight(FONT));
if (isLandscape(tft))
{
// align left (SHIFT, SPACE)
tft.drawRoundRect(15 - 2, y - 1, tft.textWidth(SHIFT, FONT) + 4, tft.fontHeight(FONT) + 2, 3, espgui::TFT_DARKGREY);
tft.drawRoundRect(30 + tft.textWidth(SHIFT, FONT) - 2, y - 1, tft.textWidth(SPACE, FONT) + 4, tft.fontHeight(FONT) + 2, 3,
tft.drawRoundRect(15 - 2, y - 1, fontRenderer.textWidth(SHIFT, FONT) + 4, fontRenderer.fontHeight(FONT) + 2, 3, espgui::TFT_DARKGREY);
tft.drawRoundRect(30 + fontRenderer.textWidth(SHIFT, FONT) - 2, y - 1, fontRenderer.textWidth(SPACE, FONT) + 4, fontRenderer.fontHeight(FONT) + 2, 3,
espgui::TFT_DARKGREY);
// align right (BACKSPACE, ENTER); align from tft.width()
tft.drawRoundRect(tft.width() - 30 - tft.textWidth(ENTER, FONT) - tft.textWidth(BACKSPACE, FONT) - 2, y - 1,
tft.textWidth(BACKSPACE, FONT) + 4, tft.fontHeight(FONT) + 2, 3, espgui::TFT_DARKGREY);
tft.drawRoundRect(tft.width() - 15 - tft.textWidth(ENTER, FONT) - 2, y - 1, tft.textWidth(ENTER, FONT) + 4,
tft.fontHeight(FONT) + 2, 3, espgui::TFT_DARKGREY);
tft.drawRoundRect(tft.width() - 30 - fontRenderer.textWidth(ENTER, FONT) - fontRenderer.textWidth(BACKSPACE, FONT) - 2, y - 1,
fontRenderer.textWidth(BACKSPACE, FONT) + 4, fontRenderer.fontHeight(FONT) + 2, 3, espgui::TFT_DARKGREY);
tft.drawRoundRect(tft.width() - 15 - fontRenderer.textWidth(ENTER, FONT) - 2, y - 1, fontRenderer.textWidth(ENTER, FONT) + 4,
fontRenderer.fontHeight(FONT) + 2, 3, espgui::TFT_DARKGREY);
// if (!dont_draw_string)
{
// align left (SHIFT, SPACE)
tft.drawString(SHIFT, 15, y, (m_char_index == m_char_length ? espgui::TFT_BLACK : espgui::TFT_WHITE), (m_char_index == m_char_length ? espgui::TFT_WHITE : espgui::TFT_BLACK), FONT);
tft.drawString(SPACE, 30 + tft.textWidth(SHIFT, FONT), y, (m_char_index == m_char_length + 1 ? espgui::TFT_BLACK : espgui::TFT_WHITE), (m_char_index == m_char_length +1 ? espgui::TFT_WHITE : espgui::TFT_BLACK), FONT);
fontRenderer.drawString(SHIFT, 15, y, (m_char_index == m_char_length ? espgui::TFT_BLACK : espgui::TFT_WHITE), (m_char_index == m_char_length ? espgui::TFT_WHITE : espgui::TFT_BLACK), FONT);
fontRenderer.drawString(SPACE, 30 + fontRenderer.textWidth(SHIFT, FONT), y, (m_char_index == m_char_length + 1 ? espgui::TFT_BLACK : espgui::TFT_WHITE), (m_char_index == m_char_length +1 ? espgui::TFT_WHITE : espgui::TFT_BLACK), FONT);
// align right (BACKSPACE, ENTER); align from tft.width()
tft.drawString(BACKSPACE, tft.width() - 30 - tft.textWidth(ENTER, FONT) - tft.textWidth(BACKSPACE, FONT), y, (m_char_index == m_char_length + 2 ? espgui::TFT_BLACK : espgui::TFT_WHITE), (m_char_index == m_char_length + 2 ? espgui::TFT_WHITE : espgui::TFT_BLACK), FONT);
tft.drawString(ENTER, tft.width() - 15 - tft.textWidth(ENTER, FONT), y, (m_char_index == m_char_length + 3 ? espgui::TFT_BLACK : espgui::TFT_WHITE), (m_char_index == m_char_length + 3 ? espgui::TFT_WHITE : espgui::TFT_BLACK), FONT);
fontRenderer.drawString(BACKSPACE, tft.width() - 30 - fontRenderer.textWidth(ENTER, FONT) - fontRenderer.textWidth(BACKSPACE, FONT), y, (m_char_index == m_char_length + 2 ? espgui::TFT_BLACK : espgui::TFT_WHITE), (m_char_index == m_char_length + 2 ? espgui::TFT_WHITE : espgui::TFT_BLACK), FONT);
fontRenderer.drawString(ENTER, tft.width() - 15 - fontRenderer.textWidth(ENTER, FONT), y, (m_char_index == m_char_length + 3 ? espgui::TFT_BLACK : espgui::TFT_WHITE), (m_char_index == m_char_length + 3 ? espgui::TFT_WHITE : espgui::TFT_BLACK), FONT);
}
}
else
{
const int32_t y_2 = y + tft.fontHeight(FONT) + 4;
const int32_t y_2 = y + fontRenderer.fontHeight(FONT) + 4;
// align left (SHIFT, SPACE)
tft.drawRoundRect(15 - 2, y - 1, tft.textWidth(SHIFT, FONT) + 4, tft.fontHeight(FONT) + 2, 3, espgui::TFT_DARKGREY);
tft.drawRoundRect(15 - 2, y_2 - 1, tft.textWidth(SPACE, FONT) + 4, tft.fontHeight(FONT) + 2, 3, espgui::TFT_DARKGREY);
tft.drawRoundRect(15 - 2, y - 1, fontRenderer.textWidth(SHIFT, FONT) + 4, fontRenderer.fontHeight(FONT) + 2, 3, espgui::TFT_DARKGREY);
tft.drawRoundRect(15 - 2, y_2 - 1, fontRenderer.textWidth(SPACE, FONT) + 4, fontRenderer.fontHeight(FONT) + 2, 3, espgui::TFT_DARKGREY);
// align right (BACKSPACE, ENTER); align from tft.width()
tft.drawRoundRect(tft.width() - 15 - tft.textWidth(ENTER, FONT) - 2, y - 1, tft.textWidth(ENTER, FONT) + 4,
tft.fontHeight(FONT) + 2, 3, espgui::TFT_DARKGREY);
tft.drawRoundRect(tft.width() - 15 - tft.textWidth(BACKSPACE, FONT) - 2, y_2 - 1, tft.textWidth(BACKSPACE, FONT) + 4,
tft.fontHeight(FONT) + 2, 3, espgui::TFT_DARKGREY);
tft.drawRoundRect(tft.width() - 15 - fontRenderer.textWidth(ENTER, FONT) - 2, y - 1, fontRenderer.textWidth(ENTER, FONT) + 4,
fontRenderer.fontHeight(FONT) + 2, 3, espgui::TFT_DARKGREY);
tft.drawRoundRect(tft.width() - 15 - fontRenderer.textWidth(BACKSPACE, FONT) - 2, y_2 - 1, fontRenderer.textWidth(BACKSPACE, FONT) + 4,
fontRenderer.fontHeight(FONT) + 2, 3, espgui::TFT_DARKGREY);
// if (!dont_draw_string)
{
// align left (SHIFT, SPACE)
tft.drawString(SHIFT, 15, y, (m_char_index == m_char_length ? espgui::TFT_BLACK : espgui::TFT_WHITE), (m_char_index == m_char_length ? espgui::TFT_WHITE : espgui::TFT_BLACK), FONT);
tft.drawString(SPACE, 15, y_2, (m_char_index == m_char_length + 1 ? espgui::TFT_BLACK : espgui::TFT_WHITE), (m_char_index == m_char_length + 1 ? espgui::TFT_WHITE : espgui::TFT_BLACK), FONT);
fontRenderer.drawString(SHIFT, 15, y, (m_char_index == m_char_length ? espgui::TFT_BLACK : espgui::TFT_WHITE), (m_char_index == m_char_length ? espgui::TFT_WHITE : espgui::TFT_BLACK), FONT);
fontRenderer.drawString(SPACE, 15, y_2, (m_char_index == m_char_length + 1 ? espgui::TFT_BLACK : espgui::TFT_WHITE), (m_char_index == m_char_length + 1 ? espgui::TFT_WHITE : espgui::TFT_BLACK), FONT);
// align right (BACKSPACE, ENTER); align from tft.width()
tft.drawString(BACKSPACE, tft.width() - 15 - tft.textWidth(BACKSPACE, FONT), y_2, (m_char_index == m_char_length + 2 ? espgui::TFT_BLACK : espgui::TFT_WHITE), (m_char_index == m_char_length + 2 ? espgui::TFT_WHITE : espgui::TFT_BLACK), FONT);
tft.drawString(ENTER, tft.width() - 15 - tft.textWidth(ENTER, FONT), y, (m_char_index == m_char_length + 3 ? espgui::TFT_BLACK : espgui::TFT_WHITE), (m_char_index == m_char_length + 3 ? espgui::TFT_WHITE : espgui::TFT_BLACK), FONT);
fontRenderer.drawString(BACKSPACE, tft.width() - 15 - fontRenderer.textWidth(BACKSPACE, FONT), y_2, (m_char_index == m_char_length + 2 ? espgui::TFT_BLACK : espgui::TFT_WHITE), (m_char_index == m_char_length + 2 ? espgui::TFT_WHITE : espgui::TFT_BLACK), FONT);
fontRenderer.drawString(ENTER, tft.width() - 15 - fontRenderer.textWidth(ENTER, FONT), y, (m_char_index == m_char_length + 3 ? espgui::TFT_BLACK : espgui::TFT_WHITE), (m_char_index == m_char_length + 3 ? espgui::TFT_WHITE : espgui::TFT_BLACK), FONT);
}
}
}

View File

@ -6,6 +6,7 @@
// 3rdparty lib includes
#include <screenmanager.h>
#include <cppmacros.h>
#include <fontrenderer.h>
// local includes
#include "tftinterface.h"
@ -36,6 +37,8 @@ void MessagePopupDisplay::buttonPressed(Button button)
void MessagePopupDisplay::initOverlay(TftInterface &tft)
{
FontRenderer fontRenderer{tft};
const auto leftMargin = 20;
const auto rightMargin = leftMargin;
const auto topMargin = tft.height() > 300 ? 50 : 20;
@ -61,12 +64,12 @@ void MessagePopupDisplay::initOverlay(TftInterface &tft)
if (c == '\n' || x > tft.width() - rightMargin - 10)
{
x = leftMargin + 5;
y += tft.fontHeight(4);
y += fontRenderer.fontHeight(4);
}
if (c != '\n')
{
const auto addedWidth = tft.drawString(std::string_view{&c, 1}, x, y, TFT_WHITE, color565(30, 30, 30), 4);
const auto addedWidth = fontRenderer.drawString(std::string_view{&c, 1}, x, y, TFT_WHITE, color565(30, 30, 30), 4);
x += addedWidth;
}
@ -83,7 +86,7 @@ void MessagePopupDisplay::initOverlay(TftInterface &tft)
color565(100, 100, 100),
color565(170, 170, 170));
tft.drawString("Retry", leftMargin + 18, bottom - 37, TFT_BLACK, color565(170, 170, 170), 4);
fontRenderer.drawString("Retry", leftMargin + 18, bottom - 37, TFT_BLACK, color565(170, 170, 170), 4);
}
tft.drawSunkenRect(leftMargin + 15 + ((width - 15 - 30 - 15) / 2) + 15, bottom - 40,
@ -93,7 +96,7 @@ void MessagePopupDisplay::initOverlay(TftInterface &tft)
color565(100, 100, 100),
color565(170, 170, 170));
tft.drawString("Ok", leftMargin + 18 + ((width - 15 - 30 - 15) / 2) + 15 + 1, bottom - 37, TFT_BLACK, color565(170, 170, 170), 4);
fontRenderer.drawString("Ok", leftMargin + 18 + ((width - 15 - 30 - 15) / 2) + 15 + 1, bottom - 37, TFT_BLACK, color565(170, 170, 170), 4);
}
} // namespace espgui

View File

@ -5,6 +5,7 @@
// 3rdparty lib includes
#include <strutils.h>
#include <fontrenderer.h>
// local includes
#include "tftinterface.h"
@ -24,22 +25,24 @@ std::string richTextEscape(std::string_view subject)
int16_t renderRichText(TftInterface &tft, std::string_view str, int32_t poX, int32_t poY, uint16_t color, uint16_t bgcolor, uint8_t font)
{
FontRenderer fontRenderer{tft};
if (str.empty())
return 0;
const int16_t fontHeight = tft.fontHeight(font);
const int16_t fontHeight = fontRenderer.fontHeight(font);
const uint16_t oldColor = color;
const uint8_t oldFont = font;
int16_t width{};
const auto drawString = [&tft, &poX, &poY, &color, &bgcolor, &font, &width, &fontHeight, &oldFont](std::string_view str) {
const auto addedWith = tft.drawString(str, poX, poY, color, bgcolor, font);
const auto drawString = [&tft, &fontRenderer, &poX, &poY, &color, &bgcolor, &font, &width, &fontHeight, &oldFont](std::string_view str) {
const auto addedWith = fontRenderer.drawString(str, poX, poY, color, bgcolor, font);
if (font != oldFont)
{
if (const int16_t newFontHeight = tft.fontHeight(font); newFontHeight < fontHeight)
if (const int16_t newFontHeight = fontRenderer.fontHeight(font); newFontHeight < fontHeight)
{
tft.fillRect(poX, poY + newFontHeight,
addedWith, fontHeight - newFontHeight,

View File

@ -1,85 +0,0 @@
#pragma once
// 3rdparty lib includes
#include "TFT_eSPI.h"
// local includes
#include "tftinterface.h"
namespace espgui {
class TftESpiImpl : public TftInterface
{
public:
void init() { m_tft.init(); }
void drawPixel(int32_t x, int32_t y, uint16_t color) override { m_tft.drawPixel(x, y, color); }
void drawChar(int32_t x, int32_t y, uint16_t c, uint16_t color, uint16_t bg, uint8_t size) override { m_tft.drawChar(x, y, c, color, bg, size); }
void drawLine(int32_t xs, int32_t ys, int32_t xe, int32_t ye, uint16_t color) override { m_tft.drawLine(xs, ys, xe, ye, color); }
void drawFastVLine(int32_t x, int32_t y, int32_t h, uint16_t color) override { m_tft.drawFastVLine(x, y, h, color); }
void drawFastHLine(int32_t x, int32_t y, int32_t w, uint16_t color) override { m_tft.drawFastHLine(x, y, w, color); }
void fillRect(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t color) override { m_tft.fillRect(x, y, w, h, color); }
int16_t drawChar(uint16_t uniCode, int32_t x, int32_t y, uint16_t color, uint16_t bgcolor, uint8_t font) override { return m_tft.drawChar(uniCode, x, y, color, bgcolor, font); }
int16_t height() const override { return m_tft.height(); }
int16_t width() const override { return m_tft.width(); }
void setRotation(uint8_t r) override { m_tft.setRotation(r); }
uint8_t getRotation(void) const { return m_tft.getRotation(); }
void setTextSize(uint8_t s) override { m_tft.setTextSize(s); }
// Graphics drawing
void fillScreen(uint32_t color) override { m_tft.fillScreen(color); }
void drawRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color) override { m_tft.drawRect(x, y, w, h, color); }
void drawRoundRect(int32_t x, int32_t y, int32_t w, int32_t h, int32_t radius, uint32_t color) override { m_tft.drawRoundRect(x, y, w, h, radius, color); }
void fillRoundRect(int32_t x, int32_t y, int32_t w, int32_t h, int32_t radius, uint32_t color) override { m_tft.fillRoundRect(x, y, w, h, radius, color); }
void fillRectVGradient(int16_t x, int16_t y, int16_t w, int16_t h, uint32_t color1, uint32_t color2) override { m_tft.fillRectVGradient(x, y, w, h, color1, color2); }
void fillRectHGradient(int16_t x, int16_t y, int16_t w, int16_t h, uint32_t color1, uint32_t color2) override { m_tft.fillRectHGradient(x, y, w, h, color1, color2); }
void drawSpot(float ax, float ay, float r, uint32_t fg_color, uint32_t bg_color = 0x00FFFFFF) override { m_tft.drawSpot(ax, ay, r, fg_color, bg_color); }
void fillSmoothCircle(int32_t x, int32_t y, int32_t r, uint32_t color, uint32_t bg_color = 0x00FFFFFF) override { m_tft.fillSmoothCircle(x, y, r, color, bg_color); }
void fillSmoothRoundRect(int32_t x, int32_t y, int32_t w, int32_t h, int32_t radius, uint32_t color, uint32_t bg_color = 0x00FFFFFF) override { m_tft.fillSmoothRoundRect(x, y, w, h, radius, color, bg_color); }
void drawWideLine(float ax, float ay, float bx, float by, float wd, uint32_t fg_color, uint32_t bg_color = 0x00FFFFFF) override { m_tft.drawWideLine(ax, ay, bx, by, wd, fg_color, bg_color); }
void drawWedgeLine(float ax, float ay, float bx, float by, float aw, float bw, uint32_t fg_color, uint32_t bg_color = 0x00FFFFFF) override { m_tft.drawWedgeLine(ax, ay, bx, by, aw, bw, fg_color, bg_color); }
void drawSunkenRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color0, uint32_t color1, uint32_t color2) override { m_tft.drawSunkenRect(x, y, w, h, color0, color1, color2); }
void drawCircle(int32_t x, int32_t y, int32_t r, uint32_t color) override { m_tft.drawCircle(x, y, r, color); }
void drawCircleHelper(int32_t x, int32_t y, int32_t r, uint8_t cornername, uint32_t color) override { m_tft.drawCircleHelper(x, y, r, cornername, color); }
void fillCircle(int32_t x, int32_t y, int32_t r, uint32_t color) override { m_tft.fillCircle(x, y, r, color); }
void fillCircleHelper(int32_t x, int32_t y, int32_t r, uint8_t cornername, int32_t delta, uint32_t color) override { m_tft.fillCircleHelper(x, y, r, cornername, delta, color); }
void drawEllipse(int16_t x, int16_t y, int32_t rx, int32_t ry, uint16_t color) override { m_tft.drawEllipse(x, y, rx, ry, color); }
void fillEllipse(int16_t x, int16_t y, int32_t rx, int32_t ry, uint16_t color) override { m_tft.fillEllipse(x, y, rx, ry, color); }
void drawTriangle(int32_t x1,int32_t y1, int32_t x2,int32_t y2, int32_t x3,int32_t y3, uint32_t color) override { m_tft.drawTriangle(x1, y1, x2, y2, x3, y3, color); }
void fillTriangle(int32_t x1,int32_t y1, int32_t x2,int32_t y2, int32_t x3,int32_t y3, uint32_t color) override { m_tft.fillTriangle(x1, y1, x2, y2, x3, y3, color); }
int16_t textWidth(std::string_view string, uint8_t font) override { return m_tft.textWidth(string, font); }
int16_t fontHeight(int16_t font) override { return m_tft.fontHeight(font); }
int16_t drawString(std::string_view string, int32_t x, int32_t y, uint16_t color, uint16_t bgcolor, uint8_t font, uint8_t datum = 0) override { return m_tft.drawString(string, x, y, color, bgcolor, font, datum); }
int16_t drawCentreString(std::string_view string, int32_t x, int32_t y, uint16_t color, uint16_t bgcolor, uint8_t font) override { return m_tft.drawCentreString(string, x, y, color, bgcolor, font); }
int16_t drawRightString(std::string_view string, int32_t x, int32_t y, uint16_t color, uint16_t bgcolor, uint8_t font) override { return m_tft.drawRightString(string, x, y, color, bgcolor, font); }
void pushImage(int32_t x, int32_t y, int32_t w, int32_t h, const uint16_t *data) { m_tft.pushImage(x, y, w, h, data); }
void pushImage(int32_t x, int32_t y, int32_t w, int32_t h, const uint16_t *data, uint16_t transparent) { m_tft.pushImage(x, y, w, h, data, transparent); }
void startWrite(void) override { m_tft.startWrite(); }
void writeColor(uint16_t color, uint32_t len) override { m_tft.writeColor(color, len); }
void endWrite(void) override { m_tft.endWrite(); }
void pushColor(uint16_t color, uint32_t len) override { m_tft.pushColor(color, len); }
void setAddrWindow(int32_t xs, int32_t ys, int32_t w, int32_t h) override { m_tft.setAddrWindow(xs, ys, w, h); }
private:
TFT_eSPI m_tft;
};
} // namespace espgui

View File

@ -1,100 +0,0 @@
#pragma once
// system includes
#include <cstdint>
#include <string_view>
namespace espgui {
class TftInterface
{
public:
explicit TftInterface() = default;
virtual ~TftInterface() = default;
virtual void drawPixel(int32_t x, int32_t y, uint16_t color) = 0;
virtual void drawChar(int32_t x, int32_t y, uint16_t c, uint16_t color, uint16_t bg, uint8_t size) = 0;
virtual void drawLine(int32_t xs, int32_t ys, int32_t xe, int32_t ye, uint16_t color) = 0;
virtual void drawFastVLine(int32_t x, int32_t y, int32_t h, uint16_t color) = 0;
virtual void drawFastHLine(int32_t x, int32_t y, int32_t w, uint16_t color) = 0;
virtual void fillRect(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t color) = 0;
virtual int16_t drawChar(uint16_t uniCode, int32_t x, int32_t y, uint16_t color, uint16_t bgcolor, uint8_t font) = 0;
virtual int16_t height(void) const = 0;
virtual int16_t width(void) const = 0;
virtual void setRotation(uint8_t r) = 0; // Set the display image orientation to 0, 1, 2 or 3
virtual uint8_t getRotation(void) const = 0; // Read the current rotation
virtual void setTextSize(uint8_t size) = 0; // Set character size multiplier (this increases pixel size)
// Graphics drawing
virtual void fillScreen(uint32_t color) = 0;
virtual void drawRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color) = 0;
virtual void drawRoundRect(int32_t x, int32_t y, int32_t w, int32_t h, int32_t radius, uint32_t color) = 0;
virtual void fillRoundRect(int32_t x, int32_t y, int32_t w, int32_t h, int32_t radius, uint32_t color) = 0;
virtual void fillRectVGradient(int16_t x, int16_t y, int16_t w, int16_t h, uint32_t color1, uint32_t color2) = 0;
virtual void fillRectHGradient(int16_t x, int16_t y, int16_t w, int16_t h, uint32_t color1, uint32_t color2) = 0;
// Draw a small anti-aliased filled circle at ax,ay with radius r (uses drawWideLine)
// If bg_color is not included the background pixel colour will be read from TFT or sprite
virtual void drawSpot(float ax, float ay, float r, uint32_t fg_color, uint32_t bg_color = 0x00FFFFFF) = 0;
// Draw an anti-aliased filled circle at x, y with radius r
// If bg_color is not included the background pixel colour will be read from TFT or sprite
virtual void fillSmoothCircle(int32_t x, int32_t y, int32_t r, uint32_t color, uint32_t bg_color = 0x00FFFFFF) = 0;
virtual void fillSmoothRoundRect(int32_t x, int32_t y, int32_t w, int32_t h, int32_t radius, uint32_t color, uint32_t bg_color = 0x00FFFFFF) = 0;
// Draw an anti-aliased wide line from ax,ay to bx,by width wd with radiused ends (radius is wd/2)
// If bg_color is not included the background pixel colour will be read from TFT or sprite
virtual void drawWideLine(float ax, float ay, float bx, float by, float wd, uint32_t fg_color, uint32_t bg_color = 0x00FFFFFF) = 0;
// Draw an anti-aliased wide line from ax,ay to bx,by with different width at each end aw, bw and with radiused ends
// If bg_color is not included the background pixel colour will be read from TFT or sprite
virtual void drawWedgeLine(float ax, float ay, float bx, float by, float aw, float bw, uint32_t fg_color, uint32_t bg_color = 0x00FFFFFF) = 0;
virtual void drawSunkenRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color0, uint32_t color1, uint32_t color2) = 0;
virtual void drawCircle(int32_t x, int32_t y, int32_t r, uint32_t color) = 0;
virtual void drawCircleHelper(int32_t x, int32_t y, int32_t r, uint8_t cornername, uint32_t color) = 0;
virtual void fillCircle(int32_t x, int32_t y, int32_t r, uint32_t color) = 0;
virtual void fillCircleHelper(int32_t x, int32_t y, int32_t r, uint8_t cornername, int32_t delta, uint32_t color) = 0;
virtual void drawEllipse(int16_t x, int16_t y, int32_t rx, int32_t ry, uint16_t color) = 0;
virtual void fillEllipse(int16_t x, int16_t y, int32_t rx, int32_t ry, uint16_t color) = 0;
// Corner 1 Corner 2 Corner 3
virtual void drawTriangle(int32_t x1,int32_t y1, int32_t x2,int32_t y2, int32_t x3,int32_t y3, uint32_t color) = 0;
virtual void fillTriangle(int32_t x1,int32_t y1, int32_t x2,int32_t y2, int32_t x3,int32_t y3, uint32_t color) = 0;
virtual int16_t textWidth(std::string_view string, uint8_t font) = 0; // Returns pixel width of string in specified font
virtual int16_t fontHeight(int16_t font) = 0; // Returns pixel height of string in specified font
// Handle char arrays
// Use with setTextDatum() to position string on TFT, and setTextPadding() to blank old displayed strings
virtual int16_t drawString(std::string_view string, int32_t x, int32_t y, uint16_t color, uint16_t bgcolor, uint8_t font, uint8_t datum = 0) = 0; // Draw string using specifed font number
virtual int16_t drawCentreString(std::string_view string, int32_t x, int32_t y, uint16_t color, uint16_t bgcolor, uint8_t font) = 0; // Deprecated, use setTextDatum() and drawString()
virtual int16_t drawRightString(std::string_view string, int32_t x, int32_t y, uint16_t color, uint16_t bgcolor, uint8_t font) = 0; // Deprecated, use setTextDatum() and drawString()
// These are used to render images or sprites stored in RAM arrays (used by Sprite class for 16bpp Sprites)
virtual void pushImage(int32_t x, int32_t y, int32_t w, int32_t h, const uint16_t *data) = 0;
virtual void pushImage(int32_t x, int32_t y, int32_t w, int32_t h, const uint16_t *data, uint16_t transparent) = 0;
// Bare metal functions
virtual void startWrite(void) = 0;
virtual void writeColor(uint16_t color, uint32_t len) = 0;
virtual void endWrite(void) = 0;
// Push (aka write pixel) colours to the set window
virtual void pushColor(uint16_t color, uint32_t len) = 0;
// The TFT_eSprite class inherits the following functions (not all are useful to Sprite class
virtual void setAddrWindow(int32_t xs, int32_t ys, int32_t w, int32_t h) = 0;
};
inline bool isLandscape(const TftInterface &tft)
{
return (tft.getRotation() == 1 || tft.getRotation() == 3);
}
} // namespace espgui

View File

@ -1,5 +1,8 @@
#include "label.h"
// 3rdparty lib includes
#include <fontrenderer.h>
// local includes
#include "tftinterface.h"
#include "richtextrenderer.h"
@ -22,6 +25,12 @@ void Label::start(TftInterface &tft)
}
void Label::redraw(TftInterface &tft, std::string_view str, uint16_t color, uint16_t bgcolor, uint8_t font, bool forceRedraw)
{
espgui::FontRenderer fontRenderer{tft};
redraw(tft, fontRenderer, str, color, bgcolor, font, forceRedraw);
}
void Label::redraw(TftInterface &tft, FontRenderer &fontRenderer, std::string_view str, uint16_t color, uint16_t bgcolor, uint8_t font, bool forceRedraw)
{
if (m_lastStr == str &&
m_lastColor == color &&
@ -30,7 +39,7 @@ void Label::redraw(TftInterface &tft, std::string_view str, uint16_t color, uint
return;
const auto renderedWidth = renderRichText(tft, str, m_x, m_y, color, bgcolor, font);
const auto renderedHeight = tft.fontHeight(font);
const auto renderedHeight = fontRenderer.fontHeight(font);
if (renderedWidth < m_lastWidth)
tft.fillRect(m_x + renderedWidth, m_y,

View File

@ -6,6 +6,7 @@
// forward declares
namespace espgui {
class TftInterface;
class FontRenderer;
} // namespace espgui
namespace espgui {
@ -19,6 +20,7 @@ public:
void start(TftInterface &tft);
void redraw(TftInterface &tft, std::string_view str, uint16_t color, uint16_t bgcolor, uint8_t font, bool forceRedraw = false);
void redraw(TftInterface &tft, FontRenderer &fontRenderer, std::string_view str, uint16_t color, uint16_t bgcolor, uint8_t font, bool forceRedraw = false);
void clear(TftInterface &tft, uint16_t bgcolor);
private:

View File

@ -2,6 +2,7 @@
// 3rdparty lib includes
#include <cpputils.h>
#include <fontrenderer.h>
// local includes
#include "tftinterface.h"
@ -15,10 +16,12 @@ VerticalMeter::VerticalMeter(const char *text, const char *format, int x, int y)
void VerticalMeter::start(TftInterface &tft)
{
FontRenderer fontRenderer{tft};
int w = 36;
tft.drawRect(m_x, m_y, w, 155, TFT_GREY);
tft.fillRect(m_x + 2, m_y + 19, w - 3, 155 - 38, TFT_WHITE);
tft.drawCentreString(m_text, m_x + w / 2, m_y + 2, TFT_CYAN, TFT_BLACK, 2);
fontRenderer.drawCentreString(m_text, m_x + w / 2, m_y + 2, TFT_CYAN, TFT_BLACK, 2);
for (int i = 0; i < 110; i += 10)
tft.drawFastHLine(m_x + 20, m_y + 27 + i, 6, TFT_BLACK);
@ -29,14 +32,16 @@ void VerticalMeter::start(TftInterface &tft)
tft.fillTriangle(m_x + 3, m_y + 127, m_x + 3 + 16, m_y + 127, m_x + 3, m_y + 127 - 5, TFT_RED);
tft.fillTriangle(m_x + 3, m_y + 127, m_x + 3 + 16, m_y + 127, m_x + 3, m_y + 127 + 5, TFT_RED);
tft.drawCentreString("---", m_x + w / 2, m_y + 155 - 18, TFT_CYAN, TFT_BLACK, 2);
fontRenderer.drawCentreString("---", m_x + w / 2, m_y + 155 - 18, TFT_CYAN, TFT_BLACK, 2);
}
void VerticalMeter::redraw(TftInterface &tft, float value, float min, float max)
{
FontRenderer fontRenderer{tft};
char buf[16];
snprintf(&buf[0], 16, m_format, value);
tft.drawRightString(buf, m_x + 36 - 5, 187 - 27 + 155 - 18, TFT_GREEN, TFT_BLACK, 2);
fontRenderer.drawRightString(buf, m_x + 36 - 5, 187 - 27 + 155 - 18, TFT_GREEN, TFT_BLACK, 2);
const int dx = 3 + m_x;
value = cpputils::mapValueClamped<float>(value, min, max, 0.f, 100.f);

View File

@ -6,6 +6,7 @@
// 3rdparty lib includes
#include <cpputils.h>
#include <stdlib_noniso.h>
#include <fontrenderer.h>
// local includes
#include "tftinterface.h"
@ -14,6 +15,8 @@
namespace espgui {
void VuMeter::start(TftInterface &tft)
{
FontRenderer fontRenderer{tft};
ltx = 0;
osx = 120;
osy = 120;
@ -79,11 +82,11 @@ void VuMeter::start(TftInterface &tft)
x0 = sx * (100 + tl + 10) + 120;
y0 = sy * (100 + tl + 10) + 140;
switch (i / 25) {
case -2: tft.drawCentreString("0", x0, y0 - 12, TFT_BLACK, TFT_BLACK, 2); break;
case -1: tft.drawCentreString("7.5", x0, y0 - 9, TFT_BLACK, TFT_BLACK, 2); break;
case 0: tft.drawCentreString("15", x0, y0 - 6, TFT_BLACK, TFT_BLACK, 2); break;
case 1: tft.drawCentreString("22.5", x0, y0 - 9, TFT_BLACK, TFT_BLACK, 2); break;
case 2: tft.drawCentreString("30", x0, y0 - 12, TFT_BLACK, TFT_BLACK, 2); break;
case -2: fontRenderer.drawCentreString("0", x0, y0 - 12, TFT_BLACK, TFT_BLACK, 2); break;
case -1: fontRenderer.drawCentreString("7.5", x0, y0 - 9, TFT_BLACK, TFT_BLACK, 2); break;
case 0: fontRenderer.drawCentreString("15", x0, y0 - 6, TFT_BLACK, TFT_BLACK, 2); break;
case 1: fontRenderer.drawCentreString("22.5", x0, y0 - 9, TFT_BLACK, TFT_BLACK, 2); break;
case 2: fontRenderer.drawCentreString("30", x0, y0 - 12, TFT_BLACK, TFT_BLACK, 2); break;
}
}
@ -96,15 +99,17 @@ void VuMeter::start(TftInterface &tft)
if (i < 50) tft.drawLine(x0, y0, x1, y1, TFT_BLACK);
}
tft.drawString("KM/h", 5 + 230 - 40, 119 - 20, TFT_BLACK, TFT_BLACK, 2); // Units at bottom right
tft.drawCentreString("KM/h", 120, 70, TFT_BLACK, TFT_BLACK, 4); // Comment out to avoid font 4
fontRenderer.drawString("KM/h", 5 + 230 - 40, 119 - 20, TFT_BLACK, TFT_BLACK, 2); // Units at bottom right
fontRenderer.drawCentreString("KM/h", 120, 70, TFT_BLACK, TFT_BLACK, 4); // Comment out to avoid font 4
tft.drawRect(5, 3, 230, 119, TFT_BLACK); // Draw bezel line
}
void VuMeter::redraw(TftInterface &tft, float value)
{
FontRenderer fontRenderer{tft};
char buf[8]; dtostrf(value, 4, 0, buf);
tft.drawRightString(buf, 50, 119 - 25, TFT_BLACK, TFT_WHITE, 4);
fontRenderer.drawRightString(buf, 50, 119 - 25, TFT_BLACK, TFT_WHITE, 4);
if (value < -3) value = -3; // Limit value to emulate needle end stops
if (value > 33) value = 33;
@ -123,7 +128,7 @@ void VuMeter::redraw(TftInterface &tft, float value)
tft.drawLine(120 + 20 * ltx + 1, 140 - 20, osx + 1, osy, TFT_WHITE);
// Re-plot text under needle
tft.drawCentreString("KM/h", 120, 70, TFT_BLACK, TFT_BLACK, 4); // // Comment out to avoid font 4
fontRenderer.drawCentreString("KM/h", 120, 70, TFT_BLACK, TFT_BLACK, 4); // // Comment out to avoid font 4
// Store new needle end coords for next erase
ltx = tx;