Skip to main content

ferroui_vello/
render_target_bitmap_impl.rs

1use crate::framebuffer_render_target::FramebufferRenderTarget;
2use crate::i_drawable_bitmap_impl::IDrawableBitmapImpl;
3use crate::vello_options::VelloRenderingMode;
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::utilities::ThreadBound;
15use ferroui_base::{PixelSize, Vector};
16use peniko::ImageData;
17use std::any::Any;
18use std::io::{self, Write};
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 pixel format the renderers
33    /// draw. `rendering_modes` are the modes scenes are drawn in, in the
34    /// order they are tried.
35    pub fn new(size: PixelSize, dpi: Vector, rendering_modes: Vec<VelloRenderingMode>) -> Self {
36        let bitmap = WriteableBitmapImpl::new(size, dpi, PixelFormat::RGBA8888, AlphaFormat::Premul);
37        let render_target = FramebufferRenderTarget::from_render_target(
38            Self::framebuffer_render_target(&bitmap),
39            true,
40            rendering_modes,
41        );
42
43        Self { bitmap, render_target: ThreadBound::new(render_target) }
44    }
45
46    fn framebuffer_render_target(bitmap: &Arc<WriteableBitmapImpl>) -> Rc<dyn IFramebufferRenderTarget> {
47        let bitmap = bitmap.clone();
48        Rc::new(FuncFramebufferRenderTarget::new(move || bitmap.lock()))
49    }
50
51    /// Whether the contents of the bitmap have been lost. Never the case for
52    /// a bitmap in memory.
53    pub fn is_corrupted(&self) -> bool {
54        false
55    }
56}
57
58impl IBitmapImpl for RenderTargetBitmapImpl {
59    fn dpi(&self) -> Vector {
60        self.bitmap.dpi()
61    }
62
63    fn pixel_size(&self) -> PixelSize {
64        self.bitmap.pixel_size()
65    }
66
67    fn version(&self) -> i32 {
68        self.bitmap.version()
69    }
70
71    fn save(&self, stream: &mut dyn Write, options: &BitmapEncoderOptions) -> io::Result<()> {
72        IBitmapImpl::save(&*self.bitmap, stream, options)
73    }
74
75    fn dispose(&self) {
76        if self.render_target.is_on_thread() {
77            self.render_target.get().dispose();
78        }
79        self.bitmap.dispose();
80    }
81
82    fn as_any(&self) -> &dyn Any {
83        self
84    }
85
86    fn as_readable_bitmap(&self) -> Option<&dyn IReadableBitmapImpl> {
87        Some(self)
88    }
89}
90
91impl IReadableBitmapImpl for RenderTargetBitmapImpl {
92    fn format(&self) -> Option<PixelFormat> {
93        self.bitmap.format()
94    }
95
96    fn alpha_format(&self) -> Option<AlphaFormat> {
97        self.bitmap.alpha_format()
98    }
99
100    fn lock(&self) -> Rc<dyn ILockedFramebuffer> {
101        self.bitmap.lock()
102    }
103}
104
105impl IWriteableBitmapImpl for RenderTargetBitmapImpl {}
106
107impl IRenderTargetBitmapImpl for RenderTargetBitmapImpl {
108    fn create_drawing_context(&self) -> Box<dyn IDrawingContextImpl> {
109        let scene_info = RenderTargetSceneInfo::new(
110            self.pixel_size(),
111            self.dpi().x / 96.0,
112            CompositionTransparencyLevel::None,
113        );
114
115        self.render_target.get().create_drawing_context(&scene_info).0
116    }
117}
118
119impl IDrawableBitmapImpl for RenderTargetBitmapImpl {
120    fn image(&self) -> Option<ImageData> {
121        self.bitmap.image()
122    }
123}
124
125impl IPlatformRenderSurface for RenderTargetBitmapImpl {
126    fn as_framebuffer_surface(&self) -> Option<&dyn IFramebufferPlatformSurface> {
127        Some(self)
128    }
129
130    fn as_any(&self) -> &dyn Any {
131        self
132    }
133}
134
135impl IFramebufferPlatformSurface for RenderTargetBitmapImpl {
136    fn create_framebuffer_render_target(&self) -> Rc<dyn IFramebufferRenderTarget> {
137        Self::framebuffer_render_target(&self.bitmap)
138    }
139}