1use crate::{prelude::*, scalar, Path, PathDirection, PathFillType, Point, RRect, Rect, Vector};
2use skia_bindings::{self as sb, SkPathBuilder};
3use std::{fmt, mem};
4
5pub use skia_bindings::SkPathBuilder_ArcSize as ArcSize;
6variant_name!(ArcSize::Large);
7
8pub type PathBuilder = Handle<SkPathBuilder>;
9unsafe_send_sync!(PathBuilder);
10
11impl NativeDrop for SkPathBuilder {
12 fn drop(&mut self) {
13 unsafe { sb::C_SkPathBuilder_destruct(self) }
14 }
15}
16
17impl Clone for PathBuilder {
18 fn clone(&self) -> Self {
19 Self::construct(|pb: *mut SkPathBuilder| unsafe { sb::C_SkPathBuilder_CopyConstruct(uninitialized:pb, self.native()) })
20 }
21}
22
23impl fmt::Debug for PathBuilder {
24 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
25 f&mut DebugStruct<'_, '_>.debug_struct("PathBuilder")
26 .field(name:"fill_type", &self.fill_type())
27 .finish()
28 }
29}
30
31impl PathBuilder {
32 pub fn new() -> Self {
33 Self::construct(|pb| unsafe { sb::C_SkPathBuilder_Construct(pb) })
34 }
35
36 /* m87: No Implementation.
37 pub fn new_fill_type(fill_type: PathFillType) -> Self {
38 Self::construct(|pb| unsafe { sb::C_SkPathBuilder_Construct2(pb, fill_type) })
39 }
40 */
41
42 pub fn new_path(path: &Path) -> Self {
43 Self::construct(|pb| unsafe { sb::C_SkPathBuilder_Construct3(pb, path.native()) })
44 }
45
46 pub fn fill_type(&self) -> PathFillType {
47 self.native().fFillType
48 }
49
50 pub fn compute_bounds(&self) -> Rect {
51 Rect::construct(|r| unsafe { sb::C_SkPathBuilder_computeBounds(self.native(), r) })
52 }
53
54 pub fn snapshot(&self) -> Path {
55 let mut path = Path::default();
56 unsafe { sb::C_SkPathBuilder_snapshot(self.native(), path.native_mut()) }
57 path
58 }
59
60 pub fn detach(&mut self) -> Path {
61 let mut path = Path::default();
62 unsafe { sb::C_SkPathBuilder_detach(self.native_mut(), path.native_mut()) }
63 path
64 }
65
66 pub fn set_fill_type(&mut self, ft: PathFillType) -> &mut Self {
67 self.native_mut().fFillType = ft;
68 self
69 }
70
71 pub fn set_is_volatile(&mut self, is_volatile: bool) -> &mut Self {
72 self.native_mut().fIsVolatile = is_volatile;
73 self
74 }
75
76 pub fn reset(&mut self) -> &mut Self {
77 unsafe {
78 self.native_mut().reset();
79 }
80 self
81 }
82
83 pub fn move_to(&mut self, pt: impl Into<Point>) -> &mut Self {
84 unsafe {
85 self.native_mut().moveTo(pt.into().into_native());
86 }
87 self
88 }
89
90 pub fn line_to(&mut self, pt: impl Into<Point>) -> &mut Self {
91 unsafe {
92 self.native_mut().lineTo(pt.into().into_native());
93 }
94 self
95 }
96
97 pub fn quad_to(&mut self, p1: impl Into<Point>, p2: impl Into<Point>) -> &mut Self {
98 unsafe {
99 self.native_mut()
100 .quadTo(p1.into().into_native(), p2.into().into_native());
101 }
102 self
103 }
104
105 pub fn conic_to(&mut self, p1: impl Into<Point>, p2: impl Into<Point>, w: scalar) -> &mut Self {
106 unsafe {
107 self.native_mut()
108 .conicTo(p1.into().into_native(), p2.into().into_native(), w);
109 }
110 self
111 }
112
113 pub fn cubic_to(
114 &mut self,
115 p1: impl Into<Point>,
116 p2: impl Into<Point>,
117 p3: impl Into<Point>,
118 ) -> &mut Self {
119 unsafe {
120 self.native_mut().cubicTo(
121 p1.into().into_native(),
122 p2.into().into_native(),
123 p3.into().into_native(),
124 )
125 };
126 self
127 }
128
129 pub fn close(&mut self) -> &mut Self {
130 unsafe {
131 self.native_mut().close();
132 }
133 self
134 }
135
136 pub fn polyline_to(&mut self, points: &[Point]) -> &mut Self {
137 unsafe {
138 self.native_mut()
139 .polylineTo(points.native().as_ptr(), points.len().try_into().unwrap());
140 }
141 self
142 }
143
144 pub fn r_line_to(&mut self, pt: impl Into<Point>) -> &mut Self {
145 unsafe {
146 self.native_mut().rLineTo(pt.into().into_native());
147 }
148 self
149 }
150
151 pub fn r_quad_to(&mut self, pt1: impl Into<Point>, pt2: impl Into<Point>) -> &mut Self {
152 unsafe {
153 self.native_mut()
154 .rQuadTo(pt1.into().into_native(), pt2.into().into_native());
155 }
156 self
157 }
158
159 pub fn r_conic_to(
160 &mut self,
161 pt1: impl Into<Point>,
162 pt2: impl Into<Point>,
163 w: scalar,
164 ) -> &mut Self {
165 unsafe {
166 self.native_mut()
167 .rConicTo(pt1.into().into_native(), pt2.into().into_native(), w);
168 }
169 self
170 }
171
172 pub fn r_cubic_to(
173 &mut self,
174 pt1: impl Into<Point>,
175 pt2: impl Into<Point>,
176 pt3: impl Into<Point>,
177 ) -> &mut Self {
178 unsafe {
179 self.native_mut().rCubicTo(
180 pt1.into().into_native(),
181 pt2.into().into_native(),
182 pt3.into().into_native(),
183 );
184 }
185 self
186 }
187
188 pub fn arc_to(
189 &mut self,
190 oval: impl AsRef<Rect>,
191 start_angle_deg: scalar,
192 sweep_angle_deg: scalar,
193 force_move_to: bool,
194 ) -> &mut Self {
195 unsafe {
196 self.native_mut().arcTo(
197 oval.as_ref().native(),
198 start_angle_deg,
199 sweep_angle_deg,
200 force_move_to,
201 );
202 }
203 self
204 }
205
206 pub fn arc_to_tangent(
207 &mut self,
208 p1: impl Into<Point>,
209 p2: impl Into<Point>,
210 radius: scalar,
211 ) -> &mut Self {
212 unsafe {
213 self.native_mut()
214 .arcTo1(p1.into().into_native(), p2.into().into_native(), radius);
215 }
216 self
217 }
218
219 pub fn arc_to_radius(
220 &mut self,
221 r: impl Into<Point>,
222 x_axis_rotate: scalar,
223 large_arc: ArcSize,
224 sweep: PathDirection,
225 xy: impl Into<Point>,
226 ) -> &mut Self {
227 unsafe {
228 self.native_mut().arcTo2(
229 r.into().into_native(),
230 x_axis_rotate,
231 large_arc,
232 sweep,
233 xy.into().into_native(),
234 );
235 }
236 self
237 }
238
239 pub fn add_arc(
240 &mut self,
241 oval: impl AsRef<Rect>,
242 start_angle_deg: scalar,
243 sweep_angle_deg: scalar,
244 ) -> &mut Self {
245 unsafe {
246 self.native_mut()
247 .addArc(oval.as_ref().native(), start_angle_deg, sweep_angle_deg);
248 }
249 self
250 }
251
252 pub fn add_rect(
253 &mut self,
254 rect: impl AsRef<Rect>,
255 dir: impl Into<Option<PathDirection>>,
256 start_index: impl Into<Option<usize>>,
257 ) -> &mut Self {
258 let dir = dir.into().unwrap_or(PathDirection::CW);
259 let start_index = start_index.into().unwrap_or(0);
260 unsafe {
261 self.native_mut()
262 .addRect(rect.as_ref().native(), dir, start_index.try_into().unwrap());
263 }
264 self
265 }
266
267 pub fn add_oval(
268 &mut self,
269 rect: impl AsRef<Rect>,
270 dir: impl Into<Option<PathDirection>>,
271 start_index: impl Into<Option<usize>>,
272 ) -> &mut Self {
273 let dir = dir.into().unwrap_or(PathDirection::CW);
274 // m86: default start index changed from 0 to 1
275 let start_index = start_index.into().unwrap_or(1);
276 unsafe {
277 self.native_mut()
278 .addOval(rect.as_ref().native(), dir, start_index.try_into().unwrap());
279 }
280 self
281 }
282
283 pub fn add_rrect(
284 &mut self,
285 rect: impl AsRef<RRect>,
286 dir: impl Into<Option<PathDirection>>,
287 start_index: impl Into<Option<usize>>,
288 ) -> &mut Self {
289 let dir = dir.into().unwrap_or(PathDirection::CW);
290 // m86: default start index changed from 0 to 6 or 7 depending on the path's direction.
291 let start_index =
292 start_index
293 .into()
294 .unwrap_or(if dir == PathDirection::CW { 6 } else { 7 });
295 unsafe {
296 self.native_mut().addRRect(
297 rect.as_ref().native(),
298 dir,
299 start_index.try_into().unwrap(),
300 );
301 }
302 self
303 }
304
305 pub fn add_circle(
306 &mut self,
307 center: impl Into<Point>,
308 radius: scalar,
309 dir: impl Into<Option<PathDirection>>,
310 ) -> &mut Self {
311 let center = center.into();
312 let dir = dir.into().unwrap_or(PathDirection::CW);
313 unsafe {
314 self.native_mut().addCircle(center.x, center.y, radius, dir);
315 }
316 self
317 }
318
319 pub fn add_polygon(&mut self, pts: &[Point], is_closed: bool) -> &mut Self {
320 unsafe {
321 self.native_mut().addPolygon(
322 pts.native().as_ptr(),
323 pts.len().try_into().unwrap(),
324 is_closed,
325 );
326 }
327 self
328 }
329
330 pub fn add_path(&mut self, path: &Path) -> &mut Self {
331 unsafe { self.native_mut().addPath(path.native()) };
332 self
333 }
334
335 pub fn inc_reserve(&mut self, extra_pt_count: usize, extra_verb_count: usize) {
336 unsafe {
337 self.native_mut().incReserve(
338 extra_pt_count.try_into().unwrap(),
339 extra_verb_count.try_into().unwrap(),
340 )
341 }
342 }
343
344 pub fn offset(&mut self, d: impl Into<Vector>) -> &mut Self {
345 let d = d.into();
346 unsafe {
347 self.native_mut().offset(d.x, d.y);
348 }
349 self
350 }
351
352 pub fn toggle_inverse_fill_type(&mut self) -> &mut Self {
353 let n = self.native_mut();
354 n.fFillType = unsafe { mem::transmute(n.fFillType as i32 ^ 2) };
355 self
356 }
357
358 #[deprecated(since = "0.35.0", note = "Removed without replacement")]
359 pub fn make(
360 _points: &[Point],
361 _verbs: &[u8],
362 _conic_weights: &[scalar],
363 _fill_type: PathFillType,
364 _is_volatile: impl Into<Option<bool>>,
365 ) -> ! {
366 panic!("Removed without replacement");
367 }
368}
369
370#[test]
371fn test_creation_snapshot_and_detach() {
372 let mut builder: Handle = PathBuilder::new();
373 let _path: Handle = builder.snapshot();
374 let _path: Handle = builder.detach();
375}
376