1 | use crate::{prelude::*, BBHFactory, Canvas, Drawable, Picture, Rect}; |
2 | use skia_bindings::{self as sb, SkPictureRecorder, SkRect}; |
3 | use std::{fmt, ptr}; |
4 | |
5 | pub type PictureRecorder = Handle<SkPictureRecorder>; |
6 | |
7 | impl NativeDrop for SkPictureRecorder { |
8 | fn drop(&mut self) { |
9 | unsafe { |
10 | sb::C_SkPictureRecorder_destruct(self); |
11 | } |
12 | } |
13 | } |
14 | |
15 | impl fmt::Debug for PictureRecorder { |
16 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
17 | f.debug_struct(name:"PictureRecorder" ).finish() |
18 | } |
19 | } |
20 | |
21 | impl PictureRecorder { |
22 | pub fn new() -> Self { |
23 | Self::construct(|pr| unsafe { sb::C_SkPictureRecorder_Construct(pr) }) |
24 | } |
25 | |
26 | // TODO: beginRecording with BBoxHierarchy |
27 | |
28 | pub fn begin_recording( |
29 | &mut self, |
30 | bounds: impl AsRef<Rect>, |
31 | mut bbh_factory: Option<&mut BBHFactory>, |
32 | ) -> &Canvas { |
33 | let canvas_ref = unsafe { |
34 | &*self.native_mut().beginRecording1( |
35 | bounds.as_ref().native(), |
36 | bbh_factory.native_ptr_or_null_mut(), |
37 | ) |
38 | }; |
39 | |
40 | Canvas::borrow_from_native(canvas_ref) |
41 | } |
42 | |
43 | pub fn recording_canvas(&mut self) -> Option<&Canvas> { |
44 | let canvas = unsafe { self.native_mut().getRecordingCanvas() }; |
45 | if canvas.is_null() { |
46 | return None; |
47 | } |
48 | Some(Canvas::borrow_from_native(unsafe { &*canvas })) |
49 | } |
50 | |
51 | pub fn finish_recording_as_picture(&mut self, cull_rect: Option<&Rect>) -> Option<Picture> { |
52 | self.recording_canvas()?; |
53 | let cull_rect_ptr: *const SkRect = |
54 | cull_rect.map(|r| r.native() as _).unwrap_or(ptr::null()); |
55 | |
56 | let picture_ptr = unsafe { |
57 | sb::C_SkPictureRecorder_finishRecordingAsPicture(self.native_mut(), cull_rect_ptr) |
58 | }; |
59 | |
60 | Picture::from_ptr(picture_ptr) |
61 | } |
62 | |
63 | pub fn finish_recording_as_drawable(&mut self) -> Option<Drawable> { |
64 | self.recording_canvas()?; |
65 | Drawable::from_ptr(unsafe { |
66 | sb::C_SkPictureRecorder_finishRecordingAsDrawable(self.native_mut()) |
67 | }) |
68 | } |
69 | } |
70 | |
71 | #[test ] |
72 | fn good_case() { |
73 | let mut recorder: Handle = PictureRecorder::new(); |
74 | let canvas: &Canvas = recorder.begin_recording(bounds:Rect::new(0.0, 0.0, 100.0, 100.0), bbh_factory:None); |
75 | canvas.clear(color:crate::Color::WHITE); |
76 | let _picture: RCHandle = recorder.finish_recording_as_picture(cull_rect:None).unwrap(); |
77 | } |
78 | |
79 | #[test ] |
80 | fn begin_recording_two_times() { |
81 | let mut recorder: Handle = PictureRecorder::new(); |
82 | let canvas: &Canvas = recorder.begin_recording(bounds:Rect::new(0.0, 0.0, 100.0, 100.0), bbh_factory:None); |
83 | canvas.clear(color:crate::Color::WHITE); |
84 | assert!(recorder.recording_canvas().is_some()); |
85 | let canvas: &Canvas = recorder.begin_recording(bounds:Rect::new(0.0, 0.0, 100.0, 100.0), bbh_factory:None); |
86 | canvas.clear(color:crate::Color::WHITE); |
87 | assert!(recorder.recording_canvas().is_some()); |
88 | } |
89 | |
90 | #[test ] |
91 | fn finishing_recording_two_times() { |
92 | let mut recorder: Handle = PictureRecorder::new(); |
93 | let canvas: &Canvas = recorder.begin_recording(bounds:Rect::new(0.0, 0.0, 100.0, 100.0), bbh_factory:None); |
94 | canvas.clear(color:crate::Color::WHITE); |
95 | assert!(recorder.finish_recording_as_picture(None).is_some()); |
96 | assert!(recorder.recording_canvas().is_none()); |
97 | assert!(recorder.finish_recording_as_picture(None).is_none()); |
98 | } |
99 | |
100 | #[test ] |
101 | fn not_recording_no_canvas() { |
102 | let mut recorder: Handle = PictureRecorder::new(); |
103 | assert!(recorder.recording_canvas().is_none()); |
104 | } |
105 | |