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

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

Issue 2763893002: [WIP] Clean up DocumentMarkerController API (Closed)
Patch Set: Created 3 years, 9 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 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
42 #include "core/editing/markers/TextMatchMarkerList.h" 42 #include "core/editing/markers/TextMatchMarkerList.h"
43 #include "core/frame/FrameView.h" 43 #include "core/frame/FrameView.h"
44 #include "core/layout/LayoutObject.h" 44 #include "core/layout/LayoutObject.h"
45 45
46 #ifndef NDEBUG 46 #ifndef NDEBUG
47 #include <stdio.h> 47 #include <stdio.h>
48 #endif 48 #endif
49 49
50 namespace blink { 50 namespace blink {
51 51
52 MarkerRemoverPredicate::MarkerRemoverPredicate(const Vector<String>& words)
53 : m_words(words) {}
54
55 bool MarkerRemoverPredicate::operator()(const DocumentMarker& documentMarker,
56 const Text& textNode) const {
57 unsigned start = documentMarker.startOffset();
58 unsigned length = documentMarker.endOffset() - documentMarker.startOffset();
59
60 String markerText = textNode.data().substring(start, length);
61 return m_words.contains(markerText);
62 }
63
64 DocumentMarkerController::DocumentMarkerController(Document& document) 52 DocumentMarkerController::DocumentMarkerController(Document& document)
65 : m_document(&document) { 53 : m_document(&document) {
66 setContext(&document); 54 setContext(&document);
67 } 55 }
68 56
69 void DocumentMarkerController::clear() { 57 void DocumentMarkerController::clear() {
70 m_spelling.clear(); 58 m_spelling.clear();
71 m_grammar.clear(); 59 m_grammar.clear();
72 m_textMatches.clear(); 60 m_textMatches.clear();
73 m_compositions.clear(); 61 m_compositions.clear();
74 } 62 }
75 63
76 void DocumentMarkerController::addMarker(const Position& start,
77 const Position& end,
78 DocumentMarker::MarkerType type,
79 const String& description) {
80 // Use a TextIterator to visit the potentially multiple nodes the range
81 // covers.
82 for (TextIterator markedText(start, end); !markedText.atEnd();
83 markedText.advance()) {
84 addMarker(markedText.currentContainer(),
85 new DocumentMarker(
86 type, markedText.startOffsetInCurrentContainer(),
87 markedText.endOffsetInCurrentContainer(), description));
88 }
89 }
90
91 void DocumentMarkerController::addTextMatchMarker(const EphemeralRange& range,
92 bool activeMatch) {
93 DCHECK(!m_document->needsLayoutTreeUpdate());
94
95 // Use a TextIterator to visit the potentially multiple nodes the range
96 // covers.
97 for (TextIterator markedText(range.startPosition(), range.endPosition());
98 !markedText.atEnd(); markedText.advance()) {
99 addMarker(markedText.currentContainer(),
100 new DocumentMarker(markedText.startOffsetInCurrentContainer(),
101 markedText.endOffsetInCurrentContainer(),
102 activeMatch));
103 }
104 // Don't invalidate tickmarks here. TextFinder invalidates tickmarks using a
105 // throttling algorithm. crbug.com/6819.
106 }
107
108 void DocumentMarkerController::addCompositionMarker(const Position& start, 64 void DocumentMarkerController::addCompositionMarker(const Position& start,
109 const Position& end, 65 const Position& end,
110 Color underlineColor, 66 Color underlineColor,
111 bool thick, 67 bool thick,
112 Color backgroundColor) { 68 Color backgroundColor) {
113 DCHECK(!m_document->needsLayoutTreeUpdate()); 69 DCHECK(!m_document->needsLayoutTreeUpdate());
114 70
115 for (TextIterator markedText(start, end); !markedText.atEnd(); 71 for (TextIterator markedText(start, end); !markedText.atEnd();
116 markedText.advance()) { 72 markedText.advance()) {
117 addMarker(markedText.currentContainer(), 73 addMarker(markedText.currentContainer(),
118 new DocumentMarker(markedText.startOffsetInCurrentContainer(), 74 DocumentMarker::createCompositionMarker(
119 markedText.endOffsetInCurrentContainer(), 75 markedText.startOffsetInCurrentContainer(),
120 underlineColor, thick, backgroundColor)); 76 markedText.endOffsetInCurrentContainer(), underlineColor,
77 thick, backgroundColor));
121 } 78 }
122 } 79 }
123 80
81 void DocumentMarkerController::addGrammarOrSpellingMarker(
82 const Position& start,
83 const Position& end,
84 DocumentMarker::MarkerType type,
85 const String& description) {
86 DCHECK(!m_document->needsLayoutTreeUpdate());
87 DCHECK(type == DocumentMarker::Grammar || type == DocumentMarker::Spelling);
88 // Use a TextIterator to visit the potentially multiple nodes the range
89 // covers.
90 for (TextIterator markedText(start, end); !markedText.atEnd();
91 markedText.advance()) {
92 DocumentMarker* marker;
93 if (type == DocumentMarker::Grammar) {
94 marker = DocumentMarker::createGrammarMarker(
95 markedText.startOffsetInCurrentContainer(),
96 markedText.endOffsetInCurrentContainer(), description);
97 } else {
98 marker = DocumentMarker::createSpellingMarker(
99 markedText.startOffsetInCurrentContainer(),
100 markedText.endOffsetInCurrentContainer(), description);
101 }
102
103 addMarker(markedText.currentContainer(), marker);
104 }
105 }
106
107 void DocumentMarkerController::addGrammarMarker(const Position& start,
108 const Position& end,
109 const String& description) {
110 addGrammarOrSpellingMarker(start, end, DocumentMarker::Grammar, description);
111 }
112
113 void DocumentMarkerController::addSpellingMarker(const Position& start,
114 const Position& end,
115 const String& description) {
116 addGrammarOrSpellingMarker(start, end, DocumentMarker::Spelling, description);
117 }
118
119 void DocumentMarkerController::addTextMatchMarker(const Position& start,
120 const Position& end,
121 bool activeMatch) {
122 DCHECK(!m_document->needsLayoutTreeUpdate());
123
124 // Use a TextIterator to visit the potentially multiple nodes the range
125 // covers.
126 for (TextIterator markedText(start, end); !markedText.atEnd();
127 markedText.advance()) {
128 addMarker(markedText.currentContainer(),
129 DocumentMarker::createTextMatchMarker(
130 markedText.startOffsetInCurrentContainer(),
131 markedText.endOffsetInCurrentContainer(), activeMatch));
132 }
133 // Don't invalidate tickmarks here. TextFinder invalidates tickmarks using a
134 // throttling algorithm. crbug.com/6819.
135 }
136
124 void DocumentMarkerController::prepareForDestruction() { 137 void DocumentMarkerController::prepareForDestruction() {
125 clear(); 138 clear();
126 } 139 }
127 140
128 void DocumentMarkerController::removeMarkers( 141 void DocumentMarkerController::removeMarkers(
129 const EphemeralRange& range, 142 const EphemeralRange& range,
130 DocumentMarker::MarkerTypes markerTypes, 143 DocumentMarker::MarkerTypes markerTypes,
131 RemovePartiallyOverlappingMarkerOrNot 144 RemovePartiallyOverlappingMarkerOrNot
132 shouldRemovePartiallyOverlappingMarker) { 145 shouldRemovePartiallyOverlappingMarker) {
133 DCHECK(!m_document->needsLayoutTreeUpdate()); 146 DCHECK(!m_document->needsLayoutTreeUpdate());
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
297 if (node == startContainer && marker->endOffset() <= startOffset) 310 if (node == startContainer && marker->endOffset() <= startOffset)
298 continue; 311 continue;
299 if (node == endContainer && marker->startOffset() >= endOffset) 312 if (node == endContainer && marker->startOffset() >= endOffset)
300 continue; 313 continue;
301 foundMarkers.push_back(marker); 314 foundMarkers.push_back(marker);
302 } 315 }
303 } 316 }
304 return foundMarkers; 317 return foundMarkers;
305 } 318 }
306 319
307 Vector<IntRect> DocumentMarkerController::renderedRectsForMarkers( 320 Vector<IntRect> DocumentMarkerController::renderedRectsForTextMatchMarkers() {
308 DocumentMarker::MarkerType) {
309 Vector<IntRect> result; 321 Vector<IntRect> result;
310 322
311 // outer loop: process each node 323 // outer loop: process each node
312 for (auto nodeIterator = m_textMatches.begin(); 324 for (auto nodeIterator = m_textMatches.begin();
313 nodeIterator != m_textMatches.end(); ++nodeIterator) { 325 nodeIterator != m_textMatches.end(); ++nodeIterator) {
314 // inner loop; process each marker in this node 326 // inner loop; process each marker in this node
315 const Node& node = *nodeIterator->key; 327 const Node& node = *nodeIterator->key;
316 TextMatchMarkerList* list = nodeIterator->value.get(); 328 TextMatchMarkerList* list = nodeIterator->value.get();
317 #if DCHECK_IS_ON() 329 #if DCHECK_IS_ON()
318 if (!list->empty()) { 330 if (!list->empty()) {
(...skipping 11 matching lines...) Expand all
330 } 342 }
331 343
332 return result; 344 return result;
333 } 345 }
334 346
335 static void invalidatePaintForTickmarks(const Node& node) { 347 static void invalidatePaintForTickmarks(const Node& node) {
336 if (FrameView* frameView = node.document().view()) 348 if (FrameView* frameView = node.document().view())
337 frameView->invalidatePaintForTickmarks(); 349 frameView->invalidatePaintForTickmarks();
338 } 350 }
339 351
340 void DocumentMarkerController::invalidateRectsForMarkersInNode(Node& node) { 352 void DocumentMarkerController::invalidateRectsForTextMatchMarkersInNode(
353 Node& node) {
341 if (!m_textMatches.contains(&node)) 354 if (!m_textMatches.contains(&node))
342 return; 355 return;
343 356
344 TextMatchMarkerList& markerList = *(m_textMatches.find(&node)->value); 357 TextMatchMarkerList& markerList = *(m_textMatches.find(&node)->value);
345 358
346 for (Member<DocumentMarker> marker : markerList) { 359 for (Member<DocumentMarker> marker : markerList) {
347 auto renderedTextMatchMarker = toRenderedTextMatchMarkerOrDie(marker.get()); 360 auto renderedTextMatchMarker = toRenderedTextMatchMarkerOrDie(marker.get());
348 renderedTextMatchMarker->invalidate(); 361 renderedTextMatchMarker->invalidate();
349 } 362 }
350 363
351 invalidatePaintForTickmarks(node); 364 invalidatePaintForTickmarks(node);
352 } 365 }
353 366
354 void DocumentMarkerController::invalidateRectsForAllMarkers() { 367 void DocumentMarkerController::invalidateRectsForAllTextMatchMarkers() {
355 for (auto& nodeMarkers : m_textMatches) 368 for (auto& nodeMarkers : m_textMatches)
356 invalidateRectsForMarkersInNode(*nodeMarkers.key); 369 invalidateRectsForTextMatchMarkersInNode(*nodeMarkers.key);
357 } 370 }
358 371
359 DEFINE_TRACE(DocumentMarkerController) { 372 DEFINE_TRACE(DocumentMarkerController) {
360 visitor->trace(m_spelling); 373 visitor->trace(m_spelling);
361 visitor->trace(m_grammar); 374 visitor->trace(m_grammar);
362 visitor->trace(m_textMatches); 375 visitor->trace(m_textMatches);
363 visitor->trace(m_compositions); 376 visitor->trace(m_compositions);
364 visitor->trace(m_document); 377 visitor->trace(m_document);
365 SynchronousMutationObserver::trace(visitor); 378 SynchronousMutationObserver::trace(visitor);
366 } 379 }
367 380
368 void DocumentMarkerController::removeMarkers( 381 void DocumentMarkerController::removeMarkers(
369 Node* node, 382 Node* node,
370 DocumentMarker::MarkerTypes markerTypes) { 383 DocumentMarker::MarkerTypes markerTypes) {
371 if (markerTypes.contains(DocumentMarker::Spelling)) 384 if (markerTypes.contains(DocumentMarker::Spelling))
372 m_spelling.remove(node); 385 m_spelling.remove(node);
373 386
374 if (markerTypes.contains(DocumentMarker::Grammar)) 387 if (markerTypes.contains(DocumentMarker::Grammar))
375 m_grammar.remove(node); 388 m_grammar.remove(node);
376 389
377 if (markerTypes.contains(DocumentMarker::TextMatch)) 390 if (markerTypes.contains(DocumentMarker::TextMatch))
378 m_textMatches.remove(node); 391 m_textMatches.remove(node);
379 392
380 if (markerTypes.contains(DocumentMarker::Composition)) 393 if (markerTypes.contains(DocumentMarker::Composition))
381 m_compositions.remove(node); 394 m_compositions.remove(node);
382 } 395 }
383 396
397 void DocumentMarkerController::removeSpellingMarkersForWords(
398 const Vector<String>& words) {
399 for (auto& nodeMarkers : m_spelling) {
400 const Node& node = *nodeMarkers.key;
401 if (!node.isTextNode())
402 continue;
403 nodeMarkers.value->removeMarkersForWords(static_cast<const Text&>(node),
404 words);
405 }
406 }
407
384 void DocumentMarkerController::removeMarkers( 408 void DocumentMarkerController::removeMarkers(
385 DocumentMarker::MarkerTypes markerTypes) { 409 DocumentMarker::MarkerTypes markerTypes) {
386 if (markerTypes.contains(DocumentMarker::Spelling)) 410 if (markerTypes.contains(DocumentMarker::Spelling))
387 m_spelling.clear(); 411 m_spelling.clear();
388 412
389 if (markerTypes.contains(DocumentMarker::Grammar)) 413 if (markerTypes.contains(DocumentMarker::Grammar))
390 m_grammar.clear(); 414 m_grammar.clear();
391 415
392 if (markerTypes.contains(DocumentMarker::TextMatch)) 416 if (markerTypes.contains(DocumentMarker::TextMatch))
393 m_textMatches.clear(); 417 m_textMatches.clear();
394 418
395 if (markerTypes.contains(DocumentMarker::Composition)) 419 if (markerTypes.contains(DocumentMarker::Composition))
396 m_compositions.clear(); 420 m_compositions.clear();
397 } 421 }
398 422
399 void DocumentMarkerController::removeMarkers(
400 const MarkerRemoverPredicate& shouldRemoveMarker) {
401 for (auto& nodeMarkers : m_spelling) {
402 const Node& node = *nodeMarkers.key;
403 if (!node.isTextNode())
404 continue;
405 nodeMarkers.value->removeMarkersForWords(static_cast<const Text&>(node),
406 shouldRemoveMarker.m_words);
407 }
408 }
409
410 void DocumentMarkerController::repaintMarkers( 423 void DocumentMarkerController::repaintMarkers(
411 DocumentMarker::MarkerTypes markerTypes) { 424 DocumentMarker::MarkerTypes markerTypes) {
412 HeapHashSet<Member<Node>> nodesToRepaint; 425 HeapHashSet<Member<Node>> nodesToRepaint;
413 for (auto& nodeMarkers : m_spelling) { 426 for (auto& nodeMarkers : m_spelling) {
414 if (!nodeMarkers.value->empty()) 427 if (!nodeMarkers.value->empty())
415 nodesToRepaint.insert(nodeMarkers.key.get()); 428 nodesToRepaint.insert(nodeMarkers.key.get());
416 } 429 }
417 430
418 for (auto& nodeMarkers : m_grammar) { 431 for (auto& nodeMarkers : m_grammar) {
419 if (!nodeMarkers.value->empty()) 432 if (!nodeMarkers.value->empty())
(...skipping 13 matching lines...) Expand all
433 for (Member<Node> node : nodesToRepaint) { 446 for (Member<Node> node : nodesToRepaint) {
434 // cause the node to be redrawn 447 // cause the node to be redrawn
435 if (LayoutObject* layoutObject = node->layoutObject()) { 448 if (LayoutObject* layoutObject = node->layoutObject()) {
436 layoutObject->setShouldDoFullPaintInvalidation( 449 layoutObject->setShouldDoFullPaintInvalidation(
437 PaintInvalidationDocumentMarkerChange); 450 PaintInvalidationDocumentMarkerChange);
438 break; 451 break;
439 } 452 }
440 } 453 }
441 } 454 }
442 455
443 bool DocumentMarkerController::setMarkersActive(const EphemeralRange& range, 456 bool DocumentMarkerController::setTextMatchMarkersActive(
444 bool active) { 457 const EphemeralRange& range,
458 bool active) {
445 Node* const startContainer = range.startPosition().computeContainerNode(); 459 Node* const startContainer = range.startPosition().computeContainerNode();
446 DCHECK(startContainer); 460 DCHECK(startContainer);
447 Node* const endContainer = range.endPosition().computeContainerNode(); 461 Node* const endContainer = range.endPosition().computeContainerNode();
448 DCHECK(endContainer); 462 DCHECK(endContainer);
449 463
450 const unsigned containerStartOffset = 464 const unsigned containerStartOffset =
451 range.startPosition().computeOffsetInContainerNode(); 465 range.startPosition().computeOffsetInContainerNode();
452 const unsigned containerEndOffset = 466 const unsigned containerEndOffset =
453 range.endPosition().computeOffsetInContainerNode(); 467 range.endPosition().computeOffsetInContainerNode();
454 468
455 bool markerFound = false; 469 bool markerFound = false;
456 for (Node& node : range.nodes()) { 470 for (Node& node : range.nodes()) {
457 int startOffset = node == startContainer ? containerStartOffset : 0; 471 int startOffset = node == startContainer ? containerStartOffset : 0;
458 int endOffset = node == endContainer ? containerEndOffset : INT_MAX; 472 int endOffset = node == endContainer ? containerEndOffset : INT_MAX;
459 markerFound |= setMarkersActive(&node, startOffset, endOffset, active); 473 markerFound |=
474 setTextMatchMarkersActive(&node, startOffset, endOffset, active);
460 } 475 }
461 return markerFound; 476 return markerFound;
462 } 477 }
463 478
464 bool DocumentMarkerController::hasMarkers(Node* node) const { 479 bool DocumentMarkerController::hasMarkers(Node* node) const {
465 return m_spelling.contains(node) || m_grammar.contains(node) || 480 return m_spelling.contains(node) || m_grammar.contains(node) ||
466 m_textMatches.contains(node) || m_compositions.contains(node); 481 m_textMatches.contains(node) || m_compositions.contains(node);
467 } 482 }
468 483
469 bool DocumentMarkerController::setMarkersActive(Node* node, 484 bool DocumentMarkerController::setTextMatchMarkersActive(Node* node,
470 unsigned startOffset, 485 unsigned startOffset,
471 unsigned endOffset, 486 unsigned endOffset,
472 bool active) { 487 bool active) {
473 bool docDirty = false; 488 bool docDirty = false;
474 if (m_textMatches.contains(node)) { 489 if (m_textMatches.contains(node)) {
475 docDirty = m_textMatches.at(node)->setTextMatchMarkersActive( 490 docDirty = m_textMatches.at(node)->setTextMatchMarkersActive(
476 startOffset, endOffset, active); 491 startOffset, endOffset, active);
477 } 492 }
478 493
479 if (docDirty && node->layoutObject()) 494 if (docDirty && node->layoutObject())
480 node->layoutObject()->setShouldDoFullPaintInvalidation( 495 node->layoutObject()->setShouldDoFullPaintInvalidation(
481 PaintInvalidationDocumentMarkerChange); 496 PaintInvalidationDocumentMarkerChange);
482 497
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
618 shiftMarkersInNode(&m_spelling, node, offset, oldLength, newLength, 633 shiftMarkersInNode(&m_spelling, node, offset, oldLength, newLength,
619 &didShiftMarker); 634 &didShiftMarker);
620 shiftMarkersInNode(&m_grammar, node, offset, oldLength, newLength, 635 shiftMarkersInNode(&m_grammar, node, offset, oldLength, newLength,
621 &didShiftMarker); 636 &didShiftMarker);
622 shiftMarkersInNode(&m_textMatches, node, offset, oldLength, newLength, 637 shiftMarkersInNode(&m_textMatches, node, offset, oldLength, newLength,
623 &didShiftMarker); 638 &didShiftMarker);
624 shiftMarkersInNode(&m_compositions, node, offset, oldLength, newLength, 639 shiftMarkersInNode(&m_compositions, node, offset, oldLength, newLength,
625 &didShiftMarker); 640 &didShiftMarker);
626 641
627 if (didShiftMarker) { 642 if (didShiftMarker) {
628 invalidateRectsForMarkersInNode(*node); 643 invalidateRectsForTextMatchMarkersInNode(*node);
629 // repaint the affected node 644 // repaint the affected node
630 if (node->layoutObject()) { 645 if (node->layoutObject()) {
631 node->layoutObject()->setShouldDoFullPaintInvalidation( 646 node->layoutObject()->setShouldDoFullPaintInvalidation(
632 PaintInvalidationDocumentMarkerChange); 647 PaintInvalidationDocumentMarkerChange);
633 } 648 }
634 } 649 }
635 } 650 }
636 651
637 } // namespace blink 652 } // namespace blink
638 653
639 #ifndef NDEBUG 654 #ifndef NDEBUG
640 void showDocumentMarkers(const blink::DocumentMarkerController* controller) { 655 void showDocumentMarkers(const blink::DocumentMarkerController* controller) {
641 if (controller) 656 if (controller)
642 controller->showMarkers(); 657 controller->showMarkers();
643 } 658 }
644 #endif 659 #endif
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698