Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/LibreOffice/starmath/source/mathml/   (Office von Apache Version 25.8.3.2©)  Datei vom 5.10.2025 mit Größe 40 kB image not shown  

Quelle  export.cxx   Sprache: C

 
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * 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/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */


// Our mathml
#include <mathml/export.hxx>
#include <mathml/iterator.hxx>

// LO tools to use
#include <com/sun/star/beans/PropertyAttribute.hpp>
#include <com/sun/star/embed/ElementModes.hpp>
#include <com/sun/star/task/XStatusIndicator.hpp>
#include <com/sun/star/uno/Any.h>
#include <com/sun/star/util/MeasureUnit.hpp>
#include <com/sun/star/xml/sax/Writer.hpp>

// Extra LO tools
#include <comphelper/genericpropertyset.hxx>
#include <comphelper/processfactory.hxx>
#include <comphelper/propertysetinfo.hxx>
#include <comphelper/servicehelper.hxx>
#include <sfx2/frame.hxx>
#include <sfx2/docfile.hxx>
#include <sfx2/sfxsids.hrc>
#include <svl/itemset.hxx>
#include <svl/stritem.hxx>
#include <unotools/streamwrap.hxx>
#include <xmloff/namespacemap.hxx>

// Our starmath tools
#include <document.hxx>
#include <smmod.hxx>
#include <strings.hrc>
#include <unomodel.hxx>
#include <xparsmlbase.hxx>
#include <starmathdatabase.hxx>

// Old parser
#include <mathmlexport.hxx>

using namespace ::com::sun::star;
using namespace xmloff::token;

using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::document;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star;
using namespace ::xmloff::token;

// SmMLExportWrapper
/*************************************************************************************************/

bool SmMLExportWrapper::Export(SfxMedium& rMedium)
{
    bool bRet = true;
    const uno::Reference<uno::XComponentContext>& xContext(
        comphelper::getProcessComponentContext());

    // Check all fine
    SAL_WARN_IF(m_xModel == nullptr, "starmath""Missing model");
    SAL_WARN_IF(xContext == nullptr, "starmath""Missing context");
    if (m_xModel == nullptr || xContext == nullptr)
        return false;

    // Get doc shell
    SmDocShell* pDocShell = static_cast<SmDocShell*>(m_xModel->GetObjectShell());
    if (pDocShell == nullptr)
    {
        SAL_WARN("starmath""Failed to fetch sm document");
        return false;
    }

    // Check if it is a standalone window or embed object
    bool bEmbedded = SfxObjectCreateMode::EMBEDDED == pDocShell->GetCreateMode();

    // Medium item set
    SfxItemSet& rMediumItemSet = rMedium.GetItemSet();

    // Progress bar ~
    uno::Reference<task::XStatusIndicator> xStatusIndicator;

    if (!bEmbedded)
    {
        // Extra check to ensure everything is fine
        if (pDocShell->GetMedium() != &rMedium)
        {
            SAL_WARN("starmath""Input medium and sm document medium do not match");
            //return false;
        }

        // Fetch progress bar
        const SfxUnoAnyItem* pItem = rMediumItemSet.GetItem(SID_PROGRESS_STATUSBAR_CONTROL);
        if (pItem)
        {
            // set progress range and start status indicator
            pItem->GetValue() >>= xStatusIndicator;
            xStatusIndicator->start(SmResId(STR_STATSTR_WRITING), 3);
            xStatusIndicator->setValue(0);
        }
    }

    // create XPropertySet with three properties for status indicator
    static const comphelper::PropertyMapEntry aInfoMap[]{
        { u"UsePrettyPrinting"_ustr, 0, cppu::UnoType<bool>::get(),
          beans::PropertyAttribute::MAYBEVOID, 0 },
        { u"BaseURI"_ustr, 0, ::cppu::UnoType<OUString>::get(), beans::PropertyAttribute::MAYBEVOID,
          0 },
        { u"StreamRelPath"_ustr, 0, ::cppu::UnoType<OUString>::get(),
          beans::PropertyAttribute::MAYBEVOID, 0 },
        { u"StreamName"_ustr, 0, ::cppu::UnoType<OUString>::get(),
          beans::PropertyAttribute::MAYBEVOID, 0 }
    };
    uno::Reference<beans::XPropertySet> xInfoSet(
        comphelper::GenericPropertySet_CreateInstance(new comphelper::PropertySetInfo(aInfoMap)));

    // Always print pretty
    xInfoSet->setPropertyValue(u"UsePrettyPrinting"_ustr, Any(true));

    // Set base URI
    xInfoSet->setPropertyValue(u"BaseURI"_ustr, Any(rMedium.GetBaseURL(true)));

    if (!m_bFlat) //Storage (Package) of Stream
    {
        // Fetch the output storage
        uno::Reference<embed::XStorage> xStg = rMedium.GetOutputStorage();
        if (xStg == nullptr)
        {
            SAL_WARN("starmath""Failed to fetch output storage");
            return false;
        }

        // TODO/LATER: handle the case of embedded links gracefully
        if (bEmbedded) //&& !pStg->IsRoot() )
        {
            const SfxStringItem* pDocHierarchItem
                = rMediumItemSet.GetItem(SID_DOC_HIERARCHICALNAME);
            if (pDocHierarchItem != nullptr)
            {
                OUString aName = pDocHierarchItem->GetValue();
                if (!aName.isEmpty())
                    xInfoSet->setPropertyValue(u"StreamRelPath"_ustr, Any(aName));
            }
        }
        else
        {
            // Write file metadata ( data, LO version ... )
            // Note: export through an XML exporter component (storage version)
            if (xStatusIndicator.is())
                xStatusIndicator->setValue(1);

            bRet = WriteThroughComponentS(xStg, m_xModel, u"meta.xml", xContext, xInfoSet,
                                          u"com.sun.star.comp.Math.MLOasisMetaExporter", 6);
        }

        // Write starmath formula
        // Note: export through an XML exporter component (storage version)
        if (bRet)
        {
            if (xStatusIndicator.is())
                xStatusIndicator->setValue(2);

            if (pDocShell->GetSmSyntaxVersion() == 5)
                bRet = WriteThroughComponentS(xStg, m_xModel, u"content.xml", xContext, xInfoSet,
                                              u"com.sun.star.comp.Math.XMLContentExporter", 5);
            else
                bRet = WriteThroughComponentS(xStg, m_xModel, u"content.xml", xContext, xInfoSet,
                                              u"com.sun.star.comp.Math.MLContentExporter", 6);
        }

        // Write starmath settings
        // Note: export through an XML exporter component (storage version)
        if (bRet)
        {
            if (xStatusIndicator.is())
                xStatusIndicator->setValue(3);

            bRet = WriteThroughComponentS(xStg, m_xModel, u"settings.xml", xContext, xInfoSet,
                                          u"com.sun.star.comp.Math.MLOasisSettingsExporter", 6);
        }
    }
    else
    {
        // Fetch the output stream
        SvStream* pStream = rMedium.GetOutStream();
        if (pStream == nullptr)
        {
            SAL_WARN("starmath""Missing output stream");
            return false;
        }
        uno::Reference<io::XOutputStream> xOut(new utl::OOutputStreamWrapper(*pStream));

        if (xStatusIndicator.is())
            xStatusIndicator->setValue(1);

        // Write everything in the same place
        // Note: export through an XML exporter component (output stream version)
        if (pDocShell->GetSmSyntaxVersion() == 5)
            bRet = WriteThroughComponentOS(xOut, m_xModel, xContext, xInfoSet,
                                           u"com.sun.star.comp.Math.XMLContentExporter", 5);
        else
            bRet = WriteThroughComponentOS(xOut, m_xModel, xContext, xInfoSet,
                                           u"com.sun.star.comp.Math.MLContentExporter", 6);
    }

    if (xStatusIndicator.is())
        xStatusIndicator->end();
    return bRet;
}

