Commit 076416bb authored by Koji Ishii's avatar Koji Ishii Committed by Commit Bot

[FragmentItem] Change to the array of |NGFragmentItem|

This patch changes the array of |scoped_refptr<NGFragmentItem>|
to the array of |NGFragmentItem|.

This change:
* Improves memory usages.
* Improves memory locality when traversing items.
* Slows copying |NGFragmentItem|.

Pinpoint results show the memory improvement:
https://pinpoint-dot-chromeperf.appspot.com/job/15aa024e120000
but layout/paint look almost neutral, less than originally
expected unfortunately; some tests are faster but tests that
leverage simplified layout a lot are slower:
win10 blink_perf.layout
https://pinpoint-dot-chromeperf.appspot.com/job/165dcc45120000
linux blink_perf.layout
https://pinpoint-dot-chromeperf.appspot.com/job/14b5417a120000
linux blink_perf.paint
https://pinpoint-dot-chromeperf.appspot.com/job/143fc65a120000

Bug: 982194
Change-Id: I86b8a7e5eff4ad211da2cdaed065eacbec316469
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2208806
Commit-Queue: Koji Ishii <kojii@chromium.org>
Reviewed-by: default avatarIan Kilpatrick <ikilpatrick@chromium.org>
Reviewed-by: default avatarYoshifumi Inoue <yosin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#774510}
parent 820dae59
......@@ -17,7 +17,7 @@ namespace blink {
namespace {
struct SameSizeAsNGFragmentItem : RefCounted<NGFragmentItem> {
struct SameSizeAsNGFragmentItem {
struct {
void* pointer;
NGTextOffset text_offset;
......@@ -87,10 +87,9 @@ NGFragmentItem::NGFragmentItem(
DCHECK(!IsFormattingContextRoot());
}
NGFragmentItem::NGFragmentItem(const NGPhysicalLineBoxFragment& line,
wtf_size_t item_count)
NGFragmentItem::NGFragmentItem(const NGPhysicalLineBoxFragment& line)
: layout_object_(line.ContainerLayoutObject()),
line_({&line, item_count}),
line_({&line, /* descendants_count */ 1}),
rect_({PhysicalOffset(), line.Size()}),
type_(kLine),
sub_type_(static_cast<unsigned>(line.LineBoxType())),
......@@ -106,7 +105,7 @@ NGFragmentItem::NGFragmentItem(const NGPhysicalLineBoxFragment& line,
NGFragmentItem::NGFragmentItem(const NGPhysicalBoxFragment& box,
TextDirection resolved_direction)
: layout_object_(box.GetLayoutObject()),
box_({&box, 1}),
box_({&box, /* descendants_count */ 1}),
rect_({PhysicalOffset(), box.Size()}),
type_(kBox),
style_variant_(static_cast<unsigned>(box.StyleVariant())),
......@@ -118,28 +117,66 @@ NGFragmentItem::NGFragmentItem(const NGPhysicalBoxFragment& box,
DCHECK_EQ(IsFormattingContextRoot(), box.IsFormattingContextRoot());
}
// static
scoped_refptr<NGFragmentItem> NGFragmentItem::Create(
NGLogicalLineItem&& line_item,
WritingMode writing_mode) {
if (line_item.fragment)
return base::AdoptRef(new NGFragmentItem(*line_item.fragment));
NGFragmentItem::NGFragmentItem(NGLogicalLineItem&& line_item,
WritingMode writing_mode) {
DCHECK(line_item.CanCreateFragmentItem());
if (line_item.fragment) {
new (this) NGFragmentItem(*line_item.fragment);
return;
}
if (line_item.inline_item) {
return base::AdoptRef(new NGFragmentItem(
*line_item.inline_item, std::move(line_item.shape_result),
line_item.text_offset,
ToPhysicalSize(line_item.MarginSize(), writing_mode)));
new (this)
NGFragmentItem(*line_item.inline_item,
std::move(line_item.shape_result), line_item.text_offset,
ToPhysicalSize(line_item.MarginSize(), writing_mode));
return;
}
if (line_item.layout_result) {
const NGPhysicalBoxFragment& box_fragment =
To<NGPhysicalBoxFragment>(line_item.layout_result->PhysicalFragment());
return base::AdoptRef(
new NGFragmentItem(box_fragment, line_item.ResolvedDirection()));
new (this) NGFragmentItem(box_fragment, line_item.ResolvedDirection());
return;
}
return nullptr;
// CanCreateFragmentItem()
NOTREACHED();
CHECK(false);
}
NGFragmentItem::NGFragmentItem(NGFragmentItem&& source)
: layout_object_(source.layout_object_),
rect_(source.rect_),
ink_overflow_(std::move(source.ink_overflow_)),
fragment_id_(source.fragment_id_),
delta_to_next_for_same_layout_object_(
source.delta_to_next_for_same_layout_object_),
type_(source.type_),
sub_type_(source.sub_type_),
style_variant_(source.style_variant_),
is_hidden_for_paint_(source.is_hidden_for_paint_),
text_direction_(source.text_direction_),
ink_overflow_computed_(source.ink_overflow_computed_),
is_dirty_(source.is_dirty_),
is_last_for_node_(source.is_last_for_node_) {
DCHECK(!source.ink_overflow_); // Ensure it was moved.
switch (Type()) {
case kText:
new (&text_) TextItem(std::move(source.text_));
break;
case kGeneratedText:
new (&generated_text_)
GeneratedTextItem(std::move(source.generated_text_));
break;
case kLine:
new (&line_) LineItem(std::move(source.line_));
break;
case kBox:
new (&box_) BoxItem(std::move(source.box_));
break;
}
}
NGFragmentItem::~NGFragmentItem() {
......
......@@ -29,7 +29,7 @@ struct NGLogicalLineItem;
//
// This class consumes less memory than a full fragment, and can be stored in a
// flat list (NGFragmentItems) for easier and faster traversal.
class CORE_EXPORT NGFragmentItem : public RefCounted<NGFragmentItem> {
class CORE_EXPORT NGFragmentItem {
public:
// Represents regular text that exists in the DOM.
struct TextItem {
......@@ -65,6 +65,8 @@ class CORE_EXPORT NGFragmentItem : public RefCounted<NGFragmentItem> {
enum ItemType { kText, kGeneratedText, kLine, kBox };
// Create appropriate type for |line_item|.
NGFragmentItem(NGLogicalLineItem&& line_item, WritingMode writing_mode);
// Create a text item.
// TODO(kojii): Should be able to create without once creating fragments.
explicit NGFragmentItem(const NGPhysicalTextFragment& text);
......@@ -72,11 +74,10 @@ class CORE_EXPORT NGFragmentItem : public RefCounted<NGFragmentItem> {
NGFragmentItem(const NGPhysicalBoxFragment& box,
TextDirection resolved_direction);
// Create a line item.
NGFragmentItem(const NGPhysicalLineBoxFragment& line, wtf_size_t item_count);
explicit NGFragmentItem(const NGPhysicalLineBoxFragment& line);
// Create |NGFragmentItem| for all items in |child_list|.
static scoped_refptr<NGFragmentItem> Create(NGLogicalLineItem&& child,
WritingMode writing_mode);
// The move constructor.
NGFragmentItem(NGFragmentItem&&);
~NGFragmentItem();
......@@ -176,8 +177,15 @@ class CORE_EXPORT NGFragmentItem : public RefCounted<NGFragmentItem> {
}
bool HasChildren() const { return DescendantsCount() > 1; }
void SetDescendantsCount(wtf_size_t count) {
CHECK_EQ(Type(), kBox);
box_.descendants_count = count;
if (Type() == kBox) {
box_.descendants_count = count;
return;
}
if (Type() == kLine) {
line_.descendants_count = count;
return;
}
NOTREACHED();
}
// Returns |NGPhysicalBoxFragment| if one is associated with this item.
......@@ -357,6 +365,8 @@ class CORE_EXPORT NGFragmentItem : public RefCounted<NGFragmentItem> {
// Returns true if this item is reusable.
bool CanReuse() const;
const NGFragmentItem* operator->() const { return this; }
// Get a description of |this| for the debug purposes.
String ToString() const;
......
......@@ -20,16 +20,13 @@ NGFragmentItems::NGFragmentItems(NGFragmentItemsBuilder* builder)
for (unsigned i = 0; i < size_; ++i) {
// Call the move constructor to move without |AddRef|. Items in
// |NGFragmentItemsBuilder| are not used after |this| was constructed.
DCHECK(source_items[i].item);
new (&items_[i])
scoped_refptr<const NGFragmentItem>(std::move(source_items[i].item));
DCHECK(!source_items[i].item); // Ensure the source was moved.
new (&items_[i]) NGFragmentItem(std::move(source_items[i].item));
}
}
NGFragmentItems::~NGFragmentItems() {
for (unsigned i = 0; i < size_; ++i)
items_[i]->Release();
items_[i].~NGFragmentItem();
}
bool NGFragmentItems::IsSubSpan(const Span& span) const {
......@@ -58,27 +55,27 @@ void NGFragmentItems::FinalizeAfterLayout(
const Span items = current->Items();
wtf_size_t index = 0;
for (const scoped_refptr<const NGFragmentItem>& item : items) {
for (const NGFragmentItem& item : items) {
++index;
if (item->Type() == NGFragmentItem::kLine) {
DCHECK_EQ(item->DeltaToNextForSameLayoutObject(), 0u);
if (item.Type() == NGFragmentItem::kLine) {
DCHECK_EQ(item.DeltaToNextForSameLayoutObject(), 0u);
continue;
}
LayoutObject* const layout_object = item->GetMutableLayoutObject();
LayoutObject* const layout_object = item.GetMutableLayoutObject();
if (UNLIKELY(layout_object->IsFloating())) {
DCHECK_EQ(item->DeltaToNextForSameLayoutObject(), 0u);
DCHECK_EQ(item.DeltaToNextForSameLayoutObject(), 0u);
continue;
}
DCHECK(!layout_object->IsOutOfFlowPositioned());
DCHECK(layout_object->IsInLayoutNGInlineFormattingContext()) << *item;
DCHECK(layout_object->IsInLayoutNGInlineFormattingContext());
item->SetDeltaToNextForSameLayoutObject(0);
item->SetIsLastForNode(false);
item.SetDeltaToNextForSameLayoutObject(0);
item.SetIsLastForNode(false);
const auto last_item_result =
last_items.insert(layout_object, LastItem{item.get(), 0, index});
last_items.insert(layout_object, LastItem{&item, 0, index});
if (last_item_result.is_new_entry) {
item->SetFragmentId(0);
item.SetFragmentId(0);
if (create_index_cache) {
DCHECK_EQ(layout_object->FirstInlineFragmentItemIndex(), 0u);
layout_object->SetFirstInlineFragmentItemIndex(index);
......@@ -91,13 +88,13 @@ void NGFragmentItems::FinalizeAfterLayout(
DCHECK_EQ(last_item->DeltaToNextForSameLayoutObject(), 0u);
if (create_index_cache) {
const wtf_size_t last_index = last->item_index;
DCHECK_GT(last_index, 0u) << *item;
DCHECK_GT(last_index, 0u);
DCHECK_LT(last_index, items.size());
DCHECK_LT(last_index, index);
last_item->SetDeltaToNextForSameLayoutObject(index - last_index);
}
item->SetFragmentId(++last->fragment_id);
last->item = item.get();
item.SetFragmentId(++last->fragment_id);
last->item = &item;
last->item_index = index;
}
}
......@@ -182,7 +179,7 @@ bool NGFragmentItems::TryDirtyFirstLineFor(
DCHECK(layout_object.IsInLayoutNGInlineFormattingContext());
DCHECK(!layout_object.IsFloatingOrOutOfFlowPositioned());
if (wtf_size_t index = layout_object.FirstInlineFragmentItemIndex()) {
const NGFragmentItem& item = *Items()[index - 1];
const NGFragmentItem& item = Items()[index - 1];
DCHECK_EQ(&layout_object, item.GetLayoutObject());
item.SetDirty();
return true;
......@@ -291,8 +288,8 @@ void NGFragmentItems::LayoutObjectWillBeMoved(
*container.GetPhysicalFragment(idx);
DCHECK(fragment.Items());
for (const auto& item : fragment.Items()->Items()) {
if (item->GetLayoutObject() == &layout_object)
item->LayoutObjectWillBeMoved();
if (item.GetLayoutObject() == &layout_object)
item.LayoutObjectWillBeMoved();
}
}
return;
......@@ -318,8 +315,8 @@ void NGFragmentItems::LayoutObjectWillBeDestroyed(
*container.GetPhysicalFragment(idx);
DCHECK(fragment.Items());
for (const auto& item : fragment.Items()->Items()) {
if (item->GetLayoutObject() == &layout_object)
item->LayoutObjectWillBeDestroyed();
if (item.GetLayoutObject() == &layout_object)
item.LayoutObjectWillBeDestroyed();
}
}
return;
......
......@@ -24,7 +24,7 @@ class CORE_EXPORT NGFragmentItems {
wtf_size_t Size() const { return size_; }
using Span = base::span<const scoped_refptr<const NGFragmentItem>>;
using Span = base::span<const NGFragmentItem>;
Span Items() const { return base::make_span(ItemsData(), size_); }
bool Equals(const Span& span) const {
return ItemsData() == span.data() && Size() == span.size();
......@@ -33,7 +33,7 @@ class CORE_EXPORT NGFragmentItems {
const NGFragmentItem& front() const {
CHECK_GE(size_, 1u);
return *items_[0];
return items_[0];
}
const String& Text(bool first_line) const {
......@@ -69,9 +69,7 @@ class CORE_EXPORT NGFragmentItems {
wtf_size_t ByteSize() const { return ByteSizeFor(Size()); }
private:
const scoped_refptr<const NGFragmentItem>* ItemsData() const {
return reinterpret_cast<const scoped_refptr<const NGFragmentItem>*>(items_);
}
const NGFragmentItem* ItemsData() const { return items_; }
static bool CanReuseAll(NGInlineCursor* cursor);
bool TryDirtyFirstLineFor(const LayoutObject& layout_object) const;
......@@ -89,7 +87,7 @@ class CORE_EXPORT NGFragmentItems {
static_assert(
sizeof(NGFragmentItem*) == sizeof(scoped_refptr<const NGFragmentItem>),
"scoped_refptr must be the size of a pointer for |ItemsData()| to work");
NGFragmentItem* items_[];
NGFragmentItem items_[0];
};
} // namespace blink
......
......@@ -60,15 +60,15 @@ void NGFragmentItemsBuilder::AddLine(const NGPhysicalLineBoxFragment& line,
// Add an empty item so that the start of the line can be set later.
const wtf_size_t line_start_index = items_.size();
items_.emplace_back(offset);
items_.emplace_back(offset, line);
AddItems(current_line_.begin(), current_line_.end());
// All children are added. Create an item for the start of the line.
NGFragmentItem& line_item = items_[line_start_index].item;
const wtf_size_t item_count = items_.size() - line_start_index;
DCHECK(!items_[line_start_index].item);
items_[line_start_index].item =
base::MakeRefCounted<NGFragmentItem>(line, item_count);
DCHECK_EQ(line_item.DescendantsCount(), 1u);
line_item.SetDescendantsCount(item_count);
// Keep children's offsets relative to |line|. They will be adjusted later in
// |ConvertToPhysical()|.
......@@ -89,27 +89,23 @@ void NGFragmentItemsBuilder::AddItems(NGLogicalLineItem* child_begin,
NGLogicalLineItem& child = *child_iter;
// OOF children should have been added to their parent box fragments.
DCHECK(!child.out_of_flow_positioned_box);
scoped_refptr<NGFragmentItem> item =
NGFragmentItem::Create(std::move(child), writing_mode_);
if (!item) {
if (!child.CanCreateFragmentItem()) {
++child_iter;
continue;
}
if (child.children_count <= 1) {
items_.emplace_back(std::move(item), child.rect.offset);
items_.emplace_back(child.rect.offset, std::move(child), writing_mode_);
++child_iter;
continue;
}
DCHECK(item->IsContainer());
DCHECK(!item->IsFloating());
// Children of inline boxes are flattened and added to |items_|, with the
// count of descendant items to preserve the tree structure.
//
// Add an empty item so that the start of the box can be set later.
const wtf_size_t box_start_index = items_.size();
items_.emplace_back(child.rect.offset);
items_.emplace_back(child.rect.offset, std::move(child), writing_mode_);
// Add all children, including their desendants, skipping this item.
CHECK_GE(child.children_count, 1u); // 0 will loop infinitely.
......@@ -121,9 +117,9 @@ void NGFragmentItemsBuilder::AddItems(NGLogicalLineItem* child_begin,
// All children are added. Compute how many items are actually added. The
// number of items added maybe different from |child.children_count|.
const wtf_size_t item_count = items_.size() - box_start_index;
item->SetDescendantsCount(item_count);
DCHECK(!items_[box_start_index].item);
items_[box_start_index].item = std::move(item);
NGFragmentItem& box_item = items_[box_start_index].item;
DCHECK_EQ(box_item.DescendantsCount(), 1u);
box_item.SetDescendantsCount(item_count);
}
}
......@@ -135,9 +131,7 @@ void NGFragmentItemsBuilder::AddListMarker(
// Resolved direction matters only for inline items, and outside list markers
// are not inline.
const TextDirection resolved_direction = TextDirection::kLtr;
items_.emplace_back(
base::MakeRefCounted<NGFragmentItem>(marker_fragment, resolved_direction),
offset);
items_.emplace_back(offset, marker_fragment, resolved_direction);
}
NGFragmentItemsBuilder::AddPreviousItemsResult
......@@ -169,7 +163,7 @@ NGFragmentItemsBuilder::AddPreviousItems(
const NGFragmentItem* const end_item =
stop_at_dirty ? items.EndOfReusableItems() : nullptr;
const NGFragmentItem* last_line_start_item = nullptr;
const NGPhysicalLineBoxFragment* last_line_fragment = nullptr;
LayoutUnit used_block_size;
for (NGInlineCursor cursor(items); cursor;) {
......@@ -182,38 +176,43 @@ NGFragmentItemsBuilder::AddPreviousItems(
const LogicalOffset item_offset =
item.OffsetInContainerBlock().ConvertToLogical(
writing_mode_, direction_, container_size, item.Size());
items_.emplace_back(&item, item_offset);
if (item.Type() == NGFragmentItem::kLine) {
DCHECK(item.LineBoxFragment());
if (stop_at_dirty) {
last_line_fragment = item.LineBoxFragment();
container_builder->AddChild(*last_line_fragment, item_offset);
used_block_size +=
item.Size().ConvertToLogical(writing_mode_).block_size;
}
items_.emplace_back(item_offset,
std::move(const_cast<NGFragmentItem&>(item)));
const PhysicalRect line_box_bounds = item.RectInContainerBlock();
for (NGInlineCursor line = cursor.CursorForDescendants(); line;
line.MoveToNext()) {
const NGFragmentItem& line_child = *line.Current().Item();
DCHECK(line_child.CanReuse());
items_.emplace_back(
&line_child,
(line_child.OffsetInContainerBlock() - line_box_bounds.offset)
.ConvertToLogical(line_writing_mode, TextDirection::kLtr,
line_box_bounds.size, line_child.Size()));
line_box_bounds.size, line_child.Size()),
std::move(const_cast<NGFragmentItem&>(line_child)));
}
cursor.MoveToNextSkippingChildren();
DCHECK(item.LineBoxFragment());
if (stop_at_dirty) {
container_builder->AddChild(*item.LineBoxFragment(), item_offset);
last_line_start_item = &item;
used_block_size +=
item.Size().ConvertToLogical(writing_mode_).block_size;
}
continue;
}
DCHECK_NE(item.Type(), NGFragmentItem::kLine);
DCHECK(!stop_at_dirty);
items_.emplace_back(item_offset,
std::move(const_cast<NGFragmentItem&>(item)));
cursor.MoveToNext();
}
if (stop_at_dirty && last_line_start_item) {
result.inline_break_token = last_line_start_item->InlineBreakToken();
if (stop_at_dirty && last_line_fragment) {
result.inline_break_token =
To<NGInlineBreakToken>(last_line_fragment->BreakToken());
DCHECK(result.inline_break_token);
DCHECK(!result.inline_break_token->IsFinished());
result.used_block_size = used_block_size;
......@@ -241,7 +240,7 @@ void NGFragmentItemsBuilder::ConvertToPhysical(const PhysicalSize& outer_size) {
const WritingMode line_writing_mode = ToLineWritingMode(writing_mode_);
for (ItemWithOffset* iter = items_.begin(); iter != items_.end(); ++iter) {
NGFragmentItem* item = const_cast<NGFragmentItem*>(iter->item.get());
NGFragmentItem* item = &iter->item;
item->SetOffset(iter->offset.ConvertToPhysical(writing_mode_, direction_,
outer_size, item->Size()));
......@@ -256,7 +255,7 @@ void NGFragmentItemsBuilder::ConvertToPhysical(const PhysicalSize& outer_size) {
while (--descendants_count) {
++iter;
DCHECK_NE(iter, items_.end());
item = const_cast<NGFragmentItem*>(iter->item.get());
item = &iter->item;
// Use `kLtr` because inline items are after bidi-reoder, and that
// their offset is visual, not logical.
item->SetOffset(iter->offset.ConvertToPhysical(
......
......@@ -87,15 +87,14 @@ class CORE_EXPORT NGFragmentItemsBuilder {
DISALLOW_NEW();
public:
ItemWithOffset(scoped_refptr<const NGFragmentItem> item,
const LogicalOffset& offset)
: item(std::move(item)), offset(offset) {}
explicit ItemWithOffset(const LogicalOffset& offset) : offset(offset) {}
template <class... Args>
explicit ItemWithOffset(const LogicalOffset& offset, Args&&... args)
: item(std::forward<Args>(args)...), offset(offset) {}
const NGFragmentItem& operator*() const { return *item; }
const NGFragmentItem* operator->() const { return item.get(); }
const NGFragmentItem& operator*() const { return item; }
const NGFragmentItem* operator->() const { return &item; }
scoped_refptr<const NGFragmentItem> item;
NGFragmentItem item;
LogicalOffset offset;
};
......
......@@ -120,7 +120,7 @@ const LayoutBlockFlow* NGInlineCursor::GetLayoutBlockFlow() const {
return layout_object->RootInlineFormattingContext();
}
if (IsItemCursor()) {
const NGFragmentItem& item = *fragment_items_->Items().front();
const NGFragmentItem& item = fragment_items_->front();
const LayoutObject* layout_object = item.GetLayoutObject();
if (item.Type() == NGFragmentItem::kLine)
return To<LayoutBlockFlow>(layout_object);
......@@ -916,7 +916,7 @@ NGInlineCursor::ItemsSpan::iterator NGInlineCursor::SlowFirstItemIteratorFor(
const LayoutObject& layout_object,
const ItemsSpan& items) {
for (ItemsSpan::iterator iter = items.begin(); iter != items.end(); ++iter) {
if ((*iter)->GetLayoutObject() == &layout_object)
if (iter->GetLayoutObject() == &layout_object)
return iter;
}
return items.end();
......@@ -995,7 +995,7 @@ bool NGInlineCursor::IsAtFirst() const {
if (const NGPaintFragment* paint_fragment = Current().PaintFragment())
return paint_fragment == root_paint_fragment_->FirstChild();
if (const NGFragmentItem* item = Current().Item())
return item == items_.front().get();
return item == &items_.front();
return false;
}
......@@ -1025,7 +1025,7 @@ void NGInlineCursor::MoveToFirstLine() {
if (IsItemCursor()) {
auto iter = std::find_if(
items_.begin(), items_.end(),
[](const auto& item) { return item->Type() == NGFragmentItem::kLine; });
[](const auto& item) { return item.Type() == NGFragmentItem::kLine; });
if (iter != items_.end()) {
MoveToItem(iter);
return;
......@@ -1061,7 +1061,7 @@ void NGInlineCursor::MoveToLastLine() {
DCHECK(IsItemCursor());
auto iter = std::find_if(
items_.rbegin(), items_.rend(),
[](const auto& item) { return item->Type() == NGFragmentItem::kLine; });
[](const auto& item) { return item.Type() == NGFragmentItem::kLine; });
if (iter != items_.rend())
MoveToItem(std::next(iter).base());
else
......@@ -1229,7 +1229,7 @@ void NGInlineCursor::MoveToNextItem() {
return;
DCHECK(current_.item_iter_ != items_.end());
if (++current_.item_iter_ != items_.end()) {
current_.item_ = current_.item_iter_->get();
current_.item_ = &*current_.item_iter_;
return;
}
MakeNull();
......@@ -1253,7 +1253,7 @@ void NGInlineCursor::MoveToPreviousItem() {
if (current_.item_iter_ == items_.begin())
return MakeNull();
--current_.item_iter_;
current_.item_ = current_.item_iter_->get();
current_.item_ = &*current_.item_iter_;
}
void NGInlineCursor::MoveToParentPaintFragment() {
......@@ -1380,7 +1380,7 @@ void NGInlineCursor::MoveTo(const LayoutObject& layout_object) {
if (UNLIKELY(!fragment_items_->Equals(items_))) {
const wtf_size_t span_begin_item_index = SpanBeginItemIndex();
while (UNLIKELY(item_index < span_begin_item_index)) {
const NGFragmentItem& item = *fragment_items_->Items()[item_index];
const NGFragmentItem& item = fragment_items_->Items()[item_index];
const wtf_size_t next_delta = item.DeltaToNextForSameLayoutObject();
if (!next_delta) {
MakeNull();
......@@ -1475,10 +1475,8 @@ NGInlineBackwardCursor::NGInlineBackwardCursor(const NGInlineCursor& cursor)
sibling.MoveToNextSkippingChildren())
sibling_item_iterators_.push_back(sibling.Current().item_iter_);
current_index_ = sibling_item_iterators_.size();
if (current_index_) {
current_.item_iter_ = sibling_item_iterators_[--current_index_];
current_.item_ = current_.item_iter_->get();
}
if (current_index_)
current_.Set(sibling_item_iterators_[--current_index_]);
return;
}
DCHECK(!cursor);
......@@ -1503,8 +1501,7 @@ void NGInlineBackwardCursor::MoveToPreviousSibling() {
return;
}
if (current_.item_) {
current_.item_iter_ = sibling_item_iterators_[--current_index_];
current_.item_ = current_.item_iter_->get();
current_.Set(sibling_item_iterators_[--current_index_]);
return;
}
NOTREACHED();
......
......@@ -174,7 +174,7 @@ class CORE_EXPORT NGInlineCursorPosition {
void Set(const ItemsSpan::iterator& iter) {
DCHECK(!paint_fragment_);
item_iter_ = iter;
item_ = iter->get();
item_ = &*iter;
}
void Clear() {
......
......@@ -106,6 +106,7 @@ struct NGLogicalLineItem {
bool HasFragment() const {
return HasInFlowOrFloatingFragment() || HasOutOfFlowFragment();
}
bool CanCreateFragmentItem() const { return HasInFlowOrFloatingFragment(); }
bool HasBidiLevel() const { return bidi_level != 0xff; }
bool IsPlaceholder() const { return !HasFragment() && !HasBidiLevel(); }
bool IsOpaqueToBidiReordering() const {
......
......@@ -78,10 +78,8 @@ LayoutUnit NGPhysicalTextFragment::InlinePositionForOffset(
unsigned offset,
LayoutUnit (*round_function)(float),
AdjustMidCluster adjust_mid_cluster) const {
scoped_refptr<NGFragmentItem> item =
base::MakeRefCounted<NGFragmentItem>(*this);
return item->InlinePositionForOffset(Text(), offset, round_function,
adjust_mid_cluster);
return NGFragmentItem(*this).InlinePositionForOffset(
Text(), offset, round_function, adjust_mid_cluster);
}
// TODO(yosin): We should move |NGFragmentItem::InlinePositionForOffset" to
......@@ -125,17 +123,14 @@ LayoutUnit NGFragmentItem::InlinePositionForOffset(StringView text,
LayoutUnit NGPhysicalTextFragment::InlinePositionForOffset(
unsigned offset) const {
scoped_refptr<NGFragmentItem> item =
base::MakeRefCounted<NGFragmentItem>(*this);
return item->InlinePositionForOffset(Text(), offset);
return NGFragmentItem(*this).InlinePositionForOffset(Text(), offset);
}
std::pair<LayoutUnit, LayoutUnit>
NGPhysicalTextFragment::LineLeftAndRightForOffsets(unsigned start_offset,
unsigned end_offset) const {
scoped_refptr<NGFragmentItem> item =
base::MakeRefCounted<NGFragmentItem>(*this);
return item->LineLeftAndRightForOffsets(Text(), start_offset, end_offset);
return NGFragmentItem(*this).LineLeftAndRightForOffsets(Text(), start_offset,
end_offset);
}
// TODO(yosin): We should move |NGFragmentItem::InlinePositionForOffset" to
......@@ -162,9 +157,7 @@ std::pair<LayoutUnit, LayoutUnit> NGFragmentItem::LineLeftAndRightForOffsets(
PhysicalRect NGPhysicalTextFragment::LocalRect(unsigned start_offset,
unsigned end_offset) const {
scoped_refptr<NGFragmentItem> item =
base::MakeRefCounted<NGFragmentItem>(*this);
return item->LocalRect(Text(), start_offset, end_offset);
return NGFragmentItem(*this).LocalRect(Text(), start_offset, end_offset);
}
// TODO(yosin): We should move |NGFragmentItem::InlinePositionForOffset" to
......
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