basegfx/source/polygon/b2dpolygontools.cxx  |   51 +++++++++++++++++++++-------
 include/basegfx/polygon/b2dpolygontools.hxx |    2 -
 2 files changed, 40 insertions(+), 13 deletions(-)

New commits:
commit 9f4ccc63346b26d8d774b22124da0842ef18e0bc
Author:     Noel Grandin <noel.gran...@collabora.co.uk>
AuthorDate: Wed Sep 13 14:27:02 2023 +0200
Commit:     Noel Grandin <noel.gran...@collabora.co.uk>
CommitDate: Wed Sep 13 15:42:37 2023 +0200

    tdf#156995 speed up dragging complex group objects
    
    These shaves 20% of the time of the construction of the "drag view"
    object. Of course, it is still heinously slow.
    
    Change-Id: I4c6ee2d7e0cc2030a9966a281d2fdbe7f6859289
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/156896
    Tested-by: Jenkins
    Reviewed-by: Noel Grandin <noel.gran...@collabora.co.uk>

diff --git a/basegfx/source/polygon/b2dpolygontools.cxx 
b/basegfx/source/polygon/b2dpolygontools.cxx
index 04a22df578a6..56b286403671 100644
--- a/basegfx/source/polygon/b2dpolygontools.cxx
+++ b/basegfx/source/polygon/b2dpolygontools.cxx
@@ -475,7 +475,7 @@ namespace basegfx::utils
             return fRetval;
         }
 
-        double getLength(const B2DPolygon& rCandidate)
+        double getLength(const B2DPolygon& rCandidate, bool 
bApproximateBezierLength)
         {
             double fRetval(0.0);
             const sal_uInt32 nPointCount(rCandidate.count());
@@ -486,18 +486,45 @@ namespace basegfx::utils
 
                 if(rCandidate.areControlPointsUsed())
                 {
-                    B2DCubicBezier aEdge;
-                    aEdge.setStartPoint(rCandidate.getB2DPoint(0));
+                    if (bApproximateBezierLength)
+                    {
+                        B2DPoint aStartPoint = rCandidate.getB2DPoint(0);
 
-                    for(sal_uInt32 a(0); a < nEdgeCount; a++)
+                        for(sal_uInt32 a(0); a < nEdgeCount; a++)
+                        {
+                            // An approximate length of a cubic Bezier curve 
is the average
+                            // of its chord length and the sum of the lengths 
of its control net sides.
+                            const sal_uInt32 nNextIndex((a + 1) % nPointCount);
+                            const B2DPoint& aControlPoint1 = 
rCandidate.getNextControlPoint(a);
+                            const B2DPoint& aControlPoint2 = 
rCandidate.getPrevControlPoint(nNextIndex);
+                            const B2DPoint& aEndPoint = 
rCandidate.getB2DPoint(nNextIndex);
+
+                            double chord_length = B2DVector(aEndPoint - 
aStartPoint).getLength();
+                            double control_net_length = B2DVector(aStartPoint 
- aControlPoint1).getLength()
+                                + B2DVector(aControlPoint2 - 
aControlPoint1).getLength()
+                                + B2DVector(aEndPoint - 
aControlPoint2).getLength();
+                            double approximate_arc_length = 
(control_net_length + chord_length) / 2;
+
+                            fRetval += approximate_arc_length;
+                            aStartPoint = aEndPoint;
+                        }
+
+                    }
+                    else
                     {
-                        const sal_uInt32 nNextIndex((a + 1) % nPointCount);
-                        
aEdge.setControlPointA(rCandidate.getNextControlPoint(a));
-                        
aEdge.setControlPointB(rCandidate.getPrevControlPoint(nNextIndex));
-                        aEdge.setEndPoint(rCandidate.getB2DPoint(nNextIndex));
+                        B2DCubicBezier aEdge;
+                        aEdge.setStartPoint(rCandidate.getB2DPoint(0));
 
-                        fRetval += aEdge.getLength();
-                        aEdge.setStartPoint(aEdge.getEndPoint());
+                        for(sal_uInt32 a(0); a < nEdgeCount; a++)
+                        {
+                            const sal_uInt32 nNextIndex((a + 1) % nPointCount);
+                            
aEdge.setControlPointA(rCandidate.getNextControlPoint(a));
+                            
aEdge.setControlPointB(rCandidate.getPrevControlPoint(nNextIndex));
+                            
aEdge.setEndPoint(rCandidate.getB2DPoint(nNextIndex));
+
+                            fRetval += aEdge.getLength();
+                            aEdge.setStartPoint(aEdge.getEndPoint());
+                        }
                     }
                 }
                 else
@@ -1236,9 +1263,9 @@ namespace basegfx::utils
             // precalculate maximal acceptable length of candidate polygon 
assuming
             // we want to create a maximum of fNumberOfAllowedSnippets. For
             // fNumberOfAllowedSnippets use ca. 65536, double due to line & 
gap.
-            static const double fNumberOfAllowedSnippets(65535.0 * 2.0);
+            static const double fNumberOfAllowedSnippets(100.0 * 2.0);
             const double fAllowedLength((fNumberOfAllowedSnippets * 
fDotDashLength) / double(rDotDashArray.size()));
-            const double 
fCandidateLength(basegfx::utils::getLength(rCandidate));
+            const double 
fCandidateLength(basegfx::utils::getLength(rCandidate, 
/*bApproximateBezierLength*/true));
             std::vector<double> aDotDashArray(rDotDashArray);
 
             if(fCandidateLength > fAllowedLength)
diff --git a/include/basegfx/polygon/b2dpolygontools.hxx 
b/include/basegfx/polygon/b2dpolygontools.hxx
index 2f73b76d33c6..eff5f06a9cff 100644
--- a/include/basegfx/polygon/b2dpolygontools.hxx
+++ b/include/basegfx/polygon/b2dpolygontools.hxx
@@ -113,7 +113,7 @@ namespace basegfx::utils
         BASEGFX_DLLPUBLIC double getEdgeLength(const B2DPolygon& rCandidate, 
sal_uInt32 nIndex);
 
         /** get length of polygon */
-        BASEGFX_DLLPUBLIC double getLength(const B2DPolygon& rCandidate);
+        BASEGFX_DLLPUBLIC double getLength(const B2DPolygon& rCandidate, bool 
bApproximateBezierLength = false);
 
         // get position on polygon for absolute given distance. If
         // length is given, it is assumed the correct polygon length, if 0.0 
it is calculated

Reply via email to