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 {
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.
inline void AddInlineSizeToOverflow(const PhysicalRect& rect,
const WritingMode container_writing_mode,
......@@ -139,54 +119,23 @@ PhysicalRect NGPhysicalLineBoxFragment::ScrollableOverflow(
return overflow;
}
PhysicalRect NGPhysicalLineBoxFragment::ScrollableOverflow(
PhysicalRect NGPhysicalLineBoxFragment::ScrollableOverflowForLine(
const NGPhysicalBoxFragment& container,
const ComputedStyle& container_style,
const NGFragmentItem& child,
const NGFragmentItem& line,
const NGInlineCursor& cursor) const {
DCHECK(RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled());
DCHECK_EQ(&child, cursor.CurrentItem());
DCHECK_EQ(child.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;
}
DCHECK_EQ(&line, cursor.CurrentItem());
DCHECK_EQ(line.LineBoxFragment(), this);
// 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();
}
PhysicalRect overflow;
AddScrollableOverflowForInlineChild(container, container_style, line,
has_hanging_, cursor, &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);
return overflow;
......
......@@ -66,10 +66,10 @@ class CORE_EXPORT NGPhysicalLineBoxFragment final
// to resolve relative position of its children.
PhysicalRect ScrollableOverflow(const NGPhysicalBoxFragment& container,
const ComputedStyle& container_style) const;
PhysicalRect ScrollableOverflow(const NGPhysicalBoxFragment& container,
const ComputedStyle& container_style,
const NGFragmentItem& child,
const NGInlineCursor& cursor) const;
PhysicalRect ScrollableOverflowForLine(const NGPhysicalBoxFragment& container,
const ComputedStyle& container_style,
const NGFragmentItem& line,
const NGInlineCursor& cursor) const;
// Whether the content soft-wraps to the next line.
bool HasSoftWrapToNextLine() const;
......
......@@ -268,7 +268,7 @@ PhysicalRect NGPhysicalBoxFragment::ScrollableOverflowFromChildren() const {
const NGPhysicalLineBoxFragment* line_box = child.LineBoxFragment();
DCHECK(line_box);
PhysicalRect child_scrollable_overflow =
line_box->ScrollableOverflow(container, style, child, cursor);
line_box->ScrollableOverflowForLine(container, style, child, cursor);
AddChild(child_scrollable_overflow);
}
......
......@@ -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 {
......@@ -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
// LocalToAncestorRect returns rects wrt containing_block.
void NGPhysicalContainerFragment::AddOutlineRectsForDescendant(
......
......@@ -17,6 +17,7 @@
namespace blink {
class NGContainerFragmentBuilder;
class NGFragmentItem;
struct NGPhysicalOutOfFlowPositionedNode;
enum class NGOutlineType;
......@@ -149,6 +150,19 @@ class CORE_EXPORT NGPhysicalContainerFragment : public NGPhysicalFragment {
NGFragmentType,
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(
Vector<PhysicalRect>* outline_rects,
const PhysicalOffset& additional_offset,
......
......@@ -417,10 +417,16 @@ PhysicalRect NGPhysicalFragment::ScrollableOverflow() const {
PhysicalRect NGPhysicalFragment::ScrollableOverflowForPropagation(
const NGPhysicalBoxFragment& container) const {
PhysicalRect overflow = ScrollableOverflow();
AdjustScrollableOverflowForPropagation(container, &overflow);
return overflow;
}
void NGPhysicalFragment::AdjustScrollableOverflowForPropagation(
const NGPhysicalBoxFragment& container,
PhysicalRect* overflow) const {
DCHECK(!IsLineBox());
if (!IsCSSBox())
return overflow;
return;
const LayoutObject* layout_object = GetLayoutObject();
DCHECK(layout_object);
......@@ -430,10 +436,9 @@ PhysicalRect NGPhysicalFragment::ScrollableOverflowForPropagation(
TransformationMatrix transform;
layout_object->GetTransformFromContainer(container_layout_object,
PhysicalOffset(), transform);
overflow =
PhysicalRect::EnclosingRect(transform.MapRect(FloatRect(overflow)));
*overflow =
PhysicalRect::EnclosingRect(transform.MapRect(FloatRect(*overflow)));
}
return overflow;
}
const Vector<NGInlineItem>& NGPhysicalFragment::InlineItemsOfContainingBlock()
......
......@@ -278,6 +278,9 @@ class CORE_EXPORT NGPhysicalFragment
// This does not include any offsets from the parent (including relpos).
PhysicalRect ScrollableOverflowForPropagation(
const NGPhysicalBoxFragment& container) const;
void AdjustScrollableOverflowForPropagation(
const NGPhysicalBoxFragment& container,
PhysicalRect* overflow) const;
// The allowed touch action is the union of the effective touch action
// (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
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-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/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 ]
......
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