mirror of
https://github.com/danbulant/cushy
synced 2026-07-05 11:10:34 +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.
|
evaluation.
|
||||||
- `Graphics::set_font_family` now clears the cached font family list, ensuring
|
- `Graphics::set_font_family` now clears the cached font family list, ensuring
|
||||||
that the next call to apply_current_font_settings works correctly.
|
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
|
### Changed
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
//! A widget that displays an image/texture.
|
//! A widget that displays an image/texture.
|
||||||
|
|
||||||
use figures::units::UPx;
|
use figures::units::{Px, UPx};
|
||||||
use figures::{FloatConversion, IntoSigned, Point, Rect, Size, Zero};
|
use figures::{FloatConversion, IntoSigned, IntoUnsigned, Point, Rect, Size, Zero};
|
||||||
use kludgine::{AnyTexture, CollectedTexture, LazyTexture, SharedTexture, Texture, TextureRegion};
|
use kludgine::{AnyTexture, CollectedTexture, LazyTexture, SharedTexture, Texture, TextureRegion};
|
||||||
|
|
||||||
use crate::animation::ZeroToOne;
|
use crate::animation::ZeroToOne;
|
||||||
|
|
@ -109,37 +109,44 @@ impl Image {
|
||||||
Value::Dynamic(amount) => Value::Dynamic(amount.map_each_cloned(ImageScaling::Scale)),
|
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 {
|
impl Widget for Image {
|
||||||
fn redraw(&mut self, context: &mut crate::context::GraphicsContext<'_, '_, '_, '_>) {
|
fn redraw(&mut self, context: &mut crate::context::GraphicsContext<'_, '_, '_, '_>) {
|
||||||
self.contents.map(|texture| {
|
self.contents.map(|texture| {
|
||||||
let size = texture.size().into_signed();
|
let rect = self.calculate_image_rect(texture, context.gfx.size(), context);
|
||||||
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()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
context.gfx.draw_texture(texture, rect);
|
context.gfx.draw_texture(texture, rect);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -149,15 +156,10 @@ impl Widget for Image {
|
||||||
available_space: Size<ConstraintLimit>,
|
available_space: Size<ConstraintLimit>,
|
||||||
context: &mut LayoutContext<'_, '_, '_, '_>,
|
context: &mut LayoutContext<'_, '_, '_, '_>,
|
||||||
) -> Size<UPx> {
|
) -> Size<UPx> {
|
||||||
match self.scaling.get_tracking_invalidate(context) {
|
let rect = self.contents.map(|texture| {
|
||||||
ImageScaling::Aspect { .. } | ImageScaling::Stretch => {
|
self.calculate_image_rect(texture, available_space.map(ConstraintLimit::max), context)
|
||||||
available_space.map(ConstraintLimit::min)
|
});
|
||||||
}
|
rect.size.into_unsigned()
|
||||||
ImageScaling::Scale(factor) => self
|
|
||||||
.contents
|
|
||||||
.map_tracking_invalidate(context, AnyTexture::size)
|
|
||||||
.map(|px| px * factor),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue