Fix approximated size of reflow: true transformations (#4462)

Co-authored-by: Laurenz <laurmaedje@gmail.com>
This commit is contained in:
shinyfelix 2024-07-20 14:26:57 +02:00 committed by GitHub
parent 3ef0991fbb
commit 3aa18beacf
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 18 additions and 15 deletions

View File

@ -12,6 +12,7 @@ use crate::layout::{
Abs, Alignment, Angle, Axes, BlockElem, FixedAlignment, Frame, HAlignment, Length, Abs, Alignment, Angle, Axes, BlockElem, FixedAlignment, Frame, HAlignment, Length,
Point, Ratio, Region, Regions, Rel, Size, VAlignment, Point, Ratio, Region, Regions, Rel, Size, VAlignment,
}; };
use crate::utils::Numeric;
/// Moves content without affecting layout. /// Moves content without affecting layout.
/// ///
@ -153,12 +154,11 @@ fn layout_rotate(
let align = elem.origin(styles).resolve(styles); let align = elem.origin(styles).resolve(styles);
// Compute the new region's approximate size. // Compute the new region's approximate size.
let size = region let size = if region.size.is_finite() {
.size compute_bounding_box(region.size, Transform::rotate(-angle)).1
.to_point() } else {
.transform_inf(Transform::rotate(angle)) Size::splat(Abs::inf())
.map(Abs::abs) };
.to_size();
measure_and_layout( measure_and_layout(
engine, engine,
@ -248,7 +248,10 @@ fn layout_scale(
) -> SourceResult<Frame> { ) -> SourceResult<Frame> {
// Compute the new region's approximate size. // Compute the new region's approximate size.
let scale = elem.resolve_scale(engine, locator.relayout(), region.size, styles)?; let scale = elem.resolve_scale(engine, locator.relayout(), region.size, styles)?;
let size = region.size.zip_map(scale, |r, s| s.of(r)).map(Abs::abs); let size = region
.size
.zip_map(scale, |r, s| if r.is_finite() { Ratio::new(1.0 / s).of(r) } else { r })
.map(Abs::abs);
measure_and_layout( measure_and_layout(
engine, engine,
@ -489,7 +492,7 @@ fn measure_and_layout(
.pre_concat(Transform::translate(-x, -y)); .pre_concat(Transform::translate(-x, -y));
// Compute the bounding box and offset and wrap in a new frame. // Compute the bounding box and offset and wrap in a new frame.
let (offset, size) = compute_bounding_box(&frame, ts); let (offset, size) = compute_bounding_box(frame.size(), ts);
frame.transform(ts); frame.transform(ts);
frame.translate(offset); frame.translate(offset);
frame.set_size(size); frame.set_size(size);
@ -512,20 +515,20 @@ fn measure_and_layout(
} }
} }
/// Computes the bounding box and offset of a transformed frame. /// Computes the bounding box and offset of a transformed area.
fn compute_bounding_box(frame: &Frame, ts: Transform) -> (Point, Size) { fn compute_bounding_box(size: Size, ts: Transform) -> (Point, Size) {
let top_left = Point::zero().transform_inf(ts); let top_left = Point::zero().transform_inf(ts);
let top_right = Point::new(frame.width(), Abs::zero()).transform_inf(ts); let top_right = Point::with_x(size.x).transform_inf(ts);
let bottom_left = Point::new(Abs::zero(), frame.height()).transform_inf(ts); let bottom_left = Point::with_y(size.y).transform_inf(ts);
let bottom_right = Point::new(frame.width(), frame.height()).transform_inf(ts); let bottom_right = size.to_point().transform_inf(ts);
// We first compute the new bounding box of the rotated frame. // We first compute the new bounding box of the rotated area.
let min_x = top_left.x.min(top_right.x).min(bottom_left.x).min(bottom_right.x); let min_x = top_left.x.min(top_right.x).min(bottom_left.x).min(bottom_right.x);
let min_y = top_left.y.min(top_right.y).min(bottom_left.y).min(bottom_right.y); let min_y = top_left.y.min(top_right.y).min(bottom_left.y).min(bottom_right.y);
let max_x = top_left.x.max(top_right.x).max(bottom_left.x).max(bottom_right.x); let max_x = top_left.x.max(top_right.x).max(bottom_left.x).max(bottom_right.x);
let max_y = top_left.y.max(top_right.y).max(bottom_left.y).max(bottom_right.y); let max_y = top_left.y.max(top_right.y).max(bottom_left.y).max(bottom_right.y);
// Then we compute the new size of the frame. // Then we compute the new size of the area.
let width = max_x - min_x; let width = max_x - min_x;
let height = max_y - min_y; let height = max_y - min_y;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB