diff --git a/glyphs-reader/src/font.rs b/glyphs-reader/src/font.rs index 492c52d89..7f94e69c6 100644 --- a/glyphs-reader/src/font.rs +++ b/glyphs-reader/src/font.rs @@ -3443,6 +3443,25 @@ impl Instance { tags_done.insert(axes[axis_index].tag.as_str()); } + // For non-wght without an "Axis Location" CP, the user + // location defaults to the design location (identity mapping), matching + // glyphsLib's AxisDefinition.get_user_loc() behavior: + // https://github.com/googlefonts/glyphsLib/blob/75c07d42/Lib/glyphsLib/builder/axes.py#L403-L405 + for (i, axis) in axes.iter().enumerate() { + if tags_done.contains(axis.tag.as_str()) { + continue; + } + if axis.tag == "wght" || axis.tag == "wdth" { + continue; + } + if let Some(&design) = value.axes_values.get(i) { + axis_mappings + .entry(axis.name.clone()) + .or_default() + .add_if_new(design, design); + } + } + // only infer legacy mappings when Axis Locations aren't defined if !masters_have_axis_locations && !tags_done.contains("wght") { // OS/2 weight_class corresponds to 'wght' axis user-space value @@ -4744,6 +4763,26 @@ mod tests { assert_eq!(font_without.axis_mappings, font.axis_mappings); } + #[test] + fn custom_axis_instance_without_axis_location_gets_identity_mapping() { + // A font with a custom axis (YEAR) where instances lack "Axis Location" CPs + // should get identity mappings (user = design) for that axis. + // Regression test for dancoull/ClimateCrisis crash. + let font = Font::load(&glyphs3_dir().join("CustomAxisNoAxisLocation.glyphs")).unwrap(); + + assert_eq!( + UserToDesignMapping(BTreeMap::from([( + "Year".into(), + AxisUserToDesignMap(vec![ + (OrderedFloat(1979.0), OrderedFloat(1979.0)), + (OrderedFloat(2020.0), OrderedFloat(2020.0)), + (OrderedFloat(2050.0), OrderedFloat(2050.0)), + ]) + )])), + font.axis_mappings + ); + } + #[test] fn loads_global_axis_mappings_from_instances_wdth_glyphs3() { let font = Font::load(&glyphs3_dir().join("WdthVar.glyphs")).unwrap(); diff --git a/resources/testdata/glyphs3/CustomAxisNoAxisLocation.glyphs b/resources/testdata/glyphs3/CustomAxisNoAxisLocation.glyphs new file mode 100644 index 000000000..839695dc1 --- /dev/null +++ b/resources/testdata/glyphs3/CustomAxisNoAxisLocation.glyphs @@ -0,0 +1,70 @@ +{ +.appVersion = "3316"; +.formatVersion = 3; +axes = ( +{ +name = Year; +tag = YEAR; +} +); +customParameters = ( +{ +name = "Variable Font Origin"; +value = m01; +} +); +familyName = CustomAxisTest; +fontMaster = ( +{ +axesValues = ( +1979 +); +id = m01; +name = "Master 1979"; +}, +{ +axesValues = ( +2050 +); +id = m02; +name = "Master 2050"; +} +); +glyphs = ( +{ +glyphname = space; +layers = ( +{ +layerId = m01; +width = 200; +}, +{ +layerId = m02; +width = 250; +} +); +unicode = 32; +} +); +instances = ( +{ +axesValues = ( +1979 +); +name = "Year 1979"; +}, +{ +axesValues = ( +2020 +); +name = "Year 2020"; +}, +{ +axesValues = ( +2050 +); +name = "Year 2050"; +} +); +unitsPerEm = 1000; +}