Commit fc70bf9e authored by Kent Tamura's avatar Kent Tamura Committed by Commit Bot

LayoutNG for buttons: Implement baseline handling, and enable the feature as "experimental"

This CL ports LayoutButton::BaselinePosition() to
ng_flex_layout_algorithm.cc.

FlexNG's children don't have the last-line baseline values. So we set
BaselineAlgorithmType in NGFlexLayoutAlgorithm::Layout() so that
children provide the last-line baseline as well as the first-line
baseline. PropagateBaselineFromChild() needs to call |NGBoxFragment::
FirstBaseline()| explicitly because button children's Baseline() is
the last-line baselines.

* text-overflow-ellipsis-button-expected.html
  Ellipsis processing in LayoutNG keeps the first letter.

Bug: 1040826
Change-Id: I36402b4fc291d2989c45fb1764202f4fcea91fda
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2300902
Commit-Queue: Kent Tamura <tkent@chromium.org>
Reviewed-by: default avatarIan Kilpatrick <ikilpatrick@chromium.org>
Cr-Commit-Position: refs/heads/master@{#795798}
parent 803be6f2
...@@ -76,6 +76,8 @@ bool BaseButtonInputType::ShouldSaveAndRestoreFormControlState() const { ...@@ -76,6 +76,8 @@ bool BaseButtonInputType::ShouldSaveAndRestoreFormControlState() const {
void BaseButtonInputType::AppendToFormData(FormData&) const {} void BaseButtonInputType::AppendToFormData(FormData&) const {}
bool BaseButtonInputType::TypeShouldForceLegacyLayout() const { bool BaseButtonInputType::TypeShouldForceLegacyLayout() const {
if (RuntimeEnabledFeatures::LayoutNGForControlsEnabled())
return false;
UseCounter::Count(GetElement().GetDocument(), UseCounter::Count(GetElement().GetDocument(),
WebFeature::kLegacyLayoutByButton); WebFeature::kLegacyLayoutByButton);
return true; return true;
......
...@@ -47,6 +47,8 @@ void HTMLButtonElement::setType(const AtomicString& type) { ...@@ -47,6 +47,8 @@ void HTMLButtonElement::setType(const AtomicString& type) {
} }
bool HTMLButtonElement::TypeShouldForceLegacyLayout() const { bool HTMLButtonElement::TypeShouldForceLegacyLayout() const {
if (RuntimeEnabledFeatures::LayoutNGForControlsEnabled())
return false;
UseCounter::Count(GetDocument(), WebFeature::kLegacyLayoutByButton); UseCounter::Count(GetDocument(), WebFeature::kLegacyLayoutByButton);
return true; return true;
} }
......
...@@ -941,6 +941,15 @@ scoped_refptr<const NGLayoutResult> NGFlexLayoutAlgorithm::LayoutInternal() { ...@@ -941,6 +941,15 @@ scoped_refptr<const NGLayoutResult> NGFlexLayoutAlgorithm::LayoutInternal() {
if (ShouldItemShrinkToFit(flex_item.ng_input_node)) if (ShouldItemShrinkToFit(flex_item.ng_input_node))
space_builder.SetIsShrinkToFit(true); space_builder.SetIsShrinkToFit(true);
// For a button child, we need the baseline type same as the container's
// baseline type for UseCounter. For example, if the container's display
// property is 'inline-block', we need the last-line baseline of the
// child. See the bottom of GiveLinesAndItemsFinalPositionAndSize().
if (Node().IsButton()) {
space_builder.SetBaselineAlgorithmType(
ConstraintSpace().BaselineAlgorithmType());
}
NGConstraintSpace child_space = space_builder.ToConstraintSpace(); NGConstraintSpace child_space = space_builder.ToConstraintSpace();
flex_item.layout_result = flex_item.layout_result =
flex_item.ng_input_node.Layout(child_space, nullptr /*break token*/); flex_item.ng_input_node.Layout(child_space, nullptr /*break token*/);
...@@ -961,8 +970,7 @@ scoped_refptr<const NGLayoutResult> NGFlexLayoutAlgorithm::LayoutInternal() { ...@@ -961,8 +970,7 @@ scoped_refptr<const NGLayoutResult> NGFlexLayoutAlgorithm::LayoutInternal() {
LayoutUnit intrinsic_block_size = BorderScrollbarPadding().BlockSum(); LayoutUnit intrinsic_block_size = BorderScrollbarPadding().BlockSum();
if (algorithm_->FlexLines().IsEmpty() && if (algorithm_->FlexLines().IsEmpty() && Node().HasLineIfEmpty()) {
To<LayoutBlock>(Node().GetLayoutBox())->HasLineIfEmpty()) {
intrinsic_block_size += Node().GetLayoutBox()->LogicalHeightForEmptyLine(); intrinsic_block_size += Node().GetLayoutBox()->LogicalHeightForEmptyLine();
} else { } else {
intrinsic_block_size += algorithm_->IntrinsicContentBlockSize(); intrinsic_block_size += algorithm_->IntrinsicContentBlockSize();
...@@ -1122,10 +1130,54 @@ bool NGFlexLayoutAlgorithm::GiveLinesAndItemsFinalPositionAndSize() { ...@@ -1122,10 +1130,54 @@ bool NGFlexLayoutAlgorithm::GiveLinesAndItemsFinalPositionAndSize() {
if (!container_builder_.Baseline() && fallback_baseline) if (!container_builder_.Baseline() && fallback_baseline)
container_builder_.SetBaseline(*fallback_baseline); container_builder_.SetBaseline(*fallback_baseline);
if (Node().IsButton())
AdjustButtonBaseline(final_content_cross_size);
// Signal if we need to relayout with new child scrollbar information. // Signal if we need to relayout with new child scrollbar information.
return success; return success;
} }
void NGFlexLayoutAlgorithm::AdjustButtonBaseline(
LayoutUnit final_content_cross_size) {
// See LayoutButton::BaselinePosition()
if (!Node().HasLineIfEmpty() && !Node().ShouldApplyLayoutContainment() &&
!container_builder_.Baseline()) {
// To ensure that we have a consistent baseline when we have no children,
// even when we have the anonymous LayoutBlock child, we calculate the
// baseline for the empty case manually here.
container_builder_.SetBaseline(BorderScrollbarPadding().block_start +
final_content_cross_size);
return;
}
// Apply flexbox's baseline as is. That is to say, the baseline of the
// first line.
// However, we count the differences between it and the last-line baseline
// of the anonymous block. crbug.com/690036.
// The button should have at most one child.
const NGContainerFragmentBuilder::ChildrenVector& children =
container_builder_.Children();
if (children.size() < 1)
return;
DCHECK_EQ(children.size(), 1u);
const NGContainerFragmentBuilder::ChildWithOffset& child = children[0];
DCHECK(!child.fragment->IsLineBox());
const NGConstraintSpace& space = ConstraintSpace();
NGBoxFragment fragment(space.GetWritingMode(), space.Direction(),
To<NGPhysicalBoxFragment>(*child.fragment));
base::Optional<LayoutUnit> child_baseline =
space.BaselineAlgorithmType() == NGBaselineAlgorithmType::kFirstLine
? fragment.FirstBaseline()
: fragment.Baseline();
if (child_baseline)
child_baseline = *child_baseline + child.offset.block_offset;
if (container_builder_.Baseline() != child_baseline) {
UseCounter::Count(Node().GetDocument(),
WebFeature::kWrongBaselineOfButtonElement);
}
}
void NGFlexLayoutAlgorithm::PropagateBaselineFromChild( void NGFlexLayoutAlgorithm::PropagateBaselineFromChild(
const FlexItem& flex_item, const FlexItem& flex_item,
const NGBoxFragment& fragment, const NGBoxFragment& fragment,
...@@ -1136,7 +1188,9 @@ void NGFlexLayoutAlgorithm::PropagateBaselineFromChild( ...@@ -1136,7 +1188,9 @@ void NGFlexLayoutAlgorithm::PropagateBaselineFromChild(
return; return;
LayoutUnit baseline_offset = LayoutUnit baseline_offset =
block_offset + fragment.Baseline().value_or(fragment.BlockSize()); block_offset +
(Node().IsButton() ? fragment.FirstBaseline() : fragment.Baseline())
.value_or(fragment.BlockSize());
// We prefer a baseline from a child with baseline alignment, and no // We prefer a baseline from a child with baseline alignment, and no
// auto-margins in the cross axis (even if we have to synthesize the // auto-margins in the cross axis (even if we have to synthesize the
......
...@@ -73,6 +73,8 @@ class CORE_EXPORT NGFlexLayoutAlgorithm ...@@ -73,6 +73,8 @@ class CORE_EXPORT NGFlexLayoutAlgorithm
void HandleOutOfFlowPositioned(NGBlockNode child); void HandleOutOfFlowPositioned(NGBlockNode child);
void AdjustButtonBaseline(LayoutUnit final_content_cross_size);
// Propagates the baseline from the given flex-item if needed. // Propagates the baseline from the given flex-item if needed.
void PropagateBaselineFromChild( void PropagateBaselineFromChild(
const FlexItem&, const FlexItem&,
......
...@@ -161,6 +161,16 @@ class CORE_EXPORT NGBlockNode final : public NGLayoutInputNode { ...@@ -161,6 +161,16 @@ class CORE_EXPORT NGBlockNode final : public NGLayoutInputNode {
static bool CanUseNewLayout(const LayoutBox&); static bool CanUseNewLayout(const LayoutBox&);
bool CanUseNewLayout() const; bool CanUseNewLayout() const;
bool ShouldApplyLayoutContainment() const {
return box_->ShouldApplyLayoutContainment();
}
bool HasLineIfEmpty() const {
if (const auto* block = DynamicTo<LayoutBlock>(box_))
return block->HasLineIfEmpty();
return false;
}
String ToString() const; String ToString() const;
private: private:
......
...@@ -128,6 +128,7 @@ class CORE_EXPORT NGLayoutInputNode { ...@@ -128,6 +128,7 @@ class CORE_EXPORT NGLayoutInputNode {
DCHECK(IsListMarker()); DCHECK(IsListMarker());
return ToLayoutNGOutsideListMarker(box_)->NeedsOccupyWholeLine(); return ToLayoutNGOutsideListMarker(box_)->NeedsOccupyWholeLine();
} }
bool IsButton() const { return IsBlock() && box_->IsLayoutNGButton(); }
bool IsFieldsetContainer() const { bool IsFieldsetContainer() const {
return IsBlock() && box_->IsLayoutNGFieldset(); return IsBlock() && box_->IsLayoutNGFieldset();
} }
......
...@@ -404,6 +404,7 @@ crbug.com/591099 external/wpt/quirks/line-height-trailing-collapsable-whitespace ...@@ -404,6 +404,7 @@ crbug.com/591099 external/wpt/quirks/line-height-trailing-collapsable-whitespace
### fast/css/ ### fast/css/
crbug.com/591099 fast/css/absolute-inline-alignment-2.html [ Failure ] crbug.com/591099 fast/css/absolute-inline-alignment-2.html [ Failure ]
crbug.com/591099 fast/css/text-overflow-ellipsis-button.html [ Failure ]
### fast/writing-mode/ ### fast/writing-mode/
crbug.com/591099 fast/writing-mode/flipped-blocks-inline-map-local-to-container.html [ Failure ] crbug.com/591099 fast/writing-mode/flipped-blocks-inline-map-local-to-container.html [ Failure ]
......
...@@ -1123,6 +1123,7 @@ crbug.com/591099 virtual/layout_ng_block_frag/fast/multicol/dynamic/remove-colum ...@@ -1123,6 +1123,7 @@ crbug.com/591099 virtual/layout_ng_block_frag/fast/multicol/dynamic/remove-colum
crbug.com/591099 virtual/layout_ng_block_frag/fast/multicol/dynamic/static-becomes-relpos-has-abspos.html [ Crash Failure ] crbug.com/591099 virtual/layout_ng_block_frag/fast/multicol/dynamic/static-becomes-relpos-has-abspos.html [ Crash Failure ]
crbug.com/591099 virtual/layout_ng_block_frag/fast/multicol/event-offset-in-nested.html [ Failure ] crbug.com/591099 virtual/layout_ng_block_frag/fast/multicol/event-offset-in-nested.html [ Failure ]
crbug.com/875235 virtual/layout_ng_block_frag/fast/multicol/fieldset-as-multicol.html [ Failure ] crbug.com/875235 virtual/layout_ng_block_frag/fast/multicol/fieldset-as-multicol.html [ Failure ]
crbug.com/829028 virtual/layout_ng_block_frag/fast/multicol/file-upload-as-multicol.html [ Failure ]
crbug.com/591099 virtual/layout_ng_block_frag/fast/multicol/float-after-break-after.html [ Failure ] crbug.com/591099 virtual/layout_ng_block_frag/fast/multicol/float-after-break-after.html [ Failure ]
crbug.com/591099 virtual/layout_ng_block_frag/fast/multicol/float-avoidance.html [ Failure ] crbug.com/591099 virtual/layout_ng_block_frag/fast/multicol/float-avoidance.html [ Failure ]
crbug.com/591099 virtual/layout_ng_block_frag/fast/multicol/float-margin-at-row-boundary.html [ Failure ] crbug.com/591099 virtual/layout_ng_block_frag/fast/multicol/float-margin-at-row-boundary.html [ Failure ]
...@@ -1501,7 +1502,6 @@ crbug.com/1053725 [ Mac ] virtual/web-components-v0-disabled/fast/dom/title-text ...@@ -1501,7 +1502,6 @@ crbug.com/1053725 [ Mac ] virtual/web-components-v0-disabled/fast/dom/title-text
# Needs triage: # Needs triage:
crbug.com/1053725 [ Mac ] fast/css/button-height.html [ Skip ] crbug.com/1053725 [ Mac ] fast/css/button-height.html [ Skip ]
crbug.com/1053725 [ Mac ] fast/css-grid-layout/preferred-width-computed-after-layout.html [ Skip ] crbug.com/1053725 [ Mac ] fast/css-grid-layout/preferred-width-computed-after-layout.html [ Skip ]
crbug.com/1053725 [ Mac ] fast/css/text-overflow-ellipsis-button.html [ Skip ]
crbug.com/1053725 [ Mac ] editing/selection/replaced-boundaries-3.html [ Skip ] crbug.com/1053725 [ Mac ] editing/selection/replaced-boundaries-3.html [ Skip ]
...@@ -4355,6 +4355,7 @@ crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/grid-model/co ...@@ -4355,6 +4355,7 @@ crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/grid-model/co
crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/grid-model/display-grid.html [ Failure ] crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/grid-model/display-grid.html [ Failure ]
crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/grid-model/display-inline-grid.html [ Failure ] crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/grid-model/display-inline-grid.html [ Failure ]
crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/grid-model/grid-box-sizing-001.html [ Failure ] crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/grid-model/grid-box-sizing-001.html [ Failure ]
crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/grid-model/grid-button-001.html [ Failure ]
crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/grid-model/grid-container-ignores-first-letter-001.html [ Failure ] crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/grid-model/grid-container-ignores-first-letter-001.html [ Failure ]
crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/grid-model/grid-container-scrollbar-001.html [ Failure ] crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/grid-model/grid-container-scrollbar-001.html [ Failure ]
crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/grid-model/grid-container-scrollbar-vertical-lr-001.html [ Failure ] crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/grid-model/grid-container-scrollbar-vertical-lr-001.html [ Failure ]
......
...@@ -11,6 +11,6 @@ ...@@ -11,6 +11,6 @@
</style> </style>
</head> </head>
<body> <body>
<button type="button">&#x2026;</button> <button type="button">L&#x2026;</button>
</body> </body>
</html> </html>
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
"backgroundColor": "#FFFFFF" "backgroundColor": "#FFFFFF"
}, },
{ {
"name": "LayoutButton INPUT id='control' class='composited'", "name": "LayoutNGButton INPUT id='control' class='composited'",
"bounds": [127, 22], "bounds": [127, 22],
"backgroundColor": "#EFEFEF", "backgroundColor": "#EFEFEF",
"transform": 1 "transform": 1
......
{
"layers": [
{
"name": "Scrolling Contents Layer",
"bounds": [800, 600],
"contentsOpaque": true,
"backgroundColor": "#FFFFFF"
},
{
"name": "LayoutButton INPUT id='control' class='composited'",
"bounds": [127, 22],
"backgroundColor": "#EFEFEF",
"transform": 1
}
],
"transforms": [
{
"id": 1,
"transform": [
[1, 0, 0, 0],
[0, 1, 0, 0],
[0, 0, 1, 0],
[8, 8, 0, 1]
]
}
]
}
...@@ -92,7 +92,7 @@ button{ ...@@ -92,7 +92,7 @@ button{
"isKeyboardFocusable": true, "isKeyboardFocusable": true,
"accessibleName": "click", "accessibleName": "click",
"accessibleRole": "button", "accessibleRole": "button",
"layoutObjectName": "LayoutButton", "layoutObjectName": "LayoutNGButton",
"showAccessibilityInfo": true "showAccessibilityInfo": true
} }
} }
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
"backgroundColor": "#FFFFFF" "backgroundColor": "#FFFFFF"
}, },
{ {
"name": "LayoutButton INPUT id='control' class='composited'", "name": "LayoutNGButton INPUT id='control' class='composited'",
"bounds": [129, 21], "bounds": [129, 21],
"backgroundColor": "#EFEFEF", "backgroundColor": "#EFEFEF",
"transform": 1 "transform": 1
......
This is a testharness.js-based test.
FAIL abspos button with auto width, non-auto left/right (rtl) assert_equals: offsetLeft expected 663 but got 100
PASS abspos button with auto width, non-auto left/right (ltr)
Harness: the test ran to completion.
...@@ -92,7 +92,7 @@ button{ ...@@ -92,7 +92,7 @@ button{
"isKeyboardFocusable": true, "isKeyboardFocusable": true,
"accessibleName": "click", "accessibleName": "click",
"accessibleRole": "button", "accessibleRole": "button",
"layoutObjectName": "LayoutButton", "layoutObjectName": "LayoutNGButton",
"showAccessibilityInfo": true "showAccessibilityInfo": true
} }
} }
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
"contentsOpaque": true, "contentsOpaque": true,
"backgroundColor": "#FFFFFF", "backgroundColor": "#FFFFFF",
"invalidations": [ "invalidations": [
[75, 113, 66, 16], [75, 114, 66, 15],
[9, 84, 65, 15] [9, 84, 65, 15]
] ]
} }
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
"backgroundColor": "#FFFFFF" "backgroundColor": "#FFFFFF"
}, },
{ {
"name": "LayoutButton INPUT id='control' class='composited'", "name": "LayoutNGButton INPUT id='control' class='composited'",
"bounds": [127, 22], "bounds": [127, 22],
"backgroundColor": "#EFEFEF", "backgroundColor": "#EFEFEF",
"transform": 1 "transform": 1
......
...@@ -92,7 +92,7 @@ button{ ...@@ -92,7 +92,7 @@ button{
"isKeyboardFocusable": true, "isKeyboardFocusable": true,
"accessibleName": "click", "accessibleName": "click",
"accessibleRole": "button", "accessibleRole": "button",
"layoutObjectName": "LayoutButton", "layoutObjectName": "LayoutNGButton",
"showAccessibilityInfo": true "showAccessibilityInfo": true
} }
} }
......
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