From: Ben Pfaff Date: Tue, 14 Jan 2025 17:59:09 +0000 (-0800) Subject: work X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=550fa7be20e2d5a073cdda62326c6ea888d3fc3f;p=pspp work --- diff --git a/rust/pspp/src/output/render.rs b/rust/pspp/src/output/render.rs index 6a8752cde3..5057a6bb36 100644 --- a/rust/pspp/src/output/render.rs +++ b/rust/pspp/src/output/render.rs @@ -334,7 +334,7 @@ impl Page { // 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() { @@ -356,22 +356,14 @@ impl Page { 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::>() - }); + let mut columns = unspanned_columns.clone(); for cell in table.cells().filter(|cell| cell.col_span() > 1) { let rect = cell.rect(); @@ -379,6 +371,7 @@ impl Page { 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], ); @@ -386,7 +379,12 @@ impl Page { } 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], + ); } } @@ -394,8 +392,8 @@ impl Page { // 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]; } } @@ -403,7 +401,7 @@ impl Page { let rule_widths = rules[X].iter().copied().sum::(); let table_widths = columns .iter() - .map(|row| row.iter().map(|row| row.width).sum::() + rule_widths) + .map(|row| row.iter().sum::() + rule_widths) .collect::>(); let cp_x = if table_widths[1] <= device.params().size[X] { @@ -413,7 +411,6 @@ impl Page { // 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], @@ -428,27 +425,28 @@ impl Page { }; // 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], ); @@ -492,14 +490,14 @@ impl Page { vec } - fn use_row_widths(rows: &[Row], rules: &[usize]) -> Vec { + fn use_row_widths(rows: &[usize], rules: &[usize]) -> Vec { 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()); @@ -507,10 +505,9 @@ impl Page { } 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], @@ -520,15 +517,13 @@ impl Page { 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::>(); return Self::use_row_widths(&rows_mid, rules); @@ -773,18 +768,24 @@ struct Map { /// 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::() - + (&rules[1..n - 1]).iter().copied().sum::(); +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::() + (&rules[1..n - 1]).iter().copied().sum::(); 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 @@ -795,8 +796,8 @@ fn distribute_spanned_width(width: usize, rows: &mut [Row], rules: &[usize]) { 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 { @@ -804,22 +805,11 @@ fn distribute_spanned_width(width: usize, rows: &mut [Row], rules: &[usize]) { } 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 {