Title: [225736] trunk
Revision
225736
Author
[email protected]
Date
2017-12-10 19:10:41 -0800 (Sun, 10 Dec 2017)

Log Message

Incorrect bounds inside <mover>/<munder> when a stretchy operator is present
https://bugs.webkit.org/show_bug.cgi?id=179682

Patch by Minsheng Liu <[email protected]> on 2017-12-10
Reviewed by Frédéric Wang.

Source/WebCore:

Currently a stretchy operator inside <mover>/<munder>/<munderover> is stretched
during paint() rather than layout(), which leads to both end user confusion
and many unexpected behaviors. This patch rewrites
RenderMathMLUnderOver::stretchHorizontalOperatorsAndLayoutChildren()
to both eliminate the issue and make operator stretching more standard
conforming.

A test is added to check the stretch width of stretchy operators in various
scenarios:
mathml/opentype/munderover-stretch-width.html

A previous test is updated:
mathml/opentype/opentype-stretchy-horizontal.html

* rendering/mathml/RenderMathMLOperator.cpp:
(WebCore::RenderMathMLOperator::stretchTo):
(WebCore::RenderMathMLOperator::resetStretchSize):
(WebCore::RenderMathMLOperator::paint):
* rendering/mathml/RenderMathMLOperator.h:
(WebCore::RenderMathMLOperator::setStretchWidthLocked):
(WebCore::RenderMathMLOperator::isStretchWidthLocked const):
* rendering/mathml/RenderMathMLUnderOver.cpp:
(WebCore::toHorizontalStretchyOperator):
(WebCore::fixLayoutAfterStretch):
(WebCore::RenderMathMLUnderOver::stretchHorizontalOperatorsAndLayoutChildren):

LayoutTests:

Added test case: mathml/opentype/munderover-stretch-width.html

Updated test case: mathml/opentype/opentype-stretchy-horizontal
We update the test file to make sure the stretchy <mo> has zero lspace/rspace.
Expected results for macOS and iOS are included.

* mathml/opentype/munderover-stretch-width-expected.txt: Added.
* mathml/opentype/munderover-stretch-width.html: Added.
* mathml/opentype/opentype-stretchy-horizontal.html:
* platform/gtk/mathml/opentype/opentype-stretchy-horizontal-expected.txt: Removed.
* platform/ios/mathml/opentype/opentype-stretchy-horizontal-expected.png:
* platform/ios/mathml/opentype/opentype-stretchy-horizontal-expected.txt:
* platform/mac/mathml/opentype/opentype-stretchy-horizontal-expected.png:
* platform/mac/mathml/opentype/opentype-stretchy-horizontal-expected.txt:
* platform/win/mathml/opentype/opentype-stretchy-horizontal-expected.txt: Removed.

Modified Paths

Added Paths

Removed Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (225735 => 225736)


--- trunk/LayoutTests/ChangeLog	2017-12-11 01:32:19 UTC (rev 225735)
+++ trunk/LayoutTests/ChangeLog	2017-12-11 03:10:41 UTC (rev 225736)
@@ -1,3 +1,26 @@
+2017-12-10  Minsheng Liu  <[email protected]>
+
+        Incorrect bounds inside <mover>/<munder> when a stretchy operator is present
+        https://bugs.webkit.org/show_bug.cgi?id=179682
+
+        Reviewed by Frédéric Wang.
+
+        Added test case: mathml/opentype/munderover-stretch-width.html
+
+        Updated test case: mathml/opentype/opentype-stretchy-horizontal
+        We update the test file to make sure the stretchy <mo> has zero lspace/rspace.
+        Expected results for macOS and iOS are included.
+
+        * mathml/opentype/munderover-stretch-width-expected.txt: Added.
+        * mathml/opentype/munderover-stretch-width.html: Added.
+        * mathml/opentype/opentype-stretchy-horizontal.html:
+        * platform/gtk/mathml/opentype/opentype-stretchy-horizontal-expected.txt: Removed.
+        * platform/ios/mathml/opentype/opentype-stretchy-horizontal-expected.png:
+        * platform/ios/mathml/opentype/opentype-stretchy-horizontal-expected.txt:
+        * platform/mac/mathml/opentype/opentype-stretchy-horizontal-expected.png:
+        * platform/mac/mathml/opentype/opentype-stretchy-horizontal-expected.txt:
+        * platform/win/mathml/opentype/opentype-stretchy-horizontal-expected.txt: Removed.
+
 2017-12-09  Darin Adler  <[email protected]>
 
         Add test demonstrating leaks that happen when we create reference cycles with DOM objects

