diff options
Diffstat (limited to 'starmath/source/ooxmlexport.cxx')
-rw-r--r-- | starmath/source/ooxmlexport.cxx | 600 |
1 files changed, 600 insertions, 0 deletions
diff --git a/starmath/source/ooxmlexport.cxx b/starmath/source/ooxmlexport.cxx new file mode 100644 index 000000000..fff9cd7c5 --- /dev/null +++ b/starmath/source/ooxmlexport.cxx @@ -0,0 +1,600 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "ooxmlexport.hxx" +#include <node.hxx> + +#include <oox/token/tokens.hxx> +#include <rtl/ustring.hxx> +#include <sal/log.hxx> +#include <oox/mathml/export.hxx> + +using namespace oox; +using namespace oox::core; + +SmOoxmlExport::SmOoxmlExport(const SmNode *const pIn, OoxmlVersion const v, + drawingml::DocumentType const documentType) +: SmWordExportBase( pIn ) +, version( v ) +, m_DocumentType(documentType) +{ +} + +void SmOoxmlExport::ConvertFromStarMath( const ::sax_fastparser::FSHelperPtr& serializer, const sal_Int8 nAlign ) +{ + if( m_pTree == nullptr ) + return; + m_pSerializer = serializer; + + //Formula alignment situations: + // + // 1)Inline(as before): + // + // <m:oMath> + // <m:r> ... </m:r> + // </m:oMath> + // + // 2)Aligned: + // + // <m:oMathPara> + // <m:oMathParaPr> + // <m:jc m:val="left|right|center"> + // </m:oMathParaPr> + // <m:oMath> + // <m:r> ... </m:r> + // </m:oMath> + // </m:oMathPara> + + if (nAlign != FormulaExportBase::eFormulaAlign::INLINE) + { + m_pSerializer->startElementNS(XML_m, XML_oMathPara, + FSNS(XML_xmlns, XML_m), "http://schemas.openxmlformats.org/officeDocument/2006/math"); + m_pSerializer->startElementNS(XML_m, XML_oMathParaPr); + if (nAlign == FormulaExportBase::eFormulaAlign::CENTER) + m_pSerializer->singleElementNS(XML_m, XML_jc, FSNS(XML_m, XML_val), "center"); + if (nAlign == FormulaExportBase::eFormulaAlign::GROUPEDCENTER) + m_pSerializer->singleElementNS(XML_m, XML_jc, FSNS(XML_m, XML_val), "center"); + if (nAlign == FormulaExportBase::eFormulaAlign::LEFT) + m_pSerializer->singleElementNS(XML_m, XML_jc, FSNS(XML_m, XML_val), "left"); + if (nAlign == FormulaExportBase::eFormulaAlign::RIGHT) + m_pSerializer->singleElementNS(XML_m, XML_jc, FSNS(XML_m, XML_val), "right"); + m_pSerializer->endElementNS(XML_m, XML_oMathParaPr); + m_pSerializer->startElementNS(XML_m, XML_oMath); + HandleNode(m_pTree, 0); + m_pSerializer->endElementNS(XML_m, XML_oMath); + m_pSerializer->endElementNS(XML_m, XML_oMathPara); + } + else //else, inline as was before + { + m_pSerializer->startElementNS(XML_m, XML_oMath, + FSNS(XML_xmlns, XML_m), "http://schemas.openxmlformats.org/officeDocument/2006/math"); + HandleNode( m_pTree, 0 ); + m_pSerializer->endElementNS( XML_m, XML_oMath ); + } +} + +// NOTE: This is still work in progress and unfinished, but it already covers a good +// part of the ooxml math stuff. + +void SmOoxmlExport::HandleVerticalStack( const SmNode* pNode, int nLevel ) +{ + m_pSerializer->startElementNS(XML_m, XML_eqArr); + int size = pNode->GetNumSubNodes(); + for( int i = 0; + i < size; + ++i ) + { + m_pSerializer->startElementNS(XML_m, XML_e); + HandleNode( pNode->GetSubNode( i ), nLevel + 1 ); + m_pSerializer->endElementNS( XML_m, XML_e ); + } + m_pSerializer->endElementNS( XML_m, XML_eqArr ); +} + +void SmOoxmlExport::HandleText( const SmNode* pNode, int /*nLevel*/) +{ + m_pSerializer->startElementNS(XML_m, XML_r); + + if( pNode->GetToken().eType == TTEXT ) // literal text (in quotes) + { + m_pSerializer->startElementNS(XML_m, XML_rPr); + m_pSerializer->singleElementNS(XML_m, XML_lit); + m_pSerializer->singleElementNS(XML_m, XML_nor); + m_pSerializer->endElementNS( XML_m, XML_rPr ); + } + if (drawingml::DOCUMENT_DOCX == m_DocumentType && ECMA_DIALECT == version) + { // HACK: MSOffice2007 does not import characters properly unless this font is explicitly given + m_pSerializer->startElementNS(XML_w, XML_rPr); + m_pSerializer->singleElementNS( XML_w, XML_rFonts, FSNS( XML_w, XML_ascii ), "Cambria Math", + FSNS( XML_w, XML_hAnsi ), "Cambria Math" ); + m_pSerializer->endElementNS( XML_w, XML_rPr ); + } + m_pSerializer->startElementNS(XML_m, XML_t, FSNS(XML_xml, XML_space), "preserve"); + const SmTextNode* pTemp = static_cast<const SmTextNode* >(pNode); + SAL_INFO( "starmath.ooxml", "Text:" << pTemp->GetText()); + OUStringBuffer buf(pTemp->GetText()); + for(sal_Int32 i=0;i<pTemp->GetText().getLength();i++) + { +#if 0 + if ((nPendingAttributes) && + (i == ((pTemp->GetText().getLength()+1)/2)-1)) + { + *pS << sal_uInt8(0x22); //char, with attributes right + //after the character + } + else + *pS << sal_uInt8(CHAR); + + sal_uInt8 nFace = 0x1; + if (pNode->GetFont().GetItalic() == ITALIC_NORMAL) + nFace = 0x3; + else if (pNode->GetFont().GetWeight() == WEIGHT_BOLD) + nFace = 0x7; + *pS << sal_uInt8(nFace+128); //typeface +#endif + buf[i] = SmTextNode::ConvertSymbolToUnicode(buf[i]); +#if 0 + //Mathtype can only have these sort of character + //attributes on a single character, starmath can put them + //anywhere, when the entity involved is a text run this is + //a large effort to place the character attribute on the + //central mathtype character so that it does pretty much + //what the user probably has in mind. The attributes + //filled in here are dummy ones which are replaced in the + //ATTRIBUT handler if a suitable location for the + //attributes was found here. Unfortunately it is + //possible for starmath to place character attributes on + //entities which cannot occur in mathtype e.g. a Summation + //symbol so these attributes may be lost + if ((nPendingAttributes) && + (i == ((pTemp->GetText().getLength()+1)/2)-1)) + { + *pS << sal_uInt8(EMBEL); + while (nPendingAttributes) + { + *pS << sal_uInt8(2); + //wedge the attributes in here and clear + //the pending stack + nPendingAttributes--; + } + nInsertion=pS->Tell(); + *pS << sal_uInt8(END); //end embel + *pS << sal_uInt8(END); //end embel + } +#endif + } + m_pSerializer->writeEscaped(buf.makeStringAndClear()); + m_pSerializer->endElementNS( XML_m, XML_t ); + m_pSerializer->endElementNS( XML_m, XML_r ); +} + +void SmOoxmlExport::HandleFractions( const SmNode* pNode, int nLevel, const char* type ) +{ + m_pSerializer->startElementNS(XML_m, XML_f); + if( type != nullptr ) + { + m_pSerializer->startElementNS(XML_m, XML_fPr); + m_pSerializer->singleElementNS(XML_m, XML_type, FSNS(XML_m, XML_val), type); + m_pSerializer->endElementNS( XML_m, XML_fPr ); + } + assert( pNode->GetNumSubNodes() == 3 ); + m_pSerializer->startElementNS(XML_m, XML_num); + HandleNode( pNode->GetSubNode( 0 ), nLevel + 1 ); + m_pSerializer->endElementNS( XML_m, XML_num ); + m_pSerializer->startElementNS(XML_m, XML_den); + HandleNode( pNode->GetSubNode( 2 ), nLevel + 1 ); + m_pSerializer->endElementNS( XML_m, XML_den ); + m_pSerializer->endElementNS( XML_m, XML_f ); +} + +void SmOoxmlExport::HandleAttribute( const SmAttributNode* pNode, int nLevel ) +{ + switch( pNode->Attribute()->GetToken().eType ) + { + case TCHECK: + case TACUTE: + case TGRAVE: + case TBREVE: + case TCIRCLE: + case TVEC: + case TTILDE: + case THAT: + case TDOT: + case TDDOT: + case TDDDOT: + case TWIDETILDE: + case TWIDEHAT: + case TWIDEHARPOON: + case TWIDEVEC: + case TBAR: + { + m_pSerializer->startElementNS(XML_m, XML_acc); + m_pSerializer->startElementNS(XML_m, XML_accPr); + OString value = OUStringToOString( + OUString( pNode->Attribute()->GetToken().cMathChar ), RTL_TEXTENCODING_UTF8 ); + m_pSerializer->singleElementNS(XML_m, XML_chr, FSNS(XML_m, XML_val), value); + m_pSerializer->endElementNS( XML_m, XML_accPr ); + m_pSerializer->startElementNS(XML_m, XML_e); + HandleNode( pNode->Body(), nLevel + 1 ); + m_pSerializer->endElementNS( XML_m, XML_e ); + m_pSerializer->endElementNS( XML_m, XML_acc ); + break; + } + case TOVERLINE: + case TUNDERLINE: + m_pSerializer->startElementNS(XML_m, XML_bar); + m_pSerializer->startElementNS(XML_m, XML_barPr); + m_pSerializer->singleElementNS( XML_m, XML_pos, FSNS( XML_m, XML_val ), + ( pNode->Attribute()->GetToken().eType == TUNDERLINE ) ? "bot" : "top" ); + m_pSerializer->endElementNS( XML_m, XML_barPr ); + m_pSerializer->startElementNS(XML_m, XML_e); + HandleNode( pNode->Body(), nLevel + 1 ); + m_pSerializer->endElementNS( XML_m, XML_e ); + m_pSerializer->endElementNS( XML_m, XML_bar ); + break; + case TOVERSTRIKE: + m_pSerializer->startElementNS(XML_m, XML_borderBox); + m_pSerializer->startElementNS(XML_m, XML_borderBoxPr); + m_pSerializer->singleElementNS(XML_m, XML_hideTop, FSNS(XML_m, XML_val), "1"); + m_pSerializer->singleElementNS(XML_m, XML_hideBot, FSNS(XML_m, XML_val), "1"); + m_pSerializer->singleElementNS(XML_m, XML_hideLeft, FSNS(XML_m, XML_val), "1"); + m_pSerializer->singleElementNS(XML_m, XML_hideRight, FSNS(XML_m, XML_val), "1"); + m_pSerializer->singleElementNS(XML_m, XML_strikeH, FSNS(XML_m, XML_val), "1"); + m_pSerializer->endElementNS( XML_m, XML_borderBoxPr ); + m_pSerializer->startElementNS(XML_m, XML_e); + HandleNode( pNode->Body(), nLevel + 1 ); + m_pSerializer->endElementNS( XML_m, XML_e ); + m_pSerializer->endElementNS( XML_m, XML_borderBox ); + break; + default: + HandleAllSubNodes( pNode, nLevel ); + break; + } +} + +void SmOoxmlExport::HandleRoot( const SmRootNode* pNode, int nLevel ) +{ + m_pSerializer->startElementNS(XML_m, XML_rad); + if( const SmNode* argument = pNode->Argument()) + { + m_pSerializer->startElementNS(XML_m, XML_deg); + HandleNode( argument, nLevel + 1 ); + m_pSerializer->endElementNS( XML_m, XML_deg ); + } + else + { + m_pSerializer->startElementNS(XML_m, XML_radPr); + m_pSerializer->singleElementNS(XML_m, XML_degHide, FSNS(XML_m, XML_val), "1"); + m_pSerializer->endElementNS( XML_m, XML_radPr ); + m_pSerializer->singleElementNS(XML_m, XML_deg); // empty but present + } + m_pSerializer->startElementNS(XML_m, XML_e); + HandleNode( pNode->Body(), nLevel + 1 ); + m_pSerializer->endElementNS( XML_m, XML_e ); + m_pSerializer->endElementNS( XML_m, XML_rad ); +} + +static OString mathSymbolToString( const SmNode* node ) +{ + assert( node->GetType() == SmNodeType::Math || node->GetType() == SmNodeType::MathIdent ); + const SmTextNode* txtnode = static_cast< const SmTextNode* >( node ); + assert( txtnode->GetText().getLength() == 1 ); + sal_Unicode chr = SmTextNode::ConvertSymbolToUnicode( txtnode->GetText()[0] ); + return OUStringToOString( OUString( chr ), RTL_TEXTENCODING_UTF8 ); +} + +void SmOoxmlExport::HandleOperator( const SmOperNode* pNode, int nLevel ) +{ + SAL_INFO( "starmath.ooxml", "Operator: " << int( pNode->GetToken().eType )); + switch( pNode->GetToken().eType ) + { + case TINT: + case TINTD: + case TIINT: + case TIIINT: + case TLINT: + case TLLINT: + case TLLLINT: + case TPROD: + case TCOPROD: + case TSUM: + { + const SmSubSupNode* subsup = pNode->GetSubNode( 0 )->GetType() == SmNodeType::SubSup + ? static_cast< const SmSubSupNode* >( pNode->GetSubNode( 0 )) : nullptr; + const SmNode* operation = subsup != nullptr ? subsup->GetBody() : pNode->GetSubNode( 0 ); + m_pSerializer->startElementNS(XML_m, XML_nary); + m_pSerializer->startElementNS(XML_m, XML_naryPr); + m_pSerializer->singleElementNS( XML_m, XML_chr, + FSNS( XML_m, XML_val ), mathSymbolToString(operation) ); + if( subsup == nullptr || subsup->GetSubSup( CSUB ) == nullptr ) + m_pSerializer->singleElementNS(XML_m, XML_subHide, FSNS(XML_m, XML_val), "1"); + if( subsup == nullptr || subsup->GetSubSup( CSUP ) == nullptr ) + m_pSerializer->singleElementNS(XML_m, XML_supHide, FSNS(XML_m, XML_val), "1"); + m_pSerializer->endElementNS( XML_m, XML_naryPr ); + if( subsup == nullptr || subsup->GetSubSup( CSUB ) == nullptr ) + m_pSerializer->singleElementNS(XML_m, XML_sub); + else + { + m_pSerializer->startElementNS(XML_m, XML_sub); + HandleNode( subsup->GetSubSup( CSUB ), nLevel + 1 ); + m_pSerializer->endElementNS( XML_m, XML_sub ); + } + if( subsup == nullptr || subsup->GetSubSup( CSUP ) == nullptr ) + m_pSerializer->singleElementNS(XML_m, XML_sup); + else + { + m_pSerializer->startElementNS(XML_m, XML_sup); + HandleNode( subsup->GetSubSup( CSUP ), nLevel + 1 ); + m_pSerializer->endElementNS( XML_m, XML_sup ); + } + m_pSerializer->startElementNS(XML_m, XML_e); + HandleNode( pNode->GetSubNode( 1 ), nLevel + 1 ); // body + m_pSerializer->endElementNS( XML_m, XML_e ); + m_pSerializer->endElementNS( XML_m, XML_nary ); + break; + } + case TLIM: + m_pSerializer->startElementNS(XML_m, XML_func); + m_pSerializer->startElementNS(XML_m, XML_fName); + m_pSerializer->startElementNS(XML_m, XML_limLow); + m_pSerializer->startElementNS(XML_m, XML_e); + HandleNode( pNode->GetSymbol(), nLevel + 1 ); + m_pSerializer->endElementNS( XML_m, XML_e ); + m_pSerializer->startElementNS(XML_m, XML_lim); + if( const SmSubSupNode* subsup = pNode->GetSubNode( 0 )->GetType() == SmNodeType::SubSup + ? static_cast< const SmSubSupNode* >( pNode->GetSubNode( 0 )) : nullptr ) + { + if( subsup->GetSubSup( CSUB ) != nullptr ) + HandleNode( subsup->GetSubSup( CSUB ), nLevel + 1 ); + } + m_pSerializer->endElementNS( XML_m, XML_lim ); + m_pSerializer->endElementNS( XML_m, XML_limLow ); + m_pSerializer->endElementNS( XML_m, XML_fName ); + m_pSerializer->startElementNS(XML_m, XML_e); + HandleNode( pNode->GetSubNode( 1 ), nLevel + 1 ); // body + m_pSerializer->endElementNS( XML_m, XML_e ); + m_pSerializer->endElementNS( XML_m, XML_func ); + break; + default: + SAL_WARN("starmath.ooxml", "Unhandled operation"); + HandleAllSubNodes( pNode, nLevel ); + break; + } +} + +void SmOoxmlExport::HandleSubSupScriptInternal( const SmSubSupNode* pNode, int nLevel, int flags ) +{ +// docx supports only a certain combination of sub/super scripts, but LO can have any, +// so try to merge it using several tags if necessary + if( flags == 0 ) // none + return; + if(( flags & ( 1 << RSUP | 1 << RSUB )) == ( 1 << RSUP | 1 << RSUB )) + { // m:sSubSup + m_pSerializer->startElementNS(XML_m, XML_sSubSup); + m_pSerializer->startElementNS(XML_m, XML_e); + flags &= ~( 1 << RSUP | 1 << RSUB ); + if( flags == 0 ) + HandleNode( pNode->GetBody(), nLevel + 1 ); + else + HandleSubSupScriptInternal( pNode, nLevel, flags ); + m_pSerializer->endElementNS( XML_m, XML_e ); + m_pSerializer->startElementNS(XML_m, XML_sub); + HandleNode( pNode->GetSubSup( RSUB ), nLevel + 1 ); + m_pSerializer->endElementNS( XML_m, XML_sub ); + m_pSerializer->startElementNS(XML_m, XML_sup); + HandleNode( pNode->GetSubSup( RSUP ), nLevel + 1 ); + m_pSerializer->endElementNS( XML_m, XML_sup ); + m_pSerializer->endElementNS( XML_m, XML_sSubSup ); + } + else if(( flags & ( 1 << RSUB )) == 1 << RSUB ) + { // m:sSub + m_pSerializer->startElementNS(XML_m, XML_sSub); + m_pSerializer->startElementNS(XML_m, XML_e); + flags &= ~( 1 << RSUB ); + if( flags == 0 ) + HandleNode( pNode->GetBody(), nLevel + 1 ); + else + HandleSubSupScriptInternal( pNode, nLevel, flags ); + m_pSerializer->endElementNS( XML_m, XML_e ); + m_pSerializer->startElementNS(XML_m, XML_sub); + HandleNode( pNode->GetSubSup( RSUB ), nLevel + 1 ); + m_pSerializer->endElementNS( XML_m, XML_sub ); + m_pSerializer->endElementNS( XML_m, XML_sSub ); + } + else if(( flags & ( 1 << RSUP )) == 1 << RSUP ) + { // m:sSup + m_pSerializer->startElementNS(XML_m, XML_sSup); + m_pSerializer->startElementNS(XML_m, XML_e); + flags &= ~( 1 << RSUP ); + if( flags == 0 ) + HandleNode( pNode->GetBody(), nLevel + 1 ); + else + HandleSubSupScriptInternal( pNode, nLevel, flags ); + m_pSerializer->endElementNS( XML_m, XML_e ); + m_pSerializer->startElementNS(XML_m, XML_sup); + HandleNode( pNode->GetSubSup( RSUP ), nLevel + 1 ); + m_pSerializer->endElementNS( XML_m, XML_sup ); + m_pSerializer->endElementNS( XML_m, XML_sSup ); + } + else if(( flags & ( 1 << LSUP | 1 << LSUB )) == ( 1 << LSUP | 1 << LSUB )) + { // m:sPre + m_pSerializer->startElementNS(XML_m, XML_sPre); + m_pSerializer->startElementNS(XML_m, XML_sub); + HandleNode( pNode->GetSubSup( LSUB ), nLevel + 1 ); + m_pSerializer->endElementNS( XML_m, XML_sub ); + m_pSerializer->startElementNS(XML_m, XML_sup); + HandleNode( pNode->GetSubSup( LSUP ), nLevel + 1 ); + m_pSerializer->endElementNS( XML_m, XML_sup ); + m_pSerializer->startElementNS(XML_m, XML_e); + flags &= ~( 1 << LSUP | 1 << LSUB ); + if( flags == 0 ) + HandleNode( pNode->GetBody(), nLevel + 1 ); + else + HandleSubSupScriptInternal( pNode, nLevel, flags ); + m_pSerializer->endElementNS( XML_m, XML_e ); + m_pSerializer->endElementNS( XML_m, XML_sPre ); + } + else if(( flags & ( 1 << CSUB )) == ( 1 << CSUB )) + { // m:limLow looks like a good element for central superscript + m_pSerializer->startElementNS(XML_m, XML_limLow); + m_pSerializer->startElementNS(XML_m, XML_e); + flags &= ~( 1 << CSUB ); + if( flags == 0 ) + HandleNode( pNode->GetBody(), nLevel + 1 ); + else + HandleSubSupScriptInternal( pNode, nLevel, flags ); + m_pSerializer->endElementNS( XML_m, XML_e ); + m_pSerializer->startElementNS(XML_m, XML_lim); + HandleNode( pNode->GetSubSup( CSUB ), nLevel + 1 ); + m_pSerializer->endElementNS( XML_m, XML_lim ); + m_pSerializer->endElementNS( XML_m, XML_limLow ); + } + else if(( flags & ( 1 << CSUP )) == ( 1 << CSUP )) + { // m:limUpp looks like a good element for central superscript + m_pSerializer->startElementNS(XML_m, XML_limUpp); + m_pSerializer->startElementNS(XML_m, XML_e); + flags &= ~( 1 << CSUP ); + if( flags == 0 ) + HandleNode( pNode->GetBody(), nLevel + 1 ); + else + HandleSubSupScriptInternal( pNode, nLevel, flags ); + m_pSerializer->endElementNS( XML_m, XML_e ); + m_pSerializer->startElementNS(XML_m, XML_lim); + HandleNode( pNode->GetSubSup( CSUP ), nLevel + 1 ); + m_pSerializer->endElementNS( XML_m, XML_lim ); + m_pSerializer->endElementNS( XML_m, XML_limUpp ); + } + else + { + SAL_WARN("starmath.ooxml", "Unhandled sub/sup combination"); + // TODO do not do anything, this should be probably an assert() + // HandleAllSubNodes( pNode, nLevel ); + } +} + +void SmOoxmlExport::HandleMatrix( const SmMatrixNode* pNode, int nLevel ) +{ + m_pSerializer->startElementNS(XML_m, XML_m); + for (size_t row = 0; row < pNode->GetNumRows(); ++row) + { + m_pSerializer->startElementNS(XML_m, XML_mr); + for (size_t col = 0; col < pNode->GetNumCols(); ++col) + { + m_pSerializer->startElementNS(XML_m, XML_e); + if( const SmNode* node = pNode->GetSubNode( row * pNode->GetNumCols() + col )) + HandleNode( node, nLevel + 1 ); + m_pSerializer->endElementNS( XML_m, XML_e ); + } + m_pSerializer->endElementNS( XML_m, XML_mr ); + } + m_pSerializer->endElementNS( XML_m, XML_m ); +} + +void SmOoxmlExport::HandleBrace( const SmBraceNode* pNode, int nLevel ) +{ + m_pSerializer->startElementNS(XML_m, XML_d); + m_pSerializer->startElementNS(XML_m, XML_dPr); + + //check if the node has an opening brace + if( TNONE == pNode->OpeningBrace()->GetToken().eType ) + m_pSerializer->singleElementNS(XML_m, XML_begChr, FSNS(XML_m, XML_val), ""); + else + m_pSerializer->singleElementNS( XML_m, XML_begChr, + FSNS( XML_m, XML_val ), mathSymbolToString( pNode->OpeningBrace()) ); + + std::vector< const SmNode* > subnodes; + if( pNode->Body()->GetType() == SmNodeType::Bracebody ) + { + const SmBracebodyNode* body = static_cast< const SmBracebodyNode* >( pNode->Body()); + bool separatorWritten = false; // assume all separators are the same + for (size_t i = 0; i < body->GetNumSubNodes(); ++i) + { + const SmNode* subnode = body->GetSubNode( i ); + if (subnode->GetType() == SmNodeType::Math || subnode->GetType() == SmNodeType::MathIdent) + { // do not write, but write what separator it is + const SmMathSymbolNode* math = static_cast< const SmMathSymbolNode* >( subnode ); + if( !separatorWritten ) + { + m_pSerializer->singleElementNS( XML_m, XML_sepChr, + FSNS( XML_m, XML_val ), mathSymbolToString(math) ); + separatorWritten = true; + } + } + else + subnodes.push_back( subnode ); + } + } + else + subnodes.push_back( pNode->Body()); + + if( TNONE == pNode->ClosingBrace()->GetToken().eType ) + m_pSerializer->singleElementNS(XML_m, XML_endChr, FSNS(XML_m, XML_val), ""); + else + m_pSerializer->singleElementNS( XML_m, XML_endChr, + FSNS( XML_m, XML_val ), mathSymbolToString(pNode->ClosingBrace()) ); + + m_pSerializer->endElementNS( XML_m, XML_dPr ); + for(const SmNode* subnode : subnodes) + { + m_pSerializer->startElementNS(XML_m, XML_e); + HandleNode( subnode, nLevel + 1 ); + m_pSerializer->endElementNS( XML_m, XML_e ); + } + m_pSerializer->endElementNS( XML_m, XML_d ); +} + +void SmOoxmlExport::HandleVerticalBrace( const SmVerticalBraceNode* pNode, int nLevel ) +{ + SAL_INFO( "starmath.ooxml", "Vertical: " << int( pNode->GetToken().eType )); + switch( pNode->GetToken().eType ) + { + case TOVERBRACE: + case TUNDERBRACE: + { + bool top = ( pNode->GetToken().eType == TOVERBRACE ); + m_pSerializer->startElementNS(XML_m, top ? XML_limUpp : XML_limLow); + m_pSerializer->startElementNS(XML_m, XML_e); + m_pSerializer->startElementNS(XML_m, XML_groupChr); + m_pSerializer->startElementNS(XML_m, XML_groupChrPr); + m_pSerializer->singleElementNS( XML_m, XML_chr, + FSNS( XML_m, XML_val ), mathSymbolToString(pNode->Brace()) ); + // TODO not sure if pos and vertJc are correct + m_pSerializer->singleElementNS( XML_m, XML_pos, + FSNS( XML_m, XML_val ), top ? "top" : "bot" ); + m_pSerializer->singleElementNS(XML_m, XML_vertJc, FSNS(XML_m, XML_val), + top ? "bot" : "top"); + m_pSerializer->endElementNS( XML_m, XML_groupChrPr ); + m_pSerializer->startElementNS(XML_m, XML_e); + HandleNode( pNode->Body(), nLevel + 1 ); + m_pSerializer->endElementNS( XML_m, XML_e ); + m_pSerializer->endElementNS( XML_m, XML_groupChr ); + m_pSerializer->endElementNS( XML_m, XML_e ); + m_pSerializer->startElementNS(XML_m, XML_lim); + HandleNode( pNode->Script(), nLevel + 1 ); + m_pSerializer->endElementNS( XML_m, XML_lim ); + m_pSerializer->endElementNS( XML_m, top ? XML_limUpp : XML_limLow ); + break; + } + default: + SAL_WARN("starmath.ooxml", "Unhandled vertical brace"); + HandleAllSubNodes( pNode, nLevel ); + break; + } +} + +void SmOoxmlExport::HandleBlank() +{ + m_pSerializer->startElementNS(XML_m, XML_r); + m_pSerializer->startElementNS(XML_m, XML_t, FSNS(XML_xml, XML_space), "preserve"); + m_pSerializer->write( " " ); + m_pSerializer->endElementNS( XML_m, XML_t ); + m_pSerializer->endElementNS( XML_m, XML_r ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |