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); }