Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(641)

Unified Diff: Source/core/dom/DocumentMarkerController.cpp

Issue 23728006: addMarker() optimizations. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « Source/core/dom/DocumentMarkerController.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: Source/core/dom/DocumentMarkerController.cpp
diff --git a/Source/core/dom/DocumentMarkerController.cpp b/Source/core/dom/DocumentMarkerController.cpp
index 0682b64d971844063c2305a976fcfb79acb7c53b..659d292b96107417202500ef698b2b0ba5d54cab 100644
--- a/Source/core/dom/DocumentMarkerController.cpp
+++ b/Source/core/dom/DocumentMarkerController.cpp
@@ -133,6 +133,16 @@ void DocumentMarkerController::removeMarkers(Range* range, DocumentMarker::Marke
}
}
+static bool startsFurther(const DocumentMarker& lhv, const DocumentMarker& rhv)
groby-ooo-7-16 2013/09/13 18:05:48 Chromium preference is putting helper functions in
tony 2013/09/13 18:18:49 Most blink code uses static functions, but I don't
+{
+ return lhv.startOffset() < rhv.startOffset();
+}
+
+static bool doesNotOverlap(const DocumentMarker& lhv, const DocumentMarker& rhv)
groby-ooo-7-16 2013/09/17 11:52:42 I just woke up at 4am to realize this does not wor
pstanek 2013/09/17 12:46:30 I thought about the same but I convinced myself it
groby-ooo-7-16 2013/09/17 14:20:26 Do-while is fine - but in line 194, you use doesNo
pstanek 2013/09/17 14:48:05 But with lower_bound() we find the first overlappi
groby-ooo-7-16 2013/09/17 17:14:09 Yes, but the vector is unsorted with respect to en
pstanek 2013/09/17 17:30:41 Ah :/ On 2013/09/17 17:14:09, groby wrote:
pstanek 2013/09/17 17:39:45 Then to make this efficient markers would have to
groby-ooo-7-16 2013/09/17 18:39:37 Separating them by type would certainly be helpful
pstanek 2013/09/18 10:49:46 Yes. The assumptions seem to be right but I fear u
groby-ooo-7-16 2013/09/18 18:24:08 Postponing this seems fine to me. (If you do, you
+{
+ return lhv.endOffset() < rhv.startOffset();
+}
+
// Markers are stored in order sorted by their start offset.
// Markers of the same type do not overlap each other.
@@ -151,42 +161,19 @@ void DocumentMarkerController::addMarker(Node* node, const DocumentMarker& newMa
list->append(RenderedDocumentMarker(newMarker));
} else {
RenderedDocumentMarker toInsert(newMarker);
- size_t numMarkers = list->size();
- size_t i;
- // Iterate over all markers whose start offset is less than or equal to the new marker's.
- // If one of them is of the same type as the new marker and touches it or intersects with it
- // (there is at most one), remove it and adjust the new marker's start offset to encompass it.
- for (i = 0; i < numMarkers; ++i) {
- DocumentMarker marker = list->at(i);
- if (marker.startOffset() > toInsert.startOffset())
- break;
- if (marker.type() == toInsert.type() && marker.type() != DocumentMarker::TextMatch && marker.endOffset() >= toInsert.startOffset()) {
- toInsert.setStartOffset(marker.startOffset());
- list->remove(i);
- numMarkers--;
- break;
+ if (list->last().endOffset() >= newMarker.startOffset()) {
groby-ooo-7-16 2013/09/13 18:05:48 Isn't that covered by lower_bound already?
pstanek 2013/09/14 08:18:50 Yes, but the point was to avoid searching if no me
groby-ooo-7-16 2013/09/17 02:23:47 You probably want '>', though. if last.end == new.
pstanek 2013/09/17 13:54:00 But this if controls entering merging block so we'
groby-ooo-7-16 2013/09/17 14:34:41 Sigh. I misread that, sorry. Done. On 2013/09/17
+ if (toInsert.type() != DocumentMarker::TextMatch) {
+ mergeOverlapping(list.get(), toInsert);
+ } else {
+ MarkerList::iterator pos = std::lower_bound(list->begin(), list->end(), toInsert, startsFurther);
+ if (pos != list->end())
groby-ooo-7-16 2013/09/13 18:05:48 AFAIK, insert works for pos == list->end()-list->b
pstanek 2013/09/17 16:57:00 Done.
+ list->insert(pos - list->begin(), RenderedDocumentMarker(toInsert));
+ else
+ list->append(RenderedDocumentMarker(toInsert));
}
+ } else {
+ list->append(RenderedDocumentMarker(toInsert));
}
- size_t j = i;
- // Iterate over all markers whose end offset is less than or equal to the new marker's,
- // removing markers of the same type as the new marker which touch it or intersect with it,
- // adjusting the new marker's end offset to cover them if necessary.
- while (j < numMarkers) {
- DocumentMarker marker = list->at(j);
- if (marker.startOffset() > toInsert.endOffset())
- break;
- if (marker.type() == toInsert.type() && marker.type() != DocumentMarker::TextMatch) {
- list->remove(j);
- if (toInsert.endOffset() <= marker.endOffset()) {
- toInsert.setEndOffset(marker.endOffset());
- break;
- }
- numMarkers--;
- } else
- j++;
- }
- // At this point i points to the node before which we want to insert.
- list->insert(i, RenderedDocumentMarker(toInsert));
}
// repaint the affected node
@@ -194,6 +181,51 @@ void DocumentMarkerController::addMarker(Node* node, const DocumentMarker& newMa
node->renderer()->repaint();
}
+void DocumentMarkerController::mergeOverlapping(MarkerList* list, DocumentMarker& toInsert)
groby-ooo-7-16 2013/09/13 18:05:48 I think this can be simplified - find the first ov
pstanek 2013/09/14 08:18:50 This is exactly what it does. upper_bound is used
groby-ooo-7-16 2013/09/17 02:23:47 Caveat:I might be missing something and all this m
pstanek 2013/09/17 16:20:38 I'll try to combine your approach with the origina
pstanek 2013/09/17 16:57:00 Done. (at least partially)
+{
+ // Iterate over all markers whose start offset is less than or equal to the new marker's.
+ // If one of them is of the same type as the new marker and touches it or intersects with it
+ // (there is at most one), remove it and adjust the new marker's start offset to encompass it.
+ size_t numMarkers = list->size();
+ MarkerList::iterator end = std::upper_bound(list->begin(), list->end(), toInsert, startsFurther);
+ MarkerList::iterator overlapping = list->begin();
+ size_t offset = 0;
+ do {
+ overlapping = std::lower_bound(overlapping + offset, end, toInsert, doesNotOverlap);
+ offset = 1;
+ } while (overlapping != end && overlapping->type() != toInsert.type());
+
+ size_t index = numMarkers;
+ if (overlapping != list->end())
+ index = overlapping - list->begin();
+ if (overlapping != end) {
+ toInsert.setStartOffset(overlapping->startOffset());
+ list->remove(index);
+ --numMarkers;
+ }
+
+ // Iterate over all markers whose end offset is less than or equal to the new marker's,
+ // removing markers of the same type as the new marker which touch it or intersect with it,
+ // adjusting the new marker's end offset to cover them if necessary.
+ for (size_t i = index; i < numMarkers;) {
+ DocumentMarker marker = list->at(i);
groby-ooo-7-16 2013/09/17 02:23:47 Calling at() will bounds-check each element - iter
pstanek 2013/09/17 16:57:00 Done.
+ if (marker.startOffset() > toInsert.endOffset())
+ break;
+ if (marker.type() == toInsert.type()) {
+ list->remove(i);
+ if (toInsert.endOffset() <= marker.endOffset()) {
+ toInsert.setEndOffset(marker.endOffset());
+ break;
groby-ooo-7-16 2013/09/17 02:23:47 Why break here? Couldn't we potentially have more
pstanek 2013/09/17 16:57:00 Done.
+ }
+ --numMarkers;
+ } else {
+ ++i;
+ }
+ }
+ // At this point index points to the node before which we want to insert.
+ list->insert(index, RenderedDocumentMarker(toInsert));
+}
+
// copies markers from srcNode to dstNode, applying the specified shift delta to the copies. The shift is
// useful if, e.g., the caller has created the dstNode from a non-prefix substring of the srcNode.
void DocumentMarkerController::copyMarkers(Node* srcNode, unsigned startOffset, int length, Node* dstNode, int delta)
« no previous file with comments | « Source/core/dom/DocumentMarkerController.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698