Apply Character-level mirroring to stretchy operators in RTL mode.
authorfred.wang@free.fr <fred.wang@free.fr@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 5 Jun 2014 16:23:08 +0000 (16:23 +0000)
committerfred.wang@free.fr <fred.wang@free.fr@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 5 Jun 2014 16:23:08 +0000 (16:23 +0000)
https://bugs.webkit.org/show_bug.cgi?id=130839

Reviewed by Chris Fleizach.

Source/WebCore:
We add support for character-level mirroring for stretchy MathML operators in RTL mode.
Glyph-level mirroring (via the rtlm OpenType feature) will be handled in bug 130840.

Test: mathml/presentation/stretchy-rtl.html

* rendering/mathml/RenderMathMLOperator.cpp: reorganize the Unicode stretchyCharacters table to make mirroring easy.
(WebCore::RenderMathMLOperator::computePreferredLogicalWidths): pass the right boolean to glyphDataForCharacter.
(WebCore::RenderMathMLOperator::getDisplayStyleLargeOperator): ditto
(WebCore::RenderMathMLOperator::findStretchyData): ditto and change the index for the stretchyCharacters fallback.
(WebCore::RenderMathMLOperator::updateStyle): pass the right boolean to glyphDataForCharacter.
(WebCore::RenderMathMLOperator::paint): remove the FIXME comment.
(WebCore::RenderMathMLOperator::paintVerticalGlyphAssembly): switch the leading/trailing space in RTL mode.

LayoutTests:
Add some tests to verify that stretchy operators are correctly mirrored in RTL mode.

* mathml/presentation/stretchy-rtl-expected.html: Added.
* mathml/presentation/stretchy-rtl.html: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@169617 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/ChangeLog
LayoutTests/mathml/presentation/stretchy-rtl-expected.html [new file with mode: 0644]
LayoutTests/mathml/presentation/stretchy-rtl.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/rendering/mathml/RenderMathMLOperator.cpp

index 770736e..9acd3c5 100644 (file)
@@ -1,3 +1,15 @@
+2014-06-05  Frédéric Wang  <fred.wang@free.fr>
+
+        Apply Character-level mirroring to stretchy operators in RTL mode.
+        https://bugs.webkit.org/show_bug.cgi?id=130839
+
+        Reviewed by Chris Fleizach.
+
+        Add some tests to verify that stretchy operators are correctly mirrored in RTL mode.
+
+        * mathml/presentation/stretchy-rtl-expected.html: Added.
+        * mathml/presentation/stretchy-rtl.html: Added.
+
 2014-06-05  Zoltan Horvath  <zoltan@webkit.org>
 
         [CSS Regions][CSS Shapes] Add Shapes tests which flow through multiple regions
