summaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorMax <me@mkor.je>2024-09-26 14:30:47 +0000
committerGitHub <noreply@github.com>2024-09-26 14:30:47 +0000
commita40e068590895562f0d1a4aa17fe97b9bf5630a3 (patch)
treee4d5ca3264d056b7b8fc172492de921abbaeef07 /crates
parentcf35c2f44c6fdd8d6ef6f5df81f144db7355286d (diff)
Add alignment parameter to matrices and vectors (#4998)
Diffstat (limited to 'crates')
-rw-r--r--crates/typst/src/math/matrix.rs40
-rw-r--r--crates/typst/src/math/underover.rs6
2 files changed, 40 insertions, 6 deletions
diff --git a/crates/typst/src/math/matrix.rs b/crates/typst/src/math/matrix.rs
index 9f9b82bc..5b9b17a7 100644
--- a/crates/typst/src/math/matrix.rs
+++ b/crates/typst/src/math/matrix.rs
@@ -7,7 +7,8 @@ use crate::foundations::{
Smart, StyleChain, Value,
};
use crate::layout::{
- Abs, Axes, Em, FixedAlignment, Frame, FrameItem, Length, Point, Ratio, Rel, Size,
+ Abs, Axes, Em, FixedAlignment, Frame, FrameItem, HAlignment, Length, Point, Ratio,
+ Rel, Size,
};
use crate::math::{
alignments, scaled_font_size, stack, style_for_denominator, AlignmentResult,
@@ -29,7 +30,8 @@ const DEFAULT_STROKE_THICKNESS: Em = Em::new(0.05);
/// A column vector.
///
-/// Content in the vector's elements can be aligned with the `&` symbol.
+/// Content in the vector's elements can be aligned with the
+/// [`align`]($math.vec.align) parameter, or the `&` symbol.
///
/// # Example
/// ```example
@@ -47,6 +49,16 @@ pub struct VecElem {
#[default(DelimiterPair::PAREN)]
pub delim: DelimiterPair,
+ /// The horizontal alignment that each element should have.
+ ///
+ /// ```example
+ /// #set math.vec(align: right)
+ /// $ vec(-1, 1, -1) $
+ /// ```
+ #[resolve]
+ #[default(HAlignment::Center)]
+ pub align: HAlignment,
+
/// The gap between elements.
///
/// ```example
@@ -70,7 +82,7 @@ impl LayoutMath for Packed<VecElem> {
ctx,
styles,
self.children(),
- FixedAlignment::Center,
+ self.align(styles),
self.gap(styles),
LeftRightAlternator::Right,
)?;
@@ -87,7 +99,9 @@ impl LayoutMath for Packed<VecElem> {
/// special syntax of math function calls to define custom functions that take
/// 2D data.
///
-/// Content in cells that are in the same row can be aligned with the `&` symbol.
+/// Content in cells can be aligned with the [`align`]($math.mat.align)
+/// parameter, or content in cells that are in the same row can be aligned with
+/// the `&` symbol.
///
/// # Example
/// ```example
@@ -109,6 +123,16 @@ pub struct MatElem {
#[default(DelimiterPair::PAREN)]
pub delim: DelimiterPair,
+ /// The horizontal alignment that each cell should have.
+ ///
+ /// ```example
+ /// #set math.mat(align: right)
+ /// $ mat(-1, 1, 1; 1, -1, 1; 1, 1, -1) $
+ /// ```
+ #[resolve]
+ #[default(HAlignment::Center)]
+ pub align: HAlignment,
+
/// Draws augmentation lines in a matrix.
///
/// - `{none}`: No lines are drawn.
@@ -249,6 +273,7 @@ impl LayoutMath for Packed<MatElem> {
ctx,
styles,
rows,
+ self.align(styles),
augment,
Axes::new(self.column_gap(styles), self.row_gap(styles)),
self.span(),
@@ -454,6 +479,7 @@ fn layout_mat_body(
ctx: &mut MathContext,
styles: StyleChain,
rows: &[Vec<Content>],
+ align: FixedAlignment,
augment: Option<Augment<Abs>>,
gap: Axes<Rel<Abs>>,
span: Span,
@@ -538,7 +564,11 @@ fn layout_mat_body(
for (cell, &(ascent, descent)) in col.into_iter().zip(&heights) {
let cell = cell.into_line_frame(&points, LeftRightAlternator::Right);
let pos = Point::new(
- if points.is_empty() { x + (rcol - cell.width()) / 2.0 } else { x },
+ if points.is_empty() {
+ x + align.position(rcol - cell.width())
+ } else {
+ x
+ },
y + ascent - cell.ascent(),
);
diff --git a/crates/typst/src/math/underover.rs b/crates/typst/src/math/underover.rs
index f1789b7a..5ad7f457 100644
--- a/crates/typst/src/math/underover.rs
+++ b/crates/typst/src/math/underover.rs
@@ -476,7 +476,11 @@ pub(super) fn stack(
let mut y = Abs::zero();
for (i, row) in rows.into_iter().enumerate() {
- let x = align.position(width - row.width());
+ let x = if points.is_empty() {
+ align.position(width - row.width())
+ } else {
+ Abs::zero()
+ };
let ascent_padded_part = minimum_ascent_descent
.map_or(Abs::zero(), |(a, _)| (a - row.ascent()))
.max(Abs::zero());