summaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorWenzhuo Liu <mgt@oi-wiki.org>2024-06-04 23:42:02 +0800
committerGitHub <noreply@github.com>2024-06-04 15:42:02 +0000
commit681badf76a029e421415986aa3a46c0081d28470 (patch)
tree43ee7f1cad04f6ad41b23d329d9da6e472a06b0a /crates
parentada0f5da65ef41ac8fa11111839437c76edd3c68 (diff)
Pad matrix cell to make matrix have a consistent height (#4153)
Diffstat (limited to 'crates')
-rw-r--r--crates/typst/src/math/matrix.rs20
-rw-r--r--crates/typst/src/math/underover.rs26
2 files changed, 35 insertions, 11 deletions
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::<Abs>()
+ rows.iter().map(|row| padded_height(row.height())).sum::<Abs>()
+ 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);
}