[prev in list] [next in list] [prev in thread] [next in thread]
List: kwrite-devel
Subject: KDE/kdelibs/kate/buffer
From: David Nolden <david.nolden.kde () art-master ! de>
Date: 2010-07-22 1:22:42
Message-ID: 20100722012242.2E041AC7AB () svn ! kde ! org
[Download RAW message or body]
SVN commit 1152789 by zwabel:
Add a cache for MovingRanges that are contained only by a single line, and use it to \
speed up the rendering of highlighting-intensive documents (like in KDevelop4) by \
magnitues. Please review and test this intensively for backporting, it seems to work \
fine.
CCMAIL: kwrite-devel@kde.org
CCMAIL: kdevelop-devel@kde.org
M +68 -20 katetextblock.cpp
M +34 -1 katetextblock.h
M +4 -2 katetextbuffer.cpp
M +2 -2 katetextrange.cpp
--- trunk/KDE/kdelibs/kate/buffer/katetextblock.cpp #1152788:1152789
@@ -35,7 +35,6 @@
Q_ASSERT (m_lines.empty());
Q_ASSERT (m_cursors.empty());
- // m_ranges will not be checked
// it only is a hint for ranges for this block, not the storage of them
}
@@ -108,7 +107,6 @@
* cursor and range handling below
*/
- // no need to touch m_ranges explicit!
// no cursors will leave or join this block
// no cursors in this block, no work to do..
@@ -152,7 +150,6 @@
}
// check validity of all ranges, might invalidate them...
- // might adjust m_ranges!
foreach (TextRange *range, changedRanges)
range->checkValidity ();
}
@@ -191,7 +188,7 @@
*/
// no cursors in this and previous block, no work to do..
- // no need to touch m_ranges, without cursors, no range could end between this \
blocks! + // no need to touch ranges-cache, without cursors, no range could end \
between this blocks! if (previousBlock->m_cursors.empty() && m_cursors.empty())
return;
@@ -228,18 +225,16 @@
}
previousBlock->m_cursors = newPreviousCursors;
- // adjust m_ranges
foreach (TextRange *range, rangesMoved) {
// either now only in new block
if (range->start().line () >= startLine())
- previousBlock->m_ranges.remove (range);
+ previousBlock->removeRange (range);
// or now in both
- m_ranges.insert (range);
+ updateRange (range);
}
// check validity of all ranges, might invalidate them...
- // might touch m_ranges!
foreach (TextRange *range, changedRanges)
range->checkValidity ();
@@ -288,7 +283,6 @@
}
// check validity of all ranges, might invalidate them...
- // might adjust m_ranges!
foreach (TextRange *range, changedRanges)
range->checkValidity ();
}
@@ -350,7 +344,6 @@
}
// check validity of all ranges, might invalidate them...
- // might adjust m_ranges!
foreach (TextRange *range, changedRanges)
range->checkValidity ();
}
@@ -413,7 +406,6 @@
}
// check validity of all ranges, might invalidate them...
- // might adjust m_ranges!
foreach (TextRange *range, changedRanges)
range->checkValidity ();
}
@@ -457,16 +449,14 @@
}
m_cursors = oldBlockSet;
- // adjust m_ranges
- newBlock->m_ranges = m_ranges;
foreach (TextRange *range, rangesInteresting) {
// only in new block
if (range->start().line () >= newBlock->startLine())
- m_ranges.remove (range);
-
- if (range->end().line () < newBlock->startLine())
- newBlock->m_ranges.remove (range);
+ {
+ removeRange (range);
+ newBlock->updateRange (range);
}
+ }
// return the new generated block
return newBlock;
@@ -482,15 +472,18 @@
}
m_cursors.clear ();
- // unite ranges
- targetBlock->m_ranges.unite (m_ranges);
-
// move lines
targetBlock->m_lines.reserve (targetBlock->lines() + lines ());
for (int i = 0; i < m_lines.size(); ++i)
targetBlock->m_lines.append (m_lines[i]);
m_lines.clear ();
+
+ foreach(TextRange* range, m_allRanges)
+ {
+ removeRange(range);
+ targetBlock->updateRange(range);
}
+}
void TextBlock::deleteBlockContent ()
{
@@ -522,4 +515,59 @@
m_lines.clear ();
}
+void TextBlock::updateRange(TextRange* range)
+{
+ int startLine = range->startInternal().lineInternal();
+ int endLine = range->endInternal().lineInternal();
+
+ bool isSingleLine = startLine == endLine;
+
+ if(isSingleLine && m_cachedLineForRanges.contains(range) && \
m_cachedLineForRanges[range] == startLine - m_startLine) + {
+ // The range is still a single-line range, and is still cached to the correct \
line. + return;
+ }else if(startLine != endLine && m_uncachedRanges.contains(range))
+ {
+ // The range is still a multi-line range, and is already in the correct set.
+ return;
}
+
+ if(m_allRanges.contains(range))
+ removeRange(range);
+
+ if(isSingleLine)
+ {
+ // The range is contained by a single line, put it into the line-cache
+ int lineOffset = startLine - m_startLine;
+ if(m_cachedRangesForLine.size() <= lineOffset)
+ m_cachedRangesForLine.resize(lineOffset+1);
+
+ m_cachedRangesForLine[lineOffset].insert(range);
+ m_cachedLineForRanges[range] = lineOffset;
+ }else{
+ // The range cannot be cached per line, as it spans multiple lines
+ m_uncachedRanges.insert(range);
+ }
+
+ m_allRanges.insert(range);
+}
+
+void TextBlock::removeRange(TextRange* range)
+{
+ Q_ASSERT(m_allRanges.contains(range));
+ m_allRanges.remove(range);
+ if(m_uncachedRanges.contains(range))
+ {
+ Q_ASSERT(!m_cachedLineForRanges.contains(range));
+ m_uncachedRanges.remove(range);
+ }else{
+ Q_ASSERT(!m_uncachedRanges.contains(range));
+ QMap<TextRange*, int>::iterator it = m_cachedLineForRanges.find(range);
+ Q_ASSERT(it != m_cachedLineForRanges.end());
+ Q_ASSERT(m_cachedRangesForLine[*it].contains(range));
+ m_cachedRangesForLine[*it].remove(range);
+ m_cachedLineForRanges.erase(it);
+ }
+}
+
+}
--- trunk/KDE/kdelibs/kate/buffer/katetextblock.h #1152788:1152789
@@ -155,6 +155,22 @@
*/
void clearBlockContent (TextBlock *targetBlock);
+ void updateRange(TextRange* range);
+
+ void removeRange(TextRange* range);
+
+ QSet<TextRange*> cachedRangesForLine(int line) {
+ line -= m_startLine;
+ if(line >= 0 && line < m_cachedRangesForLine.size())
+ return m_cachedRangesForLine[line];
+ else
+ return QSet<TextRange*>();
+ }
+
+ QList<QSet<TextRange*> > allRangesIntersectingLine(int line) {
+ return QList<QSet<TextRange*> >() << m_uncachedRanges << \
cachedRangesForLine(line); + }
+
private:
/**
* parent text buffer
@@ -177,11 +193,28 @@
QSet<TextCursor *> m_cursors;
/**
+ * Contains for each line-offset the ranges that were cached into it.
+ * These ranges are fully contained by the line.
+ */
+ QVector<QSet<TextRange*> > m_cachedRangesForLine;
+
+ /**
+ * Maps for each cached range the line into which the range was cached.
+ */
+ QMap<TextRange*, int> m_cachedLineForRanges;
+
+ /**
+ * This contains all the ranges that are not cached.
+ */
+ QSet<TextRange*> m_uncachedRanges;
+ /**
* Set of ranges spanning this block or being contained in it.
* This is used for fast lookup of ranges.
* Only expensive for ranges spanning many blocks, which are rare, beside \
selection. + *
+ * This set always equals the sum of the uncached and the cached ranges.
*/
- QSet<TextRange *> m_ranges;
+ QSet<TextRange *> m_allRanges;
};
}
--- trunk/KDE/kdelibs/kate/buffer/katetextbuffer.cpp #1152788:1152789
@@ -732,10 +732,11 @@
const int blockIndex = blockForLine (line);
// get the ranges of the right block
- const QSet<TextRange *> &ranges = m_blocks[blockIndex]->m_ranges;
- // collect the right ones
QList<TextRange *> rightRanges;
+
+ foreach(const QSet<TextRange *> &ranges, \
m_blocks[blockIndex]->allRangesIntersectingLine(line)) + {
foreach (TextRange * const range, ranges) {
/**
* we want only ranges with attributes, but this one has none
@@ -761,6 +762,7 @@
if (range->startInternal().lineInternal() <= line && line <= \
range->endInternal().lineInternal()) rightRanges.append (range);
}
+ }
// return right ranges
return rightRanges;
--- trunk/KDE/kdelibs/kate/buffer/katetextrange.cpp #1152788:1152789
@@ -227,9 +227,9 @@
// either insert or remove range
if ((endLine < block->startLine()) || (startLine >= (block->startLine() + \
block->lines())))
- block->m_ranges.remove (this);
+ block->removeRange (this);
else
- block->m_ranges.insert (this);
+ block->updateRange (this);
// ok, reached end block
if (endLineMax < (block->startLine() + block->lines()))
_______________________________________________
KWrite-Devel mailing list
KWrite-Devel@kde.org
https://mail.kde.org/mailman/listinfo/kwrite-devel
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic