Commit 0ec9ade3 authored by Xiaocheng Hu's avatar Xiaocheng Hu Committed by Commit Bot

Refactor InRenderedText() with LayoutText::ContainsCaretOffset()

This patch refactors InRenderedText() by moving the work on InlineTextBox to
LayoutText::ContainsCaretOffset(), so that InRenderedText() no longer works
on InlineTextBox directly.

A follow-up patch will introduce a LayoutNG version of
LayoutText::ContainsCaretOffset().

Bug: 771398
Change-Id: If786ff57cf881869632e72e2347741433f6a4a17
Reviewed-on: https://chromium-review.googlesource.com/721629
Commit-Queue: Xiaocheng Hu <xiaochengh@chromium.org>
Commit-Queue: Koji Ishii <kojii@chromium.org>
Reviewed-by: default avatarKoji Ishii <kojii@chromium.org>
Reviewed-by: default avatarYoshifumi Inoue <yosin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#509342}
parent deec29ca
...@@ -826,24 +826,15 @@ static bool InRenderedText(const PositionTemplate<Strategy>& position) { ...@@ -826,24 +826,15 @@ static bool InRenderedText(const PositionTemplate<Strategy>& position) {
const LayoutText* text_layout_object = ToLayoutText(layout_object); const LayoutText* text_layout_object = ToLayoutText(layout_object);
const int text_offset = const int text_offset =
offset_in_node - text_layout_object->TextStartOffset(); offset_in_node - text_layout_object->TextStartOffset();
for (InlineTextBox* box : InlineTextBoxesOf(*text_layout_object)) { if (!text_layout_object->ContainsCaretOffset(text_offset))
if (text_offset < static_cast<int>(box->Start()) && return false;
!text_layout_object->ContainsReversedText()) { // Return false for offsets inside composed characters.
// The offset we're looking for is before this node // TODO(editing-dev): Previous/NextGraphemeBoundaryOf() work on DOM offsets,
// this means the offset must be in content that is // So they should use |offset_in_node| instead of |text_offset|.
// not laid out. Return false. return text_offset == text_layout_object->CaretMinOffset() ||
return false; text_offset == NextGraphemeBoundaryOf(*anchor_node,
} PreviousGraphemeBoundaryOf(
if (box->ContainsCaretOffset(text_offset)) { *anchor_node, text_offset));
// Return false for offsets inside composed characters.
return text_offset == text_layout_object->CaretMinOffset() ||
text_offset == NextGraphemeBoundaryOf(
*anchor_node, PreviousGraphemeBoundaryOf(
*anchor_node, text_offset));
}
}
return false;
} }
static FloatQuad LocalToAbsoluteQuadOf(const LocalCaretRect& caret_rect) { static FloatQuad LocalToAbsoluteQuadOf(const LocalCaretRect& caret_rect) {
......
...@@ -1985,6 +1985,22 @@ bool LayoutText::HasNonCollapsedText() const { ...@@ -1985,6 +1985,22 @@ bool LayoutText::HasNonCollapsedText() const {
return FirstTextBox(); return FirstTextBox();
} }
bool LayoutText::ContainsCaretOffset(int text_offset) const {
// TODO(crbug.com/771398): Add LayoutNG alternative.
for (InlineTextBox* box : InlineTextBoxesOf(*this)) {
if (text_offset < static_cast<int>(box->Start()) &&
!ContainsReversedText()) {
// The offset we're looking for is before this node
// this means the offset must be in content that is
// not laid out. Return false.
return false;
}
if (box->ContainsCaretOffset(text_offset))
return true;
}
return false;
}
void LayoutText::MomentarilyRevealLastTypedCharacter( void LayoutText::MomentarilyRevealLastTypedCharacter(
unsigned last_typed_character_offset) { unsigned last_typed_character_offset) {
if (!g_secure_text_timers) if (!g_secure_text_timers)
......
...@@ -201,6 +201,13 @@ class CORE_EXPORT LayoutText : public LayoutObject { ...@@ -201,6 +201,13 @@ class CORE_EXPORT LayoutText : public LayoutObject {
// whitespace) output. // whitespace) output.
bool HasTextBoxes() const { return FirstTextBox(); } bool HasTextBoxes() const { return FirstTextBox(); }
// Returns true if the offset (0-based in the |text_| string) is next to a
// non-collapsed non-linebreak character, or before a forced linebreak (<br>,
// or segment break in node with style white-space: pre/pre-line/pre-wrap).
// TODO(editing-dev): The behavior is introduced by crrev.com/e3eb4e in
// InlineTextBox::ContainsCaretOffset(). Try to understand it.
bool ContainsCaretOffset(int) const;
int CaretMinOffset() const override; int CaretMinOffset() const override;
int CaretMaxOffset() const override; int CaretMaxOffset() const override;
virtual unsigned ResolvedTextLength() const; virtual unsigned ResolvedTextLength() const;
......
...@@ -134,4 +134,54 @@ TEST_F(LayoutTextTest, ResolvedTextLengthNG) { ...@@ -134,4 +134,54 @@ TEST_F(LayoutTextTest, ResolvedTextLengthNG) {
EXPECT_EQ(3u, GetBasicText()->ResolvedTextLength()); EXPECT_EQ(3u, GetBasicText()->ResolvedTextLength());
} }
TEST_F(LayoutTextTest, ContainsCaretOffset) {
// This test records the behavior introduced in crrev.com/e3eb4e
SetBasicBody(" foo bar ");
EXPECT_FALSE(GetBasicText()->ContainsCaretOffset(0)); // "| foo bar "
EXPECT_TRUE(GetBasicText()->ContainsCaretOffset(1)); // " |foo bar "
EXPECT_TRUE(GetBasicText()->ContainsCaretOffset(2)); // " f|oo bar "
EXPECT_TRUE(GetBasicText()->ContainsCaretOffset(3)); // " fo|o bar "
EXPECT_TRUE(GetBasicText()->ContainsCaretOffset(4)); // " foo| bar "
EXPECT_TRUE(GetBasicText()->ContainsCaretOffset(5)); // " foo | bar "
EXPECT_FALSE(GetBasicText()->ContainsCaretOffset(6)); // " foo | bar "
EXPECT_TRUE(GetBasicText()->ContainsCaretOffset(7)); // " foo |bar "
EXPECT_TRUE(GetBasicText()->ContainsCaretOffset(8)); // " foo b|ar "
EXPECT_TRUE(GetBasicText()->ContainsCaretOffset(9)); // " foo ba|r "
EXPECT_TRUE(GetBasicText()->ContainsCaretOffset(10)); // " foo bar| "
EXPECT_FALSE(GetBasicText()->ContainsCaretOffset(11)); // " foo bar |"
}
TEST_F(LayoutTextTest, ContainsCaretOffsetInPre) {
// These tests record the behavior introduced in crrev.com/e3eb4e
SetBodyInnerHTML("<pre id='target'>foo bar</pre>");
EXPECT_TRUE(GetBasicText()->ContainsCaretOffset(0)); // "|foo bar"
EXPECT_TRUE(GetBasicText()->ContainsCaretOffset(1)); // "f|oo bar"
EXPECT_TRUE(GetBasicText()->ContainsCaretOffset(2)); // "fo|o bar"
EXPECT_TRUE(GetBasicText()->ContainsCaretOffset(3)); // "foo| bar"
EXPECT_TRUE(GetBasicText()->ContainsCaretOffset(4)); // "foo | bar"
EXPECT_TRUE(GetBasicText()->ContainsCaretOffset(5)); // "foo | bar"
EXPECT_TRUE(GetBasicText()->ContainsCaretOffset(6)); // "foo |bar"
EXPECT_TRUE(GetBasicText()->ContainsCaretOffset(7)); // "foo b|ar"
EXPECT_TRUE(GetBasicText()->ContainsCaretOffset(8)); // "foo ba|r"
EXPECT_TRUE(GetBasicText()->ContainsCaretOffset(9)); // "foo bar|"
SetBodyInnerHTML("<pre id='target'>foo\n</div>");
EXPECT_TRUE(GetBasicText()->ContainsCaretOffset(0)); // "|foo\n"
EXPECT_TRUE(GetBasicText()->ContainsCaretOffset(1)); // "f|oo\n"
EXPECT_TRUE(GetBasicText()->ContainsCaretOffset(2)); // "fo|o\n"
EXPECT_TRUE(GetBasicText()->ContainsCaretOffset(3)); // "foo|\n"
EXPECT_FALSE(GetBasicText()->ContainsCaretOffset(4)); // "foo\n|"
SetBodyInnerHTML("<pre id='target'>foo\nbar</pre>");
EXPECT_TRUE(GetBasicText()->ContainsCaretOffset(0)); // "|foo\nbar"
EXPECT_TRUE(GetBasicText()->ContainsCaretOffset(1)); // "f|oo\nbar"
EXPECT_TRUE(GetBasicText()->ContainsCaretOffset(2)); // "fo|o\nbar"
EXPECT_TRUE(GetBasicText()->ContainsCaretOffset(3)); // "foo|\nbar"
EXPECT_TRUE(GetBasicText()->ContainsCaretOffset(4)); // "foo\n|bar"
EXPECT_TRUE(GetBasicText()->ContainsCaretOffset(5)); // "foo\nb|ar"
EXPECT_TRUE(GetBasicText()->ContainsCaretOffset(6)); // "foo\nba|r"
EXPECT_TRUE(GetBasicText()->ContainsCaretOffset(7)); // "foo\nbar|"
}
} // namespace blink } // namespace blink
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