2025-12-03 22:00:29 +11:00
|
|
|
#pragma once
|
|
|
|
|
|
2025-12-30 15:09:30 +10:00
|
|
|
#include <Print.h>
|
|
|
|
|
|
2025-12-24 22:36:13 +11:00
|
|
|
#include <memory>
|
2025-12-03 22:00:29 +11:00
|
|
|
#include <string>
|
|
|
|
|
#include <unordered_map>
|
|
|
|
|
#include <vector>
|
|
|
|
|
|
2025-12-24 22:36:13 +11:00
|
|
|
#include "Epub/BookMetadataCache.h"
|
2025-12-03 22:00:29 +11:00
|
|
|
|
2025-12-13 19:36:01 +11:00
|
|
|
class ZipFile;
|
2025-12-03 22:00:29 +11:00
|
|
|
|
|
|
|
|
class Epub {
|
2026-01-03 16:10:35 +08:00
|
|
|
// the ncx file (EPUB 2)
|
2025-12-03 22:00:29 +11:00
|
|
|
std::string tocNcxItem;
|
2026-01-03 16:10:35 +08:00
|
|
|
// the nav file (EPUB 3)
|
|
|
|
|
std::string tocNavItem;
|
2025-12-03 22:00:29 +11:00
|
|
|
// where is the EPUBfile?
|
|
|
|
|
std::string filepath;
|
|
|
|
|
// the base path for items in the EPUB file
|
|
|
|
|
std::string contentBasePath;
|
|
|
|
|
// Uniq cache key based on filepath
|
|
|
|
|
std::string cachePath;
|
2025-12-24 22:36:13 +11:00
|
|
|
// Spine and TOC cache
|
|
|
|
|
std::unique_ptr<BookMetadataCache> bookMetadataCache;
|
2025-12-03 22:00:29 +11:00
|
|
|
|
2025-12-13 19:36:01 +11:00
|
|
|
bool findContentOpfFile(std::string* contentOpfFile) const;
|
2025-12-24 22:36:13 +11:00
|
|
|
bool parseContentOpf(BookMetadataCache::BookMetadata& bookMetadata);
|
|
|
|
|
bool parseTocNcxFile() const;
|
2026-01-03 16:10:35 +08:00
|
|
|
bool parseTocNavFile() const;
|
2025-12-03 22:00:29 +11:00
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
explicit Epub(std::string filepath, const std::string& cacheDir) : filepath(std::move(filepath)) {
|
|
|
|
|
// create a cache key based on the filepath
|
|
|
|
|
cachePath = cacheDir + "/epub_" + std::to_string(std::hash<std::string>{}(this->filepath));
|
|
|
|
|
}
|
|
|
|
|
~Epub() = default;
|
|
|
|
|
std::string& getBasePath() { return contentBasePath; }
|
2025-12-30 22:18:10 +10:00
|
|
|
bool load(bool buildIfMissing = true);
|
2025-12-12 22:13:34 +11:00
|
|
|
bool clearCache() const;
|
2025-12-03 22:00:29 +11:00
|
|
|
void setupCacheDir() const;
|
|
|
|
|
const std::string& getCachePath() const;
|
|
|
|
|
const std::string& getPath() const;
|
|
|
|
|
const std::string& getTitle() const;
|
2025-12-30 21:15:44 +10:00
|
|
|
const std::string& getAuthor() const;
|
2026-01-12 10:55:47 +01:00
|
|
|
std::string getCoverBmpPath(bool cropped = false) const;
|
|
|
|
|
bool generateCoverBmp(bool cropped = false) const;
|
Add cover image display in *Continue Reading* card with framebuffer caching (#200)
## Summary
* **What is the goal of this PR?** (e.g., Fixes a bug in the user
authentication module,
Display the book cover image in the **"Continue Reading"** card on the
home screen, with fast navigation using framebuffer caching.
* **What changes are included?**
- Display book cover image in the "Continue Reading" card on home screen
- Load cover from cached BMP (same as sleep screen cover)
- Add framebuffer store/restore functions (`copyStoredBwBuffer`,
`freeStoredBwBuffer`) for fast navigation after initial render
- Fix `drawBitmap` scaling bug: apply scale to offset only, not to base
coordinates
- Add white text boxes behind title/author/continue reading label for
readability on cover
- Support both EPUB and XTC file cover images
- Increase HomeActivity task stack size from 2048 to 4096 for cover
image rendering
## Additional Context
* Add any other information that might be helpful for the reviewer
(e.g., performance implications, potential risks, specific areas to
focus on).
- Performance: First render loads cover from SD card (~800ms),
subsequent navigation uses cached framebuffer (~instant)
- Memory: Framebuffer cache uses ~48KB (6 chunks × 8KB) while on home
screen, freed on exit
- Fallback: If cover image is not available, falls back to standard
text-only display
- The `drawBitmap` fix corrects a bug where screenY = (y + offset) scale
was incorrectly scaling the base coordinates. Now correctly uses screenY
= y + (offset scale)
2026-01-14 19:24:02 +09:00
|
|
|
std::string getThumbBmpPath() const;
|
|
|
|
|
bool generateThumbBmp() const;
|
2025-12-08 00:39:17 +11:00
|
|
|
uint8_t* readItemContentsToBytes(const std::string& itemHref, size_t* size = nullptr,
|
|
|
|
|
bool trailingNullByte = false) const;
|
|
|
|
|
bool readItemContentsToStream(const std::string& itemHref, Print& out, size_t chunkSize) const;
|
2025-12-13 19:36:01 +11:00
|
|
|
bool getItemSize(const std::string& itemHref, size_t* size) const;
|
2025-12-24 22:36:13 +11:00
|
|
|
BookMetadataCache::SpineEntry getSpineItem(int spineIndex) const;
|
|
|
|
|
BookMetadataCache::TocEntry getTocItem(int tocIndex) const;
|
2025-12-03 22:00:29 +11:00
|
|
|
int getSpineItemsCount() const;
|
|
|
|
|
int getTocItemsCount() const;
|
|
|
|
|
int getSpineIndexForTocIndex(int tocIndex) const;
|
|
|
|
|
int getTocIndexForSpineIndex(int spineIndex) const;
|
2025-12-24 22:36:13 +11:00
|
|
|
size_t getCumulativeSpineItemSize(int spineIndex) const;
|
2025-12-30 13:02:46 +01:00
|
|
|
int getSpineIndexForTextReference() const;
|
2025-12-17 13:05:24 +01:00
|
|
|
|
|
|
|
|
size_t getBookSize() const;
|
2025-12-29 20:17:29 +10:00
|
|
|
uint8_t calculateProgress(int currentSpineIndex, float currentSpineRead) const;
|
2025-12-03 22:00:29 +11:00
|
|
|
};
|