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 |