skia_safe/core/
picture.rs

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.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("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}