Added: trunk/LayoutTests/mathml/opentype/munderover-stretch-width-expected.txt (0 => 225736)


--- trunk/LayoutTests/mathml/opentype/munderover-stretch-width-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/mathml/opentype/munderover-stretch-width-expected.txt	2017-12-11 03:10:41 UTC (rev 225736)
@@ -0,0 +1,35 @@
+This test passes if you see the black thing has the same width as the red bar.
+
+↜
+This test passes if you see the black thing has the same width as the red bar.
+
+↜
+This test passes if you see the black thing has the same width as the red bar below and wider than the green bar above.
+
+↜
+This test passes if you see the black thing has the same width as the red bar below and narrower than the green bar above.
+
+↜
+This test passes if you see all three things have the same width.
+
+↜
+↜
+This test passes if you see the black thing has the same width as the red bar.
+
+↜
+This test passes if you see the black thing has the same width as the red bar.
+
+↜
+This test passes if you see the black thing has the same width as the red bar.
+
+↜
+
+PASS simple stretchy over 
+PASS simple stretchy under 
+PASS embellished op over with wide base 
+PASS embellished op over with narrow base 
+PASS unembellished op under with plain op over 
+PASS nested embellished op 
+PASS nested non-munderover embellished op 
+PASS simple stretchy under should equal over 
+

Added: trunk/LayoutTests/mathml/opentype/munderover-stretch-width.html (0 => 225736)


