diff --git a/library/src/layout/enum.rs b/library/src/layout/enum.rs index 91866d155..d66477fc4 100644 --- a/library/src/layout/enum.rs +++ b/library/src/layout/enum.rs @@ -256,7 +256,6 @@ impl Layout for EnumElem { } let layouter = GridLayouter::new( - vt, Axes::with_x(&[ Sizing::Rel(indent.into()), Sizing::Auto, @@ -269,7 +268,7 @@ impl Layout for EnumElem { styles, ); - Ok(layouter.layout()?.fragment) + Ok(layouter.layout(vt)?.fragment) } } diff --git a/library/src/layout/grid.rs b/library/src/layout/grid.rs index acf13d648..ed4c75b4e 100644 --- a/library/src/layout/grid.rs +++ b/library/src/layout/grid.rs @@ -94,7 +94,7 @@ pub struct GridElem { #[parse(args.named("row-gutter")?.or_else(|| gutter.clone()))] pub row_gutter: TrackSizings, - /// The contents of the table cells. + /// The contents of the grid cells. /// /// The cells are populated in row-major order. #[variadic] @@ -112,7 +112,6 @@ impl Layout for GridElem { // Prepare grid layout by unifying content and gutter tracks. let cells = self.children(); let layouter = GridLayouter::new( - vt, Axes::new(&self.columns(styles).0, &self.rows(styles).0), Axes::new(&self.column_gutter(styles).0, &self.row_gutter(styles).0), &cells, @@ -121,7 +120,7 @@ impl Layout for GridElem { ); // Measure the columns and layout the grid row-by-row. - Ok(layouter.layout()?.fragment) + Ok(layouter.layout(vt)?.fragment) } } @@ -138,9 +137,7 @@ cast! { } /// Performs grid layout. -pub struct GridLayouter<'a, 'v> { - /// The core context. - vt: &'a mut Vt<'v>, +pub struct GridLayouter<'a> { /// The grid cells. cells: &'a [Content], /// Whether this is an RTL grid. @@ -198,12 +195,11 @@ enum Row { Fr(Fr, usize), } -impl<'a, 'v> GridLayouter<'a, 'v> { +impl<'a> GridLayouter<'a> { /// Create a new grid layouter. /// /// This prepares grid layout by unifying content and gutter tracks. pub fn new( - vt: &'a mut Vt<'v>, tracks: Axes<&[Sizing]>, gutter: Axes<&[Sizing]>, cells: &'a [Content], @@ -260,51 +256,47 @@ impl<'a, 'v> GridLayouter<'a, 'v> { cols.reverse(); } - let rcols = vec![Abs::zero(); cols.len()]; - let lrows = vec![]; - // We use these regions for auto row measurement. Since at that moment, // columns are already sized, we can enable horizontal expansion. let mut regions = regions; regions.expand = Axes::new(true, false); Self { - vt, cells, is_rtl, has_gutter, - cols, rows, regions, styles, - rcols, + rcols: vec![Abs::zero(); cols.len()], + cols, width: Abs::zero(), rrows: vec![], - lrows, + lrows: vec![], initial: regions.size, finished: vec![], } } /// Determines the columns sizes and then layouts the grid row-by-row. - pub fn layout(mut self) -> SourceResult { - self.measure_columns()?; + pub fn layout(mut self, vt: &mut Vt) -> SourceResult { + self.measure_columns(vt)?; for y in 0..self.rows.len() { // Skip to next region if current one is full, but only for content // rows, not for gutter rows. if self.regions.is_full() && (!self.has_gutter || y % 2 == 0) { - self.finish_region()?; + self.finish_region(vt)?; } match self.rows[y] { - Sizing::Auto => self.layout_auto_row(y)?, - Sizing::Rel(v) => self.layout_relative_row(v, y)?, + Sizing::Auto => self.layout_auto_row(vt, y)?, + Sizing::Rel(v) => self.layout_relative_row(vt, v, y)?, Sizing::Fr(v) => self.lrows.push(Row::Fr(v, y)), } } - self.finish_region()?; + self.finish_region(vt)?; Ok(GridLayout { fragment: Fragment::frames(self.finished), @@ -315,7 +307,7 @@ impl<'a, 'v> GridLayouter<'a, 'v> { /// Determine all column sizes. #[tracing::instrument(name = "GridLayouter::measure_columns", skip_all)] - fn measure_columns(&mut self) -> SourceResult<()> { + fn measure_columns(&mut self, vt: &mut Vt) -> SourceResult<()> { // Sum of sizes of resolved relative tracks. let mut rel = Abs::zero(); @@ -341,7 +333,7 @@ impl<'a, 'v> GridLayouter<'a, 'v> { let available = self.regions.size.x - rel; if available >= Abs::zero() { // Determine size of auto columns. - let (auto, count) = self.measure_auto_columns(available)?; + let (auto, count) = self.measure_auto_columns(vt, available)?; // If there is remaining space, distribute it to fractional columns, // otherwise shrink auto columns. @@ -360,7 +352,11 @@ impl<'a, 'v> GridLayouter<'a, 'v> { } /// Measure the size that is available to auto columns. - fn measure_auto_columns(&mut self, available: Abs) -> SourceResult<(Abs, usize)> { + fn measure_auto_columns( + &mut self, + vt: &mut Vt, + available: Abs, + ) -> SourceResult<(Abs, usize)> { let mut auto = Abs::zero(); let mut count = 0; @@ -385,7 +381,7 @@ impl<'a, 'v> GridLayouter<'a, 'v> { let size = Size::new(available, height); let pod = Regions::one(size, Axes::splat(false)); - let frame = cell.measure(self.vt, self.styles, pod)?.into_frame(); + let frame = cell.measure(vt, self.styles, pod)?.into_frame(); resolved.set_max(frame.width()); } } @@ -446,14 +442,14 @@ impl<'a, 'v> GridLayouter<'a, 'v> { /// Layout a row with automatic height. Such a row may break across multiple /// regions. - fn layout_auto_row(&mut self, y: usize) -> SourceResult<()> { + fn layout_auto_row(&mut self, vt: &mut Vt, y: usize) -> SourceResult<()> { // Determine the size for each region of the row. If the first region // ends up empty for some column, skip the region and remeasure. - let mut resolved = match self.measure_auto_row(y, true)? { + let mut resolved = match self.measure_auto_row(vt, y, true)? { Some(resolved) => resolved, None => { - self.finish_region()?; - self.measure_auto_row(y, false)?.unwrap() + self.finish_region(vt)?; + self.measure_auto_row(vt, y, false)?.unwrap() } }; @@ -464,7 +460,7 @@ impl<'a, 'v> GridLayouter<'a, 'v> { // Layout into a single region. if let &[first] = resolved.as_slice() { - let frame = self.layout_single_row(first, y)?; + let frame = self.layout_single_row(vt, first, y)?; self.push_row(frame, y); return Ok(()); } @@ -482,12 +478,12 @@ impl<'a, 'v> GridLayouter<'a, 'v> { } // Layout into multiple regions. - let fragment = self.layout_multi_row(&resolved, y)?; + let fragment = self.layout_multi_row(vt, &resolved, y)?; let len = fragment.len(); for (i, frame) in fragment.into_iter().enumerate() { self.push_row(frame, y); if i + 1 < len { - self.finish_region()?; + self.finish_region(vt)?; } } @@ -498,6 +494,7 @@ impl<'a, 'v> GridLayouter<'a, 'v> { /// if `can_skip` is false. fn measure_auto_row( &mut self, + vt: &mut Vt, y: usize, can_skip: bool, ) -> SourceResult>> { @@ -508,7 +505,7 @@ impl<'a, 'v> GridLayouter<'a, 'v> { let mut pod = self.regions; pod.size.x = rcol; - let frames = cell.measure(self.vt, self.styles, pod)?.into_frames(); + let frames = cell.measure(vt, self.styles, pod)?.into_frames(); // Skip the first region if one cell in it is empty. Then, // remeasure. @@ -537,14 +534,19 @@ 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, y: usize) -> SourceResult<()> { + fn layout_relative_row( + &mut self, + vt: &mut Vt, + v: Rel, + y: usize, + ) -> SourceResult<()> { let resolved = v.resolve(self.styles).relative_to(self.regions.base().y); - let frame = self.layout_single_row(resolved, y)?; + let frame = self.layout_single_row(vt, resolved, y)?; // Skip to fitting region. let height = frame.height(); while !self.regions.size.y.fits(height) && !self.regions.in_last() { - self.finish_region()?; + self.finish_region(vt)?; // Don't skip multiple regions for gutter and don't push a row. if self.has_gutter && y % 2 == 1 { @@ -558,7 +560,12 @@ impl<'a, 'v> GridLayouter<'a, 'v> { } /// Layout a row with fixed height and return its frame. - fn layout_single_row(&mut self, height: Abs, y: usize) -> SourceResult { + fn layout_single_row( + &mut self, + vt: &mut Vt, + height: Abs, + y: usize, + ) -> SourceResult { let mut output = Frame::new(Size::new(self.width, height)); let mut pos = Point::zero(); @@ -569,7 +576,7 @@ impl<'a, 'v> GridLayouter<'a, 'v> { if self.rows[y] == Sizing::Auto { pod.full = self.regions.full; } - let frame = cell.layout(self.vt, self.styles, pod)?.into_frame(); + let frame = cell.layout(vt, self.styles, pod)?.into_frame(); output.push_frame(pos, frame); } @@ -580,7 +587,12 @@ impl<'a, 'v> GridLayouter<'a, 'v> { } /// Layout a row spanning multiple regions. - fn layout_multi_row(&mut self, heights: &[Abs], y: usize) -> SourceResult { + fn layout_multi_row( + &mut self, + vt: &mut Vt, + heights: &[Abs], + y: usize, + ) -> SourceResult { // Prepare frames. let mut outputs: Vec<_> = heights .iter() @@ -600,7 +612,7 @@ impl<'a, 'v> GridLayouter<'a, 'v> { pod.size.x = rcol; // Push the layouted frames into the individual output frames. - let fragment = cell.layout(self.vt, self.styles, pod)?; + let fragment = cell.layout(vt, self.styles, pod)?; for (output, frame) in outputs.iter_mut().zip(fragment) { output.push_frame(pos, frame); } @@ -619,7 +631,7 @@ impl<'a, 'v> GridLayouter<'a, 'v> { } /// Finish rows for one region. - fn finish_region(&mut self) -> SourceResult<()> { + fn finish_region(&mut self, vt: &mut Vt) -> SourceResult<()> { // Determine the height of existing rows in the region. let mut used = Abs::zero(); let mut fr = Fr::zero(); @@ -649,7 +661,7 @@ impl<'a, 'v> GridLayouter<'a, 'v> { Row::Fr(v, y) => { let remaining = self.regions.full - used; let height = v.share(fr, remaining); - (self.layout_single_row(height, y)?, y) + (self.layout_single_row(vt, height, y)?, y) } }; diff --git a/library/src/layout/list.rs b/library/src/layout/list.rs index 9dce466d4..e39ec3f50 100644 --- a/library/src/layout/list.rs +++ b/library/src/layout/list.rs @@ -151,7 +151,6 @@ impl Layout for ListElem { } let layouter = GridLayouter::new( - vt, Axes::with_x(&[ Sizing::Rel(indent.into()), Sizing::Auto, @@ -164,7 +163,7 @@ impl Layout for ListElem { styles, ); - Ok(layouter.layout()?.fragment) + Ok(layouter.layout(vt)?.fragment) } } diff --git a/library/src/layout/table.rs b/library/src/layout/table.rs index 357263f49..62f8c1318 100644 --- a/library/src/layout/table.rs +++ b/library/src/layout/table.rs @@ -162,7 +162,6 @@ impl Layout for TableElem { // Prepare grid layout by unifying content and gutter tracks. let layouter = GridLayouter::new( - vt, tracks.as_deref(), gutter.as_deref(), &cells, @@ -171,7 +170,7 @@ impl Layout for TableElem { ); // Measure the columns and layout the grid row-by-row. - let mut layout = layouter.layout()?; + let mut layout = layouter.layout(vt)?; // Add lines and backgrounds. for (frame, rows) in layout.fragment.iter_mut().zip(&layout.rows) {