include/svx/svdgeodata.hxx     |   15 +++
 include/svx/svdobj.hxx         |    1 
 include/svx/svdtrans.hxx       |   21 +++--
 svx/qa/unit/svdraw.cxx         |  107 +++++++++++++++++++++++++++
 svx/source/svdraw/svdobj.cxx   |   43 +++++++----
 svx/source/svdraw/svdotxtr.cxx |  160 ++++++++++++++++++++++++++---------------
 svx/source/svdraw/svdtrans.cxx |   32 ++++++++
 7 files changed, 299 insertions(+), 80 deletions(-)

New commits:
commit 032e0799423b28cd4512bc863ea54bd527a8b82a
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: Sat May 31 10:30:58 2025 +0200

    svx: change SdrObjGeoData aBoundRectangle using gfx::Range2DLWrap
    
    Change-Id: I13213ea2bdbfc5badb87d1bbd836192b8ae45e72

diff --git a/include/svx/svdgeodata.hxx b/include/svx/svdgeodata.hxx
index 7f5a8b9713a4..c87dacab99a6 100644
--- a/include/svx/svdgeodata.hxx
+++ b/include/svx/svdgeodata.hxx
@@ -23,14 +23,27 @@
 #include <svx/svdglue.hxx>
 #include <tools/gen.hxx>
 #include <optional>
+#include <basegfx/units/Range2DLWrap.hxx>
 
 /**
  * All geometrical data of an arbitrary object for use in undo/redo
  */
 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::optional<SdrGluePointList> moGluePoints;
     bool bMovProt;
diff --git a/include/svx/svdobj.hxx b/include/svx/svdobj.hxx
index 7bb597b60415..c53223601501 100644
--- a/include/svx/svdobj.hxx
+++ b/include/svx/svdobj.hxx
@@ -396,6 +396,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 bf1fa06b92ad..4433c023baa8 100644
--- a/svx/source/svdraw/svdobj.cxx
+++ b/svx/source/svdraw/svdobj.cxx
@@ -959,6 +959,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
@@ -1915,7 +1922,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      ;
@@ -1935,7 +1942,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 9bc0e9c0c60b19d475e8ca55b45829d618251d32
Author:     Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk>
AuthorDate: Sun Mar 5 18:48:23 2023 +0900
Commit:     Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk>
CommitDate: Sat May 31 10:30:57 2025 +0200

    svx: use gfx::Length based types directly in SdrTextObj::NbcResize
    
    Change-Id: I839430b30685994e1767998b353c63b97f461284

