1use crate::path::Path;
4use crate::pathkit;
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
8pub enum StrokeCap {
9 #[default]
11 Butt = 0,
12 Round = 1,
14 Square = 2,
16}
17
18#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
20pub enum StrokeJoin {
21 #[default]
23 Miter = 0,
24 Round = 1,
26 Bevel = 2,
28}
29
30impl From<StrokeCap> for pathkit::SkPaint_Cap::Type {
31 fn from(c: StrokeCap) -> Self {
32 match c {
33 StrokeCap::Butt => pathkit::SkPaint_Cap::kButt_Cap,
34 StrokeCap::Round => pathkit::SkPaint_Cap::kRound_Cap,
35 StrokeCap::Square => pathkit::SkPaint_Cap::kSquare_Cap,
36 }
37 }
38}
39
40impl From<u32> for StrokeCap {
41 fn from(v: u32) -> Self {
42 match v {
43 1 => StrokeCap::Round,
44 2 => StrokeCap::Square,
45 _ => StrokeCap::Butt,
46 }
47 }
48}
49
50impl From<StrokeJoin> for pathkit::SkPaint_Join::Type {
51 fn from(j: StrokeJoin) -> Self {
52 match j {
53 StrokeJoin::Miter => pathkit::SkPaint_Join::kMiter_Join,
54 StrokeJoin::Round => pathkit::SkPaint_Join::kRound_Join,
55 StrokeJoin::Bevel => pathkit::SkPaint_Join::kBevel_Join,
56 }
57 }
58}
59
60impl From<u32> for StrokeJoin {
61 fn from(v: u32) -> Self {
62 match v {
63 1 => StrokeJoin::Round,
64 2 => StrokeJoin::Bevel,
65 _ => StrokeJoin::Miter,
66 }
67 }
68}
69
70#[derive(Debug, Clone, Copy, PartialEq)]
72pub enum StrokeStyle {
73 Hairline,
75 Fill,
77 Stroke { width: f32, stroke_and_fill: bool },
79 StrokeAndFill { width: f32 },
81}
82
83pub struct StrokeRec {
89 inner: pathkit::SkStrokeRec,
90}
91
92impl StrokeRec {
93 pub fn new_fill() -> Self {
95 Self {
96 inner: unsafe {
97 pathkit::SkStrokeRec::new(pathkit::SkStrokeRec_InitStyle::kFill_InitStyle)
98 },
99 }
100 }
101
102 pub fn new_hairline() -> Self {
104 Self {
105 inner: unsafe {
106 pathkit::SkStrokeRec::new(pathkit::SkStrokeRec_InitStyle::kHairline_InitStyle)
107 },
108 }
109 }
110
111 pub fn new_stroke(width: f32, stroke_and_fill: bool) -> Self {
113 let mut rec = Self::new_hairline();
114 unsafe {
115 rec.inner.setStrokeStyle(width, stroke_and_fill);
116 }
117 rec
118 }
119
120 pub fn set_fill(&mut self) {
122 unsafe {
123 self.inner.setFillStyle();
124 }
125 }
126
127 pub fn set_hairline(&mut self) {
129 unsafe {
130 self.inner.setHairlineStyle();
131 }
132 }
133
134 pub fn set_stroke_style(&mut self, width: f32, stroke_and_fill: bool) {
136 unsafe {
137 self.inner.setStrokeStyle(width, stroke_and_fill);
138 }
139 }
140
141 pub fn set_cap(&mut self, cap: StrokeCap) {
143 self.inner.set_fCap(cap as u32);
144 }
145
146 pub fn set_join(&mut self, join: StrokeJoin) {
148 self.inner.set_fJoin(join as u32);
149 }
150
151 pub fn set_stroke_params(&mut self, cap: StrokeCap, join: StrokeJoin, miter_limit: f32) {
153 self.inner.set_fCap(cap as u32);
154 self.inner.set_fJoin(join as u32);
155 self.inner.fMiterLimit = miter_limit;
156 }
157
158 pub fn cap(&self) -> StrokeCap {
160 StrokeCap::from(self.inner.fCap())
161 }
162
163 pub fn join(&self) -> StrokeJoin {
165 StrokeJoin::from(self.inner.fJoin())
166 }
167
168 pub fn miter_limit(&self) -> f32 {
170 self.inner.fMiterLimit
171 }
172
173 pub fn style(&self) -> StrokeStyle {
175 let raw = unsafe { self.inner.getStyle() };
176 match raw {
177 pathkit::SkStrokeRec_Style::kHairline_Style => StrokeStyle::Hairline,
178 pathkit::SkStrokeRec_Style::kFill_Style => StrokeStyle::Fill,
179 pathkit::SkStrokeRec_Style::kStroke_Style => StrokeStyle::Stroke {
180 width: self.inner.fWidth,
181 stroke_and_fill: false,
182 },
183 pathkit::SkStrokeRec_Style::kStrokeAndFill_Style => StrokeStyle::StrokeAndFill {
184 width: self.inner.fWidth,
185 },
186 _ => StrokeStyle::Fill,
187 }
188 }
189
190 pub fn width(&self) -> f32 {
192 self.inner.fWidth
193 }
194
195 pub fn inflation_radius(&self) -> f32 {
197 unsafe { self.inner.getInflationRadius() }
198 }
199
200 pub fn apply_to_path(&self, path: &Path) -> Option<Path> {
206 let mut dst = Path::new();
207 let ok = unsafe {
208 pathkit::SkStrokeRec_applyToPath(
209 &self.inner as *const _,
210 dst.as_raw_mut() as *mut _,
211 path.as_raw() as *const _,
212 )
213 };
214 if ok {
215 Some(dst)
216 } else {
217 None
218 }
219 }
220
221 #[allow(dead_code)]
223 pub(crate) fn as_raw(&self) -> &pathkit::SkStrokeRec {
224 &self.inner
225 }
226
227 #[allow(dead_code)]
229 pub(crate) fn as_raw_mut(&mut self) -> &mut pathkit::SkStrokeRec {
230 &mut self.inner
231 }
232}
233
234impl Default for StrokeRec {
235 fn default() -> Self {
236 Self::new_fill()
237 }
238}