OUString SmMLExportWrapper::Export(SmMlElement* pElementTree)
{
    const uno::Reference<uno::XComponentContext>& xContext(
        comphelper::getProcessComponentContext());

    // Check all fine
    m_pElementTree = nullptr;
    SAL_WARN_IF(m_xModel == nullptr, "starmath""Missing model");
    SAL_WARN_IF(xContext == nullptr, "starmath""Missing context");
    if (m_xModel == nullptr || xContext == nullptr)
        return u""_ustr;

    //Get model
    SmModel* pModel = m_xModel.get();
    SAL_WARN_IF(pModel == nullptr, "starmath""Failed to get threw uno tunnel");
    if (pModel == nullptr)
        return u""_ustr;

    // Get doc shell
    SmDocShell* pDocShell = static_cast<SmDocShell*>(pModel->GetObjectShell());
    if (pDocShell == nullptr)
    {
        SAL_WARN("starmath""Failed to fetch sm document");
        return u""_ustr;
    }

    // create XPropertySet with three properties for status indicator
    static const comphelper::PropertyMapEntry aInfoMap[]{
        { u"UsePrettyPrinting"_ustr, 0, cppu::UnoType<bool>::get(),
          beans::PropertyAttribute::MAYBEVOID, 0 },
        { u"BaseURI"_ustr, 0, ::cppu::UnoType<OUString>::get(), beans::PropertyAttribute::MAYBEVOID,
          0 },
        { u"StreamRelPath"_ustr, 0, ::cppu::UnoType<OUString>::get(),
          beans::PropertyAttribute::MAYBEVOID, 0 },
        { u"StreamName"_ustr, 0, ::cppu::UnoType<OUString>::get(),
          beans::PropertyAttribute::MAYBEVOID, 0 }
    };
    uno::Reference<beans::XPropertySet> xInfoSet(
        comphelper::GenericPropertySet_CreateInstance(new comphelper::PropertySetInfo(aInfoMap)));

    // Always print pretty
    xInfoSet->setPropertyValue(u"UsePrettyPrinting"_ustr, Any(true));

    // Fetch mathml tree
    m_pElementTree = pElementTree;

    // Write stuff
    // Note: export through an XML exporter component (memory stream version)
    return WriteThroughComponentMS(uno::Reference<lang::XComponent>(m_xModel), xContext, xInfoSet);
}

// export through an XML exporter component (output stream version)
bool SmMLExportWrapper::WriteThroughComponentOS(const Reference<io::XOutputStream>&&nbsp;xOutputStream,
                                                const Reference<XComponent>& xComponent,
                                                Reference<uno::XComponentContext> const& rxContext,
                                                Reference<beans::XPropertySet> const& rPropSet,
                                                const char16_t* pComponentName,
                                                int_fast16_t nSyntaxVersion)
{
    // We need a output stream but it is already checked by caller
    // We need a component but it is already checked by caller
    // We need a context but it is already checked by caller
    // We need a property set but it is already checked by caller
    // We need a component name but it is already checked by caller

    // get sax writer
    Reference<xml::sax::XWriter> xSaxWriter = xml::sax::Writer::create(rxContext);

    // connect XML writer to output stream
    xSaxWriter->setOutputStream(xOutputStream);
    if (m_bUseHTMLMLEntities)
        xSaxWriter->setCustomEntityNames(starmathdatabase::icustomMathmlHtmlEntitiesExport);

    // prepare arguments (prepend doc handler to given arguments)
    Sequence<Any> aArgs{ Any(xSaxWriter), Any(rPropSet) };

    // get filter component
    auto xExporterData = rxContext->getServiceManager()->createInstanceWithArgumentsAndContext(
        OUString(pComponentName), aArgs, rxContext);
    Reference<document::XExporter> xExporter(xExporterData, UNO_QUERY);

    // Check everything is fine
    if (!xExporter.is())
    {
        SAL_WARN("starmath""can't instantiate export filter component");
        return false;
    }

    // connect model and filter
    xExporter->setSourceDocument(xComponent);
    Reference<XFilter> xFilter(xExporter, UNO_QUERY);
    uno::Sequence<PropertyValue> aProps(0);

    // filter
    if (nSyntaxVersion == 5)
    {
        SmXMLExport* pFilter = dynamic_cast<SmXMLExport*>(xFilter.get());
        if (pFilter == nullptr)
        {
            SAL_WARN("starmath""Failed to fetch SmMLExport");
            return false;
        }
        xFilter->filter(aProps);
        return pFilter->GetSuccess();
    }

    // filter
    SmMLExport* pFilter = dynamic_cast<SmMLExport*>(xFilter.get());

    // Setup filter
    if (pFilter == nullptr)
    {
        SAL_WARN("starmath""Failed to fetch SmMLExport");
        return false;
    }
    pFilter->setUseExportTag(m_bUseExportTag);
    pFilter->setElementTree(m_pElementTree);

    // Execute operation
    xFilter->filter(aProps);
    return pFilter->getSuccess();
}

// export through an XML exporter component (storage version)
bool SmMLExportWrapper::WriteThroughComponentS(const Reference<embed::XStorage>& xStorage,
                                               const Reference<XComponent>& xComponent,
                                               const char16_t* pStreamName,
                                               Reference<uno::XComponentContext> const& rxContext,
                                               Reference<beans::XPropertySet> const& rPropSet,
                                               const char16_t* pComponentName,
                                               int_fast16_t nSyntaxVersion)
{
    // We need a storage name but it is already checked by caller
    // We need a component name but it is already checked by caller
    // We need a stream name but it is already checked by caller
    // We need a context but it is already checked by caller
    // We need a property set but it is already checked by caller
    // We need a component but it is already checked by caller

    // open stream
    Reference<io::XStream> xStream;
    try
    {
        xStream = xStorage->openStreamElement(
            OUString(pStreamName), embed::ElementModes::READWRITE | embed::ElementModes::TRUNCATE);
    }
    catch (const uno::Exception&)
    {
        SAL_WARN("starmath""Can't create output stream in package");
        return false;
    }

    // Set stream as text / xml
    uno::Reference<beans::XPropertySet> xSet(xStream, uno::UNO_QUERY);
    xSet->setPropertyValue(u"MediaType"_ustr, Any(u"text/xml"_ustr));

    // all streams must be encrypted in encrypted document
    xSet->setPropertyValue(u"UseCommonStoragePasswordEncryption"_ustr, Any(true));

    // set Base URL
    rPropSet->setPropertyValue(u"StreamName"_ustr, Any(OUString(pStreamName)));

    // write the stuff
    // Note: export through an XML exporter component (output stream version)
    return WriteThroughComponentOS(xStream->getOutputStream(), xComponent, rxContext, rPropSet,
                                   pComponentName, nSyntaxVersion);
}

