From d4ca360f6632f03e9fb7e9af37aac40d23f1249a Mon Sep 17 00:00:00 2001 From: Regina Henschel Date: Tue, 15 Dec 2020 20:20:55 +0100 Subject: [PATCH] tdf#138945 update fObjectRotation for NbcResize SdrObjCustomShape::NbcResize uses the inherited SdrTextObj::NbcResize. But a SdrTextObj does not know fObjectRotation. Explicit update to new rotation angle after resize is needed. The error became visible, if you changed width or height of a rotated or sheared custom shape in the Position&Size dialog. Then the shape handles were not on the shape outline. Change-Id: Idbe47a3b1ef2b34e9645d62830cb330f2e49bd3e Reviewed-on: https://gerrit.libreoffice.org/c/core/+/107792 Tested-by: Jenkins Reviewed-by: Regina Henschel --- svx/qa/unit/customshapes.cxx | 82 ++++++++++++++++++ .../data/tdf138945_resizeRotatedShape.odg | Bin 0 -> 9457 bytes svx/source/svdraw/svdoashp.cxx | 24 +++++ 3 files changed, 106 insertions(+) create mode 100644 svx/qa/unit/data/tdf138945_resizeRotatedShape.odg diff --git a/svx/qa/unit/customshapes.cxx b/svx/qa/unit/customshapes.cxx index 737ab5bdf6d0..e3a5e0ac92a3 100644 --- a/svx/qa/unit/customshapes.cxx +++ b/svx/qa/unit/customshapes.cxx @@ -90,6 +90,88 @@ sal_uInt8 CustomshapesTest::countShapes() return xDrawPage->getCount(); } +void lcl_AssertRectEqualWithTolerance(const OString& sInfo, const tools::Rectangle& rExpected, + const tools::Rectangle& rActual, const sal_Int32 nTolerance) +{ + // Left + OString sMsg = sInfo + " Left expected " + OString::number(rExpected.Left()) + " actual " + + OString::number(rActual.Left()) + " Tolerance " + OString::number(nTolerance); + CPPUNIT_ASSERT_MESSAGE(sMsg.getStr(), + std::abs(rExpected.Left() - rActual.Left()) <= nTolerance); + + // Top + sMsg = sInfo + " Top expected " + OString::number(rExpected.Top()) + " actual " + + OString::number(rActual.Top()) + " Tolerance " + OString::number(nTolerance); + CPPUNIT_ASSERT_MESSAGE(sMsg.getStr(), std::abs(rExpected.Top() - rActual.Top()) <= nTolerance); + + // Width + sMsg = sInfo + " Width expected " + OString::number(rExpected.GetWidth()) + " actual " + + OString::number(rActual.GetWidth()) + " Tolerance " + OString::number(nTolerance); + CPPUNIT_ASSERT_MESSAGE(sMsg.getStr(), + std::abs(rExpected.GetWidth() - rActual.GetWidth()) <= nTolerance); + + // Height + sMsg = sInfo + " Height expected " + OString::number(rExpected.GetHeight()) + " actual " + + OString::number(rActual.GetHeight()) + " Tolerance " + OString::number(nTolerance); + CPPUNIT_ASSERT_MESSAGE(sMsg.getStr(), + std::abs(rExpected.GetHeight() - rActual.GetHeight()) <= nTolerance); +} + +CPPUNIT_TEST_FIXTURE(CustomshapesTest, testResizeRotatedShape) +{ + // tdf#138945 Setting width or height for a rotated or sheared shape in the Position&Size dialog + // had resulted in a mismatch of handle position and shape outline. That becomes visible in object + // properties as mismatch of frame rectangle and bound rectangle. + // Problem was, that fObjectRotation was not updated. + + // Load document and get shape. It is a rectangle custom shape with 45° shear and 330° rotation. + OUString aURL + = m_directories.getURLFromSrc(sDataDirectory) + "tdf138945_resizeRotatedShape.odg"; + mxComponent = loadFromDesktop(aURL, "com.sun.star.comp.presentation.PresentationDocument"); + CPPUNIT_ASSERT_MESSAGE("Could not load document", mxComponent.is()); + uno::Reference xShape(getShape(0)); + + // Change height and mirror vertical + { + SdrObjCustomShape& rSdrShape( + static_cast(*GetSdrObjectFromXShape(xShape))); + rSdrShape.NbcResize(rSdrShape.GetRelativePos(), Fraction(1.0), Fraction(-0.5)); + tools::Rectangle aSnapRect(rSdrShape.GetSnapRect()); + tools::Rectangle aBoundRect(rSdrShape.GetCurrentBoundRect()); + lcl_AssertRectEqualWithTolerance("height changed, mirror vert", aSnapRect, aBoundRect, 3); + } + + // Change height + { + SdrObjCustomShape& rSdrShape( + static_cast(*GetSdrObjectFromXShape(xShape))); + rSdrShape.NbcResize(rSdrShape.GetRelativePos(), Fraction(1.0), Fraction(2.0)); + tools::Rectangle aSnapRect(rSdrShape.GetSnapRect()); + tools::Rectangle aBoundRect(rSdrShape.GetCurrentBoundRect()); + lcl_AssertRectEqualWithTolerance("height changed", aSnapRect, aBoundRect, 3); + } + + // Change width + { + SdrObjCustomShape& rSdrShape( + static_cast(*GetSdrObjectFromXShape(xShape))); + rSdrShape.NbcResize(rSdrShape.GetRelativePos(), Fraction(2.0), Fraction(1.0)); + tools::Rectangle aSnapRect(rSdrShape.GetSnapRect()); + tools::Rectangle aBoundRect(rSdrShape.GetCurrentBoundRect()); + lcl_AssertRectEqualWithTolerance("width changed", aSnapRect, aBoundRect, 3); + } + + // Change width and mirror horizontal + { + SdrObjCustomShape& rSdrShape( + static_cast(*GetSdrObjectFromXShape(xShape))); + rSdrShape.NbcResize(rSdrShape.GetRelativePos(), Fraction(-0.5), Fraction(1.0)); + tools::Rectangle aSnapRect(rSdrShape.GetSnapRect()); + tools::Rectangle aBoundRect(rSdrShape.GetCurrentBoundRect()); + lcl_AssertRectEqualWithTolerance("width changed, mirror hori", aSnapRect, aBoundRect, 3); + } +} + CPPUNIT_TEST_FIXTURE(CustomshapesTest, testViewBoxLeftTop) { // tdf#121890 formula values "left" and "top" are wrongly calculated diff --git a/svx/qa/unit/data/tdf138945_resizeRotatedShape.odg b/svx/qa/unit/data/tdf138945_resizeRotatedShape.odg new file mode 100644 index 0000000000000000000000000000000000000000..20a2825af7fe0d2088d7171d905daf54e09a18d3 GIT binary patch literal 9457 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 YHLr@Y&@fNcP#<4(k9^fvlBc`>1BM8@?*IS* literal 0 HcmV?d00001 diff --git a/svx/source/svdraw/svdoashp.cxx b/svx/source/svdraw/svdoashp.cxx index 35812345b27b..30552b63fa4d 100644 --- a/svx/source/svdraw/svdoashp.cxx +++ b/svx/source/svdraw/svdoashp.cxx @@ -1525,6 +1525,30 @@ void SdrObjCustomShape::NbcResize( const Point& rRef, const Fraction& rxFact, co { } } + + // updating fObjectRotation + tools::Long nTextObjRotation = aGeo.nRotationAngle; + double fAngle = nTextObjRotation; + fAngle /= 100.0; + if (IsMirroredX()) + { + 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(); }