[Libreoffice-commits] core.git: sw/Library_msword.mk sw/source

Miklos Vajna vmiklos at collabora.co.uk
Fri Dec 13 08:45:19 PST 2013


 sw/Library_msword.mk                         |    1 
 sw/source/filter/ww8/docxattributeoutput.cxx |  514 -------------------------
 sw/source/filter/ww8/docxattributeoutput.hxx |    9 
 sw/source/filter/ww8/docxexport.cxx          |   15 
 sw/source/filter/ww8/docxexport.hxx          |    7 
 sw/source/filter/ww8/docxsdrexport.cxx       |  552 +++++++++++++++++++++++++++
 sw/source/filter/ww8/docxsdrexport.hxx       |   54 ++
 7 files changed, 639 insertions(+), 513 deletions(-)

New commits:
commit 984c3b733fe3b118f6e4b855fa8a6396fe194f8e
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date:   Fri Dec 13 15:53:33 2013 +0100

    Factor out DocxSdrExport from DocxAttributeOutput
    
    DocxAttributeOutput is getting huge, and the drawing-related
    functionality is an obvious subset the can be separated from the rest of
    the calls. Move most of that into the new DocxSdrExport.
    
    Change-Id: I6e5c750e2bef07730c97fd018f042883721ac410

diff --git a/sw/Library_msword.mk b/sw/Library_msword.mk
index 069795b..336f267 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 2d938b5..a486305 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 <oox/mathml/export.hxx>
 #include <oox/drawingml/drawingmltypes.hxx>
 
-#include <i18nlangtag/languagetag.hxx>
-
 #include <editeng/autokernitem.hxx>
 #include <editeng/unoprnms.hxx>
 #include <editeng/fontitem.hxx>
@@ -72,26 +71,19 @@
 #include <editeng/frmdiritem.hxx>
 #include <editeng/blinkitem.hxx>
 #include <editeng/charhiddenitem.hxx>
-#include <editeng/opaqitem.hxx>
 #include <editeng/editobj.hxx>
-#include <svx/svdmodel.hxx>
-#include <svx/svdobj.hxx>
-#include <svx/svdogrp.hxx>
 #include <svx/xfillit0.hxx>
 #include <svx/xflgrit.hxx>
 #include <svl/grabbagitem.hxx>
 #include <sfx2/sfxbasemodel.hxx>
 #include <tools/datetimeutils.hxx>
 
-#include <anchoredobject.hxx>
 #include <docufld.hxx>
 #include <flddropdown.hxx>
-#include <fmtanchr.hxx>
 #include <fmtclds.hxx>
 #include <fmtinfmt.hxx>
 #include <fmtrowsplt.hxx>
 #include <fmtline.hxx>
-#include <frmatr.hxx>
 #include <ftninfo.hxx>
 #include <htmltbl.hxx>
 #include <lineinfo.hxx>
@@ -109,19 +101,12 @@
 #include <docsh.hxx>
 
 #include <osl/file.hxx>
-#include <rtl/tencinfo.h>
 #include <vcl/embeddedfontshelper.hxx>
 #include <svtools/miscopt.hxx>
 
 #include <com/sun/star/i18n/ScriptType.hpp>
 #include <com/sun/star/chart2/XChartDocument.hpp>
 #include <com/sun/star/drawing/ShadingPattern.hpp>
-#include <com/sun/star/xml/dom/XDocument.hpp>
-#include <com/sun/star/xml/dom/XNode.hpp>
-#include <com/sun/star/xml/dom/XNamedNodeMap.hpp>
-#include <com/sun/star/xml/dom/XAttr.hpp>
-#include <com/sun/star/xml/sax/Writer.hpp>
-#include <com/sun/star/xml/sax/XSAXSerializable.hpp>
 #include <com/sun/star/text/GraphicCrop.hpp>
 
 #include <algorithm>
@@ -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<drawing::XShape> xShape(const_cast<SdrObject*>(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<xml::dom::XDocument> dataDom;
-    uno::Reference<xml::dom::XDocument> layoutDom;
-    uno::Reference<xml::dom::XDocument> styleDom;
-    uno::Reference<xml::dom::XDocument> colorDom;
-    uno::Reference<xml::dom::XDocument> 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 3ef815a..18fd11e 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 2409e42..051d841 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 <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
 #include <com/sun/star/document/XDocumentProperties.hpp>
@@ -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<const SvxBrushItem*> DocxExport::getBackground()
 {
     boost::optional<const SvxBrushItem*> 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 5dd9e04..10f2f8d 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 0000000..57affcf
--- /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 <com/sun/star/drawing/XShape.hpp>
+#include <com/sun/star/xml/dom/XDocument.hpp>
+#include <com/sun/star/xml/sax/XSAXSerializable.hpp>
+#include <com/sun/star/xml/sax/Writer.hpp>
+#include <editeng/lrspitem.hxx>
+#include <editeng/ulspitem.hxx>
+#include <editeng/opaqitem.hxx>
+#include <editeng/shaditem.hxx>
+#include <editeng/unoprnms.hxx>
+#include <svx/svdobj.hxx>
+#include <svx/svdmodel.hxx>
+#include <svx/svdogrp.hxx>
+#include <oox/token/tokens.hxx>
+#include <oox/export/drawingml.hxx>
+#include <oox/export/utils.hxx>
+#include <oox/export/vmlexport.hxx>
+
+#include <frmatr.hxx>
+#include <frmfmt.hxx>
+#include <fmtanchr.hxx>
+#include <fmtornt.hxx>
+#include <fmtsrnd.hxx>
+
+#include <docxsdrexport.hxx>
+#include <docxexport.hxx>
+#include <docxexportfilter.hxx>
+
+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<drawing::XShape> xShape(const_cast<SdrObject*>(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<xml::dom::XDocument> dataDom;
+    uno::Reference<xml::dom::XDocument> layoutDom;
+    uno::Reference<xml::dom::XDocument> styleDom;
+    uno::Reference<xml::dom::XDocument> colorDom;
+    uno::Reference<xml::dom::XDocument> 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 0000000..02e0c52
--- /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 <boost/shared_ptr.hpp>
+#include <sax/fshelper.hxx>
+
+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<Impl> 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: */


More information about the Libreoffice-commits mailing list