From c6006a7f8c31cd8e7dddad58894e1ba6c87e1362 Mon Sep 17 00:00:00 2001 From: Cosimo Lupo Date: Thu, 21 Mar 2019 12:16:54 +0000 Subject: [PATCH] [glyf] remove_hinting should del program from composite glyph Unlike simple glyphs, which always have 'program' attribute (even when empty, with no instructions) in composite glyphs, it's the presence of 'program' attribute that determines whether the optional WE_HAVE_INSTRUCTIONS component flag is set or not. Thus, the trim method (with remove_hinting=True) should delete the attribute for composite glyphs. Fixes https://github.com/fonttools/fonttools/issues/1550 --- Lib/fontTools/ttLib/tables/_g_l_y_f.py | 8 ++++-- Tests/ttLib/tables/_g_l_y_f_test.py | 36 ++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/Lib/fontTools/ttLib/tables/_g_l_y_f.py b/Lib/fontTools/ttLib/tables/_g_l_y_f.py index b8020ca7b..83d5315bb 100644 --- a/Lib/fontTools/ttLib/tables/_g_l_y_f.py +++ b/Lib/fontTools/ttLib/tables/_g_l_y_f.py @@ -917,8 +917,12 @@ class Glyph(object): expanding it.""" if not hasattr(self, "data"): if remove_hinting: - self.program = ttProgram.Program() - self.program.fromBytecode([]) + if self.isComposite(): + if hasattr(self, "program"): + del self.program + else: + self.program = ttProgram.Program() + self.program.fromBytecode([]) # No padding to trim. return if not self.data: diff --git a/Tests/ttLib/tables/_g_l_y_f_test.py b/Tests/ttLib/tables/_g_l_y_f_test.py index 00c74bcf5..b30528aae 100644 --- a/Tests/ttLib/tables/_g_l_y_f_test.py +++ b/Tests/ttLib/tables/_g_l_y_f_test.py @@ -4,6 +4,7 @@ from fontTools.misc.fixedTools import otRound from fontTools.pens.ttGlyphPen import TTGlyphPen from fontTools.ttLib import TTFont, newTable, TTLibError from fontTools.ttLib.tables._g_l_y_f import GlyphCoordinates +from fontTools.ttLib.tables import ttProgram import sys import array import pytest @@ -240,6 +241,41 @@ class glyfTableTest(unittest.TestCase): with self.assertRaisesRegex(TTLibError, "glyph '.' contains a recursive component reference"): glyph_A.getCoordinates(glyphSet) + def test_trim_remove_hinting_composite_glyph(self): + glyphSet = {"dummy": TTGlyphPen(None).glyph()} + + pen = TTGlyphPen(glyphSet) + pen.addComponent("dummy", (1, 0, 0, 1, 0, 0)) + composite = pen.glyph() + p = ttProgram.Program() + p.fromAssembly(['SVTCA[0]']) + composite.program = p + glyphSet["composite"] = composite + + glyfTable = newTable("glyf") + glyfTable.glyphs = glyphSet + glyfTable.glyphOrder = sorted(glyphSet) + + composite.compact(glyfTable) + + self.assertTrue(hasattr(composite, "data")) + + # remove hinting from the compacted composite glyph, without expanding it + composite.trim(remove_hinting=True) + + # check that, after expanding the glyph, we have no instructions + composite.expand(glyfTable) + self.assertFalse(hasattr(composite, "program")) + + # now remove hinting from expanded composite glyph + composite.program = p + composite.trim(remove_hinting=True) + + # check we have no instructions + self.assertFalse(hasattr(composite, "program")) + + composite.compact(glyfTable) + if __name__ == "__main__": import sys