COMMIT_MESSAGE (3/5)

 1Bug 155714 - Use Stack* parameters from the OpenType MATH table
 2

LayoutTests/ChangeLog

 12016-03-21 Frederic Wang <fwang@igalia.com>
 2
 3 Use Stack* parameters from the OpenType MATH table
 4 https://bugs.webkit.org/show_bug.cgi?id=155714
 5
 6 Reviewed by NOBODY (OOPS!).
 7
 8 We import a test from the MathML in HTML5 test suite to verify Stack* parameters.
 9
 10 * imported/mathml-in-html5/fonts/math/stack-axisheight7000.woff: Added.
 11 * imported/mathml-in-html5/fonts/math/stack-bottomdisplaystyleshiftdown5000.woff: Added.
 12 * imported/mathml-in-html5/fonts/math/stack-bottomshiftdown6000.woff: Added.
 13 * imported/mathml-in-html5/fonts/math/stack-displaystylegapmin4000.woff: Added.
 14 * imported/mathml-in-html5/fonts/math/stack-gapmin8000.woff: Added.
 15 * imported/mathml-in-html5/fonts/math/stack-topdisplaystyleshiftup3000.woff: Added.
 16 * imported/mathml-in-html5/fonts/math/stack-topshiftup9000.woff: Added.
 17 * imported/mathml-in-html5/mathml/presentation-markup/fractions/frac-parameters-2-expected.txt: Added.
 18 * imported/mathml-in-html5/mathml/presentation-markup/fractions/frac-parameters-2.html: Added.
 19
1202016-03-17 Frederic Wang <fwang@igalia.com>
221
322 Add support for mathvariants that cannot be emulated via CSS.

LayoutTests/imported/mathml-in-html5/fonts/math/stack-axisheight7000.woff

Binary file, nothing to see here

LayoutTests/imported/mathml-in-html5/fonts/math/stack-bottomdisplaystyleshiftdown5000.woff

Binary file, nothing to see here

LayoutTests/imported/mathml-in-html5/fonts/math/stack-bottomshiftdown6000.woff

Binary file, nothing to see here

LayoutTests/imported/mathml-in-html5/fonts/math/stack-displaystylegapmin4000.woff

Binary file, nothing to see here

LayoutTests/imported/mathml-in-html5/fonts/math/stack-gapmin8000.woff

Binary file, nothing to see here

LayoutTests/imported/mathml-in-html5/fonts/math/stack-topdisplaystyleshiftup3000.woff

Binary file, nothing to see here

LayoutTests/imported/mathml-in-html5/fonts/math/stack-topshiftup9000.woff

Binary file, nothing to see here

LayoutTests/imported/mathml-in-html5/mathml/presentation-markup/fractions/frac-parameters-2-expected.txt

 1
 2PASS AxisHeight
 3PASS BottomDisplayStyleShiftDown
 4PASS BottomShiftDown
 5PASS DisplayStyleGapMin
 6PASS GapMin
 7PASS TopDisplayStyleShiftUp
 8PASS ToShiftUp
 9

