| 29 | } |
| 30 | |
| 31 | bool SdCardFontManager::loadFamily(const SdCardFontFamilyInfo& family, GfxRenderer& renderer, uint8_t fontSizeEnum) { |
| 32 | // Unload any previously loaded family first |
| 33 | if (!loadedFamilyName_.empty()) { |
| 34 | unloadAll(renderer); |
| 35 | } |
| 36 | |
| 37 | // Select the physical point size closest to the built-in reader sizes. Some |
| 38 | // CJK font packs only ship larger sizes, so ordinal selection can make |
| 39 | // MEDIUM load 18pt+ and produce oversized pages on small devices. |
| 40 | const SdCardFontFileInfo* selected = family.findClosestReaderSize(fontSizeEnum); |
| 41 | if (!selected) { |
| 42 | LOG_ERR("SDMGR", "Family %s has no files to load", family.name.c_str()); |
| 43 | return false; |
| 44 | } |
| 45 | |
| 46 | auto* font = new (std::nothrow) SdCardFont(); |
| 47 | if (!font) { |
| 48 | LOG_ERR("SDMGR", "Failed to allocate SdCardFont for %s", selected->path.c_str()); |
| 49 | return false; |
| 50 | } |
| 51 | |
| 52 | if (!font->load(selected->path.c_str())) { |
| 53 | LOG_ERR("SDMGR", "Failed to load %s", selected->path.c_str()); |
| 54 | delete font; |
| 55 | return false; |
| 56 | } |
| 57 | |
| 58 | int fontId = computeFontId(font->contentHash(), family.name.c_str(), selected->pointSize); |
| 59 | // Guard against collision with built-in font IDs (astronomically unlikely |
| 60 | // with FNV-1a hashes, but provides a safety net) |
| 61 | if (renderer.getFontMap().count(fontId) != 0) { |
| 62 | LOG_ERR("SDMGR", "Font ID %d collides with existing font, skipping %s", fontId, selected->path.c_str()); |
| 63 | delete font; |
| 64 | return false; |
| 65 | } |
| 66 | renderer.registerSdCardFont(fontId, font); |
| 67 | loaded_.push_back({font, fontId, selected->pointSize}); |
| 68 | |
| 69 | LOG_DBG("SDMGR", "Loaded %s size=%u id=%d styles=%u (sizeEnum=%u)", selected->path.c_str(), selected->pointSize, |
| 70 | fontId, font->styleCount(), fontSizeEnum); |
| 71 | |
| 72 | EpdFontFamily fontFamily(font->getEpdFont(0), font->getEpdFont(1), font->getEpdFont(2), font->getEpdFont(3)); |
| 73 | renderer.insertFont(fontId, fontFamily); |
| 74 | |
| 75 | loadedFamilyName_ = family.name; |
| 76 | loadedPointSize_ = selected->pointSize; |
| 77 | return true; |
| 78 | } |
| 79 | |
| 80 | void SdCardFontManager::unloadAll(GfxRenderer& renderer) { |
| 81 | renderer.clearSdCardFonts(); |
no test coverage detected