From d1ca8ec0cd9bf4974f0ba11bbb4a8f03d951c8f3 Mon Sep 17 00:00:00 2001 From: Nicolas Date: Wed, 20 Nov 2024 22:05:22 +0100 Subject: [PATCH] handle image loading on wasm in the old way --- .../egui_extras/src/loaders/image_loader.rs | 96 +++++++++++++------ 1 file changed, 68 insertions(+), 28 deletions(-) diff --git a/crates/egui_extras/src/loaders/image_loader.rs b/crates/egui_extras/src/loaders/image_loader.rs index d26d64b1587..5356c3cf70d 100644 --- a/crates/egui_extras/src/loaders/image_loader.rs +++ b/crates/egui_extras/src/loaders/image_loader.rs @@ -1,11 +1,14 @@ use ahash::HashMap; use egui::{ - load::{BytesPoll, ImageLoadResult, ImageLoader, ImagePoll, LoadError, SizeHint}, + load::{Bytes, BytesPoll, ImageLoadResult, ImageLoader, ImagePoll, LoadError, SizeHint}, mutex::Mutex, ColorImage, }; use image::ImageFormat; -use std::{mem::size_of, path::Path, sync::Arc, task::Poll, thread}; +use std::{mem::size_of, path::Path, sync::Arc, task::Poll}; + +#[cfg(not(target_arch = "wasm32"))] +use std::thread; type Entry = Poll, String>>; @@ -55,7 +58,61 @@ impl ImageLoader for ImageCrateLoader { return Err(LoadError::NotSupported); } - let mut cache = self.cache.lock(); + let cache = self.cache.lock(); + + #[cfg(not(target_arch = "wasm32"))] + #[allow(clippy::unnecessary_wraps)] // needed here to match other return types + fn load_image( + ctx: &egui::Context, + uri: &str, + cache: &Arc>>, + bytes: Bytes, + ) -> ImageLoadResult { + let mut cache_lock = cache.lock(); + + let uri = uri.to_owned(); + cache_lock.insert(uri.clone(), Poll::Pending); + drop(cache_lock); + + // Do the image parsing on a bg thread + thread::Builder::new() + .name(format!("egui_extras::ImageLoader::load({uri:?})")) + .spawn({ + let ctx = ctx.clone(); + let cache = cache.clone(); + + let uri = uri.clone(); + move || { + log::trace!("ImageLoader - started loading {uri:?}"); + let result = crate::image::load_image_bytes(&bytes).map(Arc::new); + log::trace!("ImageLoader - finished loading {uri:?}"); + let prev = cache.lock().insert(uri, Poll::Ready(result)); + assert!(matches!(prev, Some(Poll::Pending))); + + ctx.request_repaint(); + } + }) + .expect("failed to spawn thread"); + + Ok(ImagePoll::Pending { size: None }) + } + + fn load_image_wasm( + uri: &str, + cache: &Arc>>, + bytes: &Bytes, + ) -> ImageLoadResult { + let mut cache_lock = cache.lock(); + log::trace!("started loading {uri:?}"); + let result = crate::image::load_image_bytes(bytes).map(Arc::new); + log::trace!("finished loading {uri:?}"); + cache_lock.insert(uri.into(), std::task::Poll::Ready(result.clone())); + match result { + Ok(image) => Ok(ImagePoll::Ready { image }), + Err(err) => Err(LoadError::Loading(err)), + } + } + if let Some(entry) = cache.get(uri).cloned() { match entry { Poll::Ready(Ok(image)) => Ok(ImagePoll::Ready { image }), @@ -72,31 +129,14 @@ impl ImageLoader for ImageCrateLoader { return Err(LoadError::NotSupported); } - let uri = uri.to_owned(); - cache.insert(uri.clone(), Poll::Pending); - drop(cache); - - // Do the image parsing on a bg thread - thread::Builder::new() - .name(format!("egui_extras::ImageLoader::load({uri:?})")) - .spawn({ - let ctx = ctx.clone(); - let cache = self.cache.clone(); - - let uri = uri.clone(); - move || { - log::trace!("ImageLoader - started loading {uri:?}"); - let result = crate::image::load_image_bytes(&bytes).map(Arc::new); - log::trace!("ImageLoader - finished loading {uri:?}"); - let prev = cache.lock().insert(uri, Poll::Ready(result)); - assert!(matches!(prev, Some(Poll::Pending))); - - ctx.request_repaint(); - } - }) - .expect("failed to spawn thread"); - - Ok(ImagePoll::Pending { size: None }) + if cfg!(target_arch = "wasm32") { + load_image_wasm(uri, &self.cache, &bytes) + } else { + #[cfg(target_arch = "wasm32")] + unreachable!(); + #[cfg(not(target_arch = "wasm32"))] + load_image(ctx, uri, &self.cache, bytes) + } } Ok(BytesPoll::Pending { size }) => Ok(ImagePoll::Pending { size }), Err(err) => Err(err),