diff options
author | Olivier Goffart <ogoffart@woboq.com> | 2012-07-19 12:54:10 (GMT) |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2012-08-31 20:21:28 (GMT) |
commit | 49fbb6e14af78f751fa114c3cf986aaa607d7408 (patch) | |
tree | 09b0adfee85ef0f072e78eb393ea2a82378853c9 /src/gui/text | |
parent | 5fd483d0511864a4099c3f0786a708f4e992979e (diff) | |
download | Qt-49fbb6e14af78f751fa114c3cf986aaa607d7408.zip Qt-49fbb6e14af78f751fa114c3cf986aaa607d7408.tar.gz Qt-49fbb6e14af78f751fa114c3cf986aaa607d7408.tar.bz2 |
Speed up QTextEngine::resolveAdditionalFormats
Don't call the linear QTextEngine::format in the loop.
Instead, keep track of the current formats by indexing their start and end position.
Task-number: QTBUG-8389
Change-Id: I89c18b804111edfab6254442cbee33da39d1a273
Reviewed-by: Lars Knoll <lars.knoll@nokia.com>
(cherry picked from commit 4f6efe16416f0222ae78ab16c0eb8085bf9c521b)
Diffstat (limited to 'src/gui/text')
-rw-r--r-- | src/gui/text/qtextengine.cpp | 67 |
1 files changed, 65 insertions, 2 deletions
diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp index d3d8126..fbaf71f 100644 --- a/src/gui/text/qtextengine.cpp +++ b/src/gui/text/qtextengine.cpp @@ -2786,6 +2786,25 @@ QFixed QTextEngine::calculateTabWidth(int item, QFixed x) const return tabWidth; } +namespace { +class FormatRangeComparatorByStart { + const QList<QTextLayout::FormatRange> &list; +public: + FormatRangeComparatorByStart(const QList<QTextLayout::FormatRange> &list) : list(list) { } + bool operator()(int a, int b) { + return list.at(a).start < list.at(b).start; + } +}; +class FormatRangeComparatorByEnd { + const QList<QTextLayout::FormatRange> &list; +public: + FormatRangeComparatorByEnd(const QList<QTextLayout::FormatRange> &list) : list(list) { } + bool operator()(int a, int b) { + return list.at(a).start + list.at(a).length < list.at(b).start + list.at(b).length; + } +}; +} + void QTextEngine::resolveAdditionalFormats() const { if (!specialData || specialData->addFormats.isEmpty() @@ -2797,9 +2816,53 @@ void QTextEngine::resolveAdditionalFormats() const specialData->resolvedFormatIndices.clear(); QVector<int> indices(layoutData->items.count()); + + + QVarLengthArray<int, 64> addFormatSortedByStart; + addFormatSortedByStart.reserve(specialData->addFormats.count()); + for (int i = 0; i < specialData->addFormats.count(); ++i) + addFormatSortedByStart.append(i); + QVarLengthArray<int, 64> addFormatSortedByEnd = addFormatSortedByStart; + qSort(addFormatSortedByStart.begin(), addFormatSortedByStart.end(), + FormatRangeComparatorByStart(specialData->addFormats)); + qSort(addFormatSortedByEnd.begin(), addFormatSortedByEnd.end(), + FormatRangeComparatorByEnd(specialData->addFormats)); + + QVarLengthArray<int, 16> currentFormats; + const int *startIt = addFormatSortedByStart.constBegin(); + const int *endIt = addFormatSortedByEnd.constBegin(); + for (int i = 0; i < layoutData->items.count(); ++i) { - QTextCharFormat f = format(&layoutData->items.at(i)); - indices[i] = collection->indexForFormat(f); + const QScriptItem *si = &layoutData->items.at(i); + int end = si->position + length(si); + + while (startIt != addFormatSortedByStart.end() && + specialData->addFormats.at(*startIt).start <= si->position) { + currentFormats.insert(qUpperBound(currentFormats.begin(), currentFormats.end(), *startIt), + *startIt); + ++startIt; + } + while (endIt != addFormatSortedByEnd.end() && + specialData->addFormats.at(*endIt).start + specialData->addFormats.at(*endIt).length < end) { + currentFormats.remove(qBinaryFind(currentFormats, *endIt) - currentFormats.begin()); + ++endIt; + } + QTextCharFormat format; + const QTextFormatCollection *formats = 0; + if (block.docHandle()) { + formats = this->formats(); + format = formats->charFormat(formatIndex(si)); + } + foreach (int cur, currentFormats) { + const QTextLayout::FormatRange &r = specialData->addFormats.at(cur); + Q_ASSERT (r.start <= si->position && r.start + r.length >= end); + if (!specialData->addFormatIndices.isEmpty()) { + format.merge(formats->format(specialData->addFormatIndices.at(cur))); + } else { + format.merge(r.format); + } + } + indices[i] = collection->indexForFormat(format); } specialData->resolvedFormatIndices = indices; } |