Commit ad3078c8 authored by Xiaocheng Hu's avatar Xiaocheng Hu Committed by Commit Bot

[LayoutNG] Avoid inline fragment traversal on self-painting inlines

NGInlineFragmentTraversal::SelfFragmentsOf() traverses the entire
inline formatting context's fragment tree to find fragments of a
certain layout object, which is basically unnecessary since we can
locate the paint fragments directly. The only exception is culled
inline, where the layout object doesn't have its own fragments, in
which case we still need to traverse the fragment tree.

As performance optimization, this patch changes SelfFragmentsOf() to
find paint fragments directly, unless the given layout object can be
a culled inline.

With this patch, the time spent on SelfFragmentsOf() when rendering
the single-page HTML5 spec becomes negligible.

Bug: 873798
Cq-Include-Trybots: luci.chromium.try:linux_layout_tests_layout_ng
Change-Id: Id4a9e5a8a8e416e9757916e5ae9cf589c4660688
Reviewed-on: https://chromium-review.googlesource.com/1173725
Commit-Queue: Xiaocheng Hu <xiaochengh@chromium.org>
Reviewed-by: default avatarEmil A Eklund <eae@chromium.org>
Reviewed-by: default avatarYoshifumi Inoue <yosin@chromium.org>
Reviewed-by: default avatarKoji Ishii <kojii@chromium.org>
Cr-Commit-Position: refs/heads/master@{#583499}
parent 46465504
......@@ -7,6 +7,7 @@
#include "third_party/blink/renderer/core/layout/layout_inline.h"
#include "third_party/blink/renderer/core/layout/layout_object.h"
#include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h"
#include "third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h"
namespace blink {
......@@ -181,30 +182,6 @@ class LayoutInlineCollector final : public NGPhysicalFragmentCollectorBase {
DISALLOW_COPY_AND_ASSIGN(LayoutInlineCollector);
};
// The visitor emitting all fragments generated from the given LayoutObject.
class LayoutObjectCollector final : public NGPhysicalFragmentCollectorBase {
STACK_ALLOCATED();
public:
explicit LayoutObjectCollector(const LayoutObject* layout_object)
: target_(layout_object) {}
Vector<Result> CollectFrom(const NGPhysicalFragment& fragment) final {
return CollectExclusivelyFrom(fragment);
}
private:
void Visit() final {
if (GetFragment().GetLayoutObject() == target_)
Emit();
VisitChildren();
}
const LayoutObject* target_;
DISALLOW_COPY_AND_ASSIGN(LayoutObjectCollector);
};
// The visitor emitting ancestors of the given fragment in bottom-up order.
class AncestorCollector : public NGPhysicalFragmentCollectorBase {
STACK_ALLOCATED();
......@@ -271,11 +248,21 @@ class InclusiveAncestorCollector : public NGPhysicalFragmentCollectorBase {
Vector<Result> NGInlineFragmentTraversal::SelfFragmentsOf(
const NGPhysicalContainerFragment& container,
const LayoutObject* layout_object) {
if (layout_object->IsLayoutInline()) {
return LayoutInlineCollector(ToLayoutInline(*layout_object))
.CollectFrom(container);
if (const LayoutInline* layout_inline = ToLayoutInlineOrNull(layout_object)) {
// TODO(crbug.com/874361): Stop partial culling of inline boxes, so that we
// can simply check existence of paint fragments below.
if (!layout_inline->HasSelfPaintingLayer()) {
return LayoutInlineCollector(ToLayoutInline(*layout_object))
.CollectFrom(container);
}
}
Vector<Result> result;
for (const NGPaintFragment* fragment :
NGPaintFragment::InlineFragmentsFor(layout_object)) {
result.push_back(Result{&fragment->PhysicalFragment(),
fragment->InlineOffsetToContainerBox()});
}
return LayoutObjectCollector(layout_object).CollectFrom(container);
return result;
}
// static
......
......@@ -44,6 +44,14 @@ class CORE_EXPORT NGInlineFragmentTraversal {
// Returns list of inline fragments produced from the specified LayoutObject.
// The search is restricted in the subtree of |container|.
// Note: When |target| is a LayoutInline, some/all of its own box fragments
// may be absent from the fragment tree, in which case the nearest box/text
// descendant fragments are returned.
// Note 2: Most callers should use the enclosing block flow fragment of
// |target| as |container|. The only exception is
// LayoutInline::HitTestCulledInline().
// TODO(xiaochengh): As |container| is redundant in most cases, split this
// function into two variants that takes/omits |container|.
static Vector<NGPhysicalFragmentWithOffset> SelfFragmentsOf(
const NGPhysicalContainerFragment& container,
const LayoutObject* target);
......
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