work
authorBen Pfaff <blp@cs.stanford.edu>
Tue, 2 Dec 2025 17:15:00 +0000 (09:15 -0800)
committerBen Pfaff <blp@cs.stanford.edu>
Tue, 2 Dec 2025 17:15:00 +0000 (09:15 -0800)
rust/pspp/src/output/drivers/html.rs
rust/pspp/src/output/render.rs
rust/pspp/src/output/table.rs

index 2172cc0a0d30c0de36607484042cdb2cfb17aa00..747156b718545e2a017527e1900f113da3d3ae6e 100644 (file)
@@ -232,17 +232,17 @@ where
                 table.get_rule(Axis2::X, rect.top_left()),
                 "left",
             );
-            if rect[Axis2::X].end == table.n[Axis2::X] {
+            if rect.x.end == table.n[Axis2::X] {
                 Self::put_border(
                     &mut style,
-                    table.get_rule(Axis2::X, CellPos(rect[Axis2::X].end, rect[Axis2::Y].start)),
+                    table.get_rule(Axis2::X, CellPos(rect.x.end, rect.y.start)),
                     "right",
                 );
             }
-            if rect[Axis2::Y].end == table.n[Axis2::Y] {
+            if rect.y.end == table.n[Axis2::Y] {
                 Self::put_border(
                     &mut style,
-                    table.get_rule(Axis2::Y, CellPos(rect[Axis2::X].start, rect[Axis2::Y].end)),
+                    table.get_rule(Axis2::Y, CellPos(rect.x.start, rect.y.end)),
                     "bottom",
                 );
             }
@@ -258,12 +258,12 @@ where
             )?;
         }
 
