Skip to content

Commit

Permalink
Merge pull request #330 from googlefonts/kern
Browse files Browse the repository at this point in the history
Add example .glyphs kern and ability to read it
  • Loading branch information
rsheeter committed Jun 6, 2023
2 parents dff94e7 + 96d77c1 commit db5eca1
Show file tree
Hide file tree
Showing 4 changed files with 118 additions and 8 deletions.
74 changes: 72 additions & 2 deletions glyphs-reader/src/font.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ pub struct Font {
pub version_major: i32,
pub version_minor: u32,
pub date: Option<String>,

// master id => { (name or class, name or class) => adjustment }
pub kerning_ltr: BTreeMap<String, BTreeMap<(String, String), i32>>,
}

#[derive(Debug, PartialEq, Eq, Hash)]
Expand Down Expand Up @@ -968,13 +971,21 @@ impl RawFont {
Ok(())
}

fn v2_to_v3_kerning(&mut self) -> Result<(), Error> {
if let Some(kerning) = self.other_stuff.remove("kerning") {
self.other_stuff.insert("kerningLTR".to_string(), kerning);
};
Ok(())
}

/// `<See https://github.com/schriftgestalt/GlyphsSDK/blob/Glyphs3/GlyphsFileFormat/GlyphsFileFormatv3.md#differences-between-version-2>`
fn v2_to_v3(&mut self) -> Result<(), Error> {
self.v2_to_v3_weight()?;
self.v2_to_v3_axes()?;
self.v2_to_v3_metrics()?;
self.v2_to_v3_names()?;
self.v2_to_v3_instances()?;
self.v2_to_v3_kerning()?;
Ok(())
}
}
Expand Down Expand Up @@ -1027,6 +1038,31 @@ fn parse_codepoints(raw_font: &mut RawFont, radix: u32) -> BTreeMap<String, BTre
name_to_cp
}

fn parse_kerning(kerning: Option<&Plist>) -> BTreeMap<String, BTreeMap<(String, String), i32>> {
let mut result = BTreeMap::new();
let Some(Plist::Dictionary(kerning)) = kerning else {
return result;
};
for (master_id, kerning) in kerning {
let mut master_kerns = BTreeMap::new();
if let Plist::Dictionary(kerning) = kerning {
for (kern_from, kern_tos) in kerning {
let Plist::Dictionary(kern_tos) = kern_tos else {
continue;
};
for (kern_to, adjustment) in kern_tos {
let Some(adjustment) = adjustment.as_i64() else {
continue;
};
master_kerns.insert((kern_from.clone(), kern_to.clone()), adjustment as i32);
}
}
}
result.insert(master_id.clone(), master_kerns);
}
result
}

/// <https://github.com/googlefonts/glyphsLib/blob/6f243c1f732ea1092717918d0328f3b5303ffe56/Lib/glyphsLib/builder/axes.py#L578>
fn default_master_idx(raw_font: &RawFont) -> usize {
// Prefer an explicit origin
Expand Down Expand Up @@ -1584,6 +1620,7 @@ impl TryFrom<RawFont> for Font {
version_major: from.versionMajor.unwrap_or_default() as i32,
version_minor: from.versionMinor.unwrap_or_default() as u32,
date: from.date,
kerning_ltr: parse_kerning(from.other_stuff.get("kerningLTR")),
})
}
}
Expand Down Expand Up @@ -1662,7 +1699,7 @@ mod tests {
Font, FromPlist, Node, Plist, Shape,
};
use std::{
collections::{BTreeMap, BTreeSet},
collections::{BTreeMap, BTreeSet, HashSet},
path::{Path, PathBuf},
};

