Update docs

This commit is contained in:
jpirnay
2026-02-25 22:44:08 +01:00
parent 7e8bd70f3c
commit c335e027b4
6 changed files with 164 additions and 14 deletions
+17
View File
@@ -125,6 +125,23 @@ Notes:
- rendering favors reusing precomputed layout data to keep page turns responsive on constrained hardware
- progress/session state is persisted so the reader can reopen at the last position after reboot/sleep
## KOReader sync position mapping
KOReader sync integration is implemented under `lib/KOReaderSync/` and is used by
`src/activities/reader/KOReaderSyncActivity.*`.
Position translation currently follows a dual-path strategy:
- CrossPoint -> KOReader: prefer element-level XPath extracted from the current
spine XHTML; fallback to chapter-level `DocFragment` path when needed.
- KOReader -> CrossPoint: prefer incoming XPath resolution; fallback to
percentage-based estimation if XPath is invalid or cannot be resolved.
Detailed algorithm and constraints (including low-memory rationale for ESP32-C3)
are documented in:
- [KOReader Sync XPath Mapping](koreader-sync-xpath-mapping.md)
## State and persistence
Two singletons are central:
@@ -0,0 +1,83 @@
# KOReader Sync XPath Mapping
This note documents how CrossPoint maps reading positions to and from KOReader sync payloads.
## Problem
CrossPoint internally stores position as:
- `spineIndex` (chapter index)
- `pageNumber` + `totalPages`
KOReader sync payload stores:
- `progress` (XPath-like location)
- `percentage` (overall progress)
A direct 1:1 mapping is not guaranteed because page layout differs between engines/devices.
## Current Strategy
### CrossPoint -> KOReader
Implemented in `ProgressMapper::toKOReader`.
1. Compute overall `percentage` from chapter/page.
2. Attempt to compute a real element-level XPath via `ChapterXPathIndexer::findXPathForProgress`.
3. If XPath extraction fails, fallback to synthetic chapter path:
- `/body/DocFragment[N]/body`
### KOReader -> CrossPoint
Implemented in `ProgressMapper::toCrossPoint`.
1. Attempt to parse `DocFragment[N]` from incoming XPath.
2. If valid, attempt XPath-to-offset mapping via `ChapterXPathIndexer::findProgressForXPath`.
3. Convert resolved intra-spine progress to page estimate.
4. If XPath path is invalid/unresolvable, fallback to percentage-based chapter/page estimation.
## ChapterXPathIndexer Design
The module reparses **one spine XHTML** on demand using Expat and builds temporary anchors:
- anchor: `<xpath, textOffset>`
- `textOffset` counts non-whitespace bytes
Matching for reverse lookup:
1. exact path match
2. index-insensitive path match (`div[2]` vs `div[3]` tolerated)
3. ancestor fallback
If no match is found, caller must fallback to percentage.
## Memory / Safety Constraints (ESP32-C3)
The implementation intentionally avoids full DOM storage.
- Parse one chapter only.
- Keep anchors in transient vectors only for duration of call.
- Free XML parser and chapter byte buffer on all success/failure paths.
- No persistent cache structures are introduced by this module.
## Known Limitations
- Page number on reverse mapping is still an estimate (renderer differences).
- Image-only/low-text chapters may yield coarse anchors.
- Extremely malformed XHTML can force fallback behavior.
## Operational Logging
`ProgressMapper` logs mapping source in reverse direction:
- `xpath` when XPath mapping path was used
- `percentage` when fallback path was used
It also logs exactness (`exact=yes/no`) for XPath matches.
## Validation
Use test vectors in:
- `test/koreader_sync/roundtrip_vectors.md`
- `test/koreader_sync/memory_resource_qa.md`