tooling: decompose and remove overlaps of SVG glyphs generated for the website

This commit is contained in:
Rasmus Andersson 2018-09-17 10:05:45 -07:00
parent 287f146a06
commit c163658d67

View file

@ -18,9 +18,11 @@ from collections import OrderedDict
from math import ceil, floor from math import ceil, floor
from defcon import Font from defcon import Font
from svg import SVGPathPen from svg import SVGPathPen
from ufo2ft.filters.decomposeComponents import DecomposeComponentsFilter
from ufo2ft.filters.removeOverlaps import RemoveOverlapsFilter
font = None # RFont ufo = None
ufopath = '' ufopath = ''
effectiveAscender = 0 effectiveAscender = 0
scale = 0.1 scale = 0.1
@ -30,31 +32,6 @@ def num(s):
return int(s) if s.find('.') == -1 else float(s) return int(s) if s.find('.') == -1 else float(s)
def decomposeGlyph(font, glyph):
"""Moves the components of a glyph to its outline."""
if len(glyph.components):
deepCopyContours(font, glyph, glyph, (0, 0), (1, 1))
glyph.clearComponents()
def deepCopyContours(font, parent, component, offset, scale):
"""Copy contours to parent from component, including nested components."""
for nested in component.components:
deepCopyContours(
font, parent, font[nested.baseGlyph],
(offset[0] + nested.offset[0], offset[1] + nested.offset[1]),
(scale[0] * nested.scale[0], scale[1] * nested.scale[1]))
if component == parent:
return
for contour in component:
contour = contour.copy()
contour.scale(scale)
contour.move(offset)
parent.appendContour(contour)
def glyphToSVGPath(g, yMul): def glyphToSVGPath(g, yMul):
pen = SVGPathPen(g.getParent(), yMul) pen = SVGPathPen(g.getParent(), yMul)
@ -82,16 +59,16 @@ def glyphToSVG(g):
''' % { ''' % {
'name': g.name, 'name': g.name,
'width': int(ceil(width * scale)), 'width': int(ceil(width * scale)),
'height': int(ceil((effectiveAscender - font.info.descender) * scale)), 'height': int(ceil((effectiveAscender - ufo.info.descender) * scale)),
'xoffs': -(xoffs * scale), 'xoffs': -(xoffs * scale),
'yoffs': effectiveAscender * scale, 'yoffs': effectiveAscender * scale,
# 'leftMargin': g.leftMargin * scale, # 'leftMargin': g.leftMargin * scale,
# 'rightMargin': g.rightMargin * scale, # 'rightMargin': g.rightMargin * scale,
'glyphSVGPath': glyphToSVGPath(g, -1), 'glyphSVGPath': glyphToSVGPath(g, -1),
# 'ascender': font.info.ascender * scale, # 'ascender': ufo.info.ascender * scale,
# 'descender': font.info.descender * scale, # 'descender': ufo.info.descender * scale,
# 'baselineOffset': (font.info.unitsPerEm + font.info.descender) * scale, # 'baselineOffset': (ufo.info.unitsPerEm + ufo.info.descender) * scale,
# 'unitsPerEm': font.info.unitsPerEm, # 'unitsPerEm': ufo.info.unitsPerEm,
'scale': scale, 'scale': scale,
# 'margin': [g.leftMargin * scale, g.rightMargin * scale], # 'margin': [g.leftMargin * scale, g.rightMargin * scale],
@ -173,7 +150,7 @@ def findGlifFile(glyphname):
usedSVGNames = set() usedSVGNames = set()
def genGlyph(glyphName): def genGlyph(glyphName):
g = font[glyphName] g = ufo[glyphName]
return glyphToSVG(g) return glyphToSVG(g)
@ -188,11 +165,11 @@ def genGlyphIDs(glyphnames):
return nameToIdMap, idToNameMap return nameToIdMap, idToNameMap
def genKerningInfo(font, glyphnames, nameToIdMap): def genKerningInfo(ufo, glyphnames, nameToIdMap):
kerning = font.kerning kerning = ufo.kerning
# load groups # load groups
filename = os.path.join(font.path, 'groups.plist') filename = os.path.join(ufo.path, 'groups.plist')
groups = plistlib.readPlist(filename) groups = plistlib.readPlist(filename)
pairs = [] pairs = []
@ -269,16 +246,27 @@ if len(args.scale):
ufopath = args.ufopath.rstrip('/') ufopath = args.ufopath.rstrip('/')
font = Font(ufopath) ufo = Font(ufopath)
effectiveAscender = max(font.info.ascender, font.info.unitsPerEm) effectiveAscender = max(ufo.info.ascender, ufo.info.unitsPerEm)
# print('\n'.join(font.keys())) print('preprocessing glyphs')
filters = [
DecomposeComponentsFilter(),
RemoveOverlapsFilter(backend=RemoveOverlapsFilter.Backend.SKIA_PATHOPS),
]
glyphSet = {g.name: g for g in ufo}
for func in filters:
func(ufo, glyphSet)
print('generating SVGs and metrics data')
# print('\n'.join(ufo.keys()))
# sys.exit(0) # sys.exit(0)
deleteNames.add('.notdef') deleteNames.add('.notdef')
deleteNames.add('.null') deleteNames.add('.null')
glyphnames = args.glyphs if len(args.glyphs) else font.keys() glyphnames = args.glyphs if len(args.glyphs) else ufo.keys()
glyphnameSet = set(glyphnames) glyphnameSet = set(glyphnames)
glyphnames = [gn for gn in glyphnames if gn not in deleteNames] glyphnames = [gn for gn in glyphnames if gn not in deleteNames]
@ -321,7 +309,7 @@ if startPos == -1 or endPos == -1:
print(msg % relfilename, file=sys.stderr) print(msg % relfilename, file=sys.stderr)
sys.exit(1) sys.exit(1)
kerning = genKerningInfo(font, glyphnames, nameToIdMap) kerning = genKerningInfo(ufo, glyphnames, nameToIdMap)
metaJson = '{\n' metaJson = '{\n'
metaJson += '"nameids":' + fmtJsonDict(idToNameMap) + ',\n' metaJson += '"nameids":' + fmtJsonDict(idToNameMap) + ',\n'
metaJson += '"metrics":' + fmtJsonDict(glyphMetrics) + ',\n' metaJson += '"metrics":' + fmtJsonDict(glyphMetrics) + ',\n'