Skip to main content

ferroui_base/media/imaging/
render_target_bitmap.rs

1use crate::media::imaging::{Bitmap, BitmapEncoderOptions, IBitmap};
2use crate::media::{Colors, DrawingContext, IImage, IImageBrushSource, PlatformDrawingContext};
3use crate::platform::{self, IBitmapImpl, IDrawingContextImpl, IRenderTargetBitmapImpl};
4use crate::rendering::ImmediateRenderer;
5use crate::utilities::{RefCountable, RefCounted};
6use crate::{PixelSize, Rect, Ref, Size, Vector, Visual};
7use std::any::Any;
8use std::io::Write;
9use std::ops::Deref;
10
11/// A bitmap that holds the rendering of a visual.
12pub struct RenderTargetBitmap {
13    base: Bitmap,
14    platform_impl: RefCounted<dyn IRenderTargetBitmapImpl>,
15}
16
17impl Deref for RenderTargetBitmap {
18    type Target = Bitmap;
19
20    #[inline]
21    fn deref(&self) -> &Bitmap {
22        &self.base
23    }
24}
25
26impl RenderTargetBitmap {
27    /// Creates a bitmap of the given size, in pixels, at 96 DPI.
28    pub fn new(pixel_size: PixelSize) -> RenderTargetBitmap {
29        Self::with_dpi(pixel_size, Vector::new(96.0, 96.0))
30    }
31
32    /// Creates a bitmap of the given size, in pixels, and DPI.
33    pub fn with_dpi(pixel_size: PixelSize, dpi: Vector) -> RenderTargetBitmap {
34        let item = Self::create_impl(pixel_size, dpi);
35        let release = item.clone();
36        Self::from_ref(RefCountable::create(item, move || release.dispose()))
37    }
38
39    fn from_ref(platform_impl: RefCounted<dyn IRenderTargetBitmapImpl>) -> RenderTargetBitmap {
40        let base_impl: RefCounted<crate::platform::SharedBitmapImpl> = platform_impl.clone_as(|item| item as std::sync::Arc<crate::platform::SharedBitmapImpl>);
41        let base = Bitmap::from_ref(&base_impl);
42        base_impl.dispose();
43        RenderTargetBitmap { base, platform_impl }
44    }
45
46    /// The platform-specific bitmap implementation.
47    pub fn platform_impl(&self) -> &RefCounted<dyn IRenderTargetBitmapImpl> {
48        &self.platform_impl
49    }
50
51    /// Renders a visual to the bitmap.
52    pub fn render(&self, visual: &Ref<Visual>) {
53        let mut context = self.create_drawing_context();
54        ImmediateRenderer::render(&mut context, visual);
55        context.dispose();
56    }
57
58    fn create_impl(size: PixelSize, dpi: Vector) -> std::sync::Arc<dyn IRenderTargetBitmapImpl> {
59        platform::render_interface().create_render_target_bitmap(size, dpi)
60    }
61
62    /// Creates a drawing context that draws into the bitmap, after clearing
63    /// the bitmap. Disposing (or dropping) the context finishes the drawing.
64    pub fn create_drawing_context(&self) -> DrawingContext<'static> {
65        self.create_drawing_context_with_clear(true)
66    }
67
68    /// Creates a drawing context that draws into the bitmap, clearing the
69    /// bitmap first when `clear` is set.
70    pub fn create_drawing_context_with_clear(&self, clear: bool) -> DrawingContext<'static> {
71        let platform = self.create_platform_drawing_context(clear);
72        DrawingContext::owned(Box::new(PlatformDrawingContext::new(platform)))
73    }
74
75    /// Creates the platform drawing context that draws into the bitmap,
76    /// clearing the bitmap first when `clear` is set.
77    pub fn create_platform_drawing_context(&self, clear: bool) -> Box<dyn IDrawingContextImpl> {
78        let mut platform = self.platform_impl.item().create_drawing_context();
79        if clear {
80            platform.clear(Colors::TRANSPARENT);
81        }
82        platform
83    }
84
85    /// Releases the bitmap's references to the platform bitmap.
86    pub fn dispose(&self) {
87        self.platform_impl.dispose();
88        self.base.dispose();
89    }
90}
91
92impl IImage for RenderTargetBitmap {
93    fn size(&self) -> Size {
94        self.base.size()
95    }
96
97    fn draw(&self, context: &mut DrawingContext<'_>, source_rect: Rect, dest_rect: Rect) {
98        IImage::draw(&self.base, context, source_rect, dest_rect)
99    }
100
101    fn as_any(&self) -> &dyn Any {
102        self
103    }
104
105    fn as_bitmap(&self) -> Option<&dyn IBitmap> {
106        Some(self)
107    }
108}
109
110impl IBitmap for RenderTargetBitmap {
111    fn dpi(&self) -> Vector {
112        self.base.dpi()
113    }
114
115    fn pixel_size(&self) -> PixelSize {
116        self.base.pixel_size()
117    }
118
119    fn platform_impl(&self) -> &RefCounted<crate::platform::SharedBitmapImpl> {
120        self.base.platform_impl()
121    }
122
123    fn save(&self, stream: &mut dyn Write, options: &BitmapEncoderOptions) -> std::io::Result<()> {
124        self.base.save(stream, options)
125    }
126
127    fn dispose(&self) {
128        RenderTargetBitmap::dispose(self)
129    }
130}
131
132impl IImageBrushSource for RenderTargetBitmap {
133    fn bitmap(&self) -> Option<&RefCounted<crate::platform::SharedBitmapImpl>> {
134        IImageBrushSource::bitmap(&self.base)
135    }
136}