summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTakeshi Abe <tabe@fixedpoint.jp>2016-11-27 02:55:15 +0900
committerTakeshi Abe <tabe@fixedpoint.jp>2016-11-29 01:04:08 +0000
commit2bad9f1cd8da0cd3d8ff33e875eaf10c1fd9d0bf (patch)
tree2183236d12fdf71d43cc98dfee404450c06289c9
parent9abc547ef28f3f6891030597fd304ca757b102da (diff)
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@libreoffice.org> Reviewed-by: Takeshi Abe <tabe@fixedpoint.jp>
-rw-r--r--starmath/qa/extras/data/tdf103430.mml15
-rw-r--r--starmath/qa/extras/mmlimport-test.cxx11
-rw-r--r--starmath/source/mathmlattr.cxx35
-rw-r--r--starmath/source/mathmlattr.hxx27
-rw-r--r--starmath/source/mathmlimport.cxx201
-rw-r--r--starmath/source/mathmlimport.hxx3
-rw-r--r--starmath/source/node.cxx5
7 files changed, 267 insertions, 30 deletions
diff --git a/starmath/qa/extras/data/tdf103430.mml b/starmath/qa/extras/data/tdf103430.mml
new file mode 100644
index 000000000000..92fba05dc295
--- /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 3db697f1f849..01ae2ffaaec7 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 262609f1875d..0c39c3e2862e 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 75dddb06d402..f5402546e68e 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 dc0d03212fa0..476150850a98 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 626ee0bb0fb8..3f8f376f3190 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 ca21a7ed4f42..ba7f5c1fcc33 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)