skia_safe/core/
path_effect.rs

1use crate::{prelude::*, Matrix, NativeFlattenable, Path, PathBuilder, Rect, StrokeRec};
2use sb::SkPathEffect_INHERITED;
3use skia_bindings::{self as sb, SkFlattenable, SkPathEffect, SkRefCntBase};
4use std::fmt;
5
6pub type PathEffect = RCHandle<SkPathEffect>;
7unsafe_send_sync!(PathEffect);
8require_type_equality!(SkPathEffect_INHERITED, SkFlattenable);
9
10impl NativeBase<SkRefCntBase> for SkPathEffect {}
11impl NativeBase<SkFlattenable> for SkPathEffect {}
12
13impl NativeRefCountedBase for SkPathEffect {
14    type Base = SkRefCntBase;
15}
16
17impl NativeFlattenable for SkPathEffect {
18    fn native_flattenable(&self) -> &SkFlattenable {
19        self.base()
20    }
21
22    fn native_deserialize(data: &[u8]) -> *mut Self {
23        unsafe { sb::C_SkPathEffect_Deserialize(data.as_ptr() as _, data.len()) }
24    }
25}
26
27impl fmt::Debug for PathEffect {
28    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
29        f.debug_struct("PathEffect")
30            .field("needs_ctm", &self.needs_ctm())
31            .finish()
32    }
33}
34
35impl PathEffect {
36    pub fn sum(first: impl Into<PathEffect>, second: impl Into<PathEffect>) -> PathEffect {
37        PathEffect::from_ptr(unsafe {
38            sb::C_SkPathEffect_MakeSum(first.into().into_ptr(), second.into().into_ptr())
39        })
40        .unwrap()
41    }
42
43    pub fn compose(first: impl Into<PathEffect>, second: impl Into<PathEffect>) -> PathEffect {
44        PathEffect::from_ptr(unsafe {
45            sb::C_SkPathEffect_MakeCompose(first.into().into_ptr(), second.into().into_ptr())
46        })
47        .unwrap()
48    }
49
50    pub fn filter_path(
51        &self,
52        src: &Path,
53        stroke_rec: &StrokeRec,
54        cull_rect: impl AsRef<Rect>,
55    ) -> Option<(PathBuilder, StrokeRec)> {
56        let mut dst = PathBuilder::new();
57        let mut stroke_rec_r = stroke_rec.clone();
58        self.filter_path_inplace(&mut dst, src, &mut stroke_rec_r, cull_rect)
59            .then_some((dst, stroke_rec_r))
60    }
61
62    pub fn filter_path_inplace(
63        &self,
64        dst: &mut PathBuilder,
65        src: &Path,
66        stroke_rec: &mut StrokeRec,
67        cull_rect: impl AsRef<Rect>,
68    ) -> bool {
69        unsafe {
70            self.native().filterPath(
71                dst.native_mut(),
72                src.native(),
73                stroke_rec.native_mut(),
74                cull_rect.as_ref().native(),
75                Matrix::new_identity().native(),
76            )
77        }
78    }
79
80    pub fn filter_path_inplace_with_matrix(
81        &self,
82        dst: &mut PathBuilder,
83        src: &Path,
84        stroke_rec: &mut StrokeRec,
85        cull_rect: impl AsRef<Rect>,
86        ctm: &Matrix,
87    ) -> bool {
88        unsafe {
89            self.native().filterPath(
90                dst.native_mut(),
91                src.native(),
92                stroke_rec.native_mut(),
93                cull_rect.as_ref().native(),
94                ctm.native(),
95            )
96        }
97    }
98
99    pub fn needs_ctm(&self) -> bool {
100        unsafe { self.native().needsCTM() }
101    }
102}