include/oox/drawingml/shape.hxx                |    2 
 oox/source/core/xmlfilterbase.cxx              |    1 
 oox/source/drawingml/connectorshapecontext.cxx |    8 ++
 oox/source/drawingml/shape.cxx                 |    4 +
 oox/source/drawingml/shapecontext.cxx          |    8 ++
 oox/source/drawingml/shapegroupcontext.cxx     |    8 ++
 oox/source/export/shapes.cxx                   |   73 +++++++++++++++++----
 oox/source/ppt/pptshapegroupcontext.cxx        |    8 ++
 sd/qa/unit/data/pptx/tdf141058-1.pptx          |binary
 sd/qa/unit/export-tests.cxx                    |   86 +++++++++++++++++++++++++
 sw/qa/extras/globalfilter/globalfilter.cxx     |   17 ++++
 sw/source/filter/ww8/docxattributeoutput.cxx   |   15 ----
 sw/source/filter/ww8/docxsdrexport.cxx         |   23 ++++++
 sw/source/filter/ww8/docxsdrexport.hxx         |    5 +
 14 files changed, 229 insertions(+), 29 deletions(-)

New commits:
commit e751d59264c369cfc342dab5f0759be12341d306
Author:     Michael Stahl <michael.st...@allotropia.de>
AuthorDate: Thu Jul 6 16:57:08 2023 +0200
Commit:     Michael Stahl <michael.st...@allotropia.de>
CommitDate: Thu Jul 6 20:28:40 2023 +0200

    tdf#141058 oox,sw: OOXML import/export of decorative on shapes
    
    Also add a test for PPTX (using the oox filters), and add a SdrObject to
    the testTdf143311 for DOCX (using the writerfilter/docxsdrexport).
    
    Change-Id: Iccee46c0d30316c33c0947b117e2604c96fa0182
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/154137
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>

diff --git a/include/oox/drawingml/shape.hxx b/include/oox/drawingml/shape.hxx
index 72ce51ef6476..ccf477bef805 100644
--- a/include/oox/drawingml/shape.hxx
+++ b/include/oox/drawingml/shape.hxx
@@ -174,6 +174,7 @@ public:
     void                            setId( const OUString& rId ) { msId = rId; 
}
     const OUString&                 getId() const { return msId; }
     void                            setDescription( const OUString& rDescr ) { 
msDescription = rDescr; }
+    void                            setDecorative(bool const isDecorative) { 
m_isDecorative = isDecorative; }
     void                            setHidden( bool bHidden ) { mbHidden = 
bHidden; }
     void                            setHiddenMasterShape( bool 
bHiddenMasterShape ) { mbHiddenMasterShape = bHiddenMasterShape; }
     void                            setLocked( bool bLocked ) { mbLocked = 
bLocked; }
@@ -356,6 +357,7 @@ protected:
     OUString                    msInternalName; // used by diagram; not 
displayed in UI
     OUString                    msId;
     OUString                    msDescription;
+    bool                        m_isDecorative = false;
     sal_Int32                   mnSubType;      // if this type is not zero, 
then the shape is a placeholder
     std::optional< sal_Int32 >  moSubTypeIndex;
 
diff --git a/oox/source/core/xmlfilterbase.cxx 
b/oox/source/core/xmlfilterbase.cxx
index c2911a756047..0c95980accd4 100644
--- a/oox/source/core/xmlfilterbase.cxx
+++ b/oox/source/core/xmlfilterbase.cxx
@@ -148,6 +148,7 @@ const Sequence< beans::Pair< OUString, sal_Int32 > >& 
NamespaceIds()
              NMSP_c15},
             
{"http://schemas.microsoft.com/office/spreadsheetml/2015/revision2";,
              NMSP_xr2},
+            {"http://schemas.microsoft.com/office/drawing/2017/decorative";, 
NMSP_adec},
         };
     return SINGLETON;
 };
