diff options
author | Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@nokia.com> | 2010-05-27 07:08:14 (GMT) |
---|---|---|
committer | Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@nokia.com> | 2010-05-27 07:41:52 (GMT) |
commit | 7cc8e62f74f66f20c216a8bc8c3187c989a3dcb4 (patch) | |
tree | 94156a2ff64389bbddd08b7275ed69a12fcd37b4 | |
parent | 11a8c52498e8dc74fdfef48e953055338c8f18d7 (diff) | |
download | Qt-7cc8e62f74f66f20c216a8bc8c3187c989a3dcb4.zip Qt-7cc8e62f74f66f20c216a8bc8c3187c989a3dcb4.tar.gz Qt-7cc8e62f74f66f20c216a8bc8c3187c989a3dcb4.tar.bz2 |
Optimize initialization of QStaticText
Since QStaticText would be created once and used often, not much thought
was put into optimizing its initialization. For simplicity, the code
would do two drawText() passes. Since this was an unnecessary overhead,
the extra pass has been removed and replaced by memmoves instead.
Initialization is now twice as fast.
Reviewed-by: Samuel
-rw-r--r-- | src/gui/text/qstatictext.cpp | 163 | ||||
-rw-r--r-- | src/gui/text/qstatictext_p.h | 19 |
2 files changed, 101 insertions, 81 deletions
diff --git a/src/gui/text/qstatictext.cpp b/src/gui/text/qstatictext.cpp index c7817c6..2889a96 100644 --- a/src/gui/text/qstatictext.cpp +++ b/src/gui/text/qstatictext.cpp @@ -363,23 +363,24 @@ QSizeF QStaticText::size() const } QStaticTextPrivate::QStaticTextPrivate() - : textWidth(-1.0), items(0), itemCount(0), glyphPool(0), positionPool(0), + : textWidth(-1.0), items(0), itemCount(0), glyphPool(0), positionPool(0), charPool(0), needsRelayout(true), useBackendOptimizations(false), textFormat(Qt::AutoText) { } QStaticTextPrivate::QStaticTextPrivate(const QStaticTextPrivate &other) : text(other.text), font(other.font), textWidth(other.textWidth), matrix(other.matrix), - items(0), itemCount(0), glyphPool(0), positionPool(0), needsRelayout(true), + items(0), itemCount(0), glyphPool(0), positionPool(0), charPool(0), needsRelayout(true), useBackendOptimizations(other.useBackendOptimizations), textFormat(other.textFormat) { } QStaticTextPrivate::~QStaticTextPrivate() { - delete[] items; + delete[] items; delete[] glyphPool; delete[] positionPool; + delete[] charPool; } QStaticTextPrivate *QStaticTextPrivate::get(const QStaticText *q) @@ -395,15 +396,8 @@ namespace { class DrawTextItemRecorder: public QPaintEngine { public: - DrawTextItemRecorder(int expectedItemCount, QStaticTextItem *items, - int expectedGlyphCount, QFixedPoint *positionPool, glyph_t *glyphPool) - : m_items(items), - m_itemCount(0), m_glyphCount(0), - m_expectedItemCount(expectedItemCount), - m_expectedGlyphCount(expectedGlyphCount), - m_glyphPool(glyphPool), - m_positionPool(positionPool), - m_dirtyPen(false) + DrawTextItemRecorder(bool useBackendOptimizations, int numChars) + : m_dirtyPen(false), m_useBackendOptimizations(useBackendOptimizations) { } @@ -415,26 +409,19 @@ namespace { virtual void drawTextItem(const QPointF &position, const QTextItem &textItem) { - const QTextItemInt &ti = static_cast<const QTextItemInt &>(textItem); - - m_itemCount++; - m_glyphCount += ti.glyphs.numGlyphs; - if (m_items == 0) - return; - - Q_ASSERT(m_itemCount <= m_expectedItemCount); - Q_ASSERT(m_glyphCount <= m_expectedGlyphCount); - - QStaticTextItem *currentItem = (m_items + (m_itemCount - 1)); - currentItem->fontEngine = ti.fontEngine; - currentItem->font = ti.font(); - currentItem->chars = ti.chars; - currentItem->numChars = ti.num_chars; - currentItem->numGlyphs = ti.glyphs.numGlyphs; - currentItem->glyphs = m_glyphPool; - currentItem->glyphPositions = m_positionPool; + const QTextItemInt &ti = static_cast<const QTextItemInt &>(textItem); + + QStaticTextItem currentItem; + currentItem.fontEngine = ti.fontEngine; + currentItem.font = ti.font(); + currentItem.charOffset = m_chars.size(); + currentItem.numChars = ti.num_chars; + currentItem.numGlyphs = ti.glyphs.numGlyphs; + currentItem.glyphOffset = m_glyphs.size(); // Store offset into glyph pool + currentItem.positionOffset = m_glyphs.size(); // Offset into position pool + currentItem.useBackendOptimizations = m_useBackendOptimizations; if (m_dirtyPen) - currentItem->color = state->pen().color(); + currentItem.color = state->pen().color(); QTransform matrix = state->transform(); matrix.translate(position.x(), position.y()); @@ -447,13 +434,21 @@ namespace { Q_ASSERT(size == ti.glyphs.numGlyphs); Q_ASSERT(size == positions.size()); - memmove(currentItem->glyphs, glyphs.constData(), sizeof(glyph_t) * size); - memmove(currentItem->glyphPositions, positions.constData(), sizeof(QFixedPoint) * size); + m_glyphs.resize(m_glyphs.size() + size); + m_positions.resize(m_glyphs.size()); + m_chars.resize(m_chars.size() + ti.num_chars); - m_glyphPool += size; - m_positionPool += size; - } + glyph_t *glyphsDestination = m_glyphs.data() + currentItem.glyphOffset; + memmove(glyphsDestination, glyphs.constData(), sizeof(glyph_t) * currentItem.numGlyphs); + QFixedPoint *positionsDestination = m_positions.data() + currentItem.positionOffset; + memmove(positionsDestination, positions.constData(), sizeof(QFixedPoint) * currentItem.numGlyphs); + + QChar *charsDestination = m_chars.data() + currentItem.charOffset; + memmove(charsDestination, ti.chars, sizeof(QChar) * currentItem.numChars); + + m_items.append(currentItem); + } virtual bool begin(QPaintDevice *) { return true; } virtual bool end() { return true; } @@ -463,38 +458,42 @@ namespace { return User; } - int itemCount() const + QVector<QStaticTextItem> items() const { - return m_itemCount; + return m_items; } - int glyphCount() const + QVector<QFixedPoint> positions() const { - return m_glyphCount; + return m_positions; } - private: - QStaticTextItem *m_items; - int m_itemCount; - int m_glyphCount; - int m_expectedItemCount; - int m_expectedGlyphCount; + QVector<glyph_t> glyphs() const + { + return m_glyphs; + } + + QVector<QChar> chars() const + { + return m_chars; + } - glyph_t *m_glyphPool; - QFixedPoint *m_positionPool; + private: + QVector<QStaticTextItem> m_items; + QVector<QFixedPoint> m_positions; + QVector<glyph_t> m_glyphs; + QVector<QChar> m_chars; bool m_dirtyPen; + bool m_useBackendOptimizations; }; class DrawTextItemDevice: public QPaintDevice { public: - DrawTextItemDevice(int expectedItemCount = -1, QStaticTextItem *items = 0, - int expectedGlyphCount = -1, QFixedPoint *positionPool = 0, - glyph_t *glyphPool = 0) + DrawTextItemDevice(bool useBackendOptimizations, int numChars) { - m_paintEngine = new DrawTextItemRecorder(expectedItemCount, items, - expectedGlyphCount, positionPool, glyphPool); + m_paintEngine = new DrawTextItemRecorder(useBackendOptimizations, numChars); } ~DrawTextItemDevice() @@ -538,14 +537,24 @@ namespace { return m_paintEngine; } - int itemCount() const + QVector<glyph_t> glyphs() const { - return m_paintEngine->itemCount(); + return m_paintEngine->glyphs(); } - int glyphCount() const + QVector<QFixedPoint> positions() const { - return m_paintEngine->glyphCount(); + return m_paintEngine->positions(); + } + + QVector<QStaticTextItem> items() const + { + return m_paintEngine->items(); + } + + QVector<QChar> chars() const + { + return m_paintEngine->chars(); } private: @@ -616,42 +625,42 @@ void QStaticTextPrivate::init() delete[] items; delete[] glyphPool; delete[] positionPool; + delete[] charPool; position = QPointF(0, 0); - // Draw once to count number of items and glyphs, so that we can use as little memory - // as possible to store the data - DrawTextItemDevice counterDevice; + DrawTextItemDevice device(useBackendOptimizations, text.size()); { - QPainter painter(&counterDevice); + QPainter painter(&device); painter.setFont(font); painter.setTransform(matrix); paintText(QPointF(0, 0), &painter); - } - itemCount = counterDevice.itemCount(); + QVector<QStaticTextItem> deviceItems = device.items(); + QVector<QFixedPoint> positions = device.positions(); + QVector<glyph_t> glyphs = device.glyphs(); + QVector<QChar> chars = device.chars(); + + itemCount = deviceItems.size(); items = new QStaticTextItem[itemCount]; - if (useBackendOptimizations) { - for (int i=0; i<itemCount; ++i) - items[i].useBackendOptimizations = true; - } + glyphPool = new glyph_t[glyphs.size()]; + memmove(glyphPool, glyphs.constData(), glyphs.size() * sizeof(glyph_t)); + positionPool = new QFixedPoint[positions.size()]; + memmove(positionPool, positions.constData(), positions.size() * sizeof(QFixedPoint)); - int glyphCount = counterDevice.glyphCount(); - glyphPool = new glyph_t[glyphCount]; - positionPool = new QFixedPoint[glyphCount]; + charPool = new QChar[chars.size()]; + memmove(charPool, chars.constData(), chars.size() * sizeof(QChar)); - // Draw again to actually record the items and glyphs - DrawTextItemDevice recorderDevice(itemCount, items, glyphCount, positionPool, glyphPool); - { - QPainter painter(&recorderDevice); - painter.setFont(font); - painter.setTransform(matrix); + for (int i=0; i<itemCount; ++i) { + items[i] = deviceItems.at(i); - paintText(QPointF(0, 0), &painter); + items[i].glyphs = glyphPool + items[i].glyphOffset; + items[i].glyphPositions = positionPool + items[i].positionOffset; + items[i].chars = charPool + items[i].charOffset; } needsRelayout = false; diff --git a/src/gui/text/qstatictext_p.h b/src/gui/text/qstatictext_p.h index f017ed1..2ab5579 100644 --- a/src/gui/text/qstatictext_p.h +++ b/src/gui/text/qstatictext_p.h @@ -88,9 +88,18 @@ public: userData = newUserData; } - QFixedPoint *glyphPositions; // 8 bytes per glyph - glyph_t *glyphs; // 4 bytes per glyph - const QChar *chars; // 2 bytes per glyph + union { + QFixedPoint *glyphPositions; // 8 bytes per glyph + int positionOffset; + }; + union { + glyph_t *glyphs; // 4 bytes per glyph + int glyphOffset; + }; + union { + QChar *chars; // 2 bytes per glyph + int charOffset; + }; // ================= // 14 bytes per glyph @@ -134,14 +143,16 @@ public: QTransform matrix; // 80 bytes per text QStaticTextItem *items; // 4 bytes per text int itemCount; // 4 bytes per text + glyph_t *glyphPool; // 4 bytes per text QFixedPoint *positionPool; // 4 bytes per text + QChar *charPool; // 4 bytes per text unsigned char needsRelayout : 1; unsigned char useBackendOptimizations : 1; // 1 byte per text unsigned char textFormat : 2; // ================ - // 163 bytes per text + // 167 bytes per text static QStaticTextPrivate *get(const QStaticText *q); }; |