<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[201854] trunk/Source/WebCore</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/201854">201854</a></dd>
<dt>Author</dt> <dd>fred.wang@free.fr</dd>
<dt>Date</dt> <dd>2016-06-08 23:17:40 -0700 (Wed, 08 Jun 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>Move selection and drawing of stretchy operators into a separate MathOperator class
https://bugs.webkit.org/show_bug.cgi?id=156921

Patch by Frederic Wang &lt;fwang@igalia.com&gt; on 2016-06-08
Reviewed by Martin Robinson.

No new tests, behavior is not changed.

* CMakeLists.txt: Add the MathOperator files.
* WebCore.xcodeproj/project.pbxproj: Ditto.
* rendering/mathml/MathOperator.cpp: Added.
(WebCore::boundsForGlyph): Moved from RenderMathMLOperator.
(WebCore::heightForGlyph): Moved from RenderMathMLOperator.
(WebCore::advanceWidthForGlyph): Moved from RenderMathMLOperator.
(WebCore::MathOperator::MathOperator):
(WebCore::MathOperator::setOperator):
(WebCore::MathOperator::getBaseGlyph): Moved from RenderMathMLOperator.
(WebCore::MathOperator::setSizeVariant): Moved from RenderMathMLOperator.
(WebCore::MathOperator::setGlyphAssembly): Moved from RenderMathMLOperator.
(WebCore::MathOperator::calculateDisplayStyleLargeOperator): Moved from RenderMathMLOperator with additional style parameter.
(WebCore::MathOperator::calculateGlyphAssemblyFallBack): Ditto.
(WebCore::MathOperator::calculateStretchyData): Ditto.
(WebCore::MathOperator::paintGlyph): Ditto.
(WebCore::MathOperator::fillWithVerticalExtensionGlyph): Ditto.
(WebCore::MathOperator::fillWithHorizontalExtensionGlyph): Ditto.
(WebCore::MathOperator::paintVerticalGlyphAssembly): Ditto.
(WebCore::MathOperator::paintHorizontalGlyphAssembly): Ditto.
* rendering/mathml/MathOperator.h: Added.
(WebCore::MathOperator::italicCorrection):
(WebCore::MathOperator::isStretched):
(WebCore::MathOperator::unstretch):
(WebCore::MathOperator::GlyphAssemblyData::GlyphAssemblyData): Moved from RenderMathMLOperator.
(WebCore::MathOperator::stretchSize):
* rendering/mathml/RenderMathMLOperator.cpp:
(WebCore::RenderMathMLOperator::computePreferredLogicalWidths): Updated to use MathOperator members.
For now we call setOperator to transmit information to m_mathOperator.
(WebCore::RenderMathMLOperator::updateStyle): Updated to use MathOperator members.
For now we set some m_mathOperator members to transmit it some information.
(WebCore::RenderMathMLOperator::firstLineBaseline): Updated to use MathOperator members.
(WebCore::RenderMathMLOperator::computeLogicalHeight): Ditto.
(WebCore::RenderMathMLOperator::paint): Ditto.
For now we set some m_mathOperator members to transmit it some information.
(WebCore::RenderMathMLOperator::paintChildren): Updated to use MathOperator members.
(WebCore::RenderMathMLOperator::trailingSpaceError): Ditto.
(WebCore::RenderMathMLOperator::getBaseGlyph): Deleted.
(WebCore::RenderMathMLOperator::setSizeVariant): Deleted.
(WebCore::RenderMathMLOperator::setGlyphAssembly): Deleted.
(WebCore::RenderMathMLOperator::calculateGlyphAssemblyFallBack): Deleted.
(WebCore::RenderMathMLOperator::calculateDisplayStyleLargeOperator): Deleted.
(WebCore::RenderMathMLOperator::calculateStretchyData): Deleted.
(WebCore::RenderMathMLOperator::paintGlyph): Deleted.
(WebCore::RenderMathMLOperator::fillWithVerticalExtensionGlyph): Deleted.
(WebCore::RenderMathMLOperator::fillWithHorizontalExtensionGlyph): Deleted.
(WebCore::RenderMathMLOperator::paintVerticalGlyphAssembly): Deleted.
(WebCore::RenderMathMLOperator::paintHorizontalGlyphAssembly): Deleted.
* rendering/mathml/RenderMathMLOperator.h:
(WebCore::RenderMathMLOperator::italicCorrection): Updated to use MathOperator members.
(WebCore::RenderMathMLOperator::GlyphAssemblyData::GlyphAssemblyData): Deleted.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreCMakeListstxt">trunk/Source/WebCore/CMakeLists.txt</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreWebCorexcodeprojprojectpbxproj">trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceWebCorerenderingmathmlRenderMathMLOperatorcpp">trunk/Source/WebCore/rendering/mathml/RenderMathMLOperator.cpp</a></li>
<li><a href="#trunkSourceWebCorerenderingmathmlRenderMathMLOperatorh">trunk/Source/WebCore/rendering/mathml/RenderMathMLOperator.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceWebCorerenderingmathmlMathOperatorcpp">trunk/Source/WebCore/rendering/mathml/MathOperator.cpp</a></li>
<li><a href="#trunkSourceWebCorerenderingmathmlMathOperatorh">trunk/Source/WebCore/rendering/mathml/MathOperator.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreCMakeListstxt"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/CMakeLists.txt (201853 => 201854)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/CMakeLists.txt        2016-06-09 05:43:46 UTC (rev 201853)
+++ trunk/Source/WebCore/CMakeLists.txt        2016-06-09 06:17:40 UTC (rev 201854)
</span><span class="lines">@@ -2517,6 +2517,7 @@
</span><span class="cx">     rendering/line/TrailingObjects.cpp
</span><span class="cx"> 
</span><span class="cx">     rendering/mathml/MathMLOperatorDictionary.cpp
</span><ins>+    rendering/mathml/MathOperator.cpp
</ins><span class="cx">     rendering/mathml/RenderMathMLBlock.cpp
</span><span class="cx">     rendering/mathml/RenderMathMLFenced.cpp
</span><span class="cx">     rendering/mathml/RenderMathMLFraction.cpp
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (201853 => 201854)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2016-06-09 05:43:46 UTC (rev 201853)
+++ trunk/Source/WebCore/ChangeLog        2016-06-09 06:17:40 UTC (rev 201854)
</span><span class="lines">@@ -1,3 +1,63 @@
</span><ins>+2016-06-08  Frederic Wang  &lt;fwang@igalia.com&gt;
+
+        Move selection and drawing of stretchy operators into a separate MathOperator class
+        https://bugs.webkit.org/show_bug.cgi?id=156921
+
+        Reviewed by Martin Robinson.
+
+        No new tests, behavior is not changed.
+
+        * CMakeLists.txt: Add the MathOperator files.
+        * WebCore.xcodeproj/project.pbxproj: Ditto.
+        * rendering/mathml/MathOperator.cpp: Added.
+        (WebCore::boundsForGlyph): Moved from RenderMathMLOperator.
+        (WebCore::heightForGlyph): Moved from RenderMathMLOperator.
+        (WebCore::advanceWidthForGlyph): Moved from RenderMathMLOperator.
+        (WebCore::MathOperator::MathOperator):
+        (WebCore::MathOperator::setOperator):
+        (WebCore::MathOperator::getBaseGlyph): Moved from RenderMathMLOperator.
+        (WebCore::MathOperator::setSizeVariant): Moved from RenderMathMLOperator.
+        (WebCore::MathOperator::setGlyphAssembly): Moved from RenderMathMLOperator.
+        (WebCore::MathOperator::calculateDisplayStyleLargeOperator): Moved from RenderMathMLOperator with additional style parameter.
+        (WebCore::MathOperator::calculateGlyphAssemblyFallBack): Ditto.
+        (WebCore::MathOperator::calculateStretchyData): Ditto.
+        (WebCore::MathOperator::paintGlyph): Ditto.
+        (WebCore::MathOperator::fillWithVerticalExtensionGlyph): Ditto.
+        (WebCore::MathOperator::fillWithHorizontalExtensionGlyph): Ditto.
+        (WebCore::MathOperator::paintVerticalGlyphAssembly): Ditto.
+        (WebCore::MathOperator::paintHorizontalGlyphAssembly): Ditto.
+        * rendering/mathml/MathOperator.h: Added.
+        (WebCore::MathOperator::italicCorrection):
+        (WebCore::MathOperator::isStretched):
+        (WebCore::MathOperator::unstretch):
+        (WebCore::MathOperator::GlyphAssemblyData::GlyphAssemblyData): Moved from RenderMathMLOperator.
+        (WebCore::MathOperator::stretchSize):
+        * rendering/mathml/RenderMathMLOperator.cpp:
+        (WebCore::RenderMathMLOperator::computePreferredLogicalWidths): Updated to use MathOperator members.
+        For now we call setOperator to transmit information to m_mathOperator.
+        (WebCore::RenderMathMLOperator::updateStyle): Updated to use MathOperator members.
+        For now we set some m_mathOperator members to transmit it some information.
+        (WebCore::RenderMathMLOperator::firstLineBaseline): Updated to use MathOperator members.
+        (WebCore::RenderMathMLOperator::computeLogicalHeight): Ditto.
+        (WebCore::RenderMathMLOperator::paint): Ditto.
+        For now we set some m_mathOperator members to transmit it some information.
+        (WebCore::RenderMathMLOperator::paintChildren): Updated to use MathOperator members.
+        (WebCore::RenderMathMLOperator::trailingSpaceError): Ditto.
+        (WebCore::RenderMathMLOperator::getBaseGlyph): Deleted.
+        (WebCore::RenderMathMLOperator::setSizeVariant): Deleted.
+        (WebCore::RenderMathMLOperator::setGlyphAssembly): Deleted.
+        (WebCore::RenderMathMLOperator::calculateGlyphAssemblyFallBack): Deleted.
+        (WebCore::RenderMathMLOperator::calculateDisplayStyleLargeOperator): Deleted.
+        (WebCore::RenderMathMLOperator::calculateStretchyData): Deleted.
+        (WebCore::RenderMathMLOperator::paintGlyph): Deleted.
+        (WebCore::RenderMathMLOperator::fillWithVerticalExtensionGlyph): Deleted.
+        (WebCore::RenderMathMLOperator::fillWithHorizontalExtensionGlyph): Deleted.
+        (WebCore::RenderMathMLOperator::paintVerticalGlyphAssembly): Deleted.
+        (WebCore::RenderMathMLOperator::paintHorizontalGlyphAssembly): Deleted.
+        * rendering/mathml/RenderMathMLOperator.h:
+        (WebCore::RenderMathMLOperator::italicCorrection): Updated to use MathOperator members.
+        (WebCore::RenderMathMLOperator::GlyphAssemblyData::GlyphAssemblyData): Deleted.
+
</ins><span class="cx"> 2016-06-08  Chris Dumez  &lt;cdumez@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         DedicatedWorkerGlobalScope prototype chain is incorrect
</span></span></pre></div>
<a id="trunkSourceWebCoreWebCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (201853 => 201854)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj        2016-06-09 05:43:46 UTC (rev 201853)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj        2016-06-09 06:17:40 UTC (rev 201854)
</span><span class="lines">@@ -1670,6 +1670,8 @@
</span><span class="cx">                 439046E812DA25E800AF80A2 /* RenderMathMLScripts.h in Headers */ = {isa = PBXBuildFile; fileRef = 439046D412DA25E800AF80A2 /* RenderMathMLScripts.h */; };
</span><span class="cx">                 439046E912DA25E800AF80A2 /* RenderMathMLUnderOver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 439046D512DA25E800AF80A2 /* RenderMathMLUnderOver.cpp */; };
</span><span class="cx">                 439046EA12DA25E800AF80A2 /* RenderMathMLUnderOver.h in Headers */ = {isa = PBXBuildFile; fileRef = 439046D612DA25E800AF80A2 /* RenderMathMLUnderOver.h */; };
</span><ins>+                439046E912DA25E812AF80AC /* MathOperator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 439046D512DA25E812AF80AC /* MathOperator.cpp */; };
+                439046EA12DA25E812AF80AC /* MathOperator.h in Headers */ = {isa = PBXBuildFile; fileRef = 439046D612DA25E812AF80AC /* MathOperator.h */; };
</ins><span class="cx">                 439046EB12DA25E800AF80A9 /* RenderMathMLToken.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 439046D712DA25E800AF80A9 /* RenderMathMLToken.cpp */; };
</span><span class="cx">                 439046EC12DA25E800AF80A9 /* RenderMathMLToken.h in Headers */ = {isa = PBXBuildFile; fileRef = 439046D812DA25E800AF80A9 /* RenderMathMLToken.h */; };
</span><span class="cx">                 439D334313A6911C00C20F4F /* SVGAnimatedType.h in Headers */ = {isa = PBXBuildFile; fileRef = 439D334013A6911C00C20F4F /* SVGAnimatedType.h */; };
</span><span class="lines">@@ -9233,6 +9235,8 @@
</span><span class="cx">                 439046D412DA25E800AF80A2 /* RenderMathMLScripts.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderMathMLScripts.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 439046D512DA25E800AF80A2 /* RenderMathMLUnderOver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderMathMLUnderOver.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 439046D612DA25E800AF80A2 /* RenderMathMLUnderOver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderMathMLUnderOver.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                439046D512DA25E812AF80AC /* MathOperator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MathOperator.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                439046D612DA25E812AF80AC /* MathOperator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MathOperator.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 439046D712DA25E800AF80A9 /* RenderMathMLToken.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderMathMLToken.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 439046D812DA25E800AF80A9 /* RenderMathMLToken.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderMathMLToken.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 439D334013A6911C00C20F4F /* SVGAnimatedType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SVGAnimatedType.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -16983,6 +16987,8 @@
</span><span class="cx">                                 439046D812DA25E800AF80A9 /* RenderMathMLToken.h */,
</span><span class="cx">                                 439046D512DA25E800AF80A2 /* RenderMathMLUnderOver.cpp */,
</span><span class="cx">                                 439046D612DA25E800AF80A2 /* RenderMathMLUnderOver.h */,
</span><ins>+                                439046D512DA25E812AF80AC /* MathOperator.cpp */,
+                                439046D612DA25E812AF80AC /* MathOperator.h */,
</ins><span class="cx">                         );
</span><span class="cx">                         path = mathml;
</span><span class="cx">                         sourceTree = &quot;&lt;group&gt;&quot;;
</span><span class="lines">@@ -27701,6 +27707,7 @@
</span><span class="cx">                                 439046E612DA25E800AF80A2 /* RenderMathMLSquareRoot.h in Headers */,
</span><span class="cx">                                 439046EC12DA25E800AF80A9 /* RenderMathMLToken.h in Headers */,
</span><span class="cx">                                 439046EA12DA25E800AF80A2 /* RenderMathMLUnderOver.h in Headers */,
</span><ins>+                                439046EA12DA25E812AF80AC /* MathOperator.h in Headers */,
</ins><span class="cx">                                 E4C279590CF9741900E97B98 /* RenderMedia.h in Headers */,
</span><span class="cx">                                 DEBCCDD216646E8200A452E1 /* RenderMediaControlElements.h in Headers */,
</span><span class="cx">                                 41FA303F1316C29C00C0BFC5 /* RenderMediaControls.h in Headers */,
</span><span class="lines">@@ -31381,6 +31388,7 @@
</span><span class="cx">                                 439046E512DA25E800AF80A2 /* RenderMathMLSquareRoot.cpp in Sources */,
</span><span class="cx">                                 439046EB12DA25E800AF80A9 /* RenderMathMLToken.cpp in Sources */,
</span><span class="cx">                                 439046E912DA25E800AF80A2 /* RenderMathMLUnderOver.cpp in Sources */,
</span><ins>+                                439046E912DA25E812AF80AC /* MathOperator.cpp in Sources */,
</ins><span class="cx">                                 E4C279580CF9741900E97B98 /* RenderMedia.cpp in Sources */,
</span><span class="cx">                                 DE49B309165F2FE10010338D /* RenderMediaControlElements.cpp in Sources */,
</span><span class="cx">                                 41FA303E1316C29C00C0BFC5 /* RenderMediaControls.cpp in Sources */,
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingmathmlMathOperatorcpp"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/rendering/mathml/MathOperator.cpp (0 => 201854)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/mathml/MathOperator.cpp                                (rev 0)
+++ trunk/Source/WebCore/rendering/mathml/MathOperator.cpp        2016-06-09 06:17:40 UTC (rev 201854)
</span><span class="lines">@@ -0,0 +1,504 @@
</span><ins>+/*
+ * Copyright (C) 2016 Igalia S.L. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * &quot;AS IS&quot; AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include &quot;config.h&quot;
+
+#if ENABLE(MATHML)
+#include &quot;MathOperator.h&quot;
+
+#include &quot;RenderStyle.h&quot;
+#include &quot;StyleInheritedData.h&quot;
+
+namespace WebCore {
+
+static inline FloatRect boundsForGlyph(const GlyphData&amp; data)
+{
+    return data.isValid() ? data.font-&gt;boundsForGlyph(data.glyph) : FloatRect();
+}
+
+static inline float heightForGlyph(const GlyphData&amp; data)
+{
+    return boundsForGlyph(data).height();
+}
+
+static inline float advanceWidthForGlyph(const GlyphData&amp; data)
+{
+    return data.isValid() ? data.font-&gt;widthForGlyph(data.glyph) : 0;
+}
+
+// FIXME: This hardcoded data can be removed when OpenType MATH font are widely available (http://wkbug/156837).
+struct StretchyCharacter {
+    UChar character;
+    UChar topChar;
+    UChar extensionChar;
+    UChar bottomChar;
+    UChar middleChar;
+};
+// The first leftRightPairsCount pairs correspond to left/right fences that can easily be mirrored in RTL.
+static const short leftRightPairsCount = 5;
+static const StretchyCharacter stretchyCharacters[14] = {
+    { 0x28  , 0x239b, 0x239c, 0x239d, 0x0    }, // left parenthesis
+    { 0x29  , 0x239e, 0x239f, 0x23a0, 0x0    }, // right parenthesis
+    { 0x5b  , 0x23a1, 0x23a2, 0x23a3, 0x0    }, // left square bracket
+    { 0x5d  , 0x23a4, 0x23a5, 0x23a6, 0x0    }, // right square bracket
+    { 0x7b  , 0x23a7, 0x23aa, 0x23a9, 0x23a8 }, // left curly bracket
+    { 0x7d  , 0x23ab, 0x23aa, 0x23ad, 0x23ac }, // right curly bracket
+    { 0x2308, 0x23a1, 0x23a2, 0x23a2, 0x0    }, // left ceiling
+    { 0x2309, 0x23a4, 0x23a5, 0x23a5, 0x0    }, // right ceiling
+    { 0x230a, 0x23a2, 0x23a2, 0x23a3, 0x0    }, // left floor
+    { 0x230b, 0x23a5, 0x23a5, 0x23a6, 0x0    }, // right floor
+    { 0x7c  , 0x7c,   0x7c,   0x7c,   0x0    }, // vertical bar
+    { 0x2016, 0x2016, 0x2016, 0x2016, 0x0    }, // double vertical line
+    { 0x2225, 0x2225, 0x2225, 0x2225, 0x0    }, // parallel to
+    { 0x222b, 0x2320, 0x23ae, 0x2321, 0x0    } // integral sign
+};
+
+void MathOperator::setOperator(UChar baseCharacter, bool isVertical)
+{
+    m_baseCharacter = baseCharacter;
+    m_isVertical = isVertical;
+}
+
+bool MathOperator::getBaseGlyph(const RenderStyle&amp; style, GlyphData&amp; baseGlyph) const
+{
+    baseGlyph = style.fontCascade().glyphDataForCharacter(m_baseCharacter, !style.isLeftToRightDirection());
+    return baseGlyph.isValid() &amp;&amp; baseGlyph.font == &amp;style.fontCascade().primaryFont();
+}
+
+void MathOperator::setSizeVariant(const GlyphData&amp; sizeVariant)
+{
+    ASSERT(sizeVariant.isValid());
+    ASSERT(sizeVariant.font-&gt;mathData());
+    m_stretchType = StretchType::SizeVariant;
+    m_variant = sizeVariant;
+}
+
+void MathOperator::setGlyphAssembly(const GlyphAssemblyData&amp; assemblyData)
+{
+    m_stretchType = StretchType::GlyphAssembly;
+    m_assembly = assemblyData;
+}
+
+void MathOperator::calculateDisplayStyleLargeOperator(const RenderStyle&amp; style)
+{
+    ASSERT(m_isVertical);
+
+    GlyphData baseGlyph;
+    if (!getBaseGlyph(style, baseGlyph) || !baseGlyph.font-&gt;mathData())
+        return;
+
+    // The value of displayOperatorMinHeight is sometimes too small, so we ensure that it is at least \sqrt{2} times the size of the base glyph.
+    float displayOperatorMinHeight = std::max(heightForGlyph(baseGlyph) * sqrtOfTwoFloat, baseGlyph.font-&gt;mathData()-&gt;getMathConstant(*baseGlyph.font, OpenTypeMathData::DisplayOperatorMinHeight));
+
+    Vector&lt;Glyph&gt; sizeVariants;
+    Vector&lt;OpenTypeMathData::AssemblyPart&gt; assemblyParts;
+    baseGlyph.font-&gt;mathData()-&gt;getMathVariants(baseGlyph.glyph, true, sizeVariants, assemblyParts);
+
+    // We choose the first size variant that is larger than the expected displayOperatorMinHeight and otherwise fallback to the largest variant.
+    for (auto&amp; sizeVariant : sizeVariants) {
+        GlyphData glyphData(sizeVariant, baseGlyph.font);
+        setSizeVariant(glyphData);
+        m_italicCorrection = glyphData.font-&gt;mathData()-&gt;getItalicCorrection(*glyphData.font, glyphData.glyph);
+        if (heightForGlyph(glyphData) &gt;= displayOperatorMinHeight)
+            break;
+    }
+}
+
+bool MathOperator::calculateGlyphAssemblyFallback(const RenderStyle&amp; style, const Vector&lt;OpenTypeMathData::AssemblyPart&gt;&amp; assemblyParts, GlyphAssemblyData&amp; assemblyData) const
+{
+    // The structure of the Open Type Math table is a bit more general than the one currently used by the MathOperator code, so we try to fallback in a reasonable way.
+    // FIXME: MathOperator should support the most general format (https://bugs.webkit.org/show_bug.cgi?id=130327).
+    // We use the approach of the copyComponents function in github.com/mathjax/MathJax-dev/blob/master/fonts/OpenTypeMath/fontUtil.py
+
+    // We count the number of non extender pieces.
+    int nonExtenderCount = 0;
+    for (auto&amp; part : assemblyParts) {
+        if (!part.isExtender)
+            nonExtenderCount++;
+    }
+    if (nonExtenderCount &gt; 3)
+        return false; // This is not supported: there are too many pieces.
+
+    // We now browse the list of pieces from left to right for horizontal operators and from bottom to top for vertical operators.
+    enum PartType {
+        Start,
+        ExtenderBetweenStartAndMiddle,
+        Middle,
+        ExtenderBetweenMiddleAndEnd,
+        End,
+        None
+    };
+    PartType expectedPartType = Start;
+    assemblyData.extension.glyph = 0;
+    assemblyData.middle.glyph = 0;
+    for (auto&amp; part : assemblyParts) {
+        if (nonExtenderCount &lt; 3) {
+            // If we only have at most two non-extenders then we skip the middle glyph.
+            if (expectedPartType == ExtenderBetweenStartAndMiddle)
+                expectedPartType = ExtenderBetweenMiddleAndEnd;
+            else if (expectedPartType == Middle)
+                expectedPartType = End;
+        }
+        if (part.isExtender) {
+            if (!assemblyData.extension.glyph)
+                assemblyData.extension.glyph = part.glyph; // We copy the extender part.
+            else if (assemblyData.extension.glyph != part.glyph)
+                return false; // This is not supported: the assembly has different extenders.
+
+            switch (expectedPartType) {
+            case Start:
+                // We ignore the left/bottom part.
+                expectedPartType = ExtenderBetweenStartAndMiddle;
+                continue;
+            case Middle:
+                // We ignore the middle part.
+                expectedPartType = ExtenderBetweenMiddleAndEnd;
+                continue;
+            case End:
+            case None:
+                // This is not supported: we got an unexpected extender.
+                return false;
+            case ExtenderBetweenStartAndMiddle:
+            case ExtenderBetweenMiddleAndEnd:
+                // We ignore multiple consecutive extenders.
+                continue;
+            }
+        }
+
+        switch (expectedPartType) {
+        case Start:
+            // We copy the left/bottom part.
+            assemblyData.bottomOrLeft.glyph = part.glyph;
+            expectedPartType = ExtenderBetweenStartAndMiddle;
+            continue;
+        case ExtenderBetweenStartAndMiddle:
+        case Middle:
+            // We copy the middle part.
+            assemblyData.middle.glyph = part.glyph;
+            expectedPartType = ExtenderBetweenMiddleAndEnd;
+            continue;
+        case ExtenderBetweenMiddleAndEnd:
+        case End:
+            // We copy the right/top part.
+            assemblyData.topOrRight.glyph = part.glyph;
+            expectedPartType = None;
+            continue;
+        case None:
+            // This is not supported: we got an unexpected non-extender part.
+            return false;
+        }
+    }
+
+    if (!assemblyData.extension.glyph)
+        return false; // This is not supported: we always assume that we have an extension glyph.
+
+    // If we don't have top/bottom glyphs, we use the extension glyph.
+    if (!assemblyData.topOrRight.glyph)
+        assemblyData.topOrRight.glyph = assemblyData.extension.glyph;
+    if (!assemblyData.bottomOrLeft.glyph)
+        assemblyData.bottomOrLeft.glyph = assemblyData.extension.glyph;
+
+    assemblyData.topOrRight.font = &amp;style.fontCascade().primaryFont();
+    assemblyData.extension.font = assemblyData.topOrRight.font;
+    assemblyData.bottomOrLeft.font = assemblyData.topOrRight.font;
+    assemblyData.middle.font = assemblyData.middle.glyph ? assemblyData.topOrRight.font : nullptr;
+
+    return true;
+}
+
+void MathOperator::calculateStretchyData(const RenderStyle&amp; style, float* maximumGlyphWidth, LayoutUnit targetSize)
+{
+    ASSERT(!maximumGlyphWidth || m_isVertical);
+
+    GlyphData baseGlyph;
+    if (!getBaseGlyph(style, baseGlyph))
+        return;
+
+    if (!maximumGlyphWidth) {
+        // We do not stretch if the base glyph is large enough.
+        float baseSize = m_isVertical ? heightForGlyph(baseGlyph) : advanceWidthForGlyph(baseGlyph);
+        if (targetSize &lt;= baseSize)
+            return;
+    }
+
+    MathOperator::GlyphAssemblyData assemblyData;
+    if (baseGlyph.font-&gt;mathData()) {
+        Vector&lt;Glyph&gt; sizeVariants;
+        Vector&lt;OpenTypeMathData::AssemblyPart&gt; assemblyParts;
+        baseGlyph.font-&gt;mathData()-&gt;getMathVariants(baseGlyph.glyph, m_isVertical, sizeVariants, assemblyParts);
+        // We verify the size variants.
+        for (auto&amp; sizeVariant : sizeVariants) {
+            GlyphData glyphData(sizeVariant, baseGlyph.font);
+            if (maximumGlyphWidth)
+                *maximumGlyphWidth = std::max(*maximumGlyphWidth, advanceWidthForGlyph(glyphData));
+            else {
+                setSizeVariant(glyphData);
+                float size = m_isVertical ? heightForGlyph(glyphData) : advanceWidthForGlyph(glyphData);
+                if (size &gt;= targetSize)
+                    return;
+            }
+        }
+
+        // We verify if there is a construction.
+        if (!calculateGlyphAssemblyFallback(style, assemblyParts, assemblyData))
+            return;
+    } else {
+        if (!m_isVertical)
+            return;
+
+        // 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);
+        for (unsigned index = 0; index &lt; maxIndex; ++index) {
+            if (stretchyCharacters[index].character == m_baseCharacter) {
+                stretchyCharacter = &amp;stretchyCharacters[index];
+                if (!style.isLeftToRightDirection() &amp;&amp; index &lt; leftRightPairsCount * 2) {
+                    // If we are in right-to-left direction we select the mirrored form by adding -1 or +1 according to the parity of index.
+                    index += index % 2 ? -1 : 1;
+                }
+                break;
+            }
+        }
+
+        // If we didn't find a stretchy character set for this character, we don't know how to stretch it.
+        if (!stretchyCharacter)
+            return;
+
+        // We convert the list of Unicode characters into a list of glyph data.
+        assemblyData.topOrRight = style.fontCascade().glyphDataForCharacter(stretchyCharacter-&gt;topChar, false);
+        assemblyData.extension = style.fontCascade().glyphDataForCharacter(stretchyCharacter-&gt;extensionChar, false);
+        assemblyData.bottomOrLeft = style.fontCascade().glyphDataForCharacter(stretchyCharacter-&gt;bottomChar, false);
+        assemblyData.middle = stretchyCharacter-&gt;middleChar ? style.fontCascade().glyphDataForCharacter(stretchyCharacter-&gt;middleChar, false) : GlyphData();
+    }
+
+    // If we are measuring the maximum width, verify each component.
+    if (maximumGlyphWidth) {
+        *maximumGlyphWidth = std::max(*maximumGlyphWidth, advanceWidthForGlyph(assemblyData.topOrRight));
+        *maximumGlyphWidth = std::max(*maximumGlyphWidth, advanceWidthForGlyph(assemblyData.extension));
+        *maximumGlyphWidth = std::max(*maximumGlyphWidth, advanceWidthForGlyph(assemblyData.middle));
+        *maximumGlyphWidth = std::max(*maximumGlyphWidth, advanceWidthForGlyph(assemblyData.bottomOrLeft));
+        return;
+    }
+
+    // We ensure that the size is large enough to avoid glyph overlaps.
+    float minSize = m_isVertical ?
+        heightForGlyph(assemblyData.topOrRight) + heightForGlyph(assemblyData.middle) + heightForGlyph(assemblyData.bottomOrLeft)
+        : advanceWidthForGlyph(assemblyData.bottomOrLeft) + advanceWidthForGlyph(assemblyData.middle) + advanceWidthForGlyph(assemblyData.topOrRight);
+    if (minSize &gt; targetSize)
+        return;
+
+    setGlyphAssembly(assemblyData);
+}
+
+LayoutRect MathOperator::paintGlyph(const RenderStyle&amp; style, PaintInfo&amp; info, const GlyphData&amp; data, const LayoutPoint&amp; origin, GlyphPaintTrimming trim)
+{
+    FloatRect glyphBounds = boundsForGlyph(data);
+
+    LayoutRect glyphPaintRect(origin, LayoutSize(glyphBounds.x() + glyphBounds.width(), glyphBounds.height()));
+    glyphPaintRect.setY(origin.y() + glyphBounds.y());
+
+    // In order to have glyphs fit snugly with one another we snap the connecting edges to pixel boundaries
+    // and trim off one pixel. The pixel trim is to account for fonts that have edge pixels that have less
+    // than full coverage. These edge pixels can introduce small seams between connected glyphs.
+    FloatRect clipBounds = info.rect;
+    switch (trim) {
+    case TrimTop:
+        glyphPaintRect.shiftYEdgeTo(glyphPaintRect.y().ceil() + 1);
+        clipBounds.shiftYEdgeTo(glyphPaintRect.y());
+        break;
+    case TrimBottom:
+        glyphPaintRect.shiftMaxYEdgeTo(glyphPaintRect.maxY().floor() - 1);
+        clipBounds.shiftMaxYEdgeTo(glyphPaintRect.maxY());
+        break;
+    case TrimTopAndBottom:
+        glyphPaintRect.shiftYEdgeTo(glyphPaintRect.y().ceil() + 1);
+        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:
+        glyphPaintRect.shiftXEdgeTo(glyphPaintRect.x().ceil() + 1);
+        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.
+    GraphicsContextStateSaver stateSaver(info.context());
+    info.context().clip(clipBounds);
+
+    GlyphBuffer buffer;
+    buffer.add(data.glyph, data.font, advanceWidthForGlyph(data));
+    info.context().drawGlyphs(style.fontCascade(), *data.font, buffer, 0, 1, origin);
+
+    return glyphPaintRect;
+}
+
+void MathOperator::fillWithVerticalExtensionGlyph(const RenderStyle&amp; style, PaintInfo&amp; info, const LayoutPoint&amp; from, const LayoutPoint&amp; to)
+{
+    ASSERT(m_isVertical);
+    ASSERT(m_stretchType == StretchType::GlyphAssembly);
+    ASSERT(m_assembly.extension.isValid());
+    ASSERT(from.y() &lt;= to.y());
+
+    // If there is no space for the extension glyph, we don't need to do anything.
+    if (from.y() == to.y())
+        return;
+
+    GraphicsContextStateSaver stateSaver(info.context());
+
+    FloatRect glyphBounds = boundsForGlyph(m_assembly.extension);
+
+    // 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.shiftYEdgeTo(from.y());
+    clipBounds.shiftMaxYEdgeTo(to.y());
+    info.context().clip(clipBounds);
+
+    // Trimming may remove up to two pixels from the top of the extender glyph, so we move it up by two pixels.
+    float offsetToGlyphTop = glyphBounds.y() + 2;
+    LayoutPoint glyphOrigin = LayoutPoint(from.x(), from.y() - offsetToGlyphTop);
+    FloatRect lastPaintedGlyphRect(from, FloatSize());
+
+    while (lastPaintedGlyphRect.maxY() &lt; to.y()) {
+        lastPaintedGlyphRect = paintGlyph(style, info, m_assembly.extension, glyphOrigin, TrimTopAndBottom);
+        glyphOrigin.setY(glyphOrigin.y() + lastPaintedGlyphRect.height());
+
+        // 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 MathOperator::fillWithHorizontalExtensionGlyph(const RenderStyle&amp; style, PaintInfo&amp; info, const LayoutPoint&amp; from, const LayoutPoint&amp; to)
+{
+    ASSERT(!m_isVertical);
+    ASSERT(m_stretchType == StretchType::GlyphAssembly);
+    ASSERT(m_assembly.extension.isValid());
+    ASSERT(from.x() &lt;= 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()));
+    FloatRect lastPaintedGlyphRect(from, FloatSize());
+
+    while (lastPaintedGlyphRect.maxX() &lt; to.x()) {
+        lastPaintedGlyphRect = paintGlyph(style, info, m_assembly.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 MathOperator::paintVerticalGlyphAssembly(const RenderStyle&amp; style, PaintInfo&amp; info, const LayoutPoint&amp; paintOffset)
+{
+    ASSERT(m_isVertical);
+    ASSERT(m_stretchType == StretchType::GlyphAssembly);
+    ASSERT(m_assembly.topOrRight.isValid());
+    ASSERT(m_assembly.bottomOrLeft.isValid());
+
+    // 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;
+    operatorTopLeft = ceiledIntPoint(operatorTopLeft);
+    FloatRect topGlyphBounds = boundsForGlyph(m_assembly.topOrRight);
+    LayoutPoint topGlyphOrigin(operatorTopLeft.x(), operatorTopLeft.y() - topGlyphBounds.y());
+    LayoutRect topGlyphPaintRect = paintGlyph(style, info, m_assembly.topOrRight, topGlyphOrigin, TrimBottom);
+
+    FloatRect bottomGlyphBounds = boundsForGlyph(m_assembly.bottomOrLeft);
+    LayoutPoint bottomGlyphOrigin(operatorTopLeft.x(), operatorTopLeft.y() + stretchSize() - (bottomGlyphBounds.height() + bottomGlyphBounds.y()));
+    LayoutRect bottomGlyphPaintRect = paintGlyph(style, info, m_assembly.bottomOrLeft, bottomGlyphOrigin, TrimTop);
+
+    if (m_assembly.middle.isValid()) {
+        // Center the glyph origin between the start and end glyph paint extents. Then shift it half the paint height toward the bottom glyph.
+        FloatRect middleGlyphBounds = boundsForGlyph(m_assembly.middle);
+        LayoutPoint middleGlyphOrigin(operatorTopLeft.x(), topGlyphOrigin.y());
+        middleGlyphOrigin.moveBy(LayoutPoint(0, (bottomGlyphPaintRect.y() - topGlyphPaintRect.maxY()) / 2.0));
+        middleGlyphOrigin.moveBy(LayoutPoint(0, middleGlyphBounds.height() / 2.0));
+
+        LayoutRect middleGlyphPaintRect = paintGlyph(style, info, m_assembly.middle, middleGlyphOrigin, TrimTopAndBottom);
+        fillWithVerticalExtensionGlyph(style, info, topGlyphPaintRect.minXMaxYCorner(), middleGlyphPaintRect.minXMinYCorner());
+        fillWithVerticalExtensionGlyph(style, info, middleGlyphPaintRect.minXMaxYCorner(), bottomGlyphPaintRect.minXMinYCorner());
+    } else
+        fillWithVerticalExtensionGlyph(style, info, topGlyphPaintRect.minXMaxYCorner(), bottomGlyphPaintRect.minXMinYCorner());
+}
+
+void MathOperator::paintHorizontalGlyphAssembly(const RenderStyle&amp; style, PaintInfo&amp; info, const LayoutPoint&amp; paintOffset)
+{
+    ASSERT(!m_isVertical);
+    ASSERT(m_stretchType == StretchType::GlyphAssembly);
+    ASSERT(m_assembly.bottomOrLeft.isValid());
+    ASSERT(m_assembly.topOrRight.isValid());
+
+    // 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;
+    operatorTopLeft = ceiledIntPoint(operatorTopLeft);
+    LayoutPoint leftGlyphOrigin(operatorTopLeft.x(), operatorTopLeft.y() + m_ascent);
+    LayoutRect leftGlyphPaintRect = paintGlyph(style, info, m_assembly.bottomOrLeft, leftGlyphOrigin, TrimRight);
+
+    FloatRect rightGlyphBounds = boundsForGlyph(m_assembly.topOrRight);
+    LayoutPoint rightGlyphOrigin(operatorTopLeft.x() + m_width - rightGlyphBounds.width(), operatorTopLeft.y() + m_ascent);
+    LayoutRect rightGlyphPaintRect = paintGlyph(style, info, m_assembly.topOrRight, rightGlyphOrigin, TrimLeft);
+
+    LayoutPoint baselineShift(0, m_ascent);
+    if (m_assembly.middle.isValid()) {
+        // 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(style, info, m_assembly.middle, middleGlyphOrigin, TrimLeftAndRight);
+        fillWithHorizontalExtensionGlyph(style, info, leftGlyphPaintRect.maxXMinYCorner() + baselineShift, middleGlyphPaintRect.minXMinYCorner() + baselineShift);
+        fillWithHorizontalExtensionGlyph(style, info, middleGlyphPaintRect.maxXMinYCorner() + baselineShift, rightGlyphPaintRect.minXMinYCorner() + baselineShift);
+    } else
+        fillWithHorizontalExtensionGlyph(style, info, leftGlyphPaintRect.maxXMinYCorner() + baselineShift, rightGlyphPaintRect.minXMinYCorner() + baselineShift);
+}
+
+}
+
+#endif
</ins><span class="cx">Property changes on: trunk/Source/WebCore/rendering/mathml/MathOperator.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceWebCorerenderingmathmlMathOperatorh"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/rendering/mathml/MathOperator.h (0 => 201854)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/mathml/MathOperator.h                                (rev 0)
+++ trunk/Source/WebCore/rendering/mathml/MathOperator.h        2016-06-09 06:17:40 UTC (rev 201854)
</span><span class="lines">@@ -0,0 +1,98 @@
</span><ins>+/*
+ * Copyright (C) 2016 Igalia S.L. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * &quot;AS IS&quot; AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef MathOperator_h
+#define MathOperator_h
+
+#if ENABLE(MATHML)
+#include &quot;GlyphPage.h&quot;
+#include &quot;LayoutUnit.h&quot;
+#include &quot;OpenTypeMathData.h&quot;
+#include &quot;PaintInfo.h&quot;
+#include &lt;unicode/utypes.h&gt;
+
+namespace WebCore {
+
+class RenderStyle;
+
+class MathOperator {
+public:
+    MathOperator() { }
+    void setOperator(UChar baseCharacter, bool isVertical);
+
+    LayoutUnit italicCorrection() const { return m_italicCorrection; }
+
+    bool isStretched() const { return m_stretchType != StretchType::Unstretched; }
+    void unstretch() { m_stretchType = StretchType::Unstretched; }
+
+    // FIXME: All the code below should be private when it is no longer needed by RenderMathMLOperator (http://webkit.org/b/152244).
+
+    struct GlyphAssemblyData {
+        GlyphData topOrRight;
+        GlyphData extension;
+        GlyphData bottomOrLeft;
+        GlyphData middle;
+    };
+    enum class StretchType { Unstretched, SizeVariant, GlyphAssembly };
+    enum GlyphPaintTrimming {
+        TrimTop,
+        TrimBottom,
+        TrimTopAndBottom,
+        TrimLeft,
+        TrimRight,
+        TrimLeftAndRight
+    };
+
+    LayoutUnit stretchSize() const { return m_isVertical ? m_ascent + m_descent : m_width; };
+    bool getBaseGlyph(const RenderStyle&amp;, GlyphData&amp;) const;
+    void setSizeVariant(const GlyphData&amp;);
+    void setGlyphAssembly(const GlyphAssemblyData&amp;);
+    void calculateDisplayStyleLargeOperator(const RenderStyle&amp;);
+    void calculateStretchyData(const RenderStyle&amp;, float* maximumGlyphWidth, LayoutUnit targetSize = 0);
+    bool calculateGlyphAssemblyFallback(const RenderStyle&amp;, const Vector&lt;OpenTypeMathData::AssemblyPart&gt;&amp;, GlyphAssemblyData&amp;) const;
+
+    LayoutRect paintGlyph(const RenderStyle&amp;, PaintInfo&amp;, const GlyphData&amp;, const LayoutPoint&amp; origin, GlyphPaintTrimming);
+    void fillWithVerticalExtensionGlyph(const RenderStyle&amp;, PaintInfo&amp;, const LayoutPoint&amp; from, const LayoutPoint&amp; to);
+    void fillWithHorizontalExtensionGlyph(const RenderStyle&amp;, PaintInfo&amp;, const LayoutPoint&amp; from, const LayoutPoint&amp; to);
+    void paintVerticalGlyphAssembly(const RenderStyle&amp;, PaintInfo&amp;, const LayoutPoint&amp;);
+    void paintHorizontalGlyphAssembly(const RenderStyle&amp;, PaintInfo&amp;, const LayoutPoint&amp;);
+
+    UChar m_baseCharacter = 0;
+    bool m_isVertical = false;
+    StretchType m_stretchType = StretchType::Unstretched;
+    union {
+        GlyphData m_variant;
+        GlyphAssemblyData m_assembly;
+    };
+    LayoutUnit m_width = 0;
+    LayoutUnit m_ascent = 0;
+    LayoutUnit m_descent = 0;
+    LayoutUnit m_italicCorrection = 0;
+};
+
+}
+
+#endif // ENABLE(MATHML)
+#endif // MathOperator_h
</ins><span class="cx">Property changes on: trunk/Source/WebCore/rendering/mathml/MathOperator.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceWebCorerenderingmathmlRenderMathMLOperatorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/mathml/RenderMathMLOperator.cpp (201853 => 201854)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/mathml/RenderMathMLOperator.cpp        2016-06-09 05:43:46 UTC (rev 201853)
+++ trunk/Source/WebCore/rendering/mathml/RenderMathMLOperator.cpp        2016-06-09 06:17:40 UTC (rev 201854)
</span><span class="lines">@@ -45,33 +45,6 @@
</span><span class="cx">     
</span><span class="cx"> using namespace MathMLNames;
</span><span class="cx"> 
</span><del>-// FIXME: The OpenType MATH table contains information that should override this table (http://wkbug/122297).
-struct StretchyCharacter {
-    UChar character;
-    UChar topChar;
-    UChar extensionChar;
-    UChar bottomChar;
-    UChar middleChar;
-};
-// The first leftRightPairsCount pairs correspond to left/right fences that can easily be mirrored in RTL.
-static const short leftRightPairsCount = 5;
-static const StretchyCharacter stretchyCharacters[14] = {
-    { 0x28  , 0x239b, 0x239c, 0x239d, 0x0    }, // left parenthesis
-    { 0x29  , 0x239e, 0x239f, 0x23a0, 0x0    }, // right parenthesis
-    { 0x5b  , 0x23a1, 0x23a2, 0x23a3, 0x0    }, // left square bracket
-    { 0x5d  , 0x23a4, 0x23a5, 0x23a6, 0x0    }, // right square bracket
-    { 0x7b  , 0x23a7, 0x23aa, 0x23a9, 0x23a8 }, // left curly bracket
-    { 0x7d  , 0x23ab, 0x23aa, 0x23ad, 0x23ac }, // right curly bracket
-    { 0x2308, 0x23a1, 0x23a2, 0x23a2, 0x0    }, // left ceiling
-    { 0x2309, 0x23a4, 0x23a5, 0x23a5, 0x0    }, // right ceiling
-    { 0x230a, 0x23a2, 0x23a2, 0x23a3, 0x0    }, // left floor
-    { 0x230b, 0x23a5, 0x23a5, 0x23a6, 0x0    }, // right floor
-    { 0x7c  , 0x7c,   0x7c,   0x7c,   0x0    }, // vertical bar
-    { 0x2016, 0x2016, 0x2016, 0x2016, 0x0    }, // double vertical line
-    { 0x2225, 0x2225, 0x2225, 0x2225, 0x0    }, // parallel to
-    { 0x222b, 0x2320, 0x23ae, 0x2321, 0x0    } // integral sign
-};
-
</del><span class="cx"> RenderMathMLOperator::RenderMathMLOperator(MathMLElement&amp; element, RenderStyle&amp;&amp; style)
</span><span class="cx">     : RenderMathMLToken(element, WTFMove(style))
</span><span class="cx">     , m_stretchHeightAboveBaseline(0)
</span><span class="lines">@@ -294,8 +267,9 @@
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    m_mathOperator.setOperator(m_textContent, m_isVertical);
</ins><span class="cx">     GlyphData baseGlyph;
</span><del>-    float maximumGlyphWidth = getBaseGlyph(style(), baseGlyph) ? advanceWidthForGlyph(baseGlyph) : 0;
</del><ins>+    float maximumGlyphWidth = m_mathOperator.getBaseGlyph(style(), baseGlyph) ? advanceWidthForGlyph(baseGlyph) : 0;
</ins><span class="cx">     if (!m_isVertical) {
</span><span class="cx">         if (maximumGlyphWidth &lt; stretchSize())
</span><span class="cx">             maximumGlyphWidth = stretchSize();
</span><span class="lines">@@ -305,12 +279,12 @@
</span><span class="cx">     }
</span><span class="cx">     if (isLargeOperatorInDisplayStyle()) {
</span><span class="cx">         // 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/).
</span><del>-        calculateDisplayStyleLargeOperator();
-        if (m_stretchType == StretchType::SizeVariant)
-            maximumGlyphWidth = boundsForGlyph(m_variant).width();
</del><ins>+        m_mathOperator.calculateDisplayStyleLargeOperator(style());
+        if (m_mathOperator.m_stretchType == MathOperator::StretchType::SizeVariant)
+            maximumGlyphWidth = boundsForGlyph(m_mathOperator.m_variant).width();
</ins><span class="cx">     } else {
</span><span class="cx">         // FIXME: some glyphs (e.g. the one for &quot;FRACTION SLASH&quot; in the STIX Math font or large operators) have a width that depends on the height, resulting in large gaps (https://bugs.webkit.org/show_bug.cgi?id=130326).
</span><del>-        calculateStretchyData(&amp;maximumGlyphWidth);
</del><ins>+        m_mathOperator.calculateStretchyData(style(), &amp;maximumGlyphWidth);
</ins><span class="cx">     }
</span><span class="cx">     m_maxPreferredLogicalWidth = m_minPreferredLogicalWidth = m_leadingSpace + maximumGlyphWidth + m_trailingSpace;
</span><span class="cx"> }
</span><span class="lines">@@ -374,245 +348,14 @@
</span><span class="cx">     updateOperatorProperties();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool RenderMathMLOperator::getBaseGlyph(const RenderStyle&amp; style, GlyphData&amp; baseGlyph) const
-{
-    baseGlyph = style.fontCascade().glyphDataForCharacter(m_textContent, !style.isLeftToRightDirection());
-    return baseGlyph.isValid() &amp;&amp; baseGlyph.font == &amp;style.fontCascade().primaryFont();
-}
-
-void RenderMathMLOperator::setSizeVariant(const GlyphData&amp; sizeVariant)
-{
-    ASSERT(sizeVariant.isValid() &amp;&amp; sizeVariant.font-&gt;mathData());
-    m_stretchType = StretchType::SizeVariant;
-    m_variant = sizeVariant;
-}
-
-void RenderMathMLOperator::setGlyphAssembly(const GlyphAssemblyData&amp; assemblyData)
-{
-    m_stretchType = StretchType::GlyphAssembly;
-    m_assembly = assemblyData;
-}
-
-bool RenderMathMLOperator::calculateGlyphAssemblyFallBack(const Vector&lt;OpenTypeMathData::AssemblyPart&gt;&amp; assemblyParts, GlyphAssemblyData&amp; assemblyData) const
-{
-    // The structure of the Open Type Math table is a bit more general than the one currently used by the RenderMathMLOperator code, so we try to fallback in a reasonable way.
-    // FIXME: RenderMathMLOperator should support the most general format (https://bugs.webkit.org/show_bug.cgi?id=130327).
-    // We use the approach of the copyComponents function in github.com/mathjax/MathJax-dev/blob/master/fonts/OpenTypeMath/fontUtil.py
-
-    // We count the number of non extender pieces.
-    int nonExtenderCount = 0;
-    for (auto&amp; part : assemblyParts) {
-        if (!part.isExtender)
-            nonExtenderCount++;
-    }
-    if (nonExtenderCount &gt; 3)
-        return false; // This is not supported: there are too many pieces.
-
-    // We now browse the list of pieces from left to right for horizontal operators and from bottom to top for vertical operators.
-    enum PartType {
-        Start,
-        ExtenderBetweenStartAndMiddle,
-        Middle,
-        ExtenderBetweenMiddleAndEnd,
-        End,
-        None
-    };
-    PartType expectedPartType = Start;
-    assemblyData.extension.glyph = 0;
-    assemblyData.middle.glyph = 0;
-    for (auto&amp; part : assemblyParts) {
-        if (nonExtenderCount &lt; 3) {
-            // If we only have at most two non-extenders then we skip the middle glyph.
-            if (expectedPartType == ExtenderBetweenStartAndMiddle)
-                expectedPartType = ExtenderBetweenMiddleAndEnd;
-            else if (expectedPartType == Middle)
-                expectedPartType = End;
-        }
-        if (part.isExtender) {
-            if (!assemblyData.extension.glyph)
-                assemblyData.extension.glyph = part.glyph; // We copy the extender part.
-            else if (assemblyData.extension.glyph != part.glyph)
-                return false; // This is not supported: the assembly has different extenders.
-
-            switch (expectedPartType) {
-            case Start:
-                // We ignore the left/bottom part.
-                expectedPartType = ExtenderBetweenStartAndMiddle;
-                continue;
-            case Middle:
-                // We ignore the middle part.
-                expectedPartType = ExtenderBetweenMiddleAndEnd;
-                continue;
-            case End:
-            case None:
-                // This is not supported: we got an unexpected extender.
-                return false;
-            case ExtenderBetweenStartAndMiddle:
-            case ExtenderBetweenMiddleAndEnd:
-                // We ignore multiple consecutive extenders.
-                continue;
-            }
-        }
-
-        switch (expectedPartType) {
-        case Start:
-            // We copy the left/bottom part.
-            assemblyData.bottomOrLeft.glyph = part.glyph;
-            expectedPartType = ExtenderBetweenStartAndMiddle;
-            continue;
-        case ExtenderBetweenStartAndMiddle:
-        case Middle:
-            // We copy the middle part.
-            assemblyData.middle.glyph = part.glyph;
-            expectedPartType = ExtenderBetweenMiddleAndEnd;
-            continue;
-        case ExtenderBetweenMiddleAndEnd:
-        case End:
-            // We copy the right/top part.
-            assemblyData.topOrRight.glyph = part.glyph;
-            expectedPartType = None;
-            continue;
-        case None:
-            // This is not supported: we got an unexpected non-extender part.
-            return false;
-        }
-    }
-
-    if (!assemblyData.extension.glyph)
-        return false; // This is not supported: we always assume that we have an extension glyph.
-
-    // If we don't have top/right or left/bottom glyphs, we use the extension glyph.
-    if (!assemblyData.topOrRight.glyph)
-        assemblyData.topOrRight.glyph = assemblyData.extension.glyph;
-    if (!assemblyData.bottomOrLeft.glyph)
-        assemblyData.bottomOrLeft.glyph = assemblyData.extension.glyph;
-
-    assemblyData.topOrRight.font = &amp;style().fontCascade().primaryFont();
-    assemblyData.extension.font = assemblyData.topOrRight.font;
-    assemblyData.bottomOrLeft.font = assemblyData.topOrRight.font;
-    assemblyData.middle.font = assemblyData.middle.glyph ? assemblyData.topOrRight.font : nullptr;
-
-    return true;
-}
-
-void RenderMathMLOperator::calculateDisplayStyleLargeOperator()
-{
-    ASSERT(m_isVertical &amp;&amp; isLargeOperatorInDisplayStyle());
-
-    GlyphData baseGlyph;
-    if (!getBaseGlyph(style(), baseGlyph) || !baseGlyph.font-&gt;mathData())
-        return;
-
-    Vector&lt;Glyph&gt; sizeVariants;
-    Vector&lt;OpenTypeMathData::AssemblyPart&gt; assemblyParts;
-
-    // The value of displayOperatorMinHeight is sometimes too small, so we ensure that it is at least \sqrt{2} times the size of the base glyph.
-    float displayOperatorMinHeight = std::max(baseGlyph.font-&gt;boundsForGlyph(baseGlyph.glyph).height() * sqrtOfTwoFloat, baseGlyph.font-&gt;mathData()-&gt;getMathConstant(*baseGlyph.font, OpenTypeMathData::DisplayOperatorMinHeight));
-
-    baseGlyph.font-&gt;mathData()-&gt;getMathVariants(baseGlyph.glyph, true, sizeVariants, assemblyParts);
-
-    // We choose the first size variant that is larger than the expected displayOperatorMinHeight and otherwise fallback to the largest variant.
-    for (auto&amp; sizeVariant : sizeVariants) {
-        GlyphData glyphData(sizeVariant, baseGlyph.font);
-        setSizeVariant(glyphData);
-        m_italicCorrection = glyphData.font-&gt;mathData()-&gt;getItalicCorrection(*glyphData.font, glyphData.glyph);
-        if (heightForGlyph(glyphData) &gt;= displayOperatorMinHeight)
-            break;
-    }
-}
-
-void RenderMathMLOperator::calculateStretchyData(float* maximumGlyphWidth, LayoutUnit targetSize)
-{
-    ASSERT(!maximumGlyphWidth || m_isVertical);
-
-    GlyphData baseGlyph;
-    if (!getBaseGlyph(style(), baseGlyph))
-        return;
-    
-    if (!maximumGlyphWidth) {
-        // We do not stretch if the base glyph is large enough.
-        float baseSize = m_isVertical ? heightForGlyph(baseGlyph) : advanceWidthForGlyph(baseGlyph);
-        if (targetSize &lt;= baseSize)
-            return;
-    }
-
-    GlyphAssemblyData assemblyData;
-    if (baseGlyph.font-&gt;mathData()) {
-        Vector&lt;Glyph&gt; sizeVariants;
-        Vector&lt;OpenTypeMathData::AssemblyPart&gt; assemblyParts;
-        baseGlyph.font-&gt;mathData()-&gt;getMathVariants(baseGlyph.glyph, m_isVertical, sizeVariants, assemblyParts);
-        // We verify the size variants.
-        for (auto&amp; sizeVariant : sizeVariants) {
-            GlyphData glyphData(sizeVariant, baseGlyph.font);
-            if (maximumGlyphWidth)
-                *maximumGlyphWidth = std::max(*maximumGlyphWidth, advanceWidthForGlyph(glyphData));
-            else {
-                setSizeVariant(glyphData);
-                float size = m_isVertical ? heightForGlyph(glyphData) : advanceWidthForGlyph(glyphData);
-                if (size &gt;= targetSize)
-                    return;
-            }
-        }
-
-        // We verify if there is a construction.
-        if (!calculateGlyphAssemblyFallBack(assemblyParts, assemblyData))
-            return;
-    } else {
-        if (!m_isVertical)
-            return;
-
-        // 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);
-        for (unsigned index = 0; index &lt; maxIndex; ++index) {
-            if (stretchyCharacters[index].character == m_textContent) {
-                stretchyCharacter = &amp;stretchyCharacters[index];
-                if (!style().isLeftToRightDirection() &amp;&amp; index &lt; leftRightPairsCount * 2) {
-                    // If we are in right-to-left direction we select the mirrored form by adding -1 or +1 according to the parity of index.
-                    index += index % 2 ? -1 : 1;
-                }
-                break;
-            }
-        }
-
-        // If we didn't find a stretchy character set for this character, we don't know how to stretch it.
-        if (!stretchyCharacter)
-            return;
-
-        // We convert the list of Unicode characters into a list of glyph data.
-        assemblyData.topOrRight = style().fontCascade().glyphDataForCharacter(stretchyCharacter-&gt;topChar, false);
-        assemblyData.extension = style().fontCascade().glyphDataForCharacter(stretchyCharacter-&gt;extensionChar, false);
-        assemblyData.bottomOrLeft = style().fontCascade().glyphDataForCharacter(stretchyCharacter-&gt;bottomChar, false);
-        assemblyData.middle = stretchyCharacter-&gt;middleChar ? style().fontCascade().glyphDataForCharacter(stretchyCharacter-&gt;middleChar, false) : GlyphData();
-    }
-
-    // If we are measuring the maximum width, verify each component.
-    if (maximumGlyphWidth) {
-        *maximumGlyphWidth = std::max(*maximumGlyphWidth, advanceWidthForGlyph(assemblyData.topOrRight));
-        *maximumGlyphWidth = std::max(*maximumGlyphWidth, advanceWidthForGlyph(assemblyData.extension));
-        *maximumGlyphWidth = std::max(*maximumGlyphWidth, advanceWidthForGlyph(assemblyData.middle));
-        *maximumGlyphWidth = std::max(*maximumGlyphWidth, advanceWidthForGlyph(assemblyData.bottomOrLeft));
-        return;
-    }
-
-    // We ensure that the size is large enough to avoid glyph overlaps.
-    float minSize = m_isVertical ?
-        heightForGlyph(assemblyData.topOrRight) + heightForGlyph(assemblyData.middle) + heightForGlyph(assemblyData.bottomOrLeft)
-        : advanceWidthForGlyph(assemblyData.bottomOrLeft) + advanceWidthForGlyph(assemblyData.middle) + advanceWidthForGlyph(assemblyData.topOrRight);
-    if (minSize &gt; targetSize)
-        return;
-
-    setGlyphAssembly(assemblyData);
-}
-
</del><span class="cx"> void RenderMathMLOperator::updateStyle()
</span><span class="cx"> {
</span><span class="cx">     ASSERT(firstChild());
</span><span class="cx">     if (!firstChild())
</span><span class="cx">         return;
</span><span class="cx"> 
</span><del>-    m_stretchType = StretchType::Unstretched;
-    m_italicCorrection = 0;
</del><ins>+    m_mathOperator.unstretch();
+    m_mathOperator.m_italicCorrection = 0;
</ins><span class="cx">     // We add spacing around the operator.
</span><span class="cx">     // FIXME: The spacing should be added to the whole embellished operator (https://bugs.webkit.org/show_bug.cgi?id=124831).
</span><span class="cx">     // FIXME: The spacing should only be added inside (perhaps inferred) mrow (http://www.w3.org/TR/MathML/chapter3.html#presm.opspacing).
</span><span class="lines">@@ -626,25 +369,26 @@
</span><span class="cx">     if (!shouldAllowStretching())
</span><span class="cx">         return;
</span><span class="cx"> 
</span><ins>+    m_mathOperator.setOperator(m_textContent, m_isVertical);
</ins><span class="cx">     if (m_isVertical &amp;&amp; isLargeOperatorInDisplayStyle())
</span><del>-        calculateDisplayStyleLargeOperator();
</del><ins>+        m_mathOperator.calculateDisplayStyleLargeOperator(style());
</ins><span class="cx">     else {
</span><del>-        calculateStretchyData(nullptr, stretchSize());
-        if (m_stretchType == StretchType::Unstretched)
</del><ins>+        m_mathOperator.calculateStretchyData(style(), nullptr, stretchSize());
+        if (!m_mathOperator.isStretched())
</ins><span class="cx">             return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    if (m_isVertical &amp;&amp; m_stretchType == StretchType::SizeVariant) {
</del><ins>+    if (m_isVertical &amp;&amp; m_mathOperator.m_stretchType == MathOperator::StretchType::SizeVariant) {
</ins><span class="cx">         // We resize the operator to match the one of the size variant.
</span><span class="cx">         if (isLargeOperatorInDisplayStyle()) {
</span><span class="cx">             // The stretch size is actually not involved in the selection of the size variant in findDisplayStyleLargeOperator.
</span><span class="cx">             // We simply use the height and depth of the selected size variant glyph.
</span><del>-            FloatRect glyphBounds = boundsForGlyph(m_variant);
</del><ins>+            FloatRect glyphBounds = boundsForGlyph(m_mathOperator.m_variant);
</ins><span class="cx">             m_stretchHeightAboveBaseline = -glyphBounds.y();
</span><span class="cx">             m_stretchDepthBelowBaseline = glyphBounds.maxY();
</span><span class="cx">         } else {
</span><span class="cx">             // We rescale the height and depth proportionately.
</span><del>-            float variantSize = heightForGlyph(m_variant);
</del><ins>+            float variantSize = heightForGlyph(m_mathOperator.m_variant);
</ins><span class="cx">             float size = stretchSize();
</span><span class="cx">             float aspect = size &gt; 0 ? variantSize / size : 1.0;
</span><span class="cx">             m_stretchHeightAboveBaseline *= aspect;
</span><span class="lines">@@ -653,30 +397,30 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     if (!m_isVertical) {
</span><del>-        if (m_stretchType == StretchType::SizeVariant) {
-            FloatRect glyphBounds = boundsForGlyph(m_variant);
</del><ins>+        if (m_mathOperator.m_stretchType == MathOperator::StretchType::SizeVariant) {
+            FloatRect glyphBounds = boundsForGlyph(m_mathOperator.m_variant);
</ins><span class="cx">             m_stretchHeightAboveBaseline = -glyphBounds.y();
</span><span class="cx">             m_stretchDepthBelowBaseline = glyphBounds.maxY();
</span><del>-            m_stretchWidth = advanceWidthForGlyph(m_variant);
-        } else if (m_stretchType == StretchType::GlyphAssembly) {
</del><ins>+            m_stretchWidth = advanceWidthForGlyph(m_mathOperator.m_variant);
+        } else if (m_mathOperator.m_stretchType == MathOperator::StretchType::GlyphAssembly) {
</ins><span class="cx">             FloatRect glyphBounds;
</span><span class="cx">             m_stretchHeightAboveBaseline = 0;
</span><span class="cx">             m_stretchDepthBelowBaseline = 0;
</span><span class="cx"> 
</span><del>-            glyphBounds = boundsForGlyph(m_assembly.bottomOrLeft);
</del><ins>+            glyphBounds = boundsForGlyph(m_mathOperator.m_assembly.bottomOrLeft);
</ins><span class="cx">             m_stretchHeightAboveBaseline = std::max&lt;LayoutUnit&gt;(m_stretchHeightAboveBaseline, -glyphBounds.y());
</span><span class="cx">             m_stretchDepthBelowBaseline = std::max&lt;LayoutUnit&gt;(m_stretchDepthBelowBaseline, glyphBounds.maxY());
</span><span class="cx"> 
</span><del>-            glyphBounds = boundsForGlyph(m_assembly.topOrRight);
</del><ins>+            glyphBounds = boundsForGlyph(m_mathOperator.m_assembly.topOrRight);
</ins><span class="cx">             m_stretchHeightAboveBaseline = std::max&lt;LayoutUnit&gt;(m_stretchHeightAboveBaseline, -glyphBounds.y());
</span><span class="cx">             m_stretchDepthBelowBaseline = std::max&lt;LayoutUnit&gt;(m_stretchDepthBelowBaseline, glyphBounds.maxY());
</span><span class="cx"> 
</span><del>-            glyphBounds = boundsForGlyph(m_assembly.extension);
</del><ins>+            glyphBounds = boundsForGlyph(m_mathOperator.m_assembly.extension);
</ins><span class="cx">             m_stretchHeightAboveBaseline = std::max&lt;LayoutUnit&gt;(m_stretchHeightAboveBaseline, -glyphBounds.y());
</span><span class="cx">             m_stretchDepthBelowBaseline = std::max&lt;LayoutUnit&gt;(m_stretchDepthBelowBaseline, glyphBounds.maxY());
</span><span class="cx"> 
</span><del>-            if (m_assembly.middle.isValid()) {
-                glyphBounds = boundsForGlyph(m_assembly.middle);
</del><ins>+            if (m_mathOperator.m_assembly.middle.isValid()) {
+                glyphBounds = boundsForGlyph(m_mathOperator.m_assembly.middle);
</ins><span class="cx">                 m_stretchHeightAboveBaseline = std::max&lt;LayoutUnit&gt;(m_stretchHeightAboveBaseline, -glyphBounds.y());
</span><span class="cx">                 m_stretchDepthBelowBaseline = std::max&lt;LayoutUnit&gt;(m_stretchDepthBelowBaseline, glyphBounds.maxY());
</span><span class="cx">             }
</span><span class="lines">@@ -686,237 +430,54 @@
</span><span class="cx"> 
</span><span class="cx"> Optional&lt;int&gt; RenderMathMLOperator::firstLineBaseline() const
</span><span class="cx"> {
</span><del>-    if (m_stretchType != StretchType::Unstretched)
</del><ins>+    if (m_mathOperator.isStretched())
</ins><span class="cx">         return Optional&lt;int&gt;(m_stretchHeightAboveBaseline);
</span><span class="cx">     return RenderMathMLToken::firstLineBaseline();
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void RenderMathMLOperator::computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logicalTop, LogicalExtentComputedValues&amp; computedValues) const
</span><span class="cx"> {
</span><del>-    if (m_stretchType != StretchType::Unstretched)
</del><ins>+    if (m_mathOperator.isStretched())
</ins><span class="cx">         logicalHeight = m_stretchHeightAboveBaseline + m_stretchDepthBelowBaseline;
</span><span class="cx">     RenderBox::computeLogicalHeight(logicalHeight, logicalTop, computedValues);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-LayoutRect RenderMathMLOperator::paintGlyph(PaintInfo&amp; info, const GlyphData&amp; data, const LayoutPoint&amp; origin, GlyphPaintTrimming trim)
-{
-    FloatRect glyphBounds = boundsForGlyph(data);
-
-    LayoutRect glyphPaintRect(origin, LayoutSize(glyphBounds.x() + glyphBounds.width(), glyphBounds.height()));
-    glyphPaintRect.setY(origin.y() + glyphBounds.y());
-
-    // In order to have glyphs fit snugly with one another we snap the connecting edges to pixel boundaries
-    // and trim off one pixel. The pixel trim is to account for fonts that have edge pixels that have less
-    // than full coverage. These edge pixels can introduce small seams between connected glyphs.
-    FloatRect clipBounds = info.rect;
-    switch (trim) {
-    case TrimTop:
-        glyphPaintRect.shiftYEdgeTo(glyphPaintRect.y().ceil() + 1);
-        clipBounds.shiftYEdgeTo(glyphPaintRect.y());
-        break;
-    case TrimBottom:
-        glyphPaintRect.shiftMaxYEdgeTo(glyphPaintRect.maxY().floor() - 1);
-        clipBounds.shiftMaxYEdgeTo(glyphPaintRect.maxY());
-        break;
-    case TrimTopAndBottom:
-        glyphPaintRect.shiftYEdgeTo(glyphPaintRect.y().ceil() + 1);
-        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:
-        glyphPaintRect.shiftXEdgeTo(glyphPaintRect.x().ceil() + 1);
-        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.
-    GraphicsContextStateSaver stateSaver(info.context());
-    info.context().clip(clipBounds);
-
-    GlyphBuffer buffer;
-    buffer.add(data.glyph, data.font, advanceWidthForGlyph(data));
-    info.context().drawGlyphs(style().fontCascade(), *data.font, buffer, 0, 1, origin);
-
-    return glyphPaintRect;
-}
-
-void RenderMathMLOperator::fillWithVerticalExtensionGlyph(PaintInfo&amp; info, const LayoutPoint&amp; from, const LayoutPoint&amp; to)
-{
-    ASSERT(m_isVertical);
-    ASSERT(m_stretchType == StretchType::GlyphAssembly);
-    ASSERT(m_assembly.extension.isValid());
-    ASSERT(from.y() &lt;= to.y());
-
-    // If there is no space for the extension glyph, we don't need to do anything.
-    if (from.y() == to.y())
-        return;
-
-    GraphicsContextStateSaver stateSaver(info.context());
-
-    FloatRect glyphBounds = boundsForGlyph(m_assembly.extension);
-
-    // 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.shiftYEdgeTo(from.y());
-    clipBounds.shiftMaxYEdgeTo(to.y());
-    info.context().clip(clipBounds);
-
-    // Trimming may remove up to two pixels from the top of the extender glyph, so we move it up by two pixels.
-    float offsetToGlyphTop = glyphBounds.y() + 2;
-    LayoutPoint glyphOrigin = LayoutPoint(from.x(), from.y() - offsetToGlyphTop);
-    FloatRect lastPaintedGlyphRect(from, FloatSize());
-
-    while (lastPaintedGlyphRect.maxY() &lt; to.y()) {
-        lastPaintedGlyphRect = paintGlyph(info, m_assembly.extension, glyphOrigin, TrimTopAndBottom);
-        glyphOrigin.setY(glyphOrigin.y() + lastPaintedGlyphRect.height());
-
-        // 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::fillWithHorizontalExtensionGlyph(PaintInfo&amp; info, const LayoutPoint&amp; from, const LayoutPoint&amp; to)
-{
-    ASSERT(!m_isVertical);
-    ASSERT(m_stretchType == StretchType::GlyphAssembly);
-    ASSERT(m_assembly.extension.isValid());
-    ASSERT(from.x() &lt;= 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() &lt; to.x()) {
-        lastPaintedGlyphRect = paintGlyph(info, m_assembly.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;
-    }
-}
-
</del><span class="cx"> void RenderMathMLOperator::paint(PaintInfo&amp; info, const LayoutPoint&amp; paintOffset)
</span><span class="cx"> {
</span><span class="cx">     RenderMathMLToken::paint(info, paintOffset);
</span><span class="cx"> 
</span><del>-    if (info.context().paintingDisabled() || info.phase != PaintPhaseForeground || style().visibility() != VISIBLE || m_stretchType == StretchType::Unstretched)
</del><ins>+    if (info.context().paintingDisabled() || info.phase != PaintPhaseForeground || style().visibility() != VISIBLE || !m_mathOperator.isStretched())
</ins><span class="cx">         return;
</span><span class="cx"> 
</span><span class="cx">     GraphicsContextStateSaver stateSaver(info.context());
</span><span class="cx">     info.context().setFillColor(style().visitedDependentColor(CSSPropertyColor));
</span><span class="cx"> 
</span><del>-    if (m_stretchType == StretchType::SizeVariant) {
-        ASSERT(m_variant.isValid());
</del><ins>+    if (m_mathOperator.m_stretchType == MathOperator::StretchType::SizeVariant) {
+        ASSERT(m_mathOperator.m_variant.isValid());
</ins><span class="cx">         GlyphBuffer buffer;
</span><del>-        buffer.add(m_variant.glyph, m_variant.font, advanceWidthForGlyph(m_variant));
</del><ins>+        buffer.add(m_mathOperator.m_variant.glyph, m_mathOperator.m_variant.font, advanceWidthForGlyph(m_mathOperator.m_variant));
</ins><span class="cx">         LayoutPoint operatorTopLeft = ceiledIntPoint(paintOffset + location());
</span><del>-        FloatRect glyphBounds = boundsForGlyph(m_variant);
</del><ins>+        FloatRect glyphBounds = boundsForGlyph(m_mathOperator.m_variant);
</ins><span class="cx">         LayoutPoint operatorOrigin(operatorTopLeft.x(), operatorTopLeft.y() - glyphBounds.y());
</span><del>-        info.context().drawGlyphs(style().fontCascade(), *m_variant.font, buffer, 0, 1, operatorOrigin);
</del><ins>+        info.context().drawGlyphs(style().fontCascade(), *m_mathOperator.m_variant.font, buffer, 0, 1, operatorOrigin);
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    m_mathOperator.m_ascent = m_stretchHeightAboveBaseline;
+    m_mathOperator.m_descent = m_stretchDepthBelowBaseline;
+    m_mathOperator.m_width = logicalWidth();
+    LayoutPoint operatorTopLeft = paintOffset + location();
+    operatorTopLeft.move(style().isLeftToRightDirection() ? m_leadingSpace : m_trailingSpace, 0);
</ins><span class="cx">     if (m_isVertical)
</span><del>-        paintVerticalGlyphAssembly(info, paintOffset);
</del><ins>+        m_mathOperator.paintVerticalGlyphAssembly(style(), info, operatorTopLeft);
</ins><span class="cx">     else
</span><del>-        paintHorizontalGlyphAssembly(info, paintOffset);
</del><ins>+        m_mathOperator.paintHorizontalGlyphAssembly(style(), info, operatorTopLeft);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void RenderMathMLOperator::paintVerticalGlyphAssembly(PaintInfo&amp; info, const LayoutPoint&amp; paintOffset)
-{
-    ASSERT(m_isVertical);
-    ASSERT(m_stretchType == StretchType::GlyphAssembly);
-    ASSERT(m_assembly.topOrRight.isValid());
-    ASSERT(m_assembly.bottomOrLeft.isValid());
-
-    // 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(style().isLeftToRightDirection() ? m_leadingSpace : m_trailingSpace, 0);
-    operatorTopLeft = ceiledIntPoint(operatorTopLeft);
-    FloatRect topGlyphBounds = boundsForGlyph(m_assembly.topOrRight);
-    LayoutPoint topGlyphOrigin(operatorTopLeft.x(), operatorTopLeft.y() - topGlyphBounds.y());
-    LayoutRect topGlyphPaintRect = paintGlyph(info, m_assembly.topOrRight, topGlyphOrigin, TrimBottom);
-
-    FloatRect bottomGlyphBounds = boundsForGlyph(m_assembly.bottomOrLeft);
-    LayoutPoint bottomGlyphOrigin(operatorTopLeft.x(), operatorTopLeft.y() + offsetHeight() - (bottomGlyphBounds.height() + bottomGlyphBounds.y()));
-    LayoutRect bottomGlyphPaintRect = paintGlyph(info, m_assembly.bottomOrLeft, bottomGlyphOrigin, TrimTop);
-
-    if (m_assembly.middle.isValid()) {
-        // Center the glyph origin between the start and end glyph paint extents. Then shift it half the paint height toward the bottom glyph.
-        FloatRect middleGlyphBounds = boundsForGlyph(m_assembly.middle);
-        LayoutPoint middleGlyphOrigin(operatorTopLeft.x(), topGlyphOrigin.y());
-        middleGlyphOrigin.moveBy(LayoutPoint(0, (bottomGlyphPaintRect.y() - topGlyphPaintRect.maxY()) / 2.0));
-        middleGlyphOrigin.moveBy(LayoutPoint(0, middleGlyphBounds.height() / 2.0));
-
-        LayoutRect middleGlyphPaintRect = paintGlyph(info, m_assembly.middle, middleGlyphOrigin, TrimTopAndBottom);
-        fillWithVerticalExtensionGlyph(info, topGlyphPaintRect.minXMaxYCorner(), middleGlyphPaintRect.minXMinYCorner());
-        fillWithVerticalExtensionGlyph(info, middleGlyphPaintRect.minXMaxYCorner(), bottomGlyphPaintRect.minXMinYCorner());
-    } else
-        fillWithVerticalExtensionGlyph(info, topGlyphPaintRect.minXMaxYCorner(), bottomGlyphPaintRect.minXMinYCorner());
-}
-
-void RenderMathMLOperator::paintHorizontalGlyphAssembly(PaintInfo&amp; info, const LayoutPoint&amp; paintOffset)
-{
-    ASSERT(!m_isVertical);
-    ASSERT(m_stretchType == StretchType::GlyphAssembly);
-    ASSERT(m_assembly.bottomOrLeft.isValid());
-    ASSERT(m_assembly.topOrRight.isValid());
-
-    // 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_assembly.bottomOrLeft, leftGlyphOrigin, TrimRight);
-
-    FloatRect rightGlyphBounds = boundsForGlyph(m_assembly.topOrRight);
-    LayoutPoint rightGlyphOrigin(operatorTopLeft.x() + offsetWidth() - rightGlyphBounds.width(), operatorTopLeft.y() + m_stretchHeightAboveBaseline);
-    LayoutRect rightGlyphPaintRect = paintGlyph(info, m_assembly.topOrRight, rightGlyphOrigin, TrimLeft);
-
-    if (m_assembly.middle.isValid()) {
-        // 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_assembly.middle, middleGlyphOrigin, TrimLeftAndRight);
-        fillWithHorizontalExtensionGlyph(info, leftGlyphPaintRect.maxXMinYCorner(), middleGlyphPaintRect.minXMinYCorner());
-        fillWithHorizontalExtensionGlyph(info, middleGlyphPaintRect.maxXMinYCorner(), rightGlyphPaintRect.minXMinYCorner());
-    } else
-        fillWithHorizontalExtensionGlyph(info, leftGlyphPaintRect.maxXMinYCorner(), rightGlyphPaintRect.minXMinYCorner());
-}
-
</del><span class="cx"> void RenderMathMLOperator::paintChildren(PaintInfo&amp; paintInfo, const LayoutPoint&amp; paintOffset, PaintInfo&amp; paintInfoForChild, bool usePrintRect)
</span><span class="cx"> {
</span><span class="cx">     // We skip painting for invisible operators too to avoid some &quot;missing character&quot; glyph to appear if appropriate math fonts are not available.
</span><del>-    if (m_stretchType != StretchType::Unstretched || isInvisibleOperator())
</del><ins>+    if (m_mathOperator.isStretched() || isInvisibleOperator())
</ins><span class="cx">         return;
</span><span class="cx">     RenderMathMLToken::paintChildren(paintInfo, paintOffset, paintInfoForChild, usePrintRect);
</span><span class="cx"> }
</span><span class="lines">@@ -931,19 +492,19 @@
</span><span class="cx">     // Hence we determine the error in the logical width with respect to the actual width of the glyph(s) used to paint the operator.
</span><span class="cx">     LayoutUnit width = logicalWidth();
</span><span class="cx"> 
</span><del>-    if (m_stretchType == StretchType::Unstretched) {
</del><ins>+    if (!m_mathOperator.isStretched()) {
</ins><span class="cx">         GlyphData data = style().fontCascade().glyphDataForCharacter(textContent(), !style().isLeftToRightDirection());
</span><span class="cx">         return width - advanceWidthForGlyph(data);
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    if (m_stretchType == StretchType::SizeVariant)
-        return width - advanceWidthForGlyph(m_variant);
</del><ins>+    if (m_mathOperator.m_stretchType == MathOperator::StretchType::SizeVariant)
+        return width - advanceWidthForGlyph(m_mathOperator.m_variant);
</ins><span class="cx"> 
</span><del>-    float assemblyWidth = advanceWidthForGlyph(m_assembly.topOrRight);
-    assemblyWidth = std::max(assemblyWidth, advanceWidthForGlyph(m_assembly.bottomOrLeft));
-    assemblyWidth = std::max(assemblyWidth, advanceWidthForGlyph(m_assembly.extension));
-    if (m_assembly.middle.isValid())
-        assemblyWidth = std::max(assemblyWidth, advanceWidthForGlyph(m_assembly.middle));
</del><ins>+    float assemblyWidth = advanceWidthForGlyph(m_mathOperator.m_assembly.topOrRight);
+    assemblyWidth = std::max(assemblyWidth, advanceWidthForGlyph(m_mathOperator.m_assembly.bottomOrLeft));
+    assemblyWidth = std::max(assemblyWidth, advanceWidthForGlyph(m_mathOperator.m_assembly.extension));
+    if (m_mathOperator.m_assembly.middle.isValid())
+        assemblyWidth = std::max(assemblyWidth, advanceWidthForGlyph(m_mathOperator.m_assembly.middle));
</ins><span class="cx">     return width - assemblyWidth;
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingmathmlRenderMathMLOperatorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/mathml/RenderMathMLOperator.h (201853 => 201854)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/mathml/RenderMathMLOperator.h        2016-06-09 05:43:46 UTC (rev 201853)
+++ trunk/Source/WebCore/rendering/mathml/RenderMathMLOperator.h        2016-06-09 06:17:40 UTC (rev 201854)
</span><span class="lines">@@ -32,6 +32,7 @@
</span><span class="cx"> #include &quot;GlyphPage.h&quot;
</span><span class="cx"> #include &quot;MathMLElement.h&quot;
</span><span class="cx"> #include &quot;MathMLOperatorDictionary.h&quot;
</span><ins>+#include &quot;MathOperator.h&quot;
</ins><span class="cx"> #include &quot;OpenTypeMathData.h&quot;
</span><span class="cx"> #include &quot;RenderMathMLToken.h&quot;
</span><span class="cx"> 
</span><span class="lines">@@ -51,7 +52,7 @@
</span><span class="cx">     // FIXME: The displaystyle property is not implemented (https://bugs.webkit.org/show_bug.cgi?id=118737).
</span><span class="cx">     bool isLargeOperatorInDisplayStyle() const { return !hasOperatorFlag(MathMLOperatorDictionary::Stretchy) &amp;&amp; hasOperatorFlag(MathMLOperatorDictionary::LargeOp); }
</span><span class="cx">     bool isVertical() const { return m_isVertical; }
</span><del>-    LayoutUnit italicCorrection() const { return m_italicCorrection; }
</del><ins>+    LayoutUnit italicCorrection() const { return m_mathOperator.italicCorrection(); }
</ins><span class="cx"> 
</span><span class="cx">     void styleDidChange(StyleDifference, const RenderStyle* oldStyle) final;
</span><span class="cx">     void updateStyle() final;
</span><span class="lines">@@ -73,20 +74,6 @@
</span><span class="cx">     UChar textContent() const { return m_textContent; }
</span><span class="cx"> 
</span><span class="cx"> private:
</span><del>-    struct GlyphAssemblyData {
-        GlyphData topOrRight;
-        GlyphData extension;
-        GlyphData bottomOrLeft;
-        GlyphData middle;
-    };
-    enum class StretchType { Unstretched, SizeVariant, GlyphAssembly };
-    StretchType m_stretchType;
-    union {
-        GlyphData m_variant;
-        GlyphAssemblyData m_assembly;
-    };
-    LayoutUnit m_italicCorrection;
-
</del><span class="cx">     const char* renderName() const override { return isAnonymous() ? &quot;RenderMathMLOperator (anonymous)&quot; : &quot;RenderMathMLOperator&quot;; }
</span><span class="cx">     void paintChildren(PaintInfo&amp; forSelf, const LayoutPoint&amp;, PaintInfo&amp; forChild, bool usePrintRect) final;
</span><span class="cx">     bool isRenderMathMLOperator() const final { return true; }
</span><span class="lines">@@ -100,27 +87,6 @@
</span><span class="cx"> 
</span><span class="cx">     bool shouldAllowStretching() const;
</span><span class="cx"> 
</span><del>-    bool getBaseGlyph(const RenderStyle&amp;, GlyphData&amp;) const;
-    void setSizeVariant(const GlyphData&amp;);
-    void setGlyphAssembly(const GlyphAssemblyData&amp;);
-    bool calculateGlyphAssemblyFallBack(const Vector&lt;OpenTypeMathData::AssemblyPart&gt;&amp;, GlyphAssemblyData&amp;) const;
-    void calculateDisplayStyleLargeOperator();
-    void calculateStretchyData(float* maximumGlyphWidth, LayoutUnit targetSize = 0);
-
-    enum GlyphPaintTrimming {
-        TrimTop,
-        TrimBottom,
-        TrimTopAndBottom,
-        TrimLeft,
-        TrimRight,
-        TrimLeftAndRight
-    };
-
-    LayoutRect paintGlyph(PaintInfo&amp;, const GlyphData&amp;, const LayoutPoint&amp; origin, GlyphPaintTrimming);
-    void fillWithVerticalExtensionGlyph(PaintInfo&amp;, const LayoutPoint&amp; from, const LayoutPoint&amp; to);
-    void fillWithHorizontalExtensionGlyph(PaintInfo&amp;, const LayoutPoint&amp; from, const LayoutPoint&amp; to);
-    void paintVerticalGlyphAssembly(PaintInfo&amp;, const LayoutPoint&amp;);
-    void paintHorizontalGlyphAssembly(PaintInfo&amp;, const LayoutPoint&amp;);
</del><span class="cx">     void setOperatorFlagFromAttribute(MathMLOperatorDictionary::Flag, const QualifiedName&amp;);
</span><span class="cx">     void setOperatorFlagFromAttributeValue(MathMLOperatorDictionary::Flag, const AtomicString&amp; attributeValue);
</span><span class="cx">     void setOperatorPropertiesFromOpDictEntry(const MathMLOperatorDictionary::Entry*);
</span><span class="lines">@@ -137,6 +103,7 @@
</span><span class="cx">     LayoutUnit m_trailingSpace;
</span><span class="cx">     LayoutUnit m_minSize;
</span><span class="cx">     LayoutUnit m_maxSize;
</span><ins>+    MathOperator m_mathOperator;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebCore
</span></span></pre>
</div>
</div>

</body>
</html>