PPTX export: save SmartArt as diagram instead of group of shapes

preserving SmartArt allows editing it in PowerPoint after saving as pptx file

* moved common parts for docx and pptx export to oox/drawingml
* fixed export tests that expected shapes on output

Change-Id: I3e70a9f4177bebf5e1671232f4cd0ef0e7212626
Reviewed-on: https://gerrit.libreoffice.org/69598
Tested-by: Jenkins
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
diff --git a/include/oox/export/drawingml.hxx b/include/oox/export/drawingml.hxx
index fbcc25f..b3cdbb3 100644
--- a/include/oox/export/drawingml.hxx
+++ b/include/oox/export/drawingml.hxx
@@ -258,7 +258,12 @@ public:
    void WriteShape3DEffects( const css::uno::Reference< css::beans::XPropertySet >& rXPropSet );
    void WriteArtisticEffect( const css::uno::Reference< css::beans::XPropertySet >& rXPropSet );
    OString WriteWdpPicture( const OUString& rFileId, const css::uno::Sequence< sal_Int8 >& rPictureData );
    void WriteDiagram(const css::uno::Reference<css::drawing::XShape>& rXShape, int nDiagramId);
    void writeDiagramRels(const css::uno::Sequence<css::uno::Sequence<css::uno::Any>>& xRelSeq,
                          const css::uno::Reference<css::io::XOutputStream>& xOutStream,
                          const OUString& sGrabBagProperyName, int nDiagramId);
    static bool IsGroupShape( const css::uno::Reference< css::drawing::XShape >& rXShape );
    static bool IsDiagram(const css::uno::Reference<css::drawing::XShape>& rXShape);
    sal_Int32 getBulletMarginIndentation (const css::uno::Reference< css::beans::XPropertySet >& rXPropSet,sal_Int16 nLevel, const OUString& propName);

    static void ResetCounters();
diff --git a/oox/source/export/drawingml.cxx b/oox/source/export/drawingml.cxx
index b5047b8..1cebeaa 100644
--- a/oox/source/export/drawingml.cxx
+++ b/oox/source/export/drawingml.cxx
@@ -25,10 +25,12 @@
#include <oox/core/xmlfilterbase.hxx>
#include <oox/export/drawingml.hxx>
#include <oox/export/utils.hxx>
#include <oox/helper/propertyset.hxx>
#include <oox/drawingml/color.hxx>
#include <drawingml/fillproperties.hxx>
#include <drawingml/textparagraph.hxx>
#include <oox/token/namespaces.hxx>
#include <oox/token/properties.hxx>
#include <oox/token/relationship.hxx>
#include <oox/token/tokens.hxx>
#include <oox/drawingml/drawingmltypes.hxx>
@@ -80,7 +82,13 @@
#include <com/sun/star/text/XTextField.hpp>
#include <com/sun/star/text/XTextRange.hpp>
#include <com/sun/star/style/CaseMap.hpp>
#include <com/sun/star/xml/dom/XNodeList.hpp>
#include <com/sun/star/xml/sax/Writer.hpp>
#include <com/sun/star/xml/sax/XSAXSerializable.hpp>

#include <comphelper/processfactory.hxx>
#include <comphelper/random.hxx>
#include <comphelper/seqstream.hxx>
#include <comphelper/storagehelper.hxx>
#include <comphelper/xmltools.hxx>
#include <o3tl/any.hxx>
@@ -99,6 +107,7 @@
#include <editeng/outlobj.hxx>
#include <editeng/svxenum.hxx>
#include <editeng/unonames.hxx>
#include <editeng/unoprnms.hxx>
#include <editeng/flditem.hxx>
#include <svx/sdtfsitm.hxx>
#include <svx/svdoashp.hxx>
@@ -2268,6 +2277,31 @@ bool DrawingML::IsGroupShape( const Reference< XShape >& rXShape )
    return bRet;
}

bool DrawingML::IsDiagram(const Reference<XShape>& rXShape)
{
    uno::Reference<beans::XPropertySet> xPropSet(rXShape, uno::UNO_QUERY);
    if (!xPropSet.is())
        return false;

    // if the shape doesn't have the InteropGrabBag property, it's not a diagram
    uno::Reference<beans::XPropertySetInfo> xPropSetInfo = xPropSet->getPropertySetInfo();
    OUString aName = UNO_NAME_MISC_OBJ_INTEROPGRABBAG;
    if (!xPropSetInfo->hasPropertyByName(aName))
        return false;

    uno::Sequence<beans::PropertyValue> propList;
    xPropSet->getPropertyValue(aName) >>= propList;
    for (sal_Int32 nProp = 0; nProp < propList.getLength(); ++nProp)
    {
        // if we find any of the diagram components, it's a diagram
        OUString propName = propList[nProp].Name;
        if (propName == "OOXData" || propName == "OOXLayout" || propName == "OOXStyle"
            || propName == "OOXColor" || propName == "OOXDrawing")
            return true;
    }
    return false;
}

