Move to smart pointers and split out ParsedText class (#6)

* Move to smart pointers and split out ParsedText class

* Cleanup ParsedText

* Fix clearCache functions and clear section cache if page load fails

* Bump Page and Section file versions

* Combine removeDir implementations in Epub

* Adjust screen margins
This commit is contained in:
Dave Allie
2025-12-12 22:13:34 +11:00
committed by GitHub
parent 09f68a3d03
commit 69f357998e
20 changed files with 430 additions and 322 deletions

View File

@@ -62,19 +62,18 @@ constexpr unsigned long POWER_BUTTON_WAKEUP_MS = 1000;
// Time required to enter sleep mode
constexpr unsigned long POWER_BUTTON_SLEEP_MS = 1000;
Epub* loadEpub(const std::string& path) {
std::unique_ptr<Epub> loadEpub(const std::string& path) {
if (!SD.exists(path.c_str())) {
Serial.printf("[%lu] [ ] File does not exist: %s\n", millis(), path.c_str());
return nullptr;
}
const auto epub = new Epub(path, "/.crosspoint");
auto epub = std::unique_ptr<Epub>(new Epub(path, "/.crosspoint"));
if (epub->load()) {
return epub;
}
Serial.printf("[%lu] [ ] Failed to load epub\n", millis());
delete epub;
return nullptr;
}
@@ -151,12 +150,12 @@ void onSelectEpubFile(const std::string& path) {
exitScreen();
enterNewScreen(new FullScreenMessageScreen(renderer, inputManager, "Loading..."));
Epub* epub = loadEpub(path);
auto epub = loadEpub(path);
if (epub) {
appState.openEpubPath = path;
appState.saveToFile();
exitScreen();
enterNewScreen(new EpubReaderScreen(renderer, inputManager, epub, onGoHome));
enterNewScreen(new EpubReaderScreen(renderer, inputManager, std::move(epub), onGoHome));
} else {
exitScreen();
enterNewScreen(
@@ -206,10 +205,10 @@ void setup() {
appState.loadFromFile();
if (!appState.openEpubPath.empty()) {
Epub* epub = loadEpub(appState.openEpubPath);
auto epub = loadEpub(appState.openEpubPath);
if (epub) {
exitScreen();
enterNewScreen(new EpubReaderScreen(renderer, inputManager, epub, onGoHome));
enterNewScreen(new EpubReaderScreen(renderer, inputManager, std::move(epub), onGoHome));
// Ensure we're not still holding the power button before leaving setup
waitForPowerRelease();
return;

View File

@@ -10,9 +10,9 @@
constexpr int PAGES_PER_REFRESH = 15;
constexpr unsigned long SKIP_CHAPTER_MS = 700;
constexpr float lineCompression = 0.95f;
constexpr int marginTop = 11;
constexpr int marginTop = 10;
constexpr int marginRight = 10;
constexpr int marginBottom = 30;
constexpr int marginBottom = 20;
constexpr int marginLeft = 10;
void EpubReaderScreen::taskTrampoline(void* param) {
@@ -60,10 +60,8 @@ void EpubReaderScreen::onExit() {
}
vSemaphoreDelete(renderingMutex);
renderingMutex = nullptr;
delete section;
section = nullptr;
delete epub;
epub = nullptr;
section.reset();
epub.reset();
}
void EpubReaderScreen::handleInput() {
@@ -88,8 +86,7 @@ void EpubReaderScreen::handleInput() {
xSemaphoreTake(renderingMutex, portMAX_DELAY);
nextPageNumber = 0;
currentSpineIndex = nextReleased ? currentSpineIndex + 1 : currentSpineIndex - 1;
delete section;
section = nullptr;
section.reset();
xSemaphoreGive(renderingMutex);
updateRequired = true;
return;
@@ -109,8 +106,7 @@ void EpubReaderScreen::handleInput() {
xSemaphoreTake(renderingMutex, portMAX_DELAY);
nextPageNumber = UINT16_MAX;
currentSpineIndex--;
delete section;
section = nullptr;
section.reset();
xSemaphoreGive(renderingMutex);
}
updateRequired = true;
@@ -122,8 +118,7 @@ void EpubReaderScreen::handleInput() {
xSemaphoreTake(renderingMutex, portMAX_DELAY);
nextPageNumber = 0;
currentSpineIndex++;
delete section;
section = nullptr;
section.reset();
xSemaphoreGive(renderingMutex);
}
updateRequired = true;
@@ -155,7 +150,7 @@ void EpubReaderScreen::renderScreen() {
if (!section) {
const auto filepath = epub->getSpineItem(currentSpineIndex);
Serial.printf("[%lu] [ERS] Loading file: %s, index: %d\n", millis(), filepath.c_str(), currentSpineIndex);
section = new Section(epub, currentSpineIndex, renderer);
section = std::unique_ptr<Section>(new Section(epub, currentSpineIndex, renderer));
if (!section->loadCacheMetadata(READER_FONT_ID, lineCompression, marginTop, marginRight, marginBottom,
marginLeft)) {
Serial.printf("[%lu] [ERS] Cache not found, building...\n", millis());
@@ -179,8 +174,7 @@ void EpubReaderScreen::renderScreen() {
if (!section->persistPageDataToSD(READER_FONT_ID, lineCompression, marginTop, marginRight, marginBottom,
marginLeft)) {
Serial.printf("[%lu] [ERS] Failed to persist page data to SD\n", millis());
delete section;
section = nullptr;
section.reset();
return;
}
} else {
@@ -212,11 +206,18 @@ void EpubReaderScreen::renderScreen() {
return;
}
const Page* p = section->loadPageFromSD();
const auto start = millis();
renderContents(p);
Serial.printf("[%lu] [ERS] Rendered page in %dms\n", millis(), millis() - start);
delete p;
{
auto p = section->loadPageFromSD();
if (!p) {
Serial.printf("[%lu] [ERS] Failed to load page from SD - clearing section cache\n", millis());
section->clearCache();
section.reset();
return renderScreen();
}
const auto start = millis();
renderContents(std::move(p));
Serial.printf("[%lu] [ERS] Rendered page in %dms\n", millis(), millis() - start);
}
File f = SD.open((epub->getCachePath() + "/progress.bin").c_str(), FILE_WRITE);
uint8_t data[4];
@@ -228,8 +229,8 @@ void EpubReaderScreen::renderScreen() {
f.close();
}
void EpubReaderScreen::renderContents(const Page* p) {
p->render(renderer, READER_FONT_ID);
void EpubReaderScreen::renderContents(std::unique_ptr<Page> page) {
page->render(renderer, READER_FONT_ID);
renderStatusBar();
if (pagesUntilFullRefresh <= 1) {
renderer.displayBuffer(EInkDisplay::HALF_REFRESH);
@@ -244,13 +245,13 @@ void EpubReaderScreen::renderContents(const Page* p) {
{
renderer.clearScreen(0x00);
renderer.setFontRenderMode(GfxRenderer::GRAYSCALE_LSB);
p->render(renderer, READER_FONT_ID);
page->render(renderer, READER_FONT_ID);
renderer.copyGrayscaleLsbBuffers();
// Render and copy to MSB buffer
renderer.clearScreen(0x00);
renderer.setFontRenderMode(GfxRenderer::GRAYSCALE_MSB);
p->render(renderer, READER_FONT_ID);
page->render(renderer, READER_FONT_ID);
renderer.copyGrayscaleMsbBuffers();
// display grayscale part

View File

@@ -8,8 +8,8 @@
#include "Screen.h"
class EpubReaderScreen final : public Screen {
Epub* epub;
Section* section = nullptr;
std::shared_ptr<Epub> epub;
std::unique_ptr<Section> section = nullptr;
TaskHandle_t displayTaskHandle = nullptr;
SemaphoreHandle_t renderingMutex = nullptr;
int currentSpineIndex = 0;
@@ -21,13 +21,13 @@ class EpubReaderScreen final : public Screen {
static void taskTrampoline(void* param);
[[noreturn]] void displayTaskLoop();
void renderScreen();
void renderContents(const Page* p);
void renderContents(std::unique_ptr<Page> p);
void renderStatusBar() const;
public:
explicit EpubReaderScreen(GfxRenderer& renderer, InputManager& inputManager, Epub* epub,
explicit EpubReaderScreen(GfxRenderer& renderer, InputManager& inputManager, std::unique_ptr<Epub> epub,
const std::function<void()>& onGoHome)
: Screen(renderer, inputManager), epub(epub), onGoHome(onGoHome) {}
: Screen(renderer, inputManager), epub(std::move(epub)), onGoHome(onGoHome) {}
void onEnter() override;
void onExit() override;
void handleInput() override;