Merge pull request #3075 from colinmford/main

[varLib.interpolatable] Allow for sparse masters
This commit is contained in:
Cosimo Lupo 2023-04-06 21:15:37 +01:00 committed by GitHub
commit 1c283756a5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
37 changed files with 4187 additions and 86 deletions

View File

@ -137,12 +137,14 @@ def min_cost_perfect_bipartite_matching(G):
return best, best_cost
def test(glyphsets, glyphs=None, names=None):
def test(glyphsets, glyphs=None, names=None, ignore_missing=False):
if names is None:
names = glyphsets
if glyphs is None:
glyphs = glyphsets[0].keys()
# `glyphs = glyphsets[0].keys()` is faster, certainly, but doesn't allow for sparse TTFs/OTFs given out of order
# ... risks the sparse master being the first one, and only processing a subset of the glyphs
glyphs = {g for glyphset in glyphsets for g in glyphset.keys()}
hist = []
problems = OrderedDict()
@ -151,20 +153,23 @@ def test(glyphsets, glyphs=None, names=None):
problems.setdefault(glyphname, []).append(problem)
for glyph_name in glyphs:
# print()
# print(glyph_name)
try:
m0idx = 0
allVectors = []
allNodeTypes = []
allContourIsomorphisms = []
for glyphset, name in zip(glyphsets, names):
# print('.', end='')
if glyph_name not in glyphset:
add_problem(glyph_name, {"type": "missing", "master": name})
continue
glyph = glyphset[glyph_name]
if glyph is None:
if not ignore_missing:
add_problem(glyph_name, {"type": "missing", "master": name})
allNodeTypes.append(None)
allVectors.append(None)
allContourIsomorphisms.append(None)
continue
perContourPen = PerContourOrComponentPen(
RecordingPen, glyphset=glyphset
)
@ -243,16 +248,23 @@ def test(glyphsets, glyphs=None, names=None):
_rot_list([complex(*pt) for pt, bl in mirrored], i)
)
# Check each master against the first on in the list.
m0 = allNodeTypes[0]
for i, m1 in enumerate(allNodeTypes[1:]):
# m0idx should be the index of the first non-None item in allNodeTypes,
# else give it the first index of None, which is likely 0
m0idx = allNodeTypes.index(
next((x for x in allNodeTypes if x is not None), None)
)
# m0 is the first non-None item in allNodeTypes, or the first item if all are None
m0 = allNodeTypes[m0idx]
for i, m1 in enumerate(allNodeTypes[m0idx + 1 :]):
if m1 is None:
continue
if len(m0) != len(m1):
add_problem(
glyph_name,
{
"type": "path_count",
"master_1": names[0],
"master_2": names[i + 1],
"master_1": names[m0idx],
"master_2": names[m0idx + i + 1],
"value_1": len(m0),
"value_2": len(m1),
},
@ -268,8 +280,8 @@ def test(glyphsets, glyphs=None, names=None):
{
"type": "node_count",
"path": pathIx,
"master_1": names[0],
"master_2": names[i + 1],
"master_1": names[m0idx],
"master_2": names[m0idx + i + 1],
"value_1": len(nodes1),
"value_2": len(nodes2),
},
@ -283,16 +295,24 @@ def test(glyphsets, glyphs=None, names=None):
"type": "node_incompatibility",
"path": pathIx,
"node": nodeIx,
"master_1": names[0],
"master_2": names[i + 1],
"master_1": names[m0idx],
"master_2": names[m0idx + i + 1],
"value_1": n1,
"value_2": n2,
},
)
continue
m0 = allVectors[0]
for i, m1 in enumerate(allVectors[1:]):
# m0idx should be the index of the first non-None item in allVectors,
# else give it the first index of None, which is likely 0
m0idx = allVectors.index(
next((x for x in allVectors if x is not None), None)
)
# m0 is the first non-None item in allVectors, or the first item if all are None
m0 = allVectors[m0idx]
for i, m1 in enumerate(allVectors[m0idx + 1 :]):
if m1 is None:
continue
if len(m0) != len(m1):
# We already reported this
continue
@ -310,16 +330,24 @@ def test(glyphsets, glyphs=None, names=None):
glyph_name,
{
"type": "contour_order",
"master_1": names[0],
"master_2": names[i + 1],
"master_1": names[m0idx],
"master_2": names[m0idx + i + 1],
"value_1": list(range(len(m0))),
"value_2": matching,
},
)
break
m0 = allContourIsomorphisms[0]
for i, m1 in enumerate(allContourIsomorphisms[1:]):
# m0idx should be the index of the first non-None item in allContourIsomorphisms,
# else give it the first index of None, which is likely 0
m0idx = allContourIsomorphisms.index(
next((x for x in allContourIsomorphisms if x is not None), None)
)
# m0 is the first non-None item in allContourIsomorphisms, or the first item if all are None
m0 = allContourIsomorphisms[m0idx]
for i, m1 in enumerate(allContourIsomorphisms[m0idx + 1 :]):
if m1 is None:
continue
if len(m0) != len(m1):
# We already reported this
continue
@ -338,8 +366,8 @@ def test(glyphsets, glyphs=None, names=None):
{
"type": "wrong_start_point",
"contour": ix,
"master_1": names[0],
"master_2": names[i + 1],
"master_1": names[m0idx],
"master_2": names[m0idx + i + 1],
},
)
@ -365,7 +393,21 @@ def main(args=None):
help="Output report in JSON format",
)
parser.add_argument(
"inputs", metavar="FILE", type=str, nargs="+", help="Input TTF/UFO files"
"--quiet",
action="store_true",
help="Only exit with code 1 or 0, no output",
)
parser.add_argument(
"--ignore-missing",
action="store_true",
help="Will not report glyphs missing from sparse masters as errors",
)
parser.add_argument(
"inputs",
metavar="FILE",
type=str,
nargs="+",
help="Input a single DesignSpace/Glyphs file, or multiple TTF/UFO files",
)
args = parser.parse_args(args)
@ -439,12 +481,29 @@ def main(args=None):
names.append(basename(filename).rsplit(".", 1)[0])
if hasattr(fonts[0], "getGlyphSet"):
glyphsets = [font.getGlyphSet() for font in fonts]
glyphsets = []
for font in fonts:
if hasattr(font, "getGlyphSet"):
glyphset = font.getGlyphSet()
else:
glyphsets = fonts
glyphset = font
glyphsets.append({k: glyphset[k] for k in glyphset.keys()})
problems = test(glyphsets, glyphs=glyphs, names=names)
if not glyphs:
glyphs = set([gn for glyphset in glyphsets for gn in glyphset.keys()])
for glyphset in glyphsets:
glyphSetGlyphNames = set(glyphset.keys())
diff = glyphs - glyphSetGlyphNames
if diff:
for gn in diff:
glyphset[gn] = None
problems = test(
glyphsets, glyphs=glyphs, names=names, ignore_missing=args.ignore_missing
)
if not args.quiet:
if args.json:
import json
@ -504,6 +563,14 @@ def main(args=None):
p["master_2"],
)
)
if p["type"] == "math_error":
print(
" Miscellaneous error in %s: %s"
% (
p["master"],
p["error"],
)
)
if problems:
return problems

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,486 @@
{
.appVersion = "895";
customParameters = (
{
name = glyphOrder;
value = (
.notdef,
a,
e,
edotabove,
s,
dotabovecomb
);
},
{
name = "Disable Last Change";
value = 1;
}
);
disablesAutomaticAlignment = 1;
familyName = "Sparse Masters";
fontMaster = (
{
ascender = 750;
capHeight = 700;
customParameters = (
{
name = "UFO Filename";
value = "master_ufo/SparseMasters-Regular.ufo";
}
);
descender = -250;
id = "CCC32AD0-E3D7-4595-BA12-BA39A95902C9";
userData = {
com.defcon.sortDescriptor = (
{
ascending = (
.notdef,
a,
e,
edotabove,
s,
dotabovecomb
);
type = glyphList;
}
);
};
weightValue = 350;
xHeight = 500;
},
{
ascender = 750;
capHeight = 700;
customParameters = (
{
name = "UFO Filename";
value = "master_ufo/SparseMasters-Medium.ufo";
},
{
name = "Master Name";
value = Medium;
}
);
descender = -250;
id = "2B2F6A55-E8C4-4456-AFD7-7A9468BB18B9";
userData = {
};
weightValue = 450;
xHeight = 500;
},
{
ascender = 750;
capHeight = 700;
customParameters = (
{
name = "UFO Filename";
value = "master_ufo/SparseMasters-Bold.ufo";
},
{
name = "Master Name";
value = Bold;
}
);
descender = -250;
id = "36D5BF76-782C-4F60-A6DB-0A9BC5828108";
userData = {
com.defcon.sortDescriptor = (
{
ascending = (
.notdef,
a,
e,
edotabove,
s,
dotabovecomb
);
type = glyphList;
}
);
};
weightValue = 625;
xHeight = 500;
}
);
glyphs = (
{
glyphname = .notdef;
layers = (
{
layerId = "CCC32AD0-E3D7-4595-BA12-BA39A95902C9";
paths = (
{
closed = 1;
nodes = (
"450 750 LINE",
"450 -250 LINE",
"50 -250 LINE",
"50 750 LINE"
);
},
{
closed = 1;
nodes = (
"400 700 LINE",
"100 700 LINE",
"100 -200 LINE",
"400 -200 LINE"
);
}
);
vertWidth = 0;
width = 500;
},
{
layerId = "2B2F6A55-E8C4-4456-AFD7-7A9468BB18B9";
paths = (
{
closed = 1;
nodes = (
"450 750 LINE",
"450 -250 LINE",
"50 -250 LINE",
"50 750 LINE"
);
},
{
closed = 1;
nodes = (
"400 700 LINE",
"100 700 LINE",
"100 -200 LINE",
"400 -200 LINE"
);
}
);
vertWidth = 0;
width = 500;
},
{
layerId = "36D5BF76-782C-4F60-A6DB-0A9BC5828108";
paths = (
{
closed = 1;
nodes = (
"450 750 LINE",
"450 -250 LINE",
"50 -250 LINE",
"50 750 LINE"
);
},
{
closed = 1;
nodes = (
"400 700 LINE",
"100 700 LINE",
"100 -200 LINE",
"400 -200 LINE"
);
}
);
vertWidth = 0;
width = 500;
}
);
note = .notdef;
},
{
glyphname = a;
layers = (
{
layerId = "CCC32AD0-E3D7-4595-BA12-BA39A95902C9";
paths = (
{
closed = 1;
nodes = (
"214 504 LINE",
"9 428 LINE",
"36 337 LINE",
"208 397 LINE",
"363 357 LINE",
"366 -3 LINE",
"468 -1 LINE",
"447 434 LINE"
);
},
{
closed = 1;
nodes = (
"29 22 LINE",
"168 -12 LINE",
"389 71 LINE",
"383 134 LINE",
"161 74 LINE",
"86 126 LINE",
"88 172 LINE",
"382 207 LINE",
"378 263 LINE",
"26 240 LINE"
);
}
);
vertWidth = 0;
width = 600;
},
{
layerId = "36D5BF76-782C-4F60-A6DB-0A9BC5828108";
paths = (
{
closed = 1;
nodes = (
"214 504 LINE",
"9 428 LINE",
"36 281 LINE",
"208 341 LINE",
"304 303 LINE",
"307 -1 LINE",
"468 -1 LINE",
"447 434 LINE"
);
},
{
closed = 1;
nodes = (
"29 22 LINE",
"168 -12 LINE",
"389 71 LINE",
"383 149 LINE",
"201 102 LINE",
"163 133 LINE",
"165 179 LINE",
"381 184 LINE",
"378 263 LINE",
"26 240 LINE"
);
}
);
vertWidth = 0;
width = 600;
}
);
note = a;
unicode = 0061;
},
{
glyphname = e;
layers = (
{
layerId = "CCC32AD0-E3D7-4595-BA12-BA39A95902C9";
paths = (
{
closed = 1;
nodes = (
"571 305 LINE",
"316 513 LINE",
"40 261 LINE",
"188 -18 LINE",
"526 45 LINE",
"509 129 LINE",
"229 75 LINE",
"147 263 LINE",
"317 416 LINE",
"480 292 LINE",
"125 298 LINE",
"127 228 LINE",
"576 226 LINE"
);
}
);
vertWidth = 0;
width = 600;
},
{
layerId = "2B2F6A55-E8C4-4456-AFD7-7A9468BB18B9";
paths = (
{
closed = 1;
nodes = (
"571 305 LINE",
"316 513 LINE",
"40 261 LINE",
"188 -18 LINE",
"526 45 LINE",
"507 157 LINE",
"264 116 LINE",
"180 264 LINE",
"318 387 LINE",
"396 297 LINE",
"125 298 LINE",
"126 203 LINE",
"576 199 LINE"
);
}
);
vertWidth = 0;
width = 600;
},
{
layerId = "36D5BF76-782C-4F60-A6DB-0A9BC5828108";
paths = (
{
closed = 1;
nodes = (
"596 304 LINE",
"314 548 LINE",
"9 262 LINE",
"188 -18 LINE",
"528 0 LINE",
"524 184 LINE",
"244 130 LINE",
"217 264 LINE",
"301 360 LINE",
"404 293 LINE",
"195 299 LINE",
"197 229 LINE",
"601 225 LINE"
);
}
);
vertWidth = 0;
width = 600;
}
);
note = e;
unicode = 0065;
},
{
glyphname = edotabove;
layers = (
{
components = (
{
name = e;
},
{
name = dotabovecomb;
transform = "{1, 0, 0, 1, 313, 96}";
}
);
layerId = "CCC32AD0-E3D7-4595-BA12-BA39A95902C9";
vertWidth = 0;
width = 600;
},
{
components = (
{
name = e;
},
{
name = dotabovecomb;
transform = "{1, 0, 0, 1, 307, 187}";
}
);
layerId = "36D5BF76-782C-4F60-A6DB-0A9BC5828108";
vertWidth = 0;
width = 600;
}
);
note = edotabove;
unicode = 0117;
},
{
glyphname = s;
layers = (
{
layerId = "CCC32AD0-E3D7-4595-BA12-BA39A95902C9";
paths = (
{
closed = 1;
nodes = (
"38 343 LINE",
"427 155 LINE",
"282 76 LINE",
"53 174 LINE",
"25 83 LINE",
"304 -13 LINE",
"582 174 LINE",
"213 366 LINE",
"326 442 LINE",
"539 376 LINE",
"559 459 LINE",
"324 530 LINE"
);
}
);
vertWidth = 0;
width = 600;
},
{
layerId = "36D5BF76-782C-4F60-A6DB-0A9BC5828108";
paths = (
{
closed = 1;
nodes = (
"16 398 LINE",
"347 149 LINE",
"221 119 LINE",
"26 226 LINE",
"7 79 LINE",
"284 -58 LINE",
"608 141 LINE",
"268 357 LINE",
"324 402 LINE",
"537 336 LINE",
"559 459 LINE",
"324 530 LINE"
);
}
);
vertWidth = 0;
width = 600;
}
);
note = s;
unicode = 0073;
},
{
glyphname = dotabovecomb;
layers = (
{
layerId = "CCC32AD0-E3D7-4595-BA12-BA39A95902C9";
paths = (
{
closed = 1;
nodes = (
"41 501 LINE",
"50 589 LINE",
"-21 597 LINE",
"-37 503 LINE"
);
}
);
vertWidth = 0;
width = 0;
},
{
layerId = "36D5BF76-782C-4F60-A6DB-0A9BC5828108";
paths = (
{
closed = 1;
nodes = (
"58 488 LINE",
"63 605 LINE",
"-29 625 LINE",
"-64 483 LINE"
);
}
);
vertWidth = 0;
width = 0;
}
);
note = dotabovecomb;
unicode = 0307;
}
);
instances = (
);
unitsPerEm = 1000;
userData = {
com.schriftgestaltung.Glyphs.groupsNotInFeature = (
);
};
versionMajor = 1;
versionMinor = 0;
}

