Some review comments
This commit is contained in:
@@ -432,7 +432,14 @@ bool SdCardFont::load(const char* path) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Begin content hash: accumulate global header
|
||||
// Begin content hash: accumulate global header.
|
||||
// KNOWN LIMITATION: hash covers global header + per-style TOC only, not the
|
||||
// payload sections (intervals / glyph metrics / kern / ligature / bitmap). A
|
||||
// font edit that alters payload bytes without changing any TOC count would
|
||||
// produce the same contentHash and could leave stale EPUB section caches.
|
||||
// Acceptable in practice because generate-sd-fonts.sh regeneration almost
|
||||
// always changes interval/glyph/kern counts; revisit if we see real-world
|
||||
// mismatches.
|
||||
uint32_t hash = fnv1a(headerBuf, HEADER_SIZE);
|
||||
|
||||
bool is2Bit = (readU16(headerBuf + 10) & 1) != 0;
|
||||
@@ -1214,7 +1221,12 @@ const EpdGlyph* SdCardFont::onGlyphMiss(void* ctx, uint32_t codepoint) {
|
||||
|
||||
EpdGlyph tempGlyph;
|
||||
uint32_t glyphFileOff = s.glyphsFileOffset + static_cast<uint32_t>(globalIdx) * sizeof(EpdGlyph);
|
||||
file.seekSet(glyphFileOff);
|
||||
if (!file.seekSet(glyphFileOff)) {
|
||||
LOG_ERR("SDCF", "Overflow: seek failed for glyph metadata U+%04X style %u", codepoint, styleIdx);
|
||||
file.close();
|
||||
if (!wasAtCapacity) self->overflowCount_--;
|
||||
return nullptr;
|
||||
}
|
||||
if (file.read(reinterpret_cast<uint8_t*>(&tempGlyph), sizeof(EpdGlyph)) != sizeof(EpdGlyph)) {
|
||||
LOG_ERR("SDCF", "Overflow: failed to read glyph metadata for U+%04X style %u", codepoint, styleIdx);
|
||||
file.close();
|
||||
@@ -1232,7 +1244,13 @@ const EpdGlyph* SdCardFont::onGlyphMiss(void* ctx, uint32_t codepoint) {
|
||||
if (!wasAtCapacity) self->overflowCount_--;
|
||||
return nullptr;
|
||||
}
|
||||
file.seekSet(s.bitmapFileOffset + tempGlyph.dataOffset);
|
||||
if (!file.seekSet(s.bitmapFileOffset + tempGlyph.dataOffset)) {
|
||||
LOG_ERR("SDCF", "Overflow: seek failed for bitmap U+%04X style %u", codepoint, styleIdx);
|
||||
delete[] tempBitmap;
|
||||
file.close();
|
||||
if (!wasAtCapacity) self->overflowCount_--;
|
||||
return nullptr;
|
||||
}
|
||||
if (file.read(tempBitmap, tempGlyph.dataLength) != static_cast<int>(tempGlyph.dataLength)) {
|
||||
LOG_ERR("SDCF", "Overflow: failed to read bitmap for U+%04X", codepoint);
|
||||
delete[] tempBitmap;
|
||||
|
||||
@@ -39,15 +39,7 @@ bool SdCardFontManager::loadFamily(const SdCardFontFamilyInfo& family, GfxRender
|
||||
// Pick the single file whose size is closest to targetPtSize. Loading
|
||||
// only one size bounds resident memory (intervals + kern/ligature tables
|
||||
// per style) to one file's worth, vs. N_sizes × per-file overhead.
|
||||
const SdCardFontFileInfo* selected = nullptr;
|
||||
int bestDiff = INT32_MAX;
|
||||
for (const auto& fileInfo : family.files) {
|
||||
int diff = std::abs(static_cast<int>(fileInfo.pointSize) - static_cast<int>(targetPtSize));
|
||||
if (diff < bestDiff) {
|
||||
bestDiff = diff;
|
||||
selected = &fileInfo;
|
||||
}
|
||||
}
|
||||
const SdCardFontFileInfo* selected = family.pickClosestSize(targetPtSize);
|
||||
if (!selected) {
|
||||
LOG_ERR("SDMGR", "Family %s has no files to load", family.name.c_str());
|
||||
return false;
|
||||
|
||||
@@ -38,6 +38,21 @@ std::vector<uint8_t> SdCardFontFamilyInfo::availableSizes() const {
|
||||
return sizes;
|
||||
}
|
||||
|
||||
const SdCardFontFileInfo* SdCardFontFamilyInfo::pickClosestSize(uint8_t targetPtSize) const {
|
||||
const SdCardFontFileInfo* selected = nullptr;
|
||||
int bestDiff = INT32_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 ---
|
||||
|
||||
bool SdCardFontRegistry::parseFilename(const char* filename, uint8_t& size, uint8_t& style) {
|
||||
|
||||
@@ -19,6 +19,11 @@ struct SdCardFontFamilyInfo {
|
||||
const SdCardFontFileInfo* findFile(uint8_t size, uint8_t style = 0) const;
|
||||
bool hasSize(uint8_t size) 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.
|
||||
const SdCardFontFileInfo* pickClosestSize(uint8_t targetPtSize) const;
|
||||
};
|
||||
|
||||
class SdCardFontRegistry {
|
||||
|
||||
@@ -451,6 +451,12 @@ def rasterize_font_style(fontfile, size, intervals, style_id=0, force_autohint=F
|
||||
style_label = style_names.get(style_id, str(style_id))
|
||||
|
||||
face = freetype.Face(fontfile)
|
||||
# Set font size at 150 DPI (matching fontconvert.py) BEFORE any glyph load
|
||||
# — load_glyph() with FT_LOAD_RENDER renders at the active size, so calling
|
||||
# it before set_char_size() would waste work at the default size and risk
|
||||
# Invalid_Size_Handle on some fonts.
|
||||
face.set_char_size(size << 6, size << 6, 150, 150)
|
||||
|
||||
load_flags = freetype.FT_LOAD_RENDER
|
||||
if force_autohint:
|
||||
load_flags |= freetype.FT_LOAD_FORCE_AUTOHINT
|
||||
@@ -480,9 +486,6 @@ def rasterize_font_style(fontfile, size, intervals, style_id=0, force_autohint=F
|
||||
total_glyphs = sum(end - start + 1 for start, end in intervals)
|
||||
print(f" [{style_label}] Validated: {len(intervals)} intervals, {total_glyphs} glyphs", file=sys.stderr)
|
||||
|
||||
# Set font size at 150 DPI (matching fontconvert.py)
|
||||
face.set_char_size(size << 6, size << 6, 150, 150)
|
||||
|
||||
# Rasterize all glyphs
|
||||
total_bitmap_size = 0
|
||||
all_glyphs = []
|
||||
|
||||
Reference in New Issue
Block a user