summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--library/src/layout/columns.rs16
-rw-r--r--library/src/layout/container.rs10
-rw-r--r--library/src/layout/flow.rs21
-rw-r--r--library/src/layout/grid.rs59
-rw-r--r--library/src/layout/page.rs4
-rw-r--r--library/src/layout/par.rs44
-rw-r--r--library/src/layout/place.rs6
-rw-r--r--library/src/layout/regions.rs56
-rw-r--r--library/src/layout/stack.rs27
-rw-r--r--library/src/layout/transform.rs2
-rw-r--r--library/src/math/ctx.rs7
-rw-r--r--library/src/visualize/image.rs2
-rw-r--r--library/src/visualize/line.rs6
-rw-r--r--library/src/visualize/shape.rs15
14 files changed, 131 insertions, 144 deletions
diff --git a/library/src/layout/columns.rs b/library/src/layout/columns.rs
index 7da9c4a0..4cf840cd 100644
--- a/library/src/layout/columns.rs
+++ b/library/src/layout/columns.rs
@@ -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);
diff --git a/library/src/layout/container.rs b/library/src/layout/container.rs
index 094ed05a..b7e7aa18 100644
--- a/library/src/layout/container.rs
+++ b/library/src/layout/container.rs
@@ -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))
diff --git a/library/src/layout/flow.rs b/library/src/layout/flow.rs
index 61188f9c..e21dcd2a 100644
--- a/library/src/layout/flow.rs
+++ b/library/src/layout/flow.rs
@@ -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.
diff --git a/library/src/layout/grid.rs b/library/src/layout/grid.rs
index da8c4fca..95e4ac8f 100644
--- a/library/src/layout/grid.rs
+++ b/library/src/layout/grid.rs
@@ -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();
diff --git a/library/src/layout/page.rs b/library/src/layout/page.rs
index 3de12634..6a0c07b0 100644
--- a/library/src/layout/page.rs
+++ b/library/src/layout/page.rs
@@ -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);
diff --git a/library/src/layout/par.rs b/library/src/layout/par.rs
index dbf2c936..21551268 100644
--- a/library/src/layout/par.rs
+++ b/library/src/layout/par.rs
@@ -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);
diff --git a/library/src/layout/place.rs b/library/src/layout/place.rs
index 16b091fe..c6e26b72 100644
--- a/library/src/layout/place.rs
+++ b/library/src/layout/place.rs
@@ -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))
diff --git a/library/src/layout/regions.rs b/library/src/layout/regions.rs
index 2592210b..94c81704 100644
--- a/library/src/layout/regions.rs
+++ b/library/src/layout/regions.rs
@@ -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(&(..));
}
diff --git a/library/src/layout/stack.rs b/library/src/layout/stack.rs
index 54b03bdc..5c1a471c 100644
--- a/library/src/layout/stack.rs
+++ b/library/src/layout/stack.rs
@@ -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);
diff --git a/library/src/layout/transform.rs b/library/src/layout/transform.rs
index 25f74e01..1c9dfce5 100644
--- a/library/src/layout/transform.rs
+++ b/library/src/layout/transform.rs
@@ -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)
diff --git a/library/src/math/ctx.rs b/library/src/math/ctx.rs
index d43d1b2a..a3aa4047 100644
--- a/library/src/math/ctx.rs
+++ b/library/src/math/ctx.rs
@@ -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,
diff --git a/library/src/visualize/image.rs b/library/src/visualize/image.rs
index 87b67287..330f1d04 100644
--- a/library/src/visualize/image.rs
+++ b/library/src/visualize/image.rs
@@ -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;
diff --git a/library/src/visualize/line.rs b/library/src/visualize/line.rs
index a8b0e334..28910a26 100644
--- a/library/src/visualize/line.rs
+++ b/library/src/visualize/line.rs
@@ -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);
diff --git a/library/src/visualize/shape.rs b/library/src/visualize/shape.rs
index c0c81bf5..6f70b6c1 100644
--- a/library/src/visualize/shape.rs
+++ b/library/src/visualize/shape.rs
@@ -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);