fix: handle fallbacks for advance table and prewarm (#1929)
## Summary - Fixes #1928 by having the prewarm and advance table functions resolve fallback styles --- ### AI Usage Did you use AI tools to help write this code? YES - Codex --------- Co-authored-by: Uri Tauber <uritaube@gmail.com> # Conflicts: # lib/EpdFont/SdCardFont.cpp
This commit is contained in:
committed by
Zach Nelson
parent
b971f7bda4
commit
fd79074d43
@@ -9,6 +9,8 @@
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
|
||||
#include "EpdFontFamily.h"
|
||||
|
||||
static_assert(sizeof(EpdGlyph) == 16, "EpdGlyph must be 16 bytes to match .cpfont file layout");
|
||||
static_assert(sizeof(EpdUnicodeInterval) == 12, "EpdUnicodeInterval must be 12 bytes to match .cpfont file layout");
|
||||
static_assert(sizeof(EpdKernClassEntry) == 3, "EpdKernClassEntry must be 3 bytes to match .cpfont file layout");
|
||||
@@ -617,6 +619,8 @@ int32_t SdCardFont::findGlobalGlyphIndex(const PerStyle& s, uint32_t codepoint)
|
||||
|
||||
int SdCardFont::prewarm(const char* utf8Text, uint8_t styleMask, bool metadataOnly) {
|
||||
if (!loaded_) return -1;
|
||||
styleMask = resolveStyleMask(styleMask);
|
||||
if (styleMask == 0) return 0;
|
||||
|
||||
unsigned long startMs = millis();
|
||||
|
||||
@@ -1211,6 +1215,35 @@ EpdFont* SdCardFont::getEpdFont(uint8_t style) {
|
||||
|
||||
bool SdCardFont::hasStyle(uint8_t style) const { return styles_[style & (MAX_STYLES - 1)].present; }
|
||||
|
||||
uint8_t SdCardFont::resolveStyle(uint8_t style) const {
|
||||
static const uint8_t kFallbacks[MAX_STYLES][MAX_STYLES] = {
|
||||
// REGULAR: REGULAR -> BOLD -> ITALIC -> BOLD_ITALIC
|
||||
{EpdFontFamily::REGULAR, EpdFontFamily::BOLD, EpdFontFamily::ITALIC, EpdFontFamily::BOLD_ITALIC},
|
||||
// BOLD: BOLD -> REGULAR -> BOLD_ITALIC -> ITALIC
|
||||
{EpdFontFamily::BOLD, EpdFontFamily::REGULAR, EpdFontFamily::BOLD_ITALIC, EpdFontFamily::ITALIC},
|
||||
// ITALIC: ITALIC -> REGULAR -> BOLD_ITALIC -> BOLD
|
||||
{EpdFontFamily::ITALIC, EpdFontFamily::REGULAR, EpdFontFamily::BOLD_ITALIC, EpdFontFamily::BOLD},
|
||||
// BOLD_ITALIC: BOLD_ITALIC -> BOLD -> ITALIC -> REGULAR
|
||||
{EpdFontFamily::BOLD_ITALIC, EpdFontFamily::BOLD, EpdFontFamily::ITALIC, EpdFontFamily::REGULAR},
|
||||
};
|
||||
|
||||
const uint8_t styleBits = style & (MAX_STYLES - 1);
|
||||
for (uint8_t candidate : kFallbacks[styleBits]) {
|
||||
if (styles_[candidate].present) return candidate;
|
||||
}
|
||||
return EpdFontFamily::REGULAR;
|
||||
}
|
||||
|
||||
uint8_t SdCardFont::resolveStyleMask(uint8_t styleMask) const {
|
||||
uint8_t resolvedMask = 0;
|
||||
for (uint8_t si = 0; si < MAX_STYLES; si++) {
|
||||
if (styleMask & (1 << si)) {
|
||||
resolvedMask |= static_cast<uint8_t>(1u << resolveStyle(si));
|
||||
}
|
||||
}
|
||||
return resolvedMask;
|
||||
}
|
||||
|
||||
// --- On-demand glyph loading (overflow buffer) ---
|
||||
|
||||
const EpdGlyph* SdCardFont::onGlyphMiss(void* ctx, uint32_t codepoint) {
|
||||
|
||||
@@ -74,6 +74,13 @@ class SdCardFont {
|
||||
// Returns true if the given style is present in this font file.
|
||||
bool hasStyle(uint8_t style) const;
|
||||
|
||||
// Resolve requested style bits to the closest present style.
|
||||
uint8_t resolveStyle(uint8_t style) const;
|
||||
|
||||
// Resolve every requested style bit through fallback and return the actual
|
||||
// styles that need cache/advance preparation.
|
||||
uint8_t resolveStyleMask(uint8_t styleMask) const;
|
||||
|
||||
// Number of styles present in this font file.
|
||||
uint8_t styleCount() const { return styleCount_; }
|
||||
|
||||
|
||||
@@ -19,23 +19,7 @@ const char* resolveVisualText(const char* text, std::string& visualBuffer, int p
|
||||
* Falls back gracefully when the font lacks the requested variant.
|
||||
*/
|
||||
uint8_t resolveSdCardStyle(const SdCardFont& font, const EpdFontFamily::Style style) {
|
||||
// Indexed by styleBits (0=REGULAR, 1=BOLD, 2=ITALIC, 3=BOLD_ITALIC)
|
||||
static const uint8_t kFallbacks[4][4] = {
|
||||
// REGULAR: REGULAR → BOLD → ITALIC → BOLD_ITALIC
|
||||
{EpdFontFamily::REGULAR, EpdFontFamily::BOLD, EpdFontFamily::ITALIC, EpdFontFamily::BOLD_ITALIC},
|
||||
// BOLD: BOLD → BOLD_ITALIC → REGULAR → ITALIC
|
||||
{EpdFontFamily::BOLD, EpdFontFamily::BOLD_ITALIC, EpdFontFamily::REGULAR, EpdFontFamily::ITALIC},
|
||||
// ITALIC: ITALIC → REGULAR → BOLD → BOLD_ITALIC (REGULAR before BOLD!)
|
||||
{EpdFontFamily::ITALIC, EpdFontFamily::REGULAR, EpdFontFamily::BOLD, EpdFontFamily::BOLD_ITALIC},
|
||||
// BOLD_ITALIC: BOLD_ITALIC → BOLD → ITALIC → REGULAR
|
||||
{EpdFontFamily::BOLD_ITALIC, EpdFontFamily::BOLD, EpdFontFamily::ITALIC, EpdFontFamily::REGULAR},
|
||||
};
|
||||
|
||||
const uint8_t styleBits = static_cast<uint8_t>(style) & 0x03;
|
||||
for (uint8_t candidate : kFallbacks[styleBits]) {
|
||||
if (font.hasStyle(candidate)) return candidate;
|
||||
}
|
||||
return EpdFontFamily::REGULAR; // no-variant-at-all safety net
|
||||
return font.resolveStyle(static_cast<uint8_t>(style));
|
||||
}
|
||||
} // namespace
|
||||
|
||||
|
||||
Reference in New Issue
Block a user