Title: [203714] trunk
Revision
203714
Author
[email protected]
Date
2016-07-26 00:46:58 -0700 (Tue, 26 Jul 2016)

Log Message

MathOperator: Add a mapping from combining to non-combining equivalents
https://bugs.webkit.org/show_bug.cgi?id=159513

Patch by Frederic Wang <[email protected]> on 2016-07-25
Reviewed by Darin Adler.

Source/WebCore:

Many math fonts provide stretch variants and assemblies for combining characters but not for
their non-combining equivalent. In the MathML recommendation, it is suggested to use
non-combining charaters, so we allow the operator stretching code to look for constructions
associated to these non-combining characters in order to still be able to stretch the
combining ones.

Test: mathml/presentation/bug159513.html

* rendering/mathml/MathOperator.cpp:
(WebCore::MathOperator::getGlyph): New function extending getBaseGlyph to retrieve the glyph
data for an arbitrary character.
(WebCore::MathOperator::getMathVariantsWithFallback): This helper function calls
getMathVariants for the base glyph. If no constructions are available, it calls
getMathVariants for the glyph associated to equivalent fallback characters as listed in the
small characterFallback table.
(WebCore::MathOperator::calculateStretchyData): Call getMathVariantsWithFallback instead of
getMathVariants. Note that we do not need to do that for calculateDisplayStyleLargeOperator
as we do not use fallback for large operators.
* rendering/mathml/MathOperator.h:
(WebCore::MathOperator::getBaseGlyph): Use getGlyph to implement this function.

LayoutTests:

* mathml/presentation/bug159513.html: Added.
* platform/gtk/mathml/presentation/bug159513-expected.png: Added.
* platform/gtk/mathml/presentation/bug159513-expected.txt: Added.
* platform/ios-simulator/TestExpectations: Skip this test on iOS.
* platform/mac/TestExpectations: Skip this test on Mac.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (203713 => 203714)


--- trunk/LayoutTests/ChangeLog	2016-07-26 05:46:53 UTC (rev 203713)
+++ trunk/LayoutTests/ChangeLog	2016-07-26 07:46:58 UTC (rev 203714)
@@ -1,3 +1,16 @@
+2016-07-25  Frederic Wang  <[email protected]>
+
+        MathOperator: Add a mapping from combining to non-combining equivalents
+        https://bugs.webkit.org/show_bug.cgi?id=159513
+
+        Reviewed by Darin Adler.
+
+        * mathml/presentation/bug159513.html: Added.
+        * platform/gtk/mathml/presentation/bug159513-expected.png: Added.
+        * platform/gtk/mathml/presentation/bug159513-expected.txt: Added.
+        * platform/ios-simulator/TestExpectations: Skip this test on iOS.
+        * platform/mac/TestExpectations: Skip this test on Mac.
+
 2016-07-25  Chris Dumez  <[email protected]>
 
         Second parameter to Range.setStart() / setEnd() should be mandatory

Added: trunk/LayoutTests/mathml/presentation/bug159513.html (0 => 203714)


--- trunk/LayoutTests/mathml/presentation/bug159513.html	                        (rev 0)
+++ trunk/LayoutTests/mathml/presentation/bug159513.html	2016-07-26 07:46:58 UTC (rev 203714)
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <title>bug 159513</title>
+    <meta charset="utf-8"/>
+    <style type="text/css">
+      /* This test requires the Latin Modern Math font. */
+      math {
+        font-family: Latin Modern Math;
+        font-size: 200%;
+      }
+    </style>
+  </head>
+  <body>
+    <p>Test passes if horizontal operators stretch.</p>
+    <math>
+      <mover>
+        <mspace width="60px" height="30px" mathbackground="green"/>
+        <mo stretchy="true">&#x005E;</mo>
+      </mover>
+    </math>
+    <math>
+      <munder>
+        <mspace width="60px" height="30px" mathbackground="green"/>
+        <mo stretchy="true">&#x005F;</mo>
+      </munder>
+    </math>
+    <math>
+      <mover>
+        <mspace width="60px" height="30px" mathbackground="green"/>
+        <mo stretchy="true">&#x007E;</mo>
+      </mover>
+    </math>
+    <math>
+      <mover>
+        <mspace width="60px" height="30px" mathbackground="green"/>
+        <mo stretchy="true">&#x00AF;</mo>
+      </mover>
+    </math>
+    <math>
+      <mover>
+        <mspace width="60px" height="30px" mathbackground="green"/>
+        <mo stretchy="true">&#x02C6;</mo>
+      </mover>
+    </math>
+    <math>
+      <mover>
+        <mspace width="60px" height="30px" mathbackground="green"/>
+        <mo stretchy="true">&#x02C7;</mo>
+      </mover>
+    </math>
+  </body>
+</html>
Property changes on: trunk/LayoutTests/mathml/presentation/bug159513.html
___________________________________________________________________