diff --git a/svx/source/svdraw/svdotxtr.cxx b/svx/source/svdraw/svdotxtr.cxx
index 0c6183f8ceac..45d2c55e127d 100644
--- a/svx/source/svdraw/svdotxtr.cxx
+++ b/svx/source/svdraw/svdotxtr.cxx
@@ -123,80 +123,102 @@ void SdrTextObj::NbcMove(const Size& rSize)
 
 void SdrTextObj::NbcResize(const Point& rRef, const Fraction& xFact, const 
Fraction& yFact)
 {
-    bool bNotSheared=maGeo.m_nShearAngle==0_deg100;
-    bool bRotate90=bNotSheared && maGeo.m_nRotationAngle.get() % 9000 ==0;
-    bool bXMirr=(xFact.GetNumerator()<0) != (xFact.GetDenominator()<0);
-    bool bYMirr=(yFact.GetNumerator()<0) != (yFact.GetDenominator()<0);
-    if (bXMirr || bYMirr) {
+    bool bNotSheared = maGeo.m_nShearAngle == 0_deg100;
+    bool bRotate90 = bNotSheared && maGeo.m_nRotationAngle.get() % 9000 == 0;
+
+    bool bXMirrored = (xFact.GetNumerator() < 0) != (xFact.GetDenominator() < 
0);
+    bool bYMirrored = (yFact.GetNumerator() < 0) != (yFact.GetDenominator() < 
0);
+
+    double fFactorX = xFact.IsValid() ? double(xFact) : 1.0;
+    double fFactorY = yFact.IsValid() ? double(yFact) : 1.0;
+
+    if (bXMirrored || bYMirrored)
+    {
         Point aRef1(GetSnapRect().Center());
-        if (bXMirr) {
+        if (bXMirrored)
+        {
             Point aRef2(aRef1);
             aRef2.AdjustY( 1 );
             NbcMirrorGluePoints(aRef1,aRef2);
         }
-        if (bYMirr) {
+        if (bYMirrored)
+        {
             Point aRef2(aRef1);
             aRef2.AdjustX( 1 );
             NbcMirrorGluePoints(aRef1,aRef2);
         }
     }
 
-    if (maGeo.m_nRotationAngle==0_deg100 && maGeo.m_nShearAngle==0_deg100) {
-        auto aRectangle = getRectangle();
-        ResizeRect(aRectangle, rRef, xFact, yFact);
-        setRectangle(aRectangle);
-        if (bYMirr)
+    if (maGeo.m_nRotationAngle == 0_deg100 && maGeo.m_nShearAngle == 0_deg100)
+    {
+        auto eUnit = getSdrModelFromSdrObject().getUnit();
+        gfx::Tuple2DL aReference = createTupleFromPoint(rRef, eUnit);
+        svx::resizeRange(maRectangleRange, aReference, fFactorX, fFactorY);
+
+        if (bYMirrored)
         {
-            moveRectangle(aRectangle.Right() - aRectangle.Left(), 
aRectangle.Bottom() - aRectangle.Top());
-            maGeo.m_nRotationAngle=18000_deg100;
+            maRectangleRange.shift(maRectangleRange.getWidth(), 
maRectangleRange.getHeight());
+            maGeo.m_nRotationAngle = 18000_deg100;
             maGeo.RecalcSinCos();
         }
     }
     else
     {
-        tools::Polygon aPol(Rect2Poly(getRectangle(), maGeo));
+        tools::Polygon aPolygon(Rect2Poly(getRectangle(), maGeo));
 
-        for(sal_uInt16 a(0); a < aPol.GetSize(); a++)
+        for (sal_uInt16 a(0); a < aPolygon.GetSize(); a++)
         {
-             ResizePoint(aPol[a], rRef, xFact, yFact);
+             ResizePoint(aPolygon[a], rRef, xFact, yFact);
         }
 
-        if(bXMirr != bYMirr)
+        if (bXMirrored != bYMirrored)
         {
             // turn polygon and move it a little
-            tools::Polygon aPol0(aPol);
+            tools::Polygon aPol0(aPolygon);
 
-            aPol[0] = aPol0[1];
-            aPol[1] = aPol0[0];
-            aPol[2] = aPol0[3];
-            aPol[3] = aPol0[2];
-            aPol[4] = aPol0[1];
+            aPolygon[0] = aPol0[1];
+            aPolygon[1] = aPol0[0];
+            aPolygon[2] = aPol0[3];
+            aPolygon[3] = aPol0[2];
+            aPolygon[4] = aPol0[1];
         }
-        tools::Rectangle aRectangle = svx::polygonToRectangle(aPol, maGeo);
+        tools::Rectangle aRectangle = svx::polygonToRectangle(aPolygon, maGeo);
         setRectangle(aRectangle);
     }
 
-    if (bRotate90) {
-        bool bRota90=maGeo.m_nRotationAngle.get() % 9000 ==0;
-        if (!bRota90) { // there's seems to be a rounding error occurring: 
correct it
-            Degree100 a=NormAngle36000(maGeo.m_nRotationAngle);
-            if (a<4500_deg100) a=0_deg100;
-            else if (a<13500_deg100) a=9000_deg100;
-            else if (a<22500_deg100) a=18000_deg100;
-            else if (a<31500_deg100) a=27000_deg100;
-            else a=0_deg100;
-            maGeo.m_nRotationAngle=a;
+    if (bRotate90)
+    {
+        bool bRota90 = maGeo.m_nRotationAngle.get() % 9000 == 0;
+        if (!bRota90)
+        {
+            // there's seems to be a rounding error occurring: correct it
+
+            Degree100 angle = NormAngle36000(maGeo.m_nRotationAngle);
+            if (angle < 4500_deg100)
+                angle = 0_deg100;
+            else if (angle < 13500_deg100)
+                angle = 9000_deg100;
+            else if (angle < 22500_deg100)
+                angle = 18000_deg100;
+            else if (angle < 31500_deg100)
+                angle = 27000_deg100;
+            else
+                angle = 0_deg100;
+
+            maGeo.m_nRotationAngle = angle;
             maGeo.RecalcSinCos();
         }
-        if (bNotSheared!=(maGeo.m_nShearAngle==0_deg100)) { // correct a 
rounding error occurring with Shear
-            maGeo.m_nShearAngle=0_deg100;
+        if (bNotSheared != (maGeo.m_nShearAngle == 0_deg100))
+        {
+            // correct a rounding error occurring with Shear
+            maGeo.m_nShearAngle = 0_deg100;
             maGeo.RecalcTan();
         }
     }
 
     AdaptTextMinSize();
 
-    if(mbTextFrame && !getSdrModelFromSdrObject().IsPasteResize())
+    if (mbTextFrame && !getSdrModelFromSdrObject().IsPasteResize())
     {
         NbcAdjustTextFrameWidthAndHeight();
     }
commit 644b5d59f939e62b1d1d7ae8ebf675af44ea4604
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: Sat May 31 10:30:57 2025 +0200

    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 4d6c4014e4c8..0c6183f8ceac 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.m_nRotationAngle || maGeo.m_nShearAngle)
@@ -96,8 +108,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 33e84c5cb0046f83c2a6e711237adb87da15c881
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: Sat May 31 10:29:44 2025 +0200

    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 e0677e55f48b..1dab54c7603d 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() + basegfx::fround<tools::Long>((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(basegfx::fround<tools::Long>(rRef.X() + dx * cs + dy * sn));
-    rPnt.setY(basegfx::fround<tools::Long>(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 99333df65655..031a25e28980 100644
--- a/svx/qa/unit/svdraw.cxx
+++ b/svx/qa/unit/svdraw.cxx
@@ -950,6 +950,46 @@ CPPUNIT_TEST_FIXTURE(SvdrawTest, testResizeRect)
         CPPUNIT_ASSERT_EQUAL(tools::Rectangle(6, 6, 10, 10), aRectangle);
     }
 }
+
+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());
+    }
+}
+
 } // end anonymous namespace
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/svdraw/svdotxtr.cxx b/svx/source/svdraw/svdotxtr.cxx
index 30e3d7264e35..4d6c4014e4c8 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.m_nRotationAngle==0_deg100) {
-        maGeo.m_nRotationAngle=NormAngle36000(nAngle);
-        maGeo.mfSinRotationAngle=sn;
-        maGeo.mfCosRotationAngle=cs;
-    } else {
-        maGeo.m_nRotationAngle=NormAngle36000(maGeo.m_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.m_nRotationAngle == 0_deg100)
+    {
+        maGeo.m_nRotationAngle = NormAngle36000(nAngle);
+        maGeo.mfSinRotationAngle = sn;
+        maGeo.mfCosRotationAngle = cs;
+    }
+    else
+    {
+        maGeo.m_nRotationAngle = NormAngle36000(maGeo.m_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 4df9f3075555..3c6d006a6295 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& rPoint, const Point& rRef, double sn, double cs)
+{
+    tools::Long dx = rPoint.X() - rRef.X();
+    tools::Long dy = rPoint.Y() - rRef.Y();
+    rPoint.setX(basegfx::fround(rRef.X() + dx * cs + dy * sn));
+    rPoint.setY(basegfx::fround(rRef.Y() + dy * cs - dx * sn));
+}
 
 void ResizePoly(tools::Polygon& rPoly, const Point& rRef, const Fraction& 
xFact, const Fraction& yFact)
 {
commit 8d29f2da6b126b7ff8408c0dabb4b24a1ec0e0a2
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: Sat May 31 09:54:10 2025 +0200

    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 1d490b1e1158..e0677e55f48b 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
 inline 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 fe3f5e2d96ff..99333df65655 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>
@@ -45,6 +45,8 @@
 
 #include <sdr/contact/objectcontactofobjlistpainter.hxx>
 
+#include <test/unoapixml_test.hxx>
+
 using namespace ::com::sun::star;
 
 namespace
@@ -885,6 +887,69 @@ CPPUNIT_TEST_FIXTURE(SvdrawTest, testVisualSignResize)
     CPPUNIT_ASSERT_LESS(static_cast<sal_Int32>(10000), 
xShape->getSize().Width);
     CPPUNIT_ASSERT_LESS(static_cast<sal_Int32>(10000), 
xShape->getSize().Height);
 }
+
+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);
+    }
+}
 } // end anonymous namespace
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/svdraw/svdobj.cxx b/svx/source/svdraw/svdobj.cxx
index 06900bb082f2..bf1fa06b92ad 100644
--- a/svx/source/svdraw/svdobj.cxx
+++ b/svx/source/svdraw/svdobj.cxx
@@ -33,6 +33,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>
@@ -974,9 +975,8 @@ void SdrObject::RecalcBoundRect()
         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
@@ -1431,24 +1431,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 eb2964dec823..4df9f3075555 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)
 {

Reply via email to