1use crate::Blender;
2use crate::{
3 prelude::*, scalar, BlendMode, Color, Color4f, ColorFilter, ColorSpace, ImageFilter,
4 MaskFilter, PathEffect, Shader,
5};
6use core::fmt;
7
8use skia_bindings::{self as sb, SkPaint};
9
10pub use sb::SkPaint_Style as Style;
11variant_name!(Style::Fill);
12
13pub use sb::SkPaint_Cap as Cap;
14variant_name!(Cap::Butt);
15
16pub use sb::SkPaint_Join as Join;
17variant_name!(Join::Miter);
18
19pub type Paint = Handle<SkPaint>;
20unsafe_send_sync!(Paint);
21
22impl NativeDrop for SkPaint {
23 fn drop(&mut self) {
24 unsafe { sb::C_SkPaint_destruct(self) }
25 }
26}
27
28impl NativeClone for SkPaint {
29 fn clone(&self) -> Self {
30 unsafe { SkPaint::new2(self) }
31 }
32}
33
34impl NativePartialEq for SkPaint {
35 fn eq(&self, rhs: &Self) -> bool {
36 unsafe { sb::C_SkPaint_Equals(self, rhs) }
37 }
38}
39
40impl Default for Handle<SkPaint> {
41 fn default() -> Self {
42 Paint::from_native_c(unsafe { SkPaint::new() })
43 }
44}
45
46impl fmt::Debug for Paint {
47 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
48 f&mut DebugStruct<'_, '_>.debug_struct("Paint")
49 .field("is_anti_alias", &self.is_anti_alias())
50 .field("is_dither", &self.is_dither())
51 .field("style", &self.style())
52 .field("color", &self.color4f())
53 .field("stroke_width", &self.stroke_width())
54 .field("stroke_miter", &self.stroke_miter())
55 .field("stroke_cap", &self.stroke_cap())
56 .field("stroke_join", &self.stroke_join())
57 .field("color_filter", &self.color_filter())
58 .field("blend_mode", &self.as_blend_mode())
59 .field("path_effect", &self.path_effect())
60 .field("mask_filter", &self.mask_filter())
61 .field(name:"image_filter", &self.image_filter())
62 .finish()
63 }
64}
65
66impl Paint {
67 pub fn new<'a>(
68 color: impl AsRef<Color4f>,
69 color_space: impl Into<Option<&'a ColorSpace>>,
70 ) -> Paint {
71 let color_space = color_space.into();
72 Paint::from_native_c(unsafe {
73 SkPaint::new1(
74 color.as_ref().native(),
75 color_space.native_ptr_or_null_mut_force(),
76 )
77 })
78 }
79
80 pub fn reset(&mut self) -> &mut Self {
81 unsafe { self.native_mut().reset() }
82 self
83 }
84
85 pub fn is_anti_alias(&self) -> bool {
86 unsafe { self.native().__bindgen_anon_1.fBitfields.fAntiAlias() != 0 }
87 }
88
89 pub fn set_anti_alias(&mut self, anti_alias: bool) -> &mut Self {
90 unsafe {
91 self.native_mut()
92 .__bindgen_anon_1
93 .fBitfields
94 .set_fAntiAlias(anti_alias as _);
95 }
96 self
97 }
98
99 pub fn is_dither(&self) -> bool {
100 unsafe { self.native().__bindgen_anon_1.fBitfields.fDither() != 0 }
101 }
102
103 pub fn set_dither(&mut self, dither: bool) -> &mut Self {
104 unsafe {
105 self.native_mut()
106 .__bindgen_anon_1
107 .fBitfields
108 .set_fDither(dither as _);
109 }
110 self
111 }
112
113 pub fn style(&self) -> Style {
114 unsafe { sb::C_SkPaint_getStyle(self.native()) }
115 }
116
117 pub fn set_style(&mut self, style: Style) -> &mut Self {
118 unsafe { self.native_mut().setStyle(style) }
119 self
120 }
121
122 pub fn set_stroke(&mut self, stroke: bool) -> &mut Self {
123 unsafe { self.native_mut().setStroke(stroke) }
124 self
125 }
126
127 pub fn color(&self) -> Color {
128 self.color4f().to_color()
129 }
130
131 pub fn color4f(&self) -> Color4f {
132 Color4f::from_native_c(self.native().fColor4f)
133 }
134
135 pub fn set_color(&mut self, color: impl Into<Color>) -> &mut Self {
136 let color = color.into();
137 unsafe { self.native_mut().setColor(color.into_native()) }
138 self
139 }
140
141 pub fn set_color4f<'a>(
142 &mut self,
143 color: impl AsRef<Color4f>,
144 color_space: impl Into<Option<&'a ColorSpace>>,
145 ) -> &mut Self {
146 let color_space: Option<&'a ColorSpace> = color_space.into();
147 unsafe {
148 self.native_mut().setColor1(
149 color.as_ref().native(),
150 color_space.native_ptr_or_null_mut_force(),
151 )
152 }
153 self
154 }
155
156 pub fn alpha_f(&self) -> f32 {
157 self.color4f().a
158 }
159
160 pub fn alpha(&self) -> u8 {
161 unsafe { sb::C_SkPaint_getAlpha(self.native()) }
162 }
163
164 pub fn set_alpha_f(&mut self, alpha: f32) -> &mut Self {
165 unsafe { self.native_mut().setAlphaf(alpha) }
166 self
167 }
168
169 pub fn set_alpha(&mut self, alpha: u8) -> &mut Self {
170 self.set_alpha_f(f32::from(alpha) * (1.0 / 255.0))
171 }
172
173 pub fn set_argb(&mut self, a: u8, r: u8, g: u8, b: u8) -> &mut Self {
174 unsafe {
175 self.native_mut()
176 .setARGB(a.into(), r.into(), g.into(), b.into())
177 }
178 self
179 }
180
181 pub fn stroke_width(&self) -> scalar {
182 self.native().fWidth
183 }
184
185 pub fn set_stroke_width(&mut self, width: scalar) -> &mut Self {
186 unsafe { self.native_mut().setStrokeWidth(width) }
187 self
188 }
189
190 pub fn stroke_miter(&self) -> scalar {
191 self.native().fMiterLimit
192 }
193
194 pub fn set_stroke_miter(&mut self, miter: scalar) -> &mut Self {
195 unsafe { self.native_mut().setStrokeMiter(miter) }
196 self
197 }
198
199 pub fn stroke_cap(&self) -> Cap {
200 unsafe { sb::C_SkPaint_getStrokeCap(self.native()) }
201 }
202
203 pub fn set_stroke_cap(&mut self, cap: Cap) -> &mut Self {
204 unsafe { self.native_mut().setStrokeCap(cap) }
205 self
206 }
207
208 pub fn stroke_join(&self) -> Join {
209 unsafe { sb::C_SkPaint_getStrokeJoin(self.native()) }
210 }
211
212 pub fn set_stroke_join(&mut self, join: Join) -> &mut Self {
213 unsafe { self.native_mut().setStrokeJoin(join) }
214 self
215 }
216
217 pub fn shader(&self) -> Option<Shader> {
218 Shader::from_unshared_ptr(self.native().fShader.fPtr)
219 }
220
221 pub fn set_shader(&mut self, shader: impl Into<Option<Shader>>) -> &mut Self {
222 unsafe { sb::C_SkPaint_setShader(self.native_mut(), shader.into().into_ptr_or_null()) }
223 self
224 }
225
226 pub fn color_filter(&self) -> Option<ColorFilter> {
227 ColorFilter::from_unshared_ptr(self.native().fColorFilter.fPtr)
228 }
229
230 pub fn set_color_filter(&mut self, color_filter: impl Into<Option<ColorFilter>>) -> &mut Self {
231 unsafe {
232 sb::C_SkPaint_setColorFilter(self.native_mut(), color_filter.into().into_ptr_or_null())
233 }
234 self
235 }
236
237 pub fn as_blend_mode(&self) -> Option<BlendMode> {
238 let mut bm = BlendMode::default();
239 unsafe { sb::C_SkPaint_asBlendMode(self.native(), &mut bm) }.if_true_some(bm)
240 }
241
242 pub fn blend_mode_or(&self, default_mode: BlendMode) -> BlendMode {
243 unsafe { self.native().getBlendMode_or(default_mode) }
244 }
245
246 #[deprecated(
247 since = "0.42.0",
248 note = "Use as_blend_mode() or blend_mode_or() instead."
249 )]
250 pub fn blend_mode(&self) -> BlendMode {
251 self.blend_mode_or(BlendMode::SrcOver)
252 }
253
254 pub fn is_src_over(&self) -> bool {
255 unsafe { self.native().isSrcOver() }
256 }
257
258 pub fn set_blend_mode(&mut self, mode: BlendMode) -> &mut Self {
259 unsafe { self.native_mut().setBlendMode(mode) }
260 self
261 }
262
263 pub fn blender(&self) -> Option<Blender> {
264 Blender::from_unshared_ptr(self.native().fBlender.fPtr)
265 }
266
267 pub fn set_blender(&mut self, blender: impl Into<Option<Blender>>) -> &mut Self {
268 unsafe { sb::C_SkPaint_setBlender(self.native_mut(), blender.into().into_ptr_or_null()) }
269 self
270 }
271
272 pub fn path_effect(&self) -> Option<PathEffect> {
273 PathEffect::from_unshared_ptr(self.native().fPathEffect.fPtr)
274 }
275
276 pub fn set_path_effect(&mut self, path_effect: impl Into<Option<PathEffect>>) -> &mut Self {
277 unsafe {
278 sb::C_SkPaint_setPathEffect(self.native_mut(), path_effect.into().into_ptr_or_null())
279 }
280 self
281 }
282
283 pub fn mask_filter(&self) -> Option<MaskFilter> {
284 MaskFilter::from_unshared_ptr(self.native().fMaskFilter.fPtr)
285 }
286
287 pub fn set_mask_filter(&mut self, mask_filter: impl Into<Option<MaskFilter>>) -> &mut Self {
288 unsafe {
289 sb::C_SkPaint_setMaskFilter(self.native_mut(), mask_filter.into().into_ptr_or_null())
290 }
291 self
292 }
293
294 pub fn image_filter(&self) -> Option<ImageFilter> {
295 ImageFilter::from_unshared_ptr(self.native().fImageFilter.fPtr)
296 }
297
298 pub fn set_image_filter(&mut self, image_filter: impl Into<Option<ImageFilter>>) -> &mut Self {
299 unsafe {
300 sb::C_SkPaint_setImageFilter(self.native_mut(), image_filter.into().into_ptr_or_null())
301 }
302 self
303 }
304
305 pub fn nothing_to_draw(&self) -> bool {
306 unsafe { self.native().nothingToDraw() }
307 }
308}
309
310#[test]
311fn default_creation() {
312 let paint: Handle = Paint::default();
313 drop(paint)
314}
315
316#[test]
317fn method_chaining_compiles() {
318 let mut paint: Handle = Paint::default();
319 let _paint: &mut Handle = paint.reset().reset();
320}
321
322#[test]
323fn union_flags() {
324 let mut paint = Paint::default();
325 assert!(!paint.is_anti_alias());
326 assert!(!paint.is_dither());
327 assert_eq!(paint.style(), Style::Fill);
328
329 {
330 paint.set_anti_alias(true);
331
332 assert!(paint.is_anti_alias());
333 assert!(!paint.is_dither());
334 assert_eq!(paint.style(), Style::Fill);
335
336 paint.set_anti_alias(false);
337 }
338
339 {
340 paint.set_style(Style::StrokeAndFill);
341
342 assert!(!paint.is_anti_alias());
343 assert!(!paint.is_dither());
344 assert_eq!(paint.style(), Style::StrokeAndFill);
345
346 paint.set_style(Style::Fill);
347 }
348}
349
350#[test]
351fn set_color4f_color_space() {
352 let mut paint: Handle = Paint::default();
353 let color: Color4f = Color4f::from(Color::DARK_GRAY);
354 let color_space: RCHandle = ColorSpace::new_srgb();
355 paint.set_color4f(color, color_space:None);
356 paint.set_color4f(color, &color_space);
357 let color2: Color4f = Color4f::from(Color::DARK_GRAY);
358 paint.set_color4f(color:color2, color_space:Some(&color_space));
359}
360