tdf#136176 Correct update fObjectRotation in NbcShear

Change-Id: I4a73a720845436d25fc1a02eb615dad47f17f96d
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/103269
Tested-by: Jenkins
Reviewed-by: Regina Henschel <rb.henschel@t-online.de>
diff --git a/svx/qa/unit/customshapes.cxx b/svx/qa/unit/customshapes.cxx
index e500c9b..10abdad 100644
--- a/svx/qa/unit/customshapes.cxx
+++ b/svx/qa/unit/customshapes.cxx
@@ -12,10 +12,14 @@
#include <rtl/ustring.hxx>
#include <editeng/unoprnms.hxx>
#include <basegfx/polygon/b2dpolypolygon.hxx>
#include <basegfx/polygon/b2dpolygon.hxx>
#include <basegfx/point/b2dpoint.hxx>
#include <svx/EnhancedCustomShape2d.hxx>
#include <svx/svdoashp.hxx>
#include <svx/svdopath.hxx>
#include <svx/unoapi.hxx>
#include <unotools/mediadescriptor.hxx>
#include <unotools/tempfile.hxx>

#include <cppunit/TestAssert.h>

@@ -24,6 +28,7 @@
#include <com/sun/star/drawing/XDrawPage.hpp>
#include <com/sun/star/awt/Rectangle.hpp>
#include <com/sun/star/frame/Desktop.hpp>
#include <com/sun/star/frame/XStorable.hpp>

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

@@ -749,6 +754,58 @@ CPPUNIT_TEST_FIXTURE(CustomshapesTest, testTdf122323_largeSwingAngle)
    const basegfx::B2DPoint aEnd(aPolygon.getB2DPoint(aPolygon.count() - 2));
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Start <> End", aStart, aEnd);
}

CPPUNIT_TEST_FIXTURE(CustomshapesTest, testTdf136176)
{
    // Error was, that fObjectRotation was not correctly updated after shearing.
    // The problem becomes visible after save and reload.
    OUString sURL = m_directories.getURLFromSrc(sDataDirectory) + "tdf136176_rot30_flip.odg";
    mxComponent = loadFromDesktop(sURL, "com.sun.star.comp.drawing.DrawingDocument");
    CPPUNIT_ASSERT_MESSAGE("Could not load document", mxComponent.is());

    for (sal_uInt16 i = 0; i < 3; i++)
    {
        // get shape
        uno::Reference<drawing::XShape> xShape(getShape(i));
        SdrObjCustomShape& rSdrObjCustomShape(
            static_cast<SdrObjCustomShape&>(*GetSdrObjectFromXShape(xShape)));
        // apply shearing 20deg
        const Point aCenter = rSdrObjCustomShape.GetSnapRect().Center();
        rSdrObjCustomShape.Shear(aCenter, 2000, tan(basegfx::deg2rad(20.0)), false);
    }

    // Save and reload
    uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY);
    utl::TempFile aTempFile;
    utl::MediaDescriptor aMediaDescriptor;
    aMediaDescriptor["FilterName"] <<= OUString("draw8");
    xStorable->storeToURL(aTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList());
    mxComponent->dispose();
    mxComponent = loadFromDesktop(aTempFile.GetURL());

    // Expected values of point 4 of the shape polygon
    const OString sTestCase[] = { "FlipH", "FlipV", "FlipHV" };
    const double fX[] = { 14981.0, 3849.0, 15214.0 };
    const double fY[] = { 9366.0, 16464.0, 23463.0 };

    // Verify correct positions
    for (sal_uInt16 i = 0; i < 3; i++)
    {
        // Get shape
        const uno::Reference<drawing::XShape> xShape(getShape(i));
        const SdrObjCustomShape& rSdrObjCustomShape(
            static_cast<SdrObjCustomShape&>(*GetSdrObjectFromXShape(xShape)));
        // Create polygon from shape and examine point 4 of the polygon
        const basegfx::B2DPolyPolygon aLineGeometry = rSdrObjCustomShape.GetLineGeometry(false);
        const basegfx::B2DPoint aPoint(aLineGeometry.getB2DPolygon(0).getB2DPoint(4));
        // Allow some tolerance for rounding errors
        if (fabs(aPoint.getX() - fX[i]) > 2.0 || fabs(aPoint.getY() - fY[i]) > 2.0)
        {
            CPPUNIT_ASSERT_EQUAL_MESSAGE(sTestCase[i].getStr(), aPoint,
                                         basegfx::B2DPoint(fX[i], fY[i]));
        }
    }
}
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/qa/unit/data/tdf136176_rot30_flip.odg b/svx/qa/unit/data/tdf136176_rot30_flip.odg
new file mode 100644
index 0000000..75707a0
--- /dev/null
+++ b/svx/qa/unit/data/tdf136176_rot30_flip.odg
Binary files differ
diff --git a/svx/source/svdraw/svdoashp.cxx b/svx/source/svdraw/svdoashp.cxx
index 662ab4a0..3e7391d 100644
--- a/svx/source/svdraw/svdoashp.cxx
+++ b/svx/source/svdraw/svdoashp.cxx
@@ -1649,22 +1649,29 @@ void SdrObjCustomShape::NbcShear( const Point& rRef, long nAngle, double tn, boo
    // updating fObjectRotation
    long nTextObjRotation = aGeo.nRotationAngle;
    double fAngle = nTextObjRotation;

    fAngle /= 100.0;

    bool bSingleFlip = (IsMirroredX()!= IsMirroredY());

    fObjectRotation = fmod( bSingleFlip ? -fAngle : fAngle, 360.0 );

    if ( fObjectRotation < 0 )
    if (IsMirroredX())
    {
        fObjectRotation = 360.0 + fObjectRotation;
        if (IsMirroredY())
            fObjectRotation = fAngle - 180.0;
        else
            fObjectRotation = -fAngle;
    }
    else
    {
        if (IsMirroredY())
            fObjectRotation = 180.0 - fAngle;
        else
            fObjectRotation = fAngle;
    }
    while (fObjectRotation < 0)
        fObjectRotation += 360.0;
    while (fObjectRotation >= 360.0)
        fObjectRotation -= 360.0;

    InvalidateRenderGeometry();
}


SdrGluePoint SdrObjCustomShape::GetVertexGluePoint(sal_uInt16 nPosNum) const
{
    sal_Int32 nWdt = ImpGetLineWdt(); // #i25616#