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

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

Issue 2755013004: Improve how DocumentMarkerController updates markers in response to text edits (Closed)
Patch Set: Rebase 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 161 matching lines...) Expand 10 before | Expand all | Expand 10 after
172 TextIterator marked_text(range.StartPosition(), range.EndPosition()); 172 TextIterator marked_text(range.StartPosition(), range.EndPosition());
173 DocumentMarkerController::RemoveMarkers( 173 DocumentMarkerController::RemoveMarkers(
174 marked_text, marker_types, should_remove_partially_overlapping_marker); 174 marked_text, marker_types, should_remove_partially_overlapping_marker);
175 } 175 }
176 176
177 static bool StartsFurther(const Member<RenderedDocumentMarker>& lhv, 177 static bool StartsFurther(const Member<RenderedDocumentMarker>& lhv,
178 const DocumentMarker* rhv) { 178 const DocumentMarker* rhv) {
179 return lhv->StartOffset() < rhv->StartOffset(); 179 return lhv->StartOffset() < rhv->StartOffset();
180 } 180 }
181 181
182 static bool StartsAfter(const Member<RenderedDocumentMarker>& marker,
183 size_t start_offset) {
184 return marker->StartOffset() < start_offset;
185 }
186
187 static bool EndsBefore(size_t start_offset, 182 static bool EndsBefore(size_t start_offset,
188 const Member<RenderedDocumentMarker>& rhv) { 183 const Member<RenderedDocumentMarker>& rhv) {
189 return start_offset < rhv->EndOffset(); 184 return start_offset < rhv->EndOffset();
190 } 185 }
191 186
192 static bool CompareByStart(const Member<DocumentMarker>& lhv, 187 static bool CompareByStart(const Member<DocumentMarker>& lhv,
193 const Member<DocumentMarker>& rhv) { 188 const Member<DocumentMarker>& rhv) {
194 return lhv->StartOffset() < rhv->StartOffset(); 189 return lhv->StartOffset() < rhv->StartOffset();
195 } 190 }
196 191
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
296 291
297 if (!PossiblyHasMarkers(DocumentMarker::AllMarkers())) 292 if (!PossiblyHasMarkers(DocumentMarker::AllMarkers()))
298 return; 293 return;
299 DCHECK(!markers_.IsEmpty()); 294 DCHECK(!markers_.IsEmpty());
300 295
301 MarkerLists* markers = markers_.at(src_node); 296 MarkerLists* markers = markers_.at(src_node);
302 if (!markers) 297 if (!markers)
303 return; 298 return;
304 299
305 bool doc_dirty = false; 300 bool doc_dirty = false;
306 for (size_t marker_list_index = 0; 301 for (Member<MarkerList> list : *markers) {
307 marker_list_index < DocumentMarker::kMarkerTypeIndexesCount;
308 ++marker_list_index) {
309 Member<MarkerList>& list = (*markers)[marker_list_index];
310 if (!list) 302 if (!list)
311 continue; 303 continue;
312 304
313 unsigned end_offset = length - 1; 305 unsigned end_offset = length - 1;
314 MarkerList::iterator it; 306 MarkerList::iterator it;
315 for (it = list->begin(); it != list->end(); ++it) { 307 for (it = list->begin(); it != list->end(); ++it) {
316 DocumentMarker* marker = it->Get(); 308 DocumentMarker* marker = it->Get();
317 309
318 // stop if we are now past the specified range 310 // stop if we are now past the specified range
319 if (marker->StartOffset() > end_offset) 311 if (marker->StartOffset() > end_offset)
(...skipping 403 matching lines...) Expand 10 before | Expand all | Expand 10 after
723 // cause the node to be redrawn 715 // cause the node to be redrawn
724 if (LayoutObject* layout_object = node->GetLayoutObject()) { 716 if (LayoutObject* layout_object = node->GetLayoutObject()) {
725 layout_object->SetShouldDoFullPaintInvalidation( 717 layout_object->SetShouldDoFullPaintInvalidation(
726 kPaintInvalidationDocumentMarkerChange); 718 kPaintInvalidationDocumentMarkerChange);
727 break; 719 break;
728 } 720 }
729 } 721 }
730 } 722 }
731 } 723 }
732 724
733 void DocumentMarkerController::ShiftMarkers(Node* node,
734 unsigned start_offset,
735 int delta) {
736 if (!PossiblyHasMarkers(DocumentMarker::AllMarkers()))
737 return;
738 DCHECK(!markers_.IsEmpty());
739
740 MarkerLists* markers = markers_.at(node);
741 if (!markers)
742 return;
743
744 bool did_shift_marker = false;
745 for (size_t marker_list_index = 0;
746 marker_list_index < DocumentMarker::kMarkerTypeIndexesCount;
747 ++marker_list_index) {
748 Member<MarkerList>& list = (*markers)[marker_list_index];
749 if (!list)
750 continue;
751 MarkerList::iterator start_pos =
752 std::lower_bound(list->begin(), list->end(), start_offset, StartsAfter);
753 for (MarkerList::iterator marker = start_pos; marker != list->end();
754 ++marker) {
755 #if DCHECK_IS_ON()
756 int start_offset = (*marker)->StartOffset();
757 DCHECK_GE(start_offset + delta, 0);
758 #endif
759 (*marker)->ShiftOffsets(delta);
760 did_shift_marker = true;
761 }
762 }
763
764 if (did_shift_marker) {
765 InvalidateRectsForMarkersInNode(*node);
766 // repaint the affected node
767 if (node->GetLayoutObject()) {
768 node->GetLayoutObject()->SetShouldDoFullPaintInvalidation(
769 kPaintInvalidationDocumentMarkerChange);
770 }
771 }
772 }
773
774 bool DocumentMarkerController::SetMarkersActive(const EphemeralRange& range, 725 bool DocumentMarkerController::SetMarkersActive(const EphemeralRange& range,
775 bool active) { 726 bool active) {
776 if (!PossiblyHasMarkers(DocumentMarker::AllMarkers())) 727 if (!PossiblyHasMarkers(DocumentMarker::AllMarkers()))
777 return false; 728 return false;
778 729
779 DCHECK(!markers_.IsEmpty()); 730 DCHECK(!markers_.IsEmpty());
780 731
781 Node* const start_container = range.StartPosition().ComputeContainerNode(); 732 Node* const start_container = range.StartPosition().ComputeContainerNode();
782 DCHECK(start_container); 733 DCHECK(start_container);
783 Node* const end_container = range.EndPosition().ComputeContainerNode(); 734 Node* const end_container = range.EndPosition().ComputeContainerNode();
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
863 LOG(INFO) << markers_.size() << " nodes have markers:\n" 814 LOG(INFO) << markers_.size() << " nodes have markers:\n"
864 << builder.ToString().Utf8().Data(); 815 << builder.ToString().Utf8().Data();
865 } 816 }
866 #endif 817 #endif
867 818
868 // SynchronousMutationObserver 819 // SynchronousMutationObserver
869 void DocumentMarkerController::DidUpdateCharacterData(CharacterData* node, 820 void DocumentMarkerController::DidUpdateCharacterData(CharacterData* node,
870 unsigned offset, 821 unsigned offset,
871 unsigned old_length, 822 unsigned old_length,
872 unsigned new_length) { 823 unsigned new_length) {
873 // Shift markers as if we first remove the old text, then insert the new text 824 if (!PossiblyHasMarkers(DocumentMarker::AllMarkers()))
874 RemoveMarkers(node, offset, old_length); 825 return;
875 ShiftMarkers(node, offset + old_length, 0 - old_length); 826 DCHECK(!markers_.IsEmpty());
876 ShiftMarkers(node, offset, new_length); 827
828 MarkerLists* markers = markers_.at(node);
829 if (!markers)
830 return;
831
832 bool did_shift_marker = false;
833 for (MarkerList* list : *markers) {
834 if (!list)
835 continue;
836
837 for (MarkerList::iterator it = list->begin(); it != list->end(); ++it) {
838 RenderedDocumentMarker& marker = **it;
839 Optional<DocumentMarker::MarkerOffsets> result =
840 marker.ComputeOffsetsAfterShift(offset, old_length, new_length);
841 if (result == WTF::kNullopt) {
842 list->erase(it - list->begin());
843 --it;
844 did_shift_marker = true;
845 continue;
846 }
847
848 if (marker.StartOffset() != result.value().start_offset ||
849 marker.EndOffset() != result.value().end_offset) {
850 did_shift_marker = true;
851 marker.SetStartOffset(result.value().start_offset);
852 marker.SetEndOffset(result.value().end_offset);
853 }
854 }
855 }
856
857 if (!did_shift_marker)
858 return;
859 if (!node->GetLayoutObject())
860 return;
861 InvalidateRectsForMarkersInNode(*node);
862 // repaint the affected node
863 node->GetLayoutObject()->SetShouldDoFullPaintInvalidation();
877 } 864 }
878 865
879 } // namespace blink 866 } // namespace blink
880 867
881 #ifndef NDEBUG 868 #ifndef NDEBUG
882 void showDocumentMarkers(const blink::DocumentMarkerController* controller) { 869 void showDocumentMarkers(const blink::DocumentMarkerController* controller) {
883 if (controller) 870 if (controller)
884 controller->ShowMarkers(); 871 controller->ShowMarkers();
885 } 872 }
886 #endif 873 #endif
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698