Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(125)

Side by Side Diff: third_party/WebKit/Source/core/layout/ng/inline/ng_line_breaker.cc

Issue 2888643004: [LayoutNG] Implement LayoutBR/preserved newlines and tabs (Closed)
Patch Set: Rebase Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "core/layout/ng/inline/ng_line_breaker.h" 5 #include "core/layout/ng/inline/ng_line_breaker.h"
6 6
7 #include "core/layout/ng/inline/ng_inline_break_token.h" 7 #include "core/layout/ng/inline/ng_inline_break_token.h"
8 #include "core/layout/ng/inline/ng_inline_layout_algorithm.h" 8 #include "core/layout/ng/inline/ng_inline_layout_algorithm.h"
9 #include "core/layout/ng/inline/ng_inline_node.h" 9 #include "core/layout/ng/inline/ng_inline_node.h"
10 #include "core/layout/ng/inline/ng_text_fragment.h" 10 #include "core/layout/ng/inline/ng_text_fragment.h"
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
120 item_results->push_back( 120 item_results->push_back(
121 NGInlineItemResult(item_index_, offset_, item.EndOffset())); 121 NGInlineItemResult(item_index_, offset_, item.EndOffset()));
122 NGInlineItemResult* item_result = &item_results->back(); 122 NGInlineItemResult* item_result = &item_results->back();
123 123
124 // If the start offset is at the item boundary, try to add the entire item. 124 // If the start offset is at the item boundary, try to add the entire item.
125 if (offset_ == item.StartOffset()) { 125 if (offset_ == item.StartOffset()) {
126 if (item.Type() == NGInlineItem::kText) { 126 if (item.Type() == NGInlineItem::kText) {
127 item_result->inline_size = item.InlineSize(); 127 item_result->inline_size = item.InlineSize();
128 } else if (item.Type() == NGInlineItem::kAtomicInline) { 128 } else if (item.Type() == NGInlineItem::kAtomicInline) {
129 LayoutAtomicInline(item, item_result); 129 LayoutAtomicInline(item, item_result);
130 } else if (item.Type() == NGInlineItem::kControl) {
131 if (HandleControlItem(item, text, item_result, position)) {
132 MoveToNextOf(item);
133 break;
134 }
130 } else if (item.Type() == NGInlineItem::kFloating) { 135 } else if (item.Type() == NGInlineItem::kFloating) {
131 algorithm->LayoutAndPositionFloat(position, item.GetLayoutObject()); 136 algorithm->LayoutAndPositionFloat(position, item.GetLayoutObject());
132 // Floats may change the available width if they fit. 137 // Floats may change the available width if they fit.
133 available_width = algorithm->AvailableWidth(); 138 available_width = algorithm->AvailableWidth();
134 // Floats are already positioned in the container_builder. 139 // Floats are already positioned in the container_builder.
135 item_results->pop_back(); 140 item_results->pop_back();
136 offset_ = item.EndOffset(); 141 MoveToNextOf(item);
137 item_index_++;
138 continue; 142 continue;
139 } else { 143 } else {
140 offset_ = item.EndOffset(); 144 MoveToNextOf(item);
141 item_index_++;
142 continue; 145 continue;
143 } 146 }
144 LayoutUnit next_position = position + item_result->inline_size; 147 LayoutUnit next_position = position + item_result->inline_size;
145 if (next_position <= available_width) { 148 if (next_position <= available_width) {
146 offset_ = item.EndOffset(); 149 MoveToNextOf(item);
147 item_index_++;
148 position = next_position; 150 position = next_position;
149 continue; 151 continue;
150 } 152 }
151 153
152 // The entire item does not fit. Handle non-text items as overflow, 154 // The entire item does not fit. Handle non-text items as overflow,
153 // since only text item is breakable. 155 // since only text item is breakable.
154 if (item.Type() != NGInlineItem::kText) { 156 if (item.Type() != NGInlineItem::kText) {
155 offset_ = item.EndOffset(); 157 MoveToNextOf(item);
156 item_index_++;
157 return HandleOverflow(item_results, break_iterator); 158 return HandleOverflow(item_results, break_iterator);
158 } 159 }
159 } 160 }
160 161
161 // Either the start or the break is in the mid of a text item. 162 // Either the start or the break is in the mid of a text item.
162 DCHECK_EQ(item.Type(), NGInlineItem::kText); 163 DCHECK_EQ(item.Type(), NGInlineItem::kText);
163 DCHECK_LT(offset_, item.EndOffset()); 164 DCHECK_LT(offset_, item.EndOffset());
164 break_iterator.SetLocale(item.Style()->LocaleForLineBreakIterator()); 165 break_iterator.SetLocale(item.Style()->LocaleForLineBreakIterator());
165 break_iterator.SetBreakType(GetLineBreakType(*item.Style())); 166 break_iterator.SetBreakType(GetLineBreakType(*item.Style()));
166 #if defined(MOCK_SHAPE_LINE) 167 #if defined(MOCK_SHAPE_LINE)
(...skipping 20 matching lines...) Expand all
187 188
188 // If the break found within the item, break here. 189 // If the break found within the item, break here.
189 if (break_offset < item.EndOffset()) { 190 if (break_offset < item.EndOffset()) {
190 offset_ = item_result->end_offset = break_offset; 191 offset_ = item_result->end_offset = break_offset;
191 if (position <= available_width) 192 if (position <= available_width)
192 break; 193 break;
193 // The first break opportunity of the item does not fit. 194 // The first break opportunity of the item does not fit.
194 } else { 195 } else {
195 // No break opporunity in the item, or the first break opportunity is at 196 // No break opporunity in the item, or the first break opportunity is at
196 // the end of the item. If it fits, continue to the next item. 197 // the end of the item. If it fits, continue to the next item.
197 offset_ = item_result->end_offset = item.EndOffset(); 198 item_result->end_offset = item.EndOffset();
198 item_index_++; 199 MoveToNextOf(item);
199 if (position <= available_width) 200 if (position <= available_width)
200 continue; 201 continue;
201 } 202 }
202 203
203 // We need to look at next item if we're overflowing, and the break 204 // We need to look at next item if we're overflowing, and the break
204 // opportunity is beyond this item. 205 // opportunity is beyond this item.
205 if (break_offset > item.EndOffset()) 206 if (break_offset > item.EndOffset())
206 continue; 207 continue;
207 return HandleOverflow(item_results, break_iterator); 208 return HandleOverflow(item_results, break_iterator);
208 } 209 }
209 } 210 }
210 211
212 // Measure control items; new lines and tab, that are similar to text, affect
213 // layout, but do not need shaping/painting.
214 bool NGLineBreaker::HandleControlItem(const NGInlineItem& item,
215 const String& text,
216 NGInlineItemResult* item_result,
217 LayoutUnit position) {
218 DCHECK_EQ(item.Length(), 1u);
219 UChar character = text[item.StartOffset()];
220 if (character == kNewlineCharacter)
221 return true;
222
223 DCHECK_EQ(character, kTabulationCharacter);
224 DCHECK(item.Style());
225 const ComputedStyle& style = *item.Style();
226 const Font& font = style.GetFont();
227 item_result->inline_size = font.TabWidth(style.GetTabSize(), position);
228 return false;
229 }
230
211 void NGLineBreaker::LayoutAtomicInline(const NGInlineItem& item, 231 void NGLineBreaker::LayoutAtomicInline(const NGInlineItem& item,
212 NGInlineItemResult* item_result) { 232 NGInlineItemResult* item_result) {
213 DCHECK_EQ(item.Type(), NGInlineItem::kAtomicInline); 233 DCHECK_EQ(item.Type(), NGInlineItem::kAtomicInline);
214 NGBlockNode* node = new NGBlockNode(item.GetLayoutObject()); 234 NGBlockNode* node = new NGBlockNode(item.GetLayoutObject());
215 const ComputedStyle& style = node->Style(); 235 const ComputedStyle& style = node->Style();
216 NGConstraintSpaceBuilder constraint_space_builder(constraint_space_); 236 NGConstraintSpaceBuilder constraint_space_builder(constraint_space_);
217 RefPtr<NGConstraintSpace> constraint_space = 237 RefPtr<NGConstraintSpace> constraint_space =
218 constraint_space_builder.SetIsNewFormattingContext(true) 238 constraint_space_builder.SetIsNewFormattingContext(true)
219 .SetIsShrinkToFit(true) 239 .SetIsShrinkToFit(true)
220 .SetTextDirection(style.Direction()) 240 .SetTextDirection(style.Direction())
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
285 item_results->Shrink(new_end); 305 item_results->Shrink(new_end);
286 306
287 // Update the current item index and offset to the new break point. 307 // Update the current item index and offset to the new break point.
288 const NGInlineItemResult& last_item_result = item_results->back(); 308 const NGInlineItemResult& last_item_result = item_results->back();
289 offset_ = last_item_result.end_offset; 309 offset_ = last_item_result.end_offset;
290 item_index_ = last_item_result.item_index; 310 item_index_ = last_item_result.item_index;
291 if (items[item_index_].EndOffset() == offset_) 311 if (items[item_index_].EndOffset() == offset_)
292 item_index_++; 312 item_index_++;
293 } 313 }
294 314
315 void NGLineBreaker::MoveToNextOf(const NGInlineItem& item) {
316 DCHECK_EQ(&item, &node_->Items()[item_index_]);
317 offset_ = item.EndOffset();
318 item_index_++;
319 }
320
295 void NGLineBreaker::SkipCollapsibleWhitespaces() { 321 void NGLineBreaker::SkipCollapsibleWhitespaces() {
296 const Vector<NGInlineItem>& items = node_->Items(); 322 const Vector<NGInlineItem>& items = node_->Items();
297 if (item_index_ >= items.size()) 323 if (item_index_ >= items.size())
298 return; 324 return;
299 const NGInlineItem& item = items[item_index_]; 325 const NGInlineItem& item = items[item_index_];
300 if (item.Type() != NGInlineItem::kText || !item.Style()->CollapseWhiteSpace()) 326 if (item.Type() != NGInlineItem::kText || !item.Style()->CollapseWhiteSpace())
301 return; 327 return;
302 328
303 DCHECK_LT(offset_, item.EndOffset()); 329 DCHECK_LT(offset_, item.EndOffset());
304 if (node_->Text()[offset_] == kSpaceCharacter) { 330 if (node_->Text()[offset_] == kSpaceCharacter) {
(...skipping 17 matching lines...) Expand all
322 } 348 }
323 349
324 RefPtr<NGInlineBreakToken> NGLineBreaker::CreateBreakToken() const { 350 RefPtr<NGInlineBreakToken> NGLineBreaker::CreateBreakToken() const {
325 const Vector<NGInlineItem>& items = node_->Items(); 351 const Vector<NGInlineItem>& items = node_->Items();
326 if (item_index_ >= items.size()) 352 if (item_index_ >= items.size())
327 return nullptr; 353 return nullptr;
328 return NGInlineBreakToken::Create(node_, item_index_, offset_); 354 return NGInlineBreakToken::Create(node_, item_index_, offset_);
329 } 355 }
330 356
331 } // namespace blink 357 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/layout/ng/inline/ng_line_breaker.h ('k') | third_party/WebKit/Source/platform/fonts/Font.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698