Proper refresh on exit

This commit is contained in:
jpirnay
2026-04-08 11:22:21 +02:00
parent 7c44a92360
commit bcf49a943a
4 changed files with 47 additions and 22 deletions
+40 -18
View File
@@ -751,11 +751,12 @@ void GfxRenderer::drawCenteredText(const int fontId, const int y, const char* te
void GfxRenderer::drawText(const int fontId, const int x, const int y, const char* text, const bool black,
const EpdFontFamily::Style style) const {
const int yPos = y + getFontAscenderSize(fontId);
int32_t xPosFP = fp4::fromPixel(x); // 12.4 fixed-point accumulator
int lastBaseX = x;
int lastBaseLeft = 0;
int lastBaseWidth = 0;
int lastBaseTop = 0;
int lastBaseAdvanceFP = 0; // 12.4 fixed-point
int32_t prevAdvanceFP = 0; // 12.4 fixed-point: prev glyph's advance + next kern for snap
// cannot draw a NULL / empty string
if (text == nullptr || *text == '\0') {
@@ -788,20 +789,24 @@ void GfxRenderer::drawText(const int fontId, const int x, const int y, const cha
}
cp = font.applyLigatures(cp, text, style);
const int kernFP = (prevCp != 0) ? font.getKerning(prevCp, cp, style) : 0; // 4.4 fixed-point kern
xPosFP += kernFP;
lastBaseX = fp4::toPixel(xPosFP); // snap 12.4 fixed-point to nearest pixel
// Differential rounding: snap (previous advance + current kern) as one unit so
// identical character pairs always produce the same pixel step regardless of
// where they fall on the line.
if (prevCp != 0) {
const auto kernFP = font.getKerning(prevCp, cp, style); // 4.4 fixed-point kern
lastBaseX += fp4::toPixel(prevAdvanceFP + kernFP); // snap 12.4 fixed-point to nearest pixel
}
const EpdGlyph* glyph = font.getGlyph(cp, style);
lastBaseLeft = glyph ? glyph->left : 0;
lastBaseWidth = glyph ? glyph->width : 0;
lastBaseTop = glyph ? glyph->top : 0;
lastBaseAdvanceFP = glyph ? glyph->advanceX : 0;
prevAdvanceFP = lastBaseAdvanceFP;
renderCharImpl<TextRotation::None>(*this, renderMode, font, cp, lastBaseX, yPos, black, style);
if (glyph) {
xPosFP += glyph->advanceX; // 12.4 fixed-point advance
}
prevCp = cp;
}
}
@@ -1583,10 +1588,17 @@ void GfxRenderer::invertScreen() const {
}
}
void GfxRenderer::setNextDisplayRefreshMode(const HalDisplay::RefreshMode refreshMode) const {
useNextRefreshOverride = true;
nextRefreshOverride = refreshMode;
}
void GfxRenderer::displayBuffer(const HalDisplay::RefreshMode refreshMode) const {
const auto effectiveMode = useNextRefreshOverride ? nextRefreshOverride : refreshMode;
useNextRefreshOverride = false;
auto elapsed = millis() - start_ms;
LOG_DBG("GFX", "Time = %lu ms from clearScreen to displayBuffer", elapsed);
display.displayBuffer(refreshMode, fadingFix);
display.displayBuffer(effectiveMode, fadingFix);
}
std::string GfxRenderer::truncatedText(const int fontId, const char* text, const int maxWidth,
@@ -1744,21 +1756,28 @@ int GfxRenderer::getTextAdvanceX(const int fontId, const char* text, EpdFontFami
uint32_t cp;
uint32_t prevCp = 0;
int32_t widthFP = 0; // 12.4 fixed-point accumulator
int widthPx = 0;
int32_t prevAdvanceFP = 0; // 12.4 fixed-point: prev glyph's advance + next kern for snap
const auto& font = fontIt->second;
while ((cp = utf8NextCodepoint(reinterpret_cast<const uint8_t**>(&text)))) {
if (utf8IsCombiningMark(cp)) {
continue;
}
cp = font.applyLigatures(cp, text, style);
// Differential rounding: snap (previous advance + current kern) together,
// matching drawText so measurement and rendering agree exactly.
if (prevCp != 0) {
widthFP += font.getKerning(prevCp, cp, style); // 4.4 fixed-point kern
const auto kernFP = font.getKerning(prevCp, cp, style); // 4.4 fixed-point kern
widthPx += fp4::toPixel(prevAdvanceFP + kernFP); // snap 12.4 fixed-point to nearest pixel
}
const EpdGlyph* glyph = font.getGlyph(cp, style);
if (glyph) widthFP += glyph->advanceX; // 12.4 fixed-point advance
prevAdvanceFP = glyph ? glyph->advanceX : 0;
prevCp = cp;
}
return fp4::toPixel(widthFP); // snap 12.4 fixed-point to nearest pixel
widthPx += fp4::toPixel(prevAdvanceFP); // final glyph's advance
return widthPx;
}
int GfxRenderer::getFontAscenderSize(const int fontId) const {
@@ -1805,11 +1824,12 @@ void GfxRenderer::drawTextRotated90CW(const int fontId, const int x, const int y
const auto& font = fontIt->second;
int32_t yPosFP = fp4::fromPixel(y); // 12.4 fixed-point accumulator
int lastBaseY = y;
int lastBaseLeft = 0;
int lastBaseWidth = 0;
int lastBaseTop = 0;
int lastBaseAdvanceFP = 0; // 12.4 fixed-point
int32_t prevAdvanceFP = 0; // 12.4 fixed-point: prev glyph's advance + next kern for snap
uint32_t cp;
uint32_t prevCp = 0;
@@ -1826,21 +1846,23 @@ void GfxRenderer::drawTextRotated90CW(const int fontId, const int x, const int y
}
cp = font.applyLigatures(cp, text, style);
// Differential rounding: snap (previous advance + current kern) as one unit,
// subtracting for the rotated coordinate direction.
if (prevCp != 0) {
yPosFP -= font.getKerning(prevCp, cp, style); // 4.4 fixed-point kern (subtract for rotated)
const auto kernFP = font.getKerning(prevCp, cp, style); // 4.4 fixed-point kern
lastBaseY -= fp4::toPixel(prevAdvanceFP + kernFP); // snap 12.4 fixed-point to nearest pixel
}
lastBaseY = fp4::toPixel(yPosFP); // snap 12.4 fixed-point to nearest pixel
const EpdGlyph* glyph = font.getGlyph(cp, style);
lastBaseLeft = glyph ? glyph->left : 0;
lastBaseWidth = glyph ? glyph->width : 0;
lastBaseTop = glyph ? glyph->top : 0;
lastBaseAdvanceFP = glyph ? glyph->advanceX : 0;
prevAdvanceFP = lastBaseAdvanceFP;
renderCharImpl<TextRotation::Rotated90CW>(*this, renderMode, font, cp, x, lastBaseY, black, style);
if (glyph) {
yPosFP -= glyph->advanceX; // 12.4 fixed-point advance (subtract for rotated)
}
prevCp = cp;
}
}
+3
View File
@@ -47,6 +47,8 @@ class GfxRenderer {
// recording to the (non-const) FontCacheManager. Same pragmatic compromise
// as before, concentrated in a single pointer instead of four fields.
mutable FontCacheManager* fontCacheManager_ = nullptr;
mutable bool useNextRefreshOverride = false;
mutable HalDisplay::RefreshMode nextRefreshOverride = HalDisplay::FAST_REFRESH;
void renderChar(const EpdFontFamily& fontFamily, uint32_t cp, int* x, int* y, bool pixelState,
EpdFontFamily::Style style) const;
@@ -92,6 +94,7 @@ class GfxRenderer {
int getScreenWidth() const;
int getScreenHeight() const;
void displayBuffer(HalDisplay::RefreshMode refreshMode = HalDisplay::FAST_REFRESH) const;
void setNextDisplayRefreshMode(HalDisplay::RefreshMode refreshMode) const;
// EXPERIMENTAL: Windowed update - display only a rectangular region
// void displayWindow(int x, int y, int width, int height) const;
void invertScreen() const;