diff --git a/crates/typst/src/math/matrix.rs b/crates/typst/src/math/matrix.rs index 4dadd756..34e0611a 100644 --- a/crates/typst/src/math/matrix.rs +++ b/crates/typst/src/math/matrix.rs @@ -22,7 +22,7 @@ use crate::visualize::{FixedStroke, Geometry, LineCap, Shape, Stroke}; use super::delimiter_alignment; -const DEFAULT_ROW_GAP: Em = Em::new(0.5); +const DEFAULT_ROW_GAP: Em = Em::new(0.2); 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); @@ -441,8 +441,12 @@ fn layout_vec_body( for child in column { flat.push(ctx.layout_into_run(child, styles.chain(&denom_style))?); } - - Ok(stack(flat, align, gap, 0, alternator)) + // We pad ascent and descent with the ascent and descent of the paren + // to ensure that normal vectors are aligned with others unless they are + // way too big. + let paren = + GlyphFragment::new(ctx, styles.chain(&denom_style), '(', Span::detached()); + Ok(stack(flat, align, gap, 0, alternator, Some((paren.ascent, paren.descent)))) } /// Layout the inner contents of a matrix. @@ -499,12 +503,18 @@ fn layout_mat_body( let mut cols = vec![vec![]; ncols]; let denom_style = style_for_denominator(styles); + // We pad ascent and descent with the ascent and descent of the paren + // to ensure that normal matrices are aligned with others unless they are + // way too big. + let paren = + GlyphFragment::new(ctx, styles.chain(&denom_style), '(', Span::detached()); + for (row, (ascent, descent)) in rows.iter().zip(&mut heights) { for (cell, col) in row.iter().zip(&mut cols) { let cell = ctx.layout_into_run(cell, styles.chain(&denom_style))?; - ascent.set_max(cell.ascent()); - descent.set_max(cell.descent()); + ascent.set_max(cell.ascent().max(paren.ascent)); + descent.set_max(cell.descent().max(paren.descent)); col.push(cell); } diff --git a/crates/typst/src/math/underover.rs b/crates/typst/src/math/underover.rs index 6be86d9f..defa46c1 100644 --- a/crates/typst/src/math/underover.rs +++ b/crates/typst/src/math/underover.rs @@ -291,8 +291,14 @@ fn layout_underoverspreader( baseline = rows.len() - 1; } - let frame = - stack(rows, FixedAlignment::Center, gap, baseline, LeftRightAlternator::Right); + let frame = stack( + rows, + FixedAlignment::Center, + gap, + baseline, + LeftRightAlternator::Right, + None, + ); ctx.push(FrameFragment::new(ctx, styles, frame).with_class(body_class)); Ok(()) @@ -309,6 +315,7 @@ pub(super) fn stack( gap: Abs, baseline: usize, alternator: LeftRightAlternator, + minimum_ascent_descent: Option<(Abs, Abs)>, ) -> Frame { let rows: Vec<_> = rows.into_iter().flat_map(|r| r.rows()).collect(); let AlignmentResult { points, width } = alignments(&rows); @@ -317,20 +324,27 @@ pub(super) fn stack( .map(|row| row.into_line_frame(&points, alternator)) .collect(); + let padded_height = |height: Abs| { + height.max(minimum_ascent_descent.map_or(Abs::zero(), |(a, d)| a + d)) + }; + let mut frame = Frame::soft(Size::new( width, - rows.iter().map(|row| row.height()).sum::() + rows.iter().map(|row| padded_height(row.height())).sum::() + rows.len().saturating_sub(1) as f64 * gap, )); let mut y = Abs::zero(); for (i, row) in rows.into_iter().enumerate() { let x = align.position(width - row.width()); - let pos = Point::new(x, y); + let ascent_padded_part = minimum_ascent_descent + .map_or(Abs::zero(), |(a, _)| (a - row.ascent())) + .max(Abs::zero()); + let pos = Point::new(x, y + ascent_padded_part); if i == baseline { - frame.set_baseline(y + row.baseline()); + frame.set_baseline(y + row.baseline() + ascent_padded_part); } - y += row.height() + gap; + y += padded_height(row.height()) + gap; frame.push_frame(pos, row); } diff --git a/tests/ref/enum-numbering-closure-nested-complex.png b/tests/ref/enum-numbering-closure-nested-complex.png index a756f37c..f287f4dd 100644 Binary files a/tests/ref/enum-numbering-closure-nested-complex.png and b/tests/ref/enum-numbering-closure-nested-complex.png differ diff --git a/tests/ref/gradient-math-conic.png b/tests/ref/gradient-math-conic.png index 88ff7a85..ffd3e806 100644 Binary files a/tests/ref/gradient-math-conic.png and b/tests/ref/gradient-math-conic.png differ diff --git a/tests/ref/gradient-math-dir.png b/tests/ref/gradient-math-dir.png index 5ed19182..8a9954ad 100644 Binary files a/tests/ref/gradient-math-dir.png and b/tests/ref/gradient-math-dir.png differ diff --git a/tests/ref/gradient-math-mat.png b/tests/ref/gradient-math-mat.png index aa3332b9..ecf95303 100644 Binary files a/tests/ref/gradient-math-mat.png and b/tests/ref/gradient-math-mat.png differ diff --git a/tests/ref/gradient-math-misc.png b/tests/ref/gradient-math-misc.png index b8fbdd74..b9b55d4d 100644 Binary files a/tests/ref/gradient-math-misc.png and b/tests/ref/gradient-math-misc.png differ diff --git a/tests/ref/gradient-math-radial.png b/tests/ref/gradient-math-radial.png index c9b966b2..8d0047bb 100644 Binary files a/tests/ref/gradient-math-radial.png and b/tests/ref/gradient-math-radial.png differ diff --git a/tests/ref/issue-1617-mat-align.png b/tests/ref/issue-1617-mat-align.png new file mode 100644 index 00000000..bd4ea16f Binary files /dev/null and b/tests/ref/issue-1617-mat-align.png differ diff --git a/tests/ref/issue-2055-math-eval.png b/tests/ref/issue-2055-math-eval.png index 168b8913..f058a995 100644 Binary files a/tests/ref/issue-2055-math-eval.png and b/tests/ref/issue-2055-math-eval.png differ diff --git a/tests/ref/issue-2268-mat-augment-color.png b/tests/ref/issue-2268-mat-augment-color.png index 5aca29ca..70f52dcf 100644 Binary files a/tests/ref/issue-2268-mat-augment-color.png and b/tests/ref/issue-2268-mat-augment-color.png differ diff --git a/tests/ref/issue-3774-math-call-empty-2d-args.png b/tests/ref/issue-3774-math-call-empty-2d-args.png index ce4b4eb8..c1bf52d0 100644 Binary files a/tests/ref/issue-3774-math-call-empty-2d-args.png and b/tests/ref/issue-3774-math-call-empty-2d-args.png differ diff --git a/tests/ref/issue-852-mat-type.png b/tests/ref/issue-852-mat-type.png index 81af3bb5..8e2bd498 100644 Binary files a/tests/ref/issue-852-mat-type.png and b/tests/ref/issue-852-mat-type.png differ diff --git a/tests/ref/math-align-cases.png b/tests/ref/math-align-cases.png index 4ea9a264..54105b55 100644 Binary files a/tests/ref/math-align-cases.png and b/tests/ref/math-align-cases.png differ diff --git a/tests/ref/math-call-2d-semicolon-priority.png b/tests/ref/math-call-2d-semicolon-priority.png index 18807e0b..d74ca9ab 100644 Binary files a/tests/ref/math-call-2d-semicolon-priority.png and b/tests/ref/math-call-2d-semicolon-priority.png differ diff --git a/tests/ref/math-cases-delim.png b/tests/ref/math-cases-delim.png index e54e277c..74a6c29b 100644 Binary files a/tests/ref/math-cases-delim.png and b/tests/ref/math-cases-delim.png differ diff --git a/tests/ref/math-cases-gap.png b/tests/ref/math-cases-gap.png index e3579130..746572fa 100644 Binary files a/tests/ref/math-cases-gap.png and b/tests/ref/math-cases-gap.png differ diff --git a/tests/ref/math-cases.png b/tests/ref/math-cases.png index 2e8c260a..456b2550 100644 Binary files a/tests/ref/math-cases.png and b/tests/ref/math-cases.png differ diff --git a/tests/ref/math-equation-font.png b/tests/ref/math-equation-font.png index b105d9e3..eb84634e 100644 Binary files a/tests/ref/math-equation-font.png and b/tests/ref/math-equation-font.png differ diff --git a/tests/ref/math-mat-align-complex.png b/tests/ref/math-mat-align-complex.png index 682fed22..3cba2588 100644 Binary files a/tests/ref/math-mat-align-complex.png and b/tests/ref/math-mat-align-complex.png differ diff --git a/tests/ref/math-mat-align-explicit--alternating.png b/tests/ref/math-mat-align-explicit--alternating.png index cb29eb06..37e8dc06 100644 Binary files a/tests/ref/math-mat-align-explicit--alternating.png and b/tests/ref/math-mat-align-explicit--alternating.png differ diff --git a/tests/ref/math-mat-align-explicit-left.png b/tests/ref/math-mat-align-explicit-left.png index 97fe0a1f..09ce9398 100644 Binary files a/tests/ref/math-mat-align-explicit-left.png and b/tests/ref/math-mat-align-explicit-left.png differ diff --git a/tests/ref/math-mat-align-explicit-right.png b/tests/ref/math-mat-align-explicit-right.png index 80966e52..3592c0cf 100644 Binary files a/tests/ref/math-mat-align-explicit-right.png and b/tests/ref/math-mat-align-explicit-right.png differ diff --git a/tests/ref/math-mat-align-implicit.png b/tests/ref/math-mat-align-implicit.png index 0c14f1a7..0c508efc 100644 Binary files a/tests/ref/math-mat-align-implicit.png and b/tests/ref/math-mat-align-implicit.png differ diff --git a/tests/ref/math-mat-align-signed-numbers.png b/tests/ref/math-mat-align-signed-numbers.png index 02a3c582..c9274379 100644 Binary files a/tests/ref/math-mat-align-signed-numbers.png and b/tests/ref/math-mat-align-signed-numbers.png differ diff --git a/tests/ref/math-mat-augment-set.png b/tests/ref/math-mat-augment-set.png index f3827c41..c5881b13 100644 Binary files a/tests/ref/math-mat-augment-set.png and b/tests/ref/math-mat-augment-set.png differ diff --git a/tests/ref/math-mat-augment.png b/tests/ref/math-mat-augment.png index 3a272ce9..0e2a42a2 100644 Binary files a/tests/ref/math-mat-augment.png and b/tests/ref/math-mat-augment.png differ diff --git a/tests/ref/math-mat-baseline.png b/tests/ref/math-mat-baseline.png index 51e90a1f..c5aa1e20 100644 Binary files a/tests/ref/math-mat-baseline.png and b/tests/ref/math-mat-baseline.png differ diff --git a/tests/ref/math-mat-delim-direct.png b/tests/ref/math-mat-delim-direct.png index b40fd36c..75915689 100644 Binary files a/tests/ref/math-mat-delim-direct.png and b/tests/ref/math-mat-delim-direct.png differ diff --git a/tests/ref/math-mat-delim-set.png b/tests/ref/math-mat-delim-set.png index fc92fd4b..b7a2b8d6 100644 Binary files a/tests/ref/math-mat-delim-set.png and b/tests/ref/math-mat-delim-set.png differ diff --git a/tests/ref/math-mat-delims-inverted.png b/tests/ref/math-mat-delims-inverted.png index 06f1cdb3..84047952 100644 Binary files a/tests/ref/math-mat-delims-inverted.png and b/tests/ref/math-mat-delims-inverted.png differ diff --git a/tests/ref/math-mat-delims-pair.png b/tests/ref/math-mat-delims-pair.png index 954e6d82..56597571 100644 Binary files a/tests/ref/math-mat-delims-pair.png and b/tests/ref/math-mat-delims-pair.png differ diff --git a/tests/ref/math-mat-delims.png b/tests/ref/math-mat-delims.png index 6ba589c8..9a859c3b 100644 Binary files a/tests/ref/math-mat-delims.png and b/tests/ref/math-mat-delims.png differ diff --git a/tests/ref/math-mat-gap.png b/tests/ref/math-mat-gap.png index 5eb8460d..e4f87b59 100644 Binary files a/tests/ref/math-mat-gap.png and b/tests/ref/math-mat-gap.png differ diff --git a/tests/ref/math-mat-gaps.png b/tests/ref/math-mat-gaps.png index 38cf5247..5c954766 100644 Binary files a/tests/ref/math-mat-gaps.png and b/tests/ref/math-mat-gaps.png differ diff --git a/tests/ref/math-mat-semicolon.png b/tests/ref/math-mat-semicolon.png index abb5d1df..2a88818d 100644 Binary files a/tests/ref/math-mat-semicolon.png and b/tests/ref/math-mat-semicolon.png differ diff --git a/tests/ref/math-mat-sparse.png b/tests/ref/math-mat-sparse.png index 4d077931..e9f0d948 100644 Binary files a/tests/ref/math-mat-sparse.png and b/tests/ref/math-mat-sparse.png differ diff --git a/tests/ref/math-shorthands.png b/tests/ref/math-shorthands.png index ff26ce96..65b35aca 100644 Binary files a/tests/ref/math-shorthands.png and b/tests/ref/math-shorthands.png differ diff --git a/tests/ref/math-spacing-decorated.png b/tests/ref/math-spacing-decorated.png index e34066ea..4a785e71 100644 Binary files a/tests/ref/math-spacing-decorated.png and b/tests/ref/math-spacing-decorated.png differ diff --git a/tests/ref/math-table.png b/tests/ref/math-table.png index 5eb93218..75d25f3e 100644 Binary files a/tests/ref/math-table.png and b/tests/ref/math-table.png differ diff --git a/tests/ref/math-vec-align-explicit-alternating.png b/tests/ref/math-vec-align-explicit-alternating.png index cb29eb06..37e8dc06 100644 Binary files a/tests/ref/math-vec-align-explicit-alternating.png and b/tests/ref/math-vec-align-explicit-alternating.png differ diff --git a/tests/ref/math-vec-delim-set.png b/tests/ref/math-vec-delim-set.png index 8024d594..9e508fa7 100644 Binary files a/tests/ref/math-vec-delim-set.png and b/tests/ref/math-vec-delim-set.png differ diff --git a/tests/ref/math-vec-gap.png b/tests/ref/math-vec-gap.png index 06f8cf7d..e48b3e90 100644 Binary files a/tests/ref/math-vec-gap.png and b/tests/ref/math-vec-gap.png differ diff --git a/tests/ref/math-vec-wide.png b/tests/ref/math-vec-wide.png index 30853a00..9dc887a8 100644 Binary files a/tests/ref/math-vec-wide.png and b/tests/ref/math-vec-wide.png differ diff --git a/tests/suite/math/mat.typ b/tests/suite/math/mat.typ index 85f918ee..1f6716d7 100644 --- a/tests/suite/math/mat.typ +++ b/tests/suite/math/mat.typ @@ -212,3 +212,18 @@ $ mat(delim: angle.r, 1, 2; 3, 4) $ --- math-mat-delims-pair --- $ mat(delim: #(none, "["), 1, 2; 3, 4) $ $ mat(delim: #(sym.angle.r, sym.bracket.double.r), 1, 2; 3, 4) $ + +--- issue-1617-mat-align --- +#set page(width: auto) +$ mat(a, b; c, d) mat(x; y) $ + +$ x mat(a; c) + y mat(b; d) + = mat(a x+b y; c x+d y) $ + +$ mat( + -d_0, lambda_0, 0, 0, dots; + mu_1, -d_1, lambda_1, 0, dots; + 0, mu_2, -d_2, lambda_2, dots; + dots.v, dots.v, dots.v, dots.v, dots.down; + ) + mat(p_0; p_1; p_2; dots.v) $