-        let col_span = rect[Axis2::X].len();
+        let col_span = rect.x.len();
         if col_span > 1 {
             write!(&mut self.writer, r#" colspan="{col_span}""#)?;
         }
 
-        let row_span = rect[Axis2::Y].len();
+        let row_span = rect.y.len();
         if row_span > 1 {
             write!(&mut self.writer, r#" rowspan="{row_span}""#)?;
         }
index 079783b25cc0bf493739efbbe5232daa64091cea..69bb0fa746cac4090a3bc431ec7dc232af1b70e7 100644 (file)
@@ -428,9 +428,9 @@ impl Page {
             for ext in [Min, Max] {
                 distribute_spanned_width(
                     w[ext],
-                    &unspanned_columns[ext][rect[X].clone()],
-                    &mut columns[ext][rect[X].clone()],
-                    &rules[X][rect[X].start..rect[X].end + 1],
+                    &unspanned_columns[ext][rect.x.clone()],
+                    &mut columns[ext][rect.x.clone()],
+                    &rules[X][rect.x.start..rect.x.end + 1],
                 );
             }
         }
@@ -480,7 +480,7 @@ impl Page {
         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 w = joined_width(&cp_x, rect.x.clone());
             let h = device.measure_cell_height(&DrawCell::new(cell.inner(), &table), w);
 
             let row = &mut unspanned_rows[cell.pos.1];
@@ -493,13 +493,13 @@ impl Page {
         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 w = joined_width(&cp_x, rect.x.clone());
             let h = device.measure_cell_height(&DrawCell::new(cell.inner(), &table), w);
             distribute_spanned_width(
                 h,
-                &unspanned_rows[rect[Y].clone()],
-                &mut rows[rect[Y].clone()],
-                &rules[Y][rect[Y].start..rect[Y].end + 1],
+                &unspanned_rows[rect.y.clone()],
+                &mut rows[rect.y.clone()],
+                &rules[Y][rect.y.start..rect.y.end + 1],
             );
         }
 
@@ -659,10 +659,10 @@ impl Page {
         let maps = EnumMap::from_fn(|axis| self.get_map(axis, coord[axis]));
         let cell = self.table.get(self.map_coord(coord));
         RenderCell {
-            rect: CellRect(cell.rect().0.map(|axis, Range { start, end }| {
+            rect: cell.rect().map(|axis, Range { start, end }| {
                 let m = maps[axis];
                 max(m.p0, start - m.ofs)..min(m.p0 + m.n, end - m.ofs)
-            })),
+            }),
             content: cell.content,
         }
     }
@@ -844,22 +844,21 @@ impl Page {
     }
 
     fn draw_cells(&self, device: &mut dyn Device, ofs: Coord2, cells: CellRect) {
-        use Axis2::*;
-        for y in cells[Y].clone() {
-            let mut x = cells[X].start;
-            while x < cells[X].end {
+        for y in cells.y.clone() {
+            let mut x = cells.x.start;
+            while x < cells.x.end {
                 if !is_rule(x) && !is_rule(y) {
                     let cell = self.get_cell(CellPos(x / 2, y / 2));
                     self.draw_cell(device, ofs, &cell);
-                    x = rule_ofs(cell.rect[X].end);
+                    x = rule_ofs(cell.rect.x.end);
                 } else {
                     x += 1;
                 }
             }
         }
 
-        for y in cells[Y].clone() {
-            for x in cells[X].clone() {
+        for y in cells.y.clone() {
+            for x in cells.x.clone() {
                 if is_rule(x) || is_rule(y) {
                     self.draw_rule(device, ofs, CellPos(x, y));
                 }
@@ -1287,11 +1286,11 @@ impl Break {
                         cell.content,
                         Coord2::new(
                             self.page
-                                .joined_width(Axis2::X, cell.rect[Axis2::X].clone()),
+                                .joined_width(Axis2::X, cell.rect.x.clone()),
                             pixel,
                         ),
                     );
-                    x += cell.rect[Axis2::X].len();
+                    x += cell.rect.x.len();
 
                     if better_pixel < pixel {
                         let start_pixel = if z > self.z { self.pixel } else { 0 };
index 4626addb5becea0f3a341ca145823bf7c2e86771..05ad8e9cac675d4f0103cdf6819466f5778a6055 100644 (file)
@@ -91,34 +91,58 @@ impl IndexMut<Axis2> for CellPos {
 
 /// A rectangular group of cells in a [Table].
 #[derive(Clone, Debug, Default)]
-pub struct CellRect(
-    /// The `x` range and `y` range spanned by the rectangle.
-    pub EnumMap<Axis2, Range<usize>>,
-);
+pub struct CellRect {
+    pub x: Range<usize>,
+    pub y: Range<usize>,
+}
 
 impl CellRect {
-    pub fn new(x_range: Range<usize>, y_range: Range<usize>) -> Self {
-        Self(enum_map! {
-            Axis2::X => x_range.clone(),
-            Axis2::Y => y_range.clone(),
-        })
+    pub fn new(x: Range<usize>, y: Range<usize>) -> Self {
+        Self { x, y }
     }
     pub fn for_cell(cell: CellPos) -> Self {
         Self::new(cell.0..cell.0 + 1, cell.1..cell.1 + 1)
     }
-    pub fn for_ranges((a, a_range): (Axis2, Range<usize>), b_range: Range<usize>) -> Self {
-        let b = !a;
-        let mut ranges = EnumMap::default();
-        ranges[a] = a_range;
-        ranges[b] = b_range;
-        Self(ranges)
+    pub fn for_ranges((a_axis, a): (Axis2, Range<usize>), b: Range<usize>) -> Self {
+        match a_axis {
+            Axis2::X => Self { x: a, y: b },
+            Axis2::Y => Self { x: b, y: a },
+        }
     }
     pub fn top_left(&self) -> CellPos {
-        use Axis2::*;
-        CellPos(self[X].start, self[Y].start)
+        CellPos(self.x.start, self.y.start)
     }
     pub fn is_empty(&self) -> bool {
-        self[Axis2::X].is_empty() || self[Axis2::Y].is_empty()
+        self.x.is_empty() || self.y.is_empty()
+    }
+    pub fn map<F>(&self, mut f: F) -> Self
+    where
+        F: FnMut(Axis2, Range<usize>) -> Range<usize>,
+    {
+        Self {
+            x: f(Axis2::X, self.x.clone()),
+            y: f(Axis2::Y, self.y.clone()),
+        }
+    }
+}
+
+impl Index<Axis2> for CellRect {
+    type Output = Range<usize>;
+
+    fn index(&self, index: Axis2) -> &Self::Output {
+        match index {
+            Axis2::X => &self.x,
+            Axis2::Y => &self.y,
+        }
+    }
+}
+
+impl IndexMut<Axis2> for CellRect {
+    fn index_mut(&mut self, index: Axis2) -> &mut Self::Output {
+        match index {
+            Axis2::X => &mut self.x,
+            Axis2::Y => &mut self.y,
+        }
     }
 }
 
@@ -198,8 +222,7 @@ impl Content {
     }
 
     pub fn next_x(&self, x: usize) -> usize {
-        self.joined_rect()
-            .map_or(x + 1, |region| region[Axis2::X].end)
+        self.joined_rect().map_or(x + 1, |region| region.x.end)
     }
 
     pub fn is_top_left(&self, pos: CellPos) -> bool {
@@ -208,7 +231,7 @@ impl Content {
 
     pub fn span(&self, axis: Axis2) -> usize {
         self.joined_rect().map_or(1, |r| {
-            let range = &r.0[axis];
+            let range = &r[axis];
             range.end - range.start
         })
     }
@@ -331,13 +354,12 @@ impl Table {
     }
 
     pub fn put(&mut self, region: CellRect, inner: CellInner) {
-        use Axis2::*;
-        if region[X].len() == 1 && region[Y].len() == 1 {
-            self.contents[[region[X].start, region[Y].start]] = Content::Value(inner);
+        if region.x.len() == 1 && region.y.len() == 1 {
+            self.contents[[region.x.start, region.y.start]] = Content::Value(inner);
         } else {
             let cell = Arc::new(Cell::new(inner, region.clone()));
-            for y in region[Y].clone() {
-                for x in region[X].clone() {
+            for y in region.y.clone() {
+                for x in region.x.clone() {
                     self.contents[[x, y]] = Content::Join(cell.clone())
                 }
             }