Chromium Code Reviews| Index: third_party/WebKit/Source/core/editing/spellcheck/HotModeSpellCheckRequester.cpp |
| diff --git a/third_party/WebKit/Source/core/editing/spellcheck/HotModeSpellCheckRequester.cpp b/third_party/WebKit/Source/core/editing/spellcheck/HotModeSpellCheckRequester.cpp |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..3bbebca8d5c150cef282577b4094c41f20d5fd71 |
| --- /dev/null |
| +++ b/third_party/WebKit/Source/core/editing/spellcheck/HotModeSpellCheckRequester.cpp |
| @@ -0,0 +1,107 @@ |
| +// Copyright 2017 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "core/editing/spellcheck/HotModeSpellCheckRequester.h" |
| + |
| +#include "core/editing/EditingUtilities.h" |
| +#include "core/editing/Editor.h" |
| +#include "core/editing/VisiblePosition.h" |
| +#include "core/editing/commands/CompositeEditCommand.h" |
| +#include "core/editing/commands/TypingCommand.h" |
| +#include "core/editing/iterators/BackwardsCharacterIterator.h" |
| +#include "core/editing/iterators/CharacterIterator.h" |
| +#include "core/editing/spellcheck/SpellCheckRequester.h" |
| +#include "core/editing/spellcheck/SpellChecker.h" |
| + |
| +namespace blink { |
| + |
| +namespace { |
| + |
| +const int kHotModeChunkSize = 1024; |
| + |
| +bool isInOrAdjacentToWord(const Position& pos) { |
| + const VisiblePosition& visiblePos = createVisiblePosition(pos); |
| + const VisiblePosition& wordStart = previousWordPosition(visiblePos); |
| + if (wordStart.isNull()) |
| + return false; |
| + const VisiblePosition& wordEnd = endOfWord(wordStart); |
| + if (wordEnd.isNull()) |
| + return false; |
| + return comparePositions(visiblePos, wordEnd) <= 0; |
| +} |
| + |
| +bool isTypingInPartialWord(const Element& editable) { |
| + const LocalFrame& frame = *editable.document().frame(); |
| + const SelectionInDOMTree& selection = frame.selection().selectionInDOMTree(); |
| + if (!selection.isCaret()) |
| + return false; |
| + if (rootEditableElementOf(selection.base()) != &editable) |
| + return false; |
| + |
| + CompositeEditCommand* typingCommand = |
| + frame.editor().lastTypingCommandIfStillOpenForTyping(); |
| + if (!typingCommand) |
| + return false; |
| + if (typingCommand->endingSelection().asSelection() != selection) |
| + return false; |
| + return isInOrAdjacentToWord(selection.base()); |
| +} |
| + |
| +bool shouldCheckRootEditableInHotMode(const Element& editable, |
| + const Position& position) { |
| + if (!editable.isSpellCheckingEnabled() && |
| + !SpellChecker::isSpellCheckingEnabledAt(position)) |
| + return false; |
| + if (editable.visibleBoundsInVisualViewport().isEmpty()) |
| + return false; |
| + // TODO(xiaochengh): Design more aggressive strategies to reduce checking when |
| + // we are just moving selection around without modifying anything. |
| + return !isTypingInPartialWord(editable); |
| +} |
| + |
| +EphemeralRange calculateHotModeCheckingRange(const Element& editable, |
| + const Position& position) { |
| + const EphemeralRange& fullRange = EphemeralRange::rangeOfContents(editable); |
| + const int fullLength = TextIterator::rangeLength(fullRange.startPosition(), |
| + fullRange.endPosition()); |
| + if (fullLength <= kHotModeChunkSize) |
| + return fullRange; |
| + |
| + TextIteratorBehavior behavior = TextIteratorBehavior::Builder() |
| + .setEmitsObjectReplacementCharacter(true) |
| + .build(); |
| + BackwardsCharacterIterator backwardIterator(fullRange.startPosition(), |
| + position, behavior); |
| + backwardIterator.advance(kHotModeChunkSize / 2); |
| + const Position& chunkStart = backwardIterator.endPosition(); |
| + CharacterIterator forwardIterator(position, fullRange.endPosition(), |
| + behavior); |
| + forwardIterator.advance(kHotModeChunkSize / 2); |
| + const Position& chunkEnd = forwardIterator.endPosition(); |
| + return expandRangeToSentenceBoundary(EphemeralRange(chunkStart, chunkEnd)); |
| +} |
| +} |
|
yosin_UTC9
2017/03/07 01:30:31
nit: s"}"} // namespace"
Xiaocheng
2017/03/07 01:37:19
Done.
|
| + |
| +HotModeSpellCheckRequester::HotModeSpellCheckRequester( |
| + SpellCheckRequester& requester) |
| + : m_requester(requester) {} |
| + |
| +void HotModeSpellCheckRequester::checkSpellingAt(const Position& position) { |
| + const Element* rootEditable = rootEditableElementOf(position); |
| + if (!rootEditable || !rootEditable->isConnected()) |
| + return; |
| + |
| + if (m_processedRootEditables.contains(rootEditable)) |
| + return; |
| + m_processedRootEditables.push_back(rootEditable); |
| + |
| + if (!shouldCheckRootEditableInHotMode(*rootEditable, position)) |
| + return; |
| + |
| + SpellCheckRequest* request = SpellCheckRequest::create( |
| + calculateHotModeCheckingRange(*rootEditable, position)); |
| + m_requester->requestCheckingFor(request); |
| +} |
| + |
| +} // namespace blink |