1use crate::gpu::{drawable_image, needs_mipmaps, ISkiaGrContext};
2use crate::helpers::image_saving_helper;
3use crate::i_drawable_bitmap_impl::IDrawableBitmapImpl;
4use crate::immutable_bitmap::{decode_bitmap, decode_bitmap_to_size, SendBitmap};
5use crate::skia_platform::SkiaPlatform;
6use crate::skia_sharp_extensions::{
7 to_alpha_format, to_pixel_format, to_pixel_format_opt, to_sk_alpha_type, to_sk_color_type_or_panic,
8};
9use ferroui_base::media::imaging::{BitmapEncoderOptions, BitmapInterpolationMode};
10use ferroui_base::platform::{
11 AlphaFormat, IBitmapImpl, ILockedFramebuffer, IReadableBitmapImpl, IWriteableBitmapImpl, PixelFormat,
12};
13use ferroui_base::{PixelSize, Vector};
14use skia_safe::canvas::SrcRectConstraint;
15use skia_safe::{images, Bitmap, Canvas, Color, Data, Image, ImageInfo, Paint, Rect, SamplingOptions};
16use std::any::Any;
17use std::cell::RefCell;
18use std::io::{self, Read, Write};
19use std::rc::Rc;
20use std::sync::atomic::{AtomicI32, Ordering};
21use std::sync::{Arc, Mutex, Weak};
22
23pub struct WriteableBitmapImpl {
28 weak_self: Weak<WriteableBitmapImpl>,
29 pixels: Mutex<Pixels>,
30 dpi: Vector,
31 pixel_size: PixelSize,
32 version: AtomicI32,
33}
34
35struct Pixels {
36 bitmap: Option<SendBitmap>,
37 image: Option<Image>,
39}
40
41impl WriteableBitmapImpl {
42 fn from_bitmap(bitmap: Bitmap, pixel_size: PixelSize, dpi: Vector) -> Arc<Self> {
43 Arc::new_cyclic(|weak_self| Self {
44 weak_self: weak_self.clone(),
45 pixels: Mutex::new(Pixels { bitmap: Some(SendBitmap(bitmap)), image: None }),
46 dpi,
47 pixel_size,
48 version: AtomicI32::new(1),
49 })
50 }
51
52 pub fn from_stream(stream: &mut dyn Read) -> io::Result<Arc<Self>> {
54 let bitmap = decode_bitmap(stream)?;
55 let pixel_size = PixelSize::new(bitmap.width(), bitmap.height());
56
57 Ok(Self::from_bitmap(bitmap, pixel_size, SkiaPlatform::default_dpi()))
58 }
59
60 pub fn from_stream_to_size(
63 stream: &mut dyn Read,
64 decode_size: i32,
65 horizontal: bool,
66 interpolation_mode: BitmapInterpolationMode,
67 ) -> io::Result<Arc<Self>> {
68 let bitmap = decode_bitmap_to_size(stream, decode_size, horizontal, interpolation_mode)?;
69 let pixel_size = PixelSize::new(bitmap.width(), bitmap.height());
70
71 Ok(Self::from_bitmap(bitmap, pixel_size, SkiaPlatform::default_dpi()))
72 }
73
74 pub fn new(size: PixelSize, dpi: Vector, format: PixelFormat, alpha_format: AlphaFormat) -> Arc<Self> {
81 let color_type = to_sk_color_type_or_panic(format);
82 let alpha_type = to_sk_alpha_type(alpha_format);
83
84 let nfo = ImageInfo::new((size.width, size.height), color_type, alpha_type, None);
85
86 let mut bitmap = Bitmap::new();
87 if !bitmap.try_alloc_pixels_info(&nfo, None) {
88 panic!("Unable to allocate a {}x{} bitmap", size.width, size.height);
89 }
90 bitmap.erase_color(Color::TRANSPARENT);
91
92 Self::from_bitmap(bitmap, size, dpi)
93 }
94
95 fn with_bitmap<R>(&self, f: impl FnOnce(&Bitmap) -> R) -> R {
96 let pixels = self.pixels.lock().unwrap();
97 f(pixels.bitmap.as_ref().expect("WriteableBitmapImpl has been disposed"))
98 }
99
100 fn snapshot_of(bitmap: &Bitmap) -> Image {
101 let pixmap = bitmap.pixmap();
102 let bytes = pixmap.bytes().unwrap_or(&[]);
103 images::raster_from_data(bitmap.info(), Data::new_copy(bytes), bitmap.row_bytes())
104 .unwrap_or_else(|| panic!("Unable to create an image from the bitmap pixels"))
105 }
106
107 pub fn get_snapshot(&self) -> Image {
110 self.with_bitmap(Self::snapshot_of)
111 }
112}
113
114impl IBitmapImpl for WriteableBitmapImpl {
115 fn dpi(&self) -> Vector {
116 self.dpi
117 }
118
119 fn pixel_size(&self) -> PixelSize {
120 self.pixel_size
121 }
122
123 fn version(&self) -> i32 {
124 self.version.load(Ordering::SeqCst)
125 }
126
127 fn save(&self, stream: &mut dyn Write, options: &BitmapEncoderOptions) -> io::Result<()> {
128 let image = self.get_snapshot();
129 image_saving_helper::save_image(&image, stream, options)
130 }
131
132 fn dispose(&self) {
133 let mut pixels = self.pixels.lock().unwrap();
134 pixels.image.take();
135 pixels.bitmap.take();
136 }
137
138 fn as_any(&self) -> &dyn Any {
139 self
140 }
141
142 fn as_readable_bitmap(&self) -> Option<&dyn IReadableBitmapImpl> {
143 Some(self)
144 }
145}
146
147impl IDrawableBitmapImpl for WriteableBitmapImpl {
148 fn draw(
149 &self,
150 gr_context: Option<&dyn ISkiaGrContext>,
151 canvas: &Canvas,
152 source_rect: &Rect,
153 dest_rect: &Rect,
154 sampling_options: SamplingOptions,
155 paint: &Paint,
156 ) {
157 let image = {
158 let mut pixels = self.pixels.lock().unwrap();
159 if pixels.image.is_none() {
160 let snapshot =
165 Self::snapshot_of(pixels.bitmap.as_ref().expect("WriteableBitmapImpl has been disposed"));
166 pixels.image = Some(snapshot);
167 }
168 pixels.image.clone()
169 };
170
171 if let Some(image) = image {
172 canvas.draw_image_rect_with_sampling_options(
173 drawable_image(gr_context, image, needs_mipmaps(&sampling_options)),
174 Some((source_rect, SrcRectConstraint::Fast)),
175 dest_rect,
176 sampling_options,
177 paint,
178 );
179 }
180 }
181}
182
183impl IReadableBitmapImpl for WriteableBitmapImpl {
184 fn format(&self) -> Option<PixelFormat> {
185 self.with_bitmap(|bitmap| to_pixel_format_opt(bitmap.color_type()))
186 }
187
188 fn alpha_format(&self) -> Option<AlphaFormat> {
189 self.with_bitmap(|bitmap| Some(to_alpha_format(bitmap.alpha_type())))
190 }
191
192 fn lock(&self) -> Rc<dyn ILockedFramebuffer> {
193 let parent = self.weak_self.upgrade().expect("WriteableBitmapImpl is alive while it is used");
194 Rc::new(BitmapFramebuffer { parent: RefCell::new(Some(parent)) })
195 }
196}
197
198impl IWriteableBitmapImpl for WriteableBitmapImpl {}
199
200struct BitmapFramebuffer {
202 parent: RefCell<Option<Arc<WriteableBitmapImpl>>>,
203}
204
205impl BitmapFramebuffer {
206 fn with_bitmap<R>(&self, f: impl FnOnce(&WriteableBitmapImpl, &Bitmap) -> R) -> R {
207 let parent = self.parent.borrow();
208 let parent = parent.as_ref().expect("the framebuffer has been unlocked");
209 parent.with_bitmap(|bitmap| f(parent, bitmap))
210 }
211}
212
213impl ILockedFramebuffer for BitmapFramebuffer {
214 fn address(&self) -> *mut u8 {
215 self.with_bitmap(|_, bitmap| bitmap.pixmap().addr() as *mut u8)
216 }
217
218 fn with_data(&self, access: &mut dyn FnMut(&mut [u8])) {
219 self.with_bitmap(|_, bitmap| match bitmap.peek_pixels().as_mut().and_then(|pixmap| pixmap.bytes_mut()) {
220 Some(bytes) => access(bytes),
221 None => access(&mut []),
222 });
223 }
224
225 fn size(&self) -> PixelSize {
226 self.with_bitmap(|_, bitmap| PixelSize::new(bitmap.width(), bitmap.height()))
227 }
228
229 fn row_bytes(&self) -> i32 {
230 self.with_bitmap(|_, bitmap| bitmap.row_bytes() as i32)
231 }
232
233 fn dpi(&self) -> Vector {
234 self.with_bitmap(|parent, _| parent.dpi)
235 }
236
237 fn format(&self) -> PixelFormat {
238 self.with_bitmap(|_, bitmap| to_pixel_format(bitmap.color_type()))
239 }
240
241 fn alpha_format(&self) -> AlphaFormat {
242 self.with_bitmap(|_, bitmap| to_alpha_format(bitmap.alpha_type()))
243 }
244
245 fn dispose(&self) {
246 if let Some(parent) = self.parent.borrow_mut().take() {
247 let mut pixels = parent.pixels.lock().unwrap();
248 if let Some(bitmap) = pixels.bitmap.as_ref() {
249 bitmap.notify_pixels_changed();
250 }
251 parent.version.fetch_add(1, Ordering::SeqCst);
252 pixels.image = None;
254 }
255 }
256}