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