Add support for negative augment indexes (#2372)

This commit is contained in:
SekoiaTree 2023-10-22 13:22:34 +02:00 committed by GitHub
parent 208711203e
commit 3faad6bc5d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 26 additions and 15 deletions

View File

@ -97,7 +97,7 @@ pub struct MatElem {
/// ///
/// - `{none}`: No lines are drawn. /// - `{none}`: No lines are drawn.
/// - A single number: A vertical augmentation line is drawn /// - A single number: A vertical augmentation line is drawn
/// after the specified column number. /// after the specified column number. Negative numbers start from the end.
/// - A dictionary: With a dictionary, multiple augmentation lines can be /// - A dictionary: With a dictionary, multiple augmentation lines can be
/// drawn both horizontally and vertically. Additionally, the style of the /// drawn both horizontally and vertically. Additionally, the style of the
/// lines can be set. The dictionary can contain the following keys: /// lines can be set. The dictionary can contain the following keys:
@ -105,17 +105,19 @@ pub struct MatElem {
/// For example, an offset of `2` would result in a horizontal line /// For example, an offset of `2` would result in a horizontal line
/// being drawn after the second row of the matrix. Accepts either an /// being drawn after the second row of the matrix. Accepts either an
/// integer for a single line, or an array of integers /// integer for a single line, or an array of integers
/// for multiple lines. /// for multiple lines. Like for a single number, negative numbers start from the end.
/// - `vline`: The offsets at which vertical lines should be drawn. /// - `vline`: The offsets at which vertical lines should be drawn.
/// For example, an offset of `2` would result in a vertical line being /// For example, an offset of `2` would result in a vertical line being
/// drawn after the second column of the matrix. Accepts either an /// drawn after the second column of the matrix. Accepts either an
/// integer for a single line, or an array of integers /// integer for a single line, or an array of integers
/// for multiple lines. /// for multiple lines. Like for a single number, negative numbers start from the end.
/// - `stroke`: How to [stroke]($stroke) the line. If set to `{auto}`, /// - `stroke`: How to [stroke]($stroke) the line. If set to `{auto}`,
/// takes on a thickness of 0.05em and square line caps. /// takes on a thickness of 0.05em and square line caps.
/// ///
/// ```example /// ```example
/// $ mat(1, 0, 1; 0, 1, 2; augment: #2) $ /// $ mat(1, 0, 1; 0, 1, 2; augment: #2) $
/// // Equivalent to:
/// $ mat(1, 0, 1; 0, 1, 2; augment: #(-1)) $
/// ``` /// ```
/// ///
/// ```example /// ```example
@ -200,15 +202,16 @@ impl LayoutMath for MatElem {
// validate inputs // validate inputs
let augment = self.augment(ctx.styles()); let augment = self.augment(ctx.styles());
let rows = self.rows();
if let Some(aug) = &augment { if let Some(aug) = &augment {
for &offset in &aug.hline.0 { for &offset in &aug.hline.0 {
if offset == 0 || offset >= self.rows().len() { if offset == 0 || offset.unsigned_abs() >= rows.len() {
bail!( bail!(
self.span(), self.span(),
"cannot draw a horizontal line after row {} of a matrix with {} rows", "cannot draw a horizontal line after row {} of a matrix with {} rows",
offset, if offset < 0 { rows.len() as isize + offset } else { offset },
self.rows().len() rows.len()
); );
} }
} }
@ -216,11 +219,11 @@ impl LayoutMath for MatElem {
let ncols = self.rows().first().map_or(0, |row| row.len()); let ncols = self.rows().first().map_or(0, |row| row.len());
for &offset in &aug.vline.0 { for &offset in &aug.vline.0 {
if offset == 0 || offset >= ncols { if offset == 0 || offset.unsigned_abs() >= ncols {
bail!( bail!(
self.span(), self.span(),
"cannot draw a vertical line after column {} of a matrix with {} columns", "cannot draw a vertical line after column {} of a matrix with {} columns",
offset, if offset < 0 { ncols as isize + offset } else { offset },
ncols ncols
); );
} }
@ -230,7 +233,7 @@ impl LayoutMath for MatElem {
let delim = self.delim(ctx.styles()); let delim = self.delim(ctx.styles());
let frame = layout_mat_body( let frame = layout_mat_body(
ctx, ctx,
&self.rows(), &rows,
augment, augment,
Axes::new(self.column_gap(ctx.styles()), self.row_gap(ctx.styles())), Axes::new(self.column_gap(ctx.styles()), self.row_gap(ctx.styles())),
self.span(), self.span(),
@ -472,7 +475,9 @@ fn layout_mat_body(
x += rcol; x += rcol;
// If a vertical line should be inserted after this column // If a vertical line should be inserted after this column
if vline.0.contains(&(index + 1)) { if vline.0.contains(&(index as isize + 1))
|| vline.0.contains(&(1 - ((ncols - index) as isize)))
{
frame.push( frame.push(
Point::with_x(x + half_gap.x), Point::with_x(x + half_gap.x),
line_item(total_height, true, stroke.clone(), span), line_item(total_height, true, stroke.clone(), span),
@ -488,8 +493,10 @@ fn layout_mat_body(
// This allows the horizontal lines to be laid out // This allows the horizontal lines to be laid out
for line in hline.0 { for line in hline.0 {
let offset = (heights[0..line].iter().map(|&(a, b)| a + b).sum::<Abs>() let real_line =
+ gap.y * (line - 1) as f64) if line < 0 { nrows - line.unsigned_abs() } else { line as usize };
let offset = (heights[0..real_line].iter().map(|&(a, b)| a + b).sum::<Abs>()
+ gap.y * (real_line - 1) as f64)
+ half_gap.y; + half_gap.y;
frame.push( frame.push(
@ -605,7 +612,7 @@ cast! {
d.into_value() d.into_value()
}, },
v: usize => Augment { v: isize => Augment {
hline: Offsets::default(), hline: Offsets::default(),
vline: Offsets(vec![v]), vline: Offsets(vec![v]),
stroke: Smart::Auto, stroke: Smart::Auto,
@ -632,11 +639,11 @@ cast! {
/// The offsets at which augmentation lines /// The offsets at which augmentation lines
/// should be drawn on a matrix. /// should be drawn on a matrix.
#[derive(Debug, Default, Clone, Hash)] #[derive(Debug, Default, Clone, Hash)]
pub struct Offsets(Vec<usize>); pub struct Offsets(Vec<isize>);
cast! { cast! {
Offsets, Offsets,
self => self.0.into_value(), self => self.0.into_value(),
v: usize => Self(vec![v]), v: isize => Self(vec![v]),
v: Array => Self(v.into_iter().map(Value::cast).collect::<StrResult<_>>()?), v: Array => Self(v.into_iter().map(Value::cast).collect::<StrResult<_>>()?),
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 43 KiB

View File

@ -72,9 +72,13 @@ $ mat(#1, #(foo: "bar")) $
gutter: 10pt, gutter: 10pt,
$ mat(10, 2, 3, 4; 5, 6, 7, 8; augment: #3) $, $ mat(10, 2, 3, 4; 5, 6, 7, 8; augment: #3) $,
$ mat(10, 2, 3, 4; 5, 6, 7, 8; augment: #(-1)) $,
$ mat(100, 2, 3; 4, 5, 6; 7, 8, 9; augment: #(hline: 2)) $, $ mat(100, 2, 3; 4, 5, 6; 7, 8, 9; augment: #(hline: 2)) $,
$ mat(100, 2, 3; 4, 5, 6; 7, 8, 9; augment: #(hline: -1)) $,
$ mat(100, 2, 3; 4, 5, 6; 7, 8, 9; augment: #(hline: 1, vline: 1)) $, $ mat(100, 2, 3; 4, 5, 6; 7, 8, 9; augment: #(hline: 1, vline: 1)) $,
$ mat(100, 2, 3; 4, 5, 6; 7, 8, 9; augment: #(hline: -2, vline: -2)) $,
$ mat(100, 2, 3; 4, 5, 6; 7, 8, 9; augment: #(vline: 2, stroke: 1pt + blue)) $, $ mat(100, 2, 3; 4, 5, 6; 7, 8, 9; augment: #(vline: 2, stroke: 1pt + blue)) $,
$ mat(100, 2, 3; 4, 5, 6; 7, 8, 9; augment: #(vline: -1, stroke: 1pt + blue)) $,
) )
--- ---