diff --git a/LayoutTests/mathml/presentation/stretchy-rtl-expected.html b/LayoutTests/mathml/presentation/stretchy-rtl-expected.html
new file mode 100644 (file)
index 0000000..b1334aa
--- /dev/null
@@ -0,0 +1,11 @@
+<html>
+  <head>
+    <title>stretchy rtl</title>
+    <meta charset="utf-8">
+  </head>
+  <body>
+
+    <math dir="rtl"><mo>&#x230a;</mo><mo>&#x2308;</mo><mo>{</mo><mo>[</mo><mo rspace="3em">(</mo><mspace width="1em" height="2em" depth="2em" mathbackground="red"/><mo lspace="2em">)</mo><mo>]</mo><mo>}</mo><mo>&#x2309;</mo><mo>&#x230b;</mo></math>
+
+  </body>
+</html>
diff --git a/LayoutTests/mathml/presentation/stretchy-rtl.html b/LayoutTests/mathml/presentation/stretchy-rtl.html
new file mode 100644 (file)
index 0000000..4325d65
--- /dev/null
@@ -0,0 +1,13 @@
+<html>
+  <head>
+    <title>stretchy rtl</title>
+    <meta charset="utf-8">
+  </head>
+  <body>
+
+    <!-- This tests stretchy operators in RTL mode. They should render the same as the symmetric LTR expressions. -->
+
+    <math dir="rtl"><mo>&#x230a;</mo><mo>&#x2308;</mo><mo>{</mo><mo>[</mo><mo rspace="3em">(</mo><mspace width="1em" height="2em" depth="2em" mathbackground="red"/><mo lspace="2em">)</mo><mo>]</mo><mo>}</mo><mo>&#x2309;</mo><mo>&#x230b;</mo></math>
+
+  </body>
+</html>
index 7388885..ce67c9d 100644 (file)
@@ -1,3 +1,23 @@
+2014-06-05  Frédéric Wang  <fred.wang@free.fr>
+
+        Apply Character-level mirroring to stretchy operators in RTL mode.
+        https://bugs.webkit.org/show_bug.cgi?id=130839
+
+        Reviewed by Chris Fleizach.
+
+        We add support for character-level mirroring for stretchy MathML operators in RTL mode.
+        Glyph-level mirroring (via the rtlm OpenType feature) will be handled in bug 130840.
+
+        Test: mathml/presentation/stretchy-rtl.html
+
+        * rendering/mathml/RenderMathMLOperator.cpp: reorganize the Unicode stretchyCharacters table to make mirroring easy.
+        (WebCore::RenderMathMLOperator::computePreferredLogicalWidths): pass the right boolean to glyphDataForCharacter.
+        (WebCore::RenderMathMLOperator::getDisplayStyleLargeOperator): ditto
+        (WebCore::RenderMathMLOperator::findStretchyData): ditto and change the index for the stretchyCharacters fallback.
+        (WebCore::RenderMathMLOperator::updateStyle): pass the right boolean to glyphDataForCharacter.
+        (WebCore::RenderMathMLOperator::paint): remove the FIXME comment.
+        (WebCore::RenderMathMLOperator::paintVerticalGlyphAssembly): switch the leading/trailing space in RTL mode.
+
 2014-06-05  Zalan Bujtas  <zalan@apple.com>
 
         Subpixel rendering: Buttons in default media controls shift vertically when controls fade in or out.
index 48704a3..34788b0 100644 (file)
@@ -55,20 +55,22 @@ struct StretchyCharacter {
     UChar bottomChar;
     UChar middleChar;
 };
+// The first leftRightPairsCount pairs correspond to left/right fences that can easily be mirrored in RTL.
+static const short leftRightPairsCount = 5;
 static const StretchyCharacter stretchyCharacters[14] = {
     { 0x28  , 0x239b, 0x239c, 0x239d, 0x0    }, // left parenthesis
     { 0x29  , 0x239e, 0x239f, 0x23a0, 0x0    }, // right parenthesis
     { 0x5b  , 0x23a1, 0x23a2, 0x23a3, 0x0    }, // left square bracket
-    { 0x2308, 0x23a1, 0x23a2, 0x23a2, 0x0    }, // left ceiling
-    { 0x230a, 0x23a2, 0x23a2, 0x23a3, 0x0    }, // left floor
     { 0x5d  , 0x23a4, 0x23a5, 0x23a6, 0x0    }, // right square bracket
+    { 0x7b  , 0x23a7, 0x23aa, 0x23a9, 0x23a8 }, // left curly bracket
+    { 0x7d  , 0x23ab, 0x23aa, 0x23ad, 0x23ac }, // right curly bracket
+    { 0x2308, 0x23a1, 0x23a2, 0x23a2, 0x0    }, // left ceiling
     { 0x2309, 0x23a4, 0x23a5, 0x23a5, 0x0    }, // right ceiling
+    { 0x230a, 0x23a2, 0x23a2, 0x23a3, 0x0    }, // left floor
     { 0x230b, 0x23a5, 0x23a5, 0x23a6, 0x0    }, // right floor
-    { 0x7b  , 0x23a7, 0x23aa, 0x23a9, 0x23a8 }, // left curly bracket
     { 0x7c  , 0x7c,   0x7c,   0x7c,   0x0    }, // vertical bar
     { 0x2016, 0x2016, 0x2016, 0x2016, 0x0    }, // double vertical line
     { 0x2225, 0x2225, 0x2225, 0x2225, 0x0    }, // parallel to
-    { 0x7d  , 0x23ab, 0x23aa, 0x23ad, 0x23ac }, // right curly bracket
     { 0x222b, 0x2320, 0x23ae, 0x2321, 0x0    } // integral sign
 };
 
