skia_safe/core/
path_builder.rs

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| unsafe { sb::C_SkPathBuilder_CopyConstruct(pb, self.native()) })
20    }
21}
22
23impl fmt::Debug for PathBuilder {
24    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
25        f.debug_struct("PathBuilder")
26            .field("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::<i32, sb::SkPathFillType>(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#[cfg(test)]
371mod tests {
372    use super::*;
373
374    #[test]
375    fn test_creation_snapshot_and_detach() {
376        let mut builder = PathBuilder::new();
377        let _path = builder.snapshot();
378        let _path = builder.detach();
379    }
380}