[Libreoffice-commits] core.git: starmath/qa starmath/source

Takeshi Abe tabe at fixedpoint.jp
Tue Nov 29 01:04:32 UTC 2016


 starmath/qa/extras/data/tdf103430.mml |   15 ++
 starmath/qa/extras/mmlimport-test.cxx |   11 +
 starmath/source/mathmlattr.cxx        |   35 +++++
 starmath/source/mathmlattr.hxx        |   27 ++++
 starmath/source/mathmlimport.cxx      |  201 +++++++++++++++++++++++++++++-----
 starmath/source/mathmlimport.hxx      |    3 
 starmath/source/node.cxx              |    5 
 7 files changed, 267 insertions(+), 30 deletions(-)

New commits:
commit 2bad9f1cd8da0cd3d8ff33e875eaf10c1fd9d0bf
Author: Takeshi Abe <tabe at fixedpoint.jp>
Date:   Sun Nov 27 02:55:15 2016 +0900

    tdf#103430 Apply mathvariant attribute to <mi> and <mo>
    
    by emulating it with SmFontNode.
    In case of <mo>, current implementation supports only the one named
    with an alphabet.
    
    Change-Id: I827a7e80f5aa94e243098a6e50eb758cf915c282
    Reviewed-on: https://gerrit.libreoffice.org/31240
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Takeshi Abe <tabe at fixedpoint.jp>

diff --git a/starmath/qa/extras/data/tdf103430.mml b/starmath/qa/extras/data/tdf103430.mml
new file mode 100644
index 0000000..92fba05
--- /dev/null
+++ b/starmath/qa/extras/data/tdf103430.mml
@@ -0,0 +1,15 @@
+<math xmlns="http://www.w3.org/1998/Math/MathML">
+  <mfrac>
+   <mrow>
+     <msup>
+      <mo form="prefix" rspace="0">d</mo>
+      <mn>2</mn>
+     </msup>
+    <mi mathvariant="normal" mathcolor="blue">y</mi>
+   </mrow>
+   <mrow>
+     <mo fontstyle="italic" fontweight="bold" mathvariant="normal" form="prefix" rspace="0">d</mo>
+     <mi fontfamily="serif" mathvariant="sans-serif-bold-italic" mathcolor="red">x</mi>
+   </mrow>
+  </mfrac>
+</math>
diff --git a/starmath/qa/extras/mmlimport-test.cxx b/starmath/qa/extras/mmlimport-test.cxx
index 3db697f..01ae2ff 100644
--- a/starmath/qa/extras/mmlimport-test.cxx
+++ b/starmath/qa/extras/mmlimport-test.cxx
@@ -34,6 +34,7 @@ public:
     void testMaction();
     void testMspace();
     void testtdf99556();
+    void testTdf103430();
     void testTdf103500();
 
     CPPUNIT_TEST_SUITE(Test);
@@ -42,6 +43,7 @@ public:
     CPPUNIT_TEST(testMaction);
     CPPUNIT_TEST(testMspace);
     CPPUNIT_TEST(testtdf99556);
+    CPPUNIT_TEST(testTdf103430);
     CPPUNIT_TEST(testTdf103500);
     CPPUNIT_TEST_SUITE_END();
 
@@ -122,10 +124,17 @@ void Test::testtdf99556()
     CPPUNIT_ASSERT_EQUAL_MESSAGE("loaded text", sExpected, mxDocShell->GetText());
 }
 
+void Test::testTdf103430()
+{
+    loadURL(m_directories.getURLFromSrc("starmath/qa/extras/data/tdf103430.mml"));
+    CPPUNIT_ASSERT_EQUAL(OUString("{{nitalic d}^2 {nitalic {color blue y}}} over {{nitalic d} {font sans {bold {italic {color red x}}}}}"),
+                         mxDocShell->GetText());
+}
+
 void Test::testTdf103500()
 {
     loadURL(m_directories.getURLFromSrc("starmath/qa/extras/data/tdf103500.mml"));
-    CPPUNIT_ASSERT_EQUAL(OUString("{{ int csub a csup b {1 over x ` d x}} = {intd csub a csup b {1 over y ` d y}}}"),
+    CPPUNIT_ASSERT_EQUAL(OUString("{{ int csub a csup b {1 over x ` {nitalic d} x}} = {intd csub a csup b {1 over y ` {nitalic d} y}}}"),
                          mxDocShell->GetText());
 }
 
diff --git a/starmath/source/mathmlattr.cxx b/starmath/source/mathmlattr.cxx
index 262609f..0c39c3e 100644
--- a/starmath/source/mathmlattr.cxx
+++ b/starmath/source/mathmlattr.cxx
@@ -10,6 +10,7 @@
 #include "mathmlattr.hxx"
 
 #include <cassert>
+#include <unordered_map>
 
 namespace {
 
@@ -144,4 +145,38 @@ sal_Int32 ParseMathMLAttributeLengthValue(const OUString &rStr, MathMLAttributeL
     return nIdx;
 }
 
+
+bool GetMathMLMathvariantValue(const OUString &rStr, MathMLMathvariantValue *pV)
+{
+    static const std::unordered_map<OUString, MathMLMathvariantValue, OUStringHash> aMap{
+        {"normal", MathMLMathvariantValue::Normal},
+        {"bold", MathMLMathvariantValue::Bold},
+        {"italic", MathMLMathvariantValue::Italic},
+        {"bold-italic", MathMLMathvariantValue::BoldItalic},
+        {"double-struck", MathMLMathvariantValue::DoubleStruck},
+        {"bold-fraktur", MathMLMathvariantValue::BoldFraktur},
+        {"script", MathMLMathvariantValue::Script},
+        {"bold-script", MathMLMathvariantValue::BoldScript},
+        {"fraktur", MathMLMathvariantValue::Fraktur},
+        {"sans-serif", MathMLMathvariantValue::SansSerif},
+        {"bold-sans-serif", MathMLMathvariantValue::BoldSansSerif},
+        {"sans-serif-italic", MathMLMathvariantValue::SansSerifItalic},
+        {"sans-serif-bold-italic", MathMLMathvariantValue::SansSerifBoldItalic},
+        {"monospace", MathMLMathvariantValue::Monospace},
+        {"initial", MathMLMathvariantValue::Initial},
+        {"tailed", MathMLMathvariantValue::Tailed},
+        {"looped", MathMLMathvariantValue::Looped},
+        {"stretched", MathMLMathvariantValue::Stretched}
+    };
+
+    assert(pV);
+    auto it = aMap.find(rStr);
+    if (it != aMap.end())
+    {
+        *pV = it->second;
+        return true;
+    }
+    return false;
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/starmath/source/mathmlattr.hxx b/starmath/source/mathmlattr.hxx
index 75dddb0..f540254 100644
--- a/starmath/source/mathmlattr.hxx
+++ b/starmath/source/mathmlattr.hxx
@@ -47,6 +47,33 @@ struct MathMLAttributeLengthValue
 
 sal_Int32 ParseMathMLAttributeLengthValue(const OUString &rStr, MathMLAttributeLengthValue *pV);
 
+
+// MathML 3: 3.2.2 Mathematics style attributes common to token elements
+// <https://www.w3.org/TR/MathML3/chapter3.html#presm.commatt>
+
+enum class MathMLMathvariantValue {
+    Normal,
+    Bold,
+    Italic,
+    BoldItalic,
+    DoubleStruck,
+    BoldFraktur,
+    Script,
+    BoldScript,
+    Fraktur,
+    SansSerif,
+    BoldSansSerif,
+    SansSerifItalic,
+    SansSerifBoldItalic,
+    Monospace,
+    Initial,
+    Tailed,
+    Looped,
+    Stretched
+};
+
+bool GetMathMLMathvariantValue(const OUString &rStr, MathMLMathvariantValue *pV);
+
 #endif
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/starmath/source/mathmlimport.cxx b/starmath/source/mathmlimport.cxx
index dc0d032..4761508 100644
--- a/starmath/source/mathmlimport.cxx
+++ b/starmath/source/mathmlimport.cxx
@@ -43,6 +43,7 @@ one go*/
 #include <comphelper/servicehelper.hxx>
 #include <comphelper/string.hxx>
 #include <o3tl/make_unique.hxx>
+#include <rtl/character.hxx>
 #include <rtl/math.hxx>
 #include <sfx2/frame.hxx>
 #include <sfx2/docfile.hxx>
@@ -573,7 +574,6 @@ struct SmXMLContext_Helper
     sal_Int8 nIsBold;
     sal_Int8 nIsItalic;
     double nFontSize;
-    bool bFontNodeNeeded;
     OUString sFontFamily;
     OUString sColor;
 
@@ -583,22 +583,28 @@ struct SmXMLContext_Helper
         : nIsBold( -1 )
         , nIsItalic( -1 )
         , nFontSize( 0.0 )
-        , bFontNodeNeeded( false )
         , rContext( rImport )
         {}
 
+    bool IsFontNodeNeeded() const;
     void RetrieveAttrs(const uno::Reference< xml::sax::XAttributeList > &xAttrList );
     void ApplyAttrs();
 };
 
+bool SmXMLContext_Helper::IsFontNodeNeeded() const
+{
+    return nIsBold != -1 ||
+        nIsItalic != -1 ||
+        nFontSize != 0.0 ||
+        !sFontFamily.isEmpty() ||
+        !sColor.isEmpty();
+}
+
 void SmXMLContext_Helper::RetrieveAttrs(const uno::Reference<
     xml::sax::XAttributeList > & xAttrList )
 {
-    sal_Int8 nOldIsBold=nIsBold;
-    sal_Int8 nOldIsItalic=nIsItalic;
-    double nOldFontSize=nFontSize;
+    bool bMvFound = false;
     sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
-    OUString sOldFontFamily = sFontFamily;
     for (sal_Int16 i=0;i<nAttrCount;i++)
     {
         OUString sAttrName = xAttrList->getNameByIndex(i);
@@ -640,24 +646,30 @@ void SmXMLContext_Helper::RetrieveAttrs(const uno::Reference<
             case XML_TOK_MATHCOLOR:
                 sColor = sValue;
                 break;
+            case XML_TOK_MATHVARIANT:
+                bMvFound = true;
+                break;
             default:
                 break;
         }
     }
 
-    if ((nOldIsBold!=nIsBold) || (nOldIsItalic!=nIsItalic) ||
-        (nOldFontSize!=nFontSize) || (sOldFontFamily!=sFontFamily)
-        || !sColor.isEmpty())
-        bFontNodeNeeded=true;
-    else
-        bFontNodeNeeded=false;
+    if (bMvFound)
+    {
+        // Ignore deprecated attributes fontfamily, fontweight, and fontstyle
+        // in favor of mathvariant, as specified in
+        // <https://www.w3.org/TR/MathML3/chapter3.html#presm.deprecatt>.
+        sFontFamily.clear();
+        nIsBold = -1;
+        nIsItalic = -1;
+    }
 }
 
 void SmXMLContext_Helper::ApplyAttrs()
 {
     SmNodeStack &rNodeStack = rContext.GetSmImport().GetNodeStack();
 
-    if (bFontNodeNeeded)
+    if (IsFontNodeNeeded())
     {
         SmToken aToken;
         aToken.cMathChar = '\0';
@@ -741,6 +753,131 @@ void SmXMLContext_Helper::ApplyAttrs()
 }
 
 
+class SmXMLTokenAttrHelper
+{
+    SmXMLImportContext& mrContext;
+    MathMLMathvariantValue meMv;
+    bool mbMvFound;
+
+public:
+    SmXMLTokenAttrHelper(SmXMLImportContext& rContext)
+        : mrContext(rContext)
+        , meMv(MathMLMathvariantValue::Normal)
+        , mbMvFound(false)
+    {}
+
+    void RetrieveAttrs(const uno::Reference<xml::sax::XAttributeList>& xAttrList);
+    void ApplyAttrs(MathMLMathvariantValue eDefaultMv);
+};
+
+void SmXMLTokenAttrHelper::RetrieveAttrs(const uno::Reference<xml::sax::XAttributeList>& xAttrList)
+{
+    if (!xAttrList.is())
+        return;
+    sal_Int16 nAttrCount = xAttrList->getLength();
+    for (sal_Int16 i=0;i<nAttrCount;i++)
+    {
+        OUString sAttrName = xAttrList->getNameByIndex(i);
+        OUString aLocalName;
+        sal_uInt16 nPrefix = mrContext.GetSmImport().GetNamespaceMap().
+            GetKeyByAttrName(sAttrName, &aLocalName);
+        OUString sValue = xAttrList->getValueByIndex(i);
+        const SvXMLTokenMap &rAttrTokenMap =
+            mrContext.GetSmImport().GetPresLayoutAttrTokenMap();
+        switch(rAttrTokenMap.Get(nPrefix, aLocalName))
+        {
+            case XML_TOK_MATHVARIANT:
+                if (!GetMathMLMathvariantValue(sValue, &meMv))
+                    SAL_WARN("starmath", "failed to recognize mathvariant: " << sValue);
+                mbMvFound = true;
+                break;
+            default:
+                break;
+        }
+    }
+}
+
+void SmXMLTokenAttrHelper::ApplyAttrs(MathMLMathvariantValue eDefaultMv)
+{
+    assert( eDefaultMv == MathMLMathvariantValue::Normal ||
+            eDefaultMv == MathMLMathvariantValue::Italic );
+
+    std::vector<SmTokenType> vVariant;
+    MathMLMathvariantValue eMv = mbMvFound ? meMv : eDefaultMv;
+    switch(eMv)
+    {
+        case MathMLMathvariantValue::Normal:
+            vVariant.push_back(TNITALIC);
+            break;
+        case MathMLMathvariantValue::Bold:
+            vVariant.push_back(TBOLD);
+            break;
+        case MathMLMathvariantValue::Italic:
+            // nothing to do
+            break;
+        case MathMLMathvariantValue::BoldItalic:
+            vVariant.push_back(TITALIC);
+            vVariant.push_back(TBOLD);
+            break;
+        case MathMLMathvariantValue::DoubleStruck:
+            // TODO
+            break;
+        case MathMLMathvariantValue::BoldFraktur:
+            // TODO: Fraktur
+            vVariant.push_back(TBOLD);
+            break;
+        case MathMLMathvariantValue::Script:
+            // TODO
+            break;
+        case MathMLMathvariantValue::BoldScript:
+            // TODO: Script
+            vVariant.push_back(TBOLD);
+            break;
+        case MathMLMathvariantValue::Fraktur:
+            // TODO
+            break;
+        case MathMLMathvariantValue::SansSerif:
+            vVariant.push_back(TSANS);
+            break;
+        case MathMLMathvariantValue::BoldSansSerif:
+            vVariant.push_back(TSANS);
+            vVariant.push_back(TBOLD);
+            break;
+        case MathMLMathvariantValue::SansSerifItalic:
+            vVariant.push_back(TITALIC);
+            vVariant.push_back(TSANS);
+            break;
+        case MathMLMathvariantValue::SansSerifBoldItalic:
+            vVariant.push_back(TITALIC);
+            vVariant.push_back(TBOLD);
+            vVariant.push_back(TSANS);
+            break;
+        case MathMLMathvariantValue::Monospace:
+            vVariant.push_back(TFIXED);
+            break;
+        case MathMLMathvariantValue::Initial:
+        case MathMLMathvariantValue::Tailed:
+        case MathMLMathvariantValue::Looped:
+        case MathMLMathvariantValue::Stretched:
+            // TODO
+            break;
+    }
+    if (vVariant.empty())
+        return;
+    SmNodeStack &rNodeStack = mrContext.GetSmImport().GetNodeStack();
+    for (auto eType : vVariant)
+    {
+        SmToken aToken;
+        aToken.eType = eType;
+        aToken.cMathChar = '\0';
+        aToken.nLevel = 5;
+        std::unique_ptr<SmFontNode> pFontNode(new SmFontNode(aToken));
+        pFontNode->SetSubNodes(nullptr, popOrZero(rNodeStack));
+        rNodeStack.push_front(std::move(pFontNode));
+    }
+}
+
+
 class SmXMLDocContext_Impl : public SmXMLImportContext
 {
 public:
@@ -1198,14 +1335,16 @@ void SmXMLStringContext_Impl::EndElement()
 
 class SmXMLIdentifierContext_Impl : public SmXMLImportContext
 {
-protected:
+    SmXMLTokenAttrHelper maTokenAttrHelper;
     SmXMLContext_Helper aStyleHelper;
     SmToken aToken;
 
 public:
     SmXMLIdentifierContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
         const OUString& rLName)
-        : SmXMLImportContext(rImport,nPrefix,rLName),aStyleHelper(*this)
+        : SmXMLImportContext(rImport,nPrefix,rLName)
+        , maTokenAttrHelper(*this)
+        , aStyleHelper(*this)
     {
         aToken.cMathChar = '\0';
         aToken.nLevel = 5;
@@ -1215,6 +1354,7 @@ public:
     void TCharacters(const OUString &rChars) override;
     void StartElement(const uno::Reference< xml::sax::XAttributeList > & xAttrList ) override
     {
+        maTokenAttrHelper.RetrieveAttrs(xAttrList);
         aStyleHelper.RetrieveAttrs(xAttrList);
     };
     void EndElement() override;
@@ -1234,23 +1374,20 @@ void SmXMLIdentifierContext_Impl::EndElement()
     }
     else
         pNode.reset(new SmTextNode(aToken,FNT_VARIABLE));
-    if (aStyleHelper.bFontNodeNeeded && aStyleHelper.nIsItalic != -1)
+    if (aStyleHelper.nIsItalic != -1)
     {
         if (aStyleHelper.nIsItalic)
             pNode->GetFont().SetItalic(ITALIC_NORMAL);
         else
             pNode->GetFont().SetItalic(ITALIC_NONE);
+        aStyleHelper.nIsItalic = -1;
     }
-
-    if ((-1!=aStyleHelper.nIsBold) || (0.0!=aStyleHelper.nFontSize) ||
-        (!aStyleHelper.sFontFamily.isEmpty()) ||
-        !aStyleHelper.sColor.isEmpty())
-        aStyleHelper.bFontNodeNeeded=true;
-    else
-        aStyleHelper.bFontNodeNeeded=false;
-    if (aStyleHelper.bFontNodeNeeded)
-        aStyleHelper.ApplyAttrs();
     GetSmImport().GetNodeStack().push_front(std::move(pNode));
+    aStyleHelper.ApplyAttrs();
+
+    maTokenAttrHelper.ApplyAttrs( (aToken.aText.getLength() == 1)
+                                  ? MathMLMathvariantValue::Italic
+                                  : MathMLMathvariantValue::Normal );
 }
 
 void SmXMLIdentifierContext_Impl::TCharacters(const OUString &rChars)
@@ -1261,15 +1398,16 @@ void SmXMLIdentifierContext_Impl::TCharacters(const OUString &rChars)
 
 class SmXMLOperatorContext_Impl : public SmXMLImportContext
 {
+    SmXMLTokenAttrHelper maTokenAttrHelper;
     bool bIsStretchy;
-
-protected:
     SmToken aToken;
 
 public:
     SmXMLOperatorContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
         const OUString& rLName)
-        : SmXMLImportContext(rImport,nPrefix,rLName), bIsStretchy(false)
+        : SmXMLImportContext(rImport,nPrefix,rLName)
+        , maTokenAttrHelper(*this)
+        , bIsStretchy(false)
     {
         aToken.eType = TSPECIAL;
         aToken.nLevel = 5;
@@ -1294,12 +1432,18 @@ void SmXMLOperatorContext_Impl::EndElement()
     if (bIsStretchy)
         pNode->SetScaleMode(SCALE_HEIGHT);
     GetSmImport().GetNodeStack().push_front(std::move(pNode));
+
+    // TODO: apply to non-alphabetic characters too
+    if (rtl::isAsciiAlpha(aToken.cMathChar))
+        maTokenAttrHelper.ApplyAttrs(MathMLMathvariantValue::Normal);
 }
 
 
 void SmXMLOperatorContext_Impl::StartElement(const uno::Reference<
     xml::sax::XAttributeList > & xAttrList )
 {
+    maTokenAttrHelper.RetrieveAttrs(xAttrList);
+
     sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
     for (sal_Int16 i=0;i<nAttrCount;i++)
     {
@@ -1885,6 +2029,7 @@ static const SvXMLTokenMapEntry aPresLayoutAttrTokenMap[] =
     { XML_NAMESPACE_MATH,   XML_FONTFAMILY,      XML_TOK_FONTFAMILY    },
     { XML_NAMESPACE_MATH,   XML_COLOR,           XML_TOK_COLOR },
     { XML_NAMESPACE_MATH,   XML_MATHCOLOR,       XML_TOK_MATHCOLOR },
+    { XML_NAMESPACE_MATH,   XML_MATHVARIANT,     XML_TOK_MATHVARIANT },
     XML_TOKEN_MAP_END
 };
 
diff --git a/starmath/source/mathmlimport.hxx b/starmath/source/mathmlimport.hxx
index 626ee0b..3f8f376 100644
--- a/starmath/source/mathmlimport.hxx
+++ b/starmath/source/mathmlimport.hxx
@@ -286,7 +286,8 @@ enum SmXMLPresLayoutAttrTokenMap
     XML_TOK_FONTSIZE,
     XML_TOK_FONTFAMILY,
     XML_TOK_COLOR,
-    XML_TOK_MATHCOLOR
+    XML_TOK_MATHCOLOR,
+    XML_TOK_MATHVARIANT
 };
 
 
diff --git a/starmath/source/node.cxx b/starmath/source/node.cxx
index ca21a7e..ba7f5c1 100644
--- a/starmath/source/node.cxx
+++ b/starmath/source/node.cxx
@@ -1710,6 +1710,8 @@ void SmAttributNode::Arrange(OutputDevice &rDev, const SmFormat &rFormat)
 
 void SmFontNode::CreateTextFromNode(OUString &rText)
 {
+    rText += "{";
+
     switch (GetToken().eType)
     {
         case TBOLD:
@@ -1823,6 +1825,9 @@ void SmFontNode::CreateTextFromNode(OUString &rText)
     }
     if(GetNumSubNodes() > 1)
         GetSubNode(1)->CreateTextFromNode(rText);
+
+    rText = comphelper::string::stripEnd(rText, ' ');
+    rText += "} ";
 }
 
 void SmFontNode::Prepare(const SmFormat &rFormat, const SmDocShell &rDocShell)


More information about the Libreoffice-commits mailing list