From 2afb9da08358807a853609393485f005fe061a95 Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Tue, 6 Jan 2026 11:18:09 -0800 Subject: [PATCH] work (breaks tests) --- rust/pspp/src/output/drivers/cairo/fsm.rs | 2 +- rust/pspp/src/output/drivers/text.rs | 43 +++++++++++++++++++---- rust/pspp/src/output/render.rs | 31 +++++++++++----- 3 files changed, 59 insertions(+), 17 deletions(-) diff --git a/rust/pspp/src/output/drivers/cairo/fsm.rs b/rust/pspp/src/output/drivers/cairo/fsm.rs index 0fb0c668d9..5e5738d6ac 100644 --- a/rust/pspp/src/output/drivers/cairo/fsm.rs +++ b/rust/pspp/src/output/drivers/cairo/fsm.rs @@ -553,7 +553,7 @@ impl Device for CairoDevice<'_> { todo!() } - fn draw_line(&mut self, bb: Rect2, styles: EnumMap) { + fn draw_line(&mut self, bb: Rect2, styles: EnumMap, _bg: Color) { let x0 = bb[Axis2::X].start; let y0 = bb[Axis2::Y].start; let x3 = bb[Axis2::X].end; diff --git a/rust/pspp/src/output/drivers/text.rs b/rust/pspp/src/output/drivers/text.rs index 855a87c940..5b778246ca 100644 --- a/rust/pspp/src/output/drivers/text.rs +++ b/rust/pspp/src/output/drivers/text.rs @@ -30,7 +30,8 @@ use unicode_linebreak::{BreakOpportunity, linebreaks}; use unicode_width::UnicodeWidthStr; use crate::output::{ - Itemlike, drivers::text::text_line::Attribute, render::Extreme, table::DrawCell, + Itemlike, drivers::text::text_line::Attribute, pivot::look::Color, render::Extreme, + table::DrawCell, }; use crate::output::{ @@ -650,7 +651,7 @@ impl Device for TextRenderer { unreachable!() } - fn draw_line(&mut self, bb: Rect2, styles: EnumMap) { + fn draw_line(&mut self, bb: Rect2, styles: EnumMap, bg: Color) { use Axis2::*; let x = bb[X].start.max(0)..bb[X].end.min(self.width); let y = bb[Y].start.max(0)..bb[Y].end; @@ -665,9 +666,25 @@ impl Device for TextRenderer { b: styles[X][1].stroke.into(), }; let c = self.box_chars[lines]; + let attribute = self.emphasis.is_some().then(|| { + let mut fg = Color::BLACK; + for styles in styles.values() { + for style in styles { + if style.stroke != Stroke::None { + fg = style.color; + break; + } + } + } + Attribute { + fg, + bg, + ..Attribute::default() + } + }); for y in y { self.get_line(y as usize) - .put_multiple(x.start as usize, c, x.len(), None); + .put_multiple(x.start as usize, c, x.len(), attribute); } } @@ -683,6 +700,22 @@ impl Device for TextRenderer { let text = display.to_string(); let horz_align = cell.horz_align(&display); + let attribute = self + .emphasis + .is_some() + .then(|| Attribute::for_style(cell.font_style)); + + if let Some(attribute) = attribute { + for y in bb[Y].clone() { + self.get_line(y as usize).put_multiple( + bb[X].start as usize, + ' ', + bb[X].len(), + Some(attribute), + ); + } + } + use Axis2::*; let breaks = new_line_breaks(&text, bb[X].len()); for (text, y) in breaks.zip(bb[Y].start + valign_offset..bb[Y].end) { @@ -700,10 +733,6 @@ impl Device for TextRenderer { continue; }; - let attribute = self - .emphasis - .is_some() - .then(|| Attribute::for_style(cell.font_style)); self.get_line(y as usize).put(x as usize, &text, attribute); } } diff --git a/rust/pspp/src/output/render.rs b/rust/pspp/src/output/render.rs index 2f0509e055..301eb0186a 100644 --- a/rust/pspp/src/output/render.rs +++ b/rust/pspp/src/output/render.rs @@ -24,6 +24,7 @@ use itertools::{Itertools, interleave}; use num::Integer; use smallvec::SmallVec; +use crate::output::pivot::look::Color; use crate::output::{ pivot::{ Axis2, Coord2, PivotTable, Rect2, @@ -138,7 +139,7 @@ pub trait Device { /// `styles[Axis2::X][1]`: style of line from bottom of `bb` to its center. /// `styles[Axis2::Y][0]`: style of line from left of `bb` to its center. /// `styles[Axis2::Y][1]`: style of line from right of `bb` to its center. - fn draw_line(&mut self, bb: Rect2, styles: EnumMap); + fn draw_line(&mut self, bb: Rect2, styles: EnumMap, bg: Color); /// Draws `cell` within bounding box `bb`. `clip` is the same as `bb` (the /// common case) or a subregion enclosed by `bb`. In the latter case only @@ -647,12 +648,29 @@ impl Page { continue; } - self.draw_rule(device, ofs, CellPos { x, y }, bb); + let bg = if !self.table.table.is_empty() { + let x = (x / 2).min(self.table.n().x - 1); + let y = (y / 2).min(self.table.n().y - 1); + let cell = self.table.table.get(CellPos::new(x, y)); + let area = cell.inner().area; + self.table.table.areas[area].font_style.bg + } else { + Color::WHITE + }; + + self.draw_rule(device, ofs, CellPos { x, y }, bb, bg); } } } - fn draw_rule(&self, device: &mut dyn Device, ofs: Coord2, coord: CellPos, bb: Rect2) { + fn draw_rule( + &self, + device: &mut dyn Device, + ofs: Coord2, + coord: CellPos, + bb: Rect2, + bg: Color, + ) { const NO_BORDER: BorderStyle = BorderStyle::none(); let styles = EnumMap::from_fn(|a: Axis2| { let b = !a; @@ -680,12 +698,7 @@ impl Page { } }); - if !styles - .values() - .all(|border| border.iter().all(BorderStyle::is_none)) - { - device.draw_line(bb.translate(ofs), styles); - } + device.draw_line(bb.translate(ofs), styles, bg); } fn get_rule(&self, a: Axis2, coord: CellPos) -> BorderStyle { -- 2.30.2