[mathml] Wrap <mtd> children in an anonymous <mrow>
This CL wraps the children of an <mtd> cell within an anonymous <mrow>.
That way, such children are laid out as if they were in an explicit
<mrow>, in particular avoiding line breaks, performing operator
stretching and adding proper operator spacing [1]. In particular, this
fixes the second use case demonstrated at BlinkOn 16 [2].
[1] https://w3c.github.io/mathml-core/#layout-of-mrow
[2] https://people.igalia.com/fwang/2022-blinkon-16-remainder-estimate-for-mathml-integration/?showNotes=true#/19
Bug: 6606, 1125111, 1237043
Change-Id: Icd330b523df4548bf7065eed986bd3698514f50b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3657309
Reviewed-by: Ian Kilpatrick <ikilpatrick@chromium.org>
Commit-Queue: Frédéric Wang <fwang@igalia.com>
Cr-Commit-Position: refs/heads/main@{#1010954}
diff --git a/mathml/presentation-markup/mrow/inferred-mrow-baseline.html b/mathml/presentation-markup/mrow/inferred-mrow-baseline.html
index 2b208aa..cc007cf 100644
--- a/mathml/presentation-markup/mrow/inferred-mrow-baseline.html
+++ b/mathml/presentation-markup/mrow/inferred-mrow-baseline.html
@@ -20,7 +20,7 @@
window.addEventListener("load", runTests);
function runTests()
{
- ["Mrow", "Sqrt", "Style", "Error", "Phantom", "Math", "Menclose", "Mpadded", "Unknown"].forEach((tag) => {
+ ["Mrow", "Sqrt", "Style", "Error", "Phantom", "Math", "Menclose", "Mpadded", "Unknown", "Mtd"].forEach((tag) => {
var x = document.getElementById("above" + tag).getBoundingClientRect();
var y = document.getElementById("below" + tag).getBoundingClientRect();
test(function() {
@@ -48,6 +48,8 @@
></mspace><mspace id="belowMpadded" width="10px" depth="30px" style="background: blue"></mspace></mpadded></math>
<math><unknown><mspace id="aboveUnknown" width="10px" height="30px" style="background: purple"
></mspace><mspace id="belowUnknown" width="10px" depth="30px" style="background: blue"></mspace></unknown></math>
+ <math><mtable><mtr><mtd><mspace id="aboveMtd" width="10px" height="30px" style="background: purple"
+></mspace><mspace id="belowMtd" width="10px" depth="30px" style="background: blue"></mspace></mtd></mtr></mtable></math>
</p>
</body>
</html>
diff --git a/mathml/presentation-markup/mrow/inferred-mrow-stretchy.html b/mathml/presentation-markup/mrow/inferred-mrow-stretchy.html
index 35c6d69..a1e409a 100644
--- a/mathml/presentation-markup/mrow/inferred-mrow-stretchy.html
+++ b/mathml/presentation-markup/mrow/inferred-mrow-stretchy.html
@@ -32,7 +32,7 @@
window.addEventListener("load", () => { loadAllFonts().then(runTests); });
function runTests()
{
- ["Mrow", "Sqrt", "Style", "Error", "Phantom", "Math", "Menclose", "Mpadded", "Unknown"].forEach((tag) => {
+ ["Mrow", "Sqrt", "Style", "Error", "Phantom", "Math", "Menclose", "Mpadded", "Unknown", "Mtd"].forEach((tag) => {
var mo = document.getElementById("mo" + tag);
test(function() {
assert_true(MathMLFeatureDetection.has_mspace());
@@ -56,6 +56,7 @@
<math><menclose notation="box"><mo id="moMenclose">↨</mo><mspace width="1px" height="100px" style="background: magenta"></mspace></menclose></math>
<math><mpadded lspace="10px"><mo id="moMpadded">↨</mo><mspace width="1px" height="100px" style="background: magenta"></mspace></mpadded></math>
<math><unknown><mo id="moUnknown">↨</mo><mspace width="1px" height="100px" style="background: magenta"></mspace></unknown></math>
+ <math><mtable><mtr><mtd><mo id="moMtd">↨</mo><mspace width="1px" height="100px" style="background: magenta"></mspace></mtd></mtr></mtable></math>
</p>
</body>
</html>
diff --git a/mathml/presentation-markup/mrow/spacing.html b/mathml/presentation-markup/mrow/spacing.html
index bad3370..c066f72 100644
--- a/mathml/presentation-markup/mrow/spacing.html
+++ b/mathml/presentation-markup/mrow/spacing.html
@@ -22,7 +22,7 @@
window.addEventListener("load", () => { loadAllFonts().then(runTests); });
function runTests()
{
- ["Mrow", "Sqrt", "Style", "Error", "Phantom", "Math", "Menclose", "Mpadded", "Unknown"].forEach((tag) => {
+ ["Mrow", "Sqrt", "Style", "Error", "Phantom", "Math", "Menclose", "Mpadded", "Unknown", "Mtd"].forEach((tag) => {
test(function() {
assert_true(MathMLFeatureDetection.has_operator_spacing());
var mrow = document.getElementById(tag);
@@ -48,6 +48,7 @@
<math><menclose id="Menclose" notation="box"><mn>1</mn><mo lspace="50px">|</mo><mn>2</mn></menclose></math>
<math><mpadded id="Mpadded" lspace="10px"><mn>1</mn><mo lspace="50px">|</mo><mn>2</mn></mpadded></math>
<math><unknown id="Unknown"><mn>1</mn><mo lspace="50px">|</mo><mn>2</mn></unknown></math>
+ <math><mtable><mtr><mtd id="Mtd"><mn>1</mn><mo lspace="50px">|</mo><mn>2</mn></mtd></mtr></mtable></math>
</p>
</body>
</html>
diff --git a/mathml/presentation-markup/tables/table-cell-mrow-layout.html b/mathml/presentation-markup/tables/table-cell-mrow-layout.html
new file mode 100644
index 0000000..1e76e39
--- /dev/null
+++ b/mathml/presentation-markup/tables/table-cell-mrow-layout.html
@@ -0,0 +1,74 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Table cell mrow layout</title>
+<link rel="help" href="https://w3c.github.io/mathml-core/#table-or-matrix-mtable">
+<meta name="assert" content="Table cell relies on the mrow layout for their children.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/mathml/support/feature-detection.js"></script>
+<script src="/mathml/support/layout-comparison.js"></script>
+<style>
+ /* Remove default padding, since there is none on reference mrow element. */
+ mtd { padding: 0; }
+</style>
+</head>
+<body>
+ <div id="log"></div>
+ <p>
+ <math>
+ <mtable id="mtable">
+ <mtr>
+ <mtd id="mtd">
+ <mspace width="10px" depth="20px" height="20px" style="background: blue"/>
+ <mspace width="10px" depth="10px" height="30px" style="background: lightblue"/>
+ <mspace width="10px" depth="30px" height="10px" style="background: black"/>
+ </mtd>
+ </mtr>
+ </mtable>
+ </math>
+ </p>
+ <p>
+ <math>
+ <mrow id="mtd-reference">
+ <mspace width="10px" depth="20px" height="20px" style="background: blue"/>
+ <mspace width="10px" depth="10px" height="30px" style="background: lightblue"/>
+ <mspace width="10px" depth="30px" height="10px" style="background: black"/>
+ </mrow>
+ </math>
+ </p>
+ <p>
+ <math>
+ <mtable id="mtable-reference">
+ <mtr>
+ <mtd>
+ <mrow>
+ <mspace width="10px" depth="20px" height="20px" style="background: blue"/>
+ <mspace width="10px" depth="10px" height="30px" style="background: lightblue"/>
+ <mspace width="10px" depth="30px" height="10px" style="background: black"/>
+ </mrow>
+ </mtd>
+ </mtr>
+ </mtable>
+ </math>
+ </p>
+ <script>
+ const epsilon = 1;
+
+ test(function() {
+ assert_true(MathMLFeatureDetection.has_mspace());
+ let mtd = document.getElementById("mtd");
+ let reference = document.getElementById("mtd-reference");
+ compareLayout(mtd, reference, epsilon);
+ }, "<mtd> relies on mrow algorithm to layout its children");
+
+ test(function() {
+ assert_true(MathMLFeatureDetection.has_mspace());
+ let mtable = document.getElementById("mtable");
+ let reference = document.getElementById("mtable-reference");
+ compareLayout(mtable, reference, epsilon);
+ }, "<mtable> layout does not change if children of <mtd> elements are wrapped in an explicit <mrow>");
+ </script>
+</body>
+</html>
diff --git a/mathml/relations/html5-tree/dynamic-childlist-002.html b/mathml/relations/html5-tree/dynamic-childlist-002.html
index e4b4313..099401e 100644
--- a/mathml/relations/html5-tree/dynamic-childlist-002.html
+++ b/mathml/relations/html5-tree/dynamic-childlist-002.html
@@ -30,7 +30,17 @@
element.appendChild(mrow);
}
}
- math.appendChild(element);
+ if (FragmentHelper.isValidChildOfMrow(tag)) {
+ math.appendChild(element);
+ } else if (tag === "mtd") {
+ let mtr = FragmentHelper.createElement("mtr");
+ mtr.appendChild(element);
+ let mtable = FragmentHelper.createElement("mtable");
+ mtable.appendChild(mtr);
+ math.appendChild(mtable);
+ } else {
+ throw `Invalid argument: ${tag}`;
+ }
return math;
}
@@ -38,7 +48,7 @@
window.addEventListener("load", function() {
for (tag in MathMLFragments) {
- if (!FragmentHelper.isValidChildOfMrow(tag))
+ if (!FragmentHelper.isValidChildOfMrow(tag) || tag === "mtd")
continue;
document.body.insertAdjacentHTML("beforeend", `<div style='display: none; background: pink;'>${tag}: <div></div><div></div><div></div></div>`);