LayoutTests/imported/mathml-in-html5/mathml/presentation-markup/fractions/frac-parameters-2.html

 1<!DOCTYPE html>
 2<html>
 3<head>
 4<meta charset="utf-8">
 5<title>Stack parameters</title>
 6<link rel="help" href="http://www.mathml-association.org/MathMLinHTML5/S3.html#SS3.SSS2">
 7<meta name="assert" content="Element mfrac correctly uses the stack parameters from the MATH table.">
 8<script src="../../../../../resources/testharness.js"></script>
 9<script src="../../../../../resources/testharnessreport.js"></script>
 10<style>
 11 math, mspace {
 12 font-size: 10px;
 13 }
 14 @font-face {
 15 font-family: axisheight7000;
 16 src: url("../../../fonts/math/stack-axisheight7000.woff");
 17 }
 18 @font-face {
 19 font-family: bottomdisplaystyleshiftdown5000;
 20 src: url("../../../fonts/math/stack-bottomdisplaystyleshiftdown5000.woff");
 21 }
 22 @font-face {
 23 font-family: bottomshiftdown6000;
 24 src: url("../../../fonts/math/stack-bottomshiftdown6000.woff");
 25 }
 26 @font-face {
 27 font-family: displaystylegapmin4000;
 28 src: url("../../../fonts/math/stack-displaystylegapmin4000.woff");
 29 }
 30 @font-face {
 31 font-family: gapmin8000;
 32 src: url("../../../fonts/math/stack-gapmin8000.woff");
 33 }
 34 @font-face {
 35 font-family: topdisplaystyleshiftup3000;
 36 src: url("../../../fonts/math/stack-topdisplaystyleshiftup3000.woff");
 37 }
 38 @font-face {
 39 font-family: topshiftup9000;
 40 src: url("../../../fonts/math/stack-topshiftup9000.woff");
 41 }
 42</style>
 43<script>
 44 var emToPx = 10 / 1000; // font-size: 10px, font.em = 1000
 45 var epsilon = 1;
 46
 47 function getBox(aId) {
 48 return document.getElementById(aId).getBoundingClientRect();
 49 }
 50
 51 setup({ explicit_done: true });
 52 window.addEventListener("load", function() {
 53 document.fonts.ready.then(function() {
 54 window.setTimeout(runTests, 250);
 55 });
 56 });
 57
 58 function runTests() {
 59 test(function() {
 60 var v = 7000 * emToPx;
 61 assert_approx_equals(getBox("ref0001").top - getBox("num0001").bottom,
 62 v, epsilon, "mfrac: axis height");
 63 }, "AxisHeight");
 64
 65 test(function() {
 66 var v = 5000 * emToPx;
 67 assert_approx_equals(getBox("den0002").top - getBox("ref0002").bottom,
 68 v, epsilon, "mfrac: denominator shift");
 69 }, "BottomDisplayStyleShiftDown");
 70
 71 test(function() {
 72 var v = 6000 * emToPx;
 73 assert_approx_equals(getBox("den0003").top - getBox("ref0003").bottom,
 74 v, epsilon, "mfrac: denominator shift");
 75 }, "BottomShiftDown");
 76
 77 test(function() {
 78 var v = 4000 * emToPx;
 79 assert_approx_equals(getBox("den0004").top - getBox("num0004").bottom,
 80 v, epsilon, "mfrac: gap");
 81 }, "DisplayStyleGapMin");
 82
 83 test(function() {
 84 var v = 8000 * emToPx;
 85 assert_approx_equals(getBox("den0005").top - getBox("num0005").bottom,
 86 v, epsilon, "mfrac: gap");
 87 }, "GapMin");
 88
 89 test(function() {
 90 var v = 3000 * emToPx;
 91 assert_approx_equals(getBox("ref0006").top - getBox("num0006").bottom,
 92 v, epsilon, "mfrac: numerator shift");
 93 }, "TopDisplayStyleShiftUp");
 94
 95 test(function() {
 96 var v = 9000 * emToPx;
 97 assert_approx_equals(getBox("ref0007").top - getBox("num0007").bottom,
 98 v, epsilon, "mfrac: numerator shift");
 99 }, "ToShiftUp");
 100
 101 done();
 102 }
 103</script>
 104</head>
 105<body>
 106 <p>
 107 <math style="font-family: axisheight7000;">
 108 <mspace id="ref0001" depth="1em" width="3em" mathbackground="green"/>
 109 <mfrac linethickness="0px">
 110 <mspace width="3em" height="1em" id="num0001" mathbackground="blue"/>
 111 <mspace width="3em"/>
 112 </mfrac>
 113 </math>
 114 </p>
 115 <hr/>
 116 <p>
 117 <math display="block" style="font-family: bottomdisplaystyleshiftdown5000;">
 118 <mspace id="ref0002" width="3em" height="1em" mathbackground="green"/>
 119 <mfrac linethickness="0px">
 120 <mspace width="3em"/>
 121 <mspace width="3em" depth="1em" id="den0002" mathbackground="blue"/>
 122 </mfrac>
 123 </math>
 124 </p>
 125 <hr/>
 126 <p>
 127 <math style="font-family: bottomshiftdown6000;">
 128 <mspace id="ref0003" width="3em" height="1em" mathbackground="green"/>
 129 <mfrac linethickness="0px">
 130 <mspace width="3em"/>
 131 <mspace width="3em" depth="1em" id="den0003" mathbackground="blue"/>
 132 </mfrac>
 133 </math>
 134 </p>
 135 <hr/>
 136 <p>
 137 <math display="block" style="font-family: displaystylegapmin4000;">
 138 <mfrac linethickness="0px">
 139 <mspace width="3em" height="1em" id="num0004" mathbackground="blue"/>
 140 <mspace width="3em" depth="1em" id="den0004" mathbackground="green"/>
 141 </mfrac>
 142 </math>
 143 </p>
 144 <hr/>
 145 <p>
 146 <math style="font-family: gapmin8000;">
 147 <mfrac linethickness="0px">
 148 <mspace width="3em" height="1em" id="num0005" mathbackground="blue"/>
 149 <mspace width="3em" depth="1em" id="den0005" mathbackground="green"/>
 150 </mfrac>
 151 </math>
 152 </p>
 153 <hr/>
 154 <p>
 155 <math display="block" style="font-family: topdisplaystyleshiftup3000;">
 156 <mspace id="ref0006" width="3em" depth="1em" mathbackground="green"/>
 157 <mfrac linethickness="0px">
 158 <mspace width="3em" height="1em" id="num0006" mathbackground="blue"/>
 159 <mspace width="3em"/>
 160 </mfrac>
 161 </math>
 162 </p>
 163 <hr/>
 164 <p>
 165 <math style="font-family: topshiftup9000;">
 166 <mspace id="ref0007" width="3em" depth="1em" mathbackground="green"/>
 167 <mfrac linethickness="0px">
 168 <mspace width="3em" height="1em" id="num0007" mathbackground="blue"/>
 169 <mspace width="3em"/>
 170 </mfrac>
 171 </math>
 172 </p>
 173 <hr/>
 174</body>
 175</html>

Source/WebCore/ChangeLog

 12016-03-21 Frederic Wang <fred.wang@free.fr>
 2
 3 Use Stack* parameters from the OpenType MATH table
 4 https://bugs.webkit.org/show_bug.cgi?id=155714
 5
 6 Reviewed by NOBODY (OOPS!).
 7
 8 Test: mathml/mathml-in-html5/frac-parameters-2.html
 9
 10 * rendering/mathml/RenderMathMLFraction.cpp:
 11 (WebCore::RenderMathMLFraction::updateFromElement): Set the stack parameters when
 12 the line thickness is zero.
 13 (WebCore::RenderMathMLFraction::layoutBlock): Correctly set the <mfrac> ascent and
 14 the denominator vertical offset when the line thickness is zero.
 15 (WebCore::RenderMathMLFraction::paint): Early return when we actually do not need to
 16 paint any fraction bar.
 17 * rendering/mathml/RenderMathMLFraction.h: Define a isStack helper function and define
 18 members corresponding to stack parameters.
 19
1202016-03-17 Frederic Wang <fwang@igalia.com>
221
322 Add support for mathvariants that cannot be emulated via CSS.

Source/WebCore/rendering/mathml/RenderMathMLFraction.cpp

@@void RenderMathMLFraction::updateFromElement()
110110 }
111111
112112 // We now know whether we should layout as a normal fraction or as a stack (fraction without bar) and so determine the relevant constants.
113  // FIXME: If m_lineThickness == 0, we should read Stack* parameters. See http://wkb.ug/122297
114113 bool display = mathMLStyle()->displayStyle();
115  if (mathData) {
116  m_numeratorGapMin = mathData->getMathConstant(primaryFont, display ? OpenTypeMathData::FractionNumDisplayStyleGapMin : OpenTypeMathData::FractionNumeratorGapMin);
117  m_denominatorGapMin = mathData->getMathConstant(primaryFont, display ? OpenTypeMathData::FractionDenomDisplayStyleGapMin : OpenTypeMathData::FractionDenominatorGapMin);
118  m_numeratorMinShiftUp = mathData->getMathConstant(primaryFont, display ? OpenTypeMathData::FractionNumeratorDisplayStyleShiftUp : OpenTypeMathData::FractionNumeratorShiftUp);
119  m_denominatorMinShiftDown = mathData->getMathConstant(primaryFont, display ? OpenTypeMathData::FractionDenominatorDisplayStyleShiftDown : OpenTypeMathData::FractionDenominatorShiftDown);
 114 if (isStack()) {
 115 if (mathData) {
 116 m_gapMin = mathData->getMathConstant(primaryFont, display ? OpenTypeMathData::StackDisplayStyleGapMin : OpenTypeMathData::StackGapMin);
 117 m_topShiftUp = mathData->getMathConstant(primaryFont, display ? OpenTypeMathData::StackTopDisplayStyleShiftUp : OpenTypeMathData::StackTopShiftUp);
 118 m_bottomShiftDown = mathData->getMathConstant(primaryFont, display ? OpenTypeMathData::StackBottomDisplayStyleShiftDown : OpenTypeMathData::StackBottomShiftDown);
 119 } else {
 120 // We use the values suggested in the MATH table specification.
 121 m_gapMin = m_denominatorGapMin = display ? 7 * ruleThicknessFallback() : 3 * ruleThicknessFallback();
 122
 123 // The MATH table specification does not suggest any values for shifts, so we leave them at zero.
 124 m_topShiftUp = m_bottomShiftDown = 0;
 125 }
120126 } else {
121  // The MATH table specification suggests default rule thickness or (in displaystyle) 3 times default rule thickness for the gaps.
122  m_numeratorGapMin = m_denominatorGapMin = display ? 3 * ruleThicknessFallback() : ruleThicknessFallback();
123 
124  // The MATH table specification does not suggest any values for shifts, so we leave them at zero.
125  m_numeratorMinShiftUp = m_denominatorMinShiftDown = 0;
 127 if (mathData) {
 128 m_numeratorGapMin = mathData->getMathConstant(primaryFont, display ? OpenTypeMathData::FractionNumDisplayStyleGapMin : OpenTypeMathData::FractionNumeratorGapMin);
 129 m_denominatorGapMin = mathData->getMathConstant(primaryFont, display ? OpenTypeMathData::FractionDenomDisplayStyleGapMin : OpenTypeMathData::FractionDenominatorGapMin);
 130 m_numeratorMinShiftUp = mathData->getMathConstant(primaryFont, display ? OpenTypeMathData::FractionNumeratorDisplayStyleShiftUp : OpenTypeMathData::FractionNumeratorShiftUp);
 131 m_denominatorMinShiftDown = mathData->getMathConstant(primaryFont, display ? OpenTypeMathData::FractionDenominatorDisplayStyleShiftDown : OpenTypeMathData::FractionDenominatorShiftDown);
 132 } else {
 133 // The MATH table specification suggests default rule thickness or (in displaystyle) 3 times default rule thickness for the gaps.
 134 m_numeratorGapMin = m_denominatorGapMin = display ? 3 * ruleThicknessFallback() : ruleThicknessFallback();
 135
 136 // The MATH table specification does not suggest any values for shifts, so we leave them at zero.
 137 m_numeratorMinShiftUp = m_denominatorMinShiftDown = 0;
 138 }
126139 }
127140
128141 // Parse alignment attributes.

@@void RenderMathMLFraction::layoutBlock(bool relayoutChildren, LayoutUnit)
202215 numerator().setLocation(numeratorLocation);
203216
204217 LayoutUnit numeratorAscent = ascentForChild(numerator());
205  verticalOffset += std::max(numerator().logicalHeight() + m_numeratorGapMin + m_lineThickness / 2, numeratorAscent + m_numeratorMinShiftUp); // This is the middle of the fraction bar.
206  m_ascent = verticalOffset + mathAxisHeight();
207 
 218 LayoutUnit numeratorDescent = numerator().logicalHeight() - numeratorAscent;
208219 LayoutUnit denominatorAscent = ascentForChild(denominator());
209220 LayoutUnit denominatorDescent = denominator().logicalHeight() - denominatorAscent;
210  verticalOffset += std::max(m_lineThickness / 2 + m_denominatorGapMin, m_denominatorMinShiftDown - denominatorAscent);
 221 if (isStack()) {
 222 LayoutUnit topShiftUp = m_topShiftUp;
 223 LayoutUnit bottomShiftDown = m_bottomShiftDown;
 224 LayoutUnit gap = topShiftUp - numeratorDescent + bottomShiftDown - denominatorAscent;
 225 if (gap < m_gapMin) {
 226 // If the gap is not large enough, we increase the shifts by the same value.
 227 LayoutUnit delta = (m_gapMin - gap) / 2;
 228 topShiftUp += delta;
 229 bottomShiftDown += delta;
 230 }
 231 verticalOffset += numeratorAscent + topShiftUp; // This is the middle of the stack gap.
 232 m_ascent = verticalOffset + mathAxisHeight();
 233 verticalOffset += bottomShiftDown - denominatorAscent;
 234 } else {
 235 verticalOffset += std::max(numerator().logicalHeight() + m_numeratorGapMin + m_lineThickness / 2, numeratorAscent + m_numeratorMinShiftUp); // This is the middle of the fraction bar.
 236 m_ascent = verticalOffset + mathAxisHeight();
 237 verticalOffset += std::max(m_lineThickness / 2 + m_denominatorGapMin, m_denominatorMinShiftDown - denominatorAscent);
 238 }
 239
211240 LayoutPoint denominatorLocation(horizontalOffset(denominator(), m_denominatorAlign), verticalOffset);
212241 denominator().setLocation(denominatorLocation);
213242

@@void RenderMathMLFraction::layoutBlock(bool relayoutChildren, LayoutUnit)
220249void RenderMathMLFraction::paint(PaintInfo& info, const LayoutPoint& paintOffset)
221250{
222251 RenderMathMLBlock::paint(info, paintOffset);
223  if (info.context().paintingDisabled() || info.phase != PaintPhaseForeground || style().visibility() != VISIBLE || !isValid())
 252 if (info.context().paintingDisabled() || info.phase != PaintPhaseForeground || style().visibility() != VISIBLE || !isValid() || isStack())
224253 return;
225254
226255 IntPoint adjustedPaintOffset = roundedIntPoint(paintOffset + location() + LayoutPoint(0, m_ascent - mathAxisHeight()));

Source/WebCore/rendering/mathml/RenderMathMLFraction.h

@@private:
5757 RenderMathMLOperator* unembellishedOperator() final;
5858 void styleDidChange(StyleDifference, const RenderStyle* oldStyle) final;
5959
 60 bool isStack() const { return !m_lineThickness; }
6061 bool isValid() const;
6162 RenderBox& numerator() const;
6263 RenderBox& denominator() const;

@@private:
7172 LayoutUnit m_ascent;
7273 LayoutUnit m_defaultLineThickness = 1;
7374 LayoutUnit m_lineThickness;
74  LayoutUnit m_numeratorGapMin;
 75 union {
 76 LayoutUnit m_numeratorGapMin;
 77 LayoutUnit m_gapMin;
 78 };
7579 LayoutUnit m_denominatorGapMin;
76  LayoutUnit m_numeratorMinShiftUp;
77  LayoutUnit m_denominatorMinShiftDown;
7880 FractionAlignment m_numeratorAlign = FractionAlignmentCenter;
7981 FractionAlignment m_denominatorAlign = FractionAlignmentCenter;
 82 union {
 83 LayoutUnit m_numeratorMinShiftUp;
 84 LayoutUnit m_topShiftUp;
 85 };
 86 union {
 87 LayoutUnit m_denominatorMinShiftDown;
 88 LayoutUnit m_bottomShiftDown;
 89 };
8090};
8191
8292} // namespace WebCore