sal_Int32 DrawingML::getBulletMarginIndentation (const Reference< XPropertySet >& rXPropSet,sal_Int16 nLevel, const OUString& propName)
{
    if (nLevel < 0 || !GetProperty(rXPropSet, "NumberingRules"))
@@ -3984,6 +4018,292 @@ OString DrawingML::WriteWdpPicture( const OUString& rFileId, const Sequence< sal
    return OUStringToOString( sId, RTL_TEXTENCODING_UTF8 );
}

void DrawingML::WriteDiagram(const css::uno::Reference<css::drawing::XShape>& rXShape, int nDiagramId)
{
    uno::Reference<beans::XPropertySet> xPropSet(rXShape, 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;
    uno::Sequence<uno::Sequence<uno::Any>> xDataRelSeq;
    uno::Sequence<uno::Any> diagramDrawing;

    // retrieve the doms from the GrabBag
    uno::Sequence<beans::PropertyValue> propList;
    xPropSet->getPropertyValue(UNO_NAME_MISC_OBJ_INTEROPGRABBAG) >>= 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 >>= diagramDrawing;
            diagramDrawing[0]
                >>= drawingDom; // if there is OOXDrawing property then set drawingDom here only.
        }
        else if (propName == "OOXDiagramDataRels")
            propList[nProp].Value >>= xDataRelSeq;
    }

    // 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;

    // generate an unique id
    sax_fastparser::FastAttributeList* pDocPrAttrList
        = sax_fastparser::FastSerializerHelper::createAttrList();
    pDocPrAttrList->add(XML_id, OString::number(nDiagramId).getStr());
    OUString sName = "Diagram" + OUString::number(nDiagramId);
    pDocPrAttrList->add(XML_name, OUStringToOString(sName, RTL_TEXTENCODING_UTF8).getStr());
    sax_fastparser::XFastAttributeListRef xDocPrAttrListRef(pDocPrAttrList);

    if (GetDocumentType() == DOCUMENT_DOCX)
    {
        mpFS->singleElementNS(XML_wp, XML_docPr, xDocPrAttrListRef);
        mpFS->singleElementNS(XML_wp, XML_cNvGraphicFramePr, FSEND);

        mpFS->startElementNS(
            XML_a, XML_graphic, FSNS(XML_xmlns, XML_a),
            OUStringToOString(mpFB->getNamespaceURL(OOX_NS(dml)), RTL_TEXTENCODING_UTF8).getStr(),
            FSEND);
    }
    else
    {
        mpFS->startElementNS(XML_p, XML_nvGraphicFramePr, FSEND);

        mpFS->singleElementNS(XML_p, XML_cNvPr, xDocPrAttrListRef);
        mpFS->singleElementNS(XML_p, XML_cNvGraphicFramePr, FSEND);

        mpFS->startElementNS(XML_p, XML_nvPr, FSEND);
        mpFS->startElementNS(XML_p, XML_extLst, FSEND);
        // change tracking extension - required in PPTX
        mpFS->startElementNS(XML_p, XML_ext, XML_uri, "{D42A27DB-BD31-4B8C-83A1-F6EECF244321}",
                             FSEND);
        mpFS->singleElementNS(
            XML_p14, XML_modId, FSNS(XML_xmlns, XML_p14),
            OUStringToOString(mpFB->getNamespaceURL(OOX_NS(p14)), RTL_TEXTENCODING_UTF8).getStr(),
            XML_val,
            OString::number(comphelper::rng::uniform_uint_distribution(1, SAL_MAX_UINT32)).getStr(),
            FSEND);
        mpFS->endElementNS(XML_p, XML_ext);
        mpFS->endElementNS(XML_p, XML_extLst);
        mpFS->endElementNS(XML_p, XML_nvPr);

        mpFS->endElementNS(XML_p, XML_nvGraphicFramePr);

        awt::Point aPos = rXShape->getPosition();
        awt::Size aSize = rXShape->getSize();
        WriteTransformation(tools::Rectangle(Point(aPos.X, aPos.Y), Size(aSize.Width, aSize.Height)),
            XML_p, false, false, 0, false);

        mpFS->startElementNS(XML_a, XML_graphic, FSEND);
    }

    mpFS->startElementNS(XML_a, XML_graphicData, XML_uri,
                         "http://schemas.openxmlformats.org/drawingml/2006/diagram", FSEND);

    OUString sRelationCompPrefix = OUString::createFromAscii(GetRelationCompPrefix());

    // add data relation
    OUString dataFileName = "diagrams/data" + OUString::number(nDiagramId) + ".xml";
    OString dataRelId = OUStringToOString(
        mpFB->addRelation(mpFS->getOutputStream(), oox::getRelationship(Relationship::DIAGRAMDATA),
                          sRelationCompPrefix + dataFileName),
        RTL_TEXTENCODING_UTF8);

    // add layout relation
    OUString layoutFileName = "diagrams/layout" + OUString::number(nDiagramId) + ".xml";
    OString layoutRelId
        = OUStringToOString(mpFB->addRelation(mpFS->getOutputStream(),
                                              oox::getRelationship(Relationship::DIAGRAMLAYOUT),
                                              sRelationCompPrefix + layoutFileName),
                            RTL_TEXTENCODING_UTF8);

    // add style relation
    OUString styleFileName = "diagrams/quickStyle" + OUString::number(nDiagramId) + ".xml";
    OString styleRelId
        = OUStringToOString(mpFB->addRelation(mpFS->getOutputStream(),
                                              oox::getRelationship(Relationship::DIAGRAMQUICKSTYLE),
                                              sRelationCompPrefix + styleFileName),
                            RTL_TEXTENCODING_UTF8);

    // add color relation
    OUString colorFileName = "diagrams/colors" + OUString::number(nDiagramId) + ".xml";
    OString colorRelId
        = OUStringToOString(mpFB->addRelation(mpFS->getOutputStream(),
                                              oox::getRelationship(Relationship::DIAGRAMCOLORS),
                                              sRelationCompPrefix + colorFileName),
                            RTL_TEXTENCODING_UTF8);

    OUString drawingFileName;
    if (drawingDom.is())
    {
        // add drawing relation
        drawingFileName = "diagrams/drawing" + OUString::number(nDiagramId) + ".xml";
        OUString drawingRelId = mpFB->addRelation(
            mpFS->getOutputStream(), oox::getRelationship(Relationship::DIAGRAMDRAWING),
            sRelationCompPrefix + drawingFileName);

        // 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);
    }

    mpFS->singleElementNS(
        XML_dgm, XML_relIds, FSNS(XML_xmlns, XML_dgm),
        OUStringToOString(mpFB->getNamespaceURL(OOX_NS(dmlDiagram)), RTL_TEXTENCODING_UTF8)
            .getStr(),
        FSNS(XML_xmlns, XML_r),
        OUStringToOString(mpFB->getNamespaceURL(OOX_NS(officeRel)), RTL_TEXTENCODING_UTF8).getStr(),
        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);

    mpFS->endElementNS(XML_a, XML_graphicData);
    mpFS->endElementNS(XML_a, XML_graphic);

    uno::Reference<xml::sax::XSAXSerializable> serializer;
    uno::Reference<xml::sax::XWriter> writer
        = xml::sax::Writer::create(comphelper::getProcessComponentContext());

    OUString sDir = OUString::createFromAscii(GetComponentDir());

    // write data file
    serializer.set(dataDom, uno::UNO_QUERY);
    uno::Reference<io::XOutputStream> xDataOutputStream = mpFB->openFragmentStream(
        sDir + "/" + dataFileName,
        "application/vnd.openxmlformats-officedocument.drawingml.diagramData+xml");
    writer->setOutputStream(xDataOutputStream);
    serializer->serialize(uno::Reference<xml::sax::XDocumentHandler>(writer, uno::UNO_QUERY_THROW),
                          uno::Sequence<beans::StringPair>());

    // write the associated Images and rels for data file
    writeDiagramRels(xDataRelSeq, xDataOutputStream, "OOXDiagramDataRels", nDiagramId);

    // write layout file
    serializer.set(layoutDom, uno::UNO_QUERY);
    writer->setOutputStream(mpFB->openFragmentStream(
        sDir + "/" + 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(mpFB->openFragmentStream(
        sDir + "/" + 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(mpFB->openFragmentStream(
        sDir + "/" + 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);
        uno::Reference<io::XOutputStream> xDrawingOutputStream = mpFB->openFragmentStream(
            sDir + "/" + drawingFileName, "application/vnd.ms-office.drawingml.diagramDrawing+xml");
        writer->setOutputStream(xDrawingOutputStream);
        serializer->serialize(
            uno::Reference<xml::sax::XDocumentHandler>(writer, uno::UNO_QUERY_THROW),
            uno::Sequence<beans::StringPair>());

        // write the associated Images and rels for drawing file
        uno::Sequence<uno::Sequence<uno::Any>> xDrawingRelSeq;
        diagramDrawing[1] >>= xDrawingRelSeq;
        writeDiagramRels(xDrawingRelSeq, xDrawingOutputStream, "OOXDiagramDrawingRels", nDiagramId);
    }
}

void DrawingML::writeDiagramRels(const uno::Sequence<uno::Sequence<uno::Any>>& xRelSeq,
                                 const uno::Reference<io::XOutputStream>& xOutStream,
                                 const OUString& sGrabBagProperyName, int nDiagramId)
{
    // add image relationships of OOXData, OOXDiagram
    OUString sType(oox::getRelationship(Relationship::IMAGE));
    uno::Reference<xml::sax::XWriter> xWriter
        = xml::sax::Writer::create(comphelper::getProcessComponentContext());
    xWriter->setOutputStream(xOutStream);

    // retrieve the relationships from Sequence
    for (sal_Int32 j = 0; j < xRelSeq.getLength(); j++)
    {
        // diagramDataRelTuple[0] => RID,
        // diagramDataRelTuple[1] => xInputStream
        // diagramDataRelTuple[2] => extension
        uno::Sequence<uno::Any> diagramDataRelTuple = xRelSeq[j];

        OUString sRelId;
        OUString sExtension;
        diagramDataRelTuple[0] >>= sRelId;
        diagramDataRelTuple[2] >>= sExtension;
        OUString sContentType;
        if (sExtension.equalsIgnoreAsciiCase(".WMF"))
            sContentType = "image/x-wmf";
        else
            sContentType = "image/" + sExtension.copy(1);
        sRelId = sRelId.copy(3);

        StreamDataSequence dataSeq;
        diagramDataRelTuple[1] >>= dataSeq;
        uno::Reference<io::XInputStream> dataImagebin(
            new ::comphelper::SequenceInputStream(dataSeq));

        //nDiagramId is used to make the name unique irrespective of the number of smart arts.
        OUString sFragment = "media/" + sGrabBagProperyName + OUString::number(nDiagramId) + "_"
                             + OUString::number(j) + sExtension;

        PropertySet aProps(xOutStream);
        aProps.setAnyProperty(PROP_RelId, uno::makeAny(sRelId.toInt32()));

        mpFB->addRelation(xOutStream, sType, "../" + sFragment);

        OUString sDir = OUString::createFromAscii(GetComponentDir());
        uno::Reference<io::XOutputStream> xBinOutStream
            = mpFB->openFragmentStream(sDir + "/" + sFragment, sContentType);

        try
        {
            comphelper::OStorageHelper::CopyInputToOutput(dataImagebin, xBinOutStream);
        }
        catch (const uno::Exception& rException)
        {
            SAL_WARN("oox.drawingml", "DrawingML::writeDiagramRels Failed to copy grabbaged Image: "
                     << rException);
        }
        dataImagebin->closeInput();
    }
}

}
}

diff --git a/oox/source/token/tokens.txt b/oox/source/token/tokens.txt
index 653050e..3929d8c 100644
--- a/oox/source/token/tokens.txt
+++ b/oox/source/token/tokens.txt
@@ -3431,6 +3431,7 @@ miter
miterlimit
moccasin
mod
modId
modelId
modern
modified
diff --git a/sd/qa/unit/data/pptx/group.pptx b/sd/qa/unit/data/pptx/group.pptx
index 8895fe2a..f0b739e 100644
--- a/sd/qa/unit/data/pptx/group.pptx
+++ b/sd/qa/unit/data/pptx/group.pptx
Binary files differ
diff --git a/sd/qa/unit/data/pptx/smartart-preserve.pptx b/sd/qa/unit/data/pptx/smartart-preserve.pptx
new file mode 100644
index 0000000..6108a8c
--- /dev/null
+++ b/sd/qa/unit/data/pptx/smartart-preserve.pptx
Binary files differ
diff --git a/sd/qa/unit/export-tests-ooxml2.cxx b/sd/qa/unit/export-tests-ooxml2.cxx
index 06330de..9192956 100644
--- a/sd/qa/unit/export-tests-ooxml2.cxx
+++ b/sd/qa/unit/export-tests-ooxml2.cxx
@@ -199,6 +199,7 @@ public:
    void testTdf99213();
    void testPotxExport();
    void testTdf44223();
    void testSmartArtPreserve();

    CPPUNIT_TEST_SUITE(SdOOXMLExportTest2);

@@ -280,6 +281,7 @@ public:
    CPPUNIT_TEST(testTdf99213);
    CPPUNIT_TEST(testPotxExport);
    CPPUNIT_TEST(testTdf44223);
    CPPUNIT_TEST(testSmartArtPreserve);

    CPPUNIT_TEST_SUITE_END();

@@ -304,6 +306,7 @@ public:
            { "a14", "http://schemas.microsoft.com/office/drawing/2010/main" },
            { "wps", "http://schemas.microsoft.com/office/word/2010/wordprocessingShape" },
            { "wpg", "http://schemas.microsoft.com/office/word/2010/wordprocessingGroup" },
            { "dgm", "http://schemas.openxmlformats.org/drawingml/2006/diagram" },
        };
        for (size_t i = 0; i < SAL_N_ELEMENTS(namespaces); ++i)
        {
@@ -1360,6 +1363,12 @@ void SdOOXMLExportTest2::testTdf104788()
void SdOOXMLExportTest2::testSmartartRotation2()
{
    ::sd::DrawDocShellRef xDocShRef = loadURL(m_directories.getURLFromSrc("sd/qa/unit/data/pptx/smartart-rotation2.pptx"), PPTX);

    // clear SmartArt data to check how group shapes with double-rotated children are exported, not smartart
    uno::Reference<beans::XPropertySet> xShape(getShapeFromPage(0, 0, xDocShRef));
    uno::Sequence<beans::PropertyValue> aInteropGrabBag;
    xShape->setPropertyValue("InteropGrabBag", uno::makeAny(aInteropGrabBag));

    utl::TempFile tempFile;
    xDocShRef = saveAndReload(xDocShRef.get(), PPTX, &tempFile);
    xDocShRef->DoClose();
@@ -1413,10 +1422,10 @@ void SdOOXMLExportTest2::testGroupsPosition()
    xDocShRef->DoClose();

    xmlDocPtr pXmlDocContent = parseExport(tempFile, "ppt/slides/slide1.xml");
    assertXPath(pXmlDocContent, "/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:sp[1]/p:spPr/a:xfrm/a:off", "x", "4040640");
    assertXPath(pXmlDocContent, "/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:sp[1]/p:spPr/a:xfrm/a:off", "y", "4273920");
    assertXPath(pXmlDocContent, "/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:sp[3]/p:spPr/a:xfrm/a:off", "x", "6796800");
    assertXPath(pXmlDocContent, "/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:sp[3]/p:spPr/a:xfrm/a:off", "y", "4273920");
    assertXPath(pXmlDocContent, "/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:sp[1]/p:spPr/a:xfrm/a:off", "x", "5004000");
    assertXPath(pXmlDocContent, "/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:sp[1]/p:spPr/a:xfrm/a:off", "y", "3310560");
    assertXPath(pXmlDocContent, "/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:sp[3]/p:spPr/a:xfrm/a:off", "x", "7760160");
    assertXPath(pXmlDocContent, "/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:sp[3]/p:spPr/a:xfrm/a:off", "y", "3310560");
}

void SdOOXMLExportTest2::testGroupsRotatedPosition()
@@ -2105,6 +2114,51 @@ void SdOOXMLExportTest2::testTdf44223()
    xDocShRef->DoClose();
}

void SdOOXMLExportTest2::testSmartArtPreserve()
{
    ::sd::DrawDocShellRef xDocShRef
        = loadURL(m_directories.getURLFromSrc("sd/qa/unit/data/pptx/smartart-preserve.pptx"), PPTX);
    utl::TempFile tempFile;
    xDocShRef = saveAndReload(xDocShRef.get(), PPTX, &tempFile);

    xmlDocPtr pXmlDoc = parseExport(tempFile, "ppt/slides/slide1.xml");
    assertXPath(pXmlDoc, "//p:sld/p:cSld/p:spTree/p:graphicFrame/p:nvGraphicFramePr/p:cNvPr");
    assertXPath(pXmlDoc, "//p:sld/p:cSld/p:spTree/p:graphicFrame/a:graphic/a:graphicData/dgm:relIds");
    assertXPath(pXmlDoc, "//p:sld/p:cSld/p:spTree/p:graphicFrame/p:nvGraphicFramePr/p:nvPr/p:extLst/p:ext",
                "uri", "{D42A27DB-BD31-4B8C-83A1-F6EECF244321}");
    assertXPath(pXmlDoc, "//p:sld/p:cSld/p:spTree/p:graphicFrame/p:nvGraphicFramePr/p:nvPr/p:extLst/p:ext/p14:modId");

    xmlDocPtr pXmlDocRels = parseExport(tempFile, "ppt/slides/_rels/slide1.xml.rels");
    assertXPath(pXmlDocRels,
                "(/rels:Relationships/rels:Relationship[@Target='../diagrams/layout1.xml'])[1]", "Type",
                "http://schemas.openxmlformats.org/officeDocument/2006/relationships/diagramLayout");
    assertXPath(pXmlDocRels,
                "(/rels:Relationships/rels:Relationship[@Target='../diagrams/data1.xml'])[1]", "Type",
                "http://schemas.openxmlformats.org/officeDocument/2006/relationships/diagramData");
    assertXPath(pXmlDocRels,
                "(/rels:Relationships/rels:Relationship[@Target='../diagrams/colors1.xml'])[1]", "Type",
                "http://schemas.openxmlformats.org/officeDocument/2006/relationships/diagramColors");
    assertXPath(pXmlDocRels,
                "(/rels:Relationships/rels:Relationship[@Target='../diagrams/quickStyle1.xml'])[1]", "Type",
                "http://schemas.openxmlformats.org/officeDocument/2006/relationships/diagramQuickStyle");

    xmlDocPtr pXmlContentType = parseExport(tempFile, "[Content_Types].xml");
    assertXPath(pXmlContentType,
                "/ContentType:Types/ContentType:Override[@PartName='/ppt/diagrams/layout1.xml']",
                "ContentType", "application/vnd.openxmlformats-officedocument.drawingml.diagramLayout+xml");
    assertXPath(pXmlContentType,
                "/ContentType:Types/ContentType:Override[@PartName='/ppt/diagrams/data1.xml']",
                "ContentType", "application/vnd.openxmlformats-officedocument.drawingml.diagramData+xml");
    assertXPath(pXmlContentType,
                "/ContentType:Types/ContentType:Override[@PartName='/ppt/diagrams/colors1.xml']",
                "ContentType", "application/vnd.openxmlformats-officedocument.drawingml.diagramColors+xml");
    assertXPath(pXmlContentType,
                "/ContentType:Types/ContentType:Override[@PartName='/ppt/diagrams/quickStyle1.xml']",
                "ContentType", "application/vnd.openxmlformats-officedocument.drawingml.diagramStyle+xml");

    xDocShRef->DoClose();
}

CPPUNIT_TEST_SUITE_REGISTRATION(SdOOXMLExportTest2);

CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/sd/source/filter/eppt/epptooxml.hxx b/sd/source/filter/eppt/epptooxml.hxx
index 5791c02..02b96de 100644
--- a/sd/source/filter/eppt/epptooxml.hxx
+++ b/sd/source/filter/eppt/epptooxml.hxx
@@ -50,6 +50,8 @@ enum PlaceholderType
    Subtitle
};

