@@ -5,6 +5,7 @@ use crate::uuid::generate_uuid;
5
5
use bezier_rs:: BezierHandles ;
6
6
use core:: hash:: BuildHasher ;
7
7
use dyn_any:: DynAny ;
8
+ use kurbo:: { BezPath , PathEl } ;
8
9
use std:: collections:: { HashMap , HashSet } ;
9
10
10
11
/// Represents a procedural change to the [`PointDomain`] in [`VectorData`].
@@ -552,3 +553,95 @@ where
552
553
let visitor = HashMapVisitor { marker : std:: marker:: PhantomData } ;
553
554
deserializer. deserialize_seq ( visitor)
554
555
}
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