diff --git a/sw/Library_msword.mk b/sw/Library_msword.mk index 069795b4a005..336f26772d35 100644 --- a/sw/Library_msword.mk +++ b/sw/Library_msword.mk @@ -78,6 +78,7 @@ $(eval $(call gb_Library_add_exception_objects,msword,\ sw/source/filter/ww8/docxattributeoutput \ sw/source/filter/ww8/docxexport \ sw/source/filter/ww8/docxexportfilter \ + sw/source/filter/ww8/docxsdrexport \ sw/source/filter/ww8/docxtablestyleexport \ sw/source/filter/ww8/rtfattributeoutput \ sw/source/filter/ww8/rtfexport \ diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx index 2d938b57c45d..a486305916f5 100644 --- a/sw/source/filter/ww8/docxattributeoutput.cxx +++ b/sw/source/filter/ww8/docxattributeoutput.cxx @@ -19,6 +19,7 @@ #include "docxattributeoutput.hxx" #include "docxhelper.hxx" +#include "docxsdrexport.hxx" #include "docxexportfilter.hxx" #include "docxfootnotes.hxx" #include "writerwordglue.hxx" @@ -36,8 +37,6 @@ #include #include -#include - #include #include #include @@ -72,26 +71,19 @@ #include #include #include -#include #include -#include -#include -#include #include #include #include #include #include -#include #include #include -#include #include #include #include #include -#include #include #include #include @@ -109,19 +101,12 @@ #include #include -#include #include #include #include #include #include -#include -#include -#include -#include -#include -#include #include #include @@ -141,10 +126,6 @@ using namespace sw::util; using namespace ::com::sun::star; using namespace ::com::sun::star::drawing; -// TODO the whole Sdr code should be factored out to a separate class. -void lcl_startDMLAnchorInline(sax_fastparser::FSHelperPtr pSerializer, const SwFrmFmt* pFrmFmt, const Size& rSize); -void lcl_endDMLAnchorInline(sax_fastparser::FSHelperPtr pSerializer, const SwFrmFmt* pFrmFmt); - class FFDataWriterHelper { ::sax_fastparser::FSHelperPtr m_pSerializer; @@ -443,7 +424,7 @@ void DocxAttributeOutput::WriteDMLTextFrame(sw::Frame* pParentFrame) // to lots of contents, this size contains the real size. const Size aSize = pParentFrame->GetSize(); - lcl_startDMLAnchorInline(m_pSerializer, &rFrmFmt, aSize); + m_rExport.SdrExporter().startDMLAnchorInline(&rFrmFmt, aSize); sax_fastparser::FastAttributeList* pDocPrAttrList = m_pSerializer->createAttrList(); pDocPrAttrList->add(XML_id, OString::number(m_anchorId++).getStr()); @@ -495,7 +476,7 @@ void DocxAttributeOutput::WriteDMLTextFrame(sw::Frame* pParentFrame) m_pSerializer->endElementNS(XML_wps, XML_wsp); m_pSerializer->endElementNS(XML_a, XML_graphicData); m_pSerializer->endElementNS(XML_a, XML_graphic); - lcl_endDMLAnchorInline(m_pSerializer, &rFrmFmt); + m_rExport.SdrExporter().endDMLAnchorInline(&rFrmFmt); } void DocxAttributeOutput::EndParagraph( ww8::WW8TableNodeInfoInner::Pointer_t pTextNodeInfoInner ) @@ -1297,7 +1278,7 @@ void DocxAttributeOutput::WritePostponedDiagram() for( std::list< PostponedDiagram >::const_iterator it = m_postponedDiagram->begin(); it != m_postponedDiagram->end(); ++it ) - WriteDiagram( it->object, it->size ); + m_rExport.SdrExporter().writeDiagram( it->object, it->size ); delete m_postponedDiagram; m_postponedDiagram = NULL; } @@ -2865,221 +2846,6 @@ void DocxAttributeOutput::WriteSrcRect(const SdrObject* pSdrObj ) } } -void lcl_endDMLAnchorInline(sax_fastparser::FSHelperPtr pSerializer, const SwFrmFmt* pFrmFmt) -{ - bool isAnchor = pFrmFmt->GetAnchor().GetAnchorId() != FLY_AS_CHAR; - pSerializer->endElementNS( XML_wp, isAnchor ? XML_anchor : XML_inline ); - - pSerializer->endElementNS( XML_w, XML_drawing ); -} - -void lcl_startDMLAnchorInline(sax_fastparser::FSHelperPtr pSerializer, const SwFrmFmt* pFrmFmt, const Size& rSize) -{ - pSerializer->startElementNS( XML_w, XML_drawing, FSEND ); - - const SvxLRSpaceItem pLRSpaceItem = pFrmFmt->GetLRSpace(false); - const SvxULSpaceItem pULSpaceItem = pFrmFmt->GetULSpace(false); - - bool isAnchor = pFrmFmt->GetAnchor().GetAnchorId() != FLY_AS_CHAR; - if( isAnchor ) - { - ::sax_fastparser::FastAttributeList* attrList = pSerializer->createAttrList(); - attrList->add( XML_behindDoc, pFrmFmt->GetOpaque().GetValue() ? "0" : "1" ); - attrList->add( XML_distT, OString::number( TwipsToEMU( pULSpaceItem.GetUpper() ) ).getStr( ) ); - attrList->add( XML_distB, OString::number( TwipsToEMU( pULSpaceItem.GetLower() ) ).getStr( ) ); - attrList->add( XML_distL, OString::number( TwipsToEMU( pLRSpaceItem.GetLeft() ) ).getStr( ) ); - attrList->add( XML_distR, OString::number( TwipsToEMU( pLRSpaceItem.GetRight() ) ).getStr( ) ); - attrList->add( XML_simplePos, "0" ); - attrList->add( XML_locked, "0" ); - attrList->add( XML_layoutInCell, "1" ); - attrList->add( XML_allowOverlap, "1" ); // TODO - if( const SdrObject* pObj = pFrmFmt->FindRealSdrObject()) - attrList->add( XML_relativeHeight, OString::number( pObj->GetOrdNum())); - pSerializer->startElementNS( XML_wp, XML_anchor, XFastAttributeListRef( attrList )); - pSerializer->singleElementNS( XML_wp, XML_simplePos, XML_x, "0", XML_y, "0", FSEND ); // required, unused - const char* relativeFromH; - const char* relativeFromV; - const char* alignH = NULL; - const char* alignV = NULL; - switch (pFrmFmt->GetVertOrient().GetRelationOrient() ) - { - case text::RelOrientation::PAGE_PRINT_AREA: - relativeFromV = "margin"; - break; - case text::RelOrientation::PAGE_FRAME: - relativeFromV = "page"; - break; - case text::RelOrientation::FRAME: - relativeFromV = "paragraph"; - break; - case text::RelOrientation::TEXT_LINE: - default: - relativeFromV = "line"; - break; - } - switch (pFrmFmt->GetVertOrient().GetVertOrient() ) - { - case text::VertOrientation::TOP: - case text::VertOrientation::CHAR_TOP: - case text::VertOrientation::LINE_TOP: - if( pFrmFmt->GetVertOrient().GetRelationOrient() == text::RelOrientation::TEXT_LINE) - alignV = "bottom"; - else - alignV = "top"; - break; - case text::VertOrientation::BOTTOM: - case text::VertOrientation::CHAR_BOTTOM: - case text::VertOrientation::LINE_BOTTOM: - if( pFrmFmt->GetVertOrient().GetRelationOrient() == text::RelOrientation::TEXT_LINE) - alignV = "top"; - else - alignV = "bottom"; - break; - case text::VertOrientation::CENTER: - case text::VertOrientation::CHAR_CENTER: - case text::VertOrientation::LINE_CENTER: - alignV = "center"; - break; - default: - break; - } - switch (pFrmFmt->GetHoriOrient().GetRelationOrient() ) - { - case text::RelOrientation::PAGE_PRINT_AREA: - relativeFromH = "margin"; - break; - case text::RelOrientation::PAGE_FRAME: - relativeFromH = "page"; - break; - case text::RelOrientation::CHAR: - relativeFromH = "character"; - break; - case text::RelOrientation::FRAME: - default: - relativeFromH = "column"; - break; - } - switch (pFrmFmt->GetHoriOrient().GetHoriOrient() ) - { - case text::HoriOrientation::LEFT: - alignH = "left"; - break; - case text::HoriOrientation::RIGHT: - alignH = "right"; - break; - case text::HoriOrientation::CENTER: - alignH = "center"; - break; - case text::HoriOrientation::INSIDE: - alignH = "inside"; - break; - case text::HoriOrientation::OUTSIDE: - alignH = "outside"; - break; - default: - break; - } - pSerializer->startElementNS( XML_wp, XML_positionH, XML_relativeFrom, relativeFromH, FSEND ); - if( alignH != NULL ) - { - pSerializer->startElementNS( XML_wp, XML_align, FSEND ); - pSerializer->write( alignH ); - pSerializer->endElementNS( XML_wp, XML_align ); - } - else - { - pSerializer->startElementNS( XML_wp, XML_posOffset, FSEND ); - pSerializer->write( TwipsToEMU( pFrmFmt->GetHoriOrient().GetPos())); - pSerializer->endElementNS( XML_wp, XML_posOffset ); - } - pSerializer->endElementNS( XML_wp, XML_positionH ); - pSerializer->startElementNS( XML_wp, XML_positionV, XML_relativeFrom, relativeFromV, FSEND ); - if( alignV != NULL ) - { - pSerializer->startElementNS( XML_wp, XML_align, FSEND ); - pSerializer->write( alignV ); - pSerializer->endElementNS( XML_wp, XML_align ); - } - else - { - pSerializer->startElementNS( XML_wp, XML_posOffset, FSEND ); - pSerializer->write( TwipsToEMU( pFrmFmt->GetVertOrient().GetPos())); - pSerializer->endElementNS( XML_wp, XML_posOffset ); - } - pSerializer->endElementNS( XML_wp, XML_positionV ); - } - else - { - pSerializer->startElementNS( XML_wp, XML_inline, - XML_distT, OString::number( TwipsToEMU( pULSpaceItem.GetUpper() ) ).getStr( ), - XML_distB, OString::number( TwipsToEMU( pULSpaceItem.GetLower() ) ).getStr( ), - XML_distL, OString::number( TwipsToEMU( pLRSpaceItem.GetLeft() ) ).getStr( ), - XML_distR, OString::number( TwipsToEMU( pLRSpaceItem.GetRight() ) ).getStr( ), - FSEND ); - } - - // now the common parts - // extent of the image - OString aWidth( OString::number( TwipsToEMU( rSize.Width() ) ) ); - OString aHeight( OString::number( TwipsToEMU( rSize.Height() ) ) ); - pSerializer->singleElementNS( XML_wp, XML_extent, - XML_cx, aWidth.getStr(), - XML_cy, aHeight.getStr(), - FSEND ); - - // effectExtent, extent including the effect (shadow only for now) - SvxShadowItem aShadowItem = pFrmFmt->GetShadow(); - OString aLeftExt("0"), aRightExt("0"), aTopExt("0"), aBottomExt("0"); - if ( aShadowItem.GetLocation() != SVX_SHADOW_NONE ) - { - OString aShadowWidth( OString::number( TwipsToEMU( aShadowItem.GetWidth() ) ) ); - switch ( aShadowItem.GetLocation() ) - { - case SVX_SHADOW_TOPLEFT: - aTopExt = aLeftExt = aShadowWidth; - break; - case SVX_SHADOW_TOPRIGHT: - aTopExt = aRightExt = aShadowWidth; - break; - case SVX_SHADOW_BOTTOMLEFT: - aBottomExt = aLeftExt = aShadowWidth; - break; - case SVX_SHADOW_BOTTOMRIGHT: - aBottomExt = aRightExt = aShadowWidth; - break; - case SVX_SHADOW_NONE: - case SVX_SHADOW_END: - break; - } - } - - pSerializer->singleElementNS( XML_wp, XML_effectExtent, - XML_l, aLeftExt, XML_t, aTopExt, XML_r, aRightExt, XML_b, aBottomExt, - FSEND ); - - if( isAnchor ) - { - switch( pFrmFmt->GetSurround().GetValue()) - { - case SURROUND_NONE: - pSerializer->singleElementNS( XML_wp, XML_wrapTopAndBottom, FSEND ); - break; - case SURROUND_THROUGHT: - pSerializer->singleElementNS( XML_wp, XML_wrapNone, FSEND ); - break; - case SURROUND_PARALLEL: - pSerializer->singleElementNS( XML_wp, XML_wrapSquare, - XML_wrapText, "bothSides", FSEND ); - break; - case SURROUND_IDEAL: - default: - pSerializer->singleElementNS( XML_wp, XML_wrapSquare, - XML_wrapText, "largest", FSEND ); - break; - } - } -} - void DocxAttributeOutput::FlyFrameGraphic( const SwGrfNode* pGrfNode, const Size& rSize, const SwFlyFrmFmt* pOLEFrmFmt, SwOLENode* pOLENode, const SdrObject* pSdrObj ) { OSL_TRACE( "TODO DocxAttributeOutput::FlyFrameGraphic( const SwGrfNode* pGrfNode, const Size& rSize, const SwFlyFrmFmt* pOLEFrmFmt, SwOLENode* pOLENode, const SdrObject* pSdrObj ) - some stuff still missing" ); @@ -3123,7 +2889,7 @@ void DocxAttributeOutput::FlyFrameGraphic( const SwGrfNode* pGrfNode, const Size if ( aRelId.isEmpty() ) return; - lcl_startDMLAnchorInline(m_pSerializer, pFrmFmt, rSize); + m_rExport.SdrExporter().startDMLAnchorInline(pFrmFmt, rSize); // picture description (used for pic:cNvPr later too) ::sax_fastparser::FastAttributeList* docPrattrList = m_pSerializer->createAttrList(); @@ -3282,7 +3048,7 @@ void DocxAttributeOutput::FlyFrameGraphic( const SwGrfNode* pGrfNode, const Size m_pSerializer->endElementNS( XML_a, XML_graphicData ); m_pSerializer->endElementNS( XML_a, XML_graphic ); - lcl_endDMLAnchorInline(m_pSerializer, pFrmFmt); + m_rExport.SdrExporter().endDMLAnchorInline(pFrmFmt); } void DocxAttributeOutput::WriteOLE2Obj( const SdrObject* pSdrObj, SwOLENode& rOLENode, const Size& rSize, const SwFlyFrmFmt* pFlyFrmFmt ) @@ -3435,7 +3201,7 @@ void DocxAttributeOutput::WritePostponedVMLDrawing() it != m_postponedVMLDrawing->end(); ++it ) { - WriteVMLDrawing(it->object, *(it->frame), *(it->point)); + m_rExport.SdrExporter().writeVMLDrawing(it->object, *(it->frame), *(it->point)); } delete m_postponedVMLDrawing; m_postponedVMLDrawing = NULL; @@ -3450,89 +3216,12 @@ void DocxAttributeOutput::WritePostponedDMLDrawing() it != m_postponedDMLDrawing->end(); ++it ) { - WriteDMLAndVMLDrawing(it->object, *(it->frame), *(it->point)); + m_rExport.SdrExporter().writeDMLAndVMLDrawing(it->object, *(it->frame), *(it->point), m_anchorId++); } delete m_postponedDMLDrawing; m_postponedDMLDrawing = NULL; } -void DocxAttributeOutput::WriteDMLDrawing( const SdrObject* pSdrObject, const SwFrmFmt* pFrmFmt ) -{ - Size aSize(pSdrObject->GetSnapRect().GetWidth(), pSdrObject->GetSnapRect().GetHeight()); - lcl_startDMLAnchorInline(m_pSerializer, pFrmFmt, aSize); - - sax_fastparser::FastAttributeList* pDocPrAttrList = m_pSerializer->createAttrList(); - pDocPrAttrList->add( XML_id, OString::number( m_anchorId++).getStr()); - pDocPrAttrList->add( XML_name, OUStringToOString(pSdrObject->GetName(), RTL_TEXTENCODING_UTF8).getStr() ); - XFastAttributeListRef xDocPrAttrListRef( pDocPrAttrList ); - m_pSerializer->singleElementNS( XML_wp, XML_docPr, xDocPrAttrListRef ); - - m_pSerializer->startElementNS( XML_a, XML_graphic, - FSNS( XML_xmlns, XML_a ), "http://schemas.openxmlformats.org/drawingml/2006/main", - FSEND ); - const SdrObjGroup* pObjGroup = PTR_CAST(SdrObjGroup, pSdrObject); - m_pSerializer->startElementNS( XML_a, XML_graphicData, - XML_uri, (pObjGroup ? "http://schemas.microsoft.com/office/word/2010/wordprocessingGroup" : "http://schemas.microsoft.com/office/word/2010/wordprocessingShape"), - FSEND ); - - uno::Reference xShape(const_cast(pSdrObject)->getUnoShape(), uno::UNO_QUERY_THROW); - m_rExport.OutputDML(xShape); - - m_pSerializer->endElementNS( XML_a, XML_graphicData ); - m_pSerializer->endElementNS( XML_a, XML_graphic ); - - lcl_endDMLAnchorInline(m_pSerializer, pFrmFmt); -} - -void DocxAttributeOutput::WriteDMLAndVMLDrawing(const SdrObject* sdrObj, const SwFrmFmt& rFrmFmt,const Point& rNdTopLeft) -{ - m_pSerializer->startElementNS(XML_mc, XML_AlternateContent, FSEND); - - const SdrObjGroup* pObjGroup = PTR_CAST(SdrObjGroup, sdrObj); - m_pSerializer->startElementNS(XML_mc, XML_Choice, - XML_Requires, (pObjGroup ? "wpg" : "wps"), - FSEND); - WriteDMLDrawing(sdrObj, &rFrmFmt); - m_pSerializer->endElementNS(XML_mc, XML_Choice); - - m_pSerializer->startElementNS(XML_mc, XML_Fallback, FSEND); - WriteVMLDrawing(sdrObj, rFrmFmt, rNdTopLeft); - m_pSerializer->endElementNS(XML_mc, XML_Fallback); - - m_pSerializer->endElementNS(XML_mc, XML_AlternateContent); -} - -void DocxAttributeOutput::WriteVMLDrawing( const SdrObject* sdrObj, const SwFrmFmt& rFrmFmt,const Point& rNdTopLeft ) -{ - bool bSwapInPage = false; - if ( !(sdrObj)->GetPage() ) - { - if ( SdrModel* pModel = m_rExport.pDoc->GetDrawModel() ) - { - if ( SdrPage *pPage = pModel->GetPage( 0 ) ) - { - bSwapInPage = true; - const_cast< SdrObject* >( sdrObj )->SetPage( pPage ); - } - } - } - - m_pSerializer->startElementNS( XML_w, XML_pict, FSEND ); - m_rDrawingML.SetFS(m_pSerializer); - // See WinwordAnchoring::SetAnchoring(), these are not part of the SdrObject, have to be passed around manually. - - SwFmtHoriOrient rHoriOri = (rFrmFmt).GetHoriOrient(); - SwFmtVertOrient rVertOri = (rFrmFmt).GetVertOrient(); - m_rExport.VMLExporter().AddSdrObject( *(sdrObj), - rHoriOri.GetHoriOrient(), rVertOri.GetVertOrient(), - rHoriOri.GetRelationOrient(), - rVertOri.GetRelationOrient(), (&rNdTopLeft), true ); - m_pSerializer->endElementNS( XML_w, XML_pict ); - - if ( bSwapInPage ) - const_cast< SdrObject* >( sdrObj )->SetPage( 0 ); -} - void DocxAttributeOutput::OutputFlyFrame_Impl( const sw::Frame &rFrame, const Point& rNdTopLeft ) { m_pSerializer->mark(); @@ -3563,7 +3252,7 @@ void DocxAttributeOutput::OutputFlyFrame_Impl( const sw::Frame &rFrame, const Po if ( IsDiagram( pSdrObj ) ) { if ( m_postponedDiagram == NULL ) - WriteDiagram( pSdrObj, rFrame.GetLayoutSize() ); + m_rExport.SdrExporter().writeDiagram( pSdrObj, rFrame.GetLayoutSize() ); else // we are writing out attributes, but w:drawing should not be inside w:rPr, { // so write it out later m_postponedDiagram->push_back( PostponedDiagram( pSdrObj, rFrame.GetSize() ) ); @@ -3575,7 +3264,7 @@ void DocxAttributeOutput::OutputFlyFrame_Impl( const sw::Frame &rFrame, const Po if (aMiscOptions.IsExperimentalMode()) { if ( m_postponedDMLDrawing == NULL ) - WriteDMLAndVMLDrawing( pSdrObj, rFrame.GetFrmFmt(), rNdTopLeft); + m_rExport.SdrExporter().writeDMLAndVMLDrawing( pSdrObj, rFrame.GetFrmFmt(), rNdTopLeft, m_anchorId++); else // we are writing out attributes, but w:drawing should not be inside w:rPr, so write it out later m_postponedDMLDrawing->push_back(PostponedDrawing(pSdrObj, &(rFrame.GetFrmFmt()), &rNdTopLeft)); @@ -3583,7 +3272,7 @@ void DocxAttributeOutput::OutputFlyFrame_Impl( const sw::Frame &rFrame, const Po else { if ( m_postponedVMLDrawing == NULL ) - WriteVMLDrawing( pSdrObj, rFrame.GetFrmFmt(), rNdTopLeft); + m_rExport.SdrExporter().writeVMLDrawing( pSdrObj, rFrame.GetFrmFmt(), rNdTopLeft); else // we are writing out attributes, but w:pict should not be inside w:rPr, { // so write it out later m_postponedVMLDrawing->push_back( PostponedDrawing( pSdrObj, &(rFrame.GetFrmFmt()), &rNdTopLeft ) ); @@ -3651,187 +3340,6 @@ bool DocxAttributeOutput::IsDiagram( const SdrObject* sdrObject ) return false; } -void DocxAttributeOutput::WriteDiagram( const SdrObject* sdrObject, const Size& size ) -{ - uno::Reference< drawing::XShape > xShape( ((SdrObject*)sdrObject)->getUnoShape(), uno::UNO_QUERY ); - uno::Reference< beans::XPropertySet > xPropSet( xShape, uno::UNO_QUERY ); - - uno::Reference dataDom; - uno::Reference layoutDom; - uno::Reference styleDom; - uno::Reference colorDom; - uno::Reference drawingDom; - - // retrieve the doms from the GrabBag - OUString pName = UNO_NAME_MISC_OBJ_INTEROPGRABBAG; - uno::Sequence< beans::PropertyValue > propList; - xPropSet->getPropertyValue( pName ) >>= propList; - for ( sal_Int32 nProp=0; nProp < propList.getLength(); ++nProp ) - { - OUString propName = propList[nProp].Name; - if ( propName == "OOXData" ) - propList[nProp].Value >>= dataDom; - else if ( propName == "OOXLayout" ) - propList[nProp].Value >>= layoutDom; - else if ( propName == "OOXStyle" ) - propList[nProp].Value >>= styleDom; - else if ( propName == "OOXColor" ) - propList[nProp].Value >>= colorDom; - else if ( propName == "OOXDrawing" ) - propList[nProp].Value >>= drawingDom; - } - - // check that we have the 4 mandatory XDocuments - // if not, there was an error importing and we won't output anything - if ( !dataDom.is() || !layoutDom.is() || !styleDom.is() || !colorDom.is() ) - return; - - // write necessary tags to document.xml - m_pSerializer->startElementNS( XML_w, XML_drawing, - FSEND ); - m_pSerializer->startElementNS( XML_wp, XML_inline, - XML_distT, "0", XML_distB, "0", XML_distL, "0", XML_distR, "0", - FSEND ); - - OString aWidth( OString::number( TwipsToEMU( size.Width() ) ) ); - OString aHeight( OString::number( TwipsToEMU( size.Height() ) ) ); - m_pSerializer->singleElementNS( XML_wp, XML_extent, - XML_cx, aWidth.getStr(), - XML_cy, aHeight.getStr(), - FSEND ); - // TODO - the right effectExtent, extent including the effect - m_pSerializer->singleElementNS( XML_wp, XML_effectExtent, - XML_l, "0", XML_t, "0", XML_r, "0", XML_b, "0", - FSEND ); - - // generate an unique id - static sal_Int32 diagramCount = 0; - diagramCount++; - OUString sName = "Diagram" + OUString::number( diagramCount ); - - m_pSerializer->singleElementNS( XML_wp, XML_docPr, - XML_id, I32S( diagramCount ), - XML_name, USS( sName ), - FSEND ); - - m_pSerializer->singleElementNS( XML_wp, XML_cNvGraphicFramePr, - FSEND ); - - m_pSerializer->startElementNS( XML_a, XML_graphic, - FSNS( XML_xmlns, XML_a ), "http://schemas.openxmlformats.org/drawingml/2006/main", - FSEND ); - - m_pSerializer->startElementNS( XML_a, XML_graphicData, - XML_uri, "http://schemas.openxmlformats.org/drawingml/2006/diagram", - FSEND ); - - // add data relation - OUString dataFileName = "diagrams/data" + OUString::number( diagramCount ) + ".xml"; - OString dataRelId = OUStringToOString(m_rExport.GetFilter().addRelation( m_pSerializer->getOutputStream(), - "http://schemas.openxmlformats.org/officeDocument/2006/relationships/diagramData", - dataFileName, false ), RTL_TEXTENCODING_UTF8 ); - - // add layout relation - OUString layoutFileName = "diagrams/layout" + OUString::number( diagramCount ) + ".xml"; - OString layoutRelId = OUStringToOString(m_rExport.GetFilter().addRelation( m_pSerializer->getOutputStream(), - "http://schemas.openxmlformats.org/officeDocument/2006/relationships/diagramLayout", - layoutFileName, false ), RTL_TEXTENCODING_UTF8 ); - - // add style relation - OUString styleFileName = "diagrams/quickStyle" + OUString::number( diagramCount ) + ".xml"; - OString styleRelId = OUStringToOString(m_rExport.GetFilter().addRelation( m_pSerializer->getOutputStream(), - "http://schemas.openxmlformats.org/officeDocument/2006/relationships/diagramQuickStyle", - styleFileName , false), RTL_TEXTENCODING_UTF8 ); - - // add color relation - OUString colorFileName = "diagrams/colors" + OUString::number( diagramCount ) + ".xml"; - OString colorRelId = OUStringToOString(m_rExport.GetFilter().addRelation( m_pSerializer->getOutputStream(), - "http://schemas.openxmlformats.org/officeDocument/2006/relationships/diagramColors", - colorFileName, false ), RTL_TEXTENCODING_UTF8 ); - - OUString drawingFileName; - if ( drawingDom.is() ) - { - // add drawing relation - drawingFileName = "diagrams/drawing" + OUString::number( diagramCount ) + ".xml"; - OUString drawingRelId = m_rExport.GetFilter().addRelation( m_pSerializer->getOutputStream(), - "http://schemas.microsoft.com/office/2007/relationships/diagramDrawing", - drawingFileName , false); - - // the data dom contains a reference to the drawing relation. We need to update it with the new generated - // relation value before writing the dom to a file - - // Get the dsp:damaModelExt node from the dom - uno::Reference< xml::dom::XNodeList > nodeList = - dataDom->getElementsByTagNameNS( "http://schemas.microsoft.com/office/drawing/2008/diagram", "dataModelExt" ); - - // There must be one element only so get it - uno::Reference< xml::dom::XNode > node = nodeList->item( 0 ); - - // Get the list of attributes of the node - uno::Reference< xml::dom::XNamedNodeMap > nodeMap = node->getAttributes(); - - // Get the node with the relId attribute and set its new value - uno::Reference< xml::dom::XNode > relIdNode = nodeMap->getNamedItem( "relId" ); - relIdNode->setNodeValue( drawingRelId ); - } - - m_pSerializer->singleElementNS ( XML_dgm, XML_relIds, - FSNS( XML_xmlns, XML_dgm ), "http://schemas.openxmlformats.org/drawingml/2006/diagram", - FSNS( XML_xmlns, XML_r ), "http://schemas.openxmlformats.org/officeDocument/2006/relationships", - FSNS( XML_r, XML_dm ), dataRelId.getStr(), - FSNS( XML_r, XML_lo ), layoutRelId.getStr(), - FSNS( XML_r, XML_qs ), styleRelId.getStr(), - FSNS( XML_r, XML_cs ), colorRelId.getStr(), - FSEND ); - - m_pSerializer->endElementNS( XML_a, XML_graphicData ); - m_pSerializer->endElementNS( XML_a, XML_graphic ); - m_pSerializer->endElementNS( XML_wp, XML_inline ); - m_pSerializer->endElementNS( XML_w, XML_drawing ); - - uno::Reference< xml::sax::XSAXSerializable > serializer; - uno::Reference< xml::sax::XWriter > writer = xml::sax::Writer::create( comphelper::getProcessComponentContext() ); - - // write data file - serializer.set( dataDom, uno::UNO_QUERY ); - writer->setOutputStream( m_rExport.GetFilter().openFragmentStream( "word/" + dataFileName, - "application/vnd.openxmlformats-officedocument.drawingml.diagramData+xml" ) ); - serializer->serialize( uno::Reference< xml::sax::XDocumentHandler >( writer, uno::UNO_QUERY_THROW ), - uno::Sequence< beans::StringPair >() ); - - // write layout file - serializer.set( layoutDom, uno::UNO_QUERY ); - writer->setOutputStream( m_rExport.GetFilter().openFragmentStream( "word/" + layoutFileName, - "application/vnd.openxmlformats-officedocument.drawingml.diagramLayout+xml" ) ); - serializer->serialize( uno::Reference< xml::sax::XDocumentHandler >( writer, uno::UNO_QUERY_THROW ), - uno::Sequence< beans::StringPair >() ); - - // write style file - serializer.set( styleDom, uno::UNO_QUERY ); - writer->setOutputStream( m_rExport.GetFilter().openFragmentStream( "word/" + styleFileName, - "application/vnd.openxmlformats-officedocument.drawingml.diagramStyle+xml" ) ); - serializer->serialize( uno::Reference< xml::sax::XDocumentHandler >( writer, uno::UNO_QUERY_THROW ), - uno::Sequence< beans::StringPair >() ); - - // write color file - serializer.set( colorDom, uno::UNO_QUERY ); - writer->setOutputStream( m_rExport.GetFilter().openFragmentStream( "word/" + colorFileName, - "application/vnd.openxmlformats-officedocument.drawingml.diagramColors+xml" ) ); - serializer->serialize( uno::Reference< xml::sax::XDocumentHandler >( writer, uno::UNO_QUERY_THROW ), - uno::Sequence< beans::StringPair >() ); - - // write drawing file - if ( drawingDom.is() ) - { - serializer.set( drawingDom, uno::UNO_QUERY ); - writer->setOutputStream( m_rExport.GetFilter().openFragmentStream( "word/" + drawingFileName, - "application/vnd.openxmlformats-officedocument.drawingml.diagramDrawing+xml" ) ); - serializer->serialize( uno::Reference< xml::sax::XDocumentHandler >( writer, uno::UNO_QUERY_THROW ), - uno::Sequence< beans::StringPair >() ); - } -} - void DocxAttributeOutput::WriteOutliner(const OutlinerParaObject& rParaObj) { const EditTextObject& rEditObj = rParaObj.GetTextObject(); diff --git a/sw/source/filter/ww8/docxattributeoutput.hxx b/sw/source/filter/ww8/docxattributeoutput.hxx index 3ef815abbfa6..18fd11e5fb11 100644 --- a/sw/source/filter/ww8/docxattributeoutput.hxx +++ b/sw/source/filter/ww8/docxattributeoutput.hxx @@ -388,15 +388,6 @@ private: /// checks whether the current component is a diagram bool IsDiagram (const SdrObject* sdrObject); - /// writes a diagram - void WriteDiagram(const SdrObject* sdrObject, const Size& size); - - /// writes VML data - void WriteVMLDrawing( const SdrObject* sdrObj, const SwFrmFmt& rFrmFmt,const Point& rNdTopLeft ); - /// Writes wp wrapper code around an SdrObject, which itself is written using drawingML syntax. - void WriteDMLDrawing( const SdrObject* pSdrObj, const SwFrmFmt* pFrmFmt ); - /// Writes shape in both DML and VML format. - void WriteDMLAndVMLDrawing( const SdrObject* sdrObj, const SwFrmFmt& rFrmFmt,const Point& rNdTopLeft ); /// Writes text frame in VML format. void WriteVMLTextFrame(sw::Frame* pParentFrame); diff --git a/sw/source/filter/ww8/docxexport.cxx b/sw/source/filter/ww8/docxexport.cxx index 2409e425ad94..051d84180c1f 100644 --- a/sw/source/filter/ww8/docxexport.cxx +++ b/sw/source/filter/ww8/docxexport.cxx @@ -20,6 +20,7 @@ #include "docxexport.hxx" #include "docxexportfilter.hxx" #include "docxattributeoutput.hxx" +#include "docxsdrexport.hxx" #include #include @@ -629,6 +630,7 @@ void DocxExport::WriteHeaderFooter( const SwFmt& rFmt, bool bHeader, const char* // switch the serializer to redirect the output to word/styles.xml m_pAttrOutput->SetSerializer( pFS ); m_pVMLExport->SetFS( pFS ); + m_pSdrExport->setSerializer(pFS); m_pAttrOutput->switchHeaderFooter(true, m_nHeadersFootersInSection++); // do the work WriteHeaderFooterText( rFmt, bHeader ); @@ -636,6 +638,7 @@ void DocxExport::WriteHeaderFooter( const SwFmt& rFmt, bool bHeader, const char* // switch the serializer back m_pAttrOutput->SetSerializer( m_pDocumentFS ); m_pVMLExport->SetFS( m_pDocumentFS ); + m_pSdrExport->setSerializer(m_pDocumentFS); // close the tag sal_Int32 nReference; @@ -1076,6 +1079,11 @@ VMLExport& DocxExport::VMLExporter() return *m_pVMLExport; } +DocxSdrExport& DocxExport::SdrExporter() +{ + return *m_pSdrExport; +} + boost::optional DocxExport::getBackground() { boost::optional oRet; @@ -1201,7 +1209,8 @@ DocxExport::DocxExport( DocxExportFilter *pFilter, SwDoc *pDocument, SwPaM *pCur m_nHeaders( 0 ), m_nFooters( 0 ), m_nHeadersFootersInSection(0), - m_pVMLExport( NULL ) + m_pVMLExport( NULL ), + m_pSdrExport( NULL ) { // Write the document properies WriteProperties( ); @@ -1222,10 +1231,14 @@ DocxExport::DocxExport( DocxExportFilter *pFilter, SwDoc *pDocument, SwPaM *pCur // the related VMLExport m_pVMLExport = new VMLExport( m_pDocumentFS, m_pAttrOutput ); + + // the related drawing export + m_pSdrExport = new DocxSdrExport( *this, m_pDocumentFS, m_pDrawingML ); } DocxExport::~DocxExport() { + delete m_pSdrExport, m_pSdrExport = NULL; delete m_pVMLExport, m_pVMLExport = NULL; delete m_pAttrOutput, m_pAttrOutput = NULL; delete m_pDrawingML, m_pDrawingML = NULL; diff --git a/sw/source/filter/ww8/docxexport.hxx b/sw/source/filter/ww8/docxexport.hxx index 5dd9e04b9f1b..10f2f8de7beb 100644 --- a/sw/source/filter/ww8/docxexport.hxx +++ b/sw/source/filter/ww8/docxexport.hxx @@ -38,6 +38,7 @@ class SwTableNode; class SwTxtNode; class SwGrfNode; class SwOLENode; +class DocxSdrExport; namespace oox { namespace drawingml { class DrawingML; } @@ -89,6 +90,9 @@ class DocxExport : public MSWordExportBase /// Exporter of the VML shapes. oox::vml::VMLExport *m_pVMLExport; + /// Exporter of drawings. + DocxSdrExport* m_pSdrExport; + DocxSettingsData settings; public: @@ -242,6 +246,9 @@ public: /// Reference to the VMLExport instance for the main document. oox::vml::VMLExport& VMLExporter(); + /// Reference to the DocxSdrExport instance for the main document. + DocxSdrExport& SdrExporter(); + /// Set the document default tab stop. void setDefaultTabStop( int stop ) { settings.defaultTabStop = stop; } diff --git a/sw/source/filter/ww8/docxsdrexport.cxx b/sw/source/filter/ww8/docxsdrexport.cxx new file mode 100644 index 000000000000..57affcf91cde --- /dev/null +++ b/sw/source/filter/ww8/docxsdrexport.cxx @@ -0,0 +1,552 @@ +/* -*- 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +using namespace com::sun::star; +using namespace oox; + +/// Holds data used by DocxSdrExport only. +struct DocxSdrExport::Impl +{ + DocxSdrExport& m_rSdrExport; + DocxExport& m_rExport; + sax_fastparser::FSHelperPtr m_pSerializer; + oox::drawingml::DrawingML* m_pDrawingML; + + Impl(DocxSdrExport& rSdrExport, DocxExport& rExport, sax_fastparser::FSHelperPtr pSerializer, oox::drawingml::DrawingML* pDrawingML) + : m_rSdrExport(rSdrExport), + m_rExport(rExport), + m_pSerializer(pSerializer), + m_pDrawingML(pDrawingML) + { + } + /// Writes wp wrapper code around an SdrObject, which itself is written using drawingML syntax. + void writeDMLDrawing(const SdrObject* pSdrObj, const SwFrmFmt* pFrmFmt, int nAnchorId); +}; + +DocxSdrExport::DocxSdrExport(DocxExport& rExport, sax_fastparser::FSHelperPtr pSerializer, oox::drawingml::DrawingML* pDrawingML) + : m_pImpl(new Impl(*this, rExport, pSerializer, pDrawingML)) +{ +} + +DocxSdrExport::~DocxSdrExport() +{ +} + +void DocxSdrExport::setSerializer(sax_fastparser::FSHelperPtr pSerializer) +{ + m_pImpl->m_pSerializer = pSerializer; +} + +void DocxSdrExport::startDMLAnchorInline(const SwFrmFmt* pFrmFmt, const Size& rSize) +{ + m_pImpl->m_pSerializer->startElementNS(XML_w, XML_drawing, FSEND); + + const SvxLRSpaceItem pLRSpaceItem = pFrmFmt->GetLRSpace(false); + const SvxULSpaceItem pULSpaceItem = pFrmFmt->GetULSpace(false); + + bool isAnchor = pFrmFmt->GetAnchor().GetAnchorId() != FLY_AS_CHAR; + if (isAnchor) + { + ::sax_fastparser::FastAttributeList* attrList = m_pImpl->m_pSerializer->createAttrList(); + attrList->add(XML_behindDoc, pFrmFmt->GetOpaque().GetValue() ? "0" : "1"); + attrList->add(XML_distT, OString::number(TwipsToEMU(pULSpaceItem.GetUpper())).getStr()); + attrList->add(XML_distB, OString::number(TwipsToEMU(pULSpaceItem.GetLower())).getStr()); + attrList->add(XML_distL, OString::number(TwipsToEMU(pLRSpaceItem.GetLeft())).getStr()); + attrList->add(XML_distR, OString::number(TwipsToEMU(pLRSpaceItem.GetRight())).getStr()); + attrList->add(XML_simplePos, "0"); + attrList->add(XML_locked, "0"); + attrList->add(XML_layoutInCell, "1"); + attrList->add(XML_allowOverlap, "1"); // TODO + if (const SdrObject* pObj = pFrmFmt->FindRealSdrObject()) + attrList->add(XML_relativeHeight, OString::number(pObj->GetOrdNum())); + sax_fastparser::XFastAttributeListRef xAttrList(attrList); + m_pImpl->m_pSerializer->startElementNS(XML_wp, XML_anchor, xAttrList); + m_pImpl->m_pSerializer->singleElementNS(XML_wp, XML_simplePos, XML_x, "0", XML_y, "0", FSEND); // required, unused + const char* relativeFromH; + const char* relativeFromV; + const char* alignH = NULL; + const char* alignV = NULL; + switch (pFrmFmt->GetVertOrient().GetRelationOrient()) + { + case text::RelOrientation::PAGE_PRINT_AREA: + relativeFromV = "margin"; + break; + case text::RelOrientation::PAGE_FRAME: + relativeFromV = "page"; + break; + case text::RelOrientation::FRAME: + relativeFromV = "paragraph"; + break; + case text::RelOrientation::TEXT_LINE: + default: + relativeFromV = "line"; + break; + } + switch (pFrmFmt->GetVertOrient().GetVertOrient()) + { + case text::VertOrientation::TOP: + case text::VertOrientation::CHAR_TOP: + case text::VertOrientation::LINE_TOP: + if (pFrmFmt->GetVertOrient().GetRelationOrient() == text::RelOrientation::TEXT_LINE) + alignV = "bottom"; + else + alignV = "top"; + break; + case text::VertOrientation::BOTTOM: + case text::VertOrientation::CHAR_BOTTOM: + case text::VertOrientation::LINE_BOTTOM: + if (pFrmFmt->GetVertOrient().GetRelationOrient() == text::RelOrientation::TEXT_LINE) + alignV = "top"; + else + alignV = "bottom"; + break; + case text::VertOrientation::CENTER: + case text::VertOrientation::CHAR_CENTER: + case text::VertOrientation::LINE_CENTER: + alignV = "center"; + break; + default: + break; + } + switch (pFrmFmt->GetHoriOrient().GetRelationOrient()) + { + case text::RelOrientation::PAGE_PRINT_AREA: + relativeFromH = "margin"; + break; + case text::RelOrientation::PAGE_FRAME: + relativeFromH = "page"; + break; + case text::RelOrientation::CHAR: + relativeFromH = "character"; + break; + case text::RelOrientation::FRAME: + default: + relativeFromH = "column"; + break; + } + switch (pFrmFmt->GetHoriOrient().GetHoriOrient()) + { + case text::HoriOrientation::LEFT: + alignH = "left"; + break; + case text::HoriOrientation::RIGHT: + alignH = "right"; + break; + case text::HoriOrientation::CENTER: + alignH = "center"; + break; + case text::HoriOrientation::INSIDE: + alignH = "inside"; + break; + case text::HoriOrientation::OUTSIDE: + alignH = "outside"; + break; + default: + break; + } + m_pImpl->m_pSerializer->startElementNS(XML_wp, XML_positionH, XML_relativeFrom, relativeFromH, FSEND); + if (alignH != NULL) + { + m_pImpl->m_pSerializer->startElementNS(XML_wp, XML_align, FSEND); + m_pImpl->m_pSerializer->write(alignH); + m_pImpl->m_pSerializer->endElementNS(XML_wp, XML_align); + } + else + { + m_pImpl->m_pSerializer->startElementNS(XML_wp, XML_posOffset, FSEND); + m_pImpl->m_pSerializer->write(TwipsToEMU(pFrmFmt->GetHoriOrient().GetPos())); + m_pImpl->m_pSerializer->endElementNS(XML_wp, XML_posOffset); + } + m_pImpl->m_pSerializer->endElementNS(XML_wp, XML_positionH); + m_pImpl->m_pSerializer->startElementNS(XML_wp, XML_positionV, XML_relativeFrom, relativeFromV, FSEND); + if (alignV != NULL) + { + m_pImpl->m_pSerializer->startElementNS(XML_wp, XML_align, FSEND); + m_pImpl->m_pSerializer->write(alignV); + m_pImpl->m_pSerializer->endElementNS(XML_wp, XML_align); + } + else + { + m_pImpl->m_pSerializer->startElementNS(XML_wp, XML_posOffset, FSEND); + m_pImpl->m_pSerializer->write(TwipsToEMU(pFrmFmt->GetVertOrient().GetPos())); + m_pImpl->m_pSerializer->endElementNS(XML_wp, XML_posOffset); + } + m_pImpl->m_pSerializer->endElementNS(XML_wp, XML_positionV); + } + else + { + m_pImpl->m_pSerializer->startElementNS(XML_wp, XML_inline, + XML_distT, OString::number(TwipsToEMU(pULSpaceItem.GetUpper())).getStr(), + XML_distB, OString::number(TwipsToEMU(pULSpaceItem.GetLower())).getStr(), + XML_distL, OString::number(TwipsToEMU(pLRSpaceItem.GetLeft())).getStr(), + XML_distR, OString::number(TwipsToEMU(pLRSpaceItem.GetRight())).getStr(), + FSEND); + } + + // now the common parts + // extent of the image + OString aWidth(OString::number(TwipsToEMU(rSize.Width()))); + OString aHeight(OString::number(TwipsToEMU(rSize.Height()))); + m_pImpl->m_pSerializer->singleElementNS(XML_wp, XML_extent, + XML_cx, aWidth.getStr(), + XML_cy, aHeight.getStr(), + FSEND); + + // effectExtent, extent including the effect (shadow only for now) + SvxShadowItem aShadowItem = pFrmFmt->GetShadow(); + OString aLeftExt("0"), aRightExt("0"), aTopExt("0"), aBottomExt("0"); + if (aShadowItem.GetLocation() != SVX_SHADOW_NONE) + { + OString aShadowWidth(OString::number(TwipsToEMU(aShadowItem.GetWidth()))); + switch (aShadowItem.GetLocation()) + { + case SVX_SHADOW_TOPLEFT: + aTopExt = aLeftExt = aShadowWidth; + break; + case SVX_SHADOW_TOPRIGHT: + aTopExt = aRightExt = aShadowWidth; + break; + case SVX_SHADOW_BOTTOMLEFT: + aBottomExt = aLeftExt = aShadowWidth; + break; + case SVX_SHADOW_BOTTOMRIGHT: + aBottomExt = aRightExt = aShadowWidth; + break; + case SVX_SHADOW_NONE: + case SVX_SHADOW_END: + break; + } + } + + m_pImpl->m_pSerializer->singleElementNS(XML_wp, XML_effectExtent, + XML_l, aLeftExt, + XML_t, aTopExt, + XML_r, aRightExt, + XML_b, aBottomExt, + FSEND); + + if (isAnchor) + { + switch (pFrmFmt->GetSurround().GetValue()) + { + case SURROUND_NONE: + m_pImpl->m_pSerializer->singleElementNS(XML_wp, XML_wrapTopAndBottom, FSEND); + break; + case SURROUND_THROUGHT: + m_pImpl->m_pSerializer->singleElementNS(XML_wp, XML_wrapNone, FSEND); + break; + case SURROUND_PARALLEL: + m_pImpl->m_pSerializer->singleElementNS(XML_wp, XML_wrapSquare, + XML_wrapText, "bothSides", FSEND); + break; + case SURROUND_IDEAL: + default: + m_pImpl->m_pSerializer->singleElementNS(XML_wp, XML_wrapSquare, + XML_wrapText, "largest", FSEND); + break; + } + } +} + +void DocxSdrExport::endDMLAnchorInline(const SwFrmFmt* pFrmFmt) +{ + bool isAnchor = pFrmFmt->GetAnchor().GetAnchorId() != FLY_AS_CHAR; + m_pImpl->m_pSerializer->endElementNS(XML_wp, isAnchor ? XML_anchor : XML_inline); + + m_pImpl->m_pSerializer->endElementNS(XML_w, XML_drawing); +} + +void DocxSdrExport::writeVMLDrawing(const SdrObject* sdrObj, const SwFrmFmt& rFrmFmt,const Point& rNdTopLeft) +{ + bool bSwapInPage = false; + if (!(sdrObj)->GetPage()) + { + if (SdrModel* pModel = m_pImpl->m_rExport.pDoc->GetDrawModel()) + { + if (SdrPage* pPage = pModel->GetPage(0)) + { + bSwapInPage = true; + const_cast< SdrObject* >(sdrObj)->SetPage(pPage); + } + } + } + + m_pImpl->m_pSerializer->startElementNS(XML_w, XML_pict, FSEND); + m_pImpl->m_pDrawingML->SetFS(m_pImpl->m_pSerializer); + // See WinwordAnchoring::SetAnchoring(), these are not part of the SdrObject, have to be passed around manually. + + SwFmtHoriOrient rHoriOri = (rFrmFmt).GetHoriOrient(); + SwFmtVertOrient rVertOri = (rFrmFmt).GetVertOrient(); + m_pImpl->m_rExport.VMLExporter().AddSdrObject(*(sdrObj), + rHoriOri.GetHoriOrient(), rVertOri.GetVertOrient(), + rHoriOri.GetRelationOrient(), + rVertOri.GetRelationOrient(), (&rNdTopLeft), true); + m_pImpl->m_pSerializer->endElementNS(XML_w, XML_pict); + + if (bSwapInPage) + const_cast< SdrObject* >(sdrObj)->SetPage(0); +} + +void DocxSdrExport::Impl::writeDMLDrawing(const SdrObject* pSdrObject, const SwFrmFmt* pFrmFmt, int nAnchorId) +{ + sax_fastparser::FSHelperPtr pFS = m_pSerializer; + Size aSize(pSdrObject->GetSnapRect().GetWidth(), pSdrObject->GetSnapRect().GetHeight()); + m_rSdrExport.startDMLAnchorInline(pFrmFmt, aSize); + + sax_fastparser::FastAttributeList* pDocPrAttrList = pFS->createAttrList(); + pDocPrAttrList->add(XML_id, OString::number(nAnchorId).getStr()); + pDocPrAttrList->add(XML_name, OUStringToOString(pSdrObject->GetName(), RTL_TEXTENCODING_UTF8).getStr()); + sax_fastparser::XFastAttributeListRef xDocPrAttrListRef(pDocPrAttrList); + pFS->singleElementNS(XML_wp, XML_docPr, xDocPrAttrListRef); + + pFS->startElementNS(XML_a, XML_graphic, + FSNS(XML_xmlns, XML_a), "http://schemas.openxmlformats.org/drawingml/2006/main", + FSEND); + const SdrObjGroup* pObjGroup = PTR_CAST(SdrObjGroup, pSdrObject); + pFS->startElementNS(XML_a, XML_graphicData, + XML_uri, (pObjGroup ? "http://schemas.microsoft.com/office/word/2010/wordprocessingGroup" : "http://schemas.microsoft.com/office/word/2010/wordprocessingShape"), + FSEND); + + uno::Reference xShape(const_cast(pSdrObject)->getUnoShape(), uno::UNO_QUERY_THROW); + m_rExport.OutputDML(xShape); + + pFS->endElementNS(XML_a, XML_graphicData); + pFS->endElementNS(XML_a, XML_graphic); + + m_rSdrExport.endDMLAnchorInline(pFrmFmt); +} + +void DocxSdrExport::writeDMLAndVMLDrawing(const SdrObject* sdrObj, const SwFrmFmt& rFrmFmt,const Point& rNdTopLeft, int nAnchorId) +{ + m_pImpl->m_pSerializer->startElementNS(XML_mc, XML_AlternateContent, FSEND); + + const SdrObjGroup* pObjGroup = PTR_CAST(SdrObjGroup, sdrObj); + m_pImpl->m_pSerializer->startElementNS(XML_mc, XML_Choice, + XML_Requires, (pObjGroup ? "wpg" : "wps"), + FSEND); + m_pImpl->writeDMLDrawing(sdrObj, &rFrmFmt, nAnchorId); + m_pImpl->m_pSerializer->endElementNS(XML_mc, XML_Choice); + + m_pImpl->m_pSerializer->startElementNS(XML_mc, XML_Fallback, FSEND); + writeVMLDrawing(sdrObj, rFrmFmt, rNdTopLeft); + m_pImpl->m_pSerializer->endElementNS(XML_mc, XML_Fallback); + + m_pImpl->m_pSerializer->endElementNS(XML_mc, XML_AlternateContent); +} + +void DocxSdrExport::writeDiagram(const SdrObject* sdrObject, const Size& size) +{ + sax_fastparser::FSHelperPtr pFS = m_pImpl->m_pSerializer; + uno::Reference< drawing::XShape > xShape(((SdrObject*)sdrObject)->getUnoShape(), uno::UNO_QUERY); + uno::Reference< beans::XPropertySet > xPropSet(xShape, uno::UNO_QUERY); + + uno::Reference dataDom; + uno::Reference layoutDom; + uno::Reference styleDom; + uno::Reference colorDom; + uno::Reference drawingDom; + + // retrieve the doms from the GrabBag + OUString pName = UNO_NAME_MISC_OBJ_INTEROPGRABBAG; + uno::Sequence< beans::PropertyValue > propList; + xPropSet->getPropertyValue(pName) >>= propList; + for (sal_Int32 nProp=0; nProp < propList.getLength(); ++nProp) + { + OUString propName = propList[nProp].Name; + if (propName == "OOXData") + propList[nProp].Value >>= dataDom; + else if (propName == "OOXLayout") + propList[nProp].Value >>= layoutDom; + else if (propName == "OOXStyle") + propList[nProp].Value >>= styleDom; + else if (propName == "OOXColor") + propList[nProp].Value >>= colorDom; + else if (propName == "OOXDrawing") + propList[nProp].Value >>= drawingDom; + } + + // check that we have the 4 mandatory XDocuments + // if not, there was an error importing and we won't output anything + if (!dataDom.is() || !layoutDom.is() || !styleDom.is() || !colorDom.is()) + return; + + // write necessary tags to document.xml + pFS->startElementNS(XML_w, XML_drawing, + FSEND); + pFS->startElementNS(XML_wp, XML_inline, + XML_distT, "0", XML_distB, "0", XML_distL, "0", XML_distR, "0", + FSEND); + + OString aWidth(OString::number(TwipsToEMU(size.Width()))); + OString aHeight(OString::number(TwipsToEMU(size.Height()))); + pFS->singleElementNS(XML_wp, XML_extent, + XML_cx, aWidth.getStr(), + XML_cy, aHeight.getStr(), + FSEND); + // TODO - the right effectExtent, extent including the effect + pFS->singleElementNS(XML_wp, XML_effectExtent, + XML_l, "0", XML_t, "0", XML_r, "0", XML_b, "0", + FSEND); + + // generate an unique id + static sal_Int32 diagramCount = 0; + diagramCount++; + OUString sName = "Diagram" + OUString::number(diagramCount); + + pFS->singleElementNS(XML_wp, XML_docPr, + XML_id, I32S(diagramCount), + XML_name, USS(sName), + FSEND); + + pFS->singleElementNS(XML_wp, XML_cNvGraphicFramePr, + FSEND); + + pFS->startElementNS(XML_a, XML_graphic, + FSNS(XML_xmlns, XML_a), "http://schemas.openxmlformats.org/drawingml/2006/main", + FSEND); + + pFS->startElementNS(XML_a, XML_graphicData, + XML_uri, "http://schemas.openxmlformats.org/drawingml/2006/diagram", + FSEND); + + // add data relation + OUString dataFileName = "diagrams/data" + OUString::number(diagramCount) + ".xml"; + OString dataRelId = OUStringToOString(m_pImpl->m_rExport.GetFilter().addRelation(pFS->getOutputStream(), + "http://schemas.openxmlformats.org/officeDocument/2006/relationships/diagramData", + dataFileName, false), RTL_TEXTENCODING_UTF8); + + // add layout relation + OUString layoutFileName = "diagrams/layout" + OUString::number(diagramCount) + ".xml"; + OString layoutRelId = OUStringToOString(m_pImpl->m_rExport.GetFilter().addRelation(pFS->getOutputStream(), + "http://schemas.openxmlformats.org/officeDocument/2006/relationships/diagramLayout", + layoutFileName, false), RTL_TEXTENCODING_UTF8); + + // add style relation + OUString styleFileName = "diagrams/quickStyle" + OUString::number(diagramCount) + ".xml"; + OString styleRelId = OUStringToOString(m_pImpl->m_rExport.GetFilter().addRelation(pFS->getOutputStream(), + "http://schemas.openxmlformats.org/officeDocument/2006/relationships/diagramQuickStyle", + styleFileName , false), RTL_TEXTENCODING_UTF8); + + // add color relation + OUString colorFileName = "diagrams/colors" + OUString::number(diagramCount) + ".xml"; + OString colorRelId = OUStringToOString(m_pImpl->m_rExport.GetFilter().addRelation(pFS->getOutputStream(), + "http://schemas.openxmlformats.org/officeDocument/2006/relationships/diagramColors", + colorFileName, false), RTL_TEXTENCODING_UTF8); + + OUString drawingFileName; + if (drawingDom.is()) + { + // add drawing relation + drawingFileName = "diagrams/drawing" + OUString::number(diagramCount) + ".xml"; + OUString drawingRelId = m_pImpl->m_rExport.GetFilter().addRelation(pFS->getOutputStream(), + "http://schemas.microsoft.com/office/2007/relationships/diagramDrawing", + drawingFileName , false); + + // the data dom contains a reference to the drawing relation. We need to update it with the new generated + // relation value before writing the dom to a file + + // Get the dsp:damaModelExt node from the dom + uno::Reference< xml::dom::XNodeList > nodeList = + dataDom->getElementsByTagNameNS("http://schemas.microsoft.com/office/drawing/2008/diagram", "dataModelExt"); + + // There must be one element only so get it + uno::Reference< xml::dom::XNode > node = nodeList->item(0); + + // Get the list of attributes of the node + uno::Reference< xml::dom::XNamedNodeMap > nodeMap = node->getAttributes(); + + // Get the node with the relId attribute and set its new value + uno::Reference< xml::dom::XNode > relIdNode = nodeMap->getNamedItem("relId"); + relIdNode->setNodeValue(drawingRelId); + } + + pFS->singleElementNS(XML_dgm, XML_relIds, + FSNS(XML_xmlns, XML_dgm), "http://schemas.openxmlformats.org/drawingml/2006/diagram", + FSNS(XML_xmlns, XML_r), "http://schemas.openxmlformats.org/officeDocument/2006/relationships", + FSNS(XML_r, XML_dm), dataRelId.getStr(), + FSNS(XML_r, XML_lo), layoutRelId.getStr(), + FSNS(XML_r, XML_qs), styleRelId.getStr(), + FSNS(XML_r, XML_cs), colorRelId.getStr(), + FSEND); + + pFS->endElementNS(XML_a, XML_graphicData); + pFS->endElementNS(XML_a, XML_graphic); + pFS->endElementNS(XML_wp, XML_inline); + pFS->endElementNS(XML_w, XML_drawing); + + uno::Reference< xml::sax::XSAXSerializable > serializer; + uno::Reference< xml::sax::XWriter > writer = xml::sax::Writer::create(comphelper::getProcessComponentContext()); + + // write data file + serializer.set(dataDom, uno::UNO_QUERY); + writer->setOutputStream(m_pImpl->m_rExport.GetFilter().openFragmentStream("word/" + dataFileName, + "application/vnd.openxmlformats-officedocument.drawingml.diagramData+xml")); + serializer->serialize(uno::Reference< xml::sax::XDocumentHandler >(writer, uno::UNO_QUERY_THROW), + uno::Sequence< beans::StringPair >()); + + // write layout file + serializer.set(layoutDom, uno::UNO_QUERY); + writer->setOutputStream(m_pImpl->m_rExport.GetFilter().openFragmentStream("word/" + layoutFileName, + "application/vnd.openxmlformats-officedocument.drawingml.diagramLayout+xml")); + serializer->serialize(uno::Reference< xml::sax::XDocumentHandler >(writer, uno::UNO_QUERY_THROW), + uno::Sequence< beans::StringPair >()); + + // write style file + serializer.set(styleDom, uno::UNO_QUERY); + writer->setOutputStream(m_pImpl->m_rExport.GetFilter().openFragmentStream("word/" + styleFileName, + "application/vnd.openxmlformats-officedocument.drawingml.diagramStyle+xml")); + serializer->serialize(uno::Reference< xml::sax::XDocumentHandler >(writer, uno::UNO_QUERY_THROW), + uno::Sequence< beans::StringPair >()); + + // write color file + serializer.set(colorDom, uno::UNO_QUERY); + writer->setOutputStream(m_pImpl->m_rExport.GetFilter().openFragmentStream("word/" + colorFileName, + "application/vnd.openxmlformats-officedocument.drawingml.diagramColors+xml")); + serializer->serialize(uno::Reference< xml::sax::XDocumentHandler >(writer, uno::UNO_QUERY_THROW), + uno::Sequence< beans::StringPair >()); + + // write drawing file + if (drawingDom.is()) + { + serializer.set(drawingDom, uno::UNO_QUERY); + writer->setOutputStream(m_pImpl->m_rExport.GetFilter().openFragmentStream("word/" + drawingFileName, + "application/vnd.openxmlformats-officedocument.drawingml.diagramDrawing+xml")); + serializer->serialize(uno::Reference< xml::sax::XDocumentHandler >(writer, uno::UNO_QUERY_THROW), + uno::Sequence< beans::StringPair >()); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/filter/ww8/docxsdrexport.hxx b/sw/source/filter/ww8/docxsdrexport.hxx new file mode 100644 index 000000000000..02e0c52baf7e --- /dev/null +++ b/sw/source/filter/ww8/docxsdrexport.hxx @@ -0,0 +1,54 @@ +/* -*- 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/. + */ + +#ifndef INCLUDED_SW_SOURCE_FILTER_WW8_DOCXSDREXPORT_HXX +#define INCLUDED_SW_SOURCE_FILTER_WW8_DOCXSDREXPORT_HXX + +#include +#include + +namespace oox +{ +namespace drawingml +{ +class DrawingML; +} +} +class Size; +class Point; +class SdrObject; + +class SwFrmFmt; + +class DocxExport; + +/// Handles DOCX export of drawings. +class DocxSdrExport +{ + struct Impl; + boost::shared_ptr m_pImpl; +public: + DocxSdrExport(DocxExport& rExport, sax_fastparser::FSHelperPtr pSerializer, oox::drawingml::DrawingML* pDrawingML); + ~DocxSdrExport(); + + void setSerializer(sax_fastparser::FSHelperPtr pSerializer); + + void startDMLAnchorInline(const SwFrmFmt* pFrmFmt, const Size& rSize); + void endDMLAnchorInline(const SwFrmFmt* pFrmFmt); + /// Writes a drawing as VML data. + void writeVMLDrawing(const SdrObject* sdrObj, const SwFrmFmt& rFrmFmt,const Point& rNdTopLeft); + /// Writes shape in both DML and VML format. + void writeDMLAndVMLDrawing(const SdrObject* sdrObj, const SwFrmFmt& rFrmFmt,const Point& rNdTopLeft, int nAnchorId); + /// Writes a diagram (smartart). + void writeDiagram(const SdrObject* sdrObject, const Size& size); +}; + +#endif // INCLUDED_SW_SOURCE_FILTER_WW8_DOCXSDREXPORT_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */