Support subsetting of variation fonts

This commit is contained in:
Sascha Brawer 2016-03-31 16:23:24 +02:00
parent d8004de04c
commit 0fad6e66ec
5 changed files with 1063 additions and 19 deletions

View File

@ -1450,7 +1450,7 @@ def prune_features(self):
@_add_method(ttLib.getTableClass('GSUB'),
ttLib.getTableClass('GPOS'))
def prune_pre_subset(self, options):
def prune_pre_subset(self, font, options):
# Drop undesired features
if '*' not in options.layout_features:
self.subset_feature_tags(options.layout_features)
@ -1584,7 +1584,7 @@ def prune_post_subset(self, options):
(table.Version >= 0x00010002/0x10000 and table.MarkGlyphSetsDef))
@_add_method(ttLib.getTableClass('kern'))
def prune_pre_subset(self, options):
def prune_pre_subset(self, font, options):
# Prune unknown kern table types
self.kernTables = [t for t in self.kernTables if hasattr(t, 'kernTable')]
return bool(self.kernTables)
@ -1613,6 +1613,22 @@ def subset_glyphs(self, s):
self.hdmx = {sz:_dict_subset(l, s.glyphs) for sz,l in self.hdmx.items()}
return bool(self.hdmx)
@_add_method(ttLib.getTableClass('avar'), ttLib.getTableClass('fvar'))
def subset_glyphs(self, s):
return True
@_add_method(ttLib.getTableClass('gvar'))
def prune_pre_subset(self, font, options):
if options.notdef_glyph and not options.notdef_outline:
self.variations[font.glyphOrder[0]] = []
return True
@_add_method(ttLib.getTableClass('gvar'))
def subset_glyphs(self, s):
self.variations = _dict_subset(self.variations, s.glyphs)
self.glyphCount = len(self.variations)
return bool(self.variations)
@_add_method(ttLib.getTableClass('VORG'))
def subset_glyphs(self, s):
self.VOriginRecords = {g:v for g,v in self.VOriginRecords.items()
@ -1621,7 +1637,7 @@ def subset_glyphs(self, s):
return True # Never drop; has default metrics
@_add_method(ttLib.getTableClass('post'))
def prune_pre_subset(self, options):
def prune_pre_subset(self, font, options):
if not options.glyph_names:
self.formatType = 3.0
return True # Required table
@ -1784,7 +1800,7 @@ def closure_glyphs(self, s):
s.glyphs.update(components)
@_add_method(ttLib.getTableClass('glyf'))
def prune_pre_subset(self, options):
def prune_pre_subset(self, font, options):
if options.notdef_glyph and not options.notdef_outline:
g = self[self.glyphOrder[0]]
# Yay, easy!
@ -1813,7 +1829,7 @@ def prune_post_subset(self, options):
return True
@_add_method(ttLib.getTableClass('CFF '))
def prune_pre_subset(self, options):
def prune_pre_subset(self, font, options):
cff = self.cff
# CFF table must have one font only
cff.fontNames = cff.fontNames[:1]
@ -2278,7 +2294,7 @@ def closure_glyphs(self, s):
s.unicodes_missing.difference_update(table.cmap)
@_add_method(ttLib.getTableClass('cmap'))
def prune_pre_subset(self, options):
def prune_pre_subset(self, font, options):
if not options.legacy_cmap:
# Drop non-Unicode / non-Symbol cmaps
self.tables = [t for t in self.tables if t.isUnicode() or t.isSymbol()]
@ -2318,14 +2334,14 @@ def subset_glyphs(self, s):
return True # Required table
@_add_method(ttLib.getTableClass('DSIG'))
def prune_pre_subset(self, options):
def prune_pre_subset(self, font, options):
# Drop all signatures since they will be invalid
self.usNumSigs = 0
self.signatureRecords = []
return True
@_add_method(ttLib.getTableClass('maxp'))
def prune_pre_subset(self, options):
def prune_pre_subset(self, font, options):
if not options.hinting:
if self.tableVersion == 0x00010000:
self.maxZones = 1
@ -2337,9 +2353,14 @@ def prune_pre_subset(self, options):
return True
@_add_method(ttLib.getTableClass('name'))
def prune_pre_subset(self, options):
def prune_pre_subset(self, font, options):
nameIDs = set(options.name_IDs)
fvar = font.get('fvar')
if fvar:
nameIDs.update([inst.nameID for inst in fvar.instances])
nameIDs.update([axis.nameID for axis in fvar.axes])
if '*' not in options.name_IDs:
self.names = [n for n in self.names if n.nameID in options.name_IDs]
self.names = [n for n in self.names if n.nameID in nameIDs]
if not options.name_legacy:
# TODO(behdad) Sometimes (eg Apple Color Emoji) there's only a macroman
# entry for Latin and no Unicode names.
@ -2391,7 +2412,7 @@ class Options(object):
_no_subset_tables_default = ['gasp', 'head', 'hhea', 'maxp',
'vhea', 'OS/2', 'loca', 'name', 'cvt',
'fpgm', 'prep', 'VDMX', 'DSIG', 'CPAL']
_hinting_tables_default = ['cvt', 'fpgm', 'prep', 'hdmx', 'VDMX']
_hinting_tables_default = ['cvar', 'cvt', 'fpgm', 'prep', 'hdmx', 'VDMX']
# Based on HarfBuzz shapers
_layout_features_groups = {
@ -2553,10 +2574,7 @@ class Subsetter(object):
self.glyph_ids_requested.update(gids)
def _prune_pre_subset(self, font):
for tag in font.keys():
if tag == 'GlyphOrder': continue
for tag in self._sort_tables(font):
if(tag.strip() in self.options.drop_tables or
(tag.strip() in self.options.hinting_tables and not self.options.hinting) or
(tag == 'kern' and (not self.options.legacy_kern and 'GPOS' in font))):
@ -2570,7 +2588,7 @@ class Subsetter(object):
with timer("load '%s'" % tag):
table = font[tag]
with timer("prune '%s'" % tag):
retain = table.prune_pre_subset(self.options)
retain = table.prune_pre_subset(font, self.options)
if not retain:
log.info("%s pruned to empty; dropped", tag)
del font[tag]
@ -2681,8 +2699,7 @@ class Subsetter(object):
del self.glyphs
def _subset_glyphs(self, font):
for tag in font.keys():
if tag == 'GlyphOrder': continue
for tag in self._sort_tables(font):
clazz = ttLib.getTableClass(tag)
if tag.strip() in self.options.no_subset_tables:
@ -2727,8 +2744,13 @@ class Subsetter(object):
else:
log.info("%s pruned", tag)
def subset(self, font):
def _sort_tables(self, font):
tagOrder = ['fvar', 'avar', 'gvar', 'name', 'glyf']
tagOrder = {t: i + 1 for i, t in enumerate(tagOrder)}
tags = sorted(font.keys(), key=lambda tag: tagOrder.get(tag, 0))
return [t for t in tags if t != 'GlyphOrder']
def subset(self, font):
self._prune_pre_subset(font)
self._closure_glyphs(font)
self._subset_glyphs(font)

View File

@ -100,6 +100,20 @@ class SubsetTest(unittest.TestCase):
subsetfont = TTFont(subsetpath)
self.expect_ttx(subsetfont, self.getpath("expect_keep_colr.ttx"), ["GlyphOrder", "hmtx", "glyf", "COLR", "CPAL"])
def test_subset_gvar(self):
_, fontpath = self.compile_font(self.getpath("TestGVAR.ttx"), ".ttf")
subsetpath = self.temp_path(".ttf")
subset.main([fontpath, "--unicodes=U+002B,U+2212", "--output-file=%s" % subsetpath])
subsetfont = TTFont(subsetpath)
self.expect_ttx(subsetfont, self.getpath("expect_keep_gvar.ttx"), ["GlyphOrder", "avar", "fvar", "gvar", "name"])
def test_subset_gvar_notdef_outline(self):
_, fontpath = self.compile_font(self.getpath("TestGVAR.ttx"), ".ttf")
subsetpath = self.temp_path(".ttf")
subset.main([fontpath, "--unicodes=U+0030", "--notdef_outline", "--output-file=%s" % subsetpath])
subsetfont = TTFont(subsetpath)
self.expect_ttx(subsetfont, self.getpath("expect_keep_gvar_notdef_outline.ttx"), ["GlyphOrder", "avar", "fvar", "gvar", "name"])
def test_subset_math(self):
_, fontpath = self.compile_font(self.getpath("TestMATH-Regular.ttx"), ".ttf")
subsetpath = self.temp_path(".ttf")

View File

@ -0,0 +1,655 @@
<?xml version="1.0" encoding="UTF-8"?>
<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="3.0">
<GlyphOrder>
<!-- The 'id' attribute is only for humans; it is ignored when parsed. -->
<GlyphID id="0" name=".notdef"/>
<GlyphID id="1" name="space"/>
<GlyphID id="2" name="zero"/>
<GlyphID id="3" name="equal"/>
<GlyphID id="4" name="minus"/>
<GlyphID id="5" name="plus"/>
</GlyphOrder>
<head>
<!-- Most of this table will be recalculated by the compiler -->
<tableVersion value="1.0"/>
<fontRevision value="1.0"/>
<checkSumAdjustment value="0xf1c8c54f"/>
<magicNumber value="0x5f0f3cf5"/>
<flags value="00000000 00000011"/>
<unitsPerEm value="1000"/>
<created value="Thu Mar 31 07:56:22 2016"/>
<modified value="Thu Mar 31 11:16:24 2016"/>
<xMin value="40"/>
<yMin value="-10"/>
<xMax value="620"/>
<yMax value="710"/>
<macStyle value="00000000 00000000"/>
<lowestRecPPEM value="7"/>
<fontDirectionHint value="2"/>
<indexToLocFormat value="0"/>
<glyphDataFormat value="0"/>
</head>
<hhea>
<tableVersion value="1.0"/>
<ascent value="1000"/>
<descent value="-200"/>
<lineGap value="0"/>
<advanceWidthMax value="700"/>
<minLeftSideBearing value="40"/>
<minRightSideBearing value="40"/>
<xMaxExtent value="620"/>
<caretSlopeRise value="1"/>
<caretSlopeRun value="0"/>
<caretOffset value="0"/>
<reserved0 value="0"/>
<reserved1 value="0"/>
<reserved2 value="0"/>
<reserved3 value="0"/>
<metricDataFormat value="0"/>
<numberOfHMetrics value="4"/>
</hhea>
<maxp>
<!-- Most of this table will be recalculated by the compiler -->
<tableVersion value="0x10000"/>
<numGlyphs value="6"/>
<maxPoints value="32"/>
<maxContours value="2"/>
<maxCompositePoints value="0"/>
<maxCompositeContours value="0"/>
<maxZones value="1"/>
<maxTwilightPoints value="0"/>
<maxStorage value="0"/>
<maxFunctionDefs value="1"/>
<maxInstructionDefs value="0"/>
<maxStackElements value="0"/>
<maxSizeOfInstructions value="0"/>
<maxComponentElements value="0"/>
<maxComponentDepth value="0"/>
</maxp>
<OS_2>
<!-- The fields 'usFirstCharIndex' and 'usLastCharIndex'
will be recalculated by the compiler -->
<version value="3"/>
<xAvgCharWidth value="606"/>
<usWeightClass value="400"/>
<usWidthClass value="5"/>
<fsType value="00000000 00001000"/>
<ySubscriptXSize value="650"/>
<ySubscriptYSize value="600"/>
<ySubscriptXOffset value="0"/>
<ySubscriptYOffset value="75"/>
<ySuperscriptXSize value="650"/>
<ySuperscriptYSize value="600"/>
<ySuperscriptXOffset value="0"/>
<ySuperscriptYOffset value="350"/>
<yStrikeoutSize value="50"/>
<yStrikeoutPosition value="300"/>
<sFamilyClass value="0"/>
<panose>
<bFamilyType value="0"/>
<bSerifStyle value="0"/>
<bWeight value="5"/>
<bProportion value="0"/>
<bContrast value="0"/>
<bStrokeVariation value="0"/>
<bArmStyle value="0"/>
<bLetterForm value="0"/>
<bMidline value="0"/>
<bXHeight value="0"/>
</panose>
<ulUnicodeRange1 value="00000000 00000000 00000000 00000001"/>
<ulUnicodeRange2 value="00000000 00000000 00000000 00000000"/>
<ulUnicodeRange3 value="00000000 00000000 00000000 00000000"/>
<ulUnicodeRange4 value="00000000 00000000 00000000 00000000"/>
<achVendID value="UKWN"/>
<fsSelection value="00000000 01000000"/>
<usFirstCharIndex value="32"/>
<usLastCharIndex value="8722"/>
<sTypoAscender value="800"/>
<sTypoDescender value="-200"/>
<sTypoLineGap value="200"/>
<usWinAscent value="1000"/>
<usWinDescent value="200"/>
<ulCodePageRange1 value="00000000 00000000 00000000 00000001"/>
<ulCodePageRange2 value="00000000 00000000 00000000 00000000"/>
<sxHeight value="500"/>
<sCapHeight value="700"/>
<usDefaultChar value="0"/>
<usBreakChar value="32"/>
<usMaxContext value="0"/>
</OS_2>
<hmtx>
<mtx name=".notdef" width="700" lsb="80"/>
<mtx name="equal" width="660" lsb="80"/>
<mtx name="minus" width="660" lsb="80"/>
<mtx name="plus" width="660" lsb="80"/>
<mtx name="space" width="700" lsb="0"/>
<mtx name="zero" width="625" lsb="40"/>
</hmtx>
<cmap>
<tableVersion version="0"/>
<cmap_format_4 platformID="0" platEncID="3" language="0">
<map code="0x20" name="space"/><!-- SPACE -->
<map code="0x2b" name="plus"/><!-- PLUS SIGN -->
<map code="0x30" name="zero"/><!-- DIGIT ZERO -->
<map code="0x3d" name="equal"/><!-- EQUALS SIGN -->
<map code="0x2212" name="minus"/><!-- MINUS SIGN -->
</cmap_format_4>
</cmap>
<loca>
<!-- The 'loca' table will be calculated by the compiler -->
</loca>
<glyf>
<!-- The xMin, yMin, xMax and yMax values
will be recalculated by the compiler. -->
<TTGlyph name=".notdef" xMin="80" yMin="0" xMax="620" yMax="700">
<contour>
<pt x="620" y="700" on="1"/>
<pt x="620" y="0" on="1"/>
<pt x="80" y="0" on="1"/>
<pt x="80" y="700" on="1"/>
</contour>
<contour>
<pt x="160" y="80" on="1"/>
<pt x="540" y="80" on="1"/>
<pt x="540" y="620" on="1"/>
<pt x="160" y="620" on="1"/>
</contour>
<instructions><assembly>
</assembly></instructions>
</TTGlyph>
<TTGlyph name="equal" xMin="80" yMin="230" xMax="580" yMax="490">
<contour>
<pt x="580" y="490" on="1"/>
<pt x="580" y="410" on="1"/>
<pt x="80" y="410" on="1"/>
<pt x="80" y="490" on="1"/>
</contour>
<contour>
<pt x="580" y="310" on="1"/>
<pt x="580" y="230" on="1"/>
<pt x="80" y="230" on="1"/>
<pt x="80" y="310" on="1"/>
</contour>
<instructions><assembly>
</assembly></instructions>
</TTGlyph>
<TTGlyph name="minus" xMin="80" yMin="310" xMax="580" yMax="390">
<contour>
<pt x="580" y="390" on="1"/>
<pt x="580" y="310" on="1"/>
<pt x="80" y="310" on="1"/>
<pt x="80" y="390" on="1"/>
</contour>
<instructions><assembly>
</assembly></instructions>
</TTGlyph>
<TTGlyph name="plus" xMin="80" yMin="100" xMax="580" yMax="600">
<contour>
<pt x="580" y="310" on="1"/>
<pt x="370" y="310" on="1"/>
<pt x="370" y="100" on="1"/>
<pt x="290" y="100" on="1"/>
<pt x="290" y="310" on="1"/>
<pt x="80" y="310" on="1"/>
<pt x="80" y="390" on="1"/>
<pt x="290" y="390" on="1"/>
<pt x="290" y="600" on="1"/>
<pt x="370" y="600" on="1"/>
<pt x="370" y="390" on="1"/>
<pt x="580" y="390" on="1"/>
</contour>
<instructions><assembly>
</assembly></instructions>
</TTGlyph>
<TTGlyph name="space"/><!-- contains no outline data -->
<TTGlyph name="zero" xMin="40" yMin="-10" xMax="585" yMax="710">
<contour>
<pt x="237" y="-10" on="0"/>
<pt x="113" y="78" on="0"/>
<pt x="40" y="241" on="0"/>
<pt x="40" y="350" on="1"/>
<pt x="40" y="459" on="0"/>
<pt x="113" y="622" on="0"/>
<pt x="237" y="710" on="0"/>
<pt x="313" y="710" on="1"/>
<pt x="388" y="710" on="0"/>
<pt x="513" y="622" on="0"/>
<pt x="585" y="459" on="0"/>
<pt x="585" y="350" on="1"/>
<pt x="585" y="241" on="0"/>
<pt x="513" y="78" on="0"/>
<pt x="388" y="-10" on="0"/>
<pt x="313" y="-10" on="1"/>
</contour>
<contour>
<pt x="366" y="74" on="0"/>
<pt x="454" y="144" on="0"/>
<pt x="505" y="270" on="0"/>
<pt x="505" y="350" on="1"/>
<pt x="505" y="430" on="0"/>
<pt x="454" y="556" on="0"/>
<pt x="366" y="626" on="0"/>
<pt x="313" y="626" on="1"/>
<pt x="260" y="626" on="0"/>
<pt x="171" y="556" on="0"/>
<pt x="120" y="430" on="0"/>
<pt x="120" y="350" on="1"/>
<pt x="120" y="270" on="0"/>
<pt x="171" y="144" on="0"/>
<pt x="260" y="74" on="0"/>
<pt x="313" y="74" on="1"/>
</contour>
<instructions><assembly>
</assembly></instructions>
</TTGlyph>
</glyf>
<name>
<namerecord nameID="1" platformID="1" platEncID="0" langID="0x0" unicode="True">
TestGVAR
</namerecord>
<namerecord nameID="2" platformID="1" platEncID="0" langID="0x0" unicode="True">
Regular
</namerecord>
<namerecord nameID="3" platformID="1" platEncID="0" langID="0x0" unicode="True">
1.000;UKWN;TestGVAR-Regular
</namerecord>
<namerecord nameID="4" platformID="1" platEncID="0" langID="0x0" unicode="True">
TestGVAR
</namerecord>
<namerecord nameID="5" platformID="1" platEncID="0" langID="0x0" unicode="True">
Version 1.000
</namerecord>
<namerecord nameID="6" platformID="1" platEncID="0" langID="0x0" unicode="True">
TestGVAR-Regular
</namerecord>
<namerecord nameID="9" platformID="1" platEncID="0" langID="0x0" unicode="True">
Sascha Brawer
</namerecord>
<namerecord nameID="257" platformID="1" platEncID="0" langID="0x0" unicode="True">
Weight
</namerecord>
<namerecord nameID="258" platformID="1" platEncID="0" langID="0x0" unicode="True">
Thin
</namerecord>
<namerecord nameID="259" platformID="1" platEncID="0" langID="0x0" unicode="True">
Light
</namerecord>
<namerecord nameID="260" platformID="1" platEncID="0" langID="0x0" unicode="True">
Regular
</namerecord>
<namerecord nameID="261" platformID="1" platEncID="0" langID="0x0" unicode="True">
Bold
</namerecord>
<namerecord nameID="262" platformID="1" platEncID="0" langID="0x0" unicode="True">
Black
</namerecord>
<namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
TestGVAR
</namerecord>
<namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
Regular
</namerecord>
<namerecord nameID="3" platformID="3" platEncID="1" langID="0x409">
1.000;UKWN;TestGVAR-Regular
</namerecord>
<namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
TestGVAR-Regular
</namerecord>
<namerecord nameID="5" platformID="3" platEncID="1" langID="0x409">
Version 1.000
</namerecord>
<namerecord nameID="6" platformID="3" platEncID="1" langID="0x409">
TestGVAR-Regular
</namerecord>
<namerecord nameID="9" platformID="3" platEncID="1" langID="0x409">
Sascha Brawer
</namerecord>
<namerecord nameID="257" platformID="3" platEncID="1" langID="0x409">
Weight
</namerecord>
<namerecord nameID="258" platformID="3" platEncID="1" langID="0x409">
Thin
</namerecord>
<namerecord nameID="259" platformID="3" platEncID="1" langID="0x409">
Light
</namerecord>
<namerecord nameID="260" platformID="3" platEncID="1" langID="0x409">
Regular
</namerecord>
<namerecord nameID="261" platformID="3" platEncID="1" langID="0x409">
Bold
</namerecord>
<namerecord nameID="262" platformID="3" platEncID="1" langID="0x409">
Black
</namerecord>
</name>
<post>
<formatType value="2.0"/>
<italicAngle value="0.0"/>
<underlinePosition value="-75"/>
<underlineThickness value="50"/>
<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>
<gasp>
<gaspRange rangeMaxPPEM="7" rangeGaspBehavior="10"/>
<gaspRange rangeMaxPPEM="19" rangeGaspBehavior="7"/>
<gaspRange rangeMaxPPEM="65535" rangeGaspBehavior="15"/>
</gasp>
<GSUB>
<Version value="1.0"/>
</GSUB>
<avar>
<segment axis="wght">
<mapping from="-1.0" to="-1.0"/>
<mapping from="0.0" to="0.0"/>
<mapping from="0.3" to="0.5"/>
<mapping from="1.0" to="1.0"/>
</segment>
</avar>
<fvar>
<!-- Weight -->
<Axis>
<AxisTag>wght</AxisTag>
<MinValue>100.0</MinValue>
<DefaultValue>400.0</DefaultValue>
<MaxValue>900.0</MaxValue>
<NameID>257</NameID>
</Axis>
<!-- Thin -->
<NamedInstance nameID="258">
<coord axis="wght" value="100.0"/>
</NamedInstance>
<!-- Light -->
<NamedInstance nameID="259">
<coord axis="wght" value="300.0"/>
</NamedInstance>
<!-- Regular -->
<NamedInstance nameID="260">
<coord axis="wght" value="400.0"/>
</NamedInstance>
<!-- Bold -->
<NamedInstance nameID="261">
<coord axis="wght" value="700.0"/>
</NamedInstance>
<!-- Black -->
<NamedInstance nameID="262">
<coord axis="wght" value="900.0"/>
</NamedInstance>
</fvar>
<gvar>
<version value="1"/>
<reserved value="0"/>
<glyphVariations glyph=".notdef">
<tuple>
<coord axis="wght" value="-1.0"/>
<delta pt="0" x="-20" y="0"/>
<delta pt="1" x="-20" y="0"/>
<delta pt="2" x="-20" y="0"/>
<delta pt="3" x="-20" y="0"/>
<delta pt="4" x="-80" y="-60"/>
<delta pt="5" x="40" y="-60"/>
<delta pt="6" x="40" y="60"/>
<delta pt="7" x="-80" y="60"/>
<delta pt="8" x="0" y="0"/>
<delta pt="9" x="-40" y="0"/>
<delta pt="10" x="0" y="0"/>
<delta pt="11" x="0" y="0"/>
</tuple>
<tuple>
<coord axis="wght" value="1.0"/>
<delta pt="0" x="20" y="0"/>
<delta pt="1" x="20" y="0"/>
<delta pt="2" x="20" y="0"/>
<delta pt="3" x="20" y="0"/>
<delta pt="4" x="80" y="60"/>
<delta pt="5" x="-40" y="60"/>
<delta pt="6" x="-40" y="-60"/>
<delta pt="7" x="80" y="-60"/>
<delta pt="8" x="0" y="0"/>
<delta pt="9" x="40" y="0"/>
<delta pt="10" x="0" y="0"/>
<delta pt="11" x="0" y="0"/>
</tuple>
</glyphVariations>
<glyphVariations glyph="space">
<tuple>
<coord axis="wght" value="-1.0"/>
<delta pt="0" x="0" y="0"/>
<delta pt="1" x="-100" y="0"/>
<delta pt="2" x="0" y="0"/>
<delta pt="3" x="0" y="0"/>
</tuple>
<tuple>
<coord axis="wght" value="1.0"/>
<delta pt="0" x="0" y="0"/>
<delta pt="1" x="100" y="0"/>
<delta pt="2" x="0" y="0"/>
<delta pt="3" x="0" y="0"/>
</tuple>
</glyphVariations>
<glyphVariations glyph="zero">
<tuple>
<coord axis="wght" value="-1.0"/>
<delta pt="0" x="-10" y="0"/>
<delta pt="1" x="-10" y="0"/>
<delta pt="2" x="-10" y="0"/>
<delta pt="3" x="-10" y="0"/>
<delta pt="4" x="-10" y="0"/>
<delta pt="5" x="-10" y="0"/>
<delta pt="6" x="-10" y="0"/>
<delta pt="7" x="-10" y="0"/>
<delta pt="8" x="-10" y="0"/>
<delta pt="9" x="-10" y="0"/>
<delta pt="10" x="-10" y="0"/>
<delta pt="11" x="-10" y="0"/>
<delta pt="12" x="-10" y="0"/>
<delta pt="13" x="-10" y="0"/>
<delta pt="14" x="-10" y="0"/>
<delta pt="15" x="-10" y="0"/>
<delta pt="16" x="7" y="-64"/>
<delta pt="17" x="34" y="-53"/>
<delta pt="18" x="50" y="-25"/>
<delta pt="19" x="50" y="0"/>
<delta pt="20" x="50" y="25"/>
<delta pt="21" x="34" y="53"/>
<delta pt="22" x="7" y="64"/>
<delta pt="23" x="-10" y="64"/>
<delta pt="24" x="-28" y="64"/>
<delta pt="25" x="-54" y="53"/>
<delta pt="26" x="-70" y="25"/>
<delta pt="27" x="-70" y="0"/>
<delta pt="28" x="-70" y="-25"/>
<delta pt="29" x="-54" y="-53"/>
<delta pt="30" x="-28" y="-64"/>
<delta pt="31" x="-10" y="-64"/>
<delta pt="32" x="0" y="0"/>
<delta pt="33" x="-20" y="0"/>
<delta pt="34" x="0" y="0"/>
<delta pt="35" x="0" y="0"/>
</tuple>
<tuple>
<coord axis="wght" value="1.0"/>
<delta pt="0" x="10" y="0"/>
<delta pt="1" x="10" y="0"/>
<delta pt="2" x="10" y="0"/>
<delta pt="3" x="10" y="0"/>
<delta pt="4" x="10" y="0"/>
<delta pt="5" x="10" y="0"/>
<delta pt="6" x="10" y="0"/>
<delta pt="7" x="10" y="0"/>
<delta pt="8" x="10" y="0"/>
<delta pt="9" x="10" y="0"/>
<delta pt="10" x="10" y="0"/>
<delta pt="11" x="10" y="0"/>
<delta pt="12" x="10" y="0"/>
<delta pt="13" x="10" y="0"/>
<delta pt="14" x="10" y="0"/>
<delta pt="15" x="10" y="0"/>
<delta pt="16" x="-6" y="55"/>
<delta pt="17" x="-34" y="37"/>
<delta pt="18" x="-50" y="11"/>
<delta pt="19" x="-50" y="0"/>
<delta pt="20" x="-50" y="-11"/>
<delta pt="21" x="-34" y="-37"/>
<delta pt="22" x="-6" y="-55"/>
<delta pt="23" x="10" y="-55"/>
<delta pt="24" x="25" y="-55"/>
<delta pt="25" x="54" y="-37"/>
<delta pt="26" x="70" y="-11"/>
<delta pt="27" x="70" y="0"/>
<delta pt="28" x="70" y="11"/>
<delta pt="29" x="54" y="37"/>
<delta pt="30" x="25" y="55"/>
<delta pt="31" x="10" y="55"/>
<delta pt="32" x="0" y="0"/>
<delta pt="33" x="20" y="0"/>
<delta pt="34" x="0" y="0"/>
<delta pt="35" x="0" y="0"/>
</tuple>
</glyphVariations>
<glyphVariations glyph="equal">
<tuple>
<coord axis="wght" value="-1.0"/>
<delta pt="0" x="-20" y="-60"/>
<delta pt="1" x="-20" y="0"/>
<delta pt="2" x="-20" y="0"/>
<delta pt="3" x="-20" y="-60"/>
<delta pt="4" x="-20" y="-30"/>
<delta pt="5" x="-20" y="30"/>
<delta pt="6" x="-20" y="30"/>
<delta pt="7" x="-20" y="-30"/>
<delta pt="8" x="0" y="0"/>
<delta pt="9" x="-40" y="0"/>
<delta pt="10" x="0" y="-60"/>
<delta pt="11" x="0" y="-30"/>
</tuple>
<tuple>
<coord axis="wght" value="1.0"/>
<delta pt="0" x="20" y="10"/>
<delta pt="1" x="20" y="-30"/>
<delta pt="2" x="20" y="-30"/>
<delta pt="3" x="20" y="10"/>
<delta pt="4" x="20" y="10"/>
<delta pt="5" x="20" y="-30"/>
<delta pt="6" x="20" y="-30"/>
<delta pt="7" x="20" y="10"/>
<delta pt="8" x="0" y="0"/>
<delta pt="9" x="40" y="0"/>
<delta pt="10" x="0" y="10"/>
<delta pt="11" x="0" y="30"/>
</tuple>
</glyphVariations>
<glyphVariations glyph="minus">
<tuple>
<coord axis="wght" value="-1.0"/>
<delta pt="0" x="-20" y="-30"/>
<delta pt="1" x="-20" y="30"/>
<delta pt="2" x="-20" y="30"/>
<delta pt="3" x="-20" y="-30"/>
<delta pt="4" x="0" y="0"/>
<delta pt="5" x="-40" y="0"/>
<delta pt="6" x="0" y="-30"/>
<delta pt="7" x="0" y="-30"/>
</tuple>
<tuple>
<coord axis="wght" value="1.0"/>
<delta pt="0" x="20" y="30"/>
<delta pt="1" x="20" y="-30"/>
<delta pt="2" x="20" y="-30"/>
<delta pt="3" x="20" y="30"/>
<delta pt="4" x="0" y="0"/>
<delta pt="5" x="40" y="0"/>
<delta pt="6" x="0" y="30"/>
<delta pt="7" x="0" y="30"/>
</tuple>
</glyphVariations>
<glyphVariations glyph="plus">
<tuple>
<coord axis="wght" value="-1.0"/>
<delta pt="0" x="-20" y="30"/>
<delta pt="1" x="-50" y="30"/>
<delta pt="2" x="-50" y="0"/>
<delta pt="3" x="10" y="0"/>
<delta pt="4" x="10" y="30"/>
<delta pt="5" x="-20" y="30"/>
<delta pt="6" x="-20" y="-30"/>
<delta pt="7" x="10" y="-30"/>
<delta pt="8" x="10" y="0"/>
<delta pt="9" x="-50" y="0"/>
<delta pt="10" x="-50" y="-30"/>
<delta pt="11" x="-20" y="-30"/>
<delta pt="12" x="0" y="0"/>
<delta pt="13" x="-40" y="0"/>
<delta pt="14" x="0" y="0"/>
<delta pt="15" x="0" y="0"/>
</tuple>
<tuple>
<coord axis="wght" value="1.0"/>
<delta pt="0" x="20" y="-30"/>
<delta pt="1" x="50" y="-30"/>
<delta pt="2" x="50" y="0"/>
<delta pt="3" x="-10" y="0"/>
<delta pt="4" x="-10" y="-30"/>
<delta pt="5" x="20" y="-30"/>
<delta pt="6" x="20" y="30"/>
<delta pt="7" x="-10" y="30"/>
<delta pt="8" x="-10" y="0"/>
<delta pt="9" x="50" y="0"/>
<delta pt="10" x="50" y="30"/>
<delta pt="11" x="20" y="30"/>
<delta pt="12" x="0" y="0"/>
<delta pt="13" x="40" y="0"/>
<delta pt="14" x="0" y="0"/>
<delta pt="15" x="0" y="0"/>
</tuple>
</glyphVariations>
</gvar>
</ttFont>

View File

@ -0,0 +1,153 @@
<?xml version="1.0" encoding="UTF-8"?>
<ttFont sfntVersion="OTTO" ttLibVersion="3.0">
<GlyphOrder>
<!-- The 'id' attribute is only for humans; it is ignored when parsed. -->
<GlyphID id="0" name=".notdef"/>
<GlyphID id="1" name="minus"/>
<GlyphID id="2" name="plus"/>
</GlyphOrder>
<avar>
<segment axis="wght">
<mapping from="-1.0" to="-1.0"/>
<mapping from="0.0" to="0.0"/>
<mapping from="0.3" to="0.5"/>
<mapping from="1.0" to="1.0"/>
</segment>
</avar>
<fvar>
<!-- Weight -->
<Axis>
<AxisTag>wght</AxisTag>
<MinValue>100.0</MinValue>
<DefaultValue>400.0</DefaultValue>
<MaxValue>900.0</MaxValue>
<NameID>257</NameID>
</Axis>
<!-- Thin -->
<NamedInstance nameID="258">
<coord axis="wght" value="100.0"/>
</NamedInstance>
<!-- Light -->
<NamedInstance nameID="259">
<coord axis="wght" value="300.0"/>
</NamedInstance>
<!-- Regular -->
<NamedInstance nameID="260">
<coord axis="wght" value="400.0"/>
</NamedInstance>
<!-- Bold -->
<NamedInstance nameID="261">
<coord axis="wght" value="700.0"/>
</NamedInstance>
<!-- Black -->
<NamedInstance nameID="262">
<coord axis="wght" value="900.0"/>
</NamedInstance>
</fvar>
<gvar>
<version value="1"/>
<reserved value="0"/>
<glyphVariations glyph="minus">
<tuple>
<coord axis="wght" value="-1.0"/>
<delta pt="0" x="-20" y="-30"/>
<delta pt="1" x="-20" y="30"/>
<delta pt="2" x="-20" y="30"/>
<delta pt="3" x="-20" y="-30"/>
<delta pt="4" x="0" y="0"/>
<delta pt="5" x="-40" y="0"/>
<delta pt="6" x="0" y="-30"/>
<delta pt="7" x="0" y="-30"/>
</tuple>
<tuple>
<coord axis="wght" value="1.0"/>
<delta pt="0" x="20" y="30"/>
<delta pt="1" x="20" y="-30"/>
<delta pt="2" x="20" y="-30"/>
<delta pt="3" x="20" y="30"/>
<delta pt="4" x="0" y="0"/>
<delta pt="5" x="40" y="0"/>
<delta pt="6" x="0" y="30"/>
<delta pt="7" x="0" y="30"/>
</tuple>
</glyphVariations>
<glyphVariations glyph="plus">
<tuple>
<coord axis="wght" value="-1.0"/>
<delta pt="0" x="-20" y="30"/>
<delta pt="1" x="-50" y="30"/>
<delta pt="2" x="-50" y="0"/>
<delta pt="3" x="10" y="0"/>
<delta pt="4" x="10" y="30"/>
<delta pt="5" x="-20" y="30"/>
<delta pt="6" x="-20" y="-30"/>
<delta pt="7" x="10" y="-30"/>
<delta pt="8" x="10" y="0"/>
<delta pt="9" x="-50" y="0"/>
<delta pt="10" x="-50" y="-30"/>
<delta pt="11" x="-20" y="-30"/>
<delta pt="12" x="0" y="0"/>
<delta pt="13" x="-40" y="0"/>
<delta pt="14" x="0" y="0"/>
<delta pt="15" x="0" y="0"/>
</tuple>
<tuple>
<coord axis="wght" value="1.0"/>
<delta pt="0" x="20" y="-30"/>
<delta pt="1" x="50" y="-30"/>
<delta pt="2" x="50" y="0"/>
<delta pt="3" x="-10" y="0"/>
<delta pt="4" x="-10" y="-30"/>
<delta pt="5" x="20" y="-30"/>
<delta pt="6" x="20" y="30"/>
<delta pt="7" x="-10" y="30"/>
<delta pt="8" x="-10" y="0"/>
<delta pt="9" x="50" y="0"/>
<delta pt="10" x="50" y="30"/>
<delta pt="11" x="20" y="30"/>
<delta pt="12" x="0" y="0"/>
<delta pt="13" x="40" y="0"/>
<delta pt="14" x="0" y="0"/>
<delta pt="15" x="0" y="0"/>
</tuple>
</glyphVariations>
</gvar>
<name>
<namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
TestGVAR
</namerecord>
<namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
Regular
</namerecord>
<namerecord nameID="257" platformID="3" platEncID="1" langID="0x409">
Weight
</namerecord>
<namerecord nameID="258" platformID="3" platEncID="1" langID="0x409">
Thin
</namerecord>
<namerecord nameID="259" platformID="3" platEncID="1" langID="0x409">
Light
</namerecord>
<namerecord nameID="260" platformID="3" platEncID="1" langID="0x409">
Regular
</namerecord>
<namerecord nameID="261" platformID="3" platEncID="1" langID="0x409">
Bold
</namerecord>
<namerecord nameID="262" platformID="3" platEncID="1" langID="0x409">
Black
</namerecord>
</name>
</ttFont>

View File

@ -0,0 +1,200 @@
<?xml version="1.0" encoding="UTF-8"?>
<ttFont sfntVersion="OTTO" ttLibVersion="3.0">
<GlyphOrder>
<!-- The 'id' attribute is only for humans; it is ignored when parsed. -->
<GlyphID id="0" name=".notdef"/>
<GlyphID id="1" name="zero"/>
</GlyphOrder>
<avar>
<segment axis="wght">
<mapping from="-1.0" to="-1.0"/>
<mapping from="0.0" to="0.0"/>
<mapping from="0.3" to="0.5"/>
<mapping from="1.0" to="1.0"/>
</segment>
</avar>
<fvar>
<!-- Weight -->
<Axis>
<AxisTag>wght</AxisTag>
<MinValue>100.0</MinValue>
<DefaultValue>400.0</DefaultValue>
<MaxValue>900.0</MaxValue>
<NameID>257</NameID>
</Axis>
<!-- Thin -->
<NamedInstance nameID="258">
<coord axis="wght" value="100.0"/>
</NamedInstance>
<!-- Light -->
<NamedInstance nameID="259">
<coord axis="wght" value="300.0"/>
</NamedInstance>
<!-- Regular -->
<NamedInstance nameID="260">
<coord axis="wght" value="400.0"/>
</NamedInstance>
<!-- Bold -->
<NamedInstance nameID="261">
<coord axis="wght" value="700.0"/>
</NamedInstance>
<!-- Black -->
<NamedInstance nameID="262">
<coord axis="wght" value="900.0"/>
</NamedInstance>
</fvar>
<gvar>
<version value="1"/>
<reserved value="0"/>
<glyphVariations glyph=".notdef">
<tuple>
<coord axis="wght" value="-1.0"/>
<delta pt="0" x="-20" y="0"/>
<delta pt="1" x="-20" y="0"/>
<delta pt="2" x="-20" y="0"/>
<delta pt="3" x="-20" y="0"/>
<delta pt="4" x="-80" y="-60"/>
<delta pt="5" x="40" y="-60"/>
<delta pt="6" x="40" y="60"/>
<delta pt="7" x="-80" y="60"/>
<delta pt="8" x="0" y="0"/>
<delta pt="9" x="-40" y="0"/>
<delta pt="10" x="0" y="0"/>
<delta pt="11" x="0" y="0"/>
</tuple>
<tuple>
<coord axis="wght" value="1.0"/>
<delta pt="0" x="20" y="0"/>
<delta pt="1" x="20" y="0"/>
<delta pt="2" x="20" y="0"/>
<delta pt="3" x="20" y="0"/>
<delta pt="4" x="80" y="60"/>
<delta pt="5" x="-40" y="60"/>
<delta pt="6" x="-40" y="-60"/>
<delta pt="7" x="80" y="-60"/>
<delta pt="8" x="0" y="0"/>
<delta pt="9" x="40" y="0"/>
<delta pt="10" x="0" y="0"/>
<delta pt="11" x="0" y="0"/>
</tuple>
</glyphVariations>
<glyphVariations glyph="zero">
<tuple>
<coord axis="wght" value="-1.0"/>
<delta pt="0" x="-10" y="0"/>
<delta pt="1" x="-10" y="0"/>
<delta pt="2" x="-10" y="0"/>
<delta pt="3" x="-10" y="0"/>
<delta pt="4" x="-10" y="0"/>
<delta pt="5" x="-10" y="0"/>
<delta pt="6" x="-10" y="0"/>
<delta pt="7" x="-10" y="0"/>
<delta pt="8" x="-10" y="0"/>
<delta pt="9" x="-10" y="0"/>
<delta pt="10" x="-10" y="0"/>
<delta pt="11" x="-10" y="0"/>
<delta pt="12" x="-10" y="0"/>
<delta pt="13" x="-10" y="0"/>
<delta pt="14" x="-10" y="0"/>
<delta pt="15" x="-10" y="0"/>
<delta pt="16" x="7" y="-64"/>
<delta pt="17" x="34" y="-53"/>
<delta pt="18" x="50" y="-25"/>
<delta pt="19" x="50" y="0"/>
<delta pt="20" x="50" y="25"/>
<delta pt="21" x="34" y="53"/>
<delta pt="22" x="7" y="64"/>
<delta pt="23" x="-10" y="64"/>
<delta pt="24" x="-28" y="64"/>
<delta pt="25" x="-54" y="53"/>
<delta pt="26" x="-70" y="25"/>
<delta pt="27" x="-70" y="0"/>
<delta pt="28" x="-70" y="-25"/>
<delta pt="29" x="-54" y="-53"/>
<delta pt="30" x="-28" y="-64"/>
<delta pt="31" x="-10" y="-64"/>
<delta pt="32" x="0" y="0"/>
<delta pt="33" x="-20" y="0"/>
<delta pt="34" x="0" y="0"/>
<delta pt="35" x="0" y="0"/>
</tuple>
<tuple>
<coord axis="wght" value="1.0"/>
<delta pt="0" x="10" y="0"/>
<delta pt="1" x="10" y="0"/>
<delta pt="2" x="10" y="0"/>
<delta pt="3" x="10" y="0"/>
<delta pt="4" x="10" y="0"/>
<delta pt="5" x="10" y="0"/>
<delta pt="6" x="10" y="0"/>
<delta pt="7" x="10" y="0"/>
<delta pt="8" x="10" y="0"/>
<delta pt="9" x="10" y="0"/>
<delta pt="10" x="10" y="0"/>
<delta pt="11" x="10" y="0"/>
<delta pt="12" x="10" y="0"/>
<delta pt="13" x="10" y="0"/>
<delta pt="14" x="10" y="0"/>
<delta pt="15" x="10" y="0"/>
<delta pt="16" x="-6" y="55"/>
<delta pt="17" x="-34" y="37"/>
<delta pt="18" x="-50" y="11"/>
<delta pt="19" x="-50" y="0"/>
<delta pt="20" x="-50" y="-11"/>
<delta pt="21" x="-34" y="-37"/>
<delta pt="22" x="-6" y="-55"/>
<delta pt="23" x="10" y="-55"/>
<delta pt="24" x="25" y="-55"/>
<delta pt="25" x="54" y="-37"/>
<delta pt="26" x="70" y="-11"/>
<delta pt="27" x="70" y="0"/>
<delta pt="28" x="70" y="11"/>
<delta pt="29" x="54" y="37"/>
<delta pt="30" x="25" y="55"/>
<delta pt="31" x="10" y="55"/>
<delta pt="32" x="0" y="0"/>
<delta pt="33" x="20" y="0"/>
<delta pt="34" x="0" y="0"/>
<delta pt="35" x="0" y="0"/>
</tuple>
</glyphVariations>
</gvar>
<name>
<namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
TestGVAR
</namerecord>
<namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
Regular
</namerecord>
<namerecord nameID="257" platformID="3" platEncID="1" langID="0x409">
Weight
</namerecord>
<namerecord nameID="258" platformID="3" platEncID="1" langID="0x409">
Thin
</namerecord>
<namerecord nameID="259" platformID="3" platEncID="1" langID="0x409">
Light
</namerecord>
<namerecord nameID="260" platformID="3" platEncID="1" langID="0x409">
Regular
</namerecord>
<namerecord nameID="261" platformID="3" platEncID="1" langID="0x409">
Bold
</namerecord>
<namerecord nameID="262" platformID="3" platEncID="1" langID="0x409">
Black
</namerecord>
</name>
</ttFont>