// export through an XML exporter component (memory stream version)
OUString
SmMLExportWrapper::WriteThroughComponentMS(const Reference<XComponent>& xComponent,
                                           Reference<uno::XComponentContext> const& rxContext,
                                           Reference<beans::XPropertySet> const& rPropSet)
{
    // We need a component but it is already checked by caller
    // We need a context but it is already checked by caller
    // We need a property set it is already checked by caller

    // open stream
    SvMemoryStream aMemoryStream(8192, 1024);
    uno::Reference<io::XOutputStream> xStream(new utl::OOutputStreamWrapper(aMemoryStream));

    // Set the stream as text
    uno::Reference<beans::XPropertySet> xSet(xStream, uno::UNO_QUERY);
    xSet->setPropertyValue(u"MediaType"_ustr, Any(u"text/xml"_ustr));

    // write the stuff
    // Note: export through an XML exporter component (output stream version)
    bool bOk = WriteThroughComponentOS(xStream, xComponent, rxContext, rPropSet,
                                       u"com.sun.star.comp.Mathml.MLContentExporter", 6);

    // We don't want to read uninitialized data
    if (!bOk)
        return u""_ustr;

    // Recover data and generate string
    OString aString(static_cast<const char*>(aMemoryStream.GetData()),
                    aMemoryStream.GetSize() / sizeof(char));
    return OStringToOUString(aString, RTL_TEXTENCODING_UTF8);
}

// SmMLExport technical
/*************************************************************************************************/

extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
Math_MLExporter_get_implementation(css::uno::XComponentContext* context,
                                   css::uno::Sequence<css::uno::Any> const&)
{
    return cppu::acquire(new SmMLExport(context, u"com.sun.star.comp.Math.XMLExporter"_ustr,
                                        SvXMLExportFlags::OASIS | SvXMLExportFlags::ALL));
}

extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
Math_MLOasisMetaExporter_get_implementation(css::uno::XComponentContext* context,
                                            css::uno::Sequence<css::uno::Any> const&)
{
    return cppu::acquire(new SmMLExport(context,
                                        u"com.sun.star.comp.Math.XMLOasisMetaExporter"_ustr,
                                        SvXMLExportFlags::OASIS | SvXMLExportFlags::META));
}

extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
Math_MLOasisSettingsExporter_get_implementation(css::uno::XComponentContext* context,
                                                css::uno::Sequence<css::uno::Any> const&)
{
    return cppu::acquire(new SmMLExport(context,
                                        u"com.sun.star.comp.Math.XMLOasisSettingsExporter"_ustr,
                                        SvXMLExportFlags::OASIS | SvXMLExportFlags::SETTINGS));
}

extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
Math_MLContentExporter_get_implementation(css::uno::XComponentContext* context,
                                          css::uno::Sequence<css::uno::Any> const&)
{
    return cppu::acquire(new SmMLExport(context, u"com.sun.star.comp.Math.XMLContentExporter"_ustr,
                                        SvXMLExportFlags::OASIS | SvXMLExportFlags::CONTENT));
}

SmDocShell* SmMLExport::getSmDocShell()
{
    SmModel* pModel = comphelper::getFromUnoTunnel<SmModel>(GetModel());
    if (pModel != nullptr)
        return static_cast<SmDocShell*>(pModel->GetObjectShell());
    return nullptr;
}

ErrCode SmMLExport::exportDoc(enum XMLTokenEnum eClass)
{
    if (!(getExportFlags() & SvXMLExportFlags::CONTENT))
    {
        // Everything that isn't the formula itself get's default export
        SvXMLExport::exportDoc(eClass);
        return ERRCODE_NONE;
    }

    // Checks if it has to export a particular tree
    if (m_pElementTree == nullptr)
    {
        // Set element tree
        SmDocShell* pDocShell = getSmDocShell();
        if (pDocShell != nullptr)
            m_pElementTree = pDocShell->GetMlElementTree();
        else
        {
            m_bSuccess = false;
            return SVSTREAM_INVALID_PARAMETER;
        }
    }

    // Start document and encrypt if necessary
    GetDocHandler()->startDocument();
    addChaffWhenEncryptedStorage();

    // make use of a default namespace
    // Math doesn't need namespaces from xmloff, since it now uses default namespaces
    // Because that is common with current MathML usage in the web -> ResetNamespaceMap();
    GetNamespaceMap_().Add(u""_ustr, GetXMLToken(XML_N_MATH), XML_NAMESPACE_MATH);

    // Add xmlns line
    if (m_bUseExportTag)
    {
        GetAttrList().AddAttribute(GetNamespaceMap().GetAttrNameByKey(XML_NAMESPACE_MATH),
                                   GetNamespaceMap().GetNameByKey(XML_NAMESPACE_MATH));
    }

    // Export and close document
    ExportContent_();
    GetDocHandler()->endDocument();

    return ERRCODE_NONE;
}

