diff options
author | Luboš Luňák <l.lunak@suse.cz> | 2011-08-16 13:56:29 +0200 |
---|---|---|
committer | Luboš Luňák <l.lunak@suse.cz> | 2011-08-18 15:33:45 +0200 |
commit | 047a5de1fe8fdc60ffb07c68125c6d0a08353e0d (patch) | |
tree | 409cb94778058f34c147dae568d62adac4767f75 /starmath/source | |
parent | 2e5e29471f9ac61ec454bf90a985525a0ad5cb1c (diff) |
starting work on OOXML export of formulas
Diffstat (limited to 'starmath/source')
-rw-r--r-- | starmath/source/document.cxx | 14 | ||||
-rw-r--r-- | starmath/source/ooxml.cxx | 396 | ||||
-rw-r--r-- | starmath/source/ooxml.hxx | 57 | ||||
-rw-r--r-- | starmath/source/unomodel.cxx | 2 |
4 files changed, 467 insertions, 2 deletions
diff --git a/starmath/source/document.cxx b/starmath/source/document.cxx index b0ec43e32615..b9db1f5db35e 100644 --- a/starmath/source/document.cxx +++ b/starmath/source/document.cxx @@ -95,6 +95,7 @@ #include <utility.hxx> #include <view.hxx> #include "mathtype.hxx" +#include "ooxml.hxx" #include "mathmlimport.hxx" #include "mathmlexport.hxx" #include <sfx2/sfxsids.hrc> @@ -990,6 +991,18 @@ sal_Bool SmDocShell::ConvertTo( SfxMedium &rMedium ) return bRet; } +bool SmDocShell::writeFormulaOoxml( ::sax_fastparser::FSHelperPtr m_pSerializer ) +{ + RTL_LOGFILE_CONTEXT( aLog, "starmath: SmDocShell::writeFormulaOoxml" ); + + if( !pTree ) + Parse(); + if( pTree && !IsFormulaArranged() ) + ArrangeFormula(); + SmOoxml aEquation( aText, pTree ); + return aEquation.ConvertFromStarMath( m_pSerializer ); +} + sal_Bool SmDocShell::SaveCompleted( const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& xStorage ) { RTL_LOGFILE_CONTEXT( aLog, "starmath: SmDocShell::SaveCompleted" ); @@ -1433,5 +1446,4 @@ bool SmDocShell::WriteAsMathType3( SfxMedium& rMedium ) return bRet; } - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/starmath/source/ooxml.cxx b/starmath/source/ooxml.cxx new file mode 100644 index 000000000000..e702b4c15bb2 --- /dev/null +++ b/starmath/source/ooxml.cxx @@ -0,0 +1,396 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Version: MPL 1.1 / GPLv3+ / LGPLv3+ + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License or as specified alternatively below. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * Major Contributor(s): + * Copyright (C) 2011 Lubos Lunak <l.lunak@suse.cz> (initial developer) + * + * All Rights Reserved. + * + * For minor contributions see the git repository. + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 3 or later (the "GPLv3+"), or + * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"), + * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable + * instead of those above. + */ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_starmath.hxx" + +#include "ooxml.hxx" + +#include <oox/token/tokens.hxx> + +using namespace oox; + +// TODO duped from MathType + +static sal_Unicode Convert(sal_Unicode nIn) +{ + //Find the best match in accepted unicode for our private area symbols + static sal_Unicode aStarMathPrivateToUnicode[] = + { + 0x2030, 0xF613, 0xF612, 0x002B, 0x003C, 0x003E, 0xE425, 0xE421, 0xE088, 0x2208, + 0x0192, 0x2026, 0x2192, 0x221A, 0x221A, 0x221A, 0xE090, 0x005E, 0x02C7, 0x02D8, + 0x00B4, 0x0060, 0x02DC, 0x00AF, 0x0362, 0xE099, 0xE09A, 0x20DB, 0xE09C, 0xE09D, + 0x0028, 0x0029, 0x2220, 0x22AF, 0xE0A2, 0xE0A3, 0xE0A4, 0xE0A5, 0xE0A6, 0xE0A7, + 0x002F, 0x005C, 0x274F, 0xE0AB, 0x0393, 0x0394, 0x0398, 0x039b, 0x039e, 0x03A0, + 0x03a3, 0x03a5, 0x03a6, 0x03a8, 0x03A9, 0x03B1, 0x03B2, 0x03b3, 0x03b4, 0x03b5, + 0x03b6, 0x03b7, 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf, + 0x03c0, 0x03c1, 0x03c3, 0x03c4, 0x03c5, 0x03c6, 0x03c7, 0x03c8, 0x03c9, 0x03b5, + 0x03d1, 0x03d6, 0xE0D2, 0x03db, 0x2118, 0x2202, 0x2129, 0xE0D7, 0xE0D8, 0x22A4, + 0xE0DA, 0x2190, 0x2191, 0x2193 + }; + if ((nIn >= 0xE080) && (nIn <= 0xE0DD)) + nIn = aStarMathPrivateToUnicode[nIn-0xE080]; + + //For whatever unicode glyph that equation editor doesn't ship with that + //we have a possible match we can munge it to. + switch (nIn) + { + case 0x2223: + nIn = '|'; + break; + default: + break; + } + + return nIn; +} + +SmOoxml::SmOoxml(String &rIn,SmNode *pIn) +: str( rIn ) +, pTree( pIn ) +{ +} + +bool SmOoxml::ConvertFromStarMath( ::sax_fastparser::FSHelperPtr serializer ) +{ + if( pTree == NULL ) + return false; + m_pSerializer = serializer; +// TODO check that the document includes the m namespace + m_pSerializer->startElementNS( XML_m, XML_oMath, + FSNS( XML_xmlns, XML_m ), "http://schemas.openxmlformats.org/wordprocessingml/2006/math", FSEND ); + HandleNodes( pTree, 0 ); + m_pSerializer->endElementNS( XML_m, XML_oMath ); + return true; +} + +void SmOoxml::HandleNodes(SmNode *pNode,int nLevel) +{ + fprintf(stderr,"XX %d %d\n", nLevel, pNode->GetType()); + switch(pNode->GetType()) + { +#if 0 + case NATTRIBUT: + HandleAttributes(pNode,nLevel); + break; +#endif + case NTEXT: + HandleText(pNode,nLevel); + break; +#if 0 + case NVERTICAL_BRACE: + HandleVerticalBrace(pNode,nLevel); + break; + case NBRACE: + HandleBrace(pNode,nLevel); + break; + case NOPER: + HandleOperator(pNode,nLevel); + break; + case NBINVER: + HandleFractions(pNode,nLevel); + break; + case NROOT: + HandleRoot(pNode,nLevel); + break; + case NSPECIAL: + { + SmTextNode *pText=(SmTextNode *)pNode; + //if the token str and the result text are the same then this + //is to be seen as text, else assume its a mathchar + if (pText->GetText() == pText->GetToken().aText) + HandleText(pText,nLevel); + else + HandleMath(pText,nLevel); + } + break; +#endif + case NMATH: + HandleMath(pNode,nLevel); + break; +#if 0 + case NSUBSUP: + HandleSubSupScript(pNode,nLevel); + break; +#endif + case NEXPRESSION: + { + sal_uInt16 nSize = pNode->GetNumSubNodes(); + for (sal_uInt16 i = 0; i < nSize; i++) + if (SmNode *pTemp = pNode->GetSubNode(i)) + HandleNodes(pTemp,nLevel+1); + } + break; + case NTABLE: + //Root Node, PILE equivalent, i.e. vertical stack + HandleTable(pNode,nLevel); + break; +#if 0 + case NMATRIX: + HandleSmMatrix((SmMatrixNode *)pNode,nLevel); + break; +#endif + case NLINE: + { +// TODO +// *pS << sal_uInt8(LINE); + sal_uInt16 nSize = pNode->GetNumSubNodes(); + for (sal_uInt16 i = 0; i < nSize; i++) + if (SmNode *pTemp = pNode->GetSubNode(i)) + HandleNodes(pTemp,nLevel+1); +// *pS << sal_uInt8(END); + } + break; +#if 0 + case NALIGN: + HandleMAlign(pNode,nLevel); + break; + case NBLANK: + *pS << sal_uInt8(CHAR); + *pS << sal_uInt8(0x98); + if (pNode->GetToken().eType == TSBLANK) + *pS << sal_uInt16(0xEB04); + else + *pS << sal_uInt16(0xEB05); + break; +#endif + default: + { + sal_uInt16 nSize = pNode->GetNumSubNodes(); + for (sal_uInt16 i = 0; i < nSize; i++) + if (SmNode *pTemp = pNode->GetSubNode(i)) + HandleNodes(pTemp,nLevel+1); + } + break; + } +} + +//Root Node, PILE equivalent, i.e. vertical stack +void SmOoxml::HandleTable(SmNode *pNode,int nLevel) +{ + sal_uInt16 nSize = pNode->GetNumSubNodes(); + //The root of the starmath is a table, if + //we convert this them each iteration of + //conversion from starmath to mathtype will + //add an extra unnecessary level to the + //mathtype output stack which would grow + //without bound in a multi step conversion + +// TODO +// if ( nLevel || (nSize >1)) +// { +// *pS << sal_uInt8(PILE); +// *pS << sal_uInt8(nHAlign); //vAlign ? +// *pS << sal_uInt8(0x01); //hAlign +// } + + for (sal_uInt16 i = 0; i < nSize; i++) + if (SmNode *pTemp = pNode->GetSubNode(i)) + { +// *pS << sal_uInt8(LINE); + HandleNodes(pTemp,nLevel+1); +// *pS << sal_uInt8(END); + } +// if (nLevel || (nSize>1)) +// *pS << sal_uInt8(END); +} + +void SmOoxml::HandleText(SmNode *pNode, int /*nLevel*/) +{ + m_pSerializer->startElementNS( XML_m, XML_r, FSEND ); + m_pSerializer->startElementNS( XML_m, XML_t, FSEND ); + SmTextNode *pTemp=(SmTextNode *)pNode; + fprintf(stderr, "T %s\n", rtl::OUStringToOString( pTemp->GetText(), RTL_TEXTENCODING_UTF8 ).getStr()); + for(xub_StrLen i=0;i<pTemp->GetText().Len();i++) + { +#if 0 + if ((nPendingAttributes) && + (i == ((pTemp->GetText().Len()+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 + sal_uInt16 nChar = pTemp->GetText().GetChar(i); + m_pSerializer->write( rtl::OUString( Convert(nChar))); + +#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().Len()+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->endElementNS( XML_m, XML_t ); + m_pSerializer->endElementNS( XML_m, XML_r ); +} + +void SmOoxml::HandleMath(SmNode *pNode,int nLevel) +{ + HandleText( pNode, nLevel ); +#if 0 + if (pNode->GetToken().eType == TMLINE) + { + *pS << sal_uInt8(END); + *pS << sal_uInt8(LINE); + bIsReInterpBrace=1; + return; + } + SmMathSymbolNode *pTemp=(SmMathSymbolNode *)pNode; + for(xub_StrLen i=0;i<pTemp->GetText().Len();i++) + { + sal_Unicode nArse = Convert(pTemp->GetText().GetChar(i)); + if ((nArse == 0x2224) || (nArse == 0x2288) || (nArse == 0x2285) || + (nArse == 0x2289)) + { + *pS << sal_uInt8(CHAR|0x20); + } + else if ((nPendingAttributes) && + (i == ((pTemp->GetText().Len()+1)/2)-1)) + { + *pS << sal_uInt8(0x22); + } + else + *pS << sal_uInt8(CHAR); //char without formula recognition + //The typeface seems to be MTEXTRA for unicode characters, + //though how to determine when mathtype chooses one over + //the other is unknown. This should do the trick + //nevertheless. + sal_uInt8 nBias; + if ( (nArse == 0x2213) || (nArse == 0x2218) || + (nArse == 0x210F) || ( + (nArse >= 0x22EE) && (nArse <= 0x22FF) + )) + { + nBias = 0xB; //typeface + } + else if ((nArse > 0x2000) || (nArse == 0x00D7)) + nBias = 0x6; //typeface + else if (nArse == 0x3d1) + nBias = 0x4; + else if ((nArse > 0xFF) && ((nArse < 0x393) || (nArse > 0x3c9))) + nBias = 0xB; //typeface + else if ((nArse == 0x2F) || (nArse == 0x2225)) + nBias = 0x2; //typeface + else + nBias = 0x3; //typeface + + *pS << sal_uInt8(nSpec+nBias+128); //typeface + + if (nArse == 0x2224) + { + *pS << sal_uInt16(0x7C); + *pS << sal_uInt8(EMBEL); + *pS << sal_uInt8(0x0A); + *pS << sal_uInt8(END); //end embel + *pS << sal_uInt8(END); //end embel + } + else if (nArse == 0x2225) + *pS << sal_uInt16(0xEC09); + else if (nArse == 0xE421) + *pS << sal_uInt16(0x2265); + else if (nArse == 0x230A) + *pS << sal_uInt16(0xF8F0); + else if (nArse == 0x230B) + *pS << sal_uInt16(0xF8FB); + else if (nArse == 0xE425) + *pS << sal_uInt16(0x2264); + else if (nArse == 0x226A) + { + *pS << sal_uInt16(0x3C); + *pS << sal_uInt8(CHAR); + *pS << sal_uInt8(0x98); + *pS << sal_uInt16(0xEB01); + *pS << sal_uInt8(CHAR); + *pS << sal_uInt8(0x86); + *pS << sal_uInt16(0x3c); + } + else if (nArse == 0x2288) + { + *pS << sal_uInt16(0x2286); + *pS << sal_uInt8(EMBEL); + *pS << sal_uInt8(0x0A); + *pS << sal_uInt8(END); //end embel + *pS << sal_uInt8(END); //end embel + } + else if (nArse == 0x2289) + { + *pS << sal_uInt16(0x2287); + *pS << sal_uInt8(EMBEL); + *pS << sal_uInt8(0x0A); + *pS << sal_uInt8(END); //end embel + *pS << sal_uInt8(END); //end embel + } + else if (nArse == 0x2285) + { + *pS << sal_uInt16(0x2283); + *pS << sal_uInt8(EMBEL); + *pS << sal_uInt8(0x0A); + *pS << sal_uInt8(END); //end embel + *pS << sal_uInt8(END); //end embel + } + else + *pS << nArse; + } + nPendingAttributes = 0; +#endif +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/starmath/source/ooxml.hxx b/starmath/source/ooxml.hxx new file mode 100644 index 000000000000..70de500ebff5 --- /dev/null +++ b/starmath/source/ooxml.hxx @@ -0,0 +1,57 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Version: MPL 1.1 / GPLv3+ / LGPLv3+ + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License or as specified alternatively below. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * Major Contributor(s): + * Copyright (C) 2011 Lubos Lunak <l.lunak@suse.cz> (initial developer) + * + * All Rights Reserved. + * + * For minor contributions see the git repository. + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 3 or later (the "GPLv3+"), or + * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"), + * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable + * instead of those above. + */ + +#ifndef SM_OOXML_HXX +#define SM_OOXML_HXX + +#include "node.hxx" + +#include <sax/fshelper.hxx> + +/** + Class implementing writing of formulas to OOXML. + */ +class SmOoxml +{ +public: + SmOoxml(String &rIn,SmNode *pIn); + bool ConvertFromStarMath( ::sax_fastparser::FSHelperPtr m_pSerializer ); +private: + void HandleNodes(SmNode *pNode,int nLevel); + void HandleTable(SmNode *pNode,int nLevel); + void HandleText(SmNode *pNode,int nLevel); + void HandleMath(SmNode *pNode,int nLevel); + String str; + SmNode *pTree; + ::sax_fastparser::FSHelperPtr m_pSerializer; +}; + + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/starmath/source/unomodel.cxx b/starmath/source/unomodel.cxx index 1820420e7c4c..d44485a605cb 100644 --- a/starmath/source/unomodel.cxx +++ b/starmath/source/unomodel.cxx @@ -1134,7 +1134,7 @@ void SAL_CALL SmModel::setParent( const uno::Reference< uno::XInterface >& xPare void SmModel::writeFormulaOoxml( ::sax_fastparser::FSHelperPtr m_pSerializer ) { -// static_cast< SmDocShell* >( GetObjectShell())->writeFormulaOoxml( m_pSerializer ); + static_cast< SmDocShell* >( GetObjectShell())->writeFormulaOoxml( m_pSerializer ); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |