1use crate::{prelude::*, BBHFactory, Canvas, Drawable, Picture, Rect};
2use skia_bindings::{self as sb, SkPictureRecorder, SkRect};
3use std::{fmt, ptr};
4
5pub type PictureRecorder = Handle<SkPictureRecorder>;
6
7impl NativeDrop for SkPictureRecorder {
8 fn drop(&mut self) {
9 unsafe {
10 sb::C_SkPictureRecorder_destruct(self);
11 }
12 }
13}
14
15impl fmt::Debug for PictureRecorder {
16 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
17 f.debug_struct(name:"PictureRecorder").finish()
18 }
19}
20
21impl 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]
72fn 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]
80fn 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]
91fn 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]
101fn not_recording_no_canvas() {
102 let mut recorder: Handle = PictureRecorder::new();
103 assert!(recorder.recording_canvas().is_none());
104}
105