tdf#83671 SmartArt: preserve pos and size for metafile

Import of a SmartArt creates a group with a background shape and then
the SmartArt shapes. The background shape determines the position and
size of the group.

The method Shape::convertSmartArtToMetafile() replaces the existing
SmartArt shapes with a metafile object and thereby throws away the
background shape. Thus the group takes it size from the metafile object,
which has default size 100x100 (Hmm) and position 0|0.
The patch remembers the original size and position from the background
shape and applies it then to the metafile shape.

Change-Id: Id7b1ccd20b2597c5e2adca7294a994fd2e0e066f
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/141830
Tested-by: Jenkins
Reviewed-by: Regina Henschel <rb.henschel@t-online.de>
diff --git a/oox/source/drawingml/shape.cxx b/oox/source/drawingml/shape.cxx
index e43b6b9..7357e36 100644
--- a/oox/source/drawingml/shape.cxx
+++ b/oox/source/drawingml/shape.cxx
@@ -1966,9 +1966,16 @@ void Shape::convertSmartArtToMetafile(XmlFilterBase const & rFilterBase)
        // from them
        Reference<XShape> xShape(renderDiagramToGraphic(rFilterBase));
        Reference<XShapes> xShapes(mxShape, UNO_QUERY_THROW);
        tools::Rectangle aBackgroundRect
            = SdrObject::getSdrObjectFromXShape(
                  Reference<XShape>(xShapes->getByIndex(0), UNO_QUERY_THROW))
                  ->GetLogicRect();
        while (xShapes->hasElements())
            xShapes->remove(Reference<XShape>(xShapes->getByIndex(0), UNO_QUERY_THROW));
        xShapes->add(xShape);
        SdrObject::getSdrObjectFromXShape(
            Reference<XShape>(xShapes->getByIndex(0), UNO_QUERY_THROW))
            ->NbcSetLogicRect(aBackgroundRect);
    }
    catch (const Exception&)
    {
diff --git a/sc/qa/unit/subsequent_filters_test2.cxx b/sc/qa/unit/subsequent_filters_test2.cxx
index 1ce547a..8ae23af 100644
--- a/sc/qa/unit/subsequent_filters_test2.cxx
+++ b/sc/qa/unit/subsequent_filters_test2.cxx
@@ -187,6 +187,7 @@ public:
    void testInvalidBareBiff5();
    void testTooManyColsRows();
    void testTdf83671_SmartArt_import();
    void testTdf83671_SmartArt_import2();

    CPPUNIT_TEST_SUITE(ScFiltersTest2);

@@ -304,6 +305,7 @@ public:
    CPPUNIT_TEST(testInvalidBareBiff5);
    CPPUNIT_TEST(testTooManyColsRows);
    CPPUNIT_TEST(testTdf83671_SmartArt_import);
    CPPUNIT_TEST(testTdf83671_SmartArt_import2);

    CPPUNIT_TEST_SUITE_END();
};
@@ -3089,6 +3091,52 @@ void ScFiltersTest2::testTdf83671_SmartArt_import()
    xDocSh->DoClose();
}

void ScFiltersTest2::testTdf83671_SmartArt_import2()
{
    // The example doc contains a diagram (SmartArt). Such should be imported as group object.
    // With conversion enabled, the group contains only a graphic. Error was, that the shape
    // had size 100x100 Hmm and position 0|0.

    // Make sure SmartArt is loaded with converting to metafile
    bool bUseGroup = officecfg::Office::Common::Filter::Microsoft::Import::SmartArtToShapes::get();
    if (bUseGroup)
    {
        std::shared_ptr<comphelper::ConfigurationChanges> pChange(
            comphelper::ConfigurationChanges::create());
        officecfg::Office::Common::Filter::Microsoft::Import::SmartArtToShapes::set(false, pChange);
        pChange->commit();
    }

    // Get document and shape
    ScDocShellRef xDocSh = loadDoc(u"tdf83671_SmartArt_import.", FORMAT_XLSX);
    ScDocument& rDoc = xDocSh->GetDocument();
    ScDrawLayer* pDrawLayer = rDoc.GetDrawLayer();
    SdrPage* pPage = pDrawLayer->GetPage(0);
    SdrObject* pObj = pPage->GetObj(0);

    // Check that it is a group shape with 1 child
    CPPUNIT_ASSERT(pObj->IsGroupObject());
    SdrObjList* pChildren = pObj->getChildrenOfSdrObject();
    CPPUNIT_ASSERT_EQUAL(size_t(1), pChildren->GetObjCount());

    // The child shape should have about 60mm x 42mm size and position 1164|1270.
    // Without fix its size was 100x100 and position 0|0.
    tools::Rectangle aBackground = pChildren->GetObj(0)->GetLogicRect();
    CPPUNIT_ASSERT_DOUBLES_EQUAL(sal_Int32(6000), aBackground.getOpenWidth(), 10);
    CPPUNIT_ASSERT_DOUBLES_EQUAL(sal_Int32(4200), aBackground.getOpenHeight(), 10);
    CPPUNIT_ASSERT_EQUAL(Point(1164, 1270), aBackground.GetPos());

    if (bUseGroup)
    {
        std::shared_ptr<comphelper::ConfigurationChanges> pChange(
            comphelper::ConfigurationChanges::create());
        officecfg::Office::Common::Filter::Microsoft::Import::SmartArtToShapes::set(true, pChange);
        pChange->commit();
    }

    xDocSh->DoClose();
}

CPPUNIT_TEST_SUITE_REGISTRATION(ScFiltersTest2);

CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/sc/subsequent_setup.mk b/sc/subsequent_setup.mk
index 5e649e5..5c9b092 100644
--- a/sc/subsequent_setup.mk
+++ b/sc/subsequent_setup.mk
@@ -104,6 +104,7 @@ $(eval $(call gb_CppunitTest_use_components,sc_subsequent_$(1),\
    svl/util/svl \
    svl/source/fsstor/fsstorage \
    svtools/util/svt \
    svx/util/svxcore \
    toolkit/util/tk \
    ucb/source/core/ucb1 \
    ucb/source/ucp/file/ucpfile1 \