Skip to main content

ferroui_skia/
render_target_bitmap_impl.rs

1use crate::framebuffer_render_target::FramebufferRenderTarget;
2use crate::gpu::ISkiaGrContext;
3use crate::i_drawable_bitmap_impl::IDrawableBitmapImpl;
4use crate::writeable_bitmap_impl::WriteableBitmapImpl;
5use ferroui_base::media::imaging::BitmapEncoderOptions;
6use ferroui_base::platform::surfaces::{
7    FuncFramebufferRenderTarget, IFramebufferPlatformSurface, IFramebufferRenderTarget, IPlatformRenderSurface,
8};
9use ferroui_base::platform::{
10    AlphaFormat, IBitmapImpl, IDrawingContextImpl, ILockedFramebuffer, IReadableBitmapImpl, IRenderTarget,
11    IRenderTargetBitmapImpl, IWriteableBitmapImpl, PixelFormat, RenderTargetSceneInfo,
12};
13use ferroui_base::rendering::composition::CompositionTransparencyLevel;
14use ferroui_base::{PixelSize, Vector};
15use skia_safe::{Canvas, ColorType, Paint, Rect, SamplingOptions};
16use std::any::Any;
17use std::io::{self, Write};
18use ferroui_base::utilities::ThreadBound;
19use std::rc::Rc;
20use std::sync::Arc;
21
22/// A render target bitmap: a writeable bitmap that is drawn into through a
23/// framebuffer render target over its own pixels.
24pub struct RenderTargetBitmapImpl {
25    bitmap: Arc<WriteableBitmapImpl>,
26    /// The render target the bitmap is drawn into with, on the thread that
27    /// created the bitmap.
28    render_target: ThreadBound<FramebufferRenderTarget>,
29}
30
31impl RenderTargetBitmapImpl {
32    /// Creates a render target bitmap in the platform's native pixel format.
33    pub fn new(size: PixelSize, dpi: Vector) -> Self {
34        let format = if ColorType::N32 == ColorType::RGBA8888 { PixelFormat::RGBA8888 } else { PixelFormat::BGRA8888 };
35        let bitmap = WriteableBitmapImpl::new(size, dpi, format, AlphaFormat::Premul);
36        let render_target = FramebufferRenderTarget::from_render_target(Self::framebuffer_render_target(&bitmap), true);
37
38        Self { bitmap, render_target: ThreadBound::new(render_target) }
39    }
40
41    fn framebuffer_render_target(bitmap: &Arc<WriteableBitmapImpl>) -> Rc<dyn IFramebufferRenderTarget> {
42        let bitmap = bitmap.clone();
43        Rc::new(FuncFramebufferRenderTarget::new(move || bitmap.lock()))
44    }
45
46    /// Whether the contents of the bitmap have been lost. Never the case for
47    /// a bitmap in memory.
48    pub fn is_corrupted(&self) -> bool {
49        false
50    }
51}
52
53impl IBitmapImpl for RenderTargetBitmapImpl {
54    fn dpi(&self) -> Vector {
55        self.bitmap.dpi()
56    }
57
58    fn pixel_size(&self) -> PixelSize {
59        self.bitmap.pixel_size()
60    }
61
62    fn version(&self) -> i32 {
63        self.bitmap.version()
64    }
65
66    fn save(&self, stream: &mut dyn Write, options: &BitmapEncoderOptions) -> io::Result<()> {
67        IBitmapImpl::save(&*self.bitmap, stream, options)
68    }
69
70    fn dispose(&self) {
71        if self.render_target.is_on_thread() {
72            self.render_target.get().dispose();
73        }
74        self.bitmap.dispose();
75    }
76
77    fn as_any(&self) -> &dyn Any {
78        self
79    }
80
81    fn as_readable_bitmap(&self) -> Option<&dyn IReadableBitmapImpl> {
82        Some(self)
83    }
84}
85
86impl IReadableBitmapImpl for RenderTargetBitmapImpl {
87    fn format(&self) -> Option<PixelFormat> {
88        self.bitmap.format()
89    }
90
91    fn alpha_format(&self) -> Option<AlphaFormat> {
92        self.bitmap.alpha_format()
93    }
94
95    fn lock(&self) -> Rc<dyn ILockedFramebuffer> {
96        self.bitmap.lock()
97    }
98}
99
100impl IWriteableBitmapImpl for RenderTargetBitmapImpl {}
101
102impl IRenderTargetBitmapImpl for RenderTargetBitmapImpl {
103    fn create_drawing_context(&self) -> Box<dyn IDrawingContextImpl> {
104        let scene_info = RenderTargetSceneInfo::new(
105            self.pixel_size(),
106            self.dpi().x / 96.0,
107            CompositionTransparencyLevel::None,
108        );
109
110        self.render_target.get().create_drawing_context(&scene_info).0
111    }
112}
113
114impl IDrawableBitmapImpl for RenderTargetBitmapImpl {
115    fn draw(
116        &self,
117        gr_context: Option<&dyn ISkiaGrContext>,
118        canvas: &Canvas,
119        source_rect: &Rect,
120        dest_rect: &Rect,
121        sampling_options: SamplingOptions,
122        paint: &Paint,
123    ) {
124        self.bitmap.draw(gr_context, canvas, source_rect, dest_rect, sampling_options, paint);
125    }
126}
127
128impl IPlatformRenderSurface for RenderTargetBitmapImpl {
129    fn as_framebuffer_surface(&self) -> Option<&dyn IFramebufferPlatformSurface> {
130        Some(self)
131    }
132
133    fn as_any(&self) -> &dyn Any {
134        self
135    }
136}
137
138impl IFramebufferPlatformSurface for RenderTargetBitmapImpl {
139    fn create_framebuffer_render_target(&self) -> Rc<dyn IFramebufferRenderTarget> {
140        Self::framebuffer_render_target(&self.bitmap)
141    }
142}