1 | use crate::Blender; |
2 | use crate::{ |
3 | prelude::*, scalar, BlendMode, Color, Color4f, ColorFilter, ColorSpace, ImageFilter, |
4 | MaskFilter, PathEffect, Shader, |
5 | }; |
6 | use core::fmt; |
7 | |
8 | use skia_bindings::{self as sb, SkPaint}; |
9 | |
10 | pub use sb::SkPaint_Style as Style; |
11 | variant_name!(Style::Fill); |
12 | |
13 | pub use sb::SkPaint_Cap as Cap; |
14 | variant_name!(Cap::Butt); |
15 | |
16 | pub use sb::SkPaint_Join as Join; |
17 | variant_name!(Join::Miter); |
18 | |
19 | pub type Paint = Handle<SkPaint>; |
20 | unsafe_send_sync!(Paint); |
21 | |
22 | impl NativeDrop for SkPaint { |
23 | fn drop(&mut self) { |
24 | unsafe { sb::C_SkPaint_destruct(self) } |
25 | } |
26 | } |
27 | |
28 | impl NativeClone for SkPaint { |
29 | fn clone(&self) -> Self { |
30 | unsafe { SkPaint::new2(self) } |
31 | } |
32 | } |
33 | |
34 | impl NativePartialEq for SkPaint { |
35 | fn eq(&self, rhs: &Self) -> bool { |
36 | unsafe { sb::C_SkPaint_Equals(self, rhs) } |
37 | } |
38 | } |
39 | |
40 | impl Default for Handle<SkPaint> { |
41 | fn default() -> Self { |
42 | Paint::from_native_c(unsafe { SkPaint::new() }) |
43 | } |
44 | } |
45 | |
46 | impl 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 | |
66 | impl 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 ] |
311 | fn default_creation() { |
312 | let paint: Handle = Paint::default(); |
313 | drop(paint) |
314 | } |
315 | |
316 | #[test ] |
317 | fn method_chaining_compiles() { |
318 | let mut paint: Handle = Paint::default(); |
319 | let _paint: &mut Handle = paint.reset().reset(); |
320 | } |
321 | |
322 | #[test ] |
323 | fn 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 ] |
351 | fn 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 | |