diff --git a/crates/gpui2/src/elements/img.rs b/crates/gpui2/src/elements/img.rs index 87a7cda07f..dd59ddb17c 100644 --- a/crates/gpui2/src/elements/img.rs +++ b/crates/gpui2/src/elements/img.rs @@ -1,8 +1,9 @@ use std::sync::Arc; use crate::{ - size, Bounds, Element, ImageData, InteractiveElement, InteractiveElementState, Interactivity, - IntoElement, LayoutId, Pixels, SharedString, Size, StyleRefinement, Styled, WindowContext, + point, size, Bounds, DevicePixels, Element, ImageData, InteractiveElement, + InteractiveElementState, Interactivity, IntoElement, LayoutId, Pixels, SharedString, Size, + StyleRefinement, Styled, WindowContext, }; use futures::FutureExt; use media::core_video::CVImageBuffer; @@ -63,54 +64,8 @@ impl Element for Img { element_state: Option, cx: &mut WindowContext, ) -> (LayoutId, Self::State) { - self.interactivity.layout(element_state, cx, |style, cx| { - let image_size = match &self.source { - ImageSource::Uri(uri) => { - let image_future = cx.image_cache.get(uri.clone()); - if let Some(data) = image_future - .clone() - .now_or_never() - .and_then(|result| result.ok()) - { - data.size().map(|pixels| Pixels::from(u32::from(pixels))) - } else { - Size::default() - } - } - - ImageSource::Data(data) => { - data.size().map(|pixels| Pixels::from(u32::from(pixels))) - } - - ImageSource::Surface(surface) => { - size(surface.width().into(), surface.height().into()) - } - }; - dbg!(image_size); - - cx.request_measured_layout( - style, - cx.rem_size(), - move |known_dimensions, available_space| match dbg!( - known_dimensions.width, - known_dimensions.height, - ) { - (None, None) => image_size, - - (None, Some(height)) => { - let aspect_ratio = height / image_size.height; - size(image_size.width * aspect_ratio, height) - } - - (Some(width), None) => { - let aspect_ratio = width / image_size.width; - size(width, image_size.height * aspect_ratio) - } - - (Some(width), Some(height)) => size(width, height), - }, - ) - }) + self.interactivity + .layout(element_state, cx, |style, cx| cx.request_layout(&style, [])) } fn paint( @@ -135,7 +90,8 @@ impl Element for Img { .now_or_never() .and_then(|result| result.ok()) { - cx.paint_image(bounds, corner_radii, data, self.grayscale) + let new_bounds = preserve_aspect_ratio(bounds, data.size()); + cx.paint_image(new_bounds, corner_radii, data, self.grayscale) .log_err(); } else { cx.spawn(|mut cx| async move { @@ -147,14 +103,17 @@ impl Element for Img { } } - ImageSource::Data(image) => { - cx.paint_image(bounds, corner_radii, image, self.grayscale) + ImageSource::Data(data) => { + let new_bounds = preserve_aspect_ratio(bounds, data.size()); + cx.paint_image(new_bounds, corner_radii, data, self.grayscale) .log_err(); } ImageSource::Surface(surface) => { + let size = size(surface.width().into(), surface.height().into()); + let new_bounds = preserve_aspect_ratio(bounds, size); // TODO: Add support for corner_radii and grayscale. - cx.paint_surface(bounds, surface); + cx.paint_surface(new_bounds, surface); } }; }); @@ -186,3 +145,21 @@ impl InteractiveElement for Img { &mut self.interactivity } } + +fn preserve_aspect_ratio(bounds: Bounds, image_size: Size) -> Bounds { + let new_size = if bounds.size.width > bounds.size.height { + let ratio = u32::from(image_size.height) as f32 / u32::from(image_size.width) as f32; + size(bounds.size.width, bounds.size.width * ratio) + } else { + let ratio = u32::from(image_size.width) as f32 / u32::from(image_size.height) as f32; + size(bounds.size.width * ratio, bounds.size.height) + }; + + Bounds { + origin: point( + bounds.origin.x + (bounds.size.width - new_size.width) / 2.0, + bounds.origin.y + (bounds.size.height - new_size.height) / 2.0, + ), + size: new_size, + } +} diff --git a/crates/gpui2/src/geometry.rs b/crates/gpui2/src/geometry.rs index 5ade68663c..bc927a17ba 100644 --- a/crates/gpui2/src/geometry.rs +++ b/crates/gpui2/src/geometry.rs @@ -965,6 +965,18 @@ impl From for DevicePixels { } } +impl From for usize { + fn from(device_pixels: DevicePixels) -> Self { + device_pixels.0 as usize + } +} + +impl From for DevicePixels { + fn from(device_pixels: usize) -> Self { + DevicePixels(device_pixels as i32) + } +} + #[derive(Clone, Copy, Default, Add, AddAssign, Sub, SubAssign, Div, PartialEq, PartialOrd)] #[repr(transparent)] pub struct ScaledPixels(pub(crate) f32);