Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(17)

Side by Side Diff: third_party/WebKit/Source/core/editing/markers/DocumentMarkerController.cpp

Issue 2820633002: [DMC #2] Add DocumentMarkerList interface and GenericDocumentMarkerListImpl (Closed)
Patch Set: Change AppendMarkersToInputList() to GetMarkers() Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 17 matching lines...) Expand all
28 28
29 #include "core/editing/markers/DocumentMarkerController.h" 29 #include "core/editing/markers/DocumentMarkerController.h"
30 30
31 #include <algorithm> 31 #include <algorithm>
32 #include "core/dom/Node.h" 32 #include "core/dom/Node.h"
33 #include "core/dom/NodeTraversal.h" 33 #include "core/dom/NodeTraversal.h"
34 #include "core/dom/Range.h" 34 #include "core/dom/Range.h"
35 #include "core/dom/Text.h" 35 #include "core/dom/Text.h"
36 #include "core/editing/iterators/TextIterator.h" 36 #include "core/editing/iterators/TextIterator.h"
37 #include "core/editing/markers/DocumentMarkerListEditor.h" 37 #include "core/editing/markers/DocumentMarkerListEditor.h"
38 #include "core/editing/markers/GenericDocumentMarkerListImpl.h"
38 #include "core/editing/markers/RenderedDocumentMarker.h" 39 #include "core/editing/markers/RenderedDocumentMarker.h"
39 #include "core/frame/FrameView.h" 40 #include "core/frame/FrameView.h"
40 #include "core/layout/LayoutObject.h" 41 #include "core/layout/LayoutObject.h"
41 42
42 #ifndef NDEBUG 43 #ifndef NDEBUG
43 #include <stdio.h> 44 #include <stdio.h>
44 #endif 45 #endif
45 46
46 namespace blink { 47 namespace blink {
47 48
(...skipping 23 matching lines...) Expand all
71 case DocumentMarker::kComposition: 72 case DocumentMarker::kComposition:
72 return DocumentMarker::kCompositionMarkerIndex; 73 return DocumentMarker::kCompositionMarkerIndex;
73 } 74 }
74 75
75 NOTREACHED(); 76 NOTREACHED();
76 return DocumentMarker::kSpellingMarkerIndex; 77 return DocumentMarker::kSpellingMarkerIndex;
77 } 78 }
78 79
79 } // namespace 80 } // namespace
80 81
81 Member<DocumentMarkerController::MarkerList>& 82 Member<DocumentMarkerList>& DocumentMarkerController::ListForType(
82 DocumentMarkerController::ListForType(MarkerLists* marker_lists, 83 MarkerLists* marker_lists,
83 DocumentMarker::MarkerType type) { 84 DocumentMarker::MarkerType type) {
84 const size_t marker_list_index = MarkerTypeToMarkerIndex(type); 85 const size_t marker_list_index = MarkerTypeToMarkerIndex(type);
85 return (*marker_lists)[marker_list_index]; 86 return (*marker_lists)[marker_list_index];
86 } 87 }
87 88
88 inline bool DocumentMarkerController::PossiblyHasMarkers( 89 inline bool DocumentMarkerController::PossiblyHasMarkers(
89 DocumentMarker::MarkerTypes types) { 90 DocumentMarker::MarkerTypes types) {
90 return possibly_existing_marker_types_.Intersects(types); 91 return possibly_existing_marker_types_.Intersects(types);
91 } 92 }
92 93
93 DocumentMarkerController::DocumentMarkerController(Document& document) 94 DocumentMarkerController::DocumentMarkerController(Document& document)
94 : possibly_existing_marker_types_(0), document_(&document) { 95 : possibly_existing_marker_types_(0), document_(&document) {
95 SetContext(&document); 96 SetContext(&document);
96 } 97 }
97 98
98 void DocumentMarkerController::Clear() { 99 void DocumentMarkerController::Clear() {
99 markers_.Clear(); 100 markers_.Clear();
100 possibly_existing_marker_types_ = 0; 101 possibly_existing_marker_types_ = 0;
101 } 102 }
102 103
103 void DocumentMarkerController::AddMarker(const Position& start, 104 void DocumentMarkerController::AddMarker(const Position& start,
104 const Position& end, 105 const Position& end,
105 DocumentMarker::MarkerType type, 106 DocumentMarker::MarkerType type,
106 const String& description) { 107 const String& description) {
107 // Use a TextIterator to visit the potentially multiple nodes the range 108 // Use a TextIterator to visit the potentially multiple nodes the range
108 // covers. 109 // covers.
109 for (TextIterator marked_text(start, end); !marked_text.AtEnd(); 110 for (TextIterator marked_text(start, end); !marked_text.AtEnd();
110 marked_text.Advance()) { 111 marked_text.Advance()) {
111 AddMarker( 112 AddMarker(marked_text.CurrentContainer(),
112 marked_text.CurrentContainer(), 113 new DocumentMarker(
113 DocumentMarker(type, marked_text.StartOffsetInCurrentContainer(), 114 type, marked_text.StartOffsetInCurrentContainer(),
114 marked_text.EndOffsetInCurrentContainer(), description)); 115 marked_text.EndOffsetInCurrentContainer(), description));
115 } 116 }
116 } 117 }
117 118
118 void DocumentMarkerController::AddTextMatchMarker( 119 void DocumentMarkerController::AddTextMatchMarker(
119 const EphemeralRange& range, 120 const EphemeralRange& range,
120 DocumentMarker::MatchStatus match_status) { 121 DocumentMarker::MatchStatus match_status) {
121 DCHECK(!document_->NeedsLayoutTreeUpdate()); 122 DCHECK(!document_->NeedsLayoutTreeUpdate());
122 123
123 // Use a TextIterator to visit the potentially multiple nodes the range 124 // Use a TextIterator to visit the potentially multiple nodes the range
124 // covers. 125 // covers.
125 for (TextIterator marked_text(range.StartPosition(), range.EndPosition()); 126 for (TextIterator marked_text(range.StartPosition(), range.EndPosition());
126 !marked_text.AtEnd(); marked_text.Advance()) { 127 !marked_text.AtEnd(); marked_text.Advance()) {
127 AddMarker(marked_text.CurrentContainer(), 128 AddMarker(marked_text.CurrentContainer(),
128 DocumentMarker(marked_text.StartOffsetInCurrentContainer(), 129 new DocumentMarker(marked_text.StartOffsetInCurrentContainer(),
129 marked_text.EndOffsetInCurrentContainer(), 130 marked_text.EndOffsetInCurrentContainer(),
130 match_status)); 131 match_status));
131 } 132 }
132 // Don't invalidate tickmarks here. TextFinder invalidates tickmarks using a 133 // Don't invalidate tickmarks here. TextFinder invalidates tickmarks using a
133 // throttling algorithm. crbug.com/6819. 134 // throttling algorithm. crbug.com/6819.
134 } 135 }
135 136
136 void DocumentMarkerController::AddCompositionMarker(const Position& start, 137 void DocumentMarkerController::AddCompositionMarker(const Position& start,
137 const Position& end, 138 const Position& end,
138 Color underline_color, 139 Color underline_color,
139 bool thick, 140 bool thick,
140 Color background_color) { 141 Color background_color) {
141 DCHECK(!document_->NeedsLayoutTreeUpdate()); 142 DCHECK(!document_->NeedsLayoutTreeUpdate());
142 143
143 for (TextIterator marked_text(start, end); !marked_text.AtEnd(); 144 for (TextIterator marked_text(start, end); !marked_text.AtEnd();
144 marked_text.Advance()) 145 marked_text.Advance()) {
145 AddMarker(marked_text.CurrentContainer(), 146 AddMarker(marked_text.CurrentContainer(),
146 DocumentMarker(marked_text.StartOffsetInCurrentContainer(), 147 new DocumentMarker(marked_text.StartOffsetInCurrentContainer(),
147 marked_text.EndOffsetInCurrentContainer(), 148 marked_text.EndOffsetInCurrentContainer(),
148 underline_color, thick, background_color)); 149 underline_color, thick, background_color));
150 }
149 } 151 }
150 152
151 void DocumentMarkerController::PrepareForDestruction() { 153 void DocumentMarkerController::PrepareForDestruction() {
152 Clear(); 154 Clear();
153 } 155 }
154 156
155 void DocumentMarkerController::RemoveMarkers( 157 void DocumentMarkerController::RemoveMarkers(
156 TextIterator& marked_text, 158 TextIterator& marked_text,
157 DocumentMarker::MarkerTypes marker_types) { 159 DocumentMarker::MarkerTypes marker_types) {
158 for (; !marked_text.AtEnd(); marked_text.Advance()) { 160 for (; !marked_text.AtEnd(); marked_text.Advance()) {
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
194 } else { 196 } else {
195 marker.NullifyRenderedRect(); 197 marker.NullifyRenderedRect();
196 } 198 }
197 range->Dispose(); 199 range->Dispose();
198 } 200 }
199 201
200 // Markers are stored in order sorted by their start offset. 202 // Markers are stored in order sorted by their start offset.
201 // Markers of the same type do not overlap each other. 203 // Markers of the same type do not overlap each other.
202 204
203 void DocumentMarkerController::AddMarker(Node* node, 205 void DocumentMarkerController::AddMarker(Node* node,
204 const DocumentMarker& new_marker) { 206 DocumentMarker* new_marker) {
205 DCHECK_GE(new_marker.EndOffset(), new_marker.StartOffset()); 207 DCHECK_GE(new_marker->EndOffset(), new_marker->StartOffset());
206 if (new_marker.EndOffset() == new_marker.StartOffset()) 208 if (new_marker->EndOffset() == new_marker->StartOffset())
207 return; 209 return;
208 210
209 possibly_existing_marker_types_.Add(new_marker.GetType()); 211 possibly_existing_marker_types_.Add(new_marker->GetType());
210 212
211 Member<MarkerLists>& markers = 213 Member<MarkerLists>& markers =
212 markers_.insert(node, nullptr).stored_value->value; 214 markers_.insert(node, nullptr).stored_value->value;
213 if (!markers) { 215 if (!markers) {
214 markers = new MarkerLists; 216 markers = new MarkerLists;
215 markers->Grow(DocumentMarker::kMarkerTypeIndexesCount); 217 markers->Grow(DocumentMarker::kMarkerTypeIndexesCount);
216 } 218 }
217 219
218 const DocumentMarker::MarkerType new_marker_type = new_marker.GetType(); 220 const DocumentMarker::MarkerType new_marker_type = new_marker->GetType();
219 if (!ListForType(markers, new_marker_type)) 221 if (!ListForType(markers, new_marker_type))
220 ListForType(markers, new_marker_type) = new MarkerList; 222 ListForType(markers, new_marker_type) = new GenericDocumentMarkerListImpl;
Xiaocheng 2017/04/20 08:41:34 Could you add a TODO of introducing a new function
221 223
222 Member<MarkerList>& list = ListForType(markers, new_marker_type); 224 Member<DocumentMarkerList>& list = ListForType(markers, new_marker_type);
223 DocumentMarkerListEditor::AddMarker(list, &new_marker); 225 list->Add(new_marker);
224 226
225 // repaint the affected node 227 // repaint the affected node
226 if (node->GetLayoutObject()) { 228 if (node->GetLayoutObject()) {
227 node->GetLayoutObject()->SetShouldDoFullPaintInvalidation( 229 node->GetLayoutObject()->SetShouldDoFullPaintInvalidation(
228 kPaintInvalidationDocumentMarkerChange); 230 kPaintInvalidationDocumentMarkerChange);
229 } 231 }
230 } 232 }
231 233
232 // Moves markers from src_node to dst_node. Markers are moved if their start 234 // Moves markers from src_node to dst_node. Markers are moved if their start
233 // offset is less than length. Markers that run past that point are truncated. 235 // offset is less than length. Markers that run past that point are truncated.
(...skipping 13 matching lines...) Expand all
247 249
248 if (!markers_.Contains(dst_node)) { 250 if (!markers_.Contains(dst_node)) {
249 markers_.insert(dst_node, 251 markers_.insert(dst_node,
250 new MarkerLists(DocumentMarker::kMarkerTypeIndexesCount)); 252 new MarkerLists(DocumentMarker::kMarkerTypeIndexesCount));
251 } 253 }
252 MarkerLists* dst_markers = markers_.at(dst_node); 254 MarkerLists* dst_markers = markers_.at(dst_node);
253 255
254 bool doc_dirty = false; 256 bool doc_dirty = false;
255 for (size_t marker_list_index = 0; marker_list_index < src_markers->size(); 257 for (size_t marker_list_index = 0; marker_list_index < src_markers->size();
256 ++marker_list_index) { 258 ++marker_list_index) {
257 MarkerList* src_list = src_markers->at(marker_list_index); 259 DocumentMarkerList* src_list = src_markers->at(marker_list_index);
258 if (!src_list) 260 if (!src_list)
259 continue; 261 continue;
260 262
261 if (!dst_markers->at(marker_list_index)) 263 if (!dst_markers->at(marker_list_index))
262 dst_markers->at(marker_list_index) = new MarkerList; 264 dst_markers->at(marker_list_index) = new GenericDocumentMarkerListImpl;
Xiaocheng 2017/04/20 08:41:34 ditto.
263 MarkerList* dst_list = dst_markers->at(marker_list_index);
264 265
265 if (DocumentMarkerListEditor::MoveMarkers(src_list, length, dst_list)) 266 if (src_list->MoveMarkers(length, dst_markers->at(marker_list_index)))
266 doc_dirty = true; 267 doc_dirty = true;
267 } 268 }
268 269
269 // repaint the affected node 270 // repaint the affected node
270 if (doc_dirty && dst_node->GetLayoutObject()) { 271 if (doc_dirty && dst_node->GetLayoutObject()) {
271 dst_node->GetLayoutObject()->SetShouldDoFullPaintInvalidation( 272 dst_node->GetLayoutObject()->SetShouldDoFullPaintInvalidation(
272 kPaintInvalidationDocumentMarkerChange); 273 kPaintInvalidationDocumentMarkerChange);
273 } 274 }
274 } 275 }
275 276
276 void DocumentMarkerController::RemoveMarkers( 277 void DocumentMarkerController::RemoveMarkers(
277 Node* node, 278 Node* node,
278 unsigned start_offset, 279 unsigned start_offset,
279 int length, 280 int length,
280 DocumentMarker::MarkerTypes marker_types) { 281 DocumentMarker::MarkerTypes marker_types) {
281 if (length <= 0) 282 if (length <= 0)
282 return; 283 return;
283 284
284 if (!PossiblyHasMarkers(marker_types)) 285 if (!PossiblyHasMarkers(marker_types))
285 return; 286 return;
286 DCHECK(!(markers_.IsEmpty())); 287 DCHECK(!(markers_.IsEmpty()));
287 288
288 MarkerLists* markers = markers_.at(node); 289 MarkerLists* markers = markers_.at(node);
289 if (!markers) 290 if (!markers)
290 return; 291 return;
291 292
292 bool doc_dirty = false; 293 bool doc_dirty = false;
293 size_t empty_lists_count = 0; 294 size_t empty_lists_count = 0;
294 for (size_t marker_list_index = 0; 295 for (DocumentMarker::MarkerType type : DocumentMarker::AllMarkers()) {
295 marker_list_index < DocumentMarker::kMarkerTypeIndexesCount; 296 size_t marker_list_index = MarkerTypeToMarkerIndex(type);
296 ++marker_list_index) { 297 DocumentMarkerList* list = (*markers)[marker_list_index];
297 Member<MarkerList>& list = (*markers)[marker_list_index];
298 if (!list || list->IsEmpty()) { 298 if (!list || list->IsEmpty()) {
299 if (list.Get() && list->IsEmpty()) 299 if (list && list->IsEmpty())
300 list.Clear(); 300 (*markers)[marker_list_index] = nullptr;
301 ++empty_lists_count; 301 ++empty_lists_count;
302 continue; 302 continue;
303 } 303 }
304 if (!marker_types.Contains((*list->begin())->GetType())) 304 if (!marker_types.Contains(type))
305 continue; 305 continue;
306 306
307 if (DocumentMarkerListEditor::RemoveMarkers(list, start_offset, length)) 307 if (list->RemoveMarkers(start_offset, length))
308 doc_dirty = true; 308 doc_dirty = true;
309 309
310 if (list->IsEmpty()) { 310 if (list->IsEmpty()) {
311 list.Clear(); 311 (*markers)[marker_list_index] = nullptr;
312 ++empty_lists_count; 312 ++empty_lists_count;
313 } 313 }
314 } 314 }
315 315
316 if (empty_lists_count == DocumentMarker::kMarkerTypeIndexesCount) { 316 if (empty_lists_count == DocumentMarker::kMarkerTypeIndexesCount) {
317 markers_.erase(node); 317 markers_.erase(node);
318 if (markers_.IsEmpty()) 318 if (markers_.IsEmpty())
319 possibly_existing_marker_types_ = 0; 319 possibly_existing_marker_types_ = 0;
320 } 320 }
321 321
322 // repaint the affected node 322 // repaint the affected node
323 if (doc_dirty && node->GetLayoutObject()) { 323 if (doc_dirty && node->GetLayoutObject()) {
324 node->GetLayoutObject()->SetShouldDoFullPaintInvalidation( 324 node->GetLayoutObject()->SetShouldDoFullPaintInvalidation(
325 kPaintInvalidationDocumentMarkerChange); 325 kPaintInvalidationDocumentMarkerChange);
326 } 326 }
327 } 327 }
328 328
329 DocumentMarkerVector DocumentMarkerController::MarkersFor( 329 DocumentMarkerVector DocumentMarkerController::MarkersFor(
330 Node* node, 330 Node* node,
331 DocumentMarker::MarkerTypes marker_types) { 331 DocumentMarker::MarkerTypes marker_types) {
332 DocumentMarkerVector result; 332 DocumentMarkerVector result;
333 333
334 MarkerLists* markers = markers_.at(node); 334 MarkerLists* markers = markers_.at(node);
335 if (!markers) 335 if (!markers)
336 return result; 336 return result;
337 337
338 for (size_t marker_list_index = 0; 338 for (DocumentMarker::MarkerType type : DocumentMarker::AllMarkers()) {
339 marker_list_index < DocumentMarker::kMarkerTypeIndexesCount; 339 size_t marker_list_index = MarkerTypeToMarkerIndex(type);
340 ++marker_list_index) { 340 DocumentMarkerList* list = (*markers)[marker_list_index];
341 Member<MarkerList>& list = (*markers)[marker_list_index]; 341 if (!list || list->IsEmpty() || !marker_types.Contains(type))
342 if (!list || list->IsEmpty() ||
343 !marker_types.Contains((*list->begin())->GetType()))
344 continue; 342 continue;
345 343
346 for (size_t i = 0; i < list->size(); ++i) 344 result.AppendVector(list->GetMarkers());
347 result.push_back(list->at(i).Get());
348 } 345 }
349 346
350 std::sort(result.begin(), result.end(), 347 std::sort(result.begin(), result.end(),
351 [](const Member<DocumentMarker>& marker1, 348 [](const Member<DocumentMarker>& marker1,
352 const Member<DocumentMarker>& marker2) { 349 const Member<DocumentMarker>& marker2) {
353 return marker1->StartOffset() < marker2->StartOffset(); 350 return marker1->StartOffset() < marker2->StartOffset();
354 }); 351 });
355 return result; 352 return result;
356 } 353 }
357 354
358 DocumentMarkerVector DocumentMarkerController::Markers() { 355 DocumentMarkerVector DocumentMarkerController::Markers() {
359 DocumentMarkerVector result; 356 DocumentMarkerVector result;
360 for (MarkerMap::iterator i = markers_.begin(); i != markers_.end(); ++i) { 357 for (MarkerMap::iterator i = markers_.begin(); i != markers_.end(); ++i) {
361 MarkerLists* markers = i->value.Get(); 358 MarkerLists* markers = i->value.Get();
362 for (size_t marker_list_index = 0; 359 for (size_t marker_list_index = 0;
363 marker_list_index < DocumentMarker::kMarkerTypeIndexesCount; 360 marker_list_index < DocumentMarker::kMarkerTypeIndexesCount;
364 ++marker_list_index) { 361 ++marker_list_index) {
365 Member<MarkerList>& list = (*markers)[marker_list_index]; 362 DocumentMarkerList* list = (*markers)[marker_list_index];
366 for (size_t j = 0; list.Get() && j < list->size(); ++j) 363 if (!list)
367 result.push_back(list->at(j).Get()); 364 continue;
365 result.AppendVector(list->GetMarkers());
368 } 366 }
369 } 367 }
370 std::sort(result.begin(), result.end(), 368 std::sort(result.begin(), result.end(),
371 [](const Member<DocumentMarker>& marker1, 369 [](const Member<DocumentMarker>& marker1,
372 const Member<DocumentMarker>& marker2) { 370 const Member<DocumentMarker>& marker2) {
373 return marker1->StartOffset() < marker2->StartOffset(); 371 return marker1->StartOffset() < marker2->StartOffset();
374 }); 372 });
375 return result; 373 return result;
376 } 374 }
377 375
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
416 414
417 // outer loop: process each node 415 // outer loop: process each node
418 MarkerMap::iterator end = markers_.end(); 416 MarkerMap::iterator end = markers_.end();
419 for (MarkerMap::iterator node_iterator = markers_.begin(); 417 for (MarkerMap::iterator node_iterator = markers_.begin();
420 node_iterator != end; ++node_iterator) { 418 node_iterator != end; ++node_iterator) {
421 // inner loop; process each marker in this node 419 // inner loop; process each marker in this node
422 const Node& node = *node_iterator->key; 420 const Node& node = *node_iterator->key;
423 if (!node.isConnected()) 421 if (!node.isConnected())
424 continue; 422 continue;
425 MarkerLists* markers = node_iterator->value.Get(); 423 MarkerLists* markers = node_iterator->value.Get();
426 for (size_t marker_list_index = 0; 424 for (DocumentMarker::MarkerType type : DocumentMarker::AllMarkers()) {
427 marker_list_index < DocumentMarker::kMarkerTypeIndexesCount; 425 size_t marker_list_index = MarkerTypeToMarkerIndex(type);
428 ++marker_list_index) { 426 DocumentMarkerList* list = (*markers)[marker_list_index];
429 Member<MarkerList>& list = (*markers)[marker_list_index]; 427 if (!list || list->IsEmpty() || type != marker_type)
430 if (!list || list->IsEmpty() ||
431 (*list->begin())->GetType() != marker_type)
432 continue; 428 continue;
433 for (unsigned marker_index = 0; marker_index < list->size(); 429
434 ++marker_index) { 430 const HeapVector<Member<RenderedDocumentMarker>>& markers_in_list =
435 RenderedDocumentMarker* marker = list->at(marker_index).Get(); 431 list->GetMarkers();
436 UpdateMarkerRenderedRectIfNeeded(node, *marker); 432 for (DocumentMarker* marker : markers_in_list) {
Xiaocheng 2017/04/20 08:41:34 No need to cast back and forth. nit: We can also
437 if (!marker->IsRendered()) 433 RenderedDocumentMarker* rendered_marker =
434 ToRenderedDocumentMarker(marker);
435 UpdateMarkerRenderedRectIfNeeded(node, *rendered_marker);
436 if (!rendered_marker->IsRendered())
438 continue; 437 continue;
439 result.push_back(marker->RenderedRect()); 438 result.push_back(rendered_marker->RenderedRect());
440 } 439 }
441 } 440 }
442 } 441 }
443 442
444 return result; 443 return result;
445 } 444 }
446 445
447 static void InvalidatePaintForTickmarks(const Node& node) { 446 static void InvalidatePaintForTickmarks(const Node& node) {
448 if (FrameView* frame_view = node.GetDocument().View()) 447 if (FrameView* frame_view = node.GetDocument().View())
449 frame_view->InvalidatePaintForTickmarks(); 448 frame_view->InvalidatePaintForTickmarks();
450 } 449 }
451 450
452 void DocumentMarkerController::UpdateMarkerRenderedRectIfNeeded( 451 void DocumentMarkerController::UpdateMarkerRenderedRectIfNeeded(
453 const Node& node, 452 const Node& node,
454 RenderedDocumentMarker& marker) { 453 RenderedDocumentMarker& marker) {
455 DCHECK(!document_->View() || !document_->View()->NeedsLayout()); 454 DCHECK(!document_->View() || !document_->View()->NeedsLayout());
456 DCHECK(!document_->NeedsLayoutTreeUpdate()); 455 DCHECK(!document_->NeedsLayoutTreeUpdate());
457 if (!marker.IsValid()) 456 if (!marker.IsValid())
458 UpdateMarkerRenderedRect(node, marker); 457 UpdateMarkerRenderedRect(node, marker);
459 } 458 }
460 459
461 void DocumentMarkerController::InvalidateRectsForMarkersInNode( 460 void DocumentMarkerController::InvalidateRectsForMarkersInNode(
462 const Node& node) { 461 const Node& node) {
463 MarkerLists* markers = markers_.at(&node); 462 MarkerLists* markers = markers_.at(&node);
464 463
465 for (auto& marker_list : *markers) { 464 for (auto& marker_list : *markers) {
466 if (!marker_list || marker_list->IsEmpty()) 465 if (!marker_list || marker_list->IsEmpty())
467 continue; 466 continue;
468 467
469 for (auto& marker : *marker_list) 468 const HeapVector<Member<RenderedDocumentMarker>>& markers_in_list =
469 marker_list->GetMarkers();
470 for (auto& marker : markers_in_list)
470 marker->Invalidate(); 471 marker->Invalidate();
471 472
472 if (marker_list->front()->GetType() == DocumentMarker::kTextMatch) 473 if (markers_in_list.front()->GetType() == DocumentMarker::kTextMatch)
473 InvalidatePaintForTickmarks(node); 474 InvalidatePaintForTickmarks(node);
474 } 475 }
475 } 476 }
476 477
477 void DocumentMarkerController::InvalidateRectsForAllMarkers() { 478 void DocumentMarkerController::InvalidateRectsForAllMarkers() {
478 for (auto& node_markers : markers_) { 479 for (auto& node_markers : markers_) {
479 const Node& node = *node_markers.key; 480 const Node& node = *node_markers.key;
480 for (auto& marker_list : *node_markers.value) { 481 for (auto& marker_list : *node_markers.value) {
481 if (!marker_list || marker_list->IsEmpty()) 482 if (!marker_list || marker_list->IsEmpty())
482 continue; 483 continue;
483 484
484 for (auto& marker : *marker_list) 485 const HeapVector<Member<RenderedDocumentMarker>>& markers_in_list =
485 marker->Invalidate(); 486 marker_list->GetMarkers();
487 for (DocumentMarker* marker : markers_in_list)
Xiaocheng 2017/04/20 08:41:34 No need to cast back and forth.
488 ToRenderedDocumentMarker(marker)->Invalidate();
486 489
487 if (marker_list->front()->GetType() == DocumentMarker::kTextMatch) 490 if (markers_in_list.front()->GetType() == DocumentMarker::kTextMatch)
488 InvalidatePaintForTickmarks(node); 491 InvalidatePaintForTickmarks(node);
489 } 492 }
490 } 493 }
491 } 494 }
492 495
493 DEFINE_TRACE(DocumentMarkerController) { 496 DEFINE_TRACE(DocumentMarkerController) {
494 visitor->Trace(markers_); 497 visitor->Trace(markers_);
495 visitor->Trace(document_); 498 visitor->Trace(document_);
496 SynchronousMutationObserver::Trace(visitor); 499 SynchronousMutationObserver::Trace(visitor);
497 } 500 }
(...skipping 13 matching lines...) Expand all
511 void DocumentMarkerController::RemoveMarkers( 514 void DocumentMarkerController::RemoveMarkers(
512 const MarkerRemoverPredicate& should_remove_marker) { 515 const MarkerRemoverPredicate& should_remove_marker) {
513 for (auto& node_markers : markers_) { 516 for (auto& node_markers : markers_) {
514 const Node& node = *node_markers.key; 517 const Node& node = *node_markers.key;
515 if (!node.IsTextNode()) // MarkerRemoverPredicate requires a Text node. 518 if (!node.IsTextNode()) // MarkerRemoverPredicate requires a Text node.
516 continue; 519 continue;
517 MarkerLists& markers = *node_markers.value; 520 MarkerLists& markers = *node_markers.value;
518 for (size_t marker_list_index = 0; 521 for (size_t marker_list_index = 0;
519 marker_list_index < DocumentMarker::kMarkerTypeIndexesCount; 522 marker_list_index < DocumentMarker::kMarkerTypeIndexesCount;
520 ++marker_list_index) { 523 ++marker_list_index) {
521 Member<MarkerList>& list = markers[marker_list_index]; 524 DocumentMarkerList* list = markers[marker_list_index];
Xiaocheng 2017/04/20 08:41:34 This impl doesn't look good -- dump everything out
rlanday 2017/04/20 10:03:18 Ah, I was going to clean this up when we introduce
yosin_UTC9 2017/04/21 01:32:25 Could you rename DMC::RemoveMarkers() by usage pat
522 if (!list) 525 if (!list)
523 continue; 526 continue;
524 bool removed_markers = false; 527 bool removed_markers = false;
525 for (size_t j = list->size(); j > 0; --j) { 528
526 if (should_remove_marker(*list->at(j - 1), 529 HeapVector<Member<RenderedDocumentMarker>> markers_in_list =
530 list->GetMarkers();
531 for (size_t j = markers_in_list.size(); j > 0; --j) {
532 if (should_remove_marker(*markers_in_list[j - 1],
527 static_cast<const Text&>(node))) { 533 static_cast<const Text&>(node))) {
528 list->erase(j - 1); 534 markers_in_list.erase(j - 1);
529 removed_markers = true; 535 removed_markers = true;
530 } 536 }
531 } 537 }
538
539 list->Clear();
540 for (DocumentMarker* marker : markers_in_list)
541 list->Add(marker);
542
532 if (removed_markers && 543 if (removed_markers &&
533 marker_list_index == DocumentMarker::kTextMatchMarkerIndex) 544 marker_list_index == DocumentMarker::kTextMatchMarkerIndex)
534 InvalidatePaintForTickmarks(node); 545 InvalidatePaintForTickmarks(node);
535 } 546 }
536 } 547 }
537 } 548 }
538 549
539 void DocumentMarkerController::RemoveMarkers( 550 void DocumentMarkerController::RemoveMarkers(
540 DocumentMarker::MarkerTypes marker_types) { 551 DocumentMarker::MarkerTypes marker_types) {
541 if (!PossiblyHasMarkers(marker_types)) 552 if (!PossiblyHasMarkers(marker_types))
(...skipping 18 matching lines...) Expand all
560 bool needs_repainting = false; 571 bool needs_repainting = false;
561 bool node_can_be_removed; 572 bool node_can_be_removed;
562 573
563 size_t empty_lists_count = 0; 574 size_t empty_lists_count = 0;
564 if (marker_types == DocumentMarker::AllMarkers()) { 575 if (marker_types == DocumentMarker::AllMarkers()) {
565 needs_repainting = true; 576 needs_repainting = true;
566 node_can_be_removed = true; 577 node_can_be_removed = true;
567 } else { 578 } else {
568 MarkerLists* markers = iterator->value.Get(); 579 MarkerLists* markers = iterator->value.Get();
569 580
570 for (size_t marker_list_index = 0; 581 for (DocumentMarker::MarkerType type : DocumentMarker::AllMarkers()) {
571 marker_list_index < DocumentMarker::kMarkerTypeIndexesCount; 582 size_t marker_list_index = MarkerTypeToMarkerIndex(type);
572 ++marker_list_index) { 583 DocumentMarkerList* list = (*markers)[marker_list_index];
573 Member<MarkerList>& list = (*markers)[marker_list_index];
574 if (!list || list->IsEmpty()) { 584 if (!list || list->IsEmpty()) {
575 if (list.Get() && list->IsEmpty()) 585 if (list && list->IsEmpty())
576 list.Clear(); 586 (*markers)[marker_list_index] = nullptr;
577 ++empty_lists_count; 587 ++empty_lists_count;
578 continue; 588 continue;
579 } 589 }
580 if (marker_types.Contains((*list->begin())->GetType())) { 590 if (marker_types.Contains(type)) {
581 list->clear(); 591 list->Clear();
582 list.Clear(); 592 ListForType(markers, type) = nullptr;
Xiaocheng 2017/04/20 08:41:34 For consistency, either apply ListForType() at all
583 ++empty_lists_count; 593 ++empty_lists_count;
584 needs_repainting = true; 594 needs_repainting = true;
585 } 595 }
586 } 596 }
587 597
588 node_can_be_removed = 598 node_can_be_removed =
589 empty_lists_count == DocumentMarker::kMarkerTypeIndexesCount; 599 empty_lists_count == DocumentMarker::kMarkerTypeIndexesCount;
590 } 600 }
591 601
592 if (needs_repainting) { 602 if (needs_repainting) {
(...skipping 18 matching lines...) Expand all
611 return; 621 return;
612 DCHECK(!markers_.IsEmpty()); 622 DCHECK(!markers_.IsEmpty());
613 623
614 // outer loop: process each markered node in the document 624 // outer loop: process each markered node in the document
615 MarkerMap::iterator end = markers_.end(); 625 MarkerMap::iterator end = markers_.end();
616 for (MarkerMap::iterator i = markers_.begin(); i != end; ++i) { 626 for (MarkerMap::iterator i = markers_.begin(); i != end; ++i) {
617 const Node* node = i->key; 627 const Node* node = i->key;
618 628
619 // inner loop: process each marker in the current node 629 // inner loop: process each marker in the current node
620 MarkerLists* markers = i->value.Get(); 630 MarkerLists* markers = i->value.Get();
621 for (size_t marker_list_index = 0; 631 for (DocumentMarker::MarkerType type : DocumentMarker::AllMarkers()) {
622 marker_list_index < DocumentMarker::kMarkerTypeIndexesCount; 632 size_t marker_list_index = MarkerTypeToMarkerIndex(type);
623 ++marker_list_index) { 633 DocumentMarkerList* list = (*markers)[marker_list_index];
624 Member<MarkerList>& list = (*markers)[marker_list_index]; 634 if (!list || list->IsEmpty() || !marker_types.Contains(type))
625 if (!list || list->IsEmpty() ||
626 !marker_types.Contains((*list->begin())->GetType()))
627 continue; 635 continue;
628 636
629 // cause the node to be redrawn 637 // cause the node to be redrawn
630 if (LayoutObject* layout_object = node->GetLayoutObject()) { 638 if (LayoutObject* layout_object = node->GetLayoutObject()) {
631 layout_object->SetShouldDoFullPaintInvalidation( 639 layout_object->SetShouldDoFullPaintInvalidation(
632 kPaintInvalidationDocumentMarkerChange); 640 kPaintInvalidationDocumentMarkerChange);
633 break; 641 break;
634 } 642 }
635 } 643 }
636 } 644 }
(...skipping 27 matching lines...) Expand all
664 672
665 bool DocumentMarkerController::SetMarkersActive(Node* node, 673 bool DocumentMarkerController::SetMarkersActive(Node* node,
666 unsigned start_offset, 674 unsigned start_offset,
667 unsigned end_offset, 675 unsigned end_offset,
668 bool active) { 676 bool active) {
669 MarkerLists* markers = markers_.at(node); 677 MarkerLists* markers = markers_.at(node);
670 if (!markers) 678 if (!markers)
671 return false; 679 return false;
672 680
673 bool doc_dirty = false; 681 bool doc_dirty = false;
674 Member<MarkerList>& list = ListForType(markers, DocumentMarker::kTextMatch); 682 DocumentMarkerList* list = ListForType(markers, DocumentMarker::kTextMatch);
683
675 if (!list) 684 if (!list)
676 return false; 685 return false;
677 MarkerList::iterator start_pos = std::upper_bound( 686
678 list->begin(), list->end(), start_offset, 687 const HeapVector<Member<RenderedDocumentMarker>>& markers_in_list =
679 [](size_t start_offset, const Member<RenderedDocumentMarker>& marker) { 688 list->GetMarkers();
689 const auto start_pos = std::upper_bound(
Xiaocheng 2017/04/20 08:41:34 This impl assumes that the markers are sorted, whi
690 markers_in_list.begin(), markers_in_list.end(), start_offset,
691 [](size_t start_offset, const Member<DocumentMarker>& marker) {
680 return start_offset < marker->EndOffset(); 692 return start_offset < marker->EndOffset();
681 }); 693 });
682 for (MarkerList::iterator marker = start_pos; marker != list->end(); 694 for (auto marker = start_pos; marker != markers_in_list.end(); ++marker) {
683 ++marker) {
684 // Markers are returned in order, so stop if we are now past the specified 695 // Markers are returned in order, so stop if we are now past the specified
685 // range. 696 // range.
686 if ((*marker)->StartOffset() >= end_offset) 697 if ((*marker)->StartOffset() >= end_offset)
687 break; 698 break;
688 699
689 (*marker)->SetIsActiveMatch(active); 700 (*marker)->SetIsActiveMatch(active);
690 doc_dirty = true; 701 doc_dirty = true;
691 } 702 }
692 703
693 // repaint the affected node 704 // repaint the affected node
694 if (doc_dirty && node->GetLayoutObject()) { 705 if (doc_dirty && node->GetLayoutObject()) {
695 node->GetLayoutObject()->SetShouldDoFullPaintInvalidation( 706 node->GetLayoutObject()->SetShouldDoFullPaintInvalidation(
696 kPaintInvalidationDocumentMarkerChange); 707 kPaintInvalidationDocumentMarkerChange);
697 } 708 }
698 return doc_dirty; 709 return doc_dirty;
699 } 710 }
700 711
701 #ifndef NDEBUG 712 #ifndef NDEBUG
702 void DocumentMarkerController::ShowMarkers() const { 713 void DocumentMarkerController::ShowMarkers() const {
703 StringBuilder builder; 714 StringBuilder builder;
704 MarkerMap::const_iterator end = markers_.end(); 715 MarkerMap::const_iterator end = markers_.end();
705 for (MarkerMap::const_iterator node_iterator = markers_.begin(); 716 for (MarkerMap::const_iterator node_iterator = markers_.begin();
706 node_iterator != end; ++node_iterator) { 717 node_iterator != end; ++node_iterator) {
707 const Node* node = node_iterator->key; 718 const Node* node = node_iterator->key;
708 builder.Append(String::Format("%p", node)); 719 builder.Append(String::Format("%p", node));
709 MarkerLists* markers = markers_.at(node); 720 MarkerLists* markers = markers_.at(node);
710 for (size_t marker_list_index = 0; 721 for (size_t marker_list_index = 0;
711 marker_list_index < DocumentMarker::kMarkerTypeIndexesCount; 722 marker_list_index < DocumentMarker::kMarkerTypeIndexesCount;
712 ++marker_list_index) { 723 ++marker_list_index) {
713 Member<MarkerList>& list = (*markers)[marker_list_index]; 724 DocumentMarkerList* list = (*markers)[marker_list_index];
714 for (unsigned marker_index = 0; list.Get() && marker_index < list->size(); 725
715 ++marker_index) { 726 const HeapVector<Member<RenderedDocumentMarker>>& markers_in_list =
716 DocumentMarker* marker = list->at(marker_index).Get(); 727 list->GetMarkers();
728 for (const DocumentMarker* marker : markers_in_list) {
717 builder.Append(" "); 729 builder.Append(" ");
718 builder.AppendNumber(marker->GetType()); 730 builder.AppendNumber(marker->GetType());
719 builder.Append(":["); 731 builder.Append(":[");
720 builder.AppendNumber(marker->StartOffset()); 732 builder.AppendNumber(marker->StartOffset());
721 builder.Append(":"); 733 builder.Append(":");
722 builder.AppendNumber(marker->EndOffset()); 734 builder.AppendNumber(marker->EndOffset());
723 builder.Append("]("); 735 builder.Append("](");
724 builder.AppendNumber(marker->IsActiveMatch()); 736 builder.AppendNumber(marker->IsActiveMatch());
725 builder.Append(")"); 737 builder.Append(")");
726 } 738 }
(...skipping 12 matching lines...) Expand all
739 unsigned new_length) { 751 unsigned new_length) {
740 if (!PossiblyHasMarkers(DocumentMarker::AllMarkers())) 752 if (!PossiblyHasMarkers(DocumentMarker::AllMarkers()))
741 return; 753 return;
742 DCHECK(!markers_.IsEmpty()); 754 DCHECK(!markers_.IsEmpty());
743 755
744 MarkerLists* markers = markers_.at(node); 756 MarkerLists* markers = markers_.at(node);
745 if (!markers) 757 if (!markers)
746 return; 758 return;
747 759
748 bool did_shift_marker = false; 760 bool did_shift_marker = false;
749 for (MarkerList* list : *markers) { 761 for (DocumentMarkerList* list : *markers) {
750 if (!list) 762 if (!list)
751 continue; 763 continue;
752 764
753 if (DocumentMarkerListEditor::ShiftMarkers(list, offset, old_length, 765 if (list->ShiftMarkers(offset, old_length, new_length))
754 new_length))
755 did_shift_marker = true; 766 did_shift_marker = true;
756 } 767 }
757 768
758 if (!did_shift_marker) 769 if (!did_shift_marker)
759 return; 770 return;
760 if (!node->GetLayoutObject()) 771 if (!node->GetLayoutObject())
761 return; 772 return;
762 InvalidateRectsForMarkersInNode(*node); 773 InvalidateRectsForMarkersInNode(*node);
763 // repaint the affected node 774 // repaint the affected node
764 node->GetLayoutObject()->SetShouldDoFullPaintInvalidation(); 775 node->GetLayoutObject()->SetShouldDoFullPaintInvalidation();
765 } 776 }
766 777
767 } // namespace blink 778 } // namespace blink
768 779
769 #ifndef NDEBUG 780 #ifndef NDEBUG
770 void showDocumentMarkers(const blink::DocumentMarkerController* controller) { 781 void showDocumentMarkers(const blink::DocumentMarkerController* controller) {
771 if (controller) 782 if (controller)
772 controller->ShowMarkers(); 783 controller->ShowMarkers();
773 } 784 }
774 #endif 785 #endif
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698