Chromium Code Reviews| Index: third_party/WebKit/Source/core/layout/ng/inline/ng_line_breaker_test.cc |
| diff --git a/third_party/WebKit/Source/core/layout/ng/inline/ng_line_breaker_test.cc b/third_party/WebKit/Source/core/layout/ng/inline/ng_line_breaker_test.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..1e5d401ddd2dbc9a179444f810824f77c850c620 |
| --- /dev/null |
| +++ b/third_party/WebKit/Source/core/layout/ng/inline/ng_line_breaker_test.cc |
| @@ -0,0 +1,252 @@ |
| +// 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. |
| + |
| +#include "core/layout/ng/ng_base_layout_algorithm_test.h" |
| + |
| +#include "core/layout/ng/inline/ng_inline_layout_algorithm.h" |
| +#include "core/layout/ng/inline/ng_inline_node.h" |
| +#include "core/layout/ng/inline/ng_line_breaker.h" |
| +#include "core/layout/ng/layout_ng_block_flow.h" |
| +#include "core/layout/ng/ng_constraint_space_builder.h" |
| +#include "platform/wtf/text/StringBuilder.h" |
| + |
| +namespace blink { |
| + |
| +class NGLineBreakerTest : public NGBaseLayoutAlgorithmTest { |
| + protected: |
| + NGInlineNode* CreateInlineNode(const String& html_content) { |
| + SetBodyInnerHTML(html_content); |
| + |
| + LayoutNGBlockFlow* block_flow = |
| + ToLayoutNGBlockFlow(GetLayoutObjectByElementId("container")); |
| + NGInlineNode* inline_node = |
| + new NGInlineNode(block_flow->FirstChild(), block_flow); |
| + |
| + return inline_node; |
| + } |
| + |
| + // Break lines using the specified available width. |
| + Vector<NGInlineItemResults> BreakLines(NGInlineNode* node, |
| + LayoutUnit available_width) { |
| + if (!node->IsPrepareLayoutFinished()) |
| + node->PrepareLayout(); |
| + |
| + RefPtr<NGConstraintSpace> space = |
| + NGConstraintSpaceBuilder(NGWritingMode::kHorizontalTopBottom) |
| + .SetAvailableSize({available_width, NGSizeIndefinite}) |
| + .ToConstraintSpace(NGWritingMode::kHorizontalTopBottom); |
| + NGLineBreaker line_breaker(node, space.Get()); |
| + NGInlineLayoutAlgorithm algorithm(node, space.Get()); |
| + Vector<NGInlineItemResults> lines; |
| + while (true) { |
| + NGInlineItemResults item_results; |
| + line_breaker.NextLine(&item_results, &algorithm); |
| + if (item_results.IsEmpty()) |
| + break; |
| + lines.push_back(item_results); |
| + } |
| + return lines; |
| + } |
| +}; |
| + |
| +namespace { |
| + |
| +String ToString(NGInlineItemResults line, NGInlineNode* node) { |
| + StringBuilder builder; |
| + for (const auto& item_result : line) { |
| + builder.Append( |
| + node->Text(item_result.start_offset, item_result.end_offset)); |
| + } |
| + return builder.ToString(); |
| +} |
| + |
| +TEST_F(NGLineBreakerTest, SingleNode) { |
| + LoadAhem(); |
| + NGInlineNode* node = CreateInlineNode(R"HTML( |
| +<!DOCTYPE html> |
| +<style> |
| +#container { |
| + font: 10px/1 Ahem; |
| +} |
| +</style> |
| +<div id=container>123 456 789</div> |
| +)HTML"); |
| + |
| + Vector<NGInlineItemResults> lines; |
| + lines = BreakLines(node, LayoutUnit(80)); |
| + EXPECT_EQ(2u, lines.size()); |
| + EXPECT_EQ("123 456", ToString(lines[0], node)); |
| + EXPECT_EQ("789", ToString(lines[1], node)); |
| + |
| + lines = BreakLines(node, LayoutUnit(60)); |
| + EXPECT_EQ(3u, lines.size()); |
| + EXPECT_EQ("123", ToString(lines[0], node)); |
| + EXPECT_EQ("456", ToString(lines[1], node)); |
| + EXPECT_EQ("789", ToString(lines[2], node)); |
| +} |
| + |
| +TEST_F(NGLineBreakerTest, OverflowWord) { |
| + LoadAhem(); |
| + NGInlineNode* node = CreateInlineNode(R"HTML( |
| +<!DOCTYPE html> |
| +<style> |
| +#container { |
| + font: 10px/1 Ahem; |
| +} |
| +</style> |
| +<div id=container>12345 678</div> |
| +)HTML"); |
| + |
| + // The first line overflows, but the last line does not. |
| + Vector<NGInlineItemResults> lines; |
| + lines = BreakLines(node, LayoutUnit(40)); |
| + EXPECT_EQ(2u, lines.size()); |
| + EXPECT_EQ("12345", ToString(lines[0], node)); |
| + EXPECT_EQ("678", ToString(lines[1], node)); |
| + |
| + // Both lines overflow. |
| + lines = BreakLines(node, LayoutUnit(20)); |
| + EXPECT_EQ(2u, lines.size()); |
| + EXPECT_EQ("12345", ToString(lines[0], node)); |
| + EXPECT_EQ("678", ToString(lines[1], node)); |
| +} |
| + |
| +TEST_F(NGLineBreakerTest, OverflowAtomicInline) { |
| + LoadAhem(); |
| + NGInlineNode* node = CreateInlineNode(R"HTML( |
| +<!DOCTYPE html> |
| +<style> |
| +#container { |
| + font: 10px/1 Ahem; |
| +} |
| +span { |
| + display: inline-block; |
| + width: 30px; |
| + height: 10px; |
| +} |
| +</style> |
| +<div id=container>12345<span></span>678</div> |
| +)HTML"); |
| + |
| + Vector<NGInlineItemResults> lines; |
| + lines = BreakLines(node, LayoutUnit(80)); |
| + EXPECT_EQ(2u, lines.size()); |
| + EXPECT_EQ(String(u"12345\uFFFC"), ToString(lines[0], node)); |
| + EXPECT_EQ("678", ToString(lines[1], node)); |
| + |
| + lines = BreakLines(node, LayoutUnit(70)); |
| + EXPECT_EQ(2u, lines.size()); |
| + EXPECT_EQ("12345", ToString(lines[0], node)); |
| + EXPECT_EQ(String(u"\uFFFC678"), ToString(lines[1], node)); |
| + |
| + lines = BreakLines(node, LayoutUnit(40)); |
| + EXPECT_EQ(3u, lines.size()); |
| + EXPECT_EQ("12345", ToString(lines[0], node)); |
| + EXPECT_EQ(String(u"\uFFFC"), ToString(lines[1], node)); |
| + EXPECT_EQ("678", ToString(lines[2], node)); |
| + |
| + lines = BreakLines(node, LayoutUnit(20)); |
| + EXPECT_EQ(3u, lines.size()); |
| + EXPECT_EQ("12345", ToString(lines[0], node)); |
| + EXPECT_EQ(String(u"\uFFFC"), ToString(lines[1], node)); |
| + EXPECT_EQ("678", ToString(lines[2], node)); |
| +} |
| + |
| +TEST_F(NGLineBreakerTest, OverflowMargin) { |
| + LoadAhem(); |
| + NGInlineNode* node = CreateInlineNode(R"HTML( |
| +<!DOCTYPE html> |
| +<style> |
| +#container { |
| + font: 10px/1 Ahem; |
| +} |
| +span { |
| + margin-right: 4em; |
| +} |
| +</style> |
| +<div id=container><span>123 456</span> 789</div> |
| +)HTML"); |
| + const Vector<NGInlineItem>& items = node->Items(); |
| + |
| + // While "123 456" can fit in a line, "456" has a right margin that cannot |
| + // fit. Since "456" and its right margin is not breakable, "456" should be on |
| + // the next line. |
| + Vector<NGInlineItemResults> lines; |
| + lines = BreakLines(node, LayoutUnit(80)); |
| + EXPECT_EQ(3u, lines.size()); |
| + EXPECT_EQ("123", ToString(lines[0], node)); |
| + EXPECT_EQ("456", ToString(lines[1], node)); |
| + DCHECK_EQ(NGInlineItem::kCloseTag, items[lines[1].back().item_index].Type()); |
| + EXPECT_EQ("789", ToString(lines[2], node)); |
| + |
| + // Same as above, but this time "456" overflows the line because it is 70px. |
| + lines = BreakLines(node, LayoutUnit(60)); |
| + EXPECT_EQ(3u, lines.size()); |
| + EXPECT_EQ("123", ToString(lines[0], node)); |
| + EXPECT_EQ("456", ToString(lines[1], node)); |
| + DCHECK_EQ(NGInlineItem::kCloseTag, items[lines[1].back().item_index].Type()); |
| + EXPECT_EQ("789", ToString(lines[2], node)); |
| +} |
| + |
| +TEST_F(NGLineBreakerTest, BoundaryInWord) { |
| + LoadAhem(); |
| + NGInlineNode* node = CreateInlineNode(R"HTML( |
| +<!DOCTYPE html> |
| +<style> |
| +#container { |
| + font: 10px/1 Ahem; |
| +} |
| +</style> |
| +<div id=container><span>123 456</span>789 abc</div> |
| +)HTML"); |
| + |
| + // The element boundary within "456789" should not cause a break. |
| + // Since "789" does not fit, it should go to the next line along with "456". |
| + Vector<NGInlineItemResults> lines; |
| + lines = BreakLines(node, LayoutUnit(80)); |
| + EXPECT_EQ(3u, lines.size()); |
| + EXPECT_EQ("123", ToString(lines[0], node)); |
| + EXPECT_EQ("456789", ToString(lines[1], node)); |
| + EXPECT_EQ("abc", ToString(lines[2], node)); |
| + |
| + // Same as above, but this time "456789" overflows the line because it is |
| + // 60px. |
| + lines = BreakLines(node, LayoutUnit(50)); |
| + EXPECT_EQ(3u, lines.size()); |
| + EXPECT_EQ("123", ToString(lines[0], node)); |
| + EXPECT_EQ("456789", ToString(lines[1], node)); |
| + EXPECT_EQ("abc", ToString(lines[2], node)); |
| +} |
| + |
| +TEST_F(NGLineBreakerTest, BoundaryInFirstWord) { |
| + LoadAhem(); |
| + NGInlineNode* node = CreateInlineNode(R"HTML( |
| +<!DOCTYPE html> |
|
ikilpatrick
2017/05/30 16:05:26
we've been indenting these.
kojii
2017/05/30 17:56:18
Done, didn't check other files, thank you!
|
| +<style> |
| +#container { |
| + font: 10px/1 Ahem; |
| +} |
| +</style> |
| +<div id=container><span>123</span>456 789</div> |
| +)HTML"); |
| + |
| + Vector<NGInlineItemResults> lines; |
| + lines = BreakLines(node, LayoutUnit(80)); |
| + EXPECT_EQ(2u, lines.size()); |
| + EXPECT_EQ("123456", ToString(lines[0], node)); |
| + EXPECT_EQ("789", ToString(lines[1], node)); |
| + |
| + lines = BreakLines(node, LayoutUnit(50)); |
| + EXPECT_EQ(2u, lines.size()); |
| + EXPECT_EQ("123456", ToString(lines[0], node)); |
| + EXPECT_EQ("789", ToString(lines[1], node)); |
| + |
| + lines = BreakLines(node, LayoutUnit(20)); |
| + EXPECT_EQ(2u, lines.size()); |
| + EXPECT_EQ("123456", ToString(lines[0], node)); |
| + EXPECT_EQ("789", ToString(lines[1], node)); |
| +} |
| + |
| +} // namespace |
| +} // namespace blink |