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

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

Issue 2692093003: Rewrite DocumentMarkerController to use SynchronousMutationObserver (Closed)
Patch Set: Fix didShiftMarker assignment and remove removeZeroLengthMarkers() from header 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 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 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
77 return DocumentMarker::SpellingMarkerIndex; 77 return DocumentMarker::SpellingMarkerIndex;
78 } 78 }
79 79
80 } // namespace 80 } // namespace
81 81
82 inline bool DocumentMarkerController::possiblyHasMarkers( 82 inline bool DocumentMarkerController::possiblyHasMarkers(
83 DocumentMarker::MarkerTypes types) { 83 DocumentMarker::MarkerTypes types) {
84 return m_possiblyExistingMarkerTypes.intersects(types); 84 return m_possiblyExistingMarkerTypes.intersects(types);
85 } 85 }
86 86
87 DocumentMarkerController::DocumentMarkerController(const Document& document) 87 DocumentMarkerController::DocumentMarkerController(Document& document)
88 : m_possiblyExistingMarkerTypes(0), m_document(&document) {} 88 : m_possiblyExistingMarkerTypes(0), m_document(&document) {
89 setContext(&document);
90 }
89 91
90 void DocumentMarkerController::clear() { 92 void DocumentMarkerController::clear() {
91 m_markers.clear(); 93 m_markers.clear();
92 m_possiblyExistingMarkerTypes = 0; 94 m_possiblyExistingMarkerTypes = 0;
93 } 95 }
94 96
95 void DocumentMarkerController::addMarker(const Position& start, 97 void DocumentMarkerController::addMarker(const Position& start,
96 const Position& end, 98 const Position& end,
97 DocumentMarker::MarkerType type, 99 DocumentMarker::MarkerType type,
98 const String& description, 100 const String& description,
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
171 TextIterator markedText(range.startPosition(), range.endPosition()); 173 TextIterator markedText(range.startPosition(), range.endPosition());
172 DocumentMarkerController::removeMarkers( 174 DocumentMarkerController::removeMarkers(
173 markedText, markerTypes, shouldRemovePartiallyOverlappingMarker); 175 markedText, markerTypes, shouldRemovePartiallyOverlappingMarker);
174 } 176 }
175 177
176 static bool startsFurther(const Member<RenderedDocumentMarker>& lhv, 178 static bool startsFurther(const Member<RenderedDocumentMarker>& lhv,
177 const DocumentMarker* rhv) { 179 const DocumentMarker* rhv) {
178 return lhv->startOffset() < rhv->startOffset(); 180 return lhv->startOffset() < rhv->startOffset();
179 } 181 }
180 182
181 static bool startsAfter(const Member<RenderedDocumentMarker>& marker,
182 size_t startOffset) {
183 return marker->startOffset() < startOffset;
184 }
185
186 static bool endsBefore(size_t startOffset, 183 static bool endsBefore(size_t startOffset,
187 const Member<RenderedDocumentMarker>& rhv) { 184 const Member<RenderedDocumentMarker>& rhv) {
188 return startOffset < rhv->endOffset(); 185 return startOffset < rhv->endOffset();
189 } 186 }
190 187
191 static bool compareByStart(const Member<DocumentMarker>& lhv, 188 static bool compareByStart(const Member<DocumentMarker>& lhv,
192 const Member<DocumentMarker>& rhv) { 189 const Member<DocumentMarker>& rhv) {
193 return lhv->startOffset() < rhv->startOffset(); 190 return lhv->startOffset() < rhv->startOffset();
194 } 191 }
195 192
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
301 298
302 if (!possiblyHasMarkers(DocumentMarker::AllMarkers())) 299 if (!possiblyHasMarkers(DocumentMarker::AllMarkers()))
303 return; 300 return;
304 DCHECK(!m_markers.isEmpty()); 301 DCHECK(!m_markers.isEmpty());
305 302
306 MarkerLists* markers = m_markers.at(srcNode); 303 MarkerLists* markers = m_markers.at(srcNode);
307 if (!markers) 304 if (!markers)
308 return; 305 return;
309 306
310 bool docDirty = false; 307 bool docDirty = false;
311 for (size_t markerListIndex = 0; 308 for (Member<MarkerList> list : *markers) {
312 markerListIndex < DocumentMarker::MarkerTypeIndexesCount;
313 ++markerListIndex) {
314 Member<MarkerList>& list = (*markers)[markerListIndex];
315 if (!list) 309 if (!list)
316 continue; 310 continue;
317 311
318 unsigned endOffset = startOffset + length - 1; 312 unsigned endOffset = startOffset + length - 1;
319 MarkerList::iterator startPos = std::lower_bound( 313 MarkerList::iterator startPos = std::lower_bound(
320 list->begin(), list->end(), startOffset, doesNotInclude); 314 list->begin(), list->end(), startOffset, doesNotInclude);
321 for (MarkerList::iterator i = startPos; i != list->end(); ++i) { 315 for (MarkerList::iterator i = startPos; i != list->end(); ++i) {
322 DocumentMarker* marker = i->get(); 316 DocumentMarker* marker = i->get();
323 317
324 // stop if we are now past the specified range 318 // stop if we are now past the specified range
(...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after
581 575
582 if (markerList->front()->type() == DocumentMarker::TextMatch) 576 if (markerList->front()->type() == DocumentMarker::TextMatch)
583 invalidatePaintForTickmarks(node); 577 invalidatePaintForTickmarks(node);
584 } 578 }
585 } 579 }
586 } 580 }
587 581
588 DEFINE_TRACE(DocumentMarkerController) { 582 DEFINE_TRACE(DocumentMarkerController) {
589 visitor->trace(m_markers); 583 visitor->trace(m_markers);
590 visitor->trace(m_document); 584 visitor->trace(m_document);
585 SynchronousMutationObserver::trace(visitor);
591 } 586 }
592 587
593 void DocumentMarkerController::removeMarkers( 588 void DocumentMarkerController::removeMarkers(
594 Node* node, 589 Node* node,
595 DocumentMarker::MarkerTypes markerTypes) { 590 DocumentMarker::MarkerTypes markerTypes) {
596 if (!possiblyHasMarkers(markerTypes)) 591 if (!possiblyHasMarkers(markerTypes))
597 return; 592 return;
598 DCHECK(!m_markers.isEmpty()); 593 DCHECK(!m_markers.isEmpty());
599 594
600 MarkerMap::iterator iterator = m_markers.find(node); 595 MarkerMap::iterator iterator = m_markers.find(node);
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
720 715
721 // cause the node to be redrawn 716 // cause the node to be redrawn
722 if (LayoutObject* layoutObject = node->layoutObject()) { 717 if (LayoutObject* layoutObject = node->layoutObject()) {
723 layoutObject->setShouldDoFullPaintInvalidation(); 718 layoutObject->setShouldDoFullPaintInvalidation();
724 break; 719 break;
725 } 720 }
726 } 721 }
727 } 722 }
728 } 723 }
729 724
730 void DocumentMarkerController::shiftMarkers(Node* node,
731 unsigned startOffset,
732 int delta) {
733 if (!possiblyHasMarkers(DocumentMarker::AllMarkers()))
734 return;
735 DCHECK(!m_markers.isEmpty());
736
737 MarkerLists* markers = m_markers.at(node);
738 if (!markers)
739 return;
740
741 bool didShiftMarker = false;
742 for (size_t markerListIndex = 0;
743 markerListIndex < DocumentMarker::MarkerTypeIndexesCount;
744 ++markerListIndex) {
745 Member<MarkerList>& list = (*markers)[markerListIndex];
746 if (!list)
747 continue;
748 MarkerList::iterator startPos =
749 std::lower_bound(list->begin(), list->end(), startOffset, startsAfter);
750 for (MarkerList::iterator marker = startPos; marker != list->end();
751 ++marker) {
752 #if DCHECK_IS_ON()
753 int startOffset = (*marker)->startOffset();
754 DCHECK_GE(startOffset + delta, 0);
755 #endif
756 (*marker)->shiftOffsets(delta);
757 didShiftMarker = true;
758 }
759 }
760
761 if (didShiftMarker) {
762 invalidateRectsForMarkersInNode(*node);
763 // repaint the affected node
764 if (node->layoutObject())
765 node->layoutObject()->setShouldDoFullPaintInvalidation();
766 }
767 }
768
769 bool DocumentMarkerController::setMarkersActive(const EphemeralRange& range, 725 bool DocumentMarkerController::setMarkersActive(const EphemeralRange& range,
770 bool active) { 726 bool active) {
771 if (!possiblyHasMarkers(DocumentMarker::AllMarkers())) 727 if (!possiblyHasMarkers(DocumentMarker::AllMarkers()))
772 return false; 728 return false;
773 729
774 DCHECK(!m_markers.isEmpty()); 730 DCHECK(!m_markers.isEmpty());
775 731
776 Node* const startContainer = range.startPosition().computeContainerNode(); 732 Node* const startContainer = range.startPosition().computeContainerNode();
777 DCHECK(startContainer); 733 DCHECK(startContainer);
778 Node* const endContainer = range.endPosition().computeContainerNode(); 734 Node* const endContainer = range.endPosition().computeContainerNode();
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
851 builder.append(")"); 807 builder.append(")");
852 } 808 }
853 } 809 }
854 builder.append("\n"); 810 builder.append("\n");
855 } 811 }
856 LOG(INFO) << m_markers.size() << " nodes have markers:\n" 812 LOG(INFO) << m_markers.size() << " nodes have markers:\n"
857 << builder.toString().utf8().data(); 813 << builder.toString().utf8().data();
858 } 814 }
859 #endif 815 #endif
860 816
817 // SynchronousMutationObserver
818 void DocumentMarkerController::didUpdateCharacterData(CharacterData* node,
819 unsigned offset,
820 unsigned oldLength,
821 unsigned newLength) {
822 // If we're doing a pure remove operation, remove the markers in the range
823 // being removed (markers containing, but larger than, the range, will be
824 // split)
825 if (newLength == 0)
826 removeMarkers(node, offset, oldLength);
827
828 if (!possiblyHasMarkers(DocumentMarker::AllMarkers()))
829 return;
830 DCHECK(!m_markers.isEmpty());
831
832 MarkerLists* markers = m_markers.at(node);
833 if (!markers)
834 return;
835
836 bool didShiftMarker = false;
837 for (MarkerList* list : *markers) {
838 if (!list)
839 continue;
840
841 for (MarkerList::iterator marker = list->begin(); marker != list->end();
yosin_UTC9 2017/02/24 04:36:18 nit: s/marker/it/ or s/marker/marker_it/ since it
842 ++marker) {
843 // algorithm inspired by https://dom.spec.whatwg.org/#concept-cd-replace
844 // but with some changes
845 if ((*marker)->startOffset() > offset) {
846 // Deviation from the concept-cd-replace algorithm: < instead of <= in
847 // the next line
848 if ((*marker)->startOffset() < offset + oldLength) {
849 // Marker start was in the replaced text. Move to end of new text
850 // (Deviation from the concept-cd-replace algorithm: that algorithm
851 // would move to the beginning of the new text here)
852 (*marker)->setStartOffset(offset + newLength);
853 } else {
854 // Marker start was after the replaced text. Shift by length
855 // difference
856 unsigned oldStartOffset = (*marker)->startOffset();
857 (*marker)->setStartOffset(oldStartOffset + newLength - oldLength);
858 }
859 didShiftMarker = true;
860 }
861
862 if ((*marker)->endOffset() > offset) {
863 // Deviation from the concept-cd-replace algorithm: < instead of <= in
864 // the next line
865 if ((*marker)->endOffset() < offset + oldLength) {
866 // Marker end was in the replaced text. Move to beginning of new text
867 (*marker)->setEndOffset(offset);
868 } else {
869 // Marker end was after the replaced text. Shift by length difference
870 unsigned oldEndOffset = (*marker)->endOffset();
871 (*marker)->setEndOffset(oldEndOffset + newLength - oldLength);
872 }
873 didShiftMarker = true;
874 }
875
876 if ((*marker)->startOffset() >= (*marker)->endOffset()) {
877 list->remove(marker - list->begin());
878 --marker;
879 continue;
880 }
881 }
882 }
883
884 if (didShiftMarker) {
yosin_UTC9 2017/02/24 04:36:18 Let's use early-return style if (!didShiftMarker)
885 invalidateRectsForMarkersInNode(*node);
yosin_UTC9 2017/02/24 04:36:18 I think we don't need to call invalidateRectsForMa
886 // repaint the affected node
887 if (node->layoutObject())
888 node->layoutObject()->setShouldDoFullPaintInvalidation();
889 }
890 }
891
861 } // namespace blink 892 } // namespace blink
862 893
863 #ifndef NDEBUG 894 #ifndef NDEBUG
864 void showDocumentMarkers(const blink::DocumentMarkerController* controller) { 895 void showDocumentMarkers(const blink::DocumentMarkerController* controller) {
865 if (controller) 896 if (controller)
866 controller->showMarkers(); 897 controller->showMarkers();
867 } 898 }
868 #endif 899 #endif
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698