MathML operators not stretched horizontally
authorfred.wang@free.fr <fred.wang@free.fr@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 5 Jun 2014 06:35:04 +0000 (06:35 +0000)
committerfred.wang@free.fr <fred.wang@free.fr@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 5 Jun 2014 06:35:04 +0000 (06:35 +0000)
https://bugs.webkit.org/show_bug.cgi?id=72828

Reviewed by Chris Fleizach.

Source/WebCore:
This patch adds basic horizontal stretching rules for operators inside
an <munder>, <mover> or <munderover> elements. The stretchy operators
in such an element stretch to cover the size of the non-stretchy
operators. This only works when fonts that have an OpenType MATH table
are used.

Tests: mathml/opentype/horizontal-LatinModern.html
       mathml/opentype/opentype-stretchy-horizontal.html
       mathml/opentype/horizontal-LatinModern-munderover.html

* rendering/mathml/RenderMathMLOperator.cpp:
(WebCore::MathMLOperatorDictionary::ExtractKeyHorizontal): We add an ordered list of operators that have horizontal stretch direction.
(WebCore::RenderMathMLOperator::RenderMathMLOperator): init m_Vertical
(WebCore::RenderMathMLOperator::SetOperatorProperties): set m_Vertical by checking whether the operator is in the horizontalOperators list.
(WebCore::RenderMathMLOperator::stretchTo): We do not stretch vertically
if the operator has horizontal direction.
We also add a new version stretchTo(LayoutUnit width) for horizontal stretching only.
(WebCore::RenderMathMLOperator::computePreferredLogicalWidths): Handle horizontal stretching: the maximumGlyphWidth is the maximum of
the base size or of the stretch size.
(WebCore::RenderMathMLOperator::getDisplayStyleLargeOperator): Add an ASSERT to ensure that this function is only called for vertical stretching.
(WebCore::RenderMathMLOperator::findStretchyData): Add an ASSERT to ensure that this function is not called to get the maximum width of a horizontal stretchy operator.
We take into account m_isVertical when calling getMathVariants or computing sizes.
There is not any Unicode-only construction for horizontal stretching, so a MATH table is required for horizontal stretching.
(WebCore::RenderMathMLOperator::updateStyle): Ignore some code paths specific to vertical stretching and take into account the m_Vertical parameters.
For horizontal stretching, the m_stretch*Baseline parameters are now updated to match the metrics of the size variant or of the maximum of the parts in the glyph assembly.
(WebCore::RenderMathMLOperator::computeLogicalHeight): logicalHeight is now explicitely the sum of m_stretchHeightAboveBaseline and m_stretchDepthBelowBaseline, since it can be different from the stretchSize() in horizontal stretching.
(WebCore::RenderMathMLOperator::paintGlyph): handle trimming for horizontal stretching.
(WebCore::RenderMathMLOperator::fillWithVerticalExtensionGlyph): rename the function and ensure it is only call for m_isVertical.
(WebCore::RenderMathMLOperator::fillWithHorizontalExtensionGlyph): same as fillWithVerticalExtensionGlyph, but for horizontal stretching.
(WebCore::RenderMathMLOperator::paint): For glyph assembly, choose between paintVerticalGlyphAssembly or paintHorizontalGlyphAssembly.
(WebCore::RenderMathMLOperator::paintVerticalGlyphAssembly): rename the function and ensure it is only call for m_isVertical.
(WebCore::RenderMathMLOperator::paintHorizontalGlyphAssembly): same as paintVerticalGlyphAssembly but for horizontal stretching.
* rendering/mathml/RenderMathMLOperator.h: we add a m_isVertical member to indicate the stretch direction and a m_stretchWidth to indicate the width of the stretchy character.
We define the horizontal counterparts of fillWith*ExtensionGlyph, paint*GlyphAssembly, GlyphPaintTrimming  StretchyData.
Finally stretchSize() takes into account the stretch direction.
* rendering/mathml/RenderMathMLUnderOver.cpp: We override the layout() function to stretch munderover children horizontally.
(WebCore::RenderMathMLUnderOver::layout):
* rendering/mathml/RenderMathMLUnderOver.h: we declare layout().

LayoutTests:
Add some tests to verify horizontal stretching with the MATH data.

* mathml/opentype/horizontal-LatinModern-munderover.html: Added.
* mathml/opentype/horizontal-LatinModern.html: Added.
* mathml/opentype/opentype-stretchy-horizontal.html: Added.
* platform/efl/TestExpectations: mark tests as failing.
* platform/gtk/mathml/opentype/horizontal-LatinModern-expected.png: Added.
* platform/gtk/mathml/opentype/horizontal-LatinModern-expected.txt: Added.
* platform/gtk/mathml/opentype/horizontal-LatinModern-munderover-expected.png: Added.
* platform/gtk/mathml/opentype/horizontal-LatinModern-munderover-expected.txt: Added.
* platform/gtk/mathml/opentype/opentype-stretchy-horizontal-expected.png: Added.
* platform/gtk/mathml/opentype/opentype-stretchy-horizontal-expected.txt: Added.
* platform/mac/TestExpectations: mark tests as failing.
* platform/win/TestExpectations: ditto.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@169607 268f45cc-cd09-0410-ab3c-d52691b4dbfc

18 files changed:
LayoutTests/ChangeLog
LayoutTests/mathml/opentype/horizontal-LatinModern-munderover.html [new file with mode: 0644]
LayoutTests/mathml/opentype/horizontal-LatinModern.html [new file with mode: 0644]
LayoutTests/mathml/opentype/opentype-stretchy-horizontal.html [new file with mode: 0644]
LayoutTests/platform/efl/TestExpectations
LayoutTests/platform/gtk/mathml/opentype/horizontal-LatinModern-expected.png [new file with mode: 0644]
LayoutTests/platform/gtk/mathml/opentype/horizontal-LatinModern-expected.txt [new file with mode: 0644]
LayoutTests/platform/gtk/mathml/opentype/horizontal-LatinModern-munderover-expected.png [new file with mode: 0644]
LayoutTests/platform/gtk/mathml/opentype/horizontal-LatinModern-munderover-expected.txt [new file with mode: 0644]
LayoutTests/platform/gtk/mathml/opentype/opentype-stretchy-horizontal-expected.png [new file with mode: 0644]
LayoutTests/platform/gtk/mathml/opentype/opentype-stretchy-horizontal-expected.txt [new file with mode: 0644]
LayoutTests/platform/mac/TestExpectations
LayoutTests/platform/win/TestExpectations
Source/WebCore/ChangeLog
Source/WebCore/rendering/mathml/RenderMathMLOperator.cpp
Source/WebCore/rendering/mathml/RenderMathMLOperator.h
Source/WebCore/rendering/mathml/RenderMathMLUnderOver.cpp
Source/WebCore/rendering/mathml/RenderMathMLUnderOver.h

index e87e080..797daa3 100644 (file)
@@ -1,3 +1,25 @@
+2014-06-05  Frédéric Wang  <fred.wang@free.fr>
+
+        MathML operators not stretched horizontally
+        https://bugs.webkit.org/show_bug.cgi?id=72828
+
+        Reviewed by Chris Fleizach.
+
+        Add some tests to verify horizontal stretching with the MATH data.
+
+        * mathml/opentype/horizontal-LatinModern-munderover.html: Added.
+        * mathml/opentype/horizontal-LatinModern.html: Added.
+        * mathml/opentype/opentype-stretchy-horizontal.html: Added.
+        * platform/efl/TestExpectations: mark tests as failing.
+        * platform/gtk/mathml/opentype/horizontal-LatinModern-expected.png: Added.
+        * platform/gtk/mathml/opentype/horizontal-LatinModern-expected.txt: Added.
+        * platform/gtk/mathml/opentype/horizontal-LatinModern-munderover-expected.png: Added.
+        * platform/gtk/mathml/opentype/horizontal-LatinModern-munderover-expected.txt: Added.
+        * platform/gtk/mathml/opentype/opentype-stretchy-horizontal-expected.png: Added.
+        * platform/gtk/mathml/opentype/opentype-stretchy-horizontal-expected.txt: Added.
+        * platform/mac/TestExpectations: mark tests as failing.
+        * platform/win/TestExpectations: ditto.
+
 2014-06-04  Bem Jones-Bey  <bjonesbe@adobe.com>
 
         [CSS Shapes] Image lifetime is not properly handled for gradient shapes
