Chromium Code Reviews| Index: third_party/WebKit/Source/core/editing/markers/DocumentMarkerController.cpp |
| diff --git a/third_party/WebKit/Source/core/editing/markers/DocumentMarkerController.cpp b/third_party/WebKit/Source/core/editing/markers/DocumentMarkerController.cpp |
| index 34506d1809171ca1ef41fdc04d995e252f4aa773..7b8c0c0d71e4204a397d8983afad17520d1e6566 100644 |
| --- a/third_party/WebKit/Source/core/editing/markers/DocumentMarkerController.cpp |
| +++ b/third_party/WebKit/Source/core/editing/markers/DocumentMarkerController.cpp |
| @@ -177,11 +177,6 @@ static bool startsFurther(const Member<RenderedDocumentMarker>& lhv, |
| return lhv->startOffset() < rhv->startOffset(); |
| } |
| -static bool startsAfter(const Member<RenderedDocumentMarker>& marker, |
| - size_t startOffset) { |
| - return marker->startOffset() < startOffset; |
| -} |
| - |
| static bool endsBefore(size_t startOffset, |
| const Member<RenderedDocumentMarker>& rhv) { |
| return startOffset < rhv->endOffset(); |
| @@ -309,10 +304,7 @@ void DocumentMarkerController::copyMarkers(Node* srcNode, |
| return; |
| bool docDirty = false; |
| - for (size_t markerListIndex = 0; |
| - markerListIndex < DocumentMarker::MarkerTypeIndexesCount; |
| - ++markerListIndex) { |
| - Member<MarkerList>& list = (*markers)[markerListIndex]; |
| + for (Member<MarkerList> list : *markers) { |
| if (!list) |
| continue; |
| @@ -654,6 +646,53 @@ void DocumentMarkerController::removeMarkers( |
| m_possiblyExistingMarkerTypes.remove(markerTypes); |
| } |
| +bool DocumentMarkerController::relocateMarkerIfNeeded( |
|
Xiaocheng
2017/03/29 18:35:19
Can we implement this function directly in Documen
|
| + RenderedDocumentMarker* marker, |
| + unsigned offset, |
| + unsigned oldLength, |
| + unsigned newLength) { |
| + bool didShiftMarker = false; |
| + |
| + // algorithm inspired by https://dom.spec.whatwg.org/#concept-cd-replace |
| + // but with some changes |
| + |
| + // Deviation from the concept-cd-replace algorithm: second condition in the |
| + // next line (don't include text inserted immediately before a marker in the |
| + // marked range, but do include the new text if it's replacing text in the |
| + // marked range) |
| + if (marker->startOffset() > offset || |
| + (marker->startOffset() == offset && oldLength == 0)) { |
| + if (marker->startOffset() <= offset + oldLength) { |
| + // Marker start was in the replaced text. Move to end of new text |
| + // (Deviation from the concept-cd-replace algorithm: that algorithm |
| + // would move to the beginning of the new text here) |
| + marker->setStartOffset(offset + newLength); |
| + } else { |
| + // Marker start was after the replaced text. Shift by length |
| + // difference |
| + unsigned oldStartOffset = marker->startOffset(); |
| + marker->setStartOffset(oldStartOffset + newLength - oldLength); |
| + } |
| + didShiftMarker = true; |
| + } |
| + |
| + if (marker->endOffset() > offset) { |
| + // Deviation from the concept-cd-replace algorithm: < instead of <= in |
| + // the next line |
| + if (marker->endOffset() < offset + oldLength) { |
| + // Marker end was in the replaced text. Move to beginning of new text |
| + marker->setEndOffset(offset); |
| + } else { |
| + // Marker end was after the replaced text. Shift by length difference |
| + unsigned oldEndOffset = marker->endOffset(); |
| + marker->setEndOffset(oldEndOffset + newLength - oldLength); |
| + } |
| + didShiftMarker = true; |
| + } |
| + |
| + return didShiftMarker; |
| +} |
| + |
| void DocumentMarkerController::removeMarkersFromList( |
| MarkerMap::iterator iterator, |
| DocumentMarker::MarkerTypes markerTypes) { |
| @@ -736,47 +775,6 @@ void DocumentMarkerController::repaintMarkers( |
| } |
| } |
| -void DocumentMarkerController::shiftMarkers(Node* node, |
| - unsigned startOffset, |
| - int delta) { |
| - if (!possiblyHasMarkers(DocumentMarker::AllMarkers())) |
| - return; |
| - DCHECK(!m_markers.isEmpty()); |
| - |
| - MarkerLists* markers = m_markers.at(node); |
| - if (!markers) |
| - return; |
| - |
| - bool didShiftMarker = false; |
| - for (size_t markerListIndex = 0; |
| - markerListIndex < DocumentMarker::MarkerTypeIndexesCount; |
| - ++markerListIndex) { |
| - Member<MarkerList>& list = (*markers)[markerListIndex]; |
| - if (!list) |
| - continue; |
| - MarkerList::iterator startPos = |
| - std::lower_bound(list->begin(), list->end(), startOffset, startsAfter); |
| - for (MarkerList::iterator marker = startPos; marker != list->end(); |
| - ++marker) { |
| -#if DCHECK_IS_ON() |
| - int startOffset = (*marker)->startOffset(); |
| - DCHECK_GE(startOffset + delta, 0); |
| -#endif |
| - (*marker)->shiftOffsets(delta); |
| - didShiftMarker = true; |
| - } |
| - } |
| - |
| - if (didShiftMarker) { |
| - invalidateRectsForMarkersInNode(*node); |
| - // repaint the affected node |
| - if (node->layoutObject()) { |
| - node->layoutObject()->setShouldDoFullPaintInvalidation( |
| - PaintInvalidationDocumentMarkerChange); |
| - } |
| - } |
| -} |
| - |
| bool DocumentMarkerController::setMarkersActive(const EphemeralRange& range, |
| bool active) { |
| if (!possiblyHasMarkers(DocumentMarker::AllMarkers())) |
| @@ -876,10 +874,45 @@ void DocumentMarkerController::didUpdateCharacterData(CharacterData* node, |
| unsigned offset, |
| unsigned oldLength, |
| unsigned newLength) { |
| - // Shift markers as if we first remove the old text, then insert the new text |
| - removeMarkers(node, offset, oldLength); |
| - shiftMarkers(node, offset + oldLength, 0 - oldLength); |
| - shiftMarkers(node, offset, newLength); |
| + // If we're doing a pure remove operation, remove the markers in the range |
| + // being removed (markers containing, but larger than, the range, will be |
| + // split) |
| + if (newLength == 0) |
| + removeMarkers(node, offset, oldLength); |
| + |
| + if (!possiblyHasMarkers(DocumentMarker::AllMarkers())) |
| + return; |
| + DCHECK(!m_markers.isEmpty()); |
| + |
| + MarkerLists* markers = m_markers.at(node); |
| + if (!markers) |
| + return; |
| + |
| + bool didShiftMarker = false; |
| + for (MarkerList* list : *markers) { |
| + if (!list) |
| + continue; |
| + |
| + for (MarkerList::iterator it = list->begin(); it != list->end(); ++it) { |
| + RenderedDocumentMarker& marker = **it; |
| + if (relocateMarkerIfNeeded(&marker, offset, oldLength, newLength)) { |
| + didShiftMarker = true; |
| + |
| + if (marker.startOffset() < marker.endOffset()) |
| + continue; |
| + list->erase(it - list->begin()); |
| + --it; |
| + } |
| + } |
| + } |
| + |
| + if (!didShiftMarker) |
| + return; |
| + if (!node->layoutObject()) |
| + return; |
| + invalidateRectsForMarkersInNode(*node); |
| + // repaint the affected node |
| + node->layoutObject()->setShouldDoFullPaintInvalidation(); |
| } |
| } // namespace blink |