@@ -5,6 +5,7 @@ use crate::uuid::generate_uuid;
55use bezier_rs:: BezierHandles ;
66use core:: hash:: BuildHasher ;
77use dyn_any:: DynAny ;
8+ use kurbo:: { BezPath , PathEl } ;
89use std:: collections:: { HashMap , HashSet } ;
910
1011/// Represents a procedural change to the [`PointDomain`] in [`VectorData`].
@@ -552,3 +553,95 @@ where
552553 let visitor = HashMapVisitor { marker : std:: marker:: PhantomData } ;
553554 deserializer. deserialize_seq ( visitor)
554555}
556+
557+ pub struct AppendBezpath < ' a > {
558+ first_point_index : Option < usize > ,
559+ last_point_index : Option < usize > ,
560+ first_segment_id : Option < SegmentId > ,
561+ last_segment_id : Option < SegmentId > ,
562+ next_handle : Option < BezierHandles > ,
563+ point_id : PointId ,
564+ segment_id : SegmentId ,
565+ vector_data : & ' a mut VectorData ,
566+ }
567+
568+ impl < ' a > AppendBezpath < ' a > {
569+ fn new ( vector_data : & ' a mut VectorData ) -> Self {
570+ Self {
571+ first_point_index : None ,
572+ last_point_index : None ,
573+ first_segment_id : None ,
574+ last_segment_id : None ,
575+ next_handle : None ,
576+ point_id : vector_data. point_domain . next_id ( ) ,
577+ segment_id : vector_data. segment_domain . next_id ( ) ,
578+ vector_data,
579+ }
580+ }
581+
582+ fn append_path_element ( & mut self , handle : BezierHandles , point : kurbo:: Point , next_element : Option < & PathEl > ) {
583+ if let Some ( PathEl :: ClosePath ) = next_element {
584+ self . next_handle = Some ( handle) ;
585+ } else {
586+ let next_point_index = self . vector_data . point_domain . ids ( ) . len ( ) ;
587+ self . vector_data . point_domain . push ( self . point_id . next_id ( ) , point_to_dvec2 ( point) ) ;
588+
589+ let next_segment_id = self . segment_id . next_id ( ) ;
590+ self . vector_data
591+ . segment_domain
592+ . push ( self . segment_id . next_id ( ) , self . last_point_index . unwrap ( ) , next_point_index, handle, StrokeId :: ZERO ) ;
593+
594+ self . last_point_index = Some ( next_point_index) ;
595+ self . first_segment_id = Some ( self . first_segment_id . unwrap_or ( next_segment_id) ) ;
596+ self . last_segment_id = Some ( next_segment_id) ;
597+ }
598+ }
599+
600+ pub fn append_bezpath ( vector_data : & ' a mut VectorData , bezpath : BezPath ) {
601+ let mut this = Self :: new ( vector_data) ;
602+
603+ let stroke_id = StrokeId :: ZERO ;
604+ let fill_id = FillId :: ZERO ;
605+
606+ for i in 0 ..bezpath. elements ( ) . len ( ) {
607+ let current_element = bezpath. elements ( ) [ i] ;
608+ let next_element = bezpath. elements ( ) . get ( i + 1 ) ;
609+
610+ match current_element {
611+ kurbo:: PathEl :: MoveTo ( point) => {
612+ let next_point_index = this. vector_data . point_domain . ids ( ) . len ( ) ;
613+ this. vector_data . point_domain . push ( this. point_id . next_id ( ) , point_to_dvec2 ( point) ) ;
614+ this. first_point_index = Some ( next_point_index) ;
615+ this. last_point_index = Some ( next_point_index) ;
616+ }
617+ kurbo:: PathEl :: ClosePath => match ( this. first_point_index , this. last_point_index ) {
618+ ( Some ( first_point_index) , Some ( last_point_index) ) => {
619+ let next_segment_id = this. segment_id . next_id ( ) ;
620+ this. vector_data
621+ . segment_domain
622+ . push ( next_segment_id, last_point_index, first_point_index, this. next_handle . unwrap_or ( BezierHandles :: Linear ) , stroke_id) ;
623+
624+ let next_region_id = this. vector_data . region_domain . next_id ( ) ;
625+ // In case there is only one anchor point.
626+ let first_segment_id = this. first_segment_id . unwrap_or ( next_segment_id) ;
627+
628+ this. vector_data . region_domain . push ( next_region_id, first_segment_id..=next_segment_id, fill_id) ;
629+ }
630+ _ => {
631+ error ! ( "Empty bezpath cannot be closed." )
632+ }
633+ } ,
634+ kurbo:: PathEl :: LineTo ( point) => this. append_path_element ( BezierHandles :: Linear , point, next_element) ,
635+ kurbo:: PathEl :: QuadTo ( handle, point) => this. append_path_element ( BezierHandles :: Quadratic { handle : point_to_dvec2 ( handle) } , point, next_element) ,
636+ kurbo:: PathEl :: CurveTo ( handle_start, handle_end, point) => this. append_path_element (
637+ BezierHandles :: Cubic {
638+ handle_start : point_to_dvec2 ( handle_start) ,
639+ handle_end : point_to_dvec2 ( handle_end) ,
640+ } ,
641+ point,
642+ next_element,
643+ ) ,
644+ }
645+ }
646+ }
647+ }
0 commit comments