From 6c600aacfb97bf61695aca94ff28e8559ccc9f8d Mon Sep 17 00:00:00 2001 From: Andrea Bogazzi Date: Sat, 10 Aug 2024 00:10:11 +0200 Subject: [PATCH] fix(): Fix path Arc parsing regression issue (#10048) --- CHANGELOG.md | 1 + .../path/__snapshots__/index.spec.ts.snap | 327 ++++++++++++++++++ src/util/path/index.spec.ts | 15 +- src/util/path/index.ts | 6 +- 4 files changed, 343 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e968ac3f1d9..3c3d09c9f71 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## [next] +- fix(): Fix path Arc parsing regression issue [#10048](https://github.com/fabricjs/fabric.js/pull/10048) - chore(TS): Update TS to latest [#10044](https://github.com/fabricjs/fabric.js/pull/10044) - feat(): Add has method to classRegistry to allow to check if a class exists. (fixes #10001) diff --git a/src/util/path/__snapshots__/index.spec.ts.snap b/src/util/path/__snapshots__/index.spec.ts.snap index ca6342284bf..5bf39ccb1aa 100644 --- a/src/util/path/__snapshots__/index.spec.ts.snap +++ b/src/util/path/__snapshots__/index.spec.ts.snap @@ -53,3 +53,330 @@ exports[`Path Utils getPathSegmentsInfo operates as expected 1`] = ` }, ] `; + +exports[`Path Utils makePathSimpler can parse paths that return NaN segments 1`] = ` +[ + [ + "M", + 22, + 6.58, + ], + [ + "C", + 21.86757184091244, + 6.561276219544052, + 21.739164165358723, + 6.520726427263932, + 21.62, + 6.46, + ], + [ + "C", + 21.62, + 6.26, + 21.740000000000002, + 6.26, + 21.71, + 5.96, + ], + [ + "L", + 21.71, + 5.9, + ], + [ + "C", + 21.71, + 5.99, + 21.71, + 6, + 21.650000000000002, + 5.9, + ], + [ + "C", + 21.590000000000003, + 5.800000000000001, + 21.55, + 5.61, + 21.580000000000002, + 5.46, + ], + [ + "C", + 21.610000000000003, + 5.31, + 21.76, + 5.65, + 21.720000000000002, + 5.28, + ], + [ + "C", + 21.650000000000002, + 5.28, + 21.51, + 5.08, + 21.51, + 5.28, + ], + [ + "L", + 21.560000000000002, + 5.28, + ], + [ + "L", + 21.560000000000002, + 5.73, + ], + [ + "C", + 21.560000000000002, + 5.57, + 21.490000000000002, + 5.840000000000001, + 21.44, + 5.58, + ], + [ + "C", + 21.44, + 5.53, + 21.5, + 5.53, + 21.52, + 5.49, + ], + [ + "C", + 21.54, + 5.45, + 21.41, + 5.49, + 21.37, + 5.42, + ], + [ + "L", + 21.43, + 5.51, + ], + [ + "C", + 21.41364349396296, + 5.60927934079435, + 21.355351504565153, + 5.69671732489106, + 21.27, + 5.75, + ], + [ + "L", + 21.21, + 5.75, + ], + [ + "C", + 21.21, + 5.65, + 21.1, + 5.64, + 21.11, + 5.46, + ], + [ + "C", + 21.119999999999997, + 5.28, + 21.18, + 5.53, + 21.16, + 5.46, + ], + [ + "C", + 21.16, + 5.22, + 21.1, + 5.46, + 21.05, + 5.25, + ], + [ + "C", + 21.05, + 5.4, + 21, + 5.49, + 21.05, + 5.66, + ], + [ + "C", + 21, + 5.5600000000000005, + 20.98, + 5.8100000000000005, + 20.91, + 5.66, + ], + [ + "C", + 20.91756710278662, + 5.699642118471354, + 20.91756710278662, + 5.740357881528646, + 20.91, + 5.78, + ], + [ + "C", + 20.91, + 5.78, + 20.86, + 5.78, + 20.84, + 5.84, + ], + [ + "L", + 20.84, + 5.84, + ], + [ + "C", + 20.84, + 5.84, + 20.84, + 5.84, + 20.84, + 5.84, + ], + [ + "C", + 20.84, + 5.84, + 20.84, + 5.63, + 20.9, + 5.49, + ], + [ + "L", + 20.9, + 5.49, + ], + [ + "C", + 20.9, + 5.49, + 20.959999999999997, + 5.49, + 20.9, + 5.49, + ], + [ + "L", + 20.9, + 5.390000000000001, + ], + [ + "C", + 20.9, + 5.120000000000001, + 20.97, + 4.8500000000000005, + 20.99, + 4.73, + ], + [ + "L", + 20.99, + 4.87, + ], + [ + "C", + 20.99, + 4.53, + 21.119999999999997, + 4.87, + 21.13, + 4.6, + ], + [ + "C", + 21.13, + 4.6, + 21.13, + 4.67, + 21.13, + 4.68, + ], + [ + "C", + 21.13, + 4.6899999999999995, + 21.13, + 4.239999999999999, + 21.27, + 4.449999999999999, + ], + [ + "L", + 21.27, + 4.609999999999999, + ], + [ + "C", + 21.284655737743563, + 4.503836748916477, + 21.284655737743563, + 4.396163251083522, + 21.27, + 4.289999999999999, + ], + [ + "C", + 21.27, + 4.349999999999999, + 21.27, + 4.419999999999999, + 21.169999999999998, + 4.389999999999999, + ], + [ + "C", + 21.16217733233167, + 4.313532879407623, + 21.16217733233167, + 4.2364671205923745, + 21.169999999999998, + 4.159999999999998, + ], + [ + "L", + 21.169999999999998, + 4.159999999999998, + ], + [ + "L", + 21.169999999999998, + 4.159999999999998, + ], + [ + "L", + 21.169999999999998, + 4.159999999999998, + ], + [ + "C", + 21.164440069923444, + 4.1403864102807, + 21.164440069923444, + 4.119613589719297, + 21.169999999999998, + 4.099999999999999, + ], +] +`; diff --git a/src/util/path/index.spec.ts b/src/util/path/index.spec.ts index 8825446a9f0..77c486ff5c2 100644 --- a/src/util/path/index.spec.ts +++ b/src/util/path/index.spec.ts @@ -1,8 +1,19 @@ -import { getPathSegmentsInfo } from '.'; +import { getPathSegmentsInfo, parsePath, makePathSimpler } from '.'; describe('Path Utils', () => { + describe('makePathSimpler', () => { + test('can parse paths that return NaN segments', () => { + expect( + makePathSimpler( + parsePath( + 'M22,6.58a1.21,1.21,0,0,1-.38-.12c0-.2.12-.2.09-.5l0-.06c0,.09,0,.1-.06,0s-.1-.29-.07-.44.18.19.14-.18c-.07,0-.21-.2-.21,0h.05v.45c0-.16-.07.11-.12-.15,0-.05.06-.05.08-.09s-.11,0-.15-.07l.06.09a.35.35,0,0,1-.16.24h-.06c0-.1-.11-.11-.1-.29s.07.07.05,0c0-.24-.06,0-.11-.21,0,.15-.05.24,0,.41-.05-.1-.07.15-.14,0a.32.32,0,0,1,0,.12s-.05,0-.07.06l0,0s0,0,0,0,0-.21.06-.35h0s.06,0,0,0l0-.1c0-.27.07-.54.09-.66v.14c0-.34.13,0,.14-.27,0,0,0,.07,0,.08s0-.44.14-.23l0,.16a1.17,1.17,0,0,0,0-.32c0,.06,0,.13-.1.1a1.13,1.13,0,0,1,0-.23l0,0v0l0,0a.11.11,0,0,0,0,0,.11.11,0,0,1,0-.06' + ) + ) + ).toMatchSnapshot(); + }); + }); describe('getPathSegmentsInfo', () => { - it('operates as expected', () => { + test('operates as expected', () => { const data = getPathSegmentsInfo([ ['M', 50, 50], ['Q', 50, 50, 75, 75], diff --git a/src/util/path/index.ts b/src/util/path/index.ts index 7fca1dbd576..77f93d64c93 100644 --- a/src/util/path/index.ts +++ b/src/util/path/index.ts @@ -10,7 +10,6 @@ import type { TCurveInfo, TComplexPathData, TParsedAbsoluteCubicCurveCommand, - TParsedCubicCurveCommand, TPathSegmentInfo, TPointAngle, TSimpleParsedCommand, @@ -60,7 +59,7 @@ const segmentToBezier = ( mT: number, fromX: number, fromY: number -): TParsedCubicCurveCommand => { +): TParsedAbsoluteCubicCurveCommand => { const costh1 = cos(theta1), sinth1 = sin(theta1), costh2 = cos(theta2), @@ -145,7 +144,7 @@ const arcToSegments = ( // Convert into cubic bezier segments <= 90deg const segments = Math.ceil(Math.abs((dtheta / PI) * 2)), - result = new Array(segments), + result = [], mDelta = dtheta / segments, mT = ((8 / 3) * Math.sin(mDelta / 4) * Math.sin(mDelta / 4)) / @@ -842,7 +841,6 @@ const rePathCmd = new RegExp(rePathCommand, 'i'); * ['Q', 3, 5, 2, 1, 4, 0], * ['Q', 9, 12, 2, 1, 4, 0], * ]; - * */ export const parsePath = (pathString: string): TComplexPathData => { // clean the string