Title: [200569] trunk/Source/WebCore
Revision
200569
Author
[email protected]
Date
2016-05-08 22:51:37 -0700 (Sun, 08 May 2016)

Log Message

RenderMathMLOperator: refactor management of stretchy data and italic correction
https://bugs.webkit.org/show_bug.cgi?id=156913

Patch by Frederic Wang <[email protected]> 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.

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (200568 => 200569)


--- 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)
@@ -1,3 +1,64 @@
+2016-05-08  Frederic Wang  <[email protected]>
+
+        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.
+
 2016-05-08  Zalan Bujtas  <[email protected]>
 
         iOS selection: Use inflow containing block for positioned <br>.

Modified: trunk/Source/WebCore/rendering/mathml/RenderMathMLOperator.cpp (200568 => 200569)


--- 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)
@@ -202,18 +202,6 @@
     return false;
 }
 
-LayoutUnit RenderMathMLOperator::italicCorrection() const
-{
-    if (isLargeOperatorInDisplayStyle()) {
-        const auto& primaryFont = style().fontCascade().primaryFont();
-        if (auto* mathData = primaryFont.mathData()) {
-            StretchyData largeOperator = getDisplayStyleLargeOperator();
-            return mathData->getItalicCorrection(primaryFont, largeOperator.variant().glyph);
-        }
-    }
-    return 0;
-}
-
 void RenderMathMLOperator::stretchTo(LayoutUnit heightAboveBaseline, LayoutUnit depthBelowBaseline)
 {
     ASSERT(hasOperatorFlag(MathMLOperatorDictionary::Stretchy));
@@ -317,12 +305,12 @@
     }
     if (isLargeOperatorInDisplayStyle()) {
         // Large operators in STIX Word have incorrect advance width, causing misplacement of superscript, so we use the glyph bound instead (http://sourceforge.net/p/stixfonts/tracking/49/).
-        StretchyData largeOperator = getDisplayStyleLargeOperator();
-        if (largeOperator.mode() == DrawSizeVariant)
-            maximumGlyphWidth = boundsForGlyph(largeOperator.variant()).width();
+        calculateDisplayStyleLargeOperator();
+        if (m_stretchType == StretchType::SizeVariant)
+            maximumGlyphWidth = boundsForGlyph(m_variant).width();
     } else {
         // FIXME: some glyphs (e.g. the one for "FRACTION SLASH" 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).
-        findStretchyData(&maximumGlyphWidth);
+        calculateStretchyData(&maximumGlyphWidth);
     }
     m_maxPreferredLogicalWidth = m_minPreferredLogicalWidth = m_leadingSpace + maximumGlyphWidth + m_trailingSpace;
 }
@@ -392,13 +380,21 @@
     return baseGlyph.isValid() && baseGlyph.font == &style.fontCascade().primaryFont();
 }
 
-bool RenderMathMLOperator::getGlyphAssemblyFallBack(Vector<OpenTypeMathData::AssemblyPart> assemblyParts, StretchyData& stretchyData) const
+void RenderMathMLOperator::setSizeVariant(const GlyphData& sizeVariant)
 {
-    GlyphData top;
-    GlyphData extension;
-    GlyphData bottom;
-    GlyphData middle;
+    ASSERT(sizeVariant.isValid() && sizeVariant.font->mathData());
+    m_stretchType = StretchType::SizeVariant;
+    m_variant = sizeVariant;
+}
 
+void RenderMathMLOperator::setGlyphAssembly(const GlyphAssemblyData& assemblyData)
+{
+    m_stretchType = StretchType::GlyphAssembly;
+    m_assembly = assemblyData;
+}
+
+bool RenderMathMLOperator::calculateGlyphAssemblyFallBack(const Vector<OpenTypeMathData::AssemblyPart>& assemblyParts, GlyphAssemblyData& 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
@@ -422,8 +418,8 @@
         None
     };
     PartType expectedPartType = Start;
