tdf#148926 tdf#151678 PPTX import: position of standard connector - part1

Connectors are typically connected to connection dots,
which exist on shapes. If both or one of the two shapes
are missing, it will be drawn the default type of a
standard connector in LO. In this case, there is an
adjustment point which is used to modify positions and
shapes of the connectors. This patch fixes the position of
the connector by calculating and setting the adjustment
value.

Change-Id: Iee384d2a92a22ff95d7b17ba0b4f09698176bc84
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/141723
Tested-by: László Németh <nemeth@numbertext.org>
Reviewed-by: László Németh <nemeth@numbertext.org>
Signed-off-by: Xisco Fauli <xiscofauli@libreoffice.org>
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/142159
Tested-by: Jenkins
diff --git a/include/oox/drawingml/shape.hxx b/include/oox/drawingml/shape.hxx
index 5f4173c..5c4f788 100644
--- a/include/oox/drawingml/shape.hxx
+++ b/include/oox/drawingml/shape.hxx
@@ -136,6 +136,7 @@ public:

    CustomShapePropertiesPtr&       getCustomShapeProperties(){ return mpCustomShapePropertiesPtr; }

    OUString&                       getConnectorName() { return msConnectorName; }
    ConnectorShapePropertiesList&   getConnectorShapeProperties() { return maConnectorShapePropertiesList; }
    void                            setConnectorShape(bool bConnector) { mbConnector = bConnector; }
    bool                            isConnectorShape() const { return mbConnector; }
@@ -163,6 +164,8 @@ public:
    sal_Int32                       getRotation() const { return mnRotation; }
    void                            setDiagramRotation( sal_Int32 nRotation ) { mnDiagramRotation = nRotation; }
    void                            setFlip( bool bFlipH, bool bFlipV ) { mbFlipH = bFlipH; mbFlipV = bFlipV; }
    bool                            getFlipH() const { return mbFlipH; }
    bool                            getFlipV() const { return mbFlipV; }
    void                            addChild( const ShapePtr& rChildPtr ) { maChildren.push_back( rChildPtr ); }
    std::vector< ShapePtr >&        getChildren() { return maChildren; }

@@ -347,6 +350,7 @@ protected:
    css::uno::Reference< css::drawing::XShape > mxShape;
    ConnectorShapePropertiesList maConnectorShapePropertiesList;

    OUString                    msConnectorName;
    OUString                    msServiceName;
    OUString                    msName;
    OUString                    msInternalName; // used by diagram; not displayed in UI
