fmt::Debug,
io::{Cursor, ErrorKind},
iter::{repeat, zip},
- marker::PhantomData,
mem::take,
num::NonZeroUsize,
ops::{Not, Range},
output::{
SpvGraphMembers, SpvInfo, SpvMembers,
drivers::cairo::{pt_to_xr, xr_to_pt},
- pivot::{Axis2, Axis3, Length, ParseLengthError, look::Color},
+ pivot::{
+ Axis2, Axis3, Length, ParseLengthError,
+ look::{Color, HorzAlign},
+ },
},
spv::{
legacy_bin::{DataSeries, DataSource, DataSources, LegacyBin, LegacyBinWarning},
mod style;
mod symbols;
-#[derive(Debug)]
-struct Ref<T> {
- references: String,
- _phantom: PhantomData<T>,
-}
-
-impl<T> Ref<T> {
- fn get<'a>(&self, table: &HashMap<&str, &'a T>) -> Option<&'a T> {
- table.get(self.references.as_str()).map(|v| &**v)
- }
-}
-
-impl<'de, T> Deserialize<'de> for Ref<T> {
- fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
- where
- D: serde::Deserializer<'de>,
- {
- Ok(Self {
- references: String::deserialize(deserializer)?,
- _phantom: PhantomData,
- })
- }
-}
-
#[derive(Clone, Debug, Default)]
struct Map(HashMap<Datum<String>, String>);
#[serde(rename = "@lang")]
lang: Option<String>,
- /// Base style for the graph.
+ /// The `id` for the base [Style] for the graph.
#[serde(rename = "@style")]
- _style: Option<Ref<Style>>,
+ _style: Option<String>,
/// Title or caption.
#[serde(rename = "@description")]
for frame in &frames.frames {
if let Some(label_frame) = frame.frame_type.as_label_frame()
&& let Some(left) = frame.position[Axis2::X].start()
- && let Some(_width) = frame.position[Axis2::X].length()
+ && let Some(right) = frame.position[Axis2::X].end()
&& let Some(top) = frame.position[Axis2::Y].start()
&& let Some(_height) = frame.position[Axis2::Y].length()
- && let Some(text) = label_frame.text()
+ && let Some(label) = &label_frame.label
{
+ let text = label.text().unwrap_or_default();
let _metrics = font_metrics.measure(&text);
+ let text_alignment = label
+ .style
+ .as_deref()
+ .and_then(|style| styles.get(style))
+ .and_then(|style| style.label_horz_align())
+ .unwrap_or(HorzAlign::Center);
+ let (x, text_anchor) = match text_alignment {
+ HorzAlign::Left | HorzAlign::Decimal { .. } => (left, "start"),
+ HorzAlign::Right => (right, "end"),
+ HorzAlign::Center => (left.midpoint(right), "middle"),
+ };
document.append(
svg::node::element::Text::new(text)
.with_id(&label_frame.id)
- .set("x", left)
+ .set("x", x)
.set("y", top)
.set("dominant-baseline", "hanging")
+ .set("text-anchor", text_anchor)
.set("font-family", "sans-serif"),
); /*
document.append(
#[serde(default)] // XXX not sure this is the correct default
categorical: bool,
- /// A variable whose string values correspond one-to-one with the values of
- /// this variable and are suitable as value labels.
+ /// The `id` for a [SourceVariable] whose string values correspond
+ /// one-to-one with the values of this variable and are suitable as value
+ /// labels.
#[serde(rename = "@labelVariable")]
- label_variable: Option<Ref<SourceVariable>>,
+ label_variable: Option<String>,
format: Option<Format>,
string_format: Option<StringFormat>,
_warn: &mut dyn FnMut(GraphWarning),
) -> bool {
let label_series = if let Some(label_variable) = &self.label_variable {
- if let Some(label_series) = series.get(label_variable.references.as_str()) {
+ if let Some(label_series) = series.get(label_variable.as_str()) {
Some(label_series)
} else {
return false;
#[serde(rename = "@target")]
target: String,
+ /// The `id` for a [Style].
#[serde(rename = "@style")]
- style: Ref<Style>,
+ style: String,
}
#[derive(Deserialize, Debug)]
#[serde(rename = "@target")]
target: String,
+ /// The `id` for a [Style].
#[serde(rename = "@style")]
- style: Ref<Style>,
+ style: String,
}
#[derive(Deserialize, Debug)]
#[serde(default, rename = "@connectingLines")]
connecting_lines: bool,
+ /// The `id` for a [Style].
#[serde(rename = "@style")]
- style: Option<Ref<Style>>,
+ style: Option<String>,
+ /// The `id` for a [Style].
#[serde(rename = "@textFrameStyle")]
- text_frame_style: Option<Ref<Style>>,
+ text_frame_style: Option<String>,
#[serde(rename = "$value", default)]
children: Vec<LabelingChild>,
#[derive(Deserialize, Debug)]
#[serde(rename_all = "camelCase")]
struct MajorTicks {
+ /// The `id` for a [Style].
#[serde(rename = "@style")]
- style: Ref<Style>,
+ style: String,
}
#[derive(Deserialize, Debug)]
#[serde(rename_all = "camelCase")]
struct Label {
+ /// The `id` for a [Style].
#[serde(rename = "@style")]
- style: Option<Ref<Style>>,
+ style: Option<String>,
+ /// The `id` for a [Style].
#[serde(rename = "@textFrameStyle")]
- text_frame_style: Option<Ref<Style>>,
+ text_frame_style: Option<String>,
#[serde(rename = "@purpose")]
purpose: Option<Purpose>,