Home | History | Annotate | Download | only in tables
      1 from __future__ import print_function, division, absolute_import, unicode_literals
      2 from fontTools.misc.py23 import *
      3 from fontTools.misc.testTools import FakeFont, getXML, parseXML
      4 from fontTools.misc.textTools import deHexStr, hexStr
      5 from fontTools.ttLib import newTable
      6 import unittest
      7 
      8 
      9 # Example: Format 0 Optical Bounds Table
     10 # https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6opbd.html
     11 OPBD_FORMAT_0_DATA = deHexStr(
     12     '0001 0000 0000 '       #  0: Version=1.0, Format=0
     13     '0006 0004 0002 '       #  6: LookupFormat=6, UnitSize=4, NUnits=2
     14     '0008 0001 0000 '       # 12: SearchRange=8, EntrySelector=1, RangeShift=0
     15     '000A 001E '            # 18: Glyph=10(=C), OffsetOfOpticalBoundsDeltas=30
     16     '002B 0026 '            # 22: Glyph=43(=A), OffsetOfOpticalBoundsDeltas=38
     17     'FFFF 0000 '            # 26: Glyph=<end>, OffsetOfOpticalBoundsDeltas=0
     18     'FFCE 0005 0037 FFFB '  # 30: Bounds[C].Left=-50 .Top=5 .Right=55 .Bottom=-5
     19     'FFF6 000F 0000 0000 '  # 38: Bounds[A].Left=-10 .Top=15 .Right=0 .Bottom=0
     20 )                           # 46: <end>
     21 assert(len(OPBD_FORMAT_0_DATA) == 46)
     22 
     23 
     24 OPBD_FORMAT_0_XML = [
     25     '<Version value="0x00010000"/>',
     26     '<OpticalBounds Format="0">',
     27     '  <OpticalBoundsDeltas>',
     28     '    <Lookup glyph="A">',
     29     '      <Left value="-10"/>',
     30     '      <Top value="15"/>',
     31     '      <Right value="0"/>',
     32     '      <Bottom value="0"/>',
     33     '    </Lookup>',
     34     '    <Lookup glyph="C">',
     35     '      <Left value="-50"/>',
     36     '      <Top value="5"/>',
     37     '      <Right value="55"/>',
     38     '      <Bottom value="-5"/>',
     39     '    </Lookup>',
     40     '  </OpticalBoundsDeltas>',
     41     '</OpticalBounds>',
     42 ]
     43 
     44 
     45 # Example: Format 1 Optical Bounds Table
     46 # https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6opbd.html
     47 OPBD_FORMAT_1_DATA = deHexStr(
     48     '0001 0000 0001 '       #  0: Version=1.0, Format=1
     49     '0006 0004 0002 '       #  6: LookupFormat=6, UnitSize=4, NUnits=2
     50     '0008 0001 0000 '       # 12: SearchRange=8, EntrySelector=1, RangeShift=0
     51     '000A 001E '            # 18: Glyph=10(=C), OffsetOfOpticalBoundsPoints=30
     52     '002B 0026 '            # 22: Glyph=43(=A), OffsetOfOpticalBoundsPoints=38
     53     'FFFF 0000 '            # 26: Glyph=<end>, OffsetOfOpticalBoundsPoints=0
     54     '0024 0025 0026 0027 '  # 30: Bounds[C].Left=36 .Top=37 .Right=38 .Bottom=39
     55     '0020 0029 FFFF FFFF '  # 38: Bounds[A].Left=32 .Top=41 .Right=-1 .Bottom=-1
     56 )                           # 46: <end>
     57 assert(len(OPBD_FORMAT_1_DATA) == 46)
     58 
     59 
     60 OPBD_FORMAT_1_XML = [
     61     '<Version value="0x00010000"/>',
     62     '<OpticalBounds Format="1">',
     63     '  <OpticalBoundsPoints>',
     64     '    <Lookup glyph="A">',
     65     '      <Left value="32"/>',
     66     '      <Top value="41"/>',
     67     '      <Right value="-1"/>',
     68     '      <Bottom value="-1"/>',
     69     '    </Lookup>',
     70     '    <Lookup glyph="C">',
     71     '      <Left value="36"/>',
     72     '      <Top value="37"/>',
     73     '      <Right value="38"/>',
     74     '      <Bottom value="39"/>',
     75     '    </Lookup>',
     76     '  </OpticalBoundsPoints>',
     77     '</OpticalBounds>',
     78 ]
     79 
     80 
     81 # This is the content of the Optical Bounds table in AppleChancery.ttf,
     82 # font version 8.0d1e1 of 2013-02-06. An early version of fontTools
     83 # was crashing when trying to decompile this table.
     84 # https://github.com/fonttools/fonttools/issues/1031
     85 OPBD_APPLE_CHANCERY_DATA = deHexStr(
     86     '0001 0000 0000 '  #   0: Version=1.0, Format=0
     87     '0004 0006 0011 '  #   6: LookupFormat=4, UnitSize=6, NUnits=17
     88     '0060 0004 0006 '  #  12: SearchRange=96, EntrySelector=4, RangeShift=6
     89     '017d 017d 0072 '  #  18: Seg[0].LastGlyph=381, FirstGlyph=381, Off=114(+6)
     90     '0183 0180 0074 '  #  24: Seg[1].LastGlyph=387, FirstGlyph=384, Off=116(+6)
     91     '0186 0185 007c '  #  30: Seg[2].LastGlyph=390, FirstGlyph=389, Off=124(+6)
     92     '018f 018b 0080 '  #  36: Seg[3].LastGlyph=399, FirstGlyph=395, Off=128(+6)
     93     '01a0 0196 008a '  #  42: Seg[4].LastGlyph=416, FirstGlyph=406, Off=138(+6)
     94     '01a5 01a3 00a0 '  #  48: Seg[5].LastGlyph=421, FirstGlyph=419, Off=160(+6)
     95     '01aa 01aa 00a6 '  #  54: Seg[6].LastGlyph=426, FirstGlyph=426, Off=166(+6)
     96     '01ac 01ac 00a8 '  #  60: Seg[7].LastGlyph=428, FirstGlyph=428, Off=168(+6)
     97     '01fb 01f1 00aa '  #  66: Seg[8].LastGlyph=507, FirstGlyph=497, Off=170(+6)
     98     '0214 0209 00c0 '  #  72: Seg[9].LastGlyph=532, FirstGlyph=521, Off=192(+6)
     99     '021d 0216 00d8 '  #  78: Seg[10].LastGlyph=541, FirstGlyph=534, Off=216(+6)
    100     '0222 0220 00e8 '  #  84: Seg[11].LastGlyph=546, FirstGlyph=544, Off=232(+6)
    101     '0227 0225 00ee '  #  90: Seg[12].LastGlyph=551, FirstGlyph=549, Off=238(+6)
    102     '0229 0229 00f4 '  #  96: Seg[13].LastGlyph=553, FirstGlyph=553, Off=244(+6)
    103     '023b 023b 00f6 '  # 102: Seg[14].LastGlyph=571, FirstGlyph=571, Off=246(+6)
    104     '023e 023e 00f8 '  # 108: Seg[15].LastGlyph=574, FirstGlyph=574, Off=248(+6)
    105     'ffff ffff 00fa '  # 114: Seg[16]=<end>
    106     '0100 0108 0110 0118 0120 0128 0130 0138 0140 0148 0150 0158 '
    107     '0160 0168 0170 0178 0180 0188 0190 0198 01a0 01a8 01b0 01b8 '
    108     '01c0 01c8 01d0 01d8 01e0 01e8 01f0 01f8 0200 0208 0210 0218 '
    109     '0220 0228 0230 0238 0240 0248 0250 0258 0260 0268 0270 0278 '
    110     '0280 0288 0290 0298 02a0 02a8 02b0 02b8 02c0 02c8 02d0 02d8 '
    111     '02e0 02e8 02f0 02f8 0300 0308 0310 0318 fd98 0000 0000 0000 '
    112     'fdbc 0000 0000 0000 fdbc 0000 0000 0000 fdbf 0000 0000 0000 '
    113     'fdbc 0000 0000 0000 fd98 0000 0000 0000 fda9 0000 0000 0000 '
    114     'fd98 0000 0000 0000 fd98 0000 0000 0000 fd98 0000 0000 0000 '
    115     '0000 0000 0205 0000 0000 0000 0205 0000 0000 0000 02a4 0000 '
    116     '0000 0000 027e 0000 0000 0000 02f4 0000 0000 0000 02a4 0000 '
    117     '0000 0000 0365 0000 0000 0000 0291 0000 0000 0000 0291 0000 '
    118     '0000 0000 026a 0000 0000 0000 02b8 0000 0000 0000 02cb 0000 '
    119     '0000 0000 02a4 0000 0000 0000 01a9 0000 0000 0000 0244 0000 '
    120     '0000 0000 02a4 0000 0000 0000 02cb 0000 0000 0000 0244 0000 '
    121     '0000 0000 0307 0000 0000 0000 0307 0000 0000 0000 037f 0000 '
    122     '0000 0000 0307 0000 0000 0000 0307 0000 0000 0000 0307 0000 '
    123     '0000 0000 0307 0000 0000 0000 0307 0000 0000 0000 03e3 0000 '
    124     '0000 0000 030c 0000 0000 0000 0307 0000 fe30 0000 0000 0000 '
    125     'fe7e 0000 0000 0000 fe91 0000 0000 0000 fe6a 0000 0000 0000 '
    126     'fe6a 0000 0000 0000 fecb 0000 0000 0000 fe6a 0000 0000 0000 '
    127     'fe7e 0000 0000 0000 fea4 0000 0000 0000 fe7e 0000 0000 0000 '
    128     'fe44 0000 0000 0000 fea4 0000 0000 0000 feb8 0000 0000 0000 '
    129     'fe7e 0000 0000 0000 fe5e 0000 0000 0000 fe37 0000 0000 0000 '
    130     'fe37 0000 0000 0000 fcbd 0000 0000 0000 fd84 0000 0000 0000 '
    131     'fd98 0000 0000 0000 fd82 0000 0000 0000 fcbd 0000 0000 0000 '
    132     'fd84 0000 0000 0000 fcbd 0000 0000 0000 fcbd 0000 0000 0000 '
    133     'fe72 0000 0000 0000 ff9d 0000 0000 0000 0000 0000 032f 0000 '
    134     '0000 0000 03ba 0000 '
    135 )
    136 assert len(OPBD_APPLE_CHANCERY_DATA) == 800
    137 
    138 
    139 class OPBDTest(unittest.TestCase):
    140 
    141     @classmethod
    142     def setUpClass(cls):
    143         cls.maxDiff = None
    144         glyphs = ['.notdef'] + ['X.alt%d' for g in range(1, 50)]
    145         glyphs[10] = 'C'
    146         glyphs[43] = 'A'
    147         cls.font = FakeFont(glyphs)
    148 
    149     def test_decompile_toXML_format0(self):
    150         table = newTable('opbd')
    151         table.decompile(OPBD_FORMAT_0_DATA, self.font)
    152         self.assertEqual(getXML(table.toXML), OPBD_FORMAT_0_XML)
    153 
    154     def test_compile_fromXML_format0(self):
    155         table = newTable('opbd')
    156         for name, attrs, content in parseXML(OPBD_FORMAT_0_XML):
    157             table.fromXML(name, attrs, content, font=self.font)
    158         self.assertEqual(hexStr(table.compile(self.font)),
    159                          hexStr(OPBD_FORMAT_0_DATA))
    160 
    161     def test_decompile_toXML_format1(self):
    162         table = newTable('opbd')
    163         table.decompile(OPBD_FORMAT_1_DATA, self.font)
    164         self.assertEqual(getXML(table.toXML), OPBD_FORMAT_1_XML)
    165 
    166     def test_compile_fromXML_format1(self):
    167         table = newTable('opbd')
    168         for name, attrs, content in parseXML(OPBD_FORMAT_1_XML):
    169             table.fromXML(name, attrs, content, font=self.font)
    170         self.assertEqual(hexStr(table.compile(self.font)),
    171                          hexStr(OPBD_FORMAT_1_DATA))
    172 
    173     def test_decompile_AppleChancery(self):
    174         # Make sure we do not crash when decompiling the 'opbd' table of
    175         # AppleChancery.ttf. https://github.com/fonttools/fonttools/issues/1031
    176         table = newTable('opbd')
    177         table.decompile(OPBD_APPLE_CHANCERY_DATA, self.font)
    178         self.assertIn('<OpticalBounds Format="0">', getXML(table.toXML))
    179 
    180 
    181 if __name__ == '__main__':
    182     import sys
    183     sys.exit(unittest.main())
    184