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