mirror of
https://github.com/typst/typst
synced 2025-05-18 11:05:28 +08:00
Fix approximated size of reflow: true
transformations (#4462)
Co-authored-by: Laurenz <laurmaedje@gmail.com>
This commit is contained in:
parent
3ef0991fbb
commit
3aa18beacf
@ -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 |
Loading…
x
Reference in New Issue
Block a user