From e6400861ab5c4d7ab437901b2334e5822c2693a5 Mon Sep 17 00:00:00 2001 From: Laurenz Date: Thu, 2 Feb 2023 14:40:16 +0100 Subject: [PATCH] Matrix baseline alignment --- library/src/math/matrix.rs | 30 ++++++++++++++++-------------- library/src/math/row.rs | 20 +++++++++++--------- tests/ref/math/content.png | Bin 5366 -> 5372 bytes tests/ref/math/matrix.png | Bin 4894 -> 7154 bytes tests/typ/math/matrix.typ | 12 ++++++++++-- 5 files changed, 37 insertions(+), 25 deletions(-) diff --git a/library/src/math/matrix.rs b/library/src/math/matrix.rs index 5f448901b..e5ae6a1d2 100644 --- a/library/src/math/matrix.rs +++ b/library/src/math/matrix.rs @@ -249,38 +249,40 @@ fn layout_mat_body(ctx: &mut MathContext, rows: &[Vec]) -> SourceResult return Ok(Frame::new(Size::zero())); } - let mut rcols = vec![Abs::zero(); ncols]; - let mut rrows = vec![Abs::zero(); nrows]; + let mut widths = vec![Abs::zero(); ncols]; + let mut ascents = vec![Abs::zero(); nrows]; + let mut descents = vec![Abs::zero(); nrows]; ctx.style(ctx.style.for_denominator()); let mut cols = vec![vec![]; ncols]; - for (row, rrow) in rows.iter().zip(&mut rrows) { - for ((cell, rcol), col) in row.iter().zip(&mut rcols).zip(&mut cols) { + for ((row, ascent), descent) in rows.iter().zip(&mut ascents).zip(&mut descents) { + for ((cell, rcol), col) in row.iter().zip(&mut widths).zip(&mut cols) { let cell = ctx.layout_row(cell)?; rcol.set_max(cell.width()); - rrow.set_max(cell.height()); + ascent.set_max(cell.ascent()); + descent.set_max(cell.descent()); col.push(cell); } } ctx.unstyle(); - let width = rcols.iter().sum::() + col_gap * (ncols - 1) as f64; - let height = rrows.iter().sum::() + row_gap * (nrows - 1) as f64; + let width = widths.iter().sum::() + col_gap * (ncols - 1) as f64; + let height = ascents.iter().sum::() + + descents.iter().sum::() + + row_gap * (nrows - 1) as f64; let size = Size::new(width, height); let mut frame = Frame::new(size); let mut x = Abs::zero(); - for (col, &rcol) in cols.into_iter().zip(&rcols) { + for (col, &rcol) in cols.into_iter().zip(&widths) { let points = alignments(&col); let mut y = Abs::zero(); - for (cell, &rrow) in col.into_iter().zip(&rrows) { + for ((cell, &ascent), &descent) in col.into_iter().zip(&ascents).zip(&descents) { let cell = cell.to_aligned_frame(ctx, &points, Align::Center); - let pos = Point::new( - x + (rcol - cell.width()) / 2.0, - y + (rrow - cell.height()) / 2.0, - ); + let pos = + Point::new(x + (rcol - cell.width()) / 2.0, y + ascent - cell.ascent()); frame.push_frame(pos, cell); - y += rrow + row_gap; + y += ascent + descent + row_gap; } x += rcol + col_gap; } diff --git a/library/src/math/row.rs b/library/src/math/row.rs index e66fc18e8..41136a9e3 100644 --- a/library/src/math/row.rs +++ b/library/src/math/row.rs @@ -17,8 +17,15 @@ impl MathRow { } pub fn height(&self) -> Abs { - let (ascent, descent) = self.extent(); - ascent + descent + self.ascent() + self.descent() + } + + pub fn ascent(&self) -> Abs { + self.0.iter().map(MathFragment::ascent).max().unwrap_or_default() + } + + pub fn descent(&self) -> Abs { + self.0.iter().map(MathFragment::descent).max().unwrap_or_default() } pub fn push( @@ -124,7 +131,8 @@ impl MathRow { } fn to_line_frame(self, ctx: &MathContext, points: &[Abs], align: Align) -> Frame { - let (ascent, descent) = self.extent(); + let ascent = self.ascent(); + let descent = self.descent(); let size = Size::new(Abs::zero(), ascent + descent); let mut frame = Frame::new(size); let mut x = Abs::zero(); @@ -161,12 +169,6 @@ impl MathRow { frame.size_mut().x = x; frame } - - fn extent(&self) -> (Abs, Abs) { - let ascent = self.0.iter().map(MathFragment::ascent).max().unwrap_or_default(); - let descent = self.0.iter().map(MathFragment::descent).max().unwrap_or_default(); - (ascent, descent) - } } impl From for MathRow diff --git a/tests/ref/math/content.png b/tests/ref/math/content.png index 5d222f92938b2f425bc28de2014f3f72dd7adec5..f02045269d3457004be6373aca7a27eaae2400d3 100644 GIT binary patch literal 5372 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 literal 5366 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 GD)Jx7KHMq* diff --git a/tests/typ/math/matrix.typ b/tests/typ/math/matrix.typ index 99e8fa19d..63294e039 100644 --- a/tests/typ/math/matrix.typ +++ b/tests/typ/math/matrix.typ @@ -13,12 +13,20 @@ $mat() dot --- // Test sparse matrix. -$mat( +$ mat( 1, 2, ..., 10; 2, 2, ..., 10; dots.v, dots.v, dots.down, dots.v; 10, 10, ..., 10; -)$ +) $ + +--- +// Test baseline alignment. +$ mat( + a, b^2; + sum_(x \ y) x, a^(1/2); + zeta, alpha; + ) $ --- // Test alternative delimiter.