]> pintos-os.org Git - pspp/commitdiff
work on ticsk
authorBen Pfaff <blp@cs.stanford.edu>
Sun, 28 Jun 2026 02:10:44 +0000 (19:10 -0700)
committerBen Pfaff <blp@cs.stanford.edu>
Sun, 28 Jun 2026 02:10:44 +0000 (19:10 -0700)
rust/pspp/src/spv/read/graph.rs

index 32536e699a86f705bb50c66c63640bd16c48b287..2ddab431638a9a17acf37b0953aaceff603c0689 100644 (file)
@@ -17,6 +17,7 @@
 //#![allow(dead_code, unused)]
 use std::{
     borrow::{Borrow, Cow},
+    cell::RefCell,
     collections::{BTreeMap, HashMap},
     fmt::Debug,
     io::{Cursor, ErrorKind},
@@ -605,7 +606,7 @@ impl Visualization {
             document.assign("height", height);
         }
 
-        let mut font_metrics = FontMetrics::new();
+        let font_metrics = FontMetrics::new();
         for frame in &frames.frames {
             if let Some(label_frame) = frame.frame_type.as_label_frame()
                 && let Some(left) = frame.position[Axis2::X].start()
@@ -684,7 +685,7 @@ impl Visualization {
             styles,
         )?;
 
-        let mut font_metrics = FontMetrics::new();
+        let font_metrics = FontMetrics::new();
         let font_height = font_metrics.measure("0")[Axis2::Y];
         let mut rect = graph_frame.rect().unwrap();
 
@@ -737,7 +738,8 @@ impl Visualization {
                     &axis_domains[axis.into()],
                     rect.0[axis].length() - heading_heights[!axis],
                     graph.axis_dimension(axis),
-                    &mut font_metrics,
+                    &font_metrics,
+                    axis == Axis2::Y,
                 );
                 heading_heights[axis] = heading.total_height();
                 heading
@@ -1164,7 +1166,7 @@ impl Visualization {
 }
 
 struct FontMetrics {
-    layout: pango::Layout,
+    layout: RefCell<pango::Layout>,
 }
 
 impl FontMetrics {
@@ -1173,17 +1175,21 @@ impl FontMetrics {
         let context = Context::new(&surface).unwrap();
         let layout = pangocairo::functions::create_layout(&context);
         layout.set_font_description(Some(&FontDescription::from_string("sans-serif")));
-        Self { layout }
+        Self {
+            layout: RefCell::new(layout),
+        }
     }
-    fn measure(&mut self, s: &str) -> EnumMap<Axis2, f64> {
-        self.layout.set_text(s);
-        let (w, h) = self.layout.size();
+    fn measure(&self, s: &str) -> EnumMap<Axis2, f64> {
+        let layout = self.layout.borrow_mut();
+        layout.set_text(s);
+        let (w, h) = layout.size();
         enum_map! { Axis2::X => xr_to_pt(w as isize), Axis2::Y => xr_to_pt(h as isize) }
     }
-    fn measure_height_for_width(&mut self, s: &str, width: f64) -> f64 {
-        self.layout.set_width(pt_to_xr(width) as i32);
-        self.layout.set_text(s);
-        let (_w, h) = self.layout.size();
+    fn measure_height_for_width(&self, s: &str, width: f64) -> f64 {
+        let layout = self.layout.borrow_mut();
+        layout.set_width(pt_to_xr(width) as i32);
+        layout.set_text(s);
+        let (_w, h) = layout.size();
         xr_to_pt(h as isize)
     }
 }
@@ -4984,7 +4990,8 @@ impl<'a> FacetHeadings<'a> {
         axis_domain: &'a AxisDomain<'a>,
         width: f64,
         dimension: Option<&'a Dimension>,
-        font_metrics: &mut FontMetrics,
+        font_metrics: &FontMetrics,
+        rotate_ticks: bool,
     ) -> Self {
         let axis_facets = AxisFacets::new(facets);
         let n_facets = axis_facets.len();
@@ -5053,14 +5060,22 @@ impl<'a> FacetHeadings<'a> {
             })
             .collect();
         let ticks = axis_domain.axis.map(|axis| {
+            let ticks = axis_domain.ticks();
+            let ticks_height = ticks
+                .iter()
+                .map(|(_, s)| {
+                    font_metrics.measure(s)[if rotate_ticks { Axis2::Y } else { Axis2::Y }]
+                })
+                .max_by(|a, b| a.total_cmp(b))
+                .unwrap_or_default();
             (
                 if axis.opposite {
                     !default_side
                 } else {
                     default_side
                 },
-                axis_domain.ticks(),
-                10.0,
+                ticks,
+                ticks_height + 10.0,
             )
         });
         Self {
@@ -5083,6 +5098,7 @@ impl<'a> FacetHeadings<'a> {
             group: &mut Group,
             span: &DividedSpan,
             y: f64,
+            height: f64,
         ) {
             for facet_span in (0..this.n_facets).map(|index| span.nth(index)) {
                 for (frac, label) in ticks {
@@ -5095,10 +5111,26 @@ impl<'a> FacetHeadings<'a> {
                             .set("y2", y + 10.0)
                             .set("stroke", "black"),
                     );
+                }
+            }
+        }
+
+        fn render_tick_labels(
+            this: &FacetHeadings,
+            ticks: &[(f64, String)],
+            group: &mut Group,
+            span: &DividedSpan,
+            y: f64,
+            height: f64,
+        ) {
+            for facet_span in (0..this.n_facets).map(|index| span.nth(index)) {
+                for (frac, label) in ticks {
+                    let x = facet_span.frac(*frac);
+                    let label = if label.is_empty() { "x" } else { &label };
                     group.append(
                         svg::node::element::Text::new(dbg!(label))
                             .set("x", x)
-                            .set("y", y + 10.0)
+                            .set("y", y)
                             .set("dominant-baseline", "hanging")
                             .set("text-anchor", "middle"),
                     );
@@ -5111,7 +5143,8 @@ impl<'a> FacetHeadings<'a> {
             && side == *ticks_side
             && side == Side::Bottom
         {
-            render_ticks(self, ticks, &mut group, &span, y);
+            render_ticks(self, ticks, &mut group, &span, y, *height);
+            render_tick_labels(self, ticks, &mut group, &span, y + 10.0, *height);
             y += height;
         }
         /*
@@ -5211,7 +5244,15 @@ impl<'a> FacetHeadings<'a> {
             && *ticks_side == side
             && side == Side::Top
         {
-            render_ticks(self, ticks, &mut group, &span, y);
+            render_tick_labels(self, ticks, &mut group, &span, y, *height);
+            render_ticks(
+                self,
+                ticks,
+                &mut group,
+                &span,
+                y + (*height - 10.0),
+                *height,
+            );
             y += height;
         }
         group