diff options
author | Antti Määttä <antti.maatta@qt.io> | 2021-05-06 11:00:08 +0300 |
---|---|---|
committer | Antti Määttä <antti.maatta@qt.io> | 2021-05-07 06:53:54 +0300 |
commit | 1fb4a3ef2bd86d650495e15a23c7efc1e600a59a (patch) | |
tree | 5cf1f04e886c1058f9b51e73be5da0fdaf90bb33 | |
parent | 6128880ca270a0a6799b51a283596e5142d1a747 (diff) |
Add text bounds cache
Improve performance by caching recently used text bounds.
Charts keeps requesting bounds for the same text multiple times.
Store the recently requested bounds to a cache to improve performance.
In android device reduces the frame time by about 30 % and in windows
reduces the total time spent in native text function used to get the
bounds from 8.5% to 3.1%.
Fixes: QTBUG-59040
Pick-to: 5.15 6.1
Change-Id: I8a2fd89f2f2076e0c9364618a4cdc2596e0087a1
Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io>
-rw-r--r-- | src/charts/chartpresenter.cpp | 51 |
1 files changed, 46 insertions, 5 deletions
diff --git a/src/charts/chartpresenter.cpp b/src/charts/chartpresenter.cpp index 2a704fa0..f9e7a481 100644 --- a/src/charts/chartpresenter.cpp +++ b/src/charts/chartpresenter.cpp @@ -478,18 +478,59 @@ ChartTitle *ChartPresenter::titleElement() return m_title; } +template <int TSize> +struct TextBoundCache +{ + struct element + { + quint32 lastUsed; + QRectF bounds; + }; + QHash<QString, element> elements; + quint32 usedCounter = 0; + QGraphicsTextItem dummyText; + + QRectF bounds(const QFont &font, const QString &text) + { + const QString key = font.key() + text; + auto elem = elements.find(key); + if (elem != elements.end()) { + usedCounter++; + elem->lastUsed = usedCounter; + return elem->bounds; + } + dummyText.setFont(font); + dummyText.setHtml(text); + const QRectF bounds = dummyText.boundingRect(); + if (elements.size() >= TSize) { + auto elem = std::min_element(elements.begin(), elements.end(), + [](const element &a, const element &b) { + return a.lastUsed < b.lastUsed; + }); + if (elem != elements.end()) { + const QString key = elem.key(); + elements.remove(key); + } + } + elements.insert(key, {usedCounter++, bounds}); + return bounds; + } + QTextDocument *document() + { + return dummyText.document(); + } +}; + QRectF ChartPresenter::textBoundingRect(const QFont &font, const QString &text, qreal angle) { - static QGraphicsTextItem dummyTextItem; + static TextBoundCache<32> textBoundCache; static bool initMargin = true; if (initMargin) { - dummyTextItem.document()->setDocumentMargin(textMargin()); + textBoundCache.document()->setDocumentMargin(textMargin()); initMargin = false; } - dummyTextItem.setFont(font); - dummyTextItem.setHtml(text); - QRectF boundingRect = dummyTextItem.boundingRect(); + QRectF boundingRect = textBoundCache.bounds(font, text); // Take rotation into account if (angle) { |