| 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_inline_layout_algorithm.h" | 5 #include "core/layout/ng/ng_inline_layout_algorithm.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 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 61 NGLogicalOffset offset = PositionFloat(origin_point, space->BfcOffset(), | 61 NGLogicalOffset offset = PositionFloat(origin_point, space->BfcOffset(), |
| 62 floating_object.get(), space); | 62 floating_object.get(), space); |
| 63 builder->AddFloatingObject(floating_object, offset); | 63 builder->AddFloatingObject(floating_object, offset); |
| 64 } | 64 } |
| 65 builder->MutableUnpositionedFloats().clear(); | 65 builder->MutableUnpositionedFloats().clear(); |
| 66 } | 66 } |
| 67 | 67 |
| 68 } // namespace | 68 } // namespace |
| 69 | 69 |
| 70 NGInlineLayoutAlgorithm::NGInlineLayoutAlgorithm( | 70 NGInlineLayoutAlgorithm::NGInlineLayoutAlgorithm( |
| 71 NGInlineNode* inline_box, | 71 NGInlineNode* inline_node, |
| 72 NGConstraintSpace* constraint_space, | 72 NGConstraintSpace* space, |
| 73 NGInlineBreakToken* break_token) | 73 NGInlineBreakToken* break_token) |
| 74 : inline_box_(inline_box), | 74 : NGLayoutAlgorithm(inline_node, space, break_token), |
| 75 constraint_space_(constraint_space), | 75 container_builder_(NGPhysicalFragment::kFragmentBox, inline_node), |
| 76 container_builder_(NGPhysicalFragment::kFragmentBox, inline_box_), | |
| 77 is_horizontal_writing_mode_( | 76 is_horizontal_writing_mode_( |
| 78 blink::IsHorizontalWritingMode(constraint_space->WritingMode())), | 77 blink::IsHorizontalWritingMode(space->WritingMode())), |
| 79 space_builder_(constraint_space) | 78 space_builder_(space) |
| 80 #if DCHECK_IS_ON() | 79 #if DCHECK_IS_ON() |
| 81 , | 80 , |
| 82 is_bidi_reordered_(false) | 81 is_bidi_reordered_(false) |
| 83 #endif | 82 #endif |
| 84 { | 83 { |
| 85 if (!is_horizontal_writing_mode_) | 84 if (!is_horizontal_writing_mode_) |
| 86 baseline_type_ = FontBaseline::IdeographicBaseline; | 85 baseline_type_ = FontBaseline::IdeographicBaseline; |
| 87 if (break_token) | 86 if (break_token) |
| 88 Initialize(break_token->ItemIndex(), break_token->TextOffset()); | 87 Initialize(break_token->ItemIndex(), break_token->TextOffset()); |
| 89 else | 88 else |
| (...skipping 14 matching lines...) Expand all Loading... |
| 104 bool NGInlineLayoutAlgorithm::HasBreakOpportunity() const { | 103 bool NGInlineLayoutAlgorithm::HasBreakOpportunity() const { |
| 105 return start_offset_ != last_break_opportunity_offset_; | 104 return start_offset_ != last_break_opportunity_offset_; |
| 106 } | 105 } |
| 107 | 106 |
| 108 bool NGInlineLayoutAlgorithm::HasItemsAfterLastBreakOpportunity() const { | 107 bool NGInlineLayoutAlgorithm::HasItemsAfterLastBreakOpportunity() const { |
| 109 return last_break_opportunity_offset_ != end_offset_; | 108 return last_break_opportunity_offset_ != end_offset_; |
| 110 } | 109 } |
| 111 | 110 |
| 112 void NGInlineLayoutAlgorithm::Initialize(unsigned index, unsigned offset) { | 111 void NGInlineLayoutAlgorithm::Initialize(unsigned index, unsigned offset) { |
| 113 if (index || offset) | 112 if (index || offset) |
| 114 inline_box_->AssertOffset(index, offset); | 113 Node()->AssertOffset(index, offset); |
| 115 | 114 |
| 116 start_index_ = last_index_ = last_break_opportunity_index_ = index; | 115 start_index_ = last_index_ = last_break_opportunity_index_ = index; |
| 117 start_offset_ = end_offset_ = last_break_opportunity_offset_ = offset; | 116 start_offset_ = end_offset_ = last_break_opportunity_offset_ = offset; |
| 118 end_position_ = last_break_opportunity_position_ = LayoutUnit(); | 117 end_position_ = last_break_opportunity_position_ = LayoutUnit(); |
| 119 | 118 |
| 120 FindNextLayoutOpportunity(); | 119 FindNextLayoutOpportunity(); |
| 121 } | 120 } |
| 122 | 121 |
| 123 void NGInlineLayoutAlgorithm::SetEnd(unsigned new_end_offset) { | 122 void NGInlineLayoutAlgorithm::SetEnd(unsigned new_end_offset) { |
| 124 DCHECK_GT(new_end_offset, end_offset_); | 123 DCHECK_GT(new_end_offset, end_offset_); |
| 125 const Vector<NGLayoutInlineItem>& items = inline_box_->Items(); | 124 const Vector<NGLayoutInlineItem>& items = Node()->Items(); |
| 126 DCHECK_LE(new_end_offset, items.back().EndOffset()); | 125 DCHECK_LE(new_end_offset, items.back().EndOffset()); |
| 127 | 126 |
| 128 // SetEnd() while |new_end_offset| is beyond the current last item. | 127 // SetEnd() while |new_end_offset| is beyond the current last item. |
| 129 unsigned index = last_index_; | 128 unsigned index = last_index_; |
| 130 const NGLayoutInlineItem* item = &items[index]; | 129 const NGLayoutInlineItem* item = &items[index]; |
| 131 if (new_end_offset > item->EndOffset()) { | 130 if (new_end_offset > item->EndOffset()) { |
| 132 if (end_offset_ < item->EndOffset()) { | 131 if (end_offset_ < item->EndOffset()) { |
| 133 SetEnd(index, item->EndOffset(), | 132 SetEnd(index, item->EndOffset(), |
| 134 InlineSize(*item, end_offset_, item->EndOffset())); | 133 InlineSize(*item, end_offset_, item->EndOffset())); |
| 135 } | 134 } |
| (...skipping 12 matching lines...) Expand all Loading... |
| 148 item = &items[++index]; | 147 item = &items[++index]; |
| 149 if (item->Type() != NGLayoutInlineItem::kCloseTag) | 148 if (item->Type() != NGLayoutInlineItem::kCloseTag) |
| 150 break; | 149 break; |
| 151 SetEnd(index, new_end_offset, InlineSize(*item)); | 150 SetEnd(index, new_end_offset, InlineSize(*item)); |
| 152 } | 151 } |
| 153 } | 152 } |
| 154 | 153 |
| 155 void NGInlineLayoutAlgorithm::SetEnd(unsigned index, | 154 void NGInlineLayoutAlgorithm::SetEnd(unsigned index, |
| 156 unsigned new_end_offset, | 155 unsigned new_end_offset, |
| 157 LayoutUnit inline_size_since_current_end) { | 156 LayoutUnit inline_size_since_current_end) { |
| 158 const Vector<NGLayoutInlineItem>& items = inline_box_->Items(); | 157 const Vector<NGLayoutInlineItem>& items = Node()->Items(); |
| 159 DCHECK_LE(new_end_offset, items.back().EndOffset()); | 158 DCHECK_LE(new_end_offset, items.back().EndOffset()); |
| 160 | 159 |
| 161 // |new_end_offset| should be in the current item or next. | 160 // |new_end_offset| should be in the current item or next. |
| 162 // TODO(kojii): Reconsider this restriction if needed. | 161 // TODO(kojii): Reconsider this restriction if needed. |
| 163 DCHECK((index == last_index_ && new_end_offset > end_offset_) || | 162 DCHECK((index == last_index_ && new_end_offset > end_offset_) || |
| 164 (index == last_index_ + 1 && new_end_offset >= end_offset_ && | 163 (index == last_index_ + 1 && new_end_offset >= end_offset_ && |
| 165 end_offset_ == items[last_index_].EndOffset())); | 164 end_offset_ == items[last_index_].EndOffset())); |
| 166 const NGLayoutInlineItem& item = items[index]; | 165 const NGLayoutInlineItem& item = items[index]; |
| 167 item.AssertEndOffset(new_end_offset); | 166 item.AssertEndOffset(new_end_offset); |
| 168 | 167 |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 205 const NGLayoutInlineItem& item) { | 204 const NGLayoutInlineItem& item) { |
| 206 return NGBoxFragment(ConstraintSpace().WritingMode(), | 205 return NGBoxFragment(ConstraintSpace().WritingMode(), |
| 207 toNGPhysicalBoxFragment( | 206 toNGPhysicalBoxFragment( |
| 208 LayoutItem(item)->PhysicalFragment().get())) | 207 LayoutItem(item)->PhysicalFragment().get())) |
| 209 .InlineSize(); | 208 .InlineSize(); |
| 210 } | 209 } |
| 211 | 210 |
| 212 const NGLayoutResult* NGInlineLayoutAlgorithm::LayoutItem( | 211 const NGLayoutResult* NGInlineLayoutAlgorithm::LayoutItem( |
| 213 const NGLayoutInlineItem& item) { | 212 const NGLayoutInlineItem& item) { |
| 214 // Returns the cached NGLayoutResult if available. | 213 // Returns the cached NGLayoutResult if available. |
| 215 const Vector<NGLayoutInlineItem>& items = inline_box_->Items(); | 214 const Vector<NGLayoutInlineItem>& items = Node()->Items(); |
| 216 if (layout_results_.isEmpty()) | 215 if (layout_results_.isEmpty()) |
| 217 layout_results_.resize(items.size()); | 216 layout_results_.resize(items.size()); |
| 218 unsigned index = std::distance(items.begin(), &item); | 217 unsigned index = std::distance(items.begin(), &item); |
| 219 RefPtr<NGLayoutResult>* layout_result = &layout_results_[index]; | 218 RefPtr<NGLayoutResult>* layout_result = &layout_results_[index]; |
| 220 if (*layout_result) | 219 if (*layout_result) |
| 221 return layout_result->get(); | 220 return layout_result->get(); |
| 222 | 221 |
| 223 DCHECK(item.Type() == NGLayoutInlineItem::kAtomicInline); | 222 DCHECK(item.Type() == NGLayoutInlineItem::kAtomicInline); |
| 224 NGBlockNode* node = new NGBlockNode(item.GetLayoutObject()); | 223 NGBlockNode* node = new NGBlockNode(item.GetLayoutObject()); |
| 225 // TODO(kojii): Keep node in NGLayoutInlineItem. | 224 // TODO(kojii): Keep node in NGLayoutInlineItem. |
| 226 const ComputedStyle& style = node->Style(); | 225 const ComputedStyle& style = node->Style(); |
| 227 NGConstraintSpaceBuilder constraint_space_builder(&ConstraintSpace()); | 226 NGConstraintSpaceBuilder constraint_space_builder(&ConstraintSpace()); |
| 228 RefPtr<NGConstraintSpace> constraint_space = | 227 RefPtr<NGConstraintSpace> constraint_space = |
| 229 constraint_space_builder.SetIsNewFormattingContext(true) | 228 constraint_space_builder.SetIsNewFormattingContext(true) |
| 230 .SetIsShrinkToFit(true) | 229 .SetIsShrinkToFit(true) |
| 231 .SetTextDirection(style.direction()) | 230 .SetTextDirection(style.direction()) |
| 232 .ToConstraintSpace(FromPlatformWritingMode(style.getWritingMode())); | 231 .ToConstraintSpace(FromPlatformWritingMode(style.getWritingMode())); |
| 233 *layout_result = node->Layout(constraint_space.get()); | 232 *layout_result = node->Layout(constraint_space.get()); |
| 234 return layout_result->get(); | 233 return layout_result->get(); |
| 235 } | 234 } |
| 236 | 235 |
| 237 bool NGInlineLayoutAlgorithm::CreateLine() { | 236 bool NGInlineLayoutAlgorithm::CreateLine() { |
| 238 if (HasItemsAfterLastBreakOpportunity()) | 237 if (HasItemsAfterLastBreakOpportunity()) |
| 239 SetBreakOpportunity(); | 238 SetBreakOpportunity(); |
| 240 return CreateLineUpToLastBreakOpportunity(); | 239 return CreateLineUpToLastBreakOpportunity(); |
| 241 } | 240 } |
| 242 | 241 |
| 243 bool NGInlineLayoutAlgorithm::CreateLineUpToLastBreakOpportunity() { | 242 bool NGInlineLayoutAlgorithm::CreateLineUpToLastBreakOpportunity() { |
| 244 const Vector<NGLayoutInlineItem>& items = inline_box_->Items(); | 243 const Vector<NGLayoutInlineItem>& items = Node()->Items(); |
| 245 | 244 |
| 246 // Create a list of LineItemChunk from |start| and |last_break_opportunity|. | 245 // Create a list of LineItemChunk from |start| and |last_break_opportunity|. |
| 247 // TODO(kojii): Consider refactoring LineItemChunk once NGLineBuilder's public | 246 // TODO(kojii): Consider refactoring LineItemChunk once NGLineBuilder's public |
| 248 // API is more finalized. It does not fit well with the current API. | 247 // API is more finalized. It does not fit well with the current API. |
| 249 Vector<LineItemChunk, 32> line_item_chunks; | 248 Vector<LineItemChunk, 32> line_item_chunks; |
| 250 unsigned start_offset = start_offset_; | 249 unsigned start_offset = start_offset_; |
| 251 for (unsigned i = start_index_; i <= last_break_opportunity_index_; i++) { | 250 for (unsigned i = start_index_; i <= last_break_opportunity_index_; i++) { |
| 252 const NGLayoutInlineItem& item = items[i]; | 251 const NGLayoutInlineItem& item = items[i]; |
| 253 unsigned end_offset = | 252 unsigned end_offset = |
| 254 std::min(item.EndOffset(), last_break_opportunity_offset_); | 253 std::min(item.EndOffset(), last_break_opportunity_offset_); |
| 255 line_item_chunks.push_back( | 254 line_item_chunks.push_back( |
| 256 LineItemChunk{i, start_offset, end_offset, | 255 LineItemChunk{i, start_offset, end_offset, |
| 257 InlineSize(item, start_offset, end_offset)}); | 256 InlineSize(item, start_offset, end_offset)}); |
| 258 start_offset = end_offset; | 257 start_offset = end_offset; |
| 259 } | 258 } |
| 260 | 259 |
| 261 if (inline_box_->IsBidiEnabled()) | 260 if (Node()->IsBidiEnabled()) |
| 262 BidiReorder(&line_item_chunks); | 261 BidiReorder(&line_item_chunks); |
| 263 | 262 |
| 264 if (!PlaceItems(line_item_chunks)) | 263 if (!PlaceItems(line_item_chunks)) |
| 265 return false; | 264 return false; |
| 266 | 265 |
| 267 // Prepare for the next line. | 266 // Prepare for the next line. |
| 268 // Move |start| to |last_break_opportunity|, keeping items after | 267 // Move |start| to |last_break_opportunity|, keeping items after |
| 269 // |last_break_opportunity|. | 268 // |last_break_opportunity|. |
| 270 start_index_ = last_break_opportunity_index_; | 269 start_index_ = last_break_opportunity_index_; |
| 271 start_offset_ = last_break_opportunity_offset_; | 270 start_offset_ = last_break_opportunity_offset_; |
| 272 DCHECK_GE(end_position_, last_break_opportunity_position_); | 271 DCHECK_GE(end_position_, last_break_opportunity_position_); |
| 273 end_position_ -= last_break_opportunity_position_; | 272 end_position_ -= last_break_opportunity_position_; |
| 274 last_break_opportunity_position_ = LayoutUnit(); | 273 last_break_opportunity_position_ = LayoutUnit(); |
| 275 #if DCHECK_IS_ON() | 274 #if DCHECK_IS_ON() |
| 276 is_bidi_reordered_ = false; | 275 is_bidi_reordered_ = false; |
| 277 #endif | 276 #endif |
| 278 | 277 |
| 279 NGLogicalOffset origin_point = | 278 NGLogicalOffset origin_point = |
| 280 GetOriginPointForFloats(ConstraintSpace(), content_size_); | 279 GetOriginPointForFloats(ConstraintSpace(), content_size_); |
| 281 PositionPendingFloats(origin_point, constraint_space_, &container_builder_); | 280 PositionPendingFloats(origin_point, MutableConstraintSpace(), |
| 281 &container_builder_); |
| 282 FindNextLayoutOpportunity(); | 282 FindNextLayoutOpportunity(); |
| 283 return true; | 283 return true; |
| 284 } | 284 } |
| 285 | 285 |
| 286 void NGInlineLayoutAlgorithm::BidiReorder( | 286 void NGInlineLayoutAlgorithm::BidiReorder( |
| 287 Vector<LineItemChunk, 32>* line_item_chunks) { | 287 Vector<LineItemChunk, 32>* line_item_chunks) { |
| 288 #if DCHECK_IS_ON() | 288 #if DCHECK_IS_ON() |
| 289 DCHECK(!is_bidi_reordered_); | 289 DCHECK(!is_bidi_reordered_); |
| 290 is_bidi_reordered_ = true; | 290 is_bidi_reordered_ = true; |
| 291 #endif | 291 #endif |
| 292 | 292 |
| 293 // TODO(kojii): UAX#9 L1 is not supported yet. Supporting L1 may change | 293 // TODO(kojii): UAX#9 L1 is not supported yet. Supporting L1 may change |
| 294 // embedding levels of parts of runs, which requires to split items. | 294 // embedding levels of parts of runs, which requires to split items. |
| 295 // http://unicode.org/reports/tr9/#L1 | 295 // http://unicode.org/reports/tr9/#L1 |
| 296 // BidiResolver does not support L1 crbug.com/316409. | 296 // BidiResolver does not support L1 crbug.com/316409. |
| 297 | 297 |
| 298 // Create a list of chunk indices in the visual order. | 298 // Create a list of chunk indices in the visual order. |
| 299 // ICU |ubidi_getVisualMap()| works for a run of characters. Since we can | 299 // ICU |ubidi_getVisualMap()| works for a run of characters. Since we can |
| 300 // handle the direction of each run, we use |ubidi_reorderVisual()| to reorder | 300 // handle the direction of each run, we use |ubidi_reorderVisual()| to reorder |
| 301 // runs instead of characters. | 301 // runs instead of characters. |
| 302 Vector<UBiDiLevel, 32> levels; | 302 Vector<UBiDiLevel, 32> levels; |
| 303 levels.reserveInitialCapacity(line_item_chunks->size()); | 303 levels.reserveInitialCapacity(line_item_chunks->size()); |
| 304 for (const auto& chunk : *line_item_chunks) | 304 for (const auto& chunk : *line_item_chunks) |
| 305 levels.push_back(inline_box_->Items()[chunk.index].BidiLevel()); | 305 levels.push_back(Node()->Items()[chunk.index].BidiLevel()); |
| 306 Vector<int32_t, 32> indices_in_visual_order(line_item_chunks->size()); | 306 Vector<int32_t, 32> indices_in_visual_order(line_item_chunks->size()); |
| 307 NGBidiParagraph::IndicesInVisualOrder(levels, &indices_in_visual_order); | 307 NGBidiParagraph::IndicesInVisualOrder(levels, &indices_in_visual_order); |
| 308 | 308 |
| 309 // Reorder |line_item_chunks| in visual order. | 309 // Reorder |line_item_chunks| in visual order. |
| 310 Vector<LineItemChunk, 32> line_item_chunks_in_visual_order( | 310 Vector<LineItemChunk, 32> line_item_chunks_in_visual_order( |
| 311 line_item_chunks->size()); | 311 line_item_chunks->size()); |
| 312 for (unsigned visual_index = 0; visual_index < indices_in_visual_order.size(); | 312 for (unsigned visual_index = 0; visual_index < indices_in_visual_order.size(); |
| 313 visual_index++) { | 313 visual_index++) { |
| 314 unsigned logical_index = indices_in_visual_order[visual_index]; | 314 unsigned logical_index = indices_in_visual_order[visual_index]; |
| 315 line_item_chunks_in_visual_order[visual_index] = | 315 line_item_chunks_in_visual_order[visual_index] = |
| (...skipping 16 matching lines...) Expand all Loading... |
| 332 // determine if it fits on this line, then perform layout with the correct | 332 // determine if it fits on this line, then perform layout with the correct |
| 333 // fragmentation line. | 333 // fragmentation line. |
| 334 // diff writing mode - get the inline size from performing layout. | 334 // diff writing mode - get the inline size from performing layout. |
| 335 RefPtr<NGLayoutResult> layout_result = node->Layout(float_space.get()); | 335 RefPtr<NGLayoutResult> layout_result = node->Layout(float_space.get()); |
| 336 | 336 |
| 337 NGBoxFragment float_fragment( | 337 NGBoxFragment float_fragment( |
| 338 float_space->WritingMode(), | 338 float_space->WritingMode(), |
| 339 toNGPhysicalBoxFragment(layout_result->PhysicalFragment().get())); | 339 toNGPhysicalBoxFragment(layout_result->PhysicalFragment().get())); |
| 340 | 340 |
| 341 RefPtr<NGFloatingObject> floating_object = NGFloatingObject::Create( | 341 RefPtr<NGFloatingObject> floating_object = NGFloatingObject::Create( |
| 342 float_space.get(), constraint_space_, node->Style(), NGBoxStrut(), | 342 float_space.get(), MutableConstraintSpace(), node->Style(), NGBoxStrut(), |
| 343 current_opportunity_.size, layout_result->PhysicalFragment().get()); | 343 current_opportunity_.size, layout_result->PhysicalFragment().get()); |
| 344 | 344 |
| 345 bool float_does_not_fit = end_position + float_fragment.InlineSize() > | 345 bool float_does_not_fit = end_position + float_fragment.InlineSize() > |
| 346 current_opportunity_.InlineSize(); | 346 current_opportunity_.InlineSize(); |
| 347 // Check if we already have a pending float. That's because a float cannot be | 347 // Check if we already have a pending float. That's because a float cannot be |
| 348 // higher than any block or floated box generated before. | 348 // higher than any block or floated box generated before. |
| 349 if (!container_builder_.UnpositionedFloats().isEmpty() || | 349 if (!container_builder_.UnpositionedFloats().isEmpty() || |
| 350 float_does_not_fit) { | 350 float_does_not_fit) { |
| 351 container_builder_.AddUnpositionedFloat(floating_object); | 351 container_builder_.AddUnpositionedFloat(floating_object); |
| 352 } else { | 352 } else { |
| 353 NGLogicalOffset origin_point = | 353 NGLogicalOffset origin_point = |
| 354 GetOriginPointForFloats(ConstraintSpace(), content_size_); | 354 GetOriginPointForFloats(ConstraintSpace(), content_size_); |
| 355 NGLogicalOffset offset = | 355 NGLogicalOffset offset = |
| 356 PositionFloat(origin_point, constraint_space_->BfcOffset(), | 356 PositionFloat(origin_point, ConstraintSpace().BfcOffset(), |
| 357 floating_object.get(), constraint_space_); | 357 floating_object.get(), MutableConstraintSpace()); |
| 358 container_builder_.AddFloatingObject(floating_object, offset); | 358 container_builder_.AddFloatingObject(floating_object, offset); |
| 359 FindNextLayoutOpportunity(); | 359 FindNextLayoutOpportunity(); |
| 360 } | 360 } |
| 361 } | 361 } |
| 362 | 362 |
| 363 bool NGInlineLayoutAlgorithm::PlaceItems( | 363 bool NGInlineLayoutAlgorithm::PlaceItems( |
| 364 const Vector<LineItemChunk, 32>& line_item_chunks) { | 364 const Vector<LineItemChunk, 32>& line_item_chunks) { |
| 365 const Vector<NGLayoutInlineItem>& items = inline_box_->Items(); | 365 const Vector<NGLayoutInlineItem>& items = Node()->Items(); |
| 366 | 366 |
| 367 NGLineBoxFragmentBuilder line_box(inline_box_); | 367 NGLineBoxFragmentBuilder line_box(Node()); |
| 368 NGTextFragmentBuilder text_builder(inline_box_); | 368 NGTextFragmentBuilder text_builder(Node()); |
| 369 | 369 |
| 370 // Accumulate a "strut"; a zero-width inline box with the element's font and | 370 // Accumulate a "strut"; a zero-width inline box with the element's font and |
| 371 // line height properties. https://drafts.csswg.org/css2/visudet.html#strut | 371 // line height properties. https://drafts.csswg.org/css2/visudet.html#strut |
| 372 NGLineHeightMetrics block_metrics(inline_box_->Style(), baseline_type_); | 372 NGLineHeightMetrics block_metrics(Style(), baseline_type_); |
| 373 line_box.UniteMetrics(block_metrics); | 373 line_box.UniteMetrics(block_metrics); |
| 374 | 374 |
| 375 // Use the block style to compute the estimated baseline position because the | 375 // Use the block style to compute the estimated baseline position because the |
| 376 // baseline position is not known until we know the maximum ascent and leading | 376 // baseline position is not known until we know the maximum ascent and leading |
| 377 // of the line. Items are placed on this baseline, then adjusted later if the | 377 // of the line. Items are placed on this baseline, then adjusted later if the |
| 378 // estimation turned out to be different. | 378 // estimation turned out to be different. |
| 379 LayoutUnit estimated_baseline = | 379 LayoutUnit estimated_baseline = |
| 380 content_size_ + LayoutUnit(block_metrics.ascent_and_leading); | 380 content_size_ + LayoutUnit(block_metrics.ascent_and_leading); |
| 381 | 381 |
| 382 LayoutUnit inline_size; | 382 LayoutUnit inline_size; |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 450 | 450 |
| 451 // If the estimated baseline position was not the actual position, move all | 451 // If the estimated baseline position was not the actual position, move all |
| 452 // fragments in the block direction. | 452 // fragments in the block direction. |
| 453 LayoutUnit adjust_baseline(line_box.Metrics().ascent_and_leading - | 453 LayoutUnit adjust_baseline(line_box.Metrics().ascent_and_leading - |
| 454 block_metrics.ascent_and_leading); | 454 block_metrics.ascent_and_leading); |
| 455 if (adjust_baseline) | 455 if (adjust_baseline) |
| 456 line_box.MoveChildrenInBlockDirection(adjust_baseline); | 456 line_box.MoveChildrenInBlockDirection(adjust_baseline); |
| 457 | 457 |
| 458 // If there are more content to consume, create an unfinished break token. | 458 // If there are more content to consume, create an unfinished break token. |
| 459 if (last_break_opportunity_index_ != items.size() - 1 || | 459 if (last_break_opportunity_index_ != items.size() - 1 || |
| 460 last_break_opportunity_offset_ != inline_box_->Text().length()) { | 460 last_break_opportunity_offset_ != Node()->Text().length()) { |
| 461 line_box.SetBreakToken( | 461 line_box.SetBreakToken(NGInlineBreakToken::create( |
| 462 NGInlineBreakToken::create(inline_box_, last_break_opportunity_index_, | 462 Node(), last_break_opportunity_index_, last_break_opportunity_offset_)); |
| 463 last_break_opportunity_offset_)); | |
| 464 } | 463 } |
| 465 | 464 |
| 466 line_box.SetInlineSize(inline_size); | 465 line_box.SetInlineSize(inline_size); |
| 467 container_builder_.AddChild(line_box.ToLineBoxFragment(), | 466 container_builder_.AddChild(line_box.ToLineBoxFragment(), |
| 468 {LayoutUnit(), content_size_}); | 467 {LayoutUnit(), content_size_}); |
| 469 | 468 |
| 470 max_inline_size_ = std::max(max_inline_size_, inline_size); | 469 max_inline_size_ = std::max(max_inline_size_, inline_size); |
| 471 content_size_ = block_end; | 470 content_size_ = block_end; |
| 472 return true; | 471 return true; |
| 473 } | 472 } |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 517 metrics.descent_and_leading = block_size - baseline_offset; | 516 metrics.descent_and_leading = block_size - baseline_offset; |
| 518 line_box->UniteMetrics(metrics); | 517 line_box->UniteMetrics(metrics); |
| 519 | 518 |
| 520 // TODO(kojii): Figure out what to do with OOF in NGLayoutResult. | 519 // TODO(kojii): Figure out what to do with OOF in NGLayoutResult. |
| 521 // Floats are ok because atomic inlines are BFC? | 520 // Floats are ok because atomic inlines are BFC? |
| 522 | 521 |
| 523 return block_start; | 522 return block_start; |
| 524 } | 523 } |
| 525 | 524 |
| 526 void NGInlineLayoutAlgorithm::FindNextLayoutOpportunity() { | 525 void NGInlineLayoutAlgorithm::FindNextLayoutOpportunity() { |
| 527 NGLogicalOffset iter_offset = constraint_space_->BfcOffset(); | 526 NGLogicalOffset iter_offset = ConstraintSpace().BfcOffset(); |
| 528 iter_offset.block_offset += content_size_; | 527 iter_offset.block_offset += content_size_; |
| 529 auto* iter = constraint_space_->LayoutOpportunityIterator(iter_offset); | 528 auto* iter = MutableConstraintSpace()->LayoutOpportunityIterator(iter_offset); |
| 530 NGLayoutOpportunity opportunity = iter->Next(); | 529 NGLayoutOpportunity opportunity = iter->Next(); |
| 531 if (!opportunity.IsEmpty()) | 530 if (!opportunity.IsEmpty()) |
| 532 current_opportunity_ = opportunity; | 531 current_opportunity_ = opportunity; |
| 533 } | 532 } |
| 534 | 533 |
| 535 RefPtr<NGLayoutResult> NGInlineLayoutAlgorithm::Layout() { | 534 RefPtr<NGLayoutResult> NGInlineLayoutAlgorithm::Layout() { |
| 536 // TODO(koji): The relationship of NGInlineLayoutAlgorithm and NGLineBreaker | 535 // TODO(koji): The relationship of NGInlineLayoutAlgorithm and NGLineBreaker |
| 537 // should be inverted. | 536 // should be inverted. |
| 538 if (!inline_box_->Text().isEmpty()) | 537 if (!Node()->Text().isEmpty()) |
| 539 NGLineBreaker().BreakLines(this, inline_box_->Text(), start_offset_); | 538 NGLineBreaker().BreakLines(this, Node()->Text(), start_offset_); |
| 540 | 539 |
| 541 // TODO(kojii): Check if the line box width should be content or available. | 540 // TODO(kojii): Check if the line box width should be content or available. |
| 542 container_builder_.SetInlineSize(max_inline_size_) | 541 container_builder_.SetInlineSize(max_inline_size_) |
| 543 .SetInlineOverflow(max_inline_size_) | 542 .SetInlineOverflow(max_inline_size_) |
| 544 .SetBlockSize(content_size_) | 543 .SetBlockSize(content_size_) |
| 545 .SetBlockOverflow(content_size_); | 544 .SetBlockOverflow(content_size_); |
| 546 | 545 |
| 547 return container_builder_.ToBoxFragment(); | 546 return container_builder_.ToBoxFragment(); |
| 548 } | 547 } |
| 549 | 548 |
| 550 MinMaxContentSize NGInlineLayoutAlgorithm::ComputeMinMaxContentSizeByLayout() { | 549 MinMaxContentSize NGInlineLayoutAlgorithm::ComputeMinMaxContentSizeByLayout() { |
| 551 DCHECK(ConstraintSpace().AvailableSize().inline_size == LayoutUnit() && | 550 DCHECK(ConstraintSpace().AvailableSize().inline_size == LayoutUnit() && |
| 552 ConstraintSpace().AvailableSize().block_size == NGSizeIndefinite); | 551 ConstraintSpace().AvailableSize().block_size == NGSizeIndefinite); |
| 553 if (!inline_box_->Text().isEmpty()) | 552 if (!Node()->Text().isEmpty()) |
| 554 NGLineBreaker().BreakLines(this, inline_box_->Text(), start_offset_); | 553 NGLineBreaker().BreakLines(this, Node()->Text(), start_offset_); |
| 555 MinMaxContentSize sizes; | 554 MinMaxContentSize sizes; |
| 556 sizes.min_content = MaxInlineSize(); | 555 sizes.min_content = MaxInlineSize(); |
| 557 | 556 |
| 558 // max-content is the width without any line wrapping. | 557 // max-content is the width without any line wrapping. |
| 559 // TODO(kojii): Implement hard breaks (<br> etc.) to break. | 558 // TODO(kojii): Implement hard breaks (<br> etc.) to break. |
| 560 for (const auto& item : inline_box_->Items()) | 559 for (const auto& item : Node()->Items()) |
| 561 sizes.max_content += InlineSize(item); | 560 sizes.max_content += InlineSize(item); |
| 562 | 561 |
| 563 return sizes; | 562 return sizes; |
| 564 } | 563 } |
| 565 | 564 |
| 566 void NGInlineLayoutAlgorithm::CopyFragmentDataToLayoutBlockFlow( | 565 void NGInlineLayoutAlgorithm::CopyFragmentDataToLayoutBlockFlow( |
| 567 NGLayoutResult* layout_result) { | 566 NGLayoutResult* layout_result) { |
| 568 LayoutBlockFlow* block = inline_box_->GetLayoutBlockFlow(); | 567 LayoutBlockFlow* block = Node()->GetLayoutBlockFlow(); |
| 569 block->deleteLineBoxTree(); | 568 block->deleteLineBoxTree(); |
| 570 | 569 |
| 571 Vector<NGLayoutInlineItem>& items = inline_box_->Items(); | 570 Vector<NGLayoutInlineItem>& items = Node()->Items(); |
| 572 Vector<unsigned, 32> text_offsets(items.size()); | 571 Vector<unsigned, 32> text_offsets(items.size()); |
| 573 inline_box_->GetLayoutTextOffsets(&text_offsets); | 572 Node()->GetLayoutTextOffsets(&text_offsets); |
| 574 | 573 |
| 575 Vector<const NGPhysicalFragment*, 32> fragments_for_bidi_runs; | 574 Vector<const NGPhysicalFragment*, 32> fragments_for_bidi_runs; |
| 576 fragments_for_bidi_runs.reserveInitialCapacity(items.size()); | 575 fragments_for_bidi_runs.reserveInitialCapacity(items.size()); |
| 577 BidiRunList<BidiRun> bidi_runs; | 576 BidiRunList<BidiRun> bidi_runs; |
| 578 LineInfo line_info; | 577 LineInfo line_info; |
| 579 NGPhysicalBoxFragment* box_fragment = | 578 NGPhysicalBoxFragment* box_fragment = |
| 580 toNGPhysicalBoxFragment(layout_result->PhysicalFragment().get()); | 579 toNGPhysicalBoxFragment(layout_result->PhysicalFragment().get()); |
| 581 for (const auto& container_child : box_fragment->Children()) { | 580 for (const auto& container_child : box_fragment->Children()) { |
| 582 NGPhysicalLineBoxFragment* physical_line_box = | 581 NGPhysicalLineBoxFragment* physical_line_box = |
| 583 toNGPhysicalLineBoxFragment(container_child.get()); | 582 toNGPhysicalLineBoxFragment(container_child.get()); |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 645 root_line_box->setLineTopBottomPositions( | 644 root_line_box->setLineTopBottomPositions( |
| 646 baseline - LayoutUnit(metrics.ascent), | 645 baseline - LayoutUnit(metrics.ascent), |
| 647 baseline + LayoutUnit(metrics.descent), line_top_with_leading, | 646 baseline + LayoutUnit(metrics.descent), line_top_with_leading, |
| 648 baseline + LayoutUnit(metrics.descent_and_leading)); | 647 baseline + LayoutUnit(metrics.descent_and_leading)); |
| 649 | 648 |
| 650 bidi_runs.deleteRuns(); | 649 bidi_runs.deleteRuns(); |
| 651 fragments_for_bidi_runs.clear(); | 650 fragments_for_bidi_runs.clear(); |
| 652 } | 651 } |
| 653 } | 652 } |
| 654 } // namespace blink | 653 } // namespace blink |
| OLD | NEW |