From d05617b4bd3d928932952a32cefbfc541ec5256c Mon Sep 17 00:00:00 2001 From: Sascha Brawer Date: Thu, 17 Aug 2017 18:52:21 +0200 Subject: [PATCH] [AAT] Support `prop` table with glyph properties --- Lib/fontTools/ttLib/tables/__init__.py | 1 + Lib/fontTools/ttLib/tables/_p_r_o_p.py | 8 +++ Lib/fontTools/ttLib/tables/otBase.py | 1 - Lib/fontTools/ttLib/tables/otData.py | 21 +++++++ README.rst | 4 +- Tests/ttLib/tables/_p_r_o_p_test.py | 84 ++++++++++++++++++++++++++ 6 files changed, 116 insertions(+), 3 deletions(-) create mode 100644 Lib/fontTools/ttLib/tables/_p_r_o_p.py create mode 100644 Tests/ttLib/tables/_p_r_o_p_test.py diff --git a/Lib/fontTools/ttLib/tables/__init__.py b/Lib/fontTools/ttLib/tables/__init__.py index 16d3a330c..0858bd371 100644 --- a/Lib/fontTools/ttLib/tables/__init__.py +++ b/Lib/fontTools/ttLib/tables/__init__.py @@ -73,6 +73,7 @@ def _moduleFinderHint(): from . import _n_a_m_e from . import _p_o_s_t from . import _p_r_e_p + from . import _p_r_o_p from . import _s_b_i_x from . import _t_r_a_k from . import _v_h_e_a diff --git a/Lib/fontTools/ttLib/tables/_p_r_o_p.py b/Lib/fontTools/ttLib/tables/_p_r_o_p.py new file mode 100644 index 000000000..7da18eab8 --- /dev/null +++ b/Lib/fontTools/ttLib/tables/_p_r_o_p.py @@ -0,0 +1,8 @@ +from __future__ import print_function, division, absolute_import +from fontTools.misc.py23 import * +from .otBase import BaseTTXConverter + + +# https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6prop.html +class table__p_r_o_p(BaseTTXConverter): + pass diff --git a/Lib/fontTools/ttLib/tables/otBase.py b/Lib/fontTools/ttLib/tables/otBase.py index 87d644ab4..7efca19bc 100644 --- a/Lib/fontTools/ttLib/tables/otBase.py +++ b/Lib/fontTools/ttLib/tables/otBase.py @@ -782,7 +782,6 @@ class FormatSwitchingBaseTable(BaseTable): def readFormat(self, reader): self.Format = reader.readUShort() - assert self.Format != 0, (self, reader.pos, len(reader.data)) def writeFormat(self, writer): writer.writeUShort(self.Format) diff --git a/Lib/fontTools/ttLib/tables/otData.py b/Lib/fontTools/ttLib/tables/otData.py index 21f2fac6a..1ef357795 100755 --- a/Lib/fontTools/ttLib/tables/otData.py +++ b/Lib/fontTools/ttLib/tables/otData.py @@ -1318,4 +1318,25 @@ otData = [ # If the 'morx' table version is 3 or greater, then the last subtable in the chain is followed by a subtableGlyphCoverageArray, as described below. # ('Offset', 'MarkGlyphSetsDef', None, 'int(round(Version*0x10000)) >= 0x00010002', 'Offset to the table of mark set definitions-from beginning of GDEF header (may be NULL)'), + + # + # prop + # + + ('prop', [ + ('Fixed', 'Version', None, None, 'Version number of the AAT glyphs property table. Version 1.0 is the initial table version. Version 2.0, which is recognized by macOS 8.5 and later, adds support for the “attaches on right” bit. Version 3.0, which gets recognized by macOS X and iOS, adds support for the additional directional properties defined in Unicode 3.0.'), + ('struct', 'GlyphProperties', None, None, 'Glyph properties.'), + ]), + + ('GlyphPropertiesFormat0', [ + ('uint16', 'Format', None, None, 'Format, = 0.'), + ('uint16', 'DefaultProperties', None, None, 'Default properties applied to a glyph. Since there is no lookup table in prop format 0, the default properties get applied to every glyph in the font.'), + ]), + + ('GlyphPropertiesFormat1', [ + ('uint16', 'Format', None, None, 'Format, = 1.'), + ('uint16', 'DefaultProperties', None, None, 'Default properties applied to a glyph if that glyph is not present in the Properties lookup table.'), + ('AATLookup(uint16)', 'Properties', None, None, 'Lookup data associating glyphs with their properties.'), + ]), + ] diff --git a/README.rst b/README.rst index d871561ff..a79a1967f 100644 --- a/README.rst +++ b/README.rst @@ -102,8 +102,8 @@ The following tables are currently supported: OS/2, SING, STAT, SVG, TSI0, TSI1, TSI2, TSI3, TSI5, TSIB, TSID, TSIJ, TSIP, TSIS, TSIV, TTFA, VDMX, VORG, VVAR, avar, cmap, cvar, cvt, feat, fpgm, fvar, gasp, glyf, gvar, hdmx, head, hhea, hmtx, - kern, lcar, loca, ltag, maxp, meta, name, post, prep, sbix, trak, - vhea and vmtx + kern, lcar, loca, ltag, maxp, meta, name, post, prep, prop, sbix, + trak, vhea and vmtx .. end table list Other tables are dumped as hexadecimal data. diff --git a/Tests/ttLib/tables/_p_r_o_p_test.py b/Tests/ttLib/tables/_p_r_o_p_test.py new file mode 100644 index 000000000..edac91555 --- /dev/null +++ b/Tests/ttLib/tables/_p_r_o_p_test.py @@ -0,0 +1,84 @@ +from __future__ import print_function, division, absolute_import, unicode_literals +from fontTools.misc.py23 import * +from fontTools.misc.testTools import FakeFont, getXML, parseXML +from fontTools.misc.textTools import deHexStr, hexStr +from fontTools.ttLib import newTable +import unittest + + +PROP_FORMAT_0_DATA = deHexStr( + '0001 0000 0000 ' # 0: Version=1.0, Format=0 + '0005 ' # 6: DefaultProperties=European number terminator +) # 8: +assert(len(PROP_FORMAT_0_DATA) == 8) + + +PROP_FORMAT_0_XML = [ + '', + '', + ' ', + '', +] + + +PROP_FORMAT_1_DATA = deHexStr( + '0003 0000 0001 ' # 0: Version=3.0, Format=1 + '0000 ' # 6: DefaultProperties=left-to-right; non-whitespace + '0008 0003 0004 ' # 8: LookupFormat=8, FirstGlyph=3, GlyphCount=4 + '000B ' # 14: Properties[C]=other neutral + '000A ' # 16: Properties[D]=whitespace + '600B ' # 18: Properties[E]=other neutral; hanging punct + '0005 ' # 20: Properties[F]=European number terminator +) # 22: +assert(len(PROP_FORMAT_1_DATA) == 22) + + +PROP_FORMAT_1_XML = [ + '', + '', + ' ', + ' ', + ' ', + ' ', + ' ', + ' ', + ' ', + '', +] + + +class PROPTest(unittest.TestCase): + + @classmethod + def setUpClass(cls): + cls.maxDiff = None + cls.font = FakeFont(['.notdef', 'A', 'B', 'C', 'D', 'E', 'F', 'G']) + + def test_decompile_toXML_format0(self): + table = newTable('prop') + table.decompile(PROP_FORMAT_0_DATA, self.font) + self.assertEqual(getXML(table.toXML), PROP_FORMAT_0_XML) + + def test_compile_fromXML_format0(self): + table = newTable('prop') + for name, attrs, content in parseXML(PROP_FORMAT_0_XML): + table.fromXML(name, attrs, content, font=self.font) + self.assertEqual(hexStr(table.compile(self.font)), + hexStr(PROP_FORMAT_0_DATA)) + + def test_decompile_toXML_format1(self): + table = newTable('prop') + table.decompile(PROP_FORMAT_1_DATA, self.font) + self.assertEqual(getXML(table.toXML), PROP_FORMAT_1_XML) + + def test_compile_fromXML_format1(self): + table = newTable('prop') + for name, attrs, content in parseXML(PROP_FORMAT_1_XML): + table.fromXML(name, attrs, content, font=self.font) + self.assertEqual(hexStr(table.compile(self.font)), + hexStr(PROP_FORMAT_1_DATA)) + + +if __name__ == '__main__': + import sys + sys.exit(unittest.main())