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 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 70 case DocumentMarker::kComposition: | 70 case DocumentMarker::kComposition: |
| 71 return DocumentMarker::kCompositionMarkerIndex; | 71 return DocumentMarker::kCompositionMarkerIndex; |
| 72 } | 72 } |
| 73 | 73 |
| 74 NOTREACHED(); | 74 NOTREACHED(); |
| 75 return DocumentMarker::kSpellingMarkerIndex; | 75 return DocumentMarker::kSpellingMarkerIndex; |
| 76 } | 76 } |
| 77 | 77 |
| 78 } // namespace | 78 } // namespace |
| 79 | 79 |
| 80 static bool StartsFurther(const Member<DocumentMarker>& lhv, | |
| 81 const DocumentMarker* rhv) { | |
| 82 return lhv->StartOffset() < rhv->StartOffset(); | |
| 83 } | |
| 84 | |
| 85 static bool EndsBefore(size_t start_offset, const Member<DocumentMarker>& rhv) { | |
| 86 return start_offset < rhv->EndOffset(); | |
| 87 } | |
| 88 | |
| 89 static bool CompareByStart(const Member<DocumentMarker>& lhv, | |
| 90 const Member<DocumentMarker>& rhv) { | |
| 91 return lhv->StartOffset() < rhv->StartOffset(); | |
| 92 } | |
| 93 | |
| 94 static bool DoesNotOverlap(const Member<DocumentMarker>& lhv, | |
| 95 const DocumentMarker* rhv) { | |
| 96 return lhv->EndOffset() < rhv->StartOffset(); | |
| 97 } | |
| 98 | |
| 99 bool DocumentMarkerList::IsEmpty() const { | |
| 100 return markers_.IsEmpty(); | |
| 101 } | |
| 102 | |
| 103 void DocumentMarkerList::Add(DocumentMarker* marker) { | |
| 104 if (markers_.IsEmpty() || | |
| 105 markers_.back()->EndOffset() < marker->StartOffset()) { | |
| 106 markers_.push_back(marker); | |
| 107 } else { | |
| 108 if (marker->GetType() != DocumentMarker::kTextMatch && | |
| 109 marker->GetType() != DocumentMarker::kComposition) { | |
| 110 MergeOverlapping(marker); | |
| 111 } else { | |
| 112 const auto pos = std::lower_bound(markers_.begin(), markers_.end(), | |
| 113 marker, StartsFurther); | |
| 114 markers_.insert(pos - markers_.begin(), marker); | |
| 115 } | |
| 116 } | |
| 117 } | |
| 118 | |
| 119 void DocumentMarkerList::Clear() { | |
| 120 markers_.Clear(); | |
| 121 } | |
| 122 | |
| 123 void DocumentMarkerList::AppendMarkersToInputList( | |
| 124 DocumentMarkerVector* input_list) const { | |
| 125 input_list->AppendVector(markers_); | |
| 126 } | |
| 127 | |
| 128 bool DocumentMarkerList::MoveMarkers(int length, DocumentMarkerList* dst_list) { | |
| 129 DCHECK_GT(length, 0); | |
| 130 bool didMoveMarker = false; | |
| 131 unsigned end_offset = length - 1; | |
| 132 | |
| 133 DocumentMarkerVector::iterator it; | |
| 134 for (it = markers_.begin(); it != markers_.end(); ++it) { | |
| 135 DocumentMarker& marker = **it; | |
| 136 if (marker.StartOffset() > end_offset) | |
| 137 break; | |
| 138 | |
| 139 // pin the marker to the specified range and apply the shift delta | |
| 140 if (marker.EndOffset() > end_offset) | |
| 141 marker.SetEndOffset(end_offset); | |
| 142 | |
| 143 dst_list->Add(&marker); | |
| 144 didMoveMarker = true; | |
| 145 } | |
| 146 | |
| 147 // Remove the range of markers that were moved to dstNode | |
| 148 markers_.erase(0, it - markers_.begin()); | |
| 149 | |
| 150 return didMoveMarker; | |
| 151 } | |
| 152 | |
| 153 bool DocumentMarkerList::RemoveMarkers(unsigned start_offset, int length) { | |
| 154 unsigned end_offset = start_offset + length; | |
| 155 | |
| 156 const auto startPos = std::upper_bound(markers_.begin(), markers_.end(), | |
| 157 start_offset, EndsBefore); | |
| 158 auto it = startPos; | |
| 159 for (; it != markers_.end(); ++it) { | |
| 160 if ((*it)->StartOffset() >= end_offset) | |
| 161 break; | |
| 162 } | |
| 163 | |
| 164 // it should now point at the first marker *not* to be removed (or at | |
| 165 // markers_->end()) | |
| 166 markers_.erase(startPos - markers_.begin(), it - startPos); | |
| 167 | |
| 168 if (it == startPos) | |
| 169 return false; | |
| 170 | |
| 171 return true; | |
| 172 } | |
| 173 | |
| 174 bool DocumentMarkerList::ShiftMarkers(unsigned offset, | |
| 175 unsigned old_length, | |
| 176 unsigned new_length) { | |
| 177 DocumentMarkerVector newMarkerList; | |
| 178 bool didShiftMarker = false; | |
| 179 for (Member<DocumentMarker> marker : markers_) { | |
| 180 Optional<DocumentMarker::MarkerOffsets> result = | |
| 181 marker->ComputeOffsetsAfterShift(offset, old_length, new_length); | |
| 182 | |
| 183 if (result == WTF::kNullopt) { | |
| 184 didShiftMarker = true; | |
| 185 continue; | |
| 186 } | |
| 187 | |
| 188 if (result.value().start_offset != marker->StartOffset() || | |
| 189 result.value().end_offset != marker->EndOffset()) { | |
| 190 marker->SetStartOffset(result.value().start_offset); | |
| 191 marker->SetEndOffset(result.value().end_offset); | |
| 192 | |
| 193 didShiftMarker = true; | |
| 194 } | |
| 195 | |
| 196 newMarkerList.push_back(marker); | |
| 197 } | |
| 198 | |
| 199 swap(markers_, newMarkerList); | |
| 200 return didShiftMarker; | |
| 201 } | |
| 202 | |
| 203 void DocumentMarkerList::MergeOverlapping(DocumentMarker* marker) { | |
| 204 auto first_overlapping = std::lower_bound(markers_.begin(), markers_.end(), | |
| 205 marker, DoesNotOverlap); | |
| 206 size_t index = first_overlapping - markers_.begin(); | |
| 207 markers_.insert(index, marker); | |
| 208 const auto inserted = markers_.begin() + index; | |
| 209 first_overlapping = inserted + 1; | |
| 210 for (auto i = first_overlapping; | |
| 211 i != markers_.end() && | |
| 212 (*i)->StartOffset() <= (*inserted)->EndOffset();) { | |
| 213 (*inserted)->SetStartOffset( | |
| 214 std::min((*inserted)->StartOffset(), (*i)->StartOffset())); | |
| 215 (*inserted)->SetEndOffset( | |
| 216 std::max((*inserted)->EndOffset(), (*i)->EndOffset())); | |
| 217 markers_.erase(i - markers_.begin()); | |
| 218 } | |
| 219 } | |
| 220 | |
| 221 DEFINE_TRACE(DocumentMarkerList) { | |
| 222 visitor->Trace(markers_); | |
| 223 } | |
| 224 | |
| 80 inline bool DocumentMarkerController::PossiblyHasMarkers( | 225 inline bool DocumentMarkerController::PossiblyHasMarkers( |
| 81 DocumentMarker::MarkerTypes types) { | 226 DocumentMarker::MarkerTypes types) { |
| 82 return possibly_existing_marker_types_.Intersects(types); | 227 return possibly_existing_marker_types_.Intersects(types); |
| 83 } | 228 } |
| 84 | 229 |
| 85 DocumentMarkerController::DocumentMarkerController(Document& document) | 230 DocumentMarkerController::DocumentMarkerController(Document& document) |
| 86 : possibly_existing_marker_types_(0), document_(&document) { | 231 : possibly_existing_marker_types_(0), document_(&document) { |
| 87 SetContext(&document); | 232 SetContext(&document); |
| 88 } | 233 } |
| 89 | 234 |
| 90 void DocumentMarkerController::Clear() { | 235 void DocumentMarkerController::Clear() { |
| 91 markers_.Clear(); | 236 markers_.Clear(); |
| 92 possibly_existing_marker_types_ = 0; | 237 possibly_existing_marker_types_ = 0; |
| 93 } | 238 } |
| 94 | 239 |
| 95 void DocumentMarkerController::AddMarker(const Position& start, | 240 void DocumentMarkerController::AddMarker(const Position& start, |
| 96 const Position& end, | 241 const Position& end, |
| 97 DocumentMarker::MarkerType type, | 242 DocumentMarker::MarkerType type, |
| 98 const String& description) { | 243 const String& description) { |
| 99 // Use a TextIterator to visit the potentially multiple nodes the range | 244 // Use a TextIterator to visit the potentially multiple nodes the range |
| 100 // covers. | 245 // covers. |
| 101 for (TextIterator marked_text(start, end); !marked_text.AtEnd(); | 246 for (TextIterator marked_text(start, end); !marked_text.AtEnd(); |
| 102 marked_text.Advance()) { | 247 marked_text.Advance()) { |
| 103 AddMarker( | 248 AddMarker(marked_text.CurrentContainer(), |
| 104 marked_text.CurrentContainer(), | 249 new DocumentMarker( |
| 105 DocumentMarker(type, marked_text.StartOffsetInCurrentContainer(), | 250 type, marked_text.StartOffsetInCurrentContainer(), |
| 106 marked_text.EndOffsetInCurrentContainer(), description)); | 251 marked_text.EndOffsetInCurrentContainer(), description)); |
| 107 } | 252 } |
| 108 } | 253 } |
| 109 | 254 |
| 110 void DocumentMarkerController::AddTextMatchMarker( | 255 void DocumentMarkerController::AddTextMatchMarker( |
| 111 const EphemeralRange& range, | 256 const EphemeralRange& range, |
| 112 DocumentMarker::MatchStatus match_status) { | 257 DocumentMarker::MatchStatus match_status) { |
| 113 DCHECK(!document_->NeedsLayoutTreeUpdate()); | 258 DCHECK(!document_->NeedsLayoutTreeUpdate()); |
| 114 | 259 |
| 115 // Use a TextIterator to visit the potentially multiple nodes the range | 260 // Use a TextIterator to visit the potentially multiple nodes the range |
| 116 // covers. | 261 // covers. |
| 117 for (TextIterator marked_text(range.StartPosition(), range.EndPosition()); | 262 for (TextIterator marked_text(range.StartPosition(), range.EndPosition()); |
| 118 !marked_text.AtEnd(); marked_text.Advance()) { | 263 !marked_text.AtEnd(); marked_text.Advance()) { |
| 119 AddMarker(marked_text.CurrentContainer(), | 264 AddMarker(marked_text.CurrentContainer(), |
| 120 DocumentMarker(marked_text.StartOffsetInCurrentContainer(), | 265 new DocumentMarker(marked_text.StartOffsetInCurrentContainer(), |
| 121 marked_text.EndOffsetInCurrentContainer(), | 266 marked_text.EndOffsetInCurrentContainer(), |
| 122 match_status)); | 267 match_status)); |
| 123 } | 268 } |
| 124 // Don't invalidate tickmarks here. TextFinder invalidates tickmarks using a | 269 // Don't invalidate tickmarks here. TextFinder invalidates tickmarks using a |
| 125 // throttling algorithm. crbug.com/6819. | 270 // throttling algorithm. crbug.com/6819. |
| 126 } | 271 } |
| 127 | 272 |
| 128 void DocumentMarkerController::AddCompositionMarker(const Position& start, | 273 void DocumentMarkerController::AddCompositionMarker(const Position& start, |
| 129 const Position& end, | 274 const Position& end, |
| 130 Color underline_color, | 275 Color underline_color, |
| 131 bool thick, | 276 bool thick, |
| 132 Color background_color) { | 277 Color background_color) { |
| 133 DCHECK(!document_->NeedsLayoutTreeUpdate()); | 278 DCHECK(!document_->NeedsLayoutTreeUpdate()); |
| 134 | 279 |
| 135 for (TextIterator marked_text(start, end); !marked_text.AtEnd(); | 280 for (TextIterator marked_text(start, end); !marked_text.AtEnd(); |
| 136 marked_text.Advance()) | 281 marked_text.Advance()) { |
| 137 AddMarker(marked_text.CurrentContainer(), | 282 AddMarker(marked_text.CurrentContainer(), |
| 138 DocumentMarker(marked_text.StartOffsetInCurrentContainer(), | 283 new DocumentMarker(marked_text.StartOffsetInCurrentContainer(), |
| 139 marked_text.EndOffsetInCurrentContainer(), | 284 marked_text.EndOffsetInCurrentContainer(), |
| 140 underline_color, thick, background_color)); | 285 underline_color, thick, background_color)); |
| 286 } | |
| 141 } | 287 } |
| 142 | 288 |
| 143 void DocumentMarkerController::PrepareForDestruction() { | 289 void DocumentMarkerController::PrepareForDestruction() { |
| 144 Clear(); | 290 Clear(); |
| 145 } | 291 } |
| 146 | 292 |
| 147 void DocumentMarkerController::RemoveMarkers( | 293 void DocumentMarkerController::RemoveMarkers( |
| 148 TextIterator& marked_text, | 294 TextIterator& marked_text, |
| 149 DocumentMarker::MarkerTypes marker_types) { | 295 DocumentMarker::MarkerTypes marker_types) { |
| 150 for (; !marked_text.AtEnd(); marked_text.Advance()) { | 296 for (; !marked_text.AtEnd(); marked_text.Advance()) { |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 161 | 307 |
| 162 void DocumentMarkerController::RemoveMarkers( | 308 void DocumentMarkerController::RemoveMarkers( |
| 163 const EphemeralRange& range, | 309 const EphemeralRange& range, |
| 164 DocumentMarker::MarkerTypes marker_types) { | 310 DocumentMarker::MarkerTypes marker_types) { |
| 165 DCHECK(!document_->NeedsLayoutTreeUpdate()); | 311 DCHECK(!document_->NeedsLayoutTreeUpdate()); |
| 166 | 312 |
| 167 TextIterator marked_text(range.StartPosition(), range.EndPosition()); | 313 TextIterator marked_text(range.StartPosition(), range.EndPosition()); |
| 168 DocumentMarkerController::RemoveMarkers(marked_text, marker_types); | 314 DocumentMarkerController::RemoveMarkers(marked_text, marker_types); |
| 169 } | 315 } |
| 170 | 316 |
| 171 static bool StartsFurther(const Member<RenderedDocumentMarker>& lhv, | |
|
Xiaocheng
2017/04/13 02:39:51
There's no need to touch these functions if we kee
| |
| 172 const DocumentMarker* rhv) { | |
| 173 return lhv->StartOffset() < rhv->StartOffset(); | |
| 174 } | |
| 175 | |
| 176 static bool EndsBefore(size_t start_offset, | |
| 177 const Member<RenderedDocumentMarker>& rhv) { | |
| 178 return start_offset < rhv->EndOffset(); | |
| 179 } | |
| 180 | |
| 181 static bool CompareByStart(const Member<DocumentMarker>& lhv, | |
| 182 const Member<DocumentMarker>& rhv) { | |
| 183 return lhv->StartOffset() < rhv->StartOffset(); | |
| 184 } | |
| 185 | |
| 186 static bool DoesNotOverlap(const Member<RenderedDocumentMarker>& lhv, | |
| 187 const DocumentMarker* rhv) { | |
| 188 return lhv->EndOffset() < rhv->StartOffset(); | |
| 189 } | |
| 190 | |
| 191 static void UpdateMarkerRenderedRect(const Node& node, | 317 static void UpdateMarkerRenderedRect(const Node& node, |
| 192 RenderedDocumentMarker& marker) { | 318 RenderedDocumentMarker& marker) { |
| 193 Range* range = Range::Create(node.GetDocument()); | 319 Range* range = Range::Create(node.GetDocument()); |
| 194 // The offsets of the marker may be out-dated, so check for exceptions. | 320 // The offsets of the marker may be out-dated, so check for exceptions. |
| 195 DummyExceptionStateForTesting exception_state; | 321 DummyExceptionStateForTesting exception_state; |
| 196 range->setStart(&const_cast<Node&>(node), marker.StartOffset(), | 322 range->setStart(&const_cast<Node&>(node), marker.StartOffset(), |
| 197 exception_state); | 323 exception_state); |
| 198 if (!exception_state.HadException()) { | 324 if (!exception_state.HadException()) { |
| 199 range->setEnd(&const_cast<Node&>(node), marker.EndOffset(), | 325 range->setEnd(&const_cast<Node&>(node), marker.EndOffset(), |
| 200 IGNORE_EXCEPTION_FOR_TESTING); | 326 IGNORE_EXCEPTION_FOR_TESTING); |
| 201 } | 327 } |
| 202 if (!exception_state.HadException()) { | 328 if (!exception_state.HadException()) { |
| 203 // TODO(yosin): Once we have a |EphemeralRange| version of |boundingBox()|, | 329 // TODO(yosin): Once we have a |EphemeralRange| version of |boundingBox()|, |
| 204 // we should use it instead of |Range| version. | 330 // we should use it instead of |Range| version. |
| 205 marker.SetRenderedRect(LayoutRect(range->BoundingBox())); | 331 marker.SetRenderedRect(LayoutRect(range->BoundingBox())); |
| 206 } else { | 332 } else { |
| 207 marker.NullifyRenderedRect(); | 333 marker.NullifyRenderedRect(); |
| 208 } | 334 } |
| 209 range->Dispose(); | 335 range->Dispose(); |
| 210 } | 336 } |
| 211 | 337 |
| 212 // Markers are stored in order sorted by their start offset. | 338 // Markers are stored in order sorted by their start offset. |
| 213 // Markers of the same type do not overlap each other. | 339 // Markers of the same type do not overlap each other. |
| 214 | 340 |
| 215 void DocumentMarkerController::AddMarker(Node* node, | 341 void DocumentMarkerController::AddMarker(Node* node, |
| 216 const DocumentMarker& new_marker) { | 342 const DocumentMarker* new_marker) { |
| 217 DCHECK_GE(new_marker.EndOffset(), new_marker.StartOffset()); | 343 DCHECK_GE(new_marker->EndOffset(), new_marker->StartOffset()); |
| 218 if (new_marker.EndOffset() == new_marker.StartOffset()) | 344 if (new_marker->EndOffset() == new_marker->StartOffset()) |
| 219 return; | 345 return; |
| 220 | 346 |
| 221 possibly_existing_marker_types_.Add(new_marker.GetType()); | 347 possibly_existing_marker_types_.Add(new_marker->GetType()); |
| 222 | 348 |
| 223 Member<MarkerLists>& markers = | 349 Member<MarkerLists>& markers = |
| 224 markers_.insert(node, nullptr).stored_value->value; | 350 markers_.insert(node, nullptr).stored_value->value; |
| 225 if (!markers) { | 351 if (!markers) { |
| 226 markers = new MarkerLists; | 352 markers = new MarkerLists; |
| 227 markers->Grow(DocumentMarker::kMarkerTypeIndexesCount); | 353 markers->Grow(DocumentMarker::kMarkerTypeIndexesCount); |
| 228 } | 354 } |
| 229 | 355 |
| 230 DocumentMarker::MarkerTypeIndex marker_list_index = | 356 DocumentMarker::MarkerTypeIndex marker_list_index = |
| 231 MarkerTypeToMarkerIndex(new_marker.GetType()); | 357 MarkerTypeToMarkerIndex(new_marker->GetType()); |
| 232 if (!markers->at(marker_list_index)) { | 358 if (!markers->at(marker_list_index)) { |
| 233 markers->at(marker_list_index) = new MarkerList; | 359 markers->at(marker_list_index) = new DocumentMarkerList; |
| 234 } | 360 } |
| 235 | 361 |
| 236 Member<MarkerList>& list = markers->at(marker_list_index); | 362 DocumentMarkerList* list = markers->at(marker_list_index); |
| 237 RenderedDocumentMarker* new_rendered_marker = | 363 RenderedDocumentMarker* new_rendered_marker = |
| 238 RenderedDocumentMarker::Create(new_marker); | 364 RenderedDocumentMarker::Create(*new_marker); |
| 239 if (list->IsEmpty() || list->back()->EndOffset() < new_marker.StartOffset()) { | 365 list->Add(new_rendered_marker); |
| 240 list->push_back(new_rendered_marker); | |
| 241 } else { | |
| 242 if (new_marker.GetType() != DocumentMarker::kTextMatch && | |
| 243 new_marker.GetType() != DocumentMarker::kComposition) { | |
| 244 MergeOverlapping(list.Get(), new_rendered_marker); | |
| 245 } else { | |
| 246 MarkerList::iterator pos = std::lower_bound(list->begin(), list->end(), | |
| 247 &new_marker, StartsFurther); | |
| 248 list->insert(pos - list->begin(), new_rendered_marker); | |
| 249 } | |
| 250 } | |
| 251 | 366 |
| 252 // repaint the affected node | 367 // repaint the affected node |
| 253 if (node->GetLayoutObject()) { | 368 if (node->GetLayoutObject()) { |
| 254 node->GetLayoutObject()->SetShouldDoFullPaintInvalidation( | 369 node->GetLayoutObject()->SetShouldDoFullPaintInvalidation( |
| 255 kPaintInvalidationDocumentMarkerChange); | 370 kPaintInvalidationDocumentMarkerChange); |
| 256 } | 371 } |
| 257 } | 372 } |
| 258 | 373 |
| 259 void DocumentMarkerController::MergeOverlapping( | |
|
Xiaocheng
2017/04/13 02:39:51
DML::MergeOverlapping can be put here, so that it
| |
| 260 MarkerList* list, | |
| 261 RenderedDocumentMarker* to_insert) { | |
| 262 MarkerList::iterator first_overlapping = | |
| 263 std::lower_bound(list->begin(), list->end(), to_insert, DoesNotOverlap); | |
| 264 size_t index = first_overlapping - list->begin(); | |
| 265 list->insert(index, to_insert); | |
| 266 MarkerList::iterator inserted = list->begin() + index; | |
| 267 first_overlapping = inserted + 1; | |
| 268 for (MarkerList::iterator i = first_overlapping; | |
| 269 i != list->end() && (*i)->StartOffset() <= (*inserted)->EndOffset();) { | |
| 270 (*inserted)->SetStartOffset( | |
| 271 std::min((*inserted)->StartOffset(), (*i)->StartOffset())); | |
| 272 (*inserted)->SetEndOffset( | |
| 273 std::max((*inserted)->EndOffset(), (*i)->EndOffset())); | |
| 274 list->erase(i - list->begin()); | |
| 275 } | |
| 276 } | |
| 277 | |
| 278 // Moves markers from src_node to dst_node. Markers are moved if their start | 374 // Moves markers from src_node to dst_node. Markers are moved if their start |
| 279 // offset is less than length. Markers that run past that point are truncated. | 375 // offset is less than length. Markers that run past that point are truncated. |
| 280 void DocumentMarkerController::MoveMarkers(Node* src_node, | 376 void DocumentMarkerController::MoveMarkers(Node* src_node, |
| 281 int length, | 377 int length, |
| 282 Node* dst_node) { | 378 Node* dst_node) { |
| 283 if (length <= 0) | 379 if (length <= 0) |
| 284 return; | 380 return; |
| 285 | 381 |
| 286 if (!PossiblyHasMarkers(DocumentMarker::AllMarkers())) | 382 if (!PossiblyHasMarkers(DocumentMarker::AllMarkers())) |
| 287 return; | 383 return; |
| 288 DCHECK(!markers_.IsEmpty()); | 384 DCHECK(!markers_.IsEmpty()); |
| 289 | 385 |
| 290 MarkerLists* markers = markers_.at(src_node); | 386 MarkerLists* src_markers = markers_.at(src_node); |
| 291 if (!markers) | 387 if (!src_markers) |
| 292 return; | 388 return; |
| 293 | 389 |
| 390 Member<MarkerLists>& dst_markers = | |
| 391 markers_.insert(dst_node, nullptr).stored_value->value; | |
| 392 if (!dst_markers) { | |
| 393 dst_markers = new MarkerLists; | |
| 394 dst_markers->Grow(DocumentMarker::kMarkerTypeIndexesCount); | |
| 395 } | |
| 396 | |
| 294 bool doc_dirty = false; | 397 bool doc_dirty = false; |
| 295 for (Member<MarkerList> list : *markers) { | 398 for (size_t marker_list_index = 0; marker_list_index < src_markers->size(); |
| 296 if (!list) | 399 marker_list_index++) { |
| 400 DocumentMarkerList* src_list = src_markers->at(marker_list_index); | |
| 401 if (!src_list) | |
| 297 continue; | 402 continue; |
| 298 | 403 |
| 299 unsigned end_offset = length - 1; | 404 if (!dst_markers->at(marker_list_index)) { |
| 300 MarkerList::iterator it; | 405 dst_markers->at(marker_list_index) = new DocumentMarkerList; |
| 301 for (it = list->begin(); it != list->end(); ++it) { | |
| 302 DocumentMarker* marker = it->Get(); | |
| 303 | |
| 304 // stop if we are now past the specified range | |
| 305 if (marker->StartOffset() > end_offset) | |
| 306 break; | |
| 307 | |
| 308 // pin the marker to the specified range | |
| 309 doc_dirty = true; | |
| 310 if (marker->EndOffset() > end_offset) | |
| 311 marker->SetEndOffset(end_offset); | |
| 312 | |
| 313 AddMarker(dst_node, *marker); | |
| 314 } | 406 } |
| 315 | 407 |
| 316 // Remove the range of markers that were moved to dstNode | 408 src_list->MoveMarkers(length, dst_markers->at(marker_list_index)); |
| 317 list->erase(0, it - list->begin()); | |
| 318 } | 409 } |
| 319 | 410 |
| 320 // repaint the affected node | 411 // repaint the affected node |
| 321 if (doc_dirty && dst_node->GetLayoutObject()) { | 412 if (doc_dirty && dst_node->GetLayoutObject()) { |
| 322 dst_node->GetLayoutObject()->SetShouldDoFullPaintInvalidation( | 413 dst_node->GetLayoutObject()->SetShouldDoFullPaintInvalidation( |
| 323 kPaintInvalidationDocumentMarkerChange); | 414 kPaintInvalidationDocumentMarkerChange); |
| 324 } | 415 } |
| 325 } | 416 } |
| 326 | 417 |
| 327 void DocumentMarkerController::RemoveMarkers( | 418 void DocumentMarkerController::RemoveMarkers( |
| 328 Node* node, | 419 Node* node, |
| 329 unsigned start_offset, | 420 unsigned start_offset, |
| 330 int length, | 421 int length, |
| 331 DocumentMarker::MarkerTypes marker_types) { | 422 DocumentMarker::MarkerTypes marker_types) { |
| 332 if (length <= 0) | 423 if (length <= 0) |
| 333 return; | 424 return; |
| 334 | 425 |
| 335 if (!PossiblyHasMarkers(marker_types)) | 426 if (!PossiblyHasMarkers(marker_types)) |
| 336 return; | 427 return; |
| 337 DCHECK(!(markers_.IsEmpty())); | 428 DCHECK(!(markers_.IsEmpty())); |
| 338 | 429 |
| 339 MarkerLists* markers = markers_.at(node); | 430 MarkerLists* markers = markers_.at(node); |
| 340 if (!markers) | 431 if (!markers) |
| 341 return; | 432 return; |
| 342 | 433 |
| 343 bool doc_dirty = false; | 434 bool doc_dirty = false; |
| 344 size_t empty_lists_count = 0; | 435 size_t empty_lists_count = 0; |
| 345 for (size_t marker_list_index = 0; | 436 for (DocumentMarker::MarkerType type : DocumentMarker::AllMarkers()) { |
| 346 marker_list_index < DocumentMarker::kMarkerTypeIndexesCount; | 437 size_t marker_list_index = MarkerTypeToMarkerIndex(type); |
| 347 ++marker_list_index) { | 438 |
| 348 Member<MarkerList>& list = (*markers)[marker_list_index]; | 439 Member<DocumentMarkerList>& list = (*markers)[marker_list_index]; |
| 349 if (!list || list->IsEmpty()) { | 440 if (!list || list->IsEmpty()) { |
| 350 if (list.Get() && list->IsEmpty()) | 441 if (list.Get() && list->IsEmpty()) |
| 351 list.Clear(); | 442 list.Clear(); |
| 352 ++empty_lists_count; | 443 ++empty_lists_count; |
| 353 continue; | 444 continue; |
| 354 } | 445 } |
| 355 if (!marker_types.Contains((*list->begin())->GetType())) | 446 if (!marker_types.Contains(type)) |
| 356 continue; | 447 continue; |
| 357 unsigned end_offset = start_offset + length; | |
| 358 MarkerList::iterator start_pos = | |
| 359 std::upper_bound(list->begin(), list->end(), start_offset, EndsBefore); | |
| 360 for (MarkerList::iterator i = start_pos; i != list->end();) { | |
| 361 DocumentMarker marker(*i->Get()); | |
| 362 | 448 |
| 363 // markers are returned in order, so stop if we are now past the specified | 449 doc_dirty = list->RemoveMarkers(start_offset, length) || doc_dirty; |
| 364 // range | |
| 365 if (marker.StartOffset() >= end_offset) | |
| 366 break; | |
| 367 | |
| 368 list->erase(i - list->begin()); | |
| 369 doc_dirty = true; | |
| 370 } | |
| 371 | 450 |
| 372 if (list->IsEmpty()) { | 451 if (list->IsEmpty()) { |
| 373 list.Clear(); | 452 list.Clear(); |
| 374 ++empty_lists_count; | 453 ++empty_lists_count; |
| 375 } | 454 } |
| 376 } | 455 } |
| 377 | 456 |
| 378 if (empty_lists_count == DocumentMarker::kMarkerTypeIndexesCount) { | 457 if (empty_lists_count == DocumentMarker::kMarkerTypeIndexesCount) { |
| 379 markers_.erase(node); | 458 markers_.erase(node); |
| 380 if (markers_.IsEmpty()) | 459 if (markers_.IsEmpty()) |
| 381 possibly_existing_marker_types_ = 0; | 460 possibly_existing_marker_types_ = 0; |
| 382 } | 461 } |
| 383 | 462 |
| 384 // repaint the affected node | 463 // repaint the affected node |
| 385 if (doc_dirty && node->GetLayoutObject()) { | 464 if (doc_dirty && node->GetLayoutObject()) { |
| 386 node->GetLayoutObject()->SetShouldDoFullPaintInvalidation( | 465 node->GetLayoutObject()->SetShouldDoFullPaintInvalidation( |
| 387 kPaintInvalidationDocumentMarkerChange); | 466 kPaintInvalidationDocumentMarkerChange); |
| 388 } | 467 } |
| 389 } | 468 } |
| 390 | 469 |
| 391 DocumentMarkerVector DocumentMarkerController::MarkersFor( | 470 DocumentMarkerVector DocumentMarkerController::MarkersFor( |
| 392 Node* node, | 471 Node* node, |
| 393 DocumentMarker::MarkerTypes marker_types) { | 472 DocumentMarker::MarkerTypes marker_types) { |
| 394 DocumentMarkerVector result; | 473 DocumentMarkerVector result; |
| 395 | 474 |
| 396 MarkerLists* markers = markers_.at(node); | 475 MarkerLists* markers = markers_.at(node); |
| 397 if (!markers) | 476 if (!markers) |
| 398 return result; | 477 return result; |
| 399 | 478 |
| 400 for (size_t marker_list_index = 0; | 479 for (DocumentMarker::MarkerType type : DocumentMarker::AllMarkers()) { |
| 401 marker_list_index < DocumentMarker::kMarkerTypeIndexesCount; | 480 size_t marker_list_index = MarkerTypeToMarkerIndex(type); |
| 402 ++marker_list_index) { | 481 |
| 403 Member<MarkerList>& list = (*markers)[marker_list_index]; | 482 DocumentMarkerList* list = (*markers)[marker_list_index]; |
| 404 if (!list || list->IsEmpty() || | 483 if (!list || list->IsEmpty() || !marker_types.Contains(type)) |
| 405 !marker_types.Contains((*list->begin())->GetType())) | |
| 406 continue; | 484 continue; |
| 407 | 485 |
| 408 for (size_t i = 0; i < list->size(); ++i) | 486 list->AppendMarkersToInputList(&result); |
| 409 result.push_back(list->at(i).Get()); | |
| 410 } | 487 } |
| 411 | 488 |
| 412 std::sort(result.begin(), result.end(), CompareByStart); | 489 std::sort(result.begin(), result.end(), CompareByStart); |
| 413 return result; | 490 return result; |
| 414 } | 491 } |
| 415 | 492 |
| 416 DocumentMarkerVector DocumentMarkerController::Markers() { | 493 DocumentMarkerVector DocumentMarkerController::Markers() { |
| 417 DocumentMarkerVector result; | 494 DocumentMarkerVector result; |
| 418 for (MarkerMap::iterator i = markers_.begin(); i != markers_.end(); ++i) { | 495 for (MarkerMap::iterator i = markers_.begin(); i != markers_.end(); ++i) { |
| 419 MarkerLists* markers = i->value.Get(); | 496 MarkerLists* markers = i->value.Get(); |
| 420 for (size_t marker_list_index = 0; | 497 for (size_t marker_list_index = 0; |
| 421 marker_list_index < DocumentMarker::kMarkerTypeIndexesCount; | 498 marker_list_index < DocumentMarker::kMarkerTypeIndexesCount; |
| 422 ++marker_list_index) { | 499 ++marker_list_index) { |
| 423 Member<MarkerList>& list = (*markers)[marker_list_index]; | 500 DocumentMarkerList* list = (*markers)[marker_list_index]; |
| 424 for (size_t j = 0; list.Get() && j < list->size(); ++j) | 501 if (!list) |
| 425 result.push_back(list->at(j).Get()); | 502 continue; |
| 503 | |
| 504 list->AppendMarkersToInputList(&result); | |
| 426 } | 505 } |
| 427 } | 506 } |
| 507 | |
| 428 std::sort(result.begin(), result.end(), CompareByStart); | 508 std::sort(result.begin(), result.end(), CompareByStart); |
| 429 return result; | 509 return result; |
| 430 } | 510 } |
| 431 | 511 |
| 432 DocumentMarkerVector DocumentMarkerController::MarkersInRange( | 512 DocumentMarkerVector DocumentMarkerController::MarkersInRange( |
| 433 const EphemeralRange& range, | 513 const EphemeralRange& range, |
| 434 DocumentMarker::MarkerTypes marker_types) { | 514 DocumentMarker::MarkerTypes marker_types) { |
| 435 if (!PossiblyHasMarkers(marker_types)) | 515 if (!PossiblyHasMarkers(marker_types)) |
| 436 return DocumentMarkerVector(); | 516 return DocumentMarkerVector(); |
| 437 | 517 |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 468 return result; | 548 return result; |
| 469 DCHECK(!(markers_.IsEmpty())); | 549 DCHECK(!(markers_.IsEmpty())); |
| 470 | 550 |
| 471 // outer loop: process each node | 551 // outer loop: process each node |
| 472 MarkerMap::iterator end = markers_.end(); | 552 MarkerMap::iterator end = markers_.end(); |
| 473 for (MarkerMap::iterator node_iterator = markers_.begin(); | 553 for (MarkerMap::iterator node_iterator = markers_.begin(); |
| 474 node_iterator != end; ++node_iterator) { | 554 node_iterator != end; ++node_iterator) { |
| 475 // inner loop; process each marker in this node | 555 // inner loop; process each marker in this node |
| 476 const Node& node = *node_iterator->key; | 556 const Node& node = *node_iterator->key; |
| 477 MarkerLists* markers = node_iterator->value.Get(); | 557 MarkerLists* markers = node_iterator->value.Get(); |
| 478 for (size_t marker_list_index = 0; | 558 for (DocumentMarker::MarkerType type : DocumentMarker::AllMarkers()) { |
| 479 marker_list_index < DocumentMarker::kMarkerTypeIndexesCount; | 559 size_t marker_list_index = MarkerTypeToMarkerIndex(type); |
| 480 ++marker_list_index) { | 560 DocumentMarkerList* list = (*markers)[marker_list_index]; |
| 481 Member<MarkerList>& list = (*markers)[marker_list_index]; | 561 if (!list || list->IsEmpty() || type != marker_type) |
| 482 if (!list || list->IsEmpty() || | |
| 483 (*list->begin())->GetType() != marker_type) | |
| 484 continue; | 562 continue; |
| 485 for (unsigned marker_index = 0; marker_index < list->size(); | 563 DocumentMarkerVector markers_in_list; |
| 486 ++marker_index) { | 564 list->AppendMarkersToInputList(&markers_in_list); |
| 487 RenderedDocumentMarker* marker = list->at(marker_index).Get(); | 565 for (DocumentMarker* marker : markers_in_list) { |
| 488 UpdateMarkerRenderedRectIfNeeded(node, *marker); | 566 RenderedDocumentMarker* rendered_marker = |
| 489 if (!marker->IsRendered()) | 567 ToRenderedDocumentMarker(marker); |
| 568 UpdateMarkerRenderedRectIfNeeded(node, *rendered_marker); | |
| 569 if (!rendered_marker->IsRendered()) | |
| 490 continue; | 570 continue; |
| 491 result.push_back(marker->RenderedRect()); | 571 result.push_back(rendered_marker->RenderedRect()); |
| 492 } | 572 } |
| 493 } | 573 } |
| 494 } | 574 } |
| 495 | 575 |
| 496 return result; | 576 return result; |
| 497 } | 577 } |
| 498 | 578 |
| 499 static void InvalidatePaintForTickmarks(const Node& node) { | 579 static void InvalidatePaintForTickmarks(const Node& node) { |
| 500 if (FrameView* frame_view = node.GetDocument().View()) | 580 if (FrameView* frame_view = node.GetDocument().View()) |
| 501 frame_view->InvalidatePaintForTickmarks(); | 581 frame_view->InvalidatePaintForTickmarks(); |
| 502 } | 582 } |
| 503 | 583 |
| 504 void DocumentMarkerController::UpdateMarkerRenderedRectIfNeeded( | 584 void DocumentMarkerController::UpdateMarkerRenderedRectIfNeeded( |
| 505 const Node& node, | 585 const Node& node, |
| 506 RenderedDocumentMarker& marker) { | 586 RenderedDocumentMarker& marker) { |
| 507 DCHECK(!document_->View() || !document_->View()->NeedsLayout()); | 587 DCHECK(!document_->View() || !document_->View()->NeedsLayout()); |
| 508 DCHECK(!document_->NeedsLayoutTreeUpdate()); | 588 DCHECK(!document_->NeedsLayoutTreeUpdate()); |
| 509 if (!marker.IsValid()) | 589 if (!marker.IsValid()) |
| 510 UpdateMarkerRenderedRect(node, marker); | 590 UpdateMarkerRenderedRect(node, marker); |
| 511 } | 591 } |
| 512 | 592 |
| 513 void DocumentMarkerController::InvalidateRectsForMarkersInNode( | 593 void DocumentMarkerController::InvalidateRectsForMarkersInNode( |
| 514 const Node& node) { | 594 const Node& node) { |
| 515 MarkerLists* markers = markers_.at(&node); | 595 MarkerLists* markers = markers_.at(&node); |
| 516 | 596 |
| 517 for (auto& marker_list : *markers) { | 597 for (DocumentMarkerList* marker_list : *markers) { |
| 518 if (!marker_list || marker_list->IsEmpty()) | 598 if (!marker_list || marker_list->IsEmpty()) |
| 519 continue; | 599 continue; |
| 520 | 600 |
| 521 for (auto& marker : *marker_list) | 601 DocumentMarkerVector markers_in_list; |
| 522 marker->Invalidate(); | 602 marker_list->AppendMarkersToInputList(&markers_in_list); |
| 523 | 603 |
| 524 if (marker_list->front()->GetType() == DocumentMarker::kTextMatch) | 604 for (DocumentMarker* marker : markers_in_list) |
| 605 ToRenderedDocumentMarker(marker)->Invalidate(); | |
| 606 | |
| 607 if (markers_in_list.front()->GetType() == DocumentMarker::kTextMatch) | |
| 525 InvalidatePaintForTickmarks(node); | 608 InvalidatePaintForTickmarks(node); |
| 526 } | 609 } |
| 527 } | 610 } |
| 528 | 611 |
| 529 void DocumentMarkerController::InvalidateRectsForAllMarkers() { | 612 void DocumentMarkerController::InvalidateRectsForAllMarkers() { |
| 530 for (auto& node_markers : markers_) { | 613 for (auto& node_markers : markers_) { |
| 531 const Node& node = *node_markers.key; | 614 const Node& node = *node_markers.key; |
| 532 for (auto& marker_list : *node_markers.value) { | 615 for (DocumentMarkerList* marker_list : *node_markers.value) { |
| 533 if (!marker_list || marker_list->IsEmpty()) | 616 if (!marker_list || marker_list->IsEmpty()) |
| 534 continue; | 617 continue; |
| 535 | 618 |
| 536 for (auto& marker : *marker_list) | 619 DocumentMarkerVector markers_in_list; |
| 537 marker->Invalidate(); | 620 marker_list->AppendMarkersToInputList(&markers_in_list); |
| 621 for (DocumentMarker* marker : markers_in_list) | |
| 622 ToRenderedDocumentMarker(marker)->Invalidate(); | |
| 538 | 623 |
| 539 if (marker_list->front()->GetType() == DocumentMarker::kTextMatch) | 624 if (markers_in_list.front()->GetType() == DocumentMarker::kTextMatch) |
| 540 InvalidatePaintForTickmarks(node); | 625 InvalidatePaintForTickmarks(node); |
| 541 } | 626 } |
| 542 } | 627 } |
| 543 } | 628 } |
| 544 | 629 |
| 545 DEFINE_TRACE(DocumentMarkerController) { | 630 DEFINE_TRACE(DocumentMarkerController) { |
| 546 visitor->Trace(markers_); | 631 visitor->Trace(markers_); |
| 547 visitor->Trace(document_); | 632 visitor->Trace(document_); |
| 548 SynchronousMutationObserver::Trace(visitor); | 633 SynchronousMutationObserver::Trace(visitor); |
| 549 } | 634 } |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 563 void DocumentMarkerController::RemoveMarkers( | 648 void DocumentMarkerController::RemoveMarkers( |
| 564 const MarkerRemoverPredicate& should_remove_marker) { | 649 const MarkerRemoverPredicate& should_remove_marker) { |
| 565 for (auto& node_markers : markers_) { | 650 for (auto& node_markers : markers_) { |
| 566 const Node& node = *node_markers.key; | 651 const Node& node = *node_markers.key; |
| 567 if (!node.IsTextNode()) // MarkerRemoverPredicate requires a Text node. | 652 if (!node.IsTextNode()) // MarkerRemoverPredicate requires a Text node. |
| 568 continue; | 653 continue; |
| 569 MarkerLists& markers = *node_markers.value; | 654 MarkerLists& markers = *node_markers.value; |
| 570 for (size_t marker_list_index = 0; | 655 for (size_t marker_list_index = 0; |
| 571 marker_list_index < DocumentMarker::kMarkerTypeIndexesCount; | 656 marker_list_index < DocumentMarker::kMarkerTypeIndexesCount; |
| 572 ++marker_list_index) { | 657 ++marker_list_index) { |
| 573 Member<MarkerList>& list = markers[marker_list_index]; | 658 DocumentMarkerList* list = markers[marker_list_index]; |
| 574 if (!list) | 659 if (!list) |
| 575 continue; | 660 continue; |
| 576 bool removed_markers = false; | 661 bool removed_markers = false; |
| 577 for (size_t j = list->size(); j > 0; --j) { | 662 |
| 578 if (should_remove_marker(*list->at(j - 1), | 663 DocumentMarkerVector markers_in_list; |
| 664 list->AppendMarkersToInputList(&markers_in_list); | |
| 665 | |
| 666 for (size_t j = markers_in_list.size(); j > 0; --j) { | |
| 667 if (should_remove_marker(*markers_in_list[j - 1], | |
| 579 static_cast<const Text&>(node))) { | 668 static_cast<const Text&>(node))) { |
| 580 list->erase(j - 1); | 669 markers_in_list.erase(j - 1); |
| 581 removed_markers = true; | 670 removed_markers = true; |
| 582 } | 671 } |
| 583 } | 672 } |
| 673 | |
| 674 list->Clear(); | |
| 675 for (DocumentMarker* marker : markers_in_list) | |
| 676 list->Add(marker); | |
| 677 | |
| 584 if (removed_markers && | 678 if (removed_markers && |
| 585 marker_list_index == DocumentMarker::kTextMatchMarkerIndex) | 679 marker_list_index == DocumentMarker::kTextMatchMarkerIndex) |
| 586 InvalidatePaintForTickmarks(node); | 680 InvalidatePaintForTickmarks(node); |
| 587 } | 681 } |
| 588 } | 682 } |
| 589 } | 683 } |
| 590 | 684 |
| 591 void DocumentMarkerController::RemoveMarkers( | 685 void DocumentMarkerController::RemoveMarkers( |
| 592 DocumentMarker::MarkerTypes marker_types) { | 686 DocumentMarker::MarkerTypes marker_types) { |
| 593 if (!PossiblyHasMarkers(marker_types)) | 687 if (!PossiblyHasMarkers(marker_types)) |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 612 bool needs_repainting = false; | 706 bool needs_repainting = false; |
| 613 bool node_can_be_removed; | 707 bool node_can_be_removed; |
| 614 | 708 |
| 615 size_t empty_lists_count = 0; | 709 size_t empty_lists_count = 0; |
| 616 if (marker_types == DocumentMarker::AllMarkers()) { | 710 if (marker_types == DocumentMarker::AllMarkers()) { |
| 617 needs_repainting = true; | 711 needs_repainting = true; |
| 618 node_can_be_removed = true; | 712 node_can_be_removed = true; |
| 619 } else { | 713 } else { |
| 620 MarkerLists* markers = iterator->value.Get(); | 714 MarkerLists* markers = iterator->value.Get(); |
| 621 | 715 |
| 622 for (size_t marker_list_index = 0; | 716 for (DocumentMarker::MarkerType type : marker_types) { |
| 623 marker_list_index < DocumentMarker::kMarkerTypeIndexesCount; | 717 size_t marker_list_index = MarkerTypeToMarkerIndex(type); |
| 624 ++marker_list_index) { | 718 DocumentMarkerList* list = (*markers)[marker_list_index]; |
| 625 Member<MarkerList>& list = (*markers)[marker_list_index]; | 719 if (list) |
| 626 if (!list || list->IsEmpty()) { | |
| 627 if (list.Get() && list->IsEmpty()) | |
| 628 list.Clear(); | |
| 629 ++empty_lists_count; | |
| 630 continue; | |
| 631 } | |
| 632 if (marker_types.Contains((*list->begin())->GetType())) { | |
| 633 list->Clear(); | 720 list->Clear(); |
| 634 list.Clear(); | 721 |
| 635 ++empty_lists_count; | 722 ++empty_lists_count; |
| 636 needs_repainting = true; | 723 needs_repainting = true; |
| 637 } | |
| 638 } | 724 } |
| 639 | 725 |
| 640 node_can_be_removed = | 726 node_can_be_removed = |
| 641 empty_lists_count == DocumentMarker::kMarkerTypeIndexesCount; | 727 empty_lists_count == DocumentMarker::kMarkerTypeIndexesCount; |
| 642 } | 728 } |
| 643 | 729 |
| 644 if (needs_repainting) { | 730 if (needs_repainting) { |
| 645 const Node& node = *iterator->key; | 731 const Node& node = *iterator->key; |
| 646 if (LayoutObject* layout_object = node.GetLayoutObject()) { | 732 if (LayoutObject* layout_object = node.GetLayoutObject()) { |
| 647 layout_object->SetShouldDoFullPaintInvalidation( | 733 layout_object->SetShouldDoFullPaintInvalidation( |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 663 return; | 749 return; |
| 664 DCHECK(!markers_.IsEmpty()); | 750 DCHECK(!markers_.IsEmpty()); |
| 665 | 751 |
| 666 // outer loop: process each markered node in the document | 752 // outer loop: process each markered node in the document |
| 667 MarkerMap::iterator end = markers_.end(); | 753 MarkerMap::iterator end = markers_.end(); |
| 668 for (MarkerMap::iterator i = markers_.begin(); i != end; ++i) { | 754 for (MarkerMap::iterator i = markers_.begin(); i != end; ++i) { |
| 669 const Node* node = i->key; | 755 const Node* node = i->key; |
| 670 | 756 |
| 671 // inner loop: process each marker in the current node | 757 // inner loop: process each marker in the current node |
| 672 MarkerLists* markers = i->value.Get(); | 758 MarkerLists* markers = i->value.Get(); |
| 673 for (size_t marker_list_index = 0; | 759 for (DocumentMarker::MarkerType type : DocumentMarker::AllMarkers()) { |
| 674 marker_list_index < DocumentMarker::kMarkerTypeIndexesCount; | 760 size_t marker_list_index = MarkerTypeToMarkerIndex(type); |
| 675 ++marker_list_index) { | 761 DocumentMarkerList* list = (*markers)[marker_list_index]; |
| 676 Member<MarkerList>& list = (*markers)[marker_list_index]; | 762 if (!list || list->IsEmpty() || !marker_types.Contains(type)) |
| 677 if (!list || list->IsEmpty() || | |
| 678 !marker_types.Contains((*list->begin())->GetType())) | |
| 679 continue; | 763 continue; |
| 680 | 764 |
| 681 // cause the node to be redrawn | 765 // cause the node to be redrawn |
| 682 if (LayoutObject* layout_object = node->GetLayoutObject()) { | 766 if (LayoutObject* layout_object = node->GetLayoutObject()) { |
| 683 layout_object->SetShouldDoFullPaintInvalidation( | 767 layout_object->SetShouldDoFullPaintInvalidation( |
| 684 kPaintInvalidationDocumentMarkerChange); | 768 kPaintInvalidationDocumentMarkerChange); |
| 685 break; | 769 break; |
| 686 } | 770 } |
| 687 } | 771 } |
| 688 } | 772 } |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 716 | 800 |
| 717 bool DocumentMarkerController::SetMarkersActive(Node* node, | 801 bool DocumentMarkerController::SetMarkersActive(Node* node, |
| 718 unsigned start_offset, | 802 unsigned start_offset, |
| 719 unsigned end_offset, | 803 unsigned end_offset, |
| 720 bool active) { | 804 bool active) { |
| 721 MarkerLists* markers = markers_.at(node); | 805 MarkerLists* markers = markers_.at(node); |
| 722 if (!markers) | 806 if (!markers) |
| 723 return false; | 807 return false; |
| 724 | 808 |
| 725 bool doc_dirty = false; | 809 bool doc_dirty = false; |
| 726 Member<MarkerList>& list = | 810 DocumentMarkerList* list = |
| 727 (*markers)[MarkerTypeToMarkerIndex(DocumentMarker::kTextMatch)]; | 811 markers->at(MarkerTypeToMarkerIndex(DocumentMarker::kTextMatch)); |
| 728 if (!list) | 812 if (!list) |
| 729 return false; | 813 return false; |
| 730 MarkerList::iterator start_pos = | 814 |
| 731 std::upper_bound(list->begin(), list->end(), start_offset, EndsBefore); | 815 DocumentMarkerVector markers_in_list; |
| 732 for (MarkerList::iterator marker = start_pos; marker != list->end(); | 816 list->AppendMarkersToInputList(&markers_in_list); |
| 733 ++marker) { | 817 |
| 818 const auto start_pos = std::upper_bound( | |
| 819 markers_in_list.begin(), markers_in_list.end(), start_offset, EndsBefore); | |
| 820 for (auto marker_it = start_pos; marker_it != markers_in_list.end(); | |
| 821 ++marker_it) { | |
| 734 // Markers are returned in order, so stop if we are now past the specified | 822 // Markers are returned in order, so stop if we are now past the specified |
| 735 // range. | 823 // range. |
| 736 if ((*marker)->StartOffset() >= end_offset) | 824 if ((*marker_it)->StartOffset() >= end_offset) |
| 737 break; | 825 break; |
| 738 | 826 |
| 739 (*marker)->SetIsActiveMatch(active); | 827 (*marker_it)->SetIsActiveMatch(active); |
| 740 doc_dirty = true; | 828 doc_dirty = true; |
| 741 } | 829 } |
| 742 | 830 |
| 743 // repaint the affected node | 831 // repaint the affected node |
| 744 if (doc_dirty && node->GetLayoutObject()) { | 832 if (doc_dirty && node->GetLayoutObject()) { |
| 745 node->GetLayoutObject()->SetShouldDoFullPaintInvalidation( | 833 node->GetLayoutObject()->SetShouldDoFullPaintInvalidation( |
| 746 kPaintInvalidationDocumentMarkerChange); | 834 kPaintInvalidationDocumentMarkerChange); |
| 747 } | 835 } |
| 748 return doc_dirty; | 836 return doc_dirty; |
| 749 } | 837 } |
| 750 | 838 |
| 751 #ifndef NDEBUG | 839 #ifndef NDEBUG |
| 752 void DocumentMarkerController::ShowMarkers() const { | 840 void DocumentMarkerController::ShowMarkers() const { |
| 753 StringBuilder builder; | 841 StringBuilder builder; |
| 754 MarkerMap::const_iterator end = markers_.end(); | 842 MarkerMap::const_iterator end = markers_.end(); |
| 755 for (MarkerMap::const_iterator node_iterator = markers_.begin(); | 843 for (MarkerMap::const_iterator node_iterator = markers_.begin(); |
| 756 node_iterator != end; ++node_iterator) { | 844 node_iterator != end; ++node_iterator) { |
| 757 const Node* node = node_iterator->key; | 845 const Node* node = node_iterator->key; |
| 758 builder.Append(String::Format("%p", node)); | 846 builder.Append(String::Format("%p", node)); |
| 759 MarkerLists* markers = markers_.at(node); | 847 MarkerLists* markers = markers_.at(node); |
| 760 for (size_t marker_list_index = 0; | 848 for (size_t marker_list_index = 0; |
| 761 marker_list_index < DocumentMarker::kMarkerTypeIndexesCount; | 849 marker_list_index < DocumentMarker::kMarkerTypeIndexesCount; |
| 762 ++marker_list_index) { | 850 ++marker_list_index) { |
| 763 Member<MarkerList>& list = (*markers)[marker_list_index]; | 851 DocumentMarkerList* list = markers->at(marker_list_index); |
| 764 for (unsigned marker_index = 0; list.Get() && marker_index < list->size(); | 852 DocumentMarkerVector markers_in_list; |
| 765 ++marker_index) { | 853 list->AppendMarkersToInputList(&markers_in_list); |
| 766 DocumentMarker* marker = list->at(marker_index).Get(); | 854 for (unsigned marker_index = 0; |
| 855 list && marker_index < markers_in_list.size(); ++marker_index) { | |
| 856 DocumentMarker* marker = markers_in_list[marker_index]; | |
| 767 builder.Append(" "); | 857 builder.Append(" "); |
| 768 builder.AppendNumber(marker->GetType()); | 858 builder.AppendNumber(marker->GetType()); |
| 769 builder.Append(":["); | 859 builder.Append(":["); |
| 770 builder.AppendNumber(marker->StartOffset()); | 860 builder.AppendNumber(marker->StartOffset()); |
| 771 builder.Append(":"); | 861 builder.Append(":"); |
| 772 builder.AppendNumber(marker->EndOffset()); | 862 builder.AppendNumber(marker->EndOffset()); |
| 773 builder.Append("]("); | 863 builder.Append("]("); |
| 774 builder.AppendNumber(marker->IsActiveMatch()); | 864 builder.AppendNumber(marker->IsActiveMatch()); |
| 775 builder.Append(")"); | 865 builder.Append(")"); |
| 776 } | 866 } |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 789 unsigned new_length) { | 879 unsigned new_length) { |
| 790 if (!PossiblyHasMarkers(DocumentMarker::AllMarkers())) | 880 if (!PossiblyHasMarkers(DocumentMarker::AllMarkers())) |
| 791 return; | 881 return; |
| 792 DCHECK(!markers_.IsEmpty()); | 882 DCHECK(!markers_.IsEmpty()); |
| 793 | 883 |
| 794 MarkerLists* markers = markers_.at(node); | 884 MarkerLists* markers = markers_.at(node); |
| 795 if (!markers) | 885 if (!markers) |
| 796 return; | 886 return; |
| 797 | 887 |
| 798 bool did_shift_marker = false; | 888 bool did_shift_marker = false; |
| 799 for (MarkerList* list : *markers) { | 889 for (DocumentMarkerList* list : *markers) { |
| 800 if (!list) | 890 if (!list) |
| 801 continue; | 891 continue; |
| 802 | 892 |
| 803 for (MarkerList::iterator it = list->begin(); it != list->end(); ++it) { | 893 did_shift_marker = |
| 804 RenderedDocumentMarker& marker = **it; | 894 list->ShiftMarkers(offset, old_length, new_length) || did_shift_marker; |
| 805 Optional<DocumentMarker::MarkerOffsets> result = | |
| 806 marker.ComputeOffsetsAfterShift(offset, old_length, new_length); | |
| 807 if (result == WTF::kNullopt) { | |
| 808 list->erase(it - list->begin()); | |
| 809 --it; | |
| 810 did_shift_marker = true; | |
| 811 continue; | |
| 812 } | |
| 813 | |
| 814 if (marker.StartOffset() != result.value().start_offset || | |
| 815 marker.EndOffset() != result.value().end_offset) { | |
| 816 did_shift_marker = true; | |
| 817 marker.SetStartOffset(result.value().start_offset); | |
| 818 marker.SetEndOffset(result.value().end_offset); | |
| 819 } | |
| 820 } | |
| 821 } | 895 } |
| 822 | 896 |
| 823 if (!did_shift_marker) | 897 if (!did_shift_marker) |
| 824 return; | 898 return; |
| 825 if (!node->GetLayoutObject()) | 899 if (!node->GetLayoutObject()) |
| 826 return; | 900 return; |
| 827 InvalidateRectsForMarkersInNode(*node); | 901 InvalidateRectsForMarkersInNode(*node); |
| 828 // repaint the affected node | 902 // repaint the affected node |
| 829 node->GetLayoutObject()->SetShouldDoFullPaintInvalidation(); | 903 node->GetLayoutObject()->SetShouldDoFullPaintInvalidation(); |
| 830 } | 904 } |
| 831 | 905 |
| 832 } // namespace blink | 906 } // namespace blink |
| 833 | 907 |
| 834 #ifndef NDEBUG | 908 #ifndef NDEBUG |
| 835 void showDocumentMarkers(const blink::DocumentMarkerController* controller) { | 909 void showDocumentMarkers(const blink::DocumentMarkerController* controller) { |
| 836 if (controller) | 910 if (controller) |
| 837 controller->ShowMarkers(); | 911 controller->ShowMarkers(); |
| 838 } | 912 } |
| 839 #endif | 913 #endif |
| OLD | NEW |