Chromium Code Reviews| 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 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 258 newMarker.type() != DocumentMarker::Composition) { | 255 newMarker.type() != DocumentMarker::Composition) { |
| 259 mergeOverlapping(list.get(), newRenderedMarker); | 256 mergeOverlapping(list.get(), newRenderedMarker); |
| 260 } else { | 257 } else { |
| 261 MarkerList::iterator pos = std::lower_bound(list->begin(), list->end(), | 258 MarkerList::iterator pos = std::lower_bound(list->begin(), list->end(), |
| 262 &newMarker, startsFurther); | 259 &newMarker, startsFurther); |
| 263 list->insert(pos - list->begin(), newRenderedMarker); | 260 list->insert(pos - list->begin(), newRenderedMarker); |
| 264 } | 261 } |
| 265 } | 262 } |
| 266 | 263 |
| 267 // repaint the affected node | 264 // repaint the affected node |
| 268 if (node->layoutObject()) | 265 if (node->layoutObject()) { |
|
Xiaocheng
2017/02/23 18:58:35
nit: no need to add braces
| |
| 269 node->layoutObject()->setShouldDoFullPaintInvalidation(); | 266 node->layoutObject()->setShouldDoFullPaintInvalidation(); |
| 267 } | |
| 270 } | 268 } |
| 271 | 269 |
| 272 void DocumentMarkerController::mergeOverlapping( | 270 void DocumentMarkerController::mergeOverlapping( |
| 273 MarkerList* list, | 271 MarkerList* list, |
| 274 RenderedDocumentMarker* toInsert) { | 272 RenderedDocumentMarker* toInsert) { |
| 275 MarkerList::iterator firstOverlapping = | 273 MarkerList::iterator firstOverlapping = |
| 276 std::lower_bound(list->begin(), list->end(), toInsert, doesNotOverlap); | 274 std::lower_bound(list->begin(), list->end(), toInsert, doesNotOverlap); |
| 277 size_t index = firstOverlapping - list->begin(); | 275 size_t index = firstOverlapping - list->begin(); |
| 278 list->insert(index, toInsert); | 276 list->insert(index, toInsert); |
| 279 MarkerList::iterator inserted = list->begin() + index; | 277 MarkerList::iterator inserted = list->begin() + index; |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 301 | 299 |
| 302 if (!possiblyHasMarkers(DocumentMarker::AllMarkers())) | 300 if (!possiblyHasMarkers(DocumentMarker::AllMarkers())) |
| 303 return; | 301 return; |
| 304 DCHECK(!m_markers.isEmpty()); | 302 DCHECK(!m_markers.isEmpty()); |
| 305 | 303 |
| 306 MarkerLists* markers = m_markers.at(srcNode); | 304 MarkerLists* markers = m_markers.at(srcNode); |
| 307 if (!markers) | 305 if (!markers) |
| 308 return; | 306 return; |
| 309 | 307 |
| 310 bool docDirty = false; | 308 bool docDirty = false; |
| 311 for (size_t markerListIndex = 0; | 309 for (Member<MarkerList> list : *markers) { |
| 312 markerListIndex < DocumentMarker::MarkerTypeIndexesCount; | |
| 313 ++markerListIndex) { | |
| 314 Member<MarkerList>& list = (*markers)[markerListIndex]; | |
| 315 if (!list) | 310 if (!list) |
| 316 continue; | 311 continue; |
| 317 | 312 |
| 318 unsigned endOffset = startOffset + length - 1; | 313 unsigned endOffset = startOffset + length - 1; |
| 319 MarkerList::iterator startPos = std::lower_bound( | 314 MarkerList::iterator startPos = std::lower_bound( |
| 320 list->begin(), list->end(), startOffset, doesNotInclude); | 315 list->begin(), list->end(), startOffset, doesNotInclude); |
| 321 for (MarkerList::iterator i = startPos; i != list->end(); ++i) { | 316 for (MarkerList::iterator i = startPos; i != list->end(); ++i) { |
| 322 DocumentMarker* marker = i->get(); | 317 DocumentMarker* marker = i->get(); |
| 323 | 318 |
| 324 // stop if we are now past the specified range | 319 // stop if we are now past the specified range |
| 325 if (marker->startOffset() > endOffset) | 320 if (marker->startOffset() > endOffset) |
| 326 break; | 321 break; |
| 327 | 322 |
| 328 // pin the marker to the specified range and apply the shift delta | 323 // pin the marker to the specified range and apply the shift delta |
| 329 docDirty = true; | 324 docDirty = true; |
| 330 if (marker->startOffset() < startOffset) | 325 if (marker->startOffset() < startOffset) |
| 331 marker->setStartOffset(startOffset); | 326 marker->setStartOffset(startOffset); |
| 332 if (marker->endOffset() > endOffset) | 327 if (marker->endOffset() > endOffset) |
| 333 marker->setEndOffset(endOffset); | 328 marker->setEndOffset(endOffset); |
| 334 marker->shiftOffsets(delta); | 329 marker->shiftOffsets(delta); |
| 335 | 330 |
| 336 addMarker(dstNode, *marker); | 331 addMarker(dstNode, *marker); |
| 337 } | 332 } |
| 338 } | 333 } |
| 339 | 334 |
| 340 // repaint the affected node | 335 // repaint the affected node |
| 341 if (docDirty && dstNode->layoutObject()) | 336 if (docDirty && dstNode->layoutObject()) { |
|
Xiaocheng
2017/02/23 18:58:35
nit: no need to add braces
| |
| 342 dstNode->layoutObject()->setShouldDoFullPaintInvalidation(); | 337 dstNode->layoutObject()->setShouldDoFullPaintInvalidation(); |
| 338 } | |
| 343 } | 339 } |
| 344 | 340 |
| 345 void DocumentMarkerController::removeMarkers( | 341 void DocumentMarkerController::removeMarkers( |
| 346 Node* node, | 342 Node* node, |
| 347 unsigned startOffset, | 343 unsigned startOffset, |
| 348 int length, | 344 int length, |
| 349 DocumentMarker::MarkerTypes markerTypes, | 345 DocumentMarker::MarkerTypes markerTypes, |
| 350 RemovePartiallyOverlappingMarkerOrNot | 346 RemovePartiallyOverlappingMarkerOrNot |
| 351 shouldRemovePartiallyOverlappingMarker) { | 347 shouldRemovePartiallyOverlappingMarker) { |
| 352 if (length <= 0) | 348 if (length <= 0) |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 421 } | 417 } |
| 422 } | 418 } |
| 423 | 419 |
| 424 if (emptyListsCount == DocumentMarker::MarkerTypeIndexesCount) { | 420 if (emptyListsCount == DocumentMarker::MarkerTypeIndexesCount) { |
| 425 m_markers.erase(node); | 421 m_markers.erase(node); |
| 426 if (m_markers.isEmpty()) | 422 if (m_markers.isEmpty()) |
| 427 m_possiblyExistingMarkerTypes = 0; | 423 m_possiblyExistingMarkerTypes = 0; |
| 428 } | 424 } |
| 429 | 425 |
| 430 // repaint the affected node | 426 // repaint the affected node |
| 431 if (docDirty && node->layoutObject()) | 427 if (docDirty && node->layoutObject()) { |
|
Xiaocheng
2017/02/23 18:58:35
nit: no need to add braces
| |
| 432 node->layoutObject()->setShouldDoFullPaintInvalidation(); | 428 node->layoutObject()->setShouldDoFullPaintInvalidation(); |
| 429 } | |
| 433 } | 430 } |
| 434 | 431 |
| 435 DocumentMarkerVector DocumentMarkerController::markersFor( | 432 DocumentMarkerVector DocumentMarkerController::markersFor( |
| 436 Node* node, | 433 Node* node, |
| 437 DocumentMarker::MarkerTypes markerTypes) { | 434 DocumentMarker::MarkerTypes markerTypes) { |
| 438 DocumentMarkerVector result; | 435 DocumentMarkerVector result; |
| 439 | 436 |
| 440 MarkerLists* markers = m_markers.at(node); | 437 MarkerLists* markers = m_markers.at(node); |
| 441 if (!markers) | 438 if (!markers) |
| 442 return result; | 439 return result; |
| (...skipping 138 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 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 678 needsRepainting = true; | 676 needsRepainting = true; |
| 679 } | 677 } |
| 680 } | 678 } |
| 681 | 679 |
| 682 nodeCanBeRemoved = | 680 nodeCanBeRemoved = |
| 683 emptyListsCount == DocumentMarker::MarkerTypeIndexesCount; | 681 emptyListsCount == DocumentMarker::MarkerTypeIndexesCount; |
| 684 } | 682 } |
| 685 | 683 |
| 686 if (needsRepainting) { | 684 if (needsRepainting) { |
| 687 const Node& node = *iterator->key; | 685 const Node& node = *iterator->key; |
| 688 if (LayoutObject* layoutObject = node.layoutObject()) | 686 if (LayoutObject* layoutObject = node.layoutObject()) { |
|
Xiaocheng
2017/02/23 18:58:35
nit: no need to add braces
| |
| 689 layoutObject->setShouldDoFullPaintInvalidation(); | 687 layoutObject->setShouldDoFullPaintInvalidation(); |
| 688 } | |
| 690 invalidatePaintForTickmarks(node); | 689 invalidatePaintForTickmarks(node); |
| 691 } | 690 } |
| 692 | 691 |
| 693 if (nodeCanBeRemoved) { | 692 if (nodeCanBeRemoved) { |
| 694 m_markers.remove(iterator); | 693 m_markers.remove(iterator); |
| 695 if (m_markers.isEmpty()) | 694 if (m_markers.isEmpty()) |
| 696 m_possiblyExistingMarkerTypes = 0; | 695 m_possiblyExistingMarkerTypes = 0; |
| 697 } | 696 } |
| 698 } | 697 } |
| 699 | 698 |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 720 | 719 |
| 721 // cause the node to be redrawn | 720 // cause the node to be redrawn |
| 722 if (LayoutObject* layoutObject = node->layoutObject()) { | 721 if (LayoutObject* layoutObject = node->layoutObject()) { |
| 723 layoutObject->setShouldDoFullPaintInvalidation(); | 722 layoutObject->setShouldDoFullPaintInvalidation(); |
| 724 break; | 723 break; |
| 725 } | 724 } |
| 726 } | 725 } |
| 727 } | 726 } |
| 728 } | 727 } |
| 729 | 728 |
| 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, | 729 bool DocumentMarkerController::setMarkersActive(const EphemeralRange& range, |
| 770 bool active) { | 730 bool active) { |
| 771 if (!possiblyHasMarkers(DocumentMarker::AllMarkers())) | 731 if (!possiblyHasMarkers(DocumentMarker::AllMarkers())) |
| 772 return false; | 732 return false; |
| 773 | 733 |
| 774 DCHECK(!m_markers.isEmpty()); | 734 DCHECK(!m_markers.isEmpty()); |
| 775 | 735 |
| 776 Node* const startContainer = range.startPosition().computeContainerNode(); | 736 Node* const startContainer = range.startPosition().computeContainerNode(); |
| 777 DCHECK(startContainer); | 737 DCHECK(startContainer); |
| 778 Node* const endContainer = range.endPosition().computeContainerNode(); | 738 Node* const endContainer = range.endPosition().computeContainerNode(); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 812 // Markers are returned in order, so stop if we are now past the specified | 772 // Markers are returned in order, so stop if we are now past the specified |
| 813 // range. | 773 // range. |
| 814 if ((*marker)->startOffset() >= endOffset) | 774 if ((*marker)->startOffset() >= endOffset) |
| 815 break; | 775 break; |
| 816 | 776 |
| 817 (*marker)->setActiveMatch(active); | 777 (*marker)->setActiveMatch(active); |
| 818 docDirty = true; | 778 docDirty = true; |
| 819 } | 779 } |
| 820 | 780 |
| 821 // repaint the affected node | 781 // repaint the affected node |
| 822 if (docDirty && node->layoutObject()) | 782 if (docDirty && node->layoutObject()) { |
|
Xiaocheng
2017/02/23 18:58:35
nit: no need to add braces.
| |
| 823 node->layoutObject()->setShouldDoFullPaintInvalidation(); | 783 node->layoutObject()->setShouldDoFullPaintInvalidation(); |
| 784 } | |
| 824 return docDirty; | 785 return docDirty; |
| 825 } | 786 } |
| 826 | 787 |
| 827 #ifndef NDEBUG | 788 #ifndef NDEBUG |
| 828 void DocumentMarkerController::showMarkers() const { | 789 void DocumentMarkerController::showMarkers() const { |
| 829 StringBuilder builder; | 790 StringBuilder builder; |
| 830 MarkerMap::const_iterator end = m_markers.end(); | 791 MarkerMap::const_iterator end = m_markers.end(); |
| 831 for (MarkerMap::const_iterator nodeIterator = m_markers.begin(); | 792 for (MarkerMap::const_iterator nodeIterator = m_markers.begin(); |
| 832 nodeIterator != end; ++nodeIterator) { | 793 nodeIterator != end; ++nodeIterator) { |
| 833 const Node* node = nodeIterator->key; | 794 const Node* node = nodeIterator->key; |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 851 builder.append(")"); | 812 builder.append(")"); |
| 852 } | 813 } |
| 853 } | 814 } |
| 854 builder.append("\n"); | 815 builder.append("\n"); |
| 855 } | 816 } |
| 856 LOG(INFO) << m_markers.size() << " nodes have markers:\n" | 817 LOG(INFO) << m_markers.size() << " nodes have markers:\n" |
| 857 << builder.toString().utf8().data(); | 818 << builder.toString().utf8().data(); |
| 858 } | 819 } |
| 859 #endif | 820 #endif |
| 860 | 821 |
| 822 // SynchronousMutationObserver | |
| 823 void DocumentMarkerController::didUpdateCharacterData(CharacterData* node, | |
| 824 unsigned offset, | |
| 825 unsigned oldLength, | |
| 826 unsigned newLength) { | |
| 827 // If we're doing a pure remove operation, remove the markers in the range | |
| 828 // being removed (markers containing, but larger than, the range, will be | |
| 829 // split) | |
| 830 if (newLength == 0) | |
| 831 removeMarkers(node, offset, oldLength); | |
| 832 | |
| 833 if (!possiblyHasMarkers(DocumentMarker::AllMarkers())) | |
| 834 return; | |
| 835 DCHECK(!m_markers.isEmpty()); | |
| 836 | |
| 837 MarkerLists* markers = m_markers.at(node); | |
| 838 if (!markers) | |
| 839 return; | |
| 840 | |
| 841 bool didShiftMarker = false; | |
| 842 for (MarkerList* list : *markers) { | |
| 843 if (!list) | |
| 844 continue; | |
| 845 | |
| 846 for (MarkerList::iterator marker = list->begin(); marker != list->end(); | |
| 847 ++marker) { | |
| 848 // algorithm inspired by https://dom.spec.whatwg.org/#concept-cd-replace | |
| 849 // but with some changes | |
| 850 if ((*marker)->startOffset() > offset) { | |
| 851 // Deviation from the concept-cd-replace algorithm: < instead of <= in | |
| 852 // the next line | |
| 853 if ((*marker)->startOffset() < offset + oldLength) { | |
| 854 // Marker start was in the replaced text. Move to end of new text | |
| 855 // (Deviation from the concept-cd-replace algorithm: that algorithm | |
| 856 // would move to the beginning of the new text here) | |
| 857 (*marker)->setStartOffset(offset + newLength); | |
| 858 } else { | |
| 859 // Marker start was after the replaced text. Shift by length | |
| 860 // difference | |
| 861 unsigned oldStartOffset = (*marker)->startOffset(); | |
| 862 (*marker)->setStartOffset(oldStartOffset + newLength - oldLength); | |
| 863 } | |
| 864 } | |
| 865 | |
| 866 if ((*marker)->endOffset() > offset) { | |
| 867 // Deviation from the concept-cd-replace algorithm: < instead of <= in | |
| 868 // the next line | |
| 869 if ((*marker)->endOffset() < offset + oldLength) { | |
| 870 // Marker end was in the replaced text. Move to beginning of new text | |
| 871 (*marker)->setEndOffset(offset); | |
| 872 } else { | |
| 873 // Marker end was after the replaced text. Shift by length difference | |
| 874 unsigned oldEndOffset = (*marker)->endOffset(); | |
| 875 (*marker)->setEndOffset(oldEndOffset + newLength - oldLength); | |
| 876 } | |
| 877 } | |
| 878 | |
| 879 if ((*marker)->startOffset() >= (*marker)->endOffset()) { | |
| 880 list->remove(marker - list->begin()); | |
| 881 --marker; | |
| 882 continue; | |
| 883 } | |
| 884 | |
| 885 didShiftMarker = true; | |
|
Xiaocheng
2017/02/23 18:58:35
didShiftMarker = true should be set after L863 and
| |
| 886 } | |
| 887 } | |
| 888 | |
| 889 if (didShiftMarker) { | |
| 890 invalidateRectsForMarkersInNode(*node); | |
| 891 // repaint the affected node | |
| 892 if (node->layoutObject()) { | |
| 893 node->layoutObject()->setShouldDoFullPaintInvalidation(); | |
| 894 } | |
| 895 } | |
| 896 } | |
| 897 | |
| 861 } // namespace blink | 898 } // namespace blink |
| 862 | 899 |
| 863 #ifndef NDEBUG | 900 #ifndef NDEBUG |
| 864 void showDocumentMarkers(const blink::DocumentMarkerController* controller) { | 901 void showDocumentMarkers(const blink::DocumentMarkerController* controller) { |
| 865 if (controller) | 902 if (controller) |
| 866 controller->showMarkers(); | 903 controller->showMarkers(); |
| 867 } | 904 } |
| 868 #endif | 905 #endif |
| OLD | NEW |