summaryrefslogtreecommitdiffstats
path: root/src/gui
diff options
context:
space:
mode:
authorOlivier Goffart <ogoffart@woboq.com>2012-07-19 14:54:10 +0200
committerQt by Nokia <qt-info@nokia.com>2012-08-23 23:31:10 +0200
commit4f6efe16416f0222ae78ab16c0eb8085bf9c521b (patch)
treee4828363b565a51e56a5ae23ea4a6c02ea424401 /src/gui
parent7dfe25e2cd276b52d2683f7ecdad39943fdfbdce (diff)
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>
Diffstat (limited to 'src/gui')
-rw-r--r--src/gui/text/qtextengine.cpp67
1 files changed, 65 insertions, 2 deletions
diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp
index 83fdea6c88..a9c57dfa05 100644
--- a/src/gui/text/qtextengine.cpp
+++ b/src/gui/text/qtextengine.cpp
@@ -2678,6 +2678,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()
@@ -2689,9 +2708,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;
}