ruby-align: Implement the layout behavior

... and make the status "experimental".

The main logic is ApplyRubyAlign() in ruby_utils.cc. We already have
alignment logic. So this CL just adjusts it for ruby-align values.

* LineBreaker::AddRubyColumnResult() should set LineStyle to pass
  <ruby>'s style.

* GetOverhang() should return an empty AnnotationOverhang instance
  for ruby-align:space-between and an end-only instance for
  ruby-align:start.

* Move out space-around tests from css-ruby/ruby-align-00*.html because
  Firefox and Chrome have different justification opportunity counts
  for "X X X".

Bug: 40249572
Change-Id: I78af66e853356301135dc03bd1ab82c1a0e6ca31
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5595788
Reviewed-by: Koji Ishii <kojii@chromium.org>
Auto-Submit: Kent Tamura <tkent@chromium.org>
Commit-Queue: Koji Ishii <kojii@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1309784}
diff --git a/third_party/blink/renderer/core/layout/inline/line_breaker.cc b/third_party/blink/renderer/core/layout/inline/line_breaker.cc
index 5dff553..b73f54c 100644
--- a/third_party/blink/renderer/core/layout/inline/line_breaker.cc
+++ b/third_party/blink/renderer/core/layout/inline/line_breaker.cc
@@ -3453,6 +3453,7 @@
   auto* data = MakeGarbageCollected<InlineItemResultRubyColumn>();
   column_result->ruby_column = data;
   data->base_line = base_line_info;
