Fix reindexing on toc-page-break
This commit is contained in:
@@ -170,6 +170,17 @@ void ChapterHtmlSlimParser::flushPartWordBuffer() {
|
|||||||
nextWordContinues = false;
|
nextWordContinues = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Emit the current page, keeping paragraphLutPerPage and completedPageCount in lockstep.
|
||||||
|
// Callers must ensure currentPage is non-null and carries content; the helper resets
|
||||||
|
// currentPage to a fresh Page and zeroes currentPageNextY so the caller can keep building.
|
||||||
|
void ChapterHtmlSlimParser::emitPage(uint32_t xhtmlByteOffset) {
|
||||||
|
paragraphLutPerPage.push_back({xhtmlByteOffset, xpathParagraphIndex});
|
||||||
|
completePageFn(std::move(currentPage));
|
||||||
|
completedPageCount++;
|
||||||
|
currentPage.reset(new Page());
|
||||||
|
currentPageNextY = 0;
|
||||||
|
}
|
||||||
|
|
||||||
// start a new text block if needed
|
// start a new text block if needed
|
||||||
void ChapterHtmlSlimParser::startNewTextBlock(const BlockStyle& blockStyle) {
|
void ChapterHtmlSlimParser::startNewTextBlock(const BlockStyle& blockStyle) {
|
||||||
nextWordContinues = false; // New block = new paragraph, no continuation
|
nextWordContinues = false; // New block = new paragraph, no continuation
|
||||||
@@ -198,10 +209,7 @@ void ChapterHtmlSlimParser::startNewTextBlock(const BlockStyle& blockStyle) {
|
|||||||
if (!pendingAnchorId.empty()) {
|
if (!pendingAnchorId.empty()) {
|
||||||
if (std::find(tocAnchors.begin(), tocAnchors.end(), pendingAnchorId) != tocAnchors.end()) {
|
if (std::find(tocAnchors.begin(), tocAnchors.end(), pendingAnchorId) != tocAnchors.end()) {
|
||||||
if (currentPage && !currentPage->elements.empty()) {
|
if (currentPage && !currentPage->elements.empty()) {
|
||||||
completePageFn(std::move(currentPage));
|
emitPage(lastBodyChildByteOffset);
|
||||||
completedPageCount++;
|
|
||||||
currentPage.reset(new Page());
|
|
||||||
currentPageNextY = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
anchorData.push_back({std::move(pendingAnchorId), static_cast<uint16_t>(completedPageCount)});
|
anchorData.push_back({std::move(pendingAnchorId), static_cast<uint16_t>(completedPageCount)});
|
||||||
@@ -218,10 +226,7 @@ void ChapterHtmlSlimParser::startNewTextBlock(const BlockStyle& blockStyle) {
|
|||||||
if (!pendingAnchorId.empty() &&
|
if (!pendingAnchorId.empty() &&
|
||||||
std::find(tocAnchors.begin(), tocAnchors.end(), pendingAnchorId) != tocAnchors.end()) {
|
std::find(tocAnchors.begin(), tocAnchors.end(), pendingAnchorId) != tocAnchors.end()) {
|
||||||
if (currentPage && !currentPage->elements.empty()) {
|
if (currentPage && !currentPage->elements.empty()) {
|
||||||
completePageFn(std::move(currentPage));
|
emitPage(lastBodyChildByteOffset);
|
||||||
completedPageCount++;
|
|
||||||
currentPage.reset(new Page());
|
|
||||||
currentPageNextY = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Record deferred anchor after previous block is flushed (and any TOC page break)
|
// Record deferred anchor after previous block is flushed (and any TOC page break)
|
||||||
@@ -593,15 +598,11 @@ void XMLCALL ChapterHtmlSlimParser::startElement(void* userData, const XML_Char*
|
|||||||
(self->currentPageNextY + totalImageHeightWithSpacing > self->viewportHeight)) {
|
(self->currentPageNextY + totalImageHeightWithSpacing > self->viewportHeight)) {
|
||||||
LOG_DBG("EHP", "Image page break: currentY=%d needed=%d viewportH=%d", self->currentPageNextY,
|
LOG_DBG("EHP", "Image page break: currentY=%d needed=%d viewportH=%d", self->currentPageNextY,
|
||||||
totalImageHeightWithSpacing, self->viewportHeight);
|
totalImageHeightWithSpacing, self->viewportHeight);
|
||||||
self->paragraphLutPerPage.push_back({self->lastBodyChildByteOffset, self->xpathParagraphIndex});
|
self->emitPage(self->lastBodyChildByteOffset);
|
||||||
self->completePageFn(std::move(self->currentPage));
|
|
||||||
self->completedPageCount++;
|
|
||||||
self->currentPage.reset(new Page());
|
|
||||||
if (!self->currentPage) {
|
if (!self->currentPage) {
|
||||||
LOG_ERR("EHP", "Failed to create new page");
|
LOG_ERR("EHP", "Failed to create new page");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
self->currentPageNextY = 0;
|
|
||||||
} else if (!self->currentPage) {
|
} else if (!self->currentPage) {
|
||||||
self->currentPage.reset(new Page());
|
self->currentPage.reset(new Page());
|
||||||
if (!self->currentPage) {
|
if (!self->currentPage) {
|
||||||
@@ -1423,9 +1424,7 @@ bool ChapterHtmlSlimParser::parseAndBuildPages() {
|
|||||||
anchorData.push_back({std::move(pendingAnchorId), static_cast<uint16_t>(completedPageCount)});
|
anchorData.push_back({std::move(pendingAnchorId), static_cast<uint16_t>(completedPageCount)});
|
||||||
pendingAnchorId.clear();
|
pendingAnchorId.clear();
|
||||||
}
|
}
|
||||||
paragraphLutPerPage.push_back({0u, xpathParagraphIndex}); // post-parse: no byte offset available
|
emitPage(0u); // post-parse: no byte offset available
|
||||||
completePageFn(std::move(currentPage));
|
|
||||||
completedPageCount++;
|
|
||||||
currentPage.reset();
|
currentPage.reset();
|
||||||
currentTextBlock.reset();
|
currentTextBlock.reset();
|
||||||
}
|
}
|
||||||
@@ -1444,11 +1443,7 @@ ParsedText::LineProcessResult ChapterHtmlSlimParser::addLineToPage(std::shared_p
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (currentPageNextY + lineHeight > viewportHeight) {
|
if (currentPageNextY + lineHeight > viewportHeight) {
|
||||||
paragraphLutPerPage.push_back({lastBodyChildByteOffset, xpathParagraphIndex});
|
emitPage(lastBodyChildByteOffset);
|
||||||
completePageFn(std::move(currentPage));
|
|
||||||
completedPageCount++;
|
|
||||||
currentPage.reset(new Page());
|
|
||||||
currentPageNextY = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool noRoomForAnotherLine =
|
const bool noRoomForAnotherLine =
|
||||||
|
|||||||
@@ -127,6 +127,10 @@ class ChapterHtmlSlimParser {
|
|||||||
void startNewTextBlock(const BlockStyle& blockStyle);
|
void startNewTextBlock(const BlockStyle& blockStyle);
|
||||||
void flushPartWordBuffer();
|
void flushPartWordBuffer();
|
||||||
void makePages();
|
void makePages();
|
||||||
|
// Emit currentPage to the consumer while keeping paragraphLutPerPage and completedPageCount
|
||||||
|
// in lockstep. Every page break MUST go through this helper; open-coded completePageFn
|
||||||
|
// calls risk desynchronising paragraphLutPerPage and failing the size check in Section.cpp.
|
||||||
|
void emitPage(uint32_t xhtmlByteOffset);
|
||||||
// XML callbacks
|
// XML callbacks
|
||||||
static void XMLCALL startElement(void* userData, const XML_Char* name, const XML_Char** atts);
|
static void XMLCALL startElement(void* userData, const XML_Char* name, const XML_Char** atts);
|
||||||
static void XMLCALL characterData(void* userData, const XML_Char* s, int len);
|
static void XMLCALL characterData(void* userData, const XML_Char* s, int len);
|
||||||
|
|||||||
Reference in New Issue
Block a user