Commit e5fb002b authored by Kent Tamura's avatar Kent Tamura Committed by Commit Bot

RubyNG: Move ruby-related functions to ng_ruby_utils.{cc,h}

Moves the following functions:
 - NGInlineLayoutAlgorithm::ComputeAnnotationOverflow()
 - LastLineTextLogicalBottom() in ng_block_layout_algorithm.cc
 - FirstLineTextLogicalTop()  in ng_block_layout_algorithm.cc

This CL has no behavior changes.

Bug: 1069817
Change-Id: Ie59211a2644f81a4e43bcde5f7010f8765b2955a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2249431
Commit-Queue: Koji Ishii <kojii@chromium.org>
Auto-Submit: Kent Tamura <tkent@chromium.org>
Reviewed-by: default avatarKoji Ishii <kojii@chromium.org>
Cr-Commit-Position: refs/heads/master@{#779327}
parent 82c7f7d7
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include "third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.h" #include "third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_line_truncator.h" #include "third_party/blink/renderer/core/layout/ng/inline/ng_line_truncator.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_physical_text_fragment.h" #include "third_party/blink/renderer/core/layout/ng/inline/ng_physical_text_fragment.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_ruby_utils.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_text_fragment_builder.h" #include "third_party/blink/renderer/core/layout/ng/inline/ng_text_fragment_builder.h"
#include "third_party/blink/renderer/core/layout/ng/list/layout_ng_outside_list_marker.h" #include "third_party/blink/renderer/core/layout/ng/list/layout_ng_outside_list_marker.h"
#include "third_party/blink/renderer/core/layout/ng/list/ng_unpositioned_list_marker.h" #include "third_party/blink/renderer/core/layout/ng/list/ng_unpositioned_list_marker.h"
...@@ -386,8 +387,9 @@ void NGInlineLayoutAlgorithm::CreateLine( ...@@ -386,8 +387,9 @@ void NGInlineLayoutAlgorithm::CreateLine(
NGLineHeightMetrics annotation_metrics = NGLineHeightMetrics::Zero(); NGLineHeightMetrics annotation_metrics = NGLineHeightMetrics::Zero();
if (Node().HasRuby() && if (Node().HasRuby() &&
!RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()) { !RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()) {
annotation_metrics = ComputeAnnotationOverflow( annotation_metrics = ComputeAnnotationOverflow(line_box_, line_box_metrics,
line_box_metrics, -line_box_metrics.ascent, line_info->LineStyle()); -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
...@@ -421,7 +423,7 @@ void NGInlineLayoutAlgorithm::CreateLine( ...@@ -421,7 +423,7 @@ void NGInlineLayoutAlgorithm::CreateLine(
if (Node().HasRuby() && if (Node().HasRuby() &&
RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()) { RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()) {
annotation_metrics = ComputeAnnotationOverflow( annotation_metrics = ComputeAnnotationOverflow(
line_box_metrics, LayoutUnit(), line_info->LineStyle()); line_box_, line_box_metrics, LayoutUnit(), line_info->LineStyle());
} }
LayoutUnit annotation_block_start; LayoutUnit annotation_block_start;
LayoutUnit annotation_block_end; LayoutUnit annotation_block_end;
...@@ -454,96 +456,6 @@ void NGInlineLayoutAlgorithm::CreateLine( ...@@ -454,96 +456,6 @@ void NGInlineLayoutAlgorithm::CreateLine(
container_builder_.SetBlockEndAnnotationSpace(-annotation_block_end); container_builder_.SetBlockEndAnnotationSpace(-annotation_block_end);
} }
// Return value:
// .ascent > 0: The amount of annotation overflow at the line-top side
// .ascent < 0: The amount of annotation space which the next line at the
// line-top side can consume.
// .descent > 0: The amount of annotation overflow at the line-bottom side.
// .descent < 0: The amount of annotation space which the next line at the
// line-bottom side can consume.
NGLineHeightMetrics NGInlineLayoutAlgorithm::ComputeAnnotationOverflow(
const NGLineHeightMetrics& line_box_metrics,
LayoutUnit line_block_start,
const ComputedStyle& line_style) {
DCHECK(Node().HasRuby());
DCHECK(RuntimeEnabledFeatures::LayoutNGRubyEnabled());
// Min/max position of content without line-height.
LayoutUnit content_block_start = line_block_start + line_box_metrics.ascent;
LayoutUnit content_block_end = content_block_start;
// Min/max position of annotations.
LayoutUnit annotation_block_start = content_block_start;
LayoutUnit annotation_block_end = content_block_start;
const LayoutUnit line_block_end =
line_block_start + line_box_metrics.LineHeight();
bool has_over_emphasis = false;
bool has_under_emphasis = false;
for (const NGLogicalLineItem& item : line_box_) {
if (item.HasInFlowFragment()) {
if (!item.IsControl()) {
content_block_start = std::min(content_block_start, item.BlockOffset());
content_block_end = std::max(content_block_end, item.BlockEndOffset());
}
if (const auto* style = item.Style()) {
if (style->GetTextEmphasisMark() != TextEmphasisMark::kNone) {
if (style->GetTextEmphasisLineLogicalSide() == LineLogicalSide::kOver)
has_over_emphasis = true;
else
has_under_emphasis = true;
}
}
}
// Accumulate |AnnotationOverflow| from ruby runs. All ruby run items have
// |layout_result|.
const NGLayoutResult* layout_result = item.layout_result.get();
if (!layout_result)
continue;
LayoutUnit overflow = layout_result->AnnotationOverflow();
if (IsFlippedLinesWritingMode(line_style.GetWritingMode()))
overflow = -overflow;
if (overflow < LayoutUnit()) {
annotation_block_start = std::min(
annotation_block_start, item.rect.offset.block_offset + overflow);
} else if (overflow > LayoutUnit()) {
const LayoutUnit block_end =
item.rect.offset.block_offset +
layout_result->PhysicalFragment()
.Size()
.ConvertToLogical(line_style.GetWritingMode())
.block_size;
annotation_block_end =
std::max(annotation_block_end, block_end + overflow);
}
}
// Probably this is an empty line. We should secure font-size space.
const LayoutUnit font_size(line_style.ComputedFontSize());
if (content_block_end - content_block_start < font_size) {
LayoutUnit half_leading = (line_box_metrics.LineHeight() - font_size) / 2;
half_leading = half_leading.ClampNegativeToZero();
content_block_start = line_block_start + half_leading;
content_block_end = line_block_end - half_leading;
}
// Don't provide annotation space if text-emphasis exists.
// TODO(layout-dev): If the text-emphasis is in
// [line_block_start, line_block_end], this line can provide annotation space.
if (has_over_emphasis)
content_block_start = line_block_start;
if (has_under_emphasis)
content_block_end = line_block_end;
const LayoutUnit content_or_annotation_block_start =
std::min(content_block_start, annotation_block_start);
const LayoutUnit content_or_annotation_block_end =
std::max(content_block_end, annotation_block_end);
return NGLineHeightMetrics(
line_block_start - content_or_annotation_block_start,
content_or_annotation_block_end - line_block_end);
}
void NGInlineLayoutAlgorithm::PlaceControlItem(const NGInlineItem& item, void NGInlineLayoutAlgorithm::PlaceControlItem(const NGInlineItem& item,
const NGLineInfo& line_info, const NGLineInfo& line_info,
NGInlineItemResult* item_result, NGInlineItemResult* item_result,
......
...@@ -113,11 +113,6 @@ class CORE_EXPORT NGInlineLayoutAlgorithm final ...@@ -113,11 +113,6 @@ 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_;
......
...@@ -4,12 +4,87 @@ ...@@ -4,12 +4,87 @@
#include "third_party/blink/renderer/core/layout/ng/inline/ng_ruby_utils.h" #include "third_party/blink/renderer/core/layout/ng/inline/ng_ruby_utils.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_result.h" #include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_result.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_logical_line_item.h"
#include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h"
#include "third_party/blink/renderer/core/layout/ng/ng_physical_container_fragment.h" #include "third_party/blink/renderer/core/layout/ng/ng_physical_container_fragment.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h" #include "third_party/blink/renderer/platform/runtime_enabled_features.h"
namespace blink { namespace blink {
// TODO(layout-dev): Using ScrollableOverflow() is same as legacy
// LayoutRubyRun. However its result is not good with some fonts/platforms.
// See crbug.com/1082087.
LayoutUnit LastLineTextLogicalBottom(const NGPhysicalBoxFragment& container,
LayoutUnit default_value) {
const ComputedStyle& container_style = container.Style();
if (RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()) {
if (!container.Items())
return default_value;
NGInlineCursor cursor(*container.Items());
cursor.MoveToLastLine();
const auto* line_item = cursor.CurrentItem();
if (!line_item)
return default_value;
DCHECK_EQ(line_item->Type(), NGFragmentItem::kLine);
DCHECK(line_item->LineBoxFragment());
PhysicalRect line_rect =
line_item->LineBoxFragment()->ScrollableOverflowForLine(
container, container_style, *line_item, cursor);
return container.ConvertChildToLogical(line_rect).BlockEndOffset();
}
const NGPhysicalLineBoxFragment* last_line = nullptr;
PhysicalOffset last_line_offset;
for (const auto& child_link : container.PostLayoutChildren()) {
if (const auto* maybe_line =
DynamicTo<NGPhysicalLineBoxFragment>(*child_link)) {
last_line = maybe_line;
last_line_offset = child_link.offset;
}
}
if (!last_line)
return default_value;
PhysicalRect line_rect =
last_line->ScrollableOverflow(container, container_style);
line_rect.Move(last_line_offset);
return container.ConvertChildToLogical(line_rect).BlockEndOffset();
}
// TODO(layout-dev): Using ScrollableOverflow() is same as legacy
// LayoutRubyRun. However its result is not good with some fonts/platforms.
// See crbug.com/1082087.
LayoutUnit FirstLineTextLogicalTop(const NGPhysicalBoxFragment& container,
LayoutUnit default_value) {
const ComputedStyle& container_style = container.Style();
if (RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()) {
if (!container.Items())
return default_value;
NGInlineCursor cursor(*container.Items());
cursor.MoveToFirstLine();
const auto* line_item = cursor.CurrentItem();
if (!line_item)
return default_value;
DCHECK_EQ(line_item->Type(), NGFragmentItem::kLine);
DCHECK(line_item->LineBoxFragment());
PhysicalRect line_rect =
line_item->LineBoxFragment()->ScrollableOverflowForLine(
container, container_style, *line_item, cursor);
return container.ConvertChildToLogical(line_rect).offset.block_offset;
}
for (const auto& child_link : container.PostLayoutChildren()) {
if (const auto* line = DynamicTo<NGPhysicalLineBoxFragment>(*child_link)) {
PhysicalRect line_rect =
line->ScrollableOverflow(container, container_style);
line_rect.Move(child_link.offset);
return container.ConvertChildToLogical(line_rect).offset.block_offset;
}
}
return default_value;
}
// See LayoutRubyRun::GetOverhang(). // See LayoutRubyRun::GetOverhang().
NGAnnotationOverhang GetOverhang(const NGInlineItemResult& item) { NGAnnotationOverhang GetOverhang(const NGInlineItemResult& item) {
DCHECK(RuntimeEnabledFeatures::LayoutNGRubyEnabled()); DCHECK(RuntimeEnabledFeatures::LayoutNGRubyEnabled());
...@@ -142,4 +217,87 @@ LayoutUnit CommitPendingEndOverhang(NGLineInfo* line_info) { ...@@ -142,4 +217,87 @@ LayoutUnit CommitPendingEndOverhang(NGLineInfo* line_info) {
return end_overhang; return end_overhang;
} }
NGLineHeightMetrics ComputeAnnotationOverflow(
const NGLogicalLineItems& logical_line,
const NGLineHeightMetrics& line_box_metrics,
LayoutUnit line_block_start,
const ComputedStyle& line_style) {
DCHECK(RuntimeEnabledFeatures::LayoutNGRubyEnabled());
// Min/max position of content without line-height.
LayoutUnit content_block_start = line_block_start + line_box_metrics.ascent;
LayoutUnit content_block_end = content_block_start;
// Min/max position of annotations.
LayoutUnit annotation_block_start = content_block_start;
LayoutUnit annotation_block_end = content_block_start;
const LayoutUnit line_block_end =
line_block_start + line_box_metrics.LineHeight();
bool has_over_emphasis = false;
bool has_under_emphasis = false;
for (const NGLogicalLineItem& item : logical_line) {
if (item.HasInFlowFragment()) {
if (!item.IsControl()) {
content_block_start = std::min(content_block_start, item.BlockOffset());
content_block_end = std::max(content_block_end, item.BlockEndOffset());
}
if (const auto* style = item.Style()) {
if (style->GetTextEmphasisMark() != TextEmphasisMark::kNone) {
if (style->GetTextEmphasisLineLogicalSide() == LineLogicalSide::kOver)
has_over_emphasis = true;
else
has_under_emphasis = true;
}
}
}
// Accumulate |AnnotationOverflow| from ruby runs. All ruby run items have
// |layout_result|.
const NGLayoutResult* layout_result = item.layout_result.get();
if (!layout_result)
continue;
LayoutUnit overflow = layout_result->AnnotationOverflow();
if (IsFlippedLinesWritingMode(line_style.GetWritingMode()))
overflow = -overflow;
if (overflow < LayoutUnit()) {
annotation_block_start = std::min(
annotation_block_start, item.rect.offset.block_offset + overflow);
} else if (overflow > LayoutUnit()) {
const LayoutUnit block_end =
item.rect.offset.block_offset +
layout_result->PhysicalFragment()
.Size()
.ConvertToLogical(line_style.GetWritingMode())
.block_size;
annotation_block_end =
std::max(annotation_block_end, block_end + overflow);
}
}
// Probably this is an empty line. We should secure font-size space.
const LayoutUnit font_size(line_style.ComputedFontSize());
if (content_block_end - content_block_start < font_size) {
LayoutUnit half_leading = (line_box_metrics.LineHeight() - font_size) / 2;
half_leading = half_leading.ClampNegativeToZero();
content_block_start = line_block_start + half_leading;
content_block_end = line_block_end - half_leading;
}
// Don't provide annotation space if text-emphasis exists.
// TODO(layout-dev): If the text-emphasis is in
// [line_block_start, line_block_end], this line can provide annotation space.
if (has_over_emphasis)
content_block_start = line_block_start;
if (has_under_emphasis)
content_block_end = line_block_end;
const LayoutUnit content_or_annotation_block_start =
std::min(content_block_start, annotation_block_start);
const LayoutUnit content_or_annotation_block_end =
std::max(content_block_end, annotation_block_end);
return NGLineHeightMetrics(
line_block_start - content_or_annotation_block_start,
content_or_annotation_block_end - line_block_end);
}
} // namespace blink } // namespace blink
...@@ -9,8 +9,26 @@ ...@@ -9,8 +9,26 @@
namespace blink { namespace blink {
class ComputedStyle;
class NGLineInfo; class NGLineInfo;
class NGLogicalLineItems;
class NGPhysicalBoxFragment;
struct NGInlineItemResult; struct NGInlineItemResult;
struct NGLineHeightMetrics;
// Returns the logical bottom offset of the last line text, relative to
// |container| origin. This is used to decide ruby annotation box position.
//
// See NGBlockLayoutAlgorithm::LayoutRubyText().
LayoutUnit LastLineTextLogicalBottom(const NGPhysicalBoxFragment& container,
LayoutUnit default_value);
// Returns the logical top offset of the first line text, relative to
// |container| origin. This is used to decide ruby annotation box position.
//
// See NGBlockLayoutAlgorithm::LayoutRubyText().
LayoutUnit FirstLineTextLogicalTop(const NGPhysicalBoxFragment& container,
LayoutUnit default_value);
struct NGAnnotationOverhang { struct NGAnnotationOverhang {
LayoutUnit start; LayoutUnit start;
...@@ -37,6 +55,21 @@ bool CanApplyStartOverhang(const NGLineInfo& line_info, ...@@ -37,6 +55,21 @@ bool CanApplyStartOverhang(const NGLineInfo& line_info,
// in |line_info| // in |line_info|
LayoutUnit CommitPendingEndOverhang(NGLineInfo* line_info); LayoutUnit CommitPendingEndOverhang(NGLineInfo* line_info);
// Compute over/under annotation overflow/space for the specified line.
//
// Return value:
// .ascent > 0: The amount of annotation overflow at the line-top side
// .ascent < 0: The amount of annotation space which the next line at the
// line-top side can consume.
// .descent > 0: The amount of annotation overflow at the line-bottom side.
// .descent < 0: The amount of annotation space which the next line at the
// line-bottom side can consume.
NGLineHeightMetrics ComputeAnnotationOverflow(
const NGLogicalLineItems& logical_line,
const NGLineHeightMetrics& line_box_metrics,
LayoutUnit line_block_start,
const ComputedStyle& line_style);
} // namespace blink } // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_RUBY_UTILS_H_ #endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_RUBY_UTILS_H_
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.h" #include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.h" #include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_physical_line_box_fragment.h" #include "third_party/blink/renderer/core/layout/ng/inline/ng_physical_line_box_fragment.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_ruby_utils.h"
#include "third_party/blink/renderer/core/layout/ng/legacy_layout_tree_walking.h" #include "third_party/blink/renderer/core/layout/ng/legacy_layout_tree_walking.h"
#include "third_party/blink/renderer/core/layout/ng/list/ng_unpositioned_list_marker.h" #include "third_party/blink/renderer/core/layout/ng/list/ng_unpositioned_list_marker.h"
#include "third_party/blink/renderer/core/layout/ng/ng_block_child_iterator.h" #include "third_party/blink/renderer/core/layout/ng/ng_block_child_iterator.h"
...@@ -59,82 +60,6 @@ bool HasLineEvenIfEmpty(LayoutBox* box) { ...@@ -59,82 +60,6 @@ bool HasLineEvenIfEmpty(LayoutBox* box) {
return NGInlineNode(block_flow).HasLineEvenIfEmpty(); return NGInlineNode(block_flow).HasLineEvenIfEmpty();
} }
// Returns the logical bottom offset of the last line text, relative to
// |container| origin. This is used to decide ruby annotation box position.
//
// TODO(layout-dev): Using ScrollableOverflow() is same as legacy
// LayoutRubyRun. However its result is not good with some fonts/platforms.
LayoutUnit LastLineTextLogicalBottom(const NGPhysicalBoxFragment& container,
LayoutUnit default_value) {
const ComputedStyle& container_style = container.Style();
if (RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()) {
if (!container.Items())
return default_value;
NGInlineCursor cursor(*container.Items());
cursor.MoveToLastLine();
const auto* line_item = cursor.CurrentItem();
if (!line_item)
return default_value;
DCHECK_EQ(line_item->Type(), NGFragmentItem::kLine);
DCHECK(line_item->LineBoxFragment());
PhysicalRect line_rect =
line_item->LineBoxFragment()->ScrollableOverflowForLine(
container, container_style, *line_item, cursor);
return container.ConvertChildToLogical(line_rect).BlockEndOffset();
}
const NGPhysicalLineBoxFragment* last_line = nullptr;
PhysicalOffset last_line_offset;
for (const auto& child_link : container.PostLayoutChildren()) {
if (const auto* maybe_line =
DynamicTo<NGPhysicalLineBoxFragment>(*child_link)) {
last_line = maybe_line;
last_line_offset = child_link.offset;
}
}
if (!last_line)
return default_value;
PhysicalRect line_rect =
last_line->ScrollableOverflow(container, container_style);
line_rect.Move(last_line_offset);
return container.ConvertChildToLogical(line_rect).BlockEndOffset();
}
// Returns the logical top offset of the first line text, relative to
// |container| origin. This is used to decide ruby annotation box position.
//
// TODO(layout-dev): Using ScrollableOverflow() is same as legacy
// LayoutRubyRun. However its result is not good with some fonts/platforms.
LayoutUnit FirstLineTextLogicalTop(const NGPhysicalBoxFragment& container,
LayoutUnit default_value) {
const ComputedStyle& container_style = container.Style();
if (RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()) {
if (!container.Items())
return default_value;
NGInlineCursor cursor(*container.Items());
cursor.MoveToFirstLine();
const auto* line_item = cursor.CurrentItem();
if (!line_item)
return default_value;
DCHECK_EQ(line_item->Type(), NGFragmentItem::kLine);
DCHECK(line_item->LineBoxFragment());
PhysicalRect line_rect =
line_item->LineBoxFragment()->ScrollableOverflowForLine(
container, container_style, *line_item, cursor);
return container.ConvertChildToLogical(line_rect).offset.block_offset;
}
for (const auto& child_link : container.PostLayoutChildren()) {
if (const auto* line = DynamicTo<NGPhysicalLineBoxFragment>(*child_link)) {
PhysicalRect line_rect =
line->ScrollableOverflow(container, container_style);
line_rect.Move(child_link.offset);
return container.ConvertChildToLogical(line_rect).offset.block_offset;
}
}
return default_value;
}
inline scoped_refptr<const NGLayoutResult> LayoutBlockChild( inline scoped_refptr<const NGLayoutResult> LayoutBlockChild(
const NGConstraintSpace& space, const NGConstraintSpace& space,
const NGBreakToken* break_token, const NGBreakToken* break_token,
......
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