Files
Crosspoint/lib/Epub/Epub.h
T
Justin Mitchell 9d147cade9 Deduplicate identical CSS files in EPUB parsing & probe images for dimensions instead of reading the full file
Some EPUB converters emit byte-identical stylesheets per chapter (100+ entries). Now scan the ZIP central directory once to identify duplicates by CRC32 and compressed size, then skip parsing identical files. This avoids redundant ZIP lookups and SD extraction round-trips while preserving all styles since rules merge into a global set. Also add extractItemToFile helper and allowEarlyStop parameter to readItemContentsToStream.
2026-07-20 17:16:54 -04:00

81 lines
3.0 KiB
C++

#pragma once
#include <Print.h>
#include <memory>
#include <string>
#include <unordered_map>
#include <vector>
#include "Epub/BookMetadataCache.h"
#include "Epub/css/CssParser.h"
class ZipFile;
class Epub {
// the ncx file (EPUB 2)
std::string tocNcxItem;
// the nav file (EPUB 3)
std::string tocNavItem;
// 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;
// Spine and TOC cache
std::unique_ptr<BookMetadataCache> bookMetadataCache;
// CSS parser for styling
std::unique_ptr<CssParser> cssParser;
// CSS files
std::vector<std::string> cssFiles;
bool findContentOpfFile(std::string* contentOpfFile) const;
bool parseContentOpf(BookMetadataCache::BookMetadata& bookMetadata, bool writeSpineEntries = true);
bool parseTocNcxFile() const;
bool parseTocNavFile() const;
void discoverCssFilesFromZip();
void parseCssFiles() const;
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; }
bool load(bool buildIfMissing = true, bool skipLoadingCss = false);
bool clearCache() const;
void setupCacheDir() const;
const std::string& getCachePath() const;
const std::string& getPath() const;
const std::string& getTitle() const;
const std::string& getAuthor() const;
const std::string& getLanguage() const;
std::string getCoverBmpPath(bool cropped = false) const;
bool generateCoverBmp(bool cropped = false) const;
std::string getThumbBmpPath() const;
std::string getThumbBmpPath(int height) const;
bool generateThumbBmp(int height) const;
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,
bool allowEarlyStop = false) const;
// Extract an item to a file on SD. On failure the partial file is removed.
bool extractItemToFile(const std::string& itemHref, const std::string& destPath) const;
bool getItemSize(const std::string& itemHref, size_t* size) const;
BookMetadataCache::SpineEntry getSpineItem(int spineIndex) const;
BookMetadataCache::TocEntry getTocItem(int tocIndex) const;
int getSpineItemsCount() const;
int getTocItemsCount() const;
int getSpineIndexForTocIndex(int tocIndex) const;
int getTocIndexForSpineIndex(int spineIndex) const;
size_t getCumulativeSpineItemSize(int spineIndex) const;
int getSpineIndexForTextReference() const;
size_t getBookSize() const;
float calculateProgress(int currentSpineIndex, float currentSpineRead) const;
CssParser* getCssParser() const { return cssParser.get(); }
int resolveHrefToSpineIndex(const std::string& href) const;
};