--- trunk/LayoutTests/mathml/opentype/munderover-stretch-width.html	                        (rev 0)
+++ trunk/LayoutTests/mathml/opentype/munderover-stretch-width.html	2017-12-11 03:10:41 UTC (rev 225736)
@@ -0,0 +1,144 @@
+<!doctype html>
+<html>
+  <head>
+    <title>&lt;munderover&gt; stretch width</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;
+      }
+    </style>
+    <script src=""
+    <script src=""
+    <script>
+      setup({ "explicit_done": true });
+
+      function assertApproxEquals(description, widths) {
+        function checkWidths() {
+          let epsilon = 1;
+          for (let i = 1; i < widths.length; i ++)  
+            assert_approx_equals(widths[i - 1], widths[i], epsilon);
+        }
+        test(checkWidths, description);
+      }
+
+      function getWidths(caseNo, names) {
+        let widths = []
+        for (let name of names)
+          widths.push(document.getElementById(`${caseNo}-${name}`)
+                              .getBoundingClientRect()
+                              .width);
+        return widths;
+      }
+
+      function runCase(caseNo, description, ...names) {
+        let widths = getWidths(caseNo, names);
+        assertApproxEquals(description, widths);
+      }
+
+      function run() {
+        runCase(1, 'simple stretchy over', 'red', 'op');
+        runCase(2, 'simple stretchy under', 'red', 'op');
+        runCase(3, 'embellished op over with wide base', 'red', 'op');
+        runCase(4, 'embellished op over with narrow base', 'red', 'op');
+        runCase(5, 'unembellished op under with plain op over', 'red', 'op1', 'op2');
+        runCase(6, 'nested embellished op', 'red', 'op');
+        runCase(7, 'nested non-munderover embellished op', 'red', 'op');
+        runCase(8, 'simple stretchy under should equal over', 'red', 'op');
+        done();
+      }
+    </script>
+  </head>
+  <body _onload_="run()">
+    <p>This test passes if you see the black thing has the same width as the red bar.</p>
+    <math display="block">
+      <mover>
+        <mspace id="1-red" width="200px" height="10px" depth="10px" mathbackground="red"/>
+        <mo id="1-op" lspace="0px" rspace="0px" stretchy="true">&#x219C;</mo>
+      </mover>
+    </math>
+
+    <p>This test passes if you see the black thing has the same width as the red bar.</p>
+    <math display="block">
+      <munder>
+        <mspace id="2-red" width="200px" height="10px" depth="10px" mathbackground="red"/>
+        <mo id="2-op" lspace="0px" rspace="0px" stretchy="true">&#x219C;</mo>
+      </munder>
+    </math>
+
+    <p>This test passes if you see the black thing has the same width as the red bar below and wider than the green bar above.</p>
+    <math display="block">
+      <mover>
+        <mspace id="3-red" width="300px" height="10px" depth="10px" mathbackground="red"/>
+        <mover>
+          <mo id="3-op" lspace="0px" rspace="0px" stretchy="true">&#x219C;</mo>
+          <mspace id="3-green" width="200px" height="10px" depth="10px" mathbackground="green"/>
+        </mover>
+      </mover>
+    </math>
+
+    <p>This test passes if you see the black thing has the same width as the red bar below and narrower than the green bar above.</p>
+    <math display="block">
+      <mover>
+        <mspace id="4-red" width="200px" height="10px" depth="10px" mathbackground="red"/>
+        <mover>
+          <mo id="4-op" lspace="0px" rspace="0px" stretchy="true">&#x219C;</mo>
+          <mspace id="4-green" width="300px" height="10px" depth="10px" mathbackground="green"/>
+        </mover>
+      </mover>
+    </math>
+
+    <p>This test passes if you see all three things have the same width.</p>
+    <math display="block">
+      <mover>
+        <munder>
+          <mspace id="5-red" width="200px" height="10px" depth="10px" mathbackground="red"/>
+          <mo id="5-op1" lspace="0px" rspace="0px" stretchy="true">&#x219C;</mo>
+        </munder>
+        <mo id="5-op2" lspace="0px" rspace="0px" stretchy="true">&#x219C;</mo>
+      </mover>
+    </math>
+
+    <p>This test passes if you see the black thing has the same width as the red bar.</p>
+    <math display="block">
+      <munder>
+        <mspace id="6-red" width="200px" height="10px" depth="10px" mathbackground="red"/>
+        <munder>
+          <munder>
+            <mo id="6-op" lspace="0px" rspace="0px" stretchy="true">&#x219C;</mo>
+            <mspace id="6-green" width="150px" height="10px" depth="10px" mathbackground="green"/>
+          </munder>
+          <mspace id="6-blue" width="100px" height="10px" depth="10px" mathbackground="blue"/>
+        </munder>
+      </munder>
+    </math>
+
+    <p>This test passes if you see the black thing has the same width as the red bar.</p>
+    <math display="block">
+      <munder>
+        <mspace id="7-red" width="200px" height="10px" depth="10px" mathbackground="red"/>
+        <mfrac>
+          <mfrac>
+            <mo id="7-op" lspace="0px" rspace="0px" stretchy="true">&#x219C;</mo>
+            <mspace id="7-green" width="150px" height="10px" depth="10px" mathbackground="green"/>
+          </mfrac>
+          <mspace id="7-blue" width="100px" height="10px" depth="10px" mathbackground="blue"/>
+        </mfrac>
+      </munder>
+    </math>
+
+    <p>This test passes if you see the black thing has the same width as the red bar.</p>
+    <math display="block">
+      <munderover>
+        <mspace id="8-blue" width="100px" height="10px" depth="10px" mathbackground="blue"></mspace>
+        <mo id="8-op" lspace="0px" rspace="0px" stretchy="true">&#x219C;</mo>
+        <mspace id="8-red" width="200px" height="10px" depth="10px" mathbackground="red"></mspace>
+      </munderover>
+    </math>
+  </body>
+</html>

Modified: trunk/LayoutTests/mathml/opentype/opentype-stretchy-horizontal.html (225735 => 225736)


--- trunk/LayoutTests/mathml/opentype/opentype-stretchy-horizontal.html	2017-12-11 01:32:19 UTC (rev 225735)
+++ trunk/LayoutTests/mathml/opentype/opentype-stretchy-horizontal.html	2017-12-11 03:10:41 UTC (rev 225736)
@@ -21,7 +21,7 @@
     <p>
       <math>
         <mstyle scriptsizemultiplier="1">
-          <mover><mo stretchy="true">&#x219C;</mo><mspace width="1em" height="1px"/></mover>
+          <mover><mo lspace="0" rspace="0" stretchy="true">&#x219C;</mo><mspace width="1em" height="1px"/></mover>
         </mstyle>
       </math>
     </p>
@@ -28,7 +28,7 @@
     <p>
       <math>
         <mstyle scriptsizemultiplier="1">
-          <mover><mo stretchy="true">&#x219C;</mo><mspace width="2em" height="1px"/></mover>
+          <mover><mo lspace="0" rspace="0" stretchy="true">&#x219C;</mo><mspace width="2em" height="1px"/></mover>
         </mstyle>
       </math>
     </p>
