Chromium Code Reviews| 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_constraint_space.h" | 12 #include "core/layout/ng/ng_constraint_space.h" |
| 13 #include "core/layout/ng/ng_fragment_builder.h" | 13 #include "core/layout/ng/ng_fragment_builder.h" |
| 14 #include "core/layout/ng/ng_inline_node.h" | 14 #include "core/layout/ng/ng_inline_node.h" |
| 15 #include "core/layout/ng/ng_length_utils.h" | 15 #include "core/layout/ng/ng_length_utils.h" |
| 16 #include "core/layout/ng/ng_text_fragment.h" | 16 #include "core/layout/ng/ng_text_fragment.h" |
| 17 #include "core/style/ComputedStyle.h" | 17 #include "core/style/ComputedStyle.h" |
| 18 #include "platform/text/BidiRunList.h" | 18 #include "platform/text/BidiRunList.h" |
| 19 | 19 |
| 20 namespace blink { | 20 namespace blink { |
| 21 | 21 |
| 22 NGLineBuilder::NGLineBuilder(NGInlineNode* inline_box, | 22 NGLineBuilder::NGLineBuilder(NGInlineNode* inline_box, |
| 23 NGConstraintSpace* constraint_space, | 23 NGConstraintSpace* constraint_space, |
| 24 NGFragmentBuilder* containing_block_builder) | 24 NGFragmentBuilder* containing_block_builder) |
| 25 : inline_box_(inline_box), | 25 : inline_box_(inline_box), |
| 26 constraint_space_(constraint_space), | 26 constraint_space_(constraint_space), |
| 27 containing_block_builder_(containing_block_builder), | 27 containing_block_builder_(containing_block_builder), |
| 28 baseline_type_(constraint_space->WritingMode() == | 28 is_horizontal_writing_mode_( |
| 29 NGWritingMode::kHorizontalTopBottom | 29 blink::IsHorizontalWritingMode(constraint_space->WritingMode())) |
| 30 ? FontBaseline::AlphabeticBaseline | |
| 31 : FontBaseline::IdeographicBaseline) | |
| 32 #if DCHECK_IS_ON() | 30 #if DCHECK_IS_ON() |
| 33 , | 31 , |
| 34 is_bidi_reordered_(false) | 32 is_bidi_reordered_(false) |
| 35 #endif | 33 #endif |
| 36 { | 34 { |
| 35 if (!is_horizontal_writing_mode_) | |
| 36 baseline_type_ = FontBaseline::IdeographicBaseline; | |
| 37 } | 37 } |
| 38 | 38 |
| 39 bool NGLineBuilder::CanFitOnLine() const { | 39 bool NGLineBuilder::CanFitOnLine() const { |
| 40 LayoutUnit available_size = current_opportunity_.InlineSize(); | 40 LayoutUnit available_size = current_opportunity_.InlineSize(); |
| 41 if (available_size == NGSizeIndefinite) | 41 if (available_size == NGSizeIndefinite) |
| 42 return true; | 42 return true; |
| 43 return end_position_ <= available_size; | 43 return end_position_ <= available_size; |
| 44 } | 44 } |
| 45 | 45 |
| 46 bool NGLineBuilder::HasItems() const { | 46 bool NGLineBuilder::HasItems() const { |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 69 DCHECK_GT(new_end_offset, end_offset_); | 69 DCHECK_GT(new_end_offset, end_offset_); |
| 70 const Vector<NGLayoutInlineItem>& items = inline_box_->Items(); | 70 const Vector<NGLayoutInlineItem>& items = inline_box_->Items(); |
| 71 DCHECK_LE(new_end_offset, items.back().EndOffset()); | 71 DCHECK_LE(new_end_offset, items.back().EndOffset()); |
| 72 | 72 |
| 73 // SetEnd() while |new_end_offset| is beyond the current last item. | 73 // SetEnd() while |new_end_offset| is beyond the current last item. |
| 74 unsigned last_index = last_index_; | 74 unsigned last_index = last_index_; |
| 75 const NGLayoutInlineItem* item = &items[last_index]; | 75 const NGLayoutInlineItem* item = &items[last_index]; |
| 76 if (new_end_offset > item->EndOffset()) { | 76 if (new_end_offset > item->EndOffset()) { |
| 77 if (end_offset_ < item->EndOffset()) { | 77 if (end_offset_ < item->EndOffset()) { |
| 78 SetEnd(item->EndOffset(), | 78 SetEnd(item->EndOffset(), |
| 79 item->InlineSize(end_offset_, item->EndOffset())); | 79 InlineSize(*item, end_offset_, item->EndOffset())); |
| 80 } | 80 } |
| 81 item = &items[++last_index]; | 81 item = &items[++last_index]; |
| 82 | 82 |
| 83 while (new_end_offset > item->EndOffset()) { | 83 while (new_end_offset > item->EndOffset()) { |
| 84 SetEnd(item->EndOffset(), item->InlineSize()); | 84 SetEnd(item->EndOffset(), InlineSize(*item)); |
| 85 item = &items[++last_index]; | 85 item = &items[++last_index]; |
| 86 } | 86 } |
| 87 } | 87 } |
| 88 | 88 |
| 89 SetEnd(new_end_offset, item->InlineSize(end_offset_, new_end_offset)); | 89 SetEnd(new_end_offset, InlineSize(*item, end_offset_, new_end_offset)); |
| 90 } | 90 } |
| 91 | 91 |
| 92 void NGLineBuilder::SetEnd(unsigned new_end_offset, | 92 void NGLineBuilder::SetEnd(unsigned new_end_offset, |
| 93 LayoutUnit inline_size_since_current_end) { | 93 LayoutUnit inline_size_since_current_end) { |
| 94 DCHECK_GT(new_end_offset, end_offset_); | 94 DCHECK_GT(new_end_offset, end_offset_); |
| 95 const Vector<NGLayoutInlineItem>& items = inline_box_->Items(); | 95 const Vector<NGLayoutInlineItem>& items = inline_box_->Items(); |
| 96 DCHECK_LE(new_end_offset, items.back().EndOffset()); | 96 DCHECK_LE(new_end_offset, items.back().EndOffset()); |
| 97 | 97 |
| 98 // |new_end_offset| should be in the current item or next. | 98 // |new_end_offset| should be in the current item or next. |
| 99 // TODO(kojii): Reconsider this restriction if needed. | 99 // TODO(kojii): Reconsider this restriction if needed. |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 118 void NGLineBuilder::SetBreakOpportunity() { | 118 void NGLineBuilder::SetBreakOpportunity() { |
| 119 last_break_opportunity_index_ = last_index_; | 119 last_break_opportunity_index_ = last_index_; |
| 120 last_break_opportunity_offset_ = end_offset_; | 120 last_break_opportunity_offset_ = end_offset_; |
| 121 last_break_opportunity_position_ = end_position_; | 121 last_break_opportunity_position_ = end_position_; |
| 122 } | 122 } |
| 123 | 123 |
| 124 void NGLineBuilder::SetStartOfHangables(unsigned offset) { | 124 void NGLineBuilder::SetStartOfHangables(unsigned offset) { |
| 125 // TODO(kojii): Implement. | 125 // TODO(kojii): Implement. |
| 126 } | 126 } |
| 127 | 127 |
| 128 LayoutUnit NGLineBuilder::InlineSize(const NGLayoutInlineItem& item) { | |
| 129 if (item.IsAtomicInlineLevel()) | |
| 130 return InlineSizeFromLayout(item); | |
| 131 return item.InlineSize(); | |
| 132 } | |
| 133 | |
| 134 LayoutUnit NGLineBuilder::InlineSize(const NGLayoutInlineItem& item, | |
| 135 unsigned start_offset, | |
| 136 unsigned end_offset) { | |
| 137 if (item.StartOffset() == start_offset && item.EndOffset() == end_offset && | |
| 138 item.IsAtomicInlineLevel()) | |
| 139 return InlineSizeFromLayout(item); | |
| 140 return item.InlineSize(start_offset, end_offset); | |
| 141 } | |
| 142 | |
| 143 LayoutUnit NGLineBuilder::InlineSizeFromLayout(const NGLayoutInlineItem& item) { | |
| 144 const RefPtr<NGLayoutResult>& layout_result = LayoutItem(item); | |
| 145 return IsHorizontalWritingMode() | |
|
ikilpatrick
2017/03/16 16:15:40
instead of this can you stack allocate a NGBoxFrag
kojii
2017/03/16 16:48:45
Done. I didn't know I can pass parent's writing-mo
| |
| 146 ? layout_result->PhysicalFragment()->Width() | |
| 147 : layout_result->PhysicalFragment()->Height(); | |
| 148 } | |
| 149 | |
| 150 RefPtr<NGLayoutResult>& NGLineBuilder::LayoutItem( | |
| 151 const NGLayoutInlineItem& item) { | |
| 152 const Vector<NGLayoutInlineItem>& items = inline_box_->Items(); | |
| 153 if (layout_results_.isEmpty()) | |
| 154 layout_results_.resize(items.size()); | |
| 155 unsigned index = std::distance(items.begin(), &item); | |
| 156 RefPtr<NGLayoutResult>& layout_result = layout_results_[index]; | |
| 157 if (!layout_result) | |
| 158 layout_result = item.Layout(ConstraintSpace()); | |
|
ikilpatrick
2017/03/16 16:15:41
We'll need to fix this constraint space, this migh
ikilpatrick
2017/03/16 16:15:41
on this is not a NGLayoutInputNode, hmmm... i foun
kojii
2017/03/16 16:48:45
Understood, moved the layout code here.
| |
| 159 return layout_result; | |
|
ikilpatrick
2017/03/16 16:15:40
do we need to assign back to the layout_results_ v
kojii
2017/03/16 16:48:45
|layout_result| here is a reference to the vector.
| |
| 160 } | |
| 161 | |
| 128 void NGLineBuilder::CreateLine() { | 162 void NGLineBuilder::CreateLine() { |
| 129 if (HasItemsAfterLastBreakOpportunity()) | 163 if (HasItemsAfterLastBreakOpportunity()) |
| 130 SetBreakOpportunity(); | 164 SetBreakOpportunity(); |
| 131 CreateLineUpToLastBreakOpportunity(); | 165 CreateLineUpToLastBreakOpportunity(); |
| 132 } | 166 } |
| 133 | 167 |
| 134 void NGLineBuilder::CreateLineUpToLastBreakOpportunity() { | 168 void NGLineBuilder::CreateLineUpToLastBreakOpportunity() { |
| 135 const Vector<NGLayoutInlineItem>& items = inline_box_->Items(); | 169 const Vector<NGLayoutInlineItem>& items = inline_box_->Items(); |
| 136 | 170 |
| 137 // Create a list of LineItemChunk from |start| and |last_break_opportunity|. | 171 // Create a list of LineItemChunk from |start| and |last_break_opportunity|. |
| 138 // TODO(kojii): Consider refactoring LineItemChunk once NGLineBuilder's public | 172 // TODO(kojii): Consider refactoring LineItemChunk once NGLineBuilder's public |
| 139 // API is more finalized. It does not fit well with the current API. | 173 // API is more finalized. It does not fit well with the current API. |
| 140 Vector<LineItemChunk, 32> line_item_chunks; | 174 Vector<LineItemChunk, 32> line_item_chunks; |
| 141 unsigned start_offset = start_offset_; | 175 unsigned start_offset = start_offset_; |
| 142 for (unsigned i = start_index_; i <= last_break_opportunity_index_; i++) { | 176 for (unsigned i = start_index_; i <= last_break_opportunity_index_; i++) { |
| 143 const NGLayoutInlineItem& item = items[i]; | 177 const NGLayoutInlineItem& item = items[i]; |
| 144 unsigned end_offset = | 178 unsigned end_offset = |
| 145 std::min(item.EndOffset(), last_break_opportunity_offset_); | 179 std::min(item.EndOffset(), last_break_opportunity_offset_); |
| 146 line_item_chunks.push_back( | 180 line_item_chunks.push_back( |
| 147 LineItemChunk{i, start_offset, end_offset, | 181 LineItemChunk{i, start_offset, end_offset, |
| 148 item.InlineSize(start_offset, end_offset)}); | 182 InlineSize(item, start_offset, end_offset)}); |
| 149 start_offset = end_offset; | 183 start_offset = end_offset; |
| 150 } | 184 } |
| 151 | 185 |
| 152 if (inline_box_->IsBidiEnabled()) | 186 if (inline_box_->IsBidiEnabled()) |
| 153 BidiReorder(&line_item_chunks); | 187 BidiReorder(&line_item_chunks); |
| 154 | 188 |
| 155 PlaceItems(line_item_chunks); | 189 PlaceItems(line_item_chunks); |
| 156 | 190 |
| 157 // Prepare for the next line. | 191 // Prepare for the next line. |
| 158 // Move |start| to |last_break_opportunity|, keeping items after | 192 // Move |start| to |last_break_opportunity|, keeping items after |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 226 // estimation turned out to be different. | 260 // estimation turned out to be different. |
| 227 LayoutUnit estimated_baseline = | 261 LayoutUnit estimated_baseline = |
| 228 content_size_ + LayoutUnit(block_metrics.ascent_and_leading); | 262 content_size_ + LayoutUnit(block_metrics.ascent_and_leading); |
| 229 | 263 |
| 230 for (const auto& line_item_chunk : line_item_chunks) { | 264 for (const auto& line_item_chunk : line_item_chunks) { |
| 231 const NGLayoutInlineItem& item = items[line_item_chunk.index]; | 265 const NGLayoutInlineItem& item = items[line_item_chunk.index]; |
| 232 // Skip bidi controls. | 266 // Skip bidi controls. |
| 233 if (!item.GetLayoutObject()) | 267 if (!item.GetLayoutObject()) |
| 234 continue; | 268 continue; |
| 235 | 269 |
| 236 LayoutUnit top, height; | 270 LayoutUnit top; |
| 237 const ComputedStyle* style = item.Style(); | 271 const ComputedStyle* style = item.Style(); |
| 238 if (style) { | 272 if (style) { |
| 273 DCHECK(item.GetLayoutObject()->isText()); | |
| 239 // |InlineTextBoxPainter| sets the baseline at |top + | 274 // |InlineTextBoxPainter| sets the baseline at |top + |
| 240 // ascent-of-primary-font|. Compute |top| to match. | 275 // ascent-of-primary-font|. Compute |top| to match. |
| 241 InlineItemMetrics metrics(*style, baseline_type_); | 276 InlineItemMetrics metrics(*style, baseline_type_); |
| 242 top = estimated_baseline - LayoutUnit(metrics.ascent); | 277 top = estimated_baseline - LayoutUnit(metrics.ascent); |
| 243 height = LayoutUnit(metrics.ascent + metrics.descent); | 278 LayoutUnit height = LayoutUnit(metrics.ascent + metrics.descent); |
| 244 line_box_data.UpdateMaxAscentAndDescent(metrics); | 279 line_box_data.UpdateMaxAscentAndDescent(metrics); |
| 245 | 280 |
| 246 // Take all used fonts into account if 'line-height: normal'. | 281 // Take all used fonts into account if 'line-height: normal'. |
| 247 if (style->lineHeight().isNegative()) | 282 if (style->lineHeight().isNegative()) |
| 248 AccumulateUsedFonts(item, line_item_chunk, &line_box_data); | 283 AccumulateUsedFonts(item, line_item_chunk, &line_box_data); |
| 284 | |
| 285 // The direction of a fragment is the CSS direction to resolve logical | |
| 286 // properties, not the resolved bidi direction. | |
| 287 text_builder.SetDirection(style->direction()) | |
| 288 .SetInlineSize(line_item_chunk.inline_size) | |
| 289 .SetInlineOverflow(line_item_chunk.inline_size) | |
| 290 .SetBlockSize(height) | |
| 291 .SetBlockOverflow(height); | |
| 249 } else { | 292 } else { |
| 250 LayoutObject* layout_object = item.GetLayoutObject(); | 293 LayoutObject* layout_object = item.GetLayoutObject(); |
| 251 if (layout_object->isOutOfFlowPositioned()) { | 294 if (layout_object->isOutOfFlowPositioned()) { |
| 252 if (containing_block_builder_) { | 295 if (containing_block_builder_) { |
| 253 // Absolute positioning blockifies the box's display type. | 296 // Absolute positioning blockifies the box's display type. |
| 254 // https://drafts.csswg.org/css-display/#transformations | 297 // https://drafts.csswg.org/css-display/#transformations |
| 255 containing_block_builder_->AddOutOfFlowChildCandidate( | 298 containing_block_builder_->AddOutOfFlowChildCandidate( |
| 256 new NGBlockNode(layout_object), | 299 new NGBlockNode(layout_object), |
| 257 NGLogicalOffset(line_box_data.inline_size, content_size_)); | 300 NGLogicalOffset(line_box_data.inline_size, content_size_)); |
| 258 } | 301 } |
| 259 continue; | 302 continue; |
| 260 } else if (layout_object->isFloating()) { | 303 } else if (layout_object->isFloating()) { |
| 261 // TODO(kojii): Implement float. | 304 // TODO(kojii): Implement float. |
| 262 DLOG(ERROR) << "Floats in inline not implemented yet."; | 305 DLOG(ERROR) << "Floats in inline not implemented yet."; |
| 263 // TODO(kojii): Temporarily clearNeedsLayout() for not to assert. | 306 // TODO(kojii): Temporarily clearNeedsLayout() for not to assert. |
| 264 layout_object->clearNeedsLayout(); | 307 layout_object->clearNeedsLayout(); |
| 265 continue; | 308 continue; |
| 266 } | 309 } |
| 267 DCHECK(layout_object->isAtomicInlineLevel()); | 310 top = PlaceAtomicInline(item, estimated_baseline, &line_box_data, |
| 268 // TODO(kojii): Implement atomic inline. | 311 &text_builder); |
| 269 style = layout_object->style(); | |
| 270 top = content_size_; | |
| 271 } | 312 } |
| 272 | 313 |
| 273 // The direction of a fragment is the CSS direction to resolve logical | |
| 274 // properties, not the resolved bidi direction. | |
| 275 text_builder.SetDirection(style->direction()) | |
| 276 .SetInlineSize(line_item_chunk.inline_size) | |
| 277 .SetInlineOverflow(line_item_chunk.inline_size) | |
| 278 .SetBlockSize(height) | |
| 279 .SetBlockOverflow(height); | |
| 280 RefPtr<NGPhysicalTextFragment> text_fragment = text_builder.ToTextFragment( | 314 RefPtr<NGPhysicalTextFragment> text_fragment = text_builder.ToTextFragment( |
| 281 line_item_chunk.index, line_item_chunk.start_offset, | 315 line_item_chunk.index, line_item_chunk.start_offset, |
| 282 line_item_chunk.end_offset); | 316 line_item_chunk.end_offset); |
| 283 fragments_.push_back(std::move(text_fragment)); | 317 fragments_.push_back(std::move(text_fragment)); |
| 284 | 318 |
| 285 NGLogicalOffset logical_offset( | 319 NGLogicalOffset logical_offset( |
| 286 line_box_data.inline_size + current_opportunity_.InlineStartOffset() - | 320 line_box_data.inline_size + current_opportunity_.InlineStartOffset() - |
| 287 ConstraintSpace().BfcOffset().inline_offset, | 321 ConstraintSpace().BfcOffset().inline_offset, |
| 288 top); | 322 top); |
| 289 offsets_.push_back(logical_offset); | 323 offsets_.push_back(logical_offset); |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 360 HashSet<const SimpleFontData*> fallback_fonts; | 394 HashSet<const SimpleFontData*> fallback_fonts; |
| 361 item.GetFallbackFonts(&fallback_fonts, line_item_chunk.start_offset, | 395 item.GetFallbackFonts(&fallback_fonts, line_item_chunk.start_offset, |
| 362 line_item_chunk.end_offset); | 396 line_item_chunk.end_offset); |
| 363 for (const auto& fallback_font : fallback_fonts) { | 397 for (const auto& fallback_font : fallback_fonts) { |
| 364 InlineItemMetrics fallback_font_metrics(fallback_font->getFontMetrics(), | 398 InlineItemMetrics fallback_font_metrics(fallback_font->getFontMetrics(), |
| 365 baseline_type_); | 399 baseline_type_); |
| 366 line_box_data->UpdateMaxAscentAndDescent(fallback_font_metrics); | 400 line_box_data->UpdateMaxAscentAndDescent(fallback_font_metrics); |
| 367 } | 401 } |
| 368 } | 402 } |
| 369 | 403 |
| 404 LayoutUnit NGLineBuilder::PlaceAtomicInline(const NGLayoutInlineItem& item, | |
| 405 LayoutUnit estimated_baseline, | |
| 406 LineBoxData* line_box_data, | |
| 407 NGFragmentBuilder* text_builder) { | |
| 408 const RefPtr<NGLayoutResult>& layout_result = LayoutItem(item); | |
| 409 RefPtr<NGPhysicalFragment> fragment = layout_result->PhysicalFragment(); | |
| 410 LayoutUnit height; | |
| 411 // TODO(kojii): Try to eliminate the text fragment and use the |fragment| | |
| 412 // directly. Currently |CopyFragmentDataToLayoutBlockFlow| requires a text | |
| 413 // fragment. | |
| 414 // TODO(kojii): Margin and border in block progression not implemented yet. | |
| 415 if (IsHorizontalWritingMode()) { | |
| 416 height = fragment->Height(); | |
| 417 text_builder->SetInlineSize(fragment->Width()) | |
| 418 .SetInlineOverflow(fragment->WidthOverflow()) | |
| 419 .SetBlockSize(height) | |
| 420 .SetBlockOverflow(fragment->HeightOverflow()); | |
| 421 } else { | |
| 422 height = fragment->Width(); | |
| 423 text_builder->SetInlineSize(fragment->Height()) | |
| 424 .SetInlineOverflow(fragment->HeightOverflow()) | |
| 425 .SetBlockSize(height) | |
| 426 .SetBlockOverflow(fragment->WidthOverflow()); | |
| 427 } | |
| 428 | |
| 429 // TODO(kojii): Add baseline position to NGPhysicalFragment. | |
| 430 LayoutBox* box = toLayoutBox(item.GetLayoutObject()); | |
| 431 LineDirectionMode line_direction_mode = | |
| 432 IsHorizontalWritingMode() ? LineDirectionMode::HorizontalLine | |
| 433 : LineDirectionMode::VerticalLine; | |
| 434 bool is_first_line = line_box_data_list_.size() == 1; | |
| 435 int baseline_offset = | |
| 436 box->baselinePosition(baseline_type_, is_first_line, line_direction_mode); | |
| 437 LayoutUnit top = estimated_baseline - baseline_offset; | |
| 438 | |
| 439 line_box_data->max_ascent_and_leading = | |
| 440 std::max<float>(baseline_offset, line_box_data->max_ascent_and_leading); | |
| 441 line_box_data->max_descent_and_leading = std::max<float>( | |
| 442 height - baseline_offset, line_box_data->max_descent_and_leading); | |
| 443 | |
| 444 // TODO(kojii): Figure out what to do with OOF in NGLayoutResult. | |
| 445 // Floats are ok because atomic inlines are BFC? | |
| 446 | |
| 447 return top; | |
| 448 } | |
| 449 | |
| 370 void NGLineBuilder::FindNextLayoutOpportunity() { | 450 void NGLineBuilder::FindNextLayoutOpportunity() { |
| 371 NGLogicalOffset iter_offset = constraint_space_->BfcOffset(); | 451 NGLogicalOffset iter_offset = constraint_space_->BfcOffset(); |
| 372 iter_offset.block_offset += content_size_; | 452 iter_offset.block_offset += content_size_; |
| 373 auto* iter = constraint_space_->LayoutOpportunityIterator(iter_offset); | 453 auto* iter = constraint_space_->LayoutOpportunityIterator(iter_offset); |
| 374 NGLayoutOpportunity opportunity = iter->Next(); | 454 NGLayoutOpportunity opportunity = iter->Next(); |
| 375 if (!opportunity.IsEmpty()) | 455 if (!opportunity.IsEmpty()) |
| 376 current_opportunity_ = opportunity; | 456 current_opportunity_ = opportunity; |
| 377 } | 457 } |
| 378 | 458 |
| 379 RefPtr<NGLayoutResult> NGLineBuilder::CreateFragments() { | 459 RefPtr<NGLayoutResult> NGLineBuilder::CreateFragments() { |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 425 if (layout_object->isText()) { | 505 if (layout_object->isText()) { |
| 426 unsigned text_offset = text_offsets[text_fragment->ItemIndex()]; | 506 unsigned text_offset = text_offsets[text_fragment->ItemIndex()]; |
| 427 run = new BidiRun(text_fragment->StartOffset() - text_offset, | 507 run = new BidiRun(text_fragment->StartOffset() - text_offset, |
| 428 text_fragment->EndOffset() - text_offset, | 508 text_fragment->EndOffset() - text_offset, |
| 429 item.BidiLevel(), LineLayoutItem(layout_object)); | 509 item.BidiLevel(), LineLayoutItem(layout_object)); |
| 430 layout_object->clearNeedsLayout(); | 510 layout_object->clearNeedsLayout(); |
| 431 } else { | 511 } else { |
| 432 DCHECK(layout_object->isAtomicInlineLevel()); | 512 DCHECK(layout_object->isAtomicInlineLevel()); |
| 433 run = | 513 run = |
| 434 new BidiRun(0, 1, item.BidiLevel(), LineLayoutItem(layout_object)); | 514 new BidiRun(0, 1, item.BidiLevel(), LineLayoutItem(layout_object)); |
| 435 // TODO(kojii): Temporarily clearNeedsLayout() for not to assert. | |
| 436 layout_object->clearNeedsLayout(); | |
| 437 } | 515 } |
| 438 bidi_runs.addRun(run); | 516 bidi_runs.addRun(run); |
| 439 fragments_for_bidi_runs.push_back(text_fragment); | 517 fragments_for_bidi_runs.push_back(text_fragment); |
| 440 } | 518 } |
| 441 // TODO(kojii): bidi needs to find the logical last run. | 519 // TODO(kojii): bidi needs to find the logical last run. |
| 442 bidi_runs.setLogicallyLastRun(bidi_runs.lastRun()); | 520 bidi_runs.setLogicallyLastRun(bidi_runs.lastRun()); |
| 443 | 521 |
| 444 // Create a RootInlineBox from BidiRunList. InlineBoxes created for the | 522 // Create a RootInlineBox from BidiRunList. InlineBoxes created for the |
| 445 // RootInlineBox are set to Bidirun::m_box. | 523 // RootInlineBox are set to Bidirun::m_box. |
| 446 line_info.setEmpty(false); | 524 line_info.setEmpty(false); |
| 447 // TODO(kojii): Implement setFirstLine, LastLine, etc. | 525 // TODO(kojii): Implement setFirstLine, LastLine, etc. |
| 448 RootInlineBox* line_box = block->constructLine(bidi_runs, line_info); | 526 RootInlineBox* line_box = block->constructLine(bidi_runs, line_info); |
| 449 | 527 |
| 450 // Copy fragments data to InlineBoxes. | 528 // Copy fragments data to InlineBoxes. |
| 451 DCHECK_EQ(fragments_for_bidi_runs.size(), bidi_runs.runCount()); | 529 DCHECK_EQ(fragments_for_bidi_runs.size(), bidi_runs.runCount()); |
| 452 BidiRun* run = bidi_runs.firstRun(); | 530 BidiRun* run = bidi_runs.firstRun(); |
| 453 for (auto* physical_fragment : fragments_for_bidi_runs) { | 531 for (auto* physical_fragment : fragments_for_bidi_runs) { |
| 454 DCHECK(run); | 532 DCHECK(run); |
| 455 NGTextFragment fragment(ConstraintSpace().WritingMode(), | 533 NGTextFragment fragment(ConstraintSpace().WritingMode(), |
| 456 toNGPhysicalTextFragment(physical_fragment)); | 534 toNGPhysicalTextFragment(physical_fragment)); |
| 457 InlineBox* inline_box = run->m_box; | 535 InlineBox* inline_box = run->m_box; |
| 458 inline_box->setLogicalWidth(fragment.InlineSize()); | 536 inline_box->setLogicalWidth(fragment.InlineSize()); |
| 459 inline_box->setLogicalLeft(fragment.InlineOffset()); | 537 inline_box->setLogicalLeft(fragment.InlineOffset()); |
| 460 inline_box->setLogicalTop(fragment.BlockOffset()); | 538 inline_box->setLogicalTop(fragment.BlockOffset()); |
| 539 if (inline_box->getLineLayoutItem().isBox()) { | |
| 540 LineLayoutBox box(inline_box->getLineLayoutItem()); | |
| 541 box.setLocation(inline_box->location()); | |
| 542 } | |
| 461 run = run->next(); | 543 run = run->next(); |
| 462 } | 544 } |
| 463 DCHECK(!run); | 545 DCHECK(!run); |
| 464 | 546 |
| 465 // Copy LineBoxData to RootInlineBox. | 547 // Copy LineBoxData to RootInlineBox. |
| 466 line_box->setLogicalWidth(line_box_data.inline_size); | 548 line_box->setLogicalWidth(line_box_data.inline_size); |
| 549 line_box->setLogicalTop(line_box_data.top_with_leading); | |
| 467 LayoutUnit baseline_position = | 550 LayoutUnit baseline_position = |
| 468 line_box_data.top_with_leading + | 551 line_box_data.top_with_leading + |
| 469 LayoutUnit(line_box_data.max_ascent_and_leading); | 552 LayoutUnit(line_box_data.max_ascent_and_leading); |
| 470 line_box->setLineTopBottomPositions( | 553 line_box->setLineTopBottomPositions( |
| 471 baseline_position - LayoutUnit(line_box_data.max_ascent), | 554 baseline_position - LayoutUnit(line_box_data.max_ascent), |
| 472 baseline_position + LayoutUnit(line_box_data.max_descent), | 555 baseline_position + LayoutUnit(line_box_data.max_descent), |
| 473 line_box_data.top_with_leading, | 556 line_box_data.top_with_leading, |
| 474 baseline_position + LayoutUnit(line_box_data.max_descent_and_leading)); | 557 baseline_position + LayoutUnit(line_box_data.max_descent_and_leading)); |
| 475 | 558 |
| 476 bidi_runs.deleteRuns(); | 559 bidi_runs.deleteRuns(); |
| 477 fragments_for_bidi_runs.clear(); | 560 fragments_for_bidi_runs.clear(); |
| 478 } | 561 } |
| 479 } | 562 } |
| 480 } // namespace blink | 563 } // namespace blink |
| OLD | NEW |