View File

@ -0,0 +1,23 @@
<?xml version='1.0' encoding='UTF-8'?>
<designspace format="4.0">
<axes>
<axis tag="wght" name="Weight" minimum="350" maximum="625" default="350"/>
</axes>
<sources>
<source filename="master_ufo/SparseMasters-Regular.ufo" name="Sparse Masters Regular">
<location>
<dimension name="Weight" xvalue="350"/>
</location>
</source>
<source filename="master_ufo/SparseMasters-Medium.ufo" name="Sparse Masters Medium">
<location>
<dimension name="Weight" xvalue="450"/>
</location>
</source>
<source filename="master_ufo/SparseMasters-Bold.ufo" name="Sparse Masters Bold">
<location>
<dimension name="Weight" xvalue="625"/>
</location>
</source>
</sources>
</designspace>

View File

@ -0,0 +1,501 @@
<?xml version="1.0" encoding="UTF-8"?>
<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="4.39">
<GlyphOrder>
<!-- The 'id' attribute is only for humans; it is ignored when parsed. -->
<GlyphID id="0" name=".notdef"/>
<GlyphID id="1" name="a"/>
<GlyphID id="2" name="e"/>
<GlyphID id="3" name="edotabove"/>
<GlyphID id="4" name="s"/>
<GlyphID id="5" name="dotabovecomb"/>
</GlyphOrder>
<head>
<!-- Most of this table will be recalculated by the compiler -->
<tableVersion value="1.0"/>
<fontRevision value="0.0"/>
<checkSumAdjustment value="0x193b520f"/>
<magicNumber value="0x5f0f3cf5"/>
<flags value="00000000 00000011"/>
<unitsPerEm value="1000"/>
<created value="Thu Apr 6 00:27:50 2023"/>
<modified value="Thu Apr 6 00:27:50 2023"/>
<xMin value="-37"/>
<yMin value="-250"/>
<xMax value="582"/>
<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="950"/>
<descent value="-250"/>
<lineGap value="0"/>
<advanceWidthMax value="600"/>
<minLeftSideBearing value="-37"/>
<minRightSideBearing value="-50"/>
<xMaxExtent value="582"/>
<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="6"/>
</hhea>
<maxp>
<!-- Most of this table will be recalculated by the compiler -->
<tableVersion value="0x10000"/>
<numGlyphs value="6"/>
<maxPoints value="18"/>
<maxContours value="2"/>
<maxCompositePoints value="17"/>
<maxCompositeContours value="2"/>
<maxZones value="1"/>
<maxTwilightPoints value="0"/>
<maxStorage value="0"/>
<maxFunctionDefs value="0"/>
<maxInstructionDefs value="0"/>
<maxStackElements value="0"/>
<maxSizeOfInstructions value="0"/>
<maxComponentElements value="2"/>
<maxComponentDepth value="1"/>
</maxp>
<OS_2>
<!-- The fields 'usFirstCharIndex' and 'usLastCharIndex'
will be recalculated by the compiler -->
<version value="4"/>
<xAvgCharWidth value="580"/>
<usWeightClass value="350"/>
<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="300"/>
<sFamilyClass value="0"/>
<panose>
<bFamilyType value="0"/>
<bSerifStyle value="0"/>
<bWeight value="0"/>
<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 01000101"/>
<ulUnicodeRange2 value="00000000 00000000 00000000 00000000"/>
<ulUnicodeRange3 value="00000000 00000000 00000000 00000000"/>
<ulUnicodeRange4 value="00000000 00000000 00000000 00000000"/>
<achVendID value="NONE"/>
<fsSelection value="00000000 01000000"/>
<usFirstCharIndex value="97"/>
<usLastCharIndex value="775"/>
<sTypoAscender value="750"/>
<sTypoDescender value="-250"/>
<sTypoLineGap value="200"/>
<usWinAscent value="950"/>
<usWinDescent value="250"/>
<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="500" lsb="50"/>
<mtx name="a" width="600" lsb="9"/>
<mtx name="dotabovecomb" width="0" lsb="-37"/>
<mtx name="e" width="600" lsb="40"/>
<mtx name="edotabove" width="600" lsb="40"/>
<mtx name="s" width="600" lsb="25"/>
</hmtx>
<cmap>
<tableVersion version="0"/>
<cmap_format_4 platformID="0" platEncID="3" language="0">
<map code="0x61" name="a"/><!-- LATIN SMALL LETTER A -->
<map code="0x65" name="e"/><!-- LATIN SMALL LETTER E -->
<map code="0x73" name="s"/><!-- LATIN SMALL LETTER S -->
<map code="0x117" name="edotabove"/><!-- LATIN SMALL LETTER E WITH DOT ABOVE -->
<map code="0x307" name="dotabovecomb"/><!-- COMBINING DOT ABOVE -->
</cmap_format_4>
<cmap_format_4 platformID="3" platEncID="1" language="0">
<map code="0x61" name="a"/><!-- LATIN SMALL LETTER A -->
<map code="0x65" name="e"/><!-- LATIN SMALL LETTER E -->
<map code="0x73" name="s"/><!-- LATIN SMALL LETTER S -->
<map code="0x117" name="edotabove"/><!-- LATIN SMALL LETTER E WITH DOT ABOVE -->
<map code="0x307" name="dotabovecomb"/><!-- COMBINING DOT ABOVE -->
</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="50" yMin="-250" xMax="450" yMax="750">
<contour>
<pt x="50" y="750" on="1"/>
<pt x="50" y="-250" on="1"/>
<pt x="450" y="-250" on="1"/>
<pt x="450" y="750" on="1"/>
</contour>
<contour>
<pt x="400" y="-200" on="1"/>
<pt x="100" y="-200" on="1"/>
<pt x="100" y="700" on="1"/>
<pt x="400" y="700" on="1"/>
</contour>
<instructions/>
</TTGlyph>
<TTGlyph name="a" xMin="9" yMin="-12" xMax="468" yMax="504">
<contour>
<pt x="447" y="434" on="1"/>
<pt x="468" y="-1" on="1"/>
<pt x="366" y="-3" on="1"/>
<pt x="363" y="357" on="1"/>
<pt x="208" y="397" on="1"/>
<pt x="36" y="337" on="1"/>
<pt x="9" y="428" on="1"/>
<pt x="214" y="504" on="1"/>
</contour>
<contour>
<pt x="26" y="240" on="1"/>
<pt x="378" y="263" on="1"/>
<pt x="382" y="207" on="1"/>
<pt x="88" y="172" on="1"/>
<pt x="86" y="126" on="1"/>
<pt x="161" y="74" on="1"/>
<pt x="383" y="134" on="1"/>
<pt x="389" y="71" on="1"/>
<pt x="168" y="-12" on="1"/>
<pt x="29" y="22" on="1"/>
</contour>
<instructions/>
</TTGlyph>
<TTGlyph name="dotabovecomb" xMin="-37" yMin="501" xMax="50" yMax="597">
<contour>
<pt x="-37" y="503" on="1"/>
<pt x="-21" y="597" on="1"/>
<pt x="50" y="589" on="1"/>
<pt x="41" y="501" on="1"/>
</contour>
<instructions/>
</TTGlyph>
<TTGlyph name="e" xMin="40" yMin="-18" xMax="576" yMax="513">
<contour>
<pt x="576" y="226" on="1"/>
<pt x="127" y="228" on="1"/>
<pt x="125" y="298" on="1"/>
<pt x="480" y="292" on="1"/>
<pt x="317" y="416" on="1"/>
<pt x="147" y="263" on="1"/>
<pt x="229" y="75" on="1"/>
<pt x="509" y="129" on="1"/>
<pt x="526" y="45" on="1"/>
<pt x="188" y="-18" on="1"/>
<pt x="40" y="261" on="1"/>
<pt x="316" y="513" on="1"/>
<pt x="571" y="305" on="1"/>
</contour>
<instructions/>
</TTGlyph>
<TTGlyph name="edotabove" xMin="40" yMin="-18" xMax="576" yMax="693">
<component glyphName="e" x="0" y="0" flags="0x204"/>
<component glyphName="dotabovecomb" x="313" y="96" flags="0x4"/>
</TTGlyph>
<TTGlyph name="s" xMin="25" yMin="-13" xMax="582" yMax="530">
<contour>
<pt x="324" y="530" on="1"/>
<pt x="559" y="459" on="1"/>
<pt x="539" y="376" on="1"/>
<pt x="326" y="442" on="1"/>
<pt x="213" y="366" on="1"/>
<pt x="582" y="174" on="1"/>
<pt x="304" y="-13" on="1"/>
<pt x="25" y="83" on="1"/>
<pt x="53" y="174" on="1"/>
<pt x="282" y="76" on="1"/>
<pt x="427" y="155" on="1"/>
<pt x="38" y="343" on="1"/>
</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">
Sparse Masters
</namerecord>
<namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
Regular
</namerecord>
<namerecord nameID="3" platformID="3" platEncID="1" langID="0x409">
0.000;NONE;SparseMasters-Regular
</namerecord>
<namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
Sparse Masters Regular
</namerecord>
<namerecord nameID="5" platformID="3" platEncID="1" langID="0x409">
Version 0.000
</namerecord>
<namerecord nameID="6" platformID="3" platEncID="1" langID="0x409">
SparseMasters-Regular
</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="edotabove"/>
<psName name="dotabovecomb"/>
</extraNames>
</post>
<HVAR>
<Version value="0x00010000"/>
<VarStore Format="1">
<Format value="1"/>
<VarRegionList>
<!-- RegionAxisCount=1 -->
<!-- RegionCount=3 -->
<Region index="0">
<VarRegionAxis index="0">
<StartCoord value="0.0"/>
<PeakCoord value="0.36365"/>
<EndCoord value="1.0"/>
</VarRegionAxis>
</Region>
<Region index="1">
<VarRegionAxis index="0">
<StartCoord value="0.36365"/>
<PeakCoord value="1.0"/>
<EndCoord value="1.0"/>
</VarRegionAxis>
</Region>
<Region index="2">
<VarRegionAxis index="0">
<StartCoord value="0.0"/>
<PeakCoord value="1.0"/>
<EndCoord value="1.0"/>
</VarRegionAxis>
</Region>
</VarRegionList>
<!-- VarDataCount=1 -->
<VarData index="0">
<!-- ItemCount=1 -->
<NumShorts value="0"/>
<!-- VarRegionCount=0 -->
<Item index="0" value="[]"/>
</VarData>
</VarStore>
<AdvWidthMap>
<Map glyph=".notdef" outer="0" inner="0"/>
<Map glyph="a" outer="0" inner="0"/>
<Map glyph="dotabovecomb" outer="0" inner="0"/>
<Map glyph="e" outer="0" inner="0"/>
<Map glyph="edotabove" outer="0" inner="0"/>
<Map glyph="s" outer="0" inner="0"/>
</AdvWidthMap>
</HVAR>
<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>350.0</MinValue>
<DefaultValue>350.0</DefaultValue>
<MaxValue>625.0</MaxValue>
<AxisNameID>256</AxisNameID>
</Axis>
</fvar>
<gvar>
<version value="1"/>
<reserved value="0"/>
<glyphVariations glyph="a">
<tuple>
<coord axis="wght" value="1.0"/>
<delta pt="0" x="0" y="0"/>
<delta pt="1" x="0" y="0"/>
<delta pt="2" x="-59" y="2"/>
<delta pt="3" x="-59" y="-54"/>
<delta pt="4" x="0" y="-56"/>
<delta pt="5" x="0" y="-56"/>
<delta pt="6" x="0" y="0"/>
<delta pt="7" x="0" y="0"/>
<delta pt="8" x="0" y="0"/>
<delta pt="9" x="0" y="0"/>
<delta pt="10" x="-1" y="-23"/>
<delta pt="11" x="77" y="7"/>
<delta pt="12" x="77" y="7"/>
<delta pt="13" x="40" y="28"/>
<delta pt="14" x="0" y="15"/>
<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"/>
<delta pt="20" x="0" y="0"/>
<delta pt="21" x="0" y="0"/>
</tuple>
</glyphVariations>
<glyphVariations glyph="dotabovecomb">
<tuple>
<coord axis="wght" value="1.0"/>
<delta pt="0" x="-27" y="-20"/>
<delta pt="1" x="-8" y="28"/>
<delta pt="2" x="13" y="16"/>
<delta pt="3" x="17" y="-13"/>
<delta pt="4" x="0" y="0"/>
<delta pt="5" x="0" y="0"/>
<delta pt="6" x="0" y="0"/>
<delta pt="7" x="0" y="0"/>
</tuple>
</glyphVariations>
<glyphVariations glyph="e">
<tuple>
<coord axis="wght" min="0.0" value="0.36365" max="1.0"/>
<delta pt="0" x="0" y="-27"/>
<delta pt="1" x="-1" y="-25"/>
<delta pt="2" x="0" y="0"/>
<delta pt="3" x="-84" y="5"/>
<delta pt="4" x="1" y="-29"/>
<delta pt="5" x="33" y="1"/>
<delta pt="6" x="35" y="41"/>
<delta pt="7" x="-2" y="28"/>
<delta pt="8" x="0" y="0"/>
<delta pt="9" x="0" y="0"/>
<delta pt="10" x="0" y="0"/>
<delta pt="11" x="0" y="0"/>
<delta pt="12" x="0" y="0"/>
<delta pt="13" x="0" y="0"/>
<delta pt="14" x="0" y="0"/>
<delta pt="15" x="0" y="0"/>
<delta pt="16" x="0" y="0"/>
</tuple>
<tuple>
<coord axis="wght" min="0.36365" value="1.0" max="1.0"/>
<delta pt="0" x="25" y="-1"/>
<delta pt="1" x="70" y="1"/>
<delta pt="2" x="70" y="1"/>
<delta pt="3" x="-76" y="1"/>
<delta pt="4" x="-16" y="-56"/>
<delta pt="5" x="70" y="1"/>
<delta pt="6" x="15" y="55"/>
<delta pt="7" x="15" y="55"/>
<delta pt="8" x="2" y="-45"/>
<delta pt="9" x="0" y="0"/>
<delta pt="10" x="-31" y="1"/>
<delta pt="11" x="-2" y="35"/>
<delta pt="12" x="25" y="-1"/>
<delta pt="13" x="0" y="0"/>
<delta pt="14" x="0" y="0"/>
<delta pt="15" x="0" y="0"/>
<delta pt="16" x="0" y="0"/>
</tuple>
</glyphVariations>
<glyphVariations glyph="edotabove">
<tuple>
<coord axis="wght" value="1.0"/>
<delta pt="1" x="-6" y="91"/>
</tuple>
</glyphVariations>
<glyphVariations glyph="s">
<tuple>
<coord axis="wght" value="1.0"/>
<delta pt="0" x="0" y="0"/>
<delta pt="1" x="0" y="0"/>
<delta pt="2" x="-2" y="-40"/>
<delta pt="3" x="-2" y="-40"/>
<delta pt="4" x="55" y="-9"/>
<delta pt="5" x="26" y="-33"/>
<delta pt="6" x="-20" y="-45"/>
<delta pt="7" x="-18" y="-4"/>
<delta pt="8" x="-27" y="52"/>
<delta pt="9" x="-61" y="43"/>
<delta pt="10" x="-80" y="-6"/>
<delta pt="11" x="-22" y="55"/>
<delta pt="12" x="0" y="0"/>
<delta pt="13" x="0" 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,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>ascender</key>
<integer>750</integer>
<key>capHeight</key>
<integer>700</integer>
<key>descender</key>
<integer>-250</integer>
<key>familyName</key>
<string>Sparse Masters</string>
<key>styleName</key>
<string>Bold</string>
<key>unitsPerEm</key>
<integer>1000</integer>
<key>xHeight</key>
<integer>500</integer>
</dict>
</plist>

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<glyph name=".notdef" format="2">
<advance width="500"/>
<outline>
<contour>
<point x="50" y="750" type="line"/>
<point x="450" y="750" type="line"/>
<point x="450" y="-250" type="line"/>
<point x="50" y="-250" type="line"/>
</contour>
<contour>
<point x="400" y="-200" type="line"/>
<point x="400" y="700" type="line"/>
<point x="100" y="700" type="line"/>
<point x="100" y="-200" type="line"/>
</contour>
</outline>
</glyph>

