summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.cc')
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.cc404
1 files changed, 227 insertions, 177 deletions
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.cc b/chromium/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.cc
index 6a8ee5eaedd..be334862956 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.cc
@@ -25,7 +25,7 @@ NGOutOfFlowLayoutPart::NGOutOfFlowLayoutPart(
NGBoxFragmentBuilder* container_builder,
bool contains_absolute,
bool contains_fixed,
- const NGBoxStrut& borders_and_scrollers,
+ const NGBoxStrut& border_scrollbar,
const NGConstraintSpace& container_space,
const ComputedStyle& container_style,
base::Optional<NGLogicalSize> initial_containing_block_fixed_size)
@@ -34,34 +34,77 @@ NGOutOfFlowLayoutPart::NGOutOfFlowLayoutPart(
contains_fixed_(contains_fixed) {
if (!container_builder->HasOutOfFlowDescendantCandidates())
return;
- NGPhysicalBoxStrut physical_borders = borders_and_scrollers.ConvertToPhysical(
- container_style.GetWritingMode(), container_style.Direction());
+
+ NGPhysicalBoxStrut physical_border_scrollbar =
+ border_scrollbar.ConvertToPhysical(container_style.GetWritingMode(),
+ container_style.Direction());
default_containing_block_.style = &container_style;
default_containing_block_.content_size_for_absolute =
container_builder_->Size();
default_containing_block_.content_size_for_absolute.inline_size =
std::max(default_containing_block_.content_size_for_absolute.inline_size -
- borders_and_scrollers.InlineSum(),
+ border_scrollbar.InlineSum(),
LayoutUnit());
default_containing_block_.content_size_for_absolute.block_size =
std::max(default_containing_block_.content_size_for_absolute.block_size -
- borders_and_scrollers.BlockSum(),
+ border_scrollbar.BlockSum(),
LayoutUnit());
default_containing_block_.content_size_for_fixed =
initial_containing_block_fixed_size
? initial_containing_block_fixed_size.value()
: default_containing_block_.content_size_for_absolute;
- default_containing_block_.content_offset = NGLogicalOffset{
- borders_and_scrollers.inline_start, borders_and_scrollers.block_start};
- default_containing_block_.content_physical_offset =
- NGPhysicalOffset(physical_borders.left, physical_borders.top);
+
+ default_containing_block_.container_offset = NGLogicalOffset(
+ border_scrollbar.inline_start, border_scrollbar.block_start);
+ default_containing_block_.physical_container_offset = NGPhysicalOffset(
+ physical_border_scrollbar.left, physical_border_scrollbar.top);
}
void NGOutOfFlowLayoutPart::Run(LayoutBox* only_layout) {
Vector<NGOutOfFlowPositionedDescendant> descendant_candidates;
+ const LayoutObject* current_container = container_builder_->GetLayoutObject();
+
container_builder_->GetAndClearOutOfFlowDescendantCandidates(
- &descendant_candidates, container_builder_->GetLayoutObject());
+ &descendant_candidates, current_container);
+
+ // Special case: containing block is a split inline.
+ // Detailed explanation of what this means is inside
+ // NGOutOfFlowLayoutPart::LayoutDescendant.
+ // This code can be removed once we stop inline splitting.
+ // only_layout is only true when positioning blocks for Legacy.
+ // Cross-anonymous inline containers cannot be done in Legacy.
+ if (descendant_candidates.size() > 0 && current_container && !only_layout &&
+ current_container->IsAnonymousBlock() &&
+ current_container->IsRelPositioned()) {
+ // Comments and code copied from
+ // LayoutBox::ContainingBlockLogicalWidthForPositioned.
+ // Ensure we compute our width based on the width of our rel-pos inline
+ // container rather than any anonymous block created to manage a block-flow
+ // ancestor of ours in the rel-pos inline's inline flow.
+ LayoutBoxModelObject* absolute_containing_block =
+ ToLayoutBox(current_container)->Continuation();
+ // There may be nested parallel inline continuations. We have now found the
+ // innermost inline (which may not be relatively positioned). Locate the
+ // inline that serves as the containing block of this box.
+ while (!absolute_containing_block->CanContainOutOfFlowPositionedElement(
+ EPosition::kAbsolute)) {
+ absolute_containing_block =
+ ToLayoutBoxModelObject(absolute_containing_block->Container());
+ }
+ DCHECK(absolute_containing_block->IsLayoutInline());
+ // Make absolute_containing_block continuation root.
+ absolute_containing_block = ToLayoutBoxModelObject(
+ absolute_containing_block->GetNode()->GetLayoutObject());
+ for (auto& candidate : descendant_candidates) {
+ if (absolute_containing_block->CanContainOutOfFlowPositionedElement(
+ candidate.node.Style().GetPosition())) {
+ candidate.inline_container = absolute_containing_block;
+ container_builder_->AddOutOfFlowDescendant(candidate);
+ }
+ }
+ return;
+ }
while (descendant_candidates.size() > 0) {
ComputeInlineContainingBlocks(descendant_candidates);
@@ -70,7 +113,7 @@ void NGOutOfFlowLayoutPart::Run(LayoutBox* only_layout) {
(!only_layout || candidate.node.GetLayoutBox() == only_layout)) {
NGLogicalOffset offset;
scoped_refptr<NGLayoutResult> result =
- LayoutDescendant(candidate, &offset);
+ LayoutDescendant(candidate, &offset, only_layout);
container_builder_->AddChild(*result, offset);
if (candidate.node.GetLayoutBox() != only_layout)
candidate.node.UseOldOutOfFlowPositioning();
@@ -82,7 +125,7 @@ void NGOutOfFlowLayoutPart::Run(LayoutBox* only_layout) {
// This happens when an absolute container has a fixed child.
descendant_candidates.Shrink(0);
container_builder_->GetAndClearOutOfFlowDescendantCandidates(
- &descendant_candidates, container_builder_->GetLayoutObject());
+ &descendant_candidates, current_container);
}
}
@@ -100,223 +143,185 @@ NGOutOfFlowLayoutPart::GetContainingBlockInfo(
void NGOutOfFlowLayoutPart::ComputeInlineContainingBlocks(
Vector<NGOutOfFlowPositionedDescendant> descendants) {
- HashMap<const LayoutObject*, NGBoxFragmentBuilder::FragmentPair>
- inline_container_fragments;
+ NGBoxFragmentBuilder::InlineContainingBlockMap inline_container_fragments;
for (auto& descendant : descendants) {
if (descendant.inline_container &&
!inline_container_fragments.Contains(descendant.inline_container)) {
- NGBoxFragmentBuilder::FragmentPair fragment_pair = {};
+ NGBoxFragmentBuilder::InlineContainingBlockGeometry inline_geometry = {};
inline_container_fragments.insert(descendant.inline_container,
- fragment_pair);
+ inline_geometry);
}
}
// Fetch start/end fragment info.
- NGLogicalSize container_builder_size;
container_builder_->ComputeInlineContainerFragments(
- &inline_container_fragments, &container_builder_size);
+ &inline_container_fragments);
+ NGLogicalSize container_builder_size = container_builder_->Size();
NGPhysicalSize container_builder_physical_size =
ToNGPhysicalSize(container_builder_size,
default_containing_block_.style->GetWritingMode());
// Translate start/end fragments into ContainingBlockInfo.
for (auto& block_info : inline_container_fragments) {
// Variables needed to describe ContainingBlockInfo
- const ComputedStyle* inline_cb_style;
+ const ComputedStyle* inline_cb_style = block_info.key->Style();
NGLogicalSize inline_cb_size;
- NGLogicalOffset inline_content_offset;
- NGPhysicalOffset inline_content_physical_offset;
- NGLogicalOffset default_container_offset;
- if (!block_info.value.start_fragment) {
+ NGLogicalOffset container_offset;
+ NGPhysicalOffset physical_container_offset;
+
+ if (!block_info.value.has_value()) {
// This happens when Legacy block is the default container.
// In this case, container builder does not have any fragments because
// ng layout algorithm did not run.
DCHECK(block_info.key->IsLayoutInline());
- inline_cb_style = block_info.key->Style();
NOTIMPLEMENTED()
<< "Inline containing block might need geometry information";
// TODO(atotic) ContainingBlockInfo geometry
// must be computed from Legacy algorithm
} else {
- inline_cb_style = &block_info.value.start_fragment->Style();
+ DCHECK(inline_cb_style);
+
+ // TODO Creating dummy constraint space just to get borders feels wrong.
NGConstraintSpace dummy_constraint_space =
NGConstraintSpaceBuilder(inline_cb_style->GetWritingMode(),
inline_cb_style->GetWritingMode(),
/* is_new_fc */ false)
.ToConstraintSpace();
-
- // TODO Creating dummy constraint space just to get borders feels wrong.
NGBoxStrut inline_cb_borders =
ComputeBorders(dummy_constraint_space, *inline_cb_style);
- NGPhysicalBoxStrut physical_borders = inline_cb_borders.ConvertToPhysical(
- inline_cb_style->GetWritingMode(), inline_cb_style->Direction());
- NGBoxStrut inline_cb_padding =
- ComputePadding(dummy_constraint_space, *inline_cb_style);
- // Warning: lots of non-obvious coordinate manipulation ahead.
+ // The calculation below determines the size of the inline containing
+ // block rect.
+ //
+ // To perform this calculation we:
+ // 1. Determine the start_offset "^", this is at the logical-start (wrt.
+ // default containing block), of the start fragment rect.
+ // 2. Determine the end_offset "$", this is at the logical-end (wrt.
+ // default containing block), of the end fragment rect.
+ // 3. Determine the logical rectangle defined by these two offsets.
//
- // High level goal is:
- // - Find logical topleft of start fragment, and logical bottomright
- // of end fragment.
- // - Use these to compute inline-cb geometry:
- // - inline-cb size (content_size)
- // - inline-cb offset from containing block (default_container_offset)
+ // Case 1a: Same direction, overlapping fragments.
+ // +---------------
+ // ---> |^*****-------->
+ // +*----*---------
+ // * *
+ // ------*----*+
+ // ----> *****$| --->
+ // ------------+
//
- // We start with:
- // start_fragment, which has physical offset from start_linebox_fragment,
- // end_fragment, also with physical offset.
- // start_linebox_fragment, which has logical offset from containing box.
- // end_linebox_fragment, which also has logical offset from containing
- // box.
+ // Case 1b: Different direction, overlapping fragments.
+ // +---------------
+ // ---> ^******* <-----|
+ // *------*--------
+ // * *
+ // -----*------*
+ // |<-- *******$ --->
+ // ------------+
//
- // Then magic happens.^H^H^H^H^H^H^H
+ // Case 2a: Same direction, non-overlapping fragments.
+ // +--------
+ // ---------> |^ ----->
+ // +*-------
+ // *
+ // --------+ *
+ // ------->| $ --->
+ // --------+
//
- // Then we do the following:
- // 1. Find start fragment physical topleft wrt containing box.
- // - convert start_fragment offset to logical.
- // - convert start fragment inline/block start to physical.
- // - convert linebox topleft to physical.
- // - add start fragment to linebox topleft
- // 2. Find end fragment bottom right wrt containing box
- // - convert end fragment offset to logical.
- // - convert end fragment inline/block end to physical
- // - convert linebox topleft to physical
- // - add end fragment bottomLeft to linebox topleft
- // 3. Convert both topleft/bottomright to logical, so that we can
- // 4. Enforce logical topLeft < bottomRight
- // 5. Compute size, physical offset
- const NGPhysicalFragment* start_fragment =
- block_info.value.start_fragment;
- const NGPhysicalLineBoxFragment* start_linebox_fragment =
- block_info.value.start_linebox_fragment;
+ // Case 2b: Same direction, non-overlapping fragments.
+ // +--------
+ // ---------> ^ <-----|
+ // *--------
+ // *
+ // --------+ *
+ // | <------ $ --->
+ // --------+
+ //
+ // Note in cases [1a, 2a] we need to account for the inline borders of
+ // the rectangles, where-as in [1b, 2b] we do not. This is handled by the
+ // is_same_direction check(s).
+ //
+ // Note in cases [2a, 2b] we don't allow a "negative" containing block
+ // size, we clamp negative sizes to zero.
WritingMode container_writing_mode =
default_containing_block_.style->GetWritingMode();
TextDirection container_direction =
default_containing_block_.style->Direction();
- // Step 1
- NGLogicalOffset start_fragment_logical_offset =
- block_info.value.start_fragment_union_rect.offset.ConvertToLogical(
- container_writing_mode, container_direction,
- start_linebox_fragment->Size(),
- block_info.value.start_fragment_union_rect.size);
- // Text fragments do not include inline-cb borders and padding.
- if (start_fragment->IsText()) {
- start_fragment_logical_offset -= inline_cb_borders.StartOffset();
- start_fragment_logical_offset -= inline_cb_padding.StartOffset();
- }
- NGPhysicalOffset start_fragment_physical_offset =
- start_fragment_logical_offset.ConvertToPhysical(
- container_writing_mode, container_direction,
- start_linebox_fragment->Size(), NGPhysicalSize());
- // Step 2
- const NGPhysicalLineBoxFragment* end_linebox_fragment =
- block_info.value.end_linebox_fragment;
- const NGPhysicalFragment* end_fragment = block_info.value.end_fragment;
- NGLogicalOffset end_fragment_logical_offset =
- block_info.value.end_fragment_union_rect.offset.ConvertToLogical(
- container_writing_mode, container_direction,
- end_linebox_fragment->Size(),
- block_info.value.end_fragment_union_rect.size);
- // Text fragments do not include inline-cb borders and padding.
- if (end_fragment->IsText()) {
- end_fragment_logical_offset += NGLogicalOffset(
- inline_cb_borders.inline_end, inline_cb_borders.block_end);
- end_fragment_logical_offset += NGLogicalOffset(
- inline_cb_padding.inline_end, inline_cb_padding.block_end);
- }
- NGLogicalOffset end_fragment_bottom_right =
- end_fragment_logical_offset +
- block_info.value.end_fragment_union_rect.size.ConvertToLogical(
- container_writing_mode);
- NGPhysicalOffset end_fragment_physical_offset =
- end_fragment_bottom_right.ConvertToPhysical(
- container_writing_mode, container_direction,
- end_linebox_fragment->Size(), NGPhysicalSize());
- // Step 3
- NGLogicalOffset start_fragment_logical_offset_wrt_box =
- start_fragment_physical_offset.ConvertToLogical(
- inline_cb_style->GetWritingMode(), inline_cb_style->Direction(),
- container_builder_physical_size, NGPhysicalSize());
- NGLogicalOffset end_fragment_logical_offset_wrt_box =
- end_fragment_physical_offset.ConvertToLogical(
- inline_cb_style->GetWritingMode(), inline_cb_style->Direction(),
- container_builder_physical_size, NGPhysicalSize());
-
- // Step 4
- end_fragment_logical_offset_wrt_box.inline_offset =
- std::max(end_fragment_logical_offset_wrt_box.inline_offset,
- start_fragment_logical_offset_wrt_box.inline_offset +
- inline_cb_borders.InlineSum());
- end_fragment_logical_offset_wrt_box.block_offset =
- std::max(end_fragment_logical_offset_wrt_box.block_offset,
- start_fragment_logical_offset_wrt_box.block_offset +
- inline_cb_borders.BlockSum());
-
- // Step 5
- inline_cb_size.inline_size =
- end_fragment_logical_offset_wrt_box.inline_offset -
- start_fragment_logical_offset_wrt_box.inline_offset -
- inline_cb_borders.InlineSum();
- inline_cb_size.block_size =
- end_fragment_logical_offset_wrt_box.block_offset -
- start_fragment_logical_offset_wrt_box.block_offset -
- inline_cb_borders.BlockSum();
+ bool is_same_direction =
+ container_direction == inline_cb_style->Direction();
+
+ // Step 1 - determine the start_offset.
+ const NGPhysicalOffsetRect& start_rect =
+ block_info.value.value().start_fragment_union_rect;
+ NGLogicalOffset start_offset = start_rect.offset.ConvertToLogical(
+ container_writing_mode, container_direction,
+ container_builder_physical_size, start_rect.size);
+
+ // Make sure we add the inline borders, we don't need to do this in the
+ // inline direction if the blocks are in opposite directions.
+ start_offset.block_offset += inline_cb_borders.block_start;
+ if (is_same_direction)
+ start_offset.inline_offset += inline_cb_borders.inline_start;
+
+ // Step 2 - determine the end_offset.
+ const NGPhysicalOffsetRect& end_rect =
+ block_info.value.value().end_fragment_union_rect;
+ NGLogicalOffset end_offset = end_rect.offset.ConvertToLogical(
+ container_writing_mode, container_direction,
+ container_builder_physical_size, end_rect.size);
+
+ // Add in the size of the fragment to get the logical end of the fragment.
+ end_offset += end_rect.size.ConvertToLogical(container_writing_mode);
+
+ // Make sure we substract the inline borders, we don't need to do this in
+ // the inline direction if the blocks are in opposite directions.
+ end_offset.block_offset -= inline_cb_borders.block_end;
+ if (is_same_direction)
+ end_offset.inline_offset -= inline_cb_borders.inline_end;
+
+ // Make sure we don't end up with a rectangle with "negative" size.
+ end_offset.inline_offset =
+ std::max(end_offset.inline_offset, start_offset.inline_offset);
+
+ // Step 3 - determine the logical rectange.
+
+ // Determine the logical size of the containing block.
+ inline_cb_size = {end_offset.inline_offset - start_offset.inline_offset,
+ end_offset.block_offset - start_offset.block_offset};
DCHECK_GE(inline_cb_size.inline_size, LayoutUnit());
DCHECK_GE(inline_cb_size.block_size, LayoutUnit());
- inline_content_offset = NGLogicalOffset{inline_cb_borders.inline_start,
- inline_cb_borders.block_start};
- inline_content_physical_offset =
- NGPhysicalOffset(physical_borders.left, physical_borders.top);
-
- // NGPaint offset is wrt parent fragment.
- default_container_offset = start_fragment_logical_offset_wrt_box -
- default_containing_block_.content_offset;
- default_container_offset += inline_cb_borders.StartOffset();
+ // Determine the container offsets.
+ container_offset = start_offset;
+ physical_container_offset = container_offset.ConvertToPhysical(
+ container_writing_mode, container_direction,
+ container_builder_physical_size,
+ ToNGPhysicalSize(inline_cb_size, container_writing_mode));
}
containing_blocks_map_.insert(
block_info.key,
ContainingBlockInfo{inline_cb_style, inline_cb_size, inline_cb_size,
- inline_content_offset,
- inline_content_physical_offset,
- default_container_offset});
+ container_offset, physical_container_offset});
}
}
scoped_refptr<NGLayoutResult> NGOutOfFlowLayoutPart::LayoutDescendant(
const NGOutOfFlowPositionedDescendant& descendant,
- NGLogicalOffset* offset) {
+ NGLogicalOffset* offset,
+ LayoutBox* only_layout) {
ContainingBlockInfo container_info = GetContainingBlockInfo(descendant);
WritingMode container_writing_mode(container_info.style->GetWritingMode());
WritingMode descendant_writing_mode(descendant.node.Style().GetWritingMode());
- // Adjust the static_position origin.
- // The static_position coordinate origin is relative to default_container's
- // border box.
- // ng_absolute_utils expects static position to be relative to
- // the container's padding box.
- // Adjust static position by offset of container from default container,
- // and default_container border width.
+ // Adjust the static_position (which is currently relative to the default
+ // container's border-box). ng_absolute_utils expects the static position to
+ // be relative to the container's padding-box.
NGStaticPosition static_position(descendant.static_position);
- NGPhysicalSize default_containing_block_physical_size =
- ToNGPhysicalSize(default_containing_block_.ContentSize(
- descendant.node.Style().GetPosition()),
- default_containing_block_.style->GetWritingMode());
- NGPhysicalOffset default_container_physical_offset =
- container_info.default_container_offset.ConvertToPhysical(
- default_containing_block_.style->GetWritingMode(),
- default_containing_block_.style->Direction(),
- default_containing_block_physical_size,
- default_containing_block_physical_size);
-
- static_position.offset = static_position.offset -
- default_containing_block_.content_physical_offset -
- default_container_physical_offset;
+ static_position.offset -= container_info.physical_container_offset;
NGLogicalSize container_content_size =
container_info.ContentSize(descendant.node.Style().GetPosition());
- // The block estimate is in the descendant's writing mode.
+
NGConstraintSpace descendant_constraint_space =
NGConstraintSpaceBuilder(container_writing_mode, descendant_writing_mode,
/* is_new_fc */ true)
@@ -324,8 +329,10 @@ scoped_refptr<NGLayoutResult> NGOutOfFlowLayoutPart::LayoutDescendant(
.SetAvailableSize(container_content_size)
.SetPercentageResolutionSize(container_content_size)
.ToConstraintSpace();
- base::Optional<MinMaxSize> min_max_size;
+
+ // The block_estimate is in the descendant's writing mode.
base::Optional<LayoutUnit> block_estimate;
+ base::Optional<MinMaxSize> min_max_size;
scoped_refptr<NGLayoutResult> layout_result = nullptr;
@@ -389,19 +396,16 @@ scoped_refptr<NGLayoutResult> NGOutOfFlowLayoutPart::LayoutDescendant(
ToLayoutBlock(node.GetLayoutBox())
->SetIsLegacyInitiatedOutOfFlowLayout(false);
}
- // Compute logical offset, NGAbsolutePhysicalPosition is calculated relative
- // to the padding box so add back the container's borders.
+
NGBoxStrut inset = node_position.inset.ConvertToLogical(
- container_writing_mode, container_info.style->Direction());
+ container_writing_mode, default_containing_block_.style->Direction());
+
+ // inset is relative to the container's padding-box. Convert this to being
+ // relative to the default container's border-box.
offset->inline_offset =
- inset.inline_start +
- default_containing_block_.content_offset.inline_offset;
+ inset.inline_start + container_info.container_offset.inline_offset;
offset->block_offset =
- inset.block_start + default_containing_block_.content_offset.block_offset;
-
- offset->inline_offset +=
- container_info.default_container_offset.inline_offset;
- offset->block_offset += container_info.default_container_offset.block_offset;
+ inset.block_start + container_info.container_offset.block_offset;
base::Optional<LayoutUnit> y = ComputeAbsoluteDialogYPosition(
*descendant.node.GetLayoutBox(),
@@ -413,6 +417,47 @@ scoped_refptr<NGLayoutResult> NGOutOfFlowLayoutPart::LayoutDescendant(
offset->inline_offset = y.value();
}
+ // Special case: oof css container is a split inline.
+ // When css container spans multiple anonymous blocks, its dimensions
+ // can only be computed by a block that is an ancestor of all fragments
+ // generated by css container. That block is parent of anonymous containing
+ // block.
+ // That is why instead of OOF being placed by its anononymous container,
+ // they get placed by anonymous container's parent.
+ // This is different from all other OOF blocks, and requires special
+ // handling in several places in the OOF code.
+ // There is an exception to special case: if anonymous block is Legacy,
+ // we cannot do the fancy multiple anonymous block traversal, and we handle
+ // it like regular blocks.
+ //
+ // Detailed example:
+ //
+ // If Layout tree looks like this:
+ // LayoutNGBlockFlow#container
+ // LayoutNGBlockFlow (anonymous#1)
+ // LayoutInline#1 (relative)
+ // LayoutNGBlockFlow (anonymous#2 relative)
+ // LayoutNGBlockFlow#oof (positioned)
+ // LayoutNGBlockFlow (anonymous#3)
+ // LayoutInline#3 (continuation)
+ //
+ // The containing block geometry is defined by split inlines,
+ // LayoutInline#1, LayoutInline#3.
+ // Css container anonymous#2 does not have information needed
+ // to compute containing block geometry.
+ // Therefore, #oof cannot be placed by anonymous#2. NG handles this case
+ // by placing #oof in parent of anonymous (#container).
+ //
+ // But, PaintPropertyTreeBuilder expects #oof.Location() to be wrt
+ // css container, #anonymous2. This is why the code below adjusts
+ // the legacy offset from being wrt #container to being wrt #anonymous2.
+
+ const LayoutObject* container = descendant.node.GetLayoutBox()->Container();
+ if (!only_layout && container->IsAnonymousBlock()) {
+ NGLogicalOffset container_offset =
+ container_builder_->GetChildOffset(container);
+ *offset -= container_offset;
+ }
return layout_result;
}
@@ -423,6 +468,11 @@ bool NGOutOfFlowLayoutPart::IsContainingBlockForDescendant(
// Descendants whose containing block is inline are always positioned
// inside closest parent block flow.
if (descendant.inline_container) {
+ DCHECK(
+ descendant.node.Style().GetPosition() == EPosition::kAbsolute &&
+ descendant.inline_container->CanContainAbsolutePositionObjects() ||
+ (descendant.node.Style().GetPosition() == EPosition::kFixed &&
+ descendant.inline_container->CanContainFixedPositionObjects()));
return true;
}
return (contains_absolute_ && position == EPosition::kAbsolute) ||