1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <mathml/export.hxx>
22 #include <mathml/iterator.hxx>
25 #include <com/sun/star/beans/PropertyAttribute.hpp>
26 #include <com/sun/star/embed/ElementModes.hpp>
27 #include <com/sun/star/task/XStatusIndicator.hpp>
28 #include <com/sun/star/uno/Any.h>
29 #include <com/sun/star/util/MeasureUnit.hpp>
30 #include <com/sun/star/xml/sax/Writer.hpp>
33 #include <comphelper/genericpropertyset.hxx>
34 #include <comphelper/processfactory.hxx>
35 #include <comphelper/propertysetinfo.hxx>
36 #include <comphelper/servicehelper.hxx>
37 #include <sfx2/frame.hxx>
38 #include <sfx2/docfile.hxx>
39 #include <sfx2/sfxsids.hrc>
40 #include <svl/itemset.hxx>
41 #include <svl/stritem.hxx>
42 #include <unotools/streamwrap.hxx>
43 #include <xmloff/namespacemap.hxx>
46 #include <document.hxx>
48 #include <strings.hrc>
49 #include <unomodel.hxx>
50 #include <xparsmlbase.hxx>
51 #include <starmathdatabase.hxx>
54 #include <mathmlexport.hxx>
56 using namespace ::com::sun::star
;
57 using namespace xmloff::token
;
59 using namespace ::com::sun::star::beans
;
60 using namespace ::com::sun::star::document
;
61 using namespace ::com::sun::star::lang
;
62 using namespace ::com::sun::star::uno
;
63 using namespace ::com::sun::star
;
64 using namespace ::xmloff::token
;
67 /*************************************************************************************************/
69 bool SmMLExportWrapper::Export(SfxMedium
& rMedium
)
72 const uno::Reference
<uno::XComponentContext
>& xContext(
73 comphelper::getProcessComponentContext());
76 SAL_WARN_IF(m_xModel
== nullptr, "starmath", "Missing model");
77 SAL_WARN_IF(xContext
== nullptr, "starmath", "Missing context");
78 if (m_xModel
== nullptr || xContext
== nullptr)
82 SmDocShell
* pDocShell
= static_cast<SmDocShell
*>(m_xModel
->GetObjectShell());
83 if (pDocShell
== nullptr)
85 SAL_WARN("starmath", "Failed to fetch sm document");
89 // Check if it is a standalone window or embed object
90 bool bEmbedded
= SfxObjectCreateMode::EMBEDDED
== pDocShell
->GetCreateMode();
93 SfxItemSet
& rMediumItemSet
= rMedium
.GetItemSet();
96 uno::Reference
<task::XStatusIndicator
> xStatusIndicator
;
100 // Extra check to ensure everything is fine
101 if (pDocShell
->GetMedium() != &rMedium
)
103 SAL_WARN("starmath", "Input medium and sm document medium do not match");
107 // Fetch progress bar
108 const SfxUnoAnyItem
* pItem
= rMediumItemSet
.GetItem(SID_PROGRESS_STATUSBAR_CONTROL
);
111 // set progress range and start status indicator
112 pItem
->GetValue() >>= xStatusIndicator
;
113 xStatusIndicator
->start(SmResId(STR_STATSTR_WRITING
), 3);
114 xStatusIndicator
->setValue(0);
118 // create XPropertySet with three properties for status indicator
119 static const comphelper::PropertyMapEntry aInfoMap
[]{
120 { u
"UsePrettyPrinting"_ustr
, 0, cppu::UnoType
<bool>::get(),
121 beans::PropertyAttribute::MAYBEVOID
, 0 },
122 { u
"BaseURI"_ustr
, 0, ::cppu::UnoType
<OUString
>::get(), beans::PropertyAttribute::MAYBEVOID
,
124 { u
"StreamRelPath"_ustr
, 0, ::cppu::UnoType
<OUString
>::get(),
125 beans::PropertyAttribute::MAYBEVOID
, 0 },
126 { u
"StreamName"_ustr
, 0, ::cppu::UnoType
<OUString
>::get(),
127 beans::PropertyAttribute::MAYBEVOID
, 0 }
129 uno::Reference
<beans::XPropertySet
> xInfoSet(
130 comphelper::GenericPropertySet_CreateInstance(new comphelper::PropertySetInfo(aInfoMap
)));
132 // Always print pretty
133 xInfoSet
->setPropertyValue(u
"UsePrettyPrinting"_ustr
, Any(true));
136 xInfoSet
->setPropertyValue(u
"BaseURI"_ustr
, Any(rMedium
.GetBaseURL(true)));
138 if (!m_bFlat
) //Storage (Package) of Stream
140 // Fetch the output storage
141 uno::Reference
<embed::XStorage
> xStg
= rMedium
.GetOutputStorage();
144 SAL_WARN("starmath", "Failed to fetch output storage");
148 // TODO/LATER: handle the case of embedded links gracefully
149 if (bEmbedded
) //&& !pStg->IsRoot() )
151 const SfxStringItem
* pDocHierarchItem
152 = rMediumItemSet
.GetItem(SID_DOC_HIERARCHICALNAME
);
153 if (pDocHierarchItem
!= nullptr)
155 OUString aName
= pDocHierarchItem
->GetValue();
156 if (!aName
.isEmpty())
157 xInfoSet
->setPropertyValue(u
"StreamRelPath"_ustr
, Any(aName
));
162 // Write file metadata ( data, LO version ... )
163 // Note: export through an XML exporter component (storage version)
164 if (xStatusIndicator
.is())
165 xStatusIndicator
->setValue(1);
167 bRet
= WriteThroughComponentS(xStg
, m_xModel
, u
"meta.xml", xContext
, xInfoSet
,
168 u
"com.sun.star.comp.Math.MLOasisMetaExporter", 6);
171 // Write starmath formula
172 // Note: export through an XML exporter component (storage version)
175 if (xStatusIndicator
.is())
176 xStatusIndicator
->setValue(2);
178 if (pDocShell
->GetSmSyntaxVersion() == 5)
179 bRet
= WriteThroughComponentS(xStg
, m_xModel
, u
"content.xml", xContext
, xInfoSet
,
180 u
"com.sun.star.comp.Math.XMLContentExporter", 5);
182 bRet
= WriteThroughComponentS(xStg
, m_xModel
, u
"content.xml", xContext
, xInfoSet
,
183 u
"com.sun.star.comp.Math.MLContentExporter", 6);
186 // Write starmath settings
187 // Note: export through an XML exporter component (storage version)
190 if (xStatusIndicator
.is())
191 xStatusIndicator
->setValue(3);
193 bRet
= WriteThroughComponentS(xStg
, m_xModel
, u
"settings.xml", xContext
, xInfoSet
,
194 u
"com.sun.star.comp.Math.MLOasisSettingsExporter", 6);
199 // Fetch the output stream
200 SvStream
* pStream
= rMedium
.GetOutStream();
201 if (pStream
== nullptr)
203 SAL_WARN("starmath", "Missing output stream");
206 uno::Reference
<io::XOutputStream
> xOut(new utl::OOutputStreamWrapper(*pStream
));
208 if (xStatusIndicator
.is())
209 xStatusIndicator
->setValue(1);
211 // Write everything in the same place
212 // Note: export through an XML exporter component (output stream version)
213 if (pDocShell
->GetSmSyntaxVersion() == 5)
214 bRet
= WriteThroughComponentOS(xOut
, m_xModel
, xContext
, xInfoSet
,
215 u
"com.sun.star.comp.Math.XMLContentExporter", 5);
217 bRet
= WriteThroughComponentOS(xOut
, m_xModel
, xContext
, xInfoSet
,
218 u
"com.sun.star.comp.Math.MLContentExporter", 6);
221 if (xStatusIndicator
.is())
222 xStatusIndicator
->end();
226 OUString
SmMLExportWrapper::Export(SmMlElement
* pElementTree
)
228 const uno::Reference
<uno::XComponentContext
>& xContext(
229 comphelper::getProcessComponentContext());
232 m_pElementTree
= nullptr;
233 SAL_WARN_IF(m_xModel
== nullptr, "starmath", "Missing model");
234 SAL_WARN_IF(xContext
== nullptr, "starmath", "Missing context");
235 if (m_xModel
== nullptr || xContext
== nullptr)
239 uno::Reference
<lang::XComponent
> xModelComp
= m_xModel
;
240 SAL_WARN_IF(xModelComp
== nullptr, "starmath", "Missing model component");
241 SmModel
* pModel
= m_xModel
.get();
242 SAL_WARN_IF(pModel
== nullptr, "starmath", "Failed to get threw uno tunnel");
243 if (xModelComp
== nullptr || pModel
== nullptr)
247 SmDocShell
* pDocShell
= static_cast<SmDocShell
*>(pModel
->GetObjectShell());
248 if (pDocShell
== nullptr)
250 SAL_WARN("starmath", "Failed to fetch sm document");
254 // create XPropertySet with three properties for status indicator
255 static const comphelper::PropertyMapEntry aInfoMap
[]{
256 { u
"UsePrettyPrinting"_ustr
, 0, cppu::UnoType
<bool>::get(),
257 beans::PropertyAttribute::MAYBEVOID
, 0 },
258 { u
"BaseURI"_ustr
, 0, ::cppu::UnoType
<OUString
>::get(), beans::PropertyAttribute::MAYBEVOID
,
260 { u
"StreamRelPath"_ustr
, 0, ::cppu::UnoType
<OUString
>::get(),
261 beans::PropertyAttribute::MAYBEVOID
, 0 },
262 { u
"StreamName"_ustr
, 0, ::cppu::UnoType
<OUString
>::get(),
263 beans::PropertyAttribute::MAYBEVOID
, 0 }
265 uno::Reference
<beans::XPropertySet
> xInfoSet(
266 comphelper::GenericPropertySet_CreateInstance(new comphelper::PropertySetInfo(aInfoMap
)));
268 // Always print pretty
269 xInfoSet
->setPropertyValue(u
"UsePrettyPrinting"_ustr
, Any(true));
272 m_pElementTree
= pElementTree
;
275 // Note: export through an XML exporter component (memory stream version)
276 return WriteThroughComponentMS(xModelComp
, xContext
, xInfoSet
);
279 // export through an XML exporter component (output stream version)
280 bool SmMLExportWrapper::WriteThroughComponentOS(const Reference
<io::XOutputStream
>& xOutputStream
,
281 const Reference
<XComponent
>& xComponent
,
282 Reference
<uno::XComponentContext
> const& rxContext
,
283 Reference
<beans::XPropertySet
> const& rPropSet
,
284 const char16_t
* pComponentName
,
285 int_fast16_t nSyntaxVersion
)
287 // We need a output stream but it is already checked by caller
288 // We need a component but it is already checked by caller
289 // We need a context but it is already checked by caller
290 // We need a property set but it is already checked by caller
291 // We need a component name but it is already checked by caller
294 Reference
<xml::sax::XWriter
> xSaxWriter
= xml::sax::Writer::create(rxContext
);
296 // connect XML writer to output stream
297 xSaxWriter
->setOutputStream(xOutputStream
);
298 if (m_bUseHTMLMLEntities
)
299 xSaxWriter
->setCustomEntityNames(starmathdatabase::icustomMathmlHtmlEntitiesExport
);
301 // prepare arguments (prepend doc handler to given arguments)
302 Sequence
<Any
> aArgs
{ Any(xSaxWriter
), Any(rPropSet
) };
304 // get filter component
305 auto xExporterData
= rxContext
->getServiceManager()->createInstanceWithArgumentsAndContext(
306 OUString(pComponentName
), aArgs
, rxContext
);
307 Reference
<document::XExporter
> xExporter(xExporterData
, UNO_QUERY
);
309 // Check everything is fine
312 SAL_WARN("starmath", "can't instantiate export filter component");
316 // connect model and filter
317 xExporter
->setSourceDocument(xComponent
);
318 Reference
<XFilter
> xFilter(xExporter
, UNO_QUERY
);
319 uno::Sequence
<PropertyValue
> aProps(0);
322 if (nSyntaxVersion
== 5)
324 SmXMLExport
* pFilter
= dynamic_cast<SmXMLExport
*>(xFilter
.get());
325 if (pFilter
== nullptr)
327 SAL_WARN("starmath", "Failed to fetch SmMLExport");
330 xFilter
->filter(aProps
);
331 return pFilter
->GetSuccess();
335 SmMLExport
* pFilter
= dynamic_cast<SmMLExport
*>(xFilter
.get());
338 if (pFilter
== nullptr)
340 SAL_WARN("starmath", "Failed to fetch SmMLExport");
343 pFilter
->setUseExportTag(m_bUseExportTag
);
344 pFilter
->setElementTree(m_pElementTree
);
347 xFilter
->filter(aProps
);
348 return pFilter
->getSuccess();
351 // export through an XML exporter component (storage version)
352 bool SmMLExportWrapper::WriteThroughComponentS(const Reference
<embed::XStorage
>& xStorage
,
353 const Reference
<XComponent
>& xComponent
,
354 const char16_t
* pStreamName
,
355 Reference
<uno::XComponentContext
> const& rxContext
,
356 Reference
<beans::XPropertySet
> const& rPropSet
,
357 const char16_t
* pComponentName
,
358 int_fast16_t nSyntaxVersion
)
360 // We need a storage name but it is already checked by caller
361 // We need a component name but it is already checked by caller
362 // We need a stream name but it is already checked by caller
363 // We need a context but it is already checked by caller
364 // We need a property set but it is already checked by caller
365 // We need a component but it is already checked by caller
368 Reference
<io::XStream
> xStream
;
371 xStream
= xStorage
->openStreamElement(
372 OUString(pStreamName
), embed::ElementModes::READWRITE
| embed::ElementModes::TRUNCATE
);
374 catch (const uno::Exception
&)
376 SAL_WARN("starmath", "Can't create output stream in package");
380 // Set stream as text / xml
381 uno::Reference
<beans::XPropertySet
> xSet(xStream
, uno::UNO_QUERY
);
382 xSet
->setPropertyValue(u
"MediaType"_ustr
, Any(u
"text/xml"_ustr
));
384 // all streams must be encrypted in encrypted document
385 xSet
->setPropertyValue(u
"UseCommonStoragePasswordEncryption"_ustr
, Any(true));
388 rPropSet
->setPropertyValue(u
"StreamName"_ustr
, Any(OUString(pStreamName
)));
391 // Note: export through an XML exporter component (output stream version)
392 return WriteThroughComponentOS(xStream
->getOutputStream(), xComponent
, rxContext
, rPropSet
,
393 pComponentName
, nSyntaxVersion
);
396 // export through an XML exporter component (memory stream version)
398 SmMLExportWrapper::WriteThroughComponentMS(const Reference
<XComponent
>& xComponent
,
399 Reference
<uno::XComponentContext
> const& rxContext
,
400 Reference
<beans::XPropertySet
> const& rPropSet
)
402 // We need a component but it is already checked by caller
403 // We need a context but it is already checked by caller
404 // We need a property set it is already checked by caller
407 SvMemoryStream
aMemoryStream(8192, 1024);
408 uno::Reference
<io::XOutputStream
> xStream(new utl::OOutputStreamWrapper(aMemoryStream
));
410 // Set the stream as text
411 uno::Reference
<beans::XPropertySet
> xSet(xStream
, uno::UNO_QUERY
);
412 xSet
->setPropertyValue(u
"MediaType"_ustr
, Any(u
"text/xml"_ustr
));
415 // Note: export through an XML exporter component (output stream version)
416 bool bOk
= WriteThroughComponentOS(xStream
, xComponent
, rxContext
, rPropSet
,
417 u
"com.sun.star.comp.Mathml.MLContentExporter", 6);
419 // We don't want to read uninitialized data
423 // Recover data and generate string
424 OString
aString(static_cast<const char*>(aMemoryStream
.GetData()),
425 aMemoryStream
.GetSize() / sizeof(char));
426 return OStringToOUString(aString
, RTL_TEXTENCODING_UTF8
);
429 // SmMLExport technical
430 /*************************************************************************************************/
432 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
433 Math_MLExporter_get_implementation(css::uno::XComponentContext
* context
,
434 css::uno::Sequence
<css::uno::Any
> const&)
436 return cppu::acquire(new SmMLExport(context
, u
"com.sun.star.comp.Math.XMLExporter"_ustr
,
437 SvXMLExportFlags::OASIS
| SvXMLExportFlags::ALL
));
440 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
441 Math_MLOasisMetaExporter_get_implementation(css::uno::XComponentContext
* context
,
442 css::uno::Sequence
<css::uno::Any
> const&)
444 return cppu::acquire(new SmMLExport(context
,
445 u
"com.sun.star.comp.Math.XMLOasisMetaExporter"_ustr
,
446 SvXMLExportFlags::OASIS
| SvXMLExportFlags::META
));
449 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
450 Math_MLOasisSettingsExporter_get_implementation(css::uno::XComponentContext
* context
,
451 css::uno::Sequence
<css::uno::Any
> const&)
453 return cppu::acquire(new SmMLExport(context
,
454 u
"com.sun.star.comp.Math.XMLOasisSettingsExporter"_ustr
,
455 SvXMLExportFlags::OASIS
| SvXMLExportFlags::SETTINGS
));
458 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
459 Math_MLContentExporter_get_implementation(css::uno::XComponentContext
* context
,
460 css::uno::Sequence
<css::uno::Any
> const&)
462 return cppu::acquire(new SmMLExport(context
, u
"com.sun.star.comp.Math.XMLContentExporter"_ustr
,
463 SvXMLExportFlags::OASIS
| SvXMLExportFlags::CONTENT
));
466 SmDocShell
* SmMLExport::getSmDocShell()
468 SmModel
* pModel
= comphelper::getFromUnoTunnel
<SmModel
>(GetModel());
469 if (pModel
!= nullptr)
470 return static_cast<SmDocShell
*>(pModel
->GetObjectShell());
474 ErrCode
SmMLExport::exportDoc(enum XMLTokenEnum eClass
)
476 if (!(getExportFlags() & SvXMLExportFlags::CONTENT
))
478 // Everything that isn't the formula itself get's default export
479 SvXMLExport::exportDoc(eClass
);
483 // Checks if it has to export a particular tree
484 if (m_pElementTree
== nullptr)
487 SmDocShell
* pDocShell
= getSmDocShell();
488 if (pDocShell
!= nullptr)
489 m_pElementTree
= pDocShell
->GetMlElementTree();
493 return SVSTREAM_INVALID_PARAMETER
;
497 // Start document and encrypt if necessary
498 GetDocHandler()->startDocument();
499 addChaffWhenEncryptedStorage();
501 // make use of a default namespace
502 // Math doesn't need namespaces from xmloff, since it now uses default namespaces
503 // Because that is common with current MathML usage in the web -> ResetNamespaceMap();
504 GetNamespaceMap_().Add(u
""_ustr
, GetXMLToken(XML_N_MATH
), XML_NAMESPACE_MATH
);
509 GetAttrList().AddAttribute(GetNamespaceMap().GetAttrNameByKey(XML_NAMESPACE_MATH
),
510 GetNamespaceMap().GetNameByKey(XML_NAMESPACE_MATH
));
513 // Export and close document
515 GetDocHandler()->endDocument();
520 void SmMLExport::GetViewSettings(Sequence
<PropertyValue
>& aProps
)
522 // Get the document shell
523 SmDocShell
* pDocShell
= getSmDocShell();
524 if (pDocShell
== nullptr)
526 SAL_WARN("starmath", "Missing document shell so no view settings");
530 // Allocate enough memory
532 PropertyValue
* pValue
= aProps
.getArray();
534 // The view settings are the formula display settings
535 tools::Rectangle
aRect(pDocShell
->GetVisArea());
537 pValue
[0].Name
= "ViewAreaTop";
538 pValue
[0].Value
<<= aRect
.Top();
540 pValue
[1].Name
= "ViewAreaLeft";
541 pValue
[1].Value
<<= aRect
.Left();
543 pValue
[2].Name
= "ViewAreaWidth";
544 pValue
[2].Value
<<= aRect
.GetWidth();
546 pValue
[3].Name
= "ViewAreaHeight";
547 pValue
[3].Value
<<= aRect
.GetHeight();
550 void SmMLExport::GetConfigurationSettings(Sequence
<PropertyValue
>& rProps
)
552 // Get model property set (settings)
553 Reference
<XPropertySet
> xProps(GetModel(), UNO_QUERY
);
556 SAL_WARN("starmath", "Missing model properties so no configuration settings");
560 // Get model property set info (settings values)
561 Reference
<XPropertySetInfo
> xPropertySetInfo
= xProps
->getPropertySetInfo();
562 if (!xPropertySetInfo
.is())
564 SAL_WARN("starmath", "Missing model properties info so no configuration settings");
568 // Allocate to store the properties
569 Sequence
<Property
> aProps
= xPropertySetInfo
->getProperties();
570 const sal_Int32 nCount
= aProps
.getLength();
571 rProps
.realloc(nCount
);
572 auto pProps
= rProps
.getArray();
575 // This needs further revision
576 // Based in code mathmlexport.cxx::GetConfigurationSettings
577 for (sal_Int32 i
= 0; i
< nCount
; ++i
)
579 if (aProps
[i
].Name
!= "Formula" && aProps
[i
].Name
!= "BasicLibraries"
580 && aProps
[i
].Name
!= "DialogLibraries" && aProps
[i
].Name
!= "RuntimeUID")
582 pProps
[i
].Name
= aProps
[i
].Name
;
583 pProps
[i
].Value
= xProps
->getPropertyValue(aProps
[i
].Name
);
588 SmMLExport::SmMLExport(const css::uno::Reference
<css::uno::XComponentContext
>& rContext
,
589 OUString
const& implementationName
, SvXMLExportFlags nExportFlags
)
590 : SvXMLExport(rContext
, implementationName
, util::MeasureUnit::INCH
, XML_MATH
, nExportFlags
)
591 , m_pElementTree(nullptr)
593 , m_bUseExportTag(true)
598 /*************************************************************************************************/
600 void SmMLExport::declareMlError()
602 SAL_WARN("starmath", "Invalid use of mathml.");
606 void SmMLExport::exportMlAttributeLength(xmloff::token::XMLTokenEnum pAttribute
,
607 const SmLengthValue
& aLengthValue
)
609 if (!aLengthValue
.m_aOriginalText
->isEmpty())
611 addAttribute(pAttribute
, *aLengthValue
.m_aOriginalText
);
615 OUStringBuffer
aSizeBuffer(64);
616 aSizeBuffer
.append(aLengthValue
.m_aLengthValue
);
617 switch (aLengthValue
.m_aLengthUnit
)
619 case SmLengthUnit::MlEm
:
620 aSizeBuffer
.append(u
"em");
622 case SmLengthUnit::MlEx
:
623 aSizeBuffer
.append(u
"ex");
625 case SmLengthUnit::MlPx
:
626 aSizeBuffer
.append(u
"px");
628 case SmLengthUnit::MlIn
:
629 aSizeBuffer
.append(u
"in");
631 case SmLengthUnit::MlCm
:
632 aSizeBuffer
.append(u
"cm");
634 case SmLengthUnit::MlMm
:
635 aSizeBuffer
.append(u
"mm");
637 case SmLengthUnit::MlPt
:
638 aSizeBuffer
.append(u
"pt");
640 case SmLengthUnit::MlPc
:
641 aSizeBuffer
.append(u
"pc");
643 case SmLengthUnit::MlP
:
644 aSizeBuffer
.append(u
"%");
646 case SmLengthUnit::MlM
:
652 addAttribute(pAttribute
, aSizeBuffer
.makeStringAndClear());
656 void SmMLExport::exportMlAttributes(const SmMlElement
* pMlElement
)
658 size_t nAttributeCount
= pMlElement
->getAttributeCount();
659 for (size_t i
= 0; i
< nAttributeCount
; ++i
)
661 SmMlAttribute aAttribute
= pMlElement
->getAttribute(i
);
662 if (!aAttribute
.isSet())
665 switch (aAttribute
.getMlAttributeValueType())
667 case SmMlAttributeValueType::MlAccent
:
669 auto aAttributeValue
= aAttribute
.getMlAccent();
670 switch (aAttributeValue
->m_aAccent
)
672 case SmMlAttributeValueAccent::MlFalse
:
673 addAttribute(XML_ACCENT
, XML_FALSE
);
675 case SmMlAttributeValueAccent::MlTrue
:
676 addAttribute(XML_ACCENT
, XML_TRUE
);
684 case SmMlAttributeValueType::MlDir
:
686 auto aAttributeValue
= aAttribute
.getMlDir();
687 switch (aAttributeValue
->m_aDir
)
689 case SmMlAttributeValueDir::MlLtr
:
690 addAttribute(XML_DIR
, XML_LTR
);
692 case SmMlAttributeValueDir::MlRtl
:
693 addAttribute(XML_DIR
, XML_RTL
);
701 case SmMlAttributeValueType::MlDisplaystyle
:
703 auto aAttributeValue
= aAttribute
.getMlDisplaystyle();
704 switch (aAttributeValue
->m_aDisplaystyle
)
706 case SmMlAttributeValueDisplaystyle::MlTrue
:
707 addAttribute(XML_DISPLAYSTYLE
, XML_FALSE
);
709 case SmMlAttributeValueDisplaystyle::MlFalse
:
710 addAttribute(XML_DISPLAYSTYLE
, XML_TRUE
);
718 case SmMlAttributeValueType::MlFence
:
720 auto aAttributeValue
= aAttribute
.getMlFence();
721 switch (aAttributeValue
->m_aFence
)
723 case SmMlAttributeValueFence::MlTrue
:
724 addAttribute(XML_FENCE
, XML_FALSE
);
726 case SmMlAttributeValueFence::MlFalse
:
727 addAttribute(XML_FENCE
, XML_TRUE
);
735 case SmMlAttributeValueType::MlHref
:
737 auto aAttributeValue
= aAttribute
.getMlHref();
738 switch (aAttributeValue
->m_aHref
)
740 case SmMlAttributeValueHref::NMlEmpty
:
742 case SmMlAttributeValueHref::NMlValid
:
743 addAttribute(XML_HREF
, *aAttributeValue
->m_aLnk
);
751 case SmMlAttributeValueType::MlLspace
:
753 auto pSizeData
= aAttribute
.getMlLspace();
754 exportMlAttributeLength(XML_LSPACE
, pSizeData
->m_aLengthValue
);
757 case SmMlAttributeValueType::MlMathbackground
:
759 auto aAttributeValue
= aAttribute
.getMlMathbackground();
760 switch (aAttributeValue
->m_aMathbackground
)
762 case SmMlAttributeValueMathbackground::MlTransparent
:
763 addAttribute(XML_MATHBACKGROUND
, u
"transparent"_ustr
);
765 case SmMlAttributeValueMathbackground::MlRgb
:
767 const OUString
& rTextColor
= starmathdatabase::Identify_Color_MATHML(
768 sal_uInt32(aAttributeValue
->m_aCol
))
770 addAttribute(XML_MATHBACKGROUND
, rTextColor
);
779 case SmMlAttributeValueType::MlMathcolor
:
781 auto aAttributeValue
= aAttribute
.getMlMathcolor();
782 switch (aAttributeValue
->m_aMathcolor
)
784 case SmMlAttributeValueMathcolor::MlDefault
:
786 case SmMlAttributeValueMathcolor::MlRgb
:
788 const OUString
& rTextColor
= starmathdatabase::Identify_Color_MATHML(
789 sal_uInt32(aAttributeValue
->m_aCol
))
791 addAttribute(XML_MATHCOLOR
, rTextColor
);
800 case SmMlAttributeValueType::MlMathsize
:
802 auto pSizeData
= aAttribute
.getMlMathsize();
803 exportMlAttributeLength(XML_MATHSIZE
, pSizeData
->m_aLengthValue
);
806 case SmMlAttributeValueType::MlMathvariant
:
808 auto aAttributeValue
= aAttribute
.getMlMathvariant();
809 switch (aAttributeValue
->m_aMathvariant
)
811 case SmMlAttributeValueMathvariant::normal
:
812 addAttribute(XML_MATHVARIANT
, u
"normal"_ustr
);
814 case SmMlAttributeValueMathvariant::bold
:
815 addAttribute(XML_MATHVARIANT
, u
"bold"_ustr
);
817 case SmMlAttributeValueMathvariant::italic
:
818 addAttribute(XML_MATHVARIANT
, u
"italic"_ustr
);
820 case SmMlAttributeValueMathvariant::double_struck
:
821 addAttribute(XML_MATHVARIANT
, u
"double-struck"_ustr
);
823 case SmMlAttributeValueMathvariant::script
:
824 addAttribute(XML_MATHVARIANT
, u
"script"_ustr
);
826 case SmMlAttributeValueMathvariant::fraktur
:
827 addAttribute(XML_MATHVARIANT
, u
"fraktur"_ustr
);
829 case SmMlAttributeValueMathvariant::sans_serif
:
830 addAttribute(XML_MATHVARIANT
, u
"sans-serif"_ustr
);
832 case SmMlAttributeValueMathvariant::monospace
:
833 addAttribute(XML_MATHVARIANT
, u
"monospace"_ustr
);
835 case SmMlAttributeValueMathvariant::bold_italic
:
836 addAttribute(XML_MATHVARIANT
, u
"bold-italic"_ustr
);
838 case SmMlAttributeValueMathvariant::bold_fraktur
:
839 addAttribute(XML_MATHVARIANT
, u
"bold-fracktur"_ustr
);
841 case SmMlAttributeValueMathvariant::bold_script
:
842 addAttribute(XML_MATHVARIANT
, u
"bold-script"_ustr
);
844 case SmMlAttributeValueMathvariant::bold_sans_serif
:
845 addAttribute(XML_MATHVARIANT
, u
"bold-sans-serif"_ustr
);
847 case SmMlAttributeValueMathvariant::sans_serif_italic
:
848 addAttribute(XML_MATHVARIANT
, u
"sans-serif-italic"_ustr
);
850 case SmMlAttributeValueMathvariant::sans_serif_bold_italic
:
851 addAttribute(XML_MATHVARIANT
, u
"sans-serif-bold-italic"_ustr
);
853 case SmMlAttributeValueMathvariant::initial
:
854 addAttribute(XML_MATHVARIANT
, u
"initial"_ustr
);
856 case SmMlAttributeValueMathvariant::tailed
:
857 addAttribute(XML_MATHVARIANT
, u
"tailed"_ustr
);
859 case SmMlAttributeValueMathvariant::looped
:
860 addAttribute(XML_MATHVARIANT
, u
"looped"_ustr
);
862 case SmMlAttributeValueMathvariant::stretched
:
863 addAttribute(XML_MATHVARIANT
, u
"stretched"_ustr
);
871 case SmMlAttributeValueType::MlMaxsize
:
873 auto pSizeData
= aAttribute
.getMlMaxsize();
874 switch (pSizeData
->m_aMaxsize
)
876 case SmMlAttributeValueMaxsize::MlInfinity
:
878 addAttribute(XML_MAXSIZE
, XML_INFINITY
);
881 case SmMlAttributeValueMaxsize::MlFinite
:
883 exportMlAttributeLength(XML_MAXSIZE
, pSizeData
->m_aLengthValue
);
889 case SmMlAttributeValueType::MlMinsize
:
891 auto pSizeData
= aAttribute
.getMlMinsize();
892 exportMlAttributeLength(XML_MINSIZE
, pSizeData
->m_aLengthValue
);
895 case SmMlAttributeValueType::MlMovablelimits
:
897 auto aAttributeValue
= aAttribute
.getMlMovablelimits();
898 switch (aAttributeValue
->m_aMovablelimits
)
900 case SmMlAttributeValueMovablelimits::MlFalse
:
901 addAttribute(XML_MOVABLELIMITS
, XML_FALSE
);
903 case SmMlAttributeValueMovablelimits::MlTrue
:
904 addAttribute(XML_MOVABLELIMITS
, XML_TRUE
);
912 case SmMlAttributeValueType::MlRspace
:
914 auto pSizeData
= aAttribute
.getMlRspace();
915 exportMlAttributeLength(XML_RSPACE
, pSizeData
->m_aLengthValue
);
918 case SmMlAttributeValueType::MlSeparator
:
920 auto aAttributeValue
= aAttribute
.getMlSeparator();
921 switch (aAttributeValue
->m_aSeparator
)
923 case SmMlAttributeValueSeparator::MlFalse
:
924 addAttribute(XML_SEPARATOR
, XML_FALSE
);
926 case SmMlAttributeValueSeparator::MlTrue
:
927 addAttribute(XML_SEPARATOR
, XML_TRUE
);
935 case SmMlAttributeValueType::MlStretchy
:
937 auto aAttributeValue
= aAttribute
.getMlStretchy();
938 switch (aAttributeValue
->m_aStretchy
)
940 case SmMlAttributeValueStretchy::MlFalse
:
941 addAttribute(XML_STRETCHY
, XML_FALSE
);
943 case SmMlAttributeValueStretchy::MlTrue
:
944 addAttribute(XML_STRETCHY
, XML_TRUE
);
952 case SmMlAttributeValueType::MlSymmetric
:
954 auto aAttributeValue
= aAttribute
.getMlSymmetric();
955 switch (aAttributeValue
->m_aSymmetric
)
957 case SmMlAttributeValueSymmetric::MlFalse
:
958 addAttribute(XML_SYMMETRIC
, XML_FALSE
);
960 case SmMlAttributeValueSymmetric::MlTrue
:
961 addAttribute(XML_SYMMETRIC
, XML_TRUE
);
976 SvXMLElementExport
* SmMLExport::exportMlElement(const SmMlElement
* pMlElement
)
978 SvXMLElementExport
* pElementExport
;
979 switch (pMlElement
->getMlElementType())
981 case SmMlElementType::MlMath
:
982 pElementExport
= createElementExport(XML_MATH
);
984 case SmMlElementType::MlMi
:
985 pElementExport
= createElementExport(XML_MI
);
987 case SmMlElementType::MlMerror
:
988 pElementExport
= createElementExport(XML_MERROR
);
990 case SmMlElementType::MlMn
:
991 pElementExport
= createElementExport(XML_MN
);
993 case SmMlElementType::MlMo
:
994 pElementExport
= createElementExport(XML_MO
);
996 case SmMlElementType::MlMrow
:
997 pElementExport
= createElementExport(XML_MROW
);
999 case SmMlElementType::MlMtext
:
1000 pElementExport
= createElementExport(XML_MTEXT
);
1002 case SmMlElementType::MlMstyle
:
1003 pElementExport
= createElementExport(XML_MSTYLE
);
1006 pElementExport
= nullptr;
1008 const OUString
& aElementText
= pMlElement
->getText();
1009 exportMlAttributes(pMlElement
);
1010 if (aElementText
.isEmpty())
1011 GetDocHandler()->characters(aElementText
);
1012 return pElementExport
;
1017 struct exportMlElementTreeExecData
1020 SmMLExport
* m_pSmMLExport
;
1021 std::vector
<SvXMLElementExport
*> m_aSvXMLElementExportList
;
1025 inline exportMlElementTreeExecData(SmMLExport
* pSmMLExport
)
1026 : m_pSmMLExport(pSmMLExport
)
1027 , m_aSvXMLElementExportList(1024)
1032 inline void deleteDepthData()
1034 delete m_aSvXMLElementExportList
[m_nDepth
];
1038 inline void setDepthData(SvXMLElementExport
* aSvXMLElementExportList
)
1040 if (m_nDepth
== m_aSvXMLElementExportList
.size())
1041 m_aSvXMLElementExportList
.resize(m_aSvXMLElementExportList
.size() + 1024);
1042 m_aSvXMLElementExportList
[m_nDepth
] = aSvXMLElementExportList
;
1045 inline void incrementDepth() { ++m_nDepth
; }
1047 inline SmMLExport
* getSmMLExport() { return m_pSmMLExport
; };
1050 } // end unnamed namespace
1052 static inline void exportMlElementTreeExec(SmMlElement
* aSmMlElement
, void* aData
)
1055 exportMlElementTreeExecData
* pData
= static_cast<exportMlElementTreeExecData
*>(aData
);
1056 pData
->setDepthData(pData
->getSmMLExport()->exportMlElement(aSmMlElement
));
1058 // Prepare for following
1059 // If it has sub elements, then it will be the next
1060 if (aSmMlElement
->getSubElementsCount() != 0)
1061 pData
->incrementDepth();
1062 else // Otherwise remounts up to where it should be
1064 while (aSmMlElement
->getParentElement() != nullptr)
1067 SmMlElement
* pParent
= aSmMlElement
->getParentElement();
1068 pData
->deleteDepthData();
1069 // was this the last branch ?
1070 if (aSmMlElement
->getSubElementId() + 1 != pParent
->getSubElementsCount()) // yes -> up
1071 break; // no -> stop going up
1072 // Prepare for next round
1073 aSmMlElement
= pParent
;
1078 void SmMLExport::exportMlElementTree()
1080 exportMlElementTreeExecData
* aData
= new exportMlElementTreeExecData(this);
1081 mathml::SmMlIteratorTopToBottom(m_pElementTree
, exportMlElementTreeExec
, aData
);
1085 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */