Refactor pendig thumbnails

This commit is contained in:
jpirnay
2026-05-18 16:42:38 +02:00
parent 3ac6752241
commit a3cef380a7
3 changed files with 58 additions and 12 deletions
@@ -377,6 +377,7 @@ void RecentBooksActivity::renderGridCell(int index, bool selected, int cellX, in
if (!book.coverBmpPath.empty()) { if (!book.coverBmpPath.empty()) {
const std::string thumbPath = gridThumbPath(book.coverBmpPath, tw, th); const std::string thumbPath = gridThumbPath(book.coverBmpPath, tw, th);
FsFile file; FsFile file;
bool thumbDrawn = false;
if (Storage.openFileForRead("RBA", thumbPath, file)) { if (Storage.openFileForRead("RBA", thumbPath, file)) {
Bitmap bmp(file); Bitmap bmp(file);
if (bmp.parseHeaders() == BmpReaderError::Ok) { if (bmp.parseHeaders() == BmpReaderError::Ok) {
@@ -399,10 +400,19 @@ void RecentBooksActivity::renderGridCell(int index, bool selected, int cellX, in
// shows through in the surrounding space. // shows through in the surrounding space.
renderer.fillRect(cellX + offsetX, cellY + offsetY, rendW, rendH, false); renderer.fillRect(cellX + offsetX, cellY + offsetY, rendW, rendH, false);
renderer.drawBitmap1Bit(bmp, cellX + offsetX, cellY + offsetY, rendW, rendH); renderer.drawBitmap1Bit(bmp, cellX + offsetX, cellY + offsetY, rendW, rendH);
thumbDrawn = true;
} }
} }
file.close(); file.close();
} }
if (!thumbDrawn) {
// Thumbnail not yet generated — clear interior and show loading label
renderer.fillRect(cellX + 1, cellY + 1, tw - 2, th - 2, false);
const char* loadingText = tr(STR_LOADING);
const int textW = renderer.getTextWidth(SMALL_FONT_ID, loadingText);
const int textH = renderer.getLineHeight(SMALL_FONT_ID);
renderer.drawText(SMALL_FONT_ID, cellX + (tw - textW) / 2, cellY + (th - textH) / 2, loadingText, true);
}
} else { } else {
// No cover — clear the whole interior so the placeholder looks clean. // No cover — clear the whole interior so the placeholder looks clean.
renderer.fillRect(cellX + 1, cellY + 1, tw - 2, th - 2, false); renderer.fillRect(cellX + 1, cellY + 1, tw - 2, th - 2, false);
@@ -2,6 +2,7 @@
#include <GfxRenderer.h> #include <GfxRenderer.h>
#include <HalStorage.h> #include <HalStorage.h>
#include <I18n.h>
#include <cstdint> #include <cstdint>
#include <string> #include <string>
@@ -32,10 +33,12 @@ void Lyra3CoversTheme::drawRecentBookCover(GfxRenderer& renderer, Rect rect, con
// Only load from SD on first render, then use stored buffer // Only load from SD on first render, then use stored buffer
if (hasContinueReading) { if (hasContinueReading) {
if (!coverRendered) { if (!coverRendered) {
bool anyPending = false;
for (int i = 0; for (int i = 0;
i < std::min(static_cast<int>(recentBooks.size()), Lyra3CoversMetrics::values.homeRecentBooksCount); i++) { i < std::min(static_cast<int>(recentBooks.size()), Lyra3CoversMetrics::values.homeRecentBooksCount); i++) {
std::string coverPath = recentBooks[i].coverBmpPath; std::string coverPath = recentBooks[i].coverBmpPath;
bool hasCover = true; bool hasCover = true;
bool tilePending = false;
int tileX = Lyra3CoversMetrics::values.contentSidePadding + tileWidth * i; int tileX = Lyra3CoversMetrics::values.contentSidePadding + tileWidth * i;
if (coverPath.empty()) { if (coverPath.empty()) {
hasCover = false; hasCover = false;
@@ -62,6 +65,8 @@ void Lyra3CoversTheme::drawRecentBookCover(GfxRenderer& renderer, Rect rect, con
file.close(); file.close();
} else { } else {
hasCover = false; hasCover = false;
tilePending = true; // path exists but BMP not ready yet
anyPending = true;
} }
} }
// Draw either way // Draw either way
@@ -69,15 +74,29 @@ void Lyra3CoversTheme::drawRecentBookCover(GfxRenderer& renderer, Rect rect, con
coverHeight, true); coverHeight, true);
if (!hasCover) { if (!hasCover) {
// Render empty cover if (tilePending) {
renderer.fillRect(tileX + hPaddingInSelection, tileY + hPaddingInSelection + (coverHeight / 3), // Cover is being generated — show a loading label centred in the tile
tileWidth - 2 * hPaddingInSelection, 2 * coverHeight / 3, true); const char* loadingText = tr(STR_LOADING);
renderer.drawIcon(CoverIcon, tileX + hPaddingInSelection + 24, tileY + hPaddingInSelection + 24, 32, 32); const int textW = renderer.getTextWidth(SMALL_FONT_ID, loadingText);
const int textH = renderer.getLineHeight(SMALL_FONT_ID);
renderer.drawText(SMALL_FONT_ID,
tileX + hPaddingInSelection + (tileWidth - 2 * hPaddingInSelection - textW) / 2,
tileY + hPaddingInSelection + (coverHeight - textH) / 2, loadingText, true);
} else {
// No cover at all — render empty cover placeholder
renderer.fillRect(tileX + hPaddingInSelection, tileY + hPaddingInSelection + (coverHeight / 3),
tileWidth - 2 * hPaddingInSelection, 2 * coverHeight / 3, true);
renderer.drawIcon(CoverIcon, tileX + hPaddingInSelection + 24, tileY + hPaddingInSelection + 24, 32, 32);
}
} }
} }
coverBufferStored = storeCoverBuffer(); // Only cache the frame buffer once all tiles are definitively resolved.
coverRendered = coverBufferStored; // Only consider it rendered if we successfully stored the buffer // If any cover is still being generated we keep coverRendered=false so the next render will retry.
if (!anyPending) {
coverBufferStored = storeCoverBuffer();
coverRendered = coverBufferStored;
}
} }
for (int i = 0; i < std::min(static_cast<int>(recentBooks.size()), Lyra3CoversMetrics::values.homeRecentBooksCount); for (int i = 0; i < std::min(static_cast<int>(recentBooks.size()), Lyra3CoversMetrics::values.homeRecentBooksCount);
+23 -6
View File
@@ -554,6 +554,7 @@ void LyraTheme::drawRecentBookCover(GfxRenderer& renderer, Rect rect, const std:
if (!coverRendered) { if (!coverRendered) {
std::string coverPath = book.coverBmpPath; std::string coverPath = book.coverBmpPath;
bool hasCover = true; bool hasCover = true;
bool coverPending = false;
int tileX = LyraMetrics::values.contentSidePadding; int tileX = LyraMetrics::values.contentSidePadding;
if (coverPath.empty()) { if (coverPath.empty()) {
hasCover = false; hasCover = false;
@@ -572,6 +573,9 @@ void LyraTheme::drawRecentBookCover(GfxRenderer& renderer, Rect rect, const std:
hasCover = false; hasCover = false;
} }
file.close(); file.close();
} else {
hasCover = false;
coverPending = true; // path exists but BMP not ready yet
} }
} }
@@ -579,14 +583,27 @@ void LyraTheme::drawRecentBookCover(GfxRenderer& renderer, Rect rect, const std:
renderer.drawRect(tileX + hPaddingInSelection, tileY + hPaddingInSelection, coverWidth, coverHeight, true); renderer.drawRect(tileX + hPaddingInSelection, tileY + hPaddingInSelection, coverWidth, coverHeight, true);
if (!hasCover) { if (!hasCover) {
// Render empty cover if (coverPending) {
renderer.fillRect(tileX + hPaddingInSelection, tileY + hPaddingInSelection + (coverHeight / 3), coverWidth, // Cover is being generated — show a loading label centred in the cover area
2 * coverHeight / 3, true); const char* loadingText = tr(STR_LOADING);
renderer.drawIcon(CoverIcon, tileX + hPaddingInSelection + 24, tileY + hPaddingInSelection + 24, 32, 32); const int textW = renderer.getTextWidth(SMALL_FONT_ID, loadingText);
const int textH = renderer.getLineHeight(SMALL_FONT_ID);
renderer.drawText(SMALL_FONT_ID, tileX + hPaddingInSelection + (coverWidth - textW) / 2,
tileY + hPaddingInSelection + (coverHeight - textH) / 2, loadingText, true);
} else {
// No cover at all — render empty cover placeholder
renderer.fillRect(tileX + hPaddingInSelection, tileY + hPaddingInSelection + (coverHeight / 3), coverWidth,
2 * coverHeight / 3, true);
renderer.drawIcon(CoverIcon, tileX + hPaddingInSelection + 24, tileY + hPaddingInSelection + 24, 32, 32);
}
} }
coverBufferStored = storeCoverBuffer(); // Only cache the frame buffer once the cover is definitively resolved (loaded or confirmed absent).
coverRendered = coverBufferStored; // Only consider it rendered if we successfully stored the buffer // If a cover is still being generated we keep coverRendered=false so the next render will retry.
if (!coverPending) {
coverBufferStored = storeCoverBuffer();
coverRendered = coverBufferStored;
}
} }
bool bookSelected = (selectorIndex == 0); bool bookSelected = (selectorIndex == 0);