[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