-
Notifications
You must be signed in to change notification settings - Fork 37
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
Show kerning groups in the sidebar. #241
Open
xorgy
wants to merge
1
commit into
linebender:master
Choose a base branch
from
xorgy:sidebar-show-kern-group
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -87,6 +87,8 @@ pub struct GlyphDetail { | |
// the full outline, including things like components | ||
pub outline: Arc<BezPath>, | ||
metrics: FontMetrics, | ||
pub kern1_group: String, | ||
pub kern2_group: String, | ||
is_placeholder: bool, | ||
} | ||
|
||
|
@@ -599,6 +601,7 @@ mod lenses { | |
use std::sync::Arc; | ||
|
||
use druid::{Data, Lens}; | ||
use norad::glyph::Glyph; | ||
use norad::GlyphName as GlyphName_; | ||
|
||
use super::{ | ||
|
@@ -722,10 +725,13 @@ mod lenses { | |
let outline = state.font.get_bezier(&glyph.name); | ||
let is_placeholder = outline.is_none(); | ||
let metrics = state.font.info.metrics.clone(); | ||
let (kern1_group, kern2_group) = find_kern_groups(&state.font, &glyph); | ||
GlyphDetail { | ||
glyph, | ||
outline: outline.unwrap_or_else(|| state.font.font.placeholder.clone()), | ||
is_placeholder, | ||
kern1_group, | ||
kern2_group, | ||
metrics, | ||
} | ||
} | ||
|
@@ -762,10 +768,13 @@ mod lenses { | |
let outline = data.get_bezier(&glyph.name); | ||
let is_placeholder = outline.is_none(); | ||
let metrics = data.info.metrics.clone(); | ||
let (kern1_group, kern2_group) = find_kern_groups(data, glyph); | ||
GlyphDetail { | ||
glyph: Arc::clone(glyph), | ||
outline: outline.unwrap_or_else(|| data.font.placeholder.clone()), | ||
metrics, | ||
kern1_group, | ||
kern2_group, | ||
is_placeholder, | ||
} | ||
}); | ||
|
@@ -786,10 +795,13 @@ mod lenses { | |
let outline = data.get_bezier(&glyph.name); | ||
let is_placeholder = outline.is_none(); | ||
let metrics = data.info.metrics.clone(); | ||
let (kern1_group, kern2_group) = find_kern_groups(data, glyph); | ||
GlyphDetail { | ||
glyph: Arc::clone(glyph), | ||
outline: outline.unwrap_or_else(|| data.font.placeholder.clone()), | ||
metrics, | ||
kern1_group, | ||
kern2_group, | ||
is_placeholder, | ||
} | ||
}); | ||
|
@@ -911,6 +923,25 @@ mod lenses { | |
f(&mut s) | ||
} | ||
} | ||
|
||
fn find_kern_groups(data: &Workspace, glyph: &Glyph) -> (String, String) { | ||
let mut kern1_group = "".to_string(); | ||
let mut kern2_group = "".to_string(); | ||
Comment on lines
+928
to
+929
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I guess a few different things here:
At a higher level: I wonder if runebender shouldn't keep track of kern groups via some other mechanism, and only extract / write back to the UFO format as needed? trying to manipulate this directly just feels so awkward. |
||
if let Some(gs) = &data.font.ufo.groups { | ||
for (gk, gv) in gs.iter() { | ||
if let Some(gn) = gk.strip_prefix("public.kern1.") { | ||
if (*gv).iter().any(|n| *n == glyph.name) { | ||
kern1_group = gn.to_string(); | ||
} | ||
} else if let Some(gn) = gk.strip_prefix("public.kern2.") { | ||
if (*gv).iter().any(|n| *n == glyph.name) { | ||
kern2_group = gn.to_string(); | ||
} | ||
} | ||
} | ||
} | ||
(kern1_group, kern2_group) | ||
} | ||
} | ||
|
||
//FIXME: put this in some `GlyphExt` trait or something | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
lens get processed a lot, so I'm cautious of doing work in them that might get expensive. I guess this isn't too bad, being O(nm) over the number of glyphs and number of groups, which have practical upper bounds?
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.
Due to the way that it searches, I think it is always worst case on n, and the typical case for m is hard to say.
The better way to do this would be to have the core glyph datastructure hold the kern1 and kern2 group until it's time to save, since UFO demands there only be one of them per glyph anyway. The thing that makes that messy is that the glyphs as they come from Norad are not coupled to the font overall; this is nice for concurrent loading, but because UFO is kinda a mess, it makes it uglier to meet the constraints.
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.
so maybe a compromise would be to have something like a
HashMap<GlyphName, [GroupName; 2]>
in the runebenderFontObject
, or something?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.
Hmm, that could work; it would definitely be faster. This seems like a problem that should be solved at the Norad level though, since it deals with maintaining a spec constraint.
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'd prefer norad to be a fairly transparent mapping of the UFO object on disk; so while I agree it's a bit of a funny fit in runebender that's still my current preference? I'm not sure exactly what the rules/constraints are with kern groups though, so maybe @madig has an opinion?
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.
Maybe between Norad and Runebender, we need uhh... a federal bureaucracy.
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.
RE the constraints on kern groups: the UFO spec says that a given glyph must not appear in more than one kerning group per side.
https://unifiedfontobject.org/versions/ufo3/groups.plist/#4-glyphs-must-not-appear-in-more-than-one-kerning-group-per-side
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.
@madig how would you feel if we had, in norad, a representation of kerning groups that was distinct from what we load from and write to disk? This would just be some sort of map, where each glyph could have left and right kerning groups assigned. This seems better than exposing a literal representation of the UFO kern-groups to users?
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'm fine with whatever fits Runebender best, but keep in mind that splitting data out of structures requires that you be careful when merging them back in. If you split out kerning groups into their own structure and the user somehow writes kerning groups into the original structure from out under you (scripting), you'll overwrite things or end up with inconsistent state.
Glyphs also has a UI where you set left and right group at glyph level and it serializes into a
HashMap<String, HashMap<String, String>>
.