Commit 1dac1463 authored by Yoshifumi Inoue's avatar Yoshifumi Inoue Committed by Commit Bot

[EditingNG] Introduce NGInluneCursor::PositionForPointInChild()

This patch introuces |NGInluneCursor::PositionForPointInChild()| as replacement
of existing verion with following differences:
 - It takes only one parameter |point_in_container|, because |child_item| is
   reduntant and as same as current cursor position.
 - It works both |NGPaintFragment| and |NGFragmentItem|.
for preparation of the CL[1].

[1] http://crrev.com/2249278 [EditingNG] Make SelectionModifier::
{Next,Previous}LinePosition() to move editable to editalbe correctly

Bug: 707656
Change-Id: If5605edd02bec664c331cecebc70c4723094ab56
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2247943
Commit-Queue: Yoshifumi Inoue <yosin@chromium.org>
Auto-Submit: Yoshifumi Inoue <yosin@chromium.org>
Reviewed-by: default avatarKent Tamura <tkent@chromium.org>
Reviewed-by: default avatarKoji Ishii <kojii@chromium.org>
Cr-Commit-Position: refs/heads/master@{#779185}
parent 53ab73c1
......@@ -860,14 +860,14 @@ PositionWithAffinity NGInlineCursor::PositionForPointInInlineBox(
}
if (const PositionWithAffinity child_position =
descendants.PositionForPointInChild(point, *child_item))
descendants.PositionForPointInChild(point))
return child_position;
}
if (closest_child_after) {
descendants.MoveTo(closest_child_after);
if (const PositionWithAffinity child_position =
descendants.PositionForPointInChild(point, *closest_child_after))
descendants.PositionForPointInChild(point))
return child_position;
// TODO(yosin): we should do like "closest_child_before" once we have a
// case.
......@@ -876,7 +876,7 @@ PositionWithAffinity NGInlineCursor::PositionForPointInInlineBox(
if (closest_child_before) {
descendants.MoveTo(closest_child_before);
if (const PositionWithAffinity child_position =
descendants.PositionForPointInChild(point, *closest_child_before))
descendants.PositionForPointInChild(point))
return child_position;
if (closest_child_before->BoxFragment()) {
// LayoutViewHitTest.HitTestHorizontal "Top-right corner (outside) of div"
......@@ -908,13 +908,18 @@ PositionWithAffinity NGInlineCursor::PositionForPointInInlineBox(
}
PositionWithAffinity NGInlineCursor::PositionForPointInChild(
const PhysicalOffset& point,
const NGFragmentItem& child_item) const {
DCHECK_EQ(&child_item, CurrentItem());
const PhysicalOffset& point_in_container) const {
if (auto* paint_fragment = CurrentPaintFragment()) {
const PhysicalOffset point_in_child =
point_in_container - paint_fragment->OffsetInContainerBlock();
return paint_fragment->PositionForPoint(point_in_child);
}
DCHECK(CurrentItem());
const NGFragmentItem& child_item = *CurrentItem();
switch (child_item.Type()) {
case NGFragmentItem::kText:
return child_item.PositionForPointInText(
point - child_item.OffsetInContainerBlock(), *this);
point_in_container - child_item.OffsetInContainerBlock(), *this);
case NGFragmentItem::kGeneratedText:
break;
case NGFragmentItem::kBox:
......@@ -927,7 +932,7 @@ PositionWithAffinity NGInlineCursor::PositionForPointInChild(
// TODO(xiaochengh): Don't fallback to legacy for NG block layout.
if (!box_fragment->IsInlineBox()) {
return child_item.GetLayoutObject()->PositionForPoint(
point - child_item.OffsetInContainerBlock());
point_in_container - child_item.OffsetInContainerBlock());
}
} else {
// |LayoutInline| used to be culled.
......
......@@ -315,6 +315,16 @@ class CORE_EXPORT NGInlineCursor {
PositionWithAffinity PositionForPointInInlineBox(
const PhysicalOffset& point) const;
// Returns |PositionWithAffinity| in current position at x-coordinate of
// |point_in_container| for horizontal writing mode, or y-coordinate of
// |point_in_container| for vertical writing mode.
// Note: Even if |point_in_container| is outside of an item of current
// position, this function returns boundary position of an item.
// Note: This function is used for locating caret at same x/y-coordinate as
// previous caret after line up/down.
PositionWithAffinity PositionForPointInChild(
const PhysicalOffset& point_in_container) const;
// Returns first/last position of |this| line. |this| should be line box.
PositionWithAffinity PositionForStartOfLine() const;
PositionWithAffinity PositionForEndOfLine() const;
......@@ -460,10 +470,6 @@ class CORE_EXPORT NGInlineCursor {
wtf_size_t SpanBeginItemIndex() const;
wtf_size_t SpanIndexFromItemIndex(unsigned index) const;
PositionWithAffinity PositionForPointInChild(
const PhysicalOffset& point,
const NGFragmentItem& child_item) const;
NGInlineCursorPosition current_;
ItemsSpan items_;
......
......@@ -698,6 +698,152 @@ TEST_P(NGInlineCursorTest, EmptyOutOfFlow) {
EXPECT_THAT(list, ElementsAre());
}
TEST_P(NGInlineCursorTest, PositionForPointInChildHorizontalLTR) {
LoadAhem();
InsertStyleElement(
"p {"
"direction: ltr;"
"font: 10px/20px Ahem;"
"padding: 10px;"
"writing-mode: horizontal-tb;"
"}");
NGInlineCursor cursor = SetupCursor("<p id=root>ab</p>");
const auto& text = *To<Text>(GetElementById("root")->firstChild());
ASSERT_TRUE(cursor.Current().IsLineBox());
EXPECT_EQ(PhysicalRect(PhysicalOffset(10, 10), PhysicalSize(20, 20)),
cursor.Current().RectInContainerBlock());
cursor.MoveTo(*text.GetLayoutObject());
EXPECT_EQ(PhysicalRect(PhysicalOffset(10, 15), PhysicalSize(20, 10)),
cursor.Current().RectInContainerBlock());
const PhysicalOffset left_top = cursor.Current().OffsetInContainerBlock();
EXPECT_EQ(PositionWithAffinity(Position(text, 0)),
cursor.PositionForPointInChild(left_top + PhysicalOffset(-5, 0)));
EXPECT_EQ(PositionWithAffinity(Position(text, 0)),
cursor.PositionForPointInChild(left_top));
EXPECT_EQ(PositionWithAffinity(Position(text, 0)),
cursor.PositionForPointInChild(left_top + PhysicalOffset(5, 0)));
EXPECT_EQ(PositionWithAffinity(Position(text, 1)),
cursor.PositionForPointInChild(left_top + PhysicalOffset(10, 0)));
EXPECT_EQ(PositionWithAffinity(Position(text, 1)),
cursor.PositionForPointInChild(left_top + PhysicalOffset(15, 0)));
EXPECT_EQ(PositionWithAffinity(Position(text, 2), TextAffinity::kUpstream),
cursor.PositionForPointInChild(left_top + PhysicalOffset(20, 0)));
EXPECT_EQ(PositionWithAffinity(Position(text, 2), TextAffinity::kUpstream),
cursor.PositionForPointInChild(left_top + PhysicalOffset(25, 0)));
}
TEST_P(NGInlineCursorTest, PositionForPointInChildHorizontalRTL) {
LoadAhem();
InsertStyleElement(
"p {"
"direction: rtl;"
"font: 10px/20px Ahem;"
"padding: 10px;"
"writing-mode: horizontal-tb;"
"}");
NGInlineCursor cursor = SetupCursor("<p id=root><bdo dir=rtl>AB</bdo></p>");
const auto& text =
*To<Text>(GetElementById("root")->firstChild()->firstChild());
ASSERT_TRUE(cursor.Current().IsLineBox());
EXPECT_EQ(PhysicalRect(PhysicalOffset(754, 10), PhysicalSize(20, 20)),
cursor.Current().RectInContainerBlock());
cursor.MoveTo(*text.GetLayoutObject());
EXPECT_EQ(PhysicalRect(PhysicalOffset(754, 15), PhysicalSize(20, 10)),
cursor.Current().RectInContainerBlock());
const PhysicalOffset left_top = cursor.Current().OffsetInContainerBlock();
EXPECT_EQ(PositionWithAffinity(Position(text, 2), TextAffinity::kUpstream),
cursor.PositionForPointInChild(left_top + PhysicalOffset(-5, 0)));
EXPECT_EQ(PositionWithAffinity(Position(text, 2), TextAffinity::kUpstream),
cursor.PositionForPointInChild(left_top));
EXPECT_EQ(PositionWithAffinity(Position(text, 2), TextAffinity::kUpstream),
cursor.PositionForPointInChild(left_top + PhysicalOffset(5, 0)));
EXPECT_EQ(PositionWithAffinity(Position(text, 1)),
cursor.PositionForPointInChild(left_top + PhysicalOffset(10, 0)));
EXPECT_EQ(PositionWithAffinity(Position(text, 1)),
cursor.PositionForPointInChild(left_top + PhysicalOffset(15, 0)));
EXPECT_EQ(PositionWithAffinity(Position(text, 0)),
cursor.PositionForPointInChild(left_top + PhysicalOffset(20, 0)));
EXPECT_EQ(PositionWithAffinity(Position(text, 0)),
cursor.PositionForPointInChild(left_top + PhysicalOffset(25, 0)));
}
TEST_P(NGInlineCursorTest, PositionForPointInChildVerticalLTR) {
LoadAhem();
InsertStyleElement(
"p {"
"direction: ltr;"
"font: 10px/20px Ahem;"
"padding: 10px;"
"writing-mode: vertical-lr;"
"}");
NGInlineCursor cursor = SetupCursor("<p id=root>ab</p>");
const auto& text = *To<Text>(GetElementById("root")->firstChild());
ASSERT_TRUE(cursor.Current().IsLineBox());
EXPECT_EQ(PhysicalRect(PhysicalOffset(10, 10), PhysicalSize(20, 20)),
cursor.Current().RectInContainerBlock());
cursor.MoveTo(*text.GetLayoutObject());
EXPECT_EQ(PhysicalRect(PhysicalOffset(15, 10), PhysicalSize(10, 20)),
cursor.Current().RectInContainerBlock());
const PhysicalOffset left_top = cursor.Current().OffsetInContainerBlock();
EXPECT_EQ(PositionWithAffinity(Position(text, 0)),
cursor.PositionForPointInChild(left_top + PhysicalOffset(0, -5)));
EXPECT_EQ(PositionWithAffinity(Position(text, 0)),
cursor.PositionForPointInChild(left_top));
EXPECT_EQ(PositionWithAffinity(Position(text, 0)),
cursor.PositionForPointInChild(left_top + PhysicalOffset(0, 5)));
EXPECT_EQ(PositionWithAffinity(Position(text, 1)),
cursor.PositionForPointInChild(left_top + PhysicalOffset(0, 10)));
EXPECT_EQ(PositionWithAffinity(Position(text, 1)),
cursor.PositionForPointInChild(left_top + PhysicalOffset(0, 15)));
EXPECT_EQ(PositionWithAffinity(Position(text, 2), TextAffinity::kUpstream),
cursor.PositionForPointInChild(left_top + PhysicalOffset(0, 20)));
EXPECT_EQ(PositionWithAffinity(Position(text, 2), TextAffinity::kUpstream),
cursor.PositionForPointInChild(left_top + PhysicalOffset(0, 25)));
}
TEST_P(NGInlineCursorTest, PositionForPointInChildVerticalRTL) {
LoadAhem();
InsertStyleElement(
"p {"
"direction: rtl;"
"font: 10px/20px Ahem;"
"padding: 10px;"
"writing-mode: vertical-rl;"
"}");
NGInlineCursor cursor = SetupCursor("<p id=root><bdo dir=rtl>AB</bdo></p>");
const auto& text =
*To<Text>(GetElementById("root")->firstChild()->firstChild());
ASSERT_TRUE(cursor.Current().IsLineBox());
EXPECT_EQ(PhysicalRect(PhysicalOffset(10, 10), PhysicalSize(20, 20)),
cursor.Current().RectInContainerBlock());
cursor.MoveTo(*text.GetLayoutObject());
EXPECT_EQ(PhysicalRect(PhysicalOffset(15, 10), PhysicalSize(10, 20)),
cursor.Current().RectInContainerBlock());
const PhysicalOffset left_top = cursor.Current().OffsetInContainerBlock();
EXPECT_EQ(PositionWithAffinity(Position(text, 2), TextAffinity::kUpstream),
cursor.PositionForPointInChild(left_top + PhysicalOffset(0, -5)));
EXPECT_EQ(PositionWithAffinity(Position(text, 2), TextAffinity::kUpstream),
cursor.PositionForPointInChild(left_top));
EXPECT_EQ(PositionWithAffinity(Position(text, 2), TextAffinity::kUpstream),
cursor.PositionForPointInChild(left_top + PhysicalOffset(0, 5)));
EXPECT_EQ(PositionWithAffinity(Position(text, 1)),
cursor.PositionForPointInChild(left_top + PhysicalOffset(0, 10)));
EXPECT_EQ(PositionWithAffinity(Position(text, 1)),
cursor.PositionForPointInChild(left_top + PhysicalOffset(0, 15)));
EXPECT_EQ(PositionWithAffinity(Position(text, 0)),
cursor.PositionForPointInChild(left_top + PhysicalOffset(0, 20)));
EXPECT_EQ(PositionWithAffinity(Position(text, 0)),
cursor.PositionForPointInChild(left_top + PhysicalOffset(0, 25)));
}
TEST_P(NGInlineCursorTest, Previous) {
// TDOO(yosin): Remove <style> once NGFragmentItem don't do culled inline.
InsertStyleElement("b { background: gray; }");
......
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