From b63b717eacc7ea579c53a382232db12ad800a665 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 14 Sep 2021 16:39:35 -0600 Subject: [PATCH] Preserve aspect ratio when scaling images Co-Authored-By: Max Brunsfeld --- gpui/src/elements.rs | 15 ++++++++++++++- gpui/src/elements/image.rs | 6 +++++- gpui/src/elements/svg.rs | 21 ++++++--------------- 3 files changed, 25 insertions(+), 17 deletions(-) diff --git a/gpui/src/elements.rs b/gpui/src/elements.rs index 252cebd7334f57874a8fd6164da15ad0ba3c2986..42e9810cfbff21ea9c96017b54689cb5a77f48cd 100644 --- a/gpui/src/elements.rs +++ b/gpui/src/elements.rs @@ -24,7 +24,10 @@ pub use self::{ }; pub use crate::presenter::ChildView; use crate::{ - geometry::{rect::RectF, vector::Vector2F}, + geometry::{ + rect::RectF, + vector::{vec2f, Vector2F}, + }, json, DebugContext, Event, EventContext, LayoutContext, PaintContext, SizeConstraint, }; use core::panic; @@ -359,3 +362,13 @@ pub trait ParentElement<'a>: Extend + Sized { } impl<'a, T> ParentElement<'a> for T where T: Extend {} + +fn constrain_size_preserving_aspect_ratio(max_size: Vector2F, size: Vector2F) -> Vector2F { + if max_size.x().is_infinite() && max_size.y().is_infinite() { + size + } else if max_size.x().is_infinite() || max_size.x() / max_size.y() > size.x() / size.y() { + vec2f(size.x() * max_size.y() / size.y(), max_size.y()) + } else { + vec2f(max_size.x(), size.y() * max_size.x() / size.x()) + } +} diff --git a/gpui/src/elements/image.rs b/gpui/src/elements/image.rs index 2611478fe0b85e93ee9f55147e0b758e53427153..f9908a76fb77b9ce3c14b1fc2f7073401ed84a00 100644 --- a/gpui/src/elements/image.rs +++ b/gpui/src/elements/image.rs @@ -6,6 +6,8 @@ use crate::{ }; use std::sync::Arc; +use super::constrain_size_preserving_aspect_ratio; + pub struct Image { data: Arc, border: Border, @@ -41,7 +43,9 @@ impl Element for Image { constraint: SizeConstraint, _: &mut LayoutContext, ) -> (Vector2F, Self::LayoutState) { - (constraint.max, ()) + let size = + constrain_size_preserving_aspect_ratio(constraint.max, self.data.size().to_f32()); + (size, ()) } fn paint( diff --git a/gpui/src/elements/svg.rs b/gpui/src/elements/svg.rs index 8adb285b99a73c1e2ab661976d4f2d58d4d635db..55e11a92531341262e69e79ff6365a2c20cfa5b6 100644 --- a/gpui/src/elements/svg.rs +++ b/gpui/src/elements/svg.rs @@ -41,21 +41,10 @@ impl Element for Svg { ) -> (Vector2F, Self::LayoutState) { match cx.asset_cache.svg(&self.path) { Ok(tree) => { - let size = if constraint.max.x().is_infinite() && constraint.max.y().is_infinite() { - let rect = from_usvg_rect(tree.svg_node().view_box.rect); - rect.size() - } else { - let max_size = constraint.max; - let svg_size = from_usvg_rect(tree.svg_node().view_box.rect).size(); - - if max_size.x().is_infinite() - || max_size.x() / max_size.y() > svg_size.x() / svg_size.y() - { - vec2f(svg_size.x() * max_size.y() / svg_size.y(), max_size.y()) - } else { - vec2f(max_size.x(), svg_size.y() * max_size.x() / svg_size.x()) - } - }; + let size = constrain_size_preserving_aspect_ratio( + constraint.max, + from_usvg_rect(tree.svg_node().view_box.rect).size(), + ); (size, Some(tree)) } Err(error) => { @@ -111,6 +100,8 @@ impl Element for Svg { use crate::json::ToJson; +use super::constrain_size_preserving_aspect_ratio; + fn from_usvg_rect(rect: usvg::Rect) -> RectF { RectF::new( vec2f(rect.x() as f32, rect.y() as f32),