void SmMLExport::GetViewSettings(Sequence<PropertyValue>& aProps)
{
    // Get the document shell
    SmDocShell* pDocShell = getSmDocShell();
    if (pDocShell == nullptr)
    {
        SAL_WARN("starmath""Missing document shell so no view settings");
        return;
    }

    // Allocate enough memory
    aProps.realloc(4);
    PropertyValue* pValue = aProps.getArray();

    // The view settings are the formula display settings
    tools::Rectangle aRect(pDocShell->GetVisArea());

    pValue[0].Name = "ViewAreaTop";
    pValue[0].Value <<= aRect.Top();

    pValue[1].Name = "ViewAreaLeft";
    pValue[1].Value <<= aRect.Left();

    pValue[2].Name = "ViewAreaWidth";
    pValue[2].Value <<= aRect.GetWidth();

    pValue[3].Name = "ViewAreaHeight";
    pValue[3].Value <<= aRect.GetHeight();
}

void SmMLExport::GetConfigurationSettings(Sequence<PropertyValue>& rProps)
{
    // Get model property set (settings)
    Reference<XPropertySet> xProps(GetModel(), UNO_QUERY);
    if (!xProps.is())
    {
        SAL_WARN("starmath""Missing model properties so no configuration settings");
        return;
    }

    // Get model property set info (settings values)
    Reference<XPropertySetInfo> xPropertySetInfo = xProps->getPropertySetInfo();
    if (!xPropertySetInfo.is())
    {
        SAL_WARN("starmath""Missing model properties info so no configuration settings");
        return;
    }

    // Allocate to store the properties
    Sequence<Property> aProps = xPropertySetInfo->getProperties();
    const sal_Int32 nCount = aProps.getLength();
    rProps.realloc(nCount);
    auto pProps = rProps.getArray();

    // Copy properties
    // This needs further revision
    // Based in code mathmlexport.cxx::GetConfigurationSettings
    for (sal_Int32 i = 0; i < nCount; ++i)
    {
        if (aProps[i].Name != "Formula" && aProps[i].Name != "BasicLibraries"
            && aProps[i].Name != "DialogLibraries" && aProps[i].Name != "RuntimeUID")
        {
            pProps[i].Name = aProps[i].Name;
            pProps[i].Value = xProps->getPropertyValue(aProps[i].Name);
        }
    }
}

SmMLExport::SmMLExport(const css::uno::Reference<css::uno::XComponentContext>& rContext,
                       OUString const& implementationName, SvXMLExportFlags nExportFlags)
    : SvXMLExport(rContext, implementationName, util::MeasureUnit::INCH, XML_MATH, nExportFlags)
    , m_pElementTree(nullptr)
    , m_bSuccess(true)
    , m_bUseExportTag(true)
{
}

// SmMLExport
/*************************************************************************************************/

void SmMLExport::declareMlError()
{
    SAL_WARN("starmath""Invalid use of mathml.");
    m_bSuccess = false;
}

void SmMLExport::exportMlAttributeLength(xmloff::token::XMLTokenEnum pAttribute,
                                         const SmLengthValue& aLengthValue)
{
    if (!aLengthValue.m_aOriginalText->isEmpty())
    {
        addAttribute(pAttribute, *aLengthValue.m_aOriginalText);
    }
    else
    {
        OUStringBuffer aSizeBuffer(64);
        aSizeBuffer.append(aLengthValue.m_aLengthValue);
        switch (aLengthValue.m_aLengthUnit)
        {
            case SmLengthUnit::MlEm:
                aSizeBuffer.append(u"em");
                break;
            case SmLengthUnit::MlEx:
                aSizeBuffer.append(u"ex");
                break;
            case SmLengthUnit::MlPx:
                aSizeBuffer.append(u"px");
                break;
            case SmLengthUnit::MlIn:
                aSizeBuffer.append(u"in");
                break;
            case SmLengthUnit::MlCm:
                aSizeBuffer.append(u"cm");
                break;
            case SmLengthUnit::MlMm:
                aSizeBuffer.append(u"mm");
                break;
            case SmLengthUnit::MlPt:
                aSizeBuffer.append(u"pt");
                break;
            case SmLengthUnit::MlPc:
                aSizeBuffer.append(u"pc");
                break;
            case SmLengthUnit::MlP:
                aSizeBuffer.append(u"%");
                break;
            case SmLengthUnit::MlM:
                break;
            default:
                declareMlError();
                break;
        }
        addAttribute(pAttribute, aSizeBuffer.makeStringAndClear());
    }
}

