Rebased ref, commits from common ancestor: commit 2808e39cc88f54aa87a65da9599ff7dd8350040c Author: Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk> AuthorDate: Sun Mar 5 14:46:10 2023 +0900 Commit: Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk> CommitDate: Sun Mar 5 14:54:23 2023 +0900
svx: use gfx::Length based types directly in SdrTextObj::NbcMove Change-Id: Ib0d4a9f60a2ae7f64d914c7a39aa146fef6a9f74 diff --git a/svx/source/svdraw/svdotxtr.cxx b/svx/source/svdraw/svdotxtr.cxx index b3afdb9a5779..74afe966425f 100644 --- a/svx/source/svdraw/svdotxtr.cxx +++ b/svx/source/svdraw/svdotxtr.cxx @@ -40,6 +40,18 @@ using namespace com::sun::star; +namespace +{ + +gfx::Tuple2DL createTupleFromPoint(Point const& rPoint, gfx::LengthUnit eUnit = gfx::LengthUnit::hmm) +{ + auto x = gfx::Length::from(eUnit, rPoint.X()); + auto y = gfx::Length::from(eUnit, rPoint.Y()); + return gfx::Tuple2DL(x, y); +} + +} // end anonymous + void SdrTextObj::NbcSetSnapRect(const tools::Rectangle& rRect) { if (maGeo.nRotationAngle || maGeo.nShearAngle) @@ -95,8 +107,15 @@ Degree100 SdrTextObj::GetShearAngle(bool /*bVertical*/) const void SdrTextObj::NbcMove(const Size& rSize) { - moveRectangle(rSize.Width(), rSize.Height()); - moveOutRectangle(rSize.Width(), rSize.Height()); + gfx::Tuple2DL aDelta = createTupleFromPoint(Point(rSize.Width(), rSize.Height()), getSdrModelFromSdrObject().getUnit()); + gfx::Length xDelta = aDelta.getX(); + gfx::Length yDelta = aDelta.getY(); + + if (xDelta == 0_emu && yDelta == 0_emu) + return; + + maRectangleRange.shift(xDelta, yDelta); + m_aOutterRange.shift(xDelta, yDelta); maSnapRect.Move(rSize); SetBoundAndSnapRectsDirty(true); } @@ -186,19 +205,6 @@ void SdrTextObj::NbcResize(const Point& rRef, const Fraction& xFact, const Fract SetBoundAndSnapRectsDirty(); } -namespace -{ - -gfx::Tuple2DL createTupleFromPoint(Point const& rPoint, gfx::LengthUnit eUnit = gfx::LengthUnit::hmm) -{ - auto x = gfx::Length::from(eUnit, rPoint.X()); - auto y = gfx::Length::from(eUnit, rPoint.Y()); - return gfx::Tuple2DL(x, y); -} - -} // end anonymous - - void SdrTextObj::NbcRotate(const Point& rRef, Degree100 nAngle, double sn, double cs) { SetGlueReallyAbsolute(true); commit d40210f220d5b5a1c79a90ca5467f4410896ae29 Author: Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk> AuthorDate: Sat Mar 4 22:12:51 2023 +0900 Commit: Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk> CommitDate: Sun Mar 5 14:54:23 2023 +0900 svx: use gfx::Length based types directly in SdrTextObj::NbcRotate Change-Id: Ic5ee712fa7507e016441595f8847649fd18b50ee diff --git a/include/svx/svdtrans.hxx b/include/svx/svdtrans.hxx index e213d5f1ea61..549e84ed9d67 100644 --- a/include/svx/svdtrans.hxx +++ b/include/svx/svdtrans.hxx @@ -46,13 +46,15 @@ SVXCORE_DLLPUBLIC void ResizeRect(tools::Rectangle& rRect, const Point& rRef, co namespace svx { SVXCORE_DLLPUBLIC void resizeRange(gfx::Range2DLWrap& rRange, gfx::Tuple2DL const& rReference, double fFactorX, double fFactorY); +SVXCORE_DLLPUBLIC gfx::Tuple2DL rotatePoint(gfx::Tuple2DL const& rPoint, gfx::Tuple2DL const& rReference, double sinAngle, double cosAngle); } inline void ResizePoint(Point& rPnt, const Point& rRef, const Fraction& xFract, const Fraction& yFract); void ResizePoly(tools::Polygon& rPoly, const Point& rRef, const Fraction& xFact, const Fraction& yFact); void ResizeXPoly(XPolygon& rPoly, const Point& rRef, const Fraction& xFact, const Fraction& yFact); -inline void RotatePoint(Point& rPnt, const Point& rRef, double sn, double cs); +SVXCORE_DLLPUBLIC void RotatePoint(Point& rPnt, const Point& rRef, double sn, double cs); + SVXCORE_DLLPUBLIC void RotatePoly(tools::Polygon& rPoly, const Point& rRef, double sn, double cs); void RotateXPoly(XPolygon& rPoly, const Point& rRef, double sn, double cs); void RotateXPoly(XPolyPolygon& rPoly, const Point& rRef, double sn, double cs); @@ -107,14 +109,6 @@ inline void ResizePoint(Point& rPnt, const Point& rRef, const Fraction& xFract, rPnt.setY(rRef.Y() + FRound( (rPnt.Y() - rRef.Y()) * nyFract )); } -inline void RotatePoint(Point& rPnt, const Point& rRef, double sn, double cs) -{ - tools::Long dx=rPnt.X()-rRef.X(); - tools::Long dy=rPnt.Y()-rRef.Y(); - rPnt.setX(FRound(rRef.X()+dx*cs+dy*sn)); - rPnt.setY(FRound(rRef.Y()+dy*cs-dx*sn)); -} - inline void ShearPoint(Point& rPnt, const Point& rRef, double tn, bool bVShear) { if (!bVShear) { // Horizontal diff --git a/svx/qa/unit/svdraw.cxx b/svx/qa/unit/svdraw.cxx index e513d49284e4..b632fc642aeb 100644 --- a/svx/qa/unit/svdraw.cxx +++ b/svx/qa/unit/svdraw.cxx @@ -734,4 +734,162 @@ CPPUNIT_TEST_FIXTURE(SvdrawTest, testResizeRect) } } +CPPUNIT_TEST_FIXTURE(SvdrawTest, testRotatePoint) +{ + { + auto angle = 18000_deg100; + double angleRadians = toRadians(angle); + Point aPoint(2000, 1000); + Point aReference(1000, 1000); + RotatePoint(aPoint, aReference, std::sin(angleRadians), std::cos(angleRadians)); + + CPPUNIT_ASSERT_EQUAL(Point(0, 1000), aPoint); + } + + { + auto angle = 9000_deg100; + double angleRadians = toRadians(angle); + Point aPoint(2000, 1000); + Point aReference(1000, 1000); + RotatePoint(aPoint, aReference, std::sin(angleRadians), std::cos(angleRadians)); + + CPPUNIT_ASSERT_EQUAL(Point(1000, 0), aPoint); + } + + { + auto angle = 18000_deg100; + double angleRadians = toRadians(angle); + Point aPoint(100, 100); + Point aReference(200, 200); + RotatePoint(aPoint, aReference, std::sin(angleRadians), std::cos(angleRadians)); + + CPPUNIT_ASSERT_EQUAL(Point(300, 300), aPoint); + } +} + +CPPUNIT_TEST_FIXTURE(SvdrawTest, testRectangleObjectMove) +{ + std::unique_ptr<SdrModel> pModel(new SdrModel(nullptr, nullptr, true)); + pModel->GetItemPool().FreezeIdRanges(); + + rtl::Reference<SdrPage> pPage(new SdrPage(*pModel, false)); + pPage->setSize({ 50_cm, 50_cm }); + pModel->InsertPage(pPage.get(), 0); + + tools::Rectangle aRect(Point(), Size(100, 100)); + rtl::Reference<SdrRectObj> pRectangleObject = new SdrRectObj(*pModel, aRect); + pPage->NbcInsertObject(pRectangleObject.get()); + + CPPUNIT_ASSERT_EQUAL(tools::Rectangle(Point(), Size(100, 100)), + pRectangleObject->GetLogicRect()); + pRectangleObject->NbcMove({ 100, 100 }); + CPPUNIT_ASSERT_EQUAL(tools::Rectangle(Point(100, 100), Size(100, 100)), + pRectangleObject->GetLogicRect()); + + pPage->RemoveObject(0); +} + +CPPUNIT_TEST_FIXTURE(SvdrawTest, testRectangleObjectRotate) +{ + std::unique_ptr<SdrModel> pModel(new SdrModel(nullptr, nullptr, true)); + pModel->GetItemPool().FreezeIdRanges(); + + rtl::Reference<SdrPage> pPage(new SdrPage(*pModel, false)); + pPage->setSize({ 50_cm, 50_cm }); + pModel->InsertPage(pPage.get(), 0); + + { + tools::Rectangle aObjectSize(Point(), Size(100, 100)); + rtl::Reference<SdrRectObj> pRectangleObject = new SdrRectObj(*pModel, aObjectSize); + pPage->NbcInsertObject(pRectangleObject.get()); + + CPPUNIT_ASSERT_EQUAL(tools::Rectangle(Point(0, 0), Size(100, 100)), + pRectangleObject->GetLogicRect()); + CPPUNIT_ASSERT_EQUAL(tools::Rectangle(Point(0, 0), Size(100, 100)), + pRectangleObject->GetSnapRect()); + CPPUNIT_ASSERT_EQUAL(tools::Rectangle(Point(-1, -1), Size(102, 102)), + pRectangleObject->GetCurrentBoundRect()); + + auto angle = 9000_deg100; + double angleRadians = toRadians(angle); + pRectangleObject->NbcRotate(aObjectSize.Center(), angle, std::sin(angleRadians), + std::cos(angleRadians)); + + CPPUNIT_ASSERT_EQUAL(tools::Rectangle(Point(0, 98), Size(100, 100)), + pRectangleObject->GetLogicRect()); + CPPUNIT_ASSERT_EQUAL(tools::Rectangle(Point(0, -1), Size(100, 100)), + pRectangleObject->GetSnapRect()); + CPPUNIT_ASSERT_EQUAL(tools::Rectangle(Point(-1, -2), Size(102, 102)), + pRectangleObject->GetCurrentBoundRect()); + + pPage->RemoveObject(0); + } + + { + tools::Rectangle aObjectSize(Point(), Size(100, 100)); + rtl::Reference<SdrRectObj> pRectangleObject = new SdrRectObj(*pModel, aObjectSize); + pPage->NbcInsertObject(pRectangleObject.get()); + + CPPUNIT_ASSERT_EQUAL(tools::Rectangle(Point(0, 0), Size(100, 100)), + pRectangleObject->GetLogicRect()); + CPPUNIT_ASSERT_EQUAL(tools::Rectangle(Point(0, 0), Size(100, 100)), + pRectangleObject->GetSnapRect()); + CPPUNIT_ASSERT_EQUAL(tools::Rectangle(Point(-1, -1), Size(102, 102)), + pRectangleObject->GetCurrentBoundRect()); + + auto angle = -4500_deg100; + double angleRadians = toRadians(angle); + pRectangleObject->NbcRotate(aObjectSize.Center(), angle, std::sin(angleRadians), + std::cos(angleRadians)); + + CPPUNIT_ASSERT_EQUAL(tools::Rectangle(Point(49, -20), Size(100, 100)), + pRectangleObject->GetLogicRect()); + CPPUNIT_ASSERT_EQUAL(tools::Rectangle(Point(-21, -20), Size(141, 141)), + pRectangleObject->GetSnapRect()); + CPPUNIT_ASSERT_EQUAL(tools::Rectangle(Point(-22, -21), Size(143, 143)), + pRectangleObject->GetCurrentBoundRect()); + + pPage->RemoveObject(0); + } +} + +CPPUNIT_TEST_FIXTURE(SvdrawTest, testRotatePoint2D) +{ + { + auto angle = 18000_deg100; + double angleRadians = toRadians(angle); + gfx::Tuple2DL aPoint(2_cm, 1_cm); + gfx::Tuple2DL aReference(1_cm, 1_cm); + aPoint + = svx::rotatePoint(aPoint, aReference, std::sin(angleRadians), std::cos(angleRadians)); + + CPPUNIT_ASSERT_EQUAL(0_cm, aPoint.getX()); + CPPUNIT_ASSERT_EQUAL(1_cm, aPoint.getY()); + } + + { + auto angle = 9000_deg100; + double angleRadians = toRadians(angle); + gfx::Tuple2DL aPoint(2_cm, 1_cm); + gfx::Tuple2DL aReference(1_cm, 1_cm); + aPoint + = svx::rotatePoint(aPoint, aReference, std::sin(angleRadians), std::cos(angleRadians)); + + CPPUNIT_ASSERT_EQUAL(1_cm, aPoint.getX()); + CPPUNIT_ASSERT_EQUAL(0_cm, aPoint.getY()); + } + + { + auto angle = 18000_deg100; + double angleRadians = toRadians(angle); + gfx::Tuple2DL aPoint(1_cm, 1_cm); + gfx::Tuple2DL aReference(2_cm, 2_cm); + aPoint + = svx::rotatePoint(aPoint, aReference, std::sin(angleRadians), std::cos(angleRadians)); + + CPPUNIT_ASSERT_EQUAL(3_cm, aPoint.getX()); + CPPUNIT_ASSERT_EQUAL(3_cm, aPoint.getY()); + } +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/svdraw/svdotxtr.cxx b/svx/source/svdraw/svdotxtr.cxx index f2df68068717..b3afdb9a5779 100644 --- a/svx/source/svdraw/svdotxtr.cxx +++ b/svx/source/svdraw/svdotxtr.cxx @@ -186,28 +186,50 @@ void SdrTextObj::NbcResize(const Point& rRef, const Fraction& xFact, const Fract SetBoundAndSnapRectsDirty(); } +namespace +{ + +gfx::Tuple2DL createTupleFromPoint(Point const& rPoint, gfx::LengthUnit eUnit = gfx::LengthUnit::hmm) +{ + auto x = gfx::Length::from(eUnit, rPoint.X()); + auto y = gfx::Length::from(eUnit, rPoint.Y()); + return gfx::Tuple2DL(x, y); +} + +} // end anonymous + + void SdrTextObj::NbcRotate(const Point& rRef, Degree100 nAngle, double sn, double cs) { SetGlueReallyAbsolute(true); - tools::Rectangle aRectangle = getRectangle(); - tools::Long dx = aRectangle.Right() - aRectangle.Left(); - tools::Long dy = aRectangle.Bottom() - aRectangle.Top(); - Point aPoint1(aRectangle.TopLeft()); - RotatePoint(aPoint1, rRef, sn, cs); - Point aPoint2(aPoint1.X() + dx, aPoint1.Y() + dy); - aRectangle = tools::Rectangle(aPoint1, aPoint2); - setRectangle(aRectangle); + gfx::Tuple2DL aReference = createTupleFromPoint(rRef, getSdrModelFromSdrObject().getUnit()); - if (maGeo.nRotationAngle==0_deg100) { - maGeo.nRotationAngle=NormAngle36000(nAngle); - maGeo.mfSinRotationAngle=sn; - maGeo.mfCosRotationAngle=cs; - } else { - maGeo.nRotationAngle=NormAngle36000(maGeo.nRotationAngle+nAngle); + gfx::Length aWidth = maRectangleRange.getWidth(); + gfx::Length aHeight = maRectangleRange.getHeight(); + + gfx::Tuple2DL aPoint(maRectangleRange.getMinX(), maRectangleRange.getMinY()); + gfx::Tuple2DL aRotated = svx::rotatePoint(aPoint, aReference, sn, cs); + + maRectangleRange = gfx::Range2DLWrap( + aRotated.getX(), + aRotated.getY(), + aRotated.getX() + aWidth, + aRotated.getY() + aHeight); + + if (maGeo.nRotationAngle == 0_deg100) + { + maGeo.nRotationAngle = NormAngle36000(nAngle); + maGeo.mfSinRotationAngle = sn; + maGeo.mfCosRotationAngle = cs; + } + else + { + maGeo.nRotationAngle = NormAngle36000(maGeo.nRotationAngle + nAngle); maGeo.RecalcSinCos(); } + SetBoundAndSnapRectsDirty(); - NbcRotateGluePoints(rRef,nAngle,sn,cs); + NbcRotateGluePoints(rRef, nAngle, sn, cs); SetGlueReallyAbsolute(false); } diff --git a/svx/source/svdraw/svdtrans.cxx b/svx/source/svdraw/svdtrans.cxx index 04b02e9184c6..5afacc34dd9a 100644 --- a/svx/source/svdraw/svdtrans.cxx +++ b/svx/source/svdraw/svdtrans.cxx @@ -75,8 +75,24 @@ void resizeRange(gfx::Range2DLWrap& rRange, gfx::Tuple2DL const& rReference, dou rRange = gfx::Range2DLWrap(left, top, right, bottom, rRange.getUnit()); } +gfx::Tuple2DL rotatePoint(gfx::Tuple2DL const& rPoint, gfx::Tuple2DL const& rReference, double sinAngle, double cosAngle) +{ + gfx::Length dx = rPoint.getX() - rReference.getX(); + gfx::Length dy = rPoint.getY() - rReference.getY(); + gfx::Length x = rReference.getX() + dx * cosAngle + dy * sinAngle; + gfx::Length y = rReference.getY() + dy * cosAngle - dx * sinAngle; + return {x, y}; +} + } // end svx namespace +void RotatePoint(Point& rPnt, const Point& rRef, double sn, double cs) +{ + tools::Long dx=rPnt.X()-rRef.X(); + tools::Long dy=rPnt.Y()-rRef.Y(); + rPnt.setX(FRound(rRef.X()+dx*cs+dy*sn)); + rPnt.setY(FRound(rRef.Y()+dy*cs-dx*sn)); +} void ResizePoly(tools::Polygon& rPoly, const Point& rRef, const Fraction& xFact, const Fraction& yFact) { commit 1119816a7a2c13803777351c86ea2b13a03fb31f Author: Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk> AuthorDate: Tue Feb 21 22:05:02 2023 +0900 Commit: Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk> CommitDate: Sun Mar 5 14:54:23 2023 +0900 svx: change SdrObjGeoData aBoundRectangle using gfx::Range2DLWrap Change-Id: I13213ea2bdbfc5badb87d1bbd836192b8ae45e72 diff --git a/include/svx/svdobj.hxx b/include/svx/svdobj.hxx index 55d800e9852d..9202bd575c3a 100644 --- a/include/svx/svdobj.hxx +++ b/include/svx/svdobj.hxx @@ -173,8 +173,20 @@ public: */ class SVXCORE_DLLPUBLIC SdrObjGeoData { +private: + gfx::Range2DLWrap maBoundRange; + public: - tools::Rectangle aBoundRect; + gfx::Range2DLWrap const& getBoundRange() const + { + return maBoundRange; + } + + void setBoundRange(gfx::Range2DLWrap const& rRange) + { + maBoundRange = rRange; + } + Point aAnchor; std::unique_ptr<SdrGluePointList> pGPL; @@ -185,7 +197,6 @@ public: bool mbVisible; SdrLayerID mnLayerID; -public: SdrObjGeoData(); virtual ~SdrObjGeoData(); }; @@ -417,6 +428,7 @@ public: // non-useful BoundRects sometimes) i rename that method from GetBoundRect() to // GetCurrentBoundRect(). virtual const tools::Rectangle& GetCurrentBoundRect() const; + virtual const gfx::Range2DLWrap& getCurrentBoundRange() const; // To have a possibility to get the last calculated BoundRect e.g for producing // the first rectangle for repaints (old and new need to be used) without forcing diff --git a/svx/source/svdraw/svdobj.cxx b/svx/source/svdraw/svdobj.cxx index 791229023d79..5e7333e1afa3 100644 --- a/svx/source/svdraw/svdobj.cxx +++ b/svx/source/svdraw/svdobj.cxx @@ -932,6 +932,13 @@ const tools::Rectangle& SdrObject::GetCurrentBoundRect() const return getOutRectangle(); } +const gfx::Range2DLWrap& SdrObject::getCurrentBoundRange() const +{ + if (m_aOutterRange.isEmpty()) + const_cast<SdrObject*>(this)->RecalcBoundRect(); + return m_aOutterRange; +} + // To have a possibility to get the last calculated BoundRect e.g for producing // the first rectangle for repaints (old and new need to be used) without forcing // a RecalcBoundRect (which may be problematical and expensive sometimes) I add here @@ -1866,7 +1873,7 @@ std::unique_ptr<SdrObjGeoData> SdrObject::NewGeoData() const void SdrObject::SaveGeoData(SdrObjGeoData& rGeo) const { - rGeo.aBoundRect =GetCurrentBoundRect(); + rGeo.setBoundRange(getCurrentBoundRange()); rGeo.aAnchor =m_aAnchor ; rGeo.bMovProt =m_bMovProt ; rGeo.bSizProt =m_bSizProt ; @@ -1890,7 +1897,7 @@ void SdrObject::SaveGeoData(SdrObjGeoData& rGeo) const void SdrObject::RestoreGeoData(const SdrObjGeoData& rGeo) { SetBoundAndSnapRectsDirty(); - setOutRectangle(rGeo.aBoundRect); + m_aOutterRange = rGeo.getBoundRange(); m_aAnchor =rGeo.aAnchor ; m_bMovProt =rGeo.bMovProt ; m_bSizProt =rGeo.bSizProt ; commit fa1dc625299992ba44fa8d05be8d4d8a23a2ec85 Author: Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk> AuthorDate: Fri Feb 10 18:10:33 2023 +0900 Commit: Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk> CommitDate: Sun Mar 5 14:54:23 2023 +0900 svx: refactor SdrObject resize to use m_aOutterRange directly Change-Id: I77aad10b32a53545c7f7bbf8fd87b914395a5bad diff --git a/include/svx/svdtrans.hxx b/include/svx/svdtrans.hxx index dea845a26bc1..e213d5f1ea61 100644 --- a/include/svx/svdtrans.hxx +++ b/include/svx/svdtrans.hxx @@ -29,6 +29,9 @@ #include <tools/mapunit.hxx> #include <tools/poly.hxx> +#include <basegfx/units/Range2DLWrap.hxx> +#include <basegfx/units/LengthTypes.hxx> + // That maximum shear angle constexpr Degree100 SDRMAXSHEAR(8900); @@ -39,6 +42,12 @@ inline void MovePoly(tools::Polygon& rPoly, const Size& S) { rPoly.Move(S.W void MoveXPoly(XPolygon& rPoly, const Size& S); SVXCORE_DLLPUBLIC void ResizeRect(tools::Rectangle& rRect, const Point& rRef, const Fraction& xFact, const Fraction& yFact); + +namespace svx +{ +SVXCORE_DLLPUBLIC void resizeRange(gfx::Range2DLWrap& rRange, gfx::Tuple2DL const& rReference, double fFactorX, double fFactorY); +} + inline void ResizePoint(Point& rPnt, const Point& rRef, const Fraction& xFract, const Fraction& yFract); void ResizePoly(tools::Polygon& rPoly, const Point& rRef, const Fraction& xFact, const Fraction& yFact); void ResizeXPoly(XPolygon& rPoly, const Point& rRef, const Fraction& xFact, const Fraction& yFact); diff --git a/svx/qa/unit/svdraw.cxx b/svx/qa/unit/svdraw.cxx index 006158bbe49e..e513d49284e4 100644 --- a/svx/qa/unit/svdraw.cxx +++ b/svx/qa/unit/svdraw.cxx @@ -7,7 +7,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#include <test/unoapixml_test.hxx> +#include <basegfx/units/Length.hxx> #include <com/sun/star/beans/XPropertySet.hpp> #include <com/sun/star/drawing/XDrawPagesSupplier.hpp> @@ -38,10 +38,10 @@ #include <sdr/contact/objectcontactofobjlistpainter.hxx> +#include <test/unoapixml_test.hxx> + using namespace ::com::sun::star; -namespace -{ /// Tests for svx/source/svdraw/ code. class SvdrawTest : public UnoApiXmlTest { @@ -669,6 +669,69 @@ CPPUNIT_TEST_FIXTURE(SvdrawTest, testRotatePoint) CPPUNIT_ASSERT_EQUAL(Point(300, 300), aPoint); } } + +CPPUNIT_TEST_FIXTURE(SvdrawTest, testResizeRect) +{ + { + tools::Rectangle aRectangle(1, 1, 10, 10); + Point aReference(1, 1); + ResizeRect(aRectangle, aReference, Fraction(1, 2), Fraction(1, 2)); + + CPPUNIT_ASSERT_EQUAL(tools::Rectangle(1, 1, 6, 6), aRectangle); + } + + { + tools::Rectangle aRectangle(1, 1, 10, 10); + Point aReference(10, 10); + ResizeRect(aRectangle, aReference, Fraction(1, 2), Fraction(1, 2)); + + CPPUNIT_ASSERT_EQUAL(tools::Rectangle(5, 5, 10, 10), aRectangle); + } + + { + gfx::Range2DLWrap aRange(1_hmm, 1_hmm, 10_hmm, 10_hmm); + CPPUNIT_ASSERT_EQUAL(9_hmm, aRange.getWidth()); + CPPUNIT_ASSERT_EQUAL(9_hmm, aRange.getHeight()); + + gfx::Tuple2DL aReference(1_hmm, 1_hmm); + svx::resizeRange(aRange, aReference, 0.5, 0.5); + + CPPUNIT_ASSERT_EQUAL(false, aRange.isEmpty()); + + CPPUNIT_ASSERT_EQUAL(1_hmm, aRange.getMinX()); + CPPUNIT_ASSERT_EQUAL(5.5_hmm, aRange.getMaxX()); + CPPUNIT_ASSERT_EQUAL(1_hmm, aRange.getMinY()); + CPPUNIT_ASSERT_EQUAL(5.5_hmm, aRange.getMaxY()); + + CPPUNIT_ASSERT_EQUAL(4.5_hmm, aRange.getWidth()); + CPPUNIT_ASSERT_EQUAL(4.5_hmm, aRange.getHeight()); + + auto aRectangle = aRange.toToolsRect(); + CPPUNIT_ASSERT_EQUAL(tools::Rectangle(1, 1, 6, 6), aRectangle); + } + + { + gfx::Range2DLWrap aRange(1_hmm, 1_hmm, 10_hmm, 10_hmm); + CPPUNIT_ASSERT_EQUAL(9_hmm, aRange.getWidth()); + CPPUNIT_ASSERT_EQUAL(9_hmm, aRange.getHeight()); + + gfx::Tuple2DL aReference(10_hmm, 10_hmm); + svx::resizeRange(aRange, aReference, 0.5, 0.5); + + CPPUNIT_ASSERT_EQUAL(false, aRange.isEmpty()); + + CPPUNIT_ASSERT_EQUAL(5.5_hmm, aRange.getMinX()); + CPPUNIT_ASSERT_EQUAL(10_hmm, aRange.getMaxX()); + CPPUNIT_ASSERT_EQUAL(5.5_hmm, aRange.getMinY()); + CPPUNIT_ASSERT_EQUAL(10_hmm, aRange.getMaxY()); + + CPPUNIT_ASSERT_EQUAL(4.5_hmm, aRange.getWidth()); + CPPUNIT_ASSERT_EQUAL(4.5_hmm, aRange.getHeight()); + + auto aRectangle = aRange.toToolsRect(); + CPPUNIT_ASSERT_EQUAL(tools::Rectangle(6, 6, 10, 10), aRectangle); + } +} } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/svdraw/svdobj.cxx b/svx/source/svdraw/svdobj.cxx index 514eddd80595..791229023d79 100644 --- a/svx/source/svdraw/svdobj.cxx +++ b/svx/source/svdraw/svdobj.cxx @@ -35,6 +35,7 @@ #include <basegfx/polygon/b2dpolypolygoncutter.hxx> #include <basegfx/polygon/b2dpolypolygontools.hxx> #include <basegfx/units/Range2DLWrap.hxx> +#include <basegfx/units/LengthTypes.hxx> #include <basegfx/range/b2drange.hxx> #include <drawinglayer/processor2d/contourextractor2d.hxx> #include <drawinglayer/processor2d/linegeometryextractor2d.hxx> @@ -946,10 +947,8 @@ void SdrObject::RecalcBoundRect() if ((getSdrModelFromSdrObject().isLocked()) || utl::ConfigManager::IsFuzzing()) return; - auto const& rRectangle = getOutRectangle(); - // central new method which will calculate the BoundRect using primitive geometry - if (!rRectangle.IsEmpty()) + if (!isOutRectangleEmpty()) return; // Use view-independent data - we do not want any connections @@ -1404,24 +1403,32 @@ void SdrObject::NbcMove(const Size& rSize) void SdrObject::NbcResize(const Point& rRef, const Fraction& xFact, const Fraction& yFact) { - bool bXMirr=(xFact.GetNumerator()<0) != (xFact.GetDenominator()<0); - bool bYMirr=(yFact.GetNumerator()<0) != (yFact.GetDenominator()<0); - if (bXMirr || bYMirr) { + bool bXMirror = (xFact.GetNumerator() < 0) != (xFact.GetDenominator() < 0); + bool bYMirror = (yFact.GetNumerator() < 0) != (yFact.GetDenominator() < 0); + if (bXMirror || bYMirror) + { Point aRef1(GetSnapRect().Center()); - if (bXMirr) { + if (bXMirror) + { Point aRef2(aRef1); aRef2.AdjustY( 1 ); - NbcMirrorGluePoints(aRef1,aRef2); + NbcMirrorGluePoints(aRef1, aRef2); } - if (bYMirr) { + if (bYMirror) + { Point aRef2(aRef1); aRef2.AdjustX( 1 ); - NbcMirrorGluePoints(aRef1,aRef2); + NbcMirrorGluePoints(aRef1, aRef2); } } - auto aRectangle = getOutRectangle(); - ResizeRect(aRectangle, rRef, xFact, yFact); - setOutRectangle(aRectangle); + + auto eUnit = getSdrModelFromSdrObject().getUnit(); + gfx::Tuple2DL aReference{ + gfx::Length::from(eUnit, rRef.X()), + gfx::Length::from(eUnit, rRef.Y())}; + double fFactorX = xFact.IsValid() ? double(xFact) : 1.0; + double fFactorY = yFact.IsValid() ? double(yFact) : 1.0; + svx::resizeRange(m_aOutterRange, aReference, fFactorX, fFactorY); SetBoundAndSnapRectsDirty(); } diff --git a/svx/source/svdraw/svdtrans.cxx b/svx/source/svdraw/svdtrans.cxx index ad44aa230e17..04b02e9184c6 100644 --- a/svx/source/svdraw/svdtrans.cxx +++ b/svx/source/svdraw/svdtrans.cxx @@ -61,6 +61,22 @@ void ResizeRect(tools::Rectangle& rRect, const Point& rRef, const Fraction& rxFa rRect.Normalize(); } +namespace svx +{ + +void resizeRange(gfx::Range2DLWrap& rRange, gfx::Tuple2DL const& rReference, double fFactorX, double fFactorY) +{ + auto left = rReference.getX() + ((rRange.getMinX() - rReference.getX()) * fFactorX); + auto right = rReference.getX() + ((rRange.getMaxX() - rReference.getX()) * fFactorX); + + auto top = rReference.getY() + ((rRange.getMinY() - rReference.getY()) * fFactorY); + auto bottom = rReference.getY() + ((rRange.getMaxY() - rReference.getY()) * fFactorY); + + rRange = gfx::Range2DLWrap(left, top, right, bottom, rRange.getUnit()); +} + +} // end svx namespace + void ResizePoly(tools::Polygon& rPoly, const Point& rRef, const Fraction& xFact, const Fraction& yFact) { commit f2b0424936cd69fe272e43294691efb1fa235b9e Author: Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk> AuthorDate: Thu Feb 9 10:03:43 2023 +0900 Commit: Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk> CommitDate: Sun Mar 5 14:54:14 2023 +0900 use Range2DLWrap for the main rectangle in SdrTextObject Change-Id: I0d8ac090f9442fe561b4f87aa767185a987874c4 diff --git a/include/svx/svdotext.hxx b/include/svx/svdotext.hxx index a1cccb0804a4..4861eb3bf5ce 100644 --- a/include/svx/svdotext.hxx +++ b/include/svx/svdotext.hxx @@ -28,6 +28,7 @@ #include <tools/datetime.hxx> #include <svl/style.hxx> #include <svx/svdtext.hxx> +#include <svx/svdmodel.hxx> #include <svx/svxdllapi.h> #include <drawinglayer/primitive2d/Primitive2DContainer.hxx> #include <memory> @@ -165,31 +166,44 @@ protected: // The "aRect" is also the rect of RectObj and CircObj. // When mbTextFrame=true the text will be formatted into this rect // When mbTextFrame=false the text will be centered around its middle - tools::Rectangle maRectangle; + gfx::Range2DLWrap maRectangleRange; tools::Rectangle const& getRectangle() const { - return maRectangle; + return maRectangleRange.toToolsRect(); } void setRectangle(tools::Rectangle const& rRectangle) { - maRectangle = rRectangle; + auto eUnit = getSdrModelFromSdrObject().getUnit(); + maRectangleRange = gfx::Range2DLWrap::create(rRectangle, eUnit); } void setRectangleSize(sal_Int32 nWidth, sal_Int32 nHeight) { - maRectangle.SetSize(Size(nWidth, nHeight)); + auto eUnit = getSdrModelFromSdrObject().getUnit(); + auto width = gfx::Length::from(eUnit, nWidth); + auto height = gfx::Length::from(eUnit, nHeight); + maRectangleRange.setSize(width, height); } void moveRectangle(sal_Int32 nXDelta, sal_Int32 nYDelta) { - maRectangle.Move(nXDelta, nYDelta); + if (nXDelta == 0 && nYDelta == 0) + return; + + auto eUnit = getSdrModelFromSdrObject().getUnit(); + auto xDelta = gfx::Length::from(eUnit, nXDelta); + auto yDelta = gfx::Length::from(eUnit, nYDelta); + maRectangleRange.shift(xDelta, yDelta); } void moveRectanglePosition(sal_Int32 nX, sal_Int32 nY) { - maRectangle.SetPos(Point(nX, nY)); + auto eUnit = getSdrModelFromSdrObject().getUnit(); + auto x = gfx::Length::from(eUnit, nX); + auto y = gfx::Length::from(eUnit, nY); + maRectangleRange.setPosition(x, y); } // The GeoStat contains the rotation and shear angles diff --git a/svx/source/svdraw/svdocirc.cxx b/svx/source/svdraw/svdocirc.cxx index ab8bc58ddf85..020551bcdf5e 100644 --- a/svx/source/svdraw/svdocirc.cxx +++ b/svx/source/svdraw/svdocirc.cxx @@ -706,8 +706,9 @@ bool SdrCircObj::MovCreate(SdrDragStat& rStat) ImpSetCreateParams(rStat); ImpCircUser* pU=static_cast<ImpCircUser*>(rStat.GetUser()); rStat.SetActionRect(pU->aR); - setRectangle(pU->aR); // for ObjName - ImpJustifyRect(maRectangle); + auto aRectangle = pU->aR; + ImpJustifyRect(aRectangle); + setRectangle(aRectangle); // for ObjName nStartAngle=pU->nStart; nEndAngle=pU->nEnd; SetBoundRectDirty(); @@ -1048,8 +1049,9 @@ void SdrCircObj::NbcSetSnapRect(const tools::Rectangle& rRect) NbcResize(maSnapRect.TopLeft(),Fraction(nWdt1,nWdt0),Fraction(nHgt1,nHgt0)); NbcMove(Size(rRect.Left()-aSR0.Left(),rRect.Top()-aSR0.Top())); } else { - setRectangle(rRect); - ImpJustifyRect(maRectangle); + tools::Rectangle aRectangle(rRect); + ImpJustifyRect(aRectangle); + setRectangle(aRectangle); } SetBoundAndSnapRectsDirty(); SetXPolyDirty(); diff --git a/svx/source/svdraw/svdotext.cxx b/svx/source/svdraw/svdotext.cxx index 20e54ca976ac..7b33092dfc48 100644 --- a/svx/source/svdraw/svdotext.cxx +++ b/svx/source/svdraw/svdotext.cxx @@ -101,7 +101,7 @@ SdrTextObj::SdrTextObj(SdrModel& rSdrModel, SdrTextObj const & rSource) // #i25616# mbSupportTextIndentingOnLineWidthChange = true; - maRectangle = rSource.maRectangle; + maRectangleRange = rSource.maRectangleRange; maGeo = rSource.maGeo; maTextSize = rSource.maTextSize; @@ -201,8 +201,6 @@ SdrTextObj::~SdrTextObj() void SdrTextObj::FitFrameToTextSize() { - ImpJustifyRect(maRectangle); - SdrText* pText = getActiveText(); if(pText==nullptr || !pText->GetOutlinerParaObject()) return; diff --git a/svx/source/svdraw/svdotxtr.cxx b/svx/source/svdraw/svdotxtr.cxx index 1454bc52f946..f2df68068717 100644 --- a/svx/source/svdraw/svdotxtr.cxx +++ b/svx/source/svdraw/svdotxtr.cxx @@ -56,9 +56,9 @@ void SdrTextObj::NbcSetSnapRect(const tools::Rectangle& rRect) else { // No rotation or shear. - - setRectangle(rRect); - ImpJustifyRect(maRectangle); + tools::Rectangle aRectangle(rRect); + ImpJustifyRect(aRectangle); + setRectangle(aRectangle); AdaptTextMinSize(); @@ -74,8 +74,9 @@ const tools::Rectangle& SdrTextObj::GetLogicRect() const void SdrTextObj::NbcSetLogicRect(const tools::Rectangle& rRect) { - setRectangle(rRect); - ImpJustifyRect(maRectangle); + tools::Rectangle aRectangle(rRect); + ImpJustifyRect(aRectangle); + setRectangle(aRectangle); AdaptTextMinSize(); @@ -126,7 +127,7 @@ void SdrTextObj::NbcResize(const Point& rRef, const Fraction& xFact, const Fract setRectangle(aRectangle); if (bYMirr) { - maRectangle.Normalize(); + //maRectangle.Normalize(); moveRectangle(aRectangle.Right() - aRectangle.Left(), aRectangle.Bottom() - aRectangle.Top()); maGeo.nRotationAngle=18000_deg100; maGeo.RecalcSinCos(); @@ -174,8 +175,6 @@ void SdrTextObj::NbcResize(const Point& rRef, const Fraction& xFact, const Fract } } - ImpJustifyRect(maRectangle); - AdaptTextMinSize(); if(mbTextFrame && !getSdrModelFromSdrObject().IsPasteResize()) @@ -190,12 +189,13 @@ void SdrTextObj::NbcResize(const Point& rRef, const Fraction& xFact, const Fract void SdrTextObj::NbcRotate(const Point& rRef, Degree100 nAngle, double sn, double cs) { SetGlueReallyAbsolute(true); - tools::Long dx = getRectangle().Right() - getRectangle().Left(); - tools::Long dy = getRectangle().Bottom() - getRectangle().Top(); - Point aPoint1(getRectangle().TopLeft()); + tools::Rectangle aRectangle = getRectangle(); + tools::Long dx = aRectangle.Right() - aRectangle.Left(); + tools::Long dy = aRectangle.Bottom() - aRectangle.Top(); + Point aPoint1(aRectangle.TopLeft()); RotatePoint(aPoint1, rRef, sn, cs); Point aPoint2(aPoint1.X() + dx, aPoint1.Y() + dy); - tools::Rectangle aRectangle(aPoint1, aPoint2); + aRectangle = tools::Rectangle(aPoint1, aPoint2); setRectangle(aRectangle); if (maGeo.nRotationAngle==0_deg100) { @@ -215,16 +215,17 @@ void SdrTextObj::NbcShear(const Point& rRef, Degree100 /*nAngle*/, double tn, bo { SetGlueReallyAbsolute(true); + auto aRectangle = getRectangle(); // when this is a SdrPathObj, aRect may be uninitialized - tools::Polygon aPol(Rect2Poly(getRectangle().IsEmpty() ? GetSnapRect() : getRectangle(), maGeo)); + tools::Polygon aPol(Rect2Poly(aRectangle.IsEmpty() ? GetSnapRect() : aRectangle, maGeo)); sal_uInt16 nPointCount=aPol.GetSize(); for (sal_uInt16 i=0; i<nPointCount; i++) { ShearPoint(aPol[i],rRef,tn,bVShear); } - tools::Rectangle aRectangle = svx::polygonToRectangle(aPol, maGeo); + aRectangle = svx::polygonToRectangle(aPol, maGeo); + ImpJustifyRect(aRectangle); setRectangle(aRectangle); - ImpJustifyRect(maRectangle); if (mbTextFrame) { NbcAdjustTextFrameWidthAndHeight(); @@ -245,7 +246,7 @@ void SdrTextObj::NbcMirror(const Point& rRef1, const Point& rRef2) std::abs(rRef1.X()-rRef2.X())==std::abs(rRef1.Y()-rRef2.Y()))) { bRotate90=maGeo.nRotationAngle.get() % 9000 ==0; } - tools::Polygon aPol(Rect2Poly(getRectangle(),maGeo)); + tools::Polygon aPol(Rect2Poly(getRectangle(), maGeo)); sal_uInt16 i; sal_uInt16 nPointCount=aPol.GetSize(); for (i=0; i<nPointCount; i++) { @@ -279,7 +280,6 @@ void SdrTextObj::NbcMirror(const Point& rRef1, const Point& rRef2) maGeo.RecalcTan(); } - ImpJustifyRect(maRectangle); if (mbTextFrame) { NbcAdjustTextFrameWidthAndHeight(); } diff --git a/svx/source/table/svdotable.cxx b/svx/source/table/svdotable.cxx index 25ab8715d307..b927bfbd2ebe 100644 --- a/svx/source/table/svdotable.cxx +++ b/svx/source/table/svdotable.cxx @@ -842,7 +842,7 @@ SdrTableObj::SdrTableObj(SdrModel& rSdrModel, SdrTableObj const & rSource) TableModelNotifyGuard aGuard( mpImpl.is() ? mpImpl->mxTable.get() : nullptr ); maLogicRect = rSource.maLogicRect; - maRectangle = rSource.maRectangle; + maRectangleRange = rSource.maRectangleRange; maGeo = rSource.maGeo; meTextKind = rSource.meTextKind; mbTextFrame = rSource.mbTextFrame;