diff options
author | David Faure <[email protected]> | 2022-05-16 23:58:30 +0200 |
---|---|---|
committer | David Faure <[email protected]> | 2022-05-17 22:37:40 +0200 |
commit | bb2f4d08d9d138e4f70d6d6db46e24e34500becc (patch) | |
tree | 94a38a14157c6b3e0cbaa41692364b45584d29ca | |
parent | 7fa17b5f7998926c8f8650694a977eb7a24ae191 (diff) |
QTextDocument/QGraphicsTextItem: skip layout in setTextWidth(0)
In a QGraphicsTextItem without a width yet, there's no need to do any
layouting. The use case is obviously items with an app-defined size,
not the default where text items adapt to their contents.
Results:
0.065 msecs to create a QGraphicsTextItem with some text (layouted)
0.036 msecs to set everything up in a QGraphicsTextItem with 0 width
QTextEdit was abusing the width 0 to mean "no wrap, width comes from
contents", but since the value -1 means that already in QTextDocument,
QTextEdit now uses a width of -1 for that meaning.
Change-Id: I67ad59c305e5dd34830886e4e6c56dde03c93668
Reviewed-by: Qt CI Bot <[email protected]>
Reviewed-by: Volker Hilsheimer <[email protected]>
-rw-r--r-- | src/gui/text/qtextdocument_p.h | 5 | ||||
-rw-r--r-- | src/gui/text/qtextdocumentlayout.cpp | 10 | ||||
-rw-r--r-- | src/widgets/widgets/qtextedit.cpp | 2 | ||||
-rw-r--r-- | tests/auto/widgets/widgets/qtextedit/tst_qtextedit.cpp | 5 | ||||
-rw-r--r-- | tests/benchmarks/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp | 19 |
5 files changed, 33 insertions, 8 deletions
diff --git a/src/gui/text/qtextdocument_p.h b/src/gui/text/qtextdocument_p.h index 195006b130b..3769d07eb73 100644 --- a/src/gui/text/qtextdocument_p.h +++ b/src/gui/text/qtextdocument_p.h @@ -291,6 +291,11 @@ public: return get(object->document()); } + // Only test the width for 0: + // * setTextWidth(x) leads to height -1, which is valid + // * the default page size of (-1, -1) means size determined from contents, this is valid too + bool canLayout() const { return !qIsNull(pageSize.width()); } + private: QTextDocumentPrivate(const QTextDocumentPrivate& m); QTextDocumentPrivate& operator= (const QTextDocumentPrivate& m); diff --git a/src/gui/text/qtextdocumentlayout.cpp b/src/gui/text/qtextdocumentlayout.cpp index 81eb0f49fbe..6b75449ae9e 100644 --- a/src/gui/text/qtextdocumentlayout.cpp +++ b/src/gui/text/qtextdocumentlayout.cpp @@ -3705,7 +3705,7 @@ void QTextDocumentLayout::draw(QPainter *painter, const PaintContext &context) } QFixed width = fd->size.width; - if (d->document->pageSize().width() == 0 && d->viewportRect.isValid()) { + if (d->document->pageSize().width() == -1 && d->viewportRect.isValid()) { // we're in NoWrap mode, meaning the frame should expand to the viewport // so that backgrounds are drawn correctly fd->size.width = qMax(width, QFixed::fromReal(d->viewportRect.right())); @@ -3754,7 +3754,7 @@ void QTextDocumentLayout::documentChanged(int from, int oldLength, int length) for (; blockIt.isValid() && blockIt != endIt; blockIt = blockIt.next()) blockIt.clearLayout(); - if (d->docPrivate->pageSize.isNull()) + if (!d->docPrivate->canLayout()) return; QRectF updateRect; @@ -4032,7 +4032,7 @@ QRectF QTextDocumentLayout::tableCellBoundingRect(QTextTable *table, const QText QRectF QTextDocumentLayout::tableBoundingRect(QTextTable *table) const { Q_D(const QTextDocumentLayout); - if (d->docPrivate->pageSize.isNull()) + if (!d->docPrivate->canLayout()) return QRectF(); d->ensureLayoutFinished(); @@ -4059,7 +4059,7 @@ QRectF QTextDocumentLayout::tableBoundingRect(QTextTable *table) const QRectF QTextDocumentLayout::frameBoundingRect(QTextFrame *frame) const { Q_D(const QTextDocumentLayout); - if (d->docPrivate->pageSize.isNull()) + if (!d->docPrivate->canLayout()) return QRectF(); d->ensureLayoutFinished(); return d->frameBoundingRectInternal(frame); @@ -4088,7 +4088,7 @@ QRectF QTextDocumentLayoutPrivate::frameBoundingRectInternal(QTextFrame *frame) QRectF QTextDocumentLayout::blockBoundingRect(const QTextBlock &block) const { Q_D(const QTextDocumentLayout); - if (d->docPrivate->pageSize.isNull() || !block.isValid() || !block.isVisible()) + if (!d->docPrivate->canLayout() || !block.isValid() || !block.isVisible()) return QRectF(); d->ensureLayoutedByPosition(block.position() + block.length()); QTextFrame *frame = d->document->frameAt(block.position()); diff --git a/src/widgets/widgets/qtextedit.cpp b/src/widgets/widgets/qtextedit.cpp index c11b87c6bba..944dfe7aaa4 100644 --- a/src/widgets/widgets/qtextedit.cpp +++ b/src/widgets/widgets/qtextedit.cpp @@ -1521,7 +1521,7 @@ void QTextEditPrivate::relayoutDocument() QVariant alignmentProperty = doc->documentLayout()->property("contentHasAlignment"); if (alignmentProperty.userType() == QMetaType::Bool && !alignmentProperty.toBool()) { - width = 0; + width = -1; } } diff --git a/tests/auto/widgets/widgets/qtextedit/tst_qtextedit.cpp b/tests/auto/widgets/widgets/qtextedit/tst_qtextedit.cpp index bc533df48ae..72d2cc7aa70 100644 --- a/tests/auto/widgets/widgets/qtextedit/tst_qtextedit.cpp +++ b/tests/auto/widgets/widgets/qtextedit/tst_qtextedit.cpp @@ -1194,8 +1194,9 @@ void tst_QTextEdit::undoRedoShouldRepositionTextEditCursor() void tst_QTextEdit::lineWrapModes() { ed->setLineWrapMode(QTextEdit::NoWrap); - // NoWrap at the same time as having all lines that are all left aligned means we optimize to only layout once. The effect is that the width is always 0 - QCOMPARE(ed->document()->pageSize().width(), qreal(0)); + // NoWrap at the same time as having all lines that are all left aligned means we optimize to + // only layout once. The effect is that the width is always -1 + QCOMPARE(ed->document()->pageSize().width(), qreal(-1)); QTextCursor cursor = QTextCursor(ed->document()); cursor.insertText(QString("A simple line")); diff --git a/tests/benchmarks/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/benchmarks/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp index fd74a7b3b90..536d366b638 100644 --- a/tests/benchmarks/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp +++ b/tests/benchmarks/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp @@ -5,6 +5,7 @@ #include <QGraphicsItem> #include <QGraphicsScene> #include <QGraphicsView> +#include <QTextDocument> class tst_QGraphicsItem : public QObject { @@ -33,6 +34,7 @@ private slots: void shear(); void translate(); void createTextItem(); + void createTextItemZeroWidth(); }; tst_QGraphicsItem::tst_QGraphicsItem() @@ -216,5 +218,22 @@ void tst_QGraphicsItem::createTextItem() } } +void tst_QGraphicsItem::createTextItemZeroWidth() +{ + // Ensure QFontDatabase loaded the font beforehand + QFontInfo(qApp->font()).family(); + const QString text = "This is some text"; + QBENCHMARK { + QGraphicsTextItem item; + item.document()->setTextWidth(0); + // Prepare everything + item.setPlainText(text); + QTextOption option = item.document()->defaultTextOption(); + option.setAlignment(Qt::AlignHCenter); + item.document()->setDefaultTextOption(option); + // And (in a real app) set actual text width here + } +} + QTEST_MAIN(tst_QGraphicsItem) #include "tst_qgraphicsitem.moc" |