1
0
mirror of https://github.com/thooge/esp32-nmea2000-obp60.git synced 2026-08-18 10:22:31 +02:00

Implement shaddow frame buffer for TFT display

This commit is contained in:
Norbert Walter
2026-03-01 15:55:34 +00:00
parent 907a817573
commit 762004ac9f
3 changed files with 187 additions and 11 deletions
+146 -3
View File
@@ -268,7 +268,148 @@ private:
lgfx::Panel_ST7796 _panel_instance;
};
LGFX & getdisplay();
class LGFXCanvas : public lgfx::LGFX_Sprite {
public:
explicit LGFXCanvas(lgfx::LGFX_Device* parent = nullptr) : lgfx::LGFX_Sprite(parent) {}
using lgfx::LGFX_Sprite::setFont;
void setFont(const GFXfont *font) {
if (font == nullptr) {
_currentAdfFont = nullptr;
lgfx::LGFX_Sprite::setFont(nullptr);
return;
}
if (font->glyph == nullptr || font->bitmap == nullptr || font->last < font->first) {
_currentAdfFont = nullptr;
lgfx::LGFX_Sprite::setFont(nullptr);
return;
}
const uint16_t glyphCount = static_cast<uint16_t>(font->last - font->first + 1);
if (glyphCount == 0) {
lgfx::LGFX_Sprite::setFont(nullptr);
return;
}
if (_adfGlyphCount != glyphCount || _adfGlyphBridge == nullptr) {
if (_adfGlyphBridge != nullptr) {
free(_adfGlyphBridge);
_adfGlyphBridge = nullptr;
_adfGlyphCount = 0;
}
_adfGlyphBridge = static_cast<lgfx::GFXglyph*>(malloc(sizeof(lgfx::GFXglyph) * glyphCount));
if (_adfGlyphBridge == nullptr) {
lgfx::LGFX_Sprite::setFont(nullptr);
return;
}
_adfGlyphCount = glyphCount;
}
for (uint16_t index = 0; index < glyphCount; ++index) {
_adfGlyphBridge[index].bitmapOffset = font->glyph[index].bitmapOffset;
_adfGlyphBridge[index].width = font->glyph[index].width;
_adfGlyphBridge[index].height = font->glyph[index].height;
_adfGlyphBridge[index].xAdvance = font->glyph[index].xAdvance;
_adfGlyphBridge[index].xOffset = font->glyph[index].xOffset;
_adfGlyphBridge[index].yOffset = font->glyph[index].yOffset;
}
_adfFontBridge = lgfx::GFXfont(
const_cast<uint8_t*>(font->bitmap),
_adfGlyphBridge,
font->first,
font->last,
font->yAdvance
);
_currentAdfFont = font;
lgfx::LGFX_Sprite::setFont(&_adfFontBridge);
}
void getTextBounds(const String &txt, int16_t x, int16_t y,
int16_t *x0, int16_t *y0,
uint16_t *w, uint16_t *h) {
if (w == nullptr || h == nullptr) {
return;
}
if (_currentAdfFont == nullptr || txt.length() == 0) {
*w = textWidth(txt);
*h = fontHeight();
if (x0) *x0 = x;
if (y0) *y0 = y - static_cast<int16_t>(*h);
return;
}
const float sx = getTextSizeX();
const float sy = getTextSizeY();
int32_t cursorX = x;
int32_t cursorY = y;
int32_t minX = 0;
int32_t minY = 0;
int32_t maxX = 0;
int32_t maxY = 0;
bool hasPixel = false;
for (size_t i = 0; i < txt.length(); ++i) {
char c = txt[i];
if (c == '\r') continue;
if (c == '\n') {
cursorX = x;
cursorY += static_cast<int32_t>(_currentAdfFont->yAdvance * sy);
continue;
}
if (c < _currentAdfFont->first || c > _currentAdfFont->last) {
continue;
}
const GFXglyph* glyph = &_currentAdfFont->glyph[static_cast<uint16_t>(c) - _currentAdfFont->first];
const int32_t gw = static_cast<int32_t>(glyph->width * sx);
const int32_t gh = static_cast<int32_t>(glyph->height * sy);
const int32_t gx1 = cursorX + static_cast<int32_t>(glyph->xOffset * sx);
const int32_t gy1 = cursorY + static_cast<int32_t>(glyph->yOffset * sy);
if (gw > 0 && gh > 0) {
const int32_t gx2 = gx1 + gw - 1;
const int32_t gy2 = gy1 + gh - 1;
if (!hasPixel) {
minX = gx1; minY = gy1; maxX = gx2; maxY = gy2;
hasPixel = true;
} else {
if (gx1 < minX) minX = gx1;
if (gy1 < minY) minY = gy1;
if (gx2 > maxX) maxX = gx2;
if (gy2 > maxY) maxY = gy2;
}
}
cursorX += static_cast<int32_t>(glyph->xAdvance * sx);
}
if (hasPixel) {
if (x0) *x0 = static_cast<int16_t>(minX);
if (y0) *y0 = static_cast<int16_t>(minY);
*w = static_cast<uint16_t>(maxX - minX + 1);
*h = static_cast<uint16_t>(maxY - minY + 1);
} else {
if (x0) *x0 = x;
if (y0) *y0 = y;
*w = 0;
*h = 0;
}
}
void setFullWindow() { /* no-op on TFT */ }
private:
lgfx::GFXfont _adfFontBridge { nullptr, nullptr, 0, 0, 0 };
lgfx::GFXglyph* _adfGlyphBridge = nullptr;
uint16_t _adfGlyphCount = 0;
const GFXfont* _currentAdfFont = nullptr;
};
LGFXCanvas & getdisplay();
LGFX & getpaneldisplay();
bool initDisplayShadowBuffer();
#endif
// Page display return values
@@ -344,7 +485,7 @@ inline void displayDrawBitmap(int16_t x, int16_t y,
inline void displayFirstPage() {
#ifdef DISPLAY_ST7796
// TFT LCD doesn't need firstPage()
initDisplayShadowBuffer();
#else
getdisplay().firstPage();
#endif
@@ -352,7 +493,9 @@ inline void displayFirstPage() {
inline void displayNextPage() {
#ifdef DISPLAY_ST7796
// TFT LCD doesn't need nextPage() for refresh
if (initDisplayShadowBuffer()) {
getdisplay().pushSprite(0, 0);
}
#else
getdisplay().nextPage();
#endif