View File

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<glyph name="a" format="2">
<unicode hex="0061"/>
<advance width="600"/>
<outline>
<contour>
<point x="447" y="434" type="line"/>
<point x="214" y="504" type="line"/>
<point x="9" y="428" type="line"/>
<point x="36" y="281" type="line"/>
<point x="208" y="341" type="line"/>
<point x="304" y="303" type="line"/>
<point x="307" y="-1" type="line"/>
<point x="468" y="-1" type="line"/>
</contour>
<contour>
<point x="26" y="240" type="line"/>
<point x="29" y="22" type="line"/>
<point x="168" y="-12" type="line"/>
<point x="389" y="71" type="line"/>
<point x="383" y="149" type="line"/>
<point x="201" y="102" type="line"/>
<point x="163" y="133" type="line"/>
<point x="165" y="179" type="line"/>
<point x="381" y="184" type="line"/>
<point x="378" y="263" type="line"/>
</contour>
</outline>
</glyph>

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>.notdef</key>
<string>_notdef.glif</string>
<key>a</key>
<string>a.glif</string>
<key>dotabovecomb</key>
<string>dotabovecomb.glif</string>
<key>e</key>
<string>e.glif</string>
<key>edotabove</key>
<string>edotabove.glif</string>
<key>s</key>
<string>s.glif</string>
</dict>
</plist>

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<glyph name="dotabovecomb" format="2">
<unicode hex="0307"/>
<outline>
<contour>
<point x="-64" y="483" type="line"/>
<point x="58" y="488" type="line"/>
<point x="63" y="605" type="line"/>
<point x="-29" y="625" type="line"/>
</contour>
</outline>
</glyph>

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<glyph name="e" format="2">
<unicode hex="0065"/>
<advance width="600"/>
<outline>
<contour>
<point x="601" y="225" type="line"/>
<point x="596" y="304" type="line"/>
<point x="314" y="548" type="line"/>
<point x="9" y="262" type="line"/>
<point x="188" y="-18" type="line"/>
<point x="528" y="0" type="line"/>
<point x="524" y="184" type="line"/>
<point x="244" y="130" type="line"/>
<point x="217" y="264" type="line"/>
<point x="301" y="360" type="line"/>
<point x="404" y="293" type="line"/>
<point x="195" y="299" type="line"/>
<point x="197" y="229" type="line"/>
</contour>
</outline>
</glyph>

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<glyph name="edotabove" format="2">
<unicode hex="0117"/>
<advance width="600"/>
<outline>
<component base="e"/>
<component base="dotabovecomb" xOffset="307" yOffset="187"/>
</outline>
</glyph>

