@@ -5,7 +5,7 @@ use crate::uuid::generate_uuid;
55use  bezier_rs:: BezierHandles ; 
66use  core:: hash:: BuildHasher ; 
77use  dyn_any:: DynAny ; 
8- use  kurbo:: { BezPath ,  PathEl } ; 
8+ use  kurbo:: { BezPath ,  PathEl ,   Point } ; 
99use  std:: collections:: { HashMap ,  HashSet } ; 
1010
1111/// Represents a procedural change to the [`PointDomain`] in [`VectorData`]. 
@@ -556,11 +556,12 @@ where
556556} 
557557
558558pub  struct  AppendBezpath < ' a >  { 
559+ 	first_point :  Option < Point > , 
560+ 	last_point :  Option < Point > , 
559561	first_point_index :  Option < usize > , 
560562	last_point_index :  Option < usize > , 
561563	first_segment_id :  Option < SegmentId > , 
562564	last_segment_id :  Option < SegmentId > , 
563- 	next_handle :  Option < BezierHandles > , 
564565	point_id :  PointId , 
565566	segment_id :  SegmentId , 
566567	vector_data :  & ' a  mut  VectorData , 
@@ -569,79 +570,118 @@ pub struct AppendBezpath<'a> {
569570impl < ' a >  AppendBezpath < ' a >  { 
570571	fn  new ( vector_data :  & ' a  mut  VectorData )  -> Self  { 
571572		Self  { 
573+ 			first_point :  None , 
574+ 			last_point :  None , 
572575			first_point_index :  None , 
573576			last_point_index :  None , 
574577			first_segment_id :  None , 
575578			last_segment_id :  None , 
576- 			next_handle :  None , 
577579			point_id :  vector_data. point_domain . next_id ( ) , 
578580			segment_id :  vector_data. segment_domain . next_id ( ) , 
579581			vector_data, 
580582		} 
581583	} 
582584
583- 	fn  append_path_element ( & mut  self ,  handle :  BezierHandles ,  point :  kurbo:: Point ,  next_element :  Option < & PathEl > )  { 
584- 		if  let  Some ( PathEl :: ClosePath )  = next_element { 
585- 			self . next_handle  = Some ( handle) ; 
585+ 	fn  append_segment_and_close_path ( & mut  self ,  point :  Point ,  handle :  BezierHandles )  { 
586+ 		let  handle = if  self . first_point . unwrap ( )  != point { 
587+ 			// If the first point is not the same as the last point of the path then we append the segment 
588+ 			// with given handle and point and then close the path with linear handle. 
589+ 			self . append_segment ( point,  handle) ; 
590+ 			BezierHandles :: Linear 
586591		}  else  { 
587- 			let  next_point_index = self . vector_data . point_domain . ids ( ) . len ( ) ; 
588- 			self . vector_data . point_domain . push ( self . point_id . next_id ( ) ,  point_to_dvec2 ( point) ) ; 
592+ 			// if the endpoints are the same then we close the path with given handle. 
593+ 			handle
594+ 		} ; 
595+ 
596+ 		// Create a new segment. 
597+ 		let  next_segment_id = self . segment_id . next_id ( ) ; 
598+ 		self . vector_data 
599+ 			. segment_domain 
600+ 			. push ( next_segment_id,  self . last_point_index . unwrap ( ) ,  self . first_point_index . unwrap ( ) ,  handle,  StrokeId :: ZERO ) ; 
601+ 
602+ 		// Create a new region. 
603+ 		let  next_region_id = self . vector_data . region_domain . next_id ( ) ; 
604+ 		let  first_segment_id = self . first_segment_id . unwrap_or ( next_segment_id) ; 
605+ 		let  last_segment_id = next_segment_id; 
606+ 
607+ 		self . vector_data . region_domain . push ( next_region_id,  first_segment_id..=last_segment_id,  FillId :: ZERO ) ; 
608+ 	} 
589609
590- 			 let  next_segment_id =  self . segment_id . next_id ( ) ; 
591- 			 self . vector_data 
592- 				 . segment_domain 
593- 				 . push ( self . segment_id . next_id ( ) ,   self . last_point_index . unwrap ( ) ,  next_point_index ,  handle ,   StrokeId :: ZERO ) ; 
610+ 	fn   append_segment ( & mut   self ,   end_point :   Point ,   handle :   BezierHandles )   { 
611+ 		// Append the point. 
612+ 		let  next_point_index =  self . vector_data . point_domain . ids ( ) . len ( ) ; 
613+ 		let  next_point_id =  self . point_id . next_id ( ) ; 
594614
595- 			self . last_point_index  = Some ( next_point_index) ; 
596- 			self . first_segment_id  = Some ( self . first_segment_id . unwrap_or ( next_segment_id) ) ; 
597- 			self . last_segment_id  = Some ( next_segment_id) ; 
598- 		} 
615+ 		self . vector_data . point_domain . push ( next_point_id,  point_to_dvec2 ( end_point) ) ; 
616+ 
617+ 		// Append the segment. 
618+ 		let  next_segment_id = self . segment_id . next_id ( ) ; 
619+ 		self . vector_data 
620+ 			. segment_domain 
621+ 			. push ( next_segment_id,  self . last_point_index . unwrap ( ) ,  next_point_index,  handle,  StrokeId :: ZERO ) ; 
622+ 
623+ 		// Update the states. 
624+ 		self . last_point  = Some ( end_point) ; 
625+ 		self . last_point_index  = Some ( next_point_index) ; 
626+ 
627+ 		self . first_segment_id  = Some ( self . first_segment_id . unwrap_or ( next_segment_id) ) ; 
628+ 		self . last_segment_id  = Some ( next_segment_id) ; 
599629	} 
600630
601- 	pub  fn  append_bezpath ( vector_data :  & ' a  mut  VectorData ,  bezpath :  BezPath )  { 
602- 		let  mut  this = Self :: new ( vector_data) ; 
631+ 	fn  append_first_point ( & mut  self ,  point :  Point )  { 
632+ 		self . first_point  = Some ( point) ; 
633+ 		self . last_point  = Some ( point) ; 
603634
604- 		let  stroke_id = StrokeId :: ZERO ; 
605- 		let  fill_id = FillId :: ZERO ; 
635+ 		// Append the first point. 
636+ 		let  next_point_index = self . vector_data . point_domain . ids ( ) . len ( ) ; 
637+ 		self . vector_data . point_domain . push ( self . point_id . next_id ( ) ,  point_to_dvec2 ( point) ) ; 
606638
607- 		for  i in  0 ..bezpath. elements ( ) . len ( )  { 
608- 			let  current_element = bezpath. elements ( ) [ i] ; 
609- 			let  next_element = bezpath. elements ( ) . get ( i + 1 ) ; 
639+ 		// Update the state. 
640+ 		self . first_point_index  = Some ( next_point_index) ; 
641+ 		self . last_point_index  = Some ( next_point_index) ; 
642+ 	} 
610643
611- 			match  current_element { 
612- 				kurbo:: PathEl :: MoveTo ( point)  => { 
613- 					let  next_point_index = this. vector_data . point_domain . ids ( ) . len ( ) ; 
614- 					this. vector_data . point_domain . push ( this. point_id . next_id ( ) ,  point_to_dvec2 ( point) ) ; 
615- 					this. first_point_index  = Some ( next_point_index) ; 
616- 					this. last_point_index  = Some ( next_point_index) ; 
644+ 	pub  fn  append_bezpath ( vector_data :  & ' a  mut  VectorData ,  bezpath :  BezPath )  { 
645+ 		let  mut  this = Self :: new ( vector_data) ; 
646+ 		let  mut  elements = bezpath. elements ( ) . iter ( ) . peekable ( ) ; 
647+ 
648+ 		while  let  Some ( element)  = elements. next ( )  { 
649+ 			let  close_path = elements. peek ( ) . is_some_and ( |elm| * * elm == PathEl :: ClosePath ) ; 
650+ 
651+ 			match  * element { 
652+ 				PathEl :: MoveTo ( point)  => this. append_first_point ( point) , 
653+ 				PathEl :: LineTo ( point)  => { 
654+ 					let  handle = BezierHandles :: Linear ; 
655+ 					if  close_path { 
656+ 						this. append_segment_and_close_path ( point,  handle) ; 
657+ 					}  else  { 
658+ 						this. append_segment ( point,  handle) ; 
659+ 					} 
617660				} 
618- 				kurbo:: PathEl :: ClosePath  => match  ( this. first_point_index ,  this. last_point_index )  { 
619- 					( Some ( first_point_index) ,  Some ( last_point_index) )  => { 
620- 						let  next_segment_id = this. segment_id . next_id ( ) ; 
621- 						this. vector_data 
622- 							. segment_domain 
623- 							. push ( next_segment_id,  last_point_index,  first_point_index,  this. next_handle . unwrap_or ( BezierHandles :: Linear ) ,  stroke_id) ; 
624- 
625- 						let  next_region_id = this. vector_data . region_domain . next_id ( ) ; 
626- 						// In case there is only one anchor point. 
627- 						let  first_segment_id = this. first_segment_id . unwrap_or ( next_segment_id) ; 
628- 
629- 						this. vector_data . region_domain . push ( next_region_id,  first_segment_id..=next_segment_id,  fill_id) ; 
661+ 				PathEl :: QuadTo ( point,  point1)  => { 
662+ 					let  handle = BezierHandles :: Quadratic  {  handle :  point_to_dvec2 ( point)  } ; 
663+ 					if  close_path { 
664+ 						this. append_segment_and_close_path ( point1,  handle) ; 
665+ 					}  else  { 
666+ 						this. append_segment ( point1,  handle) ; 
630667					} 
631- 					_ => { 
632- 						error ! ( "Empty bezpath cannot be closed." ) 
668+ 				} 
669+ 				PathEl :: CurveTo ( point,  point1,  point2)  => { 
670+ 					let  handle = BezierHandles :: Cubic  { 
671+ 						handle_start :  point_to_dvec2 ( point) , 
672+ 						handle_end :  point_to_dvec2 ( point1) , 
673+ 					} ; 
674+ 
675+ 					if  close_path { 
676+ 						this. append_segment_and_close_path ( point2,  handle) ; 
677+ 					}  else  { 
678+ 						this. append_segment ( point2,  handle) ; 
633679					} 
634- 				} , 
635- 				kurbo:: PathEl :: LineTo ( point)  => this. append_path_element ( BezierHandles :: Linear ,  point,  next_element) , 
636- 				kurbo:: PathEl :: QuadTo ( handle,  point)  => this. append_path_element ( BezierHandles :: Quadratic  {  handle :  point_to_dvec2 ( handle)  } ,  point,  next_element) , 
637- 				kurbo:: PathEl :: CurveTo ( handle_start,  handle_end,  point)  => this. append_path_element ( 
638- 					BezierHandles :: Cubic  { 
639- 						handle_start :  point_to_dvec2 ( handle_start) , 
640- 						handle_end :  point_to_dvec2 ( handle_end) , 
641- 					} , 
642- 					point, 
643- 					next_element, 
644- 				) , 
680+ 				} 
681+ 				PathEl :: ClosePath  => { 
682+ 					// Already handled using `append_segment_and_close_path()`; 
683+ 					break ; 
684+ 				} 
645685			} 
646686		} 
647687	} 
0 commit comments