-    extension.glyph = 0;
-    middle.glyph = 0;
+    assemblyData.extension.glyph = 0;
+    assemblyData.middle.glyph = 0;
     for (auto& part : assemblyParts) {
         if (nonExtenderCount < 3) {
             // If we only have at most two non-extenders then we skip the middle glyph.
@@ -433,9 +429,9 @@
                 expectedPartType = End;
         }
         if (part.isExtender) {
-            if (!extension.glyph)
-                extension.glyph = part.glyph; // We copy the extender part.
-            else if (extension.glyph != part.glyph)
+            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) {
@@ -461,19 +457,19 @@
         switch (expectedPartType) {
         case Start:
             // We copy the left/bottom part.
-            bottom.glyph = part.glyph;
+            assemblyData.bottomOrLeft.glyph = part.glyph;
             expectedPartType = ExtenderBetweenStartAndMiddle;
             continue;
         case ExtenderBetweenStartAndMiddle:
         case Middle:
             // We copy the middle part.
-            middle.glyph = part.glyph;
+            assemblyData.middle.glyph = part.glyph;
             expectedPartType = ExtenderBetweenMiddleAndEnd;
             continue;
         case ExtenderBetweenMiddleAndEnd:
         case End:
             // We copy the right/top part.
-            top.glyph = part.glyph;
+            assemblyData.topOrRight.glyph = part.glyph;
             expectedPartType = None;
             continue;
         case None:
@@ -482,35 +478,30 @@
         }
     }
 
-    if (!extension.glyph)
+    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 (!top.glyph)
-        top.glyph = extension.glyph;
-    if (!bottom.glyph)
-        bottom.glyph = 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;
 
-    top.font = &style().fontCascade().primaryFont();
-    extension.font = top.font;
-    bottom.font = top.font;
-    if (middle.glyph)
-        middle.font = top.font;
+    assemblyData.topOrRight.font = &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;
 
-    stretchyData.setGlyphAssemblyMode(top, extension, bottom, middle);
-
     return true;
 }
 
-RenderMathMLOperator::StretchyData RenderMathMLOperator::getDisplayStyleLargeOperator() const
+void RenderMathMLOperator::calculateDisplayStyleLargeOperator()
 {
-    StretchyData data;
-
     ASSERT(m_isVertical && isLargeOperatorInDisplayStyle());
 
     GlyphData baseGlyph;
     if (!getBaseGlyph(style(), baseGlyph) || !baseGlyph.font->mathData())
-        return data;
+        return;
 
     Vector<Glyph> sizeVariants;
     Vector<OpenTypeMathData::AssemblyPart> assemblyParts;
@@ -521,53 +512,54 @@
     baseGlyph.font->mathData()->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& variant : sizeVariants) {
-        GlyphData sizeVariant;
-        sizeVariant.glyph = variant;
-        sizeVariant.font = baseGlyph.font;
-        data.setSizeVariantMode(sizeVariant);
-        if (boundsForGlyph(sizeVariant).height() >= displayOperatorMinHeight)
-            return data;
+    for (auto& sizeVariant : sizeVariants) {
+        GlyphData glyphData(sizeVariant, baseGlyph.font);
+        setSizeVariant(glyphData);
+        m_italicCorrection = glyphData.font->mathData()->getItalicCorrection(*glyphData.font, glyphData.glyph);
+        if (heightForGlyph(glyphData) >= displayOperatorMinHeight)
+            break;
     }
-    return data;
 }
 
