mirror of
https://github.com/typst/typst
synced 2025-08-15 07:28:32 +08:00
use the name 'columns' and built-in next multiple of
This commit is contained in:
parent
cadbb3dcff
commit
87f430379e
@ -671,14 +671,14 @@ impl<'a> CellGrid<'a> {
|
|||||||
let mut rows = vec![];
|
let mut rows = vec![];
|
||||||
|
|
||||||
// Number of content columns: Always at least one.
|
// Number of content columns: Always at least one.
|
||||||
let c = tracks.x.len().max(1);
|
let columns = tracks.x.len().max(1);
|
||||||
|
|
||||||
// Number of content rows: At least as many as given, but also at least
|
// Number of content rows: At least as many as given, but also at least
|
||||||
// as many as needed to place each item.
|
// as many as needed to place each item.
|
||||||
let r = {
|
let r = {
|
||||||
let len = entries.len();
|
let len = entries.len();
|
||||||
let given = tracks.y.len();
|
let given = tracks.y.len();
|
||||||
let needed = len / c + (len % c).clamp(0, 1);
|
let needed = len / columns + (len % columns).clamp(0, 1);
|
||||||
given.max(needed)
|
given.max(needed)
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -690,7 +690,7 @@ impl<'a> CellGrid<'a> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Collect content and gutter columns.
|
// Collect content and gutter columns.
|
||||||
for x in 0..c {
|
for x in 0..columns {
|
||||||
cols.push(get_or(tracks.x, x, auto));
|
cols.push(get_or(tracks.x, x, auto));
|
||||||
if has_gutter {
|
if has_gutter {
|
||||||
cols.push(get_or(gutter.x, x, zero));
|
cols.push(get_or(gutter.x, x, zero));
|
||||||
@ -987,24 +987,18 @@ impl<'x> CellGridResolver<'_, '_, 'x> {
|
|||||||
// automatically-positioned cell.
|
// automatically-positioned cell.
|
||||||
let mut auto_index: usize = 0;
|
let mut auto_index: usize = 0;
|
||||||
|
|
||||||
// We have to rebuild the grid to account for arbitrary positions.
|
// We have to rebuild the grid to account for fixed cell positions.
|
||||||
|
//
|
||||||
// Create at least 'children.len()' positions, since there could be at
|
// Create at least 'children.len()' positions, since there could be at
|
||||||
// least 'children.len()' cells (if no explicit lines were specified),
|
// least 'children.len()' cells (if no explicit lines were specified),
|
||||||
// even though some of them might be placed in arbitrary positions and
|
// even though some of them might be placed in fixed positions and thus
|
||||||
// thus cause the grid to expand.
|
// cause the grid to expand.
|
||||||
//
|
//
|
||||||
// Additionally, make sure we allocate up to the next multiple of
|
// Additionally, make sure we allocate up to the next multiple of
|
||||||
// 'columns', since each row will have 'columns' cells, even if the
|
// 'columns', since each row will have 'columns' cells, even if the
|
||||||
// last few cells weren't explicitly specified by the user.
|
// last few cells weren't explicitly specified by the user.
|
||||||
//
|
|
||||||
// We apply '% columns' twice so that the amount of cells potentially
|
|
||||||
// missing is zero when 'children.len()' is already a multiple of
|
|
||||||
// 'columns' (thus 'children.len() % columns' would be zero).
|
|
||||||
let children = children.into_iter();
|
let children = children.into_iter();
|
||||||
let Some(child_count) = children
|
let Some(child_count) = children.len().checked_next_multiple_of(columns) else {
|
||||||
.len()
|
|
||||||
.checked_add((columns - children.len() % columns) % columns)
|
|
||||||
else {
|
|
||||||
bail!(self.span, "too many cells or lines were given")
|
bail!(self.span, "too many cells or lines were given")
|
||||||
};
|
};
|
||||||
let mut resolved_cells: Vec<Option<Entry>> = Vec::with_capacity(child_count);
|
let mut resolved_cells: Vec<Option<Entry>> = Vec::with_capacity(child_count);
|
||||||
@ -1057,7 +1051,7 @@ impl<'x> CellGridResolver<'_, '_, 'x> {
|
|||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
fn resolve_grid_child<T, I>(
|
fn resolve_grid_child<T, I>(
|
||||||
&mut self,
|
&mut self,
|
||||||
c: usize,
|
columns: usize,
|
||||||
pending_hlines: &mut Vec<(Span, Line, bool)>,
|
pending_hlines: &mut Vec<(Span, Line, bool)>,
|
||||||
pending_vlines: &mut Vec<(Span, Line)>,
|
pending_vlines: &mut Vec<(Span, Line)>,
|
||||||
header: &mut Option<Header>,
|
header: &mut Option<Header>,
|
||||||
@ -1111,7 +1105,7 @@ impl<'x> CellGridResolver<'_, '_, 'x> {
|
|||||||
*repeat_header = repeat;
|
*repeat_header = repeat;
|
||||||
|
|
||||||
first_available_row =
|
first_available_row =
|
||||||
find_next_empty_row(resolved_cells, local_auto_index, c);
|
find_next_empty_row(resolved_cells, local_auto_index, columns);
|
||||||
|
|
||||||
// If any cell in the header is automatically positioned,
|
// If any cell in the header is automatically positioned,
|
||||||
// have it skip to the next empty row. This is to avoid
|
// have it skip to the next empty row. This is to avoid
|
||||||
@ -1122,7 +1116,7 @@ impl<'x> CellGridResolver<'_, '_, 'x> {
|
|||||||
// latest auto-position cell, since each auto-position cell
|
// latest auto-position cell, since each auto-position cell
|
||||||
// always occupies the first available position after the
|
// always occupies the first available position after the
|
||||||
// previous one. Therefore, this will be >= auto_index.
|
// previous one. Therefore, this will be >= auto_index.
|
||||||
local_auto_index = first_available_row * c;
|
local_auto_index = first_available_row * columns;
|
||||||
|
|
||||||
(Some(items), None)
|
(Some(items), None)
|
||||||
}
|
}
|
||||||
@ -1137,9 +1131,9 @@ impl<'x> CellGridResolver<'_, '_, 'x> {
|
|||||||
*repeat_footer = repeat;
|
*repeat_footer = repeat;
|
||||||
|
|
||||||
first_available_row =
|
first_available_row =
|
||||||
find_next_empty_row(resolved_cells, local_auto_index, c);
|
find_next_empty_row(resolved_cells, local_auto_index, columns);
|
||||||
|
|
||||||
local_auto_index = first_available_row * c;
|
local_auto_index = first_available_row * columns;
|
||||||
|
|
||||||
(Some(items), None)
|
(Some(items), None)
|
||||||
}
|
}
|
||||||
@ -1159,7 +1153,7 @@ impl<'x> CellGridResolver<'_, '_, 'x> {
|
|||||||
skip_auto_index_through_fully_merged_rows(
|
skip_auto_index_through_fully_merged_rows(
|
||||||
resolved_cells,
|
resolved_cells,
|
||||||
&mut local_auto_index,
|
&mut local_auto_index,
|
||||||
c,
|
columns,
|
||||||
);
|
);
|
||||||
|
|
||||||
// When no 'y' is specified for the hline, we place
|
// When no 'y' is specified for the hline, we place
|
||||||
@ -1184,7 +1178,7 @@ impl<'x> CellGridResolver<'_, '_, 'x> {
|
|||||||
// that header's first row. Similarly for footers.
|
// that header's first row. Similarly for footers.
|
||||||
local_auto_index
|
local_auto_index
|
||||||
.checked_sub(1)
|
.checked_sub(1)
|
||||||
.map_or(0, |last_auto_index| last_auto_index / c + 1)
|
.map_or(0, |last_auto_index| last_auto_index / columns + 1)
|
||||||
});
|
});
|
||||||
if end.is_some_and(|end| end.get() < start) {
|
if end.is_some_and(|end| end.get() < start) {
|
||||||
bail!(span, "line cannot end before it starts");
|
bail!(span, "line cannot end before it starts");
|
||||||
@ -1233,8 +1227,8 @@ impl<'x> CellGridResolver<'_, '_, 'x> {
|
|||||||
// automatically positioned cell. Same for footers.
|
// automatically positioned cell. Same for footers.
|
||||||
local_auto_index
|
local_auto_index
|
||||||
.checked_sub(1)
|
.checked_sub(1)
|
||||||
.filter(|_| local_auto_index > first_available_row * c)
|
.filter(|_| local_auto_index > first_available_row * columns)
|
||||||
.map_or(0, |last_auto_index| last_auto_index % c + 1)
|
.map_or(0, |last_auto_index| last_auto_index % columns + 1)
|
||||||
});
|
});
|
||||||
if end.is_some_and(|end| end.get() < start) {
|
if end.is_some_and(|end| end.get() < start) {
|
||||||
bail!(span, "line cannot end before it starts");
|
bail!(span, "line cannot end before it starts");
|
||||||
@ -1267,15 +1261,15 @@ impl<'x> CellGridResolver<'_, '_, 'x> {
|
|||||||
resolved_cells,
|
resolved_cells,
|
||||||
&mut local_auto_index,
|
&mut local_auto_index,
|
||||||
first_available_row,
|
first_available_row,
|
||||||
c,
|
columns,
|
||||||
row_group_data.is_some(),
|
row_group_data.is_some(),
|
||||||
)
|
)
|
||||||
.at(cell_span)?
|
.at(cell_span)?
|
||||||
};
|
};
|
||||||
let x = resolved_index % c;
|
let x = resolved_index % columns;
|
||||||
let y = resolved_index / c;
|
let y = resolved_index / columns;
|
||||||
|
|
||||||
if colspan > c - x {
|
if colspan > columns - x {
|
||||||
bail!(
|
bail!(
|
||||||
cell_span,
|
cell_span,
|
||||||
"cell's colspan would cause it to exceed the available column(s)";
|
"cell's colspan would cause it to exceed the available column(s)";
|
||||||
@ -1283,7 +1277,7 @@ impl<'x> CellGridResolver<'_, '_, 'x> {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
let Some(largest_index) = c
|
let Some(largest_index) = columns
|
||||||
.checked_mul(rowspan - 1)
|
.checked_mul(rowspan - 1)
|
||||||
.and_then(|full_rowspan_offset| {
|
.and_then(|full_rowspan_offset| {
|
||||||
resolved_index.checked_add(full_rowspan_offset)
|
resolved_index.checked_add(full_rowspan_offset)
|
||||||
@ -1310,7 +1304,7 @@ impl<'x> CellGridResolver<'_, '_, 'x> {
|
|||||||
first_available_row,
|
first_available_row,
|
||||||
y,
|
y,
|
||||||
rowspan,
|
rowspan,
|
||||||
c,
|
columns,
|
||||||
)
|
)
|
||||||
.at(cell_span)?,
|
.at(cell_span)?,
|
||||||
);
|
);
|
||||||
@ -1322,7 +1316,7 @@ impl<'x> CellGridResolver<'_, '_, 'x> {
|
|||||||
|
|
||||||
if largest_index >= resolved_cells.len() {
|
if largest_index >= resolved_cells.len() {
|
||||||
// Ensure the length of the vector of resolved cells is
|
// Ensure the length of the vector of resolved cells is
|
||||||
// always a multiple of 'c' by pushing full rows every
|
// always a multiple of 'columns' by pushing full rows every
|
||||||
// time. Here, we add enough absent positions (later
|
// time. Here, we add enough absent positions (later
|
||||||
// converted to empty cells) to ensure the last row in the
|
// converted to empty cells) to ensure the last row in the
|
||||||
// new vector length is completely filled. This is
|
// new vector length is completely filled. This is
|
||||||
@ -1332,7 +1326,7 @@ impl<'x> CellGridResolver<'_, '_, 'x> {
|
|||||||
// resolved as empty cells in a second loop below.
|
// resolved as empty cells in a second loop below.
|
||||||
let Some(new_len) = largest_index
|
let Some(new_len) = largest_index
|
||||||
.checked_add(1)
|
.checked_add(1)
|
||||||
.and_then(|new_len| new_len.checked_add((c - new_len % c) % c))
|
.and_then(|new_len| new_len.checked_next_multiple_of(columns))
|
||||||
else {
|
else {
|
||||||
bail!(cell_span, "cell position too large")
|
bail!(cell_span, "cell position too large")
|
||||||
};
|
};
|
||||||
@ -1367,7 +1361,7 @@ impl<'x> CellGridResolver<'_, '_, 'x> {
|
|||||||
// pointing to the original cell as its parent.
|
// pointing to the original cell as its parent.
|
||||||
for rowspan_offset in 0..rowspan {
|
for rowspan_offset in 0..rowspan {
|
||||||
let spanned_y = y + rowspan_offset;
|
let spanned_y = y + rowspan_offset;
|
||||||
let first_row_index = resolved_index + c * rowspan_offset;
|
let first_row_index = resolved_index + columns * rowspan_offset;
|
||||||
for (colspan_offset, slot) in
|
for (colspan_offset, slot) in
|
||||||
resolved_cells[first_row_index..][..colspan].iter_mut().enumerate()
|
resolved_cells[first_row_index..][..colspan].iter_mut().enumerate()
|
||||||
{
|
{
|
||||||
@ -1395,13 +1389,13 @@ impl<'x> CellGridResolver<'_, '_, 'x> {
|
|||||||
None => {
|
None => {
|
||||||
// Empty header/footer: consider the header/footer to be
|
// Empty header/footer: consider the header/footer to be
|
||||||
// at the next empty row after the latest auto index.
|
// at the next empty row after the latest auto index.
|
||||||
local_auto_index = first_available_row * c;
|
local_auto_index = first_available_row * columns;
|
||||||
let group_start = first_available_row;
|
let group_start = first_available_row;
|
||||||
let group_end = group_start + 1;
|
let group_end = group_start + 1;
|
||||||
|
|
||||||
if resolved_cells.len() <= c * group_start {
|
if resolved_cells.len() <= columns * group_start {
|
||||||
// Ensure the automatically chosen row actually exists.
|
// Ensure the automatically chosen row actually exists.
|
||||||
resolved_cells.resize_with(c * (group_start + 1), || None);
|
resolved_cells.resize_with(columns * (group_start + 1), || None);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Even though this header or footer is fully empty, we add one
|
// Even though this header or footer is fully empty, we add one
|
||||||
|
Loading…
x
Reference in New Issue
Block a user