+  data->base_line.OverrideLineStyle(*current_style_);
   data->base_line.SetIsRubyBase();
   data->base_line.UpdateTextAlign();
   if (data->base_line.MayHaveRubyOverhang()) {
diff --git a/third_party/blink/renderer/core/layout/inline/ruby_utils.cc b/third_party/blink/renderer/core/layout/inline/ruby_utils.cc
index be826e9..11f1670 100644
--- a/third_party/blink/renderer/core/layout/inline/ruby_utils.cc
+++ b/third_party/blink/renderer/core/layout/inline/ruby_utils.cc
@@ -190,6 +190,15 @@
   if (item.IsRubyColumn()) {
     DCHECK(RuntimeEnabledFeatures::RubyLineBreakableEnabled());
     const InlineItemResultRubyColumn& column = *item.ruby_column;
+    ERubyAlign ruby_align = column.base_line.LineStyle().RubyAlign();
+    switch (ruby_align) {
+      case ERubyAlign::kSpaceBetween:
+        return overhang;
+      case ERubyAlign::kStart:
+      case ERubyAlign::kSpaceAround:
+      case ERubyAlign::kCenter:
+        break;
+    }
     LayoutUnit half_width_of_annotation_font;
     for (const auto& annotation_line : column.annotation_line_list) {
       if (annotation_line.Width() == item.inline_size) {
@@ -201,8 +210,16 @@
     if (half_width_of_annotation_font == LayoutUnit()) {
       return overhang;
     }
-    std::optional<LayoutUnit> inset = ComputeRubyBaseInset(
-        item.inline_size - column.base_line.Width(), column.base_line);
+    LayoutUnit space = item.inline_size - column.base_line.Width();
+    if (space <= LayoutUnit()) {
+      return overhang;
+    }
+    if (ruby_align == ERubyAlign::kStart) {
+      overhang.end = std::min(space, half_width_of_annotation_font);
+      return overhang;
+    }
+    std::optional<LayoutUnit> inset =
+        ComputeRubyBaseInset(space, column.base_line);
     if (!inset) {
       return overhang;
     }
@@ -390,16 +407,35 @@
   if (space <= LayoutUnit()) {
     return {LayoutUnit(), LayoutUnit()};
   }
+
+  ERubyAlign ruby_align = line_info.LineStyle().RubyAlign();
   ETextAlign text_align = line_info.TextAlign();
-  // Handle `space-around`.
+  switch (ruby_align) {
+    case ERubyAlign::kSpaceAround:
+      // We respect to the text-align value as ever if ruby-align is the
+      // initial value.
+      break;
+    case ERubyAlign::kSpaceBetween:
+      on_start_edge = true;
+      on_end_edge = true;
+      text_align = ETextAlign::kJustify;
+      break;
+    case ERubyAlign::kStart:
+      return IsLtr(line_info.BaseDirection())
+                 ? std::make_pair(LayoutUnit(), space)
+                 : std::make_pair(space, LayoutUnit());
+    case ERubyAlign::kCenter:
+      return {space / 2, space / 2};
+  }
+
+  // Handle `space-around` and `space-between`.
   if (text_align == ETextAlign::kJustify) {
-    JustificationTarget target = JustificationTarget::kNormal;
-    if (line_info.IsRubyBase()) {
-      target = JustificationTarget::kRubyBase;
+    JustificationTarget target;
+    if (on_start_edge && on_end_edge) {
       // Switch to `space-between` if this needs to align both edges.
-      if (on_start_edge && on_end_edge) {
-        target = JustificationTarget::kNormal;
-      }
+      target = JustificationTarget::kNormal;
+    } else if (line_info.IsRubyBase()) {
+      target = JustificationTarget::kRubyBase;
     } else {
       DCHECK(line_info.IsRubyText());
       target = JustificationTarget::kRubyText;
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5
index 1c9f333a..4db3b0b5 100644
--- a/third_party/blink/renderer/platform/runtime_enabled_features.json5
+++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -993,7 +993,7 @@
     {
       // crbug.com/40249572
       name: "CssRubyAlign",
-      status: "test",
+      status: "experimental",
       depends_on: ["RubyLineBreakable"],
     },
     {
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index a7cd93a7..f333295f 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -2344,10 +2344,8 @@
 crbug.com/27659 external/wpt/css/css-ruby/improperly-contained-annotation-001.html [ Failure ]
 crbug.com/27659 external/wpt/css/css-ruby/rb-display-001.html [ Failure ]
 crbug.com/27659 external/wpt/css/css-ruby/rt-display-001.html [ Failure ]
-crbug.com/27659 external/wpt/css/css-ruby/ruby-align-001.html [ Failure ]
 crbug.com/27659 external/wpt/css/css-ruby/ruby-align-001a.html [ Failure ]
-crbug.com/27659 external/wpt/css/css-ruby/ruby-align-002.html [ Failure ]
-crbug.com/27659 external/wpt/css/css-ruby/ruby-align-002a.html [ Failure ]
+crbug.com/27659 external/wpt/css/css-ruby/ruby-align-space-around.html [ Failure ]
 crbug.com/27659 external/wpt/css/css-ruby/ruby-annotation-pairing-001.html [ Failure ]
 crbug.com/27659 external/wpt/css/css-ruby/ruby-base-container-abs.html [ Failure ]
 crbug.com/27659 external/wpt/css/css-ruby/ruby-base-container-float.html [ Failure ]
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ruby/ruby-align-001-ref.html b/third_party/blink/web_tests/external/wpt/css/css-ruby/ruby-align-001-ref.html
index eb368b3a..4497858 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-ruby/ruby-align-001-ref.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-ruby/ruby-align-001-ref.html
@@ -12,6 +12,3 @@
 <div>X X X</div>
 <div style="text-align: center">X X X</div>
 <div style="text-align-last: justify">X X X</div>
-<!-- 8px = (width: 160px - 5 * font-size: 16px) /
-            (1 + justification opportunities: 4) / 2 -->
-<div style="text-align-last: justify; padding: 0 8px">X X X</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ruby/ruby-align-001.html b/third_party/blink/web_tests/external/wpt/css/css-ruby/ruby-align-001.html
index 13c96f5..c611a56 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-ruby/ruby-align-001.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-ruby/ruby-align-001.html
@@ -20,7 +20,4 @@
 </ruby><br>
 <ruby style="ruby-align: space-between">
   <rb>X X X<rt><div></div></rt>
-</ruby><br>
-<ruby style="ruby-align: space-around">
-  <rb>X X X<rt><div></div></rt>
 </ruby>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ruby/ruby-align-001a.html b/third_party/blink/web_tests/external/wpt/css/css-ruby/ruby-align-001a.html
index 6e652f1..a2c492bb 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-ruby/ruby-align-001a.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-ruby/ruby-align-001a.html
@@ -20,7 +20,4 @@
 </ruby><br>
 <ruby>
   <rb style="ruby-align: space-between">X X X<rt><div></div></rt>
-</ruby><br>
-<ruby>
-  <rb style="ruby-align: space-around">X X X<rt><div></div></rt>
 </ruby>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ruby/ruby-align-002-ref.html b/third_party/blink/web_tests/external/wpt/css/css-ruby/ruby-align-002-ref.html
index e4dd3c8..b0d7ec4 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-ruby/ruby-align-002-ref.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-ruby/ruby-align-002-ref.html
@@ -20,9 +20,4 @@
 </ruby><br>
 <ruby>
   <rb></rb><rt><div style="text-align-last: justify">X X X</div></rt>
-</ruby><br>
-<!-- 8px = (width: 160px - 5 * font-size: 16px) /
-            (1 + justification opportunities: 4) / 2 -->
-<ruby>
-  <rb></rb><rt><div style="text-align-last: justify; padding: 0 8px">X X X</div></rt>
 </ruby>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ruby/ruby-align-002.html b/third_party/blink/web_tests/external/wpt/css/css-ruby/ruby-align-002.html
index ec40be5..22e43e4 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-ruby/ruby-align-002.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-ruby/ruby-align-002.html
@@ -22,7 +22,4 @@
 </ruby><br>
 <ruby style="ruby-align: space-between">
   <rb><div></div><rt>X X X</rt>
-</ruby><br>
-<ruby style="ruby-align: space-around">
-  <rb><div></div><rt>X X X</rt>
 </ruby>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ruby/ruby-align-002a.html b/third_party/blink/web_tests/external/wpt/css/css-ruby/ruby-align-002a.html
index dfb7ae3..21838c9 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-ruby/ruby-align-002a.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-ruby/ruby-align-002a.html
@@ -22,7 +22,4 @@
 </ruby><br>
 <ruby>
   <rb><div></div><rt style="ruby-align: space-between">X X X</rt>
-</ruby><br>
-<ruby>
-  <rb><div></div><rt style="ruby-align: space-around">X X X</rt>
 </ruby>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ruby/ruby-align-space-around-ref.html b/third_party/blink/web_tests/external/wpt/css/css-ruby/ruby-align-space-around-ref.html
new file mode 100644
index 0000000..8eec06f
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-ruby/ruby-align-space-around-ref.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<meta charset="UTF-8">
+<title>Tests for ruby-align</title>
+<link rel="author" title="Xidorn Quan" href="https://www.upsuper.org">
+<link rel="author" title="Mozilla" href="https://www.mozilla.org">
+<link rel="stylesheet" href="/fonts/ahem.css">
+<link rel="stylesheet" href="support/ruby-common.css">
+<style>
+  div { width: 160px; box-sizing: border-box; }
+
+  .annotation-test ruby { line-height: 0; }
+  .annotation-test rt { font-size: 100%; }
+  .annotation-test rb { font-size: 0; }
+  .annotation-test rt > div { width: 160px; box-sizing: border-box; }
+</style>
+<body style="font: 16px/3 Ahem">
+<!-- 8px = (width: 160px - 5 * font-size: 16px) /
+            (1 + justification opportunities: 4) / 2 -->
+<div style="text-align-last: justify; padding: 0 8px">X X X</div>
+<div style="text-align-last: justify; padding: 0 8px">X X X</div>
+
+<div class="annotation-test">
+<!-- 8px = (width: 160px - 5 * font-size: 16px) /
+            (1 + justification opportunities: 4) / 2 -->
+<ruby>
+  <rb></rb><rt><div style="text-align-last: justify; padding: 0 8px">X X X</div></rt>
+</ruby><br>
+<ruby>
+  <rb></rb><rt><div style="text-align-last: justify; padding: 0 8px">X X X</div></rt>
+</ruby>
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ruby/ruby-align-space-around.html b/third_party/blink/web_tests/external/wpt/css/css-ruby/ruby-align-space-around.html
new file mode 100644
index 0000000..dfc1b6a
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-ruby/ruby-align-space-around.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<meta charset="UTF-8">
+<title>Tests for ruby-align</title>
+<link rel="author" title="Xidorn Quan" href="https://www.upsuper.org">
+<link rel="author" title="Mozilla" href="https://www.mozilla.org">
+<link rel="help" href="https://drafts.csswg.org/css-ruby-1/#ruby-align-property">
+<link rel="match" href="ruby-align-space-around-ref.html">
+<link rel="stylesheet" href="/fonts/ahem.css">
+<link rel="stylesheet" href="support/ruby-common.css">
+<style>
+  ruby { line-height: 0; }
+  rt > div { width: 160px; }
+
+  .annotation-test ruby { line-height: 0; }
+  .annotation-test rt { font-size: 100%; }
+  .annotation-test rb { font-size: 0; }
+  .annotation-test rb > div { width: 160px; }
+</style>
+<body style="font: 16px/3 Ahem">
+<ruby style="ruby-align: space-around">
+  <rb>X X X<rt><div></div></rt>
+</ruby><br>
+<ruby>
+  <rb style="ruby-align: space-around">X X X<rt><div></div></rt>
+</ruby>
+
+<div class="annotation-test">
+<ruby style="ruby-align: space-around">
+  <rb><div></div><rt>X X X</rt>
+</ruby><br>
+<ruby>
+  <rb><div></div><rt style="ruby-align: space-around">X X X</rt>
+</ruby>
+</div>