Skip to content

Commit

Permalink
[glyphs] Handle additional custom params
Browse files Browse the repository at this point in the history
Specifically openTypeHeadLowestRecPPEM, and the various hhea & vhea
caret properties.

(vhea isn't handled yet, but we can at least parse it now in preparation)
  • Loading branch information
cmyr committed Nov 26, 2024
1 parent 23146c9 commit 0b33566
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 2 deletions.
54 changes: 52 additions & 2 deletions glyphs-reader/src/font.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,13 @@ pub struct CustomParameters {
pub codepage_range_bits: Option<BTreeSet<u32>>,
pub panose: Option<Vec<i64>>,

pub lowest_rec_ppem: Option<i64>,
pub hhea_caret_slope_run: Option<i64>,
pub hhea_caret_slope_rise: Option<i64>,
pub hhea_caret_offset: Option<i64>,
pub vhea_caret_slope_run: Option<i64>,
pub vhea_caret_slope_rise: Option<i64>,
pub vhea_caret_offset: Option<i64>,
// these fields are parsed via the config, but are stored
// in the top-level `Font` struct
pub virtual_masters: Option<Vec<BTreeMap<String, OrderedFloat<f64>>>>,
Expand Down Expand Up @@ -520,7 +527,15 @@ impl RawCustomParameters {
{
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));
Expand Down Expand Up @@ -570,14 +585,48 @@ 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. Maybe only fonts converted to glyphs format
// from something else?
"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:?}'"),
},
"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);
Expand Down Expand Up @@ -2266,6 +2315,7 @@ impl TryFrom<RawFont> for Font {

let mut custom_parameters = from.custom_parameters.cook()?;
let glyph_order = make_glyph_order(&from.glyphs, custom_parameters.glyph_order.take());

let axes = from.axes.clone();
let instances: Vec<_> = from
.instances
Expand Down
21 changes: 21 additions & 0 deletions glyphs2fontir/src/source.rs
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,9 @@ impl Work<Context, WorkId, Error> 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
Expand Down Expand Up @@ -607,6 +610,9 @@ impl Work<Context, WorkId, Error> 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 <https://github.com/googlefonts/glyphsLib/blob/9d5828d874110c42dfc5f542db8eb84f88641eb5/Lib/glyphsLib/builder/custom_params.py#L1136-L1156>
set_metric!(UnderlineThickness, underline_thickness, 50.0);
// -100.0 is the Glyphs default <https://github.com/googlefonts/glyphsLib/blob/9d5828d874110c42dfc5f542db8eb84f88641eb5/Lib/glyphsLib/builder/custom_params.py#L1136-L1156>
Expand Down Expand Up @@ -1846,4 +1852,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.);
}
}

0 comments on commit 0b33566

Please sign in to comment.