diff options
Diffstat (limited to 'chromium/third_party/blink/renderer/core/layout/ng/ng_physical_container_fragment.cc')
-rw-r--r-- | chromium/third_party/blink/renderer/core/layout/ng/ng_physical_container_fragment.cc | 135 |
1 files changed, 128 insertions, 7 deletions
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_physical_container_fragment.cc b/chromium/third_party/blink/renderer/core/layout/ng/ng_physical_container_fragment.cc index 6e7ac12f47b..82f57612ce4 100644 --- a/chromium/third_party/blink/renderer/core/layout/ng/ng_physical_container_fragment.cc +++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_physical_container_fragment.cc @@ -6,10 +6,12 @@ #include "third_party/blink/renderer/core/layout/layout_block_flow.h" #include "third_party/blink/renderer/core/layout/layout_inline.h" +#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.h" #include "third_party/blink/renderer/core/layout/ng/inline/ng_physical_line_box_fragment.h" #include "third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.h" #include "third_party/blink/renderer/core/layout/ng/ng_outline_utils.h" #include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h" +#include "third_party/blink/renderer/core/layout/ng/ng_relative_utils.h" #include "third_party/blink/renderer/platform/geometry/layout_rect.h" namespace blink { @@ -88,6 +90,40 @@ void NGPhysicalContainerFragment::AddOutlineRectsForNormalChildren( const PhysicalOffset& additional_offset, NGOutlineType outline_type, const LayoutBoxModelObject* containing_block) const { + if (const auto* box = DynamicTo<NGPhysicalBoxFragment>(this)) { + if (const NGFragmentItems* items = box->Items()) { + for (NGInlineCursor cursor(*items); cursor; cursor.MoveToNext()) { + DCHECK(cursor.Current().Item()); + const NGFragmentItem& item = *cursor.Current().Item(); + if (item.Type() == NGFragmentItem::kLine) { + AddOutlineRectsForDescendant( + {item.LineBoxFragment(), item.OffsetInContainerBlock()}, + outline_rects, additional_offset, outline_type, containing_block); + continue; + } + if (item.Type() == NGFragmentItem::kBox) { + if (const NGPhysicalBoxFragment* child_box = item.BoxFragment()) { + DCHECK(!child_box->IsOutOfFlowPositioned()); + AddOutlineRectsForDescendant( + {child_box, item.OffsetInContainerBlock()}, outline_rects, + additional_offset, outline_type, containing_block); + } + continue; + } + DCHECK(item.IsText()); + } + // Don't add |Children()|. If |this| has |NGFragmentItems|, children are + // either line box, which we already handled in items, or OOF, which we + // should ignore. + DCHECK(std::all_of(PostLayoutChildren().begin(), + PostLayoutChildren().end(), [](const NGLink& child) { + return child->IsLineBox() || + child->IsOutOfFlowPositioned(); + })); + return; + } + } + for (const auto& child : PostLayoutChildren()) { // Outlines of out-of-flow positioned descendants are handled in // NGPhysicalBoxFragment::AddSelfOutlineRects(). @@ -111,6 +147,84 @@ void NGPhysicalContainerFragment::AddOutlineRectsForNormalChildren( } } +void NGPhysicalContainerFragment::AddScrollableOverflowForInlineChild( + const NGPhysicalBoxFragment& container, + const ComputedStyle& container_style, + const NGFragmentItem& line, + bool has_hanging, + const NGInlineCursor& cursor, + PhysicalRect* overflow) const { + DCHECK(RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()); + DCHECK(IsLineBox() || IsInlineBox()); + DCHECK(cursor.Current().Item() && + (cursor.Current().Item()->BoxFragment() == this || + cursor.Current().Item()->LineBoxFragment() == this)); + const WritingMode container_writing_mode = container_style.GetWritingMode(); + const TextDirection container_direction = container_style.Direction(); + for (NGInlineCursor descendants = cursor.CursorForDescendants(); + descendants;) { + const NGFragmentItem* item = descendants.CurrentItem(); + DCHECK(item); + if (item->IsText()) { + PhysicalRect child_scroll_overflow = item->RectInContainerBlock(); + if (UNLIKELY(has_hanging)) { + AdjustScrollableOverflowForHanging(line.RectInContainerBlock(), + container_writing_mode, + &child_scroll_overflow); + } + overflow->Unite(child_scroll_overflow); + descendants.MoveToNextSkippingChildren(); + continue; + } + + if (const NGPhysicalBoxFragment* child_box = item->BoxFragment()) { + PhysicalRect child_scroll_overflow = item->RectInContainerBlock(); + if (child_box->IsInlineBox()) { + child_box->AddScrollableOverflowForInlineChild( + container, container_style, line, has_hanging, descendants, + &child_scroll_overflow); + child_box->AdjustScrollableOverflowForPropagation( + container, &child_scroll_overflow); + } else { + child_scroll_overflow = + child_box->ScrollableOverflowForPropagation(container); + child_scroll_overflow.offset += item->OffsetInContainerBlock(); + } + child_scroll_overflow.offset += + ComputeRelativeOffset(child_box->Style(), container_writing_mode, + container_direction, container.Size()); + overflow->Unite(child_scroll_overflow); + descendants.MoveToNextSkippingChildren(); + continue; + } + + // Add all children of a culled inline box; i.e., an inline box without + // margin/border/padding etc. + DCHECK_EQ(item->Type(), NGFragmentItem::kBox); + descendants.MoveToNext(); + } +} + +// Chop the hanging part from scrollable overflow. Children overflow in inline +// direction should hang, which should not cause scroll. +// TODO(kojii): Should move to text fragment to make this more accurate. +void NGPhysicalContainerFragment::AdjustScrollableOverflowForHanging( + const PhysicalRect& rect, + const WritingMode container_writing_mode, + PhysicalRect* overflow) { + if (IsHorizontalWritingMode(container_writing_mode)) { + if (overflow->offset.left < rect.offset.left) + overflow->offset.left = rect.offset.left; + if (overflow->Right() > rect.Right()) + overflow->ShiftRightEdgeTo(rect.Right()); + } else { + if (overflow->offset.top < rect.offset.top) + overflow->offset.top = rect.offset.top; + if (overflow->Bottom() > rect.Bottom()) + overflow->ShiftBottomEdgeTo(rect.Bottom()); + } +} + // additional_offset must be offset from the containing_block because // LocalToAncestorRect returns rects wrt containing_block. void NGPhysicalContainerFragment::AddOutlineRectsForDescendant( @@ -212,16 +326,23 @@ bool NGPhysicalContainerFragment::DependsOnPercentageBlockSize( // element if it has a percentage block-size however, but this will return // the correct result from below. + // There are two conditions where we need to know about an (arbitrary) + // descendant which depends on a %-block-size. + // - In quirks mode, the arbitrary descendant may depend the percentage + // resolution block-size given (to this node), and need to relayout if + // this size changes. + // - A flex-item may have its "definiteness" change, (e.g. if itself is a + // flex item which is being stretched). This definiteness change will + // affect any %-block-size children. + // + // NOTE(ikilpatrick): For the flex-item case this is potentially too general. + // We only need to know about if this flex-item has a %-block-size child if + // the "definiteness" changes, not if the percentage resolution size changes. if ((builder.has_descendant_that_depends_on_percentage_block_size_ || builder.is_legacy_layout_root_) && - node.UseParentPercentageResolutionBlockSizeForChildren()) { - // Quirks mode has different %-block-size behaviour, than standards mode. - // An arbitrary descendant may depend on the percentage resolution - // block-size given. - // If this is also an anonymous block we need to mark ourselves dependent - // if we have a dependent child. + (node.UseParentPercentageResolutionBlockSizeForChildren() || + node.IsFlexItem())) return true; - } const ComputedStyle& style = builder.Style(); if (style.LogicalHeight().IsPercentOrCalc() || |