From: Ben Pfaff Date: Tue, 14 Jan 2025 02:54:12 +0000 (-0800) Subject: work X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3dced7b4a3cb4c88af5926ca552359d31a738a41;p=pspp work --- diff --git a/rust/pspp/src/format.rs b/rust/pspp/src/format.rs index a266953a7f..0747cac03c 100644 --- a/rust/pspp/src/format.rs +++ b/rust/pspp/src/format.rs @@ -781,7 +781,7 @@ pub struct Settings { pub leading_zero: bool, /// Custom currency styles. - pub ccs: EnumMap>, + pub ccs: EnumMap>>, } #[derive(Copy, Clone, Enum)] @@ -849,7 +849,7 @@ impl Settings { }); &PCT.get(self) } - Type::CC(cc) => self.ccs[cc].as_ref().unwrap_or(&DEFAULT), + Type::CC(cc) => self.ccs[cc].as_deref().unwrap_or(&DEFAULT), Type::N | Type::Z | Type::P diff --git a/rust/pspp/src/output/pivot/mod.rs b/rust/pspp/src/output/pivot/mod.rs index 606bb55177..cc8a3b093b 100644 --- a/rust/pspp/src/output/pivot/mod.rs +++ b/rust/pspp/src/output/pivot/mod.rs @@ -80,7 +80,7 @@ use crate::{ pub mod output; /// Areas of a pivot table for styling purposes. -#[derive(Copy, Clone, Debug, Enum, PartialEq, Eq)] +#[derive(Copy, Clone, Debug, Default, Enum, PartialEq, Eq)] pub enum Area { Title, Caption, @@ -93,6 +93,7 @@ pub enum Area { ColumnLabels, RowLabels, + #[default] Data, /// Layer indication. @@ -351,7 +352,7 @@ impl Dimension { #[derive(Clone, Debug)] pub struct Group { parent: Option>, - name: Value, + name: Box, label_depth: usize, extra_depth: usize, @@ -370,7 +371,7 @@ pub struct Group { #[derive(Clone, Debug)] pub struct Leaf { parent: Weak, - name: Value, + name: Box, label_depth: usize, extra_depth: usize, @@ -871,7 +872,7 @@ pub struct PivotTable { pub current_layer: Vec, /// Column and row sizing and page breaks. - pub sizing: EnumMap, + pub sizing: EnumMap>>, /// Format settings. pub settings: FormatSettings, @@ -889,10 +890,10 @@ pub struct PivotTable { pub datafile: Option, pub date: Option, pub footnotes: Vec, - pub title: Option, - pub subtype: Option, - pub corner_text: Option, - pub caption: Option, + pub title: Option>, + pub subtype: Option>, + pub corner_text: Option>, + pub caption: Option>, pub notes: Option, pub dimensions: Vec>, pub axes: EnumMap, diff --git a/rust/pspp/src/output/pivot/output.rs b/rust/pspp/src/output/pivot/output.rs index 678350ec06..28e62c85bf 100644 --- a/rust/pspp/src/output/pivot/output.rs +++ b/rust/pspp/src/output/pivot/output.rs @@ -182,7 +182,7 @@ impl PivotTable { CellInner { rotate: false, area: Area::Data, - value: value.cloned(), + value: value.map(|value| Box::new(value.clone())), }, ); } @@ -275,7 +275,7 @@ impl PivotTable { f.display_marker(Some(self)), f.display_content(Some(self)) ); - let value = Some(Value::new_user_text(s)); + let value = Some(Box::new(Value::new_user_text(s))); footnotes.put( Rect2::for_cell(Coord2::new(0, y)), CellInner::new(Area::Footer, value), @@ -480,7 +480,7 @@ fn compose_headings( rotate: (rotate_inner_labels && is_inner_row) || (rotate_outer_labels && is_outer_row), area, - value: Some(c.name().clone()), + value: Some(Box::new(c.name().clone())), }, ); diff --git a/rust/pspp/src/output/render.rs b/rust/pspp/src/output/render.rs index f417dc17c1..dcc1da6acc 100644 --- a/rust/pspp/src/output/render.rs +++ b/rust/pspp/src/output/render.rs @@ -160,23 +160,23 @@ struct Page { /// "Cell positions". /// - /// cp[H] represents x positions within the table. - /// cp[H][0] = 0. - /// cp[H][1] = the width of the leftmost vertical rule. - /// cp[H][2] = cp[H][1] + the width of the leftmost column. - /// cp[H][3] = cp[H][2] + the width of the second-from-left vertical rule. + /// cp[X] represents x positions within the table. + /// cp[X][0] = 0. + /// cp[X][1] = the width of the leftmost vertical rule. + /// cp[X][2] = cp[X][1] + the width of the leftmost column. + /// cp[X][3] = cp[X][2] + the width of the second-from-left vertical rule. /// and so on: - /// cp[H][2 * n[H]] = x position of the rightmost vertical rule. - /// cp[H][2 * n[H] + 1] = total table width including all rules. + /// cp[X][2 * n[X]] = x position of the rightmost vertical rule. + /// cp[X][2 * n[X] + 1] = total table width including all rules. /// - /// Similarly, cp[V] represents y positions within the table. - /// cp[V][0] = 0. - /// cp[V][1] = the height of the topmost horizontal rule. - /// cp[V][2] = cp[V][1] + the height of the topmost row. - /// cp[V][3] = cp[V][2] + the height of the second-from-top horizontal rule. + /// Similarly, cp[Y] represents y positions within the table. + /// cp[Y][0] = 0. + /// cp[Y][1] = the height of the topmost horizontal rule. + /// cp[Y][2] = cp[Y][1] + the height of the topmost row. + /// cp[Y][3] = cp[Y][2] + the height of the second-from-top horizontal rule. /// and so on: - /// cp[V][2 * n[V]] = y position of the bottommost horizontal rule. - /// cp[V][2 * n[V] + 1] = total table height including all rules. + /// cp[Y][2 * n[Y]] = y position of the bottommost horizontal rule. + /// cp[Y][2 * n[Y] + 1] = total table height including all rules. /// /// Rules and columns can have width or height 0, in which case consecutive /// values in this array are equal. @@ -196,10 +196,10 @@ struct Page { /// /// # Interpretation /// - /// overflow[H][0]: space trimmed off its left side. - /// overflow[H][1]: space trimmed off its right side. - /// overflow[V][0]: space trimmed off its top. - /// overflow[V][1]: space trimmed off its bottom. + /// overflow[X][0]: space trimmed off its left side. + /// overflow[X][1]: space trimmed off its right side. + /// overflow[Y][0]: space trimmed off its top. + /// overflow[Y][1]: space trimmed off its bottom. /// /// During rendering, this information is used to position the rendered /// portion of the cell within the available space. @@ -225,9 +225,9 @@ struct Page { /// /// If this render_page is broken at the rule that separates "gh" from /// "ijk", then the page that contains the left side of the "abcdef" cell - /// will have overflow[H][1] of 10 + 30 = 40 for its portion of the cell, + /// will have overflow[X][1] of 10 + 30 = 40 for its portion of the cell, /// and the page that contains the right side of the cell will have - /// overflow[H][0] of 20 + 10 = 30. The two resulting pages would look like + /// overflow[X][0] of 20 + 10 = 30. The two resulting pages would look like /// this: /// /// ```text @@ -256,13 +256,13 @@ struct Page { /// across multiple render_pages. This member indicates when this has /// happened: /// - /// is_edge_cutoff[H][0] is true if pixels have been cut off the left side + /// is_edge_cutoff[X][0] is true if pixels have been cut off the left side /// of the leftmost column in this page, and false otherwise. /// - /// is_edge_cutoff[H][1] is true if pixels have been cut off the right side + /// is_edge_cutoff[X][1] is true if pixels have been cut off the right side /// of the rightmost column in this page, and false otherwise. /// - /// is_edge_cutoff[V][0] and is_edge_cutoff[V][1] are similar for the top + /// is_edge_cutoff[Y][0] and is_edge_cutoff[Y][1] are similar for the top /// and bottom of the table. /// /// The effect of is_edge_cutoff is to prevent rules along the edge in @@ -539,6 +539,7 @@ impl Page { *self.cp[axis].last().unwrap() } + /// XXX This could return a fn get_map(&self, a: Axis2, z: usize) -> Map { if z < self.h[a] { Map { @@ -554,8 +555,107 @@ impl Page { } } } + +/* + fn get_cell(&self, coord: Coord2) -> RenderCell<'_> { + + }*/ + + /// Creates and returns a new [Page] whose contents are a subregion of + /// thispage's contents. The new page includes cells `extent` (exclusive) + /// along `axis`, plus any headers on `axis`. + /// + /// If `pixel0` is nonzero, then it is a number of pixels to exclude from + /// the left or top (according to `axis`) of cell `extent.start`. + /// Similarly, `pixel1` is a number of pixels to exclude from the right or + /// bottom of cell `extent.end - 1`. (`pixel0` and `pixel1` are used to + /// render cells that are too large to fit on a single page.) + /// + /// The whole of axis `!axis` is included. (The caller may follow up with + /// another call to select on `!axis` to select on that axis as well.) + fn select( + self: &Arc, + axis: Axis2, + extent: Range, + pixel0: usize, + pixel1: usize, + ) -> Arc { + let z0 = extent.start; + let z1 = extent.end; + + // If all of the page is selected, just make a copy. + if z0 == self.h[axis] && z1 == self.n[axis] && pixel0 == 0 && pixel1 == 0 { + return self.clone(); + } + + // Figure out `n`, `h`, `r` for the subpage. + let trim = [z0 - self.h[axis], self.n[axis] - z1]; + let mut n = self.n; + n[axis] -= trim[0] + trim[1]; + let mut h = self.h; + let mut r = self.r.clone(); + r[axis].start += trim[0]; + r[axis].end -= trim[1]; + + // An edge is cut off if it was cut off in `self` or if we're trimming + // pixels off that side of the page and there are no headers. + let mut is_edge_cutoff = self.is_edge_cutoff.clone(); + is_edge_cutoff[axis][0] = + h[axis] == 0 && (pixel0 > 0 || (z0 == 0 && self.is_edge_cutoff[axis][0])); + is_edge_cutoff[axis][1] = + pixel1 > 0 || (z1 == self.n[axis] && self.is_edge_cutoff[axis][1]); + + // Select widths from `self` into subpage. + let scp = self.cp[axis].as_slice(); + let mut dcp = Vec::with_capacity(2 * n[axis] + 1); + dcp.push(0); + let mut total = 0; + for z in 0..=Self::rule_ofs(h[axis]) { + total += if z == 0 && is_edge_cutoff[axis][0] { + 0 + } else { + scp[z + 1] - scp[z] + }; + dcp.push(total); + } + for z in Self::cell_ofs(z0)..=Self::cell_ofs(z1 - 1) { + total += scp[z + 1] - scp[z]; + if z== Self::cell_ofs(z0) { + total -= pixel0; + } + if z == Self::cell_ofs(z1 - 1) { + total -= pixel1; + } + dcp.push(total); + } + let z = self.rule_ofs_r(axis, 0); + if !is_edge_cutoff[axis][1] { + total += scp[z + 1] - scp[z]; + } + dcp.push(total); + debug_assert_eq!(dcp.len(), 2 * n[axis] + 1); + + let mut cp = EnumMap::default(); + cp[axis] = dcp; + cp[!axis] = self.cp[!axis].clone(); + + // Add new overflows. + let s = Selection; + if self.h[axis] == 0 || z0 > self.h[axis] || pixel0 > 0 { + let b = !axis; + let mut z = 0; + while z < self.n[b] { + let d = Coord2::for_axis((axis, z0), z); + + } + } + + todo!() + } } +struct Selection; + /// Maps a contiguous range of cells from a page to the underlying table along /// the horizontal or vertical dimension. struct Map { diff --git a/rust/pspp/src/output/table.rs b/rust/pspp/src/output/table.rs index 4b3ba58dfe..bf6a2f8f0c 100644 --- a/rust/pspp/src/output/table.rs +++ b/rust/pspp/src/output/table.rs @@ -58,33 +58,20 @@ impl<'a> CellRef<'a> { #[derive(Clone)] pub enum Content { - Empty, - Value(Box), + Value(CellInner), Join(Arc), } impl Content { pub fn inner(&self) -> &CellInner { match self { - Content::Empty => { - static INNER: CellInner = CellInner { - rotate: false, - area: Area::Title, - value: None, - }; - &INNER - } Content::Value(cell_inner) => &cell_inner, Content::Join(cell) => &cell.inner, } } pub fn is_empty(&self) -> bool { - if let Content::Empty = self { - true - } else { - false - } + self.inner().is_empty() } /// Returns the rectangle that this cell covers, only if the cell contains @@ -130,6 +117,12 @@ impl Content { } } +impl Default for Content { + fn default() -> Self { + Self::Value(CellInner::default()) + } +} + #[derive(Clone)] pub struct Cell { inner: CellInner, @@ -144,7 +137,7 @@ impl Cell { } } -#[derive(Clone)] +#[derive(Clone, Default)] pub struct CellInner { /// Rotate cell contents 90 degrees? pub rotate: bool, @@ -152,17 +145,21 @@ pub struct CellInner { /// The area that the cell belongs to. pub area: Area, - pub value: Option, + pub value: Option>, } impl CellInner { - pub fn new(area: Area, value: Option) -> Self { + pub fn new(area: Area, value: Option>) -> Self { Self { rotate: false, area, value, } } + + pub fn is_empty(&self) -> bool { + self.value.is_none() + } } /// A table. @@ -195,7 +192,7 @@ impl Table { Self { n, h: headers, - contents: vec![Content::Empty; n.y() * n.x()], + contents: vec![Content::default(); n.y() * n.x()], areas, borders, rules: enum_map! { @@ -232,7 +229,7 @@ impl Table { use Axis2::*; if region[X].len() == 1 && region[Y].len() == 1 { let offset = self.offset(Coord2::new(region[X].start, region[Y].start)); - self.contents[offset] = Content::Value(Box::new(inner)); + self.contents[offset] = Content::Value(inner); } else { let cell = Arc::new(Cell::new(inner, region.clone())); for y in region[Y].clone() {