1 | use crate::{prelude::*, Canvas, Data, FilterMode, Matrix, Rect, Shader, TileMode}; |
2 | use skia_bindings::{self as sb, SkPicture, SkRefCntBase}; |
3 | use std::fmt; |
4 | |
5 | pub type Picture = RCHandle<SkPicture>; |
6 | unsafe_send_sync!(Picture); |
7 | |
8 | impl NativeRefCountedBase for SkPicture { |
9 | type Base = SkRefCntBase; |
10 | } |
11 | |
12 | impl 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 | |
23 | impl 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 | |