View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<glyph name="s" format="2">
<unicode hex="0073"/>
<advance width="600"/>
<outline>
<contour>
<point x="324" y="530" type="line"/>
<point x="16" y="398" type="line"/>
<point x="347" y="149" type="line"/>
<point x="221" y="119" type="line"/>
<point x="26" y="226" type="line"/>
<point x="7" y="79" type="line"/>
<point x="284" y="-58" type="line"/>
<point x="608" y="141" type="line"/>
<point x="268" y="357" type="line"/>
<point x="324" y="402" type="line"/>
<point x="537" y="336" type="line"/>
<point x="559" y="459" type="line"/>
</contour>
</outline>
</glyph>

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
<array>
<string>public.default</string>
<string>glyphs</string>
</array>
</array>
</plist>

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>public.glyphOrder</key>
<array>
<string>.notdef</string>
<string>a</string>
<string>e</string>
<string>edotabove</string>
<string>s</string>
<string>dotabovecomb</string>
</array>
</dict>
</plist>

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>creator</key>
<string>com.github.fonttools.ufoLib</string>
<key>formatVersion</key>
<integer>3</integer>
</dict>
</plist>

View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>ascender</key>
<integer>750</integer>
<key>capHeight</key>
<integer>700</integer>
<key>descender</key>
<integer>-250</integer>
<key>familyName</key>
<string>Sparse Masters</string>
<key>styleName</key>
<string>Medium</string>
<key>unitsPerEm</key>
<integer>1000</integer>
<key>xHeight</key>
<integer>500</integer>
</dict>
</plist>

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<glyph name=".notdef" format="2">
<advance width="500"/>
<outline>
<contour>
<point x="50" y="750" type="line"/>
<point x="450" y="750" type="line"/>
<point x="450" y="-250" type="line"/>
<point x="50" y="-250" type="line"/>
</contour>
<contour>
<point x="400" y="-200" type="line"/>
<point x="400" y="700" type="line"/>
<point x="100" y="700" type="line"/>
<point x="100" y="-200" type="line"/>
</contour>
</outline>
</glyph>

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>.notdef</key>
<string>_notdef.glif</string>
<key>e</key>
<string>e.glif</string>
</dict>
</plist>

