OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2017 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "core/layout/ng/ng_base_layout_algorithm_test.h" | |
6 | |
7 #include "core/layout/ng/inline/ng_inline_layout_algorithm.h" | |
8 #include "core/layout/ng/inline/ng_inline_node.h" | |
9 #include "core/layout/ng/inline/ng_line_breaker.h" | |
10 #include "core/layout/ng/layout_ng_block_flow.h" | |
11 #include "core/layout/ng/ng_constraint_space_builder.h" | |
12 #include "platform/wtf/text/StringBuilder.h" | |
13 | |
14 namespace blink { | |
15 | |
16 class NGLineBreakerTest : public NGBaseLayoutAlgorithmTest { | |
17 protected: | |
18 NGInlineNode* CreateInlineNode(const String& html_content) { | |
19 SetBodyInnerHTML(html_content); | |
20 | |
21 LayoutNGBlockFlow* block_flow = | |
22 ToLayoutNGBlockFlow(GetLayoutObjectByElementId("container")); | |
23 NGInlineNode* inline_node = | |
24 new NGInlineNode(block_flow->FirstChild(), block_flow); | |
25 | |
26 return inline_node; | |
27 } | |
28 | |
29 // Break lines using the specified available width. | |
30 Vector<NGInlineItemResults> BreakLines(NGInlineNode* node, | |
31 LayoutUnit available_width) { | |
32 if (!node->IsPrepareLayoutFinished()) | |
33 node->PrepareLayout(); | |
34 | |
35 RefPtr<NGConstraintSpace> space = | |
36 NGConstraintSpaceBuilder(NGWritingMode::kHorizontalTopBottom) | |
37 .SetAvailableSize({available_width, NGSizeIndefinite}) | |
38 .ToConstraintSpace(NGWritingMode::kHorizontalTopBottom); | |
39 NGLineBreaker line_breaker(node, space.Get()); | |
40 NGInlineLayoutAlgorithm algorithm(node, space.Get()); | |
41 Vector<NGInlineItemResults> lines; | |
42 while (true) { | |
43 NGInlineItemResults item_results; | |
44 line_breaker.NextLine(&item_results, &algorithm); | |
45 if (item_results.IsEmpty()) | |
46 break; | |
47 lines.push_back(item_results); | |
48 } | |
49 return lines; | |
50 } | |
51 }; | |
52 | |
53 namespace { | |
54 | |
55 String ToString(NGInlineItemResults line, NGInlineNode* node) { | |
56 StringBuilder builder; | |
57 for (const auto& item_result : line) { | |
58 builder.Append( | |
59 node->Text(item_result.start_offset, item_result.end_offset)); | |
60 } | |
61 return builder.ToString(); | |
62 } | |
63 | |
64 TEST_F(NGLineBreakerTest, SingleNode) { | |
65 LoadAhem(); | |
66 NGInlineNode* node = CreateInlineNode(R"HTML( | |
67 <!DOCTYPE html> | |
68 <style> | |
69 #container { | |
70 font: 10px/1 Ahem; | |
71 } | |
72 </style> | |
73 <div id=container>123 456 789</div> | |
74 )HTML"); | |
75 | |
76 Vector<NGInlineItemResults> lines; | |
77 lines = BreakLines(node, LayoutUnit(80)); | |
78 EXPECT_EQ(2u, lines.size()); | |
79 EXPECT_EQ("123 456", ToString(lines[0], node)); | |
80 EXPECT_EQ("789", ToString(lines[1], node)); | |
81 | |
82 lines = BreakLines(node, LayoutUnit(60)); | |
83 EXPECT_EQ(3u, lines.size()); | |
84 EXPECT_EQ("123", ToString(lines[0], node)); | |
85 EXPECT_EQ("456", ToString(lines[1], node)); | |
86 EXPECT_EQ("789", ToString(lines[2], node)); | |
87 } | |
88 | |
89 TEST_F(NGLineBreakerTest, OverflowWord) { | |
90 LoadAhem(); | |
91 NGInlineNode* node = CreateInlineNode(R"HTML( | |
92 <!DOCTYPE html> | |
93 <style> | |
94 #container { | |
95 font: 10px/1 Ahem; | |
96 } | |
97 </style> | |
98 <div id=container>12345 678</div> | |
99 )HTML"); | |
100 | |
101 // The first line overflows, but the last line does not. | |
102 Vector<NGInlineItemResults> lines; | |
103 lines = BreakLines(node, LayoutUnit(40)); | |
104 EXPECT_EQ(2u, lines.size()); | |
105 EXPECT_EQ("12345", ToString(lines[0], node)); | |
106 EXPECT_EQ("678", ToString(lines[1], node)); | |
107 | |
108 // Both lines overflow. | |
109 lines = BreakLines(node, LayoutUnit(20)); | |
110 EXPECT_EQ(2u, lines.size()); | |
111 EXPECT_EQ("12345", ToString(lines[0], node)); | |
112 EXPECT_EQ("678", ToString(lines[1], node)); | |
113 } | |
114 | |
115 TEST_F(NGLineBreakerTest, OverflowAtomicInline) { | |
116 LoadAhem(); | |
117 NGInlineNode* node = CreateInlineNode(R"HTML( | |
118 <!DOCTYPE html> | |
119 <style> | |
120 #container { | |
121 font: 10px/1 Ahem; | |
122 } | |
123 span { | |
124 display: inline-block; | |
125 width: 30px; | |
126 height: 10px; | |
127 } | |
128 </style> | |
129 <div id=container>12345<span></span>678</div> | |
130 )HTML"); | |
131 | |
132 Vector<NGInlineItemResults> lines; | |
133 lines = BreakLines(node, LayoutUnit(80)); | |
134 EXPECT_EQ(2u, lines.size()); | |
135 EXPECT_EQ(String(u"12345\uFFFC"), ToString(lines[0], node)); | |
136 EXPECT_EQ("678", ToString(lines[1], node)); | |
137 | |
138 lines = BreakLines(node, LayoutUnit(70)); | |
139 EXPECT_EQ(2u, lines.size()); | |
140 EXPECT_EQ("12345", ToString(lines[0], node)); | |
141 EXPECT_EQ(String(u"\uFFFC678"), ToString(lines[1], node)); | |
142 | |
143 lines = BreakLines(node, LayoutUnit(40)); | |
144 EXPECT_EQ(3u, lines.size()); | |
145 EXPECT_EQ("12345", ToString(lines[0], node)); | |
146 EXPECT_EQ(String(u"\uFFFC"), ToString(lines[1], node)); | |
147 EXPECT_EQ("678", ToString(lines[2], node)); | |
148 | |
149 lines = BreakLines(node, LayoutUnit(20)); | |
150 EXPECT_EQ(3u, lines.size()); | |
151 EXPECT_EQ("12345", ToString(lines[0], node)); | |
152 EXPECT_EQ(String(u"\uFFFC"), ToString(lines[1], node)); | |
153 EXPECT_EQ("678", ToString(lines[2], node)); | |
154 } | |
155 | |
156 TEST_F(NGLineBreakerTest, OverflowMargin) { | |
157 LoadAhem(); | |
158 NGInlineNode* node = CreateInlineNode(R"HTML( | |
159 <!DOCTYPE html> | |
160 <style> | |
161 #container { | |
162 font: 10px/1 Ahem; | |
163 } | |
164 span { | |
165 margin-right: 4em; | |
166 } | |
167 </style> | |
168 <div id=container><span>123 456</span> 789</div> | |
169 )HTML"); | |
170 const Vector<NGInlineItem>& items = node->Items(); | |
171 | |
172 // While "123 456" can fit in a line, "456" has a right margin that cannot | |
173 // fit. Since "456" and its right margin is not breakable, "456" should be on | |
174 // the next line. | |
175 Vector<NGInlineItemResults> lines; | |
176 lines = BreakLines(node, LayoutUnit(80)); | |
177 EXPECT_EQ(3u, lines.size()); | |
178 EXPECT_EQ("123", ToString(lines[0], node)); | |
179 EXPECT_EQ("456", ToString(lines[1], node)); | |
180 DCHECK_EQ(NGInlineItem::kCloseTag, items[lines[1].back().item_index].Type()); | |
181 EXPECT_EQ("789", ToString(lines[2], node)); | |
182 | |
183 // Same as above, but this time "456" overflows the line because it is 70px. | |
184 lines = BreakLines(node, LayoutUnit(60)); | |
185 EXPECT_EQ(3u, lines.size()); | |
186 EXPECT_EQ("123", ToString(lines[0], node)); | |
187 EXPECT_EQ("456", ToString(lines[1], node)); | |
188 DCHECK_EQ(NGInlineItem::kCloseTag, items[lines[1].back().item_index].Type()); | |
189 EXPECT_EQ("789", ToString(lines[2], node)); | |
190 } | |
191 | |
192 TEST_F(NGLineBreakerTest, BoundaryInWord) { | |
193 LoadAhem(); | |
194 NGInlineNode* node = CreateInlineNode(R"HTML( | |
195 <!DOCTYPE html> | |
196 <style> | |
197 #container { | |
198 font: 10px/1 Ahem; | |
199 } | |
200 </style> | |
201 <div id=container><span>123 456</span>789 abc</div> | |
202 )HTML"); | |
203 | |
204 // The element boundary within "456789" should not cause a break. | |
205 // Since "789" does not fit, it should go to the next line along with "456". | |
206 Vector<NGInlineItemResults> lines; | |
207 lines = BreakLines(node, LayoutUnit(80)); | |
208 EXPECT_EQ(3u, lines.size()); | |
209 EXPECT_EQ("123", ToString(lines[0], node)); | |
210 EXPECT_EQ("456789", ToString(lines[1], node)); | |
211 EXPECT_EQ("abc", ToString(lines[2], node)); | |
212 | |
213 // Same as above, but this time "456789" overflows the line because it is | |
214 // 60px. | |
215 lines = BreakLines(node, LayoutUnit(50)); | |
216 EXPECT_EQ(3u, lines.size()); | |
217 EXPECT_EQ("123", ToString(lines[0], node)); | |
218 EXPECT_EQ("456789", ToString(lines[1], node)); | |
219 EXPECT_EQ("abc", ToString(lines[2], node)); | |
220 } | |
221 | |
222 TEST_F(NGLineBreakerTest, BoundaryInFirstWord) { | |
223 LoadAhem(); | |
224 NGInlineNode* node = CreateInlineNode(R"HTML( | |
225 <!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!
| |
226 <style> | |
227 #container { | |
228 font: 10px/1 Ahem; | |
229 } | |
230 </style> | |
231 <div id=container><span>123</span>456 789</div> | |
232 )HTML"); | |
233 | |
234 Vector<NGInlineItemResults> lines; | |
235 lines = BreakLines(node, LayoutUnit(80)); | |
236 EXPECT_EQ(2u, lines.size()); | |
237 EXPECT_EQ("123456", ToString(lines[0], node)); | |
238 EXPECT_EQ("789", ToString(lines[1], node)); | |
239 | |
240 lines = BreakLines(node, LayoutUnit(50)); | |
241 EXPECT_EQ(2u, lines.size()); | |
242 EXPECT_EQ("123456", ToString(lines[0], node)); | |
243 EXPECT_EQ("789", ToString(lines[1], node)); | |
244 | |
245 lines = BreakLines(node, LayoutUnit(20)); | |
246 EXPECT_EQ(2u, lines.size()); | |
247 EXPECT_EQ("123456", ToString(lines[0], node)); | |
248 EXPECT_EQ("789", ToString(lines[1], node)); | |
249 } | |
250 | |
251 } // namespace | |
252 } // namespace blink | |
OLD | NEW |