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" |
11 #include "core/layout/ng/ng_bidi_paragraph.h" | 11 #include "core/layout/ng/ng_bidi_paragraph.h" |
12 #include "core/layout/ng/ng_box_fragment.h" | 12 #include "core/layout/ng/ng_box_fragment.h" |
13 #include "core/layout/ng/ng_constraint_space.h" | 13 #include "core/layout/ng/ng_constraint_space.h" |
14 #include "core/layout/ng/ng_constraint_space_builder.h" | 14 #include "core/layout/ng/ng_constraint_space_builder.h" |
15 #include "core/layout/ng/ng_fragment_builder.h" | 15 #include "core/layout/ng/ng_fragment_builder.h" |
16 #include "core/layout/ng/ng_inline_node.h" | 16 #include "core/layout/ng/ng_inline_node.h" |
17 #include "core/layout/ng/ng_length_utils.h" | 17 #include "core/layout/ng/ng_length_utils.h" |
18 #include "core/layout/ng/ng_linebox_fragment.h" | |
19 #include "core/layout/ng/ng_linebox_fragment_builder.h" | |
18 #include "core/layout/ng/ng_text_fragment.h" | 20 #include "core/layout/ng/ng_text_fragment.h" |
21 #include "core/layout/ng/ng_text_fragment_builder.h" | |
19 #include "core/style/ComputedStyle.h" | 22 #include "core/style/ComputedStyle.h" |
20 #include "platform/text/BidiRunList.h" | 23 #include "platform/text/BidiRunList.h" |
21 | 24 |
22 namespace blink { | 25 namespace blink { |
23 | 26 |
24 NGLineBuilder::NGLineBuilder(NGInlineNode* inline_box, | 27 NGLineBuilder::NGLineBuilder(NGInlineNode* inline_box, |
25 NGConstraintSpace* constraint_space) | 28 NGConstraintSpace* constraint_space) |
26 : inline_box_(inline_box), | 29 : inline_box_(inline_box), |
27 constraint_space_(constraint_space), | 30 constraint_space_(constraint_space), |
28 container_builder_(NGPhysicalFragment::kFragmentBox, inline_box_), | 31 container_builder_(NGPhysicalFragment::kFragmentBox, inline_box_), |
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
254 unsigned logical_index = indices_in_visual_order[visual_index]; | 257 unsigned logical_index = indices_in_visual_order[visual_index]; |
255 line_item_chunks_in_visual_order[visual_index] = | 258 line_item_chunks_in_visual_order[visual_index] = |
256 (*line_item_chunks)[logical_index]; | 259 (*line_item_chunks)[logical_index]; |
257 } | 260 } |
258 line_item_chunks->swap(line_item_chunks_in_visual_order); | 261 line_item_chunks->swap(line_item_chunks_in_visual_order); |
259 } | 262 } |
260 | 263 |
261 void NGLineBuilder::PlaceItems( | 264 void NGLineBuilder::PlaceItems( |
262 const Vector<LineItemChunk, 32>& line_item_chunks) { | 265 const Vector<LineItemChunk, 32>& line_item_chunks) { |
263 const Vector<NGLayoutInlineItem>& items = inline_box_->Items(); | 266 const Vector<NGLayoutInlineItem>& items = inline_box_->Items(); |
264 const unsigned fragment_start_index = container_builder_.Children().size(); | |
265 | 267 |
266 NGFragmentBuilder text_builder(NGPhysicalFragment::kFragmentText, | 268 NGLineboxFragmentBuilder linebox(inline_box_); |
ikilpatrick
2017/03/23 16:47:26
This is going to be incredibly annoying but should
| |
267 inline_box_); | 269 NGTextFragmentBuilder text_builder(inline_box_); |
268 text_builder.SetWritingMode(ConstraintSpace().WritingMode()); | |
269 line_box_data_list_.grow(line_box_data_list_.size() + 1); | |
270 LineBoxData& line_box_data = line_box_data_list_.back(); | |
271 | 270 |
272 // Accumulate a "strut"; a zero-width inline box with the element's font and | 271 // Accumulate a "strut"; a zero-width inline box with the element's font and |
273 // line height properties. https://drafts.csswg.org/css2/visudet.html#strut | 272 // line height properties. https://drafts.csswg.org/css2/visudet.html#strut |
274 const ComputedStyle* block_style = inline_box_->BlockStyle(); | 273 const ComputedStyle* block_style = inline_box_->BlockStyle(); |
275 InlineItemMetrics block_metrics(*block_style, baseline_type_); | 274 NGLineHeightMetrics block_metrics(*block_style, baseline_type_); |
276 line_box_data.UpdateMaxAscentAndDescent(block_metrics); | 275 linebox.UniteMetrics(block_metrics); |
277 | 276 |
278 // Use the block style to compute the estimated baseline position because the | 277 // Use the block style to compute the estimated baseline position because the |
279 // baseline position is not known until we know the maximum ascent and leading | 278 // baseline position is not known until we know the maximum ascent and leading |
280 // of the line. Items are placed on this baseline, then adjusted later if the | 279 // of the line. Items are placed on this baseline, then adjusted later if the |
281 // estimation turned out to be different. | 280 // estimation turned out to be different. |
282 LayoutUnit estimated_baseline = | 281 LayoutUnit estimated_baseline = |
283 content_size_ + LayoutUnit(block_metrics.ascent_and_leading); | 282 content_size_ + LayoutUnit(block_metrics.ascent_and_leading); |
284 | 283 |
284 LayoutUnit inline_size; | |
285 for (const auto& line_item_chunk : line_item_chunks) { | 285 for (const auto& line_item_chunk : line_item_chunks) { |
286 const NGLayoutInlineItem& item = items[line_item_chunk.index]; | 286 const NGLayoutInlineItem& item = items[line_item_chunk.index]; |
287 // Skip bidi controls. | 287 // Skip bidi controls. |
288 if (!item.GetLayoutObject()) | 288 if (!item.GetLayoutObject()) |
289 continue; | 289 continue; |
290 | 290 |
291 LayoutUnit block_start; | 291 LayoutUnit block_start; |
292 if (item.Type() == NGLayoutInlineItem::kText) { | 292 if (item.Type() == NGLayoutInlineItem::kText) { |
293 DCHECK(item.GetLayoutObject()->isText()); | 293 DCHECK(item.GetLayoutObject()->isText()); |
294 const ComputedStyle* style = item.Style(); | 294 const ComputedStyle* style = item.Style(); |
295 // The direction of a fragment is the CSS direction to resolve logical | |
296 // properties, not the resolved bidi direction. | |
297 text_builder.SetDirection(style->direction()) | |
298 .SetInlineSize(line_item_chunk.inline_size); | |
299 | |
295 // |InlineTextBoxPainter| sets the baseline at |top + | 300 // |InlineTextBoxPainter| sets the baseline at |top + |
296 // ascent-of-primary-font|. Compute |top| to match. | 301 // ascent-of-primary-font|. Compute |top| to match. |
297 InlineItemMetrics metrics(*style, baseline_type_); | 302 NGLineHeightMetrics metrics(*style, baseline_type_); |
298 block_start = estimated_baseline - LayoutUnit(metrics.ascent); | 303 block_start = estimated_baseline - LayoutUnit(metrics.ascent); |
299 LayoutUnit line_height = LayoutUnit(metrics.ascent + metrics.descent); | 304 text_builder.SetBlockSize(metrics.LineHeight()); |
300 line_box_data.UpdateMaxAscentAndDescent(metrics); | 305 linebox.UniteMetrics(metrics); |
301 | 306 |
302 // Take all used fonts into account if 'line-height: normal'. | 307 // Take all used fonts into account if 'line-height: normal'. |
303 if (style->lineHeight().isNegative()) | 308 if (style->lineHeight().isNegative()) |
304 AccumulateUsedFonts(item, line_item_chunk, &line_box_data); | 309 AccumulateUsedFonts(item, line_item_chunk, &linebox); |
305 | |
306 // The direction of a fragment is the CSS direction to resolve logical | |
307 // properties, not the resolved bidi direction. | |
308 text_builder.SetDirection(style->direction()) | |
309 .SetInlineSize(line_item_chunk.inline_size) | |
310 .SetInlineOverflow(line_item_chunk.inline_size) | |
311 .SetBlockSize(line_height) | |
312 .SetBlockOverflow(line_height); | |
313 } else if (item.Type() == NGLayoutInlineItem::kAtomicInline) { | 310 } else if (item.Type() == NGLayoutInlineItem::kAtomicInline) { |
314 block_start = PlaceAtomicInline(item, estimated_baseline, &line_box_data, | 311 block_start = |
315 &text_builder); | 312 PlaceAtomicInline(item, estimated_baseline, &linebox, &text_builder); |
316 } else if (item.Type() == NGLayoutInlineItem::kOutOfFlowPositioned) { | 313 } else if (item.Type() == NGLayoutInlineItem::kOutOfFlowPositioned) { |
317 // TODO(layout-dev): Report the correct static position for the out of | 314 // TODO(layout-dev): Report the correct static position for the out of |
318 // flow descendant. We can't do this here yet as it doesn't know the | 315 // flow descendant. We can't do this here yet as it doesn't know the |
319 // size of the line box. | 316 // size of the line box. |
320 container_builder_.AddOutOfFlowDescendant( | 317 container_builder_.AddOutOfFlowDescendant( |
321 // Absolute positioning blockifies the box's display type. | 318 // Absolute positioning blockifies the box's display type. |
322 // https://drafts.csswg.org/css-display/#transformations | 319 // https://drafts.csswg.org/css-display/#transformations |
323 new NGBlockNode(item.GetLayoutObject()), | 320 new NGBlockNode(item.GetLayoutObject()), |
324 NGStaticPosition::Create(ConstraintSpace().WritingMode(), | 321 NGStaticPosition::Create(ConstraintSpace().WritingMode(), |
325 ConstraintSpace().Direction(), | 322 ConstraintSpace().Direction(), |
326 NGPhysicalOffset())); | 323 NGPhysicalOffset())); |
327 continue; | 324 continue; |
328 } else if (item.Type() == NGLayoutInlineItem::kFloating) { | 325 } else if (item.Type() == NGLayoutInlineItem::kFloating) { |
329 // TODO(kojii): Implement float. | 326 // TODO(kojii): Implement float. |
330 DLOG(ERROR) << "Floats in inline not implemented yet."; | 327 DLOG(ERROR) << "Floats in inline not implemented yet."; |
331 // TODO(kojii): Temporarily clearNeedsLayout() for not to assert. | 328 // TODO(kojii): Temporarily clearNeedsLayout() for not to assert. |
332 item.GetLayoutObject()->clearNeedsLayout(); | 329 item.GetLayoutObject()->clearNeedsLayout(); |
333 continue; | 330 continue; |
334 } else { | 331 } else { |
335 continue; | 332 continue; |
336 } | 333 } |
337 | 334 |
338 RefPtr<NGPhysicalTextFragment> text_fragment = text_builder.ToTextFragment( | 335 RefPtr<NGPhysicalTextFragment> text_fragment = text_builder.ToTextFragment( |
339 line_item_chunk.index, line_item_chunk.start_offset, | 336 line_item_chunk.index, line_item_chunk.start_offset, |
340 line_item_chunk.end_offset); | 337 line_item_chunk.end_offset); |
341 | 338 |
342 NGLogicalOffset logical_offset( | 339 NGLogicalOffset logical_offset( |
343 line_box_data.inline_size + current_opportunity_.InlineStartOffset() - | 340 inline_size + current_opportunity_.InlineStartOffset() - |
344 ConstraintSpace().BfcOffset().inline_offset, | 341 ConstraintSpace().BfcOffset().inline_offset, |
345 block_start); | 342 block_start); |
346 container_builder_.AddChild(std::move(text_fragment), logical_offset); | 343 linebox.AddChild(std::move(text_fragment), logical_offset); |
347 line_box_data.inline_size += line_item_chunk.inline_size; | 344 inline_size += line_item_chunk.inline_size; |
348 } | 345 } |
349 | 346 |
350 if (fragment_start_index == container_builder_.Children().size()) { | 347 if (linebox.Children().isEmpty()) { |
351 // The line was empty. Remove the LineBoxData. | 348 // The line was empty. |
352 line_box_data_list_.shrink(line_box_data_list_.size() - 1); | |
353 return; | 349 return; |
354 } | 350 } |
355 | 351 |
356 // If the estimated baseline position was not the actual position, move all | 352 // If the estimated baseline position was not the actual position, move all |
357 // fragments in the block direction. | 353 // fragments in the block direction. |
358 if (block_metrics.ascent_and_leading != | 354 LayoutUnit adjust_baseline(linebox.Metrics().ascent_and_leading - |
359 line_box_data.max_ascent_and_leading) { | 355 block_metrics.ascent_and_leading); |
360 LayoutUnit adjust_top(line_box_data.max_ascent_and_leading - | 356 if (adjust_baseline) |
361 block_metrics.ascent_and_leading); | 357 linebox.MoveChildrenInBlockDirection(adjust_baseline); |
362 auto& offsets = container_builder_.MutableOffsets(); | |
363 for (unsigned i = fragment_start_index; i < offsets.size(); i++) | |
364 offsets[i].block_offset += adjust_top; | |
365 } | |
366 | 358 |
367 line_box_data.fragment_end = container_builder_.Children().size(); | 359 linebox.SetInlineSize(inline_size); |
368 line_box_data.top_with_leading = content_size_; | 360 NGLogicalOffset offset(LayoutUnit(), content_size_); |
369 max_inline_size_ = std::max(max_inline_size_, line_box_data.inline_size); | 361 container_builder_.AddChild(linebox.ToLineboxFragment(), offset); |
370 content_size_ += LayoutUnit(line_box_data.max_ascent_and_leading + | 362 max_inline_size_ = std::max(max_inline_size_, inline_size); |
371 line_box_data.max_descent_and_leading); | 363 content_size_ += linebox.Metrics().LineHeight(); |
372 } | |
373 | |
374 NGLineBuilder::InlineItemMetrics::InlineItemMetrics( | |
375 const ComputedStyle& style, | |
376 FontBaseline baseline_type) { | |
377 const SimpleFontData* font_data = style.font().primaryFont(); | |
378 DCHECK(font_data); | |
379 Initialize(font_data->getFontMetrics(), baseline_type, | |
380 style.computedLineHeightInFloat()); | |
381 } | |
382 | |
383 NGLineBuilder::InlineItemMetrics::InlineItemMetrics( | |
384 const FontMetrics& font_metrics, | |
385 FontBaseline baseline_type) { | |
386 Initialize(font_metrics, baseline_type, font_metrics.floatLineSpacing()); | |
387 } | |
388 | |
389 void NGLineBuilder::InlineItemMetrics::Initialize( | |
390 const FontMetrics& font_metrics, | |
391 FontBaseline baseline_type, | |
392 float line_height) { | |
393 ascent = font_metrics.floatAscent(baseline_type); | |
394 descent = font_metrics.floatDescent(baseline_type); | |
395 float half_leading = (line_height - (ascent + descent)) / 2; | |
396 // Ensure the top and the baseline is snapped to CSS pixel. | |
397 // TODO(kojii): How to handle fractional ascent isn't determined yet. Should | |
398 // we snap top or baseline? If baseline, top needs fractional. If top, | |
399 // baseline may not align across fonts. | |
400 ascent_and_leading = ascent + floor(half_leading); | |
401 descent_and_leading = line_height - ascent_and_leading; | |
402 } | |
403 | |
404 void NGLineBuilder::LineBoxData::UpdateMaxAscentAndDescent( | |
405 const NGLineBuilder::InlineItemMetrics& metrics) { | |
406 max_ascent = std::max(max_ascent, metrics.ascent); | |
407 max_descent = std::max(max_descent, metrics.descent); | |
408 max_ascent_and_leading = | |
409 std::max(max_ascent_and_leading, metrics.ascent_and_leading); | |
410 max_descent_and_leading = | |
411 std::max(max_descent_and_leading, metrics.descent_and_leading); | |
412 } | 364 } |
413 | 365 |
414 void NGLineBuilder::AccumulateUsedFonts(const NGLayoutInlineItem& item, | 366 void NGLineBuilder::AccumulateUsedFonts(const NGLayoutInlineItem& item, |
415 const LineItemChunk& line_item_chunk, | 367 const LineItemChunk& line_item_chunk, |
416 LineBoxData* line_box_data) { | 368 NGLineboxFragmentBuilder* linebox) { |
417 HashSet<const SimpleFontData*> fallback_fonts; | 369 HashSet<const SimpleFontData*> fallback_fonts; |
418 item.GetFallbackFonts(&fallback_fonts, line_item_chunk.start_offset, | 370 item.GetFallbackFonts(&fallback_fonts, line_item_chunk.start_offset, |
419 line_item_chunk.end_offset); | 371 line_item_chunk.end_offset); |
420 for (const auto& fallback_font : fallback_fonts) { | 372 for (const auto& fallback_font : fallback_fonts) { |
421 InlineItemMetrics fallback_font_metrics(fallback_font->getFontMetrics(), | 373 NGLineHeightMetrics metrics(fallback_font->getFontMetrics(), |
422 baseline_type_); | 374 baseline_type_); |
423 line_box_data->UpdateMaxAscentAndDescent(fallback_font_metrics); | 375 linebox->UniteMetrics(metrics); |
424 } | 376 } |
425 } | 377 } |
426 | 378 |
427 LayoutUnit NGLineBuilder::PlaceAtomicInline(const NGLayoutInlineItem& item, | 379 LayoutUnit NGLineBuilder::PlaceAtomicInline( |
428 LayoutUnit estimated_baseline, | 380 const NGLayoutInlineItem& item, |
429 LineBoxData* line_box_data, | 381 LayoutUnit estimated_baseline, |
430 NGFragmentBuilder* text_builder) { | 382 NGLineboxFragmentBuilder* linebox, |
383 NGTextFragmentBuilder* text_builder) { | |
431 NGBoxFragment fragment( | 384 NGBoxFragment fragment( |
432 ConstraintSpace().WritingMode(), | 385 ConstraintSpace().WritingMode(), |
433 toNGPhysicalBoxFragment(LayoutItem(item)->PhysicalFragment().get())); | 386 toNGPhysicalBoxFragment(LayoutItem(item)->PhysicalFragment().get())); |
434 // TODO(kojii): Margin and border in block progression not implemented yet. | 387 // TODO(kojii): Margin and border in block progression not implemented yet. |
435 LayoutUnit block_size = fragment.BlockSize(); | 388 LayoutUnit block_size = fragment.BlockSize(); |
436 | 389 |
437 // TODO(kojii): Try to eliminate the wrapping text fragment and use the | 390 // TODO(kojii): Try to eliminate the wrapping text fragment and use the |
438 // |fragment| directly. Currently |CopyFragmentDataToLayoutBlockFlow| | 391 // |fragment| directly. Currently |CopyFragmentDataToLayoutBlockFlow| |
439 // requires a text fragment. | 392 // requires a text fragment. |
440 text_builder->SetInlineSize(fragment.InlineSize()) | 393 text_builder->SetInlineSize(fragment.InlineSize()).SetBlockSize(block_size); |
441 .SetInlineOverflow(fragment.InlineOverflow()) | |
442 .SetBlockSize(block_size) | |
443 .SetBlockOverflow(fragment.BlockOverflow()); | |
444 | 394 |
445 // TODO(kojii): Add baseline position to NGPhysicalFragment. | 395 // TODO(kojii): Add baseline position to NGPhysicalFragment. |
446 LayoutBox* box = toLayoutBox(item.GetLayoutObject()); | 396 LayoutBox* box = toLayoutBox(item.GetLayoutObject()); |
447 LineDirectionMode line_direction_mode = | 397 LineDirectionMode line_direction_mode = |
448 IsHorizontalWritingMode() ? LineDirectionMode::HorizontalLine | 398 IsHorizontalWritingMode() ? LineDirectionMode::HorizontalLine |
449 : LineDirectionMode::VerticalLine; | 399 : LineDirectionMode::VerticalLine; |
450 bool is_first_line = line_box_data_list_.size() == 1; | 400 bool is_first_line = container_builder_.Children().isEmpty(); |
451 int baseline_offset = | 401 int baseline_offset = |
452 box->baselinePosition(baseline_type_, is_first_line, line_direction_mode); | 402 box->baselinePosition(baseline_type_, is_first_line, line_direction_mode); |
453 LayoutUnit block_start = estimated_baseline - baseline_offset; | 403 LayoutUnit block_start = estimated_baseline - baseline_offset; |
454 | 404 |
455 line_box_data->max_ascent_and_leading = | 405 NGLineHeightMetrics metrics; |
456 std::max<float>(baseline_offset, line_box_data->max_ascent_and_leading); | 406 metrics.ascent_and_leading = baseline_offset; |
457 line_box_data->max_descent_and_leading = std::max<float>( | 407 metrics.descent_and_leading = block_size - baseline_offset; |
458 block_size - baseline_offset, line_box_data->max_descent_and_leading); | 408 linebox->UniteMetrics(metrics); |
459 | 409 |
460 // TODO(kojii): Figure out what to do with OOF in NGLayoutResult. | 410 // TODO(kojii): Figure out what to do with OOF in NGLayoutResult. |
461 // Floats are ok because atomic inlines are BFC? | 411 // Floats are ok because atomic inlines are BFC? |
462 | 412 |
463 return block_start; | 413 return block_start; |
464 } | 414 } |
465 | 415 |
466 void NGLineBuilder::FindNextLayoutOpportunity() { | 416 void NGLineBuilder::FindNextLayoutOpportunity() { |
467 NGLogicalOffset iter_offset = constraint_space_->BfcOffset(); | 417 NGLogicalOffset iter_offset = constraint_space_->BfcOffset(); |
468 iter_offset.block_offset += content_size_; | 418 iter_offset.block_offset += content_size_; |
(...skipping 22 matching lines...) Expand all Loading... | |
491 block->deleteLineBoxTree(); | 441 block->deleteLineBoxTree(); |
492 | 442 |
493 Vector<NGLayoutInlineItem>& items = inline_box_->Items(); | 443 Vector<NGLayoutInlineItem>& items = inline_box_->Items(); |
494 Vector<unsigned, 32> text_offsets(items.size()); | 444 Vector<unsigned, 32> text_offsets(items.size()); |
495 inline_box_->GetLayoutTextOffsets(&text_offsets); | 445 inline_box_->GetLayoutTextOffsets(&text_offsets); |
496 | 446 |
497 Vector<const NGPhysicalFragment*, 32> fragments_for_bidi_runs; | 447 Vector<const NGPhysicalFragment*, 32> fragments_for_bidi_runs; |
498 fragments_for_bidi_runs.reserveInitialCapacity(items.size()); | 448 fragments_for_bidi_runs.reserveInitialCapacity(items.size()); |
499 BidiRunList<BidiRun> bidi_runs; | 449 BidiRunList<BidiRun> bidi_runs; |
500 LineInfo line_info; | 450 LineInfo line_info; |
501 unsigned fragment_index = 0; | |
502 NGPhysicalBoxFragment* box_fragment = toNGPhysicalBoxFragment( | 451 NGPhysicalBoxFragment* box_fragment = toNGPhysicalBoxFragment( |
503 container_layout_result_->PhysicalFragment().get()); | 452 container_layout_result_->PhysicalFragment().get()); |
504 for (const auto& line_box_data : line_box_data_list_) { | 453 for (const auto& container_child : box_fragment->Children()) { |
454 NGPhysicalLineboxFragment* physical_linebox = | |
455 toNGPhysicalLineboxFragment(container_child.get()); | |
505 // Create a BidiRunList for this line. | 456 // Create a BidiRunList for this line. |
506 for (; fragment_index < line_box_data.fragment_end; fragment_index++) { | 457 for (const auto& line_child : physical_linebox->Children()) { |
507 const NGPhysicalFragment* fragment = | 458 const auto* text_fragment = toNGPhysicalTextFragment(line_child.get()); |
508 box_fragment->Children()[fragment_index].get(); | |
509 if (!fragment->IsText()) | |
510 continue; | |
511 const auto* text_fragment = toNGPhysicalTextFragment(fragment); | |
512 const NGLayoutInlineItem& item = items[text_fragment->ItemIndex()]; | 459 const NGLayoutInlineItem& item = items[text_fragment->ItemIndex()]; |
513 LayoutObject* layout_object = item.GetLayoutObject(); | |
514 if (!layout_object) // Skip bidi controls. | |
515 continue; | |
516 BidiRun* run; | 460 BidiRun* run; |
517 if (layout_object->isText()) { | 461 if (item.Type() == NGLayoutInlineItem::kText) { |
462 LayoutObject* layout_object = item.GetLayoutObject(); | |
463 DCHECK(layout_object->isText()); | |
518 unsigned text_offset = text_offsets[text_fragment->ItemIndex()]; | 464 unsigned text_offset = text_offsets[text_fragment->ItemIndex()]; |
519 run = new BidiRun(text_fragment->StartOffset() - text_offset, | 465 run = new BidiRun(text_fragment->StartOffset() - text_offset, |
520 text_fragment->EndOffset() - text_offset, | 466 text_fragment->EndOffset() - text_offset, |
521 item.BidiLevel(), LineLayoutItem(layout_object)); | 467 item.BidiLevel(), LineLayoutItem(layout_object)); |
522 layout_object->clearNeedsLayout(); | 468 layout_object->clearNeedsLayout(); |
523 } else { | 469 } else if (item.Type() == NGLayoutInlineItem::kAtomicInline) { |
470 LayoutObject* layout_object = item.GetLayoutObject(); | |
524 DCHECK(layout_object->isAtomicInlineLevel()); | 471 DCHECK(layout_object->isAtomicInlineLevel()); |
525 run = | 472 run = |
526 new BidiRun(0, 1, item.BidiLevel(), LineLayoutItem(layout_object)); | 473 new BidiRun(0, 1, item.BidiLevel(), LineLayoutItem(layout_object)); |
474 } else { | |
475 continue; | |
527 } | 476 } |
528 bidi_runs.addRun(run); | 477 bidi_runs.addRun(run); |
529 fragments_for_bidi_runs.push_back(text_fragment); | 478 fragments_for_bidi_runs.push_back(text_fragment); |
530 } | 479 } |
531 // TODO(kojii): bidi needs to find the logical last run. | 480 // TODO(kojii): bidi needs to find the logical last run. |
532 bidi_runs.setLogicallyLastRun(bidi_runs.lastRun()); | 481 bidi_runs.setLogicallyLastRun(bidi_runs.lastRun()); |
533 | 482 |
534 // Create a RootInlineBox from BidiRunList. InlineBoxes created for the | 483 // Create a RootInlineBox from BidiRunList. InlineBoxes created for the |
535 // RootInlineBox are set to Bidirun::m_box. | 484 // RootInlineBox are set to Bidirun::m_box. |
536 line_info.setEmpty(false); | 485 line_info.setEmpty(false); |
537 // TODO(kojii): Implement setFirstLine, LastLine, etc. | 486 // TODO(kojii): Implement setFirstLine, LastLine, etc. |
538 RootInlineBox* line_box = block->constructLine(bidi_runs, line_info); | 487 RootInlineBox* root_line_box = block->constructLine(bidi_runs, line_info); |
539 | 488 |
540 // Copy fragments data to InlineBoxes. | 489 // Copy fragments data to InlineBoxes. |
541 DCHECK_EQ(fragments_for_bidi_runs.size(), bidi_runs.runCount()); | 490 DCHECK_EQ(fragments_for_bidi_runs.size(), bidi_runs.runCount()); |
542 BidiRun* run = bidi_runs.firstRun(); | 491 BidiRun* run = bidi_runs.firstRun(); |
543 for (auto* physical_fragment : fragments_for_bidi_runs) { | 492 for (auto* physical_fragment : fragments_for_bidi_runs) { |
544 DCHECK(run); | 493 DCHECK(run); |
545 NGTextFragment fragment(ConstraintSpace().WritingMode(), | 494 NGTextFragment fragment(ConstraintSpace().WritingMode(), |
546 toNGPhysicalTextFragment(physical_fragment)); | 495 toNGPhysicalTextFragment(physical_fragment)); |
547 InlineBox* inline_box = run->m_box; | 496 InlineBox* inline_box = run->m_box; |
548 inline_box->setLogicalWidth(fragment.InlineSize()); | 497 inline_box->setLogicalWidth(fragment.InlineSize()); |
549 inline_box->setLogicalLeft(fragment.InlineOffset()); | 498 inline_box->setLogicalLeft(fragment.InlineOffset()); |
550 inline_box->setLogicalTop(fragment.BlockOffset()); | 499 inline_box->setLogicalTop(fragment.BlockOffset()); |
551 if (inline_box->getLineLayoutItem().isBox()) { | 500 if (inline_box->getLineLayoutItem().isBox()) { |
552 LineLayoutBox box(inline_box->getLineLayoutItem()); | 501 LineLayoutBox box(inline_box->getLineLayoutItem()); |
553 box.setLocation(inline_box->location()); | 502 box.setLocation(inline_box->location()); |
554 } | 503 } |
555 run = run->next(); | 504 run = run->next(); |
556 } | 505 } |
557 DCHECK(!run); | 506 DCHECK(!run); |
558 | 507 |
559 // Copy LineBoxData to RootInlineBox. | 508 // Copy to RootInlineBox. |
560 line_box->setLogicalWidth(line_box_data.inline_size); | 509 NGLineboxFragment linebox(ConstraintSpace().WritingMode(), |
561 line_box->setLogicalTop(line_box_data.top_with_leading); | 510 physical_linebox); |
562 LayoutUnit baseline_position = | 511 root_line_box->setLogicalWidth(linebox.InlineSize()); |
563 line_box_data.top_with_leading + | 512 LayoutUnit line_top_with_leading = linebox.BlockOffset(); |
564 LayoutUnit(line_box_data.max_ascent_and_leading); | 513 root_line_box->setLogicalTop(line_top_with_leading); |
565 line_box->setLineTopBottomPositions( | 514 const NGLineHeightMetrics& metrics = physical_linebox->Metrics(); |
566 baseline_position - LayoutUnit(line_box_data.max_ascent), | 515 LayoutUnit baseline = |
567 baseline_position + LayoutUnit(line_box_data.max_descent), | 516 line_top_with_leading + LayoutUnit(metrics.ascent_and_leading); |
568 line_box_data.top_with_leading, | 517 root_line_box->setLineTopBottomPositions( |
569 baseline_position + LayoutUnit(line_box_data.max_descent_and_leading)); | 518 baseline - LayoutUnit(metrics.ascent), |
519 baseline + LayoutUnit(metrics.descent), line_top_with_leading, | |
520 baseline + LayoutUnit(metrics.descent_and_leading)); | |
570 | 521 |
571 bidi_runs.deleteRuns(); | 522 bidi_runs.deleteRuns(); |
572 fragments_for_bidi_runs.clear(); | 523 fragments_for_bidi_runs.clear(); |
573 } | 524 } |
574 } | 525 } |
575 } // namespace blink | 526 } // namespace blink |
OLD | NEW |