diff --git a/glyphs-reader/src/font.rs b/glyphs-reader/src/font.rs index a2b5c243..60403eaa 100644 --- a/glyphs-reader/src/font.rs +++ b/glyphs-reader/src/font.rs @@ -95,6 +95,13 @@ pub struct CustomParameters { pub codepage_range_bits: Option>, pub panose: Option>, + pub lowest_rec_ppem: Option, + pub hhea_caret_slope_run: Option, + pub hhea_caret_slope_rise: Option, + pub hhea_caret_offset: Option, + pub vhea_caret_slope_run: Option, + pub vhea_caret_slope_rise: Option, + pub vhea_caret_offset: Option, // these fields are parsed via the config, but are stored // in the top-level `Font` struct pub virtual_masters: Option>>>, @@ -524,7 +531,15 @@ impl RawCustomParameters { // function. macro_rules! add_and_report_issues { ($field:ident, $converter:path) => {{ - let value = $converter(value); + add_and_report_issues!($field, $converter(value)) + }}; + + ($field:ident, $converter:path, into) => {{ + add_and_report_issues!($field, $converter(value).map(Into::into)) + }}; + + ($field:ident, $value_expr:expr) => {{ + let value = $value_expr; if value.is_none() { log::warn!("failed to parse param for '{}'", stringify!($field)); @@ -574,6 +589,40 @@ impl RawCustomParameters { "codePageRanges" => { add_and_report_issues!(codepage_range_bits, Plist::as_codepage_bits) } + // these values are not listed in the glyphs.app UI, but exist + // in some fonts: + // https://github.com/googlefonts/fontc/pull/1144#issuecomment-2503134008 + "openTypeHeadLowestRecPPEM" => { + add_and_report_issues!(lowest_rec_ppem, Plist::as_i64) + } + "openTypeHheaCaretSlopeRun" => { + add_and_report_issues!(hhea_caret_slope_run, Plist::as_i64) + } + "openTypeHheaCaretSlopeRise" => { + add_and_report_issues!(hhea_caret_slope_rise, Plist::as_i64) + } + "openTypeHheaCaretOffset" => { + add_and_report_issues!(hhea_caret_offset, Plist::as_i64) + } + "openTypeVheaCaretSlopeRun" => { + add_and_report_issues!(vhea_caret_slope_run, Plist::as_i64) + } + "openTypeVheaCaretSlopeRise" => { + add_and_report_issues!(vhea_caret_slope_rise, Plist::as_i64) + } + "openTypeVheaCaretOffset" => { + add_and_report_issues!(vhea_caret_offset, Plist::as_i64) + } + // these might need to be handled? they're in the same list as + // the items above: + // https://github.com/googlefonts/glyphsLib/blob/74c63244fdb/Lib/glyphsLib/builder/custom_params.py#L429 + "openTypeNameUniqueID" + | "openTypeNameVersion" + | "openTypeOS2FamilyClass" + | "openTypeHeadFlags" => { + log::warn!("unhandled custom param '{name}'") + } + "Virtual Master" => match value.as_virtual_master() { Some(val) => virtual_masters.push(val), None => log::warn!("failed to parse virtual master '{value:?}'"), @@ -581,7 +630,7 @@ impl RawCustomParameters { "panose" => panose = value.as_vec_of_ints(), "openTypeOS2Panose" => panose_old = value.as_vec_of_ints(), "glyphOrder" => add_and_report_issues!(glyph_order, Plist::as_vec_of_string), - _ => log::warn!("unhandled custom parameter '{name}'"), + _ => log::warn!("unknown custom parameter '{name}'"), } } params.panose = panose.or(panose_old); @@ -2270,6 +2319,7 @@ impl TryFrom for Font { let mut custom_parameters = from.custom_parameters.to_custom_params()?; let glyph_order = make_glyph_order(&from.glyphs, custom_parameters.glyph_order.take()); + let axes = from.axes.clone(); let instances: Vec<_> = from .instances diff --git a/glyphs2fontir/src/source.rs b/glyphs2fontir/src/source.rs index 6b6d4603..61da51b8 100644 --- a/glyphs2fontir/src/source.rs +++ b/glyphs2fontir/src/source.rs @@ -429,6 +429,9 @@ impl Work for StaticMetadataWork { static_metadata.misc.version_major = font.version_major; static_metadata.misc.version_minor = font.version_minor; + if let Some(lowest_rec_ppm) = font.custom_parameters.lowest_rec_ppem { + static_metadata.misc.lowest_rec_ppm = lowest_rec_ppm as _; + } static_metadata.misc.created = font .date @@ -607,6 +610,9 @@ impl Work for GlobalMetricWork { set_metric!(HheaAscender, hhea_ascender); set_metric!(HheaDescender, hhea_descender); set_metric!(HheaLineGap, hhea_line_gap); + set_metric!(CaretSlopeRun, hhea_caret_slope_run); + set_metric!(CaretSlopeRise, hhea_caret_slope_rise); + set_metric!(CaretOffset, hhea_caret_offset); // 50.0 is the Glyphs default set_metric!(UnderlineThickness, underline_thickness, 50.0); // -100.0 is the Glyphs default @@ -1844,4 +1850,19 @@ mod tests { context.static_metadata.get().misc.panose ); } + + #[test] + fn capture_unsual_params() { + // both parameters; value under short name should be preferred + let (_, context) = build_static_metadata(glyphs3_dir().join("UnusualCustomParams.glyphs")); + let meta = context.static_metadata.get(); + assert_eq!(meta.misc.lowest_rec_ppm, 7); + + // some of these end up as metrics: + let (_, context) = build_global_metrics(glyphs3_dir().join("UnusualCustomParams.glyphs")); + let metrics = context.global_metrics.get(); + assert_eq!(unique_value(&metrics, GlobalMetric::CaretOffset), 2.); + assert_eq!(unique_value(&metrics, GlobalMetric::CaretSlopeRise), 1.); + assert_eq!(unique_value(&metrics, GlobalMetric::CaretSlopeRun), 5.); + } } diff --git a/resources/testdata/glyphs3/UnusualCustomParams.glyphs b/resources/testdata/glyphs3/UnusualCustomParams.glyphs new file mode 100644 index 00000000..b440ea90 --- /dev/null +++ b/resources/testdata/glyphs3/UnusualCustomParams.glyphs @@ -0,0 +1,36 @@ +{ +.appVersion = "3260"; +.formatVersion = 3; +customParameters = ( +{ +name = openTypeHeadFlags; +value = ( +0 +); +}, +{ +name = openTypeHeadLowestRecPPEM; +value = 7; +}, +{ +name = openTypeHheaCaretOffset; +value = 2; +}, +{ +name = openTypeHheaCaretSlopeRise; +value = 1; +}, +{ +name = openTypeHheaCaretSlopeRun; +value = 5; +}, +); +familyName = UnusualParams; +fontMaster = ( +{ +id = master01; +name = Regular; +} +); +unitsPerEm = 1000; +}