#include "SdCardFontSystem.h" #include #include #include "CrossPointSettings.h" namespace { static uint8_t fontSizeEnumFromSettings() { uint8_t e = SETTINGS.fontSize; if (e >= CrossPointSettings::FONT_SIZE_COUNT) e = 1; // default to MEDIUM return e; } } // namespace void SdCardFontSystem::begin(GfxRenderer& renderer) { registry_.discover(); // Register this system as the SD font ID resolver in settings. // Uses a static trampoline since CrossPointSettings stores a plain function pointer. SETTINGS.sdFontIdResolver = [](void* ctx, const char* familyName, uint8_t fontSizeEnum) -> int { return static_cast(ctx)->resolveFontId(familyName, fontSizeEnum); }; SETTINGS.sdFontResolverCtx = this; // If user has a saved SD font selection, load it if (SETTINGS.sdFontFamilyName[0] != '\0') { const auto* family = registry_.findFamily(SETTINGS.sdFontFamilyName); if (family) { if (manager_.loadFamily(*family, renderer, fontSizeEnumFromSettings())) { LOG_DBG("SDFS", "Loaded SD card font family: %s", SETTINGS.sdFontFamilyName); } else { LOG_ERR("SDFS", "Failed to load SD font family: %s (clearing)", SETTINGS.sdFontFamilyName); SETTINGS.sdFontFamilyName[0] = '\0'; } } else { LOG_DBG("SDFS", "SD font family not found on card: %s (clearing)", SETTINGS.sdFontFamilyName); SETTINGS.sdFontFamilyName[0] = '\0'; } } LOG_DBG("SDFS", "SD font system ready (%d families discovered)", registry_.getFamilyCount()); } void SdCardFontSystem::ensureLoaded(GfxRenderer& renderer) { // If the web server (or another task) installed/deleted fonts, re-discover. // Track whether we just re-discovered so we can force a reload below even // when the wanted family/size still maps to the same point size — the file // contents on disk may have changed (e.g. user re-uploaded a new build). const bool registryWasDirty = registryDirty_.exchange(false, std::memory_order_acquire); if (registryWasDirty) { LOG_DBG("SDFS", "Registry dirty — re-discovering fonts"); registry_.discover(); } const char* wantedFamily = SETTINGS.sdFontFamilyName; const std::string& currentFamily = manager_.currentFamilyName(); const uint8_t sizeEnum = fontSizeEnumFromSettings(); if (wantedFamily[0] == '\0') { if (!currentFamily.empty()) { manager_.unloadAll(renderer); } return; } // Reload if family changed OR if the user-selected size maps to a // different file than what's currently loaded OR if the registry was // just rediscovered (file may have been replaced on disk). bool familyMatches = (currentFamily == wantedFamily); if (familyMatches) { const auto* family = registry_.findFamily(wantedFamily); if (!family) { LOG_DBG("SDFS", "SD font family disappeared: %s (clearing)", wantedFamily); manager_.unloadAll(renderer); SETTINGS.sdFontFamilyName[0] = '\0'; return; } const auto* selected = family->findClosestReaderSize(sizeEnum); const uint8_t wantedPt = selected ? selected->pointSize : 0; if (!registryWasDirty && wantedPt == manager_.currentPointSize()) return; LOG_DBG("SDFS", "Reloading %s: size %u -> %u (enum %u)%s", wantedFamily, manager_.currentPointSize(), wantedPt, sizeEnum, registryWasDirty ? " [registry dirty]" : ""); } if (!currentFamily.empty()) { manager_.unloadAll(renderer); } const auto* family = registry_.findFamily(wantedFamily); if (family) { if (manager_.loadFamily(*family, renderer, sizeEnum)) { LOG_DBG("SDFS", "Loaded SD font family: %s", wantedFamily); } else { LOG_ERR("SDFS", "Failed to load SD font family: %s (clearing)", wantedFamily); SETTINGS.sdFontFamilyName[0] = '\0'; } } else { LOG_DBG("SDFS", "SD font family not found: %s (clearing)", wantedFamily); SETTINGS.sdFontFamilyName[0] = '\0'; } } int SdCardFontSystem::resolveFontId(const char* familyName, uint8_t /*fontSizeEnum*/) const { // The manager loads exactly one size (closest to SETTINGS.fontSize), so the // enum is implicit — always return the single loaded font ID for this family. // ensureLoaded() must have been called with the current settings before this. return manager_.getFontId(familyName); }