summaryrefslogtreecommitdiff
path: root/basegfx
diff options
context:
space:
mode:
authorNoel Grandin <noel.grandin@collabora.co.uk>2023-09-13 14:27:02 +0200
committerNoel Grandin <noel.grandin@collabora.co.uk>2023-09-13 15:42:37 +0200
commit9f4ccc63346b26d8d774b22124da0842ef18e0bc (patch)
treeadfab5819128940c4eaf3072eeab0d0f97cff7c0 /basegfx
parent747a9838ee53a4d2c005729419047b1ffde0db70 (diff)
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.grandin@collabora.co.uk>
Diffstat (limited to 'basegfx')
-rw-r--r--basegfx/source/polygon/b2dpolygontools.cxx51
1 files changed, 39 insertions, 12 deletions
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)