-RenderMathMLOperator::StretchyData RenderMathMLOperator::findStretchyData(float* maximumGlyphWidth)
+void RenderMathMLOperator::calculateStretchyData(float* maximumGlyphWidth, LayoutUnit targetSize)
 {
     ASSERT(!maximumGlyphWidth || m_isVertical);
 
-    StretchyData data;
-    StretchyData assemblyData;
-
     GlyphData baseGlyph;
     if (!getBaseGlyph(style(), baseGlyph))
-        return data;
+        return;
     
+    if (!maximumGlyphWidth) {
+        // We do not stretch if the base glyph is large enough.
+        float baseSize = m_isVertical ? heightForGlyph(baseGlyph) : advanceWidthForGlyph(baseGlyph);
+        if (targetSize <= baseSize)
+            return;
+    }
+
+    GlyphAssemblyData assemblyData;
     if (baseGlyph.font->mathData()) {
         Vector<Glyph> sizeVariants;
         Vector<OpenTypeMathData::AssemblyPart> assemblyParts;
         baseGlyph.font->mathData()->getMathVariants(baseGlyph.glyph, m_isVertical, sizeVariants, assemblyParts);
         // We verify the size variants.
-        for (auto& variant : sizeVariants) {
-            GlyphData sizeVariant;
-            sizeVariant.glyph = variant;
-            sizeVariant.font = baseGlyph.font;
+        for (auto& sizeVariant : sizeVariants) {
+            GlyphData glyphData(sizeVariant, baseGlyph.font);
             if (maximumGlyphWidth)
-                *maximumGlyphWidth = std::max(*maximumGlyphWidth, advanceWidthForGlyph(sizeVariant));
+                *maximumGlyphWidth = std::max(*maximumGlyphWidth, advanceWidthForGlyph(glyphData));
             else {
-                data.setSizeVariantMode(sizeVariant);
-                float size = m_isVertical ? heightForGlyph(sizeVariant) : advanceWidthForGlyph(sizeVariant);
-                if (size >= stretchSize()) 
-                    return data;
+                setSizeVariant(glyphData);
+                float size = m_isVertical ? heightForGlyph(glyphData) : advanceWidthForGlyph(glyphData);
+                if (size >= targetSize)
+                    return;
             }
         }
 
         // We verify if there is a construction.
-        if (!getGlyphAssemblyFallBack(assemblyParts, assemblyData))
-            return data;
+        if (!calculateGlyphAssemblyFallBack(assemblyParts, assemblyData))
+            return;
     } else {
         if (!m_isVertical)
-            return data;
+            return;
 
         // If the font does not have a MATH table, we fallback to the Unicode-only constructions.
         const StretchyCharacter* stretchyCharacter = nullptr;
@@ -585,45 +577,32 @@
 
         // If we didn't find a stretchy character set for this character, we don't know how to stretch it.
         if (!stretchyCharacter)
-            return data;
+            return;
 
         // We convert the list of Unicode characters into a list of glyph data.
-        GlyphData top = style().fontCascade().glyphDataForCharacter(stretchyCharacter->topChar, false);
-        GlyphData extension = style().fontCascade().glyphDataForCharacter(stretchyCharacter->extensionChar, false);
-        GlyphData bottom = style().fontCascade().glyphDataForCharacter(stretchyCharacter->bottomChar, false);
-        GlyphData middle;
-        if (stretchyCharacter->middleChar)
-            middle = style().fontCascade().glyphDataForCharacter(stretchyCharacter->middleChar, false);
-        assemblyData.setGlyphAssemblyMode(top, extension, bottom, middle);
+        assemblyData.topOrRight = style().fontCascade().glyphDataForCharacter(stretchyCharacter->topChar, false);
+        assemblyData.extension = style().fontCascade().glyphDataForCharacter(stretchyCharacter->extensionChar, false);
+        assemblyData.bottomOrLeft = style().fontCascade().glyphDataForCharacter(stretchyCharacter->bottomChar, false);
+        assemblyData.middle = stretchyCharacter->middleChar ? style().fontCascade().glyphDataForCharacter(stretchyCharacter->middleChar, false) : GlyphData();
     }
 
-    ASSERT(assemblyData.mode() == DrawGlyphAssembly);
-
     // If we are measuring the maximum width, verify each component.
     if (maximumGlyphWidth) {
-        *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;
+        *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 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 > stretchSize())
-        return data;
+    float minSize = m_isVertical ?
+        heightForGlyph(assemblyData.topOrRight) + heightForGlyph(assemblyData.middle) + heightForGlyph(assemblyData.bottomOrLeft)
+        : advanceWidthForGlyph(assemblyData.bottomOrLeft) + advanceWidthForGlyph(assemblyData.middle) + advanceWidthForGlyph(assemblyData.topOrRight);
+    if (minSize > targetSize)
+        return;
 
-    return assemblyData;
+    setGlyphAssembly(assemblyData);
 }
 
 void RenderMathMLOperator::updateStyle()
@@ -632,7 +611,8 @@
     if (!firstChild())
         return;
 
-    m_stretchyData.setNormalMode();
+    m_stretchType = StretchType::Unstretched;
+    m_italicCorrection = 0;
     // We add spacing around the operator.
     // FIXME: The spacing should be added to the whole embellished operator (https://bugs.webkit.org/show_bug.cgi?id=124831).
     // FIXME: The spacing should only be added inside (perhaps inferred) mrow (http://www.w3.org/TR/MathML/chapter3.html#presm.opspacing).
@@ -647,27 +627,24 @@
         return;
 
     if (m_isVertical && isLargeOperatorInDisplayStyle())
-        m_stretchyData = getDisplayStyleLargeOperator();
+        calculateDisplayStyleLargeOperator();
     else {
-        // 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() <= baseSize)
+        calculateStretchyData(nullptr, stretchSize());
+        if (m_stretchType == StretchType::Unstretched)
             return;
-        m_stretchyData = findStretchyData(nullptr);
     }
 
-    if (m_isVertical && m_stretchyData.mode() == DrawSizeVariant) {
+    if (m_isVertical && m_stretchType == StretchType::SizeVariant) {
         // We resize the operator to match the one of the size variant.
         if (isLargeOperatorInDisplayStyle()) {
-            // The stretch size is actually not involved in the selection of the size variant in getDisplayStyleLargeOperator.
+            // The stretch size is actually not involved in the selection of the size variant in findDisplayStyleLargeOperator.
             // We simply use the height and depth of the selected size variant glyph.
-            FloatRect glyphBounds = boundsForGlyph(m_stretchyData.variant());
+            FloatRect glyphBounds = boundsForGlyph(m_variant);
             m_stretchHeightAboveBaseline = -glyphBounds.y();
             m_stretchDepthBelowBaseline = glyphBounds.maxY();
         } else {
             // We rescale the height and depth proportionately.
-            float variantSize = heightForGlyph(m_stretchyData.variant());
+            float variantSize = heightForGlyph(m_variant);
             float size = stretchSize();
             float aspect = size > 0 ? variantSize / size : 1.0;
             m_stretchHeightAboveBaseline *= aspect;
@@ -676,30 +653,30 @@
     }
 
     if (!m_isVertical) {
-        if (m_stretchyData.mode() == DrawSizeVariant) {
-            FloatRect glyphBounds = boundsForGlyph(m_stretchyData.variant());
+        if (m_stretchType == StretchType::SizeVariant) {
+            FloatRect glyphBounds = boundsForGlyph(m_variant);
             m_stretchHeightAboveBaseline = -glyphBounds.y();
             m_stretchDepthBelowBaseline = glyphBounds.maxY();
-            m_stretchWidth = advanceWidthForGlyph(m_stretchyData.variant());
-        } else if (m_stretchyData.mode() == DrawGlyphAssembly) {
+            m_stretchWidth = advanceWidthForGlyph(m_variant);
+        } else if (m_stretchType == StretchType::GlyphAssembly) {
             FloatRect glyphBounds;
             m_stretchHeightAboveBaseline = 0;
             m_stretchDepthBelowBaseline = 0;
 
-            glyphBounds = boundsForGlyph(m_stretchyData.left());
+            glyphBounds = boundsForGlyph(m_assembly.bottomOrLeft);
             m_stretchHeightAboveBaseline = std::max<LayoutUnit>(m_stretchHeightAboveBaseline, -glyphBounds.y());
             m_stretchDepthBelowBaseline = std::max<LayoutUnit>(m_stretchDepthBelowBaseline, glyphBounds.maxY());
 
-            glyphBounds = boundsForGlyph(m_stretchyData.right());
+            glyphBounds = boundsForGlyph(m_assembly.topOrRight);
             m_stretchHeightAboveBaseline = std::max<LayoutUnit>(m_stretchHeightAboveBaseline, -glyphBounds.y());
             m_stretchDepthBelowBaseline = std::max<LayoutUnit>(m_stretchDepthBelowBaseline, glyphBounds.maxY());
 
-            glyphBounds = boundsForGlyph(m_stretchyData.extension());
+            glyphBounds = boundsForGlyph(m_assembly.extension);
             m_stretchHeightAboveBaseline = std::max<LayoutUnit>(m_stretchHeightAboveBaseline, -glyphBounds.y());
             m_stretchDepthBelowBaseline = std::max<LayoutUnit>(m_stretchDepthBelowBaseline, glyphBounds.maxY());
 
-            if (m_stretchyData.middle().glyph) {
-                glyphBounds = boundsForGlyph(m_stretchyData.middle());
+            if (m_assembly.middle.isValid()) {
+                glyphBounds = boundsForGlyph(m_assembly.middle);
                 m_stretchHeightAboveBaseline = std::max<LayoutUnit>(m_stretchHeightAboveBaseline, -glyphBounds.y());
                 m_stretchDepthBelowBaseline = std::max<LayoutUnit>(m_stretchDepthBelowBaseline, glyphBounds.maxY());
             }
@@ -709,14 +686,14 @@
 
 Optional<int> RenderMathMLOperator::firstLineBaseline() const
 {
-    if (m_stretchyData.mode() != DrawNormal)
+    if (m_stretchType != StretchType::Unstretched)
         return Optional<int>(m_stretchHeightAboveBaseline);
     return RenderMathMLToken::firstLineBaseline();
 }
 
 void RenderMathMLOperator::computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logicalTop, LogicalExtentComputedValues& computedValues) const
 {
-    if (m_stretchyData.mode() != DrawNormal)
+    if (m_stretchType != StretchType::Unstretched)
         logicalHeight = m_stretchHeightAboveBaseline + m_stretchDepthBelowBaseline;
     RenderBox::computeLogicalHeight(logicalHeight, logicalTop, computedValues);
 }
@@ -776,8 +753,8 @@
 void RenderMathMLOperator::fillWithVerticalExtensionGlyph(PaintInfo& info, const LayoutPoint& from, const LayoutPoint& to)
 {
     ASSERT(m_isVertical);
-    ASSERT(m_stretchyData.mode() == DrawGlyphAssembly);
-    ASSERT(m_stretchyData.extension().glyph);
+    ASSERT(m_stretchType == StretchType::GlyphAssembly);
+    ASSERT(m_assembly.extension.isValid());
     ASSERT(from.y() <= to.y());
 
     // If there is no space for the extension glyph, we don't need to do anything.
@@ -786,7 +763,7 @@
 
     GraphicsContextStateSaver stateSaver(info.context());
 
-    FloatRect glyphBounds = boundsForGlyph(m_stretchyData.extension());
+    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.
@@ -801,7 +778,7 @@
     FloatRect lastPaintedGlyphRect(from, FloatSize());
 
     while (lastPaintedGlyphRect.maxY() < to.y()) {
-        lastPaintedGlyphRect = paintGlyph(info, m_stretchyData.extension(), glyphOrigin, TrimTopAndBottom);
+        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
@@ -814,8 +791,8 @@
 void RenderMathMLOperator::fillWithHorizontalExtensionGlyph(PaintInfo& info, const LayoutPoint& from, const LayoutPoint& to)
 {
     ASSERT(!m_isVertical);
-    ASSERT(m_stretchyData.mode() == DrawGlyphAssembly);
-    ASSERT(m_stretchyData.extension().glyph);
+    ASSERT(m_stretchType == StretchType::GlyphAssembly);
+    ASSERT(m_assembly.extension.isValid());
     ASSERT(from.x() <= to.x());
 
     // If there is no space for the extension glyph, we don't need to do anything.
@@ -837,7 +814,7 @@
     FloatRect lastPaintedGlyphRect(from, FloatSize());
 
     while (lastPaintedGlyphRect.maxX() < to.x()) {
-        lastPaintedGlyphRect = paintGlyph(info, m_stretchyData.extension(), glyphOrigin, TrimLeftAndRight);
+        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
@@ -851,20 +828,20 @@
 {
     RenderMathMLToken::paint(info, paintOffset);
 
-    if (info.context().paintingDisabled() || info.phase != PaintPhaseForeground || style().visibility() != VISIBLE || m_stretchyData.mode() == DrawNormal)
+    if (info.context().paintingDisabled() || info.phase != PaintPhaseForeground || style().visibility() != VISIBLE || m_stretchType == StretchType::Unstretched)
         return;
 
     GraphicsContextStateSaver stateSaver(info.context());
     info.context().setFillColor(style().visitedDependentColor(CSSPropertyColor));
 
-    if (m_stretchyData.mode() == DrawSizeVariant) {
-        ASSERT(m_stretchyData.variant().glyph);
+    if (m_stretchType == StretchType::SizeVariant) {
+        ASSERT(m_variant.isValid());
         GlyphBuffer buffer;
-        buffer.add(m_stretchyData.variant().glyph, m_stretchyData.variant().font, advanceWidthForGlyph(m_stretchyData.variant()));
+        buffer.add(m_variant.glyph, m_variant.font, advanceWidthForGlyph(m_variant));
         LayoutPoint operatorTopLeft = ceiledIntPoint(paintOffset + location());
-        FloatRect glyphBounds = boundsForGlyph(m_stretchyData.variant());
+        FloatRect glyphBounds = boundsForGlyph(m_variant);
         LayoutPoint operatorOrigin(operatorTopLeft.x(), operatorTopLeft.y() - glyphBounds.y());
-        info.context().drawGlyphs(style().fontCascade(), *m_stretchyData.variant().font, buffer, 0, 1, operatorOrigin);
+        info.context().drawGlyphs(style().fontCascade(), *m_variant.font, buffer, 0, 1, operatorOrigin);
         return;
     }
 
@@ -877,30 +854,30 @@
 void RenderMathMLOperator::paintVerticalGlyphAssembly(PaintInfo& info, const LayoutPoint& paintOffset)
 {
     ASSERT(m_isVertical);
-    ASSERT(m_stretchyData.mode() == DrawGlyphAssembly);
-    ASSERT(m_stretchyData.top().glyph);
-    ASSERT(m_stretchyData.bottom().glyph);
+    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_stretchyData.top());
+    FloatRect topGlyphBounds = boundsForGlyph(m_assembly.topOrRight);
     LayoutPoint topGlyphOrigin(operatorTopLeft.x(), operatorTopLeft.y() - topGlyphBounds.y());
-    LayoutRect topGlyphPaintRect = paintGlyph(info, m_stretchyData.top(), topGlyphOrigin, TrimBottom);
+    LayoutRect topGlyphPaintRect = paintGlyph(info, m_assembly.topOrRight, topGlyphOrigin, TrimBottom);
 
-    FloatRect bottomGlyphBounds = boundsForGlyph(m_stretchyData.bottom());
+    FloatRect bottomGlyphBounds = boundsForGlyph(m_assembly.bottomOrLeft);
     LayoutPoint bottomGlyphOrigin(operatorTopLeft.x(), operatorTopLeft.y() + offsetHeight() - (bottomGlyphBounds.height() + bottomGlyphBounds.y()));
-    LayoutRect bottomGlyphPaintRect = paintGlyph(info, m_stretchyData.bottom(), bottomGlyphOrigin, TrimTop);
+    LayoutRect bottomGlyphPaintRect = paintGlyph(info, m_assembly.bottomOrLeft, bottomGlyphOrigin, TrimTop);
 
-    if (m_stretchyData.middle().glyph) {
+    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_stretchyData.middle());
+        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_stretchyData.middle(), middleGlyphOrigin, TrimTopAndBottom);
+        LayoutRect middleGlyphPaintRect = paintGlyph(info, m_assembly.middle, middleGlyphOrigin, TrimTopAndBottom);
         fillWithVerticalExtensionGlyph(info, topGlyphPaintRect.minXMaxYCorner(), middleGlyphPaintRect.minXMinYCorner());
         fillWithVerticalExtensionGlyph(info, middleGlyphPaintRect.minXMaxYCorner(), bottomGlyphPaintRect.minXMinYCorner());
     } else
@@ -910,26 +887,26 @@
 void RenderMathMLOperator::paintHorizontalGlyphAssembly(PaintInfo& info, const LayoutPoint& paintOffset)
 {
     ASSERT(!m_isVertical);
-    ASSERT(m_stretchyData.mode() == DrawGlyphAssembly);
-    ASSERT(m_stretchyData.left().glyph);
-    ASSERT(m_stretchyData.right().glyph);
+    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_stretchyData.left(), leftGlyphOrigin, TrimRight);
+    LayoutRect leftGlyphPaintRect = paintGlyph(info, m_assembly.bottomOrLeft, leftGlyphOrigin, TrimRight);
 
-    FloatRect rightGlyphBounds = boundsForGlyph(m_stretchyData.right());
+    FloatRect rightGlyphBounds = boundsForGlyph(m_assembly.topOrRight);
     LayoutPoint rightGlyphOrigin(operatorTopLeft.x() + offsetWidth() - rightGlyphBounds.width(), operatorTopLeft.y() + m_stretchHeightAboveBaseline);
-    LayoutRect rightGlyphPaintRect = paintGlyph(info, m_stretchyData.right(), rightGlyphOrigin, TrimLeft);
+    LayoutRect rightGlyphPaintRect = paintGlyph(info, m_assembly.topOrRight, rightGlyphOrigin, TrimLeft);
 
-    if (m_stretchyData.middle().glyph) {
+    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_stretchyData.middle(), middleGlyphOrigin, TrimLeftAndRight);
+        LayoutRect middleGlyphPaintRect = paintGlyph(info, m_assembly.middle, middleGlyphOrigin, TrimLeftAndRight);
         fillWithHorizontalExtensionGlyph(info, leftGlyphPaintRect.maxXMinYCorner(), middleGlyphPaintRect.minXMinYCorner());
         fillWithHorizontalExtensionGlyph(info, middleGlyphPaintRect.maxXMinYCorner(), rightGlyphPaintRect.minXMinYCorner());
     } else
@@ -939,7 +916,7 @@
 void RenderMathMLOperator::paintChildren(PaintInfo& paintInfo, const LayoutPoint& paintOffset, PaintInfo& paintInfoForChild, bool usePrintRect)
 {
     // We skip painting for invisible operators too to avoid some "missing character" glyph to appear if appropriate math fonts are not available.
-    if (m_stretchyData.mode() != DrawNormal || isInvisibleOperator())
+    if (m_stretchType != StretchType::Unstretched || isInvisibleOperator())
         return;
     RenderMathMLToken::paintChildren(paintInfo, paintOffset, paintInfoForChild, usePrintRect);
 }
@@ -954,19 +931,19 @@
     // Hence we determine the error in the logical width with respect to the actual width of the glyph(s) used to paint the operator.
     LayoutUnit width = logicalWidth();
 
-    if (m_stretchyData.mode() == DrawNormal) {
+    if (m_stretchType == StretchType::Unstretched) {
         GlyphData data = "" !style().isLeftToRightDirection());
         return width - advanceWidthForGlyph(data);
     }
 
-    if (m_stretchyData.mode() == DrawSizeVariant)
-        return width - advanceWidthForGlyph(m_stretchyData.variant());
+    if (m_stretchType == StretchType::SizeVariant)
+        return width - advanceWidthForGlyph(m_variant);
 
-    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()));
+    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));
     return width - assemblyWidth;
 }
 

Modified: trunk/Source/WebCore/rendering/mathml/RenderMathMLOperator.h (200568 => 200569)


--- 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)
@@ -51,7 +51,7 @@
     // FIXME: The displaystyle property is not implemented (https://bugs.webkit.org/show_bug.cgi?id=118737).
     bool isLargeOperatorInDisplayStyle() const { return !hasOperatorFlag(MathMLOperatorDictionary::Stretchy) && hasOperatorFlag(MathMLOperatorDictionary::LargeOp); }
     bool isVertical() const { return m_isVertical; }
-    LayoutUnit italicCorrection() const;
+    LayoutUnit italicCorrection() const { return m_italicCorrection; }
 
     void styleDidChange(StyleDifference, const RenderStyle* oldStyle) final;
     void updateStyle() final;
@@ -73,60 +73,19 @@
     UChar textContent() const { return m_textContent; }
 
 private:
-    enum DrawMode {
-        DrawNormal, DrawSizeVariant, DrawGlyphAssembly
+    struct GlyphAssemblyData {
+        GlyphData topOrRight;
+        GlyphData extension;
+        GlyphData bottomOrLeft;
+        GlyphData middle;
     };
-
-    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& variant)
-        {
-            m_mode = DrawSizeVariant;
-            m_data[0] = variant;
-        }
-        void setGlyphAssemblyMode(const GlyphData& top, const GlyphData& extension, const GlyphData& bottom, const GlyphData& 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& 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];
+    enum class StretchType { Unstretched, SizeVariant, GlyphAssembly };
+    StretchType m_stretchType;
+    union {
+        GlyphData m_variant;
+        GlyphAssemblyData m_assembly;
     };
+    LayoutUnit m_italicCorrection;
 
     const char* renderName() const override { return isAnonymous() ? "RenderMathMLOperator (anonymous)" : "RenderMathMLOperator"; }
     void paintChildren(PaintInfo& forSelf, const LayoutPoint&, PaintInfo& forChild, bool usePrintRect) final;
@@ -142,9 +101,11 @@
     bool shouldAllowStretching() const;
 
     bool getBaseGlyph(const RenderStyle&, GlyphData&) const;
-    bool getGlyphAssemblyFallBack(Vector<OpenTypeMathData::AssemblyPart>, StretchyData&) const;
-    StretchyData getDisplayStyleLargeOperator() const;
-    StretchyData findStretchyData(float* maximumGlyphWidth);
+    void setSizeVariant(const GlyphData&);
+    void setGlyphAssembly(const GlyphAssemblyData&);
+    bool calculateGlyphAssemblyFallBack(const Vector<OpenTypeMathData::AssemblyPart>&, GlyphAssemblyData&) const;
+    void calculateDisplayStyleLargeOperator();
+    void calculateStretchyData(float* maximumGlyphWidth, LayoutUnit targetSize = 0);
 
     enum GlyphPaintTrimming {
         TrimTop,
@@ -176,7 +137,6 @@
     LayoutUnit m_trailingSpace;
     LayoutUnit m_minSize;
     LayoutUnit m_maxSize;
-    StretchyData m_stretchyData;
 };
 
 } // namespace WebCore
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to