Make ComputeNGCaretPosition() faster
This patch changes |ComputeNGCaretPosition()| to utilize |LayoutText|
parameter to start searching caret position at inline fragment
associated to |LayoutText| parameter instead of starting from first
inline fragment in containing block to avoid redundant looping for
making |ComputeNGCaretPosition()| faster.
This patch also fixes legacy layout and LayoutNG differences observed
in |ParameterizedLocalCaretRectTest|.
Bug: 707656
Change-Id: I57087ab4634e528ca5c66a9ac87b7c95a18e9674
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2509832
Commit-Queue: Yoshifumi Inoue <yosin@chromium.org>
Auto-Submit: Yoshifumi Inoue <yosin@chromium.org>
Reviewed-by: Kent Tamura <tkent@chromium.org>
Cr-Commit-Position: refs/heads/master@{#823104}
diff --git a/third_party/blink/perf_tests/editing/move_backward_with_may_elements.html b/third_party/blink/perf_tests/editing/move_backward_with_may_elements.html
new file mode 100644
index 0000000..511e39d
--- /dev/null
+++ b/third_party/blink/perf_tests/editing/move_backward_with_may_elements.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<body>
+<script src="../resources/runner.js"></script>
+<script src="resources/line-layout-perf-test.js"></script>
+<style>
+#container {
+ width: 400px;
+ height: 200px;
+ overflow: scroll;
+}
+</style>
+<div id="container"></div>
+<script>
+const NUMBER_OF_WORDS = 300;
+const NUMBER_OF_MOVES = 500;
+const container = document.getElementById('container');
+const selection = window.getSelection();
+
+for (let wordCount = NUMBER_OF_WORDS; wordCount > 0; --wordCount) {
+ const word = document.createElement('span');
+ word.textContent = Math.random().toString(36).slice(2) + ' ';
+ container.appendChild(word);
+}
+
+PerfTestRunner.measureRunsPerSecond({
+ setup: () => {
+ },
+ run: () => {
+ container.scrollTo(0, container.scrollHeight);
+ selection.collapse(container, container.childNodes.length);
+ for (let i = 0; i < NUMBER_OF_MOVES; ++i)
+ selection.modify('extend', 'backward', 'character');
+ },
+});
+</script>
diff --git a/third_party/blink/renderer/core/editing/local_caret_rect_test.cc b/third_party/blink/renderer/core/editing/local_caret_rect_test.cc
index 4f59c057..03a54014 100644
--- a/third_party/blink/renderer/core/editing/local_caret_rect_test.cc
+++ b/third_party/blink/renderer/core/editing/local_caret_rect_test.cc
@@ -445,13 +445,10 @@
PositionWithAffinity(after_c, TextAffinity::kDownstream)));
const Position before_d(text_d, 0);
- // TODO(xiaochengh): Should return the same result for legacy and LayoutNG.
- EXPECT_EQ(LayoutNGEnabled() ? LocalCaretRect(text_c->GetLayoutObject(),
- PhysicalRect(29, 0, 1, 10))
- : LocalCaretRect(text_d->GetLayoutObject(),
- PhysicalRect(0, 10, 1, 10)),
- LocalCaretRectOfPosition(
- PositionWithAffinity(before_d, TextAffinity::kUpstream)));
+ EXPECT_EQ(
+ LocalCaretRect(text_d->GetLayoutObject(), PhysicalRect(0, 10, 1, 10)),
+ LocalCaretRectOfPosition(
+ PositionWithAffinity(before_d, TextAffinity::kUpstream)));
EXPECT_EQ(
LocalCaretRect(text_d->GetLayoutObject(), PhysicalRect(0, 10, 1, 10)),
LocalCaretRectOfPosition(
@@ -487,13 +484,10 @@
PositionWithAffinity(after_c, TextAffinity::kDownstream)));
const Position before_d(text_d, 0);
- // TODO(xiaochengh): Should return the same result for legacy and LayoutNG.
- EXPECT_EQ(LayoutNGEnabled() ? LocalCaretRect(text_c->GetLayoutObject(),
- PhysicalRect(0, 0, 1, 10))
- : LocalCaretRect(text_d->GetLayoutObject(),
- PhysicalRect(29, 10, 1, 10)),
- LocalCaretRectOfPosition(
- PositionWithAffinity(before_d, TextAffinity::kUpstream)));
+ EXPECT_EQ(
+ LocalCaretRect(text_d->GetLayoutObject(), PhysicalRect(29, 10, 1, 10)),
+ LocalCaretRectOfPosition(
+ PositionWithAffinity(before_d, TextAffinity::kUpstream)));
EXPECT_EQ(
LocalCaretRect(text_d->GetLayoutObject(), PhysicalRect(29, 10, 1, 10)),
LocalCaretRectOfPosition(
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_caret_position.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_caret_position.cc
index dc599758..06bcec8 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_caret_position.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_caret_position.cc
@@ -271,6 +271,8 @@
NGInlineCursor cursor(context);
NGCaretPosition candidate;
+ if (layout_text && layout_text->HasInlineFragments())
+ cursor.MoveTo(*layout_text);
for (; cursor; cursor.MoveToNext()) {
const CaretPositionResolution resolution =
TryResolveCaretPositionWithFragment(cursor, offset, affinity);
@@ -321,7 +323,8 @@
const LayoutText* const layout_text =
position.IsOffsetInAnchor() && IsA<Text>(position.AnchorNode())
- ? To<Text>(position.AnchorNode())->GetLayoutObject()
+ ? ToLayoutText(AssociatedLayoutObjectOf(
+ *position.AnchorNode(), position.OffsetInContainerNode()))
: nullptr;
const unsigned offset = *maybe_offset;