Added: svn:eol-style

+LF \ No newline at end of property

Added: svn:mime-type

+text/html \ No newline at end of property

Added: trunk/LayoutTests/platform/gtk/mathml/presentation/bug159513-expected.png


(Binary files differ)
Index: trunk/LayoutTests/platform/gtk/mathml/presentation/bug159513-expected.png =================================================================== --- trunk/LayoutTests/platform/gtk/mathml/presentation/bug159513-expected.png 2016-07-26 05:46:53 UTC (rev 203713) +++ trunk/LayoutTests/platform/gtk/mathml/presentation/bug159513-expected.png 2016-07-26 07:46:58 UTC (rev 203714) Property changes on: trunk/LayoutTests/platform/gtk/mathml/presentation/bug159513-expected.png ___________________________________________________________________

Added: svn:mime-type

+image/png \ No newline at end of property

Added: trunk/LayoutTests/platform/gtk/mathml/presentation/bug159513-expected.txt (0 => 203714)


--- trunk/LayoutTests/platform/gtk/mathml/presentation/bug159513-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/platform/gtk/mathml/presentation/bug159513-expected.txt	2016-07-26 07:46:58 UTC (rev 203714)
@@ -0,0 +1,62 @@
+layer at (0,0) size 800x600
+  RenderView at (0,0) size 800x600
+layer at (0,0) size 800x114
+  RenderBlock {HTML} at (0,0) size 800x114
+    RenderBody {BODY} at (8,16) size 784x90
+      RenderBlock {P} at (0,0) size 784x17
+        RenderText {#text} at (0,0) size 262x17
+          text run at (0,0) width 262: "Test passes if horizontal operators stretch."
+      RenderBlock (anonymous) at (0,33) size 784x57
+        RenderMathMLMath {math} at (0,8) size 60x41
+          RenderMathMLUnderOver {mover} at (0,0) size 60x41
+            RenderMathMLSpace {mspace} at (0,10) size 60x31 [bgcolor=#008000]
+            RenderMathMLOperator {mo} at (22,1) size 16x6
+              RenderBlock (anonymous) at (0,0) size 13x19
+                RenderText {#text} at (0,-68) size 13x160
+                  text run at (0,-68) width 13: "^"
+        RenderText {#text} at (60,34) size 4x17
+          text run at (60,34) width 4: " "
+        RenderMathMLMath {math} at (64,18) size 60x40
+          RenderMathMLUnderOver {munder} at (0,0) size 60x40
+            RenderMathMLSpace {mspace} at (0,0) size 60x30 [bgcolor=#008000]
+            RenderMathMLOperator {mo} at (24,33) size 12x5
+              RenderBlock (anonymous) at (0,0) size 8x4
+                RenderText {#text} at (0,-86) size 8x160
+                  text run at (0,-86) width 8: "_"
+        RenderText {#text} at (124,34) size 4x17
+          text run at (124,34) width 4: " "
+        RenderMathMLMath {math} at (128,10) size 60x39
+          RenderMathMLUnderOver {mover} at (0,0) size 60x39
+            RenderMathMLSpace {mspace} at (0,8) size 60x31 [bgcolor=#008000]
+            RenderMathMLOperator {mo} at (23,1) size 14x8
+              RenderBlock (anonymous) at (0,0) size 13x9
+                RenderText {#text} at (0,-78) size 13x160
+                  text run at (0,-78) width 13: "~"
+        RenderText {#text} at (188,34) size 4x17
+          text run at (188,34) width 4: " "
+        RenderMathMLMath {math} at (192,0) size 60x49
+          RenderMathMLUnderOver {mover} at (0,0) size 60x49
+            RenderMathMLSpace {mspace} at (0,18) size 60x31 [bgcolor=#008000]
+            RenderMathMLOperator {mo} at (24,1) size 12x18
+              RenderBlock (anonymous) at (0,0) size 12x16
+                RenderText {#text} at (0,-71) size 12x160
+                  text run at (0,-71) width 12: "\x{AF}"
+        RenderText {#text} at (252,34) size 4x17
+          text run at (252,34) width 4: " "
+        RenderMathMLMath {math} at (256,12) size 60x37
+          RenderMathMLUnderOver {mover} at (0,0) size 60x37
+            RenderMathMLSpace {mspace} at (0,6) size 60x31 [bgcolor=#008000]
+            RenderMathMLOperator {mo} at (24,1) size 12x6
+              RenderBlock (anonymous) at (0,0) size 12x18
+                RenderText {#text} at (0,-69) size 12x160
+                  text run at (0,-69) width 12: "\x{2C6}"
+        RenderText {#text} at (316,34) size 4x17
+          text run at (316,34) width 4: " "
+        RenderMathMLMath {math} at (320,12) size 60x37
+          RenderMathMLUnderOver {mover} at (0,0) size 60x37
+            RenderMathMLSpace {mspace} at (0,6) size 60x31 [bgcolor=#008000]
+            RenderMathMLOperator {mo} at (24,1) size 12x6
+              RenderBlock (anonymous) at (0,0) size 12x18
+                RenderText {#text} at (0,-69) size 12x160
+                  text run at (0,-69) width 12: "\x{2C7}"
+        RenderText {#text} at (0,0) size 0x0
Property changes on: trunk/LayoutTests/platform/gtk/mathml/presentation/bug159513-expected.txt
___________________________________________________________________

Added: svn:eol-style

+LF \ No newline at end of property

Modified: trunk/LayoutTests/platform/ios-simulator/TestExpectations (203713 => 203714)


--- trunk/LayoutTests/platform/ios-simulator/TestExpectations	2016-07-26 05:46:53 UTC (rev 203713)
+++ trunk/LayoutTests/platform/ios-simulator/TestExpectations	2016-07-26 07:46:58 UTC (rev 203714)
@@ -671,6 +671,7 @@
 mathml/opentype/fraction-line.html [ Skip ]
 mathml/presentation/fractions-linethickness.html [ Skip ]
 mathml/opentype/large-operators-italic-correction.html [ Skip ]
+mathml/presentation/bug159513.html [ Skip ]
 
 # These reftests require a font with Mathematical Alphanumeric Symbols.
 mathml/presentation/attributes-mathvariant.html [ Skip ]

Modified: trunk/LayoutTests/platform/mac/TestExpectations (203713 => 203714)


--- trunk/LayoutTests/platform/mac/TestExpectations	2016-07-26 05:46:53 UTC (rev 203713)
+++ trunk/LayoutTests/platform/mac/TestExpectations	2016-07-26 07:46:58 UTC (rev 203714)
@@ -804,6 +804,7 @@
 mathml/opentype/fraction-line.html [ Skip ]
 mathml/presentation/fractions-linethickness.html [ Skip ]
 mathml/opentype/large-operators-italic-correction.html [ Skip ]
+mathml/presentation/bug159513.html [ Skip ]
 
 # These tests use key navigation to test MathML links but do not seem to work on Mac.
 webkit.org/b/159662 mathml/presentation/href-enter.html [ Skip ]

Modified: trunk/Source/WebCore/ChangeLog (203713 => 203714)


--- trunk/Source/WebCore/ChangeLog	2016-07-26 05:46:53 UTC (rev 203713)
+++ trunk/Source/WebCore/ChangeLog	2016-07-26 07:46:58 UTC (rev 203714)
@@ -1,3 +1,31 @@
+2016-07-25  Frederic Wang  <[email protected]>
+
+        MathOperator: Add a mapping from combining to non-combining equivalents
+        https://bugs.webkit.org/show_bug.cgi?id=159513
+
+        Reviewed by Darin Adler.
+
+        Many math fonts provide stretch variants and assemblies for combining characters but not for
+        their non-combining equivalent. In the MathML recommendation, it is suggested to use
+        non-combining charaters, so we allow the operator stretching code to look for constructions
+        associated to these non-combining characters in order to still be able to stretch the
+        combining ones.
+
+        Test: mathml/presentation/bug159513.html
+
+        * rendering/mathml/MathOperator.cpp:
+        (WebCore::MathOperator::getGlyph): New function extending getBaseGlyph to retrieve the glyph
+        data for an arbitrary character.
+        (WebCore::MathOperator::getMathVariantsWithFallback): This helper function calls
+        getMathVariants for the base glyph. If no constructions are available, it calls
+        getMathVariants for the glyph associated to equivalent fallback characters as listed in the
+        small characterFallback table.
+        (WebCore::MathOperator::calculateStretchyData): Call getMathVariantsWithFallback instead of
+        getMathVariants. Note that we do not need to do that for calculateDisplayStyleLargeOperator
+        as we do not use fallback for large operators.
+        * rendering/mathml/MathOperator.h:
+        (WebCore::MathOperator::getBaseGlyph): Use getGlyph to implement this function.
+
 2016-07-25  Chris Dumez  <[email protected]>
 
         Second parameter to Range.setStart() / setEnd() should be mandatory

Modified: trunk/Source/WebCore/rendering/mathml/MathOperator.cpp (203713 => 203714)


--- trunk/Source/WebCore/rendering/mathml/MathOperator.cpp	2016-07-26 05:46:53 UTC (rev 203713)
+++ trunk/Source/WebCore/rendering/mathml/MathOperator.cpp	2016-07-26 07:46:58 UTC (rev 203714)
@@ -121,10 +121,10 @@
     return m_operatorType == Type::VerticalOperator ? m_ascent + m_descent : m_width;
 }
 
-bool MathOperator::getBaseGlyph(const RenderStyle& style, GlyphData& baseGlyph) const
+bool MathOperator::getGlyph(const RenderStyle& style, UChar character, GlyphData& glyph) const
 {
-    baseGlyph = style.fontCascade().glyphDataForCharacter(m_baseCharacter, !style.isLeftToRightDirection());
-    return baseGlyph.font && baseGlyph.font == &style.fontCascade().primaryFont();
+    glyph = style.fontCascade().glyphDataForCharacter(character, !style.isLeftToRightDirection());
+    return glyph.font && glyph.font == &style.fontCascade().primaryFont();
 }
 
 void MathOperator::setSizeVariant(const GlyphData& sizeVariant)
@@ -167,6 +167,47 @@
     }
 }
 
+// The MathML specification recommends avoiding combining characters.
+// See https://www.w3.org/TR/MathML/chapter7.html#chars.comb-chars
+// However, many math fonts do not provide constructions for the non-combining equivalent.
+const unsigned maxFallbackPerCharacter = 3;
+static const UChar characterFallback[][maxFallbackPerCharacter] = {
+    { 0x005E, 0x0302, 0 }, // CIRCUMFLEX ACCENT
+    { 0x005F, 0x0332, 0 }, // LOW LINE
+    { 0x007E, 0x0303, 0 }, // TILDE
+    { 0x00AF, 0x0304, 0x0305 }, // MACRON
+    { 0x02C6, 0x0302, 0 }, // MODIFIER LETTER CIRCUMFLEX ACCENT
+    { 0x02C7, 0x030C, 0 } // CARON
+};
+const unsigned characterFallbackSize = WTF_ARRAY_LENGTH(characterFallback);
+
+void MathOperator::getMathVariantsWithFallback(const RenderStyle& style, bool isVertical, Vector<Glyph>& sizeVariants, Vector<OpenTypeMathData::AssemblyPart>& assemblyParts)
+{
+    // In general, we first try and find contruction for the base glyph.
+    GlyphData baseGlyph;
+    if (!getBaseGlyph(style, baseGlyph) || !baseGlyph.font->mathData())
+        return;
+    baseGlyph.font->mathData()->getMathVariants(baseGlyph.glyph, isVertical, sizeVariants, assemblyParts);
+    if (!sizeVariants.isEmpty() || !assemblyParts.isEmpty())
+        return;
+
+    // Otherwise, we try and find fallback constructions using similar characters.
+    for (unsigned i = 0; i < characterFallbackSize; i++) {
+        unsigned j = 0;
+        if (characterFallback[i][j] == m_baseCharacter) {
+            for (j++; j < maxFallbackPerCharacter && characterFallback[i][j]; j++) {
+                GlyphData glyphData;
+                if (!getGlyph(style, characterFallback[i][j], glyphData))
+                    continue;
+                glyphData.font->mathData()->getMathVariants(glyphData.glyph, isVertical, sizeVariants, assemblyParts);
+                if (!sizeVariants.isEmpty() || !assemblyParts.isEmpty())
+                    return;
+            }
+            break;
+        }
+    }
+}
+
 void MathOperator::calculateDisplayStyleLargeOperator(const RenderStyle& style)
 {
     ASSERT(m_operatorType == Type::DisplayOperator);
@@ -316,7 +357,7 @@
     if (baseGlyph.font->mathData()) {
         Vector<Glyph> sizeVariants;
         Vector<OpenTypeMathData::AssemblyPart> assemblyParts;
-        baseGlyph.font->mathData()->getMathVariants(baseGlyph.glyph, isVertical, sizeVariants, assemblyParts);
+        getMathVariantsWithFallback(style, isVertical, sizeVariants, assemblyParts);
         // We verify the size variants.
         for (auto& sizeVariant : sizeVariants) {
             GlyphData glyphData(sizeVariant, baseGlyph.font);

Modified: trunk/Source/WebCore/rendering/mathml/MathOperator.h (203713 => 203714)


--- trunk/Source/WebCore/rendering/mathml/MathOperator.h	2016-07-26 05:46:53 UTC (rev 203713)
+++ trunk/Source/WebCore/rendering/mathml/MathOperator.h	2016-07-26 07:46:58 UTC (rev 203714)
@@ -72,9 +72,11 @@
     };
 
     LayoutUnit stretchSize() const;
-    bool getBaseGlyph(const RenderStyle&, GlyphData&) const;
+    bool getGlyph(const RenderStyle&, UChar character, GlyphData&) const;
+    bool getBaseGlyph(const RenderStyle& style, GlyphData& baseGlyph) const { return getGlyph(style, m_baseCharacter, baseGlyph); }
     void setSizeVariant(const GlyphData&);
     void setGlyphAssembly(const GlyphAssemblyData&);
+    void getMathVariantsWithFallback(const RenderStyle&, bool isVertical, Vector<Glyph>&, Vector<OpenTypeMathData::AssemblyPart>&);
     void calculateDisplayStyleLargeOperator(const RenderStyle&);
     void calculateStretchyData(const RenderStyle&, bool calculateMaxPreferredWidth, LayoutUnit targetSize = 0);
     bool calculateGlyphAssemblyFallback(const RenderStyle&, const Vector<OpenTypeMathData::AssemblyPart>&, GlyphAssemblyData&) const;
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to