1
1
mirror of https://github.com/rsms/inter.git synced 2024-12-25 16:44:27 +03:00

Adds misc/kernsample.py

This commit is contained in:
Rasmus Andersson 2017-09-19 10:54:02 -07:00
parent e867bb7bd7
commit 9209081fe9
2 changed files with 180 additions and 0 deletions

View File

@ -228,6 +228,45 @@ You can now visit `http://localhost:2015/lab/`.
After you rebuild some font files, reload the web page to refresh fonts.
### Kerning
Kerning is the concept of harmony in the pace of characters, defined as a set of distances
between specific character pairs, like "A" & "c".
Good kerning makes words more readable. Oftentimes this means that when adjusting kerning,
you have to look at whole words and sentences when adjusting the kerning of a pair, since
the spacing between two characters should work in harmony with the spacing of all other characters.
All major font editors provide user interfaces for previewing and adjusting kerning.
When adding or adjusting kerning:
- Make sure to use kerning groups (`src/Inter-UI-*.ufo/groups.plist`)
- If a glyphname is missing in kerning groups, define a new group for it.
Group naming scheme is: `@KERN_<DIRECTION>_<NAME>` where `<DIRECTION>`
is either `LEFT` or `RIGHT`, depending on if the group represents the left-hand side
of a pair or the right-hand side. `<NAME>` is the name of a glyph that most commonly
represents the group. For instance, for all glyphs that has a left-side shape similar
to "c", like "d", the group name is "c". This makes it easy to test kerning of groups
by just using the `<NAME>` part in previews.
- Try to submit image samples of kerning adjustments with your pull requests whenever
feasible.
The script `misc/kernsample.py` is helpful in generating samples for all existing
right-hand side characters given a left-hand side glyphname.
```txt
$ misc/kernsample.py src/Inter-UI-Black.ufo P -suffix MOR
PAMOR P/AE MOR PJMOR PXMOR PYMOR PZMOR P/ae mor P/ampersand mor P/backslash mor P/dzcaron mor P/eightsub mor P/ellipsis mor Pfmor P/four mor P/guilsinglleft mor P/idieresisacute mor P/periodcentered mor P/quotedblbase mor Psmor P/seven mor P/slash mor Ptmor P/two mor P/underscore mor Pymor
```
Type `misc/kernsample.py -h` for help on how to use the program.
This only includes existing kerning and is thus only useful for adjustments.
Additions must still be done manually.
## FAQ
> Do I need RoboFont?

141
misc/kernsample.py Executable file
View File

@ -0,0 +1,141 @@
#!/usr/bin/env python
# encoding: utf8
from __future__ import print_function
import os, sys, plistlib
from collections import OrderedDict
from argparse import ArgumentParser
from robofab.objects.objectsRF import OpenFont
def mapGroups(groups): # => { glyphname => set(groupname, ...), ... }
m = OrderedDict()
for groupname, glyphnames in groups.iteritems():
for glyphname in glyphnames:
m.setdefault(glyphname, set()).add(groupname)
return m
def _addRightnames(groups, kerning, leftname, rightnames, includeAll=True):
if leftname in kerning:
for rightname in kerning[leftname]:
if rightname[0] == '@':
for rightname2 in groups[rightname]:
rightnames.add(rightname2)
if not includeAll:
# TODO: in this case, pick the one rightname that has the highest
# ranking in glyphorder
break
else:
rightnames.add(rightname)
def fmtGlyphname(glyphname, glyph=None):
if glyph is not None and len(glyphname) == 1 and ord(glyphname[0]) == glyph.unicode:
# literal, e.g. "A"
return glyphname
else:
# named, e.g. "\Omega"
return '/' + glyphname + ' '
def samplesForGlyphname(font, groups, groupmap, kerning, glyphname, args):
leftGlyph = font[glyphname] # verify it's present
rightnames = set()
_addRightnames(groups, kerning, glyphname, rightnames, includeAll=args.includeAllInGroup)
if glyphname in groupmap:
for groupname in groupmap[glyphname]:
_addRightnames(groups, kerning, groupname, rightnames, includeAll=args.includeAllInGroup)
rightnames = sorted(rightnames)
out = []
if args.formatAsUnicode:
left = '\\u%04X' % leftGlyph.unicode
for rightname in rightnames:
if rightname in font:
rightGlyph = font[rightname]
if rightGlyph.unicode is not None:
out.append('%s\\u%04X' % (left, rightGlyph.unicode))
else:
left = fmtGlyphname(glyphname, leftGlyph)
suffix_uc = ''
suffix_lc = ''
if len(args.suffix) > 0:
s = unicode(args.suffix)
if s[0].isupper():
suffix_uc = args.suffix
suffix_lc = args.suffix.lower()
else:
suffix_uc = args.suffix.upper()
suffix_lc = args.suffix
for rightname in rightnames:
if rightname in font:
rightGlyph = None
if len(rightname) == 1:
rightGlyph = font[rightname]
suffix = suffix_lc
if unicode(rightname[0]).isupper():
suffix = suffix_uc
out.append('%s%s%s' % (left, fmtGlyphname(rightname, rightGlyph), suffix))
print(' '.join(out))
def main():
argparser = ArgumentParser(
description='Generate kerning samples by providing the left-hand side glyph')
argparser.add_argument(
'-u', dest='formatAsUnicode', action='store_const', const=True, default=False,
help='Format output as unicode escape sequences instead of glyphnames. ' +
'E.g. "\\u2126" instead of "\\Omega"')
argparser.add_argument(
'-suffix', dest='suffix', metavar='<text>', type=str,
help='Text to append after each pair')
argparser.add_argument(
'-all-in-groups', dest='includeAllInGroup',
action='store_const', const=True, default=False,
help='Include all glyphs for groups rather than just the first glyph listed.')
argparser.add_argument(
'fontPath', metavar='<ufofile>', type=str, help='UFO font source')
argparser.add_argument(
'glyphnames', metavar='<glyphname>', type=str, nargs='+',
help='Name of glyphs to generate samples for. '+
'You can also provide a Unicode code point using the syntax "U+XXXX"')
args = argparser.parse_args()
dryRun = args.dryRun
font = OpenFont(args.fontPath)
groupsFilename = os.path.join(args.fontPath, 'groups.plist')
kerningFilename = os.path.join(args.fontPath, 'kerning.plist')
groups = plistlib.readPlist(groupsFilename) # { groupName => [glyphName] }
kerning = plistlib.readPlist(kerningFilename) # { leftName => {rightName => kernVal} }
groupmap = mapGroups(groups)
# expand any unicode codepoints
glyphnames = []
for glyphname in args.glyphnames:
if len(glyphname) > 2 and glyphname[:2] == 'U+':
cp = int(glyphname[2:], 16)
ucmap = font.getCharacterMapping() # { 2126: ['Omega', ...], ...}
for glyphname2 in ucmap[cp]:
glyphnames.append(glyphname2)
else:
glyphnames.append(glyphname)
for glyphname in glyphnames:
samplesForGlyphname(font, groups, groupmap, kerning, glyphname, args)
main()