From 7b024cc1749494114fffc3c434b58846707a64af Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Mon, 18 Nov 2024 13:28:28 +0100 Subject: [PATCH] Don't count overflowing inline image height to previous line In the line break algorithm, we try filling characters and objects onto a text line until we see an overflow. We then keep the state *before* the overflow as the current line and move to the next. However, for inline images we would store its height to the current state before checking if it overflowed. So if the inline image did cause an overflow it would be counted towards the height of the preceding line in addition to the line where it actually ended up. [ChangeLog][Text] Fixed an issue which could cause the height of a word-wrapped text line to grow if the immediate line after it began with an inline image. Pick-to: 5.15 6.5 6.8 Fixes: QTBUG-130980 Change-Id: I68494b49059e5e35349cbde77aefc64abeb69697 Reviewed-by: Lars Knoll --- src/gui/text/qtextlayout.cpp | 7 +-- .../gui/text/qtextlayout/tst_qtextlayout.cpp | 49 +++++++++++++++++++ 2 files changed, 53 insertions(+), 3 deletions(-) diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp index f0c7dd24e5b..de56f1040e0 100644 --- a/src/gui/text/qtextlayout.cpp +++ b/src/gui/text/qtextlayout.cpp @@ -1951,15 +1951,16 @@ void QTextLine::layout_helper(int maxGlyphs) } } - hasInlineObject = true; - maxInlineObjectHeight = qMax(maxInlineObjectHeight, current.ascent + current.descent); - lbh.tmpData.textWidth += current.width; newItem = item + 1; ++lbh.glyphCount; if (lbh.checkFullOtherwiseExtend(line)) goto found; + + hasInlineObject = true; + maxInlineObjectHeight = qMax(maxInlineObjectHeight, current.ascent + current.descent); + } else if (attributes[lbh.currentPosition].whiteSpace && eng->layoutData->string.at(lbh.currentPosition).decompositionTag() != QChar::NoBreak) { lbh.whiteSpaceOrObject = true; diff --git a/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp b/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp index a8c737634a3..a6f4ecaa9af 100644 --- a/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp +++ b/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp @@ -128,6 +128,7 @@ private slots: void min_maximumWidth_data(); void min_maximumWidth(); void negativeLineWidth(); + void embeddedImageLineHeight(); private: QFont testFont; @@ -2761,5 +2762,53 @@ void tst_QTextLayout::negativeLineWidth() } } +void tst_QTextLayout::embeddedImageLineHeight() +{ + QString s1 = QStringLiteral("Foobar Foobar Foobar Foobar"); + QString s2 = QStringLiteral("Foobar Foobar Foobar Foobar"); + + qreal s1Width; + qreal s1Height; + { + QTextDocument document; + document.setHtml(s1); + QCOMPARE(document.blockCount(), 1); + + // Trigger layout + { + QImage img(1, 1, QImage::Format_ARGB32_Premultiplied); + QPainter p(&img); + document.drawContents(&p); + } + + QTextLayout *layout = document.firstBlock().layout(); + QVERIFY(layout != nullptr); + QCOMPARE(layout->lineCount(), 1); + QTextLine line = layout->lineAt(0); + s1Width = document.idealWidth(); + s1Height = line.ascent() + line.descent(); + } + + { + QTextDocument document; + document.setHtml(s1 + s2); + document.setTextWidth(std::ceil(s1Width)); + QCOMPARE(document.blockCount(), 1); + + // Trigger layout + { + QImage img(1, 1, QImage::Format_ARGB32_Premultiplied); + QPainter p(&img); + document.drawContents(&p); + } + + QTextLayout *layout = document.firstBlock().layout(); + QVERIFY(layout != nullptr); + QVERIFY(layout->lineCount() > 1); + QTextLine line = layout->lineAt(0); + QCOMPARE(line.ascent() + line.descent(), s1Height); + } +} + QTEST_MAIN(tst_QTextLayout) #include "tst_qtextlayout.moc"