From a8fc89d01f4b281cd4ebd30532a6b61fa51bc913 Mon Sep 17 00:00:00 2001 From: Rasmus Andersson Date: Fri, 23 Nov 2018 12:52:50 -0800 Subject: fontbuild: adds support for post-processing directives on a per-glyph basis. Add "!post:DIRECTIVE" in glyph notes. Only supported directive is "removeoverlaps" --- misc/fontbuild | 64 +++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 50 insertions(+), 14 deletions(-) diff --git a/misc/fontbuild b/misc/fontbuild index d272a7aec..ebbcd4329 100755 --- a/misc/fontbuild +++ b/misc/fontbuild @@ -25,10 +25,11 @@ from fontTools.pens.reverseContourPen import ReverseContourPen from glyphsLib.interpolation import apply_instance_data from mutatorMath.ufo.document import DesignSpaceDocumentReader from multiprocessing import Process, Queue -# from ufo2ft.filters.removeOverlaps import RemoveOverlapsFilter +from ufo2ft.filters.removeOverlaps import RemoveOverlapsFilter log = logging.getLogger(__name__) stripItalic_re = re.compile(r'(?:^|\b)italic(?:\b|$)', re.I | re.U) +findPost_re = re.compile(r'\!post:([^ ]+)', re.I | re.U) def stripItalic(name): @@ -77,6 +78,26 @@ def composedGlyphIsNonTrivial(g, yAxisIsNonTrivial=False): return False +knownDirectives = set([ + 'removeoverlap', +]) + + +def findGlyphDirectives(g): # -> set | None + directives = set() + if g.note and len(g.note) > 0: + for directive in findPost_re.findall(g.note): + directive = directive.lower() + if directive in knownDirectives: + directives.add(directive) + else: + print( + 'unknown glyph directive !post:%s in glyph %s' % (directive, g.name), + file=sys.stderr + ) + return directives + + class VarFontProject(FontProject): def decompose_glyphs(self, ufos, glyph_filter=lambda g: True): """Move components of UFOs' glyphs to their outlines.""" @@ -100,29 +121,42 @@ class VarFontProject(FontProject): # the contour direction of the component xx, xy, yx, yy = transformation[:4] if xx*yy - xy*yx < 0: - pen = ReverseContourPen(pen) + pen = ReverseContourPen(pen) component.draw(pen) def build_interpolatable_ttfs(self, ufos, **kwargs): """Build OpenType binaries with interpolatable TrueType outlines.""" # We decompose any glyph with two or more components to make sure # that fontTools varLib is able to produce properly-slanting interpolation. - + decomposeGlyphs = set() + removeOverlapsGlyphs = set() + for ufo in ufos: updateFontVersion(ufo) isItalic = ufo.info.italicAngle != 0 - for glyph in ufo: - if glyph.components and composedGlyphIsNonTrivial(glyph, yAxisIsNonTrivial=isItalic): - decomposeGlyphs.add(glyph.name) + ufoname = basename(ufo.path) + for g in ufo: + directives = findGlyphDirectives(g) + if g.components and composedGlyphIsNonTrivial(g, yAxisIsNonTrivial=isItalic): + decomposeGlyphs.add(g.name) + if 'removeoverlap' in directives: + if g.components and len(g.components) > 0: + decomposeGlyphs.add(g.name) + removeOverlapsGlyphs.add(g) self.decompose_glyphs(ufos, lambda g: g.name in decomposeGlyphs) - # for ufo in ufos: - # filter = RemoveOverlapsFilter(backend='pathops') - # filter.start() - # for g in ufo: - # filter.filter(g) + if len(removeOverlapsGlyphs) > 0: + rmoverlapFilter = RemoveOverlapsFilter(backend='pathops') + rmoverlapFilter.start() + for g in removeOverlapsGlyphs: + log.info( + 'Removing overlaps in glyph "%s" of %s', + g.name, + basename(g.getParent().path) + ) + rmoverlapFilter.filter(g) self.save_otfs(ufos, ttf=True, interpolatable=True, **kwargs) @@ -268,6 +302,7 @@ class Main(object): # parse CLI arguments args = argparser.parse_args(argv[1:i]) + logFormat = '%(funcName)s: %(message)s' if args.quiet: self.quiet = True if args.debug: @@ -275,13 +310,14 @@ class Main(object): if args.verbose: fatal("--quiet and --verbose are mutually exclusive arguments") elif args.debug: - logging.basicConfig(level=logging.DEBUG) + logging.basicConfig(level=logging.DEBUG, format=logFormat) self.logLevelName = 'DEBUG' elif args.verbose: - logging.basicConfig(level=logging.INFO) + logging.basicConfig(level=logging.INFO, format=logFormat) self.logLevelName = 'INFO' else: - logging.basicConfig(level=logging.WARNING) + logFormat = '%(message)s' + logging.basicConfig(level=logging.WARNING, format=logFormat) self.logLevelName = 'WARNING' if args.chdir: -- cgit v1.2.3