From: Ben Pfaff Date: Thu, 30 Jan 2025 01:20:16 +0000 (-0800) Subject: OK actually got it complete now? X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=refs%2Fheads%2Frust;p=pspp OK actually got it complete now? --- diff --git a/rust/pspp/src/output/pivot/mod.rs b/rust/pspp/src/output/pivot/mod.rs index 8d219e99f0..d6f8108305 100644 --- a/rust/pspp/src/output/pivot/mod.rs +++ b/rust/pspp/src/output/pivot/mod.rs @@ -688,6 +688,29 @@ pub struct BorderStyle { pub color: Color, } +impl BorderStyle { + pub const fn none() -> Self { + Self { + stroke: Stroke::None, + color: Color::BLACK, + } + } + + pub fn is_none(&self) -> bool { + self.stroke.is_none() + } + + /// Returns a border style that "combines" the two arguments, that is, that + /// gives a reasonable choice for a rule for different reasons should have + /// both styles. + pub fn combine(self, other: BorderStyle) -> Self { + Self { + stroke: self.stroke.combine(other.stroke), + color: self.color, + } + } +} + #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Enum)] pub enum Stroke { None, @@ -699,10 +722,14 @@ pub enum Stroke { } impl Stroke { + pub fn is_none(&self) -> bool { + self == &Self::None + } + /// Returns a stroke that "combines" the two arguments, that is, that gives /// a reasonable stroke choice for a rule for different reasons should have /// both styles. - fn combine(self, other: Stroke) -> Self { + pub fn combine(self, other: Stroke) -> Self { self.max(other) } } @@ -751,6 +778,13 @@ impl Coord2 { coord } + pub fn from_fn(f: F) -> Self + where + F: FnMut(Axis2) -> usize, + { + Self(EnumMap::from_fn(f)) + } + pub fn x(&self) -> usize { self.0[Axis2::X] } @@ -814,7 +848,7 @@ impl Rect2 { { Self(EnumMap::from_fn(f)) } - pub fn offset(self, offset: Coord2) -> Rect2 { + pub fn translate(self, offset: Coord2) -> Rect2 { Self::from_fn(|axis| self[axis].start + offset[axis]..self[axis].end + offset[axis]) } } diff --git a/rust/pspp/src/output/render.rs b/rust/pspp/src/output/render.rs index 7eed58f130..6f78a28136 100644 --- a/rust/pspp/src/output/render.rs +++ b/rust/pspp/src/output/render.rs @@ -71,16 +71,6 @@ pub struct Params { can_scale: bool, } -/* -pub struct DeviceCell { - /// Rotate cell contents 90 degrees? - rotate: bool, - - /// Value to render. - value: &ValueInner, - - -}*/ pub trait Device { fn params(&self) -> &Params; @@ -633,21 +623,28 @@ impl Page { }) } - fn get_map(&self, axis: Axis2, ordinate: usize) -> &Map { - if ordinate < self.h[axis] { + fn get_map(&self, axis: Axis2, z: usize) -> &Map { + if z < self.h[axis] { &self.maps[axis][0] } else { &self.maps[axis][1] } } + fn map_z(&self, axis: Axis2, z: usize) -> usize { + z + self.get_map(axis, z).ofs + } + + fn map_coord(&self, coord: Coord2) -> Coord2 { + Coord2::from_fn(|a| self.map_z(a, coord[a])) + } + fn get_cell(&self, coord: Coord2) -> RenderCell<'_> { let maps = EnumMap::from_fn(|axis| self.get_map(axis, coord[axis])); - let coord = Coord2(coord.0.map(|axis, ordinate| ordinate + maps[axis].ofs)); - let cell = self.table.get(coord); + let cell = self.table.get(self.map_coord(coord)); RenderCell { rect: Rect2(cell.rect().0.map(|axis, Range { start, end }| { - let m = &maps[axis]; + let m = maps[axis]; max(m.p0, start - m.ofs)..min(m.p0 + m.n, end - m.ofs) })), content: cell.content, @@ -852,6 +849,62 @@ impl Page { }*/ } + fn draw_rule(&self, ofs: Coord2, draw: &mut dyn Draw, coord: Coord2) { + const NO_BORDER: BorderStyle = BorderStyle::none(); + let styles = EnumMap::from_fn(|a: Axis2| { + let b = !a; + if !is_rule(coord[a]) + || (self.is_edge_cutoff[a][0] && coord[a] == 0) + || (self.is_edge_cutoff[a][1] && coord[a] == self.n[a] * 2) + { + [NO_BORDER, NO_BORDER] + } else if is_rule(coord[b]) { + let first = if coord[b] > 0 { + let mut e = coord; + e[b] -= 1; + self.get_rule(a, e) + } else { + NO_BORDER + }; + + let second = if coord[b] / 2 < self.n[b] { + self.get_rule(a, coord) + } else { + NO_BORDER + }; + + [first, second] + } else { + let rule = self.get_rule(a, coord); + [rule, rule] + } + }); + + if !styles + .values() + .all(|border| border.iter().all(BorderStyle::is_none)) + { + let bb = + Rect2::from_fn(|a| self.cp[a][coord[a]]..self.cp[a][coord[a] + 1]).translate(ofs); + draw.draw_line(bb, styles); + } + } + + fn get_rule(&self, a: Axis2, coord: Coord2) -> BorderStyle { + let coord = Coord2::from_fn(|a| coord[a] / 2); + let coord = self.map_coord(coord); + + let border = self.table.get_rule(a, coord); + if self.h[a] > 0 && coord[a] == self.h[a] { + let border2 = self + .table + .get_rule(a, Coord2::for_axis((a, self.h[a]), coord[!a])); + border.combine(border2) + } else { + border + } + } + fn extra_height(&self, bb: &Rect2, inner: &CellInner) -> usize { use Axis2::*; let height = self.device.measure_cell_height(inner, bb[X].len()); @@ -880,7 +933,7 @@ impl Page { let mut bb = Rect2::from_fn(|a| { self.cp[a][cell.rect[a].start * 2 + 1]..self.cp[a][cell.rect[a].end * 2] }) - .offset(ofs); + .translate(ofs); let spill = EnumMap::from_fn(|a| { [ self.rule_width(a, cell.rect[a].start) / 2,