<!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>[200569] 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/200569">200569</a></dd>
<dt>Author</dt> <dd>fred.wang@free.fr</dd>
<dt>Date</dt> <dd>2016-05-08 22:51:37 -0700 (Sun, 08 May 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>RenderMathMLOperator: refactor management of stretchy data and italic correction
https://bugs.webkit.org/show_bug.cgi?id=156913

Patch by Frederic Wang &lt;fwang@igalia.com&gt; on 2016-05-08
Reviewed by Darin Adler.

No new tests, behavior is not changed.

The stretchy data uses a shared space to describe horizontal / vertical directions and
unstretched / size variant / glyph assembly. We use a simple struct with some unions to
represent it instead of the current implementation with a class.
We also modify the signature of some functions to retrieve display operator and stretchy
data to use that new structure and prepare the move to a separate MathOperator class.
Finally, we introduce some helper functions to easily set the stretchy data.

* rendering/mathml/RenderMathMLOperator.cpp:
(WebCore::RenderMathMLOperator::computePreferredLogicalWidths): Use the new data members and
function signatures.
(WebCore::RenderMathMLOperator::setSizeVariant): New helper function to set a size variant.
(WebCore::RenderMathMLOperator::setGlyphAssembly): New helper function to set a glyph
assembly.
(WebCore::RenderMathMLOperator::getGlyphAssemblyFallBack): We change the signature to use a
GlyphAssemblyData.
(WebCore::RenderMathMLOperator::findDisplayStyleLargeOperator): We rename the function and
change its signature to remove the return value. We now also set the italic correction when
a display operator is found.
(WebCore::RenderMathMLOperator::findStretchyData): We change the signature to introduce a
target size and remove the return value. This also does the early return when the base glyph
is large enough.
(WebCore::RenderMathMLOperator::updateStyle): We use the new data members and function
signatures. The check for the base glyph size is now done in findStretchyData, so we just
check whether m_stretchType is Unstretched to do an early return.
(WebCore::RenderMathMLOperator::firstLineBaseline): We use m_stretchType.
(WebCore::RenderMathMLOperator::computeLogicalHeight): Ditto.
(WebCore::RenderMathMLOperator::fillWithVerticalExtensionGlyph): Use the new class members.
(WebCore::RenderMathMLOperator::fillWithHorizontalExtensionGlyph): Ditto.
(WebCore::RenderMathMLOperator::paint): Ditto.
(WebCore::RenderMathMLOperator::paintVerticalGlyphAssembly): Ditto.
(WebCore::RenderMathMLOperator::paintHorizontalGlyphAssembly): Ditto.
(WebCore::RenderMathMLOperator::paintChildren): Ditto.
(WebCore::RenderMathMLOperator::trailingSpaceError): Ditto.
(WebCore::RenderMathMLOperator::italicCorrection): Moved to RenderMathMLOperator.h.
(WebCore::RenderMathMLOperator::getDisplayStyleLargeOperator): Deleted.
* rendering/mathml/RenderMathMLOperator.h:
(WebCore::RenderMathMLOperator::italicCorrection): We just return m_italicCorrection.
(WebCore::RenderMathMLOperator::GlyphAssemblyData::GlyphAssemblyData): New class to store an
assembly of GlyphData.
(WebCore::RenderMathMLOperator::StretchyData::mode): Deleted.
(WebCore::RenderMathMLOperator::StretchyData::variant): Deleted.
(WebCore::RenderMathMLOperator::StretchyData::top): Deleted.
(WebCore::RenderMathMLOperator::StretchyData::extension): Deleted.
(WebCore::RenderMathMLOperator::StretchyData::bottom): Deleted.
(WebCore::RenderMathMLOperator::StretchyData::middle): Deleted.
(WebCore::RenderMathMLOperator::StretchyData::left): Deleted.
(WebCore::RenderMathMLOperator::StretchyData::right): Deleted.
(WebCore::RenderMathMLOperator::StretchyData::setNormalMode): Deleted.
(WebCore::RenderMathMLOperator::StretchyData::setSizeVariantMode): Deleted.
(WebCore::RenderMathMLOperator::StretchyData::setGlyphAssemblyMode): Deleted.
(WebCore::RenderMathMLOperator::StretchyData::StretchyData): Deleted.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</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>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (200568 => 200569)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2016-05-09 04:55:34 UTC (rev 200568)
+++ trunk/Source/WebCore/ChangeLog        2016-05-09 05:51:37 UTC (rev 200569)
</span><span class="lines">@@ -1,3 +1,64 @@
</span><ins>+2016-05-08  Frederic Wang  &lt;fwang@igalia.com&gt;
+
+        RenderMathMLOperator: refactor management of stretchy data and italic correction
+        https://bugs.webkit.org/show_bug.cgi?id=156913
+
+        Reviewed by Darin Adler.
+
+        No new tests, behavior is not changed.
+
+        The stretchy data uses a shared space to describe horizontal / vertical directions and
+        unstretched / size variant / glyph assembly. We use a simple struct with some unions to
+        represent it instead of the current implementation with a class.
+        We also modify the signature of some functions to retrieve display operator and stretchy
+        data to use that new structure and prepare the move to a separate MathOperator class.
+        Finally, we introduce some helper functions to easily set the stretchy data.
+
+        * rendering/mathml/RenderMathMLOperator.cpp:
+        (WebCore::RenderMathMLOperator::computePreferredLogicalWidths): Use the new data members and
+        function signatures.
+        (WebCore::RenderMathMLOperator::setSizeVariant): New helper function to set a size variant.
+        (WebCore::RenderMathMLOperator::setGlyphAssembly): New helper function to set a glyph
+        assembly.
+        (WebCore::RenderMathMLOperator::getGlyphAssemblyFallBack): We change the signature to use a
+        GlyphAssemblyData.
+        (WebCore::RenderMathMLOperator::findDisplayStyleLargeOperator): We rename the function and
+        change its signature to remove the return value. We now also set the italic correction when
+        a display operator is found.
+        (WebCore::RenderMathMLOperator::findStretchyData): We change the signature to introduce a
+        target size and remove the return value. This also does the early return when the base glyph
+        is large enough.
+        (WebCore::RenderMathMLOperator::updateStyle): We use the new data members and function
+        signatures. The check for the base glyph size is now done in findStretchyData, so we just
+        check whether m_stretchType is Unstretched to do an early return.
+        (WebCore::RenderMathMLOperator::firstLineBaseline): We use m_stretchType.
+        (WebCore::RenderMathMLOperator::computeLogicalHeight): Ditto.
+        (WebCore::RenderMathMLOperator::fillWithVerticalExtensionGlyph): Use the new class members.
+        (WebCore::RenderMathMLOperator::fillWithHorizontalExtensionGlyph): Ditto.
+        (WebCore::RenderMathMLOperator::paint): Ditto.
+        (WebCore::RenderMathMLOperator::paintVerticalGlyphAssembly): Ditto.
+        (WebCore::RenderMathMLOperator::paintHorizontalGlyphAssembly): Ditto.
+        (WebCore::RenderMathMLOperator::paintChildren): Ditto.
+        (WebCore::RenderMathMLOperator::trailingSpaceError): Ditto.
+        (WebCore::RenderMathMLOperator::italicCorrection): Moved to RenderMathMLOperator.h.
+        (WebCore::RenderMathMLOperator::getDisplayStyleLargeOperator): Deleted.
+        * rendering/mathml/RenderMathMLOperator.h:
+        (WebCore::RenderMathMLOperator::italicCorrection): We just return m_italicCorrection.
+        (WebCore::RenderMathMLOperator::GlyphAssemblyData::GlyphAssemblyData): New class to store an
+        assembly of GlyphData.
+        (WebCore::RenderMathMLOperator::StretchyData::mode): Deleted.
+        (WebCore::RenderMathMLOperator::StretchyData::variant): Deleted.
+        (WebCore::RenderMathMLOperator::StretchyData::top): Deleted.
+        (WebCore::RenderMathMLOperator::StretchyData::extension): Deleted.
+        (WebCore::RenderMathMLOperator::StretchyData::bottom): Deleted.
+        (WebCore::RenderMathMLOperator::StretchyData::middle): Deleted.
+        (WebCore::RenderMathMLOperator::StretchyData::left): Deleted.
+        (WebCore::RenderMathMLOperator::StretchyData::right): Deleted.
+        (WebCore::RenderMathMLOperator::StretchyData::setNormalMode): Deleted.
+        (WebCore::RenderMathMLOperator::StretchyData::setSizeVariantMode): Deleted.
+        (WebCore::RenderMathMLOperator::StretchyData::setGlyphAssemblyMode): Deleted.
+        (WebCore::RenderMathMLOperator::StretchyData::StretchyData): Deleted.
+
</ins><span class="cx"> 2016-05-08  Zalan Bujtas  &lt;zalan@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         iOS selection: Use inflow containing block for positioned &lt;br&gt;.
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingmathmlRenderMathMLOperatorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/mathml/RenderMathMLOperator.cpp (200568 => 200569)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/mathml/RenderMathMLOperator.cpp        2016-05-09 04:55:34 UTC (rev 200568)
+++ trunk/Source/WebCore/rendering/mathml/RenderMathMLOperator.cpp        2016-05-09 05:51:37 UTC (rev 200569)
</span><span class="lines">@@ -202,18 +202,6 @@
</span><span class="cx">     return false;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-LayoutUnit RenderMathMLOperator::italicCorrection() const
-{
-    if (isLargeOperatorInDisplayStyle()) {
-        const auto&amp; primaryFont = style().fontCascade().primaryFont();
-        if (auto* mathData = primaryFont.mathData()) {
-            StretchyData largeOperator = getDisplayStyleLargeOperator();
-            return mathData-&gt;getItalicCorrection(primaryFont, largeOperator.variant().glyph);
-        }
-    }
-    return 0;
-}
-
</del><span class="cx"> void RenderMathMLOperator::stretchTo(LayoutUnit heightAboveBaseline, LayoutUnit depthBelowBaseline)
</span><span class="cx"> {
</span><span class="cx">     ASSERT(hasOperatorFlag(MathMLOperatorDictionary::Stretchy));
</span><span class="lines">@@ -317,12 +305,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>-        StretchyData largeOperator = getDisplayStyleLargeOperator();
-        if (largeOperator.mode() == DrawSizeVariant)
-            maximumGlyphWidth = boundsForGlyph(largeOperator.variant()).width();
</del><ins>+        calculateDisplayStyleLargeOperator();
+        if (m_stretchType == StretchType::SizeVariant)
+            maximumGlyphWidth = boundsForGlyph(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>-        findStretchyData(&amp;maximumGlyphWidth);
</del><ins>+        calculateStretchyData(&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">@@ -392,13 +380,21 @@
</span><span class="cx">     return baseGlyph.isValid() &amp;&amp; baseGlyph.font == &amp;style.fontCascade().primaryFont();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool RenderMathMLOperator::getGlyphAssemblyFallBack(Vector&lt;OpenTypeMathData::AssemblyPart&gt; assemblyParts, StretchyData&amp; stretchyData) const
</del><ins>+void RenderMathMLOperator::setSizeVariant(const GlyphData&amp; sizeVariant)
</ins><span class="cx"> {
</span><del>-    GlyphData top;
-    GlyphData extension;
-    GlyphData bottom;
-    GlyphData middle;
</del><ins>+    ASSERT(sizeVariant.isValid() &amp;&amp; sizeVariant.font-&gt;mathData());
+    m_stretchType = StretchType::SizeVariant;
+    m_variant = sizeVariant;
+}
</ins><span class="cx"> 
</span><ins>+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
+{
</ins><span class="cx">     // 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.
</span><span class="cx">     // FIXME: RenderMathMLOperator should support the most general format (https://bugs.webkit.org/show_bug.cgi?id=130327).
</span><span class="cx">     // We use the approach of the copyComponents function in github.com/mathjax/MathJax-dev/blob/master/fonts/OpenTypeMath/fontUtil.py
</span><span class="lines">@@ -422,8 +418,8 @@
</span><span class="cx">         None
</span><span class="cx">     };
</span><span class="cx">     PartType expectedPartType = Start;
</span><del>-    extension.glyph = 0;
-    middle.glyph = 0;
</del><ins>+    assemblyData.extension.glyph = 0;
+    assemblyData.middle.glyph = 0;
</ins><span class="cx">     for (auto&amp; part : assemblyParts) {
</span><span class="cx">         if (nonExtenderCount &lt; 3) {
</span><span class="cx">             // If we only have at most two non-extenders then we skip the middle glyph.
</span><span class="lines">@@ -433,9 +429,9 @@
</span><span class="cx">                 expectedPartType = End;
</span><span class="cx">         }
</span><span class="cx">         if (part.isExtender) {
</span><del>-            if (!extension.glyph)
-                extension.glyph = part.glyph; // We copy the extender part.
-            else if (extension.glyph != part.glyph)
</del><ins>+            if (!assemblyData.extension.glyph)
+                assemblyData.extension.glyph = part.glyph; // We copy the extender part.
+            else if (assemblyData.extension.glyph != part.glyph)
</ins><span class="cx">                 return false; // This is not supported: the assembly has different extenders.
</span><span class="cx"> 
</span><span class="cx">             switch (expectedPartType) {
</span><span class="lines">@@ -461,19 +457,19 @@
</span><span class="cx">         switch (expectedPartType) {
</span><span class="cx">         case Start:
</span><span class="cx">             // We copy the left/bottom part.
</span><del>-            bottom.glyph = part.glyph;
</del><ins>+            assemblyData.bottomOrLeft.glyph = part.glyph;
</ins><span class="cx">             expectedPartType = ExtenderBetweenStartAndMiddle;
</span><span class="cx">             continue;
</span><span class="cx">         case ExtenderBetweenStartAndMiddle:
</span><span class="cx">         case Middle:
</span><span class="cx">             // We copy the middle part.
</span><del>-            middle.glyph = part.glyph;
</del><ins>+            assemblyData.middle.glyph = part.glyph;
</ins><span class="cx">             expectedPartType = ExtenderBetweenMiddleAndEnd;
</span><span class="cx">             continue;
</span><span class="cx">         case ExtenderBetweenMiddleAndEnd:
</span><span class="cx">         case End:
</span><span class="cx">             // We copy the right/top part.
</span><del>-            top.glyph = part.glyph;
</del><ins>+            assemblyData.topOrRight.glyph = part.glyph;
</ins><span class="cx">             expectedPartType = None;
</span><span class="cx">             continue;
</span><span class="cx">         case None:
</span><span class="lines">@@ -482,35 +478,30 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    if (!extension.glyph)
</del><ins>+    if (!assemblyData.extension.glyph)
</ins><span class="cx">         return false; // This is not supported: we always assume that we have an extension glyph.
</span><span class="cx"> 
</span><del>-    // If we don't have top/bottom glyphs, we use the extension glyph.
-    if (!top.glyph)
-        top.glyph = extension.glyph;
-    if (!bottom.glyph)
-        bottom.glyph = extension.glyph;
</del><ins>+    // 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;
</ins><span class="cx"> 
</span><del>-    top.font = &amp;style().fontCascade().primaryFont();
-    extension.font = top.font;
-    bottom.font = top.font;
-    if (middle.glyph)
-        middle.font = top.font;
</del><ins>+    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;
</ins><span class="cx"> 
</span><del>-    stretchyData.setGlyphAssemblyMode(top, extension, bottom, middle);
-
</del><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-RenderMathMLOperator::StretchyData RenderMathMLOperator::getDisplayStyleLargeOperator() const
</del><ins>+void RenderMathMLOperator::calculateDisplayStyleLargeOperator()
</ins><span class="cx"> {
</span><del>-    StretchyData data;
-
</del><span class="cx">     ASSERT(m_isVertical &amp;&amp; isLargeOperatorInDisplayStyle());
</span><span class="cx"> 
</span><span class="cx">     GlyphData baseGlyph;
</span><span class="cx">     if (!getBaseGlyph(style(), baseGlyph) || !baseGlyph.font-&gt;mathData())
</span><del>-        return data;
</del><ins>+        return;
</ins><span class="cx"> 
</span><span class="cx">     Vector&lt;Glyph&gt; sizeVariants;
</span><span class="cx">     Vector&lt;OpenTypeMathData::AssemblyPart&gt; assemblyParts;
</span><span class="lines">@@ -521,53 +512,54 @@
</span><span class="cx">     baseGlyph.font-&gt;mathData()-&gt;getMathVariants(baseGlyph.glyph, true, sizeVariants, assemblyParts);
</span><span class="cx"> 
</span><span class="cx">     // We choose the first size variant that is larger than the expected displayOperatorMinHeight and otherwise fallback to the largest variant.
</span><del>-    for (auto&amp; variant : sizeVariants) {
-        GlyphData sizeVariant;
-        sizeVariant.glyph = variant;
-        sizeVariant.font = baseGlyph.font;
-        data.setSizeVariantMode(sizeVariant);
-        if (boundsForGlyph(sizeVariant).height() &gt;= displayOperatorMinHeight)
-            return data;
</del><ins>+    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;
</ins><span class="cx">     }
</span><del>-    return data;
</del><span class="cx"> }
</span><span class="cx"> 
</span><del>-RenderMathMLOperator::StretchyData RenderMathMLOperator::findStretchyData(float* maximumGlyphWidth)
</del><ins>+void RenderMathMLOperator::calculateStretchyData(float* maximumGlyphWidth, LayoutUnit targetSize)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(!maximumGlyphWidth || m_isVertical);
</span><span class="cx"> 
</span><del>-    StretchyData data;
-    StretchyData assemblyData;
-
</del><span class="cx">     GlyphData baseGlyph;
</span><span class="cx">     if (!getBaseGlyph(style(), baseGlyph))
</span><del>-        return data;
</del><ins>+        return;
</ins><span class="cx">     
</span><ins>+    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;
</ins><span class="cx">     if (baseGlyph.font-&gt;mathData()) {
</span><span class="cx">         Vector&lt;Glyph&gt; sizeVariants;
</span><span class="cx">         Vector&lt;OpenTypeMathData::AssemblyPart&gt; assemblyParts;
</span><span class="cx">         baseGlyph.font-&gt;mathData()-&gt;getMathVariants(baseGlyph.glyph, m_isVertical, sizeVariants, assemblyParts);
</span><span class="cx">         // We verify the size variants.
</span><del>-        for (auto&amp; variant : sizeVariants) {
-            GlyphData sizeVariant;
-            sizeVariant.glyph = variant;
-            sizeVariant.font = baseGlyph.font;
</del><ins>+        for (auto&amp; sizeVariant : sizeVariants) {
+            GlyphData glyphData(sizeVariant, baseGlyph.font);
</ins><span class="cx">             if (maximumGlyphWidth)
</span><del>-                *maximumGlyphWidth = std::max(*maximumGlyphWidth, advanceWidthForGlyph(sizeVariant));
</del><ins>+                *maximumGlyphWidth = std::max(*maximumGlyphWidth, advanceWidthForGlyph(glyphData));
</ins><span class="cx">             else {
</span><del>-                data.setSizeVariantMode(sizeVariant);
-                float size = m_isVertical ? heightForGlyph(sizeVariant) : advanceWidthForGlyph(sizeVariant);
-                if (size &gt;= stretchSize()) 
-                    return data;
</del><ins>+                setSizeVariant(glyphData);
+                float size = m_isVertical ? heightForGlyph(glyphData) : advanceWidthForGlyph(glyphData);
+                if (size &gt;= targetSize)
+                    return;
</ins><span class="cx">             }
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         // We verify if there is a construction.
</span><del>-        if (!getGlyphAssemblyFallBack(assemblyParts, assemblyData))
-            return data;
</del><ins>+        if (!calculateGlyphAssemblyFallBack(assemblyParts, assemblyData))
+            return;
</ins><span class="cx">     } else {
</span><span class="cx">         if (!m_isVertical)
</span><del>-            return data;
</del><ins>+            return;
</ins><span class="cx"> 
</span><span class="cx">         // If the font does not have a MATH table, we fallback to the Unicode-only constructions.
</span><span class="cx">         const StretchyCharacter* stretchyCharacter = nullptr;
</span><span class="lines">@@ -585,45 +577,32 @@
</span><span class="cx"> 
</span><span class="cx">         // If we didn't find a stretchy character set for this character, we don't know how to stretch it.
</span><span class="cx">         if (!stretchyCharacter)
</span><del>-            return data;
</del><ins>+            return;
</ins><span class="cx"> 
</span><span class="cx">         // We convert the list of Unicode characters into a list of glyph data.
</span><del>-        GlyphData top = style().fontCascade().glyphDataForCharacter(stretchyCharacter-&gt;topChar, false);
-        GlyphData extension = style().fontCascade().glyphDataForCharacter(stretchyCharacter-&gt;extensionChar, false);
-        GlyphData bottom = style().fontCascade().glyphDataForCharacter(stretchyCharacter-&gt;bottomChar, false);
-        GlyphData middle;
-        if (stretchyCharacter-&gt;middleChar)
-            middle = style().fontCascade().glyphDataForCharacter(stretchyCharacter-&gt;middleChar, false);
-        assemblyData.setGlyphAssemblyMode(top, extension, bottom, middle);
</del><ins>+        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();
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    ASSERT(assemblyData.mode() == DrawGlyphAssembly);
-
</del><span class="cx">     // If we are measuring the maximum width, verify each component.
</span><span class="cx">     if (maximumGlyphWidth) {
</span><del>-        *maximumGlyphWidth = std::max(*maximumGlyphWidth, advanceWidthForGlyph(assemblyData.top()));
-        *maximumGlyphWidth = std::max(*maximumGlyphWidth, advanceWidthForGlyph(assemblyData.extension()));
-        if (assemblyData.middle().glyph)
-            *maximumGlyphWidth = std::max(*maximumGlyphWidth, advanceWidthForGlyph(assemblyData.middle()));
-        *maximumGlyphWidth = std::max(*maximumGlyphWidth, advanceWidthForGlyph(assemblyData.bottom()));
-        return assemblyData;
</del><ins>+        *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;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     // We ensure that the size is large enough to avoid glyph overlaps.
</span><del>-    float size;
-    if (m_isVertical) {
-        size = heightForGlyph(assemblyData.top()) + heightForGlyph(assemblyData.bottom());
-        if (assemblyData.middle().glyph)
-            size += heightForGlyph(assemblyData.middle());
-    } else {
-        size = advanceWidthForGlyph(assemblyData.left()) + advanceWidthForGlyph(assemblyData.right());
-        if (assemblyData.middle().glyph)
-            size += advanceWidthForGlyph(assemblyData.middle());
-    }
-    if (size &gt; stretchSize())
-        return data;
</del><ins>+    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;
</ins><span class="cx"> 
</span><del>-    return assemblyData;
</del><ins>+    setGlyphAssembly(assemblyData);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void RenderMathMLOperator::updateStyle()
</span><span class="lines">@@ -632,7 +611,8 @@
</span><span class="cx">     if (!firstChild())
</span><span class="cx">         return;
</span><span class="cx"> 
</span><del>-    m_stretchyData.setNormalMode();
</del><ins>+    m_stretchType = StretchType::Unstretched;
+    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">@@ -647,27 +627,24 @@
</span><span class="cx">         return;
</span><span class="cx"> 
</span><span class="cx">     if (m_isVertical &amp;&amp; isLargeOperatorInDisplayStyle())
</span><del>-        m_stretchyData = getDisplayStyleLargeOperator();
</del><ins>+        calculateDisplayStyleLargeOperator();
</ins><span class="cx">     else {
</span><del>-        // We do not stretch if the base glyph is large enough.
-        GlyphData baseGlyph = style().fontCascade().glyphDataForCharacter(m_textContent, !style().isLeftToRightDirection());
-        float baseSize = m_isVertical ? heightForGlyph(baseGlyph) : advanceWidthForGlyph(baseGlyph);
-        if (stretchSize() &lt;= baseSize)
</del><ins>+        calculateStretchyData(nullptr, stretchSize());
+        if (m_stretchType == StretchType::Unstretched)
</ins><span class="cx">             return;
</span><del>-        m_stretchyData = findStretchyData(nullptr);
</del><span class="cx">     }
</span><span class="cx"> 
</span><del>-    if (m_isVertical &amp;&amp; m_stretchyData.mode() == DrawSizeVariant) {
</del><ins>+    if (m_isVertical &amp;&amp; m_stretchType == 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><del>-            // The stretch size is actually not involved in the selection of the size variant in getDisplayStyleLargeOperator.
</del><ins>+            // The stretch size is actually not involved in the selection of the size variant in findDisplayStyleLargeOperator.
</ins><span class="cx">             // We simply use the height and depth of the selected size variant glyph.
</span><del>-            FloatRect glyphBounds = boundsForGlyph(m_stretchyData.variant());
</del><ins>+            FloatRect glyphBounds = boundsForGlyph(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_stretchyData.variant());
</del><ins>+            float variantSize = heightForGlyph(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">@@ -676,30 +653,30 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     if (!m_isVertical) {
</span><del>-        if (m_stretchyData.mode() == DrawSizeVariant) {
-            FloatRect glyphBounds = boundsForGlyph(m_stretchyData.variant());
</del><ins>+        if (m_stretchType == StretchType::SizeVariant) {
+            FloatRect glyphBounds = boundsForGlyph(m_variant);
</ins><span class="cx">             m_stretchHeightAboveBaseline = -glyphBounds.y();
</span><span class="cx">             m_stretchDepthBelowBaseline = glyphBounds.maxY();
</span><del>-            m_stretchWidth = advanceWidthForGlyph(m_stretchyData.variant());
-        } else if (m_stretchyData.mode() == DrawGlyphAssembly) {
</del><ins>+            m_stretchWidth = advanceWidthForGlyph(m_variant);
+        } else if (m_stretchType == 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_stretchyData.left());
</del><ins>+            glyphBounds = boundsForGlyph(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_stretchyData.right());
</del><ins>+            glyphBounds = boundsForGlyph(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_stretchyData.extension());
</del><ins>+            glyphBounds = boundsForGlyph(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_stretchyData.middle().glyph) {
-                glyphBounds = boundsForGlyph(m_stretchyData.middle());
</del><ins>+            if (m_assembly.middle.isValid()) {
+                glyphBounds = boundsForGlyph(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">@@ -709,14 +686,14 @@
</span><span class="cx"> 
</span><span class="cx"> Optional&lt;int&gt; RenderMathMLOperator::firstLineBaseline() const
</span><span class="cx"> {
</span><del>-    if (m_stretchyData.mode() != DrawNormal)
</del><ins>+    if (m_stretchType != StretchType::Unstretched)
</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_stretchyData.mode() != DrawNormal)
</del><ins>+    if (m_stretchType != StretchType::Unstretched)
</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="lines">@@ -776,8 +753,8 @@
</span><span class="cx"> void RenderMathMLOperator::fillWithVerticalExtensionGlyph(PaintInfo&amp; info, const LayoutPoint&amp; from, const LayoutPoint&amp; to)
</span><span class="cx"> {
</span><span class="cx">     ASSERT(m_isVertical);
</span><del>-    ASSERT(m_stretchyData.mode() == DrawGlyphAssembly);
-    ASSERT(m_stretchyData.extension().glyph);
</del><ins>+    ASSERT(m_stretchType == StretchType::GlyphAssembly);
+    ASSERT(m_assembly.extension.isValid());
</ins><span class="cx">     ASSERT(from.y() &lt;= to.y());
</span><span class="cx"> 
</span><span class="cx">     // If there is no space for the extension glyph, we don't need to do anything.
</span><span class="lines">@@ -786,7 +763,7 @@
</span><span class="cx"> 
</span><span class="cx">     GraphicsContextStateSaver stateSaver(info.context());
</span><span class="cx"> 
</span><del>-    FloatRect glyphBounds = boundsForGlyph(m_stretchyData.extension());
</del><ins>+    FloatRect glyphBounds = boundsForGlyph(m_assembly.extension);
</ins><span class="cx"> 
</span><span class="cx">     // Clipping the extender region here allows us to draw the bottom extender glyph into the
</span><span class="cx">     // regions of the bottom glyph without worrying about overdraw (hairy pixels) and simplifies later clipping.
</span><span class="lines">@@ -801,7 +778,7 @@
</span><span class="cx">     FloatRect lastPaintedGlyphRect(from, FloatSize());
</span><span class="cx"> 
</span><span class="cx">     while (lastPaintedGlyphRect.maxY() &lt; to.y()) {
</span><del>-        lastPaintedGlyphRect = paintGlyph(info, m_stretchyData.extension(), glyphOrigin, TrimTopAndBottom);
</del><ins>+        lastPaintedGlyphRect = paintGlyph(info, m_assembly.extension, glyphOrigin, TrimTopAndBottom);
</ins><span class="cx">         glyphOrigin.setY(glyphOrigin.y() + lastPaintedGlyphRect.height());
</span><span class="cx"> 
</span><span class="cx">         // There's a chance that if the font size is small enough the glue glyph has been reduced to an empty rectangle
</span><span class="lines">@@ -814,8 +791,8 @@
</span><span class="cx"> void RenderMathMLOperator::fillWithHorizontalExtensionGlyph(PaintInfo&amp; info, const LayoutPoint&amp; from, const LayoutPoint&amp; to)
</span><span class="cx"> {
</span><span class="cx">     ASSERT(!m_isVertical);
</span><del>-    ASSERT(m_stretchyData.mode() == DrawGlyphAssembly);
-    ASSERT(m_stretchyData.extension().glyph);
</del><ins>+    ASSERT(m_stretchType == StretchType::GlyphAssembly);
+    ASSERT(m_assembly.extension.isValid());
</ins><span class="cx">     ASSERT(from.x() &lt;= to.x());
</span><span class="cx"> 
</span><span class="cx">     // If there is no space for the extension glyph, we don't need to do anything.
</span><span class="lines">@@ -837,7 +814,7 @@
</span><span class="cx">     FloatRect lastPaintedGlyphRect(from, FloatSize());
</span><span class="cx"> 
</span><span class="cx">     while (lastPaintedGlyphRect.maxX() &lt; to.x()) {
</span><del>-        lastPaintedGlyphRect = paintGlyph(info, m_stretchyData.extension(), glyphOrigin, TrimLeftAndRight);
</del><ins>+        lastPaintedGlyphRect = paintGlyph(info, m_assembly.extension, glyphOrigin, TrimLeftAndRight);
</ins><span class="cx">         glyphOrigin.setX(glyphOrigin.x() + lastPaintedGlyphRect.width());
</span><span class="cx"> 
</span><span class="cx">         // There's a chance that if the font size is small enough the glue glyph has been reduced to an empty rectangle
</span><span class="lines">@@ -851,20 +828,20 @@
</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_stretchyData.mode() == DrawNormal)
</del><ins>+    if (info.context().paintingDisabled() || info.phase != PaintPhaseForeground || style().visibility() != VISIBLE || m_stretchType == StretchType::Unstretched)
</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_stretchyData.mode() == DrawSizeVariant) {
-        ASSERT(m_stretchyData.variant().glyph);
</del><ins>+    if (m_stretchType == StretchType::SizeVariant) {
+        ASSERT(m_variant.isValid());
</ins><span class="cx">         GlyphBuffer buffer;
</span><del>-        buffer.add(m_stretchyData.variant().glyph, m_stretchyData.variant().font, advanceWidthForGlyph(m_stretchyData.variant()));
</del><ins>+        buffer.add(m_variant.glyph, m_variant.font, advanceWidthForGlyph(m_variant));
</ins><span class="cx">         LayoutPoint operatorTopLeft = ceiledIntPoint(paintOffset + location());
</span><del>-        FloatRect glyphBounds = boundsForGlyph(m_stretchyData.variant());
</del><ins>+        FloatRect glyphBounds = boundsForGlyph(m_variant);
</ins><span class="cx">         LayoutPoint operatorOrigin(operatorTopLeft.x(), operatorTopLeft.y() - glyphBounds.y());
</span><del>-        info.context().drawGlyphs(style().fontCascade(), *m_stretchyData.variant().font, buffer, 0, 1, operatorOrigin);
</del><ins>+        info.context().drawGlyphs(style().fontCascade(), *m_variant.font, buffer, 0, 1, operatorOrigin);
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -877,30 +854,30 @@
</span><span class="cx"> void RenderMathMLOperator::paintVerticalGlyphAssembly(PaintInfo&amp; info, const LayoutPoint&amp; paintOffset)
</span><span class="cx"> {
</span><span class="cx">     ASSERT(m_isVertical);
</span><del>-    ASSERT(m_stretchyData.mode() == DrawGlyphAssembly);
-    ASSERT(m_stretchyData.top().glyph);
-    ASSERT(m_stretchyData.bottom().glyph);
</del><ins>+    ASSERT(m_stretchType == StretchType::GlyphAssembly);
+    ASSERT(m_assembly.topOrRight.isValid());
+    ASSERT(m_assembly.bottomOrLeft.isValid());
</ins><span class="cx"> 
</span><span class="cx">     // We are positioning the glyphs so that the edge of the tight glyph bounds line up exactly with the edges of our paint box.
</span><span class="cx">     LayoutPoint operatorTopLeft = paintOffset + location();
</span><span class="cx">     operatorTopLeft.move(style().isLeftToRightDirection() ? m_leadingSpace : m_trailingSpace, 0);
</span><span class="cx">     operatorTopLeft = ceiledIntPoint(operatorTopLeft);
</span><del>-    FloatRect topGlyphBounds = boundsForGlyph(m_stretchyData.top());
</del><ins>+    FloatRect topGlyphBounds = boundsForGlyph(m_assembly.topOrRight);
</ins><span class="cx">     LayoutPoint topGlyphOrigin(operatorTopLeft.x(), operatorTopLeft.y() - topGlyphBounds.y());
</span><del>-    LayoutRect topGlyphPaintRect = paintGlyph(info, m_stretchyData.top(), topGlyphOrigin, TrimBottom);
</del><ins>+    LayoutRect topGlyphPaintRect = paintGlyph(info, m_assembly.topOrRight, topGlyphOrigin, TrimBottom);
</ins><span class="cx"> 
</span><del>-    FloatRect bottomGlyphBounds = boundsForGlyph(m_stretchyData.bottom());
</del><ins>+    FloatRect bottomGlyphBounds = boundsForGlyph(m_assembly.bottomOrLeft);
</ins><span class="cx">     LayoutPoint bottomGlyphOrigin(operatorTopLeft.x(), operatorTopLeft.y() + offsetHeight() - (bottomGlyphBounds.height() + bottomGlyphBounds.y()));
</span><del>-    LayoutRect bottomGlyphPaintRect = paintGlyph(info, m_stretchyData.bottom(), bottomGlyphOrigin, TrimTop);
</del><ins>+    LayoutRect bottomGlyphPaintRect = paintGlyph(info, m_assembly.bottomOrLeft, bottomGlyphOrigin, TrimTop);
</ins><span class="cx"> 
</span><del>-    if (m_stretchyData.middle().glyph) {
</del><ins>+    if (m_assembly.middle.isValid()) {
</ins><span class="cx">         // Center the glyph origin between the start and end glyph paint extents. Then shift it half the paint height toward the bottom glyph.
</span><del>-        FloatRect middleGlyphBounds = boundsForGlyph(m_stretchyData.middle());
</del><ins>+        FloatRect middleGlyphBounds = boundsForGlyph(m_assembly.middle);
</ins><span class="cx">         LayoutPoint middleGlyphOrigin(operatorTopLeft.x(), topGlyphOrigin.y());
</span><span class="cx">         middleGlyphOrigin.moveBy(LayoutPoint(0, (bottomGlyphPaintRect.y() - topGlyphPaintRect.maxY()) / 2.0));
</span><span class="cx">         middleGlyphOrigin.moveBy(LayoutPoint(0, middleGlyphBounds.height() / 2.0));
</span><span class="cx"> 
</span><del>-        LayoutRect middleGlyphPaintRect = paintGlyph(info, m_stretchyData.middle(), middleGlyphOrigin, TrimTopAndBottom);
</del><ins>+        LayoutRect middleGlyphPaintRect = paintGlyph(info, m_assembly.middle, middleGlyphOrigin, TrimTopAndBottom);
</ins><span class="cx">         fillWithVerticalExtensionGlyph(info, topGlyphPaintRect.minXMaxYCorner(), middleGlyphPaintRect.minXMinYCorner());
</span><span class="cx">         fillWithVerticalExtensionGlyph(info, middleGlyphPaintRect.minXMaxYCorner(), bottomGlyphPaintRect.minXMinYCorner());
</span><span class="cx">     } else
</span><span class="lines">@@ -910,26 +887,26 @@
</span><span class="cx"> void RenderMathMLOperator::paintHorizontalGlyphAssembly(PaintInfo&amp; info, const LayoutPoint&amp; paintOffset)
</span><span class="cx"> {
</span><span class="cx">     ASSERT(!m_isVertical);
</span><del>-    ASSERT(m_stretchyData.mode() == DrawGlyphAssembly);
-    ASSERT(m_stretchyData.left().glyph);
-    ASSERT(m_stretchyData.right().glyph);
</del><ins>+    ASSERT(m_stretchType == StretchType::GlyphAssembly);
+    ASSERT(m_assembly.bottomOrLeft.isValid());
+    ASSERT(m_assembly.topOrRight.isValid());
</ins><span class="cx"> 
</span><span class="cx">     // We are positioning the glyphs so that the edge of the tight glyph bounds line up exactly with the edges of our paint box.
</span><span class="cx">     LayoutPoint operatorTopLeft = paintOffset + location();
</span><span class="cx">     operatorTopLeft.move(m_leadingSpace, 0);
</span><span class="cx">     operatorTopLeft = ceiledIntPoint(operatorTopLeft);
</span><span class="cx">     LayoutPoint leftGlyphOrigin(operatorTopLeft.x(), operatorTopLeft.y() + m_stretchHeightAboveBaseline);
</span><del>-    LayoutRect leftGlyphPaintRect = paintGlyph(info, m_stretchyData.left(), leftGlyphOrigin, TrimRight);
</del><ins>+    LayoutRect leftGlyphPaintRect = paintGlyph(info, m_assembly.bottomOrLeft, leftGlyphOrigin, TrimRight);
</ins><span class="cx"> 
</span><del>-    FloatRect rightGlyphBounds = boundsForGlyph(m_stretchyData.right());
</del><ins>+    FloatRect rightGlyphBounds = boundsForGlyph(m_assembly.topOrRight);
</ins><span class="cx">     LayoutPoint rightGlyphOrigin(operatorTopLeft.x() + offsetWidth() - rightGlyphBounds.width(), operatorTopLeft.y() + m_stretchHeightAboveBaseline);
</span><del>-    LayoutRect rightGlyphPaintRect = paintGlyph(info, m_stretchyData.right(), rightGlyphOrigin, TrimLeft);
</del><ins>+    LayoutRect rightGlyphPaintRect = paintGlyph(info, m_assembly.topOrRight, rightGlyphOrigin, TrimLeft);
</ins><span class="cx"> 
</span><del>-    if (m_stretchyData.middle().glyph) {
</del><ins>+    if (m_assembly.middle.isValid()) {
</ins><span class="cx">         // Center the glyph origin between the start and end glyph paint extents.
</span><span class="cx">         LayoutPoint middleGlyphOrigin(operatorTopLeft.x(), leftGlyphOrigin.y());
</span><span class="cx">         middleGlyphOrigin.moveBy(LayoutPoint((rightGlyphPaintRect.x() - leftGlyphPaintRect.maxX()) / 2.0, 0));
</span><del>-        LayoutRect middleGlyphPaintRect = paintGlyph(info, m_stretchyData.middle(), middleGlyphOrigin, TrimLeftAndRight);
</del><ins>+        LayoutRect middleGlyphPaintRect = paintGlyph(info, m_assembly.middle, middleGlyphOrigin, TrimLeftAndRight);
</ins><span class="cx">         fillWithHorizontalExtensionGlyph(info, leftGlyphPaintRect.maxXMinYCorner(), middleGlyphPaintRect.minXMinYCorner());
</span><span class="cx">         fillWithHorizontalExtensionGlyph(info, middleGlyphPaintRect.maxXMinYCorner(), rightGlyphPaintRect.minXMinYCorner());
</span><span class="cx">     } else
</span><span class="lines">@@ -939,7 +916,7 @@
</span><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_stretchyData.mode() != DrawNormal || isInvisibleOperator())
</del><ins>+    if (m_stretchType != StretchType::Unstretched || isInvisibleOperator())
</ins><span class="cx">         return;
</span><span class="cx">     RenderMathMLToken::paintChildren(paintInfo, paintOffset, paintInfoForChild, usePrintRect);
</span><span class="cx"> }
</span><span class="lines">@@ -954,19 +931,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_stretchyData.mode() == DrawNormal) {
</del><ins>+    if (m_stretchType == StretchType::Unstretched) {
</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_stretchyData.mode() == DrawSizeVariant)
-        return width - advanceWidthForGlyph(m_stretchyData.variant());
</del><ins>+    if (m_stretchType == StretchType::SizeVariant)
+        return width - advanceWidthForGlyph(m_variant);
</ins><span class="cx"> 
</span><del>-    float assemblyWidth = advanceWidthForGlyph(m_stretchyData.top());
-    assemblyWidth = std::max(assemblyWidth, advanceWidthForGlyph(m_stretchyData.bottom()));
-    assemblyWidth = std::max(assemblyWidth, advanceWidthForGlyph(m_stretchyData.extension()));
-    if (m_stretchyData.middle().glyph)
-        assemblyWidth = std::max(assemblyWidth, advanceWidthForGlyph(m_stretchyData.middle()));
</del><ins>+    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));
</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 (200568 => 200569)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/mathml/RenderMathMLOperator.h        2016-05-09 04:55:34 UTC (rev 200568)
+++ trunk/Source/WebCore/rendering/mathml/RenderMathMLOperator.h        2016-05-09 05:51:37 UTC (rev 200569)
</span><span class="lines">@@ -51,7 +51,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;
</del><ins>+    LayoutUnit italicCorrection() const { return m_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,60 +73,19 @@
</span><span class="cx">     UChar textContent() const { return m_textContent; }
</span><span class="cx"> 
</span><span class="cx"> private:
</span><del>-    enum DrawMode {
-        DrawNormal, DrawSizeVariant, DrawGlyphAssembly
</del><ins>+    struct GlyphAssemblyData {
+        GlyphData topOrRight;
+        GlyphData extension;
+        GlyphData bottomOrLeft;
+        GlyphData middle;
</ins><span class="cx">     };
</span><del>-
-    class StretchyData {
-    public:
-        DrawMode mode() const { return m_mode; }
-        GlyphData variant() const { return m_data[0]; }
-        GlyphData top() const { return m_data[0]; }
-        GlyphData extension() const { return m_data[1]; }
-        GlyphData bottom() const { return m_data[2]; }
-        GlyphData middle() const { return m_data[3]; }
-        GlyphData left() const { return m_data[2]; }
-        GlyphData right() const { return m_data[0]; }
-
-        void setNormalMode()
-        {
-            m_mode = DrawNormal;
-        }
-        void setSizeVariantMode(const GlyphData&amp; variant)
-        {
-            m_mode = DrawSizeVariant;
-            m_data[0] = variant;
-        }
-        void setGlyphAssemblyMode(const GlyphData&amp; top, const GlyphData&amp; extension, const GlyphData&amp; bottom, const GlyphData&amp; middle)
-        {
-            m_mode = DrawGlyphAssembly;
-            m_data[0] = top;
-            m_data[1] = extension;
-            m_data[2] = bottom;
-            m_data[3] = middle;
-        }
-        StretchyData()
-            : m_mode(DrawNormal) { }
-        StretchyData(const StretchyData&amp; data)
-        {
-            switch (data.m_mode) {
-            case DrawNormal:
-                setNormalMode();
-                break;
-            case DrawSizeVariant:
-                setSizeVariantMode(data.variant());
-                break;
-            case DrawGlyphAssembly:
-                setGlyphAssemblyMode(data.top(), data.extension(), data.bottom(), data.middle());
-                break;
-            }
-        }
-
-    private:
-        DrawMode m_mode;
-        // FIXME: For OpenType fonts with a MATH table all the glyphs are from the same font, so we would only need to store the glyph indices here.
-        GlyphData m_data[4];
</del><ins>+    enum class StretchType { Unstretched, SizeVariant, GlyphAssembly };
+    StretchType m_stretchType;
+    union {
+        GlyphData m_variant;
+        GlyphAssemblyData m_assembly;
</ins><span class="cx">     };
</span><ins>+    LayoutUnit m_italicCorrection;
</ins><span class="cx"> 
</span><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="lines">@@ -142,9 +101,11 @@
</span><span class="cx">     bool shouldAllowStretching() const;
</span><span class="cx"> 
</span><span class="cx">     bool getBaseGlyph(const RenderStyle&amp;, GlyphData&amp;) const;
</span><del>-    bool getGlyphAssemblyFallBack(Vector&lt;OpenTypeMathData::AssemblyPart&gt;, StretchyData&amp;) const;
-    StretchyData getDisplayStyleLargeOperator() const;
-    StretchyData findStretchyData(float* maximumGlyphWidth);
</del><ins>+    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);
</ins><span class="cx"> 
</span><span class="cx">     enum GlyphPaintTrimming {
</span><span class="cx">         TrimTop,
</span><span class="lines">@@ -176,7 +137,6 @@
</span><span class="cx">     LayoutUnit m_trailingSpace;
</span><span class="cx">     LayoutUnit m_minSize;
</span><span class="cx">     LayoutUnit m_maxSize;
</span><del>-    StretchyData m_stretchyData;
</del><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebCore
</span></span></pre>
</div>
</div>

</body>
</html>