Merge pull request #3147 from fonttools/varlib-drop-implied-oncurves

[varlib] add --drop-implied-oncurves option
This commit is contained in:
Cosimo Lupo 2023-06-05 12:28:51 +01:00 committed by GitHub
commit d673fad56b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 1355 additions and 30 deletions

View File

@ -144,10 +144,7 @@ class _TTGlyphBasePen:
glyph.coordinates = GlyphCoordinates(self.points)
glyph.endPtsOfContours = self.endPts
glyph.flags = array("B", self.types)
glyph.coordinates.toInt()
if dropImpliedOnCurves:
dropImpliedOnCurvePoints(glyph)
self.init()
@ -160,6 +157,8 @@ class _TTGlyphBasePen:
glyph.numberOfContours = len(glyph.endPtsOfContours)
glyph.program = ttProgram.Program()
glyph.program.fromBytecode(b"")
if dropImpliedOnCurves:
dropImpliedOnCurvePoints(glyph)
return glyph

View File

@ -28,6 +28,7 @@ from fontTools.misc import xmlWriter
from fontTools.misc.filenames import userNameToFileName
from fontTools.misc.loggingTools import deprecateFunction
from enum import IntFlag
from types import SimpleNamespace
from typing import Set
log = logging.getLogger(__name__)
@ -1541,6 +1542,8 @@ def dropImpliedOnCurvePoints(*interpolatable_glyphs: Glyph) -> Set[int]:
If more than one glyphs are passed, these are assumed to be interpolatable masters
of the same glyph impliable, and thus only the on-curve points that are impliable
for all of them will actually be implied.
Composite glyphs or empty glyphs are skipped, only simple glyphs with 1 or more
contours are considered.
The input glyph(s) is/are modified in-place.
Args:
@ -1549,18 +1552,40 @@ def dropImpliedOnCurvePoints(*interpolatable_glyphs: Glyph) -> Set[int]:
Returns:
The set of point indices that were dropped if any.
Raises:
ValueError if simple glyphs are not in fact interpolatable because they have
different point flags or number of contours.
Reference:
https://developer.apple.com/fonts/TrueType-Reference-Manual/RM01/Chap1.html
"""
assert len(interpolatable_glyphs) > 0
staticAttributes = SimpleNamespace(
numberOfContours=None, flags=None, endPtsOfContours=None
)
drop = None
for glyph in interpolatable_glyphs:
simple_glyphs = []
for i, glyph in enumerate(interpolatable_glyphs):
if glyph.numberOfContours < 1:
# ignore composite or empty glyphs
continue
for attr in staticAttributes.__dict__:
expected = getattr(staticAttributes, attr)
found = getattr(glyph, attr)
if expected is None:
setattr(staticAttributes, attr, found)
elif expected != found:
raise ValueError(
f"Incompatible {attr} for glyph at master index {i}: "
f"expected {expected}, found {found}"
)
may_drop = set()
start = 0
flags = glyph.flags
coords = glyph.coordinates
for last in glyph.endPtsOfContours:
flags = staticAttributes.flags
endPtsOfContours = staticAttributes.endPtsOfContours
for last in endPtsOfContours:
for i in range(start, last + 1):
if not (flags[i] & flagOnCurve):
continue
@ -1583,32 +1608,39 @@ def dropImpliedOnCurvePoints(*interpolatable_glyphs: Glyph) -> Set[int]:
else:
drop.intersection_update(may_drop)
simple_glyphs.append(glyph)
if drop:
# Do the actual dropping
for glyph in interpolatable_glyphs:
flags = staticAttributes.flags
assert flags is not None
newFlags = array.array(
"B", (flags[i] for i in range(len(flags)) if i not in drop)
)
endPts = staticAttributes.endPtsOfContours
assert endPts is not None
newEndPts = []
i = 0
delta = 0
for d in sorted(drop):
while d > endPts[i]:
newEndPts.append(endPts[i] - delta)
i += 1
delta += 1
while i < len(endPts):
newEndPts.append(endPts[i] - delta)
i += 1
for glyph in simple_glyphs:
coords = glyph.coordinates
glyph.coordinates = GlyphCoordinates(
coords[i] for i in range(len(coords)) if i not in drop
)
glyph.flags = array.array(
"B", (flags[i] for i in range(len(flags)) if i not in drop)
)
endPts = glyph.endPtsOfContours
newEndPts = []
i = 0
delta = 0
for d in sorted(drop):
while d > endPts[i]:
newEndPts.append(endPts[i] - delta)
i += 1
delta += 1
while i < len(endPts):
newEndPts.append(endPts[i] - delta)
i += 1
glyph.flags = newFlags
glyph.endPtsOfContours = newEndPts
return drop
return drop if drop is not None else set()
class GlyphComponent(object):

View File

@ -24,7 +24,7 @@ from fontTools.misc.roundTools import noRound, otRound
from fontTools.misc.textTools import Tag, tostr
from fontTools.ttLib import TTFont, newTable
from fontTools.ttLib.tables._f_v_a_r import Axis, NamedInstance
from fontTools.ttLib.tables._g_l_y_f import GlyphCoordinates
from fontTools.ttLib.tables._g_l_y_f import GlyphCoordinates, dropImpliedOnCurvePoints
from fontTools.ttLib.tables.ttProgram import Program
from fontTools.ttLib.tables.TupleVariation import TupleVariation
from fontTools.ttLib.tables import otTables as ot
@ -40,7 +40,7 @@ from fontTools.varLib.stat import buildVFStatTable
from fontTools.colorLib.builder import buildColrV1
from fontTools.colorLib.unbuilder import unbuildColrV1
from functools import partial
from collections import OrderedDict, namedtuple
from collections import OrderedDict, defaultdict, namedtuple
import os.path
import logging
from copy import deepcopy
@ -965,6 +965,46 @@ def set_default_weight_width_slant(font, location):
font["post"].italicAngle = italicAngle
def drop_implied_oncurve_points(*masters: TTFont) -> int:
"""Drop impliable on-curve points from all the simple glyphs in masters.
In TrueType glyf outlines, on-curve points can be implied when they are located
exactly at the midpoint of the line connecting two consecutive off-curve points.
The input masters' glyf tables are assumed to contain same-named glyphs that are
interpolatable. Oncurve points are only dropped if they can be implied for all
the masters. The fonts are modified in-place.
Args:
masters: The TTFont(s) to modify
Returns:
The total number of points that were dropped if any.
Reference:
https://developer.apple.com/fonts/TrueType-Reference-Manual/RM01/Chap1.html
"""
count = 0
glyph_masters = defaultdict(list)
# multiple DS source may point to the same TTFont object and we want to
# avoid processing the same glyph twice as they are modified in-place
for font in {id(m): m for m in masters}.values():
glyf = font["glyf"]
for glyphName in glyf.keys():
glyph_masters[glyphName].append(glyf[glyphName])
count = 0
for glyphName, glyphs in glyph_masters.items():
try:
dropped = dropImpliedOnCurvePoints(*glyphs)
except ValueError as e:
# we don't fail for incompatible glyphs in _add_gvar so we shouldn't here
log.warning("Failed to drop implied oncurves for %r: %s", glyphName, e)
else:
count += len(dropped)
return count
def build_many(
designspace: DesignSpaceDocument,
master_finder=lambda s: s,
@ -972,6 +1012,7 @@ def build_many(
optimize=True,
skip_vf=lambda vf_name: False,
colr_layer_reuse=True,
drop_implied_oncurves=False,
):
"""
Build variable fonts from a designspace file, version 5 which can define
@ -1015,6 +1056,7 @@ def build_many(
exclude=exclude,
optimize=optimize,
colr_layer_reuse=colr_layer_reuse,
drop_implied_oncurves=drop_implied_oncurves,
)[0]
if doBuildStatFromDSv5:
buildVFStatTable(vf, designspace, name)
@ -1028,6 +1070,7 @@ def build(
exclude=[],
optimize=True,
colr_layer_reuse=True,
drop_implied_oncurves=False,
):
"""
Build variation font from a designspace file.
@ -1055,6 +1098,13 @@ def build(
except AttributeError:
master_ttfs.append(None) # in-memory fonts have no path
if drop_implied_oncurves and "glyf" in master_fonts[ds.base_idx]:
drop_count = drop_implied_oncurve_points(*master_fonts)
log.info(
"Dropped %s on-curve points from simple glyphs in the 'glyf' table",
drop_count,
)
# Copy the base master to work from it
vf = deepcopy(master_fonts[ds.base_idx])
@ -1228,6 +1278,14 @@ def main(args=None):
action="store_false",
help="do not rebuild variable COLR table to optimize COLR layer reuse",
)
parser.add_argument(
"--drop-implied-oncurves",
action="store_true",
help=(
"drop on-curve points that can be implied when exactly in the middle of "
"two off-curve points (only applies to TrueType fonts)"
),
)
parser.add_argument(
"--master-finder",
default="master_ttf_interpolatable/{stem}.ttf",
@ -1312,6 +1370,7 @@ def main(args=None):
exclude=options.exclude,
optimize=options.optimize,
colr_layer_reuse=options.colr_layer_reuse,
drop_implied_oncurves=options.drop_implied_oncurves,
)
for vf_name, vf in vfs.items():

View File

@ -860,13 +860,17 @@ def test_dropImpliedOnCurvePoints_all_quad_off_curves():
],
Transform().scale(2.0),
)
# also add an empty glyph (will be ignored); we use this trick for 'sparse' masters
glyph3 = Glyph()
glyph3.numberOfContours = 0
assert dropImpliedOnCurvePoints(glyph1, glyph2) == {0, 2, 4, 6}
assert dropImpliedOnCurvePoints(glyph1, glyph2, glyph3) == {0, 2, 4, 6}
assert glyph1.flags == glyph2.flags == array.array("B", [0, 0, 0, 0])
assert glyph1.coordinates == GlyphCoordinates([(1, 1), (1, -1), (-1, -1), (-1, 1)])
assert glyph2.coordinates == GlyphCoordinates([(2, 2), (2, -2), (-2, -2), (-2, 2)])
assert glyph1.endPtsOfContours == glyph2.endPtsOfContours == [3]
assert glyph3.numberOfContours == 0
def test_dropImpliedOnCurvePoints_all_cubic_off_curves():
@ -890,8 +894,10 @@ def test_dropImpliedOnCurvePoints_all_cubic_off_curves():
],
Transform().translate(10.0),
)
glyph3 = Glyph()
glyph3.numberOfContours = 0
assert dropImpliedOnCurvePoints(glyph1, glyph2) == {0, 3, 6, 9}
assert dropImpliedOnCurvePoints(glyph1, glyph2, glyph3) == {0, 3, 6, 9}
assert glyph1.flags == glyph2.flags == array.array("B", [flagCubic] * 8)
assert glyph1.coordinates == GlyphCoordinates(
@ -901,6 +907,7 @@ def test_dropImpliedOnCurvePoints_all_cubic_off_curves():
[(11, 1), (11, 1), (11, -1), (11, -1), (9, -1), (9, -1), (9, 1), (9, 1)]
)
assert glyph1.endPtsOfContours == glyph2.endPtsOfContours == [7]
assert glyph3.numberOfContours == 0
def test_dropImpliedOnCurvePoints_not_all_impliable():
@ -936,6 +943,66 @@ def test_dropImpliedOnCurvePoints_not_all_impliable():
assert glyph2.flags == array.array("B", [0, flagOnCurve, 0, 0, 0])
def test_dropImpliedOnCurvePoints_all_empty_glyphs():
glyph1 = Glyph()
glyph1.numberOfContours = 0
glyph2 = Glyph()
glyph2.numberOfContours = 0
assert dropImpliedOnCurvePoints(glyph1, glyph2) == set()
def test_dropImpliedOnCurvePoints_incompatible_number_of_contours():
glyph1 = Glyph()
glyph1.numberOfContours = 1
glyph1.endPtsOfContours = [3]
glyph1.flags = array.array("B", [1, 1, 1, 1])
glyph1.coordinates = GlyphCoordinates([(0, 0), (1, 1), (2, 2), (3, 3)])
glyph2 = Glyph()
glyph2.numberOfContours = 2
glyph2.endPtsOfContours = [1, 3]
glyph2.flags = array.array("B", [1, 1, 1, 1])
glyph2.coordinates = GlyphCoordinates([(0, 0), (1, 1), (2, 2), (3, 3)])
with pytest.raises(ValueError, match="Incompatible numberOfContours"):
dropImpliedOnCurvePoints(glyph1, glyph2)
def test_dropImpliedOnCurvePoints_incompatible_flags():
glyph1 = Glyph()
glyph1.numberOfContours = 1
glyph1.endPtsOfContours = [3]
glyph1.flags = array.array("B", [1, 1, 1, 1])
glyph1.coordinates = GlyphCoordinates([(0, 0), (1, 1), (2, 2), (3, 3)])
glyph2 = Glyph()
glyph2.numberOfContours = 1
glyph2.endPtsOfContours = [3]
glyph2.flags = array.array("B", [0, 0, 0, 0])
glyph2.coordinates = GlyphCoordinates([(0, 0), (1, 1), (2, 2), (3, 3)])
with pytest.raises(ValueError, match="Incompatible flags"):
dropImpliedOnCurvePoints(glyph1, glyph2)
def test_dropImpliedOnCurvePoints_incompatible_endPtsOfContours():
glyph1 = Glyph()
glyph1.numberOfContours = 2
glyph1.endPtsOfContours = [2, 6]
glyph1.flags = array.array("B", [1, 1, 1, 1, 1, 1, 1])
glyph1.coordinates = GlyphCoordinates([(i, i) for i in range(7)])
glyph2 = Glyph()
glyph2.numberOfContours = 2
glyph2.endPtsOfContours = [3, 6]
glyph2.flags = array.array("B", [1, 1, 1, 1, 1, 1, 1])
glyph2.coordinates = GlyphCoordinates([(i, i) for i in range(7)])
with pytest.raises(ValueError, match="Incompatible endPtsOfContours"):
dropImpliedOnCurvePoints(glyph1, glyph2)
if __name__ == "__main__":
import sys

View File

@ -0,0 +1,20 @@
<?xml version='1.0' encoding='utf-8'?>
<designspace format="3">
<axes>
<axis default="400" maximum="1000" minimum="400" name="weight" tag="wght" />
</axes>
<sources>
<source familyname="Test Family" filename="master_ufo/TestFamily-Master1.ttx" name="master_1" stylename="Master1">
<location>
<dimension name="weight" xvalue="400" />
</location>
</source>
<source familyname="Test Family" filename="master_ufo/TestFamily-Master2.ttx" name="master_2" stylename="Master2">
<location>
<dimension name="weight" xvalue="1000" />
</location>
</source>
</sources>
<instances>
</instances>
</designspace>

View File

@ -0,0 +1,312 @@
<?xml version="1.0" encoding="UTF-8"?>
<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="3.7">
<GlyphOrder>
<!-- The 'id' attribute is only for humans; it is ignored when parsed. -->
<GlyphID id="0" name=".notdef"/>
<GlyphID id="1" name="uni0020"/>
<GlyphID id="2" name="uni0061"/>
</GlyphOrder>
<head>
<!-- Most of this table will be recalculated by the compiler -->
<tableVersion value="1.0"/>
<fontRevision value="1.001"/>
<checkSumAdjustment value="0xd723fbc6"/>
<magicNumber value="0x5f0f3cf5"/>
<flags value="00000000 00000011"/>
<unitsPerEm value="1000"/>
<created value="Tue Feb 28 16:48:24 2017"/>
<modified value="Tue Feb 28 16:48:24 2017"/>
<xMin value="5"/>
<yMin value="-115"/>
<xMax value="653"/>
<yMax value="750"/>
<macStyle value="00000000 00000000"/>
<lowestRecPPEM value="6"/>
<fontDirectionHint value="2"/>
<indexToLocFormat value="0"/>
<glyphDataFormat value="0"/>
</head>
<hhea>
<tableVersion value="0x00010000"/>
<ascent value="918"/>
<descent value="-335"/>
<lineGap value="0"/>
<advanceWidthMax value="663"/>
<minLeftSideBearing value="5"/>
<minRightSideBearing value="7"/>
<xMaxExtent value="653"/>
<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="5"/>
</hhea>
<maxp>
<!-- Most of this table will be recalculated by the compiler -->
<tableVersion value="0x10000"/>
<numGlyphs value="3"/>
<maxPoints value="60"/>
<maxContours value="4"/>
<maxCompositePoints value="0"/>
<maxCompositeContours value="0"/>
<maxZones value="1"/>
<maxTwilightPoints value="0"/>
<maxStorage value="0"/>
<maxFunctionDefs value="1"/>
<maxInstructionDefs value="0"/>
<maxStackElements value="1"/>
<maxSizeOfInstructions value="5"/>
<maxComponentElements value="0"/>
<maxComponentDepth value="0"/>
</maxp>
<OS_2>
<!-- The fields 'usFirstCharIndex' and 'usLastCharIndex'
will be recalculated by the compiler -->
<version value="4"/>
<xAvgCharWidth value="506"/>
<usWeightClass value="400"/>
<usWidthClass value="5"/>
<fsType value="00000000 00000100"/>
<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="284"/>
<sFamilyClass value="0"/>
<panose>
<bFamilyType value="2"/>
<bSerifStyle value="4"/>
<bWeight value="6"/>
<bProportion value="3"/>
<bContrast value="5"/>
<bStrokeVariation value="4"/>
<bArmStyle value="5"/>
<bLetterForm value="2"/>
<bMidline value="2"/>
<bXHeight value="4"/>
</panose>
<ulUnicodeRange1 value="00000000 00000000 00000000 00000011"/>
<ulUnicodeRange2 value="00000000 00000000 00000000 00000000"/>
<ulUnicodeRange3 value="00000000 00000000 00000000 00000000"/>
<ulUnicodeRange4 value="00000000 00000000 00000000 00000000"/>
<achVendID value="ADBO"/>
<fsSelection value="00000000 01000000"/>
<usFirstCharIndex value="32"/>
<usLastCharIndex value="97"/>
<sTypoAscender value="730"/>
<sTypoDescender value="-270"/>
<sTypoLineGap value="0"/>
<usWinAscent value="918"/>
<usWinDescent value="335"/>
<ulCodePageRange1 value="00100000 00000000 00000000 00000011"/>
<ulCodePageRange2 value="00000000 00000000 00000000 00000000"/>
<sxHeight value="474"/>
<sCapHeight value="677"/>
<usDefaultChar value="0"/>
<usBreakChar value="32"/>
<usMaxContext value="0"/>
</OS_2>
<hmtx>
<mtx name=".notdef" width="640" lsb="80"/>
<mtx name="uni0020" width="234" lsb="0"/>
<mtx name="uni0061" width="508" lsb="46"/>
</hmtx>
<cmap>
<tableVersion version="0"/>
<cmap_format_4 platformID="0" platEncID="3" language="0">
<map code="0x20" name="uni0020"/><!-- SPACE -->
<map code="0x61" name="uni0061"/><!-- LATIN SMALL LETTER A -->
</cmap_format_4>
<cmap_format_4 platformID="3" platEncID="1" language="0">
<map code="0x20" name="uni0020"/><!-- SPACE -->
<map code="0x61" name="uni0061"/><!-- LATIN SMALL LETTER A -->
</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="560" yMax="670">
<contour>
<pt x="80" y="0" on="1"/>
<pt x="500" y="670" on="1"/>
<pt x="560" y="670" on="1"/>
<pt x="140" y="0" on="1"/>
</contour>
<contour>
<pt x="560" y="0" on="1"/>
<pt x="500" y="0" on="1"/>
<pt x="80" y="670" on="1"/>
<pt x="140" y="670" on="1"/>
</contour>
<contour>
<pt x="140" y="50" on="1"/>
<pt x="500" y="50" on="1"/>
<pt x="500" y="620" on="1"/>
<pt x="140" y="620" on="1"/>
</contour>
<contour>
<pt x="80" y="0" on="1"/>
<pt x="80" y="670" on="1"/>
<pt x="560" y="670" on="1"/>
<pt x="560" y="0" on="1"/>
</contour>
<instructions/>
</TTGlyph>
<TTGlyph name="uni0020"/><!-- contains no outline data -->
<TTGlyph name="uni0061" xMin="46" yMin="-13" xMax="501" yMax="487">
<contour>
<pt x="46" y="102" on="1"/>
<pt x="46" y="154" on="0"/>
<pt x="110" y="225" on="0"/>
<pt x="210" y="262" on="1"/>
<pt x="242" y="273" on="0"/>
<pt x="328" y="297" on="0"/>
<pt x="365" y="304" on="1"/>
<pt x="365" y="268" on="1"/>
<pt x="331" y="261" on="0"/>
<pt x="254" y="237" on="0"/>
<pt x="231" y="228" on="1"/>
<pt x="164" y="202" on="0"/>
<pt x="131" y="148" on="0"/>
<pt x="131" y="126" on="1"/>
<pt x="131" y="86" on="0"/>
<pt x="178" y="52" on="0"/>
<pt x="212" y="52" on="1"/>
<pt x="238" y="52" on="0"/>
<pt x="283" y="76" on="0"/>
<pt x="330" y="110" on="1"/>
<pt x="350" y="125" on="1"/>
<pt x="364" y="104" on="1"/>
<pt x="335" y="75" on="1"/>
<pt x="290" y="30" on="0"/>
<pt x="226" y="-13" on="0"/>
<pt x="180" y="-13" on="1"/>
<pt x="125" y="-13" on="0"/>
<pt x="46" y="50" on="0"/>
</contour>
<contour>
<pt x="325" y="92" on="1"/>
<pt x="325" y="320" on="1"/>
<pt x="325" y="394" on="0"/>
<pt x="280" y="442" on="0"/>
<pt x="231" y="442" on="1"/>
<pt x="214" y="442" on="0"/>
<pt x="169" y="435" on="0"/>
<pt x="141" y="424" on="1"/>
<pt x="181" y="455" on="1"/>
<pt x="155" y="369" on="1"/>
<pt x="148" y="347" on="0"/>
<pt x="124" y="324" on="0"/>
<pt x="104" y="324" on="1"/>
<pt x="62" y="324" on="0"/>
<pt x="59" y="364" on="1"/>
<pt x="73" y="421" on="0"/>
<pt x="177" y="487" on="0"/>
<pt x="252" y="487" on="1"/>
<pt x="329" y="487" on="0"/>
<pt x="405" y="408" on="0"/>
<pt x="405" y="314" on="1"/>
<pt x="405" y="102" on="1"/>
<pt x="405" y="68" on="0"/>
<pt x="425" y="41" on="0"/>
<pt x="442" y="41" on="1"/>
<pt x="455" y="41" on="0"/>
<pt x="473" y="53" on="0"/>
<pt x="481" y="63" on="1"/>
<pt x="501" y="41" on="1"/>
<pt x="469" y="-10" on="0"/>
<pt x="416" y="-10" on="1"/>
<pt x="375" y="-10" on="0"/>
<pt x="325" y="46" on="0"/>
</contour>
<instructions/>
</TTGlyph>
</glyf>
<name>
<namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
Test Family
</namerecord>
<namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
Regular
</namerecord>
<namerecord nameID="3" platformID="3" platEncID="1" langID="0x409">
Version 1.001;ADBO;Test Family Regular
</namerecord>
<namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
Test Family
</namerecord>
<namerecord nameID="5" platformID="3" platEncID="1" langID="0x409">
Version 1.001
</namerecord>
<namerecord nameID="6" platformID="3" platEncID="1" langID="0x409">
TestFamily-Master1
</namerecord>
<namerecord nameID="9" platformID="3" platEncID="1" langID="0x409">
Frank Grießhammer
</namerecord>
<namerecord nameID="17" platformID="3" platEncID="1" langID="0x409">
Master 1
</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 -->
<psName name="uni0020"/>
<psName name="uni0061"/>
</extraNames>
</post>
<GDEF>
<Version value="0x00010003"/>
<GlyphClassDef>
<ClassDef glyph="uni0061" class="1"/>
</GlyphClassDef>
</GDEF>
</ttFont>

View File

@ -0,0 +1,313 @@
<?xml version="1.0" encoding="UTF-8"?>
<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="3.7">
<GlyphOrder>
<!-- The 'id' attribute is only for humans; it is ignored when parsed. -->
<GlyphID id="0" name=".notdef"/>
<GlyphID id="1" name="uni0020"/>
<GlyphID id="2" name="uni0061"/>
</GlyphOrder>
<head>
<!-- Most of this table will be recalculated by the compiler -->
<tableVersion value="1.0"/>
<fontRevision value="1.001"/>
<checkSumAdjustment value="0x4b3253f0"/>
<magicNumber value="0x5f0f3cf5"/>
<flags value="00000000 00000011"/>
<unitsPerEm value="1000"/>
<created value="Tue Feb 28 16:48:24 2017"/>
<modified value="Tue Feb 28 16:48:24 2017"/>
<xMin value="10"/>
<yMin value="-115"/>
<xMax value="665"/>
<yMax value="731"/>
<macStyle value="00000000 00000000"/>
<lowestRecPPEM value="6"/>
<fontDirectionHint value="2"/>
<indexToLocFormat value="0"/>
<glyphDataFormat value="0"/>
</head>
<hhea>
<tableVersion value="0x00010000"/>
<ascent value="918"/>
<descent value="-335"/>
<lineGap value="0"/>
<advanceWidthMax value="680"/>
<minLeftSideBearing value="10"/>
<minRightSideBearing value="-8"/>
<xMaxExtent value="665"/>
<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="5"/>
</hhea>
<maxp>
<!-- Most of this table will be recalculated by the compiler -->
<tableVersion value="0x10000"/>
<numGlyphs value="3"/>
<maxPoints value="60"/>
<maxContours value="4"/>
<maxCompositePoints value="0"/>
<maxCompositeContours value="0"/>
<maxZones value="1"/>
<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>
<OS_2>
<!-- The fields 'usFirstCharIndex' and 'usLastCharIndex'
will be recalculated by the compiler -->
<version value="4"/>
<xAvgCharWidth value="531"/>
<usWeightClass value="900"/>
<usWidthClass value="5"/>
<fsType value="00000000 00000100"/>
<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="292"/>
<sFamilyClass value="0"/>
<panose>
<bFamilyType value="2"/>
<bSerifStyle value="4"/>
<bWeight value="9"/>
<bProportion value="3"/>
<bContrast value="5"/>
<bStrokeVariation value="4"/>
<bArmStyle value="5"/>
<bLetterForm value="2"/>
<bMidline value="2"/>
<bXHeight value="4"/>
</panose>
<ulUnicodeRange1 value="00000000 00000000 00000000 00000011"/>
<ulUnicodeRange2 value="00000000 00000000 00000000 00000000"/>
<ulUnicodeRange3 value="00000000 00000000 00000000 00000000"/>
<ulUnicodeRange4 value="00000000 00000000 00000000 00000000"/>
<achVendID value="ADBO"/>
<fsSelection value="00000000 01000000"/>
<usFirstCharIndex value="32"/>
<usLastCharIndex value="97"/>
<sTypoAscender value="730"/>
<sTypoDescender value="-270"/>
<sTypoLineGap value="0"/>
<usWinAscent value="918"/>
<usWinDescent value="335"/>
<ulCodePageRange1 value="00100000 00000000 00000000 00000011"/>
<ulCodePageRange2 value="00000000 00000000 00000000 00000000"/>
<sxHeight value="487"/>
<sCapHeight value="677"/>
<usDefaultChar value="0"/>
<usBreakChar value="32"/>
<usMaxContext value="0"/>
</OS_2>
<hmtx>
<mtx name=".notdef" width="640" lsb="80"/>
<mtx name="uni0020" width="206" lsb="0"/>
<mtx name="uni0061" width="540" lsb="25"/>
</hmtx>
<cmap>
<tableVersion version="0"/>
<cmap_format_4 platformID="0" platEncID="3" language="0">
<map code="0x20" name="uni0020"/><!-- SPACE -->
<map code="0x61" name="uni0061"/><!-- LATIN SMALL LETTER A -->
</cmap_format_4>
<cmap_format_4 platformID="3" platEncID="1" language="0">
<map code="0x20" name="uni0020"/><!-- SPACE -->
<map code="0x61" name="uni0061"/><!-- LATIN SMALL LETTER A -->
</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="560" yMax="652">
<contour>
<pt x="80" y="0" on="1"/>
<pt x="480" y="652" on="1"/>
<pt x="560" y="652" on="1"/>
<pt x="160" y="0" on="1"/>
</contour>
<contour>
<pt x="560" y="0" on="1"/>
<pt x="480" y="0" on="1"/>
<pt x="80" y="652" on="1"/>
<pt x="160" y="652" on="1"/>
</contour>
<contour>
<pt x="150" y="60" on="1"/>
<pt x="490" y="60" on="1"/>
<pt x="490" y="592" on="1"/>
<pt x="150" y="592" on="1"/>
</contour>
<contour>
<pt x="80" y="0" on="1"/>
<pt x="80" y="652" on="1"/>
<pt x="560" y="652" on="1"/>
<pt x="560" y="0" on="1"/>
</contour>
<instructions/>
</TTGlyph>
<TTGlyph name="uni0020"/><!-- contains no outline data -->
<TTGlyph name="uni0061" xMin="25" yMin="-16" xMax="548" yMax="503">
<contour>
<pt x="25" y="111" on="1"/>
<pt x="25" y="170" on="0"/>
<pt x="108" y="253" on="0"/>
<pt x="230" y="285" on="1"/>
<pt x="261" y="293" on="0"/>
<pt x="356" y="318" on="0"/>
<pt x="391" y="327" on="1"/>
<pt x="391" y="283" on="1"/>
<pt x="355" y="273" on="0"/>
<pt x="284" y="254" on="0"/>
<pt x="262" y="243" on="1"/>
<pt x="241" y="233" on="0"/>
<pt x="197" y="184" on="0"/>
<pt x="197" y="144" on="1"/>
<pt x="197" y="107" on="0"/>
<pt x="227" y="71" on="0"/>
<pt x="249" y="71" on="1"/>
<pt x="259" y="71" on="0"/>
<pt x="281" y="81" on="0"/>
<pt x="296" y="92" on="1"/>
<pt x="344" y="128" on="1"/>
<pt x="353" y="116" on="1"/>
<pt x="306" y="64" on="1"/>
<pt x="273" y="28" on="0"/>
<pt x="213" y="-16" on="0"/>
<pt x="155" y="-16" on="1"/>
<pt x="96" y="-16" on="0"/>
<pt x="25" y="52" on="0"/>
</contour>
<contour>
<pt x="291" y="78" on="1"/>
<pt x="291" y="337" on="1"/>
<pt x="291" y="401" on="0"/>
<pt x="262" y="449" on="0"/>
<pt x="215" y="449" on="1"/>
<pt x="196" y="449" on="0"/>
<pt x="154" y="444" on="0"/>
<pt x="120" y="436" on="1"/>
<pt x="200" y="478" on="1"/>
<pt x="200" y="415" on="1"/>
<pt x="200" y="354" on="0"/>
<pt x="150" y="303" on="0"/>
<pt x="118" y="303" on="1"/>
<pt x="57" y="303" on="0"/>
<pt x="42" y="357" on="1"/>
<pt x="42" y="422" on="0"/>
<pt x="165" y="503" on="0"/>
<pt x="286" y="503" on="1"/>
<pt x="390" y="503" on="0"/>
<pt x="475" y="412" on="0"/>
<pt x="475" y="309" on="1"/>
<pt x="475" y="80" on="1"/>
<pt x="475" y="72" on="0"/>
<pt x="484" y="63" on="0"/>
<pt x="492" y="63" on="1"/>
<pt x="498" y="63" on="0"/>
<pt x="510" y="72" on="0"/>
<pt x="519" y="85" on="1"/>
<pt x="548" y="69" on="1"/>
<pt x="515" y="-16" on="0"/>
<pt x="414" y="-16" on="1"/>
<pt x="359" y="-16" on="0"/>
<pt x="300" y="33" on="0"/>
</contour>
<instructions/>
</TTGlyph>
</glyf>
<name>
<namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
Test Family
</namerecord>
<namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
Regular
</namerecord>
<namerecord nameID="3" platformID="3" platEncID="1" langID="0x409">
Version 1.001;ADBO;Test Family Regular
</namerecord>
<namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
Test Family
</namerecord>
<namerecord nameID="5" platformID="3" platEncID="1" langID="0x409">
Version 1.001
</namerecord>
<namerecord nameID="6" platformID="3" platEncID="1" langID="0x409">
TestFamily-Master2
</namerecord>
<namerecord nameID="9" platformID="3" platEncID="1" langID="0x409">
Frank Grießhammer
</namerecord>
<namerecord nameID="17" platformID="3" platEncID="1" langID="0x409">
Master 2
</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 -->
<psName name="dollar.nostroke"/>
<psName name="uni0020"/>
<psName name="uni0061"/>
</extraNames>
</post>
<GDEF>
<Version value="0x00010003"/>
<GlyphClassDef>
<ClassDef glyph="uni0061" class="1"/>
</GlyphClassDef>
</GDEF>
</ttFont>

View File

@ -0,0 +1,498 @@
<?xml version="1.0" encoding="UTF-8"?>
<ttFont>
<GlyphOrder>
<!-- The 'id' attribute is only for humans; it is ignored when parsed. -->
<GlyphID id="0" name=".notdef"/>
<GlyphID id="1" name="uni0020"/>
<GlyphID id="2" name="uni0061"/>
</GlyphOrder>
<hhea>
<tableVersion value="0x00010000"/>
<ascent value="918"/>
<descent value="-335"/>
<lineGap value="0"/>
<advanceWidthMax value="640"/>
<minLeftSideBearing value="46"/>
<minRightSideBearing value="7"/>
<xMaxExtent value="560"/>
<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="3"/>
</hhea>
<maxp>
<!-- Most of this table will be recalculated by the compiler -->
<tableVersion value="0x10000"/>
<numGlyphs value="3"/>
<maxPoints value="60"/>
<maxContours value="4"/>
<maxCompositePoints value="0"/>
<maxCompositeContours value="0"/>
<maxZones value="1"/>
<maxTwilightPoints value="0"/>
<maxStorage value="0"/>
<maxFunctionDefs value="1"/>
<maxInstructionDefs value="0"/>
<maxStackElements value="1"/>
<maxSizeOfInstructions value="5"/>
<maxComponentElements value="0"/>
<maxComponentDepth value="0"/>
</maxp>
<OS_2>
<!-- The fields 'usFirstCharIndex' and 'usLastCharIndex'
will be recalculated by the compiler -->
<version value="4"/>
<xAvgCharWidth value="506"/>
<usWeightClass value="400"/>
<usWidthClass value="5"/>
<fsType value="00000000 00000100"/>
<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="284"/>
<sFamilyClass value="0"/>
<panose>
<bFamilyType value="2"/>
<bSerifStyle value="4"/>
<bWeight value="6"/>
<bProportion value="3"/>
<bContrast value="5"/>
<bStrokeVariation value="4"/>
<bArmStyle value="5"/>
<bLetterForm value="2"/>
<bMidline value="2"/>
<bXHeight value="4"/>
</panose>
<ulUnicodeRange1 value="00000000 00000000 00000000 00000011"/>
<ulUnicodeRange2 value="00000000 00000000 00000000 00000000"/>
<ulUnicodeRange3 value="00000000 00000000 00000000 00000000"/>
<ulUnicodeRange4 value="00000000 00000000 00000000 00000000"/>
<achVendID value="ADBO"/>
<fsSelection value="00000000 01000000"/>
<usFirstCharIndex value="32"/>
<usLastCharIndex value="97"/>
<sTypoAscender value="730"/>
<sTypoDescender value="-270"/>
<sTypoLineGap value="0"/>
<usWinAscent value="918"/>
<usWinDescent value="335"/>
<ulCodePageRange1 value="00100000 00000000 00000000 00000011"/>
<ulCodePageRange2 value="00000000 00000000 00000000 00000000"/>
<sxHeight value="474"/>
<sCapHeight value="677"/>
<usDefaultChar value="0"/>
<usBreakChar value="32"/>
<usMaxContext value="0"/>
</OS_2>
<hmtx>
<mtx name=".notdef" width="640" lsb="80"/>
<mtx name="uni0020" width="234" lsb="0"/>
<mtx name="uni0061" width="508" lsb="46"/>
</hmtx>
<cmap>
<tableVersion version="0"/>
<cmap_format_4 platformID="0" platEncID="3" language="0">
<map code="0x20" name="uni0020"/><!-- SPACE -->
<map code="0x61" name="uni0061"/><!-- LATIN SMALL LETTER A -->
</cmap_format_4>
<cmap_format_4 platformID="3" platEncID="1" language="0">
<map code="0x20" name="uni0020"/><!-- SPACE -->
<map code="0x61" name="uni0061"/><!-- LATIN SMALL LETTER A -->
</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="560" yMax="670">
<contour>
<pt x="80" y="0" on="1"/>
<pt x="500" y="670" on="1"/>
<pt x="560" y="670" on="1"/>
<pt x="140" y="0" on="1"/>
</contour>
<contour>
<pt x="560" y="0" on="1"/>
<pt x="500" y="0" on="1"/>
<pt x="80" y="670" on="1"/>
<pt x="140" y="670" on="1"/>
</contour>
<contour>
<pt x="140" y="50" on="1"/>
<pt x="500" y="50" on="1"/>
<pt x="500" y="620" on="1"/>
<pt x="140" y="620" on="1"/>
</contour>
<contour>
<pt x="80" y="0" on="1"/>
<pt x="80" y="670" on="1"/>
<pt x="560" y="670" on="1"/>
<pt x="560" y="0" on="1"/>
</contour>
<instructions/>
</TTGlyph>
<TTGlyph name="uni0020"/><!-- contains no outline data -->
<TTGlyph name="uni0061" xMin="46" yMin="-13" xMax="501" yMax="487">
<contour>
<pt x="46" y="154" on="0"/>
<pt x="110" y="225" on="0"/>
<pt x="210" y="262" on="1"/>
<pt x="242" y="273" on="0"/>
<pt x="328" y="297" on="0"/>
<pt x="365" y="304" on="1"/>
<pt x="365" y="268" on="1"/>
<pt x="331" y="261" on="0"/>
<pt x="254" y="237" on="0"/>
<pt x="231" y="228" on="1"/>
<pt x="164" y="202" on="0"/>
<pt x="131" y="148" on="0"/>
<pt x="131" y="126" on="1"/>
<pt x="131" y="86" on="0"/>
<pt x="178" y="52" on="0"/>
<pt x="212" y="52" on="1"/>
<pt x="238" y="52" on="0"/>
<pt x="283" y="76" on="0"/>
<pt x="330" y="110" on="1"/>
<pt x="350" y="125" on="1"/>
<pt x="364" y="104" on="1"/>
<pt x="335" y="75" on="1"/>
<pt x="290" y="30" on="0"/>
<pt x="226" y="-13" on="0"/>
<pt x="180" y="-13" on="1"/>
<pt x="125" y="-13" on="0"/>
<pt x="46" y="50" on="0"/>
</contour>
<contour>
<pt x="325" y="92" on="1"/>
<pt x="325" y="320" on="1"/>
<pt x="325" y="394" on="0"/>
<pt x="280" y="442" on="0"/>
<pt x="231" y="442" on="1"/>
<pt x="214" y="442" on="0"/>
<pt x="169" y="435" on="0"/>
<pt x="141" y="424" on="1"/>
<pt x="181" y="455" on="1"/>
<pt x="155" y="369" on="1"/>
<pt x="148" y="347" on="0"/>
<pt x="124" y="324" on="0"/>
<pt x="104" y="324" on="1"/>
<pt x="62" y="324" on="0"/>
<pt x="59" y="364" on="1"/>
<pt x="73" y="421" on="0"/>
<pt x="177" y="487" on="0"/>
<pt x="252" y="487" on="1"/>
<pt x="329" y="487" on="0"/>
<pt x="405" y="408" on="0"/>
<pt x="405" y="314" on="1"/>
<pt x="405" y="102" on="1"/>
<pt x="405" y="68" on="0"/>
<pt x="425" y="41" on="0"/>
<pt x="442" y="41" on="1"/>
<pt x="455" y="41" on="0"/>
<pt x="473" y="53" on="0"/>
<pt x="481" y="63" on="1"/>
<pt x="501" y="41" on="1"/>
<pt x="469" y="-10" on="0"/>
<pt x="416" y="-10" on="1"/>
<pt x="375" y="-10" on="0"/>
<pt x="325" y="46" on="0"/>
</contour>
<instructions/>
</TTGlyph>
</glyf>
<name>
<namerecord nameID="256" platformID="1" platEncID="0" langID="0x0" unicode="True">
Weight
</namerecord>
<namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
Test Family
</namerecord>
<namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
Regular
</namerecord>
<namerecord nameID="3" platformID="3" platEncID="1" langID="0x409">
Version 1.001;ADBO;Test Family Regular
</namerecord>
<namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
Test Family
</namerecord>
<namerecord nameID="5" platformID="3" platEncID="1" langID="0x409">
Version 1.001
</namerecord>
<namerecord nameID="6" platformID="3" platEncID="1" langID="0x409">
TestFamily-Master1
</namerecord>
<namerecord nameID="9" platformID="3" platEncID="1" langID="0x409">
Frank Grießhammer
</namerecord>
<namerecord nameID="17" platformID="3" platEncID="1" langID="0x409">
Master 1
</namerecord>
<namerecord nameID="256" platformID="3" platEncID="1" langID="0x409">
Weight
</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 -->
<psName name="uni0020"/>
<psName name="uni0061"/>
</extraNames>
</post>
<GDEF>
<Version value="0x00010003"/>
<GlyphClassDef>
<ClassDef glyph="uni0061" class="1"/>
</GlyphClassDef>
</GDEF>
<HVAR>
<Version value="0x00010000"/>
<VarStore Format="1">
<Format value="1"/>
<VarRegionList>
<!-- RegionAxisCount=1 -->
<!-- RegionCount=1 -->
<Region index="0">
<VarRegionAxis index="0">
<StartCoord value="0.0"/>
<PeakCoord value="1.0"/>
<EndCoord value="1.0"/>
</VarRegionAxis>
</Region>
</VarRegionList>
<!-- VarDataCount=1 -->
<VarData index="0">
<!-- ItemCount=3 -->
<NumShorts value="0"/>
<!-- VarRegionCount=1 -->
<VarRegionIndex index="0" value="0"/>
<Item index="0" value="[0]"/>
<Item index="1" value="[-28]"/>
<Item index="2" value="[32]"/>
</VarData>
</VarStore>
</HVAR>
<MVAR>
<Version value="0x00010000"/>
<Reserved value="0"/>
<ValueRecordSize value="8"/>
<!-- ValueRecordCount=2 -->
<VarStore Format="1">
<Format value="1"/>
<VarRegionList>
<!-- RegionAxisCount=1 -->
<!-- RegionCount=1 -->
<Region index="0">
<VarRegionAxis index="0">
<StartCoord value="0.0"/>
<PeakCoord value="1.0"/>
<EndCoord value="1.0"/>
</VarRegionAxis>
</Region>
</VarRegionList>
<!-- VarDataCount=1 -->
<VarData index="0">
<!-- ItemCount=2 -->
<NumShorts value="0"/>
<!-- VarRegionCount=1 -->
<VarRegionIndex index="0" value="0"/>
<Item index="0" value="[8]"/>
<Item index="1" value="[13]"/>
</VarData>
</VarStore>
<ValueRecord index="0">
<ValueTag value="stro"/>
<VarIdx value="0"/>
</ValueRecord>
<ValueRecord index="1">
<ValueTag value="xhgt"/>
<VarIdx value="1"/>
</ValueRecord>
</MVAR>
<STAT>
<Version value="0x00010001"/>
<DesignAxisRecordSize value="8"/>
<!-- DesignAxisCount=1 -->
<DesignAxisRecord>
<Axis index="0">
<AxisTag value="wght"/>
<AxisNameID value="256"/> <!-- Weight -->
<AxisOrdering value="0"/>
</Axis>
</DesignAxisRecord>
<!-- AxisValueCount=0 -->
<ElidedFallbackNameID value="2"/> <!-- Regular -->
</STAT>
<fvar>
<!-- Weight -->
<Axis>
<AxisTag>wght</AxisTag>
<Flags>0x0</Flags>
<MinValue>400.0</MinValue>
<DefaultValue>400.0</DefaultValue>
<MaxValue>1000.0</MaxValue>
<AxisNameID>256</AxisNameID>
</Axis>
</fvar>
<gvar>
<version value="1"/>
<reserved value="0"/>
<glyphVariations glyph=".notdef">
<tuple>
<coord axis="wght" value="1.0"/>
<delta pt="0" x="0" y="0"/>
<delta pt="1" x="-20" y="-18"/>
<delta pt="2" x="0" y="-18"/>
<delta pt="3" x="20" y="0"/>
<delta pt="4" x="0" y="0"/>
<delta pt="5" x="-20" y="0"/>
<delta pt="6" x="0" y="-18"/>
<delta pt="7" x="20" y="-18"/>
<delta pt="8" x="10" y="10"/>
<delta pt="9" x="-10" y="10"/>
<delta pt="10" x="-10" y="-28"/>
<delta pt="11" x="10" y="-28"/>
<delta pt="12" x="0" y="0"/>
<delta pt="13" x="0" y="-18"/>
<delta pt="14" x="0" y="-18"/>
<delta pt="15" x="0" y="0"/>
<delta pt="16" x="0" y="0"/>
<delta pt="17" x="0" y="0"/>
<delta pt="18" x="0" y="0"/>
<delta pt="19" x="0" y="0"/>
</tuple>
</glyphVariations>
<glyphVariations glyph="uni0020">
<tuple>
<coord axis="wght" value="1.0"/>
<delta pt="0" x="0" y="0"/>
<delta pt="1" x="-28" y="0"/>
<delta pt="2" x="0" y="0"/>
<delta pt="3" x="0" y="0"/>
</tuple>
</glyphVariations>
<glyphVariations glyph="uni0061">
<tuple>
<coord axis="wght" value="1.0"/>
<delta pt="0" x="-21" y="16"/>
<delta pt="1" x="-2" y="28"/>
<delta pt="2" x="20" y="23"/>
<delta pt="3" x="19" y="20"/>
<delta pt="4" x="28" y="21"/>
<delta pt="5" x="26" y="23"/>
<delta pt="6" x="26" y="15"/>
<delta pt="7" x="24" y="12"/>
<delta pt="8" x="30" y="17"/>
<delta pt="9" x="31" y="15"/>
<delta pt="10" x="77" y="31"/>
<delta pt="11" x="66" y="36"/>
<delta pt="12" x="66" y="18"/>
<delta pt="13" x="66" y="21"/>
<delta pt="14" x="49" y="19"/>
<delta pt="15" x="37" y="19"/>
<delta pt="16" x="21" y="19"/>
<delta pt="17" x="-2" y="5"/>
<delta pt="18" x="-34" y="-18"/>
<delta pt="19" x="-6" y="3"/>
<delta pt="20" x="-11" y="12"/>
<delta pt="21" x="-29" y="-11"/>
<delta pt="22" x="-17" y="-2"/>
<delta pt="23" x="-13" y="-3"/>
<delta pt="24" x="-25" y="-3"/>
<delta pt="25" x="-29" y="-3"/>
<delta pt="26" x="-21" y="2"/>
<delta pt="27" x="-34" y="-14"/>
<delta pt="28" x="-34" y="17"/>
<delta pt="29" x="-34" y="7"/>
<delta pt="30" x="-18" y="7"/>
<delta pt="31" x="-16" y="7"/>
<delta pt="32" x="-18" y="7"/>
<delta pt="33" x="-15" y="9"/>
<delta pt="34" x="-21" y="12"/>
<delta pt="35" x="19" y="23"/>
<delta pt="36" x="45" y="46"/>
<delta pt="37" x="52" y="7"/>
<delta pt="38" x="26" y="-21"/>
<delta pt="39" x="14" y="-21"/>
<delta pt="40" x="-5" y="-21"/>
<delta pt="41" x="-17" y="-7"/>
<delta pt="42" x="-31" y="1"/>
<delta pt="43" x="-12" y="16"/>
<delta pt="44" x="34" y="16"/>
<delta pt="45" x="61" y="16"/>
<delta pt="46" x="70" y="4"/>
<delta pt="47" x="70" y="-5"/>
<delta pt="48" x="70" y="-22"/>
<delta pt="49" x="70" y="4"/>
<delta pt="50" x="59" y="22"/>
<delta pt="51" x="50" y="22"/>
<delta pt="52" x="43" y="22"/>
<delta pt="53" x="37" y="19"/>
<delta pt="54" x="38" y="22"/>
<delta pt="55" x="47" y="28"/>
<delta pt="56" x="46" y="-6"/>
<delta pt="57" x="-2" y="-6"/>
<delta pt="58" x="-16" y="-6"/>
<delta pt="59" x="-25" y="-13"/>
<delta pt="60" x="0" y="0"/>
<delta pt="61" x="32" y="0"/>
<delta pt="62" x="0" y="0"/>
<delta pt="63" x="0" y="0"/>
</tuple>
</glyphVariations>
</gvar>
</ttFont>

View File

@ -538,6 +538,31 @@ class BuildTest(unittest.TestCase):
self.assertTrue(os.path.isdir(outdir))
self.assertTrue(os.path.exists(os.path.join(outdir, "BuildMain-VF.ttf")))
def test_varLib_main_drop_implied_oncurves(self):
self.temp_dir()
outdir = os.path.join(self.tempdir, "drop_implied_oncurves_test")
self.assertFalse(os.path.exists(outdir))
ttf_dir = os.path.join(outdir, "master_ttf_interpolatable")
os.makedirs(ttf_dir)
ttx_dir = self.get_test_input("master_ttx_drop_oncurves")
ttx_paths = self.get_file_list(ttx_dir, ".ttx", "TestFamily-")
for path in ttx_paths:
self.compile_font(path, ".ttf", ttf_dir)
ds_copy = os.path.join(outdir, "DropOnCurves.designspace")
ds_path = self.get_test_input("DropOnCurves.designspace")
shutil.copy2(ds_path, ds_copy)
finder = "%s/master_ttf_interpolatable/{stem}.ttf" % outdir
varLib_main([ds_copy, "--master-finder", finder, "--drop-implied-oncurves"])
vf_path = os.path.join(outdir, "DropOnCurves-VF.ttf")
varfont = TTFont(vf_path)
tables = [table_tag for table_tag in varfont.keys() if table_tag != "head"]
expected_ttx_path = self.get_test_output("DropOnCurves.ttx")
self.expect_ttx(varfont, expected_ttx_path, tables)
def test_varLib_build_many_no_overwrite_STAT(self):
# Ensure that varLib.build_many doesn't overwrite a pre-existing STAT table,
# e.g. one built by feaLib from features.fea; the VF simply should inherit the