Revert "feat: closest-pt size selection instead of ordinal slot" (#1949)
Reverts crosspoint-reader/crosspoint-reader#1912 This was meant to be more robust with partial SD card fonts, but causes trouble for folks using custom font sizes. We need a better approach to decouple numeric font sizes from S/M/L/XL settings.
This commit is contained in:
@@ -28,21 +28,25 @@ int SdCardFontManager::computeFontId(uint32_t contentHash, const char* familyNam
|
|||||||
return id != 0 ? id : 1; // 0 is reserved as "not found" sentinel
|
return id != 0 ? id : 1; // 0 is reserved as "not found" sentinel
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SdCardFontManager::loadFamily(const SdCardFontFamilyInfo& family, GfxRenderer& renderer, uint8_t targetPtSize) {
|
bool SdCardFontManager::loadFamily(const SdCardFontFamilyInfo& family, GfxRenderer& renderer, uint8_t fontSizeEnum) {
|
||||||
// Unload any previously loaded family first
|
// Unload any previously loaded family first
|
||||||
if (!loadedFamilyName_.empty()) {
|
if (!loadedFamilyName_.empty()) {
|
||||||
unloadAll(renderer);
|
unloadAll(renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pick the single file whose size is closest to targetPtSize. Loading
|
// Select by ordinal position: sort available sizes, then map the font size
|
||||||
// only one size bounds resident memory (intervals + kern/ligature tables
|
// enum (SMALL=0 .. EXTRA_LARGE=3) to the corresponding slot. When the
|
||||||
// per style) to one file's worth, vs. N_sizes × per-file overhead.
|
// family has fewer sizes than 4, clamp to the last available size.
|
||||||
const SdCardFontFileInfo* selected = family.pickClosestSize(targetPtSize);
|
auto sizes = family.availableSizes();
|
||||||
if (!selected) {
|
if (sizes.empty()) {
|
||||||
LOG_ERR("SDMGR", "Family %s has no files to load", family.name.c_str());
|
LOG_ERR("SDMGR", "Family %s has no files to load", family.name.c_str());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t idx = fontSizeEnum;
|
||||||
|
if (idx >= sizes.size()) idx = sizes.size() - 1;
|
||||||
|
const SdCardFontFileInfo* selected = family.findFile(sizes[idx]);
|
||||||
|
|
||||||
auto* font = new (std::nothrow) SdCardFont();
|
auto* font = new (std::nothrow) SdCardFont();
|
||||||
if (!font) {
|
if (!font) {
|
||||||
LOG_ERR("SDMGR", "Failed to allocate SdCardFont for %s", selected->path.c_str());
|
LOG_ERR("SDMGR", "Failed to allocate SdCardFont for %s", selected->path.c_str());
|
||||||
@@ -66,8 +70,8 @@ bool SdCardFontManager::loadFamily(const SdCardFontFamilyInfo& family, GfxRender
|
|||||||
renderer.registerSdCardFont(fontId, font);
|
renderer.registerSdCardFont(fontId, font);
|
||||||
loaded_.push_back({font, fontId, selected->pointSize});
|
loaded_.push_back({font, fontId, selected->pointSize});
|
||||||
|
|
||||||
LOG_DBG("SDMGR", "Loaded %s size=%u id=%d styles=%u (target=%u)", selected->path.c_str(), selected->pointSize, fontId,
|
LOG_DBG("SDMGR", "Loaded %s size=%u id=%d styles=%u (sizeEnum=%u)", selected->path.c_str(), selected->pointSize,
|
||||||
font->styleCount(), targetPtSize);
|
fontId, font->styleCount(), fontSizeEnum);
|
||||||
|
|
||||||
EpdFontFamily fontFamily(font->getEpdFont(0), font->getEpdFont(1), font->getEpdFont(2), font->getEpdFont(3));
|
EpdFontFamily fontFamily(font->getEpdFont(0), font->getEpdFont(1), font->getEpdFont(2), font->getEpdFont(3));
|
||||||
renderer.insertFont(fontId, fontFamily);
|
renderer.insertFont(fontId, fontFamily);
|
||||||
|
|||||||
@@ -15,16 +15,12 @@ class SdCardFontManager {
|
|||||||
SdCardFontManager(const SdCardFontManager&) = delete;
|
SdCardFontManager(const SdCardFontManager&) = delete;
|
||||||
SdCardFontManager& operator=(const SdCardFontManager&) = delete;
|
SdCardFontManager& operator=(const SdCardFontManager&) = delete;
|
||||||
|
|
||||||
// Load the single size whose pointSize is closest to targetPtSize. Only one
|
// Load the font file matching fontSizeEnum (SMALL=0 .. EXTRA_LARGE=3) by
|
||||||
// .cpfont file is loaded; other sizes remain on disk. This keeps resident
|
// ordinal position in the family's sorted size list. Only one .cpfont file
|
||||||
// interval + kern/ligature tables to one size's worth of memory.
|
// is loaded; other sizes remain on disk. This keeps resident interval +
|
||||||
//
|
// kern/ligature tables to one size's worth of memory.
|
||||||
// Closest-pt selection is robust against families that don't ship the
|
|
||||||
// canonical {12,14,16,18}: a family with only [10,14,18] still resolves
|
|
||||||
// any reasonable target, where ordinal slot-mapping by SMALL..EXTRA_LARGE
|
|
||||||
// would mis-select.
|
|
||||||
// Returns true on success.
|
// Returns true on success.
|
||||||
bool loadFamily(const SdCardFontFamilyInfo& family, GfxRenderer& renderer, uint8_t targetPtSize);
|
bool loadFamily(const SdCardFontFamilyInfo& family, GfxRenderer& renderer, uint8_t fontSizeEnum);
|
||||||
|
|
||||||
// Unload everything, unregister from renderer.
|
// Unload everything, unregister from renderer.
|
||||||
void unloadAll(GfxRenderer& renderer);
|
void unloadAll(GfxRenderer& renderer);
|
||||||
|
|||||||
@@ -4,8 +4,6 @@
|
|||||||
#include <Logging.h>
|
#include <Logging.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <climits>
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
// --- SdCardFontFamilyInfo helpers ---
|
// --- SdCardFontFamilyInfo helpers ---
|
||||||
@@ -40,21 +38,6 @@ std::vector<uint8_t> SdCardFontFamilyInfo::availableSizes() const {
|
|||||||
return sizes;
|
return sizes;
|
||||||
}
|
}
|
||||||
|
|
||||||
const SdCardFontFileInfo* SdCardFontFamilyInfo::pickClosestSize(uint8_t targetPtSize) const {
|
|
||||||
const SdCardFontFileInfo* selected = nullptr;
|
|
||||||
int bestDiff = INT_MAX;
|
|
||||||
for (const auto& f : files) {
|
|
||||||
int diff = std::abs(static_cast<int>(f.pointSize) - static_cast<int>(targetPtSize));
|
|
||||||
// Strict < ensures the first scan wins on ties; then tie-break by smaller
|
|
||||||
// pointSize to make the choice independent of filesystem enumeration order.
|
|
||||||
if (diff < bestDiff || (diff == bestDiff && selected && f.pointSize < selected->pointSize)) {
|
|
||||||
bestDiff = diff;
|
|
||||||
selected = &f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return selected;
|
|
||||||
}
|
|
||||||
|
|
||||||
// --- SdCardFontRegistry ---
|
// --- SdCardFontRegistry ---
|
||||||
|
|
||||||
bool SdCardFontRegistry::parseFilename(const char* filename, uint8_t& size, uint8_t& style) {
|
bool SdCardFontRegistry::parseFilename(const char* filename, uint8_t& size, uint8_t& style) {
|
||||||
|
|||||||
@@ -20,15 +20,6 @@ struct SdCardFontFamilyInfo {
|
|||||||
const SdCardFontFileInfo* findFile(uint8_t size, uint8_t style = 0) const;
|
const SdCardFontFileInfo* findFile(uint8_t size, uint8_t style = 0) const;
|
||||||
bool hasSize(uint8_t size) const;
|
bool hasSize(uint8_t size) const;
|
||||||
std::vector<uint8_t> availableSizes() const;
|
std::vector<uint8_t> availableSizes() const;
|
||||||
|
|
||||||
// Pick the file whose pointSize is closest to targetPtSize. On ties (equal
|
|
||||||
// distance) prefers the smaller pointSize so behaviour is deterministic
|
|
||||||
// across SD card layouts. Returns nullptr when files is empty.
|
|
||||||
//
|
|
||||||
// Robust against families that don't ship the canonical {12,14,16,18} set:
|
|
||||||
// a family with only [10,14,18] resolves target 12 → 10 (or 14 on tie),
|
|
||||||
// target 16 → 14 or 18, etc., instead of mis-indexing by ordinal slot.
|
|
||||||
const SdCardFontFileInfo* pickClosestSize(uint8_t targetPtSize) const;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class SdCardFontRegistry {
|
class SdCardFontRegistry {
|
||||||
|
|||||||
+14
-17
@@ -5,15 +5,10 @@
|
|||||||
|
|
||||||
#include "CrossPointSettings.h"
|
#include "CrossPointSettings.h"
|
||||||
|
|
||||||
// Map fontSize enum (SMALL=0, MEDIUM=1, LARGE=2, EXTRA_LARGE=3) to the point
|
static uint8_t fontSizeEnumFromSettings() {
|
||||||
// sizes shipped with the built-in fonts. Used to drive closest-pt selection
|
|
||||||
// in the SD card font registry (see SdCardFontFamilyInfo::pickClosestSize).
|
|
||||||
static constexpr uint8_t FONT_SIZE_TO_PT[CrossPointSettings::FONT_SIZE_COUNT] = {12, 14, 16, 18};
|
|
||||||
|
|
||||||
static uint8_t targetPtSizeFromSettings() {
|
|
||||||
uint8_t e = SETTINGS.fontSize;
|
uint8_t e = SETTINGS.fontSize;
|
||||||
if (e >= CrossPointSettings::FONT_SIZE_COUNT) e = 1; // default to MEDIUM
|
if (e >= CrossPointSettings::FONT_SIZE_COUNT) e = 1; // default to MEDIUM
|
||||||
return FONT_SIZE_TO_PT[e];
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SdCardFontSystem::begin(GfxRenderer& renderer) {
|
void SdCardFontSystem::begin(GfxRenderer& renderer) {
|
||||||
@@ -30,7 +25,7 @@ void SdCardFontSystem::begin(GfxRenderer& renderer) {
|
|||||||
if (SETTINGS.sdFontFamilyName[0] != '\0') {
|
if (SETTINGS.sdFontFamilyName[0] != '\0') {
|
||||||
const auto* family = registry_.findFamily(SETTINGS.sdFontFamilyName);
|
const auto* family = registry_.findFamily(SETTINGS.sdFontFamilyName);
|
||||||
if (family) {
|
if (family) {
|
||||||
if (manager_.loadFamily(*family, renderer, targetPtSizeFromSettings())) {
|
if (manager_.loadFamily(*family, renderer, fontSizeEnumFromSettings())) {
|
||||||
LOG_DBG("SDFS", "Loaded SD card font family: %s", SETTINGS.sdFontFamilyName);
|
LOG_DBG("SDFS", "Loaded SD card font family: %s", SETTINGS.sdFontFamilyName);
|
||||||
} else {
|
} else {
|
||||||
LOG_ERR("SDFS", "Failed to load SD font family: %s (clearing)", SETTINGS.sdFontFamilyName);
|
LOG_ERR("SDFS", "Failed to load SD font family: %s (clearing)", SETTINGS.sdFontFamilyName);
|
||||||
@@ -58,7 +53,7 @@ void SdCardFontSystem::ensureLoaded(GfxRenderer& renderer) {
|
|||||||
|
|
||||||
const char* wantedFamily = SETTINGS.sdFontFamilyName;
|
const char* wantedFamily = SETTINGS.sdFontFamilyName;
|
||||||
const std::string& currentFamily = manager_.currentFamilyName();
|
const std::string& currentFamily = manager_.currentFamilyName();
|
||||||
const uint8_t targetPt = targetPtSizeFromSettings();
|
const uint8_t sizeEnum = fontSizeEnumFromSettings();
|
||||||
|
|
||||||
if (wantedFamily[0] == '\0') {
|
if (wantedFamily[0] == '\0') {
|
||||||
if (!currentFamily.empty()) {
|
if (!currentFamily.empty()) {
|
||||||
@@ -67,8 +62,8 @@ void SdCardFontSystem::ensureLoaded(GfxRenderer& renderer) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reload if family changed OR if the user-selected size now resolves to a
|
// Reload if family changed OR if the user-selected size maps to a
|
||||||
// different on-disk file than what's currently loaded OR if the registry was
|
// different file than what's currently loaded OR if the registry was
|
||||||
// just rediscovered (file may have been replaced on disk).
|
// just rediscovered (file may have been replaced on disk).
|
||||||
bool familyMatches = (currentFamily == wantedFamily);
|
bool familyMatches = (currentFamily == wantedFamily);
|
||||||
if (familyMatches) {
|
if (familyMatches) {
|
||||||
@@ -79,11 +74,13 @@ void SdCardFontSystem::ensureLoaded(GfxRenderer& renderer) {
|
|||||||
SETTINGS.sdFontFamilyName[0] = '\0';
|
SETTINGS.sdFontFamilyName[0] = '\0';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const auto* best = family->pickClosestSize(targetPt);
|
auto sizes = family->availableSizes();
|
||||||
const uint8_t bestPt = best ? best->pointSize : 0;
|
uint8_t idx = sizeEnum;
|
||||||
if (!registryWasDirty && bestPt == manager_.currentPointSize()) return;
|
if (idx >= sizes.size()) idx = sizes.size() - 1;
|
||||||
LOG_DBG("SDFS", "Reloading %s: size %u -> %u (target %u)%s", wantedFamily, manager_.currentPointSize(), bestPt,
|
uint8_t wantedPt = sizes.empty() ? 0 : sizes[idx];
|
||||||
targetPt, registryWasDirty ? " [registry dirty]" : "");
|
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()) {
|
if (!currentFamily.empty()) {
|
||||||
@@ -92,7 +89,7 @@ void SdCardFontSystem::ensureLoaded(GfxRenderer& renderer) {
|
|||||||
|
|
||||||
const auto* family = registry_.findFamily(wantedFamily);
|
const auto* family = registry_.findFamily(wantedFamily);
|
||||||
if (family) {
|
if (family) {
|
||||||
if (manager_.loadFamily(*family, renderer, targetPt)) {
|
if (manager_.loadFamily(*family, renderer, sizeEnum)) {
|
||||||
LOG_DBG("SDFS", "Loaded SD font family: %s", wantedFamily);
|
LOG_DBG("SDFS", "Loaded SD font family: %s", wantedFamily);
|
||||||
} else {
|
} else {
|
||||||
LOG_ERR("SDFS", "Failed to load SD font family: %s (clearing)", wantedFamily);
|
LOG_ERR("SDFS", "Failed to load SD font family: %s (clearing)", wantedFamily);
|
||||||
|
|||||||
Reference in New Issue
Block a user