OLD | NEW |
---|---|
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 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
170 TextIterator markedText(range.startPosition(), range.endPosition()); | 170 TextIterator markedText(range.startPosition(), range.endPosition()); |
171 DocumentMarkerController::removeMarkers( | 171 DocumentMarkerController::removeMarkers( |
172 markedText, markerTypes, shouldRemovePartiallyOverlappingMarker); | 172 markedText, markerTypes, shouldRemovePartiallyOverlappingMarker); |
173 } | 173 } |
174 | 174 |
175 static bool startsFurther(const Member<RenderedDocumentMarker>& lhv, | 175 static bool startsFurther(const Member<RenderedDocumentMarker>& lhv, |
176 const DocumentMarker* rhv) { | 176 const DocumentMarker* rhv) { |
177 return lhv->startOffset() < rhv->startOffset(); | 177 return lhv->startOffset() < rhv->startOffset(); |
178 } | 178 } |
179 | 179 |
180 static bool startsAfter(const Member<RenderedDocumentMarker>& marker, | |
181 size_t startOffset) { | |
182 return marker->startOffset() < startOffset; | |
183 } | |
184 | |
185 static bool endsBefore(size_t startOffset, | 180 static bool endsBefore(size_t startOffset, |
186 const Member<RenderedDocumentMarker>& rhv) { | 181 const Member<RenderedDocumentMarker>& rhv) { |
187 return startOffset < rhv->endOffset(); | 182 return startOffset < rhv->endOffset(); |
188 } | 183 } |
189 | 184 |
190 static bool compareByStart(const Member<DocumentMarker>& lhv, | 185 static bool compareByStart(const Member<DocumentMarker>& lhv, |
191 const Member<DocumentMarker>& rhv) { | 186 const Member<DocumentMarker>& rhv) { |
192 return lhv->startOffset() < rhv->startOffset(); | 187 return lhv->startOffset() < rhv->startOffset(); |
193 } | 188 } |
194 | 189 |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
302 | 297 |
303 if (!possiblyHasMarkers(DocumentMarker::AllMarkers())) | 298 if (!possiblyHasMarkers(DocumentMarker::AllMarkers())) |
304 return; | 299 return; |
305 DCHECK(!m_markers.isEmpty()); | 300 DCHECK(!m_markers.isEmpty()); |
306 | 301 |
307 MarkerLists* markers = m_markers.at(srcNode); | 302 MarkerLists* markers = m_markers.at(srcNode); |
308 if (!markers) | 303 if (!markers) |
309 return; | 304 return; |
310 | 305 |
311 bool docDirty = false; | 306 bool docDirty = false; |
312 for (size_t markerListIndex = 0; | 307 for (Member<MarkerList> list : *markers) { |
313 markerListIndex < DocumentMarker::MarkerTypeIndexesCount; | |
314 ++markerListIndex) { | |
315 Member<MarkerList>& list = (*markers)[markerListIndex]; | |
316 if (!list) | 308 if (!list) |
317 continue; | 309 continue; |
318 | 310 |
319 unsigned endOffset = startOffset + length - 1; | 311 unsigned endOffset = startOffset + length - 1; |
320 MarkerList::iterator startPos = std::lower_bound( | 312 MarkerList::iterator startPos = std::lower_bound( |
321 list->begin(), list->end(), startOffset, doesNotInclude); | 313 list->begin(), list->end(), startOffset, doesNotInclude); |
322 for (MarkerList::iterator i = startPos; i != list->end(); ++i) { | 314 for (MarkerList::iterator i = startPos; i != list->end(); ++i) { |
323 DocumentMarker* marker = i->get(); | 315 DocumentMarker* marker = i->get(); |
324 | 316 |
325 // stop if we are now past the specified range | 317 // stop if we are now past the specified range |
(...skipping 403 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
729 // cause the node to be redrawn | 721 // cause the node to be redrawn |
730 if (LayoutObject* layoutObject = node->layoutObject()) { | 722 if (LayoutObject* layoutObject = node->layoutObject()) { |
731 layoutObject->setShouldDoFullPaintInvalidation( | 723 layoutObject->setShouldDoFullPaintInvalidation( |
732 PaintInvalidationDocumentMarkerChange); | 724 PaintInvalidationDocumentMarkerChange); |
733 break; | 725 break; |
734 } | 726 } |
735 } | 727 } |
736 } | 728 } |
737 } | 729 } |
738 | 730 |
739 void DocumentMarkerController::shiftMarkers(Node* node, | |
740 unsigned startOffset, | |
741 int delta) { | |
742 if (!possiblyHasMarkers(DocumentMarker::AllMarkers())) | |
743 return; | |
744 DCHECK(!m_markers.isEmpty()); | |
745 | |
746 MarkerLists* markers = m_markers.at(node); | |
747 if (!markers) | |
748 return; | |
749 | |
750 bool didShiftMarker = false; | |
751 for (size_t markerListIndex = 0; | |
752 markerListIndex < DocumentMarker::MarkerTypeIndexesCount; | |
753 ++markerListIndex) { | |
754 Member<MarkerList>& list = (*markers)[markerListIndex]; | |
755 if (!list) | |
756 continue; | |
757 MarkerList::iterator startPos = | |
758 std::lower_bound(list->begin(), list->end(), startOffset, startsAfter); | |
759 for (MarkerList::iterator marker = startPos; marker != list->end(); | |
760 ++marker) { | |
761 #if DCHECK_IS_ON() | |
762 int startOffset = (*marker)->startOffset(); | |
763 DCHECK_GE(startOffset + delta, 0); | |
764 #endif | |
765 (*marker)->shiftOffsets(delta); | |
766 didShiftMarker = true; | |
767 } | |
768 } | |
769 | |
770 if (didShiftMarker) { | |
771 invalidateRectsForMarkersInNode(*node); | |
772 // repaint the affected node | |
773 if (node->layoutObject()) { | |
774 node->layoutObject()->setShouldDoFullPaintInvalidation( | |
775 PaintInvalidationDocumentMarkerChange); | |
776 } | |
777 } | |
778 } | |
779 | |
780 bool DocumentMarkerController::setMarkersActive(const EphemeralRange& range, | 731 bool DocumentMarkerController::setMarkersActive(const EphemeralRange& range, |
781 bool active) { | 732 bool active) { |
782 if (!possiblyHasMarkers(DocumentMarker::AllMarkers())) | 733 if (!possiblyHasMarkers(DocumentMarker::AllMarkers())) |
783 return false; | 734 return false; |
784 | 735 |
785 DCHECK(!m_markers.isEmpty()); | 736 DCHECK(!m_markers.isEmpty()); |
786 | 737 |
787 Node* const startContainer = range.startPosition().computeContainerNode(); | 738 Node* const startContainer = range.startPosition().computeContainerNode(); |
788 DCHECK(startContainer); | 739 DCHECK(startContainer); |
789 Node* const endContainer = range.endPosition().computeContainerNode(); | 740 Node* const endContainer = range.endPosition().computeContainerNode(); |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
869 LOG(INFO) << m_markers.size() << " nodes have markers:\n" | 820 LOG(INFO) << m_markers.size() << " nodes have markers:\n" |
870 << builder.toString().utf8().data(); | 821 << builder.toString().utf8().data(); |
871 } | 822 } |
872 #endif | 823 #endif |
873 | 824 |
874 // SynchronousMutationObserver | 825 // SynchronousMutationObserver |
875 void DocumentMarkerController::didUpdateCharacterData(CharacterData* node, | 826 void DocumentMarkerController::didUpdateCharacterData(CharacterData* node, |
876 unsigned offset, | 827 unsigned offset, |
877 unsigned oldLength, | 828 unsigned oldLength, |
878 unsigned newLength) { | 829 unsigned newLength) { |
879 // Shift markers as if we first remove the old text, then insert the new text | 830 // If we're doing a pure remove operation, remove the markers in the range |
880 removeMarkers(node, offset, oldLength); | 831 // being removed (markers containing, but larger than, the range, will be |
881 shiftMarkers(node, offset + oldLength, 0 - oldLength); | 832 // split) |
882 shiftMarkers(node, offset, newLength); | 833 if (newLength == 0) |
834 removeMarkers(node, offset, oldLength); | |
835 | |
836 if (!possiblyHasMarkers(DocumentMarker::AllMarkers())) | |
837 return; | |
838 DCHECK(!m_markers.isEmpty()); | |
839 | |
840 MarkerLists* markers = m_markers.at(node); | |
841 if (!markers) | |
842 return; | |
843 | |
844 bool didShiftMarker = false; | |
845 for (MarkerList* list : *markers) { | |
846 if (!list) | |
847 continue; | |
848 | |
849 for (MarkerList::iterator it = list->begin(); it != list->end(); ++it) { | |
850 RenderedDocumentMarker& marker = **it; | |
851 // algorithm inspired by https://dom.spec.whatwg.org/#concept-cd-replace | |
852 // but with some changes | |
853 if (marker.startOffset() > offset) { | |
yosin_UTC9
2017/03/23 04:10:26
It is nice if we can move this logic into function
| |
854 // Deviation from the concept-cd-replace algorithm: < instead of <= in | |
855 // the next line | |
856 if (marker.startOffset() < offset + oldLength) { | |
857 // Marker start was in the replaced text. Move to end of new text | |
858 // (Deviation from the concept-cd-replace algorithm: that algorithm | |
859 // would move to the beginning of the new text here) | |
860 marker.setStartOffset(offset + newLength); | |
861 } else { | |
862 // Marker start was after the replaced text. Shift by length | |
863 // difference | |
864 unsigned oldStartOffset = marker.startOffset(); | |
865 marker.setStartOffset(oldStartOffset + newLength - oldLength); | |
866 } | |
867 didShiftMarker = true; | |
868 } | |
869 | |
870 if (marker.endOffset() > offset) { | |
871 // Deviation from the concept-cd-replace algorithm: < instead of <= in | |
872 // the next line | |
873 if (marker.endOffset() < offset + oldLength) { | |
874 // Marker end was in the replaced text. Move to beginning of new text | |
875 marker.setEndOffset(offset); | |
876 } else { | |
877 // Marker end was after the replaced text. Shift by length difference | |
878 unsigned oldEndOffset = marker.endOffset(); | |
879 marker.setEndOffset(oldEndOffset + newLength - oldLength); | |
880 } | |
881 didShiftMarker = true; | |
882 } | |
883 | |
884 if (marker.startOffset() < marker.endOffset()) | |
885 continue; | |
886 list->remove(it - list->begin()); | |
887 --it; | |
888 } | |
889 } | |
890 | |
891 if (!didShiftMarker) | |
892 return; | |
893 if (!node->layoutObject()) | |
894 return; | |
895 invalidateRectsForMarkersInNode(*node); | |
896 // repaint the affected node | |
897 node->layoutObject()->setShouldDoFullPaintInvalidation(); | |
883 } | 898 } |
884 | 899 |
885 } // namespace blink | 900 } // namespace blink |
886 | 901 |
887 #ifndef NDEBUG | 902 #ifndef NDEBUG |
888 void showDocumentMarkers(const blink::DocumentMarkerController* controller) { | 903 void showDocumentMarkers(const blink::DocumentMarkerController* controller) { |
889 if (controller) | 904 if (controller) |
890 controller->showMarkers(); | 905 controller->showMarkers(); |
891 } | 906 } |
892 #endif | 907 #endif |
OLD | NEW |