Bug 1912435 - Make MathML boolean attributes ASCII case-insensitive. r=emilio
This commit ensures MathML boolean attributes (namely displaystyle, mo@stretchy, mo@symmetric, mo@largeop, mo@movablelimits, munder@accentunder, mover@accent, munderover@accent, munderover@accentunder) are ASCII case-insensitive [1]. For displaystyle that was handled in [2]. For mover/munder/munderover attributes, this is covered by a test case from scriptlevel-001.html checking both case-insensitivity and dynamic changes at the same time ; the latter still seems broken, so these checks are moved into separate test cases. For mo attributes, a new WPT test is added. Note that mo@accent, mo@fence, mo@separator are not part of MathML Core (with the two last without visual effect), we make them case-insensitive for consistency but don't bother adding tests for them. [1] https://w3c.github.io/mathml-core/#dfn-boolean used here: [2] https://bugzilla.mozilla.org/show_bug.cgi?id=1574087 Differential Revision: https://phabricator.services.mozilla.com/D218944
This commit is contained in:
@@ -237,17 +237,19 @@ void nsMathMLmoFrame::ProcessOperatorData() {
|
|||||||
|
|
||||||
// see if the accent attribute is there
|
// see if the accent attribute is there
|
||||||
mContent->AsElement()->GetAttr(nsGkAtoms::accent_, value);
|
mContent->AsElement()->GetAttr(nsGkAtoms::accent_, value);
|
||||||
if (value.EqualsLiteral("true"))
|
if (value.LowerCaseEqualsLiteral("true")) {
|
||||||
mEmbellishData.flags |= NS_MATHML_EMBELLISH_ACCENT;
|
mEmbellishData.flags |= NS_MATHML_EMBELLISH_ACCENT;
|
||||||
else if (value.EqualsLiteral("false"))
|
} else if (value.LowerCaseEqualsLiteral("false")) {
|
||||||
mEmbellishData.flags &= ~NS_MATHML_EMBELLISH_ACCENT;
|
mEmbellishData.flags &= ~NS_MATHML_EMBELLISH_ACCENT;
|
||||||
|
}
|
||||||
|
|
||||||
// see if the movablelimits attribute is there
|
// see if the movablelimits attribute is there
|
||||||
mContent->AsElement()->GetAttr(nsGkAtoms::movablelimits_, value);
|
mContent->AsElement()->GetAttr(nsGkAtoms::movablelimits_, value);
|
||||||
if (value.EqualsLiteral("true"))
|
if (value.LowerCaseEqualsLiteral("true")) {
|
||||||
mEmbellishData.flags |= NS_MATHML_EMBELLISH_MOVABLELIMITS;
|
mEmbellishData.flags |= NS_MATHML_EMBELLISH_MOVABLELIMITS;
|
||||||
else if (value.EqualsLiteral("false"))
|
} else if (value.LowerCaseEqualsLiteral("false")) {
|
||||||
mEmbellishData.flags &= ~NS_MATHML_EMBELLISH_MOVABLELIMITS;
|
mEmbellishData.flags &= ~NS_MATHML_EMBELLISH_MOVABLELIMITS;
|
||||||
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------
|
// ---------------------------------------------------------------------
|
||||||
// we will be called again to re-sync the rest of our state next time...
|
// we will be called again to re-sync the rest of our state next time...
|
||||||
@@ -444,36 +446,39 @@ void nsMathMLmoFrame::ProcessOperatorData() {
|
|||||||
// don't process them here
|
// don't process them here
|
||||||
|
|
||||||
mContent->AsElement()->GetAttr(nsGkAtoms::stretchy_, value);
|
mContent->AsElement()->GetAttr(nsGkAtoms::stretchy_, value);
|
||||||
if (value.EqualsLiteral("false")) {
|
if (value.LowerCaseEqualsLiteral("false")) {
|
||||||
mFlags &= ~NS_MATHML_OPERATOR_STRETCHY;
|
mFlags &= ~NS_MATHML_OPERATOR_STRETCHY;
|
||||||
} else if (value.EqualsLiteral("true")) {
|
} else if (value.LowerCaseEqualsLiteral("true")) {
|
||||||
mFlags |= NS_MATHML_OPERATOR_STRETCHY;
|
mFlags |= NS_MATHML_OPERATOR_STRETCHY;
|
||||||
}
|
}
|
||||||
if (NS_MATHML_OPERATOR_IS_FENCE(mFlags)) {
|
if (NS_MATHML_OPERATOR_IS_FENCE(mFlags)) {
|
||||||
mContent->AsElement()->GetAttr(nsGkAtoms::fence_, value);
|
mContent->AsElement()->GetAttr(nsGkAtoms::fence_, value);
|
||||||
if (value.EqualsLiteral("false"))
|
if (value.LowerCaseEqualsLiteral("false")) {
|
||||||
mFlags &= ~NS_MATHML_OPERATOR_FENCE;
|
mFlags &= ~NS_MATHML_OPERATOR_FENCE;
|
||||||
else
|
} else {
|
||||||
mEmbellishData.flags |= NS_MATHML_EMBELLISH_FENCE;
|
mEmbellishData.flags |= NS_MATHML_EMBELLISH_FENCE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
mContent->AsElement()->GetAttr(nsGkAtoms::largeop_, value);
|
mContent->AsElement()->GetAttr(nsGkAtoms::largeop_, value);
|
||||||
if (value.EqualsLiteral("false")) {
|
if (value.LowerCaseEqualsLiteral("false")) {
|
||||||
mFlags &= ~NS_MATHML_OPERATOR_LARGEOP;
|
mFlags &= ~NS_MATHML_OPERATOR_LARGEOP;
|
||||||
} else if (value.EqualsLiteral("true")) {
|
} else if (value.LowerCaseEqualsLiteral("true")) {
|
||||||
mFlags |= NS_MATHML_OPERATOR_LARGEOP;
|
mFlags |= NS_MATHML_OPERATOR_LARGEOP;
|
||||||
}
|
}
|
||||||
if (NS_MATHML_OPERATOR_IS_SEPARATOR(mFlags)) {
|
if (NS_MATHML_OPERATOR_IS_SEPARATOR(mFlags)) {
|
||||||
mContent->AsElement()->GetAttr(nsGkAtoms::separator_, value);
|
mContent->AsElement()->GetAttr(nsGkAtoms::separator_, value);
|
||||||
if (value.EqualsLiteral("false"))
|
if (value.LowerCaseEqualsLiteral("false")) {
|
||||||
mFlags &= ~NS_MATHML_OPERATOR_SEPARATOR;
|
mFlags &= ~NS_MATHML_OPERATOR_SEPARATOR;
|
||||||
else
|
} else {
|
||||||
mEmbellishData.flags |= NS_MATHML_EMBELLISH_SEPARATOR;
|
mEmbellishData.flags |= NS_MATHML_EMBELLISH_SEPARATOR;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
mContent->AsElement()->GetAttr(nsGkAtoms::symmetric_, value);
|
mContent->AsElement()->GetAttr(nsGkAtoms::symmetric_, value);
|
||||||
if (value.EqualsLiteral("false"))
|
if (value.LowerCaseEqualsLiteral("false")) {
|
||||||
mFlags &= ~NS_MATHML_OPERATOR_SYMMETRIC;
|
mFlags &= ~NS_MATHML_OPERATOR_SYMMETRIC;
|
||||||
else if (value.EqualsLiteral("true"))
|
} else if (value.LowerCaseEqualsLiteral("true")) {
|
||||||
mFlags |= NS_MATHML_OPERATOR_SYMMETRIC;
|
mFlags |= NS_MATHML_OPERATOR_SYMMETRIC;
|
||||||
|
}
|
||||||
|
|
||||||
// minsize
|
// minsize
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -223,9 +223,9 @@ XXX The winner is the outermost setting in conflicting settings like these:
|
|||||||
// if we have an accentunder attribute, it overrides what the underscript
|
// if we have an accentunder attribute, it overrides what the underscript
|
||||||
// said
|
// said
|
||||||
if (mContent->AsElement()->GetAttr(nsGkAtoms::accentunder_, value)) {
|
if (mContent->AsElement()->GetAttr(nsGkAtoms::accentunder_, value)) {
|
||||||
if (value.EqualsLiteral("true")) {
|
if (value.LowerCaseEqualsLiteral("true")) {
|
||||||
mEmbellishData.flags |= NS_MATHML_EMBELLISH_ACCENTUNDER;
|
mEmbellishData.flags |= NS_MATHML_EMBELLISH_ACCENTUNDER;
|
||||||
} else if (value.EqualsLiteral("false")) {
|
} else if (value.LowerCaseEqualsLiteral("false")) {
|
||||||
mEmbellishData.flags &= ~NS_MATHML_EMBELLISH_ACCENTUNDER;
|
mEmbellishData.flags &= ~NS_MATHML_EMBELLISH_ACCENTUNDER;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -244,9 +244,9 @@ XXX The winner is the outermost setting in conflicting settings like these:
|
|||||||
|
|
||||||
// if we have an accent attribute, it overrides what the overscript said
|
// if we have an accent attribute, it overrides what the overscript said
|
||||||
if (mContent->AsElement()->GetAttr(nsGkAtoms::accent_, value)) {
|
if (mContent->AsElement()->GetAttr(nsGkAtoms::accent_, value)) {
|
||||||
if (value.EqualsLiteral("true")) {
|
if (value.LowerCaseEqualsLiteral("true")) {
|
||||||
mEmbellishData.flags |= NS_MATHML_EMBELLISH_ACCENTOVER;
|
mEmbellishData.flags |= NS_MATHML_EMBELLISH_ACCENTOVER;
|
||||||
} else if (value.EqualsLiteral("false")) {
|
} else if (value.LowerCaseEqualsLiteral("false")) {
|
||||||
mEmbellishData.flags &= ~NS_MATHML_EMBELLISH_ACCENTOVER;
|
mEmbellishData.flags &= ~NS_MATHML_EMBELLISH_ACCENTOVER;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
[scriptlevel-001.html]
|
[scriptlevel-001.html]
|
||||||
[checking dynamic/case-insensitive accent/accentunder]
|
[checking dynamic accent/accentunder]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|||||||
@@ -0,0 +1,45 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<meta charset="utf-8"/>
|
||||||
|
<title>Test case insensitivity of mo boolean attributes (reference)</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" />
|
||||||
|
<style>
|
||||||
|
math {
|
||||||
|
font: 25px/1 Ahem;
|
||||||
|
}
|
||||||
|
@font-face {
|
||||||
|
font-family: operators;
|
||||||
|
src: url("/fonts/math/operators.woff");
|
||||||
|
}
|
||||||
|
mo {
|
||||||
|
font-family: operators;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<p>
|
||||||
|
<math>
|
||||||
|
<mrow>
|
||||||
|
<mo symmetric="false" stretchy="false">⥯</mo>
|
||||||
|
<mspace height="2em"></mspace>
|
||||||
|
</mrow>
|
||||||
|
</math>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<math>
|
||||||
|
<mrow>
|
||||||
|
<mo symmetric="true" stretchy="true">⥯</mo>
|
||||||
|
<mspace height="1.5em"></mspace>
|
||||||
|
</mrow>
|
||||||
|
</math>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<math displaystyle="true">
|
||||||
|
<mo largeop="false">∑</mo>
|
||||||
|
</math>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<math>
|
||||||
|
<munder>
|
||||||
|
<mo movablelimits="false">∑</mo>
|
||||||
|
<mtext>X</mtext>
|
||||||
|
</munder>
|
||||||
|
</math>
|
||||||
|
</p>
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<meta charset="utf-8"/>
|
||||||
|
<title>Test case insensitivity of mo boolean attributes</title>
|
||||||
|
<link rel="help" href="https://w3c.github.io/mathml-core/#operator-fence-separator-or-accent-mo">
|
||||||
|
<link rel="help" href="https://w3c.github.io/mathml-core/#dom-and-javascript">
|
||||||
|
<meta name="assert" content="Verifies case insensitivity of mo boolean attributes.">
|
||||||
|
<link rel="match" href="mo-boolean-attributes-case-insensitive-ref.html">
|
||||||
|
<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" />
|
||||||
|
<style>
|
||||||
|
math {
|
||||||
|
font: 25px/1 Ahem;
|
||||||
|
}
|
||||||
|
@font-face {
|
||||||
|
font-family: operators;
|
||||||
|
src: url("/fonts/math/operators.woff");
|
||||||
|
}
|
||||||
|
mo {
|
||||||
|
font-family: operators;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<p>
|
||||||
|
<math>
|
||||||
|
<mrow>
|
||||||
|
<mo symmetric="false" stretchy="FaLsE">⥯</mo>
|
||||||
|
<mspace height="2em"></mspace>
|
||||||
|
</mrow>
|
||||||
|
</math>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<math>
|
||||||
|
<mrow>
|
||||||
|
<mo symmetric="TrUe" stretchy="true">⥯</mo>
|
||||||
|
<mspace height="1.5em"></mspace>
|
||||||
|
</mrow>
|
||||||
|
</math>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<math displaystyle="true">
|
||||||
|
<mo largeop="FALSe">∑</mo>
|
||||||
|
</math>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<math>
|
||||||
|
<munder>
|
||||||
|
<mo movablelimits="fALse">∑</mo>
|
||||||
|
<mtext>X</mtext>
|
||||||
|
</munder>
|
||||||
|
</math>
|
||||||
|
</p>
|
||||||
|
<script src="/mathml/support/feature-detection.js"></script>
|
||||||
|
<script>MathMLFeatureDetection.ensure_for_match_reftest("has_munderover");</script>
|
||||||
@@ -55,43 +55,50 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
test(function() {
|
test(function() {
|
||||||
var element = document.querySelector("munder[accentunder='true']");
|
var element = document.getElementById("munder-accentunder")
|
||||||
assert_approx_equals(fontSize(element.children[0]), fontSizeAtScriptLevelZero, epsilon, "base");
|
assert_approx_equals(fontSize(element.children[0]), fontSizeAtScriptLevelZero, epsilon, "base");
|
||||||
assert_approx_equals(fontSize(element.children[1]), fontSizeAtScriptLevelZero, epsilon, "under");
|
assert_approx_equals(fontSize(element.children[1]), fontSizeAtScriptLevelZero, epsilon, "under");
|
||||||
}, `automatic scriptlevel on munder (accentunder=true)`);
|
}, `automatic scriptlevel on munder (accentunder=true)`);
|
||||||
|
|
||||||
test(function() {
|
test(function() {
|
||||||
var element = document.querySelector("mover[accent='true']");
|
var element = document.getElementById("mover-accent")
|
||||||
assert_approx_equals(fontSize(element.children[0]), fontSizeAtScriptLevelZero, epsilon, "base");
|
assert_approx_equals(fontSize(element.children[0]), fontSizeAtScriptLevelZero, epsilon, "base");
|
||||||
assert_approx_equals(fontSize(element.children[1]), fontSizeAtScriptLevelZero, epsilon, "over");
|
assert_approx_equals(fontSize(element.children[1]), fontSizeAtScriptLevelZero, epsilon, "over");
|
||||||
}, `automatic scriptlevel on mover (accent=true)`);
|
}, `automatic scriptlevel on mover (accent=true)`);
|
||||||
|
|
||||||
test(function() {
|
test(function() {
|
||||||
var element = document.querySelector("munderover[accentunder='true']");
|
var element = document.getElementById("munderover-accentunder")
|
||||||
assert_approx_equals(fontSize(element.children[0]), fontSizeAtScriptLevelZero, epsilon, "base");
|
assert_approx_equals(fontSize(element.children[0]), fontSizeAtScriptLevelZero, epsilon, "base");
|
||||||
assert_approx_equals(fontSize(element.children[1]), fontSizeAtScriptLevelZero, epsilon, "under");
|
assert_approx_equals(fontSize(element.children[1]), fontSizeAtScriptLevelZero, epsilon, "under");
|
||||||
assert_approx_equals(fontSize(element.children[2]), fontSizeAtScriptLevelZero * .71, epsilon, "over");
|
assert_approx_equals(fontSize(element.children[2]), fontSizeAtScriptLevelZero * .71, epsilon, "over");
|
||||||
}, `automatic scriptlevel on munderover (accentunder=true)`);
|
}, `automatic scriptlevel on munderover (accentunder=true)`);
|
||||||
|
|
||||||
test(function() {
|
test(function() {
|
||||||
var element = document.querySelector("munderover[accent='true']");
|
var element = document.getElementById("munderover-accent")
|
||||||
assert_approx_equals(fontSize(element.children[0]), fontSizeAtScriptLevelZero, epsilon, "base");
|
assert_approx_equals(fontSize(element.children[0]), fontSizeAtScriptLevelZero, epsilon, "base");
|
||||||
assert_approx_equals(fontSize(element.children[1]), fontSizeAtScriptLevelZero * .71, epsilon, "under");
|
assert_approx_equals(fontSize(element.children[1]), fontSizeAtScriptLevelZero * .71, epsilon, "under");
|
||||||
assert_approx_equals(fontSize(element.children[2]), fontSizeAtScriptLevelZero, epsilon, "over");
|
assert_approx_equals(fontSize(element.children[2]), fontSizeAtScriptLevelZero, epsilon, "over");
|
||||||
}, `automatic scriptlevel on munderover (accent=true)`);
|
}, `automatic scriptlevel on munderover (accent=true)`);
|
||||||
|
|
||||||
test(function() {
|
test(function() {
|
||||||
var element = document.getElementById("munderover-dynamic-case-insensitive")
|
var element = document.getElementById("munderover-case-insensitive")
|
||||||
|
assert_approx_equals(fontSize(element.children[0]), fontSizeAtScriptLevelZero, epsilon, "base");
|
||||||
|
assert_approx_equals(fontSize(element.children[1]), fontSizeAtScriptLevelZero, epsilon, "under");
|
||||||
|
assert_approx_equals(fontSize(element.children[2]), fontSizeAtScriptLevelZero, epsilon, "over");
|
||||||
|
}, "checking case-insensitivity accent/accentunder");
|
||||||
|
|
||||||
|
test(function() {
|
||||||
|
var element = document.getElementById("munderover-dynamic")
|
||||||
assert_approx_equals(fontSize(element.children[0]), fontSizeAtScriptLevelZero, epsilon, "base");
|
assert_approx_equals(fontSize(element.children[0]), fontSizeAtScriptLevelZero, epsilon, "base");
|
||||||
assert_approx_equals(fontSize(element.children[1]), fontSizeAtScriptLevelZero * .71, epsilon, "under");
|
assert_approx_equals(fontSize(element.children[1]), fontSizeAtScriptLevelZero * .71, epsilon, "under");
|
||||||
assert_approx_equals(fontSize(element.children[2]), fontSizeAtScriptLevelZero, epsilon, "over");
|
assert_approx_equals(fontSize(element.children[2]), fontSizeAtScriptLevelZero, epsilon, "over");
|
||||||
|
|
||||||
element.removeAttribute("accent");
|
element.removeAttribute("accent");
|
||||||
element.setAttribute("accentunder", "TrUe");
|
element.setAttribute("accentunder", "true");
|
||||||
assert_approx_equals(fontSize(element.children[0]), fontSizeAtScriptLevelZero, epsilon, "base");
|
assert_approx_equals(fontSize(element.children[0]), fontSizeAtScriptLevelZero, epsilon, "base");
|
||||||
assert_approx_equals(fontSize(element.children[1]), fontSizeAtScriptLevelZero, epsilon, "under");
|
assert_approx_equals(fontSize(element.children[1]), fontSizeAtScriptLevelZero, epsilon, "under");
|
||||||
assert_approx_equals(fontSize(element.children[2]), fontSizeAtScriptLevelZero * .71, epsilon, "over");
|
assert_approx_equals(fontSize(element.children[2]), fontSizeAtScriptLevelZero * .71, epsilon, "over");
|
||||||
}, "checking dynamic/case-insensitive accent/accentunder");
|
}, "checking dynamic accent/accentunder");
|
||||||
|
|
||||||
done();
|
done();
|
||||||
}
|
}
|
||||||
@@ -179,26 +186,26 @@
|
|||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<math>
|
<math>
|
||||||
<munder accentunder="true">
|
<munder id="munder-accentunder" accentunder="true">
|
||||||
<mn>0</mn>
|
<mn>0</mn>
|
||||||
<mn>1</mn>
|
<mn>1</mn>
|
||||||
</munder>
|
</munder>
|
||||||
</math>
|
</math>
|
||||||
<math>
|
<math>
|
||||||
<mover accent="true">
|
<mover id="mover-accent" accent="true">
|
||||||
<mn>0</mn>
|
<mn>0</mn>
|
||||||
<mn>1</mn>
|
<mn>1</mn>
|
||||||
</mover>
|
</mover>
|
||||||
</math>
|
</math>
|
||||||
<math>
|
<math>
|
||||||
<munderover accent="true">
|
<munderover id="munderover-accent" accent="true">
|
||||||
<mn>0</mn>
|
<mn>0</mn>
|
||||||
<mn>1</mn>
|
<mn>1</mn>
|
||||||
<mn>2</mn>
|
<mn>2</mn>
|
||||||
</munderover>
|
</munderover>
|
||||||
</math>
|
</math>
|
||||||
<math>
|
<math>
|
||||||
<munderover accentunder="true">
|
<munderover id="munderover-accentunder" accentunder="true">
|
||||||
<mn>0</mn>
|
<mn>0</mn>
|
||||||
<mn>1</mn>
|
<mn>1</mn>
|
||||||
<mn>2</mn>
|
<mn>2</mn>
|
||||||
@@ -207,7 +214,16 @@
|
|||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<math>
|
<math>
|
||||||
<munderover id="munderover-dynamic-case-insensitive" accent="TrUe">
|
<munderover id="munderover-case-insensitive" accent="TrUe" accentunder="TrUe">
|
||||||
|
<mn>0</mn>
|
||||||
|
<mn>1</mn>
|
||||||
|
<mn>2</mn>
|
||||||
|
</munderover>
|
||||||
|
</math>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<math>
|
||||||
|
<munderover id="munderover-dynamic" accent="true">
|
||||||
<mn>0</mn>
|
<mn>0</mn>
|
||||||
<mn>1</mn>
|
<mn>1</mn>
|
||||||
<mn>2</mn>
|
<mn>2</mn>
|
||||||
|
|||||||
Reference in New Issue
Block a user