Commit 2c852be8 authored by Alison Maher's avatar Alison Maher Committed by Commit Bot

[LayoutNG] Fieldset content with negative margin block start

Handle fragmentation for fieldset content with a negative margin block
start. The following was required to accomplish this:

1. Don't wait to layout fieldset content until there is available
space in the current fragment.
2. Break before fieldset content if necessary.

Bug: 875235
Change-Id: I0c95fe37694e2a0022ed9222db0a7af13cc958b9
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2099284
Commit-Queue: Alison Maher <almaher@microsoft.com>
Reviewed-by: default avatarMorten Stenshorne <mstensho@chromium.org>
Cr-Commit-Position: refs/heads/master@{#750233}
parent 44bdde21
......@@ -173,24 +173,16 @@ scoped_refptr<const NGLayoutResult> NGFieldsetLayoutAlgorithm::Layout() {
borders_with_legend.block_start = block_start_padding_edge;
LogicalSize adjusted_padding_box_size =
ShrinkAvailableSize(border_box_size, borders_with_legend);
if (content_break_token ||
if ((IsResumingLayout(content_break_token.get())) ||
(!block_start_padding_edge_adjusted && IsResumingLayout(BreakToken()))) {
borders_with_legend.block_start = LayoutUnit();
}
LayoutUnit intrinsic_block_size = borders_with_legend.BlockSum();
bool has_space_left = true;
if (ConstraintSpace().HasKnownFragmentainerBlockSize()) {
LayoutUnit space_left =
FragmentainerSpaceAtBfcStart(ConstraintSpace()) - intrinsic_block_size;
has_space_left = space_left > 0;
}
// Proceed with normal fieldset children (excluding the rendered legend). They
// all live inside an anonymous child box of the fieldset container.
auto fieldset_content = Node().GetFieldsetContent();
if (has_space_left && fieldset_content &&
(content_break_token || !has_seen_all_children)) {
if (fieldset_content && (content_break_token || !has_seen_all_children)) {
auto child_space = CreateConstraintSpaceForFieldsetContent(
fieldset_content, adjusted_padding_box_size,
borders_with_legend.block_start);
......@@ -200,26 +192,34 @@ scoped_refptr<const NGLayoutResult> NGFieldsetLayoutAlgorithm::Layout() {
// TODO(layout-dev): Handle abortions caused by block fragmentation.
DCHECK_EQ(result->Status(), NGLayoutResult::kSuccess);
container_builder_.AddResult(*result, borders_with_legend.StartOffset());
NGBreakStatus break_status = NGBreakStatus::kContinue;
if (ConstraintSpace().HasBlockFragmentation()) {
LayoutUnit block_offset =
ConstraintSpace().FragmentainerOffsetAtBfc() + intrinsic_block_size;
break_status = BreakBeforeChildIfNeeded(
ConstraintSpace(), fieldset_content, *result.get(), block_offset,
/*has_container_separation*/ true, &container_builder_);
}
const auto& physical_fragment = result->PhysicalFragment();
if (break_status == NGBreakStatus::kContinue) {
container_builder_.AddResult(*result, borders_with_legend.StartOffset());
intrinsic_block_size +=
NGFragment(writing_mode, physical_fragment).BlockSize();
NGFragment(writing_mode, result->PhysicalFragment()).BlockSize();
container_builder_.SetHasSeenAllChildren();
}
}
LayoutUnit consumed_block_size =
BreakToken() ? BreakToken()->ConsumedBlockSize() : LayoutUnit();
if (!fieldset_content) {
container_builder_.SetHasSeenAllChildren();
// There was no anonymous child to provide the padding, so we have to add it
// ourselves. Subtract out the consumed block size to avoid over-calculating
// the block size when the fieldset's height is auto.
// ourselves.
intrinsic_block_size += padding.BlockSum();
}
intrinsic_block_size = ClampIntrinsicBlockSize(
ConstraintSpace(), Node(), adjusted_border_padding, intrinsic_block_size);
LayoutUnit consumed_block_size =
BreakToken() ? BreakToken()->ConsumedBlockSize() : LayoutUnit();
// Recompute the block-axis size now that we know our content size.
border_box_size.block_size =
......
......@@ -514,7 +514,6 @@ TEST_F(NGFieldsetLayoutAlgorithmTest, MinMax) {
// line.
TEST_F(NGFieldsetLayoutAlgorithmTest, NoFragmentation) {
SetBodyInnerHTML(R"HTML(
<!DOCTYPE html>
<style>
fieldset {
border:3px solid; margin:0; padding:10px; width: 150px; height: 100px;
......@@ -541,7 +540,6 @@ TEST_F(NGFieldsetLayoutAlgorithmTest, NoFragmentation) {
// Tests that a fieldset will fragment if it reaches the fragmentation line.
TEST_F(NGFieldsetLayoutAlgorithmTest, SimpleFragmentation) {
SetBodyInnerHTML(R"HTML(
<!DOCTYPE html>
<style>
#fieldset {
border:3px solid; margin:0; padding:10px; width: 150px; height: 500px;
......@@ -617,7 +615,6 @@ TEST_F(NGFieldsetLayoutAlgorithmTest, FragmentationNoPadding) {
// the fragmentation line.
TEST_F(NGFieldsetLayoutAlgorithmTest, FieldsetContentFragmentationAutoHeight) {
SetBodyInnerHTML(R"HTML(
<!DOCTYPE html>
<style>
#fieldset {
border:3px solid; margin:0; padding:10px; width: 150px;
......@@ -680,7 +677,6 @@ TEST_F(NGFieldsetLayoutAlgorithmTest, FieldsetContentFragmentationAutoHeight) {
// reaches the fragmentation line.
TEST_F(NGFieldsetLayoutAlgorithmTest, FieldsetContentFragmentation) {
SetBodyInnerHTML(R"HTML(
<!DOCTYPE html>
<style>
#fieldset {
border:3px solid; margin:0; padding:10px; width: 150px; height: 100px;
......@@ -743,7 +739,6 @@ TEST_F(NGFieldsetLayoutAlgorithmTest, FieldsetContentFragmentation) {
// the fragmentation line.
TEST_F(NGFieldsetLayoutAlgorithmTest, LegendFragmentationAutoHeight) {
SetBodyInnerHTML(R"HTML(
<!DOCTYPE html>
<style>
#fieldset {
border:3px solid; margin:0; padding:10px; width: 150px;
......@@ -805,7 +800,6 @@ TEST_F(NGFieldsetLayoutAlgorithmTest, LegendFragmentationAutoHeight) {
// encompass the legend.
TEST_F(NGFieldsetLayoutAlgorithmTest, LegendFragmentation) {
SetBodyInnerHTML(R"HTML(
<!DOCTYPE html>
<style>
#fieldset {
border:3px solid; margin:0; padding:10px; width: 150px; height: 100px;
......@@ -866,7 +860,6 @@ TEST_F(NGFieldsetLayoutAlgorithmTest, LegendFragmentation) {
// reaches the fragmentation line.
TEST_F(NGFieldsetLayoutAlgorithmTest, LegendAndContentFragmentationAutoHeight) {
SetBodyInnerHTML(R"HTML(
<!DOCTYPE html>
<style>
#fieldset {
border:3px solid; margin:0; padding:10px; width: 150px;
......@@ -944,7 +937,6 @@ TEST_F(NGFieldsetLayoutAlgorithmTest, LegendAndContentFragmentationAutoHeight) {
// reaches the fragmentation line.
TEST_F(NGFieldsetLayoutAlgorithmTest, LegendAndContentFragmentation) {
SetBodyInnerHTML(R"HTML(
<!DOCTYPE html>
<style>
#fieldset {
border:3px solid; margin:0; padding:10px; width: 150px; height: 100px;
......@@ -1021,7 +1013,6 @@ TEST_F(NGFieldsetLayoutAlgorithmTest, LegendAndContentFragmentation) {
// Tests fragmentation when a legend's child content overflows.
TEST_F(NGFieldsetLayoutAlgorithmTest, LegendFragmentationWithOverflow) {
SetBodyInnerHTML(R"HTML(
<!DOCTYPE html>
<style>
fieldset, legend { margin:0; border:none; padding:0; }
</style>
......@@ -1070,5 +1061,62 @@ TEST_F(NGFieldsetLayoutAlgorithmTest, LegendFragmentationWithOverflow) {
EXPECT_EQ(expectation, dump);
}
// Tests that fragmentation works as expected when the fieldset content has a
// negative margin block start.
TEST_F(NGFieldsetLayoutAlgorithmTest,
LegendAndContentFragmentationNegativeMargin) {
SetBodyInnerHTML(R"HTML(
<style>
#fieldset {
border:none; margin:0; padding:0px; width: 150px; height: 100px;
}
#legend {
padding:0px; margin:0; width: 50px; height: 100px;
}
#child {
margin-top: -20px; width: 100px; height: 40px;
}
</style>
<fieldset id="fieldset">
<legend id="legend"></legend>
<div id="child"></div>
</fieldset>
)HTML");
LayoutUnit kFragmentainerSpaceAvailable(100);
NGBlockNode node(ToLayoutBox(GetLayoutObjectByElementId("fieldset")));
NGConstraintSpace space = ConstructBlockLayoutTestConstraintSpace(
WritingMode::kHorizontalTb, TextDirection::kLtr,
LogicalSize(LayoutUnit(1000), kIndefiniteSize), false,
node.CreatesNewFormattingContext(), kFragmentainerSpaceAvailable);
scoped_refptr<const NGPhysicalBoxFragment> fragment =
NGBaseLayoutAlgorithmTest::RunFieldsetLayoutAlgorithm(node, space);
ASSERT_FALSE(fragment->BreakToken()->IsFinished());
String dump = DumpFragmentTree(fragment.get());
String expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::.
offset:unplaced size:150x100
offset:0,0 size:50x100
offset:0,100 size:150x0
offset:0,-20 size:100x20
)DUMP";
EXPECT_EQ(expectation, dump);
fragment = NGBaseLayoutAlgorithmTest::RunFieldsetLayoutAlgorithm(
node, space, fragment->BreakToken());
ASSERT_FALSE(fragment->BreakToken());
// TODO(almaher): The second node should not be 100px tall.
dump = DumpFragmentTree(fragment.get());
expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::.
offset:unplaced size:150x0
offset:0,0 size:150x100
offset:0,0 size:100x20
)DUMP";
EXPECT_EQ(expectation, dump);
}
} // anonymous namespace
} // 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