#!/usr/bin/env python3 """ Tells you how an icon can be coloured. python builder/shapes.py sync-alt gear server Two answers per icon: duotone font awesome's own two-layer version exists in the duotone face - -primary and -secondary. This is what a two-colour favicon uses, and it is what the website shows under "duotone". formen how many separately colourable shapes the regular glyph has, for icons the duotone face does not carry. Holes are grouped with the shape they sit in: a gear is one shape with three counters cut out of it, a server is two boxes with their own slots. Reads the same fonts and stylesheet the rollout uses (builder/config.json), so what it reports is what you would actually get. """ import json import os import sys sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) from subset import SECONDARY_OFFSET, codepoints, groups # noqa: E402 TOOL_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) def main(): names = sys.argv[1:] if not names: print(__doc__.strip()) raise SystemExit(2) with open(os.path.join(TOOL_DIR, 'builder', 'config.json'), encoding='utf-8') as handle: config = json.load(handle) def tool_path(entry): return os.path.normpath(os.path.join(TOOL_DIR, entry)) if entry else '' font_path = tool_path(config['font']) css_path = tool_path(config['css']) duotone_path = tool_path(config.get('duotone', '')) from fontTools.ttLib import TTFont known = codepoints(css_path) font = TTFont(font_path) cmap = font.getBestCmap() glyph_set = font.getGlyphSet() duotone_cmap = {} if duotone_path and os.path.isfile(duotone_path): duotone_cmap = TTFont(duotone_path).getBestCmap() print('%s + %s\n%s\n' % (os.path.basename(font_path), os.path.basename(duotone_path) or 'kein duotone-schnitt', os.path.basename(css_path))) for name in names: key = name[3:] if name.startswith('fa-') else name if key not in known: print('%-24s unbekannter font-awesome-name' % name) continue point = known[key] if point not in cmap: print('%-24s \\%x nicht in diesem schnitt' % (name, point)) continue has_duotone = (point in duotone_cmap and point + SECONDARY_OFFSET in duotone_cmap) shapes = groups(glyph_set, cmap[point]) if has_duotone: verdict = 'DUOTONE (primary + secondary)' elif len(shapes) > 1: verdict = 'kein duotone, aber %d formen -> bis zu %d farben' % ( len(shapes), len(shapes)) else: verdict = 'nur einfarbig - kein duotone, eine einzige form' print('%-24s \\%x %s' % (name, point, verdict)) for index, (bounds, _) in enumerate(shapes): x0, y0, x1, y1 = (round(v) for v in bounds) print(' form %d x %4d..%-4d y %4d..%-4d' % (index, x0, x1, y0, y1)) main()