ferroui_skia/
render_target_bitmap_impl.rs1use 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
22pub struct RenderTargetBitmapImpl {
25 bitmap: Arc<WriteableBitmapImpl>,
26 render_target: ThreadBound<FramebufferRenderTarget>,
29}
30
31impl RenderTargetBitmapImpl {
32 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 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}