fix: Optimize Bookmark Rendering by Removing XPath Lookup (#2417)

## Summary

fix #2414 

### Root Cause

`updateBookmarkFlag()` was introduced in commit 1db1442 and is executed
on every render (every page turn). The function calls:

`ProgressMapper::toSavedProgress()`
→ `ChapterXPathResolver::findXPathForProgress()`

This path decompresses the current EPUB section content twice:

1. To count visible characters.
2. To resolve the corresponding XPath.

For larger sections (e.g. ~133 KB decompressed content), this adds
approximately **1 second of I/O overhead per page turn**, with the cost
increasing as chapter size grows.

### Fix

`updateBookmarkFlag()` only needs to determine whether a bookmark falls
within the currently displayed page range.

The required information is already available during rendering:

* `currentPage`
* `section->pageCount`
* `currentSpineIndex`

Instead of converting the current location to a saved progress object
(and resolving an XPath), the implementation now computes the current
page's progress range directly and compares bookmark percentages against
that range.

This is effectively the same percentage-based matching logic already
used as a fallback in `bookmarkMatchesProgress()` when XPath matching is
unavailable.

---

### AI Usage

While CrossPoint doesn't have restrictions on AI tools in contributing,
please be transparent about their usage as it
helps set the right context for reviewers.

Did you use AI tools to help write this code? _**< PARTIALLY >**_
This commit is contained in:
Uri Tauber
2026-06-25 09:20:24 -04:00
committed by GitHub
parent 8626d69f46
commit a09aef0889
+6 -2
View File
@@ -1350,11 +1350,15 @@ void EpubReaderActivity::updateBookmarkFlag() {
currentPageBookmarked = false;
return;
}
SavedProgressPosition progress = ProgressMapper::toSavedProgress(epub, getCurrentPosition());
const ProgressRange pageRange =
getPageProgressRange(epub, currentSpineIndex, section->currentPage, section->pageCount);
currentPageBookmarked = std::any_of(cachedBookmarks.begin(), cachedBookmarks.end(), [&](const BookmarkEntry& b) {
return bookmarkMatchesProgress(b, progress, pageRange);
if (b.computedSpineIndex == currentSpineIndex && b.computedChapterPageCount == section->pageCount &&
b.computedChapterProgress == section->currentPage) {
return true;
}
const float bp = std::clamp(b.percentage, 0.0f, 1.0f);
return bp + bookmarkProgressEpsilon >= pageRange.start && bp - bookmarkProgressEpsilon <= pageRange.end;
});
}