Merge pull request #1582 from fonttools/max_ctx_recalc
(Re)calculate OS/2.usMaxContext value
This commit is contained in:
commit
6edf6257e6
@ -7,6 +7,7 @@ from fontTools.feaLib.error import FeatureLibError
|
|||||||
from fontTools.feaLib.parser import Parser
|
from fontTools.feaLib.parser import Parser
|
||||||
from fontTools.feaLib.ast import FeatureFile
|
from fontTools.feaLib.ast import FeatureFile
|
||||||
from fontTools.otlLib import builder as otl
|
from fontTools.otlLib import builder as otl
|
||||||
|
from fontTools.otlLib.maxContextCalc import maxCtxFont
|
||||||
from fontTools.ttLib import newTable, getTableModule
|
from fontTools.ttLib import newTable, getTableModule
|
||||||
from fontTools.ttLib.tables import otBase, otTables
|
from fontTools.ttLib.tables import otBase, otTables
|
||||||
from collections import defaultdict, OrderedDict
|
from collections import defaultdict, OrderedDict
|
||||||
@ -137,6 +138,9 @@ class Builder(object):
|
|||||||
fontTable.table = table
|
fontTable.table = table
|
||||||
elif tag in self.font:
|
elif tag in self.font:
|
||||||
del self.font[tag]
|
del self.font[tag]
|
||||||
|
if (any(tag in self.font for tag in ("GPOS", "GSUB")) and
|
||||||
|
"OS/2" in self.font):
|
||||||
|
self.font["OS/2"].usMaxContext = maxCtxFont(self.font)
|
||||||
if "GDEF" in tables:
|
if "GDEF" in tables:
|
||||||
gdef = self.buildGDEF()
|
gdef = self.buildGDEF()
|
||||||
if gdef:
|
if gdef:
|
||||||
|
@ -21,6 +21,7 @@ that works:
|
|||||||
fb.setupHorizontalHeader()
|
fb.setupHorizontalHeader()
|
||||||
fb.setupNameTable(...)
|
fb.setupNameTable(...)
|
||||||
fb.setupOS2()
|
fb.setupOS2()
|
||||||
|
fb.addOpenTypeFeatures(...)
|
||||||
fb.setupPost()
|
fb.setupPost()
|
||||||
fb.save(...)
|
fb.save(...)
|
||||||
|
|
||||||
@ -299,7 +300,7 @@ _OS2Defaults = dict(
|
|||||||
sCapHeight = 0,
|
sCapHeight = 0,
|
||||||
usDefaultChar = 0, # .notdef
|
usDefaultChar = 0, # .notdef
|
||||||
usBreakChar = 32, # space
|
usBreakChar = 32, # space
|
||||||
usMaxContext = 2, # just kerning
|
usMaxContext = 0,
|
||||||
usLowerOpticalPointSize = 0,
|
usLowerOpticalPointSize = 0,
|
||||||
usUpperOpticalPointSize = 0,
|
usUpperOpticalPointSize = 0,
|
||||||
)
|
)
|
||||||
|
101
Lib/fontTools/otlLib/maxContextCalc.py
Normal file
101
Lib/fontTools/otlLib/maxContextCalc.py
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
from __future__ import print_function, division, absolute_import, unicode_literals
|
||||||
|
|
||||||
|
__all__ = ['maxCtxFont']
|
||||||
|
|
||||||
|
|
||||||
|
def maxCtxFont(font):
|
||||||
|
"""Calculate the usMaxContext value for an entire font."""
|
||||||
|
|
||||||
|
maxCtx = 0
|
||||||
|
for tag in ('GSUB', 'GPOS'):
|
||||||
|
if tag not in font:
|
||||||
|
continue
|
||||||
|
table = font[tag].table
|
||||||
|
if not table.LookupList:
|
||||||
|
continue
|
||||||
|
for lookup in table.LookupList.Lookup:
|
||||||
|
for st in lookup.SubTable:
|
||||||
|
maxCtx = maxCtxSubtable(maxCtx, tag, lookup.LookupType, st)
|
||||||
|
return maxCtx
|
||||||
|
|
||||||
|
|
||||||
|
def maxCtxSubtable(maxCtx, tag, lookupType, st):
|
||||||
|
"""Calculate usMaxContext based on a single lookup table (and an existing
|
||||||
|
max value).
|
||||||
|
"""
|
||||||
|
|
||||||
|
# single positioning, single / multiple substitution
|
||||||
|
if (tag == 'GPOS' and lookupType == 1) or (
|
||||||
|
tag == 'GSUB' and lookupType in (1, 2, 3)):
|
||||||
|
maxCtx = max(maxCtx, 1)
|
||||||
|
|
||||||
|
# pair positioning
|
||||||
|
elif tag == 'GPOS' and lookupType == 2:
|
||||||
|
maxCtx = max(maxCtx, 2)
|
||||||
|
|
||||||
|
# ligatures
|
||||||
|
elif tag == 'GSUB' and lookupType == 4:
|
||||||
|
for ligatures in st.ligatures.values():
|
||||||
|
for ligature in ligatures:
|
||||||
|
maxCtx = max(maxCtx, ligature.CompCount)
|
||||||
|
|
||||||
|
# context
|
||||||
|
elif (tag == 'GPOS' and lookupType == 7) or (
|
||||||
|
tag == 'GSUB' and lookupType == 5):
|
||||||
|
maxCtx = maxCtxContextualSubtable(
|
||||||
|
maxCtx, st, 'Pos' if tag == 'GPOS' else 'Sub')
|
||||||
|
|
||||||
|
# chained context
|
||||||
|
elif (tag == 'GPOS' and lookupType == 8) or (
|
||||||
|
tag == 'GSUB' and lookupType == 6):
|
||||||
|
maxCtx = maxCtxContextualSubtable(
|
||||||
|
maxCtx, st, 'Pos' if tag == 'GPOS' else 'Sub', 'Chain')
|
||||||
|
|
||||||
|
# extensions
|
||||||
|
elif (tag == 'GPOS' and lookupType == 9) or (
|
||||||
|
tag == 'GSUB' and lookupType == 7):
|
||||||
|
maxCtx = maxCtxSubtable(
|
||||||
|
maxCtx, tag, st.ExtensionLookupType, st.ExtSubTable)
|
||||||
|
|
||||||
|
# reverse-chained context
|
||||||
|
elif tag == 'GSUB' and lookupType == 8:
|
||||||
|
maxCtx = maxCtxContextualRule(maxCtx, st, 'Reverse')
|
||||||
|
|
||||||
|
return maxCtx
|
||||||
|
|
||||||
|
|
||||||
|
def maxCtxContextualSubtable(maxCtx, st, ruleType, chain=''):
|
||||||
|
"""Calculate usMaxContext based on a contextual feature subtable."""
|
||||||
|
|
||||||
|
if st.Format == 1:
|
||||||
|
for ruleset in getattr(st, '%s%sRuleSet' % (chain, ruleType)):
|
||||||
|
if ruleset is None:
|
||||||
|
continue
|
||||||
|
for rule in getattr(ruleset, '%s%sRule' % (chain, ruleType)):
|
||||||
|
if rule is None:
|
||||||
|
continue
|
||||||
|
maxCtx = maxCtxContextualRule(maxCtx, rule, chain)
|
||||||
|
|
||||||
|
elif st.Format == 2:
|
||||||
|
for ruleset in getattr(st, '%s%sClassSet' % (chain, ruleType)):
|
||||||
|
if ruleset is None:
|
||||||
|
continue
|
||||||
|
for rule in getattr(ruleset, '%s%sClassRule' % (chain, ruleType)):
|
||||||
|
if rule is None:
|
||||||
|
continue
|
||||||
|
maxCtx = maxCtxContextualRule(maxCtx, rule, chain)
|
||||||
|
|
||||||
|
elif st.Format == 3:
|
||||||
|
maxCtx = maxCtxContextualRule(maxCtx, st, chain)
|
||||||
|
|
||||||
|
return maxCtx
|
||||||
|
|
||||||
|
|
||||||
|
def maxCtxContextualRule(maxCtx, st, chain):
|
||||||
|
"""Calculate usMaxContext based on a contextual feature rule."""
|
||||||
|
|
||||||
|
if not chain:
|
||||||
|
return max(maxCtx, st.GlyphCount)
|
||||||
|
elif chain == 'Reverse':
|
||||||
|
return max(maxCtx, st.GlyphCount + st.LookAheadGlyphCount)
|
||||||
|
return max(maxCtx, st.InputGlyphCount + st.LookAheadGlyphCount)
|
@ -7,6 +7,7 @@ from fontTools.misc.py23 import *
|
|||||||
from fontTools.misc.fixedTools import otRound
|
from fontTools.misc.fixedTools import otRound
|
||||||
from fontTools import ttLib
|
from fontTools import ttLib
|
||||||
from fontTools.ttLib.tables import otTables
|
from fontTools.ttLib.tables import otTables
|
||||||
|
from fontTools.otlLib.maxContextCalc import maxCtxFont
|
||||||
from fontTools.pens.basePen import NullPen
|
from fontTools.pens.basePen import NullPen
|
||||||
from fontTools.misc.loggingTools import Timer
|
from fontTools.misc.loggingTools import Timer
|
||||||
from fontTools.subset.cff import *
|
from fontTools.subset.cff import *
|
||||||
@ -322,6 +323,10 @@ Other font-specific options:
|
|||||||
Update the 'OS/2 xAvgCharWidth' field after subsetting.
|
Update the 'OS/2 xAvgCharWidth' field after subsetting.
|
||||||
--no-recalc-average-width
|
--no-recalc-average-width
|
||||||
Don't change the 'OS/2 xAvgCharWidth' field. [default]
|
Don't change the 'OS/2 xAvgCharWidth' field. [default]
|
||||||
|
--recalc-max-context
|
||||||
|
Update the 'OS/2 usMaxContext' field after subsetting.
|
||||||
|
--no-recalc-max-context
|
||||||
|
Don't change the 'OS/2 usMaxContext' field. [default]
|
||||||
--font-number=<number>
|
--font-number=<number>
|
||||||
Select font number for TrueType Collection (.ttc/.otc), starting from 0.
|
Select font number for TrueType Collection (.ttc/.otc), starting from 0.
|
||||||
|
|
||||||
@ -2305,6 +2310,7 @@ class Options(object):
|
|||||||
self.recalc_timestamp = False # Recalculate font modified timestamp
|
self.recalc_timestamp = False # Recalculate font modified timestamp
|
||||||
self.prune_unicode_ranges = True # Clear unused 'ulUnicodeRange' bits
|
self.prune_unicode_ranges = True # Clear unused 'ulUnicodeRange' bits
|
||||||
self.recalc_average_width = False # update 'xAvgCharWidth'
|
self.recalc_average_width = False # update 'xAvgCharWidth'
|
||||||
|
self.recalc_max_context = False # update 'usMaxContext'
|
||||||
self.canonical_order = None # Order tables as recommended
|
self.canonical_order = None # Order tables as recommended
|
||||||
self.flavor = None # May be 'woff' or 'woff2'
|
self.flavor = None # May be 'woff' or 'woff2'
|
||||||
self.with_zopfli = False # use zopfli instead of zlib for WOFF 1.0
|
self.with_zopfli = False # use zopfli instead of zlib for WOFF 1.0
|
||||||
@ -2614,6 +2620,11 @@ class Subsetter(object):
|
|||||||
if avg_width != font[tag].xAvgCharWidth:
|
if avg_width != font[tag].xAvgCharWidth:
|
||||||
font[tag].xAvgCharWidth = avg_width
|
font[tag].xAvgCharWidth = avg_width
|
||||||
log.info("%s xAvgCharWidth updated: %d", tag, avg_width)
|
log.info("%s xAvgCharWidth updated: %d", tag, avg_width)
|
||||||
|
if self.options.recalc_max_context:
|
||||||
|
max_context = maxCtxFont(font)
|
||||||
|
if max_context != font[tag].usMaxContext:
|
||||||
|
font[tag].usMaxContext = max_context
|
||||||
|
log.info("%s usMaxContext updated: %d", tag, max_context)
|
||||||
clazz = ttLib.getTableClass(tag)
|
clazz = ttLib.getTableClass(tag)
|
||||||
if hasattr(clazz, 'prune_post_subset'):
|
if hasattr(clazz, 'prune_post_subset'):
|
||||||
with timer("prune '%s'" % tag):
|
with timer("prune '%s'" % tag):
|
||||||
|
@ -233,6 +233,57 @@
|
|||||||
</GlobalSubrs>
|
</GlobalSubrs>
|
||||||
</CFF>
|
</CFF>
|
||||||
|
|
||||||
|
<GPOS>
|
||||||
|
<Version value="0x00010000"/>
|
||||||
|
<ScriptList>
|
||||||
|
<!-- ScriptCount=1 -->
|
||||||
|
<ScriptRecord index="0">
|
||||||
|
<ScriptTag value="DFLT"/>
|
||||||
|
<Script>
|
||||||
|
<DefaultLangSys>
|
||||||
|
<ReqFeatureIndex value="65535"/>
|
||||||
|
<!-- FeatureCount=1 -->
|
||||||
|
<FeatureIndex index="0" value="0"/>
|
||||||
|
</DefaultLangSys>
|
||||||
|
<!-- LangSysCount=0 -->
|
||||||
|
</Script>
|
||||||
|
</ScriptRecord>
|
||||||
|
</ScriptList>
|
||||||
|
<FeatureList>
|
||||||
|
<!-- FeatureCount=1 -->
|
||||||
|
<FeatureRecord index="0">
|
||||||
|
<FeatureTag value="kern"/>
|
||||||
|
<Feature>
|
||||||
|
<!-- LookupCount=1 -->
|
||||||
|
<LookupListIndex index="0" value="0"/>
|
||||||
|
</Feature>
|
||||||
|
</FeatureRecord>
|
||||||
|
</FeatureList>
|
||||||
|
<LookupList>
|
||||||
|
<!-- LookupCount=1 -->
|
||||||
|
<Lookup index="0">
|
||||||
|
<LookupType value="2"/>
|
||||||
|
<LookupFlag value="0"/>
|
||||||
|
<!-- SubTableCount=1 -->
|
||||||
|
<PairPos index="0" Format="1">
|
||||||
|
<Coverage Format="1">
|
||||||
|
<Glyph value="A"/>
|
||||||
|
</Coverage>
|
||||||
|
<ValueFormat1 value="4"/>
|
||||||
|
<ValueFormat2 value="0"/>
|
||||||
|
<!-- PairSetCount=1 -->
|
||||||
|
<PairSet index="0">
|
||||||
|
<!-- PairValueCount=1 -->
|
||||||
|
<PairValueRecord index="0">
|
||||||
|
<SecondGlyph value="a"/>
|
||||||
|
<Value1 XAdvance="-50"/>
|
||||||
|
</PairValueRecord>
|
||||||
|
</PairSet>
|
||||||
|
</PairPos>
|
||||||
|
</Lookup>
|
||||||
|
</LookupList>
|
||||||
|
</GPOS>
|
||||||
|
|
||||||
<hmtx>
|
<hmtx>
|
||||||
<mtx name=".notdef" width="600" lsb="100"/>
|
<mtx name=".notdef" width="600" lsb="100"/>
|
||||||
<mtx name=".null" width="600" lsb="100"/>
|
<mtx name=".null" width="600" lsb="100"/>
|
||||||
|
@ -119,7 +119,7 @@
|
|||||||
<sCapHeight value="0"/>
|
<sCapHeight value="0"/>
|
||||||
<usDefaultChar value="0"/>
|
<usDefaultChar value="0"/>
|
||||||
<usBreakChar value="32"/>
|
<usBreakChar value="32"/>
|
||||||
<usMaxContext value="2"/>
|
<usMaxContext value="1"/>
|
||||||
</OS_2>
|
</OS_2>
|
||||||
|
|
||||||
<hmtx>
|
<hmtx>
|
||||||
@ -257,6 +257,45 @@
|
|||||||
</extraNames>
|
</extraNames>
|
||||||
</post>
|
</post>
|
||||||
|
|
||||||
|
<GSUB>
|
||||||
|
<Version value="0x00010000"/>
|
||||||
|
<ScriptList>
|
||||||
|
<!-- ScriptCount=1 -->
|
||||||
|
<ScriptRecord index="0">
|
||||||
|
<ScriptTag value="DFLT"/>
|
||||||
|
<Script>
|
||||||
|
<DefaultLangSys>
|
||||||
|
<ReqFeatureIndex value="65535"/>
|
||||||
|
<!-- FeatureCount=1 -->
|
||||||
|
<FeatureIndex index="0" value="0"/>
|
||||||
|
</DefaultLangSys>
|
||||||
|
<!-- LangSysCount=0 -->
|
||||||
|
</Script>
|
||||||
|
</ScriptRecord>
|
||||||
|
</ScriptList>
|
||||||
|
<FeatureList>
|
||||||
|
<!-- FeatureCount=1 -->
|
||||||
|
<FeatureRecord index="0">
|
||||||
|
<FeatureTag value="salt"/>
|
||||||
|
<Feature>
|
||||||
|
<!-- LookupCount=1 -->
|
||||||
|
<LookupListIndex index="0" value="0"/>
|
||||||
|
</Feature>
|
||||||
|
</FeatureRecord>
|
||||||
|
</FeatureList>
|
||||||
|
<LookupList>
|
||||||
|
<!-- LookupCount=1 -->
|
||||||
|
<Lookup index="0">
|
||||||
|
<LookupType value="1"/>
|
||||||
|
<LookupFlag value="0"/>
|
||||||
|
<!-- SubTableCount=1 -->
|
||||||
|
<SingleSubst index="0" Format="1">
|
||||||
|
<Substitution in="A" out="a"/>
|
||||||
|
</SingleSubst>
|
||||||
|
</Lookup>
|
||||||
|
</LookupList>
|
||||||
|
</GSUB>
|
||||||
|
|
||||||
<DSIG>
|
<DSIG>
|
||||||
<!-- note that the Digital Signature will be invalid after recompilation! -->
|
<!-- note that the Digital Signature will be invalid after recompilation! -->
|
||||||
<tableHeader flag="0x1" numSigs="1" version="1"/>
|
<tableHeader flag="0x1" numSigs="1" version="1"/>
|
||||||
|
@ -105,7 +105,7 @@
|
|||||||
<sCapHeight value="0"/>
|
<sCapHeight value="0"/>
|
||||||
<usDefaultChar value="0"/>
|
<usDefaultChar value="0"/>
|
||||||
<usBreakChar value="32"/>
|
<usBreakChar value="32"/>
|
||||||
<usMaxContext value="2"/>
|
<usMaxContext value="0"/>
|
||||||
</OS_2>
|
</OS_2>
|
||||||
|
|
||||||
<hmtx>
|
<hmtx>
|
||||||
|
@ -119,7 +119,7 @@
|
|||||||
<sCapHeight value="0"/>
|
<sCapHeight value="0"/>
|
||||||
<usDefaultChar value="0"/>
|
<usDefaultChar value="0"/>
|
||||||
<usBreakChar value="32"/>
|
<usBreakChar value="32"/>
|
||||||
<usMaxContext value="2"/>
|
<usMaxContext value="0"/>
|
||||||
</OS_2>
|
</OS_2>
|
||||||
|
|
||||||
<hmtx>
|
<hmtx>
|
||||||
|
@ -117,6 +117,7 @@ def test_build_ttf(tmpdir):
|
|||||||
fb.setupHorizontalHeader(ascent=824, descent=200)
|
fb.setupHorizontalHeader(ascent=824, descent=200)
|
||||||
fb.setupNameTable(nameStrings)
|
fb.setupNameTable(nameStrings)
|
||||||
fb.setupOS2()
|
fb.setupOS2()
|
||||||
|
fb.addOpenTypeFeatures("feature salt { sub A by a; } salt;")
|
||||||
fb.setupPost()
|
fb.setupPost()
|
||||||
fb.setupDummyDSIG()
|
fb.setupDummyDSIG()
|
||||||
|
|
||||||
@ -145,6 +146,7 @@ def test_build_otf(tmpdir):
|
|||||||
fb.setupHorizontalHeader(ascent=824, descent=200)
|
fb.setupHorizontalHeader(ascent=824, descent=200)
|
||||||
fb.setupNameTable(nameStrings)
|
fb.setupNameTable(nameStrings)
|
||||||
fb.setupOS2()
|
fb.setupOS2()
|
||||||
|
fb.addOpenTypeFeatures("feature kern { pos A a -50; } kern;")
|
||||||
fb.setupPost()
|
fb.setupPost()
|
||||||
fb.setupDummyDSIG()
|
fb.setupDummyDSIG()
|
||||||
|
|
||||||
|
99
Tests/otlLib/data/gpos_91.ttx
Normal file
99
Tests/otlLib/data/gpos_91.ttx
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="3.40">
|
||||||
|
|
||||||
|
<GlyphOrder>
|
||||||
|
<!-- The 'id' attribute is only for humans; it is ignored when parsed. -->
|
||||||
|
<GlyphID id="0" name=".notdef"/>
|
||||||
|
<GlyphID id="1" name="A"/>
|
||||||
|
</GlyphOrder>
|
||||||
|
|
||||||
|
<maxp>
|
||||||
|
<!-- Most of this table will be recalculated by the compiler -->
|
||||||
|
<tableVersion value="0x10000"/>
|
||||||
|
<numGlyphs value="2"/>
|
||||||
|
<maxPoints value="0"/>
|
||||||
|
<maxContours value="0"/>
|
||||||
|
<maxCompositePoints value="0"/>
|
||||||
|
<maxCompositeContours value="0"/>
|
||||||
|
<maxZones value="2"/>
|
||||||
|
<maxTwilightPoints value="0"/>
|
||||||
|
<maxStorage value="0"/>
|
||||||
|
<maxFunctionDefs value="0"/>
|
||||||
|
<maxInstructionDefs value="0"/>
|
||||||
|
<maxStackElements value="0"/>
|
||||||
|
<maxSizeOfInstructions value="0"/>
|
||||||
|
<maxComponentElements value="0"/>
|
||||||
|
<maxComponentDepth value="0"/>
|
||||||
|
</maxp>
|
||||||
|
|
||||||
|
<post>
|
||||||
|
<formatType value="2.0"/>
|
||||||
|
<italicAngle value="0.0"/>
|
||||||
|
<underlinePosition value="0"/>
|
||||||
|
<underlineThickness value="0"/>
|
||||||
|
<isFixedPitch value="0"/>
|
||||||
|
<minMemType42 value="0"/>
|
||||||
|
<maxMemType42 value="0"/>
|
||||||
|
<minMemType1 value="0"/>
|
||||||
|
<maxMemType1 value="0"/>
|
||||||
|
<psNames>
|
||||||
|
<!-- This file uses unique glyph names based on the information
|
||||||
|
found in the 'post' table. Since these names might not be unique,
|
||||||
|
we have to invent artificial names in case of clashes. In order to
|
||||||
|
be able to retain the original information, we need a name to
|
||||||
|
ps name mapping for those cases where they differ. That's what
|
||||||
|
you see below.
|
||||||
|
-->
|
||||||
|
</psNames>
|
||||||
|
<extraNames>
|
||||||
|
<!-- following are the name that are not taken from the standard Mac glyph order -->
|
||||||
|
</extraNames>
|
||||||
|
</post>
|
||||||
|
|
||||||
|
<GPOS>
|
||||||
|
<Version value="0x00010000"/>
|
||||||
|
<ScriptList>
|
||||||
|
<!-- ScriptCount=1 -->
|
||||||
|
<ScriptRecord index="0">
|
||||||
|
<ScriptTag value="latn"/>
|
||||||
|
<Script>
|
||||||
|
<DefaultLangSys>
|
||||||
|
<ReqFeatureIndex value="65535"/>
|
||||||
|
<!-- FeatureCount=1 -->
|
||||||
|
<FeatureIndex index="0" value="0"/>
|
||||||
|
</DefaultLangSys>
|
||||||
|
<!-- LangSysCount=0 -->
|
||||||
|
</Script>
|
||||||
|
</ScriptRecord>
|
||||||
|
</ScriptList>
|
||||||
|
<FeatureList>
|
||||||
|
<!-- FeatureCount=1 -->
|
||||||
|
<FeatureRecord index="0">
|
||||||
|
<FeatureTag value="test"/>
|
||||||
|
<Feature>
|
||||||
|
<!-- LookupCount=1 -->
|
||||||
|
<LookupListIndex index="0" value="0"/>
|
||||||
|
</Feature>
|
||||||
|
</FeatureRecord>
|
||||||
|
</FeatureList>
|
||||||
|
<LookupList>
|
||||||
|
<!-- LookupCount=1 -->
|
||||||
|
<Lookup index="0">
|
||||||
|
<LookupType value="9"/>
|
||||||
|
<LookupFlag value="0"/>
|
||||||
|
<!-- SubTableCount=1 -->
|
||||||
|
<ExtensionPos index="0" Format="1">
|
||||||
|
<ExtensionLookupType value="1"/>
|
||||||
|
<SinglePos Format="1">
|
||||||
|
<Coverage Format="1">
|
||||||
|
<Glyph value="A"/>
|
||||||
|
</Coverage>
|
||||||
|
<ValueFormat value="4"/>
|
||||||
|
<Value XAdvance="20"/>
|
||||||
|
</SinglePos>
|
||||||
|
</ExtensionPos>
|
||||||
|
</Lookup>
|
||||||
|
</LookupList>
|
||||||
|
</GPOS>
|
||||||
|
|
||||||
|
</ttFont>
|
146
Tests/otlLib/data/gsub_51.ttx
Normal file
146
Tests/otlLib/data/gsub_51.ttx
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="3.40">
|
||||||
|
|
||||||
|
<GlyphOrder>
|
||||||
|
<!-- The 'id' attribute is only for humans; it is ignored when parsed. -->
|
||||||
|
<GlyphID id="0" name=".notdef"/>
|
||||||
|
<GlyphID id="1" name="g20"/>
|
||||||
|
<GlyphID id="2" name="g21"/>
|
||||||
|
<GlyphID id="3" name="g22"/>
|
||||||
|
<GlyphID id="4" name="g60"/>
|
||||||
|
<GlyphID id="5" name="g61"/>
|
||||||
|
<GlyphID id="6" name="g62"/>
|
||||||
|
<GlyphID id="7" name="g63"/>
|
||||||
|
</GlyphOrder>
|
||||||
|
|
||||||
|
<maxp>
|
||||||
|
<!-- Most of this table will be recalculated by the compiler -->
|
||||||
|
<tableVersion value="0x10000"/>
|
||||||
|
<numGlyphs value="8"/>
|
||||||
|
<maxPoints value="0"/>
|
||||||
|
<maxContours value="0"/>
|
||||||
|
<maxCompositePoints value="0"/>
|
||||||
|
<maxCompositeContours value="0"/>
|
||||||
|
<maxZones value="2"/>
|
||||||
|
<maxTwilightPoints value="0"/>
|
||||||
|
<maxStorage value="0"/>
|
||||||
|
<maxFunctionDefs value="0"/>
|
||||||
|
<maxInstructionDefs value="0"/>
|
||||||
|
<maxStackElements value="0"/>
|
||||||
|
<maxSizeOfInstructions value="0"/>
|
||||||
|
<maxComponentElements value="0"/>
|
||||||
|
<maxComponentDepth value="0"/>
|
||||||
|
</maxp>
|
||||||
|
|
||||||
|
<post>
|
||||||
|
<formatType value="2.0"/>
|
||||||
|
<italicAngle value="0.0"/>
|
||||||
|
<underlinePosition value="0"/>
|
||||||
|
<underlineThickness value="0"/>
|
||||||
|
<isFixedPitch value="0"/>
|
||||||
|
<minMemType42 value="0"/>
|
||||||
|
<maxMemType42 value="0"/>
|
||||||
|
<minMemType1 value="0"/>
|
||||||
|
<maxMemType1 value="0"/>
|
||||||
|
<psNames>
|
||||||
|
<!-- This file uses unique glyph names based on the information
|
||||||
|
found in the 'post' table. Since these names might not be unique,
|
||||||
|
we have to invent artificial names in case of clashes. In order to
|
||||||
|
be able to retain the original information, we need a name to
|
||||||
|
ps name mapping for those cases where they differ. That's what
|
||||||
|
you see below.
|
||||||
|
-->
|
||||||
|
</psNames>
|
||||||
|
<extraNames>
|
||||||
|
<!-- following are the name that are not taken from the standard Mac glyph order -->
|
||||||
|
</extraNames>
|
||||||
|
</post>
|
||||||
|
|
||||||
|
<GSUB>
|
||||||
|
<Version value="0x00010000"/>
|
||||||
|
<ScriptList>
|
||||||
|
<!-- ScriptCount=1 -->
|
||||||
|
<ScriptRecord index="0">
|
||||||
|
<ScriptTag value="latn"/>
|
||||||
|
<Script>
|
||||||
|
<DefaultLangSys>
|
||||||
|
<ReqFeatureIndex value="65535"/>
|
||||||
|
<!-- FeatureCount=1 -->
|
||||||
|
<FeatureIndex index="0" value="0"/>
|
||||||
|
</DefaultLangSys>
|
||||||
|
<!-- LangSysCount=0 -->
|
||||||
|
</Script>
|
||||||
|
</ScriptRecord>
|
||||||
|
</ScriptList>
|
||||||
|
<FeatureList>
|
||||||
|
<!-- FeatureCount=1 -->
|
||||||
|
<FeatureRecord index="0">
|
||||||
|
<FeatureTag value="test"/>
|
||||||
|
<Feature>
|
||||||
|
<!-- LookupCount=1 -->
|
||||||
|
<LookupListIndex index="0" value="4"/>
|
||||||
|
</Feature>
|
||||||
|
</FeatureRecord>
|
||||||
|
</FeatureList>
|
||||||
|
<LookupList>
|
||||||
|
<!-- LookupCount=5 -->
|
||||||
|
<Lookup index="0">
|
||||||
|
<LookupType value="1"/>
|
||||||
|
<LookupFlag value="0"/>
|
||||||
|
<!-- SubTableCount=1 -->
|
||||||
|
<SingleSubst index="0" Format="1">
|
||||||
|
<Substitution in="g20" out="g60"/>
|
||||||
|
<Substitution in="g21" out="g61"/>
|
||||||
|
</SingleSubst>
|
||||||
|
</Lookup>
|
||||||
|
<Lookup index="1">
|
||||||
|
<LookupType value="4"/>
|
||||||
|
<LookupFlag value="0"/>
|
||||||
|
<!-- SubTableCount=1 -->
|
||||||
|
<LigatureSubst index="0" Format="1">
|
||||||
|
<LigatureSet glyph="g21">
|
||||||
|
<Ligature components="g22" glyph="g61"/>
|
||||||
|
</LigatureSet>
|
||||||
|
</LigatureSubst>
|
||||||
|
</Lookup>
|
||||||
|
<Lookup index="2">
|
||||||
|
<LookupType value="4"/>
|
||||||
|
<LookupFlag value="8"/>
|
||||||
|
<!-- SubTableCount=1 -->
|
||||||
|
<LigatureSubst index="0" Format="1">
|
||||||
|
<LigatureSet glyph="g21">
|
||||||
|
<Ligature components="g22" glyph="g61"/>
|
||||||
|
</LigatureSet>
|
||||||
|
</LigatureSubst>
|
||||||
|
</Lookup>
|
||||||
|
<Lookup index="3">
|
||||||
|
<LookupType value="2"/>
|
||||||
|
<LookupFlag value="0"/>
|
||||||
|
<!-- SubTableCount=1 -->
|
||||||
|
<MultipleSubst index="0" Format="1">
|
||||||
|
<Substitution in="g21" out="g61,g62,g63"/>
|
||||||
|
</MultipleSubst>
|
||||||
|
</Lookup>
|
||||||
|
<Lookup index="4">
|
||||||
|
<LookupType value="5"/>
|
||||||
|
<LookupFlag value="0"/>
|
||||||
|
<!-- SubTableCount=1 -->
|
||||||
|
<ContextSubst index="0" Format="1">
|
||||||
|
<Coverage Format="1">
|
||||||
|
<Glyph value="g20"/>
|
||||||
|
</Coverage>
|
||||||
|
<!-- SubRuleSetCount=1 -->
|
||||||
|
<SubRuleSet index="0">
|
||||||
|
<!-- SubRuleCount=1 -->
|
||||||
|
<SubRule index="0">
|
||||||
|
<!-- GlyphCount=2 -->
|
||||||
|
<!-- SubstCount=0 -->
|
||||||
|
<Input index="0" value="g20"/>
|
||||||
|
</SubRule>
|
||||||
|
</SubRuleSet>
|
||||||
|
</ContextSubst>
|
||||||
|
</Lookup>
|
||||||
|
</LookupList>
|
||||||
|
</GSUB>
|
||||||
|
|
||||||
|
</ttFont>
|
150
Tests/otlLib/data/gsub_52.ttx
Normal file
150
Tests/otlLib/data/gsub_52.ttx
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="3.40">
|
||||||
|
|
||||||
|
<GlyphOrder>
|
||||||
|
<!-- The 'id' attribute is only for humans; it is ignored when parsed. -->
|
||||||
|
<GlyphID id="0" name=".notdef"/>
|
||||||
|
<GlyphID id="1" name="g20"/>
|
||||||
|
<GlyphID id="2" name="g21"/>
|
||||||
|
<GlyphID id="3" name="g22"/>
|
||||||
|
<GlyphID id="4" name="g60"/>
|
||||||
|
<GlyphID id="5" name="g61"/>
|
||||||
|
<GlyphID id="6" name="g62"/>
|
||||||
|
<GlyphID id="7" name="g63"/>
|
||||||
|
</GlyphOrder>
|
||||||
|
|
||||||
|
<maxp>
|
||||||
|
<!-- Most of this table will be recalculated by the compiler -->
|
||||||
|
<tableVersion value="0x10000"/>
|
||||||
|
<numGlyphs value="8"/>
|
||||||
|
<maxPoints value="0"/>
|
||||||
|
<maxContours value="0"/>
|
||||||
|
<maxCompositePoints value="0"/>
|
||||||
|
<maxCompositeContours value="0"/>
|
||||||
|
<maxZones value="2"/>
|
||||||
|
<maxTwilightPoints value="0"/>
|
||||||
|
<maxStorage value="0"/>
|
||||||
|
<maxFunctionDefs value="0"/>
|
||||||
|
<maxInstructionDefs value="0"/>
|
||||||
|
<maxStackElements value="0"/>
|
||||||
|
<maxSizeOfInstructions value="0"/>
|
||||||
|
<maxComponentElements value="0"/>
|
||||||
|
<maxComponentDepth value="0"/>
|
||||||
|
</maxp>
|
||||||
|
|
||||||
|
<post>
|
||||||
|
<formatType value="2.0"/>
|
||||||
|
<italicAngle value="0.0"/>
|
||||||
|
<underlinePosition value="0"/>
|
||||||
|
<underlineThickness value="0"/>
|
||||||
|
<isFixedPitch value="0"/>
|
||||||
|
<minMemType42 value="0"/>
|
||||||
|
<maxMemType42 value="0"/>
|
||||||
|
<minMemType1 value="0"/>
|
||||||
|
<maxMemType1 value="0"/>
|
||||||
|
<psNames>
|
||||||
|
<!-- This file uses unique glyph names based on the information
|
||||||
|
found in the 'post' table. Since these names might not be unique,
|
||||||
|
we have to invent artificial names in case of clashes. In order to
|
||||||
|
be able to retain the original information, we need a name to
|
||||||
|
ps name mapping for those cases where they differ. That's what
|
||||||
|
you see below.
|
||||||
|
-->
|
||||||
|
</psNames>
|
||||||
|
<extraNames>
|
||||||
|
<!-- following are the name that are not taken from the standard Mac glyph order -->
|
||||||
|
</extraNames>
|
||||||
|
</post>
|
||||||
|
|
||||||
|
<GSUB>
|
||||||
|
<Version value="0x00010000"/>
|
||||||
|
<ScriptList>
|
||||||
|
<!-- ScriptCount=1 -->
|
||||||
|
<ScriptRecord index="0">
|
||||||
|
<ScriptTag value="latn"/>
|
||||||
|
<Script>
|
||||||
|
<DefaultLangSys>
|
||||||
|
<ReqFeatureIndex value="65535"/>
|
||||||
|
<!-- FeatureCount=1 -->
|
||||||
|
<FeatureIndex index="0" value="0"/>
|
||||||
|
</DefaultLangSys>
|
||||||
|
<!-- LangSysCount=0 -->
|
||||||
|
</Script>
|
||||||
|
</ScriptRecord>
|
||||||
|
</ScriptList>
|
||||||
|
<FeatureList>
|
||||||
|
<!-- FeatureCount=1 -->
|
||||||
|
<FeatureRecord index="0">
|
||||||
|
<FeatureTag value="test"/>
|
||||||
|
<Feature>
|
||||||
|
<!-- LookupCount=1 -->
|
||||||
|
<LookupListIndex index="0" value="4"/>
|
||||||
|
</Feature>
|
||||||
|
</FeatureRecord>
|
||||||
|
</FeatureList>
|
||||||
|
<LookupList>
|
||||||
|
<!-- LookupCount=5 -->
|
||||||
|
<Lookup index="0">
|
||||||
|
<LookupType value="1"/>
|
||||||
|
<LookupFlag value="0"/>
|
||||||
|
<!-- SubTableCount=1 -->
|
||||||
|
<SingleSubst index="0" Format="1">
|
||||||
|
<Substitution in="g20" out="g60"/>
|
||||||
|
<Substitution in="g21" out="g61"/>
|
||||||
|
</SingleSubst>
|
||||||
|
</Lookup>
|
||||||
|
<Lookup index="1">
|
||||||
|
<LookupType value="4"/>
|
||||||
|
<LookupFlag value="0"/>
|
||||||
|
<!-- SubTableCount=1 -->
|
||||||
|
<LigatureSubst index="0" Format="1">
|
||||||
|
<LigatureSet glyph="g21">
|
||||||
|
<Ligature components="g22" glyph="g61"/>
|
||||||
|
</LigatureSet>
|
||||||
|
</LigatureSubst>
|
||||||
|
</Lookup>
|
||||||
|
<Lookup index="2">
|
||||||
|
<LookupType value="4"/>
|
||||||
|
<LookupFlag value="8"/>
|
||||||
|
<!-- SubTableCount=1 -->
|
||||||
|
<LigatureSubst index="0" Format="1">
|
||||||
|
<LigatureSet glyph="g21">
|
||||||
|
<Ligature components="g22" glyph="g61"/>
|
||||||
|
</LigatureSet>
|
||||||
|
</LigatureSubst>
|
||||||
|
</Lookup>
|
||||||
|
<Lookup index="3">
|
||||||
|
<LookupType value="2"/>
|
||||||
|
<LookupFlag value="0"/>
|
||||||
|
<!-- SubTableCount=1 -->
|
||||||
|
<MultipleSubst index="0" Format="1">
|
||||||
|
<Substitution in="g21" out="g61,g62,g63"/>
|
||||||
|
</MultipleSubst>
|
||||||
|
</Lookup>
|
||||||
|
<Lookup index="4">
|
||||||
|
<LookupType value="5"/>
|
||||||
|
<LookupFlag value="0"/>
|
||||||
|
<!-- SubTableCount=1 -->
|
||||||
|
<ContextSubst index="0" Format="2">
|
||||||
|
<Coverage Format="1">
|
||||||
|
<Glyph value="g20"/>
|
||||||
|
</Coverage>
|
||||||
|
<ClassDef Format="2">
|
||||||
|
<ClassDef glyph="g20" class="1"/>
|
||||||
|
</ClassDef>
|
||||||
|
<!-- SubClassSetCount=2 -->
|
||||||
|
<SubClassSet index="0" empty="1"/>
|
||||||
|
<SubClassSet index="1">
|
||||||
|
<!-- SubClassRuleCount=1 -->
|
||||||
|
<SubClassRule index="0">
|
||||||
|
<!-- GlyphCount=2 -->
|
||||||
|
<!-- SubstCount=0 -->
|
||||||
|
<Class index="0" value="1"/>
|
||||||
|
</SubClassRule>
|
||||||
|
</SubClassSet>
|
||||||
|
</ContextSubst>
|
||||||
|
</Lookup>
|
||||||
|
</LookupList>
|
||||||
|
</GSUB>
|
||||||
|
|
||||||
|
</ttFont>
|
99
Tests/otlLib/data/gsub_71.ttx
Normal file
99
Tests/otlLib/data/gsub_71.ttx
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="3.40">
|
||||||
|
|
||||||
|
<GlyphOrder>
|
||||||
|
<!-- The 'id' attribute is only for humans; it is ignored when parsed. -->
|
||||||
|
<GlyphID id="0" name=".notdef"/>
|
||||||
|
<GlyphID id="1" name="g18"/>
|
||||||
|
<GlyphID id="2" name="g19"/>
|
||||||
|
<GlyphID id="3" name="g23"/>
|
||||||
|
<GlyphID id="4" name="g24"/>
|
||||||
|
</GlyphOrder>
|
||||||
|
|
||||||
|
<maxp>
|
||||||
|
<!-- Most of this table will be recalculated by the compiler -->
|
||||||
|
<tableVersion value="0x10000"/>
|
||||||
|
<numGlyphs value="5"/>
|
||||||
|
<maxPoints value="0"/>
|
||||||
|
<maxContours value="0"/>
|
||||||
|
<maxCompositePoints value="0"/>
|
||||||
|
<maxCompositeContours value="0"/>
|
||||||
|
<maxZones value="2"/>
|
||||||
|
<maxTwilightPoints value="0"/>
|
||||||
|
<maxStorage value="0"/>
|
||||||
|
<maxFunctionDefs value="0"/>
|
||||||
|
<maxInstructionDefs value="0"/>
|
||||||
|
<maxStackElements value="0"/>
|
||||||
|
<maxSizeOfInstructions value="0"/>
|
||||||
|
<maxComponentElements value="0"/>
|
||||||
|
<maxComponentDepth value="0"/>
|
||||||
|
</maxp>
|
||||||
|
|
||||||
|
<post>
|
||||||
|
<formatType value="2.0"/>
|
||||||
|
<italicAngle value="0.0"/>
|
||||||
|
<underlinePosition value="0"/>
|
||||||
|
<underlineThickness value="0"/>
|
||||||
|
<isFixedPitch value="0"/>
|
||||||
|
<minMemType42 value="0"/>
|
||||||
|
<maxMemType42 value="0"/>
|
||||||
|
<minMemType1 value="0"/>
|
||||||
|
<maxMemType1 value="0"/>
|
||||||
|
<psNames>
|
||||||
|
<!-- This file uses unique glyph names based on the information
|
||||||
|
found in the 'post' table. Since these names might not be unique,
|
||||||
|
we have to invent artificial names in case of clashes. In order to
|
||||||
|
be able to retain the original information, we need a name to
|
||||||
|
ps name mapping for those cases where they differ. That's what
|
||||||
|
you see below.
|
||||||
|
-->
|
||||||
|
</psNames>
|
||||||
|
<extraNames>
|
||||||
|
<!-- following are the name that are not taken from the standard Mac glyph order -->
|
||||||
|
</extraNames>
|
||||||
|
</post>
|
||||||
|
|
||||||
|
<GSUB>
|
||||||
|
<Version value="0x00010000"/>
|
||||||
|
<ScriptList>
|
||||||
|
<!-- ScriptCount=1 -->
|
||||||
|
<ScriptRecord index="0">
|
||||||
|
<ScriptTag value="latn"/>
|
||||||
|
<Script>
|
||||||
|
<DefaultLangSys>
|
||||||
|
<ReqFeatureIndex value="65535"/>
|
||||||
|
<!-- FeatureCount=1 -->
|
||||||
|
<FeatureIndex index="0" value="0"/>
|
||||||
|
</DefaultLangSys>
|
||||||
|
<!-- LangSysCount=0 -->
|
||||||
|
</Script>
|
||||||
|
</ScriptRecord>
|
||||||
|
</ScriptList>
|
||||||
|
<FeatureList>
|
||||||
|
<!-- FeatureCount=1 -->
|
||||||
|
<FeatureRecord index="0">
|
||||||
|
<FeatureTag value="test"/>
|
||||||
|
<Feature>
|
||||||
|
<!-- LookupCount=1 -->
|
||||||
|
<LookupListIndex index="0" value="0"/>
|
||||||
|
</Feature>
|
||||||
|
</FeatureRecord>
|
||||||
|
</FeatureList>
|
||||||
|
<LookupList>
|
||||||
|
<!-- LookupCount=1 -->
|
||||||
|
<Lookup index="0">
|
||||||
|
<LookupType value="7"/>
|
||||||
|
<LookupFlag value="0"/>
|
||||||
|
<!-- SubTableCount=1 -->
|
||||||
|
<ExtensionSubst index="0" Format="1">
|
||||||
|
<ExtensionLookupType value="1"/>
|
||||||
|
<SingleSubst Format="1">
|
||||||
|
<Substitution in="g18" out="g23"/>
|
||||||
|
<Substitution in="g19" out="g24"/>
|
||||||
|
</SingleSubst>
|
||||||
|
</ExtensionSubst>
|
||||||
|
</Lookup>
|
||||||
|
</LookupList>
|
||||||
|
</GSUB>
|
||||||
|
|
||||||
|
</ttFont>
|
76
Tests/otlLib/maxContextCalc_test.py
Normal file
76
Tests/otlLib/maxContextCalc_test.py
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
from __future__ import print_function, division, absolute_import
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import os
|
||||||
|
import pytest
|
||||||
|
from fontTools.ttLib import TTFont
|
||||||
|
from fontTools.otlLib.maxContextCalc import maxCtxFont
|
||||||
|
from fontTools.feaLib.builder import addOpenTypeFeaturesFromString
|
||||||
|
|
||||||
|
|
||||||
|
def test_max_ctx_calc_no_features():
|
||||||
|
font = TTFont()
|
||||||
|
assert maxCtxFont(font) == 0
|
||||||
|
font.setGlyphOrder(['.notdef'])
|
||||||
|
addOpenTypeFeaturesFromString(font, '')
|
||||||
|
assert maxCtxFont(font) == 0
|
||||||
|
|
||||||
|
|
||||||
|
def test_max_ctx_calc_features():
|
||||||
|
glyphs = '.notdef space A B C a b c'.split()
|
||||||
|
features = """
|
||||||
|
lookup GSUB_EXT useExtension {
|
||||||
|
sub a by b;
|
||||||
|
} GSUB_EXT;
|
||||||
|
|
||||||
|
lookup GPOS_EXT useExtension {
|
||||||
|
pos a b -10;
|
||||||
|
} GPOS_EXT;
|
||||||
|
|
||||||
|
feature sub1 {
|
||||||
|
sub A by a;
|
||||||
|
sub A B by b;
|
||||||
|
sub A B C by c;
|
||||||
|
sub [A B] C by c;
|
||||||
|
sub [A B] C [A B] by c;
|
||||||
|
sub A by A B;
|
||||||
|
sub A' C by A B;
|
||||||
|
sub a' by b;
|
||||||
|
sub a' b by c;
|
||||||
|
sub a from [A B C];
|
||||||
|
rsub a by b;
|
||||||
|
rsub a' by b;
|
||||||
|
rsub a b' by c;
|
||||||
|
rsub a b' c by A;
|
||||||
|
rsub [a b] c' by A;
|
||||||
|
rsub [a b] c' [a b] by B;
|
||||||
|
lookup GSUB_EXT;
|
||||||
|
} sub1;
|
||||||
|
|
||||||
|
feature pos1 {
|
||||||
|
pos A 20;
|
||||||
|
pos A B -50;
|
||||||
|
pos A B' 10 C;
|
||||||
|
lookup GPOS_EXT;
|
||||||
|
} pos1;
|
||||||
|
"""
|
||||||
|
font = TTFont()
|
||||||
|
font.setGlyphOrder(glyphs)
|
||||||
|
addOpenTypeFeaturesFromString(font, features)
|
||||||
|
|
||||||
|
assert maxCtxFont(font) == 3
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('file_name, max_context', [
|
||||||
|
('gsub_51', 2),
|
||||||
|
('gsub_52', 2),
|
||||||
|
('gsub_71', 1),
|
||||||
|
('gpos_91', 1),
|
||||||
|
])
|
||||||
|
def test_max_ctx_calc_features_ttx(file_name, max_context):
|
||||||
|
ttx_path = os.path.join(os.path.dirname(__file__),
|
||||||
|
'data', '{}.ttx'.format(file_name))
|
||||||
|
font = TTFont()
|
||||||
|
font.importXML(ttx_path)
|
||||||
|
|
||||||
|
assert maxCtxFont(font) == max_context
|
@ -485,6 +485,24 @@ class SubsetTest(unittest.TestCase):
|
|||||||
subset.main([fontpath, "--recalc-timestamp", "--output-file=%s" % subsetpath, "*"])
|
subset.main([fontpath, "--recalc-timestamp", "--output-file=%s" % subsetpath, "*"])
|
||||||
self.assertLess(modified, TTFont(subsetpath)['head'].modified)
|
self.assertLess(modified, TTFont(subsetpath)['head'].modified)
|
||||||
|
|
||||||
|
def test_recalc_max_context(self):
|
||||||
|
ttxpath = self.getpath("Lobster.subset.ttx")
|
||||||
|
font = TTFont()
|
||||||
|
font.importXML(ttxpath)
|
||||||
|
max_context = font['OS/2'].usMaxContext
|
||||||
|
_, fontpath = self.compile_font(ttxpath, ".otf")
|
||||||
|
subsetpath = self.temp_path(".otf")
|
||||||
|
|
||||||
|
# by default, the subsetter does not recalculate the usMaxContext
|
||||||
|
subset.main([fontpath, "--drop-tables+=GSUB,GPOS",
|
||||||
|
"--output-file=%s" % subsetpath])
|
||||||
|
self.assertEqual(max_context, TTFont(subsetpath)['OS/2'].usMaxContext)
|
||||||
|
|
||||||
|
subset.main([fontpath, "--recalc-max-context",
|
||||||
|
"--drop-tables+=GSUB,GPOS",
|
||||||
|
"--output-file=%s" % subsetpath])
|
||||||
|
self.assertEqual(0, TTFont(subsetpath)['OS/2'].usMaxContext)
|
||||||
|
|
||||||
def test_retain_gids_ttf(self):
|
def test_retain_gids_ttf(self):
|
||||||
_, fontpath = self.compile_font(self.getpath("TestTTF-Regular.ttx"), ".ttf")
|
_, fontpath = self.compile_font(self.getpath("TestTTF-Regular.ttx"), ".ttf")
|
||||||
font = TTFont(fontpath)
|
font = TTFont(fontpath)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user