@@ -1339,7 +1341,7 @@ void RenderMathMLOperator::computePreferredLogicalWidths()
         return;
     }
 
-    GlyphData data = style().font().glyphDataForCharacter(m_operator, false);
+    GlyphData data = style().font().glyphDataForCharacter(m_operator, !style().isLeftToRightDirection());
     float maximumGlyphWidth = advanceForGlyph(data);
     if (!m_isVertical) {
         if (maximumGlyphWidth < stretchSize())
@@ -1514,7 +1516,7 @@ RenderMathMLOperator::StretchyData RenderMathMLOperator::getDisplayStyleLargeOpe
     ASSERT(m_isVertical && isLargeOperatorInDisplayStyle());
 
     const auto& primaryFontData = style().font().primaryFont();
-    GlyphData baseGlyph = style().font().glyphDataForCharacter(character, false);
+    GlyphData baseGlyph = style().font().glyphDataForCharacter(character, !style().isLeftToRightDirection());
     if (!primaryFontData || !primaryFontData->mathData() || baseGlyph.fontData != primaryFontData)
         return data;
 
@@ -1546,7 +1548,7 @@ RenderMathMLOperator::StretchyData RenderMathMLOperator::findStretchyData(UChar
     StretchyData assemblyData;
 
     const auto& primaryFontData = style().font().primaryFont();
-    GlyphData baseGlyph = style().font().glyphDataForCharacter(character, false);
+    GlyphData baseGlyph = style().font().glyphDataForCharacter(character, !style().isLeftToRightDirection());
     
     if (primaryFontData && primaryFontData->mathData() && baseGlyph.fontData == primaryFontData) {
         Vector<Glyph> sizeVariants;
@@ -1580,6 +1582,10 @@ RenderMathMLOperator::StretchyData RenderMathMLOperator::findStretchyData(UChar
         for (unsigned index = 0; index < maxIndex; ++index) {
             if (stretchyCharacters[index].character == character) {
                 stretchyCharacter = &stretchyCharacters[index];
+                if (!style().isLeftToRightDirection() && index < leftRightPairsCount * 2) {
+                    // If we are in right-to-left direction we select the mirrored form by adding -1 or +1 according to the parity of index.
+                    index += index % 2 ? -1 : 1;
+                }
                 break;
             }
         }
@@ -1653,7 +1659,7 @@ void RenderMathMLOperator::updateStyle()
         m_stretchyData = getDisplayStyleLargeOperator(m_operator);
     else {
         // We do not stretch if the base glyph is large enough.
-        GlyphData baseGlyph = style().font().glyphDataForCharacter(m_operator, false);
+        GlyphData baseGlyph = style().font().glyphDataForCharacter(m_operator, !style().isLeftToRightDirection());
         float baseSize = m_isVertical ? heightForGlyph(baseGlyph) : advanceForGlyph(baseGlyph);
         if (stretchSize() <= baseSize)
             return;
@@ -1861,8 +1867,6 @@ void RenderMathMLOperator::paint(PaintInfo& info, const LayoutPoint& paintOffset
     if (info.context->paintingDisabled() || info.phase != PaintPhaseForeground || style().visibility() != VISIBLE || m_stretchyData.mode() == DrawNormal)
         return;
 
-    // FIXME: This painting should work in RTL mode too (https://bugs.webkit.org/show_bug.cgi?id=123018).
-
     GraphicsContextStateSaver stateSaver(*info.context);
     info.context->setFillColor(style().visitedDependentColor(CSSPropertyColor), style().colorSpace());
 
@@ -1892,7 +1896,7 @@ void RenderMathMLOperator::paintVerticalGlyphAssembly(PaintInfo& info, const Lay
 
     // 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.move(style().isLeftToRightDirection() ? m_leadingSpace : m_trailingSpace, 0);
     operatorTopLeft = ceiledIntPoint(operatorTopLeft);
     FloatRect topGlyphBounds = boundsForGlyph(m_stretchyData.top());
     LayoutPoint topGlyphOrigin(operatorTopLeft.x(), operatorTopLeft.y() - topGlyphBounds.y());