diff --git a/oox/source/drawingml/shape.cxx b/oox/source/drawingml/shape.cxx
index 12b3303..1dd4eb3 100644
--- a/oox/source/drawingml/shape.cxx
+++ b/oox/source/drawingml/shape.cxx
@@ -1678,6 +1678,13 @@ Reference< XShape > const & Shape::createAndInsert(

        if (bIsConnectorShape)
        {
            OUString sConnectorShapePresetTypeName(
                reinterpret_cast<const char*>(
                    mpCustomShapePropertiesPtr->getShapePresetTypeName().getConstArray()),
                mpCustomShapePropertiesPtr->getShapePresetTypeName().getLength(),
                RTL_TEXTENCODING_UTF8);
            msConnectorName = sConnectorShapePresetTypeName;

            sal_Int32 nType = mpCustomShapePropertiesPtr->getShapePresetType();
            switch (nType)
            {
diff --git a/oox/source/ppt/slidepersist.cxx b/oox/source/ppt/slidepersist.cxx
index 8d45bcd..137a9c4 100644
--- a/oox/source/ppt/slidepersist.cxx
+++ b/oox/source/ppt/slidepersist.cxx
@@ -44,6 +44,7 @@
#include <com/sun/star/drawing/XGluePointsSupplier.hpp>
#include <com/sun/star/container/XIdentifierContainer.hpp>
#include <com/sun/star/drawing/EnhancedCustomShapeGluePointType.hpp>
#include <com/sun/star/drawing/ConnectorType.hpp>

using namespace ::com::sun::star;
using namespace ::oox::core;
@@ -350,6 +351,70 @@ Reference<XAnimationNode> SlidePersist::getAnimationNode(const OUString& sId) co
    return aResult;
}

static void lcl_SetEdgeLineValue(uno::Reference<drawing::XShape>& rXConnector,
                                 oox::drawingml::ShapePtr& rShapePtr)
{
    sal_Int32 nEdge = 0;
    awt::Point aStartPt, aEndPt;
    uno::Reference<drawing::XShape> xStartSp, xEndSp;
    uno::Reference<beans::XPropertySet> xPropSet(rXConnector, uno::UNO_QUERY);
    xPropSet->getPropertyValue("EdgeStartPoint") >>= aStartPt;
    xPropSet->getPropertyValue("EdgeEndPoint") >>= aEndPt;
    xPropSet->getPropertyValue("StartShape") >>= xStartSp;
    xPropSet->getPropertyValue("EndShape") >>= xEndSp;
    xPropSet->setPropertyValue("EdgeNode1HorzDist", Any(sal_Int32(0)));
    xPropSet->setPropertyValue("EdgeNode1VertDist", Any(sal_Int32(0)));
    xPropSet->setPropertyValue("EdgeNode2HorzDist", Any(sal_Int32(0)));
    xPropSet->setPropertyValue("EdgeNode2VertDist", Any(sal_Int32(0)));

    const OUString sConnectorName = rShapePtr->getConnectorName();
    if (sConnectorName == "bentConnector2")
    {
        awt::Size aConnSize = rXConnector->getSize();
        if (xStartSp.is() || xEndSp.is())
        {
            if (aConnSize.Height < aConnSize.Width)
            {
                if (xStartSp.is())
                    nEdge = (aStartPt.Y > aEndPt.Y) ? -aConnSize.Height : aConnSize.Height;
                else
                    nEdge = (aStartPt.Y > aEndPt.Y) ? aConnSize.Height : -aConnSize.Height;
            }
            else
            {
                if (xStartSp.is())
                    nEdge = (aStartPt.X > aEndPt.X) ? -aConnSize.Width : aConnSize.Width;
                else
                    nEdge = (aStartPt.X > aEndPt.X) ? aConnSize.Width : -aConnSize.Width;
            }
        }
        else
        {
            bool bFlipH = rShapePtr->getFlipH();
            bool bFlipV = rShapePtr->getFlipV();
            sal_Int32 nConnectorAngle = rShapePtr->getRotation() / 60000;
            if (aConnSize.Height < aConnSize.Width)
            {
                if ((nConnectorAngle == 90 && bFlipH && bFlipV) || (nConnectorAngle == 180)
                    || (nConnectorAngle == 180 && bFlipV) || (nConnectorAngle == 270 && bFlipH))
                    nEdge -= aConnSize.Width;
                else
                    nEdge += aConnSize.Width;
            }
            else
            {
                if ((nConnectorAngle == 180 && bFlipV) || (nConnectorAngle == 270 && bFlipV)
                    || (nConnectorAngle == 90 && bFlipH && bFlipV)
                    || (nConnectorAngle == 0 && !bFlipV))
                    nEdge -= aConnSize.Height;
                else
                    nEdge += aConnSize.Height;
            }
        }
        xPropSet->setPropertyValue("EdgeLine1Delta", Any(nEdge / 2));
    }
}

// create connection between two shape with a connector shape.
void SlidePersist::createConnectorShapeConnection()
{
@@ -408,6 +473,10 @@ void SlidePersist::createConnectorShapeConnection()
                    }
                }
            }
            ConnectorType aConnectorType;
            xPropertySet->getPropertyValue("EdgeKind") >>= aConnectorType;
            if (aConnectorType == ConnectorType_STANDARD)
                lcl_SetEdgeLineValue(xConnector, pIt->second);
        }
    }
    maConnectorShapeId.clear();
diff --git a/sd/qa/unit/data/pptx/connectors.pptx b/sd/qa/unit/data/pptx/connectors.pptx
new file mode 100644
index 0000000..fa03ef0
--- /dev/null
+++ b/sd/qa/unit/data/pptx/connectors.pptx
Binary files differ
diff --git a/sd/qa/unit/import-tests.cxx b/sd/qa/unit/import-tests.cxx
index 6816153..87d282a 100644
--- a/sd/qa/unit/import-tests.cxx
+++ b/sd/qa/unit/import-tests.cxx
@@ -61,6 +61,7 @@
#include <comphelper/lok.hxx>
#include <svx/svdograf.hxx>
#include <vcl/filter/PDFiumLibrary.hxx>
#include <filter/msfilter/escherex.hxx>

using namespace ::com::sun::star;

@@ -83,6 +84,7 @@ public:
    virtual void setUp() override;

    void testDocumentLayout();
    void testConnectors();
    void testTdf149314();
    void testTdf149124();
    void testTdf148965();
@@ -154,6 +156,7 @@ public:
    CPPUNIT_TEST_SUITE(SdImportTest);

    CPPUNIT_TEST(testDocumentLayout);
    CPPUNIT_TEST(testConnectors);
    CPPUNIT_TEST(testTdf149314);
    CPPUNIT_TEST(testTdf149124);
    CPPUNIT_TEST(testTdf148965);
@@ -303,6 +306,21 @@ void SdImportTest::testDocumentLayout()
    }
}

void SdImportTest::testConnectors()
{
    ::sd::DrawDocShellRef xDocShRef
        = loadURL(m_directories.getURLFromSrc(u"/sd/qa/unit/data/pptx/connectors.pptx"), PPTX);

    sal_Int32 aEdgeValue[] = { -1167, -1167, -1591, 1476, 1357, -1357, 1604, -1540 };
    for (size_t i = 1; i < 9; i++)
    {
        uno::Reference<beans::XPropertySet> xConnector(getShapeFromPage(i, 0, xDocShRef));
        sal_Int32 nEdgeLine = xConnector->getPropertyValue("EdgeLine1Delta").get<sal_Int32>();
        CPPUNIT_ASSERT_EQUAL(aEdgeValue[i-1], nEdgeLine);
    }
    xDocShRef->DoClose();
}

void SdImportTest::testTdf149314()
{
    sd::DrawDocShellRef xDocShRef