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

Unified Diff: third_party/WebKit/Source/core/editing/markers/DocumentMarkerController.cpp

Issue 2692093003: Rewrite DocumentMarkerController to use SynchronousMutationObserver (Closed)
Patch Set: Don't try to use -1 as default value for unsigned int Created 3 years, 10 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
Index: third_party/WebKit/Source/core/editing/markers/DocumentMarkerController.cpp
diff --git a/third_party/WebKit/Source/core/editing/markers/DocumentMarkerController.cpp b/third_party/WebKit/Source/core/editing/markers/DocumentMarkerController.cpp
index 41afe11c85185d22f509ddc551141887d1ae33c5..987f73f5546fb15ec77b757743b3060fc39a891c 100644
--- a/third_party/WebKit/Source/core/editing/markers/DocumentMarkerController.cpp
+++ b/third_party/WebKit/Source/core/editing/markers/DocumentMarkerController.cpp
@@ -84,8 +84,10 @@ inline bool DocumentMarkerController::possiblyHasMarkers(
return m_possiblyExistingMarkerTypes.intersects(types);
}
-DocumentMarkerController::DocumentMarkerController(const Document& document)
- : m_possiblyExistingMarkerTypes(0), m_document(&document) {}
+DocumentMarkerController::DocumentMarkerController(Document& document)
+ : m_possiblyExistingMarkerTypes(0), m_document(&document) {
+ setContext(&document);
+}
void DocumentMarkerController::clear() {
m_markers.clear();
@@ -178,11 +180,6 @@ static bool startsFurther(const Member<RenderedDocumentMarker>& lhv,
return lhv->startOffset() < rhv->startOffset();
}
-static bool startsAfter(const Member<RenderedDocumentMarker>& marker,
- size_t startOffset) {
- return marker->startOffset() < startOffset;
-}
-
static bool endsBefore(size_t startOffset,
const Member<RenderedDocumentMarker>& rhv) {
return startOffset < rhv->endOffset();
@@ -588,6 +585,7 @@ void DocumentMarkerController::invalidateRectsForAllMarkers() {
DEFINE_TRACE(DocumentMarkerController) {
visitor->trace(m_markers);
visitor->trace(m_document);
+ SynchronousMutationObserver::trace(visitor);
}
void DocumentMarkerController::removeMarkers(
@@ -697,6 +695,30 @@ void DocumentMarkerController::removeMarkersFromList(
}
}
+void DocumentMarkerController::removeZeroLengthMarkers() {
+ for (auto& nodeMarkers : m_markers) {
+ const Node& node = *nodeMarkers.key;
+ MarkerLists& markers = *nodeMarkers.value;
+ for (size_t markerListIndex = 0;
+ markerListIndex < DocumentMarker::MarkerTypeIndexesCount;
+ ++markerListIndex) {
+ Member<MarkerList>& list = markers[markerListIndex];
+ if (!list)
+ continue;
+ bool removedMarkers = false;
+ for (size_t j = list->size(); j > 0; --j) {
+ if (list->at(j - 1)->startOffset() == list->at(j - 1)->endOffset()) {
+ list->remove(j - 1);
+ removedMarkers = true;
+ }
+ }
+ if (removedMarkers &&
+ markerListIndex == DocumentMarker::TextMatchMarkerIndex)
+ invalidatePaintForTickmarks(node);
+ }
+ }
+}
+
void DocumentMarkerController::repaintMarkers(
DocumentMarker::MarkerTypes markerTypes) {
if (!possiblyHasMarkers(markerTypes))
@@ -728,8 +750,20 @@ void DocumentMarkerController::repaintMarkers(
}
void DocumentMarkerController::shiftMarkers(Node* node,
yosin_UTC9 2017/02/15 02:23:25 Let's make this function as didUpdateCharacterData
- unsigned startOffset,
- int delta) {
+ int startOffset,
+ int prevLength,
+ int newLength) {
+ DCHECK_GE(startOffset, 0);
+ DCHECK_GE(prevLength, 0);
+ DCHECK_GE(newLength, 0);
+
+ // If we're doing a pure remove operation, remove the markers in the range
+ // being removed (markers containing, but larger than, the range, will be
+ // split)
+ if (newLength == 0) {
+ removeMarkers(node, startOffset, prevLength);
+ }
+
if (!possiblyHasMarkers(DocumentMarker::AllMarkers()))
return;
DCHECK(!m_markers.isEmpty());
@@ -745,20 +779,56 @@ void DocumentMarkerController::shiftMarkers(Node* node,
Member<MarkerList>& list = (*markers)[markerListIndex];
if (!list)
continue;
- MarkerList::iterator startPos =
- std::lower_bound(list->begin(), list->end(), startOffset, startsAfter);
- for (MarkerList::iterator marker = startPos; marker != list->end();
+
+ for (MarkerList::iterator marker = list->begin(); marker != list->end();
++marker) {
-#if DCHECK_IS_ON()
- int startOffset = (*marker)->startOffset();
- DCHECK_GE(startOffset + delta, 0);
-#endif
- (*marker)->shiftOffsets(delta);
+ // if marker is contained by but not equal to the replaced range, remove
+ // the marker
+ if (((unsigned)startOffset <= (*marker)->startOffset() &&
+ (*marker)->endOffset() < (unsigned)(startOffset + prevLength)) ||
+ ((unsigned)startOffset < (*marker)->startOffset() &&
+ (*marker)->endOffset() <= (unsigned)(startOffset + prevLength))) {
+ list->remove(marker - list->begin());
+ marker--;
+ continue;
+ }
+
+ // algorithm inspired by https://dom.spec.whatwg.org/#concept-cd-replace
+ // but with some changes
+ if ((*marker)->startOffset() > (unsigned)startOffset) {
+ // Deviation from the concept-cd-replace algorithm: < instead of <= in
+ // the next line
+ if ((*marker)->startOffset() < (unsigned)(startOffset + prevLength)) {
+ // Marker start was in the replaced text. Move to beginning of new
+ // text
+ (*marker)->setStartOffset(startOffset);
+ } else {
+ // Marker start was after the replaced text. Shift by length
+ // difference
+ unsigned oldStartOffset = (*marker)->startOffset();
+ (*marker)->setStartOffset(oldStartOffset + newLength - prevLength);
+ }
+ }
+
+ if ((*marker)->endOffset() > (unsigned)startOffset) {
+ // Deviation from the concept-cd-replace algorithm: < instead of <= in
+ // the next line
+ if ((*marker)->endOffset() < (unsigned)(startOffset + prevLength)) {
+ // Marker end was in the replaced text. Move to beginning of new text
+ (*marker)->setEndOffset(startOffset);
+ } else {
+ // Marker end was after the replaced text. Shift by length difference
+ unsigned oldEndOffset = (*marker)->endOffset();
+ (*marker)->setEndOffset(oldEndOffset + newLength - prevLength);
+ }
+ }
+
didShiftMarker = true;
}
}
if (didShiftMarker) {
+ removeZeroLengthMarkers();
invalidateRectsForMarkersInNode(*node);
// repaint the affected node
if (node->layoutObject())
@@ -858,6 +928,14 @@ void DocumentMarkerController::showMarkers() const {
}
#endif
+// SynchronousMutationObserver
+void DocumentMarkerController::didUpdateCharacterData(CharacterData* node,
+ unsigned offset,
+ unsigned oldLength,
+ unsigned newLength) {
+ shiftMarkers(node, offset, oldLength, newLength);
+}
+
} // namespace blink
#ifndef NDEBUG

Powered by Google App Engine
This is Rietveld 408576698