rustmotion_core/engine/renderer/
shapes.rs1use skia_safe::{Canvas, Paint, Rect};
2
3use crate::schema::ShapeType;
4
5pub fn build_shape_path(
7 shape_type: &ShapeType,
8 x: f32,
9 y: f32,
10 w: f32,
11 h: f32,
12 corner_radius: Option<f32>,
13) -> Option<skia_safe::Path> {
14 match shape_type {
15 ShapeType::Rect => {
16 let mut path = skia_safe::PathBuilder::new();
17 path.add_rect(Rect::from_xywh(x, y, w, h), None, None);
18 Some(path.detach())
19 }
20 ShapeType::RoundedRect => {
21 let r = corner_radius.unwrap_or(8.0);
22 let rrect = skia_safe::RRect::new_rect_xy(Rect::from_xywh(x, y, w, h), r, r);
23 let mut path = skia_safe::PathBuilder::new();
24 path.add_rrect(rrect, None, None);
25 Some(path.detach())
26 }
27 ShapeType::Circle => {
28 let radius = w.min(h) / 2.0;
29 let mut path = skia_safe::PathBuilder::new();
30 path.add_circle((x + w / 2.0, y + h / 2.0), radius, None);
31 Some(path.detach())
32 }
33 ShapeType::Ellipse => {
34 let mut path = skia_safe::PathBuilder::new();
35 path.add_oval(Rect::from_xywh(x, y, w, h), None, None);
36 Some(path.detach())
37 }
38 ShapeType::Triangle => {
39 let mut path = skia_safe::PathBuilder::new();
40 path.move_to((x + w / 2.0, y));
41 path.line_to((x + w, y + h));
42 path.line_to((x, y + h));
43 path.close();
44 Some(path.detach())
45 }
46 ShapeType::Star { points } => {
47 let cx = x + w / 2.0;
48 let cy = y + h / 2.0;
49 let outer_r = w.min(h) / 2.0;
50 let inner_r = outer_r * 0.4;
51 let n = *points as usize;
52 let mut path = skia_safe::PathBuilder::new();
53 for i in 0..(n * 2) {
54 let angle =
55 (i as f32) * std::f32::consts::PI / n as f32 - std::f32::consts::FRAC_PI_2;
56 let r = if i % 2 == 0 { outer_r } else { inner_r };
57 let px = cx + r * angle.cos();
58 let py = cy + r * angle.sin();
59 if i == 0 {
60 path.move_to((px, py));
61 } else {
62 path.line_to((px, py));
63 }
64 }
65 path.close();
66 Some(path.detach())
67 }
68 ShapeType::Polygon { sides } => {
69 let cx = x + w / 2.0;
70 let cy = y + h / 2.0;
71 let r = w.min(h) / 2.0;
72 let n = *sides as usize;
73 let mut path = skia_safe::PathBuilder::new();
74 for i in 0..n {
75 let angle = (i as f32) * 2.0 * std::f32::consts::PI / n as f32
76 - std::f32::consts::FRAC_PI_2;
77 let px = cx + r * angle.cos();
78 let py = cy + r * angle.sin();
79 if i == 0 {
80 path.move_to((px, py));
81 } else {
82 path.line_to((px, py));
83 }
84 }
85 path.close();
86 Some(path.detach())
87 }
88 ShapeType::Path { data } => skia_safe::Path::from_svg(data),
89 }
90}
91
92pub fn draw_shape_path(
93 canvas: &Canvas,
94 shape_type: &ShapeType,
95 x: f32,
96 y: f32,
97 w: f32,
98 h: f32,
99 corner_radius: Option<f32>,
100 paint: &Paint,
101) {
102 let rect = Rect::from_xywh(x, y, w, h);
103 match shape_type {
104 ShapeType::Rect => {
105 canvas.draw_rect(rect, paint);
106 }
107 ShapeType::RoundedRect => {
108 let r = corner_radius.unwrap_or(8.0);
109 let rrect = skia_safe::RRect::new_rect_xy(rect, r, r);
110 canvas.draw_rrect(rrect, paint);
111 }
112 ShapeType::Circle => {
113 let radius = w.min(h) / 2.0;
114 canvas.draw_circle((x + w / 2.0, y + h / 2.0), radius, paint);
115 }
116 ShapeType::Ellipse => {
117 canvas.draw_oval(rect, paint);
118 }
119 ShapeType::Triangle => {
120 let mut path = skia_safe::PathBuilder::new();
121 path.move_to((x + w / 2.0, y));
122 path.line_to((x + w, y + h));
123 path.line_to((x, y + h));
124 path.close();
125 canvas.draw_path(&path.detach(), paint);
126 }
127 ShapeType::Star { points } => {
128 let cx = x + w / 2.0;
129 let cy = y + h / 2.0;
130 let outer_r = w.min(h) / 2.0;
131 let inner_r = outer_r * 0.4;
132 let n = *points as usize;
133 let mut path = skia_safe::PathBuilder::new();
134 for i in 0..(n * 2) {
135 let angle =
136 (i as f32) * std::f32::consts::PI / n as f32 - std::f32::consts::FRAC_PI_2;
137 let r = if i % 2 == 0 { outer_r } else { inner_r };
138 let px = cx + r * angle.cos();
139 let py = cy + r * angle.sin();
140 if i == 0 {
141 path.move_to((px, py));
142 } else {
143 path.line_to((px, py));
144 }
145 }
146 path.close();
147 canvas.draw_path(&path.detach(), paint);
148 }
149 ShapeType::Polygon { sides } => {
150 let cx = x + w / 2.0;
151 let cy = y + h / 2.0;
152 let r = w.min(h) / 2.0;
153 let n = *sides as usize;
154 let mut path = skia_safe::PathBuilder::new();
155 for i in 0..n {
156 let angle = (i as f32) * 2.0 * std::f32::consts::PI / n as f32
157 - std::f32::consts::FRAC_PI_2;
158 let px = cx + r * angle.cos();
159 let py = cy + r * angle.sin();
160 if i == 0 {
161 path.move_to((px, py));
162 } else {
163 path.line_to((px, py));
164 }
165 }
166 path.close();
167 canvas.draw_path(&path.detach(), paint);
168 }
169 ShapeType::Path { data } => {
170 if let Some(path) = skia_safe::Path::from_svg(data) {
171 canvas.draw_path(&path, paint);
172 }
173 }
174 }
175}