diff options
-rw-r--r-- | sw/source/filter/ww8/docxattributeoutput.cxx | 85 | ||||
-rw-r--r-- | sw/source/filter/ww8/docxattributeoutput.hxx | 11 | ||||
-rw-r--r-- | sw/source/filter/ww8/docxexport.cxx | 41 | ||||
-rw-r--r-- | sw/source/filter/ww8/docxexport.hxx | 7 |
4 files changed, 144 insertions, 0 deletions
diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx index 132213138cad..469585492ebc 100644 --- a/sw/source/filter/ww8/docxattributeoutput.cxx +++ b/sw/source/filter/ww8/docxattributeoutput.cxx @@ -1071,6 +1071,9 @@ void DocxAttributeOutput::StartRunProperties() assert(!m_postponedDMLDrawing); m_postponedDMLDrawing = new std::list< PostponedDrawing >; + + assert( !m_postponedOLE ); + m_postponedOLE = new std::list< PostponedOLE >; } void DocxAttributeOutput::InitCollectedRunProperties() @@ -1326,6 +1329,8 @@ void DocxAttributeOutput::EndRunProperties( const SwRedlineData* pRedlineData ) WritePostponedVMLDrawing(); WritePostponedDMLDrawing(); + WritePostponedOLE(); + // merge the properties _before_ the run text (strictly speaking, just // after the start of the run) m_pSerializer->mergeTopMarks( sax_fastparser::MERGE_MARKS_PREPEND ); @@ -3306,6 +3311,8 @@ void DocxAttributeOutput::WriteOLE2Obj( const SdrObject* pSdrObj, SwOLENode& rOL return; if( WriteOLEMath( pSdrObj, rOLENode, rSize )) return; + if( PostponeOLE( pSdrObj, rOLENode, rSize, pFlyFrmFmt )) + return; // Then we fall back to just export the object as a graphic. if( m_postponedGraphic == NULL ) FlyFrameGraphic( 0, rSize, pFlyFrmFmt, &rOLENode ); @@ -3467,6 +3474,83 @@ void DocxAttributeOutput::WritePostponedFormControl(const SdrObject* pObject) } } +bool DocxAttributeOutput::PostponeOLE( const SdrObject*, SwOLENode& rNode, const Size& rSize, const SwFlyFrmFmt* pFlyFrmFmt ) +{ + if( m_postponedVMLDrawing == NULL ) + return false; + m_postponedOLE->push_back( PostponedOLE( &rNode, rSize, pFlyFrmFmt ) ); + return true; +} + +/* + * Write w:object hierarchy for embedded objects after end element of w:rPr tag. + */ +void DocxAttributeOutput::WritePostponedOLE() +{ + if( m_postponedOLE == NULL ) + return; + + SAL_INFO( "sw.ww8", OSL_THIS_FUNC ); + + for( std::list< PostponedOLE >::iterator it = m_postponedOLE->begin(); + it != m_postponedOLE->end(); + ++it ) + { + // write embedded file + OString sId = m_rExport.WriteOLENode( *it->object ); + + if( sId.isEmpty() ) + { + // the embedded file could not be saved + // fallback: save as an image + FlyFrameGraphic( 0, it->size, it->frame, it->object ); + continue; + } + + // write preview image + const Graphic* pGraphic = const_cast< SwOLENode* >( it->object )->GetGraphic(); + OUString sImageId = m_rDrawingML.WriteImage( *pGraphic ); + + m_pSerializer->startElementNS( XML_w, XML_object, FSEND ); + + OStringBuffer sShapeStyle, sShapeId; + sShapeStyle.append( "width:" ).append( double( it->size.Width() ) / 20 ) + .append( "pt;height:" ).append( double( it->size.Height() ) / 20 ) + .append( "pt" ); //from VMLExport::AddRectangleDimensions(), it does: value/20 + sShapeId.append( "ole_" ).append( sId ); + + // shape definition + m_pSerializer->startElementNS( XML_v, XML_shape, + XML_id, sShapeId.getStr(), + XML_style, sShapeStyle.getStr(), + FSNS( XML_o, XML_ole ), "", //compulsory, even if it's empty + FSEND ); + + // shape filled with the preview image + m_pSerializer->singleElementNS( XML_v, XML_imagedata, + FSNS( XML_r, XML_id ), OUStringToOString( sImageId, RTL_TEXTENCODING_UTF8 ).getStr(), + FSEND ); + + m_pSerializer->endElementNS( XML_v, XML_shape ); + + // OLE object definition + m_pSerializer->singleElementNS( XML_o, XML_OLEObject, + XML_Type, "Embed", + XML_ProgID,"Excel.Sheet.12", //TODO: should be auto-detected somehow + XML_ShapeID, sShapeId.getStr(), + XML_DrawAspect, "Content", + XML_ObjectID, "_" + OString::number( rand() ), + FSNS( XML_r, XML_id ), sId.getStr(), + FSEND ); + + m_pSerializer->endElementNS( XML_w, XML_object ); + } + + // clear list of postponed objects + delete m_postponedOLE; + m_postponedOLE = NULL; +} + /* * Write w:pict hierarchy end element of w:rPr tag. */ @@ -6520,6 +6604,7 @@ DocxAttributeOutput::DocxAttributeOutput( DocxExport &rExport, FSHelperPtr pSeri m_postponedDiagram( NULL ), m_postponedVMLDrawing(NULL), m_postponedDMLDrawing(NULL), + m_postponedOLE( NULL ), m_postponedMath( NULL ), m_postponedChart( NULL ), pendingPlaceholder( NULL ), diff --git a/sw/source/filter/ww8/docxattributeoutput.hxx b/sw/source/filter/ww8/docxattributeoutput.hxx index 30474f17b35c..de98b3c8b64c 100644 --- a/sw/source/filter/ww8/docxattributeoutput.hxx +++ b/sw/source/filter/ww8/docxattributeoutput.hxx @@ -393,6 +393,7 @@ private: void WriteOLE2Obj( const SdrObject* pSdrObj, SwOLENode& rNode, const Size& rSize, const SwFlyFrmFmt* pFlyFrmFmt); bool WriteOLEChart( const SdrObject* pSdrObj, const Size& rSize ); bool WriteOLEMath( const SdrObject* pSdrObj, const SwOLENode& rNode, const Size& rSize ); + bool PostponeOLE( const SdrObject* pSdrObj, SwOLENode& rNode, const Size& rSize, const SwFlyFrmFmt* pFlyFrmFmt ); /// checks whether the current component is a diagram bool IsDiagram (const SdrObject* sdrObject); @@ -668,6 +669,7 @@ private: void WritePostponedFormControl(const SdrObject* pObject); void WritePostponedDiagram(); void WritePostponedChart(); + void WritePostponedOLE(); void WritePostponedVMLDrawing(); void WritePostponedDMLDrawing(); @@ -786,6 +788,15 @@ private: std::list< PostponedDrawing >* m_postponedVMLDrawing; std::list< PostponedDrawing >* m_postponedDMLDrawing; + struct PostponedOLE + { + PostponedOLE( SwOLENode* rObject, const Size rSize, const SwFlyFrmFmt* rFrame ) : object( rObject ), size( rSize ), frame( rFrame ) {}; + SwOLENode* object; + const Size size; + const SwFlyFrmFmt* frame; + }; + std::list< PostponedOLE >* m_postponedOLE; + const SwOLENode* m_postponedMath; const SdrObject* m_postponedChart; Size m_postponedChartSize; diff --git a/sw/source/filter/ww8/docxexport.cxx b/sw/source/filter/ww8/docxexport.cxx index 321e01e6e5ec..41e70834de67 100644 --- a/sw/source/filter/ww8/docxexport.cxx +++ b/sw/source/filter/ww8/docxexport.cxx @@ -66,6 +66,7 @@ #include "ww8par.hxx" #include "ww8scan.hxx" #include <oox/token/properties.hxx> +#include <comphelper/embeddedobjectcontainer.hxx> #include <comphelper/string.hxx> #include <rtl/ustrbuf.hxx> #include <vcl/font.hxx> @@ -357,6 +358,45 @@ OString DocxExport::OutputChart( uno::Reference< frame::XModel >& xModel, sal_In return OUStringToOString( sId, RTL_TEXTENCODING_UTF8 ); } +OString DocxExport::WriteOLENode( const SwOLENode& rNode ) +{ + uno::Reference <embed::XEmbeddedObject> xObj( const_cast<SwOLENode&>(rNode).GetOLEObj().GetOleRef() ); + OUString sId, sMediaType; + comphelper::EmbeddedObjectContainer* aContainer = const_cast<SwOLENode&>(rNode).GetOLEObj().GetObject().GetContainer(); + uno::Reference< io::XInputStream > xInStream = aContainer->GetObjectStream( xObj, &sMediaType ); + + OUString sFileName = "embeddings/Microsoft_Excel_Worksheet" + OUString::number( ++m_nOLEObjects ) + ".xlsx"; + uno::Reference< io::XOutputStream > xOutStream = GetFilter().openFragmentStream( OUStringBuffer() + .appendAscii( "word/" ) + .append( sFileName ) + .makeStringAndClear(), + sMediaType ); + + if( lcl_CopyStream( xInStream, xOutStream ) ) + + sId = m_pFilter->addRelation( m_pDocumentFS->getOutputStream(), + "http://schemas.openxmlformats.org/officeDocument/2006/relationships/package", + sFileName, false ); + + return OUStringToOString( sId, RTL_TEXTENCODING_UTF8 ); +} + +// function copied from embeddedobj/source/msole/oleembed.cxx +bool DocxExport::lcl_CopyStream( uno::Reference<io::XInputStream> xIn, uno::Reference<io::XOutputStream> xOut ) +{ + const sal_Int32 nChunkSize = 4096; + uno::Sequence< sal_Int8 > aData(nChunkSize); + sal_Int32 nTotalRead = 0; + sal_Int32 nRead = 0; + do + { + nRead = xIn->readBytes(aData, nChunkSize); + nTotalRead += nRead; + xOut->writeBytes(aData); + } while (nRead == nChunkSize); + return nTotalRead != 0; +} + void DocxExport::OutputDML(uno::Reference<drawing::XShape>& xShape) { uno::Reference<lang::XServiceInfo> xServiceInfo(xShape, uno::UNO_QUERY_THROW); @@ -1319,6 +1359,7 @@ DocxExport::DocxExport( DocxExportFilter *pFilter, SwDoc *pDocument, SwPaM *pCur m_pSections( NULL ), m_nHeaders( 0 ), m_nFooters( 0 ), + m_nOLEObjects( 0 ), m_nHeadersFootersInSection(0), m_pVMLExport( NULL ), m_pSdrExport( NULL ) diff --git a/sw/source/filter/ww8/docxexport.hxx b/sw/source/filter/ww8/docxexport.hxx index d058302d34a3..60779669fae0 100644 --- a/sw/source/filter/ww8/docxexport.hxx +++ b/sw/source/filter/ww8/docxexport.hxx @@ -29,6 +29,7 @@ #include <cstdio> #include <vector> #include <boost/optional.hpp> +#include <ndole.hxx> class DocxAttributeOutput; class DocxExportFilter; @@ -84,6 +85,9 @@ class DocxExport : public MSWordExportBase /// Footer counter. sal_Int32 m_nFooters; + /// OLE objects counter. + sal_Int32 m_nOLEObjects; + ///Footer and Header counter in Section properties sal_Int32 m_nHeadersFootersInSection; @@ -159,6 +163,9 @@ public: /// Returns the relationd id OString OutputChart( com::sun::star::uno::Reference< com::sun::star::frame::XModel >& xModel, sal_Int32 nCount, ::sax_fastparser::FSHelperPtr m_pSerializer ); + OString WriteOLENode( const SwOLENode& rNode ); + bool lcl_CopyStream( css::uno::Reference< css::io::XInputStream> xIn, css::uno::Reference< css::io::XOutputStream > xOut ); + /// Writes the shape using drawingML syntax. void OutputDML( com::sun::star::uno::Reference< com::sun::star::drawing::XShape >& xShape ); |