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

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

Issue 2806683002: Don't ever split DocumentMarkers on remove (Closed)
Patch Set: Leave partial markers in place for non-splitting case, preserve endpoints for splitting case Created 3 years, 8 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 unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 1999 Antti Koivisto (koivisto@kde.org) 3 * (C) 1999 Antti Koivisto (koivisto@kde.org)
4 * (C) 2001 Dirk Mueller (mueller@kde.org) 4 * (C) 2001 Dirk Mueller (mueller@kde.org)
5 * (C) 2006 Alexey Proskuryakov (ap@webkit.org) 5 * (C) 2006 Alexey Proskuryakov (ap@webkit.org)
6 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights 6 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights
7 * reserved. 7 * reserved.
8 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. 8 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved.
9 * (http://www.torchmobile.com/) 9 * (http://www.torchmobile.com/)
10 * Copyright (C) Research In Motion Limited 2010. All rights reserved. 10 * Copyright (C) Research In Motion Limited 2010. All rights reserved.
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
139 markedText.endOffsetInCurrentContainer(), 139 markedText.endOffsetInCurrentContainer(),
140 underlineColor, thick, backgroundColor)); 140 underlineColor, thick, backgroundColor));
141 } 141 }
142 142
143 void DocumentMarkerController::prepareForDestruction() { 143 void DocumentMarkerController::prepareForDestruction() {
144 clear(); 144 clear();
145 } 145 }
146 146
147 void DocumentMarkerController::removeMarkers( 147 void DocumentMarkerController::removeMarkers(
148 TextIterator& markedText, 148 TextIterator& markedText,
149 DocumentMarker::MarkerTypes markerTypes, 149 DocumentMarker::MarkerTypes markerTypes) {
150 RemovePartiallyOverlappingMarkerOrNot
151 shouldRemovePartiallyOverlappingMarker) {
152 for (; !markedText.atEnd(); markedText.advance()) { 150 for (; !markedText.atEnd(); markedText.advance()) {
153 if (!possiblyHasMarkers(markerTypes)) 151 if (!possiblyHasMarkers(markerTypes))
154 return; 152 return;
155 DCHECK(!m_markers.isEmpty()); 153 DCHECK(!m_markers.isEmpty());
156 154
157 int startOffset = markedText.startOffsetInCurrentContainer(); 155 int startOffset = markedText.startOffsetInCurrentContainer();
158 int endOffset = markedText.endOffsetInCurrentContainer(); 156 int endOffset = markedText.endOffsetInCurrentContainer();
159 removeMarkers(markedText.currentContainer(), startOffset, 157 removeMarkers(markedText.currentContainer(), startOffset,
160 endOffset - startOffset, markerTypes, 158 endOffset - startOffset, markerTypes);
161 shouldRemovePartiallyOverlappingMarker);
162 } 159 }
163 } 160 }
164 161
165 void DocumentMarkerController::removeMarkers( 162 void DocumentMarkerController::removeMarkers(
166 const EphemeralRange& range, 163 const EphemeralRange& range,
167 DocumentMarker::MarkerTypes markerTypes, 164 DocumentMarker::MarkerTypes markerTypes) {
168 RemovePartiallyOverlappingMarkerOrNot
169 shouldRemovePartiallyOverlappingMarker) {
170 DCHECK(!m_document->needsLayoutTreeUpdate()); 165 DCHECK(!m_document->needsLayoutTreeUpdate());
171 166
172 TextIterator markedText(range.startPosition(), range.endPosition()); 167 TextIterator markedText(range.startPosition(), range.endPosition());
173 DocumentMarkerController::removeMarkers( 168 DocumentMarkerController::removeMarkers(markedText, markerTypes);
174 markedText, markerTypes, shouldRemovePartiallyOverlappingMarker);
175 } 169 }
176 170
177 static bool startsFurther(const Member<RenderedDocumentMarker>& lhv, 171 static bool startsFurther(const Member<RenderedDocumentMarker>& lhv,
178 const DocumentMarker* rhv) { 172 const DocumentMarker* rhv) {
179 return lhv->startOffset() < rhv->startOffset(); 173 return lhv->startOffset() < rhv->startOffset();
180 } 174 }
181 175
182 static bool endsBefore(size_t startOffset, 176 static bool endsBefore(size_t startOffset,
183 const Member<RenderedDocumentMarker>& rhv) { 177 const Member<RenderedDocumentMarker>& rhv) {
184 return startOffset < rhv->endOffset(); 178 return startOffset < rhv->endOffset();
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after
336 if (docDirty && dstNode->layoutObject()) { 330 if (docDirty && dstNode->layoutObject()) {
337 dstNode->layoutObject()->setShouldDoFullPaintInvalidation( 331 dstNode->layoutObject()->setShouldDoFullPaintInvalidation(
338 PaintInvalidationDocumentMarkerChange); 332 PaintInvalidationDocumentMarkerChange);
339 } 333 }
340 } 334 }
341 335
342 void DocumentMarkerController::removeMarkers( 336 void DocumentMarkerController::removeMarkers(
343 Node* node, 337 Node* node,
344 unsigned startOffset, 338 unsigned startOffset,
345 int length, 339 int length,
346 DocumentMarker::MarkerTypes markerTypes, 340 DocumentMarker::MarkerTypes markerTypes) {
347 RemovePartiallyOverlappingMarkerOrNot
348 shouldRemovePartiallyOverlappingMarker) {
349 if (length <= 0) 341 if (length <= 0)
350 return; 342 return;
351 343
352 if (!possiblyHasMarkers(markerTypes)) 344 if (!possiblyHasMarkers(markerTypes))
353 return; 345 return;
354 DCHECK(!(m_markers.isEmpty())); 346 DCHECK(!(m_markers.isEmpty()));
355 347
356 MarkerLists* markers = m_markers.at(node); 348 MarkerLists* markers = m_markers.at(node);
357 if (!markers) 349 if (!markers)
358 return; 350 return;
(...skipping 16 matching lines...) Expand all
375 MarkerList::iterator startPos = 367 MarkerList::iterator startPos =
376 std::upper_bound(list->begin(), list->end(), startOffset, endsBefore); 368 std::upper_bound(list->begin(), list->end(), startOffset, endsBefore);
377 for (MarkerList::iterator i = startPos; i != list->end();) { 369 for (MarkerList::iterator i = startPos; i != list->end();) {
378 DocumentMarker marker(*i->get()); 370 DocumentMarker marker(*i->get());
379 371
380 // markers are returned in order, so stop if we are now past the specified 372 // markers are returned in order, so stop if we are now past the specified
381 // range 373 // range
382 if (marker.startOffset() >= endOffset) 374 if (marker.startOffset() >= endOffset)
383 break; 375 break;
384 376
385 // at this point we know that marker and target intersect in some way 377 list->erase(i - list->begin());
386 docDirty = true; 378 docDirty = true;
387
388 // pitch the old marker
389 list->erase(i - list->begin());
390
391 if (shouldRemovePartiallyOverlappingMarker) {
392 // Stop here. Don't add resulting slices back.
393 continue;
394 }
395
396 // add either of the resulting slices that are left after removing target
397 if (startOffset > marker.startOffset()) {
398 DocumentMarker newLeft = marker;
399 newLeft.setEndOffset(startOffset);
400 size_t insertIndex = i - list->begin();
401 list->insert(insertIndex, RenderedDocumentMarker::create(newLeft));
402 // Move to the marker after the inserted one.
403 i = list->begin() + insertIndex + 1;
404 }
405 if (marker.endOffset() > endOffset) {
406 DocumentMarker newRight = marker;
407 newRight.setStartOffset(endOffset);
408 size_t insertIndex = i - list->begin();
409 list->insert(insertIndex, RenderedDocumentMarker::create(newRight));
410 // Move to the marker after the inserted one.
411 i = list->begin() + insertIndex + 1;
412 }
413 } 379 }
414 380
415 if (list->isEmpty()) { 381 if (list->isEmpty()) {
416 list.clear(); 382 list.clear();
417 ++emptyListsCount; 383 ++emptyListsCount;
418 } 384 }
419 } 385 }
420 386
421 if (emptyListsCount == DocumentMarker::MarkerTypeIndexesCount) { 387 if (emptyListsCount == DocumentMarker::MarkerTypeIndexesCount) {
422 m_markers.erase(node); 388 m_markers.erase(node);
(...skipping 399 matching lines...) Expand 10 before | Expand all | Expand 10 after
822 LOG(INFO) << m_markers.size() << " nodes have markers:\n" 788 LOG(INFO) << m_markers.size() << " nodes have markers:\n"
823 << builder.toString().utf8().data(); 789 << builder.toString().utf8().data();
824 } 790 }
825 #endif 791 #endif
826 792
827 // SynchronousMutationObserver 793 // SynchronousMutationObserver
828 void DocumentMarkerController::didUpdateCharacterData(CharacterData* node, 794 void DocumentMarkerController::didUpdateCharacterData(CharacterData* node,
829 unsigned offset, 795 unsigned offset,
830 unsigned oldLength, 796 unsigned oldLength,
831 unsigned newLength) { 797 unsigned newLength) {
832 // If we're doing a pure remove operation, remove the markers in the range
Xiaocheng 2017/04/08 00:23:36 I see. But this change fits better in the previou
833 // being removed (markers containing, but larger than, the range, will be
834 // split)
835 if (newLength == 0)
836 removeMarkers(node, offset, oldLength);
837
838 if (!possiblyHasMarkers(DocumentMarker::AllMarkers())) 798 if (!possiblyHasMarkers(DocumentMarker::AllMarkers()))
839 return; 799 return;
840 DCHECK(!m_markers.isEmpty()); 800 DCHECK(!m_markers.isEmpty());
841 801
842 MarkerLists* markers = m_markers.at(node); 802 MarkerLists* markers = m_markers.at(node);
843 if (!markers) 803 if (!markers)
844 return; 804 return;
845 805
846 bool didShiftMarker = false; 806 bool didShiftMarker = false;
847 for (MarkerList* list : *markers) { 807 for (MarkerList* list : *markers) {
(...skipping 30 matching lines...) Expand all
878 } 838 }
879 839
880 } // namespace blink 840 } // namespace blink
881 841
882 #ifndef NDEBUG 842 #ifndef NDEBUG
883 void showDocumentMarkers(const blink::DocumentMarkerController* controller) { 843 void showDocumentMarkers(const blink::DocumentMarkerController* controller) {
884 if (controller) 844 if (controller)
885 controller->showMarkers(); 845 controller->showMarkers();
886 } 846 }
887 #endif 847 #endif
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698