[AAT] Support the opbd
table with optical bounds
Interestingly, this can handle the examples from the AAT specification (which are part of the unit tests), and also most AAT fonts on my disk. However, some other AAT fonts such as Apple Chancery cannot be decompiled. The failure seems to be a general problem with how fonttools decompiles AAT lookups of format 4, and unrelated to this present change.
This commit is contained in:
parent
1aef1683df
commit
a47f658855
@ -71,6 +71,7 @@ def _moduleFinderHint():
|
|||||||
from . import _m_a_x_p
|
from . import _m_a_x_p
|
||||||
from . import _m_e_t_a
|
from . import _m_e_t_a
|
||||||
from . import _n_a_m_e
|
from . import _n_a_m_e
|
||||||
|
from . import _o_p_b_d
|
||||||
from . import _p_o_s_t
|
from . import _p_o_s_t
|
||||||
from . import _p_r_e_p
|
from . import _p_r_e_p
|
||||||
from . import _p_r_o_p
|
from . import _p_r_o_p
|
||||||
|
8
Lib/fontTools/ttLib/tables/_o_p_b_d.py
Normal file
8
Lib/fontTools/ttLib/tables/_o_p_b_d.py
Normal file
@ -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/Chap6opbd.html
|
||||||
|
class table__o_p_b_d(BaseTTXConverter):
|
||||||
|
pass
|
@ -1337,6 +1337,40 @@ otData = [
|
|||||||
('uint16', 'Format', None, None, 'Format, = 1.'),
|
('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.'),
|
('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.'),
|
('AATLookup(uint16)', 'Properties', None, None, 'Lookup data associating glyphs with their properties.'),
|
||||||
|
]),
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# opbd
|
||||||
|
#
|
||||||
|
|
||||||
|
('opbd', [
|
||||||
|
('Version', 'Version', None, None, 'Version number of the optical bounds table (0x00010000 for the initial version).'),
|
||||||
|
('struct', 'OpticalBounds', None, None, 'Optical bounds table.'),
|
||||||
|
]),
|
||||||
|
|
||||||
|
('OpticalBoundsFormat0', [
|
||||||
|
('uint16', 'Format', None, None, 'Format of the optical bounds table, = 0.'),
|
||||||
|
('AATLookup(OpticalBoundsDeltas)', 'OpticalBoundsDeltas', None, None, 'Lookup table associating glyphs with their optical bounds, given as deltas in font units.'),
|
||||||
|
]),
|
||||||
|
|
||||||
|
('OpticalBoundsFormat1', [
|
||||||
|
('uint16', 'Format', None, None, 'Format of the optical bounds table, = 1.'),
|
||||||
|
('AATLookup(OpticalBoundsPoints)', 'OpticalBoundsPoints', None, None, 'Lookup table associating glyphs with their optical bounds, given as references to control points.'),
|
||||||
|
]),
|
||||||
|
|
||||||
|
('OpticalBoundsDeltas', [
|
||||||
|
('int16', 'Left', None, None, 'Delta value for the left-side optical edge.'),
|
||||||
|
('int16', 'Top', None, None, 'Delta value for the top-side optical edge.'),
|
||||||
|
('int16', 'Right', None, None, 'Delta value for the right-side optical edge.'),
|
||||||
|
('int16', 'Bottom', None, None, 'Delta value for the bottom-side optical edge.'),
|
||||||
|
]),
|
||||||
|
|
||||||
|
('OpticalBoundsPoints', [
|
||||||
|
('int16', 'Left', None, None, 'Control point index for the left-side optical edge, or -1 if this glyph has none.'),
|
||||||
|
('int16', 'Top', None, None, 'Control point index for the top-side optical edge, or -1 if this glyph has none.'),
|
||||||
|
('int16', 'Right', None, None, 'Control point index for the right-side optical edge, or -1 if this glyph has none.'),
|
||||||
|
('int16', 'Bottom', None, None, 'Control point index for the bottom-side optical edge, or -1 if this glyph has none.'),
|
||||||
]),
|
]),
|
||||||
|
|
||||||
]
|
]
|
||||||
|
@ -102,8 +102,8 @@ The following tables are currently supported:
|
|||||||
OS/2, SING, STAT, SVG, TSI0, TSI1, TSI2, TSI3, TSI5, TSIB, TSID,
|
OS/2, SING, STAT, SVG, TSI0, TSI1, TSI2, TSI3, TSI5, TSIB, TSID,
|
||||||
TSIJ, TSIP, TSIS, TSIV, TTFA, VDMX, VORG, VVAR, avar, cmap, cvar,
|
TSIJ, TSIP, TSIS, TSIV, TTFA, VDMX, VORG, VVAR, avar, cmap, cvar,
|
||||||
cvt, feat, fpgm, fvar, gasp, glyf, gvar, hdmx, head, hhea, hmtx,
|
cvt, feat, fpgm, fvar, gasp, glyf, gvar, hdmx, head, hhea, hmtx,
|
||||||
kern, lcar, loca, ltag, maxp, meta, name, post, prep, prop, sbix,
|
kern, lcar, loca, ltag, maxp, meta, name, opbd, post, prep, prop,
|
||||||
trak, vhea and vmtx
|
sbix, trak, vhea and vmtx
|
||||||
.. end table list
|
.. end table list
|
||||||
|
|
||||||
Other tables are dumped as hexadecimal data.
|
Other tables are dumped as hexadecimal data.
|
||||||
|
118
Tests/ttLib/tables/_o_p_b_d_test.py
Normal file
118
Tests/ttLib/tables/_o_p_b_d_test.py
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
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
|
||||||
|
|
||||||
|
|
||||||
|
# Example: Format 0 Optical Bounds Table
|
||||||
|
# https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6opbd.html
|
||||||
|
OPBD_FORMAT_0_DATA = deHexStr(
|
||||||
|
'0001 0000 0000 ' # 0: Version=1.0, Format=0
|
||||||
|
'0006 0004 0002 ' # 6: LookupFormat=6, UnitSize=4, NUnits=2
|
||||||
|
'0008 0001 0000 ' # 12: SearchRange=8, EntrySelector=1, RangeShift=0
|
||||||
|
'000A 001E ' # 18: Glyph=10(=C), OffsetOfOpticalBoundsDeltas=30
|
||||||
|
'002B 0026 ' # 22: Glyph=43(=A), OffsetOfOpticalBoundsDeltas=38
|
||||||
|
'FFFF 0000 ' # 26: Glyph=<end>, OffsetOfOpticalBoundsDeltas=0
|
||||||
|
'FFCE 0005 0037 FFFB ' # 30: Bounds[C].Left=-50 .Top=5 .Right=55 .Bottom=-5
|
||||||
|
'FFF6 000F 0000 0000 ' # 38: Bounds[A].Left=-10 .Top=15 .Right=0 .Bottom=0
|
||||||
|
) # 46: <end>
|
||||||
|
assert(len(OPBD_FORMAT_0_DATA) == 46)
|
||||||
|
|
||||||
|
|
||||||
|
OPBD_FORMAT_0_XML = [
|
||||||
|
'<Version value="0x00010000"/>',
|
||||||
|
'<OpticalBounds Format="0">',
|
||||||
|
' <OpticalBoundsDeltas>',
|
||||||
|
' <Lookup glyph="A">',
|
||||||
|
' <Left value="-10"/>',
|
||||||
|
' <Top value="15"/>',
|
||||||
|
' <Right value="0"/>',
|
||||||
|
' <Bottom value="0"/>',
|
||||||
|
' </Lookup>',
|
||||||
|
' <Lookup glyph="C">',
|
||||||
|
' <Left value="-50"/>',
|
||||||
|
' <Top value="5"/>',
|
||||||
|
' <Right value="55"/>',
|
||||||
|
' <Bottom value="-5"/>',
|
||||||
|
' </Lookup>',
|
||||||
|
' </OpticalBoundsDeltas>',
|
||||||
|
'</OpticalBounds>',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
# Example: Format 1 Optical Bounds Table
|
||||||
|
# https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6opbd.html
|
||||||
|
OPBD_FORMAT_1_DATA = deHexStr(
|
||||||
|
'0001 0000 0001 ' # 0: Version=1.0, Format=1
|
||||||
|
'0006 0004 0002 ' # 6: LookupFormat=6, UnitSize=4, NUnits=2
|
||||||
|
'0008 0001 0000 ' # 12: SearchRange=8, EntrySelector=1, RangeShift=0
|
||||||
|
'000A 001E ' # 18: Glyph=10(=C), OffsetOfOpticalBoundsPoints=30
|
||||||
|
'002B 0026 ' # 22: Glyph=43(=A), OffsetOfOpticalBoundsPoints=38
|
||||||
|
'FFFF 0000 ' # 26: Glyph=<end>, OffsetOfOpticalBoundsPoints=0
|
||||||
|
'0024 0025 0026 0027 ' # 30: Bounds[C].Left=36 .Top=37 .Right=38 .Bottom=39
|
||||||
|
'0020 0029 FFFF FFFF ' # 38: Bounds[A].Left=32 .Top=41 .Right=-1 .Bottom=-1
|
||||||
|
) # 46: <end>
|
||||||
|
assert(len(OPBD_FORMAT_1_DATA) == 46)
|
||||||
|
|
||||||
|
|
||||||
|
OPBD_FORMAT_1_XML = [
|
||||||
|
'<Version value="0x00010000"/>',
|
||||||
|
'<OpticalBounds Format="1">',
|
||||||
|
' <OpticalBoundsPoints>',
|
||||||
|
' <Lookup glyph="A">',
|
||||||
|
' <Left value="32"/>',
|
||||||
|
' <Top value="41"/>',
|
||||||
|
' <Right value="-1"/>',
|
||||||
|
' <Bottom value="-1"/>',
|
||||||
|
' </Lookup>',
|
||||||
|
' <Lookup glyph="C">',
|
||||||
|
' <Left value="36"/>',
|
||||||
|
' <Top value="37"/>',
|
||||||
|
' <Right value="38"/>',
|
||||||
|
' <Bottom value="39"/>',
|
||||||
|
' </Lookup>',
|
||||||
|
' </OpticalBoundsPoints>',
|
||||||
|
'</OpticalBounds>',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class OPBDTest(unittest.TestCase):
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
cls.maxDiff = None
|
||||||
|
glyphs = ['.notdef'] + ['X.alt%d' for g in range(1, 50)]
|
||||||
|
glyphs[10] = 'C'
|
||||||
|
glyphs[43] = 'A'
|
||||||
|
cls.font = FakeFont(glyphs)
|
||||||
|
|
||||||
|
def test_decompile_toXML_format0(self):
|
||||||
|
table = newTable('opbd')
|
||||||
|
table.decompile(OPBD_FORMAT_0_DATA, self.font)
|
||||||
|
self.assertEqual(getXML(table.toXML), OPBD_FORMAT_0_XML)
|
||||||
|
|
||||||
|
def test_compile_fromXML_format0(self):
|
||||||
|
table = newTable('opbd')
|
||||||
|
for name, attrs, content in parseXML(OPBD_FORMAT_0_XML):
|
||||||
|
table.fromXML(name, attrs, content, font=self.font)
|
||||||
|
self.assertEqual(hexStr(table.compile(self.font)),
|
||||||
|
hexStr(OPBD_FORMAT_0_DATA))
|
||||||
|
|
||||||
|
def test_decompile_toXML_format1(self):
|
||||||
|
table = newTable('opbd')
|
||||||
|
table.decompile(OPBD_FORMAT_1_DATA, self.font)
|
||||||
|
self.assertEqual(getXML(table.toXML), OPBD_FORMAT_1_XML)
|
||||||
|
|
||||||
|
def test_compile_fromXML_format1(self):
|
||||||
|
table = newTable('opbd')
|
||||||
|
for name, attrs, content in parseXML(OPBD_FORMAT_1_XML):
|
||||||
|
table.fromXML(name, attrs, content, font=self.font)
|
||||||
|
self.assertEqual(hexStr(table.compile(self.font)),
|
||||||
|
hexStr(OPBD_FORMAT_1_DATA))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
import sys
|
||||||
|
sys.exit(unittest.main())
|
Loading…
x
Reference in New Issue
Block a user