@@ -37,7 +37,7 @@
     <p>
       <math>
         <mstyle scriptsizemultiplier="1">
-          <mover><mo stretchy="true">&#x219C;</mo><mspace width="20em" height="1px"/></mover>
+          <mover><mo lspace="0" rspace="0" stretchy="true">&#x219C;</mo><mspace width="20em" height="1px"/></mover>
         </mstyle>
       </math>
     </p>

Deleted: trunk/LayoutTests/platform/gtk/mathml/opentype/opentype-stretchy-horizontal-expected.txt (225735 => 225736)


--- trunk/LayoutTests/platform/gtk/mathml/opentype/opentype-stretchy-horizontal-expected.txt	2017-12-11 01:32:19 UTC (rev 225735)
+++ trunk/LayoutTests/platform/gtk/mathml/opentype/opentype-stretchy-horizontal-expected.txt	2017-12-11 03:10:41 UTC (rev 225736)
@@ -1,35 +0,0 @@
-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 8x23
-          RenderMathMLRow {mstyle} at (0,0) size 8x23
-            RenderMathMLUnderOver {mover} at (0,0) size 8x23
-              RenderMathMLOperator {mo} at (0,1) size 8x22
-                RenderBlock (anonymous) at (0,0) size 1x4
-                  RenderText {#text} at (0,-3) size 1x0
-                    text run at (0,-3) width 1: "\x{219C}"
-              RenderMathMLSpace {mspace} at (0,0) size 8x1
-        RenderText {#text} at (0,0) size 0x0
-      RenderBlock {P} at (0,41) size 784x25
-        RenderMathMLMath {math} at (0,2) size 15x23
-          RenderMathMLRow {mstyle} at (0,0) size 15x23
-            RenderMathMLUnderOver {mover} at (0,0) size 15x23
-              RenderMathMLOperator {mo} at (4,1) size 7x22
-                RenderBlock (anonymous) at (0,0) size 1x4
-                  RenderText {#text} at (0,-3) size 1x0
-                    text run at (0,-3) width 1: "\x{219C}"
-              RenderMathMLSpace {mspace} at (0,0) size 15x1
-        RenderText {#text} at (0,0) size 0x0
-      RenderBlock {P} at (0,82) size 784x43
-        RenderMathMLMath {math} at (0,0) size 150x43
-          RenderMathMLRow {mstyle} at (0,0) size 150x43
-            RenderMathMLUnderOver {mover} at (0,0) size 150x43
-              RenderMathMLOperator {mo} at (71,1) size 8x42
-                RenderBlock (anonymous) at (0,0) size 1x4
-                  RenderText {#text} at (0,-3) size 1x0
-                    text run at (0,-3) width 1: "\x{219C}"
-              RenderMathMLSpace {mspace} at (0,0) size 150x1
-        RenderText {#text} at (0,0) size 0x0

Modified: trunk/LayoutTests/platform/ios/mathml/opentype/opentype-stretchy-horizontal-expected.png


(Binary files differ)

Modified: trunk/LayoutTests/platform/ios/mathml/opentype/opentype-stretchy-horizontal-expected.txt (225735 => 225736)


--- trunk/LayoutTests/platform/ios/mathml/opentype/opentype-stretchy-horizontal-expected.txt	2017-12-11 01:32:19 UTC (rev 225735)
+++ trunk/LayoutTests/platform/ios/mathml/opentype/opentype-stretchy-horizontal-expected.txt	2017-12-11 03:10:41 UTC (rev 225736)
@@ -4,30 +4,30 @@
   RenderBlock {HTML} at (0,0) size 800x155
     RenderBody {BODY} at (8,16) size 784x123
       RenderBlock {P} at (0,0) size 784x25
-        RenderMathMLMath {math} at (0,4) size 8x22
-          RenderMathMLRow {mstyle} at (0,0) size 8x22
-            RenderMathMLUnderOver {mover} at (0,0) size 8x22
-              RenderMathMLOperator {mo} at (0,1) size 8x21
+        RenderMathMLMath {math} at (0,4) size 11x22
+          RenderMathMLRow {mstyle} at (0,0) size 11x22
+            RenderMathMLUnderOver {mover} at (0,0) size 11x22
+              RenderMathMLOperator {mo} at (0,1) size 11x21
                 RenderBlock (anonymous) at (0,0) size 2x4
                   RenderText {#text} at (0,-3) size 2x0
                     text run at (0,-3) width 2: "\x{219C}"
-              RenderMathMLSpace {mspace} at (0,0) size 8x1
+              RenderMathMLSpace {mspace} at (1,0) size 8x1
         RenderText {#text} at (0,0) size 0x0
       RenderBlock {P} at (0,41) size 784x25
-        RenderMathMLMath {math} at (0,4) size 15x22
-          RenderMathMLRow {mstyle} at (0,0) size 15x22
-            RenderMathMLUnderOver {mover} at (0,0) size 15x22
-              RenderMathMLOperator {mo} at (4,1) size 7x21
+        RenderMathMLMath {math} at (0,4) size 21x22
+          RenderMathMLRow {mstyle} at (0,0) size 21x22
+            RenderMathMLUnderOver {mover} at (0,0) size 21x22
+              RenderMathMLOperator {mo} at (0,1) size 21x21
                 RenderBlock (anonymous) at (0,0) size 2x4
                   RenderText {#text} at (0,-3) size 2x0
                     text run at (0,-3) width 2: "\x{219C}"
-              RenderMathMLSpace {mspace} at (0,0) size 15x1
+              RenderMathMLSpace {mspace} at (2,0) size 16x1
         RenderText {#text} at (0,0) size 0x0
       RenderBlock {P} at (0,82) size 784x41
         RenderMathMLMath {math} at (0,0) size 150x42
           RenderMathMLRow {mstyle} at (0,0) size 150x42
             RenderMathMLUnderOver {mover} at (0,0) size 150x42
-              RenderMathMLOperator {mo} at (71,1) size 8x41
+              RenderMathMLOperator {mo} at (0,1) size 150x41
                 RenderBlock (anonymous) at (0,0) size 2x4
                   RenderText {#text} at (0,-3) size 2x0
                     text run at (0,-3) width 2: "\x{219C}"

Modified: trunk/LayoutTests/platform/mac/mathml/opentype/opentype-stretchy-horizontal-expected.png


(Binary files differ)

Modified: trunk/LayoutTests/platform/mac/mathml/opentype/opentype-stretchy-horizontal-expected.txt (225735 => 225736)


--- trunk/LayoutTests/platform/mac/mathml/opentype/opentype-stretchy-horizontal-expected.txt	2017-12-11 01:32:19 UTC (rev 225735)
+++ trunk/LayoutTests/platform/mac/mathml/opentype/opentype-stretchy-horizontal-expected.txt	2017-12-11 03:10:41 UTC (rev 225736)
@@ -4,30 +4,30 @@
   RenderBlock {HTML} at (0,0) size 800x153
     RenderBody {BODY} at (8,16) size 784x121
       RenderBlock {P} at (0,0) size 784x24
-        RenderMathMLMath {math} at (0,3) size 8x22
-          RenderMathMLRow {mstyle} at (0,0) size 8x22
-            RenderMathMLUnderOver {mover} at (0,0) size 8x22
-              RenderMathMLOperator {mo} at (0,1) size 8x21
+        RenderMathMLMath {math} at (0,3) size 11x22
+          RenderMathMLRow {mstyle} at (0,0) size 11x22
+            RenderMathMLUnderOver {mover} at (0,0) size 11x22
+              RenderMathMLOperator {mo} at (0,1) size 11x21
                 RenderBlock (anonymous) at (0,0) size 2x4
                   RenderText {#text} at (0,-3) size 2x0
                     text run at (0,-3) width 2: "\x{219C}"
-              RenderMathMLSpace {mspace} at (0,0) size 8x1
+              RenderMathMLSpace {mspace} at (1,0) size 8x1
         RenderText {#text} at (0,0) size 0x0
       RenderBlock {P} at (0,40) size 784x24
-        RenderMathMLMath {math} at (0,3) size 15x22
-          RenderMathMLRow {mstyle} at (0,0) size 15x22
-            RenderMathMLUnderOver {mover} at (0,0) size 15x22
-              RenderMathMLOperator {mo} at (4,1) size 7x21
+        RenderMathMLMath {math} at (0,3) size 21x22
+          RenderMathMLRow {mstyle} at (0,0) size 21x22
+            RenderMathMLUnderOver {mover} at (0,0) size 21x22
+              RenderMathMLOperator {mo} at (0,1) size 21x21
                 RenderBlock (anonymous) at (0,0) size 2x4
                   RenderText {#text} at (0,-3) size 2x0
                     text run at (0,-3) width 2: "\x{219C}"
-              RenderMathMLSpace {mspace} at (0,0) size 15x1
+              RenderMathMLSpace {mspace} at (2,0) size 16x1
         RenderText {#text} at (0,0) size 0x0
       RenderBlock {P} at (0,80) size 784x41
         RenderMathMLMath {math} at (0,0) size 150x42
           RenderMathMLRow {mstyle} at (0,0) size 150x42
             RenderMathMLUnderOver {mover} at (0,0) size 150x42
-              RenderMathMLOperator {mo} at (71,1) size 8x41
+              RenderMathMLOperator {mo} at (0,1) size 150x41
                 RenderBlock (anonymous) at (0,0) size 2x4
                   RenderText {#text} at (0,-3) size 2x0
                     text run at (0,-3) width 2: "\x{219C}"

Deleted: trunk/LayoutTests/platform/win/mathml/opentype/opentype-stretchy-horizontal-expected.txt (225735 => 225736)


--- trunk/LayoutTests/platform/win/mathml/opentype/opentype-stretchy-horizontal-expected.txt	2017-12-11 01:32:19 UTC (rev 225735)
+++ trunk/LayoutTests/platform/win/mathml/opentype/opentype-stretchy-horizontal-expected.txt	2017-12-11 03:10:41 UTC (rev 225736)
@@ -1,35 +0,0 @@
-layer at (0,0) size 785x33554431
-  RenderView at (0,0) size 785x600
-layer at (0,0) size 785x33554431
-  RenderBlock {HTML} at (0,0) size 785x33554431
-    RenderBody {BODY} at (8,16) size 769x33554415
-      RenderBlock {P} at (0,0) size 769x19
-        RenderMathMLMath {math} at (0,8) size 8x11
-          RenderMathMLRow {mstyle} at (0,0) size 8x11
-            RenderMathMLUnderOver {mover} at (0,0) size 8x11
-              RenderMathMLOperator {mo} at (0,1) size 8x10
-                RenderBlock (anonymous) at (0,0) size 1x10
-                  RenderText {#text} at (0,0) size 1x0
-                    text run at (0,0) width 1: "\x{219C}"
-              RenderMathMLSpace {mspace} at (0,0) size 8x1
-        RenderText {#text} at (0,0) size 0x0
-      RenderBlock {P} at (0,35) size 769x19
-        RenderMathMLMath {math} at (0,8) size 15x11
-          RenderMathMLRow {mstyle} at (0,0) size 15x11
-            RenderMathMLUnderOver {mover} at (0,0) size 15x11
-              RenderMathMLOperator {mo} at (4,1) size 7x10
-                RenderBlock (anonymous) at (0,0) size 1x10
-                  RenderText {#text} at (0,0) size 1x0
-                    text run at (0,0) width 1: "\x{219C}"
-              RenderMathMLSpace {mspace} at (0,0) size 15x1
-        RenderText {#text} at (0,0) size 0x0
-      RenderBlock {P} at (0,70) size 769x33554361
-        RenderMathMLMath {math} at (0,8) size 150x33554423
-          RenderMathMLRow {mstyle} at (0,0) size 150x33554431
-            RenderMathMLUnderOver {mover} at (0,0) size 150x33554431
-              RenderMathMLOperator {mo} at (71,1) size 8x33554430
-                RenderBlock (anonymous) at (0,0) size 1x10
-                  RenderText {#text} at (0,0) size 1x0
-                    text run at (0,0) width 1: "\x{219C}"
-              RenderMathMLSpace {mspace} at (0,0) size 150x1
-        RenderText {#text} at (0,0) size 0x0

Modified: trunk/Source/WebCore/ChangeLog (225735 => 225736)


--- trunk/Source/WebCore/ChangeLog	2017-12-11 01:32:19 UTC (rev 225735)
+++ trunk/Source/WebCore/ChangeLog	2017-12-11 03:10:41 UTC (rev 225736)
@@ -1,3 +1,36 @@
+2017-12-10  Minsheng Liu  <[email protected]>
+
+        Incorrect bounds inside <mover>/<munder> when a stretchy operator is present
+        https://bugs.webkit.org/show_bug.cgi?id=179682
+
+        Reviewed by Frédéric Wang.
+
+        Currently a stretchy operator inside <mover>/<munder>/<munderover> is stretched
+        during paint() rather than layout(), which leads to both end user confusion
+        and many unexpected behaviors. This patch rewrites
+        RenderMathMLUnderOver::stretchHorizontalOperatorsAndLayoutChildren()
+        to both eliminate the issue and make operator stretching more standard
+        conforming.
+
+        A test is added to check the stretch width of stretchy operators in various
+        scenarios:
+        mathml/opentype/munderover-stretch-width.html
+
+        A previous test is updated:
+        mathml/opentype/opentype-stretchy-horizontal.html
+
+        * rendering/mathml/RenderMathMLOperator.cpp:
+        (WebCore::RenderMathMLOperator::stretchTo):
+        (WebCore::RenderMathMLOperator::resetStretchSize):
+        (WebCore::RenderMathMLOperator::paint):
+        * rendering/mathml/RenderMathMLOperator.h:
+        (WebCore::RenderMathMLOperator::setStretchWidthLocked):
+        (WebCore::RenderMathMLOperator::isStretchWidthLocked const):
+        * rendering/mathml/RenderMathMLUnderOver.cpp:
+        (WebCore::toHorizontalStretchyOperator):
+        (WebCore::fixLayoutAfterStretch):
+        (WebCore::RenderMathMLUnderOver::stretchHorizontalOperatorsAndLayoutChildren):
+
 2017-12-10  Yusuke Suzuki  <[email protected]>
 
         Unreviewed, follow-up patch after r225470

Modified: trunk/Source/WebCore/rendering/mathml/RenderMathMLOperator.cpp (225735 => 225736)


--- trunk/Source/WebCore/rendering/mathml/RenderMathMLOperator.cpp	2017-12-11 01:32:19 UTC (rev 225735)
+++ trunk/Source/WebCore/rendering/mathml/RenderMathMLOperator.cpp	2017-12-11 03:10:41 UTC (rev 225736)
@@ -122,6 +122,7 @@
 {
     ASSERT(isStretchy());
     ASSERT(isVertical());
+    ASSERT(!isStretchWidthLocked());
 
     if (!isVertical() || (heightAboveBaseline == m_stretchHeightAboveBaseline && depthBelowBaseline == m_stretchDepthBelowBaseline))
         return;
@@ -162,6 +163,7 @@
 {
     ASSERT(isStretchy());
     ASSERT(!isVertical());
+    ASSERT(!isStretchWidthLocked());
 
     if (isVertical() || m_stretchWidth == width)
         return;
@@ -169,11 +171,14 @@
     m_stretchWidth = width;
     m_mathOperator.stretchTo(style(), width);
 
+    setLogicalWidth(leadingSpace() + width + trailingSpace());
     setLogicalHeight(m_mathOperator.ascent() + m_mathOperator.descent());
 }
 
 void RenderMathMLOperator::resetStretchSize()
 {
+    ASSERT(!isStretchWidthLocked());
+    
     if (isVertical()) {
         m_stretchHeightAboveBaseline = 0;
         m_stretchDepthBelowBaseline = 0;
@@ -306,10 +311,6 @@
     LayoutPoint operatorTopLeft = paintOffset + location();
     operatorTopLeft.move(style().isLeftToRightDirection() ? leadingSpace() : trailingSpace(), 0);
 
-    // Center horizontal operators.
-    if (!isVertical())
-        operatorTopLeft.move(-(m_mathOperator.width() - width()) / 2, 0);
-
     m_mathOperator.paint(style(), info, operatorTopLeft);
 }
 

Modified: trunk/Source/WebCore/rendering/mathml/RenderMathMLOperator.h (225735 => 225736)


--- trunk/Source/WebCore/rendering/mathml/RenderMathMLOperator.h	2017-12-11 01:32:19 UTC (rev 225735)
+++ trunk/Source/WebCore/rendering/mathml/RenderMathMLOperator.h	2017-12-11 03:10:41 UTC (rev 225736)
@@ -46,6 +46,8 @@
     void stretchTo(LayoutUnit width);
     LayoutUnit stretchSize() const { return isVertical() ? m_stretchHeightAboveBaseline + m_stretchDepthBelowBaseline : m_stretchWidth; }
     void resetStretchSize();
+    void setStretchWidthLocked(bool stretchWidthLocked) { m_isStretchWidthLocked = stretchWidthLocked; }
+    bool isStretchWidthLocked() const { return m_isStretchWidthLocked; }
 
     virtual bool hasOperatorFlag(MathMLOperatorDictionary::Flag) const;
     bool isLargeOperatorInDisplayStyle() const { return !hasOperatorFlag(MathMLOperatorDictionary::Stretchy) && hasOperatorFlag(MathMLOperatorDictionary::LargeOp) && mathMLStyle().displayStyle(); }
@@ -85,6 +87,7 @@
     LayoutUnit m_stretchHeightAboveBaseline { 0 };
     LayoutUnit m_stretchDepthBelowBaseline { 0 };
     LayoutUnit m_stretchWidth;
+    bool m_isStretchWidthLocked { false };
 
     MathOperator m_mathOperator;
 };

Modified: trunk/Source/WebCore/rendering/mathml/RenderMathMLUnderOver.cpp (225735 => 225736)


--- trunk/Source/WebCore/rendering/mathml/RenderMathMLUnderOver.cpp	2017-12-11 01:32:19 UTC (rev 225735)
+++ trunk/Source/WebCore/rendering/mathml/RenderMathMLUnderOver.cpp	2017-12-11 03:10:41 UTC (rev 225736)
@@ -50,33 +50,57 @@
     return static_cast<MathMLUnderOverElement&>(nodeForNonAnonymous());
 }
 
+static RenderMathMLOperator* toHorizontalStretchyOperator(RenderBox* box)
+{
+    if (is<RenderMathMLBlock>(box)) {
+        if (auto renderOperator = downcast<RenderMathMLBlock>(*box).unembellishedOperator()) {
+            if (renderOperator->isStretchy() && !renderOperator->isVertical() && !renderOperator->isStretchWidthLocked())
+                return renderOperator;
+        }
+    }
+    return nullptr;
+}
+    
+static void fixLayoutAfterStretch(RenderBox* ancestor, RenderMathMLOperator* stretchyOperator)
+{
+    stretchyOperator->setStretchWidthLocked(true);
+    stretchyOperator->setNeedsLayout();
+    ancestor->layoutIfNeeded();
+    stretchyOperator->setStretchWidthLocked(false);
+}
+
 void RenderMathMLUnderOver::stretchHorizontalOperatorsAndLayoutChildren()
 {
+    ASSERT(isValid());
+    ASSERT(needsLayout());
+    
+    Vector<RenderBox*, 3> embellishedOperators;
+    Vector<RenderMathMLOperator*, 3> stretchyOperators;
+    bool isAllStretchyOperators = true;
     LayoutUnit stretchWidth = 0;
-    Vector<RenderMathMLOperator*, 2> renderOperators;
-
+    
     for (auto* child = firstChildBox(); child; child = child->nextSiblingBox()) {
-        if (child->needsLayout()) {
-            if (is<RenderMathMLBlock>(child)) {
-                if (auto renderOperator = downcast<RenderMathMLBlock>(*child).unembellishedOperator()) {
-                    if (renderOperator->isStretchy() && !renderOperator->isVertical()) {
-                        renderOperator->resetStretchSize();
-                        renderOperators.append(renderOperator);
-                    }
-                }
-            }
-
-            child->layout();
+        if (auto* stretchyOperator = toHorizontalStretchyOperator(child)) {
+            embellishedOperators.append(child);
+            stretchyOperators.append(stretchyOperator);
+            stretchyOperator->resetStretchSize();
+            fixLayoutAfterStretch(child, stretchyOperator);
+        } else {
+            isAllStretchyOperators = false;
+            child->layoutIfNeeded();
+            stretchWidth = std::max(stretchWidth, child->logicalWidth());
         }
-
-        // Skipping the embellished op does not work for nested structures like
-        // <munder><mover><mo>_</mo>...</mover> <mo>_</mo></munder>.
-        stretchWidth = std::max(stretchWidth, child->logicalWidth());
     }
-
-    // Set the sizes of (possibly embellished) stretchy operator children.
-    for (auto& renderOperator : renderOperators)
-        renderOperator->stretchTo(stretchWidth);
+    
+    if (isAllStretchyOperators) {
+        for (auto* embellishedOperator : embellishedOperators)
+            stretchWidth = std::max(stretchWidth, embellishedOperator->logicalWidth());
+    }
+    
+    for (size_t i = 0; i < embellishedOperators.size(); i++) {
+        stretchyOperators[i]->stretchTo(stretchWidth);
+        fixLayoutAfterStretch(embellishedOperators[i], stretchyOperators[i]);
+    }
 }
 
 bool RenderMathMLUnderOver::isValid() const
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to