| 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 | |