aboutsummaryrefslogtreecommitdiff
path: root/Tests/varLib
diff options
context:
space:
mode:
Diffstat (limited to 'Tests/varLib')
-rw-r--r--Tests/varLib/builder_test.py191
-rw-r--r--Tests/varLib/data/BuildAvar2.designspace55
-rw-r--r--Tests/varLib/data/DropOnCurves.designspace20
-rw-r--r--Tests/varLib/data/InterpolateLayout.glyphs2402
-rw-r--r--Tests/varLib/data/SparseCFF2.designspace23
-rw-r--r--Tests/varLib/data/SparseMasters.glyphs486
-rw-r--r--Tests/varLib/data/SparseMasters_ufo.designspace23
-rw-r--r--Tests/varLib/data/TestNoOverwriteSTAT.designspace36
-rw-r--r--Tests/varLib/data/master_no_overwrite_stat/Test-CondensedBlack.ttx243
-rw-r--r--Tests/varLib/data/master_no_overwrite_stat/Test-CondensedThin.ttx373
-rw-r--r--Tests/varLib/data/master_no_overwrite_stat/Test-ExtendedBlack.ttx243
-rw-r--r--Tests/varLib/data/master_no_overwrite_stat/Test-ExtendedThin.ttx243
-rw-r--r--Tests/varLib/data/master_sparse_cff2_empty/SparseCFF-Bold.ttx302
-rw-r--r--Tests/varLib/data/master_sparse_cff2_empty/SparseCFF-Medium.ttx100
-rw-r--r--Tests/varLib/data/master_sparse_cff2_empty/SparseCFF-Regular.ttx302
-rw-r--r--Tests/varLib/data/master_ttx_drop_oncurves/TestFamily-Master1.ttx312
-rw-r--r--Tests/varLib/data/master_ttx_drop_oncurves/TestFamily-Master2.ttx313
-rw-r--r--Tests/varLib/data/master_ttx_varfont_otf/TestCFF2VF.ttx1
-rw-r--r--Tests/varLib/data/master_ttx_varfont_ttf/SparseMasters-VF.ttx501
-rw-r--r--Tests/varLib/data/master_ufo/SparseMasters-Bold.ufo/fontinfo.plist20
-rw-r--r--Tests/varLib/data/master_ufo/SparseMasters-Bold.ufo/glyphs/_notdef.glif18
-rw-r--r--Tests/varLib/data/master_ufo/SparseMasters-Bold.ufo/glyphs/a.glif29
-rw-r--r--Tests/varLib/data/master_ufo/SparseMasters-Bold.ufo/glyphs/contents.plist18
-rw-r--r--Tests/varLib/data/master_ufo/SparseMasters-Bold.ufo/glyphs/dotabovecomb.glif12
-rw-r--r--Tests/varLib/data/master_ufo/SparseMasters-Bold.ufo/glyphs/e.glif22
-rw-r--r--Tests/varLib/data/master_ufo/SparseMasters-Bold.ufo/glyphs/edotabove.glif9
-rw-r--r--Tests/varLib/data/master_ufo/SparseMasters-Bold.ufo/glyphs/s.glif21
-rw-r--r--Tests/varLib/data/master_ufo/SparseMasters-Bold.ufo/layercontents.plist10
-rw-r--r--Tests/varLib/data/master_ufo/SparseMasters-Bold.ufo/lib.plist15
-rw-r--r--Tests/varLib/data/master_ufo/SparseMasters-Bold.ufo/metainfo.plist10
-rw-r--r--Tests/varLib/data/master_ufo/SparseMasters-Medium.ufo/fontinfo.plist20
-rw-r--r--Tests/varLib/data/master_ufo/SparseMasters-Medium.ufo/glyphs/_notdef.glif18
-rw-r--r--Tests/varLib/data/master_ufo/SparseMasters-Medium.ufo/glyphs/contents.plist10
-rw-r--r--Tests/varLib/data/master_ufo/SparseMasters-Medium.ufo/glyphs/e.glif21
-rw-r--r--Tests/varLib/data/master_ufo/SparseMasters-Medium.ufo/layercontents.plist10
-rw-r--r--Tests/varLib/data/master_ufo/SparseMasters-Medium.ufo/lib.plist11
-rw-r--r--Tests/varLib/data/master_ufo/SparseMasters-Medium.ufo/metainfo.plist10
-rw-r--r--Tests/varLib/data/master_ufo/SparseMasters-Regular.ufo/fontinfo.plist20
-rw-r--r--Tests/varLib/data/master_ufo/SparseMasters-Regular.ufo/glyphs/_notdef.glif18
-rw-r--r--Tests/varLib/data/master_ufo/SparseMasters-Regular.ufo/glyphs/a.glif29
-rw-r--r--Tests/varLib/data/master_ufo/SparseMasters-Regular.ufo/glyphs/contents.plist18
-rw-r--r--Tests/varLib/data/master_ufo/SparseMasters-Regular.ufo/glyphs/dotabovecomb.glif12
-rw-r--r--Tests/varLib/data/master_ufo/SparseMasters-Regular.ufo/glyphs/e.glif22
-rw-r--r--Tests/varLib/data/master_ufo/SparseMasters-Regular.ufo/glyphs/edotabove.glif9
-rw-r--r--Tests/varLib/data/master_ufo/SparseMasters-Regular.ufo/glyphs/s.glif21
-rw-r--r--Tests/varLib/data/master_ufo/SparseMasters-Regular.ufo/layercontents.plist10
-rw-r--r--Tests/varLib/data/master_ufo/SparseMasters-Regular.ufo/lib.plist15
-rw-r--r--Tests/varLib/data/master_ufo/SparseMasters-Regular.ufo/metainfo.plist10
-rw-r--r--Tests/varLib/data/test_results/Build.ttx99
-rw-r--r--Tests/varLib/data/test_results/BuildAvar2.ttx41
-rw-r--r--Tests/varLib/data/test_results/BuildAvarEmptyAxis.ttx1
-rw-r--r--Tests/varLib/data/test_results/BuildAvarIdentityMaps.ttx1
-rw-r--r--Tests/varLib/data/test_results/BuildAvarSingleAxis.ttx1
-rw-r--r--Tests/varLib/data/test_results/BuildMain.ttx99
-rw-r--r--Tests/varLib/data/test_results/DropOnCurves.ttx498
-rw-r--r--Tests/varLib/data/test_results/FeatureVars_rclt.ttx2
-rw-r--r--Tests/varLib/data/test_results/InterpolateLayoutGPOS_7_diff.ttx116
-rw-r--r--Tests/varLib/data/test_results/InterpolateLayoutGPOS_7_same.ttx116
-rw-r--r--Tests/varLib/data/test_results/SparseCFF2-VF.ttx157
-rw-r--r--Tests/varLib/data/test_results/SparseMasters.ttx25
-rw-r--r--Tests/varLib/data/test_results/TestSparseCFF2VF.ttx808
-rw-r--r--Tests/varLib/data/test_results/TestVVAR.ttx11
-rw-r--r--Tests/varLib/featureVars_test.py93
-rw-r--r--Tests/varLib/instancer/data/PartialInstancerTest-VF.ttx17
-rw-r--r--Tests/varLib/instancer/data/PartialInstancerTest2-VF.ttx1
-rw-r--r--Tests/varLib/instancer/data/STATInstancerTest.ttx1
-rw-r--r--Tests/varLib/instancer/data/SinglePos.ttx1
-rw-r--r--Tests/varLib/instancer/data/test_results/PartialInstancerTest2-VF-instance-100,100.ttx2
-rw-r--r--Tests/varLib/instancer/data/test_results/PartialInstancerTest2-VF-instance-100,62.5.ttx2
-rw-r--r--Tests/varLib/instancer/data/test_results/PartialInstancerTest2-VF-instance-400,100.ttx2
-rw-r--r--Tests/varLib/instancer/data/test_results/PartialInstancerTest2-VF-instance-400,62.5.ttx2
-rw-r--r--Tests/varLib/instancer/data/test_results/PartialInstancerTest2-VF-instance-900,100.ttx2
-rw-r--r--Tests/varLib/instancer/data/test_results/PartialInstancerTest2-VF-instance-900,62.5.ttx2
-rw-r--r--Tests/varLib/instancer/instancer_test.py364
-rw-r--r--Tests/varLib/instancer/names_test.py37
-rw-r--r--Tests/varLib/instancer/solver_test.py300
-rw-r--r--Tests/varLib/interpolatable_test.py192
-rw-r--r--Tests/varLib/interpolate_layout_test.py655
-rw-r--r--Tests/varLib/iup_test.py114
-rw-r--r--Tests/varLib/merger_test.py100
-rw-r--r--Tests/varLib/models_test.py123
-rw-r--r--Tests/varLib/mutator_test.py88
-rw-r--r--Tests/varLib/stat_test.py24
-rw-r--r--Tests/varLib/varLib_test.py343
-rw-r--r--Tests/varLib/varStore_test.py206
85 files changed, 10037 insertions, 1246 deletions
diff --git a/Tests/varLib/builder_test.py b/Tests/varLib/builder_test.py
index 6cad103a..33d1dfb0 100644
--- a/Tests/varLib/builder_test.py
+++ b/Tests/varLib/builder_test.py
@@ -2,27 +2,31 @@ from fontTools.varLib.builder import buildVarData
import pytest
-@pytest.mark.parametrize("region_indices, items, expected_num_shorts", [
- ([], [], 0),
- ([0], [[1]], 0),
- ([0], [[128]], 1),
- ([0, 1, 2], [[128, 1, 2], [3, -129, 5], [6, 7, 8]], 2),
- ([0, 1, 2], [[0, 128, 2], [3, 4, 5], [6, 7, -129]], 3),
- ([0], [[32768]], 0x8001),
- ([0, 1, 2], [[32768, 1, 2], [3, -129, 5], [6, 7, 8]], 0x8001),
- ([0, 1, 2], [[32768, 1, 2], [3, -32769, 5], [6, 7, 8]], 0x8002),
- ([0, 1, 2], [[0, 32768, 2], [3, 4, 5], [6, 7, -32769]], 0x8003),
-], ids=[
- "0_regions_0_deltas",
- "1_region_1_uint8",
- "1_region_1_short",
- "3_regions_2_shorts_ordered",
- "3_regions_2_shorts_unordered",
- "1_region_1_long",
- "3_regions_1_long_ordered",
- "3_regions_2_longs_ordered",
- "3_regions_2_longs_unordered",
-])
+@pytest.mark.parametrize(
+ "region_indices, items, expected_num_shorts",
+ [
+ ([], [], 0),
+ ([0], [[1]], 0),
+ ([0], [[128]], 1),
+ ([0, 1, 2], [[128, 1, 2], [3, -129, 5], [6, 7, 8]], 2),
+ ([0, 1, 2], [[0, 128, 2], [3, 4, 5], [6, 7, -129]], 3),
+ ([0], [[32768]], 0x8001),
+ ([0, 1, 2], [[32768, 1, 2], [3, -129, 5], [6, 7, 8]], 0x8001),
+ ([0, 1, 2], [[32768, 1, 2], [3, -32769, 5], [6, 7, 8]], 0x8002),
+ ([0, 1, 2], [[0, 32768, 2], [3, 4, 5], [6, 7, -32769]], 0x8003),
+ ],
+ ids=[
+ "0_regions_0_deltas",
+ "1_region_1_uint8",
+ "1_region_1_short",
+ "3_regions_2_shorts_ordered",
+ "3_regions_2_shorts_unordered",
+ "1_region_1_long",
+ "3_regions_1_long_ordered",
+ "3_regions_2_longs_ordered",
+ "3_regions_2_longs_unordered",
+ ],
+)
def test_buildVarData_no_optimize(region_indices, items, expected_num_shorts):
data = buildVarData(region_indices, items, optimize=False)
@@ -33,48 +37,110 @@ def test_buildVarData_no_optimize(region_indices, items, expected_num_shorts):
assert data.Item == items
-@pytest.mark.parametrize([
- "region_indices", "items", "expected_num_shorts",
- "expected_regions", "expected_items"
-], [
- ([0, 1, 2], [[0, 1, 2], [3, 4, 5], [6, 7, 8]], 0,
- [0, 1, 2], [[0, 1, 2], [3, 4, 5], [6, 7, 8]]),
- ([0, 1, 2], [[0, 128, 2], [3, 4, 5], [6, 7, 8]], 1,
- [1, 0, 2], [[128, 0, 2], [4, 3, 5], [7, 6, 8]]),
- ([0, 1, 2], [[0, 1, 128], [3, 4, 5], [6, -129, 8]], 2,
- [1, 2, 0], [[1, 128, 0], [4, 5, 3], [-129, 8, 6]]),
- ([0, 1, 2], [[128, 1, -129], [3, 4, 5], [6, 7, 8]], 2,
- [0, 2, 1], [[128, -129, 1], [3, 5, 4], [6, 8, 7]]),
- ([0, 1, 2], [[0, 1, 128], [3, -129, 5], [256, 7, 8]], 3,
- [0, 1, 2], [[0, 1, 128], [3, -129, 5], [256, 7, 8]]),
- ([0, 1, 2], [[0, 128, 2], [0, 4, 5], [0, 7, 8]], 1,
- [1, 2], [[128, 2], [4, 5], [7, 8]]),
- ([0, 1, 2], [[0, 32768, 2], [3, 4, 5], [6, 7, 8]], 0x8001,
- [1, 0, 2], [[32768, 0, 2], [4, 3, 5], [7, 6, 8]]),
- ([0, 1, 2], [[0, 1, 32768], [3, 4, 5], [6, -32769, 8]], 0x8002,
- [1, 2, 0], [[1, 32768, 0], [4, 5, 3], [-32769, 8, 6]]),
- ([0, 1, 2], [[32768, 1, -32769], [3, 4, 5], [6, 7, 8]], 0x8002,
- [0, 2, 1], [[32768, -32769, 1], [3, 5, 4], [6, 8, 7]]),
- ([0, 1, 2], [[0, 1, 32768], [3, -32769, 5], [65536, 7, 8]], 0x8003,
- [0, 1, 2], [[0, 1, 32768], [3, -32769, 5], [65536, 7, 8]]),
- ([0, 1, 2], [[0, 32768, 2], [0, 4, 5], [0, 7, 8]], 0x8001,
- [1, 2], [[32768, 2], [4, 5], [7, 8]]),
-], ids=[
- "0/3_shorts_no_reorder",
- "1/3_shorts_reorder",
- "2/3_shorts_reorder",
- "2/3_shorts_same_row_reorder",
- "3/3_shorts_no_reorder",
- "1/3_shorts_1/3_zeroes",
- "1/3_longs_reorder",
- "2/3_longs_reorder",
- "2/3_longs_same_row_reorder",
- "3/3_longs_no_reorder",
- "1/3_longs_1/3_zeroes",
-])
+@pytest.mark.parametrize(
+ [
+ "region_indices",
+ "items",
+ "expected_num_shorts",
+ "expected_regions",
+ "expected_items",
+ ],
+ [
+ (
+ [0, 1, 2],
+ [[0, 1, 2], [3, 4, 5], [6, 7, 8]],
+ 0,
+ [0, 1, 2],
+ [[0, 1, 2], [3, 4, 5], [6, 7, 8]],
+ ),
+ (
+ [0, 1, 2],
+ [[0, 128, 2], [3, 4, 5], [6, 7, 8]],
+ 1,
+ [1, 0, 2],
+ [[128, 0, 2], [4, 3, 5], [7, 6, 8]],
+ ),
+ (
+ [0, 1, 2],
+ [[0, 1, 128], [3, 4, 5], [6, -129, 8]],
+ 2,
+ [1, 2, 0],
+ [[1, 128, 0], [4, 5, 3], [-129, 8, 6]],
+ ),
+ (
+ [0, 1, 2],
+ [[128, 1, -129], [3, 4, 5], [6, 7, 8]],
+ 2,
+ [0, 2, 1],
+ [[128, -129, 1], [3, 5, 4], [6, 8, 7]],
+ ),
+ (
+ [0, 1, 2],
+ [[0, 1, 128], [3, -129, 5], [256, 7, 8]],
+ 3,
+ [0, 1, 2],
+ [[0, 1, 128], [3, -129, 5], [256, 7, 8]],
+ ),
+ (
+ [0, 1, 2],
+ [[0, 128, 2], [0, 4, 5], [0, 7, 8]],
+ 1,
+ [1, 2],
+ [[128, 2], [4, 5], [7, 8]],
+ ),
+ (
+ [0, 1, 2],
+ [[0, 32768, 2], [3, 4, 5], [6, 7, 8]],
+ 0x8001,
+ [1, 0, 2],
+ [[32768, 0, 2], [4, 3, 5], [7, 6, 8]],
+ ),
+ (
+ [0, 1, 2],
+ [[0, 1, 32768], [3, 4, 5], [6, -32769, 8]],
+ 0x8002,
+ [1, 2, 0],
+ [[1, 32768, 0], [4, 5, 3], [-32769, 8, 6]],
+ ),
+ (
+ [0, 1, 2],
+ [[32768, 1, -32769], [3, 4, 5], [6, 7, 8]],
+ 0x8002,
+ [0, 2, 1],
+ [[32768, -32769, 1], [3, 5, 4], [6, 8, 7]],
+ ),
+ (
+ [0, 1, 2],
+ [[0, 1, 32768], [3, -32769, 5], [65536, 7, 8]],
+ 0x8003,
+ [0, 1, 2],
+ [[0, 1, 32768], [3, -32769, 5], [65536, 7, 8]],
+ ),
+ (
+ [0, 1, 2],
+ [[0, 32768, 2], [0, 4, 5], [0, 7, 8]],
+ 0x8001,
+ [1, 2],
+ [[32768, 2], [4, 5], [7, 8]],
+ ),
+ ],
+ ids=[
+ "0/3_shorts_no_reorder",
+ "1/3_shorts_reorder",
+ "2/3_shorts_reorder",
+ "2/3_shorts_same_row_reorder",
+ "3/3_shorts_no_reorder",
+ "1/3_shorts_1/3_zeroes",
+ "1/3_longs_reorder",
+ "2/3_longs_reorder",
+ "2/3_longs_same_row_reorder",
+ "3/3_longs_no_reorder",
+ "1/3_longs_1/3_zeroes",
+ ],
+)
def test_buildVarData_optimize(
- region_indices, items, expected_num_shorts, expected_regions,
- expected_items):
+ region_indices, items, expected_num_shorts, expected_regions, expected_items
+):
data = buildVarData(region_indices, items, optimize=True)
assert data.ItemCount == len(items)
@@ -86,4 +152,5 @@ def test_buildVarData_optimize(
if __name__ == "__main__":
import sys
+
sys.exit(pytest.main(sys.argv))
diff --git a/Tests/varLib/data/BuildAvar2.designspace b/Tests/varLib/data/BuildAvar2.designspace
new file mode 100644
index 00000000..1cfa94ab
--- /dev/null
+++ b/Tests/varLib/data/BuildAvar2.designspace
@@ -0,0 +1,55 @@
+<?xml version='1.0' encoding='utf-8'?>
+<designspace format="3">
+ <axes>
+ <axis default="400.0" maximum="900.0" minimum="100.0" name="weight" tag="wght">
+ <map input="100.0" output="26" />
+ <map input="200.0" output="39" />
+ <map input="300.0" output="58" />
+ <map input="400.0" output="90" />
+ <map input="500.0" output="108" />
+ <map input="600.0" output="128" />
+ <map input="700.0" output="151" />
+ <map input="800.0" output="169" />
+ <map input="900.0" output="190" />
+ <labelname xml:lang="en">Weight</labelname>
+ </axis>
+ <mappings>
+ <mapping>
+ <input>
+ <dimension name="weight" xvalue="128"/>
+ </input>
+ <output>
+ <dimension name="weight" xvalue="138"/>
+ </output>
+ </mapping>
+ </mappings>
+ </axes>
+ <sources>
+ <source familyname="Test Family 3" filename="master_ufo/TestFamily3-Light.ufo" name="Test Family 3 Light" stylename="Light">
+ <location>
+ <dimension name="weight" xvalue="26.000000" />
+ </location>
+ </source>
+ <source familyname="Test Family 3" filename="master_ufo/TestFamily3-Regular.ufo" name="Test Family 3 Regular" stylename="Regular">
+ <lib copy="1" />
+ <groups copy="1" />
+ <features copy="1" />
+ <info copy="1" />
+ <location>
+ <dimension name="weight" xvalue="90.000000" />
+ </location>
+ </source>
+ <source familyname="Test Family 3" filename="master_ufo/TestFamily3-SemiBold.ufo" name="Test Family 3 SemiBold" stylename="SemiBold">
+ <location>
+ <dimension name="weight" xvalue="151.000000" />
+ </location>
+ </source>
+ <source familyname="Test Family 3" filename="master_ufo/TestFamily3-Bold.ufo" name="Test Family 3 Bold" stylename="Bold">
+ <location>
+ <dimension name="weight" xvalue="190.000000" />
+ </location>
+ </source>
+ </sources>
+ <instances>
+ </instances>
+</designspace>
diff --git a/Tests/varLib/data/DropOnCurves.designspace b/Tests/varLib/data/DropOnCurves.designspace
new file mode 100644
index 00000000..a4769aa2
--- /dev/null
+++ b/Tests/varLib/data/DropOnCurves.designspace
@@ -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>
diff --git a/Tests/varLib/data/InterpolateLayout.glyphs b/Tests/varLib/data/InterpolateLayout.glyphs
new file mode 100644
index 00000000..90493950
--- /dev/null
+++ b/Tests/varLib/data/InterpolateLayout.glyphs
@@ -0,0 +1,2402 @@
+{
+.appVersion = "895";
+customParameters = (
+{
+name = hheaAscender;
+value = 984;
+},
+{
+name = hheaDescender;
+value = -273;
+},
+{
+name = hheaLineGap;
+value = 0;
+},
+{
+name = panose;
+value = (
+2,
+11,
+5,
+3,
+3,
+4,
+3,
+2,
+2,
+4
+);
+},
+{
+name = typoAscender;
+value = 750;
+},
+{
+name = typoDescender;
+value = -250;
+},
+{
+name = typoLineGap;
+value = 0;
+},
+{
+name = unicodeRanges;
+value = (
+0,
+1
+);
+},
+{
+name = blueScale;
+value = 0.0625;
+},
+{
+name = underlinePosition;
+value = -75;
+},
+{
+name = vendorID;
+value = ADBO;
+},
+{
+name = postscriptFontName;
+value = "TestFamily2-Master0";
+},
+{
+name = postscriptBlueFuzz;
+value = 0;
+},
+{
+name = postscriptForceBold;
+value = 0;
+},
+{
+name = styleMapFamilyName;
+value = "Test Family 2";
+},
+{
+name = postscriptFamilyBlues;
+value = (
+-12,
+0,
+486,
+498,
+518,
+530,
+574,
+586,
+638,
+650,
+656,
+668,
+712,
+724
+);
+},
+{
+name = postscriptFamilyOtherBlues;
+value = (
+-217,
+-205
+);
+},
+{
+name = codePageRanges;
+value = (
+1252,
+1250
+);
+},
+{
+name = codePageRangesUnsupportedBits;
+value = (
+29
+);
+},
+{
+name = winAscent;
+value = 984;
+},
+{
+name = winDescent;
+value = 273;
+},
+{
+name = weightClass;
+value = 200;
+},
+{
+name = glyphOrder;
+value = (
+.notdef,
+space,
+A,
+a,
+d,
+f,
+n,
+t,
+f_t,
+a.alt,
+A.sc,
+atilde,
+ampersand,
+circledotted,
+tildecmb,
+dieresiscmb,
+tildebelowcmb,
+dieresisbelowcmb
+);
+},
+{
+name = "Disable Last Change";
+value = 1;
+},
+{
+name = Axes;
+value = (
+{
+Name = weight;
+Tag = wght;
+}
+);
+}
+);
+designer = "Paul D. Hunt";
+disablesAutomaticAlignment = 1;
+familyName = "Test Family 2";
+featurePrefixes = (
+{
+code = "# Do not use Glyphs to edit features.\012#\012# This Glyphs file was made from several UFOs that had different\012# features. As a result, the features are not editable in Glyphs and\012# the original features will be restored when you go back to UFOs.\012";
+name = WARNING;
+}
+);
+fontMaster = (
+{
+alignmentZones = (
+"{722, 12}",
+"{660, 12}",
+"{640, 12}",
+"{570, 12}",
+"{510, 12}",
+"{478, 12}",
+"{0, -12}",
+"{-222, -12}"
+);
+ascender = 722;
+capHeight = 660;
+customParameters = (
+{
+name = "UFO Filename";
+value = "master_ufo/TestFamily2-Master0.ufo";
+},
+{
+name = "Master Name";
+value = "Master 0";
+},
+{
+name = hheaAscender;
+value = 984;
+},
+{
+name = hheaDescender;
+value = -273;
+},
+{
+name = hheaLineGap;
+value = 0;
+},
+{
+name = panose;
+value = (
+2,
+11,
+5,
+3,
+3,
+4,
+3,
+2,
+2,
+4
+);
+},
+{
+name = typoAscender;
+value = 750;
+},
+{
+name = typoDescender;
+value = -250;
+},
+{
+name = typoLineGap;
+value = 0;
+},
+{
+name = unicodeRanges;
+value = (
+0,
+1
+);
+},
+{
+name = blueScale;
+value = 0.0625;
+},
+{
+name = underlinePosition;
+value = -75;
+},
+{
+name = vendorID;
+value = ADBO;
+},
+{
+name = postscriptFontName;
+value = "TestFamily2-Master0";
+},
+{
+name = postscriptBlueFuzz;
+value = 0;
+},
+{
+name = postscriptForceBold;
+value = 0;
+},
+{
+name = styleMapFamilyName;
+value = "Test Family 2";
+},
+{
+name = postscriptFamilyBlues;
+value = (
+-12,
+0,
+486,
+498,
+518,
+530,
+574,
+586,
+638,
+650,
+656,
+668,
+712,
+724
+);
+},
+{
+name = postscriptFamilyOtherBlues;
+value = (
+-217,
+-205
+);
+},
+{
+name = codePageRanges;
+value = (
+1252,
+1250
+);
+},
+{
+name = codePageRangesUnsupportedBits;
+value = (
+29
+);
+},
+{
+name = winAscent;
+value = 984;
+},
+{
+name = winDescent;
+value = 273;
+},
+{
+name = weightClass;
+value = 200;
+}
+);
+descender = -222;
+horizontalStems = (
+28,
+40
+);
+id = "8DB0CCF0-BD6F-426B-90E2-48FD021BE868";
+userData = {
+com.schriftgestaltung.Glyphs.originalFeatureCode = "table head {\012 FontRevision 2.020;\012} head;\012\012\012table name {\012 nameid 9 \"Paul D. Hunt\";\012 nameid 9 1 \"Paul D. Hunt\";\012} name;\012\012\012table hhea {\012 Ascender 984;\012 Descender -273;\012 LineGap 0;\012} hhea;\012\012\012table BASE {\012 HorizAxis.BaseTagList ideo romn;\012 HorizAxis.BaseScriptList\012 latn romn -170 0,\012 grek romn -170 0,\012 cyrl romn -170 0,\012 DFLT romn -170 0;\012} BASE;\012\012\012table OS/2 {\012 Panose 2 11 3 3 3 4 3 2 2 4;\012 XHeight 478;\012 WeightClass 200;\012\012 TypoAscender 750;\012 TypoDescender -250;\012 TypoLineGap 0;\012 winAscent 984;\012 winDescent 273;\012\012 CapHeight 660;\012 WidthClass 5;\012 Vendor \"ADBO\";\012 FSType 0;\012} OS/2;\012\012\012languagesystem DFLT dflt;\012languagesystem latn dflt;\012\012# GSUB =========================================\012# Merging of GSUB is not performed. The variable\012# font will inherit the GSUB table from the\012# base master.\012\012feature c2sc {\012 sub A by A.sc; # GSUB LookupType 1\012} c2sc;\012\012feature ss01 {\012 featureNames {\012 name \"Alternate a\";\012 name 1 0 0 \"Alternate a\";};\012 sub a by a.alt;\012} ss01;\012\012feature ccmp {\012 sub ampersand by a n d; # GSUB LookupType 2\012} ccmp;\012\012feature salt {\012 sub a from [a.alt A.sc]; # GSUB LookupType 3\012} salt;\012\012feature liga {\012 sub f t by f_t; # GSUB LookupType 4\012} liga;\012\012feature calt {\012 sub a' t by a.alt; # GSUB LookupType 6\012} calt;\012\012";
+};
+verticalStems = (
+32,
+48
+);
+weightValue = 0;
+xHeight = 478;
+},
+{
+alignmentZones = (
+"{696, 12}",
+"{650, 12}",
+"{634, 12}",
+"{580, 12}",
+"{532, 12}",
+"{500, 12}",
+"{0, -12}",
+"{-176, -12}"
+);
+ascender = 696;
+capHeight = 650;
+customParameters = (
+{
+name = "UFO Filename";
+value = "master_ufo/TestFamily2-Master1.ufo";
+},
+{
+name = "Master Name";
+value = "Master 1";
+},
+{
+name = hheaAscender;
+value = 984;
+},
+{
+name = hheaDescender;
+value = -273;
+},
+{
+name = hheaLineGap;
+value = 0;
+},
+{
+name = panose;
+value = (
+2,
+11,
+5,
+3,
+3,
+4,
+3,
+2,
+2,
+4
+);
+},
+{
+name = typoAscender;
+value = 750;
+},
+{
+name = typoDescender;
+value = -250;
+},
+{
+name = typoLineGap;
+value = 0;
+},
+{
+name = unicodeRanges;
+value = (
+0,
+1
+);
+},
+{
+name = blueScale;
+value = 0.0625;
+},
+{
+name = underlinePosition;
+value = -75;
+},
+{
+name = vendorID;
+value = ADBO;
+},
+{
+name = postscriptFontName;
+value = "TestFamily2-Master1";
+},
+{
+name = postscriptBlueFuzz;
+value = 0;
+},
+{
+name = postscriptForceBold;
+value = 0;
+},
+{
+name = styleMapFamilyName;
+value = "Test Family 2";
+},
+{
+name = postscriptFamilyBlues;
+value = (
+-12,
+0,
+486,
+498,
+518,
+530,
+574,
+586,
+638,
+650,
+656,
+668,
+712,
+724
+);
+},
+{
+name = postscriptFamilyOtherBlues;
+value = (
+-217,
+-205
+);
+},
+{
+name = codePageRanges;
+value = (
+1252,
+1250
+);
+},
+{
+name = codePageRangesUnsupportedBits;
+value = (
+29
+);
+},
+{
+name = winAscent;
+value = 984;
+},
+{
+name = winDescent;
+value = 273;
+},
+{
+name = weightClass;
+value = 900;
+}
+);
+descender = -176;
+horizontalStems = (
+134,
+144
+);
+id = "A99E50E2-B754-449B-A60B-37BA27802C99";
+userData = {
+com.schriftgestaltung.Glyphs.originalFeatureCode = "table head {\012 FontRevision 2.020;\012} head;\012\012\012table name {\012 nameid 9 \"Paul D. Hunt\";\012 nameid 9 1 \"Paul D. Hunt\";\012} name;\012\012\012table hhea {\012 Ascender 984;\012 Descender -273;\012 LineGap 0;\012} hhea;\012\012\012table BASE {\012 HorizAxis.BaseTagList ideo romn;\012 HorizAxis.BaseScriptList\012 latn romn -170 0,\012 grek romn -170 0,\012 cyrl romn -170 0,\012 DFLT romn -170 0;\012} BASE;\012\012\012table OS/2 {\012 Panose 2 11 8 3 3 4 3 2 2 4;\012 XHeight 500;\012 WeightClass 900;\012\012 TypoAscender 750;\012 TypoDescender -250;\012 TypoLineGap 0;\012 winAscent 984;\012 winDescent 273;\012\012 CapHeight 660;\012 WidthClass 5;\012 Vendor \"ADBO\";\012 FSType 0;\012} OS/2;\012\012\012languagesystem DFLT dflt;\012languagesystem latn dflt;\012\012# GSUB =========================================\012# No merging of GSUB is performed. The variable\012# font will inherit the GSUB table from the\012# base master.\012\012";
+};
+verticalStems = (
+172,
+176
+);
+weightValue = 1000;
+xHeight = 500;
+}
+);
+glyphs = (
+{
+glyphname = .notdef;
+layers = (
+{
+layerId = "8DB0CCF0-BD6F-426B-90E2-48FD021BE868";
+paths = (
+{
+closed = 1;
+nodes = (
+"528 0 LINE",
+"528 660 LINE",
+"96 660 LINE",
+"96 0 LINE"
+);
+},
+{
+closed = 1;
+nodes = (
+"246 208 LINE",
+"310 314 LINE",
+"314 314 LINE",
+"376 208 LINE",
+"476 32 LINE",
+"144 32 LINE"
+);
+},
+{
+closed = 1;
+nodes = (
+"254 458 LINE",
+"160 626 LINE",
+"462 626 LINE",
+"368 458 LINE",
+"314 366 LINE",
+"310 366 LINE"
+);
+},
+{
+closed = 1;
+nodes = (
+"134 610 LINE",
+"288 340 LINE",
+"134 74 LINE"
+);
+},
+{
+closed = 1;
+nodes = (
+"336 340 LINE",
+"488 610 LINE",
+"488 74 LINE"
+);
+}
+);
+vertWidth = 0;
+width = 624;
+},
+{
+layerId = "A99E50E2-B754-449B-A60B-37BA27802C99";
+paths = (
+{
+closed = 1;
+nodes = (
+"628 0 LINE",
+"628 660 LINE",
+"76 660 LINE",
+"76 0 LINE"
+);
+},
+{
+closed = 1;
+nodes = (
+"314 160 LINE",
+"350 256 LINE",
+"354 256 LINE",
+"390 160 LINE",
+"416 104 LINE",
+"288 104 LINE"
+);
+},
+{
+closed = 1;
+nodes = (
+"310 520 LINE",
+"292 556 LINE",
+"412 556 LINE",
+"394 520 LINE",
+"354 424 LINE",
+"350 424 LINE"
+);
+},
+{
+closed = 1;
+nodes = (
+"188 508 LINE",
+"270 340 LINE",
+"188 172 LINE"
+);
+},
+{
+closed = 1;
+nodes = (
+"434 340 LINE",
+"516 508 LINE",
+"516 172 LINE"
+);
+}
+);
+vertWidth = 0;
+width = 704;
+}
+);
+note = "";
+},
+{
+glyphname = space;
+layers = (
+{
+layerId = "8DB0CCF0-BD6F-426B-90E2-48FD021BE868";
+vertWidth = 0;
+width = 200;
+},
+{
+layerId = "A99E50E2-B754-449B-A60B-37BA27802C99";
+vertWidth = 0;
+width = 200;
+}
+);
+note = "";
+unicode = 0020;
+},
+{
+glyphname = A;
+layers = (
+{
+layerId = "8DB0CCF0-BD6F-426B-90E2-48FD021BE868";
+paths = (
+{
+closed = 1;
+nodes = (
+"42 0 LINE",
+"182 396 LINE SMOOTH",
+"210 476 OFFCURVE",
+"234 544 OFFCURVE",
+"258 626 CURVE",
+"262 626 LINE",
+"286 544 OFFCURVE",
+"310 476 OFFCURVE",
+"338 396 CURVE SMOOTH",
+"476 0 LINE",
+"510 0 LINE",
+"274 660 LINE",
+"246 660 LINE",
+"10 0 LINE"
+);
+},
+{
+closed = 1;
+nodes = (
+"405 236 LINE",
+"405 264 LINE",
+"112 264 LINE",
+"112 236 LINE"
+);
+}
+);
+vertWidth = 0;
+width = 520;
+},
+{
+layerId = "A99E50E2-B754-449B-A60B-37BA27802C99";
+paths = (
+{
+closed = 1;
+nodes = (
+"166 0 LINE",
+"240 316 LINE SMOOTH",
+"256 378 OFFCURVE",
+"272 456 OFFCURVE",
+"286 522 CURVE",
+"290 522 LINE",
+"306 457 OFFCURVE",
+"322 378 OFFCURVE",
+"338 316 CURVE SMOOTH",
+"412 0 LINE",
+"594 0 LINE",
+"396 650 LINE",
+"188 650 LINE",
+"-10 0 LINE"
+);
+},
+{
+closed = 1;
+nodes = (
+"450 138 LINE",
+"450 271 LINE",
+"132 271 LINE",
+"132 138 LINE"
+);
+}
+);
+vertWidth = 0;
+width = 584;
+}
+);
+note = "";
+unicode = 0041;
+},
+{
+glyphname = a;
+layers = (
+{
+layerId = "8DB0CCF0-BD6F-426B-90E2-48FD021BE868";
+paths = (
+{
+closed = 1;
+nodes = (
+"262 -12 OFFCURVE",
+"322 24 OFFCURVE",
+"372 64 CURVE",
+"374 64 LINE",
+"378 0 LINE",
+"404 0 LINE",
+"404 310 LINE SMOOTH",
+"404 406 OFFCURVE",
+"370 490 OFFCURVE",
+"258 490 CURVE SMOOTH",
+"180 490 OFFCURVE",
+"114 450 OFFCURVE",
+"84 428 CURVE",
+"100 404 LINE",
+"130 428 OFFCURVE",
+"188 462 OFFCURVE",
+"256 462 CURVE SMOOTH",
+"356 462 OFFCURVE",
+"376 376 OFFCURVE",
+"374 298 CURVE",
+"158 274 OFFCURVE",
+"60 224 OFFCURVE",
+"60 117 CURVE SMOOTH",
+"60 26 OFFCURVE",
+"124 -12 OFFCURVE",
+"198 -12 CURVE SMOOTH"
+);
+},
+{
+closed = 1;
+nodes = (
+"142 16 OFFCURVE",
+"92 44 OFFCURVE",
+"92 118 CURVE SMOOTH",
+"92 200 OFFCURVE",
+"164 248 OFFCURVE",
+"374 272 CURVE",
+"374 98 LINE",
+"310 44 OFFCURVE",
+"258 16 OFFCURVE",
+"200 16 CURVE SMOOTH"
+);
+}
+);
+vertWidth = 0;
+width = 486;
+},
+{
+layerId = "A99E50E2-B754-449B-A60B-37BA27802C99";
+paths = (
+{
+closed = 1;
+nodes = (
+"242 -12 OFFCURVE",
+"286 12 OFFCURVE",
+"326 48 CURVE",
+"330 48 LINE",
+"342 0 LINE",
+"482 0 LINE",
+"482 278 LINE SMOOTH",
+"482 442 OFFCURVE",
+"404 512 OFFCURVE",
+"274 512 CURVE SMOOTH",
+"196 512 OFFCURVE",
+"124 488 OFFCURVE",
+"54 446 CURVE",
+"114 334 LINE",
+"166 362 OFFCURVE",
+"204 376 OFFCURVE",
+"240 376 CURVE SMOOTH",
+"284 376 OFFCURVE",
+"306 360 OFFCURVE",
+"310 324 CURVE",
+"118 304 OFFCURVE",
+"38 246 OFFCURVE",
+"38 142 CURVE SMOOTH",
+"38 60 OFFCURVE",
+"94 -12 OFFCURVE",
+"188 -12 CURVE SMOOTH"
+);
+},
+{
+closed = 1;
+nodes = (
+"218 120 OFFCURVE",
+"202 133 OFFCURVE",
+"202 156 CURVE SMOOTH",
+"202 184 OFFCURVE",
+"228 210 OFFCURVE",
+"310 222 CURVE",
+"310 154 LINE",
+"292 134 OFFCURVE",
+"276 120 OFFCURVE",
+"248 120 CURVE SMOOTH"
+);
+}
+);
+vertWidth = 0;
+width = 536;
+}
+);
+note = "";
+unicode = 0061;
+},
+{
+glyphname = d;
+layers = (
+{
+layerId = "8DB0CCF0-BD6F-426B-90E2-48FD021BE868";
+paths = (
+{
+closed = 1;
+nodes = (
+"318 -12 OFFCURVE",
+"372 24 OFFCURVE",
+"412 64 CURVE",
+"414 64 LINE",
+"418 0 LINE",
+"444 0 LINE",
+"444 722 LINE",
+"414 722 LINE",
+"414 520 LINE",
+"416 430 LINE",
+"366 468 OFFCURVE",
+"326 490 OFFCURVE",
+"268 490 CURVE SMOOTH",
+"152 490 OFFCURVE",
+"54 392 OFFCURVE",
+"54 238 CURVE SMOOTH",
+"54 76 OFFCURVE",
+"132 -12 OFFCURVE",
+"252 -12 CURVE SMOOTH"
+);
+},
+{
+closed = 1;
+nodes = (
+"146 16 OFFCURVE",
+"86 106 OFFCURVE",
+"86 238 CURVE SMOOTH",
+"86 362 OFFCURVE",
+"164 462 OFFCURVE",
+"266 462 CURVE SMOOTH",
+"316 462 OFFCURVE",
+"360 444 OFFCURVE",
+"414 396 CURVE",
+"414 100 LINE",
+"360 46 OFFCURVE",
+"310 16 OFFCURVE",
+"254 16 CURVE SMOOTH"
+);
+}
+);
+vertWidth = 0;
+width = 540;
+},
+{
+layerId = "A99E50E2-B754-449B-A60B-37BA27802C99";
+paths = (
+{
+closed = 1;
+nodes = (
+"284 -12 OFFCURVE",
+"332 12 OFFCURVE",
+"366 46 CURVE",
+"370 46 LINE",
+"382 0 LINE",
+"522 0 LINE",
+"522 696 LINE",
+"350 696 LINE",
+"350 534 LINE",
+"356 462 LINE",
+"326 492 OFFCURVE",
+"294 512 OFFCURVE",
+"240 512 CURVE SMOOTH",
+"138 512 OFFCURVE",
+"36 414 OFFCURVE",
+"36 250 CURVE SMOOTH",
+"36 88 OFFCURVE",
+"116 -12 OFFCURVE",
+"240 -12 CURVE SMOOTH"
+);
+},
+{
+closed = 1;
+nodes = (
+"240 128 OFFCURVE",
+"212 162 OFFCURVE",
+"212 252 CURVE SMOOTH",
+"212 340 OFFCURVE",
+"246 372 OFFCURVE",
+"282 372 CURVE SMOOTH",
+"304 372 OFFCURVE",
+"330 366 OFFCURVE",
+"350 348 CURVE",
+"350 164 LINE",
+"332 136 OFFCURVE",
+"312 128 OFFCURVE",
+"286 128 CURVE SMOOTH"
+);
+}
+);
+vertWidth = 0;
+width = 580;
+}
+);
+note = "";
+unicode = 0064;
+},
+{
+glyphname = f;
+layers = (
+{
+layerId = "8DB0CCF0-BD6F-426B-90E2-48FD021BE868";
+paths = (
+{
+closed = 1;
+nodes = (
+"130 0 LINE",
+"130 592 LINE SMOOTH",
+"130 664 OFFCURVE",
+"154 706 OFFCURVE",
+"208 706 CURVE SMOOTH",
+"226 706 OFFCURVE",
+"246 702 OFFCURVE",
+"266 692 CURVE",
+"276 718 LINE",
+"254 728 OFFCURVE",
+"230 734 OFFCURVE",
+"210 734 CURVE SMOOTH",
+"142 734 OFFCURVE",
+"100 690 OFFCURVE",
+"100 596 CURVE SMOOTH",
+"100 0 LINE"
+);
+},
+{
+closed = 1;
+nodes = (
+"244 450 LINE",
+"244 478 LINE",
+"100 478 LINE",
+"34 474 LINE",
+"34 450 LINE"
+);
+}
+);
+vertWidth = 0;
+width = 252;
+},
+{
+layerId = "A99E50E2-B754-449B-A60B-37BA27802C99";
+paths = (
+{
+closed = 1;
+nodes = (
+"260 0 LINE",
+"260 512 LINE SMOOTH",
+"260 559 OFFCURVE",
+"280 574 OFFCURVE",
+"312 574 CURVE SMOOTH",
+"328 574 OFFCURVE",
+"346 570 OFFCURVE",
+"362 564 CURVE",
+"392 690 LINE",
+"370 698 OFFCURVE",
+"332 708 OFFCURVE",
+"286 708 CURVE SMOOTH",
+"138 708 OFFCURVE",
+"88 613 OFFCURVE",
+"88 506 CURVE SMOOTH",
+"88 0 LINE"
+);
+},
+{
+closed = 1;
+nodes = (
+"344 366 LINE",
+"344 500 LINE",
+"98 500 LINE",
+"22 494 LINE",
+"22 366 LINE"
+);
+}
+);
+vertWidth = 0;
+width = 360;
+}
+);
+note = "";
+unicode = 0066;
+},
+{
+glyphname = n;
+layers = (
+{
+layerId = "8DB0CCF0-BD6F-426B-90E2-48FD021BE868";
+paths = (
+{
+closed = 1;
+nodes = (
+"126 0 LINE",
+"126 366 LINE",
+"188 430 OFFCURVE",
+"232 462 OFFCURVE",
+"292 462 CURVE SMOOTH",
+"374 462 OFFCURVE",
+"408 410 OFFCURVE",
+"408 304 CURVE SMOOTH",
+"408 0 LINE",
+"438 0 LINE",
+"438 308 LINE SMOOTH",
+"438 432 OFFCURVE",
+"392 490 OFFCURVE",
+"294 490 CURVE SMOOTH",
+"228 490 OFFCURVE",
+"178 452 OFFCURVE",
+"128 402 CURVE",
+"126 402 LINE",
+"122 478 LINE",
+"96 478 LINE",
+"96 0 LINE"
+);
+}
+);
+vertWidth = 0;
+width = 526;
+},
+{
+layerId = "A99E50E2-B754-449B-A60B-37BA27802C99";
+paths = (
+{
+closed = 1;
+nodes = (
+"230 0 LINE",
+"230 328 LINE",
+"256 352 OFFCURVE",
+"274 366 OFFCURVE",
+"306 366 CURVE SMOOTH",
+"340 366 OFFCURVE",
+"356 350 OFFCURVE",
+"356 286 CURVE SMOOTH",
+"356 0 LINE",
+"528 0 LINE",
+"528 308 LINE SMOOTH",
+"528 432 OFFCURVE",
+"482 512 OFFCURVE",
+"372 512 CURVE SMOOTH",
+"304 512 OFFCURVE",
+"254 478 OFFCURVE",
+"214 440 CURVE",
+"210 440 LINE",
+"198 500 LINE",
+"58 500 LINE",
+"58 0 LINE"
+);
+}
+);
+vertWidth = 0;
+width = 582;
+}
+);
+note = "";
+unicode = 006E;
+},
+{
+glyphname = t;
+layers = (
+{
+layerId = "8DB0CCF0-BD6F-426B-90E2-48FD021BE868";
+paths = (
+{
+closed = 1;
+nodes = (
+"234 -12 OFFCURVE",
+"264 -4 OFFCURVE",
+"292 6 CURVE",
+"282 32 LINE",
+"264 24 OFFCURVE",
+"238 16 OFFCURVE",
+"220 16 CURVE SMOOTH",
+"150 16 OFFCURVE",
+"136 60 OFFCURVE",
+"136 122 CURVE SMOOTH",
+"136 450 LINE",
+"278 450 LINE",
+"278 478 LINE",
+"136 478 LINE",
+"136 618 LINE",
+"110 618 LINE",
+"106 478 LINE",
+"30 474 LINE",
+"30 450 LINE",
+"106 450 LINE",
+"106 126 LINE SMOOTH",
+"106 44 OFFCURVE",
+"130 -12 OFFCURVE",
+"218 -12 CURVE SMOOTH"
+);
+}
+);
+vertWidth = 0;
+width = 302;
+},
+{
+layerId = "A99E50E2-B754-449B-A60B-37BA27802C99";
+paths = (
+{
+closed = 1;
+nodes = (
+"319 -12 OFFCURVE",
+"356 -2 OFFCURVE",
+"382 6 CURVE",
+"356 130 LINE",
+"344 126 OFFCURVE",
+"328 122 OFFCURVE",
+"312 122 CURVE SMOOTH",
+"280 122 OFFCURVE",
+"252 140 OFFCURVE",
+"252 195 CURVE SMOOTH",
+"252 366 LINE",
+"366 366 LINE",
+"366 500 LINE",
+"252 500 LINE",
+"252 630 LINE",
+"110 630 LINE",
+"90 500 LINE",
+"14 494 LINE",
+"14 366 LINE",
+"80 366 LINE",
+"80 192 LINE SMOOTH",
+"80 70 OFFCURVE",
+"134 -12 OFFCURVE",
+"264 -12 CURVE SMOOTH"
+);
+}
+);
+vertWidth = 0;
+width = 400;
+}
+);
+note = "";
+unicode = 0074;
+},
+{
+glyphname = f_t;
+layers = (
+{
+layerId = "8DB0CCF0-BD6F-426B-90E2-48FD021BE868";
+paths = (
+{
+closed = 1;
+nodes = (
+"130 0 LINE",
+"130 592 LINE SMOOTH",
+"130 664 OFFCURVE",
+"154 706 OFFCURVE",
+"208 706 CURVE SMOOTH",
+"226 706 OFFCURVE",
+"246 702 OFFCURVE",
+"266 692 CURVE",
+"276 718 LINE",
+"254 728 OFFCURVE",
+"230 734 OFFCURVE",
+"210 734 CURVE SMOOTH",
+"142 734 OFFCURVE",
+"100 690 OFFCURVE",
+"100 596 CURVE SMOOTH",
+"100 0 LINE"
+);
+},
+{
+closed = 1;
+nodes = (
+"450 -12 OFFCURVE",
+"480 -4 OFFCURVE",
+"508 6 CURVE",
+"498 32 LINE",
+"480 24 OFFCURVE",
+"454 16 OFFCURVE",
+"436 16 CURVE SMOOTH",
+"366 16 OFFCURVE",
+"352 60 OFFCURVE",
+"352 122 CURVE SMOOTH",
+"352 450 LINE",
+"494 450 LINE",
+"494 478 LINE",
+"352 478 LINE",
+"352 618 LINE",
+"326 618 LINE",
+"322 478 LINE",
+"100 478 LINE",
+"34 474 LINE",
+"34 450 LINE",
+"322 450 LINE",
+"322 126 LINE SMOOTH",
+"322 44 OFFCURVE",
+"346 -12 OFFCURVE",
+"434 -12 CURVE SMOOTH"
+);
+}
+);
+vertWidth = 0;
+width = 518;
+},
+{
+layerId = "A99E50E2-B754-449B-A60B-37BA27802C99";
+paths = (
+{
+closed = 1;
+nodes = (
+"260 0 LINE",
+"260 512 LINE SMOOTH",
+"260 559 OFFCURVE",
+"280 574 OFFCURVE",
+"312 574 CURVE SMOOTH",
+"328 574 OFFCURVE",
+"346 570 OFFCURVE",
+"362 564 CURVE",
+"392 690 LINE",
+"370 698 OFFCURVE",
+"332 708 OFFCURVE",
+"286 708 CURVE SMOOTH",
+"138 708 OFFCURVE",
+"88 613 OFFCURVE",
+"88 506 CURVE SMOOTH",
+"88 0 LINE"
+);
+},
+{
+closed = 1;
+nodes = (
+"643 -12 OFFCURVE",
+"680 -2 OFFCURVE",
+"706 6 CURVE",
+"680 130 LINE",
+"668 126 OFFCURVE",
+"652 122 OFFCURVE",
+"636 122 CURVE SMOOTH",
+"604 122 OFFCURVE",
+"576 140 OFFCURVE",
+"576 195 CURVE",
+"576 366 LINE",
+"690 366 LINE",
+"690 500 LINE",
+"576 500 LINE",
+"576 630 LINE",
+"434 630 LINE",
+"414 500 LINE",
+"98 500 LINE",
+"22 494 LINE",
+"22 366 LINE",
+"404 366 LINE",
+"404 192 LINE SMOOTH",
+"404 70 OFFCURVE",
+"458 -12 OFFCURVE",
+"588 -12 CURVE SMOOTH"
+);
+}
+);
+vertWidth = 0;
+width = 724;
+}
+);
+note = "";
+},
+{
+glyphname = a.alt;
+layers = (
+{
+layerId = "8DB0CCF0-BD6F-426B-90E2-48FD021BE868";
+paths = (
+{
+closed = 1;
+nodes = (
+"318 -12 OFFCURVE",
+"372 24 OFFCURVE",
+"412 64 CURVE",
+"414 64 LINE",
+"418 0 LINE",
+"444 0 LINE",
+"444 478 LINE",
+"416 478 LINE",
+"414 432 LINE",
+"412 432 LINE",
+"366 468 OFFCURVE",
+"326 490 OFFCURVE",
+"268 490 CURVE SMOOTH",
+"152 490 OFFCURVE",
+"54 392 OFFCURVE",
+"54 238 CURVE SMOOTH",
+"54 76 OFFCURVE",
+"132 -12 OFFCURVE",
+"252 -12 CURVE SMOOTH"
+);
+},
+{
+closed = 1;
+nodes = (
+"146 16 OFFCURVE",
+"86 106 OFFCURVE",
+"86 238 CURVE SMOOTH",
+"86 362 OFFCURVE",
+"164 462 OFFCURVE",
+"266 462 CURVE SMOOTH",
+"316 462 OFFCURVE",
+"360 444 OFFCURVE",
+"414 396 CURVE",
+"414 100 LINE",
+"360 46 OFFCURVE",
+"310 16 OFFCURVE",
+"254 16 CURVE SMOOTH"
+);
+}
+);
+vertWidth = 0;
+width = 540;
+},
+{
+layerId = "A99E50E2-B754-449B-A60B-37BA27802C99";
+paths = (
+{
+closed = 1;
+nodes = (
+"284 -12 OFFCURVE",
+"332 12 OFFCURVE",
+"366 46 CURVE",
+"370 46 LINE",
+"382 0 LINE",
+"522 0 LINE",
+"522 500 LINE",
+"388 500 LINE",
+"374 450 LINE",
+"370 450 LINE",
+"332 494 OFFCURVE",
+"292 512 OFFCURVE",
+"244 512 CURVE SMOOTH",
+"142 512 OFFCURVE",
+"36 414 OFFCURVE",
+"36 250 CURVE SMOOTH",
+"36 88 OFFCURVE",
+"116 -12 OFFCURVE",
+"240 -12 CURVE SMOOTH"
+);
+},
+{
+closed = 1;
+nodes = (
+"240 128 OFFCURVE",
+"212 162 OFFCURVE",
+"212 252 CURVE SMOOTH",
+"212 340 OFFCURVE",
+"246 372 OFFCURVE",
+"282 372 CURVE SMOOTH",
+"304 372 OFFCURVE",
+"330 366 OFFCURVE",
+"350 348 CURVE",
+"350 164 LINE",
+"332 136 OFFCURVE",
+"312 128 OFFCURVE",
+"286 128 CURVE SMOOTH"
+);
+}
+);
+vertWidth = 0;
+width = 580;
+}
+);
+note = "";
+},
+{
+glyphname = A.sc;
+layers = (
+{
+layerId = "8DB0CCF0-BD6F-426B-90E2-48FD021BE868";
+paths = (
+{
+closed = 1;
+nodes = (
+"42 0 LINE",
+"158 304 LINE SMOOTH",
+"181 366 OFFCURVE",
+"199 414 OFFCURVE",
+"220 475 CURVE",
+"224 475 LINE",
+"245 415 OFFCURVE",
+"263 367 OFFCURVE",
+"286 304 CURVE SMOOTH",
+"400 0 LINE",
+"434 0 LINE",
+"236 510 LINE",
+"207 510 LINE",
+"10 0 LINE"
+);
+},
+{
+closed = 1;
+nodes = (
+"345 176 LINE",
+"345 204 LINE",
+"97 204 LINE",
+"97 176 LINE"
+);
+}
+);
+vertWidth = 0;
+width = 444;
+},
+{
+layerId = "A99E50E2-B754-449B-A60B-37BA27802C99";
+paths = (
+{
+closed = 1;
+nodes = (
+"164 0 LINE",
+"219 244 LINE SMOOTH",
+"230 292 OFFCURVE",
+"241 358 OFFCURVE",
+"252 409 CURVE",
+"256 409 LINE",
+"269 359 OFFCURVE",
+"280 292 OFFCURVE",
+"291 244 CURVE SMOOTH",
+"346 0 LINE",
+"526 0 LINE",
+"361 532 LINE",
+"155 532 LINE",
+"-10 0 LINE"
+);
+},
+{
+closed = 1;
+nodes = (
+"397 94 LINE",
+"397 216 LINE",
+"118 216 LINE",
+"118 94 LINE"
+);
+}
+);
+vertWidth = 0;
+width = 516;
+}
+);
+note = "";
+},
+{
+glyphname = atilde;
+layers = (
+{
+components = (
+{
+name = a;
+},
+{
+name = tildecmb;
+transform = "{1, 0, 0, 1, 242, 0}";
+}
+);
+layerId = "8DB0CCF0-BD6F-426B-90E2-48FD021BE868";
+vertWidth = 0;
+width = 486;
+},
+{
+components = (
+{
+name = a;
+},
+{
+name = tildecmb;
+transform = "{1, 0, 0, 1, 266, 0}";
+}
+);
+layerId = "A99E50E2-B754-449B-A60B-37BA27802C99";
+vertWidth = 0;
+width = 536;
+}
+);
+note = "";
+unicode = 00E3;
+},
+{
+glyphname = ampersand;
+layers = (
+{
+layerId = "8DB0CCF0-BD6F-426B-90E2-48FD021BE868";
+paths = (
+{
+closed = 1;
+nodes = (
+"302 -12 OFFCURVE",
+"360 28 OFFCURVE",
+"410 84 CURVE SMOOTH",
+"468 153 OFFCURVE",
+"510 244 OFFCURVE",
+"538 342 CURVE",
+"508 342 LINE",
+"482 248 OFFCURVE",
+"444 166 OFFCURVE",
+"388 102 CURVE SMOOTH",
+"344 52 OFFCURVE",
+"288 16 OFFCURVE",
+"226 16 CURVE SMOOTH",
+"142 16 OFFCURVE",
+"70 76 OFFCURVE",
+"70 168 CURVE SMOOTH",
+"70 332 OFFCURVE",
+"364 392 OFFCURVE",
+"364 556 CURVE SMOOTH",
+"364 622 OFFCURVE",
+"328 672 OFFCURVE",
+"260 672 CURVE SMOOTH",
+"184 672 OFFCURVE",
+"130 612 OFFCURVE",
+"130 528 CURVE SMOOTH",
+"130 382 OFFCURVE",
+"264 196 OFFCURVE",
+"392 82 CURVE SMOOTH",
+"446 34 OFFCURVE",
+"496 4 OFFCURVE",
+"538 -12 CURVE",
+"550 16 LINE",
+"508 32 OFFCURVE",
+"460 62 OFFCURVE",
+"410 106 CURVE SMOOTH",
+"290 210 OFFCURVE",
+"160 392 OFFCURVE",
+"160 530 CURVE SMOOTH",
+"160 592 OFFCURVE",
+"196 644 OFFCURVE",
+"258 644 CURVE SMOOTH",
+"314 644 OFFCURVE",
+"334 598 OFFCURVE",
+"334 554 CURVE SMOOTH",
+"334 402 OFFCURVE",
+"38 346 OFFCURVE",
+"38 166 CURVE SMOOTH",
+"38 56 OFFCURVE",
+"124 -12 OFFCURVE",
+"224 -12 CURVE SMOOTH"
+);
+}
+);
+vertWidth = 0;
+width = 562;
+},
+{
+layerId = "A99E50E2-B754-449B-A60B-37BA27802C99";
+paths = (
+{
+closed = 1;
+nodes = (
+"362 -12 OFFCURVE",
+"452 34 OFFCURVE",
+"516 104 CURVE SMOOTH",
+"590 187 OFFCURVE",
+"638 276 OFFCURVE",
+"668 374 CURVE",
+"512 374 LINE",
+"490 292 OFFCURVE",
+"448 228 OFFCURVE",
+"398 180 CURVE SMOOTH",
+"356 142 OFFCURVE",
+"310 118 OFFCURVE",
+"268 118 CURVE SMOOTH",
+"216 118 OFFCURVE",
+"184 146 OFFCURVE",
+"184 186 CURVE SMOOTH",
+"184 296 OFFCURVE",
+"458 332 OFFCURVE",
+"458 508 CURVE SMOOTH",
+"458 602 OFFCURVE",
+"390 662 OFFCURVE",
+"286 662 CURVE SMOOTH",
+"170 662 OFFCURVE",
+"98 580 OFFCURVE",
+"98 486 CURVE SMOOTH",
+"98 359 OFFCURVE",
+"244 182 OFFCURVE",
+"415 75 CURVE SMOOTH",
+"485 31 OFFCURVE",
+"560 0 OFFCURVE",
+"630 -12 CURVE",
+"670 126 LINE",
+"627 131 OFFCURVE",
+"573 153 OFFCURVE",
+"518 183 CURVE SMOOTH",
+"382 258 OFFCURVE",
+"239 390 OFFCURVE",
+"239 486 CURVE SMOOTH",
+"239 528 OFFCURVE",
+"263 550 OFFCURVE",
+"290 550 CURVE SMOOTH",
+"315 550 OFFCURVE",
+"328 536 OFFCURVE",
+"328 508 CURVE SMOOTH",
+"328 386 OFFCURVE",
+"22 396 OFFCURVE",
+"22 176 CURVE SMOOTH",
+"22 78 OFFCURVE",
+"95 -12 OFFCURVE",
+"246 -12 CURVE SMOOTH"
+);
+}
+);
+vertWidth = 0;
+width = 690;
+}
+);
+note = "";
+unicode = 0026;
+},
+{
+glyphname = circledotted;
+production = uni25CC;
+layers = (
+{
+layerId = "8DB0CCF0-BD6F-426B-90E2-48FD021BE868";
+paths = (
+{
+closed = 1;
+nodes = (
+"129 97 OFFCURVE",
+"141 110 OFFCURVE",
+"141 129 CURVE SMOOTH",
+"141 150 OFFCURVE",
+"128 161 OFFCURVE",
+"110 161 CURVE SMOOTH",
+"94 161 OFFCURVE",
+"81 150 OFFCURVE",
+"81 129 CURVE SMOOTH",
+"81 110 OFFCURVE",
+"94 97 OFFCURVE",
+"110 97 CURVE SMOOTH"
+);
+},
+{
+closed = 1;
+nodes = (
+"101 207 OFFCURVE",
+"114 219 OFFCURVE",
+"114 239 CURVE SMOOTH",
+"114 260 OFFCURVE",
+"101 270 OFFCURVE",
+"82 270 CURVE SMOOTH",
+"67 270 OFFCURVE",
+"54 260 OFFCURVE",
+"54 239 CURVE SMOOTH",
+"54 219 OFFCURVE",
+"67 207 OFFCURVE",
+"82 207 CURVE SMOOTH"
+);
+},
+{
+closed = 1;
+nodes = (
+"129 318 OFFCURVE",
+"141 330 OFFCURVE",
+"141 351 CURVE SMOOTH",
+"141 371 OFFCURVE",
+"128 382 OFFCURVE",
+"110 382 CURVE SMOOTH",
+"94 382 OFFCURVE",
+"81 371 OFFCURVE",
+"81 351 CURVE SMOOTH",
+"81 330 OFFCURVE",
+"94 318 OFFCURVE",
+"110 318 CURVE SMOOTH"
+);
+},
+{
+closed = 1;
+nodes = (
+"207 15 OFFCURVE",
+"219 27 OFFCURVE",
+"219 49 CURVE SMOOTH",
+"219 68 OFFCURVE",
+"206 78 OFFCURVE",
+"189 78 CURVE SMOOTH",
+"173 78 OFFCURVE",
+"160 68 OFFCURVE",
+"160 49 CURVE SMOOTH",
+"160 27 OFFCURVE",
+"173 15 OFFCURVE",
+"189 15 CURVE SMOOTH"
+);
+},
+{
+closed = 1;
+nodes = (
+"207 400 OFFCURVE",
+"219 412 OFFCURVE",
+"219 431 CURVE SMOOTH",
+"219 453 OFFCURVE",
+"206 463 OFFCURVE",
+"189 463 CURVE SMOOTH",
+"173 463 OFFCURVE",
+"160 453 OFFCURVE",
+"160 431 CURVE SMOOTH",
+"160 412 OFFCURVE",
+"173 400 OFFCURVE",
+"189 400 CURVE SMOOTH"
+);
+},
+{
+closed = 1;
+nodes = (
+"313 -12 OFFCURVE",
+"326 -1 OFFCURVE",
+"326 20 CURVE SMOOTH",
+"326 40 OFFCURVE",
+"313 51 OFFCURVE",
+"295 51 CURVE SMOOTH",
+"279 51 OFFCURVE",
+"266 40 OFFCURVE",
+"266 20 CURVE SMOOTH",
+"266 -1 OFFCURVE",
+"279 -12 OFFCURVE",
+"295 -12 CURVE SMOOTH"
+);
+},
+{
+closed = 1;
+nodes = (
+"313 426 OFFCURVE",
+"326 438 OFFCURVE",
+"326 458 CURVE SMOOTH",
+"326 478 OFFCURVE",
+"313 490 OFFCURVE",
+"295 490 CURVE SMOOTH",
+"279 490 OFFCURVE",
+"266 478 OFFCURVE",
+"266 458 CURVE SMOOTH",
+"266 438 OFFCURVE",
+"279 426 OFFCURVE",
+"295 426 CURVE SMOOTH"
+);
+},
+{
+closed = 1;
+nodes = (
+"420 15 OFFCURVE",
+"431 27 OFFCURVE",
+"431 49 CURVE SMOOTH",
+"431 68 OFFCURVE",
+"418 78 OFFCURVE",
+"401 78 CURVE SMOOTH",
+"386 78 OFFCURVE",
+"373 68 OFFCURVE",
+"373 49 CURVE SMOOTH",
+"373 27 OFFCURVE",
+"386 15 OFFCURVE",
+"401 15 CURVE SMOOTH"
+);
+},
+{
+closed = 1;
+nodes = (
+"420 399 OFFCURVE",
+"431 412 OFFCURVE",
+"431 431 CURVE SMOOTH",
+"431 452 OFFCURVE",
+"418 462 OFFCURVE",
+"401 462 CURVE SMOOTH",
+"386 462 OFFCURVE",
+"373 452 OFFCURVE",
+"373 431 CURVE SMOOTH",
+"373 412 OFFCURVE",
+"386 399 OFFCURVE",
+"401 399 CURVE SMOOTH"
+);
+},
+{
+closed = 1;
+nodes = (
+"499 97 OFFCURVE",
+"510 110 OFFCURVE",
+"510 129 CURVE SMOOTH",
+"510 150 OFFCURVE",
+"497 161 OFFCURVE",
+"480 161 CURVE SMOOTH",
+"465 161 OFFCURVE",
+"451 150 OFFCURVE",
+"451 129 CURVE SMOOTH",
+"451 110 OFFCURVE",
+"465 97 OFFCURVE",
+"480 97 CURVE SMOOTH"
+);
+},
+{
+closed = 1;
+nodes = (
+"526 207 OFFCURVE",
+"538 219 OFFCURVE",
+"538 239 CURVE SMOOTH",
+"538 260 OFFCURVE",
+"523 270 OFFCURVE",
+"508 270 CURVE SMOOTH",
+"491 270 OFFCURVE",
+"478 260 OFFCURVE",
+"478 239 CURVE SMOOTH",
+"478 219 OFFCURVE",
+"491 207 OFFCURVE",
+"508 207 CURVE SMOOTH"
+);
+},
+{
+closed = 1;
+nodes = (
+"499 317 OFFCURVE",
+"510 329 OFFCURVE",
+"510 349 CURVE SMOOTH",
+"510 369 OFFCURVE",
+"497 380 OFFCURVE",
+"480 380 CURVE SMOOTH",
+"465 380 OFFCURVE",
+"451 369 OFFCURVE",
+"451 349 CURVE SMOOTH",
+"451 329 OFFCURVE",
+"465 317 OFFCURVE",
+"480 317 CURVE SMOOTH"
+);
+}
+);
+vertWidth = 0;
+width = 592;
+},
+{
+layerId = "A99E50E2-B754-449B-A60B-37BA27802C99";
+paths = (
+{
+closed = 1;
+nodes = (
+"131 96 OFFCURVE",
+"149 112 OFFCURVE",
+"149 141 CURVE SMOOTH",
+"149 170 OFFCURVE",
+"130 187 OFFCURVE",
+"104 187 CURVE SMOOTH",
+"82 187 OFFCURVE",
+"61 170 OFFCURVE",
+"61 141 CURVE SMOOTH",
+"61 112 OFFCURVE",
+"82 96 OFFCURVE",
+"104 96 CURVE SMOOTH"
+);
+},
+{
+closed = 1;
+nodes = (
+"104 204 OFFCURVE",
+"122 221 OFFCURVE",
+"122 251 CURVE SMOOTH",
+"122 279 OFFCURVE",
+"102 295 OFFCURVE",
+"76 295 CURVE SMOOTH",
+"53 295 OFFCURVE",
+"32 279 OFFCURVE",
+"32 251 CURVE SMOOTH",
+"32 221 OFFCURVE",
+"53 204 OFFCURVE",
+"76 204 CURVE SMOOTH"
+);
+},
+{
+closed = 1;
+nodes = (
+"131 313 OFFCURVE",
+"149 331 OFFCURVE",
+"149 360 CURVE SMOOTH",
+"149 390 OFFCURVE",
+"130 405 OFFCURVE",
+"104 405 CURVE SMOOTH",
+"82 405 OFFCURVE",
+"61 390 OFFCURVE",
+"61 360 CURVE SMOOTH",
+"61 331 OFFCURVE",
+"82 313 OFFCURVE",
+"104 313 CURVE SMOOTH"
+);
+},
+{
+closed = 1;
+nodes = (
+"208 14 OFFCURVE",
+"227 31 OFFCURVE",
+"227 61 CURVE SMOOTH",
+"227 89 OFFCURVE",
+"206 105 OFFCURVE",
+"182 105 CURVE SMOOTH",
+"158 105 OFFCURVE",
+"137 89 OFFCURVE",
+"137 61 CURVE SMOOTH",
+"137 31 OFFCURVE",
+"158 14 OFFCURVE",
+"182 14 CURVE SMOOTH"
+);
+},
+{
+closed = 1;
+nodes = (
+"208 395 OFFCURVE",
+"227 412 OFFCURVE",
+"227 440 CURVE SMOOTH",
+"227 470 OFFCURVE",
+"206 486 OFFCURVE",
+"182 486 CURVE SMOOTH",
+"158 486 OFFCURVE",
+"137 470 OFFCURVE",
+"137 440 CURVE SMOOTH",
+"137 412 OFFCURVE",
+"158 395 OFFCURVE",
+"182 395 CURVE SMOOTH"
+);
+},
+{
+closed = 1;
+nodes = (
+"314 -13 OFFCURVE",
+"332 4 OFFCURVE",
+"332 34 CURVE SMOOTH",
+"332 62 OFFCURVE",
+"313 78 OFFCURVE",
+"287 78 CURVE SMOOTH",
+"264 78 OFFCURVE",
+"244 62 OFFCURVE",
+"244 34 CURVE SMOOTH",
+"244 4 OFFCURVE",
+"264 -13 OFFCURVE",
+"287 -13 CURVE SMOOTH"
+);
+},
+{
+closed = 1;
+nodes = (
+"314 421 OFFCURVE",
+"332 439 OFFCURVE",
+"332 468 CURVE SMOOTH",
+"332 496 OFFCURVE",
+"313 512 OFFCURVE",
+"287 512 CURVE SMOOTH",
+"264 512 OFFCURVE",
+"244 496 OFFCURVE",
+"244 468 CURVE SMOOTH",
+"244 439 OFFCURVE",
+"264 421 OFFCURVE",
+"287 421 CURVE SMOOTH"
+);
+},
+{
+closed = 1;
+nodes = (
+"420 14 OFFCURVE",
+"438 31 OFFCURVE",
+"438 61 CURVE SMOOTH",
+"438 89 OFFCURVE",
+"417 105 OFFCURVE",
+"392 105 CURVE SMOOTH",
+"369 105 OFFCURVE",
+"348 89 OFFCURVE",
+"348 61 CURVE SMOOTH",
+"348 31 OFFCURVE",
+"369 14 OFFCURVE",
+"392 14 CURVE SMOOTH"
+);
+},
+{
+closed = 1;
+nodes = (
+"420 394 OFFCURVE",
+"438 411 OFFCURVE",
+"438 440 CURVE SMOOTH",
+"438 469 OFFCURVE",
+"417 486 OFFCURVE",
+"392 486 CURVE SMOOTH",
+"369 486 OFFCURVE",
+"348 469 OFFCURVE",
+"348 440 CURVE SMOOTH",
+"348 411 OFFCURVE",
+"369 394 OFFCURVE",
+"392 394 CURVE SMOOTH"
+);
+},
+{
+closed = 1;
+nodes = (
+"498 96 OFFCURVE",
+"516 112 OFFCURVE",
+"516 141 CURVE SMOOTH",
+"516 170 OFFCURVE",
+"496 187 OFFCURVE",
+"472 187 CURVE SMOOTH",
+"447 187 OFFCURVE",
+"426 170 OFFCURVE",
+"426 141 CURVE SMOOTH",
+"426 112 OFFCURVE",
+"447 96 OFFCURVE",
+"472 96 CURVE SMOOTH"
+);
+},
+{
+closed = 1;
+nodes = (
+"524 204 OFFCURVE",
+"543 221 OFFCURVE",
+"543 251 CURVE SMOOTH",
+"543 279 OFFCURVE",
+"522 295 OFFCURVE",
+"498 295 CURVE SMOOTH",
+"473 295 OFFCURVE",
+"453 279 OFFCURVE",
+"453 251 CURVE SMOOTH",
+"453 221 OFFCURVE",
+"473 204 OFFCURVE",
+"498 204 CURVE SMOOTH"
+);
+},
+{
+closed = 1;
+nodes = (
+"498 313 OFFCURVE",
+"516 330 OFFCURVE",
+"516 359 CURVE SMOOTH",
+"516 388 OFFCURVE",
+"496 404 OFFCURVE",
+"472 404 CURVE SMOOTH",
+"447 404 OFFCURVE",
+"426 388 OFFCURVE",
+"426 359 CURVE SMOOTH",
+"426 330 OFFCURVE",
+"447 313 OFFCURVE",
+"472 313 CURVE SMOOTH"
+);
+}
+);
+vertWidth = 0;
+width = 574;
+}
+);
+note = "";
+unicode = 25CC;
+},
+{
+glyphname = tildecmb;
+production = uni0303;
+layers = (
+{
+layerId = "8DB0CCF0-BD6F-426B-90E2-48FD021BE868";
+paths = (
+{
+closed = 1;
+nodes = (
+"140 580 OFFCURVE",
+"156 646 OFFCURVE",
+"160 702 CURVE",
+"134 704 LINE",
+"132 652 OFFCURVE",
+"116 606 OFFCURVE",
+"79 606 CURVE SMOOTH",
+"20 606 OFFCURVE",
+"0 706 OFFCURVE",
+"-76 706 CURVE SMOOTH",
+"-140 706 OFFCURVE",
+"-156 641 OFFCURVE",
+"-160 584 CURVE",
+"-134 582 LINE",
+"-132 636 OFFCURVE",
+"-116 680 OFFCURVE",
+"-78 680 CURVE SMOOTH",
+"-20 680 OFFCURVE",
+"0 580 OFFCURVE",
+"77 580 CURVE SMOOTH"
+);
+}
+);
+vertWidth = 0;
+width = 0;
+},
+{
+layerId = "A99E50E2-B754-449B-A60B-37BA27802C99";
+paths = (
+{
+closed = 1;
+nodes = (
+"144 572 OFFCURVE",
+"194 617 OFFCURVE",
+"196 730 CURVE",
+"90 736 LINE",
+"86 700 OFFCURVE",
+"76 690 OFFCURVE",
+"60 690 CURVE SMOOTH",
+"34 690 OFFCURVE",
+"-4 746 OFFCURVE",
+"-64 746 CURVE SMOOTH",
+"-144 746 OFFCURVE",
+"-194 701 OFFCURVE",
+"-196 588 CURVE",
+"-90 582 LINE",
+"-86 618 OFFCURVE",
+"-76 628 OFFCURVE",
+"-60 628 CURVE SMOOTH",
+"-34 628 OFFCURVE",
+"4 572 OFFCURVE",
+"64 572 CURVE SMOOTH"
+);
+}
+);
+vertWidth = 0;
+width = 0;
+}
+);
+note = "";
+unicode = 0303;
+},
+{
+glyphname = dieresiscmb;
+production = uni0308;
+layers = (
+{
+layerId = "8DB0CCF0-BD6F-426B-90E2-48FD021BE868";
+paths = (
+{
+closed = 1;
+nodes = (
+"-68 602 OFFCURVE",
+"-54 616 OFFCURVE",
+"-54 634 CURVE SMOOTH",
+"-54 652 OFFCURVE",
+"-68 666 OFFCURVE",
+"-86 666 CURVE SMOOTH",
+"-104 666 OFFCURVE",
+"-118 652 OFFCURVE",
+"-118 634 CURVE SMOOTH",
+"-118 616 OFFCURVE",
+"-104 602 OFFCURVE",
+"-86 602 CURVE SMOOTH"
+);
+},
+{
+closed = 1;
+nodes = (
+"104 602 OFFCURVE",
+"118 616 OFFCURVE",
+"118 634 CURVE SMOOTH",
+"118 652 OFFCURVE",
+"104 666 OFFCURVE",
+"86 666 CURVE SMOOTH",
+"68 666 OFFCURVE",
+"54 652 OFFCURVE",
+"54 634 CURVE SMOOTH",
+"54 616 OFFCURVE",
+"68 602 OFFCURVE",
+"86 602 CURVE SMOOTH"
+);
+}
+);
+vertWidth = 0;
+width = 0;
+},
+{
+layerId = "A99E50E2-B754-449B-A60B-37BA27802C99";
+paths = (
+{
+closed = 1;
+nodes = (
+"-67 562 OFFCURVE",
+"-34 597 OFFCURVE",
+"-34 642 CURVE SMOOTH",
+"-34 687 OFFCURVE",
+"-67 722 OFFCURVE",
+"-114 722 CURVE SMOOTH",
+"-161 722 OFFCURVE",
+"-194 687 OFFCURVE",
+"-194 642 CURVE SMOOTH",
+"-194 597 OFFCURVE",
+"-161 562 OFFCURVE",
+"-114 562 CURVE SMOOTH"
+);
+},
+{
+closed = 1;
+nodes = (
+"161 562 OFFCURVE",
+"194 597 OFFCURVE",
+"194 642 CURVE SMOOTH",
+"194 687 OFFCURVE",
+"161 722 OFFCURVE",
+"114 722 CURVE SMOOTH",
+"67 722 OFFCURVE",
+"34 687 OFFCURVE",
+"34 642 CURVE SMOOTH",
+"34 597 OFFCURVE",
+"67 562 OFFCURVE",
+"114 562 CURVE SMOOTH"
+);
+}
+);
+vertWidth = 0;
+width = 0;
+}
+);
+note = "";
+unicode = 0308;
+},
+{
+glyphname = tildebelowcmb;
+production = uni0330;
+layers = (
+{
+components = (
+{
+name = tildecmb;
+transform = "{1, 0, 0, 1, 0, -800}";
+}
+);
+layerId = "8DB0CCF0-BD6F-426B-90E2-48FD021BE868";
+vertWidth = 0;
+width = 0;
+},
+{
+components = (
+{
+name = tildecmb;
+transform = "{1, 0, 0, 1, 0, -800}";
+}
+);
+layerId = "A99E50E2-B754-449B-A60B-37BA27802C99";
+vertWidth = 0;
+width = 0;
+}
+);
+note = "";
+unicode = 0330;
+},
+{
+glyphname = dieresisbelowcmb;
+production = uni0324;
+layers = (
+{
+components = (
+{
+name = dieresiscmb;
+transform = "{1, 0, 0, 1, 0, -790}";
+}
+);
+layerId = "8DB0CCF0-BD6F-426B-90E2-48FD021BE868";
+vertWidth = 0;
+width = 0;
+},
+{
+components = (
+{
+name = dieresiscmb;
+transform = "{1, 0, 0, 1, 0, -786}";
+}
+);
+layerId = "A99E50E2-B754-449B-A60B-37BA27802C99";
+vertWidth = 0;
+width = 0;
+}
+);
+note = "";
+unicode = 0324;
+}
+);
+instances = (
+{
+customParameters = (
+{
+name = weightClass;
+value = 0;
+},
+{
+name = postscriptFontName;
+value = "TestFamily2-ExtraLight";
+},
+{
+name = "UFO Filename";
+value = "instances/TestFamily2-ExtraLight.ufo";
+}
+);
+interpolationWeight = 0;
+name = ExtraLight;
+weightClass = Thin;
+},
+{
+customParameters = (
+{
+name = postscriptFontName;
+value = "TestFamily2-Light";
+},
+{
+name = "UFO Filename";
+value = "instances/TestFamily2-Light.ufo";
+}
+);
+name = Light;
+weightClass = Thin;
+},
+{
+customParameters = (
+{
+name = weightClass;
+value = 368;
+},
+{
+name = postscriptFontName;
+value = "TestFamily2-Regular";
+},
+{
+name = "UFO Filename";
+value = "instances/TestFamily2-Regular.ufo";
+}
+);
+interpolationWeight = 368;
+name = Regular;
+weightClass = Normal;
+},
+{
+customParameters = (
+{
+name = postscriptFontName;
+value = "TestFamily2-Semibold";
+},
+{
+name = "UFO Filename";
+value = "instances/TestFamily2-Semibold.ufo";
+}
+);
+interpolationWeight = 600;
+name = Semibold;
+weightClass = DemiBold;
+},
+{
+customParameters = (
+{
+name = weightClass;
+value = 824;
+},
+{
+name = postscriptFontName;
+value = "TestFamily2-Bold";
+},
+{
+name = "UFO Filename";
+value = "instances/TestFamily2-Bold.ufo";
+}
+);
+interpolationWeight = 824;
+name = Bold;
+weightClass = ExtraBold;
+},
+{
+customParameters = (
+{
+name = weightClass;
+value = 1000;
+},
+{
+name = postscriptFontName;
+value = "TestFamily2-Black";
+},
+{
+name = "UFO Filename";
+value = "instances/TestFamily2-Black.ufo";
+}
+);
+interpolationWeight = 1000;
+name = Black;
+weightClass = Black;
+}
+);
+unitsPerEm = 1000;
+userData = {
+com.schriftgestaltung.Glyphs.groupsNotInFeature = (
+);
+};
+versionMajor = 2;
+versionMinor = 20;
+}
diff --git a/Tests/varLib/data/SparseCFF2.designspace b/Tests/varLib/data/SparseCFF2.designspace
new file mode 100644
index 00000000..cd8823a7
--- /dev/null
+++ b/Tests/varLib/data/SparseCFF2.designspace
@@ -0,0 +1,23 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<designspace format="5.0">
+ <axes>
+ <axis tag="wght" name="Weight" minimum="350" maximum="625" default="350"/>
+ </axes>
+ <sources>
+ <source filename="master_sparse_cff2_empty/SparseCFF-Regular.ttx" name="Sparse Font Regular" familyname="Sparse Font" stylename="Regular">
+ <location>
+ <dimension name="Weight" xvalue="350"/>
+ </location>
+ </source>
+ <source filename="master_sparse_cff2_empty/SparseCFF-Medium.ttx" name="Sparse Font Medium" familyname="Sparse Font" stylename="Medium">
+ <location>
+ <dimension name="Weight" xvalue="450"/>
+ </location>
+ </source>
+ <source filename="master_sparse_cff2_empty/SparseCFF-Bold.ttx" name="Sparse Font Bold" familyname="Sparse Font" stylename="Bold">
+ <location>
+ <dimension name="Weight" xvalue="625"/>
+ </location>
+ </source>
+ </sources>
+</designspace>
diff --git a/Tests/varLib/data/SparseMasters.glyphs b/Tests/varLib/data/SparseMasters.glyphs
new file mode 100644
index 00000000..a9843a46
--- /dev/null
+++ b/Tests/varLib/data/SparseMasters.glyphs
@@ -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;
+}
diff --git a/Tests/varLib/data/SparseMasters_ufo.designspace b/Tests/varLib/data/SparseMasters_ufo.designspace
new file mode 100644
index 00000000..1fd57bca
--- /dev/null
+++ b/Tests/varLib/data/SparseMasters_ufo.designspace
@@ -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>
diff --git a/Tests/varLib/data/TestNoOverwriteSTAT.designspace b/Tests/varLib/data/TestNoOverwriteSTAT.designspace
new file mode 100644
index 00000000..e06a1be5
--- /dev/null
+++ b/Tests/varLib/data/TestNoOverwriteSTAT.designspace
@@ -0,0 +1,36 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<designspace format="5.0">
+ <axes>
+ <axis tag="wght" name="Weight" minimum="100" maximum="900" default="100">
+ <map input="100" output="30"/>
+ <map input="900" output="240"/>
+ </axis>
+ <axis tag="wdth" name="Width" minimum="80" maximum="115" default="80"/>
+ </axes>
+ <sources>
+ <source filename="master_no_overwrite_stat/Test-CondensedThin.ttx" name="Test Condensed Thin">
+ <location>
+ <dimension name="Weight" xvalue="30"/>
+ <dimension name="Width" xvalue="80"/>
+ </location>
+ </source>
+ <source filename="master_no_overwrite_stat/Test-CondensedBlack.ttx" name="Test Condensed Black">
+ <location>
+ <dimension name="Weight" xvalue="240"/>
+ <dimension name="Width" xvalue="80"/>
+ </location>
+ </source>
+ <source filename="master_no_overwrite_stat/Test-ExtendedThin.ttx" name="Test Extended Thin">
+ <location>
+ <dimension name="Weight" xvalue="30"/>
+ <dimension name="Width" xvalue="115"/>
+ </location>
+ </source>
+ <source filename="master_no_overwrite_stat/Test-ExtendedBlack.ttx" name="Test Extended Black">
+ <location>
+ <dimension name="Weight" xvalue="240"/>
+ <dimension name="Width" xvalue="115"/>
+ </location>
+ </source>
+ </sources>
+</designspace>
diff --git a/Tests/varLib/data/master_no_overwrite_stat/Test-CondensedBlack.ttx b/Tests/varLib/data/master_no_overwrite_stat/Test-CondensedBlack.ttx
new file mode 100644
index 00000000..db687a9f
--- /dev/null
+++ b/Tests/varLib/data/master_no_overwrite_stat/Test-CondensedBlack.ttx
@@ -0,0 +1,243 @@
+<?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"/>
+ </GlyphOrder>
+
+ <head>
+ <!-- Most of this table will be recalculated by the compiler -->
+ <tableVersion value="1.0"/>
+ <fontRevision value="3.013"/>
+ <checkSumAdjustment value="0x37268237"/>
+ <magicNumber value="0x5f0f3cf5"/>
+ <flags value="00000000 00000011"/>
+ <unitsPerEm value="1000"/>
+ <created value="Fri Feb 17 14:29:44 2023"/>
+ <modified value="Tue Mar 7 12:56:58 2023"/>
+ <xMin value="-2"/>
+ <yMin value="-250"/>
+ <xMax value="583"/>
+ <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="1000"/>
+ <descent value="-300"/>
+ <lineGap value="0"/>
+ <advanceWidthMax value="582"/>
+ <minLeftSideBearing value="-2"/>
+ <minRightSideBearing value="-1"/>
+ <xMaxExtent value="583"/>
+ <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="2"/>
+ </hhea>
+
+ <maxp>
+ <!-- Most of this table will be recalculated by the compiler -->
+ <tableVersion value="0x10000"/>
+ <numGlyphs value="2"/>
+ <maxPoints value="19"/>
+ <maxContours value="2"/>
+ <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="541"/>
+ <usWeightClass value="900"/>
+ <usWidthClass value="3"/>
+ <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="80"/>
+ <yStrikeoutPosition value="303"/>
+ <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 00000001"/>
+ <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="65"/>
+ <usLastCharIndex value="65"/>
+ <sTypoAscender value="750"/>
+ <sTypoDescender value="-250"/>
+ <sTypoLineGap value="250"/>
+ <usWinAscent value="1000"/>
+ <usWinDescent value="300"/>
+ <ulCodePageRange1 value="00000000 00000000 00000000 00000001"/>
+ <ulCodePageRange2 value="00000000 00000000 00000000 00000000"/>
+ <sxHeight value="505"/>
+ <sCapHeight value="670"/>
+ <usDefaultChar value="0"/>
+ <usBreakChar value="32"/>
+ <usMaxContext value="0"/>
+ </OS_2>
+
+ <hmtx>
+ <mtx name=".notdef" width="500" lsb="50"/>
+ <mtx name="A" width="582" lsb="-2"/>
+ </hmtx>
+
+ <cmap>
+ <tableVersion version="0"/>
+ <cmap_format_4 platformID="0" platEncID="3" language="0">
+ <map code="0x41" name="A"/><!-- LATIN CAPITAL LETTER A -->
+ </cmap_format_4>
+ <cmap_format_4 platformID="3" platEncID="1" language="0">
+ <map code="0x41" name="A"/><!-- LATIN CAPITAL 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="50" yMin="-250" xMax="450" yMax="750">
+ <contour>
+ <pt x="50" y="-250" on="1"/>
+ <pt x="50" y="750" on="1"/>
+ <pt x="450" y="750" on="1"/>
+ <pt x="450" y="-250" on="1"/>
+ </contour>
+ <contour>
+ <pt x="100" y="-200" on="1"/>
+ <pt x="400" y="-200" on="1"/>
+ <pt x="400" y="700" on="1"/>
+ <pt x="100" y="700" on="1"/>
+ </contour>
+ <instructions/>
+ </TTGlyph>
+
+ <TTGlyph name="A" xMin="-2" yMin="0" xMax="583" yMax="672">
+ <contour>
+ <pt x="410" y="672" on="1"/>
+ <pt x="570" y="81" on="1"/>
+ <pt x="576" y="58" on="0"/>
+ <pt x="583" y="19" on="0"/>
+ <pt x="583" y="0" on="1"/>
+ <pt x="384" y="0" on="1"/>
+ <pt x="315" y="355" on="1"/>
+ <pt x="297" y="480" on="1"/>
+ <pt x="292" y="480" on="1"/>
+ <pt x="195" y="0" on="1"/>
+ <pt x="-2" y="0" on="1"/>
+ <pt x="-2" y="15" on="0"/>
+ <pt x="2" y="55" on="0"/>
+ <pt x="9" y="79" on="1"/>
+ <pt x="176" y="668" on="1"/>
+ </contour>
+ <contour>
+ <pt x="422" y="257" on="1"/>
+ <pt x="422" y="107" on="1"/>
+ <pt x="137" y="107" on="1"/>
+ <pt x="137" y="257" on="1"/>
+ </contour>
+ <instructions/>
+ </TTGlyph>
+
+ </glyf>
+
+ <name>
+ <namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
+ Test Condensed Black
+ </namerecord>
+ <namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
+ Regular
+ </namerecord>
+ <namerecord nameID="3" platformID="3" platEncID="1" langID="0x409">
+ 3.013;NONE;Test-CondensedBlack
+ </namerecord>
+ <namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
+ Test Condensed Black
+ </namerecord>
+ <namerecord nameID="5" platformID="3" platEncID="1" langID="0x409">
+ Version 3.013
+ </namerecord>
+ <namerecord nameID="6" platformID="3" platEncID="1" langID="0x409">
+ Test-CondensedBlack
+ </namerecord>
+ <namerecord nameID="16" platformID="3" platEncID="1" langID="0x409">
+ Test
+ </namerecord>
+ <namerecord nameID="17" platformID="3" platEncID="1" langID="0x409">
+ Condensed Black
+ </namerecord>
+ </name>
+
+ <post>
+ <formatType value="2.0"/>
+ <italicAngle value="0.0"/>
+ <underlinePosition value="-130"/>
+ <underlineThickness value="80"/>
+ <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>
+
+</ttFont>
diff --git a/Tests/varLib/data/master_no_overwrite_stat/Test-CondensedThin.ttx b/Tests/varLib/data/master_no_overwrite_stat/Test-CondensedThin.ttx
new file mode 100644
index 00000000..e3d16464
--- /dev/null
+++ b/Tests/varLib/data/master_no_overwrite_stat/Test-CondensedThin.ttx
@@ -0,0 +1,373 @@
+<?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"/>
+ </GlyphOrder>
+
+ <head>
+ <!-- Most of this table will be recalculated by the compiler -->
+ <tableVersion value="1.0"/>
+ <fontRevision value="3.013"/>
+ <checkSumAdjustment value="0x176a479f"/>
+ <magicNumber value="0x5f0f3cf5"/>
+ <flags value="00000000 00000011"/>
+ <unitsPerEm value="1000"/>
+ <created value="Fri Feb 17 14:29:44 2023"/>
+ <modified value="Tue Mar 7 12:56:58 2023"/>
+ <xMin value="28"/>
+ <yMin value="-250"/>
+ <xMax value="450"/>
+ <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="1000"/>
+ <descent value="-300"/>
+ <lineGap value="0"/>
+ <advanceWidthMax value="500"/>
+ <minLeftSideBearing value="28"/>
+ <minRightSideBearing value="31"/>
+ <xMaxExtent value="450"/>
+ <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="2"/>
+ </hhea>
+
+ <maxp>
+ <!-- Most of this table will be recalculated by the compiler -->
+ <tableVersion value="0x10000"/>
+ <numGlyphs value="2"/>
+ <maxPoints value="19"/>
+ <maxContours value="2"/>
+ <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="482"/>
+ <usWeightClass value="100"/>
+ <usWidthClass value="3"/>
+ <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="25"/>
+ <yStrikeoutPosition value="274"/>
+ <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 00000001"/>
+ <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="65"/>
+ <usLastCharIndex value="65"/>
+ <sTypoAscender value="750"/>
+ <sTypoDescender value="-250"/>
+ <sTypoLineGap value="250"/>
+ <usWinAscent value="1000"/>
+ <usWinDescent value="300"/>
+ <ulCodePageRange1 value="00000000 00000000 00000000 00000001"/>
+ <ulCodePageRange2 value="00000000 00000000 00000000 00000000"/>
+ <sxHeight value="456"/>
+ <sCapHeight value="670"/>
+ <usDefaultChar value="0"/>
+ <usBreakChar value="32"/>
+ <usMaxContext value="0"/>
+ </OS_2>
+
+ <hmtx>
+ <mtx name=".notdef" width="500" lsb="50"/>
+ <mtx name="A" width="464" lsb="28"/>
+ </hmtx>
+
+ <cmap>
+ <tableVersion version="0"/>
+ <cmap_format_4 platformID="0" platEncID="3" language="0">
+ <map code="0x41" name="A"/><!-- LATIN CAPITAL LETTER A -->
+ </cmap_format_4>
+ <cmap_format_4 platformID="3" platEncID="1" language="0">
+ <map code="0x41" name="A"/><!-- LATIN CAPITAL 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="50" yMin="-250" xMax="450" yMax="750">
+ <contour>
+ <pt x="50" y="-250" on="1"/>
+ <pt x="50" y="750" on="1"/>
+ <pt x="450" y="750" on="1"/>
+ <pt x="450" y="-250" on="1"/>
+ </contour>
+ <contour>
+ <pt x="100" y="-200" on="1"/>
+ <pt x="400" y="-200" on="1"/>
+ <pt x="400" y="700" on="1"/>
+ <pt x="100" y="700" on="1"/>
+ </contour>
+ <instructions/>
+ </TTGlyph>
+
+ <TTGlyph name="A" xMin="28" yMin="0" xMax="433" yMax="672">
+ <contour>
+ <pt x="247" y="672" on="1"/>
+ <pt x="408" y="90" on="1"/>
+ <pt x="414" y="68" on="0"/>
+ <pt x="427" y="23" on="0"/>
+ <pt x="433" y="0" on="1"/>
+ <pt x="399" y="0" on="1"/>
+ <pt x="266" y="482" on="1"/>
+ <pt x="235" y="613" on="1"/>
+ <pt x="233" y="613" on="1"/>
+ <pt x="62" y="0" on="1"/>
+ <pt x="28" y="0" on="1"/>
+ <pt x="35" y="23" on="0"/>
+ <pt x="47" y="68" on="0"/>
+ <pt x="54" y="90" on="1"/>
+ <pt x="218" y="668" on="1"/>
+ </contour>
+ <contour>
+ <pt x="354" y="244" on="1"/>
+ <pt x="354" y="217" on="1"/>
+ <pt x="109" y="217" on="1"/>
+ <pt x="109" y="244" on="1"/>
+ </contour>
+ <instructions/>
+ </TTGlyph>
+
+ </glyf>
+
+ <name>
+ <namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
+ Test Condensed Thin
+ </namerecord>
+ <namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
+ Regular
+ </namerecord>
+ <namerecord nameID="3" platformID="3" platEncID="1" langID="0x409">
+ 3.013;NONE;Test-CondensedThin
+ </namerecord>
+ <namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
+ Test Condensed Thin
+ </namerecord>
+ <namerecord nameID="5" platformID="3" platEncID="1" langID="0x409">
+ Version 3.013
+ </namerecord>
+ <namerecord nameID="6" platformID="3" platEncID="1" langID="0x409">
+ Test-CondensedThin
+ </namerecord>
+ <namerecord nameID="16" platformID="3" platEncID="1" langID="0x409">
+ Test
+ </namerecord>
+ <namerecord nameID="17" platformID="3" platEncID="1" langID="0x409">
+ Condensed Thin
+ </namerecord>
+ <namerecord nameID="256" platformID="3" platEncID="1" langID="0x409">
+ Standard
+ </namerecord>
+ <namerecord nameID="257" platformID="3" platEncID="1" langID="0x409">
+ Heaviness
+ </namerecord>
+ <namerecord nameID="258" platformID="3" platEncID="1" langID="0x409">
+ Extralight
+ </namerecord>
+ <namerecord nameID="259" platformID="3" platEncID="1" langID="0x409">
+ Thin
+ </namerecord>
+ <namerecord nameID="260" platformID="3" platEncID="1" langID="0x409">
+ Light
+ </namerecord>
+ <namerecord nameID="261" platformID="3" platEncID="1" langID="0x409">
+ Regular
+ </namerecord>
+ <namerecord nameID="262" platformID="3" platEncID="1" langID="0x409">
+ Medium
+ </namerecord>
+ <namerecord nameID="263" platformID="3" platEncID="1" langID="0x409">
+ Semibold
+ </namerecord>
+ <namerecord nameID="264" platformID="3" platEncID="1" langID="0x409">
+ Bold
+ </namerecord>
+ <namerecord nameID="265" platformID="3" platEncID="1" langID="0x409">
+ Wideness
+ </namerecord>
+ <namerecord nameID="266" platformID="3" platEncID="1" langID="0x409">
+ Compressed
+ </namerecord>
+ <namerecord nameID="267" platformID="3" platEncID="1" langID="0x409">
+ Condensed
+ </namerecord>
+ <namerecord nameID="268" platformID="3" platEncID="1" langID="0x409">
+ Normal
+ </namerecord>
+ <namerecord nameID="269" platformID="3" platEncID="1" langID="0x409">
+ Extended
+ </namerecord>
+ </name>
+
+ <post>
+ <formatType value="2.0"/>
+ <italicAngle value="0.0"/>
+ <underlinePosition value="-130"/>
+ <underlineThickness value="25"/>
+ <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>
+
+ <STAT>
+ <Version value="0x00010001"/>
+ <DesignAxisRecordSize value="8"/>
+ <!-- DesignAxisCount=2 -->
+ <DesignAxisRecord>
+ <Axis index="0">
+ <AxisTag value="wght"/>
+ <AxisNameID value="257"/> <!-- Heaviness -->
+ <AxisOrdering value="0"/>
+ </Axis>
+ <Axis index="1">
+ <AxisTag value="wdth"/>
+ <AxisNameID value="265"/> <!-- Wideness -->
+ <AxisOrdering value="1"/>
+ </Axis>
+ </DesignAxisRecord>
+ <!-- AxisValueCount=11 -->
+ <AxisValueArray>
+ <AxisValue index="0" Format="1">
+ <AxisIndex value="0"/>
+ <Flags value="0"/>
+ <ValueNameID value="258"/> <!-- Extralight -->
+ <Value value="100.0"/>
+ </AxisValue>
+ <AxisValue index="1" Format="1">
+ <AxisIndex value="0"/>
+ <Flags value="0"/>
+ <ValueNameID value="259"/> <!-- Thin -->
+ <Value value="200.0"/>
+ </AxisValue>
+ <AxisValue index="2" Format="1">
+ <AxisIndex value="0"/>
+ <Flags value="0"/>
+ <ValueNameID value="260"/> <!-- Light -->
+ <Value value="300.0"/>
+ </AxisValue>
+ <AxisValue index="3" Format="1">
+ <AxisIndex value="0"/>
+ <Flags value="2"/> <!-- ElidableAxisValueName -->
+ <ValueNameID value="261"/> <!-- Regular -->
+ <Value value="400.0"/>
+ </AxisValue>
+ <AxisValue index="4" Format="1">
+ <AxisIndex value="0"/>
+ <Flags value="0"/>
+ <ValueNameID value="262"/> <!-- Medium -->
+ <Value value="500.0"/>
+ </AxisValue>
+ <AxisValue index="5" Format="1">
+ <AxisIndex value="0"/>
+ <Flags value="0"/>
+ <ValueNameID value="263"/> <!-- Semibold -->
+ <Value value="600.0"/>
+ </AxisValue>
+ <AxisValue index="6" Format="1">
+ <AxisIndex value="0"/>
+ <Flags value="0"/>
+ <ValueNameID value="264"/> <!-- Bold -->
+ <Value value="700.0"/>
+ </AxisValue>
+ <AxisValue index="7" Format="1">
+ <AxisIndex value="1"/>
+ <Flags value="0"/>
+ <ValueNameID value="266"/> <!-- Compressed -->
+ <Value value="80.0"/>
+ </AxisValue>
+ <AxisValue index="8" Format="1">
+ <AxisIndex value="1"/>
+ <Flags value="0"/>
+ <ValueNameID value="267"/> <!-- Condensed -->
+ <Value value="90.0"/>
+ </AxisValue>
+ <AxisValue index="9" Format="1">
+ <AxisIndex value="1"/>
+ <Flags value="0"/>
+ <ValueNameID value="268"/> <!-- Normal -->
+ <Value value="100.0"/>
+ </AxisValue>
+ <AxisValue index="10" Format="1">
+ <AxisIndex value="1"/>
+ <Flags value="0"/>
+ <ValueNameID value="269"/> <!-- Extended -->
+ <Value value="115.0"/>
+ </AxisValue>
+ </AxisValueArray>
+ <ElidedFallbackNameID value="256"/> <!-- Standard -->
+ </STAT>
+
+</ttFont>
diff --git a/Tests/varLib/data/master_no_overwrite_stat/Test-ExtendedBlack.ttx b/Tests/varLib/data/master_no_overwrite_stat/Test-ExtendedBlack.ttx
new file mode 100644
index 00000000..8dc69399
--- /dev/null
+++ b/Tests/varLib/data/master_no_overwrite_stat/Test-ExtendedBlack.ttx
@@ -0,0 +1,243 @@
+<?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"/>
+ </GlyphOrder>
+
+ <head>
+ <!-- Most of this table will be recalculated by the compiler -->
+ <tableVersion value="1.0"/>
+ <fontRevision value="3.013"/>
+ <checkSumAdjustment value="0xc2b89a77"/>
+ <magicNumber value="0x5f0f3cf5"/>
+ <flags value="00000000 00000011"/>
+ <unitsPerEm value="1000"/>
+ <created value="Fri Feb 17 14:29:44 2023"/>
+ <modified value="Tue Mar 7 12:56:58 2023"/>
+ <xMin value="-6"/>
+ <yMin value="-250"/>
+ <xMax value="759"/>
+ <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="1000"/>
+ <descent value="-300"/>
+ <lineGap value="0"/>
+ <advanceWidthMax value="762"/>
+ <minLeftSideBearing value="-6"/>
+ <minRightSideBearing value="3"/>
+ <xMaxExtent value="759"/>
+ <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="2"/>
+ </hhea>
+
+ <maxp>
+ <!-- Most of this table will be recalculated by the compiler -->
+ <tableVersion value="0x10000"/>
+ <numGlyphs value="2"/>
+ <maxPoints value="19"/>
+ <maxContours value="2"/>
+ <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="631"/>
+ <usWeightClass value="900"/>
+ <usWidthClass value="6"/>
+ <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="100"/>
+ <yStrikeoutPosition value="303"/>
+ <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 00000001"/>
+ <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="65"/>
+ <usLastCharIndex value="65"/>
+ <sTypoAscender value="750"/>
+ <sTypoDescender value="-250"/>
+ <sTypoLineGap value="250"/>
+ <usWinAscent value="1000"/>
+ <usWinDescent value="300"/>
+ <ulCodePageRange1 value="00000000 00000000 00000000 00000001"/>
+ <ulCodePageRange2 value="00000000 00000000 00000000 00000000"/>
+ <sxHeight value="505"/>
+ <sCapHeight value="670"/>
+ <usDefaultChar value="0"/>
+ <usBreakChar value="32"/>
+ <usMaxContext value="0"/>
+ </OS_2>
+
+ <hmtx>
+ <mtx name=".notdef" width="500" lsb="50"/>
+ <mtx name="A" width="762" lsb="-6"/>
+ </hmtx>
+
+ <cmap>
+ <tableVersion version="0"/>
+ <cmap_format_4 platformID="0" platEncID="3" language="0">
+ <map code="0x41" name="A"/><!-- LATIN CAPITAL LETTER A -->
+ </cmap_format_4>
+ <cmap_format_4 platformID="3" platEncID="1" language="0">
+ <map code="0x41" name="A"/><!-- LATIN CAPITAL 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="50" yMin="-250" xMax="450" yMax="750">
+ <contour>
+ <pt x="50" y="-250" on="1"/>
+ <pt x="50" y="750" on="1"/>
+ <pt x="450" y="750" on="1"/>
+ <pt x="450" y="-250" on="1"/>
+ </contour>
+ <contour>
+ <pt x="100" y="-200" on="1"/>
+ <pt x="400" y="-200" on="1"/>
+ <pt x="400" y="700" on="1"/>
+ <pt x="100" y="700" on="1"/>
+ </contour>
+ <instructions/>
+ </TTGlyph>
+
+ <TTGlyph name="A" xMin="-6" yMin="0" xMax="759" yMax="672">
+ <contour>
+ <pt x="542" y="672" on="1"/>
+ <pt x="735" y="121" on="1"/>
+ <pt x="747" y="86" on="0"/>
+ <pt x="759" y="24" on="0"/>
+ <pt x="759" y="0" on="1"/>
+ <pt x="501" y="0" on="1"/>
+ <pt x="421" y="258" on="1"/>
+ <pt x="384" y="458" on="1"/>
+ <pt x="377" y="458" on="1"/>
+ <pt x="244" y="0" on="1"/>
+ <pt x="-6" y="0" on="1"/>
+ <pt x="-6" y="21" on="0"/>
+ <pt x="4" y="87" on="0"/>
+ <pt x="17" y="121" on="1"/>
+ <pt x="233" y="668" on="1"/>
+ </contour>
+ <contour>
+ <pt x="545" y="259" on="1"/>
+ <pt x="545" y="92" on="1"/>
+ <pt x="176" y="92" on="1"/>
+ <pt x="176" y="259" on="1"/>
+ </contour>
+ <instructions/>
+ </TTGlyph>
+
+ </glyf>
+
+ <name>
+ <namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
+ Test Extended Black
+ </namerecord>
+ <namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
+ Regular
+ </namerecord>
+ <namerecord nameID="3" platformID="3" platEncID="1" langID="0x409">
+ 3.013;NONE;Test-ExtendedBlack
+ </namerecord>
+ <namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
+ Test Extended Black
+ </namerecord>
+ <namerecord nameID="5" platformID="3" platEncID="1" langID="0x409">
+ Version 3.013
+ </namerecord>
+ <namerecord nameID="6" platformID="3" platEncID="1" langID="0x409">
+ Test-ExtendedBlack
+ </namerecord>
+ <namerecord nameID="16" platformID="3" platEncID="1" langID="0x409">
+ Test
+ </namerecord>
+ <namerecord nameID="17" platformID="3" platEncID="1" langID="0x409">
+ Extended Black
+ </namerecord>
+ </name>
+
+ <post>
+ <formatType value="2.0"/>
+ <italicAngle value="0.0"/>
+ <underlinePosition value="-130"/>
+ <underlineThickness value="100"/>
+ <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>
+
+</ttFont>
diff --git a/Tests/varLib/data/master_no_overwrite_stat/Test-ExtendedThin.ttx b/Tests/varLib/data/master_no_overwrite_stat/Test-ExtendedThin.ttx
new file mode 100644
index 00000000..d9209edd
--- /dev/null
+++ b/Tests/varLib/data/master_no_overwrite_stat/Test-ExtendedThin.ttx
@@ -0,0 +1,243 @@
+<?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"/>
+ </GlyphOrder>
+
+ <head>
+ <!-- Most of this table will be recalculated by the compiler -->
+ <tableVersion value="1.0"/>
+ <fontRevision value="3.013"/>
+ <checkSumAdjustment value="0x4af8381f"/>
+ <magicNumber value="0x5f0f3cf5"/>
+ <flags value="00000000 00000011"/>
+ <unitsPerEm value="1000"/>
+ <created value="Fri Feb 17 14:29:44 2023"/>
+ <modified value="Tue Mar 7 12:56:58 2023"/>
+ <xMin value="23"/>
+ <yMin value="-250"/>
+ <xMax value="605"/>
+ <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="1000"/>
+ <descent value="-300"/>
+ <lineGap value="0"/>
+ <advanceWidthMax value="633"/>
+ <minLeftSideBearing value="23"/>
+ <minRightSideBearing value="28"/>
+ <xMaxExtent value="605"/>
+ <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="2"/>
+ </hhea>
+
+ <maxp>
+ <!-- Most of this table will be recalculated by the compiler -->
+ <tableVersion value="0x10000"/>
+ <numGlyphs value="2"/>
+ <maxPoints value="19"/>
+ <maxContours value="2"/>
+ <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="567"/>
+ <usWeightClass value="100"/>
+ <usWidthClass value="6"/>
+ <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="28"/>
+ <yStrikeoutPosition value="274"/>
+ <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 00000001"/>
+ <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="65"/>
+ <usLastCharIndex value="65"/>
+ <sTypoAscender value="750"/>
+ <sTypoDescender value="-250"/>
+ <sTypoLineGap value="250"/>
+ <usWinAscent value="1000"/>
+ <usWinDescent value="300"/>
+ <ulCodePageRange1 value="00000000 00000000 00000000 00000001"/>
+ <ulCodePageRange2 value="00000000 00000000 00000000 00000000"/>
+ <sxHeight value="456"/>
+ <sCapHeight value="670"/>
+ <usDefaultChar value="0"/>
+ <usBreakChar value="32"/>
+ <usMaxContext value="0"/>
+ </OS_2>
+
+ <hmtx>
+ <mtx name=".notdef" width="500" lsb="50"/>
+ <mtx name="A" width="633" lsb="23"/>
+ </hmtx>
+
+ <cmap>
+ <tableVersion version="0"/>
+ <cmap_format_4 platformID="0" platEncID="3" language="0">
+ <map code="0x41" name="A"/><!-- LATIN CAPITAL LETTER A -->
+ </cmap_format_4>
+ <cmap_format_4 platformID="3" platEncID="1" language="0">
+ <map code="0x41" name="A"/><!-- LATIN CAPITAL 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="50" yMin="-250" xMax="450" yMax="750">
+ <contour>
+ <pt x="50" y="-250" on="1"/>
+ <pt x="50" y="750" on="1"/>
+ <pt x="450" y="750" on="1"/>
+ <pt x="450" y="-250" on="1"/>
+ </contour>
+ <contour>
+ <pt x="100" y="-200" on="1"/>
+ <pt x="400" y="-200" on="1"/>
+ <pt x="400" y="700" on="1"/>
+ <pt x="100" y="700" on="1"/>
+ </contour>
+ <instructions/>
+ </TTGlyph>
+
+ <TTGlyph name="A" xMin="23" yMin="0" xMax="605" yMax="672">
+ <contour>
+ <pt x="339" y="672" on="1"/>
+ <pt x="566" y="100" on="1"/>
+ <pt x="576" y="75" on="0"/>
+ <pt x="595" y="25" on="0"/>
+ <pt x="605" y="0" on="1"/>
+ <pt x="563" y="0" on="1"/>
+ <pt x="384" y="453" on="1"/>
+ <pt x="320" y="626" on="1"/>
+ <pt x="317" y="626" on="1"/>
+ <pt x="62" y="0" on="1"/>
+ <pt x="23" y="0" on="1"/>
+ <pt x="34" y="25" on="0"/>
+ <pt x="54" y="75" on="0"/>
+ <pt x="64" y="100" on="1"/>
+ <pt x="297" y="668" on="1"/>
+ </contour>
+ <contour>
+ <pt x="491" y="250" on="1"/>
+ <pt x="491" y="217" on="1"/>
+ <pt x="139" y="217" on="1"/>
+ <pt x="139" y="250" on="1"/>
+ </contour>
+ <instructions/>
+ </TTGlyph>
+
+ </glyf>
+
+ <name>
+ <namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
+ Test Extended Thin
+ </namerecord>
+ <namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
+ Regular
+ </namerecord>
+ <namerecord nameID="3" platformID="3" platEncID="1" langID="0x409">
+ 3.013;NONE;Test-ExtendedThin
+ </namerecord>
+ <namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
+ Test Extended Thin
+ </namerecord>
+ <namerecord nameID="5" platformID="3" platEncID="1" langID="0x409">
+ Version 3.013
+ </namerecord>
+ <namerecord nameID="6" platformID="3" platEncID="1" langID="0x409">
+ Test-ExtendedThin
+ </namerecord>
+ <namerecord nameID="16" platformID="3" platEncID="1" langID="0x409">
+ Test
+ </namerecord>
+ <namerecord nameID="17" platformID="3" platEncID="1" langID="0x409">
+ Extended Thin
+ </namerecord>
+ </name>
+
+ <post>
+ <formatType value="2.0"/>
+ <italicAngle value="0.0"/>
+ <underlinePosition value="-130"/>
+ <underlineThickness value="28"/>
+ <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>
+
+</ttFont>
diff --git a/Tests/varLib/data/master_sparse_cff2_empty/SparseCFF-Bold.ttx b/Tests/varLib/data/master_sparse_cff2_empty/SparseCFF-Bold.ttx
new file mode 100644
index 00000000..410489dc
--- /dev/null
+++ b/Tests/varLib/data/master_sparse_cff2_empty/SparseCFF-Bold.ttx
@@ -0,0 +1,302 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ttFont sfntVersion="OTTO" ttLibVersion="4.41">
+
+ <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"/>
+ </GlyphOrder>
+
+ <head>
+ <!-- Most of this table will be recalculated by the compiler -->
+ <tableVersion value="1.0"/>
+ <fontRevision value="0.0"/>
+ <checkSumAdjustment value="0xaa7fc0dd"/>
+ <magicNumber value="0x5f0f3cf5"/>
+ <flags value="00000000 00000011"/>
+ <unitsPerEm value="1000"/>
+ <created value="Wed Nov 21 11:49:03 2018"/>
+ <modified value="Wed Aug 2 11:47:17 2023"/>
+ <xMin value="-64"/>
+ <yMin value="-350"/>
+ <xMax value="608"/>
+ <yMax value="812"/>
+ <macStyle value="00000000 00000001"/>
+ <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="-64"/>
+ <minRightSideBearing value="-63"/>
+ <xMaxExtent value="608"/>
+ <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="2"/>
+ </hhea>
+
+ <maxp>
+ <tableVersion value="0x5000"/>
+ <numGlyphs value="3"/>
+ </maxp>
+
+ <OS_2>
+ <!-- The fields 'usFirstCharIndex' and 'usLastCharIndex'
+ will be recalculated by the compiler -->
+ <version value="4"/>
+ <xAvgCharWidth value="580"/>
+ <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="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 00000001"/>
+ <ulUnicodeRange2 value="00000000 00000000 00000000 00000000"/>
+ <ulUnicodeRange3 value="00000000 00000000 00000000 00000000"/>
+ <ulUnicodeRange4 value="00000000 00000000 00000000 00000000"/>
+ <achVendID value="NONE"/>
+ <fsSelection value="00000000 00100000"/>
+ <usFirstCharIndex value="97"/>
+ <usLastCharIndex value="101"/>
+ <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="4"/>
+ </OS_2>
+
+ <name>
+ <namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
+ Sparse CFF
+ </namerecord>
+ <namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
+ Bold
+ </namerecord>
+ <namerecord nameID="3" platformID="3" platEncID="1" langID="0x409">
+ 0.000;NONE;SparseCFF-Bold
+ </namerecord>
+ <namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
+ Sparse CFF Bold
+ </namerecord>
+ <namerecord nameID="5" platformID="3" platEncID="1" langID="0x409">
+ Version 0.000
+ </namerecord>
+ <namerecord nameID="6" platformID="3" platEncID="1" langID="0x409">
+ SparseCFF-Bold
+ </namerecord>
+ </name>
+
+ <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 -->
+ </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 -->
+ </cmap_format_4>
+ </cmap>
+
+ <post>
+ <formatType value="3.0"/>
+ <italicAngle value="0.0"/>
+ <underlinePosition value="-100"/>
+ <underlineThickness value="50"/>
+ <isFixedPitch value="0"/>
+ <minMemType42 value="0"/>
+ <maxMemType42 value="0"/>
+ <minMemType1 value="0"/>
+ <maxMemType1 value="0"/>
+ </post>
+
+ <CFF>
+ <major value="1"/>
+ <minor value="0"/>
+ <CFFFont name="SparseCFF-Bold">
+ <version value="0.0"/>
+ <Notice value=""/>
+ <Copyright value=""/>
+ <FullName value="Sparse CFF Bold"/>
+ <FamilyName value="Sparse CFF"/>
+ <isFixedPitch value="0"/>
+ <ItalicAngle value="0"/>
+ <UnderlinePosition value="-100"/>
+ <UnderlineThickness value="50"/>
+ <PaintType value="0"/>
+ <CharstringType value="2"/>
+ <FontMatrix value="0.001 0 0 0.001 0 0"/>
+ <FontBBox value="-64 -350 608 812"/>
+ <StrokeWidth value="0"/>
+ <!-- charset is dumped separately as the 'GlyphOrder' element -->
+ <Encoding name="StandardEncoding"/>
+ <Private>
+ <BlueScale value="0.039625"/>
+ <BlueShift value="7"/>
+ <BlueFuzz value="1"/>
+ <ForceBold value="0"/>
+ <LanguageGroup value="0"/>
+ <ExpansionFactor value="0.06"/>
+ <initialRandomSeed value="0"/>
+ <defaultWidthX value="600"/>
+ <nominalWidthX value="0"/>
+ </Private>
+ <CharStrings>
+ <CharString name=".notdef">
+ 500 50 -350 rmoveto
+ 500 0 rlineto
+ 0 1100 rlineto
+ -500 0 rlineto
+ 50 -950 rmoveto
+ 0 900 rlineto
+ 300 0 rlineto
+ 0 -900 rlineto
+ endchar
+ </CharString>
+ <CharString name="a">
+ 468 -1 rmoveto
+ -21 435 rlineto
+ -233 70 rlineto
+ -205 -76 rlineto
+ 27 -147 rlineto
+ 172 60 rlineto
+ 96 -38 rlineto
+ 3 -304 rlineto
+ 71 264 rmoveto
+ -352 -23 rlineto
+ 3 -218 rlineto
+ 139 -34 rlineto
+ 221 83 rlineto
+ -6 78 rlineto
+ -182 -47 rlineto
+ -38 31 rlineto
+ 2 46 rlineto
+ 216 5 rlineto
+ endchar
+ </CharString>
+ <CharString name="e">
+ 197 229 rmoveto
+ 404 -4 rlineto
+ -5 79 rlineto
+ -282 244 rlineto
+ -305 -286 rlineto
+ 179 -280 rlineto
+ 340 18 rlineto
+ -4 184 rlineto
+ -280 -54 rlineto
+ -27 134 rlineto
+ 84 96 rlineto
+ 103 -67 rlineto
+ -209 6 rlineto
+ endchar
+ </CharString>
+ </CharStrings>
+ </CFFFont>
+
+ <GlobalSubrs>
+ <!-- The 'index' attribute is only for humans; it is ignored when parsed. -->
+ </GlobalSubrs>
+ </CFF>
+
+ <GDEF>
+ <Version value="0x00010000"/>
+ <GlyphClassDef>
+ <ClassDef glyph="e" class="1"/>
+ </GlyphClassDef>
+ </GDEF>
+
+ <GPOS>
+ <Version value="0x00010000"/>
+ <ScriptList>
+ <!-- ScriptCount=1 -->
+ <ScriptRecord index="0">
+ <ScriptTag value="DFLT"/>
+ <Script>
+ <DefaultLangSys>
+ <ReqFeatureIndex value="65535"/>
+ <!-- FeatureCount=0 -->
+ </DefaultLangSys>
+ <!-- LangSysCount=0 -->
+ </Script>
+ </ScriptRecord>
+ </ScriptList>
+ <FeatureList>
+ <!-- FeatureCount=0 -->
+ </FeatureList>
+ <LookupList>
+ <!-- LookupCount=0 -->
+ </LookupList>
+ </GPOS>
+
+ <GSUB>
+ <Version value="0x00010000"/>
+ <ScriptList>
+ <!-- ScriptCount=1 -->
+ <ScriptRecord index="0">
+ <ScriptTag value="DFLT"/>
+ <Script>
+ <DefaultLangSys>
+ <ReqFeatureIndex value="65535"/>
+ <!-- FeatureCount=0 -->
+ </DefaultLangSys>
+ <!-- LangSysCount=0 -->
+ </Script>
+ </ScriptRecord>
+ </ScriptList>
+ <FeatureList>
+ <!-- FeatureCount=0 -->
+ </FeatureList>
+ <LookupList>
+ <!-- LookupCount=0 -->
+ </LookupList>
+ </GSUB>
+
+ <hmtx>
+ <mtx name=".notdef" width="800" lsb="200"/>
+ <mtx name="a" width="600" lsb="9"/>
+ <mtx name="e" width="600" lsb="9"/>
+ </hmtx>
+
+</ttFont>
diff --git a/Tests/varLib/data/master_sparse_cff2_empty/SparseCFF-Medium.ttx b/Tests/varLib/data/master_sparse_cff2_empty/SparseCFF-Medium.ttx
new file mode 100644
index 00000000..1b583bd3
--- /dev/null
+++ b/Tests/varLib/data/master_sparse_cff2_empty/SparseCFF-Medium.ttx
@@ -0,0 +1,100 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ttFont sfntVersion="OTTO" ttLibVersion="4.41">
+
+ <GlyphOrder>
+ <!-- The 'id' attribute is only for humans; it is ignored when parsed. -->
+ <GlyphID id="0" name=".notdef"/>
+ <GlyphID id="1" name="e"/>
+ </GlyphOrder>
+
+ <head>
+ <!-- Most of this table will be recalculated by the compiler -->
+ <tableVersion value="1.0"/>
+ <fontRevision value="0.0"/>
+ <checkSumAdjustment value="0x263f439"/>
+ <magicNumber value="0x5f0f3cf5"/>
+ <flags value="00000000 00000011"/>
+ <unitsPerEm value="1000"/>
+ <created value="Wed Nov 21 11:49:03 2018"/>
+ <modified value="Wed Aug 2 11:47:17 2023"/>
+ <xMin value="40"/>
+ <yMin value="-18"/>
+ <xMax value="576"/>
+ <yMax value="513"/>
+ <macStyle value="00000000 00000000"/>
+ <lowestRecPPEM value="6"/>
+ <fontDirectionHint value="2"/>
+ <indexToLocFormat value="0"/>
+ <glyphDataFormat value="0"/>
+ </head>
+
+ <maxp>
+ <tableVersion value="0x5000"/>
+ <numGlyphs value="2"/>
+ </maxp>
+
+ <CFF>
+ <major value="1"/>
+ <minor value="0"/>
+ <CFFFont name="LayerFont-Regular">
+ <version value="0.0"/>
+ <Notice value=""/>
+ <Copyright value=""/>
+ <FullName value="Layer Font Regular"/>
+ <FamilyName value="Layer Font"/>
+ <isFixedPitch value="0"/>
+ <ItalicAngle value="0"/>
+ <UnderlinePosition value="-75"/>
+ <UnderlineThickness value="50"/>
+ <PaintType value="0"/>
+ <CharstringType value="2"/>
+ <FontMatrix value="0.001 0 0 0.001 0 0"/>
+ <FontBBox value="40 -18 576 513"/>
+ <StrokeWidth value="0"/>
+ <!-- charset is dumped separately as the 'GlyphOrder' element -->
+ <Encoding name="StandardEncoding"/>
+ <Private>
+ <BlueScale value="0.039625"/>
+ <BlueShift value="7"/>
+ <BlueFuzz value="1"/>
+ <ForceBold value="0"/>
+ <LanguageGroup value="0"/>
+ <ExpansionFactor value="0.06"/>
+ <initialRandomSeed value="0"/>
+ <defaultWidthX value="500"/>
+ <nominalWidthX value="500"/>
+ </Private>
+ <CharStrings>
+ <CharString name=".notdef">
+ endchar
+ </CharString>
+ <CharString name="e">
+ 100 126 203 rmoveto
+ 450 -4 rlineto
+ -5 106 rlineto
+ -255 208 rlineto
+ -276 -252 rlineto
+ 148 -279 rlineto
+ 338 63 rlineto
+ -19 112 rlineto
+ -243 -41 rlineto
+ -84 148 rlineto
+ 138 123 rlineto
+ 78 -90 rlineto
+ -271 1 rlineto
+ endchar
+ </CharString>
+ </CharStrings>
+ </CFFFont>
+
+ <GlobalSubrs>
+ <!-- The 'index' attribute is only for humans; it is ignored when parsed. -->
+ </GlobalSubrs>
+ </CFF>
+
+ <hmtx>
+ <mtx name=".notdef" width="65535" lsb="0"/>
+ <mtx name="e" width="600" lsb="40"/>
+ </hmtx>
+
+</ttFont>
diff --git a/Tests/varLib/data/master_sparse_cff2_empty/SparseCFF-Regular.ttx b/Tests/varLib/data/master_sparse_cff2_empty/SparseCFF-Regular.ttx
new file mode 100644
index 00000000..a4dda26f
--- /dev/null
+++ b/Tests/varLib/data/master_sparse_cff2_empty/SparseCFF-Regular.ttx
@@ -0,0 +1,302 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ttFont sfntVersion="OTTO" ttLibVersion="4.41">
+
+ <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"/>
+ </GlyphOrder>
+
+ <head>
+ <!-- Most of this table will be recalculated by the compiler -->
+ <tableVersion value="1.0"/>
+ <fontRevision value="0.0"/>
+ <checkSumAdjustment value="0xbfef2bdd"/>
+ <magicNumber value="0x5f0f3cf5"/>
+ <flags value="00000000 00000011"/>
+ <unitsPerEm value="1000"/>
+ <created value="Wed Nov 21 11:49:03 2018"/>
+ <modified value="Wed Aug 2 11:47:17 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="2"/>
+ </hhea>
+
+ <maxp>
+ <tableVersion value="0x5000"/>
+ <numGlyphs value="3"/>
+ </maxp>
+
+ <OS_2>
+ <!-- The fields 'usFirstCharIndex' and 'usLastCharIndex'
+ will be recalculated by the compiler -->
+ <version value="4"/>
+ <xAvgCharWidth value="580"/>
+ <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="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 00000001"/>
+ <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="101"/>
+ <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="4"/>
+ </OS_2>
+
+ <name>
+ <namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
+ Sparse CFF
+ </namerecord>
+ <namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
+ Regular
+ </namerecord>
+ <namerecord nameID="3" platformID="3" platEncID="1" langID="0x409">
+ 0.000;NONE;SparseCFF-Regular
+ </namerecord>
+ <namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
+ Sparse CFF Regular
+ </namerecord>
+ <namerecord nameID="5" platformID="3" platEncID="1" langID="0x409">
+ Version 0.000
+ </namerecord>
+ <namerecord nameID="6" platformID="3" platEncID="1" langID="0x409">
+ SparseCFF-Regular
+ </namerecord>
+ </name>
+
+ <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 -->
+ </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 -->
+ </cmap_format_4>
+ </cmap>
+
+ <post>
+ <formatType value="3.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"/>
+ </post>
+
+ <CFF>
+ <major value="1"/>
+ <minor value="0"/>
+ <CFFFont name="SparseCFF-Regular">
+ <version value="0.0"/>
+ <Notice value=""/>
+ <Copyright value=""/>
+ <FullName value="Sparse CFF Regular"/>
+ <FamilyName value="Sparse CFF"/>
+ <isFixedPitch value="0"/>
+ <ItalicAngle value="0"/>
+ <UnderlinePosition value="-75"/>
+ <UnderlineThickness value="50"/>
+ <PaintType value="0"/>
+ <CharstringType value="2"/>
+ <FontMatrix value="0.001 0 0 0.001 0 0"/>
+ <FontBBox value="-37 -250 582 750"/>
+ <StrokeWidth value="0"/>
+ <!-- charset is dumped separately as the 'GlyphOrder' element -->
+ <Encoding name="StandardEncoding"/>
+ <Private>
+ <BlueScale value="0.039625"/>
+ <BlueShift value="7"/>
+ <BlueFuzz value="1"/>
+ <ForceBold value="0"/>
+ <LanguageGroup value="0"/>
+ <ExpansionFactor value="0.06"/>
+ <initialRandomSeed value="0"/>
+ <defaultWidthX value="600"/>
+ <nominalWidthX value="0"/>
+ </Private>
+ <CharStrings>
+ <CharString name=".notdef">
+ 500 50 -250 rmoveto
+ 400 0 rlineto
+ 0 1000 rlineto
+ -400 0 rlineto
+ 50 -950 rmoveto
+ 0 900 rlineto
+ 300 0 rlineto
+ 0 -900 rlineto
+ endchar
+ </CharString>
+ <CharString name="a">
+ 468 -1 rmoveto
+ -21 435 rlineto
+ -233 70 rlineto
+ -205 -76 rlineto
+ 27 -91 rlineto
+ 172 60 rlineto
+ 155 -40 rlineto
+ 3 -360 rlineto
+ 12 266 rmoveto
+ -352 -23 rlineto
+ 3 -218 rlineto
+ 139 -34 rlineto
+ 221 83 rlineto
+ -6 63 rlineto
+ -222 -60 rlineto
+ -75 52 rlineto
+ 2 46 rlineto
+ 294 35 rlineto
+ endchar
+ </CharString>
+ <CharString name="e">
+ 127 228 rmoveto
+ 449 -2 rlineto
+ -5 79 rlineto
+ -255 208 rlineto
+ -276 -252 rlineto
+ 148 -279 rlineto
+ 338 63 rlineto
+ -17 84 rlineto
+ -280 -54 rlineto
+ -82 188 rlineto
+ 170 153 rlineto
+ 163 -124 rlineto
+ -355 6 rlineto
+ endchar
+ </CharString>
+ </CharStrings>
+ </CFFFont>
+
+ <GlobalSubrs>
+ <!-- The 'index' attribute is only for humans; it is ignored when parsed. -->
+ </GlobalSubrs>
+ </CFF>
+
+ <GDEF>
+ <Version value="0x00010000"/>
+ <GlyphClassDef>
+ <ClassDef glyph="e" class="1"/>
+ </GlyphClassDef>
+ </GDEF>
+
+ <GPOS>
+ <Version value="0x00010000"/>
+ <ScriptList>
+ <!-- ScriptCount=1 -->
+ <ScriptRecord index="0">
+ <ScriptTag value="DFLT"/>
+ <Script>
+ <DefaultLangSys>
+ <ReqFeatureIndex value="65535"/>
+ <!-- FeatureCount=0 -->
+ </DefaultLangSys>
+ <!-- LangSysCount=0 -->
+ </Script>
+ </ScriptRecord>
+ </ScriptList>
+ <FeatureList>
+ <!-- FeatureCount=0 -->
+ </FeatureList>
+ <LookupList>
+ <!-- LookupCount=0 -->
+ </LookupList>
+ </GPOS>
+
+ <GSUB>
+ <Version value="0x00010000"/>
+ <ScriptList>
+ <!-- ScriptCount=1 -->
+ <ScriptRecord index="0">
+ <ScriptTag value="DFLT"/>
+ <Script>
+ <DefaultLangSys>
+ <ReqFeatureIndex value="65535"/>
+ <!-- FeatureCount=0 -->
+ </DefaultLangSys>
+ <!-- LangSysCount=0 -->
+ </Script>
+ </ScriptRecord>
+ </ScriptList>
+ <FeatureList>
+ <!-- FeatureCount=0 -->
+ </FeatureList>
+ <LookupList>
+ <!-- LookupCount=0 -->
+ </LookupList>
+ </GSUB>
+
+ <hmtx>
+ <mtx name=".notdef" width="500" lsb="50"/>
+ <mtx name="a" width="600" lsb="9"/>
+ <mtx name="e" width="600" lsb="40"/>
+ </hmtx>
+
+</ttFont>
diff --git a/Tests/varLib/data/master_ttx_drop_oncurves/TestFamily-Master1.ttx b/Tests/varLib/data/master_ttx_drop_oncurves/TestFamily-Master1.ttx
new file mode 100644
index 00000000..14e64a75
--- /dev/null
+++ b/Tests/varLib/data/master_ttx_drop_oncurves/TestFamily-Master1.ttx
@@ -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>
diff --git a/Tests/varLib/data/master_ttx_drop_oncurves/TestFamily-Master2.ttx b/Tests/varLib/data/master_ttx_drop_oncurves/TestFamily-Master2.ttx
new file mode 100644
index 00000000..1559071a
--- /dev/null
+++ b/Tests/varLib/data/master_ttx_drop_oncurves/TestFamily-Master2.ttx
@@ -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>
diff --git a/Tests/varLib/data/master_ttx_varfont_otf/TestCFF2VF.ttx b/Tests/varLib/data/master_ttx_varfont_otf/TestCFF2VF.ttx
index 29c5bb31..5de73115 100644
--- a/Tests/varLib/data/master_ttx_varfont_otf/TestCFF2VF.ttx
+++ b/Tests/varLib/data/master_ttx_varfont_otf/TestCFF2VF.ttx
@@ -761,6 +761,7 @@
</STAT>
<avar>
+ <version major="1" minor="0"/>
<segment axis="wght">
<mapping from="-1.0" to="-1.0"/>
<mapping from="-0.5" to="-0.7283"/>
diff --git a/Tests/varLib/data/master_ttx_varfont_ttf/SparseMasters-VF.ttx b/Tests/varLib/data/master_ttx_varfont_ttf/SparseMasters-VF.ttx
new file mode 100644
index 00000000..819b3441
--- /dev/null
+++ b/Tests/varLib/data/master_ttx_varfont_ttf/SparseMasters-VF.ttx
@@ -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>
diff --git a/Tests/varLib/data/master_ufo/SparseMasters-Bold.ufo/fontinfo.plist b/Tests/varLib/data/master_ufo/SparseMasters-Bold.ufo/fontinfo.plist
new file mode 100644
index 00000000..3898ecc8
--- /dev/null
+++ b/Tests/varLib/data/master_ufo/SparseMasters-Bold.ufo/fontinfo.plist
@@ -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>
diff --git a/Tests/varLib/data/master_ufo/SparseMasters-Bold.ufo/glyphs/_notdef.glif b/Tests/varLib/data/master_ufo/SparseMasters-Bold.ufo/glyphs/_notdef.glif
new file mode 100644
index 00000000..5d3ca4d6
--- /dev/null
+++ b/Tests/varLib/data/master_ufo/SparseMasters-Bold.ufo/glyphs/_notdef.glif
@@ -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>
diff --git a/Tests/varLib/data/master_ufo/SparseMasters-Bold.ufo/glyphs/a.glif b/Tests/varLib/data/master_ufo/SparseMasters-Bold.ufo/glyphs/a.glif
new file mode 100644
index 00000000..0e038d68
--- /dev/null
+++ b/Tests/varLib/data/master_ufo/SparseMasters-Bold.ufo/glyphs/a.glif
@@ -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>
diff --git a/Tests/varLib/data/master_ufo/SparseMasters-Bold.ufo/glyphs/contents.plist b/Tests/varLib/data/master_ufo/SparseMasters-Bold.ufo/glyphs/contents.plist
new file mode 100644
index 00000000..da7e7a78
--- /dev/null
+++ b/Tests/varLib/data/master_ufo/SparseMasters-Bold.ufo/glyphs/contents.plist
@@ -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>
diff --git a/Tests/varLib/data/master_ufo/SparseMasters-Bold.ufo/glyphs/dotabovecomb.glif b/Tests/varLib/data/master_ufo/SparseMasters-Bold.ufo/glyphs/dotabovecomb.glif
new file mode 100644
index 00000000..1c11088c
--- /dev/null
+++ b/Tests/varLib/data/master_ufo/SparseMasters-Bold.ufo/glyphs/dotabovecomb.glif
@@ -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>
diff --git a/Tests/varLib/data/master_ufo/SparseMasters-Bold.ufo/glyphs/e.glif b/Tests/varLib/data/master_ufo/SparseMasters-Bold.ufo/glyphs/e.glif
new file mode 100644
index 00000000..c78c38f4
--- /dev/null
+++ b/Tests/varLib/data/master_ufo/SparseMasters-Bold.ufo/glyphs/e.glif
@@ -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>
diff --git a/Tests/varLib/data/master_ufo/SparseMasters-Bold.ufo/glyphs/edotabove.glif b/Tests/varLib/data/master_ufo/SparseMasters-Bold.ufo/glyphs/edotabove.glif
new file mode 100644
index 00000000..bf481928
--- /dev/null
+++ b/Tests/varLib/data/master_ufo/SparseMasters-Bold.ufo/glyphs/edotabove.glif
@@ -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>
diff --git a/Tests/varLib/data/master_ufo/SparseMasters-Bold.ufo/glyphs/s.glif b/Tests/varLib/data/master_ufo/SparseMasters-Bold.ufo/glyphs/s.glif
new file mode 100644
index 00000000..ae47e9a9
--- /dev/null
+++ b/Tests/varLib/data/master_ufo/SparseMasters-Bold.ufo/glyphs/s.glif
@@ -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>
diff --git a/Tests/varLib/data/master_ufo/SparseMasters-Bold.ufo/layercontents.plist b/Tests/varLib/data/master_ufo/SparseMasters-Bold.ufo/layercontents.plist
new file mode 100644
index 00000000..03e5dde5
--- /dev/null
+++ b/Tests/varLib/data/master_ufo/SparseMasters-Bold.ufo/layercontents.plist
@@ -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>
diff --git a/Tests/varLib/data/master_ufo/SparseMasters-Bold.ufo/lib.plist b/Tests/varLib/data/master_ufo/SparseMasters-Bold.ufo/lib.plist
new file mode 100644
index 00000000..b0fd5eb2
--- /dev/null
+++ b/Tests/varLib/data/master_ufo/SparseMasters-Bold.ufo/lib.plist
@@ -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>
diff --git a/Tests/varLib/data/master_ufo/SparseMasters-Bold.ufo/metainfo.plist b/Tests/varLib/data/master_ufo/SparseMasters-Bold.ufo/metainfo.plist
new file mode 100644
index 00000000..555d9ce4
--- /dev/null
+++ b/Tests/varLib/data/master_ufo/SparseMasters-Bold.ufo/metainfo.plist
@@ -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>
diff --git a/Tests/varLib/data/master_ufo/SparseMasters-Medium.ufo/fontinfo.plist b/Tests/varLib/data/master_ufo/SparseMasters-Medium.ufo/fontinfo.plist
new file mode 100644
index 00000000..a8f59388
--- /dev/null
+++ b/Tests/varLib/data/master_ufo/SparseMasters-Medium.ufo/fontinfo.plist
@@ -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>
diff --git a/Tests/varLib/data/master_ufo/SparseMasters-Medium.ufo/glyphs/_notdef.glif b/Tests/varLib/data/master_ufo/SparseMasters-Medium.ufo/glyphs/_notdef.glif
new file mode 100644
index 00000000..5d3ca4d6
--- /dev/null
+++ b/Tests/varLib/data/master_ufo/SparseMasters-Medium.ufo/glyphs/_notdef.glif
@@ -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>
diff --git a/Tests/varLib/data/master_ufo/SparseMasters-Medium.ufo/glyphs/contents.plist b/Tests/varLib/data/master_ufo/SparseMasters-Medium.ufo/glyphs/contents.plist
new file mode 100644
index 00000000..456fd5de
--- /dev/null
+++ b/Tests/varLib/data/master_ufo/SparseMasters-Medium.ufo/glyphs/contents.plist
@@ -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>
diff --git a/Tests/varLib/data/master_ufo/SparseMasters-Medium.ufo/glyphs/e.glif b/Tests/varLib/data/master_ufo/SparseMasters-Medium.ufo/glyphs/e.glif
new file mode 100644
index 00000000..bf15c1ab
--- /dev/null
+++ b/Tests/varLib/data/master_ufo/SparseMasters-Medium.ufo/glyphs/e.glif
@@ -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>
diff --git a/Tests/varLib/data/master_ufo/SparseMasters-Medium.ufo/layercontents.plist b/Tests/varLib/data/master_ufo/SparseMasters-Medium.ufo/layercontents.plist
new file mode 100644
index 00000000..03e5dde5
--- /dev/null
+++ b/Tests/varLib/data/master_ufo/SparseMasters-Medium.ufo/layercontents.plist
@@ -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>
diff --git a/Tests/varLib/data/master_ufo/SparseMasters-Medium.ufo/lib.plist b/Tests/varLib/data/master_ufo/SparseMasters-Medium.ufo/lib.plist
new file mode 100644
index 00000000..3326cd65
--- /dev/null
+++ b/Tests/varLib/data/master_ufo/SparseMasters-Medium.ufo/lib.plist
@@ -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>
diff --git a/Tests/varLib/data/master_ufo/SparseMasters-Medium.ufo/metainfo.plist b/Tests/varLib/data/master_ufo/SparseMasters-Medium.ufo/metainfo.plist
new file mode 100644
index 00000000..555d9ce4
--- /dev/null
+++ b/Tests/varLib/data/master_ufo/SparseMasters-Medium.ufo/metainfo.plist
@@ -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>
diff --git a/Tests/varLib/data/master_ufo/SparseMasters-Regular.ufo/fontinfo.plist b/Tests/varLib/data/master_ufo/SparseMasters-Regular.ufo/fontinfo.plist
new file mode 100644
index 00000000..a36990b7
--- /dev/null
+++ b/Tests/varLib/data/master_ufo/SparseMasters-Regular.ufo/fontinfo.plist
@@ -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>
diff --git a/Tests/varLib/data/master_ufo/SparseMasters-Regular.ufo/glyphs/_notdef.glif b/Tests/varLib/data/master_ufo/SparseMasters-Regular.ufo/glyphs/_notdef.glif
new file mode 100644
index 00000000..5d3ca4d6
--- /dev/null
+++ b/Tests/varLib/data/master_ufo/SparseMasters-Regular.ufo/glyphs/_notdef.glif
@@ -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>
diff --git a/Tests/varLib/data/master_ufo/SparseMasters-Regular.ufo/glyphs/a.glif b/Tests/varLib/data/master_ufo/SparseMasters-Regular.ufo/glyphs/a.glif
new file mode 100644
index 00000000..5dcc9322
--- /dev/null
+++ b/Tests/varLib/data/master_ufo/SparseMasters-Regular.ufo/glyphs/a.glif
@@ -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>
diff --git a/Tests/varLib/data/master_ufo/SparseMasters-Regular.ufo/glyphs/contents.plist b/Tests/varLib/data/master_ufo/SparseMasters-Regular.ufo/glyphs/contents.plist
new file mode 100644
index 00000000..da7e7a78
--- /dev/null
+++ b/Tests/varLib/data/master_ufo/SparseMasters-Regular.ufo/glyphs/contents.plist
@@ -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>
diff --git a/Tests/varLib/data/master_ufo/SparseMasters-Regular.ufo/glyphs/dotabovecomb.glif b/Tests/varLib/data/master_ufo/SparseMasters-Regular.ufo/glyphs/dotabovecomb.glif
new file mode 100644
index 00000000..3abb24fd
--- /dev/null
+++ b/Tests/varLib/data/master_ufo/SparseMasters-Regular.ufo/glyphs/dotabovecomb.glif
@@ -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>
diff --git a/Tests/varLib/data/master_ufo/SparseMasters-Regular.ufo/glyphs/e.glif b/Tests/varLib/data/master_ufo/SparseMasters-Regular.ufo/glyphs/e.glif
new file mode 100644
index 00000000..52fc2b3c
--- /dev/null
+++ b/Tests/varLib/data/master_ufo/SparseMasters-Regular.ufo/glyphs/e.glif
@@ -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>
diff --git a/Tests/varLib/data/master_ufo/SparseMasters-Regular.ufo/glyphs/edotabove.glif b/Tests/varLib/data/master_ufo/SparseMasters-Regular.ufo/glyphs/edotabove.glif
new file mode 100644
index 00000000..9a6dbc56
--- /dev/null
+++ b/Tests/varLib/data/master_ufo/SparseMasters-Regular.ufo/glyphs/edotabove.glif
@@ -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>
diff --git a/Tests/varLib/data/master_ufo/SparseMasters-Regular.ufo/glyphs/s.glif b/Tests/varLib/data/master_ufo/SparseMasters-Regular.ufo/glyphs/s.glif
new file mode 100644
index 00000000..205b0e3d
--- /dev/null
+++ b/Tests/varLib/data/master_ufo/SparseMasters-Regular.ufo/glyphs/s.glif
@@ -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>
diff --git a/Tests/varLib/data/master_ufo/SparseMasters-Regular.ufo/layercontents.plist b/Tests/varLib/data/master_ufo/SparseMasters-Regular.ufo/layercontents.plist
new file mode 100644
index 00000000..03e5dde5
--- /dev/null
+++ b/Tests/varLib/data/master_ufo/SparseMasters-Regular.ufo/layercontents.plist
@@ -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>
diff --git a/Tests/varLib/data/master_ufo/SparseMasters-Regular.ufo/lib.plist b/Tests/varLib/data/master_ufo/SparseMasters-Regular.ufo/lib.plist
new file mode 100644
index 00000000..b0fd5eb2
--- /dev/null
+++ b/Tests/varLib/data/master_ufo/SparseMasters-Regular.ufo/lib.plist
@@ -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>
diff --git a/Tests/varLib/data/master_ufo/SparseMasters-Regular.ufo/metainfo.plist b/Tests/varLib/data/master_ufo/SparseMasters-Regular.ufo/metainfo.plist
new file mode 100644
index 00000000..555d9ce4
--- /dev/null
+++ b/Tests/varLib/data/master_ufo/SparseMasters-Regular.ufo/metainfo.plist
@@ -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>
diff --git a/Tests/varLib/data/test_results/Build.ttx b/Tests/varLib/data/test_results/Build.ttx
index c802bf32..144cca5e 100644
--- a/Tests/varLib/data/test_results/Build.ttx
+++ b/Tests/varLib/data/test_results/Build.ttx
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
-<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="3.17">
+<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="4.42">
<GDEF>
<Version value="0x00010003"/>
@@ -17,7 +17,7 @@
<Format value="1"/>
<VarRegionList>
<!-- RegionAxisCount=2 -->
- <!-- RegionCount=5 -->
+ <!-- RegionCount=2 -->
<Region index="0">
<VarRegionAxis index="0">
<StartCoord value="-1.0"/>
@@ -42,58 +42,29 @@
<EndCoord value="0.0"/>
</VarRegionAxis>
</Region>
- <Region index="2">
- <VarRegionAxis index="0">
- <StartCoord value="0.0"/>
- <PeakCoord value="0.0"/>
- <EndCoord value="0.0"/>
- </VarRegionAxis>
- <VarRegionAxis index="1">
- <StartCoord value="0.0"/>
- <PeakCoord value="1.0"/>
- <EndCoord value="1.0"/>
- </VarRegionAxis>
- </Region>
- <Region index="3">
- <VarRegionAxis index="0">
- <StartCoord value="-1.0"/>
- <PeakCoord value="-1.0"/>
- <EndCoord value="0.0"/>
- </VarRegionAxis>
- <VarRegionAxis index="1">
- <StartCoord value="0.0"/>
- <PeakCoord value="1.0"/>
- <EndCoord value="1.0"/>
- </VarRegionAxis>
- </Region>
- <Region index="4">
- <VarRegionAxis index="0">
- <StartCoord value="0.0"/>
- <PeakCoord value="1.0"/>
- <EndCoord value="1.0"/>
- </VarRegionAxis>
- <VarRegionAxis index="1">
- <StartCoord value="0.0"/>
- <PeakCoord value="1.0"/>
- <EndCoord value="1.0"/>
- </VarRegionAxis>
- </Region>
</VarRegionList>
<!-- VarDataCount=1 -->
<VarData index="0">
- <!-- ItemCount=6 -->
+ <!-- ItemCount=5 -->
<NumShorts value="0"/>
<!-- VarRegionCount=2 -->
<VarRegionIndex index="0" value="0"/>
<VarRegionIndex index="1" value="1"/>
- <Item index="0" value="[0, 0]"/>
- <Item index="1" value="[14, -28]"/>
- <Item index="2" value="[-10, 17]"/>
- <Item index="3" value="[-3, 32]"/>
- <Item index="4" value="[-7, 63]"/>
- <Item index="5" value="[-7, 63]"/>
+ <Item index="0" value="[-10, 17]"/>
+ <Item index="1" value="[-7, 63]"/>
+ <Item index="2" value="[-3, 32]"/>
+ <Item index="3" value="[0, 0]"/>
+ <Item index="4" value="[14, -28]"/>
</VarData>
</VarStore>
+ <AdvWidthMap>
+ <Map glyph=".notdef" outer="0" inner="3"/>
+ <Map glyph="uni0020" outer="0" inner="4"/>
+ <Map glyph="uni0024" outer="0" inner="1"/>
+ <Map glyph="uni0024.nostroke" outer="0" inner="1"/>
+ <Map glyph="uni0041" outer="0" inner="0"/>
+ <Map glyph="uni0061" outer="0" inner="2"/>
+ </AdvWidthMap>
</HVAR>
<MVAR>
@@ -105,7 +76,7 @@
<Format value="1"/>
<VarRegionList>
<!-- RegionAxisCount=2 -->
- <!-- RegionCount=5 -->
+ <!-- RegionCount=2 -->
<Region index="0">
<VarRegionAxis index="0">
<StartCoord value="-1.0"/>
@@ -130,42 +101,6 @@
<EndCoord value="0.0"/>
</VarRegionAxis>
</Region>
- <Region index="2">
- <VarRegionAxis index="0">
- <StartCoord value="0.0"/>
- <PeakCoord value="0.0"/>
- <EndCoord value="0.0"/>
- </VarRegionAxis>
- <VarRegionAxis index="1">
- <StartCoord value="0.0"/>
- <PeakCoord value="1.0"/>
- <EndCoord value="1.0"/>
- </VarRegionAxis>
- </Region>
- <Region index="3">
- <VarRegionAxis index="0">
- <StartCoord value="-1.0"/>
- <PeakCoord value="-1.0"/>
- <EndCoord value="0.0"/>
- </VarRegionAxis>
- <VarRegionAxis index="1">
- <StartCoord value="0.0"/>
- <PeakCoord value="1.0"/>
- <EndCoord value="1.0"/>
- </VarRegionAxis>
- </Region>
- <Region index="4">
- <VarRegionAxis index="0">
- <StartCoord value="0.0"/>
- <PeakCoord value="1.0"/>
- <EndCoord value="1.0"/>
- </VarRegionAxis>
- <VarRegionAxis index="1">
- <StartCoord value="0.0"/>
- <PeakCoord value="1.0"/>
- <EndCoord value="1.0"/>
- </VarRegionAxis>
- </Region>
</VarRegionList>
<!-- VarDataCount=1 -->
<VarData index="0">
diff --git a/Tests/varLib/data/test_results/BuildAvar2.ttx b/Tests/varLib/data/test_results/BuildAvar2.ttx
new file mode 100644
index 00000000..27a41bfb
--- /dev/null
+++ b/Tests/varLib/data/test_results/BuildAvar2.ttx
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="3.14">
+
+ <avar>
+ <version major="2" minor="0"/>
+ <segment axis="wght">
+ <mapping from="-1.0" to="-1.0"/>
+ <mapping from="-0.6667" to="-0.7969"/>
+ <mapping from="-0.3333" to="-0.5"/>
+ <mapping from="0.0" to="0.0"/>
+ <mapping from="0.2" to="0.18"/>
+ <mapping from="0.4" to="0.38"/>
+ <mapping from="0.6" to="0.61"/>
+ <mapping from="0.8" to="0.79"/>
+ <mapping from="1.0" to="1.0"/>
+ </segment>
+ <VarStore Format="1">
+ <Format value="1"/>
+ <VarRegionList>
+ <!-- RegionAxisCount=1 -->
+ <!-- RegionCount=1 -->
+ <Region index="0">
+ <VarRegionAxis index="0">
+ <StartCoord value="0.0"/>
+ <PeakCoord value="0.38"/>
+ <EndCoord value="0.38"/>
+ </VarRegionAxis>
+ </Region>
+ </VarRegionList>
+ <!-- VarDataCount=1 -->
+ <VarData index="0">
+ <!-- ItemCount=1 -->
+ <NumShorts value="1"/>
+ <!-- VarRegionCount=1 -->
+ <VarRegionIndex index="0" value="0"/>
+ <Item index="0" value="[1638]"/>
+ </VarData>
+ </VarStore>
+ </avar>
+
+</ttFont>
diff --git a/Tests/varLib/data/test_results/BuildAvarEmptyAxis.ttx b/Tests/varLib/data/test_results/BuildAvarEmptyAxis.ttx
index aee6f5ae..bff0993c 100644
--- a/Tests/varLib/data/test_results/BuildAvarEmptyAxis.ttx
+++ b/Tests/varLib/data/test_results/BuildAvarEmptyAxis.ttx
@@ -2,6 +2,7 @@
<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="3.14">
<avar>
+ <version major="1" minor="0"/>
<segment axis="wght">
<mapping from="-1.0" to="-1.0"/>
<mapping from="0.0" to="0.0"/>
diff --git a/Tests/varLib/data/test_results/BuildAvarIdentityMaps.ttx b/Tests/varLib/data/test_results/BuildAvarIdentityMaps.ttx
index 799d68f1..f348a5b7 100644
--- a/Tests/varLib/data/test_results/BuildAvarIdentityMaps.ttx
+++ b/Tests/varLib/data/test_results/BuildAvarIdentityMaps.ttx
@@ -2,6 +2,7 @@
<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="3.14">
<avar>
+ <version major="1" minor="0"/>
<segment axis="wght">
<mapping from="-1.0" to="-1.0"/>
<mapping from="-0.6667" to="-0.7969"/>
diff --git a/Tests/varLib/data/test_results/BuildAvarSingleAxis.ttx b/Tests/varLib/data/test_results/BuildAvarSingleAxis.ttx
index 9daa330f..aacd2888 100644
--- a/Tests/varLib/data/test_results/BuildAvarSingleAxis.ttx
+++ b/Tests/varLib/data/test_results/BuildAvarSingleAxis.ttx
@@ -2,6 +2,7 @@
<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="3.14">
<avar>
+ <version major="1" minor="0"/>
<segment axis="wght">
<mapping from="-1.0" to="-1.0"/>
<mapping from="-0.6667" to="-0.7969"/>
diff --git a/Tests/varLib/data/test_results/BuildMain.ttx b/Tests/varLib/data/test_results/BuildMain.ttx
index 27d02d1d..3a1bcfd3 100644
--- a/Tests/varLib/data/test_results/BuildMain.ttx
+++ b/Tests/varLib/data/test_results/BuildMain.ttx
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
-<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="3.19">
+<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="4.42">
<GlyphOrder>
<!-- The 'id' attribute is only for humans; it is ignored when parsed. -->
@@ -629,7 +629,7 @@
<Format value="1"/>
<VarRegionList>
<!-- RegionAxisCount=2 -->
- <!-- RegionCount=5 -->
+ <!-- RegionCount=2 -->
<Region index="0">
<VarRegionAxis index="0">
<StartCoord value="-1.0"/>
@@ -654,58 +654,29 @@
<EndCoord value="0.0"/>
</VarRegionAxis>
</Region>
- <Region index="2">
- <VarRegionAxis index="0">
- <StartCoord value="0.0"/>
- <PeakCoord value="0.0"/>
- <EndCoord value="0.0"/>
- </VarRegionAxis>
- <VarRegionAxis index="1">
- <StartCoord value="0.0"/>
- <PeakCoord value="1.0"/>
- <EndCoord value="1.0"/>
- </VarRegionAxis>
- </Region>
- <Region index="3">
- <VarRegionAxis index="0">
- <StartCoord value="-1.0"/>
- <PeakCoord value="-1.0"/>
- <EndCoord value="0.0"/>
- </VarRegionAxis>
- <VarRegionAxis index="1">
- <StartCoord value="0.0"/>
- <PeakCoord value="1.0"/>
- <EndCoord value="1.0"/>
- </VarRegionAxis>
- </Region>
- <Region index="4">
- <VarRegionAxis index="0">
- <StartCoord value="0.0"/>
- <PeakCoord value="1.0"/>
- <EndCoord value="1.0"/>
- </VarRegionAxis>
- <VarRegionAxis index="1">
- <StartCoord value="0.0"/>
- <PeakCoord value="1.0"/>
- <EndCoord value="1.0"/>
- </VarRegionAxis>
- </Region>
</VarRegionList>
<!-- VarDataCount=1 -->
<VarData index="0">
- <!-- ItemCount=6 -->
+ <!-- ItemCount=5 -->
<NumShorts value="0"/>
<!-- VarRegionCount=2 -->
<VarRegionIndex index="0" value="0"/>
<VarRegionIndex index="1" value="1"/>
- <Item index="0" value="[0, 0]"/>
- <Item index="1" value="[14, -28]"/>
- <Item index="2" value="[-10, 17]"/>
- <Item index="3" value="[-3, 32]"/>
- <Item index="4" value="[-7, 63]"/>
- <Item index="5" value="[-7, 63]"/>
+ <Item index="0" value="[-10, 17]"/>
+ <Item index="1" value="[-7, 63]"/>
+ <Item index="2" value="[-3, 32]"/>
+ <Item index="3" value="[0, 0]"/>
+ <Item index="4" value="[14, -28]"/>
</VarData>
</VarStore>
+ <AdvWidthMap>
+ <Map glyph=".notdef" outer="0" inner="3"/>
+ <Map glyph="uni0020" outer="0" inner="4"/>
+ <Map glyph="uni0024" outer="0" inner="1"/>
+ <Map glyph="uni0024.nostroke" outer="0" inner="1"/>
+ <Map glyph="uni0041" outer="0" inner="0"/>
+ <Map glyph="uni0061" outer="0" inner="2"/>
+ </AdvWidthMap>
</HVAR>
<MVAR>
@@ -717,7 +688,7 @@
<Format value="1"/>
<VarRegionList>
<!-- RegionAxisCount=2 -->
- <!-- RegionCount=5 -->
+ <!-- RegionCount=2 -->
<Region index="0">
<VarRegionAxis index="0">
<StartCoord value="-1.0"/>
@@ -742,42 +713,6 @@
<EndCoord value="0.0"/>
</VarRegionAxis>
</Region>
- <Region index="2">
- <VarRegionAxis index="0">
- <StartCoord value="0.0"/>
- <PeakCoord value="0.0"/>
- <EndCoord value="0.0"/>
- </VarRegionAxis>
- <VarRegionAxis index="1">
- <StartCoord value="0.0"/>
- <PeakCoord value="1.0"/>
- <EndCoord value="1.0"/>
- </VarRegionAxis>
- </Region>
- <Region index="3">
- <VarRegionAxis index="0">
- <StartCoord value="-1.0"/>
- <PeakCoord value="-1.0"/>
- <EndCoord value="0.0"/>
- </VarRegionAxis>
- <VarRegionAxis index="1">
- <StartCoord value="0.0"/>
- <PeakCoord value="1.0"/>
- <EndCoord value="1.0"/>
- </VarRegionAxis>
- </Region>
- <Region index="4">
- <VarRegionAxis index="0">
- <StartCoord value="0.0"/>
- <PeakCoord value="1.0"/>
- <EndCoord value="1.0"/>
- </VarRegionAxis>
- <VarRegionAxis index="1">
- <StartCoord value="0.0"/>
- <PeakCoord value="1.0"/>
- <EndCoord value="1.0"/>
- </VarRegionAxis>
- </Region>
</VarRegionList>
<!-- VarDataCount=1 -->
<VarData index="0">
diff --git a/Tests/varLib/data/test_results/DropOnCurves.ttx b/Tests/varLib/data/test_results/DropOnCurves.ttx
new file mode 100644
index 00000000..4bfd36ad
--- /dev/null
+++ b/Tests/varLib/data/test_results/DropOnCurves.ttx
@@ -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>
diff --git a/Tests/varLib/data/test_results/FeatureVars_rclt.ttx b/Tests/varLib/data/test_results/FeatureVars_rclt.ttx
index b889f3a5..43691364 100644
--- a/Tests/varLib/data/test_results/FeatureVars_rclt.ttx
+++ b/Tests/varLib/data/test_results/FeatureVars_rclt.ttx
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
-<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="3.29">
+<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="4.39">
<fvar>
diff --git a/Tests/varLib/data/test_results/InterpolateLayoutGPOS_7_diff.ttx b/Tests/varLib/data/test_results/InterpolateLayoutGPOS_7_diff.ttx
new file mode 100644
index 00000000..8a73402e
--- /dev/null
+++ b/Tests/varLib/data/test_results/InterpolateLayoutGPOS_7_diff.ttx
@@ -0,0 +1,116 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ttFont>
+
+ <GPOS>
+ <Version value="0x00010000"/>
+ <ScriptList>
+ <!-- ScriptCount=1 -->
+ <ScriptRecord index="0">
+ <ScriptTag value="DFLT"/>
+ <Script>
+ <DefaultLangSys>
+ <ReqFeatureIndex value="65535"/>
+ <!-- FeatureCount=1 -->
+ <FeatureIndex index="0" value="0"/>
+ </DefaultLangSys>
+ <!-- LangSysCount=0 -->
+ </Script>
+ </ScriptRecord>
+ </ScriptList>
+ <FeatureList>
+ <!-- FeatureCount=1 -->
+ <FeatureRecord index="0">
+ <FeatureTag value="xxxx"/>
+ <Feature>
+ <!-- LookupCount=1 -->
+ <LookupListIndex index="0" value="2"/>
+ </Feature>
+ </FeatureRecord>
+ </FeatureList>
+ <LookupList>
+ <!-- LookupCount=3 -->
+ <Lookup index="0">
+ <LookupType value="2"/>
+ <LookupFlag value="0"/>
+ <!-- SubTableCount=1 -->
+ <PairPos index="0" Format="1">
+ <Coverage>
+ <Glyph value="A"/>
+ </Coverage>
+ <ValueFormat1 value="4"/>
+ <ValueFormat2 value="0"/>
+ <!-- PairSetCount=1 -->
+ <PairSet index="0">
+ <!-- PairValueCount=1 -->
+ <PairValueRecord index="0">
+ <SecondGlyph value="a"/>
+ <Value1 XAdvance="17"/>
+ </PairValueRecord>
+ </PairSet>
+ </PairPos>
+ </Lookup>
+ <Lookup index="1">
+ <LookupType value="4"/>
+ <LookupFlag value="0"/>
+ <!-- SubTableCount=1 -->
+ <MarkBasePos index="0" Format="1">
+ <MarkCoverage>
+ <Glyph value="uni0303"/>
+ </MarkCoverage>
+ <BaseCoverage>
+ <Glyph value="a"/>
+ </BaseCoverage>
+ <!-- ClassCount=1 -->
+ <MarkArray>
+ <!-- MarkCount=1 -->
+ <MarkRecord index="0">
+ <Class value="0"/>
+ <MarkAnchor Format="1">
+ <XCoordinate value="0"/>
+ <YCoordinate value="510"/>
+ </MarkAnchor>
+ </MarkRecord>
+ </MarkArray>
+ <BaseArray>
+ <!-- BaseCount=1 -->
+ <BaseRecord index="0">
+ <BaseAnchor index="0" Format="1">
+ <XCoordinate value="273"/>
+ <YCoordinate value="510"/>
+ </BaseAnchor>
+ </BaseRecord>
+ </BaseArray>
+ </MarkBasePos>
+ </Lookup>
+ <Lookup index="2">
+ <LookupType value="7"/>
+ <LookupFlag value="0"/>
+ <!-- SubTableCount=1 -->
+ <ContextPos index="0" Format="1">
+ <Coverage>
+ <Glyph value="A"/>
+ </Coverage>
+ <!-- PosRuleSetCount=1 -->
+ <PosRuleSet index="0">
+ <!-- PosRuleCount=1 -->
+ <PosRule index="0">
+ <!-- GlyphCount=3 -->
+ <!-- PosCount=2 -->
+ <Input index="0" value="a"/>
+ <Input index="1" value="uni0303"/>
+ <PosLookupRecord index="0">
+ <SequenceIndex value="0"/>
+ <LookupListIndex value="0"/>
+ </PosLookupRecord>
+ <PosLookupRecord index="1">
+ <SequenceIndex value="2"/>
+ <LookupListIndex value="1"/>
+ </PosLookupRecord>
+ </PosRule>
+ </PosRuleSet>
+ </ContextPos>
+ </Lookup>
+ </LookupList>
+ </GPOS>
+
+</ttFont>
diff --git a/Tests/varLib/data/test_results/InterpolateLayoutGPOS_7_same.ttx b/Tests/varLib/data/test_results/InterpolateLayoutGPOS_7_same.ttx
new file mode 100644
index 00000000..17636512
--- /dev/null
+++ b/Tests/varLib/data/test_results/InterpolateLayoutGPOS_7_same.ttx
@@ -0,0 +1,116 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ttFont>
+
+ <GPOS>
+ <Version value="0x00010000"/>
+ <ScriptList>
+ <!-- ScriptCount=1 -->
+ <ScriptRecord index="0">
+ <ScriptTag value="DFLT"/>
+ <Script>
+ <DefaultLangSys>
+ <ReqFeatureIndex value="65535"/>
+ <!-- FeatureCount=1 -->
+ <FeatureIndex index="0" value="0"/>
+ </DefaultLangSys>
+ <!-- LangSysCount=0 -->
+ </Script>
+ </ScriptRecord>
+ </ScriptList>
+ <FeatureList>
+ <!-- FeatureCount=1 -->
+ <FeatureRecord index="0">
+ <FeatureTag value="xxxx"/>
+ <Feature>
+ <!-- LookupCount=1 -->
+ <LookupListIndex index="0" value="2"/>
+ </Feature>
+ </FeatureRecord>
+ </FeatureList>
+ <LookupList>
+ <!-- LookupCount=3 -->
+ <Lookup index="0">
+ <LookupType value="2"/>
+ <LookupFlag value="0"/>
+ <!-- SubTableCount=1 -->
+ <PairPos index="0" Format="1">
+ <Coverage>
+ <Glyph value="A"/>
+ </Coverage>
+ <ValueFormat1 value="4"/>
+ <ValueFormat2 value="0"/>
+ <!-- PairSetCount=1 -->
+ <PairSet index="0">
+ <!-- PairValueCount=1 -->
+ <PairValueRecord index="0">
+ <SecondGlyph value="a"/>
+ <Value1 XAdvance="-23"/>
+ </PairValueRecord>
+ </PairSet>
+ </PairPos>
+ </Lookup>
+ <Lookup index="1">
+ <LookupType value="4"/>
+ <LookupFlag value="0"/>
+ <!-- SubTableCount=1 -->
+ <MarkBasePos index="0" Format="1">
+ <MarkCoverage>
+ <Glyph value="uni0303"/>
+ </MarkCoverage>
+ <BaseCoverage>
+ <Glyph value="a"/>
+ </BaseCoverage>
+ <!-- ClassCount=1 -->
+ <MarkArray>
+ <!-- MarkCount=1 -->
+ <MarkRecord index="0">
+ <Class value="0"/>
+ <MarkAnchor Format="1">
+ <XCoordinate value="0"/>
+ <YCoordinate value="500"/>
+ </MarkAnchor>
+ </MarkRecord>
+ </MarkArray>
+ <BaseArray>
+ <!-- BaseCount=1 -->
+ <BaseRecord index="0">
+ <BaseAnchor index="0" Format="1">
+ <XCoordinate value="260"/>
+ <YCoordinate value="500"/>
+ </BaseAnchor>
+ </BaseRecord>
+ </BaseArray>
+ </MarkBasePos>
+ </Lookup>
+ <Lookup index="2">
+ <LookupType value="7"/>
+ <LookupFlag value="0"/>
+ <!-- SubTableCount=1 -->
+ <ContextPos index="0" Format="1">
+ <Coverage>
+ <Glyph value="A"/>
+ </Coverage>
+ <!-- PosRuleSetCount=1 -->
+ <PosRuleSet index="0">
+ <!-- PosRuleCount=1 -->
+ <PosRule index="0">
+ <!-- GlyphCount=3 -->
+ <!-- PosCount=2 -->
+ <Input index="0" value="a"/>
+ <Input index="1" value="uni0303"/>
+ <PosLookupRecord index="0">
+ <SequenceIndex value="0"/>
+ <LookupListIndex value="0"/>
+ </PosLookupRecord>
+ <PosLookupRecord index="1">
+ <SequenceIndex value="2"/>
+ <LookupListIndex value="1"/>
+ </PosLookupRecord>
+ </PosRule>
+ </PosRuleSet>
+ </ContextPos>
+ </Lookup>
+ </LookupList>
+ </GPOS>
+
+</ttFont>
diff --git a/Tests/varLib/data/test_results/SparseCFF2-VF.ttx b/Tests/varLib/data/test_results/SparseCFF2-VF.ttx
new file mode 100644
index 00000000..4a1861c9
--- /dev/null
+++ b/Tests/varLib/data/test_results/SparseCFF2-VF.ttx
@@ -0,0 +1,157 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ttFont sfntVersion="OTTO" ttLibVersion="4.42">
+
+ <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"/>
+ </GlyphOrder>
+
+ <CFF2>
+ <major value="2"/>
+ <minor value="0"/>
+ <CFFFont name="CFF2Font">
+ <FontMatrix value="0.001 0 0 0.001 0 0"/>
+ <FDArray>
+ <FontDict index="0">
+ <Private>
+ <BlueScale value="0.039625"/>
+ <BlueShift value="7"/>
+ <BlueFuzz value="1"/>
+ <LanguageGroup value="0"/>
+ <ExpansionFactor value="0.06"/>
+ </Private>
+ </FontDict>
+ </FDArray>
+ <CharStrings>
+ <CharString name=".notdef">
+ 50 -250 -100 1 blend
+ rmoveto
+ 400 1000 -400 100 100 -100 3 blend
+ hlineto
+ 50 -950 rmoveto
+ 900 300 -900 vlineto
+ </CharString>
+ <CharString name="a">
+ 468 -1 rmoveto
+ -21 435 -233 70 -205 -76 27 -91 -56 1 blend
+ 172 60 155 -40 -59 2 2 blend
+ 3 -360 56 1 blend
+ rlineto
+ 12 266 59 -2 2 blend
+ rmoveto
+ -352 -23 3 -218 139 -34 221 83 -6 63 -222 -60 -75 52 15 40 13 37 -21 5 blend
+ 2 46 294 35 -78 -30 2 blend
+ rlineto
+ </CharString>
+ <CharString name="e">
+ 1 vsindex
+ 127 228 -1 70 -25 1 2 blend
+ rmoveto
+ 449 -2 1 -45 -2 -2 2 blend
+ -5 79 -255 208 -276 -252 148 -279 338 63 -17 84 -280 -54 -82 188 170 153 163 -124 -355 6 27 0 0 -27 0 36 0 -29 0 -34 0 31 0 -1 0 2 0 -45 -2 13 28 100 37 0 13 0 -2 55 -40 -54 -32 -86 -30 -57 -85 -60 34 57 84 146 -5 0 21 blend
+ rlineto
+ </CharString>
+ </CharStrings>
+ <VarStore Format="1">
+ <Format value="1"/>
+ <VarRegionList>
+ <!-- RegionAxisCount=1 -->
+ <!-- RegionCount=3 -->
+ <Region index="0">
+ <VarRegionAxis index="0">
+ <StartCoord value="0.0"/>
+ <PeakCoord value="1.0"/>
+ <EndCoord value="1.0"/>
+ </VarRegionAxis>
+ </Region>
+ <Region index="1">
+ <VarRegionAxis index="0">
+ <StartCoord value="0.0"/>
+ <PeakCoord value="0.36365"/>
+ <EndCoord value="1.0"/>
+ </VarRegionAxis>
+ </Region>
+ <Region index="2">
+ <VarRegionAxis index="0">
+ <StartCoord value="0.36365"/>
+ <PeakCoord value="1.0"/>
+ <EndCoord value="1.0"/>
+ </VarRegionAxis>
+ </Region>
+ </VarRegionList>
+ <!-- VarDataCount=2 -->
+ <VarData index="0">
+ <!-- ItemCount=0 -->
+ <NumShorts value="0"/>
+ <!-- VarRegionCount=1 -->
+ <VarRegionIndex index="0" value="0"/>
+ </VarData>
+ <VarData index="1">
+ <!-- ItemCount=0 -->
+ <NumShorts value="0"/>
+ <!-- VarRegionCount=2 -->
+ <VarRegionIndex index="0" value="1"/>
+ <VarRegionIndex index="1" value="2"/>
+ </VarData>
+ </VarStore>
+ </CFFFont>
+
+ <GlobalSubrs>
+ <!-- The 'index' attribute is only for humans; it is ignored when parsed. -->
+ </GlobalSubrs>
+ </CFF2>
+
+ <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>
+
+ <hmtx>
+ <mtx name=".notdef" width="500" lsb="50"/>
+ <mtx name="a" width="600" lsb="9"/>
+ <mtx name="e" width="600" lsb="40"/>
+ </hmtx>
+
+ <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=2 -->
+ <NumShorts value="1"/>
+ <!-- VarRegionCount=1 -->
+ <VarRegionIndex index="0" value="0"/>
+ <Item index="0" value="[0]"/>
+ <Item index="1" value="[300]"/>
+ </VarData>
+ </VarStore>
+ <AdvWidthMap>
+ <Map glyph=".notdef" outer="0" inner="1"/>
+ <Map glyph="a" outer="0" inner="0"/>
+ <Map glyph="e" outer="0" inner="0"/>
+ </AdvWidthMap>
+ </HVAR>
+
+</ttFont>
diff --git a/Tests/varLib/data/test_results/SparseMasters.ttx b/Tests/varLib/data/test_results/SparseMasters.ttx
index a3f8e619..2871e24f 100644
--- a/Tests/varLib/data/test_results/SparseMasters.ttx
+++ b/Tests/varLib/data/test_results/SparseMasters.ttx
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
-<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="3.35">
+<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="4.42">
<GlyphOrder>
<!-- The 'id' attribute is only for humans; it is ignored when parsed. -->
@@ -440,28 +440,7 @@
<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>
+ <!-- RegionCount=0 -->
</VarRegionList>
<!-- VarDataCount=1 -->
<VarData index="0">
diff --git a/Tests/varLib/data/test_results/TestSparseCFF2VF.ttx b/Tests/varLib/data/test_results/TestSparseCFF2VF.ttx
index 264a3d4a..7c3267a8 100644
--- a/Tests/varLib/data/test_results/TestSparseCFF2VF.ttx
+++ b/Tests/varLib/data/test_results/TestSparseCFF2VF.ttx
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
-<ttFont sfntVersion="OTTO" ttLibVersion="3.41">
+<ttFont sfntVersion="OTTO" ttLibVersion="4.37">
<fvar>
@@ -189,7 +189,7 @@
<CharString name="cid00002" fdSelectIndex="2">
-12 83 1 126 2 blend
hstemhm
- 74 73 -57 40 -26 129 -125 122 4 blend
+ 74 73 -57 40 -26 129 -125 121.5 4 blend
vstemhm
hintmask 10100000
134 755 107 18 2 blend
@@ -208,927 +208,927 @@
</CharString>
<CharString name="cid01177" fdSelectIndex="1">
1 vsindex
- -72 30 253 30 94 30 92 30 65 30 131 45 -30 112 -99 17 -8 0 -12 59 -2 85 -64 2 -92 39 -1 56 -44 2 -63 35 -1 51 -43 1 -62 39 -1 56 -21 0 -31 56 -2 81 -56 2 -81 44 -2 63 -57 3 -81 31 -1 45 -18 0 -27 44 -2 63 16 blend
+ -72 30 253 30 94 30 92 30 65 30 131 45 -30 112 -99 17 -8 -0.02417 -12 59 -1.82175 85 -64 1.80664 -92 39 -0.88217 56 -44 1.86707 -63 35 -0.89426 51 -43 0.87009 -62 39 -0.88217 56 -21 -0.06345 -31 56 -1.83081 81 -56 1.83081 -81 44 -1.86707 63 -57 2.82779 -81 31 -0.90634 45 -18 -0.05438 -27 44 -1.86707 63 16 blend
hstemhm
- 193 30 83 30 147 30 173 30 66 30 -20 1 -28 75 -3 107 -74 3 -106 78 -4 111 -99 5 -141 81 -3 116 -79 2 -114 64 -2 92 -81 4 -115 80 -4 114 10 blend
+ 193 30 83 30 147 30 173 30 66 30 -20 0.93958 -28 75 -2.7734 107 -74 2.77643 -106 78 -3.76434 111 -99 4.70091 -141 81 -2.75528 116 -79 1.76132 -114 64 -1.80664 92 -81 3.75528 -115 80 -3.7583 114 10 blend
vstemhm
hintmask 1111100011111000
- 306 142 -19 1 -27 7 0 10 2 blend
+ 306 142 -19 0.9426 -27 7 0.02115 10 2 blend
rmoveto
- -156 45 -2 64 1 blend
+ -156 45 -1.86404 64 1 blend
vlineto
- -50 22 -8 79 -42 2 -59 8 -1 11 -18 0 -27 43 -1 62 4 blend
+ -50 22 -8 79 -42 1.87311 -59 8 -0.97583 11 -18 -0.05438 -27 43 -0.87009 62 4 blend
vhcurveto
- 17 186 8 -1 11 -68 3 -97 2 blend
- 0 18 8 0 12 1 blend
+ 17 186 8 -0.97583 11 -68 2.79456 -97 2 blend
+ 0 18 8 0.02417 12 1 blend
hhcurveto
- 70 13 25 114 5 22 -1 31 17 -1 24 2 1 4 0 -1 -1 7 0 10 5 blend
+ 70 13 25 114 5 22 -0.93353 31 17 -0.94864 24 2 1 4 0 -1 -1 7 0.02115 10 5 blend
hvcurveto
- -9 3 -12 4 -9 6 -20 1 -28 3 0 4 -31 1 -45 10 0 15 -13 0 -19 9 -1 13 6 blend
+ -9 3 -12 4 -9 6 -20 0.93958 -28 3 0 4 -31 0.90634 -45 10 0.03021 15 -13 -0.03928 -19 9 -0.97281 13 6 blend
rrcurveto
- -109 -4 -7 -13 -49 -38 -156 33 -1 47 -1 0 -1 1 0 1 2 0 3 10 0 15 9 0 13 60 -3 85 7 blend
- 0 -27 5 0 8 1 blend
+ -109 -4 -7 -13 -49 -38 -156 33 -0.9003 47 -1 0 -1 1 0 1 2 0 3 10 0.03021 15 9 0.02719 13 60 -2.81873 85 7 blend
+ 0 -27 5 0.0151 8 1 blend
hhcurveto
- -59 -10 5 22 11 0 16 2 -1 2 -1 0 -2 4 0 6 4 blend
+ -59 -10 5 22 11 0.03323 16 2 -1 2 -1 0 -2 4 0.01208 6 4 blend
hvcurveto
- 157 -47 2 -67 1 blend
+ 157 -47 1.858 -67 1 blend
vlineto
- 63 34 -74 3 -106 -25 1 -36 2 blend
+ 63 34 -74 2.77643 -106 -25 0.92447 -36 2 blend
rmoveto
- 65 -30 74 -47 37 -37 -7 1 -10 5 -1 7 -3 0 -4 5 0 7 -3 0 -4 6 0 9 6 blend
+ 65 -30 74 -47 37 -37 -7 0.97885 -10 5 -0.9849 7 -3 0 -4 5 0.0151 7 -3 0 -4 6 0.01813 9 6 blend
rrcurveto
- 20 22 -37 36 -75 47 -65 28 48 -2 68 47 -2 67 -1 0 -1 -6 1 -8 2 0 3 -8 0 -11 8 -1 11 -6 0 -9 8 blend
+ 20 22 -37 36 -75 47 -65 28 48 -1.85498 68 47 -1.858 67 -1 0 -1 -6 0.98187 -8 2 0 3 -8 -0.02417 -11 8 -0.97583 11 -6 -0.01813 -9 8 blend
rlinecurve
- 320 -64 -49 3 -69 -32 1 -46 2 blend
+ 320 -64 -49 2.85196 -69 -32 0.90332 -46 2 blend
rmoveto
- 76 -49 83 -75 38 -12 0 -18 -6 1 -8 -13 0 -19 -4 0 -6 -9 1 -12 5 blend
+ 76 -49 83 -75 38 -12 -0.03625 -18 -6 0.98187 -8 -13 -0.03928 -19 -4 -0.01208 -6 -9 0.97281 -12 5 blend
-54 rrcurveto
- 23 19 -38 54 -84 73 -76 49 69 -3 98 35 -2 50 5 0 8 2 0 3 11 0 16 2 0 2 13 -1 18 2 0 4 8 blend
+ 23 19 -38 54 -84 73 -76 49 69 -2.79153 98 35 -1.89426 50 5 0.0151 8 2 0 3 11 0.03323 16 2 0 2 13 -0.96072 18 2 0 4 8 blend
rlinecurve
- -557 -5 -85 4 -121 -6 0 -9 2 blend
+ -557 -5 -85 3.74321 -121 -6 -0.01813 -9 2 blend
rmoveto
- -28 -68 -50 -72 -77 -40 5 -1 6 1 0 1 3 1 5 6 0 9 13 -1 18 1 0 1 6 blend
+ -28 -68 -50 -72 -77 -40 5 -0.9849 6 1 0 1 3 1 5 6 0.01813 9 13 -0.96072 18 1 0 1 6 blend
rrcurveto
- 24 -17 79 42 47 74 31 71 62 -3 89 -42 2 -60 -7 1 -10 5 -1 7 -6 0 -8 1 0 1 -2 -1 -4 4 1 7 8 blend
+ 24 -17 79 42 47 74 31 71 62 -2.81268 89 -42 1.87311 -60 -7 0.97885 -10 5 -0.9849 7 -6 -0.01813 -8 1 0 1 -2 -1 -4 4 1.01208 7 8 blend
rlinecurve
- -117 625 -26 2 -36 42 -3 59 2 blend
+ -117 625 -26 1.92145 -36 42 -2.87311 59 2 blend
rmoveto
- -30 775 30 -57 3 -81 -3 0 -5 57 -3 81 3 blend
+ -30 775 30 -57 2.82779 -81 -3 0 -5 57 -2.82779 81 3 blend
vlineto
- -818 -176 -1 0 -2 12 0 18 2 blend
+ -818 -176 -1 0 -2 12 0.03625 18 2 blend
rmoveto
- -30 869 30 -56 2 -81 3 0 5 56 -2 81 3 blend
+ -30 869 30 -56 1.83081 -81 3 0 5 56 -1.83081 81 3 blend
vlineto
hintmask 0000001000100000
- -455 258 -40 2 -57 -38 2 -54 2 blend
+ -455 258 -40 1.87915 -57 -38 1.8852 -54 2 blend
rmoveto
hintmask 0000000100100000
- -99 30 -18 0 -27 81 -3 116 2 blend
+ -99 30 -18 -0.05438 -27 81 -2.75528 116 2 blend
vlineto
hintmask 0000001000100000
- 99 18 0 27 1 blend
+ 99 18 0.05438 27 1 blend
vlineto
hintmask 0111010010001000
- -236 -127 -60 2 -86 -18 0 -27 2 blend
+ -236 -127 -60 1.81873 -86 -18 -0.05438 -27 2 blend
rmoveto
- 26 -40 25 -53 9 -36 -12 1 -17 10 0 15 -10 -1 -15 13 0 19 -4 0 -6 11 -1 15 6 blend
+ 26 -40 25 -53 9 -36 -12 0.96375 -17 10 0.03021 15 -10 -1.03021 -15 13 0.03928 19 -4 -0.01208 -6 11 -0.96677 15 6 blend
rrcurveto
- 29 12 -10 35 -25 53 -27 39 76 -3 109 12 0 18 3 1 5 -10 0 -15 10 -1 14 -15 1 -21 11 0 16 -11 0 -16 8 blend
+ 29 12 -10 35 -25 53 -27 39 76 -2.77039 109 12 0.03625 18 3 1 5 -10 -0.03021 -15 10 -0.96979 14 -15 0.95468 -21 11 0.03323 16 -11 -0.03323 -16 8 blend
rlinecurve
- 393 2 -112 4 -161 -1 0 -2 2 blend
+ 393 2 -112 3.66164 -161 -1 0 -2 2 blend
rmoveto
- -16 -38 -31 -57 -23 -35 7 0 11 12 -1 17 13 -1 18 19 0 28 10 0 14 8 -1 11 6 blend
+ -16 -38 -31 -57 -23 -35 7 0.02115 11 12 -0.96375 17 13 -0.96072 18 19 0.0574 28 10 0.03021 14 8 -0.97583 11 6 blend
rrcurveto
- 27 -12 24 36 26 48 23 46 70 -2 101 -10 1 -14 -8 0 -12 -13 1 -18 -6 -1 -9 -17 0 -25 -1 1 -1 -10 1 -14 8 blend
+ 27 -12 24 36 26 48 23 46 70 -1.78851 101 -10 0.96979 -14 -8 -0.02417 -12 -13 0.96072 -18 -6 -1.01813 -9 -17 -0.05136 -25 -1 1 -1 -10 0.96979 -14 8 blend
rlinecurve
- -504 -378 27 -1 39 -8 0 -12 2 blend
+ -504 -378 27 -0.91843 39 -8 -0.02417 -12 2 blend
rmoveto
- 559 -94 -559 -110 5 -157 44 -2 63 110 -5 157 3 blend
+ 559 -94 -559 -110 4.66768 -157 44 -1.86707 63 110 -4.66768 157 3 blend
hlineto
- 216 -52 2 -74 1 blend
+ 216 -52 1.8429 -74 1 blend
vmoveto
- 559 -92 -559 -110 5 -157 43 -1 62 110 -5 157 3 blend
+ 559 -92 -559 -110 4.66768 -157 43 -0.87009 62 110 -4.66768 157 3 blend
hlineto
- -30 122 -75 3 -107 -4 0 -6 2 blend
+ -30 122 -75 2.7734 -107 -4 -0.01208 -6 2 blend
rmoveto
- -276 619 276 -26 0 -38 45 -2 64 26 0 38 3 blend
+ -276 619 276 -26 -0.07855 -38 45 -1.86404 64 26 0.07855 38 3 blend
vlineto
</CharString>
<CharString name="cid06449" fdSelectIndex="1">
2 vsindex
- -60 30 203 30 -9 9 67 7 -7 14 -14 30 -20 20 80 30 59 30 121 30 18 93 -30 30 -30 108 -23 0 -26 67 2 76 -98 -2 -111 42 0 47 -13 0 -14 13 0 14 -33 0 -37 11 0 13 -11 0 -13 8 0 8 -8 0 -8 53 0 60 -32 0 -36 32 0 36 -52 0 -59 57 1 65 -33 0 -38 53 0 60 -83 -1 -93 54 0 60 -6 -19 -24 33 19 55 -76 -1 -86 76 1 86 -76 -1 -86 59 1 67 26 blend
+ -60 30 203 30 -9 9 67 7 -7 14 -14 30 -20 20 80 30 59 30 121 30 18 93 -30 30 -30 108 -23 -0.20721 -26 67 1.6036 76 -98 -1.88289 -111 42 0.37837 47 -13 -0.11711 -14 13 0.11711 14 -33 -0.2973 -37 11 0.0991 13 -11 -0.0991 -13 7.5 0.06757 8.5 -7.5 -0.06757 -8.5 53 0.47748 60 -32 -0.28828 -36 32 0.28828 36 -52 -0.46848 -59 57 0.51352 65 -33 -0.2973 -38 53 0.47748 60 -83 -0.74774 -93 54 0.48648 60 -6 -19.05405 -24 33 19.2973 55 -76 -0.68468 -86 76 0.68468 86 -76 -0.68468 -86 59 0.53152 67 26 blend
hstemhm
- 77 30 42 30 139 30 23 30 71 10 74 30 15 30 16 30 158 30 28 30 -4 29 -14 0 -16 88 1 99 -82 -1 -92 87 1 98 -130 -1 -146 102 1 114 -73 -1 -82 74 2 84 -112 -2 -126 27 0 30 13 0 15 90 1 101 -126 -1 -142 75 1 84 -68 -1 -76 102 1 115 -144 -1 -162 94 1 105 -79 -1 -88 95 1 106 -81 -1 -91 74 1 83 22 blend
+ 77 30 42 30 139 30 23 30 71 10 74 30 15 30 16 30 158 30 28 30 -4 29 -14 -0.12613 -16 88 0.79279 99 -82 -0.73874 -92 87 0.78378 98 -130 -1.17117 -146 102 0.91891 114 -73 -0.65765 -82 74 1.66667 84 -112 -2 -126 27 0.24324 30 13 0.11711 15 90 0.8108 101 -126 -1.13513 -142 75 0.67567 84 -68 -0.61261 -76 102 0.91891 115 -144 -1.2973 -162 94 0.84685 105 -79 -0.71172 -88 95 0.85585 106 -81 -0.72974 -91 74 0.66667 83 22 blend
vstemhm
hintmask 110001011101011101101101
- 53 761 -3 0 -3 31 0 35 2 blend
+ 53 761 -3 -0.02702 -3 31 0.27928 35 2 blend
rmoveto
- -30 896 30 -76 -1 -86 5 0 5 76 1 86 3 blend
+ -30 896 30 -76 -0.68468 -86 5 0.04504 5 76 0.68468 86 3 blend
vlineto
- -802 -461 2 0 2 -23 0 -26 2 blend
+ -802 -461 2 0.01802 2 -23 -0.20721 -26 2 blend
rmoveto
- -30 703 30 -53 0 -60 3 0 4 53 0 60 3 blend
+ -30 703 30 -53 -0.47748 -60 3 0.02702 4 53 0.47748 60 3 blend
vlineto
hintmask 000000000000100100000000
- -532 539 -58 -1 -65 6 0 7 2 blend
+ -532 539 -58 -0.52252 -65 6 0.05405 7 2 blend
rmoveto
hintmask 000000000010000100000000
- -171 30 -16 -19 -36 102 1 114 2 blend
+ -171 30 -16 -19.14415 -36 102 0.91891 114 2 blend
vlineto
hintmask 000000000000100100001000
- 171 16 19 36 1 blend
+ 171 16 19.14415 36 1 blend
vlineto
- 299 -100 -1 -112 1 blend
+ 299 -100 -0.9009 -112 1 blend
hmoveto
hintmask 000000000010000000001000
- -171 30 -16 -19 -36 102 1 115 2 blend
+ -171 30 -16 -19.14415 -36 102 0.91891 115 2 blend
vlineto
hintmask 000000000000100000001000
- 171 16 19 36 1 blend
+ 171 16 19.14415 36 1 blend
vlineto
hintmask 000000111100011010010100
- -46 -219 -34 0 -39 -64 -1 -72 2 blend
+ -46 -219 -34 -0.3063 -39 -64 -0.57658 -72 2 blend
rmoveto
- 204 -121 -204 -110 -1 -123 83 1 93 110 1 123 3 blend
+ 204 -121 -204 -110 -1 -123 83 0.74774 93 110 1 123 3 blend
hlineto
- -230 121 33 1 38 -83 -1 -93 2 blend
+ -230 121 33 1.2973 38 -83 -0.74774 -93 2 blend
rmoveto
- 200 -121 -200 -108 -2 -122 83 1 93 108 2 122 3 blend
+ 200 -121 -200 -108 -1.97298 -122 83 0.74774 93 108 1.97298 122 3 blend
hlineto
- -222 121 27 -1 30 -83 -1 -93 2 blend
+ -222 121 27 -0.75676 30 -83 -0.74774 -93 2 blend
rmoveto
- 192 -121 -192 -101 -1 -114 83 1 93 101 1 114 3 blend
+ 192 -121 -192 -101 -0.90991 -114 83 0.74774 93 101 0.90991 114 3 blend
hlineto
- -30 151 -87 -1 -98 -29 0 -33 2 blend
+ -30 151 -87 -0.78378 -98 -29 -0.26126 -33 2 blend
rmoveto
- -181 716 181 -24 0 -27 11 0 12 24 0 27 3 blend
+ -181 716 181 -24 -0.21622 -27 11 0.0991 12 24 0.21622 27 3 blend
vlineto
- -788 -240 -17 0 -19 9 0 11 2 blend
+ -788 -240 -17 -0.15315 -19 9 0.08109 11 2 blend
rmoveto
- -130 30 100 -37 0 -42 88 1 99 -20 0 -23 3 blend
+ -130 30 100 -37 -0.33333 -42 88 0.79279 99 -20 -0.18018 -23 3 blend
vlineto
hintmask 000000110000000000000010
- 786 -100 30 130 -150 -1 -168 20 0 23 95 1 106 37 0 42 4 blend
+ 786 -100 30 130 -150 -1.35135 -168 20 0.18018 23 95 0.85585 106 37 0.33333 42 4 blend
hlineto
hintmask 000010000000000100000000
- -610 -123 -56 -1 -63 -44 0 -50 2 blend
+ -610 -123 -56 -0.5045 -63 -44 -0.3964 -50 2 blend
rmoveto
- -50 -62 -93 -73 -118 -54 8 -4 10 -9 6 -7 9 0 11 13 0 15 19 0 21 29 0 32 9 0 10 22 0 25 12 0 14 -11 0 -12 19 0 21 -26 0 -30 7 0 8 -16 0 -18 12 blend
+ -50 -62 -93 -73 -118 -54 8 -4 10 -9 6 -7 9 0.08109 11 13 0.11711 15 19 0.17117 21 29 0.26126 32 9 0.08109 10 22 0.1982 25 12 0.10811 14 -11 -0.0991 -12 19 0.17117 21 -26 -0.23424 -30 7 0.06306 8 -16 -0.14415 -18 12 blend
rrcurveto
hintmask 010000000000000001000000
- 121 58 92 75 59 70 3 0 3 -13 0 -14 -10 0 -11 -19 0 -21 -2 0 -2 8 0 8 6 blend
+ 121 58 92 75 59 70 3 0.02702 3 -13 -0.11711 -14 -10 -0.09009 -11 -19 -0.17117 -21 -2 -0.01802 -2 8 0.07207 8 6 blend
rrcurveto
- 124 -78 -89 -1 -100 32 0 36 2 blend
+ 124 -78 -89 -0.8018 -100 32 0.28828 36 2 blend
rmoveto
- -7 -6 0 -6 1 blend
+ -7 -6 -0.05405 -6 1 blend
vlineto
- -65 -139 -176 -81 -162 -31 6 -6 8 -12 3 -8 16 0 17 30 0 34 36 0 41 26 0 29 -7 0 -8 12 0 13 12 0 14 -16 0 -18 15 0 16 -30 0 -33 5 0 6 -18 0 -21 12 blend
+ -65 -139 -176 -81 -162 -31 6 -6 8 -12 3 -8 16 0.14415 17 30 0.27026 34 36 0.32433 41 26 0.23424 29 -7 -0.06306 -8 12 0.10811 13 12 0.10811 14 -16 -0.14415 -18 15 0.13513 16 -30 -0.27026 -33 5 0.04504 6 -18 -0.16216 -21 12 blend
rrcurveto
hintmask 001000000000000001000000
- 168 37 178 84 72 154 26 0 29 -5 0 -5 -23 0 -26 -12 0 -14 -5 0 -5 6 0 7 6 blend
+ 168 37 178 84 72 154 26 0.23424 29 -5 -0.04504 -5 -23 -0.20721 -26 -12 -0.10811 -14 -5 -0.04504 -5 6 0.05405 7 6 blend
rrcurveto
hintmask 110100000000000001100001
- -19 11 -6 -2 -47 0 -53 13 0 15 -13 0 -15 0 0 -1 4 blend
+ -19 11 -6 -2 -47 -0.42342 -53 13 0.11711 15 -13 -0.11711 -15 0 0 -1 4 blend
rlineto
- -333 -72 75 1 85 -55 0 -61 2 blend
+ -333 -72 75 0.67567 85 -55 -0.4955 -61 2 blend
rmoveto
- 65 -25 75 -46 38 -35 -35 0 -40 8 0 9 -38 0 -42 15 0 17 -18 0 -21 14 0 15 6 blend
+ 65 -25 75 -46 38 -35 -35 -0.31532 -40 8 0.07207 9 -38 -0.34235 -42 15 0.13513 17 -18 -0.16216 -21 14 0.12613 15 6 blend
rrcurveto
- 26 19 -39 34 -76 45 -64 25 49 0 56 31 0 35 19 0 21 -14 0 -16 39 0 44 -18 0 -20 32 0 36 -9 0 -10 8 blend
+ 26 19 -39 34 -76 45 -64 25 49 0.44144 56 31 0.27928 35 19 0.17117 21 -14 -0.12613 -16 39 0.35135 44 -18 -0.16216 -20 32 0.28828 36 -9 -0.08109 -10 8 blend
rlinecurve
- 72 55 -55 0 -62 28 0 31 2 blend
+ 72 55 -55 -0.4955 -62 28 0.25226 31 2 blend
rmoveto
- -30 -30 -42 0 -47 -42 0 -47 2 blend
+ -30 -30 -42 -0.37837 -47 -42 -0.37837 -47 2 blend
rlineto
- 269 30 -14 0 -16 42 0 47 2 blend
+ 269 30 -14 -0.12613 -16 42 0.37837 47 2 blend
hlineto
- 74 74 13 0 15 -22 0 -24 2 blend
+ 74 74 13 0.11711 15 -22 -0.1982 -24 2 blend
rmoveto
- -276 80 1 90 1 blend
+ -276 80 0.72072 90 1 blend
vlineto
- -52 21 -9 77 -48 0 -54 8 0 9 -21 0 -24 44 0 49 4 blend
+ -52 21 -9 77 -48 -0.43243 -54 8 0.07207 9 -21 -0.1892 -24 44 0.3964 49 4 blend
vhcurveto
- 16 182 8 0 9 -90 -1 -101 2 blend
- 0 18 8 0 9 1 blend
+ 16 182 8 0.07207 9 -90 -0.8108 -101 2 blend
+ 0 18 8 0.07207 9 1 blend
hhcurveto
- 62 12 21 88 4 25 0 28 20 0 22 6 0 7 10 0 11 9 0 10 5 blend
+ 62 12 21 88 4 25 0.22522 28 20 0.18018 22 6 0.05405 7 10 0.09009 11 9 0.08109 10 5 blend
hvcurveto
- -9 2 -12 5 -8 6 -24 0 -26 4 0 5 -34 0 -39 12 0 13 -16 0 -18 10 0 11 6 blend
+ -9 2 -12 5 -8 6 -24 -0.21622 -26 4 0.03604 5 -34 -0.3063 -39 12 0.10811 13 -16 -0.14415 -18 10 0.09009 11 6 blend
rrcurveto
- -81 25 0 28 1 blend
- -4 -6 -11 -41 -37 -154 -1 0 -1 0 1 1 11 -1 12 15 1 17 79 1 89 5 blend
- 0 -26 9 0 10 1 blend
+ -81 25 0.22522 28 1 blend
+ -4 -6 -11 -41 -37 -154 -1 0 -1 0 1 1 11 -0.9009 12 15 1.13513 17 79 0.71172 89 5 blend
+ 0 -26 9 0.08109 10 1 blend
hhcurveto
- -56 -9 6 25 17 0 19 2 0 3 -1 -1 -2 4 0 5 4 blend
+ -56 -9 6 25 17 0.15315 19 2 0.01802 3 -1 -1 -2 4 0.03604 5 4 blend
hvcurveto
- 276 -81 -1 -91 1 blend
+ 276 -81 -0.72974 -91 1 blend
vlineto
- 278 -62 -114 -1 -128 32 0 36 2 blend
+ 278 -62 -114 -1.02702 -128 32 0.28828 36 2 blend
rmoveto
- -66 -32 -126 -33 -107 -23 5 -7 5 -10 2 -7 110 22 126 32 81 36 10 0 11 7 0 8 30 0 34 11 0 12 21 0 23 9 0 10 7 0 8 -14 0 -16 9 0 10 -27 0 -30 3 0 4 -15 0 -17 -15 0 -17 -10 0 -11 -12 0 -14 -11 0 -12 3 0 4 -3 0 -4 18 blend
+ -66 -32 -126 -33 -107 -23 5 -7 5 -10 2 -7 110 22 126 32 81 36 10 0.09009 11 7 0.06306 8 30 0.27026 34 11 0.0991 12 21 0.1892 23 9 0.08109 10 7 0.06306 8 -14 -0.12613 -16 9 0.08109 10 -27 -0.24324 -30 3 0.02702 4 -15 -0.13513 -17 -15 -0.13513 -17 -10 -0.09009 -11 -12 -0.10811 -14 -11 -0.0991 -12 3 0.02702 4 -3 -0.02702 -4 18 blend
rrcurveto
</CharString>
<CharString name="cid06821" fdSelectIndex="1">
3 vsindex
- -58 30 100 30 70 22 -22 30 94 30 19 31 -17 28 152 20 -20 30 -12 12 66 30 -30 89 -5 30 -30 121 -11 0 -24 36 0 81 -32 0 -74 22 0 52 -17 0 -39 16 1 37 -16 -1 -37 21 0 48 -27 0 -63 21 0 49 -11 0 -26 41 0 93 -47 0 -107 24 0 56 -34 0 -78 11 0 26 -11 0 -26 17 0 39 -15 0 -35 15 0 35 -19 0 -43 12 0 26 -12 0 -26 4 0 8 -5 0 -11 28 0 65 -28 0 -65 23 0 52 28 blend
+ -58 30 100 30 70 22 -22 30 94 30 19 31 -17 28 152 20 -20 30 -12 12 66 30 -30 89 -5 30 -30 121 -11 -0.0196 -24 36 0.06418 81 -32 -0.05704 -74 22 0.03922 52 -17 -0.0303 -39 16 1.02852 37 -16 -1.02852 -37 21 0.03743 48 -27 -0.04813 -63 21 0.03743 49 -11 -0.0196 -26 41 0.07309 93 -47 -0.08379 -107 24 0.04279 56 -34 -0.06061 -78 11 0.0196 26 -11 -0.0196 -26 17 0.0303 39 -15 -0.02673 -35 15 0.02673 35 -19 -0.03387 -43 12 0.0214 26 -12 -0.0214 -26 4 0 8 -5 0 -11 28 0.04991 65 -28 -0.04991 -65 23 0.041 52 28 blend
hstemhm
- 127 30 -18 18 199 30 -20 20 -20 30 -24 14 97 30 -11 11 72 31 202 30 87 29 -12 0 -27 44 1 101 -19 -1 -45 19 1 45 -46 -1 -106 37 0 85 -31 0 -71 31 0 71 -31 0 -71 40 0 91 -27 0 -62 18 0 42 -47 0 -108 51 0 117 -27 0 -62 27 0 62 -53 0 -122 43 0 99 -60 -1 -138 52 1 120 -32 0 -73 32 0 72 22 blend
+ 127 30 -18 18 199 30 -20 20 -20 30 -24 14 97 30 -11 11 72 31 202 30 87 29 -12 -0.0214 -27 44 1.07843 101 -19 -1.03387 -45 19 1.03387 45 -46 -1.082 -106 37 0.06595 85 -31 -0.05525 -71 31 0.05525 71 -31 -0.05525 -71 40 0.0713 91 -27 -0.04813 -62 18 0.03209 42 -47 -0.08379 -108 51 0.09091 117 -27 -0.04813 -62 27 0.04813 62 -53 -0.09447 -122 43 0.07664 99 -60 -1.10695 -138 52 1.0927 120 -32 -0.05704 -73 32 0.05704 72 22 blend
vstemhm
hintmask 00011000000000000000000100000000
- 193 296 41 0 93 -8 0 -19 2 blend
+ 193 296 41 0.07309 93 -8 -0.01427 -19 2 blend
rmoveto
- 625 -94 -625 -84 -1 -192 27 0 63 84 1 192 3 blend
+ 625 -94 -625 -84 -1.14973 -192 27 0.04813 63 84 1.14973 192 3 blend
hlineto
- -30 124 -48 0 -110 -6 0 -14 2 blend
+ -30 124 -48 -0.08556 -110 -6 -0.0107 -14 2 blend
rmoveto
- -154 685 154 -15 0 -34 16 0 38 15 0 34 3 blend
+ -154 685 154 -15 -0.02673 -34 16 0.02852 38 15 0.02673 34 3 blend
vlineto
hintmask 00100000000000000000100000000000
- -365 -132 -33 0 -76 1 1 3 2 blend
+ -365 -132 -33 -0.05882 -76 1 1 3 2 blend
rmoveto
- -232 -7 -1 -16 1 blend
+ -232 -7 -1.01248 -16 1 blend
vlineto
- 30 -5 51 0 117 -11 0 -27 2 blend
+ 30 -5 51 0.09091 117 -11 -0.0196 -27 2 blend
rlineto
- 237 18 1 43 1 blend
+ 237 18 1.03209 43 1 blend
vlineto
hintmask 01000000000010010000010000000000
- -11 -92 -27 0 -62 1 -1 2 2 blend
+ -11 -92 -27 -0.04813 -62 1 -1 2 2 blend
rmoveto
- -30 397 30 -22 0 -52 -12 0 -27 22 0 52 3 blend
+ -30 397 30 -22 -0.03922 -52 -12 -0.0214 -27 22 0.03922 52 3 blend
vlineto
- -760 647 25 0 56 -4 0 -9 2 blend
+ -760 647 25 0.04456 56 -4 0 -9 2 blend
rmoveto
- -30 811 30 -28 0 -65 -12 0 -27 28 0 65 3 blend
+ -30 811 30 -28 -0.04991 -65 -12 -0.0214 -27 28 0.04991 65 3 blend
vlineto
hintmask 00000000000010100000000000000000
- -823 -13 0 -29 1 blend
+ -823 -13 -0.02318 -29 1 blend
hmoveto
- -143 12 0 27 1 blend
+ -143 12 0.0214 27 1 blend
vlineto
-83 -13 -107 -75 -82 4 0 9 3 0 6 5 1 12 -1 0 -1 5 -1 11 5 blend
vhcurveto
- 7 -4 11 -9 5 -6 10 0 21 -5 0 -12 20 0 46 -17 0 -38 6 0 15 -8 0 -18 6 blend
+ 7 -4 11 -9 5 -6 10 0.01782 21 -5 0 -12 20 0.03564 46 -17 -0.0303 -38 6 0.0107 15 -8 -0.01427 -18 6 blend
rrcurveto
79 5 0 11 1 blend
- 85 16 118 88 1 1 3 9 0 19 6 0 15 3 blend
+ 85 16 118 88 1 1 3 9 0.01604 19 6 0.0107 15 3 blend
vvcurveto
- 143 -11 0 -25 1 blend
+ 143 -11 -0.0196 -25 1 blend
vlineto
hintmask 00000000010100001000000000000000
- 199 -25 -46 -1 -106 -23 0 -54 2 blend
+ 199 -25 -46 -1.082 -106 -23 -0.041 -54 2 blend
rmoveto
-167 vlineto
hintmask 00000000010100000100000000000000
- 30 37 0 85 1 blend
+ 30 37 0.06595 85 1 blend
167 hlineto
hintmask 00000000101000000001000000000000
- -14 -59 -18 0 -42 8 0 18 2 blend
+ -14 -59 -18 -0.03209 -42 8 0.01427 18 2 blend
rmoveto
- -30 185 30 -12 0 -26 -4 0 -9 12 0 26 3 blend
+ -30 185 30 -12 -0.0214 -26 -4 0 -9 12 0.0214 26 3 blend
vlineto
- -365 -96 10 0 22 7 0 17 2 blend
+ -365 -96 10 0.01782 22 7 0.01248 17 2 blend
rmoveto
- -30 392 30 -17 0 -39 -4 0 -9 17 0 39 3 blend
+ -30 392 30 -17 -0.0303 -39 -4 0 -9 17 0.0303 39 3 blend
vlineto
hintmask 00000011000000000100000000000000
- -218 -10 -15 0 -33 -6 0 -13 2 blend
+ -218 -10 -15 -0.02673 -33 -6 -0.0107 -13 2 blend
rmoveto
- -160 23 0 51 1 blend
+ -160 23 0.041 51 1 blend
vlineto
-8 -2 0 0 -1 1 blend
-3 -11 -1 1 0 3 0 0 1 2 blend
vhcurveto
-11 -1 -30 2 0 4 1 0 1 4 0 10 3 blend
- 0 -47 13 0 30 1 blend
- 1 5 -9 6 -10 2 -9 4 0 8 -6 0 -13 6 0 13 -11 0 -25 2 0 6 -8 0 -19 6 blend
+ 0 -47 13 0.02318 30 1 blend
+ 1 5 -9 6 -10 2 -9 4 0 8 -6 -0.0107 -13 6 0.0107 13 -11 -0.0196 -25 2 0 6 -8 -0.01427 -19 6 blend
rrcurveto
hintmask 00000011000001000010001000000000
50 30 -5 0 -11 1 0 2 2 blend
0 6 17 3 0 8 5 1 12 2 blend
hvcurveto
- 17 5 4 9 21 6 -1 12 4 0 9 1 0 3 4 0 8 11 0 25 5 blend
+ 17 5 4 9 21 6 -0.9893 12 4 0 9 1 0 3 4 0 8 11 0.0196 25 5 blend
vvcurveto
- 159 -21 0 -46 1 blend
+ 159 -21 -0.03743 -46 1 blend
vlineto
- -132 -50 -39 0 -88 1 0 1 2 blend
+ -132 -50 -39 -0.06952 -88 1 0 1 2 blend
rmoveto
- -25 -42 -40 -39 -44 -30 8 -4 13 -10 5 -4 41 6 0 12 3 0 8 7 0 16 3 0 5 5 0 13 1 0 4 6 0 13 -3 0 -8 10 0 22 -6 0 -14 5 0 12 -5 0 -10 -3 0 -8 13 blend
- 30 45 -7 0 -14 1 blend
+ -25 -42 -40 -39 -44 -30 8 -4 13 -10 5 -4 41 6 0.0107 12 3 0 8 7 0.01248 16 3 0 5 5 0 13 1 0 4 6 0.0107 13 -3 0 -8 10 0.01782 22 -6 -0.0107 -14 5 0 12 -5 0 -10 -3 0 -8 13 blend
+ 30 45 -7 -0.01248 -14 1 blend
47 26 45 -3 0 -8 1 0 1 2 blend
rrcurveto
- 153 -7 -13 0 -30 -1 0 -2 2 blend
+ 153 -7 -13 -0.02318 -30 -1 0 -2 2 blend
rmoveto
- 35 -27 38 -39 18 -28 -8 3 -11 3 -5 -3 -9 3 -14 6 -7 -3 -5 1 -9 4 -4 0 6 blend
+ 35 -27 38 -39 18 -28 -8 2.98573 -11 3 -5 -3 -9 2.98396 -14 6 -6.9893 -3 -5 1 -9 4 -4 0 6 blend
rrcurveto
- 24 18 -18 27 -39 39 -34 25 23 1 55 6 -1 12 4 -1 8 -3 4 1 9 -3 13 -6 7 2 7 -3 9 -4 5 4 8 blend
+ 24 18 -18 27 -39 39 -34 25 23 1.041 55 6 -0.9893 12 4 -1 8 -3 4 1 9 -2.98396 13 -6 6.9893 2 7 -2.98752 9 -4 5 4 8 blend
rlinecurve
- 115 330 -53 -1 -124 9 1 21 2 blend
+ 115 330 -53 -1.09447 -124 9 1.01604 21 2 blend
rmoveto
hintmask 10000101000001000000001010000000
- 14 -286 131 -209 160 0 50 1 18 34 6 108 -9 3 -11 5 -9 7 -4 -92 -9 -34 -31 -1 -137 -2 -126 185 -12 281 3 0 8 6 0 14 5 0 10 -10 0 -22 -3 0 -6 0 0 -1 14 0 33 -1 0 -1 11 0 23 -3 0 -8 5 0 12 10 0 24 -10 0 -23 3 0 7 -14 0 -32 8 0 18 -8 0 -17 8 0 17 0 0 -1 11 0 26 0 0 1 4 0 9 5 0 11 1 0 1 29 0 67 0 1 2 8 0 17 0 -1 -1 -2 0 -4 -37 0 -85 30 blend
+ 14 -286 131 -209 160 0 50 1 18 34 6 108 -9 3 -11 5 -9 7 -4 -92 -9 -34 -31 -1 -137 -2 -126 185 -12 281 3 0 8 6 0.0107 14 5 0 10 -10 -0.01782 -22 -3 0 -6 0 0 -1 14 0.02495 33 -1 0 -1 11 0.0196 23 -3 0 -8 5 0 12 10 0.01782 24 -10 -0.01782 -23 3 0 7 -14 -0.02495 -32 8 0.01427 18 -8 -0.01427 -17 8 0.01427 17 0 0 -1 11 0.0196 26 0 0 1 4 0 9 5 0 11 1 0 1 29 0.0517 67 0 1 2 8 0.01427 17 0 -1 -1 -2 0 -4 -37 -0.06595 -85 30 blend
rrcurveto
- 207 -169 -37 0 -85 -4 0 -9 2 blend
+ 207 -169 -37 -0.06595 -85 -4 0 -9 2 blend
rmoveto
- -61 -129 -111 -108 -121 -69 7 -5 12 -11 5 -6 119 74 113 110 66 136 4 15 19 8 14 33 4 28 29 8 5 22 2 28 27 6 2 17 8 1 20 -6 0 -14 14 1 34 -13 -1 -31 6 0 15 -7 0 -17 0 -28 -23 -4 -2 -10 0 -27 -20 -1 -3 -5 -1 -16 -12 -1 -15 -19 18 blend
+ -61 -129 -111 -108 -121 -69 7 -5 12 -11 5 -6 119 74 113 110 66 136 4 15 19 8 14.01427 33 4 28 29 8 5.01427 22 2 28 27 6 2.0107 17 8 1.01427 20 -6 -0.0107 -14 14 1.02495 34 -13 -1.02318 -31 6 0.0107 15 -7 -0.01248 -17 0 -28 -23 -4 -2 -10 0 -27 -20 -1 -3 -5 -1 -16 -12 -1 -15 -19 18 blend
rrcurveto
- -156 153 -20 -2 -49 -2 0 -3 2 blend
+ -156 153 -20 -2.03564 -49 -2 0 -3 2 blend
rmoveto
52 -15 63 -26 34 -1 0 -3 -1 0 -1 0 0 1 0 0 -2 0 0 -2 5 blend
-21 rrcurveto
- 15 27 -34 20 -64 24 -51 14 21 0 48 20 0 47 -1 0 -1 1 0 1 0 0 -1 0 0 1 1 0 3 -1 0 -2 8 blend
+ 15 27 -34 20 -64 24 -51 14 21 0.03743 48 20 0.03564 47 -1 0 -1 1 0 1 0 0 -1 0 0 1 1 0 3 -1 0 -2 8 blend
rlinecurve
- -453 -763 1 0 2 12 0 27 2 blend
+ -453 -763 1 0 2 12 0.0214 27 2 blend
rmoveto
- -25 -16 -31 0 -71 -7 0 -17 2 blend
+ -25 -16 -31 -0.05525 -71 -7 -0.01248 -17 2 blend
rlineto
- -100 89 146 -18 233 -21 0 -46 -5 0 -12 -13 0 -29 -4 0 -9 -8 0 -18 5 blend
+ -100 89 146 -18 233 -21 -0.03743 -46 -5 0 -12 -13 -0.02318 -29 -4 0 -9 -8 -0.01427 -18 5 blend
hhcurveto
- 249 23 0 53 1 blend
+ 249 23 0.03743 53 1 blend
hlineto
- 2 8 6 14 6 8 -35 0 -207 2 -1 3 11 0 25 5 1 12 17 0 38 4 0 10 8 0 18 -16 0 -37 -1 0 -3 -1 0 -2 9 blend
- 0 -22 -14 0 -32 1 blend
- 0 -214 0 -150 15 -78 89 24 0 55 0 0 1 18 0 40 -2 0 -5 12 0 28 -1 0 -2 6 blend
+ 2 8 6 14 6 8 -35 0 -207 2 -1 3 11 0.0196 25 5 1 12 17 0.0303 38 4 0 10 8 0.01427 18 -16 -0.02852 -37 -1 0 -3 -1 0 -2 9 blend
+ 0 -22 -14 -0.02495 -32 1 blend
+ 0 -214 0 -150 15 -78 89 24 0.04279 55 0 0 1 18 0.03209 40 -2 0 -5 12 0.0214 28 -1 0 -2 6 blend
rrcurveto
- 5 62 -50 0 -114 -10 0 -22 2 blend
+ 5 62 -50 -0.08913 -114 -10 -0.01782 -22 2 blend
rmoveto
- -30 -97 -92 -60 -107 -36 8 -6 12 -11 4 -6 105 41 99 65 32 106 5 0 12 7 0 15 15 0 34 1 0 3 7 0 16 1 0 2 10 0 22 -6 0 -15 18 0 41 -17 0 -37 8 0 18 -8 0 -19 -2 0 -5 4 0 9 -12 0 -27 7 0 16 -1 0 -2 6 0 14 18 blend
+ -30 -97 -92 -60 -107 -36 8 -6 12 -11 4 -6 105 41 99 65 32 106 5 0 12 7 0.01248 15 15 0.02673 34 1 0 3 7 0.01248 16 1 0 2 10 0.01782 22 -6 -0.0107 -15 18 0.03209 41 -17 -0.0303 -37 8 0.01427 18 -8 -0.01427 -19 -2 0 -5 4 0 9 -12 -0.0214 -27 7 0.01248 16 -1 0 -2 6 0.0107 14 18 blend
rrcurveto
</CharString>
<CharString name="cid07253" fdSelectIndex="1">
1 vsindex
- -80 27 95 49 -48 48 -45 45 -30 30 -16 16 -13 13 49 30 48 30 47 19 -19 30 53 30 -18 18 51 11 -11 30 -22 22 62 30 60 30 15 81 -30 30 -30 102 -10 1 -14 41 -2 59 -53 2 -76 27 -1 38 -26 1 -37 26 -1 37 -27 1 -39 27 -1 39 -27 1 -39 27 -1 39 -13 0 -19 13 0 19 -14 0 -20 14 0 20 -19 1 -27 13 -1 19 -18 1 -26 13 0 19 -18 0 -26 18 0 26 -18 0 -26 23 -1 33 -21 1 -30 42 -2 60 -29 1 -42 29 -1 42 -19 1 -27 7 0 10 -7 0 -10 26 -1 37 -24 1 -34 24 -1 34 -27 1 -39 24 -1 34 -26 1 -37 26 -1 37 -40 1 -45 53 -2 66 -44 2 -62 44 -2 62 -44 2 -62 18 0 23 42 blend
+ -80 27 95 49 -48 48 -45 45 -30 30 -16 16 -13 13 49 30 48 30 47 19 -19 30 53 30 -18 18 51 11 -11 30 -22 22 62 30 60 30 15 81 -30 30 -30 102 -10 0.96979 -14 41 -1.87613 59 -53 1.83987 -76 27 -0.91843 38 -26 0.92145 -37 26 -0.92145 37 -27 0.91843 -39 27 -0.91843 39 -27 0.91843 -39 27 -0.91843 39 -13 -0.03928 -19 13 0.03928 19 -14 -0.0423 -20 14 0.0423 20 -19 0.9426 -27 13 -0.96072 19 -18 0.94562 -26 13 0.03928 19 -18 -0.05438 -26 18 0.05438 26 -18 -0.05438 -26 23 -0.93051 33 -21 0.93655 -30 42 -1.87311 60 -29 0.91238 -42 29 -0.91238 42 -19 0.9426 -27 7 0.02115 10 -7 -0.02115 -10 26 -0.92145 37 -24 0.92749 -34 24 -0.92749 34 -27 0.91843 -39 24 -0.92749 34 -26 0.92145 -37 26 -0.92145 37 -40 0.87915 -45 53 -1.83987 66 -44 1.86707 -62 44 -1.86707 62 -44 1.86707 -62 18 0.05438 23 42 blend
hstemhm
- 193 30 -1 30 -15 15 106 29 96 30 142 30 109 30 5 10 -28 1 -40 71 -2 102 -56 2 -80 75 -4 106 -21 2 -29 21 -2 29 -104 5 -148 55 -3 78 -42 3 -59 69 -4 98 -84 4 -120 79 -3 113 -94 3 -135 76 -3 109 -51 2 -73 25 -1 36 16 blend
+ 193 30 -1 30 -15 15 106 29 96 30 142 30 109 30 5 10 -28 0.9154 -40 71 -1.78549 102 -56 1.83081 -80 75 -3.7734 106 -21 1.93655 -29 21 -1.93655 29 -104 4.6858 -148 55 -2.83383 78 -42 2.87311 -59 69 -3.79153 98 -84 3.74623 -120 79 -2.76132 113 -94 2.71602 -135 76 -2.77039 109 -51 1.84592 -73 25 -0.92447 36 16 blend
vstemhm
hintmask 10000011101100101101000101110000
- 55 767 2 0 3 37 -2 55 2 blend
+ 55 767 2 0 3 37 -1.88821 55 2 blend
rmoveto
- -30 892 30 -44 2 -62 -6 0 -9 44 -2 62 3 blend
+ -30 892 30 -44 1.86707 -62 -6 -0.01813 -9 44 -1.86707 62 3 blend
vlineto
hintmask 00000000000000000000100000000000
- -637 72 -28 1 -40 -26 2 -39 2 blend
+ -637 72 -28 0.9154 -40 -26 1.92145 -39 2 blend
rmoveto
hintmask 00000000000000000010000000000000
- -153 30 -27 0 -27 77 -2 111 2 blend
+ -153 30 -27 -0.08157 -27 77 -1.76736 111 2 blend
vlineto
hintmask 00000000000000000000100000100000
- 153 27 0 27 1 blend
+ 153 27 0.08157 27 1 blend
vlineto
- 315 -89 3 -128 1 blend
+ 315 -89 2.73112 -128 1 blend
hmoveto
hintmask 00000000000000000010000000100000
- -153 30 -27 0 -27 79 -3 113 2 blend
+ -153 30 -27 -0.08157 -27 79 -2.76132 113 2 blend
vlineto
hintmask 00000000000100101100110000110000
- 153 27 0 27 1 blend
+ 153 27 0.08157 27 1 blend
vlineto
- -462 -288 8 0 12 -11 0 -16 2 blend
+ -462 -288 8 0.02417 12 -11 -0.03323 -16 2 blend
rmoveto
- 571 -62 -571 -102 3 -147 27 -1 39 102 -3 147 3 blend
+ 571 -62 -571 -102 2.69185 -147 27 -0.91843 39 102 -2.69185 147 3 blend
hlineto
- 152 -29 1 -42 1 blend
+ 152 -29 0.91238 -42 1 blend
vmoveto
- 571 -60 -571 -102 3 -147 26 -1 37 102 -3 147 3 blend
+ 571 -60 -571 -102 2.69185 -147 26 -0.92145 37 102 -2.69185 147 3 blend
hlineto
- -30 -71 2 -102 1 blend
+ -30 -71 1.78549 -102 1 blend
90 rmoveto
- -212 631 212 -23 1 -32 45 -2 64 23 -1 32 3 blend
+ -212 631 212 -23 0.93051 -32 45 -1.86404 64 23 -0.93051 32 3 blend
vlineto
- -776 -263 -22 1 -31 -4 0 -5 2 blend
+ -776 -263 -22 0.93353 -31 -4 -0.01208 -5 2 blend
rmoveto
- -30 905 30 -42 2 -60 10 0 14 42 -2 60 3 blend
+ -30 905 30 -42 1.87311 -60 10 0.03021 14 42 -1.87311 60 3 blend
vlineto
hintmask 00000001100000000000000100000000
- -716 -160 36 -1 52 -26 2 -37 2 blend
+ -716 -160 36 -0.89124 52 -26 1.92145 -37 2 blend
rmoveto
- -30 554 30 -13 0 -19 -59 2 -85 13 0 19 3 blend
+ -30 554 30 -13 -0.03928 -19 -59 1.82175 -85 13 0.03928 19 3 blend
vlineto
- -554 -78 59 -2 85 5 -1 7 2 blend
+ -554 -78 59 -1.82175 85 5 -0.9849 7 2 blend
rmoveto
- -30 563 30 -13 1 -19 -56 1 -81 13 -1 19 3 blend
+ -30 563 30 -13 0.96072 -19 -56 0.83081 -81 13 -0.96072 19 3 blend
vlineto
hintmask 00000010000000000000001000000000
- -578 -79 2 1 4 6 0 8 2 blend
+ -578 -79 2 1 4 6 0.01813 8 2 blend
rmoveto
hintmask 00001000000000000000001000001000
- -30 617 -27 1 -39 4 -1 5 2 blend
+ -30 617 -27 0.91843 -39 4 -0.98792 5 2 blend
vlineto
hintmask 00000010000001000000000000001000
- 30 27 -1 39 1 blend
+ 30 27 -0.91843 39 1 blend
vlineto
- -477 382 -24 2 -34 8 0 12 2 blend
+ -477 382 -24 1.92749 -34 8 0.02417 12 2 blend
rmoveto
- -46 -92 -113 -104 -167 -65 7 -5 10 -9 5 -8 6 -1 8 -5 -1 -8 17 0 25 11 0 16 -3 -1 -5 6 0 9 12 0 18 -11 0 -16 18 0 26 -27 1 -39 6 -1 8 -16 1 -23 12 blend
+ -46 -92 -113 -104 -167 -65 7 -5 10 -9 5 -8 6 -0.98187 8 -5 -1.0151 -8 17 0.05136 25 11 0.03323 16 -3 -1 -5 6 0.01813 9 12 0.03625 18 -11 -0.03323 -16 18 0.05438 26 -27 0.91843 -39 6 -0.98187 8 -16 0.95166 -23 12 blend
rrcurveto
hintmask 00000100010010010000000001000000
- 172 70 111 106 55 101 14 0 20 3 0 5 -6 0 -8 1 0 1 3 0 4 28 -1 41 6 blend
+ 172 70 111 106 55 101 14 0.0423 20 3 0 5 -6 -0.01813 -8 1 0 1 3 0 4 28 -0.9154 41 6 blend
rrcurveto
- 298 -65 -24 0 -35 3 0 4 2 blend
+ 298 -65 -24 -0.07251 -35 3 0 4 2 blend
rmoveto
- -25 -12 -55 2 -79 -15 0 -22 2 blend
+ -25 -12 -55 1.83383 -79 -15 -0.04532 -22 2 blend
rlineto
- 62 -80 121 -81 100 -38 5 8 9 11 7 6 -101 33 -119 76 -59 77 2 0 3 -14 1 -20 -10 1 -14 2 0 3 20 0 29 1 0 2 9 -1 13 18 -1 25 20 -1 28 26 -1 38 14 0 21 14 -1 19 -13 0 -19 -7 0 -10 9 0 13 -18 2 -25 4 -1 5 -7 0 -10 18 blend
+ 62 -80 121 -81 100 -38 5 8 9 11 7 6 -101 33 -119 76 -59 77 2 0 3 -14 0.9577 -20 -10 0.96979 -14 2 0 3 20 0.06042 29 1 0 2 9 -0.97281 13 18 -0.94562 25 20 -0.93958 28 26 -0.92145 38 14 0.0423 21 14 -0.9577 19 -13 -0.03928 -19 -7 -0.02115 -10 9 0.02719 13 -18 1.94562 -25 4 -0.98792 5 -7 -0.02115 -10 18 blend
rrcurveto
- -211 -88 -39 3 -55 -12 1 -17 2 blend
+ -211 -88 -39 2.88217 -55 -12 0.96375 -17 2 blend
rmoveto
- -239 30 239 -2 -1 -4 69 -4 98 2 1 4 3 blend
+ -239 30 239 -2 -1 -4 69 -3.79153 98 2 1 4 3 blend
vlineto
hintmask 10000010000000000000000000001000
- 316 -223 -74 3 -106 11 -1 15 2 blend
+ 316 -223 -74 2.77643 -106 11 -0.96677 15 2 blend
rmoveto
- -6 -4 0 -6 1 blend
+ -6 -4 -0.01208 -6 1 blend
vlineto
- -8 -87 -7 -34 -10 -10 2 0 3 24 -1 35 -1 1 -1 6 0 9 1 -1 1 1 0 1 6 blend
+ -8 -87 -7 -34 -10 -10 2 0 3 24 -0.92749 35 -1 1 -1 6 0.01813 9 1 -1 1 1 0 1 6 blend
rrcurveto
-6 -1 0 -1 1 blend
-6 -6 -1 -12 2 0 3 1 blend
hhcurveto
- -11 -31 1 0 1 10 0 15 2 blend
- 1 3 -34 0 -1 -1 9 0 13 2 blend
+ -11 -31 1 0 1 10 0.03021 15 2 blend
+ 1 3 -34 0 -1 -1 9 0.02719 13 2 blend
hvcurveto
- 5 -8 3 -13 6 -1 8 -11 1 -16 5 0 8 -19 1 -26 4 blend
- 1 -8 28 -2 30 -1 14 1 -14 1 -20 7 -1 9 1 0 1 2 0 3 2 -1 2 3 1 5 0 1 1 7 blend
- 21 0 10 4 10 9 16 15 7 35 2 -1 2 8 -1 11 2 0 3 5 0 7 5 0 8 3 -1 4 3 0 4 2 1 4 3 0 4 9 blend
- 9 89 -15 1 -21 1 blend
+ 5 -8 3 -13 6 -0.98187 8 -11 0.96677 -16 5 0.0151 8 -19 0.9426 -26 4 blend
+ 1 -8 28 -2 30 -1 14 1 -14 0.9577 -20 7 -0.97885 9 1 0 1 2 0 3 2 -1 2 3 1 5 0 1 1 7 blend
+ 21 0 10 4 10 9 16 15 7 35 2 -1 2 8 -0.97583 11 2 0 3 5 0.0151 7 5 0.0151 8 3 -1 4 3 0 4 2 1 4 3 0 4 9 blend
+ 9 89 -15 0.95468 -21 1 blend
rrcurveto
- 7 1 1 12 6 -1 8 1 0 1 1 -1 1 9 0 13 4 blend
+ 7 1 1 12 6 -0.98187 8 1 0 1 1 -1 1 9 0.02719 13 4 blend
0 hhcurveto
- -660 -34 -57 3 -82 -8 0 -11 2 blend
+ -660 -34 -57 2.82779 -82 -8 -0.02417 -11 2 blend
rmoveto
- -17 -46 1 0 2 7 0 10 2 blend
- -32 -46 -46 5 0 7 5 0 7 2 blend
- -23 20 -21 56 -2 81 -24 0 -35 2 blend
+ -17 -46 1 0 2 7 0.02115 10 2 blend
+ -32 -46 -46 5 0.0151 7 5 0.0151 7 2 blend
+ -23 20 -21 56 -1.83081 81 -24 -0.07251 -35 2 blend
rcurveline
hintmask 10010000000000000000000000000000
- 52 28 31 51 17 46 -4 -1 -7 0 1 1 -4 1 -5 -7 0 -10 1 -1 1 0 0 -1 6 blend
+ 52 28 31 51 17 46 -4 -1.01208 -7 0 1 1 -4 0.98792 -5 -7 -0.02115 -10 1 -1 1 0 0 -1 6 blend
rrcurveto
hintmask 00100000000000000000000010000000
- 110 -3 -67 3 -96 1 0 2 2 blend
+ 110 -3 -67 2.79758 -96 1 0 2 2 blend
rmoveto
- 13 -38 10 -49 0 -32 -3 0 -4 4 -1 5 -2 0 -3 2 1 4 -1 1 -1 3 0 4 6 blend
+ 13 -38 10 -49 0 -32 -3 0 -4 4 -0.98792 5 -2 0 -3 2 1 4 -1 1 -1 3 0 4 6 blend
rrcurveto
- 29 6 55 -3 78 8 -1 11 2 blend
- -1 31 -10 50 -15 37 -3 0 -4 0 1 1 -4 0 -6 3 -1 4 -4 1 -5 5 blend
+ 29 6 55 -2.83383 78 8 -0.97583 11 2 blend
+ -1 31 -10 50 -15 37 -3 0 -4 0 1 1 -4 -0.01208 -6 3 -1 4 -4 0.98792 -5 5 blend
rlinecurve
hintmask 01000000000000000000000000100000
- 113 -6 -56 3 -80 -7 0 -10 2 blend
+ 113 -6 -56 2.83081 -80 -7 -0.02115 -10 2 blend
rmoveto
22 -32 20 -44 7 -30 2 0 3 1 -1 1 3 -1 3 1 0 1 2 0 3 5 blend
rrcurveto
- 28 10 -8 29 -21 44 -23 32 48 -2 69 15 0 22 -2 1 -2 -1 0 -2 0 -1 -1 -5 1 -6 -1 1 -1 -4 0 -6 8 blend
+ 28 10 -8 29 -21 44 -23 32 48 -1.85498 69 15 0.04532 22 -2 1 -2 -1 0 -2 0 -1 -1 -5 0.9849 -6 -1 1 -1 -4 -0.01208 -6 8 blend
rlinecurve
hintmask 00010000001000000000001000000000
- 117 -5 -45 1 -65 -17 1 -24 2 blend
+ 117 -5 -45 0.86404 -65 -17 0.94864 -24 2 blend
rmoveto
25 -23 -1 0 -1 2 -1 2 2 blend
27 -32 13 -23 -2 1 -2 1 0 2 2 blend
rrcurveto
- 21 14 -12 44 -2 63 20 -1 28 0 0 -1 3 blend
+ 21 14 -12 44 -1.86707 63 20 -0.93958 28 0 0 -1 3 blend
22 -27 32 -26 22 -2 0 -2 -2 0 -3 1 0 1 -2 1 -2 4 blend
rlinecurve
- -381 267 39 -1 56 7 -1 10 2 blend
+ -381 267 39 -0.88217 56 7 -0.97885 10 2 blend
rmoveto
- -16 -30 -33 1 -47 -23 1 -33 2 blend
+ -16 -30 -33 0.9003 -47 -23 0.93051 -33 2 blend
rlineto
- 498 30 -42 1 -61 23 -1 33 2 blend
+ 498 30 -42 0.87311 -61 23 -0.93051 33 2 blend
hlineto
- -516 -23 21 0 31 -14 0 -21 2 blend
+ -516 -23 21 0.06345 31 -14 -0.0423 -21 2 blend
rmoveto
hintmask 00000010000000000000001000000000
- -224 6 0 9 1 blend
+ -224 6 0.01813 9 1 blend
vlineto
hintmask 00000010001000000000000100000000
- 30 247 75 -4 106 10 0 14 2 blend
+ 30 247 75 -3.7734 106 10 0.03021 14 2 blend
hlineto
</CharString>
<CharString name="cid13393" fdSelectIndex="1">
4 vsindex
- -50 30 -19 19 114 30 44 30 23 30 -30 114 35 30 316 30 -10 10 37 12 -21 0 -26 66 0 82 -29 21 -10 29 -21 10 -64 0 -80 55 0 69 -79 0 -99 75 0 94 -46 0 -58 56 0 71 -56 0 -71 26 21 59 -18 -25 -54 54 0 68 -76 8 -85 58 0 73 -24 0 -31 24 0 31 -46 -4 -63 30 0 37 20 blend
+ -50 30 -19 19 114 30 44 30 23 30 -30 114 35 30 316 30 -10 10 37 12 -21 -0.10448 -26 66 0.32835 82 -29 20.85573 -10 29 -20.85573 10 -64 -0.3184 -80 55 0.27364 69 -79 -0.39304 -99 75 0.37314 94 -46 -0.22885 -58 56 0.27861 71 -56 -0.27861 -71 26 21.12935 59 -18 -25.08955 -54 54 0.26866 68 -76 7.62189 -85 58 0.28856 73 -24 -0.1194 -31 24 0.1194 31 -46 -4.22885 -63 30 0.14925 37 20 blend
hstemhm
- 82 30 197 30 -26 8 317 30 168 13 -13 0 -16 77 0 96 -109 -1 -136 78 0 97 -77 0 -96 29 0 36 -10 0 -12 84 0 105 -86 0 -108 21 0 27 10 blend
+ 82 30 197 30 -26 8 317 30 168 13 -13 -0.06468 -16 77 0.38309 96 -109 -0.54228 -136 78 0.38806 97 -77 -0.38309 -96 29 0.14427 36 -10 -0.04974 -12 84 0.41791 105 -86 -0.42786 -108 21 0.10448 27 10 blend
vstemhm
hintmask 1010101101110110
- 529 746 23 0 29 30 4 43 2 blend
+ 529 746 23 0.11443 29 30 4.14925 43 2 blend
rmoveto
- -30 320 30 -58 0 -73 -29 0 -36 58 0 73 3 blend
+ -30 320 30 -58 -0.28856 -73 -29 -0.14427 -36 58 0.28856 73 3 blend
vlineto
- -397 -495 15 0 18 12 -4 10 2 blend
+ -397 -495 15 0.07463 18 12 -3.94029 10 2 blend
rmoveto
- -30 442 30 -56 0 -71 21 0 27 56 0 71 3 blend
+ -30 442 30 -56 -0.27861 -71 21 0.10448 27 56 0.27861 71 3 blend
vlineto
- -420 149 -6 0 -8 6 -4 2 2 blend
+ -420 149 -6 -0.02985 -8 6 -3.97015 2 2 blend
rmoveto
- -30 374 30 -54 0 -68 -25 0 -31 54 0 68 3 blend
+ -30 374 30 -54 -0.26866 -68 -25 -0.12437 -31 54 0.26866 68 3 blend
vlineto
- -514 -420 34 0 42 -3 4 1 2 blend
+ -514 -420 34 0.16916 42 -3 3.98508 1 2 blend
rmoveto
- -30 626 30 -66 0 -82 -29 0 -36 66 0 82 3 blend
+ -30 626 30 -66 -0.32835 -82 -29 -0.14427 -36 66 0.32835 82 3 blend
vlineto
- -531 144 15 0 19 -9 0 -11 2 blend
+ -531 144 15 0.07463 19 -9 -0.04477 -11 2 blend
rmoveto
- -30 460 30 -55 0 -69 -4 0 -5 55 0 69 3 blend
+ -30 460 30 -55 -0.27364 -69 -4 -0.0199 -5 55 0.27364 69 3 blend
vlineto
- -53 622 -42 0 -53 -6 4 -2 2 blend
+ -53 622 -42 -0.20895 -53 -6 3.97015 -2 2 blend
rmoveto
- -7 -9 0 -12 1 blend
+ -7 -9 -0.04477 -12 1 blend
vlineto
- -86 -171 -222 -118 -188 -45 7 -7 8 -11 3 -8 14 0 18 37 0 46 27 0 34 19 0 24 -7 0 -9 5 0 7 15 0 18 -16 0 -20 17 0 22 -32 0 -40 9 0 11 -19 0 -24 12 blend
+ -86 -171 -222 -118 -188 -45 7 -7 8 -11 3 -8 14 0.06966 18 37 0.18408 46 27 0.13432 34 19 0.09453 24 -7 -0.03482 -9 5 0.02487 7 15 0.07463 18 -16 -0.0796 -20 17 0.08458 22 -32 -0.15921 -40 9 0.04477 11 -19 -0.09453 -24 12 blend
rrcurveto
hintmask 0000000010000010
- 192 51 224 119 94 187 21 0 26 3 0 3 -17 0 -21 -9 0 -11 2 0 2 -3 0 -4 6 blend
+ 192 51 224 119 94 187 21 0.10448 26 3 0.01492 3 -17 -0.08458 -21 -9 -0.04477 -11 2 0 2 -3 -0.01492 -4 6 blend
rrcurveto
hintmask 0100010100000110
- -19 12 -6 -2 -55 0 -68 27 0 34 -12 0 -15 -3 0 -3 4 blend
+ -19 12 -6 -2 -55 -0.27364 -68 27 0.13432 34 -12 -0.05971 -15 -3 -0.01492 -3 4 blend
rlineto
- -323 -32 55 0 69 -25 0 -32 2 blend
+ -323 -32 55 0.27364 69 -25 -0.12437 -32 2 blend
rmoveto
- -25 -11 -68 0 -86 -23 0 -28 2 blend
+ -25 -11 -68 -0.3383 -86 -23 -0.11443 -28 2 blend
rlineto
- 83 -154 177 -116 201 -44 4 8 9 12 7 6 -200 39 -177 113 -79 147 11 0 14 12 0 15 -18 0 -22 21 0 26 -1 0 -1 4 0 5 11 0 13 21 0 26 21 0 27 32 0 40 17 0 21 16 0 20 9 0 11 -10 0 -12 17 0 21 -36 0 -45 1 0 2 -37 0 -47 18 blend
+ 83 -154 177 -116 201 -44 4 8 9 12 7 6 -200 39 -177 113 -79 147 11 0.05473 14 12 0.05971 15 -18 -0.08955 -22 21 0.10448 26 -1 0 -1 4 0.0199 5 11 0.05473 13 21 0.10448 26 21 0.10448 27 32 0.15921 40 17 0.08458 21 16 0.0796 20 9 0.04477 11 -10 -0.04974 -12 17 0.08458 21 -36 -0.17911 -45 1 0 2 -37 -0.18408 -47 18 blend
rrcurveto
- 59 127 -46 0 -58 9 -4 6 2 blend
+ 59 127 -46 -0.22885 -58 9 -3.95523 6 2 blend
rmoveto
- -40 -82 -80 -104 -112 -75 8 -4 10 -9 6 -7 115 80 2 0 2 8 0 10 7 0 9 23 0 29 2 0 3 16 0 20 16 0 20 -12 0 -15 26 0 32 -30 0 -37 10 0 13 -18 0 -23 8 0 10 -4 0 -5 14 blend
- 80 106 47 90 -13 0 -16 11 0 13 14 0 17 3 blend
+ -40 -82 -80 -104 -112 -75 8 -4 10 -9 6 -7 115 80 2 0 2 8 0.0398 10 7 0.03482 9 23 0.11443 29 2 0 3 16 0.0796 20 16 0.0796 20 -12 -0.05971 -15 26 0.12935 32 -30 -0.14925 -37 10 0.04974 13 -18 -0.08955 -23 8 0.0398 10 -4 -0.0199 -5 14 blend
+ 80 106 47 90 -13 -0.06468 -16 11 0.05473 13 14 0.06966 17 3 blend
rrcurveto
- -129 -493 -106 -5 -137 21 6 34 2 blend
+ -129 -493 -106 -4.52736 -137 21 6.10448 34 2 blend
rmoveto
- -27 -73 -43 -71 -51 -50 8 -5 13 -9 5 -5 49 52 47 77 29 77 6 0 8 11 0 14 7 0 8 8 0 10 5 0 7 8 0 10 16 0 20 -8 0 -10 28 0 35 -17 -1 -22 15 0 18 -11 0 -14 -3 0 -4 -4 0 -5 -2 0 -2 -1 0 -1 -3 0 -4 -3 1 -3 18 blend
+ -27 -73 -43 -71 -51 -50 8 -5 13 -9 5 -5 49 52 47 77 29 77 6 0.02985 8 11 0.05473 14 7 0.03482 8 8 0.0398 10 5 0.02487 7 8 0.0398 10 16 0.0796 20 -8 -0.0398 -10 28 0.1393 35 -17 -1.08458 -22 15 0.07463 18 -11 -0.05473 -14 -3 -0.01492 -4 -4 -0.0199 -5 -2 0 -2 -1 0 -1 -3 -0.01492 -4 -3 0.98508 -3 18 blend
rrcurveto
- 124 -1 -66 4 -77 10 15 31 2 blend
+ 124 -1 -66 3.67165 -77 10 15.04974 31 2 blend
rmoveto
- -374 30 374 4 0 5 84 0 105 -4 0 -5 3 blend
+ -374 30 374 4 0.0199 5 84 0.41791 105 -4 -0.0199 -5 3 blend
vlineto
hintmask 0000000000101000
- -586 460 -72 0 -90 2 -21 -24 2 blend
+ -586 460 -72 -0.35822 -90 2 -21 -24 2 blend
rmoveto
- -875 30 845 209 30 -27 0 -33 77 0 96 -53 0 -66 -79 0 -99 80 0 99 5 blend
+ -875 30 845 209 30 -27 -0.13432 -33 77 0.38309 96 -53 -0.26369 -66 -79 -0.39304 -99 80 0.39801 99 5 blend
vlineto
- -8 -29 0 -36 1 blend
+ -8 -29 -0.14427 -36 1 blend
hmoveto
- -7 -29 0 -36 1 blend
+ -7 -29 -0.14427 -36 1 blend
vlineto
- -28 -75 -43 -102 -46 -95 14 0 17 10 0 13 11 0 14 -41 0 -51 17 0 22 4 0 5 6 blend
+ -28 -75 -43 -102 -46 -95 14 0.06966 17 10 0.04974 13 11 0.05473 14 -41 -0.20398 -51 17 0.08458 22 4 0.0199 5 6 blend
rrcurveto
hintmask 0001000000010000
- 89 -91 24 -74 -63 -32 0 -40 23 0 28 -11 0 -14 10 0 13 17 0 21 5 blend
+ 89 -91 24 -74 -63 -32 -0.15921 -40 23 0.11443 28 -11 -0.05473 -14 10 0.04974 13 17 0.08458 21 5 blend
vvcurveto
- -33 -6 -35 -19 -13 3 0 4 1 0 1 15 0 18 7 0 9 4 0 5 5 blend
+ -33 -6 -35 -19 -13 3 0.01492 4 1 0 1 15 0.07463 18 7 0.03482 9 4 0.0199 5 5 blend
vhcurveto
- -10 -6 -12 3 0 3 0 0 1 1 0 2 3 blend
- -3 -14 -1 -20 -2 -26 1 -29 4 0 5 1 0 1 7 0 9 2 0 2 13 0 16 -1 0 -1 11 0 14 7 blend
- 2 7 -9 4 -13 11 0 13 -21 0 -26 5 0 6 -33 0 -41 4 blend
- 1 -8 22 -2 27 0 22 -21 0 -27 1 0 2 1 0 1 -3 0 -4 0 0 1 -4 0 -5 6 blend
- 2 19 2 17 5 12 9 3 0 4 2 0 2 3 0 3 2 0 2 4 0 5 3 0 4 6 blend
+ -10 -6 -12 3 0.01492 3 0 0 1 1 0 2 3 blend
+ -3 -14 -1 -20 -2 -26 1 -29 4 0.0199 5 1 0 1 7 0.03482 9 2 0 2 13 0.06468 16 -1 0 -1 11 0.05473 14 7 blend
+ 2 7 -9 4 -13 11 0.05473 13 -21 -0.10448 -26 5 0.02487 6 -33 -0.16418 -41 4 blend
+ 1 -8 22 -2 27 0 22 -21 -0.10448 -27 1 0 2 1 0 1 -3 -0.01492 -4 0 0 1 -4 -0.0199 -5 6 blend
+ 2 19 2 17 5 12 9 3 0.01492 4 2 0 2 3 0.01492 3 2 0 2 4 0.0199 5 3 0.01492 4 6 blend
rrcurveto
- 25 17 10 7 0 9 5 0 7 4 0 5 3 blend
- 43 44 22 0 27 1 blend
+ 25 17 10 7 0.03482 9 5 0.02487 7 4 0.0199 5 3 blend
+ 43 44 22 0.10945 27 1 blend
vvcurveto
- 67 -22 76 -86 89 -8 0 -10 9 0 12 -6 0 -8 24 0 30 -11 0 -13 5 blend
+ 67 -22 76 -86 89 -8 -0.0398 -10 9 0.04477 12 -6 -0.02985 -8 24 0.1194 30 -11 -0.05473 -13 5 blend
vhcurveto
hintmask 0000000001001000
- 39 84 42 98 33 81 -10 0 -13 -4 0 -5 -8 0 -10 14 0 17 -6 0 -8 7 0 9 6 blend
+ 39 84 42 98 33 81 -10 -0.04974 -13 -4 -0.0199 -5 -8 -0.0398 -10 14 0.06966 17 -6 -0.02985 -8 7 0.03482 9 6 blend
rrcurveto
hintmask 0000000000001000
- -20 14 -6 -2 -60 0 -75 32 0 40 -12 0 -14 -2 0 -3 4 blend
+ -20 14 -6 -2 -60 -0.29851 -75 32 0.15921 40 -12 -0.05971 -14 -2 0 -3 4 blend
rlineto
</CharString>
<CharString name="cid17290" fdSelectIndex="1">
5 vsindex
- 121 30 -22 22 148 30 -30 136 23 30 129 30 116 30 -21 4 -29 52 3 92 -32 23 -21 32 -23 21 -54 9 -83 50 4 90 -50 -4 -90 22 27 62 -2 -43 -47 41 0 69 -44 0 -74 37 0 62 -50 0 -84 36 0 61 14 blend
+ 121 30 -22 22 148 30 -30 136 23 30 129 30 116 30 -21 3.94763 -29 52 3.12967 92 -32 22.9202 -21 32 -22.9202 21 -54 8.86534 -83 50 4.1247 90 -50 -4.1247 -90 22 27.05486 62 -2 -43 -47 41 0.10225 69 -44 -0.10973 -74 37 0.09227 62 -50 -0.1247 -84 36 0.08978 61 14 blend
hstemhm
- 167 30 129 30 -16 16 123 30 48 30 -6 29 -29 111 -30 30 -16 16 201 30 1 29 -29 0 -49 64 0 108 -34 0 -57 51 0 85 -29 0 -48 29 0 48 -72 -2 -123 60 2 103 -69 0 -115 46 0 77 -42 0 -70 42 0 70 -42 0 -70 67 0 111 -51 0 -85 51 0 85 -29 0 -48 29 0 48 -79 0 -132 47 0 79 -45 0 -75 42 0 70 22 blend
+ 167 30 129 30 -16 16 123 30 48 30 -6 29 -29 111 -30 30 -16 16 201 30 1 29 -29 -0.07233 -49 64 0.1596 108 -34 -0.0848 -57 51 0.12718 85 -29 -0.07233 -48 29 0.07233 48 -72 -2.17955 -123 60 2.14963 103 -69 -0.17207 -115 46 0.11472 77 -42 -0.10474 -70 42 0.10474 70 -42 -0.10474 -70 67 0.16708 111 -51 -0.12718 -85 51 0.12718 85 -29 -0.07233 -48 29 0.07233 48 -79 -0.197 -132 47 0.1172 79 -45 -0.11221 -75 42 0.10474 70 22 blend
vstemhm
hintmask 011011111011001010000000
- 326 793 1 0 2 17 0 29 2 blend
+ 326 793 1 0 2 17 0.04239 29 2 blend
rmoveto
- -280 24 0 40 1 blend
+ -280 24 0.05984 40 1 blend
vlineto
- -47 16 -8 59 -31 0 -53 6 0 10 -13 0 -21 20 0 33 4 blend
+ -47 16 -8 59 -31 -0.0773 -53 6 0.01497 10 -13 -0.03242 -21 20 0.04988 33 4 blend
vhcurveto
hintmask 000010000000100000000000
- 13 120 4 0 6 -46 0 -76 2 blend
+ 13 120 4 0 6 -46 -0.11472 -76 2 blend
0 13 4 0 7 1 blend
hhcurveto
- 49 10 20 82 4 12 0 19 12 0 20 3 0 5 2 0 3 4 0 8 5 blend
+ 49 10 20 82 4 12 0.02992 19 12 0.02992 20 3 0 5 2 0 3 4 0 8 5 blend
hvcurveto
hintmask 101010101000010000000000
- -10 2 -11 5 -8 6 -12 0 -21 3 0 5 -21 0 -35 6 0 11 -9 0 -14 7 0 11 6 blend
+ -10 2 -11 5 -8 6 -12 -0.02992 -21 3 0 5 -21 -0.05237 -35 6 0.01497 11 -9 -0.02245 -14 7 0.01746 11 6 blend
rrcurveto
- -75 19 0 32 1 blend
- -3 -5 -10 -29 -24 -102 1 0 1 1 0 2 7 0 12 9 0 14 42 0 70 5 blend
- 0 -18 6 0 10 1 blend
+ -75 19 0.04738 32 1 blend
+ -3 -5 -10 -29 -24 -102 1 0 1 1 0 2 7 0.01746 12 9 0.02245 14 42 0.10474 70 5 blend
+ 0 -18 6 0.01497 10 1 blend
hhcurveto
- -38 -6 4 21 10 0 18 2 0 3 0 0 -1 4 0 7 4 blend
+ -38 -6 4 21 10 0.02493 18 2 0 3 0 0 -1 4 0 7 4 blend
hvcurveto
- 280 -25 0 -41 1 blend
+ 280 -25 -0.06235 -41 1 blend
vlineto
- -41 -464 -40 -8 -74 10 20 41 2 blend
+ -41 -464 -40 -8.09975 -74 10 20.02493 41 2 blend
rmoveto
- -30 617 30 -50 -4 -90 -5 12 5 50 4 90 3 blend
+ -30 617 30 -50 -4.1247 -90 -5 11.98753 5 50 4.1247 90 3 blend
vlineto
- -661 -178 11 -4 12 4 -13 -7 2 blend
+ -661 -178 11 -3.97256 12 4 -13 -7 2 blend
rmoveto
- -30 689 30 -52 -3 -92 -11 0 -18 52 3 92 3 blend
+ -30 689 30 -52 -3.12967 -92 -11 -0.02744 -18 52 3.12967 92 3 blend
vlineto
hintmask 010101100111001000000000
- -481 284 -27 -2 -48 -32 36 -21 2 blend
+ -481 284 -27 -2.06734 -48 -32 35.9202 -21 2 blend
rmoveto
- -306 30 306 0 -13 0 60 2 103 0 13 0 3 blend
+ -306 30 306 0 -13 0 60 2.14963 103 0 13 0 3 blend
vlineto
- 218 0 -61 0 -102 -1 0 -1 2 blend
+ 218 0 -61 -0.15211 -102 -1 0 -1 2 blend
rmoveto
- -306 30 306 0 -13 0 61 1 104 0 13 0 3 blend
+ -306 30 306 0 -13 0 61 1.15211 104 0 13 0 3 blend
vlineto
- -417 358 -17 -1 -30 19 -43 -12 2 blend
+ -417 358 -17 -1.04239 -30 19 -42.95262 -12 2 blend
rmoveto
- -30 217 -116 -217 -30 247 176 -36 0 -61 -52 0 -87 50 0 84 52 0 87 -37 0 -62 -6 0 -10 23 0 39 7 blend
+ -30 217 -116 -217 -30 247 176 -36 -0.08978 -61 -52 -0.12967 -87 50 0.1247 84 52 0.12967 87 -37 -0.09227 -62 -6 -0.01497 -10 23 0.05736 39 7 blend
vlineto
- 75 -26 0 -44 1 blend
+ 75 -26 -0.06483 -44 1 blend
hmoveto
hintmask 000010100000001001000000
- -280 24 0 40 1 blend
+ -280 24 0.05984 40 1 blend
vlineto
- -47 17 -8 60 -31 0 -53 5 0 9 -13 0 -21 20 0 33 4 blend
+ -47 17 -8 60 -31 -0.0773 -53 5 0.01247 9 -13 -0.03242 -21 20 0.04988 33 4 blend
vhcurveto
- 12 125 5 0 8 -47 0 -78 2 blend
+ 12 125 5 0.01247 8 -47 -0.1172 -78 2 blend
0 14 4 0 7 1 blend
hhcurveto
- 49 11 20 82 3 12 0 20 12 0 19 3 1 6 2 1 6 5 0 9 5 blend
+ 49 11 20 82 3 12 0.02992 20 12 0.02992 19 3 1 6 2 1 6 5 0.01247 9 5 blend
hvcurveto
- -9 2 -12 4 -8 7 -14 1 -22 3 0 5 -19 -1 -34 7 0 12 -9 0 -14 6 0 10 6 blend
+ -9 2 -12 4 -8 7 -14 0.96509 -22 3 0 5 -19 -1.04738 -34 7 0.01746 12 -9 -0.02245 -14 6 0.01497 10 6 blend
rrcurveto
- -75 19 -1 29 1 blend
- -3 -5 -10 -30 -25 -105 1 -1 1 8 0 13 8 0 14 42 0 70 4 blend
- 0 -18 6 0 9 1 blend
+ -75 19 -0.95262 29 1 blend
+ -3 -5 -10 -30 -25 -105 1 -1 1 8 0.01994 13 8 0.01994 14 42 0.10474 70 4 blend
+ 0 -18 6 0.01497 9 1 blend
hhcurveto
- -40 -6 4 21 11 0 19 2 0 3 0 0 -1 4 1 8 4 blend
+ -40 -6 4 21 11 0.02744 19 2 0 3 0 0 -1 4 1 8 4 blend
hvcurveto
- 280 -25 -1 -42 1 blend
+ 280 -25 -1.06235 -42 1 blend
vlineto
hintmask 000001110000000110000000
- -16 -29 0 -48 1 blend
+ -16 -29 -0.07233 -48 1 blend
hmoveto
- -30 217 -116 -217 -30 247 176 -36 0 -61 -50 0 -84 50 0 84 50 0 84 -37 0 -62 -3 0 -5 23 0 39 7 blend
+ -30 217 -116 -217 -30 247 176 -36 -0.08978 -61 -50 -0.1247 -84 50 0.1247 84 50 0.1247 84 -37 -0.09227 -62 -3 0 -5 23 0.05736 39 7 blend
vlineto
- -424 -714 -19 0 -32 -12 0 -21 2 blend
+ -424 -714 -19 -0.04738 -32 -12 -0.02992 -21 2 blend
rmoveto
- -52 -54 -91 -49 -81 -33 8 -5 11 -13 4 -6 80 36 94 56 56 58 7 0 11 9 0 15 5 0 9 11 0 18 -2 0 -3 9 0 15 13 0 22 -11 0 -18 24 0 39 -22 0 -36 11 0 19 -12 0 -21 4 0 7 -4 0 -6 2 0 2 -2 0 -4 -1 0 -1 3 0 5 18 blend
+ -52 -54 -91 -49 -81 -33 8 -5 11 -13 4 -6 80 36 94 56 56 58 7 0.01746 11 9 0.02245 15 5 0.01247 9 11 0.02744 18 -2 0 -3 9 0.02245 15 13 0.03242 22 -11 -0.02744 -18 24 0.05984 39 -22 -0.05486 -36 11 0.02744 19 -12 -0.02992 -21 4 0 7 -4 0 -6 2 0 2 -2 0 -4 -1 0 -1 3 0 5 18 blend
rrcurveto
- 200 -7 -92 0 -154 -5 0 -8 2 blend
+ 200 -7 -92 -0.22943 -154 -5 -0.01247 -8 2 blend
rmoveto
- 76 -41 90 -62 46 -42 -6 0 -10 5 0 8 -5 0 -7 6 0 10 -4 0 -7 4 0 7 6 blend
+ 76 -41 90 -62 46 -42 -6 -0.01497 -10 5 0.01247 8 -5 -0.01247 -7 6 0.01497 10 -4 0 -7 4 0 7 6 blend
rrcurveto
- 22 23 -46 42 -91 60 -75 39 60 0 100 29 0 48 0 0 -1 -3 0 -5 3 0 5 -7 0 -11 6 0 11 -7 0 -11 8 blend
+ 22 23 -46 42 -91 60 -75 39 60 0.14963 100 29 0.07233 48 0 0 -1 -3 0 -5 3 0 5 -7 -0.01746 -11 6 0.01497 11 -7 -0.01746 -11 8 blend
rlinecurve
- -499 750 -48 0 -81 6 0 10 2 blend
+ -499 750 -48 -0.1197 -81 6 0.01497 10 2 blend
rmoveto
- -54 -167 -87 -164 -96 -108 7 -6 11 -12 4 -6 98 116 88 165 58 175 7 0 13 15 0 25 10 0 16 14 0 22 11 0 19 10 0 17 9 0 15 -20 0 -33 15 0 24 -44 0 -73 4 0 7 -18 0 -30 4 0 6 4 0 6 3 0 6 19 0 32 0 0 -1 1 0 1 18 blend
+ -54 -167 -87 -164 -96 -108 7 -6 11 -12 4 -6 98 116 88 165 58 175 7 0.01746 13 15 0.0374 25 10 0.02493 16 14 0.03491 22 11 0.02744 19 10 0.02493 17 9 0.02245 15 -20 -0.04988 -33 15 0.0374 24 -44 -0.10973 -73 4 0 7 -18 -0.04489 -30 4 0 6 4 0 6 3 0 6 19 0.04738 32 0 0 -1 1 0 1 18 blend
rrcurveto
- -113 -214 -60 0 -100 -23 0 -37 2 blend
+ -113 -214 -60 -0.14963 -100 -23 -0.05736 -37 2 blend
rmoveto
- -691 30 718 20 0 33 64 0 108 43 0 72 3 blend
+ -691 30 718 20 0.04988 33 64 0.1596 108 43 0.10724 72 3 blend
vlineto
-1 -1 0 -3 1 blend
2 rlineto
</CharString>
<CharString name="cid17852" fdSelectIndex="1">
5 vsindex
- -67 29 219 30 154 30 -16 16 150 30 -30 122 -85 30 -18 18 87 30 -30 140 -122 12 -14 0 -22 46 0 78 -59 -3 -106 46 0 77 -53 -9 -92 46 2 81 -18 20 -1 18 -20 1 -54 13 -80 46 2 81 -46 -2 -81 25 31 61 -14 -34 -48 60 0 100 -64 0 -107 64 0 107 -55 0 -92 54 0 90 -54 0 -90 36 0 59 -19 0 -31 37 0 62 22 blend
+ -67 29 219 30 154 30 -16 16 150 30 -30 122 -85 30 -18 18 87 30 -30 140 -122 12 -14 -0.03491 -22 46 0.11472 78 -59 -3.14713 -106 46 0.11472 77 -53 -9.13217 -92 46 2.11472 81 -18 19.95511 -1 18 -19.95511 1 -54 12.86534 -80 46 2.11472 81 -46 -2.11472 -81 25 31.06235 61 -14 -34.03491 -48 60 0.14963 100 -64 -0.1596 -107 64 0.1596 107 -55 -0.13716 -92 54 0.13466 90 -54 -0.13466 -90 36 0.08978 59 -19 -0.04738 -31 37 0.09227 62 22 blend
hstemhm
- 51 188 -30 30 -30 149 21 30 -18 18 -13 13 66 30 -12 12 135 30 41 30 172 30 -6 28 -8 0 -14 30 0 50 -62 0 -103 62 0 103 -62 0 -103 32 0 53 -5 0 -7 59 0 98 -24 0 -41 24 0 41 -16 0 -27 16 0 27 -32 0 -53 53 0 88 -33 0 -56 33 0 56 -87 0 -146 63 0 106 -42 0 -70 54 0 90 -99 0 -165 55 0 91 -42 0 -70 45 0 75 24 blend
+ 51 188 -30 30 -30 149 21 30 -18 18 -13 13 66 30 -12 12 135 30 41 30 172 30 -6 28 -8 -0.01994 -14 30 0.07481 50 -62 -0.15462 -103 62 0.15462 103 -62 -0.15462 -103 32 0.0798 53 -5 -0.01247 -7 59 0.14713 98 -24 -0.05984 -41 24 0.05984 41 -16 -0.0399 -27 16 0.0399 27 -32 -0.0798 -53 53 0.13217 88 -33 -0.08229 -56 33 0.08229 56 -87 -0.21696 -146 63 0.1571 106 -42 -0.10474 -70 54 0.13466 90 -99 -0.24689 -165 55 0.13716 91 -42 -0.10474 -70 45 0.11221 75 24 blend
vstemhm
hintmask 000000100001000000000000
- 51 612 -8 0 -14 29 0 49 2 blend
+ 51 612 -8 -0.01994 -14 29 0.07233 49 2 blend
rmoveto
- -30 -60 0 -100 1 blend
+ -30 -60 -0.14963 -100 1 blend
vlineto
hintmask 000000100000010000000000
- 307 30 60 0 100 1 blend
+ 307 30 60 0.14963 100 1 blend
hlineto
hintmask 000000010010100100000000
- -149 228 -32 0 -53 -20 0 -34 2 blend
+ -149 228 -32 -0.0798 -53 -20 -0.04988 -34 2 blend
rmoveto
- -918 30 918 -19 0 -32 62 0 103 19 0 32 3 blend
+ -918 30 918 -19 -0.04738 -32 62 0.15462 103 19 0.04738 32 3 blend
vlineto
- -36 -238 -55 0 -91 -32 0 -53 2 blend
+ -36 -238 -55 -0.13716 -91 -32 -0.0798 -53 2 blend
rmoveto
- -31 -160 -74 -193 -68 -95 7 -5 10 -11 6 -8 70 101 74 203 33 160 6 0 10 25 0 42 13 0 21 23 0 37 4 0 7 1 0 2 8 0 14 -18 0 -30 13 0 21 -27 0 -44 4 0 7 -19 0 -32 1 0 2 6 0 10 -12 0 -20 -2 0 -3 -2 0 -4 -1 0 -2 18 blend
+ -31 -160 -74 -193 -68 -95 7 -5 10 -11 6 -8 70 101 74 203 33 160 6 0.01497 10 25 0.06235 42 13 0.03242 21 23 0.05736 37 4 0 7 1 0 2 8 0.01994 14 -18 -0.04489 -30 13 0.03242 21 -27 -0.06734 -44 4 0 7 -19 -0.04738 -32 1 0 2 6 0.01497 10 -12 -0.02992 -20 -2 0 -3 -2 0 -4 -1 0 -2 18 blend
rrcurveto
- 4 -143 19 0 32 77 0 128 2 blend
+ 4 -143 19 0.04738 32 77 0.19202 128 2 blend
rmoveto
- -21 -16 25 -26 72 -92 21 -33 -23 0 -38 -34 0 -57 1 0 2 -15 0 -24 -12 0 -21 -6 0 -11 2 0 3 -18 0 -29 8 blend
+ -21 -16 25 -26 72 -92 21 -33 -23 -0.05736 -38 -34 -0.0848 -57 1 0 2 -15 -0.0374 -24 -12 -0.02992 -21 -6 -0.01497 -11 2 0 3 -18 -0.04489 -29 8 blend
rlinecurve
- 24 24 -18 25 -81 96 -22 22 28 0 48 63 0 105 2 0 2 -1 0 -2 1 0 3 10 0 16 1 0 1 1 0 2 8 blend
+ 24 24 -18 25 -81 96 -22 22 28 0.06982 48 63 0.1571 105 2 0 2 -1 0 -2 1 0 3 10 0.02493 16 1 0 1 1 0 2 8 blend
rlinecurve
- 157 278 1 0 1 -14 0 -23 2 blend
+ 157 278 1 0 1 -14 -0.03491 -23 2 blend
rmoveto
hintmask 000000001000000100000000
- -30 559 -54 0 -90 -17 3 -23 2 blend
+ -30 559 -54 -0.13466 -90 -17 2.95761 -23 2 blend
vlineto
hintmask 010000000010000000100000
- 30 54 0 90 1 blend
+ 30 54 0.13466 90 1 blend
vlineto
- -457 -518 29 -3 43 -9 -3 -20 2 blend
+ -457 -518 29 -2.92767 43 -9 -3.02245 -20 2 blend
rmoveto
- -30 176 30 -46 0 -77 -17 0 -27 46 0 77 3 blend
+ -30 176 30 -46 -0.11472 -77 -17 -0.04239 -27 46 0.11472 77 3 blend
vlineto
hintmask 000000000100000001010000
- -194 120 -3 0 -5 -42 37 -35 2 blend
+ -194 120 -3 0 -5 -42 36.89526 -35 2 blend
rmoveto
- -365 30 365 38 -29 45 53 0 88 -38 29 -45 3 blend
+ -365 30 365 38 -28.90524 45 53 0.13217 88 -38 28.90524 -45 3 blend
vlineto
- 135 508 -87 0 -146 33 -34 24 2 blend
+ 135 508 -87 -0.21696 -146 33 -33.91771 24 2 blend
rmoveto
hintmask 000000000010000000010000
- -122 30 -19 0 -31 63 0 106 2 blend
+ -122 30 -19 -0.04738 -31 63 0.1571 106 2 blend
vlineto
hintmask 000101000100000000010000
- 122 19 0 31 1 blend
+ 122 19 0.04738 31 1 blend
vlineto
- -115 -172 -60 0 -100 -27 34 -19 2 blend
+ -115 -172 -60 -0.14963 -100 -27 33.93266 -19 2 blend
rmoveto
- -288 30 288 11 -24 18 50 0 83 -11 24 -18 3 blend
+ -288 30 288 11 -23.97256 18 50 0.1247 83 -11 23.97256 -18 3 blend
vlineto
- 148 -62 -2 -106 1 blend
+ 148 -62 -2.15462 -106 1 blend
hmoveto
- -288 30 288 11 -24 18 50 0 83 -11 24 -18 3 blend
+ -288 30 288 11 -23.97256 18 50 0.1247 83 -11 23.97256 -18 3 blend
vlineto
- 156 -394 -30 2 -47 19 -34 6 2 blend
+ 156 -394 -30 1.92519 -47 19 -33.95262 6 2 blend
rmoveto
- -52 -36 -89 -48 -61 -29 7 0 12 2 0 4 14 0 23 3 0 4 11 0 18 4 0 8 6 blend
+ -52 -36 -89 -48 -61 -29 7 0.01746 12 2 0 4 14 0.03491 23 3 0 4 11 0.02744 18 4 0 8 6 blend
rrcurveto
- 15 -21 62 28 86 41 57 44 25 0 42 -39 0 -66 -10 0 -17 -4 0 -6 -12 0 -19 -3 0 -5 -6 0 -11 -5 0 -9 8 blend
+ 15 -21 62 28 86 41 57 44 25 0.06235 42 -39 -0.09726 -66 -10 -0.02493 -17 -4 0 -6 -12 -0.02992 -19 -3 0 -5 -6 -0.01497 -11 -5 -0.01247 -9 8 blend
rlinecurve
hintmask 101010000000000010001100
- -541 323 10 0 17 44 5 84 2 blend
+ -541 323 10 0.02493 17 44 5.10973 84 2 blend
rmoveto
- -30 517 -150 -517 -30 547 210 -46 -2 -81 -74 0 -123 54 -13 80 74 0 123 -46 -2 -81 -19 0 -32 38 17 82 7 blend
+ -30 517 -150 -517 -30 547 210 -46 -2.11472 -81 -74 -0.18454 -123 54 -12.86534 80 74 0.18454 123 -46 -2.11472 -81 -19 -0.04738 -32 38 17.09476 82 7 blend
vlineto
- -232 -242 -10 0 -16 -28 29 -27 2 blend
+ -232 -242 -10 -0.02493 -16 -28 28.93018 -27 2 blend
rmoveto
- -344 58 -32 71 1 blend
+ -344 58 -31.85536 71 1 blend
vlineto
- -47 15 -9 54 -33 -2 -58 3 0 4 -15 0 -25 22 0 37 4 blend
+ -47 15 -9 54 -33 -2.08229 -58 3 0 4 -15 -0.0374 -25 22 0.05486 37 4 blend
vhcurveto
hintmask 100000000010001000001010
- 12 100 3 0 5 -47 0 -78 2 blend
+ 12 100 3 0 5 -47 -0.1172 -78 2 blend
0 12 4 0 6 1 blend
hhcurveto
- 48 10 25 102 3 12 0 20 11 0 19 4 1 9 11 -1 16 5 0 8 5 blend
+ 48 10 25 102 3 12 0.02992 20 11 0.02744 19 4 1 9 11 -0.97256 16 5 0.01247 8 5 blend
hvcurveto
- -9 3 -11 4 -8 6 -14 0 -23 3 -1 5 -23 1 -37 8 1 15 -8 -1 -15 8 0 12 6 blend
+ -9 3 -11 4 -8 6 -14 -0.03491 -23 3 -1 5 -23 0.94264 -37 8 1.01994 15 -8 -1.01994 -15 8 0.01994 12 6 blend
rrcurveto
- -97 11 1 20 1 blend
- -3 -4 -14 -29 -21 -84 0 0 1 1 -1 1 10 0 16 10 1 17 43 -1 71 5 blend
- 0 -16 7 0 12 1 blend
+ -97 11 1.02744 20 1 blend
+ -3 -4 -14 -29 -21 -84 0 0 1 1 -1 1 10 0.02493 16 10 1.02493 17 43 -0.89276 71 5 blend
+ 0 -16 7 0.01746 12 1 blend
hhcurveto
- -33 -6 5 22 13 0 22 3 0 5 -1 0 -2 4 0 7 4 blend
+ -33 -6 5 22 13 0.03242 22 3 0 5 -1 0 -2 4 0 7 4 blend
hvcurveto
- 344 -59 34 -71 1 blend
+ 344 -59 33.85287 -71 1 blend
vlineto
- -346 -371 -24 0 -41 65 -34 78 2 blend
+ -346 -371 -24 -0.05984 -41 65 -33.8379 78 2 blend
rmoveto
- 10 -31 77 16 100 22 99 21 3 0 5 -54 0 -90 -2 0 -3 -3 0 -5 -9 0 -15 -6 0 -10 -10 0 -17 -5 0 -8 8 blend
+ 10 -31 77 16 100 22 99 21 3 0 5 -54 -0.13466 -90 -2 0 -3 -3 0 -5 -9 -0.02245 -15 -6 -0.01497 -10 -10 -0.02493 -17 -5 -0.01247 -8 8 blend
rlinecurve
- -2 29 -108 -22 -104 -22 -72 -13 -3 0 -5 52 0 86 9 0 16 6 0 10 8 0 13 6 0 11 4 0 6 4 0 6 8 blend
+ -2 29 -108 -22 -104 -22 -72 -13 -3 0 -5 52 0.12967 86 9 0.02245 16 6 0.01497 10 8 0.01994 13 6 0.01497 11 4 0 6 4 0 6 8 blend
rlinecurve
- -16 767 -44 0 -72 -13 0 -21 2 blend
+ -16 767 -44 -0.10973 -72 -13 -0.03242 -21 2 blend
rmoveto
- -316 -6 0 -11 1 blend
+ -316 -6 -0.01497 -11 1 blend
vlineto
- -142 -7 -194 -74 -141 2 0 2 -2 0 -2 2 0 4 6 0 9 4 blend
+ -142 -7 -194 -74 -141 2 0 2 -2 0 -2 2 0 4 6 0.01497 9 4 blend
vhcurveto
- 8 -3 13 -7 5 -6 13 0 21 -7 0 -11 25 0 43 -20 0 -34 11 0 17 -10 0 -17 6 blend
+ 8 -3 13 -7 5 -6 13 0.03242 21 -7 -0.01746 -11 25 0.06235 43 -20 -0.04988 -34 11 0.02744 17 -10 -0.02493 -17 6 blend
rrcurveto
- 75 143 10 205 145 4 0 7 3 0 5 2 0 4 21 0 35 9 0 15 5 blend
+ 75 143 10 205 145 4 0 7 3 0 5 2 0 4 21 0.05237 35 9 0.02245 15 5 blend
vvcurveto
- 316 6 0 11 1 blend
+ 316 6 0.01497 11 1 blend
vlineto
</CharString>
<CharString name="cid18480" fdSelectIndex="1">
3 vsindex
- -71 30 427 30 153 30 33 111 -30 30 -30 126 -6 0 -13 45 0 102 -58 0 -132 38 0 87 -48 0 -111 38 0 87 -4 -2 -13 21 2 53 -43 0 -99 43 0 99 -43 0 -99 24 0 55 12 blend
+ -71 30 427 30 153 30 33 111 -30 30 -30 126 -6 -0.0107 -13 45 0.08022 102 -58 -0.1034 -132 38 0.06773 87 -48 -0.08556 -111 38 0.06773 87 -4 -2 -13 21 2.03743 53 -43 -0.07664 -99 43 0.07664 99 -43 -0.07664 -99 24 0.04279 55 12 blend
hstemhm
- 159 30 -19 19 126 30 -6 30 281 30 160 30 18 31 -7 0 -16 50 0 114 -18 0 -42 18 0 42 -71 0 -161 50 0 114 -26 0 -61 48 0 111 -66 0 -150 51 0 115 -68 0 -154 50 0 114 -36 -1 -84 44 1 101 14 blend
+ 159 30 -19 19 126 30 -6 30 281 30 160 30 18 31 -7 -0.01248 -16 50 0.08913 114 -18 -0.03209 -42 18 0.03209 42 -71 -0.12656 -161 50 0.08913 114 -26 -0.04634 -61 48 0.08556 111 -66 -0.11765 -150 51 0.09091 115 -68 -0.12122 -154 50 0.08913 114 -36 -1.06418 -84 44 1.07843 101 14 blend
vstemhm
hintmask 1110100101110000
- 58 743 -1 0 -2 26 0 60 2 blend
+ 58 743 -1 0 -2 26 0.04634 60 2 blend
rmoveto
- -30 887 30 -43 0 -99 2 0 5 43 0 99 3 blend
+ -30 887 30 -43 -0.07664 -99 2 0 5 43 0.07664 99 3 blend
vlineto
hintmask 0000010010000000
- -630 96 -29 0 -66 -19 0 -44 2 blend
+ -630 96 -29 -0.0517 -66 -19 -0.03387 -44 2 blend
rmoveto
hintmask 0001000010000000
- -207 30 -2 -2 -9 50 0 114 2 blend
+ -207 30 -2 -2 -9 50 0.08913 114 2 blend
vlineto
hintmask 0000010010100000
207 2 2 9 1 blend
vlineto
- 305 -44 0 -100 1 blend
+ 305 -44 -0.07843 -100 1 blend
hmoveto
hintmask 0001000000100000
- -207 30 -2 -2 -9 51 0 115 2 blend
+ -207 30 -2 -2 -9 51 0.09091 115 2 blend
vlineto
hintmask 0010011000100000
207 2 2 9 1 blend
vlineto
- -521 -240 -36 0 -82 2 0 4 2 blend
+ -521 -240 -36 -0.06418 -82 2 0 4 2 blend
rmoveto
-206 -5 0 -10 1 blend
vlineto
- -137 -15 -184 -109 -136 5 0 11 3 0 6 5 0 10 -1 0 -1 8 0 19 5 blend
+ -137 -15 -184 -109 -136 5 0 11 3 0 6 5 0 10 -1 0 -1 8 0.01427 19 5 blend
vhcurveto
- 7 -3 12 -9 5 -6 12 0 27 -6 0 -13 22 0 51 -15 0 -35 10 0 21 -8 0 -19 6 blend
+ 7 -3 12 -9 5 -6 12 0.0214 27 -6 -0.0107 -13 22 0.03922 51 -15 -0.02673 -35 10 0.01782 21 -8 -0.01427 -19 6 blend
rrcurveto
hintmask 1110000101010000
- 112 139 18 194 141 3 0 7 -4 0 -8 1 0 3 11 0 24 4 0 10 5 blend
+ 112 139 18 194 141 3 0 7 -4 0 -8 1 0 3 11 0.0196 24 4 0 10 5 blend
vvcurveto
207 5 0 11 1 blend
vlineto
- -19 -18 0 -42 1 blend
+ -19 -18 -0.03209 -42 1 blend
hmoveto
- -30 670 -153 -670 -30 700 213 -38 0 -87 -64 0 -144 48 0 111 64 0 144 -38 0 -87 -14 0 -30 28 0 63 7 blend
+ -30 670 -153 -670 -30 700 213 -38 -0.06773 -87 -64 -0.11407 -144 48 0.08556 111 64 0.11407 144 -38 -0.06773 -87 -14 -0.02495 -30 28 0.04991 63 7 blend
vlineto
- -531 -249 -15 0 -36 -23 0 -51 2 blend
+ -531 -249 -15 -0.02673 -36 -23 -0.041 -51 2 blend
rmoveto
- -343 50 0 112 1 blend
+ -343 50 0.08913 112 1 blend
vlineto
- -66 31 -12 105 -29 0 -66 6 0 14 -13 0 -28 29 0 66 4 blend
+ -66 31 -12 105 -29 -0.0517 -66 6 0.0107 14 -13 -0.02318 -28 29 0.0517 66 4 blend
vhcurveto
- 23 278 5 0 12 -59 0 -134 2 blend
- 0 24 6 0 14 1 blend
+ 23 278 5 0 12 -59 -0.10516 -134 2 blend
+ 0 24 6 0.0107 14 1 blend
hhcurveto
hintmask 1000000001001000
- 96 15 31 123 8 20 0 44 11 0 26 4 0 8 14 0 32 5 0 11 5 blend
+ 96 15 31 123 8 20 0.03564 44 11 0.0196 26 4 0 8 14 0.02495 32 5 0 11 5 blend
hvcurveto
- -9 3 -13 4 -9 7 -13 0 -30 2 0 5 -21 0 -48 8 0 17 -10 -1 -23 6 0 15 6 blend
+ -9 3 -13 4 -9 7 -13 -0.02318 -30 2 0 5 -21 -0.03743 -48 8 0.01427 17 -10 -1.01782 -23 6 0.0107 15 6 blend
rrcurveto
- -117 -6 -11 -21 -69 -56 -236 8 0 18 -1 1 -1 1 -1 1 3 0 7 3 1 9 7 0 15 49 0 112 7 blend
+ -117 -6 -11 -21 -69 -56 -236 8 0.01427 18 -1 1 -1 1 -1 1 3 0 7 3 1 9 7 0.01248 15 49 0.08734 112 7 blend
0 -41 4 0 8 1 blend
hhcurveto
-84 -16 11 37 4 0 10 2 0 5 -3 0 -7 1 0 2 4 blend
hvcurveto
- 343 -51 0 -115 1 blend
+ 343 -51 -0.09091 -115 1 blend
vlineto
- 444 -47 -59 0 -135 26 0 59 2 blend
+ 444 -47 -59 -0.10516 -135 26 0.04634 59 2 blend
rmoveto
- -101 -52 -195 -56 -169 -40 4 -7 5 -10 3 -7 172 40 193 54 120 56 4 0 8 3 0 7 18 0 43 9 0 19 12 0 26 8 0 19 5 0 12 -10 0 -22 7 0 15 -18 0 -41 1 0 3 -11 0 -25 -8 0 -19 -9 0 -21 -8 0 -18 -8 0 -19 5 0 11 0 0 1 18 blend
+ -101 -52 -195 -56 -169 -40 4 -7 5 -10 3 -7 172 40 193 54 120 56 4 0 8 3 0 7 18 0.03209 43 9 0.01604 19 12 0.0214 26 8 0.01427 19 5 0 12 -10 -0.01782 -22 7 0.01248 15 -18 -0.03209 -41 1 0 3 -11 -0.0196 -25 -8 -0.01427 -19 -9 -0.01604 -21 -8 -0.01427 -18 -8 -0.01427 -19 5 0 11 0 0 1 18 blend
rrcurveto
</CharString>
<CharString name="cid22370" fdSelectIndex="1">
2 vsindex
- 64 30 77 30 76 30 74 30 72 30 109 30 25 84 -30 30 -30 108 -2 0 -2 42 0 47 -48 0 -54 38 0 43 -48 0 -54 38 0 43 -46 0 -52 42 0 47 -43 0 -48 56 1 63 -72 -1 -81 57 1 64 -8 -32 -41 30 32 65 -65 -1 -73 65 1 73 -65 -1 -73 43 0 49 18 blend
+ 64 30 77 30 76 30 74 30 72 30 109 30 25 84 -30 30 -30 108 -2 -0.01802 -2 42 0.37837 47 -48 -0.43243 -54 38 0.34235 43 -48 -0.43243 -54 38 0.34235 43 -46 -0.41441 -52 42 0.37837 47 -43 -0.38739 -48 56 0.5045 63 -72 -0.64865 -81 57 0.51352 64 -8 -32.07207 -41 30 32.27026 65 -65 -0.58559 -73 65 0.58559 73 -65 -0.58559 -73 43 0.38739 49 18 blend
hstemhm
- 135 30 21 30 102 30 14 30 205 30 17 30 113 30 19 30 -19 0 -21 87 2 98 -86 -2 -97 99 1 111 -125 -1 -141 98 1 111 -79 -1 -89 75 1 84 -99 -1 -111 75 1 84 -77 -1 -86 100 1 112 -127 -1 -143 105 1 118 -102 -1 -114 94 1 105 16 blend
+ 135 30 21 30 102 30 14 30 205 30 17 30 113 30 19 30 -19 -0.17117 -21 87 1.78378 98 -86 -1.77478 -97 99 0.89189 111 -125 -1.12613 -141 98 0.88289 111 -79 -0.71172 -89 75 0.67567 84 -99 -0.89189 -111 75 0.67567 84 -77 -0.6937 -86 100 0.9009 112 -127 -1.14415 -143 105 0.94595 118 -102 -0.91891 -114 94 0.84685 105 16 blend
vstemhm
hintmask 111111010011001100000000
- 53 761 -3 0 -3 36 0 40 2 blend
+ 53 761 -3 -0.02702 -3 36 0.32433 40 2 blend
rmoveto
- -30 896 30 -65 -1 -73 5 0 5 65 1 73 3 blend
+ -30 896 30 -65 -0.58559 -73 5 0.04504 5 65 0.58559 73 3 blend
vlineto
hintmask 000000001001000000000000
- -631 78 -46 0 -52 -22 0 -24 2 blend
+ -631 78 -46 -0.41441 -52 -22 -0.1982 -24 2 blend
rmoveto
hintmask 000000100001000000000000
- -162 30 -8 -32 -41 98 1 111 2 blend
+ -162 30 -8 -32.07207 -41 98 0.88289 111 2 blend
vlineto
hintmask 000000001001001000000000
- 162 8 32 41 1 blend
+ 162 8 32.07207 41 1 blend
vlineto
- 296 -105 -1 -118 1 blend
+ 296 -105 -0.94595 -118 1 blend
hmoveto
hintmask 000000100000001000000000
- -162 30 -8 -32 -41 100 1 112 2 blend
+ -162 30 -8 -32.07207 -41 100 0.9009 112 2 blend
vlineto
hintmask 000000001000001000000000
- 162 8 32 41 1 blend
+ 162 8 32.07207 41 1 blend
vlineto
hintmask 000011000100110010000000
- -47 -217 -23 0 -26 -57 -1 -64 2 blend
+ -47 -217 -23 -0.20721 -26 -57 -0.51352 -64 2 blend
rmoveto
- 209 -109 -209 -101 -1 -113 72 1 81 101 1 113 3 blend
+ 209 -109 -209 -101 -0.90991 -113 72 0.64865 81 101 0.90991 113 3 blend
hlineto
- -235 109 24 0 27 -72 -1 -81 2 blend
+ -235 109 24 0.21622 27 -72 -0.64865 -81 2 blend
rmoveto
- 205 -109 -205 -99 -1 -111 72 1 81 99 1 111 3 blend
+ 205 -109 -205 -99 -0.89189 -111 72 0.64865 81 99 0.89189 111 3 blend
hlineto
- -227 109 18 1 21 -72 -1 -81 2 blend
+ -227 109 18 1.16216 21 -72 -0.64865 -81 2 blend
rmoveto
- 197 -109 -197 -93 -2 -105 72 1 81 93 2 105 3 blend
+ 197 -109 -197 -93 -1.83784 -105 72 0.64865 81 93 1.83784 105 3 blend
hlineto
- -30 139 -87 -2 -98 -15 0 -17 2 blend
+ -30 139 -87 -1.78378 -98 -15 -0.13513 -17 2 blend
rmoveto
- -169 731 169 -41 0 -46 38 0 42 41 0 46 3 blend
+ -169 731 169 -41 -0.36937 -46 38 0.34235 42 41 0.36937 46 3 blend
vlineto
hintmask 111100000010000100000000
- -650 -375 62 1 70 -32 0 -36 2 blend
+ -650 -375 62 0.55856 70 -32 -0.28828 -36 2 blend
rmoveto
- 571 -76 -571 -159 -1 -179 48 0 54 159 1 179 3 blend
+ 571 -76 -571 -159 -1.43243 -179 48 0.43243 54 159 1.43243 179 3 blend
hlineto
- -30 -38 0 -43 1 blend
+ -30 -38 -0.34235 -43 1 blend
vmoveto
- 571 -77 -571 -159 -1 -179 48 0 54 159 1 179 3 blend
+ 571 -77 -571 -159 -1.43243 -179 48 0.43243 54 159 1.43243 179 3 blend
hlineto
- 287 -66 -1 -74 1 blend
+ 287 -66 -0.59459 -74 1 blend
vmoveto
- 571 -74 -571 -159 -1 -179 46 0 52 159 1 179 3 blend
+ 571 -74 -571 -159 -1.43243 -179 46 0.41441 52 159 1.43243 179 3 blend
hlineto
- -30 104 -99 -1 -111 -4 0 -5 2 blend
+ -30 104 -99 -0.89189 -111 -4 -0.03604 -5 2 blend
rmoveto
- -347 631 347 -18 0 -20 45 0 50 18 0 20 3 blend
+ -347 631 347 -18 -0.16216 -20 45 0.40541 50 18 0.16216 20 3 blend
vlineto
- -216 -389 -86 -1 -96 -31 0 -35 2 blend
+ -216 -389 -86 -0.77478 -96 -31 -0.27928 -35 2 blend
rmoveto
- 127 -34 121 -39 72 -31 -17 0 -19 2 0 2 -13 0 -15 -2 0 -2 -13 0 -15 3 0 3 6 blend
+ 127 -34 121 -39 72 -31 -17 -0.15315 -19 2 0.01802 2 -13 -0.11711 -15 -2 -0.01802 -2 -13 -0.11711 -15 3 0.02702 3 6 blend
rrcurveto
- 31 22 -78 32 -126 39 -121 136 1 153 39 0 44 1 0 1 -3 0 -3 -8 0 -9 4 0 5 9 0 10 7 blend
+ 31 22 -78 32 -126 39 -121 136 1.22522 153 39 0.35135 44 1 0 1 -3 -0.02702 -3 -8 -0.07207 -9 4 0.03604 5 9 0.08109 10 7 blend
31 rlinecurve
- -258 -1 -67 -1 -75 0 0 -1 2 blend
+ -258 -1 -67 -0.6036 -75 0 0 -1 2 blend
rmoveto
- -81 -39 -128 -36 -107 -23 8 -6 12 -12 5 -6 103 25 130 41 86 43 9 0 10 6 0 7 3 0 4 7 0 8 -4 0 -5 7 0 8 19 0 22 -14 0 -16 32 0 36 -32 0 -36 17 0 19 -19 0 -21 3 0 3 -1 0 -1 5 0 6 2 0 2 1 0 1 4 0 5 18 blend
+ -81 -39 -128 -36 -107 -23 8 -6 12 -12 5 -6 103 25 130 41 86 43 9 0.08109 10 6 0.05405 7 3 0.02702 4 7 0.06306 8 -4 -0.03604 -5 7 0.06306 8 19 0.17117 22 -14 -0.12613 -16 32 0.28828 36 -32 -0.28828 -36 17 0.15315 19 -19 -0.17117 -21 3 0.02702 3 -1 0 -1 5 0.04504 6 2 0.01802 2 1 0 1 4 0.03604 5 18 blend
rrcurveto
</CharString>
</CharStrings>
diff --git a/Tests/varLib/data/test_results/TestVVAR.ttx b/Tests/varLib/data/test_results/TestVVAR.ttx
index 53c038c1..c16266d3 100644
--- a/Tests/varLib/data/test_results/TestVVAR.ttx
+++ b/Tests/varLib/data/test_results/TestVVAR.ttx
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
-<ttFont sfntVersion="OTTO" ttLibVersion="3.39">
+<ttFont sfntVersion="OTTO" ttLibVersion="4.42">
<VVAR>
<Version value="0x00010000"/>
@@ -7,14 +7,7 @@
<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>
+ <!-- RegionCount=0 -->
</VarRegionList>
<!-- VarDataCount=1 -->
<VarData index="0">
diff --git a/Tests/varLib/featureVars_test.py b/Tests/varLib/featureVars_test.py
index 89675af2..7a3a6650 100644
--- a/Tests/varLib/featureVars_test.py
+++ b/Tests/varLib/featureVars_test.py
@@ -1,36 +1,45 @@
-from fontTools.varLib.featureVars import (
- overlayFeatureVariations)
+from fontTools.varLib.featureVars import overlayFeatureVariations, overlayBox
-def test_linear(n = 10):
+def _test_linear(n):
conds = []
for i in range(n):
end = i / n
- start = end - 1.
- region = [{'X': (start, end)}]
- subst = {'g%.2g'%start: 'g%.2g'%end}
+ start = end - 1.0
+ region = [{"X": (start, end)}]
+ subst = {"g%.2g" % start: "g%.2g" % end}
conds.append((region, subst))
overlaps = overlayFeatureVariations(conds)
assert len(overlaps) == 2 * n - 1, overlaps
return conds, overlaps
-def test_quadratic(n = 10):
+
+def test_linear():
+ _test_linear(10)
+
+
+def _test_quadratic(n):
conds = []
for i in range(1, n + 1):
- region = [{'X': (0, i / n),
- 'Y': (0, (n + 1 - i) / n)}]
+ region = [{"X": (0, i / n), "Y": (0, (n + 1 - i) / n)}]
subst = {str(i): str(n + 1 - i)}
conds.append((region, subst))
overlaps = overlayFeatureVariations(conds)
assert len(overlaps) == n * (n + 1) // 2, overlaps
return conds, overlaps
+
+def test_quadratic():
+ _test_quadratic(10)
+
+
def _merge_substitutions(substitutions):
merged = {}
for subst in substitutions:
merged.update(subst)
return merged
+
def _match_condition(location, overlaps):
for box, substitutions in overlaps:
for tag, coord in location.items():
@@ -39,59 +48,69 @@ def _match_condition(location, overlaps):
return _merge_substitutions(substitutions)
return {} # no match
+
def test_overlaps_1():
# https://github.com/fonttools/fonttools/issues/1400
conds = [
- ([{'abcd': (4, 9)}], {0: 0}),
- ([{'abcd': (5, 10)}], {1: 1}),
- ([{'abcd': (0, 8)}], {2: 2}),
- ([{'abcd': (3, 7)}], {3: 3}),
+ ([{"abcd": (4, 9)}], {0: 0}),
+ ([{"abcd": (5, 10)}], {1: 1}),
+ ([{"abcd": (0, 8)}], {2: 2}),
+ ([{"abcd": (3, 7)}], {3: 3}),
]
overlaps = overlayFeatureVariations(conds)
- subst = _match_condition({'abcd': 0}, overlaps)
+ subst = _match_condition({"abcd": 0}, overlaps)
assert subst == {2: 2}
- subst = _match_condition({'abcd': 1}, overlaps)
+ subst = _match_condition({"abcd": 1}, overlaps)
assert subst == {2: 2}
- subst = _match_condition({'abcd': 3}, overlaps)
+ subst = _match_condition({"abcd": 3}, overlaps)
assert subst == {2: 2, 3: 3}
- subst = _match_condition({'abcd': 4}, overlaps)
+ subst = _match_condition({"abcd": 4}, overlaps)
assert subst == {0: 0, 2: 2, 3: 3}
- subst = _match_condition({'abcd': 5}, overlaps)
+ subst = _match_condition({"abcd": 5}, overlaps)
assert subst == {0: 0, 1: 1, 2: 2, 3: 3}
- subst = _match_condition({'abcd': 7}, overlaps)
+ subst = _match_condition({"abcd": 7}, overlaps)
assert subst == {0: 0, 1: 1, 2: 2, 3: 3}
- subst = _match_condition({'abcd': 8}, overlaps)
+ subst = _match_condition({"abcd": 8}, overlaps)
assert subst == {0: 0, 1: 1, 2: 2}
- subst = _match_condition({'abcd': 9}, overlaps)
+ subst = _match_condition({"abcd": 9}, overlaps)
assert subst == {0: 0, 1: 1}
- subst = _match_condition({'abcd': 10}, overlaps)
+ subst = _match_condition({"abcd": 10}, overlaps)
assert subst == {1: 1}
+
def test_overlaps_2():
# https://github.com/fonttools/fonttools/issues/1400
conds = [
- ([{'abcd': (1, 9)}], {0: 0}),
- ([{'abcd': (8, 10)}], {1: 1}),
- ([{'abcd': (3, 4)}], {2: 2}),
- ([{'abcd': (1, 10)}], {3: 3}),
+ ([{"abcd": (1, 9)}], {0: 0}),
+ ([{"abcd": (8, 10)}], {1: 1}),
+ ([{"abcd": (3, 4)}], {2: 2}),
+ ([{"abcd": (1, 10)}], {3: 3}),
]
overlaps = overlayFeatureVariations(conds)
- subst = _match_condition({'abcd': 0}, overlaps)
+ subst = _match_condition({"abcd": 0}, overlaps)
assert subst == {}
- subst = _match_condition({'abcd': 1}, overlaps)
+ subst = _match_condition({"abcd": 1}, overlaps)
assert subst == {0: 0, 3: 3}
- subst = _match_condition({'abcd': 2}, overlaps)
+ subst = _match_condition({"abcd": 2}, overlaps)
assert subst == {0: 0, 3: 3}
- subst = _match_condition({'abcd': 3}, overlaps)
+ subst = _match_condition({"abcd": 3}, overlaps)
assert subst == {0: 0, 2: 2, 3: 3}
- subst = _match_condition({'abcd': 5}, overlaps)
+ subst = _match_condition({"abcd": 5}, overlaps)
assert subst == {0: 0, 3: 3}
- subst = _match_condition({'abcd': 10}, overlaps)
+ subst = _match_condition({"abcd": 10}, overlaps)
assert subst == {1: 1, 3: 3}
-def run(test, n, quiet):
+def test_overlayBox():
+ # https://github.com/fonttools/fonttools/issues/3003
+ top = {"opsz": (0.75, 1.0), "wght": (0.5, 1.0)}
+ bot = {"wght": (0.25, 1.0)}
+ intersection, remainder = overlayBox(top, bot)
+ assert intersection == {"opsz": (0.75, 1.0), "wght": (0.5, 1.0)}
+ assert remainder == {"wght": (0.25, 1.0)}
+
+def run(test, n, quiet):
print()
print("%s:" % test.__name__)
input, output = test(n)
@@ -106,16 +125,18 @@ def run(test, n, quiet):
pprint(output)
print()
+
if __name__ == "__main__":
import sys
from pprint import pprint
+
quiet = False
n = 3
- if len(sys.argv) > 1 and sys.argv[1] == '-q':
+ if len(sys.argv) > 1 and sys.argv[1] == "-q":
quiet = True
del sys.argv[1]
if len(sys.argv) > 1:
n = int(sys.argv[1])
- run(test_linear, n=n, quiet=quiet)
- run(test_quadratic, n=n, quiet=quiet)
+ run(_test_linear, n=n, quiet=quiet)
+ run(_test_quadratic, n=n, quiet=quiet)
diff --git a/Tests/varLib/instancer/data/PartialInstancerTest-VF.ttx b/Tests/varLib/instancer/data/PartialInstancerTest-VF.ttx
index 268b5068..2f1754b0 100644
--- a/Tests/varLib/instancer/data/PartialInstancerTest-VF.ttx
+++ b/Tests/varLib/instancer/data/PartialInstancerTest-VF.ttx
@@ -728,7 +728,7 @@
<AxisOrdering value="2"/>
</Axis>
</DesignAxisRecord>
- <!-- AxisValueCount=5 -->
+ <!-- AxisValueCount=7 -->
<AxisValueArray>
<AxisValue index="0" Format="1">
<AxisIndex value="0"/>
@@ -743,7 +743,13 @@
<Value value="400.0"/>
<LinkedValue value="700.0"/>
</AxisValue>
- <AxisValue index="2" Format="2">
+ <AxisValue index="2" Format="1">
+ <AxisIndex value="0"/>
+ <Flags value="0"/>
+ <ValueNameID value="262"/> <!-- Medium -->
+ <Value value="500.0"/>
+ </AxisValue>
+ <AxisValue index="3" Format="2">
<AxisIndex value="0"/>
<Flags value="0"/>
<ValueNameID value="266"/> <!-- Black -->
@@ -751,7 +757,7 @@
<RangeMinValue value="801.0"/>
<RangeMaxValue value="900.0"/>
</AxisValue>
- <AxisValue index="3" Format="4">
+ <AxisValue index="4" Format="4">
<!-- AxisCount=1 -->
<Flags value="0"/>
<ValueNameID value="279"/> <!-- Condensed -->
@@ -760,14 +766,14 @@
<Value value="79.0"/>
</AxisValueRecord>
</AxisValue>
- <AxisValue index="4" Format="3">
+ <AxisValue index="5" Format="3">
<AxisIndex value="2"/>
<Flags value="2"/>
<ValueNameID value="295"/> <!-- Upright -->
<Value value="0.0"/>
<LinkedValue value="1.0"/>
</AxisValue>
- <AxisValue index="3" Format="4">
+ <AxisValue index="6" Format="4">
<!-- AxisCount=1 -->
<Flags value="2"/>
<ValueNameID value="297"/> <!-- Normal -->
@@ -781,6 +787,7 @@
</STAT>
<avar>
+ <version major="1" minor="0"/>
<segment axis="wght">
<mapping from="-1.0" to="-1.0"/>
<mapping from="-0.6667" to="-0.7969"/>
diff --git a/Tests/varLib/instancer/data/PartialInstancerTest2-VF.ttx b/Tests/varLib/instancer/data/PartialInstancerTest2-VF.ttx
index cd7ffa05..3acbf56d 100644
--- a/Tests/varLib/instancer/data/PartialInstancerTest2-VF.ttx
+++ b/Tests/varLib/instancer/data/PartialInstancerTest2-VF.ttx
@@ -1139,6 +1139,7 @@
</STAT>
<avar>
+ <version major="1" minor="0"/>
<segment axis="wght">
<mapping from="-1.0" to="-1.0"/>
<mapping from="-0.6667" to="-0.7969"/>
diff --git a/Tests/varLib/instancer/data/STATInstancerTest.ttx b/Tests/varLib/instancer/data/STATInstancerTest.ttx
index eee24d82..e4506cec 100644
--- a/Tests/varLib/instancer/data/STATInstancerTest.ttx
+++ b/Tests/varLib/instancer/data/STATInstancerTest.ttx
@@ -1336,6 +1336,7 @@
</STAT>
<avar>
+ <version major="1" minor="0"/>
<segment axis="wght">
<mapping from="-1.0" to="-1.0"/>
<mapping from="-0.6667" to="-0.74194"/>
diff --git a/Tests/varLib/instancer/data/SinglePos.ttx b/Tests/varLib/instancer/data/SinglePos.ttx
index 64ffd9f5..dda441e3 100644
--- a/Tests/varLib/instancer/data/SinglePos.ttx
+++ b/Tests/varLib/instancer/data/SinglePos.ttx
@@ -213,6 +213,7 @@
</GPOS>
<avar>
+ <version major="1" minor="0"/>
<segment axis="opsz">
<mapping from="-1.0" to="-1.0"/>
<mapping from="-0.01" to="-0.9"/>
diff --git a/Tests/varLib/instancer/data/test_results/PartialInstancerTest2-VF-instance-100,100.ttx b/Tests/varLib/instancer/data/test_results/PartialInstancerTest2-VF-instance-100,100.ttx
index 776a92f1..c89949c2 100644
--- a/Tests/varLib/instancer/data/test_results/PartialInstancerTest2-VF-instance-100,100.ttx
+++ b/Tests/varLib/instancer/data/test_results/PartialInstancerTest2-VF-instance-100,100.ttx
@@ -74,7 +74,7 @@
<!-- The fields 'usFirstCharIndex' and 'usLastCharIndex'
will be recalculated by the compiler -->
<version value="4"/>
- <xAvgCharWidth value="577"/>
+ <xAvgCharWidth value="502"/>
<usWeightClass value="100"/>
<usWidthClass value="5"/>
<fsType value="00000000 00000000"/>
diff --git a/Tests/varLib/instancer/data/test_results/PartialInstancerTest2-VF-instance-100,62.5.ttx b/Tests/varLib/instancer/data/test_results/PartialInstancerTest2-VF-instance-100,62.5.ttx
index 61bc41cc..a78019f8 100644
--- a/Tests/varLib/instancer/data/test_results/PartialInstancerTest2-VF-instance-100,62.5.ttx
+++ b/Tests/varLib/instancer/data/test_results/PartialInstancerTest2-VF-instance-100,62.5.ttx
@@ -74,7 +74,7 @@
<!-- The fields 'usFirstCharIndex' and 'usLastCharIndex'
will be recalculated by the compiler -->
<version value="4"/>
- <xAvgCharWidth value="577"/>
+ <xAvgCharWidth value="383"/>
<usWeightClass value="100"/>
<usWidthClass value="2"/>
<fsType value="00000000 00000000"/>
diff --git a/Tests/varLib/instancer/data/test_results/PartialInstancerTest2-VF-instance-400,100.ttx b/Tests/varLib/instancer/data/test_results/PartialInstancerTest2-VF-instance-400,100.ttx
index c2d20571..635acd71 100644
--- a/Tests/varLib/instancer/data/test_results/PartialInstancerTest2-VF-instance-400,100.ttx
+++ b/Tests/varLib/instancer/data/test_results/PartialInstancerTest2-VF-instance-400,100.ttx
@@ -74,7 +74,7 @@
<!-- The fields 'usFirstCharIndex' and 'usLastCharIndex'
will be recalculated by the compiler -->
<version value="4"/>
- <xAvgCharWidth value="577"/>
+ <xAvgCharWidth value="543"/>
<usWeightClass value="400"/>
<usWidthClass value="5"/>
<fsType value="00000000 00000000"/>
diff --git a/Tests/varLib/instancer/data/test_results/PartialInstancerTest2-VF-instance-400,62.5.ttx b/Tests/varLib/instancer/data/test_results/PartialInstancerTest2-VF-instance-400,62.5.ttx
index 63eeb0e7..fcafe91c 100644
--- a/Tests/varLib/instancer/data/test_results/PartialInstancerTest2-VF-instance-400,62.5.ttx
+++ b/Tests/varLib/instancer/data/test_results/PartialInstancerTest2-VF-instance-400,62.5.ttx
@@ -74,7 +74,7 @@
<!-- The fields 'usFirstCharIndex' and 'usLastCharIndex'
will be recalculated by the compiler -->
<version value="4"/>
- <xAvgCharWidth value="577"/>
+ <xAvgCharWidth value="428"/>
<usWeightClass value="400"/>
<usWidthClass value="2"/>
<fsType value="00000000 00000000"/>
diff --git a/Tests/varLib/instancer/data/test_results/PartialInstancerTest2-VF-instance-900,100.ttx b/Tests/varLib/instancer/data/test_results/PartialInstancerTest2-VF-instance-900,100.ttx
index 013ba1e7..61c3b2bb 100644
--- a/Tests/varLib/instancer/data/test_results/PartialInstancerTest2-VF-instance-900,100.ttx
+++ b/Tests/varLib/instancer/data/test_results/PartialInstancerTest2-VF-instance-900,100.ttx
@@ -74,7 +74,7 @@
<!-- The fields 'usFirstCharIndex' and 'usLastCharIndex'
will be recalculated by the compiler -->
<version value="4"/>
- <xAvgCharWidth value="577"/>
+ <xAvgCharWidth value="609"/>
<usWeightClass value="900"/>
<usWidthClass value="5"/>
<fsType value="00000000 00000000"/>
diff --git a/Tests/varLib/instancer/data/test_results/PartialInstancerTest2-VF-instance-900,62.5.ttx b/Tests/varLib/instancer/data/test_results/PartialInstancerTest2-VF-instance-900,62.5.ttx
index 45e34cbf..fa31886a 100644
--- a/Tests/varLib/instancer/data/test_results/PartialInstancerTest2-VF-instance-900,62.5.ttx
+++ b/Tests/varLib/instancer/data/test_results/PartialInstancerTest2-VF-instance-900,62.5.ttx
@@ -74,7 +74,7 @@
<!-- The fields 'usFirstCharIndex' and 'usLastCharIndex'
will be recalculated by the compiler -->
<version value="4"/>
- <xAvgCharWidth value="577"/>
+ <xAvgCharWidth value="506"/>
<usWeightClass value="900"/>
<usWidthClass value="2"/>
<fsType value="00000000 00000000"/>
diff --git a/Tests/varLib/instancer/instancer_test.py b/Tests/varLib/instancer/instancer_test.py
index db224cca..20d9194f 100644
--- a/Tests/varLib/instancer/instancer_test.py
+++ b/Tests/varLib/instancer/instancer_test.py
@@ -1,4 +1,5 @@
from fontTools.misc.fixedTools import floatToFixedToFloat
+from fontTools.misc.roundTools import noRound
from fontTools.misc.testTools import stripVariableItemsFromTTX
from fontTools.misc.textTools import Tag
from fontTools import ttLib
@@ -51,7 +52,15 @@ def fvarAxes():
def _get_coordinates(varfont, glyphname):
# converts GlyphCoordinates to a list of (x, y) tuples, so that pytest's
# assert will give us a nicer diff
- return list(varfont["glyf"].getCoordinatesAndControls(glyphname, varfont)[0])
+ return list(
+ varfont["glyf"]._getCoordinatesAndControls(
+ glyphname,
+ varfont["hmtx"].metrics,
+ varfont["vmtx"].metrics,
+ # the tests expect float coordinates
+ round=noRound,
+ )[0]
+ )
class InstantiateGvarTest(object):
@@ -112,6 +121,8 @@ class InstantiateGvarTest(object):
],
)
def test_pin_and_drop_axis(self, varfont, glyph_name, location, expected, optimize):
+ location = instancer.NormalizedAxisLimits(location)
+
instancer.instantiateGvar(varfont, location, optimize=optimize)
assert _get_coordinates(varfont, glyph_name) == expected[glyph_name]
@@ -124,9 +135,9 @@ class InstantiateGvarTest(object):
)
def test_full_instance(self, varfont, optimize):
- instancer.instantiateGvar(
- varfont, {"wght": 0.0, "wdth": -0.5}, optimize=optimize
- )
+ location = instancer.NormalizedAxisLimits(wght=0.0, wdth=-0.5)
+
+ instancer.instantiateGvar(varfont, location, optimize=optimize)
assert _get_coordinates(varfont, "hyphen") == [
(33.5, 229),
@@ -169,7 +180,7 @@ class InstantiateGvarTest(object):
assert hmtx["minus"] == (422, 40)
assert vmtx["minus"] == (536, 229)
- location = {"wght": -1.0, "wdth": -1.0}
+ location = instancer.NormalizedAxisLimits(wght=-1.0, wdth=-1.0)
instancer.instantiateGvar(varfont, location)
@@ -206,6 +217,8 @@ class InstantiateCvarTest(object):
],
)
def test_pin_and_drop_axis(self, varfont, location, expected):
+ location = instancer.NormalizedAxisLimits(location)
+
instancer.instantiateCvar(varfont, location)
assert list(varfont["cvt "].values) == expected
@@ -217,7 +230,9 @@ class InstantiateCvarTest(object):
)
def test_full_instance(self, varfont):
- instancer.instantiateCvar(varfont, {"wght": -0.5, "wdth": -0.5})
+ location = instancer.NormalizedAxisLimits(wght=-0.5, wdth=-0.5)
+
+ instancer.instantiateCvar(varfont, location)
assert list(varfont["cvt "].values) == [500, -400, 165, 225]
@@ -272,6 +287,8 @@ class InstantiateMVARTest(object):
assert mvar.VarStore.VarData[1].VarRegionCount == 1
assert all(len(item) == 1 for item in mvar.VarStore.VarData[1].Item)
+ location = instancer.NormalizedAxisLimits(location)
+
instancer.instantiateMVAR(varfont, location)
for mvar_tag, expected_value in expected.items():
@@ -312,6 +329,8 @@ class InstantiateMVARTest(object):
],
)
def test_full_instance(self, varfont, location, expected):
+ location = instancer.NormalizedAxisLimits(location)
+
instancer.instantiateMVAR(varfont, location)
for mvar_tag, expected_value in expected.items():
@@ -344,6 +363,8 @@ class InstantiateHVARTest(object):
],
)
def test_partial_instance(self, varfont, location, expectedRegions, expectedDeltas):
+ location = instancer.NormalizedAxisLimits(location)
+
instancer.instantiateHVAR(varfont, location)
assert "HVAR" in varfont
@@ -376,7 +397,9 @@ class InstantiateHVARTest(object):
assert varStore.VarData[varIdx >> 16].Item[varIdx & 0xFFFF] == expectedDeltas
def test_full_instance(self, varfont):
- instancer.instantiateHVAR(varfont, {"wght": 0, "wdth": 0})
+ location = instancer.NormalizedAxisLimits(wght=0, wdth=0)
+
+ instancer.instantiateHVAR(varfont, location)
assert "HVAR" not in varfont
@@ -390,7 +413,9 @@ class InstantiateHVARTest(object):
axis.axisTag = "TEST"
fvar.axes.append(axis)
- instancer.instantiateHVAR(varfont, {"wght": 0, "wdth": 0})
+ location = instancer.NormalizedAxisLimits(wght=0, wdth=0)
+
+ instancer.instantiateHVAR(varfont, location)
assert "HVAR" in varfont
@@ -452,6 +477,8 @@ class InstantiateItemVariationStoreTest(object):
def test_instantiate_default_deltas(
self, varStore, fvarAxes, location, expected_deltas, num_regions
):
+ location = instancer.NormalizedAxisLimits(location)
+
defaultDeltas = instancer.instantiateItemVariationStore(
varStore, fvarAxes, location
)
@@ -504,8 +531,9 @@ class TupleVarStoreAdapterTest(object):
adapter = instancer._TupleVarStoreAdapter(
regions, axisOrder, tupleVarData, itemCounts=[2, 2]
)
+ location = instancer.NormalizedAxisLimits(wght=0.5)
- defaultDeltaArray = adapter.instantiate({"wght": 0.5})
+ defaultDeltaArray = adapter.instantiate(location)
assert defaultDeltaArray == [[15, 45], [0, 0]]
assert adapter.regions == [{"wdth": (-1.0, -1.0, 0)}]
@@ -747,6 +775,8 @@ class InstantiateOTLTest(object):
vf = varfontGDEF
assert "GDEF" in vf
+ location = instancer.NormalizedAxisLimits(location)
+
instancer.instantiateOTL(vf, location)
assert "GDEF" in vf
@@ -778,6 +808,8 @@ class InstantiateOTLTest(object):
vf = varfontGDEF
assert "GDEF" in vf
+ location = instancer.NormalizedAxisLimits(location)
+
instancer.instantiateOTL(vf, location)
assert "GDEF" in vf
@@ -806,6 +838,8 @@ class InstantiateOTLTest(object):
assert "GDEF" in vf
assert "GPOS" in vf
+ location = instancer.NormalizedAxisLimits(location)
+
instancer.instantiateOTL(vf, location)
gdef = vf["GDEF"].table
@@ -839,6 +873,8 @@ class InstantiateOTLTest(object):
assert "GDEF" in vf
assert "GPOS" in vf
+ location = instancer.NormalizedAxisLimits(location)
+
instancer.instantiateOTL(vf, location)
assert "GDEF" not in vf
@@ -870,6 +906,8 @@ class InstantiateOTLTest(object):
assert "GDEF" in vf
assert "GPOS" in vf
+ location = instancer.NormalizedAxisLimits(location)
+
instancer.instantiateOTL(vf, location)
v1, v2 = expected
@@ -915,6 +953,8 @@ class InstantiateOTLTest(object):
assert "GDEF" in vf
assert "GPOS" in vf
+ location = instancer.NormalizedAxisLimits(location)
+
instancer.instantiateOTL(vf, location)
v1, v2 = expected
@@ -955,7 +995,7 @@ class InstantiateOTLTest(object):
# check that MutatorMerger for ValueRecord doesn't raise AttributeError
# when XAdvDevice is present but there's no corresponding XAdvance.
- instancer.instantiateOTL(vf, {"wght": 0.5})
+ instancer.instantiateOTL(vf, instancer.NormalizedAxisLimits(wght=0.5))
pairPos = vf["GPOS"].table.LookupList.Lookup[0].SubTable[0]
assert pairPos.ValueFormat1 == 0x4
@@ -967,12 +1007,16 @@ class InstantiateOTLTest(object):
class InstantiateAvarTest(object):
@pytest.mark.parametrize("location", [{"wght": 0.0}, {"wdth": 0.0}])
def test_pin_and_drop_axis(self, varfont, location):
+ location = instancer.AxisLimits(location)
+
instancer.instantiateAvar(varfont, location)
assert set(varfont["avar"].segments).isdisjoint(location)
def test_full_instance(self, varfont):
- instancer.instantiateAvar(varfont, {"wght": 0.0, "wdth": 0.0})
+ location = instancer.AxisLimits(wght=0.0, wdth=0.0)
+
+ instancer.instantiateAvar(varfont, location)
assert "avar" not in varfont
@@ -1139,6 +1183,8 @@ class InstantiateAvarTest(object):
],
)
def test_limit_axes(self, varfont, axisLimits, expectedSegments):
+ axisLimits = instancer.AxisLimits(axisLimits)
+
instancer.instantiateAvar(varfont, axisLimits)
newSegments = varfont["avar"].segments
@@ -1162,8 +1208,10 @@ class InstantiateAvarTest(object):
def test_drop_invalid_segment_map(self, varfont, invalidSegmentMap, caplog):
varfont["avar"].segments["wght"] = invalidSegmentMap
+ axisLimits = instancer.AxisLimits(wght=(100, 400))
+
with caplog.at_level(logging.WARNING, logger="fontTools.varLib.instancer"):
- instancer.instantiateAvar(varfont, {"wght": (100, 400)})
+ instancer.instantiateAvar(varfont, axisLimits)
assert "Invalid avar" in caplog.text
assert "wght" not in varfont["avar"].segments
@@ -1210,6 +1258,8 @@ class InstantiateFvarTest(object):
],
)
def test_pin_and_drop_axis(self, varfont, location, instancesLeft):
+ location = instancer.AxisLimits(location)
+
instancer.instantiateFvar(varfont, location)
fvar = varfont["fvar"]
@@ -1224,20 +1274,51 @@ class InstantiateFvarTest(object):
] == instancesLeft
def test_full_instance(self, varfont):
- instancer.instantiateFvar(varfont, {"wght": 0.0, "wdth": 0.0})
+ location = instancer.AxisLimits({"wght": 0.0, "wdth": 0.0})
+
+ instancer.instantiateFvar(varfont, location)
assert "fvar" not in varfont
+ @pytest.mark.parametrize(
+ "location, expected",
+ [
+ ({"wght": (30, 40, 700)}, (100, 100, 700)),
+ ({"wght": (30, 40, None)}, (100, 100, 900)),
+ ({"wght": (30, None, 700)}, (100, 400, 700)),
+ ({"wght": (None, 200, 700)}, (100, 200, 700)),
+ ({"wght": (40, None, None)}, (100, 400, 900)),
+ ({"wght": (None, 40, None)}, (100, 100, 900)),
+ ({"wght": (None, None, 700)}, (100, 400, 700)),
+ ({"wght": (None, None, None)}, (100, 400, 900)),
+ ],
+ )
+ def test_axis_limits(self, varfont, location, expected):
+ location = instancer.AxisLimits(location)
+
+ varfont = instancer.instantiateVariableFont(varfont, location)
+
+ fvar = varfont["fvar"]
+ axes = {a.axisTag: a for a in fvar.axes}
+ assert axes["wght"].minValue == expected[0]
+ assert axes["wght"].defaultValue == expected[1]
+ assert axes["wght"].maxValue == expected[2]
+
class InstantiateSTATTest(object):
@pytest.mark.parametrize(
"location, expected",
[
({"wght": 400}, ["Regular", "Condensed", "Upright", "Normal"]),
- ({"wdth": 100}, ["Thin", "Regular", "Black", "Upright", "Normal"]),
+ (
+ {"wdth": 100},
+ ["Thin", "Regular", "Medium", "Black", "Upright", "Normal"],
+ ),
],
)
def test_pin_and_drop_axis(self, varfont, location, expected):
+ location = instancer.AxisLimits(location)
+
instancer.instantiateSTAT(varfont, location)
stat = varfont["STAT"].table
@@ -1256,7 +1337,7 @@ class InstantiateSTATTest(object):
def test_skip_table_no_axis_value_array(self, varfont):
varfont["STAT"].table.AxisValueArray = None
- instancer.instantiateSTAT(varfont, {"wght": 100})
+ instancer.instantiateSTAT(varfont, instancer.AxisLimits(wght=100))
assert len(varfont["STAT"].table.DesignAxisRecord.Axis) == 3
assert varfont["STAT"].table.AxisValueArray is None
@@ -1318,7 +1399,9 @@ class InstantiateSTATTest(object):
return result
def test_limit_axes(self, varfont2):
- instancer.instantiateSTAT(varfont2, {"wght": (400, 500), "wdth": (75, 100)})
+ axisLimits = instancer.AxisLimits({"wght": (400, 500), "wdth": (75, 100)})
+
+ instancer.instantiateSTAT(varfont2, axisLimits)
assert len(varfont2["STAT"].table.AxisValueArray.AxisValue) == 5
assert self.get_STAT_axis_values(varfont2["STAT"].table) == [
@@ -1344,11 +1427,11 @@ class InstantiateSTATTest(object):
axisValue.AxisValueRecord.append(rec)
stat.AxisValueArray.AxisValue.append(axisValue)
- instancer.instantiateSTAT(varfont2, {"wght": (100, 600)})
+ instancer.instantiateSTAT(varfont2, instancer.AxisLimits(wght=(100, 600)))
assert axisValue in varfont2["STAT"].table.AxisValueArray.AxisValue
- instancer.instantiateSTAT(varfont2, {"wdth": (62.5, 87.5)})
+ instancer.instantiateSTAT(varfont2, instancer.AxisLimits(wdth=(62.5, 87.5)))
assert axisValue not in varfont2["STAT"].table.AxisValueArray.AxisValue
@@ -1359,7 +1442,7 @@ class InstantiateSTATTest(object):
stat.AxisValueArray.AxisValue.append(axisValue)
with caplog.at_level(logging.WARNING, logger="fontTools.varLib.instancer"):
- instancer.instantiateSTAT(varfont2, {"wght": 400})
+ instancer.instantiateSTAT(varfont2, instancer.AxisLimits(wght=400))
assert "Unknown AxisValue table format (5)" in caplog.text
assert axisValue in varfont2["STAT"].table.AxisValueArray.AxisValue
@@ -1452,6 +1535,18 @@ class InstantiateVariableFontTest(object):
assert _dump_ttx(instance) == expected
+ def test_move_weight_width_axis_default(self, varfont2):
+ # https://github.com/fonttools/fonttools/issues/2885
+ assert varfont2["OS/2"].usWeightClass == 400
+ assert varfont2["OS/2"].usWidthClass == 5
+
+ varfont = instancer.instantiateVariableFont(
+ varfont2, {"wght": (100, 500, 900), "wdth": 87.5}
+ )
+
+ assert varfont["OS/2"].usWeightClass == 500
+ assert varfont["OS/2"].usWidthClass == 4
+
@pytest.mark.parametrize(
"overlap, wght",
[
@@ -1482,20 +1577,39 @@ class InstantiateVariableFontTest(object):
location = {"wght": 280, "opsz": 18}
instance = instancer.instantiateVariableFont(
- varfont, location,
+ varfont,
+ location,
)
- expected = _get_expected_instance_ttx(
- "SinglePos", *location.values()
- )
+ expected = _get_expected_instance_ttx("SinglePos", *location.values())
assert _dump_ttx(instance) == expected
+ def test_varComposite(self):
+ input_path = os.path.join(
+ TESTDATA, "..", "..", "..", "ttLib", "data", "varc-ac00-ac01.ttf"
+ )
+ varfont = ttLib.TTFont(input_path)
+
+ location = {"wght": 600}
+
+ instance = instancer.instantiateVariableFont(
+ varfont,
+ location,
+ )
+
+ location = {"0000": 0.5}
+
+ instance = instancer.instantiateVariableFont(
+ varfont,
+ location,
+ )
def _conditionSetAsDict(conditionSet, axisOrder):
result = {}
- for cond in conditionSet.ConditionTable:
+ conditionSets = conditionSet.ConditionTable if conditionSet is not None else []
+ for cond in conditionSets:
assert cond.Format == 1
axisTag = axisOrder[cond.AxisIndex]
result[axisTag] = (cond.FilterRangeMinValue, cond.FilterRangeMaxValue)
@@ -1541,10 +1655,11 @@ class InstantiateFeatureVariationsTest(object):
({"wght": 0}, {}, [({"cntr": (0.75, 1.0)}, {"uni0041": "uni0061"})]),
(
{"wght": -1.0},
- {},
+ {"uni0061": "uni0041"},
[
({"cntr": (0, 0.25)}, {"uni0061": "uni0041"}),
({"cntr": (0.75, 1.0)}, {"uni0041": "uni0061"}),
+ ({}, {}),
],
),
(
@@ -1554,7 +1669,8 @@ class InstantiateFeatureVariationsTest(object):
(
{"cntr": (0.75, 1.0)},
{"uni0024": "uni0024.nostroke", "uni0041": "uni0061"},
- )
+ ),
+ ({}, {}),
],
),
(
@@ -1572,7 +1688,66 @@ class InstantiateFeatureVariationsTest(object):
(
{"wght": (0.20886, 1.0)},
{"uni0024": "uni0024.nostroke", "uni0041": "uni0061"},
- )
+ ),
+ ({}, {}),
+ ],
+ ),
+ (
+ {"cntr": (-0.5, 0, 1.0)},
+ {},
+ [
+ (
+ {"wght": (0.20886, 1.0), "cntr": (0.75, 1)},
+ {"uni0024": "uni0024.nostroke", "uni0041": "uni0061"},
+ ),
+ (
+ {"wght": (-1.0, -0.45654), "cntr": (0, 0.25)},
+ {"uni0061": "uni0041"},
+ ),
+ (
+ {"cntr": (0.75, 1.0)},
+ {"uni0041": "uni0061"},
+ ),
+ (
+ {"wght": (0.20886, 1.0)},
+ {"uni0024": "uni0024.nostroke"},
+ ),
+ ],
+ ),
+ (
+ {"cntr": (0.8, 0.9, 1.0)},
+ {"uni0041": "uni0061"},
+ [
+ (
+ {"wght": (0.20886, 1.0)},
+ {"uni0024": "uni0024.nostroke", "uni0041": "uni0061"},
+ ),
+ (
+ {},
+ {"uni0041": "uni0061"},
+ ),
+ ],
+ ),
+ (
+ {"cntr": (0.7, 0.9, 1.0)},
+ {"uni0041": "uni0061"},
+ [
+ (
+ {"cntr": (-0.7499999999999999, 1.0), "wght": (0.20886, 1.0)},
+ {"uni0024": "uni0024.nostroke", "uni0041": "uni0061"},
+ ),
+ (
+ {"cntr": (-0.7499999999999999, 1.0)},
+ {"uni0041": "uni0061"},
+ ),
+ (
+ {"wght": (0.20886, 1.0)},
+ {"uni0024": "uni0024.nostroke"},
+ ),
+ (
+ {},
+ {},
+ ),
],
),
],
@@ -1589,25 +1764,30 @@ class InstantiateFeatureVariationsTest(object):
]
)
- instancer.instantiateFeatureVariations(font, location)
+ limits = instancer.NormalizedAxisLimits(location)
+ instancer.instantiateFeatureVariations(font, limits)
gsub = font["GSUB"].table
featureVariations = gsub.FeatureVariations
assert featureVariations.FeatureVariationCount == len(expectedRecords)
- axisOrder = [a.axisTag for a in font["fvar"].axes if a.axisTag not in location]
+ axisOrder = [
+ a.axisTag
+ for a in font["fvar"].axes
+ if a.axisTag not in location or isinstance(location[a.axisTag], tuple)
+ ]
for i, (expectedConditionSet, expectedSubs) in enumerate(expectedRecords):
rec = featureVariations.FeatureVariationRecord[i]
conditionSet = _conditionSetAsDict(rec.ConditionSet, axisOrder)
- assert conditionSet == expectedConditionSet
+ assert conditionSet == expectedConditionSet, i
subsRecord = rec.FeatureTableSubstitution.SubstitutionRecord[0]
lookupIndices = subsRecord.Feature.LookupListIndex
substitutions = _getSubstitutions(gsub, lookupIndices)
- assert substitutions == expectedSubs
+ assert substitutions == expectedSubs, i
appliedLookupIndices = gsub.FeatureList.FeatureRecord[0].Feature.LookupListIndex
@@ -1638,11 +1818,16 @@ class InstantiateFeatureVariationsTest(object):
),
]
)
+ gsub = font["GSUB"].table
+ assert gsub.FeatureVariations
+ assert gsub.Version == 0x00010001
+
+ location = instancer.NormalizedAxisLimits(location)
instancer.instantiateFeatureVariations(font, location)
- gsub = font["GSUB"].table
assert not hasattr(gsub, "FeatureVariations")
+ assert gsub.Version == 0x00010000
if appliedSubs:
lookupIndices = gsub.FeatureList.FeatureRecord[0].Feature.LookupListIndex
@@ -1650,6 +1835,24 @@ class InstantiateFeatureVariationsTest(object):
else:
assert not gsub.FeatureList.FeatureRecord
+ def test_null_conditionset(self):
+ # A null ConditionSet offset should be treated like an empty ConditionTable, i.e.
+ # all contexts are matched; see https://github.com/fonttools/fonttools/issues/3211
+ font = makeFeatureVarsFont(
+ [([{"wght": (-1.0, 1.0)}], {"uni0024": "uni0024.nostroke"})]
+ )
+ gsub = font["GSUB"].table
+ gsub.FeatureVariations.FeatureVariationRecord[0].ConditionSet = None
+
+ location = instancer.NormalizedAxisLimits({"wght": 0.5})
+ instancer.instantiateFeatureVariations(font, location)
+
+ assert not hasattr(gsub, "FeatureVariations")
+ assert gsub.Version == 0x00010000
+
+ lookupIndices = gsub.FeatureList.FeatureRecord[0].Feature.LookupListIndex
+ assert _getSubstitutions(gsub, lookupIndices) == {"uni0024": "uni0024.nostroke"}
+
def test_unsupported_condition_format(self, caplog):
font = makeFeatureVarsFont(
[
@@ -1665,7 +1868,9 @@ class InstantiateFeatureVariationsTest(object):
rec1.ConditionSet.ConditionTable[0].Format = 2
with caplog.at_level(logging.WARNING, logger="fontTools.varLib.instancer"):
- instancer.instantiateFeatureVariations(font, {"wdth": 0})
+ instancer.instantiateFeatureVariations(
+ font, instancer.NormalizedAxisLimits(wdth=0)
+ )
assert (
"Condition table 0 of FeatureVariationRecord 0 "
@@ -1695,7 +1900,7 @@ class InstantiateFeatureVariationsTest(object):
class LimitTupleVariationAxisRangesTest:
def check_limit_single_var_axis_range(self, var, axisTag, axisRange, expected):
- result = instancer.limitTupleVariationAxisRange(var, axisTag, axisRange)
+ result = instancer.changeTupleVariationAxisLimit(var, axisTag, axisRange)
print(result)
assert len(result) == len(expected)
@@ -1758,8 +1963,8 @@ class LimitTupleVariationAxisRangesTest:
"wght",
0.4,
[
- TupleVariation({"wght": (0.0, 0.5, 1.99994)}, [100, 100]),
- TupleVariation({"wght": (0.5, 1.0, 1.0)}, [8.33333, 8.33333]),
+ TupleVariation({"wght": (0.0, 0.5, 1.0)}, [100, 100]),
+ TupleVariation({"wght": (0.5, 1.0, 1.0)}, [75, 75]),
],
),
(
@@ -1777,7 +1982,7 @@ class LimitTupleVariationAxisRangesTest:
],
)
def test_positive_var(self, var, axisTag, newMax, expected):
- axisRange = instancer.NormalizedAxisRange(0, newMax)
+ axisRange = instancer.NormalizedAxisTripleAndDistances(0, 0, newMax)
self.check_limit_single_var_axis_range(var, axisTag, axisRange, expected)
@pytest.mark.parametrize(
@@ -1837,8 +2042,8 @@ class LimitTupleVariationAxisRangesTest:
"wght",
-0.4,
[
- TupleVariation({"wght": (-2.0, -0.5, -0.0)}, [100, 100]),
- TupleVariation({"wght": (-1.0, -1.0, -0.5)}, [8.33333, 8.33333]),
+ TupleVariation({"wght": (-1.0, -0.5, -0.0)}, [100, 100]),
+ TupleVariation({"wght": (-1.0, -1.0, -0.5)}, [75, 75]),
],
),
(
@@ -1856,30 +2061,30 @@ class LimitTupleVariationAxisRangesTest:
],
)
def test_negative_var(self, var, axisTag, newMin, expected):
- axisRange = instancer.NormalizedAxisRange(newMin, 0)
+ axisRange = instancer.NormalizedAxisTripleAndDistances(newMin, 0, 0, 1, 1)
self.check_limit_single_var_axis_range(var, axisTag, axisRange, expected)
@pytest.mark.parametrize(
- "oldRange, newRange, expected",
+ "oldRange, newLimit, expected",
[
- ((1.0, -1.0), (-1.0, 1.0), None), # invalid oldRange min > max
- ((0.6, 1.0), (0, 0.5), None),
- ((-1.0, -0.6), (-0.5, 0), None),
- ((0.4, 1.0), (0, 0.5), (0.8, 1.0)),
- ((-1.0, -0.4), (-0.5, 0), (-1.0, -0.8)),
- ((0.4, 1.0), (0, 0.4), (1.0, 1.0)),
- ((-1.0, -0.4), (-0.4, 0), (-1.0, -1.0)),
- ((-0.5, 0.5), (-0.4, 0.4), (-1.0, 1.0)),
- ((0, 1.0), (-1.0, 0), (0, 0)), # or None?
- ((-1.0, 0), (0, 1.0), (0, 0)), # or None?
+ ((1.0, -1.0), (-1.0, 0, 1.0), None), # invalid oldRange min > max
+ ((0.6, 1.0), (0, 0, 0.5), None),
+ ((-1.0, -0.6), (-0.5, 0, 0), None),
+ ((0.4, 1.0), (0, 0, 0.5), (0.8, 1.0)),
+ ((-1.0, -0.4), (-0.5, 0, 0), (-1.0, -0.8)),
+ ((0.4, 1.0), (0, 0, 0.4), (1.0, 1.0)),
+ ((-1.0, -0.4), (-0.4, 0, 0), (-1.0, -1.0)),
+ ((-0.5, 0.5), (-0.4, 0, 0.4), (-1.0, 1.0)),
+ ((0, 1.0), (-1.0, 0, 0), (0, 0)), # or None?
+ ((-1.0, 0), (0, 0, 1.0), (0, 0)), # or None?
],
)
-def test_limitFeatureVariationConditionRange(oldRange, newRange, expected):
+def test_limitFeatureVariationConditionRange(oldRange, newLimit, expected):
condition = featureVars.buildConditionTable(0, *oldRange)
- result = instancer._limitFeatureVariationConditionRange(
- condition, instancer.NormalizedAxisRange(*newRange)
+ result = instancer.featureVars._limitFeatureVariationConditionRange(
+ condition, instancer.NormalizedAxisTripleAndDistances(*newLimit, 1, 1)
)
assert result == expected
@@ -1890,12 +2095,33 @@ def test_limitFeatureVariationConditionRange(oldRange, newRange, expected):
[
(["wght=400", "wdth=100"], {"wght": 400, "wdth": 100}),
(["wght=400:900"], {"wght": (400, 900)}),
- (["slnt=11.4"], {"slnt": pytest.approx(11.399994)}),
+ (["wght=400:700:900"], {"wght": (400, 700, 900)}),
+ (["slnt=11.4"], {"slnt": 11.399994}),
(["ABCD=drop"], {"ABCD": None}),
+ (["wght=:500:"], {"wght": (None, 500, None)}),
+ (["wght=::700"], {"wght": (None, None, 700)}),
+ (["wght=200::"], {"wght": (200, None, None)}),
+ (["wght=200:300:"], {"wght": (200, 300, None)}),
+ (["wght=:300:500"], {"wght": (None, 300, 500)}),
+ (["wght=300::700"], {"wght": (300, None, 700)}),
+ (["wght=300:700"], {"wght": (300, None, 700)}),
+ (["wght=:700"], {"wght": (None, None, 700)}),
+ (["wght=200:"], {"wght": (200, None, None)}),
],
)
def test_parseLimits(limits, expected):
- assert instancer.parseLimits(limits) == expected
+ limits = instancer.parseLimits(limits)
+ expected = instancer.AxisLimits(expected)
+
+ assert limits.keys() == expected.keys()
+ for axis, triple in limits.items():
+ expected_triple = expected[axis]
+ if expected_triple is None:
+ assert triple is None
+ else:
+ assert isinstance(triple, instancer.AxisTriple)
+ assert isinstance(expected_triple, instancer.AxisTriple)
+ assert triple == pytest.approx(expected_triple)
@pytest.mark.parametrize(
@@ -1906,27 +2132,35 @@ def test_parseLimits_invalid(limits):
instancer.parseLimits(limits)
-def test_normalizeAxisLimits_tuple(varfont):
- normalized = instancer.normalizeAxisLimits(varfont, {"wght": (100, 400)})
- assert normalized == {"wght": (-1.0, 0)}
+@pytest.mark.parametrize(
+ "limits, expected",
+ [
+ # 300, 500 come from the font having 100,400,900 fvar axis limits.
+ ({"wght": (100, 400)}, {"wght": (-1.0, 0, 0, 300, 500)}),
+ ({"wght": (100, 400, 400)}, {"wght": (-1.0, 0, 0, 300, 500)}),
+ ({"wght": (100, 300, 400)}, {"wght": (-1.0, -0.5, 0, 300, 500)}),
+ ],
+)
+def test_normalizeAxisLimits(varfont, limits, expected):
+ limits = instancer.AxisLimits(limits)
+ normalized = limits.normalize(varfont)
-def test_normalizeAxisLimits_unsupported_range(varfont):
- with pytest.raises(NotImplementedError, match="Unsupported range"):
- instancer.normalizeAxisLimits(varfont, {"wght": (401, 700)})
+ assert normalized == instancer.NormalizedAxisLimits(expected)
def test_normalizeAxisLimits_no_avar(varfont):
del varfont["avar"]
- normalized = instancer.normalizeAxisLimits(varfont, {"wght": (400, 500)})
+ limits = instancer.AxisLimits(wght=(400, 400, 500))
+ normalized = limits.normalize(varfont)
- assert normalized["wght"] == pytest.approx((0, 0.2), 1e-4)
+ assert normalized["wght"] == pytest.approx((0, 0, 0.2, 300, 500), 1e-4)
def test_normalizeAxisLimits_missing_from_fvar(varfont):
with pytest.raises(ValueError, match="not present in fvar"):
- instancer.normalizeAxisLimits(varfont, {"ZZZZ": 1000})
+ instancer.AxisLimits({"ZZZZ": 1000}).normalize(varfont)
def test_sanityCheckVariableTables(varfont):
diff --git a/Tests/varLib/instancer/names_test.py b/Tests/varLib/instancer/names_test.py
index 9774458a..0d7ef1a8 100644
--- a/Tests/varLib/instancer/names_test.py
+++ b/Tests/varLib/instancer/names_test.py
@@ -115,7 +115,7 @@ def _test_name_records(varfont, expected, isNonRIBBI, platforms=[0x409]):
),
# Condensed with unpinned weights
(
- {"wdth": 79, "wght": instancer.AxisRange(400, 900)},
+ {"wdth": 79, "wght": (400, 900)},
{
(1, 3, 1, 0x409): "Test Variable Font Condensed",
(2, 3, 1, 0x409): "Regular",
@@ -126,6 +126,19 @@ def _test_name_records(varfont, expected, isNonRIBBI, platforms=[0x409]):
},
True,
),
+ # Restrict weight and move default, new minimum (500) > old default (400)
+ (
+ {"wght": (500, 900)},
+ {
+ (1, 3, 1, 0x409): "Test Variable Font Medium",
+ (2, 3, 1, 0x409): "Regular",
+ (3, 3, 1, 0x409): "2.001;GOOG;TestVariableFont-Medium",
+ (6, 3, 1, 0x409): "TestVariableFont-Medium",
+ (16, 3, 1, 0x409): "Test Variable Font",
+ (17, 3, 1, 0x409): "Medium",
+ },
+ True,
+ ),
],
)
def test_updateNameTable_with_registered_axes_ribbi(
@@ -215,7 +228,7 @@ def test_updateNameTable_with_multilingual_names(varfont, limits, expected, isNo
def test_updateNameTable_missing_axisValues(varfont):
- with pytest.raises(ValueError, match="Cannot find Axis Values \['wght=200'\]"):
+ with pytest.raises(ValueError, match="Cannot find Axis Values {'wght': 200}"):
instancer.names.updateNameTable(varfont, {"wght": 200})
@@ -257,7 +270,7 @@ def test_updateNameTable_missing_stat(varfont):
def test_updateNameTable_vf_with_italic_attribute(
varfont, limits, expected, isNonRIBBI
):
- font_link_axisValue = varfont["STAT"].table.AxisValueArray.AxisValue[4]
+ font_link_axisValue = varfont["STAT"].table.AxisValueArray.AxisValue[5]
# Unset ELIDABLE_AXIS_VALUE_NAME flag
font_link_axisValue.Flags &= ~instancer.names.ELIDABLE_AXIS_VALUE_NAME
font_link_axisValue.ValueNameID = 294 # Roman --> Italic
@@ -320,3 +333,21 @@ def test_updateNameTable_existing_subfamily_name_is_not_regular(varfont):
instancer.names.updateNameTable(varfont, {"wght": 100})
expected = {(2, 3, 1, 0x409): "Regular", (17, 3, 1, 0x409): "Thin"}
_test_name_records(varfont, expected, isNonRIBBI=True)
+
+
+def test_name_irrelevant_axes(varfont):
+ # Cannot update name table if not on a named axis value location
+ with pytest.raises(ValueError) as excinfo:
+ location = {"wght": 400, "wdth": 90}
+ instance = instancer.instantiateVariableFont(
+ varfont, location, updateFontNames=True
+ )
+ assert "Cannot find Axis Values" in str(excinfo.value)
+
+ # Now let's make the wdth axis "irrelevant" to naming (no axis values)
+ varfont["STAT"].table.AxisValueArray.AxisValue.pop(6)
+ varfont["STAT"].table.AxisValueArray.AxisValue.pop(4)
+ location = {"wght": 400, "wdth": 90}
+ instance = instancer.instantiateVariableFont(
+ varfont, location, updateFontNames=True
+ )
diff --git a/Tests/varLib/instancer/solver_test.py b/Tests/varLib/instancer/solver_test.py
new file mode 100644
index 00000000..b9acf82f
--- /dev/null
+++ b/Tests/varLib/instancer/solver_test.py
@@ -0,0 +1,300 @@
+from fontTools.varLib.instancer import solver
+from fontTools.varLib.instancer import NormalizedAxisTripleAndDistances
+import pytest
+
+
+class RebaseTentTest(object):
+ @pytest.mark.parametrize(
+ "tent, axisRange, expected",
+ [
+ # Case 1: # Pin at default
+ pytest.param((0, 1, 1), (0.0, 0.0, 0.0), []),
+ # Case 1:
+ pytest.param((0.3, 0.5, 0.8), (0.1, 0.2, 0.3), []),
+ # Pin axis
+ pytest.param(
+ (0, 1, 1),
+ (0.5, 0.5, 0.5),
+ [
+ (0.5, None),
+ ],
+ ),
+ # Case 2:
+ pytest.param(
+ (0, 1, 1),
+ (-1, 0, 0.5),
+ [
+ (0.5, (0, 1, 1)),
+ ],
+ ),
+ # Case 2:
+ pytest.param(
+ (0, 1, 1),
+ (-1, 0, 0.75),
+ [
+ (0.75, (0, 1, 1)),
+ ],
+ ),
+ #
+ # Without gain:
+ #
+ # Case 3
+ pytest.param(
+ (0, 0.2, 1),
+ (-1, 0, 0.8),
+ [
+ (1, (0, 0.25, 1.25)),
+ ],
+ ),
+ # Case 3 boundary
+ pytest.param(
+ (0, 0.4, 1),
+ (-1, 0, 0.5),
+ [
+ (1, (0, 0.8, 1.99994)),
+ ],
+ ),
+ # Case 4
+ pytest.param(
+ (0, 0.25, 1),
+ (-1, 0, 0.4),
+ [
+ (1, (0, 0.625, 1)),
+ (0.8, (0.625, 1, 1)),
+ ],
+ ),
+ pytest.param(
+ (0.25, 0.3, 1.05),
+ (0, 0.2, 0.4),
+ [
+ (1, (0.25, 0.5, 1)),
+ (2.6 / 3, (0.5, 1, 1)),
+ ],
+ ),
+ # Case 4 boundary
+ pytest.param(
+ (0.25, 0.5, 1),
+ (0, 0.25, 0.5),
+ [
+ (1, (0, 1, 1)),
+ ],
+ ),
+ #
+ # With gain:
+ #
+ # Case 3a/1neg
+ pytest.param(
+ (0.0, 0.5, 1),
+ (0, 0.5, 1),
+ [
+ (1, None),
+ (-1, (0, 1, 1)),
+ (-1, (-1, -1, 0)),
+ ],
+ ),
+ pytest.param(
+ (0.0, 0.5, 1),
+ (0, 0.5, 0.75),
+ [
+ (1, None),
+ (-0.5, (0, 1, 1)),
+ (-1, (-1, -1, 0)),
+ ],
+ ),
+ pytest.param(
+ (0.0, 0.5, 1),
+ (0, 0.25, 0.8),
+ [
+ (0.5, None),
+ (0.5, (0, 0.45454545, 0.9090909090)),
+ (-0.1, (0.9090909090, 1.0, 1.0)),
+ (-0.5, (-1, -1, 0)),
+ ],
+ ),
+ # Case 3a/1neg
+ pytest.param(
+ (0.0, 0.5, 2),
+ (0.2, 0.5, 0.8),
+ [
+ (1, None),
+ (-0.2, (0, 1, 1)),
+ (-0.6, (-1, -1, 0)),
+ ],
+ ),
+ # Case 3a/1neg
+ pytest.param(
+ (0.0, 0.5, 2),
+ (0.2, 0.5, 1),
+ [
+ (1, None),
+ (-1 / 3, (0, 1, 1)),
+ (-0.6, (-1, -1, 0)),
+ ],
+ ),
+ # Case 3
+ pytest.param(
+ (0, 0.5, 1),
+ (0.25, 0.25, 0.75),
+ [
+ (0.5, None),
+ (0.5, (0, 0.5, 1.0)),
+ ],
+ ),
+ # Case 1neg
+ pytest.param(
+ (0.0, 0.5, 1),
+ (0, 0.25, 0.5),
+ [
+ (0.5, None),
+ (0.5, (0, 1, 1)),
+ (-0.5, (-1, -1, 0)),
+ ],
+ ),
+ # Case 2neg
+ pytest.param(
+ (0.05, 0.55, 1),
+ (0, 0.25, 0.5),
+ [
+ (0.4, None),
+ (0.5, (0, 1, 1)),
+ (-0.4, (-1, -0.8, 0)),
+ (-0.4, (-1, -1, -0.8)),
+ ],
+ ),
+ # Case 2neg, other side
+ pytest.param(
+ (-1, -0.55, -0.05),
+ (-0.5, -0.25, 0),
+ [
+ (0.4, None),
+ (0.5, (-1, -1, 0)),
+ (-0.4, (0, 0.8, 1)),
+ (-0.4, (0.8, 1, 1)),
+ ],
+ ),
+ #
+ # Misc corner cases
+ #
+ pytest.param(
+ (0.5, 0.5, 0.5),
+ (0.5, 0.5, 0.5),
+ [
+ (1, None),
+ ],
+ ),
+ pytest.param(
+ (0.3, 0.5, 0.7),
+ (0.1, 0.5, 0.9),
+ [
+ (1, None),
+ (-1, (0, 0.5, 1)),
+ (-1, (0.5, 1, 1)),
+ (-1, (-1, -0.5, 0)),
+ (-1, (-1, -1, -0.5)),
+ ],
+ ),
+ pytest.param(
+ (0.5, 0.5, 0.5),
+ (0.25, 0.25, 0.5),
+ [
+ (1, (1, 1, 1)),
+ ],
+ ),
+ pytest.param(
+ (0.5, 0.5, 0.5),
+ (0.25, 0.35, 0.5),
+ [
+ (1, (1, 1, 1)),
+ ],
+ ),
+ pytest.param(
+ (0.5, 0.5, 0.55),
+ (0.25, 0.35, 0.5),
+ [
+ (1, (1, 1, 1)),
+ ],
+ ),
+ pytest.param(
+ (0.5, 0.5, 1),
+ (0.5, 0.5, 1),
+ [
+ (1, None),
+ (-1, (0, 1, 1)),
+ ],
+ ),
+ pytest.param(
+ (0.25, 0.5, 1),
+ (0.5, 0.5, 1),
+ [
+ (1, None),
+ (-1, (0, 1, 1)),
+ ],
+ ),
+ pytest.param(
+ (0, 0.2, 1),
+ (0, 0, 0.5),
+ [
+ (1, (0, 0.4, 1.99994)),
+ ],
+ ),
+ # https://github.com/fonttools/fonttools/issues/3139
+ pytest.param(
+ (0, 0.5, 1),
+ (-1, 0.25, 1),
+ [
+ (0.5, None),
+ (0.5, (0.0, 1 / 3, 2 / 3)),
+ (-0.5, (2 / 3, 1, 1)),
+ (-0.5, (-1, -0.2, 0)),
+ (-0.5, (-1, -1, -0.2)),
+ ],
+ ),
+ # Dirac delta at new default. Fancy!
+ pytest.param(
+ (0.5, 0.5, 0.5),
+ (0, 0.5, 1),
+ [
+ (1, None),
+ (-1, (0, 0.0001220703, 1)),
+ (-1, (0.0001220703, 1, 1)),
+ (-1, (-1, -0.0001220703, 0)),
+ (-1, (-1, -1, -0.0001220703)),
+ ],
+ ),
+ # https://github.com/fonttools/fonttools/issues/3177
+ pytest.param(
+ (0, 1, 1),
+ (-1, -0.5, +1, 1, 1),
+ [
+ (1.0, (1 / 3, 1.0, 1.0)),
+ ],
+ ),
+ pytest.param(
+ (0, 1, 1),
+ (-1, -0.5, +1, 2, 1),
+ [
+ (1.0, (0.5, 1.0, 1.0)),
+ ],
+ ),
+ # https://github.com/fonttools/fonttools/issues/3291
+ pytest.param(
+ (0.6, 0.7, 0.8),
+ (-1, 0.2, +1, 1, 1),
+ [
+ (1.0, (0.5, 0.625, 0.75)),
+ ],
+ ),
+ ],
+ )
+ def test_rebaseTent(self, tent, axisRange, expected):
+ axisRange = NormalizedAxisTripleAndDistances(*axisRange)
+
+ sol = solver.rebaseTent(tent, axisRange)
+
+ a = pytest.approx
+ expected = [
+ (a(scalar), (a(v[0]), a(v[1]), a(v[2])) if v is not None else None)
+ for scalar, v in expected
+ ]
+
+ assert sol == expected, (tent, axisRange)
diff --git a/Tests/varLib/interpolatable_test.py b/Tests/varLib/interpolatable_test.py
index a30be71e..10b9cc30 100644
--- a/Tests/varLib/interpolatable_test.py
+++ b/Tests/varLib/interpolatable_test.py
@@ -5,6 +5,7 @@ import shutil
import sys
import tempfile
import unittest
+import pytest
try:
import scipy
@@ -35,12 +36,12 @@ class InterpolatableTest(unittest.TestCase):
shutil.rmtree(self.tempdir)
@staticmethod
- def get_test_input(test_file_or_folder):
+ def get_test_input(*test_file_or_folder):
path, _ = os.path.split(__file__)
- return os.path.join(path, "data", test_file_or_folder)
+ return os.path.join(path, "data", *test_file_or_folder)
@staticmethod
- def get_file_list(folder, suffix, prefix=''):
+ def get_file_list(folder, suffix, prefix=""):
all_files = os.listdir(folder)
file_list = []
for p in all_files:
@@ -51,8 +52,7 @@ class InterpolatableTest(unittest.TestCase):
def temp_path(self, suffix):
self.temp_dir()
self.num_tempfiles += 1
- return os.path.join(self.tempdir,
- "tmp%d%s" % (self.num_tempfiles, suffix))
+ return os.path.join(self.tempdir, "tmp%d%s" % (self.num_tempfiles, suffix))
def temp_dir(self):
if not self.tempdir:
@@ -60,41 +60,201 @@ class InterpolatableTest(unittest.TestCase):
def compile_font(self, path, suffix, temp_dir):
ttx_filename = os.path.basename(path)
- savepath = os.path.join(temp_dir, ttx_filename.replace('.ttx', suffix))
+ savepath = os.path.join(temp_dir, ttx_filename.replace(".ttx", suffix))
font = TTFont(recalcBBoxes=False, recalcTimestamp=False)
font.importXML(path)
font.save(savepath, reorderTables=None)
return font, savepath
-# -----
-# Tests
-# -----
+ # -----
+ # Tests
+ # -----
def test_interpolatable_ttf(self):
- suffix = '.ttf'
- ttx_dir = self.get_test_input('master_ttx_interpolatable_ttf')
+ suffix = ".ttf"
+ ttx_dir = self.get_test_input("master_ttx_interpolatable_ttf")
self.temp_dir()
- ttx_paths = self.get_file_list(ttx_dir, '.ttx', 'TestFamily2-')
+ ttx_paths = self.get_file_list(ttx_dir, ".ttx", "TestFamily2-")
for path in ttx_paths:
self.compile_font(path, suffix, self.tempdir)
ttf_paths = self.get_file_list(self.tempdir, suffix)
self.assertIsNone(interpolatable_main(ttf_paths))
-
def test_interpolatable_otf(self):
- suffix = '.otf'
- ttx_dir = self.get_test_input('master_ttx_interpolatable_otf')
+ suffix = ".otf"
+ ttx_dir = self.get_test_input("master_ttx_interpolatable_otf")
self.temp_dir()
- ttx_paths = self.get_file_list(ttx_dir, '.ttx', 'TestFamily2-')
+ ttx_paths = self.get_file_list(ttx_dir, ".ttx", "TestFamily2-")
for path in ttx_paths:
self.compile_font(path, suffix, self.tempdir)
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"
+ )
+ # This particular test font which was generated by machine-learning
+ # exhibits an "error" in one of the masters; it's a false-positive.
+ # Just make sure the code runs.
+ interpolatable_main((input_path,))
+
if __name__ == "__main__":
sys.exit(unittest.main())
diff --git a/Tests/varLib/interpolate_layout_test.py b/Tests/varLib/interpolate_layout_test.py
index 219f087f..1844e3b1 100644
--- a/Tests/varLib/interpolate_layout_test.py
+++ b/Tests/varLib/interpolate_layout_test.py
@@ -39,7 +39,7 @@ class InterpolateLayoutTest(unittest.TestCase):
return os.path.join(path, "data", "test_results", test_file_or_folder)
@staticmethod
- def get_file_list(folder, suffix, prefix=''):
+ def get_file_list(folder, suffix, prefix=""):
all_files = os.listdir(folder)
file_list = []
for p in all_files:
@@ -50,8 +50,7 @@ class InterpolateLayoutTest(unittest.TestCase):
def temp_path(self, suffix):
self.temp_dir()
self.num_tempfiles += 1
- return os.path.join(self.tempdir,
- "tmp%d%s" % (self.num_tempfiles, suffix))
+ return os.path.join(self.tempdir, "tmp%d%s" % (self.num_tempfiles, suffix))
def temp_dir(self):
if not self.tempdir:
@@ -75,7 +74,8 @@ class InterpolateLayoutTest(unittest.TestCase):
expected = self.read_ttx(expected_ttx)
if actual != expected:
for line in difflib.unified_diff(
- expected, actual, fromfile=expected_ttx, tofile=path):
+ expected, actual, fromfile=expected_ttx, tofile=path
+ ):
sys.stdout.write(line)
self.fail("TTX output is different from expected")
@@ -85,19 +85,21 @@ class InterpolateLayoutTest(unittest.TestCase):
font.save(path)
self.expect_ttx(TTFont(path), expected_ttx, tables)
- def compile_font(self, path, suffix, temp_dir, features=None):
+ def compile_font(self, path, suffix, temp_dir, features=None, cfg=None):
ttx_filename = os.path.basename(path)
- savepath = os.path.join(temp_dir, ttx_filename.replace('.ttx', suffix))
+ savepath = os.path.join(temp_dir, ttx_filename.replace(".ttx", suffix))
font = TTFont(recalcBBoxes=False, recalcTimestamp=False)
+ if cfg:
+ font.cfg.update(cfg)
font.importXML(path)
if features:
addOpenTypeFeaturesFromString(font, features)
font.save(savepath, reorderTables=None)
return font, savepath
-# -----
-# Tests
-# -----
+ # -----
+ # Tests
+ # -----
def test_varlib_interpolate_layout_GSUB_only_ttf(self):
"""Only GSUB, and only in the base master.
@@ -105,49 +107,47 @@ class InterpolateLayoutTest(unittest.TestCase):
The variable font will inherit the GSUB table from the
base master.
"""
- suffix = '.ttf'
- ds_path = self.get_test_input('InterpolateLayout.designspace')
- ufo_dir = self.get_test_input('master_ufo')
- ttx_dir = self.get_test_input('master_ttx_interpolatable_ttf')
+ suffix = ".ttf"
+ ds_path = self.get_test_input("InterpolateLayout.designspace")
+ ufo_dir = self.get_test_input("master_ufo")
+ ttx_dir = self.get_test_input("master_ttx_interpolatable_ttf")
self.temp_dir()
- ttx_paths = self.get_file_list(ttx_dir, '.ttx', 'TestFamily2-')
+ ttx_paths = self.get_file_list(ttx_dir, ".ttx", "TestFamily2-")
for path in ttx_paths:
self.compile_font(path, suffix, self.tempdir)
- finder = lambda s: s.replace(ufo_dir, self.tempdir).replace('.ufo', suffix)
- instfont = interpolate_layout(ds_path, {'weight': 500}, finder)
+ finder = lambda s: s.replace(ufo_dir, self.tempdir).replace(".ufo", suffix)
+ instfont = interpolate_layout(ds_path, {"weight": 500}, finder)
- tables = ['GSUB']
- expected_ttx_path = self.get_test_output('InterpolateLayout.ttx')
+ tables = ["GSUB"]
+ expected_ttx_path = self.get_test_output("InterpolateLayout.ttx")
self.expect_ttx(instfont, expected_ttx_path, tables)
self.check_ttx_dump(instfont, expected_ttx_path, tables, suffix)
-
def test_varlib_interpolate_layout_no_GSUB_ttf(self):
"""The base master has no GSUB table.
The variable font will end up without a GSUB table.
"""
- suffix = '.ttf'
- ds_path = self.get_test_input('InterpolateLayout2.designspace')
- ufo_dir = self.get_test_input('master_ufo')
- ttx_dir = self.get_test_input('master_ttx_interpolatable_ttf')
+ suffix = ".ttf"
+ ds_path = self.get_test_input("InterpolateLayout2.designspace")
+ ufo_dir = self.get_test_input("master_ufo")
+ ttx_dir = self.get_test_input("master_ttx_interpolatable_ttf")
self.temp_dir()
- ttx_paths = self.get_file_list(ttx_dir, '.ttx', 'TestFamily2-')
+ ttx_paths = self.get_file_list(ttx_dir, ".ttx", "TestFamily2-")
for path in ttx_paths:
self.compile_font(path, suffix, self.tempdir)
- finder = lambda s: s.replace(ufo_dir, self.tempdir).replace('.ufo', suffix)
- instfont = interpolate_layout(ds_path, {'weight': 500}, finder)
+ finder = lambda s: s.replace(ufo_dir, self.tempdir).replace(".ufo", suffix)
+ instfont = interpolate_layout(ds_path, {"weight": 500}, finder)
- tables = ['GSUB']
- expected_ttx_path = self.get_test_output('InterpolateLayout2.ttx')
+ tables = ["GSUB"]
+ expected_ttx_path = self.get_test_output("InterpolateLayout2.ttx")
self.expect_ttx(instfont, expected_ttx_path, tables)
self.check_ttx_dump(instfont, expected_ttx_path, tables, suffix)
-
def test_varlib_interpolate_layout_GSUB_only_no_axes_ttf(self):
"""Only GSUB, and only in the base master.
Designspace file has no <axes> element.
@@ -155,17 +155,16 @@ class InterpolateLayoutTest(unittest.TestCase):
The variable font will inherit the GSUB table from the
base master.
"""
- ds_path = self.get_test_input('InterpolateLayout3.designspace')
+ ds_path = self.get_test_input("InterpolateLayout3.designspace")
with self.assertRaisesRegex(DesignSpaceDocumentError, "No axes defined"):
- instfont = interpolate_layout(ds_path, {'weight': 500})
+ instfont = interpolate_layout(ds_path, {"weight": 500})
def test_varlib_interpolate_layout_GPOS_only_size_feat_same_val_ttf(self):
- """Only GPOS; 'size' feature; same values in all masters.
- """
- suffix = '.ttf'
- ds_path = self.get_test_input('InterpolateLayout.designspace')
- ufo_dir = self.get_test_input('master_ufo')
- ttx_dir = self.get_test_input('master_ttx_interpolatable_ttf')
+ """Only GPOS; 'size' feature; same values in all masters."""
+ suffix = ".ttf"
+ ds_path = self.get_test_input("InterpolateLayout.designspace")
+ ufo_dir = self.get_test_input("master_ufo")
+ ttx_dir = self.get_test_input("master_ttx_interpolatable_ttf")
fea_str = """
feature size {
@@ -175,26 +174,26 @@ class InterpolateLayoutTest(unittest.TestCase):
features = [fea_str] * 2
self.temp_dir()
- ttx_paths = self.get_file_list(ttx_dir, '.ttx', 'TestFamily2-')
+ ttx_paths = self.get_file_list(ttx_dir, ".ttx", "TestFamily2-")
for i, path in enumerate(ttx_paths):
self.compile_font(path, suffix, self.tempdir, features[i])
- finder = lambda s: s.replace(ufo_dir, self.tempdir).replace('.ufo', suffix)
- instfont = interpolate_layout(ds_path, {'weight': 500}, finder)
+ finder = lambda s: s.replace(ufo_dir, self.tempdir).replace(".ufo", suffix)
+ instfont = interpolate_layout(ds_path, {"weight": 500}, finder)
- tables = ['GPOS']
- expected_ttx_path = self.get_test_output('InterpolateLayoutGPOS_size_feat_same.ttx')
+ tables = ["GPOS"]
+ expected_ttx_path = self.get_test_output(
+ "InterpolateLayoutGPOS_size_feat_same.ttx"
+ )
self.expect_ttx(instfont, expected_ttx_path, tables)
self.check_ttx_dump(instfont, expected_ttx_path, tables, suffix)
-
def test_varlib_interpolate_layout_GPOS_only_LookupType_1_same_val_ttf(self):
- """Only GPOS; LookupType 1; same values in all masters.
- """
- suffix = '.ttf'
- ds_path = self.get_test_input('InterpolateLayout.designspace')
- ufo_dir = self.get_test_input('master_ufo')
- ttx_dir = self.get_test_input('master_ttx_interpolatable_ttf')
+ """Only GPOS; LookupType 1; same values in all masters."""
+ suffix = ".ttf"
+ ds_path = self.get_test_input("InterpolateLayout.designspace")
+ ufo_dir = self.get_test_input("master_ufo")
+ ttx_dir = self.get_test_input("master_ttx_interpolatable_ttf")
fea_str = """
feature xxxx {
@@ -204,26 +203,24 @@ class InterpolateLayoutTest(unittest.TestCase):
features = [fea_str] * 2
self.temp_dir()
- ttx_paths = self.get_file_list(ttx_dir, '.ttx', 'TestFamily2-')
+ ttx_paths = self.get_file_list(ttx_dir, ".ttx", "TestFamily2-")
for i, path in enumerate(ttx_paths):
self.compile_font(path, suffix, self.tempdir, features[i])
- finder = lambda s: s.replace(ufo_dir, self.tempdir).replace('.ufo', suffix)
- instfont = interpolate_layout(ds_path, {'weight': 500}, finder)
+ finder = lambda s: s.replace(ufo_dir, self.tempdir).replace(".ufo", suffix)
+ instfont = interpolate_layout(ds_path, {"weight": 500}, finder)
- tables = ['GPOS']
- expected_ttx_path = self.get_test_output('InterpolateLayoutGPOS_1_same.ttx')
+ tables = ["GPOS"]
+ expected_ttx_path = self.get_test_output("InterpolateLayoutGPOS_1_same.ttx")
self.expect_ttx(instfont, expected_ttx_path, tables)
self.check_ttx_dump(instfont, expected_ttx_path, tables, suffix)
-
def test_varlib_interpolate_layout_GPOS_only_LookupType_1_diff_val_ttf(self):
- """Only GPOS; LookupType 1; different values in each master.
- """
- suffix = '.ttf'
- ds_path = self.get_test_input('InterpolateLayout.designspace')
- ufo_dir = self.get_test_input('master_ufo')
- ttx_dir = self.get_test_input('master_ttx_interpolatable_ttf')
+ """Only GPOS; LookupType 1; different values in each master."""
+ suffix = ".ttf"
+ ds_path = self.get_test_input("InterpolateLayout.designspace")
+ ufo_dir = self.get_test_input("master_ufo")
+ ttx_dir = self.get_test_input("master_ttx_interpolatable_ttf")
fea_str_0 = """
feature xxxx {
@@ -238,26 +235,24 @@ class InterpolateLayoutTest(unittest.TestCase):
features = [fea_str_0, fea_str_1]
self.temp_dir()
- ttx_paths = self.get_file_list(ttx_dir, '.ttx', 'TestFamily2-')
+ ttx_paths = self.get_file_list(ttx_dir, ".ttx", "TestFamily2-")
for i, path in enumerate(ttx_paths):
self.compile_font(path, suffix, self.tempdir, features[i])
- finder = lambda s: s.replace(ufo_dir, self.tempdir).replace('.ufo', suffix)
- instfont = interpolate_layout(ds_path, {'weight': 500}, finder)
+ finder = lambda s: s.replace(ufo_dir, self.tempdir).replace(".ufo", suffix)
+ instfont = interpolate_layout(ds_path, {"weight": 500}, finder)
- tables = ['GPOS']
- expected_ttx_path = self.get_test_output('InterpolateLayoutGPOS_1_diff.ttx')
+ tables = ["GPOS"]
+ expected_ttx_path = self.get_test_output("InterpolateLayoutGPOS_1_diff.ttx")
self.expect_ttx(instfont, expected_ttx_path, tables)
self.check_ttx_dump(instfont, expected_ttx_path, tables, suffix)
-
def test_varlib_interpolate_layout_GPOS_only_LookupType_1_diff2_val_ttf(self):
- """Only GPOS; LookupType 1; different values and items in each master.
- """
- suffix = '.ttf'
- ds_path = self.get_test_input('InterpolateLayout.designspace')
- ufo_dir = self.get_test_input('master_ufo')
- ttx_dir = self.get_test_input('master_ttx_interpolatable_ttf')
+ """Only GPOS; LookupType 1; different values and items in each master."""
+ suffix = ".ttf"
+ ds_path = self.get_test_input("InterpolateLayout.designspace")
+ ufo_dir = self.get_test_input("master_ufo")
+ ttx_dir = self.get_test_input("master_ttx_interpolatable_ttf")
fea_str_0 = """
feature xxxx {
@@ -273,26 +268,26 @@ class InterpolateLayoutTest(unittest.TestCase):
features = [fea_str_0, fea_str_1]
self.temp_dir()
- ttx_paths = self.get_file_list(ttx_dir, '.ttx', 'TestFamily2-')
+ ttx_paths = self.get_file_list(ttx_dir, ".ttx", "TestFamily2-")
for i, path in enumerate(ttx_paths):
self.compile_font(path, suffix, self.tempdir, features[i])
- finder = lambda s: s.replace(ufo_dir, self.tempdir).replace('.ufo', suffix)
- instfont = interpolate_layout(ds_path, {'weight': 500}, finder)
+ finder = lambda s: s.replace(ufo_dir, self.tempdir).replace(".ufo", suffix)
+ instfont = interpolate_layout(ds_path, {"weight": 500}, finder)
- tables = ['GPOS']
- expected_ttx_path = self.get_test_output('InterpolateLayoutGPOS_1_diff2.ttx')
+ tables = ["GPOS"]
+ expected_ttx_path = self.get_test_output("InterpolateLayoutGPOS_1_diff2.ttx")
self.expect_ttx(instfont, expected_ttx_path, tables)
self.check_ttx_dump(instfont, expected_ttx_path, tables, suffix)
-
- def test_varlib_interpolate_layout_GPOS_only_LookupType_2_spec_pairs_same_val_ttf(self):
- """Only GPOS; LookupType 2 specific pairs; same values in all masters.
- """
- suffix = '.ttf'
- ds_path = self.get_test_input('InterpolateLayout.designspace')
- ufo_dir = self.get_test_input('master_ufo')
- ttx_dir = self.get_test_input('master_ttx_interpolatable_ttf')
+ def test_varlib_interpolate_layout_GPOS_only_LookupType_2_spec_pairs_same_val_ttf(
+ self,
+ ):
+ """Only GPOS; LookupType 2 specific pairs; same values in all masters."""
+ suffix = ".ttf"
+ ds_path = self.get_test_input("InterpolateLayout.designspace")
+ ufo_dir = self.get_test_input("master_ufo")
+ ttx_dir = self.get_test_input("master_ttx_interpolatable_ttf")
fea_str = """
feature xxxx {
@@ -302,26 +297,28 @@ class InterpolateLayoutTest(unittest.TestCase):
features = [fea_str] * 2
self.temp_dir()
- ttx_paths = self.get_file_list(ttx_dir, '.ttx', 'TestFamily2-')
+ ttx_paths = self.get_file_list(ttx_dir, ".ttx", "TestFamily2-")
for i, path in enumerate(ttx_paths):
self.compile_font(path, suffix, self.tempdir, features[i])
- finder = lambda s: s.replace(ufo_dir, self.tempdir).replace('.ufo', suffix)
- instfont = interpolate_layout(ds_path, {'weight': 500}, finder)
+ finder = lambda s: s.replace(ufo_dir, self.tempdir).replace(".ufo", suffix)
+ instfont = interpolate_layout(ds_path, {"weight": 500}, finder)
- tables = ['GPOS']
- expected_ttx_path = self.get_test_output('InterpolateLayoutGPOS_2_spec_same.ttx')
+ tables = ["GPOS"]
+ expected_ttx_path = self.get_test_output(
+ "InterpolateLayoutGPOS_2_spec_same.ttx"
+ )
self.expect_ttx(instfont, expected_ttx_path, tables)
self.check_ttx_dump(instfont, expected_ttx_path, tables, suffix)
-
- def test_varlib_interpolate_layout_GPOS_only_LookupType_2_spec_pairs_diff_val_ttf(self):
- """Only GPOS; LookupType 2 specific pairs; different values in each master.
- """
- suffix = '.ttf'
- ds_path = self.get_test_input('InterpolateLayout.designspace')
- ufo_dir = self.get_test_input('master_ufo')
- ttx_dir = self.get_test_input('master_ttx_interpolatable_ttf')
+ def test_varlib_interpolate_layout_GPOS_only_LookupType_2_spec_pairs_diff_val_ttf(
+ self,
+ ):
+ """Only GPOS; LookupType 2 specific pairs; different values in each master."""
+ suffix = ".ttf"
+ ds_path = self.get_test_input("InterpolateLayout.designspace")
+ ufo_dir = self.get_test_input("master_ufo")
+ ttx_dir = self.get_test_input("master_ttx_interpolatable_ttf")
fea_str_0 = """
feature xxxx {
@@ -336,26 +333,28 @@ class InterpolateLayoutTest(unittest.TestCase):
features = [fea_str_0, fea_str_1]
self.temp_dir()
- ttx_paths = self.get_file_list(ttx_dir, '.ttx', 'TestFamily2-')
+ ttx_paths = self.get_file_list(ttx_dir, ".ttx", "TestFamily2-")
for i, path in enumerate(ttx_paths):
self.compile_font(path, suffix, self.tempdir, features[i])
- finder = lambda s: s.replace(ufo_dir, self.tempdir).replace('.ufo', suffix)
- instfont = interpolate_layout(ds_path, {'weight': 500}, finder)
+ finder = lambda s: s.replace(ufo_dir, self.tempdir).replace(".ufo", suffix)
+ instfont = interpolate_layout(ds_path, {"weight": 500}, finder)
- tables = ['GPOS']
- expected_ttx_path = self.get_test_output('InterpolateLayoutGPOS_2_spec_diff.ttx')
+ tables = ["GPOS"]
+ expected_ttx_path = self.get_test_output(
+ "InterpolateLayoutGPOS_2_spec_diff.ttx"
+ )
self.expect_ttx(instfont, expected_ttx_path, tables)
self.check_ttx_dump(instfont, expected_ttx_path, tables, suffix)
-
- def test_varlib_interpolate_layout_GPOS_only_LookupType_2_spec_pairs_diff2_val_ttf(self):
- """Only GPOS; LookupType 2 specific pairs; different values and items in each master.
- """
- suffix = '.ttf'
- ds_path = self.get_test_input('InterpolateLayout.designspace')
- ufo_dir = self.get_test_input('master_ufo')
- ttx_dir = self.get_test_input('master_ttx_interpolatable_ttf')
+ def test_varlib_interpolate_layout_GPOS_only_LookupType_2_spec_pairs_diff2_val_ttf(
+ self,
+ ):
+ """Only GPOS; LookupType 2 specific pairs; different values and items in each master."""
+ suffix = ".ttf"
+ ds_path = self.get_test_input("InterpolateLayout.designspace")
+ ufo_dir = self.get_test_input("master_ufo")
+ ttx_dir = self.get_test_input("master_ttx_interpolatable_ttf")
fea_str_0 = """
feature xxxx {
@@ -371,26 +370,28 @@ class InterpolateLayoutTest(unittest.TestCase):
features = [fea_str_0, fea_str_1]
self.temp_dir()
- ttx_paths = self.get_file_list(ttx_dir, '.ttx', 'TestFamily2-')
+ ttx_paths = self.get_file_list(ttx_dir, ".ttx", "TestFamily2-")
for i, path in enumerate(ttx_paths):
self.compile_font(path, suffix, self.tempdir, features[i])
- finder = lambda s: s.replace(ufo_dir, self.tempdir).replace('.ufo', suffix)
- instfont = interpolate_layout(ds_path, {'weight': 500}, finder)
+ finder = lambda s: s.replace(ufo_dir, self.tempdir).replace(".ufo", suffix)
+ instfont = interpolate_layout(ds_path, {"weight": 500}, finder)
- tables = ['GPOS']
- expected_ttx_path = self.get_test_output('InterpolateLayoutGPOS_2_spec_diff2.ttx')
+ tables = ["GPOS"]
+ expected_ttx_path = self.get_test_output(
+ "InterpolateLayoutGPOS_2_spec_diff2.ttx"
+ )
self.expect_ttx(instfont, expected_ttx_path, tables)
self.check_ttx_dump(instfont, expected_ttx_path, tables, suffix)
-
- def test_varlib_interpolate_layout_GPOS_only_LookupType_2_class_pairs_same_val_ttf(self):
- """Only GPOS; LookupType 2 class pairs; same values in all masters.
- """
- suffix = '.ttf'
- ds_path = self.get_test_input('InterpolateLayout.designspace')
- ufo_dir = self.get_test_input('master_ufo')
- ttx_dir = self.get_test_input('master_ttx_interpolatable_ttf')
+ def test_varlib_interpolate_layout_GPOS_only_LookupType_2_class_pairs_same_val_ttf(
+ self,
+ ):
+ """Only GPOS; LookupType 2 class pairs; same values in all masters."""
+ suffix = ".ttf"
+ ds_path = self.get_test_input("InterpolateLayout.designspace")
+ ufo_dir = self.get_test_input("master_ufo")
+ ttx_dir = self.get_test_input("master_ttx_interpolatable_ttf")
fea_str = """
feature xxxx {
@@ -400,26 +401,28 @@ class InterpolateLayoutTest(unittest.TestCase):
features = [fea_str] * 2
self.temp_dir()
- ttx_paths = self.get_file_list(ttx_dir, '.ttx', 'TestFamily2-')
+ ttx_paths = self.get_file_list(ttx_dir, ".ttx", "TestFamily2-")
for i, path in enumerate(ttx_paths):
self.compile_font(path, suffix, self.tempdir, features[i])
- finder = lambda s: s.replace(ufo_dir, self.tempdir).replace('.ufo', suffix)
- instfont = interpolate_layout(ds_path, {'weight': 500}, finder)
+ finder = lambda s: s.replace(ufo_dir, self.tempdir).replace(".ufo", suffix)
+ instfont = interpolate_layout(ds_path, {"weight": 500}, finder)
- tables = ['GPOS']
- expected_ttx_path = self.get_test_output('InterpolateLayoutGPOS_2_class_same.ttx')
+ tables = ["GPOS"]
+ expected_ttx_path = self.get_test_output(
+ "InterpolateLayoutGPOS_2_class_same.ttx"
+ )
self.expect_ttx(instfont, expected_ttx_path, tables)
self.check_ttx_dump(instfont, expected_ttx_path, tables, suffix)
-
- def test_varlib_interpolate_layout_GPOS_only_LookupType_2_class_pairs_diff_val_ttf(self):
- """Only GPOS; LookupType 2 class pairs; different values in each master.
- """
- suffix = '.ttf'
- ds_path = self.get_test_input('InterpolateLayout.designspace')
- ufo_dir = self.get_test_input('master_ufo')
- ttx_dir = self.get_test_input('master_ttx_interpolatable_ttf')
+ def test_varlib_interpolate_layout_GPOS_only_LookupType_2_class_pairs_diff_val_ttf(
+ self,
+ ):
+ """Only GPOS; LookupType 2 class pairs; different values in each master."""
+ suffix = ".ttf"
+ ds_path = self.get_test_input("InterpolateLayout.designspace")
+ ufo_dir = self.get_test_input("master_ufo")
+ ttx_dir = self.get_test_input("master_ttx_interpolatable_ttf")
fea_str_0 = """
feature xxxx {
@@ -434,26 +437,28 @@ class InterpolateLayoutTest(unittest.TestCase):
features = [fea_str_0, fea_str_1]
self.temp_dir()
- ttx_paths = self.get_file_list(ttx_dir, '.ttx', 'TestFamily2-')
+ ttx_paths = self.get_file_list(ttx_dir, ".ttx", "TestFamily2-")
for i, path in enumerate(ttx_paths):
self.compile_font(path, suffix, self.tempdir, features[i])
- finder = lambda s: s.replace(ufo_dir, self.tempdir).replace('.ufo', suffix)
- instfont = interpolate_layout(ds_path, {'weight': 500}, finder)
+ finder = lambda s: s.replace(ufo_dir, self.tempdir).replace(".ufo", suffix)
+ instfont = interpolate_layout(ds_path, {"weight": 500}, finder)
- tables = ['GPOS']
- expected_ttx_path = self.get_test_output('InterpolateLayoutGPOS_2_class_diff.ttx')
+ tables = ["GPOS"]
+ expected_ttx_path = self.get_test_output(
+ "InterpolateLayoutGPOS_2_class_diff.ttx"
+ )
self.expect_ttx(instfont, expected_ttx_path, tables)
self.check_ttx_dump(instfont, expected_ttx_path, tables, suffix)
-
- def test_varlib_interpolate_layout_GPOS_only_LookupType_2_class_pairs_diff2_val_ttf(self):
- """Only GPOS; LookupType 2 class pairs; different values and items in each master.
- """
- suffix = '.ttf'
- ds_path = self.get_test_input('InterpolateLayout.designspace')
- ufo_dir = self.get_test_input('master_ufo')
- ttx_dir = self.get_test_input('master_ttx_interpolatable_ttf')
+ def test_varlib_interpolate_layout_GPOS_only_LookupType_2_class_pairs_diff2_val_ttf(
+ self,
+ ):
+ """Only GPOS; LookupType 2 class pairs; different values and items in each master."""
+ suffix = ".ttf"
+ ds_path = self.get_test_input("InterpolateLayout.designspace")
+ ufo_dir = self.get_test_input("master_ufo")
+ ttx_dir = self.get_test_input("master_ttx_interpolatable_ttf")
fea_str_0 = """
feature xxxx {
@@ -469,26 +474,26 @@ class InterpolateLayoutTest(unittest.TestCase):
features = [fea_str_0, fea_str_1]
self.temp_dir()
- ttx_paths = self.get_file_list(ttx_dir, '.ttx', 'TestFamily2-')
+ ttx_paths = self.get_file_list(ttx_dir, ".ttx", "TestFamily2-")
for i, path in enumerate(ttx_paths):
self.compile_font(path, suffix, self.tempdir, features[i])
- finder = lambda s: s.replace(ufo_dir, self.tempdir).replace('.ufo', suffix)
- instfont = interpolate_layout(ds_path, {'weight': 500}, finder)
+ finder = lambda s: s.replace(ufo_dir, self.tempdir).replace(".ufo", suffix)
+ instfont = interpolate_layout(ds_path, {"weight": 500}, finder)
- tables = ['GPOS']
- expected_ttx_path = self.get_test_output('InterpolateLayoutGPOS_2_class_diff2.ttx')
+ tables = ["GPOS"]
+ expected_ttx_path = self.get_test_output(
+ "InterpolateLayoutGPOS_2_class_diff2.ttx"
+ )
self.expect_ttx(instfont, expected_ttx_path, tables)
self.check_ttx_dump(instfont, expected_ttx_path, tables, suffix)
-
def test_varlib_interpolate_layout_GPOS_only_LookupType_3_same_val_ttf(self):
- """Only GPOS; LookupType 3; same values in all masters.
- """
- suffix = '.ttf'
- ds_path = self.get_test_input('InterpolateLayout.designspace')
- ufo_dir = self.get_test_input('master_ufo')
- ttx_dir = self.get_test_input('master_ttx_interpolatable_ttf')
+ """Only GPOS; LookupType 3; same values in all masters."""
+ suffix = ".ttf"
+ ds_path = self.get_test_input("InterpolateLayout.designspace")
+ ufo_dir = self.get_test_input("master_ufo")
+ ttx_dir = self.get_test_input("master_ttx_interpolatable_ttf")
fea_str = """
feature xxxx {
@@ -498,26 +503,24 @@ class InterpolateLayoutTest(unittest.TestCase):
features = [fea_str] * 2
self.temp_dir()
- ttx_paths = self.get_file_list(ttx_dir, '.ttx', 'TestFamily2-')
+ ttx_paths = self.get_file_list(ttx_dir, ".ttx", "TestFamily2-")
for i, path in enumerate(ttx_paths):
self.compile_font(path, suffix, self.tempdir, features[i])
- finder = lambda s: s.replace(ufo_dir, self.tempdir).replace('.ufo', suffix)
- instfont = interpolate_layout(ds_path, {'weight': 500}, finder)
+ finder = lambda s: s.replace(ufo_dir, self.tempdir).replace(".ufo", suffix)
+ instfont = interpolate_layout(ds_path, {"weight": 500}, finder)
- tables = ['GPOS']
- expected_ttx_path = self.get_test_output('InterpolateLayoutGPOS_3_same.ttx')
+ tables = ["GPOS"]
+ expected_ttx_path = self.get_test_output("InterpolateLayoutGPOS_3_same.ttx")
self.expect_ttx(instfont, expected_ttx_path, tables)
self.check_ttx_dump(instfont, expected_ttx_path, tables, suffix)
-
def test_varlib_interpolate_layout_GPOS_only_LookupType_3_diff_val_ttf(self):
- """Only GPOS; LookupType 3; different values in each master.
- """
- suffix = '.ttf'
- ds_path = self.get_test_input('InterpolateLayout.designspace')
- ufo_dir = self.get_test_input('master_ufo')
- ttx_dir = self.get_test_input('master_ttx_interpolatable_ttf')
+ """Only GPOS; LookupType 3; different values in each master."""
+ suffix = ".ttf"
+ ds_path = self.get_test_input("InterpolateLayout.designspace")
+ ufo_dir = self.get_test_input("master_ufo")
+ ttx_dir = self.get_test_input("master_ttx_interpolatable_ttf")
fea_str_0 = """
feature xxxx {
@@ -532,26 +535,24 @@ class InterpolateLayoutTest(unittest.TestCase):
features = [fea_str_0, fea_str_1]
self.temp_dir()
- ttx_paths = self.get_file_list(ttx_dir, '.ttx', 'TestFamily2-')
+ ttx_paths = self.get_file_list(ttx_dir, ".ttx", "TestFamily2-")
for i, path in enumerate(ttx_paths):
self.compile_font(path, suffix, self.tempdir, features[i])
- finder = lambda s: s.replace(ufo_dir, self.tempdir).replace('.ufo', suffix)
- instfont = interpolate_layout(ds_path, {'weight': 500}, finder)
+ finder = lambda s: s.replace(ufo_dir, self.tempdir).replace(".ufo", suffix)
+ instfont = interpolate_layout(ds_path, {"weight": 500}, finder)
- tables = ['GPOS']
- expected_ttx_path = self.get_test_output('InterpolateLayoutGPOS_3_diff.ttx')
+ tables = ["GPOS"]
+ expected_ttx_path = self.get_test_output("InterpolateLayoutGPOS_3_diff.ttx")
self.expect_ttx(instfont, expected_ttx_path, tables)
self.check_ttx_dump(instfont, expected_ttx_path, tables, suffix)
-
def test_varlib_interpolate_layout_GPOS_only_LookupType_4_same_val_ttf(self):
- """Only GPOS; LookupType 4; same values in all masters.
- """
- suffix = '.ttf'
- ds_path = self.get_test_input('InterpolateLayout.designspace')
- ufo_dir = self.get_test_input('master_ufo')
- ttx_dir = self.get_test_input('master_ttx_interpolatable_ttf')
+ """Only GPOS; LookupType 4; same values in all masters."""
+ suffix = ".ttf"
+ ds_path = self.get_test_input("InterpolateLayout.designspace")
+ ufo_dir = self.get_test_input("master_ufo")
+ ttx_dir = self.get_test_input("master_ttx_interpolatable_ttf")
fea_str = """
markClass uni0303 <anchor 0 500> @MARKS_ABOVE;
@@ -562,26 +563,24 @@ class InterpolateLayoutTest(unittest.TestCase):
features = [fea_str] * 2
self.temp_dir()
- ttx_paths = self.get_file_list(ttx_dir, '.ttx', 'TestFamily2-')
+ ttx_paths = self.get_file_list(ttx_dir, ".ttx", "TestFamily2-")
for i, path in enumerate(ttx_paths):
self.compile_font(path, suffix, self.tempdir, features[i])
- finder = lambda s: s.replace(ufo_dir, self.tempdir).replace('.ufo', suffix)
- instfont = interpolate_layout(ds_path, {'weight': 500}, finder)
+ finder = lambda s: s.replace(ufo_dir, self.tempdir).replace(".ufo", suffix)
+ instfont = interpolate_layout(ds_path, {"weight": 500}, finder)
- tables = ['GPOS']
- expected_ttx_path = self.get_test_output('InterpolateLayoutGPOS_4_same.ttx')
+ tables = ["GPOS"]
+ expected_ttx_path = self.get_test_output("InterpolateLayoutGPOS_4_same.ttx")
self.expect_ttx(instfont, expected_ttx_path, tables)
self.check_ttx_dump(instfont, expected_ttx_path, tables, suffix)
-
def test_varlib_interpolate_layout_GPOS_only_LookupType_4_diff_val_ttf(self):
- """Only GPOS; LookupType 4; different values in each master.
- """
- suffix = '.ttf'
- ds_path = self.get_test_input('InterpolateLayout.designspace')
- ufo_dir = self.get_test_input('master_ufo')
- ttx_dir = self.get_test_input('master_ttx_interpolatable_ttf')
+ """Only GPOS; LookupType 4; different values in each master."""
+ suffix = ".ttf"
+ ds_path = self.get_test_input("InterpolateLayout.designspace")
+ ufo_dir = self.get_test_input("master_ufo")
+ ttx_dir = self.get_test_input("master_ttx_interpolatable_ttf")
fea_str_0 = """
markClass uni0303 <anchor 0 500> @MARKS_ABOVE;
@@ -598,26 +597,24 @@ class InterpolateLayoutTest(unittest.TestCase):
features = [fea_str_0, fea_str_1]
self.temp_dir()
- ttx_paths = self.get_file_list(ttx_dir, '.ttx', 'TestFamily2-')
+ ttx_paths = self.get_file_list(ttx_dir, ".ttx", "TestFamily2-")
for i, path in enumerate(ttx_paths):
self.compile_font(path, suffix, self.tempdir, features[i])
- finder = lambda s: s.replace(ufo_dir, self.tempdir).replace('.ufo', suffix)
- instfont = interpolate_layout(ds_path, {'weight': 500}, finder)
+ finder = lambda s: s.replace(ufo_dir, self.tempdir).replace(".ufo", suffix)
+ instfont = interpolate_layout(ds_path, {"weight": 500}, finder)
- tables = ['GPOS']
- expected_ttx_path = self.get_test_output('InterpolateLayoutGPOS_4_diff.ttx')
+ tables = ["GPOS"]
+ expected_ttx_path = self.get_test_output("InterpolateLayoutGPOS_4_diff.ttx")
self.expect_ttx(instfont, expected_ttx_path, tables)
self.check_ttx_dump(instfont, expected_ttx_path, tables, suffix)
-
def test_varlib_interpolate_layout_GPOS_only_LookupType_5_same_val_ttf(self):
- """Only GPOS; LookupType 5; same values in all masters.
- """
- suffix = '.ttf'
- ds_path = self.get_test_input('InterpolateLayout.designspace')
- ufo_dir = self.get_test_input('master_ufo')
- ttx_dir = self.get_test_input('master_ttx_interpolatable_ttf')
+ """Only GPOS; LookupType 5; same values in all masters."""
+ suffix = ".ttf"
+ ds_path = self.get_test_input("InterpolateLayout.designspace")
+ ufo_dir = self.get_test_input("master_ufo")
+ ttx_dir = self.get_test_input("master_ttx_interpolatable_ttf")
fea_str = """
markClass uni0330 <anchor 0 -50> @MARKS_BELOW;
@@ -629,26 +626,24 @@ class InterpolateLayoutTest(unittest.TestCase):
features = [fea_str] * 2
self.temp_dir()
- ttx_paths = self.get_file_list(ttx_dir, '.ttx', 'TestFamily2-')
+ ttx_paths = self.get_file_list(ttx_dir, ".ttx", "TestFamily2-")
for i, path in enumerate(ttx_paths):
self.compile_font(path, suffix, self.tempdir, features[i])
- finder = lambda s: s.replace(ufo_dir, self.tempdir).replace('.ufo', suffix)
- instfont = interpolate_layout(ds_path, {'weight': 500}, finder)
+ finder = lambda s: s.replace(ufo_dir, self.tempdir).replace(".ufo", suffix)
+ instfont = interpolate_layout(ds_path, {"weight": 500}, finder)
- tables = ['GPOS']
- expected_ttx_path = self.get_test_output('InterpolateLayoutGPOS_5_same.ttx')
+ tables = ["GPOS"]
+ expected_ttx_path = self.get_test_output("InterpolateLayoutGPOS_5_same.ttx")
self.expect_ttx(instfont, expected_ttx_path, tables)
self.check_ttx_dump(instfont, expected_ttx_path, tables, suffix)
-
def test_varlib_interpolate_layout_GPOS_only_LookupType_5_diff_val_ttf(self):
- """Only GPOS; LookupType 5; different values in each master.
- """
- suffix = '.ttf'
- ds_path = self.get_test_input('InterpolateLayout.designspace')
- ufo_dir = self.get_test_input('master_ufo')
- ttx_dir = self.get_test_input('master_ttx_interpolatable_ttf')
+ """Only GPOS; LookupType 5; different values in each master."""
+ suffix = ".ttf"
+ ds_path = self.get_test_input("InterpolateLayout.designspace")
+ ufo_dir = self.get_test_input("master_ufo")
+ ttx_dir = self.get_test_input("master_ttx_interpolatable_ttf")
fea_str_0 = """
markClass uni0330 <anchor 0 -50> @MARKS_BELOW;
@@ -667,26 +662,24 @@ class InterpolateLayoutTest(unittest.TestCase):
features = [fea_str_0, fea_str_1]
self.temp_dir()
- ttx_paths = self.get_file_list(ttx_dir, '.ttx', 'TestFamily2-')
+ ttx_paths = self.get_file_list(ttx_dir, ".ttx", "TestFamily2-")
for i, path in enumerate(ttx_paths):
self.compile_font(path, suffix, self.tempdir, features[i])
- finder = lambda s: s.replace(ufo_dir, self.tempdir).replace('.ufo', suffix)
- instfont = interpolate_layout(ds_path, {'weight': 500}, finder)
+ finder = lambda s: s.replace(ufo_dir, self.tempdir).replace(".ufo", suffix)
+ instfont = interpolate_layout(ds_path, {"weight": 500}, finder)
- tables = ['GPOS']
- expected_ttx_path = self.get_test_output('InterpolateLayoutGPOS_5_diff.ttx')
+ tables = ["GPOS"]
+ expected_ttx_path = self.get_test_output("InterpolateLayoutGPOS_5_diff.ttx")
self.expect_ttx(instfont, expected_ttx_path, tables)
self.check_ttx_dump(instfont, expected_ttx_path, tables, suffix)
-
def test_varlib_interpolate_layout_GPOS_only_LookupType_6_same_val_ttf(self):
- """Only GPOS; LookupType 6; same values in all masters.
- """
- suffix = '.ttf'
- ds_path = self.get_test_input('InterpolateLayout.designspace')
- ufo_dir = self.get_test_input('master_ufo')
- ttx_dir = self.get_test_input('master_ttx_interpolatable_ttf')
+ """Only GPOS; LookupType 6; same values in all masters."""
+ suffix = ".ttf"
+ ds_path = self.get_test_input("InterpolateLayout.designspace")
+ ufo_dir = self.get_test_input("master_ufo")
+ ttx_dir = self.get_test_input("master_ttx_interpolatable_ttf")
fea_str = """
markClass uni0303 <anchor 0 500> @MARKS_ABOVE;
@@ -697,26 +690,24 @@ class InterpolateLayoutTest(unittest.TestCase):
features = [fea_str] * 2
self.temp_dir()
- ttx_paths = self.get_file_list(ttx_dir, '.ttx', 'TestFamily2-')
+ ttx_paths = self.get_file_list(ttx_dir, ".ttx", "TestFamily2-")
for i, path in enumerate(ttx_paths):
self.compile_font(path, suffix, self.tempdir, features[i])
- finder = lambda s: s.replace(ufo_dir, self.tempdir).replace('.ufo', suffix)
- instfont = interpolate_layout(ds_path, {'weight': 500}, finder)
+ finder = lambda s: s.replace(ufo_dir, self.tempdir).replace(".ufo", suffix)
+ instfont = interpolate_layout(ds_path, {"weight": 500}, finder)
- tables = ['GPOS']
- expected_ttx_path = self.get_test_output('InterpolateLayoutGPOS_6_same.ttx')
+ tables = ["GPOS"]
+ expected_ttx_path = self.get_test_output("InterpolateLayoutGPOS_6_same.ttx")
self.expect_ttx(instfont, expected_ttx_path, tables)
self.check_ttx_dump(instfont, expected_ttx_path, tables, suffix)
-
def test_varlib_interpolate_layout_GPOS_only_LookupType_6_diff_val_ttf(self):
- """Only GPOS; LookupType 6; different values in each master.
- """
- suffix = '.ttf'
- ds_path = self.get_test_input('InterpolateLayout.designspace')
- ufo_dir = self.get_test_input('master_ufo')
- ttx_dir = self.get_test_input('master_ttx_interpolatable_ttf')
+ """Only GPOS; LookupType 6; different values in each master."""
+ suffix = ".ttf"
+ ds_path = self.get_test_input("InterpolateLayout.designspace")
+ ufo_dir = self.get_test_input("master_ufo")
+ ttx_dir = self.get_test_input("master_ttx_interpolatable_ttf")
fea_str_0 = """
markClass uni0303 <anchor 0 500> @MARKS_ABOVE;
@@ -733,26 +724,112 @@ class InterpolateLayoutTest(unittest.TestCase):
features = [fea_str_0, fea_str_1]
self.temp_dir()
- ttx_paths = self.get_file_list(ttx_dir, '.ttx', 'TestFamily2-')
+ ttx_paths = self.get_file_list(ttx_dir, ".ttx", "TestFamily2-")
for i, path in enumerate(ttx_paths):
self.compile_font(path, suffix, self.tempdir, features[i])
- finder = lambda s: s.replace(ufo_dir, self.tempdir).replace('.ufo', suffix)
- instfont = interpolate_layout(ds_path, {'weight': 500}, finder)
+ finder = lambda s: s.replace(ufo_dir, self.tempdir).replace(".ufo", suffix)
+ instfont = interpolate_layout(ds_path, {"weight": 500}, finder)
- tables = ['GPOS']
- expected_ttx_path = self.get_test_output('InterpolateLayoutGPOS_6_diff.ttx')
+ tables = ["GPOS"]
+ expected_ttx_path = self.get_test_output("InterpolateLayoutGPOS_6_diff.ttx")
self.expect_ttx(instfont, expected_ttx_path, tables)
self.check_ttx_dump(instfont, expected_ttx_path, tables, suffix)
+ def test_varlib_interpolate_layout_GPOS_only_LookupType_7_same_val_ttf(self):
+ """Only GPOS; LookupType 7; same values in all masters."""
+ suffix = ".ttf"
+ ds_path = self.get_test_input("InterpolateLayout.designspace")
+ ufo_dir = self.get_test_input("master_ufo")
+ ttx_dir = self.get_test_input("master_ttx_interpolatable_ttf")
- def test_varlib_interpolate_layout_GPOS_only_LookupType_8_same_val_ttf(self):
- """Only GPOS; LookupType 8; same values in all masters.
+ fea_str = """
+ markClass uni0303 <anchor 0 500> @MARKS_ABOVE;
+ lookup CNTXT_PAIR_POS {
+ pos A a -23;
+ } CNTXT_PAIR_POS;
+
+ lookup CNTXT_MARK_TO_BASE {
+ pos base a <anchor 260 500> mark @MARKS_ABOVE;
+ } CNTXT_MARK_TO_BASE;
+
+ feature xxxx {
+ pos A' lookup CNTXT_PAIR_POS a' @MARKS_ABOVE' lookup CNTXT_MARK_TO_BASE;
+ } xxxx;
"""
- suffix = '.ttf'
- ds_path = self.get_test_input('InterpolateLayout.designspace')
- ufo_dir = self.get_test_input('master_ufo')
- ttx_dir = self.get_test_input('master_ttx_interpolatable_ttf')
+ features = [fea_str] * 2
+
+ self.temp_dir()
+ ttx_paths = self.get_file_list(ttx_dir, ".ttx", "TestFamily2-")
+ cfg = {"fontTools.otlLib.builder:WRITE_GPOS7": True}
+ for i, path in enumerate(ttx_paths):
+ self.compile_font(path, suffix, self.tempdir, features[i], cfg)
+
+ finder = lambda s: s.replace(ufo_dir, self.tempdir).replace(".ufo", suffix)
+ instfont = interpolate_layout(ds_path, {"weight": 500}, finder)
+
+ tables = ["GPOS"]
+ expected_ttx_path = self.get_test_output("InterpolateLayoutGPOS_7_same.ttx")
+ self.expect_ttx(instfont, expected_ttx_path, tables)
+ self.check_ttx_dump(instfont, expected_ttx_path, tables, suffix)
+
+ def test_varlib_interpolate_layout_GPOS_only_LookupType_7_diff_val_ttf(self):
+ """Only GPOS; LookupType 7; different values in each master."""
+ suffix = ".ttf"
+ ds_path = self.get_test_input("InterpolateLayout.designspace")
+ ufo_dir = self.get_test_input("master_ufo")
+ ttx_dir = self.get_test_input("master_ttx_interpolatable_ttf")
+
+ fea_str_0 = """
+ markClass uni0303 <anchor 0 500> @MARKS_ABOVE;
+ lookup CNTXT_PAIR_POS {
+ pos A a -23;
+ } CNTXT_PAIR_POS;
+
+ lookup CNTXT_MARK_TO_BASE {
+ pos base a <anchor 260 500> mark @MARKS_ABOVE;
+ } CNTXT_MARK_TO_BASE;
+
+ feature xxxx {
+ pos A' lookup CNTXT_PAIR_POS a' @MARKS_ABOVE' lookup CNTXT_MARK_TO_BASE;
+ } xxxx;
+ """
+ fea_str_1 = """
+ markClass uni0303 <anchor 0 520> @MARKS_ABOVE;
+ lookup CNTXT_PAIR_POS {
+ pos A a 57;
+ } CNTXT_PAIR_POS;
+
+ lookup CNTXT_MARK_TO_BASE {
+ pos base a <anchor 285 520> mark @MARKS_ABOVE;
+ } CNTXT_MARK_TO_BASE;
+
+ feature xxxx {
+ pos A' lookup CNTXT_PAIR_POS a' @MARKS_ABOVE' lookup CNTXT_MARK_TO_BASE;
+ } xxxx;
+ """
+ features = [fea_str_0, fea_str_1]
+
+ self.temp_dir()
+ ttx_paths = self.get_file_list(ttx_dir, ".ttx", "TestFamily2-")
+ cfg = {"fontTools.otlLib.builder:WRITE_GPOS7": True}
+ for i, path in enumerate(ttx_paths):
+ self.compile_font(path, suffix, self.tempdir, features[i], cfg)
+
+ finder = lambda s: s.replace(ufo_dir, self.tempdir).replace(".ufo", suffix)
+ instfont = interpolate_layout(ds_path, {"weight": 500}, finder)
+
+ tables = ["GPOS"]
+ expected_ttx_path = self.get_test_output("InterpolateLayoutGPOS_7_diff.ttx")
+ self.expect_ttx(instfont, expected_ttx_path, tables)
+ self.check_ttx_dump(instfont, expected_ttx_path, tables, suffix)
+
+ def test_varlib_interpolate_layout_GPOS_only_LookupType_8_same_val_ttf(self):
+ """Only GPOS; LookupType 8; same values in all masters."""
+ suffix = ".ttf"
+ ds_path = self.get_test_input("InterpolateLayout.designspace")
+ ufo_dir = self.get_test_input("master_ufo")
+ ttx_dir = self.get_test_input("master_ttx_interpolatable_ttf")
fea_str = """
markClass uni0303 <anchor 0 500> @MARKS_ABOVE;
@@ -771,26 +848,24 @@ class InterpolateLayoutTest(unittest.TestCase):
features = [fea_str] * 2
self.temp_dir()
- ttx_paths = self.get_file_list(ttx_dir, '.ttx', 'TestFamily2-')
+ ttx_paths = self.get_file_list(ttx_dir, ".ttx", "TestFamily2-")
for i, path in enumerate(ttx_paths):
self.compile_font(path, suffix, self.tempdir, features[i])
- finder = lambda s: s.replace(ufo_dir, self.tempdir).replace('.ufo', suffix)
- instfont = interpolate_layout(ds_path, {'weight': 500}, finder)
+ finder = lambda s: s.replace(ufo_dir, self.tempdir).replace(".ufo", suffix)
+ instfont = interpolate_layout(ds_path, {"weight": 500}, finder)
- tables = ['GPOS']
- expected_ttx_path = self.get_test_output('InterpolateLayoutGPOS_8_same.ttx')
+ tables = ["GPOS"]
+ expected_ttx_path = self.get_test_output("InterpolateLayoutGPOS_8_same.ttx")
self.expect_ttx(instfont, expected_ttx_path, tables)
self.check_ttx_dump(instfont, expected_ttx_path, tables, suffix)
-
def test_varlib_interpolate_layout_GPOS_only_LookupType_8_diff_val_ttf(self):
- """Only GPOS; LookupType 8; different values in each master.
- """
- suffix = '.ttf'
- ds_path = self.get_test_input('InterpolateLayout.designspace')
- ufo_dir = self.get_test_input('master_ufo')
- ttx_dir = self.get_test_input('master_ttx_interpolatable_ttf')
+ """Only GPOS; LookupType 8; different values in each master."""
+ suffix = ".ttf"
+ ds_path = self.get_test_input("InterpolateLayout.designspace")
+ ufo_dir = self.get_test_input("master_ufo")
+ ttx_dir = self.get_test_input("master_ttx_interpolatable_ttf")
fea_str_0 = """
markClass uni0303 <anchor 0 500> @MARKS_ABOVE;
@@ -823,49 +898,47 @@ class InterpolateLayoutTest(unittest.TestCase):
features = [fea_str_0, fea_str_1]
self.temp_dir()
- ttx_paths = self.get_file_list(ttx_dir, '.ttx', 'TestFamily2-')
+ ttx_paths = self.get_file_list(ttx_dir, ".ttx", "TestFamily2-")
for i, path in enumerate(ttx_paths):
self.compile_font(path, suffix, self.tempdir, features[i])
- finder = lambda s: s.replace(ufo_dir, self.tempdir).replace('.ufo', suffix)
- instfont = interpolate_layout(ds_path, {'weight': 500}, finder)
+ finder = lambda s: s.replace(ufo_dir, self.tempdir).replace(".ufo", suffix)
+ instfont = interpolate_layout(ds_path, {"weight": 500}, finder)
- tables = ['GPOS']
- expected_ttx_path = self.get_test_output('InterpolateLayoutGPOS_8_diff.ttx')
+ tables = ["GPOS"]
+ expected_ttx_path = self.get_test_output("InterpolateLayoutGPOS_8_diff.ttx")
self.expect_ttx(instfont, expected_ttx_path, tables)
self.check_ttx_dump(instfont, expected_ttx_path, tables, suffix)
-
def test_varlib_interpolate_layout_main_ttf(self):
- """Mostly for testing varLib.interpolate_layout.main()
- """
- suffix = '.ttf'
- ds_path = self.get_test_input('Build.designspace')
- ufo_dir = self.get_test_input('master_ufo')
- ttx_dir = self.get_test_input('master_ttx_interpolatable_ttf')
+ """Mostly for testing varLib.interpolate_layout.main()"""
+ suffix = ".ttf"
+ ds_path = self.get_test_input("Build.designspace")
+ ufo_dir = self.get_test_input("master_ufo")
+ ttx_dir = self.get_test_input("master_ttx_interpolatable_ttf")
self.temp_dir()
- ttf_dir = os.path.join(self.tempdir, 'master_ttf_interpolatable')
+ ttf_dir = os.path.join(self.tempdir, "master_ttf_interpolatable")
os.makedirs(ttf_dir)
- ttx_paths = self.get_file_list(ttx_dir, '.ttx', 'TestFamily-')
+ ttx_paths = self.get_file_list(ttx_dir, ".ttx", "TestFamily-")
for path in ttx_paths:
self.compile_font(path, suffix, ttf_dir)
- finder = lambda s: s.replace(ufo_dir, ttf_dir).replace('.ufo', suffix)
+ finder = lambda s: s.replace(ufo_dir, ttf_dir).replace(".ufo", suffix)
varfont, _, _ = build(ds_path, finder)
- varfont_name = 'InterpolateLayoutMain'
+ varfont_name = "InterpolateLayoutMain"
varfont_path = os.path.join(self.tempdir, varfont_name + suffix)
varfont.save(varfont_path)
- ds_copy = os.path.splitext(varfont_path)[0] + '.designspace'
+ ds_copy = os.path.splitext(varfont_path)[0] + ".designspace"
shutil.copy2(ds_path, ds_copy)
- args = [ds_copy, 'weight=500', 'contrast=50']
+ args = [ds_copy, "weight=500", "contrast=50"]
interpolate_layout_main(args)
- instfont_path = os.path.splitext(varfont_path)[0] + '-instance' + suffix
+ instfont_path = os.path.splitext(varfont_path)[0] + "-instance" + suffix
instfont = TTFont(instfont_path)
- tables = [table_tag for table_tag in instfont.keys() if table_tag != 'head']
- expected_ttx_path = self.get_test_output(varfont_name + '.ttx')
+ tables = [table_tag for table_tag in instfont.keys() if table_tag != "head"]
+ expected_ttx_path = self.get_test_output(varfont_name + ".ttx")
self.expect_ttx(instfont, expected_ttx_path, tables)
diff --git a/Tests/varLib/iup_test.py b/Tests/varLib/iup_test.py
index 76b2af51..36f63e0e 100644
--- a/Tests/varLib/iup_test.py
+++ b/Tests/varLib/iup_test.py
@@ -4,40 +4,109 @@ import pytest
class IupTest:
-
-# -----
-# Tests
-# -----
+ # -----
+ # Tests
+ # -----
@pytest.mark.parametrize(
"delta, coords, forced",
[
- (
- [(0, 0)],
- [(1, 2)],
- set()
- ),
- (
- [(0, 0), (0, 0), (0, 0)],
- [(1, 2), (3, 2), (2, 3)],
- set()
- ),
+ ([(0, 0)], [(1, 2)], set()),
+ ([(0, 0), (0, 0), (0, 0)], [(1, 2), (3, 2), (2, 3)], set()),
(
[(1, 1), (-1, 1), (-1, -1), (1, -1)],
[(0, 0), (2, 0), (2, 2), (0, 2)],
- set()
+ set(),
),
(
- [(-1, 0), (-1, 0), (-1, 0), (-1, 0), (-1, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (-1, 0)],
- [(-35, -152), (-86, -101), (-50, -65), (0, -116), (51, -65), (86, -99), (35, -151), (87, -202), (51, -238), (-1, -187), (-53, -239), (-88, -205)],
- {11}
+ [
+ (-1, 0),
+ (-1, 0),
+ (-1, 0),
+ (-1, 0),
+ (-1, 0),
+ (0, 0),
+ (0, 0),
+ (0, 0),
+ (0, 0),
+ (0, 0),
+ (0, 0),
+ (-1, 0),
+ ],
+ [
+ (-35, -152),
+ (-86, -101),
+ (-50, -65),
+ (0, -116),
+ (51, -65),
+ (86, -99),
+ (35, -151),
+ (87, -202),
+ (51, -238),
+ (-1, -187),
+ (-53, -239),
+ (-88, -205),
+ ],
+ {11},
),
(
- [(0, 0), (1, 0), (2, 0), (2, 0), (0, 0), (1, 0), (3, 0), (3, 0), (2, 0), (2, 0), (0, 0), (0, 0), (-1, 0), (-1, 0), (-1, 0), (-3, 0), (-1, 0), (0, 0), (0, 0), (-2, 0), (-2, 0), (-1, 0), (-1, 0), (-1, 0), (-4, 0)],
- [(330, 65), (401, 65), (499, 117), (549, 225), (549, 308), (549, 422), (549, 500), (497, 600), (397, 648), (324, 648), (271, 648), (200, 620), (165, 570), (165, 536), (165, 473), (252, 407), (355, 407), (396, 407), (396, 333), (354, 333), (249, 333), (141, 268), (141, 203), (141, 131), (247, 65)],
- {5, 15, 24}
+ [
+ (0, 0),
+ (1, 0),
+ (2, 0),
+ (2, 0),
+ (0, 0),
+ (1, 0),
+ (3, 0),
+ (3, 0),
+ (2, 0),
+ (2, 0),
+ (0, 0),
+ (0, 0),
+ (-1, 0),
+ (-1, 0),
+ (-1, 0),
+ (-3, 0),
+ (-1, 0),
+ (0, 0),
+ (0, 0),
+ (-2, 0),
+ (-2, 0),
+ (-1, 0),
+ (-1, 0),
+ (-1, 0),
+ (-4, 0),
+ ],
+ [
+ (330, 65),
+ (401, 65),
+ (499, 117),
+ (549, 225),
+ (549, 308),
+ (549, 422),
+ (549, 500),
+ (497, 600),
+ (397, 648),
+ (324, 648),
+ (271, 648),
+ (200, 620),
+ (165, 570),
+ (165, 536),
+ (165, 473),
+ (252, 407),
+ (355, 407),
+ (396, 407),
+ (396, 333),
+ (354, 333),
+ (249, 333),
+ (141, 268),
+ (141, 203),
+ (141, 131),
+ (247, 65),
+ ],
+ {5, 15, 24},
),
- ]
+ ],
)
def test_forced_set(self, delta, coords, forced):
f = iup._iup_contour_bound_forced_set(delta, coords)
@@ -49,5 +118,6 @@ class IupTest:
assert chain1 == chain2, f
assert costs1 == costs2, f
+
if __name__ == "__main__":
sys.exit(pytest.main(sys.argv))
diff --git a/Tests/varLib/merger_test.py b/Tests/varLib/merger_test.py
index aa7a6998..e44d466d 100644
--- a/Tests/varLib/merger_test.py
+++ b/Tests/varLib/merger_test.py
@@ -7,6 +7,7 @@ from fontTools.varLib.models import VariationModel
from fontTools.ttLib import TTFont
from fontTools.ttLib.tables import otTables as ot
from fontTools.ttLib.tables.otBase import OTTableReader, OTTableWriter
+from io import BytesIO
import pytest
@@ -1842,3 +1843,102 @@ class COLRVariationMergerTest:
if colr.table.LayerList:
assert len({id(p) for p in colr.table.LayerList.Paint}) == after_layer_count
+
+
+class SparsePositioningMergerTest:
+ def test_zero_kern_at_default(self):
+ # https://github.com/fonttools/fonttools/issues/3111
+
+ pytest.importorskip("ufo2ft")
+ pytest.importorskip("ufoLib2")
+
+ from fontTools.designspaceLib import DesignSpaceDocument
+ from ufo2ft import compileVariableTTF
+ from ufoLib2 import Font
+
+ ds = DesignSpaceDocument()
+ ds.addAxisDescriptor(
+ name="wght", tag="wght", minimum=100, maximum=900, default=400
+ )
+ ds.addSourceDescriptor(font=Font(), location=dict(wght=100))
+ ds.addSourceDescriptor(font=Font(), location=dict(wght=400))
+ ds.addSourceDescriptor(font=Font(), location=dict(wght=900))
+
+ ds.sources[0].font.newGlyph("a").unicode = ord("a")
+ ds.sources[0].font.newGlyph("b").unicode = ord("b")
+ ds.sources[0].font.features.text = "feature kern { pos a b b' 100; } kern;"
+
+ ds.sources[1].font.newGlyph("a").unicode = ord("a")
+ ds.sources[1].font.newGlyph("b").unicode = ord("b")
+ ds.sources[1].font.features.text = "feature kern { pos a b b' 0; } kern;"
+
+ ds.sources[2].font.newGlyph("a").unicode = ord("a")
+ ds.sources[2].font.newGlyph("b").unicode = ord("b")
+ ds.sources[2].font.features.text = "feature kern { pos a b b' -100; } kern;"
+
+ font = compileVariableTTF(ds, inplace=True)
+ b = BytesIO()
+ font.save(b)
+
+ assert font["GDEF"].table.VarStore.VarData[0].Item[0] == [100, -100]
+
+ def test_sparse_cursive(self):
+ # https://github.com/fonttools/fonttools/issues/3168
+
+ pytest.importorskip("ufo2ft")
+ pytest.importorskip("ufoLib2")
+
+ from fontTools.designspaceLib import DesignSpaceDocument
+ from ufo2ft import compileVariableTTF
+ from ufoLib2 import Font
+
+ ds = DesignSpaceDocument()
+ ds.addAxisDescriptor(
+ name="wght", tag="wght", minimum=100, maximum=900, default=400
+ )
+ ds.addSourceDescriptor(font=Font(), location=dict(wght=100))
+ ds.addSourceDescriptor(font=Font(), location=dict(wght=400))
+ ds.addSourceDescriptor(font=Font(), location=dict(wght=900))
+
+ ds.sources[0].font.newGlyph("a").unicode = ord("a")
+ ds.sources[0].font.newGlyph("b").unicode = ord("b")
+ ds.sources[0].font.newGlyph("c").unicode = ord("c")
+ ds.sources[
+ 0
+ ].font.features.text = """
+ feature curs {
+ position cursive a <anchor 400 20> <anchor 0 -20>;
+ position cursive c <anchor NULL> <anchor 0 -20>;
+ } curs;
+ """
+
+ ds.sources[1].font.newGlyph("a").unicode = ord("a")
+ ds.sources[1].font.newGlyph("b").unicode = ord("b")
+ ds.sources[1].font.newGlyph("c").unicode = ord("c")
+ ds.sources[
+ 1
+ ].font.features.text = """
+ feature curs {
+ position cursive a <anchor 500 20> <anchor 0 -20>;
+ position cursive b <anchor 50 22> <anchor 0 -10>;
+ position cursive c <anchor NULL> <anchor 0 -20>;
+ } curs;
+ """
+
+ ds.sources[2].font.newGlyph("a").unicode = ord("a")
+ ds.sources[2].font.newGlyph("b").unicode = ord("b")
+ ds.sources[2].font.newGlyph("c").unicode = ord("c")
+ ds.sources[
+ 2
+ ].font.features.text = """
+ feature curs {
+ position cursive b <anchor 100 40> <anchor 0 -30>;
+ position cursive c <anchor NULL> <anchor 0 -20>;
+ } curs;
+ """
+
+ font = compileVariableTTF(ds, inplace=True)
+ b = BytesIO()
+ font.save(b)
+
+ assert font["GDEF"].table.VarStore.VarData[0].Item[0] == [-100, 0]
diff --git a/Tests/varLib/models_test.py b/Tests/varLib/models_test.py
index e0080129..11ec1a1e 100644
--- a/Tests/varLib/models_test.py
+++ b/Tests/varLib/models_test.py
@@ -31,15 +31,130 @@ def test_normalizeLocation():
assert normalizeLocation({"wght": 1001}, axes) == {"wght": 0.0}
+@pytest.mark.parametrize(
+ "axes, location, expected",
+ [
+ # lower != default != upper
+ ({"wght": (100, 400, 900)}, {"wght": 1000}, {"wght": 1.2}),
+ ({"wght": (100, 400, 900)}, {"wght": 900}, {"wght": 1.0}),
+ ({"wght": (100, 400, 900)}, {"wght": 650}, {"wght": 0.5}),
+ ({"wght": (100, 400, 900)}, {"wght": 400}, {"wght": 0.0}),
+ ({"wght": (100, 400, 900)}, {"wght": 250}, {"wght": -0.5}),
+ ({"wght": (100, 400, 900)}, {"wght": 100}, {"wght": -1.0}),
+ ({"wght": (100, 400, 900)}, {"wght": 25}, {"wght": -1.25}),
+ # lower == default != upper
+ (
+ {"wght": (400, 400, 900), "wdth": (100, 100, 150)},
+ {"wght": 1000, "wdth": 200},
+ {"wght": 1.2, "wdth": 2.0},
+ ),
+ (
+ {"wght": (400, 400, 900), "wdth": (100, 100, 150)},
+ {"wght": 25, "wdth": 25},
+ {"wght": -0.75, "wdth": -1.5},
+ ),
+ # lower != default == upper
+ (
+ {"wght": (100, 400, 400), "wdth": (50, 100, 100)},
+ {"wght": 700, "wdth": 150},
+ {"wght": 1.0, "wdth": 1.0},
+ ),
+ (
+ {"wght": (100, 400, 400), "wdth": (50, 100, 100)},
+ {"wght": -50, "wdth": 25},
+ {"wght": -1.5, "wdth": -1.5},
+ ),
+ # degenerate case with lower == default == upper, normalized location always 0
+ ({"wght": (400, 400, 400)}, {"wght": 100}, {"wght": 0.0}),
+ ({"wght": (400, 400, 400)}, {"wght": 400}, {"wght": 0.0}),
+ ({"wght": (400, 400, 400)}, {"wght": 700}, {"wght": 0.0}),
+ ],
+)
+def test_normalizeLocation_extrapolate(axes, location, expected):
+ assert normalizeLocation(location, axes, extrapolate=True) == expected
+
+
def test_supportScalar():
assert supportScalar({}, {}) == 1.0
assert supportScalar({"wght": 0.2}, {}) == 1.0
assert supportScalar({"wght": 0.2}, {"wght": (0, 2, 3)}) == 0.1
assert supportScalar({"wght": 2.5}, {"wght": (0, 2, 4)}) == 0.75
- assert supportScalar({"wght": 4}, {"wght": (0, 2, 2)}) == 0.0
- assert supportScalar({"wght": 4}, {"wght": (0, 2, 2)}, extrapolate=True) == 2.0
- assert supportScalar({"wght": 4}, {"wght": (0, 2, 3)}, extrapolate=True) == 2.0
- assert supportScalar({"wght": 2}, {"wght": (0, 0.75, 1)}, extrapolate=True) == -4.0
+ assert supportScalar({"wght": 3}, {"wght": (0, 2, 2)}) == 0.0
+ assert (
+ supportScalar(
+ {"wght": 3},
+ {"wght": (0, 2, 2)},
+ extrapolate=True,
+ axisRanges={"wght": (0, 2)},
+ )
+ == 1.5
+ )
+ assert (
+ supportScalar(
+ {"wght": -1},
+ {"wght": (0, 2, 2)},
+ extrapolate=True,
+ axisRanges={"wght": (0, 2)},
+ )
+ == -0.5
+ )
+ assert (
+ supportScalar(
+ {"wght": 3},
+ {"wght": (0, 1, 2)},
+ extrapolate=True,
+ axisRanges={"wght": (0, 2)},
+ )
+ == -1.0
+ )
+ assert (
+ supportScalar(
+ {"wght": -1},
+ {"wght": (0, 1, 2)},
+ extrapolate=True,
+ axisRanges={"wght": (0, 2)},
+ )
+ == -1.0
+ )
+ assert (
+ supportScalar(
+ {"wght": 2},
+ {"wght": (0, 0.75, 1)},
+ extrapolate=True,
+ axisRanges={"wght": (0, 1)},
+ )
+ == -4.0
+ )
+ with pytest.raises(TypeError):
+ supportScalar(
+ {"wght": 2}, {"wght": (0, 0.75, 1)}, extrapolate=True, axisRanges=None
+ )
+
+
+def test_model_extrapolate():
+ locations = [{}, {"a": 1}, {"b": 1}, {"a": 1, "b": 1}]
+ model = VariationModel(locations, extrapolate=True)
+ masterValues = [100, 200, 300, 400]
+ testLocsAndValues = [
+ ({"a": -1, "b": -1}, -200),
+ ({"a": -1, "b": 0}, 0),
+ ({"a": -1, "b": 1}, 200),
+ ({"a": -1, "b": 2}, 400),
+ ({"a": 0, "b": -1}, -100),
+ ({"a": 0, "b": 0}, 100),
+ ({"a": 0, "b": 1}, 300),
+ ({"a": 0, "b": 2}, 500),
+ ({"a": 1, "b": -1}, 0),
+ ({"a": 1, "b": 0}, 200),
+ ({"a": 1, "b": 1}, 400),
+ ({"a": 1, "b": 2}, 600),
+ ({"a": 2, "b": -1}, 100),
+ ({"a": 2, "b": 0}, 300),
+ ({"a": 2, "b": 1}, 500),
+ ({"a": 2, "b": 2}, 700),
+ ]
+ for loc, expectedValue in testLocsAndValues:
+ assert expectedValue == model.interpolateFromMasters(loc, masterValues)
@pytest.mark.parametrize(
diff --git a/Tests/varLib/mutator_test.py b/Tests/varLib/mutator_test.py
index 03ad870f..a3149c95 100644
--- a/Tests/varLib/mutator_test.py
+++ b/Tests/varLib/mutator_test.py
@@ -37,7 +37,7 @@ class MutatorTest(unittest.TestCase):
return os.path.join(path, "data", "test_results", test_file_or_folder)
@staticmethod
- def get_file_list(folder, suffix, prefix=''):
+ def get_file_list(folder, suffix, prefix=""):
all_files = os.listdir(folder)
file_list = []
for p in all_files:
@@ -48,8 +48,7 @@ class MutatorTest(unittest.TestCase):
def temp_path(self, suffix):
self.temp_dir()
self.num_tempfiles += 1
- return os.path.join(self.tempdir,
- "tmp%d%s" % (self.num_tempfiles, suffix))
+ return os.path.join(self.tempdir, "tmp%d%s" % (self.num_tempfiles, suffix))
def temp_dir(self):
if not self.tempdir:
@@ -73,110 +72,111 @@ class MutatorTest(unittest.TestCase):
expected = self.read_ttx(expected_ttx)
if actual != expected:
for line in difflib.unified_diff(
- expected, actual, fromfile=expected_ttx, tofile=path):
+ expected, actual, fromfile=expected_ttx, tofile=path
+ ):
sys.stdout.write(line)
self.fail("TTX output is different from expected")
def compile_font(self, path, suffix, temp_dir):
ttx_filename = os.path.basename(path)
- savepath = os.path.join(temp_dir, ttx_filename.replace('.ttx', suffix))
+ savepath = os.path.join(temp_dir, ttx_filename.replace(".ttx", suffix))
font = TTFont(recalcBBoxes=False, recalcTimestamp=False)
font.importXML(path)
font.save(savepath, reorderTables=None)
return font, savepath
-# -----
-# Tests
-# -----
+ # -----
+ # Tests
+ # -----
def test_varlib_mutator_ttf(self):
- suffix = '.ttf'
- ds_path = self.get_test_input('Build.designspace')
- ufo_dir = self.get_test_input('master_ufo')
- ttx_dir = self.get_test_input('master_ttx_interpolatable_ttf')
+ suffix = ".ttf"
+ ds_path = self.get_test_input("Build.designspace")
+ ufo_dir = self.get_test_input("master_ufo")
+ ttx_dir = self.get_test_input("master_ttx_interpolatable_ttf")
self.temp_dir()
- ttx_paths = self.get_file_list(ttx_dir, '.ttx', 'TestFamily-')
+ ttx_paths = self.get_file_list(ttx_dir, ".ttx", "TestFamily-")
for path in ttx_paths:
self.compile_font(path, suffix, self.tempdir)
- finder = lambda s: s.replace(ufo_dir, self.tempdir).replace('.ufo', suffix)
+ finder = lambda s: s.replace(ufo_dir, self.tempdir).replace(".ufo", suffix)
varfont, _, _ = build(ds_path, finder)
- varfont_name = 'Mutator'
+ varfont_name = "Mutator"
varfont_path = os.path.join(self.tempdir, varfont_name + suffix)
varfont.save(varfont_path)
- args = [varfont_path, 'wght=500', 'cntr=50']
+ args = [varfont_path, "wght=500", "cntr=50"]
mutator(args)
- instfont_path = os.path.splitext(varfont_path)[0] + '-instance' + suffix
+ instfont_path = os.path.splitext(varfont_path)[0] + "-instance" + suffix
instfont = TTFont(instfont_path)
- tables = [table_tag for table_tag in instfont.keys() if table_tag != 'head']
- expected_ttx_path = self.get_test_output(varfont_name + '.ttx')
+ tables = [table_tag for table_tag in instfont.keys() if table_tag != "head"]
+ expected_ttx_path = self.get_test_output(varfont_name + ".ttx")
self.expect_ttx(instfont, expected_ttx_path, tables)
def test_varlib_mutator_getvar_ttf(self):
- suffix = '.ttf'
- ttx_dir = self.get_test_input('master_ttx_getvar_ttf')
+ suffix = ".ttf"
+ ttx_dir = self.get_test_input("master_ttx_getvar_ttf")
self.temp_dir()
- ttx_paths = self.get_file_list(ttx_dir, '.ttx', 'Mutator_Getvar')
+ ttx_paths = self.get_file_list(ttx_dir, ".ttx", "Mutator_Getvar")
for path in ttx_paths:
self.compile_font(path, suffix, self.tempdir)
- varfont_name = 'Mutator_Getvar'
+ varfont_name = "Mutator_Getvar"
varfont_path = os.path.join(self.tempdir, varfont_name + suffix)
- args = [varfont_path, 'wdth=80', 'ASCN=628']
+ args = [varfont_path, "wdth=80", "ASCN=628"]
mutator(args)
- instfont_path = os.path.splitext(varfont_path)[0] + '-instance' + suffix
+ instfont_path = os.path.splitext(varfont_path)[0] + "-instance" + suffix
instfont = TTFont(instfont_path)
- tables = [table_tag for table_tag in instfont.keys() if table_tag != 'head']
- expected_ttx_path = self.get_test_output(varfont_name + '-instance.ttx')
+ tables = [table_tag for table_tag in instfont.keys() if table_tag != "head"]
+ expected_ttx_path = self.get_test_output(varfont_name + "-instance.ttx")
self.expect_ttx(instfont, expected_ttx_path, tables)
def test_varlib_mutator_iup_ttf(self):
- suffix = '.ttf'
- ufo_dir = self.get_test_input('master_ufo')
- ttx_dir = self.get_test_input('master_ttx_varfont_ttf')
+ suffix = ".ttf"
+ ufo_dir = self.get_test_input("master_ufo")
+ ttx_dir = self.get_test_input("master_ttx_varfont_ttf")
self.temp_dir()
- ttx_paths = self.get_file_list(ttx_dir, '.ttx', 'Mutator_IUP')
+ ttx_paths = self.get_file_list(ttx_dir, ".ttx", "Mutator_IUP")
for path in ttx_paths:
self.compile_font(path, suffix, self.tempdir)
- varfont_name = 'Mutator_IUP'
+ varfont_name = "Mutator_IUP"
varfont_path = os.path.join(self.tempdir, varfont_name + suffix)
-
- args = [varfont_path, 'wdth=80', 'ASCN=628']
+
+ args = [varfont_path, "wdth=80", "ASCN=628"]
mutator(args)
- instfont_path = os.path.splitext(varfont_path)[0] + '-instance' + suffix
+ instfont_path = os.path.splitext(varfont_path)[0] + "-instance" + suffix
instfont = TTFont(instfont_path)
- tables = [table_tag for table_tag in instfont.keys() if table_tag != 'head']
- expected_ttx_path = self.get_test_output(varfont_name + '-instance.ttx')
+ tables = [table_tag for table_tag in instfont.keys() if table_tag != "head"]
+ expected_ttx_path = self.get_test_output(varfont_name + "-instance.ttx")
self.expect_ttx(instfont, expected_ttx_path, tables)
def test_varlib_mutator_CFF2(self):
- suffix = '.otf'
- ttx_dir = self.get_test_input('master_ttx_varfont_otf')
+ suffix = ".otf"
+ ttx_dir = self.get_test_input("master_ttx_varfont_otf")
self.temp_dir()
- ttx_paths = self.get_file_list(ttx_dir, '.ttx', 'TestCFF2VF')
+ ttx_paths = self.get_file_list(ttx_dir, ".ttx", "TestCFF2VF")
for path in ttx_paths:
self.compile_font(path, suffix, self.tempdir)
- varfont_name = 'TestCFF2VF'
+ varfont_name = "TestCFF2VF"
varfont_path = os.path.join(self.tempdir, varfont_name + suffix)
- expected_ttx_name = 'InterpolateTestCFF2VF'
+ expected_ttx_name = "InterpolateTestCFF2VF"
tables = ["hmtx", "CFF2"]
- loc = {'wght':float(200)}
+ loc = {"wght": float(200)}
varfont = TTFont(varfont_path)
new_font = make_instance(varfont, loc)
- expected_ttx_path = self.get_test_output(expected_ttx_name + '.ttx')
+ expected_ttx_path = self.get_test_output(expected_ttx_name + ".ttx")
self.expect_ttx(new_font, expected_ttx_path, tables)
diff --git a/Tests/varLib/stat_test.py b/Tests/varLib/stat_test.py
index 6def990e..ce04423a 100644
--- a/Tests/varLib/stat_test.py
+++ b/Tests/varLib/stat_test.py
@@ -65,6 +65,18 @@ def test_getStatAxes(datadir):
"rangeMaxValue": 900.0,
"rangeMinValue": 850.0,
},
+ {
+ "flags": 2,
+ "name": {"en": "Regular"},
+ "value": 400.0,
+ "linkedValue": 700.0,
+ },
+ {
+ "flags": 0,
+ "name": {"en": "Bold"},
+ "value": 700.0,
+ "linkedValue": 400.0,
+ },
],
"name": {"en": "Wéíght", "fa-IR": "قطر"},
"ordering": 2,
@@ -120,6 +132,18 @@ def test_getStatAxes(datadir):
"rangeMaxValue": 850.0,
"rangeMinValue": 650.0,
},
+ {
+ "flags": 2,
+ "name": {"en": "Regular"},
+ "value": 400.0,
+ "linkedValue": 700.0,
+ },
+ {
+ "flags": 0,
+ "name": {"en": "Bold"},
+ "value": 700.0,
+ "linkedValue": 400.0,
+ },
],
"name": {"en": "Wéíght", "fa-IR": "قطر"},
"ordering": 2,
diff --git a/Tests/varLib/varLib_test.py b/Tests/varLib/varLib_test.py
index 29f909ae..87616ae2 100644
--- a/Tests/varLib/varLib_test.py
+++ b/Tests/varLib/varLib_test.py
@@ -1,15 +1,21 @@
+from fontTools.colorLib.builder import buildCOLR
from fontTools.ttLib import TTFont, newTable
-from fontTools.varLib import build, load_designspace
+from fontTools.ttLib.tables import otTables as ot
+from fontTools.varLib import build, build_many, load_designspace, _add_COLR
from fontTools.varLib.errors import VarLibValidationError
import fontTools.varLib.errors as varLibErrors
+from fontTools.varLib.models import VariationModel
from fontTools.varLib.mutator import instantiateVariableFont
from fontTools.varLib import main as varLib_main, load_masters
from fontTools.varLib import set_default_weight_width_slant
from fontTools.designspaceLib import (
- DesignSpaceDocumentError, DesignSpaceDocument, SourceDescriptor,
+ DesignSpaceDocumentError,
+ DesignSpaceDocument,
+ SourceDescriptor,
)
from fontTools.feaLib.builder import addOpenTypeFeaturesFromString
import difflib
+from copy import deepcopy
from io import BytesIO
import os
import shutil
@@ -62,7 +68,7 @@ class BuildTest(unittest.TestCase):
return os.path.join(path, "data", "test_results", test_file_or_folder)
@staticmethod
- def get_file_list(folder, suffix, prefix=''):
+ def get_file_list(folder, suffix, prefix=""):
all_files = os.listdir(folder)
file_list = []
for p in all_files:
@@ -73,8 +79,7 @@ class BuildTest(unittest.TestCase):
def temp_path(self, suffix):
self.temp_dir()
self.num_tempfiles += 1
- return os.path.join(self.tempdir,
- "tmp%d%s" % (self.num_tempfiles, suffix))
+ return os.path.join(self.tempdir, "tmp%d%s" % (self.num_tempfiles, suffix))
def temp_dir(self):
if not self.tempdir:
@@ -98,7 +103,8 @@ class BuildTest(unittest.TestCase):
expected = self.read_ttx(expected_ttx)
if actual != expected:
for line in difflib.unified_diff(
- expected, actual, fromfile=expected_ttx, tofile=path):
+ expected, actual, fromfile=expected_ttx, tofile=path
+ ):
sys.stdout.write(line)
self.fail("TTX output is different from expected")
@@ -110,28 +116,34 @@ class BuildTest(unittest.TestCase):
def compile_font(self, path, suffix, temp_dir):
ttx_filename = os.path.basename(path)
- savepath = os.path.join(temp_dir, ttx_filename.replace('.ttx', suffix))
+ savepath = os.path.join(temp_dir, ttx_filename.replace(".ttx", suffix))
font = TTFont(recalcBBoxes=False, recalcTimestamp=False)
font.importXML(path)
font.save(savepath, reorderTables=None)
return font, savepath
- def _run_varlib_build_test(self, designspace_name, font_name, tables,
- expected_ttx_name, save_before_dump=False,
- post_process_master=None):
- suffix = '.ttf'
- ds_path = self.get_test_input(designspace_name + '.designspace')
- ufo_dir = self.get_test_input('master_ufo')
- ttx_dir = self.get_test_input('master_ttx_interpolatable_ttf')
+ def _run_varlib_build_test(
+ self,
+ designspace_name,
+ font_name,
+ tables,
+ expected_ttx_name,
+ save_before_dump=False,
+ post_process_master=None,
+ ):
+ suffix = ".ttf"
+ ds_path = self.get_test_input(designspace_name + ".designspace")
+ ufo_dir = self.get_test_input("master_ufo")
+ ttx_dir = self.get_test_input("master_ttx_interpolatable_ttf")
self.temp_dir()
- ttx_paths = self.get_file_list(ttx_dir, '.ttx', font_name + '-')
+ ttx_paths = self.get_file_list(ttx_dir, ".ttx", font_name + "-")
for path in ttx_paths:
font, savepath = self.compile_font(path, suffix, self.tempdir)
if post_process_master is not None:
post_process_master(font, savepath)
- finder = lambda s: s.replace(ufo_dir, self.tempdir).replace('.ufo', suffix)
+ finder = lambda s: s.replace(ufo_dir, self.tempdir).replace(".ufo", suffix)
varfont, model, _ = build(ds_path, finder)
if save_before_dump:
@@ -140,25 +152,26 @@ class BuildTest(unittest.TestCase):
# dumps we need to save to a temporary stream, and realod the font
varfont = reload_font(varfont)
- expected_ttx_path = self.get_test_output(expected_ttx_name + '.ttx')
+ expected_ttx_path = self.get_test_output(expected_ttx_name + ".ttx")
self.expect_ttx(varfont, expected_ttx_path, tables)
self.check_ttx_dump(varfont, expected_ttx_path, tables, suffix)
-# -----
-# Tests
-# -----
+
+ # -----
+ # Tests
+ # -----
def test_varlib_build_ttf(self):
"""Designspace file contains <axes> element."""
self._run_varlib_build_test(
- designspace_name='Build',
- font_name='TestFamily',
- tables=['GDEF', 'HVAR', 'MVAR', 'fvar', 'gvar'],
- expected_ttx_name='Build'
+ designspace_name="Build",
+ font_name="TestFamily",
+ tables=["GDEF", "HVAR", "MVAR", "fvar", "gvar"],
+ expected_ttx_name="Build",
)
def test_varlib_build_no_axes_ttf(self):
"""Designspace file does not contain an <axes> element."""
- ds_path = self.get_test_input('InterpolateLayout3.designspace')
+ ds_path = self.get_test_input("InterpolateLayout3.designspace")
with self.assertRaisesRegex(DesignSpaceDocumentError, "No axes defined"):
build(ds_path)
@@ -166,12 +179,12 @@ class BuildTest(unittest.TestCase):
"""Designspace file contains a 'weight' axis with <map> elements
modifying the normalization mapping. An 'avar' table is generated.
"""
- test_name = 'BuildAvarSingleAxis'
+ test_name = "BuildAvarSingleAxis"
self._run_varlib_build_test(
designspace_name=test_name,
- font_name='TestFamily3',
- tables=['avar'],
- expected_ttx_name=test_name
+ font_name="TestFamily3",
+ tables=["avar"],
+ expected_ttx_name=test_name,
)
def test_varlib_avar_with_identity_maps(self):
@@ -186,12 +199,12 @@ class BuildTest(unittest.TestCase):
https://github.com/googlei18n/fontmake/issues/295
https://github.com/fonttools/fonttools/issues/1011
"""
- test_name = 'BuildAvarIdentityMaps'
+ test_name = "BuildAvarIdentityMaps"
self._run_varlib_build_test(
designspace_name=test_name,
- font_name='TestFamily3',
- tables=['avar'],
- expected_ttx_name=test_name
+ font_name="TestFamily3",
+ tables=["avar"],
+ expected_ttx_name=test_name,
)
def test_varlib_avar_empty_axis(self):
@@ -206,12 +219,25 @@ class BuildTest(unittest.TestCase):
https://github.com/googlei18n/fontmake/issues/295
https://github.com/fonttools/fonttools/issues/1011
"""
- test_name = 'BuildAvarEmptyAxis'
+ test_name = "BuildAvarEmptyAxis"
self._run_varlib_build_test(
designspace_name=test_name,
- font_name='TestFamily3',
- tables=['avar'],
- expected_ttx_name=test_name
+ font_name="TestFamily3",
+ tables=["avar"],
+ expected_ttx_name=test_name,
+ )
+
+ def test_varlib_avar2(self):
+ """Designspace file contains a 'weight' axis with <map> elements
+ modifying the normalization mapping as well as <mappings> element
+ modifying it post-normalization. An 'avar' table is generated.
+ """
+ test_name = "BuildAvar2"
+ self._run_varlib_build_test(
+ designspace_name=test_name,
+ font_name="TestFamily3",
+ tables=["avar"],
+ expected_ttx_name=test_name,
)
def test_varlib_build_feature_variations(self):
@@ -274,6 +300,7 @@ class BuildTest(unittest.TestCase):
The multiple languages are done to verify whether multiple existing
'rclt' features are updated correctly.
"""
+
def add_rclt(font, savepath):
features = """
languagesystem DFLT dflt;
@@ -294,6 +321,7 @@ class BuildTest(unittest.TestCase):
"""
addOpenTypeFeaturesFromString(font, features)
font.save(savepath)
+
self._run_varlib_build_test(
designspace_name="FeatureVars",
font_name="TestFamily",
@@ -310,22 +338,22 @@ class BuildTest(unittest.TestCase):
https://github.com/fonttools/fonttools/issues/1381
"""
- test_name = 'BuildGvarCompositeExplicitDelta'
+ test_name = "BuildGvarCompositeExplicitDelta"
self._run_varlib_build_test(
designspace_name=test_name,
- font_name='TestFamily4',
- tables=['gvar'],
- expected_ttx_name=test_name
+ font_name="TestFamily4",
+ tables=["gvar"],
+ expected_ttx_name=test_name,
)
def test_varlib_nonmarking_CFF2(self):
self.temp_dir()
- ds_path = self.get_test_input('TestNonMarkingCFF2.designspace', copy=True)
+ ds_path = self.get_test_input("TestNonMarkingCFF2.designspace", copy=True)
ttx_dir = self.get_test_input("master_non_marking_cff2")
expected_ttx_path = self.get_test_output("TestNonMarkingCFF2.ttx")
- for path in self.get_file_list(ttx_dir, '.ttx', 'TestNonMarkingCFF2_'):
+ for path in self.get_file_list(ttx_dir, ".ttx", "TestNonMarkingCFF2_"):
self.compile_font(path, ".otf", self.tempdir)
ds = DesignSpaceDocument.fromfile(ds_path)
@@ -344,11 +372,11 @@ class BuildTest(unittest.TestCase):
def test_varlib_build_CFF2(self):
self.temp_dir()
- ds_path = self.get_test_input('TestCFF2.designspace', copy=True)
+ ds_path = self.get_test_input("TestCFF2.designspace", copy=True)
ttx_dir = self.get_test_input("master_cff2")
expected_ttx_path = self.get_test_output("BuildTestCFF2.ttx")
- for path in self.get_file_list(ttx_dir, '.ttx', 'TestCFF2_'):
+ for path in self.get_file_list(ttx_dir, ".ttx", "TestCFF2_"):
self.compile_font(path, ".otf", self.tempdir)
ds = DesignSpaceDocument.fromfile(ds_path)
@@ -367,11 +395,11 @@ class BuildTest(unittest.TestCase):
def test_varlib_build_CFF2_from_CFF2(self):
self.temp_dir()
- ds_path = self.get_test_input('TestCFF2Input.designspace', copy=True)
+ ds_path = self.get_test_input("TestCFF2Input.designspace", copy=True)
ttx_dir = self.get_test_input("master_cff2_input")
expected_ttx_path = self.get_test_output("BuildTestCFF2.ttx")
- for path in self.get_file_list(ttx_dir, '.ttx', 'TestCFF2_'):
+ for path in self.get_file_list(ttx_dir, ".ttx", "TestCFF2_"):
self.compile_font(path, ".otf", self.tempdir)
ds = DesignSpaceDocument.fromfile(ds_path)
@@ -390,11 +418,11 @@ class BuildTest(unittest.TestCase):
def test_varlib_build_sparse_CFF2(self):
self.temp_dir()
- ds_path = self.get_test_input('TestSparseCFF2VF.designspace', copy=True)
+ ds_path = self.get_test_input("TestSparseCFF2VF.designspace", copy=True)
ttx_dir = self.get_test_input("master_sparse_cff2")
expected_ttx_path = self.get_test_output("TestSparseCFF2VF.ttx")
- for path in self.get_file_list(ttx_dir, '.ttx', 'MasterSet_Kanji-'):
+ for path in self.get_file_list(ttx_dir, ".ttx", "MasterSet_Kanji-"):
self.compile_font(path, ".otf", self.tempdir)
ds = DesignSpaceDocument.fromfile(ds_path)
@@ -413,11 +441,11 @@ class BuildTest(unittest.TestCase):
def test_varlib_build_vpal(self):
self.temp_dir()
- ds_path = self.get_test_input('test_vpal.designspace', copy=True)
+ ds_path = self.get_test_input("test_vpal.designspace", copy=True)
ttx_dir = self.get_test_input("master_vpal_test")
expected_ttx_path = self.get_test_output("test_vpal.ttx")
- for path in self.get_file_list(ttx_dir, '.ttx', 'master_vpal_test_'):
+ for path in self.get_file_list(ttx_dir, ".ttx", "master_vpal_test_"):
self.compile_font(path, ".otf", self.tempdir)
ds = DesignSpaceDocument.fromfile(ds_path)
@@ -434,20 +462,19 @@ class BuildTest(unittest.TestCase):
self.expect_ttx(varfont, expected_ttx_path, tables)
def test_varlib_main_ttf(self):
- """Mostly for testing varLib.main()
- """
- suffix = '.ttf'
- ds_path = self.get_test_input('Build.designspace')
- ttx_dir = self.get_test_input('master_ttx_interpolatable_ttf')
+ """Mostly for testing varLib.main()"""
+ suffix = ".ttf"
+ ds_path = self.get_test_input("Build.designspace")
+ ttx_dir = self.get_test_input("master_ttx_interpolatable_ttf")
self.temp_dir()
- ttf_dir = os.path.join(self.tempdir, 'master_ttf_interpolatable')
+ ttf_dir = os.path.join(self.tempdir, "master_ttf_interpolatable")
os.makedirs(ttf_dir)
- ttx_paths = self.get_file_list(ttx_dir, '.ttx', 'TestFamily-')
+ ttx_paths = self.get_file_list(ttx_dir, ".ttx", "TestFamily-")
for path in ttx_paths:
self.compile_font(path, suffix, ttf_dir)
- ds_copy = os.path.join(self.tempdir, 'BuildMain.designspace')
+ ds_copy = os.path.join(self.tempdir, "BuildMain.designspace")
shutil.copy2(ds_path, ds_copy)
# by default, varLib.main finds master TTFs inside a
@@ -459,7 +486,7 @@ class BuildTest(unittest.TestCase):
finally:
os.chdir(cwd)
- varfont_path = os.path.splitext(ds_copy)[0] + '-VF' + suffix
+ varfont_path = os.path.splitext(ds_copy)[0] + "-VF" + suffix
self.assertTrue(os.path.exists(varfont_path))
# try again passing an explicit --master-finder
@@ -475,17 +502,110 @@ class BuildTest(unittest.TestCase):
self.assertTrue(os.path.exists(varfont_path))
varfont = TTFont(varfont_path)
- tables = [table_tag for table_tag in varfont.keys() if table_tag != 'head']
- expected_ttx_path = self.get_test_output('BuildMain.ttx')
+ tables = [table_tag for table_tag in varfont.keys() if table_tag != "head"]
+ expected_ttx_path = self.get_test_output("BuildMain.ttx")
+ self.expect_ttx(varfont, expected_ttx_path, tables)
+
+ def test_varLib_main_output_dir(self):
+ self.temp_dir()
+ outdir = os.path.join(self.tempdir, "output_dir_test")
+ self.assertFalse(os.path.exists(outdir))
+
+ ds_path = os.path.join(self.tempdir, "BuildMain.designspace")
+ shutil.copy2(self.get_test_input("Build.designspace"), ds_path)
+
+ shutil.copytree(
+ self.get_test_input("master_ttx_interpolatable_ttf"),
+ os.path.join(outdir, "master_ttx"),
+ )
+
+ finder = "%s/output_dir_test/master_ttx/{stem}.ttx" % self.tempdir
+
+ varLib_main([ds_path, "--output-dir", outdir, "--master-finder", finder])
+
+ self.assertTrue(os.path.isdir(outdir))
+ self.assertTrue(os.path.exists(os.path.join(outdir, "BuildMain-VF.ttf")))
+
+ def test_varLib_main_filter_variable_fonts(self):
+ self.temp_dir()
+ outdir = os.path.join(self.tempdir, "filter_variable_fonts_test")
+ self.assertFalse(os.path.exists(outdir))
+
+ ds_path = os.path.join(self.tempdir, "BuildMain.designspace")
+ shutil.copy2(self.get_test_input("Build.designspace"), ds_path)
+
+ shutil.copytree(
+ self.get_test_input("master_ttx_interpolatable_ttf"),
+ os.path.join(outdir, "master_ttx"),
+ )
+
+ finder = "%s/filter_variable_fonts_test/master_ttx/{stem}.ttx" % self.tempdir
+
+ cmd = [ds_path, "--output-dir", outdir, "--master-finder", finder]
+
+ with pytest.raises(SystemExit):
+ varLib_main(cmd + ["--variable-fonts", "FooBar"]) # no font matches
+
+ varLib_main(cmd + ["--variable-fonts", "Build.*"]) # this does match
+
+ 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
+ # STAT from the base master: https://github.com/googlefonts/fontmake/issues/985
+ base_master = TTFont()
+ base_master.importXML(
+ self.get_test_input("master_no_overwrite_stat/Test-CondensedThin.ttx")
+ )
+ assert "STAT" in base_master
+
+ vf = next(
+ iter(
+ build_many(
+ DesignSpaceDocument.fromfile(
+ self.get_test_input("TestNoOverwriteSTAT.designspace")
+ )
+ ).values()
+ )
+ )
+ assert "STAT" in vf
+
+ assert vf["STAT"].table == base_master["STAT"].table
+
def test_varlib_build_from_ds_object_in_memory_ttfonts(self):
ds_path = self.get_test_input("Build.designspace")
ttx_dir = self.get_test_input("master_ttx_interpolatable_ttf")
expected_ttx_path = self.get_test_output("BuildMain.ttx")
self.temp_dir()
- for path in self.get_file_list(ttx_dir, '.ttx', 'TestFamily-'):
+ for path in self.get_file_list(ttx_dir, ".ttx", "TestFamily-"):
self.compile_font(path, ".ttf", self.tempdir)
ds = DesignSpaceDocument.fromfile(ds_path)
@@ -510,7 +630,7 @@ class BuildTest(unittest.TestCase):
ttx_dir = self.get_test_input("master_ttx_interpolatable_ttf")
expected_ttx_path = self.get_test_output("BuildMain.ttx")
- for path in self.get_file_list(ttx_dir, '.ttx', 'TestFamily-'):
+ for path in self.get_file_list(ttx_dir, ".ttx", "TestFamily-"):
self.compile_font(path, ".ttf", self.tempdir)
ds = DesignSpaceDocument.fromfile(ds_path)
@@ -656,12 +776,12 @@ class BuildTest(unittest.TestCase):
def test_varlib_build_VVAR_CFF2(self):
self.temp_dir()
- ds_path = self.get_test_input('TestVVAR.designspace', copy=True)
+ ds_path = self.get_test_input("TestVVAR.designspace", copy=True)
ttx_dir = self.get_test_input("master_vvar_cff2")
- expected_ttx_name = 'TestVVAR'
- suffix = '.otf'
+ expected_ttx_name = "TestVVAR"
+ suffix = ".otf"
- for path in self.get_file_list(ttx_dir, '.ttx', 'TestVVAR'):
+ for path in self.get_file_list(ttx_dir, ".ttx", "TestVVAR"):
font, savepath = self.compile_font(path, suffix, self.tempdir)
ds = DesignSpaceDocument.fromfile(ds_path)
@@ -674,7 +794,7 @@ class BuildTest(unittest.TestCase):
varfont, _, _ = build(ds)
varfont = reload_font(varfont)
- expected_ttx_path = self.get_test_output(expected_ttx_name + '.ttx')
+ expected_ttx_path = self.get_test_output(expected_ttx_name + ".ttx")
tables = ["VVAR"]
self.expect_ttx(varfont, expected_ttx_path, tables)
self.check_ttx_dump(varfont, expected_ttx_path, tables, suffix)
@@ -682,12 +802,12 @@ class BuildTest(unittest.TestCase):
def test_varlib_build_BASE(self):
self.temp_dir()
- ds_path = self.get_test_input('TestBASE.designspace', copy=True)
+ ds_path = self.get_test_input("TestBASE.designspace", copy=True)
ttx_dir = self.get_test_input("master_base_test")
- expected_ttx_name = 'TestBASE'
- suffix = '.otf'
+ expected_ttx_name = "TestBASE"
+ suffix = ".otf"
- for path in self.get_file_list(ttx_dir, '.ttx', 'TestBASE'):
+ for path in self.get_file_list(ttx_dir, ".ttx", "TestBASE"):
font, savepath = self.compile_font(path, suffix, self.tempdir)
ds = DesignSpaceDocument.fromfile(ds_path)
@@ -700,17 +820,17 @@ class BuildTest(unittest.TestCase):
varfont, _, _ = build(ds)
varfont = reload_font(varfont)
- expected_ttx_path = self.get_test_output(expected_ttx_name + '.ttx')
+ expected_ttx_path = self.get_test_output(expected_ttx_name + ".ttx")
tables = ["BASE"]
self.expect_ttx(varfont, expected_ttx_path, tables)
self.check_ttx_dump(varfont, expected_ttx_path, tables, suffix)
def test_varlib_build_single_master(self):
self._run_varlib_build_test(
- designspace_name='SingleMaster',
- font_name='TestFamily',
- tables=['GDEF', 'HVAR', 'MVAR', 'STAT', 'fvar', 'cvar', 'gvar', 'name'],
- expected_ttx_name='SingleMaster',
+ designspace_name="SingleMaster",
+ font_name="TestFamily",
+ tables=["GDEF", "HVAR", "MVAR", "STAT", "fvar", "cvar", "gvar", "name"],
+ expected_ttx_name="SingleMaster",
save_before_dump=True,
)
@@ -718,7 +838,7 @@ class BuildTest(unittest.TestCase):
"""Test the correct merging of class-based pair kerning.
Problem description at https://github.com/fonttools/fonttools/pull/1638.
- Test font and Designspace generated by
+ Test font and Designspace generated by
https://gist.github.com/madig/183d0440c9f7d05f04bd1280b9664bd1.
"""
ds_path = self.get_test_input("KerningMerging.designspace")
@@ -756,7 +876,7 @@ class BuildTest(unittest.TestCase):
assert getattr(class2_zero.Value1, "XAdvDevice", None) is None
# Assert the variable font's kerning table (without deltas) is equal to the
- # default font's kerning table. The bug fixed in
+ # default font's kerning table. The bug fixed in
# https://github.com/fonttools/fonttools/pull/1638 caused rogue kerning
# values to be written to the variable font.
assert _extract_flat_kerning(varfont, class_kerning_table) == {
@@ -816,7 +936,7 @@ class BuildTest(unittest.TestCase):
def test_varlib_build_incompatible_features(self):
with pytest.raises(
varLibErrors.ShouldBeConstant,
- match = """
+ match="""
Couldn't merge the fonts, because some values were different, but should have
been the same. This happened while performing the following operation:
@@ -828,8 +948,8 @@ Expected to see .FeatureCount==2, instead saw 1
Incompatible features between masters.
Expected: kern, mark.
Got: kern.
-"""):
-
+""",
+ ):
self._run_varlib_build_test(
designspace_name="IncompatibleFeatures",
font_name="IncompatibleFeatures",
@@ -840,8 +960,7 @@ Got: kern.
def test_varlib_build_incompatible_lookup_types(self):
with pytest.raises(
- varLibErrors.MismatchedTypes,
- match = r"'MarkBasePos', instead saw 'PairPos'"
+ varLibErrors.MismatchedTypes, match=r"'MarkBasePos', instead saw 'PairPos'"
):
self._run_varlib_build_test(
designspace_name="IncompatibleLookupTypes",
@@ -854,14 +973,14 @@ Got: kern.
def test_varlib_build_incompatible_arrays(self):
with pytest.raises(
varLibErrors.ShouldBeConstant,
- match = """
+ match="""
Couldn't merge the fonts, because some values were different, but should have
been the same. This happened while performing the following operation:
GPOS.table.ScriptList.ScriptCount
The problem is likely to be in Simple Two Axis Bold:
-Expected to see .ScriptCount==1, instead saw 0"""
+Expected to see .ScriptCount==1, instead saw 0""",
):
self._run_varlib_build_test(
designspace_name="IncompatibleArrays",
@@ -873,13 +992,24 @@ Expected to see .ScriptCount==1, instead saw 0"""
def test_varlib_build_variable_colr(self):
self._run_varlib_build_test(
- designspace_name='TestVariableCOLR',
- font_name='TestVariableCOLR',
+ designspace_name="TestVariableCOLR",
+ font_name="TestVariableCOLR",
tables=["GlyphOrder", "fvar", "glyf", "COLR", "CPAL"],
- expected_ttx_name='TestVariableCOLR-VF',
+ expected_ttx_name="TestVariableCOLR-VF",
save_before_dump=True,
)
+ def test_varlib_build_variable_cff2_with_empty_sparse_glyph(self):
+ # https://github.com/fonttools/fonttools/issues/3233
+ self._run_varlib_build_test(
+ designspace_name="SparseCFF2",
+ font_name="SparseCFF2",
+ tables=["GlyphOrder", "CFF2", "fvar", "hmtx", "HVAR"],
+ expected_ttx_name="SparseCFF2-VF",
+ save_before_dump=True,
+ )
+
+
def test_load_masters_layerName_without_required_font():
ds = DesignSpaceDocument()
s = SourceDescriptor()
@@ -985,5 +1115,38 @@ class SetDefaultWeightWidthSlantTest(object):
assert ttFont["post"].italicAngle == -12.0
+def test_variable_COLR_without_VarIndexMap():
+ # test we don't add a no-op VarIndexMap to variable COLR when not needed
+ # https://github.com/fonttools/fonttools/issues/2800
+
+ font1 = TTFont()
+ font1.setGlyphOrder([".notdef", "A"])
+ font1["COLR"] = buildCOLR({"A": (ot.PaintFormat.PaintSolid, 0, 1.0)})
+ # font2 == font1 except for PaintSolid.Alpha
+ font2 = deepcopy(font1)
+ font2["COLR"].table.BaseGlyphList.BaseGlyphPaintRecord[0].Paint.Alpha = 0.0
+ master_fonts = [font1, font2]
+
+ varfont = deepcopy(font1)
+ axis_order = ["XXXX"]
+ model = VariationModel([{}, {"XXXX": 1.0}], axis_order)
+
+ _add_COLR(varfont, model, master_fonts, axis_order)
+
+ colr = varfont["COLR"].table
+
+ assert len(colr.BaseGlyphList.BaseGlyphPaintRecord) == 1
+ baserec = colr.BaseGlyphList.BaseGlyphPaintRecord[0]
+ assert baserec.Paint.Format == ot.PaintFormat.PaintVarSolid
+ assert baserec.Paint.VarIndexBase == 0
+
+ assert colr.VarStore is not None
+ assert len(colr.VarStore.VarData) == 1
+ assert len(colr.VarStore.VarData[0].Item) == 1
+ assert colr.VarStore.VarData[0].Item[0] == [-16384]
+
+ assert colr.VarIndexMap is None
+
+
if __name__ == "__main__":
sys.exit(unittest.main())
diff --git a/Tests/varLib/varStore_test.py b/Tests/varLib/varStore_test.py
index cad8ac73..7eb9d740 100644
--- a/Tests/varLib/varStore_test.py
+++ b/Tests/varLib/varStore_test.py
@@ -1,4 +1,7 @@
import pytest
+from io import StringIO
+from fontTools.misc.xmlWriter import XMLWriter
+from fontTools.misc.roundTools import noRound
from fontTools.varLib.models import VariationModel
from fontTools.varLib.varStore import OnlineVarStoreBuilder, VarStoreInstancer
from fontTools.ttLib import TTFont, newTable
@@ -13,7 +16,7 @@ from fontTools.ttLib.tables.otTables import VarStore
(
[{}, {"a": 1}],
[
- [10, 10], # Test NO_VARIATION_INDEX
+ [10, 10], # Test NO_VARIATION_INDEX
[100, 2000],
[100, 22000],
],
@@ -80,3 +83,204 @@ def buildAxis(axisTag):
axis = Axis()
axis.axisTag = axisTag
return axis
+
+
+@pytest.mark.parametrize(
+ "numRegions, varData, expectedNumVarData, expectedBytes",
+ [
+ (
+ 5,
+ [
+ [10, 10, 0, 0, 20],
+ {3: 300},
+ ],
+ 1,
+ 126,
+ ),
+ (
+ 5,
+ [
+ [10, 10, 0, 0, 20],
+ [10, 11, 0, 0, 20],
+ [10, 12, 0, 0, 20],
+ [10, 13, 0, 0, 20],
+ {3: 300},
+ ],
+ 1,
+ 175,
+ ),
+ (
+ 5,
+ [
+ [10, 11, 0, 0, 20],
+ [10, 300, 0, 0, 20],
+ [10, 301, 0, 0, 20],
+ [10, 302, 0, 0, 20],
+ [10, 303, 0, 0, 20],
+ [10, 304, 0, 0, 20],
+ ],
+ 1,
+ 180,
+ ),
+ (
+ 5,
+ [
+ [0, 11, 12, 0, 20],
+ [0, 13, 12, 0, 20],
+ [0, 14, 12, 0, 20],
+ [0, 15, 12, 0, 20],
+ [0, 16, 12, 0, 20],
+ [10, 300, 0, 0, 20],
+ [10, 301, 0, 0, 20],
+ [10, 302, 0, 0, 20],
+ [10, 303, 0, 0, 20],
+ [10, 304, 0, 0, 20],
+ ],
+ 1,
+ 200,
+ ),
+ (
+ 5,
+ [
+ [0, 11, 12, 0, 20],
+ [0, 13, 12, 0, 20],
+ [0, 14, 12, 0, 20],
+ [0, 15, 12, 0, 20],
+ [0, 16, 12, 0, 20],
+ [0, 17, 12, 0, 20],
+ [0, 18, 12, 0, 20],
+ [0, 19, 12, 0, 20],
+ [0, 20, 12, 0, 20],
+ [10, 300, 0, 0, 20],
+ [10, 301, 0, 0, 20],
+ [10, 302, 0, 0, 20],
+ [10, 303, 0, 0, 20],
+ [10, 304, 0, 0, 20],
+ ],
+ 2,
+ 218,
+ ),
+ (
+ 3,
+ [
+ [10, 10, 10],
+ ],
+ 0,
+ 12,
+ ),
+ ],
+)
+def test_optimize(numRegions, varData, expectedNumVarData, expectedBytes):
+ locations = [{i: i / 16384.0} for i in range(numRegions)]
+ axisTags = sorted({k for loc in locations for k in loc})
+
+ model = VariationModel(locations)
+ builder = OnlineVarStoreBuilder(axisTags)
+ builder.setModel(model)
+
+ for data in varData:
+ if type(data) is dict:
+ newData = [0] * numRegions
+ for k, v in data.items():
+ newData[k] = v
+ data = newData
+
+ builder.storeMasters(data)
+
+ varStore = builder.finish()
+ varStore.optimize()
+
+ dummyFont = TTFont()
+
+ writer = XMLWriter(StringIO())
+ varStore.toXML(writer, dummyFont)
+ xml = writer.file.getvalue()
+
+ assert len(varStore.VarData) == expectedNumVarData, xml
+
+ writer = OTTableWriter()
+ varStore.compile(writer, dummyFont)
+ data = writer.getAllData()
+
+ assert len(data) == expectedBytes, xml
+
+
+@pytest.mark.parametrize(
+ "quantization, expectedBytes",
+ [
+ (1, 200),
+ (2, 180),
+ (3, 170),
+ (4, 175),
+ (8, 170),
+ (32, 92),
+ (64, 56),
+ ],
+)
+def test_quantize(quantization, expectedBytes):
+ varData = [
+ [0, 11, 12, 0, 20],
+ [0, 13, 12, 0, 20],
+ [0, 14, 12, 0, 20],
+ [0, 15, 12, 0, 20],
+ [0, 16, 12, 0, 20],
+ [10, 300, 0, 0, 20],
+ [10, 301, 0, 0, 20],
+ [10, 302, 0, 0, 20],
+ [10, 303, 0, 0, 20],
+ [10, 304, 0, 0, 20],
+ ]
+
+ numRegions = 5
+ locations = [{i: i / 16384.0} for i in range(numRegions)]
+ axisTags = sorted({k for loc in locations for k in loc})
+
+ model = VariationModel(locations)
+
+ builder = OnlineVarStoreBuilder(axisTags)
+ builder.setModel(model)
+
+ for data in varData:
+ builder.storeMasters(data)
+
+ varStore = builder.finish()
+ varStore.optimize(quantization=quantization)
+
+ dummyFont = TTFont()
+
+ writer = XMLWriter(StringIO())
+ varStore.toXML(writer, dummyFont)
+ xml = writer.file.getvalue()
+
+ writer = OTTableWriter()
+ varStore.compile(writer, dummyFont)
+ data = writer.getAllData()
+
+ assert len(data) == expectedBytes, xml
+
+
+def test_optimize_overflow():
+ numRegions = 1
+ locations = [{"wght": 0}, {"wght": 0.5}]
+ axisTags = ["wght"]
+
+ model = VariationModel(locations)
+ builder = OnlineVarStoreBuilder(axisTags)
+ builder.setModel(model)
+
+ for data in range(0, 0xFFFF * 2):
+ data = [0, data]
+ builder.storeMasters(data, round=noRound)
+
+ varStore = builder.finish()
+ varStore.optimize()
+
+ for s in varStore.VarData:
+ print(len(s.Item))
+
+ # 5 data-sets:
+ # - 0..127: 1-byte dataset
+ # - 128..32767: 2-byte dataset
+ # - 32768..32768+65535-1: 4-byte dataset
+ # - 32768+65535..65535+65535-1: 4-byte dataset
+ assert len(varStore.VarData) == 4