Skip to content

Commit

Permalink
[LayoutNG] Move NGInlineNode data to NGInlineNodeData.
Browse files Browse the repository at this point in the history
In preparation for making NGInlineNode, NGBlockNode POD-like.

BUG=636993

Review-Url: https://codereview.chromium.org/2836293004
Cr-Commit-Position: refs/heads/master@{#468547}
  • Loading branch information
bfgeek authored and Commit bot committed May 2, 2017
1 parent c613a56 commit 4b3d57d
Show file tree
Hide file tree
Showing 8 changed files with 124 additions and 66 deletions.
1 change: 1 addition & 0 deletions third_party/WebKit/Source/core/layout/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,7 @@ blink_core_sources("layout") {
"ng/inline/ng_inline_layout_algorithm.h",
"ng/inline/ng_inline_node.cc",
"ng/inline/ng_inline_node.h",
"ng/inline/ng_inline_node_data.h",
"ng/inline/ng_line_box_fragment.cc",
"ng/inline/ng_line_box_fragment.h",
"ng/inline/ng_line_box_fragment_builder.cc",
Expand Down
62 changes: 34 additions & 28 deletions third_party/WebKit/Source/core/layout/ng/inline/ng_inline_node.cc
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,13 @@

namespace blink {

NGInlineNode::NGInlineNode(LayoutObject* start_inline, LayoutBlockFlow* block)
NGInlineNode::NGInlineNode(LayoutObject* start_inline, LayoutNGBlockFlow* block)
: NGLayoutInputNode(NGLayoutInputNodeType::kLegacyInline),
start_inline_(start_inline),
block_(block) {
DCHECK(start_inline);
DCHECK(block);
block->ResetNGInlineNodeData();
}

NGInlineNode::NGInlineNode()
Expand All @@ -45,19 +46,19 @@ NGInlineNode::NGInlineNode()
NGInlineNode::~NGInlineNode() {}

NGInlineItemRange NGInlineNode::Items(unsigned start, unsigned end) {
return NGInlineItemRange(&items_, start, end);
return NGInlineItemRange(&MutableData().items_, start, end);
}

void NGInlineNode::InvalidatePrepareLayout() {
text_content_ = String();
items_.clear();
MutableData().text_content_ = String();
MutableData().items_.clear();
}

void NGInlineNode::PrepareLayout() {
// Scan list of siblings collecting all in-flow non-atomic inlines. A single
// NGInlineNode represent a collection of adjacent non-atomic inlines.
CollectInlines(start_inline_, block_);
if (is_bidi_enabled_)
if (Data().is_bidi_enabled_)
SegmentText();
ShapeText();
}
Expand All @@ -67,18 +68,19 @@ void NGInlineNode::PrepareLayout() {
// parent LayoutInline where possible, and joining all text content in a single
// string to allow bidi resolution and shaping of the entire block.
void NGInlineNode::CollectInlines(LayoutObject* start, LayoutBlockFlow* block) {
DCHECK(text_content_.IsNull());
DCHECK(items_.IsEmpty());
NGInlineItemsBuilder builder(&items_);
DCHECK(Data().text_content_.IsNull());
DCHECK(Data().items_.IsEmpty());
NGInlineItemsBuilder builder(&MutableData().items_);
builder.EnterBlock(block->Style());
LayoutObject* next_sibling = CollectInlines(start, block, &builder);
builder.ExitBlock();

text_content_ = builder.ToString();
MutableData().text_content_ = builder.ToString();
DCHECK(!next_sibling || !next_sibling->IsInline());
next_sibling_ = next_sibling ? new NGBlockNode(next_sibling) : nullptr;
is_bidi_enabled_ = !text_content_.IsEmpty() &&
!(text_content_.Is8Bit() && !builder.HasBidiControls());
MutableData().is_bidi_enabled_ =
!Data().text_content_.IsEmpty() &&
!(Data().text_content_.Is8Bit() && !builder.HasBidiControls());
}

LayoutObject* NGInlineNode::CollectInlines(LayoutObject* start,
Expand Down Expand Up @@ -148,36 +150,38 @@ LayoutObject* NGInlineNode::CollectInlines(LayoutObject* start,
void NGInlineNode::SegmentText() {
// TODO(kojii): Move this to caller, this will be used again after line break.
NGBidiParagraph bidi;
text_content_.Ensure16Bit();
if (!bidi.SetParagraph(text_content_, Style())) {
MutableData().text_content_.Ensure16Bit();
if (!bidi.SetParagraph(Data().text_content_, Style())) {
// On failure, give up bidi resolving and reordering.
is_bidi_enabled_ = false;
MutableData().is_bidi_enabled_ = false;
return;
}
if (bidi.Direction() == UBIDI_LTR) {
// All runs are LTR, no need to reorder.
is_bidi_enabled_ = false;
MutableData().is_bidi_enabled_ = false;
return;
}

Vector<NGInlineItem>& items = MutableData().items_;
unsigned item_index = 0;
for (unsigned start = 0; start < text_content_.length();) {
for (unsigned start = 0; start < Data().text_content_.length();) {
UBiDiLevel level;
unsigned end = bidi.GetLogicalRun(start, &level);
DCHECK_EQ(items_[item_index].start_offset_, start);
item_index = NGInlineItem::SetBidiLevel(items_, item_index, end, level);
DCHECK_EQ(items[item_index].start_offset_, start);
item_index = NGInlineItem::SetBidiLevel(items, item_index, end, level);
start = end;
}
DCHECK_EQ(item_index, items_.size());
DCHECK_EQ(item_index, items.size());
}

void NGInlineNode::ShapeText() {
// TODO(eae): Add support for shaping latin-1 text?
text_content_.Ensure16Bit();
MutableData().text_content_.Ensure16Bit();

// Shape each item with the full context of the entire node.
HarfBuzzShaper shaper(text_content_.Characters16(), text_content_.length());
for (auto& item : items_) {
HarfBuzzShaper shaper(Data().text_content_.Characters16(),
Data().text_content_.length());
for (auto& item : MutableData().items_) {
if (item.Type() != NGInlineItem::kText)
continue;

Expand Down Expand Up @@ -234,7 +238,7 @@ void NGInlineNode::CopyFragmentDataToLayoutBox(
LayoutBlockFlow* block_flow = GetLayoutBlockFlow();
block_flow->DeleteLineBoxTree();

Vector<NGInlineItem>& items = Items();
const Vector<NGInlineItem>& items = Data().items_;
Vector<unsigned, 32> text_offsets(items.size());
GetLayoutTextOffsets(&text_offsets);

Expand Down Expand Up @@ -335,8 +339,10 @@ void NGInlineNode::GetLayoutTextOffsets(
Vector<unsigned, 32>* text_offsets_out) {
LayoutText* current_text = nullptr;
unsigned current_offset = 0;
for (unsigned i = 0; i < items_.size(); i++) {
const NGInlineItem& item = items_[i];
const Vector<NGInlineItem>& items = Data().items_;

for (unsigned i = 0; i < items.size(); i++) {
const NGInlineItem& item = items[i];
LayoutObject* next_object = item.GetLayoutObject();
LayoutText* next_text = next_object && next_object->IsText()
? ToLayoutText(next_object)
Expand All @@ -352,10 +358,10 @@ void NGInlineNode::GetLayoutTextOffsets(
}
(*text_offsets_out)[i] = current_offset;
}
if (current_text &&
current_text->TextLength() != text_content_.length() - current_offset) {
if (current_text && current_text->TextLength() !=
Data().text_content_.length() - current_offset) {
current_text->SetTextInternal(
Text(current_offset, text_content_.length()).ToString().Impl());
Text(current_offset, Data().text_content_.length()).ToString().Impl());
}
}

Expand Down
36 changes: 16 additions & 20 deletions third_party/WebKit/Source/core/layout/ng/inline/ng_inline_node.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@
#define NGInlineNode_h

#include "core/CoreExport.h"
#include "core/layout/LayoutBlockFlow.h"
#include "core/layout/ng/inline/ng_inline_item.h"
#include "core/layout/ng/inline/ng_inline_node_data.h"
#include "core/layout/ng/layout_ng_block_flow.h"
#include "core/layout/ng/ng_layout_input_node.h"
#include "platform/heap/Handle.h"
#include "platform/wtf/text/WTFString.h"
Expand All @@ -16,6 +17,7 @@ namespace blink {

class ComputedStyle;
class LayoutBlockFlow;
class LayoutNGBlockFlow;
class LayoutObject;
struct MinMaxContentSize;
class NGConstraintSpace;
Expand All @@ -28,7 +30,7 @@ class NGLayoutResult;
// inline nodes and their descendants.
class CORE_EXPORT NGInlineNode : public NGLayoutInputNode {
public:
NGInlineNode(LayoutObject* start_inline, LayoutBlockFlow*);
NGInlineNode(LayoutObject* start_inline, LayoutNGBlockFlow*);
~NGInlineNode() override;

LayoutBlockFlow* GetLayoutBlockFlow() const { return block_; }
Expand All @@ -49,18 +51,18 @@ class CORE_EXPORT NGInlineNode : public NGLayoutInputNode {
// Instruct to re-compute |PrepareLayout| on the next layout.
void InvalidatePrepareLayout();

const String& Text() const { return text_content_; }
const String& Text() const { return Data().text_content_; }
StringView Text(unsigned start_offset, unsigned end_offset) const {
return StringView(text_content_, start_offset, end_offset - start_offset);
return StringView(Data().text_content_, start_offset,
end_offset - start_offset);
}

Vector<NGInlineItem>& Items() { return items_; }
const Vector<NGInlineItem>& Items() const { return items_; }
const Vector<NGInlineItem>& Items() const { return Data().items_; }
NGInlineItemRange Items(unsigned start_index, unsigned end_index);

void GetLayoutTextOffsets(Vector<unsigned, 32>*);

bool IsBidiEnabled() const { return is_bidi_enabled_; }
bool IsBidiEnabled() const { return Data().is_bidi_enabled_; }

void AssertOffset(unsigned index, unsigned offset) const;
void AssertEndOffset(unsigned index, unsigned offset) const;
Expand All @@ -73,7 +75,7 @@ class CORE_EXPORT NGInlineNode : public NGLayoutInputNode {
// Prepare inline and text content for layout. Must be called before
// calling the Layout method.
void PrepareLayout();
bool IsPrepareLayoutFinished() const { return !text_content_.IsNull(); }
bool IsPrepareLayoutFinished() const { return !Text().IsNull(); }

void CollectInlines(LayoutObject* start, LayoutBlockFlow*);
LayoutObject* CollectInlines(LayoutObject* start,
Expand All @@ -82,27 +84,21 @@ class CORE_EXPORT NGInlineNode : public NGLayoutInputNode {
void SegmentText();
void ShapeText();

NGInlineNodeData& MutableData() { return block_->GetNGInlineNodeData(); }
const NGInlineNodeData& Data() const { return block_->GetNGInlineNodeData(); }

LayoutObject* start_inline_;
LayoutBlockFlow* block_;
LayoutNGBlockFlow* block_;
Member<NGLayoutInputNode> next_sibling_;

// Text content for all inline items represented by a single NGInlineNode
// instance. Encoded either as UTF-16 or latin-1 depending on content.
String text_content_;
Vector<NGInlineItem> items_;

// TODO(kojii): This should move to somewhere else when we move PrepareLayout
// to the correct place.
bool is_bidi_enabled_ = false;
};

inline void NGInlineNode::AssertOffset(unsigned index, unsigned offset) const {
items_[index].AssertOffset(offset);
Data().items_[index].AssertOffset(offset);
}

inline void NGInlineNode::AssertEndOffset(unsigned index,
unsigned offset) const {
items_[index].AssertEndOffset(offset);
Data().items_[index].AssertEndOffset(offset);
}

DEFINE_TYPE_CASTS(NGInlineNode,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef NGInlineNodeData_h
#define NGInlineNodeData_h

#include "core/CoreExport.h"
#include "core/layout/ng/inline/ng_inline_item.h"
#include "platform/wtf/Vector.h"

namespace blink {

// Data which is required for inline nodes.
struct CORE_EXPORT NGInlineNodeData {
private:
friend class NGInlineNode;
friend class NGInlineNodeForTest;

// Text content for all inline items represented by a single NGInlineNode.
// Encoded either as UTF-16 or latin-1 depending on the content.
String text_content_;
Vector<NGInlineItem> items_;

// TODO(kojii): This should move to somewhere else when we move PrepareLayout
// to the correct place.
bool is_bidi_enabled_ = false;
};

} // namespace blink

#endif // NGInlineNode_h
Original file line number Diff line number Diff line change
Expand Up @@ -22,33 +22,34 @@ class NGInlineNodeForTest : public NGInlineNode {
public:
using NGInlineNode::NGInlineNode;

String& Text() { return text_content_; }
Vector<NGInlineItem>& Items() { return items_; }
String& Text() { return MutableData().text_content_; }
Vector<NGInlineItem>& Items() { return MutableData().items_; }

void Append(const String& text,
const ComputedStyle* style = nullptr,
LayoutObject* layout_object = nullptr) {
unsigned start = text_content_.length();
text_content_.append(text);
items_.push_back(NGInlineItem(NGInlineItem::kText, start,
start + text.length(), style, layout_object));
unsigned start = Data().text_content_.length();
MutableData().text_content_.append(text);
MutableData().items_.push_back(NGInlineItem(NGInlineItem::kText, start,
start + text.length(), style,
layout_object));
}

void Append(UChar character) {
text_content_.append(character);
unsigned end = text_content_.length();
items_.push_back(
MutableData().text_content_.append(character);
unsigned end = Data().text_content_.length();
MutableData().items_.push_back(
NGInlineItem(NGInlineItem::kBidiControl, end - 1, end, nullptr));
is_bidi_enabled_ = true;
MutableData().is_bidi_enabled_ = true;
}

void ClearText() {
text_content_ = String();
items_.clear();
MutableData().text_content_ = String();
MutableData().items_.clear();
}

void SegmentText() {
is_bidi_enabled_ = true;
MutableData().is_bidi_enabled_ = true;
NGInlineNode::SegmentText();
}

Expand All @@ -60,13 +61,19 @@ class NGInlineNodeTest : public RenderingTest {
protected:
void SetUp() override {
RenderingTest::SetUp();
RuntimeEnabledFeatures::setLayoutNGEnabled(true);
style_ = ComputedStyle::Create();
style_->GetFont().Update(nullptr);
}

void TearDown() override {
RuntimeEnabledFeatures::setLayoutNGEnabled(false);
RenderingTest::TearDown();
}

void SetupHtml(const char* id, String html) {
SetBodyInnerHTML(html);
layout_block_flow_ = ToLayoutBlockFlow(GetLayoutObjectByElementId(id));
layout_block_flow_ = ToLayoutNGBlockFlow(GetLayoutObjectByElementId(id));
layout_object_ = layout_block_flow_->FirstChild();
style_ = layout_object_->Style();
}
Expand Down Expand Up @@ -103,7 +110,7 @@ class NGInlineNodeTest : public RenderingTest {
}

RefPtr<const ComputedStyle> style_;
LayoutBlockFlow* layout_block_flow_ = nullptr;
LayoutNGBlockFlow* layout_block_flow_ = nullptr;
LayoutObject* layout_object_ = nullptr;
FontCachePurgePreventer purge_preventer_;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,13 @@ void LayoutNGBlockFlow::UpdateBlockLayout(bool relayout_children) {
ClearNeedsLayout();
}

NGInlineNodeData& LayoutNGBlockFlow::GetNGInlineNodeData() const {
DCHECK(ng_inline_node_data_);
return *ng_inline_node_data_.get();
}

void LayoutNGBlockFlow::ResetNGInlineNodeData() {
ng_inline_node_data_ = WTF::MakeUnique<NGInlineNodeData>();
}

} // namespace blink
Loading

0 comments on commit 4b3d57d

Please sign in to comment.