From: Ben Pfaff Date: Wed, 3 Dec 2025 21:15:56 +0000 (-0800) Subject: work X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e8b4bdc04c2ac3dbcfd147aef4f111eee7578164;p=pspp work --- diff --git a/rust/pspp/src/output/drivers/cairo/fsm.rs b/rust/pspp/src/output/drivers/cairo/fsm.rs index 83f3739e15..cb6651b0a6 100644 --- a/rust/pspp/src/output/drivers/cairo/fsm.rs +++ b/rust/pspp/src/output/drivers/cairo/fsm.rs @@ -168,9 +168,7 @@ impl CairoFsm { } fn draw_table(&mut self, context: &Context, space: isize) -> isize { - let Details::Table(pivot_table) = &self.item.details else { - unreachable!() - }; + let pivot_table = self.item.details.as_table().unwrap(); let Some(pager) = &mut self.pager else { return 0; }; diff --git a/rust/pspp/src/output/drivers/cairo/pager.rs b/rust/pspp/src/output/drivers/cairo/pager.rs index 1ca673e3db..f197d5f499 100644 --- a/rust/pspp/src/output/drivers/cairo/pager.rs +++ b/rust/pspp/src/output/drivers/cairo/pager.rs @@ -146,7 +146,8 @@ impl CairoPager { }; // Prepare to render the current object. - let chunk = fsm.draw_slice(&context, self.y_max.saturating_sub(self.y)); + let chunk = fsm.draw_slice(&context, dbg!((self.y_max - self.y).max(0))); + dbg!(chunk); self.y += chunk + self.fsm_style.object_spacing; context.translate(0.0, xr_to_pt(chunk + self.fsm_style.object_spacing)); diff --git a/rust/pspp/src/output/render.rs b/rust/pspp/src/output/render.rs index 2f3ff19cb6..bca9556276 100644 --- a/rust/pspp/src/output/render.rs +++ b/rust/pspp/src/output/render.rs @@ -176,23 +176,22 @@ pub trait Device { /// [Pager] breaks a [Page] into smaller [page]s that will fit in the available /// space. /// +/// A [Page] always has the same headers as its [Table]. +/// /// # Rendered cells /// -/// The horizontal cells rendered are the leftmost `h[X]`, then `r[X]`. -/// The vertical cells rendered are the topmost `h[Y]`, then `r[Y]`. -/// `n[i]` is the sum of `h[i]` and `r[i].len()`. +/// - The columns rendered are the leftmost `self.table.h[X]`, then `r[X]`. +/// - The rows rendered are the topmost `self.table.h[Y]`, then `r[Y]`. #[derive(Debug)] struct Page { table: Arc, - /// Size of the table in cells. + /// Table size in cells. /// + /// This is the sum of `self.table.h` and `self.r`. n: CellPos, - /// Header size. Cells `0..h[X]` are rendered horizontally, and `0..h[Y]` vertically. - h: CellPos, - - /// Main region of cells to render. + /// The region of cells in `self.table` to render. r: CellRect, /// Mappings from [Page] positions to those in the underlying [Table]. @@ -299,20 +298,20 @@ struct Page { /// reasonably, then [Break::next] will split a single row or column across /// multiple [Page]s. This member indicates when this has happened: /// - /// 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[Axis2::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[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[Axis2::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[Y][0] and is_edge_cutoff[Y][1] are similar for the top - /// and bottom of the table. + /// - `is_edge_cutoff[Axis2::Y][0]` and `is_edge_cutoff[Axis2::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 - /// question from being rendered. + /// The effect is to prevent rules along the edge in question from being + /// rendered. /// - /// When is_edge_cutoff is true for a given edge, the 'overflows' hmap will - /// contain a node for each cell along that edge. + /// When `is_edge_cutoff` is true for a given edge, 'overflows' will contain + /// a node for each cell along that edge. is_edge_cutoff: EnumMap, } @@ -524,7 +523,6 @@ impl Page { Self { table, n, - h, r, cp: Axis2::new_enum(cp_x, cp_y), overflows: HashMap::new(), @@ -533,6 +531,11 @@ impl Page { } } + /// A [Page] always has the same headers as its underlying [Table]. + fn h(&self) -> CellPos { + self.table.h + } + fn use_row_widths(rows: &[isize], rules: &[isize]) -> Vec { let mut vec = once(0) .chain(interleave(rules, rows).copied()) @@ -577,7 +580,7 @@ impl Page { /// Returns the width of the headers along `axis`. fn headers_width(&self, axis: Axis2) -> isize { - self.axis_width(axis, rule_ofs(0)..cell_ofs(self.h[axis])) + self.axis_width(axis, rule_ofs(0)..cell_ofs(self.h()[axis])) } /// Returns the width of rule `z` along `axis`. @@ -610,7 +613,7 @@ impl Page { /// Returns the width of the widest cell, excluding headers, along `axis`. fn max_cell_width(&self, axis: Axis2) -> isize { - (self.h[axis]..self.n[axis]) + (self.h()[axis]..self.n[axis]) .map(|z| self.cell_width(axis, z)) .max() .unwrap_or(0) @@ -640,7 +643,7 @@ impl Page { } fn get_map(&self, axis: Axis2, z: usize) -> &Map { - if z < self.h[axis] { + if z < self.h()[axis] { &self.maps[axis][0] } else { &self.maps[axis][1] @@ -677,8 +680,8 @@ impl Page { /// 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`.) + /// The whole of axis `!a` is included. (The caller may follow up with + /// another call to select on `!a`.) fn select( self: &Arc, a: Axis2, @@ -689,17 +692,17 @@ impl Page { let b = !a; let z0 = extent.start; let z1 = extent.end; + let h = self.h(); // If all of the page is selected, just make a copy. - if z0 == self.h[a] && z1 == self.n[a] && pixel0 == 0 && pixel1 == 0 { + if z0 == h[a] && z1 == self.n[a] && pixel0 == 0 && pixel1 == 0 { return self.clone(); } // Figure out `n`, `h`, `r` for the subpage. - let trim = [z0 - self.h[a], self.n[a] - z1]; + let trim = [z0 - self.h()[a], self.n[a] - z1]; let mut n = self.n; n[a] -= trim[0] + trim[1]; - let h = self.h; let mut r = self.r.clone(); r[a].start += trim[0]; r[a].end -= trim[1]; @@ -757,7 +760,7 @@ impl Page { p1: pixel1, }; // Add overflows along the left side... - if self.h[a] == 0 || z0 > self.h[a] || pixel0 > 0 { + if h[a] == 0 || z0 > h[a] || pixel0 > 0 { let mut z = 0; while z < self.n[b] { let d = CellPos::for_axis((a, z0), z); @@ -774,11 +777,7 @@ impl Page { overflow[a][1] += pixel1 + self.axis_width(a, cell_ofs(z1)..cell_ofs(cell.rect[a].end)); } - assert!( - overflows - .insert(s.coord_to_subpage(cell.rect.top_left()), overflow) - .is_none() - ); + assert!(overflows.insert(s.coord_to_subpage(d), overflow).is_none()); } z += cell.rect[b].len(); } @@ -821,7 +820,6 @@ impl Page { Arc::new(Self { table: self.table.clone(), n, - h, r, maps, cp, @@ -912,10 +910,11 @@ impl Page { 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 h = self.h(); + if h[a] > 0 && coord[a] == h[a] { let border2 = self .table - .get_rule(a, CellPos::for_axis((a, self.h[a]), coord[!a])); + .get_rule(a, CellPos::for_axis((a, h[a]), coord[!a])); border.combine(border2) } else { border @@ -988,12 +987,20 @@ impl Selection { /// Returns the coordinates of `coord` as it will appear in this subpage. /// /// `coord` must be in the selected region or the results will not make - /// sense. + /// sense (or will panic due to overflow). fn coord_to_subpage(&self, coord: CellPos) -> CellPos { let a = self.a; let b = self.b; let ha0 = self.h[a]; - CellPos::for_axis((a, max(coord[a] + ha0 - self.z0, ha0)), coord[b]) + let z = coord[a]; + let z_subpage = if (0..ha0).contains(&z) { + z + } else if (self.z0..self.z1).contains(&z) { + z - self.z0 + ha0 + } else { + unreachable!("{z} is not in {:?} or {:?}", 0..ha0, self.z0..self.z1); + }; + CellPos::for_axis((a, z_subpage), coord[b]) } } @@ -1151,7 +1158,7 @@ struct Break { impl Break { fn new(page: Arc, axis: Axis2) -> Self { - let z = page.h[axis]; + let z = page.h()[axis]; let hw = page.headers_width(axis); Self { page, @@ -1172,7 +1179,7 @@ impl Break { // Width of header not including its rightmost rule. let mut size = self .page - .axis_width(self.axis, 0..rule_ofs(self.page.h[self.axis])); + .axis_width(self.axis, 0..rule_ofs(self.page.h()[self.axis])); // If we have a pixel offset and there is no header, then we omit // the leftmost rule of the body. Otherwise the rendering is deceptive @@ -1183,9 +1190,9 @@ impl Break { // rightmost rule in the header and the leftmost rule in the body. We // assume that the width of a merged rule is the larger of the widths of // either rule individually. - if self.pixel == 0 || self.page.h[self.axis] > 0 { + if self.pixel == 0 || self.page.h()[self.axis] > 0 { size += max( - self.page.rule_width(self.axis, self.page.h[self.axis]), + self.page.rule_width(self.axis, self.page.h()[self.axis]), self.page.rule_width(self.axis, self.z), ); }