1use crate::{prelude::*, Canvas, Data, FilterMode, Matrix, Rect, Shader, TileMode};
2use skia_bindings::{self as sb, SkPicture, SkRefCntBase};
3use std::fmt;
4
5pub type Picture = RCHandle<SkPicture>;
6unsafe_send_sync!(Picture);
7
8impl NativeRefCountedBase for SkPicture {
9 type Base = SkRefCntBase;
10}
11
12impl fmt::Debug for Picture {
13 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
14 f&mut DebugStruct<'_, '_>.debug_struct("Picture")
15 .field("cull_rect", &self.cull_rect())
16 .field("unique_id", &self.unique_id())
17 .field("approximate_op_count", &self.approximate_op_count())
18 .field(name:"approximate_bytes_used", &self.approximate_bytes_used())
19 .finish()
20 }
21}
22
23impl Picture {
24 // TODO: wrap MakeFromStream
25
26 // TODO: may support SkSerialProcs in MakeFromData?
27
28 pub fn from_data(data: &Data) -> Option<Picture> {
29 Picture::from_ptr(unsafe { sb::C_SkPicture_MakeFromData(data.native()) })
30 }
31
32 pub fn from_bytes(bytes: &[u8]) -> Option<Picture> {
33 Picture::from_ptr(unsafe {
34 sb::C_SkPicture_MakeFromData2(bytes.as_ptr() as _, bytes.len())
35 })
36 }
37
38 // TODO: AbortCallback and the function that use it.
39
40 pub fn playback(&self, canvas: &Canvas) {
41 unsafe { sb::C_SkPicture_playback(self.native(), canvas.native_mut()) }
42 }
43
44 pub fn cull_rect(&self) -> Rect {
45 Rect::construct(|r| unsafe { sb::C_SkPicture_cullRect(self.native(), r) })
46 }
47
48 pub fn unique_id(&self) -> u32 {
49 unsafe { sb::C_SkPicture_uniqueID(self.native()) }
50 }
51
52 // TODO: support SkSerialProcs in serialize()?
53
54 pub fn serialize(&self) -> Data {
55 Data::from_ptr(unsafe { sb::C_SkPicture_serialize(self.native()) }).unwrap()
56 }
57
58 pub fn new_placeholder(cull: impl AsRef<Rect>) -> Picture {
59 Picture::from_ptr(unsafe { sb::C_SkPicture_MakePlaceholder(cull.as_ref().native()) })
60 .unwrap()
61 }
62
63 pub fn approximate_op_count(&self) -> usize {
64 self.approximate_op_count_nested(false)
65 }
66
67 pub fn approximate_op_count_nested(&self, nested: impl Into<Option<bool>>) -> usize {
68 let nested = nested.into().unwrap_or(false);
69 unsafe {
70 sb::C_SkPicture_approximateOpCount(self.native(), nested)
71 .try_into()
72 .unwrap()
73 }
74 }
75
76 pub fn approximate_bytes_used(&self) -> usize {
77 unsafe {
78 let mut value = 0;
79 sb::C_SkPicture_approximateBytesUsed(self.native(), &mut value);
80 value
81 }
82 }
83
84 pub fn to_shader<'a, 'b>(
85 &self,
86 tm: impl Into<Option<(TileMode, TileMode)>>,
87 mode: FilterMode,
88 local_matrix: impl Into<Option<&'a Matrix>>,
89 tile_rect: impl Into<Option<&'b Rect>>,
90 ) -> Shader {
91 let tm = tm.into();
92 let local_matrix = local_matrix.into();
93 let tile_rect = tile_rect.into();
94 let tmx = tm.map(|tm| tm.0).unwrap_or_default();
95 let tmy = tm.map(|tm| tm.1).unwrap_or_default();
96
97 Shader::from_ptr(unsafe {
98 sb::C_SkPicture_makeShader(
99 self.native(),
100 tmx,
101 tmy,
102 mode,
103 local_matrix.native_ptr_or_null(),
104 tile_rect.native_ptr_or_null(),
105 )
106 })
107 .unwrap()
108 }
109}
110