Index: Source/core/dom/DocumentMarkerController.cpp |
diff --git a/Source/core/dom/DocumentMarkerController.cpp b/Source/core/dom/DocumentMarkerController.cpp |
deleted file mode 100644 |
index 148c90614fed9ac352283fe45e46a780284c8aab..0000000000000000000000000000000000000000 |
--- a/Source/core/dom/DocumentMarkerController.cpp |
+++ /dev/null |
@@ -1,743 +0,0 @@ |
-/* |
- * Copyright (C) 1999 Lars Knoll (knoll@kde.org) |
- * (C) 1999 Antti Koivisto (koivisto@kde.org) |
- * (C) 2001 Dirk Mueller (mueller@kde.org) |
- * (C) 2006 Alexey Proskuryakov (ap@webkit.org) |
- * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. |
- * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) |
- * Copyright (C) Research In Motion Limited 2010. All rights reserved. |
- * |
- * This library is free software; you can redistribute it and/or |
- * modify it under the terms of the GNU Library General Public |
- * License as published by the Free Software Foundation; either |
- * version 2 of the License, or (at your option) any later version. |
- * |
- * This library is distributed in the hope that it will be useful, |
- * but WITHOUT ANY WARRANTY; without even the implied warranty of |
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
- * Library General Public License for more details. |
- * |
- * You should have received a copy of the GNU Library General Public License |
- * along with this library; see the file COPYING.LIB. If not, write to |
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
- * Boston, MA 02110-1301, USA. |
- * |
- */ |
- |
-#include "config.h" |
-#include "core/dom/DocumentMarkerController.h" |
- |
-#include "core/dom/Node.h" |
-#include "core/dom/NodeTraversal.h" |
-#include "core/dom/Range.h" |
-#include "core/dom/RenderedDocumentMarker.h" |
-#include "core/dom/Text.h" |
-#include "core/editing/iterators/TextIterator.h" |
-#include "core/frame/FrameView.h" |
-#include "core/layout/LayoutObject.h" |
- |
-#ifndef NDEBUG |
-#include <stdio.h> |
-#endif |
- |
-namespace blink { |
- |
-MarkerRemoverPredicate::MarkerRemoverPredicate(const Vector<String>& words) |
- : m_words(words) |
-{ |
-} |
- |
-bool MarkerRemoverPredicate::operator()(const DocumentMarker& documentMarker, const Text& textNode) const |
-{ |
- unsigned start = documentMarker.startOffset(); |
- unsigned length = documentMarker.endOffset() - documentMarker.startOffset(); |
- |
- String markerText = textNode.data().substring(start, length); |
- return m_words.contains(markerText); |
-} |
- |
-namespace { |
- |
-DocumentMarker::MarkerTypeIndex MarkerTypeToMarkerIndex(DocumentMarker::MarkerType type) |
-{ |
- switch (type) { |
- case DocumentMarker::Spelling: |
- return DocumentMarker::SpellingMarkerIndex; |
- case DocumentMarker::Grammar: |
- return DocumentMarker::GramarMarkerIndex; |
- case DocumentMarker::TextMatch: |
- return DocumentMarker::TextMatchMarkerIndex; |
- case DocumentMarker::InvisibleSpellcheck: |
- return DocumentMarker::InvisibleSpellcheckMarkerIndex; |
- } |
- |
- ASSERT_NOT_REACHED(); |
- return DocumentMarker::SpellingMarkerIndex; |
-} |
- |
-} // namespace |
- |
-inline bool DocumentMarkerController::possiblyHasMarkers(DocumentMarker::MarkerTypes types) |
-{ |
- return m_possiblyExistingMarkerTypes.intersects(types); |
-} |
- |
-DocumentMarkerController::DocumentMarkerController() |
- : m_possiblyExistingMarkerTypes(0) |
-{ |
-} |
- |
-DEFINE_EMPTY_DESTRUCTOR_WILL_BE_REMOVED(DocumentMarkerController); |
- |
-void DocumentMarkerController::clear() |
-{ |
- m_markers.clear(); |
- m_possiblyExistingMarkerTypes = 0; |
-} |
- |
-void DocumentMarkerController::addMarker(const Position& start, const Position& end, DocumentMarker::MarkerType type, const String& description, uint32_t hash) |
-{ |
- // Use a TextIterator to visit the potentially multiple nodes the range covers. |
- for (TextIterator markedText(start, end); !markedText.atEnd(); markedText.advance()) { |
- addMarker(markedText.currentContainer(), DocumentMarker(type, markedText.startOffsetInCurrentContainer(), markedText.endOffsetInCurrentContainer(), description, hash)); |
- } |
-} |
- |
-void DocumentMarkerController::addTextMatchMarker(const Range* range, bool activeMatch) |
-{ |
- // Use a TextIterator to visit the potentially multiple nodes the range covers. |
- for (TextIterator markedText(range->startPosition(), range->endPosition()); !markedText.atEnd(); markedText.advance()) |
- addMarker(markedText.currentContainer(), DocumentMarker(markedText.startOffsetInCurrentContainer(), markedText.endOffsetInCurrentContainer(), activeMatch)); |
- // Don't invalidate tickmarks here. TextFinder invalidates tickmarks using a throttling algorithm. crbug.com/6819. |
-} |
- |
-void DocumentMarkerController::prepareForDestruction() |
-{ |
- clear(); |
-} |
- |
-void DocumentMarkerController::removeMarkers(TextIterator& markedText, DocumentMarker::MarkerTypes markerTypes, RemovePartiallyOverlappingMarkerOrNot shouldRemovePartiallyOverlappingMarker) |
-{ |
- for (; !markedText.atEnd(); markedText.advance()) { |
- if (!possiblyHasMarkers(markerTypes)) |
- return; |
- ASSERT(!m_markers.isEmpty()); |
- |
- int startOffset = markedText.startOffsetInCurrentContainer(); |
- int endOffset = markedText.endOffsetInCurrentContainer(); |
- removeMarkers(markedText.currentContainer(), startOffset, endOffset - startOffset, markerTypes, shouldRemovePartiallyOverlappingMarker); |
- } |
-} |
- |
-void DocumentMarkerController::removeMarkers(const EphemeralRange& range, DocumentMarker::MarkerTypes markerTypes, RemovePartiallyOverlappingMarkerOrNot shouldRemovePartiallyOverlappingMarker) |
-{ |
- TextIterator markedText(range.startPosition(), range.endPosition()); |
- DocumentMarkerController::removeMarkers(markedText, markerTypes, shouldRemovePartiallyOverlappingMarker); |
-} |
- |
-static bool startsFurther(const OwnPtrWillBeMember<RenderedDocumentMarker>& lhv, const DocumentMarker* rhv) |
-{ |
- return lhv->startOffset() < rhv->startOffset(); |
-} |
- |
-static bool startsAfter(const OwnPtrWillBeMember<RenderedDocumentMarker>& marker, size_t startOffset) |
-{ |
- return marker->startOffset() < startOffset; |
-} |
- |
-static bool endsBefore(size_t startOffset, const OwnPtrWillBeMember<RenderedDocumentMarker>& rhv) |
-{ |
- return startOffset < rhv->endOffset(); |
-} |
- |
-static bool compareByStart(const RawPtrWillBeMember<DocumentMarker>& lhv, const RawPtrWillBeMember<DocumentMarker>& rhv) |
-{ |
- return lhv->startOffset() < rhv->startOffset(); |
-} |
- |
-static bool doesNotOverlap(const OwnPtrWillBeMember<RenderedDocumentMarker>& lhv, const DocumentMarker* rhv) |
-{ |
- return lhv->endOffset() < rhv->startOffset(); |
-} |
- |
-static bool doesNotInclude(const OwnPtrWillBeMember<RenderedDocumentMarker>& marker, size_t startOffset) |
-{ |
- return marker->endOffset() < startOffset; |
-} |
- |
-static bool updateMarkerRenderedRect(Node* node, RenderedDocumentMarker& marker) |
-{ |
- RefPtrWillBeRawPtr<Range> range = Range::create(node->document()); |
- // The offsets of the marker may be out-dated, so check for exceptions. |
- TrackExceptionState exceptionState; |
- range->setStart(node, marker.startOffset(), exceptionState); |
- if (!exceptionState.hadException()) |
- range->setEnd(node, marker.endOffset(), IGNORE_EXCEPTION); |
- if (exceptionState.hadException()) |
- return marker.invalidateRenderedRect(); |
- return marker.setRenderedRect(LayoutRect(range->boundingBox())); |
-} |
- |
-// Markers are stored in order sorted by their start offset. |
-// Markers of the same type do not overlap each other. |
- |
-void DocumentMarkerController::addMarker(Node* node, const DocumentMarker& newMarker) |
-{ |
- ASSERT(newMarker.endOffset() >= newMarker.startOffset()); |
- if (newMarker.endOffset() == newMarker.startOffset()) |
- return; |
- |
- m_possiblyExistingMarkerTypes.add(newMarker.type()); |
- |
- OwnPtrWillBeMember<MarkerLists>& markers = m_markers.add(node, nullptr).storedValue->value; |
- if (!markers) { |
- markers = adoptPtrWillBeNoop(new MarkerLists); |
- markers->grow(DocumentMarker::MarkerTypeIndexesCount); |
- } |
- |
- DocumentMarker::MarkerTypeIndex markerListIndex = MarkerTypeToMarkerIndex(newMarker.type()); |
- if (!markers->at(markerListIndex)) { |
- markers->insert(markerListIndex, adoptPtrWillBeNoop(new MarkerList)); |
- } |
- |
- OwnPtrWillBeMember<MarkerList>& list = markers->at(markerListIndex); |
- OwnPtrWillBeRawPtr<RenderedDocumentMarker> newRenderedMarker = RenderedDocumentMarker::create(newMarker); |
- updateMarkerRenderedRect(node, *newRenderedMarker); |
- if (list->isEmpty() || list->last()->endOffset() < newMarker.startOffset()) { |
- list->append(newRenderedMarker.release()); |
- } else { |
- if (newMarker.type() != DocumentMarker::TextMatch) { |
- mergeOverlapping(list.get(), newRenderedMarker.release()); |
- } else { |
- MarkerList::iterator pos = std::lower_bound(list->begin(), list->end(), &newMarker, startsFurther); |
- list->insert(pos - list->begin(), newRenderedMarker.release()); |
- } |
- } |
- |
- // repaint the affected node |
- if (node->layoutObject()) |
- node->layoutObject()->setShouldDoFullPaintInvalidation(); |
-} |
- |
-void DocumentMarkerController::mergeOverlapping(MarkerList* list, PassOwnPtrWillBeRawPtr<RenderedDocumentMarker> toInsert) |
-{ |
- MarkerList::iterator firstOverlapping = std::lower_bound(list->begin(), list->end(), toInsert.get(), doesNotOverlap); |
- size_t index = firstOverlapping - list->begin(); |
- list->insert(index, toInsert); |
- MarkerList::iterator inserted = list->begin() + index; |
- firstOverlapping = inserted + 1; |
- for (MarkerList::iterator i = firstOverlapping; i != list->end() && (*i)->startOffset() <= (*inserted)->endOffset(); ) { |
- (*inserted)->setStartOffset(std::min((*inserted)->startOffset(), (*i)->startOffset())); |
- (*inserted)->setEndOffset(std::max((*inserted)->endOffset(), (*i)->endOffset())); |
- list->remove(i - list->begin()); |
- } |
-} |
- |
-// copies markers from srcNode to dstNode, applying the specified shift delta to the copies. The shift is |
-// useful if, e.g., the caller has created the dstNode from a non-prefix substring of the srcNode. |
-void DocumentMarkerController::copyMarkers(Node* srcNode, unsigned startOffset, int length, Node* dstNode, int delta) |
-{ |
- if (length <= 0) |
- return; |
- |
- if (!possiblyHasMarkers(DocumentMarker::AllMarkers())) |
- return; |
- ASSERT(!m_markers.isEmpty()); |
- |
- MarkerLists* markers = m_markers.get(srcNode); |
- if (!markers) |
- return; |
- |
- bool docDirty = false; |
- for (size_t markerListIndex = 0; markerListIndex < DocumentMarker::MarkerTypeIndexesCount; ++markerListIndex) { |
- OwnPtrWillBeMember<MarkerList>& list = (*markers)[markerListIndex]; |
- if (!list) |
- continue; |
- |
- unsigned endOffset = startOffset + length - 1; |
- MarkerList::iterator startPos = std::lower_bound(list->begin(), list->end(), startOffset, doesNotInclude); |
- for (MarkerList::iterator i = startPos; i != list->end(); ++i) { |
- DocumentMarker* marker = i->get(); |
- |
- // stop if we are now past the specified range |
- if (marker->startOffset() > endOffset) |
- break; |
- |
- // pin the marker to the specified range and apply the shift delta |
- docDirty = true; |
- if (marker->startOffset() < startOffset) |
- marker->setStartOffset(startOffset); |
- if (marker->endOffset() > endOffset) |
- marker->setEndOffset(endOffset); |
- marker->shiftOffsets(delta); |
- |
- addMarker(dstNode, *marker); |
- } |
- } |
- |
- // repaint the affected node |
- if (docDirty && dstNode->layoutObject()) |
- dstNode->layoutObject()->setShouldDoFullPaintInvalidation(); |
-} |
- |
-void DocumentMarkerController::removeMarkers(Node* node, unsigned startOffset, int length, DocumentMarker::MarkerTypes markerTypes, RemovePartiallyOverlappingMarkerOrNot shouldRemovePartiallyOverlappingMarker) |
-{ |
- if (length <= 0) |
- return; |
- |
- if (!possiblyHasMarkers(markerTypes)) |
- return; |
- ASSERT(!(m_markers.isEmpty())); |
- |
- MarkerLists* markers = m_markers.get(node); |
- if (!markers) |
- return; |
- |
- bool docDirty = false; |
- size_t emptyListsCount = 0; |
- for (size_t markerListIndex = 0; markerListIndex < DocumentMarker::MarkerTypeIndexesCount; ++markerListIndex) { |
- OwnPtrWillBeMember<MarkerList>& list = (*markers)[markerListIndex]; |
- if (!list || list->isEmpty()) { |
- if (list.get() && list->isEmpty()) |
- list.clear(); |
- ++emptyListsCount; |
- continue; |
- } |
- if (!markerTypes.contains((*list->begin())->type())) |
- continue; |
- unsigned endOffset = startOffset + length; |
- MarkerList::iterator startPos = std::upper_bound(list->begin(), list->end(), startOffset, endsBefore); |
- for (MarkerList::iterator i = startPos; i != list->end(); ) { |
- DocumentMarker marker(*i->get()); |
- |
- // markers are returned in order, so stop if we are now past the specified range |
- if (marker.startOffset() >= endOffset) |
- break; |
- |
- // at this point we know that marker and target intersect in some way |
- docDirty = true; |
- |
- // pitch the old marker |
- list->remove(i - list->begin()); |
- |
- if (shouldRemovePartiallyOverlappingMarker) { |
- // Stop here. Don't add resulting slices back. |
- continue; |
- } |
- |
- // add either of the resulting slices that are left after removing target |
- if (startOffset > marker.startOffset()) { |
- DocumentMarker newLeft = marker; |
- newLeft.setEndOffset(startOffset); |
- size_t insertIndex = i - list->begin(); |
- list->insert(insertIndex, RenderedDocumentMarker::create(newLeft)); |
- // Move to the marker after the inserted one. |
- i = list->begin() + insertIndex + 1; |
- } |
- if (marker.endOffset() > endOffset) { |
- DocumentMarker newRight = marker; |
- newRight.setStartOffset(endOffset); |
- size_t insertIndex = i - list->begin(); |
- list->insert(insertIndex, RenderedDocumentMarker::create(newRight)); |
- // Move to the marker after the inserted one. |
- i = list->begin() + insertIndex + 1; |
- } |
- } |
- |
- if (list->isEmpty()) { |
- list.clear(); |
- ++emptyListsCount; |
- } |
- } |
- |
- if (emptyListsCount == DocumentMarker::MarkerTypeIndexesCount) { |
- m_markers.remove(node); |
- if (m_markers.isEmpty()) |
- m_possiblyExistingMarkerTypes = 0; |
- } |
- |
- // repaint the affected node |
- if (docDirty && node->layoutObject()) |
- node->layoutObject()->setShouldDoFullPaintInvalidation(); |
-} |
- |
-DocumentMarker* DocumentMarkerController::markerContainingPoint(const LayoutPoint& point, DocumentMarker::MarkerType markerType) |
-{ |
- if (!possiblyHasMarkers(markerType)) |
- return 0; |
- ASSERT(!(m_markers.isEmpty())); |
- |
- // outer loop: process each node that contains any markers |
- MarkerMap::iterator end = m_markers.end(); |
- for (MarkerMap::iterator nodeIterator = m_markers.begin(); nodeIterator != end; ++nodeIterator) { |
- // inner loop; process each marker in this node |
- MarkerLists* markers = nodeIterator->value.get(); |
- OwnPtrWillBeMember<MarkerList>& list = (*markers)[MarkerTypeToMarkerIndex(markerType)]; |
- unsigned markerCount = list.get() ? list->size() : 0; |
- for (unsigned markerIndex = 0; markerIndex < markerCount; ++markerIndex) { |
- RenderedDocumentMarker* marker = list->at(markerIndex).get(); |
- if (marker->contains(point)) |
- return marker; |
- } |
- } |
- |
- return 0; |
-} |
- |
-DocumentMarkerVector DocumentMarkerController::markersFor(Node* node, DocumentMarker::MarkerTypes markerTypes) |
-{ |
- DocumentMarkerVector result; |
- |
- MarkerLists* markers = m_markers.get(node); |
- if (!markers) |
- return result; |
- |
- for (size_t markerListIndex = 0; markerListIndex < DocumentMarker::MarkerTypeIndexesCount; ++markerListIndex) { |
- OwnPtrWillBeMember<MarkerList>& list = (*markers)[markerListIndex]; |
- if (!list || list->isEmpty() || !markerTypes.contains((*list->begin())->type())) |
- continue; |
- |
- for (size_t i = 0; i < list->size(); ++i) |
- result.append(list->at(i).get()); |
- } |
- |
- std::sort(result.begin(), result.end(), compareByStart); |
- return result; |
-} |
- |
-DocumentMarkerVector DocumentMarkerController::markers() |
-{ |
- DocumentMarkerVector result; |
- for (MarkerMap::iterator i = m_markers.begin(); i != m_markers.end(); ++i) { |
- MarkerLists* markers = i->value.get(); |
- for (size_t markerListIndex = 0; markerListIndex < DocumentMarker::MarkerTypeIndexesCount; ++markerListIndex) { |
- OwnPtrWillBeMember<MarkerList>& list = (*markers)[markerListIndex]; |
- for (size_t j = 0; list.get() && j < list->size(); ++j) |
- result.append(list->at(j).get()); |
- } |
- } |
- std::sort(result.begin(), result.end(), compareByStart); |
- return result; |
-} |
- |
-DocumentMarkerVector DocumentMarkerController::markersInRange(const EphemeralRange& range, DocumentMarker::MarkerTypes markerTypes) |
-{ |
- if (!possiblyHasMarkers(markerTypes)) |
- return DocumentMarkerVector(); |
- |
- DocumentMarkerVector foundMarkers; |
- |
- Node* startContainer = range.startPosition().computeContainerNode(); |
- ASSERT(startContainer); |
- unsigned startOffset = static_cast<unsigned>(range.startPosition().computeOffsetInContainerNode()); |
- Node* endContainer = range.endPosition().computeContainerNode(); |
- ASSERT(endContainer); |
- unsigned endOffset = static_cast<unsigned>(range.endPosition().computeOffsetInContainerNode()); |
- |
- Node* pastLastNode = range.endPosition().nodeAsRangePastLastNode(); |
- for (Node* node = range.startPosition().nodeAsRangeFirstNode(); node != pastLastNode; node = NodeTraversal::next(*node)) { |
- for (DocumentMarker* marker : markersFor(node)) { |
- if (!markerTypes.contains(marker->type())) |
- continue; |
- if (node == startContainer && marker->endOffset() <= startOffset) |
- continue; |
- if (node == endContainer && marker->startOffset() >= endOffset) |
- continue; |
- foundMarkers.append(marker); |
- } |
- } |
- return foundMarkers; |
-} |
- |
-Vector<IntRect> DocumentMarkerController::renderedRectsForMarkers(DocumentMarker::MarkerType markerType) |
-{ |
- Vector<IntRect> result; |
- |
- if (!possiblyHasMarkers(markerType)) |
- return result; |
- ASSERT(!(m_markers.isEmpty())); |
- |
- // outer loop: process each node |
- MarkerMap::iterator end = m_markers.end(); |
- for (MarkerMap::iterator nodeIterator = m_markers.begin(); nodeIterator != end; ++nodeIterator) { |
- // inner loop; process each marker in this node |
- MarkerLists* markers = nodeIterator->value.get(); |
- for (size_t markerListIndex = 0; markerListIndex < DocumentMarker::MarkerTypeIndexesCount; ++markerListIndex) { |
- OwnPtrWillBeMember<MarkerList>& list = (*markers)[markerListIndex]; |
- if (!list || list->isEmpty() || (*list->begin())->type() != markerType) |
- continue; |
- for (unsigned markerIndex = 0; markerIndex < list->size(); ++markerIndex) { |
- RenderedDocumentMarker* marker = list->at(markerIndex).get(); |
- if (!marker->isRendered()) |
- continue; |
- result.append(marker->renderedRect()); |
- } |
- } |
- } |
- |
- return result; |
-} |
- |
-static void invalidatePaintForTickmarks(const Node& node) |
-{ |
- if (FrameView* frameView = node.document().view()) |
- frameView->invalidatePaintForTickmarks(); |
-} |
- |
-void DocumentMarkerController::updateRenderedRectsForMarkers() |
-{ |
- for (auto& nodeMarkers : m_markers) { |
- const Node* node = nodeMarkers.key; |
- for (auto& markerList : *nodeMarkers.value) { |
- if (!markerList) |
- continue; |
- bool markersChanged = false; |
- for (auto& marker : *markerList) |
- markersChanged |= updateMarkerRenderedRect(const_cast<Node*>(node), *marker); |
- |
- if (markersChanged && markerList->first()->type() == DocumentMarker::TextMatch) |
- invalidatePaintForTickmarks(*node); |
- } |
- } |
-} |
- |
-DEFINE_TRACE(DocumentMarkerController) |
-{ |
-#if ENABLE(OILPAN) |
- visitor->trace(m_markers); |
-#endif |
-} |
- |
-void DocumentMarkerController::removeMarkers(Node* node, DocumentMarker::MarkerTypes markerTypes) |
-{ |
- if (!possiblyHasMarkers(markerTypes)) |
- return; |
- ASSERT(!m_markers.isEmpty()); |
- |
- MarkerMap::iterator iterator = m_markers.find(node); |
- if (iterator != m_markers.end()) |
- removeMarkersFromList(iterator, markerTypes); |
-} |
- |
-void DocumentMarkerController::removeMarkers(const MarkerRemoverPredicate& shouldRemoveMarker) |
-{ |
- for (auto& nodeMarkers : m_markers) { |
- const Node& node = *nodeMarkers.key; |
- if (!node.isTextNode()) // MarkerRemoverPredicate requires a Text node. |
- continue; |
- MarkerLists& markers = *nodeMarkers.value; |
- for (size_t markerListIndex = 0; markerListIndex < DocumentMarker::MarkerTypeIndexesCount; ++markerListIndex) { |
- OwnPtrWillBeMember<MarkerList>& list = markers[markerListIndex]; |
- if (!list) |
- continue; |
- bool removedMarkers = false; |
- for (size_t j = list->size(); j > 0; --j) { |
- if (shouldRemoveMarker(*list->at(j - 1), static_cast<const Text&>(node))) { |
- list->remove(j - 1); |
- removedMarkers = true; |
- } |
- } |
- if (removedMarkers && markerListIndex == DocumentMarker::TextMatchMarkerIndex) |
- invalidatePaintForTickmarks(node); |
- } |
- } |
-} |
- |
-void DocumentMarkerController::removeMarkers(DocumentMarker::MarkerTypes markerTypes) |
-{ |
- if (!possiblyHasMarkers(markerTypes)) |
- return; |
- ASSERT(!m_markers.isEmpty()); |
- |
- Vector<const Node*> nodesWithMarkers; |
- copyKeysToVector(m_markers, nodesWithMarkers); |
- unsigned size = nodesWithMarkers.size(); |
- for (unsigned i = 0; i < size; ++i) { |
- MarkerMap::iterator iterator = m_markers.find(nodesWithMarkers[i]); |
- if (iterator != m_markers.end()) |
- removeMarkersFromList(iterator, markerTypes); |
- } |
- |
- m_possiblyExistingMarkerTypes.remove(markerTypes); |
-} |
- |
-void DocumentMarkerController::removeMarkersFromList(MarkerMap::iterator iterator, DocumentMarker::MarkerTypes markerTypes) |
-{ |
- bool needsRepainting = false; |
- bool nodeCanBeRemoved; |
- |
- size_t emptyListsCount = 0; |
- if (markerTypes == DocumentMarker::AllMarkers()) { |
- needsRepainting = true; |
- nodeCanBeRemoved = true; |
- } else { |
- MarkerLists* markers = iterator->value.get(); |
- |
- for (size_t markerListIndex = 0; markerListIndex < DocumentMarker::MarkerTypeIndexesCount; ++markerListIndex) { |
- OwnPtrWillBeMember<MarkerList>& list = (*markers)[markerListIndex]; |
- if (!list || list->isEmpty()) { |
- if (list.get() && list->isEmpty()) |
- list.clear(); |
- ++emptyListsCount; |
- continue; |
- } |
- if (markerTypes.contains((*list->begin())->type())) { |
- list->clear(); |
- list.clear(); |
- ++emptyListsCount; |
- needsRepainting = true; |
- } |
- } |
- |
- nodeCanBeRemoved = emptyListsCount == DocumentMarker::MarkerTypeIndexesCount; |
- } |
- |
- if (needsRepainting) { |
- const Node& node = *iterator->key; |
- if (LayoutObject* layoutObject = node.layoutObject()) |
- layoutObject->setShouldDoFullPaintInvalidation(); |
- invalidatePaintForTickmarks(node); |
- } |
- |
- if (nodeCanBeRemoved) { |
- m_markers.remove(iterator); |
- if (m_markers.isEmpty()) |
- m_possiblyExistingMarkerTypes = 0; |
- } |
-} |
- |
-void DocumentMarkerController::repaintMarkers(DocumentMarker::MarkerTypes markerTypes) |
-{ |
- if (!possiblyHasMarkers(markerTypes)) |
- return; |
- ASSERT(!m_markers.isEmpty()); |
- |
- // outer loop: process each markered node in the document |
- MarkerMap::iterator end = m_markers.end(); |
- for (MarkerMap::iterator i = m_markers.begin(); i != end; ++i) { |
- const Node* node = i->key; |
- |
- // inner loop: process each marker in the current node |
- MarkerLists* markers = i->value.get(); |
- for (size_t markerListIndex = 0; markerListIndex < DocumentMarker::MarkerTypeIndexesCount; ++markerListIndex) { |
- OwnPtrWillBeMember<MarkerList>& list = (*markers)[markerListIndex]; |
- if (!list || list->isEmpty() || !markerTypes.contains((*list->begin())->type())) |
- continue; |
- |
- // cause the node to be redrawn |
- if (LayoutObject* layoutObject = node->layoutObject()) { |
- layoutObject->setShouldDoFullPaintInvalidation(); |
- break; |
- } |
- } |
- } |
-} |
- |
-void DocumentMarkerController::shiftMarkers(Node* node, unsigned startOffset, int delta) |
-{ |
- if (!possiblyHasMarkers(DocumentMarker::AllMarkers())) |
- return; |
- ASSERT(!m_markers.isEmpty()); |
- |
- MarkerLists* markers = m_markers.get(node); |
- if (!markers) |
- return; |
- |
- bool docDirty = false; |
- for (size_t markerListIndex = 0; markerListIndex < DocumentMarker::MarkerTypeIndexesCount; ++markerListIndex) { |
- OwnPtrWillBeMember<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 ENABLE(ASSERT) |
- int startOffset = (*marker)->startOffset(); |
- ASSERT(startOffset + delta >= 0); |
-#endif |
- (*marker)->shiftOffsets(delta); |
- docDirty = true; |
- |
- updateMarkerRenderedRect(node, **marker); |
- } |
- } |
- |
- // repaint the affected node |
- if (docDirty && node->layoutObject()) |
- node->layoutObject()->setShouldDoFullPaintInvalidation(); |
-} |
- |
-void DocumentMarkerController::setMarkersActive(Range* range, bool active) |
-{ |
- if (!possiblyHasMarkers(DocumentMarker::AllMarkers())) |
- return; |
- ASSERT(!m_markers.isEmpty()); |
- |
- Node* startContainer = range->startContainer(); |
- Node* endContainer = range->endContainer(); |
- |
- Node* pastLastNode = range->pastLastNode(); |
- |
- for (Node* node = range->firstNode(); node != pastLastNode; node = NodeTraversal::next(*node)) { |
- int startOffset = node == startContainer ? range->startOffset() : 0; |
- int endOffset = node == endContainer ? range->endOffset() : INT_MAX; |
- setMarkersActive(node, startOffset, endOffset, active); |
- } |
-} |
- |
-void DocumentMarkerController::setMarkersActive(Node* node, unsigned startOffset, unsigned endOffset, bool active) |
-{ |
- MarkerLists* markers = m_markers.get(node); |
- if (!markers) |
- return; |
- |
- bool docDirty = false; |
- OwnPtrWillBeMember<MarkerList>& list = (*markers)[MarkerTypeToMarkerIndex(DocumentMarker::TextMatch)]; |
- if (!list) |
- return; |
- MarkerList::iterator startPos = std::upper_bound(list->begin(), list->end(), startOffset, endsBefore); |
- for (MarkerList::iterator marker = startPos; marker != list->end(); ++marker) { |
- |
- // Markers are returned in order, so stop if we are now past the specified range. |
- if ((*marker)->startOffset() >= endOffset) |
- break; |
- |
- (*marker)->setActiveMatch(active); |
- docDirty = true; |
- } |
- |
- // repaint the affected node |
- if (docDirty && node->layoutObject()) |
- node->layoutObject()->setShouldDoFullPaintInvalidation(); |
-} |
- |
-#ifndef NDEBUG |
-void DocumentMarkerController::showMarkers() const |
-{ |
- fprintf(stderr, "%d nodes have markers:\n", m_markers.size()); |
- MarkerMap::const_iterator end = m_markers.end(); |
- for (MarkerMap::const_iterator nodeIterator = m_markers.begin(); nodeIterator != end; ++nodeIterator) { |
- const Node* node = nodeIterator->key; |
- fprintf(stderr, "%p", node); |
- MarkerLists* markers = m_markers.get(node); |
- for (size_t markerListIndex = 0; markerListIndex < DocumentMarker::MarkerTypeIndexesCount; ++markerListIndex) { |
- OwnPtrWillBeMember<MarkerList>& list = (*markers)[markerListIndex]; |
- for (unsigned markerIndex = 0; list.get() && markerIndex < list->size(); ++markerIndex) { |
- DocumentMarker* marker = list->at(markerIndex).get(); |
- fprintf(stderr, " %d:[%d:%d](%d)", marker->type(), marker->startOffset(), marker->endOffset(), marker->activeMatch()); |
- } |
- } |
- |
- fprintf(stderr, "\n"); |
- } |
-} |
-#endif |
- |
-} // namespace blink |
- |
-#ifndef NDEBUG |
-void showDocumentMarkers(const blink::DocumentMarkerController* controller) |
-{ |
- if (controller) |
- controller->showMarkers(); |
-} |
-#endif |