//#![allow(dead_code, unused)]
use std::{
borrow::{Borrow, Cow},
+ cell::RefCell,
collections::{BTreeMap, HashMap},
fmt::Debug,
io::{Cursor, ErrorKind},
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()
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();
&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
}
struct FontMetrics {
- layout: pango::Layout,
+ layout: RefCell<pango::Layout>,
}
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)
}
}
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();
})
.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 {
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 {
.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"),
);
&& 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;
}
/*
&& *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