mirror of
https://github.com/danbulant/cushy
synced 2026-06-16 04:51:17 +00:00
Image aspect scaling now requests sizes
This commit is contained in:
parent
c242009cb8
commit
02e90e48c6
2 changed files with 46 additions and 37 deletions
|
|
@ -88,6 +88,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
evaluation.
|
||||
- `Graphics::set_font_family` now clears the cached font family list, ensuring
|
||||
that the next call to apply_current_font_settings works correctly.
|
||||
- `Image` now returns the correct size from `layout()` when in aspect scaling
|
||||
modes. Previously, it reported back the minimum size, since it's scale was
|
||||
considered flexible. This new behavior ensures that it always requests a size
|
||||
that is scaled with the aspect ratio.
|
||||
|
||||
The rendering behavior remains unchanged, and the image will scale correctly
|
||||
within whatever bounds it is given.
|
||||
|
||||
### Changed
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
//! A widget that displays an image/texture.
|
||||
|
||||
use figures::units::UPx;
|
||||
use figures::{FloatConversion, IntoSigned, Point, Rect, Size, Zero};
|
||||
use figures::units::{Px, UPx};
|
||||
use figures::{FloatConversion, IntoSigned, IntoUnsigned, Point, Rect, Size, Zero};
|
||||
use kludgine::{AnyTexture, CollectedTexture, LazyTexture, SharedTexture, Texture, TextureRegion};
|
||||
|
||||
use crate::animation::ZeroToOne;
|
||||
|
|
@ -109,37 +109,44 @@ impl Image {
|
|||
Value::Dynamic(amount) => Value::Dynamic(amount.map_each_cloned(ImageScaling::Scale)),
|
||||
})
|
||||
}
|
||||
|
||||
fn calculate_image_rect(
|
||||
&self,
|
||||
texture: &AnyTexture,
|
||||
within_size: Size<UPx>,
|
||||
context: &mut crate::context::GraphicsContext<'_, '_, '_, '_>,
|
||||
) -> Rect<Px> {
|
||||
let within_size = within_size.into_signed();
|
||||
let size = texture.size().into_signed();
|
||||
match self.scaling.get_tracking_invalidate(context) {
|
||||
ImageScaling::Aspect { mode, orientation } => {
|
||||
let scale_width = within_size.width.into_float() / size.width.into_float();
|
||||
let scale_height = within_size.height.into_float() / size.height.into_float();
|
||||
|
||||
let effective_scale = match mode {
|
||||
Aspect::Fill => scale_width.max(scale_height),
|
||||
Aspect::Fit => scale_width.min(scale_height),
|
||||
};
|
||||
let scaled = size * effective_scale;
|
||||
|
||||
let x = (within_size.width - scaled.width) * *orientation.width;
|
||||
let y = (within_size.height - scaled.height) * *orientation.height;
|
||||
|
||||
Rect::new(Point::new(x, y), scaled)
|
||||
}
|
||||
ImageScaling::Stretch => within_size.into(),
|
||||
ImageScaling::Scale(factor) => {
|
||||
let size = size.map(|px| px * factor);
|
||||
size.into()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Widget for Image {
|
||||
fn redraw(&mut self, context: &mut crate::context::GraphicsContext<'_, '_, '_, '_>) {
|
||||
self.contents.map(|texture| {
|
||||
let size = texture.size().into_signed();
|
||||
let rect = match self.scaling.get() {
|
||||
ImageScaling::Aspect { mode, orientation } => {
|
||||
let scale_width =
|
||||
context.gfx.region().size.width.into_float() / size.width.into_float();
|
||||
let scale_height =
|
||||
context.gfx.region().size.height.into_float() / size.height.into_float();
|
||||
|
||||
let effective_scale = match mode {
|
||||
Aspect::Fill => scale_width.max(scale_height),
|
||||
Aspect::Fit => scale_width.min(scale_height),
|
||||
};
|
||||
let scaled = size * effective_scale;
|
||||
|
||||
let x = (context.gfx.region().size.width - scaled.width) * *orientation.width;
|
||||
let y =
|
||||
(context.gfx.region().size.height - scaled.height) * *orientation.height;
|
||||
|
||||
Rect::new(Point::new(x, y), scaled)
|
||||
}
|
||||
ImageScaling::Stretch => context.gfx.region().size.into(),
|
||||
ImageScaling::Scale(factor) => {
|
||||
let size = size.map(|px| px * factor);
|
||||
size.into()
|
||||
}
|
||||
};
|
||||
let rect = self.calculate_image_rect(texture, context.gfx.size(), context);
|
||||
context.gfx.draw_texture(texture, rect);
|
||||
});
|
||||
}
|
||||
|
|
@ -149,15 +156,10 @@ impl Widget for Image {
|
|||
available_space: Size<ConstraintLimit>,
|
||||
context: &mut LayoutContext<'_, '_, '_, '_>,
|
||||
) -> Size<UPx> {
|
||||
match self.scaling.get_tracking_invalidate(context) {
|
||||
ImageScaling::Aspect { .. } | ImageScaling::Stretch => {
|
||||
available_space.map(ConstraintLimit::min)
|
||||
}
|
||||
ImageScaling::Scale(factor) => self
|
||||
.contents
|
||||
.map_tracking_invalidate(context, AnyTexture::size)
|
||||
.map(|px| px * factor),
|
||||
}
|
||||
let rect = self.contents.map(|texture| {
|
||||
self.calculate_image_rect(texture, available_space.map(ConstraintLimit::max), context)
|
||||
});
|
||||
rect.size.into_unsigned()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue