Commit 58605429 authored by Koji Ishii's avatar Koji Ishii Committed by Commit Bot

[LayoutNG] Reduces the size of NGPhysical{Box|Text}Fragment

This patch reduces the size of:
* NGPhysicalBoxFragment by a pointer, by removing |style_|
  from NGPhysicalFragment. This field is used only for line
  box and for ellipsis, and thus it is moved to each
  subclasses.
* NGPhysicalTextFragment by 16 bytes, by moving
  |self_ink_overflow_| and |style_| to RareData. Quick
  investigation shows that |self_ink_overflow_| is different
  from |LocalRect()| in 10-20% of the time (on Linux,
  google.com and a few other sites.)

Change-Id: I225edd42d6d9488611ffe2fa7ef9b11b7e9da4a1
Bug: 635619, 636993
Reviewed-on: https://chromium-review.googlesource.com/c/1331102Reviewed-by: default avatarAleks Totic <atotic@chromium.org>
Reviewed-by: default avatarIan Kilpatrick <ikilpatrick@chromium.org>
Commit-Queue: Koji Ishii <kojii@chromium.org>
Cr-Commit-Position: refs/heads/master@{#607444}
parent 0197d393
......@@ -15,6 +15,11 @@ bool NGPhysicalOffsetRect::operator==(const NGPhysicalOffsetRect& other) const {
return other.offset == offset && other.size == size;
}
bool NGPhysicalOffsetRect::Contains(const NGPhysicalOffsetRect& other) const {
return offset.left <= other.offset.left && offset.top <= other.offset.top &&
Right() >= other.Right() && Bottom() >= other.Bottom();
}
NGPhysicalOffsetRect NGPhysicalOffsetRect::operator+(
const NGPhysicalOffset& offset) const {
return {this->offset + offset, size};
......
......@@ -34,6 +34,8 @@ struct CORE_EXPORT NGPhysicalOffsetRect {
bool operator==(const NGPhysicalOffsetRect& other) const;
bool Contains(const NGPhysicalOffsetRect& other) const;
NGPhysicalOffsetRect operator+(const NGPhysicalOffset&) const;
void Unite(const NGPhysicalOffsetRect&);
......
......@@ -14,6 +14,7 @@ namespace blink {
namespace {
struct SameSizeAsNGPhysicalLineBoxFragment : NGPhysicalContainerFragment {
void* pointer;
NGLineHeightMetrics metrics;
};
......@@ -46,6 +47,7 @@ NGPhysicalLineBoxFragment::NGPhysicalLineBoxFragment(
kFragmentLineBox,
0),
metrics_(builder->metrics_) {
style_ = std::move(builder->style_);
base_direction_ = static_cast<unsigned>(builder->base_direction_);
}
......
......@@ -29,6 +29,7 @@ class CORE_EXPORT NGPhysicalLineBoxFragment final
return ChildLinkList(num_children_, &children_[0]);
}
const ComputedStyle& Style() const { return *style_; }
const NGLineHeightMetrics& Metrics() const { return metrics_; }
// The base direction of this line. Also known as the paragraph direction.
......@@ -66,6 +67,7 @@ class CORE_EXPORT NGPhysicalLineBoxFragment final
private:
NGPhysicalLineBoxFragment(NGLineBoxFragmentBuilder* builder);
scoped_refptr<const ComputedStyle> style_;
NGLineHeightMetrics metrics_;
NGLinkStorage children_[];
};
......
......@@ -19,8 +19,7 @@ namespace blink {
namespace {
struct SameSizeAsNGPhysicalTextFragment : NGPhysicalFragment {
void* pointers[2];
NGPhysicalOffsetRect rect;
void* pointers[3];
unsigned offsets[2];
};
......@@ -56,31 +55,31 @@ NGLineOrientation ToLineOrientation(WritingMode writing_mode) {
} // anonymous namespace
NGPhysicalTextFragment::NGPhysicalTextFragment(
LayoutObject* layout_object,
const ComputedStyle& style,
NGStyleVariant style_variant,
NGTextType text_type,
const String& text,
const NGPhysicalTextFragment& source,
unsigned start_offset,
unsigned end_offset,
NGPhysicalSize size,
NGLineOrientation line_orientation,
scoped_refptr<const ShapeResultView> shape_result)
: NGPhysicalFragment(layout_object,
style,
style_variant,
size,
: NGPhysicalFragment(source.GetLayoutObject(),
source.StyleVariant(),
source.IsHorizontal()
? NGPhysicalSize{shape_result->SnappedWidth(),
source.Size().height}
: NGPhysicalSize{source.Size().width,
shape_result->SnappedWidth()},
kFragmentText,
text_type),
text_(text),
source.TextType()),
text_(source.text_),
start_offset_(start_offset),
end_offset_(end_offset),
shape_result_(shape_result) {
DCHECK_GE(start_offset_, source.StartOffset());
DCHECK_LE(end_offset_, source.EndOffset());
DCHECK(shape_result_ || IsFlowControl()) << ToString();
line_orientation_ = static_cast<unsigned>(line_orientation);
is_anonymous_text_ = IsPhysicalTextFragmentAnonymousText(layout_object);
DCHECK(!source.rare_data_ || !source.rare_data_->style_);
line_orientation_ = source.line_orientation_;
is_anonymous_text_ = source.is_anonymous_text_;
self_ink_overflow_ = ComputeSelfInkOverflow();
UpdateSelfInkOverflow();
}
NGPhysicalTextFragment::NGPhysicalTextFragment(NGTextFragmentBuilder* builder)
......@@ -95,7 +94,29 @@ NGPhysicalTextFragment::NGPhysicalTextFragment(NGTextFragmentBuilder* builder)
is_anonymous_text_ =
IsPhysicalTextFragmentAnonymousText(builder->layout_object_);
self_ink_overflow_ = ComputeSelfInkOverflow();
if (UNLIKELY(StyleVariant() == NGStyleVariant::kEllipsis))
EnsureRareData()->style_ = std::move(builder->style_);
UpdateSelfInkOverflow();
}
NGPhysicalTextFragment::RareData* NGPhysicalTextFragment::EnsureRareData() {
if (!rare_data_)
rare_data_ = std::make_unique<RareData>();
return rare_data_.get();
}
const ComputedStyle& NGPhysicalTextFragment::Style() const {
switch (StyleVariant()) {
case NGStyleVariant::kStandard:
case NGStyleVariant::kFirstLine:
return NGPhysicalFragment::Style();
case NGStyleVariant::kEllipsis:
DCHECK(rare_data_ && rare_data_->style_);
return *rare_data_->style_;
}
NOTREACHED();
return NGPhysicalFragment::Style();
}
// Convert logical cooridnate to local physical coordinate.
......@@ -185,9 +206,20 @@ NGPhysicalOffsetRect NGPhysicalTextFragment::LocalRect(
return {};
}
NGPhysicalOffsetRect NGPhysicalTextFragment::ComputeSelfInkOverflow() const {
if (UNLIKELY(!shape_result_))
return LocalRect();
NGPhysicalOffsetRect NGPhysicalTextFragment::SelfInkOverflow() const {
return UNLIKELY(rare_data_) ? rare_data_->self_ink_overflow_ : LocalRect();
}
void NGPhysicalTextFragment::ClearSelfInkOverflow() {
if (UNLIKELY(rare_data_))
rare_data_->self_ink_overflow_ = LocalRect();
}
void NGPhysicalTextFragment::UpdateSelfInkOverflow() {
if (UNLIKELY(!shape_result_)) {
ClearSelfInkOverflow();
return;
}
// Glyph bounds is in logical coordinate, origin at the alphabetic baseline.
LayoutRect ink_overflow = EnclosingLayoutRect(shape_result_->Bounds());
......@@ -234,8 +266,13 @@ NGPhysicalOffsetRect NGPhysicalTextFragment::ComputeSelfInkOverflow() const {
// Uniting the frame rect ensures that non-ink spaces such side bearings, or
// even space characters, are included in the visual rect for decorations.
NGPhysicalOffsetRect local_ink_overflow = ConvertToLocal(ink_overflow);
local_ink_overflow.Unite(LocalRect());
return local_ink_overflow;
NGPhysicalOffsetRect local_rect = LocalRect();
if (local_rect.Contains(local_ink_overflow)) {
ClearSelfInkOverflow();
return;
}
local_ink_overflow.Unite(local_rect);
EnsureRareData()->self_ink_overflow_ = local_ink_overflow;
}
scoped_refptr<const NGPhysicalFragment> NGPhysicalTextFragment::TrimText(
......@@ -250,13 +287,9 @@ scoped_refptr<const NGPhysicalFragment> NGPhysicalTextFragment::TrimText(
scoped_refptr<ShapeResult> new_shape_result =
shape_result_->CreateShapeResult()->SubRange(new_start_offset,
new_end_offset);
LayoutUnit new_inline_size = new_shape_result->SnappedWidth();
return base::AdoptRef(new NGPhysicalTextFragment(
layout_object_, Style(), static_cast<NGStyleVariant>(style_variant_),
TextType(), text_, new_start_offset, new_end_offset,
IsHorizontal() ? NGPhysicalSize{new_inline_size, size_.height}
: NGPhysicalSize{size_.width, new_inline_size},
LineOrientation(), ShapeResultView::Create(new_shape_result.get())));
*this, new_start_offset, new_end_offset,
ShapeResultView::Create(new_shape_result.get())));
}
unsigned NGPhysicalTextFragment::TextOffsetForPoint(
......
......@@ -72,6 +72,8 @@ class CORE_EXPORT NGPhysicalTextFragment final : public NGPhysicalFragment {
return IsLineBreak() || TextType() == kFlowControl;
}
const ComputedStyle& Style() const;
unsigned Length() const { return end_offset_ - start_offset_; }
StringView Text() const { return StringView(text_, start_offset_, Length()); }
const String& TextContent() const { return text_; }
......@@ -102,7 +104,7 @@ class CORE_EXPORT NGPhysicalTextFragment final : public NGPhysicalFragment {
// The visual bounding box that includes glpyh bounding box and CSS
// properties, in local coordinates.
NGPhysicalOffsetRect SelfInkOverflow() const { return self_ink_overflow_; }
NGPhysicalOffsetRect SelfInkOverflow() const;
// Create a new fragment that has part of the text of this fragment.
// All other properties are the same as this fragment.
......@@ -135,24 +137,25 @@ class CORE_EXPORT NGPhysicalTextFragment final : public NGPhysicalFragment {
private:
// For use by TrimText only
NGPhysicalTextFragment(LayoutObject* layout_object,
const ComputedStyle& style,
NGStyleVariant style_variant,
NGTextType text_type,
const String& text,
NGPhysicalTextFragment(const NGPhysicalTextFragment& source,
unsigned start_offset,
unsigned end_offset,
NGPhysicalSize size,
NGLineOrientation line_orientation,
scoped_refptr<const ShapeResultView> shape_result);
struct RareData {
NGPhysicalOffsetRect self_ink_overflow_;
scoped_refptr<const ComputedStyle> style_; // Used only for ellipsis.
};
RareData* EnsureRareData();
LayoutUnit InlinePositionForOffset(unsigned offset,
LayoutUnit (*round)(float),
AdjustMidCluster) const;
NGPhysicalOffsetRect ConvertToLocal(const LayoutRect&) const;
NGPhysicalOffsetRect ComputeSelfInkOverflow() const;
void UpdateSelfInkOverflow();
void ClearSelfInkOverflow();
// The text of NGInlineNode; i.e., of a parent block. The text for this
// fragment is a substring(start_offset_, end_offset_) of this string.
......@@ -161,8 +164,9 @@ class CORE_EXPORT NGPhysicalTextFragment final : public NGPhysicalFragment {
// Start and end offset of the parent block text.
const unsigned start_offset_;
const unsigned end_offset_;
NGPhysicalOffsetRect self_ink_overflow_;
const scoped_refptr<const ShapeResultView> shape_result_;
std::unique_ptr<RareData> rare_data_;
};
DEFINE_TYPE_CASTS(NGPhysicalTextFragment,
......
......@@ -23,7 +23,7 @@ namespace {
struct SameSizeAsNGPhysicalFragment
: RefCounted<const NGPhysicalFragment, NGPhysicalFragmentTraits> {
void* pointers[3];
void* pointers[2];
NGPhysicalSize size;
unsigned flags;
};
......@@ -249,7 +249,6 @@ NGPhysicalFragment::NGPhysicalFragment(NGFragmentBuilder* builder,
NGFragmentType type,
unsigned sub_type)
: layout_object_(builder->layout_object_),
style_(std::move(builder->style_)),
size_(ToNGPhysicalSize(builder->size_, builder->GetWritingMode())),
break_token_(std::move(builder->break_token_)),
type_(type),
......@@ -259,14 +258,12 @@ NGPhysicalFragment::NGPhysicalFragment(NGFragmentBuilder* builder,
style_variant_((unsigned)builder->style_variant_) {}
NGPhysicalFragment::NGPhysicalFragment(LayoutObject* layout_object,
const ComputedStyle& style,
NGStyleVariant style_variant,
NGPhysicalSize size,
NGFragmentType type,
unsigned sub_type,
scoped_refptr<NGBreakToken> break_token)
: layout_object_(layout_object),
style_(&style),
size_(size),
break_token_(std::move(break_token)),
type_(type),
......@@ -298,21 +295,20 @@ void NGPhysicalFragment::Destroy() const {
}
const ComputedStyle& NGPhysicalFragment::Style() const {
DCHECK(style_);
// TODO(kojii): Returning |style_| locks the style at the layout time, and
// will not be updated when its base style is updated later. Line styles and
// ellipsis styles have this problem.
if (!GetLayoutObject())
return *style_;
if (Type() == kFragmentLineBox)
return ToNGPhysicalLineBoxFragment(this)->Style();
switch (StyleVariant()) {
case NGStyleVariant::kStandard:
DCHECK(GetLayoutObject());
return *GetLayoutObject()->Style();
case NGStyleVariant::kFirstLine:
DCHECK(GetLayoutObject());
return *GetLayoutObject()->FirstLineStyle();
case NGStyleVariant::kEllipsis:
return *style_;
return ToNGPhysicalTextFragment(this)->Style();
}
return *style_;
NOTREACHED();
return *GetLayoutObject()->Style();
}
Node* NGPhysicalFragment::GetNode() const {
......
......@@ -236,7 +236,6 @@ class CORE_EXPORT NGPhysicalFragment
unsigned sub_type);
NGPhysicalFragment(LayoutObject* layout_object,
const ComputedStyle& style,
NGStyleVariant,
NGPhysicalSize size,
NGFragmentType type,
......@@ -246,7 +245,6 @@ class CORE_EXPORT NGPhysicalFragment
const Vector<NGInlineItem>& InlineItemsOfContainingBlock() const;
LayoutObject* const layout_object_;
scoped_refptr<const ComputedStyle> style_;
const NGPhysicalSize size_;
scoped_refptr<NGBreakToken> break_token_;
......
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