Home | History | Annotate | Download | only in dom
      1 /*
      2  * Copyright (C) 1999 Lars Knoll (knoll (at) kde.org)
      3  *           (C) 1999 Antti Koivisto (koivisto (at) kde.org)
      4  *           (C) 2001 Dirk Mueller (mueller (at) kde.org)
      5  *           (C) 2006 Alexey Proskuryakov (ap (at) webkit.org)
      6  * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
      7  * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
      8  * Copyright (C) Research In Motion Limited 2010. All rights reserved.
      9  *
     10  * This library is free software; you can redistribute it and/or
     11  * modify it under the terms of the GNU Library General Public
     12  * License as published by the Free Software Foundation; either
     13  * version 2 of the License, or (at your option) any later version.
     14  *
     15  * This library is distributed in the hope that it will be useful,
     16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     18  * Library General Public License for more details.
     19  *
     20  * You should have received a copy of the GNU Library General Public License
     21  * along with this library; see the file COPYING.LIB.  If not, write to
     22  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     23  * Boston, MA 02110-1301, USA.
     24  *
     25  */
     26 
     27 #include "config.h"
     28 #include "core/dom/DocumentMarkerController.h"
     29 
     30 #include "core/dom/Node.h"
     31 #include "core/dom/NodeTraversal.h"
     32 #include "core/dom/Range.h"
     33 #include "core/dom/RenderedDocumentMarker.h"
     34 #include "core/editing/TextIterator.h"
     35 #include "core/rendering/RenderObject.h"
     36 
     37 #ifndef NDEBUG
     38 #include <stdio.h>
     39 #endif
     40 
     41 namespace WebCore {
     42 
     43 namespace {
     44 
     45 DocumentMarker::MarkerTypeIndex MarkerTypeToMarkerIndex(DocumentMarker::MarkerType type)
     46 {
     47     switch (type) {
     48     case DocumentMarker::Spelling:
     49         return DocumentMarker::SpellingMarkerIndex;
     50     case DocumentMarker::Grammar:
     51         return DocumentMarker::GramarMarkerIndex;
     52     case DocumentMarker::TextMatch:
     53         return DocumentMarker::TextMatchMarkerIndex;
     54     case DocumentMarker::InvisibleSpellcheck:
     55         return DocumentMarker::InvisibleSpellcheckMarkerIndex;
     56     }
     57 
     58     ASSERT_NOT_REACHED();
     59     return DocumentMarker::SpellingMarkerIndex;
     60 }
     61 
     62 } // namespace
     63 
     64 inline bool DocumentMarkerController::possiblyHasMarkers(DocumentMarker::MarkerTypes types)
     65 {
     66     return m_possiblyExistingMarkerTypes.intersects(types);
     67 }
     68 
     69 DocumentMarkerController::DocumentMarkerController()
     70     : m_possiblyExistingMarkerTypes(0)
     71 {
     72 }
     73 
     74 DEFINE_EMPTY_DESTRUCTOR_WILL_BE_REMOVED(DocumentMarkerController);
     75 
     76 void DocumentMarkerController::clear()
     77 {
     78     m_markers.clear();
     79     m_possiblyExistingMarkerTypes = 0;
     80 }
     81 
     82 void DocumentMarkerController::addMarker(Range* range, DocumentMarker::MarkerType type, const String& description, uint32_t hash)
     83 {
     84     // Use a TextIterator to visit the potentially multiple nodes the range covers.
     85     for (TextIterator markedText(range); !markedText.atEnd(); markedText.advance()) {
     86         RefPtrWillBeRawPtr<Range> textPiece = markedText.range();
     87         addMarker(textPiece->startContainer(), DocumentMarker(type, textPiece->startOffset(), textPiece->endOffset(), description, hash));
     88     }
     89 }
     90 
     91 void DocumentMarkerController::addMarker(Range* range, DocumentMarker::MarkerType type, const String& description)
     92 {
     93     // Use a TextIterator to visit the potentially multiple nodes the range covers.
     94     for (TextIterator markedText(range); !markedText.atEnd(); markedText.advance()) {
     95         RefPtrWillBeRawPtr<Range> textPiece = markedText.range();
     96         addMarker(textPiece->startContainer(), DocumentMarker(type, textPiece->startOffset(), textPiece->endOffset(), description));
     97     }
     98 }
     99 
    100 void DocumentMarkerController::addMarker(Range* range, DocumentMarker::MarkerType type)
    101 {
    102     // Use a TextIterator to visit the potentially multiple nodes the range covers.
    103     for (TextIterator markedText(range); !markedText.atEnd(); markedText.advance()) {
    104         RefPtrWillBeRawPtr<Range> textPiece = markedText.range();
    105         addMarker(textPiece->startContainer(), DocumentMarker(type, textPiece->startOffset(), textPiece->endOffset()));
    106     }
    107 
    108 }
    109 
    110 void DocumentMarkerController::addTextMatchMarker(const Range* range, bool activeMatch)
    111 {
    112     // Use a TextIterator to visit the potentially multiple nodes the range covers.
    113     for (TextIterator markedText(range); !markedText.atEnd(); markedText.advance()) {
    114         RefPtrWillBeRawPtr<Range> textPiece = markedText.range();
    115         unsigned startOffset = textPiece->startOffset();
    116         unsigned endOffset = textPiece->endOffset();
    117         addMarker(textPiece->startContainer(), DocumentMarker(startOffset, endOffset, activeMatch));
    118         if (endOffset > startOffset) {
    119             // Rendered rects for markers in WebKit are not populated until each time
    120             // the markers are painted. However, we need it to happen sooner, because
    121             // the whole purpose of tickmarks on the scrollbar is to show where
    122             // matches off-screen are (that haven't been painted yet).
    123             Node* node = textPiece->startContainer();
    124             WillBeHeapVector<DocumentMarker*> markers = markersFor(node);
    125             toRenderedDocumentMarker(markers[markers.size() - 1])->setRenderedRect(range->boundingBox());
    126         }
    127     }
    128 }
    129 
    130 void DocumentMarkerController::prepareForDestruction()
    131 {
    132     clear();
    133 }
    134 
    135 void DocumentMarkerController::removeMarkers(Range* range, DocumentMarker::MarkerTypes markerTypes, RemovePartiallyOverlappingMarkerOrNot shouldRemovePartiallyOverlappingMarker)
    136 {
    137     for (TextIterator markedText(range); !markedText.atEnd(); markedText.advance()) {
    138         if (!possiblyHasMarkers(markerTypes))
    139             return;
    140         ASSERT(!m_markers.isEmpty());
    141 
    142         RefPtrWillBeRawPtr<Range> textPiece = markedText.range();
    143         int startOffset = textPiece->startOffset();
    144         int endOffset = textPiece->endOffset();
    145         removeMarkers(textPiece->startContainer(), startOffset, endOffset - startOffset, markerTypes, shouldRemovePartiallyOverlappingMarker);
    146     }
    147 }
    148 
    149 static bool startsFurther(const DocumentMarker& lhv, const DocumentMarker& rhv)
    150 {
    151     return lhv.startOffset() < rhv.startOffset();
    152 }
    153 
    154 static bool startsAfter(const DocumentMarker& marker, size_t startOffset)
    155 {
    156     return marker.startOffset() < startOffset;
    157 }
    158 
    159 static bool endsBefore(size_t startOffset, const DocumentMarker& rhv)
    160 {
    161     return startOffset < rhv.endOffset();
    162 }
    163 
    164 static bool compareByStart(const DocumentMarker* lhv, const DocumentMarker* rhv)
    165 {
    166     return startsFurther(*lhv, *rhv);
    167 }
    168 
    169 static bool doesNotOverlap(const DocumentMarker& lhv, const DocumentMarker& rhv)
    170 {
    171     return lhv.endOffset() < rhv.startOffset();
    172 }
    173 
    174 static bool doesNotInclude(const DocumentMarker& marker, size_t startOffset)
    175 {
    176     return marker.endOffset() < startOffset;
    177 }
    178 
    179 // Markers are stored in order sorted by their start offset.
    180 // Markers of the same type do not overlap each other.
    181 
    182 void DocumentMarkerController::addMarker(Node* node, const DocumentMarker& newMarker)
    183 {
    184     ASSERT(newMarker.endOffset() >= newMarker.startOffset());
    185     if (newMarker.endOffset() == newMarker.startOffset())
    186         return;
    187 
    188     m_possiblyExistingMarkerTypes.add(newMarker.type());
    189 
    190     OwnPtrWillBeMember<MarkerLists>& markers = m_markers.add(node, nullptr).storedValue->value;
    191     if (!markers) {
    192         markers = adoptPtrWillBeNoop(new MarkerLists);
    193         markers->grow(DocumentMarker::MarkerTypeIndexesCount);
    194     }
    195 
    196     DocumentMarker::MarkerTypeIndex markerListIndex = MarkerTypeToMarkerIndex(newMarker.type());
    197     if (!markers->at(markerListIndex)) {
    198         markers->insert(markerListIndex, adoptPtrWillBeNoop(new MarkerList));
    199     }
    200 
    201     OwnPtrWillBeMember<MarkerList>& list = markers->at(markerListIndex);
    202     if (list->isEmpty() || list->last().endOffset() < newMarker.startOffset()) {
    203         list->append(RenderedDocumentMarker(newMarker));
    204     } else {
    205         RenderedDocumentMarker toInsert(newMarker);
    206         if (toInsert.type() != DocumentMarker::TextMatch) {
    207             mergeOverlapping(list.get(), toInsert);
    208         } else {
    209             MarkerList::iterator pos = std::lower_bound(list->begin(), list->end(), toInsert, startsFurther);
    210             list->insert(pos - list->begin(), RenderedDocumentMarker(toInsert));
    211         }
    212     }
    213 
    214     // repaint the affected node
    215     if (node->renderer())
    216         node->renderer()->paintInvalidationForWholeRenderer();
    217 }
    218 
    219 void DocumentMarkerController::mergeOverlapping(MarkerList* list, DocumentMarker& toInsert)
    220 {
    221     MarkerList::iterator firstOverlapping = std::lower_bound(list->begin(), list->end(), toInsert, doesNotOverlap);
    222     size_t index = firstOverlapping - list->begin();
    223     list->insert(index, RenderedDocumentMarker(toInsert));
    224     MarkerList::iterator inserted = list->begin() + index;
    225     firstOverlapping = inserted + 1;
    226     for (MarkerList::iterator i = firstOverlapping; i != list->end() && i->startOffset() <= inserted->endOffset(); ) {
    227         inserted->setStartOffset(std::min(inserted->startOffset(), i->startOffset()));
    228         inserted->setEndOffset(std::max(inserted->endOffset(), i->endOffset()));
    229         list->remove(i - list->begin());
    230     }
    231 }
    232 
    233 // copies markers from srcNode to dstNode, applying the specified shift delta to the copies.  The shift is
    234 // useful if, e.g., the caller has created the dstNode from a non-prefix substring of the srcNode.
    235 void DocumentMarkerController::copyMarkers(Node* srcNode, unsigned startOffset, int length, Node* dstNode, int delta)
    236 {
    237     if (length <= 0)
    238         return;
    239 
    240     if (!possiblyHasMarkers(DocumentMarker::AllMarkers()))
    241         return;
    242     ASSERT(!m_markers.isEmpty());
    243 
    244     MarkerLists* markers = m_markers.get(srcNode);
    245     if (!markers)
    246         return;
    247 
    248     bool docDirty = false;
    249     for (size_t markerListIndex = 0; markerListIndex < DocumentMarker::MarkerTypeIndexesCount; ++markerListIndex) {
    250         OwnPtrWillBeMember<MarkerList>& list = (*markers)[markerListIndex];
    251         if (!list)
    252             continue;
    253 
    254         unsigned endOffset = startOffset + length - 1;
    255         MarkerList::iterator startPos = std::lower_bound(list->begin(), list->end(), startOffset, doesNotInclude);
    256         for (MarkerList::iterator i = startPos; i != list->end(); ++i) {
    257             DocumentMarker marker = *i;
    258 
    259             // stop if we are now past the specified range
    260             if (marker.startOffset() > endOffset)
    261                 break;
    262 
    263             // pin the marker to the specified range and apply the shift delta
    264             docDirty = true;
    265             if (marker.startOffset() < startOffset)
    266                 marker.setStartOffset(startOffset);
    267             if (marker.endOffset() > endOffset)
    268                 marker.setEndOffset(endOffset);
    269             marker.shiftOffsets(delta);
    270 
    271             addMarker(dstNode, marker);
    272         }
    273     }
    274 
    275     // repaint the affected node
    276     if (docDirty && dstNode->renderer())
    277         dstNode->renderer()->paintInvalidationForWholeRenderer();
    278 }
    279 
    280 void DocumentMarkerController::removeMarkers(Node* node, unsigned startOffset, int length, DocumentMarker::MarkerTypes markerTypes, RemovePartiallyOverlappingMarkerOrNot shouldRemovePartiallyOverlappingMarker)
    281 {
    282     if (length <= 0)
    283         return;
    284 
    285     if (!possiblyHasMarkers(markerTypes))
    286         return;
    287     ASSERT(!(m_markers.isEmpty()));
    288 
    289     MarkerLists* markers = m_markers.get(node);
    290     if (!markers)
    291         return;
    292 
    293     bool docDirty = false;
    294     size_t emptyListsCount = 0;
    295     for (size_t markerListIndex = 0; markerListIndex < DocumentMarker::MarkerTypeIndexesCount; ++markerListIndex) {
    296         OwnPtrWillBeMember<MarkerList>& list = (*markers)[markerListIndex];
    297         if (!list || list->isEmpty()) {
    298             if (list.get() && list->isEmpty())
    299                 list.clear();
    300             ++emptyListsCount;
    301             continue;
    302         }
    303         if (!markerTypes.contains(list->begin()->type()))
    304             continue;
    305         unsigned endOffset = startOffset + length;
    306         MarkerList::iterator startPos = std::upper_bound(list->begin(), list->end(), startOffset, endsBefore);
    307         for (MarkerList::iterator i = startPos; i != list->end(); ) {
    308             DocumentMarker marker = *i;
    309 
    310             // markers are returned in order, so stop if we are now past the specified range
    311             if (marker.startOffset() >= endOffset)
    312                 break;
    313 
    314             // at this point we know that marker and target intersect in some way
    315             docDirty = true;
    316 
    317             // pitch the old marker
    318             list->remove(i - list->begin());
    319 
    320             if (shouldRemovePartiallyOverlappingMarker) {
    321                 // Stop here. Don't add resulting slices back.
    322                 continue;
    323             }
    324 
    325             // add either of the resulting slices that are left after removing target
    326             if (startOffset > marker.startOffset()) {
    327                 DocumentMarker newLeft = marker;
    328                 newLeft.setEndOffset(startOffset);
    329                 size_t insertIndex = i - list->begin();
    330                 list->insert(insertIndex , RenderedDocumentMarker(newLeft));
    331                 // Move to the marker after the inserted one.
    332                 i = list->begin() + insertIndex + 1;
    333             }
    334             if (marker.endOffset() > endOffset) {
    335                 DocumentMarker newRight = marker;
    336                 newRight.setStartOffset(endOffset);
    337                 size_t insertIndex = i - list->begin();
    338                 list->insert(insertIndex, RenderedDocumentMarker(newRight));
    339                 // Move to the marker after the inserted one.
    340                 i = list->begin() + insertIndex + 1;
    341             }
    342         }
    343 
    344         if (list->isEmpty()) {
    345             list.clear();
    346             ++emptyListsCount;
    347         }
    348     }
    349 
    350     if (emptyListsCount == DocumentMarker::MarkerTypeIndexesCount) {
    351         m_markers.remove(node);
    352         if (m_markers.isEmpty())
    353             m_possiblyExistingMarkerTypes = 0;
    354     }
    355 
    356     // repaint the affected node
    357     if (docDirty && node->renderer())
    358         node->renderer()->paintInvalidationForWholeRenderer();
    359 }
    360 
    361 DocumentMarker* DocumentMarkerController::markerContainingPoint(const LayoutPoint& point, DocumentMarker::MarkerType markerType)
    362 {
    363     if (!possiblyHasMarkers(markerType))
    364         return 0;
    365     ASSERT(!(m_markers.isEmpty()));
    366 
    367     // outer loop: process each node that contains any markers
    368     MarkerMap::iterator end = m_markers.end();
    369     for (MarkerMap::iterator nodeIterator = m_markers.begin(); nodeIterator != end; ++nodeIterator) {
    370         // inner loop; process each marker in this node
    371         MarkerLists* markers = nodeIterator->value.get();
    372         OwnPtrWillBeMember<MarkerList>& list = (*markers)[MarkerTypeToMarkerIndex(markerType)];
    373         unsigned markerCount = list.get() ? list->size() : 0;
    374         for (unsigned markerIndex = 0; markerIndex < markerCount; ++markerIndex) {
    375             RenderedDocumentMarker& marker = list->at(markerIndex);
    376 
    377             if (marker.contains(point))
    378                 return &marker;
    379         }
    380     }
    381 
    382     return 0;
    383 }
    384 
    385 WillBeHeapVector<DocumentMarker*> DocumentMarkerController::markersFor(Node* node, DocumentMarker::MarkerTypes markerTypes)
    386 {
    387     WillBeHeapVector<DocumentMarker*> result;
    388 
    389     MarkerLists* markers = m_markers.get(node);
    390     if (!markers)
    391         return result;
    392 
    393     for (size_t markerListIndex = 0; markerListIndex < DocumentMarker::MarkerTypeIndexesCount; ++markerListIndex) {
    394         OwnPtrWillBeMember<MarkerList>& list = (*markers)[markerListIndex];
    395         if (!list || list->isEmpty() || !markerTypes.contains(list->begin()->type()))
    396             continue;
    397 
    398         for (size_t i = 0; i < list->size(); ++i)
    399             result.append(&(list->at(i)));
    400     }
    401 
    402     std::sort(result.begin(), result.end(), compareByStart);
    403     return result;
    404 }
    405 
    406 WillBeHeapVector<DocumentMarker*> DocumentMarkerController::markers()
    407 {
    408     WillBeHeapVector<DocumentMarker*> result;
    409     for (MarkerMap::iterator i = m_markers.begin(); i != m_markers.end(); ++i) {
    410         MarkerLists* markers = i->value.get();
    411         for (size_t markerListIndex = 0; markerListIndex < DocumentMarker::MarkerTypeIndexesCount; ++markerListIndex) {
    412             OwnPtrWillBeMember<MarkerList>& list = (*markers)[markerListIndex];
    413             for (size_t j = 0; list.get() && j < list->size(); ++j)
    414                 result.append(&(list->at(j)));
    415         }
    416     }
    417     std::sort(result.begin(), result.end(), compareByStart);
    418     return result;
    419 }
    420 
    421 WillBeHeapVector<DocumentMarker*> DocumentMarkerController::markersInRange(Range* range, DocumentMarker::MarkerTypes markerTypes)
    422 {
    423     if (!possiblyHasMarkers(markerTypes))
    424         return WillBeHeapVector<DocumentMarker*>();
    425 
    426     WillBeHeapVector<DocumentMarker*> foundMarkers;
    427 
    428     Node* startContainer = range->startContainer();
    429     ASSERT(startContainer);
    430     Node* endContainer = range->endContainer();
    431     ASSERT(endContainer);
    432 
    433     Node* pastLastNode = range->pastLastNode();
    434     for (Node* node = range->firstNode(); node != pastLastNode; node = NodeTraversal::next(*node)) {
    435         WillBeHeapVector<DocumentMarker*> markers = markersFor(node);
    436         WillBeHeapVector<DocumentMarker*>::const_iterator end = markers.end();
    437         for (WillBeHeapVector<DocumentMarker*>::const_iterator it = markers.begin(); it != end; ++it) {
    438             DocumentMarker* marker = *it;
    439             if (!markerTypes.contains(marker->type()))
    440                 continue;
    441             if (node == startContainer && marker->endOffset() <= static_cast<unsigned>(range->startOffset()))
    442                 continue;
    443             if (node == endContainer && marker->startOffset() >= static_cast<unsigned>(range->endOffset()))
    444                 continue;
    445             foundMarkers.append(marker);
    446         }
    447     }
    448     return foundMarkers;
    449 }
    450 
    451 Vector<IntRect> DocumentMarkerController::renderedRectsForMarkers(DocumentMarker::MarkerType markerType)
    452 {
    453     Vector<IntRect> result;
    454 
    455     if (!possiblyHasMarkers(markerType))
    456         return result;
    457     ASSERT(!(m_markers.isEmpty()));
    458 
    459     // outer loop: process each node
    460     MarkerMap::iterator end = m_markers.end();
    461     for (MarkerMap::iterator nodeIterator = m_markers.begin(); nodeIterator != end; ++nodeIterator) {
    462         // inner loop; process each marker in this node
    463         MarkerLists* markers = nodeIterator->value.get();
    464         for (size_t markerListIndex = 0; markerListIndex < DocumentMarker::MarkerTypeIndexesCount; ++markerListIndex) {
    465             OwnPtrWillBeMember<MarkerList>& list = (*markers)[markerListIndex];
    466             if (!list || list->isEmpty() || list->begin()->type() != markerType)
    467                 continue;
    468             for (unsigned markerIndex = 0; markerIndex < list->size(); ++markerIndex) {
    469                 const RenderedDocumentMarker& marker = list->at(markerIndex);
    470 
    471                 if (!marker.isRendered())
    472                     continue;
    473 
    474                 result.append(marker.renderedRect());
    475             }
    476         }
    477     }
    478 
    479     return result;
    480 }
    481 
    482 void DocumentMarkerController::trace(Visitor* visitor)
    483 {
    484     visitor->trace(m_markers);
    485 }
    486 
    487 void DocumentMarkerController::removeMarkers(Node* node, DocumentMarker::MarkerTypes markerTypes)
    488 {
    489     if (!possiblyHasMarkers(markerTypes))
    490         return;
    491     ASSERT(!m_markers.isEmpty());
    492 
    493     MarkerMap::iterator iterator = m_markers.find(node);
    494     if (iterator != m_markers.end())
    495         removeMarkersFromList(iterator, markerTypes);
    496 }
    497 
    498 void DocumentMarkerController::removeMarkers(DocumentMarker::MarkerTypes markerTypes)
    499 {
    500     if (!possiblyHasMarkers(markerTypes))
    501         return;
    502     ASSERT(!m_markers.isEmpty());
    503 
    504     Vector<const Node*> nodesWithMarkers;
    505     copyKeysToVector(m_markers, nodesWithMarkers);
    506     unsigned size = nodesWithMarkers.size();
    507     for (unsigned i = 0; i < size; ++i) {
    508         MarkerMap::iterator iterator = m_markers.find(nodesWithMarkers[i]);
    509         if (iterator != m_markers.end())
    510             removeMarkersFromList(iterator, markerTypes);
    511     }
    512 
    513     m_possiblyExistingMarkerTypes.remove(markerTypes);
    514 }
    515 
    516 void DocumentMarkerController::removeMarkersFromList(MarkerMap::iterator iterator, DocumentMarker::MarkerTypes markerTypes)
    517 {
    518     bool needsRepainting = false;
    519     bool nodeCanBeRemoved;
    520 
    521     size_t emptyListsCount = 0;
    522     if (markerTypes == DocumentMarker::AllMarkers()) {
    523         needsRepainting = true;
    524         nodeCanBeRemoved = true;
    525     } else {
    526         MarkerLists* markers = iterator->value.get();
    527 
    528         for (size_t markerListIndex = 0; markerListIndex < DocumentMarker::MarkerTypeIndexesCount; ++markerListIndex) {
    529             OwnPtrWillBeMember<MarkerList>& list = (*markers)[markerListIndex];
    530             if (!list || list->isEmpty()) {
    531                 if (list.get() && list->isEmpty())
    532                     list.clear();
    533                 ++emptyListsCount;
    534                 continue;
    535             }
    536             if (markerTypes.contains(list->begin()->type())) {
    537                 list->clear();
    538                 list.clear();
    539                 ++emptyListsCount;
    540                 needsRepainting = true;
    541             }
    542         }
    543 
    544         nodeCanBeRemoved = emptyListsCount == DocumentMarker::MarkerTypeIndexesCount;
    545     }
    546 
    547     if (needsRepainting) {
    548         if (RenderObject* renderer = iterator->key->renderer())
    549             renderer->paintInvalidationForWholeRenderer();
    550     }
    551 
    552     if (nodeCanBeRemoved) {
    553         m_markers.remove(iterator);
    554         if (m_markers.isEmpty())
    555             m_possiblyExistingMarkerTypes = 0;
    556     }
    557 }
    558 
    559 void DocumentMarkerController::repaintMarkers(DocumentMarker::MarkerTypes markerTypes)
    560 {
    561     if (!possiblyHasMarkers(markerTypes))
    562         return;
    563     ASSERT(!m_markers.isEmpty());
    564 
    565     // outer loop: process each markered node in the document
    566     MarkerMap::iterator end = m_markers.end();
    567     for (MarkerMap::iterator i = m_markers.begin(); i != end; ++i) {
    568         const Node* node = i->key;
    569 
    570         // inner loop: process each marker in the current node
    571         MarkerLists* markers = i->value.get();
    572         for (size_t markerListIndex = 0; markerListIndex < DocumentMarker::MarkerTypeIndexesCount; ++markerListIndex) {
    573             OwnPtrWillBeMember<MarkerList>& list = (*markers)[markerListIndex];
    574             if (!list || list->isEmpty() || !markerTypes.contains(list->begin()->type()))
    575                 continue;
    576 
    577             // cause the node to be redrawn
    578             if (RenderObject* renderer = node->renderer()) {
    579                 renderer->paintInvalidationForWholeRenderer();
    580                 break;
    581             }
    582         }
    583     }
    584 }
    585 
    586 void DocumentMarkerController::invalidateRenderedRectsForMarkersInRect(const LayoutRect& r)
    587 {
    588     // outer loop: process each markered node in the document
    589     MarkerMap::iterator end = m_markers.end();
    590     for (MarkerMap::iterator i = m_markers.begin(); i != end; ++i) {
    591 
    592         // inner loop: process each rect in the current node
    593         MarkerLists* markers = i->value.get();
    594         for (size_t markerListIndex = 0; markerListIndex < DocumentMarker::MarkerTypeIndexesCount; ++markerListIndex) {
    595             OwnPtrWillBeMember<MarkerList>& list = (*markers)[markerListIndex];
    596             for (size_t markerIndex = 0; list.get() && markerIndex < list->size(); ++markerIndex)
    597                 list->at(markerIndex).invalidate(r);
    598         }
    599     }
    600 }
    601 
    602 void DocumentMarkerController::shiftMarkers(Node* node, unsigned startOffset, int delta)
    603 {
    604     if (!possiblyHasMarkers(DocumentMarker::AllMarkers()))
    605         return;
    606     ASSERT(!m_markers.isEmpty());
    607 
    608     MarkerLists* markers = m_markers.get(node);
    609     if (!markers)
    610         return;
    611 
    612     bool docDirty = false;
    613     for (size_t markerListIndex = 0; markerListIndex < DocumentMarker::MarkerTypeIndexesCount; ++markerListIndex) {
    614         OwnPtrWillBeMember<MarkerList>& list = (*markers)[markerListIndex];
    615         if (!list)
    616             continue;
    617         MarkerList::iterator startPos = std::lower_bound(list->begin(), list->end(), startOffset, startsAfter);
    618         for (MarkerList::iterator marker = startPos; marker != list->end(); ++marker) {
    619             ASSERT((int)marker->startOffset() + delta >= 0);
    620             marker->shiftOffsets(delta);
    621             docDirty = true;
    622 
    623             // Marker moved, so previously-computed rendered rectangle is now invalid
    624             marker->invalidate();
    625         }
    626     }
    627 
    628     // repaint the affected node
    629     if (docDirty && node->renderer())
    630         node->renderer()->paintInvalidationForWholeRenderer();
    631 }
    632 
    633 void DocumentMarkerController::setMarkersActive(Range* range, bool active)
    634 {
    635     if (!possiblyHasMarkers(DocumentMarker::AllMarkers()))
    636         return;
    637     ASSERT(!m_markers.isEmpty());
    638 
    639     Node* startContainer = range->startContainer();
    640     Node* endContainer = range->endContainer();
    641 
    642     Node* pastLastNode = range->pastLastNode();
    643 
    644     for (Node* node = range->firstNode(); node != pastLastNode; node = NodeTraversal::next(*node)) {
    645         int startOffset = node == startContainer ? range->startOffset() : 0;
    646         int endOffset = node == endContainer ? range->endOffset() : INT_MAX;
    647         setMarkersActive(node, startOffset, endOffset, active);
    648     }
    649 }
    650 
    651 void DocumentMarkerController::setMarkersActive(Node* node, unsigned startOffset, unsigned endOffset, bool active)
    652 {
    653     MarkerLists* markers = m_markers.get(node);
    654     if (!markers)
    655         return;
    656 
    657     bool docDirty = false;
    658     OwnPtrWillBeMember<MarkerList>& list = (*markers)[MarkerTypeToMarkerIndex(DocumentMarker::TextMatch)];
    659     if (!list)
    660         return;
    661     MarkerList::iterator startPos = std::upper_bound(list->begin(), list->end(), startOffset, endsBefore);
    662     for (MarkerList::iterator marker = startPos; marker != list->end(); ++marker) {
    663 
    664         // Markers are returned in order, so stop if we are now past the specified range.
    665         if (marker->startOffset() >= endOffset)
    666             break;
    667 
    668         marker->setActiveMatch(active);
    669         docDirty = true;
    670     }
    671 
    672     // repaint the affected node
    673     if (docDirty && node->renderer())
    674         node->renderer()->paintInvalidationForWholeRenderer();
    675 }
    676 
    677 bool DocumentMarkerController::hasMarkers(Range* range, DocumentMarker::MarkerTypes markerTypes)
    678 {
    679     if (!possiblyHasMarkers(markerTypes))
    680         return false;
    681     ASSERT(!m_markers.isEmpty());
    682 
    683     Node* startContainer = range->startContainer();
    684     ASSERT(startContainer);
    685     Node* endContainer = range->endContainer();
    686     ASSERT(endContainer);
    687 
    688     Node* pastLastNode = range->pastLastNode();
    689     for (Node* node = range->firstNode(); node != pastLastNode; node = NodeTraversal::next(*node)) {
    690         WillBeHeapVector<DocumentMarker*> markers = markersFor(node);
    691         WillBeHeapVector<DocumentMarker*>::const_iterator end = markers.end();
    692         for (WillBeHeapVector<DocumentMarker*>::const_iterator it = markers.begin(); it != end; ++it) {
    693             DocumentMarker* marker = *it;
    694             if (!markerTypes.contains(marker->type()))
    695                 continue;
    696             if (node == startContainer && marker->endOffset() <= static_cast<unsigned>(range->startOffset()))
    697                 continue;
    698             if (node == endContainer && marker->startOffset() >= static_cast<unsigned>(range->endOffset()))
    699                 continue;
    700             return true;
    701         }
    702     }
    703     return false;
    704 }
    705 
    706 #ifndef NDEBUG
    707 void DocumentMarkerController::showMarkers() const
    708 {
    709     fprintf(stderr, "%d nodes have markers:\n", m_markers.size());
    710     MarkerMap::const_iterator end = m_markers.end();
    711     for (MarkerMap::const_iterator nodeIterator = m_markers.begin(); nodeIterator != end; ++nodeIterator) {
    712         const Node* node = nodeIterator->key;
    713         fprintf(stderr, "%p", node);
    714         MarkerLists* markers = m_markers.get(node);
    715         for (size_t markerListIndex = 0; markerListIndex < DocumentMarker::MarkerTypeIndexesCount; ++markerListIndex) {
    716             OwnPtrWillBeMember<MarkerList>& list = (*markers)[markerListIndex];
    717             for (unsigned markerIndex = 0; list.get() && markerIndex < list->size(); ++markerIndex) {
    718                 const DocumentMarker& marker = list->at(markerIndex);
    719                 fprintf(stderr, " %d:[%d:%d](%d)", marker.type(), marker.startOffset(), marker.endOffset(), marker.activeMatch());
    720             }
    721         }
    722 
    723         fprintf(stderr, "\n");
    724     }
    725 }
    726 #endif
    727 
    728 } // namespace WebCore
    729 
    730 #ifndef NDEBUG
    731 void showDocumentMarkers(const WebCore::DocumentMarkerController* controller)
    732 {
    733     if (controller)
    734         controller->showMarkers();
    735 }
    736 #endif
    737