ferroui_base/platform/
path_geometry_context.rs1use crate::media::{
2 ArcSegment, BezierSegment, FillRule, LineSegment, PathFigure, PathFigures, PathGeometry, PathSegments,
3 QuadraticBezierSegment, SweepDirection,
4};
5use crate::platform::IGeometryContext;
6use crate::{Point, Ref, Size};
7
8pub struct PathGeometryContext {
11 current_figure: Option<Ref<PathFigure>>,
12 path_geometry: Option<Ref<PathGeometry>>,
13}
14
15impl PathGeometryContext {
16 pub fn new(path_geometry: Ref<PathGeometry>) -> Self {
17 Self { current_figure: None, path_geometry: Some(path_geometry) }
18 }
19
20 fn path_geometry(&self) -> &Ref<PathGeometry> {
21 self.path_geometry.as_ref().expect("PathGeometryContext is disposed")
22 }
23
24 fn current_figure_segments(&self) -> PathSegments {
25 let _ = self.path_geometry();
26 let Some(figure) = &self.current_figure else {
27 panic!("No figure in progress.");
28 };
29 figure.segments().expect("Current figure's segments cannot be null.")
30 }
31}
32
33impl IGeometryContext for PathGeometryContext {
34 fn arc_to(
35 &mut self,
36 point: Point,
37 size: Size,
38 rotation_angle: f64,
39 is_large_arc: bool,
40 sweep_direction: SweepDirection,
41 is_stroked: bool,
42 ) {
43 let arc_segment = ArcSegment::new();
44 arc_segment.set_size(size);
45 arc_segment.set_rotation_angle(rotation_angle);
46 arc_segment.set_is_large_arc(is_large_arc);
47 arc_segment.set_sweep_direction(sweep_direction);
48 arc_segment.set_point(point);
49 arc_segment.set_is_stroked(is_stroked);
50 self.current_figure_segments().add(arc_segment.upcast());
51 }
52
53 fn begin_figure(&mut self, start_point: Point, is_filled: bool) {
54 let path_geometry = self.path_geometry().clone();
55
56 let figure = PathFigure::new();
57 figure.set_start_point(start_point);
58 figure.set_is_closed(false);
59 figure.set_is_filled(is_filled);
60
61 let figures = match path_geometry.figures() {
62 Some(figures) => figures,
63 None => {
64 let figures = PathFigures::new();
65 path_geometry.set_figures(Some(figures.clone()));
66 figures
67 }
68 };
69 figures.add(figure.clone());
70 self.current_figure = Some(figure);
71 }
72
73 fn cubic_bezier_to(&mut self, control_point1: Point, control_point2: Point, end_point: Point, is_stroked: bool) {
74 let bezier_segment = BezierSegment::new();
75 bezier_segment.set_point1(control_point1);
76 bezier_segment.set_point2(control_point2);
77 bezier_segment.set_point3(end_point);
78 bezier_segment.set_is_stroked(is_stroked);
79 self.current_figure_segments().add(bezier_segment.upcast());
80 }
81
82 fn quadratic_bezier_to(&mut self, control_point: Point, end_point: Point, is_stroked: bool) {
83 let quadratic_bezier_segment = QuadraticBezierSegment::new();
84 quadratic_bezier_segment.set_point1(control_point);
85 quadratic_bezier_segment.set_point2(end_point);
86 quadratic_bezier_segment.set_is_stroked(is_stroked);
87 self.current_figure_segments().add(quadratic_bezier_segment.upcast());
88 }
89
90 fn line_to(&mut self, point: Point, is_stroked: bool) {
91 let line_segment = LineSegment::new();
92 line_segment.set_point(point);
93 line_segment.set_is_stroked(is_stroked);
94 self.current_figure_segments().add(line_segment.upcast());
95 }
96
97 fn end_figure(&mut self, is_closed: bool) {
98 if let Some(figure) = &self.current_figure {
99 figure.set_is_closed(is_closed);
100 }
101
102 self.current_figure = None;
103 }
104
105 fn set_fill_rule(&mut self, fill_rule: FillRule) {
106 self.path_geometry().set_fill_rule(fill_rule);
107 }
108
109 fn dispose(&mut self) {
110 self.path_geometry = None;
111 }
112}