diff --git a/crates/typst/src/math/matrix.rs b/crates/typst/src/math/matrix.rs index 4dadd756f..34e0611a6 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 6be86d9f5..defa46c1c 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 a756f37cd..f287f4dd2 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 88ff7a85c..ffd3e8068 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 5ed191821..8a9954adb 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 aa3332b96..ecf953038 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 b8fbdd745..b9b55d4d9 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 c9b966b29..8d0047bbe 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 000000000..bd4ea16fe 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 168b89139..f058a995d 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 5aca29cae..70f52dcf8 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 ce4b4eb8c..c1bf52d00 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 81af3bb5b..8e2bd498a 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 4ea9a264c..54105b55d 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 18807e0bf..d74ca9abf 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 e54e277c0..74a6c29bf 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 e35791307..746572fac 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 2e8c260a3..456b2550a 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 b105d9e35..eb84634e5 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 682fed228..3cba2588d 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 cb29eb067..37e8dc06a 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 97fe0a1f4..09ce93982 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 80966e524..3592c0cf5 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 0c14f1a79..0c508efc4 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 02a3c5820..c92743797 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 f3827c41f..c5881b139 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 3a272ce90..0e2a42a24 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 51e90a1f3..c5aa1e20a 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 b40fd36cf..75915689c 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 fc92fd4b3..b7a2b8d6c 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 06f1cdb34..84047952f 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 954e6d824..565975713 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 6ba589c84..9a859c3bc 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 5eb8460d7..e4f87b59b 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 38cf52475..5c954766c 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 abb5d1df8..2a88818d8 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 4d077931b..e9f0d948c 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 ff26ce96f..65b35acad 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 e34066ea2..4a785e715 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 5eb932181..75d25f3e4 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 cb29eb067..37e8dc06a 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 8024d594c..9e508fa7f 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 06f8cf7de..e48b3e902 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 30853a001..9dc887a8c 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 85f918eea..1f6716d7c 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) $