Expand All @@ -1673,7 +1710,11 @@ mod tests {
use kurbo::Affine;

fn testdata_dir() -> PathBuf {
let dir = Path::new("../resources/testdata");
// working dir varies CLI vs VSCode
let mut dir = Path::new("../resources/testdata");
if !dir.is_dir() {
dir = Path::new("./resources/testdata");
}
assert!(dir.is_dir());
dir.to_path_buf()
}
Expand Down Expand Up @@ -2139,4 +2180,33 @@ mod tests {
let font = Font::load(&glyphs2_dir().join("WghtVar_OS2.glyphs")).unwrap();
assert_eq!((None, None), (font.use_typo_metrics, font.has_wws_names));
}

#[test]
fn read_simple_kerning() {
let font = Font::load(&glyphs3_dir().join("WghtVar.glyphs")).unwrap();
assert_eq!(
HashSet::from(["m01", "E09E0C54-128D-4FEA-B209-1B70BEFE300B",]),
font.kerning_ltr
.keys()
.map(|k| k.as_str())
.collect::<HashSet<_>>()
);

let actual_kerning = font
.kerning_ltr
.get("m01")
.unwrap()
.iter()
.map(|((n1, n2), value)| (n1.as_str(), n2.as_str(), *value))
.collect::<Vec<_>>();

assert_eq!(
vec![
("exclam", "exclam", -360),
("exclam", "hyphen", 20),
("hyphen", "hyphen", -150),
],
actual_kerning,
);
}
}
2 changes: 2 additions & 0 deletions glyphs2fontir/src/source.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ impl GlyphsIrSource {
version_major: Default::default(),
version_minor: Default::default(),
date: None,
kerning_ltr: Default::default(),
};
state.track_memory("/font_master".to_string(), &font)?;
Ok(state)
Expand Down Expand Up @@ -117,6 +118,7 @@ impl GlyphsIrSource {
version_major: Default::default(),
version_minor: Default::default(),
date: None,
kerning_ltr: font.kerning_ltr.clone(),
};
state.track_memory("/font_master".to_string(), &font)?;
Ok(state)
Expand Down
25 changes: 22 additions & 3 deletions resources/testdata/glyphs2/WghtVar.glyphs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
.appVersion = "3151";
DisplayStrings = (
"-",
"!"
"!!--"
);
copyright = "Copy!";
customParameters = (
Expand Down Expand Up @@ -84,7 +84,7 @@ unicode = 0020;
},
{
glyphname = exclam;
lastChange = "2022-12-01 05:10:49 +0000";
lastChange = "2023-06-05 23:22:51 +0000";
layers = (
{
layerId = m01;
Expand Down Expand Up @@ -139,7 +139,7 @@ unicode = 0021;
},
{
glyphname = hyphen;
lastChange = "2022-12-01 04:57:39 +0000";
lastChange = "2023-06-05 23:23:03 +0000";
layers = (
{
layerId = m01;
Expand Down Expand Up @@ -208,6 +208,25 @@ width = 600;
unicode = 003D;
}
);
kerning = {
m01 = {
exclam = {
exclam = -360;
hyphen = 20;
};
hyphen = {
hyphen = -150;
};
};
"E09E0C54-128D-4FEA-B209-1B70BEFE300B" = {
exclam = {
exclam = -100;
};
hyphen = {
hyphen = -50;
};
};
};
unitsPerEm = 1000;
versionMajor = 42;
versionMinor = 42;
Expand Down
25 changes: 22 additions & 3 deletions resources/testdata/glyphs3/WghtVar.glyphs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
.formatVersion = 3;
DisplayStrings = (
"-",
"!"
"!!--"
);
axes = (
{
Expand Down Expand Up @@ -93,7 +93,7 @@ unicode = 32;
},
{
glyphname = exclam;
lastChange = "2022-12-01 05:10:49 +0000";
lastChange = "2023-06-05 23:22:51 +0000";
layers = (
{
layerId = m01;
Expand Down Expand Up @@ -148,7 +148,7 @@ unicode = 33;
},
{
glyphname = hyphen;
lastChange = "2022-12-01 04:57:39 +0000";
lastChange = "2023-06-05 23:23:03 +0000";
layers = (
{
layerId = m01;
Expand Down Expand Up @@ -218,6 +218,25 @@ width = 600;
unicode = 61;
}
);
kerningLTR = {
m01 = {
exclam = {
exclam = -360;
hyphen = 20;
};
hyphen = {
hyphen = -150;
};
};
"E09E0C54-128D-4FEA-B209-1B70BEFE300B" = {
exclam = {
exclam = -100;
};
hyphen = {
hyphen = -50;
};
};
};
metrics = (
{
type = ascender;
Expand Down

0 comments on commit db5eca1

Please sign in to comment.