2025-12-28 23:56:05 +09:00
|
|
|
/**
|
|
|
|
|
* Xtc.h
|
|
|
|
|
*
|
|
|
|
|
* Main XTC ebook class for CrossPoint Reader
|
|
|
|
|
* Provides EPUB-like interface for XTC file handling
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
|
|
#include <memory>
|
|
|
|
|
#include <string>
|
2025-12-30 12:49:18 +11:00
|
|
|
#include <vector>
|
2025-12-28 23:56:05 +09:00
|
|
|
|
|
|
|
|
#include "Xtc/XtcParser.h"
|
|
|
|
|
#include "Xtc/XtcTypes.h"
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* XTC Ebook Handler
|
|
|
|
|
*
|
|
|
|
|
* Handles XTC file loading, page access, and cover image generation.
|
|
|
|
|
* Interface is designed to be similar to Epub class for easy integration.
|
|
|
|
|
*/
|
|
|
|
|
class Xtc {
|
|
|
|
|
std::string filepath;
|
|
|
|
|
std::string cachePath;
|
|
|
|
|
std::unique_ptr<xtc::XtcParser> parser;
|
|
|
|
|
bool loaded;
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
explicit Xtc(std::string filepath, const std::string& cacheDir) : filepath(std::move(filepath)), loaded(false) {
|
|
|
|
|
// Create cache key based on filepath (same as Epub)
|
|
|
|
|
cachePath = cacheDir + "/xtc_" + std::to_string(std::hash<std::string>{}(this->filepath));
|
|
|
|
|
}
|
|
|
|
|
~Xtc() = default;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Load XTC file
|
|
|
|
|
* @return true on success
|
|
|
|
|
*/
|
|
|
|
|
bool load();
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Clear cached data
|
|
|
|
|
* @return true on success
|
|
|
|
|
*/
|
|
|
|
|
bool clearCache() const;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Setup cache directory
|
|
|
|
|
*/
|
|
|
|
|
void setupCacheDir() const;
|
|
|
|
|
|
|
|
|
|
// Path accessors
|
|
|
|
|
const std::string& getCachePath() const { return cachePath; }
|
|
|
|
|
const std::string& getPath() const { return filepath; }
|
|
|
|
|
|
|
|
|
|
// Metadata
|
|
|
|
|
std::string getTitle() const;
|
2026-01-27 22:56:51 +11:00
|
|
|
std::string getAuthor() const;
|
2025-12-30 12:49:18 +11:00
|
|
|
bool hasChapters() const;
|
|
|
|
|
const std::vector<xtc::ChapterInfo>& getChapters() const;
|
2025-12-28 23:56:05 +09:00
|
|
|
|
|
|
|
|
// Cover image support (for sleep screen)
|
|
|
|
|
std::string getCoverBmpPath() const;
|
|
|
|
|
bool generateCoverBmp() 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
|
|
|
// Thumbnail support (for Continue Reading card)
|
|
|
|
|
std::string getThumbBmpPath() const;
|
|
|
|
|
bool generateThumbBmp() const;
|
2025-12-28 23:56:05 +09:00
|
|
|
|
|
|
|
|
// Page access
|
|
|
|
|
uint32_t getPageCount() const;
|
|
|
|
|
uint16_t getPageWidth() const;
|
|
|
|
|
uint16_t getPageHeight() const;
|
|
|
|
|
uint8_t getBitDepth() const; // 1 = XTC (1-bit), 2 = XTCH (2-bit)
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Load page bitmap data
|
|
|
|
|
* @param pageIndex Page index (0-based)
|
|
|
|
|
* @param buffer Output buffer
|
|
|
|
|
* @param bufferSize Buffer size
|
|
|
|
|
* @return Number of bytes read
|
|
|
|
|
*/
|
|
|
|
|
size_t loadPage(uint32_t pageIndex, uint8_t* buffer, size_t bufferSize) const;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Load page with streaming callback
|
|
|
|
|
* @param pageIndex Page index
|
|
|
|
|
* @param callback Callback for each chunk
|
|
|
|
|
* @param chunkSize Chunk size
|
|
|
|
|
* @return Error code
|
|
|
|
|
*/
|
|
|
|
|
xtc::XtcError loadPageStreaming(uint32_t pageIndex,
|
|
|
|
|
std::function<void(const uint8_t* data, size_t size, size_t offset)> callback,
|
|
|
|
|
size_t chunkSize = 1024) const;
|
|
|
|
|
|
|
|
|
|
// Progress calculation
|
|
|
|
|
uint8_t calculateProgress(uint32_t currentPage) const;
|
|
|
|
|
|
|
|
|
|
// Check if file is loaded
|
|
|
|
|
bool isLoaded() const { return loaded; }
|
|
|
|
|
|
|
|
|
|
// Error information
|
|
|
|
|
xtc::XtcError getLastError() const;
|
|
|
|
|
};
|