[Libreoffice-commits] core.git: include/xmloff starmath/inc starmath/Library_sm.mk starmath/source xmloff/source

dante (via logerrit) logerrit at kemper.freedesktop.org
Tue Aug 17 07:05:04 UTC 2021


 include/xmloff/xmltoken.hxx       |    1 
 starmath/Library_sm.mk            |    1 
 starmath/inc/mathml/element.hxx   |   10 
 starmath/inc/mathml/import.hxx    |  148 ++++
 starmath/source/mathml/import.cxx | 1362 ++++++++++++++++++++++++++++++++++++++
 xmloff/source/core/xmltoken.cxx   |    1 
 xmloff/source/token/tokens.txt    |    1 
 7 files changed, 1523 insertions(+), 1 deletion(-)

New commits:
commit 6ff56167cb2e6ae6e354663c8c07810d432819c1
Author:     dante <dante19031999 at gmail.com>
AuthorDate: Fri Aug 13 20:23:13 2021 +0200
Commit:     Noel Grandin <noel.grandin at collabora.co.uk>
CommitDate: Tue Aug 17 09:04:29 2021 +0200

    Add import for new starmath mathml elements
    
    Change-Id: Ie867cda8780747e715d642a9b007faafb33b4d99
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/120474
    Tested-by: Jenkins
    Reviewed-by: Noel Grandin <noel.grandin at collabora.co.uk>

