Skip to content

Commit

Permalink
Make designspace source 'name' field optional
Browse files Browse the repository at this point in the history
This updates DesignSpaceDocument to allow inputs where sources do not
have names; we will autogenerate names if they are missing.
  • Loading branch information
cmyr committed Jun 29, 2023
1 parent e3249fe commit f50b7e7
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 1 deletion.
23 changes: 22 additions & 1 deletion src/designspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ pub struct Source {
#[serde(rename = "@stylename")]
pub stylename: Option<String>,
/// A unique name that can be used to identify this font if it needs to be referenced elsewhere.
#[serde(rename = "@name")]
#[serde(rename = "@name", default = "serde_impls::generate_missing_source_name")]
pub name: String,
/// A path to the source file, relative to the root path of this document.
///
Expand Down Expand Up @@ -162,6 +162,8 @@ impl DesignSpaceDocument {
}

mod serde_impls {
use std::sync::atomic::AtomicU64;

use super::{Axis, Dimension, Instance, Source};
use serde::{Deserialize, Deserializer};

Expand Down Expand Up @@ -208,6 +210,17 @@ mod serde_impls {
}
Helper::deserialize(deserializer).map(|x| x.source)
}

/// Generate a unique name for a source.
///
/// We do not make guarantees about what name will be assigned to a given
/// source, only that it will be unique within this process. If the designer
/// cares, they should provide a name explicitly.
pub fn generate_missing_source_name() -> String {
static COUNTER: AtomicU64 = AtomicU64::new(0);
let next_n = COUNTER.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
format!("unnamed_source_{next_n}")
}
}

#[cfg(test)]
Expand Down Expand Up @@ -265,4 +278,12 @@ mod tests {
fn load_with_no_instances() {
DesignSpaceDocument::load("testdata/no_instances.designspace").unwrap();
}

#[test]
fn load_with_no_source_name() {
let ds = DesignSpaceDocument::load("testdata/no_source_names.designspace").unwrap();
assert!(ds.sources[0].name.starts_with("unnamed_source_"));
assert!(ds.sources[1].name.starts_with("unnamed_source_"));
assert_ne!(ds.sources[0].name, ds.sources[1].name);
}
}
18 changes: 18 additions & 0 deletions testdata/no_source_names.designspace
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?xml version='1.0' encoding='UTF-8'?>
<designspace format="4.1">
<axes>
<axis tag="wght" name="Weight" minimum="400" maximum="700" default="400"/>
</axes>
<sources>
<source filename="TestFamily-Regular.ufo" stylename="Regular">
<location>
<dimension name="Weight" xvalue="400"/>
</location>
</source>
<source filename="TestFamily-Bold.ufo" stylename="Bold">
<location>
<dimension name="Weight" xvalue="700"/>
</location>
</source>
</sources>
</designspace>

0 comments on commit f50b7e7

Please sign in to comment.