Files
Crosspoint/lib/KOReaderSync/ProgressMapper.h
T
Justin Mitchell d364e54a69 Add KOReader XPath sync support for EPUB navigation
Implements bidirectional conversion between KOReader XPath positions and FreeInkBook character offsets. Uses streaming SAX parsing to match chapter text accounting with ChapterLayout, enabling position sync without requiring DOM or pagination. Handles element ancestry tracking, text offset calculation, and spine index extraction.
2026-07-08 01:11:29 -04:00

71 lines
2.8 KiB
C++

#pragma once
#include <Epub.h>
#include <GfxRenderer.h>
#include <memory>
#include <string>
/**
* CrossPoint position representation.
*/
struct CrossPointPosition {
int spineIndex; // Current spine item (chapter) index
int pageNumber; // Current page within the spine item
int totalPages; // Total pages in the current spine item
uint16_t paragraphIndex = 0; // 1-based synthetic paragraph index from XPath p[N]
bool hasParagraphIndex = false; // True when paragraphIndex was resolved from XPath
uint16_t liIndex = 0; // Running <li> count at the matched XPath element
bool hasLiIndex = false; // True when target element is <li> and liIndex was resolved
char xpathAnchorId[64] = {}; // First <a id> captured inside the matched XPath element
};
#include "KOReaderPosition.h" // SavedProgressPosition
/**
* Maps between CrossPoint and SavedProgress position formats, such as those used by KOReader.
*
* CrossPoint tracks position as (spineIndex, pageNumber).
* SavedProgress uses XPath-like strings + percentage.
*
* Since CrossPoint discards HTML structure during parsing, we generate
* synthetic XPath strings based on spine index, using percentage as the
* primary sync mechanism.
*/
class ProgressMapper {
public:
/**
* Convert CrossPoint position to SavedProgress format.
*
* @param epub The EPUB book
* @param pos CrossPoint position
* @return SavedProgress position
*/
static SavedProgressPosition toSavedProgress(const std::shared_ptr<Epub>& epub, const CrossPointPosition& pos);
/**
* Convert SavedProgress position to CrossPoint format.
*
* Note: The returned pageNumber may be approximate since different
* rendering settings produce different page counts.
*
* @param epub The EPUB book
* @param savedPos SavedProgress position
* @param renderer GfxRenderer for page count estimation
* @param currentSpineIndex Index of the currently open spine item (for density estimation)
* @param totalPagesInCurrentSpine Total pages in the current spine item (for density estimation)
* @return CrossPoint position
*/
static CrossPointPosition toCrossPoint(const std::shared_ptr<Epub>& epub, const SavedProgressPosition& savedPos,
GfxRenderer& renderer, int currentSpineIndex = -1,
int totalPagesInCurrentSpine = 0, int fallbackTotalPages = 0);
private:
/**
* Generate a fallback XPath by streaming the spine item's XHTML and resolving
* a paragraph/text position from intra-spine progress.
* Produces a full ancestry path such as
* /body/DocFragment[3]/body/p[42]/text().17.
*/
static std::string generateXPath(const std::shared_ptr<Epub>& epub, int spineIndex, float intraSpineProgress);
};