svx/source/xoutdev/_xpoly.cxx |   17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)

New commits:
commit dc468362e4c1f8ec518b79dfbd0d927fb5182b65
Author:     Sarper Akdemir <sarper.akde...@allotropia.de>
AuthorDate: Mon Feb 17 14:09:42 2025 +0100
Commit:     Sarper Akdemir <sarper.akde...@allotropia.de>
CommitDate: Mon Mar 31 09:33:50 2025 +0200

    tdf#94699: freehand drawing tool, ignore extremely offsetted control points
    
    Now with the /org.openoffice.Office.Common/Misc/FreehandThresholdPixels 
config
    option, when using low threshold pixels like 1px it is more apparent that
    XPolygon::PointsToBezier will sometimes make the curve shoot off.
    
    Try to counteract by ignoring control points offsetted more then the segment
    length.
    
    Better fix would be changing the PointsToBezier algorithm, but this seems to
    hold OK for now.
    
    Change-Id: I7ab0a67a33e25874ff55af932b3e087bbaad98fb
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/181841
    Tested-by: Jenkins
    Reviewed-by: Sarper Akdemir <sarper.akde...@allotropia.de>

diff --git a/svx/source/xoutdev/_xpoly.cxx b/svx/source/xoutdev/_xpoly.cxx
index 9a2f43415b78..026ae404ca61 100644
--- a/svx/source/xoutdev/_xpoly.cxx
+++ b/svx/source/xoutdev/_xpoly.cxx
@@ -729,8 +729,21 @@ void XPolygon::PointsToBezier(sal_uInt16 nFirst)
     fY2 -= fY1 * fU2 / fT2;
     fY2 -= fY3 * fT2 / (fU2 * 3);
 
-    pPoints[nFirst+1] = Point(static_cast<tools::Long>(fX1), 
static_cast<tools::Long>(fY1));
-    pPoints[nFirst+2] = Point(static_cast<tools::Long>(fX2), 
static_cast<tools::Long>(fY2));
+    Point aControlPoint1(static_cast<tools::Long>(fX1), 
static_cast<tools::Long>(fY1));
+    Point aControlPoint2(static_cast<tools::Long>(fX2), 
static_cast<tools::Long>(fY2));
+
+    auto fPointOffset1 = std::hypot(aControlPoint1.X() - pPoints[nFirst + 
1].X(), aControlPoint1.Y() - pPoints[nFirst + 1].Y());
+    auto fPointOffset2 = std::hypot(aControlPoint2.X() - pPoints[nFirst + 
2].X(), aControlPoint2.Y() - pPoints[nFirst + 2].Y());
+
+    // To prevent the curve from overshooting due to sharp direction changes 
in the given sequence of points,
+    // compare the control point offsets against the full segment length.
+    // Apply the calculated ControlPoints only if their offsets are within a 
reasonable range.
+    if( fPointOffset1 < nFullLength && fPointOffset2 < nFullLength )
+    {
+        pPoints[nFirst + 1] = aControlPoint1;
+        pPoints[nFirst + 2] = aControlPoint2;
+    }
+
     SetFlags(nFirst+1, PolyFlags::Control);
     SetFlags(nFirst+2, PolyFlags::Control);
 }

Reply via email to