Something went wrong. Try again.
A fork of https://github.com/crosspoint-reader/crosspoint-reader
Something went wrong. Try again.
5.7 kB · 120 lines
C++
at master
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121#include "Lyra3CoversTheme.h"
#include <GfxRenderer.h>#include <HalStorage.h>
#include <cstdint>#include <string>#include <vector>
#include "RecentBooksStore.h"#include "components/UITheme.h"#include "components/icons/cover.h"#include "fontIds.h"
// Internal constantsnamespace {constexpr int hPaddingInSelection = 8;constexpr int cornerRadius = 6;} // namespace
void Lyra3CoversTheme::drawRecentBookCover(GfxRenderer& renderer, Rect rect, const std::vector<RecentBook>& recentBooks, const int selectorIndex, bool& coverRendered, bool& coverBufferStored, bool& bufferRestored, std::function<bool()> storeCoverBuffer) const { const int tileWidth = (rect.width - 2 * Lyra3CoversMetrics::values.contentSidePadding) / 3; const int tileY = rect.y; const bool hasContinueReading = !recentBooks.empty();
// Draw book card regardless, fill with message based on `hasContinueReading` // Draw cover image as background if available (inside the box) // Only load from SD on first render, then use stored buffer if (hasContinueReading) { if (!coverRendered) { for (int i = 0; i < std::min(static_cast<int>(recentBooks.size()), Lyra3CoversMetrics::values.homeRecentBooksCount); i++) { std::string coverPath = recentBooks[i].coverBmpPath; bool hasCover = true; int tileX = Lyra3CoversMetrics::values.contentSidePadding + tileWidth * i; if (coverPath.empty()) { hasCover = false; } else { const std::string coverBmpPath = UITheme::getCoverThumbPath(coverPath, Lyra3CoversMetrics::values.homeCoverHeight);
// First time: load cover from SD and render FsFile file; if (Storage.openFileForRead("HOME", coverBmpPath, file)) { Bitmap bitmap(file); if (bitmap.parseHeaders() == BmpReaderError::Ok) { float coverHeight = static_cast<float>(bitmap.getHeight()); float coverWidth = static_cast<float>(bitmap.getWidth()); float ratio = coverWidth / coverHeight; const float tileRatio = static_cast<float>(tileWidth - 2 * hPaddingInSelection) / static_cast<float>(Lyra3CoversMetrics::values.homeCoverHeight); float cropX = 1.0f - (tileRatio / ratio);
renderer.drawBitmap(bitmap, tileX + hPaddingInSelection, tileY + hPaddingInSelection, tileWidth - 2 * hPaddingInSelection, Lyra3CoversMetrics::values.homeCoverHeight, cropX); } else { hasCover = false; } file.close(); } } // Draw either way renderer.drawRect(tileX + hPaddingInSelection, tileY + hPaddingInSelection, tileWidth - 2 * hPaddingInSelection, Lyra3CoversMetrics::values.homeCoverHeight, true);
if (!hasCover) { // Render empty cover renderer.fillRect(tileX + hPaddingInSelection, tileY + hPaddingInSelection + (Lyra3CoversMetrics::values.homeCoverHeight / 3), tileWidth - 2 * hPaddingInSelection, 2 * Lyra3CoversMetrics::values.homeCoverHeight / 3, true); renderer.drawIcon(CoverIcon, tileX + hPaddingInSelection + 24, tileY + hPaddingInSelection + 24, 32, 32); } }
coverBufferStored = storeCoverBuffer(); coverRendered = coverBufferStored; // Only consider it rendered if we successfully stored the buffer }
for (int i = 0; i < std::min(static_cast<int>(recentBooks.size()), Lyra3CoversMetrics::values.homeRecentBooksCount); i++) { bool bookSelected = (selectorIndex == i);
int tileX = Lyra3CoversMetrics::values.contentSidePadding + tileWidth * i;
const int maxLineWidth = tileWidth - 2 * hPaddingInSelection;
auto titleLines = renderer.wrappedText(SMALL_FONT_ID, recentBooks[i].title.c_str(), maxLineWidth, 3);
const int titleLineHeight = renderer.getLineHeight(SMALL_FONT_ID); const int dynamicBlockHeight = static_cast<int>(titleLines.size()) * titleLineHeight; // Add a little padding below the text inside the selection box just like the top padding (5 + hPaddingSelection) const int dynamicTitleBoxHeight = dynamicBlockHeight + hPaddingInSelection + 5;
if (bookSelected) { // Draw selection box renderer.fillRoundedRect(tileX, tileY, tileWidth, hPaddingInSelection, cornerRadius, true, true, false, false, Color::LightGray); renderer.fillRectDither(tileX, tileY + hPaddingInSelection, hPaddingInSelection, Lyra3CoversMetrics::values.homeCoverHeight, Color::LightGray); renderer.fillRectDither(tileX + tileWidth - hPaddingInSelection, tileY + hPaddingInSelection, hPaddingInSelection, Lyra3CoversMetrics::values.homeCoverHeight, Color::LightGray); renderer.fillRoundedRect(tileX, tileY + Lyra3CoversMetrics::values.homeCoverHeight + hPaddingInSelection, tileWidth, dynamicTitleBoxHeight, cornerRadius, false, false, true, true, Color::LightGray); }
int currentY = tileY + Lyra3CoversMetrics::values.homeCoverHeight + hPaddingInSelection + 5; for (const auto& line : titleLines) { renderer.drawText(SMALL_FONT_ID, tileX + hPaddingInSelection, currentY, line.c_str(), true); currentY += titleLineHeight; } } } else { drawEmptyRecents(renderer, rect); }}