Establish LUT cache

This commit is contained in:
jpirnay
2026-02-28 16:19:45 +01:00
parent 67fc407d63
commit 19c197e020
2 changed files with 37 additions and 20 deletions
+34 -19
View File
@@ -71,9 +71,8 @@ bool Section::loadSectionFile(const int fontId, const float lineCompression, con
uint8_t version; uint8_t version;
serialization::readPod(file, version); serialization::readPod(file, version);
if (version != SECTION_FILE_VERSION) { if (version != SECTION_FILE_VERSION) {
file.close();
LOG_ERR("SCT", "Deserialization failed: Unknown version %u", version); LOG_ERR("SCT", "Deserialization failed: Unknown version %u", version);
clearCache(); clearCache(); // closes file before removal
return false; return false;
} }
@@ -97,21 +96,30 @@ bool Section::loadSectionFile(const int fontId, const float lineCompression, con
extraParagraphSpacing != fileExtraParagraphSpacing || paragraphAlignment != fileParagraphAlignment || extraParagraphSpacing != fileExtraParagraphSpacing || paragraphAlignment != fileParagraphAlignment ||
viewportWidth != fileViewportWidth || viewportHeight != fileViewportHeight || viewportWidth != fileViewportWidth || viewportHeight != fileViewportHeight ||
hyphenationEnabled != fileHyphenationEnabled || embeddedStyle != fileEmbeddedStyle) { hyphenationEnabled != fileHyphenationEnabled || embeddedStyle != fileEmbeddedStyle) {
file.close();
LOG_ERR("SCT", "Deserialization failed: Parameters do not match"); LOG_ERR("SCT", "Deserialization failed: Parameters do not match");
clearCache(); clearCache(); // closes file before removal
return false; return false;
} }
} }
serialization::readPod(file, pageCount); serialization::readPod(file, pageCount);
file.close();
LOG_DBG("SCT", "Deserialization succeeded: %d pages", pageCount); // Load LUT into memory (file is now positioned at the lutOffset field)
uint32_t lutOffset;
serialization::readPod(file, lutOffset);
lut.resize(pageCount);
file.seek(lutOffset);
for (uint32_t& pos : lut) {
serialization::readPod(file, pos);
}
// File is intentionally left open; subsequent loadPageFromSectionFile() calls
// seek within this handle instead of re-opening the file each time.
LOG_DBG("SCT", "Deserialization succeeded: %d pages, LUT cached", pageCount);
return true; return true;
} }
// Your updated class method (assuming you are using the 'SD' object, which is a wrapper for a specific filesystem) bool Section::clearCache() {
bool Section::clearCache() const { file.close(); // Must be closed before removal on FAT32
if (!Storage.exists(filePath.c_str())) { if (!Storage.exists(filePath.c_str())) {
LOG_DBG("SCT", "Cache does not exist, no action needed"); LOG_DBG("SCT", "Cache does not exist, no action needed");
return true; return true;
@@ -242,23 +250,30 @@ bool Section::createSectionFile(const int fontId, const float lineCompression, c
if (cssParser) { if (cssParser) {
cssParser->clear(); cssParser->clear();
} }
// Cache the LUT in memory and open the file for reading so that
// subsequent loadPageFromSectionFile() calls can seek directly without re-opening.
this->lut = std::move(lut);
Storage.openFileForRead("SCT", filePath, file);
return true; return true;
} }
std::unique_ptr<Page> Section::loadPageFromSectionFile() { std::unique_ptr<Page> Section::loadPageFromSectionFile() {
if (!Storage.openFileForRead("SCT", filePath, file)) { if (currentPage < 0 || currentPage >= static_cast<int>(lut.size())) {
LOG_ERR("SCT", "loadPageFromSectionFile: page %d out of LUT range (%u entries)", currentPage,
static_cast<uint32_t>(lut.size()));
return nullptr; return nullptr;
} }
file.seek(HEADER_SIZE - sizeof(uint32_t)); if (!file) {
uint32_t lutOffset; // Safety fallback: file was closed unexpectedly; reopen
serialization::readPod(file, lutOffset); LOG_ERR("SCT", "loadPageFromSectionFile: file not open, reopening");
file.seek(lutOffset + sizeof(uint32_t) * currentPage); if (!Storage.openFileForRead("SCT", filePath, file)) {
uint32_t pagePos; return nullptr;
serialization::readPod(file, pagePos); }
file.seek(pagePos); }
auto page = Page::deserialize(file); file.seek(lut[currentPage]);
file.close(); return Page::deserialize(file);
return page; // File is intentionally NOT closed; stays open for the next page load
} }
+3 -1
View File
@@ -1,6 +1,7 @@
#pragma once #pragma once
#include <functional> #include <functional>
#include <memory> #include <memory>
#include <vector>
#include "Epub.h" #include "Epub.h"
@@ -13,6 +14,7 @@ class Section {
GfxRenderer& renderer; GfxRenderer& renderer;
std::string filePath; std::string filePath;
FsFile file; FsFile file;
std::vector<uint32_t> lut; // Cached page byte-offsets; loaded once, avoids per-page LUT seek
void writeSectionFileHeader(int fontId, float lineCompression, bool extraParagraphSpacing, uint8_t paragraphAlignment, void writeSectionFileHeader(int fontId, float lineCompression, bool extraParagraphSpacing, uint8_t paragraphAlignment,
uint16_t viewportWidth, uint16_t viewportHeight, bool hyphenationEnabled, uint16_t viewportWidth, uint16_t viewportHeight, bool hyphenationEnabled,
@@ -31,7 +33,7 @@ class Section {
~Section() = default; ~Section() = default;
bool loadSectionFile(int fontId, float lineCompression, bool extraParagraphSpacing, uint8_t paragraphAlignment, bool loadSectionFile(int fontId, float lineCompression, bool extraParagraphSpacing, uint8_t paragraphAlignment,
uint16_t viewportWidth, uint16_t viewportHeight, bool hyphenationEnabled, bool embeddedStyle); uint16_t viewportWidth, uint16_t viewportHeight, bool hyphenationEnabled, bool embeddedStyle);
bool clearCache() const; bool clearCache();
bool createSectionFile(int fontId, float lineCompression, bool extraParagraphSpacing, uint8_t paragraphAlignment, bool createSectionFile(int fontId, float lineCompression, bool extraParagraphSpacing, uint8_t paragraphAlignment,
uint16_t viewportWidth, uint16_t viewportHeight, bool hyphenationEnabled, bool embeddedStyle, uint16_t viewportWidth, uint16_t viewportHeight, bool hyphenationEnabled, bool embeddedStyle,
const std::function<void()>& popupFn = nullptr); const std::function<void()>& popupFn = nullptr);