From abd5b7c5134c2d96cd74db46da4b55f8de2568dd Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Thu, 24 Apr 2025 16:23:41 -0700 Subject: [PATCH] work --- rust/pspp/src/output/cairo/fsm.rs | 1 + rust/pspp/src/output/cairo/pager.rs | 99 +++++++++++++++++++++++++++-- 2 files changed, 95 insertions(+), 5 deletions(-) diff --git a/rust/pspp/src/output/cairo/fsm.rs b/rust/pspp/src/output/cairo/fsm.rs index c8009dfb3b..7df9ba9a14 100644 --- a/rust/pspp/src/output/cairo/fsm.rs +++ b/rust/pspp/src/output/cairo/fsm.rs @@ -27,6 +27,7 @@ fn pxf_to_xr(x: f64) -> usize { (x * (SCALE as f64 * 72.0 / 96.0)).round() as usize } +#[derive(Clone, Debug)] pub struct CairoFsmStyle { /// Page size. pub size: Coord2, diff --git a/rust/pspp/src/output/cairo/pager.rs b/rust/pspp/src/output/cairo/pager.rs index e7f649da4e..54d0221b8d 100644 --- a/rust/pspp/src/output/cairo/pager.rs +++ b/rust/pspp/src/output/cairo/pager.rs @@ -5,12 +5,16 @@ use enum_map::EnumMap; use pango::{FontDescription, Layout}; use crate::output::{ - cairo::{fsm::CairoFsmStyle, horz_align_to_pango, xr_to_pt}, + cairo::{ + fsm::{CairoFsm, CairoFsmStyle}, + horz_align_to_pango, xr_to_pt, + }, page::Heading, pivot::Axis2, - OwnedItemCursor, + Item, OwnedItemCursor, }; +#[derive(Clone, Debug)] pub struct CairoPageStyle { pub margins: EnumMap, pub headings: [Heading; 2], @@ -23,18 +27,103 @@ pub struct CairoPager { page_index: i32, heading_heights: [usize; 2], iter: Option, + context: Option, + fsm: Option, + y: usize, } impl CairoPager { - fn new(page_style: Arc, fsm_style: Arc) -> Self { + fn new(mut page_style: Arc, mut fsm_style: Arc) -> Self { + let heading_heights = measure_headings(&page_style, &fsm_style); + let total = heading_heights.iter().sum::(); + if (0..fsm_style.size[Axis2::Y]).contains(&total) { + let fsm_style = Arc::make_mut(&mut fsm_style); + let page_style = Arc::make_mut(&mut page_style); + for i in 0..2 { + page_style.margins[Axis2::Y][i] += heading_heights[i]; + } + fsm_style.size[Axis2::Y] -= total; + } Self { - heading_heights: measure_headings(&page_style, &fsm_style), + heading_heights, page_style, fsm_style, page_index: 0, iter: None, } } + + fn add_page(&mut self, context: Context) { + assert!(self.context.is_none()); + context.save().unwrap(); + self.y = 0; + + context.translate( + xr_to_pt(self.page_style.margins[Axis2::X][0]), + xr_to_pt(self.page_style.margins[Axis2::Y][0]), + ); + + let page_number = self.page_index + self.page_style.initial_page_number; + self.page_index += 1; + + if self.heading_heights[0] > 0 { + render_heading( + &context, + &self.fsm_style.font, + &self.page_style.headings[0], + page_number, + self.fsm_style.size[Axis2::X], + 0, /* XXX*/ + self.fsm_style.font_resolution, + ); + } + if self.heading_heights[0] > 0 { + render_heading( + &context, + &self.fsm_style.font, + &self.page_style.headings[1], + page_number, + self.fsm_style.size[Axis2::X], + self.fsm_style.size[Axis2::Y] + self.fsm_style.object_spacing, + self.fsm_style.font_resolution, + ); + } + + self.context = Some(context); + self.run(); + } + + fn finish_page(&mut self) { + if let Some(context) = self.context.take() { + context.restore().unwrap(); + } + } + + fn add_item(&mut self, item: Arc) { + self.iter = Some(OwnedItemCursor::new(item)); + self.run(); + } + + fn run(&mut self) { + if self.iter.is_none() || self.context.is_none() || self.y >= self.fsm_style.size[Axis2::Y] + { + return; + } + + loop { + // Make sure we've got an object to render. + while self.fsm.is_none() { + // If there are no remaining objects to render, then we're done. + if self.iter.as_mut().unwrap().cur().is_none() { + self.iter = None; + return; + } + + // Prepare to render the current object. + let fsm = CairoFsm::new(self.fsm_style.clone(), true, self.context.clone(), self) + } + } + } } fn measure_headings(page_style: &CairoPageStyle, fsm_style: &CairoFsmStyle) -> [usize; 2] { @@ -83,7 +172,7 @@ fn render_heading( layout.set_width(width as i32); context.save().unwrap(); - context.translate(0.0, xr_to_pt(width)); + context.translate(0.0, xr_to_pt(y + base_y)); pangocairo::functions::show_layout(context, &layout); context.restore().unwrap(); -- 2.30.2