Commit 98fa651b authored by Koji Ishii's avatar Koji Ishii Committed by Commit Bot

[FragmentItem] Fix scrollable overflow when inline boxes have paddings

When r728175 <crrev.com/c/1963597> supported traversing
items, it failed to add the size of child inline boxes.

The size of an inline box is different from the union of its
descendants when it has padding.

Bug: 982194
Change-Id: Id2e35cf4136cc0342f509c676f7a678ffcbece80
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2079775Reviewed-by: default avatarIan Kilpatrick <ikilpatrick@chromium.org>
Commit-Queue: Koji Ishii <kojii@chromium.org>
Cr-Commit-Position: refs/heads/master@{#746511}
parent 1ff09008
...@@ -70,26 +70,6 @@ NGLineHeightMetrics NGPhysicalLineBoxFragment::BaselineMetrics() const { ...@@ -70,26 +70,6 @@ NGLineHeightMetrics NGPhysicalLineBoxFragment::BaselineMetrics() const {
namespace { namespace {
// 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.
inline void 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());
}
}
// Include the inline-size of the line-box in the overflow. // Include the inline-size of the line-box in the overflow.
inline void AddInlineSizeToOverflow(const PhysicalRect& rect, inline void AddInlineSizeToOverflow(const PhysicalRect& rect,
const WritingMode container_writing_mode, const WritingMode container_writing_mode,
...@@ -139,54 +119,23 @@ PhysicalRect NGPhysicalLineBoxFragment::ScrollableOverflow( ...@@ -139,54 +119,23 @@ PhysicalRect NGPhysicalLineBoxFragment::ScrollableOverflow(
return overflow; return overflow;
} }
PhysicalRect NGPhysicalLineBoxFragment::ScrollableOverflow( PhysicalRect NGPhysicalLineBoxFragment::ScrollableOverflowForLine(
const NGPhysicalBoxFragment& container, const NGPhysicalBoxFragment& container,
const ComputedStyle& container_style, const ComputedStyle& container_style,
const NGFragmentItem& child, const NGFragmentItem& line,
const NGInlineCursor& cursor) const { const NGInlineCursor& cursor) const {
DCHECK(RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()); DCHECK(RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled());
DCHECK_EQ(&child, cursor.CurrentItem()); DCHECK_EQ(&line, cursor.CurrentItem());
DCHECK_EQ(child.LineBoxFragment(), this); DCHECK_EQ(line.LineBoxFragment(), this);
const WritingMode container_writing_mode = container_style.GetWritingMode();
const TextDirection container_direction = container_style.Direction();
PhysicalRect overflow;
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(child.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 =
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 PhysicalRect overflow;
// margin/border/padding etc. AddScrollableOverflowForInlineChild(container, container_style, line,
DCHECK_EQ(item->Type(), NGFragmentItem::kBox); has_hanging_, cursor, &overflow);
descendants.MoveToNext();
}
// Make sure we include the inline-size of the line-box in the overflow. // Make sure we include the inline-size of the line-box in the overflow.
AddInlineSizeToOverflow(child.RectInContainerBlock(), container_writing_mode, // Note, the bottom half-leading should not be included. crbug.com/996847
const WritingMode container_writing_mode = container_style.GetWritingMode();
AddInlineSizeToOverflow(line.RectInContainerBlock(), container_writing_mode,
&overflow); &overflow);
return overflow; return overflow;
......
...@@ -66,10 +66,10 @@ class CORE_EXPORT NGPhysicalLineBoxFragment final ...@@ -66,10 +66,10 @@ class CORE_EXPORT NGPhysicalLineBoxFragment final
// to resolve relative position of its children. // to resolve relative position of its children.
PhysicalRect ScrollableOverflow(const NGPhysicalBoxFragment& container, PhysicalRect ScrollableOverflow(const NGPhysicalBoxFragment& container,
const ComputedStyle& container_style) const; const ComputedStyle& container_style) const;
PhysicalRect ScrollableOverflow(const NGPhysicalBoxFragment& container, PhysicalRect ScrollableOverflowForLine(const NGPhysicalBoxFragment& container,
const ComputedStyle& container_style, const ComputedStyle& container_style,
const NGFragmentItem& child, const NGFragmentItem& line,
const NGInlineCursor& cursor) const; const NGInlineCursor& cursor) const;
// Whether the content soft-wraps to the next line. // Whether the content soft-wraps to the next line.
bool HasSoftWrapToNextLine() const; bool HasSoftWrapToNextLine() const;
......
...@@ -268,7 +268,7 @@ PhysicalRect NGPhysicalBoxFragment::ScrollableOverflowFromChildren() const { ...@@ -268,7 +268,7 @@ PhysicalRect NGPhysicalBoxFragment::ScrollableOverflowFromChildren() const {
const NGPhysicalLineBoxFragment* line_box = child.LineBoxFragment(); const NGPhysicalLineBoxFragment* line_box = child.LineBoxFragment();
DCHECK(line_box); DCHECK(line_box);
PhysicalRect child_scrollable_overflow = PhysicalRect child_scrollable_overflow =
line_box->ScrollableOverflow(container, style, child, cursor); line_box->ScrollableOverflowForLine(container, style, child, cursor);
AddChild(child_scrollable_overflow); AddChild(child_scrollable_overflow);
} }
......
...@@ -6,10 +6,12 @@ ...@@ -6,10 +6,12 @@
#include "third_party/blink/renderer/core/layout/layout_block_flow.h" #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/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/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_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_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_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" #include "third_party/blink/renderer/platform/geometry/layout_rect.h"
namespace blink { namespace blink {
...@@ -111,6 +113,84 @@ void NGPhysicalContainerFragment::AddOutlineRectsForNormalChildren( ...@@ -111,6 +113,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 // additional_offset must be offset from the containing_block because
// LocalToAncestorRect returns rects wrt containing_block. // LocalToAncestorRect returns rects wrt containing_block.
void NGPhysicalContainerFragment::AddOutlineRectsForDescendant( void NGPhysicalContainerFragment::AddOutlineRectsForDescendant(
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
namespace blink { namespace blink {
class NGContainerFragmentBuilder; class NGContainerFragmentBuilder;
class NGFragmentItem;
struct NGPhysicalOutOfFlowPositionedNode; struct NGPhysicalOutOfFlowPositionedNode;
enum class NGOutlineType; enum class NGOutlineType;
...@@ -149,6 +150,19 @@ class CORE_EXPORT NGPhysicalContainerFragment : public NGPhysicalFragment { ...@@ -149,6 +150,19 @@ class CORE_EXPORT NGPhysicalContainerFragment : public NGPhysicalFragment {
NGFragmentType, NGFragmentType,
unsigned sub_type); unsigned sub_type);
void AddScrollableOverflowForInlineChild(
const NGPhysicalBoxFragment& container,
const ComputedStyle& container_style,
const NGFragmentItem& line,
bool has_hanging,
const NGInlineCursor& cursor,
PhysicalRect* overflow) const;
static void AdjustScrollableOverflowForHanging(
const PhysicalRect& rect,
const WritingMode container_writing_mode,
PhysicalRect* overflow);
void AddOutlineRectsForNormalChildren( void AddOutlineRectsForNormalChildren(
Vector<PhysicalRect>* outline_rects, Vector<PhysicalRect>* outline_rects,
const PhysicalOffset& additional_offset, const PhysicalOffset& additional_offset,
......
...@@ -417,10 +417,16 @@ PhysicalRect NGPhysicalFragment::ScrollableOverflow() const { ...@@ -417,10 +417,16 @@ PhysicalRect NGPhysicalFragment::ScrollableOverflow() const {
PhysicalRect NGPhysicalFragment::ScrollableOverflowForPropagation( PhysicalRect NGPhysicalFragment::ScrollableOverflowForPropagation(
const NGPhysicalBoxFragment& container) const { const NGPhysicalBoxFragment& container) const {
PhysicalRect overflow = ScrollableOverflow(); PhysicalRect overflow = ScrollableOverflow();
AdjustScrollableOverflowForPropagation(container, &overflow);
return overflow;
}
void NGPhysicalFragment::AdjustScrollableOverflowForPropagation(
const NGPhysicalBoxFragment& container,
PhysicalRect* overflow) const {
DCHECK(!IsLineBox()); DCHECK(!IsLineBox());
if (!IsCSSBox()) if (!IsCSSBox())
return overflow; return;
const LayoutObject* layout_object = GetLayoutObject(); const LayoutObject* layout_object = GetLayoutObject();
DCHECK(layout_object); DCHECK(layout_object);
...@@ -430,10 +436,9 @@ PhysicalRect NGPhysicalFragment::ScrollableOverflowForPropagation( ...@@ -430,10 +436,9 @@ PhysicalRect NGPhysicalFragment::ScrollableOverflowForPropagation(
TransformationMatrix transform; TransformationMatrix transform;
layout_object->GetTransformFromContainer(container_layout_object, layout_object->GetTransformFromContainer(container_layout_object,
PhysicalOffset(), transform); PhysicalOffset(), transform);
overflow = *overflow =
PhysicalRect::EnclosingRect(transform.MapRect(FloatRect(overflow))); PhysicalRect::EnclosingRect(transform.MapRect(FloatRect(*overflow)));
} }
return overflow;
} }
const Vector<NGInlineItem>& NGPhysicalFragment::InlineItemsOfContainingBlock() const Vector<NGInlineItem>& NGPhysicalFragment::InlineItemsOfContainingBlock()
......
...@@ -278,6 +278,9 @@ class CORE_EXPORT NGPhysicalFragment ...@@ -278,6 +278,9 @@ class CORE_EXPORT NGPhysicalFragment
// This does not include any offsets from the parent (including relpos). // This does not include any offsets from the parent (including relpos).
PhysicalRect ScrollableOverflowForPropagation( PhysicalRect ScrollableOverflowForPropagation(
const NGPhysicalBoxFragment& container) const; const NGPhysicalBoxFragment& container) const;
void AdjustScrollableOverflowForPropagation(
const NGPhysicalBoxFragment& container,
PhysicalRect* overflow) const;
// The allowed touch action is the union of the effective touch action // The allowed touch action is the union of the effective touch action
// (from style) and blocking touch event handlers. // (from style) and blocking touch event handlers.
......
...@@ -19,7 +19,6 @@ crbug.com/982194 external/wpt/css/CSS2/floats/floats-rule7-outside-left-001.xht ...@@ -19,7 +19,6 @@ crbug.com/982194 external/wpt/css/CSS2/floats/floats-rule7-outside-left-001.xht
crbug.com/982194 external/wpt/css/CSS2/floats/floats-rule7-outside-right-001.xht [ Failure ] crbug.com/982194 external/wpt/css/CSS2/floats/floats-rule7-outside-right-001.xht [ Failure ]
crbug.com/982194 external/wpt/css/css-contain/contain-layout-017.html [ Failure ] crbug.com/982194 external/wpt/css/css-contain/contain-layout-017.html [ Failure ]
crbug.com/982194 external/wpt/css/css-contain/contain-paint-021.html [ Failure ] crbug.com/982194 external/wpt/css/css-contain/contain-paint-021.html [ Failure ]
crbug.com/982194 external/wpt/css/css-overflow/overflow-inline-transform-relative.html [ Failure ]
crbug.com/984438 external/wpt/css/css-scroll-snap/snap-at-user-scroll-end-manual.html [ Failure ] crbug.com/984438 external/wpt/css/css-scroll-snap/snap-at-user-scroll-end-manual.html [ Failure ]
crbug.com/982194 external/wpt/css/css-text-decor/text-decoration-color.html [ Failure ] crbug.com/982194 external/wpt/css/css-text-decor/text-decoration-color.html [ Failure ]
crbug.com/949909 external/wpt/css/css-text-decor/text-emphasis-color-001.xht [ Failure ] crbug.com/949909 external/wpt/css/css-text-decor/text-emphasis-color-001.xht [ Failure ]
......
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