diff options
author | Eskil Abrahamsen Blomfeldt <[email protected]> | 2024-12-10 12:29:30 +0100 |
---|---|---|
committer | Eskil Abrahamsen Blomfeldt <[email protected]> | 2024-12-11 18:41:52 +0100 |
commit | 250117086ff15bba79df8f0e15ee66192edc9ea9 (patch) | |
tree | b500c5250f0f8af8b71e5c0c2143f6f3896c6b06 | |
parent | 8784ea16a6bc66ac481d5cbf2dd1ece2d57a836b (diff) |
Include right bearing in width of layouts wrapping on spaces
When we're calculating the width of the layout, we include the
right bearing of the last character in the text line if it is
negative (i.e. it exceeds the advance width). We do this by
storing the last glyph that has been verified to fit in the
line, so that we can retrieve its right bearing when we find
a break.
However, when we were wrapping on spaces this previous glyph
would always be a space, and the right bearing would
subsequently be 0. But then the trailing spaces would be
trimmed and the right bearing of the actual last glyph
would not be recorded and never added to the text width.
This caused a failure in tst_qquicktext on Windows with both
DirectWrite and Freetype: This was purely unlucky, because
the metrics of the Tahoma font happened to be such that the
right bearing on the 'k' was enough to cause a line to
overflow. Since we didn't account for it when setting the
width, we ended up with unexpected line breaks, causing the
test to fail.
This did not happen with GDI, since it rounded the right
bearing of the character down to 0 (which was actually
visible in the layout, in that the k was painted a fraction
of a pixel outside the text layout's width).
In addition, QTBUG-130313 was causing us to pick a different
font when resolving the non-existent font requested by the test,
so therefore the bug was not found immediately when moving to
DirectWrite as the default but only when QTBUG-130313 was fixed.
We fix this by
1. When adding a chunk of whitespace, we record the previous
non-whitespace glyph that has been verified to fit.
2. When adding a chunk of non-whitespace, we only record the
previous glyph verified to fit *if* it is not whitespace.
Otherwise we keep whatever we recorded before adding the
spaces.
Pick-to: 6.8 6.9
Fixes: QTBUG-132075
Change-Id: I8d9a2f3197068f5f93520d217a6bb89633644e95
Reviewed-by: Lars Knoll <[email protected]>
-rw-r--r-- | src/gui/text/qtextlayout.cpp | 20 |
1 files changed, 16 insertions, 4 deletions
diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp index de56f1040e0..086a8dbefa2 100644 --- a/src/gui/text/qtextlayout.cpp +++ b/src/gui/text/qtextlayout.cpp @@ -1862,6 +1862,8 @@ void QTextLine::layout_helper(int maxGlyphs) bool hasInlineObject = false; QFixed maxInlineObjectHeight = 0; + const bool includeTrailingSpaces = eng->option.flags() & QTextOption::IncludeTrailingSpaces; + while (newItem < eng->layoutData->items.size()) { lbh.resetRightBearing(); if (newItem != item) { @@ -1963,6 +1965,10 @@ void QTextLine::layout_helper(int maxGlyphs) } else if (attributes[lbh.currentPosition].whiteSpace && eng->layoutData->string.at(lbh.currentPosition).decompositionTag() != QChar::NoBreak) { + // If we are adding a space block, we save the last non-whitespace glyph for calculating + // the right bearing later + if (lbh.currentPosition > 0 && !attributes[lbh.currentPosition - 1].whiteSpace) + lbh.saveCurrentGlyph(); lbh.whiteSpaceOrObject = true; while (lbh.currentPosition < end && attributes[lbh.currentPosition].whiteSpace @@ -1976,7 +1982,15 @@ void QTextLine::layout_helper(int maxGlyphs) lbh.whiteSpaceOrObject = false; bool sb_or_ws = false; - lbh.saveCurrentGlyph(); + // We save the previous glyph so we can use it for calculating the right bearing + // later. If we are trimming trailing spaces, the previous glyph is whitespace + // and we have already recorded a non-whitespace glyph, we keep that one instead. + if (lbh.currentPosition == 0 + || lbh.previousGlyph == 0 + || includeTrailingSpaces + || !attributes[lbh.currentPosition - 1].whiteSpace) { + lbh.saveCurrentGlyph(); + } QFixed accumulatedTextWidth; do { addNextCluster(lbh.currentPosition, end, lbh.tmpData, lbh.glyphCount, @@ -2137,9 +2151,7 @@ found: line.descent.toReal(), line.textWidth.toReal(), lbh.spaceData.width.toReal()); LB_DEBUG(" : '%s'", eng->layoutData->string.mid(line.from, line.length).toUtf8().data()); - const QFixed trailingSpace = (eng->option.flags() & QTextOption::IncludeTrailingSpaces - ? lbh.spaceData.textWidth - : QFixed(0)); + const QFixed trailingSpace = (includeTrailingSpaces ? lbh.spaceData.textWidth : QFixed(0)); if (eng->option.wrapMode() == QTextOption::WrapAtWordBoundaryOrAnywhere) { if ((lbh.maxGlyphs != INT_MAX && lbh.glyphCount > lbh.maxGlyphs) || (lbh.maxGlyphs == INT_MAX && line.textWidth > (line.width - trailingSpace))) { |