// Calculate minimum and maximum widths of cells that do not span
// multiple columns.
- let mut columns = [vec![0; n.x()], vec![0; n.x()]];
+ let mut unspanned_columns = [vec![0; n.x()], vec![0; n.x()]];
for cell in table.cells().filter(|cell| cell.col_span() == 1) {
let mut w = device.measure_cell_width(cell.inner());
if device.params().px_size.is_some() {
let x = cell.coord[X];
for i in 0..2 {
- if columns[i][x] < w[i] {
- columns[i][x] = w[i];
+ if unspanned_columns[i][x] < w[i] {
+ unspanned_columns[i][x] = w[i];
}
}
}
// Distribute widths of spanned columns.
- let mut columns = columns.map(|widths| {
- widths
- .into_iter()
- .map(|width| Row {
- unspanned: width,
- width,
- })
- .collect::<Vec<_>>()
- });
+ let mut columns = unspanned_columns.clone();
for cell in table.cells().filter(|cell| cell.col_span() > 1) {
let rect = cell.rect();
for i in 0..2 {
distribute_spanned_width(
w[i],
+ &unspanned_columns[i][rect[X].clone()],
&mut columns[i][rect[X].clone()],
&rules[X][rect[X].start..rect[X].end + 1],
);
}
if min_width > 0 {
for i in 0..2 {
- distribute_spanned_width(min_width, columns[i].as_mut_slice(), &rules[X]);
+ distribute_spanned_width(
+ min_width,
+ &unspanned_columns[i],
+ &mut columns[i],
+ &rules[X],
+ );
}
}
// to exceed the maximum width. This bollixes our interpolation
// algorithm later, so fix it up.
for i in 0..n.x() {
- if columns[0][i].width > columns[1][i].width {
- columns[1][i].width = columns[0][i].width;
+ if columns[0][i] > columns[1][i] {
+ columns[1][i] = columns[0][i];
}
}
let rule_widths = rules[X].iter().copied().sum::<usize>();
let table_widths = columns
.iter()
- .map(|row| row.iter().map(|row| row.width).sum::<usize>() + rule_widths)
+ .map(|row| row.iter().sum::<usize>() + rule_widths)
.collect::<SmallVec<[usize; 2]>>();
let cp_x = if table_widths[1] <= device.params().size[X] {
// Fits with minimum widths, so distribute the leftover space.
//Self::new_with_interpolated_widths()
Self::interpolate_row_widths(
- &table,
device.params(),
&columns[0],
&columns[1],
};
// Calculate heights of cells that do not span multiple rows.
- let mut rows = vec![Row::default(); n[Y]];
+ let mut unspanned_rows = vec![0; n[Y]];
for cell in table.cells().filter(|cell| cell.row_span() == 1) {
let rect = cell.rect();
let w = joined_width(&cp_x, rect[X].clone());
let h = device.measure_cell_height(cell.inner(), w);
- let row = &mut rows[cell.coord.y()];
- if h > row.unspanned {
- row.unspanned = h;
- row.width = h;
+ let row = &mut unspanned_rows[cell.coord.y()];
+ if h > *row {
+ *row = h;
}
}
// Distribute heights of spanned rows.
+ let mut rows = unspanned_rows.clone();
for cell in table.cells().filter(|cell| cell.row_span() > 1) {
let rect = cell.rect();
let w = joined_width(&cp_x, rect[X].clone());
let h = device.measure_cell_height(cell.inner(), w);
distribute_spanned_width(
h,
+ &unspanned_rows[rect[Y].clone()],
&mut rows[rect[Y].clone()],
&rules[Y][rect[Y].start..rect[Y].end + 1],
);
vec
}
- fn use_row_widths(rows: &[Row], rules: &[usize]) -> Vec<usize> {
+ fn use_row_widths(rows: &[usize], rules: &[usize]) -> Vec<usize> {
debug_assert_eq!(rows.len() + 1, rules.len());
let mut cp = Vec::with_capacity(2 * (rows.len()) + 1);
cp.push(0);
for (rule, row) in rules.iter().zip(rows.iter()) {
cp.push(*rule);
- cp.push(row.width);
+ cp.push(*row);
}
cp.push(*rules.last().unwrap());
}
fn interpolate_row_widths(
- table: &Table,
params: &Params,
- rows_min: &[Row],
- rows_max: &[Row],
+ rows_min: &[usize],
+ rows_max: &[usize],
w_min: usize,
w_max: usize,
rules: &[usize],
let mut w = wanted / 2;
let rows_mid = rows_min
.iter()
- .zip(rows_max.iter())
+ .copied()
+ .zip(rows_max.iter().copied())
.map(|(min, max)| {
- w += avail * (max.width - min.width);
+ w += avail * (max - min);
let extra = w / wanted;
w -= extra * wanted;
- Row {
- width: min.width + extra,
- unspanned: 0,
- }
+ min + extra
})
.collect::<Vec<_>>();
return Self::use_row_widths(&rows_mid, rules);
/// width, plus the width of the rule on the left, plus the width of the rule on
/// the right. That way each rule contributes to both the cell on its left and
/// on its right.)
-fn distribute_spanned_width(width: usize, rows: &mut [Row], rules: &[usize]) {
- debug_assert!(rows.len() >= 2);
- debug_assert!(rules.len() == rows.len() + 1);
-
- let n = rows.len();
- let total_unspanned = rows.iter().map(|row| row.unspanned).sum::<usize>()
- + (&rules[1..n - 1]).iter().copied().sum::<usize>();
+fn distribute_spanned_width(
+ width: usize,
+ unspanned: &[usize],
+ spanned: &mut [usize],
+ rules: &[usize],
+) {
+ let n = unspanned.len();
+ debug_assert!(n >= 2);
+ debug_assert_eq!(spanned.len(), n);
+ debug_assert_eq!(rules.len(), n + 1);
+
+ let total_unspanned =
+ unspanned.iter().sum::<usize>() + (&rules[1..n - 1]).iter().copied().sum::<usize>();
if total_unspanned >= width {
return;
}
- let d0 = rows.len();
+ let d0 = n;
let d1 = 2 * total_unspanned.max(1);
let d = if total_unspanned > 0 {
d0 * d1 * 2
for x in 0..n {
w += width * d1;
if total_unspanned > 0 {
- let mut unspanned = rows[x].unspanned * 2;
- if x < n - 1 {
+ let mut unspanned = unspanned[x] * 2;
+ if x + 1 < n {
unspanned += rules[x + 1];
}
if x > 0 {
}
w += width * unspanned * d0;
}
- rows[x].width = max(rows[x].width, w / d);
- w = w.checked_sub(rows[x].width * d).unwrap();
+ spanned[x] = max(spanned[x], w / d);
+ w = w.checked_sub(spanned[x] * d).unwrap();
}
}
-/// Row or column dimension.
-#[derive(Clone, Default)]
-struct Row {
- /// Width without considering rows (or columns) that span more than one row
- /// (or column).
- unspanned: usize,
-
- /// Width take spanned rows (or columns) into consideration.
- width: usize,
-}
-
/// Returns the width of the rule in `table` that is at offset `z` along axis
/// `a`, if rendered on `device`.
fn measure_rule(table: &Table, device: &dyn Device, a: Axis2, z: usize) -> usize {