void SmMLExport::exportMlAttributes(const SmMlElement* pMlElement)
{
    size_t nAttributeCount = pMlElement->getAttributeCount();
    for (size_t i = 0; i < nAttributeCount; ++i)
    {
        SmMlAttribute aAttribute = pMlElement->getAttribute(i);
        if (!aAttribute.isSet())
            continue;

        switch (aAttribute.getMlAttributeValueType())
        {
            case SmMlAttributeValueType::MlAccent:
            {
                auto aAttributeValue = aAttribute.getMlAccent();
                switch (aAttributeValue->m_aAccent)
                {
                    case SmMlAttributeValueAccent::MlFalse:
                        addAttribute(XML_ACCENT, XML_FALSE);
                        break;
                    case SmMlAttributeValueAccent::MlTrue:
                        addAttribute(XML_ACCENT, XML_TRUE);
                        break;
                    default:
                        declareMlError();
                        break;
                }
                break;
            }
            case SmMlAttributeValueType::MlDir:
            {
                auto aAttributeValue = aAttribute.getMlDir();
                switch (aAttributeValue->m_aDir)
                {
                    case SmMlAttributeValueDir::MlLtr:
                        addAttribute(XML_DIR, XML_LTR);
                        break;
                    case SmMlAttributeValueDir::MlRtl:
                        addAttribute(XML_DIR, XML_RTL);
                        break;
                    default:
                        declareMlError();
                        break;
                }
                break;
            }
            case SmMlAttributeValueType::MlDisplaystyle:
            {
                auto aAttributeValue = aAttribute.getMlDisplaystyle();
                switch (aAttributeValue->m_aDisplaystyle)
                {
                    case SmMlAttributeValueDisplaystyle::MlTrue:
                        addAttribute(XML_DISPLAYSTYLE, XML_FALSE);
                        break;
                    case SmMlAttributeValueDisplaystyle::MlFalse:
                        addAttribute(XML_DISPLAYSTYLE, XML_TRUE);
                        break;
                    default:
                        declareMlError();
                        break;
                }
                break;
            }
            case SmMlAttributeValueType::MlFence:
            {
                auto aAttributeValue = aAttribute.getMlFence();
                switch (aAttributeValue->m_aFence)
                {
                    case SmMlAttributeValueFence::MlTrue:
                        addAttribute(XML_FENCE, XML_FALSE);
                        break;
                    case SmMlAttributeValueFence::MlFalse:
                        addAttribute(XML_FENCE, XML_TRUE);
                        break;
                    default:
                        declareMlError();
                        break;
                }
                break;
            }
            case SmMlAttributeValueType::MlHref:
            {
                auto aAttributeValue = aAttribute.getMlHref();
                switch (aAttributeValue->m_aHref)
                {
                    case SmMlAttributeValueHref::NMlEmpty:
                        break;
                    case SmMlAttributeValueHref::NMlValid:
                        addAttribute(XML_HREF, *aAttributeValue->m_aLnk);
                        break;
                    default:
                        declareMlError();
                        break;
                }
                break;
            }
            case SmMlAttributeValueType::MlLspace:
            {
                auto pSizeData = aAttribute.getMlLspace();
                exportMlAttributeLength(XML_LSPACE, pSizeData->m_aLengthValue);
                break;
            }
            case SmMlAttributeValueType::MlMathbackground:
            {
                auto aAttributeValue = aAttribute.getMlMathbackground();
                switch (aAttributeValue->m_aMathbackground)
                {
                    case SmMlAttributeValueMathbackground::MlTransparent:
                        addAttribute(XML_MATHBACKGROUND, u"transparent"_ustr);
                        break;
                    case SmMlAttributeValueMathbackground::MlRgb:
                    {
                        const OUString& rTextColor = starmathdatabase::Identify_Color_MATHML(
                                                         sal_uInt32(aAttributeValue->m_aCol))
                                                         .aIdent;
                        addAttribute(XML_MATHBACKGROUND, rTextColor);
                        break;
                    }
                    default:
                        declareMlError();
                        break;
                }
                break;
            }
            case SmMlAttributeValueType::MlMathcolor:
            {
                auto aAttributeValue = aAttribute.getMlMathcolor();
                switch (aAttributeValue->m_aMathcolor)
                {
                    case SmMlAttributeValueMathcolor::MlDefault:
                        break;
                    case SmMlAttributeValueMathcolor::MlRgb:
                    {
                        const OUString& rTextColor = starmathdatabase::Identify_Color_MATHML(
                                                         sal_uInt32(aAttributeValue->m_aCol))
                                                         .aIdent;
                        addAttribute(XML_MATHCOLOR, rTextColor);
                        break;
                    }
                    default:
                        declareMlError();
                        break;
                }
                break;
            }
            case SmMlAttributeValueType::MlMathsize:
            {
                auto pSizeData = aAttribute.getMlMathsize();
                exportMlAttributeLength(XML_MATHSIZE, pSizeData->m_aLengthValue);
                break;
            }
            case SmMlAttributeValueType::MlMathvariant:
            {
                auto aAttributeValue = aAttribute.getMlMathvariant();
                switch (aAttributeValue->m_aMathvariant)
                {
                    case SmMlAttributeValueMathvariant::normal:
                        addAttribute(XML_MATHVARIANT, u"normal"_ustr);
                        break;
                    case SmMlAttributeValueMathvariant::bold:
                        addAttribute(XML_MATHVARIANT, u"bold"_ustr);
                        break;
                    case SmMlAttributeValueMathvariant::italic:
                        addAttribute(XML_MATHVARIANT, u"italic"_ustr);
                        break;
                    case SmMlAttributeValueMathvariant::double_struck:
                        addAttribute(XML_MATHVARIANT, u"double-struck"_ustr);
                        break;
                    case SmMlAttributeValueMathvariant::script:
                        addAttribute(XML_MATHVARIANT, u"script"_ustr);
                        break;
                    case SmMlAttributeValueMathvariant::fraktur:
                        addAttribute(XML_MATHVARIANT, u"fraktur"_ustr);
                        break;
                    case SmMlAttributeValueMathvariant::sans_serif:
                        addAttribute(XML_MATHVARIANT, u"sans-serif"_ustr);
                        break;
                    case SmMlAttributeValueMathvariant::monospace:
                        addAttribute(XML_MATHVARIANT, u"monospace"_ustr);
                        break;
                    case SmMlAttributeValueMathvariant::bold_italic:
                        addAttribute(XML_MATHVARIANT, u"bold-italic"_ustr);
                        break;
                    case SmMlAttributeValueMathvariant::bold_fraktur:
                        addAttribute(XML_MATHVARIANT, u"bold-fracktur"_ustr);
                        break;
                    case SmMlAttributeValueMathvariant::bold_script:
                        addAttribute(XML_MATHVARIANT, u"bold-script"_ustr);
                        break;
                    case SmMlAttributeValueMathvariant::bold_sans_serif:
                        addAttribute(XML_MATHVARIANT, u"bold-sans-serif"_ustr);
                        break;
                    case SmMlAttributeValueMathvariant::sans_serif_italic:
                        addAttribute(XML_MATHVARIANT, u"sans-serif-italic"_ustr);
                        break;
                    case SmMlAttributeValueMathvariant::sans_serif_bold_italic:
                        addAttribute(XML_MATHVARIANT, u"sans-serif-bold-italic"_ustr);
                        break;
                    case SmMlAttributeValueMathvariant::initial:
                        addAttribute(XML_MATHVARIANT, u"initial"_ustr);
                        break;
                    case SmMlAttributeValueMathvariant::tailed:
                        addAttribute(XML_MATHVARIANT, u"tailed"_ustr);
                        break;
                    case SmMlAttributeValueMathvariant::looped:
                        addAttribute(XML_MATHVARIANT, u"looped"_ustr);
                        break;
                    case SmMlAttributeValueMathvariant::stretched:
                        addAttribute(XML_MATHVARIANT, u"stretched"_ustr);
                        break;
                    default:
                        declareMlError();
                        break;
                }
                break;
            }
            case SmMlAttributeValueType::MlMaxsize:
            {
                auto pSizeData = aAttribute.getMlMaxsize();
                switch (pSizeData->m_aMaxsize)
                {
                    case SmMlAttributeValueMaxsize::MlInfinity:
                    {
                        addAttribute(XML_MAXSIZE, XML_INFINITY);
                        break;
                    }
                    case SmMlAttributeValueMaxsize::MlFinite:
                    {
                        exportMlAttributeLength(XML_MAXSIZE, pSizeData->m_aLengthValue);
                        break;
                    }
                }
                break;
            }
            case SmMlAttributeValueType::MlMinsize:
            {
                auto pSizeData = aAttribute.getMlMinsize();
                exportMlAttributeLength(XML_MINSIZE, pSizeData->m_aLengthValue);
                break;
            }
            case SmMlAttributeValueType::MlMovablelimits:
            {
                auto aAttributeValue = aAttribute.getMlMovablelimits();
                switch (aAttributeValue->m_aMovablelimits)
                {
                    case SmMlAttributeValueMovablelimits::MlFalse:
                        addAttribute(XML_MOVABLELIMITS, XML_FALSE);
                        break;
                    case SmMlAttributeValueMovablelimits::MlTrue:
                        addAttribute(XML_MOVABLELIMITS, XML_TRUE);
                        break;
                    default:
                        declareMlError();
                        break;
                }
                break;
            }
            case SmMlAttributeValueType::MlRspace:
            {
                auto pSizeData = aAttribute.getMlRspace();
                exportMlAttributeLength(XML_RSPACE, pSizeData->m_aLengthValue);
                break;
            }
            case SmMlAttributeValueType::MlSeparator:
            {
                auto aAttributeValue = aAttribute.getMlSeparator();
                switch (aAttributeValue->m_aSeparator)
                {
                    case SmMlAttributeValueSeparator::MlFalse:
                        addAttribute(XML_SEPARATOR, XML_FALSE);
                        break;
                    case SmMlAttributeValueSeparator::MlTrue:
                        addAttribute(XML_SEPARATOR, XML_TRUE);
                        break;
                    default:
                        declareMlError();
                        break;
                }
                break;
            }
            case SmMlAttributeValueType::MlStretchy:
            {
                auto aAttributeValue = aAttribute.getMlStretchy();
                switch (aAttributeValue->m_aStretchy)
                {
                    case SmMlAttributeValueStretchy::MlFalse:
                        addAttribute(XML_STRETCHY, XML_FALSE);
                        break;
                    case SmMlAttributeValueStretchy::MlTrue:
                        addAttribute(XML_STRETCHY, XML_TRUE);
                        break;
                    default:
                        declareMlError();
                        break;
                }
                break;
            }
            case SmMlAttributeValueType::MlSymmetric:
            {
                auto aAttributeValue = aAttribute.getMlSymmetric();
                switch (aAttributeValue->m_aSymmetric)
                {
                    case SmMlAttributeValueSymmetric::MlFalse:
                        addAttribute(XML_SYMMETRIC, XML_FALSE);
                        break;
                    case SmMlAttributeValueSymmetric::MlTrue:
                        addAttribute(XML_SYMMETRIC, XML_TRUE);
                        break;
                    default:
                        declareMlError();
                        break;
                }
                break;
            }
            default:
                declareMlError();
                break;
        }
    }
}