View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<glyph name="e" format="2">
<advance width="600"/>
<outline>
<contour>
<point x="576" y="199" type="line"/>
<point x="571" y="305" type="line"/>
<point x="316" y="513" type="line"/>
<point x="40" y="261" type="line"/>
<point x="188" y="-18" type="line"/>
<point x="526" y="45" type="line"/>
<point x="507" y="157" type="line"/>
<point x="264" y="116" type="line"/>
<point x="180" y="264" type="line"/>
<point x="318" y="387" type="line"/>
<point x="396" y="297" type="line"/>
<point x="125" y="298" type="line"/>
<point x="126" y="203" type="line"/>
</contour>
</outline>
</glyph>

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
<array>
<string>public.default</string>
<string>glyphs</string>
</array>
</array>
</plist>

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>public.glyphOrder</key>
<array>
<string>.notdef</string>
<string>e</string>
</array>
</dict>
</plist>

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>creator</key>
<string>com.github.fonttools.ufoLib</string>
<key>formatVersion</key>
<integer>3</integer>
</dict>
</plist>

View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>ascender</key>
<integer>750</integer>
<key>capHeight</key>
<integer>700</integer>
<key>descender</key>
<integer>-250</integer>
<key>familyName</key>
<string>Sparse Masters</string>
<key>styleName</key>
<string>Regular</string>
<key>unitsPerEm</key>
<integer>1000</integer>
<key>xHeight</key>
<integer>500</integer>
</dict>
</plist>

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<glyph name=".notdef" format="2">
<advance width="500"/>
<outline>
<contour>
<point x="50" y="750" type="line"/>
<point x="450" y="750" type="line"/>
<point x="450" y="-250" type="line"/>
<point x="50" y="-250" type="line"/>
</contour>
<contour>
<point x="400" y="-200" type="line"/>
<point x="400" y="700" type="line"/>
<point x="100" y="700" type="line"/>
<point x="100" y="-200" type="line"/>
</contour>
</outline>
</glyph>

