style: fix all cppcheck warnings
Some checks failed
CI / build (push) Failing after 3m20s

- Fix ignored return value in TxtReaderActivity
- Remove unused variables across multiple files
- Add const correctness to DictionaryMargins and EpubReaderActivity
- Replace inefficient substr patterns with resize+append
- Use STL algorithms (find_if, any_of, copy_if, transform) where applicable
- Remove dead sync placeholder code in EpubReaderChapterSelectionActivity
- Add cppcheck suppression for ValueFlow analysis limitation

Resolves all low, medium, and high severity cppcheck defects.
This commit is contained in:
cottongin 2026-01-28 09:45:42 -05:00
parent fe446d4690
commit bd95bfd44d
No known key found for this signature in database
GPG Key ID: 0ECC91FE4655C262
13 changed files with 66 additions and 102 deletions

View File

@ -164,8 +164,7 @@ void SleepActivity::renderBitmapSleepScreen(const Bitmap& bitmap, const std::str
float cropX = 0, cropY = 0; float cropX = 0, cropY = 0;
int drawWidth = pageWidth; int drawWidth = pageWidth;
int drawHeight = pageHeight; int drawHeight = pageHeight;
int fillWidth = pageWidth; // Actual area the image will occupy int fillWidth, fillHeight; // Actual area the image will occupy (set per mode)
int fillHeight = pageHeight;
Serial.printf("[%lu] [SLP] bitmap %d x %d, screen %d x %d\n", millis(), bitmap.getWidth(), bitmap.getHeight(), Serial.printf("[%lu] [SLP] bitmap %d x %d, screen %d x %d\n", millis(), bitmap.getWidth(), bitmap.getHeight(),
pageWidth, pageHeight); pageWidth, pageHeight);
@ -183,9 +182,9 @@ void SleepActivity::renderBitmapSleepScreen(const Bitmap& bitmap, const std::str
// Don't constrain to screen dimensions - drawBitmap will clip // Don't constrain to screen dimensions - drawBitmap will clip
drawWidth = 0; drawWidth = 0;
drawHeight = 0; drawHeight = 0;
fillWidth = bitmap.getWidth(); fillWidth = static_cast<int>(bitmap.getWidth());
fillHeight = bitmap.getHeight(); fillHeight = static_cast<int>(bitmap.getHeight());
Serial.printf("[%lu] [SLP] ACTUAL mode: centering at %d, %d\n", millis(), x, y); Serial.printf("[%lu] [SLP] ACTUAL mode: centering at %d, %d (fill: %dx%d)\n", millis(), x, y, fillWidth, fillHeight);
} else if (coverMode == CrossPointSettings::SLEEP_SCREEN_COVER_MODE::CROP) { } else if (coverMode == CrossPointSettings::SLEEP_SCREEN_COVER_MODE::CROP) {
// CROP mode: Scale to fill screen completely (may crop edges) // CROP mode: Scale to fill screen completely (may crop edges)
// Calculate crop values to fill the screen while maintaining aspect ratio // Calculate crop values to fill the screen while maintaining aspect ratio

View File

@ -18,7 +18,7 @@
* - PortraitInverted: Front=TOP, Side=LEFT * - PortraitInverted: Front=TOP, Side=LEFT
* - LandscapeCCW: Front=RIGHT, Side=TOP * - LandscapeCCW: Front=RIGHT, Side=TOP
*/ */
inline void getDictionaryContentMargins(GfxRenderer& renderer, int* outTop, int* outRight, int* outBottom, inline void getDictionaryContentMargins(const GfxRenderer& renderer, int* outTop, int* outRight, int* outBottom,
int* outLeft) { int* outLeft) {
// Start with same base margins as reader (getOrientedViewableTRBL + screenMargin) // Start with same base margins as reader (getOrientedViewableTRBL + screenMargin)
renderer.getOrientedViewableTRBL(outTop, outRight, outBottom, outLeft); renderer.getOrientedViewableTRBL(outTop, outRight, outBottom, outLeft);

View File

@ -152,7 +152,6 @@ void DictionaryResultActivity::render() const {
int marginTop, marginRight, marginBottom, marginLeft; int marginTop, marginRight, marginBottom, marginLeft;
getDictionaryContentMargins(renderer, &marginTop, &marginRight, &marginBottom, &marginLeft); getDictionaryContentMargins(renderer, &marginTop, &marginRight, &marginBottom, &marginLeft);
const auto pageWidth = renderer.getScreenWidth();
const auto pageHeight = renderer.getScreenHeight(); const auto pageHeight = renderer.getScreenHeight();
// Draw header with top margin // Draw header with top margin

View File

@ -77,13 +77,9 @@ void EpubWordSelectionActivity::buildWordList() {
while (wordIt != words.end() && xPosIt != xPositions.end() && styleIt != styles.end()) { while (wordIt != words.end() && xPosIt != xPositions.end() && styleIt != styles.end()) {
// Skip whitespace-only words // Skip whitespace-only words
const std::string& wordText = *wordIt; const std::string& wordText = *wordIt;
bool hasAlpha = false; const bool hasAlpha = std::any_of(wordText.begin(), wordText.end(), [](char c) {
for (char c : wordText) { return std::isalpha(static_cast<unsigned char>(c));
if (std::isalpha(static_cast<unsigned char>(c))) { });
hasAlpha = true;
break;
}
}
if (hasAlpha) { if (hasAlpha) {
WordInfo info; WordInfo info;
@ -106,7 +102,6 @@ void EpubWordSelectionActivity::buildWordList() {
int EpubWordSelectionActivity::findLineForWordIndex(int wordIndex) const { int EpubWordSelectionActivity::findLineForWordIndex(int wordIndex) const {
if (wordIndex < 0 || wordIndex >= static_cast<int>(allWords.size())) return 0; if (wordIndex < 0 || wordIndex >= static_cast<int>(allWords.size())) return 0;
const int targetY = allWords[wordIndex].y;
int lineIdx = 0; int lineIdx = 0;
int lastY = -1; int lastY = -1;

View File

@ -113,7 +113,6 @@ void BookmarkListActivity::loop() {
// Normal state handling // Normal state handling
const int itemCount = static_cast<int>(bookmarks.size()); const int itemCount = static_cast<int>(bookmarks.size());
const int pageItems = getPageItems();
// Long press Confirm to delete bookmark // Long press Confirm to delete bookmark
if (mappedInput.isPressed(MappedInputManager::Button::Confirm) && if (mappedInput.isPressed(MappedInputManager::Button::Confirm) &&

View File

@ -691,7 +691,8 @@ void HomeActivity::render() {
std::string truncatedLabel = listsLabel; std::string truncatedLabel = listsLabel;
const int maxLabelWidth = halfTileWidth - 16; // Padding const int maxLabelWidth = halfTileWidth - 16; // Padding
while (renderer.getTextWidth(UI_10_FONT_ID, truncatedLabel.c_str()) > maxLabelWidth && truncatedLabel.length() > 3) { while (renderer.getTextWidth(UI_10_FONT_ID, truncatedLabel.c_str()) > maxLabelWidth && truncatedLabel.length() > 3) {
truncatedLabel = truncatedLabel.substr(0, truncatedLabel.length() - 4) + "..."; truncatedLabel.resize(truncatedLabel.length() - 4);
truncatedLabel += "...";
} }
const int textWidth = renderer.getTextWidth(UI_10_FONT_ID, truncatedLabel.c_str()); const int textWidth = renderer.getTextWidth(UI_10_FONT_ID, truncatedLabel.c_str());

View File

@ -7,6 +7,7 @@
#include <algorithm> #include <algorithm>
#include <cctype> #include <cctype>
#include <cstring> #include <cstring>
#include <iterator>
#include <set> #include <set>
#include "BookListStore.h" #include "BookListStore.h"
@ -154,12 +155,11 @@ void MyLibraryActivity::loadBookmarkedBooks() {
// Try to get better metadata from recent books // Try to get better metadata from recent books
for (auto& book : bookmarkedBooks) { for (auto& book : bookmarkedBooks) {
for (const auto& recent : recentBooks) { auto it = std::find_if(recentBooks.begin(), recentBooks.end(),
if (recent.path == book.path) { [&book](const RecentBooksStore::RecentBook& recent) { return recent.path == book.path; });
if (!recent.title.empty()) book.title = recent.title; if (it != recentBooks.end()) {
if (!recent.author.empty()) book.author = recent.author; if (!it->title.empty()) book.title = it->title;
break; if (!it->author.empty()) book.author = it->author;
}
} }
} }
} }
@ -207,12 +207,11 @@ void MyLibraryActivity::loadAllBooks() {
} }
// Try to get metadata from recent books if available // Try to get metadata from recent books if available
for (const auto& recent : recentBooks) { auto it = std::find_if(recentBooks.begin(), recentBooks.end(),
if (recent.path == fullPath) { [&fullPath](const RecentBooksStore::RecentBook& recent) { return recent.path == fullPath; });
if (!recent.title.empty()) result.title = recent.title; if (it != recentBooks.end()) {
if (!recent.author.empty()) result.author = recent.author; if (!it->title.empty()) result.title = it->title;
break; if (!it->author.empty()) result.author = it->author;
}
} }
allBooks.push_back(result); allBooks.push_back(result);
@ -282,11 +281,9 @@ void MyLibraryActivity::buildSearchCharacters() {
} }
// Add symbols (anything else in the set) // Add symbols (anything else in the set)
for (char c : charSet) { std::copy_if(charSet.begin(), charSet.end(), std::back_inserter(searchCharacters), [](char c) {
if (!std::isalpha(static_cast<unsigned char>(c)) && !std::isdigit(static_cast<unsigned char>(c))) { return !std::isalpha(static_cast<unsigned char>(c)) && !std::isdigit(static_cast<unsigned char>(c));
searchCharacters.push_back(c); });
}
}
// Reset character index if it's out of bounds // Reset character index if it's out of bounds
if (searchCharIndex >= static_cast<int>(searchCharacters.size()) + 3) { // +3 for special keys if (searchCharIndex >= static_cast<int>(searchCharacters.size()) + 3) { // +3 for special keys
@ -304,16 +301,20 @@ void MyLibraryActivity::updateSearchResults() {
// Convert query to lowercase for case-insensitive matching // Convert query to lowercase for case-insensitive matching
std::string queryLower = searchQuery; std::string queryLower = searchQuery;
for (char& c : queryLower) c = tolower(c); std::transform(queryLower.begin(), queryLower.end(), queryLower.begin(),
[](unsigned char c) { return std::tolower(c); });
for (const auto& book : allBooks) { for (const auto& book : allBooks) {
// Convert title, author, and path to lowercase // Convert title, author, and path to lowercase
std::string titleLower = book.title; std::string titleLower = book.title;
std::string authorLower = book.author; std::string authorLower = book.author;
std::string pathLower = book.path; std::string pathLower = book.path;
for (char& c : titleLower) c = tolower(c); std::transform(titleLower.begin(), titleLower.end(), titleLower.begin(),
for (char& c : authorLower) c = tolower(c); [](unsigned char c) { return std::tolower(c); });
for (char& c : pathLower) c = tolower(c); std::transform(authorLower.begin(), authorLower.end(), authorLower.begin(),
[](unsigned char c) { return std::tolower(c); });
std::transform(pathLower.begin(), pathLower.end(), pathLower.begin(),
[](unsigned char c) { return std::tolower(c); });
int score = 0; int score = 0;
@ -575,6 +576,7 @@ void MyLibraryActivity::executeListAction() {
updateRequired = true; updateRequired = true;
} }
// cppcheck-suppress checkLevelNormal
void MyLibraryActivity::loop() { void MyLibraryActivity::loop() {
// Handle action menu state // Handle action menu state
if (uiState == UIState::ActionMenu) { if (uiState == UIState::ActionMenu) {
@ -1372,7 +1374,6 @@ void MyLibraryActivity::renderRecentTab() const {
const auto pageWidth = renderer.getScreenWidth(); const auto pageWidth = renderer.getScreenWidth();
const int pageItems = getPageItems(); const int pageItems = getPageItems();
const int bookCount = static_cast<int>(recentBooks.size()); const int bookCount = static_cast<int>(recentBooks.size());
const int totalItems = bookCount + 1; // +1 for "Search..." shortcut
// Calculate bezel-adjusted margins // Calculate bezel-adjusted margins
const int bezelTop = renderer.getBezelOffsetTop(); const int bezelTop = renderer.getBezelOffsetTop();
@ -1558,7 +1559,6 @@ void MyLibraryActivity::renderListsTab() const {
const auto pageWidth = renderer.getScreenWidth(); const auto pageWidth = renderer.getScreenWidth();
const int pageItems = getPageItems(); const int pageItems = getPageItems();
const int listCount = static_cast<int>(lists.size()); const int listCount = static_cast<int>(lists.size());
const int totalItems = listCount + 1; // +1 for "Search..." shortcut
// Calculate bezel-adjusted margins // Calculate bezel-adjusted margins
const int bezelTop = renderer.getBezelOffsetTop(); const int bezelTop = renderer.getBezelOffsetTop();
@ -1610,7 +1610,6 @@ void MyLibraryActivity::renderFilesTab() const {
const auto pageWidth = renderer.getScreenWidth(); const auto pageWidth = renderer.getScreenWidth();
const int pageItems = getPageItems(); const int pageItems = getPageItems();
const int fileCount = static_cast<int>(files.size()); const int fileCount = static_cast<int>(files.size());
const int totalItems = fileCount + 1; // +1 for "Search..." shortcut
// Calculate bezel-adjusted margins // Calculate bezel-adjusted margins
const int bezelTop = renderer.getBezelOffsetTop(); const int bezelTop = renderer.getBezelOffsetTop();
@ -1838,7 +1837,6 @@ void MyLibraryActivity::renderBookmarksTab() const {
const auto pageWidth = renderer.getScreenWidth(); const auto pageWidth = renderer.getScreenWidth();
const int pageItems = getPageItems(); const int pageItems = getPageItems();
const int bookCount = static_cast<int>(bookmarkedBooks.size()); const int bookCount = static_cast<int>(bookmarkedBooks.size());
const int totalItems = bookCount + 1; // +1 for "Search..." shortcut
// Calculate bezel-adjusted margins // Calculate bezel-adjusted margins
const int bezelTop = renderer.getBezelOffsetTop(); const int bezelTop = renderer.getBezelOffsetTop();
@ -2043,7 +2041,6 @@ void MyLibraryActivity::renderCharacterPicker(int y) const {
// Determine scroll offset to keep selected character visible // Determine scroll offset to keep selected character visible
int scrollOffset = 0; int scrollOffset = 0;
int selectedX = 0;
int currentX = 0; int currentX = 0;
// Calculate position of selected item // Calculate position of selected item
@ -2061,9 +2058,8 @@ void MyLibraryActivity::renderCharacterPicker(int y) const {
} }
if (i == searchCharIndex) { if (i == searchCharIndex) {
selectedX = currentX;
// Center the selected item in the visible area // Center the selected item in the visible area
scrollOffset = selectedX - availableWidth / 2 + itemWidth / 2; scrollOffset = currentX - availableWidth / 2 + itemWidth / 2;
if (scrollOffset < 0) scrollOffset = 0; if (scrollOffset < 0) scrollOffset = 0;
if (scrollOffset > totalWidth - availableWidth) { if (scrollOffset > totalWidth - availableWidth) {
scrollOffset = std::max(0, totalWidth - availableWidth); scrollOffset = std::max(0, totalWidth - availableWidth);

View File

@ -640,7 +640,8 @@ void CrossPointWebServerActivity::renderWebBrowserScreen() const {
std::string ssidInfo = "Network: " + connectedSSID; std::string ssidInfo = "Network: " + connectedSSID;
if (ssidInfo.length() > 35) { if (ssidInfo.length() > 35) {
ssidInfo = ssidInfo.substr(0, 32) + "..."; ssidInfo.resize(32);
ssidInfo += "...";
} }
renderer.drawText(NOTOSANS_12_FONT_ID, TEXT_X, textY, ssidInfo.c_str()); renderer.drawText(NOTOSANS_12_FONT_ID, TEXT_X, textY, ssidInfo.c_str());
textY += LINE_SPACING; textY += LINE_SPACING;
@ -679,7 +680,8 @@ void CrossPointWebServerActivity::renderCompanionAppScreen() const {
// Show network info // Show network info
std::string ssidInfo = "Network: " + connectedSSID; std::string ssidInfo = "Network: " + connectedSSID;
if (ssidInfo.length() > 35) { if (ssidInfo.length() > 35) {
ssidInfo = ssidInfo.substr(0, 32) + "..."; ssidInfo.resize(32);
ssidInfo += "...";
} }
renderer.drawText(NOTOSANS_12_FONT_ID, TEXT_X, textY, ssidInfo.c_str()); renderer.drawText(NOTOSANS_12_FONT_ID, TEXT_X, textY, ssidInfo.c_str());
textY += LINE_SPACING; textY += LINE_SPACING;
@ -728,7 +730,8 @@ void CrossPointWebServerActivity::renderCompanionAppLibraryScreen() const {
// Show network info // Show network info
std::string ssidInfo = "Network: " + connectedSSID; std::string ssidInfo = "Network: " + connectedSSID;
if (ssidInfo.length() > 35) { if (ssidInfo.length() > 35) {
ssidInfo = ssidInfo.substr(0, 32) + "..."; ssidInfo.resize(32);
ssidInfo += "...";
} }
renderer.drawText(NOTOSANS_12_FONT_ID, TEXT_X, textY, ssidInfo.c_str()); renderer.drawText(NOTOSANS_12_FONT_ID, TEXT_X, textY, ssidInfo.c_str());
textY += LINE_SPACING; textY += LINE_SPACING;

View File

@ -386,9 +386,7 @@ void EpubReaderActivity::loop() {
[this](QuickMenuAction action) { [this](QuickMenuAction action) {
// Cache values before exitActivity // Cache values before exitActivity
EpubReaderActivity* self = this; EpubReaderActivity* self = this;
GfxRenderer& cachedRenderer = renderer; const Section* cachedSection = section.get();
MappedInputManager& cachedMappedInput = mappedInput;
Section* cachedSection = section.get();
SemaphoreHandle_t cachedMutex = renderingMutex; SemaphoreHandle_t cachedMutex = renderingMutex;
exitActivity(); exitActivity();
@ -938,7 +936,8 @@ void EpubReaderActivity::renderEndOfBookPrompt() {
// Book title (truncated if needed) // Book title (truncated if needed)
std::string bookTitle = epub->getTitle(); std::string bookTitle = epub->getTitle();
if (bookTitle.length() > 30) { if (bookTitle.length() > 30) {
bookTitle = bookTitle.substr(0, 27) + "..."; bookTitle.resize(27);
bookTitle += "...";
} }
renderer.drawCenteredText(UI_10_FONT_ID, 120, bookTitle.c_str()); renderer.drawCenteredText(UI_10_FONT_ID, 120, bookTitle.c_str());

View File

@ -10,7 +10,12 @@ namespace {
constexpr int SKIP_PAGE_MS = 700; constexpr int SKIP_PAGE_MS = 700;
} // namespace } // namespace
bool EpubReaderChapterSelectionActivity::hasSyncOption() const { return false; } // Sync feature is currently disabled - will be enabled when implemented
// NOLINTNEXTLINE(readability-convert-member-functions-to-static)
bool EpubReaderChapterSelectionActivity::hasSyncOption() const {
// TODO: Return true when sync credentials are configured
return false;
}
int EpubReaderChapterSelectionActivity::getTotalItems() const { int EpubReaderChapterSelectionActivity::getTotalItems() const {
// Add 2 for sync options (top and bottom) if credentials are configured // Add 2 for sync options (top and bottom) if credentials are configured
@ -18,12 +23,6 @@ int EpubReaderChapterSelectionActivity::getTotalItems() const {
return epub->getTocItemsCount() + syncCount; return epub->getTocItemsCount() + syncCount;
} }
bool EpubReaderChapterSelectionActivity::isSyncItem(int index) const {
if (!hasSyncOption()) return false;
// First item and last item are sync options
return index == 0 || index == getTotalItems() - 1;
}
int EpubReaderChapterSelectionActivity::tocIndexFromItemIndex(int itemIndex) const { int EpubReaderChapterSelectionActivity::tocIndexFromItemIndex(int itemIndex) const {
// Account for the sync option at the top // Account for the sync option at the top
const int offset = hasSyncOption() ? 1 : 0; const int offset = hasSyncOption() ? 1 : 0;
@ -94,10 +93,6 @@ void EpubReaderChapterSelectionActivity::onExit() {
renderingMutex = nullptr; renderingMutex = nullptr;
} }
void EpubReaderChapterSelectionActivity::launchSyncActivity() {
// KOReader sync functionality removed
}
void EpubReaderChapterSelectionActivity::loop() { void EpubReaderChapterSelectionActivity::loop() {
if (subActivity) { if (subActivity) {
subActivity->loop(); subActivity->loop();
@ -114,13 +109,7 @@ void EpubReaderChapterSelectionActivity::loop() {
const int totalItems = getTotalItems(); const int totalItems = getTotalItems();
if (mappedInput.wasReleased(MappedInputManager::Button::Confirm)) { if (mappedInput.wasReleased(MappedInputManager::Button::Confirm)) {
// Check if sync option is selected (first or last item) // Get TOC index (account for top sync offset if enabled)
if (isSyncItem(selectorIndex)) {
launchSyncActivity();
return;
}
// Get TOC index (account for top sync offset)
const int tocIndex = tocIndexFromItemIndex(selectorIndex); const int tocIndex = tocIndexFromItemIndex(selectorIndex);
const auto newSpineIndex = epub->getSpineIndexForTocIndex(tocIndex); const auto newSpineIndex = epub->getSpineIndexForTocIndex(tocIndex);
if (newSpineIndex == -1) { if (newSpineIndex == -1) {
@ -182,19 +171,13 @@ void EpubReaderChapterSelectionActivity::renderScreen() {
const int displayY = 60 + bezelTop + (itemIndex % pageItems) * 30; const int displayY = 60 + bezelTop + (itemIndex % pageItems) * 30;
const bool isSelected = (itemIndex == selectorIndex); const bool isSelected = (itemIndex == selectorIndex);
if (isSyncItem(itemIndex)) { // Draw TOC item
// Draw sync option (at top or bottom) const int tocIndex = tocIndexFromItemIndex(itemIndex);
renderer.drawText(UI_10_FONT_ID, 20 + bezelLeft, displayY, ">> Sync Progress", !isSelected); auto item = epub->getTocItem(tocIndex);
} else { const int indentSize = 20 + bezelLeft + (item.level - 1) * 15;
// Draw TOC item (account for top sync offset) const std::string chapterName =
const int tocIndex = tocIndexFromItemIndex(itemIndex); renderer.truncatedText(UI_10_FONT_ID, item.title.c_str(), pageWidth - 40 - bezelLeft - bezelRight - indentSize + 20 + bezelLeft);
auto item = epub->getTocItem(tocIndex); renderer.drawText(UI_10_FONT_ID, indentSize, displayY, chapterName.c_str(), !isSelected);
const int indentSize = 20 + bezelLeft + (item.level - 1) * 15;
const std::string chapterName =
renderer.truncatedText(UI_10_FONT_ID, item.title.c_str(), pageWidth - 40 - bezelLeft - bezelRight - indentSize + 20 + bezelLeft);
renderer.drawText(UI_10_FONT_ID, indentSize, 60 + bezelTop + (tocIndex % pageItems) * 30, chapterName.c_str(),
tocIndex != selectorIndex);
}
} }
const auto labels = mappedInput.mapLabels("« Back", "Select", "Up", "Down"); const auto labels = mappedInput.mapLabels("« Back", "Select", "Up", "Down");

View File

@ -30,18 +30,15 @@ class EpubReaderChapterSelectionActivity final : public ActivityWithSubactivity
int getTotalItems() const; int getTotalItems() const;
// Check if sync option is available (credentials configured) // Check if sync option is available (credentials configured)
// Note: Currently always returns false - placeholder for future sync feature
bool hasSyncOption() const; bool hasSyncOption() const;
// Check if given item index is a sync option (first or last)
bool isSyncItem(int index) const;
// Convert item index to TOC index (accounting for top sync option offset) // Convert item index to TOC index (accounting for top sync option offset)
int tocIndexFromItemIndex(int itemIndex) const; int tocIndexFromItemIndex(int itemIndex) const;
static void taskTrampoline(void* param); static void taskTrampoline(void* param);
[[noreturn]] void displayTaskLoop(); [[noreturn]] void displayTaskLoop();
void renderScreen(); void renderScreen();
void launchSyncActivity();
public: public:
explicit EpubReaderChapterSelectionActivity(GfxRenderer& renderer, MappedInputManager& mappedInput, explicit EpubReaderChapterSelectionActivity(GfxRenderer& renderer, MappedInputManager& mappedInput,

View File

@ -88,7 +88,7 @@ void TxtReaderActivity::onEnter() {
renderer.displayBuffer(EInkDisplay::FAST_REFRESH); renderer.displayBuffer(EInkDisplay::FAST_REFRESH);
// Generate covers with progress callback // Generate covers with progress callback
txt->generateAllCovers([&](int percent) { (void)txt->generateAllCovers([&](int percent) {
const unsigned long now = millis(); const unsigned long now = millis();
if ((now - lastUpdate) >= 3000) { if ((now - lastUpdate) >= 3000) {
lastUpdate = now; lastUpdate = now;
@ -888,7 +888,8 @@ void TxtReaderActivity::renderEndOfBookPrompt() {
filename = filename.substr(lastSlash + 1); filename = filename.substr(lastSlash + 1);
} }
if (filename.length() > 30) { if (filename.length() > 30) {
filename = filename.substr(0, 27) + "..."; filename.resize(27);
filename += "...";
} }
renderer.drawCenteredText(UI_10_FONT_ID, 120, filename.c_str()); renderer.drawCenteredText(UI_10_FONT_ID, 120, filename.c_str());

View File

@ -200,35 +200,27 @@ void checkForFlashCommand() {
constexpr int halfWidth = LOCK_ICON_WIDTH / 2; // 16px offset for centering constexpr int halfWidth = LOCK_ICON_WIDTH / 2; // 16px offset for centering
int iconX, iconY; int iconX, iconY;
GfxRenderer::ImageRotation rotation; GfxRenderer::ImageRotation rotation;
int outW, outH; // Note: 90/270 rotation swaps output dimensions // Note: 90/270 rotation swaps output dimensions (W<->H)
switch (renderer.getOrientation()) { switch (renderer.getOrientation()) {
case GfxRenderer::Portrait: // USB at bottom-left, shackle points right case GfxRenderer::Portrait: // USB at bottom-left, shackle points right
rotation = GfxRenderer::ROTATE_90; rotation = GfxRenderer::ROTATE_90;
outW = LOCK_ICON_HEIGHT;
outH = LOCK_ICON_WIDTH;
iconX = edgeMargin; iconX = edgeMargin;
iconY = screenH - outH - edgeMargin - halfWidth; iconY = screenH - LOCK_ICON_WIDTH - edgeMargin - halfWidth;
break; break;
case GfxRenderer::PortraitInverted: // USB at top-right, shackle points left case GfxRenderer::PortraitInverted: // USB at top-right, shackle points left
rotation = GfxRenderer::ROTATE_270; rotation = GfxRenderer::ROTATE_270;
outW = LOCK_ICON_HEIGHT; iconX = screenW - LOCK_ICON_HEIGHT - edgeMargin;
outH = LOCK_ICON_WIDTH;
iconX = screenW - outW - edgeMargin;
iconY = edgeMargin + halfWidth; iconY = edgeMargin + halfWidth;
break; break;
case GfxRenderer::LandscapeClockwise: // USB at top-left, shackle points down case GfxRenderer::LandscapeClockwise: // USB at top-left, shackle points down
rotation = GfxRenderer::ROTATE_180; rotation = GfxRenderer::ROTATE_180;
outW = LOCK_ICON_WIDTH;
outH = LOCK_ICON_HEIGHT;
iconX = edgeMargin + halfWidth; iconX = edgeMargin + halfWidth;
iconY = edgeMargin; iconY = edgeMargin;
break; break;
case GfxRenderer::LandscapeCounterClockwise: // USB at bottom-right, shackle points up case GfxRenderer::LandscapeCounterClockwise: // USB at bottom-right, shackle points up
rotation = GfxRenderer::ROTATE_0; rotation = GfxRenderer::ROTATE_0;
outW = LOCK_ICON_WIDTH; iconX = screenW - LOCK_ICON_WIDTH - edgeMargin - halfWidth;
outH = LOCK_ICON_HEIGHT; iconY = screenH - LOCK_ICON_HEIGHT - edgeMargin;
iconX = screenW - outW - edgeMargin - halfWidth;
iconY = screenH - outH - edgeMargin;
break; break;
} }
renderer.drawImageRotated(LockIcon, iconX, iconY, LOCK_ICON_WIDTH, LOCK_ICON_HEIGHT, rotation); renderer.drawImageRotated(LockIcon, iconX, iconY, LOCK_ICON_WIDTH, LOCK_ICON_HEIGHT, rotation);