Use sane smaller data types for data in section.bin (#188)
Some checks are pending
CI / build (push) Waiting to run

## Summary

* Update EpdFontFamily::Style to be u8 instead of u32 (saving 3 bytes
per word)
* Update layout width/height to be u16 from int
* Update page element count to be u16 from u32
* Update text block element count to be u16 from u32
* Bumped section bin version to version 8
This commit is contained in:
Dave Allie 2025-12-31 12:11:36 +10:00 committed by GitHub
parent 40f9ed485c
commit 6e9ba1006a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
28 changed files with 133 additions and 129 deletions

View File

@ -1,6 +1,6 @@
#include "EpdFontFamily.h"
const EpdFont* EpdFontFamily::getFont(const EpdFontStyle style) const {
const EpdFont* EpdFontFamily::getFont(const Style style) const {
if (style == BOLD && bold) {
return bold;
}
@ -22,16 +22,16 @@ const EpdFont* EpdFontFamily::getFont(const EpdFontStyle style) const {
return regular;
}
void EpdFontFamily::getTextDimensions(const char* string, int* w, int* h, const EpdFontStyle style) const {
void EpdFontFamily::getTextDimensions(const char* string, int* w, int* h, const Style style) const {
getFont(style)->getTextDimensions(string, w, h);
}
bool EpdFontFamily::hasPrintableChars(const char* string, const EpdFontStyle style) const {
bool EpdFontFamily::hasPrintableChars(const char* string, const Style style) const {
return getFont(style)->hasPrintableChars(string);
}
const EpdFontData* EpdFontFamily::getData(const EpdFontStyle style) const { return getFont(style)->data; }
const EpdFontData* EpdFontFamily::getData(const Style style) const { return getFont(style)->data; }
const EpdGlyph* EpdFontFamily::getGlyph(const uint32_t cp, const EpdFontStyle style) const {
const EpdGlyph* EpdFontFamily::getGlyph(const uint32_t cp, const Style style) const {
return getFont(style)->getGlyph(cp);
};

View File

@ -1,24 +1,24 @@
#pragma once
#include "EpdFont.h"
enum EpdFontStyle { REGULAR, BOLD, ITALIC, BOLD_ITALIC };
class EpdFontFamily {
public:
enum Style : uint8_t { REGULAR = 0, BOLD = 1, ITALIC = 2, BOLD_ITALIC = 3 };
explicit EpdFontFamily(const EpdFont* regular, const EpdFont* bold = nullptr, const EpdFont* italic = nullptr,
const EpdFont* boldItalic = nullptr)
: regular(regular), bold(bold), italic(italic), boldItalic(boldItalic) {}
~EpdFontFamily() = default;
void getTextDimensions(const char* string, int* w, int* h, Style style = REGULAR) const;
bool hasPrintableChars(const char* string, Style style = REGULAR) const;
const EpdFontData* getData(Style style = REGULAR) const;
const EpdGlyph* getGlyph(uint32_t cp, Style style = REGULAR) const;
private:
const EpdFont* regular;
const EpdFont* bold;
const EpdFont* italic;
const EpdFont* boldItalic;
const EpdFont* getFont(EpdFontStyle style) const;
public:
explicit EpdFontFamily(const EpdFont* regular, const EpdFont* bold = nullptr, const EpdFont* italic = nullptr,
const EpdFont* boldItalic = nullptr)
: regular(regular), bold(bold), italic(italic), boldItalic(boldItalic) {}
~EpdFontFamily() = default;
void getTextDimensions(const char* string, int* w, int* h, EpdFontStyle style = REGULAR) const;
bool hasPrintableChars(const char* string, EpdFontStyle style = REGULAR) const;
const EpdFontData* getData(EpdFontStyle style = REGULAR) const;
const EpdGlyph* getGlyph(uint32_t cp, EpdFontStyle style = REGULAR) const;
const EpdFont* getFont(Style style) const;
};

View File

@ -32,7 +32,7 @@ void Page::render(GfxRenderer& renderer, const int fontId, const int xOffset, co
}
bool Page::serialize(FsFile& file) const {
const uint32_t count = elements.size();
const uint16_t count = elements.size();
serialization::writePod(file, count);
for (const auto& el : elements) {
@ -49,10 +49,10 @@ bool Page::serialize(FsFile& file) const {
std::unique_ptr<Page> Page::deserialize(FsFile& file) {
auto page = std::unique_ptr<Page>(new Page());
uint32_t count;
uint16_t count;
serialization::readPod(file, count);
for (uint32_t i = 0; i < count; i++) {
for (uint16_t i = 0; i < count; i++) {
uint8_t tag;
serialization::readPod(file, tag);

View File

@ -10,7 +10,7 @@
constexpr int MAX_COST = std::numeric_limits<int>::max();
void ParsedText::addWord(std::string word, const EpdFontStyle fontStyle) {
void ParsedText::addWord(std::string word, const EpdFontFamily::Style fontStyle) {
if (word.empty()) return;
words.push_back(std::move(word));
@ -18,7 +18,7 @@ void ParsedText::addWord(std::string word, const EpdFontStyle fontStyle) {
}
// Consumes data to minimize memory usage
void ParsedText::layoutAndExtractLines(const GfxRenderer& renderer, const int fontId, const int viewportWidth,
void ParsedText::layoutAndExtractLines(const GfxRenderer& renderer, const int fontId, const uint16_t viewportWidth,
const std::function<void(std::shared_ptr<TextBlock>)>& processLine,
const bool includeLastLine) {
if (words.empty()) {
@ -188,7 +188,7 @@ void ParsedText::extractLine(const size_t breakIndex, const int pageWidth, const
// *** CRITICAL STEP: CONSUME DATA USING SPLICE ***
std::list<std::string> lineWords;
lineWords.splice(lineWords.begin(), words, words.begin(), wordEndIt);
std::list<EpdFontStyle> lineWordStyles;
std::list<EpdFontFamily::Style> lineWordStyles;
lineWordStyles.splice(lineWordStyles.begin(), wordStyles, wordStyles.begin(), wordStyleEndIt);
processLine(std::make_shared<TextBlock>(std::move(lineWords), std::move(lineXPos), std::move(lineWordStyles), style));

View File

@ -14,8 +14,8 @@ class GfxRenderer;
class ParsedText {
std::list<std::string> words;
std::list<EpdFontStyle> wordStyles;
TextBlock::BLOCK_STYLE style;
std::list<EpdFontFamily::Style> wordStyles;
TextBlock::Style style;
bool extraParagraphSpacing;
std::vector<size_t> computeLineBreaks(int pageWidth, int spaceWidth, const std::vector<uint16_t>& wordWidths) const;
@ -25,16 +25,16 @@ class ParsedText {
std::vector<uint16_t> calculateWordWidths(const GfxRenderer& renderer, int fontId);
public:
explicit ParsedText(const TextBlock::BLOCK_STYLE style, const bool extraParagraphSpacing)
explicit ParsedText(const TextBlock::Style style, const bool extraParagraphSpacing)
: style(style), extraParagraphSpacing(extraParagraphSpacing) {}
~ParsedText() = default;
void addWord(std::string word, EpdFontStyle fontStyle);
void setStyle(const TextBlock::BLOCK_STYLE style) { this->style = style; }
TextBlock::BLOCK_STYLE getStyle() const { return style; }
void addWord(std::string word, EpdFontFamily::Style fontStyle);
void setStyle(const TextBlock::Style style) { this->style = style; }
TextBlock::Style getStyle() const { return style; }
size_t size() const { return words.size(); }
bool isEmpty() const { return words.empty(); }
void layoutAndExtractLines(const GfxRenderer& renderer, int fontId, int viewportWidth,
void layoutAndExtractLines(const GfxRenderer& renderer, int fontId, uint16_t viewportWidth,
const std::function<void(std::shared_ptr<TextBlock>)>& processLine,
bool includeLastLine = true);
};

View File

@ -7,9 +7,9 @@
#include "parsers/ChapterHtmlSlimParser.h"
namespace {
constexpr uint8_t SECTION_FILE_VERSION = 7;
constexpr uint32_t HEADER_SIZE = sizeof(uint8_t) + sizeof(int) + sizeof(float) + sizeof(bool) + sizeof(int) +
sizeof(int) + sizeof(int) + sizeof(uint32_t);
constexpr uint8_t SECTION_FILE_VERSION = 8;
constexpr uint32_t HEADER_SIZE = sizeof(uint8_t) + sizeof(int) + sizeof(float) + sizeof(bool) + sizeof(uint16_t) +
sizeof(uint16_t) + sizeof(uint16_t) + sizeof(uint32_t);
} // namespace
uint32_t Section::onPageComplete(std::unique_ptr<Page> page) {
@ -30,7 +30,7 @@ uint32_t Section::onPageComplete(std::unique_ptr<Page> page) {
}
void Section::writeSectionFileHeader(const int fontId, const float lineCompression, const bool extraParagraphSpacing,
const int viewportWidth, const int viewportHeight) {
const uint16_t viewportWidth, const uint16_t viewportHeight) {
if (!file) {
Serial.printf("[%lu] [SCT] File not open for writing header\n", millis());
return;
@ -50,7 +50,7 @@ void Section::writeSectionFileHeader(const int fontId, const float lineCompressi
}
bool Section::loadSectionFile(const int fontId, const float lineCompression, const bool extraParagraphSpacing,
const int viewportWidth, const int viewportHeight) {
const uint16_t viewportWidth, const uint16_t viewportHeight) {
if (!SdMan.openFileForRead("SCT", filePath, file)) {
return false;
}
@ -66,7 +66,8 @@ bool Section::loadSectionFile(const int fontId, const float lineCompression, con
return false;
}
int fileFontId, fileViewportWidth, fileViewportHeight;
int fileFontId;
uint16_t fileViewportWidth, fileViewportHeight;
float fileLineCompression;
bool fileExtraParagraphSpacing;
serialization::readPod(file, fileFontId);
@ -108,7 +109,7 @@ bool Section::clearCache() const {
}
bool Section::createSectionFile(const int fontId, const float lineCompression, const bool extraParagraphSpacing,
const int viewportWidth, const int viewportHeight,
const uint16_t viewportWidth, const uint16_t viewportHeight,
const std::function<void()>& progressSetupFn,
const std::function<void(int)>& progressFn) {
constexpr uint32_t MIN_SIZE_FOR_PROGRESS = 50 * 1024; // 50KB

View File

@ -14,12 +14,12 @@ class Section {
std::string filePath;
FsFile file;
void writeSectionFileHeader(int fontId, float lineCompression, bool extraParagraphSpacing, int viewportWidth,
int viewportHeight);
void writeSectionFileHeader(int fontId, float lineCompression, bool extraParagraphSpacing, uint16_t viewportWidth,
uint16_t viewportHeight);
uint32_t onPageComplete(std::unique_ptr<Page> page);
public:
int pageCount = 0;
uint16_t pageCount = 0;
int currentPage = 0;
explicit Section(const std::shared_ptr<Epub>& epub, const int spineIndex, GfxRenderer& renderer)
@ -28,11 +28,11 @@ class Section {
renderer(renderer),
filePath(epub->getCachePath() + "/sections/" + std::to_string(spineIndex) + ".bin") {}
~Section() = default;
bool loadSectionFile(int fontId, float lineCompression, bool extraParagraphSpacing, int viewportWidth,
int viewportHeight);
bool loadSectionFile(int fontId, float lineCompression, bool extraParagraphSpacing, uint16_t viewportWidth,
uint16_t viewportHeight);
bool clearCache() const;
bool createSectionFile(int fontId, float lineCompression, bool extraParagraphSpacing, int viewportWidth,
int viewportHeight, const std::function<void()>& progressSetupFn = nullptr,
bool createSectionFile(int fontId, float lineCompression, bool extraParagraphSpacing, uint16_t viewportWidth,
uint16_t viewportHeight, const std::function<void()>& progressSetupFn = nullptr,
const std::function<void(int)>& progressFn = nullptr);
std::unique_ptr<Page> loadPageFromSectionFile();
};

View File

@ -32,7 +32,7 @@ bool TextBlock::serialize(FsFile& file) const {
}
// Word data
serialization::writePod(file, static_cast<uint32_t>(words.size()));
serialization::writePod(file, static_cast<uint16_t>(words.size()));
for (const auto& w : words) serialization::writeString(file, w);
for (auto x : wordXpos) serialization::writePod(file, x);
for (auto s : wordStyles) serialization::writePod(file, s);
@ -44,11 +44,11 @@ bool TextBlock::serialize(FsFile& file) const {
}
std::unique_ptr<TextBlock> TextBlock::deserialize(FsFile& file) {
uint32_t wc;
uint16_t wc;
std::list<std::string> words;
std::list<uint16_t> wordXpos;
std::list<EpdFontStyle> wordStyles;
BLOCK_STYLE style;
std::list<EpdFontFamily::Style> wordStyles;
Style style;
// Word count
serialization::readPod(file, wc);

View File

@ -8,10 +8,10 @@
#include "Block.h"
// represents a block of words in the html document
// Represents a line of text on a page
class TextBlock final : public Block {
public:
enum BLOCK_STYLE : uint8_t {
enum Style : uint8_t {
JUSTIFIED = 0,
LEFT_ALIGN = 1,
CENTER_ALIGN = 2,
@ -21,16 +21,16 @@ class TextBlock final : public Block {
private:
std::list<std::string> words;
std::list<uint16_t> wordXpos;
std::list<EpdFontStyle> wordStyles;
BLOCK_STYLE style;
std::list<EpdFontFamily::Style> wordStyles;
Style style;
public:
explicit TextBlock(std::list<std::string> words, std::list<uint16_t> word_xpos, std::list<EpdFontStyle> word_styles,
const BLOCK_STYLE style)
explicit TextBlock(std::list<std::string> words, std::list<uint16_t> word_xpos,
std::list<EpdFontFamily::Style> word_styles, const Style style)
: words(std::move(words)), wordXpos(std::move(word_xpos)), wordStyles(std::move(word_styles)), style(style) {}
~TextBlock() override = default;
void setStyle(const BLOCK_STYLE style) { this->style = style; }
BLOCK_STYLE getStyle() const { return style; }
void setStyle(const Style style) { this->style = style; }
Style getStyle() const { return style; }
bool isEmpty() override { return words.empty(); }
void layout(GfxRenderer& renderer) override {};
// given a renderer works out where to break the words into lines

View File

@ -42,7 +42,7 @@ bool matches(const char* tag_name, const char* possible_tags[], const int possib
}
// start a new text block if needed
void ChapterHtmlSlimParser::startNewTextBlock(const TextBlock::BLOCK_STYLE style) {
void ChapterHtmlSlimParser::startNewTextBlock(const TextBlock::Style style) {
if (currentTextBlock) {
// already have a text block running and it is empty - just reuse it
if (currentTextBlock->isEmpty()) {
@ -116,13 +116,13 @@ void XMLCALL ChapterHtmlSlimParser::characterData(void* userData, const XML_Char
return;
}
EpdFontStyle fontStyle = REGULAR;
EpdFontFamily::Style fontStyle = EpdFontFamily::REGULAR;
if (self->boldUntilDepth < self->depth && self->italicUntilDepth < self->depth) {
fontStyle = BOLD_ITALIC;
fontStyle = EpdFontFamily::BOLD_ITALIC;
} else if (self->boldUntilDepth < self->depth) {
fontStyle = BOLD;
fontStyle = EpdFontFamily::BOLD;
} else if (self->italicUntilDepth < self->depth) {
fontStyle = ITALIC;
fontStyle = EpdFontFamily::ITALIC;
}
for (int i = 0; i < len; i++) {
@ -172,13 +172,13 @@ void XMLCALL ChapterHtmlSlimParser::endElement(void* userData, const XML_Char* n
matches(name, BOLD_TAGS, NUM_BOLD_TAGS) || matches(name, ITALIC_TAGS, NUM_ITALIC_TAGS) || self->depth == 1;
if (shouldBreakText) {
EpdFontStyle fontStyle = REGULAR;
EpdFontFamily::Style fontStyle = EpdFontFamily::REGULAR;
if (self->boldUntilDepth < self->depth && self->italicUntilDepth < self->depth) {
fontStyle = BOLD_ITALIC;
fontStyle = EpdFontFamily::BOLD_ITALIC;
} else if (self->boldUntilDepth < self->depth) {
fontStyle = BOLD;
fontStyle = EpdFontFamily::BOLD;
} else if (self->italicUntilDepth < self->depth) {
fontStyle = ITALIC;
fontStyle = EpdFontFamily::ITALIC;
}
self->partWordBuffer[self->partWordBufferIndex] = '\0';

View File

@ -33,10 +33,10 @@ class ChapterHtmlSlimParser {
int fontId;
float lineCompression;
bool extraParagraphSpacing;
int viewportWidth;
int viewportHeight;
uint16_t viewportWidth;
uint16_t viewportHeight;
void startNewTextBlock(TextBlock::BLOCK_STYLE style);
void startNewTextBlock(TextBlock::Style style);
void makePages();
// XML callbacks
static void XMLCALL startElement(void* userData, const XML_Char* name, const XML_Char** atts);
@ -45,8 +45,8 @@ class ChapterHtmlSlimParser {
public:
explicit ChapterHtmlSlimParser(const std::string& filepath, GfxRenderer& renderer, const int fontId,
const float lineCompression, const bool extraParagraphSpacing, const int viewportWidth,
const int viewportHeight,
const float lineCompression, const bool extraParagraphSpacing,
const uint16_t viewportWidth, const uint16_t viewportHeight,
const std::function<void(std::unique_ptr<Page>)>& completePageFn,
const std::function<void(int)>& progressFn = nullptr)
: filepath(filepath),

View File

@ -66,7 +66,7 @@ void GfxRenderer::drawPixel(const int x, const int y, const bool state) const {
}
}
int GfxRenderer::getTextWidth(const int fontId, const char* text, const EpdFontStyle style) const {
int GfxRenderer::getTextWidth(const int fontId, const char* text, const EpdFontFamily::Style style) const {
if (fontMap.count(fontId) == 0) {
Serial.printf("[%lu] [GFX] Font %d not found\n", millis(), fontId);
return 0;
@ -78,13 +78,13 @@ int GfxRenderer::getTextWidth(const int fontId, const char* text, const EpdFontS
}
void GfxRenderer::drawCenteredText(const int fontId, const int y, const char* text, const bool black,
const EpdFontStyle style) const {
const EpdFontFamily::Style style) const {
const int x = (getScreenWidth() - getTextWidth(fontId, text, style)) / 2;
drawText(fontId, x, y, text, black, style);
}
void GfxRenderer::drawText(const int fontId, const int x, const int y, const char* text, const bool black,
const EpdFontStyle style) const {
const EpdFontFamily::Style style) const {
const int yPos = y + getFontAscenderSize(fontId);
int xpos = x;
@ -239,7 +239,7 @@ void GfxRenderer::displayBuffer(const EInkDisplay::RefreshMode refreshMode) cons
}
std::string GfxRenderer::truncatedText(const int fontId, const char* text, const int maxWidth,
const EpdFontStyle style) const {
const EpdFontFamily::Style style) const {
std::string item = text;
int itemWidth = getTextWidth(fontId, item.c_str(), style);
while (itemWidth > maxWidth && item.length() > 8) {
@ -284,7 +284,7 @@ int GfxRenderer::getSpaceWidth(const int fontId) const {
return 0;
}
return fontMap.at(fontId).getGlyph(' ', REGULAR)->advanceX;
return fontMap.at(fontId).getGlyph(' ', EpdFontFamily::REGULAR)->advanceX;
}
int GfxRenderer::getFontAscenderSize(const int fontId) const {
@ -293,7 +293,7 @@ int GfxRenderer::getFontAscenderSize(const int fontId) const {
return 0;
}
return fontMap.at(fontId).getData(REGULAR)->ascender;
return fontMap.at(fontId).getData(EpdFontFamily::REGULAR)->ascender;
}
int GfxRenderer::getLineHeight(const int fontId) const {
@ -302,7 +302,7 @@ int GfxRenderer::getLineHeight(const int fontId) const {
return 0;
}
return fontMap.at(fontId).getData(REGULAR)->advanceY;
return fontMap.at(fontId).getData(EpdFontFamily::REGULAR)->advanceY;
}
void GfxRenderer::drawButtonHints(const int fontId, const char* btn1, const char* btn2, const char* btn3,
@ -447,7 +447,7 @@ void GfxRenderer::cleanupGrayscaleWithFrameBuffer() const {
}
void GfxRenderer::renderChar(const EpdFontFamily& fontFamily, const uint32_t cp, int* x, const int* y,
const bool pixelState, const EpdFontStyle style) const {
const bool pixelState, const EpdFontFamily::Style style) const {
const EpdGlyph* glyph = fontFamily.getGlyph(cp, style);
if (!glyph) {
// TODO: Replace with fallback glyph property?

View File

@ -31,7 +31,7 @@ class GfxRenderer {
uint8_t* bwBufferChunks[BW_BUFFER_NUM_CHUNKS] = {nullptr};
std::map<int, EpdFontFamily> fontMap;
void renderChar(const EpdFontFamily& fontFamily, uint32_t cp, int* x, const int* y, bool pixelState,
EpdFontStyle style) const;
EpdFontFamily::Style style) const;
void freeBwBufferChunks();
void rotateCoordinates(int x, int y, int* rotatedX, int* rotatedY) const;
@ -69,14 +69,16 @@ class GfxRenderer {
void drawBitmap(const Bitmap& bitmap, int x, int y, int maxWidth, int maxHeight) const;
// Text
int getTextWidth(int fontId, const char* text, EpdFontStyle style = REGULAR) const;
void drawCenteredText(int fontId, int y, const char* text, bool black = true, EpdFontStyle style = REGULAR) const;
void drawText(int fontId, int x, int y, const char* text, bool black = true, EpdFontStyle style = REGULAR) const;
int getTextWidth(int fontId, const char* text, EpdFontFamily::Style style = EpdFontFamily::REGULAR) const;
void drawCenteredText(int fontId, int y, const char* text, bool black = true,
EpdFontFamily::Style style = EpdFontFamily::REGULAR) const;
void drawText(int fontId, int x, int y, const char* text, bool black = true,
EpdFontFamily::Style style = EpdFontFamily::REGULAR) const;
int getSpaceWidth(int fontId) const;
int getFontAscenderSize(int fontId) const;
int getLineHeight(int fontId) const;
std::string truncatedText(const int fontId, const char* text, const int maxWidth,
const EpdFontStyle style = REGULAR) const;
std::string truncatedText(int fontId, const char* text, int maxWidth,
EpdFontFamily::Style style = EpdFontFamily::REGULAR) const;
// UI Components
void drawButtonHints(int fontId, const char* btn1, const char* btn2, const char* btn3, const char* btn4) const;

View File

@ -13,7 +13,7 @@ void BootActivity::onEnter() {
renderer.clearScreen();
renderer.drawImage(CrossLarge, (pageWidth + 128) / 2, (pageHeight - 128) / 2, 128, 128);
renderer.drawCenteredText(UI_10_FONT_ID, pageHeight / 2 + 70, "CrossPoint", true, BOLD);
renderer.drawCenteredText(UI_10_FONT_ID, pageHeight / 2 + 70, "CrossPoint", true, EpdFontFamily::BOLD);
renderer.drawCenteredText(SMALL_FONT_ID, pageHeight / 2 + 95, "BOOTING");
renderer.drawCenteredText(SMALL_FONT_ID, pageHeight - 30, CROSSPOINT_VERSION);
renderer.displayBuffer();

View File

@ -129,7 +129,7 @@ void SleepActivity::renderDefaultSleepScreen() const {
renderer.clearScreen();
renderer.drawImage(CrossLarge, (pageWidth + 128) / 2, (pageHeight - 128) / 2, 128, 128);
renderer.drawCenteredText(UI_10_FONT_ID, pageHeight / 2 + 70, "CrossPoint", true, BOLD);
renderer.drawCenteredText(UI_10_FONT_ID, pageHeight / 2 + 70, "CrossPoint", true, EpdFontFamily::BOLD);
renderer.drawCenteredText(SMALL_FONT_ID, pageHeight / 2 + 95, "SLEEPING");
// Make sleep screen dark unless light is selected in settings

View File

@ -334,7 +334,7 @@ void CrossPointWebServerActivity::render() const {
} else if (state == WebServerActivityState::AP_STARTING) {
renderer.clearScreen();
const auto pageHeight = renderer.getScreenHeight();
renderer.drawCenteredText(UI_12_FONT_ID, pageHeight / 2 - 20, "Starting Hotspot...", true, BOLD);
renderer.drawCenteredText(UI_12_FONT_ID, pageHeight / 2 - 20, "Starting Hotspot...", true, EpdFontFamily::BOLD);
renderer.displayBuffer();
}
}
@ -365,13 +365,13 @@ void CrossPointWebServerActivity::renderServerRunning() const {
// Use consistent line spacing
constexpr int LINE_SPACING = 28; // Space between lines
renderer.drawCenteredText(UI_12_FONT_ID, 15, "File Transfer", true, BOLD);
renderer.drawCenteredText(UI_12_FONT_ID, 15, "File Transfer", true, EpdFontFamily::BOLD);
if (isApMode) {
// AP mode display - center the content block
int startY = 55;
renderer.drawCenteredText(UI_10_FONT_ID, startY, "Hotspot Mode", true, BOLD);
renderer.drawCenteredText(UI_10_FONT_ID, startY, "Hotspot Mode", true, EpdFontFamily::BOLD);
std::string ssidInfo = "Network: " + connectedSSID;
renderer.drawCenteredText(UI_10_FONT_ID, startY + LINE_SPACING, ssidInfo.c_str());
@ -387,7 +387,7 @@ void CrossPointWebServerActivity::renderServerRunning() const {
startY += 6 * 29 + 3 * LINE_SPACING;
// Show primary URL (hostname)
std::string hostnameUrl = std::string("http://") + AP_HOSTNAME + ".local/";
renderer.drawCenteredText(UI_10_FONT_ID, startY + LINE_SPACING * 3, hostnameUrl.c_str(), true, BOLD);
renderer.drawCenteredText(UI_10_FONT_ID, startY + LINE_SPACING * 3, hostnameUrl.c_str(), true, EpdFontFamily::BOLD);
// Show IP address as fallback
std::string ipUrl = "or http://" + connectedIP + "/";
@ -412,7 +412,7 @@ void CrossPointWebServerActivity::renderServerRunning() const {
// Show web server URL prominently
std::string webInfo = "http://" + connectedIP + "/";
renderer.drawCenteredText(UI_10_FONT_ID, startY + LINE_SPACING * 2, webInfo.c_str(), true, BOLD);
renderer.drawCenteredText(UI_10_FONT_ID, startY + LINE_SPACING * 2, webInfo.c_str(), true, EpdFontFamily::BOLD);
// Also show hostname URL
std::string hostnameUrl = std::string("or http://") + AP_HOSTNAME + ".local/";

View File

@ -97,7 +97,7 @@ void NetworkModeSelectionActivity::render() const {
const auto pageHeight = renderer.getScreenHeight();
// Draw header
renderer.drawCenteredText(UI_12_FONT_ID, 15, "File Transfer", true, BOLD);
renderer.drawCenteredText(UI_12_FONT_ID, 15, "File Transfer", true, EpdFontFamily::BOLD);
// Draw subtitle
renderer.drawCenteredText(UI_10_FONT_ID, 50, "How would you like to connect?");

View File

@ -496,7 +496,7 @@ void WifiSelectionActivity::renderNetworkList() const {
const auto pageHeight = renderer.getScreenHeight();
// Draw header
renderer.drawCenteredText(UI_12_FONT_ID, 15, "WiFi Networks", true, BOLD);
renderer.drawCenteredText(UI_12_FONT_ID, 15, "WiFi Networks", true, EpdFontFamily::BOLD);
if (networks.empty()) {
// No networks found or scan failed
@ -577,7 +577,7 @@ void WifiSelectionActivity::renderConnecting() const {
if (state == WifiSelectionState::SCANNING) {
renderer.drawCenteredText(UI_10_FONT_ID, top, "Scanning...");
} else {
renderer.drawCenteredText(UI_12_FONT_ID, top - 40, "Connecting...", true, BOLD);
renderer.drawCenteredText(UI_12_FONT_ID, top - 40, "Connecting...", true, EpdFontFamily::BOLD);
std::string ssidInfo = "to " + selectedSSID;
if (ssidInfo.length() > 25) {
@ -592,7 +592,7 @@ void WifiSelectionActivity::renderConnected() const {
const auto height = renderer.getLineHeight(UI_10_FONT_ID);
const auto top = (pageHeight - height * 4) / 2;
renderer.drawCenteredText(UI_12_FONT_ID, top - 30, "Connected!", true, BOLD);
renderer.drawCenteredText(UI_12_FONT_ID, top - 30, "Connected!", true, EpdFontFamily::BOLD);
std::string ssidInfo = "Network: " + selectedSSID;
if (ssidInfo.length() > 28) {
@ -612,7 +612,7 @@ void WifiSelectionActivity::renderSavePrompt() const {
const auto height = renderer.getLineHeight(UI_10_FONT_ID);
const auto top = (pageHeight - height * 3) / 2;
renderer.drawCenteredText(UI_12_FONT_ID, top - 40, "Connected!", true, BOLD);
renderer.drawCenteredText(UI_12_FONT_ID, top - 40, "Connected!", true, EpdFontFamily::BOLD);
std::string ssidInfo = "Network: " + selectedSSID;
if (ssidInfo.length() > 28) {
@ -651,7 +651,7 @@ void WifiSelectionActivity::renderConnectionFailed() const {
const auto height = renderer.getLineHeight(UI_10_FONT_ID);
const auto top = (pageHeight - height * 2) / 2;
renderer.drawCenteredText(UI_12_FONT_ID, top - 20, "Connection Failed", true, BOLD);
renderer.drawCenteredText(UI_12_FONT_ID, top - 20, "Connection Failed", true, EpdFontFamily::BOLD);
renderer.drawCenteredText(UI_10_FONT_ID, top + 20, connectionError.c_str());
renderer.drawCenteredText(SMALL_FONT_ID, pageHeight - 30, "Press any button to continue");
}
@ -662,7 +662,7 @@ void WifiSelectionActivity::renderForgetPrompt() const {
const auto height = renderer.getLineHeight(UI_10_FONT_ID);
const auto top = (pageHeight - height * 3) / 2;
renderer.drawCenteredText(UI_12_FONT_ID, top - 40, "Forget Network?", true, BOLD);
renderer.drawCenteredText(UI_12_FONT_ID, top - 40, "Forget Network?", true, EpdFontFamily::BOLD);
std::string ssidInfo = "Network: " + selectedSSID;
if (ssidInfo.length() > 28) {

View File

@ -244,7 +244,7 @@ void EpubReaderActivity::renderScreen() {
// Show end of book screen
if (currentSpineIndex == epub->getSpineItemsCount()) {
renderer.clearScreen();
renderer.drawCenteredText(UI_12_FONT_ID, 300, "End of book", true, BOLD);
renderer.drawCenteredText(UI_12_FONT_ID, 300, "End of book", true, EpdFontFamily::BOLD);
renderer.displayBuffer();
return;
}
@ -263,8 +263,8 @@ void EpubReaderActivity::renderScreen() {
Serial.printf("[%lu] [ERS] Loading file: %s, index: %d\n", millis(), filepath.c_str(), currentSpineIndex);
section = std::unique_ptr<Section>(new Section(epub, currentSpineIndex, renderer));
const auto viewportWidth = renderer.getScreenWidth() - orientedMarginLeft - orientedMarginRight;
const auto viewportHeight = renderer.getScreenHeight() - orientedMarginTop - orientedMarginBottom;
const uint16_t viewportWidth = renderer.getScreenWidth() - orientedMarginLeft - orientedMarginRight;
const uint16_t viewportHeight = renderer.getScreenHeight() - orientedMarginTop - orientedMarginBottom;
if (!section->loadSectionFile(SETTINGS.getReaderFontId(), SETTINGS.getReaderLineCompression(),
SETTINGS.extraParagraphSpacing, viewportWidth, viewportHeight)) {
@ -332,7 +332,7 @@ void EpubReaderActivity::renderScreen() {
if (section->pageCount == 0) {
Serial.printf("[%lu] [ERS] No pages to render\n", millis());
renderer.drawCenteredText(UI_12_FONT_ID, 300, "Empty chapter", true, BOLD);
renderer.drawCenteredText(UI_12_FONT_ID, 300, "Empty chapter", true, EpdFontFamily::BOLD);
renderStatusBar(orientedMarginRight, orientedMarginBottom, orientedMarginLeft);
renderer.displayBuffer();
return;
@ -340,7 +340,7 @@ void EpubReaderActivity::renderScreen() {
if (section->currentPage < 0 || section->currentPage >= section->pageCount) {
Serial.printf("[%lu] [ERS] Page out of bounds: %d (max %d)\n", millis(), section->currentPage, section->pageCount);
renderer.drawCenteredText(UI_12_FONT_ID, 300, "Out of bounds", true, BOLD);
renderer.drawCenteredText(UI_12_FONT_ID, 300, "Out of bounds", true, EpdFontFamily::BOLD);
renderStatusBar(orientedMarginRight, orientedMarginBottom, orientedMarginLeft);
renderer.displayBuffer();
return;

View File

@ -121,8 +121,9 @@ void EpubReaderChapterSelectionActivity::renderScreen() {
const auto pageWidth = renderer.getScreenWidth();
const int pageItems = getPageItems();
std::string title = renderer.truncatedText(UI_12_FONT_ID, epub->getTitle().c_str(), pageWidth - 40, BOLD);
renderer.drawCenteredText(UI_12_FONT_ID, 15, title.c_str(), true, BOLD);
const std::string title =
renderer.truncatedText(UI_12_FONT_ID, epub->getTitle().c_str(), pageWidth - 40, EpdFontFamily::BOLD);
renderer.drawCenteredText(UI_12_FONT_ID, 15, title.c_str(), true, EpdFontFamily::BOLD);
const auto pageStartIndex = selectorIndex / pageItems * pageItems;
renderer.fillRect(0, 60 + (selectorIndex % pageItems) * 30 - 2, pageWidth - 1, 30);

View File

@ -173,7 +173,7 @@ void FileSelectionActivity::render() const {
renderer.clearScreen();
const auto pageWidth = renderer.getScreenWidth();
renderer.drawCenteredText(UI_12_FONT_ID, 15, "Books", true, BOLD);
renderer.drawCenteredText(UI_12_FONT_ID, 15, "Books", true, EpdFontFamily::BOLD);
// Help text
const auto labels = mappedInput.mapLabels("« Home", "Open", "", "");

View File

@ -68,8 +68,8 @@ void ReaderActivity::onSelectBookFile(const std::string& path) {
onGoToXtcReader(std::move(xtc));
} else {
exitActivity();
enterNewActivity(new FullScreenMessageActivity(renderer, mappedInput, "Failed to load XTC", REGULAR,
EInkDisplay::HALF_REFRESH));
enterNewActivity(new FullScreenMessageActivity(renderer, mappedInput, "Failed to load XTC",
EpdFontFamily::REGULAR, EInkDisplay::HALF_REFRESH));
delay(2000);
onGoToFileSelection();
}
@ -80,8 +80,8 @@ void ReaderActivity::onSelectBookFile(const std::string& path) {
onGoToEpubReader(std::move(epub));
} else {
exitActivity();
enterNewActivity(new FullScreenMessageActivity(renderer, mappedInput, "Failed to load epub", REGULAR,
EInkDisplay::HALF_REFRESH));
enterNewActivity(new FullScreenMessageActivity(renderer, mappedInput, "Failed to load epub",
EpdFontFamily::REGULAR, EInkDisplay::HALF_REFRESH));
delay(2000);
onGoToFileSelection();
}

View File

@ -165,7 +165,7 @@ void XtcReaderActivity::renderScreen() {
if (currentPage >= xtc->getPageCount()) {
// Show end of book screen
renderer.clearScreen();
renderer.drawCenteredText(UI_12_FONT_ID, 300, "End of book", true, BOLD);
renderer.drawCenteredText(UI_12_FONT_ID, 300, "End of book", true, EpdFontFamily::BOLD);
renderer.displayBuffer();
return;
}
@ -194,7 +194,7 @@ void XtcReaderActivity::renderPage() {
if (!pageBuffer) {
Serial.printf("[%lu] [XTR] Failed to allocate page buffer (%lu bytes)\n", millis(), pageBufferSize);
renderer.clearScreen();
renderer.drawCenteredText(UI_12_FONT_ID, 300, "Memory error", true, BOLD);
renderer.drawCenteredText(UI_12_FONT_ID, 300, "Memory error", true, EpdFontFamily::BOLD);
renderer.displayBuffer();
return;
}
@ -205,7 +205,7 @@ void XtcReaderActivity::renderPage() {
Serial.printf("[%lu] [XTR] Failed to load page %lu\n", millis(), currentPage);
free(pageBuffer);
renderer.clearScreen();
renderer.drawCenteredText(UI_12_FONT_ID, 300, "Page load error", true, BOLD);
renderer.drawCenteredText(UI_12_FONT_ID, 300, "Page load error", true, EpdFontFamily::BOLD);
renderer.displayBuffer();
return;
}

View File

@ -130,7 +130,7 @@ void XtcReaderChapterSelectionActivity::renderScreen() {
const auto pageWidth = renderer.getScreenWidth();
const int pageItems = getPageItems();
renderer.drawCenteredText(UI_12_FONT_ID, 15, "Select Chapter", true, BOLD);
renderer.drawCenteredText(UI_12_FONT_ID, 15, "Select Chapter", true, EpdFontFamily::BOLD);
const auto& chapters = xtc->getChapters();
if (chapters.empty()) {

View File

@ -127,16 +127,16 @@ void OtaUpdateActivity::render() {
const auto pageWidth = renderer.getScreenWidth();
renderer.clearScreen();
renderer.drawCenteredText(UI_12_FONT_ID, 15, "Update", true, BOLD);
renderer.drawCenteredText(UI_12_FONT_ID, 15, "Update", true, EpdFontFamily::BOLD);
if (state == CHECKING_FOR_UPDATE) {
renderer.drawCenteredText(UI_10_FONT_ID, 300, "Checking for update...", true, BOLD);
renderer.drawCenteredText(UI_10_FONT_ID, 300, "Checking for update...", true, EpdFontFamily::BOLD);
renderer.displayBuffer();
return;
}
if (state == WAITING_CONFIRMATION) {
renderer.drawCenteredText(UI_10_FONT_ID, 200, "New update available!", true, BOLD);
renderer.drawCenteredText(UI_10_FONT_ID, 200, "New update available!", true, EpdFontFamily::BOLD);
renderer.drawText(UI_10_FONT_ID, 20, 250, "Current Version: " CROSSPOINT_VERSION);
renderer.drawText(UI_10_FONT_ID, 20, 270, ("New Version: " + updater.getLatestVersion()).c_str());
@ -147,7 +147,7 @@ void OtaUpdateActivity::render() {
}
if (state == UPDATE_IN_PROGRESS) {
renderer.drawCenteredText(UI_10_FONT_ID, 310, "Updating...", true, BOLD);
renderer.drawCenteredText(UI_10_FONT_ID, 310, "Updating...", true, EpdFontFamily::BOLD);
renderer.drawRect(20, 350, pageWidth - 40, 50);
renderer.fillRect(24, 354, static_cast<int>(updaterProgress * static_cast<float>(pageWidth - 44)), 42);
renderer.drawCenteredText(UI_10_FONT_ID, 420,
@ -160,19 +160,19 @@ void OtaUpdateActivity::render() {
}
if (state == NO_UPDATE) {
renderer.drawCenteredText(UI_10_FONT_ID, 300, "No update available", true, BOLD);
renderer.drawCenteredText(UI_10_FONT_ID, 300, "No update available", true, EpdFontFamily::BOLD);
renderer.displayBuffer();
return;
}
if (state == FAILED) {
renderer.drawCenteredText(UI_10_FONT_ID, 300, "Update failed", true, BOLD);
renderer.drawCenteredText(UI_10_FONT_ID, 300, "Update failed", true, EpdFontFamily::BOLD);
renderer.displayBuffer();
return;
}
if (state == FINISHED) {
renderer.drawCenteredText(UI_10_FONT_ID, 300, "Update complete", true, BOLD);
renderer.drawCenteredText(UI_10_FONT_ID, 300, "Update complete", true, EpdFontFamily::BOLD);
renderer.drawCenteredText(UI_10_FONT_ID, 350, "Press and hold power button to turn back on");
renderer.displayBuffer();
state = SHUTTING_DOWN;

View File

@ -163,7 +163,7 @@ void SettingsActivity::render() const {
const auto pageHeight = renderer.getScreenHeight();
// Draw header
renderer.drawCenteredText(UI_12_FONT_ID, 15, "Settings", true, BOLD);
renderer.drawCenteredText(UI_12_FONT_ID, 15, "Settings", true, EpdFontFamily::BOLD);
// Draw selection
renderer.fillRect(0, 60 + selectedSettingIndex * 30 - 2, pageWidth - 1, 30);

View File

@ -9,12 +9,12 @@
class FullScreenMessageActivity final : public Activity {
std::string text;
EpdFontStyle style;
EpdFontFamily::Style style;
EInkDisplay::RefreshMode refreshMode;
public:
explicit FullScreenMessageActivity(GfxRenderer& renderer, MappedInputManager& mappedInput, std::string text,
const EpdFontStyle style = REGULAR,
const EpdFontFamily::Style style = EpdFontFamily::REGULAR,
const EInkDisplay::RefreshMode refreshMode = EInkDisplay::FAST_REFRESH)
: Activity("FullScreenMessage", renderer, mappedInput),
text(std::move(text)),

View File

@ -151,8 +151,8 @@ void verifyWakeupLongPress() {
const auto start = millis();
bool abort = false;
// It takes us some time to wake up from deep sleep, so we need to subtract that from the duration
uint16_t calibration = 29;
uint16_t calibratedPressDuration =
constexpr uint16_t calibration = 29;
const uint16_t calibratedPressDuration =
(calibration < SETTINGS.getPowerButtonDuration()) ? SETTINGS.getPowerButtonDuration() - calibration : 1;
inputManager.update();
@ -271,7 +271,7 @@ void setup() {
Serial.printf("[%lu] [ ] SD card initialization failed\n", millis());
setupDisplayAndFonts();
exitActivity();
enterNewActivity(new FullScreenMessageActivity(renderer, mappedInputManager, "SD card error", BOLD));
enterNewActivity(new FullScreenMessageActivity(renderer, mappedInputManager, "SD card error", EpdFontFamily::BOLD));
return;
}