Skip to content

Commit

Permalink
Catch edge cases were the image widget would request inf sized layout
Browse files Browse the repository at this point in the history
  • Loading branch information
fishrockz committed Jan 12, 2023
1 parent bd96450 commit e69fa2a
Showing 1 changed file with 35 additions and 8 deletions.
43 changes: 35 additions & 8 deletions druid/src/widget/image.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,12 +197,34 @@ impl<T: Data> Widget<T> for Image {
) -> Size {
bc.debug_check("Image");

// If either the width or height is constrained calculate a value so that the image fits
// in the size exactly. If it is unconstrained by both width and height then use the fill
// strategy to determine the size.
// Let the fill strat determine the size of the widget as a function of the bc.max()
// and the original image size. But catch cases were they would return INFINITY
// and try to make a sensible area as a function of the fill strat.
let max = bc.max();
let image_size = self.image_size();
let affine = self.fill.affine_to_fill(max, image_size).as_coeffs();
let mut max_width = bc.max().width;
let mut max_height = bc.max().height;
let mut fill_strat = self.fill;
if max_width == f64::INFINITY && max_height == f64::INFINITY {
// If we are in a scroll box for width and height then fall back to
// original image size
max_height = image_size.height;
max_width = image_size.width;
} else if max_width == f64::INFINITY || max_height == f64::INFINITY {
// If we are in a scroll box for width or heigh but not both
// then give self.fill a box the size of the scroll box and let it decide how to
// fill it. Unless that would result in requesting INFINITY in which case fall back
// to contain.
fill_strat = match fill_strat {
FillStrat::FitWidth if max_width == f64::INFINITY => FillStrat::Contain,
FillStrat::FitHeight if max_height == f64::INFINITY => FillStrat::Contain,
FillStrat::Cover | FillStrat::Fill => FillStrat::Contain,
_ => fill_strat,
}
}
let affine = fill_strat
.affine_to_fill(Size::new(max_width, max_height), image_size)
.as_coeffs();
// The first and forth elements of the affine are the x and y scale factor.
// So just multiply them by the original size to get the ideal area based on `self.fill`.
let mut width = affine[0] * image_size.width;
Expand All @@ -211,6 +233,7 @@ impl<T: Data> Widget<T> for Image {
// would be over scaled to keep AR fixed then we just clip back to the `bc.max()`
width = width.min(max.width);
height = height.min(max.height);

let size = Size::new(width, height);
trace!("Computed size: {}", size);
size
Expand Down Expand Up @@ -437,8 +460,10 @@ mod tests {
2,
);

let image_widget =
Scroll::new(Container::new(Image::new(image_data).fill_mode(FillStrat::Fill)).with_id(id_1)).vertical();
let image_widget = Scroll::new(
Container::new(Image::new(image_data).fill_mode(FillStrat::Fill)).with_id(id_1),
)
.vertical();

Harness::create_simple(true, image_widget, |harness| {
harness.send_initial_events();
Expand All @@ -465,8 +490,10 @@ mod tests {
2,
);

let image_widget =
Scroll::new(Container::new(Image::new(image_data).fill_mode(FillStrat::Fill)).with_id(id_1)).horizontal();
let image_widget = Scroll::new(
Container::new(Image::new(image_data).fill_mode(FillStrat::Fill)).with_id(id_1),
)
.horizontal();

Harness::create_simple(true, image_widget, |harness| {
harness.send_initial_events();
Expand Down

0 comments on commit e69fa2a

Please sign in to comment.