diff options
author | Santhosh Kumar <santhosh.kumar.selvaraj@qt.io> | 2023-12-21 13:46:52 +0100 |
---|---|---|
committer | Santhosh Kumar <santhosh.kumar.selvaraj@qt.io> | 2024-01-26 15:40:09 +0100 |
commit | d548077d205d22610ceeb623006f7fa54d4c72c7 (patch) | |
tree | 90eb43d56c2ddceb76d70dfd51a200be4daa9b13 | |
parent | 34f39f670281fdce22a402508b1a8e55be6e9fa2 (diff) |
Force text layout update in the thread where its created
The text layout gets updated while invalidating font data. This creates
an issue when quick text instance was created and invalidated across
different threads.
It mainly affects QQuickText::lineLaidOut() signal as QQuickTextLine is
designed to provide information only about current line and its to be
noted that the current line provided by QQuickTextPrivate was from
stack. Thus, triggering this signal across thread provide invalid line
information. Its possible to keep line in heap but that doesn't help as
the ultimate purpose of QQuickText::lineLaidOut() signal is to provide
current line information which user can hook to modify its geometry.
This patch makes updateLayout() to be happening in same thread where
the quick text object was created.
Fixes: QTBUG-113039
Pick-to: 6.7 6.6 6.5
Change-Id: Ic0737cb514f663f87ac1cf21506ad76fee03643e
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
-rw-r--r-- | src/quick/items/qquicktext.cpp | 2 | ||||
-rw-r--r-- | tests/auto/quick/qquicktext/data/lineLayoutFontUpdate.qml | 25 | ||||
-rw-r--r-- | tests/auto/quick/qquicktext/data/tarzeau_ocr_a.ttf | bin | 0 -> 24544 bytes | |||
-rw-r--r-- | tests/auto/quick/qquicktext/tst_qquicktext.cpp | 24 |
4 files changed, 50 insertions, 1 deletions
diff --git a/src/quick/items/qquicktext.cpp b/src/quick/items/qquicktext.cpp index 8a8b36bea3..6abb30de56 100644 --- a/src/quick/items/qquicktext.cpp +++ b/src/quick/items/qquicktext.cpp @@ -3211,7 +3211,7 @@ void QQuickText::invalidate() { Q_D(QQuickText); d->textHasChanged = true; - d->updateLayout(); + QMetaObject::invokeMethod(this,[&]{q_updateLayout();}); } bool QQuickTextPrivate::transformChanged(QQuickItem *transformedItem) diff --git a/tests/auto/quick/qquicktext/data/lineLayoutFontUpdate.qml b/tests/auto/quick/qquicktext/data/lineLayoutFontUpdate.qml new file mode 100644 index 0000000000..d018e31d29 --- /dev/null +++ b/tests/auto/quick/qquicktext/data/lineLayoutFontUpdate.qml @@ -0,0 +1,25 @@ +import QtQuick + +Item { + width: 640 + height: 480 + + FontLoader { + id: fontIcons + source: "tarzeau_ocr_a.ttf" + } + + Text { + id: exampleText + objectName: "exampleText" + text: "Example multiline text" + wrapMode: Text.WordWrap + width: 100 + onLineLaidOut: (line) => { + if (line.number < 1) { + line.x += 40; + line.width -= 40; + } + } + } +} diff --git a/tests/auto/quick/qquicktext/data/tarzeau_ocr_a.ttf b/tests/auto/quick/qquicktext/data/tarzeau_ocr_a.ttf Binary files differnew file mode 100644 index 0000000000..cf93f9651f --- /dev/null +++ b/tests/auto/quick/qquicktext/data/tarzeau_ocr_a.ttf diff --git a/tests/auto/quick/qquicktext/tst_qquicktext.cpp b/tests/auto/quick/qquicktext/tst_qquicktext.cpp index 218d1d47ac..257dc678b6 100644 --- a/tests/auto/quick/qquicktext/tst_qquicktext.cpp +++ b/tests/auto/quick/qquicktext/tst_qquicktext.cpp @@ -110,6 +110,7 @@ private slots: void largeTextInDelayedLoader(); void lineLaidOut(); void lineLaidOutRelayout(); + void lineLaidOutFontUpdate(); void lineLaidOutHAlign(); void lineLaidOutImplicitWidth(); @@ -3121,6 +3122,29 @@ void tst_qquicktext::lineLaidOutRelayout() } } +void tst_qquicktext::lineLaidOutFontUpdate() +{ + QScopedPointer<QQuickView> window(createView(testFile("lineLayoutFontUpdate.qml"))); + + window->show(); + window->requestActivate(); + QVERIFY(QTest::qWaitForWindowActive(window.data())); + + auto *myText = window->rootObject()->findChild<QQuickText*>("exampleText"); + QVERIFY(myText != nullptr); + + QQuickTextPrivate *textPrivate = QQuickTextPrivate::get(myText); + QVERIFY(textPrivate != nullptr); + + QCOMPARE(textPrivate->layout.lineCount(), 2); + + QTextLine firstLine = textPrivate->layout.lineAt(0); + QTextLine secondLine = textPrivate->layout.lineAt(1); + + QCOMPARE(firstLine.rect().x(), secondLine.rect().x() + 40); + QCOMPARE(firstLine.rect().width(), secondLine.rect().width() - 40); +} + void tst_qquicktext::lineLaidOutHAlign() { QScopedPointer<QQuickView> window(createView(testFile("lineLayoutHAlign.qml"))); |