diff --git a/lib/Epub/Epub/ParsedText.cpp b/lib/Epub/Epub/ParsedText.cpp index e57d1743..ebe758db 100644 --- a/lib/Epub/Epub/ParsedText.cpp +++ b/lib/Epub/Epub/ParsedText.cpp @@ -1006,7 +1006,10 @@ void ParsedText::extractLine(const size_t breakIndex, const int pageWidth, const int advance = renderer.getKerning(fontId, lastCodepoint(reorderedWordsScratch[wordIdx]), firstCodepoint(reorderedWordsScratch[wordIdx + 1]), reorderedStylesScratch[wordIdx]); - if (reorderedWordsScratch[wordIdx] == " " && reorderedContinuesScratch[wordIdx] && + // wordIdx > 0 mirrors the gap accounting above (which skips index 0): a leading + // no-break space must not receive justifyExtra, or the line over-stretches by one + // gap and the last word is pushed past the right margin (issue #2185). + if (wordIdx > 0 && reorderedWordsScratch[wordIdx] == " " && reorderedContinuesScratch[wordIdx] && effectiveAlignment == CssTextAlign::Justify && !isLastLine) { advance += reorderedJustifyExtra; } @@ -1048,7 +1051,8 @@ void ParsedText::extractLine(const size_t breakIndex, const int pageWidth, const // Cross-boundary kerning for continuation words int advance = renderer.getKerning(fontId, lastCodepoint(lineWords[wordIdx]), firstCodepoint(lineWords[wordIdx + 1]), lineWordStyles[wordIdx]); - if (lineWords[wordIdx] == " " && continuesVec[lastBreakAt + wordIdx] && + // wordIdx > 0: see the LTR branch — a leading no-break space is not a justifiable gap. + if (wordIdx > 0 && lineWords[wordIdx] == " " && continuesVec[lastBreakAt + wordIdx] && effectiveAlignment == CssTextAlign::Justify && !isLastLine) { advance += justifyExtra; } @@ -1086,7 +1090,10 @@ void ParsedText::extractLine(const size_t breakIndex, const int pageWidth, const int advance = wordWidths[lastBreakAt + wordIdx]; advance += renderer.getKerning(fontId, lastCodepoint(lineWords[wordIdx]), firstCodepoint(lineWords[wordIdx + 1]), lineWordStyles[wordIdx]); - if (lineWords[wordIdx] == " " && continuesVec[lastBreakAt + wordIdx] && + // wordIdx > 0 mirrors the gap accounting above (which skips index 0): a leading + // no-break space must not receive justifyExtra, or the line over-stretches by one + // gap and the last word is pushed past the right margin (issue #2185). + if (wordIdx > 0 && lineWords[wordIdx] == " " && continuesVec[lastBreakAt + wordIdx] && effectiveAlignment == CssTextAlign::Justify && !isLastLine) { advance += justifyExtra; }