Commit eef04de4 authored by rlanday's avatar rlanday Committed by Commit Bot

Optimize SpellChecker::GetSpellCheckMarkerUnderSelection()

Currently, this method does a linear scan over all spell check markers contained
in the text node(s) containing the selection. This takes about 0.553 ms on the
source for the "List of Australian treaties" Wikipedia page. This CL refactors
this method to instead use the newly-added
DocumentMarkerController::FirstMarkerIntersectingRange() method, which is more
efficient as it uses binary search. With this change, we now spend about
~0.02 ms in this method doing the same test.

BUG=736181

Review-Url: https://codereview.chromium.org/2947093003
Cr-Commit-Position: refs/heads/master@{#488577}
parent 5e4f0f6a
...@@ -836,33 +836,35 @@ SpellChecker::GetSpellCheckMarkerUnderSelection() { ...@@ -836,33 +836,35 @@ SpellChecker::GetSpellCheckMarkerUnderSelection() {
if (selection.IsNone()) if (selection.IsNone())
return Optional<std::pair<Node*, SpellCheckMarker*>>(); return Optional<std::pair<Node*, SpellCheckMarker*>>();
const EphemeralRange& range_to_check = FirstEphemeralRangeOf(selection); // Caret and range selections always return valid normalized ranges.
const EphemeralRange& selection_range = FirstEphemeralRangeOf(selection);
Node* const start_container =
range_to_check.StartPosition().ComputeContainerNode(); Node* const selection_start_container =
const unsigned start_offset = selection_range.StartPosition().ComputeContainerNode();
range_to_check.StartPosition().ComputeOffsetInContainerNode(); Node* const selection_end_container =
Node* const end_container = selection_range.EndPosition().ComputeContainerNode();
range_to_check.EndPosition().ComputeContainerNode();
const unsigned end_offset = // We don't currently support the case where a misspelling spans multiple
range_to_check.EndPosition().ComputeOffsetInContainerNode(); // nodes. See crbug.com/720065
if (selection_start_container != selection_end_container)
for (Node& node : range_to_check.Nodes()) { return {};
const DocumentMarkerVector& markers_in_node =
GetFrame().GetDocument()->Markers().MarkersFor( if (!selection_start_container->IsTextNode())
&node, DocumentMarker::MisspellingMarkers()); return {};
for (DocumentMarker* marker : markers_in_node) {
if (node == start_container && marker->EndOffset() <= start_offset) const unsigned selection_start_offset =
continue; selection_range.StartPosition().ComputeOffsetInContainerNode();
if (node == end_container && marker->StartOffset() >= end_offset) const unsigned selection_end_offset =
continue; selection_range.EndPosition().ComputeOffsetInContainerNode();
return std::make_pair(&node, &ToSpellCheckMarker(*marker)); DocumentMarker* const marker =
} GetFrame().GetDocument()->Markers().FirstMarkerIntersectingOffsetRange(
} ToText(*selection_start_container), selection_start_offset,
selection_end_offset, DocumentMarker::MisspellingMarkers());
// No marker found if (!marker)
return Optional<std::pair<Node*, SpellCheckMarker*>>(); return Optional<std::pair<Node*, SpellCheckMarker*>>();
return std::make_pair(selection_start_container, ToSpellCheckMarker(marker));
} }
void SpellChecker::ReplaceMisspelledRange(const String& text) { void SpellChecker::ReplaceMisspelledRange(const String& text) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment