Skip to content

Commit

Permalink
[glyphs] Handle legacy stylistic set names
Browse files Browse the repository at this point in the history
These were stored in the 'notes' field.
  • Loading branch information
cmyr committed Dec 4, 2024
1 parent 28f7e48 commit f12300b
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 23 deletions.
68 changes: 45 additions & 23 deletions glyphs-reader/src/font.rs
Original file line number Diff line number Diff line change
Expand Up @@ -740,6 +740,7 @@ struct RawFeature {
disabled: Option<i64>,
name: Option<String>,
tag: Option<String>,
notes: Option<String>,
code: String,
labels: Vec<RawNameValue>,

Expand Down Expand Up @@ -2131,31 +2132,29 @@ impl RawFeature {
self.disabled == Some(1)
}

/// Some glyphs sources store stylistic set names in the 'note' field
///
/// See the little sidebar item here:
/// <https://glyphsapp.com/learn/stylistic-sets#g-names-for-stylistic-sets>
fn legacy_name_record_maybe(&self) -> Option<String> {
let name = self.notes.as_deref()?.strip_prefix("Name:")?.trim();
Some(format!("name 3 1 0x409 \"{name}\";"))
}

// https://github.com/googlefonts/glyphsLib/blob/24b4d340e4c82948ba121dcfe563c1450a8e69c9/Lib/glyphsLib/builder/features.py#L134
fn feature_names(&self) -> String {
if self.labels.is_empty() {
return String::new();
}
let labels = self
.labels
.iter()
.filter_map(|label| {
GLYPHS_TO_OPENTYPE_LANGUAGE_ID
.binary_search_by_key(&label.language, |entry| entry.0.to_owned())
.ok()
.map(|index| {
let language_id = &GLYPHS_TO_OPENTYPE_LANGUAGE_ID[index].1;
let name = label.value.replace("\\", "\\005c").replace("\"", "\\0022");
format!(" name 3 1 0x{:04X} \"{}\";", language_id, name)
})
.or_else(|| {
warn!("Unknown feature label language: {}", label.language);
None
})
})
.filter_map(|label| label.to_fea())
.chain(self.legacy_name_record_maybe())
.collect::<Vec<_>>()
.join("\n");
format!("featureNames {{\n{}\n}};\n", labels)
if labels.is_empty() {
Default::default()
} else {
format!("featureNames {{\n{}\n}};\n", labels)
}
}

// https://github.com/googlefonts/glyphsLib/blob/24b4d340e4c82948ba121dcfe563c1450a8e69c9/Lib/glyphsLib/builder/features.py#L90
Expand Down Expand Up @@ -2190,6 +2189,24 @@ impl RawFeature {
}
}

impl RawNameValue {
fn to_fea(&self) -> Option<String> {
match GLYPHS_TO_OPENTYPE_LANGUAGE_ID
.binary_search_by_key(&self.language.as_str(), |entry| entry.0)
{
Ok(idx) => {
let language_id = GLYPHS_TO_OPENTYPE_LANGUAGE_ID[idx].1;
let name = self.value.replace("\\", "\\005c").replace("\"", "\\0022");
Some(format!(" name 3 1 0x{:04X} \"{}\";", language_id, name))
}
Err(_) => {
warn!("Unknown feature label language: {}", self.language);
None
}
}
}
}

/// <https://github.com/googlefonts/glyphsLib/blob/6f243c1f732ea1092717918d0328f3b5303ffe56/Lib/glyphsLib/classes.py#L220-L249>
fn lookup_class_value(axis_tag: &str, user_class: &str) -> Option<u16> {
let user_class = match user_class {
Expand Down Expand Up @@ -3215,13 +3232,9 @@ mod tests {
#[test]
fn tags_make_excellent_names() {
let raw = RawFeature {
name: None,
tag: Some("aalt".to_string()),
automatic: None,
disabled: None,
code: "blah".to_string(),
labels: vec![],
other_stuff: BTreeMap::new(),
..Default::default()
};
assert_eq!("aalt", raw.name().unwrap());
}
Expand Down Expand Up @@ -3568,4 +3581,13 @@ mod tests {
font.custom_parameters.underline_position
);
}

#[test]
fn parse_legacy_stylistic_set_name() {
let font = Font::load(&glyphs2_dir().join("FeaLegacyName.glyphs")).unwrap();
assert_eq!(font.features.len(), 1);
assert!(font.features[0]
.content
.contains("name 3 1 0x409 \"Alternate placeholder\""));
}
}
40 changes: 40 additions & 0 deletions resources/testdata/glyphs2/FeaLegacyName.glyphs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{
.appVersion = "3148";
familyName = "legacy stylistic set names";
features = (
{
automatic = 1;
code = "sub a by a.ss01;";
name = ss01;
notes = "Name: Alternate placeholder";
},
);
fontMaster = (
{
id = "m01";
},
);
glyphs = (

{
glyphname = a;
layers = (
{
layerId = "m01";
width = 600;
}
);
unicode = 97;
},
{
glyphname = a.ss01;
layers = (
{
layerId = "m01";
width = 600;
}
);
},
);
unitsPerEm = 1000;
}

0 comments on commit f12300b

Please sign in to comment.