SvXMLElementExport* SmMLExport::exportMlElement(const SmMlElement* pMlElement)
{
    SvXMLElementExport* pElementExport;
    switch (pMlElement->getMlElementType())
    {
        case SmMlElementType::MlMath:
            pElementExport = createElementExport(XML_MATH);
            break;
        case SmMlElementType::MlMi:
            pElementExport = createElementExport(XML_MI);
            break;
        case SmMlElementType::MlMerror:
            pElementExport = createElementExport(XML_MERROR);
            break;
        case SmMlElementType::MlMn:
            pElementExport = createElementExport(XML_MN);
            break;
        case SmMlElementType::MlMo:
            pElementExport = createElementExport(XML_MO);
            break;
        case SmMlElementType::MlMrow:
            pElementExport = createElementExport(XML_MROW);
            break;
        case SmMlElementType::MlMtext:
            pElementExport = createElementExport(XML_MTEXT);
            break;
        case SmMlElementType::MlMstyle:
            pElementExport = createElementExport(XML_MSTYLE);
            break;
        default:
            pElementExport = nullptr;
    }
    const OUString& aElementText = pMlElement->getText();
    exportMlAttributes(pMlElement);
    if (aElementText.isEmpty())
        GetDocHandler()->characters(aElementText);
    return pElementExport;
}

