Proper refresh on exit
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user