1
0
mirror of https://github.com/emilk/egui.git synced 2026-09-01 22:30:03 -04:00

Introduce egui_extras with RetainedImage for loading svg,png,jpeg,… (#1282)

This commit is contained in:
Emil Ernerfeldt
2022-02-21 15:26:26 +01:00
committed by GitHub
parent 713917e481
commit c3fc8997d6
18 changed files with 453 additions and 176 deletions

View File

@@ -1,82 +1,23 @@
//! A good way of displaying an SVG image in egui.
//!
//! Requires the dependencies `resvg`, `tiny-skia`, `usvg`
//! Requires the dependency `egui_extras` with the `svg` feature.
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] // hide console window on Windows in release
use eframe::{egui, epi};
/// Load an SVG and rasterize it into an egui image.
fn load_svg_data(svg_data: &[u8]) -> Result<egui::ColorImage, String> {
let mut opt = usvg::Options::default();
opt.fontdb.load_system_fonts();
let rtree = usvg::Tree::from_data(svg_data, &opt.to_ref()).map_err(|err| err.to_string())?;
let pixmap_size = rtree.svg_node().size.to_screen_size();
let [w, h] = [pixmap_size.width(), pixmap_size.height()];
let mut pixmap = tiny_skia::Pixmap::new(w, h)
.ok_or_else(|| format!("Failed to create SVG Pixmap of size {}x{}", w, h))?;
resvg::render(
&rtree,
usvg::FitTo::Original,
tiny_skia::Transform::default(),
pixmap.as_mut(),
)
.ok_or_else(|| "Failed to render SVG".to_owned())?;
let image = egui::ColorImage::from_rgba_unmultiplied(
[pixmap.width() as _, pixmap.height() as _],
pixmap.data(),
);
Ok(image)
}
// ----------------------------------------------------------------------------
/// An SVG image to be shown in egui
struct SvgImage {
image: egui::ColorImage,
texture: Option<egui::TextureHandle>,
}
impl SvgImage {
/// Pass itn the bytes of an SVG that you've loaded from disk
pub fn from_svg_data(bytes: &[u8]) -> Result<Self, String> {
Ok(Self {
image: load_svg_data(bytes)?,
texture: None,
})
}
pub fn show_max_size(&mut self, ui: &mut egui::Ui, max_size: egui::Vec2) -> egui::Response {
let mut desired_size = egui::vec2(self.image.width() as _, self.image.height() as _);
desired_size *= (max_size.x / desired_size.x).min(1.0);
desired_size *= (max_size.y / desired_size.y).min(1.0);
self.show_size(ui, desired_size)
}
pub fn show_size(&mut self, ui: &mut egui::Ui, desired_size: egui::Vec2) -> egui::Response {
// We need to convert the SVG to a texture to display it:
// Future improvement: tell backend to do mip-mapping of the image to
// make it look smoother when downsized.
let svg_texture = self
.texture
.get_or_insert_with(|| ui.ctx().load_texture("svg", self.image.clone()));
ui.image(svg_texture, desired_size)
}
}
// ----------------------------------------------------------------------------
struct MyApp {
svg_image: SvgImage,
svg_image: egui_extras::RetainedImage,
}
impl Default for MyApp {
fn default() -> Self {
Self {
svg_image: SvgImage::from_svg_data(include_bytes!("rustacean-flat-happy.svg")).unwrap(),
svg_image: egui_extras::RetainedImage::from_svg_bytes(
"rustacean-flat-happy.svg",
include_bytes!("rustacean-flat-happy.svg"),
)
.unwrap(),
}
}
}