diff --git a/LayoutTests/mathml/opentype/horizontal-LatinModern-munderover.html b/LayoutTests/mathml/opentype/horizontal-LatinModern-munderover.html
new file mode 100644 (file)
index 0000000..b50fd6c
--- /dev/null
@@ -0,0 +1,59 @@
+<!doctype html>
+<html> 
+  <head>
+    <title>Large Operator Latin Modern</title>
+    <meta charset="utf-8"/>
+    <style type="text/css">
+      @font-face {
+      font-family: "Latin Modern Math";
+      src: local("Latin Modern Math"), local("LatinModernMath-Regular"), url("latinmodern-math.woff");
+      }
+      math {
+        font-family: "Latin Modern Math";
+      }      
+    </style>
+  </head>
+  <body>
+
+    <!-- We test various munderover constructions. All the horizontal braces
+         should stretch to cover the size of the red rectangle. -->
+    <p>
+      <math>
+        <mstyle scriptsizemultiplier="1">
+          <mover><mo stretchy="true">&#x23DE;</mo><mspace mathbackground="red" height="2px" width="4em"/></mover>
+        </mstyle>
+      </math>
+      <math>
+        <mstyle scriptsizemultiplier="1">
+          <mover><mspace mathbackground="red" height="2px" width="4em"/><mo stretchy="true">&#x23DE;</mo></mover>
+        </mstyle>
+      </math>
+      <math>
+        <mstyle scriptsizemultiplier="1">
+          <munder><mo stretchy="true">&#x23DE;</mo><mspace mathbackground="red" height="2px" width="4em"/></munder>
+        </mstyle>
+      </math>
+      <math>
+        <mstyle scriptsizemultiplier="1">
+          <munderover><mspace mathbackground="red" height="2px" width="4em"/><mo stretchy="true">&#x23DE;</mo><mo stretchy="true">&#x23DE;</mo></munderover>
+        </mstyle>
+      </math>
+      <math>
+        <mstyle scriptsizemultiplier="1">
+          <munderover><mo stretchy="true">&#x23DE;</mo><mspace mathbackground="red" height="2px" width="4em"/><mo stretchy="true">&#x23DE;</mo></munderover>
+        </mstyle>
+      </math>
+      <math>
+        <mstyle scriptsizemultiplier="1">
+          <munderover><mo stretchy="true">&#x23DE;</mo><mo stretchy="true">&#x23DE;</mo><mspace mathbackground="red" height="2px" width="4em"/></munderover>
+        </mstyle>
+      </math>
+      <math>
+        <mstyle scriptsizemultiplier="1">
+          <munder><mover><mo stretchy="true">&#x23DE;</mo><mspace mathbackground="red" height="2px" width="4em"/></mover><mo stretchy="true">&#x23DE;</mo></munder>
+        </mstyle>
+      </math>
+    </p>
+
+  </body>
+</html>
diff --git a/LayoutTests/mathml/opentype/horizontal-LatinModern.html b/LayoutTests/mathml/opentype/horizontal-LatinModern.html
new file mode 100644 (file)
index 0000000..2182aa4
--- /dev/null
@@ -0,0 +1,88 @@
+<!doctype html>
+<html> 
+  <head>
+    <title>Large Operator Latin Modern</title>
+    <meta charset="utf-8"/>
+    <style type="text/css">
+      @font-face {
+      font-family: "Latin Modern Math";
+      src: local("Latin Modern Math"), local("LatinModernMath-Regular"), url("latinmodern-math.woff");
+      }
+      math {
+      font-family: "Latin Modern Math";
+      }      
+    </style>
+  </head>
+  <body>
+
+    <!-- We test various horizontal operators. They should stretch to cover the
+         size of the <mspace> element. -->
+
+    <p>
+      <math><mover><mspace width="22px" height="2px" mathbackground="blue"/><mo stretchy="true">&#x2190;</mo></mover></math>
+      <math><mover><mspace width="22px" height="2px" mathbackground="blue"/><mo stretchy="true">&#x2192;</mo></mover></math>
+      <math><mover><mspace width="22px" height="2px" mathbackground="blue"/><mo stretchy="true">&#x2194;</mo></mover></math>
+      <math><mover><mspace width="22px" height="2px" mathbackground="blue"/><mo stretchy="true">&#x21A4;</mo></mover></math>
+      <math><mover><mspace width="22px" height="2px" mathbackground="blue"/><mo stretchy="true">&#x21A6;</mo></mover></math>
+      <math><mover><mspace width="22px" height="2px" mathbackground="blue"/><mo stretchy="true">&#x21BC;</mo></mover></math>
+      <math><mover><mspace width="22px" height="2px" mathbackground="blue"/><mo stretchy="true">&#x21BD;</mo></mover></math>
+      <math><mover><mspace width="22px" height="2px" mathbackground="blue"/><mo stretchy="true">&#x21C0;</mo></mover></math>
+      <math><mover><mspace width="22px" height="2px" mathbackground="blue"/><mo stretchy="true">&#x21D0;</mo></mover></math>
+      <math><mover><mspace width="22px" height="2px" mathbackground="blue"/><mo stretchy="true">&#x21D2;</mo></mover></math>
+      <math><mover><mspace width="22px" height="2px" mathbackground="blue"/><mo stretchy="true">&#x21D4;</mo></mover></math>
+      <math><mover><mspace width="22px" height="2px" mathbackground="blue"/><mo stretchy="true">&#x21DA;</mo></mover></math>
+      <math><mover><mspace width="22px" height="2px" mathbackground="blue"/><mo stretchy="true">&#x21DB;</mo></mover></math>
+      <math><mover><mspace width="22px" height="2px" mathbackground="blue"/><mo stretchy="true">&#x23B4;</mo></mover></math>
+      <math><mover><mspace width="22px" height="2px" mathbackground="blue"/><mo stretchy="true">&#x23B5;</mo></mover></math>
+      <math><mover><mspace width="22px" height="2px" mathbackground="blue"/><mo stretchy="true">&#x23DC;</mo></mover></math>
+      <math><mover><mspace width="22px" height="2px" mathbackground="blue"/><mo stretchy="true">&#x23DD;</mo></mover></math>
+      <math><mover><mspace width="22px" height="2px" mathbackground="blue"/><mo stretchy="true">&#x23DE;</mo></mover></math>
+      <math><mover><mspace width="22px" height="2px" mathbackground="blue"/><mo stretchy="true">&#x23DF;</mo></mover></math>
+    </p>
+
+    <p>
+      <math><mover><mspace width="50px" height="2px" mathbackground="green"/><mo stretchy="true">&#x2190;</mo></mover></math>
+      <math><mover><mspace width="50px" height="2px" mathbackground="green"/><mo stretchy="true">&#x2192;</mo></mover></math>
+      <math><mover><mspace width="50px" height="2px" mathbackground="green"/><mo stretchy="true">&#x2194;</mo></mover></math>
+      <math><mover><mspace width="50px" height="2px" mathbackground="green"/><mo stretchy="true">&#x21A4;</mo></mover></math>
+      <math><mover><mspace width="50px" height="2px" mathbackground="green"/><mo stretchy="true">&#x21A6;</mo></mover></math>
+      <math><mover><mspace width="50px" height="2px" mathbackground="green"/><mo stretchy="true">&#x21BC;</mo></mover></math>
+      <math><mover><mspace width="50px" height="2px" mathbackground="green"/><mo stretchy="true">&#x21BD;</mo></mover></math>
+      <math><mover><mspace width="50px" height="2px" mathbackground="green"/><mo stretchy="true">&#x21C0;</mo></mover></math>
+      <math><mover><mspace width="50px" height="2px" mathbackground="green"/><mo stretchy="true">&#x21D0;</mo></mover></math>
+      <math><mover><mspace width="50px" height="2px" mathbackground="green"/><mo stretchy="true">&#x21D2;</mo></mover></math>
+      <math><mover><mspace width="50px" height="2px" mathbackground="green"/><mo stretchy="true">&#x21D4;</mo></mover></math>
+      <math><mover><mspace width="50px" height="2px" mathbackground="green"/><mo stretchy="true">&#x21DA;</mo></mover></math>
+      <math><mover><mspace width="50px" height="2px" mathbackground="green"/><mo stretchy="true">&#x21DB;</mo></mover></math>
+      <math><mover><mspace width="50px" height="2px" mathbackground="green"/><mo stretchy="true">&#x23B4;</mo></mover></math>
+      <math><mover><mspace width="50px" height="2px" mathbackground="green"/><mo stretchy="true">&#x23B5;</mo></mover></math>
+      <math><mover><mspace width="50px" height="2px" mathbackground="green"/><mo stretchy="true">&#x23DC;</mo></mover></math>
+      <math><mover><mspace width="50px" height="2px" mathbackground="green"/><mo stretchy="true">&#x23DD;</mo></mover></math>
+      <math><mover><mspace width="50px" height="2px" mathbackground="green"/><mo stretchy="true">&#x23DE;</mo></mover></math>
+      <math><mover><mspace width="50px" height="2px" mathbackground="green"/><mo stretchy="true">&#x23DF;</mo></mover></math>
+    </p>
+
+    <p>
+      <math><mover><mspace width="100px" height="2px" mathbackground="red"/><mo stretchy="true">&#x2190;</mo></mover></math>
+      <math><mover><mspace width="100px" height="2px" mathbackground="red"/><mo stretchy="true">&#x2192;</mo></mover></math>
+      <math><mover><mspace width="100px" height="2px" mathbackground="red"/><mo stretchy="true">&#x2194;</mo></mover></math>
+      <math><mover><mspace width="100px" height="2px" mathbackground="red"/><mo stretchy="true">&#x21A4;</mo></mover></math>
+      <math><mover><mspace width="100px" height="2px" mathbackground="red"/><mo stretchy="true">&#x21A6;</mo></mover></math>
+      <math><mover><mspace width="100px" height="2px" mathbackground="red"/><mo stretchy="true">&#x21BC;</mo></mover></math>
+      <math><mover><mspace width="100px" height="2px" mathbackground="red"/><mo stretchy="true">&#x21BD;</mo></mover></math>
+      <math><mover><mspace width="100px" height="2px" mathbackground="red"/><mo stretchy="true">&#x21C0;</mo></mover></math>
+      <math><mover><mspace width="100px" height="2px" mathbackground="red"/><mo stretchy="true">&#x21D0;</mo></mover></math>
+      <math><mover><mspace width="100px" height="2px" mathbackground="red"/><mo stretchy="true">&#x21D2;</mo></mover></math>
+      <math><mover><mspace width="100px" height="2px" mathbackground="red"/><mo stretchy="true">&#x21D4;</mo></mover></math>
+      <math><mover><mspace width="100px" height="2px" mathbackground="red"/><mo stretchy="true">&#x21DA;</mo></mover></math>
+      <math><mover><mspace width="100px" height="2px" mathbackground="red"/><mo stretchy="true">&#x21DB;</mo></mover></math>
+      <math><mover><mspace width="100px" height="2px" mathbackground="red"/><mo stretchy="true">&#x23B4;</mo></mover></math>
+      <math><mover><mspace width="100px" height="2px" mathbackground="red"/><mo stretchy="true">&#x23B5;</mo></mover></math>
+      <math><mover><mspace width="100px" height="2px" mathbackground="red"/><mo stretchy="true">&#x23DC;</mo></mover></math>
+      <math><mover><mspace width="100px" height="2px" mathbackground="red"/><mo stretchy="true">&#x23DD;</mo></mover></math>
+      <math><mover><mspace width="100px" height="2px" mathbackground="red"/><mo stretchy="true">&#x23DE;</mo></mover></math>
+      <math><mover><mspace width="100px" height="2px" mathbackground="red"/><mo stretchy="true">&#x23DF;</mo></mover></math>
+    </p>
+
+  </body>
+</html>
diff --git a/LayoutTests/mathml/opentype/opentype-stretchy-horizontal.html b/LayoutTests/mathml/opentype/opentype-stretchy-horizontal.html
new file mode 100644 (file)
index 0000000..1a532a5
--- /dev/null
@@ -0,0 +1,46 @@
+<!doctype html>
+<html>
+  <head>
+    <title>Open Type MATH - stretchy operator</title>
+    <meta charset="utf-8"/>
+    <style type="text/css">
+      /* This font is taken from Mozilla's test suite. */
+      @font-face {
+        font-family: stretchy;
+        src: url("stretchy.woff");
+      }
+      math {
+        font-family: stretchy;
+        font-size: 10px;
+      }
+    </style>
+  </head>
+  <body>
+
+    <!-- This checks various vertical size variants. -->
+    <p>
+      <math>
+        <mstyle scriptsizemultiplier="1">
+          <mover><mo stretchy="true">&#x219C;</mo><mspace width="1em" height="1px"/></mover>
+        </mstyle>
+      </math>
+    </p>
+    <p>
+      <math>
+        <mstyle scriptsizemultiplier="1">
+          <mover><mo stretchy="true">&#x219C;</mo><mspace width="2em" height="1px"/></mover>
+        </mstyle>
+      </math>
+    </p>
+
+    <!-- This checks vertical glyph assembly. -->
+    <p>
+      <math>
+        <mstyle scriptsizemultiplier="1">
+          <mover><mo stretchy="true">&#x219C;</mo><mspace width="20em" height="1px"/></mover>
+        </mstyle>
+      </math>
+    </p>
+
+  </body>
+</html>
index 5d8ed3c..d71abce 100644 (file)
@@ -1626,3 +1626,11 @@ webkit.org/b/133146 fast/sub-pixel/client-rect-has-subpixel-precision.html [ Ima
 webkit.org/b/133307 fast/forms/number/number-spinbutton-in-multi-column.html [ Failure ]
 
 webkit.org/b/133308 fast/selectors/hover-quirks.html [ Failure ]
+
+# Missing or bad references
+webkit.org/b/130322 mathml/opentype/large-operators-LatinModern.html [ Failure ]
+webkit.org/b/130322 mathml/opentype/opentype-stretchy.html [ Failure ]
+webkit.org/b/130322 mathml/opentype/vertical-LatinModern.html [ Failure ]
+webkit.org/b/72828 mathml/opentype/horizontal-LatinModern.html [ Failure ]
+webkit.org/b/72828 mathml/opentype/opentype-stretchy-horizontal.html [ Failure ]
+webkit.org/b/72828 mathml/opentype/horizontal-LatinModern-munderover.html [ Failure ]
diff --git a/LayoutTests/platform/gtk/mathml/opentype/horizontal-LatinModern-expected.png b/LayoutTests/platform/gtk/mathml/opentype/horizontal-LatinModern-expected.png
new file mode 100644 (file)
index 0000000..da1b2c1
Binary files /dev/null and b/LayoutTests/platform/gtk/mathml/opentype/horizontal-LatinModern-expected.png differ
diff --git a/LayoutTests/platform/gtk/mathml/opentype/horizontal-LatinModern-expected.txt b/LayoutTests/platform/gtk/mathml/opentype/horizontal-LatinModern-expected.txt
new file mode 100644 (file)
index 0000000..2e87e38
--- /dev/null
@@ -0,0 +1,572 @@
+layer at (0,0) size 800x600
+  RenderView at (0,0) size 800x600
+layer at (0,0) size 800x166
+  RenderBlock {HTML} at (0,0) size 800x166
+    RenderBody {BODY} at (8,16) size 784x134
+      RenderBlock {P} at (0,0) size 784x17
+        RenderMathMLMath {math} at (0,4) size 31x10 [padding: 0 1 0 1]
+          RenderMathMLUnderOver {mover} at (1,0) size 29x10
+            RenderMathMLSpace {mspace} at (3,8) size 23x2 [bgcolor=#0000FF]
+            RenderMathMLOperator {mo} at (-4,0) size 36x8
+              RenderMathMLBlock (anonymous, flex) at (3,0) size 29x8
+                RenderBlock (anonymous) at (0,0) size 12x8
+                  RenderText at (0,-36) size 12x80
+                    text run at (0,-36) width 12: "\x{2190}"
+        RenderText {#text} at (30,0) size 5x17
+          text run at (30,0) width 5: " "
+        RenderMathMLMath {math} at (34,4) size 32x10 [padding: 0 1 0 1]
+          RenderMathMLUnderOver {mover} at (1,0) size 29x10
+            RenderMathMLSpace {mspace} at (3,8) size 23x2 [bgcolor=#0000FF]
+            RenderMathMLOperator {mo} at (-4,0) size 36x8
+              RenderMathMLBlock (anonymous, flex) at (3,0) size 29x8
+                RenderBlock (anonymous) at (0,0) size 12x8
+                  RenderText at (0,-36) size 12x80
+                    text run at (0,-36) width 12: "\x{2192}"
+        RenderText {#text} at (65,0) size 5x17
+          text run at (65,0) width 5: " "
+        RenderMathMLMath {math} at (69,4) size 31x10 [padding: 0 1 0 1]
+          RenderMathMLUnderOver {mover} at (1,0) size 29x10
+            RenderMathMLSpace {mspace} at (3,8) size 23x2 [bgcolor=#0000FF]
+            RenderMathMLOperator {mo} at (-4,0) size 36x8
+              RenderMathMLBlock (anonymous, flex) at (3,0) size 29x8
+                RenderBlock (anonymous) at (0,0) size 12x8
+                  RenderText at (0,-36) size 12x80
+                    text run at (0,-36) width 12: "\x{2194}"
+        RenderText {#text} at (99,0) size 5x17
+          text run at (99,0) width 5: " "
+        RenderMathMLMath {math} at (103,4) size 32x10 [padding: 0 1 0 1]
+          RenderMathMLUnderOver {mover} at (1,0) size 29x10
+            RenderMathMLSpace {mspace} at (3,8) size 23x2 [bgcolor=#0000FF]
+            RenderMathMLOperator {mo} at (-4,0) size 36x8
+              RenderMathMLBlock (anonymous, flex) at (3,0) size 29x8
+                RenderBlock (anonymous) at (0,0) size 12x8
+                  RenderText at (0,-36) size 12x80
+                    text run at (0,-36) width 12: "\x{21A4}"
+        RenderText {#text} at (134,0) size 5x17
+          text run at (134,0) width 5: " "
+        RenderMathMLMath {math} at (138,4) size 32x10 [padding: 0 1 0 1]
+          RenderMathMLUnderOver {mover} at (1,0) size 29x10
+            RenderMathMLSpace {mspace} at (3,8) size 23x2 [bgcolor=#0000FF]
+            RenderMathMLOperator {mo} at (-4,0) size 36x8
+              RenderMathMLBlock (anonymous, flex) at (3,0) size 29x8
+                RenderBlock (anonymous) at (0,0) size 12x8
+                  RenderText at (0,-36) size 12x80
+                    text run at (0,-36) width 12: "\x{21A6}"
+        RenderText {#text} at (169,0) size 5x17
+          text run at (169,0) width 5: " "
+        RenderMathMLMath {math} at (173,5) size 31x9 [padding: 0 1 0 1]
+          RenderMathMLUnderOver {mover} at (1,0) size 29x9
+            RenderMathMLSpace {mspace} at (3,7) size 23x2 [bgcolor=#0000FF]
+            RenderMathMLOperator {mo} at (-4,0) size 36x7
+              RenderMathMLBlock (anonymous, flex) at (3,0) size 29x7
+                RenderBlock (anonymous) at (0,0) size 12x7
+                  RenderText at (0,-36) size 12x80
+                    text run at (0,-36) width 12: "\x{21BC}"
+        RenderText {#text} at (203,0) size 5x17
+          text run at (203,0) width 5: " "
+        RenderMathMLMath {math} at (207,7) size 32x7 [padding: 0 1 0 1]
+          RenderMathMLUnderOver {mover} at (1,0) size 29x7
+            RenderMathMLSpace {mspace} at (3,5) size 23x2 [bgcolor=#0000FF]
+            RenderMathMLOperator {mo} at (-4,0) size 36x5
+              RenderMathMLBlock (anonymous, flex) at (3,0) size 29x5
+                RenderBlock (anonymous) at (0,0) size 12x5
+                  RenderText at (0,-39) size 12x80
+                    text run at (0,-39) width 12: "\x{21BD}"
+        RenderText {#text} at (238,0) size 5x17
+          text run at (238,0) width 5: " "
+        RenderMathMLMath {math} at (242,5) size 32x9 [padding: 0 1 0 1]
+          RenderMathMLUnderOver {mover} at (1,0) size 29x9
+            RenderMathMLSpace {mspace} at (3,7) size 23x2 [bgcolor=#0000FF]
+            RenderMathMLOperator {mo} at (-4,0) size 36x7
+              RenderMathMLBlock (anonymous, flex) at (3,0) size 29x7
+                RenderBlock (anonymous) at (0,0) size 12x7
+                  RenderText at (0,-36) size 12x80
+                    text run at (0,-36) width 12: "\x{21C0}"
+        RenderText {#text} at (273,0) size 5x17
+          text run at (273,0) width 5: " "
+        RenderMathMLMath {math} at (277,4) size 31x10 [padding: 0 1 0 1]
+          RenderMathMLUnderOver {mover} at (1,0) size 29x10
+            RenderMathMLSpace {mspace} at (3,8) size 23x2 [bgcolor=#0000FF]
+            RenderMathMLOperator {mo} at (-4,0) size 36x8
+              RenderMathMLBlock (anonymous, flex) at (3,0) size 29x8
+                RenderBlock (anonymous) at (0,0) size 12x8
+                  RenderText at (0,-36) size 12x80
+                    text run at (0,-36) width 12: "\x{21D0}"
+        RenderText {#text} at (307,0) size 5x17
+          text run at (307,0) width 5: " "
+        RenderMathMLMath {math} at (311,4) size 32x10 [padding: 0 1 0 1]
+          RenderMathMLUnderOver {mover} at (1,0) size 29x10
+            RenderMathMLSpace {mspace} at (3,8) size 23x2 [bgcolor=#0000FF]
+            RenderMathMLOperator {mo} at (-4,0) size 36x8
+              RenderMathMLBlock (anonymous, flex) at (3,0) size 29x8
+                RenderBlock (anonymous) at (0,0) size 12x8
+                  RenderText at (0,-36) size 12x80
+                    text run at (0,-36) width 12: "\x{21D2}"
+        RenderText {#text} at (342,0) size 5x17
+          text run at (342,0) width 5: " "
+        RenderMathMLMath {math} at (346,4) size 32x10 [padding: 0 1 0 1]
+          RenderMathMLUnderOver {mover} at (1,0) size 29x10
+            RenderMathMLSpace {mspace} at (3,8) size 23x2 [bgcolor=#0000FF]
+            RenderMathMLOperator {mo} at (-4,0) size 36x8
+              RenderMathMLBlock (anonymous, flex) at (3,0) size 29x8
+                RenderBlock (anonymous) at (0,0) size 12x8
+                  RenderText at (0,-36) size 12x80
+                    text run at (0,-36) width 12: "\x{21D4}"
+        RenderText {#text} at (377,0) size 5x17
+          text run at (377,0) width 5: " "
+        RenderMathMLMath {math} at (381,2) size 31x12 [padding: 0 1 0 1]
+          RenderMathMLUnderOver {mover} at (1,0) size 29x12
+            RenderMathMLSpace {mspace} at (3,10) size 23x2 [bgcolor=#0000FF]
+            RenderMathMLOperator {mo} at (-4,0) size 36x10
+              RenderMathMLBlock (anonymous, flex) at (3,0) size 29x10
+                RenderBlock (anonymous) at (0,0) size 12x10
+                  RenderText at (0,-35) size 12x80
+                    text run at (0,-35) width 12: "\x{21DA}"
+        RenderText {#text} at (411,0) size 5x17
+          text run at (411,0) width 5: " "
+        RenderMathMLMath {math} at (415,2) size 32x12 [padding: 0 1 0 1]
+          RenderMathMLUnderOver {mover} at (1,0) size 29x12
+            RenderMathMLSpace {mspace} at (3,10) size 23x2 [bgcolor=#0000FF]
+            RenderMathMLOperator {mo} at (-4,0) size 36x10
+              RenderMathMLBlock (anonymous, flex) at (3,0) size 29x10
+                RenderBlock (anonymous) at (0,0) size 12x10
+                  RenderText at (0,-35) size 12x80
+                    text run at (0,-35) width 12: "\x{21DB}"
+        RenderText {#text} at (446,0) size 5x17
+          text run at (446,0) width 5: " "
+        RenderMathMLMath {math} at (450,9) size 25x5 [padding: 0 1 0 1]
+          RenderMathMLUnderOver {mover} at (1,0) size 22x5
+            RenderMathMLSpace {mspace} at (0,3) size 22x2 [bgcolor=#0000FF]
+            RenderMathMLOperator {mo} at (0,0) size 22x3
+              RenderMathMLBlock (anonymous, flex) at (0,0) size 22x3
+                RenderBlock (anonymous) at (0,0) size 4x3
+                  RenderText at (0,-34) size 4x80
+                    text run at (0,-34) width 4: "\x{23B4}"
+        RenderText {#text} at (474,0) size 5x17
+          text run at (474,0) width 5: " "
+        RenderMathMLMath {math} at (478,9) size 25x5 [padding: 0 1 0 1]
+          RenderMathMLUnderOver {mover} at (1,0) size 22x5
+            RenderMathMLSpace {mspace} at (0,3) size 22x2 [bgcolor=#0000FF]
+            RenderMathMLOperator {mo} at (0,0) size 22x3
+              RenderMathMLBlock (anonymous, flex) at (0,0) size 22x3
+                RenderBlock (anonymous) at (0,0) size 4x3
+                  RenderText at (0,-43) size 4x80
+                    text run at (0,-43) width 4: "\x{23B5}"
+        RenderText {#text} at (502,0) size 5x17
+          text run at (502,0) width 5: " "
+        RenderMathMLMath {math} at (506,8) size 27x6 [padding: 0 1 0 1]
+          RenderMathMLUnderOver {mover} at (1,0) size 24x6
+            RenderMathMLSpace {mspace} at (1,4) size 22x2 [bgcolor=#0000FF]
+            RenderMathMLOperator {mo} at (0,0) size 24x4
+              RenderMathMLBlock (anonymous, flex) at (0,0) size 24x4
+                RenderBlock (anonymous) at (0,0) size 6x4
+                  RenderText at (0,-34) size 6x80
+                    text run at (0,-34) width 6: "\x{23DC}"
+        RenderText {#text} at (532,0) size 5x17
+          text run at (532,0) width 5: " "
+        RenderMathMLMath {math} at (536,7) size 27x7 [padding: 0 1 0 1]
+          RenderMathMLUnderOver {mover} at (1,0) size 24x7
+            RenderMathMLSpace {mspace} at (1,5) size 22x2 [bgcolor=#0000FF]
+            RenderMathMLOperator {mo} at (0,0) size 24x5
+              RenderMathMLBlock (anonymous, flex) at (0,0) size 24x4
+                RenderBlock (anonymous) at (0,0) size 6x4
+                  RenderText at (0,-43) size 6x80
+                    text run at (0,-43) width 6: "\x{23DD}"
+        RenderText {#text} at (562,0) size 5x17
+          text run at (562,0) width 5: " "
+        RenderMathMLMath {math} at (566,8) size 27x6 [padding: 0 1 0 1]
+          RenderMathMLUnderOver {mover} at (1,0) size 24x6
+            RenderMathMLSpace {mspace} at (1,4) size 22x2 [bgcolor=#0000FF]
+            RenderMathMLOperator {mo} at (0,0) size 24x4
+              RenderMathMLBlock (anonymous, flex) at (0,0) size 24x4
+                RenderBlock (anonymous) at (0,0) size 6x4
+                  RenderText at (0,-33) size 6x80
+                    text run at (0,-33) width 6: "\x{23DE}"
+        RenderText {#text} at (592,0) size 5x17
+          text run at (592,0) width 5: " "
+        RenderMathMLMath {math} at (596,7) size 27x7 [padding: 0 1 0 1]
+          RenderMathMLUnderOver {mover} at (1,0) size 24x7
+            RenderMathMLSpace {mspace} at (1,5) size 22x2 [bgcolor=#0000FF]
+            RenderMathMLOperator {mo} at (0,0) size 24x5
+              RenderMathMLBlock (anonymous, flex) at (0,0) size 24x5
+                RenderBlock (anonymous) at (0,0) size 6x5
+                  RenderText at (0,-43) size 6x80
+                    text run at (0,-43) width 6: "\x{23DF}"
+        RenderText {#text} at (0,0) size 0x0
+      RenderBlock {P} at (0,33) size 784x34
+        RenderMathMLMath {math} at (0,4) size 59x10 [padding: 0 1 0 1]
+          RenderMathMLUnderOver {mover} at (1,0) size 57x10
+            RenderMathMLSpace {mspace} at (3,8) size 51x2 [bgcolor=#008000]
+            RenderMathMLOperator {mo} at (-4,0) size 64x8
+              RenderMathMLBlock (anonymous, flex) at (3,0) size 57x8
+                RenderBlock (anonymous) at (0,0) size 12x8
+                  RenderText at (0,-36) size 12x80
+                    text run at (0,-36) width 12: "\x{2190}"
+        RenderText {#text} at (58,0) size 5x17
+          text run at (58,0) width 5: " "
+        RenderMathMLMath {math} at (62,4) size 60x10 [padding: 0 1 0 1]
+          RenderMathMLUnderOver {mover} at (1,0) size 57x10
+            RenderMathMLSpace {mspace} at (3,8) size 51x2 [bgcolor=#008000]
+            RenderMathMLOperator {mo} at (-4,0) size 64x8
+              RenderMathMLBlock (anonymous, flex) at (3,0) size 57x8
+                RenderBlock (anonymous) at (0,0) size 12x8
+                  RenderText at (0,-36) size 12x80
+                    text run at (0,-36) width 12: "\x{2192}"
+        RenderText {#text} at (121,0) size 5x17
+          text run at (121,0) width 5: " "
+        RenderMathMLMath {math} at (125,4) size 59x10 [padding: 0 1 0 1]
+          RenderMathMLUnderOver {mover} at (1,0) size 57x10
+            RenderMathMLSpace {mspace} at (3,8) size 51x2 [bgcolor=#008000]
+            RenderMathMLOperator {mo} at (-4,0) size 64x8
+              RenderMathMLBlock (anonymous, flex) at (3,0) size 57x8
+                RenderBlock (anonymous) at (0,0) size 12x8
+                  RenderText at (0,-36) size 12x80
+                    text run at (0,-36) width 12: "\x{2194}"
+        RenderText {#text} at (183,0) size 5x17
+          text run at (183,0) width 5: " "
+        RenderMathMLMath {math} at (187,4) size 60x10 [padding: 0 1 0 1]
+          RenderMathMLUnderOver {mover} at (1,0) size 57x10
+            RenderMathMLSpace {mspace} at (3,8) size 51x2 [bgcolor=#008000]
+            RenderMathMLOperator {mo} at (-4,0) size 64x8
+              RenderMathMLBlock (anonymous, flex) at (3,0) size 57x8
+                RenderBlock (anonymous) at (0,0) size 12x8
+                  RenderText at (0,-36) size 12x80
+                    text run at (0,-36) width 12: "\x{21A4}"
+        RenderText {#text} at (246,0) size 5x17
+          text run at (246,0) width 5: " "
+        RenderMathMLMath {math} at (250,4) size 60x10 [padding: 0 1 0 1]
+          RenderMathMLUnderOver {mover} at (1,0) size 57x10
+            RenderMathMLSpace {mspace} at (3,8) size 51x2 [bgcolor=#008000]
+            RenderMathMLOperator {mo} at (-4,0) size 64x8
+              RenderMathMLBlock (anonymous, flex) at (3,0) size 57x8
+                RenderBlock (anonymous) at (0,0) size 12x8
+                  RenderText at (0,-36) size 12x80
+                    text run at (0,-36) width 12: "\x{21A6}"
+        RenderText {#text} at (309,0) size 5x17
+          text run at (309,0) width 5: " "
+        RenderMathMLMath {math} at (313,5) size 59x9 [padding: 0 1 0 1]
+          RenderMathMLUnderOver {mover} at (1,0) size 57x9
+            RenderMathMLSpace {mspace} at (3,7) size 51x2 [bgcolor=#008000]
+            RenderMathMLOperator {mo} at (-4,0) size 64x7
+              RenderMathMLBlock (anonymous, flex) at (3,0) size 57x7
+                RenderBlock (anonymous) at (0,0) size 12x7
+                  RenderText at (0,-36) size 12x80
+                    text run at (0,-36) width 12: "\x{21BC}"
+        RenderText {#text} at (371,0) size 5x17
+          text run at (371,0) width 5: " "
+        RenderMathMLMath {math} at (375,7) size 60x7 [padding: 0 1 0 1]
+          RenderMathMLUnderOver {mover} at (1,0) size 57x7
+            RenderMathMLSpace {mspace} at (3,5) size 51x2 [bgcolor=#008000]
+            RenderMathMLOperator {mo} at (-4,0) size 64x5
+              RenderMathMLBlock (anonymous, flex) at (3,0) size 57x5
+                RenderBlock (anonymous) at (0,0) size 12x5
+                  RenderText at (0,-39) size 12x80
+                    text run at (0,-39) width 12: "\x{21BD}"
+        RenderText {#text} at (434,0) size 5x17
+          text run at (434,0) width 5: " "
+        RenderMathMLMath {math} at (438,5) size 60x9 [padding: 0 1 0 1]
+          RenderMathMLUnderOver {mover} at (1,0) size 57x9
+            RenderMathMLSpace {mspace} at (3,7) size 51x2 [bgcolor=#008000]
+            RenderMathMLOperator {mo} at (-4,0) size 64x7
+              RenderMathMLBlock (anonymous, flex) at (3,0) size 57x7
+                RenderBlock (anonymous) at (0,0) size 12x7
+                  RenderText at (0,-36) size 12x80
+                    text run at (0,-36) width 12: "\x{21C0}"
+        RenderText {#text} at (497,0) size 5x17
+          text run at (497,0) width 5: " "
+        RenderMathMLMath {math} at (501,4) size 59x10 [padding: 0 1 0 1]
+          RenderMathMLUnderOver {mover} at (1,0) size 57x10
+            RenderMathMLSpace {mspace} at (3,8) size 51x2 [bgcolor=#008000]
+            RenderMathMLOperator {mo} at (-4,0) size 64x8
+              RenderMathMLBlock (anonymous, flex) at (3,0) size 57x8
+                RenderBlock (anonymous) at (0,0) size 12x8
+                  RenderText at (0,-36) size 12x80
+                    text run at (0,-36) width 12: "\x{21D0}"
+        RenderText {#text} at (559,0) size 5x17
+          text run at (559,0) width 5: " "
+        RenderMathMLMath {math} at (563,4) size 60x10 [padding: 0 1 0 1]
+          RenderMathMLUnderOver {mover} at (1,0) size 57x10
+            RenderMathMLSpace {mspace} at (3,8) size 51x2 [bgcolor=#008000]
+            RenderMathMLOperator {mo} at (-4,0) size 64x8
+              RenderMathMLBlock (anonymous, flex) at (3,0) size 57x8
+                RenderBlock (anonymous) at (0,0) size 12x8
+                  RenderText at (0,-36) size 12x80
+                    text run at (0,-36) width 12: "\x{21D2}"
+        RenderText {#text} at (622,0) size 5x17
+          text run at (622,0) width 5: " "
+        RenderMathMLMath {math} at (626,4) size 60x10 [padding: 0 1 0 1]
+          RenderMathMLUnderOver {mover} at (1,0) size 57x10
+            RenderMathMLSpace {mspace} at (3,8) size 51x2 [bgcolor=#008000]
+            RenderMathMLOperator {mo} at (-4,0) size 64x8
+              RenderMathMLBlock (anonymous, flex) at (3,0) size 57x8
+                RenderBlock (anonymous) at (0,0) size 12x8
+                  RenderText at (0,-36) size 12x80
+                    text run at (0,-36) width 12: "\x{21D4}"
+        RenderText {#text} at (685,0) size 5x17
+          text run at (685,0) width 5: " "
+        RenderMathMLMath {math} at (689,2) size 59x12 [padding: 0 1 0 1]
+          RenderMathMLUnderOver {mover} at (1,0) size 57x12
+            RenderMathMLSpace {mspace} at (3,10) size 51x2 [bgcolor=#008000]
+            RenderMathMLOperator {mo} at (-4,0) size 64x10
+              RenderMathMLBlock (anonymous, flex) at (3,0) size 57x10
+                RenderBlock (anonymous) at (0,0) size 12x10
+                  RenderText at (0,-35) size 12x80
+                    text run at (0,-35) width 12: "\x{21DA}"
+        RenderText {#text} at (0,0) size 0x0
+        RenderMathMLMath {math} at (0,19) size 59x12 [padding: 0 1 0 1]
+          RenderMathMLUnderOver {mover} at (1,0) size 57x12
+            RenderMathMLSpace {mspace} at (3,10) size 51x2 [bgcolor=#008000]
+            RenderMathMLOperator {mo} at (-4,0) size 64x10
+              RenderMathMLBlock (anonymous, flex) at (3,0) size 57x10
+                RenderBlock (anonymous) at (0,0) size 12x10
+                  RenderText at (0,-35) size 12x80
+                    text run at (0,-35) width 12: "\x{21DB}"
+        RenderText {#text} at (58,17) size 5x17
+          text run at (58,17) width 5: " "
+        RenderMathMLMath {math} at (62,19) size 53x12 [padding: 0 1 0 1]
+          RenderMathMLUnderOver {mover} at (1,0) size 50x12
+            RenderMathMLSpace {mspace} at (0,10) size 50x2 [bgcolor=#008000]
+            RenderMathMLOperator {mo} at (0,0) size 50x10
+              RenderMathMLBlock (anonymous, flex) at (0,0) size 50x10
+                RenderBlock (anonymous) at (0,0) size 4x10
+                  RenderText at (0,-34) size 4x80
+                    text run at (0,-34) width 4: "\x{23B4}"
+        RenderText {#text} at (114,17) size 5x17
+          text run at (114,17) width 5: " "
+        RenderMathMLMath {math} at (118,24) size 53x7 [padding: 0 1 0 1]
+          RenderMathMLUnderOver {mover} at (1,0) size 50x7
+            RenderMathMLSpace {mspace} at (0,5) size 50x2 [bgcolor=#008000]
+            RenderMathMLOperator {mo} at (0,0) size 50x5
+              RenderMathMLBlock (anonymous, flex) at (0,0) size 50x4
+                RenderBlock (anonymous) at (0,0) size 4x4
+                  RenderText at (0,-43) size 4x80
+                    text run at (0,-43) width 4: "\x{23B5}"
+        RenderText {#text} at (170,17) size 5x17
+          text run at (170,17) width 5: " "
+        RenderMathMLMath {math} at (174,19) size 53x12 [padding: 0 1 0 1]
+          RenderMathMLUnderOver {mover} at (1,0) size 50x12
+            RenderMathMLSpace {mspace} at (0,10) size 50x2 [bgcolor=#008000]
+            RenderMathMLOperator {mo} at (0,0) size 50x10
+              RenderMathMLBlock (anonymous, flex) at (0,0) size 50x10
+                RenderBlock (anonymous) at (0,0) size 6x10
+                  RenderText at (0,-34) size 6x80
+                    text run at (0,-34) width 6: "\x{23DC}"
+        RenderText {#text} at (226,17) size 5x17
+          text run at (226,17) width 5: " "
+        RenderMathMLMath {math} at (230,24) size 53x7 [padding: 0 1 0 1]
+          RenderMathMLUnderOver {mover} at (1,0) size 50x7
+            RenderMathMLSpace {mspace} at (0,5) size 50x2 [bgcolor=#008000]
+            RenderMathMLOperator {mo} at (0,0) size 50x5
+              RenderMathMLBlock (anonymous, flex) at (0,0) size 50x4
+                RenderBlock (anonymous) at (0,0) size 6x4
+                  RenderText at (0,-43) size 6x80
+                    text run at (0,-43) width 6: "\x{23DD}"
+        RenderText {#text} at (282,17) size 5x17
+          text run at (282,17) width 5: " "
+        RenderMathMLMath {math} at (286,18) size 53x13 [padding: 0 1 0 1]
+          RenderMathMLUnderOver {mover} at (1,0) size 50x13
+            RenderMathMLSpace {mspace} at (0,11) size 50x2 [bgcolor=#008000]
+            RenderMathMLOperator {mo} at (0,0) size 50x11
+              RenderMathMLBlock (anonymous, flex) at (0,0) size 50x11
+                RenderBlock (anonymous) at (0,0) size 6x11
+                  RenderText at (0,-33) size 6x80
+                    text run at (0,-33) width 6: "\x{23DE}"
+        RenderText {#text} at (338,17) size 5x17
+          text run at (338,17) width 5: " "
+        RenderMathMLMath {math} at (342,23) size 53x8 [padding: 0 1 0 1]
+          RenderMathMLUnderOver {mover} at (1,0) size 50x8
+            RenderMathMLSpace {mspace} at (0,6) size 50x2 [bgcolor=#008000]
+            RenderMathMLOperator {mo} at (0,0) size 50x6
+              RenderMathMLBlock (anonymous, flex) at (0,0) size 50x5
+                RenderBlock (anonymous) at (0,0) size 6x5
+                  RenderText at (0,-43) size 6x80
+                    text run at (0,-43) width 6: "\x{23DF}"
+        RenderText {#text} at (0,0) size 0x0
+      RenderBlock {P} at (0,83) size 784x51
+        RenderMathMLMath {math} at (0,4) size 109x10 [padding: 0 1 0 1]
+          RenderMathMLUnderOver {mover} at (1,0) size 107x10
+            RenderMathMLSpace {mspace} at (3,8) size 101x2 [bgcolor=#FF0000]
+            RenderMathMLOperator {mo} at (-4,0) size 114x8
+              RenderMathMLBlock (anonymous, flex) at (3,0) size 107x8
+                RenderBlock (anonymous) at (0,0) size 12x8
+                  RenderText at (0,-36) size 12x80
+                    text run at (0,-36) width 12: "\x{2190}"
+        RenderText {#text} at (108,0) size 5x17
+          text run at (108,0) width 5: " "
+        RenderMathMLMath {math} at (112,4) size 110x10 [padding: 0 1 0 1]
+          RenderMathMLUnderOver {mover} at (1,0) size 107x10
+            RenderMathMLSpace {mspace} at (3,8) size 101x2 [bgcolor=#FF0000]
+            RenderMathMLOperator {mo} at (-4,0) size 114x8
+              RenderMathMLBlock (anonymous, flex) at (3,0) size 107x8
+                RenderBlock (anonymous) at (0,0) size 12x8
+                  RenderText at (0,-36) size 12x80
+                    text run at (0,-36) width 12: "\x{2192}"
+        RenderText {#text} at (221,0) size 5x17
+          text run at (221,0) width 5: " "
+        RenderMathMLMath {math} at (225,4) size 109x10 [padding: 0 1 0 1]
+          RenderMathMLUnderOver {mover} at (1,0) size 107x10
+            RenderMathMLSpace {mspace} at (3,8) size 101x2 [bgcolor=#FF0000]
+            RenderMathMLOperator {mo} at (-4,0) size 114x8
+              RenderMathMLBlock (anonymous, flex) at (3,0) size 107x8
+                RenderBlock (anonymous) at (0,0) size 12x8
+                  RenderText at (0,-36) size 12x80
+                    text run at (0,-36) width 12: "\x{2194}"
+        RenderText {#text} at (333,0) size 5x17
+          text run at (333,0) width 5: " "
+        RenderMathMLMath {math} at (337,4) size 110x10 [padding: 0 1 0 1]
+          RenderMathMLUnderOver {mover} at (1,0) size 107x10
+            RenderMathMLSpace {mspace} at (3,8) size 101x2 [bgcolor=#FF0000]
+            RenderMathMLOperator {mo} at (-4,0) size 114x8
+              RenderMathMLBlock (anonymous, flex) at (3,0) size 107x8
+                RenderBlock (anonymous) at (0,0) size 12x8
+                  RenderText at (0,-36) size 12x80
+                    text run at (0,-36) width 12: "\x{21A4}"
+        RenderText {#text} at (446,0) size 5x17
+          text run at (446,0) width 5: " "
+        RenderMathMLMath {math} at (450,4) size 110x10 [padding: 0 1 0 1]
+          RenderMathMLUnderOver {mover} at (1,0) size 107x10
+            RenderMathMLSpace {mspace} at (3,8) size 101x2 [bgcolor=#FF0000]
+            RenderMathMLOperator {mo} at (-4,0) size 114x8
+              RenderMathMLBlock (anonymous, flex) at (3,0) size 107x8
+                RenderBlock (anonymous) at (0,0) size 12x8
+                  RenderText at (0,-36) size 12x80
+                    text run at (0,-36) width 12: "\x{21A6}"
+        RenderText {#text} at (559,0) size 5x17
+          text run at (559,0) width 5: " "
+        RenderMathMLMath {math} at (563,5) size 109x9 [padding: 0 1 0 1]
+          RenderMathMLUnderOver {mover} at (1,0) size 107x9
+            RenderMathMLSpace {mspace} at (3,7) size 101x2 [bgcolor=#FF0000]
+            RenderMathMLOperator {mo} at (-4,0) size 114x7
+              RenderMathMLBlock (anonymous, flex) at (3,0) size 107x7
+                RenderBlock (anonymous) at (0,0) size 12x7
+                  RenderText at (0,-36) size 12x80
+                    text run at (0,-36) width 12: "\x{21BC}"
+        RenderText {#text} at (0,0) size 0x0
+        RenderMathMLMath {math} at (0,24) size 109x7 [padding: 0 1 0 1]
+          RenderMathMLUnderOver {mover} at (1,0) size 107x7
+            RenderMathMLSpace {mspace} at (3,5) size 101x2 [bgcolor=#FF0000]
+            RenderMathMLOperator {mo} at (-4,0) size 114x5
+              RenderMathMLBlock (anonymous, flex) at (3,0) size 107x5
+                RenderBlock (anonymous) at (0,0) size 12x5
+                  RenderText at (0,-39) size 12x80
+                    text run at (0,-39) width 12: "\x{21BD}"
+        RenderText {#text} at (108,17) size 5x17
+          text run at (108,17) width 5: " "
+        RenderMathMLMath {math} at (112,22) size 110x9 [padding: 0 1 0 1]
+          RenderMathMLUnderOver {mover} at (1,0) size 107x9
+            RenderMathMLSpace {mspace} at (3,7) size 101x2 [bgcolor=#FF0000]
+            RenderMathMLOperator {mo} at (-4,0) size 114x7
+              RenderMathMLBlock (anonymous, flex) at (3,0) size 107x7
+                RenderBlock (anonymous) at (0,0) size 12x7
+                  RenderText at (0,-36) size 12x80
+                    text run at (0,-36) width 12: "\x{21C0}"
+        RenderText {#text} at (221,17) size 5x17
+          text run at (221,17) width 5: " "
+        RenderMathMLMath {math} at (225,21) size 109x10 [padding: 0 1 0 1]
+          RenderMathMLUnderOver {mover} at (1,0) size 107x10
+            RenderMathMLSpace {mspace} at (3,8) size 101x2 [bgcolor=#FF0000]
+            RenderMathMLOperator {mo} at (-4,0) size 114x8
+              RenderMathMLBlock (anonymous, flex) at (3,0) size 107x8
+                RenderBlock (anonymous) at (0,0) size 12x8
+                  RenderText at (0,-36) size 12x80
+                    text run at (0,-36) width 12: "\x{21D0}"
+        RenderText {#text} at (333,17) size 5x17
+          text run at (333,17) width 5: " "
+        RenderMathMLMath {math} at (337,21) size 110x10 [padding: 0 1 0 1]
+          RenderMathMLUnderOver {mover} at (1,0) size 107x10
+            RenderMathMLSpace {mspace} at (3,8) size 101x2 [bgcolor=#FF0000]
+            RenderMathMLOperator {mo} at (-4,0) size 114x8
+              RenderMathMLBlock (anonymous, flex) at (3,0) size 107x8
+                RenderBlock (anonymous) at (0,0) size 12x8
+                  RenderText at (0,-36) size 12x80
+                    text run at (0,-36) width 12: "\x{21D2}"
+        RenderText {#text} at (446,17) size 5x17
+          text run at (446,17) width 5: " "
+        RenderMathMLMath {math} at (450,21) size 110x10 [padding: 0 1 0 1]
+          RenderMathMLUnderOver {mover} at (1,0) size 107x10
+            RenderMathMLSpace {mspace} at (3,8) size 101x2 [bgcolor=#FF0000]
+            RenderMathMLOperator {mo} at (-4,0) size 114x8
+              RenderMathMLBlock (anonymous, flex) at (3,0) size 107x8
+                RenderBlock (anonymous) at (0,0) size 12x8
+                  RenderText at (0,-36) size 12x80
+                    text run at (0,-36) width 12: "\x{21D4}"
+        RenderText {#text} at (559,17) size 5x17
+          text run at (559,17) width 5: " "
+        RenderMathMLMath {math} at (563,19) size 109x12 [padding: 0 1 0 1]
+          RenderMathMLUnderOver {mover} at (1,0) size 107x12
+            RenderMathMLSpace {mspace} at (3,10) size 101x2 [bgcolor=#FF0000]
+            RenderMathMLOperator {mo} at (-4,0) size 114x10
+              RenderMathMLBlock (anonymous, flex) at (3,0) size 107x10
+                RenderBlock (anonymous) at (0,0) size 12x10
+                  RenderText at (0,-35) size 12x80
+                    text run at (0,-35) width 12: "\x{21DA}"
+        RenderText {#text} at (0,0) size 0x0
+        RenderMathMLMath {math} at (0,36) size 109x12 [padding: 0 1 0 1]
+          RenderMathMLUnderOver {mover} at (1,0) size 107x12
+            RenderMathMLSpace {mspace} at (3,10) size 101x2 [bgcolor=#FF0000]
+            RenderMathMLOperator {mo} at (-4,0) size 114x10
+              RenderMathMLBlock (anonymous, flex) at (3,0) size 107x10
+                RenderBlock (anonymous) at (0,0) size 12x10
+                  RenderText at (0,-35) size 12x80
+                    text run at (0,-35) width 12: "\x{21DB}"
+        RenderText {#text} at (108,34) size 5x17
+          text run at (108,34) width 5: " "
+        RenderMathMLMath {math} at (112,36) size 103x12 [padding: 0 1 0 1]
+          RenderMathMLUnderOver {mover} at (1,0) size 100x12
+            RenderMathMLSpace {mspace} at (0,10) size 100x2 [bgcolor=#FF0000]
+            RenderMathMLOperator {mo} at (0,0) size 100x10
+              RenderMathMLBlock (anonymous, flex) at (0,0) size 100x10
+                RenderBlock (anonymous) at (0,0) size 4x10
+                  RenderText at (0,-34) size 4x80
+                    text run at (0,-34) width 4: "\x{23B4}"
+        RenderText {#text} at (214,34) size 5x17
+          text run at (214,34) width 5: " "
+        RenderMathMLMath {math} at (218,41) size 103x7 [padding: 0 1 0 1]
+          RenderMathMLUnderOver {mover} at (1,0) size 100x7
+            RenderMathMLSpace {mspace} at (0,5) size 100x2 [bgcolor=#FF0000]
+            RenderMathMLOperator {mo} at (0,0) size 100x5
+              RenderMathMLBlock (anonymous, flex) at (0,0) size 100x4
+                RenderBlock (anonymous) at (0,0) size 4x4
+                  RenderText at (0,-43) size 4x80
+                    text run at (0,-43) width 4: "\x{23B5}"
+        RenderText {#text} at (320,34) size 5x17
+          text run at (320,34) width 5: " "
+        RenderMathMLMath {math} at (324,36) size 103x12 [padding: 0 1 0 1]
+          RenderMathMLUnderOver {mover} at (1,0) size 100x12
+            RenderMathMLSpace {mspace} at (0,10) size 100x2 [bgcolor=#FF0000]
+            RenderMathMLOperator {mo} at (0,0) size 100x10
+              RenderMathMLBlock (anonymous, flex) at (0,0) size 100x10
+                RenderBlock (anonymous) at (0,0) size 6x10
+                  RenderText at (0,-34) size 6x80
+                    text run at (0,-34) width 6: "\x{23DC}"
+        RenderText {#text} at (426,34) size 5x17
+          text run at (426,34) width 5: " "
+        RenderMathMLMath {math} at (430,41) size 103x7 [padding: 0 1 0 1]
+          RenderMathMLUnderOver {mover} at (1,0) size 100x7
+            RenderMathMLSpace {mspace} at (0,5) size 100x2 [bgcolor=#FF0000]
+            RenderMathMLOperator {mo} at (0,0) size 100x5
+              RenderMathMLBlock (anonymous, flex) at (0,0) size 100x4
+                RenderBlock (anonymous) at (0,0) size 6x4
+                  RenderText at (0,-43) size 6x80
+                    text run at (0,-43) width 6: "\x{23DD}"
+        RenderText {#text} at (532,34) size 5x17
+          text run at (532,34) width 5: " "
+        RenderMathMLMath {math} at (536,35) size 103x13 [padding: 0 1 0 1]
+          RenderMathMLUnderOver {mover} at (1,0) size 100x13
+            RenderMathMLSpace {mspace} at (0,11) size 100x2 [bgcolor=#FF0000]
+            RenderMathMLOperator {mo} at (0,0) size 100x11
+              RenderMathMLBlock (anonymous, flex) at (0,0) size 100x11
+                RenderBlock (anonymous) at (0,0) size 6x11
+                  RenderText at (0,-33) size 6x80
+                    text run at (0,-33) width 6: "\x{23DE}"
+        RenderText {#text} at (638,34) size 5x17
+          text run at (638,34) width 5: " "
+        RenderMathMLMath {math} at (642,40) size 103x8 [padding: 0 1 0 1]
+          RenderMathMLUnderOver {mover} at (1,0) size 100x8
+            RenderMathMLSpace {mspace} at (0,6) size 100x2 [bgcolor=#FF0000]
+            RenderMathMLOperator {mo} at (0,0) size 100x6
+              RenderMathMLBlock (anonymous, flex) at (0,0) size 100x5
+                RenderBlock (anonymous) at (0,0) size 6x5
+                  RenderText at (0,-43) size 6x80
+                    text run at (0,-43) width 6: "\x{23DF}"
+        RenderText {#text} at (0,0) size 0x0
diff --git a/LayoutTests/platform/gtk/mathml/opentype/horizontal-LatinModern-munderover-expected.png b/LayoutTests/platform/gtk/mathml/opentype/horizontal-LatinModern-munderover-expected.png
new file mode 100644 (file)
index 0000000..a266bc1
Binary files /dev/null and b/LayoutTests/platform/gtk/mathml/opentype/horizontal-LatinModern-munderover-expected.png differ
diff --git a/LayoutTests/platform/gtk/mathml/opentype/horizontal-LatinModern-munderover-expected.txt b/LayoutTests/platform/gtk/mathml/opentype/horizontal-LatinModern-munderover-expected.txt
new file mode 100644 (file)
index 0000000..543f0ad
--- /dev/null
@@ -0,0 +1,103 @@
+layer at (0,0) size 800x600
+  RenderView at (0,0) size 800x600
+layer at (0,0) size 800x63
+  RenderBlock {HTML} at (0,0) size 800x63
+    RenderBody {BODY} at (8,16) size 784x31
+      RenderBlock {P} at (0,0) size 784x31
+        RenderMathMLMath {math} at (0,4) size 50x16 [padding: 0 1 0 1]
+          RenderMathMLRow {mstyle} at (1,0) size 48x16
+            RenderMathMLUnderOver {mover} at (0,0) size 48x8
+              RenderMathMLOperator {mo} at (0,2) size 48x6
+                RenderMathMLBlock (anonymous, flex) at (0,0) size 48x6
+                  RenderBlock (anonymous) at (0,0) size 8x6
+                    RenderText at (0,-44) size 8x106
+                      text run at (0,-44) width 8: "\x{23DE}"
+              RenderMathMLSpace {mspace} at (0,0) size 48x2 [bgcolor=#FF0000]
+        RenderText {#text} at (50,6) size 4x17
+          text run at (50,6) width 4: " "
+        RenderMathMLMath {math} at (54,7) size 66x13 [padding: 0 1 0 1]
+          RenderMathMLRow {mstyle} at (1,0) size 64x13
+            RenderMathMLUnderOver {mover} at (0,0) size 64x13
+              RenderMathMLSpace {mspace} at (0,11) size 64x2 [bgcolor=#FF0000]
+              RenderMathMLOperator {mo} at (0,0) size 64x11
+                RenderMathMLBlock (anonymous, flex) at (0,0) size 64x11
+                  RenderBlock (anonymous) at (0,0) size 6x11
+                    RenderText at (0,-33) size 6x80
+                      text run at (0,-33) width 6: "\x{23DE}"
+        RenderText {#text} at (120,6) size 4x17
+          text run at (120,6) width 4: " "
+        RenderMathMLMath {math} at (124,6) size 50x14 [padding: 0 1 0 1]
+          RenderMathMLRow {mstyle} at (1,0) size 48x14
+            RenderMathMLUnderOver {munder} at (0,0) size 48x8
+              RenderMathMLOperator {mo} at (0,0) size 48x6
+                RenderMathMLBlock (anonymous, flex) at (0,0) size 48x6
+                  RenderBlock (anonymous) at (0,0) size 8x6
+                    RenderText at (0,-44) size 8x106
+                      text run at (0,-44) width 8: "\x{23DE}"
+              RenderMathMLSpace {mspace} at (0,6) size 48x2 [bgcolor=#FF0000]
+        RenderText {#text} at (174,6) size 4x17
+          text run at (174,6) width 4: " "
+        RenderMathMLMath {math} at (178,7) size 66x24 [padding: 0 1 0 1]
+          RenderMathMLRow {mstyle} at (1,0) size 64x24
+            RenderMathMLUnderOver {munderover} at (0,0) size 64x24
+              RenderMathMLSpace {mspace} at (0,11) size 64x2 [bgcolor=#FF0000]
+              RenderMathMLOperator {mo} at (0,13) size 64x11
+                RenderMathMLBlock (anonymous, flex) at (0,0) size 64x11
+                  RenderBlock (anonymous) at (0,0) size 6x11
+                    RenderText at (0,-33) size 6x80
+                      text run at (0,-33) width 6: "\x{23DE}"
+              RenderMathMLOperator {mo} at (0,0) size 64x11
+                RenderMathMLBlock (anonymous, flex) at (0,0) size 64x11
+                  RenderBlock (anonymous) at (0,0) size 6x11
+                    RenderText at (0,-33) size 6x80
+                      text run at (0,-33) width 6: "\x{23DE}"
+        RenderText {#text} at (244,6) size 4x17
+          text run at (244,6) width 4: " "
+        RenderMathMLMath {math} at (248,0) size 50x20 [padding: 0 1 0 1]
+          RenderMathMLRow {mstyle} at (1,0) size 48x20
+            RenderMathMLUnderOver {munderover} at (0,0) size 48x14
+              RenderMathMLOperator {mo} at (0,6) size 48x6
+                RenderMathMLBlock (anonymous, flex) at (0,0) size 48x6
+                  RenderBlock (anonymous) at (0,0) size 8x6
+                    RenderText at (0,-44) size 8x106
+                      text run at (0,-44) width 8: "\x{23DE}"
+              RenderMathMLSpace {mspace} at (0,12) size 48x2 [bgcolor=#FF0000]
+              RenderMathMLOperator {mo} at (0,0) size 48x6
+                RenderMathMLBlock (anonymous, flex) at (0,0) size 48x6
+                  RenderBlock (anonymous) at (0,0) size 6x6
+                    RenderText at (0,-33) size 6x80
+                      text run at (0,-33) width 6: "\x{23DE}"
+        RenderText {#text} at (298,6) size 4x17
+          text run at (298,6) width 4: " "
+        RenderMathMLMath {math} at (302,4) size 50x16 [padding: 0 1 0 1]
+          RenderMathMLRow {mstyle} at (1,0) size 48x16
+            RenderMathMLUnderOver {munderover} at (0,0) size 48x14
+              RenderMathMLOperator {mo} at (0,2) size 48x6
+                RenderMathMLBlock (anonymous, flex) at (0,0) size 48x6
+                  RenderBlock (anonymous) at (0,0) size 8x6
+                    RenderText at (0,-44) size 8x106
+                      text run at (0,-44) width 8: "\x{23DE}"
+              RenderMathMLOperator {mo} at (0,8) size 48x6
+                RenderMathMLBlock (anonymous, flex) at (0,0) size 48x6
+                  RenderBlock (anonymous) at (0,0) size 6x6
+                    RenderText at (0,-33) size 6x80
+                      text run at (0,-33) width 6: "\x{23DE}"
+              RenderMathMLSpace {mspace} at (0,0) size 48x2 [bgcolor=#FF0000]
+        RenderText {#text} at (352,6) size 4x17
+          text run at (352,6) width 4: " "
+        RenderMathMLMath {math} at (356,4) size 50x16 [padding: 0 1 0 1]
+          RenderMathMLRow {mstyle} at (1,0) size 48x16
+            RenderMathMLUnderOver {munder} at (0,0) size 48x14
+              RenderMathMLUnderOver {mover} at (0,0) size 48x8
+                RenderMathMLOperator {mo} at (0,2) size 48x6
+                  RenderMathMLBlock (anonymous, flex) at (0,0) size 48x6
+                    RenderBlock (anonymous) at (0,0) size 8x6
+                      RenderText at (0,-44) size 8x106
+                        text run at (0,-44) width 8: "\x{23DE}"
+                RenderMathMLSpace {mspace} at (0,0) size 48x2 [bgcolor=#FF0000]
+              RenderMathMLOperator {mo} at (0,8) size 48x6
+                RenderMathMLBlock (anonymous, flex) at (0,0) size 48x6
+                  RenderBlock (anonymous) at (0,0) size 6x6
+                    RenderText at (0,-33) size 6x80
+                      text run at (0,-33) width 6: "\x{23DE}"
+        RenderText {#text} at (0,0) size 0x0
diff --git a/LayoutTests/platform/gtk/mathml/opentype/opentype-stretchy-horizontal-expected.png b/LayoutTests/platform/gtk/mathml/opentype/opentype-stretchy-horizontal-expected.png
new file mode 100644 (file)
index 0000000..e4b53ac
Binary files /dev/null and b/LayoutTests/platform/gtk/mathml/opentype/opentype-stretchy-horizontal-expected.png differ
diff --git a/LayoutTests/platform/gtk/mathml/opentype/opentype-stretchy-horizontal-expected.txt b/LayoutTests/platform/gtk/mathml/opentype/opentype-stretchy-horizontal-expected.txt
new file mode 100644 (file)
index 0000000..708b635
--- /dev/null
@@ -0,0 +1,38 @@
+layer at (0,0) size 800x600
+  RenderView at (0,0) size 800x600
+layer at (0,0) size 800x157
+  RenderBlock {HTML} at (0,0) size 800x157
+    RenderBody {BODY} at (8,16) size 784x125
+      RenderBlock {P} at (0,0) size 784x25
+        RenderMathMLMath {math} at (0,2) size 18x23 [padding: 0 1 0 1]
+          RenderMathMLRow {mstyle} at (1,0) size 16x23
+            RenderMathMLUnderOver {mover} at (0,0) size 16x23
+              RenderMathMLOperator {mo} at (-5,1) size 26x22
+                RenderMathMLBlock (anonymous, flex) at (2,0) size 21x4
+                  RenderBlock (anonymous) at (0,0) size 1x4
+                    RenderText at (0,-3) size 1x0
+                      text run at (0,-3) width 1: "\x{219C}"
+              RenderMathMLSpace {mspace} at (4,0) size 8x1
+        RenderText {#text} at (0,0) size 0x0
+      RenderBlock {P} at (0,41) size 784x25
+        RenderMathMLMath {math} at (0,2) size 28x23 [padding: 0 1 0 1]
+          RenderMathMLRow {mstyle} at (1,0) size 26x23
+            RenderMathMLUnderOver {mover} at (0,0) size 26x23
+              RenderMathMLOperator {mo} at (-6,1) size 38x22
+                RenderMathMLBlock (anonymous, flex) at (2,0) size 32x4
+                  RenderBlock (anonymous) at (0,0) size 1x4
+                    RenderText at (0,-3) size 1x0
+                      text run at (0,-3) width 1: "\x{219C}"
+              RenderMathMLSpace {mspace} at (5,0) size 16x1
+        RenderText {#text} at (0,0) size 0x0
+      RenderBlock {P} at (0,82) size 784x43
+        RenderMathMLMath {math} at (0,0) size 158x43 [padding: 0 1 0 1]
+          RenderMathMLRow {mstyle} at (1,0) size 156x43
+            RenderMathMLUnderOver {mover} at (0,0) size 156x43
+              RenderMathMLOperator {mo} at (-3,1) size 162x42
+                RenderMathMLBlock (anonymous, flex) at (2,0) size 157x4
+                  RenderBlock (anonymous) at (0,0) size 1x4
+                    RenderText at (0,-3) size 1x0
+                      text run at (0,-3) width 1: "\x{219C}"
+              RenderMathMLSpace {mspace} at (2,0) size 151x1
+        RenderText {#text} at (0,0) size 0x0
index 265e1d0..6a94b91 100755 (executable)
@@ -1325,6 +1325,9 @@ webkit.org/b/130693 mathml/presentation/tokenElements-background-color.html [ Im
 webkit.org/b/130322 [ MountainLion Mavericks ] mathml/opentype/large-operators-LatinModern.html [ Failure ]
 webkit.org/b/130322 [ MountainLion Mavericks ] mathml/opentype/opentype-stretchy.html [ Failure ]
 webkit.org/b/130322 [ MountainLion Mavericks ] mathml/opentype/vertical-LatinModern.html [ Failure ]
+webkit.org/b/72828 mathml/opentype/horizontal-LatinModern.html [ Failure ]
+webkit.org/b/72828 mathml/opentype/opentype-stretchy-horizontal.html [ Failure ]
+webkit.org/b/72828 mathml/opentype/horizontal-LatinModern-munderover.html [ Failure ]
 
 # WebKitDataCue is supported, not DataCue
 media/track/track-datacue.html [ Skip ]
index 8994858..cec181d 100644 (file)
@@ -2746,3 +2746,6 @@ fast/canvas/canvas-path-addPath.html [ Crash ]
 webkit.org/b/130322 mathml/opentype/large-operators-LatinModern.html [ Failure ]
 webkit.org/b/130322 mathml/opentype/opentype-stretchy.html [ Failure ]
 webkit.org/b/130322 mathml/opentype/vertical-LatinModern.html [ Failure ]
+webkit.org/b/72828 mathml/opentype/horizontal-LatinModern.html [ Failure ]
+webkit.org/b/72828 mathml/opentype/opentype-stretchy-horizontal.html [ Failure ]
+webkit.org/b/72828 mathml/opentype/horizontal-LatinModern-munderover.html [ Failure ]
index fcb849e..04521b3 100644 (file)
@@ -1,3 +1,49 @@
+2014-06-05  Frédéric Wang  <fred.wang@free.fr>
+
+        MathML operators not stretched horizontally
+        https://bugs.webkit.org/show_bug.cgi?id=72828
+
+        Reviewed by Chris Fleizach.
+
+        This patch adds basic horizontal stretching rules for operators inside
+        an <munder>, <mover> or <munderover> elements. The stretchy operators
+        in such an element stretch to cover the size of the non-stretchy
+        operators. This only works when fonts that have an OpenType MATH table
+        are used.
+
+        Tests: mathml/opentype/horizontal-LatinModern.html
+               mathml/opentype/opentype-stretchy-horizontal.html
+               mathml/opentype/horizontal-LatinModern-munderover.html
+
+        * rendering/mathml/RenderMathMLOperator.cpp:
+        (WebCore::MathMLOperatorDictionary::ExtractKeyHorizontal): We add an ordered list of operators that have horizontal stretch direction.
+        (WebCore::RenderMathMLOperator::RenderMathMLOperator): init m_Vertical
+        (WebCore::RenderMathMLOperator::SetOperatorProperties): set m_Vertical by checking whether the operator is in the horizontalOperators list.
+        (WebCore::RenderMathMLOperator::stretchTo): We do not stretch vertically
+        if the operator has horizontal direction.
+        We also add a new version stretchTo(LayoutUnit width) for horizontal stretching only.
+        (WebCore::RenderMathMLOperator::computePreferredLogicalWidths): Handle horizontal stretching: the maximumGlyphWidth is the maximum of
+        the base size or of the stretch size.
+        (WebCore::RenderMathMLOperator::getDisplayStyleLargeOperator): Add an ASSERT to ensure that this function is only called for vertical stretching.
+        (WebCore::RenderMathMLOperator::findStretchyData): Add an ASSERT to ensure that this function is not called to get the maximum width of a horizontal stretchy operator.
+        We take into account m_isVertical when calling getMathVariants or computing sizes.
+        There is not any Unicode-only construction for horizontal stretching, so a MATH table is required for horizontal stretching.
+        (WebCore::RenderMathMLOperator::updateStyle): Ignore some code paths specific to vertical stretching and take into account the m_Vertical parameters.
+        For horizontal stretching, the m_stretch*Baseline parameters are now updated to match the metrics of the size variant or of the maximum of the parts in the glyph assembly.
+        (WebCore::RenderMathMLOperator::computeLogicalHeight): logicalHeight is now explicitely the sum of m_stretchHeightAboveBaseline and m_stretchDepthBelowBaseline, since it can be different from the stretchSize() in horizontal stretching.
+        (WebCore::RenderMathMLOperator::paintGlyph): handle trimming for horizontal stretching.
+        (WebCore::RenderMathMLOperator::fillWithVerticalExtensionGlyph): rename the function and ensure it is only call for m_isVertical.
+        (WebCore::RenderMathMLOperator::fillWithHorizontalExtensionGlyph): same as fillWithVerticalExtensionGlyph, but for horizontal stretching.
+        (WebCore::RenderMathMLOperator::paint): For glyph assembly, choose between paintVerticalGlyphAssembly or paintHorizontalGlyphAssembly.
+        (WebCore::RenderMathMLOperator::paintVerticalGlyphAssembly): rename the function and ensure it is only call for m_isVertical.
+        (WebCore::RenderMathMLOperator::paintHorizontalGlyphAssembly): same as paintVerticalGlyphAssembly but for horizontal stretching.
+        * rendering/mathml/RenderMathMLOperator.h: we add a m_isVertical member to indicate the stretch direction and a m_stretchWidth to indicate the width of the stretchy character.
+        We define the horizontal counterparts of fillWith*ExtensionGlyph, paint*GlyphAssembly, GlyphPaintTrimming  StretchyData.
+        Finally stretchSize() takes into account the stretch direction.
+        * rendering/mathml/RenderMathMLUnderOver.cpp: We override the layout() function to stretch munderover children horizontally.
+        (WebCore::RenderMathMLUnderOver::layout):
+        * rendering/mathml/RenderMathMLUnderOver.h: we declare layout().
+
 2014-06-04  Bem Jones-Bey  <bjonesbe@adobe.com>
 
         [CSS Shapes] Image lifetime is not properly handled for gradient shapes
index 30ffbf6..48704a3 100644 (file)
@@ -1125,6 +1125,12 @@ static const Entry dictionary[MATHML_OPDICT_SIZE] = {
     { 0x2B46, Infix, 5, 5, Stretchy} // RIGHTWARDS QUADRUPLE ARROW
 };
 
+// A list of operators that stretch in the horizontal direction. This has been generated from Mozilla's MathML operator dictionary.
+inline UChar ExtractKeyHorizontal(const UChar* entry) { return *entry; }
+static const UChar horizontalOperators[] = {
+    0x003D, 0x005E, 0x005F, 0x007E, 0x00AF, 0x02C6, 0x02C7, 0x02C9, 0x02CD, 0x02DC, 0x02F7, 0x0302, 0x0332, 0x203E, 0x20D0, 0x20D1, 0x20D6, 0x20D7, 0x20E1, 0x2190, 0x2192, 0x2194, 0x2198, 0x2199, 0x219C, 0x219D, 0x219E, 0x21A0, 0x21A2, 0x21A3, 0x21A4, 0x21A6, 0x21A9, 0x21AA, 0x21AB, 0x21AC, 0x21AD, 0x21B4, 0x21B9, 0x21BC, 0x21BD, 0x21C0, 0x21C1, 0x21C4, 0x21C6, 0x21C7, 0x21C9, 0x21CB, 0x21CC, 0x21D0, 0x21D2, 0x21D4, 0x21DA, 0x21DB, 0x21DC, 0x21DD, 0x21E0, 0x21E2, 0x21E4, 0x21E5, 0x21E6, 0x21E8, 0x21F0, 0x21F6, 0x21FD, 0x21FE, 0x21FF, 0x23B4, 0x23B5, 0x23DC, 0x23DD, 0x23DE, 0x23DF, 0x23E0, 0x23E1, 0x2500, 0x27F5, 0x27F6, 0x27F7, 0x27F8, 0x27F9, 0x27FA, 0x27FB, 0x27FC, 0x27FD, 0x27FE, 0x27FF, 0x290C, 0x290D, 0x290E, 0x290F, 0x2910, 0x294E, 0x2950, 0x2952, 0x2953, 0x2956, 0x2957, 0x295A, 0x295B, 0x295E, 0x295F, 0x2B45, 0x2B46, 0xFE35, 0xFE36, 0xFE37, 0xFE38
+};
+
 }
 
 RenderMathMLOperator::RenderMathMLOperator(MathMLElement& element, PassRef<RenderStyle> style)
@@ -1132,6 +1138,7 @@ RenderMathMLOperator::RenderMathMLOperator(MathMLElement& element, PassRef<Rende
     , m_stretchHeightAboveBaseline(0)
     , m_stretchDepthBelowBaseline(0)
     , m_operator(0)
+    , m_isVertical(true)
 {
     updateTokenContent();
 }
@@ -1141,6 +1148,7 @@ RenderMathMLOperator::RenderMathMLOperator(Document& document, PassRef<RenderSty
     , m_stretchHeightAboveBaseline(0)
     , m_stretchDepthBelowBaseline(0)
     , m_operator(0)
+    , m_isVertical(true)
     , m_operatorForm(form)
     , m_operatorFlags(flag)
 {
@@ -1173,6 +1181,9 @@ void RenderMathMLOperator::setOperatorPropertiesFromOpDictEntry(const MathMLOper
 
 void RenderMathMLOperator::SetOperatorProperties()
 {
+    // We determine the stretch direction (default is vertical).
+    m_isVertical = !(tryBinarySearch<const UChar, UChar>(MathMLOperatorDictionary::horizontalOperators, WTF_ARRAY_LENGTH(MathMLOperatorDictionary::horizontalOperators), m_operator, MathMLOperatorDictionary::ExtractKeyHorizontal));
+
     // We determine the form of the operator.
     bool explicitForm = true;
     if (!isFencedOperator()) {
@@ -1253,7 +1264,7 @@ bool RenderMathMLOperator::isChildAllowed(const RenderObject&, const RenderStyle
 
 void RenderMathMLOperator::stretchTo(LayoutUnit heightAboveBaseline, LayoutUnit depthBelowBaseline)
 {
-    if (heightAboveBaseline == m_stretchHeightAboveBaseline && depthBelowBaseline == m_stretchDepthBelowBaseline)
+    if (!m_isVertical || (heightAboveBaseline == m_stretchHeightAboveBaseline && depthBelowBaseline == m_stretchDepthBelowBaseline))
         return;
 
     m_stretchHeightAboveBaseline = heightAboveBaseline;
@@ -1283,6 +1294,18 @@ void RenderMathMLOperator::stretchTo(LayoutUnit heightAboveBaseline, LayoutUnit
     updateStyle();
 }
 
+void RenderMathMLOperator::stretchTo(LayoutUnit width)
+{
+    if (m_isVertical || m_stretchWidth == width)
+        return;
+
+    m_stretchWidth = width;
+
+    SetOperatorProperties();
+
+    updateStyle();
+}
+
 FloatRect RenderMathMLOperator::boundsForGlyph(const GlyphData& data) const
 {
     return data.fontData->boundsForGlyph(data.glyph);
@@ -1318,6 +1341,13 @@ void RenderMathMLOperator::computePreferredLogicalWidths()
 
     GlyphData data = style().font().glyphDataForCharacter(m_operator, false);
     float maximumGlyphWidth = advanceForGlyph(data);
+    if (!m_isVertical) {
+        if (maximumGlyphWidth < stretchSize())
+            maximumGlyphWidth = stretchSize();
+        m_maxPreferredLogicalWidth = m_leadingSpace + maximumGlyphWidth + m_trailingSpace;
+        m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth;
+        return;
+    }
     if (isLargeOperatorInDisplayStyle()) {
         // Large operators in STIX Word have incorrect advance width, causing misplacement of superscript, so we use the glyph bound instead (http://sourceforge.net/p/stixfonts/tracking/49/).
         StretchyData largeOperator = getDisplayStyleLargeOperator(m_operator);
@@ -1481,7 +1511,7 @@ RenderMathMLOperator::StretchyData RenderMathMLOperator::getDisplayStyleLargeOpe
 {
     StretchyData data;
 
-    ASSERT(isLargeOperatorInDisplayStyle());
+    ASSERT(m_isVertical && isLargeOperatorInDisplayStyle());
 
     const auto& primaryFontData = style().font().primaryFont();
     GlyphData baseGlyph = style().font().glyphDataForCharacter(character, false);
@@ -1510,6 +1540,8 @@ RenderMathMLOperator::StretchyData RenderMathMLOperator::getDisplayStyleLargeOpe
 
 RenderMathMLOperator::StretchyData RenderMathMLOperator::findStretchyData(UChar character, float* maximumGlyphWidth)
 {
+    ASSERT(!maximumGlyphWidth || m_isVertical);
+
     StretchyData data;
     StretchyData assemblyData;
 
@@ -1519,7 +1551,7 @@ RenderMathMLOperator::StretchyData RenderMathMLOperator::findStretchyData(UChar
     if (primaryFontData && primaryFontData->mathData() && baseGlyph.fontData == primaryFontData) {
         Vector<Glyph> sizeVariants;
         Vector<OpenTypeMathData::AssemblyPart> assemblyParts;
-        primaryFontData->mathData()->getMathVariants(baseGlyph.glyph, true, sizeVariants, assemblyParts);
+        primaryFontData->mathData()->getMathVariants(baseGlyph.glyph, m_isVertical, sizeVariants, assemblyParts);
         // We verify the size variants.
         for (auto& variant : sizeVariants) {
             GlyphData sizeVariant;
@@ -1529,7 +1561,8 @@ RenderMathMLOperator::StretchyData RenderMathMLOperator::findStretchyData(UChar
                 *maximumGlyphWidth = std::max(*maximumGlyphWidth, advanceForGlyph(sizeVariant));
             else {
                 data.setSizeVariantMode(sizeVariant);
-                if (heightForGlyph(sizeVariant) >= stretchSize())
+                float size = m_isVertical ? heightForGlyph(sizeVariant) : advanceForGlyph(sizeVariant);
+                if (size >= stretchSize()) 
                     return data;
             }
         }
@@ -1538,6 +1571,9 @@ RenderMathMLOperator::StretchyData RenderMathMLOperator::findStretchyData(UChar
         if (!getGlyphAssemblyFallBack(assemblyParts, assemblyData))
             return data;
     } else {
+        if (!m_isVertical)
+            return data;
+
         // If the font does not have a MATH table, we fallback to the Unicode-only constructions.
         const StretchyCharacter* stretchyCharacter = nullptr;
         const unsigned maxIndex = WTF_ARRAY_LENGTH(stretchyCharacters);
@@ -1574,11 +1610,18 @@ RenderMathMLOperator::StretchyData RenderMathMLOperator::findStretchyData(UChar
         return assemblyData;
     }
 
-    // We ensure that the stretch height is large enough to avoid glyph overlaps.
-    float height = heightForGlyph(assemblyData.top()) + heightForGlyph(assemblyData.bottom());
-    if (assemblyData.middle().glyph)
-        height += heightForGlyph(assemblyData.middle());
-    if (height > stretchSize())
+    // We ensure that the size is large enough to avoid glyph overlaps.
+    float size;
+    if (m_isVertical) {
+        size = heightForGlyph(assemblyData.top()) + heightForGlyph(assemblyData.bottom());
+        if (assemblyData.middle().glyph)
+            size += heightForGlyph(assemblyData.middle());
+    } else {
+        size = advanceForGlyph(assemblyData.left()) + advanceForGlyph(assemblyData.right());
+        if (assemblyData.middle().glyph)
+            size += advanceForGlyph(assemblyData.middle());
+    }
+    if (size > stretchSize())
         return data;
 
     return assemblyData;
@@ -1606,18 +1649,18 @@ void RenderMathMLOperator::updateStyle()
     if (!shouldAllowStretching())
         return;
 
-    if (isLargeOperatorInDisplayStyle())
+    if (m_isVertical && isLargeOperatorInDisplayStyle())
         m_stretchyData = getDisplayStyleLargeOperator(m_operator);
     else {
         // We do not stretch if the base glyph is large enough.
         GlyphData baseGlyph = style().font().glyphDataForCharacter(m_operator, false);
-        float baseHeight = heightForGlyph(baseGlyph);
-        if (stretchSize() <= baseHeight)
+        float baseSize = m_isVertical ? heightForGlyph(baseGlyph) : advanceForGlyph(baseGlyph);
+        if (stretchSize() <= baseSize)
             return;
         m_stretchyData = findStretchyData(m_operator, nullptr);
     }
 
-    if (m_stretchyData.mode() == DrawSizeVariant) {
+    if (m_isVertical && m_stretchyData.mode() == DrawSizeVariant) {
         // We resize the operator to match the one of the size variant.
         if (isLargeOperatorInDisplayStyle()) {
             // The stretch size is actually not involved in the selection of the size variant in getDisplayStyleLargeOperator.
@@ -1634,6 +1677,37 @@ void RenderMathMLOperator::updateStyle()
             m_stretchDepthBelowBaseline *= aspect;
         }
     }
+
+    if (!m_isVertical) {
+        if (m_stretchyData.mode() == DrawSizeVariant) {
+            FloatRect glyphBounds = boundsForGlyph(m_stretchyData.variant());
+            m_stretchHeightAboveBaseline = -glyphBounds.y();
+            m_stretchDepthBelowBaseline = glyphBounds.maxY();
+            m_stretchWidth = advanceForGlyph(m_stretchyData.variant());
+        } else if (m_stretchyData.mode() == DrawGlyphAssembly) {
+            FloatRect glyphBounds;
+            m_stretchHeightAboveBaseline = 0;
+            m_stretchDepthBelowBaseline = 0;
+
+            glyphBounds = boundsForGlyph(m_stretchyData.left());
+            m_stretchHeightAboveBaseline = std::max<LayoutUnit>(m_stretchHeightAboveBaseline, -glyphBounds.y());
+            m_stretchDepthBelowBaseline = std::max<LayoutUnit>(m_stretchDepthBelowBaseline, glyphBounds.maxY());
+
+            glyphBounds = boundsForGlyph(m_stretchyData.right());
+            m_stretchHeightAboveBaseline = std::max<LayoutUnit>(m_stretchHeightAboveBaseline, -glyphBounds.y());
+            m_stretchDepthBelowBaseline = std::max<LayoutUnit>(m_stretchDepthBelowBaseline, glyphBounds.maxY());
+
+            glyphBounds = boundsForGlyph(m_stretchyData.extension());
+            m_stretchHeightAboveBaseline = std::max<LayoutUnit>(m_stretchHeightAboveBaseline, -glyphBounds.y());
+            m_stretchDepthBelowBaseline = std::max<LayoutUnit>(m_stretchDepthBelowBaseline, glyphBounds.maxY());
+
+            if (m_stretchyData.middle().glyph) {
+                glyphBounds = boundsForGlyph(m_stretchyData.middle());
+                m_stretchHeightAboveBaseline = std::max<LayoutUnit>(m_stretchHeightAboveBaseline, -glyphBounds.y());
+                m_stretchDepthBelowBaseline = std::max<LayoutUnit>(m_stretchDepthBelowBaseline, glyphBounds.maxY());
+            }
+        }
+    }
 }
 
 int RenderMathMLOperator::firstLineBaseline() const
@@ -1646,7 +1720,7 @@ int RenderMathMLOperator::firstLineBaseline() const
 void RenderMathMLOperator::computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logicalTop, LogicalExtentComputedValues& computedValues) const
 {
     if (m_stretchyData.mode() != DrawNormal)
-        logicalHeight = stretchSize();
+        logicalHeight = m_stretchHeightAboveBaseline + m_stretchDepthBelowBaseline;
     RenderBox::computeLogicalHeight(logicalHeight, logicalTop, computedValues);
 }
 
@@ -1670,13 +1744,29 @@ LayoutRect RenderMathMLOperator::paintGlyph(PaintInfo& info, const GlyphData& da
         glyphPaintRect.shiftMaxYEdgeTo(glyphPaintRect.maxY().floor() - 1);
         clipBounds.shiftMaxYEdgeTo(glyphPaintRect.maxY());
         break;
-    case TrimTopAndBottom:
+    case TrimTopAndBottom: {
         LayoutUnit temp = glyphPaintRect.y() + 1;
         glyphPaintRect.shiftYEdgeTo(temp.ceil());
         glyphPaintRect.shiftMaxYEdgeTo(glyphPaintRect.maxY().floor() - 1);
         clipBounds.shiftYEdgeTo(glyphPaintRect.y());
         clipBounds.shiftMaxYEdgeTo(glyphPaintRect.maxY());
+    }
+        break;
+    case TrimLeft:
+        glyphPaintRect.shiftXEdgeTo(glyphPaintRect.x().ceil() + 1);
+        clipBounds.shiftXEdgeTo(glyphPaintRect.x());
         break;
+    case TrimRight:
+        glyphPaintRect.shiftMaxXEdgeTo(glyphPaintRect.maxX().floor() - 1);
+        clipBounds.shiftMaxXEdgeTo(glyphPaintRect.maxX());
+        break;
+    case TrimLeftAndRight: {
+        LayoutUnit temp = glyphPaintRect.x() + 1;
+        glyphPaintRect.shiftXEdgeTo(temp.ceil());
+        glyphPaintRect.shiftMaxXEdgeTo(glyphPaintRect.maxX().floor() - 1);
+        clipBounds.shiftXEdgeTo(glyphPaintRect.x());
+        clipBounds.shiftMaxXEdgeTo(glyphPaintRect.maxX());
+    }
     }
 
     // Clipping the enclosing IntRect avoids any potential issues at joined edges.
@@ -1690,8 +1780,9 @@ LayoutRect RenderMathMLOperator::paintGlyph(PaintInfo& info, const GlyphData& da
     return glyphPaintRect;
 }
 
-void RenderMathMLOperator::fillWithExtensionGlyph(PaintInfo& info, const LayoutPoint& from, const LayoutPoint& to)
+void RenderMathMLOperator::fillWithVerticalExtensionGlyph(PaintInfo& info, const LayoutPoint& from, const LayoutPoint& to)
 {
+    ASSERT(m_isVertical);
     ASSERT(m_stretchyData.mode() == DrawGlyphAssembly);
     ASSERT(m_stretchyData.extension().glyph);
     ASSERT(from.y() <= to.y());
@@ -1727,6 +1818,42 @@ void RenderMathMLOperator::fillWithExtensionGlyph(PaintInfo& info, const LayoutP
     }
 }
 
+void RenderMathMLOperator::fillWithHorizontalExtensionGlyph(PaintInfo& info, const LayoutPoint& from, const LayoutPoint& to)
+{
+    ASSERT(!m_isVertical);
+    ASSERT(m_stretchyData.mode() == DrawGlyphAssembly);
+    ASSERT(m_stretchyData.extension().glyph);
+    ASSERT(from.x() <= to.x());
+
+    // If there is no space for the extension glyph, we don't need to do anything.
+    if (from.x() == to.x())
+        return;
+
+    GraphicsContextStateSaver stateSaver(*info.context);
+
+    // Clipping the extender region here allows us to draw the bottom extender glyph into the
+    // regions of the bottom glyph without worrying about overdraw (hairy pixels) and simplifies later clipping.
+    LayoutRect clipBounds = info.rect;
+    clipBounds.shiftXEdgeTo(from.x());
+    clipBounds.shiftMaxXEdgeTo(to.x());
+    info.context->clip(clipBounds);
+
+    // Trimming may remove up to two pixels from the left of the extender glyph, so we move it left by two pixels.
+    float offsetToGlyphLeft = -2;
+    LayoutPoint glyphOrigin = LayoutPoint(from.x() + offsetToGlyphLeft, std::min(from.y(), to.y()) + m_stretchHeightAboveBaseline);
+    FloatRect lastPaintedGlyphRect(from, FloatSize());
+
+    while (lastPaintedGlyphRect.maxX() < to.x()) {
+        lastPaintedGlyphRect = paintGlyph(info, m_stretchyData.extension(), glyphOrigin, TrimLeftAndRight);
+        glyphOrigin.setX(glyphOrigin.x() + lastPaintedGlyphRect.width());
+
+        // There's a chance that if the font size is small enough the glue glyph has been reduced to an empty rectangle
+        // with trimming. In that case we just draw nothing.
+        if (lastPaintedGlyphRect.isEmpty())
+            break;
+    }
+}
+
 void RenderMathMLOperator::paint(PaintInfo& info, const LayoutPoint& paintOffset)
 {
     RenderMathMLToken::paint(info, paintOffset);
@@ -1750,6 +1877,15 @@ void RenderMathMLOperator::paint(PaintInfo& info, const LayoutPoint& paintOffset
         return;
     }
 
+    if (m_isVertical)
+        paintVerticalGlyphAssembly(info, paintOffset);
+    else
+        paintHorizontalGlyphAssembly(info, paintOffset);
+}
+
+void RenderMathMLOperator::paintVerticalGlyphAssembly(PaintInfo& info, const LayoutPoint& paintOffset)
+{
+    ASSERT(m_isVertical);
     ASSERT(m_stretchyData.mode() == DrawGlyphAssembly);
     ASSERT(m_stretchyData.top().glyph);
     ASSERT(m_stretchyData.bottom().glyph);
@@ -1774,10 +1910,39 @@ void RenderMathMLOperator::paint(PaintInfo& info, const LayoutPoint& paintOffset
         middleGlyphOrigin.moveBy(LayoutPoint(0, middleGlyphBounds.height() / 2.0));
 
         LayoutRect middleGlyphPaintRect = paintGlyph(info, m_stretchyData.middle(), middleGlyphOrigin, TrimTopAndBottom);
-        fillWithExtensionGlyph(info, topGlyphPaintRect.minXMaxYCorner(), middleGlyphPaintRect.minXMinYCorner());
-        fillWithExtensionGlyph(info, middleGlyphPaintRect.minXMaxYCorner(), bottomGlyphPaintRect.minXMinYCorner());
+        fillWithVerticalExtensionGlyph(info, topGlyphPaintRect.minXMaxYCorner(), middleGlyphPaintRect.minXMinYCorner());
+        fillWithVerticalExtensionGlyph(info, middleGlyphPaintRect.minXMaxYCorner(), bottomGlyphPaintRect.minXMinYCorner());
+    } else
+        fillWithVerticalExtensionGlyph(info, topGlyphPaintRect.minXMaxYCorner(), bottomGlyphPaintRect.minXMinYCorner());
+}
+
+void RenderMathMLOperator::paintHorizontalGlyphAssembly(PaintInfo& info, const LayoutPoint& paintOffset)
+{
+    ASSERT(!m_isVertical);
+    ASSERT(m_stretchyData.mode() == DrawGlyphAssembly);
+    ASSERT(m_stretchyData.left().glyph);
+    ASSERT(m_stretchyData.right().glyph);
+
+    // We are positioning the glyphs so that the edge of the tight glyph bounds line up exactly with the edges of our paint box.
+    LayoutPoint operatorTopLeft = paintOffset + location();
+    operatorTopLeft.move(m_leadingSpace, 0);
+    operatorTopLeft = ceiledIntPoint(operatorTopLeft);
+    LayoutPoint leftGlyphOrigin(operatorTopLeft.x(), operatorTopLeft.y() + m_stretchHeightAboveBaseline);
+    LayoutRect leftGlyphPaintRect = paintGlyph(info, m_stretchyData.left(), leftGlyphOrigin, TrimRight);
+
+    FloatRect rightGlyphBounds = boundsForGlyph(m_stretchyData.right());
+    LayoutPoint rightGlyphOrigin(operatorTopLeft.x() + offsetWidth() - rightGlyphBounds.width(), operatorTopLeft.y() + m_stretchHeightAboveBaseline);
+    LayoutRect rightGlyphPaintRect = paintGlyph(info, m_stretchyData.right(), rightGlyphOrigin, TrimLeft);
+
+    if (m_stretchyData.middle().glyph) {
+        // Center the glyph origin between the start and end glyph paint extents.
+        LayoutPoint middleGlyphOrigin(operatorTopLeft.x(), leftGlyphOrigin.y());
+        middleGlyphOrigin.moveBy(LayoutPoint((rightGlyphPaintRect.x() - leftGlyphPaintRect.maxX()) / 2.0, 0));
+        LayoutRect middleGlyphPaintRect = paintGlyph(info, m_stretchyData.middle(), middleGlyphOrigin, TrimLeftAndRight);
+        fillWithHorizontalExtensionGlyph(info, leftGlyphPaintRect.maxXMinYCorner(), middleGlyphPaintRect.minXMinYCorner());
+        fillWithHorizontalExtensionGlyph(info, middleGlyphPaintRect.maxXMinYCorner(), rightGlyphPaintRect.minXMinYCorner());
     } else
-        fillWithExtensionGlyph(info, topGlyphPaintRect.minXMaxYCorner(), bottomGlyphPaintRect.minXMinYCorner());
+        fillWithHorizontalExtensionGlyph(info, leftGlyphPaintRect.maxXMinYCorner(), rightGlyphPaintRect.minXMinYCorner());
 }
 
 void RenderMathMLOperator::paintChildren(PaintInfo& paintInfo, const LayoutPoint& paintOffset, PaintInfo& paintInfoForChild, bool usePrintRect)
index e12d4e0..fe19502 100644 (file)
@@ -64,7 +64,8 @@ public:
     RenderMathMLOperator(Document&, PassRef<RenderStyle>, const String& operatorString, MathMLOperatorDictionary::Form, MathMLOperatorDictionary::Flag);
 
     void stretchTo(LayoutUnit heightAboveBaseline, LayoutUnit depthBelowBaseline);
-    LayoutUnit stretchSize() const { return m_stretchHeightAboveBaseline + m_stretchDepthBelowBaseline; }
+    void stretchTo(LayoutUnit width);
+    LayoutUnit stretchSize() const { return m_isVertical ? m_stretchHeightAboveBaseline + m_stretchDepthBelowBaseline : m_stretchWidth; }
     
     bool hasOperatorFlag(MathMLOperatorDictionary::Flag flag) const { return m_operatorFlags & flag; }
     // FIXME: The displaystyle property is not implemented (https://bugs.webkit.org/show_bug.cgi?id=118737).
@@ -110,6 +111,8 @@ private:
         GlyphData extension() const { return m_data[1]; }
         GlyphData bottom() const { return m_data[2]; }
         GlyphData middle() const { return m_data[3]; }
+        GlyphData left() const { return m_data[2]; }
+        GlyphData right() const { return m_data[0]; }
 
         void setNormalMode()
         {
@@ -157,15 +160,23 @@ private:
         TrimTop,
         TrimBottom,
         TrimTopAndBottom,
+        TrimLeft,
+        TrimRight,
+        TrimLeftAndRight
     };
 
     LayoutRect paintGlyph(PaintInfo&, const GlyphData&, const LayoutPoint& origin, GlyphPaintTrimming);
-    void fillWithExtensionGlyph(PaintInfo&, const LayoutPoint& from, const LayoutPoint& to);
+    void fillWithVerticalExtensionGlyph(PaintInfo&, const LayoutPoint& from, const LayoutPoint& to);
+    void fillWithHorizontalExtensionGlyph(PaintInfo&, const LayoutPoint& from, const LayoutPoint& to);
+    void paintVerticalGlyphAssembly(PaintInfo&, const LayoutPoint&);
+    void paintHorizontalGlyphAssembly(PaintInfo&, const LayoutPoint&);
 
     LayoutUnit m_stretchHeightAboveBaseline;
     LayoutUnit m_stretchDepthBelowBaseline;
+    LayoutUnit m_stretchWidth;
 
     UChar m_operator;
+    bool m_isVertical;
     StretchyData m_stretchyData;
     MathMLOperatorDictionary::Form m_operatorForm;
     unsigned short m_operatorFlags;
index f4fb992..602d4cb 100644 (file)
@@ -30,6 +30,9 @@
 #include "RenderMathMLUnderOver.h"
 
 #include "MathMLElement.h"
+#include "MathMLNames.h"
+#include "RenderIterator.h"
+#include "RenderMathMLOperator.h"
 
 namespace WebCore {
 
@@ -68,6 +71,27 @@ int RenderMathMLUnderOver::firstLineBaseline() const
     return baseline;
 }
 
+void RenderMathMLUnderOver::layout()
+{
+    LayoutUnit stretchWidth = 0;
+    for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
+        if (child->needsLayout())
+            toRenderElement(child)->layout();
+        // Skipping the embellished op does not work for nested structures like
+        // <munder><mover><mo>_</mo>...</mover> <mo>_</mo></munder>.
+        if (child->isBox())
+            stretchWidth = std::max<LayoutUnit>(stretchWidth, toRenderBox(child)->logicalWidth());
+    }
+
+    // Set the sizes of (possibly embellished) stretchy operator children.
+    for (auto& child : childrenOfType<RenderMathMLBlock>(*this)) {
+        if (auto renderOperator = child.unembellishedOperator())
+            renderOperator->stretchTo(stretchWidth);
+    }
+
+    RenderMathMLBlock::layout();
+}
+
 }
 
 #endif // ENABLE(MATHML)
index 9409797..bde5915 100644 (file)
@@ -40,6 +40,9 @@ public:
 
     virtual int firstLineBaseline() const override;
     
+protected:
+    virtual void layout();
+
 private:
     virtual bool isRenderMathMLUnderOver() const override { return true; }
     virtual const char* renderName() const override { return "RenderMathMLUnderOver"; }