| 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 = PictureRecorder::new(); |
| 74 | let canvas = recorder.begin_recording(Rect::new(0.0, 0.0, 100.0, 100.0), None); |
| 75 | canvas.clear(crate::Color::WHITE); |
| 76 | let _picture = recorder.finish_recording_as_picture(None).unwrap(); |
| 77 | } |
| 78 | |
| 79 | #[test ] |
| 80 | fn begin_recording_two_times() { |
| 81 | let mut recorder = PictureRecorder::new(); |
| 82 | let canvas = recorder.begin_recording(Rect::new(0.0, 0.0, 100.0, 100.0), None); |
| 83 | canvas.clear(crate::Color::WHITE); |
| 84 | assert!(recorder.recording_canvas().is_some()); |
| 85 | let canvas = recorder.begin_recording(Rect::new(0.0, 0.0, 100.0, 100.0), None); |
| 86 | canvas.clear(crate::Color::WHITE); |
| 87 | assert!(recorder.recording_canvas().is_some()); |
| 88 | } |
| 89 | |
| 90 | #[test ] |
| 91 | fn finishing_recording_two_times() { |
| 92 | let mut recorder = PictureRecorder::new(); |
| 93 | let canvas = recorder.begin_recording(Rect::new(0.0, 0.0, 100.0, 100.0), None); |
| 94 | canvas.clear(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 = PictureRecorder::new(); |
| 103 | assert!(recorder.recording_canvas().is_none()); |
| 104 | } |
| 105 | |