Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(509)

Side by Side Diff: third_party/WebKit/Source/core/layout/ng/ng_line_builder.cc

Issue 2745973002: [LayoutNG] Implement atomic inlines for LayoutNGInline (Closed)
Patch Set: WIP Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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"
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after
211 // estimation turned out to be different. 211 // estimation turned out to be different.
212 LayoutUnit estimated_baseline = 212 LayoutUnit estimated_baseline =
213 content_size_ + LayoutUnit(block_metrics.ascent_and_leading); 213 content_size_ + LayoutUnit(block_metrics.ascent_and_leading);
214 214
215 for (const auto& line_item_chunk : line_item_chunks) { 215 for (const auto& line_item_chunk : line_item_chunks) {
216 const NGLayoutInlineItem& item = items[line_item_chunk.index]; 216 const NGLayoutInlineItem& item = items[line_item_chunk.index];
217 // Skip bidi controls. 217 // Skip bidi controls.
218 if (!item.GetLayoutObject()) 218 if (!item.GetLayoutObject())
219 continue; 219 continue;
220 220
221 LayoutUnit top, height; 221 LayoutUnit top;
222 const ComputedStyle* style = item.Style(); 222 const ComputedStyle* style = item.Style();
223 if (style) { 223 if (style) {
224 DCHECK(item.GetLayoutObject()->isText());
224 // |InlineTextBoxPainter| sets the baseline at |top + 225 // |InlineTextBoxPainter| sets the baseline at |top +
225 // ascent-of-primary-font|. Compute |top| to match. 226 // ascent-of-primary-font|. Compute |top| to match.
226 InlineItemMetrics metrics(*style, baseline_type_); 227 InlineItemMetrics metrics(*style, baseline_type_);
227 top = estimated_baseline - LayoutUnit(metrics.ascent); 228 top = estimated_baseline - LayoutUnit(metrics.ascent);
228 height = LayoutUnit(metrics.ascent + metrics.descent); 229 LayoutUnit height = LayoutUnit(metrics.ascent + metrics.descent);
229 line_box_data.UpdateMaxAscentAndDescent(metrics); 230 line_box_data.UpdateMaxAscentAndDescent(metrics);
230 231
231 // Take all used fonts into account if 'line-height: normal'. 232 // Take all used fonts into account if 'line-height: normal'.
232 if (style->lineHeight().isNegative()) 233 if (style->lineHeight().isNegative())
233 AccumulateUsedFonts(item, line_item_chunk, &line_box_data); 234 AccumulateUsedFonts(item, line_item_chunk, &line_box_data);
235
236 // The direction of a fragment is the CSS direction to resolve logical
237 // properties, not the resolved bidi direction.
238 text_builder.SetDirection(style->direction())
239 .SetInlineSize(line_item_chunk.inline_size)
240 .SetInlineOverflow(line_item_chunk.inline_size)
241 .SetBlockSize(height)
242 .SetBlockOverflow(height);
234 } else { 243 } else {
235 LayoutObject* layout_object = item.GetLayoutObject(); 244 LayoutObject* layout_object = item.GetLayoutObject();
236 if (layout_object->isOutOfFlowPositioned()) { 245 if (layout_object->isOutOfFlowPositioned()) {
237 if (containing_block_builder_) { 246 if (containing_block_builder_) {
238 // Absolute positioning blockifies the box's display type. 247 // Absolute positioning blockifies the box's display type.
239 // https://drafts.csswg.org/css-display/#transformations 248 // https://drafts.csswg.org/css-display/#transformations
240 containing_block_builder_->AddOutOfFlowChildCandidate( 249 containing_block_builder_->AddOutOfFlowChildCandidate(
241 new NGBlockNode(layout_object), 250 new NGBlockNode(layout_object),
242 NGLogicalOffset(line_box_data.inline_size, content_size_)); 251 NGLogicalOffset(line_box_data.inline_size, content_size_));
243 } 252 }
244 continue; 253 continue;
245 } else if (layout_object->isFloating()) { 254 } else if (layout_object->isFloating()) {
246 // TODO(kojii): Implement float. 255 // TODO(kojii): Implement float.
247 DLOG(ERROR) << "Floats in inline not implemented yet."; 256 DLOG(ERROR) << "Floats in inline not implemented yet.";
248 // TODO(kojii): Temporarily clearNeedsLayout() for not to assert. 257 // TODO(kojii): Temporarily clearNeedsLayout() for not to assert.
249 layout_object->clearNeedsLayout(); 258 layout_object->clearNeedsLayout();
250 continue; 259 continue;
251 } 260 }
252 DCHECK(layout_object->isAtomicInlineLevel()); 261 top = PlaceAtomicInline(item, estimated_baseline, &line_box_data,
253 // TODO(kojii): Implement atomic inline. 262 &text_builder);
254 style = layout_object->style();
255 top = content_size_;
256 } 263 }
257 264
258 // The direction of a fragment is the CSS direction to resolve logical
259 // properties, not the resolved bidi direction.
260 text_builder.SetDirection(style->direction())
261 .SetInlineSize(line_item_chunk.inline_size)
262 .SetInlineOverflow(line_item_chunk.inline_size)
263 .SetBlockSize(height)
264 .SetBlockOverflow(height);
265 RefPtr<NGPhysicalTextFragment> text_fragment = text_builder.ToTextFragment( 265 RefPtr<NGPhysicalTextFragment> text_fragment = text_builder.ToTextFragment(
266 line_item_chunk.index, line_item_chunk.start_offset, 266 line_item_chunk.index, line_item_chunk.start_offset,
267 line_item_chunk.end_offset); 267 line_item_chunk.end_offset);
268 fragments_.push_back(std::move(text_fragment)); 268 fragments_.push_back(std::move(text_fragment));
269 269
270 NGLogicalOffset logical_offset( 270 NGLogicalOffset logical_offset(
271 line_box_data.inline_size + current_opportunity_.InlineStartOffset() - 271 line_box_data.inline_size + current_opportunity_.InlineStartOffset() -
272 ConstraintSpace().BfcOffset().inline_offset, 272 ConstraintSpace().BfcOffset().inline_offset,
273 top); 273 top);
274 offsets_.push_back(logical_offset); 274 offsets_.push_back(logical_offset);
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
345 HashSet<const SimpleFontData*> fallback_fonts; 345 HashSet<const SimpleFontData*> fallback_fonts;
346 item.GetFallbackFonts(&fallback_fonts, line_item_chunk.start_offset, 346 item.GetFallbackFonts(&fallback_fonts, line_item_chunk.start_offset,
347 line_item_chunk.end_offset); 347 line_item_chunk.end_offset);
348 for (const auto& fallback_font : fallback_fonts) { 348 for (const auto& fallback_font : fallback_fonts) {
349 InlineItemMetrics fallback_font_metrics(fallback_font->getFontMetrics(), 349 InlineItemMetrics fallback_font_metrics(fallback_font->getFontMetrics(),
350 baseline_type_); 350 baseline_type_);
351 line_box_data->UpdateMaxAscentAndDescent(fallback_font_metrics); 351 line_box_data->UpdateMaxAscentAndDescent(fallback_font_metrics);
352 } 352 }
353 } 353 }
354 354
355 LayoutUnit NGLineBuilder::PlaceAtomicInline(const NGLayoutInlineItem& item,
356 LayoutUnit estimated_baseline,
357 LineBoxData* line_box_data,
358 NGFragmentBuilder* text_builder) {
359 LayoutObject* layout_object = item.GetLayoutObject();
360 DCHECK(layout_object && layout_object->isAtomicInlineLevel());
361 const NGLayoutResult* layout_result = item.GetLayoutResult();
362 DCHECK(layout_result);
363 RefPtr<NGPhysicalFragment> fragment = layout_result->PhysicalFragment();
364 bool is_horizontal_writing_mode =
365 IsHorizontalWritingMode(ConstraintSpace().WritingMode());
366 LayoutUnit height;
367 // TODO(kojii): Try to eliminate the text fragment and use the |fragment|
368 // directly. Currently |CopyFragmentDataToLayoutBlockFlow| requires a text
369 // fragment.
370 // TODO(kojii): Margin and border in block progression not implemented yet.
371 if (is_horizontal_writing_mode) {
372 height = fragment->Height();
373 text_builder->SetInlineSize(fragment->Width())
374 .SetInlineOverflow(fragment->WidthOverflow())
375 .SetBlockSize(height)
376 .SetBlockOverflow(fragment->HeightOverflow());
377 } else {
378 height = fragment->Width();
379 text_builder->SetInlineSize(fragment->Height())
380 .SetInlineOverflow(fragment->HeightOverflow())
381 .SetBlockSize(height)
382 .SetBlockOverflow(fragment->WidthOverflow());
383 }
384
385 // TODO(kojii): Add baseline position to NGPhysicalFragment.
386 LayoutBox* box = toLayoutBox(layout_object);
387 LineDirectionMode line_direction_mode =
388 is_horizontal_writing_mode ? LineDirectionMode::HorizontalLine
389 : LineDirectionMode::VerticalLine;
390 bool is_first_line = line_box_data_list_.size() == 1;
391 int baseline_offset =
392 box->baselinePosition(baseline_type_, is_first_line, line_direction_mode);
393 LayoutUnit top = estimated_baseline - baseline_offset;
394
395 line_box_data->max_ascent_and_leading =
396 std::max<float>(baseline_offset, line_box_data->max_ascent_and_leading);
397 line_box_data->max_descent_and_leading = std::max<float>(
398 height - baseline_offset, line_box_data->max_descent_and_leading);
399
400 return top;
401 }
402
355 void NGLineBuilder::FindNextLayoutOpportunity() { 403 void NGLineBuilder::FindNextLayoutOpportunity() {
356 NGLogicalOffset iter_offset = constraint_space_->BfcOffset(); 404 NGLogicalOffset iter_offset = constraint_space_->BfcOffset();
357 iter_offset.block_offset += content_size_; 405 iter_offset.block_offset += content_size_;
358 auto* iter = constraint_space_->LayoutOpportunityIterator(iter_offset); 406 auto* iter = constraint_space_->LayoutOpportunityIterator(iter_offset);
359 NGLayoutOpportunity opportunity = iter->Next(); 407 NGLayoutOpportunity opportunity = iter->Next();
360 if (!opportunity.IsEmpty()) 408 if (!opportunity.IsEmpty())
361 current_opportunity_ = opportunity; 409 current_opportunity_ = opportunity;
362 } 410 }
363 411
364 RefPtr<NGLayoutResult> NGLineBuilder::CreateFragments() { 412 RefPtr<NGLayoutResult> NGLineBuilder::CreateFragments() {
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
410 if (layout_object->isText()) { 458 if (layout_object->isText()) {
411 unsigned text_offset = text_offsets[text_fragment->ItemIndex()]; 459 unsigned text_offset = text_offsets[text_fragment->ItemIndex()];
412 run = new BidiRun(text_fragment->StartOffset() - text_offset, 460 run = new BidiRun(text_fragment->StartOffset() - text_offset,
413 text_fragment->EndOffset() - text_offset, 461 text_fragment->EndOffset() - text_offset,
414 item.BidiLevel(), LineLayoutItem(layout_object)); 462 item.BidiLevel(), LineLayoutItem(layout_object));
415 layout_object->clearNeedsLayout(); 463 layout_object->clearNeedsLayout();
416 } else { 464 } else {
417 DCHECK(layout_object->isAtomicInlineLevel()); 465 DCHECK(layout_object->isAtomicInlineLevel());
418 run = 466 run =
419 new BidiRun(0, 1, item.BidiLevel(), LineLayoutItem(layout_object)); 467 new BidiRun(0, 1, item.BidiLevel(), LineLayoutItem(layout_object));
420 // TODO(kojii): Temporarily clearNeedsLayout() for not to assert.
421 layout_object->clearNeedsLayout();
422 } 468 }
423 bidi_runs.addRun(run); 469 bidi_runs.addRun(run);
424 fragments_for_bidi_runs.push_back(text_fragment); 470 fragments_for_bidi_runs.push_back(text_fragment);
425 } 471 }
426 // TODO(kojii): bidi needs to find the logical last run. 472 // TODO(kojii): bidi needs to find the logical last run.
427 bidi_runs.setLogicallyLastRun(bidi_runs.lastRun()); 473 bidi_runs.setLogicallyLastRun(bidi_runs.lastRun());
428 474
429 // Create a RootInlineBox from BidiRunList. InlineBoxes created for the 475 // Create a RootInlineBox from BidiRunList. InlineBoxes created for the
430 // RootInlineBox are set to Bidirun::m_box. 476 // RootInlineBox are set to Bidirun::m_box.
431 line_info.setEmpty(false); 477 line_info.setEmpty(false);
432 // TODO(kojii): Implement setFirstLine, LastLine, etc. 478 // TODO(kojii): Implement setFirstLine, LastLine, etc.
433 RootInlineBox* line_box = block->constructLine(bidi_runs, line_info); 479 RootInlineBox* line_box = block->constructLine(bidi_runs, line_info);
434 480
435 // Copy fragments data to InlineBoxes. 481 // Copy fragments data to InlineBoxes.
436 DCHECK_EQ(fragments_for_bidi_runs.size(), bidi_runs.runCount()); 482 DCHECK_EQ(fragments_for_bidi_runs.size(), bidi_runs.runCount());
437 BidiRun* run = bidi_runs.firstRun(); 483 BidiRun* run = bidi_runs.firstRun();
438 for (auto* physical_fragment : fragments_for_bidi_runs) { 484 for (auto* physical_fragment : fragments_for_bidi_runs) {
439 DCHECK(run); 485 DCHECK(run);
440 NGTextFragment fragment(ConstraintSpace().WritingMode(), 486 NGTextFragment fragment(ConstraintSpace().WritingMode(),
441 toNGPhysicalTextFragment(physical_fragment)); 487 toNGPhysicalTextFragment(physical_fragment));
442 InlineBox* inline_box = run->m_box; 488 InlineBox* inline_box = run->m_box;
443 inline_box->setLogicalWidth(fragment.InlineSize()); 489 inline_box->setLogicalWidth(fragment.InlineSize());
444 inline_box->setLogicalLeft(fragment.InlineOffset()); 490 inline_box->setLogicalLeft(fragment.InlineOffset());
445 inline_box->setLogicalTop(fragment.BlockOffset()); 491 inline_box->setLogicalTop(fragment.BlockOffset());
492 if (inline_box->getLineLayoutItem().isBox()) {
493 LineLayoutBox box(inline_box->getLineLayoutItem());
494 box.setLocation(inline_box->location());
495 }
446 run = run->next(); 496 run = run->next();
447 } 497 }
448 DCHECK(!run); 498 DCHECK(!run);
449 499
450 // Copy LineBoxData to RootInlineBox. 500 // Copy LineBoxData to RootInlineBox.
451 line_box->setLogicalWidth(line_box_data.inline_size); 501 line_box->setLogicalWidth(line_box_data.inline_size);
502 line_box->setLogicalTop(line_box_data.top_with_leading);
452 LayoutUnit baseline_position = 503 LayoutUnit baseline_position =
453 line_box_data.top_with_leading + 504 line_box_data.top_with_leading +
454 LayoutUnit(line_box_data.max_ascent_and_leading); 505 LayoutUnit(line_box_data.max_ascent_and_leading);
455 line_box->setLineTopBottomPositions( 506 line_box->setLineTopBottomPositions(
456 baseline_position - LayoutUnit(line_box_data.max_ascent), 507 baseline_position - LayoutUnit(line_box_data.max_ascent),
457 baseline_position + LayoutUnit(line_box_data.max_descent), 508 baseline_position + LayoutUnit(line_box_data.max_descent),
458 line_box_data.top_with_leading, 509 line_box_data.top_with_leading,
459 baseline_position + LayoutUnit(line_box_data.max_descent_and_leading)); 510 baseline_position + LayoutUnit(line_box_data.max_descent_and_leading));
460 511
461 bidi_runs.deleteRuns(); 512 bidi_runs.deleteRuns();
462 fragments_for_bidi_runs.clear(); 513 fragments_for_bidi_runs.clear();
463 } 514 }
464 } 515 }
465 } // namespace blink 516 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698