summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAntti Määttä <antti.maatta@qt.io>2021-05-06 11:00:08 +0300
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2021-05-07 05:27:28 +0000
commitd3b5b6c24ae47eaa19d426ff428b8e0f58d4678c (patch)
tree688f456336324a980d88133ce1b6315a913ee01b
parent7b3987d9b000325728e4e94af3c58af52589f445 (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 Change-Id: I8a2fd89f2f2076e0c9364618a4cdc2596e0087a1 Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io> (cherry picked from commit 1fb4a3ef2bd86d650495e15a23c7efc1e600a59a) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r--src/charts/chartpresenter.cpp51
1 files changed, 46 insertions, 5 deletions
diff --git a/src/charts/chartpresenter.cpp b/src/charts/chartpresenter.cpp
index 6407a270..98bca1a1 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) {