diff options
| author | PgBiel <9021226+PgBiel@users.noreply.github.com> | 2024-02-22 05:42:10 -0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-02-22 08:42:10 +0000 |
| commit | a8671962d6cfde985c49e0ca8ebc27ed4c9118cc (patch) | |
| tree | f9fb06446bb9e40065b6d31d4056ea4529b8b2e8 /crates | |
| parent | 92a2f01b7488432df8bd6ed37b7565e39cd76f93 (diff) | |
Some table improvements [More flexible tables] (#3473)
Diffstat (limited to 'crates')
| -rw-r--r-- | crates/typst/src/layout/grid/layout.rs | 6 | ||||
| -rw-r--r-- | crates/typst/src/layout/grid/lines.rs | 45 | ||||
| -rw-r--r-- | crates/typst/src/layout/grid/mod.rs | 26 | ||||
| -rw-r--r-- | crates/typst/src/model/table.rs | 32 |
4 files changed, 77 insertions, 32 deletions
diff --git a/crates/typst/src/layout/grid/layout.rs b/crates/typst/src/layout/grid/layout.rs index 790aedac..543d736d 100644 --- a/crates/typst/src/layout/grid/layout.rs +++ b/crates/typst/src/layout/grid/layout.rs @@ -332,7 +332,7 @@ impl CellGrid { items: I, fill: &Celled<Option<Paint>>, align: &Celled<Smart<Alignment>>, - inset: Sides<Option<Rel<Length>>>, + inset: &Celled<Sides<Option<Rel<Length>>>>, stroke: &ResolvedCelled<Sides<Option<Option<Arc<Stroke>>>>>, engine: &mut Engine, styles: StyleChain, @@ -486,7 +486,7 @@ impl CellGrid { y, &fill.resolve(engine, x, y)?, align.resolve(engine, x, y)?, - inset, + inset.resolve(engine, x, y)?, stroke.resolve(engine, styles, x, y)?, styles, ); @@ -572,7 +572,7 @@ impl CellGrid { y, &fill.resolve(engine, x, y)?, align.resolve(engine, x, y)?, - inset, + inset.resolve(engine, x, y)?, stroke.resolve(engine, styles, x, y)?, styles, ); diff --git a/crates/typst/src/layout/grid/lines.rs b/crates/typst/src/layout/grid/lines.rs index 9a4da26d..6eb43c9a 100644 --- a/crates/typst/src/layout/grid/lines.rs +++ b/crates/typst/src/layout/grid/lines.rs @@ -130,7 +130,7 @@ where &CellGrid, usize, usize, - Option<Arc<Stroke<Abs>>>, + Option<Option<Arc<Stroke<Abs>>>>, ) -> Option<(Arc<Stroke<Abs>>, StrokePriority)> + 'grid, I: IntoIterator<Item = (usize, Abs)>, @@ -204,7 +204,7 @@ where // Get the expected line stroke at this track by folding the // strokes of each user-specified line (with priority to the // user-specified line specified last). - let stroke = lines + let mut line_strokes = lines .iter() .filter(|line| { line.position == expected_line_position @@ -222,8 +222,15 @@ where }) .unwrap_or_else(|| track >= gutter_factor * line.start) }) - .map(|line| line.stroke.clone()) - .fold(None, |acc, line_stroke| line_stroke.fold(acc)); + .map(|line| line.stroke.clone()); + + // Distinguish between unspecified stroke (None, if no lines + // were matched above) and specified stroke of None (Some(None), + // if some lines were matched and the one specified last had a + // stroke of None) by conditionally folding after 'next()'. + let line_stroke = line_strokes.next().map(|first_stroke| { + line_strokes.fold(first_stroke, |acc, line_stroke| line_stroke.fold(acc)) + }); // The function shall determine if it is appropriate to draw // the line at this position or not (i.e. whether or not it @@ -240,7 +247,7 @@ where // (which indicates, in the context of 'std::iter::from_fn', that // our iterator isn't over yet, and this should be its next value). if let Some((stroke, priority)) = - line_stroke_at_track(grid, index, track, stroke) + line_stroke_at_track(grid, index, track, line_stroke) { // We should draw at this position. Let's check if we were // already drawing in the previous position. @@ -301,9 +308,10 @@ where } /// Returns the correct stroke with which to draw a vline right before column -/// 'x' when going through row 'y', given the stroke of the user-specified line -/// at this position, if any. Also returns the stroke's drawing priority, which -/// depends on its source. +/// `x` when going through row `y`, given the stroke of the user-specified line +/// at this position, if any (note that a stroke of `None` is unspecified, +/// while `Some(None)` means specified to remove any stroke at this position). +/// Also returns the stroke's drawing priority, which depends on its source. /// /// If the vline would go through a colspan, returns None (shouldn't be drawn). /// If the one (when at the border) or two (otherwise) cells to the left and @@ -317,12 +325,12 @@ where /// stroke, as defined by user-specified lines (if any), is returned. /// /// The priority associated with the returned stroke follows the rules -/// described in the docs for 'generate_line_segment'. +/// described in the docs for `generate_line_segment`. pub(super) fn vline_stroke_at_row( grid: &CellGrid, x: usize, y: usize, - stroke: Option<Arc<Stroke<Abs>>>, + stroke: Option<Option<Arc<Stroke<Abs>>>>, ) -> Option<(Arc<Stroke<Abs>>, StrokePriority)> { if x != 0 && x != grid.cols.len() { // When the vline isn't at the border, we need to check if a colspan would @@ -397,15 +405,16 @@ pub(super) fn vline_stroke_at_row( // Fold the line stroke and folded cell strokes, if possible. // Give priority to the explicit line stroke. // Otherwise, use whichever of the two isn't 'none' or unspecified. - let final_stroke = stroke.fold_or(cell_stroke); + let final_stroke = stroke.fold_or(Some(cell_stroke)).flatten(); final_stroke.zip(Some(priority)) } -/// Returns the correct stroke with which to draw a hline on top of row 'y' -/// when going through column 'x', given the stroke of the user-specified line -/// at this position, if any. Also returns the stroke's drawing priority, which -/// depends on its source. +/// Returns the correct stroke with which to draw a hline on top of row `y` +/// when going through column `x`, given the stroke of the user-specified line +/// at this position, if any (note that a stroke of `None` is unspecified, +/// while `Some(None)` means specified to remove any stroke at this position). +/// Also returns the stroke's drawing priority, which depends on its source. /// /// If the one (when at the border) or two (otherwise) cells above and below /// the hline have bottom and top stroke overrides, respectively, then the @@ -418,12 +427,12 @@ pub(super) fn vline_stroke_at_row( /// defined by user-specified lines (if any), is directly returned. /// /// The priority associated with the returned stroke follows the rules -/// described in the docs for 'generate_line_segment'. +/// described in the docs for `generate_line_segment`. pub(super) fn hline_stroke_at_column( grid: &CellGrid, y: usize, x: usize, - stroke: Option<Arc<Stroke<Abs>>>, + stroke: Option<Option<Arc<Stroke<Abs>>>>, ) -> Option<(Arc<Stroke<Abs>>, StrokePriority)> { // There are no rowspans yet, so no need to add a check here. The line will // always be drawn, if it has a stroke. @@ -505,7 +514,7 @@ pub(super) fn hline_stroke_at_column( // Fold the line stroke and folded cell strokes, if possible. // Give priority to the explicit line stroke. // Otherwise, use whichever of the two isn't 'none' or unspecified. - let final_stroke = stroke.fold_or(cell_stroke); + let final_stroke = stroke.fold_or(Some(cell_stroke)).flatten(); final_stroke.zip(Some(priority)) } diff --git a/crates/typst/src/layout/grid/mod.rs b/crates/typst/src/layout/grid/mod.rs index 0ddecd84..fc884e80 100644 --- a/crates/typst/src/layout/grid/mod.rs +++ b/crates/typst/src/layout/grid/mod.rs @@ -10,7 +10,7 @@ use std::sync::Arc; use ecow::eco_format; use smallvec::{smallvec, SmallVec}; -use crate::diag::{SourceResult, StrResult, Trace, Tracepoint}; +use crate::diag::{bail, SourceResult, StrResult, Trace, Tracepoint}; use crate::engine::Engine; use crate::foundations::{ cast, elem, scope, Array, Content, Fold, Packed, Show, Smart, StyleChain, Value, @@ -19,6 +19,7 @@ use crate::layout::{ Abs, AlignElem, Alignment, Axes, Dir, Fragment, LayoutMultiple, Length, OuterHAlignment, OuterVAlignment, Regions, Rel, Sides, Sizing, }; +use crate::model::{TableCell, TableHLine, TableVLine}; use crate::syntax::Span; use crate::text::TextElem; use crate::util::NonZeroExt; @@ -270,7 +271,7 @@ pub struct GridElem { /// ) /// ``` #[fold] - pub inset: Sides<Option<Rel<Length>>>, + pub inset: Celled<Sides<Option<Rel<Length>>>>, /// The contents of the grid cells, plus any extra grid lines specified /// with the [`grid.hline`]($grid.hline) and [`grid.vline`]($grid.vline) @@ -353,7 +354,7 @@ impl LayoutMultiple for Packed<GridElem> { items, fill, align, - inset, + &inset, &stroke, engine, styles, @@ -395,7 +396,24 @@ cast! { Self::VLine(vline) => vline.into_value(), Self::Cell(cell) => cell.into_value(), }, - v: Content => v.into(), + v: Content => { + if v.is::<TableCell>() { + bail!( + "cannot use `table.cell` as a grid cell; use `grid.cell` instead" + ); + } + if v.is::<TableHLine>() { + bail!( + "cannot use `table.hline` as a grid line; use `grid.hline` instead" + ); + } + if v.is::<TableVLine>() { + bail!( + "cannot use `table.vline` as a grid line; use `grid.vline` instead" + ); + } + v.into() + } } impl From<Content> for GridChild { diff --git a/crates/typst/src/model/table.rs b/crates/typst/src/model/table.rs index ae4dbce7..a51fd1e7 100644 --- a/crates/typst/src/model/table.rs +++ b/crates/typst/src/model/table.rs @@ -3,15 +3,16 @@ use std::sync::Arc; use ecow::eco_format; -use crate::diag::{SourceResult, Trace, Tracepoint}; +use crate::diag::{bail, SourceResult, Trace, Tracepoint}; use crate::engine::Engine; use crate::foundations::{ cast, elem, scope, Content, Fold, Packed, Show, Smart, StyleChain, }; use crate::layout::{ show_grid_cell, Abs, Alignment, Axes, Cell, CellGrid, Celled, Dir, Fragment, - GridItem, GridLayouter, LayoutMultiple, Length, LinePosition, OuterHAlignment, - OuterVAlignment, Regions, Rel, ResolvableCell, Sides, TrackSizings, + GridCell, GridHLine, GridItem, GridLayouter, GridVLine, LayoutMultiple, Length, + LinePosition, OuterHAlignment, OuterVAlignment, Regions, Rel, ResolvableCell, Sides, + TrackSizings, }; use crate::model::Figurable; use crate::syntax::Span; @@ -200,8 +201,8 @@ pub struct TableElem { /// ) /// ``` #[fold] - #[default(Sides::splat(Some(Abs::pt(5.0).into())))] - pub inset: Sides<Option<Rel<Length>>>, + #[default(Celled::Value(Sides::splat(Some(Abs::pt(5.0).into()))))] + pub inset: Celled<Sides<Option<Rel<Length>>>>, /// The contents of the table cells, plus any extra table lines specified /// with the [`table.hline`]($table.hline) and @@ -282,7 +283,7 @@ impl LayoutMultiple for Packed<TableElem> { items, fill, align, - inset, + &inset, &stroke, engine, styles, @@ -349,7 +350,24 @@ cast! { Self::VLine(vline) => vline.into_value(), Self::Cell(cell) => cell.into_value(), }, - v: Content => v.into(), + v: Content => { + if v.is::<GridCell>() { + bail!( + "cannot use `grid.cell` as a table cell; use `table.cell` instead" + ); + } + if v.is::<GridHLine>() { + bail!( + "cannot use `grid.hline` as a table line; use `table.hline` instead" + ); + } + if v.is::<GridVLine>() { + bail!( + "cannot use `grid.vline` as a table line; use `table.vline` instead" + ); + } + v.into() + } } impl From<Content> for TableChild { |
