void DocumentMarkerController::shiftMarkers(Node* node, unsigned startOffset, int delta) { if (!possiblyHasMarkers(DocumentMarker::AllMarkers())) return; ASSERT(!m_markers.isEmpty()); MarkerList* list = m_markers.get(node); if (!list) return; bool docDirty = false; for (size_t i = 0; i != list->size(); ++i) { RenderedDocumentMarker& marker = list->at(i); if (marker.startOffset() >= startOffset) { ASSERT((int)marker.startOffset() + delta >= 0); marker.shiftOffsets(delta); docDirty = true; // Marker moved, so previously-computed rendered rectangle is now invalid marker.invalidate(); } } // repaint the affected node if (docDirty && node->renderer()) node->renderer()->repaint(); }
void DocumentMarkerController::shiftMarkers(Node* node, unsigned startOffset, int delta) { if (!possiblyHasMarkers(DocumentMarker::AllMarkers())) return; ASSERT(!m_markers.isEmpty()); MarkerList* list = m_markers.get(node); if (!list) return; bool docDirty = false; for (size_t i = 0; i != list->size(); ) { RenderedDocumentMarker& marker = list->at(i); #if PLATFORM(IOS) int targetStartOffset = marker.startOffset() + delta; int targetEndOffset = marker.endOffset() + delta; if (targetStartOffset >= node->maxCharacterOffset() || targetEndOffset <= 0) { list->remove(i); continue; } #endif if (marker.startOffset() >= startOffset) { ASSERT((int)marker.startOffset() + delta >= 0); marker.shiftOffsets(delta); docDirty = true; // Marker moved, so previously-computed rendered rectangle is now invalid marker.invalidate(); #if !PLATFORM(IOS) } #else // FIXME: Inserting text inside a DocumentMarker does not grow the marker. // See <https://bugs.webkit.org/show_bug.cgi?id=62504>. } else if (marker.endOffset() > startOffset) {
Vector<DocumentMarker*> DocumentMarkerController::markersInRange(Range* range, DocumentMarker::MarkerTypes markerTypes) { if (!possiblyHasMarkers(markerTypes)) return Vector<DocumentMarker*>(); Vector<DocumentMarker*> foundMarkers; Node* startContainer = range->startContainer(); ASSERT(startContainer); Node* endContainer = range->endContainer(); ASSERT(endContainer); Node* pastLastNode = range->pastLastNode(); for (Node* node = range->firstNode(); node != pastLastNode; node = NodeTraversal::next(node)) { Vector<DocumentMarker*> markers = markersFor(node); Vector<DocumentMarker*>::const_iterator end = markers.end(); for (Vector<DocumentMarker*>::const_iterator it = markers.begin(); it != end; ++it) { DocumentMarker* marker = *it; if (!markerTypes.contains(marker->type())) continue; if (node == startContainer && marker->endOffset() <= static_cast<unsigned>(range->startOffset())) continue; if (node == endContainer && marker->startOffset() >= static_cast<unsigned>(range->endOffset())) continue; foundMarkers.append(marker); } } return foundMarkers; }
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) { OwnPtr<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; // Marker moved, so previously-computed rendered rectangle is now invalid (*marker)->invalidate(); } } // repaint the affected node if (docDirty && node->renderer()) node->renderer()->doNotUseInvalidatePaintForWholeRendererSynchronously(); }
void DocumentMarkerController::updateRectsForInvalidatedMarkersOfType(DocumentMarker::MarkerType markerType) { if (!possiblyHasMarkers(markerType)) return; ASSERT(!(m_markers.isEmpty())); bool needsLayoutIfAnyRectsAreDirty = true; for (auto& nodeAndMarkers : m_markers) { Node& node = *nodeAndMarkers.key; for (auto& marker : *nodeAndMarkers.value) { if (marker.type() != markerType) continue; if (marker.isValid()) continue; // We'll do up to one layout per call if we have any dirty markers. if (needsLayoutIfAnyRectsAreDirty) { updateMainFrameLayoutIfNeeded(m_document); needsLayoutIfAnyRectsAreDirty = false; } updateRenderedRectsForMarker(marker, node); } } }
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) { OwnPtr<MarkerList>& list = (*markers)[markerListIndex]; if (!list || list->isEmpty() || !markerTypes.contains((*list->begin())->type())) continue; // cause the node to be redrawn if (RenderObject* renderer = node->renderer()) { renderer->doNotUseInvalidatePaintForWholeRendererSynchronously(); break; } } } }
void DocumentMarkerController::repaintMarkers(DocumentMarker::MarkerTypes markerTypes) { if (!possiblyHasMarkers(markerTypes)) return; ASSERT(!m_markers.isEmpty()); // outer loop: process each markered node in the document for (auto& marker : m_markers) { Node* node = marker.key.get(); // inner loop: process each marker in the current node bool nodeNeedsRepaint = false; for (auto& documentMarker : *marker.value) { if (markerTypes.contains(documentMarker.type())) { nodeNeedsRepaint = true; break; } } if (!nodeNeedsRepaint) continue; // cause the node to be redrawn if (auto renderer = node->renderer()) renderer->repaint(); } }
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 MarkerList* list = nodeIterator->value.get(); unsigned markerCount = list->size(); for (unsigned markerIndex = 0; markerIndex < markerCount; ++markerIndex) { RenderedDocumentMarker& marker = list->at(markerIndex); // skip marker that is wrong type if (marker.type() != markerType) continue; if (marker.contains(point)) return ▮ } } return 0; }
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 MarkerList* list = nodeIterator->value.get(); unsigned markerCount = list->size(); for (unsigned markerIndex = 0; markerIndex < markerCount; ++markerIndex) { const RenderedDocumentMarker& marker = list->at(markerIndex); // skip marker that is wrong type if (marker.type() != markerType) continue; if (!marker.isRendered()) continue; result.append(marker.renderedRect()); } } return result; }
bool DocumentMarkerController::hasMarkers(Range* range, DocumentMarker::MarkerTypes markerTypes) { if (!possiblyHasMarkers(markerTypes)) return false; ASSERT(!m_markers.isEmpty()); Node* startContainer = range->startContainer(); ASSERT(startContainer); Node* endContainer = range->endContainer(); ASSERT(endContainer); Node* pastLastNode = range->pastLastNode(); for (Node* node = range->firstNode(); node != pastLastNode; node = node->traverseNextNode()) { Vector<DocumentMarker*> markers = markersFor(node); Vector<DocumentMarker*>::const_iterator end = markers.end(); for (Vector<DocumentMarker*>::const_iterator it = markers.begin(); it != end; ++it) { DocumentMarker* marker = *it; if (!markerTypes.contains(marker->type())) continue; if (node == startContainer && marker->endOffset() <= static_cast<unsigned>(range->startOffset())) continue; if (node == endContainer && marker->startOffset() >= static_cast<unsigned>(range->endOffset())) continue; return true; } } return false; }
void DocumentMarkerController::clearDescriptionOnMarkersIntersectingRange(Range* range, DocumentMarker::MarkerTypes markerTypes) { if (!possiblyHasMarkers(markerTypes)) 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 = node->traverseNextNode()) { unsigned startOffset = node == startContainer ? range->startOffset() : 0; unsigned endOffset = node == endContainer ? static_cast<unsigned>(range->endOffset()) : std::numeric_limits<unsigned>::max(); MarkerList* list = m_markers.get(node); if (!list) continue; for (size_t i = 0; i < list->size(); ++i) { DocumentMarker& marker = list->at(i); // markers are returned in order, so stop if we are now past the specified range if (marker.startOffset() >= endOffset) break; // skip marker that is wrong type or before target if (marker.endOffset() <= startOffset || !markerTypes.contains(marker.type())) { i++; continue; } marker.clearDescription(); } } }
Vector<RenderedDocumentMarker*> DocumentMarkerController::markersInRange(Range* range, DocumentMarker::MarkerTypes markerTypes) { if (!possiblyHasMarkers(markerTypes)) return Vector<RenderedDocumentMarker*>(); Vector<RenderedDocumentMarker*> foundMarkers; Node* startContainer = range->startContainer(); ASSERT(startContainer); Node* endContainer = range->endContainer(); ASSERT(endContainer); Node* pastLastNode = range->pastLastNode(); for (Node* node = range->firstNode(); node != pastLastNode; node = NodeTraversal::next(*node)) { for (auto* marker : markersFor(node)) { if (!markerTypes.contains(marker->type())) continue; if (node == startContainer && marker->endOffset() <= static_cast<unsigned>(range->startOffset())) continue; if (node == endContainer && marker->startOffset() >= static_cast<unsigned>(range->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) { OwnPtr<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; }
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) { Node* node = i->key.get(); // inner loop: process each marker in the current node MarkerList* list = i->value.get(); bool nodeNeedsRepaint = false; for (size_t i = 0; i != list->size(); ++i) { DocumentMarker marker = list->at(i); // skip nodes that are not of the specified type if (markerTypes.contains(marker.type())) { nodeNeedsRepaint = true; break; } } if (!nodeNeedsRepaint) continue; // cause the node to be redrawn if (auto renderer = node->renderer()) renderer->repaint(); } }
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); }
Vector<FloatRect> DocumentMarkerController::renderedRectsForMarkers(DocumentMarker::MarkerType markerType) { Vector<FloatRect> result; if (!possiblyHasMarkers(markerType)) return result; ASSERT(!(m_markers.isEmpty())); Frame* frame = m_document.frame(); if (!frame) return result; FrameView* frameView = frame->view(); if (!frameView) return result; updateRectsForInvalidatedMarkersOfType(markerType); bool isSubframe = !frame->isMainFrame(); IntRect subframeClipRect; if (isSubframe) subframeClipRect = frameView->windowToContents(frameView->windowClipRect()); for (auto& nodeAndMarkers : m_markers) { Node& node = *nodeAndMarkers.key; FloatRect overflowClipRect; if (RenderObject* renderer = node.renderer()) overflowClipRect = renderer->absoluteClippedOverflowRect(); for (auto& marker : *nodeAndMarkers.value) { if (marker.type() != markerType) continue; auto renderedRects = marker.unclippedAbsoluteRects(); // Clip document markers by their overflow clip. if (node.renderer()) { for (auto& rect : renderedRects) rect.intersect(overflowClipRect); } // Clip subframe document markers by their frame. if (isSubframe) { for (auto& rect : renderedRects) rect.intersect(subframeClipRect); } for (const auto& rect : renderedRects) { if (!rect.isEmpty()) result.append(rect); } } } return result; }
void DocumentMarkerController::removeMarkers(Range* range, DocumentMarker::MarkerTypes markerTypes, RemovePartiallyOverlappingMarkerOrNot shouldRemovePartiallyOverlappingMarker) { for (TextIterator markedText(range); !markedText.atEnd(); markedText.advance()) { if (!possiblyHasMarkers(markerTypes)) return; ASSERT(!m_markers.isEmpty()); RefPtr<Range> textPiece = markedText.range(); int startOffset = textPiece->startOffset(); int endOffset = textPiece->endOffset(); removeMarkers(textPiece->startContainer(), startOffset, endOffset - startOffset, markerTypes, shouldRemovePartiallyOverlappingMarker); } }
void DocumentMarkerController::removeMarkers(DocumentMarker::MarkerTypes markerTypes) { if (!possiblyHasMarkers(markerTypes)) return; ASSERT(!m_markers.isEmpty()); // outer loop: process each markered node in the document MarkerMap markerMapCopy = m_markers; MarkerMap::iterator end = markerMapCopy.end(); for (MarkerMap::iterator i = markerMapCopy.begin(); i != end; ++i) removeMarkersFromList(i->first.get(), i->second, markerTypes); m_possiblyExistingMarkerTypes.remove(markerTypes); }
void DocumentMarkerController::removeMarkers(DocumentMarker::MarkerTypes markerTypes) { if (!possiblyHasMarkers(markerTypes)) return; ASSERT(!m_markers.isEmpty()); Vector<RefPtr<Node>> nodesWithMarkers; copyKeysToVector(m_markers, nodesWithMarkers); for (auto& node : nodesWithMarkers) { auto iterator = m_markers.find(node); if (iterator != m_markers.end()) removeMarkersFromList(iterator, markerTypes); } m_possiblyExistingMarkerTypes.remove(markerTypes); }
void DocumentMarkerController::setMarkersActive(Range* range, bool active) { if (!possiblyHasMarkers(DocumentMarker::AllMarkers())) return; ASSERT(!m_markers.isEmpty()); ExceptionCode ec = 0; Node* startContainer = range->startContainer(ec); Node* endContainer = range->endContainer(ec); Node* pastLastNode = range->pastLastNode(); for (Node* node = range->firstNode(); node != pastLastNode; node = node->traverseNextNode()) { int startOffset = node == startContainer ? range->startOffset(ec) : 0; int endOffset = node == endContainer ? range->endOffset(ec) : INT_MAX; setMarkersActive(node, startOffset, endOffset, active); } }
void DocumentMarkerController::removeMarkers(DocumentMarker::MarkerTypes markerTypes) { if (!possiblyHasMarkers(markerTypes)) return; ASSERT(!m_markers.isEmpty()); Vector<RefPtr<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); }
// 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) { OwnPtr<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->renderer()) dstNode->renderer()->doNotUseInvalidatePaintForWholeRendererSynchronously(); }
DocumentMarker* DocumentMarkerController::markerContainingPoint(const LayoutPoint& point, DocumentMarker::MarkerType markerType) { if (!possiblyHasMarkers(markerType)) return nullptr; ASSERT(!(m_markers.isEmpty())); updateRectsForInvalidatedMarkersOfType(markerType); for (auto& nodeAndMarkers : m_markers) { for (auto& marker : *nodeAndMarkers.value) { if (marker.type() != markerType) continue; if (marker.contains(point)) return ▮ } } return nullptr; }
// 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()); MarkerList* list = m_markers.get(srcNode); if (!list) return; bool docDirty = false; unsigned endOffset = startOffset + length - 1; for (size_t i = 0; i != list->size(); ++i) { DocumentMarker marker = list->at(i); // stop if we are now past the specified range if (marker.startOffset() > endOffset) break; // skip marker that is before the specified range or is the wrong type if (marker.endOffset() < startOffset) continue; // 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->renderer()) dstNode->renderer()->repaint(); }
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(); OwnPtr<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; }
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) { OwnPtr<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->renderer()) node->renderer()->doNotUseInvalidatePaintForWholeRendererSynchronously(); }
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())); MarkerList* list = m_markers.get(node); if (!list) return; bool docDirty = false; unsigned endOffset = startOffset + length; for (size_t i = 0; i < list->size();) { DocumentMarker marker = list->at(i); // markers are returned in order, so stop if we are now past the specified range if (marker.startOffset() >= endOffset) break; // skip marker that is wrong type or before target if (marker.endOffset() <= startOffset || !markerTypes.contains(marker.type())) { i++; continue; } // at this point we know that marker and target intersect in some way docDirty = true; // pitch the old marker list->remove(i); 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); list->insert(i, RenderedDocumentMarker(newLeft)); // i now points to the newly-inserted node, but we want to skip that one i++; } if (marker.endOffset() > endOffset) { DocumentMarker newRight = marker; newRight.setStartOffset(endOffset); list->insert(i, RenderedDocumentMarker(newRight)); // i now points to the newly-inserted node, but we want to skip that one i++; } } if (list->isEmpty()) { m_markers.remove(node); if (m_markers.isEmpty()) m_possiblyExistingMarkerTypes = 0; } // repaint the affected node if (docDirty && node->renderer()) node->renderer()->repaint(); }