Commit 4f295c5b authored by Morten Stenshorne's avatar Morten Stenshorne Committed by Commit Bot

[LayoutNG] Fragment traversal of LayoutObject-less fragments.

This code won't encounter any such fragments currently, but multicol
(and maybe also tables) will need this.

Bug: 1043787
Change-Id: Id043e1b2a1579422572626860eec230f61161cf5
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2107541Reviewed-by: default avatarIan Kilpatrick <ikilpatrick@chromium.org>
Reviewed-by: default avatarXianzhu Wang <wangxianzhu@chromium.org>
Reviewed-by: default avatarAleks Totic <atotic@chromium.org>
Commit-Queue: Morten Stenshorne <mstensho@chromium.org>
Cr-Commit-Position: refs/heads/master@{#751260}
parent f2a782dc
...@@ -124,6 +124,14 @@ class CORE_EXPORT NGPhysicalBoxFragment final ...@@ -124,6 +124,14 @@ class CORE_EXPORT NGPhysicalBoxFragment final
// Compute visual overflow of this box in the local coordinate. // Compute visual overflow of this box in the local coordinate.
PhysicalRect ComputeSelfInkOverflow() const; PhysicalRect ComputeSelfInkOverflow() const;
// Contents ink overflow includes anything that would bleed out of the box and
// would be clipped by the overflow clip ('overflow' != visible). This
// corresponds to children that overflows their parent.
PhysicalRect ContentsInkOverflow() const {
// TODO(layout-dev): Implement box fragment overflow.
return LocalRect();
}
// Fragment offset is this fragment's offset from parent. // Fragment offset is this fragment's offset from parent.
// Needed to compensate for LayoutInline Legacy code offsets. // Needed to compensate for LayoutInline Legacy code offsets.
void AddSelfOutlineRects(const PhysicalOffset& additional_offset, void AddSelfOutlineRects(const PhysicalOffset& additional_offset,
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
#include "third_party/blink/renderer/core/layout/geometry/physical_offset.h" #include "third_party/blink/renderer/core/layout/geometry/physical_offset.h"
#include "third_party/blink/renderer/core/layout/geometry/physical_rect.h" #include "third_party/blink/renderer/core/layout/geometry/physical_rect.h"
#include "third_party/blink/renderer/core/layout/geometry/physical_size.h" #include "third_party/blink/renderer/core/layout/geometry/physical_size.h"
#include "third_party/blink/renderer/core/layout/layout_object.h" #include "third_party/blink/renderer/core/layout/layout_box.h"
#include "third_party/blink/renderer/core/layout/ng/ng_style_variant.h" #include "third_party/blink/renderer/core/layout/ng/ng_style_variant.h"
#include "third_party/blink/renderer/platform/graphics/touch_action.h" #include "third_party/blink/renderer/platform/graphics/touch_action.h"
#include "third_party/blink/renderer/platform/wtf/ref_counted.h" #include "third_party/blink/renderer/platform/wtf/ref_counted.h"
...@@ -210,6 +210,17 @@ class CORE_EXPORT NGPhysicalFragment ...@@ -210,6 +210,17 @@ class CORE_EXPORT NGPhysicalFragment
// from GetNode() when this fragment is content of a pseudo node. // from GetNode() when this fragment is content of a pseudo node.
Node* NodeForHitTest() const { return layout_object_->NodeForHitTest(); } Node* NodeForHitTest() const { return layout_object_->NodeForHitTest(); }
bool IsInSelfHitTestingPhase(HitTestAction action) const {
if (const auto* box = ToLayoutBoxOrNull(GetLayoutObject()))
return box->IsInSelfHitTestingPhase(action);
if (IsInlineBox())
return action == kHitTestForeground;
// Assuming this is some sort of container, e.g. a fragmentainer (they don't
// have a LayoutObject associated).
return action == kHitTestBlockBackground ||
action == kHitTestChildBlockBackground;
}
// Whether there is a PaintLayer associated with the fragment. // Whether there is a PaintLayer associated with the fragment.
bool HasLayer() const { return IsCSSBox() && layout_object_->HasLayer(); } bool HasLayer() const { return IsCSSBox() && layout_object_->HasLayer(); }
...@@ -273,6 +284,11 @@ class CORE_EXPORT NGPhysicalFragment ...@@ -273,6 +284,11 @@ class CORE_EXPORT NGPhysicalFragment
// check if there were newer generations. // check if there were newer generations.
const NGPhysicalFragment* PostLayout() const; const NGPhysicalFragment* PostLayout() const;
PhysicalRect InkOverflow() const {
// TODO(layout-dev): Implement box fragment overflow.
return LocalRect();
}
// Scrollable overflow. including contents, in the local coordinate. // Scrollable overflow. including contents, in the local coordinate.
PhysicalRect ScrollableOverflow() const; PhysicalRect ScrollableOverflow() const;
......
...@@ -297,9 +297,9 @@ PhysicalRect NGBoxFragmentPainter::SelfInkOverflow() const { ...@@ -297,9 +297,9 @@ PhysicalRect NGBoxFragmentPainter::SelfInkOverflow() const {
} }
PhysicalRect NGBoxFragmentPainter::ContentsInkOverflow() const { PhysicalRect NGBoxFragmentPainter::ContentsInkOverflow() const {
const NGPhysicalFragment& fragment = PhysicalFragment(); if (const LayoutObject* layout_object = box_fragment_.GetLayoutObject())
return ToLayoutBox(fragment.GetLayoutObject()) return ToLayoutBox(layout_object)->PhysicalContentsVisualOverflowRect();
->PhysicalContentsVisualOverflowRect(); return box_fragment_.ContentsInkOverflow();
} }
void NGBoxFragmentPainter::Paint(const PaintInfo& paint_info) { void NGBoxFragmentPainter::Paint(const PaintInfo& paint_info) {
...@@ -490,7 +490,7 @@ void NGBoxFragmentPainter::PaintObject( ...@@ -490,7 +490,7 @@ void NGBoxFragmentPainter::PaintObject(
paint_offset); paint_offset);
} }
} else { } else {
PaintBlockChildren(paint_info); PaintBlockChildren(paint_info, paint_offset);
} }
} }
...@@ -537,7 +537,8 @@ void NGBoxFragmentPainter::PaintBlockFlowContents( ...@@ -537,7 +537,8 @@ void NGBoxFragmentPainter::PaintBlockFlowContents(
// When the layout-tree gets into a bad state, we can end up trying to paint // When the layout-tree gets into a bad state, we can end up trying to paint
// a fragment with inline children, without a paint fragment. See: // a fragment with inline children, without a paint fragment. See:
// http://crbug.com/1022545 // http://crbug.com/1022545
if ((!paint_fragment_ && !items_) || layout_object->NeedsLayout()) { if ((!paint_fragment_ && !items_) ||
(layout_object && layout_object->NeedsLayout())) {
NOTREACHED(); NOTREACHED();
return; return;
} }
...@@ -560,9 +561,6 @@ void NGBoxFragmentPainter::PaintBlockFlowContents( ...@@ -560,9 +561,6 @@ void NGBoxFragmentPainter::PaintBlockFlowContents(
if (!paint_info.GetCullRect().Intersects(content_ink_rect.ToLayoutRect())) if (!paint_info.GetCullRect().Intersects(content_ink_rect.ToLayoutRect()))
return; return;
DCHECK(layout_object->IsLayoutBlockFlow());
const auto& layout_block = To<LayoutBlock>(*layout_object);
DCHECK(layout_block.ChildrenInline());
if (paint_fragment_) { if (paint_fragment_) {
NGInlineCursor children(*paint_fragment_); NGInlineCursor children(*paint_fragment_);
PaintLineBoxChildren(&children, paint_info.ForDescendants(), paint_offset); PaintLineBoxChildren(&children, paint_info.ForDescendants(), paint_offset);
...@@ -573,7 +571,8 @@ void NGBoxFragmentPainter::PaintBlockFlowContents( ...@@ -573,7 +571,8 @@ void NGBoxFragmentPainter::PaintBlockFlowContents(
PaintLineBoxChildren(&children, paint_info.ForDescendants(), paint_offset); PaintLineBoxChildren(&children, paint_info.ForDescendants(), paint_offset);
} }
void NGBoxFragmentPainter::PaintBlockChildren(const PaintInfo& paint_info) { void NGBoxFragmentPainter::PaintBlockChildren(const PaintInfo& paint_info,
PhysicalOffset paint_offset) {
DCHECK(!box_fragment_.IsInlineFormattingContext()); DCHECK(!box_fragment_.IsInlineFormattingContext());
PaintInfo paint_info_for_descendants = paint_info.ForDescendants(); PaintInfo paint_info_for_descendants = paint_info.ForDescendants();
for (const NGLink& child : box_fragment_.Children()) { for (const NGLink& child : box_fragment_.Children()) {
...@@ -585,6 +584,19 @@ void NGBoxFragmentPainter::PaintBlockChildren(const PaintInfo& paint_info) { ...@@ -585,6 +584,19 @@ void NGBoxFragmentPainter::PaintBlockChildren(const PaintInfo& paint_info) {
const auto& box_child_fragment = To<NGPhysicalBoxFragment>(child_fragment); const auto& box_child_fragment = To<NGPhysicalBoxFragment>(child_fragment);
if (box_child_fragment.CanTraverse()) { if (box_child_fragment.CanTraverse()) {
if (!box_child_fragment.GetLayoutObject()) {
// It's normally FragmentData that provides us with the paint offset.
// FragmentData is (at least currently) associated with a LayoutObject.
// If we have no LayoutObject, we have no FragmentData, so we need to
// calculate the offset on our own (which is very simple, anyway).
// Bypass Paint() and jump directly to PaintObject(), to skip the code
// that assumes that we have a LayoutObject (and FragmentData).
PhysicalOffset child_offset = paint_offset + child.offset;
NGBoxFragmentPainter(box_child_fragment)
.PaintObject(paint_info, child_offset);
continue;
}
NGBoxFragmentPainter(box_child_fragment) NGBoxFragmentPainter(box_child_fragment)
.Paint(paint_info_for_descendants); .Paint(paint_info_for_descendants);
continue; continue;
...@@ -1207,7 +1219,7 @@ void NGBoxFragmentPainter::PaintLineBoxChildren( ...@@ -1207,7 +1219,7 @@ void NGBoxFragmentPainter::PaintLineBoxChildren(
// The only way an inline could paint like this is if it has a layer. // The only way an inline could paint like this is if it has a layer.
const auto* layout_object = box_fragment_.GetLayoutObject(); const auto* layout_object = box_fragment_.GetLayoutObject();
DCHECK(layout_object->IsLayoutBlock() || DCHECK(!layout_object || layout_object->IsLayoutBlock() ||
(layout_object->IsLayoutInline() && layout_object->HasLayer())); (layout_object->IsLayoutInline() && layout_object->HasLayer()));
// if (paint_info.phase == PaintPhase::kForeground && paint_info.IsPrinting()) // if (paint_info.phase == PaintPhase::kForeground && paint_info.IsPrinting())
...@@ -1219,7 +1231,7 @@ void NGBoxFragmentPainter::PaintLineBoxChildren( ...@@ -1219,7 +1231,7 @@ void NGBoxFragmentPainter::PaintLineBoxChildren(
return; return;
if (paint_info.phase == PaintPhase::kForcedColorsModeBackplate && if (paint_info.phase == PaintPhase::kForcedColorsModeBackplate &&
layout_object->GetDocument().InForcedColorsMode()) { box_fragment_.GetDocument().InForcedColorsMode()) {
PaintBackplate(children, paint_info, paint_offset); PaintBackplate(children, paint_info, paint_offset);
return; return;
} }
...@@ -1629,14 +1641,6 @@ BoxPainterBase::FillLayerInfo NGBoxFragmentPainter::GetFillLayerInfo( ...@@ -1629,14 +1641,6 @@ BoxPainterBase::FillLayerInfo NGBoxFragmentPainter::GetFillLayerInfo(
is_painting_scrolling_background); is_painting_scrolling_background);
} }
bool NGBoxFragmentPainter::IsInSelfHitTestingPhase(HitTestAction action) const {
// TODO(layout-dev): We should set an IsContainingBlock flag on
// NGPhysicalBoxFragment, instead of routing back to LayoutObject.
if (const auto* box = ToLayoutBoxOrNull(PhysicalFragment().GetLayoutObject()))
return box->IsInSelfHitTestingPhase(action);
return action == kHitTestForeground;
}
bool NGBoxFragmentPainter::HitTestContext::AddNodeToResult( bool NGBoxFragmentPainter::HitTestContext::AddNodeToResult(
Node* node, Node* node,
const PhysicalRect& bounds_rect, const PhysicalRect& bounds_rect,
...@@ -1661,14 +1665,16 @@ bool NGBoxFragmentPainter::NodeAtPoint(const HitTestContext& hit_test, ...@@ -1661,14 +1665,16 @@ bool NGBoxFragmentPainter::NodeAtPoint(const HitTestContext& hit_test,
const PhysicalSize& size = box_fragment_.Size(); const PhysicalSize& size = box_fragment_.Size();
const ComputedStyle& style = box_fragment_.Style(); const ComputedStyle& style = box_fragment_.Style();
bool hit_test_self = IsInSelfHitTestingPhase(hit_test.action); bool hit_test_self = fragment.IsInSelfHitTestingPhase(hit_test.action);
if (hit_test_self && box_fragment_.HasOverflowClip() && if (hit_test_self && box_fragment_.HasOverflowClip() &&
HitTestOverflowControl(hit_test, physical_offset)) HitTestOverflowControl(hit_test, physical_offset))
return true; return true;
bool skip_children = hit_test.result->GetHitTestRequest().GetStopNode() == const LayoutObject* layout_object = PhysicalFragment().GetLayoutObject();
PhysicalFragment().GetLayoutObject(); bool skip_children =
layout_object &&
layout_object == hit_test.result->GetHitTestRequest().GetStopNode();
if (!skip_children && box_fragment_.ShouldClipOverflow()) { if (!skip_children && box_fragment_.ShouldClipOverflow()) {
// PaintLayer::HitTestContentsForFragments checked the fragments' // PaintLayer::HitTestContentsForFragments checked the fragments'
// foreground rect for intersection if a layer is self painting, // foreground rect for intersection if a layer is self painting,
......
...@@ -109,7 +109,7 @@ class NGBoxFragmentPainter : public BoxPainterBase { ...@@ -109,7 +109,7 @@ class NGBoxFragmentPainter : public BoxPainterBase {
void PaintInternal(const PaintInfo&); void PaintInternal(const PaintInfo&);
void PaintAllPhasesAtomically(const PaintInfo&); void PaintAllPhasesAtomically(const PaintInfo&);
void PaintBlockChildren(const PaintInfo&); void PaintBlockChildren(const PaintInfo&, PhysicalOffset);
void PaintInlineItems(const PaintInfo&, void PaintInlineItems(const PaintInfo&,
const PhysicalOffset& paint_offset, const PhysicalOffset& paint_offset,
const PhysicalOffset& parent_offset, const PhysicalOffset& parent_offset,
...@@ -176,7 +176,6 @@ class NGBoxFragmentPainter : public BoxPainterBase { ...@@ -176,7 +176,6 @@ class NGBoxFragmentPainter : public BoxPainterBase {
bool ShouldRecordHitTestData(const PaintInfo&); bool ShouldRecordHitTestData(const PaintInfo&);
bool IsInSelfHitTestingPhase(HitTestAction) const;
bool VisibleToHitTestRequest(const HitTestRequest&) const; bool VisibleToHitTestRequest(const HitTestRequest&) const;
// This struct has common data needed while traversing trees for the hit // This struct has common data needed while traversing trees for the hit
......
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