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

[LayoutNG] Only create a constraint space for margins when necessary.

Before creating the constraint space for child layout, we need to
calculate the line-left offset for the child. This requires us to
calculate the inline margins. If there are no auto inline margins and no
special alignment involved, we have everything we need, and can defer
fully resolving the margins until right after child layout (when we
actually do know the inline size of the child).

Only create a temporary constraint space for margin resolution if we
need to calculate the inline size of the fragment before layout to
calculate the line-left offset.

Cq-Include-Trybots: luci.chromium.try:linux_layout_tests_layout_ng
Change-Id: If84e4d6360c537a8c3a662c2617bef9dece7a644
Reviewed-on: https://chromium-review.googlesource.com/c/1286425Reviewed-by: default avatarChristian Biesinger <cbiesinger@chromium.org>
Reviewed-by: default avatarIan Kilpatrick <ikilpatrick@chromium.org>
Commit-Queue: Morten Stenshorne <mstensho@chromium.org>
Cr-Commit-Position: refs/heads/master@{#601868}
parent 2961e58a
...@@ -1317,8 +1317,20 @@ bool NGBlockLayoutAlgorithm::HandleInflow( ...@@ -1317,8 +1317,20 @@ bool NGBlockLayoutAlgorithm::HandleInflow(
if (child.IsBlock()) if (child.IsBlock())
container_builder_.PropagateBreak(*layout_result); container_builder_.PropagateBreak(*layout_result);
if (child.IsBlock()) if (child.IsBlock()) {
// We haven't yet resolved margins wrt. overconstrainedness, unless that was
// also required to calculate line-left offset (due to block alignment)
// before layout. Do so now, so that we store the correct values (which is
// required by e.g. getComputedStyle()).
if (!child_data.margins_fully_resolved) {
ResolveInlineMargins(child.Style(), Style(),
child_available_size_.inline_size,
fragment.InlineSize(), &child_data.margins);
child_data.margins_fully_resolved = true;
}
ToNGBlockNode(child).StoreMargins(ConstraintSpace(), child_data.margins); ToNGBlockNode(child).StoreMargins(ConstraintSpace(), child_data.margins);
}
*previous_inflow_position = ComputeInflowPosition( *previous_inflow_position = ComputeInflowPosition(
*previous_inflow_position, child, child_data, child_bfc_block_offset, *previous_inflow_position, child, child_data, child_bfc_block_offset,
...@@ -1341,7 +1353,9 @@ NGInflowChildData NGBlockLayoutAlgorithm::ComputeChildData( ...@@ -1341,7 +1353,9 @@ NGInflowChildData NGBlockLayoutAlgorithm::ComputeChildData(
DCHECK(!child.IsFloating()); DCHECK(!child.IsFloating());
// Calculate margins in parent's writing mode. // Calculate margins in parent's writing mode.
NGBoxStrut margins = CalculateMargins(child, child_break_token); bool margins_fully_resolved;
NGBoxStrut margins =
CalculateMargins(child, child_break_token, &margins_fully_resolved);
// Append the current margin strut with child's block start margin. // Append the current margin strut with child's block start margin.
// Non empty border/padding, and new FC use cases are handled inside of the // Non empty border/padding, and new FC use cases are handled inside of the
...@@ -1367,7 +1381,8 @@ NGInflowChildData NGBlockLayoutAlgorithm::ComputeChildData( ...@@ -1367,7 +1381,8 @@ NGInflowChildData NGBlockLayoutAlgorithm::ComputeChildData(
margins.LineLeft(ConstraintSpace().Direction()), margins.LineLeft(ConstraintSpace().Direction()),
BfcBlockOffset() + logical_block_offset}; BfcBlockOffset() + logical_block_offset};
return {child_bfc_offset, margin_strut, margins, force_clearance}; return {child_bfc_offset, margin_strut, margins, margins_fully_resolved,
force_clearance};
} }
NGPreviousInflowPosition NGBlockLayoutAlgorithm::ComputeInflowPosition( NGPreviousInflowPosition NGBlockLayoutAlgorithm::ComputeInflowPosition(
...@@ -1798,26 +1813,45 @@ NGBlockLayoutAlgorithm::BreakType NGBlockLayoutAlgorithm::BreakTypeBeforeChild( ...@@ -1798,26 +1813,45 @@ NGBlockLayoutAlgorithm::BreakType NGBlockLayoutAlgorithm::BreakTypeBeforeChild(
NGBoxStrut NGBlockLayoutAlgorithm::CalculateMargins( NGBoxStrut NGBlockLayoutAlgorithm::CalculateMargins(
NGLayoutInputNode child, NGLayoutInputNode child,
const NGBreakToken* child_break_token) { const NGBreakToken* child_break_token,
bool* margins_fully_resolved) {
// We need to at least partially resolve margins before creating a constraint
// space for layout. Layout needs to know the line-left offset before
// starting. If the line-left offset cannot be calculated without fully
// resolving the margins (because of block alignment), we have to create a
// temporary constraint space now to figure out the inline size first. In all
// other cases we'll postpone full resolution until after child layout, when
// we actually have a child constraint space to use (and know the inline
// size).
*margins_fully_resolved = false;
DCHECK(child); DCHECK(child);
if (child.IsInline()) if (child.IsInline())
return {}; return {};
const ComputedStyle& child_style = child.Style(); const ComputedStyle& child_style = child.Style();
bool needs_inline_size =
NeedsInlineSizeToResolveLineLeft(child_style, Style());
if (!needs_inline_size && !child_style.HasMargin())
return {};
NGConstraintSpace space = NGBoxStrut margins = ComputeMarginsFor(
NGConstraintSpaceBuilder(ConstraintSpace()) child_style, child_percentage_size_.inline_size,
.SetAvailableSize(child_available_size_) ConstraintSpace().GetWritingMode(), ConstraintSpace().Direction());
.SetPercentageResolutionSize(child_percentage_size_)
.ToConstraintSpace(child_style.GetWritingMode());
NGBoxStrut margins = ComputeMarginsFor(space, child_style, ConstraintSpace());
if (ShouldIgnoreBlockStartMargin(ConstraintSpace(), child, child_break_token)) if (ShouldIgnoreBlockStartMargin(ConstraintSpace(), child, child_break_token))
margins.block_start = LayoutUnit(); margins.block_start = LayoutUnit();
// As long as the child isn't establishing a new formatting context, we need // As long as the child isn't establishing a new formatting context, we need
// to resolve auto margins before layout, to be able to position child floats // to know its line-left offset before layout, to be able to position child
// correctly. // floats correctly. If we need to resolve auto margins or other alignment
if (!child.CreatesNewFormattingContext()) { // properties to calculate the line-left offset, we also need to calculate its
// inline size first.
if (!child.CreatesNewFormattingContext() && needs_inline_size) {
NGConstraintSpace space =
NGConstraintSpaceBuilder(ConstraintSpace())
.SetAvailableSize(child_available_size_)
.SetPercentageResolutionSize(child_percentage_size_)
.ToConstraintSpace(child_style.GetWritingMode());
NGBoxStrut child_border_padding = NGBoxStrut child_border_padding =
ComputeBorders(space, child) + ComputePadding(space, child.Style()); ComputeBorders(space, child) + ComputePadding(space, child.Style());
LayoutUnit child_inline_size = LayoutUnit child_inline_size =
...@@ -1826,6 +1860,7 @@ NGBoxStrut NGBlockLayoutAlgorithm::CalculateMargins( ...@@ -1826,6 +1860,7 @@ NGBoxStrut NGBlockLayoutAlgorithm::CalculateMargins(
ResolveInlineMargins(child_style, Style(), ResolveInlineMargins(child_style, Style(),
space.AvailableSize().inline_size, child_inline_size, space.AvailableSize().inline_size, child_inline_size,
&margins); &margins);
*margins_fully_resolved = true;
} }
return margins; return margins;
} }
......
...@@ -39,6 +39,7 @@ struct NGInflowChildData { ...@@ -39,6 +39,7 @@ struct NGInflowChildData {
NGBfcOffset bfc_offset_estimate; NGBfcOffset bfc_offset_estimate;
NGMarginStrut margin_strut; NGMarginStrut margin_strut;
NGBoxStrut margins; NGBoxStrut margins;
bool margins_fully_resolved;
bool force_clearance; bool force_clearance;
}; };
...@@ -86,7 +87,8 @@ class CORE_EXPORT NGBlockLayoutAlgorithm ...@@ -86,7 +87,8 @@ class CORE_EXPORT NGBlockLayoutAlgorithm
} }
NGBoxStrut CalculateMargins(NGLayoutInputNode child, NGBoxStrut CalculateMargins(NGLayoutInputNode child,
const NGBreakToken* child_break_token); const NGBreakToken* child_break_token,
bool* margins_fully_resolved);
// Creates a new constraint space for the current child. // Creates a new constraint space for the current child.
NGConstraintSpace CreateConstraintSpaceForChild( NGConstraintSpace CreateConstraintSpaceForChild(
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "third_party/blink/renderer/core/layout/min_max_size.h" #include "third_party/blink/renderer/core/layout/min_max_size.h"
#include "third_party/blink/renderer/core/layout/ng/geometry/ng_box_strut.h" #include "third_party/blink/renderer/core/layout/ng/geometry/ng_box_strut.h"
#include "third_party/blink/renderer/core/layout/ng/geometry/ng_logical_size.h" #include "third_party/blink/renderer/core/layout/ng/geometry/ng_logical_size.h"
#include "third_party/blink/renderer/core/layout/ng/geometry/ng_physical_size.h"
#include "third_party/blink/renderer/core/style/computed_style_constants.h" #include "third_party/blink/renderer/core/style/computed_style_constants.h"
#include "third_party/blink/renderer/platform/text/text_direction.h" #include "third_party/blink/renderer/platform/text/text_direction.h"
#include "third_party/blink/renderer/platform/text/writing_mode.h" #include "third_party/blink/renderer/platform/text/writing_mode.h"
...@@ -81,6 +82,8 @@ CORE_EXPORT LayoutUnit ResolveBlockLength( ...@@ -81,6 +82,8 @@ CORE_EXPORT LayoutUnit ResolveBlockLength(
// given constraint space. // given constraint space.
CORE_EXPORT LayoutUnit ResolveMarginPaddingLength(const NGConstraintSpace&, CORE_EXPORT LayoutUnit ResolveMarginPaddingLength(const NGConstraintSpace&,
const Length&); const Length&);
LayoutUnit ResolveMarginPaddingLength(LayoutUnit percentage_resolution_size,
const Length&);
// For the given style and min/max content sizes, computes the min and max // For the given style and min/max content sizes, computes the min and max
// content contribution (https://drafts.csswg.org/css-sizing/#contributions). // content contribution (https://drafts.csswg.org/css-sizing/#contributions).
...@@ -161,12 +164,23 @@ CORE_EXPORT LayoutUnit ResolveUsedColumnGap(LayoutUnit available_size, ...@@ -161,12 +164,23 @@ CORE_EXPORT LayoutUnit ResolveUsedColumnGap(LayoutUnit available_size,
// Compute physical margins. // Compute physical margins.
CORE_EXPORT NGPhysicalBoxStrut ComputePhysicalMargins(const NGConstraintSpace&, CORE_EXPORT NGPhysicalBoxStrut ComputePhysicalMargins(const NGConstraintSpace&,
const ComputedStyle&); const ComputedStyle&);
CORE_EXPORT NGPhysicalBoxStrut
ComputePhysicalMargins(const ComputedStyle&,
LayoutUnit percentage_resolution_size);
// Compute margins for the specified NGConstraintSpace. // Compute margins for the specified NGConstraintSpace.
CORE_EXPORT NGBoxStrut ComputeMarginsFor(const NGConstraintSpace&, CORE_EXPORT NGBoxStrut ComputeMarginsFor(const NGConstraintSpace&,
const ComputedStyle&, const ComputedStyle&,
const NGConstraintSpace& compute_for); const NGConstraintSpace& compute_for);
inline NGBoxStrut ComputeMarginsFor(const ComputedStyle& child_style,
LayoutUnit percentage_resolution_size,
WritingMode container_writing_mode,
TextDirection container_direction) {
return ComputePhysicalMargins(child_style, percentage_resolution_size)
.ConvertToLogical(container_writing_mode, container_direction);
}
// Compute margins for the style owner. // Compute margins for the style owner.
CORE_EXPORT NGBoxStrut ComputeMarginsForSelf(const NGConstraintSpace&, CORE_EXPORT NGBoxStrut ComputeMarginsForSelf(const NGConstraintSpace&,
const ComputedStyle&); const ComputedStyle&);
...@@ -206,6 +220,14 @@ CORE_EXPORT NGBoxStrut ComputePadding(const NGConstraintSpace&, ...@@ -206,6 +220,14 @@ CORE_EXPORT NGBoxStrut ComputePadding(const NGConstraintSpace&,
CORE_EXPORT NGLineBoxStrut ComputeLinePadding(const NGConstraintSpace&, CORE_EXPORT NGLineBoxStrut ComputeLinePadding(const NGConstraintSpace&,
const ComputedStyle&); const ComputedStyle&);
// Return true if we need to know the inline size of the fragment in order to
// calculate its line-left offset. This is the case when we have auto margins,
// or when block alignment isn't line-left (e.g. with align!=left, and always in
// RTL mode).
bool NeedsInlineSizeToResolveLineLeft(
const ComputedStyle& style,
const ComputedStyle& containing_block_style);
// Convert inline margins from computed to used values. This will resolve 'auto' // Convert inline margins from computed to used values. This will resolve 'auto'
// values and over-constrainedness. This uses the available size from the // values and over-constrainedness. This uses the available size from the
// constraint space and inline size to compute the margins that are auto, if // constraint space and inline size to compute the margins that are auto, if
......
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