diff options
author | Luboš Luňák <l.lunak@suse.cz> | 2011-11-18 18:09:43 +0100 |
---|---|---|
committer | Luboš Luňák <l.lunak@suse.cz> | 2011-11-24 18:43:57 +0100 |
commit | e9462ed2d978dc3e641227ea9f553eeed4d81a97 (patch) | |
tree | 8b77274817348852458ed19be1bd46bb66d0a749 /starmath | |
parent | 1d163e4835b4906eb4559851e5ab2470b26332fe (diff) |
ooxml mathml import - first very basic implementation
still needs a number of cleanups (and handling more of course)
Diffstat (limited to 'starmath')
-rw-r--r-- | starmath/Library_sm.mk | 1 | ||||
-rw-r--r-- | starmath/inc/document.hxx | 5 | ||||
-rw-r--r-- | starmath/inc/unomodel.hxx | 6 | ||||
-rw-r--r-- | starmath/source/document.cxx | 10 | ||||
-rw-r--r-- | starmath/source/ooxmlimport.cxx | 233 | ||||
-rw-r--r-- | starmath/source/ooxmlimport.hxx | 78 | ||||
-rw-r--r-- | starmath/source/unomodel.cxx | 5 |
7 files changed, 337 insertions, 1 deletions
diff --git a/starmath/Library_sm.mk b/starmath/Library_sm.mk index 6b9c7babdca4..9c4a6904450e 100644 --- a/starmath/Library_sm.mk +++ b/starmath/Library_sm.mk @@ -80,6 +80,7 @@ $(eval $(call gb_Library_add_exception_objects,sm,\ starmath/source/mathtype \ starmath/source/node \ starmath/source/ooxmlexport \ + starmath/source/ooxmlimport \ starmath/source/parse \ starmath/source/rect \ starmath/source/register \ diff --git a/starmath/inc/document.hxx b/starmath/inc/document.hxx index 99f0d8b4cc79..c1b48629a454 100644 --- a/starmath/inc/document.hxx +++ b/starmath/inc/document.hxx @@ -53,6 +53,10 @@ class SfxMenuBarManager; class SfxPrinter; class Printer; class SmCursor; +namespace ooxmlformulaimport +{ +class XmlStream; +} #define HINT_DATACHANGED 1004 @@ -175,6 +179,7 @@ class SmDocShell : public SfxObjectShell, public SfxListener void InvalidateCursor(); bool writeFormulaOoxml( ::sax_fastparser::FSHelperPtr m_pSerializer, oox::core::OoxmlVersion version ); + bool readFormulaOoxml( ooxmlformulaimport::XmlStream& stream ); public: TYPEINFO(); diff --git a/starmath/inc/unomodel.hxx b/starmath/inc/unomodel.hxx index 66479f988ec5..1324c9f8bc88 100644 --- a/starmath/inc/unomodel.hxx +++ b/starmath/inc/unomodel.hxx @@ -38,6 +38,7 @@ #include <comphelper/propertysethelper.hxx> #include <vcl/print.hxx> #include <oox/export/ooxmlexport.hxx> +#include <oox/export/starmathimport.hxx> class SmFormat; @@ -65,7 +66,8 @@ class SmModel : public SfxBaseModel, public comphelper::PropertySetHelper, public com::sun::star::lang::XServiceInfo, public com::sun::star::view::XRenderable, - public OoxmlFormulaExportBase + public OoxmlFormulaExportBase, + public OoxmlFormulaImportBase { SmPrintUIOptions* m_pPrintUIOptions; protected: @@ -104,6 +106,8 @@ public: // OoxmlFormulaExportBase virtual void writeFormulaOoxml( ::sax_fastparser::FSHelperPtr m_pSerializer, oox::core::OoxmlVersion version ); + // OoxmlFormulaImportBase + virtual void readFormulaOoxml( ooxmlformulaimport::XmlStream& stream ); static ::com::sun::star::uno::Sequence< rtl::OUString > getSupportedServiceNames_Static(); static ::rtl::OUString getImplementationName_Static(); diff --git a/starmath/source/document.cxx b/starmath/source/document.cxx index 7586e64d3089..36df9ae505dc 100644 --- a/starmath/source/document.cxx +++ b/starmath/source/document.cxx @@ -96,6 +96,7 @@ #include <view.hxx> #include "mathtype.hxx" #include "ooxmlexport.hxx" +#include "ooxmlimport.hxx" #include "mathmlimport.hxx" #include "mathmlexport.hxx" #include <sfx2/sfxsids.hrc> @@ -998,6 +999,15 @@ bool SmDocShell::writeFormulaOoxml( ::sax_fastparser::FSHelperPtr m_pSerializer, return aEquation.ConvertFromStarMath( m_pSerializer ); } +bool SmDocShell::readFormulaOoxml( ooxmlformulaimport::XmlStream& stream ) +{ + RTL_LOGFILE_CONTEXT( aLog, "starmath: SmDocShell::readFormulaOoxml" ); + + SmOoxmlImport aEquation( stream ); + SetText( aEquation.ConvertToStarMath()); + return true; // TODO just void? +} + sal_Bool SmDocShell::SaveCompleted( const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& xStorage ) { RTL_LOGFILE_CONTEXT( aLog, "starmath: SmDocShell::SaveCompleted" ); diff --git a/starmath/source/ooxmlimport.cxx b/starmath/source/ooxmlimport.cxx new file mode 100644 index 000000000000..cd7610fd215a --- /dev/null +++ b/starmath/source/ooxmlimport.cxx @@ -0,0 +1,233 @@ +/* -*- 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 "ooxmlimport.hxx" + +#include <oox/token/tokens.hxx> +#include <oox/token/namespaces.hxx> + +using namespace oox; +using namespace ooxmlformulaimport; +using rtl::OUString; + +/* +The primary internal data structure for the formula is the text representation +(the SmNode tree is built from it), so read data must be converted into this format. +*/ + +#define M_TOKEN( token ) OOX_TOKEN( officeMath, token ) +#define OPENING_TAG( token ) OPENING( token ) +#define CLOSING_TAG( token ) CLOSING( token ) + +// *sigh* +#define STR( str ) OUString( RTL_CONSTASCII_USTRINGPARAM( str )) + +// TODO create IS_OPENING(), IS_CLOSING() instead of doing 'next == OPENING( next )' ? + +SmOoxmlImport::SmOoxmlImport( ooxmlformulaimport::XmlStream& s ) +: stream( s ) +{ +} + +OUString SmOoxmlImport::ConvertToStarMath() +{ + return handleStream(); +} + +// "toplevel" of reading, there will be oMath (if there was oMathPara, that was +// up to the parent component to handle) + +// NOT complete +OUString SmOoxmlImport::handleStream() +{ + checkOpeningTag( M_TOKEN( oMath )); + OUString ret; + bool out = false; + while( !out && !stream.nextIsEnd()) + { + switch( stream.peekNextToken()) + { + case OPENING( M_TOKEN( f )): + ret += STR( " " ) + handleF(); + break; + case CLOSING( M_TOKEN( oMath )): + out = true; + break; + default: + handleUnexpectedTag(); + break; + } + } + checkClosingTag( M_TOKEN( oMath )); + return ret; +} + +// NOT complete +OUString SmOoxmlImport::handleF() +{ + checkOpeningTag( M_TOKEN( f )); + if( stream.peekNextToken() == OPENING_TAG( M_TOKEN( fPr ))) + { + // TODO + } + checkOpeningTag( M_TOKEN( num )); + OUString num = readR(); + checkClosingTag( M_TOKEN( num )); + checkOpeningTag( M_TOKEN( den )); + OUString den = readR(); + checkClosingTag( M_TOKEN( den )); + checkClosingTag( M_TOKEN( f )); + return STR( "{" ) + num + STR( "} over {" ) + den + STR( "}" ); +} + +// NOT complete +OUString SmOoxmlImport::readR() +{ + checkOpeningTag( M_TOKEN( r )); + +// checkOpeningTag( OOX_TOKEN( doc, rPr )); +// checkOpeningTag( OOX_TOKEN( doc, rFonts )); +// checkClosingTag( OOX_TOKEN( doc, rFonts )); +// checkClosingTag( OOX_TOKEN( doc, rPr )); + + // TODO can there be more t's ? + checkOpeningTag( M_TOKEN( t )); + OUString text = stream.getCharacters(); + if( !stream.getAttributes().getBool( OOX_TOKEN( xml, space ), false )) + text = text.trim(); + checkClosingTag( M_TOKEN( t )); + checkClosingTag( M_TOKEN( r )); + return text; +} + +void SmOoxmlImport::checkOpeningTag( int token ) +{ + checkTag( OPENING( token ), "opening" ); +} + +void SmOoxmlImport::checkClosingTag( int token ) +{ + checkTag( CLOSING( token ), "closing" ); +} + +void SmOoxmlImport::checkTag( int token, const char* txt ) +{ + if( stream.peekNextToken() == token ) + { + stream.getNextToken(); // read it + return; // ok + } + if( recoverAndFindTag( token )) + { + stream.getNextToken(); // read it + return; // ok, skipped some tokens + } + fprintf( stderr, "Expected %s tag %d not found.\n", txt, token ); +} + +bool SmOoxmlImport::recoverAndFindTag( int token ) +{ + int depth = 0; + for(;;) + { + if( depth > 0 ) // we're inside a nested element, skip those + { + int next = stream.getNextToken(); + if( next == OPENING( next )) + { + fprintf( stderr, "Skipping opening tag %d\n", next ); + ++depth; + } + else if( next == CLOSING( next )) + { // TODO debug output without the OPENING/CLOSING bits set + fprintf( stderr, "Skipping closing tag %d\n", next ); + --depth; + } + else if( next == XML_TOKEN_INVALID ) // end of stream + { + fprintf( stderr, "Unexpected end of stream reached.\n" ); + return false; + } + else + { + fprintf( stderr, "Malformed token %d\n", next ); + abort(); + } + continue; + } + int next = stream.peekNextToken(); + if( next == CLOSING( next )) + return false; // that would be leaving current element, so not found + if( next == token ) + return true; // ok, found + if( next == OPENING( next )) + { + fprintf( stderr, "Skipping opening tag %d\n", next ); + stream.getNextToken(); + ++depth; + } + else if( next == XML_TOKEN_INVALID ) + { + fprintf( stderr, "Unexpected end of stream reached.\n" ); + return false; + } + else + abort(); + } +} + +void SmOoxmlImport::skipElement( int token ) +{ + int closing = ( token & ~TAG_OPENING ) | TAG_CLOSING; // make it a closing tag + assert( stream.peekNextToken() == OPENING( token )); + // just find the matching closing tag + if( recoverAndFindTag( closing )) + { + stream.getNextToken(); // read it + return; + } + fprintf( stderr, "Expected end of element %d not found.\n", token ); +} + +void SmOoxmlImport::handleUnexpectedTag() +{ + int next = stream.peekNextToken(); + if( next == XML_TOKEN_INVALID ) + return; // end of stream + if( next == CLOSING( next )) + { + stream.getNextToken(); // just skip it + return; + } + skipElement( stream.peekNextToken()); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/starmath/source/ooxmlimport.hxx b/starmath/source/ooxmlimport.hxx new file mode 100644 index 000000000000..80be1d836b5c --- /dev/null +++ b/starmath/source/ooxmlimport.hxx @@ -0,0 +1,78 @@ +/* -*- 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_OOXMLIMPORT_HXX +#define SM_OOXMLIMPORT_HXX + +#include <oox/export/starmathimport.hxx> + +#include "node.hxx" + +/** + Class implementing reading of formulas from OOXML. The toplevel element is expected + to be oMath (handle oMathPara outside of this code). + */ +class SmOoxmlImport +{ +public: + SmOoxmlImport( ooxmlformulaimport::XmlStream& stream ); + rtl::OUString ConvertToStarMath(); +private: + rtl::OUString handleStream(); + rtl::OUString handleF(); + rtl::OUString readR(); + /** + Checks that the next token is the given opening tag, if not, writes out a warning + and tries to recover (skips tags until found or until the current element would end). + */ + void checkOpeningTag( int token ); + /** + Checks that the next token is the given opening tag, if not, writes out a warning + and tries to recover (skips tags until found or until the current element would end). + */ + void checkClosingTag( int token ); + // helper for the two above + void checkTag( int token, const char* txt ); + /** + Tries to find the given token, until either found (returns true) or end of current element. + */ + bool recoverAndFindTag( int token ); + /** + Skips the given element (i.e. reads up to and including the matching closing tag). + */ + void skipElement( int token ); + /** + Handle the current (unexpected) tag. + */ + void handleUnexpectedTag(); + ooxmlformulaimport::XmlStream& stream; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/starmath/source/unomodel.cxx b/starmath/source/unomodel.cxx index 2cb17987b2ac..8b7ea8169235 100644 --- a/starmath/source/unomodel.cxx +++ b/starmath/source/unomodel.cxx @@ -1137,4 +1137,9 @@ void SmModel::writeFormulaOoxml( ::sax_fastparser::FSHelperPtr m_pSerializer, oo static_cast< SmDocShell* >( GetObjectShell())->writeFormulaOoxml( m_pSerializer, version ); } +void SmModel::readFormulaOoxml( ooxmlformulaimport::XmlStream& stream ) +{ + static_cast< SmDocShell* >( GetObjectShell())->readFormulaOoxml( stream ); +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |