mirror of
https://github.com/typst/typst
synced 2025-05-20 03:55:29 +08:00
Refactor a bit
This commit is contained in:
parent
b69c0355ec
commit
61fdc85b13
@ -22,63 +22,61 @@ impl Layout for FixedNode {
|
|||||||
fn layout(
|
fn layout(
|
||||||
&self,
|
&self,
|
||||||
ctx: &mut LayoutContext,
|
ctx: &mut LayoutContext,
|
||||||
&Regions { current, base, expand, .. }: &Regions,
|
regions: &Regions,
|
||||||
) -> Vec<Constrained<Rc<Frame>>> {
|
) -> Vec<Constrained<Rc<Frame>>> {
|
||||||
// Fill in width or height if aspect ratio and the other is given.
|
// Fill in width or height if aspect ratio and the other is given.
|
||||||
let aspect = self.aspect.map(N64::into_inner);
|
let aspect = self.aspect.map(N64::into_inner);
|
||||||
let width = self.width.or(self.height.zip(aspect).map(|(h, a)| a * h));
|
let width = self.width.or(self.height.zip(aspect).map(|(h, a)| a * h));
|
||||||
let height = self.height.or(self.width.zip(aspect).map(|(w, a)| w / a));
|
let height = self.height.or(self.width.zip(aspect).map(|(w, a)| w / a));
|
||||||
|
|
||||||
// Prepare constraints.
|
|
||||||
let mut constraints = Constraints::new(expand);
|
|
||||||
constraints.set_base_if_linear(base, Spec::new(width, height));
|
|
||||||
|
|
||||||
// If the size for one axis isn't specified, the `current` size along
|
|
||||||
// that axis needs to remain the same for the result to be reusable.
|
|
||||||
if width.is_none() {
|
|
||||||
constraints.exact.x = Some(current.w);
|
|
||||||
}
|
|
||||||
|
|
||||||
if height.is_none() {
|
|
||||||
constraints.exact.y = Some(current.h);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Resolve the linears based on the current width and height.
|
// Resolve the linears based on the current width and height.
|
||||||
let mut size = Size::new(
|
let mut child_size = Size::new(
|
||||||
width.map_or(current.w, |w| w.resolve(base.w)),
|
width.map_or(regions.current.w, |w| w.resolve(regions.base.w)),
|
||||||
height.map_or(current.h, |h| h.resolve(base.h)),
|
height.map_or(regions.current.h, |h| h.resolve(regions.base.h)),
|
||||||
);
|
);
|
||||||
|
|
||||||
// If width or height aren't set for an axis, the base should be
|
// If width or height aren't set for an axis, the base should be
|
||||||
// inherited from the parent for that axis.
|
// inherited from the parent for that axis.
|
||||||
let base = Size::new(
|
let child_base = Size::new(
|
||||||
width.map_or(base.w, |_| size.w),
|
if width.is_some() { child_size.w } else { regions.base.w },
|
||||||
height.map_or(base.h, |_| size.h),
|
if height.is_some() { child_size.h } else { regions.base.h },
|
||||||
);
|
);
|
||||||
|
|
||||||
// Handle the aspect ratio.
|
// Prepare constraints.
|
||||||
|
let mut constraints = Constraints::new(regions.expand);
|
||||||
|
constraints.set_base_if_linear(regions.base, Spec::new(width, height));
|
||||||
|
|
||||||
|
// If the size for one axis isn't specified, the `current` size along
|
||||||
|
// that axis needs to remain the same for the result to be reusable.
|
||||||
|
if width.is_none() {
|
||||||
|
constraints.exact.x = Some(regions.current.w);
|
||||||
|
}
|
||||||
|
if height.is_none() {
|
||||||
|
constraints.exact.y = Some(regions.current.h);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply the aspect ratio.
|
||||||
if let Some(aspect) = aspect {
|
if let Some(aspect) = aspect {
|
||||||
constraints.exact = current.to_spec().map(Some);
|
let width = child_size.w.min(aspect * child_size.h);
|
||||||
|
child_size = Size::new(width, width / aspect);
|
||||||
|
constraints.exact = regions.current.to_spec().map(Some);
|
||||||
constraints.min = Spec::splat(None);
|
constraints.min = Spec::splat(None);
|
||||||
constraints.max = Spec::splat(None);
|
constraints.max = Spec::splat(None);
|
||||||
|
|
||||||
let width = size.w.min(aspect * size.h);
|
|
||||||
size = Size::new(width, width / aspect);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If width or height are fixed, the child should fill the available
|
// If width or height are fixed, the child should fill the available
|
||||||
// space along that axis.
|
// space along that axis.
|
||||||
let expand = Spec::new(width.is_some(), height.is_some());
|
let child_expand = Spec::new(width.is_some(), height.is_some());
|
||||||
|
|
||||||
// Layout the child.
|
// Layout the child.
|
||||||
let mut regions = Regions::one(size, base, expand);
|
let mut regions = Regions::one(child_size, child_base, child_expand);
|
||||||
let mut frames = self.child.layout(ctx, ®ions);
|
let mut frames = self.child.layout(ctx, ®ions);
|
||||||
|
|
||||||
// If we have an aspect ratio and the child is content-sized, we need to
|
// If we have an aspect ratio and the child is content-sized, we need to
|
||||||
// relayout with expansion.
|
// relayout with expansion.
|
||||||
if let Some(aspect) = aspect {
|
if let Some(aspect) = aspect {
|
||||||
if width.is_none() && height.is_none() {
|
if width.is_none() && height.is_none() {
|
||||||
let needed = frames[0].item.size.cap(size);
|
let needed = frames[0].item.size.cap(child_size);
|
||||||
let width = needed.w.max(aspect * needed.h);
|
let width = needed.w.max(aspect * needed.h);
|
||||||
regions.current = Size::new(width, width / aspect);
|
regions.current = Size::new(width, width / aspect);
|
||||||
regions.expand = Spec::splat(true);
|
regions.expand = Spec::splat(true);
|
||||||
@ -87,8 +85,8 @@ impl Layout for FixedNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Overwrite the child's constraints with ours.
|
// Overwrite the child's constraints with ours.
|
||||||
frames[0].constraints = constraints;
|
|
||||||
assert_eq!(frames.len(), 1);
|
assert_eq!(frames.len(), 1);
|
||||||
|
frames[0].constraints = constraints;
|
||||||
|
|
||||||
frames
|
frames
|
||||||
}
|
}
|
||||||
|
@ -17,28 +17,29 @@ impl Layout for ImageNode {
|
|||||||
fn layout(
|
fn layout(
|
||||||
&self,
|
&self,
|
||||||
ctx: &mut LayoutContext,
|
ctx: &mut LayoutContext,
|
||||||
&Regions { current, base, expand, .. }: &Regions,
|
regions: &Regions,
|
||||||
) -> Vec<Constrained<Rc<Frame>>> {
|
) -> Vec<Constrained<Rc<Frame>>> {
|
||||||
let mut constraints = Constraints::new(expand);
|
|
||||||
constraints.set_base_if_linear(base, Spec::new(self.width, self.height));
|
|
||||||
|
|
||||||
let width = self.width.map(|w| w.resolve(base.w));
|
|
||||||
let height = self.height.map(|w| w.resolve(base.h));
|
|
||||||
|
|
||||||
let img = ctx.images.get(self.id);
|
let img = ctx.images.get(self.id);
|
||||||
let pixel_size = Spec::new(img.width() as f64, img.height() as f64);
|
let pixel_size = Spec::new(img.width() as f64, img.height() as f64);
|
||||||
let pixel_ratio = pixel_size.x / pixel_size.y;
|
let pixel_ratio = pixel_size.x / pixel_size.y;
|
||||||
|
|
||||||
|
let mut constraints = Constraints::new(regions.expand);
|
||||||
|
constraints.set_base_if_linear(regions.base, Spec::new(self.width, self.height));
|
||||||
|
|
||||||
|
let width = self.width.map(|w| w.resolve(regions.base.w));
|
||||||
|
let height = self.height.map(|w| w.resolve(regions.base.h));
|
||||||
|
|
||||||
let size = match (width, height) {
|
let size = match (width, height) {
|
||||||
(Some(width), Some(height)) => Size::new(width, height),
|
(Some(width), Some(height)) => Size::new(width, height),
|
||||||
(Some(width), None) => Size::new(width, width / pixel_ratio),
|
(Some(width), None) => Size::new(width, width / pixel_ratio),
|
||||||
(None, Some(height)) => Size::new(height * pixel_ratio, height),
|
(None, Some(height)) => Size::new(height * pixel_ratio, height),
|
||||||
(None, None) => {
|
(None, None) => {
|
||||||
constraints.exact.x = Some(current.w);
|
constraints.exact.x = Some(regions.current.w);
|
||||||
if current.w.is_finite() {
|
if regions.current.w.is_finite() {
|
||||||
Size::new(current.w, current.w / pixel_ratio)
|
// Fit to width.
|
||||||
|
Size::new(regions.current.w, regions.current.w / pixel_ratio)
|
||||||
} else {
|
} else {
|
||||||
// Totally unbounded region, we have to make up something,
|
// Unbounded width, we have to make up something,
|
||||||
// so it is 1pt per pixel.
|
// so it is 1pt per pixel.
|
||||||
pixel_size.map(Length::pt).to_size()
|
pixel_size.map(Length::pt).to_size()
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,7 @@ impl Layout for PadNode {
|
|||||||
ctx: &mut LayoutContext,
|
ctx: &mut LayoutContext,
|
||||||
regions: &Regions,
|
regions: &Regions,
|
||||||
) -> Vec<Constrained<Rc<Frame>>> {
|
) -> Vec<Constrained<Rc<Frame>>> {
|
||||||
|
// Layout child into padded regions.
|
||||||
let mut frames = self.child.layout(
|
let mut frames = self.child.layout(
|
||||||
ctx,
|
ctx,
|
||||||
®ions.map(|size| size - self.padding.resolve(size).size()),
|
®ions.map(|size| size - self.padding.resolve(size).size()),
|
||||||
@ -38,6 +39,12 @@ impl Layout for PadNode {
|
|||||||
let padding = self.padding.resolve(padded);
|
let padding = self.padding.resolve(padded);
|
||||||
let origin = Point::new(padding.left, padding.top);
|
let origin = Point::new(padding.left, padding.top);
|
||||||
|
|
||||||
|
// Create a new larger frame and place the child's frame inside it.
|
||||||
|
let empty = Frame::new(padded, frame.baseline + origin.y);
|
||||||
|
let prev = std::mem::replace(frame, Rc::new(empty));
|
||||||
|
let new = Rc::make_mut(frame);
|
||||||
|
new.push_frame(origin, prev);
|
||||||
|
|
||||||
// Inflate min and max contraints by the padding.
|
// Inflate min and max contraints by the padding.
|
||||||
for spec in [&mut constraints.min, &mut constraints.max] {
|
for spec in [&mut constraints.min, &mut constraints.max] {
|
||||||
if let Some(x) = spec.x.as_mut() {
|
if let Some(x) = spec.x.as_mut() {
|
||||||
@ -62,12 +69,6 @@ impl Layout for PadNode {
|
|||||||
if self.padding.top.is_relative() || self.padding.bottom.is_relative() {
|
if self.padding.top.is_relative() || self.padding.bottom.is_relative() {
|
||||||
constraints.base.y = Some(base.h);
|
constraints.base.y = Some(base.h);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new larger frame and place the child's frame inside it.
|
|
||||||
let empty = Frame::new(padded, frame.baseline + origin.y);
|
|
||||||
let prev = std::mem::replace(frame, Rc::new(empty));
|
|
||||||
let new = Rc::make_mut(frame);
|
|
||||||
new.push_frame(origin, prev);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
frames
|
frames
|
||||||
|
Loading…
x
Reference in New Issue
Block a user