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">^</mo>
+ </mover>
+ </math>
+ <math>
+ <munder>
+ <mspace width="60px" height="30px" mathbackground="green"/>
+ <mo stretchy="true">_</mo>
+ </munder>
+ </math>
+ <math>
+ <mover>
+ <mspace width="60px" height="30px" mathbackground="green"/>
+ <mo stretchy="true">~</mo>
+ </mover>
+ </math>
+ <math>
+ <mover>
+ <mspace width="60px" height="30px" mathbackground="green"/>
+ <mo stretchy="true">¯</mo>
+ </mover>
+ </math>
+ <math>
+ <mover>
+ <mspace width="60px" height="30px" mathbackground="green"/>
+ <mo stretchy="true">ˆ</mo>
+ </mover>
+ </math>
+ <math>
+ <mover>
+ <mspace width="60px" height="30px" mathbackground="green"/>
+ <mo stretchy="true">ˇ</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;