skia_safe/core/
stroke_rec.rs1use crate::PathBuilder;
2use crate::{paint, prelude::*, scalar, Paint, Path};
3use skia_bindings::{self as sb, SkStrokeRec};
4use std::fmt;
5
6pub use sb::SkStrokeRec_InitStyle as InitStyle;
7variant_name!(InitStyle::Hairline);
8
9pub use sb::SkStrokeRec_Style as Style;
10variant_name!(Style::Stroke);
11
12pub type StrokeRec = Handle<SkStrokeRec>;
13unsafe_send_sync!(StrokeRec);
14
15impl NativeDrop for SkStrokeRec {
16 fn drop(&mut self) {
17 unsafe { sb::C_SkStrokeRec_destruct(self) };
18 }
19}
20
21impl NativeClone for SkStrokeRec {
22 fn clone(&self) -> Self {
23 let mut copy = StrokeRec::new_hairline();
24 unsafe { sb::C_SkStrokeRec_copy(self, copy.native_mut()) }
25 *copy.native()
26 }
27}
28
29impl fmt::Debug for StrokeRec {
30 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
31 f.debug_struct("StrokeRec")
32 .field("style", &self.style())
33 .field("width", &self.width())
34 .field("miter", &self.miter())
35 .field("cap", &self.cap())
36 .field("join", &self.join())
37 .field("res_scale", &self.res_scale())
38 .finish()
39 }
40}
41
42impl StrokeRec {
43 pub fn new(init_style: InitStyle) -> Self {
44 Self::from_native_c(unsafe { SkStrokeRec::new(init_style) })
45 }
46
47 pub fn new_hairline() -> Self {
49 Self::new(InitStyle::Hairline)
50 }
51
52 pub fn new_fill() -> Self {
54 Self::new(InitStyle::Fill)
55 }
56
57 pub fn from_paint(
58 paint: &Paint,
59 style: impl Into<Option<paint::Style>>,
60 res_scale: impl Into<Option<scalar>>,
61 ) -> Self {
62 let res_scale = res_scale.into().unwrap_or(1.0);
63 Self::from_native_c(unsafe {
64 match style.into() {
65 Some(style) => SkStrokeRec::new1(paint.native(), style, res_scale),
66 None => SkStrokeRec::new2(paint.native(), res_scale),
67 }
68 })
69 }
70
71 pub fn style(&self) -> Style {
72 unsafe { self.native().getStyle() }
73 }
74
75 pub fn width(&self) -> scalar {
76 self.native().fWidth
77 }
78
79 pub fn miter(&self) -> scalar {
80 self.native().fMiterLimit
81 }
82
83 pub fn cap(&self) -> paint::Cap {
84 unsafe { sb::C_SkStrokeRec_getCap(self.native()) }
85 }
86
87 pub fn join(&self) -> paint::Join {
88 unsafe { sb::C_SkStrokeRec_getJoin(self.native()) }
89 }
90
91 pub fn is_hairline_style(&self) -> bool {
92 self.style() == Style::Hairline
93 }
94
95 pub fn is_fill_style(&self) -> bool {
96 self.style() == Style::Fill
97 }
98
99 pub fn set_fill_style(&mut self) -> &mut Self {
100 unsafe { self.native_mut().setFillStyle() }
101 self
102 }
103
104 pub fn set_hairline_style(&mut self) -> &mut Self {
105 unsafe { self.native_mut().setHairlineStyle() }
106 self
107 }
108
109 pub fn set_stroke_style(
110 &mut self,
111 width: scalar,
112 stroke_and_fill: impl Into<Option<bool>>,
113 ) -> &mut Self {
114 let stroke_and_fill = stroke_and_fill.into().unwrap_or(false);
115 unsafe { self.native_mut().setStrokeStyle(width, stroke_and_fill) }
116 self
117 }
118
119 pub fn set_stroke_params(
120 &mut self,
121 cap: paint::Cap,
122 join: paint::Join,
123 miter_limit: scalar,
124 ) -> &mut Self {
125 let native = self.native_mut();
126 native.set_fCap(cap as _);
127 native.set_fJoin(join as _);
128 native.fMiterLimit = miter_limit;
129 self
130 }
131
132 pub fn res_scale(&self) -> scalar {
133 self.native().fResScale
134 }
135
136 pub fn set_res_scale(&mut self, rs: scalar) {
137 debug_assert!(rs > 0.0 && rs.is_finite());
138 self.native_mut().fResScale = rs;
139 }
140
141 pub fn need_to_apply(&self) -> bool {
142 let style = self.style();
143 style == Style::Stroke || style == Style::StrokeAndFill
144 }
145
146 pub fn apply_to_path(&self, dst: &mut PathBuilder, src: &Path) -> bool {
147 unsafe { self.native().applyToPath(dst.native_mut(), src.native()) }
148 }
149
150 #[deprecated(since = "0.88.0", note = "Use apply_to_path()")]
151 pub fn apply_to_path_inplace(&self, path: &mut Path) -> bool {
152 let mut builder = PathBuilder::default();
153 let r = unsafe {
154 self.native()
155 .applyToPath(builder.native_mut(), path.native())
156 };
157 if r {
158 *path = builder.into()
159 }
160 r
161 }
162
163 pub fn apply_to_paint(&self, paint: &mut Paint) {
164 unsafe { self.native().applyToPaint(paint.native_mut()) }
165 }
166
167 pub fn inflation_radius(&self) -> scalar {
168 unsafe { self.native().getInflationRadius() }
169 }
170
171 pub fn inflation_radius_from_paint_and_style(paint: &Paint, style: paint::Style) -> scalar {
172 unsafe { SkStrokeRec::GetInflationRadius(paint.native(), style) }
173 }
174
175 pub fn inflation_radius_from_params(
176 join: paint::Join,
177 miter_limit: scalar,
178 cap: paint::Cap,
179 stroke_width: scalar,
180 ) -> scalar {
181 unsafe { SkStrokeRec::GetInflationRadius1(join, miter_limit, cap, stroke_width) }
182 }
183
184 pub fn has_equal_effect(&self, other: &StrokeRec) -> bool {
185 unsafe { sb::C_SkStrokeRec_hasEqualEffect(self.native(), other.native()) }
186 }
187}