From 3ac1ab13a0b0ea8d60cc2b19bed17d8ece690731 Mon Sep 17 00:00:00 2001 From: Jack R <79218139+prawnwhoyawns@users.noreply.github.com> Date: Sun, 10 May 2026 12:10:51 -0600 Subject: [PATCH] fix: distribute justifyExtra to non-breaking space tokens (#1783) --- lib/Epub/Epub/ParsedText.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/lib/Epub/Epub/ParsedText.cpp b/lib/Epub/Epub/ParsedText.cpp index 193b320e..e348270b 100644 --- a/lib/Epub/Epub/ParsedText.cpp +++ b/lib/Epub/Epub/ParsedText.cpp @@ -652,6 +652,11 @@ void ParsedText::extractLine(const size_t breakIndex, const int pageWidth, const renderer.getSpaceAdvance(fontId, lastCodepoint(words[lastBreakAt + wordIdx - 1]), firstCodepoint(words[lastBreakAt + wordIdx]), wordStyles[lastBreakAt + wordIdx - 1]); } else if (wordIdx > 0 && continuesVec[lastBreakAt + wordIdx]) { + // Non-breaking space tokens (" " with continues=true) are visible, stretchable spaces — + // count them as justifiable gaps so justifyExtra is distributed to them too. + if (words[lastBreakAt + wordIdx] == " ") { + actualGapCount++; + } // Cross-boundary kerning for continuation words (e.g. nonbreaking spaces, attached punctuation) totalNaturalGaps += renderer.getKerning(fontId, lastCodepoint(words[lastBreakAt + wordIdx - 1]), @@ -693,6 +698,11 @@ void ParsedText::extractLine(const size_t breakIndex, const int pageWidth, const advance += renderer.getKerning(fontId, lastCodepoint(words[lastBreakAt + wordIdx]), firstCodepoint(words[lastBreakAt + wordIdx + 1]), wordStyles[lastBreakAt + wordIdx]); + // Non-breaking space tokens are stretchable — expand them during justification like normal spaces. + if (words[lastBreakAt + wordIdx] == " " && continuesVec[lastBreakAt + wordIdx] && + blockStyle.alignment == CssTextAlign::Justify && !isLastLine) { + advance += justifyExtra; + } xpos += advance; } else { int gap = 0;