Add UI font

This commit is contained in:
Dave Allie 2025-12-06 01:37:20 +11:00
parent 248af4b8fb
commit 7198d943b0
No known key found for this signature in database
GPG Key ID: F2FDDB3AD8D0276F
13 changed files with 4222 additions and 24 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -5,15 +5,18 @@
#include "builtinFonts/bookerly_bold.h"
#include "builtinFonts/bookerly_bold_italic.h"
#include "builtinFonts/bookerly_italic.h"
#include "builtinFonts/ubuntu_10.h"
#include "builtinFonts/ubuntu_bold_10.h"
EpdRenderer::EpdRenderer(XteinkDisplay* display) {
const auto bookerlyFontFamily = new EpdFontFamily(new EpdFont(&bookerly), new EpdFont(&bookerly_bold),
new EpdFont(&bookerly_italic), new EpdFont(&bookerly_bold_italic));
const auto babyblueFontFamily = new EpdFontFamily(new EpdFont(&babyblue));
const auto ubuntuFontFamily = new EpdFontFamily(new EpdFont(&ubuntu_10), new EpdFont(&ubuntu_bold_10));
this->display = display;
this->regularFontRenderer = new EpdFontRenderer<XteinkDisplay>(bookerlyFontFamily, display);
this->smallFontRenderer = new EpdFontRenderer<XteinkDisplay>(babyblueFontFamily, display);
this->smallFontRenderer = new EpdFontRenderer<XteinkDisplay>(new EpdFontFamily(new EpdFont(&babyblue)), display);
this->uiFontRenderer = new EpdFontRenderer<XteinkDisplay>(ubuntuFontFamily, display);
this->marginTop = 11;
this->marginBottom = 30;
@ -30,6 +33,14 @@ int EpdRenderer::getTextWidth(const char* text, const EpdFontStyle style) const
return w;
}
int EpdRenderer::getUiTextWidth(const char* text, const EpdFontStyle style) const {
int w = 0, h = 0;
uiFontRenderer->fontFamily->getTextDimensions(text, &w, &h, style);
return w;
}
int EpdRenderer::getSmallTextWidth(const char* text, const EpdFontStyle style) const {
int w = 0, h = 0;
@ -45,11 +56,18 @@ void EpdRenderer::drawText(const int x, const int y, const char* text, const uin
regularFontRenderer->renderString(text, &xpos, &ypos, color > 0 ? GxEPD_BLACK : GxEPD_WHITE, style);
}
void EpdRenderer::drawUiText(const int x, const int y, const char* text, const uint16_t color,
const EpdFontStyle style) const {
int ypos = y + uiFontRenderer->fontFamily->getData(style)->advanceY + marginTop;
int xpos = x + marginLeft;
uiFontRenderer->renderString(text, &xpos, &ypos, color > 0 ? GxEPD_BLACK : GxEPD_WHITE, style);
}
void EpdRenderer::drawSmallText(const int x, const int y, const char* text, const uint16_t color,
const EpdFontStyle style) const {
int ypos = y + smallFontRenderer->fontFamily->getData(style)->advanceY + marginTop;
int xpos = x + marginLeft;
smallFontRenderer->renderString(text, &xpos, &ypos, color > 0 ? GxEPD_BLACK : GxEPD_WHITE);
smallFontRenderer->renderString(text, &xpos, &ypos, color > 0 ? GxEPD_BLACK : GxEPD_WHITE, style);
}
void EpdRenderer::drawTextBox(const int x, const int y, const std::string& text, const int width, const int height,

View File

@ -10,6 +10,7 @@ class EpdRenderer {
XteinkDisplay* display;
EpdFontRenderer<XteinkDisplay>* regularFontRenderer;
EpdFontRenderer<XteinkDisplay>* smallFontRenderer;
EpdFontRenderer<XteinkDisplay>* uiFontRenderer;
int marginTop;
int marginBottom;
int marginLeft;
@ -20,8 +21,10 @@ class EpdRenderer {
explicit EpdRenderer(XteinkDisplay* display);
~EpdRenderer() = default;
int getTextWidth(const char* text, EpdFontStyle style = REGULAR) const;
int getUiTextWidth(const char* text, EpdFontStyle style = REGULAR) const;
int getSmallTextWidth(const char* text, EpdFontStyle style = REGULAR) const;
void drawText(int x, int y, const char* text, uint16_t color = 1, EpdFontStyle style = REGULAR) const;
void drawUiText(int x, int y, const char* text, uint16_t color = 1, EpdFontStyle style = REGULAR) const;
void drawSmallText(int x, int y, const char* text, uint16_t color = 1, EpdFontStyle style = REGULAR) const;
void drawTextBox(int x, int y, const std::string& text, int width, int height, EpdFontStyle style = REGULAR) const;
void drawLine(int x1, int y1, int x2, int y2, uint16_t color = 1) const;

File diff suppressed because one or more lines are too long

View File

@ -55,11 +55,14 @@ Epub* loadEpub(const std::string& path) {
return nullptr;
}
void enterNewScreen(Screen* screen) {
void exitScreen() {
if (currentScreen) {
currentScreen->onExit();
delete currentScreen;
}
}
void enterNewScreen(Screen* screen) {
currentScreen = screen;
currentScreen->onEnter();
}
@ -90,7 +93,8 @@ void waitForNoButton() {
// Enter deep sleep mode
void enterDeepSleep() {
enterNewScreen(new FullScreenMessageScreen(renderer, "Sleeping", BOLD, true));
exitScreen();
enterNewScreen(new FullScreenMessageScreen(renderer, "Sleeping", BOLD, true, false));
Serial.println("Power button released after a long press. Entering deep sleep.");
delay(1000); // Allow Serial buffer to empty and display to update
@ -106,18 +110,25 @@ void enterDeepSleep() {
void onGoHome();
void onSelectEpubFile(const std::string& path) {
exitScreen();
enterNewScreen(new FullScreenMessageScreen(renderer, "Loading..."));
Epub* epub = loadEpub(path);
if (epub) {
appState->openEpubPath = path;
appState->saveToFile();
exitScreen();
enterNewScreen(new EpubReaderScreen(renderer, epub, onGoHome));
} else {
enterNewScreen(new FullScreenMessageScreen(renderer, "Failed to load epub"));
exitScreen();
enterNewScreen(new FullScreenMessageScreen(renderer, "Failed to load epub", REGULAR, false, false));
}
}
void onGoHome() { enterNewScreen(new FileSelectionScreen(renderer, onSelectEpubFile)); }
void onGoHome() {
exitScreen();
enterNewScreen(new FileSelectionScreen(renderer, onSelectEpubFile));
}
void setup() {
setupInputPinModes();
@ -138,6 +149,7 @@ void setup() {
display.setTextColor(GxEPD_BLACK);
Serial.println("Display initialized");
exitScreen();
enterNewScreen(new BootLogoScreen(renderer));
// SD Card Initialization
@ -147,6 +159,7 @@ void setup() {
if (!appState->openEpubPath.empty()) {
Epub* epub = loadEpub(appState->openEpubPath);
if (epub) {
exitScreen();
enterNewScreen(new EpubReaderScreen(renderer, epub, onGoHome));
// Ensure we're not still holding the power button before leaving setup
waitForNoButton();
@ -154,6 +167,7 @@ void setup() {
}
}
exitScreen();
enterNewScreen(new FileSelectionScreen(renderer, onSelectEpubFile));
// Ensure we're not still holding the power button before leaving setup

View File

@ -10,5 +10,5 @@ void BootLogoScreen::onEnter() {
renderer->clearScreen();
// Location for images is from top right in landscape orientation
renderer->drawImage(CrossLarge, (pageHeight - 128) /2, (pageWidth - 128) / 2, 128, 128);
renderer->drawImage(CrossLarge, (pageHeight - 128) / 2, (pageWidth - 128) / 2, 128, 128);
}

View File

@ -1,9 +1,8 @@
#pragma once
#include "Screen.h"
class BootLogoScreen final : public Screen {
public:
explicit BootLogoScreen(EpdRenderer* renderer): Screen(renderer) {}
public:
explicit BootLogoScreen(EpdRenderer* renderer) : Screen(renderer) {}
void onEnter() override;
};

View File

@ -41,10 +41,10 @@ void EpubReaderScreen::onEnter() {
}
void EpubReaderScreen::onExit() {
vTaskDelete(displayTaskHandle);
displayTaskHandle = nullptr;
xSemaphoreTake(sectionMutex, portMAX_DELAY);
vTaskDelete(displayTaskHandle);
vSemaphoreDelete(sectionMutex);
displayTaskHandle = nullptr;
sectionMutex = nullptr;
}

View File

@ -26,7 +26,10 @@ class EpubReaderScreen final : public Screen {
public:
explicit EpubReaderScreen(EpdRenderer* renderer, Epub* epub, const std::function<void()>& onGoHome)
: Screen(renderer), epub(epub), onGoHome(onGoHome) {}
~EpubReaderScreen() override { free(section); }
~EpubReaderScreen() override {
free(section);
free(epub);
}
void onEnter() override;
void onExit() override;
void handleInput(Input input) override;

View File

@ -95,14 +95,14 @@ void FileSelectionScreen::render() const {
renderer->drawText((pageWidth - titleWidth) / 2, 0, "CrossPoint Reader", 1, BOLD);
if (files.empty()) {
renderer->drawSmallText(50, 50, "No EPUBs found");
renderer->drawUiText(10, 50, "No EPUBs found");
} else {
// Draw selection
renderer->fillRect(0, 50 + selectorIndex * 20 + 2, pageWidth - 1, 20);
renderer->fillRect(0, 50 + selectorIndex * 30 + 2, pageWidth - 1, 30);
for (size_t i = 0; i < files.size(); i++) {
const auto file = files[i];
renderer->drawSmallText(50, 50 + i * 20, file.c_str(), i == selectorIndex ? 0 : 1);
renderer->drawUiText(10, 50 + i * 30, file.c_str(), i == selectorIndex ? 0 : 1);
}
}

View File

@ -3,13 +3,12 @@
#include <EpdRenderer.h>
void FullScreenMessageScreen::onEnter() {
const auto width = renderer->getTextWidth(text.c_str(), style);
const auto width = renderer->getUiTextWidth(text.c_str(), style);
const auto height = renderer->getLineHeight();
const auto left = (renderer->getPageWidth() - width) / 2;
const auto top = (renderer->getPageHeight() - height) / 2;
renderer->clearScreen(invert);
renderer->drawText(left, top, text.c_str(), invert ? 0 : 1, style);
// If inverted, do a full screen update to ensure no ghosting
renderer->flushDisplay(!invert);
renderer->drawUiText(left, top, text.c_str(), invert ? 0 : 1, style);
renderer->flushDisplay(partialUpdate);
}

View File

@ -9,10 +9,11 @@ class FullScreenMessageScreen final : public Screen {
std::string text;
EpdFontStyle style;
bool invert;
bool partialUpdate;
public:
explicit FullScreenMessageScreen(EpdRenderer* renderer, std::string text, const EpdFontStyle style = REGULAR,
const bool invert = false)
: Screen(renderer), text(std::move(text)), style(style), invert(invert) {}
const bool invert = false, const bool partialUpdate = true)
: Screen(renderer), text(std::move(text)), style(style), invert(invert), partialUpdate(partialUpdate) {}
void onEnter() override;
};