// Calculate minimum and maximum widths of cells that do not span
// multiple columns.
let mut columns = [vec![0; table.n.x()], vec![0; table.n.x()]];
- for y in 0..table.n[Y] {
- for x in table.iter_x(y) {
- let coord = Coord2::new(x, y);
- let contents = table.get(coord);
- if !contents.is_top_left() || contents.col_span() != 1 {
- continue;
- }
-
- let mut w = device.measure_cell_width(contents.inner());
- if device.params().px_size.is_some() {
- if let Some(region) = table.heading_region(coord) {
- let wr = &heading_widths[region];
- if w[0] < wr[0] {
- w[0] = wr[0];
- if w[0] > w[1] {
- w[1] = w[0];
- }
- } else if w[1] > wr[1] {
- w[1] = wr[1];
- if w[1] < w[0] {
- w[0] = w[1];
- }
+ 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() {
+ if let Some(region) = table.heading_region(cell.coord) {
+ let wr = &heading_widths[region];
+ if w[0] < wr[0] {
+ w[0] = wr[0];
+ if w[0] > w[1] {
+ w[1] = w[0];
+ }
+ } else if w[1] > wr[1] {
+ w[1] = wr[1];
+ if w[1] < w[0] {
+ w[0] = w[1];
}
}
}
+ }
- for i in 0..2 {
- if columns[i][x] < w[i] {
- columns[i][x] = w[i];
- }
+ let x = cell.coord[X];
+ for i in 0..2 {
+ if columns[i][x] < w[i] {
+ columns[i][x] = w[i];
}
}
}
})
.collect::<Vec<_>>()
});
- for y in 0..table.n[Y] {
- for x in table.iter_x(y) {
- let coord = Coord2::new(x, y);
- let contents = table.get(coord);
- if !contents.is_top_left() || contents.col_span() == 1 {
- continue;
- }
- let rect = contents.rect();
-
- let w = device.measure_cell_width(contents.inner());
- for i in 0..2 {
- distribute_spanned_width(
- w[i],
- &mut columns[i][rect[X].clone()],
- &rules[X][rect[X].start..rect[X].end + 1],
- );
- }
+ for cell in table.cells().filter(|cell| cell.col_span() > 1) {
+ let rect = cell.rect();
+
+ let w = device.measure_cell_width(cell.inner());
+ for i in 0..2 {
+ distribute_spanned_width(
+ w[i],
+ &mut columns[i][rect[X].clone()],
+ &rules[X][rect[X].start..rect[X].end + 1],
+ );
}
}
if min_width > 0 {
// Calculate heights of cells that do not span multiple rows.
let mut rows = vec![Row::default(); table.n[Y]];
- for y in 0..table.n[Y] {
- let row = &mut rows[y];
- for x in table.iter_x(y) {
- let coord = Coord2::new(x, y);
- let contents = table.get(coord);
- if !contents.is_top_left() {
- continue;
- }
- let rect = contents.rect();
-
- if contents.row_span() == 1 {
- let w = page.joined_width(X, rect[X].clone());
- let h = device.measure_cell_height(contents.inner(), w);
- if h > row.unspanned {
- row.unspanned = h;
- row.width = h;
- }
- }
+ for cell in table.cells().filter(|cell| cell.row_span() == 1) {
+ let rect = cell.rect();
+
+ let w = page.joined_width(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;
}
}
// Distribute heights of spanned rows.
- for y in 0..table.n[Y] {
- for x in table.iter_x(y) {
- let coord = Coord2::new(x, y);
- let contents = table.get(coord);
- if contents.is_top_left() && contents.row_span() > 1 {
- let rect = contents.rect();
- let w = page.joined_width(X, rect[X].clone());
- let h = device.measure_cell_height(contents.inner(), w);
- distribute_spanned_width(
- h,
- &mut rows[rect[Y].clone()],
- &rules[Y][rect[Y].start..rect[Y].end + 1],
- );
- }
- }
+ for cell in table.cells().filter(|cell| cell.row_span() > 1) {
+ let rect = cell.rect();
+ let w = page.joined_width(X, rect[X].clone());
+ let h = device.measure_cell_height(cell.inner(), w);
+ distribute_spanned_width(
+ h,
+ &mut rows[rect[Y].clone()],
+ &rules[Y][rect[Y].start..rect[Y].end + 1],
+ );
}
// Decide final row heights.
use super::pivot::{Area, AreaStyle, Axis2, Border, BorderStyle, HeadingRegion, Rect2, Value};
+#[derive(Clone)]
pub struct CellRef<'a> {
- coord: Coord2,
+ pub coord: Coord2,
content: &'a Content,
}
}
}
- /// Visits all the nonempty cells once.
- pub fn visit_cells(&self, mut f: impl FnMut(&CellInner)) {
- for y in 0..self.n.y() {
- for x in self.iter_x(y) {
- let coord = Coord2::new(x, y);
- let content = self.get(coord);
- if !content.is_empty() && content.is_top_left() {
- f(content.inner());
- }
- }
- }
- }
-
/// The heading region that `pos` is part of, if any.
pub fn heading_region(&self, pos: Coord2) -> Option<HeadingRegion> {
if pos.x() < self.h.x() {
None
}
}
+
+ /// Iterates across all of the cells in the table, visiting each of them
+ /// once in top-down, left-to-right order. Spanned cells are visited once,
+ /// at the point in the iteration where their top-left cell would appear if
+ /// they were not spanned.
+ pub fn cells(&self) -> Cells<'_> {
+ Cells::new(self)
+ }
+
+ pub fn is_empty(&self) -> bool {
+ self.n[Axis2::X] == 0 || self.n[Axis2::Y] == 0
+ }
}
pub struct XIter<'a> {
}
}
}
+
+/// Iterator for all of the cells in a table (see [Table::cells]).
+pub struct Cells<'a> {
+ table: &'a Table,
+ next: Option<CellRef<'a>>,
+}
+
+impl<'a> Cells<'a> {
+ fn new(table: &'a Table) -> Self {
+ Self {
+ table,
+ next: if table.is_empty() {
+ None
+ } else {
+ Some(table.get(Coord2::new(0, 0)))
+ },
+ }
+ }
+}
+
+impl<'a> Iterator for Cells<'a> {
+ type Item = CellRef<'a>;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ use Axis2::*;
+ let this = self.next.as_ref()?.clone();
+
+ let mut next = this.clone();
+ self.next = loop {
+ let next_x = next.next_x();
+ let coord = if next_x < self.table.n[X] {
+ Coord2::new(next_x, next.coord.y())
+ } else if next.coord.y() + 1 < self.table.n[Y] {
+ Coord2::new(0, next.coord.y() + 1)
+ } else {
+ break None;
+ };
+ next = self.table.get(coord);
+ if next.is_top_left() {
+ break Some(next);
+ }
+ };
+ Some(this)
+ }
+}