diff --git a/lib/EpdFont/SdCardFont.cpp b/lib/EpdFont/SdCardFont.cpp index 2d29a13e..8ad12863 100644 --- a/lib/EpdFont/SdCardFont.cpp +++ b/lib/EpdFont/SdCardFont.cpp @@ -574,7 +574,7 @@ int32_t SdCardFont::findGlobalGlyphIndex(const PerStyle& s, uint32_t codepoint) // --- Prewarm --- -int SdCardFont::prewarm(const char* utf8Text, uint8_t styleMask, bool metadataOnly) { +int SdCardFont::prewarm(const char* utf8Text, uint8_t styleMask, bool metadataOnly, bool loadKernLigatureData) { if (!loaded_) return -1; unsigned long startMs = millis(); @@ -624,10 +624,9 @@ int SdCardFont::prewarm(const char* utf8Text, uint8_t styleMask, bool metadataOn } // Add ligature output codepoints from all styles being prewarmed. - // Skip during metadata-only prewarm (layout measurement) to avoid loading - // kern/lig data for all styles upfront (~22KB per style). Kern/lig is - // loaded per-style in prewarmStyle() during the full render prewarm instead. - if (!metadataOnly) { + // Load ligature metadata when either doing a full prewarm or when + // metadata-only layout measurement needs applyLigatures()/getKerning(). + if (!metadataOnly || loadKernLigatureData) { for (uint8_t si = 0; si < MAX_STYLES; si++) { if (!(styleMask & (1 << si)) || !styles_[si].present) continue; auto& s = styles_[si]; @@ -669,7 +668,7 @@ int SdCardFont::prewarm(const char* utf8Text, uint8_t styleMask, bool metadataOn int totalMissed = 0; for (uint8_t si = 0; si < MAX_STYLES; si++) { if (!(styleMask & (1 << si)) || !styles_[si].present) continue; - totalMissed += prewarmStyle(si, codepoints.get(), cpCount, metadataOnly); + totalMissed += prewarmStyle(si, codepoints.get(), cpCount, metadataOnly, loadKernLigatureData); } stats_.prewarmTotalMs = millis() - startMs; @@ -702,7 +701,8 @@ bool SdCardFont::allCpsCovered(const PerStyle& s, const uint32_t* codepoints, ui return true; } -int SdCardFont::prewarmStyle(uint8_t styleIdx, const uint32_t* codepoints, uint32_t cpCount, bool metadataOnly) { +int SdCardFont::prewarmStyle(uint8_t styleIdx, const uint32_t* codepoints, uint32_t cpCount, bool metadataOnly, + bool loadKernLigatureData) { auto& s = styles_[styleIdx]; // ---- Fast-path coverage check ---- @@ -1104,10 +1104,10 @@ int SdCardFont::prewarmStyle(uint8_t styleIdx, const uint32_t* codepoints, uint3 // Full render prewarm: load the persistent kern classes + ligatures (one-time // per style, small — the big matrix is NOT loaded here) and then build the // per-page mini kern matrix restricted to class pairs reachable from this - // page's codepoints. Skip during metadata-only prewarm — layout only needs - // advanceX and the mini kern would be thrown away before rendering. + // page's codepoints. Also do this during layout-only metadata prewarm when + // kern/ligature metadata is explicitly requested. bool kernLigOk = false; - if (!metadataOnly) { + if (!metadataOnly || loadKernLigatureData) { if (loadStyleKernLigatureData(s)) { kernLigOk = buildMiniKernMatrix(s, codepoints, cpCount); } diff --git a/lib/EpdFont/SdCardFont.h b/lib/EpdFont/SdCardFont.h index e21f5c34..108145b1 100644 --- a/lib/EpdFont/SdCardFont.h +++ b/lib/EpdFont/SdCardFont.h @@ -22,8 +22,11 @@ class SdCardFont { // styleMask: bitmask of styles to prewarm (bit 0=regular, 1=bold, 2=italic, 3=bolditalic). // Default 0x0F = all present styles. // When metadataOnly=true, only glyph metrics are loaded (no bitmap data). + // If loadKernLigatureData=true, kern/ligature metadata is also loaded so layout + // measurement calls that use applyLigatures()/getKerning() produce correct results. // Returns number of glyphs that couldn't be loaded (0 on full success). - int prewarm(const char* utf8Text, uint8_t styleMask = 0x0F, bool metadataOnly = false); + int prewarm(const char* utf8Text, uint8_t styleMask = 0x0F, bool metadataOnly = false, + bool loadKernLigatureData = false); // Free mini data for all styles, restore stub EpdFontData. void clearCache(); diff --git a/lib/GfxRenderer/GfxRenderer.cpp b/lib/GfxRenderer/GfxRenderer.cpp index 011f5a67..961a3063 100644 --- a/lib/GfxRenderer/GfxRenderer.cpp +++ b/lib/GfxRenderer/GfxRenderer.cpp @@ -43,7 +43,8 @@ void GfxRenderer::ensureSdCardFontReady(int fontId, const char* utf8Text) const // Metadata-only: loads glyph metrics (advanceX) without bitmap data. // Saves ~50-100KB heap vs full prewarm — layout only needs advance widths. // Prewarm all present styles (0x0F) for layout measurement. - int missed = it->second->prewarm(utf8Text, 0x0F, /*metadataOnly=*/true); + int missed = it->second->prewarm(utf8Text, 0x0F, /*metadataOnly=*/true, + /*loadKernLigatureData=*/true); if (missed > 0) { LOG_DBG("GFX", "ensureSdCardFontReady: %d glyph(s) not found", missed); }