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

Unified Diff: third_party/WebKit/Source/core/editing/spellcheck/ColdModeSpellCheckRequester.cpp

Issue 2768393003: Use finer-grained checking in cold mode (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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « third_party/WebKit/Source/core/editing/spellcheck/ColdModeSpellCheckRequester.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: third_party/WebKit/Source/core/editing/spellcheck/ColdModeSpellCheckRequester.cpp
diff --git a/third_party/WebKit/Source/core/editing/spellcheck/ColdModeSpellCheckRequester.cpp b/third_party/WebKit/Source/core/editing/spellcheck/ColdModeSpellCheckRequester.cpp
index a145fa85e195218c6c142e89d4396734b64f6f3a..3fb7e20e89cb6bd796ff9783e5b5ca1df0291a49 100644
--- a/third_party/WebKit/Source/core/editing/spellcheck/ColdModeSpellCheckRequester.cpp
+++ b/third_party/WebKit/Source/core/editing/spellcheck/ColdModeSpellCheckRequester.cpp
@@ -19,6 +19,8 @@ namespace blink {
namespace {
const int kColdModeChunkSize = 16384; // in UTF16 code units
+const int kInvalidLength = -1;
+const int kInvalidChunkIndex = -1;
bool shouldCheckNode(const Node& node) {
if (!node.isElementNode())
@@ -44,6 +46,8 @@ ColdModeSpellCheckRequester* ColdModeSpellCheckRequester::create(
DEFINE_TRACE(ColdModeSpellCheckRequester) {
visitor->trace(m_frame);
visitor->trace(m_nextNode);
+ visitor->trace(m_currentRootEditable);
+ visitor->trace(m_currentChunkStart);
}
ColdModeSpellCheckRequester::ColdModeSpellCheckRequester(LocalFrame& frame)
@@ -63,48 +67,12 @@ SpellCheckRequester& ColdModeSpellCheckRequester::spellCheckRequester() const {
return frame().spellChecker().spellCheckRequester();
}
-// TODO(xiaochengh): Deduplicate with SpellChecker::chunkAndMarkAllMisspellings.
-void ColdModeSpellCheckRequester::chunkAndRequestFullCheckingFor(
- const Element& editable) {
- const EphemeralRange& fullRange = EphemeralRange::rangeOfContents(editable);
- const int fullLength = TextIterator::rangeLength(fullRange.startPosition(),
- fullRange.endPosition());
-
- // Check the full content if it is short.
- if (fullLength <= kColdModeChunkSize) {
- spellCheckRequester().requestCheckingFor(fullRange);
- return;
- }
-
- // TODO(xiaochengh): Figure out if this is going to cause performance issues.
- // In that case, we need finer-grained control over request generation.
- Position chunkStart = fullRange.startPosition();
- const int chunkLimit = fullLength / kColdModeChunkSize + 1;
- for (int chunkIndex = 0; chunkIndex <= chunkLimit; ++chunkIndex) {
- const Position& chunkEnd =
- calculateCharacterSubrange(
- EphemeralRange(chunkStart, fullRange.endPosition()), 0,
- kColdModeChunkSize)
- .endPosition();
- if (chunkEnd <= chunkStart)
- break;
- const EphemeralRange chunkRange(chunkStart, chunkEnd);
- const EphemeralRange& checkRange =
- chunkIndex >= 1 ? expandEndToSentenceBoundary(chunkRange)
- : expandRangeToSentenceBoundary(chunkRange);
-
- spellCheckRequester().requestCheckingFor(checkRange, chunkIndex);
-
- chunkStart = checkRange.endPosition();
- }
-}
-
void ColdModeSpellCheckRequester::invoke(IdleDeadline* deadline) {
TRACE_EVENT0("blink", "ColdModeSpellCheckRequester::invoke");
Node* body = frame().document()->body();
if (!body) {
- m_nextNode = nullptr;
+ resetCheckingProgress();
m_lastCheckedDOMTreeVersion = frame().document()->domTreeVersion();
return;
}
@@ -113,22 +81,101 @@ void ColdModeSpellCheckRequester::invoke(IdleDeadline* deadline) {
frame().document()->updateStyleAndLayout();
if (m_lastCheckedDOMTreeVersion != frame().document()->domTreeVersion())
- m_nextNode = body;
-
- // TODO(xiaochengh): Figure out if such frequent calls of |timeRemaining()|
- // have any performance impact. We might not want to check remaining time
- // so frequently in a page with millions of nodes.
- while (m_nextNode && deadline->timeRemaining() > 0) {
- if (!shouldCheckNode(*m_nextNode)) {
- m_nextNode = FlatTreeTraversal::next(*m_nextNode, body);
- continue;
- }
-
- chunkAndRequestFullCheckingFor(toElement(*m_nextNode));
- m_nextNode = FlatTreeTraversal::nextSkippingChildren(*m_nextNode, body);
- }
+ resetCheckingProgress();
+ while (m_nextNode && deadline->timeRemaining() > 0)
+ step();
m_lastCheckedDOMTreeVersion = frame().document()->domTreeVersion();
}
+void ColdModeSpellCheckRequester::resetCheckingProgress() {
+ m_nextNode = frame().document()->body();
+ m_currentRootEditable = nullptr;
+ m_currentFullLength = kInvalidLength;
+ m_currentChunkIndex = kInvalidChunkIndex;
+ m_currentChunkStart = Position();
+}
+
+void ColdModeSpellCheckRequester::step() {
+ if (!m_nextNode)
+ return;
+
+ if (!m_currentRootEditable) {
+ searchForNextRootEditable();
+ return;
+ }
+
+ if (m_currentFullLength == kInvalidLength) {
+ initializeForCurrentRootEditable();
+ return;
+ }
+
+ DCHECK(m_currentChunkIndex != kInvalidChunkIndex);
+ requestCheckingForNextChunk();
+}
+
+void ColdModeSpellCheckRequester::searchForNextRootEditable() {
+ // TODO(xiaochengh): Figure out if such small steps, which result in frequent
+ // calls of |timeRemaining()|, have any performance impact. We might not want
+ // to check remaining time so frequently in a page with millions of nodes.
+
+ if (shouldCheckNode(*m_nextNode)) {
+ m_currentRootEditable = toElement(m_nextNode);
+ return;
+ }
+
+ m_nextNode = FlatTreeTraversal::next(*m_nextNode, frame().document()->body());
yosin_UTC9 2017/03/24 06:38:42 We need to call |m_nextNode->updateDistribution()|
Xiaocheng 2017/03/24 21:18:43 This function is always called with clean layout,
+}
+
+void ColdModeSpellCheckRequester::initializeForCurrentRootEditable() {
+ const EphemeralRange& fullRange =
+ EphemeralRange::rangeOfContents(*m_currentRootEditable);
+ m_currentFullLength = TextIterator::rangeLength(fullRange.startPosition(),
yosin_UTC9 2017/03/24 06:38:42 Can we use DOM tree base character iterator? Or us
Xiaocheng 2017/03/24 21:18:43 Sorry I don't understand. Could you give more deta
yosin_UTC9 2017/03/27 04:44:14 TextIterator::rangeLength() is expensive and Plain
+ fullRange.endPosition());
+
+ m_currentChunkIndex = 0;
+ m_currentChunkStart = fullRange.startPosition();
+}
+
+void ColdModeSpellCheckRequester::requestCheckingForNextChunk() {
+ // Check the full content if it is short.
+ if (m_currentFullLength <= kColdModeChunkSize) {
+ spellCheckRequester().requestCheckingFor(
+ EphemeralRange::rangeOfContents(*m_currentRootEditable));
+ finishCheckingCurrentRootEditable();
+ return;
+ }
+
+ const Position& chunkEnd =
+ calculateCharacterSubrange(
+ EphemeralRange(m_currentChunkStart,
+ Position::lastPositionInNode(m_currentRootEditable)),
+ 0, kColdModeChunkSize)
+ .endPosition();
+ if (chunkEnd <= m_currentChunkStart) {
+ finishCheckingCurrentRootEditable();
+ return;
+ }
+ const EphemeralRange chunkRange(m_currentChunkStart, chunkEnd);
+ const EphemeralRange& checkRange = expandEndToSentenceBoundary(chunkRange);
+ spellCheckRequester().requestCheckingFor(checkRange, m_currentChunkIndex);
+
+ m_currentChunkStart = checkRange.endPosition();
+ ++m_currentChunkIndex;
+
+ if (m_currentChunkIndex * kColdModeChunkSize >= m_currentFullLength)
+ finishCheckingCurrentRootEditable();
+}
+
+void ColdModeSpellCheckRequester::finishCheckingCurrentRootEditable() {
+ DCHECK_EQ(m_nextNode, m_currentRootEditable);
+ m_nextNode = FlatTreeTraversal::nextSkippingChildren(
+ *m_nextNode, frame().document()->body());
+
+ m_currentRootEditable = nullptr;
+ m_currentFullLength = kInvalidLength;
+ m_currentChunkIndex = kInvalidChunkIndex;
+ m_currentChunkStart = Position();
+}
+
} // namespace blink
« no previous file with comments | « third_party/WebKit/Source/core/editing/spellcheck/ColdModeSpellCheckRequester.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698