Remove base width

This commit is contained in:
Laurenz 2023-02-12 16:56:51 +01:00
parent 697ae1f925
commit f4856c18b9
14 changed files with 130 additions and 143 deletions

View File

@ -83,16 +83,16 @@ impl Layout for ColumnsNode {
) -> SourceResult<Fragment> {
// Separating the infinite space into infinite columns does not make
// much sense.
if !regions.first.x.is_finite() {
if !regions.size.x.is_finite() {
return self.body.layout(vt, styles, regions);
}
// Determine the width of the gutter and each column.
let columns = self.count.get();
let gutter = styles.get(Self::GUTTER).relative_to(regions.base.x);
let width = (regions.first.x - gutter * (columns - 1) as f64) / columns as f64;
let gutter = styles.get(Self::GUTTER).relative_to(regions.base().x);
let width = (regions.size.x - gutter * (columns - 1) as f64) / columns as f64;
let backlog: Vec<_> = std::iter::once(&regions.first.y)
let backlog: Vec<_> = std::iter::once(&regions.size.y)
.chain(regions.backlog)
.flat_map(|&height| std::iter::repeat(height).take(columns))
.skip(1)
@ -100,8 +100,8 @@ impl Layout for ColumnsNode {
// Create the pod regions.
let pod = Regions {
first: Size::new(width, regions.first.y),
base: Size::new(width, regions.base.y),
size: Size::new(width, regions.size.y),
full: regions.full,
backlog: &backlog,
last: regions.last,
expand: Axes::new(true, regions.expand.y),
@ -121,7 +121,7 @@ impl Layout for ColumnsNode {
// case, the frame is first created with zero height and then
// resized.
let height = if regions.expand.y { region.y } else { Abs::zero() };
let mut output = Frame::new(Size::new(regions.first.x, height));
let mut output = Frame::new(Size::new(regions.size.x, height));
let mut cursor = Abs::zero();
for _ in 0..columns {
@ -134,7 +134,7 @@ impl Layout for ColumnsNode {
let x = if dir == Dir::LTR {
cursor
} else {
regions.first.x - cursor - width
regions.size.x - cursor - width
};
output.push_frame(Point::with_x(x), frame);

View File

@ -77,24 +77,22 @@ impl Layout for BoxNode {
let size = self
.sizing
.resolve(styles)
.zip(regions.base)
.zip(regions.base())
.map(|(s, b)| s.map(|v| v.relative_to(b)))
.unwrap_or(regions.first);
.unwrap_or(regions.size);
// Select the appropriate base and expansion for the child depending
// on whether it is automatically or relatively sized.
let is_auto = self.sizing.as_ref().map(Option::is_none);
let base = is_auto.select(regions.base, size);
let expand = regions.expand | !is_auto;
Regions::one(size, base, expand)
Regions::one(size, expand)
};
// Layout the child.
let mut frame = self.body.layout(vt, styles, pod)?.into_frame();
// Ensure frame size matches regions size if expansion is on.
let target = regions.expand.select(regions.first, frame.size());
let target = regions.expand.select(regions.size, frame.size());
frame.resize(target, Align::LEFT_TOP);
Ok(Fragment::frame(frame))

View File

@ -85,7 +85,7 @@ impl<'a> FlowLayouter<'a> {
/// Create a new flow layouter.
fn new(mut regions: Regions<'a>) -> Self {
let expand = regions.expand;
let full = regions.first;
let full = regions.size;
// Disable vertical expansion for children.
regions.expand.y = false;
@ -122,14 +122,7 @@ impl<'a> FlowLayouter<'a> {
let leading = styles.get(ParNode::LEADING);
let consecutive = self.last_was_par;
let frames = par
.layout(
vt,
styles,
consecutive,
self.regions.first.x,
self.regions.base,
self.regions.expand.x,
)?
.layout(vt, styles, consecutive, self.regions.base(), self.regions.expand.x)?
.into_frames();
let mut sticky = self.items.len();
@ -142,7 +135,7 @@ impl<'a> FlowLayouter<'a> {
}
if let [first, ..] = frames.as_slice() {
if !self.regions.first.y.fits(first.height()) && !self.regions.in_last() {
if !self.regions.size.y.fits(first.height()) && !self.regions.in_last() {
let carry: Vec<_> = self.items.drain(sticky..).collect();
self.finish_region();
for item in carry {
@ -199,15 +192,15 @@ impl<'a> FlowLayouter<'a> {
/// Layout a finished frame.
fn layout_item(&mut self, item: FlowItem) {
match item {
FlowItem::Absolute(v, _) => self.regions.first.y -= v,
FlowItem::Absolute(v, _) => self.regions.size.y -= v,
FlowItem::Fractional(_) => {}
FlowItem::Frame(ref frame, ..) => {
let size = frame.size();
if !self.regions.first.y.fits(size.y) && !self.regions.in_last() {
if !self.regions.size.y.fits(size.y) && !self.regions.in_last() {
self.finish_region();
}
self.regions.first.y -= size.y;
self.regions.size.y -= size.y;
}
FlowItem::Placed(_) => {}
}
@ -284,7 +277,7 @@ impl<'a> FlowLayouter<'a> {
// Advance to the next region.
self.finished.push(output);
self.regions.next();
self.full = self.regions.first;
self.full = self.regions.size;
}
/// Finish layouting and return the resulting fragment.

View File

@ -235,8 +235,6 @@ struct GridLayouter<'a, 'v> {
rcols: Vec<Abs>,
/// Rows in the current region.
lrows: Vec<Row>,
/// The full height of the current region.
full: Abs,
/// The used-up size of the current region. The horizontal size is
/// determined once after columns are resolved and not touched again.
used: Size,
@ -317,7 +315,6 @@ impl<'a, 'v> GridLayouter<'a, 'v> {
cols.reverse();
}
let full = regions.first.y;
let rcols = vec![Abs::zero(); cols.len()];
let lrows = vec![];
@ -337,7 +334,6 @@ impl<'a, 'v> GridLayouter<'a, 'v> {
styles,
rcols,
lrows,
full,
used: Size::zero(),
fr: Fr::zero(),
finished: vec![],
@ -384,7 +380,7 @@ impl<'a, 'v> GridLayouter<'a, 'v> {
TrackSizing::Auto => {}
TrackSizing::Relative(v) => {
let resolved =
v.resolve(self.styles).relative_to(self.regions.base.x);
v.resolve(self.styles).relative_to(self.regions.base().x);
*rcol = resolved;
rel += resolved;
}
@ -393,7 +389,7 @@ impl<'a, 'v> GridLayouter<'a, 'v> {
}
// Size that is not used by fixed-size columns.
let available = self.regions.first.x - rel;
let available = self.regions.size.x - rel;
if available >= Abs::zero() {
// Determine size of auto columns.
let (auto, count) = self.measure_auto_columns(available)?;
@ -429,16 +425,17 @@ impl<'a, 'v> GridLayouter<'a, 'v> {
let mut resolved = Abs::zero();
for y in 0..self.rows.len() {
if let Some(cell) = self.cell(x, y) {
let size = Size::new(available, self.regions.base.y);
let mut pod = Regions::one(size, size, Axes::splat(false));
// For relative rows, we can already resolve the correct
// base and for auto and fr we could only guess anyway.
if let TrackSizing::Relative(v) = self.rows[y] {
pod.base.y =
v.resolve(self.styles).relative_to(self.regions.base.y);
}
let height = match self.rows[y] {
TrackSizing::Relative(v) => {
v.resolve(self.styles).relative_to(self.regions.base().y)
}
_ => self.regions.base().y,
};
let size = Size::new(available, height);
let pod = Regions::one(size, Axes::splat(false));
let frame = cell.layout(self.vt, self.styles, pod)?.into_frame();
resolved.set_max(frame.width());
}
@ -508,8 +505,7 @@ impl<'a, 'v> GridLayouter<'a, 'v> {
for (x, &rcol) in self.rcols.iter().enumerate() {
if let Some(cell) = self.cell(x, y) {
let mut pod = self.regions;
pod.first.x = rcol;
pod.base.x = rcol;
pod.size.x = rcol;
let frames = cell.layout(self.vt, self.styles, pod)?.into_frames();
if let [first, rest @ ..] = frames.as_slice() {
@ -573,12 +569,12 @@ impl<'a, 'v> GridLayouter<'a, 'v> {
/// Layout a row with relative height. Such a row cannot break across
/// multiple regions, but it may force a region break.
fn layout_relative_row(&mut self, v: Rel<Length>, y: usize) -> SourceResult<()> {
let resolved = v.resolve(self.styles).relative_to(self.regions.base.y);
let resolved = v.resolve(self.styles).relative_to(self.regions.base().y);
let frame = self.layout_single_row(resolved, y)?;
// Skip to fitting region.
let height = frame.height();
while !self.regions.first.y.fits(height) && !self.regions.in_last() {
while !self.regions.size.y.fits(height) && !self.regions.in_last() {
self.finish_region()?;
// Don't skip multiple regions for gutter and don't push a row.
@ -600,14 +596,10 @@ impl<'a, 'v> GridLayouter<'a, 'v> {
for (x, &rcol) in self.rcols.iter().enumerate() {
if let Some(cell) = self.cell(x, y) {
let size = Size::new(rcol, height);
let base = Size::new(
rcol,
match self.rows[y] {
TrackSizing::Auto => self.regions.base.y,
_ => height,
},
);
let pod = Regions::one(size, base, Axes::splat(true));
let mut pod = Regions::one(size, Axes::splat(true));
if self.rows[y] == TrackSizing::Auto {
pod.full = self.regions.full;
}
let frame = cell.layout(self.vt, self.styles, pod)?.into_frame();
output.push_frame(pos, frame);
}
@ -628,15 +620,15 @@ impl<'a, 'v> GridLayouter<'a, 'v> {
// Prepare regions.
let size = Size::new(self.used.x, heights[0]);
let mut pod = Regions::one(size, self.regions.base, Axes::splat(true));
let mut pod = Regions::one(size, Axes::splat(true));
pod.full = self.regions.full;
pod.backlog = &heights[1..];
// Layout the row.
let mut pos = Point::zero();
for (x, &rcol) in self.rcols.iter().enumerate() {
if let Some(cell) = self.cell(x, y) {
pod.first.x = rcol;
pod.base.x = rcol;
pod.size.x = rcol;
// Push the layouted frames into the individual output frames.
let fragment = cell.layout(self.vt, self.styles, pod)?;
@ -653,7 +645,7 @@ impl<'a, 'v> GridLayouter<'a, 'v> {
/// Push a row frame into the current region.
fn push_row(&mut self, frame: Frame) {
self.regions.first.y -= frame.height();
self.regions.size.y -= frame.height();
self.used.y += frame.height();
self.lrows.push(Row::Frame(frame));
}
@ -663,8 +655,8 @@ impl<'a, 'v> GridLayouter<'a, 'v> {
// Determine the size of the grid in this region, expanding fully if
// there are fr rows.
let mut size = self.used;
if self.fr.get() > 0.0 && self.full.is_finite() {
size.y = self.full;
if self.fr.get() > 0.0 && self.regions.full.is_finite() {
size.y = self.regions.full;
}
// The frame for the region.
@ -676,7 +668,7 @@ impl<'a, 'v> GridLayouter<'a, 'v> {
let frame = match row {
Row::Frame(frame) => frame,
Row::Fr(v, y) => {
let remaining = self.full - self.used.y;
let remaining = self.regions.full - self.used.y;
let height = v.share(self.fr, remaining);
self.layout_single_row(height, y)?
}
@ -689,7 +681,6 @@ impl<'a, 'v> GridLayouter<'a, 'v> {
self.finished.push(output);
self.regions.next();
self.full = self.regions.first.y;
self.used.y = Abs::zero();
self.fr = Fr::zero();

View File

@ -293,7 +293,7 @@ impl PageNode {
}
// Layout the child.
let regions = Regions::repeat(size, size, size.map(Abs::is_finite));
let regions = Regions::repeat(size, size.map(Abs::is_finite));
let mut fragment = child.layout(vt, styles, regions)?;
let header = styles.get(Self::HEADER);
@ -316,7 +316,7 @@ impl PageNode {
let in_background = std::ptr::eq(marginal, background);
let Some(marginal) = marginal else { continue };
let content = marginal.resolve(vt, page)?;
let pod = Regions::one(area, area, Axes::splat(true));
let pod = Regions::one(area, Axes::splat(true));
let sub = content.layout(vt, styles, pod)?.into_frame();
if in_background {
frame.prepend_frame(pos, sub);

View File

@ -120,8 +120,7 @@ impl ParNode {
vt: &mut Vt,
styles: StyleChain,
consecutive: bool,
width: Abs,
base: Size,
region: Size,
expand: bool,
) -> SourceResult<Fragment> {
#[comemo::memoize]
@ -132,8 +131,7 @@ impl ParNode {
introspector: Tracked<Introspector>,
styles: StyleChain,
consecutive: bool,
width: Abs,
base: Size,
region: Size,
expand: bool,
) -> SourceResult<Fragment> {
let mut vt = Vt { world, provider, introspector };
@ -144,13 +142,13 @@ impl ParNode {
// Perform BiDi analysis and then prepare paragraph layout by building a
// representation on which we can do line breaking without layouting
// each and every line from scratch.
let p = prepare(&mut vt, par, &text, segments, styles, width, base)?;
let p = prepare(&mut vt, par, &text, segments, styles, region)?;
// Break the paragraph into lines.
let lines = linebreak(&vt, &p, width);
let lines = linebreak(&vt, &p, region.x);
// Stack the lines into one frame per region.
finalize(&mut vt, &p, &lines, width, base, expand)
finalize(&mut vt, &p, &lines, region, expand)
}
cached(
@ -160,8 +158,7 @@ impl ParNode {
vt.introspector,
styles,
consecutive,
width,
base,
region,
expand,
)
}
@ -595,8 +592,7 @@ fn prepare<'a>(
text: &'a str,
segments: Vec<(Segment<'a>, StyleChain<'a>)>,
styles: StyleChain<'a>,
width: Abs,
base: Size,
region: Size,
) -> SourceResult<Preparation<'a>> {
let bidi = BidiInfo::new(
text,
@ -619,7 +615,7 @@ fn prepare<'a>(
}
Segment::Spacing(spacing) => match spacing {
Spacing::Relative(v) => {
let resolved = v.resolve(styles).relative_to(base.x);
let resolved = v.resolve(styles).relative_to(region.x);
items.push(Item::Absolute(resolved));
}
Spacing::Fractional(v) => {
@ -630,8 +626,7 @@ fn prepare<'a>(
if let Some(repeat) = inline.to::<RepeatNode>() {
items.push(Item::Repeat(repeat, styles));
} else {
let size = Size::new(width, base.y);
let pod = Regions::one(size, base, Axes::splat(false));
let pod = Regions::one(region, Axes::splat(false));
let mut frame = inline.layout(vt, styles, pod)?.into_frame();
frame.translate(Point::with_y(styles.get(TextNode::BASELINE)));
items.push(Item::Frame(frame));
@ -1116,20 +1111,20 @@ fn finalize(
vt: &mut Vt,
p: &Preparation,
lines: &[Line],
mut width: Abs,
base: Size,
mut region: Size,
expand: bool,
) -> SourceResult<Fragment> {
// Determine the paragraph's width: Full width of the region if we
// should expand or there's fractional spacing, fit-to-width otherwise.
if !width.is_finite() || (!expand && lines.iter().all(|line| line.fr().is_zero())) {
width = lines.iter().map(|line| line.width).max().unwrap_or_default();
if !region.x.is_finite() || (!expand && lines.iter().all(|line| line.fr().is_zero()))
{
region.x = lines.iter().map(|line| line.width).max().unwrap_or_default();
}
// Stack the lines into one frame per region.
let mut frames: Vec<Frame> = lines
.iter()
.map(|line| commit(vt, p, line, base, width))
.map(|line| commit(vt, p, line, region))
.collect::<SourceResult<_>>()?;
// Prevent orphans.
@ -1164,10 +1159,9 @@ fn commit(
vt: &mut Vt,
p: &Preparation,
line: &Line,
base: Size,
width: Abs,
region: Size,
) -> SourceResult<Frame> {
let mut remaining = width - line.width;
let mut remaining = region.x - line.width;
let mut offset = Abs::zero();
// Reorder the line from logical to visual order.
@ -1242,8 +1236,8 @@ fn commit(
Item::Repeat(repeat, styles) => {
let before = offset;
let fill = Fr::one().share(fr, remaining);
let size = Size::new(fill, base.y);
let pod = Regions::one(size, base, Axes::new(false, false));
let size = Size::new(fill, region.y);
let pod = Regions::one(size, Axes::new(false, false));
let frame = repeat.layout(vt, *styles, pod)?.into_frame();
let width = frame.width();
let count = (fill / width).floor();
@ -1268,7 +1262,7 @@ fn commit(
remaining = Abs::zero();
}
let size = Size::new(width, top + bottom);
let size = Size::new(region.x, top + bottom);
let mut output = Frame::new(size);
output.set_baseline(top);

View File

@ -92,16 +92,16 @@ impl Layout for PlaceNode {
// The pod is the base area of the region because for absolute
// placement we don't really care about the already used area.
let pod = {
let finite = regions.base.map(Abs::is_finite);
let finite = regions.base().map(Abs::is_finite);
let expand = finite & (regions.expand | out_of_flow);
Regions::one(regions.base, regions.base, expand)
Regions::one(regions.base(), expand)
};
let mut frame = self.0.layout(vt, styles, pod)?.into_frame();
// If expansion is off, zero all sizes so that we don't take up any
// space in our parent. Otherwise, respect the expand settings.
let target = regions.expand.select(regions.first, Size::zero());
let target = regions.expand.select(regions.size, Size::zero());
frame.resize(target, Align::LEFT_TOP);
Ok(Fragment::frame(frame))

View File

@ -5,10 +5,10 @@ use typst::geom::{Abs, Axes, Size};
/// A sequence of regions to layout into.
#[derive(Copy, Clone, Hash)]
pub struct Regions<'a> {
/// The (remaining) size of the first region.
pub first: Size,
/// The base size for relative sizing.
pub base: Size,
/// The remaining size of the first region.
pub size: Size,
/// The full height of the region for relative sizing.
pub full: Abs,
/// The height of followup regions. The width is the same for all regions.
pub backlog: &'a [Abs],
/// The height of the final region that is repeated once the backlog is
@ -19,12 +19,12 @@ pub struct Regions<'a> {
pub expand: Axes<bool>,
}
impl<'a> Regions<'a> {
impl Regions<'_> {
/// Create a new region sequence with exactly one region.
pub fn one(size: Size, base: Size, expand: Axes<bool>) -> Self {
pub fn one(size: Size, expand: Axes<bool>) -> Self {
Self {
first: size,
base,
size,
full: size.y,
backlog: &[],
last: None,
expand,
@ -32,16 +32,24 @@ impl<'a> Regions<'a> {
}
/// Create a new sequence of same-size regions that repeats indefinitely.
pub fn repeat(size: Size, base: Size, expand: Axes<bool>) -> Self {
pub fn repeat(size: Size, expand: Axes<bool>) -> Self {
Self {
first: size,
base,
size,
full: size.y,
backlog: &[],
last: Some(size.y),
expand,
}
}
/// The base size, which doesn't take into account that the regions is
/// already partially used up.
///
/// This is also used for relative sizing.
pub fn base(&self) -> Size {
Size::new(self.size.x, self.full)
}
/// Create new regions where all sizes are mapped with `f`.
///
/// Note that since all regions must have the same width, the width returned
@ -50,12 +58,12 @@ impl<'a> Regions<'a> {
where
F: FnMut(Size) -> Size,
{
let x = self.first.x;
let x = self.size.x;
backlog.clear();
backlog.extend(self.backlog.iter().map(|&y| f(Size::new(x, y)).y));
Regions {
first: f(self.first),
base: f(self.base),
size: f(self.size),
full: f(Size::new(x, self.full)).y,
backlog,
last: self.last.map(|y| f(Size::new(x, y)).y),
expand: self.expand,
@ -64,14 +72,14 @@ impl<'a> Regions<'a> {
/// Whether the first region is full and a region break is called for.
pub fn is_full(&self) -> bool {
Abs::zero().fits(self.first.y) && !self.in_last()
Abs::zero().fits(self.size.y) && !self.in_last()
}
/// Whether the first region is the last usable region.
///
/// If this is true, calling `next()` will have no effect.
pub fn in_last(&self) -> bool {
self.backlog.is_empty() && self.last.map_or(true, |height| self.first.y == height)
self.backlog.is_empty() && self.last.map_or(true, |height| self.size.y == height)
}
/// Advance to the next region if there is any.
@ -85,8 +93,8 @@ impl<'a> Regions<'a> {
})
.or(self.last)
{
self.first.y = height;
self.base.y = height;
self.size.y = height;
self.full = height;
}
}
@ -95,10 +103,10 @@ impl<'a> Regions<'a> {
/// [`next()`](Self::next) repeatedly until all regions are exhausted.
/// This iterator may be infinite.
pub fn iter(&self) -> impl Iterator<Item = Size> + '_ {
let first = std::iter::once(self.first);
let first = std::iter::once(self.size);
let backlog = self.backlog.iter();
let last = self.last.iter().cycle();
first.chain(backlog.chain(last).map(|&h| Size::new(self.first.x, h)))
first.chain(backlog.chain(last).map(|&h| Size::new(self.size.x, h)))
}
}
@ -106,15 +114,15 @@ impl Debug for Regions<'_> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.write_str("Regions ")?;
let mut list = f.debug_list();
let mut prev = self.first.y;
list.entry(&self.first);
let mut prev = self.size.y;
list.entry(&self.size);
for &height in self.backlog {
list.entry(&Size::new(self.first.x, height));
list.entry(&Size::new(self.size.x, height));
prev = height;
}
if let Some(last) = self.last {
if last != prev {
list.entry(&Size::new(self.first.x, last));
list.entry(&Size::new(self.size.x, last));
}
list.entry(&(..));
}

View File

@ -177,7 +177,7 @@ impl<'a> StackLayouter<'a> {
fn new(dir: Dir, regions: Regions<'a>, styles: StyleChain<'a>) -> Self {
let axis = dir.axis();
let expand = regions.expand;
let full = regions.first;
let full = regions.size;
// Disable expansion along the block axis for children.
let mut regions = regions.clone();
@ -202,11 +202,14 @@ impl<'a> StackLayouter<'a> {
match spacing {
Spacing::Relative(v) => {
// Resolve the spacing and limit it to the remaining space.
let resolved =
v.resolve(self.styles).relative_to(self.regions.base.get(self.axis));
let remaining = self.regions.first.get_mut(self.axis);
let resolved = v
.resolve(self.styles)
.relative_to(self.regions.base().get(self.axis));
let remaining = self.regions.size.get_mut(self.axis);
let limited = resolved.min(*remaining);
*remaining -= limited;
if self.dir.axis() == Axis::Y {
*remaining -= limited;
}
self.used.main += limited;
self.items.push(StackItem::Absolute(resolved));
}
@ -242,14 +245,18 @@ impl<'a> StackLayouter<'a> {
for (i, frame) in fragment.into_iter().enumerate() {
// Grow our size, shrink the region and save the frame for later.
let size = frame.size();
let size = match self.axis {
if self.dir.axis() == Axis::Y {
self.regions.size.y -= size.y;
}
let gen = match self.axis {
Axis::X => Gen::new(size.y, size.x),
Axis::Y => Gen::new(size.x, size.y),
};
self.used.main += size.main;
self.used.cross.set_max(size.cross);
*self.regions.first.get_mut(self.axis) -= size.main;
self.used.main += gen.main;
self.used.cross.set_max(gen.cross);
self.items.push(StackItem::Frame(frame, align));
if i + 1 < len {
@ -310,7 +317,7 @@ impl<'a> StackLayouter<'a> {
// Advance to the next region.
self.regions.next();
self.full = self.regions.first;
self.full = self.regions.size;
self.used = Gen::zero();
self.fr = Fr::zero();
self.finished.push(output);

View File

@ -78,7 +78,7 @@ impl Layout for MoveNode {
let mut fragment = self.body.layout(vt, styles, regions)?;
for frame in &mut fragment {
let delta = self.delta.resolve(styles);
let delta = delta.zip(regions.base).map(|(d, s)| d.relative_to(s));
let delta = delta.zip(regions.base()).map(|(d, s)| d.relative_to(s));
frame.translate(delta.to_point());
}
Ok(fragment)

View File

@ -25,7 +25,7 @@ macro_rules! percent {
/// The context for math layout.
pub struct MathContext<'a, 'b, 'v> {
pub vt: &'v mut Vt<'b>,
pub regions: Regions<'a>,
pub regions: Regions<'static>,
pub font: &'a Font,
pub ttf: &'a ttf_parser::Face<'a>,
pub table: ttf_parser::math::Table<'a>,
@ -60,10 +60,7 @@ impl<'a, 'b, 'v> MathContext<'a, 'b, 'v> {
let variant = variant(styles);
Self {
vt,
regions: {
let size = Size::new(regions.first.x, regions.base.y);
Regions::one(size, regions.base, Axes::splat(false))
},
regions: Regions::one(regions.base(), Axes::splat(false)),
font: &font,
ttf: font.ttf(),
table,

View File

@ -76,7 +76,7 @@ impl Layout for ImageNode {
let px_ratio = pxw / pxh;
// Find out whether the image is wider or taller than the target size.
let Regions { first, expand, .. } = regions;
let Regions { size: first, expand, .. } = regions;
let region_ratio = first.x / first.y;
let wide = px_ratio > region_ratio;

View File

@ -87,17 +87,17 @@ impl Layout for LineNode {
let origin = self
.start
.resolve(styles)
.zip(regions.base)
.zip(regions.base())
.map(|(l, b)| l.relative_to(b));
let delta = self
.delta
.resolve(styles)
.zip(regions.base)
.zip(regions.base())
.map(|(l, b)| l.relative_to(b));
let size = origin.max(origin + delta).max(Size::zero());
let target = regions.expand.select(regions.first, size);
let target = regions.expand.select(regions.size, size);
let mut frame = Frame::new(target);
let shape = Geometry::Line(delta.to_point()).stroked(stroke);

View File

@ -555,41 +555,40 @@ fn layout(
// Pad the child.
let child = child.clone().padded(inset.map(|side| side.map(Length::from)));
let pod = Regions::one(regions.first, regions.base, regions.expand);
let pod = Regions::one(regions.size, regions.expand);
frame = child.layout(vt, styles, pod)?.into_frame();
// Relayout with full expansion into square region to make sure
// the result is really a square or circle.
if kind.is_quadratic() {
let length = if regions.expand.x || regions.expand.y {
let target = regions.expand.select(regions.first, Size::zero());
let target = regions.expand.select(regions.size, Size::zero());
target.x.max(target.y)
} else {
let size = frame.size();
let desired = size.x.max(size.y);
desired.min(regions.first.x).min(regions.first.y)
desired.min(regions.size.x).min(regions.size.y)
};
let size = Size::splat(length);
let pod = Regions::one(size, size, Axes::splat(true));
let pod = Regions::one(size, Axes::splat(true));
frame = child.layout(vt, styles, pod)?.into_frame();
}
} else {
// The default size that a shape takes on if it has no child and
// enough space.
let mut size = Size::new(Abs::pt(45.0), Abs::pt(30.0)).min(regions.first);
let mut size = Size::new(Abs::pt(45.0), Abs::pt(30.0)).min(regions.size);
if kind.is_quadratic() {
let length = if regions.expand.x || regions.expand.y {
let target = regions.expand.select(regions.first, Size::zero());
let target = regions.expand.select(regions.size, Size::zero());
target.x.max(target.y)
} else {
size.x.min(size.y)
};
size = Size::splat(length);
} else {
size = regions.expand.select(regions.first, size);
size = regions.expand.select(regions.size, size);
}
frame = Frame::new(size);