Pad matrix cell to make matrix have a consistent height (#4153)

This commit is contained in:
Wenzhuo Liu 2024-06-04 23:42:02 +08:00 committed by GitHub
parent ada0f5da65
commit 681badf76a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
45 changed files with 50 additions and 11 deletions

View File

@ -22,7 +22,7 @@ use crate::visualize::{FixedStroke, Geometry, LineCap, Shape, Stroke};
use super::delimiter_alignment; 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 DEFAULT_COL_GAP: Em = Em::new(0.5);
const VERTICAL_PADDING: Ratio = Ratio::new(0.1); const VERTICAL_PADDING: Ratio = Ratio::new(0.1);
const DEFAULT_STROKE_THICKNESS: Em = Em::new(0.05); const DEFAULT_STROKE_THICKNESS: Em = Em::new(0.05);
@ -441,8 +441,12 @@ fn layout_vec_body(
for child in column { for child in column {
flat.push(ctx.layout_into_run(child, styles.chain(&denom_style))?); flat.push(ctx.layout_into_run(child, styles.chain(&denom_style))?);
} }
// We pad ascent and descent with the ascent and descent of the paren
Ok(stack(flat, align, gap, 0, alternator)) // 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. /// Layout the inner contents of a matrix.
@ -499,12 +503,18 @@ fn layout_mat_body(
let mut cols = vec![vec![]; ncols]; let mut cols = vec![vec![]; ncols];
let denom_style = style_for_denominator(styles); 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 (row, (ascent, descent)) in rows.iter().zip(&mut heights) {
for (cell, col) in row.iter().zip(&mut cols) { for (cell, col) in row.iter().zip(&mut cols) {
let cell = ctx.layout_into_run(cell, styles.chain(&denom_style))?; let cell = ctx.layout_into_run(cell, styles.chain(&denom_style))?;
ascent.set_max(cell.ascent()); ascent.set_max(cell.ascent().max(paren.ascent));
descent.set_max(cell.descent()); descent.set_max(cell.descent().max(paren.descent));
col.push(cell); col.push(cell);
} }

View File

@ -291,8 +291,14 @@ fn layout_underoverspreader(
baseline = rows.len() - 1; baseline = rows.len() - 1;
} }
let frame = let frame = stack(
stack(rows, FixedAlignment::Center, gap, baseline, LeftRightAlternator::Right); rows,
FixedAlignment::Center,
gap,
baseline,
LeftRightAlternator::Right,
None,
);
ctx.push(FrameFragment::new(ctx, styles, frame).with_class(body_class)); ctx.push(FrameFragment::new(ctx, styles, frame).with_class(body_class));
Ok(()) Ok(())
@ -309,6 +315,7 @@ pub(super) fn stack(
gap: Abs, gap: Abs,
baseline: usize, baseline: usize,
alternator: LeftRightAlternator, alternator: LeftRightAlternator,
minimum_ascent_descent: Option<(Abs, Abs)>,
) -> Frame { ) -> Frame {
let rows: Vec<_> = rows.into_iter().flat_map(|r| r.rows()).collect(); let rows: Vec<_> = rows.into_iter().flat_map(|r| r.rows()).collect();
let AlignmentResult { points, width } = alignments(&rows); let AlignmentResult { points, width } = alignments(&rows);
@ -317,20 +324,27 @@ pub(super) fn stack(
.map(|row| row.into_line_frame(&points, alternator)) .map(|row| row.into_line_frame(&points, alternator))
.collect(); .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( let mut frame = Frame::soft(Size::new(
width, 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, + rows.len().saturating_sub(1) as f64 * gap,
)); ));
let mut y = Abs::zero(); let mut y = Abs::zero();
for (i, row) in rows.into_iter().enumerate() { for (i, row) in rows.into_iter().enumerate() {
let x = align.position(width - row.width()); 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 { 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); frame.push_frame(pos, row);
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 669 B

After

Width:  |  Height:  |  Size: 674 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 757 B

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 578 B

After

Width:  |  Height:  |  Size: 568 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 796 B

After

Width:  |  Height:  |  Size: 793 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 308 B

After

Width:  |  Height:  |  Size: 343 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 285 B

After

Width:  |  Height:  |  Size: 340 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 984 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 908 B

After

Width:  |  Height:  |  Size: 1009 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 896 B

After

Width:  |  Height:  |  Size: 992 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 916 B

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 930 B

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 837 B

After

Width:  |  Height:  |  Size: 802 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 580 B

After

Width:  |  Height:  |  Size: 620 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 521 B

After

Width:  |  Height:  |  Size: 552 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 489 B

After

Width:  |  Height:  |  Size: 496 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 493 B

After

Width:  |  Height:  |  Size: 489 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 898 B

After

Width:  |  Height:  |  Size: 882 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 770 B

After

Width:  |  Height:  |  Size: 784 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 908 B

After

Width:  |  Height:  |  Size: 1009 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 196 B

After

Width:  |  Height:  |  Size: 203 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 397 B

After

Width:  |  Height:  |  Size: 420 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 591 B

After

Width:  |  Height:  |  Size: 620 B

View File

@ -212,3 +212,18 @@ $ mat(delim: angle.r, 1, 2; 3, 4) $
--- math-mat-delims-pair --- --- math-mat-delims-pair ---
$ mat(delim: #(none, "["), 1, 2; 3, 4) $ $ mat(delim: #(none, "["), 1, 2; 3, 4) $
$ mat(delim: #(sym.angle.r, sym.bracket.double.r), 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) $