ferroui_vello/
writeable_bitmap_impl.rs1use crate::helpers::image_saving_helper;
2use crate::helpers::pixel_format_helper::{self, to_image, to_premul_rgba};
3use crate::i_drawable_bitmap_impl::IDrawableBitmapImpl;
4use crate::immutable_bitmap::{decode_bitmap, decode_bitmap_to_size};
5use crate::vello_platform::VelloPlatform;
6use ferroui_base::media::imaging::{BitmapEncoderOptions, BitmapInterpolationMode};
7use ferroui_base::platform::{
8 AlphaFormat, IBitmapImpl, ILockedFramebuffer, IReadableBitmapImpl, IWriteableBitmapImpl, PixelFormat,
9};
10use ferroui_base::{PixelSize, Vector};
11use peniko::ImageData;
12use std::any::Any;
13use std::cell::RefCell;
14use std::io::{self, Read, Write};
15use std::rc::Rc;
16use std::sync::atomic::{AtomicI32, Ordering};
17use std::sync::{Arc, Mutex, Weak};
18
19pub struct WriteableBitmapImpl {
25 weak_self: Weak<WriteableBitmapImpl>,
26 pixels: Mutex<Pixels>,
27 dpi: Vector,
28 pixel_size: PixelSize,
29 format: PixelFormat,
30 alpha_format: AlphaFormat,
31 version: AtomicI32,
32}
33
34struct Pixels {
35 data: Option<Vec<u8>>,
37 image: Option<ImageData>,
39}
40
41impl WriteableBitmapImpl {
42 fn from_data(data: Vec<u8>, pixel_size: PixelSize, dpi: Vector, format: PixelFormat, alpha_format: AlphaFormat) -> Arc<Self> {
43 Arc::new_cyclic(|weak_self| Self {
44 weak_self: weak_self.clone(),
45 pixels: Mutex::new(Pixels { data: Some(data), image: None }),
46 dpi,
47 pixel_size,
48 format,
49 alpha_format,
50 version: AtomicI32::new(1),
51 })
52 }
53
54 fn from_image(image: ImageData, alpha_format: AlphaFormat) -> Arc<Self> {
55 let pixel_size = PixelSize::new(image.width as i32, image.height as i32);
56 let data = image.data.data().to_vec();
57
58 Self::from_data(data, pixel_size, VelloPlatform::default_dpi(), PixelFormat::RGBA8888, alpha_format)
59 }
60
61 pub fn from_stream(stream: &mut dyn Read) -> io::Result<Arc<Self>> {
64 let (image, opaque) = decode_bitmap(stream)?;
65
66 Ok(Self::from_image(image, if opaque { AlphaFormat::Opaque } else { AlphaFormat::Premul }))
67 }
68
69 pub fn from_stream_to_size(
72 stream: &mut dyn Read,
73 decode_size: i32,
74 horizontal: bool,
75 interpolation_mode: BitmapInterpolationMode,
76 ) -> io::Result<Arc<Self>> {
77 let image = decode_bitmap_to_size(stream, decode_size, horizontal, interpolation_mode)?;
78
79 Ok(Self::from_image(image, AlphaFormat::Premul))
80 }
81
82 pub fn new(size: PixelSize, dpi: Vector, format: PixelFormat, alpha_format: AlphaFormat) -> Arc<Self> {
89 let pixel_bytes = pixel_format_helper::bytes_per_pixel(format);
90 if size.width < 1 || size.height < 1 {
91 panic!("Unable to allocate a {}x{} bitmap", size.width, size.height);
92 }
93
94 let data = vec![0u8; size.width as usize * size.height as usize * pixel_bytes];
95
96 Self::from_data(data, size, dpi, format, alpha_format)
97 }
98
99 fn with_data<R>(&self, f: impl FnOnce(&mut Vec<u8>) -> R) -> R {
100 let mut pixels = self.pixels.lock().unwrap();
101 f(pixels.data.as_mut().expect("WriteableBitmapImpl has been disposed"))
102 }
103
104 fn row_bytes(&self) -> usize {
105 self.pixel_size.width as usize * pixel_format_helper::bytes_per_pixel(self.format)
106 }
107}
108
109impl IBitmapImpl for WriteableBitmapImpl {
110 fn dpi(&self) -> Vector {
111 self.dpi
112 }
113
114 fn pixel_size(&self) -> PixelSize {
115 self.pixel_size
116 }
117
118 fn version(&self) -> i32 {
119 self.version.load(Ordering::SeqCst)
120 }
121
122 fn save(&self, stream: &mut dyn Write, options: &BitmapEncoderOptions) -> io::Result<()> {
123 let image = self.image().ok_or_else(|| io::Error::other("WriteableBitmapImpl has been disposed"))?;
124 image_saving_helper::save_image(&image, stream, options)
125 }
126
127 fn dispose(&self) {
128 let mut pixels = self.pixels.lock().unwrap();
129 pixels.image.take();
130 pixels.data.take();
131 }
132
133 fn as_any(&self) -> &dyn Any {
134 self
135 }
136
137 fn as_readable_bitmap(&self) -> Option<&dyn IReadableBitmapImpl> {
138 Some(self)
139 }
140}
141
142impl IDrawableBitmapImpl for WriteableBitmapImpl {
143 fn image(&self) -> Option<ImageData> {
144 let mut pixels = self.pixels.lock().unwrap();
145 if pixels.image.is_none() {
146 let data = pixels.data.as_ref()?;
149 let rgba = to_premul_rgba(data, self.row_bytes(), self.pixel_size, self.format, self.alpha_format);
150 pixels.image = Some(to_image(rgba, self.pixel_size));
151 }
152 pixels.image.clone()
153 }
154}
155
156impl IReadableBitmapImpl for WriteableBitmapImpl {
157 fn format(&self) -> Option<PixelFormat> {
158 Some(self.format)
159 }
160
161 fn alpha_format(&self) -> Option<AlphaFormat> {
162 Some(self.alpha_format)
163 }
164
165 fn lock(&self) -> Rc<dyn ILockedFramebuffer> {
166 let parent = self.weak_self.upgrade().expect("WriteableBitmapImpl is alive while it is used");
167 Rc::new(BitmapFramebuffer { parent: RefCell::new(Some(parent)) })
168 }
169}
170
171impl IWriteableBitmapImpl for WriteableBitmapImpl {}
172
173struct BitmapFramebuffer {
175 parent: RefCell<Option<Arc<WriteableBitmapImpl>>>,
176}
177
178impl BitmapFramebuffer {
179 fn with_parent<R>(&self, f: impl FnOnce(&WriteableBitmapImpl) -> R) -> R {
180 let parent = self.parent.borrow();
181 f(parent.as_ref().expect("the framebuffer has been unlocked"))
182 }
183}
184
185impl ILockedFramebuffer for BitmapFramebuffer {
186 fn address(&self) -> *mut u8 {
187 self.with_parent(|parent| parent.with_data(|data| data.as_mut_ptr()))
191 }
192
193 fn with_data(&self, access: &mut dyn FnMut(&mut [u8])) {
194 self.with_parent(|parent| parent.with_data(|data| access(data)));
195 }
196
197 fn size(&self) -> PixelSize {
198 self.with_parent(|parent| parent.pixel_size)
199 }
200
201 fn row_bytes(&self) -> i32 {
202 self.with_parent(|parent| parent.row_bytes() as i32)
203 }
204
205 fn dpi(&self) -> Vector {
206 self.with_parent(|parent| parent.dpi)
207 }
208
209 fn format(&self) -> PixelFormat {
210 self.with_parent(|parent| parent.format)
211 }
212
213 fn alpha_format(&self) -> AlphaFormat {
214 self.with_parent(|parent| parent.alpha_format)
215 }
216
217 fn dispose(&self) {
218 if let Some(parent) = self.parent.borrow_mut().take() {
219 let mut pixels = parent.pixels.lock().unwrap();
220 parent.version.fetch_add(1, Ordering::SeqCst);
221 pixels.image = None;
223 }
224 }
225}