notedeck

One damus client to rule them all
git clone git://jb55.com/notedeck
Log | Files | Refs | README | LICENSE

commit 7f61d9aeb7ba3dc4f6633cab4798d9dd860f3a2d
parent 55111b8b2578065f7c045d94d0e845c0b8ffb16e
Author: William Casarin <jb55@jb55.com>
Date:   Sun, 21 Apr 2024 14:34:53 -0700

images: add aspect_fill

This is similar to SwiftUI's .aspectRatio(contentMode: .fill) so that
we can get a filling banner image

Signed-off-by: William Casarin <jb55@jb55.com>

Diffstat:
Msrc/images.rs | 46+++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 45 insertions(+), 1 deletion(-)

diff --git a/src/images.rs b/src/images.rs @@ -1,7 +1,7 @@ use crate::error::Error; use crate::imgcache::ImageCache; use crate::result::Result; -use egui::{Color32, ColorImage, SizeHint, TextureHandle}; +use egui::{pos2, Color32, ColorImage, Rect, Sense, SizeHint, TextureHandle}; use image::imageops::FilterType; use poll_promise::Promise; use std::path; @@ -11,6 +11,50 @@ use tokio::fs; //pub type ImageCacheValue = Promise<Result<TextureHandle>>; //pub type ImageCache = HashMap<String, ImageCacheValue>; +// NOTE(jb55): chatgpt wrote this because I was too dumb to +pub fn aspect_fill( + ui: &mut egui::Ui, + sense: Sense, + texture_id: egui::TextureId, + aspect_ratio: f32, +) -> egui::Response { + let frame = ui.available_rect_before_wrap(); // Get the available frame space in the current layout + let frame_ratio = frame.width() / frame.height(); + + let (width, height) = if frame_ratio > aspect_ratio { + // Frame is wider than the content + (frame.width(), frame.width() / aspect_ratio) + } else { + // Frame is taller than the content + (frame.height() * aspect_ratio, frame.height()) + }; + + let content_rect = Rect::from_min_size( + frame.min + + egui::vec2( + (frame.width() - width) / 2.0, + (frame.height() - height) / 2.0, + ), + egui::vec2(width, height), + ); + + // Set the clipping rectangle to the frame + //let clip_rect = ui.clip_rect(); // Preserve the original clipping rectangle + //ui.set_clip_rect(frame); + + let uv = Rect::from_min_max(pos2(0.0, 0.0), pos2(1.0, 1.0)); + + let (response, painter) = ui.allocate_painter(ui.available_size(), sense); + + // Draw the texture within the calculated rect, potentially clipping it + painter.rect_filled(content_rect, 0.0, ui.ctx().style().visuals.window_fill()); + painter.image(texture_id, content_rect, uv, Color32::WHITE); + + // Restore the original clipping rectangle + //ui.set_clip_rect(clip_rect); + response +} + pub fn round_image(image: &mut ColorImage) { #[cfg(feature = "profiling")] puffin::profile_function!();