index/objects/
vector_object.rs

1use std::{rc::Rc, sync::Arc};
2
3use base64::{prelude::BASE64_STANDARD, Engine};
4use usvg::{ImageHrefResolver, ImageKind};
5use wasm_bindgen::{prelude::*, throw_str};
6use crate::{objects::geometry::triangle::EquilateralTriangle, utils::{bezier::CubicBezierTuple, bounding_box::BoundingBox, console::log, font_face::FontFace, image_library::ImageLibrary, interpolation::IntegerLerp, linear_algebra::TransformationMatrix, point2d::{Path2D, Point2D}, style::{Color, ImageBitmap, Style}}};
7
8use super::geometry::rectangle::Rectangle;
9
10/// A VectorObject is a vector object that can be drawn on a vector graphics canvas.
11#[wasm_bindgen]
12#[derive(Clone, Debug)]
13pub struct VectorObject {
14    /// The path of the vector object.
15    path: Path2D,
16    /// The fill style of the vector object.
17    fill: Style,
18    /// The fill rule of the vector object.
19    fill_rule: Rc<String>,
20    /// The stroke style of the vector object.
21    stroke: Style,
22    /// The stroke width of the vector object.
23    stroke_width: f32,
24    /// The stroke line cap of the vector object.
25    stroke_line_cap: Rc<String>,
26    /// The stroke line join of the vector object.
27    stroke_line_join: Rc<String>,
28    /// The stroke miter limit of the vector object.
29    stroke_miter_limit: f32,
30    /// The stroke dash offset of the vector object.
31    stroke_dash_offset: f32,
32    /// The stroke dash array of the vector object.
33    stroke_dash_array: Rc<Vec<f32>>,
34    /// The children of the vector object.
35    children: Vec<VectorObject>,
36    /// Name of the vector object.
37    name: Option<Rc<String>>,
38    /// Transform matrix of the vector object.
39    transform: TransformationMatrix,
40}
41
42#[derive(Clone)]
43pub struct VectorOperationList {
44    operations: Vec<&'static dyn VectorOperation>,
45}
46
47impl VectorOperationList {
48    pub fn new() -> VectorOperationList {
49        VectorOperationList {
50            operations: Vec::new(),
51        }
52    }
53    pub fn add_operation(&mut self, operation: &'static dyn VectorOperation) {
54        self.operations.push(operation);
55    }
56    pub fn apply_and_return(&self, object: &mut VectorObject) -> VectorObject {
57        self.apply(object);
58        object.clone()
59    }
60}
61
62impl VectorOperation for VectorOperationList {
63    fn apply(&self, object: &mut VectorObject) {
64        for operation in &self.operations {
65            operation.apply(object);
66        }
67    }
68}
69
70pub trait VectorOperation {
71    fn apply(&self, object: &mut VectorObject);
72}
73
74pub struct Shift {
75    pub dx: f32,
76    pub dy: f32,
77    pub recursive: Option<bool>,
78}
79
80impl VectorOperation for Shift {
81    fn apply(&self, object: &mut VectorObject) {
82        let apply_transform = ApplyTransform {
83            matrix: TransformationMatrix::translate(self.dx, self.dy),
84            recursive: self.recursive,
85        };
86        apply_transform.apply(object);
87    }
88}
89
90pub struct MoveTo {
91    pub point: Point2D,
92    pub recursive: Option<bool>,
93}
94
95impl VectorOperation for MoveTo {
96    fn apply(&self, object: &mut VectorObject) {
97        let center = object.center();
98        if center.is_none() {
99            return;
100        }
101        let center = center.unwrap();
102        let shift = self.point - center;
103        let shift = Shift {
104            dx: shift.x,
105            dy: shift.y,
106            recursive: self.recursive,
107        };
108        shift.apply(object);
109    }
110}
111
112pub struct Scale {
113    pub factor_x: f32,
114    pub factor_y: f32,
115    pub about_point: Option<Point2D>,
116    pub recursive: Option<bool>,
117}
118
119impl VectorOperation for Scale {
120    fn apply(&self, object: &mut VectorObject) {
121        let about_point = if let Some(point) = self.about_point {
122            point
123        } else {
124            object.bounding_box(self.recursive).unwrap().center()
125        };
126        let shift = Shift {
127            dx: -about_point.x,
128            dy: -about_point.y,
129            recursive: self.recursive,
130        };
131        shift.apply(object);
132        let apply_transform = ApplyTransform {
133            matrix: TransformationMatrix::scale(self.factor_x, self.factor_y),
134            recursive: self.recursive,
135        };
136        apply_transform.apply(object);
137        let shift = Shift {
138            dx: about_point.x,
139            dy: about_point.y,
140            recursive: self.recursive,
141        };
142        shift.apply(object);
143    }
144}
145
146pub struct ScaleToWidth {
147    pub width: f32,
148    pub stretch: Option<bool>,
149    pub about_point: Option<Point2D>,
150    pub recursive: Option<bool>,
151}
152
153impl VectorOperation for ScaleToWidth {
154    fn apply(&self, object: &mut VectorObject) {
155        let bounding_box = object.bounding_box(self.recursive);
156        if bounding_box.is_none() {
157            return;
158        }
159        let bounding_box = bounding_box.unwrap();
160        let width = bounding_box.width();
161        if width == 0.0 {
162            return;
163        }
164        let factor_x = self.width / width;
165        let factor_y = if self.stretch.unwrap_or(false) {
166            1.0
167        } else {
168            factor_x
169        };
170        let scale = Scale {
171            factor_x: factor_x,
172            factor_y: factor_y,
173            about_point: self.about_point,
174            recursive: self.recursive,
175        };
176        scale.apply(object);
177    }
178}
179
180pub struct ScaleToHeight {
181    pub height: f32,
182    pub stretch: Option<bool>,
183    pub about_point: Option<Point2D>,
184    pub recursive: Option<bool>,
185}
186
187impl VectorOperation for ScaleToHeight {
188    fn apply(&self, object: &mut VectorObject) {
189        let bounding_box = object.bounding_box(self.recursive);
190        if bounding_box.is_none() {
191            return;
192        }
193        let bounding_box = bounding_box.unwrap();
194        let height = bounding_box.height();
195        if height == 0.0 {
196            return;
197        }
198        let factor_x = if self.stretch.unwrap_or(false) {
199            1.0
200        } else {
201            self.height / height
202        };
203        let factor_y = self.height / height;
204        let scale = Scale {
205            factor_x: factor_x,
206            factor_y: factor_y,
207            about_point: self.about_point,
208            recursive: self.recursive,
209        };
210        scale.apply(object);
211    }
212}
213
214pub struct Rotate {
215    pub angle: f32,
216    pub from_point: Option<Point2D>,
217    pub recursive: Option<bool>,
218}
219
220impl VectorOperation for Rotate {
221    fn apply(&self, object: &mut VectorObject) {
222        let bounding_box = object.bounding_box(self.recursive);
223        if bounding_box.is_none() {
224            return;
225        }
226        let bounding_box = bounding_box.unwrap();
227        let center = bounding_box.center();
228        let from_point = if let Some(point) = self.from_point {
229            point
230        } else {
231            center
232        };
233        let shift = Shift {
234            dx: -from_point.x,
235            dy: -from_point.y,
236            recursive: self.recursive,
237        };
238        shift.apply(object);
239        let rotate = TransformationMatrix::rotate(self.angle);
240        let apply_transform = ApplyTransform {
241            matrix: rotate,
242            recursive: self.recursive,
243        };
244        apply_transform.apply(object);
245        let shift = Shift {
246            dx: from_point.x,
247            dy: from_point.y,
248            recursive: self.recursive,
249        };
250        shift.apply(object);
251    }
252}
253
254pub struct SetTransform {
255    pub matrix: TransformationMatrix,
256    pub recursive: Option<bool>,
257}
258
259impl VectorOperation for SetTransform {
260    fn apply(&self, object: &mut VectorObject) {
261        object.transform = self.matrix.clone();
262        if self.recursive.unwrap_or(true) {
263            for child in &mut object.children {
264                let transform = SetTransform {
265                    matrix: self.matrix.clone(),
266                    recursive: Some(true),
267                };
268                transform.apply(child);
269            }
270        }
271    }
272}
273
274pub struct AddChildren {
275    pub children: Vec<VectorObjectBuilder>,
276}
277
278impl VectorOperation for AddChildren {
279    fn apply(&self, object: &mut VectorObject) {
280        for child in &self.children {
281            let child = child.clone().build();
282            object.children.push(child);
283        }
284    }
285}
286
287pub struct RemoveChildByIndex {
288    pub index: usize,
289}
290
291impl VectorOperation for RemoveChildByIndex {
292    fn apply(&self, object: &mut VectorObject) {
293        object.children.remove(self.index);
294    }
295}
296
297pub struct RemoveChildByName {
298    pub name: Rc<String>,
299}
300
301impl VectorOperation for RemoveChildByName {
302    fn apply(&self, object: &mut VectorObject) {
303        object.children.retain(|child| child.name != Some(Rc::clone(&self.name)));
304    }
305}
306
307pub struct MatchStyleProperties {
308    pub vector_object_builder: VectorObjectBuilder,
309}
310
311impl VectorOperation for MatchStyleProperties {
312    fn apply(&self, object: &mut VectorObject) {
313        let vector_object = self.vector_object_builder.clone().build();
314        object.fill = vector_object.fill;
315        object.fill_rule = vector_object.fill_rule;
316        object.stroke = vector_object.stroke;
317        object.stroke_width = vector_object.stroke_width;
318        object.stroke_line_cap = vector_object.stroke_line_cap;
319        object.stroke_line_join = vector_object.stroke_line_join;
320        object.stroke_miter_limit = vector_object.stroke_miter_limit;
321        object.stroke_dash_offset = vector_object.stroke_dash_offset;
322        object.stroke_dash_array = vector_object.stroke_dash_array;
323    }
324}
325
326pub struct BecomePartial {
327    pub start: f32,
328    pub end: f32,
329    pub samples: Option<usize>,
330    pub extra_length: Option<f32>,
331    pub recursive: Option<bool>,
332}
333
334impl VectorOperation for BecomePartial {
335    fn apply(&self, object: &mut VectorObject) {
336        if self.start <= 0.0 && self.end >= 1.0 {
337            return;
338        }
339        if self.recursive.unwrap_or(true) {
340            for child in &mut object.children {
341                let become_partial = BecomePartial {
342                    start: self.start,
343                    end: self.end,
344                    samples: self.samples,
345                    extra_length: self.extra_length,
346                    recursive: Some(true),
347                };
348                become_partial.apply(child);
349            }
350        }
351        let subpaths = object.subpaths();
352        let mut max_length = None;
353        for subpath in subpaths {
354            let length = subpath.length(self.samples, self.extra_length);
355            if max_length.is_none() || length > max_length.unwrap() {
356                max_length = Some(length);
357            }
358        }
359        if max_length.is_none() {
360            return;
361        }
362        let max_length = max_length.unwrap();
363        object.stroke_dash_array = Rc::new(vec![max_length * (self.end - self.start), max_length]);
364        object.stroke_dash_offset = -max_length * self.start;
365    }
366}
367
368pub struct PointwiseBecomePartial {
369    pub start: f32,
370    pub end: f32,
371    pub recursive: Option<bool>,
372}
373
374impl VectorOperation for PointwiseBecomePartial {
375    fn apply(&self, object: &mut VectorObject) {
376        if self.recursive.unwrap_or(true) {
377            for child in &mut object.children {
378                let pointwise_become_partial = PointwiseBecomePartial {
379                    start: self.start,
380                    end: self.end,
381                    recursive: Some(true),
382                };
383                pointwise_become_partial.apply(child);
384            }
385        }
386        if self.start <= 0.0 && self.end >= 1.0 {
387            return; 
388        }
389        if self.start == self.end {
390            object.path = Path2D::default();
391            return;
392        }
393        let num_curves = object.num_curves();
394        if num_curves == 0 {
395            return;
396        }
397        let lower = IntegerLerp::new(0.0, num_curves as f32, self.start);
398        let upper = IntegerLerp::new(0.0, num_curves as f32, self.end);
399        let lower_index = lower.index();
400        let lower_remainder = lower.remainder();
401        let upper_index = upper.index();
402        let upper_remainder = upper.remainder();
403        if lower_index == upper_index {
404            let start = lower_remainder;
405            let end = upper_remainder;
406            let set_actual_path = SetActualPath {
407                path: object.actual_path().slice(
408                    4 * lower_index as usize,
409                    (4 * lower_index + 4) as usize,
410                ).partial_bezier_path(start, end),
411            };
412            set_actual_path.apply(object);
413        } else {
414            let mut actual_path = Path2D::fill(Point2D::default(), 4 * (upper_index - lower_index + 1) as usize);
415            actual_path.set_slice(0, 4, object.actual_path().slice(
416                4 * lower_index as usize,
417                (4 * lower_index + 4) as usize,
418            ).partial_bezier_path(lower_remainder, 1.0));
419            actual_path.set_slice(4, actual_path.len() - 4, object.actual_path().slice(
420                (4 * lower_index + 4) as usize,
421                4 * upper_index as usize,
422            ));
423            actual_path.set_slice(actual_path.len() - 4, actual_path.len(), object.actual_path().slice(
424                4 * upper_index as usize,
425                (4 * upper_index + 4) as usize,
426            ).partial_bezier_path(0.0, upper_remainder));
427            let set_actual_path = SetActualPath {
428                path: actual_path,
429            };
430            set_actual_path.apply(object);
431        }
432    }
433}
434
435pub struct MovePoint {
436    pub point: Point2D,
437}
438
439impl VectorOperation for MovePoint {
440    fn apply(&self, object: &mut VectorObject) {
441        if object.num_points() % 4 == 0 {
442            object.path.push(self.point);
443        }
444    }
445}
446
447pub struct LineTo {
448    pub point: Point2D,
449}
450
451impl VectorOperation for LineTo {
452    fn apply(&self, object: &mut VectorObject) {
453        let last_point = object.path[object.path.len() - 1];
454        object.path.push_bezier(CubicBezierTuple::new(last_point, last_point, self.point, self.point));
455    }
456}
457
458pub struct QuadraticCurveTo {
459    pub p1: Point2D,
460    pub p2: Point2D,
461}
462
463impl VectorOperation for QuadraticCurveTo {
464    fn apply(&self, object: &mut VectorObject) {
465        let last_point = object.path[object.path.len() - 1];
466        object.path.push_bezier(CubicBezierTuple::from_quadratic(last_point, self.p1, self.p2));
467    }
468}
469
470pub struct BezierCurveTo {
471    pub p1: Point2D,
472    pub p2: Point2D,
473    pub p3: Point2D,
474}
475
476impl VectorOperation for BezierCurveTo {
477    fn apply(&self, object: &mut VectorObject) {
478        let last_point = object.path[object.path.len() - 1];
479        object.path.push_bezier(CubicBezierTuple::new(last_point, self.p1, self.p2, self.p3));
480    }
481}
482
483pub struct Close {}
484
485impl VectorOperation for Close {
486    fn apply(&self, object: &mut VectorObject) {
487        if object.is_closed() {
488            return;
489        }
490        let line_to = LineTo {
491            point: object.path[0],
492        };
493        line_to.apply(object);
494    }
495}
496
497pub struct FadeFill {
498    pub factor: f32,
499    pub recursive: Option<bool>,
500}
501
502impl VectorOperation for FadeFill {
503    fn apply(&self, object: &mut VectorObject) {
504        object.fill = object.fill.fade(self.factor);
505        if self.recursive.unwrap_or(true) {
506            for child in &mut object.children {
507                let fade = FadeFill {
508                    factor: self.factor,
509                    recursive: Some(true),
510                };
511                fade.apply(child);
512            }
513        }
514    }
515}
516
517pub struct FadeStroke {
518    pub factor: f32,
519    pub recursive: Option<bool>,
520}
521
522impl VectorOperation for FadeStroke {
523    fn apply(&self, object: &mut VectorObject) {
524        object.stroke = object.stroke.fade(self.factor);
525        if self.recursive.unwrap_or(true) {
526            for child in &mut object.children {
527                let fade = FadeStroke {
528                    factor: self.factor,
529                    recursive: Some(true),
530                };
531                fade.apply(child);
532            }
533        }
534    }
535}
536
537pub struct SetPath {
538    pub path: Path2D,
539}
540
541impl VectorOperation for SetPath {
542    fn apply(&self, object: &mut VectorObject) {
543        object.path = self.path.clone();
544    }
545}
546
547pub struct SetActualPath {
548    pub path: Path2D,
549}
550
551impl VectorOperation for SetActualPath {
552    fn apply(&self, object: &mut VectorObject) {
553        // To set the actual path, we must apply the inverse of the current transformation matrix to the path.
554        // Because we want the actual path to be the path that would be drawn if the object were drawn with no transformation matrix.
555        object.path = self.path.transform(&object.transform.inverse());
556    }
557}
558
559pub struct SetFill {
560    pub fill: Style,
561    pub recursive: Option<bool>,
562}
563
564impl VectorOperation for SetFill {
565    fn apply(&self, object: &mut VectorObject) {
566        object.fill = self.fill.clone();
567        if self.recursive.unwrap_or(true) {
568            for child in &mut object.children {
569                let set_fill = SetFill {
570                    fill: self.fill.clone(),
571                    recursive: Some(true),
572                };
573                set_fill.apply(child);
574            }
575        }
576    }
577}
578
579pub struct SetFillRule {
580    pub fill_rule: Rc<String>,
581    pub recursive: Option<bool>,
582}
583
584impl VectorOperation for SetFillRule {
585    fn apply(&self, object: &mut VectorObject) {
586        object.fill_rule = Rc::clone(&self.fill_rule);
587        if self.recursive.unwrap_or(true) {
588            for child in &mut object.children {
589                let set_fill_rule = SetFillRule {
590                    fill_rule: Rc::clone(&self.fill_rule),
591                    recursive: Some(true),
592                };
593                set_fill_rule.apply(child);
594            }
595        }
596    }
597}
598
599pub struct SetStroke {
600    pub stroke: Style,
601    pub recursive: Option<bool>,
602}
603
604impl VectorOperation for SetStroke {
605    fn apply(&self, object: &mut VectorObject) {
606        object.stroke = self.stroke.clone();
607        if self.recursive.unwrap_or(true) {
608            for child in &mut object.children {
609                let set_stroke = SetStroke {
610                    stroke: self.stroke.clone(),
611                    recursive: Some(true),
612                };
613                set_stroke.apply(child);
614            }
615        }
616    }
617}
618
619pub struct SetStrokeWidth {
620    pub stroke_width: f32,
621    pub recursive: Option<bool>,
622}
623
624impl VectorOperation for SetStrokeWidth {
625    fn apply(&self, object: &mut VectorObject) {
626        object.stroke_width = self.stroke_width;
627        if self.recursive.unwrap_or(true) {
628            for child in &mut object.children {
629                let set_stroke_width = SetStrokeWidth {
630                    stroke_width: self.stroke_width,
631                    recursive: Some(true),
632                };
633                set_stroke_width.apply(child);
634            }
635        }
636    }
637}
638
639pub struct SetStrokeLineCap {
640    pub stroke_line_cap: Rc<String>,
641    pub recursive: Option<bool>,
642}
643
644impl VectorOperation for SetStrokeLineCap {
645    fn apply(&self, object: &mut VectorObject) {
646        object.stroke_line_cap = Rc::clone(&self.stroke_line_cap);
647        if self.recursive.unwrap_or(true) {
648            for child in &mut object.children {
649                let set_stroke_line_cap = SetStrokeLineCap {
650                    stroke_line_cap: self.stroke_line_cap.clone(),
651                    recursive: Some(true),
652                };
653                set_stroke_line_cap.apply(child);
654            }
655        }
656    }
657}
658
659pub struct SetStrokeLineJoin {
660    pub stroke_line_join: Rc<String>,
661    pub recursive: Option<bool>,
662}
663
664impl VectorOperation for SetStrokeLineJoin {
665    fn apply(&self, object: &mut VectorObject) {
666        object.stroke_line_join = Rc::clone(&self.stroke_line_join);
667        if self.recursive.unwrap_or(true) {
668            for child in &mut object.children {
669                let set_stroke_line_join = SetStrokeLineJoin {
670                    stroke_line_join: self.stroke_line_join.clone(),
671                    recursive: Some(true),
672                };
673                set_stroke_line_join.apply(child);
674            }
675        }
676    }
677}
678
679pub struct SetStrokeMiterLimit {
680    pub stroke_miter_limit: f32,
681    pub recursive: Option<bool>,
682}
683
684impl VectorOperation for SetStrokeMiterLimit {
685    fn apply(&self, object: &mut VectorObject) {
686        object.stroke_miter_limit = self.stroke_miter_limit;
687        if self.recursive.unwrap_or(true) {
688            for child in &mut object.children {
689                let set_stroke_miter_limit = SetStrokeMiterLimit {
690                    stroke_miter_limit: self.stroke_miter_limit,
691                    recursive: Some(true),
692                };
693                set_stroke_miter_limit.apply(child);
694            }
695        }
696    }
697}
698
699pub struct SetStrokeDashOffset {
700    pub stroke_dash_offset: f32,
701    pub recursive: Option<bool>,
702}
703
704impl VectorOperation for SetStrokeDashOffset {
705    fn apply(&self, object: &mut VectorObject) {
706        object.stroke_dash_offset = self.stroke_dash_offset;
707        if self.recursive.unwrap_or(true) {
708            for child in &mut object.children {
709                let set_stroke_dash_offset = SetStrokeDashOffset {
710                    stroke_dash_offset: self.stroke_dash_offset,
711                    recursive: Some(true),
712                };
713                set_stroke_dash_offset.apply(child);
714            }
715        }
716    }
717}
718
719pub struct SetStrokeDashArray {
720    pub stroke_dash_array: Rc<Vec<f32>>,
721    pub recursive: Option<bool>,
722}
723
724impl VectorOperation for SetStrokeDashArray {
725    fn apply(&self, object: &mut VectorObject) {
726        object.stroke_dash_array = Rc::clone(&self.stroke_dash_array);
727        if self.recursive.unwrap_or(true) {
728            for child in &mut object.children {
729                let set_stroke_dash_array = SetStrokeDashArray {
730                    stroke_dash_array: self.stroke_dash_array.clone(),
731                    recursive: Some(true),
732                };
733                set_stroke_dash_array.apply(child);
734            }
735        }
736    }
737}
738
739pub struct SetChildren {
740    pub children: Vec<VectorObjectBuilder>,
741}
742
743impl VectorOperation for SetChildren {
744    fn apply(&self, object: &mut VectorObject) {
745        object.children = self.children.iter().map(|child| child.clone().build()).collect();
746    }
747}
748
749pub struct SetName {
750    pub name: Option<Rc<String>>,
751}
752
753impl VectorOperation for SetName {
754    fn apply(&self, object: &mut VectorObject) {
755        if let Some(name) = &self.name {
756            object.name = Some(Rc::clone(name));
757        } else {
758            object.name = None;
759        }
760    }
761}
762
763pub struct ActualPathAsPath {
764    pub untransform: Option<bool>,
765    pub recursive: Option<bool>,
766}
767
768impl VectorOperation for ActualPathAsPath {
769    fn apply(&self, object: &mut VectorObject) {
770        object.path = object.actual_path();
771        if self.untransform.unwrap_or(true) {
772            object.transform = TransformationMatrix::identity();
773        }
774        if self.recursive.unwrap_or(true) {
775            for child in &mut object.children {
776                let actual_path_as_path = ActualPathAsPath {
777                    untransform: self.untransform,
778                    recursive: Some(true),
779                };
780                actual_path_as_path.apply(child);
781            }
782        }
783    }
784}
785
786pub struct AddChild {
787    pub child: VectorObjectBuilder,
788}
789
790impl VectorOperation for AddChild {
791    fn apply(&self, object: &mut VectorObject) {
792        let child = self.child.clone().build();
793        object.children.push(child);
794    }
795}
796
797pub struct InsertChild {
798    pub index: usize,
799    pub child: VectorObjectBuilder,
800}
801
802impl VectorOperation for InsertChild {
803    fn apply(&self, object: &mut VectorObject) {
804        object.children.insert(self.index, self.child.clone().build());
805    }
806}
807
808pub struct InsertChildren {
809    pub index: usize,
810    pub children: Vec<VectorObjectBuilder>,
811}
812
813impl VectorOperation for InsertChildren {
814    fn apply(&self, object: &mut VectorObject) {
815        for (i, child) in self.children.iter().enumerate() {
816            object.children.insert(self.index + i, child.clone().build());
817        }
818    }
819}
820
821pub struct RemoveChildrenAtIndices {
822    pub indices: Vec<usize>,
823}
824
825impl VectorOperation for RemoveChildrenAtIndices {
826    fn apply(&self, object: &mut VectorObject) {
827        let mut new_children = Vec::new();
828        for (i, child) in object.children.iter().enumerate() {
829            if !self.indices.contains(&i) {
830                new_children.push(child.clone());
831            }
832        }
833        object.children = new_children;
834    }
835}
836
837pub struct RemoveChildrenByNames {
838    pub names: Vec<String>,
839}
840
841impl VectorOperation for RemoveChildrenByNames {
842    fn apply(&self, object: &mut VectorObject) {
843        object.children.retain(|child| {
844            if let Some(name) = &child.name {
845                !self.names.contains(&name)
846            } else {
847                true
848            }
849        });
850    }
851}
852
853pub struct SetSliceChildren {
854    pub start: usize,
855    pub end: usize,
856    pub children: Vec<VectorObjectBuilder>,
857}
858
859pub struct SetChildrenWithNames {
860    pub names: Vec<String>,
861    pub children: Vec<VectorObjectBuilder>,
862}
863
864impl VectorOperation for SetChildrenWithNames {
865    fn apply(&self, object: &mut VectorObject) {
866        let children = self.children.clone().iter().map(|child| child.clone().build()).collect::<Vec<VectorObject>>();
867        for child in children.iter() {
868            if let Some(name) = &child.name {
869                if self.names.contains(&name) {
870                    object.children.push(child.clone());
871                }
872            }
873        }
874    }
875}
876
877impl VectorOperation for SetSliceChildren {
878    fn apply(&self, object: &mut VectorObject) {
879        object.children.splice(self.start..self.end, self.children.iter().map(|child| child.clone().build()));
880    }
881}
882
883pub struct NextToPoint {
884    pub point: Point2D,
885    pub direction: Option<Point2D>,
886    pub buff: Option<f32>,
887    pub aligned_edge: Option<Point2D>,
888    pub recursive: Option<bool>,
889}
890
891impl VectorOperation for NextToPoint {
892    fn apply(&self, object: &mut VectorObject) {
893        let bounding_box = object.bounding_box(self.recursive);
894        if bounding_box.is_none() {
895            return;
896        }
897        let direction = if let Some(direction) = self.direction {
898            direction
899        } else {
900            Point2D::new(1.0, 0.0)
901        };
902        let buff = self.buff.unwrap_or(0.0);
903        let aligned_edge = if let Some(aligned_edge) = self.aligned_edge {
904            aligned_edge
905        } else {
906            Point2D::new(0.0, 0.0)
907        };
908        let key2 = aligned_edge - direction;
909        let key2_x = key2.x;
910        let key2_y = key2.y;
911        let point_to_align = object.get_critical_point(key2_x, key2_y, self.recursive).unwrap();
912        let shift = self.point - point_to_align + buff * direction;
913        let shift = Shift {
914            dx: shift.x,
915            dy: shift.y,
916            recursive: self.recursive,
917        };
918        shift.apply(object);
919    }
920}
921
922pub struct NextToOther {
923    pub other: VectorObjectBuilder,
924    pub direction: Option<Point2D>,
925    pub buff: Option<f32>,
926    pub aligned_edge: Option<Point2D>,
927    pub recursive: Option<bool>,
928}
929
930impl VectorOperation for NextToOther {
931    fn apply(&self, object: &mut VectorObject) {
932        let bounding_box = object.bounding_box(self.recursive);
933        if bounding_box.is_none() {
934            return;
935        }
936        let other = self.other.clone().build();
937        let other_bounding_box = other.bounding_box(self.recursive);
938        if other_bounding_box.is_none() {
939            return;
940        }
941        let direction = if let Some(direction) = self.direction {
942            direction
943        } else {
944            Point2D::new(1.0, 0.0)
945        };
946        let buff = self.buff.unwrap_or(0.0);
947        let aligned_edge = if let Some(aligned_edge) = self.aligned_edge {
948            aligned_edge
949        } else {
950            Point2D::new(0.0, 0.0)
951        };
952        let key1 = aligned_edge + direction;
953        let key1_x = key1.x;
954        let key1_y = key1.y;
955        let target_point = other.get_critical_point(key1_x, key1_y, self.recursive).unwrap();
956        let next_to_point = NextToPoint {
957            point: target_point,
958            direction: Some(direction),
959            buff: Some(buff),
960            aligned_edge: Some(aligned_edge),
961            recursive: self.recursive,
962        };
963        next_to_point.apply(object);
964    }
965}
966
967pub struct ArrangeChildren {
968    pub direction: Option<Point2D>,
969    pub buff: Option<f32>,
970    pub aligned_edge: Option<Point2D>,
971    pub center: Option<Point2D>,
972    pub recursive: Option<bool>,
973}
974
975impl VectorOperation for ArrangeChildren {
976    fn apply(&self, object: &mut VectorObject) {
977        let buff = self.buff.unwrap_or(0.0);
978        let aligned_edge = if let Some(aligned_edge) = self.aligned_edge {
979            aligned_edge
980        } else {
981            Point2D::new(0.0, 0.0)
982        };
983        let first_child = object.children[0].clone();
984        for i in 1..object.children.len() {
985            object.children[i].apply_operation(&NextToOther {
986                other: VectorObjectBuilder::new(&first_child),
987                direction: self.direction,
988                buff: Some(buff),
989                aligned_edge: Some(aligned_edge),
990                recursive: self.recursive,
991            });
992        }
993        if let Some(center) = self.center {
994            let move_to = MoveTo {
995                point: center,
996                recursive: self.recursive,
997            };
998            move_to.apply(object);
999        }
1000    }
1001}
1002
1003pub struct ReversePath {}
1004
1005impl VectorOperation for ReversePath {
1006    fn apply(&self, object: &mut VectorObject) {
1007        object.path.reverse();
1008    }
1009}
1010
1011pub struct ApplyTransform {
1012    pub matrix: TransformationMatrix,
1013    pub recursive: Option<bool>,
1014}
1015
1016impl VectorOperation for ApplyTransform {
1017    fn apply(&self, object: &mut VectorObject) {
1018        object.transform.apply(&self.matrix);
1019        if self.recursive.unwrap_or(true) {
1020            for child in &mut object.children {
1021                let apply_transform = ApplyTransform {
1022                    matrix: self.matrix.clone(),
1023                    recursive: Some(true),
1024                };
1025                apply_transform.apply(child);
1026            }
1027        }
1028    }
1029}
1030
1031pub struct LerpFill {
1032    pub fill: Style,
1033    pub t: f32,
1034    pub x: Option<f32>,
1035    pub y: Option<f32>,
1036    pub width: Option<f32>,
1037    pub height: Option<f32>,
1038    pub data_width: Option<usize>,
1039    pub data_height: Option<usize>,
1040    pub recursive: Option<bool>,
1041}
1042
1043impl VectorOperation for LerpFill {
1044    fn apply(&self, object: &mut VectorObject) {
1045        let fill = Style::lerp(&object.fill, &self.fill, self.t, self.x, self.y, self.width, self.height, self.data_width, self.data_height);
1046        if fill.is_err() {
1047            throw_str(&fill.unwrap_err());
1048        }
1049        object.fill = fill.unwrap();
1050        if self.recursive.unwrap_or(true) {
1051            for child in &mut object.children {
1052                let lerp_fill = LerpFill {
1053                    fill: self.fill.clone(),
1054                    t: self.t,
1055                    x: self.x,
1056                    y: self.y,
1057                    width: self.width,
1058                    height: self.height,
1059                    data_width: self.data_width,
1060                    data_height: self.data_height,
1061                    recursive: Some(true),
1062                };
1063                lerp_fill.apply(child);
1064            }
1065        }
1066    }
1067}
1068
1069pub struct LerpStroke {
1070    pub stroke: Style,
1071    pub t: f32,
1072    pub x: Option<f32>,
1073    pub y: Option<f32>,
1074    pub width: Option<f32>,
1075    pub height: Option<f32>,
1076    pub data_width: Option<usize>,
1077    pub data_height: Option<usize>,
1078    pub recursive: Option<bool>,
1079}
1080
1081impl VectorOperation for LerpStroke {
1082    fn apply(&self, object: &mut VectorObject) {
1083        let stroke = Style::lerp(&object.stroke, &self.stroke, self.t, self.x, self.y, self.width, self.height, self.data_width, self.data_height);
1084        if stroke.is_err() {
1085            throw_str(&stroke.unwrap_err());
1086        }
1087        object.stroke = stroke.unwrap();
1088        if self.recursive.unwrap_or(true) {
1089            for child in &mut object.children {
1090                let lerp_stroke = LerpStroke {
1091                    stroke: self.stroke.clone(),
1092                    t: self.t,
1093                    x: self.x,
1094                    y: self.y,
1095                    width: self.width,
1096                    height: self.height,
1097                    data_width: self.data_width,
1098                    data_height: self.data_height,
1099                    recursive: Some(true),
1100                };
1101                lerp_stroke.apply(child);
1102            }
1103        }
1104    }
1105}
1106
1107impl Default for VectorObject {
1108    fn default() -> Self {
1109        VectorObject {
1110            path: Path2D::default(),
1111            fill: Style::default(),
1112            fill_rule: Rc::new("nonzero".to_string()),
1113            stroke: Style::default(),
1114            stroke_width: 1.0,
1115            stroke_line_cap: Rc::new("butt".to_string()),
1116            stroke_line_join: Rc::new("miter".to_string()),
1117            stroke_miter_limit: 4.0,
1118            stroke_dash_offset: 0.0,
1119            stroke_dash_array: Rc::new(Vec::new()),
1120            children: Vec::new(),
1121            name: None,
1122            transform: TransformationMatrix::identity(),
1123        }
1124    }
1125}
1126
1127/// A VectorObjectBuilder can be used to build a VectorObject with operations.
1128#[wasm_bindgen]
1129#[derive(Clone)]
1130pub struct VectorObjectBuilder {
1131    /// The vector object being built.
1132    object: Rc<VectorObject>,
1133    /// The operations to apply to the vector object.
1134    ops: VectorOperationList,
1135}
1136
1137impl Default for VectorObjectBuilder {
1138    fn default() -> Self {
1139        VectorObjectBuilder {
1140            object: Rc::new(VectorObject::default()),
1141            ops: VectorOperationList::new(),
1142        }
1143    }
1144}
1145
1146#[wasm_bindgen]
1147impl VectorObjectBuilder {
1148    /// Creates a new VectorObjectBuilder from a VectorObject.
1149    #[wasm_bindgen(constructor, return_description = "A new vector object builder.")]
1150    pub fn new(
1151        #[wasm_bindgen(param_description = "The vector object to start building on.")]
1152        vector_object: &VectorObject
1153    ) -> VectorObjectBuilder {
1154        VectorObjectBuilder {
1155            object: Rc::new(vector_object.clone()),
1156            ops: VectorOperationList::new(),
1157        }
1158    }
1159
1160    /// Returns the default tip shape pointing to the right and centered at the origin as a VectorObjectBuilder.
1161    #[wasm_bindgen(return_description = "The default tip shape pointing to the right and centered at the origin.")]
1162    pub fn default_tip_shape(
1163        #[wasm_bindgen(param_description = "The length of the tip shape.")]
1164        tip_length: f64,
1165    ) -> VectorObjectBuilder {
1166        EquilateralTriangle::new(
1167            Point2D::new(0.0, 0.0),
1168            tip_length as f32,
1169            Some(-std::f32::consts::FRAC_PI_2),
1170        ).vector_object_builder().set_fill(Style::from_color(Color::new(0, 0, 0, 1.0)), None)
1171    }
1172
1173    /// Creates a new VectorObjectBuilder from an SVG string.
1174    #[wasm_bindgen(return_description = "A new vector object builder.")]
1175    pub fn from_svg(
1176        #[wasm_bindgen(param_description = "The SVG string to create the vector object builder from.")]
1177        svg: String,
1178        #[wasm_bindgen(param_description = "Data from font faces to use for text rendering.")]
1179        font_faces: Option<Vec<FontFace>>,
1180        #[wasm_bindgen(param_description = "Image library to use for image rendering.")]
1181        image_library: Option<ImageLibrary>,
1182    ) -> VectorObjectBuilder {
1183        let mut vector_object_builder = VectorObjectBuilder::default();
1184        let mut options = usvg::Options::default();
1185        let mut fontdatabase = options.fontdb.clone();
1186        for font_face in font_faces.unwrap_or_default() {
1187            Arc::make_mut(&mut fontdatabase).load_font_data(font_face.data());
1188        }
1189        let image_library = Box::new(image_library.unwrap_or(ImageLibrary::new()));
1190        let image_library = Box::leak(image_library);
1191        options.image_href_resolver = ImageHrefResolver {
1192            resolve_data: Box::new(|mime, data, _opts| {
1193                // Don't care about the mime type, just return the data.
1194                match mime {
1195                    "image/png" => {
1196                        Some(ImageKind::PNG(data))
1197                    }
1198                    "image/jpeg" | "image/jpg" => {
1199                        Some(ImageKind::JPEG(data))
1200                    }
1201                    "image/gif" => {
1202                        Some(ImageKind::GIF(data))
1203                    }
1204                    "image/webp" => {
1205                        Some(ImageKind::WEBP(data))
1206                    }
1207                    "image/svg+xml" => {
1208                        let data = image_library.get(&format!("data:image/png;base64,{}", BASE64_STANDARD.encode(data.to_vec())));
1209                        if data.is_none() {
1210                            return None;
1211                        }
1212                        Some(ImageKind::PNG(Arc::new(data.unwrap().data())))
1213                    }
1214                    _ => {
1215                        None
1216                    }
1217                }
1218            }),
1219            resolve_string: Box::new(|string, _opts| {
1220                let data = image_library.get(&string);
1221                if data.is_none() {
1222                    return None;
1223                }
1224                Some(ImageKind::PNG(Arc::new(data.unwrap().data())))
1225            }),
1226        };
1227        options.fontdb = fontdatabase;
1228        let tree = usvg::Tree::from_str(&svg, &options);
1229        if tree.is_err() {
1230            log(&format!("Error parsing SVG: {}", tree.err().unwrap()));
1231            return vector_object_builder;
1232        }
1233        let tree = tree.unwrap();
1234        if !tree.root().has_children() {
1235            log("The SVG path is empty. No operations were applied.");
1236            return vector_object_builder;
1237        }
1238        let node = tree.root().children();
1239        for child in node {
1240            vector_object_builder = vector_object_builder.add_child(VectorObjectBuilder::from_node(&child));
1241        }
1242        vector_object_builder
1243    }
1244    /// Clones the VectorObjectBuilder.
1245    #[wasm_bindgen(js_name = clone, return_description = "A clone of the vector object builder.")]
1246    pub fn clone_js(&self) -> VectorObjectBuilder {
1247        self.clone()
1248    }
1249    /// Creates a VectorObjectBuilder representing an empty VectorObject.
1250    #[wasm_bindgen(return_description = "A new vector object builder representing an empty vector object.")]
1251    pub fn default_vector_object_builder() -> VectorObjectBuilder {
1252        VectorObjectBuilder::default()
1253    }
1254    /// Shifts the VectorObjectBuilder by the given dx and dy.
1255    #[wasm_bindgen(return_description = "The vector object being built with the shift operation.")]
1256    pub fn shift(
1257        mut self,
1258        #[wasm_bindgen(param_description = "The x-coordinate to translate the vector object by.")]
1259        dx: f32,
1260        #[wasm_bindgen(param_description = "The y-coordinate to translate the vector object by.")]
1261        dy: f32,
1262        #[wasm_bindgen(param_description = "Whether to apply the shift operation to the children of the vector object, default is true.")]
1263        recursive: Option<bool>
1264    ) -> VectorObjectBuilder {
1265        let shift = Box::new(Shift { dx, dy, recursive });
1266        self.ops.add_operation(Box::leak(shift));
1267        self
1268    }
1269    /// Centers the VectorObjectBuilder at the given Point2D.
1270    #[wasm_bindgen(return_description = "The vector object being built with the move to operation.")]
1271    pub fn move_to(
1272        mut self,
1273        #[wasm_bindgen(param_description = "The point to center the vector object at.")]
1274        point: Point2D,
1275        #[wasm_bindgen(param_description = "Whether to apply the move to operation to the children of the vector object.")]
1276        recursive: Option<bool>
1277    ) -> VectorObjectBuilder {
1278        let move_to = Box::new(MoveTo { point, recursive });
1279        self.ops.add_operation(Box::leak(move_to));
1280        self
1281    }
1282    /// Scales the VectorObjectBuilder by the given factor.
1283    #[wasm_bindgen(return_description = "The vector object being built with the scale operation.")]
1284    pub fn scale(
1285        mut self,
1286        #[wasm_bindgen(param_description = "The factor to scale the vector object by.")]
1287        factor_x: f32,
1288        #[wasm_bindgen(param_description = "The factor to scale the vector object by.")]
1289        factor_y: f32,
1290        #[wasm_bindgen(param_description = "The point to scale the vector object about.")]
1291        about_point: Option<Point2D>,
1292        #[wasm_bindgen(param_description = "Whether to apply the scale operation to the children of the vector object, default is true.")]
1293        recursive: Option<bool>
1294    ) -> VectorObjectBuilder {
1295        let scale = Box::new(Scale { factor_x, factor_y, about_point, recursive });
1296        self.ops.add_operation(Box::leak(scale));
1297        self
1298    }
1299    /// Scales the VectorObjectBuilder to the given width.
1300    #[wasm_bindgen(return_description = "The vector object being built with the scale to width operation.")]
1301    pub fn scale_to_width(
1302        mut self,
1303        #[wasm_bindgen(param_description = "The width to scale the vector object to.")]
1304        width: f32,
1305        #[wasm_bindgen(param_description = "Whether to stretch the vector object to the given width, default is false.")]
1306        stretch: Option<bool>,
1307        #[wasm_bindgen(param_description = "The point to scale the vector object about, default is the center of the bounding box.")]
1308        about_point: Option<Point2D>,
1309        #[wasm_bindgen(param_description = "Whether to apply the scale to width operation to the children of the vector object, default is true.")]
1310        recursive: Option<bool>
1311    ) -> VectorObjectBuilder {
1312        let scale_to_width = Box::new(ScaleToWidth { width, stretch, about_point, recursive });
1313        self.ops.add_operation(Box::leak(scale_to_width));
1314        self
1315    }
1316    /// Scales the VectorObjectBuilder to the given height.
1317    #[wasm_bindgen(return_description = "The vector object being built with the scale to height operation.")]
1318    pub fn scale_to_height(
1319        mut self,
1320        #[wasm_bindgen(param_description = "The height to scale the vector object to.")]
1321        height: f32,
1322        #[wasm_bindgen(param_description = "Whether to stretch the vector object to the given height, default is false.")]
1323        stretch: Option<bool>,
1324        #[wasm_bindgen(param_description = "The point to scale the vector object about, default is the center of the bounding box.")]
1325        about_point: Option<Point2D>,
1326        #[wasm_bindgen(param_description = "Whether to apply the scale to height operation to the children of the vector object, default is true.")]
1327        recursive: Option<bool>
1328    ) -> VectorObjectBuilder {
1329        let scale_to_height = Box::new(ScaleToHeight { height, stretch, about_point, recursive });
1330        self.ops.add_operation(Box::leak(scale_to_height));
1331        self
1332    }
1333    /// Rotates the VectorObjectBuilder by the given angle in radians.
1334    #[wasm_bindgen(return_description = "The vector object being built with the rotate operation.")]
1335    pub fn rotate(
1336        mut self,
1337        #[wasm_bindgen(param_description = "The angle in radians to rotate the vector object by.")]
1338        angle: f32,
1339        #[wasm_bindgen(param_description = "The point to rotate the vector object about, default is the center of the bounding box.")]
1340        from_point: Option<Point2D>,
1341        #[wasm_bindgen(param_description = "Whether to apply the rotate operation to the children of the vector object, default is true.")]
1342        recursive: Option<bool>
1343    ) -> VectorObjectBuilder {
1344        let rotate = Box::new(Rotate { angle, from_point, recursive });
1345        self.ops.add_operation(Box::leak(rotate));
1346        self
1347    }
1348    /// Sets the TransformationMatrix of the VectorObjectBuilder.
1349    #[wasm_bindgen(return_description = "The vector object being built with the transform operation.")]
1350    pub fn set_transform(
1351        mut self,
1352        #[wasm_bindgen(param_description = "The matrix in CSS format to transform the vector object by.")]
1353        matrix: TransformationMatrix,
1354        #[wasm_bindgen(param_description = "Whether to apply the transform operation to the children of the vector object.")]
1355        recursive: Option<bool>
1356    ) -> VectorObjectBuilder {
1357        let transform = Box::new(SetTransform { matrix: matrix.clone(), recursive });
1358        self.ops.add_operation(Box::leak(transform));
1359        self
1360    }
1361    /// Applies the TransformationMatrix to the VectorObjectBuilder.
1362    #[wasm_bindgen(return_description = "The vector object being built with the apply transform operation.")]
1363    pub fn apply_transform(
1364        mut self,
1365        #[wasm_bindgen(param_description = "The matrix in CSS format to apply to the vector object.")]
1366        matrix: TransformationMatrix,
1367        #[wasm_bindgen(param_description = "Whether to apply the apply transform operation to the children of the vector object, default is true.")]
1368        recursive: Option<bool>
1369    ) -> VectorObjectBuilder {
1370        let apply_transform = Box::new(ApplyTransform { matrix, recursive });
1371        self.ops.add_operation(Box::leak(apply_transform));
1372        self
1373    }
1374    /// Adds a child to the VectorObjectBuilder.
1375    #[wasm_bindgen(return_description = "The vector object being built with the add children operation.")]
1376    pub fn add_children(
1377        mut self,
1378        #[wasm_bindgen(param_description = "The children to add at the end of the vector object.")]
1379        children: Vec<VectorObjectBuilder>
1380    ) -> VectorObjectBuilder {
1381        let add_children = Box::new(AddChildren { children });
1382        self.ops.add_operation(Box::leak(add_children));
1383        self
1384    }
1385    /// Inserts a child into the VectorObjectBuilder at the given index.
1386    #[wasm_bindgen(return_description = "The vector object being built with the insert child operation.")]
1387    pub fn insert_child(
1388        mut self,
1389        #[wasm_bindgen(param_description = "The index to insert the child at.")]
1390        index: usize,
1391        #[wasm_bindgen(param_description = "The child to insert into the vector object.")]
1392        child: VectorObjectBuilder
1393    ) -> VectorObjectBuilder {
1394        let insert_child = Box::new(InsertChild { index, child });
1395        self.ops.add_operation(Box::leak(insert_child));
1396        self
1397    }
1398    /// Inserts children into the VectorObjectBuilder at the given index.
1399    #[wasm_bindgen(return_description = "The vector object being built with the insert children operation.")]
1400    pub fn insert_children(
1401        mut self,
1402        #[wasm_bindgen(param_description = "The index to insert the children at.")]
1403        index: usize,
1404        #[wasm_bindgen(param_description = "The children to insert into the vector object.")]
1405        children: Vec<VectorObjectBuilder>
1406    ) -> VectorObjectBuilder {
1407        let insert_children = Box::new(InsertChildren { index, children });
1408        self.ops.add_operation(Box::leak(insert_children));
1409        self
1410    }
1411    /// Removes a child from the VectorObjectBuilder given its index.
1412    #[wasm_bindgen(return_description = "The vector object being built with the remove child by index operation.")]
1413    pub fn remove_child_by_index(
1414        mut self,
1415        #[wasm_bindgen(param_description = "The index of the child to remove from the vector object.")]
1416        index: usize
1417    ) -> VectorObjectBuilder {
1418        let remove_child_by_index = Box::new(RemoveChildByIndex { index });
1419        self.ops.add_operation(Box::leak(remove_child_by_index));
1420        self
1421    }
1422    /// Removes a child from the VectorObjectBuilder given its name.
1423    #[wasm_bindgen(return_description = "The vector object being built with the remove child by name operation.")]
1424    pub fn remove_child_by_name(
1425        mut self,
1426        #[wasm_bindgen(param_description = "The name of the child to remove from the vector object.")]
1427        name: String
1428    ) -> VectorObjectBuilder {
1429        let remove_child_by_name = Box::new(RemoveChildByName { name: Rc::new(name) });
1430        self.ops.add_operation(Box::leak(remove_child_by_name));
1431        self
1432    }
1433    /// Matches the style properties of the VectorObjectBuilder with another VectorObject.
1434    #[wasm_bindgen(return_description = "The vector object being built with the match style properties operation.")]
1435    pub fn match_style_properties(
1436        mut self,
1437        #[wasm_bindgen(param_description = "The vector object to match the style properties of.")]
1438        vector_object_builder: VectorObjectBuilder
1439    ) -> VectorObjectBuilder {
1440        let match_style_properties = Box::new(MatchStyleProperties { vector_object_builder });
1441        self.ops.add_operation(Box::leak(match_style_properties));
1442        self
1443    }
1444    /// Sets the actual path of the VectorObjectBuilder. Actual path is the path that is drawn with its transformation matrix applied.
1445    #[wasm_bindgen(return_description = "The vector object being built with the set actual path operation.")]
1446    pub fn set_actual_path(
1447        mut self,
1448        #[wasm_bindgen(param_description = "The path to set the vector object to.")]
1449        actual_path: Path2D
1450    ) -> VectorObjectBuilder {
1451        let set_actual_path = Box::new(SetActualPath { path: actual_path });
1452        self.ops.add_operation(Box::leak(set_actual_path));
1453        self
1454    }
1455    /// Trims the stroke of the VectorObjectBuilder to the given start and end proportions.
1456    #[wasm_bindgen(return_description = "The vector object being built with the become partial operation.")]
1457    pub fn become_partial(
1458        mut self,
1459        #[wasm_bindgen(param_description = "The proportion of the path to start at.")]
1460        start: f32,
1461        #[wasm_bindgen(param_description = "The proportion of the path to end at.")]
1462        end: f32,
1463        #[wasm_bindgen(param_description = "Number of samples to compute the length of each cubic bezier curve segment.")]
1464        samples: Option<usize>,
1465        #[wasm_bindgen(param_description = "Extra length to add to each length computation to ensure the path is not too short.")]
1466        extra_length: Option<f32>,
1467        #[wasm_bindgen(param_description = "Whether to apply the become partial operation to the children of the vector object, default is true")]
1468        recursive: Option<bool>
1469    ) -> VectorObjectBuilder {
1470        let become_partial = Box::new(BecomePartial { start, end, samples, extra_length, recursive });
1471        self.ops.add_operation(Box::leak(become_partial));
1472        self
1473    }
1474    /// Trims the path of the VectorObjectBuilder to the given start and end proportions.
1475    pub fn pointwise_become_partial(
1476        mut self,
1477        #[wasm_bindgen(param_description = "The proportion of the path to start at.")]
1478        start: f32,
1479        #[wasm_bindgen(param_description = "The proportion of the path to end at.")]
1480        end: f32,
1481        #[wasm_bindgen(param_description = "Whether to apply the pointwise become partial operation to the children of the vector object, default is true")]
1482        recursive: Option<bool>
1483    ) -> VectorObjectBuilder {
1484        let pointwise_become_partial = Box::new(PointwiseBecomePartial { start, end, recursive });
1485        self.ops.add_operation(Box::leak(pointwise_become_partial));
1486        self
1487    }
1488    /// Moves the current drawing point to the given Point2D.
1489    #[wasm_bindgen(return_description = "The vector object being built with the move point operation.")]
1490    pub fn move_point(
1491        mut self,
1492        #[wasm_bindgen(param_description = "The point to start a new bezier curve at.")]
1493        point: &Point2D
1494    ) -> VectorObjectBuilder {
1495        let move_point = Box::new(MovePoint { point: *point });
1496        self.ops.add_operation(Box::leak(move_point));
1497        self
1498    }
1499    /// Draws a line from the current drawing point to the given Point2D.
1500    #[wasm_bindgen(return_description = "The vector object being built with the line to operation.")]
1501    pub fn line_to(
1502        mut self,
1503        #[wasm_bindgen(param_description = "The point to draw a line to.")]
1504        p: &Point2D
1505    ) -> VectorObjectBuilder {
1506        let line_to = Box::new(LineTo { point: *p });
1507        self.ops.add_operation(Box::leak(line_to));
1508        self
1509    }
1510    /// Draws a quadratic bezier curve from the current drawing point with the given control Point2D and end Point2D.
1511    #[wasm_bindgen(return_description = "The vector object being built with the quadratic curve to operation.")]
1512    pub fn quadratic_curve_to(
1513        mut self,
1514        #[wasm_bindgen(param_description = "The control point of the quadratic curve.")]
1515        p1: &Point2D,
1516        #[wasm_bindgen(param_description = "The end point of the quadratic curve.")]
1517        p2: &Point2D
1518    ) -> VectorObjectBuilder {
1519        let quadratic_curve_to = Box::new(QuadraticCurveTo { p1: *p1, p2: *p2 });
1520        self.ops.add_operation(Box::leak(quadratic_curve_to));
1521        self
1522    }
1523    /// Draws a cubic bezier curve from the current drawing point with the given control Point2Ds and end Point2D.
1524    #[wasm_bindgen(return_description = "The vector object being built with the bezier curve to operation.")]
1525    pub fn bezier_curve_to(
1526        mut self,
1527        #[wasm_bindgen(param_description = "The first control point of the bezier curve.")]
1528        p1: &Point2D,
1529        #[wasm_bindgen(param_description = "The second control point of the bezier curve.")]
1530        p2: &Point2D,
1531        #[wasm_bindgen(param_description = "The end point of the bezier curve.")]
1532        p3: &Point2D
1533    ) -> VectorObjectBuilder {
1534        let bezier_curve_to = Box::new(BezierCurveTo { p1: *p1, p2: *p2, p3: *p3 });
1535        self.ops.add_operation(Box::leak(bezier_curve_to));
1536        self
1537    }
1538    /// Closes the current subpath of the VectorObjectBuilder.
1539    #[wasm_bindgen(return_description = "The vector object being built with the close operation.")]
1540    pub fn close(mut self) -> VectorObjectBuilder {
1541        let close = Box::new(Close {});
1542        self.ops.add_operation(Box::leak(close));
1543        self
1544    }
1545    /// Fades fill's opacity of the VectorObjectBuilder by the given factor.
1546    #[wasm_bindgen(return_description = "The vector object being built with the fade fill operation.")]
1547    pub fn fade_fill(
1548        mut self,
1549        #[wasm_bindgen(param_description = "The factor to fade the fill style by.")]
1550        factor: f32,
1551        #[wasm_bindgen(param_description = "Whether to apply the fade fill operation to the children of the vector object.")]
1552        recursive: Option<bool>
1553    ) -> VectorObjectBuilder {
1554        let fade_fill = Box::new(FadeFill { factor, recursive });
1555        self.ops.add_operation(Box::leak(fade_fill));
1556        self
1557    }
1558    /// Fades stroke's opacity of the VectorObjectBuilder by the given factor.
1559    #[wasm_bindgen(return_description = "The vector object being built with the fade stroke operation.")]
1560    pub fn fade_stroke(
1561        mut self,
1562        #[wasm_bindgen(param_description = "The factor to fade the stroke style by.")]
1563        factor: f32,
1564        #[wasm_bindgen(param_description = "Whether to apply the fade stroke operation to the children of the vector object.")]
1565        recursive: Option<bool>
1566    ) -> VectorObjectBuilder {
1567        let fade_stroke = Box::new(FadeStroke { factor, recursive });
1568        self.ops.add_operation(Box::leak(fade_stroke));
1569        self
1570    }
1571    /// Sets the Path2D of the VectorObjectBuilder.
1572    #[wasm_bindgen(return_description = "The vector object being built with the set path operation.")]
1573    pub fn set_path(
1574        mut self,
1575        #[wasm_bindgen(param_description = "The path to set the vector object to.")]
1576        path: Path2D
1577    ) -> VectorObjectBuilder {
1578        let set_path = Box::new(SetPath { path });
1579        self.ops.add_operation(Box::leak(set_path));
1580        self
1581    }
1582    /// Sets the fill Style of the VectorObjectBuilder.
1583    #[wasm_bindgen(return_description = "The vector object being built with the set fill operation.")]
1584    pub fn set_fill(
1585        mut self,
1586        #[wasm_bindgen(param_description = "The fill style to set the vector object to.")]
1587        fill: Style,
1588        #[wasm_bindgen(param_description = "Whether to apply the set fill operation to the children of the vector object, default is true.")]
1589        recursive: Option<bool>
1590    ) -> VectorObjectBuilder {
1591        let set_fill = Box::new(SetFill { fill, recursive });
1592        self.ops.add_operation(Box::leak(set_fill));
1593        self
1594    }
1595    /// Sets the fill rule of the VectorObjectBuilder.
1596    #[wasm_bindgen(return_description = "The vector object being built with the set fill rule operation.")]
1597    pub fn set_fill_rule(
1598        mut self,
1599        #[wasm_bindgen(param_description = "The fill rule to set the vector object to.")]
1600        fill_rule: String,
1601        #[wasm_bindgen(param_description = "Whether to apply the set fill rule operation to the children of the vector object, default is true.")]
1602        recursive: Option<bool>
1603    ) -> VectorObjectBuilder {
1604        let set_fill_rule = Box::new(SetFillRule { fill_rule: Rc::new(fill_rule), recursive });
1605        self.ops.add_operation(Box::leak(set_fill_rule));
1606        self
1607    }
1608    /// Sets the stroke Style of the VectorObjectBuilder.
1609    #[wasm_bindgen(return_description = "The vector object being built with the set stroke operation.")]
1610    pub fn set_stroke(
1611        mut self,
1612        #[wasm_bindgen(param_description = "The stroke style to set the vector object to.")]
1613        stroke: Style,
1614        #[wasm_bindgen(param_description = "Whether to apply the set stroke operation to the children of the vector object, default is true.")]
1615        recursive: Option<bool>
1616    ) -> VectorObjectBuilder {
1617        let set_stroke = Box::new(SetStroke { stroke, recursive });
1618        self.ops.add_operation(Box::leak(set_stroke));
1619        self
1620    }
1621    /// Sets the stroke width of the VectorObjectBuilder.
1622    #[wasm_bindgen(return_description = "The vector object being built with the set stroke width operation.")]
1623    pub fn set_stroke_width(
1624        mut self,
1625        #[wasm_bindgen(param_description = "The stroke width to set the vector object to.")]
1626        stroke_width: f32,
1627        #[wasm_bindgen(param_description = "Whether to apply the set stroke width operation to the children of the vector object, default is true.")]
1628        recursive: Option<bool>
1629    ) -> VectorObjectBuilder {
1630        let set_stroke_width = Box::new(SetStrokeWidth { stroke_width, recursive });
1631        self.ops.add_operation(Box::leak(set_stroke_width));
1632        self
1633    }
1634    /// Sets the stroke line cap of the VectorObjectBuilder.
1635    #[wasm_bindgen(return_description = "The vector object being built with the set stroke line cap operation.")]
1636    pub fn set_stroke_line_cap(
1637        mut self,
1638        #[wasm_bindgen(param_description = "The stroke line cap to set the vector object to.")]
1639        stroke_line_cap: String,
1640        #[wasm_bindgen(param_description = "Whether to apply the set stroke line cap operation to the children of the vector object, default is true.")]
1641        recursive: Option<bool>
1642    ) -> VectorObjectBuilder {
1643        let set_stroke_line_cap = Box::new(SetStrokeLineCap { stroke_line_cap: Rc::new(stroke_line_cap), recursive });
1644        self.ops.add_operation(Box::leak(set_stroke_line_cap));
1645        self
1646    }
1647    /// Sets the stroke line join of the VectorObjectBuilder.
1648    #[wasm_bindgen(return_description = "The vector object being built with the set stroke line join operation.")]
1649    pub fn set_stroke_line_join(
1650        mut self,
1651        #[wasm_bindgen(param_description = "The stroke line join to set the vector object to.")]
1652        stroke_line_join: String,
1653        #[wasm_bindgen(param_description = "Whether to apply the set stroke line join operation to the children of the vector object, default is true.")]
1654        recursive: Option<bool>
1655    ) -> VectorObjectBuilder {
1656        let set_stroke_line_join = Box::new(SetStrokeLineJoin { stroke_line_join: Rc::new(stroke_line_join), recursive });
1657        self.ops.add_operation(Box::leak(set_stroke_line_join));
1658        self
1659    }
1660    /// Sets the stroke miter limit of the VectorObjectBuilder.
1661    #[wasm_bindgen(return_description = "The vector object being built with the set stroke miter limit operation.")]
1662    pub fn set_stroke_miter_limit(
1663        mut self,
1664        #[wasm_bindgen(param_description = "The stroke miter limit to set the vector object to.")]
1665        stroke_miter_limit: f32,
1666        #[wasm_bindgen(param_description = "Whether to apply the set stroke miter limit operation to the children of the vector object, default is true.")]
1667        recursive: Option<bool>
1668    ) -> VectorObjectBuilder {
1669        let set_stroke_miter_limit = Box::new(SetStrokeMiterLimit { stroke_miter_limit, recursive });
1670        self.ops.add_operation(Box::leak(set_stroke_miter_limit));
1671        self
1672    }
1673    /// Sets the stroke dash offset of the VectorObjectBuilder.
1674    #[wasm_bindgen(return_description = "The vector object being built with the set stroke dash offset operation.")]
1675    pub fn set_stroke_dash_offset(
1676        mut self,
1677        #[wasm_bindgen(param_description = "The stroke dash offset to set the vector object to.")]
1678        stroke_dash_offset: f32,
1679        #[wasm_bindgen(param_description = "Whether to apply the set stroke dash offset operation to the children of the vector object, default is true.")]
1680        recursive: Option<bool>
1681    ) -> VectorObjectBuilder {
1682        let set_stroke_dash_offset = Box::new(SetStrokeDashOffset { stroke_dash_offset, recursive });
1683        self.ops.add_operation(Box::leak(set_stroke_dash_offset));
1684        self
1685    }
1686    /// Sets the stroke dash array of the VectorObjectBuilder.
1687    #[wasm_bindgen(return_description = "The vector object being built with the set stroke dash array operation.")]
1688    pub fn set_stroke_dash_array(
1689        mut self,
1690        #[wasm_bindgen(param_description = "The stroke dash array to set the vector object to.", unchecked_param_type = "number[]")]
1691        stroke_dash_array: Vec<f32>,
1692        #[wasm_bindgen(param_description = "Whether to apply the set stroke dash array operation to the children of the vector object, default is true.")]
1693        recursive: Option<bool>
1694    ) -> VectorObjectBuilder {
1695        let set_stroke_dash_array = Box::new(SetStrokeDashArray { stroke_dash_array: Rc::new(stroke_dash_array), recursive });
1696        self.ops.add_operation(Box::leak(set_stroke_dash_array));
1697        self
1698    }
1699    /// Sets the children of the VectorObjectBuilder.
1700    #[wasm_bindgen(return_description = "The vector object being built with the set children operation.")]
1701    pub fn set_children(
1702        mut self,
1703        #[wasm_bindgen(param_description = "The children to set the vector object to.")]
1704        children: Vec<VectorObjectBuilder>
1705    ) -> VectorObjectBuilder {
1706        let set_children = Box::new(SetChildren { children });
1707        self.ops.add_operation(Box::leak(set_children));
1708        self
1709    }
1710    /// Sets the name of the VectorObjectBuilder.
1711    #[wasm_bindgen(return_description = "The vector object being built with the set name operation.")]
1712    pub fn set_name(
1713        mut self,
1714        #[wasm_bindgen(param_description = "The name to set the vector object to.")]
1715        name: Option<String>
1716    ) -> VectorObjectBuilder {
1717        let set_name = Box::new(SetName { name: name.map(Rc::new) });
1718        self.ops.add_operation(Box::leak(set_name));
1719        self
1720    }
1721    /// Applies the current transformation to the path of the VectorObjectBuilder.
1722    #[wasm_bindgen(return_description = "The vector object being built with the apply transformation operation.")]
1723    pub fn actual_path_as_path(
1724        mut self,
1725        #[wasm_bindgen(param_description = "Whether to remove transformations after applying the current transformation to the path, default is true.")]
1726        untransform: Option<bool>,
1727        #[wasm_bindgen(param_description = "Whether to apply the actual path as path operation to the children of the vector object, default is true.")]
1728        recursive: Option<bool>
1729    ) -> VectorObjectBuilder {
1730        let actual_path_as_path = Box::new(ActualPathAsPath { untransform, recursive });
1731        self.ops.add_operation(Box::leak(actual_path_as_path));
1732        self
1733    }
1734    /// Adds a child to the VectorObjectBuilder.
1735    #[wasm_bindgen(return_description = "The vector object being built with the add child operation.")]
1736    pub fn add_child(
1737        mut self,
1738        #[wasm_bindgen(param_description = "The child to add to the vector object.")]
1739        child: VectorObjectBuilder
1740    ) -> VectorObjectBuilder {
1741        let add_child = Box::new(AddChild { child });
1742        self.ops.add_operation(Box::leak(add_child));
1743        self
1744    }
1745    /// Removes all children with the given indices from the VectorObjectBuilder.
1746    #[wasm_bindgen(return_description = "The vector object being built with the remove children at indices operation.")]
1747    pub fn remove_children_at_indices(
1748        mut self,
1749        #[wasm_bindgen(param_description = "The indices of the children to remove from the vector object.", unchecked_param_type = "number[]")]
1750        indices: Vec<usize>
1751    ) -> VectorObjectBuilder {
1752        let remove_children_at_indices = Box::new(RemoveChildrenAtIndices { indices });
1753        self.ops.add_operation(Box::leak(remove_children_at_indices));
1754        self
1755    }
1756    /// Removes all children with the given names from the VectorObjectBuilder.
1757    #[wasm_bindgen(return_description = "The vector object being built with the remove children by names operation.")]
1758    pub fn remove_children_by_names(
1759        mut self,
1760        #[wasm_bindgen(param_description = "The names of the children to remove from the vector object.", unchecked_param_type = "string[]")]
1761        names: Vec<String>
1762    ) -> VectorObjectBuilder {
1763        let remove_children_by_names = Box::new(RemoveChildrenByNames { names });
1764        self.ops.add_operation(Box::leak(remove_children_by_names));
1765        self
1766    }
1767    /// Sets the children from the start index to the end index of the VectorObjectBuilder.
1768    #[wasm_bindgen(return_description = "The vector object being built with the set slice children operation.")]
1769    pub fn set_slice_children(
1770        mut self,
1771        #[wasm_bindgen(param_description = "The start index of the children to replace.")]
1772        start: usize,
1773        #[wasm_bindgen(param_description = "The end index of the children to replace.")]
1774        end: usize,
1775        #[wasm_bindgen(param_description = "The children to replace the children from the start index to the end index with.")]
1776        children: Vec<VectorObjectBuilder>
1777    ) -> VectorObjectBuilder {
1778        let set_slice_children = Box::new(SetSliceChildren { start, end, children });
1779        self.ops.add_operation(Box::leak(set_slice_children));
1780        self
1781    }
1782    /// Puts the VectorObjectBuilder next to the given Point2D at the given direction, with a buff distance between them and aligning at the given edge.
1783    #[wasm_bindgen(return_description = "The vector object being built with the next to point operation.")]
1784    pub fn next_to_point(
1785        mut self,
1786        #[wasm_bindgen(param_description = "The point to translate the vector object to.")]
1787        point: Point2D,
1788        #[wasm_bindgen(param_description = "The direction to translate the vector object in. If not given, the vector object will be at the right of the point, default is right.")]
1789        direction: Option<Point2D>,
1790        #[wasm_bindgen(param_description = "The buffer to leave between the vector object and the point. If not given, the vector object will be touching the point, default is 0.")]
1791        buff: Option<f32>,
1792        #[wasm_bindgen(param_description = "The edge of the vector object to align with the point. If not given, the vector object will be aligned at the middle, default is the middle.")]
1793        aligned_edge: Option<Point2D>,
1794        #[wasm_bindgen(param_description = "Whether to apply the next to point operation to the children of the vector object. If not given, the operation will be applied to the children, default is true.")]
1795        recursive: Option<bool>
1796    ) -> VectorObjectBuilder {
1797        let next_to_point = Box::new(NextToPoint { point, direction, buff, aligned_edge, recursive });
1798        self.ops.add_operation(Box::leak(next_to_point));
1799        self
1800    }
1801    /// Puts the VectorObjectBuilder next to the given VectorObjectBuilder at the given direction, with a buff distance between them and aligning at the given edge.
1802    #[wasm_bindgen(return_description = "The vector object being built with the next to other operation.")]
1803    pub fn next_to_other(
1804        mut self,
1805        #[wasm_bindgen(param_description = "The other vector object to translate the vector object to.")]
1806        other: VectorObjectBuilder,
1807        #[wasm_bindgen(param_description = "The direction to translate the vector object in. If not given, the vector object will be at the right of the other vector object, default is right.")]
1808        direction: Option<Point2D>,
1809        #[wasm_bindgen(param_description = "The buffer to leave between the vector object and the other vector object. If not given, the vector object will be touching the other vector object, default is 0.")]
1810        buff: Option<f32>,
1811        #[wasm_bindgen(param_description = "The edge of the vector object to align with the other vector object. If not given, the vector object will be aligned at the middle, default is the middle.")]
1812        aligned_edge: Option<Point2D>,
1813        #[wasm_bindgen(param_description = "Whether to apply the next to other operation to the children of the vector object. If not given, the operation will be applied to the children, default is true.")]
1814        recursive: Option<bool>
1815    ) -> VectorObjectBuilder {
1816        let next_to_other = Box::new(NextToOther { other, direction, buff, aligned_edge, recursive });
1817        self.ops.add_operation(Box::leak(next_to_other));
1818        self
1819    }
1820    /// Arranges the children of the VectorObjectBuilder in the given direction, with a buff distance between them and aligning at the given edge.
1821    #[wasm_bindgen(return_description = "The vector object being built with the arrange subobjects operation.")]
1822    pub fn arrange_children(
1823        mut self,
1824        #[wasm_bindgen(param_description = "The direction to arrange the children. If not given, the children will be arranged horizontally in the positive x direction.")]
1825        direction: Option<Point2D>,
1826        #[wasm_bindgen(param_description = "The buffer to leave between the children. If not given, the children will be touching, default is 0.")]
1827        buff: Option<f32>,
1828        #[wasm_bindgen(param_description = "The edge of the children to align with the point. If not given, the children will be aligned at the middle.")]
1829        aligned_edge: Option<Point2D>,
1830        #[wasm_bindgen(param_description = "The center of the children. If not given, the children won't be centered at any point.")]
1831        center: Option<Point2D>,
1832        #[wasm_bindgen(param_description = "Whether to apply the arrange subobjects operation to the children of the vector object, default is true.")]
1833        recursive: Option<bool>
1834    ) -> VectorObjectBuilder {
1835        let arrange_subobjects = Box::new(ArrangeChildren { direction, buff, aligned_edge, center, recursive });
1836        self.ops.add_operation(Box::leak(arrange_subobjects));
1837        self
1838    }
1839    /// Reverses the path of the VectorObjectBuilder.
1840    #[wasm_bindgen(return_description = "The vector object being built with the reverse path operation.")]
1841    pub fn reverse_path(mut self) -> VectorObjectBuilder {
1842        let reverse_path = Box::new(ReversePath {});
1843        self.ops.add_operation(Box::leak(reverse_path));
1844        self
1845    }
1846    /// Linearly interpolates the fill Style of the VectorObjectBuilder with another VectorObjectBuilder.
1847    #[wasm_bindgen(return_description = "The vector object being built with the interpolate fill operation.")]
1848    pub fn lerp_fill(
1849        mut self,
1850        #[wasm_bindgen(param_description = "The vector object to interpolate the fill style with.")]
1851        fill: Style,
1852        #[wasm_bindgen(param_description = "The factor to interpolate the fill style by.")]
1853        t: f32,
1854        #[wasm_bindgen(param_description = "The image's top left corner x-coordinate. It must be provided if the fill style contains an image or different kinds of gradients.")]
1855        x: Option<f32>,
1856        #[wasm_bindgen(param_description = "The image's top left corner y-coordinate. It must be provided if the fill style contains an image or different kinds of gradients.")]
1857        y: Option<f32>,
1858        #[wasm_bindgen(param_description = "The image's rendering width. It must be provided if the fill style contains an image or different kinds of gradients.")]
1859        width: Option<f32>,
1860        #[wasm_bindgen(param_description = "The image's rendering height. It must be provided if the fill style contains an image or different kinds of gradients.")]
1861        height: Option<f32>,
1862        #[wasm_bindgen(param_description = "The image's number of pixels in a row. It must be provided if the fill style contains an image or different kinds of gradients.")]
1863        data_width: Option<usize>,
1864        #[wasm_bindgen(param_description = "The image's number of pixels in a column. It must be provided if the fill style contains an image or different kinds of gradients.")]
1865        data_height: Option<usize>,
1866        #[wasm_bindgen(param_description = "Whether to apply the interpolate fill operation to the children of the vector object, default is true.")]
1867        recursive: Option<bool>,
1868    ) -> VectorObjectBuilder {
1869        let interpolate_fill = Box::new(LerpFill { fill, t, x, y, width, height, data_width, data_height, recursive });
1870        self.ops.add_operation(Box::leak(interpolate_fill));
1871        self
1872    }
1873    /// Linearly interpolates the stroke Style of the VectorObjectBuilder with another VectorObjectBuilder.
1874    #[wasm_bindgen(return_description = "The vector object being built with the interpolate stroke operation.")]
1875    pub fn lerp_stroke(
1876        mut self,
1877        #[wasm_bindgen(param_description = "The vector object to interpolate the stroke style with.")]
1878        stroke: Style,
1879        #[wasm_bindgen(param_description = "The factor to interpolate the stroke style by.")]
1880        t: f32,
1881        #[wasm_bindgen(param_description = "The image's top left corner x-coordinate. It must be provided if the stroke style contains an image or different kinds of gradients.")]
1882        x: Option<f32>,
1883        #[wasm_bindgen(param_description = "The image's top left corner y-coordinate. It must be provided if the stroke style contains an image or different kinds of gradients.")]
1884        y: Option<f32>,
1885        #[wasm_bindgen(param_description = "The image's rendering width. It must be provided if the stroke style contains an image or different kinds of gradients.")]
1886        width: Option<f32>,
1887        #[wasm_bindgen(param_description = "The image's rendering height. It must be provided if the stroke style contains an image or different kinds of gradients.")]
1888        height: Option<f32>,
1889        #[wasm_bindgen(param_description = "The image's number of pixels in a row. It must be provided if the stroke style contains an image or different kinds of gradients.")]
1890        data_width: Option<usize>,
1891        #[wasm_bindgen(param_description = "The image's number of pixels in a column. It must be provided if the stroke style contains an image or different kinds of gradients.")]
1892        data_height: Option<usize>,
1893        #[wasm_bindgen(param_description = "Whether to apply the interpolate stroke operation to the children of the vector object, default is true.")]
1894        recursive: Option<bool>,
1895    ) -> VectorObjectBuilder {
1896        let interpolate_stroke = Box::new(LerpStroke { stroke, t, x, y, width, height, data_width, data_height, recursive });
1897        self.ops.add_operation(Box::leak(interpolate_stroke));
1898        self
1899    }
1900    /// Builds the VectorObject by applying sequentially all the operations to the VectorObjectBuilder.
1901    #[wasm_bindgen(return_description = "The vector object built by applying the operations to it.")]
1902    pub fn build(self) -> VectorObject {
1903        let mut vector_object = Rc::clone(&self.object);
1904        let vector_object_as_mut = Rc::make_mut(&mut vector_object);
1905        self.ops.apply_and_return(vector_object_as_mut)
1906    }
1907}
1908
1909impl VectorObjectBuilder {
1910    pub fn from_node(node: &usvg::Node) -> VectorObjectBuilder {
1911        let mut builder = VectorObjectBuilder::default();
1912        match node {
1913            usvg::Node::Path(ref path) => {
1914                builder = builder.add_child(VectorObjectBuilder::from_path(path));
1915            }
1916            usvg::Node::Group(ref group) => {
1917                builder = builder.add_child(VectorObjectBuilder::from_group(group));
1918            }
1919            usvg::Node::Text(ref text) => {
1920                builder = builder.add_child(VectorObjectBuilder::from_text(text));
1921            }
1922            usvg::Node::Image(ref image) => {
1923                builder = builder.add_child(VectorObjectBuilder::from_image(image));
1924            }
1925        }
1926        builder
1927    }
1928    pub fn from_path(internal_path: &usvg::Path) -> VectorObjectBuilder {
1929        let mut vector_object_builder = VectorObjectBuilder::default();
1930        let path = Path2D::from_svg_path_data(internal_path.data());
1931        vector_object_builder = vector_object_builder.set_path(path);
1932        let internal_fill_option = internal_path.fill();
1933        let fill;
1934        let fill_rule;
1935        if let Some(internal_fill) = internal_fill_option {
1936            fill = Style::from_paint_and_opacity(internal_fill.paint(), &internal_fill.opacity());
1937            fill_rule = match internal_fill.rule() {
1938                usvg::FillRule::NonZero => "nonzero",
1939                usvg::FillRule::EvenOdd => "evenodd",
1940            };
1941        } else {
1942            fill = Style::from_color(Color::new(0, 0, 0, 0.0));
1943            fill_rule = "nonzero";
1944        }
1945        vector_object_builder = vector_object_builder.set_fill(fill, Some(false)).set_fill_rule(fill_rule.to_string(), Some(false));
1946        let internal_stroke_option = internal_path.stroke();
1947        let stroke;
1948        let stroke_width;
1949        let stroke_line_cap;
1950        let stroke_line_join;
1951        let stroke_miter_limit;
1952        let stroke_dash_offset;
1953        let stroke_dash_array;
1954        if let Some(internal_stroke) = internal_stroke_option {
1955            stroke = Style::from_paint_and_opacity(internal_stroke.paint(), &internal_stroke.opacity());
1956            stroke_width = internal_stroke.width().get();
1957            stroke_line_cap = match internal_stroke.linecap() {
1958                usvg::LineCap::Butt => "butt",
1959                usvg::LineCap::Round => "round",
1960                usvg::LineCap::Square => "square",
1961            };
1962            stroke_line_join = match internal_stroke.linejoin() {
1963                usvg::LineJoin::Miter => "miter",
1964                usvg::LineJoin::Round => "round",
1965                usvg::LineJoin::Bevel => "bevel",
1966                usvg::LineJoin::MiterClip => "miter-clip",
1967            };
1968            stroke_miter_limit = internal_stroke.miterlimit().get();
1969            stroke_dash_offset = internal_stroke.dashoffset();
1970            stroke_dash_array = internal_stroke.dasharray().unwrap_or(&[]).to_vec();
1971        } else {
1972            stroke = Style::from_color(Color::new(0, 0, 0, 0.0));
1973            stroke_width = 1.0;
1974            stroke_line_cap = "butt";
1975            stroke_line_join = "miter";
1976            stroke_miter_limit = 4.0;
1977            stroke_dash_offset = 0.0;
1978            stroke_dash_array = Vec::new();
1979        }
1980        vector_object_builder = vector_object_builder.set_stroke(stroke, Some(false)).set_stroke_width(stroke_width, Some(false)).set_stroke_line_cap(stroke_line_cap.to_string(), Some(false)).set_stroke_line_join(stroke_line_join.to_string(), Some(false)).set_stroke_miter_limit(stroke_miter_limit, Some(false)).set_stroke_dash_offset(stroke_dash_offset, Some(false)).set_stroke_dash_array(stroke_dash_array, Some(false));
1981        let transform = TransformationMatrix::from_svg_transform(internal_path.abs_transform());
1982        vector_object_builder = vector_object_builder.set_transform(transform, Some(false));
1983        vector_object_builder
1984    }
1985    pub fn from_group(internal_group: &usvg::Group) -> VectorObjectBuilder {
1986        let mut vector_object_builder = VectorObjectBuilder::default();
1987        for node in internal_group.children() {
1988            vector_object_builder = vector_object_builder.add_child(VectorObjectBuilder::from_node(node));
1989        }
1990        let transform = TransformationMatrix::from_svg_transform(internal_group.abs_transform());
1991        vector_object_builder = vector_object_builder.set_transform(transform, Some(false));
1992        vector_object_builder
1993    }
1994    pub fn from_text(text: &usvg::Text) -> VectorObjectBuilder {
1995        VectorObjectBuilder::from_group(text.flattened())
1996            .apply_transform(TransformationMatrix::from_svg_transform(text.abs_transform()), None)
1997    }
1998    pub fn from_image(image: &usvg::Image) -> VectorObjectBuilder {
1999        let kind = image.kind();
2000        let dimensions = image.size();
2001        let data_width = dimensions.width().round() as usize;
2002        let data_height = dimensions.height().round() as usize;
2003        let data = match &kind {
2004            usvg::ImageKind::PNG(data) => {
2005                let image_data = data.to_vec();
2006                Some(image_data)
2007            }
2008            usvg::ImageKind::JPEG(data) => {
2009                let image_data = data.to_vec();
2010                Some(image_data)
2011            }
2012            usvg::ImageKind::WEBP(data) => {
2013                let image_data = data.to_vec();
2014                Some(image_data)
2015            }
2016            _ => None
2017        };
2018        if data.is_none() {
2019            log("Unsupported image format.");
2020            return VectorObjectBuilder::default();
2021        }
2022        let x = image.bounding_box().x();
2023        let y = image.bounding_box().y();
2024        let width = image.bounding_box().width();
2025        let height = image.bounding_box().height();
2026        let mut vector_object_builder = Rectangle::new(
2027            BoundingBox::new(x, y, width, height).unwrap(),
2028            None
2029        ).vector_object_builder().set_stroke_width(0.0, Some(false));
2030        let img = ImageBitmap::new(x, y, width, height, data_width, data_height, data.unwrap());
2031        if img.is_err() {
2032            log("Failed to create image bitmap.");
2033            return VectorObjectBuilder::default();
2034        }
2035        vector_object_builder = vector_object_builder.set_fill(
2036            Style::from_image(img.unwrap()),
2037            Some(false)
2038        );
2039        vector_object_builder = vector_object_builder.set_transform(
2040            TransformationMatrix::from_svg_transform(image.abs_transform()),
2041            Some(false)
2042        );
2043        vector_object_builder
2044    }
2045}
2046
2047#[wasm_bindgen]
2048impl VectorObject {
2049    /// Creates a new VectorObject.
2050    #[wasm_bindgen(constructor, return_description = "A new vector object.")]
2051    pub fn new(
2052        #[wasm_bindgen(param_description = "The Path2D of the vector object.")]
2053        path: Path2D,
2054        #[wasm_bindgen(param_description = "The fill Style of the vector object.")]
2055        fill: Style,
2056        #[wasm_bindgen(param_description = "The fill rule of the vector object.")]
2057        fill_rule: String,
2058        #[wasm_bindgen(param_description = "The stroke Style of the vector object.")]
2059        stroke: Style,
2060        #[wasm_bindgen(param_description = "The stroke width of the vector object.")]
2061        stroke_width: f32,
2062        #[wasm_bindgen(param_description = "The stroke line cap of the vector object.")]
2063        stroke_line_cap: String,
2064        #[wasm_bindgen(param_description = "The stroke line join of the vector object.")]
2065        stroke_line_join: String,
2066        #[wasm_bindgen(param_description = "The stroke miter limit of the vector object.")]
2067        stroke_miter_limit: f32,
2068        #[wasm_bindgen(param_description = "The stroke dash offset of the vector object.")]
2069        stroke_dash_offset: f32,
2070        #[wasm_bindgen(param_description = "The stroke dash array of the vector object.", unchecked_param_type = "number[]")]
2071        stroke_dash_array: Vec<f32>,
2072        #[wasm_bindgen(param_description = "The children of the vector object.")]
2073        children: Vec<VectorObject>,
2074        #[wasm_bindgen(param_description = "The name of the vector object.")]
2075        name: Option<String>,
2076        #[wasm_bindgen(param_description = "The TransformationMatrix of the vector object.")]
2077        transform: TransformationMatrix
2078    ) -> VectorObject {
2079        VectorObject {
2080            path,
2081            fill,
2082            fill_rule: Rc::new(fill_rule),
2083            stroke,
2084            stroke_width,
2085            stroke_line_cap: Rc::new(stroke_line_cap),
2086            stroke_line_join: Rc::new(stroke_line_join),
2087            stroke_miter_limit,
2088            stroke_dash_offset,
2089            stroke_dash_array: Rc::new(stroke_dash_array),
2090            children,
2091            name: name.map(Rc::new),
2092            transform,
2093        }
2094    }
2095    /// Clones the vector object.
2096    #[wasm_bindgen(js_name = clone, return_description = "The cloned vector object.")]
2097    pub fn clone_js(&self) -> VectorObject {
2098        self.clone()
2099    }
2100    /// Creates a new empty VectorObject.
2101    #[wasm_bindgen(return_description = "A new empty vector object.")]
2102    pub fn default_vector_object() -> VectorObject {
2103        VectorObject::default()
2104    }
2105    /// Gets the Path2D of the VectorObject.
2106    #[wasm_bindgen(getter, return_description = "The path of the vector object.")]
2107    pub fn path(&self) -> Path2D {
2108        self.path.clone()
2109    }
2110    /// Gets the fill Style of the VectorObject.
2111    #[wasm_bindgen(getter, return_description = "The fill style of the vector object.")]
2112    pub fn fill(&self) -> Style {
2113        self.fill.clone()
2114    }
2115    /// Gets the fill rule of the VectorObject.
2116    #[wasm_bindgen(getter, return_description = "The fill rule of the vector object.")]
2117    pub fn fill_rule(&self) -> String {
2118        self.fill_rule.to_string()
2119    }
2120    /// Gets the stroke Style of the VectorObject.
2121    #[wasm_bindgen(getter, return_description = "The stroke style of the vector object.")]
2122    pub fn stroke(&self) -> Style {
2123        self.stroke.clone()
2124    }
2125    /// Gets the stroke width of the VectorObject.
2126    #[wasm_bindgen(getter, return_description = "The stroke width of the vector object.")]
2127    pub fn stroke_width(&self) -> f32 {
2128        self.stroke_width
2129    }
2130    /// Gets the stroke line cap of the VectorObject.
2131    #[wasm_bindgen(getter, return_description = "The stroke line cap of the vector object.")]
2132    pub fn stroke_line_cap(&self) -> String {
2133        self.stroke_line_cap.to_string()
2134    }
2135    /// Gets the stroke line join of the VectorObject.
2136    #[wasm_bindgen(getter, return_description = "The stroke line join of the vector object.")]
2137    pub fn stroke_line_join(&self) -> String {
2138        self.stroke_line_join.to_string()
2139    }
2140    /// Gets the stroke miter limit of VectorObject.
2141    #[wasm_bindgen(getter, return_description = "The stroke miter limit of the vector object.")]
2142    pub fn stroke_miter_limit(&self) -> f32 {
2143        self.stroke_miter_limit
2144    }
2145    /// Gets the stroke dash offset of the VectorObject.
2146    #[wasm_bindgen(getter, return_description = "The stroke dash offset of the vector object.")]
2147    pub fn stroke_dash_offset(&self) -> f32 {
2148        self.stroke_dash_offset
2149    }
2150    /// Gets the stroke dash array of the VectorObject.
2151    #[wasm_bindgen(getter, return_description = "The stroke dash array of the vector object.", unchecked_return_type = "number[]")]
2152    pub fn stroke_dash_array(&self) -> Vec<f32> {
2153        self.stroke_dash_array.to_vec()
2154    }
2155    /// Gets the children of the VectorObject.
2156    #[wasm_bindgen(getter, return_description = "The children of the vector object.")]
2157    pub fn children(&self) -> Vec<VectorObject> {
2158        self.children.clone()
2159    }
2160    /// Gets the name of the VectorObject.
2161    #[wasm_bindgen(getter, return_description = "The name of the vector object.")]
2162    pub fn name(&self) -> Option<String> {
2163        self.name.as_ref().map(|name| name.to_string())
2164    }
2165    /// Gets the transformation matrix of the VectorObject.
2166    #[wasm_bindgen(getter, return_description = "The transformation matrix of the vector object.")]
2167    pub fn transform(&self) -> TransformationMatrix {
2168        self.transform.clone()
2169    }
2170    /// Gets the Path2D with the applied TransformationMatrix.
2171    #[wasm_bindgen(getter, return_description = "The path of the vector object with the applied transform.")]
2172    pub fn actual_path(&self) -> Path2D {
2173        self.path.transform(&self.transform)
2174    }
2175    /// Gets the BoundingBox of the VectorObject.
2176    #[wasm_bindgen(return_description = "The bounding box of the vector object.")]
2177    pub fn bounding_box(
2178        &self,
2179        #[wasm_bindgen(param_description = "Whether to include the children of the vector object.")]
2180        recursive: Option<bool>
2181    ) -> Option<BoundingBox> {
2182        let path = self.actual_path();
2183        let mut bbox = BoundingBox::from_path(&path);
2184        if recursive.unwrap_or(true) {
2185            for child in self.children.iter() {
2186                let child_bbox = child.bounding_box(Some(true));
2187                bbox = BoundingBox::union(bbox, child_bbox);
2188            }
2189        }
2190        bbox
2191    }
2192    /// Gets the center Point2D of the VectorObject.
2193    #[wasm_bindgen(getter, return_description = "The center of the vector object.")]
2194    pub fn center(
2195        &self,
2196    ) -> Option<Point2D> {
2197        self.bounding_box(None).map(|bbox| bbox.center())
2198    }
2199    /// Gets the critical Point2D of the VectorObject.
2200    #[wasm_bindgen(return_description = "The critical point of the vector object.")]
2201    pub fn get_critical_point(
2202        &self,
2203        #[wasm_bindgen(param_description = "The x key of the critical point. If negative, the minimum x is returned. If positive, the maximum x is returned. If zero, the center x is returned.")]
2204        key_x: f32,
2205        #[wasm_bindgen(param_description = "The y key of the critical point. If negative, the minimum y is returned. If positive, the maximum y is returned. If zero, the center y is returned.")]
2206        key_y: f32,
2207        #[wasm_bindgen(param_description = "Whether to include the children of the vector object.")]
2208        recursive: Option<bool>
2209    ) -> Option<Point2D> {
2210        let bounding_box = self.bounding_box(recursive);
2211        if bounding_box.is_none() {
2212            return None;
2213        }
2214        let bounding_box = bounding_box.unwrap();
2215        let center = bounding_box.center();
2216        let min_x = bounding_box.min_x();
2217        let min_y = bounding_box.min_y();
2218        let width = bounding_box.width();
2219        let height = bounding_box.height();
2220        let x = if key_x < 0.0 {
2221            min_x
2222        } else if key_x > 0.0 {
2223            min_x + width
2224        } else {
2225            center.x
2226        };
2227        let y = if key_y < 0.0 {
2228            min_y
2229        } else if key_y > 0.0 {
2230            min_y + height
2231        } else {
2232            center.y
2233        };
2234        Some(Point2D { x, y })
2235    }
2236    /// Gets the children of the VectorObject recursively.
2237    #[wasm_bindgen(return_description = "The children of the vector object.")]
2238    pub fn get_children_recursive(
2239        &self,
2240        #[wasm_bindgen(param_description = "Whether to include the children of the children of the vector object, default is false.")]
2241        with_points: Option<bool>
2242    ) -> Vec<VectorObject> {
2243        let mut children = Vec::new();
2244        for child in self.children.iter() {
2245            if with_points.unwrap_or(false) {
2246                children.push(child.clone());
2247            }
2248            children.extend(child.get_children_recursive(with_points));
2249        }
2250        children
2251    }
2252    /// Gets the number of cubic bezier curves in the vector object.
2253    #[wasm_bindgen(getter, return_description = "The number of curves in the vector object.")]
2254    pub fn num_curves(&self) -> usize {
2255        self.path.len() / 4
2256    }
2257    /// Gets the number of points in the VectorObject's path.
2258    #[wasm_bindgen(getter, return_description = "The number of points in the vector object.")]
2259    pub fn num_points(&self) -> usize {
2260        self.path.len()
2261    }
2262    /// Gets the number of children in the VectorObject.
2263    #[wasm_bindgen(getter, return_description = "The number of children in the vector object.")]
2264    pub fn num_children(&self) -> usize {
2265        self.children.len()
2266    }
2267    /// Gets whether the VectorObject's path is closed.
2268    #[wasm_bindgen(getter, return_description = "Whether the vector object's path is closed.")]
2269    pub fn is_closed(&self) -> bool {
2270        self.path[0].equals(&self.path[self.path.len() - 1], None)
2271    }
2272    /// Gets the subpaths of the VectorObject.
2273    #[wasm_bindgen(getter, return_description = "The subpaths of the vector object.")]
2274    pub fn subpaths(&self) -> Vec<Path2D> {
2275        let rng = (4..self.path.len()).step_by(4);
2276        let filtered = rng.filter(|&i| !self.path[i - 1].equals(&self.path[i], None)).collect::<Vec<usize>>();
2277        let split_indices = vec![0].into_iter().chain(filtered).chain(vec![self.path.len()]).collect::<Vec<usize>>();
2278        let subpaths = split_indices.iter().zip(split_indices[1..].iter()).filter(|(start, end)| *end - *start >= 4).map(|(start, end)| self.path.slice(*start, *end)).collect();
2279        subpaths
2280    }
2281    /// Gets the width of the VectorObject.
2282    #[wasm_bindgen(getter, return_description = "The width of the vector object.")]
2283    pub fn width(&self) -> Option<f32> {
2284        self.bounding_box(None).map(|bbox| bbox.width())
2285    }
2286    /// Gets the height of the VectorObject.
2287    #[wasm_bindgen(getter, return_description = "The height of the vector object.")]
2288    pub fn height(&self) -> Option<f32> {
2289        self.bounding_box(None).map(|bbox| bbox.height())
2290    }
2291    /// Slices the VectorObject's children.
2292    #[wasm_bindgen(return_description = "The sliced children of the vector object.")]
2293    pub fn slice_children(
2294        &self,
2295        #[wasm_bindgen(param_description = "The start index of the children to slice.")]
2296        start: usize,
2297        #[wasm_bindgen(param_description = "The end index of the children to slice.")]
2298        end: usize
2299    ) -> Vec<VectorObject> {
2300        self.children[start..end].to_vec()
2301    }
2302    /// Gets the children of the VectorObject with the given names.
2303    #[wasm_bindgen(return_description = "The children with the given names.")]
2304    pub fn get_children_by_names(
2305        &self,
2306        #[wasm_bindgen(param_description = "The names of the children to get.", unchecked_param_type = "string[]")]
2307        names: Vec<String>
2308    ) -> Vec<VectorObject> {
2309        let mut children = Vec::new();
2310        for child in self.children.iter() {
2311            if let Some(name) = child.name() {
2312                if names.contains(&name) {
2313                    children.push(child.clone());
2314                }
2315            }
2316        }
2317        children
2318    }
2319}
2320
2321impl VectorObject {
2322    pub fn apply_operation(&mut self, operation: &dyn VectorOperation) {
2323        operation.apply(self);
2324    }
2325}