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.
/// - 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
/// drawn both horizontally and vertically. Additionally, the style of the
/// 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
/// being drawn after the second row of the matrix. Accepts either an
/// 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.
/// For example, an offset of `2` would result in a vertical line being
/// drawn after the second column of the matrix. Accepts either an
/// 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}`,
/// takes on a thickness of 0.05em and square line caps.
///
/// ```example
/// $ mat(1, 0, 1; 0, 1, 2; augment: #2) $
/// // Equivalent to:
/// $ mat(1, 0, 1; 0, 1, 2; augment: #(-1)) $
/// ```
///
/// ```example
@ -200,15 +202,16 @@ impl LayoutMath for MatElem {
// validate inputs
let augment = self.augment(ctx.styles());
let rows = self.rows();
if let Some(aug) = &augment {
for &offset in &aug.hline.0 {
if offset == 0 || offset >= self.rows().len() {
if offset == 0 || offset.unsigned_abs() >= rows.len() {
bail!(
self.span(),
"cannot draw a horizontal line after row {} of a matrix with {} rows",
offset,
self.rows().len()
if offset < 0 { rows.len() as isize + offset } else { offset },
rows.len()
);
}
}
@ -216,11 +219,11 @@ impl LayoutMath for MatElem {
let ncols = self.rows().first().map_or(0, |row| row.len());
for &offset in &aug.vline.0 {
if offset == 0 || offset >= ncols {
if offset == 0 || offset.unsigned_abs() >= ncols {
bail!(
self.span(),
"cannot draw a vertical line after column {} of a matrix with {} columns",
offset,
if offset < 0 { ncols as isize + offset } else { offset },
ncols
);
}
@ -230,7 +233,7 @@ impl LayoutMath for MatElem {
let delim = self.delim(ctx.styles());
let frame = layout_mat_body(
ctx,
&self.rows(),
&rows,
augment,
Axes::new(self.column_gap(ctx.styles()), self.row_gap(ctx.styles())),
self.span(),
@ -472,7 +475,9 @@ fn layout_mat_body(
x += rcol;
// 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(
Point::with_x(x + half_gap.x),
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
for line in hline.0 {
let offset = (heights[0..line].iter().map(|&(a, b)| a + b).sum::<Abs>()
+ gap.y * (line - 1) as f64)
let real_line =
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;
frame.push(
@ -605,7 +612,7 @@ cast! {
d.into_value()
},
v: usize => Augment {
v: isize => Augment {
hline: Offsets::default(),
vline: Offsets(vec![v]),
stroke: Smart::Auto,
@ -632,11 +639,11 @@ cast! {
/// The offsets at which augmentation lines
/// should be drawn on a matrix.
#[derive(Debug, Default, Clone, Hash)]
pub struct Offsets(Vec<usize>);
pub struct Offsets(Vec<isize>);
cast! {
Offsets,
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<_>>()?),
}

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,
$ 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: -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: -1, stroke: 1pt + blue)) $,
)
---