Commit f98d25da authored by Koji Ishii's avatar Koji Ishii Committed by Chromium LUCI CQ

Add |NGPhysicalBoxFragment::IsOutlineOwner|

This patch adds |NGPhysicalBoxFragment::IsOutlineOwner|, by
moving the logic from a static function in |NGOutlineUtils|.

By exposing the |InlineContainerFragmentIfOutlineOwner|,
|AddOutlineRectsForInlineBox| no longer needs to traverse
all fragments. Instead, it now creates an |NGInlineCursor|
only for the container fragment.

This patch has no behavior changes.

Bug: 1145048
Change-Id: Ia4a084d5708d870a38800bed3494bcd869daf175
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2567842
Auto-Submit: Koji Ishii <kojii@chromium.org>
Reviewed-by: default avatarYoshifumi Inoue <yosin@chromium.org>
Reviewed-by: default avatarKent Tamura <tkent@chromium.org>
Commit-Queue: Kent Tamura <tkent@chromium.org>
Commit-Queue: Koji Ishii <kojii@chromium.org>
Cr-Commit-Position: refs/heads/master@{#832693}
parent 9c3ad397
...@@ -21,35 +21,4 @@ bool NGOutlineUtils::HasPaintedOutline(const ComputedStyle& style, ...@@ -21,35 +21,4 @@ bool NGOutlineUtils::HasPaintedOutline(const ComputedStyle& style,
return true; return true;
} }
bool NGOutlineUtils::ShouldPaintOutline(
const NGPhysicalBoxFragment& physical_fragment) {
if (!physical_fragment.IsInlineBox())
return true;
// In order to compute united outlines, collect all rectangles of inline
// fragments for |LayoutInline| if |this| is the first inline fragment.
// Otherwise return none.
const LayoutObject* layout_object = physical_fragment.GetLayoutObject();
DCHECK(layout_object);
DCHECK(layout_object->IsLayoutInline());
NGInlineCursor cursor;
cursor.MoveTo(*layout_object);
DCHECK(cursor);
if (cursor.Current().BoxFragment() == &physical_fragment)
return true;
if (!cursor.IsBlockFragmented())
return false;
// When |LayoutInline| is block fragmented, unite rectangles for each block
// fragment. To do this, return |true| if |this| is the first inline fragment
// of a block fragment.
while (true) {
wtf_size_t fragment_index = cursor.ContainerFragmentIndex();
cursor.MoveToNextForSameLayoutObject();
DCHECK(cursor);
if (cursor.Current().BoxFragment() == &physical_fragment)
return fragment_index != cursor.ContainerFragmentIndex();
}
}
} // namespace blink } // namespace blink
...@@ -12,19 +12,12 @@ namespace blink { ...@@ -12,19 +12,12 @@ namespace blink {
class ComputedStyle; class ComputedStyle;
class Node; class Node;
class NGPhysicalBoxFragment;
class CORE_EXPORT NGOutlineUtils { class CORE_EXPORT NGOutlineUtils {
STATIC_ONLY(NGOutlineUtils); STATIC_ONLY(NGOutlineUtils);
public: public:
static bool HasPaintedOutline(const ComputedStyle& style, const Node* node); static bool HasPaintedOutline(const ComputedStyle& style, const Node* node);
// Returns true if this fragment should paint an outline.
//
// Specifically a |LayoutInline| can be split across multiple flows. The
// first fragment produced should paint the outline for *all* fragments.
static bool ShouldPaintOutline(const NGPhysicalBoxFragment&);
}; };
} // namespace blink } // namespace blink
......
...@@ -653,6 +653,39 @@ PhysicalSize NGPhysicalBoxFragment::ScrollSize() const { ...@@ -653,6 +653,39 @@ PhysicalSize NGPhysicalBoxFragment::ScrollSize() const {
return {box->ScrollWidth(), box->ScrollHeight()}; return {box->ScrollWidth(), box->ScrollHeight()};
} }
const NGPhysicalBoxFragment*
NGPhysicalBoxFragment::InlineContainerFragmentIfOutlineOwner() const {
DCHECK(IsInlineBox());
// In order to compute united outlines, collect all rectangles of inline
// fragments for |LayoutInline| if |this| is the first inline fragment.
// Otherwise return none.
const LayoutObject* layout_object = GetLayoutObject();
DCHECK(layout_object);
DCHECK(layout_object->IsLayoutInline());
NGInlineCursor cursor;
cursor.MoveTo(*layout_object);
DCHECK(cursor);
if (cursor.Current().BoxFragment() == this)
return &cursor.ContainerFragment();
if (!cursor.IsBlockFragmented())
return nullptr;
// When |LayoutInline| is block fragmented, unite rectangles for each block
// fragment. To do this, return |true| if |this| is the first inline fragment
// of a block fragment.
for (wtf_size_t previous_fragment_index = cursor.ContainerFragmentIndex();;) {
cursor.MoveToNextForSameLayoutObject();
DCHECK(cursor);
const wtf_size_t fragment_index = cursor.ContainerFragmentIndex();
if (cursor.Current().BoxFragment() == this) {
if (fragment_index != previous_fragment_index)
return &cursor.ContainerFragment();
return nullptr;
}
previous_fragment_index = fragment_index;
}
}
PhysicalRect NGPhysicalBoxFragment::ComputeSelfInkOverflow() const { PhysicalRect NGPhysicalBoxFragment::ComputeSelfInkOverflow() const {
DCHECK_EQ(PostLayout(), this); DCHECK_EQ(PostLayout(), this);
CheckCanUpdateInkOverflow(); CheckCanUpdateInkOverflow();
...@@ -663,8 +696,7 @@ PhysicalRect NGPhysicalBoxFragment::ComputeSelfInkOverflow() const { ...@@ -663,8 +696,7 @@ PhysicalRect NGPhysicalBoxFragment::ComputeSelfInkOverflow() const {
DCHECK(GetLayoutObject()); DCHECK(GetLayoutObject());
PhysicalRect ink_overflow(LocalRect()); PhysicalRect ink_overflow(LocalRect());
ink_overflow.Expand(style.BoxDecorationOutsets()); ink_overflow.Expand(style.BoxDecorationOutsets());
if (NGOutlineUtils::HasPaintedOutline(style, GetNode()) && if (NGOutlineUtils::HasPaintedOutline(style, GetNode()) && IsOutlineOwner()) {
NGOutlineUtils::ShouldPaintOutline(*this)) {
Vector<PhysicalRect> outline_rects; Vector<PhysicalRect> outline_rects;
// The result rects are in coordinates of this object's border box. // The result rects are in coordinates of this object's border box.
AddSelfOutlineRects(PhysicalOffset(), AddSelfOutlineRects(PhysicalOffset(),
...@@ -705,7 +737,7 @@ void NGPhysicalBoxFragment::AddOutlineRects( ...@@ -705,7 +737,7 @@ void NGPhysicalBoxFragment::AddOutlineRects(
inline_container_relative, outline_rects); inline_container_relative, outline_rects);
return; return;
} }
DCHECK(NGOutlineUtils::ShouldPaintOutline(*this)); DCHECK(IsOutlineOwner());
// For anonymous blocks, the children add outline rects. // For anonymous blocks, the children add outline rects.
if (!IsAnonymousBlock()) if (!IsAnonymousBlock())
...@@ -743,7 +775,9 @@ void NGPhysicalBoxFragment::AddOutlineRectsForInlineBox( ...@@ -743,7 +775,9 @@ void NGPhysicalBoxFragment::AddOutlineRectsForInlineBox(
DCHECK_EQ(PostLayout(), this); DCHECK_EQ(PostLayout(), this);
DCHECK(IsInlineBox()); DCHECK(IsInlineBox());
if (!NGOutlineUtils::ShouldPaintOutline(*this)) const NGPhysicalBoxFragment* container =
InlineContainerFragmentIfOutlineOwner();
if (!container)
return; return;
// In order to compute united outlines, collect all rectangles of inline // In order to compute united outlines, collect all rectangles of inline
...@@ -756,27 +790,17 @@ void NGPhysicalBoxFragment::AddOutlineRectsForInlineBox( ...@@ -756,27 +790,17 @@ void NGPhysicalBoxFragment::AddOutlineRectsForInlineBox(
DCHECK(GetLayoutObject()->IsLayoutInline()); DCHECK(GetLayoutObject()->IsLayoutInline());
const auto* layout_object = To<LayoutInline>(GetLayoutObject()); const auto* layout_object = To<LayoutInline>(GetLayoutObject());
const wtf_size_t initial_rects_size = rects->size(); const wtf_size_t initial_rects_size = rects->size();
NGInlineCursor cursor; NGInlineCursor cursor(*container);
cursor.MoveTo(*layout_object); cursor.MoveTo(*layout_object);
DCHECK(cursor); DCHECK(cursor);
wtf_size_t fragment_index = cursor.ContainerFragmentIndex(); #if DCHECK_IS_ON()
bool has_this_fragment = false; bool has_this_fragment = false;
for (;; cursor.MoveToNextForSameLayoutObject()) { #endif
if (!cursor) { for (; cursor; cursor.MoveToNextForSameLayoutObject()) {
DCHECK(has_this_fragment);
break;
}
if (fragment_index != cursor.ContainerFragmentIndex()) {
// If this block fragment has |this|, exit the loop.
if (has_this_fragment)
break;
// Otherwise clear the result and continue to the next block fragment.
fragment_index = cursor.ContainerFragmentIndex();
rects->Shrink(initial_rects_size);
}
const NGInlineCursorPosition& current = cursor.Current(); const NGInlineCursorPosition& current = cursor.Current();
#if DCHECK_IS_ON()
has_this_fragment = has_this_fragment || current.BoxFragment() == this; has_this_fragment = has_this_fragment || current.BoxFragment() == this;
#endif
if (!current.Size().IsZero()) if (!current.Size().IsZero())
rects->push_back(current.RectInContainerFragment()); rects->push_back(current.RectInContainerFragment());
...@@ -787,6 +811,9 @@ void NGPhysicalBoxFragment::AddOutlineRectsForInlineBox( ...@@ -787,6 +811,9 @@ void NGPhysicalBoxFragment::AddOutlineRectsForInlineBox(
AddOutlineRectsForCursor(rects, PhysicalOffset(), outline_type, AddOutlineRectsForCursor(rects, PhysicalOffset(), outline_type,
layout_object, &descendants); layout_object, &descendants);
} }
#if DCHECK_IS_ON()
DCHECK(has_this_fragment);
#endif
DCHECK_GE(rects->size(), initial_rects_size); DCHECK_GE(rects->size(), initial_rects_size);
if (rects->size() <= initial_rects_size) if (rects->size() <= initial_rects_size)
return; return;
......
...@@ -226,6 +226,13 @@ class CORE_EXPORT NGPhysicalBoxFragment final ...@@ -226,6 +226,13 @@ class CORE_EXPORT NGPhysicalBoxFragment final
const HitTestLocation& hit_test_location, const HitTestLocation& hit_test_location,
const PhysicalOffset& accumulated_offset) const; const PhysicalOffset& accumulated_offset) const;
// In order to paint united outline rectangles, the "owner" fragment paints
// outlines for non-owner fragments.
bool IsOutlineOwner() const {
return !IsInlineBox() || InlineContainerFragmentIfOutlineOwner();
}
const NGPhysicalBoxFragment* InlineContainerFragmentIfOutlineOwner() const;
// Returns the |ComputedStyle| to use for painting outlines. When |this| is // Returns the |ComputedStyle| to use for painting outlines. When |this| is
// a block in a continuation-chain, it may need to paint outlines if its // a block in a continuation-chain, it may need to paint outlines if its
// ancestor inline boxes in the DOM tree has outlines. // ancestor inline boxes in the DOM tree has outlines.
......
...@@ -12,7 +12,6 @@ ...@@ -12,7 +12,6 @@
#include "third_party/blink/renderer/core/layout/ng/inline/ng_ruby_utils.h" #include "third_party/blink/renderer/core/layout/ng/inline/ng_ruby_utils.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_layout_overflow_calculator.h" #include "third_party/blink/renderer/core/layout/ng/ng_layout_overflow_calculator.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/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"
...@@ -360,7 +359,7 @@ void NGPhysicalContainerFragment::AddOutlineRectsForDescendant( ...@@ -360,7 +359,7 @@ void NGPhysicalContainerFragment::AddOutlineRectsForDescendant(
// for its line box which cover the line boxes of this LayoutInline. So // for its line box which cover the line boxes of this LayoutInline. So
// the LayoutInline needs to add rects for children and continuations // the LayoutInline needs to add rects for children and continuations
// only. // only.
if (NGOutlineUtils::ShouldPaintOutline(*descendant_box)) { if (descendant_box->IsOutlineOwner()) {
// We don't pass additional_offset here because the function requires // We don't pass additional_offset here because the function requires
// additional_offset to be the offset from the containing block. // additional_offset to be the offset from the containing block.
descendant_layout_inline->AddOutlineRectsForChildrenAndContinuations( descendant_layout_inline->AddOutlineRectsForChildrenAndContinuations(
......
...@@ -25,7 +25,6 @@ ...@@ -25,7 +25,6 @@
#include "third_party/blink/renderer/core/layout/ng/ng_fragment.h" #include "third_party/blink/renderer/core/layout/ng/ng_fragment.h"
#include "third_party/blink/renderer/core/layout/ng/ng_ink_overflow.h" #include "third_party/blink/renderer/core/layout/ng/ng_ink_overflow.h"
#include "third_party/blink/renderer/core/layout/ng/ng_outline_type.h" #include "third_party/blink/renderer/core/layout/ng/ng_outline_type.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_physical_container_fragment.h" #include "third_party/blink/renderer/core/layout/ng/ng_physical_container_fragment.h"
#include "third_party/blink/renderer/core/layout/ng/ng_physical_fragment.h" #include "third_party/blink/renderer/core/layout/ng/ng_physical_fragment.h"
......
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