summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/core/layout/ng/ng_physical_container_fragment.cc
diff options
context:
space:
mode:
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.cc135
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() ||