OLD | NEW |
---|---|
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/ng_line_builder.h" | 5 #include "core/layout/ng/ng_line_builder.h" |
6 | 6 |
7 #include "core/layout/BidiRun.h" | 7 #include "core/layout/BidiRun.h" |
8 #include "core/layout/LayoutBlockFlow.h" | 8 #include "core/layout/LayoutBlockFlow.h" |
9 #include "core/layout/line/LineInfo.h" | 9 #include "core/layout/line/LineInfo.h" |
10 #include "core/layout/line/RootInlineBox.h" | 10 #include "core/layout/line/RootInlineBox.h" |
(...skipping 10 matching lines...) Expand all Loading... | |
21 | 21 |
22 NGLineBuilder::NGLineBuilder(NGInlineNode* inline_box, | 22 NGLineBuilder::NGLineBuilder(NGInlineNode* inline_box, |
23 NGConstraintSpace* constraint_space, | 23 NGConstraintSpace* constraint_space, |
24 NGFragmentBuilder* containing_block_builder) | 24 NGFragmentBuilder* containing_block_builder) |
25 : inline_box_(inline_box), | 25 : inline_box_(inline_box), |
26 constraint_space_(constraint_space), | 26 constraint_space_(constraint_space), |
27 containing_block_builder_(containing_block_builder), | 27 containing_block_builder_(containing_block_builder), |
28 baseline_type_(constraint_space->WritingMode() == | 28 baseline_type_(constraint_space->WritingMode() == |
29 NGWritingMode::kHorizontalTopBottom | 29 NGWritingMode::kHorizontalTopBottom |
30 ? FontBaseline::AlphabeticBaseline | 30 ? FontBaseline::AlphabeticBaseline |
31 : FontBaseline::IdeographicBaseline) | 31 : FontBaseline::IdeographicBaseline), |
32 container_builder_(NGPhysicalFragment::kFragmentBox, inline_box_), | |
33 container_layout_result_(nullptr) | |
32 #if DCHECK_IS_ON() | 34 #if DCHECK_IS_ON() |
33 , | 35 , |
34 is_bidi_reordered_(false) | 36 is_bidi_reordered_(false) |
35 #endif | 37 #endif |
36 { | 38 { |
37 } | 39 } |
38 | 40 |
39 bool NGLineBuilder::CanFitOnLine() const { | 41 bool NGLineBuilder::CanFitOnLine() const { |
40 LayoutUnit available_size = current_opportunity_.InlineSize(); | 42 LayoutUnit available_size = current_opportunity_.InlineSize(); |
41 if (available_size == NGSizeIndefinite) | 43 if (available_size == NGSizeIndefinite) |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
199 unsigned logical_index = indices_in_visual_order[visual_index]; | 201 unsigned logical_index = indices_in_visual_order[visual_index]; |
200 line_item_chunks_in_visual_order[visual_index] = | 202 line_item_chunks_in_visual_order[visual_index] = |
201 (*line_item_chunks)[logical_index]; | 203 (*line_item_chunks)[logical_index]; |
202 } | 204 } |
203 line_item_chunks->swap(line_item_chunks_in_visual_order); | 205 line_item_chunks->swap(line_item_chunks_in_visual_order); |
204 } | 206 } |
205 | 207 |
206 void NGLineBuilder::PlaceItems( | 208 void NGLineBuilder::PlaceItems( |
207 const Vector<LineItemChunk, 32>& line_item_chunks) { | 209 const Vector<LineItemChunk, 32>& line_item_chunks) { |
208 const Vector<NGLayoutInlineItem>& items = inline_box_->Items(); | 210 const Vector<NGLayoutInlineItem>& items = inline_box_->Items(); |
209 const unsigned fragment_start_index = fragments_.size(); | 211 const unsigned fragment_start_index = container_builder_.Children().size(); |
210 | 212 |
211 NGFragmentBuilder text_builder(NGPhysicalFragment::kFragmentText, | 213 NGFragmentBuilder text_builder(NGPhysicalFragment::kFragmentText, |
212 inline_box_); | 214 inline_box_); |
213 text_builder.SetWritingMode(ConstraintSpace().WritingMode()); | 215 text_builder.SetWritingMode(ConstraintSpace().WritingMode()); |
214 line_box_data_list_.grow(line_box_data_list_.size() + 1); | 216 line_box_data_list_.grow(line_box_data_list_.size() + 1); |
215 LineBoxData& line_box_data = line_box_data_list_.back(); | 217 LineBoxData& line_box_data = line_box_data_list_.back(); |
216 | 218 |
217 // Accumulate a "strut"; a zero-width inline box with the element's font and | 219 // Accumulate a "strut"; a zero-width inline box with the element's font and |
218 // line height properties. https://drafts.csswg.org/css2/visudet.html#strut | 220 // line height properties. https://drafts.csswg.org/css2/visudet.html#strut |
219 const ComputedStyle* block_style = inline_box_->BlockStyle(); | 221 const ComputedStyle* block_style = inline_box_->BlockStyle(); |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
273 // The direction of a fragment is the CSS direction to resolve logical | 275 // The direction of a fragment is the CSS direction to resolve logical |
274 // properties, not the resolved bidi direction. | 276 // properties, not the resolved bidi direction. |
275 text_builder.SetDirection(style->direction()) | 277 text_builder.SetDirection(style->direction()) |
276 .SetInlineSize(line_item_chunk.inline_size) | 278 .SetInlineSize(line_item_chunk.inline_size) |
277 .SetInlineOverflow(line_item_chunk.inline_size) | 279 .SetInlineOverflow(line_item_chunk.inline_size) |
278 .SetBlockSize(height) | 280 .SetBlockSize(height) |
279 .SetBlockOverflow(height); | 281 .SetBlockOverflow(height); |
280 RefPtr<NGPhysicalTextFragment> text_fragment = text_builder.ToTextFragment( | 282 RefPtr<NGPhysicalTextFragment> text_fragment = text_builder.ToTextFragment( |
281 line_item_chunk.index, line_item_chunk.start_offset, | 283 line_item_chunk.index, line_item_chunk.start_offset, |
282 line_item_chunk.end_offset); | 284 line_item_chunk.end_offset); |
283 fragments_.push_back(std::move(text_fragment)); | |
284 | 285 |
285 NGLogicalOffset logical_offset( | 286 NGLogicalOffset logical_offset( |
286 line_box_data.inline_size + current_opportunity_.InlineStartOffset() - | 287 line_box_data.inline_size + current_opportunity_.InlineStartOffset() - |
287 ConstraintSpace().BfcOffset().inline_offset, | 288 ConstraintSpace().BfcOffset().inline_offset, |
288 top); | 289 top); |
289 offsets_.push_back(logical_offset); | 290 container_builder_.AddChild(std::move(text_fragment), logical_offset); |
290 line_box_data.inline_size += line_item_chunk.inline_size; | 291 line_box_data.inline_size += line_item_chunk.inline_size; |
291 } | 292 } |
292 DCHECK_EQ(fragments_.size(), offsets_.size()); | |
293 | 293 |
294 if (fragment_start_index == fragments_.size()) { | 294 if (fragment_start_index == container_builder_.Children().size()) { |
295 // The line was empty. Remove the LineBoxData. | 295 // The line was empty. Remove the LineBoxData. |
296 line_box_data_list_.shrink(line_box_data_list_.size() - 1); | 296 line_box_data_list_.shrink(line_box_data_list_.size() - 1); |
297 return; | 297 return; |
298 } | 298 } |
299 | 299 |
300 // If the estimated baseline position was not the actual position, move all | 300 // If the estimated baseline position was not the actual position, move all |
301 // fragments in the block direction. | 301 // fragments in the block direction. |
302 if (block_metrics.ascent_and_leading != | 302 if (block_metrics.ascent_and_leading != |
303 line_box_data.max_ascent_and_leading) { | 303 line_box_data.max_ascent_and_leading) { |
304 LayoutUnit adjust_top(line_box_data.max_ascent_and_leading - | 304 LayoutUnit adjust_top(line_box_data.max_ascent_and_leading - |
305 block_metrics.ascent_and_leading); | 305 block_metrics.ascent_and_leading); |
306 for (unsigned i = fragment_start_index; i < offsets_.size(); i++) | 306 auto& offsets = container_builder_.MutableOffsets(); |
307 offsets_[i].block_offset += adjust_top; | 307 for (unsigned i = fragment_start_index; i < offsets.size(); i++) |
308 offsets[i].block_offset += adjust_top; | |
308 } | 309 } |
309 | 310 |
310 line_box_data.fragment_end = fragments_.size(); | 311 line_box_data.fragment_end = container_builder_.Children().size(); |
311 line_box_data.top_with_leading = content_size_; | 312 line_box_data.top_with_leading = content_size_; |
312 max_inline_size_ = std::max(max_inline_size_, line_box_data.inline_size); | 313 max_inline_size_ = std::max(max_inline_size_, line_box_data.inline_size); |
313 content_size_ += LayoutUnit(line_box_data.max_ascent_and_leading + | 314 content_size_ += LayoutUnit(line_box_data.max_ascent_and_leading + |
314 line_box_data.max_descent_and_leading); | 315 line_box_data.max_descent_and_leading); |
315 } | 316 } |
316 | 317 |
317 NGLineBuilder::InlineItemMetrics::InlineItemMetrics( | 318 NGLineBuilder::InlineItemMetrics::InlineItemMetrics( |
318 const ComputedStyle& style, | 319 const ComputedStyle& style, |
319 FontBaseline baseline_type) { | 320 FontBaseline baseline_type) { |
320 const SimpleFontData* font_data = style.font().primaryFont(); | 321 const SimpleFontData* font_data = style.font().primaryFont(); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
371 NGLogicalOffset iter_offset = constraint_space_->BfcOffset(); | 372 NGLogicalOffset iter_offset = constraint_space_->BfcOffset(); |
372 iter_offset.block_offset += content_size_; | 373 iter_offset.block_offset += content_size_; |
373 auto* iter = constraint_space_->LayoutOpportunityIterator(iter_offset); | 374 auto* iter = constraint_space_->LayoutOpportunityIterator(iter_offset); |
374 NGLayoutOpportunity opportunity = iter->Next(); | 375 NGLayoutOpportunity opportunity = iter->Next(); |
375 if (!opportunity.IsEmpty()) | 376 if (!opportunity.IsEmpty()) |
376 current_opportunity_ = opportunity; | 377 current_opportunity_ = opportunity; |
377 } | 378 } |
378 | 379 |
379 RefPtr<NGLayoutResult> NGLineBuilder::CreateFragments() { | 380 RefPtr<NGLayoutResult> NGLineBuilder::CreateFragments() { |
380 DCHECK(!HasItems()) << "Must call CreateLine()"; | 381 DCHECK(!HasItems()) << "Must call CreateLine()"; |
381 DCHECK_EQ(fragments_.size(), offsets_.size()); | |
382 | |
383 NGFragmentBuilder container_builder(NGPhysicalFragment::kFragmentBox, | |
384 inline_box_); | |
385 | |
386 for (unsigned i = 0; i < fragments_.size(); i++) { | |
387 // TODO(layout-dev): This should really be a std::move but | |
388 // CopyFragmentDataToLayoutBlockFlow also uses the fragments. | |
389 container_builder.AddChild(fragments_[i].get(), offsets_[i]); | |
390 } | |
391 | 382 |
392 // TODO(kojii): Check if the line box width should be content or available. | 383 // TODO(kojii): Check if the line box width should be content or available. |
393 // TODO(kojii): Need to take constraint_space into account. | 384 // TODO(kojii): Need to take constraint_space into account. |
394 container_builder.SetInlineSize(max_inline_size_) | 385 container_builder_.SetInlineSize(max_inline_size_) |
395 .SetInlineOverflow(max_inline_size_) | 386 .SetInlineOverflow(max_inline_size_) |
396 .SetBlockSize(content_size_) | 387 .SetBlockSize(content_size_) |
397 .SetBlockOverflow(content_size_); | 388 .SetBlockOverflow(content_size_); |
398 | 389 |
399 return container_builder.ToBoxFragment(); | 390 container_layout_result_ = container_builder_.ToBoxFragment(); |
391 return container_layout_result_; | |
400 } | 392 } |
401 | 393 |
402 void NGLineBuilder::CopyFragmentDataToLayoutBlockFlow() { | 394 void NGLineBuilder::CopyFragmentDataToLayoutBlockFlow() { |
403 LayoutBlockFlow* block = inline_box_->GetLayoutBlockFlow(); | 395 LayoutBlockFlow* block = inline_box_->GetLayoutBlockFlow(); |
404 block->deleteLineBoxTree(); | 396 block->deleteLineBoxTree(); |
405 | 397 |
406 Vector<NGLayoutInlineItem>& items = inline_box_->Items(); | 398 Vector<NGLayoutInlineItem>& items = inline_box_->Items(); |
407 Vector<unsigned, 32> text_offsets(items.size()); | 399 Vector<unsigned, 32> text_offsets(items.size()); |
408 inline_box_->GetLayoutTextOffsets(&text_offsets); | 400 inline_box_->GetLayoutTextOffsets(&text_offsets); |
409 | 401 |
410 Vector<NGPhysicalFragment*, 32> fragments_for_bidi_runs; | 402 Vector<const NGPhysicalFragment*, 32> fragments_for_bidi_runs; |
411 fragments_for_bidi_runs.reserveInitialCapacity(items.size()); | 403 fragments_for_bidi_runs.reserveInitialCapacity(items.size()); |
412 BidiRunList<BidiRun> bidi_runs; | 404 BidiRunList<BidiRun> bidi_runs; |
413 LineInfo line_info; | 405 LineInfo line_info; |
414 unsigned fragment_index = 0; | 406 unsigned fragment_index = 0; |
407 NGPhysicalBoxFragment* box_fragment = toNGPhysicalBoxFragment( | |
408 container_layout_result_->PhysicalFragment().get()); | |
415 for (const auto& line_box_data : line_box_data_list_) { | 409 for (const auto& line_box_data : line_box_data_list_) { |
416 // Create a BidiRunList for this line. | 410 // Create a BidiRunList for this line. |
417 for (; fragment_index < line_box_data.fragment_end; fragment_index++) { | 411 for (; fragment_index < line_box_data.fragment_end; fragment_index++) { |
418 NGPhysicalTextFragment* text_fragment = | 412 RefPtr<NGPhysicalFragment> fragment = |
419 toNGPhysicalTextFragment(fragments_[fragment_index].get()); | 413 box_fragment->Children()[fragment_index]; |
ikilpatrick
2017/03/16 21:14:16
this gan just be a raw ptr? no transfer on ownersh
Gleb Lanbin
2017/03/16 21:20:18
Done.
| |
414 if (!fragment->IsText()) | |
415 continue; | |
416 const auto* text_fragment = toNGPhysicalTextFragment(fragment.get()); | |
420 const NGLayoutInlineItem& item = items[text_fragment->ItemIndex()]; | 417 const NGLayoutInlineItem& item = items[text_fragment->ItemIndex()]; |
421 LayoutObject* layout_object = item.GetLayoutObject(); | 418 LayoutObject* layout_object = item.GetLayoutObject(); |
422 if (!layout_object) // Skip bidi controls. | 419 if (!layout_object) // Skip bidi controls. |
423 continue; | 420 continue; |
424 BidiRun* run; | 421 BidiRun* run; |
425 if (layout_object->isText()) { | 422 if (layout_object->isText()) { |
426 unsigned text_offset = text_offsets[text_fragment->ItemIndex()]; | 423 unsigned text_offset = text_offsets[text_fragment->ItemIndex()]; |
427 run = new BidiRun(text_fragment->StartOffset() - text_offset, | 424 run = new BidiRun(text_fragment->StartOffset() - text_offset, |
428 text_fragment->EndOffset() - text_offset, | 425 text_fragment->EndOffset() - text_offset, |
429 item.BidiLevel(), LineLayoutItem(layout_object)); | 426 item.BidiLevel(), LineLayoutItem(layout_object)); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
471 baseline_position - LayoutUnit(line_box_data.max_ascent), | 468 baseline_position - LayoutUnit(line_box_data.max_ascent), |
472 baseline_position + LayoutUnit(line_box_data.max_descent), | 469 baseline_position + LayoutUnit(line_box_data.max_descent), |
473 line_box_data.top_with_leading, | 470 line_box_data.top_with_leading, |
474 baseline_position + LayoutUnit(line_box_data.max_descent_and_leading)); | 471 baseline_position + LayoutUnit(line_box_data.max_descent_and_leading)); |
475 | 472 |
476 bidi_runs.deleteRuns(); | 473 bidi_runs.deleteRuns(); |
477 fragments_for_bidi_runs.clear(); | 474 fragments_for_bidi_runs.clear(); |
478 } | 475 } |
479 } | 476 } |
480 } // namespace blink | 477 } // namespace blink |
OLD | NEW |