Commit c78c300c authored by Ana SollanoKim's avatar Ana SollanoKim Committed by Commit Bot

[LayoutNG] Make fieldset legends monolithic

Previously, we had made the legends fragment in the following change
https://chromium-review.googlesource.com/c/chromium/src/+/2090762. In
this other change
https://chromium-review.googlesource.com/c/chromium/src/+/2263353
we decided to not break borders for now. Because the legend is part of
the fieldset border, we now want to treat the legend as monolithic.

We still have logic for breaking the fieldset border, this will be
addressed in a follow up change.

Bug: 1097012
Change-Id: Iace252447063eb694c47fb9eea2a406ba2fe79d7
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2353354
Commit-Queue: Ana Sollano Kim <ansollan@microsoft.com>
Reviewed-by: default avatarAlison Maher <almaher@microsoft.com>
Reviewed-by: default avatarMorten Stenshorne <mstensho@chromium.org>
Cr-Commit-Position: refs/heads/master@{#798528}
parent 1bf739db
...@@ -146,24 +146,19 @@ scoped_refptr<const NGLayoutResult> NGFieldsetLayoutAlgorithm::Layout() { ...@@ -146,24 +146,19 @@ scoped_refptr<const NGLayoutResult> NGFieldsetLayoutAlgorithm::Layout() {
} }
NGBreakStatus NGFieldsetLayoutAlgorithm::LayoutChildren() { NGBreakStatus NGFieldsetLayoutAlgorithm::LayoutChildren() {
scoped_refptr<const NGBlockBreakToken> legend_break_token;
scoped_refptr<const NGBlockBreakToken> content_break_token; scoped_refptr<const NGBlockBreakToken> content_break_token;
bool has_seen_all_children = false; bool has_seen_all_children = false;
if (const auto* token = BreakToken()) { if (const auto* token = BreakToken()) {
const auto child_tokens = token->ChildBreakTokens(); const auto child_tokens = token->ChildBreakTokens();
if (wtf_size_t break_token_count = child_tokens.size()) { if (wtf_size_t break_token_count = child_tokens.size()) {
DCHECK_LE(break_token_count, 2u);
for (wtf_size_t break_token_idx = 0; break_token_idx < break_token_count;
break_token_idx++) {
scoped_refptr<const NGBlockBreakToken> child_token = scoped_refptr<const NGBlockBreakToken> child_token =
To<NGBlockBreakToken>(child_tokens[break_token_idx]); To<NGBlockBreakToken>(child_tokens[0]);
if (child_token && child_token->InputNode().IsRenderedLegend()) { if (child_token) {
DCHECK_EQ(break_token_idx, 0u); DCHECK(!child_token->InputNode().IsRenderedLegend());
legend_break_token = child_token;
} else {
content_break_token = child_token; content_break_token = child_token;
} }
} // There shouldn't be any additional break tokens.
DCHECK_EQ(child_tokens.size(), 1u);
} }
if (token->HasSeenAllChildren()) { if (token->HasSeenAllChildren()) {
container_builder_.SetHasSeenAllChildren(); container_builder_.SetHasSeenAllChildren();
...@@ -172,14 +167,8 @@ NGBreakStatus NGFieldsetLayoutAlgorithm::LayoutChildren() { ...@@ -172,14 +167,8 @@ NGBreakStatus NGFieldsetLayoutAlgorithm::LayoutChildren() {
} }
NGBlockNode legend = Node().GetRenderedLegend(); NGBlockNode legend = Node().GetRenderedLegend();
bool legend_needs_layout = if (legend && !IsResumingLayout(BreakToken())) {
legend && (legend_break_token || !IsResumingLayout(BreakToken())); LayoutLegend(legend);
if (legend_needs_layout) {
NGBreakStatus break_status = LayoutLegend(legend, legend_break_token);
if (break_status != NGBreakStatus::kContinue)
return break_status;
// The legend may eat from the available content box block size. Calculate // The legend may eat from the available content box block size. Calculate
// the minimum block size needed to encompass the legend. // the minimum block size needed to encompass the legend.
if (!Node().ShouldApplySizeContainment()) { if (!Node().ShouldApplySizeContainment()) {
...@@ -231,11 +220,6 @@ NGBreakStatus NGFieldsetLayoutAlgorithm::LayoutChildren() { ...@@ -231,11 +220,6 @@ NGBreakStatus NGFieldsetLayoutAlgorithm::LayoutChildren() {
// all live inside an anonymous child box of the fieldset container. // all live inside an anonymous child box of the fieldset container.
auto fieldset_content = Node().GetFieldsetContent(); auto fieldset_content = Node().GetFieldsetContent();
if (fieldset_content && (content_break_token || !has_seen_all_children)) { if (fieldset_content && (content_break_token || !has_seen_all_children)) {
if (ConstraintSpace().HasBlockFragmentation() && legend_broke_ &&
IsFragmentainerOutOfSpace(ConstraintSpace().FragmentainerOffsetAtBfc() +
intrinsic_block_size_))
return NGBreakStatus::kContinue;
NGBreakStatus break_status = NGBreakStatus break_status =
LayoutFieldsetContent(fieldset_content, content_break_token, LayoutFieldsetContent(fieldset_content, content_break_token,
adjusted_padding_box_size, !!legend); adjusted_padding_box_size, !!legend);
...@@ -253,9 +237,7 @@ NGBreakStatus NGFieldsetLayoutAlgorithm::LayoutChildren() { ...@@ -253,9 +237,7 @@ NGBreakStatus NGFieldsetLayoutAlgorithm::LayoutChildren() {
return NGBreakStatus::kContinue; return NGBreakStatus::kContinue;
} }
NGBreakStatus NGFieldsetLayoutAlgorithm::LayoutLegend( void NGFieldsetLayoutAlgorithm::LayoutLegend(NGBlockNode& legend) {
NGBlockNode& legend,
scoped_refptr<const NGBlockBreakToken> legend_break_token) {
// Lay out the legend. While the fieldset container normally ignores its // Lay out the legend. While the fieldset container normally ignores its
// padding, the legend is laid out within what would have been the content // padding, the legend is laid out within what would have been the content
// box had the fieldset been a regular block with no weirdness. // box had the fieldset been a regular block with no weirdness.
...@@ -265,101 +247,47 @@ NGBreakStatus NGFieldsetLayoutAlgorithm::LayoutLegend( ...@@ -265,101 +247,47 @@ NGBreakStatus NGFieldsetLayoutAlgorithm::LayoutLegend(
legend.Style(), percentage_size.inline_size, legend.Style(), percentage_size.inline_size,
ConstraintSpace().GetWritingMode(), ConstraintSpace().Direction()); ConstraintSpace().GetWritingMode(), ConstraintSpace().Direction());
if (legend_break_token)
legend_margins.block_start = LayoutUnit();
scoped_refptr<const NGLayoutResult> result;
scoped_refptr<const NGLayoutResult> previous_result;
LayoutUnit block_offset; LayoutUnit block_offset;
do {
auto legend_space = CreateConstraintSpaceForLegend( auto legend_space = CreateConstraintSpaceForLegend(
legend, ChildAvailableSize(), percentage_size, block_offset); legend, ChildAvailableSize(), percentage_size);
result = legend.Layout(legend_space, legend_break_token.get()); scoped_refptr<const NGLayoutResult> result =
legend.Layout(legend_space, BreakToken());
// TODO(layout-dev): Handle abortions caused by block fragmentation. // TODO(layout-dev): Handle abortions caused by block fragmentation.
DCHECK_EQ(result->Status(), NGLayoutResult::kSuccess); DCHECK_EQ(result->Status(), NGLayoutResult::kSuccess);
if (ConstraintSpace().HasBlockFragmentation()) {
NGBreakStatus break_status = BreakBeforeChildIfNeeded(
ConstraintSpace(), legend, *result.get(),
ConstraintSpace().FragmentainerOffsetAtBfc() + block_offset,
/*has_container_separation*/ false, &container_builder_);
if (break_status != NGBreakStatus::kContinue)
return break_status;
EBreakBetween break_after = JoinFragmentainerBreakValues(
result->FinalBreakAfter(), legend.Style().BreakAfter());
container_builder_.SetPreviousBreakAfter(break_after);
}
const auto& physical_fragment = result->PhysicalFragment(); const auto& physical_fragment = result->PhysicalFragment();
legend_broke_ = physical_fragment.BreakToken();
// We have already adjusted the legend block offset, no need to adjust
// again.
if (block_offset != LayoutUnit()) {
// If adjusting the block_offset caused the legend to break, revert back
// to the previous result.
if (legend_broke_) {
result = std::move(previous_result);
block_offset = LayoutUnit();
}
break;
}
LayoutUnit legend_border_box_block_size = LayoutUnit legend_border_box_block_size =
NGFragment(writing_mode_, physical_fragment).BlockSize(); NGFragment(writing_mode_, physical_fragment).BlockSize();
LayoutUnit legend_margin_box_block_size = LayoutUnit legend_margin_box_block_size = legend_margins.block_start +
legend_margins.block_start + legend_border_box_block_size; legend_border_box_block_size +
legend_margins.block_end;
LayoutUnit block_end_margin = legend_margins.block_end;
if (ConstraintSpace().HasKnownFragmentainerBlockSize()) {
block_end_margin = AdjustedMarginAfterFinalChildFragment(
ConstraintSpace(), legend_margin_box_block_size, block_end_margin);
}
legend_margin_box_block_size += block_end_margin;
LayoutUnit space_left = borders_.block_start - legend_border_box_block_size; LayoutUnit space_left = borders_.block_start - legend_border_box_block_size;
if (space_left > LayoutUnit()) { if (space_left > LayoutUnit()) {
// Don't adjust the block-start offset of the legend if the legend broke.
if (legend_break_token || legend_broke_)
break;
// https://html.spec.whatwg.org/C/#the-fieldset-and-legend-elements // https://html.spec.whatwg.org/C/#the-fieldset-and-legend-elements
// * The element is expected to be positioned in the block-flow direction // * The element is expected to be positioned in the block-flow direction
// such that its border box is centered over the border on the // such that its border box is centered over the border on the
// block-start side of the fieldset element. // block-start side of the fieldset element.
block_offset += space_left / 2; block_offset += space_left / 2;
if (ConstraintSpace().HasBlockFragmentation()) {
// Save the previous result in case adjusting the block_offset causes
// the legend to break.
previous_result = std::move(result);
continue;
}
} }
// If the border is smaller than the block end offset of the legend margin // If the border is smaller than the block end offset of the legend margin
// box, intrinsic_block_size_ should now be based on the the block end // box, intrinsic_block_size_ should now be based on the the block end
// offset of the legend margin box instead of the border. // offset of the legend margin box instead of the border.
LayoutUnit legend_margin_end_offset = block_offset + LayoutUnit legend_margin_end_offset =
legend_margin_box_block_size - block_offset + legend_margin_box_block_size - legend_margins.block_start;
legend_margins.block_start;
if (legend_margin_end_offset > borders_.block_start) { if (legend_margin_end_offset > borders_.block_start) {
intrinsic_block_size_ = legend_margin_end_offset; intrinsic_block_size_ = legend_margin_end_offset;
is_legend_past_border_ = true; is_legend_past_border_ = true;
// Don't adjust the block-start offset of the fragment border if it broke.
if (BreakToken() || (ConstraintSpace().HasKnownFragmentainerBlockSize() &&
legend_margin_end_offset >
ConstraintSpace().FragmentainerBlockSize()))
break;
// If the legend is larger than the width of the fieldset block-start // If the legend is larger than the width of the fieldset block-start
// border, the actual padding edge of the fieldset will be moved // border, the actual padding edge of the fieldset will be moved
// accordingly. This will be the block-start offset for the fieldset // accordingly. This will be the block-start offset for the fieldset
// contents anonymous box. // contents anonymous box.
borders_.block_start = legend_margin_end_offset; borders_.block_start = legend_margin_end_offset;
} }
break;
} while (true);
// If the margin box of the legend is at least as tall as the fieldset // If the margin box of the legend is at least as tall as the fieldset
// block-start border width, it will start at the block-start border edge // block-start border width, it will start at the block-start border edge
...@@ -375,7 +303,6 @@ NGBreakStatus NGFieldsetLayoutAlgorithm::LayoutLegend( ...@@ -375,7 +303,6 @@ NGBreakStatus NGFieldsetLayoutAlgorithm::LayoutLegend(
LogicalOffset legend_offset = {legend_inline_start, block_offset}; LogicalOffset legend_offset = {legend_inline_start, block_offset};
container_builder_.AddResult(*result, legend_offset); container_builder_.AddResult(*result, legend_offset);
return NGBreakStatus::kContinue;
} }
LayoutUnit NGFieldsetLayoutAlgorithm::ComputeLegendInlineOffset( LayoutUnit NGFieldsetLayoutAlgorithm::ComputeLegendInlineOffset(
...@@ -488,8 +415,7 @@ const NGConstraintSpace ...@@ -488,8 +415,7 @@ const NGConstraintSpace
NGFieldsetLayoutAlgorithm::CreateConstraintSpaceForLegend( NGFieldsetLayoutAlgorithm::CreateConstraintSpaceForLegend(
NGBlockNode legend, NGBlockNode legend,
LogicalSize available_size, LogicalSize available_size,
LogicalSize percentage_size, LogicalSize percentage_size) {
LayoutUnit block_offset) {
NGConstraintSpaceBuilder builder( NGConstraintSpaceBuilder builder(
ConstraintSpace(), legend.Style().GetWritingMode(), /* is_new_fc */ true); ConstraintSpace(), legend.Style().GetWritingMode(), /* is_new_fc */ true);
SetOrthogonalFallbackInlineSizeIfNeeded(Style(), legend, &builder); SetOrthogonalFallbackInlineSizeIfNeeded(Style(), legend, &builder);
...@@ -498,12 +424,6 @@ NGFieldsetLayoutAlgorithm::CreateConstraintSpaceForLegend( ...@@ -498,12 +424,6 @@ NGFieldsetLayoutAlgorithm::CreateConstraintSpaceForLegend(
builder.SetPercentageResolutionSize(percentage_size); builder.SetPercentageResolutionSize(percentage_size);
builder.SetIsShrinkToFit(legend.Style().LogicalWidth().IsAuto()); builder.SetIsShrinkToFit(legend.Style().LogicalWidth().IsAuto());
builder.SetTextDirection(legend.Style().Direction()); builder.SetTextDirection(legend.Style().Direction());
if (ConstraintSpace().HasBlockFragmentation()) {
SetupSpaceBuilderForFragmentation(ConstraintSpace(), legend, block_offset,
&builder, /* is_new_fc */ true);
builder.SetEarlyBreakAppeal(container_builder_.BreakAppeal());
}
return builder.ToConstraintSpace(); return builder.ToConstraintSpace();
} }
......
...@@ -37,9 +37,7 @@ class CORE_EXPORT NGFieldsetLayoutAlgorithm ...@@ -37,9 +37,7 @@ class CORE_EXPORT NGFieldsetLayoutAlgorithm
private: private:
NGBreakStatus LayoutChildren(); NGBreakStatus LayoutChildren();
NGBreakStatus LayoutLegend( void LayoutLegend(NGBlockNode& legend);
NGBlockNode& legend,
scoped_refptr<const NGBlockBreakToken> legend_break_token);
NGBreakStatus LayoutFieldsetContent( NGBreakStatus LayoutFieldsetContent(
NGBlockNode& fieldset_content, NGBlockNode& fieldset_content,
scoped_refptr<const NGBlockBreakToken> content_break_token, scoped_refptr<const NGBlockBreakToken> content_break_token,
...@@ -49,13 +47,11 @@ class CORE_EXPORT NGFieldsetLayoutAlgorithm ...@@ -49,13 +47,11 @@ class CORE_EXPORT NGFieldsetLayoutAlgorithm
const NGConstraintSpace CreateConstraintSpaceForLegend( const NGConstraintSpace CreateConstraintSpaceForLegend(
NGBlockNode legend, NGBlockNode legend,
LogicalSize available_size, LogicalSize available_size,
LogicalSize percentage_size, LogicalSize percentage_size);
LayoutUnit block_offset);
const NGConstraintSpace CreateConstraintSpaceForFieldsetContent( const NGConstraintSpace CreateConstraintSpaceForFieldsetContent(
NGBlockNode fieldset_content, NGBlockNode fieldset_content,
LogicalSize padding_box_size, LogicalSize padding_box_size,
LayoutUnit block_offset); LayoutUnit block_offset);
bool IsFragmentainerOutOfSpace(LayoutUnit block_offset) const; bool IsFragmentainerOutOfSpace(LayoutUnit block_offset) const;
const WritingMode writing_mode_; const WritingMode writing_mode_;
...@@ -76,10 +72,6 @@ class CORE_EXPORT NGFieldsetLayoutAlgorithm ...@@ -76,10 +72,6 @@ class CORE_EXPORT NGFieldsetLayoutAlgorithm
// fragments. // fragments.
LayoutUnit consumed_border_block_start_; LayoutUnit consumed_border_block_start_;
// If true, this indicates that the legend broke during the current layout
// pass.
bool legend_broke_ = false;
// If true, the legend is taller than the block-start border, so that it // If true, the legend is taller than the block-start border, so that it
// sticks below it, allowing for a class C breakpoint [1] before any fieldset // sticks below it, allowing for a class C breakpoint [1] before any fieldset
// content. // content.
......
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