diff options
| author | SekoiaTree <51149447+SekoiaTree@users.noreply.github.com> | 2023-09-21 10:26:47 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-09-21 10:26:47 +0200 |
| commit | 3dcbe859fb6c0db3672feddf4c2b5043d5c24e0e (patch) | |
| tree | 29ffb3d7bcf6eef68a0d73b0a3ed9e31a252a4d4 /crates/typst-library/src | |
| parent | 50f354e9890d00f8b2089cd221db4133757b3b41 (diff) | |
Add gaps for matrix, case, and vector (#2186)
Diffstat (limited to 'crates/typst-library/src')
| -rw-r--r-- | crates/typst-library/src/math/matrix.rs | 106 |
1 files changed, 87 insertions, 19 deletions
diff --git a/crates/typst-library/src/math/matrix.rs b/crates/typst-library/src/math/matrix.rs index abb0da35..dd30209a 100644 --- a/crates/typst-library/src/math/matrix.rs +++ b/crates/typst-library/src/math/matrix.rs @@ -2,8 +2,8 @@ use typst::model::Resolve; use super::*; -const ROW_GAP: Em = Em::new(0.5); -const COL_GAP: Em = Em::new(0.5); +const DEFAULT_ROW_GAP: Em = Em::new(0.5); +const DEFAULT_COL_GAP: Em = Em::new(0.5); const VERTICAL_PADDING: Ratio = Ratio::new(0.1); const DEFAULT_STROKE_THICKNESS: Em = Em::new(0.05); @@ -28,6 +28,16 @@ pub struct VecElem { #[default(Some(Delimiter::Paren))] pub delim: Option<Delimiter>, + /// The gap between elements. + /// + /// ```example + /// #set math.vec(gap: 1em) + /// $ vec(1, 2) $ + /// ``` + #[resolve] + #[default(DEFAULT_ROW_GAP.into())] + pub gap: Rel<Length>, + /// The elements of the vector. #[variadic] pub children: Vec<Content>, @@ -37,7 +47,12 @@ impl LayoutMath for VecElem { #[tracing::instrument(skip(ctx))] fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> { let delim = self.delim(ctx.styles()); - let frame = layout_vec_body(ctx, &self.children(), FixedAlign::Center)?; + let frame = layout_vec_body( + ctx, + &self.children(), + FixedAlign::Center, + self.gap(ctx.styles()), + )?; layout_delimiters( ctx, frame, @@ -110,6 +125,40 @@ pub struct MatElem { #[fold] pub augment: Option<Augment>, + /// The gap between rows and columns. + /// + /// ```example + /// #set math.mat(gap: 1em) + /// $ mat(1, 2; 3, 4) $ + /// ``` + #[external] + pub gap: Rel<Length>, + + /// The gap between rows. Takes precedence over `gap`. + /// + /// ```example + /// #set math.mat(row-gap: 1em) + /// $ mat(1, 2; 3, 4) $ + /// ``` + #[resolve] + #[parse( + let gap = args.named("gap")?; + args.named("row-gap")?.or(gap) + )] + #[default(DEFAULT_ROW_GAP.into())] + pub row_gap: Rel<Length>, + + /// The gap between columns. Takes precedence over `gap`. + /// + /// ```example + /// #set math.mat(column-gap: 1em) + /// $ mat(1, 2; 3, 4) $ + /// ``` + #[resolve] + #[parse(args.named("column-gap")?.or(gap))] + #[default(DEFAULT_COL_GAP.into())] + pub column_gap: Rel<Length>, + /// An array of arrays with the rows of the matrix. /// /// ```example @@ -179,8 +228,13 @@ impl LayoutMath for MatElem { } let delim = self.delim(ctx.styles()); - - let frame = layout_mat_body(ctx, &self.rows(), augment, self.span())?; + let frame = layout_mat_body( + ctx, + &self.rows(), + augment, + Axes::new(self.column_gap(ctx.styles()), self.row_gap(ctx.styles())), + self.span(), + )?; layout_delimiters( ctx, @@ -216,6 +270,16 @@ pub struct CasesElem { #[default(Delimiter::Brace)] pub delim: Delimiter, + /// The gap between branches. + /// + /// ```example + /// #set math.cases(gap: 1em) + /// $ x = cases(1, 2) $ + /// ``` + #[resolve] + #[default(DEFAULT_ROW_GAP.into())] + pub gap: Rel<Length>, + /// The branches of the case distinction. #[variadic] pub children: Vec<Content>, @@ -225,7 +289,12 @@ impl LayoutMath for CasesElem { #[tracing::instrument(skip(ctx))] fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> { let delim = self.delim(ctx.styles()); - let frame = layout_vec_body(ctx, &self.children(), FixedAlign::Start)?; + let frame = layout_vec_body( + ctx, + &self.children(), + FixedAlign::Start, + self.gap(ctx.styles()), + )?; layout_delimiters(ctx, frame, Some(delim.open()), None, self.span()) } } @@ -279,8 +348,9 @@ fn layout_vec_body( ctx: &mut MathContext, column: &[Content], align: FixedAlign, + row_gap: Rel<Abs>, ) -> SourceResult<Frame> { - let gap = ROW_GAP.scaled(ctx); + let gap = row_gap.relative_to(ctx.regions.base().y); ctx.style(ctx.style.for_denominator()); let mut flat = vec![]; for child in column { @@ -295,13 +365,11 @@ fn layout_mat_body( ctx: &mut MathContext, rows: &[Vec<Content>], augment: Option<Augment<Abs>>, + gap: Axes<Rel<Abs>>, span: Span, ) -> SourceResult<Frame> { - let row_gap = ROW_GAP.scaled(ctx); - let col_gap = COL_GAP.scaled(ctx); - - let half_row_gap = row_gap * 0.5; - let half_col_gap = col_gap * 0.5; + let gap = gap.zip_map(ctx.regions.base(), Rel::relative_to); + let half_gap = gap * 0.5; // We provide a default stroke thickness that scales // with font size to ensure that augmentation lines @@ -359,7 +427,7 @@ fn layout_mat_body( // For each row, combine maximum ascent and descent into a row height. // Sum the row heights, then add the total height of the gaps between rows. let total_height = - heights.iter().map(|&(a, b)| a + b).sum::<Abs>() + row_gap * (nrows - 1) as f64; + heights.iter().map(|&(a, b)| a + b).sum::<Abs>() + gap.y * (nrows - 1) as f64; // Width starts at zero because it can't be calculated until later let mut frame = Frame::new(Size::new(Abs::zero(), total_height)); @@ -380,7 +448,7 @@ fn layout_mat_body( frame.push_frame(pos, cell); - y += ascent + descent + row_gap; + y += ascent + descent + gap.y; } // Advance to the end of the column @@ -389,23 +457,23 @@ fn layout_mat_body( // If a vertical line should be inserted after this column if vline.0.contains(&(index + 1)) { frame.push( - Point::with_x(x + half_col_gap), + Point::with_x(x + half_gap.x), line_item(total_height, true, stroke.clone(), span), ); } // Advance to the start of the next column - x += col_gap; + x += gap.x; } // Once all the columns are laid out, the total width can be calculated - let total_width = x - col_gap; + let total_width = x - gap.x; // This allows the horizontal lines to be laid out for line in hline.0 { let offset = (heights[0..line].iter().map(|&(a, b)| a + b).sum::<Abs>() - + row_gap * (line - 1) as f64) - + half_row_gap; + + gap.y * (line - 1) as f64) + + half_gap.y; frame.push( Point::with_y(offset), |
