-
Notifications
You must be signed in to change notification settings - Fork 13
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support loading from .glyphspackage #447
Conversation
dd7c62b
to
ab554d2
Compare
So I added a |
d21c26b
to
0ca0866
Compare
(in case you were in the middle of a review, I just rebased on origin/main to incorporate #446 just merged, no other changes) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Happy to see that this patch is not actually 3k lines of code. That said I think github is starting to choke on font.rs here and we should maybe split it up a bit?
A bunch of notes inline; I spent a while playing around trying to clean this code up a bit and it's not that easy, although it did motivate me to open #450, which should let us improve the situation somewhat...
glyphs-reader/src/font.rs
Outdated
Regex::new(r"(?mi)^(?P<prefix>\s*glyphname\s*=\s*)(?P<value>(?:infinity|inf|nan));\s*$") | ||
.unwrap(); | ||
let s = unicode_re.replace_all(&s, r#"$prefix"$value";"#); | ||
let s = glyphname_re.replace_all(&s, r#"$prefix"$value";"#); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is this based on other code, or brand new?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if a glyph is named "infinity", "inf" or "nan" and the name is un-quoted (as Glyphs.app does when a string only contains ascii), our plist parser misunderstands it as a float
https://doc.rust-lang.org/std/primitive.f64.html#grammar
so I uses regex to add the quotes and make sure they stay as strings
We had code (that I removed here) which would fix up the parsed glyph plist dict and unconditionally replace "glyphname" typed float with a hard-coded "infinity" string (ignoring "inf" or "nan").
I think the python openstep-plist parser (used by glyphsLib and thus fontmake) does not have this problem because it can detect that an unquoted string is neither an integer nor a float (https://github.com/fonttools/openstep-plist/blob/c9acd408ba3a374ba41dd62f595f43fa2e5bfa6f/src/openstep_plist/parser.pyx#L267-L309) and thus treat it as string; I think our current rust plist parser attempts to parse as number and if that succeeds (as in the case of "infinity") it treats it as such, so we need to prevent that -- or change the parser (but I haven't even looked into that.. would you like me to?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I changed the plist parser itself to always treat "infinity", "inf" and "nan" as strings, so we don't need the regex hack any more. I don't think inf or NaN are useful in font source formats
glyphs-reader/src/font.rs
Outdated
let glyph_plist = Plist::parse(&glyph_data) | ||
.map_err(|e| Error::ParseError(entry.path(), format!("{e:#?}")))?; | ||
let Plist::Dictionary(ref glyph_dict) = glyph_plist else { | ||
return Err(Error::ParseError( | ||
entry.path(), | ||
"Glyph must be a dict".to_string(), | ||
)); | ||
}; | ||
let glyph_name = glyph_dict | ||
.get("glyphname") | ||
.map(|s| s.to_string()) | ||
.ok_or_else(|| { | ||
Error::ParseError( | ||
entry.path(), | ||
"Glyph dict must have a 'glyphname' key".to_string(), | ||
) | ||
})?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if you rebase on #450 I hope you can now just write,
let glyph_plist = Plist::parse(&glyph_data) | |
.map_err(|e| Error::ParseError(entry.path(), format!("{e:#?}")))?; | |
let Plist::Dictionary(ref glyph_dict) = glyph_plist else { | |
return Err(Error::ParseError( | |
entry.path(), | |
"Glyph must be a dict".to_string(), | |
)); | |
}; | |
let glyph_name = glyph_dict | |
.get("glyphname") | |
.map(|s| s.to_string()) | |
.ok_or_else(|| { | |
Error::ParseError( | |
entry.path(), | |
"Glyph dict must have a 'glyphname' key".to_string(), | |
) | |
})?; | |
let glyph_dict = Plist::parse(&glyph_data) | |
.and_then(Plist::expect_dict) | |
.map_err(|e| Error::ParseError(entry.path(), e.to_string()))?; | |
let glyph_name = glyph_dict | |
.get("glyphname") | |
.map(|s| s.expect_string().ok()) | |
.ok_or_else(|| { | |
Error::ParseError( | |
entry.path(), | |
"Glyph dict must have a 'glyphname' key".to_string(), | |
) | |
})?; |
which... is still pretty gross!
…ckage matches test currently fails
to avoid spurious diffs when comparing against .glyphspackage generated using the same Glyphs build
I could not open the infinity.glyphs test file in Glyphs, it complained about an unrecognized parenthesis, apparently the fontMaster cannot be empty
and open and save infinity.glyphs to avoid spurious diffs, sorry nice indentation
was added automatically by Glyphs when saving, but we have another test that expects it to be absent and asserts it defaults to 0.000
make load_package private use path.extension() use e.to_string() instead of format!({e:#?})
0ca0866
to
358da6f
Compare
I'm not sure things have improved much...
46ca7b6
to
69f890d
Compare
remove the regex hack. We don't need to parse infinity or NaN as floats in font formats
69f890d
to
02aa40b
Compare
22a24cd
to
773fcf8
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's definitely a lot of room for cleanup here but I think it's worth getting this merged :)
Fixes #435
Initially this is just adding the test .glyphspackage files ("saved as" from the existing .glyphs test files using the latest Glyphs.app), so the test is going to fail. Will follow up with the implementation itself.