Commit 4870dfc9 authored by Morten Stenshorne's avatar Morten Stenshorne Committed by Commit Bot

[LayoutNG] Only CSS boxes should return non-nullptr for GetLayoutObject().

Using the LayoutObject associated with other (non-CSS box) fragments
(such as lines and columns) is generally wrong. We already had guards
for lines, but not for columns. Had to add a couple of new methods to
the NGPhysicalFragment API.

Also inlined some of the NGPhysicalFragment methods that I changed.

One change:
There used to be a direct call to LayoutObject::IsAnonymous(). I replaced
this with NGPhysicalFragment::IsAnonymousBlock(), which calls
LayoutObject::IsAnonymousBlock() instead of IsAnonymous(). I assume this
is more correct (given the comment where it's used), if it matters at all.

Change-Id: I2fe133fc85c5888adbc303d0d392e65ae548908d
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1913410
Commit-Queue: Morten Stenshorne <mstensho@chromium.org>
Reviewed-by: default avatarKoji Ishii <kojii@chromium.org>
Reviewed-by: default avatarIan Kilpatrick <ikilpatrick@chromium.org>
Cr-Commit-Position: refs/heads/master@{#718089}
parent 6eb2e8d7
...@@ -932,8 +932,9 @@ void NGBlockNode::PlaceChildrenInFlowThread( ...@@ -932,8 +932,9 @@ void NGBlockNode::PlaceChildrenInFlowThread(
const NGPhysicalBoxFragment& physical_fragment) { const NGPhysicalBoxFragment& physical_fragment) {
const NGBlockBreakToken* previous_break_token = nullptr; const NGBlockBreakToken* previous_break_token = nullptr;
for (const auto& child : physical_fragment.Children()) { for (const auto& child : physical_fragment.Children()) {
if (child->GetLayoutObject() != box_) { const LayoutObject* child_object = child->GetLayoutObject();
DCHECK(child->GetLayoutObject()->IsColumnSpanAll()); if (child_object && child_object != box_) {
DCHECK(child_object->IsColumnSpanAll());
CopyChildFragmentPosition(To<NGPhysicalBoxFragment>(*child), child.offset, CopyChildFragmentPosition(To<NGPhysicalBoxFragment>(*child), child.offset,
physical_fragment); physical_fragment);
continue; continue;
......
...@@ -23,10 +23,11 @@ bool NGOutlineUtils::HasPaintedOutline(const ComputedStyle& style, ...@@ -23,10 +23,11 @@ bool NGOutlineUtils::HasPaintedOutline(const ComputedStyle& style,
bool NGOutlineUtils::ShouldPaintOutline( bool NGOutlineUtils::ShouldPaintOutline(
const NGPhysicalBoxFragment& physical_fragment) { const NGPhysicalBoxFragment& physical_fragment) {
if (!physical_fragment.IsInlineBox())
return true;
const LayoutObject* layout_object = physical_fragment.GetLayoutObject(); const LayoutObject* layout_object = physical_fragment.GetLayoutObject();
DCHECK(layout_object); DCHECK(layout_object);
if (!layout_object->IsLayoutInline()) DCHECK(layout_object->IsLayoutInline());
return true;
// A |LayoutInline| can be split across multiple objects. The first fragment // A |LayoutInline| can be split across multiple objects. The first fragment
// produced should paint the outline for *all* fragments. // produced should paint the outline for *all* fragments.
......
...@@ -82,7 +82,7 @@ NGPhysicalBoxFragment::NGPhysicalBoxFragment( ...@@ -82,7 +82,7 @@ NGPhysicalBoxFragment::NGPhysicalBoxFragment(
: kFragmentBox, : kFragmentBox,
builder->BoxType()), builder->BoxType()),
baselines_(builder->baselines_) { baselines_(builder->baselines_) {
DCHECK(GetLayoutObject() && GetLayoutObject()->IsBoxModelObject()); DCHECK(layout_object_->IsBoxModelObject());
if (NGFragmentItemsBuilder* items_builder = builder->ItemsBuilder()) { if (NGFragmentItemsBuilder* items_builder = builder->ItemsBuilder()) {
has_fragment_items_ = true; has_fragment_items_ = true;
NGFragmentItems* items = NGFragmentItems* items =
...@@ -123,6 +123,8 @@ NGPhysicalBoxFragment::CloneAsHiddenForPaint() const { ...@@ -123,6 +123,8 @@ NGPhysicalBoxFragment::CloneAsHiddenForPaint() const {
} }
bool NGPhysicalBoxFragment::HasSelfPaintingLayer() const { bool NGPhysicalBoxFragment::HasSelfPaintingLayer() const {
if (!IsCSSBox())
return false;
SECURITY_DCHECK(GetLayoutObject() && GetLayoutObject()->IsBoxModelObject()); SECURITY_DCHECK(GetLayoutObject() && GetLayoutObject()->IsBoxModelObject());
return (static_cast<const LayoutBoxModelObject*>(GetLayoutObject())) return (static_cast<const LayoutBoxModelObject*>(GetLayoutObject()))
->HasSelfPaintingLayer(); ->HasSelfPaintingLayer();
...@@ -212,9 +214,10 @@ void NGPhysicalBoxFragment::AddSelfOutlineRects( ...@@ -212,9 +214,10 @@ void NGPhysicalBoxFragment::AddSelfOutlineRects(
if (!NGOutlineUtils::ShouldPaintOutline(*this)) if (!NGOutlineUtils::ShouldPaintOutline(*this))
return; return;
const LayoutObject* layout_object = GetLayoutObject(); if (IsInlineBox()) {
DCHECK(layout_object); const LayoutObject* layout_object = GetLayoutObject();
if (layout_object->IsLayoutInline()) { DCHECK(layout_object);
DCHECK(layout_object->IsLayoutInline());
Vector<PhysicalRect> blockflow_outline_rects = Vector<PhysicalRect> blockflow_outline_rects =
layout_object->OutlineRects(PhysicalOffset(), outline_type); layout_object->OutlineRects(PhysicalOffset(), outline_type);
// The rectangles returned are offset from the containing block. We need the // The rectangles returned are offset from the containing block. We need the
...@@ -234,12 +237,11 @@ void NGPhysicalBoxFragment::AddSelfOutlineRects( ...@@ -234,12 +237,11 @@ void NGPhysicalBoxFragment::AddSelfOutlineRects(
} }
return; return;
} }
DCHECK(layout_object->IsBox());
// For anonymous blocks, the children add outline rects. // For anonymous blocks, the children add outline rects.
if (!layout_object->IsAnonymous()) { if (!IsAnonymousBlock())
outline_rects->emplace_back(additional_offset, Size().ToLayoutSize()); outline_rects->emplace_back(additional_offset, Size().ToLayoutSize());
}
if (outline_type == NGOutlineType::kIncludeBlockVisualOverflow && if (outline_type == NGOutlineType::kIncludeBlockVisualOverflow &&
!HasOverflowClip() && !HasControlClip(*this)) { !HasOverflowClip() && !HasControlClip(*this)) {
// Tricky code ahead: we pass a 0,0 additional_offset to // Tricky code ahead: we pass a 0,0 additional_offset to
......
...@@ -126,11 +126,11 @@ void NGPhysicalContainerFragment::AddOutlineRectsForDescendant( ...@@ -126,11 +126,11 @@ void NGPhysicalContainerFragment::AddOutlineRectsForDescendant(
DynamicTo<NGPhysicalBoxFragment>(descendant.get())) { DynamicTo<NGPhysicalBoxFragment>(descendant.get())) {
const LayoutObject* descendant_layout_object = const LayoutObject* descendant_layout_object =
descendant_box->GetLayoutObject(); descendant_box->GetLayoutObject();
DCHECK(descendant_layout_object);
// TODO(layoutng): Explain this check. I assume we need it because layers // TODO(layoutng): Explain this check. I assume we need it because layers
// may have transforms and so we have to go through LocalToAncestorRects? // may have transforms and so we have to go through LocalToAncestorRects?
if (descendant_box->HasLayer()) { if (descendant_box->HasLayer()) {
DCHECK(descendant_layout_object);
Vector<PhysicalRect> layer_outline_rects; Vector<PhysicalRect> layer_outline_rects;
descendant_box->AddSelfOutlineRects(PhysicalOffset(), outline_type, descendant_box->AddSelfOutlineRects(PhysicalOffset(), outline_type,
&layer_outline_rects); &layer_outline_rects);
...@@ -144,12 +144,13 @@ void NGPhysicalContainerFragment::AddOutlineRectsForDescendant( ...@@ -144,12 +144,13 @@ void NGPhysicalContainerFragment::AddOutlineRectsForDescendant(
return; return;
} }
if (descendant_layout_object->IsBox()) { if (!descendant_box->IsInlineBox()) {
descendant_box->AddSelfOutlineRects( descendant_box->AddSelfOutlineRects(
additional_offset + descendant.Offset(), outline_type, outline_rects); additional_offset + descendant.Offset(), outline_type, outline_rects);
return; return;
} }
DCHECK(descendant_layout_object);
DCHECK(descendant_layout_object->IsLayoutInline()); DCHECK(descendant_layout_object->IsLayoutInline());
const LayoutInline* descendant_layout_inline = const LayoutInline* descendant_layout_inline =
ToLayoutInline(descendant_layout_object); ToLayoutInline(descendant_layout_object);
......
...@@ -269,10 +269,6 @@ void NGPhysicalFragment::Destroy() const { ...@@ -269,10 +269,6 @@ void NGPhysicalFragment::Destroy() const {
} }
} }
Node* NGPhysicalFragment::GetNode() const {
return !IsLineBox() ? layout_object_->GetNode() : nullptr;
}
PaintLayer* NGPhysicalFragment::Layer() const { PaintLayer* NGPhysicalFragment::Layer() const {
if (!HasLayer()) if (!HasLayer())
return nullptr; return nullptr;
...@@ -292,27 +288,17 @@ bool NGPhysicalFragment::HasSelfPaintingLayer() const { ...@@ -292,27 +288,17 @@ bool NGPhysicalFragment::HasSelfPaintingLayer() const {
->HasSelfPaintingLayer(); ->HasSelfPaintingLayer();
} }
bool NGPhysicalFragment::HasOverflowClip() const {
return !IsLineBox() && layout_object_->HasOverflowClip();
}
bool NGPhysicalFragment::ShouldClipOverflow() const {
return !IsLineBox() && layout_object_->ShouldClipOverflow();
}
bool NGPhysicalFragment::IsBlockFlow() const { bool NGPhysicalFragment::IsBlockFlow() const {
return !IsLineBox() && layout_object_->IsLayoutBlockFlow(); return !IsLineBox() && layout_object_->IsLayoutBlockFlow();
} }
bool NGPhysicalFragment::IsListMarker() const {
return !IsLineBox() && layout_object_->IsLayoutNGListMarker();
}
bool NGPhysicalFragment::IsPlacedByLayoutNG() const { bool NGPhysicalFragment::IsPlacedByLayoutNG() const {
// TODO(kojii): Move this to a flag for |LayoutNGBlockFlow::UpdateBlockLayout| // TODO(kojii): Move this to a flag for |LayoutNGBlockFlow::UpdateBlockLayout|
// to set. // to set.
if (IsLineBox()) if (IsLineBox())
return false; return false;
if (IsColumnBox())
return true;
const LayoutBlock* container = layout_object_->ContainingBlock(); const LayoutBlock* container = layout_object_->ContainingBlock();
if (!container) if (!container)
return false; return false;
...@@ -396,8 +382,7 @@ void NGPhysicalFragment::CheckType() const { ...@@ -396,8 +382,7 @@ void NGPhysicalFragment::CheckType() const {
void NGPhysicalFragment::CheckCanUpdateInkOverflow() const { void NGPhysicalFragment::CheckCanUpdateInkOverflow() const {
if (!GetLayoutObject()) if (!GetLayoutObject())
return; return;
const DocumentLifecycle& lifecycle = const DocumentLifecycle& lifecycle = GetDocument().Lifecycle();
GetLayoutObject()->GetDocument().Lifecycle();
DCHECK(lifecycle.GetState() >= DocumentLifecycle::kLayoutClean && DCHECK(lifecycle.GetState() >= DocumentLifecycle::kLayoutClean &&
lifecycle.GetState() < DocumentLifecycle::kCompositingClean) lifecycle.GetState() < DocumentLifecycle::kCompositingClean)
<< lifecycle.GetState(); << lifecycle.GetState();
......
...@@ -136,7 +136,12 @@ class CORE_EXPORT NGPhysicalFragment ...@@ -136,7 +136,12 @@ class CORE_EXPORT NGPhysicalFragment
bool IsCSSBox() const { return !IsLineBox() && !IsColumnBox(); } bool IsCSSBox() const { return !IsLineBox() && !IsColumnBox(); }
bool IsBlockFlow() const; bool IsBlockFlow() const;
bool IsListMarker() const; bool IsAnonymousBlock() const {
return IsCSSBox() && layout_object_->IsAnonymousBlock();
}
bool IsListMarker() const {
return IsCSSBox() && layout_object_->IsLayoutNGListMarker();
}
// Return true if this fragment is a container established by a fieldset // Return true if this fragment is a container established by a fieldset
// element. Such a fragment contains an optional rendered legend fragment and // element. Such a fragment contains an optional rendered legend fragment and
...@@ -186,7 +191,17 @@ class CORE_EXPORT NGPhysicalFragment ...@@ -186,7 +191,17 @@ class CORE_EXPORT NGPhysicalFragment
const ComputedStyle& Style() const { const ComputedStyle& Style() const {
return layout_object_->EffectiveStyle(StyleVariant()); return layout_object_->EffectiveStyle(StyleVariant());
} }
Node* GetNode() const;
const Document& GetDocument() const {
DCHECK(layout_object_);
return layout_object_->GetDocument();
}
Node* GetNode() const {
return IsCSSBox() ? layout_object_->GetNode() : nullptr;
}
Node* GeneratingNode() const {
return IsCSSBox() ? layout_object_->GeneratingNode() : nullptr;
}
// 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(); }
...@@ -199,8 +214,13 @@ class CORE_EXPORT NGPhysicalFragment ...@@ -199,8 +214,13 @@ class CORE_EXPORT NGPhysicalFragment
// True if overflow != 'visible', except for certain boxes that do not allow // True if overflow != 'visible', except for certain boxes that do not allow
// overflow clip; i.e., AllowOverflowClip() returns false. // overflow clip; i.e., AllowOverflowClip() returns false.
bool HasOverflowClip() const; bool HasOverflowClip() const {
bool ShouldClipOverflow() const; return IsCSSBox() && layout_object_->HasOverflowClip();
}
bool ShouldClipOverflow() const {
return IsCSSBox() && layout_object_->ShouldClipOverflow();
}
// This fragment is hidden for paint purpose, but exists for querying layout // This fragment is hidden for paint purpose, but exists for querying layout
// information. Used for `text-overflow: ellipsis`. // information. Used for `text-overflow: ellipsis`.
...@@ -213,12 +233,12 @@ class CORE_EXPORT NGPhysicalFragment ...@@ -213,12 +233,12 @@ class CORE_EXPORT NGPhysicalFragment
// returns |nullptr| for the historical reasons. TODO(kojii): We may change // returns |nullptr| for the historical reasons. TODO(kojii): We may change
// this in future. Use |IsLineBox()| instead of testing this is |nullptr|. // this in future. Use |IsLineBox()| instead of testing this is |nullptr|.
const LayoutObject* GetLayoutObject() const { const LayoutObject* GetLayoutObject() const {
return !IsLineBox() ? layout_object_ : nullptr; return IsCSSBox() ? layout_object_ : nullptr;
} }
// TODO(kojii): We should not have mutable version at all, the use of this // TODO(kojii): We should not have mutable version at all, the use of this
// function should be eliminiated over time. // function should be eliminiated over time.
LayoutObject* GetMutableLayoutObject() const { LayoutObject* GetMutableLayoutObject() const {
return !IsLineBox() ? layout_object_ : nullptr; return IsCSSBox() ? layout_object_ : nullptr;
} }
// |NGPhysicalFragment| may live longer than the corresponding |LayoutObject|. // |NGPhysicalFragment| may live longer than the corresponding |LayoutObject|.
......
...@@ -215,9 +215,7 @@ inline NGBoxFragmentPainter::NGBoxFragmentPainter( ...@@ -215,9 +215,7 @@ inline NGBoxFragmentPainter::NGBoxFragmentPainter(
const NGPhysicalBoxFragment& box, const NGPhysicalBoxFragment& box,
const NGPaintFragment* paint_fragment, const NGPaintFragment* paint_fragment,
NGInlineCursor* descendants) NGInlineCursor* descendants)
: BoxPainterBase(&box.GetLayoutObject()->GetDocument(), : BoxPainterBase(&box.GetDocument(), box.Style(), box.GeneratingNode()),
box.Style(),
box.GetLayoutObject()->GeneratingNode()),
box_fragment_(box), box_fragment_(box),
paint_fragment_(paint_fragment), paint_fragment_(paint_fragment),
items_(box.Items()), items_(box.Items()),
...@@ -235,8 +233,9 @@ inline NGBoxFragmentPainter::NGBoxFragmentPainter( ...@@ -235,8 +233,9 @@ inline NGBoxFragmentPainter::NGBoxFragmentPainter(
if (paint_fragment) if (paint_fragment)
DCHECK_EQ(&paint_fragment->PhysicalFragment(), &box); DCHECK_EQ(&paint_fragment->PhysicalFragment(), &box);
} }
} else if (box.GetLayoutObject()->SlowFirstChild() && } else if (box.IsColumnBox() ||
box.GetLayoutObject()->SlowFirstChild()->IsLayoutFlowThread()) { (box.GetLayoutObject()->SlowFirstChild() &&
box.GetLayoutObject()->SlowFirstChild()->IsLayoutFlowThread())) {
// TODO(kojii): NGPaintFragment for multicol has non-inline children // TODO(kojii): NGPaintFragment for multicol has non-inline children
// (kColumnBox). Could this be regular box fragments? // (kColumnBox). Could this be regular box fragments?
} else { } else {
......
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