-use std::sync::Arc;
+use std::{ops::Range, sync::Arc};
use enum_map::{enum_map, EnumMap};
+use itertools::Itertools;
use smallvec::{SmallVec, ToSmallVec};
use crate::output::{
.filter(|(_, d)| !d.hide_all_labels)
{
for row_ofs in 0..d.label_depth() {
- let mut x1 = 0;
- while x1 < n_columns {
- let Some(c): Option<Category> = find_category(
+ // Find all the categories, dropping columns without a category.
+ let categories = (0..n_columns).filter_map(|x| {
+ find_category(
d,
dim_index,
- column_enumeration.get(x1),
+ column_enumeration.get(x),
d.label_depth() - row_ofs - 1,
- ) else {
- x1 += 1;
- continue;
- };
-
- let mut x2 = x1 + 1;
- while x2 < n_columns && !vrules[x2] {
- let c2 = find_category(
- d,
- dim_index,
- column_enumeration.get(x2),
- d.label_depth() - row_ofs - 1,
- );
- if c2.as_ref().is_none_or(|c2| !c.ptr_eq(c2)) {
- break;
- }
- x2 += 1;
+ )
+ .map(|c| (x..x + 1, c))
+ });
+
+ // Merge adjacent identical categories.
+ let categories = categories.coalesce(|(a_r, a), (b_r, b)| {
+ if a.ptr_eq(&b) {
+ Ok((a_r.start..b_r.end, a))
+ } else {
+ Err(((a_r, a), (b_r, b)))
}
+ });
+ for (Range { start: x1, end: x2 }, c) in categories {
let y1 = top_row + row_ofs;
let y2 = y1 + c.extra_depth() + 1;
let is_outer_row = y1 == 0;
h_ofs..table.n[h],
);
}
- x1 = x2;
}
}
}
pub fn h_line(&mut self, border: Border, x: Range<usize>, y: usize) {
- debug_assert!(y <= self.n.y());
- debug_assert!(x.start <= x.end);
- debug_assert!(x.end <= self.n.x());
for x in x {
self.rules[Axis2::Y][[x, y]] = border;
}
}
pub fn v_line(&mut self, border: Border, x: usize, y: Range<usize>) {
- debug_assert!(x <= self.n.x());
- debug_assert!(y.start <= y.end);
- debug_assert!(y.end <= self.n.y());
for y in y {
self.rules[Axis2::X][[x, y]] = border;
}