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/inline/ng_inline_layout_algorithm.h" | 5 #include "core/layout/ng/inline/ng_inline_layout_algorithm.h" |
6 | 6 |
7 #include "core/layout/ng/inline/ng_bidi_paragraph.h" | 7 #include "core/layout/ng/inline/ng_bidi_paragraph.h" |
8 #include "core/layout/ng/inline/ng_inline_break_token.h" | 8 #include "core/layout/ng/inline/ng_inline_break_token.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_line_box_fragment.h" | 10 #include "core/layout/ng/inline/ng_line_box_fragment.h" |
(...skipping 28 matching lines...) Expand all Loading... |
39 | 39 |
40 } // namespace | 40 } // namespace |
41 | 41 |
42 NGInlineLayoutAlgorithm::NGInlineLayoutAlgorithm( | 42 NGInlineLayoutAlgorithm::NGInlineLayoutAlgorithm( |
43 NGInlineNode inline_node, | 43 NGInlineNode inline_node, |
44 NGConstraintSpace* space, | 44 NGConstraintSpace* space, |
45 NGInlineBreakToken* break_token) | 45 NGInlineBreakToken* break_token) |
46 : NGLayoutAlgorithm(inline_node, space, break_token), | 46 : NGLayoutAlgorithm(inline_node, space, break_token), |
47 is_horizontal_writing_mode_( | 47 is_horizontal_writing_mode_( |
48 blink::IsHorizontalWritingMode(space->WritingMode())), | 48 blink::IsHorizontalWritingMode(space->WritingMode())), |
49 disallow_first_line_rules_(false), | |
50 space_builder_(space) { | 49 space_builder_(space) { |
51 container_builder_.MutableUnpositionedFloats() = space->UnpositionedFloats(); | 50 container_builder_.MutableUnpositionedFloats() = space->UnpositionedFloats(); |
52 | 51 |
53 // TODO(crbug.com/716930): We may be an empty LayoutInline due to splitting. | 52 // TODO(crbug.com/716930): We may be an empty LayoutInline due to splitting. |
54 // Only resolve our BFC offset if we know that we are non-empty as we may | 53 // Only resolve our BFC offset if we know that we are non-empty as we may |
55 // need to pass through our margin strut. | 54 // need to pass through our margin strut. |
56 if (!inline_node.Items().IsEmpty()) { | 55 if (!inline_node.Items().IsEmpty()) { |
57 LayoutUnit bfc_block_offset = ConstraintSpace().BfcOffset().block_offset; | 56 LayoutUnit bfc_block_offset = ConstraintSpace().BfcOffset().block_offset; |
58 bfc_block_offset += ConstraintSpace().MarginStrut().Sum(); | 57 bfc_block_offset += ConstraintSpace().MarginStrut().Sum(); |
59 MaybeUpdateFragmentBfcOffset(ConstraintSpace(), bfc_block_offset, | 58 MaybeUpdateFragmentBfcOffset(ConstraintSpace(), bfc_block_offset, |
60 &container_builder_); | 59 &container_builder_); |
61 PositionPendingFloats(bfc_block_offset, &container_builder_, | 60 PositionPendingFloats(bfc_block_offset, &container_builder_, |
62 MutableConstraintSpace()); | 61 MutableConstraintSpace()); |
63 } | 62 } |
64 | 63 |
65 if (!is_horizontal_writing_mode_) | 64 if (!is_horizontal_writing_mode_) |
66 baseline_type_ = FontBaseline::kIdeographicBaseline; | 65 baseline_type_ = FontBaseline::kIdeographicBaseline; |
67 | 66 |
68 border_and_padding_ = ComputeBorders(ConstraintSpace(), Style()) + | 67 border_and_padding_ = ComputeBorders(ConstraintSpace(), Style()) + |
69 ComputePadding(ConstraintSpace(), Style()); | 68 ComputePadding(ConstraintSpace(), Style()); |
70 | 69 |
71 if (break_token) { | |
72 // If a break_token is given, we're re-starting layout for 2nd or later | |
73 // lines, and that the first line we create should not use the first line | |
74 // rules. | |
75 DCHECK(!break_token->IsFinished()); | |
76 DCHECK(break_token->TextOffset() || break_token->ItemIndex()); | |
77 disallow_first_line_rules_ = true; | |
78 } else { | |
79 auto& engine = Node().GetLayoutObject()->GetDocument().GetStyleEngine(); | |
80 disallow_first_line_rules_ = !engine.UsesFirstLineRules(); | |
81 } | |
82 | |
83 FindNextLayoutOpportunity(); | 70 FindNextLayoutOpportunity(); |
84 } | 71 } |
85 | 72 |
86 bool NGInlineLayoutAlgorithm::IsFirstLine() const { | |
87 return !disallow_first_line_rules_ && container_builder_.Children().IsEmpty(); | |
88 } | |
89 | |
90 const ComputedStyle& NGInlineLayoutAlgorithm::FirstLineStyle() const { | |
91 return Node().GetLayoutObject()->FirstLineStyleRef(); | |
92 } | |
93 | |
94 const ComputedStyle& NGInlineLayoutAlgorithm::LineStyle() const { | |
95 return IsFirstLine() ? FirstLineStyle() : Style(); | |
96 } | |
97 | |
98 LayoutUnit NGInlineLayoutAlgorithm::AvailableWidth() const { | 73 LayoutUnit NGInlineLayoutAlgorithm::AvailableWidth() const { |
99 return current_opportunity_.InlineSize(); | 74 return current_opportunity_.InlineSize(); |
100 } | 75 } |
101 | 76 |
102 // The offset of 'line-left' side. | 77 // The offset of 'line-left' side. |
103 // https://drafts.csswg.org/css-writing-modes/#line-left | 78 // https://drafts.csswg.org/css-writing-modes/#line-left |
104 LayoutUnit NGInlineLayoutAlgorithm::LogicalLeftOffset() const { | 79 LayoutUnit NGInlineLayoutAlgorithm::LogicalLeftOffset() const { |
105 // TODO(kojii): We need to convert 'line start' to 'line left'. They're | 80 // TODO(kojii): We need to convert 'line start' to 'line left'. They're |
106 // different in RTL. Maybe there are more where start and left are misused. | 81 // different in RTL. Maybe there are more where start and left are misused. |
107 return current_opportunity_.InlineStartOffset() - | 82 return current_opportunity_.InlineStartOffset() - |
108 ConstraintSpace().BfcOffset().inline_offset; | 83 ConstraintSpace().BfcOffset().inline_offset; |
109 } | 84 } |
110 | 85 |
111 bool NGInlineLayoutAlgorithm::CreateLine( | 86 bool NGInlineLayoutAlgorithm::CreateLine( |
112 NGInlineItemResults* item_results, | 87 NGLineInfo* line_info, |
113 RefPtr<NGInlineBreakToken> break_token) { | 88 RefPtr<NGInlineBreakToken> break_token) { |
114 if (Node().IsBidiEnabled()) | 89 if (Node().IsBidiEnabled()) |
115 BidiReorder(item_results); | 90 BidiReorder(&line_info->Results()); |
116 | 91 |
117 if (!PlaceItems(item_results, break_token)) | 92 if (!PlaceItems(line_info, break_token)) |
118 return false; | 93 return false; |
119 | 94 |
120 // Prepare for the next line. | 95 // Prepare for the next line. |
121 NGLogicalOffset origin_point = | 96 NGLogicalOffset origin_point = |
122 GetOriginPointForFloats(ContainerBfcOffset(), content_size_); | 97 GetOriginPointForFloats(ContainerBfcOffset(), content_size_); |
123 PositionPendingFloats(origin_point.block_offset, &container_builder_, | 98 PositionPendingFloats(origin_point.block_offset, &container_builder_, |
124 MutableConstraintSpace()); | 99 MutableConstraintSpace()); |
125 FindNextLayoutOpportunity(); | 100 FindNextLayoutOpportunity(); |
126 return true; | 101 return true; |
127 } | 102 } |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
205 float_does_not_fit) { | 180 float_does_not_fit) { |
206 container_builder_.AddUnpositionedFloat(unpositioned_float); | 181 container_builder_.AddUnpositionedFloat(unpositioned_float); |
207 } else { | 182 } else { |
208 container_builder_.AddPositionedFloat( | 183 container_builder_.AddPositionedFloat( |
209 PositionFloat(unpositioned_float.Get(), MutableConstraintSpace())); | 184 PositionFloat(unpositioned_float.Get(), MutableConstraintSpace())); |
210 FindNextLayoutOpportunity(); | 185 FindNextLayoutOpportunity(); |
211 } | 186 } |
212 } | 187 } |
213 | 188 |
214 bool NGInlineLayoutAlgorithm::PlaceItems( | 189 bool NGInlineLayoutAlgorithm::PlaceItems( |
215 NGInlineItemResults* line_items, | 190 NGLineInfo* line_info, |
216 RefPtr<NGInlineBreakToken> break_token) { | 191 RefPtr<NGInlineBreakToken> break_token) { |
| 192 NGInlineItemResults* line_items = &line_info->Results(); |
217 const Vector<NGInlineItem>& items = Node().Items(); | 193 const Vector<NGInlineItem>& items = Node().Items(); |
218 | 194 |
219 const ComputedStyle& line_style = LineStyle(); | 195 const ComputedStyle& line_style = line_info->LineStyle(); |
220 NGLineHeightMetrics line_metrics(line_style, baseline_type_); | 196 NGLineHeightMetrics line_metrics(line_style, baseline_type_); |
221 NGLineHeightMetrics line_metrics_with_leading = line_metrics; | 197 NGLineHeightMetrics line_metrics_with_leading = line_metrics; |
222 line_metrics_with_leading.AddLeading(line_style.ComputedLineHeightAsFixed()); | 198 line_metrics_with_leading.AddLeading(line_style.ComputedLineHeightAsFixed()); |
223 NGLineBoxFragmentBuilder line_box(Node()); | 199 NGLineBoxFragmentBuilder line_box(Node()); |
224 line_box.SetWritingMode(ConstraintSpace().WritingMode()); | 200 line_box.SetWritingMode(ConstraintSpace().WritingMode()); |
225 | 201 |
226 // Compute heights of all inline items by placing the dominant baseline at 0. | 202 // Compute heights of all inline items by placing the dominant baseline at 0. |
227 // The baseline is adjusted after the height of the line box is computed. | 203 // The baseline is adjusted after the height of the line box is computed. |
228 NGTextFragmentBuilder text_builder(Node()); | 204 NGTextFragmentBuilder text_builder(Node()); |
229 NGInlineBoxState* box = | 205 NGInlineBoxState* box = |
230 box_states_.OnBeginPlaceItems(&LineStyle(), baseline_type_); | 206 box_states_.OnBeginPlaceItems(&line_style, baseline_type_); |
231 | 207 |
232 // Place items from line-left to line-right along with the baseline. | 208 // Place items from line-left to line-right along with the baseline. |
233 // Items are already bidi-reordered to the visual order. | 209 // Items are already bidi-reordered to the visual order. |
234 LayoutUnit position; | 210 LayoutUnit position; |
235 | 211 |
236 for (auto& item_result : *line_items) { | 212 for (auto& item_result : *line_items) { |
237 const NGInlineItem& item = items[item_result.item_index]; | 213 const NGInlineItem& item = items[item_result.item_index]; |
238 if (item.Type() == NGInlineItem::kText || | 214 if (item.Type() == NGInlineItem::kText || |
239 item.Type() == NGInlineItem::kControl) { | 215 item.Type() == NGInlineItem::kControl) { |
240 DCHECK(item.GetLayoutObject()->IsText()); | 216 DCHECK(item.GetLayoutObject()->IsText()); |
(...skipping 20 matching lines...) Expand all Loading... |
261 // TODO(kojii): We may need more conditions to create box fragments. | 237 // TODO(kojii): We may need more conditions to create box fragments. |
262 if (item.Style()->HasBoxDecorationBackground()) | 238 if (item.Style()->HasBoxDecorationBackground()) |
263 box->SetNeedsBoxFragment(item, item_result, position); | 239 box->SetNeedsBoxFragment(item, item_result, position); |
264 } else if (item.Type() == NGInlineItem::kCloseTag) { | 240 } else if (item.Type() == NGInlineItem::kCloseTag) { |
265 position += item_result.inline_size; | 241 position += item_result.inline_size; |
266 if (box->needs_box_fragment) | 242 if (box->needs_box_fragment) |
267 box->SetLineRightForBoxFragment(item, item_result, position); | 243 box->SetLineRightForBoxFragment(item, item_result, position); |
268 box = box_states_.OnCloseTag(item, &line_box, box, baseline_type_); | 244 box = box_states_.OnCloseTag(item, &line_box, box, baseline_type_); |
269 continue; | 245 continue; |
270 } else if (item.Type() == NGInlineItem::kAtomicInline) { | 246 } else if (item.Type() == NGInlineItem::kAtomicInline) { |
271 box = PlaceAtomicInline(item, &item_result, position, &line_box, | 247 box = PlaceAtomicInline(item, &item_result, line_info->IsFirstLine(), |
272 &text_builder); | 248 position, &line_box, &text_builder); |
273 } else if (item.Type() == NGInlineItem::kOutOfFlowPositioned) { | 249 } else if (item.Type() == NGInlineItem::kOutOfFlowPositioned) { |
274 // TODO(layout-dev): Report the correct static position for the out of | 250 // TODO(layout-dev): Report the correct static position for the out of |
275 // flow descendant. We can't do this here yet as it doesn't know the | 251 // flow descendant. We can't do this here yet as it doesn't know the |
276 // size of the line box. | 252 // size of the line box. |
277 container_builder_.AddOutOfFlowDescendant( | 253 container_builder_.AddOutOfFlowDescendant( |
278 // Absolute positioning blockifies the box's display type. | 254 // Absolute positioning blockifies the box's display type. |
279 // https://drafts.csswg.org/css-display/#transformations | 255 // https://drafts.csswg.org/css-display/#transformations |
280 NGBlockNode(ToLayoutBox(item.GetLayoutObject())), | 256 NGBlockNode(ToLayoutBox(item.GetLayoutObject())), |
281 NGStaticPosition::Create(ConstraintSpace().WritingMode(), | 257 NGStaticPosition::Create(ConstraintSpace().WritingMode(), |
282 ConstraintSpace().Direction(), | 258 ConstraintSpace().Direction(), |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
315 // and block_start do not match. | 291 // and block_start do not match. |
316 | 292 |
317 // Up until this point, children are placed so that the dominant baseline is | 293 // Up until this point, children are placed so that the dominant baseline is |
318 // at 0. Move them to the final baseline position, and set the logical top of | 294 // at 0. Move them to the final baseline position, and set the logical top of |
319 // the line box to the line top. | 295 // the line box to the line top. |
320 line_box.MoveChildrenInBlockDirection(baseline); | 296 line_box.MoveChildrenInBlockDirection(baseline); |
321 | 297 |
322 LayoutUnit inline_size = position; | 298 LayoutUnit inline_size = position; |
323 NGLogicalOffset offset(LogicalLeftOffset(), | 299 NGLogicalOffset offset(LogicalLeftOffset(), |
324 baseline - box_states_.LineBoxState().metrics.ascent); | 300 baseline - box_states_.LineBoxState().metrics.ascent); |
325 ApplyTextAlign(&offset.inline_offset, inline_size, | 301 ApplyTextAlign(line_style, line_style.GetTextAlign(line_info->IsLastLine()), |
| 302 &offset.inline_offset, inline_size, |
326 current_opportunity_.size.inline_size); | 303 current_opportunity_.size.inline_size); |
327 | 304 |
328 line_box.SetInlineSize(inline_size); | 305 line_box.SetInlineSize(inline_size); |
329 container_builder_.AddChild(line_box.ToLineBoxFragment(), offset); | 306 container_builder_.AddChild(line_box.ToLineBoxFragment(), offset); |
330 | 307 |
331 max_inline_size_ = std::max(max_inline_size_, inline_size); | 308 max_inline_size_ = std::max(max_inline_size_, inline_size); |
332 content_size_ = line_bottom; | 309 content_size_ = line_bottom; |
333 return true; | 310 return true; |
334 } | 311 } |
335 | 312 |
336 // TODO(kojii): Currently, this function does not change item_result, but | 313 // TODO(kojii): Currently, this function does not change item_result, but |
337 // when NG paint is enabled, this will std::move() the LayoutResult. | 314 // when NG paint is enabled, this will std::move() the LayoutResult. |
338 NGInlineBoxState* NGInlineLayoutAlgorithm::PlaceAtomicInline( | 315 NGInlineBoxState* NGInlineLayoutAlgorithm::PlaceAtomicInline( |
339 const NGInlineItem& item, | 316 const NGInlineItem& item, |
340 NGInlineItemResult* item_result, | 317 NGInlineItemResult* item_result, |
| 318 bool is_first_line, |
341 LayoutUnit position, | 319 LayoutUnit position, |
342 NGLineBoxFragmentBuilder* line_box, | 320 NGLineBoxFragmentBuilder* line_box, |
343 NGTextFragmentBuilder* text_builder) { | 321 NGTextFragmentBuilder* text_builder) { |
344 DCHECK(item_result->layout_result); | 322 DCHECK(item_result->layout_result); |
345 | 323 |
346 NGInlineBoxState* box = box_states_.OnOpenTag(item, line_box); | 324 NGInlineBoxState* box = box_states_.OnOpenTag(item, line_box); |
347 | 325 |
348 // For replaced elements, inline-block elements, and inline-table elements, | 326 // For replaced elements, inline-block elements, and inline-table elements, |
349 // the height is the height of their margin box. | 327 // the height is the height of their margin box. |
350 // https://drafts.csswg.org/css2/visudet.html#line-height | 328 // https://drafts.csswg.org/css2/visudet.html#line-height |
351 NGBoxFragment fragment( | 329 NGBoxFragment fragment( |
352 ConstraintSpace().WritingMode(), | 330 ConstraintSpace().WritingMode(), |
353 ToNGPhysicalBoxFragment( | 331 ToNGPhysicalBoxFragment( |
354 item_result->layout_result->PhysicalFragment().Get())); | 332 item_result->layout_result->PhysicalFragment().Get())); |
355 LayoutUnit block_size = | 333 LayoutUnit block_size = |
356 fragment.BlockSize() + item_result->margins.BlockSum(); | 334 fragment.BlockSize() + item_result->margins.BlockSum(); |
357 | 335 |
358 // TODO(kojii): Add baseline position to NGPhysicalFragment. | 336 // TODO(kojii): Add baseline position to NGPhysicalFragment. |
359 LayoutBox* layout_box = ToLayoutBox(item.GetLayoutObject()); | 337 LayoutBox* layout_box = ToLayoutBox(item.GetLayoutObject()); |
360 LineDirectionMode line_direction_mode = | 338 LineDirectionMode line_direction_mode = |
361 IsHorizontalWritingMode() ? LineDirectionMode::kHorizontalLine | 339 IsHorizontalWritingMode() ? LineDirectionMode::kHorizontalLine |
362 : LineDirectionMode::kVerticalLine; | 340 : LineDirectionMode::kVerticalLine; |
363 LayoutUnit baseline_offset(layout_box->BaselinePosition( | 341 LayoutUnit baseline_offset(layout_box->BaselinePosition( |
364 baseline_type_, IsFirstLine(), line_direction_mode)); | 342 baseline_type_, is_first_line, line_direction_mode)); |
365 | 343 |
366 NGLineHeightMetrics metrics(baseline_offset, block_size - baseline_offset); | 344 NGLineHeightMetrics metrics(baseline_offset, block_size - baseline_offset); |
367 box->metrics.Unite(metrics); | 345 box->metrics.Unite(metrics); |
368 | 346 |
369 // TODO(kojii): Figure out what to do with OOF in NGLayoutResult. | 347 // TODO(kojii): Figure out what to do with OOF in NGLayoutResult. |
370 // Floats are ok because atomic inlines are BFC? | 348 // Floats are ok because atomic inlines are BFC? |
371 | 349 |
372 // TODO(kojii): Try to eliminate the wrapping text fragment and use the | 350 // TODO(kojii): Try to eliminate the wrapping text fragment and use the |
373 // |fragment| directly. Currently |CopyFragmentDataToLayoutBlockFlow| | 351 // |fragment| directly. Currently |CopyFragmentDataToLayoutBlockFlow| |
374 // requires a text fragment. | 352 // requires a text fragment. |
375 text_builder->SetDirection(item.Style()->Direction()); | 353 text_builder->SetDirection(item.Style()->Direction()); |
376 text_builder->SetSize({fragment.InlineSize(), block_size}); | 354 text_builder->SetSize({fragment.InlineSize(), block_size}); |
377 LayoutUnit line_top = item_result->margins.block_start - metrics.ascent; | 355 LayoutUnit line_top = item_result->margins.block_start - metrics.ascent; |
378 RefPtr<NGPhysicalTextFragment> text_fragment = text_builder->ToTextFragment( | 356 RefPtr<NGPhysicalTextFragment> text_fragment = text_builder->ToTextFragment( |
379 item_result->item_index, item_result->start_offset, | 357 item_result->item_index, item_result->start_offset, |
380 item_result->end_offset); | 358 item_result->end_offset); |
381 line_box->AddChild(std::move(text_fragment), {position, line_top}); | 359 line_box->AddChild(std::move(text_fragment), {position, line_top}); |
382 | 360 |
383 return box_states_.OnCloseTag(item, line_box, box, baseline_type_); | 361 return box_states_.OnCloseTag(item, line_box, box, baseline_type_); |
384 } | 362 } |
385 | 363 |
386 void NGInlineLayoutAlgorithm::ApplyTextAlign(LayoutUnit* line_left, | 364 void NGInlineLayoutAlgorithm::ApplyTextAlign(const ComputedStyle& line_style, |
| 365 ETextAlign text_align, |
| 366 LayoutUnit* line_left, |
387 LayoutUnit inline_size, | 367 LayoutUnit inline_size, |
388 LayoutUnit available_width) { | 368 LayoutUnit available_width) { |
389 // TODO(kojii): Implement text-align-last. | |
390 ETextAlign text_align = LineStyle().GetTextAlign(); | |
391 switch (text_align) { | 369 switch (text_align) { |
392 case ETextAlign::kRight: | 370 case ETextAlign::kRight: |
393 case ETextAlign::kWebkitRight: | 371 case ETextAlign::kWebkitRight: |
394 // Wide lines spill out of the block based off direction. | 372 // Wide lines spill out of the block based off direction. |
395 // So even if text-align is right, if direction is LTR, wide lines should | 373 // So even if text-align is right, if direction is LTR, wide lines should |
396 // overflow out of the right side of the block. | 374 // overflow out of the right side of the block. |
397 // TODO(kojii): Investigate how to handle trailing spaces. | 375 // TODO(kojii): Investigate how to handle trailing spaces. |
398 if (inline_size < available_width || | 376 if (inline_size < available_width || !line_style.IsLeftToRightDirection()) |
399 !LineStyle().IsLeftToRightDirection()) | |
400 *line_left += available_width - inline_size; | 377 *line_left += available_width - inline_size; |
401 break; | 378 break; |
402 default: | 379 default: |
403 // TODO(layout-dev): Implement. | 380 // TODO(layout-dev): Implement. |
404 // Refer to LayoutBlockFlow::UpdateLogicalWidthForAlignment(). | 381 // Refer to LayoutBlockFlow::UpdateLogicalWidthForAlignment(). |
405 break; | 382 break; |
406 } | 383 } |
407 } | 384 } |
408 | 385 |
409 void NGInlineLayoutAlgorithm::FindNextLayoutOpportunity() { | 386 void NGInlineLayoutAlgorithm::FindNextLayoutOpportunity() { |
410 NGLogicalOffset iter_offset = ConstraintSpace().BfcOffset(); | 387 NGLogicalOffset iter_offset = ConstraintSpace().BfcOffset(); |
411 if (container_builder_.BfcOffset()) { | 388 if (container_builder_.BfcOffset()) { |
412 iter_offset = ContainerBfcOffset(); | 389 iter_offset = ContainerBfcOffset(); |
413 iter_offset += | 390 iter_offset += |
414 {border_and_padding_.inline_start, border_and_padding_.block_start}; | 391 {border_and_padding_.inline_start, border_and_padding_.block_start}; |
415 } | 392 } |
416 iter_offset.block_offset += content_size_; | 393 iter_offset.block_offset += content_size_; |
417 auto* iter = MutableConstraintSpace()->LayoutOpportunityIterator(iter_offset); | 394 auto* iter = MutableConstraintSpace()->LayoutOpportunityIterator(iter_offset); |
418 NGLayoutOpportunity opportunity = iter->Next(); | 395 NGLayoutOpportunity opportunity = iter->Next(); |
419 if (!opportunity.IsEmpty()) | 396 if (!opportunity.IsEmpty()) |
420 current_opportunity_ = opportunity; | 397 current_opportunity_ = opportunity; |
421 } | 398 } |
422 | 399 |
423 RefPtr<NGLayoutResult> NGInlineLayoutAlgorithm::Layout() { | 400 RefPtr<NGLayoutResult> NGInlineLayoutAlgorithm::Layout() { |
424 // If we are resuming from a break token our start border and padding is | 401 // If we are resuming from a break token our start border and padding is |
425 // within a previous fragment. | 402 // within a previous fragment. |
426 content_size_ = BreakToken() ? LayoutUnit() : border_and_padding_.block_start; | 403 content_size_ = BreakToken() ? LayoutUnit() : border_and_padding_.block_start; |
427 | 404 |
428 NGLineBreaker line_breaker(Node(), constraint_space_, BreakToken()); | 405 NGLineBreaker line_breaker(Node(), constraint_space_, BreakToken()); |
429 NGInlineItemResults item_results; | 406 NGLineInfo line_info; |
430 while (true) { | 407 while (line_breaker.NextLine(&line_info, this)) |
431 line_breaker.NextLine(&item_results, this); | 408 CreateLine(&line_info, line_breaker.CreateBreakToken()); |
432 if (item_results.IsEmpty()) | |
433 break; | |
434 CreateLine(&item_results, line_breaker.CreateBreakToken()); | |
435 item_results.clear(); | |
436 } | |
437 | 409 |
438 // TODO(crbug.com/716930): Avoid calculating border/padding twice. | 410 // TODO(crbug.com/716930): Avoid calculating border/padding twice. |
439 if (!BreakToken()) | 411 if (!BreakToken()) |
440 content_size_ -= border_and_padding_.block_start; | 412 content_size_ -= border_and_padding_.block_start; |
441 | 413 |
442 // TODO(kojii): Check if the line box width should be content or available. | 414 // TODO(kojii): Check if the line box width should be content or available. |
443 NGLogicalSize size(max_inline_size_, content_size_); | 415 NGLogicalSize size(max_inline_size_, content_size_); |
444 container_builder_.SetSize(size).SetOverflowSize(size); | 416 container_builder_.SetSize(size).SetOverflowSize(size); |
445 | 417 |
446 // TODO(crbug.com/716930): We may be an empty LayoutInline due to splitting. | 418 // TODO(crbug.com/716930): We may be an empty LayoutInline due to splitting. |
447 // Margin struts shouldn't need to be passed through like this once we've | 419 // Margin struts shouldn't need to be passed through like this once we've |
448 // removed LayoutInline splitting. | 420 // removed LayoutInline splitting. |
449 if (!container_builder_.BfcOffset()) { | 421 if (!container_builder_.BfcOffset()) { |
450 container_builder_.SetEndMarginStrut(ConstraintSpace().MarginStrut()); | 422 container_builder_.SetEndMarginStrut(ConstraintSpace().MarginStrut()); |
451 } | 423 } |
452 | 424 |
453 return container_builder_.ToBoxFragment(); | 425 return container_builder_.ToBoxFragment(); |
454 } | 426 } |
455 | 427 |
456 } // namespace blink | 428 } // namespace blink |
OLD | NEW |