class PowerPointShapeExport;

class PowerPointExport final : public XmlFilterBase, public PPTWriterBase
{
    friend class PowerPointShapeExport;
@@ -115,6 +117,8 @@ private:

    virtual OUString SAL_CALL getImplementationName() override;

    static void WriteDiagram(const FSHelperPtr& pFS, PowerPointShapeExport& rDML, const css::uno::Reference<css::drawing::XShape>& rXShape, int nDiagramId);

    /// Should we export as .pptm, ie. do we contain macros?
    bool mbPptm;

@@ -131,6 +135,8 @@ private:
    sal_uInt32 mnSlideMasterIdMax;
    sal_uInt32 mnAnimationNodeIdMax;

    sal_uInt32 mnDiagramId;

    bool mbCreateNotes;

    ::oox::drawingml::ShapeExport::ShapeHashMap maShapeMap;
diff --git a/sd/source/filter/eppt/pptx-epptooxml.cxx b/sd/source/filter/eppt/pptx-epptooxml.cxx
index 0ac1ca4..cdc452b 100644
--- a/sd/source/filter/eppt/pptx-epptooxml.cxx
+++ b/sd/source/filter/eppt/pptx-epptooxml.cxx
@@ -333,6 +333,7 @@ PowerPointExport::PowerPointExport(const Reference< XComponentContext >& rContex
    , mnSlideIdMax(1 << 8)
    , mnSlideMasterIdMax(1U << 31)
    , mnAnimationNodeIdMax(1)
    , mnDiagramId(1)
    , mbCreateNotes(false)
{
    comphelper::SequenceAsHashMap aArgumentsMap(rArguments);
@@ -1434,7 +1435,10 @@ void PowerPointExport::WriteShapeTree(const FSHelperPtr& pFS, PageType ePageType
        if (GetShapeByIndex(GetCurrentGroupIndex(), true))
        {
            SAL_INFO("sd.eppt", "mType: " << mType);
            aDML.WriteShape(mXShape);
            if (DrawingML::IsDiagram(mXShape))
                WriteDiagram(pFS, aDML, mXShape, mnDiagramId++);
            else
                aDML.WriteShape(mXShape);
        }
    }

@@ -2031,6 +2035,14 @@ OUString PowerPointExport::getImplementationName()
    return OUString("com.sun.star.comp.Impress.oox.PowerPointExport");
}

void PowerPointExport::WriteDiagram(const FSHelperPtr& pFS, PowerPointShapeExport& rDML, const css::uno::Reference<css::drawing::XShape>& rXShape, int nDiagramId)
{
    SAL_INFO("sd.eppt", "writing Diagram " + OUString::number(nDiagramId));
    pFS->startElementNS(XML_p, XML_graphicFrame, FSEND);
    rDML.WriteDiagram(rXShape, nDiagramId);
    pFS->endElementNS(XML_p, XML_graphicFrame);
}

// UNO component
extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
css_comp_Impress_oox_PowerPointExport(uno::XComponentContext* rxCtxt,
diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx
index f1c56fa..7e621fa 100644
--- a/sw/source/filter/ww8/docxattributeoutput.cxx
+++ b/sw/source/filter/ww8/docxattributeoutput.cxx
@@ -5677,7 +5677,10 @@ void DocxAttributeOutput::OutputFlyFrame_Impl( const ww8::Frame &rFrame, const P
                const SdrObject* pSdrObj = rFrame.GetFrameFormat().FindRealSdrObject();
                if ( pSdrObj )
                {
                    if ( IsDiagram( pSdrObj ) )
                    uno::Reference<drawing::XShape> xShape(
                        const_cast<SdrObject*>(pSdrObj)->getUnoShape(), uno::UNO_QUERY);

                    if (xShape.is() && oox::drawingml::DrawingML::IsDiagram(xShape))
                    {
                        if ( !m_pPostponedDiagrams )
                        {
@@ -5786,35 +5789,6 @@ void DocxAttributeOutput::OutputFlyFrame_Impl( const ww8::Frame &rFrame, const P
    m_pSerializer->mergeTopMarks(Tag_OutputFlyFrame, sax_fastparser::MergeMarks::POSTPONE);
}

bool DocxAttributeOutput::IsDiagram( const SdrObject* sdrObject )
{
    uno::Reference< drawing::XShape > xShape( const_cast<SdrObject*>(sdrObject)->getUnoShape(), uno::UNO_QUERY );
    if ( !xShape.is() )
        return false;

    uno::Reference< beans::XPropertySet > xPropSet( xShape, uno::UNO_QUERY );
    if ( !xPropSet.is() )
        return false;

    // if the shape doesn't have the InteropGrabBag property, it's not a diagram
    uno::Reference< beans::XPropertySetInfo > xPropSetInfo = xPropSet->getPropertySetInfo();
    OUString aName = UNO_NAME_MISC_OBJ_INTEROPGRABBAG;
    if ( !xPropSetInfo->hasPropertyByName( aName ) )
        return false;

    uno::Sequence< beans::PropertyValue > propList;
    xPropSet->getPropertyValue( aName ) >>= propList;
    for ( sal_Int32 nProp=0; nProp < propList.getLength(); ++nProp )
    {
        // if we find any of the diagram components, it's a diagram
        OUString propName = propList[nProp].Name;
        if ( propName == "OOXData" || propName == "OOXLayout" || propName == "OOXStyle" ||
             propName == "OOXColor" || propName == "OOXDrawing")
            return true;
    }
    return false;
}

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 4ed30cc..2ea64b8 100644
--- a/sw/source/filter/ww8/docxattributeoutput.hxx
+++ b/sw/source/filter/ww8/docxattributeoutput.hxx
@@ -400,9 +400,6 @@ private:
    void WriteActiveXControl(const SdrObject* pObject, const SwFrameFormat& rFrameFormat, bool bInsideRun);
    bool ExportAsActiveXControl(const SdrObject* pObject) const;

    /// checks whether the current component is a diagram
    static bool IsDiagram (const SdrObject* sdrObject);

    void InitTableHelper( ww8::WW8TableNodeInfoInner::Pointer_t const & pTableTextNodeInfoInner );
    void StartTable( ww8::WW8TableNodeInfoInner::Pointer_t const & pTableTextNodeInfoInner );
    void StartTableRow( ww8::WW8TableNodeInfoInner::Pointer_t const & pTableTextNodeInfoInner );
diff --git a/sw/source/filter/ww8/docxsdrexport.cxx b/sw/source/filter/ww8/docxsdrexport.cxx
index 5f5cfe9..d28c3c9 100644
--- a/sw/source/filter/ww8/docxsdrexport.cxx
+++ b/sw/source/filter/ww8/docxsdrexport.cxx
@@ -1125,290 +1125,19 @@ void DocxSdrExport::writeDMLEffectLst(const SwFrameFormat& rFrameFormat)
    m_pImpl->getSerializer()->endElementNS(XML_a, XML_effectLst);
}

void DocxSdrExport::writeDiagramRels(const uno::Sequence<uno::Sequence<uno::Any>>& xRelSeq,
                                     const uno::Reference<io::XOutputStream>& xOutStream,
                                     const OUString& sGrabBagProperyName, int nAnchorId)
{
    // add image relationships of OOXData, OOXDiagram
    OUString sType(oox::getRelationship(Relationship::IMAGE));
    uno::Reference<xml::sax::XWriter> xWriter
        = xml::sax::Writer::create(comphelper::getProcessComponentContext());
    xWriter->setOutputStream(xOutStream);

    // retrieve the relationships from Sequence
    for (sal_Int32 j = 0; j < xRelSeq.getLength(); j++)
    {
        // diagramDataRelTuple[0] => RID,
        // diagramDataRelTuple[1] => xInputStream
        // diagramDataRelTuple[2] => extension
        uno::Sequence<uno::Any> diagramDataRelTuple = xRelSeq[j];

        OUString sRelId;
        OUString sExtension;
        diagramDataRelTuple[0] >>= sRelId;
        diagramDataRelTuple[2] >>= sExtension;
        OUString sContentType;
        if (sExtension.equalsIgnoreAsciiCase(".WMF"))
            sContentType = "image/x-wmf";
        else
            sContentType = "image/" + sExtension.copy(1);
        sRelId = sRelId.copy(3);

        StreamDataSequence dataSeq;
        diagramDataRelTuple[1] >>= dataSeq;
        uno::Reference<io::XInputStream> dataImagebin(
            new ::comphelper::SequenceInputStream(dataSeq));

        OUString sFragment("../media/");
        //nAnchorId is used to make the name unique irrespective of the number of smart arts.
        sFragment += sGrabBagProperyName + OUString::number(nAnchorId) + "_" + OUString::number(j)
                     + sExtension;

        PropertySet aProps(xOutStream);
        aProps.setAnyProperty(PROP_RelId, uno::makeAny(sRelId.toInt32()));

        m_pImpl->getExport().GetFilter().addRelation(xOutStream, sType, sFragment);

        sFragment = sFragment.replaceFirst("..", "word");
        uno::Reference<io::XOutputStream> xBinOutStream
            = m_pImpl->getExport().GetFilter().openFragmentStream(sFragment, sContentType);

        try
        {
            sal_Int32 nBufferSize = 512;
            uno::Sequence<sal_Int8> aDataBuffer(nBufferSize);
            sal_Int32 nRead;
            do
            {
                nRead = dataImagebin->readBytes(aDataBuffer, nBufferSize);
                if (nRead)
                {
                    if (nRead < nBufferSize)
                    {
                        nBufferSize = nRead;
                        aDataBuffer.realloc(nRead);
                    }
                    xBinOutStream->writeBytes(aDataBuffer);
                }
            } while (nRead);
            xBinOutStream->flush();
        }
        catch (const uno::Exception& rException)
        {
            SAL_WARN("sw.ww8", "DocxSdrExport::writeDiagramRels Failed to copy grabbaged Image: "
                                   << rException);
        }
        dataImagebin->closeInput();
    }
}

void DocxSdrExport::writeDiagram(const SdrObject* sdrObject, const SwFrameFormat& rFrameFormat,
                                 int nAnchorId)
                                 int nDiagramId)
{
    sax_fastparser::FSHelperPtr pFS = m_pImpl->getSerializer();
    uno::Reference<drawing::XShape> xShape(const_cast<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;
    uno::Sequence<uno::Sequence<uno::Any>> xDataRelSeq;
    uno::Sequence<uno::Any> diagramDrawing;

    // retrieve the doms from the GrabBag
    uno::Sequence<beans::PropertyValue> propList;
    xPropSet->getPropertyValue(UNO_NAME_MISC_OBJ_INTEROPGRABBAG) >>= 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 >>= diagramDrawing;
            diagramDrawing[0]
                >>= drawingDom; // if there is OOXDrawing property then set drawingDom here only.
        }
        else if (propName == "OOXDiagramDataRels")
            propList[nProp].Value >>= xDataRelSeq;
    }

    // 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
    Size aSize(sdrObject->GetSnapRect().GetWidth(), sdrObject->GetSnapRect().GetHeight());
    startDMLAnchorInline(&rFrameFormat, aSize);

    // generate a unique id
    sax_fastparser::FastAttributeList* pDocPrAttrList
        = sax_fastparser::FastSerializerHelper::createAttrList();
    pDocPrAttrList->add(XML_id, OString::number(nAnchorId).getStr());
    OUString sName = "Diagram" + OUString::number(nAnchorId);
    pDocPrAttrList->add(XML_name, OUStringToOString(sName, RTL_TEXTENCODING_UTF8).getStr());
    sax_fastparser::XFastAttributeListRef xDocPrAttrListRef(pDocPrAttrList);
    pFS->singleElementNS(XML_wp, XML_docPr, xDocPrAttrListRef);
    m_pImpl->getDrawingML()->WriteDiagram(xShape, nDiagramId);

    sal_Int32 diagramCount;
    diagramCount = nAnchorId;

    pFS->singleElementNS(XML_wp, XML_cNvGraphicFramePr, FSEND);

    pFS->startElementNS(
        XML_a, XML_graphic, FSNS(XML_xmlns, XML_a),
        OUStringToOString(m_pImpl->getExport().GetFilter().getNamespaceURL(OOX_NS(dml)),
                          RTL_TEXTENCODING_UTF8)
            .getStr(),
        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->getExport().GetFilter().addRelation(
            pFS->getOutputStream(), oox::getRelationship(Relationship::DIAGRAMDATA), dataFileName),
        RTL_TEXTENCODING_UTF8);

    // add layout relation
    OUString layoutFileName = "diagrams/layout" + OUString::number(diagramCount) + ".xml";
    OString layoutRelId
        = OUStringToOString(m_pImpl->getExport().GetFilter().addRelation(
                                pFS->getOutputStream(),
                                oox::getRelationship(Relationship::DIAGRAMLAYOUT), layoutFileName),
                            RTL_TEXTENCODING_UTF8);

    // add style relation
    OUString styleFileName = "diagrams/quickStyle" + OUString::number(diagramCount) + ".xml";
    OString styleRelId = OUStringToOString(
        m_pImpl->getExport().GetFilter().addRelation(
            pFS->getOutputStream(), oox::getRelationship(Relationship::DIAGRAMQUICKSTYLE),
            styleFileName),
        RTL_TEXTENCODING_UTF8);

    // add color relation
    OUString colorFileName = "diagrams/colors" + OUString::number(diagramCount) + ".xml";
    OString colorRelId
        = OUStringToOString(m_pImpl->getExport().GetFilter().addRelation(
                                pFS->getOutputStream(),
                                oox::getRelationship(Relationship::DIAGRAMCOLORS), colorFileName),
                            RTL_TEXTENCODING_UTF8);

    OUString drawingFileName;
    if (drawingDom.is())
    {
        // add drawing relation
        drawingFileName = "diagrams/drawing" + OUString::number(diagramCount) + ".xml";
        OUString drawingRelId = m_pImpl->getExport().GetFilter().addRelation(
            pFS->getOutputStream(), oox::getRelationship(Relationship::DIAGRAMDRAWING),
            drawingFileName);

        // 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),
        OUStringToOString(m_pImpl->getExport().GetFilter().getNamespaceURL(OOX_NS(dmlDiagram)),
                          RTL_TEXTENCODING_UTF8)
            .getStr(),
        FSNS(XML_xmlns, XML_r),
        OUStringToOString(m_pImpl->getExport().GetFilter().getNamespaceURL(OOX_NS(officeRel)),
                          RTL_TEXTENCODING_UTF8)
            .getStr(),
        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);
    endDMLAnchorInline(&rFrameFormat);

    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);
    uno::Reference<io::XOutputStream> xDataOutputStream
        = m_pImpl->getExport().GetFilter().openFragmentStream(
            "word/" + dataFileName,
            "application/vnd.openxmlformats-officedocument.drawingml.diagramData+xml");
    writer->setOutputStream(xDataOutputStream);
    serializer->serialize(uno::Reference<xml::sax::XDocumentHandler>(writer, uno::UNO_QUERY_THROW),
                          uno::Sequence<beans::StringPair>());

    // write the associated Images and rels for data file
    writeDiagramRels(xDataRelSeq, xDataOutputStream, "OOXDiagramDataRels", nAnchorId);

    // write layout file
    serializer.set(layoutDom, uno::UNO_QUERY);
    writer->setOutputStream(m_pImpl->getExport().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->getExport().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->getExport().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);
        uno::Reference<io::XOutputStream> xDrawingOutputStream
            = m_pImpl->getExport().GetFilter().openFragmentStream(
                "word/" + drawingFileName,
                "application/vnd.ms-office.drawingml.diagramDrawing+xml");
        writer->setOutputStream(xDrawingOutputStream);
        serializer->serialize(
            uno::Reference<xml::sax::XDocumentHandler>(writer, uno::UNO_QUERY_THROW),
            uno::Sequence<beans::StringPair>());

        // write the associated Images and rels for drawing file
        uno::Sequence<uno::Sequence<uno::Any>> xDrawingRelSeq;
        diagramDrawing[1] >>= xDrawingRelSeq;
        writeDiagramRels(xDrawingRelSeq, xDrawingOutputStream, "OOXDiagramDrawingRels", nAnchorId);
    }
}

void DocxSdrExport::writeOnlyTextOfFrame(ww8::Frame const* pParentFrame)
diff --git a/sw/source/filter/ww8/docxsdrexport.hxx b/sw/source/filter/ww8/docxsdrexport.hxx
index 81a8da8..6139787 100644
--- a/sw/source/filter/ww8/docxsdrexport.hxx
+++ b/sw/source/filter/ww8/docxsdrexport.hxx
@@ -95,10 +95,7 @@ public:
    /// Write <a:effectLst>, the effect list.
    void writeDMLEffectLst(const SwFrameFormat& rFrameFormat);
    /// Writes a diagram (smartart).
    void writeDiagram(const SdrObject* sdrObject, const SwFrameFormat& rFrameFormat, int nAnchorId);
    void writeDiagramRels(const css::uno::Sequence< css::uno::Sequence<css::uno::Any> >& xRelSeq,
                          const css::uno::Reference<css::io::XOutputStream>& xOutStream, const OUString& sGrabBagProperyName,
                          int nAnchorId);
    void writeDiagram(const SdrObject* sdrObject, const SwFrameFormat& rFrameFormat, int nDiagramId);
    /// Writes text frame in DML format.
    void writeDMLTextFrame(ww8::Frame const* pParentFrame, int nAnchorId, bool bTextBoxOnly = false);
    /// Writes text frame in VML format.