diff --git a/include/xmloff/xmltoken.hxx b/include/xmloff/xmltoken.hxx
index 761108d78ad4..4458badec53d 100644
--- a/include/xmloff/xmltoken.hxx
+++ b/include/xmloff/xmltoken.hxx
@@ -3424,6 +3424,7 @@ namespace xmloff::token {
         // Math ml
         XML_DIR,
         XML_DISPLAYSTYLE,
+        XML_INFINITY,
         XML_LSPACE,
         XML_MATHBACKGROUND,
         XML_MAXSIZE,
diff --git a/starmath/Library_sm.mk b/starmath/Library_sm.mk
index 585834be74aa..613a8cbdb7cd 100644
--- a/starmath/Library_sm.mk
+++ b/starmath/Library_sm.mk
@@ -105,6 +105,7 @@ $(eval $(call gb_Library_add_exception_objects,sm,\
         starmath/source/mathml/mathmlimport \
         starmath/source/mathml/mathmlMo \
         starmath/source/mathml/export \
+        starmath/source/mathml/import \
         starmath/source/mathml/iterator \
         starmath/source/mathml/attribute \
         starmath/source/mathml/element \
diff --git a/starmath/inc/mathml/element.hxx b/starmath/inc/mathml/element.hxx
index 513b5d84b7ea..d51f5b07e01c 100644
--- a/starmath/inc/mathml/element.hxx
+++ b/starmath/inc/mathml/element.hxx
@@ -34,7 +34,7 @@ public:
     };
     /* Mathml stuff */
 
-protected:
+public:
     SmMlElement(SmMlElementType aElementType)
         : m_aElementType(aElementType)
         , m_aText(u"\u00B6")
@@ -174,6 +174,14 @@ public: // attributes
       */
     void setAttribute(const SmMlAttribute* aAttribute);
 
+    /**
+      * Set's a given attribute.
+      * If no available does nothing.
+      * @param nAttributePos
+      * @return given attribute.
+      */
+    void setAttribute(const SmMlAttribute& aAttribute) { setAttribute(&aAttribute); }
+
     /** Checks if an attribute has been manually set
     * @param aElementType
     */
diff --git a/starmath/inc/mathml/import.hxx b/starmath/inc/mathml/import.hxx
new file mode 100644
index 000000000000..916f929440a8
--- /dev/null
+++ b/starmath/inc/mathml/import.hxx
@@ -0,0 +1,148 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+// Our mathml
+#include "element.hxx"
+
+// XML tools
+#include <vcl/errcode.hxx>
+#include <xmloff/xmlimp.hxx>
+
+// Extras
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+
+class SfxMedium;
+class SmDocShell;
+class SmMLImport;
+
+class SmMLImportWrapper
+{
+    css::uno::Reference<css::frame::XModel> m_xModel;
+    SmDocShell* m_pDocShell;
+    SmMLImport* m_pMlImport;
+
+private:
+    // Use customized entities
+
+public:
+    /** Get the element tree when parsed from text
+    */
+    SmMlElement* getElementTree();
+
+public:
+    /** Constructor
+     */
+    explicit SmMLImportWrapper(css::uno::Reference<css::frame::XModel> const& rRef)
+        : m_xModel(rRef)
+        , m_pDocShell(nullptr)
+        , m_pMlImport(nullptr)
+    {
+    }
+
+    /** Imports the mathml
+    */
+    ErrCode Import(SfxMedium& rMedium);
+
+    /** Imports the mathml
+    */
+    ErrCode Import(std::u16string_view aSource);
+
+    /** read a component from input stream
+     */
+    ErrCode ReadThroughComponent(const css::uno::Reference<css::io::XInputStream>& xInputStream,
+                                 const css::uno::Reference<css::lang::XComponent>& xModelComponent,
+                                 css::uno::Reference<css::uno::XComponentContext> const& rxContext,
+                                 css::uno::Reference<css::beans::XPropertySet> const& rPropSet,
+                                 const char16_t* pFilterName, bool bEncrypted);
+
+    /** read a component from storage
+     */
+    ErrCode ReadThroughComponent(const css::uno::Reference<css::embed::XStorage>& xStorage,
+                                 const css::uno::Reference<css::lang::XComponent>& xModelComponent,
+                                 const char16_t* pStreamName,
+                                 css::uno::Reference<css::uno::XComponentContext> const& rxContext,
+                                 css::uno::Reference<css::beans::XPropertySet> const& rPropSet,
+                                 const char16_t* pFilterName);
+
+    /** read a component from text
+     */
+    ErrCode ReadThroughComponent(std::u16string_view aText,
+                                 const css::uno::Reference<css::lang::XComponent>& xModelComponent,
+                                 css::uno::Reference<css::uno::XComponentContext> const& rxContext,
+                                 css::uno::Reference<css::beans::XPropertySet> const& rPropSet);
+};
+
+class SmMLImport : public SvXMLImport
+{
+private:
+    SmMlElement* m_pElementTree = new SmMlElement(SmMlElementType::NMlEmpty);
+    bool m_bSuccess;
+    size_t m_nSmSyntaxVersion;
+
+public:
+    /** Get's parsed element tree
+    */
+    SmMlElement* getElementTree() { return m_pElementTree; }
+
+    /** Checks out if parse was a success
+     */
+    bool getSuccess() { return m_bSuccess; }
+
+public:
+    /** Handles an error on the mathml structure
+     */
+    void declareMlError();
+
+public:
+    /** Constructor
+    */
+    SmMLImport(const css::uno::Reference<css::uno::XComponentContext>& rContext,
+               OUString const& implementationName, SvXMLImportFlags nImportFlags);
+
+    /** Destructor
+    */
+    virtual ~SmMLImport() noexcept override { cleanup(); };
+
+public:
+    // XUnoTunnel
+    sal_Int64 SAL_CALL getSomething(const css::uno::Sequence<sal_Int8>& rId) override;
+    static const css::uno::Sequence<sal_Int8>& getUnoTunnelId() noexcept;
+
+    /** End the document
+    */
+    void SAL_CALL endDocument() override;
+
+    /** Create a fast context
+    */
+    SvXMLImportContext* CreateFastContext(
+        sal_Int32 nElement,
+        const css::uno::Reference<css::xml::sax::XFastAttributeList>& xAttrList) override;
+
+    /** Imports view settings formula
+    */
+    virtual void
+    SetViewSettings(const css::uno::Sequence<css::beans::PropertyValue>& aViewProps) override;
+
+    /** Imports configurations settings formula
+    */
+    virtual void SetConfigurationSettings(
+        const css::uno::Sequence<css::beans::PropertyValue>& aViewProps) override;
+
+    /** Set syntax version
+    */
+    void SetSmSyntaxVersion(sal_uInt16 nSmSyntaxVersion) { m_nSmSyntaxVersion = nSmSyntaxVersion; }
+
+    /** Get syntax version
+    */
+    sal_uInt16 GetSmSyntaxVersion() const { return m_nSmSyntaxVersion; }
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/starmath/source/mathml/import.cxx b/starmath/source/mathml/import.cxx
new file mode 100644
index 000000000000..e9e94b0f3cc6
--- /dev/null
+++ b/starmath/source/mathml/import.cxx
@@ -0,0 +1,1362 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+// Our mathml
+#include <mathml/import.hxx>
+
+// LO tools to use
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
+#include <com/sun/star/embed/ElementModes.hpp>
+#include <com/sun/star/packages/WrongPasswordException.hpp>
+#include <com/sun/star/packages/zip/ZipIOException.hpp>
+#include <com/sun/star/task/XStatusIndicator.hpp>
+#include <com/sun/star/xml/sax/FastParser.hpp>
+#include <com/sun/star/xml/sax/InputSource.hpp>
+#include <com/sun/star/xml/sax/Parser.hpp>
+#include <com/sun/star/xml/sax/SAXParseException.hpp>
+
+// Extra LO tools
+#include <comphelper/fileformat.h>
+#include <comphelper/genericpropertyset.hxx>
+#include <comphelper/processfactory.hxx>
+#include <comphelper/propertysetinfo.hxx>
+#include <comphelper/servicehelper.hxx>
+#include <rtl/character.hxx>
+#include <sfx2/docfile.hxx>
+#include <sfx2/frame.hxx>
+#include <sfx2/sfxsids.hrc>
+#include <sfx2/sfxmodelfactory.hxx>
+#include <sot/storage.hxx>
+#include <svtools/sfxecode.hxx>
+#include <svl/itemset.hxx>
+#include <svl/stritem.hxx>
+#include <rtl/character.hxx>
+#include <sax/tools/converter.hxx>
+#include <svx/dialmgr.hxx>
+#include <svx/strings.hrc>
+#include <tools/diagnose_ex.h>
+#include <unotools/streamwrap.hxx>
+#include <xmloff/DocumentSettingsContext.hxx>
+#include <xmloff/xmlmetai.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmluconv.hxx>
+
+// Our starmath tools
+#include <cfgitem.hxx>
+#include <document.hxx>
+#include <xparsmlbase.hxx>
+#include <utility.hxx>
+#include <smmod.hxx>
+#include <starmathdatabase.hxx>
+#include <unomodel.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::document;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::uno;
+using namespace com::sun::star::xml::sax;
+using namespace ::xmloff::token;
+
+// SmMLImportContext
+/*************************************************************************************************/
+
+SmMlElement* SmMLImportWrapper::getElementTree()
+{
+    return m_pMlImport == nullptr ? nullptr : m_pMlImport->getElementTree();
+}
+
+ErrCode SmMLImportWrapper::Import(SfxMedium& rMedium)
+{
+    // Fetch context
+    uno::Reference<uno::XComponentContext> xContext(comphelper::getProcessComponentContext());
+    if (!xContext.is())
+    {
+        SAL_WARN("starmath", "Failed to fetch model while file input");
+        return ERRCODE_SFX_DOLOADFAILED;
+    }
+
+    // Check model
+    if (!m_xModel.is())
+    {
+        SAL_WARN("starmath", "Failed to fetch model while file input");
+        return ERRCODE_SFX_DOLOADFAILED;
+    }
+
+    // Make a model component from our SmModel
+    uno::Reference<lang::XComponent> xModelComp = m_xModel;
+    if (!xModelComp.is())
+    {
+        SAL_WARN("starmath", "Failed to make model while file input");
+        return ERRCODE_SFX_DOLOADFAILED;
+    }
+
+    // Try to get an XStatusIndicator from the Medium
+    uno::Reference<task::XStatusIndicator> xStatusIndicator;
+
+    // Get model via uno
+    SmModel* pModel = comphelper::getUnoTunnelImplementation<SmModel>(m_xModel);
+    if (pModel == nullptr)
+    {
+        SAL_WARN("starmath", "Failed to fetch sm model while file input");
+        return ERRCODE_SFX_DOLOADFAILED;
+    }
+
+    // Get doc shell
+    m_pDocShell = pModel ? static_cast<SmDocShell*>(pModel->GetObjectShell()) : nullptr;
+    if (m_pDocShell == nullptr)
+    {
+        SAL_WARN("starmath", "Failed to fetch smdoc shell while file input");
+        return ERRCODE_SFX_DOLOADFAILED;
+    }
+
+    // Check if it is an embed object
+    bool bEmbedded = m_pDocShell->GetCreateMode() == SfxObjectCreateMode::EMBEDDED;
+
+    if (!bEmbedded)
+    {
+        // Extra check to ensure everything is fine
+        if (m_pDocShell->GetMedium() != &rMedium)
+        {
+            SAL_WARN("starmath", "Given medium and doc shell medium differ while file input");
+            return ERRCODE_SFX_DOLOADFAILED;
+        }
+
+        // Fetch the item set
+        SfxItemSet* pSet = rMedium.GetItemSet();
+        if (pSet)
+        {
+            const SfxUnoAnyItem* pItem
+                = static_cast<const SfxUnoAnyItem*>(pSet->GetItem(SID_PROGRESS_STATUSBAR_CONTROL));
+            if (pItem != nullptr)
+                pItem->GetValue() >>= xStatusIndicator;
+        }
+    }
+
+    // Create property list
+    comphelper::PropertyMapEntry aInfoMap[]
+        = { { u"PrivateData", 0, cppu::UnoType<XInterface>::get(),
+              beans::PropertyAttribute::MAYBEVOID, 0 },
+            { u"BaseURI", 0, ::cppu::UnoType<OUString>::get(), beans::PropertyAttribute::MAYBEVOID,
+              0 },
+            { u"StreamRelPath", 0, ::cppu::UnoType<OUString>::get(),
+              beans::PropertyAttribute::MAYBEVOID, 0 },
+            { u"StreamName", 0, ::cppu::UnoType<OUString>::get(),
+              beans::PropertyAttribute::MAYBEVOID, 0 },
+            { u"", 0, css::uno::Type(), 0, 0 } };
+    uno::Reference<beans::XPropertySet> xInfoSet(
+        comphelper::GenericPropertySet_CreateInstance(new comphelper::PropertySetInfo(aInfoMap)));
+
+    // Set base URI
+    // needed for relative URLs; but it's OK to import e.g. MathML from the clipboard without one
+    SAL_INFO_IF(rMedium.GetBaseURL().isEmpty(), "starmath", "SmMLImportWrapper: no base URL");
+    xInfoSet->setPropertyValue("BaseURI", makeAny(rMedium.GetBaseURL()));
+
+    // Fetch progress range
+    sal_Int32 nProgressRange(rMedium.IsStorage() ? 3 : 1);
+    if (xStatusIndicator.is())
+    {
+        xStatusIndicator->start(SvxResId(RID_SVXSTR_DOC_LOAD), nProgressRange);
+        xStatusIndicator->setValue(0);
+    }
+
+    // Get storage
+    if (rMedium.IsStorage())
+    {
+        // TODO/LATER: handle the case of embedded links gracefully
+        if (bEmbedded) // && !rMedium.GetStorage()->IsRoot() )
+        {
+            OUString aName(u"dummyObjName");
+            if (rMedium.GetItemSet())
+            {
+                const SfxStringItem* pDocHierarchItem = static_cast<const SfxStringItem*>(
+                    rMedium.GetItemSet()->GetItem(SID_DOC_HIERARCHICALNAME));
+                if (pDocHierarchItem != nullptr)
+                    aName = pDocHierarchItem->GetValue();
+            }
+
+            if (!aName.isEmpty())
+                xInfoSet->setPropertyValue("StreamRelPath", makeAny(aName));
+        }
+
+        // Check if use OASIS
+        bool bOASIS = SotStorage::GetVersion(rMedium.GetStorage()) > SOFFICE_FILEFORMAT_60;
+        if (xStatusIndicator.is())
+            xStatusIndicator->setValue(1);
+
+        // Read metadata
+        // read a component from storage
+        ErrCode nWarn = ReadThroughComponent(rMedium.GetStorage(), xModelComp, u"meta.xml",
+                                             xContext, xInfoSet,
+                                             bOASIS ? u"com.sun.star.comp.Math.MLOasisMetaImporter"
+                                                    : u"com.sun.star.comp.Math.MLMetaImporter");
+
+        // Check if succefull
+        if (nWarn != ERRCODE_NONE)
+        {
+            if (xStatusIndicator.is())
+                xStatusIndicator->end();
+            SAL_WARN("starmath", "Failed to read file");
+            return nWarn;
+        }
+
+        // Increase success indicator
+        if (xStatusIndicator.is())
+            xStatusIndicator->setValue(2);
+
+        // Read settings
+        // read a component from storage
+        nWarn = ReadThroughComponent(rMedium.GetStorage(), xModelComp, u"settings.xml", xContext,
+                                     xInfoSet,
+                                     bOASIS ? u"com.sun.star.comp.Math.MLOasisSettingsImporter"
+                                            : u"com.sun.star.comp.Math.MLSettingsImporter");
+
+        // Check if succefull
+        if (nWarn != ERRCODE_NONE)
+        {
+            if (xStatusIndicator.is())
+                xStatusIndicator->end();
+            SAL_WARN("starmath", "Failed to read file");
+            return nWarn;
+        }
+
+        // Increase success indicator
+        if (xStatusIndicator.is())
+            xStatusIndicator->setValue(3);
+
+        // Read document
+        // read a component from storage
+        nWarn = ReadThroughComponent(rMedium.GetStorage(), xModelComp, u"content.xml", xContext,
+                                     xInfoSet, u"com.sun.star.comp.Math.MLImporter");
+        // Check if succefull
+        if (nWarn != ERRCODE_NONE)
+        {
+            if (xStatusIndicator.is())
+                xStatusIndicator->end();
+            SAL_WARN("starmath", "Failed to read file");
+            return nWarn;
+        }
+
+        // Finish
+        if (xStatusIndicator.is())
+            xStatusIndicator->end();
+        return ERRCODE_NONE;
+    }
+    else
+    {
+        // Create input stream
+        Reference<io::XInputStream> xInputStream
+            = new utl::OInputStreamWrapper(rMedium.GetInStream());
+
+        // Increase success indicator
+        if (xStatusIndicator.is())
+            xStatusIndicator->setValue(1);
+
+        // Read data
+        // read a component from input stream
+        ErrCode nError = ReadThroughComponent(xInputStream, xModelComp, xContext, xInfoSet,
+                                              u"com.sun.star.comp.Math.MLImporter", false);
+
+        // Finish
+        if (xStatusIndicator.is())
+            xStatusIndicator->end();
+
+        // Declare any error
+        if (nError != ERRCODE_NONE)
+        {
+            SAL_WARN("starmath", "Failed to read file");
+            return nError;
+        }
+
+        return ERRCODE_NONE;
+    }
+}
+
+ErrCode SmMLImportWrapper::Import(std::u16string_view aSource)
+{
+    // Fetch context
+    uno::Reference<uno::XComponentContext> xContext(comphelper::getProcessComponentContext());
+    if (!xContext.is())
+    {
+        SAL_WARN("starmath", "Failed to fetch model while file input");
+        return ERRCODE_SFX_DOLOADFAILED;
+    }
+
+    // Check model
+    if (!m_xModel.is())
+    {
+        SAL_WARN("starmath", "Failed to fetch model while file input");
+        return ERRCODE_SFX_DOLOADFAILED;
+    }
+
+    // Make a model component from our SmModel
+    uno::Reference<lang::XComponent> xModelComp = m_xModel;
+    if (!xModelComp.is())
+    {
+        SAL_WARN("starmath", "Failed to make model while file input");
+        return ERRCODE_SFX_DOLOADFAILED;
+    }
+
+    // Get model via uno
+    SmModel* pModel = comphelper::getUnoTunnelImplementation<SmModel>(m_xModel);
+    if (pModel == nullptr)
+    {
+        SAL_WARN("starmath", "Failed to fetch sm model while file input");
+        return ERRCODE_SFX_DOLOADFAILED;
+    }
+
+    // Get doc shell
+    m_pDocShell = pModel ? static_cast<SmDocShell*>(pModel->GetObjectShell()) : nullptr;
+    if (m_pDocShell == nullptr)
+    {
+        SAL_WARN("starmath", "Failed to fetch smdoc shell while file input");
+        return ERRCODE_SFX_DOLOADFAILED;
+    }
+
+    // Create property list
+    comphelper::PropertyMapEntry aInfoMap[]
+        = { { u"PrivateData", 0, cppu::UnoType<XInterface>::get(),
+              beans::PropertyAttribute::MAYBEVOID, 0 },
+            { u"BaseURI", 0, ::cppu::UnoType<OUString>::get(), beans::PropertyAttribute::MAYBEVOID,
+              0 },
+            { u"StreamRelPath", 0, ::cppu::UnoType<OUString>::get(),
+              beans::PropertyAttribute::MAYBEVOID, 0 },
+            { u"StreamName", 0, ::cppu::UnoType<OUString>::get(),
+              beans::PropertyAttribute::MAYBEVOID, 0 },
+            { u"", 0, css::uno::Type(), 0, 0 } };
+    uno::Reference<beans::XPropertySet> xInfoSet(
+        comphelper::GenericPropertySet_CreateInstance(new comphelper::PropertySetInfo(aInfoMap)));
+
+    // Read data
+    // read a component from text
+    ErrCode nError = ReadThroughComponent(aSource, xModelComp, xContext, xInfoSet);
+
+    // Declare any error
+    if (nError != ERRCODE_NONE)
+    {
+        SAL_WARN("starmath", "Failed to read file");
+        return nError;
+    }
+
+    return ERRCODE_NONE;
+}
+
+// read a component from input stream
+ErrCode SmMLImportWrapper::ReadThroughComponent(const Reference<io::XInputStream>& xInputStream,
+                                                const Reference<XComponent>& xModelComponent,
+                                                Reference<uno::XComponentContext> const& rxContext,
+                                                Reference<beans::XPropertySet> const& rPropSet,
+                                                const char16_t* pFilterName, bool bEncrypted)
+{
+    // Needs an iunput stream but checked by caller
+    // Needs a context but checked by caller
+    // Needs property set but checked by caller
+    // Needs a filter name but checked by caller
+
+    // Prepare ParserInputSource
+    xml::sax::InputSource aParserInput;
+    aParserInput.aInputStream = xInputStream;
+
+    // Prepare property list
+    Sequence<Any> aArgs(1);
+    aArgs[0] <<= rPropSet;
+
+    // Get filter
+    Reference<XInterface> xFilter
+        = rxContext->getServiceManager()->createInstanceWithArgumentsAndContext(
+            OUString(pFilterName), aArgs, rxContext);
+    if (!xFilter.is())
+    {
+        SAL_WARN("starmath", "Can't instantiate filter component " << pFilterName);
+        return ERRCODE_SFX_DOLOADFAILED;
+    }
+
+    // Connect model and filter
+    Reference<XImporter> xImporter(xFilter, UNO_QUERY);
+    xImporter->setTargetDocument(xModelComponent);
+
+    // Finally, parser the stream
+    try
+    {
+        Reference<css::xml::sax::XFastParser> xFastParser(xFilter, UNO_QUERY);
+        Reference<css::xml::sax::XFastDocumentHandler> xFastDocHandler(xFilter, UNO_QUERY);
+        if (xFastParser)
+        {
+            xFastParser->setCustomEntityNames(starmathdatabase::icustomMathmlHtmlEntities);
+            xFastParser->parseStream(aParserInput);
+        }
+        else if (xFastDocHandler)
+        {
+            Reference<css::xml::sax::XFastParser> xParser
+                = css::xml::sax::FastParser::create(rxContext);
+            xParser->setCustomEntityNames(starmathdatabase::icustomMathmlHtmlEntities);
+            xParser->setFastDocumentHandler(xFastDocHandler);
+            xParser->parseStream(aParserInput);
+        }
+        else
+        {
+            Reference<css::xml::sax::XDocumentHandler> xDocHandler(xFilter, UNO_QUERY);
+            assert(xDocHandler);
+            Reference<css::xml::sax::XParser> xParser = css::xml::sax::Parser::create(rxContext);
+            xParser->setDocumentHandler(xDocHandler);
+            xParser->parseStream(aParserInput);
+        }
+
+        m_pMlImport = comphelper::getUnoTunnelImplementation<SmMLImport>(xFilter);
+        if (m_pMlImport != nullptr && m_pMlImport->getSuccess())
+            return ERRCODE_NONE;
+        else
+        {
+            SAL_WARN("starmath", "Filter failed on file input");
+            return ERRCODE_SFX_DOLOADFAILED;
+        }
+    }
+    catch (const xml::sax::SAXParseException& r)
+    {
+        // Sax parser sends wrapped exceptions, try to find the original one
+        xml::sax::SAXException aTmp;
+        xml::sax::SAXException aSaxEx = *static_cast<const xml::sax::SAXException*>(&r);
+        while (aSaxEx.WrappedException >>= aTmp)
+            aSaxEx = aTmp;
+
+        packages::zip::ZipIOException aBrokenPackage;
+        if (aSaxEx.WrappedException >>= aBrokenPackage)
+        {
+            SAL_WARN("starmath", "Failed to read file SAXParseException");
+            return ERRCODE_IO_BROKENPACKAGE;
+        }
+
+        if (bEncrypted)
+        {
+            SAL_WARN("starmath", "Wrong file password SAXParseException");
+            return ERRCODE_SFX_WRONGPASSWORD;
+        }
+    }
+    catch (const xml::sax::SAXException& r)
+    {
+        packages::zip::ZipIOException aBrokenPackage;
+        if (r.WrappedException >>= aBrokenPackage)
+        {
+            SAL_WARN("starmath", "Failed to read file SAXException");
+            return ERRCODE_IO_BROKENPACKAGE;
+        }
+
+        if (bEncrypted)
+        {
+            SAL_WARN("starmath", "Wrong file password SAXException");
+            return ERRCODE_SFX_WRONGPASSWORD;
+        }
+    }
+    catch (const packages::zip::ZipIOException&)
+    {
+        SAL_WARN("starmath", "Failed to unzip file ZipIOException");
+        return ERRCODE_IO_BROKENPACKAGE;
+    }
+    catch (const io::IOException&)
+    {
+        SAL_WARN("starmath", "Failed to read file ZipIOException");
+        return ERRCODE_IO_UNKNOWN;
+    }
+    catch (const std::range_error&)
+    {
+        SAL_WARN("starmath", "Failed to read file");
+        return ERRCODE_ABORT;
+    }
+
+    return ERRCODE_ABORT;
+}
+
+// read a component from storage
+ErrCode SmMLImportWrapper::ReadThroughComponent(const uno::Reference<embed::XStorage>& xStorage,
+                                                const Reference<XComponent>& xModelComponent,
+                                                const char16_t* pStreamName,
+                                                Reference<uno::XComponentContext> const& rxContext,
+                                                Reference<beans::XPropertySet> const& rPropSet,
+                                                const char16_t* pFilterName)
+{
+    // Needs a storage but checked by caller
+    // Needs a model but checked by caller
+    // Needs a stream name but checked by caller
+    // Needs a context but checked by caller
+    // Needs a property set but checked by caller
+    // Needs a filter name but checked by caller
+
+    // Get the input stream
+    try
+    {
+        // Create the stream for the event read
+        uno::Reference<io::XStream> xEventsStream
+            = xStorage->openStreamElement(OUString(pStreamName), embed::ElementModes::READ);
+
+        // Determine if stream is encrypted or not
+        uno::Reference<beans::XPropertySet> xProps(xEventsStream, uno::UNO_QUERY);
+        Any aAny = xProps->getPropertyValue("Encrypted");
+        bool bEncrypted = false;
+        aAny >>= bEncrypted;
+
+        // Set base URL and open stream
+        rPropSet->setPropertyValue("StreamName", makeAny(OUString(pStreamName)));
+        Reference<io::XInputStream> xStream = xEventsStream->getInputStream();
+
+        // Execute read
+        return ReadThroughComponent(xStream, xModelComponent, rxContext, rPropSet, pFilterName,
+                                    bEncrypted);
+    }
+    catch (packages::WrongPasswordException&)
+    {
+        SAL_WARN("starmath", "Wrong file password");
+        return ERRCODE_SFX_WRONGPASSWORD;
+    }
+    catch (packages::zip::ZipIOException&)
+    {
+        SAL_WARN("starmath", "Failed to unzip file");
+        return ERRCODE_IO_BROKENPACKAGE;
+    }
+    catch (uno::Exception&)
+    {
+    }
+
+    return ERRCODE_SFX_DOLOADFAILED;
+}
+
+// read a component from text
+ErrCode SmMLImportWrapper::ReadThroughComponent(
+    std::u16string_view aText, const css::uno::Reference<css::lang::XComponent>& xModelComponent,
+    css::uno::Reference<css::uno::XComponentContext> const& rxContext,
+    css::uno::Reference<css::beans::XPropertySet> const& rPropSet)
+{
+    // Needs a storage but checked by caller
+    // Needs a model but checked by caller
+    // Needs a stream name but checked by caller
+    // Needs a context but checked by caller
+    // Needs a property set but checked by caller
+    // Needs a filter name but checked by caller
+
+    // Get the input stream
+    try
+    {
+        // Generate input memory stream
+        SvMemoryStream aMemoryStream;
+        aMemoryStream.WriteOString(OUStringToOString(aText, RTL_TEXTENCODING_UTF8));
+        uno::Reference<io::XInputStream> xStream(new utl::OInputStreamWrapper(aMemoryStream));
+
+        // Execute read
+        return ReadThroughComponent(xStream, xModelComponent, rxContext, rPropSet,
+                                    u"com.sun.star.comp.Math.MLImporter", false);
+    }
+    catch (packages::WrongPasswordException&)
+    {
+        SAL_WARN("starmath", "Wrong file password");
+        return ERRCODE_SFX_WRONGPASSWORD;
+    }
+    catch (packages::zip::ZipIOException&)
+    {
+        SAL_WARN("starmath", "Failed to unzip file");
+        return ERRCODE_IO_BROKENPACKAGE;
+    }
+    catch (uno::Exception&)
+    {
+    }
+
+    return ERRCODE_SFX_DOLOADFAILED;
+}
+
+// SmMLImportContext
+/*************************************************************************************************/
+
+namespace
+{
+class SmMLImportContext : public SvXMLImportContext
+{
+private:
+    SmMlElement** m_pParent;
+    SmMlElement* m_pElement;
+    SmMlElement* m_pStyle;
+
+public:
+    SmMLImportContext(SmMLImport& rImport, SmMlElement** pParent)
+        : SvXMLImportContext(rImport)
+        , m_pParent(pParent)
+        , m_pElement(nullptr)
+        , m_pStyle(nullptr)
+    {
+    }
+
+private:
+    void declareMlError();
+
+public:
+    /** Handles characters (text)
+     */
+    virtual void SAL_CALL characters(const OUString& aChars) override;
+
+    /** Starts the mathml element
+     */
+    virtual void SAL_CALL startFastElement(
+        sal_Int32 nElement, const Reference<XFastAttributeList>& aAttributeList) override;
+
+    /** Ends the mathml element
+     */
+    virtual void SAL_CALL endFastElement(sal_Int32 Element) override;
+
+    /** Creates child element
+     */
+    virtual uno::Reference<XFastContextHandler>
+        SAL_CALL createFastChildContext(sal_Int32 nElement,
+                                        const uno::Reference<XFastAttributeList>& Attribs) override;
+
+    /** Inherits the style from it's parents
+    */
+    void inheritStyle();
+
+    /** Inherits the style from it's parents on end
+    */
+    void inheritStyleEnd();
+
+    /** Handle mathml attributes
+    */
+    void handleAttributes(const Reference<XFastAttributeList>& aAttributeList);
+
+    /** Handle mathml length attributes
+    */
+    SmLengthValue handleLengthAttributte(const OUString& aAttribute);
+};
+
+uno::Reference<XFastContextHandler> SAL_CALL
+SmMLImportContext::createFastChildContext(sal_Int32, const uno::Reference<XFastAttributeList>&)
+{
+    uno::Reference<xml::sax::XFastContextHandler> xContext;
+    xContext = new SmMLImportContext(static_cast<SmMLImport&>(GetImport()), &m_pElement);
+    return xContext;
+}
+
+void SmMLImportContext::declareMlError()
+{
+    SmMLImport& aSmMLImport = static_cast<SmMLImport&>(GetImport());
+    aSmMLImport.declareMlError();
+}
+
+void SmMLImportContext::inheritStyle()
+{
+    while ((m_pStyle = m_pStyle->getParentElement()) != nullptr)
+    {
+        if (m_pStyle->getParentElement()->getMlElementType() == SmMlElementType::MlMstyle
+            || m_pStyle->getParentElement()->getMlElementType() == SmMlElementType::MlMath)
+            break;
+    }
+
+    // Parent inheritation
+    // Mathcolor, mathsize, dir and displaystyle are inherited from parent
+    SmMlElement* pParent = *m_pParent;
+    m_pElement->setAttribute(pParent->getAttribute(SmMlAttributeValueType::MlMathcolor));
+    m_pElement->setAttribute(pParent->getAttribute(SmMlAttributeValueType::MlMathsize));
+    m_pElement->setAttribute(pParent->getAttribute(SmMlAttributeValueType::MlDir));
+    m_pElement->setAttribute(pParent->getAttribute(SmMlAttributeValueType::MlDisplaystyle));
+
+    // Inherit operator dictionary overwrites
+    if (m_pStyle != nullptr
+        && (m_pElement->getMlElementType() == SmMlElementType::MlMo
+            || m_pElement->getMlElementType() == SmMlElementType::MlMstyle
+            || m_pElement->getMlElementType() == SmMlElementType::MlMath))
+    {
+        // TODO fetch operator dictionary first and then overwrite
+        if (m_pStyle->isAttributeSet(SmMlAttributeValueType::MlAccent))
+            m_pElement->setAttribute(m_pStyle->getAttribute(SmMlAttributeValueType::MlAccent));
+        if (m_pStyle->isAttributeSet(SmMlAttributeValueType::MlFence))
+            m_pElement->setAttribute(m_pStyle->getAttribute(SmMlAttributeValueType::MlFence));
+        if (m_pStyle->isAttributeSet(SmMlAttributeValueType::MlLspace))
+            m_pElement->setAttribute(m_pStyle->getAttribute(SmMlAttributeValueType::MlLspace));
+        if (m_pStyle->isAttributeSet(SmMlAttributeValueType::MlMaxsize))
+            m_pElement->setAttribute(m_pStyle->getAttribute(SmMlAttributeValueType::MlMaxsize));
+        if (m_pStyle->isAttributeSet(SmMlAttributeValueType::MlMinsize))
+            m_pElement->setAttribute(m_pStyle->getAttribute(SmMlAttributeValueType::MlMinsize));
+        if (m_pStyle->isAttributeSet(SmMlAttributeValueType::MlMovablelimits))
+            m_pElement->setAttribute(
+                m_pStyle->getAttribute(SmMlAttributeValueType::MlMovablelimits));
+        if (m_pStyle->isAttributeSet(SmMlAttributeValueType::MlRspace))
+            m_pElement->setAttribute(m_pStyle->getAttribute(SmMlAttributeValueType::MlRspace));
+        if (m_pStyle->isAttributeSet(SmMlAttributeValueType::MlSeparator))
+            m_pElement->setAttribute(m_pStyle->getAttribute(SmMlAttributeValueType::MlSeparator));
+        if (m_pStyle->isAttributeSet(SmMlAttributeValueType::MlStretchy))
+            m_pElement->setAttribute(m_pStyle->getAttribute(SmMlAttributeValueType::MlStretchy));
+        if (m_pStyle->isAttributeSet(SmMlAttributeValueType::MlSymmetric))
+            m_pElement->setAttribute(m_pStyle->getAttribute(SmMlAttributeValueType::MlSymmetric));
+
+        if (m_pElement->getMlElementType() == SmMlElementType::MlMo)
+        {
+            // Set form based in position
+            SmMlAttribute aAttribute(SmMlAttributeValueType::MlForm);
+            SmMlForm aForm;
+            if (m_pElement->getSubElementId() == 0)
+                aForm = { SmMlAttributeValueForm::MlPrefix };
+            else
+                aForm = { SmMlAttributeValueForm::MlInfix };
+            aAttribute.setMlForm(&aForm);
+            m_pElement->setAttribute(aAttribute);
+        }
+    }
+
+    // Inherit mathvariant
+    if (m_pStyle->isAttributeSet(SmMlAttributeValueType::MlMathvariant))
+        m_pElement->setAttribute(m_pStyle->getAttribute(SmMlAttributeValueType::MlMathvariant));
+}
+
+void SmMLImportContext::inheritStyleEnd()
+{
+    // Mo: check it is the end: postfix
+    if (m_pElement->getMlElementType() == SmMlElementType::MlMo)
+    {
+        if ((*m_pParent)->getSubElementsCount() == m_pElement->getSubElementId())
+        {
+            // Set form based in position
+            SmMlAttribute aAttribute(SmMlAttributeValueType::MlForm);
+            SmMlForm aForm = { SmMlAttributeValueForm::MlPosfix };
+            aAttribute.setMlForm(&aForm);
+            m_pElement->setAttribute(aAttribute);
+        }
+    }
+
+    // Mi: 1 char -> italic
+    if (m_pElement->getMlElementType() == SmMlElementType::MlMi)
+    {
+        // Inherit mathvariant
+        if (!m_pStyle->isAttributeSet(SmMlAttributeValueType::MlMathvariant))
+        {
+            sal_Int32 nIndexUtf16 = 0;
+            // Check if there is only one code point
+            m_pElement->getText().iterateCodePoints(&nIndexUtf16, 1);
+            // Mathml says that 1 code point -> italic
+            if (nIndexUtf16 == m_pElement->getText().getLength())
+            {
+                SmMlAttribute aAttribute(SmMlAttributeValueType::MlMathvariant);
+                SmMlMathvariant aMathvariant = { SmMlAttributeValueMathvariant::italic };
+                aAttribute.setMlMathvariant(&aMathvariant);
+                aAttribute.setSet(false);
+                m_pElement->setAttribute(aAttribute);
+            }
+        }
+    }
+}
+
+SmLengthValue SmMLImportContext::handleLengthAttributte(const OUString& aAttribute)
+{
+    // Locate unit indication
+    int32_t nUnitPos;
+    for (nUnitPos = 0;
+         nUnitPos < aAttribute.getLength()
+         && (rtl::isAsciiHexDigit(aAttribute[nUnitPos]) || aAttribute[nUnitPos] == '.');
+         ++nUnitPos)
+        ;
+
+    // Find unit
+    SmLengthUnit nUnit = SmLengthUnit::MlM;
+    if (nUnitPos != aAttribute.getLength())
+    {
+        OUString aUnit = aAttribute.copy(nUnitPos);
+        if (aUnit.compareToIgnoreAsciiCaseAscii("ex"))
+            nUnit = SmLengthUnit::MlEx;
+        if (aUnit.compareToIgnoreAsciiCaseAscii("px"))
+            nUnit = SmLengthUnit::MlPx;
+        if (aUnit.compareToIgnoreAsciiCaseAscii("in"))
+            nUnit = SmLengthUnit::MlIn;
+        if (aUnit.compareToIgnoreAsciiCaseAscii("cm"))
+            nUnit = SmLengthUnit::MlCm;
+        if (aUnit.compareToIgnoreAsciiCaseAscii("mm"))
+            nUnit = SmLengthUnit::MlMm;
+        if (aUnit.compareToIgnoreAsciiCaseAscii("pt"))
+            nUnit = SmLengthUnit::MlPt;
+        if (aUnit.compareToIgnoreAsciiCaseAscii("pc"))
+            nUnit = SmLengthUnit::MlPc;
+        if (aUnit.compareToIgnoreAsciiCaseAscii("%"))
+            nUnit = SmLengthUnit::MlP;
+        else
+            declareMlError();
+    }
+
+    // Get value
+    OUString aValue = aAttribute.copy(0, nUnitPos);
+    double nValue = aValue.toDouble();
+    if (nValue == 0)
+    {
+        nUnit = SmLengthUnit::MlM;
+        nValue = 1.0;
+        declareMlError();
+    }
+
+    // Return
+    SmLengthValue aLengthValue = { nUnit, nValue, new OUString(aAttribute) };
+    return aLengthValue;
+}
+
+void SmMLImportContext::handleAttributes(const Reference<XFastAttributeList>& aAttributeList)
+{
+    for (auto& aIter : sax_fastparser::castToFastAttributeList(aAttributeList))
+    {
+        SmMlAttribute aAttribute(SmMlAttributeValueType::NMlEmpty);
+        switch (aIter.getToken() & TOKEN_MASK)
+        {
+            case XML_ACCENT:
+            {
+                if (IsXMLToken(aIter, XML_TRUE))
+                {
+                    aAttribute.setMlAttributeValueType(SmMlAttributeValueType::MlAccent);
+                    SmMlAccent aAccent = { SmMlAttributeValueAccent::MlTrue };
+                    aAttribute.setMlAccent(&aAccent);
+                }
+                else if (IsXMLToken(aIter, XML_FALSE))
+                {
+                    aAttribute.setMlAttributeValueType(SmMlAttributeValueType::MlAccent);
+                    SmMlAccent aAccent = { SmMlAttributeValueAccent::MlFalse };
+                    aAttribute.setMlAccent(&aAccent);
+                }
+                else
+                {
+                    declareMlError();
+                }
+                break;
+            }
+            case XML_DIR:
+            {
+                if (IsXMLToken(aIter, XML_RTL))
+                {
+                    aAttribute.setMlAttributeValueType(SmMlAttributeValueType::MlDir);
+                    SmMlDir aDir = { SmMlAttributeValueDir::MlRtl };
+                    aAttribute.setMlDir(&aDir);
+                }
+                else if (IsXMLToken(aIter, XML_LTR))
+                {
+                    aAttribute.setMlAttributeValueType(SmMlAttributeValueType::MlDir);
+                    SmMlDir aDir = { SmMlAttributeValueDir::MlLtr };
+                    aAttribute.setMlDir(&aDir);
+                }
+                else
+                {
+                    declareMlError();
+                }
+                break;
+            }
+            case XML_DISPLAYSTYLE:
+                if (IsXMLToken(aIter, XML_TRUE))
+                {
+                    aAttribute.setMlAttributeValueType(SmMlAttributeValueType::MlDisplaystyle);
+                    SmMlDisplaystyle aDisplaystyle = { SmMlAttributeValueDisplaystyle::MlTrue };
+                    aAttribute.setMlDisplaystyle(&aDisplaystyle);
+                }
+                else if (IsXMLToken(aIter, XML_FALSE))
+                {
+                    aAttribute.setMlAttributeValueType(SmMlAttributeValueType::MlDisplaystyle);
+                    SmMlDisplaystyle aDisplaystyle = { SmMlAttributeValueDisplaystyle::MlFalse };
+                    aAttribute.setMlDisplaystyle(&aDisplaystyle);
+                }
+                else
+                {
+                    declareMlError();
+                }
+                break;
+            case XML_FENCE:
+                if (IsXMLToken(aIter, XML_TRUE))
+                {
+                    aAttribute.setMlAttributeValueType(SmMlAttributeValueType::MlFence);
+                    SmMlFence aFence = { SmMlAttributeValueFence::MlTrue };
+                    aAttribute.setMlFence(&aFence);
+                }
+                else if (IsXMLToken(aIter, XML_FALSE))
+                {
+                    aAttribute.setMlAttributeValueType(SmMlAttributeValueType::MlFence);
+                    SmMlFence aFence = { SmMlAttributeValueFence::MlFalse };
+                    aAttribute.setMlFence(&aFence);
+                }
+                else
+                {
+                    declareMlError();
+                }
+                break;
+            case XML_HREF:
+            {
+                aAttribute.setMlAttributeValueType(SmMlAttributeValueType::MlHref);
+                OUString* aRef = new OUString(aIter.toString());
+                SmMlHref aHref = { SmMlAttributeValueHref::NMlValid, aRef };
+                aAttribute.setMlHref(&aHref);
+                break;
+            }
+            case XML_LSPACE:
+            {
+                SmMlLspace aLspace;
+                aLspace.m_aLengthValue = handleLengthAttributte(aIter.toString());
+                aAttribute.setMlLspace(&aLspace);
+                break;
+            }
+            case XML_MATHBACKGROUND:
+            {
+                if (IsXMLToken(aIter, XML_TRANSPARENT))
+                {
+                    SmMlMathbackground aMathbackground
+                        = { SmMlAttributeValueMathbackground::MlTransparent, COL_TRANSPARENT };
+                    aAttribute.setMlMathbackground(&aMathbackground);
+                }
+                else
+                {
+                    Color aColor
+                        = starmathdatabase::Identify_ColorName_HTML(aIter.toString()).cColor;
+                    SmMlMathbackground aMathbackground
+                        = { SmMlAttributeValueMathbackground::MlRgb, aColor };
+                    aAttribute.setMlMathbackground(&aMathbackground);
+                }
+                break;
+            }
+            case XML_MATHCOLOR:
+            {
+                if (IsXMLToken(aIter, XML_DEFAULT))
+                {
+                    SmMlMathcolor aMathcolor
+                        = { SmMlAttributeValueMathcolor::MlDefault, COL_BLACK };
+                    aAttribute.setMlMathcolor(&aMathcolor);
+                }
+                else
+                {
+                    Color aColor
+                        = starmathdatabase::Identify_ColorName_HTML(aIter.toString()).cColor;
+                    SmMlMathcolor aMathcolor = { SmMlAttributeValueMathcolor::MlRgb, aColor };
+                    aAttribute.setMlMathcolor(&aMathcolor);
+                }
+                break;
+            }
+            case XML_MATHSIZE:
+            {
+                SmMlMathsize aMathsize;
+                aMathsize.m_aLengthValue = handleLengthAttributte(aIter.toString());
+                aAttribute.setMlMathsize(&aMathsize);
+                break;
+            }
+            case XML_MATHVARIANT:
+            {
+                OUString aVariant = aIter.toString();
+                SmMlAttributeValueMathvariant nVariant = SmMlAttributeValueMathvariant::normal;
+                if (aVariant.compareTo(u"normal"))
+                    nVariant = SmMlAttributeValueMathvariant::normal;
+                else if (aVariant.compareTo(u"bold"))
+                    nVariant = SmMlAttributeValueMathvariant::bold;
+                else if (aVariant.compareTo(u"italic"))
+                    nVariant = SmMlAttributeValueMathvariant::italic;
+                else if (aVariant.compareTo(u"double-struck"))
+                    nVariant = SmMlAttributeValueMathvariant::double_struck;
+                else if (aVariant.compareTo(u"script"))
+                    nVariant = SmMlAttributeValueMathvariant::script;
+                else if (aVariant.compareTo(u"fraktur"))
+                    nVariant = SmMlAttributeValueMathvariant::fraktur;
+                else if (aVariant.compareTo(u"sans-serif"))
+                    nVariant = SmMlAttributeValueMathvariant::sans_serif;
+                else if (aVariant.compareTo(u"monospace"))
+                    nVariant = SmMlAttributeValueMathvariant::monospace;
+                else if (aVariant.compareTo(u"bold-italic"))
+                    nVariant = SmMlAttributeValueMathvariant::bold_italic;
+                else if (aVariant.compareTo(u"bold-fracktur"))
+                    nVariant = SmMlAttributeValueMathvariant::bold_fraktur;
+                else if (aVariant.compareTo(u"bold-script"))
+                    nVariant = SmMlAttributeValueMathvariant::bold_script;
+                else if (aVariant.compareTo(u"bold-sans-serif"))
+                    nVariant = SmMlAttributeValueMathvariant::bold_sans_serif;
+                else if (aVariant.compareTo(u"sans-serif-italic"))
+                    nVariant = SmMlAttributeValueMathvariant::sans_serif_italic;
+                else if (aVariant.compareTo(u"sans-serif-bold-italic"))
+                    nVariant = SmMlAttributeValueMathvariant::sans_serif_bold_italic;
+                else if (aVariant.compareTo(u"initial"))
+                    nVariant = SmMlAttributeValueMathvariant::initial;
+                else if (aVariant.compareTo(u"tailed"))
+                    nVariant = SmMlAttributeValueMathvariant::tailed;
+                else if (aVariant.compareTo(u"looped"))
+                    nVariant = SmMlAttributeValueMathvariant::looped;
+                else if (aVariant.compareTo(u"stretched"))
+                    nVariant = SmMlAttributeValueMathvariant::stretched;
+                else
+                    declareMlError();
+                SmMlMathvariant aMathvariant = { nVariant };
+                aAttribute.setMlMathvariant(&aMathvariant);
+                break;
+            }
+            case XML_MAXSIZE:
+            {
+                SmMlMaxsize aMaxsize;
+                if (IsXMLToken(aIter, XML_INFINITY))
+                    aMaxsize.m_aMaxsize = SmMlAttributeValueMaxsize::MlInfinity;
+                else
+                {
+                    aMaxsize.m_aMaxsize = SmMlAttributeValueMaxsize::MlFinite;
+                    aMaxsize.m_aLengthValue = handleLengthAttributte(aIter.toString());
+                }
+                aAttribute.setMlMaxsize(&aMaxsize);
+                break;
+            }
+            case XML_MINSIZE:
+            {
+                SmMlMinsize aMinsize;
+                aMinsize.m_aLengthValue = handleLengthAttributte(aIter.toString());
+                aAttribute.setMlMinsize(&aMinsize);
+                break;
+            }
+            case XML_MOVABLELIMITS:
+                if (IsXMLToken(aIter, XML_TRUE))
+                {
+                    aAttribute.setMlAttributeValueType(SmMlAttributeValueType::MlMovablelimits);
+                    SmMlMovablelimits aMovablelimits = { SmMlAttributeValueMovablelimits::MlTrue };
+                    aAttribute.setMlMovablelimits(&aMovablelimits);
+                }
+                else if (IsXMLToken(aIter, XML_FALSE))
+                {
+                    aAttribute.setMlAttributeValueType(SmMlAttributeValueType::MlMovablelimits);
+                    SmMlMovablelimits aMovablelimits = { SmMlAttributeValueMovablelimits::MlFalse };
+                    aAttribute.setMlMovablelimits(&aMovablelimits);
+                }
+                else
+                {
+                    declareMlError();
+                }
+                break;
+            case XML_RSPACE:
+            {
+                SmMlRspace aRspace;
+                aRspace.m_aLengthValue = handleLengthAttributte(aIter.toString());
+                aAttribute.setMlRspace(&aRspace);
+                break;
+            }
+            case XML_SEPARATOR:
+                if (IsXMLToken(aIter, XML_TRUE))
+                {
+                    aAttribute.setMlAttributeValueType(SmMlAttributeValueType::MlSeparator);
+                    SmMlSeparator aSeparator = { SmMlAttributeValueSeparator::MlTrue };
+                    aAttribute.setMlSeparator(&aSeparator);
+                }
+                else if (IsXMLToken(aIter, XML_FALSE))
+                {
+                    aAttribute.setMlAttributeValueType(SmMlAttributeValueType::MlSeparator);
+                    SmMlSeparator aSeparator = { SmMlAttributeValueSeparator::MlFalse };
+                    aAttribute.setMlSeparator(&aSeparator);
+                }
+                else
+                {
+                    declareMlError();
+                }
+                break;
+            case XML_STRETCHY:
+                if (IsXMLToken(aIter, XML_TRUE))
+                {
+                    aAttribute.setMlAttributeValueType(SmMlAttributeValueType::MlStretchy);
+                    SmMlStretchy aStretchy = { SmMlAttributeValueStretchy::MlTrue };
+                    aAttribute.setMlStretchy(&aStretchy);
+                }
+                else if (IsXMLToken(aIter, XML_FALSE))
+                {
+                    aAttribute.setMlAttributeValueType(SmMlAttributeValueType::MlStretchy);
+                    SmMlStretchy aStretchy = { SmMlAttributeValueStretchy::MlFalse };
+                    aAttribute.setMlStretchy(&aStretchy);
+                }
+                else
+                {
+                    declareMlError();
+                }
+                break;
+            case XML_SYMMETRIC:
+                if (IsXMLToken(aIter, XML_TRUE))
+                {
+                    aAttribute.setMlAttributeValueType(SmMlAttributeValueType::MlSymmetric);
+                    SmMlSymmetric aSymmetric = { SmMlAttributeValueSymmetric::MlTrue };
+                    aAttribute.setMlSymmetric(&aSymmetric);
+                }
+                else if (IsXMLToken(aIter, XML_FALSE))
+                {
+                    aAttribute.setMlAttributeValueType(SmMlAttributeValueType::MlSymmetric);
+                    SmMlSymmetric aSymmetric = { SmMlAttributeValueSymmetric::MlFalse };
+                    aAttribute.setMlSymmetric(&aSymmetric);
+                }
+                else
+                {
+                    declareMlError();
+                }
+                break;
+            default:
+                declareMlError();
+                break;
+        }
+        if (aAttribute.isNullAttribute())
+            declareMlError();
+        else
+            m_pElement->setAttribute(aAttribute);
+    }
+}
+
+void SmMLImportContext::characters(const OUString& aChars) { m_pElement->setText(aChars); }
+
+void SmMLImportContext::startFastElement(sal_Int32 nElement,
+                                         const Reference<XFastAttributeList>& aAttributeList)
+{
+    switch (nElement)
+    {
+        case XML_ELEMENT(MATH, XML_MATH):
+            m_pElement = new SmMlElement(SmMlElementType::MlMath);
+            break;
+        case XML_ELEMENT(MATH, XML_MI):
+            m_pElement = new SmMlElement(SmMlElementType::MlMi);
+            break;
+        case XML_ELEMENT(MATH, XML_MERROR):
+            m_pElement = new SmMlElement(SmMlElementType::MlMerror);
+            break;
+        case XML_ELEMENT(MATH, XML_MN):
+            m_pElement = new SmMlElement(SmMlElementType::MlMn);
+            break;
+        case XML_ELEMENT(MATH, XML_MO):
+            m_pElement = new SmMlElement(SmMlElementType::MlMo);
+            break;
+        case XML_ELEMENT(MATH, XML_MROW):
+            m_pElement = new SmMlElement(SmMlElementType::MlMrow);
+            break;
+        case XML_ELEMENT(MATH, XML_MTEXT):
+            m_pElement = new SmMlElement(SmMlElementType::MlMtext);
+            break;
+        case XML_ELEMENT(MATH, XML_MSTYLE):
+            m_pElement = new SmMlElement(SmMlElementType::MlMstyle);
+            break;
+        default:
+            m_pElement = new SmMlElement(SmMlElementType::NMlEmpty);
+            declareMlError();
+            break;
+    }
+    SmMlElement* pParent = *m_pParent;
+    pParent->setSubElement(pParent->getSubElementsCount(), m_pElement);
+    inheritStyle();
+    handleAttributes(aAttributeList);
+}
+
+void SmMLImportContext::endFastElement(sal_Int32) { inheritStyleEnd(); }
+}
+
+// SmMLImport
+/*************************************************************************************************/
+
+const uno::Sequence<sal_Int8>& SmMLImport::getUnoTunnelId() noexcept
+{
+    static const UnoTunnelIdInit theSmMLImportUnoTunnelId;
+    return theSmMLImportUnoTunnelId.getSeq();
+}
+
+sal_Int64 SAL_CALL SmMLImport::getSomething(const uno::Sequence<sal_Int8>& rId)
+{
+    if (isUnoTunnelId<SmMLImport>(rId))
+        return sal::static_int_cast<sal_Int64>(reinterpret_cast<sal_uIntPtr>(this));
+
+    return SvXMLImport::getSomething(rId);
+}
+
+SvXMLImportContext*
+SmMLImport::CreateFastContext(sal_Int32 nElement,
+                              const uno::Reference<xml::sax::XFastAttributeList>& /*xAttrList*/)
+{
+    SvXMLImportContext* pContext = nullptr;
+
+    switch (nElement)
+    {
+        case XML_ELEMENT(OFFICE, XML_DOCUMENT):
+        {
+            uno::Reference<document::XDocumentPropertiesSupplier> xDPS(GetModel(),
+                                                                       uno::UNO_QUERY_THROW);
+            pContext = new SmMLImportContext(*this, &m_pElementTree);
+            break;
+        }
+        case XML_ELEMENT(OFFICE, XML_DOCUMENT_META):
+        {
+            uno::Reference<document::XDocumentPropertiesSupplier> xDPS(GetModel(),
+                                                                       uno::UNO_QUERY_THROW);
+            pContext = new SvXMLMetaDocumentContext(*this, xDPS->getDocumentProperties());
+            break;
+        }
+        case XML_ELEMENT(OFFICE, XML_DOCUMENT_SETTINGS):
+        {
+            uno::Reference<document::XDocumentPropertiesSupplier> xDPS(GetModel(),
+                                                                       uno::UNO_QUERY_THROW);
+            pContext = new XMLDocumentSettingsContext(*this);
+            break;
+        }
+        default:
+            declareMlError();
+            break;
+    }
+    return pContext;
+}
+
+void SmMLImport::endDocument()
+{
+    uno::Reference<frame::XModel> xModel = GetModel();
+    if (!xModel.is())
+    {
+        SAL_WARN("starmath", "Failed to set view settings because missing model");
+        SvXMLImport::endDocument();
+        return;
+    }
+
+    SmModel* pModel = comphelper::getUnoTunnelImplementation<SmModel>(xModel);
+    if (!pModel)
+    {
+        SAL_WARN("starmath", "Failed to set view settings because missing sm model");
+        SvXMLImport::endDocument();
+        return;
+    }
+
+    SmDocShell* pDocShell = static_cast<SmDocShell*>(pModel->GetObjectShell());
+    if (!pDocShell)
+    {
+        SAL_WARN("starmath", "Failed to set view settings because missing sm doc shell");
+        SvXMLImport::endDocument();
+        return;
+    }
+
+    // TODO handle aftermatch
+    if (m_pElementTree->getSubElementsCount() == 0)
+    {
+        delete m_pElementTree;
+        m_pElementTree = nullptr;
+    }
+    else
+    {
+        SmMlElement* pTmpElememt = m_pElementTree->getSubElement(0);
+        delete m_pElementTree;
+        m_pElementTree = pTmpElememt;
+    }
+
+    m_bSuccess = true;
+
+    SvXMLImport::endDocument();
+}
+
+void SmMLImport::SetViewSettings(const Sequence<PropertyValue>& aViewProps)
+{
+    uno::Reference<frame::XModel> xModel = GetModel();
+    if (!xModel.is())
+    {
+        SAL_WARN("starmath", "Failed to set view settings because missing model");
+        return;
+    }
+
+    SmModel* pModel = comphelper::getUnoTunnelImplementation<SmModel>(xModel);
+    if (!pModel)
+    {
+        SAL_WARN("starmath", "Failed to set view settings because missing sm model");
+        return;
+    }
+
+    SmDocShell* pDocShell = static_cast<SmDocShell*>(pModel->GetObjectShell());
+    if (!pDocShell)
+    {
+        SAL_WARN("starmath", "Failed to set view settings because missing sm doc shell");
+        return;
+    }
+
+    tools::Rectangle aRect(pDocShell->GetVisArea());
+
+    tools::Long nTmp = 0;
+
+    for (const PropertyValue& rValue : aViewProps)
+    {
+        if (rValue.Name == "ViewAreaTop")
+        {
+            rValue.Value >>= nTmp;
+            aRect.SaturatingSetY(nTmp);
+        }
+        else if (rValue.Name == "ViewAreaLeft")
+        {
+            rValue.Value >>= nTmp;
+            aRect.SaturatingSetX(nTmp);
+        }
+        else if (rValue.Name == "ViewAreaWidth")
+        {
+            rValue.Value >>= nTmp;
+            Size aSize(aRect.GetSize());
+            aSize.setWidth(nTmp);
+            aRect.SaturatingSetSize(aSize);
+        }
+        else if (rValue.Name == "ViewAreaHeight")
+        {
+            rValue.Value >>= nTmp;
+            Size aSize(aRect.GetSize());
+            aSize.setHeight(nTmp);
+            aRect.SaturatingSetSize(aSize);
+        }
+    }
+
+    pDocShell->SetVisArea(aRect);
+}
+
+void SmMLImport::SetConfigurationSettings(const Sequence<PropertyValue>& aConfProps)
+{
+    uno::Reference<frame::XModel> xModel = GetModel();
+    if (!xModel.is())
+    {
+        SAL_WARN("starmath", "Failed to set view settings because missing model");
+        return;
+    }
+
+    uno::Reference<XPropertySet> xProps(xModel, UNO_QUERY);
+    if (!xProps.is())
+    {
+        SAL_WARN("starmath", "Failed to set view settings because missing model properties");
+        return;
+    }
+
+    Reference<XPropertySetInfo> xInfo(xProps->getPropertySetInfo());
+    if (!xInfo.is())
+    {
+        SAL_WARN("starmath",
+                 "Failed to set view settings because missing model properties information");
+        return;
+    }
+
+    static const OUStringLiteral sFormula(u"Formula");
+    static const OUStringLiteral sBasicLibraries(u"BasicLibraries");
+    static const OUStringLiteral sDialogLibraries(u"DialogLibraries");
+    for (const PropertyValue& rValue : aConfProps)
+    {
+        if (rValue.Name != sFormula && rValue.Name != sBasicLibraries
+            && rValue.Name != sDialogLibraries)
+        {
+            try
+            {
+                if (xInfo->hasPropertyByName(rValue.Name))
+                    xProps->setPropertyValue(rValue.Name, rValue.Value);
+            }
+            catch (const beans::PropertyVetoException&)
+            {
+                // dealing with read-only properties here. Nothing to do...
+            }
+            catch (const Exception&)
+            {
+                SAL_WARN("starmath", "Unespected issue while loading document properties");
+            }
+        }
+    }
+}
+
+SmMLImport::SmMLImport(const css::uno::Reference<css::uno::XComponentContext>& rContext,
+                       OUString const& implementationName, SvXMLImportFlags nImportFlags)
+    : SvXMLImport(rContext, implementationName, nImportFlags)
+    , m_pElementTree(nullptr)
+    , m_bSuccess(false)
+    , m_nSmSyntaxVersion(SM_MOD()->GetConfig()->GetDefaultSmSyntaxVersion())
+{
+}
+
+/** Handles an error on the mathml structure
+ */
+void SmMLImport::declareMlError()
+{
+    m_bSuccess = false;
+    SAL_WARN("starmath", "MathML error");
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/xmloff/source/core/xmltoken.cxx b/xmloff/source/core/xmltoken.cxx
index 9bc4fca57a80..d4b996a4d9dd 100644
--- a/xmloff/source/core/xmltoken.cxx
+++ b/xmloff/source/core/xmltoken.cxx
@@ -3420,6 +3420,7 @@ namespace xmloff::token {
 
         TOKEN("dir",                 XML_DIR ),
         TOKEN("displaystyle",        XML_DISPLAYSTYLE ),
+        TOKEN("infinity",            XML_INFINITY ),
         TOKEN("lspace",              XML_LSPACE ),
         TOKEN("mathbackground",      XML_MATHBACKGROUND ),
         TOKEN("maxsize",             XML_MAXSIZE ),
diff --git a/xmloff/source/token/tokens.txt b/xmloff/source/token/tokens.txt
index 52b457602c27..9823df1e82e7 100644
--- a/xmloff/source/token/tokens.txt
+++ b/xmloff/source/token/tokens.txt
@@ -3173,6 +3173,7 @@ margin-gutter
 local-url
 dir
 displaystyle
+infinity
 lspace
 mathbackground
 maxsize


More information about the Libreoffice-commits mailing list