diff --git a/oox/source/drawingml/connectorshapecontext.cxx 
b/oox/source/drawingml/connectorshapecontext.cxx
index 8ea0bcca6965..018ca95c648d 100644
--- a/oox/source/drawingml/connectorshapecontext.cxx
+++ b/oox/source/drawingml/connectorshapecontext.cxx
@@ -69,6 +69,14 @@ ConnectorShapePropertiesContext::onCreateContext(sal_Int32 
aElementToken,
 {
     switch (getBaseToken(aElementToken))
     {
+        case XML_extLst:
+        case XML_ext:
+            break;
+        case XML_decorative:
+        {
+            mpConnectorShapePtr->setDecorative(rAttribs.getBool(XML_val, 
false));
+            break;
+        }
         case XML_cNvPr:
             mpConnectorShapePtr->setId(rAttribs.getStringDefaulted(XML_id));
             
mpConnectorShapePtr->setName(rAttribs.getStringDefaulted(XML_name));
diff --git a/oox/source/drawingml/shape.cxx b/oox/source/drawingml/shape.cxx
index 040a632563cc..0fca9c0e1ac3 100644
--- a/oox/source/drawingml/shape.cxx
+++ b/oox/source/drawingml/shape.cxx
@@ -1144,6 +1144,10 @@ Reference< XShape > const & Shape::createAndInsert(
         {
             xSet->setPropertyValue( "Description", Any( msDescription ) );
         }
+        if (m_isDecorative)
+        {
+            xSet->setPropertyValue("Decorative", Any(m_isDecorative));
+        }
         if (aServiceName != "com.sun.star.text.TextFrame")
             rxShapes->add( mxShape );
 
diff --git a/oox/source/drawingml/shapecontext.cxx 
b/oox/source/drawingml/shapecontext.cxx
index d14864ede331..73fdab79508e 100644
--- a/oox/source/drawingml/shapecontext.cxx
+++ b/oox/source/drawingml/shapecontext.cxx
@@ -66,6 +66,14 @@ ContextHandlerRef ShapeContext::onCreateContext( sal_Int32 
aElementToken, const
     // nvSpPr CT_ShapeNonVisual begin
 //  case XML_drElemPr:
 //      break;
+    case XML_extLst:
+    case XML_ext:
+        break;
+    case XML_decorative:
+        {
+            mpShapePtr->setDecorative(rAttribs.getBool(XML_val, false));
+        }
+        break;
     case XML_cNvPr:
     {
         mpShapePtr->setHidden( rAttribs.getBool( XML_hidden, false ) );
diff --git a/oox/source/drawingml/shapegroupcontext.cxx 
b/oox/source/drawingml/shapegroupcontext.cxx
index 02ce5917e682..d810b0448b9a 100644
--- a/oox/source/drawingml/shapegroupcontext.cxx
+++ b/oox/source/drawingml/shapegroupcontext.cxx
@@ -58,6 +58,14 @@ ContextHandlerRef ShapeGroupContext::onCreateContext( 
sal_Int32 aElementToken, c
 {
     switch( getBaseToken( aElementToken ) )
     {
+    case XML_extLst:
+    case XML_ext:
+        break;
+    case XML_decorative:
+        {
+            mpGroupShapePtr->setDecorative(rAttribs.getBool(XML_val, false));
+        }
+        break;
     case XML_cNvPr:
     {
         mpGroupShapePtr->setHidden( rAttribs.getBool( XML_hidden, false ) );
diff --git a/oox/source/export/shapes.cxx b/oox/source/export/shapes.cxx
index fc702c1c3a22..78614b7efbcc 100644
--- a/oox/source/export/shapes.cxx
+++ b/oox/source/export/shapes.cxx
@@ -394,6 +394,24 @@ bool ShapeExport::NonEmptyText( const Reference< 
XInterface >& xIface )
     return IsNonEmptySimpleText(xIface);
 }
 
+static void AddExtLst(FSHelperPtr const& pFS, Reference<XPropertySet> const& 
xShape)
+{
+    if (xShape->getPropertySetInfo()->hasPropertyByName("Decorative")
+        && xShape->getPropertyValue("Decorative").get<bool>())
+    {
+        pFS->startElementNS(XML_a, XML_extLst);
+//            FSNS(XML_xmlns, XML_a), 
GetExport().GetFilter().getNamespaceURL(OOX_NS(dml)));
+        pFS->startElementNS(XML_a, XML_ext,
+            // MSO uses this "URI" which is obviously not a URI
+            XML_uri, "{C183D7F6-B498-43B3-948B-1728B52AA6E4}");
+        pFS->singleElementNS(XML_adec, XML_decorative,
+            FSNS(XML_xmlns, XML_adec), 
"http://schemas.microsoft.com/office/drawing/2017/decorative";,
+            XML_val, "1");
+        pFS->endElementNS(XML_a, XML_ext);
+        pFS->endElementNS(XML_a, XML_extLst);
+    }
+}
+
 ShapeExport& ShapeExport::WritePolyPolygonShape( const Reference< XShape >& 
xShape, const bool bClosed )
 {
     SAL_INFO("oox.shape", "write polypolygon shape");
@@ -419,13 +437,16 @@ ShapeExport& ShapeExport::WritePolyPolygonShape( const 
Reference< XShape >& xSha
     SAL_INFO("oox.shape", "size: " << size.Width << " x " << size.Height);
 #endif
 
+    Reference<XPropertySet> const xProps(xShape, UNO_QUERY);
     // non visual shape properties
     if (GetDocumentType() != DOCUMENT_DOCX || mbUserShapes)
     {
         pFS->startElementNS(mnXmlNamespace, XML_nvSpPr);
-        pFS->singleElementNS( mnXmlNamespace, XML_cNvPr,
+        pFS->startElementNS(mnXmlNamespace, XML_cNvPr,
                               XML_id, OString::number(GetNewShapeID(xShape)),
                               XML_name, GetShapeName(xShape));
+        AddExtLst(pFS, xProps);
+        pFS->endElementNS(mnXmlNamespace, XML_cNvPr);
     }
     pFS->singleElementNS(mnXmlNamespace, XML_cNvSpPr);
     if (GetDocumentType() != DOCUMENT_DOCX || mbUserShapes)
@@ -438,7 +459,6 @@ ShapeExport& ShapeExport::WritePolyPolygonShape( const 
Reference< XShape >& xSha
     pFS->startElementNS(mnXmlNamespace, XML_spPr);
     WriteTransformation( xShape, aRect, XML_a );
     WritePolyPolygon(xShape, bClosed);
-    Reference< XPropertySet > xProps( xShape, UNO_QUERY );
     if( xProps.is() ) {
         if( bClosed )
             WriteFill(xProps, aSize);
@@ -484,9 +504,12 @@ ShapeExport& ShapeExport::WriteGroupShape(const 
uno::Reference<drawing::XShape>&
     if (GetDocumentType() != DOCUMENT_DOCX || mbUserShapes)
     {
         pFS->startElementNS(mnXmlNamespace, XML_nvGrpSpPr);
-        pFS->singleElementNS(mnXmlNamespace, XML_cNvPr,
+        pFS->startElementNS(mnXmlNamespace, XML_cNvPr,
                 XML_id, OString::number(GetNewShapeID(xShape)),
                 XML_name, GetShapeName(xShape));
+        uno::Reference<beans::XPropertySet> const xShapeProps(xShape, 
uno::UNO_QUERY_THROW);
+        AddExtLst(pFS, xShapeProps);
+        pFS->endElementNS(mnXmlNamespace, XML_cNvPr);
         pFS->singleElementNS(mnXmlNamespace, XML_cNvGrpSpPr);
         WriteNonVisualProperties(xShape );
         pFS->endElementNS(mnXmlNamespace, XML_nvGrpSpPr);
@@ -894,6 +917,7 @@ ShapeExport& ShapeExport::WriteCustomShape( const 
Reference< XShape >& xShape )
                 mpFS->singleElementNS(XML_a, XML_hlinkClick, FSNS(XML_r, 
XML_id), sRelId,
                                       XML_action, "ppaction://hlinksldjump");
         }
+        AddExtLst(pFS, rXPropSet);
         pFS->endElementNS(mnXmlNamespace, XML_cNvPr);
         pFS->singleElementNS(mnXmlNamespace, XML_cNvSpPr);
         WriteNonVisualProperties( xShape );
@@ -923,6 +947,7 @@ ShapeExport& ShapeExport::WriteCustomShape( const 
Reference< XShape >& xShape )
                     mpFS->singleElementNS(XML_a, XML_hlinkClick, FSNS(XML_r, 
XML_id), sRelId);
                 }
             }
+            AddExtLst(pFS, rXPropSet);
             pFS->endElementNS(mnXmlNamespace, XML_cNvPr);
         }
         pFS->singleElementNS(mnXmlNamespace, XML_cNvSpPr);
@@ -1151,13 +1176,16 @@ ShapeExport& ShapeExport::WriteEllipseShape( const 
Reference< XShape >& xShape )
 
     // TODO: connector ?
 
+    Reference<XPropertySet> const xProps(xShape, UNO_QUERY);
     // non visual shape properties
     if (GetDocumentType() != DOCUMENT_DOCX || mbUserShapes)
     {
         pFS->startElementNS(mnXmlNamespace, XML_nvSpPr);
-        pFS->singleElementNS( mnXmlNamespace, XML_cNvPr,
+        pFS->startElementNS(mnXmlNamespace, XML_cNvPr,
                 XML_id, OString::number(GetNewShapeID(xShape)),
                 XML_name, GetShapeName(xShape));
+        AddExtLst(pFS, xProps);
+        pFS->endElementNS(mnXmlNamespace, XML_cNvPr);
         pFS->singleElementNS( mnXmlNamespace, XML_cNvSpPr );
         WriteNonVisualProperties( xShape );
         pFS->endElementNS( mnXmlNamespace, XML_nvSpPr );
@@ -1165,7 +1193,6 @@ ShapeExport& ShapeExport::WriteEllipseShape( const 
Reference< XShape >& xShape )
     else
         pFS->singleElementNS(mnXmlNamespace, XML_cNvSpPr);
 
-    Reference< XPropertySet > xProps( xShape, UNO_QUERY );
     CircleKind  eCircleKind(CircleKind_FULL);
     if (xProps.is())
         xProps->getPropertyValue("CircleKind" ) >>= eCircleKind;
@@ -1369,6 +1396,7 @@ void ShapeExport::WriteGraphicObjectShapePart( const 
Reference< XShape >& xShape
             mpFS->singleElementNS(XML_a, XML_hlinkClick, FSNS(XML_r, XML_id), 
sRelId, XML_action,
                                   "ppaction://hlinksldjump");
     }
+    AddExtLst(pFS, xShapeProps);
     pFS->endElementNS(mnXmlNamespace, XML_cNvPr);
 
     pFS->singleElementNS(mnXmlNamespace, XML_cNvPicPr
@@ -1822,9 +1850,11 @@ ShapeExport& ShapeExport::WriteConnectorShape( const 
Reference< XShape >& xShape
     {
         // non visual shape properties
         pFS->startElementNS(mnXmlNamespace, XML_nvCxnSpPr);
-        pFS->singleElementNS(mnXmlNamespace, XML_cNvPr,
+        pFS->startElementNS(mnXmlNamespace, XML_cNvPr,
             XML_id, OString::number(GetNewShapeID(xShape)),
             XML_name, GetShapeName(xShape));
+        AddExtLst(pFS, rXPropSet);
+        pFS->endElementNS(mnXmlNamespace, XML_cNvPr);
         // non visual connector shape drawing properties
         pFS->startElementNS(mnXmlNamespace, XML_cNvCxnSpPr);
 
@@ -1881,13 +1911,16 @@ ShapeExport& ShapeExport::WriteLineShape( const 
Reference< XShape >& xShape )
         bFlipV = ( rPoly[ 0 ].Y() > rPoly[ 1 ].Y() );
     }
 
+    Reference<XPropertySet> const xShapeProps(xShape, UNO_QUERY);
     // non visual shape properties
     if (GetDocumentType() != DOCUMENT_DOCX || mbUserShapes)
     {
         pFS->startElementNS(mnXmlNamespace, XML_nvSpPr);
-        pFS->singleElementNS( mnXmlNamespace, XML_cNvPr,
+        pFS->startElementNS(mnXmlNamespace, XML_cNvPr,
                               XML_id, OString::number(GetNewShapeID(xShape)),
                               XML_name, GetShapeName(xShape));
+        AddExtLst(pFS, xShapeProps);
+        pFS->endElementNS(mnXmlNamespace, XML_cNvPr);
     }
     pFS->singleElementNS( mnXmlNamespace, XML_cNvSpPr );
     if (GetDocumentType() != DOCUMENT_DOCX || mbUserShapes)
@@ -1900,7 +1933,6 @@ ShapeExport& ShapeExport::WriteLineShape( const 
Reference< XShape >& xShape )
     pFS->startElementNS(mnXmlNamespace, XML_spPr);
     WriteShapeTransformation( xShape, XML_a, bFlipH, bFlipV, true);
     WritePresetShape( "line" );
-    Reference< XPropertySet > xShapeProps( xShape, UNO_QUERY );
     if( xShapeProps.is() )
         WriteOutline( xShapeProps );
     pFS->endElementNS( mnXmlNamespace, XML_spPr );
@@ -1920,9 +1952,14 @@ ShapeExport& ShapeExport::WriteLineShape( const 
Reference< XShape >& xShape )
 
 ShapeExport& ShapeExport::WriteNonVisualDrawingProperties( const Reference< 
XShape >& xShape, const char* pName )
 {
-    GetFS()->singleElementNS( mnXmlNamespace, XML_cNvPr,
+    FSHelperPtr pFS = GetFS();
+
+    Reference<XPropertySet> const xShapeProps(xShape, UNO_QUERY);
+    pFS->startElementNS(mnXmlNamespace, XML_cNvPr,
                               XML_id, OString::number(GetNewShapeID(xShape)),
                               XML_name, pName );
+    AddExtLst(pFS, xShapeProps);
+    pFS->endElementNS(mnXmlNamespace, XML_cNvPr);
 
     return *this;
 }
@@ -1960,9 +1997,11 @@ ShapeExport& ShapeExport::WriteRectangleShape( const 
Reference< XShape >& xShape
     if (GetDocumentType() == DOCUMENT_DOCX && !mbUserShapes)
         pFS->singleElementNS(mnXmlNamespace, XML_cNvSpPr);
     pFS->startElementNS(mnXmlNamespace, XML_nvSpPr);
-    pFS->singleElementNS( mnXmlNamespace, XML_cNvPr,
+    pFS->startElementNS(mnXmlNamespace, XML_cNvPr,
                           XML_id, OString::number(GetNewShapeID(xShape)),
                           XML_name, GetShapeName(xShape));
+    AddExtLst(pFS, xShapeProps);
+    pFS->endElementNS(mnXmlNamespace, XML_cNvPr);
     pFS->singleElementNS(mnXmlNamespace, XML_cNvSpPr);
     WriteNonVisualProperties( xShape );
     pFS->endElementNS( mnXmlNamespace, XML_nvSpPr );
@@ -2425,9 +2464,12 @@ ShapeExport& ShapeExport::WriteTableShape( const 
Reference< XShape >& xShape )
 
     pFS->startElementNS(mnXmlNamespace, XML_nvGraphicFramePr);
 
-    pFS->singleElementNS( mnXmlNamespace, XML_cNvPr,
+    Reference<XPropertySet> const xShapeProps(xShape, UNO_QUERY);
+    pFS->startElementNS(mnXmlNamespace, XML_cNvPr,
                           XML_id, OString::number(GetNewShapeID(xShape)),
                           XML_name,   GetShapeName(xShape));
+    AddExtLst(pFS, xShapeProps);
+    pFS->endElementNS(mnXmlNamespace, XML_cNvPr);
 
     pFS->singleElementNS(mnXmlNamespace, XML_cNvGraphicFramePr);
 
@@ -2470,6 +2512,7 @@ ShapeExport& ShapeExport::WriteTextShape( const 
Reference< XShape >& xShape )
 
             mpFS->singleElementNS(XML_a, XML_hlinkClick, FSNS(XML_r, XML_id), 
sRelId);
         }
+        AddExtLst(pFS, xShapeProps);
         pFS->endElementNS(mnXmlNamespace, XML_cNvPr);
     }
     pFS->singleElementNS(mnXmlNamespace, XML_cNvSpPr, XML_txBox, "1");
@@ -2517,9 +2560,11 @@ void ShapeExport::WriteMathShape(Reference<XShape> 
const& xShape)
         XML_Requires, "a14");
     mpFS->startElementNS(mnXmlNamespace, XML_sp);
     mpFS->startElementNS(mnXmlNamespace, XML_nvSpPr);
-    mpFS->singleElementNS(mnXmlNamespace, XML_cNvPr,
+    mpFS->startElementNS(mnXmlNamespace, XML_cNvPr,
          XML_id, OString::number(GetNewShapeID(xShape)),
          XML_name, GetShapeName(xShape));
+    AddExtLst(mpFS, xPropSet);
+    mpFS->endElementNS(mnXmlNamespace, XML_cNvPr);
     mpFS->singleElementNS(mnXmlNamespace, XML_cNvSpPr, XML_txBox, "1");
     mpFS->singleElementNS(mnXmlNamespace, XML_nvPr);
     mpFS->endElementNS(mnXmlNamespace, XML_nvSpPr);
@@ -2720,9 +2765,11 @@ ShapeExport& ShapeExport::WriteOLE2Shape( const 
Reference< XShape >& xShape )
 
     mpFS->startElementNS(mnXmlNamespace, XML_nvGraphicFramePr);
 
-    mpFS->singleElementNS( mnXmlNamespace, XML_cNvPr,
+    mpFS->startElementNS(mnXmlNamespace, XML_cNvPr,
                            XML_id,     OString::number(GetNewShapeID(xShape)),
                            XML_name,   GetShapeName(xShape));
+    AddExtLst(mpFS, xPropSet);
+    mpFS->endElementNS(mnXmlNamespace, XML_cNvPr);
 
     mpFS->singleElementNS(mnXmlNamespace, XML_cNvGraphicFramePr);
 
diff --git a/oox/source/ppt/pptshapegroupcontext.cxx 
b/oox/source/ppt/pptshapegroupcontext.cxx
index dcce466fefd2..49a5f5ce4ba6 100644
--- a/oox/source/ppt/pptshapegroupcontext.cxx
+++ b/oox/source/ppt/pptshapegroupcontext.cxx
@@ -65,6 +65,14 @@ ContextHandlerRef PPTShapeGroupContext::onCreateContext( 
sal_Int32 aElementToken
 
     switch( aElementToken )
     {
+    case OOX_TOKEN(dml, extLst):
+    case OOX_TOKEN(dml, ext):
+        break;
+    case OOX_TOKEN(adec, decorative):
+        {
+            mpGroupShapePtr->setDecorative(rAttribs.getBool(XML_val, false));
+        }
+        break;
     case PPT_TOKEN( cNvPr ):
     {
         // don't override SmartArt properties for embedded drawing's spTree
diff --git a/sd/qa/unit/data/pptx/tdf141058-1.pptx 
b/sd/qa/unit/data/pptx/tdf141058-1.pptx
new file mode 100644
index 000000000000..a93bf8824292
Binary files /dev/null and b/sd/qa/unit/data/pptx/tdf141058-1.pptx differ
diff --git a/sd/qa/unit/export-tests.cxx b/sd/qa/unit/export-tests.cxx
index aee7e6724e32..61f6736fc33f 100644
--- a/sd/qa/unit/export-tests.cxx
+++ b/sd/qa/unit/export-tests.cxx
@@ -199,6 +199,92 @@ CPPUNIT_TEST_FIXTURE(SdExportTest, 
testTransparentBackground)
     checkFontAttributes<Color, SvxColorItem>(pObj2, COL_YELLOW, 
EE_CHAR_BKGCOLOR);
 }
 
+CPPUNIT_TEST_FIXTURE(SdExportTest, testDecorative)
+{
+    createSdImpressDoc("pptx/tdf141058-1.pptx");
+
+    auto doTest = [this](OString const test) {
+        ::std::set<OString> const decorative = {
+            "Picture 6",
+            "Rectangle 7",
+            "Group 24",
+            "Connector: Elbow 9",
+            "Connector: Elbow 11",
+            "Connector: Elbow 14",
+            "Connector: Elbow 17",
+            "Straight Arrow Connector 21",
+            "Straight Arrow Connector 22",
+            "Straight Arrow Connector 23",
+        };
+
+        uno::Reference<drawing::XDrawPage> const xPage(getPage(0));
+        CPPUNIT_ASSERT_EQUAL_MESSAGE(test.getStr(), sal_Int32(5), 
xPage->getCount());
+        auto nDecorative(0);
+        auto nShapes(0);
+        auto nInnerDecorative(0);
+        auto nInnerShapes(0);
+        for (auto i = xPage->getCount(); i != 0; --i)
+        {
+            uno::Reference<beans::XPropertySet> xShape(getShape(i - 1, xPage));
+            uno::Reference<container::XNamed> xNamed(xShape, uno::UNO_QUERY);
+            OString const name(OUStringToOString(xNamed->getName(), 
RTL_TEXTENCODING_UTF8));
+            if (decorative.find(name) != decorative.end())
+            {
+                CPPUNIT_ASSERT_MESSAGE(OString(test + name).getStr(),
+                                       
xShape->getPropertyValue("Decorative").get<bool>());
+                ++nDecorative;
+            }
+            else
+            {
+                CPPUNIT_ASSERT_MESSAGE(OString(test + name).getStr(),
+                                       
!xShape->getPropertyValue("Decorative").get<bool>());
+                ++nShapes;
+            }
+            uno::Reference<drawing::XShapes> const xShapes(xShape, 
uno::UNO_QUERY);
+            if (xShapes.is())
+            {
+                for (auto j = xShapes->getCount(); j != 0; --j)
+                {
+                    uno::Reference<beans::XPropertySet> 
xInnerShape(xShapes->getByIndex(i - 1),
+                                                                    
uno::UNO_QUERY);
+                    uno::Reference<container::XNamed> xInnerNamed(xInnerShape, 
uno::UNO_QUERY);
+                    OString const innerName(
+                        OUStringToOString(xInnerNamed->getName(), 
RTL_TEXTENCODING_UTF8));
+                    if (decorative.find(innerName) != decorative.end())
+                    {
+                        CPPUNIT_ASSERT_MESSAGE(
+                            OString(test + innerName).getStr(),
+                            
xInnerShape->getPropertyValue("Decorative").get<bool>());
+                        ++nInnerDecorative;
+                    }
+                    else
+                    {
+                        CPPUNIT_ASSERT_MESSAGE(
+                            OString(test + innerName).getStr(),
+                            
!xInnerShape->getPropertyValue("Decorative").get<bool>());
+                        ++nInnerShapes;
+                    }
+                }
+            }
+        }
+        CPPUNIT_ASSERT_EQUAL_MESSAGE(test.getStr(), 
static_cast<decltype(nDecorative)>(3),
+                                     nDecorative);
+        CPPUNIT_ASSERT_EQUAL_MESSAGE(test.getStr(), 
static_cast<decltype(nShapes)>(2), nShapes);
+        CPPUNIT_ASSERT_EQUAL_MESSAGE(test.getStr(), 
static_cast<decltype(nInnerDecorative)>(7),
+                                     nInnerDecorative);
+        CPPUNIT_ASSERT_EQUAL_MESSAGE(test.getStr(), 
static_cast<decltype(nInnerShapes)>(16),
+                                     nInnerShapes);
+    };
+
+    doTest("initial pptx load: ");
+
+    saveAndReload("Impress Office Open XML");
+    doTest("reload OOXML: ");
+
+    saveAndReload("impress8");
+    doTest("reload ODF: ");
+}
+
 CPPUNIT_TEST_FIXTURE(SdExportTest, testTdf142716)
 {
     createSdImpressDoc("pptx/tdf142716.pptx");
diff --git a/sw/qa/extras/globalfilter/globalfilter.cxx 
b/sw/qa/extras/globalfilter/globalfilter.cxx
index 37f112dc624f..0c7415ddabe6 100644
--- a/sw/qa/extras/globalfilter/globalfilter.cxx
+++ b/sw/qa/extras/globalfilter/globalfilter.cxx
@@ -1657,9 +1657,21 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf143311)
 {
     createSwDoc("tdf143311-1.docx");
     CPPUNIT_ASSERT_EQUAL(true, getProperty<bool>(getShape(1), "Decorative"));
+    {
+        // add another one that's a SdrObject
+        uno::Reference<css::lang::XMultiServiceFactory> xFactory(mxComponent, 
uno::UNO_QUERY);
+        uno::Reference<drawing::XShape> xShape(
+            xFactory->createInstance("com.sun.star.drawing.RectangleShape"), 
uno::UNO_QUERY);
+        uno::Reference<beans::XPropertySet> xShapeProps(xShape, 
uno::UNO_QUERY);
+        xShapeProps->setPropertyValue("Decorative", uno::Any(true));
+        uno::Reference<drawing::XDrawPageSupplier> 
xDrawPageSupplier(mxComponent, uno::UNO_QUERY);
+        uno::Reference<drawing::XDrawPage> 
xDrawPage(xDrawPageSupplier->getDrawPage());
+        xDrawPage->add(xShape);
+    }
     // check DOCX filters
     saveAndReload("Office Open XML Text");
     CPPUNIT_ASSERT_EQUAL(true, getProperty<bool>(getShape(1), "Decorative"));
+    CPPUNIT_ASSERT_EQUAL(true, getProperty<bool>(getShape(2), "Decorative"));
     {
         // tdf#153925 not imported - check default and set it to test ODF 
filters
         uno::Reference<beans::XPropertySet> const 
xStyle(getStyles("FrameStyles")->getByName("Formula"), uno::UNO_QUERY_THROW);
@@ -1669,6 +1681,7 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf143311)
     // check ODF filters
     saveAndReload("writer8");
     CPPUNIT_ASSERT_EQUAL(true, getProperty<bool>(getShape(1), "Decorative"));
+    CPPUNIT_ASSERT_EQUAL(true, getProperty<bool>(getShape(2), "Decorative"));
     CPPUNIT_ASSERT_EQUAL(true, 
getProperty<bool>(getStyles("FrameStyles")->getByName("Formula"), 
"Decorative"));
 
     // check PDF export
@@ -1754,8 +1767,8 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf143311)
     }
     CPPUNIT_ASSERT_EQUAL_MESSAGE("unclosed MCS", Default, state);
     CPPUNIT_ASSERT_EQUAL(static_cast<decltype(nTagged)>(25), nTagged); // text 
in body
-    // 1 decorative image + 1 pre-existing rectangle border or something
-    CPPUNIT_ASSERT(nArtifacts >= 2);
+    // 1 decorative image + 1 decorative shape + 1 pre-existing rectangle 
border or something
+    CPPUNIT_ASSERT(nArtifacts >= 3);
 }
 
 void Test::testTextFormField()
diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx 
b/sw/source/filter/ww8/docxattributeoutput.cxx
index 3b095a96aea6..21e788665230 100644
--- a/sw/source/filter/ww8/docxattributeoutput.cxx
+++ b/sw/source/filter/ww8/docxattributeoutput.cxx
@@ -5266,20 +5266,7 @@ void DocxAttributeOutput::FlyFrameGraphic( const 
SwGrfNode* pGrfNode, const Size
                 FSNS( XML_xmlns, XML_a ), 
"http://schemas.openxmlformats.org/drawingml/2006/main";,
                 FSNS( XML_r, XML_id ), sRelId);
         }
-
-        if (xShapePropSet->getPropertyValue("Decorative").get<bool>())
-        {
-            m_pSerializer->startElementNS(XML_a, XML_extLst,
-                FSNS(XML_xmlns, XML_a), 
GetExport().GetFilter().getNamespaceURL(OOX_NS(dml)));
-            m_pSerializer->startElementNS(XML_a, XML_ext,
-                // Word uses this "URI" which is obviously not a URI
-                XML_uri, "{C183D7F6-B498-43B3-948B-1728B52AA6E4}");
-            m_pSerializer->singleElementNS(XML_adec, XML_decorative,
-                FSNS(XML_xmlns, XML_adec), 
"http://schemas.microsoft.com/office/drawing/2017/decorative";,
-                XML_val, "1");
-            m_pSerializer->endElementNS(XML_a, XML_ext);
-            m_pSerializer->endElementNS(XML_a, XML_extLst);
-        }
+        AddExtLst(m_pSerializer, GetExport(), xShapePropSet);
     }
 
     m_pSerializer->endElementNS( XML_wp, XML_docPr );
diff --git a/sw/source/filter/ww8/docxsdrexport.cxx 
b/sw/source/filter/ww8/docxsdrexport.cxx
index 4b3e53196a29..0c42d28fc6ad 100644
--- a/sw/source/filter/ww8/docxsdrexport.cxx
+++ b/sw/source/filter/ww8/docxsdrexport.cxx
@@ -1383,6 +1383,26 @@ static bool lcl_isLockedCanvas(const 
uno::Reference<drawing::XShape>& xShape)
     });
 }
 
+void AddExtLst(sax_fastparser::FSHelperPtr const& pFS, DocxExport const& 
rExport,
+               uno::Reference<beans::XPropertySet> const& xShape)
+{
+    if (xShape->getPropertyValue("Decorative").get<bool>())
+    {
+        pFS->startElementNS(XML_a, XML_extLst,
+                            // apparently for DOCX the namespace isn't 
declared on the root
+                            FSNS(XML_xmlns, XML_a),
+                            rExport.GetFilter().getNamespaceURL(OOX_NS(dml)));
+        pFS->startElementNS(XML_a, XML_ext,
+                            // Word uses this "URI" which is obviously not a 
URI
+                            XML_uri, "{C183D7F6-B498-43B3-948B-1728B52AA6E4}");
+        pFS->singleElementNS(XML_adec, XML_decorative, FSNS(XML_xmlns, 
XML_adec),
+                             
"http://schemas.microsoft.com/office/drawing/2017/decorative";, XML_val,
+                             "1");
+        pFS->endElementNS(XML_a, XML_ext);
+        pFS->endElementNS(XML_a, XML_extLst);
+    }
+}
+
 void DocxSdrExport::writeDMLDrawing(const SdrObject* pSdrObject, const 
SwFrameFormat* pFrameFormat,
                                     int nAnchorId)
 {
@@ -1422,6 +1442,9 @@ void DocxSdrExport::writeDMLDrawing(const SdrObject* 
pSdrObject, const SwFrameFo
                              FSNS(XML_xmlns, XML_a),
                              
m_pImpl->getExport().GetFilter().getNamespaceURL(OOX_NS(dml)));
     }
+    uno::Reference<beans::XPropertySet> const xShapeProps(xShape, 
uno::UNO_QUERY_THROW);
+    AddExtLst(pFS, m_pImpl->getExport(), xShapeProps);
+
     pFS->endElementNS(XML_wp, XML_docPr);
 
     uno::Reference<lang::XServiceInfo> xServiceInfo(xShape, 
uno::UNO_QUERY_THROW);
diff --git a/sw/source/filter/ww8/docxsdrexport.hxx 
b/sw/source/filter/ww8/docxsdrexport.hxx
index 5b29cd58db34..5ad93d51ad8e 100644
--- a/sw/source/filter/ww8/docxsdrexport.hxx
+++ b/sw/source/filter/ww8/docxsdrexport.hxx
@@ -16,6 +16,8 @@
 #include <sax/fshelper.hxx>
 #include <nodeoffset.hxx>
 
+#include <com/sun/star/beans/XPropertySet.hpp>
+
 namespace rtl
 {
 template <typename> class Reference;
@@ -99,6 +101,9 @@ public:
     void writeBoxItemLine(const SvxBoxItem& rBox);
 };
 
+void AddExtLst(sax_fastparser::FSHelperPtr const& pFS, DocxExport const& 
rExport,
+        css::uno::Reference<css::beans::XPropertySet> const& xShape);
+
 #endif // INCLUDED_SW_SOURCE_FILTER_WW8_DOCXSDREXPORT_HXX
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Reply via email to