Commit dccb421d authored by Yoshifumi Inoue's avatar Yoshifumi Inoue Committed by Commit Bot

Make {Next,Previous}OnLineInlineNG() for AXLayoutObject to utilize NGInlineCursor

This patch makes {Next,Previous}OnLineInlineNG() for AXLayoutObject to utilize
|NGInlineCursor| for preparation of migrating to |NGFragmentItem|.

This patch also introduces |NGInlineCursor::CurrentMutableLayoutObject()| to
reduce using |const_cast<LayoutObject*>()|.


Bug: 982194
Change-Id: I36d5d76b266968824ecd029851737e45c740f839
Tbr: dmazzoni@chromium.org
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1930243
Commit-Queue: Yoshifumi Inoue <yosin@chromium.org>
Reviewed-by: default avatarKoji Ishii <kojii@chromium.org>
Auto-Submit: Yoshifumi Inoue <yosin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#719879}
parent 0233452d
......@@ -95,6 +95,9 @@ class CORE_EXPORT NGFragmentItem : public DisplayItemClient {
return layout_object_->EffectiveStyle(StyleVariant());
}
const LayoutObject* GetLayoutObject() const { return layout_object_; }
LayoutObject* GetMutableLayoutObject() const {
return const_cast<LayoutObject*>(layout_object_);
}
Node* GetNode() const { return layout_object_->GetNode(); }
bool HasSameParent(const NGFragmentItem& other) const;
......
......@@ -447,6 +447,15 @@ const LayoutObject* NGInlineCursor::CurrentLayoutObject() const {
return nullptr;
}
LayoutObject* NGInlineCursor::CurrentMutableLayoutObject() const {
if (current_paint_fragment_)
return current_paint_fragment_->GetMutableLayoutObject();
if (current_item_)
return current_item_->GetMutableLayoutObject();
NOTREACHED();
return nullptr;
}
Node* NGInlineCursor::CurrentNode() const {
if (const LayoutObject* layout_object = CurrentLayoutObject())
return layout_object->GetNode();
......@@ -752,6 +761,15 @@ void NGInlineCursor::MoveToLastChild() {
MakeNull();
}
void NGInlineCursor::MoveToLastForSameLayoutObject() {
NGInlineCursor last;
while (IsNotNull()) {
last = *this;
MoveToNextForSameLayoutObject();
}
*this = last;
}
void NGInlineCursor::MoveToLastLogicalLeaf() {
DCHECK(IsLineBox());
// TODO(yosin): This isn't correct for mixed Bidi. Fix it. Besides, we
......@@ -814,6 +832,21 @@ void NGInlineCursor::MoveToNextInlineLeafIgnoringLineBreak() {
} while (IsNotNull() && IsLineBreak());
}
void NGInlineCursor::MoveToNextInlineLeafOnLine() {
MoveToLastForSameLayoutObject();
if (IsNull())
return;
NGInlineCursor last_item = *this;
MoveToContainingLine();
NGInlineCursor cursor = CursorForDescendants();
cursor.MoveTo(last_item);
// Note: AX requires this for AccessibilityLayoutTest.NextOnLine.
if (!cursor.IsInlineLeaf())
cursor.MoveToNextInlineLeaf();
cursor.MoveToNextInlineLeaf();
MoveTo(cursor);
}
void NGInlineCursor::MoveToNextLine() {
DCHECK(IsLineBox());
if (current_paint_fragment_) {
......@@ -861,6 +894,20 @@ void NGInlineCursor::MoveToPreviousInlineLeafIgnoringLineBreak() {
} while (IsNotNull() && IsLineBreak());
}
void NGInlineCursor::MoveToPreviousInlineLeafOnLine() {
if (IsNull())
return;
NGInlineCursor first_item = *this;
MoveToContainingLine();
NGInlineCursor cursor = CursorForDescendants();
cursor.MoveTo(first_item);
// Note: AX requires this for AccessibilityLayoutTest.NextOnLine.
if (!cursor.IsInlineLeaf())
cursor.MoveToPreviousInlineLeaf();
cursor.MoveToPreviousInlineLeaf();
MoveTo(cursor);
}
void NGInlineCursor::MoveToPreviousLine() {
// Note: List marker is sibling of line box.
DCHECK(IsLineBox());
......
......@@ -165,6 +165,7 @@ class CORE_EXPORT NGInlineCursor {
const NGPhysicalBoxFragment* CurrentBoxFragment() const;
const DisplayItemClient* CurrentDisplayItemClient() const;
const LayoutObject* CurrentLayoutObject() const;
LayoutObject* CurrentMutableLayoutObject() const;
Node* CurrentNode() const;
// Returns bidi level of current position. It is error to call other than
......@@ -279,6 +280,14 @@ class CORE_EXPORT NGInlineCursor {
void MoveToPreviousInlineLeaf();
void MoveToPreviousInlineLeafIgnoringLineBreak();
// Move the current position to next/previous inline leaf item on line.
// Note: If the current position isn't leaf item, this function moves the
// current position to leaf item then moves to next/previous leaf item. This
// behavior doesn't match |MoveTo{Next,Previous}InlineLeaf()|, but AX requires
// this. See AccessibilityLayoutTest.NextOnLine
void MoveToNextInlineLeafOnLine();
void MoveToPreviousInlineLeafOnLine();
// Move the cursor position to previous fragment in pre-order DFS.
void MoveToPrevious();
......@@ -317,6 +326,9 @@ class CORE_EXPORT NGInlineCursor {
// Move the cursor position to the first fragment in tree.
void MoveToFirst();
// Move the current position to the last fragment on same layout object.
void MoveToLastForSameLayoutObject();
// Same as |MoveTo()| but not support culled inline.
void InternalMoveTo(const LayoutObject& layout_object);
......
......@@ -454,6 +454,43 @@ TEST_P(NGInlineCursorTest, NextInlineLeaf) {
EXPECT_THAT(list, ElementsAre("#linebox", "abc", "DEF", "", "xyz"));
}
// Note: This is for AccessibilityLayoutTest.NextOnLine.
TEST_P(NGInlineCursorTest, NextInlineLeafOnLineFromLayoutInline) {
// TDOO(yosin): Remove <style> once NGFragmentItem don't do culled inline.
InsertStyleElement("b { background: gray; }");
NGInlineCursor cursor = SetupCursor(
"<div id=root>"
"<b id=start>abc</b> def<br>"
"<b>ABC</b> DEF<br>"
"</div>");
cursor.MoveTo(*GetElementById("start")->GetLayoutObject());
Vector<String> list;
while (cursor) {
list.push_back(ToDebugString(cursor));
cursor.MoveToNextInlineLeafOnLine();
}
EXPECT_THAT(list, ElementsAre("#start", "def", ""))
<< "we don't have 'abc' and items in second line.";
}
TEST_P(NGInlineCursorTest, NextInlineLeafOnLineFromLayoutText) {
// TDOO(yosin): Remove <style> once NGFragmentItem don't do culled inline.
InsertStyleElement("b { background: gray; }");
NGInlineCursor cursor = SetupCursor(
"<div id=root>"
"<b id=start>abc</b> def<br>"
"<b>ABC</b> DEF<br>"
"</div>");
cursor.MoveTo(*GetElementById("start")->firstChild()->GetLayoutObject());
Vector<String> list;
while (cursor) {
list.push_back(ToDebugString(cursor));
cursor.MoveToNextInlineLeafOnLine();
}
EXPECT_THAT(list, ElementsAre("abc", "def", ""))
<< "We don't have items from second line.";
}
TEST_P(NGInlineCursorTest, NextInlineLeafWithEllipsis) {
LoadAhem();
InsertStyleElement(
......@@ -658,6 +695,42 @@ TEST_P(NGInlineCursorTest, PreviousInlineLeafIgnoringLineBreak) {
EXPECT_THAT(list, ElementsAre("xyz", "DEF", "abc"));
}
TEST_P(NGInlineCursorTest, PreviousInlineLeafOnLineFromLayoutInline) {
// TDOO(yosin): Remove <style> once NGFragmentItem don't do culled inline.
InsertStyleElement("b { background: gray; }");
NGInlineCursor cursor = SetupCursor(
"<div id=root>"
"<b>abc</b> def<br>"
"<b>ABC</b> <b id=start>DEF</b><br>"
"</div>");
cursor.MoveTo(*GetElementById("start")->GetLayoutObject());
Vector<String> list;
while (cursor) {
list.push_back(ToDebugString(cursor));
cursor.MoveToPreviousInlineLeafOnLine();
}
EXPECT_THAT(list, ElementsAre("#start", "ABC"))
<< "We don't have 'DEF' and items in first line.";
}
TEST_P(NGInlineCursorTest, PreviousInlineLeafOnLineFromLayoutText) {
// TDOO(yosin): Remove <style> once NGFragmentItem don't do culled inline.
InsertStyleElement("b { background: gray; }");
NGInlineCursor cursor = SetupCursor(
"<div id=root>"
"<b>abc</b> def<br>"
"<b>ABC</b> <b id=start>DEF</b><br>"
"</div>");
cursor.MoveTo(*GetElementById("start")->firstChild()->GetLayoutObject());
Vector<String> list;
while (cursor) {
list.push_back(ToDebugString(cursor));
cursor.MoveToPreviousInlineLeafOnLine();
}
EXPECT_THAT(list, ElementsAre("DEF", "", "ABC"))
<< "We don't have items in first line.";
}
TEST_P(NGInlineCursorTest, PreviousLine) {
NGInlineCursor cursor = SetupCursor("<div id=root>abc<br>xyz</div>");
NGInlineCursor line1(cursor);
......
......@@ -76,13 +76,12 @@
#include "third_party/blink/renderer/core/layout/layout_text_control.h"
#include "third_party/blink/renderer/core/layout/layout_text_fragment.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.h"
#include "third_party/blink/renderer/core/layout/ng/list/layout_ng_list_item.h"
#include "third_party/blink/renderer/core/layout/ng/list/layout_ng_list_marker.h"
#include "third_party/blink/renderer/core/loader/progress_tracker.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h"
#include "third_party/blink/renderer/core/paint/ng/ng_paint_fragment_traversal.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
#include "third_party/blink/renderer/core/style/computed_style_constants.h"
......@@ -1265,17 +1264,18 @@ static AXObject* NextOnLineInternalNG(const AXObject& ax_object) {
DCHECK(!ax_object.IsDetached());
const LayoutObject& layout_object = *ax_object.GetLayoutObject();
DCHECK(ShouldUseLayoutNG(layout_object)) << layout_object;
if (layout_object.IsListMarkerIncludingNG())
if (layout_object.IsListMarkerIncludingNG() ||
!layout_object.IsInLayoutNGInlineFormattingContext())
return nullptr;
const auto fragments = NGPaintFragment::InlineFragmentsFor(&layout_object);
if (fragments.IsEmpty() || !fragments.IsInLayoutNGInlineFormattingContext())
NGInlineCursor cursor;
cursor.MoveTo(layout_object);
if (!cursor)
return nullptr;
NGPaintFragmentTraversal runner(*fragments.back().ContainerLineBox(),
fragments.back());
for (runner.MoveToNextInlineLeaf(); !runner.IsAtEnd();
runner.MoveToNextInlineLeaf()) {
LayoutObject* runner_layout_object = runner->GetMutableLayoutObject();
for (;;) {
cursor.MoveToNextInlineLeafOnLine();
if (!cursor)
break;
LayoutObject* runner_layout_object = cursor.CurrentMutableLayoutObject();
if (AXObject* result =
ax_object.AXObjectCache().GetOrCreate(runner_layout_object))
return result;
......@@ -1345,17 +1345,18 @@ static AXObject* PreviousOnLineInlineNG(const AXObject& ax_object) {
DCHECK(!ax_object.IsDetached());
const LayoutObject& layout_object = *ax_object.GetLayoutObject();
DCHECK(ShouldUseLayoutNG(layout_object)) << layout_object;
if (layout_object.IsListMarkerIncludingNG())
if (layout_object.IsListMarkerIncludingNG() ||
!layout_object.IsInLayoutNGInlineFormattingContext())
return nullptr;
const auto fragments = NGPaintFragment::InlineFragmentsFor(&layout_object);
if (fragments.IsEmpty() || !fragments.IsInLayoutNGInlineFormattingContext())
NGInlineCursor cursor;
cursor.MoveTo(layout_object);
if (!cursor)
return nullptr;
NGPaintFragmentTraversal runner(*fragments.front().ContainerLineBox(),
fragments.front());
for (runner.MoveToPreviousInlineLeaf(); !runner.IsAtEnd();
runner.MoveToPreviousInlineLeaf()) {
LayoutObject* earlier_layout_object = runner->GetMutableLayoutObject();
for (;;) {
cursor.MoveToPreviousInlineLeafOnLine();
if (!cursor)
break;
LayoutObject* earlier_layout_object = cursor.CurrentMutableLayoutObject();
if (AXObject* result =
ax_object.AXObjectCache().GetOrCreate(earlier_layout_object))
return result;
......
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