Compare commits

...

4 Commits

Author SHA1 Message Date
Brackyt
7bfb3af0da fix(cppcheck): more clang format fix 2026-01-26 00:33:27 +01:00
Brackyt
e6f6f14b37 fix(cppcheck): clang format 2026-01-26 00:27:58 +01:00
Brackyt
a4310bf2c3 fix(cppcheck): resolve style and performance issues
- Remove unused HomeActivity::restoreCoverBuffer
- Use initialization lists in constructors
- Mark single-argument constructors as explicit
2026-01-26 00:22:05 +01:00
Brackyt
75cc861bd0 feat: expose detailed book metadata in HomeActivity 2026-01-26 00:16:16 +01:00
9 changed files with 188 additions and 131 deletions

View File

@ -805,10 +805,11 @@ void GfxRenderer::drawBitmap1Bit(const Bitmap& bitmap, const int x, const int y,
free(rowBytes); free(rowBytes);
} }
void GfxRenderer::drawTransparentBitmap(const Bitmap& bitmap, const int x, const int y, const int w, const int h) const { void GfxRenderer::drawTransparentBitmap(const Bitmap& bitmap, const int x, const int y, const int w,
const int h) const {
// Similar to drawBitmap1Bit but strictly skips 1s (white) in the source 1-bit data // Similar to drawBitmap1Bit but strictly skips 1s (white) in the source 1-bit data
// The Bitmap reader returns 2-bit packed data where 0-2=Black and 3=White for 1-bit sources // The Bitmap reader returns 2-bit packed data where 0-2=Black and 3=White for 1-bit sources
float scale = 1.0f; float scale = 1.0f;
bool isScaled = false; bool isScaled = false;
if (w > 0) { if (w > 0) {
@ -839,11 +840,11 @@ void GfxRenderer::drawTransparentBitmap(const Bitmap& bitmap, const int x, const
} }
const int bmpYOffset = bitmap.isTopDown() ? bmpY : bitmap.getHeight() - 1 - bmpY; const int bmpYOffset = bitmap.isTopDown() ? bmpY : bitmap.getHeight() - 1 - bmpY;
// Calculate target Y span // Calculate target Y span
int startY = y + static_cast<int>(std::floor(bmpYOffset * scale)); int startY = y + static_cast<int>(std::floor(bmpYOffset * scale));
int endY = y + static_cast<int>(std::floor((bmpYOffset + 1) * scale)); int endY = y + static_cast<int>(std::floor((bmpYOffset + 1) * scale));
// Clamp to screen // Clamp to screen
if (startY < 0) startY = 0; if (startY < 0) startY = 0;
if (endY > getScreenHeight()) endY = getScreenHeight(); if (endY > getScreenHeight()) endY = getScreenHeight();
@ -853,7 +854,7 @@ void GfxRenderer::drawTransparentBitmap(const Bitmap& bitmap, const int x, const
// Calculate target X span // Calculate target X span
int startX = x + static_cast<int>(std::floor(bmpX * scale)); int startX = x + static_cast<int>(std::floor(bmpX * scale));
int endX = x + static_cast<int>(std::floor((bmpX + 1) * scale)); int endX = x + static_cast<int>(std::floor((bmpX + 1) * scale));
if (startX < 0) startX = 0; if (startX < 0) startX = 0;
if (endX > getScreenWidth()) endX = getScreenWidth(); if (endX > getScreenWidth()) endX = getScreenWidth();
if (startX >= endX) continue; if (startX >= endX) continue;
@ -864,7 +865,7 @@ void GfxRenderer::drawTransparentBitmap(const Bitmap& bitmap, const int x, const
if (val < 3) { if (val < 3) {
for (int sy = startY; sy < endY; sy++) { for (int sy = startY; sy < endY; sy++) {
for (int sx = startX; sx < endX; sx++) { for (int sx = startX; sx < endX; sx++) {
drawPixel(sx, sy, true); // Black drawPixel(sx, sy, true); // Black
} }
} }
} }
@ -945,11 +946,11 @@ void GfxRenderer::drawRoundedBitmap(const Bitmap& bitmap, const int x, const int
} }
const int bmpYOffset = bitmap.isTopDown() ? bmpY : bitmap.getHeight() - 1 - bmpY; const int bmpYOffset = bitmap.isTopDown() ? bmpY : bitmap.getHeight() - 1 - bmpY;
// Calculate target Y span // Calculate target Y span
int startY = y + static_cast<int>(std::floor(bmpYOffset * scale)); int startY = y + static_cast<int>(std::floor(bmpYOffset * scale));
int endY = y + static_cast<int>(std::floor((bmpYOffset + 1) * scale)); int endY = y + static_cast<int>(std::floor((bmpYOffset + 1) * scale));
if (startY < 0) startY = 0; if (startY < 0) startY = 0;
if (endY > getScreenHeight()) endY = getScreenHeight(); if (endY > getScreenHeight()) endY = getScreenHeight();
if (startY >= endY) continue; if (startY >= endY) continue;
@ -957,7 +958,7 @@ void GfxRenderer::drawRoundedBitmap(const Bitmap& bitmap, const int x, const int
for (int bmpX = 0; bmpX < bitmap.getWidth(); bmpX++) { for (int bmpX = 0; bmpX < bitmap.getWidth(); bmpX++) {
int startX = x + static_cast<int>(std::floor(bmpX * scale)); int startX = x + static_cast<int>(std::floor(bmpX * scale));
int endX = x + static_cast<int>(std::floor((bmpX + 1) * scale)); int endX = x + static_cast<int>(std::floor((bmpX + 1) * scale));
if (startX < 0) startX = 0; if (startX < 0) startX = 0;
if (endX > getScreenWidth()) endX = getScreenWidth(); if (endX > getScreenWidth()) endX = getScreenWidth();
if (startX >= endX) continue; if (startX >= endX) continue;
@ -968,7 +969,7 @@ void GfxRenderer::drawRoundedBitmap(const Bitmap& bitmap, const int x, const int
if (renderMode == BW) { if (renderMode == BW) {
pixelBlack = (val < 2); pixelBlack = (val < 2);
} else if (renderMode == GRAYSCALE_MSB) { } else if (renderMode == GRAYSCALE_MSB) {
pixelBlack = (val < 3); // Draw all non-white as black for icons/covers pixelBlack = (val < 3); // Draw all non-white as black for icons/covers
} else if (renderMode == GRAYSCALE_LSB) { } else if (renderMode == GRAYSCALE_LSB) {
pixelBlack = (val == 0); pixelBlack = (val == 0);
} }

View File

@ -78,7 +78,8 @@ class GfxRenderer {
float cropY = 0) const; float cropY = 0) const;
void drawBitmap1Bit(const Bitmap& bitmap, const int x, const int y, const int maxWidth, const int maxHeight) const; void drawBitmap1Bit(const Bitmap& bitmap, const int x, const int y, const int maxWidth, const int maxHeight) const;
void drawTransparentBitmap(const Bitmap& bitmap, const int x, const int y, const int w, const int h) const; void drawTransparentBitmap(const Bitmap& bitmap, const int x, const int y, const int w, const int h) const;
void drawRoundedBitmap(const Bitmap& bitmap, const int x, const int y, const int w, const int h, const int radius) const; void drawRoundedBitmap(const Bitmap& bitmap, const int x, const int y, const int w, const int h,
const int radius) const;
void draw2BitImage(const uint8_t data[], int x, int y, int w, int h) const; void draw2BitImage(const uint8_t data[], int x, int y, int w, int h) const;
void fillPolygon(const int* xPoints, const int* yPoints, int numPoints, bool state = true) const; void fillPolygon(const int* xPoints, const int* yPoints, int numPoints, bool state = true) const;

View File

@ -23,7 +23,7 @@ class Container : public UIElement {
int borderRadius = 0; // Corner radius (for future rounded rect support) int borderRadius = 0; // Corner radius (for future rounded rect support)
public: public:
Container(const std::string& id) : UIElement(id) { bgColorExpr = Expression::parse("0xFF"); } explicit Container(const std::string& id) : UIElement(id), bgColorExpr(Expression::parse("0xFF")) {}
virtual ~Container() { virtual ~Container() {
for (auto child : children) delete child; for (auto child : children) delete child;
} }
@ -145,7 +145,7 @@ class Rectangle : public UIElement {
Expression colorExpr; Expression colorExpr;
public: public:
Rectangle(const std::string& id) : UIElement(id) { colorExpr = Expression::parse("0x00"); } explicit Rectangle(const std::string& id) : UIElement(id), colorExpr(Expression::parse("0x00")) {}
ElementType getType() const override { return ElementType::Rectangle; } ElementType getType() const override { return ElementType::Rectangle; }
void setFill(bool f) { void setFill(bool f) {
@ -199,7 +199,7 @@ class Label : public UIElement {
bool ellipsis = true; // Truncate with ... if too long bool ellipsis = true; // Truncate with ... if too long
public: public:
Label(const std::string& id) : UIElement(id) { colorExpr = Expression::parse("0x00"); } explicit Label(const std::string& id) : UIElement(id), colorExpr(Expression::parse("0x00")) {}
ElementType getType() const override { return ElementType::Label; } ElementType getType() const override { return ElementType::Label; }
void setText(const std::string& expr) { void setText(const std::string& expr) {
@ -262,67 +262,67 @@ class Label : public UIElement {
// Binary search for cut point // Binary search for cut point
int len = remaining.length(); int len = remaining.length();
int cut = len; int cut = len;
// Find split point // Find split point
// Optimistic start: approximate chars that fit // Optimistic start: approximate chars that fit
int avgCharWidth = renderer.getTextWidth(fontId, "a"); int avgCharWidth = renderer.getTextWidth(fontId, "a");
if (avgCharWidth < 1) avgCharWidth = 8; if (avgCharWidth < 1) avgCharWidth = 8;
int approxChars = absW / avgCharWidth; int approxChars = absW / avgCharWidth;
if (approxChars < 1) approxChars = 1; if (approxChars < 1) approxChars = 1;
if (approxChars >= len) approxChars = len - 1; if (approxChars >= len) approxChars = len - 1;
// Refine from approxChars // Refine from approxChars
int w = renderer.getTextWidth(fontId, remaining.substr(0, approxChars).c_str()); int w = renderer.getTextWidth(fontId, remaining.substr(0, approxChars).c_str());
if (w < absW) { if (w < absW) {
// Grow // Grow
for (int i = approxChars; i <= len; i++) { for (int i = approxChars; i <= len; i++) {
if (renderer.getTextWidth(fontId, remaining.substr(0, i).c_str()) > absW) { if (renderer.getTextWidth(fontId, remaining.substr(0, i).c_str()) > absW) {
cut = i - 1; cut = i - 1;
break; break;
} }
cut = i; cut = i;
} }
} else { } else {
// Shrink // Shrink
for (int i = approxChars; i > 0; i--) { for (int i = approxChars; i > 0; i--) {
if (renderer.getTextWidth(fontId, remaining.substr(0, i).c_str()) <= absW) { if (renderer.getTextWidth(fontId, remaining.substr(0, i).c_str()) <= absW) {
cut = i; cut = i;
break; break;
} }
} }
} }
// Find last space before cut // Find last space before cut
if (cut < (int)remaining.length()) { if (cut < (int)remaining.length()) {
int space = -1; int space = -1;
for (int i = cut; i > 0; i--) { for (int i = cut; i > 0; i--) {
if (remaining[i] == ' ') { if (remaining[i] == ' ') {
space = i; space = i;
break; break;
}
} }
if (space != -1) cut = space; }
if (space != -1) cut = space;
} }
std::string line = remaining.substr(0, cut); std::string line = remaining.substr(0, cut);
// If we're at the last allowed line but still have more text // If we're at the last allowed line but still have more text
if ((int)lines.size() == maxLines - 1 && cut < (int)remaining.length()) { if ((int)lines.size() == maxLines - 1 && cut < (int)remaining.length()) {
if (ellipsis) { if (ellipsis) {
line = renderer.truncatedText(fontId, remaining.c_str(), absW); line = renderer.truncatedText(fontId, remaining.c_str(), absW);
} }
lines.push_back(line); lines.push_back(line);
break; break;
} }
lines.push_back(line); lines.push_back(line);
// Advance // Advance
if (cut < (int)remaining.length()) { if (cut < (int)remaining.length()) {
// Skip the space if check // Skip the space if check
if (remaining[cut] == ' ') cut++; if (remaining[cut] == ' ') cut++;
remaining = remaining.substr(cut); remaining = remaining.substr(cut);
} else { } else {
remaining = ""; remaining = "";
} }
} }
} else { } else {
@ -332,29 +332,29 @@ class Label : public UIElement {
} }
lines.push_back(finalText); lines.push_back(finalText);
} }
// Draw lines // Draw lines
int totalTextHeight = lines.size() * lineHeight; int totalTextHeight = lines.size() * lineHeight;
int startY = absY; int startY = absY;
// Vertical centering // Vertical centering
if (absH > 0 && totalTextHeight < absH) { if (absH > 0 && totalTextHeight < absH) {
startY = absY + (absH - totalTextHeight) / 2; startY = absY + (absH - totalTextHeight) / 2;
} }
for (size_t i = 0; i < lines.size(); i++) { for (size_t i = 0; i < lines.size(); i++) {
int lineWidth = renderer.getTextWidth(fontId, lines[i].c_str()); int lineWidth = renderer.getTextWidth(fontId, lines[i].c_str());
int drawX = absX; int drawX = absX;
if (alignment == Alignment::Center && absW > 0) { if (alignment == Alignment::Center && absW > 0) {
drawX = absX + (absW - lineWidth) / 2; drawX = absX + (absW - lineWidth) / 2;
} else if (alignment == Alignment::Right && absW > 0) { } else if (alignment == Alignment::Right && absW > 0) {
drawX = absX + absW - lineWidth; drawX = absX + absW - lineWidth;
} }
renderer.drawText(fontId, drawX, startY + i * lineHeight, lines[i].c_str(), black); renderer.drawText(fontId, drawX, startY + i * lineHeight, lines[i].c_str(), black);
} }
markClean(); markClean();
} }
}; };
@ -367,7 +367,7 @@ class BitmapElement : public UIElement {
int borderRadius = 0; int borderRadius = 0;
public: public:
BitmapElement(const std::string& id) : UIElement(id) { explicit BitmapElement(const std::string& id) : UIElement(id) {
cacheable = true; // Bitmaps benefit from caching cacheable = true; // Bitmaps benefit from caching
} }
ElementType getType() const override { return ElementType::Bitmap; } ElementType getType() const override { return ElementType::Bitmap; }
@ -407,12 +407,13 @@ class ProgressBar : public UIElement {
int borderWidth = 1; int borderWidth = 1;
public: public:
ProgressBar(const std::string& id) : UIElement(id) { explicit ProgressBar(const std::string& id)
valueExpr = Expression::parse("0"); : UIElement(id),
maxExpr = Expression::parse("100"); valueExpr(Expression::parse("0")),
fgColorExpr = Expression::parse("0x00"); // Black fill maxExpr(Expression::parse("100")),
bgColorExpr = Expression::parse("0xFF"); // White background fgColorExpr(Expression::parse("0x00")), // Black fill
} bgColorExpr(Expression::parse("0xFF")) // White background
{}
ElementType getType() const override { return ElementType::ProgressBar; } ElementType getType() const override { return ElementType::ProgressBar; }
@ -480,7 +481,7 @@ class Divider : public UIElement {
int thickness = 1; int thickness = 1;
public: public:
Divider(const std::string& id) : UIElement(id) { colorExpr = Expression::parse("0x00"); } explicit Divider(const std::string& id) : UIElement(id), colorExpr(Expression::parse("0x00")) {}
ElementType getType() const override { return ElementType::Divider; } ElementType getType() const override { return ElementType::Divider; }
@ -524,9 +525,9 @@ class BatteryIcon : public UIElement {
Expression colorExpr; Expression colorExpr;
public: public:
BatteryIcon(const std::string& id) : UIElement(id) { explicit BatteryIcon(const std::string& id)
valueExpr = Expression::parse("0"); : UIElement(id), valueExpr(Expression::parse("0")), colorExpr(Expression::parse("0x00")) {
colorExpr = Expression::parse("0x00"); // Black by default // Black by default
} }
ElementType getType() const override { return ElementType::BatteryIcon; } ElementType getType() const override { return ElementType::BatteryIcon; }

View File

@ -83,7 +83,7 @@ class ThemeContext {
} }
public: public:
ThemeContext(const ThemeContext* parent = nullptr) : parent(parent) {} explicit ThemeContext(const ThemeContext* parent = nullptr) : parent(parent) {}
void setString(const std::string& key, const std::string& value) { strings[key] = value; } void setString(const std::string& key, const std::string& value) { strings[key] = value; }
void setInt(const std::string& key, int value) { ints[key] = value; } void setInt(const std::string& key, int value) { ints[key] = value; }

View File

@ -34,7 +34,7 @@ struct Dimension {
struct Color { struct Color {
uint8_t value; // For E-Ink: 0 (Black) to 255 (White), or simplified palette uint8_t value; // For E-Ink: 0 (Black) to 255 (White), or simplified palette
Color(uint8_t v) : value(v) {} explicit Color(uint8_t v) : value(v) {}
Color() : value(0) {} Color() : value(0) {}
static Color parse(const std::string& str) { static Color parse(const std::string& str) {

View File

@ -45,7 +45,7 @@ class UIElement {
} }
public: public:
UIElement(const std::string& id) : id(id) { visibleExpr = Expression::parse("true"); } UIElement(const std::string& id) : id(id), visibleExpr(Expression::parse("true")) {}
virtual ~UIElement() { virtual ~UIElement() {
if (cachedRender) { if (cachedRender) {

View File

@ -1,10 +1,11 @@
#include "BasicElements.h" #include "BasicElements.h"
#include <GfxRenderer.h>
#include "Bitmap.h" #include "Bitmap.h"
#include "ListElement.h" #include "ListElement.h"
#include "ThemeManager.h" #include "ThemeManager.h"
#include "ThemeTypes.h" #include "ThemeTypes.h"
#include <GfxRenderer.h>
namespace ThemeEngine { namespace ThemeEngine {
@ -23,7 +24,7 @@ void BitmapElement::draw(const GfxRenderer& renderer, const ThemeContext& contex
// Resolve simplified or relative paths // Resolve simplified or relative paths
if (path.find('/') == std::string::npos || (path.length() > 0 && path[0] != '/')) { if (path.find('/') == std::string::npos || (path.length() > 0 && path[0] != '/')) {
path = ThemeManager::get().getAssetPath(path); path = ThemeManager::get().getAssetPath(path);
} }
// 1. Check if we have a cached 1-bit render // 1. Check if we have a cached 1-bit render
@ -47,46 +48,46 @@ void BitmapElement::draw(const GfxRenderer& renderer, const ThemeContext& contex
// 2. Try Streaming (Absolute paths, large images) // 2. Try Streaming (Absolute paths, large images)
if (path.length() > 0 && path[0] == '/') { if (path.length() > 0 && path[0] == '/') {
FsFile file; FsFile file;
if (SdMan.openFileForRead("HOME", path, file)) { if (SdMan.openFileForRead("HOME", path, file)) {
Bitmap bmp(file, true); // (file, dithering=true) Bitmap bmp(file, true); // (file, dithering=true)
if (bmp.parseHeaders() == BmpReaderError::Ok) { if (bmp.parseHeaders() == BmpReaderError::Ok) {
// Center logic // Center logic
int drawX = absX; int drawX = absX;
int drawY = absY; int drawY = absY;
if (bmp.getWidth() < absW) drawX += (absW - bmp.getWidth()) / 2; if (bmp.getWidth() < absW) drawX += (absW - bmp.getWidth()) / 2;
if (bmp.getHeight() < absH) drawY += (absH - bmp.getHeight()) / 2; if (bmp.getHeight() < absH) drawY += (absH - bmp.getHeight()) / 2;
if (borderRadius > 0) { if (borderRadius > 0) {
renderer.drawRoundedBitmap(bmp, drawX, drawY, absW, absH, borderRadius); renderer.drawRoundedBitmap(bmp, drawX, drawY, absW, absH, borderRadius);
} else { } else {
renderer.drawBitmap(bmp, drawX, drawY, absW, absH); renderer.drawBitmap(bmp, drawX, drawY, absW, absH);
} }
drawSuccess = true; drawSuccess = true;
}
file.close();
} }
file.close();
}
} }
// 3. Fallback to RAM Cache (Standard method) // 3. Fallback to RAM Cache (Standard method)
if (!drawSuccess) { if (!drawSuccess) {
const std::vector<uint8_t>* data = ThemeManager::get().getCachedAsset(path); const std::vector<uint8_t>* data = ThemeManager::get().getCachedAsset(path);
if (data && !data->empty()) { if (data && !data->empty()) {
Bitmap bmp(data->data(), data->size()); Bitmap bmp(data->data(), data->size());
if (bmp.parseHeaders() == BmpReaderError::Ok) { if (bmp.parseHeaders() == BmpReaderError::Ok) {
int drawX = absX; int drawX = absX;
int drawY = absY; int drawY = absY;
if (bmp.getWidth() < absW) drawX += (absW - bmp.getWidth()) / 2; if (bmp.getWidth() < absW) drawX += (absW - bmp.getWidth()) / 2;
if (bmp.getHeight() < absH) drawY += (absH - bmp.getHeight()) / 2; if (bmp.getHeight() < absH) drawY += (absH - bmp.getHeight()) / 2;
if (borderRadius > 0) { if (borderRadius > 0) {
renderer.drawRoundedBitmap(bmp, drawX, drawY, absW, absH, borderRadius); renderer.drawRoundedBitmap(bmp, drawX, drawY, absW, absH, borderRadius);
} else { } else {
renderer.drawBitmap(bmp, drawX, drawY, absW, absH); renderer.drawBitmap(bmp, drawX, drawY, absW, absH);
}
drawSuccess = true;
} }
} drawSuccess = true;
}
}
} }
// 4. Cache result if successful // 4. Cache result if successful

View File

@ -229,21 +229,6 @@ bool HomeActivity::storeCoverBuffer() {
return true; return true;
} }
bool HomeActivity::restoreCoverBuffer() {
if (!coverBuffer) {
return false;
}
uint8_t* frameBuffer = renderer.getFrameBuffer();
if (!frameBuffer) {
return false;
}
const size_t bufferSize = GfxRenderer::getBufferSize();
memcpy(frameBuffer, coverBuffer, bufferSize);
return true;
}
void HomeActivity::freeCoverBuffer() { void HomeActivity::freeCoverBuffer() {
if (coverBuffer) { if (coverBuffer) {
free(coverBuffer); free(coverBuffer);
@ -364,6 +349,74 @@ void HomeActivity::render() {
context.setBool("HasCover", hasContinueReading && hasCoverImage && !coverBmpPath.empty()); context.setBool("HasCover", hasContinueReading && hasCoverImage && !coverBmpPath.empty());
context.setBool("ShowInfoBox", true); context.setBool("ShowInfoBox", true);
// Default values
std::string chapterTitle = "";
std::string currentPageStr = "-";
std::string totalPagesStr = "-";
int progressPercent = 0;
if (hasContinueReading) {
if (StringUtils::checkFileExtension(APP_STATE.openEpubPath, ".epub")) {
Epub epub(APP_STATE.openEpubPath, "/.crosspoint");
epub.load(false);
// Read progress
FsFile f;
if (SdMan.openFileForRead("HOME", epub.getCachePath() + "/progress.bin", f)) {
uint8_t data[4];
if (f.read(data, 4) == 4) {
int spineIndex = data[0] + (data[1] << 8);
int spineCount = epub.getSpineItemsCount();
currentPageStr = std::to_string(spineIndex + 1); // Display 1-based
totalPagesStr = std::to_string(spineCount);
if (spineCount > 0) {
progressPercent = (spineIndex * 100) / spineCount;
}
// Resolve Chapter Title
auto spineEntry = epub.getSpineItem(spineIndex);
if (spineEntry.tocIndex != -1) {
auto tocEntry = epub.getTocItem(spineEntry.tocIndex);
chapterTitle = tocEntry.title;
}
}
f.close();
}
} else if (StringUtils::checkFileExtension(APP_STATE.openEpubPath, ".xtc") ||
StringUtils::checkFileExtension(APP_STATE.openEpubPath, ".xtch")) {
Xtc xtc(APP_STATE.openEpubPath, "/.crosspoint");
if (xtc.load()) {
// Read progress
FsFile f;
if (SdMan.openFileForRead("HOME", xtc.getCachePath() + "/progress.bin", f)) {
uint8_t data[4];
if (f.read(data, 4) == 4) {
uint32_t currentPage = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
uint32_t totalPages = xtc.getPageCount();
currentPageStr = std::to_string(currentPage + 1); // 1-based
totalPagesStr = std::to_string(totalPages);
if (totalPages > 0) {
progressPercent = (currentPage * 100) / totalPages;
}
chapterTitle = "Page " + currentPageStr;
}
f.close();
}
}
}
}
context.setString("BookChapter", chapterTitle);
context.setString("BookCurrentPage", currentPageStr);
context.setString("BookTotalPages", totalPagesStr);
context.setInt("BookProgressPercent", progressPercent);
context.setString("BookProgressPercentStr", std::to_string(progressPercent));
// --- Main Menu Data --- // --- Main Menu Data ---
// Menu items start after the book slot // Menu items start after the book slot
const int menuStartIdx = navBookCount; const int menuStartIdx = navBookCount;

View File

@ -46,8 +46,8 @@ class HomeActivity final : public Activity {
[[noreturn]] void displayTaskLoop(); [[noreturn]] void displayTaskLoop();
void render(); void render();
int getMenuItemCount() const; int getMenuItemCount() const;
bool storeCoverBuffer(); // Store frame buffer for cover image bool storeCoverBuffer(); // Store frame buffer for cover image
bool restoreCoverBuffer(); // Restore frame buffer from stored cover
void freeCoverBuffer(); // Free the stored cover buffer void freeCoverBuffer(); // Free the stored cover buffer
void loadRecentBooksData(); // Load and cache recent books data void loadRecentBooksData(); // Load and cache recent books data