From 4cfca7cf456722ee8659b595f231f3cc2033b80d Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Tue, 4 Aug 2009 13:41:36 +0200 Subject: Speed optimization for QStaticText Don't use QVector to store the text items, but put them in a regular array for quick access. drawStaticText() is now about 2.7 times the speed of drawText(). --- src/gui/painting/qpainter.cpp | 14 +++++++++----- src/gui/text/qstatictext.cpp | 37 ++++++++++++++++++++----------------- src/gui/text/qstatictext.h | 2 ++ src/gui/text/qstatictext_p.h | 3 ++- src/gui/text/qtextengine.cpp | 5 +++++ src/gui/text/qtextengine_p.h | 2 ++ 6 files changed, 40 insertions(+), 23 deletions(-) diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index 6bb8acd..50d27ac 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -5724,14 +5724,18 @@ void QPainter::drawText(const QPointF &p, const QString &str) */ void QPainter::drawStaticText(const QPointF &position, const QStaticText &staticText) { + Q_D(QPainter); + if (!d->engine || staticText.isEmpty() || pen().style() == Qt::NoPen) + return; + const QStaticTextPrivate *staticText_d = QStaticTextPrivate::get(&staticText); QFixed x = QFixed::fromReal(position.x()); - for (int i=0; iitems.size();++i) { - QTextItemInt *gf = staticText_d->items.at(i); - if (gf->num_chars != 0) - drawTextItem(QPointF(x.toReal(), position.y()), *gf); - x += gf->width; + for (int i=0; iitemCount; ++i) { + const QTextItemInt &gf = staticText_d->items[i]; + if (gf.num_chars != 0) + drawTextItem(QPointF(x.toReal(), position.y()), gf); + x += gf.width; } } diff --git a/src/gui/text/qstatictext.cpp b/src/gui/text/qstatictext.cpp index e9fd9c5..d97c0c9 100644 --- a/src/gui/text/qstatictext.cpp +++ b/src/gui/text/qstatictext.cpp @@ -227,7 +227,13 @@ QString QStaticText::toString() const return text(); } -QStaticTextPrivate::QStaticTextPrivate() : glyphLayoutMemory(0), logClusterMemory(0) +bool QStaticText::isEmpty() const +{ + return d_ptr->text.isEmpty(); +} + +QStaticTextPrivate::QStaticTextPrivate() + : glyphLayoutMemory(0), logClusterMemory(0), items(0), itemCount(0) { ref = 1; } @@ -244,7 +250,7 @@ QStaticTextPrivate::~QStaticTextPrivate() { delete[] glyphLayoutMemory; delete[] logClusterMemory; - qDeleteAll(items); + delete[] items; } QStaticTextPrivate *QStaticTextPrivate::get(const QStaticText *q) @@ -256,7 +262,7 @@ void QStaticTextPrivate::init() { delete[] glyphLayoutMemory; delete[] logClusterMemory; - qDeleteAll(items); + delete[] items; QStackTextEngine engine(text, font); engine.itemize(); @@ -276,6 +282,8 @@ void QStaticTextPrivate::init() int numGlyphs = engine.layoutData->used; glyphLayoutMemory = new char[QGlyphLayout::spaceNeededForGlyphLayout(numGlyphs)]; logClusterMemory = new unsigned short[numGlyphs]; + items = new QTextItemInt[nItems]; + itemCount = nItems; char *currentGlyphLayout = glyphLayoutMemory; unsigned short *currentLogCluster = logClusterMemory; @@ -285,29 +293,24 @@ void QStaticTextPrivate::init() QFont f = engine.font(si); if (si.analysis.flags >= QScriptAnalysis::TabOrObject) { - QTextItemInt *gf = new QTextItemInt(si, &f); - gf->width = si.width; - items.append(gf); + items[i].width = si.width; continue; } - QTextItemInt *gf = new QTextItemInt(si, &f); + items[i].init(si, &f); + QGlyphLayout l = engine.shapedGlyphs(&si); - gf->glyphs = l.clone(currentGlyphLayout); + items[i].glyphs = l.clone(currentGlyphLayout); currentGlyphLayout += QGlyphLayout::spaceNeededForGlyphLayout(l.numGlyphs); - gf->chars = text.unicode() + si.position; - gf->num_chars = engine.length(item); - gf->width = si.width; + items[i].chars = text.unicode() + si.position; + items[i].num_chars = engine.length(item); + items[i].width = si.width; memmove(currentLogCluster, engine.logClusters(&si), sizeof(unsigned short) * l.numGlyphs); - gf->logClusters = currentLogCluster; - currentLogCluster += l.numGlyphs; - - items.append(gf); + items[i].logClusters = currentLogCluster; + currentLogCluster += l.numGlyphs; } - - items.squeeze(); } QT_END_NAMESPACE diff --git a/src/gui/text/qstatictext.h b/src/gui/text/qstatictext.h index bcafaa9..7247bf7 100644 --- a/src/gui/text/qstatictext.h +++ b/src/gui/text/qstatictext.h @@ -73,6 +73,8 @@ public: QString toString() const; + bool isEmpty() const; + private: void detach(); diff --git a/src/gui/text/qstatictext_p.h b/src/gui/text/qstatictext_p.h index aaaf300..a0d16d4 100644 --- a/src/gui/text/qstatictext_p.h +++ b/src/gui/text/qstatictext_p.h @@ -68,7 +68,8 @@ public: void init(); QAtomicInt ref; - QVector items; + QTextItemInt *items; + int itemCount; QString text; QFont font; char *glyphLayoutMemory; diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp index da3a3c0..5343085 100644 --- a/src/gui/text/qtextengine.cpp +++ b/src/gui/text/qtextengine.cpp @@ -2637,6 +2637,11 @@ QTextItemInt::QTextItemInt(const QScriptItem &si, QFont *font, const QTextCharFo : justified(false), underlineStyle(QTextCharFormat::NoUnderline), charFormat(format), num_chars(0), chars(0), logClusters(0), f(0), fontEngine(0) { + init(si, font, format); +} + +void QTextItemInt::init(const QScriptItem &si, QFont *font, const QTextCharFormat &format) +{ // explicitly initialize flags so that initFontAttributes can be called // multiple times on the same TextItem flags = 0; diff --git a/src/gui/text/qtextengine_p.h b/src/gui/text/qtextengine_p.h index 2edbd98..0491d87 100644 --- a/src/gui/text/qtextengine_p.h +++ b/src/gui/text/qtextengine_p.h @@ -312,7 +312,9 @@ public: : justified(false), underlineStyle(QTextCharFormat::NoUnderline), num_chars(0), chars(0), logClusters(0), f(0), fontEngine(0) {} + QTextItemInt(const QScriptItem &si, QFont *font, const QTextCharFormat &format = QTextCharFormat()); + void init(const QScriptItem &si, QFont *font, const QTextCharFormat &format = QTextCharFormat()); /// copy the structure items, adjusting the glyphs arrays to the right subarrays. /// the width of the returned QTextItemInt is not adjusted, for speed reasons -- cgit v0.12