@@ -75,71 +75,61 @@ function parsePathString(pathString) {
7575 return null ;
7676 }
7777
78- var pth = paths ( pathString ) ;
78+ var paramCounts = { a : 7 , c : 6 , h : 1 , l : 2 , m : 2 , q : 4 , s : 4 , t : 2 , v : 1 , z : 0 } ,
79+ pathComponents = [ ] ;
7980
80- if ( pth . arr ) {
81- return clone ( pth . arr ) ;
82- }
81+ String ( pathString ) . replace ( pathCommand , function ( a , b , c ) {
82+ var params = [ ] ,
83+ name = b . toLowerCase ( ) ;
8384
84- var paramCounts = { a : 7 , c : 6 , h : 1 , l : 2 , m : 2 , q : 4 , s : 4 , t : 2 , v : 1 , z : 0 } ,
85- data = [ ] ;
85+ c . replace ( pathValues , function ( a , b ) {
86+ b && params . push ( + b ) ;
87+ } ) ;
8688
87- if ( isArray ( pathString ) && isArray ( pathString [ 0 ] ) ) { // rough assumption
88- data = clone ( pathString ) ;
89- }
89+ if ( name == 'm' && params . length > 2 ) {
90+ pathComponents . push ( [ b , ...params . splice ( 0 , 2 ) ] ) ;
91+ name = 'l' ;
92+ b = b == 'm' ? 'l' : 'L' ;
93+ }
9094
91- if ( ! data . length ) {
95+ while ( params . length >= paramCounts [ name ] ) {
96+ pathComponents . push ( [ b , ...params . splice ( 0 , paramCounts [ name ] ) ] ) ;
97+ if ( ! paramCounts [ name ] ) {
98+ break ;
99+ }
100+ }
101+ } ) ;
92102
93- String ( pathString ) . replace ( pathCommand , function ( a , b , c ) {
94- var params = [ ] ,
95- name = b . toLowerCase ( ) ;
103+ pathComponents . toString = pathToString ;
96104
97- c . replace ( pathValues , function ( a , b ) {
98- b && params . push ( + b ) ;
99- } ) ;
105+ return pathComponents ;
106+ }
100107
101- if ( name == 'm' && params . length > 2 ) {
102- data . push ( [ b , ...params . splice ( 0 , 2 ) ] ) ;
103- name = 'l' ;
104- b = b == 'm' ? 'l' : 'L' ;
105- }
108+ function isPathAbsolute ( pathComponents ) {
106109
107- while ( params . length >= paramCounts [ name ] ) {
108- data . push ( [ b , ...params . splice ( 0 , paramCounts [ name ] ) ] ) ;
109- if ( ! paramCounts [ name ] ) {
110- break ;
111- }
112- }
113- } ) ;
110+ for ( var i = 0 ; i < pathComponents . length ; i ++ ) {
111+ var command = pathComponents [ i ] [ 0 ] ;
112+ if ( typeof command === 'string' && command !== command . toUpperCase ( ) ) {
113+ return false ;
114+ }
114115 }
115116
116- data . toString = paths . toString ;
117- pth . arr = clone ( data ) ;
118-
119- return data ;
117+ return true ;
120118}
121119
122- function paths ( ps ) {
123- var p = paths . ps = paths . ps || { } ;
124-
125- if ( p [ ps ] ) {
126- p [ ps ] . sleep = 100 ;
127- } else {
128- p [ ps ] = {
129- sleep : 100
130- } ;
120+ function isPathCurve ( pathArray ) {
121+ if ( ! isArray ( pathArray ) || ! pathArray . length ) {
122+ return false ;
131123 }
132124
133- setTimeout ( function ( ) {
134- for ( var key in p ) {
135- if ( hasProperty ( p , key ) && key != ps ) {
136- p [ key ] . sleep -- ;
137- ! p [ key ] . sleep && delete p [ key ] ;
138- }
125+ for ( var i = 0 ; i < pathArray . length ; i ++ ) {
126+ var command = pathArray [ i ] [ 0 ] ;
127+ if ( command !== 'M' && command !== 'C' ) {
128+ return false ;
139129 }
140- } ) ;
130+ }
141131
142- return p [ ps ] ;
132+ return true ;
143133}
144134
145135function rectBBox ( x , y , width , height ) {
@@ -471,20 +461,14 @@ export default function findPathIntersections(path1, path2, justCount) {
471461 return res ;
472462}
473463
464+ function isPathComponents ( path ) {
465+ return isArray ( path ) && isArray ( path [ 0 ] ) ;
466+ }
474467
475468function pathToAbsolute ( pathArray ) {
476- var pth = paths ( pathArray ) ;
477469
478- if ( pth . abs ) {
479- return pathClone ( pth . abs ) ;
480- }
481-
482- if ( ! isArray ( pathArray ) || ! isArray ( pathArray && pathArray [ 0 ] ) ) { // rough assumption
483- pathArray = parsePathString ( pathArray ) ;
484- }
485-
486- if ( ! pathArray || ! pathArray . length ) {
487- return [ [ 'M' , 0 , 0 ] ] ;
470+ if ( isPathAbsolute ( pathArray ) ) {
471+ return pathArray ;
488472 }
489473
490474 var res = [ ] ,
@@ -564,7 +548,6 @@ function pathToAbsolute(pathArray) {
564548 }
565549
566550 res . toString = pathToString ;
567- pth . abs = pathClone ( res ) ;
568551
569552 return res ;
570553}
@@ -787,14 +770,15 @@ function curveBBox(x0, y0, x1, y1, x2, y2, x3, y3) {
787770
788771function pathToCurve ( path ) {
789772
790- var pth = paths ( path ) ;
773+ if ( ! isPathComponents ( path ) ) {
774+ path = parsePathString ( path ) ;
775+ }
791776
792- // return cached curve, if existing
793- if ( pth . curve ) {
794- return pathClone ( pth . curve ) ;
777+ if ( isPathCurve ( path ) ) {
778+ return path ;
795779 }
796780
797- var curvedPath = pathToAbsolute ( path ) ,
781+ var curvedPath = pathClone ( pathToAbsolute ( path ) ) ,
798782 attrs = { x : 0 , y : 0 , bx : 0 , by : 0 , X : 0 , Y : 0 , qx : null , qy : null } ,
799783 processPath = function ( path , d , pathCommand ) {
800784 var nx , ny ;
@@ -918,8 +902,35 @@ function pathToCurve(path) {
918902 attrs . by = toFloat ( seg [ seglen - 3 ] ) || attrs . y ;
919903 }
920904
921- // cache curve
922- pth . curve = pathClone ( curvedPath ) ;
923-
924905 return curvedPath ;
906+ }
907+
908+ /**
909+ * Parses and optimizes a path for use with intersection calculations.
910+ *
911+ * Takes an SVG path string or component array and converts it to an optimized
912+ * internal format. The result can be cached and reused for maximum
913+ * performance in intersection calculations.
914+ *
915+ * This is the recommended way to pre-parse paths for repeated use.
916+ * Paths parsed this way will not be re-parsed when passed to `intersect()`.
917+ *
918+ * @example
919+ *
920+ * import intersect, { parsePath } from 'path-intersection';
921+ *
922+ * // parse once
923+ * const path1 = parsePath('M0,0L100,100');
924+ * const path2 = parsePath('M0,100L100,0');
925+ *
926+ * // cache and reuse
927+ * const result1 = intersect(path1, parsedPath2);
928+ * const result2 = intersect(path2, parsedPath2);
929+ *
930+ * @param {Path } path - the path to parse
931+ *
932+ * @return {PathComponent[] } pre-parsed and optimized path
933+ */
934+ export function parsePath ( path ) {
935+ return pathToCurve ( path ) ;
925936}
0 commit comments