Merge branch 'feat-invalid-toc-fallback' of https://github.com/jpirnay/crosspoint-reader into mybuild
This commit is contained in:
+85
-1
@@ -336,6 +336,7 @@ void Epub::parseCssFiles() const {
|
||||
// load in the meta data for the epub file
|
||||
bool Epub::load(const bool buildIfMissing, const bool skipLoadingCss) {
|
||||
LOG_DBG("EBP", "Loading ePub: %s", filepath.c_str());
|
||||
tocReliabilityState = -1;
|
||||
|
||||
// Initialize spine/TOC cache
|
||||
bookMetadataCache.reset(new BookMetadataCache(cachePath));
|
||||
@@ -794,6 +795,18 @@ BookMetadataCache::TocEntry Epub::getTocItem(const int tocIndex) const {
|
||||
return {};
|
||||
}
|
||||
|
||||
if (syntheticTocFallbackEnabled && !hasReliableToc()) {
|
||||
const int spineCount = bookMetadataCache->getSpineCount();
|
||||
if (tocIndex < 0 || tocIndex >= spineCount) {
|
||||
LOG_DBG("EBP", "getTocItem synthetic index:%d is out of range", tocIndex);
|
||||
return {};
|
||||
}
|
||||
|
||||
const auto spine = bookMetadataCache->getSpineEntry(tocIndex);
|
||||
return BookMetadataCache::TocEntry("Section " + std::to_string(tocIndex + 1), spine.href, "", 1,
|
||||
static_cast<int16_t>(tocIndex));
|
||||
}
|
||||
|
||||
if (tocIndex < 0 || tocIndex >= bookMetadataCache->getTocCount()) {
|
||||
LOG_DBG("EBP", "getTocItem index:%d is out of range", tocIndex);
|
||||
return {};
|
||||
@@ -807,6 +820,10 @@ int Epub::getTocItemsCount() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (syntheticTocFallbackEnabled && !hasReliableToc()) {
|
||||
return bookMetadataCache->getSpineCount();
|
||||
}
|
||||
|
||||
return bookMetadataCache->getTocCount();
|
||||
}
|
||||
|
||||
@@ -817,6 +834,14 @@ int Epub::getSpineIndexForTocIndex(const int tocIndex) const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (syntheticTocFallbackEnabled && !hasReliableToc()) {
|
||||
if (tocIndex < 0 || tocIndex >= bookMetadataCache->getSpineCount()) {
|
||||
LOG_ERR("EBP", "getSpineIndexForTocIndex synthetic tocIndex %d out of range", tocIndex);
|
||||
return 0;
|
||||
}
|
||||
return tocIndex;
|
||||
}
|
||||
|
||||
if (tocIndex < 0 || tocIndex >= bookMetadataCache->getTocCount()) {
|
||||
LOG_ERR("EBP", "getSpineIndexForTocIndex: tocIndex %d out of range", tocIndex);
|
||||
return 0;
|
||||
@@ -831,7 +856,66 @@ int Epub::getSpineIndexForTocIndex(const int tocIndex) const {
|
||||
return spineIndex;
|
||||
}
|
||||
|
||||
int Epub::getTocIndexForSpineIndex(const int spineIndex) const { return getSpineItem(spineIndex).tocIndex; }
|
||||
bool Epub::hasReliableToc() const {
|
||||
if (tocReliabilityState != -1) {
|
||||
return tocReliabilityState == 1;
|
||||
}
|
||||
|
||||
if (!bookMetadataCache || !bookMetadataCache->isLoaded()) {
|
||||
tocReliabilityState = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
const int spineCount = bookMetadataCache->getSpineCount();
|
||||
const int tocCount = bookMetadataCache->getTocCount();
|
||||
|
||||
if (spineCount <= 0 || tocCount <= 0) {
|
||||
tocReliabilityState = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
// If a larger book only exposes one TOC entry, treat TOC as unusable for chapter UX.
|
||||
if (spineCount >= 8 && tocCount <= 1) {
|
||||
tocReliabilityState = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<bool> spineReferenced(static_cast<size_t>(spineCount), false);
|
||||
int distinctSpinesReferenced = 0;
|
||||
for (int i = 0; i < tocCount; i++) {
|
||||
const auto toc = bookMetadataCache->getTocEntry(i);
|
||||
if (toc.spineIndex >= 0 && toc.spineIndex < spineCount) {
|
||||
const size_t idx = static_cast<size_t>(toc.spineIndex);
|
||||
if (!spineReferenced[idx]) {
|
||||
spineReferenced[idx] = true;
|
||||
distinctSpinesReferenced++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Require at least 25% spine coverage from TOC references.
|
||||
const bool reliable = (distinctSpinesReferenced * 4 >= spineCount);
|
||||
tocReliabilityState = reliable ? 1 : 0;
|
||||
return reliable;
|
||||
}
|
||||
|
||||
int Epub::getTocIndexForSpineIndex(const int spineIndex) const {
|
||||
if (!bookMetadataCache || !bookMetadataCache->isLoaded()) {
|
||||
LOG_ERR("EBP", "getTocIndexForSpineIndex called but cache not loaded");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (spineIndex < 0 || spineIndex >= bookMetadataCache->getSpineCount()) {
|
||||
LOG_ERR("EBP", "getTocIndexForSpineIndex: spineIndex %d out of range", spineIndex);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (syntheticTocFallbackEnabled && !hasReliableToc()) {
|
||||
return spineIndex;
|
||||
}
|
||||
|
||||
return bookMetadataCache->getSpineEntry(spineIndex).tocIndex;
|
||||
}
|
||||
|
||||
size_t Epub::getBookSize() const {
|
||||
if (!bookMetadataCache || !bookMetadataCache->isLoaded() || bookMetadataCache->getSpineCount() == 0) {
|
||||
|
||||
Reference in New Issue
Block a user