Commit 058d7ff4 authored by Kent Tamura's avatar Kent Tamura Committed by Commit Bot

RubyNG: Expand line gap if ruby text exceeds line-height.

If a line contains ruby text and it overflows line-height,
 - If it overflows upwards, adjust block offset of the line in
   NGInlineLayoutAlgorithm
 - If it overflows downwards, pass the overflow amount via
   NGLayoutResult, and NGBlockLayoutAlgorithm::ComputeInflowPosition()
   refers to it.

We don't consume spaces under the previous line and spaces over the
next line yet.

Bug: 1069817
Change-Id: Idd78eae27c916ac9d4b5de528f73acbaaa26a285
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2210192
Commit-Queue: Kent Tamura <tkent@chromium.org>
Reviewed-by: default avatarKoji Ishii <kojii@chromium.org>
Reviewed-by: default avatarYoshifumi Inoue <yosin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#772132}
parent adca6337
...@@ -124,6 +124,7 @@ NGInlineBoxState* NGInlineLayoutStateStack::OnBeginPlaceItems( ...@@ -124,6 +124,7 @@ NGInlineBoxState* NGInlineLayoutStateStack::OnBeginPlaceItems(
box.metrics = box.text_metrics; box.metrics = box.text_metrics;
else else
box.ResetTextMetrics(); box.ResetTextMetrics();
box.has_annotation_overflow = false;
if (box.has_start_edge) { if (box.has_start_edge) {
// Existing box states are wrapped before they were closed, and hence // Existing box states are wrapped before they were closed, and hence
// they do not have start edges, unless 'box-decoration-break: clone'. // they do not have start edges, unless 'box-decoration-break: clone'.
...@@ -235,6 +236,8 @@ void NGInlineLayoutStateStack::EndBoxState(NGInlineBoxState* box, ...@@ -235,6 +236,8 @@ void NGInlineLayoutStateStack::EndBoxState(NGInlineBoxState* box,
NGInlineBoxState& parent_box = *std::prev(box); NGInlineBoxState& parent_box = *std::prev(box);
// Propagate necessary data back to the parent box. // Propagate necessary data back to the parent box.
parent_box.has_annotation_overflow =
parent_box.has_annotation_overflow || box->has_annotation_overflow;
// Unite the metrics to the parent box. // Unite the metrics to the parent box.
if (position_pending == kPositionNotPending) if (position_pending == kPositionNotPending)
...@@ -895,6 +898,7 @@ void NGInlineBoxState::CheckSame(const NGInlineBoxState& other) const { ...@@ -895,6 +898,7 @@ void NGInlineBoxState::CheckSame(const NGInlineBoxState& other) const {
DCHECK_EQ(metrics, other.metrics); DCHECK_EQ(metrics, other.metrics);
DCHECK_EQ(text_metrics, other.text_metrics); DCHECK_EQ(text_metrics, other.text_metrics);
DCHECK_EQ(has_annotation_overflow, other.has_annotation_overflow);
DCHECK_EQ(text_top, other.text_top); DCHECK_EQ(text_top, other.text_top);
DCHECK_EQ(text_height, other.text_height); DCHECK_EQ(text_height, other.text_height);
if (!text_metrics.IsEmpty()) { if (!text_metrics.IsEmpty()) {
......
...@@ -50,6 +50,9 @@ struct NGInlineBoxState { ...@@ -50,6 +50,9 @@ struct NGInlineBoxState {
// by the 'line-height' property. // by the 'line-height' property.
NGLineHeightMetrics text_metrics; NGLineHeightMetrics text_metrics;
// True if any boxes in the current line have non-zero annotation overflow.
bool has_annotation_overflow = false;
// The distance between the text-top and the baseline for this box. The // The distance between the text-top and the baseline for this box. The
// text-top does not include leadings. // text-top does not include leadings.
LayoutUnit text_top; LayoutUnit text_top;
......
...@@ -380,6 +380,13 @@ void NGInlineLayoutAlgorithm::CreateLine( ...@@ -380,6 +380,13 @@ void NGInlineLayoutAlgorithm::CreateLine(
exclusion_space); exclusion_space);
} }
NGLineHeightMetrics annotation_metrics = NGLineHeightMetrics::Zero();
if (box_states_->LineBoxState().has_annotation_overflow &&
!RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()) {
annotation_metrics = ComputeAnnotationOverflow(
line_box_metrics, -line_box_metrics.ascent, line_info->LineStyle());
}
// Create box fragments if needed. After this point forward, |line_box_| is a // Create box fragments if needed. After this point forward, |line_box_| is a
// tree structure. // tree structure.
// The individual children don't move position within the |line_box_|, rather // The individual children don't move position within the |line_box_|, rather
...@@ -413,12 +420,67 @@ void NGInlineLayoutAlgorithm::CreateLine( ...@@ -413,12 +420,67 @@ void NGInlineLayoutAlgorithm::CreateLine(
// the line box to the line top. // the line box to the line top.
line_box_.MoveInBlockDirection(line_box_metrics.ascent); line_box_.MoveInBlockDirection(line_box_metrics.ascent);
if (box_states_->LineBoxState().has_annotation_overflow &&
RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()) {
annotation_metrics = ComputeAnnotationOverflow(
line_box_metrics, LayoutUnit(), line_info->LineStyle());
}
if (line_info->UseFirstLineStyle()) if (line_info->UseFirstLineStyle())
container_builder_.SetStyleVariant(NGStyleVariant::kFirstLine); container_builder_.SetStyleVariant(NGStyleVariant::kFirstLine);
container_builder_.SetBaseDirection(line_info->BaseDirection()); container_builder_.SetBaseDirection(line_info->BaseDirection());
container_builder_.SetInlineSize(inline_size); container_builder_.SetInlineSize(inline_size);
container_builder_.SetMetrics(line_box_metrics); container_builder_.SetMetrics(line_box_metrics);
container_builder_.SetBfcBlockOffset(line_info->BfcOffset().block_offset); container_builder_.SetBfcBlockOffset(line_info->BfcOffset().block_offset +
annotation_metrics.ascent);
if (annotation_metrics.descent > LayoutUnit())
container_builder_.SetAnnotationOverflow(annotation_metrics.descent);
}
NGLineHeightMetrics NGInlineLayoutAlgorithm::ComputeAnnotationOverflow(
const NGLineHeightMetrics& line_box_metrics,
LayoutUnit line_block_start,
const ComputedStyle& line_style) {
DCHECK(box_states_->LineBoxState().has_annotation_overflow);
DCHECK(RuntimeEnabledFeatures::LayoutNGRubyEnabled());
LayoutUnit annotatin_block_start = line_block_start;
const LayoutUnit line_block_end =
line_block_start + line_box_metrics.LineHeight();
LayoutUnit annotation_block_end = line_block_end;
for (const auto& item : line_box_) {
if (!item.HasInFlowFragment())
continue;
if (!item.layout_result)
continue;
const auto* fragment = item.PhysicalFragment();
const scoped_refptr<NGFragmentItem> fragment_item = item.fragment_item;
LayoutUnit block_end;
if (fragment) {
block_end = item.rect.offset.block_offset +
fragment->Size()
.ConvertToLogical(line_style.GetWritingMode())
.block_size;
} else if (fragment_item) {
block_end = item.rect.offset.block_offset +
fragment_item->Size()
.ConvertToLogical(line_style.GetWritingMode())
.block_size;
} else {
continue;
}
LayoutUnit overflow = item.layout_result->AnnotationOverflow();
if (overflow < LayoutUnit()) {
annotatin_block_start = std::min(
annotatin_block_start, item.rect.offset.block_offset + overflow);
} else if (overflow > LayoutUnit()) {
annotation_block_end =
std::max(annotation_block_end, block_end + overflow);
}
}
return NGLineHeightMetrics(
std::max(line_block_start - annotatin_block_start, LayoutUnit()),
std::max(annotation_block_end - line_block_end, LayoutUnit()));
} }
void NGInlineLayoutAlgorithm::PlaceControlItem(const NGInlineItem& item, void NGInlineLayoutAlgorithm::PlaceControlItem(const NGInlineItem& item,
...@@ -520,8 +582,12 @@ void NGInlineLayoutAlgorithm::PlaceLayoutResult(NGInlineItemResult* item_result, ...@@ -520,8 +582,12 @@ void NGInlineLayoutAlgorithm::PlaceLayoutResult(NGInlineItemResult* item_result,
To<NGPhysicalBoxFragment>( To<NGPhysicalBoxFragment>(
item_result->layout_result->PhysicalFragment())) item_result->layout_result->PhysicalFragment()))
.BaselineMetrics(item_result->margins, baseline_type_); .BaselineMetrics(item_result->margins, baseline_type_);
if (box) if (box) {
box->metrics.Unite(metrics); box->metrics.Unite(metrics);
box->has_annotation_overflow =
box->has_annotation_overflow ||
item_result->layout_result->AnnotationOverflow() != LayoutUnit();
}
LayoutUnit line_top = item_result->margins.line_over - metrics.ascent; LayoutUnit line_top = item_result->margins.line_over - metrics.ascent;
line_box_.AddChild(std::move(item_result->layout_result), line_box_.AddChild(std::move(item_result->layout_result),
......
...@@ -111,6 +111,11 @@ class CORE_EXPORT NGInlineLayoutAlgorithm final ...@@ -111,6 +111,11 @@ class CORE_EXPORT NGInlineLayoutAlgorithm final
const NGExclusionSpace&, const NGExclusionSpace&,
LayoutUnit line_height); LayoutUnit line_height);
NGLineHeightMetrics ComputeAnnotationOverflow(
const NGLineHeightMetrics& line_box_metrics,
LayoutUnit line_block_start,
const ComputedStyle& line_style);
NGLogicalLineItems line_box_; NGLogicalLineItems line_box_;
NGInlineLayoutStateStack* box_states_; NGInlineLayoutStateStack* box_states_;
NGInlineChildLayoutContext* context_; NGInlineChildLayoutContext* context_;
......
...@@ -2048,7 +2048,11 @@ NGPreviousInflowPosition NGBlockLayoutAlgorithm::ComputeInflowPosition( ...@@ -2048,7 +2048,11 @@ NGPreviousInflowPosition NGBlockLayoutAlgorithm::ComputeInflowPosition(
if (!container_builder_.BfcBlockOffset()) if (!container_builder_.BfcBlockOffset())
DCHECK_EQ(logical_block_offset, LayoutUnit()); DCHECK_EQ(logical_block_offset, LayoutUnit());
} else { } else {
logical_block_offset = logical_offset.block_offset + fragment.BlockSize(); // TODO(crbug.com/1069817): We should not add AnnotationOverflow
// unconditionally here. Instead, we should pass it to the next child
// layout.
logical_block_offset = logical_offset.block_offset + fragment.BlockSize() +
layout_result.AnnotationOverflow();
} }
NGMarginStrut margin_strut = layout_result.EndMarginStrut(); NGMarginStrut margin_strut = layout_result.EndMarginStrut();
......
...@@ -206,11 +206,6 @@ class CORE_EXPORT NGBoxFragmentBuilder final ...@@ -206,11 +206,6 @@ class CORE_EXPORT NGBoxFragmentBuilder final
lines_until_clamp_ = value; lines_until_clamp_ = value;
} }
// See NGLayoutResult::AnnotationOverflow().
void SetAnnotationOverflow(LayoutUnit overflow) {
annotation_overflow_ = overflow;
}
void SetEarlyBreak(scoped_refptr<const NGEarlyBreak> breakpoint, void SetEarlyBreak(scoped_refptr<const NGEarlyBreak> breakpoint,
NGBreakAppeal appeal) { NGBreakAppeal appeal) {
early_break_ = breakpoint; early_break_ = breakpoint;
...@@ -373,9 +368,6 @@ class CORE_EXPORT NGBoxFragmentBuilder final ...@@ -373,9 +368,6 @@ class CORE_EXPORT NGBoxFragmentBuilder final
scoped_refptr<SerializedScriptValue> custom_layout_data_; scoped_refptr<SerializedScriptValue> custom_layout_data_;
base::Optional<int> lines_until_clamp_; base::Optional<int> lines_until_clamp_;
// See NGLayoutResult::AnnotationOverflow().
LayoutUnit annotation_overflow_;
friend class NGPhysicalBoxFragment; friend class NGPhysicalBoxFragment;
friend class NGLayoutResult; friend class NGLayoutResult;
}; };
......
...@@ -173,6 +173,11 @@ class CORE_EXPORT NGContainerFragmentBuilder : public NGFragmentBuilder { ...@@ -173,6 +173,11 @@ class CORE_EXPORT NGContainerFragmentBuilder : public NGFragmentBuilder {
is_fragmentation_context_root_ = true; is_fragmentation_context_root_ = true;
} }
// See NGLayoutResult::AnnotationOverflow().
void SetAnnotationOverflow(LayoutUnit overflow) {
annotation_overflow_ = overflow;
}
const NGConstraintSpace* ConstraintSpace() const { return space_; } const NGConstraintSpace* ConstraintSpace() const { return space_; }
#if DCHECK_IS_ON() #if DCHECK_IS_ON()
...@@ -225,6 +230,9 @@ class CORE_EXPORT NGContainerFragmentBuilder : public NGFragmentBuilder { ...@@ -225,6 +230,9 @@ class CORE_EXPORT NGContainerFragmentBuilder : public NGFragmentBuilder {
scoped_refptr<const NGEarlyBreak> early_break_; scoped_refptr<const NGEarlyBreak> early_break_;
NGBreakAppeal break_appeal_ = kBreakAppealLastResort; NGBreakAppeal break_appeal_ = kBreakAppealLastResort;
// See NGLayoutResult::AnnotationOverflow().
LayoutUnit annotation_overflow_;
NGAdjoiningObjectTypes adjoining_object_types_ = kAdjoiningNone; NGAdjoiningObjectTypes adjoining_object_types_ = kAdjoiningNone;
bool has_adjoining_object_descendants_ = false; bool has_adjoining_object_descendants_ = false;
......
...@@ -176,6 +176,8 @@ NGLayoutResult::NGLayoutResult( ...@@ -176,6 +176,8 @@ NGLayoutResult::NGLayoutResult(
if (builder->end_margin_strut_ != NGMarginStrut()) if (builder->end_margin_strut_ != NGMarginStrut())
EnsureRareData()->end_margin_strut = builder->end_margin_strut_; EnsureRareData()->end_margin_strut = builder->end_margin_strut_;
if (builder->annotation_overflow_ > LayoutUnit())
EnsureRareData()->annotation_overflow = builder->annotation_overflow_;
if (builder->unpositioned_list_marker_) { if (builder->unpositioned_list_marker_) {
EnsureRareData()->unpositioned_list_marker = EnsureRareData()->unpositioned_list_marker =
builder->unpositioned_list_marker_; builder->unpositioned_list_marker_;
......
...@@ -69,9 +69,10 @@ class CORE_EXPORT NGLayoutResult : public RefCounted<NGLayoutResult> { ...@@ -69,9 +69,10 @@ class CORE_EXPORT NGLayoutResult : public RefCounted<NGLayoutResult> {
} }
// How much an annotation box overflow from this box. // How much an annotation box overflow from this box.
// This is for LayoutNGRubyRun. // This is for LayoutNGRubyRun and line boxes.
// 0 : No overflow // 0 : No overflow
// -N : Overflowing by N px at block-start side // -N : Overflowing by N px at block-start side
// This happens only for LayoutRubyRun.
// N : Overflowing by N px at block-end side // N : Overflowing by N px at block-end side
LayoutUnit AnnotationOverflow() const { LayoutUnit AnnotationOverflow() const {
return HasRareData() ? rare_data_->annotation_overflow : LayoutUnit(); return HasRareData() ? rare_data_->annotation_overflow : LayoutUnit();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment