| 704 | } // namespace |
| 705 | |
| 706 | SavedProgressPosition ProgressMapper::toSavedProgress(const std::shared_ptr<Epub>& epub, |
| 707 | const CrossPointPosition& pos) { |
| 708 | SavedProgressPosition result; |
| 709 | float intra = |
| 710 | (pos.totalPages > 1) ? static_cast<float>(pos.pageNumber) / static_cast<float>(pos.totalPages - 1) : 0.0f; |
| 711 | result.percentage = epub->calculateProgress(pos.spineIndex, intra); |
| 712 | // Progress-based XPath correctly handles both <p> and <li> positions. |
| 713 | result.xpath = ChapterXPathResolver::findXPathForProgress(epub, pos.spineIndex, intra); |
| 714 | // Fall back to paragraph-index lookup when progress-based resolution fails. |
| 715 | if (result.xpath.empty() && pos.hasParagraphIndex && pos.paragraphIndex > 0) { |
| 716 | result.xpath = ChapterXPathResolver::findXPathForParagraph(epub, pos.spineIndex, pos.paragraphIndex); |
| 717 | } |
| 718 | if (result.xpath.empty()) { |
| 719 | result.xpath = generateXPath(epub, pos.spineIndex, intra); |
| 720 | } |
| 721 | LOG_DBG("PM", "-> Progress: spine=%d page=%d/%d %.2f%% %s", pos.spineIndex, pos.pageNumber, pos.totalPages, |
| 722 | result.percentage * 100, result.xpath.c_str()); |
| 723 | return result; |
| 724 | } |
| 725 | |
| 726 | CrossPointPosition ProgressMapper::toCrossPoint(const std::shared_ptr<Epub>& epub, const SavedProgressPosition& koPos, |
| 727 | GfxRenderer& renderer, int currentSpineIndex, |
nothing calls this directly
no test coverage detected