bump product version to 4.1.6.2
[LibreOffice.git] / starmath / source / mathmlexport.cxx
blob35fb1efafca46d5634d42dde7d3cb0a1eaee7457
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 .
22 Warning: The SvXMLElementExport helper class creates the beginning and
23 closing tags of xml elements in its constructor and destructor, so theres
24 hidden stuff going on, on occasion the ordering of these classes declarations
25 may be significant
29 #include <com/sun/star/xml/sax/XErrorHandler.hpp>
30 #include <com/sun/star/xml/sax/XEntityResolver.hpp>
31 #include <com/sun/star/xml/sax/InputSource.hpp>
32 #include <com/sun/star/xml/sax/XDTDHandler.hpp>
33 #include <com/sun/star/xml/sax/XParser.hpp>
34 #include <com/sun/star/xml/sax/Writer.hpp>
35 #include <com/sun/star/io/XActiveDataSource.hpp>
36 #include <com/sun/star/io/XActiveDataControl.hpp>
37 #include <com/sun/star/document/XDocumentProperties.hpp>
38 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
39 #include <com/sun/star/packages/zip/ZipIOException.hpp>
40 #include <com/sun/star/task/XStatusIndicatorFactory.hpp>
41 #include <com/sun/star/beans/PropertyAttribute.hpp>
42 #include <com/sun/star/container/XNameAccess.hpp>
43 #include <com/sun/star/embed/ElementModes.hpp>
44 #include <com/sun/star/util/MeasureUnit.hpp>
45 #include <com/sun/star/uno/Any.h>
47 #include <rtl/math.hxx>
48 #include <sfx2/frame.hxx>
49 #include <sfx2/docfile.hxx>
50 #include <osl/diagnose.h>
51 #include <svtools/sfxecode.hxx>
52 #include <unotools/saveopt.hxx>
53 #include <svl/stritem.hxx>
54 #include <svl/itemprop.hxx>
55 #include <comphelper/componentcontext.hxx>
56 #include <comphelper/processfactory.hxx>
57 #include <unotools/streamwrap.hxx>
58 #include <sax/tools/converter.hxx>
59 #include <xmloff/xmlnmspe.hxx>
60 #include <xmloff/xmltoken.hxx>
61 #include <xmloff/nmspmap.hxx>
62 #include <xmloff/attrlist.hxx>
63 #include <xmloff/xmlmetai.hxx>
64 #include <osl/mutex.hxx>
65 #include <comphelper/genericpropertyset.hxx>
66 #include <comphelper/servicehelper.hxx>
68 #include <memory>
70 #include "mathmlexport.hxx"
71 #include <starmath.hrc>
72 #include <unomodel.hxx>
73 #include <document.hxx>
74 #include <utility.hxx>
75 #include <config.hxx>
77 using namespace ::com::sun::star::beans;
78 using namespace ::com::sun::star::container;
79 using namespace ::com::sun::star::document;
80 using namespace ::com::sun::star::lang;
81 using namespace ::com::sun::star::uno;
82 using namespace ::com::sun::star;
83 using namespace ::xmloff::token;
86 #define EXPORT_SVC_NAME "com.sun.star.xml.XMLExportFilter"
88 #undef WANTEXCEPT
91 ////////////////////////////////////////////////////////////
93 sal_Bool SmXMLExportWrapper::Export(SfxMedium &rMedium)
95 sal_Bool bRet=sal_True;
96 uno::Reference<uno::XComponentContext> xContext(comphelper::getProcessComponentContext());
98 //Get model
99 uno::Reference< lang::XComponent > xModelComp(xModel, uno::UNO_QUERY );
101 sal_Bool bEmbedded = sal_False;
102 uno::Reference <lang::XUnoTunnel> xTunnel;
103 xTunnel = uno::Reference <lang::XUnoTunnel> (xModel,uno::UNO_QUERY);
104 SmModel *pModel = reinterpret_cast<SmModel *>
105 (xTunnel->getSomething(SmModel::getUnoTunnelId()));
107 SmDocShell *pDocShell = pModel ?
108 static_cast<SmDocShell*>(pModel->GetObjectShell()) : 0;
109 if ( pDocShell &&
110 SFX_CREATE_MODE_EMBEDDED == pDocShell->GetCreateMode() )
111 bEmbedded = sal_True;
113 uno::Reference<task::XStatusIndicator> xStatusIndicator;
114 if (!bEmbedded)
116 if (pDocShell /*&& pDocShell->GetMedium()*/)
118 OSL_ENSURE( pDocShell->GetMedium() == &rMedium,
119 "different SfxMedium found" );
121 SfxItemSet* pSet = rMedium.GetItemSet();
122 if (pSet)
124 const SfxUnoAnyItem* pItem = static_cast<const SfxUnoAnyItem*>(
125 pSet->GetItem(SID_PROGRESS_STATUSBAR_CONTROL) );
126 if (pItem)
127 pItem->GetValue() >>= xStatusIndicator;
131 // set progress range and start status indicator
132 if (xStatusIndicator.is())
134 sal_Int32 nProgressRange = bFlat ? 1 : 3;
135 xStatusIndicator->start(SM_RESSTR(STR_STATSTR_WRITING),
136 nProgressRange);
141 // create XPropertySet with three properties for status indicator
142 comphelper::PropertyMapEntry aInfoMap[] =
144 { "UsePrettyPrinting", sizeof("UsePrettyPrinting")-1, 0,
145 &::getBooleanCppuType(),
146 beans::PropertyAttribute::MAYBEVOID, 0},
147 { "BaseURI", sizeof("BaseURI")-1, 0,
148 &::getCppuType( (OUString *)0 ),
149 beans::PropertyAttribute::MAYBEVOID, 0 },
150 { "StreamRelPath", sizeof("StreamRelPath")-1, 0,
151 &::getCppuType( (OUString *)0 ),
152 beans::PropertyAttribute::MAYBEVOID, 0 },
153 { "StreamName", sizeof("StreamName")-1, 0,
154 &::getCppuType( (OUString *)0 ),
155 beans::PropertyAttribute::MAYBEVOID, 0 },
156 { NULL, 0, 0, NULL, 0, 0 }
158 uno::Reference< beans::XPropertySet > xInfoSet(
159 comphelper::GenericPropertySet_CreateInstance(
160 new comphelper::PropertySetInfo( aInfoMap ) ) );
162 SvtSaveOptions aSaveOpt;
163 OUString sUsePrettyPrinting("UsePrettyPrinting");
164 sal_Bool bUsePrettyPrinting( bFlat || aSaveOpt.IsPrettyPrinting() );
165 Any aAny;
166 aAny.setValue( &bUsePrettyPrinting, ::getBooleanCppuType() );
167 xInfoSet->setPropertyValue( sUsePrettyPrinting, aAny );
169 // Set base URI
170 OUString sPropName( "BaseURI" );
171 xInfoSet->setPropertyValue( sPropName, makeAny( rMedium.GetBaseURL( true ) ) );
173 sal_Int32 nSteps=0;
174 if (xStatusIndicator.is())
175 xStatusIndicator->setValue(nSteps++);
176 if (!bFlat) //Storage (Package) of Stream
178 uno::Reference < embed::XStorage > xStg = rMedium.GetOutputStorage();
179 sal_Bool bOASIS = ( SotStorage::GetVersion( xStg ) > SOFFICE_FILEFORMAT_60 );
181 // TODO/LATER: handle the case of embedded links gracefully
182 if ( bEmbedded ) //&& !pStg->IsRoot() )
184 OUString aName;
185 if ( rMedium.GetItemSet() )
187 const SfxStringItem* pDocHierarchItem = static_cast<const SfxStringItem*>(
188 rMedium.GetItemSet()->GetItem(SID_DOC_HIERARCHICALNAME) );
189 if ( pDocHierarchItem )
190 aName = pDocHierarchItem->GetValue();
193 if ( !aName.isEmpty() )
195 sPropName = "StreamRelPath";
196 xInfoSet->setPropertyValue( sPropName, makeAny( aName ) );
200 if ( !bEmbedded )
202 if (xStatusIndicator.is())
203 xStatusIndicator->setValue(nSteps++);
205 bRet = WriteThroughComponent(
206 xStg, xModelComp, "meta.xml", xContext, xInfoSet,
207 (bOASIS ? "com.sun.star.comp.Math.XMLOasisMetaExporter"
208 : "com.sun.star.comp.Math.XMLMetaExporter"));
210 if ( bRet )
212 if (xStatusIndicator.is())
213 xStatusIndicator->setValue(nSteps++);
215 bRet = WriteThroughComponent(
216 xStg, xModelComp, "content.xml", xContext, xInfoSet,
217 "com.sun.star.comp.Math.XMLContentExporter");
220 if ( bRet )
222 if (xStatusIndicator.is())
223 xStatusIndicator->setValue(nSteps++);
225 bRet = WriteThroughComponent(
226 xStg, xModelComp, "settings.xml", xContext, xInfoSet,
227 (bOASIS ? "com.sun.star.comp.Math.XMLOasisSettingsExporter"
228 : "com.sun.star.comp.Math.XMLSettingsExporter") );
231 else
233 SvStream *pStream = rMedium.GetOutStream();
234 uno::Reference<io::XOutputStream> xOut(
235 new utl::OOutputStreamWrapper(*pStream) );
237 if (xStatusIndicator.is())
238 xStatusIndicator->setValue(nSteps++);
240 bRet = WriteThroughComponent(
241 xOut, xModelComp, xContext, xInfoSet,
242 "com.sun.star.comp.Math.XMLContentExporter");
245 if (xStatusIndicator.is())
246 xStatusIndicator->end();
248 return bRet;
252 /// export through an XML exporter component (output stream version)
253 sal_Bool SmXMLExportWrapper::WriteThroughComponent(
254 Reference<io::XOutputStream> xOutputStream,
255 Reference<XComponent> xComponent,
256 Reference<uno::XComponentContext> & rxContext,
257 Reference<beans::XPropertySet> & rPropSet,
258 const sal_Char* pComponentName )
260 OSL_ENSURE(xOutputStream.is(), "I really need an output stream!");
261 OSL_ENSURE(xComponent.is(), "Need component!");
262 OSL_ENSURE(NULL != pComponentName, "Need component name!");
264 // get component
265 Reference< xml::sax::XWriter > xSaxWriter = xml::sax::Writer::create(rxContext );
267 // connect XML writer to output stream
268 xSaxWriter->setOutputStream( xOutputStream );
270 // prepare arguments (prepend doc handler to given arguments)
271 Reference<xml::sax::XDocumentHandler> xDocHandler( xSaxWriter,UNO_QUERY);
273 Sequence<Any> aArgs( 2 );
274 aArgs[0] <<= xDocHandler;
275 aArgs[1] <<= rPropSet;
277 // get filter component
278 Reference< document::XExporter > xExporter(
279 rxContext->getServiceManager()->createInstanceWithArgumentsAndContext(OUString::createFromAscii(pComponentName), aArgs, rxContext),
280 UNO_QUERY);
281 OSL_ENSURE( xExporter.is(),
282 "can't instantiate export filter component" );
283 if ( !xExporter.is() )
284 return sal_False;
287 // connect model and filter
288 xExporter->setSourceDocument( xComponent );
290 // filter!
291 Reference < XFilter > xFilter( xExporter, UNO_QUERY );
292 uno::Sequence< PropertyValue > aProps(0);
293 xFilter->filter( aProps );
295 uno::Reference<lang::XUnoTunnel> xFilterTunnel;
296 xFilterTunnel = uno::Reference<lang::XUnoTunnel>
297 ( xFilter, uno::UNO_QUERY );
298 SmXMLExport *pFilter = reinterpret_cast< SmXMLExport * >(
299 sal::static_int_cast< sal_uIntPtr >(
300 xFilterTunnel->getSomething( SmXMLExport::getUnoTunnelId() )));
301 return pFilter ? pFilter->GetSuccess() : sal_True;
305 /// export through an XML exporter component (storage version)
306 sal_Bool SmXMLExportWrapper::WriteThroughComponent(
307 const Reference < embed::XStorage >& xStorage,
308 Reference<XComponent> xComponent,
309 const sal_Char* pStreamName,
310 Reference<uno::XComponentContext> & rxContext,
311 Reference<beans::XPropertySet> & rPropSet,
312 const sal_Char* pComponentName
315 OSL_ENSURE(xStorage.is(), "Need storage!");
316 OSL_ENSURE(NULL != pStreamName, "Need stream name!");
318 // open stream
319 Reference < io::XStream > xStream;
320 OUString sStreamName = OUString::createFromAscii(pStreamName);
323 xStream = xStorage->openStreamElement( sStreamName,
324 embed::ElementModes::READWRITE | embed::ElementModes::TRUNCATE );
326 catch ( uno::Exception& )
328 OSL_FAIL( "Can't create output stream in package!" );
329 return sal_False;
332 OUString aPropName( "MediaType" );
333 OUString aMime( "text/xml" );
334 uno::Any aAny;
335 aAny <<= aMime;
337 uno::Reference < beans::XPropertySet > xSet( xStream, uno::UNO_QUERY );
338 xSet->setPropertyValue( aPropName, aAny );
340 // all streams must be encrypted in encrypted document
341 OUString aTmpPropName( "UseCommonStoragePasswordEncryption" );
342 sal_Bool bTrue = sal_True;
343 aAny.setValue( &bTrue, ::getBooleanCppuType() );
344 xSet->setPropertyValue( aTmpPropName, aAny );
346 // set Base URL
347 if ( rPropSet.is() )
349 OUString sPropName( "StreamName" );
350 rPropSet->setPropertyValue( sPropName, makeAny( sStreamName ) );
353 // write the stuff
354 sal_Bool bRet = WriteThroughComponent( xStream->getOutputStream(), xComponent, rxContext,
355 rPropSet, pComponentName );
357 return bRet;
360 ////////////////////////////////////////////////////////////
362 SmXMLExport::SmXMLExport(
363 const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > xContext,
364 sal_uInt16 nExportFlags)
365 : SvXMLExport(util::MeasureUnit::INCH, xContext, XML_MATH,
366 nExportFlags)
367 , pTree(0) ,
368 bSuccess(sal_False)
372 sal_Int64 SAL_CALL SmXMLExport::getSomething(
373 const uno::Sequence< sal_Int8 >& rId )
374 throw(uno::RuntimeException)
376 if ( rId.getLength() == 16 &&
377 0 == memcmp( getUnoTunnelId().getConstArray(),
378 rId.getConstArray(), 16 ) )
379 return sal::static_int_cast< sal_Int64 >(reinterpret_cast< sal_uIntPtr >(this));
381 return SvXMLExport::getSomething( rId );
384 namespace
386 class theSmXMLExportUnoTunnelId : public rtl::Static< UnoTunnelIdInit, theSmXMLExportUnoTunnelId> {};
389 const uno::Sequence< sal_Int8 > & SmXMLExport::getUnoTunnelId() throw()
391 return theSmXMLExportUnoTunnelId::get().getSeq();
394 OUString SAL_CALL SmXMLExport_getImplementationName() throw()
396 return OUString( "com.sun.star.comp.Math.XMLExporter" );
399 uno::Sequence< OUString > SAL_CALL SmXMLExport_getSupportedServiceNames()
400 throw()
402 const OUString aServiceName( EXPORT_SVC_NAME );
403 const uno::Sequence< OUString > aSeq( &aServiceName, 1 );
404 return aSeq;
407 uno::Reference< uno::XInterface > SAL_CALL SmXMLExport_createInstance(
408 const uno::Reference< lang::XMultiServiceFactory > & rSMgr)
409 throw( uno::Exception )
411 // EXPORT_OASIS is required here allthough there is no differrence between
412 // OOo and OASIS, because without the flag, a transformation to OOo would
413 // be chained in.
414 return (cppu::OWeakObject*)new SmXMLExport( comphelper::getComponentContext(rSMgr), EXPORT_OASIS|EXPORT_ALL );
417 ////////////////////////////////////////////////////////////
419 OUString SAL_CALL SmXMLExportMetaOOO_getImplementationName() throw()
421 return OUString( "com.sun.star.comp.Math.XMLMetaExporter" );
424 uno::Sequence< OUString > SAL_CALL SmXMLExportMetaOOO_getSupportedServiceNames()
425 throw()
427 const OUString aServiceName( EXPORT_SVC_NAME );
428 const uno::Sequence< OUString > aSeq( &aServiceName, 1 );
429 return aSeq;
432 uno::Reference< uno::XInterface > SAL_CALL SmXMLExportMetaOOO_createInstance(
433 const uno::Reference< lang::XMultiServiceFactory > & rSMgr)
434 throw( uno::Exception )
436 return (cppu::OWeakObject*)new SmXMLExport( comphelper::getComponentContext(rSMgr), EXPORT_META );
439 ////////////////////////////////////////////////////////////
441 OUString SAL_CALL SmXMLExportMeta_getImplementationName() throw()
443 return OUString( "com.sun.star.comp.Math.XMLOasisMetaExporter" );
446 uno::Sequence< OUString > SAL_CALL SmXMLExportMeta_getSupportedServiceNames()
447 throw()
449 const OUString aServiceName( EXPORT_SVC_NAME );
450 const uno::Sequence< OUString > aSeq( &aServiceName, 1 );
451 return aSeq;
454 uno::Reference< uno::XInterface > SAL_CALL SmXMLExportMeta_createInstance(
455 const uno::Reference< lang::XMultiServiceFactory > & rSMgr)
456 throw( uno::Exception )
458 return (cppu::OWeakObject*)new SmXMLExport( comphelper::getComponentContext(rSMgr), EXPORT_OASIS|EXPORT_META );
461 ////////////////////////////////////////////////////////////
463 OUString SAL_CALL SmXMLExportSettingsOOO_getImplementationName() throw()
465 return OUString( "com.sun.star.comp.Math.XMLSettingsExporter" );
468 uno::Sequence< OUString > SAL_CALL SmXMLExportSettingsOOO_getSupportedServiceNames()
469 throw()
471 const OUString aServiceName( EXPORT_SVC_NAME );
472 const uno::Sequence< OUString > aSeq( &aServiceName, 1 );
473 return aSeq;
476 uno::Reference< uno::XInterface > SAL_CALL SmXMLExportSettingsOOO_createInstance(
477 const uno::Reference< lang::XMultiServiceFactory > & rSMgr)
478 throw( uno::Exception )
480 return (cppu::OWeakObject*)new SmXMLExport( comphelper::getComponentContext(rSMgr), EXPORT_SETTINGS );
483 ////////////////////////////////////////////////////////////
485 OUString SAL_CALL SmXMLExportSettings_getImplementationName() throw()
487 return OUString( "com.sun.star.comp.Math.XMLOasisSettingsExporter" );
490 uno::Sequence< OUString > SAL_CALL SmXMLExportSettings_getSupportedServiceNames()
491 throw()
493 const OUString aServiceName( EXPORT_SVC_NAME );
494 const uno::Sequence< OUString > aSeq( &aServiceName, 1 );
495 return aSeq;
498 uno::Reference< uno::XInterface > SAL_CALL SmXMLExportSettings_createInstance(
499 const uno::Reference< lang::XMultiServiceFactory > & rSMgr)
500 throw( uno::Exception )
502 return (cppu::OWeakObject*)new SmXMLExport( comphelper::getComponentContext(rSMgr), EXPORT_OASIS|EXPORT_SETTINGS );
505 ////////////////////////////////////////////////////////////
507 OUString SAL_CALL SmXMLExportContent_getImplementationName() throw()
509 return OUString( "com.sun.star.comp.Math.XMLContentExporter" );
512 uno::Sequence< OUString > SAL_CALL SmXMLExportContent_getSupportedServiceNames()
513 throw()
515 const OUString aServiceName( EXPORT_SVC_NAME );
516 const uno::Sequence< OUString > aSeq( &aServiceName, 1 );
517 return aSeq;
520 uno::Reference< uno::XInterface > SAL_CALL SmXMLExportContent_createInstance(
521 const uno::Reference< lang::XMultiServiceFactory > & rSMgr)
522 throw( uno::Exception )
524 // The EXPORT_OASIS flag is only required to avoid that a transformer is
525 // chanied in
526 return (cppu::OWeakObject*)new SmXMLExport( comphelper::getComponentContext(rSMgr), EXPORT_OASIS|EXPORT_CONTENT );
529 ////////////////////////////////////////////////////////////
531 // XServiceInfo
532 // override empty method from parent class
533 OUString SAL_CALL SmXMLExport::getImplementationName()
534 throw(uno::RuntimeException)
536 OUString aTxt;
537 switch( getExportFlags() )
539 case EXPORT_META:
540 aTxt = SmXMLExportMeta_getImplementationName();
541 break;
542 case EXPORT_SETTINGS:
543 aTxt = SmXMLExportSettings_getImplementationName();
544 break;
545 case EXPORT_CONTENT:
546 aTxt = SmXMLExportContent_getImplementationName();
547 break;
548 case EXPORT_ALL:
549 default:
550 aTxt = SmXMLExport_getImplementationName();
551 break;
553 return aTxt;
556 sal_uInt32 SmXMLExport::exportDoc(enum XMLTokenEnum eClass)
558 if ( (getExportFlags() & EXPORT_CONTENT) == 0 )
560 SvXMLExport::exportDoc( eClass );
562 else
564 uno::Reference <frame::XModel> xModel = GetModel();
565 uno::Reference <lang::XUnoTunnel> xTunnel;
566 xTunnel = uno::Reference <lang::XUnoTunnel> (xModel,uno::UNO_QUERY);
567 SmModel *pModel = reinterpret_cast<SmModel *>
568 (xTunnel->getSomething(SmModel::getUnoTunnelId()));
570 if (pModel)
572 SmDocShell *pDocShell =
573 static_cast<SmDocShell*>(pModel->GetObjectShell());
574 pTree = pDocShell->GetFormulaTree();
575 aText = pDocShell->GetText();
578 GetDocHandler()->startDocument();
580 addChaffWhenEncryptedStorage();
582 /*Add xmlns line*/
583 SvXMLAttributeList &rList = GetAttrList();
585 // make use of a default namespace
586 ResetNamespaceMap(); // Math doesn't need namespaces from xmloff, since it now uses default namespaces (because that is common with current MathML usage in the web)
587 _GetNamespaceMap().Add( OUString(), GetXMLToken(XML_N_MATH), XML_NAMESPACE_MATH );
589 rList.AddAttribute(GetNamespaceMap().GetAttrNameByKey(XML_NAMESPACE_MATH_IDX),
590 GetNamespaceMap().GetNameByKey( XML_NAMESPACE_MATH_IDX));
592 //I think we need something like ImplExportEntities();
593 _ExportContent();
594 GetDocHandler()->endDocument();
597 bSuccess=sal_True;
598 return 0;
601 void SmXMLExport::_ExportContent()
603 SvXMLElementExport aEquation(*this, XML_NAMESPACE_MATH, XML_MATH, sal_True, sal_True);
604 SvXMLElementExport *pSemantics=0;
606 if (aText.Len())
608 pSemantics = new SvXMLElementExport(*this, XML_NAMESPACE_MATH,
609 XML_SEMANTICS, sal_True, sal_True);
612 ExportNodes(pTree, 0);
614 if (aText.Len())
616 // Convert symbol names
617 uno::Reference <frame::XModel> xModel = GetModel();
618 uno::Reference <lang::XUnoTunnel> xTunnel;
619 xTunnel = uno::Reference <lang::XUnoTunnel> (xModel,uno::UNO_QUERY);
620 SmModel *pModel = reinterpret_cast<SmModel *>
621 (xTunnel->getSomething(SmModel::getUnoTunnelId()));
622 SmDocShell *pDocShell = pModel ?
623 static_cast<SmDocShell*>(pModel->GetObjectShell()) : 0;
624 OSL_ENSURE( pDocShell, "doc shell missing" );
625 if (pDocShell)
627 SmParser &rParser = pDocShell->GetParser();
628 bool bVal = rParser.IsExportSymbolNames();
629 rParser.SetExportSymbolNames( true );
630 SmNode *pTmpTree = rParser.Parse( aText );
631 aText = rParser.GetText();
632 delete pTmpTree;
633 rParser.SetExportSymbolNames( bVal );
636 AddAttribute(XML_NAMESPACE_MATH, XML_ENCODING,
637 OUString("StarMath 5.0"));
638 SvXMLElementExport aAnnotation(*this, XML_NAMESPACE_MATH,
639 XML_ANNOTATION, sal_True, sal_False);
640 GetDocHandler()->characters(OUString( aText ));
642 delete pSemantics;
645 void SmXMLExport::GetViewSettings( Sequence < PropertyValue >& aProps)
647 uno::Reference <frame::XModel> xModel = GetModel();
648 if ( !xModel.is() )
649 return;
651 uno::Reference <lang::XUnoTunnel> xTunnel;
652 xTunnel = uno::Reference <lang::XUnoTunnel> (xModel,uno::UNO_QUERY);
653 SmModel *pModel = reinterpret_cast<SmModel *>
654 (xTunnel->getSomething(SmModel::getUnoTunnelId()));
656 if ( !pModel )
657 return;
659 SmDocShell *pDocShell =
660 static_cast<SmDocShell*>(pModel->GetObjectShell());
661 if ( !pDocShell )
662 return;
664 aProps.realloc( 4 );
665 PropertyValue *pValue = aProps.getArray();
666 sal_Int32 nIndex = 0;
668 Rectangle aRect( pDocShell->GetVisArea() );
670 pValue[nIndex].Name = "ViewAreaTop";
671 pValue[nIndex++].Value <<= aRect.Top();
673 pValue[nIndex].Name = "ViewAreaLeft";
674 pValue[nIndex++].Value <<= aRect.Left();
676 pValue[nIndex].Name = "ViewAreaWidth";
677 pValue[nIndex++].Value <<= aRect.GetWidth();
679 pValue[nIndex].Name = "ViewAreaHeight";
680 pValue[nIndex++].Value <<= aRect.GetHeight();
683 void SmXMLExport::GetConfigurationSettings( Sequence < PropertyValue > & rProps)
685 Reference < XPropertySet > xProps ( GetModel(), UNO_QUERY );
686 if ( xProps.is() )
688 Reference< XPropertySetInfo > xPropertySetInfo = xProps->getPropertySetInfo();
689 if (xPropertySetInfo.is())
691 Sequence< Property > aProps = xPropertySetInfo->getProperties();
692 sal_Int32 nCount(aProps.getLength());
693 if (nCount > 0)
695 rProps.realloc(nCount);
696 PropertyValue* pProps = rProps.getArray();
697 if (pProps)
699 SmConfig *pConfig = SM_MOD()->GetConfig();
700 const bool bUsedSymbolsOnly = pConfig ? pConfig->IsSaveOnlyUsedSymbols() : false;
702 const OUString sFormula ( "Formula" );
703 const OUString sBasicLibraries ( "BasicLibraries" );
704 const OUString sDialogLibraries ( "DialogLibraries" );
705 const OUString sRuntimeUID ( "RuntimeUID" );
706 for (sal_Int32 i = 0; i < nCount; i++, pProps++)
708 const OUString &rPropName = aProps[i].Name;
709 if (rPropName != sFormula &&
710 rPropName != sBasicLibraries &&
711 rPropName != sDialogLibraries &&
712 rPropName != sRuntimeUID)
714 pProps->Name = rPropName;
716 OUString aActualName( rPropName );
718 // handle 'save used symbols only'
719 if (bUsedSymbolsOnly && rPropName == "Symbols" )
720 aActualName = "UserDefinedSymbolsInUse";
722 pProps->Value = xProps->getPropertyValue( aActualName );
731 void SmXMLExport::ExportLine(const SmNode *pNode, int nLevel)
733 ExportExpression(pNode, nLevel);
736 void SmXMLExport::ExportBinaryHorizontal(const SmNode *pNode, int nLevel)
738 ExportExpression(pNode, nLevel);
741 void SmXMLExport::ExportUnaryHorizontal(const SmNode *pNode, int nLevel)
743 ExportExpression(pNode, nLevel);
746 void SmXMLExport::ExportExpression(const SmNode *pNode, int nLevel)
748 SvXMLElementExport *pRow=0;
749 sal_uLong nSize = pNode->GetNumSubNodes();
751 // #i115443: nodes of type expression always need to be grouped with mrow statement
752 if (nSize > 1 || (pNode && pNode->GetType() == NEXPRESSION))
753 pRow = new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MROW, sal_True, sal_True);
755 for (sal_uInt16 i = 0; i < nSize; i++)
756 if (const SmNode *pTemp = pNode->GetSubNode(i))
757 ExportNodes(pTemp, nLevel+1);
759 delete pRow;
762 void SmXMLExport::ExportBinaryVertical(const SmNode *pNode, int nLevel)
764 OSL_ENSURE(pNode->GetNumSubNodes()==3,"Bad Fraction");
765 SvXMLElementExport aFraction(*this, XML_NAMESPACE_MATH, XML_MFRAC, sal_True, sal_True);
766 ExportNodes(pNode->GetSubNode(0), nLevel);
767 ExportNodes(pNode->GetSubNode(2), nLevel);
770 void SmXMLExport::ExportTable(const SmNode *pNode, int nLevel)
772 SvXMLElementExport *pTable=0;
774 sal_uInt16 nSize = pNode->GetNumSubNodes();
776 //If the list ends in newline then the last entry has
777 //no subnodes, the newline is superfulous so we just drop
778 //the last node, inclusion would create a bad MathML
779 //table
780 if (nSize >= 1 && pNode->GetSubNode(nSize-1)->GetNumSubNodes() == 0)
781 --nSize;
783 // try to avoid creating a mtable element when the formula consists only
784 // of a single output line
785 if (nLevel || (nSize >1))
786 pTable = new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MTABLE, sal_True, sal_True);
788 for (sal_uInt16 i = 0; i < nSize; i++)
789 if (const SmNode *pTemp = pNode->GetSubNode(i))
791 SvXMLElementExport *pRow=0;
792 SvXMLElementExport *pCell=0;
793 if (pTable)
795 pRow = new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MTR, sal_True, sal_True);
796 pCell = new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MTD, sal_True, sal_True);
798 ExportNodes(pTemp, nLevel+1);
799 delete pCell;
800 delete pRow;
803 delete pTable;
806 void SmXMLExport::ExportMath(const SmNode *pNode, int /*nLevel*/)
808 const SmMathSymbolNode *pTemp = static_cast<const SmMathSymbolNode *>(pNode);
809 SvXMLElementExport aMath(*this, XML_NAMESPACE_MATH, XML_MO, sal_True, sal_False);
810 sal_Unicode nArse[2];
811 nArse[0] = pTemp->GetText()[0];
812 sal_Unicode cTmp = ConvertMathToMathML( nArse[0] );
813 if (cTmp != 0)
814 nArse[0] = cTmp;
815 OSL_ENSURE(nArse[0] != 0xffff,"Non existent symbol");
816 nArse[1] = 0;
817 GetDocHandler()->characters(nArse);
820 void SmXMLExport::ExportText(const SmNode *pNode, int /*nLevel*/)
822 SvXMLElementExport *pText;
823 const SmTextNode *pTemp = static_cast<const SmTextNode *>(pNode);
824 switch (pNode->GetToken().eType)
826 default:
827 case TIDENT:
829 //Note that we change the fontstyle to italic for strings that
830 //are italic and longer than a single character.
831 sal_Bool bIsItalic = IsItalic( pTemp->GetFont() );
832 if ((pTemp->GetText().getLength() > 1) && bIsItalic)
833 AddAttribute(XML_NAMESPACE_MATH, XML_MATHVARIANT, XML_ITALIC);
834 else if ((pTemp->GetText().getLength() == 1) && !bIsItalic)
835 AddAttribute(XML_NAMESPACE_MATH, XML_MATHVARIANT, XML_NORMAL);
836 pText = new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MI,sal_True,sal_False);
837 break;
839 case TNUMBER:
840 pText = new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MN,sal_True,sal_False);
841 break;
842 case TTEXT:
843 pText = new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MTEXT,sal_True,sal_False);
844 break;
846 GetDocHandler()->characters(pTemp->GetText());
847 delete pText;
850 void SmXMLExport::ExportBlank(const SmNode * /*pNode*/, int /*nLevel*/)
852 //!! exports an empty <mi> tag since for example "~_~" is allowed in
853 //!! Math (so it has no sense at all) but must not result in an empty
854 //!! <msub> tag in MathML !!
856 SvXMLElementExport *pText;
858 pText = new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MI, sal_True, sal_False);
860 GetDocHandler()->characters( OUString() );
861 delete pText;
864 void SmXMLExport::ExportSubSupScript(const SmNode *pNode, int nLevel)
866 const SmNode *pSub = 0;
867 const SmNode *pSup = 0;
868 const SmNode *pCSub = 0;
869 const SmNode *pCSup = 0;
870 const SmNode *pLSub = 0;
871 const SmNode *pLSup = 0;
872 SvXMLElementExport *pThing = 0, *pThing2 = 0;
874 //if we have prescripts at all then we must use the tensor notation
876 //This is one of those excellent locations where scope is vital to
877 //arrange the construction and destruction of the element helper
878 //classes correctly
879 pLSub = pNode->GetSubNode(LSUB+1);
880 pLSup = pNode->GetSubNode(LSUP+1);
881 if (pLSub || pLSup)
883 SvXMLElementExport aMultiScripts(*this, XML_NAMESPACE_MATH,
884 XML_MMULTISCRIPTS, sal_True, sal_True);
887 if (NULL != (pCSub = pNode->GetSubNode(CSUB+1))
888 && NULL != (pCSup = pNode->GetSubNode(CSUP+1)))
890 pThing2 = new SvXMLElementExport(*this, XML_NAMESPACE_MATH,
891 XML_MUNDEROVER, sal_True,sal_True);
893 else if (NULL != (pCSub = pNode->GetSubNode(CSUB+1)))
895 pThing2 = new SvXMLElementExport(*this, XML_NAMESPACE_MATH,
896 XML_MUNDER, sal_True,sal_True);
898 else if (NULL != (pCSup = pNode->GetSubNode(CSUP+1)))
900 pThing2 = new SvXMLElementExport(*this, XML_NAMESPACE_MATH,
901 XML_MOVER, sal_True,sal_True);
904 ExportNodes(pNode->GetSubNode(0), nLevel+1); //Main Term
906 if (pCSub)
907 ExportNodes(pCSub, nLevel+1);
908 if (pCSup)
909 ExportNodes(pCSup, nLevel+1);
910 delete pThing2;
912 pSub = pNode->GetSubNode(RSUB+1);
913 pSup = pNode->GetSubNode(RSUP+1);
914 if (pSub || pSup)
916 if (pSub)
917 ExportNodes(pSub, nLevel+1);
918 else
920 SvXMLElementExport aNone(*this, XML_NAMESPACE_MATH, XML_NONE,sal_True,sal_True);
922 if (pSup)
923 ExportNodes(pSup, nLevel+1);
924 else
926 SvXMLElementExport aNone(*this, XML_NAMESPACE_MATH, XML_NONE,sal_True,sal_True);
930 //Separator element between suffix and prefix sub/sup pairs
932 SvXMLElementExport aPrescripts(*this, XML_NAMESPACE_MATH,
933 XML_MPRESCRIPTS, sal_True,sal_True);
936 if (pLSub)
937 ExportNodes(pLSub, nLevel+1);
938 else
940 SvXMLElementExport aNone(*this, XML_NAMESPACE_MATH, XML_NONE,
941 sal_True,sal_True);
944 if (pLSup)
945 ExportNodes(pLSup, nLevel+1);
946 else
948 SvXMLElementExport aNone(*this, XML_NAMESPACE_MATH, XML_NONE,
949 sal_True,sal_True);
953 else
955 if (NULL != (pSub = pNode->GetSubNode(RSUB+1)) &&
956 NULL != (pSup = pNode->GetSubNode(RSUP+1)))
958 pThing = new SvXMLElementExport(*this, XML_NAMESPACE_MATH,
959 XML_MSUBSUP, sal_True,sal_True);
961 else if (NULL != (pSub = pNode->GetSubNode(RSUB+1)))
963 pThing = new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MSUB,
964 sal_True,sal_True);
966 else if (NULL != (pSup = pNode->GetSubNode(RSUP+1)))
968 pThing = new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MSUP,
969 sal_True,sal_True);
972 if (NULL != (pCSub = pNode->GetSubNode(CSUB+1))
973 && NULL != (pCSup=pNode->GetSubNode(CSUP+1)))
975 pThing2 = new SvXMLElementExport(*this, XML_NAMESPACE_MATH,
976 XML_MUNDEROVER, sal_True,sal_True);
978 else if (NULL != (pCSub = pNode->GetSubNode(CSUB+1)))
980 pThing2 = new SvXMLElementExport(*this, XML_NAMESPACE_MATH,
981 XML_MUNDER, sal_True,sal_True);
983 else if (NULL != (pCSup = pNode->GetSubNode(CSUP+1)))
985 pThing2 = new SvXMLElementExport(*this, XML_NAMESPACE_MATH,
986 XML_MOVER, sal_True,sal_True);
988 ExportNodes(pNode->GetSubNode(0), nLevel+1); //Main Term
990 if (pCSub)
991 ExportNodes(pCSub, nLevel+1);
992 if (pCSup)
993 ExportNodes(pCSup, nLevel+1);
994 delete pThing2;
996 if (pSub)
997 ExportNodes(pSub, nLevel+1);
998 if (pSup)
999 ExportNodes(pSup, nLevel+1);
1000 delete pThing;
1004 void SmXMLExport::ExportBrace(const SmNode *pNode, int nLevel)
1006 const SmNode *pTemp;
1007 const SmNode *pLeft=pNode->GetSubNode(0);
1008 const SmNode *pRight=pNode->GetSubNode(2);
1009 SvXMLElementExport *pFences=0,*pRow=0;
1010 if ( ((pLeft) && (pLeft->GetToken().eType != TNONE)) &&
1011 ((pRight) && (pRight->GetToken().eType != TNONE)) &&
1012 (pNode->GetScaleMode() == SCALE_HEIGHT))
1014 sal_Unicode nArse[2];
1015 nArse[1] = 0;
1016 nArse[0] = static_cast<
1017 const SmMathSymbolNode* >(pLeft)->GetText()[0];
1018 OSL_ENSURE(nArse[0] != 0xffff,"Non existent symbol");
1019 AddAttribute(XML_NAMESPACE_MATH, XML_OPEN,nArse);
1020 nArse[0] = static_cast<
1021 const SmMathSymbolNode* >(pRight)->GetText()[0];
1022 OSL_ENSURE(nArse[0] != 0xffff,"Non existent symbol");
1023 AddAttribute(XML_NAMESPACE_MATH, XML_CLOSE,nArse);
1024 pFences = new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MFENCED,
1025 sal_True,sal_True);
1027 else if (pLeft && (pLeft->GetToken().eType != TNONE))
1029 pRow = new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MROW,
1030 sal_True, sal_True);
1031 if (pNode->GetScaleMode() == SCALE_HEIGHT)
1032 AddAttribute(XML_NAMESPACE_MATH, XML_STRETCHY, XML_TRUE);
1033 else
1034 AddAttribute(XML_NAMESPACE_MATH, XML_STRETCHY, XML_FALSE);
1035 ExportNodes(pLeft, nLevel+1);
1037 else
1038 pRow = new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MROW,
1039 sal_True, sal_True);
1041 if (NULL != (pTemp = pNode->GetSubNode(1)))
1042 ExportNodes(pTemp, nLevel+1);
1043 if (pFences)
1044 delete pFences;
1045 else if (pRight && (pRight->GetToken().eType != TNONE))
1047 if (pNode->GetScaleMode() == SCALE_HEIGHT)
1048 AddAttribute(XML_NAMESPACE_MATH, XML_STRETCHY, XML_TRUE);
1049 else
1050 AddAttribute(XML_NAMESPACE_MATH, XML_STRETCHY, XML_FALSE);
1051 ExportNodes(pRight, nLevel+1);
1053 delete pRow;
1056 void SmXMLExport::ExportRoot(const SmNode *pNode, int nLevel)
1058 if (pNode->GetSubNode(0))
1060 SvXMLElementExport aRoot(*this, XML_NAMESPACE_MATH, XML_MROOT,sal_True,
1061 sal_True);
1062 ExportNodes(pNode->GetSubNode(2), nLevel+1);
1063 ExportNodes(pNode->GetSubNode(0), nLevel+1);
1065 else
1067 SvXMLElementExport aSqrt(*this, XML_NAMESPACE_MATH, XML_MSQRT,sal_True,
1068 sal_True);
1069 ExportNodes(pNode->GetSubNode(2), nLevel+1);
1073 void SmXMLExport::ExportOperator(const SmNode *pNode, int nLevel)
1075 /*we need to either use content or font and size attributes
1076 *here*/
1077 SvXMLElementExport aRow(*this, XML_NAMESPACE_MATH, XML_MROW,
1078 sal_True, sal_True);
1079 ExportNodes(pNode->GetSubNode(0), nLevel+1);
1080 ExportNodes(pNode->GetSubNode(1), nLevel+1);
1083 void SmXMLExport::ExportAttributes(const SmNode *pNode, int nLevel)
1085 SvXMLElementExport *pElement=0;
1087 if (pNode->GetToken().eType == TUNDERLINE)
1089 AddAttribute(XML_NAMESPACE_MATH, XML_ACCENTUNDER,
1090 XML_TRUE);
1091 pElement = new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MUNDER,
1092 sal_True,sal_True);
1094 else if (pNode->GetToken().eType != TOVERSTRIKE)
1096 AddAttribute(XML_NAMESPACE_MATH, XML_ACCENT,
1097 XML_TRUE);
1098 pElement = new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MOVER,
1099 sal_True,sal_True);
1102 ExportNodes(pNode->GetSubNode(1), nLevel+1);
1103 switch (pNode->GetToken().eType)
1105 case TOVERLINE:
1107 //proper entity support required
1108 SvXMLElementExport aMath(*this, XML_NAMESPACE_MATH, XML_MO,
1109 sal_True,sal_True);
1110 sal_Unicode nArse[2] = {0xAF,0x00};
1111 GetDocHandler()->characters(nArse);
1113 break;
1114 case TUNDERLINE:
1116 //proper entity support required
1117 SvXMLElementExport aMath(*this, XML_NAMESPACE_MATH, XML_MO,
1118 sal_True,sal_True);
1119 sal_Unicode nArse[2] = {0x0332,0x00};
1120 GetDocHandler()->characters(nArse);
1122 break;
1123 case TOVERSTRIKE:
1124 break;
1125 default:
1126 ExportNodes(pNode->GetSubNode(0), nLevel+1);
1127 break;
1129 delete pElement;
1132 static bool lcl_HasEffectOnMathvariant( const SmTokenType eType )
1134 return eType == TBOLD || eType == TNBOLD ||
1135 eType == TITALIC || eType == TNITALIC ||
1136 eType == TSANS || eType == TSERIF || eType == TFIXED;
1139 void SmXMLExport::ExportFont(const SmNode *pNode, int nLevel)
1141 SvXMLElementExport *pElement = 0;
1144 // gather the mathvariant attribut relevant data from all
1145 // successively following SmFontNodes...
1147 int nBold = -1; // for the following variables: -1 = yet undefined; 0 = false; 1 = true;
1148 int nItalic = -1; // for the following variables: -1 = yet undefined; 0 = false; 1 = true;
1149 int nSansSerifFixed = -1;
1150 SmTokenType eNodeType = TUNKNOWN;
1151 while (lcl_HasEffectOnMathvariant( (eNodeType = pNode->GetToken().eType) ))
1153 switch (eNodeType)
1155 case TBOLD : nBold = 1; break;
1156 case TNBOLD : nBold = 0; break;
1157 case TITALIC : nItalic = 1; break;
1158 case TNITALIC : nItalic = 0; break;
1159 case TSANS : nSansSerifFixed = 0; break;
1160 case TSERIF : nSansSerifFixed = 1; break;
1161 case TFIXED : nSansSerifFixed = 2; break;
1162 default:
1163 OSL_FAIL( "unexpected case" );
1165 // According to the parser every node that is to be evaluated heres
1166 // has a single non-zero subnode at index 1!! Thus we only need to check
1167 // that single node for follow-up nodes that have an effect on the attribute.
1168 if (pNode->GetNumSubNodes() > 1 && pNode->GetSubNode(1) &&
1169 lcl_HasEffectOnMathvariant( pNode->GetSubNode(1)->GetToken().eType))
1171 pNode = pNode->GetSubNode(1);
1173 else
1174 break;
1177 switch (pNode->GetToken().eType)
1179 //wrap a phantom element around everything*/
1180 case TPHANTOM:
1181 pElement = new SvXMLElementExport(*this, XML_NAMESPACE_MATH,
1182 XML_MPHANTOM, sal_True,sal_True);
1183 break;
1184 case TBLACK:
1185 AddAttribute(XML_NAMESPACE_MATH, XML_COLOR, XML_BLACK);
1186 break;
1187 case TWHITE:
1188 AddAttribute(XML_NAMESPACE_MATH, XML_COLOR, XML_WHITE);
1189 break;
1190 case TRED:
1191 AddAttribute(XML_NAMESPACE_MATH, XML_COLOR, XML_RED);
1192 break;
1193 case TGREEN:
1194 AddAttribute(XML_NAMESPACE_MATH, XML_COLOR, XML_GREEN);
1195 break;
1196 case TBLUE:
1197 AddAttribute(XML_NAMESPACE_MATH, XML_COLOR, XML_BLUE);
1198 break;
1199 case TCYAN:
1200 AddAttribute(XML_NAMESPACE_MATH, XML_COLOR, XML_AQUA);
1201 break;
1202 case TMAGENTA:
1203 AddAttribute(XML_NAMESPACE_MATH, XML_COLOR, XML_FUCHSIA);
1204 break;
1205 case TYELLOW:
1206 AddAttribute(XML_NAMESPACE_MATH, XML_COLOR, XML_YELLOW);
1207 break;
1208 case TSIZE:
1210 const SmFontNode *pFontNode = static_cast<const SmFontNode *>(pNode);
1211 const Fraction &aFrac = pFontNode->GetSizeParameter();
1213 OUStringBuffer sStrBuf;
1214 switch(pFontNode->GetSizeType())
1216 case FNTSIZ_MULTIPLY:
1217 ::sax::Converter::convertDouble(sStrBuf,
1218 static_cast<double>(aFrac*Fraction(100.00)));
1219 sStrBuf.append(static_cast<sal_Unicode>('%'));
1220 break;
1221 case FNTSIZ_DIVIDE:
1222 ::sax::Converter::convertDouble(sStrBuf,
1223 static_cast<double>(Fraction(100.00)/aFrac));
1224 sStrBuf.append(static_cast<sal_Unicode>('%'));
1225 break;
1226 case FNTSIZ_ABSOLUT:
1227 ::sax::Converter::convertDouble(sStrBuf,
1228 static_cast<double>(aFrac));
1229 sStrBuf.append(
1230 GetXMLToken(XML_UNIT_PT));
1231 break;
1232 default:
1234 //The problem here is that the wheels fall off because
1235 //font size is stored in 100th's of a mm not pts, and
1236 //rounding errors take their toll on the original
1237 //value specified in points.
1239 //Must fix StarMath to retain the original pt values
1240 Fraction aTemp = Sm100th_mmToPts(pFontNode->GetFont().
1241 GetSize().Height());
1243 if (pFontNode->GetSizeType() == FNTSIZ_MINUS)
1244 aTemp-=aFrac;
1245 else
1246 aTemp+=aFrac;
1248 double mytest = static_cast<double>(aTemp);
1250 mytest = ::rtl::math::round(mytest,1);
1251 ::sax::Converter::convertDouble(sStrBuf,mytest);
1252 sStrBuf.append(GetXMLToken(XML_UNIT_PT));
1254 break;
1257 OUString sStr(sStrBuf.makeStringAndClear());
1258 AddAttribute(XML_NAMESPACE_MATH, XML_MATHSIZE, sStr);
1260 break;
1261 case TBOLD:
1262 case TITALIC:
1263 case TNBOLD:
1264 case TNITALIC:
1265 case TFIXED:
1266 case TSANS:
1267 case TSERIF:
1269 // nBold: -1 = yet undefined; 0 = false; 1 = true;
1270 // nItalic: -1 = yet undefined; 0 = false; 1 = true;
1271 // nSansSerifFixed: -1 = undefined; 0 = sans; 1 = serif; 2 = fixed;
1272 const sal_Char *pText = "normal";
1273 if (nSansSerifFixed == -1 || nSansSerifFixed == 1)
1275 pText = "normal";
1276 if (nBold == 1 && nItalic != 1)
1277 pText = "bold";
1278 else if (nBold != 1 && nItalic == 1)
1279 pText = "italic";
1280 else if (nBold == 1 && nItalic == 1)
1281 pText = "bold-italic";
1283 else if (nSansSerifFixed == 0)
1285 pText = "sans-serif";
1286 if (nBold == 1 && nItalic != 1)
1287 pText = "bold-sans-serif";
1288 else if (nBold != 1 && nItalic == 1)
1289 pText = "sans-serif-italic";
1290 else if (nBold == 1 && nItalic == 1)
1291 pText = "sans-serif-bold-italic";
1293 else if (nSansSerifFixed == 2)
1294 pText = "monospace"; // no modifiers allowed for monospace ...
1295 else
1297 OSL_FAIL( "unexpected case" );
1299 AddAttribute(XML_NAMESPACE_MATH, XML_MATHVARIANT, OUString::createFromAscii( pText ));
1301 break;
1302 default:
1303 break;
1306 //for now we will just always export with a style and not worry about
1307 //anyone else for the moment.
1309 //wrap a style around it
1310 SvXMLElementExport aStyle(*this, XML_NAMESPACE_MATH, XML_MSTYLE, sal_True,sal_True);
1311 ExportExpression(pNode, nLevel);
1314 delete pElement;
1318 void SmXMLExport::ExportVerticalBrace(const SmNode *pNode, int nLevel)
1320 //Place the overbrace value OVER a vertical brace and then place that
1321 //expression OVER the overbrace value, If someone can find a
1322 //dedicated term in MathML to handle this overbrace/underbrace concept
1323 //let me know. C.
1324 XMLTokenEnum which;
1326 switch (pNode->GetToken().eType)
1328 case TOVERBRACE:
1329 default:
1330 which = XML_MOVER;
1331 break;
1332 case TUNDERBRACE:
1333 which = XML_MUNDER;
1334 break;
1337 OSL_ENSURE(pNode->GetNumSubNodes()==3,"Bad Vertical Brace");
1338 SvXMLElementExport aOver1(*this, XML_NAMESPACE_MATH,which, sal_True, sal_True);
1339 {//Scoping
1340 // using accents will draw the over-/underbraces too close to the base
1341 // see http://www.w3.org/TR/MathML2/chapter3.html#id.3.4.5.2
1342 // also XML_ACCENT is illegal with XML_MUNDER. Thus no XML_ACCENT attribut here!
1343 SvXMLElementExport aOver2(*this, XML_NAMESPACE_MATH,which, sal_True, sal_True);
1344 ExportNodes(pNode->GetSubNode(0), nLevel);
1345 ExportNodes(pNode->GetSubNode(1), nLevel);
1347 ExportNodes(pNode->GetSubNode(2), nLevel);
1350 void SmXMLExport::ExportMatrix(const SmNode *pNode, int nLevel)
1352 SvXMLElementExport aTable(*this, XML_NAMESPACE_MATH, XML_MTABLE, sal_True, sal_True);
1353 const SmMatrixNode *pMatrix = static_cast<const SmMatrixNode *>(pNode);
1354 sal_uInt16 i=0;
1355 for (sal_uLong y = 0; y < pMatrix->GetNumRows(); y++)
1357 SvXMLElementExport aRow(*this, XML_NAMESPACE_MATH, XML_MTR, sal_True, sal_True);
1358 for (sal_uLong x = 0; x < pMatrix->GetNumCols(); x++)
1359 if (const SmNode *pTemp = pNode->GetSubNode(i++))
1361 SvXMLElementExport aCell(*this, XML_NAMESPACE_MATH, XML_MTD, sal_True, sal_True);
1362 ExportNodes(pTemp, nLevel+1);
1367 void SmXMLExport::ExportNodes(const SmNode *pNode, int nLevel)
1369 if (!pNode)
1370 return;
1371 switch(pNode->GetType())
1373 case NTABLE:
1374 ExportTable(pNode, nLevel);
1375 break;
1376 case NALIGN:
1377 case NBRACEBODY:
1378 case NEXPRESSION:
1379 ExportExpression(pNode, nLevel);
1380 break;
1381 case NLINE:
1382 ExportLine(pNode, nLevel);
1383 break;
1384 case NTEXT:
1385 ExportText(pNode, nLevel);
1386 break;
1387 case NSPECIAL: //NSPECIAL requires some sort of Entity preservation in the XML engine.
1388 case NGLYPH_SPECIAL:
1389 case NMATH:
1391 sal_Unicode cTmp = 0;
1392 const SmTextNode *pTemp = static_cast< const SmTextNode * >(pNode);
1393 if (!pTemp->GetText().isEmpty())
1394 cTmp = ConvertMathToMathML( pTemp->GetText()[0] );
1395 if (cTmp == 0)
1397 // no conversion to MathML implemented -> export it as text
1398 // thus at least it will not vanish into nothing
1399 ExportText(pNode, nLevel);
1401 else
1403 //To fully handle generic MathML we need to implement the full
1404 //operator dictionary, we will generate MathML with explicit
1405 //stretchiness for now.
1406 sal_Int16 nLength = GetAttrList().getLength();
1407 sal_Bool bAddStretch=sal_True;
1408 for ( sal_Int16 i = 0; i < nLength; i++ )
1410 OUString sLocalName;
1411 sal_uInt16 nPrefix = GetNamespaceMap().GetKeyByAttrName(
1412 GetAttrList().getNameByIndex(i), &sLocalName );
1414 if ( ( XML_NAMESPACE_MATH == nPrefix ) &&
1415 IsXMLToken(sLocalName, XML_STRETCHY) )
1417 bAddStretch = sal_False;
1418 break;
1421 if (bAddStretch)
1423 AddAttribute(XML_NAMESPACE_MATH, XML_STRETCHY, XML_FALSE);
1425 ExportMath(pNode, nLevel);
1428 break;
1429 case NPLACE:
1430 ExportMath(pNode, nLevel);
1431 break;
1432 case NBINHOR:
1433 ExportBinaryHorizontal(pNode, nLevel);
1434 break;
1435 case NUNHOR:
1436 ExportUnaryHorizontal(pNode, nLevel);
1437 break;
1438 case NBRACE:
1439 ExportBrace(pNode, nLevel);
1440 break;
1441 case NBINVER:
1442 ExportBinaryVertical(pNode, nLevel);
1443 break;
1444 case NSUBSUP:
1445 ExportSubSupScript(pNode, nLevel);
1446 break;
1447 case NROOT:
1448 ExportRoot(pNode, nLevel);
1449 break;
1450 case NOPER:
1451 ExportOperator(pNode, nLevel);
1452 break;
1453 case NATTRIBUT:
1454 ExportAttributes(pNode, nLevel);
1455 break;
1456 case NFONT:
1457 ExportFont(pNode, nLevel);
1458 break;
1459 case NVERTICAL_BRACE:
1460 ExportVerticalBrace(pNode, nLevel);
1461 break;
1462 case NMATRIX:
1463 ExportMatrix(pNode, nLevel);
1464 break;
1465 case NBLANK:
1466 ExportBlank(pNode, nLevel);
1467 break;
1468 default:
1469 OSL_FAIL( "Warning: failed to export a node?" );
1470 break;
1475 ////////////////////////////////////////////////////////////
1477 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */