otTables.py revision 64b5c80e80444a124da335e8d4d208bffcf2737b
1"""fontTools.ttLib.tables.otTables -- A collection of classes representing the various 2OpenType subtables. 3 4Most are constructed upon import from data in otData.py, all are populated with 5converter objects from otConverters.py. 6""" 7 8from otBase import BaseTable, FormatSwitchingBaseTable 9 10 11class LookupOrder(BaseTable): 12 """Dummy class; this table isn't defined, but is used, and is always NULL.""" 13 14class FeatureParams(BaseTable): 15 """Dummy class; this table isn't defined, but is used, and is always NULL.""" 16 17 18# 19# For each subtable format there is a class. However, we don't really distinguish 20# between "field name" and "format name": often these are the same. Yet there's 21# a whole bunch of fields with different names. The following dict is a mapping 22# from "format name" to "field name". _buildClasses() uses this to create a 23# subclass for each alternate field name. 24# 25_equivalents = { 26 'MarkArray': ("Mark1Array",), 27 'LangSys': ('DefaultLangSys',), 28 'Coverage': ('MarkCoverage', 'BaseCoverage', 'LigatureCoverage', 'Mark1Coverage', 29 'Mark2Coverage', 'BacktrackCoverage', 'InputCoverage', 30 'LookaheadCoverage'), 31 'ClassDef': ('ClassDef1', 'ClassDef2', 'BacktrackClassDef', 'InputClassDef', 32 'LookaheadClassDef', 'GlyphClassDef', 'MarkAttachClassDef'), 33 'Anchor': ('EntryAnchor', 'ExitAnchor', 'BaseAnchor', 'LigatureAnchor', 34 'Mark2Anchor', 'MarkAnchor'), 35 'Device': ('XPlaDevice', 'YPlaDevice', 'XAdvDevice', 'YAdvDevice', 36 'XDeviceTable', 'YDeviceTable', 'DeviceTable'), 37 'Axis': ('HorizAxis', 'VertAxis',), 38 'MinMax': ('DefaultMinMax',), 39 'BaseCoord': ('MinCoord', 'MaxCoord',), 40 'JstfLangSys': ('DefJstfLangSys',), 41 'JstfGSUBModList': ('ShrinkageEnableGSUB', 'ShrinkageDisableGSUB', 'ExtensionEnableGSUB', 42 'ExtensionDisableGSUB',), 43 'JstfGPOSModList': ('ShrinkageEnableGPOS', 'ShrinkageDisableGPOS', 'ExtensionEnableGPOS', 44 'ExtensionDisableGPOS',), 45 'JstfMax': ('ShrinkageJstfMax', 'ExtensionJstfMax',), 46} 47 48 49def _buildClasses(): 50 import new, re 51 from otData import otData 52 53 formatPat = re.compile("([A-Za-z0-9]+)Format(\d+)$") 54 namespace = globals() 55 56 # populate module with classes 57 for name, table in otData: 58 baseClass = BaseTable 59 m = formatPat.match(name) 60 if m: 61 # XxxFormatN subtable, we only add the "base" table 62 name = m.group(1) 63 baseClass = FormatSwitchingBaseTable 64 if not namespace.has_key(name): 65 # the class doesn't exist yet, so the base implementation is used. 66 cls = new.classobj(name, (baseClass,), {}) 67 namespace[name] = cls 68 69 for base, alts in _equivalents.items(): 70 base = namespace[base] 71 for alt in alts: 72 namespace[alt] = new.classobj(alt, (base,), {}) 73 74 global lookupTypes 75 lookupTypes = { 76 'GSUB': { 77 1: SingleSubst, 78 2: MultipleSubst, 79 3: AlternateSubst, 80 4: LigatureSubst, 81 5: ContextSubst, 82 6: ChainContextSubst, 83 7: ExtensionSubst, 84 }, 85 'GPOS': { 86 1: SinglePos, 87 2: PairPos, 88 3: CursivePos, 89 4: MarkBasePos, 90 5: MarkLigPos, 91 6: MarkMarkPos, 92 7: ContextPos, 93 8: ChainContextPos, 94 9: ExtensionPos, 95 }, 96 } 97 lookupTypes['JSTF'] = lookupTypes['GPOS'] # JSTF contains GPOS 98 for lookupEnum in lookupTypes.values(): 99 for enum, cls in lookupEnum.items(): 100 cls.LookupType = enum 101 102 # add converters to classes 103 from otConverters import buildConverters 104 for name, table in otData: 105 m = formatPat.match(name) 106 if m: 107 # XxxFormatN subtable, add converter to "base" table 108 name, format = m.groups() 109 format = int(format) 110 cls = namespace[name] 111 if not hasattr(cls, "converters"): 112 cls.converters = {} 113 cls.convertersByName = {} 114 converters, convertersByName = buildConverters(table[1:], namespace) 115 cls.converters[format] = converters 116 cls.convertersByName[format] = convertersByName 117 else: 118 cls = namespace[name] 119 cls.converters, cls.convertersByName = buildConverters(table, namespace) 120 121 122_buildClasses() 123