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 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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 Loading... | |
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 385 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
581 | 578 |
582 if (markerList->front()->type() == DocumentMarker::TextMatch) | 579 if (markerList->front()->type() == DocumentMarker::TextMatch) |
583 invalidatePaintForTickmarks(node); | 580 invalidatePaintForTickmarks(node); |
584 } | 581 } |
585 } | 582 } |
586 } | 583 } |
587 | 584 |
588 DEFINE_TRACE(DocumentMarkerController) { | 585 DEFINE_TRACE(DocumentMarkerController) { |
589 visitor->trace(m_markers); | 586 visitor->trace(m_markers); |
590 visitor->trace(m_document); | 587 visitor->trace(m_document); |
588 SynchronousMutationObserver::trace(visitor); | |
591 } | 589 } |
592 | 590 |
593 void DocumentMarkerController::removeMarkers( | 591 void DocumentMarkerController::removeMarkers( |
594 Node* node, | 592 Node* node, |
595 DocumentMarker::MarkerTypes markerTypes) { | 593 DocumentMarker::MarkerTypes markerTypes) { |
596 if (!possiblyHasMarkers(markerTypes)) | 594 if (!possiblyHasMarkers(markerTypes)) |
597 return; | 595 return; |
598 DCHECK(!m_markers.isEmpty()); | 596 DCHECK(!m_markers.isEmpty()); |
599 | 597 |
600 MarkerMap::iterator iterator = m_markers.find(node); | 598 MarkerMap::iterator iterator = m_markers.find(node); |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
690 invalidatePaintForTickmarks(node); | 688 invalidatePaintForTickmarks(node); |
691 } | 689 } |
692 | 690 |
693 if (nodeCanBeRemoved) { | 691 if (nodeCanBeRemoved) { |
694 m_markers.remove(iterator); | 692 m_markers.remove(iterator); |
695 if (m_markers.isEmpty()) | 693 if (m_markers.isEmpty()) |
696 m_possiblyExistingMarkerTypes = 0; | 694 m_possiblyExistingMarkerTypes = 0; |
697 } | 695 } |
698 } | 696 } |
699 | 697 |
698 void DocumentMarkerController::removeZeroLengthMarkers() { | |
699 for (auto& nodeMarkers : m_markers) { | |
700 const Node& node = *nodeMarkers.key; | |
701 MarkerLists& markers = *nodeMarkers.value; | |
702 for (size_t markerListIndex = 0; | |
703 markerListIndex < DocumentMarker::MarkerTypeIndexesCount; | |
704 ++markerListIndex) { | |
705 Member<MarkerList>& list = markers[markerListIndex]; | |
yosin_UTC9
2017/02/20 07:26:27
nit: s/&//
| |
706 if (!list) | |
707 continue; | |
708 bool removedMarkers = false; | |
709 for (size_t j = list->size(); j > 0; --j) { | |
710 if (list->at(j - 1)->startOffset() == list->at(j - 1)->endOffset()) { | |
711 list->remove(j - 1); | |
712 removedMarkers = true; | |
713 } | |
714 } | |
715 if (removedMarkers && | |
yosin_UTC9
2017/02/20 07:26:27
We prefer early-return-style.
if (!removeMarkers)
| |
716 markerListIndex == DocumentMarker::TextMatchMarkerIndex) | |
717 invalidatePaintForTickmarks(node); | |
718 } | |
719 } | |
720 } | |
721 | |
700 void DocumentMarkerController::repaintMarkers( | 722 void DocumentMarkerController::repaintMarkers( |
701 DocumentMarker::MarkerTypes markerTypes) { | 723 DocumentMarker::MarkerTypes markerTypes) { |
702 if (!possiblyHasMarkers(markerTypes)) | 724 if (!possiblyHasMarkers(markerTypes)) |
703 return; | 725 return; |
704 DCHECK(!m_markers.isEmpty()); | 726 DCHECK(!m_markers.isEmpty()); |
705 | 727 |
706 // outer loop: process each markered node in the document | 728 // outer loop: process each markered node in the document |
707 MarkerMap::iterator end = m_markers.end(); | 729 MarkerMap::iterator end = m_markers.end(); |
708 for (MarkerMap::iterator i = m_markers.begin(); i != end; ++i) { | 730 for (MarkerMap::iterator i = m_markers.begin(); i != end; ++i) { |
709 const Node* node = i->key; | 731 const Node* node = i->key; |
(...skipping 10 matching lines...) Expand all Loading... | |
720 | 742 |
721 // cause the node to be redrawn | 743 // cause the node to be redrawn |
722 if (LayoutObject* layoutObject = node->layoutObject()) { | 744 if (LayoutObject* layoutObject = node->layoutObject()) { |
723 layoutObject->setShouldDoFullPaintInvalidation(); | 745 layoutObject->setShouldDoFullPaintInvalidation(); |
724 break; | 746 break; |
725 } | 747 } |
726 } | 748 } |
727 } | 749 } |
728 } | 750 } |
729 | 751 |
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.get(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, | 752 bool DocumentMarkerController::setMarkersActive(const EphemeralRange& range, |
770 bool active) { | 753 bool active) { |
771 if (!possiblyHasMarkers(DocumentMarker::AllMarkers())) | 754 if (!possiblyHasMarkers(DocumentMarker::AllMarkers())) |
772 return false; | 755 return false; |
773 | 756 |
774 DCHECK(!m_markers.isEmpty()); | 757 DCHECK(!m_markers.isEmpty()); |
775 | 758 |
776 Node* const startContainer = range.startPosition().computeContainerNode(); | 759 Node* const startContainer = range.startPosition().computeContainerNode(); |
777 DCHECK(startContainer); | 760 DCHECK(startContainer); |
778 Node* const endContainer = range.endPosition().computeContainerNode(); | 761 Node* const endContainer = range.endPosition().computeContainerNode(); |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
851 builder.append(")"); | 834 builder.append(")"); |
852 } | 835 } |
853 } | 836 } |
854 builder.append("\n"); | 837 builder.append("\n"); |
855 } | 838 } |
856 LOG(INFO) << m_markers.size() << " nodes have markers:\n" | 839 LOG(INFO) << m_markers.size() << " nodes have markers:\n" |
857 << builder.toString().utf8().data(); | 840 << builder.toString().utf8().data(); |
858 } | 841 } |
859 #endif | 842 #endif |
860 | 843 |
844 // SynchronousMutationObserver | |
845 void DocumentMarkerController::didUpdateCharacterData(CharacterData* node, | |
846 unsigned offset, | |
847 unsigned oldLength, | |
848 unsigned newLength) { | |
849 // If we're doing a pure remove operation, remove the markers in the range | |
850 // being removed (markers containing, but larger than, the range, will be | |
851 // split) | |
852 if (newLength == 0) { | |
yosin_UTC9
2017/02/20 07:26:27
nit: no need to have "{}"
| |
853 removeMarkers(node, offset, oldLength); | |
854 } | |
855 | |
856 if (!possiblyHasMarkers(DocumentMarker::AllMarkers())) | |
857 return; | |
858 DCHECK(!m_markers.isEmpty()); | |
859 | |
860 MarkerLists* markers = m_markers.get(node); | |
861 if (!markers) | |
862 return; | |
863 | |
864 bool didShiftMarker = false; | |
865 for (size_t markerListIndex = 0; | |
866 markerListIndex < DocumentMarker::MarkerTypeIndexesCount; | |
867 ++markerListIndex) { | |
868 Member<MarkerList>& list = (*markers)[markerListIndex]; | |
yosin_UTC9
2017/02/20 07:26:27
nit: s/&//
| |
869 if (!list) | |
870 continue; | |
871 | |
872 for (MarkerList::iterator marker = list->begin(); marker != list->end(); | |
873 ++marker) { | |
874 // if marker is contained by but not equal to the replaced range, remove | |
875 // the marker | |
876 if ((offset <= (*marker)->startOffset() && | |
877 (*marker)->endOffset() < offset + oldLength) || | |
878 (offset < (*marker)->startOffset() && | |
879 (*marker)->endOffset() <= offset + oldLength)) { | |
880 list->remove(marker - list->begin()); | |
881 marker--; | |
882 continue; | |
883 } | |
884 | |
885 // algorithm inspired by https://dom.spec.whatwg.org/#concept-cd-replace | |
886 // but with some changes | |
887 if ((*marker)->startOffset() > offset) { | |
888 // Deviation from the concept-cd-replace algorithm: < instead of <= in | |
889 // the next line | |
890 if ((*marker)->startOffset() < offset + oldLength) { | |
891 // Marker start was in the replaced text. Move to beginning of new | |
892 // text | |
893 (*marker)->setStartOffset(offset); | |
894 } else { | |
895 // Marker start was after the replaced text. Shift by length | |
896 // difference | |
897 unsigned oldStartOffset = (*marker)->startOffset(); | |
898 (*marker)->setStartOffset(oldStartOffset + newLength - oldLength); | |
899 } | |
900 } | |
901 | |
902 if ((*marker)->endOffset() > offset) { | |
903 // Deviation from the concept-cd-replace algorithm: < instead of <= in | |
904 // the next line | |
905 if ((*marker)->endOffset() < offset + oldLength) { | |
906 // Marker end was in the replaced text. Move to beginning of new text | |
907 (*marker)->setEndOffset(offset); | |
908 } else { | |
909 // Marker end was after the replaced text. Shift by length difference | |
910 unsigned oldEndOffset = (*marker)->endOffset(); | |
911 (*marker)->setEndOffset(oldEndOffset + newLength - oldLength); | |
912 } | |
913 } | |
914 | |
915 didShiftMarker = true; | |
916 } | |
917 } | |
918 | |
919 if (didShiftMarker) { | |
920 removeZeroLengthMarkers(); | |
921 invalidateRectsForMarkersInNode(*node); | |
922 // repaint the affected node | |
923 if (node->layoutObject()) | |
924 node->layoutObject()->setShouldDoFullPaintInvalidation(); | |
925 } | |
926 } | |
927 | |
861 } // namespace blink | 928 } // namespace blink |
862 | 929 |
863 #ifndef NDEBUG | 930 #ifndef NDEBUG |
864 void showDocumentMarkers(const blink::DocumentMarkerController* controller) { | 931 void showDocumentMarkers(const blink::DocumentMarkerController* controller) { |
865 if (controller) | 932 if (controller) |
866 controller->showMarkers(); | 933 controller->showMarkers(); |
867 } | 934 } |
868 #endif | 935 #endif |
OLD | NEW |