View File

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<glyph name="a" format="2">
<unicode hex="0061"/>
<advance width="600"/>
<outline>
<contour>
<point x="447" y="434" type="line"/>
<point x="214" y="504" type="line"/>
<point x="9" y="428" type="line"/>
<point x="36" y="337" type="line"/>
<point x="208" y="397" type="line"/>
<point x="363" y="357" type="line"/>
<point x="366" y="-3" type="line"/>
<point x="468" y="-1" type="line"/>
</contour>
<contour>
<point x="26" y="240" type="line"/>
<point x="29" y="22" type="line"/>
<point x="168" y="-12" type="line"/>
<point x="389" y="71" type="line"/>
<point x="383" y="134" type="line"/>
<point x="161" y="74" type="line"/>
<point x="86" y="126" type="line"/>
<point x="88" y="172" type="line"/>
<point x="382" y="207" type="line"/>
<point x="378" y="263" type="line"/>
</contour>
</outline>
</glyph>

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>.notdef</key>
<string>_notdef.glif</string>
<key>a</key>
<string>a.glif</string>
<key>dotabovecomb</key>
<string>dotabovecomb.glif</string>
<key>e</key>
<string>e.glif</string>
<key>edotabove</key>
<string>edotabove.glif</string>
<key>s</key>
<string>s.glif</string>
</dict>
</plist>

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<glyph name="dotabovecomb" format="2">
<unicode hex="0307"/>
<outline>
<contour>
<point x="-37" y="503" type="line"/>
<point x="41" y="501" type="line"/>
<point x="50" y="589" type="line"/>
<point x="-21" y="597" type="line"/>
</contour>
</outline>
</glyph>

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<glyph name="e" format="2">
<unicode hex="0065"/>
<advance width="600"/>
<outline>
<contour>
<point x="576" y="226" type="line"/>
<point x="571" y="305" type="line"/>
<point x="316" y="513" type="line"/>
<point x="40" y="261" type="line"/>
<point x="188" y="-18" type="line"/>
<point x="526" y="45" type="line"/>
<point x="509" y="129" type="line"/>
<point x="229" y="75" type="line"/>
<point x="147" y="263" type="line"/>
<point x="317" y="416" type="line"/>
<point x="480" y="292" type="line"/>
<point x="125" y="298" type="line"/>
<point x="127" y="228" type="line"/>
</contour>
</outline>
</glyph>

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<glyph name="edotabove" format="2">
<unicode hex="0117"/>
<advance width="600"/>
<outline>
<component base="e"/>
<component base="dotabovecomb" xOffset="313" yOffset="96"/>
</outline>
</glyph>

View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<glyph name="s" format="2">
<unicode hex="0073"/>
<advance width="600"/>
<outline>
<contour>
<point x="324" y="530" type="line"/>
<point x="38" y="343" type="line"/>
<point x="427" y="155" type="line"/>
<point x="282" y="76" type="line"/>
<point x="53" y="174" type="line"/>
<point x="25" y="83" type="line"/>
<point x="304" y="-13" type="line"/>
<point x="582" y="174" type="line"/>
<point x="213" y="366" type="line"/>
<point x="326" y="442" type="line"/>
<point x="539" y="376" type="line"/>
<point x="559" y="459" type="line"/>
</contour>
</outline>
</glyph>

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
<array>
<string>public.default</string>
<string>glyphs</string>
</array>
</array>
</plist>

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>public.glyphOrder</key>
<array>
<string>.notdef</string>
<string>a</string>
<string>e</string>
<string>edotabove</string>
<string>s</string>
<string>dotabovecomb</string>
</array>
</dict>
</plist>

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>creator</key>
<string>com.github.fonttools.ufoLib</string>
<key>formatVersion</key>
<integer>3</integer>
</dict>
</plist>

View File

@ -5,6 +5,7 @@ import shutil
import sys
import tempfile
import unittest
import pytest
try:
import scipy
@ -93,6 +94,158 @@ class InterpolatableTest(unittest.TestCase):
otf_paths = self.get_file_list(self.tempdir, suffix)
self.assertIsNone(interpolatable_main(otf_paths))
def test_interpolatable_ufo(self):
ttx_dir = self.get_test_input("master_ufo")
ufo_paths = self.get_file_list(ttx_dir, ".ufo", "TestFamily2-")
self.assertIsNone(interpolatable_main(ufo_paths))
def test_designspace(self):
designspace_path = self.get_test_input("InterpolateLayout.designspace")
self.assertIsNone(interpolatable_main([designspace_path]))
def test_glyphsapp(self):
pytest.importorskip("glyphsLib")
glyphsapp_path = self.get_test_input("InterpolateLayout.glyphs")
self.assertIsNone(interpolatable_main([glyphsapp_path]))
def test_VF(self):
suffix = ".ttf"
ttx_dir = self.get_test_input("master_ttx_varfont_ttf")
self.temp_dir()
ttx_paths = self.get_file_list(ttx_dir, ".ttx", "SparseMasters-")
for path in ttx_paths:
self.compile_font(path, suffix, self.tempdir)
ttf_paths = self.get_file_list(self.tempdir, suffix)
problems = interpolatable_main(["--quiet"] + ttf_paths)
self.assertIsNone(problems)
def test_sparse_interpolatable_ttfs(self):
suffix = ".ttf"
ttx_dir = self.get_test_input("master_ttx_interpolatable_ttf")
self.temp_dir()
ttx_paths = self.get_file_list(ttx_dir, ".ttx", "SparseMasters-")
for path in ttx_paths:
self.compile_font(path, suffix, self.tempdir)
ttf_paths = self.get_file_list(self.tempdir, suffix)
# without --ignore-missing
problems = interpolatable_main(["--quiet"] + ttf_paths)
self.assertEqual(
problems["a"], [{"type": "missing", "master": "SparseMasters-Medium"}]
)
self.assertEqual(
problems["s"], [{"type": "missing", "master": "SparseMasters-Medium"}]
)
self.assertEqual(
problems["edotabove"],
[{"type": "missing", "master": "SparseMasters-Medium"}],
)
self.assertEqual(
problems["dotabovecomb"],
[{"type": "missing", "master": "SparseMasters-Medium"}],
)
# normal order, with --ignore-missing
self.assertIsNone(interpolatable_main(["--ignore-missing"] + ttf_paths))
# purposely putting the sparse master (medium) first
self.assertIsNone(
interpolatable_main(
["--ignore-missing"] + [ttf_paths[1]] + [ttf_paths[0]] + [ttf_paths[2]]
)
)
# purposely putting the sparse master (medium) last
self.assertIsNone(
interpolatable_main(
["--ignore-missing"] + [ttf_paths[0]] + [ttf_paths[2]] + [ttf_paths[1]]
)
)
def test_sparse_interpolatable_ufos(self):
ttx_dir = self.get_test_input("master_ufo")
ufo_paths = self.get_file_list(ttx_dir, ".ufo", "SparseMasters-")
# without --ignore-missing
problems = interpolatable_main(["--quiet"] + ufo_paths)
self.assertEqual(
problems["a"], [{"type": "missing", "master": "SparseMasters-Medium"}]
)
self.assertEqual(
problems["s"], [{"type": "missing", "master": "SparseMasters-Medium"}]
)
self.assertEqual(
problems["edotabove"],
[{"type": "missing", "master": "SparseMasters-Medium"}],
)
self.assertEqual(
problems["dotabovecomb"],
[{"type": "missing", "master": "SparseMasters-Medium"}],
)
# normal order, with --ignore-missing
self.assertIsNone(interpolatable_main(["--ignore-missing"] + ufo_paths))
# purposely putting the sparse master (medium) first
self.assertIsNone(
interpolatable_main(
["--ignore-missing"] + [ufo_paths[1]] + [ufo_paths[0]] + [ufo_paths[2]]
)
)
# purposely putting the sparse master (medium) last
self.assertIsNone(
interpolatable_main(
["--ignore-missing"] + [ufo_paths[0]] + [ufo_paths[2]] + [ufo_paths[1]]
)
)
def test_sparse_designspace(self):
designspace_path = self.get_test_input("SparseMasters_ufo.designspace")
problems = interpolatable_main(["--quiet", designspace_path])
self.assertEqual(
problems["a"], [{"type": "missing", "master": "SparseMasters-Medium"}]
)
self.assertEqual(
problems["s"], [{"type": "missing", "master": "SparseMasters-Medium"}]
)
self.assertEqual(
problems["edotabove"],
[{"type": "missing", "master": "SparseMasters-Medium"}],
)
self.assertEqual(
problems["dotabovecomb"],
[{"type": "missing", "master": "SparseMasters-Medium"}],
)
# normal order, with --ignore-missing
self.assertIsNone(interpolatable_main(["--ignore-missing", designspace_path]))
def test_sparse_glyphsapp(self):
pytest.importorskip("glyphsLib")
glyphsapp_path = self.get_test_input("SparseMasters.glyphs")
problems = interpolatable_main(["--quiet", glyphsapp_path])
self.assertEqual(
problems["a"], [{"type": "missing", "master": "Sparse Masters-Medium"}]
)
self.assertEqual(
problems["s"], [{"type": "missing", "master": "Sparse Masters-Medium"}]
)
self.assertEqual(
problems["edotabove"],
[{"type": "missing", "master": "Sparse Masters-Medium"}],
)
self.assertEqual(
problems["dotabovecomb"],
[{"type": "missing", "master": "Sparse Masters-Medium"}],
)
# normal order, with --ignore-missing
self.assertIsNone(interpolatable_main(["--ignore-missing", glyphsapp_path]))
def test_interpolatable_varComposite(self):
input_path = self.get_test_input(
"..", "..", "ttLib", "data", "varc-ac00-ac01.ttf"

View File

@ -13,3 +13,4 @@ ufoLib2==0.14.0
pyobjc==9.0; sys_platform == "darwin"
freetype-py==2.3.0
uharfbuzz==0.32.0
glyphsLib==6.2.1 # this is only required to run Tests/varLib/interpolatable_test.py

Binary file not shown.