mirror of
https://github.com/emilk/egui.git
synced 2026-08-31 13:50:04 -04:00
Update resvg dependency of egui_extras (#3719)
Update `resvg` from v0.28 to v0.37. Remove related, unnecessary entries from `deny.toml`. ⚠ In example `images` ferris is scaled differently, but I guess that now it scales in expected way (takes all available space; before this PR it takes up to space that, was available at first render- it does not upscale). This PR is minimal adaptation to new `resvg` api and small related simplification, however it should be considered to update loaders (currently if svg image initially was small and was scaled up it will be blurred, see https://github.com/emilk/egui/issues/3501). As svg image now scales over render size, problem will be more often seen now. (currently `SvgLoader` theoretically should rerender for different sizes (but I guess it will result in memory leak in that case), but refreshing is stopped earlier in `DefaultTextureLoader`). I have initial version of loaders update, that will fix issue with svg scaling (and also enable e.g. reloading image if file has been changed), I will submit these changes in separate PR once this one is merged. Closes <https://github.com/emilk/egui/issues/3652>.
This commit is contained in:
@@ -3,10 +3,7 @@
|
||||
use egui::{mutex::Mutex, TextureOptions};
|
||||
|
||||
#[cfg(feature = "svg")]
|
||||
use resvg::{tiny_skia, usvg};
|
||||
|
||||
#[cfg(feature = "svg")]
|
||||
pub use usvg::FitTo;
|
||||
use egui::SizeHint;
|
||||
|
||||
/// An image to be shown in egui.
|
||||
///
|
||||
@@ -67,7 +64,7 @@ impl RetainedImage {
|
||||
/// On invalid image
|
||||
#[cfg(feature = "svg")]
|
||||
pub fn from_svg_bytes(debug_name: impl Into<String>, svg_bytes: &[u8]) -> Result<Self, String> {
|
||||
Self::from_svg_bytes_with_size(debug_name, svg_bytes, FitTo::Original)
|
||||
Self::from_svg_bytes_with_size(debug_name, svg_bytes, None)
|
||||
}
|
||||
|
||||
/// Pass in the str of an SVG that you've loaded.
|
||||
@@ -88,11 +85,11 @@ impl RetainedImage {
|
||||
pub fn from_svg_bytes_with_size(
|
||||
debug_name: impl Into<String>,
|
||||
svg_bytes: &[u8],
|
||||
size: FitTo,
|
||||
size_hint: Option<SizeHint>,
|
||||
) -> Result<Self, String> {
|
||||
Ok(Self::from_color_image(
|
||||
debug_name,
|
||||
load_svg_bytes_with_size(svg_bytes, size)?,
|
||||
load_svg_bytes_with_size(svg_bytes, size_hint)?,
|
||||
))
|
||||
}
|
||||
|
||||
@@ -223,7 +220,7 @@ pub fn load_image_bytes(image_bytes: &[u8]) -> Result<egui::ColorImage, String>
|
||||
/// On invalid image
|
||||
#[cfg(feature = "svg")]
|
||||
pub fn load_svg_bytes(svg_bytes: &[u8]) -> Result<egui::ColorImage, String> {
|
||||
load_svg_bytes_with_size(svg_bytes, FitTo::Original)
|
||||
load_svg_bytes_with_size(svg_bytes, None)
|
||||
}
|
||||
|
||||
/// Load an SVG and rasterize it into an egui image with a scaling parameter.
|
||||
@@ -235,36 +232,31 @@ pub fn load_svg_bytes(svg_bytes: &[u8]) -> Result<egui::ColorImage, String> {
|
||||
#[cfg(feature = "svg")]
|
||||
pub fn load_svg_bytes_with_size(
|
||||
svg_bytes: &[u8],
|
||||
fit_to: FitTo,
|
||||
size_hint: Option<SizeHint>,
|
||||
) -> Result<egui::ColorImage, String> {
|
||||
use resvg::tiny_skia::{IntSize, Pixmap};
|
||||
use resvg::usvg::{Options, Tree, TreeParsing};
|
||||
|
||||
crate::profile_function!();
|
||||
let opt = usvg::Options::default();
|
||||
let opt = Options::default();
|
||||
|
||||
let rtree = usvg::Tree::from_data(svg_bytes, &opt).map_err(|err| err.to_string())?;
|
||||
let mut rtree = Tree::from_data(svg_bytes, &opt).map_err(|err| err.to_string())?;
|
||||
|
||||
let pixmap_size = rtree.size.to_screen_size();
|
||||
let [w, h] = match fit_to {
|
||||
FitTo::Original => [pixmap_size.width(), pixmap_size.height()],
|
||||
FitTo::Size(w, h) => [w, h],
|
||||
FitTo::Height(h) => [
|
||||
(pixmap_size.width() as f32 * (h as f32 / pixmap_size.height() as f32)) as u32,
|
||||
h,
|
||||
],
|
||||
FitTo::Width(w) => [
|
||||
w,
|
||||
(pixmap_size.height() as f32 * (w as f32 / pixmap_size.width() as f32)) as u32,
|
||||
],
|
||||
FitTo::Zoom(z) => [
|
||||
(pixmap_size.width() as f32 * z) as u32,
|
||||
(pixmap_size.height() as f32 * z) as u32,
|
||||
],
|
||||
let mut size = rtree.size.to_int_size();
|
||||
match size_hint {
|
||||
None => (),
|
||||
Some(SizeHint::Size(w, h)) => size = size.scale_to(IntSize::from_wh(w, h).unwrap()),
|
||||
Some(SizeHint::Height(h)) => size = size.scale_to_height(h).unwrap(),
|
||||
Some(SizeHint::Width(w)) => size = size.scale_to_width(w).unwrap(),
|
||||
Some(SizeHint::Scale(z)) => size = size.scale_by(z.into_inner()).unwrap(),
|
||||
};
|
||||
let (w, h) = (size.width(), size.height());
|
||||
|
||||
let mut pixmap = tiny_skia::Pixmap::new(w, h)
|
||||
.ok_or_else(|| format!("Failed to create SVG Pixmap of size {w}x{h}"))?;
|
||||
let mut pixmap =
|
||||
Pixmap::new(w, h).ok_or_else(|| format!("Failed to create SVG Pixmap of size {w}x{h}"))?;
|
||||
|
||||
resvg::render(&rtree, fit_to, Default::default(), pixmap.as_mut())
|
||||
.ok_or_else(|| "Failed to render SVG".to_owned())?;
|
||||
rtree.size = size.to_size();
|
||||
resvg::Tree::from_usvg(&rtree).render(Default::default(), &mut pixmap.as_mut());
|
||||
|
||||
let image = egui::ColorImage::from_rgba_unmultiplied([w as _, h as _], pixmap.data());
|
||||
|
||||
|
||||
@@ -7,8 +7,6 @@ use egui::{
|
||||
ColorImage,
|
||||
};
|
||||
|
||||
use resvg::usvg;
|
||||
|
||||
type Entry = Result<Arc<ColorImage>, String>;
|
||||
|
||||
#[derive(Default)]
|
||||
@@ -51,14 +49,8 @@ impl ImageLoader for SvgLoader {
|
||||
match ctx.try_load_bytes(&uri) {
|
||||
Ok(BytesPoll::Ready { bytes, .. }) => {
|
||||
log::trace!("started loading {uri:?}");
|
||||
let fit_to = match size_hint {
|
||||
SizeHint::Scale(factor) => usvg::FitTo::Zoom(factor.into_inner()),
|
||||
SizeHint::Width(w) => usvg::FitTo::Width(w),
|
||||
SizeHint::Height(h) => usvg::FitTo::Height(h),
|
||||
SizeHint::Size(w, h) => usvg::FitTo::Size(w, h),
|
||||
};
|
||||
let result =
|
||||
crate::image::load_svg_bytes_with_size(&bytes, fit_to).map(Arc::new);
|
||||
let result = crate::image::load_svg_bytes_with_size(&bytes, Some(size_hint))
|
||||
.map(Arc::new);
|
||||
log::trace!("finished loading {uri:?}");
|
||||
cache.insert((uri, size_hint), result.clone());
|
||||
match result {
|
||||
|
||||
Reference in New Issue
Block a user