diff --git a/crates/eframe/Cargo.toml b/crates/eframe/Cargo.toml index 0530b64a8..197085e65 100644 --- a/crates/eframe/Cargo.toml +++ b/crates/eframe/Cargo.toml @@ -29,12 +29,18 @@ default = [ "accesskit", "default_fonts", "wayland", # Required for Linux support (including CI!) + "web_clipboard_image", "web_screen_reader", "wgpu", "winit/default", "x11", ] +## Enable PNG-encoding `egui::ColorImage`s for the web clipboard via the +## [`image`](https://docs.rs/image) crate. Disable on the web to drop the +## image (and image-webp / moxcms / ...) crates from the wasm bundle. +web_clipboard_image = ["dep:image"] + ## Enable platform accessibility API implementations through [AccessKit](https://accesskit.dev/). accesskit = ["egui-winit/accesskit"] @@ -195,7 +201,10 @@ windows-sys = { workspace = true, features = [ # web: [target.'cfg(target_arch = "wasm32")'.dependencies] bytemuck.workspace = true -image = { workspace = true, features = ["png"] } # For copying images +# `image` is only needed for the "copy image to clipboard" path on the web. +# Behind `web_clipboard_image` (default-on) so apps that don't care can drop +# the image crate (and ~600 KB of png/webp/moxcms compressed code with it). +image = { workspace = true, features = ["png"], optional = true } js-sys.workspace = true percent-encoding.workspace = true wasm-bindgen.workspace = true diff --git a/crates/eframe/src/web/app_runner.rs b/crates/eframe/src/web/app_runner.rs index 7161a665e..ea8d2765a 100644 --- a/crates/eframe/src/web/app_runner.rs +++ b/crates/eframe/src/web/app_runner.rs @@ -385,7 +385,16 @@ impl AppRunner { super::set_clipboard_text(&text); } egui::OutputCommand::CopyImage(image) => { + #[cfg(feature = "web_clipboard_image")] super::set_clipboard_image(&image); + #[cfg(not(feature = "web_clipboard_image"))] + { + let _ = image; + log::warn!( + "CopyImage requested but eframe was built without the \ + `web_clipboard_image` feature; ignoring." + ); + } } egui::OutputCommand::OpenUrl(open_url) => { super::open_url(&open_url.url, open_url.new_tab); diff --git a/crates/eframe/src/web/mod.rs b/crates/eframe/src/web/mod.rs index dc743ec49..0026ad4c4 100644 --- a/crates/eframe/src/web/mod.rs +++ b/crates/eframe/src/web/mod.rs @@ -207,6 +207,7 @@ fn set_clipboard_text(s: &str) { } /// Set the clipboard image. +#[cfg(feature = "web_clipboard_image")] fn set_clipboard_image(image: &egui::ColorImage) { if let Some(window) = web_sys::window() { if !window.is_secure_context() { @@ -250,6 +251,7 @@ fn set_clipboard_image(image: &egui::ColorImage) { } } +#[cfg(feature = "web_clipboard_image")] fn to_image(image: &egui::ColorImage) -> Result { profiling::function_scope!(); image::RgbaImage::from_raw( @@ -260,6 +262,7 @@ fn to_image(image: &egui::ColorImage) -> Result { .ok_or_else(|| "Invalid IconData".to_owned()) } +#[cfg(feature = "web_clipboard_image")] fn to_png_bytes(image: &image::RgbaImage) -> Result, String> { profiling::function_scope!(); let mut png_bytes: Vec = Vec::new(); @@ -272,6 +275,7 @@ fn to_png_bytes(image: &image::RgbaImage) -> Result, String> { Ok(png_bytes) } +#[cfg(feature = "web_clipboard_image")] fn create_clipboard_item(mime: &str, bytes: &[u8]) -> Result { let array = js_sys::Uint8Array::from(bytes); let blob_parts = js_sys::Array::new();