2010-10-14 08:30:41 +02:00
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2012-07-04 15:25:45 +01:00
/*
* 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 .
*/
2010-02-12 16:56:44 +01:00
/*
Warning : The SvXMLElementExport helper class creates the beginning and
2015-07-02 18:25:02 +02:00
closing tags of xml elements in its constructor and destructor , so there ' s
2010-02-12 16:56:44 +01:00
hidden stuff going on , on occasion the ordering of these classes declarations
may be significant
*/
# include <com/sun/star/xml/sax/XErrorHandler.hpp>
# include <com/sun/star/xml/sax/XEntityResolver.hpp>
# include <com/sun/star/xml/sax/InputSource.hpp>
# include <com/sun/star/xml/sax/XDTDHandler.hpp>
# include <com/sun/star/xml/sax/XParser.hpp>
2012-10-10 10:13:18 +02:00
# include <com/sun/star/xml/sax/Writer.hpp>
2010-02-12 16:56:44 +01:00
# include <com/sun/star/io/XActiveDataSource.hpp>
# include <com/sun/star/io/XActiveDataControl.hpp>
# include <com/sun/star/document/XDocumentProperties.hpp>
# include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
# include <com/sun/star/packages/zip/ZipIOException.hpp>
# include <com/sun/star/task/XStatusIndicatorFactory.hpp>
# include <com/sun/star/beans/PropertyAttribute.hpp>
# include <com/sun/star/container/XNameAccess.hpp>
# include <com/sun/star/embed/ElementModes.hpp>
2011-10-11 14:19:09 +02:00
# include <com/sun/star/util/MeasureUnit.hpp>
2010-02-12 16:56:44 +01:00
# include <com/sun/star/uno/Any.h>
# include <rtl/math.hxx>
# include <sfx2/frame.hxx>
# include <sfx2/docfile.hxx>
2010-10-07 11:02:05 +01:00
# include <osl/diagnose.h>
2010-02-12 16:56:44 +01:00
# include <svtools/sfxecode.hxx>
# include <unotools/saveopt.hxx>
# include <svl/stritem.hxx>
# include <svl/itemprop.hxx>
2011-11-14 11:49:31 +01:00
# include <comphelper/processfactory.hxx>
2010-02-12 16:56:44 +01:00
# include <unotools/streamwrap.hxx>
#i108468#: clean up xmluconv code duplication, part 1:
move convertNumber64 from SvXMLUnitConverter to sax::converter.
remove duplicate methods from SvXMLUnitConverter:
convertBool, convertPercent, convertColor, convertNumber, convertDouble,
indexOfComma, encodeBase64, decodeBase64, decodeBase64SomeChars,
clearUndefinedChars
2011-10-11 14:19:00 +02:00
# include <sax/tools/converter.hxx>
2010-02-12 16:56:44 +01:00
# include <xmloff/xmlnmspe.hxx>
# include <xmloff/xmltoken.hxx>
# include <xmloff/nmspmap.hxx>
# include <xmloff/attrlist.hxx>
# include <xmloff/xmlmetai.hxx>
# include <osl/mutex.hxx>
# include <comphelper/genericpropertyset.hxx>
2011-04-04 12:23:43 +01:00
# include <comphelper/servicehelper.hxx>
2010-02-12 16:56:44 +01:00
# include <memory>
2014-11-25 19:18:01 -05:00
# include <stack>
2010-02-12 16:56:44 +01:00
# include "mathmlexport.hxx"
2014-04-14 21:37:24 +02:00
# include "register.hxx"
2010-02-12 16:56:44 +01:00
# include <starmath.hrc>
# include <unomodel.hxx>
# include <document.hxx>
# include <utility.hxx>
2015-05-26 08:38:37 +02:00
# include "cfgitem.hxx"
2010-02-12 16:56:44 +01:00
using namespace : : com : : sun : : star : : beans ;
using namespace : : com : : sun : : star : : container ;
using namespace : : com : : sun : : star : : document ;
using namespace : : com : : sun : : star : : lang ;
using namespace : : com : : sun : : star : : uno ;
using namespace : : com : : sun : : star ;
using namespace : : xmloff : : token ;
2013-08-14 23:12:27 -03:00
sal_Unicode ConvertMathToMathML ( sal_Unicode cChar )
{
sal_Unicode cRes = cChar ;
if ( IsInPrivateUseArea ( cChar ) )
{
SAL_WARN ( " starmath " , " Error: private use area characters should no longer be in use! " ) ;
cRes = ( sal_Unicode ) ' @ ' ; // just some character that should easily be notice as odd in the context
}
return cRes ;
}
2010-02-12 16:56:44 +01:00
2014-04-24 12:22:08 +02:00
bool SmXMLExportWrapper : : Export ( SfxMedium & rMedium )
2010-02-12 16:56:44 +01:00
{
2014-04-24 12:22:08 +02:00
bool bRet = true ;
2013-01-03 13:41:37 +02:00
uno : : Reference < uno : : XComponentContext > xContext ( comphelper : : getProcessComponentContext ( ) ) ;
2010-02-12 16:56:44 +01:00
//Get model
uno : : Reference < lang : : XComponent > xModelComp ( xModel , uno : : UNO_QUERY ) ;
2014-04-24 12:22:08 +02:00
bool bEmbedded = false ;
2010-02-12 16:56:44 +01:00
uno : : Reference < lang : : XUnoTunnel > xTunnel ;
xTunnel = uno : : Reference < lang : : XUnoTunnel > ( xModel , uno : : UNO_QUERY ) ;
SmModel * pModel = reinterpret_cast < SmModel * >
( xTunnel - > getSomething ( SmModel : : getUnoTunnelId ( ) ) ) ;
SmDocShell * pDocShell = pModel ?
static_cast < SmDocShell * > ( pModel - > GetObjectShell ( ) ) : 0 ;
if ( pDocShell & &
2015-04-09 15:24:21 +02:00
SfxObjectCreateMode : : EMBEDDED = = pDocShell - > GetCreateMode ( ) )
2014-04-24 12:22:08 +02:00
bEmbedded = true ;
2010-02-12 16:56:44 +01:00
uno : : Reference < task : : XStatusIndicator > xStatusIndicator ;
if ( ! bEmbedded )
{
if ( pDocShell /*&& pDocShell->GetMedium()*/ )
{
2010-10-07 11:02:05 +01:00
OSL_ENSURE ( pDocShell - > GetMedium ( ) = = & rMedium ,
2010-02-12 16:56:44 +01:00
" different SfxMedium found " ) ;
SfxItemSet * pSet = rMedium . GetItemSet ( ) ;
if ( pSet )
{
const SfxUnoAnyItem * pItem = static_cast < const SfxUnoAnyItem * > (
pSet - > GetItem ( SID_PROGRESS_STATUSBAR_CONTROL ) ) ;
if ( pItem )
pItem - > GetValue ( ) > > = xStatusIndicator ;
}
}
// set progress range and start status indicator
if ( xStatusIndicator . is ( ) )
{
sal_Int32 nProgressRange = bFlat ? 1 : 3 ;
2012-10-01 22:09:35 +04:00
xStatusIndicator - > start ( SM_RESSTR ( STR_STATSTR_WRITING ) ,
2010-02-12 16:56:44 +01:00
nProgressRange ) ;
}
}
// create XPropertySet with three properties for status indicator
comphelper : : PropertyMapEntry aInfoMap [ ] =
{
2013-12-11 15:16:51 +01:00
{ OUString ( " UsePrettyPrinting " ) , 0 ,
2015-04-01 08:41:06 +02:00
cppu : : UnoType < bool > : : get ( ) ,
2010-02-12 16:56:44 +01:00
beans : : PropertyAttribute : : MAYBEVOID , 0 } ,
2013-12-11 15:16:51 +01:00
{ OUString ( " BaseURI " ) , 0 ,
2014-05-10 00:14:44 +02:00
: : cppu : : UnoType < OUString > : : get ( ) ,
2010-02-12 16:56:44 +01:00
beans : : PropertyAttribute : : MAYBEVOID , 0 } ,
2013-12-11 15:16:51 +01:00
{ OUString ( " StreamRelPath " ) , 0 ,
2014-05-10 00:14:44 +02:00
: : cppu : : UnoType < OUString > : : get ( ) ,
2010-02-12 16:56:44 +01:00
beans : : PropertyAttribute : : MAYBEVOID , 0 } ,
2013-12-11 15:16:51 +01:00
{ OUString ( " StreamName " ) , 0 ,
2014-05-10 00:14:44 +02:00
: : cppu : : UnoType < OUString > : : get ( ) ,
2010-02-12 16:56:44 +01:00
beans : : PropertyAttribute : : MAYBEVOID , 0 } ,
2013-12-11 15:16:51 +01:00
{ OUString ( ) , 0 , css : : uno : : Type ( ) , 0 , 0 }
2010-02-12 16:56:44 +01:00
} ;
uno : : Reference < beans : : XPropertySet > xInfoSet (
comphelper : : GenericPropertySet_CreateInstance (
new comphelper : : PropertySetInfo ( aInfoMap ) ) ) ;
SvtSaveOptions aSaveOpt ;
2012-03-08 14:56:00 +01:00
OUString sUsePrettyPrinting ( " UsePrettyPrinting " ) ;
2010-02-12 16:56:44 +01:00
sal_Bool bUsePrettyPrinting ( bFlat | | aSaveOpt . IsPrettyPrinting ( ) ) ;
Any aAny ;
2015-04-01 08:41:06 +02:00
aAny . setValue ( & bUsePrettyPrinting , cppu : : UnoType < bool > : : get ( ) ) ;
2010-02-12 16:56:44 +01:00
xInfoSet - > setPropertyValue ( sUsePrettyPrinting , aAny ) ;
// Set base URI
2012-03-08 14:56:00 +01:00
OUString sPropName ( " BaseURI " ) ;
2010-02-12 16:56:44 +01:00
xInfoSet - > setPropertyValue ( sPropName , makeAny ( rMedium . GetBaseURL ( true ) ) ) ;
sal_Int32 nSteps = 0 ;
if ( xStatusIndicator . is ( ) )
xStatusIndicator - > setValue ( nSteps + + ) ;
if ( ! bFlat ) //Storage (Package) of Stream
{
uno : : Reference < embed : : XStorage > xStg = rMedium . GetOutputStorage ( ) ;
2014-04-24 12:22:08 +02:00
bool bOASIS = ( SotStorage : : GetVersion ( xStg ) > SOFFICE_FILEFORMAT_60 ) ;
2010-02-12 16:56:44 +01:00
// TODO/LATER: handle the case of embedded links gracefully
if ( bEmbedded ) //&& !pStg->IsRoot() )
{
OUString aName ;
if ( rMedium . GetItemSet ( ) )
{
const SfxStringItem * pDocHierarchItem = static_cast < const SfxStringItem * > (
rMedium . GetItemSet ( ) - > GetItem ( SID_DOC_HIERARCHICALNAME ) ) ;
if ( pDocHierarchItem )
aName = pDocHierarchItem - > GetValue ( ) ;
}
2012-01-11 11:37:33 -02:00
if ( ! aName . isEmpty ( ) )
2010-02-12 16:56:44 +01:00
{
2012-03-08 14:56:00 +01:00
sPropName = " StreamRelPath " ;
2010-02-12 16:56:44 +01:00
xInfoSet - > setPropertyValue ( sPropName , makeAny ( aName ) ) ;
}
}
if ( ! bEmbedded )
{
if ( xStatusIndicator . is ( ) )
xStatusIndicator - > setValue ( nSteps + + ) ;
bRet = WriteThroughComponent (
2013-01-03 13:41:37 +02:00
xStg , xModelComp , " meta.xml " , xContext , xInfoSet ,
2010-02-12 16:56:44 +01:00
( bOASIS ? " com.sun.star.comp.Math.XMLOasisMetaExporter "
2012-11-14 16:42:11 +01:00
: " com.sun.star.comp.Math.XMLMetaExporter " ) ) ;
2010-02-12 16:56:44 +01:00
}
if ( bRet )
{
if ( xStatusIndicator . is ( ) )
xStatusIndicator - > setValue ( nSteps + + ) ;
bRet = WriteThroughComponent (
2013-01-03 13:41:37 +02:00
xStg , xModelComp , " content.xml " , xContext , xInfoSet ,
2010-02-12 16:56:44 +01:00
" com.sun.star.comp.Math.XMLContentExporter " ) ;
}
if ( bRet )
{
if ( xStatusIndicator . is ( ) )
xStatusIndicator - > setValue ( nSteps + + ) ;
bRet = WriteThroughComponent (
2013-01-03 13:41:37 +02:00
xStg , xModelComp , " settings.xml " , xContext , xInfoSet ,
2010-02-12 16:56:44 +01:00
( bOASIS ? " com.sun.star.comp.Math.XMLOasisSettingsExporter "
: " com.sun.star.comp.Math.XMLSettingsExporter " ) ) ;
}
}
else
{
SvStream * pStream = rMedium . GetOutStream ( ) ;
uno : : Reference < io : : XOutputStream > xOut (
new utl : : OOutputStreamWrapper ( * pStream ) ) ;
if ( xStatusIndicator . is ( ) )
xStatusIndicator - > setValue ( nSteps + + ) ;
bRet = WriteThroughComponent (
2013-01-03 13:41:37 +02:00
xOut , xModelComp , xContext , xInfoSet ,
2010-02-12 16:56:44 +01:00
" com.sun.star.comp.Math.XMLContentExporter " ) ;
}
if ( xStatusIndicator . is ( ) )
xStatusIndicator - > end ( ) ;
return bRet ;
}
/// export through an XML exporter component (output stream version)
2014-04-24 12:22:08 +02:00
bool SmXMLExportWrapper : : WriteThroughComponent (
2010-02-12 16:56:44 +01:00
Reference < io : : XOutputStream > xOutputStream ,
Reference < XComponent > xComponent ,
2013-01-03 13:41:37 +02:00
Reference < uno : : XComponentContext > & rxContext ,
2010-02-12 16:56:44 +01:00
Reference < beans : : XPropertySet > & rPropSet ,
const sal_Char * pComponentName )
{
2010-10-07 11:02:05 +01:00
OSL_ENSURE ( xOutputStream . is ( ) , " I really need an output stream! " ) ;
OSL_ENSURE ( xComponent . is ( ) , " Need component! " ) ;
OSL_ENSURE ( NULL ! = pComponentName , " Need component name! " ) ;
2010-02-12 16:56:44 +01:00
// get component
2013-01-03 13:41:37 +02:00
Reference < xml : : sax : : XWriter > xSaxWriter = xml : : sax : : Writer : : create ( rxContext ) ;
2010-02-12 16:56:44 +01:00
// connect XML writer to output stream
xSaxWriter - > setOutputStream ( xOutputStream ) ;
// prepare arguments (prepend doc handler to given arguments)
Reference < xml : : sax : : XDocumentHandler > xDocHandler ( xSaxWriter , UNO_QUERY ) ;
Sequence < Any > aArgs ( 2 ) ;
aArgs [ 0 ] < < = xDocHandler ;
aArgs [ 1 ] < < = rPropSet ;
// get filter component
Reference < document : : XExporter > xExporter (
2013-01-03 13:41:37 +02:00
rxContext - > getServiceManager ( ) - > createInstanceWithArgumentsAndContext ( OUString : : createFromAscii ( pComponentName ) , aArgs , rxContext ) ,
UNO_QUERY ) ;
2010-10-07 11:02:05 +01:00
OSL_ENSURE ( xExporter . is ( ) ,
2010-02-12 16:56:44 +01:00
" can't instantiate export filter component " ) ;
if ( ! xExporter . is ( ) )
2014-04-24 12:22:08 +02:00
return false ;
2010-02-12 16:56:44 +01:00
// connect model and filter
xExporter - > setSourceDocument ( xComponent ) ;
// filter!
Reference < XFilter > xFilter ( xExporter , UNO_QUERY ) ;
uno : : Sequence < PropertyValue > aProps ( 0 ) ;
xFilter - > filter ( aProps ) ;
uno : : Reference < lang : : XUnoTunnel > xFilterTunnel ;
xFilterTunnel = uno : : Reference < lang : : XUnoTunnel >
( xFilter , uno : : UNO_QUERY ) ;
SmXMLExport * pFilter = reinterpret_cast < SmXMLExport * > (
sal : : static_int_cast < sal_uIntPtr > (
xFilterTunnel - > getSomething ( SmXMLExport : : getUnoTunnelId ( ) ) ) ) ;
2015-04-24 12:33:33 +02:00
return pFilter = = nullptr | | pFilter - > GetSuccess ( ) ;
2010-02-12 16:56:44 +01:00
}
/// export through an XML exporter component (storage version)
2014-04-24 12:22:08 +02:00
bool SmXMLExportWrapper : : WriteThroughComponent (
2010-02-12 16:56:44 +01:00
const Reference < embed : : XStorage > & xStorage ,
Reference < XComponent > xComponent ,
const sal_Char * pStreamName ,
2013-01-03 13:41:37 +02:00
Reference < uno : : XComponentContext > & rxContext ,
2010-02-12 16:56:44 +01:00
Reference < beans : : XPropertySet > & rPropSet ,
2012-11-14 16:42:11 +01:00
const sal_Char * pComponentName
2010-02-12 16:56:44 +01:00
)
{
2010-10-07 11:02:05 +01:00
OSL_ENSURE ( xStorage . is ( ) , " Need storage! " ) ;
OSL_ENSURE ( NULL ! = pStreamName , " Need stream name! " ) ;
2010-02-12 16:56:44 +01:00
// open stream
Reference < io : : XStream > xStream ;
OUString sStreamName = OUString : : createFromAscii ( pStreamName ) ;
try
{
xStream = xStorage - > openStreamElement ( sStreamName ,
embed : : ElementModes : : READWRITE | embed : : ElementModes : : TRUNCATE ) ;
}
2013-09-09 08:52:34 +02:00
catch ( uno : : Exception & rEx )
2010-02-12 16:56:44 +01:00
{
2013-09-09 08:52:34 +02:00
SAL_WARN ( " starmath " , " Can't create output stream in package: " < < rEx . Message ) ;
2014-04-24 12:22:08 +02:00
return false ;
2010-02-12 16:56:44 +01:00
}
2012-03-08 14:56:00 +01:00
OUString aPropName ( " MediaType " ) ;
OUString aMime ( " text/xml " ) ;
2010-02-12 16:56:44 +01:00
uno : : Any aAny ;
aAny < < = aMime ;
uno : : Reference < beans : : XPropertySet > xSet ( xStream , uno : : UNO_QUERY ) ;
xSet - > setPropertyValue ( aPropName , aAny ) ;
2012-11-14 16:42:11 +01:00
// all streams must be encrypted in encrypted document
2012-03-08 14:56:00 +01:00
OUString aTmpPropName ( " UseCommonStoragePasswordEncryption " ) ;
2010-02-12 16:56:44 +01:00
sal_Bool bTrue = sal_True ;
2015-04-01 08:41:06 +02:00
aAny . setValue ( & bTrue , cppu : : UnoType < bool > : : get ( ) ) ;
2010-02-12 16:56:44 +01:00
xSet - > setPropertyValue ( aTmpPropName , aAny ) ;
// set Base URL
if ( rPropSet . is ( ) )
{
2012-03-08 14:56:00 +01:00
OUString sPropName ( " StreamName " ) ;
2010-02-12 16:56:44 +01:00
rPropSet - > setPropertyValue ( sPropName , makeAny ( sStreamName ) ) ;
}
// write the stuff
2014-04-24 12:22:08 +02:00
bool bRet = WriteThroughComponent ( xStream - > getOutputStream ( ) , xComponent , rxContext ,
2010-02-12 16:56:44 +01:00
rPropSet , pComponentName ) ;
return bRet ;
}
SmXMLExport : : SmXMLExport (
2015-03-04 16:29:43 +00:00
const : : com : : sun : : star : : uno : : Reference < : : com : : sun : : star : : uno : : XComponentContext > & rContext ,
2014-12-28 14:22:51 +02:00
OUString const & implementationName , SvXMLExportFlags nExportFlags )
2015-03-04 16:29:43 +00:00
: SvXMLExport ( util : : MeasureUnit : : INCH , rContext , implementationName , XML_MATH ,
nExportFlags )
, pTree ( 0 )
, bSuccess ( false )
2010-02-12 16:56:44 +01:00
{
}
sal_Int64 SAL_CALL SmXMLExport : : getSomething (
const uno : : Sequence < sal_Int8 > & rId )
2014-02-25 21:31:58 +01:00
throw ( uno : : RuntimeException , std : : exception )
2010-02-12 16:56:44 +01:00
{
if ( rId . getLength ( ) = = 16 & &
2012-09-29 14:47:11 +02:00
0 = = memcmp ( getUnoTunnelId ( ) . getConstArray ( ) ,
2010-02-12 16:56:44 +01:00
rId . getConstArray ( ) , 16 ) )
2012-11-20 16:50:46 +01:00
return sal : : static_int_cast < sal_Int64 > ( reinterpret_cast < sal_uIntPtr > ( this ) ) ;
2010-02-12 16:56:44 +01:00
return SvXMLExport : : getSomething ( rId ) ;
}
2011-04-04 12:23:43 +01:00
namespace
{
class theSmXMLExportUnoTunnelId : public rtl : : Static < UnoTunnelIdInit , theSmXMLExportUnoTunnelId > { } ;
}
2010-02-12 16:56:44 +01:00
const uno : : Sequence < sal_Int8 > & SmXMLExport : : getUnoTunnelId ( ) throw ( )
{
2011-04-04 12:23:43 +01:00
return theSmXMLExportUnoTunnelId : : get ( ) . getSeq ( ) ;
2010-02-12 16:56:44 +01:00
}
2015-05-03 17:08:28 +02:00
extern " C " SAL_DLLPUBLIC_EXPORT css : : uno : : XInterface * SAL_CALL
Math_XMLExporter_get_implementation ( css : : uno : : XComponentContext * context , css : : uno : : Sequence < css : : uno : : Any > const & )
2010-02-12 16:56:44 +01:00
{
2015-05-03 17:08:28 +02:00
return cppu : : acquire ( new SmXMLExport ( context , " com.sun.star.comp.Math.XMLExporter " , SvXMLExportFlags : : OASIS | SvXMLExportFlags : : ALL ) ) ;
2010-02-12 16:56:44 +01:00
}
2015-05-03 17:08:28 +02:00
extern " C " SAL_DLLPUBLIC_EXPORT css : : uno : : XInterface * SAL_CALL
Math_XMLMetaExporter_get_implementation ( css : : uno : : XComponentContext * context , css : : uno : : Sequence < css : : uno : : Any > const & )
2010-02-12 16:56:44 +01:00
{
2015-05-03 17:08:28 +02:00
return cppu : : acquire ( new SmXMLExport ( context , " com.sun.star.comp.Math.XMLMetaExporter " , SvXMLExportFlags : : META ) ) ;
2010-02-12 16:56:44 +01:00
}
2015-05-03 17:08:28 +02:00
extern " C " SAL_DLLPUBLIC_EXPORT css : : uno : : XInterface * SAL_CALL
Math_XMLOasisMetaExporter_get_implementation ( css : : uno : : XComponentContext * context , css : : uno : : Sequence < css : : uno : : Any > const & )
2010-02-12 16:56:44 +01:00
{
2015-05-03 17:08:28 +02:00
return cppu : : acquire ( new SmXMLExport ( context , " com.sun.star.comp.Math.XMLOasisMetaExporter " , SvXMLExportFlags : : OASIS | SvXMLExportFlags : : META ) ) ;
2010-02-12 16:56:44 +01:00
}
2015-05-03 17:08:28 +02:00
extern " C " SAL_DLLPUBLIC_EXPORT css : : uno : : XInterface * SAL_CALL
Math_XMLSettingsExporter_get_implementation ( css : : uno : : XComponentContext * context , css : : uno : : Sequence < css : : uno : : Any > const & )
2010-02-12 16:56:44 +01:00
{
2015-05-03 17:08:28 +02:00
return cppu : : acquire ( new SmXMLExport ( context , " com.sun.star.comp.Math.XMLSettingsExporter " , SvXMLExportFlags : : SETTINGS ) ) ;
2010-02-12 16:56:44 +01:00
}
2015-05-03 17:08:28 +02:00
extern " C " SAL_DLLPUBLIC_EXPORT css : : uno : : XInterface * SAL_CALL
Math_XMLOasisSettingsExporter_get_implementation ( css : : uno : : XComponentContext * context , css : : uno : : Sequence < css : : uno : : Any > const & )
2010-02-12 16:56:44 +01:00
{
2015-05-03 17:08:28 +02:00
return cppu : : acquire ( new SmXMLExport ( context , " com.sun.star.comp.Math.XMLOasisSettingsExporter " , SvXMLExportFlags : : OASIS | SvXMLExportFlags : : SETTINGS ) ) ;
2010-02-12 16:56:44 +01:00
}
2015-05-03 17:08:28 +02:00
extern " C " SAL_DLLPUBLIC_EXPORT css : : uno : : XInterface * SAL_CALL
Math_XMLContentExporter_get_implementation ( css : : uno : : XComponentContext * context , css : : uno : : Sequence < css : : uno : : Any > const & )
2010-02-12 16:56:44 +01:00
{
2015-05-03 17:08:28 +02:00
return cppu : : acquire ( new SmXMLExport ( context , " com.sun.star.comp.Math.XMLContentExporter " , SvXMLExportFlags : : OASIS | SvXMLExportFlags : : CONTENT ) ) ;
2010-02-12 16:56:44 +01:00
}
sal_uInt32 SmXMLExport : : exportDoc ( enum XMLTokenEnum eClass )
{
2014-12-28 14:22:51 +02:00
if ( ! ( getExportFlags ( ) & SvXMLExportFlags : : CONTENT ) )
2010-02-12 16:56:44 +01:00
{
SvXMLExport : : exportDoc ( eClass ) ;
}
else
{
uno : : Reference < frame : : XModel > xModel = GetModel ( ) ;
uno : : Reference < lang : : XUnoTunnel > xTunnel ;
xTunnel = uno : : Reference < lang : : XUnoTunnel > ( xModel , uno : : UNO_QUERY ) ;
SmModel * pModel = reinterpret_cast < SmModel * >
( xTunnel - > getSomething ( SmModel : : getUnoTunnelId ( ) ) ) ;
if ( pModel )
{
SmDocShell * pDocShell =
static_cast < SmDocShell * > ( pModel - > GetObjectShell ( ) ) ;
pTree = pDocShell - > GetFormulaTree ( ) ;
aText = pDocShell - > GetText ( ) ;
}
GetDocHandler ( ) - > startDocument ( ) ;
2011-09-08 13:50:30 +01:00
addChaffWhenEncryptedStorage ( ) ;
2010-02-12 16:56:44 +01:00
/*Add xmlns line*/
SvXMLAttributeList & rList = GetAttrList ( ) ;
// make use of a default namespace
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)
2010-10-30 02:12:24 +03:00
_GetNamespaceMap ( ) . Add ( OUString ( ) , GetXMLToken ( XML_N_MATH ) , XML_NAMESPACE_MATH ) ;
2010-02-12 16:56:44 +01:00
rList . AddAttribute ( GetNamespaceMap ( ) . GetAttrNameByKey ( XML_NAMESPACE_MATH_IDX ) ,
GetNamespaceMap ( ) . GetNameByKey ( XML_NAMESPACE_MATH_IDX ) ) ;
//I think we need something like ImplExportEntities();
_ExportContent ( ) ;
GetDocHandler ( ) - > endDocument ( ) ;
}
2014-04-24 12:22:08 +02:00
bSuccess = true ;
2010-02-12 16:56:44 +01:00
return 0 ;
}
void SmXMLExport : : _ExportContent ( )
{
2013-06-28 17:07:11 +02:00
uno : : Reference < frame : : XModel > xModel = GetModel ( ) ;
uno : : Reference < lang : : XUnoTunnel > xTunnel ;
xTunnel = uno : : Reference < lang : : XUnoTunnel > ( xModel , uno : : UNO_QUERY ) ;
SmModel * pModel = reinterpret_cast < SmModel * >
( xTunnel - > getSomething ( SmModel : : getUnoTunnelId ( ) ) ) ;
SmDocShell * pDocShell = pModel ?
static_cast < SmDocShell * > ( pModel - > GetObjectShell ( ) ) : 0 ;
OSL_ENSURE ( pDocShell , " doc shell missing " ) ;
if ( pDocShell & & ! pDocShell - > GetFormat ( ) . IsTextmode ( ) )
{
// If the Math equation is not in text mode, we attach a display="block"
// attribute on the <math> root. We don't do anything if it is in
// text mode, the default display="inline" value will be used.
AddAttribute ( XML_NAMESPACE_MATH , XML_DISPLAY , XML_BLOCK ) ;
}
2014-03-28 16:28:51 +02:00
SvXMLElementExport aEquation ( * this , XML_NAMESPACE_MATH , XML_MATH , true , true ) ;
2010-02-12 16:56:44 +01:00
SvXMLElementExport * pSemantics = 0 ;
2013-09-03 18:29:30 +02:00
if ( ! aText . isEmpty ( ) )
2010-02-12 16:56:44 +01:00
{
pSemantics = new SvXMLElementExport ( * this , XML_NAMESPACE_MATH ,
2014-03-28 16:28:51 +02:00
XML_SEMANTICS , true , true ) ;
2010-02-12 16:56:44 +01:00
}
ExportNodes ( pTree , 0 ) ;
2013-09-03 18:29:30 +02:00
if ( ! aText . isEmpty ( ) )
2010-02-12 16:56:44 +01:00
{
// Convert symbol names
if ( pDocShell )
{
SmParser & rParser = pDocShell - > GetParser ( ) ;
2010-11-06 01:33:05 +01:00
bool bVal = rParser . IsExportSymbolNames ( ) ;
rParser . SetExportSymbolNames ( true ) ;
2010-02-12 16:56:44 +01:00
SmNode * pTmpTree = rParser . Parse ( aText ) ;
aText = rParser . GetText ( ) ;
delete pTmpTree ;
rParser . SetExportSymbolNames ( bVal ) ;
}
AddAttribute ( XML_NAMESPACE_MATH , XML_ENCODING ,
2012-03-08 14:56:00 +01:00
OUString ( " StarMath 5.0 " ) ) ;
2010-02-12 16:56:44 +01:00
SvXMLElementExport aAnnotation ( * this , XML_NAMESPACE_MATH ,
2014-03-28 16:28:51 +02:00
XML_ANNOTATION , true , false ) ;
2013-09-03 18:29:30 +02:00
GetDocHandler ( ) - > characters ( aText ) ;
2010-02-12 16:56:44 +01:00
}
delete pSemantics ;
}
void SmXMLExport : : GetViewSettings ( Sequence < PropertyValue > & aProps )
{
uno : : Reference < frame : : XModel > xModel = GetModel ( ) ;
if ( ! xModel . is ( ) )
return ;
uno : : Reference < lang : : XUnoTunnel > xTunnel ;
xTunnel = uno : : Reference < lang : : XUnoTunnel > ( xModel , uno : : UNO_QUERY ) ;
SmModel * pModel = reinterpret_cast < SmModel * >
( xTunnel - > getSomething ( SmModel : : getUnoTunnelId ( ) ) ) ;
if ( ! pModel )
return ;
SmDocShell * pDocShell =
static_cast < SmDocShell * > ( pModel - > GetObjectShell ( ) ) ;
if ( ! pDocShell )
return ;
aProps . realloc ( 4 ) ;
PropertyValue * pValue = aProps . getArray ( ) ;
sal_Int32 nIndex = 0 ;
Rectangle aRect ( pDocShell - > GetVisArea ( ) ) ;
2012-03-08 14:56:00 +01:00
pValue [ nIndex ] . Name = " ViewAreaTop " ;
2010-02-12 16:56:44 +01:00
pValue [ nIndex + + ] . Value < < = aRect . Top ( ) ;
2012-03-08 14:56:00 +01:00
pValue [ nIndex ] . Name = " ViewAreaLeft " ;
2010-02-12 16:56:44 +01:00
pValue [ nIndex + + ] . Value < < = aRect . Left ( ) ;
2013-04-26 09:21:18 +02:00
pValue [ nIndex ] . Name = " ViewAreaWidth " ;
2010-02-12 16:56:44 +01:00
pValue [ nIndex + + ] . Value < < = aRect . GetWidth ( ) ;
2012-03-08 14:56:00 +01:00
pValue [ nIndex ] . Name = " ViewAreaHeight " ;
2010-02-12 16:56:44 +01:00
pValue [ nIndex + + ] . Value < < = aRect . GetHeight ( ) ;
}
void SmXMLExport : : GetConfigurationSettings ( Sequence < PropertyValue > & rProps )
{
Reference < XPropertySet > xProps ( GetModel ( ) , UNO_QUERY ) ;
if ( xProps . is ( ) )
{
Reference < XPropertySetInfo > xPropertySetInfo = xProps - > getPropertySetInfo ( ) ;
if ( xPropertySetInfo . is ( ) )
{
Sequence < Property > aProps = xPropertySetInfo - > getProperties ( ) ;
sal_Int32 nCount ( aProps . getLength ( ) ) ;
if ( nCount > 0 )
{
rProps . realloc ( nCount ) ;
PropertyValue * pProps = rProps . getArray ( ) ;
if ( pProps )
{
2015-05-26 08:38:37 +02:00
SmMathConfig * pConfig = SM_MOD ( ) - > GetConfig ( ) ;
2014-05-02 15:42:25 +02:00
const bool bUsedSymbolsOnly = pConfig & & pConfig - > IsSaveOnlyUsedSymbols ( ) ;
2010-10-13 11:39:15 +02:00
2012-03-08 14:56:00 +01:00
const OUString sFormula ( " Formula " ) ;
const OUString sBasicLibraries ( " BasicLibraries " ) ;
const OUString sDialogLibraries ( " DialogLibraries " ) ;
const OUString sRuntimeUID ( " RuntimeUID " ) ;
2010-02-12 16:56:44 +01:00
for ( sal_Int32 i = 0 ; i < nCount ; i + + , pProps + + )
{
const OUString & rPropName = aProps [ i ] . Name ;
if ( rPropName ! = sFormula & &
rPropName ! = sBasicLibraries & &
rPropName ! = sDialogLibraries & &
rPropName ! = sRuntimeUID )
{
pProps - > Name = rPropName ;
2010-10-13 11:39:15 +02:00
2013-04-07 12:06:47 +02:00
OUString aActualName ( rPropName ) ;
2010-10-13 11:39:15 +02:00
// handle 'save used symbols only'
2012-03-08 14:56:00 +01:00
if ( bUsedSymbolsOnly & & rPropName = = " Symbols " )
aActualName = " UserDefinedSymbolsInUse " ;
2010-10-13 11:39:15 +02:00
pProps - > Value = xProps - > getPropertyValue ( aActualName ) ;
2010-02-12 16:56:44 +01:00
}
}
}
}
}
}
}
void SmXMLExport : : ExportLine ( const SmNode * pNode , int nLevel )
{
ExportExpression ( pNode , nLevel ) ;
}
void SmXMLExport : : ExportBinaryHorizontal ( const SmNode * pNode , int nLevel )
{
2013-06-25 22:33:13 +02:00
sal_uLong nGroup = pNode - > GetToken ( ) . nGroup ;
SvXMLElementExport * pRow = new SvXMLElementExport ( * this ,
2014-03-28 16:28:51 +02:00
XML_NAMESPACE_MATH , XML_MROW , true , true ) ;
2013-06-25 22:33:13 +02:00
// Unfold the binary tree structure as long as the nodes are SmBinHorNode
// with the same nGroup. This will reduce the number of nested <mrow>
// elements e.g. we only need three <mrow> levels to export
2014-02-25 20:41:20 +01:00
2013-06-25 22:33:13 +02:00
// "a*b*c*d+e*f*g*h+i*j*k*l = a*b*c*d+e*f*g*h+i*j*k*l =
// a*b*c*d+e*f*g*h+i*j*k*l = a*b*c*d+e*f*g*h+i*j*k*l"
2014-02-25 20:41:20 +01:00
2013-06-25 22:33:13 +02:00
// See https://www.libreoffice.org/bugzilla/show_bug.cgi?id=66081
: : std : : stack < const SmNode * > s ;
s . push ( pNode ) ;
while ( ! s . empty ( ) )
{
const SmNode * node = s . top ( ) ;
s . pop ( ) ;
if ( node - > GetType ( ) ! = NBINHOR | | node - > GetToken ( ) . nGroup ! = nGroup )
{
ExportNodes ( node , nLevel + 1 ) ;
continue ;
}
const SmBinHorNode * binNode = static_cast < const SmBinHorNode * > ( node ) ;
s . push ( binNode - > RightOperand ( ) ) ;
s . push ( binNode - > Symbol ( ) ) ;
s . push ( binNode - > LeftOperand ( ) ) ;
}
delete pRow ;
2010-02-12 16:56:44 +01:00
}
void SmXMLExport : : ExportUnaryHorizontal ( const SmNode * pNode , int nLevel )
{
ExportExpression ( pNode , nLevel ) ;
}
2013-06-30 17:34:40 +02:00
void SmXMLExport : : ExportExpression ( const SmNode * pNode , int nLevel ,
bool bNoMrowContainer /*=false*/ )
2010-02-12 16:56:44 +01:00
{
SvXMLElementExport * pRow = 0 ;
2015-02-18 17:21:39 +09:00
auto nSize = pNode - > GetNumSubNodes ( ) ;
2010-02-12 16:56:44 +01:00
2010-12-01 14:03:02 +01:00
// #i115443: nodes of type expression always need to be grouped with mrow statement
2013-06-30 17:34:40 +02:00
if ( ! bNoMrowContainer & &
2014-02-19 14:53:54 +02:00
( nSize > 1 | | pNode - > GetType ( ) = = NEXPRESSION ) )
2014-03-28 16:28:51 +02:00
pRow = new SvXMLElementExport ( * this , XML_NAMESPACE_MATH , XML_MROW , true , true ) ;
2010-02-12 16:56:44 +01:00
2012-11-20 16:50:46 +01:00
for ( sal_uInt16 i = 0 ; i < nSize ; i + + )
2010-09-30 22:35:03 +01:00
if ( const SmNode * pTemp = pNode - > GetSubNode ( i ) )
ExportNodes ( pTemp , nLevel + 1 ) ;
2010-02-12 16:56:44 +01:00
delete pRow ;
}
void SmXMLExport : : ExportBinaryVertical ( const SmNode * pNode , int nLevel )
{
2010-10-07 11:02:05 +01:00
OSL_ENSURE ( pNode - > GetNumSubNodes ( ) = = 3 , " Bad Fraction " ) ;
2013-06-29 22:51:58 +02:00
const SmNode * pNum = pNode - > GetSubNode ( 0 ) ;
const SmNode * pDenom = pNode - > GetSubNode ( 2 ) ;
if ( pNum - > GetType ( ) = = NALIGN & & pNum - > GetToken ( ) . eType ! = TALIGNC )
{
// A left or right alignment is specified on the numerator:
// attach the corresponding numalign attribute.
AddAttribute ( XML_NAMESPACE_MATH , XML_NUMALIGN ,
pNum - > GetToken ( ) . eType = = TALIGNL ? XML_LEFT : XML_RIGHT ) ;
}
if ( pDenom - > GetType ( ) = = NALIGN & & pDenom - > GetToken ( ) . eType ! = TALIGNC )
{
// A left or right alignment is specified on the denominator:
// attach the corresponding denomalign attribute.
AddAttribute ( XML_NAMESPACE_MATH , XML_DENOMALIGN ,
pDenom - > GetToken ( ) . eType = = TALIGNL ? XML_LEFT : XML_RIGHT ) ;
}
2014-03-28 16:28:51 +02:00
SvXMLElementExport aFraction ( * this , XML_NAMESPACE_MATH , XML_MFRAC , true , true ) ;
2013-06-29 22:51:58 +02:00
ExportNodes ( pNum , nLevel ) ;
ExportNodes ( pDenom , nLevel ) ;
2010-02-12 16:56:44 +01:00
}
2013-06-23 21:32:37 +02:00
void SmXMLExport : : ExportBinaryDiagonal ( const SmNode * pNode , int nLevel )
{
OSL_ENSURE ( pNode - > GetNumSubNodes ( ) = = 3 , " Bad Slash " ) ;
if ( pNode - > GetToken ( ) . eType = = TWIDESLASH )
{
// wideslash
// export the node as <mfrac bevelled="true">
AddAttribute ( XML_NAMESPACE_MATH , XML_BEVELLED , XML_TRUE ) ;
SvXMLElementExport aFraction ( * this , XML_NAMESPACE_MATH , XML_MFRAC ,
2014-03-28 16:28:51 +02:00
true , true ) ;
2013-06-23 21:32:37 +02:00
ExportNodes ( pNode - > GetSubNode ( 0 ) , nLevel ) ;
ExportNodes ( pNode - > GetSubNode ( 1 ) , nLevel ) ;
}
else
{
// widebslash
// We can not use <mfrac> to a backslash, so just use <mo>\</mo>
SvXMLElementExport * pRow = new SvXMLElementExport ( * this ,
2014-03-28 16:28:51 +02:00
XML_NAMESPACE_MATH , XML_MROW , true , true ) ;
2013-06-23 21:32:37 +02:00
ExportNodes ( pNode - > GetSubNode ( 0 ) , nLevel ) ;
{ // Scoping for <mo> creation
SvXMLElementExport aMo ( * this , XML_NAMESPACE_MATH , XML_MO ,
2014-03-28 16:28:51 +02:00
true , true ) ;
2013-06-23 21:32:37 +02:00
sal_Unicode nArse [ 2 ] = { MS_BACKSLASH , 0x00 } ;
GetDocHandler ( ) - > characters ( nArse ) ;
}
ExportNodes ( pNode - > GetSubNode ( 1 ) , nLevel ) ;
delete pRow ;
}
}
2010-02-12 16:56:44 +01:00
void SmXMLExport : : ExportTable ( const SmNode * pNode , int nLevel )
{
SvXMLElementExport * pTable = 0 ;
2011-01-14 17:19:25 +01:00
sal_uInt16 nSize = pNode - > GetNumSubNodes ( ) ;
2010-02-12 16:56:44 +01:00
//If the list ends in newline then the last entry has
//no subnodes, the newline is superfulous so we just drop
//the last node, inclusion would create a bad MathML
//table
2013-07-04 10:57:35 +02:00
if ( nSize > = 1 )
{
const SmNode * pLine = pNode - > GetSubNode ( nSize - 1 ) ;
2013-07-04 20:21:06 +01:00
if ( pLine - > GetType ( ) = = NLINE & & pLine - > GetNumSubNodes ( ) = = 1 & &
2013-10-01 17:47:17 +03:00
pLine - > GetSubNode ( 0 ) ! = NULL & &
2013-07-04 20:21:06 +01:00
pLine - > GetSubNode ( 0 ) - > GetToken ( ) . eType = = TNEWLINE )
2013-07-04 10:57:35 +02:00
- - nSize ;
}
2010-02-12 16:56:44 +01:00
// try to avoid creating a mtable element when the formula consists only
// of a single output line
if ( nLevel | | ( nSize > 1 ) )
2014-03-28 16:28:51 +02:00
pTable = new SvXMLElementExport ( * this , XML_NAMESPACE_MATH , XML_MTABLE , true , true ) ;
2010-02-12 16:56:44 +01:00
2011-01-14 17:19:25 +01:00
for ( sal_uInt16 i = 0 ; i < nSize ; i + + )
2010-02-12 16:56:44 +01:00
if ( const SmNode * pTemp = pNode - > GetSubNode ( i ) )
{
SvXMLElementExport * pRow = 0 ;
SvXMLElementExport * pCell = 0 ;
if ( pTable )
{
2014-03-28 16:28:51 +02:00
pRow = new SvXMLElementExport ( * this , XML_NAMESPACE_MATH , XML_MTR , true , true ) ;
2013-07-07 08:31:56 +02:00
SmTokenType eAlign = TALIGNC ;
if ( pTemp - > GetType ( ) = = NALIGN )
2013-06-29 22:51:58 +02:00
{
2013-07-07 08:31:56 +02:00
// For Binom() and Stack() constructions, the NALIGN nodes
// are direct children.
// binom{alignl ...}{alignr ...} and
// stack{alignl ... ## alignr ... ## ...}
eAlign = pTemp - > GetToken ( ) . eType ;
}
else if ( pTemp - > GetType ( ) = = NLINE & &
pTemp - > GetNumSubNodes ( ) = = 1 & &
2014-08-20 23:02:56 +02:00
pTemp - > GetSubNode ( 0 ) & &
2013-07-07 08:31:56 +02:00
pTemp - > GetSubNode ( 0 ) - > GetType ( ) = = NALIGN )
{
// For the Table() construction, the NALIGN node is a child
// of an NLINE node.
// alignl ... newline alignr ... newline ...
eAlign = pTemp - > GetSubNode ( 0 ) - > GetToken ( ) . eType ;
}
if ( eAlign ! = TALIGNC )
{
// If a left or right alignment is specified on this line,
// attach the corresponding columnalign attribute.
AddAttribute ( XML_NAMESPACE_MATH , XML_COLUMNALIGN ,
eAlign = = TALIGNL ? XML_LEFT : XML_RIGHT ) ;
2013-06-29 22:51:58 +02:00
}
2014-03-28 16:28:51 +02:00
pCell = new SvXMLElementExport ( * this , XML_NAMESPACE_MATH , XML_MTD , true , true ) ;
2010-02-12 16:56:44 +01:00
}
ExportNodes ( pTemp , nLevel + 1 ) ;
delete pCell ;
delete pRow ;
}
delete pTable ;
}
void SmXMLExport : : ExportMath ( const SmNode * pNode , int /*nLevel*/ )
{
const SmMathSymbolNode * pTemp = static_cast < const SmMathSymbolNode * > ( pNode ) ;
2013-06-27 21:35:28 +02:00
SvXMLElementExport * pMath = 0 ;
2013-06-30 14:06:23 +02:00
if ( pNode - > GetType ( ) = = NMATH | | pNode - > GetType ( ) = = NGLYPH_SPECIAL )
2013-06-27 21:35:28 +02:00
{
2013-06-30 14:06:23 +02:00
// Export NMATH and NGLYPH_SPECIAL symbols as <mo> elements
2014-03-28 16:28:51 +02:00
pMath = new SvXMLElementExport ( * this , XML_NAMESPACE_MATH , XML_MO , true , false ) ;
2013-06-27 21:35:28 +02:00
}
else
{
// Export NMATHIDENT and NPLACE symbols as <mi> elements:
// - These math symbols should not be drawn slanted. Hence we should
// attach a mathvariant="normal" attribute to single-char <mi> elements
// that are not mathematical alphanumeric symbol. For simplicity and to
// work around browser limitations, we always attach such an attribute.
// - The MathML specification suggests to use empty <mi> elements as
// placeholders but they won't be visible in most MathML rendering
// engines so let's use an empty square for NPLACE instead.
AddAttribute ( XML_NAMESPACE_MATH , XML_MATHVARIANT , XML_NORMAL ) ;
2014-03-28 16:28:51 +02:00
pMath = new SvXMLElementExport ( * this , XML_NAMESPACE_MATH , XML_MI , true , false ) ;
2013-06-27 21:35:28 +02:00
}
2010-02-12 16:56:44 +01:00
sal_Unicode nArse [ 2 ] ;
2012-10-01 20:46:34 +04:00
nArse [ 0 ] = pTemp - > GetText ( ) [ 0 ] ;
2010-02-12 16:56:44 +01:00
sal_Unicode cTmp = ConvertMathToMathML ( nArse [ 0 ] ) ;
if ( cTmp ! = 0 )
nArse [ 0 ] = cTmp ;
2011-04-10 18:30:46 +09:00
OSL_ENSURE ( nArse [ 0 ] ! = 0xffff , " Non existent symbol " ) ;
2010-02-12 16:56:44 +01:00
nArse [ 1 ] = 0 ;
GetDocHandler ( ) - > characters ( nArse ) ;
2013-06-27 21:35:28 +02:00
delete pMath ;
2010-02-12 16:56:44 +01:00
}
void SmXMLExport : : ExportText ( const SmNode * pNode , int /*nLevel*/ )
{
SvXMLElementExport * pText ;
const SmTextNode * pTemp = static_cast < const SmTextNode * > ( pNode ) ;
switch ( pNode - > GetToken ( ) . eType )
{
default :
case TIDENT :
{
//Note that we change the fontstyle to italic for strings that
//are italic and longer than a single character.
2014-04-24 12:22:08 +02:00
bool bIsItalic = IsItalic ( pTemp - > GetFont ( ) ) ;
2012-10-01 20:46:34 +04:00
if ( ( pTemp - > GetText ( ) . getLength ( ) > 1 ) & & bIsItalic )
2010-02-12 16:56:44 +01:00
AddAttribute ( XML_NAMESPACE_MATH , XML_MATHVARIANT , XML_ITALIC ) ;
2012-10-01 20:46:34 +04:00
else if ( ( pTemp - > GetText ( ) . getLength ( ) = = 1 ) & & ! bIsItalic )
2010-02-12 16:56:44 +01:00
AddAttribute ( XML_NAMESPACE_MATH , XML_MATHVARIANT , XML_NORMAL ) ;
2014-03-28 16:28:51 +02:00
pText = new SvXMLElementExport ( * this , XML_NAMESPACE_MATH , XML_MI , true , false ) ;
2010-02-12 16:56:44 +01:00
break ;
}
case TNUMBER :
2014-03-28 16:28:51 +02:00
pText = new SvXMLElementExport ( * this , XML_NAMESPACE_MATH , XML_MN , true , false ) ;
2010-02-12 16:56:44 +01:00
break ;
case TTEXT :
2014-03-28 16:28:51 +02:00
pText = new SvXMLElementExport ( * this , XML_NAMESPACE_MATH , XML_MTEXT , true , false ) ;
2010-02-12 16:56:44 +01:00
break ;
}
2012-10-01 20:46:34 +04:00
GetDocHandler ( ) - > characters ( pTemp - > GetText ( ) ) ;
2010-02-12 16:56:44 +01:00
delete pText ;
}
2013-06-23 13:28:36 +02:00
void SmXMLExport : : ExportBlank ( const SmNode * pNode , int /*nLevel*/ )
2010-02-12 16:56:44 +01:00
{
2013-06-23 13:28:36 +02:00
const SmBlankNode * pTemp = static_cast < const SmBlankNode * > ( pNode ) ;
//!! exports an <mspace> element. Note that for example "~_~" is allowed in
2010-02-12 16:56:44 +01:00
//!! Math (so it has no sense at all) but must not result in an empty
//!! <msub> tag in MathML !!
2013-06-23 13:28:36 +02:00
if ( pTemp - > GetBlankNum ( ) ! = 0 )
{
// Attach a width attribute. We choose the (somewhat arbitrary) values
// ".5em" for a small gap '`' and "2em" for a large gap '~'.
// (see SmBlankNode::IncreaseBy for how pTemp->nNum is set).
OUStringBuffer sStrBuf ;
: : sax : : Converter : : convertDouble ( sStrBuf , pTemp - > GetBlankNum ( ) * .5 ) ;
2013-12-13 11:10:10 +02:00
sStrBuf . append ( " em " ) ;
2013-06-23 13:28:36 +02:00
AddAttribute ( XML_NAMESPACE_MATH , XML_WIDTH , sStrBuf . getStr ( ) ) ;
}
2010-02-12 16:56:44 +01:00
SvXMLElementExport * pText ;
2013-06-23 13:28:36 +02:00
pText = new SvXMLElementExport ( * this , XML_NAMESPACE_MATH , XML_MSPACE ,
2014-03-28 16:28:51 +02:00
true , false ) ;
2010-02-12 16:56:44 +01:00
GetDocHandler ( ) - > characters ( OUString ( ) ) ;
delete pText ;
}
void SmXMLExport : : ExportSubSupScript ( const SmNode * pNode , int nLevel )
{
const SmNode * pSub = 0 ;
const SmNode * pSup = 0 ;
const SmNode * pCSub = 0 ;
const SmNode * pCSup = 0 ;
const SmNode * pLSub = 0 ;
const SmNode * pLSup = 0 ;
2015-06-09 23:27:49 +09:00
SvXMLElementExport * pThing2 = nullptr ;
2010-02-12 16:56:44 +01:00
//if we have prescripts at all then we must use the tensor notation
//This is one of those excellent locations where scope is vital to
//arrange the construction and destruction of the element helper
//classes correctly
pLSub = pNode - > GetSubNode ( LSUB + 1 ) ;
pLSup = pNode - > GetSubNode ( LSUP + 1 ) ;
if ( pLSub | | pLSup )
{
SvXMLElementExport aMultiScripts ( * this , XML_NAMESPACE_MATH ,
2014-03-28 16:28:51 +02:00
XML_MMULTISCRIPTS , true , true ) ;
2010-02-12 16:56:44 +01:00
if ( NULL ! = ( pCSub = pNode - > GetSubNode ( CSUB + 1 ) )
& & NULL ! = ( pCSup = pNode - > GetSubNode ( CSUP + 1 ) ) )
{
pThing2 = new SvXMLElementExport ( * this , XML_NAMESPACE_MATH ,
2014-03-28 16:28:51 +02:00
XML_MUNDEROVER , true , true ) ;
2010-02-12 16:56:44 +01:00
}
else if ( NULL ! = ( pCSub = pNode - > GetSubNode ( CSUB + 1 ) ) )
{
pThing2 = new SvXMLElementExport ( * this , XML_NAMESPACE_MATH ,
2014-03-28 16:28:51 +02:00
XML_MUNDER , true , true ) ;
2010-02-12 16:56:44 +01:00
}
else if ( NULL ! = ( pCSup = pNode - > GetSubNode ( CSUP + 1 ) ) )
{
pThing2 = new SvXMLElementExport ( * this , XML_NAMESPACE_MATH ,
2014-03-28 16:28:51 +02:00
XML_MOVER , true , true ) ;
2010-02-12 16:56:44 +01:00
}
ExportNodes ( pNode - > GetSubNode ( 0 ) , nLevel + 1 ) ; //Main Term
if ( pCSub )
ExportNodes ( pCSub , nLevel + 1 ) ;
if ( pCSup )
ExportNodes ( pCSup , nLevel + 1 ) ;
delete pThing2 ;
pSub = pNode - > GetSubNode ( RSUB + 1 ) ;
pSup = pNode - > GetSubNode ( RSUP + 1 ) ;
if ( pSub | | pSup )
{
if ( pSub )
ExportNodes ( pSub , nLevel + 1 ) ;
else
{
2014-03-28 16:28:51 +02:00
SvXMLElementExport aNone ( * this , XML_NAMESPACE_MATH , XML_NONE , true , true ) ;
2010-02-12 16:56:44 +01:00
}
if ( pSup )
ExportNodes ( pSup , nLevel + 1 ) ;
else
{
2014-03-28 16:28:51 +02:00
SvXMLElementExport aNone ( * this , XML_NAMESPACE_MATH , XML_NONE , true , true ) ;
2010-02-12 16:56:44 +01:00
}
}
2013-05-15 10:42:04 +03:00
//Separator element between suffix and prefix sub/sup pairs
2010-02-12 16:56:44 +01:00
{
SvXMLElementExport aPrescripts ( * this , XML_NAMESPACE_MATH ,
2014-03-28 16:28:51 +02:00
XML_MPRESCRIPTS , true , true ) ;
2010-02-12 16:56:44 +01:00
}
if ( pLSub )
ExportNodes ( pLSub , nLevel + 1 ) ;
else
{
SvXMLElementExport aNone ( * this , XML_NAMESPACE_MATH , XML_NONE ,
2014-03-28 16:28:51 +02:00
true , true ) ;
2010-02-12 16:56:44 +01:00
}
if ( pLSup )
ExportNodes ( pLSup , nLevel + 1 ) ;
else
{
SvXMLElementExport aNone ( * this , XML_NAMESPACE_MATH , XML_NONE ,
2014-03-28 16:28:51 +02:00
true , true ) ;
2010-02-12 16:56:44 +01:00
}
}
else
{
2015-06-09 23:27:49 +09:00
SvXMLElementExport * pThing = nullptr ;
2010-02-12 16:56:44 +01:00
if ( NULL ! = ( pSub = pNode - > GetSubNode ( RSUB + 1 ) ) & &
NULL ! = ( pSup = pNode - > GetSubNode ( RSUP + 1 ) ) )
{
pThing = new SvXMLElementExport ( * this , XML_NAMESPACE_MATH ,
2014-03-28 16:28:51 +02:00
XML_MSUBSUP , true , true ) ;
2010-02-12 16:56:44 +01:00
}
else if ( NULL ! = ( pSub = pNode - > GetSubNode ( RSUB + 1 ) ) )
{
pThing = new SvXMLElementExport ( * this , XML_NAMESPACE_MATH , XML_MSUB ,
2014-03-28 16:28:51 +02:00
true , true ) ;
2010-02-12 16:56:44 +01:00
}
else if ( NULL ! = ( pSup = pNode - > GetSubNode ( RSUP + 1 ) ) )
{
pThing = new SvXMLElementExport ( * this , XML_NAMESPACE_MATH , XML_MSUP ,
2014-03-28 16:28:51 +02:00
true , true ) ;
2010-02-12 16:56:44 +01:00
}
if ( NULL ! = ( pCSub = pNode - > GetSubNode ( CSUB + 1 ) )
& & NULL ! = ( pCSup = pNode - > GetSubNode ( CSUP + 1 ) ) )
{
pThing2 = new SvXMLElementExport ( * this , XML_NAMESPACE_MATH ,
2014-03-28 16:28:51 +02:00
XML_MUNDEROVER , true , true ) ;
2010-02-12 16:56:44 +01:00
}
else if ( NULL ! = ( pCSub = pNode - > GetSubNode ( CSUB + 1 ) ) )
{
pThing2 = new SvXMLElementExport ( * this , XML_NAMESPACE_MATH ,
2014-03-28 16:28:51 +02:00
XML_MUNDER , true , true ) ;
2010-02-12 16:56:44 +01:00
}
else if ( NULL ! = ( pCSup = pNode - > GetSubNode ( CSUP + 1 ) ) )
{
pThing2 = new SvXMLElementExport ( * this , XML_NAMESPACE_MATH ,
2014-03-28 16:28:51 +02:00
XML_MOVER , true , true ) ;
2010-02-12 16:56:44 +01:00
}
ExportNodes ( pNode - > GetSubNode ( 0 ) , nLevel + 1 ) ; //Main Term
if ( pCSub )
ExportNodes ( pCSub , nLevel + 1 ) ;
if ( pCSup )
ExportNodes ( pCSup , nLevel + 1 ) ;
delete pThing2 ;
if ( pSub )
ExportNodes ( pSub , nLevel + 1 ) ;
if ( pSup )
ExportNodes ( pSup , nLevel + 1 ) ;
delete pThing ;
}
}
void SmXMLExport : : ExportBrace ( const SmNode * pNode , int nLevel )
{
const SmNode * pTemp ;
const SmNode * pLeft = pNode - > GetSubNode ( 0 ) ;
const SmNode * pRight = pNode - > GetSubNode ( 2 ) ;
2013-06-30 16:15:14 +02:00
SvXMLElementExport * pRow = 0 ;
// This used to generate <mfenced> or <mrow>+<mo> elements according to
// the stretchiness of fences. The MathML recommendation defines an
// <mrow>+<mo> construction that is equivalent to the <mfenced> element:
// http://www.w3.org/TR/MathML3/chapter3.html#presm.mfenced
// To simplify our code and avoid issues with mfenced implementations in
// MathML rendering engines, we now always generate <mrow>+<mo> elements.
// See #fdo 66282.
// <mrow>
pRow = new SvXMLElementExport ( * this , XML_NAMESPACE_MATH , XML_MROW ,
2014-03-28 16:28:51 +02:00
true , true ) ;
2013-06-30 16:15:14 +02:00
// <mo fence="true"> opening-fence </mo>
if ( pLeft & & ( pLeft - > GetToken ( ) . eType ! = TNONE ) )
2010-02-12 16:56:44 +01:00
{
2013-06-30 16:15:14 +02:00
AddAttribute ( XML_NAMESPACE_MATH , XML_FENCE , XML_TRUE ) ;
2010-02-12 16:56:44 +01:00
if ( pNode - > GetScaleMode ( ) = = SCALE_HEIGHT )
AddAttribute ( XML_NAMESPACE_MATH , XML_STRETCHY , XML_TRUE ) ;
else
AddAttribute ( XML_NAMESPACE_MATH , XML_STRETCHY , XML_FALSE ) ;
ExportNodes ( pLeft , nLevel + 1 ) ;
}
if ( NULL ! = ( pTemp = pNode - > GetSubNode ( 1 ) ) )
2013-06-30 16:15:14 +02:00
{
// <mrow>
SvXMLElementExport aRow ( * this , XML_NAMESPACE_MATH , XML_MROW ,
2014-03-28 16:28:51 +02:00
true , true ) ;
2010-02-12 16:56:44 +01:00
ExportNodes ( pTemp , nLevel + 1 ) ;
2013-06-30 16:15:14 +02:00
// </mrow>
}
// <mo fence="true"> closing-fence </mo>
if ( pRight & & ( pRight - > GetToken ( ) . eType ! = TNONE ) )
2010-02-12 16:56:44 +01:00
{
2013-06-30 16:15:14 +02:00
AddAttribute ( XML_NAMESPACE_MATH , XML_FENCE , XML_TRUE ) ;
2010-02-12 16:56:44 +01:00
if ( pNode - > GetScaleMode ( ) = = SCALE_HEIGHT )
AddAttribute ( XML_NAMESPACE_MATH , XML_STRETCHY , XML_TRUE ) ;
else
AddAttribute ( XML_NAMESPACE_MATH , XML_STRETCHY , XML_FALSE ) ;
ExportNodes ( pRight , nLevel + 1 ) ;
}
2013-06-30 16:15:14 +02:00
2010-02-12 16:56:44 +01:00
delete pRow ;
2013-06-30 16:15:14 +02:00
// </mrow>
2010-02-12 16:56:44 +01:00
}
void SmXMLExport : : ExportRoot ( const SmNode * pNode , int nLevel )
{
if ( pNode - > GetSubNode ( 0 ) )
{
2014-03-28 16:28:51 +02:00
SvXMLElementExport aRoot ( * this , XML_NAMESPACE_MATH , XML_MROOT , true ,
true ) ;
2010-02-12 16:56:44 +01:00
ExportNodes ( pNode - > GetSubNode ( 2 ) , nLevel + 1 ) ;
ExportNodes ( pNode - > GetSubNode ( 0 ) , nLevel + 1 ) ;
}
else
{
2014-03-28 16:28:51 +02:00
SvXMLElementExport aSqrt ( * this , XML_NAMESPACE_MATH , XML_MSQRT , true ,
true ) ;
2010-02-12 16:56:44 +01:00
ExportNodes ( pNode - > GetSubNode ( 2 ) , nLevel + 1 ) ;
}
}
void SmXMLExport : : ExportOperator ( const SmNode * pNode , int nLevel )
{
/*we need to either use content or font and size attributes
* here */
SvXMLElementExport aRow ( * this , XML_NAMESPACE_MATH , XML_MROW ,
2014-03-28 16:28:51 +02:00
true , true ) ;
2010-02-12 16:56:44 +01:00
ExportNodes ( pNode - > GetSubNode ( 0 ) , nLevel + 1 ) ;
ExportNodes ( pNode - > GetSubNode ( 1 ) , nLevel + 1 ) ;
}
void SmXMLExport : : ExportAttributes ( const SmNode * pNode , int nLevel )
{
SvXMLElementExport * pElement = 0 ;
if ( pNode - > GetToken ( ) . eType = = TUNDERLINE )
{
AddAttribute ( XML_NAMESPACE_MATH , XML_ACCENTUNDER ,
XML_TRUE ) ;
pElement = new SvXMLElementExport ( * this , XML_NAMESPACE_MATH , XML_MUNDER ,
2014-03-28 16:28:51 +02:00
true , true ) ;
2010-02-12 16:56:44 +01:00
}
2013-06-23 21:32:37 +02:00
else if ( pNode - > GetToken ( ) . eType = = TOVERSTRIKE )
{
// export as <menclose notation="horizontalstrike">
AddAttribute ( XML_NAMESPACE_MATH , XML_NOTATION , XML_HORIZONTALSTRIKE ) ;
pElement = new SvXMLElementExport ( * this , XML_NAMESPACE_MATH ,
2014-03-28 16:28:51 +02:00
XML_MENCLOSE , true , true ) ;
2013-06-23 21:32:37 +02:00
}
else
2010-02-12 16:56:44 +01:00
{
AddAttribute ( XML_NAMESPACE_MATH , XML_ACCENT ,
XML_TRUE ) ;
pElement = new SvXMLElementExport ( * this , XML_NAMESPACE_MATH , XML_MOVER ,
2014-03-28 16:28:51 +02:00
true , true ) ;
2010-02-12 16:56:44 +01:00
}
ExportNodes ( pNode - > GetSubNode ( 1 ) , nLevel + 1 ) ;
switch ( pNode - > GetToken ( ) . eType )
{
case TOVERLINE :
{
//proper entity support required
SvXMLElementExport aMath ( * this , XML_NAMESPACE_MATH , XML_MO ,
2014-03-28 16:28:51 +02:00
true , true ) ;
2010-02-12 16:56:44 +01:00
sal_Unicode nArse [ 2 ] = { 0xAF , 0x00 } ;
GetDocHandler ( ) - > characters ( nArse ) ;
}
break ;
case TUNDERLINE :
{
//proper entity support required
SvXMLElementExport aMath ( * this , XML_NAMESPACE_MATH , XML_MO ,
2014-03-28 16:28:51 +02:00
true , true ) ;
2010-02-12 16:56:44 +01:00
sal_Unicode nArse [ 2 ] = { 0x0332 , 0x00 } ;
GetDocHandler ( ) - > characters ( nArse ) ;
}
break ;
case TOVERSTRIKE :
break ;
2013-06-22 20:03:59 +02:00
case TWIDETILDE :
case TWIDEHAT :
case TWIDEVEC :
{
// make these wide accents stretchy
AddAttribute ( XML_NAMESPACE_MATH , XML_STRETCHY , XML_TRUE ) ;
ExportNodes ( pNode - > GetSubNode ( 0 ) , nLevel + 1 ) ;
}
break ;
2010-02-12 16:56:44 +01:00
default :
ExportNodes ( pNode - > GetSubNode ( 0 ) , nLevel + 1 ) ;
break ;
}
delete pElement ;
}
static bool lcl_HasEffectOnMathvariant ( const SmTokenType eType )
{
return eType = = TBOLD | | eType = = TNBOLD | |
2011-12-29 11:35:59 +01:00
eType = = TITALIC | | eType = = TNITALIC | |
2010-02-12 16:56:44 +01:00
eType = = TSANS | | eType = = TSERIF | | eType = = TFIXED ;
}
void SmXMLExport : : ExportFont ( const SmNode * pNode , int nLevel )
{
2014-02-25 20:41:20 +01:00
2014-04-11 08:52:49 +02:00
// gather the mathvariant attribute relevant data from all
2010-02-12 16:56:44 +01:00
// successively following SmFontNodes...
2014-02-25 20:41:20 +01:00
2010-02-12 16:56:44 +01:00
int nBold = - 1 ; // for the following variables: -1 = yet undefined; 0 = false; 1 = true;
int nItalic = - 1 ; // for the following variables: -1 = yet undefined; 0 = false; 1 = true;
int nSansSerifFixed = - 1 ;
SmTokenType eNodeType = TUNKNOWN ;
while ( lcl_HasEffectOnMathvariant ( ( eNodeType = pNode - > GetToken ( ) . eType ) ) )
{
switch ( eNodeType )
{
case TBOLD : nBold = 1 ; break ;
case TNBOLD : nBold = 0 ; break ;
case TITALIC : nItalic = 1 ; break ;
case TNITALIC : nItalic = 0 ; break ;
case TSANS : nSansSerifFixed = 0 ; break ;
case TSERIF : nSansSerifFixed = 1 ; break ;
case TFIXED : nSansSerifFixed = 2 ; break ;
default :
2013-09-09 08:52:34 +02:00
SAL_WARN ( " starmath " , " unexpected case " ) ;
2010-02-12 16:56:44 +01:00
}
2015-07-02 18:25:02 +02:00
// According to the parser every node that is to be evaluated here
2010-02-12 16:56:44 +01:00
// has a single non-zero subnode at index 1!! Thus we only need to check
// that single node for follow-up nodes that have an effect on the attribute.
if ( pNode - > GetNumSubNodes ( ) > 1 & & pNode - > GetSubNode ( 1 ) & &
lcl_HasEffectOnMathvariant ( pNode - > GetSubNode ( 1 ) - > GetToken ( ) . eType ) )
{
pNode = pNode - > GetSubNode ( 1 ) ;
}
else
break ;
}
switch ( pNode - > GetToken ( ) . eType )
{
case TPHANTOM :
2013-06-30 17:34:40 +02:00
// No attribute needed. An <mphantom> element will be used below.
2010-02-12 16:56:44 +01:00
break ;
case TBLACK :
AddAttribute ( XML_NAMESPACE_MATH , XML_COLOR , XML_BLACK ) ;
break ;
case TWHITE :
AddAttribute ( XML_NAMESPACE_MATH , XML_COLOR , XML_WHITE ) ;
break ;
case TRED :
AddAttribute ( XML_NAMESPACE_MATH , XML_COLOR , XML_RED ) ;
break ;
case TGREEN :
AddAttribute ( XML_NAMESPACE_MATH , XML_COLOR , XML_GREEN ) ;
break ;
case TBLUE :
AddAttribute ( XML_NAMESPACE_MATH , XML_COLOR , XML_BLUE ) ;
break ;
case TCYAN :
AddAttribute ( XML_NAMESPACE_MATH , XML_COLOR , XML_AQUA ) ;
break ;
case TMAGENTA :
AddAttribute ( XML_NAMESPACE_MATH , XML_COLOR , XML_FUCHSIA ) ;
break ;
case TYELLOW :
AddAttribute ( XML_NAMESPACE_MATH , XML_COLOR , XML_YELLOW ) ;
break ;
2014-10-30 18:41:23 +00:00
case TSILVER :
AddAttribute ( XML_NAMESPACE_MATH , XML_COLOR , XML_SILVER ) ;
break ;
case TGRAY :
AddAttribute ( XML_NAMESPACE_MATH , XML_COLOR , XML_GRAY ) ;
break ;
case TMAROON :
AddAttribute ( XML_NAMESPACE_MATH , XML_COLOR , XML_MAROON ) ;
break ;
case TOLIVE :
AddAttribute ( XML_NAMESPACE_MATH , XML_COLOR , XML_OLIVE ) ;
break ;
case TLIME :
AddAttribute ( XML_NAMESPACE_MATH , XML_COLOR , XML_LIME ) ;
break ;
case TAQUA :
AddAttribute ( XML_NAMESPACE_MATH , XML_COLOR , XML_AQUA ) ;
break ;
case TTEAL :
AddAttribute ( XML_NAMESPACE_MATH , XML_COLOR , XML_TEAL ) ;
break ;
case TNAVY :
AddAttribute ( XML_NAMESPACE_MATH , XML_COLOR , XML_NAVY ) ;
break ;
case TFUCHSIA :
AddAttribute ( XML_NAMESPACE_MATH , XML_COLOR , XML_FUCHSIA ) ;
break ;
case TPURPLE :
AddAttribute ( XML_NAMESPACE_MATH , XML_COLOR , XML_PURPLE ) ;
break ;
2010-02-12 16:56:44 +01:00
case TSIZE :
{
const SmFontNode * pFontNode = static_cast < const SmFontNode * > ( pNode ) ;
2014-10-23 17:41:47 +02:00
const Fraction & aFrac = pFontNode - > GetSizeParameter ( ) ;
2010-02-12 16:56:44 +01:00
OUStringBuffer sStrBuf ;
switch ( pFontNode - > GetSizeType ( ) )
{
2015-04-01 19:35:19 +09:00
case FontSizeType : : MULTIPLY :
#i108468#: clean up xmluconv code duplication, part 1:
move convertNumber64 from SvXMLUnitConverter to sax::converter.
remove duplicate methods from SvXMLUnitConverter:
convertBool, convertPercent, convertColor, convertNumber, convertDouble,
indexOfComma, encodeBase64, decodeBase64, decodeBase64SomeChars,
clearUndefinedChars
2011-10-11 14:19:00 +02:00
: : sax : : Converter : : convertDouble ( sStrBuf ,
2014-10-23 17:41:47 +02:00
static_cast < double > ( aFrac * Fraction ( 100.00 ) ) ) ;
2013-12-20 14:23:33 +02:00
sStrBuf . append ( ' % ' ) ;
2010-02-12 16:56:44 +01:00
break ;
2015-04-01 19:35:19 +09:00
case FontSizeType : : DIVIDE :
#i108468#: clean up xmluconv code duplication, part 1:
move convertNumber64 from SvXMLUnitConverter to sax::converter.
remove duplicate methods from SvXMLUnitConverter:
convertBool, convertPercent, convertColor, convertNumber, convertDouble,
indexOfComma, encodeBase64, decodeBase64, decodeBase64SomeChars,
clearUndefinedChars
2011-10-11 14:19:00 +02:00
: : sax : : Converter : : convertDouble ( sStrBuf ,
2014-10-23 17:41:47 +02:00
static_cast < double > ( Fraction ( 100.00 ) / aFrac ) ) ;
2013-12-20 14:23:33 +02:00
sStrBuf . append ( ' % ' ) ;
2010-02-12 16:56:44 +01:00
break ;
2015-04-01 19:35:19 +09:00
case FontSizeType : : ABSOLUT :
#i108468#: clean up xmluconv code duplication, part 1:
move convertNumber64 from SvXMLUnitConverter to sax::converter.
remove duplicate methods from SvXMLUnitConverter:
convertBool, convertPercent, convertColor, convertNumber, convertDouble,
indexOfComma, encodeBase64, decodeBase64, decodeBase64SomeChars,
clearUndefinedChars
2011-10-11 14:19:00 +02:00
: : sax : : Converter : : convertDouble ( sStrBuf ,
2014-10-23 17:41:47 +02:00
static_cast < double > ( aFrac ) ) ;
2010-02-12 16:56:44 +01:00
sStrBuf . append (
GetXMLToken ( XML_UNIT_PT ) ) ;
break ;
default :
{
//The problem here is that the wheels fall off because
//font size is stored in 100th's of a mm not pts, and
//rounding errors take their toll on the original
//value specified in points.
//Must fix StarMath to retain the original pt values
2014-10-23 17:41:47 +02:00
Fraction aTemp = Sm100th_mmToPts ( pFontNode - > GetFont ( ) .
2010-02-12 16:56:44 +01:00
GetSize ( ) . Height ( ) ) ;
2015-04-01 19:35:19 +09:00
if ( pFontNode - > GetSizeType ( ) = = FontSizeType : : MINUS )
2010-02-12 16:56:44 +01:00
aTemp - = aFrac ;
else
aTemp + = aFrac ;
2014-10-23 17:41:47 +02:00
double mytest = static_cast < double > ( aTemp ) ;
2010-02-12 16:56:44 +01:00
mytest = : : rtl : : math : : round ( mytest , 1 ) ;
#i108468#: clean up xmluconv code duplication, part 1:
move convertNumber64 from SvXMLUnitConverter to sax::converter.
remove duplicate methods from SvXMLUnitConverter:
convertBool, convertPercent, convertColor, convertNumber, convertDouble,
indexOfComma, encodeBase64, decodeBase64, decodeBase64SomeChars,
clearUndefinedChars
2011-10-11 14:19:00 +02:00
: : sax : : Converter : : convertDouble ( sStrBuf , mytest ) ;
2010-02-12 16:56:44 +01:00
sStrBuf . append ( GetXMLToken ( XML_UNIT_PT ) ) ;
}
break ;
}
OUString sStr ( sStrBuf . makeStringAndClear ( ) ) ;
AddAttribute ( XML_NAMESPACE_MATH , XML_MATHSIZE , sStr ) ;
}
break ;
case TBOLD :
case TITALIC :
case TNBOLD :
case TNITALIC :
case TFIXED :
case TSANS :
case TSERIF :
{
// nBold: -1 = yet undefined; 0 = false; 1 = true;
// nItalic: -1 = yet undefined; 0 = false; 1 = true;
// nSansSerifFixed: -1 = undefined; 0 = sans; 1 = serif; 2 = fixed;
const sal_Char * pText = " normal " ;
if ( nSansSerifFixed = = - 1 | | nSansSerifFixed = = 1 )
{
pText = " normal " ;
if ( nBold = = 1 & & nItalic ! = 1 )
pText = " bold " ;
else if ( nBold ! = 1 & & nItalic = = 1 )
pText = " italic " ;
else if ( nBold = = 1 & & nItalic = = 1 )
pText = " bold-italic " ;
}
else if ( nSansSerifFixed = = 0 )
{
pText = " sans-serif " ;
if ( nBold = = 1 & & nItalic ! = 1 )
pText = " bold-sans-serif " ;
else if ( nBold ! = 1 & & nItalic = = 1 )
pText = " sans-serif-italic " ;
else if ( nBold = = 1 & & nItalic = = 1 )
pText = " sans-serif-bold-italic " ;
}
else if ( nSansSerifFixed = = 2 )
pText = " monospace " ; // no modifiers allowed for monospace ...
else
{
2013-09-09 08:52:34 +02:00
SAL_WARN ( " starmath " , " unexpected case " ) ;
2010-02-12 16:56:44 +01:00
}
2012-03-08 14:56:00 +01:00
AddAttribute ( XML_NAMESPACE_MATH , XML_MATHVARIANT , OUString : : createFromAscii ( pText ) ) ;
2010-02-12 16:56:44 +01:00
}
break ;
default :
break ;
}
{
2013-06-30 17:34:40 +02:00
// Wrap everything in an <mphantom> or <mstyle> element. These elements
// are mrow-like, so ExportExpression doesn't need to add an explicit
// <mrow> element. See #fdo 66283.
SvXMLElementExport aElement ( * this , XML_NAMESPACE_MATH ,
pNode - > GetToken ( ) . eType = = TPHANTOM ? XML_MPHANTOM : XML_MSTYLE ,
2014-03-28 16:28:51 +02:00
true , true ) ;
2013-06-30 17:34:40 +02:00
ExportExpression ( pNode , nLevel , true ) ;
2010-02-12 16:56:44 +01:00
}
}
void SmXMLExport : : ExportVerticalBrace ( const SmNode * pNode , int nLevel )
{
2013-07-03 12:17:53 +02:00
// "[body] overbrace [script]"
2014-02-25 20:41:20 +01:00
2013-07-03 12:17:53 +02:00
// Position body, overbrace and script vertically. First place the overbrace
// OVER the body and then the script OVER this expression.
2014-02-25 20:41:20 +01:00
2013-07-03 12:17:53 +02:00
// [script]
// --[overbrace]--
// XXXXXX[body]XXXXXXX
2014-02-25 20:41:20 +01:00
2013-07-03 12:17:53 +02:00
// Similarly for the underbrace construction.
2010-02-12 16:56:44 +01:00
XMLTokenEnum which ;
switch ( pNode - > GetToken ( ) . eType )
{
case TOVERBRACE :
default :
which = XML_MOVER ;
break ;
case TUNDERBRACE :
which = XML_MUNDER ;
break ;
}
2010-10-07 11:02:05 +01:00
OSL_ENSURE ( pNode - > GetNumSubNodes ( ) = = 3 , " Bad Vertical Brace " ) ;
2014-03-28 16:28:51 +02:00
SvXMLElementExport aOver1 ( * this , XML_NAMESPACE_MATH , which , true , true ) ;
2010-02-12 16:56:44 +01:00
{ //Scoping
// using accents will draw the over-/underbraces too close to the base
// see http://www.w3.org/TR/MathML2/chapter3.html#id.3.4.5.2
2014-04-11 08:52:49 +02:00
// also XML_ACCENT is illegal with XML_MUNDER. Thus no XML_ACCENT attribute here!
2014-03-28 16:28:51 +02:00
SvXMLElementExport aOver2 ( * this , XML_NAMESPACE_MATH , which , true , true ) ;
2010-02-12 16:56:44 +01:00
ExportNodes ( pNode - > GetSubNode ( 0 ) , nLevel ) ;
2013-06-30 11:08:15 +02:00
AddAttribute ( XML_NAMESPACE_MATH , XML_STRETCHY , XML_TRUE ) ;
2010-02-12 16:56:44 +01:00
ExportNodes ( pNode - > GetSubNode ( 1 ) , nLevel ) ;
}
ExportNodes ( pNode - > GetSubNode ( 2 ) , nLevel ) ;
}
void SmXMLExport : : ExportMatrix ( const SmNode * pNode , int nLevel )
{
2014-03-28 16:28:51 +02:00
SvXMLElementExport aTable ( * this , XML_NAMESPACE_MATH , XML_MTABLE , true , true ) ;
2010-02-12 16:56:44 +01:00
const SmMatrixNode * pMatrix = static_cast < const SmMatrixNode * > ( pNode ) ;
2011-01-14 17:19:25 +01:00
sal_uInt16 i = 0 ;
2015-02-18 17:21:39 +09:00
for ( sal_uInt16 y = 0 ; y < pMatrix - > GetNumRows ( ) ; y + + )
2010-02-12 16:56:44 +01:00
{
2014-03-28 16:28:51 +02:00
SvXMLElementExport aRow ( * this , XML_NAMESPACE_MATH , XML_MTR , true , true ) ;
2015-02-18 17:21:39 +09:00
for ( sal_uInt16 x = 0 ; x < pMatrix - > GetNumCols ( ) ; x + + )
2010-02-12 16:56:44 +01:00
if ( const SmNode * pTemp = pNode - > GetSubNode ( i + + ) )
{
2013-06-29 22:51:58 +02:00
if ( pTemp - > GetType ( ) = = NALIGN & &
pTemp - > GetToken ( ) . eType ! = TALIGNC )
{
// A left or right alignment is specified on this cell,
// attach the corresponding columnalign attribute.
AddAttribute ( XML_NAMESPACE_MATH , XML_COLUMNALIGN ,
pTemp - > GetToken ( ) . eType = = TALIGNL ?
XML_LEFT : XML_RIGHT ) ;
}
2014-03-28 16:28:51 +02:00
SvXMLElementExport aCell ( * this , XML_NAMESPACE_MATH , XML_MTD , true , true ) ;
2010-02-12 16:56:44 +01:00
ExportNodes ( pTemp , nLevel + 1 ) ;
}
}
}
void SmXMLExport : : ExportNodes ( const SmNode * pNode , int nLevel )
{
if ( ! pNode )
return ;
switch ( pNode - > GetType ( ) )
{
case NTABLE :
ExportTable ( pNode , nLevel ) ;
break ;
case NALIGN :
case NBRACEBODY :
case NEXPRESSION :
ExportExpression ( pNode , nLevel ) ;
break ;
case NLINE :
ExportLine ( pNode , nLevel ) ;
break ;
case NTEXT :
ExportText ( pNode , nLevel ) ;
break ;
case NGLYPH_SPECIAL :
case NMATH :
{
sal_Unicode cTmp = 0 ;
const SmTextNode * pTemp = static_cast < const SmTextNode * > ( pNode ) ;
2012-10-01 20:46:34 +04:00
if ( ! pTemp - > GetText ( ) . isEmpty ( ) )
cTmp = ConvertMathToMathML ( pTemp - > GetText ( ) [ 0 ] ) ;
2010-02-12 16:56:44 +01:00
if ( cTmp = = 0 )
{
// no conversion to MathML implemented -> export it as text
// thus at least it will not vanish into nothing
ExportText ( pNode , nLevel ) ;
}
else
{
//To fully handle generic MathML we need to implement the full
//operator dictionary, we will generate MathML with explicit
//stretchiness for now.
sal_Int16 nLength = GetAttrList ( ) . getLength ( ) ;
2014-04-24 12:22:08 +02:00
bool bAddStretch = true ;
2010-02-12 16:56:44 +01:00
for ( sal_Int16 i = 0 ; i < nLength ; i + + )
{
OUString sLocalName ;
sal_uInt16 nPrefix = GetNamespaceMap ( ) . GetKeyByAttrName (
GetAttrList ( ) . getNameByIndex ( i ) , & sLocalName ) ;
if ( ( XML_NAMESPACE_MATH = = nPrefix ) & &
IsXMLToken ( sLocalName , XML_STRETCHY ) )
{
2014-04-24 12:22:08 +02:00
bAddStretch = false ;
2010-02-12 16:56:44 +01:00
break ;
}
}
if ( bAddStretch )
{
AddAttribute ( XML_NAMESPACE_MATH , XML_STRETCHY , XML_FALSE ) ;
}
ExportMath ( pNode , nLevel ) ;
}
}
break ;
2013-06-30 14:06:23 +02:00
case NSPECIAL : //NSPECIAL requires some sort of Entity preservation in the XML engine.
2013-06-27 21:35:28 +02:00
case NMATHIDENT :
2010-02-12 16:56:44 +01:00
case NPLACE :
ExportMath ( pNode , nLevel ) ;
break ;
case NBINHOR :
ExportBinaryHorizontal ( pNode , nLevel ) ;
break ;
case NUNHOR :
ExportUnaryHorizontal ( pNode , nLevel ) ;
break ;
case NBRACE :
ExportBrace ( pNode , nLevel ) ;
break ;
case NBINVER :
ExportBinaryVertical ( pNode , nLevel ) ;
break ;
2013-06-23 21:32:37 +02:00
case NBINDIAGONAL :
ExportBinaryDiagonal ( pNode , nLevel ) ;
break ;
2010-02-12 16:56:44 +01:00
case NSUBSUP :
ExportSubSupScript ( pNode , nLevel ) ;
break ;
case NROOT :
ExportRoot ( pNode , nLevel ) ;
break ;
case NOPER :
ExportOperator ( pNode , nLevel ) ;
break ;
case NATTRIBUT :
ExportAttributes ( pNode , nLevel ) ;
break ;
case NFONT :
ExportFont ( pNode , nLevel ) ;
break ;
case NVERTICAL_BRACE :
ExportVerticalBrace ( pNode , nLevel ) ;
break ;
case NMATRIX :
ExportMatrix ( pNode , nLevel ) ;
break ;
case NBLANK :
ExportBlank ( pNode , nLevel ) ;
break ;
default :
2013-09-09 08:52:34 +02:00
SAL_WARN ( " starmath " , " Warning: failed to export a node? " ) ;
2010-02-12 16:56:44 +01:00
break ;
}
}
2010-10-14 08:30:41 +02:00
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */