From 4ee9783e4904779f1c5608d952a34a496f739703 Mon Sep 17 00:00:00 2001 From: Arthur Tazhitdinov Date: Fri, 26 Dec 2025 01:54:43 +0500 Subject: [PATCH] Enhance line breaking logic with detailed comments for clarity and maintainability --- lib/Epub/Epub/ParsedText.cpp | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/lib/Epub/Epub/ParsedText.cpp b/lib/Epub/Epub/ParsedText.cpp index dfb16df..dc2d9c1 100644 --- a/lib/Epub/Epub/ParsedText.cpp +++ b/lib/Epub/Epub/ParsedText.cpp @@ -166,10 +166,14 @@ std::vector ParsedText::computeLineBreaks(const GfxRenderer& renderer, c auto runDp = [&](std::vector& lineBreaks) { const size_t totalWordCount = wordWidths.size(); - + + // DP table to store the minimum badness (cost) of lines starting at index i std::vector dp(totalWordCount); + // 'ans[i]' stores the index 'j' of the *last word* in the optimal line starting at 'i' std::vector ans(totalWordCount); + // Base Case + dp[totalWordCount - 1] = 0; ans[totalWordCount - 1] = totalWordCount - 1; @@ -178,6 +182,7 @@ std::vector ParsedText::computeLineBreaks(const GfxRenderer& renderer, c dp[i] = MAX_COST; for (size_t j = i; j < totalWordCount; ++j) { + // Current line length: previous width + space + current word width currlen += wordWidths[j] + spaceWidth; if (currlen > pageWidth) { @@ -200,13 +205,14 @@ std::vector ParsedText::computeLineBreaks(const GfxRenderer& renderer, c cost = 0; } else { const int remainingSpace = pageWidth - currlen; + // Use long long for the square to prevent overflow const long long cost_ll = static_cast(remainingSpace) * remainingSpace + dp[j + 1]; cost = cost_ll > MAX_COST ? MAX_COST : static_cast(cost_ll); } if (cost < dp[i]) { dp[i] = cost; - ans[i] = j; + ans[i] = j; // j is the index of the last word in this optimal line } } } @@ -222,6 +228,7 @@ std::vector ParsedText::computeLineBreaks(const GfxRenderer& renderer, c } }; + // Stores the index of the word that starts the next line (last_word_index + 1) std::vector lineBreakIndices; while (true) { @@ -307,19 +314,22 @@ void ParsedText::extractLine(const size_t breakIndex, const int pageWidth, const const size_t lastBreakAt = breakIndex > 0 ? lineBreakIndices[breakIndex - 1] : 0; const size_t lineWordCount = lineBreak - lastBreakAt; + // Calculate total word width for this line int lineWordWidthSum = 0; - for (size_t idx = lastBreakAt; idx < lineBreak; ++idx) { - lineWordWidthSum += wordWidths[idx]; + for (size_t i = lastBreakAt; i < lineBreak; i++) { + lineWordWidthSum += wordWidths[i]; } - const bool isLastLine = breakIndex == lineBreakIndices.size() - 1; + // Calculate spacing const int spareSpace = pageWidth - lineWordWidthSum; int spacing = spaceWidth; + const bool isLastLine = breakIndex == lineBreakIndices.size() - 1; if (style == TextBlock::JUSTIFIED && !isLastLine && lineWordCount >= 2) { spacing = spareSpace / (lineWordCount - 1); } + // Calculate initial x position uint16_t xpos = 0; if (style == TextBlock::RIGHT_ALIGN) { xpos = spareSpace - (lineWordCount - 1) * spaceWidth; @@ -327,6 +337,7 @@ void ParsedText::extractLine(const size_t breakIndex, const int pageWidth, const xpos = (spareSpace - (lineWordCount - 1) * spaceWidth) / 2; } + // Pre-calculate X positions for words std::list lineXPos; for (size_t i = lastBreakAt; i < lineBreak; i++) { const uint16_t currentWordWidth = wordWidths[i]; @@ -334,11 +345,13 @@ void ParsedText::extractLine(const size_t breakIndex, const int pageWidth, const xpos += currentWordWidth + spacing; } + // Iterators always start at the beginning as we are moving content with splice below auto wordEndIt = words.begin(); auto wordStyleEndIt = wordStyles.begin(); std::advance(wordEndIt, lineWordCount); std::advance(wordStyleEndIt, lineWordCount); + // *** CRITICAL STEP: CONSUME DATA USING SPLICE *** std::list lineWords; lineWords.splice(lineWords.begin(), words, words.begin(), wordEndIt); std::list lineWordStyles;