Commit a71502eb authored by Morten Stenshorne's avatar Morten Stenshorne Committed by Commit Bot

[LayoutNG] Use BoxLayoutExtraInput when calculating overflow.

This will set temporary proper override sizes.

We already use this mechanism in NGBlockNode::RunLegacyLayout(), but
that one only has an effect for things that are done from within legacy
layout (LayoutObject::Layout()). Overflow calculation happens after
layout, and is done by the legacy engine, even for NG objects.

Bug: 908083
Change-Id: I2b4e88c096f138aa820856e3c79e1ddcef07a3da
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1801770Reviewed-by: default avatarKoji Ishii <kojii@chromium.org>
Reviewed-by: default avatarChristian Biesinger <cbiesinger@chromium.org>
Reviewed-by: default avatarAleks Totic <atotic@chromium.org>
Reviewed-by: default avatarEmil A Eklund <eae@chromium.org>
Commit-Queue: Morten Stenshorne <mstensho@chromium.org>
Cr-Commit-Position: refs/heads/master@{#696752}
parent 184856ec
...@@ -203,6 +203,45 @@ LayoutUnit CalculateAvailableBlockSizeForLegacy( ...@@ -203,6 +203,45 @@ LayoutUnit CalculateAvailableBlockSizeForLegacy(
return space.PercentageResolutionBlockSize(); return space.PercentageResolutionBlockSize();
} }
void SetupBoxLayoutExtraInput(const NGConstraintSpace& space,
const LayoutBox& box,
BoxLayoutExtraInput* input) {
input->containing_block_content_inline_size =
CalculateAvailableInlineSizeForLegacy(box, space);
input->containing_block_content_block_size =
CalculateAvailableBlockSizeForLegacy(box, space);
WritingMode writing_mode = box.StyleRef().GetWritingMode();
if (LayoutObject* containing_block = box.ContainingBlock()) {
if (!IsParallelWritingMode(containing_block->StyleRef().GetWritingMode(),
writing_mode)) {
// The sizes should be in the containing block writing mode.
std::swap(input->containing_block_content_block_size,
input->containing_block_content_inline_size);
// We cannot lay out without a definite containing block inline-size. We
// end up here if we're performing a measure pass (as part of resolving
// the intrinsic min/max inline-size of some ancestor, for instance).
// Legacy layout has a tendency of clamping negative sizes to 0 anyway,
// but this is missing when it comes to resolving percentage-based
// padding, for instance.
if (input->containing_block_content_inline_size == kIndefiniteSize)
input->containing_block_content_inline_size = LayoutUnit();
}
}
// We need a definite containing block inline-size, or we'd be unable to
// resolve percentages.
DCHECK_GE(input->containing_block_content_inline_size, LayoutUnit());
input->available_inline_size = space.AvailableSize().inline_size;
if (space.IsFixedInlineSize())
input->override_inline_size = space.AvailableSize().inline_size;
if (space.IsFixedBlockSize())
input->override_block_size = space.AvailableSize().block_size;
}
} // namespace } // namespace
scoped_refptr<const NGLayoutResult> NGBlockNode::Layout( scoped_refptr<const NGLayoutResult> NGBlockNode::Layout(
...@@ -796,6 +835,9 @@ void NGBlockNode::CopyFragmentDataToLayoutBox( ...@@ -796,6 +835,9 @@ void NGBlockNode::CopyFragmentDataToLayoutBox(
physical_fragment); physical_fragment);
} }
BoxLayoutExtraInput input(*block);
SetupBoxLayoutExtraInput(constraint_space, *block, &input);
// |ComputeOverflow()| below calls |AddVisualOverflowFromChildren()|, which // |ComputeOverflow()| below calls |AddVisualOverflowFromChildren()|, which
// computes visual overflow from |RootInlineBox| if |ChildrenInline()| // computes visual overflow from |RootInlineBox| if |ChildrenInline()|
block->SetNeedsOverflowRecalc(); block->SetNeedsOverflowRecalc();
...@@ -1089,42 +1131,9 @@ scoped_refptr<const NGLayoutResult> NGBlockNode::RunLegacyLayout( ...@@ -1089,42 +1131,9 @@ scoped_refptr<const NGLayoutResult> NGBlockNode::RunLegacyLayout(
if (box_->NeedsLayout() || !layout_result || needs_force_relayout) { if (box_->NeedsLayout() || !layout_result || needs_force_relayout) {
BoxLayoutExtraInput input(*box_); BoxLayoutExtraInput input(*box_);
input.containing_block_content_inline_size =
CalculateAvailableInlineSizeForLegacy(*box_, constraint_space);
input.containing_block_content_block_size =
CalculateAvailableBlockSizeForLegacy(*box_, constraint_space);
WritingMode writing_mode = Style().GetWritingMode(); WritingMode writing_mode = Style().GetWritingMode();
if (LayoutObject* containing_block = box_->ContainingBlock()) {
if (!IsParallelWritingMode(containing_block->StyleRef().GetWritingMode(),
writing_mode)) {
// The sizes should be in the containing block writing mode.
std::swap(input.containing_block_content_block_size,
input.containing_block_content_inline_size);
// We cannot lay out without a definite containing block inline-size. We
// end up here if we're performing a measure pass (as part of resolving
// the intrinsic min/max inline-size of some ancestor, for instance).
// Legacy layout has a tendency of clamping negative sizes to 0 anyway,
// but this is missing when it comes to resolving percentage-based
// padding, for instance.
if (input.containing_block_content_inline_size == kIndefiniteSize) {
DCHECK(constraint_space.IsIntermediateLayout());
input.containing_block_content_inline_size = LayoutUnit();
}
}
}
// We need a definite containing block inline-size, or we'd be unable to
// resolve percentages.
DCHECK_GE(input.containing_block_content_inline_size, LayoutUnit());
input.available_inline_size = constraint_space.AvailableSize().inline_size;
if (constraint_space.IsFixedInlineSize()) SetupBoxLayoutExtraInput(constraint_space, *box_, &input);
input.override_inline_size = constraint_space.AvailableSize().inline_size;
if (constraint_space.IsFixedBlockSize())
input.override_block_size = constraint_space.AvailableSize().block_size;
box_->ComputeAndSetBlockDirectionMargins(box_->ContainingBlock()); box_->ComputeAndSetBlockDirectionMargins(box_->ContainingBlock());
// Using |LayoutObject::LayoutIfNeeded| save us a little bit of overhead, // Using |LayoutObject::LayoutIfNeeded| save us a little bit of overhead,
......
<!DOCTYPE html>
<link rel="author" title="Morten Stenshorne" href="mailto:mstensho@chromium.org">
<link rel="help" href="https://www.w3.org/TR/CSS22/visuren.html#propdef-left">
<link rel="help" href="https://www.w3.org/TR/CSS22/visuren.html#relative-positioning">
<link rel="help" href="https://bugs.chromium.org/p/chromium/issues/detail?id=908083">
<p>There should be no red, and no scrollbar.</p>
<div id="container" style="overflow:auto; width:500px; background:red;">
<div style="padding-right:90%; background:yellow;">
<div style="position:relative; left:900%; width:50px; height:50px; background:cyan;">
</div>
</div>
</div>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
container.scrollLeft = 123456;
test(()=> {
assert_equals(container.scrollLeft, 0);
}, "Left percentage resolved correctly for overflow contribution");
</script>
<!DOCTYPE html>
<link rel="author" title="Morten Stenshorne" href="mailto:mstensho@chromium.org">
<link rel="help" href="https://www.w3.org/TR/CSS22/visuren.html#propdef-top">
<link rel="help" href="https://www.w3.org/TR/CSS22/visuren.html#relative-positioning">
<link rel="help" href="https://bugs.chromium.org/p/chromium/issues/detail?id=908083">
<p>There should be a green square below.</p>
<div style="position:relative; width:200px; height:200px;">
<div id="container" style="overflow:hidden; position:absolute; top:0; left:0; bottom:0; right:0;">
<div style="position:relative; top:100%; width:100px; height:100px; background:green;"></div>
</div>
</div>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
container.scrollTop = 123456;
test(()=> {
assert_equals(container.scrollTop, 100);
}, "Top percentage resolved correctly for overflow contribution");
</script>
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