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() {
if (selection.IsNone())
return Optional<std::pair<Node*, SpellCheckMarker*>>();
const EphemeralRange& range_to_check = FirstEphemeralRangeOf(selection);
Node* const start_container =
range_to_check.StartPosition().ComputeContainerNode();
const unsigned start_offset =
range_to_check.StartPosition().ComputeOffsetInContainerNode();
Node* const end_container =
range_to_check.EndPosition().ComputeContainerNode();
const unsigned end_offset =
range_to_check.EndPosition().ComputeOffsetInContainerNode();
for (Node& node : range_to_check.Nodes()) {
const DocumentMarkerVector& markers_in_node =
GetFrame().GetDocument()->Markers().MarkersFor(
&node, DocumentMarker::MisspellingMarkers());
for (DocumentMarker* marker : markers_in_node) {
if (node == start_container && marker->EndOffset() <= start_offset)
continue;
if (node == end_container && marker->StartOffset() >= end_offset)
continue;
return std::make_pair(&node, &ToSpellCheckMarker(*marker));
}
}
// Caret and range selections always return valid normalized ranges.
const EphemeralRange& selection_range = FirstEphemeralRangeOf(selection);
Node* const selection_start_container =
selection_range.StartPosition().ComputeContainerNode();
Node* const selection_end_container =
selection_range.EndPosition().ComputeContainerNode();
// We don't currently support the case where a misspelling spans multiple
// nodes. See crbug.com/720065
if (selection_start_container != selection_end_container)
return {};
if (!selection_start_container->IsTextNode())
return {};
const unsigned selection_start_offset =
selection_range.StartPosition().ComputeOffsetInContainerNode();
const unsigned selection_end_offset =
selection_range.EndPosition().ComputeOffsetInContainerNode();
DocumentMarker* const marker =
GetFrame().GetDocument()->Markers().FirstMarkerIntersectingOffsetRange(
ToText(*selection_start_container), selection_start_offset,
selection_end_offset, DocumentMarker::MisspellingMarkers());
if (!marker)
return Optional<std::pair<Node*, SpellCheckMarker*>>();
// No marker found
return Optional<std::pair<Node*, SpellCheckMarker*>>();
return std::make_pair(selection_start_container, ToSpellCheckMarker(marker));
}
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