From 0fea147ad8321aaf9b8f199ddb4f362b21d9f424 Mon Sep 17 00:00:00 2001 From: Marc Foley Date: Thu, 11 Apr 2024 14:30:04 +0100 Subject: [PATCH 1/2] set-overlap-bits added --- Lib/gftools/scripts/set_overlap_bits.py | 57 +++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 Lib/gftools/scripts/set_overlap_bits.py diff --git a/Lib/gftools/scripts/set_overlap_bits.py b/Lib/gftools/scripts/set_overlap_bits.py new file mode 100644 index 00000000..cbee1964 --- /dev/null +++ b/Lib/gftools/scripts/set_overlap_bits.py @@ -0,0 +1,57 @@ +import argparse +from defcon import Font +from pathops.operations import _draw +from ufo2ft.filters.decomposeComponents import DecomposeComponentsFilter +from ufo2ft.preProcessor import TTFPreProcessor +import math +from fontTools.designspaceLib import DesignSpaceDocument + + +def set_overlap_bits(ufo): + # Skip setting bits if ufo + if any(g.lib.get("public.truetype.overlap") for g in ufo): + return + # Decompose components first because some component glyphs may have + # components that overlap each other + outline_glyphset = TTFPreProcessor( + ufo, filters=[DecomposeComponentsFilter()] + ).process() + + overlaps = set() + for glyph in outline_glyphset.values(): + paths = _draw(glyph) + area = paths.area + # rm overlaps + paths.simplify() + simplified_area = paths.area + if math.ceil(area) != math.ceil(simplified_area): + ufo[glyph.name].lib["public.truetype.overlap"] = True + overlaps.add(glyph.name) + return overlaps + + +def main(args=None): + parser = argparse.ArgumentParser(description="Set the overlap bits of a ufo/ds") + parser.add_argument("input", help="Input UFO or Designspace file", nargs="+") + args = parser.parse_args(args) + + ufos = [] + for fp in args.input: + if fp.endswith(".ufo"): + ufos.append(Font(fp)) + elif fp.endswith(".designspace"): + ds = DesignSpaceDocument.fromfile(fp) + for src in ds.sources: + ufos.append(Font(src.path)) + else: + raise NotImplementedError(f"Not supported file type: {fp}") + + for ufo in ufos: + overlapping_glyphs = set_overlap_bits(ufo) + if overlapping_glyphs: + print(f"Overlap flags set for {len(overlapping_glyphs)} glyphs") + ufo.save() + + +if __name__ == "__main__": + main() From 8eb2cba82cd6847202d9de4ee6be6bd4755de1dd Mon Sep 17 00:00:00 2001 From: Marc Foley Date: Fri, 12 Apr 2024 15:39:48 +0100 Subject: [PATCH 2/2] implement cosimo feedback --- Lib/gftools/scripts/set_overlap_bits.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/Lib/gftools/scripts/set_overlap_bits.py b/Lib/gftools/scripts/set_overlap_bits.py index cbee1964..a37b8c4f 100644 --- a/Lib/gftools/scripts/set_overlap_bits.py +++ b/Lib/gftools/scripts/set_overlap_bits.py @@ -1,6 +1,6 @@ import argparse from defcon import Font -from pathops.operations import _draw +from pathops import Path from ufo2ft.filters.decomposeComponents import DecomposeComponentsFilter from ufo2ft.preProcessor import TTFPreProcessor import math @@ -19,12 +19,15 @@ def set_overlap_bits(ufo): overlaps = set() for glyph in outline_glyphset.values(): - paths = _draw(glyph) - area = paths.area + skia_path = Path() + pen = skia_path.getPen() + for contour in glyph: + contour.draw(pen) + area = skia_path.area # rm overlaps - paths.simplify() - simplified_area = paths.area - if math.ceil(area) != math.ceil(simplified_area): + skia_path.simplify() + simplified_area = skia_path.area + if not math.isclose(area, simplified_area, abs_tol=0.1): ufo[glyph.name].lib["public.truetype.overlap"] = True overlaps.add(glyph.name) return overlaps