namespace
{
struct exportMlElementTreeExecData
{
private:
    SmMLExport* m_pSmMLExport;
    std::vector<SvXMLElementExport*> m_aSvXMLElementExportList;
    size_t m_nDepth;

public:
    inline exportMlElementTreeExecData(SmMLExport* pSmMLExport)
        : m_pSmMLExport(pSmMLExport)
        , m_aSvXMLElementExportList(1024)
        , m_nDepth(0)
    {
    }

    inline void deleteDepthData()
    {
        delete m_aSvXMLElementExportList[m_nDepth];
        --m_nDepth;
    }

    inline void setDepthData(SvXMLElementExport* aSvXMLElementExportList)
    {
        if (m_nDepth == m_aSvXMLElementExportList.size())
            m_aSvXMLElementExportList.resize(m_aSvXMLElementExportList.size() + 1024);
        m_aSvXMLElementExportList[m_nDepth] = aSvXMLElementExportList;
    }

    inline void incrementDepth() { ++m_nDepth; }

    inline SmMLExport* getSmMLExport() { return m_pSmMLExport; };
};

// end unnamed namespace

static inline void exportMlElementTreeExec(SmMlElement* aSmMlElement, void* aData)
{
    // Prepare data
    exportMlElementTreeExecData* pData = static_cast<exportMlElementTreeExecData*>(aData);
    pData->setDepthData(pData->getSmMLExport()->exportMlElement(aSmMlElement));

    // Prepare for following
    // If it has sub elements, then it will be the next
    if (aSmMlElement->getSubElementsCount() != 0)
        pData->incrementDepth();
    else // Otherwise remounts up to where it should be
    {
        while (aSmMlElement->getParentElement() != nullptr)
        {
            // get parent
            SmMlElement* pParent = aSmMlElement->getParentElement();
            pData->deleteDepthData();
            // was this the last branch ?
            if (aSmMlElement->getSubElementId() + 1 != pParent->getSubElementsCount()) // yes -> up
                break// no -> stop going up
            // Prepare for next round
            aSmMlElement = pParent;
        }
    }
}

void SmMLExport::exportMlElementTree()
{
    exportMlElementTreeExecData* aData = new exportMlElementTreeExecData(this);
    mathml::SmMlIteratorTopToBottom(m_pElementTree, exportMlElementTreeExec, aData);
    delete aData;
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Messung V0.5
C=97 H=98 G=97

¤ Dauer der Verarbeitung: 0.11 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.