1use std::fmt;
2
3use skia_bindings::{self as sb, SkDrawable, SkFlattenable, SkRefCntBase};
4
5#[cfg(feature = "gpu")]
6use crate::gpu;
7use crate::{prelude::*, Canvas, Matrix, NativeFlattenable, Picture, Point, Rect};
8
9pub type Drawable = RCHandle<SkDrawable>;
10
11impl NativeRefCountedBase for SkDrawable {
12 type Base = SkRefCntBase;
13}
14
15impl NativeFlattenable for SkDrawable {
16 fn native_flattenable(&self) -> &SkFlattenable {
17 unsafe { &*(self as *const SkDrawable as *const SkFlattenable) }
18 }
19
20 fn native_deserialize(data: &[u8]) -> *mut Self {
21 unsafe { sb::C_SkDrawable_Deserialize(data:data.as_ptr() as _, length:data.len()) }
22 }
23}
24
25impl fmt::Debug for Drawable {
26 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
27 fDebugStruct<'_, '_>.debug_struct(name:"Drawable")
28 // TODO: clarify why &self has to be mut here.
29 // .field("generation_id", &self.generation_id())
30 // .field("bounds", &self.bounds())
31 .finish()
32 }
33}
34
35impl Drawable {
36 pub fn draw(&mut self, canvas: &Canvas, matrix: Option<&Matrix>) {
37 unsafe {
38 self.native_mut()
39 .draw(canvas.native_mut(), matrix.native_ptr_or_null())
40 }
41 }
42
43 pub fn draw_at(&mut self, canvas: &Canvas, point: impl Into<Point>) {
44 let point = point.into();
45 unsafe {
46 self.native_mut()
47 .draw1(canvas.native_mut(), point.x, point.y)
48 }
49 }
50
51 #[cfg(feature = "gpu")]
52 pub fn snap_gpu_draw_handler(
53 &mut self,
54 api: gpu::BackendAPI,
55 matrix: &Matrix,
56 clip_bounds: impl Into<crate::IRect>,
57 buffer_info: &crate::ImageInfo,
58 ) -> Option<gpu_draw_handler::GPUDrawHandler> {
59 gpu_draw_handler::GPUDrawHandler::from_ptr(unsafe {
60 sb::C_SkDrawable_snapGpuDrawHandler(
61 self.native_mut(),
62 api,
63 matrix.native(),
64 clip_bounds.into().native(),
65 buffer_info.native(),
66 )
67 })
68 }
69
70 pub fn make_picture_snapshot(&mut self) -> Picture {
71 Picture::from_ptr(unsafe { sb::C_SkDrawable_makePictureSnapshot(self.native_mut()) })
72 .expect("Internal error: SkDrawable::makePictureSnapshot returned null")
73 }
74
75 pub fn generation_id(&mut self) -> u32 {
76 unsafe { self.native_mut().getGenerationID() }
77 }
78
79 pub fn bounds(&mut self) -> Rect {
80 Rect::construct(|r| unsafe { sb::C_SkDrawable_getBounds(self.native_mut(), r) })
81 }
82
83 pub fn approximate_bytes_used(&mut self) -> usize {
84 unsafe { self.native_mut().approximateBytesUsed() }
85 }
86
87 pub fn notify_drawing_changed(&mut self) {
88 unsafe { self.native_mut().notifyDrawingChanged() }
89 }
90}
91
92#[cfg(feature = "gpu")]
93pub use gpu_draw_handler::*;
94
95#[cfg(feature = "gpu")]
96pub mod gpu_draw_handler {
97 use crate::{gpu, prelude::*};
98 use skia_bindings::{self as sb, SkDrawable_GpuDrawHandler};
99 use std::fmt;
100
101 pub type GPUDrawHandler = RefHandle<SkDrawable_GpuDrawHandler>;
102
103 impl NativeDrop for SkDrawable_GpuDrawHandler {
104 fn drop(&mut self) {
105 unsafe { sb::C_SkDrawable_GpuDrawHandler_delete(self) }
106 }
107 }
108
109 impl fmt::Debug for GPUDrawHandler {
110 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
111 f.debug_struct("GPUDrawHandler").finish()
112 }
113 }
114
115 impl GPUDrawHandler {
116 pub fn draw(&mut self, info: &gpu::BackendDrawableInfo) {
117 unsafe {
118 sb::C_SkDrawable_GpuDrawHandler_draw(self.native_mut(), info.native());
119 }
120 }
121 }
122}
123