diff --git a/pyproject.toml b/pyproject.toml
index 5326128..53ecd7a 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -12,7 +12,7 @@ authors = [
]
keywords = ["font", "fonts"]
license = {text = "GNU General Public License v3"}
-dependencies = ["fontra", "fontmake", "fontc"]
+dependencies = ["fontra", "fontmake", "fontc", "cffsubr"]
dynamic = ["version"]
requires-python = ">=3.10"
classifiers = [
@@ -67,3 +67,7 @@ ignore_missing_imports = true
[[tool.mypy.overrides]]
module = "fontmake.*"
ignore_missing_imports = true
+
+[[tool.mypy.overrides]]
+module = "cffsubr.*"
+ignore_missing_imports = true
diff --git a/src/fontra_compile/__main__.py b/src/fontra_compile/__main__.py
index f68cabf..1ae3235 100644
--- a/src/fontra_compile/__main__.py
+++ b/src/fontra_compile/__main__.py
@@ -7,7 +7,7 @@
from .builder import Builder
-async def main_async():
+async def main_async() -> None:
parser = argparse.ArgumentParser()
parser.add_argument("source_font")
parser.add_argument("output_font")
@@ -25,7 +25,11 @@ async def main_async():
)
reader = getFileSystemBackend(sourceFontPath)
- builder = Builder(reader, glyphNames)
+ builder = Builder(
+ reader=reader,
+ requestedGlyphNames=glyphNames,
+ buildCFF2=outputFontPath.suffix.lower() == ".otf",
+ )
await builder.setup()
ttFont = await builder.build()
ttFont.save(outputFontPath)
diff --git a/src/fontra_compile/builder.py b/src/fontra_compile/builder.py
index d7fbe6a..67a9202 100644
--- a/src/fontra_compile/builder.py
+++ b/src/fontra_compile/builder.py
@@ -1,8 +1,10 @@
from dataclasses import dataclass, field
from typing import Any
+import cffsubr
from fontra.core.classes import VariableGlyph
-from fontra.core.path import PackedPath
+from fontra.core.path import PackedPath, Path
+from fontra.core.protocols import ReadableFontBackend
from fontTools.designspaceLib import AxisDescriptor
from fontTools.fontBuilder import FontBuilder
from fontTools.misc.fixedTools import floatToFixed as fl2fi
@@ -10,6 +12,10 @@
from fontTools.misc.timeTools import timestampNow
from fontTools.misc.transform import DecomposedTransform
from fontTools.misc.vector import Vector
+from fontTools.pens.boundsPen import BoundsPen, ControlBoundsPen
+from fontTools.pens.pointPen import PointToSegmentPen
+from fontTools.pens.recordingPen import RecordingPen
+from fontTools.pens.t2CharStringPen import T2CharStringPen
from fontTools.pens.ttGlyphPen import TTGlyphPointPen
from fontTools.ttLib import TTFont, newTable
from fontTools.ttLib.tables import otTables as ot
@@ -18,7 +24,8 @@
from fontTools.ttLib.tables._g_v_a_r import TupleVariation
from fontTools.ttLib.tables.otTables import VAR_TRANSFORM_MAPPING, VarComponentFlags
from fontTools.varLib import HVAR_FIELDS, VVAR_FIELDS
-from fontTools.varLib.builder import buildVarIdxMap
+from fontTools.varLib.builder import buildVarData, buildVarIdxMap
+from fontTools.varLib.cff import CFF2CharStringMergePen, addCFFVarStore
from fontTools.varLib.models import (
VariationModel,
VariationModelError,
@@ -53,15 +60,28 @@ class MissingBaseGlyphError(Exception):
@dataclass
class GlyphInfo:
- ttGlyph: TTGlyph
hasContours: bool
- xAdvance: float = 500
- xAdvanceVariations: list = field(default_factory=list)
- variations: list = field(default_factory=list)
+ xAdvance: float
+ xAdvanceVariations: list
+ leftSideBearing: int
+ ttGlyph: TTGlyph | None = None
+ gvarVariations: list | None = None
+ charString: Any | None = None
+ charStringSupports: tuple | None = None
variableComponents: list = field(default_factory=list)
localAxisTags: set = field(default_factory=set)
model: VariationModel | None = None
+ def __post_init__(self) -> None:
+ if self.ttGlyph is None:
+ assert self.gvarVariations is None
+ assert self.charString is not None
+ else:
+ assert self.charString is None
+ assert self.charStringSupports is None
+ if self.gvarVariations is None:
+ self.gvarVariations = []
+
@dataclass
class ComponentInfo:
@@ -125,10 +145,11 @@ def addLocationToComponent(self, compo, axisIndicesMapping, axisTags, storeBuild
compo.axisValuesVarIndex = varIdx
+@dataclass(kw_only=True)
class Builder:
- def __init__(self, reader, requestedGlyphNames=None):
- self.reader = reader # a Fontra Backend, such as DesignspaceBackend
- self.requestedGlyphNames = requestedGlyphNames
+ reader: ReadableFontBackend # a Fontra Backend, such as DesignspaceBackend
+ requestedGlyphNames: list = field(default_factory=list)
+ buildCFF2: bool = False
async def setup(self) -> None:
self.glyphMap = await self.reader.getGlyphMap()
@@ -149,7 +170,7 @@ async def setup(self) -> None:
self.globalAxisTags = {axis.name: axis.tag for axis in self.globalAxes}
self.defaultLocation = {k: v[1] for k, v in self.globalAxisDict.items()}
- self.cachedSourceGlyphs: dict[str, VariableGlyph] = {}
+ self.cachedSourceGlyphs: dict[str, VariableGlyph | None] = {}
self.cachedComponentBaseInfo: dict = {}
self.glyphInfos: dict[str, GlyphInfo] = {}
@@ -165,6 +186,7 @@ async def getSourceGlyph(
sourceGlyph = self.cachedSourceGlyphs.get(glyphName)
if sourceGlyph is None:
sourceGlyph = await self.reader.getGlyph(glyphName)
+ assert sourceGlyph is not None
if storeInCache:
self.cachedSourceGlyphs[glyphName] = sourceGlyph
return sourceGlyph
@@ -195,10 +217,19 @@ async def prepareGlyphs(self) -> None:
if glyphInfo is None:
# make .notdef based on UPM
glyphInfo = GlyphInfo(
- ttGlyph=TTGlyphPointPen(None).glyph(),
+ ttGlyph=(
+ TTGlyphPointPen(None).glyph() if not self.buildCFF2 else None
+ ),
+ charString=(
+ T2CharStringPen(None, None, CFF2=True).getCharString()
+ if self.buildCFF2
+ else None
+ ),
hasContours=False,
xAdvance=500,
+ leftSideBearing=0, # TODO: fix when actual notdef shape is added
xAdvanceVariations=[500],
+ gvarVariations=None,
)
self.glyphInfos[glyphName] = glyphInfo
@@ -225,26 +256,38 @@ async def prepareOneGlyph(self, glyphName: str) -> GlyphInfo:
xAdvanceVariations = prepareXAdvanceVariations(glyph, glyphSources)
- sourceCoordinates = prepareSourceCoordinates(glyph, glyphSources)
- variations = (
- prepareGvarVariations(sourceCoordinates, model) if model is not None else []
- )
-
defaultSourceIndex = model.reverseMapping[0] if model is not None else 0
- defaultGlyph = glyph.layers[glyphSources[defaultSourceIndex].layerName].glyph
-
- ttGlyphPen = TTGlyphPointPen(None)
- defaultGlyph.path.drawPoints(ttGlyphPen)
- ttGlyph = ttGlyphPen.glyph()
+ defaultLayerGlyph = glyph.layers[
+ glyphSources[defaultSourceIndex].layerName
+ ].glyph
+
+ ttGlyph = None
+ gvarVariations = None
+ charString = None
+ charStringSupports = None
+
+ if not self.buildCFF2:
+ ttGlyph, gvarVariations = buildTTGlyph(
+ glyph, glyphSources, defaultLayerGlyph, model
+ )
+ else:
+ charString, charStringSupports = buildCharString(
+ glyph, glyphSources, defaultLayerGlyph, model
+ )
componentInfo = await self.collectComponentInfo(glyph, defaultSourceIndex)
+ leftSideBearing = computeLeftSideBearing(defaultLayerGlyph.path, self.buildCFF2)
+
return GlyphInfo(
ttGlyph=ttGlyph,
- hasContours=not defaultGlyph.path.isEmpty(),
- xAdvance=max(defaultGlyph.xAdvance or 0, 0),
+ gvarVariations=gvarVariations,
+ charString=charString,
+ charStringSupports=charStringSupports,
+ hasContours=not defaultLayerGlyph.path.isEmpty(),
+ xAdvance=max(defaultLayerGlyph.xAdvance or 0, 0),
xAdvanceVariations=xAdvanceVariations,
- variations=variations,
+ leftSideBearing=leftSideBearing,
variableComponents=componentInfo,
localAxisTags=set(localAxisTags.values()),
model=model,
@@ -397,12 +440,15 @@ async def setupComponentBaseInfo(self, baseGlyphName: str) -> dict[str, Any]:
)
async def buildFont(self) -> TTFont:
- builder = FontBuilder(await self.reader.getUnitsPerEm(), glyphDataFormat=1)
+ builder = FontBuilder(
+ await self.reader.getUnitsPerEm(),
+ glyphDataFormat=1,
+ isTTF=not self.buildCFF2,
+ )
builder.updateHead(created=timestampNow(), modified=timestampNow())
builder.setupGlyphOrder(self.glyphOrder)
builder.setupNameTable(dict())
- builder.setupGlyf(getGlyphInfoAttributes(self.glyphInfos, "ttGlyph"))
localAxisTags = set()
for glyphInfo in self.glyphInfos.values():
@@ -417,9 +463,19 @@ async def buildFont(self) -> TTFont:
if any(axis.map for axis in dsAxes):
builder.setupAvar(dsAxes)
- variations = getGlyphInfoAttributes(self.glyphInfos, "variations")
- if variations:
- builder.setupGvar(variations)
+ if not self.buildCFF2:
+ builder.setupGlyf(getGlyphInfoAttributes(self.glyphInfos, "ttGlyph"))
+ gvarVariations = getGlyphInfoAttributes(self.glyphInfos, "gvarVariations")
+ if gvarVariations:
+ builder.setupGvar(gvarVariations)
+ else:
+ charStrings = getGlyphInfoAttributes(self.glyphInfos, "charString")
+ charStringSupports = getGlyphInfoAttributes(
+ self.glyphInfos, "charStringSupports"
+ )
+ varDataList, regionList = prepareCFFVarData(charStrings, charStringSupports)
+ builder.setupCFF2(charStrings)
+ addCFFVarStore(builder.font, None, varDataList, regionList)
if any(glyphInfo.variableComponents for glyphInfo in self.glyphInfos.values()):
varcTable = self.buildVARC(axisTags)
@@ -427,9 +483,9 @@ async def buildFont(self) -> TTFont:
builder.setupHorizontalHeader()
builder.setupHorizontalMetrics(
- addLSB(
- builder.font["glyf"],
+ dictZip(
getGlyphInfoAttributes(self.glyphInfos, "xAdvance"),
+ getGlyphInfoAttributes(self.glyphInfos, "leftSideBearing"),
)
)
hvarTable = self.buildHVAR(axisTags)
@@ -439,6 +495,9 @@ async def buildFont(self) -> TTFont:
builder.setupOS2()
builder.setupPost()
+ if self.buildCFF2:
+ cffsubr.subroutinize(builder.font)
+
return builder.font
def buildVARC(self, axisTags):
@@ -643,6 +702,24 @@ def prepareXAdvanceVariations(glyph: VariableGlyph, glyphSources):
return [glyph.layers[source.layerName].glyph.xAdvance for source in glyphSources]
+def computeLeftSideBearing(path: Path | PackedPath, useTightBounds: bool) -> int:
+ boundsPen = (BoundsPen if useTightBounds else ControlBoundsPen)(None)
+ path.drawPoints(PointToSegmentPen(boundsPen))
+ return otRound(boundsPen.bounds[0]) if boundsPen.bounds is not None else 0
+
+
+def buildTTGlyph(glyph, glyphSources, defaultLayerGlyph, model):
+ ttGlyphPen = TTGlyphPointPen(None)
+ defaultLayerGlyph.path.drawPoints(ttGlyphPen)
+ ttGlyph = ttGlyphPen.glyph()
+
+ sourceCoordinates = prepareSourceCoordinates(glyph, glyphSources)
+ gvarVariations = (
+ prepareGvarVariations(sourceCoordinates, model) if model is not None else []
+ )
+ return ttGlyph, gvarVariations
+
+
def prepareSourceCoordinates(glyph: VariableGlyph, glyphSources):
sourceCoordinates = []
@@ -681,11 +758,72 @@ def prepareGvarVariations(sourceCoordinates, model):
return [TupleVariation(s, d) for s, d in zip(supports, deltas)]
-def addLSB(glyfTable, metrics: dict[str, int]) -> dict[str, tuple[int, int]]:
- return {
- glyphName: (xAdvance, glyfTable[glyphName].xMin)
- for glyphName, xAdvance in metrics.items()
- }
+def buildCharString(glyph, glyphSources, defaultLayerGlyph, model):
+ if model is None:
+ pen = T2CharStringPen(None, None, CFF2=True)
+ defaultLayerGlyph.path.drawPoints(PointToSegmentPen(pen))
+ charString = pen.getCharString()
+ charStringSupports = None
+ else:
+ if model.reverseMapping[0] != 0:
+ # For some reason, CFF2CharStringMergePen requires the first source
+ # to be the default, so let's make it so.
+ glyphSources = [glyphSources[i] for i in model.reverseMapping]
+ model = VariationModel(model.locations, model.axisOrder)
+ assert model.reverseMapping[0] == 0
+
+ pen = CFF2CharStringMergePen([], glyph.name, len(glyphSources), 0)
+ for sourceIndex, source in enumerate(glyphSources):
+ if sourceIndex:
+ pen.restart(sourceIndex)
+ layerGlyph = glyph.layers[source.layerName].glyph
+ drawPathToSegmentPen(layerGlyph.path, pen)
+
+ charString = pen.getCharString(var_model=model)
+ charStringSupports = tuple(
+ tuple(sorted(sup.items())) for sup in model.supports[1:]
+ )
+
+ return charString, charStringSupports
+
+
+def prepareCFFVarData(charStrings, charStringSupports):
+ vsindexMap = {}
+ for supports in charStringSupports.values():
+ if supports and supports not in vsindexMap:
+ vsindexMap[supports] = len(vsindexMap)
+
+ for glyphName, charString in charStrings.items():
+ supports = charStringSupports.get(glyphName)
+ if supports is not None:
+ assert "vsindex" not in charString.program
+ vsindex = vsindexMap[supports]
+ if vsindex != 0:
+ charString.program[:0] = [vsindex, "vsindex"]
+
+ assert list(vsindexMap.values()) == list(range(len(vsindexMap)))
+
+ regionMap = {}
+ for supports in vsindexMap.keys():
+ for region in supports:
+ if region not in regionMap:
+ regionMap[region] = len(regionMap)
+ assert list(regionMap.values()) == list(range(len(regionMap)))
+ regionList = [dict(region) for region in regionMap.keys()]
+
+ varDataList = []
+ for supports in vsindexMap.keys():
+ varTupleIndexes = [regionMap[region] for region in supports]
+ varDataList.append(buildVarData(varTupleIndexes, None, False))
+
+ return varDataList, regionList
+
+
+def dictZip(*dicts: dict) -> dict:
+ keys = dicts[0].keys()
+ if not all(keys == d.keys() for d in dicts[1:]):
+ raise ValueError("all input dicts must have the same set of keys")
+ return {key: tuple(d[key] for d in dicts) for key in keys}
def applyAxisMapToAxisValues(axis) -> tuple[float, float, float]:
@@ -787,3 +925,22 @@ def getGlyphInfoAttributes(glyphInfos, attrName):
glyphName: getattr(glyphInfo, attrName)
for glyphName, glyphInfo in glyphInfos.items()
}
+
+
+def drawPathToSegmentPen(path, pen):
+ # We ask PointToSegmentPen to output implied closing lines, then filter
+ # said closing lines again because we don't need them in the CharString.
+ # The reason is that PointToSegment pen will still output closing lines
+ # in some cases, based on input coordinates, even if we ask it not to.
+ # https://github.com/fonttools/fonttools/issues/3584
+ recPen = DropImpliedClosingLinePen()
+ pointPen = PointToSegmentPen(recPen, outputImpliedClosingLine=True)
+ path.drawPoints(pointPen)
+ recPen.replay(pen)
+
+
+class DropImpliedClosingLinePen(RecordingPen):
+ def closePath(self):
+ if self.value[-1][0] == "lineTo":
+ del self.value[-1]
+ super().closePath()
diff --git a/src/fontra_compile/compile_varc_action.py b/src/fontra_compile/compile_varc_action.py
index 09adb74..7b4dd07 100644
--- a/src/fontra_compile/compile_varc_action.py
+++ b/src/fontra_compile/compile_varc_action.py
@@ -31,7 +31,10 @@ async def process(
) -> None:
outputDir = pathlib.Path(outputDir)
outputFontPath = outputDir / self.destination
- builder = Builder(self.input)
+ assert self.input is not None
+ builder = Builder(
+ reader=self.input, buildCFF2=outputFontPath.suffix.lower() == ".otf"
+ )
await builder.setup()
ttFont = await builder.build()
ttFont.save(outputFontPath)
diff --git a/tests/data/MutatorSans.otf.ttx b/tests/data/MutatorSans.otf.ttx
new file mode 100644
index 0000000..261eec7
--- /dev/null
+++ b/tests/data/MutatorSans.otf.ttx
@@ -0,0 +1,2017 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ weight
+
+
+ width
+
+
+ V000
+
+
+ V001
+
+
+ weight
+
+
+ width
+
+
+ V000
+
+
+ V001
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1 blend
+ hlineto
+
+
+ 2 blend
+ rmoveto
+
+
+ 3 blend
+ hlineto
+
+
+ 8 blend
+ hvcurveto
+
+
+ 2 blend
+ rlineto
+
+
+ 4 blend
+ rlineto
+
+
+ 0 2 blend
+ rmoveto
+
+
+ 5 blend
+ hvcurveto
+
+
+ 1 blend
+ hmoveto
+
+
+ 4 blend
+ vhcurveto
+
+
+ 0 1 blend
+ hlineto
+
+
+ -30 -30 -69 callsubr
+
+
+ -84 callsubr
+ rmoveto
+
+
+ 0 2 blend
+ rlineto
+
+
+ 5 blend
+ hhcurveto
+ -11
+
+ -91 callsubr
+ 20
+
+ 60 60 -30 -30 -90 callsubr
+
+
+ -99 callsubr
+ -89 callsubr
+
+
+ 40 700 -40 0 280 100 0 100 0 0 -280 -100 -105 callsubr
+
+
+ 3 blend
+ vlineto
+ -144 64 -48 108
+
+ 78 248 247
+
+ 0 -100 0 2 blend
+ rlineto
+
+
+ 0 -280 -112
+
+ 0 100 0 2 blend
+
+
+ -100 0 1 blend
+ vmoveto
+
+
+ 260 36 -260
+
+ 350 630 35 -215 -99 callsubr
+ 44 24 276 87 -107 callsubr
+ -94 132 -33 47 -13 16 -22 0 -41 61 23 -34 79 -94 -54 24 20 16 8 -1 -35 -26 20 10 22 9 -16 -46 -14 -2 0 2 8 blend
+ rlinecurve
+ -19 2 -171 -107 -107 callsubr
+ -153 -195 -450 -183 156 10 -109 84 -106 callsubr
+ -89 callsubr
+ 20 -40 0 230 44 -71 callsubr
+ 400 -15 -68 -77 callsubr
+ 176 -90 -142 28 -42 -13 10 83 -10 -10 84 13 -10 78 12 -28 42 13 10 86 -10 -176 90 142 -104 callsubr
+ -100 -40 90 -400 15 68 0 -152 -76 390 28 -125 -78 callsubr
+ 53 -51 3 26 36 0 -28 12 0 46 22 0 43 48 -3 -36 -26 0 -28 24 -215 -54 54 -104 callsubr
+ -90 -390 -17 112 -107 callsubr
+
+
+ -107 callsubr
+ -121 -75 -74 callsubr
+ -118 118 -137 -75 75 -20 -36 20 20 -13 -20 20 -15 -20 137 75 -75 -20 -36 20 217 118 -118 -104 callsubr
+
+
+ 70 67 -41 100 94 -39 -68 callsubr
+ -170 -61 80 0 -280 -111 170 11 -30 -76 callsubr
+ -106 94
+
+ 3 blend
+ hlineto
+ 160 63 121 146 148 -63 120 -160 215
+
+ -107 callsubr
+ 119 55 -95 -133 -133 -55 -94 -119
+
+ 3 blend
+ vlineto
+ -122 -50 -34 -81 -81 -51 34 122
+
+ 0 -356 0 0 236 0 0 -354 0
+
+ -95 -263 -264 75 -98 121 -217
+
+ -1 -1 1 -0.28877 0
+
+ 20 20 146 -20 20 143 -20
+
+ 0 -212 -35 -106 callsubr
+ 100
+
+ 0 0 0 -0.15161
+
+ -99 callsubr
+ 40 700 -40 0
+
+ 4 blend
+ hvcurveto
+ 518 -40 -518
+
+ 100 180 -100 0 -140 0
+
+ -20 -25.7662 -36 20
+
+
+
+
+
+
+
+
+ 20 30 -30 0 -99 callsubr
+ 40 7 220 63 -107 callsubr
+ 140 700 375 -56 -169 -84 callsubr
+ rlineto
+ -35 -7 -195 -43 -107 callsubr
+ -90 -536 -235 96 79 60 -144 -60 -106 callsubr
+ 250 36 -250 450 220 -190 -6 174 16 -450 -220 190 -105 callsubr
+ 257 -200 585 23 -275 -54 -130 44 -106 callsubr
+ 44 9 296 121 -107 callsubr
+ -145 700 -375 29 151 -84 callsubr
+ rlineto
+ -39 -9 -281 -121 -107 callsubr
+ -17 -39 15 -73 5 3 -221 -3 -106 callsubr
+ 47 39 -47 3 223 147 -3 221 3 -3 -223 -147 -105 callsubr
+
+
+
+
+
+
+ 1 vsindex
+ 60 60 -21 -96 callsubr
+ 193 270 110 0 72 100 1 0 -193 -270 -110 -105 callsubr
+ 20 -367 0 164 230 140 0 -84 -86 -11 -106 callsubr
+ 130 610 -36 -65 -393 -107 callsubr
+ 105 49 -64 -86 -90 -52 -57 -112 14 -55 -76 -1 6 -18 -26 4 0 45 57 0 0 34 38 4 4 41 47 1 -3 20 29 -7 -4 37 46 5 -7 60 83 -6 -104 callsubr
+ -120 -36 110 -620 29 55 403 0 -145 -202 0 620 14 6 -280 3 blend
+ hlineto
+ 153 60 79 104 90 -50 78 -120 10 7 73 102 -7 3 -7 -11 17 4 11 15 -4 -4 23 32 4 0 25 36 0 0 -4 -5 -20 -4 -12 -17 4 -3 19 26 3 6 5 7 -6 9 blend
+ hvcurveto
+ 20 -11 -40 -22 -30 20 -7 -33 -46 7 -103 callsubr
+ 89 16 41 73 78 5 -8 -12 -5 10 0 -1 -10 -2 22 31 22 -5 -15 -21 5 0 29 41 0 5 blend
+ vvcurveto
+ 101 -42 82 -161 0 34 47 0 -21 -20 -27 1 0 5 7 0 1 -53 -75 -30 4 blend
+ vhcurveto
+ -100 -36 110 -570 -14 -5 279 0 -136 -190 0 570 -22 -45 -392 -105 callsubr
+ 120 34 -61 -86 -86 -49 -63 -105 -1 -65 -91 23 21 -8 -11 -11 0 42 51 1 0 39 45 4 0 35 38 -4 -6 19 26 -4 0 47 58 9 -14 54 76 -8 -104 callsubr
+ -110 -570 22 45 392 -107 callsubr
+
+
+ 410 264 773 102 -379 13 114 -29 -106 callsubr
+ -179 -13 -57 -59 -83 4 85 14 -27 11 13 -130 33 93 -17 29 15 -193 23 162 -93 callsubr
+ -39 3 -47 -107 callsubr
+ -94 -60 -87 callsubr
+ 60 75 94 -218 38 168 -138 40 92 20 -34 -20 -20 -143 20 -20 -146 20 138 -40 -92 20 -33 -20 218 -38 -168 -104 callsubr
+ 11 39 -3 47 -107 callsubr
+ 82 57 -56 -176 14 192 -22 -162 129 -33 -92 -17 28 15 6 86 13 28 -12 -13 -100 callsubr
+ 39 5 1 251 136 -1 24 18 -103 callsubr
+ 191 -17 -71 72 -104 -5 48 -18 -27 -2 4 -130 -67 67 17 42 -28 -193 -107 104 -93 callsubr
+ -39 -14 -136 -80 callsubr
+ 11 39 14 136 -107 callsubr
+ 105 71 74 194 16 194 106 -103 130 68 -67 18 43 -28 -3 49 -18 27 2 -5 -100 callsubr
+
+
+ 60 60 -96 callsubr
+ 249 131 0 100 0 0 -249 -131 -105 callsubr
+ 26 -36 -6 207 143 0 -218 -101 callsubr
+ 121 309 -39 -168 -107 callsubr
+ 113 81 -65 -247 -248 -81 -68 -113 200 -57 -150 117 -61 -71 -20 23 -72 callsubr
+ -117 61 71 -20 24 20 -200 57 150 -104 callsubr
+ -121 -36 121 -309 31 176 0 -218 0 309 -23 -132 -105 callsubr
+ 138 98 88 264 263 -98 85 -138 200 101 -101 115 53 -53 20 43 -27 -20 8 27 -20 6 27 -115 -53 53 20 43 -27 -200 -101 101 -104 callsubr
+ -121 -309 31 124 -107 callsubr
+
+
+ 1 vsindex
+ 60 60 -14.31456 -20 -40 -69 callsubr
+ 178.932 250 130 0 71.5728 100 0 0 -178.932 -250 -130 -105 callsubr
+ 20 -36 0 50.10097 70 0 0 -167.48035 -234 -101 callsubr
+ -82 callsubr
+ 540 128.83104 180 -55 0 167.48035 234 0 -540 -128.83104 -180 55 -105 callsubr
+ -700 0 -71.5728 -83 callsubr
+ 260 36 -260 540 128.83104 180 -55 0 167.48035 234 0 -540 -128.83104 -180 55 -105 callsubr
+ 0 298 0 0.2136 0 0 0 -204.48035 -253 -101 callsubr
+ 240 36 -240 480 119 166 -50 0 146 134 0 -480 -119 -166 50 -105 callsubr
+
+
+ 1 vsindex
+ 60 60 -14 -96 callsubr
+ 179 280 100 0 72 100 0 0 -179 -280 -100 -105 callsubr
+ 20 -36 0 50 80 -10 0 -168 -214 -20 2 blend
+ rmoveto
+ -82 callsubr
+ 580 129 140 -55 0 168 214 20 -580 -129 -140 55 -105 callsubr
+ -386 -20 -89 -139 -20 1 blend
+ vmoveto
+ 240 36 -240 580 119 146 -155 0 146 174 20 -580 -119 -146 155 -105 callsubr
+
+
+ 1 vsindex
+ 250 300 220 82 170 0 0 -24 5 10 -106 callsubr
+ 159 -84 600 25 8 -500 0 24 -5 -10 2 blend
+ hlineto
+ 9 9 66 91 91 1 blend
+ -216 rlineto
+ 28 -9 80.3677 85 139 -107 callsubr
+ 0 335 0 -0.3677 0 0 -5 104 95 -5 -103 callsubr
+ -196 -600 -171 -184 270 -107 callsubr
+ 160 -51 603 5.31882 -48 -449 -2 -36.72157 -1 6 -106 callsubr
+ -199 -13 -57 -59 -83 24 75.15144 105 -6 -27 7.873 11 13 -130 19.32466 27 99 -17 20.75612 29 5 -193 6.44156 9 176 -93 callsubr
+ -89 2.14719 3 3 -107 callsubr
+ -94 -62 -87 callsubr
+ 71 75 94 -218 27.19766 38 168 -136 30.06058 42 90 20 -24.33475 -34 -20 -20 -102.3491 -143 20 -20 -104.50212 -146 20 127 -33.63922 -47 -85 20 -23.61319 -33 -20 218 -19.32466 -27 -179 -104 callsubr
+ 11 89 -2.14719 -3 -3 -107 callsubr
+ 82 0 48 -56 14 -176 39 5 192 -20.2524 -18 -166 0 -0.38681 0 0 138 -13 -22.6612 -102.3388 -17 19 32.75406 10.24594 28 -5 -12.3388 -12.6612 6 93 101.24594 -2.24594 1 158 221 166 -1 17 4 38 8 blend
+ rcurveline
+ 191 -17 -62 72 -104 -5 -2 48 -18 -27 15 -2 4 -139 -66.75343 -71 71 17 36.5728 42 -28 -193 -73 -102 99 -93 callsubr
+ -89 -10.02019 -14 -86 -107 callsubr
+ -121 -84 -74 callsubr
+ -84.4559 -118 118 -128 -47.23805 -66 66 -66 callsubr
+ 20 -9.30446 -13 -20 20 -10.73592 -15 -20 137 53.6796 75 -75 -66 callsubr
+ 217 84.4559 118 -118 -104 callsubr
+ 11 89 10.02019 14 -94 1 blend
+ hlineto
+ 105 58 74 214 6 194 72.28853 101 -98 133 54.39532 76 -65 18 30.7763 43 -18 -23 20.75612 29 2 37 8.58873 12 -15 -100 callsubr
+
+
+ -92 callsubr
+ -366 3 90 57 0 -174 10 -106 callsubr
+ 300 36 -300 561 170 -131 0 224 0 -561 -170 131 -105 callsubr
+ 280 -370 557 -20 -167 0 -150 -10 -106 callsubr
+ -89 callsubr
+
+
+ 140 310 -20 -130 -90 callsubr
+ -80 -36 -250 -10 100 0 -244 30 -106 callsubr
+ 200 36 -200 490 300 -90 0 244 -30 -490 -300 90 -105 callsubr
+ -700 0 -83 callsubr
+ 200 36 -200 490 300 -90 0 244 -30 -490 -300 90 -105 callsubr
+
+
+ -91 callsubr
+
+
+ 100 320 60 250 112 113 57 -30 2 blend
+ rmoveto
+ 380 -40 -380 -113 43 30 -85 callsubr
+ 113 -43 -30 3 blend
+ vlineto
+ 172 -330 298 175 -72 -113 -57 30 -106 callsubr
+ 106 65 48 144 183 145 -81 117 33 6 -79 callsubr
+ 29 -117 43 70 -64 23 31 -183 59 117 -182 61 114 -116 44 69 51.97546 -23 -36.90138 78.02454 -94 -44.09862 8 blend
+ vhcurveto
+ 58 -40 -58 -27 -19 26 -85 callsubr
+ 27 29 -36 -88 callsubr
+ -73.03868 -64 23.52126 117 31 8 -56.96132 -57 37.47874 181 144 -80 -98 callsubr
+
+
+ 232 238 145 -102 1 blend
+ -10 rmoveto
+ 106 65 48 144 108.7628 145 -43.7628 71.2372 33 28.7628 60.53847 67 -38.53847 79.46153 94 -31.46153 -68 callsubr
+ -140 -61 70 0 -280 -111 140 11 -40 -76 callsubr
+ -84.9855 94 35.9855 -71.20544 43 47.20544 -55.0145 23 34.0145 -108.79456 59 79.79456 -132.18182 61 101.18182 -85.81818 44 61.81818 43.01695 -23 -28.01695 56.98305 -94 -5.98305 8 blend
+ vhcurveto
+ 98 -40 -98 -50 38 -17 0 -280 -82 50 12 -45 -88 callsubr
+ -52.45589 -94 17.45589 86.72974 31 3.27026 -47.54411 -67 48.54411 131.27026 144 -85.27026 -98 callsubr
+
+
+ 122 163 104 -164 1 blend
+ -10 rmoveto
+ 125 76 58 174 164 126 -44 106 75 -24 60 57 -31 70 64 -9 4 blend
+ hvcurveto
+ 478 -40 -478 -130 -21 40 0 -282 -109 130 87 -76 3 blend
+ vlineto
+ -154 -61 -42 -100 -18 -17 2 4 -15 -74 59 43 -106 23 78 -56 2 43 -164 22 136 -38 -19.88889 54.88889 -34 -17.11111 19.11111 4 1 -6 6 6 -8 -31 -23 17 9 blend
+ vhcurveto
+ -12 -35 0 -38 6 -2 -232 -23 -103 callsubr
+ -5 19 21 -2 22 -5 -15 17 31 37 -35 34 45 -45 -3 -8 10 38 52 -54 5 blend
+ hhcurveto
+
+
+ -91 callsubr
+ 14 -366 0 280 -30 -39 -122 39 -106 callsubr
+ 71 20 -33 106 -107 callsubr
+ 213 -334 416 -115 -248 39 22 -39 -103 callsubr
+ 49 34 302 127 -107 callsubr
+ -247 370 -6 0 -443 85 136 -45 163 45 -1 -267 -35 3 -81 -3 -102 callsubr
+ -80 -26 28 -86 -107 callsubr
+ 50 -17 20 -7 73 2 -9 -2 -106 callsubr
+ 27 -15 248 362 14 220 -60 4 -93 -34 446 -56 -29 36 120 -6 -102 callsubr
+ -46 -20 -286 -120 -107 callsubr
+
+
+ -92 callsubr
+ -700 0 80 -10 0 -100 -101 callsubr
+ -82 callsubr
+ 530 140 -30 0 214 30 -530 -140 30 -105 callsubr
+
+
+ 60 60 -96 callsubr
+ 210 70 0 100 0 0 -210 -70 -105 callsubr
+ 410 -700 624 362 -218 0 -100 -101 callsubr
+ 700 -40 -700 0 100 0 0 -210 -70 0 -100 0 3 blend
+ vlineto
+ 23 658 -5 113 -15 6 -229 -31 -106 callsubr
+ -23 42 -170 -358 5 -113 15 -6 329 31 -331 21 186 -81 109 77 -102 callsubr
+ 17 31 9 -7 -107 callsubr
+ -177 358 -22 -49 175 -352 -324 28 179 81 -109 -77 4 -114 16 13 -322 -38 304 55 -216 -71 41 113 6 blend
+ rlineto
+ 25 7 59 43 -107 callsubr
+
+
+ 60 60 -30 -30 -99 callsubr
+ 35 700 -35 5 215 65 0 100 0 -5 -215 -65 -105 callsubr
+ 16 -54 7 54 127 18 -226 -84 -106 callsubr
+ 289 -646 19 54 -289 646 588 81 -298 -18 126 84 0 161 -64 -17 226 83 -590 -81 300 17 -126 -83 6 blend
+ rlineto
+ 270 -700 590 -80 -235 0 -100 -101 callsubr
+ 35 700 -35 5 215 65 0 100 0 -5 -215 -65 -105 callsubr
+
+
+ 246 384 163 -203 1 blend
+ -10 rmoveto
+ 11 49 14 126 -107 callsubr
+ 120 76 98 264 263 -76 95 -120 218 119 -119 137 75 -75 20 36 -20 -20 15 20 -20 13 20 -137 -75 75 20 36 -20 -218 -119 119 -104 callsubr
+ -11 -49 -14 -126 -80 callsubr
+ 0 36 0 9 45 0 228 -101 callsubr
+ -94 -60 -87 callsubr
+ 60 75 94 -218 38 168 -138 40 92 20 -34 -20 -20 -143 20 -20 -146 20 138 -40 -92 20 -33 -20 218 -38 -168 -104 callsubr
+ 11 49 -3 37 -107 callsubr
+ 95 59 -75 -247 -248 -59 -78 -95 218 -39 -168 139 -39 -93 -20 33 -72 callsubr
+ -139 39 93 -20 34 20 -218 39 168 -104 callsubr
+
+
+ -92 callsubr
+ -40 0 230 0 -71 callsubr
+ 390 -25 -48 -77 callsubr
+ 186 -90 -152 32 -42 -17 10 82.97183 -9.97183 -10 84.02817 12.97183 -10 78.32076 11.67924 -32 42 17 10 85.67924 -9.67924 -186 90 152 -104 callsubr
+ -100 -40 90 -390 25 48 0 -213 -35 390 8 -105 -78 callsubr
+ 73 -71 3 16 46 0 -17.73203 10.73203 0 66.73203 22.26797 0 62.30247 21.69753 -3 -16 -46 0 -17.30247 10.30247 -215 -72 72 -104 callsubr
+ -90 -390 -9 104 -107 callsubr
+
+
+ 330 378 80 -228 1 blend
+ -130 rmoveto
+ 44 0 266 110 -107 callsubr
+ -99 143 -32 -18 0 -11 -30 0 157 0 0 -251 -137 0 18 0 -102 callsubr
+
+
+ -81 callsubr
+
+
+ -81 callsubr
+
+
+ 2 vsindex
+ 349 157 731 329 -219 69.90141 34 96 -34 22.23555 -106 callsubr
+ -1 81 -49 55 -82 65 -50 40 1 1 -1 0.15161 45 128 -45 29.6887 -31 -61 16 -14.82312 -8 3 11 1.70844 -212 -65 -9 1.49152 -57 -54 55 -8.34697 -164 -2 38 -6.74109 -34 -36 34 -4.9411 8 blend
+ rcurveline
+ -62 49 -21 47 52 -147 -13 86 7.0727 -43 -43 40 -6.65053 -118 15 113 18.1315 -19 -46 21 -10.31165 54 -42 -54 -19.92839 5 blend
+ vvcurveto
+ 83 44 44 83 14 -72 -14 -18.3863 69 -31 -58 -15.72575 13 -40 -13 -14.14648 185 -34 -145 -27.33028 -98 callsubr
+ 8 63 44 89 13.53165 -107 callsubr
+ 49 40 -9 -24 40 161 33 -94 -2.55385 95 41 -29 7.70268 -34 0 34 4.21446 -30 14 30 7.57117 63 20 -14 3.77553 -100 callsubr
+ 17 37 5 19 -6 4.49112 -4 195 4 54.21736 -103 callsubr
+ 19 -37 -37 15 -62 39 -5 -40 -6.3329 -75 -26 32 -3.19858 -123 -71 49 -13.48987 27 1 -26 -2.94553 -139 4 100 13.49054 5 blend
+ hhcurveto
+ -7 -61 -37 -25 -3.6745 -107 callsubr
+ -118 -58 -66 -101 0 -169 -120 -25 -36.15671 -75 -59 30 -12.38612 0 -39 24 -6.86145 -23 -75 -1 -21.69579 -70 callsubr
+ 5 blend
+ hvcurveto
+ 0 -81 44 -57 82 -65 50 -40 -70 callsubr
+ -36 -105 36 -24.46725 45 81 -22 19.74135 6 -4 -11 -1.98393 202 51 -15 12.19203 57 52 -52 7.40297 164 1 -23 -12.18988 34 35 -34 5.43027 8 blend
+ rcurveline
+ 71 -57 18 -36 -64 159 -4 -104 -13.98608 51 50 -47 7.4714 101 -5 -91 -12.65106 16 38 -20 8.62357 -49 51 49 19.9691 5 blend
+ vvcurveto
+ -62 -44 -54 -83 -50 54 50 21.07109 -78 30 67 16.56522 -3 50 3 14.14648 -245 34 205 34.76341 -98 callsubr
+ -8 -63 -43 -78 -11.8934 -107 callsubr
+ -53 -43 10 26 -43 -124 -42 46 -5.90268 -97 -46 25 -9.59871 32 -2 -32 -4.51352 29 -13 -29 -7.17595 -63 -25 7 -5.96666 -100 callsubr
+ -17 -37 0 -19 1 -5.10217 4 -198 -4 -55.04384 -103 callsubr
+ -20 40 39 -17 67 -39 5 39 6.2843 75 31 -20 6.06728 122 83 -47 16.96371 -24 2 24 3.44896 100 -1 -49 -6.27899 5 blend
+ hhcurveto
+ 7 61 37 42 5.78055 -107 callsubr
+ 118 59 72 95 -1 229 164 -65 37.12886 83 14 -25 0.75981 0 48 -18 11 32 48 -14 11.48944 1 1 -1 0.15161 5 blend
+ hvcurveto
+
+
+ 3 vsindex
+ 358 157 737 368 -180 -22.29459 11.4528 34 96 -34 11.79451 2.65941 -106 callsubr
+ -1 81 -46 62 -85 58 -58 40 1 1 -1 0.28877 0.01683 45 119 -66 34.16841 -7.8 -34 -65 50 -26.17567 -1.54666 -15 -18 24 6.48523 29.11818 -209 -83 36 -10.26065 -2.48306 -50 -48 46 -4.69652 -2.98738 -176 -11 -87 80.20383 -30.01756 -34 -36 36 -3.369 -1.87216 8 blend
+ rcurveline
+ -66 45 -17 51 63 -143 -15 138 -31.60442 28.97484 -40 -40 36 -3.52135 -3.82814 -112 10 118 0.25461 0.54572 -22 -49 24 -6.24628 -3.45816 43 -53 -43 -8.37282 -6.45656 5 blend
+ vvcurveto
+ 62 32 54 79 35 -51 -35 -8.37698 -3.06715 71 -18 -71 1.2856 -1 3 -50 -3 -6.83139 -1.94861 189 -25 -170 0.31526 -0.34122 -98 callsubr
+ 5 126 23 93 -36.10632 15.57735 -107 callsubr
+ 96 19 -59 -135 0 159 -42 -96 12.62415 -56.23752 72 -8 -51 1.91591 -8.98091 4 43 5 5.19882 11.09567 -3 98 -8 13.82176 28.96066 12 0 -12 0.40926 -0.26755 -100 callsubr
+ 39 0 0 221 76 -18.91333 55.7757 0 0 0 0.6738 -0.38344 -103 callsubr
+ 174 0 -39 58 -114 -20 48 49 -0.73352 -49.93373 -9 0 9 0.054 -0.2495 -61 -52 9 26.95068 -1.54062 17 40 -28 -16.773 12.64397 -177 -111 48 -24.1535 -3.07494 5 blend
+ hhcurveto
+ -7 -121 -16 -11 74.72604 -0.44324 -107 callsubr
+ -105 -44 -72 -95 1 -182 -120 10 -38.58452 -3.32526 -79 -78 39 -8.96208 -2.46606 6 -30 15 -3.45882 -0.38173 -29 -84 8 -10.78777 -2.85182 -73 callsubr
+ 5 blend
+ hvcurveto
+ 1 -81 40 -64 85 -58 58 -40 -73 callsubr
+ -36 -98 50 -26.0849 -14.14938 39 87 -18 10.52098 3.02344 12 4 -13 -4.19305 -4.5906 199 68 -32 8.39786 1.32254 51 47 -44 2.13565 0.80103 176 9 84 -85.39963 36.33113 34 35 -33 2.77138 -1.23734 8 blend
+ rcurveline
+ 74 -51 15 -43 -63 156 -1 -159 28.55887 -35.8711 45 46 -41 3.65569 3.90088 104 -1 -101 -0.03444 0.01007 23 43 -28 7.11676 1.65509 -50 50 50 8.62141 13.67339 5 blend
+ vvcurveto
+ -62 -37 -54 -71 -50 54 50 8.96626 0.93427 -65 21 66 -1.09013 0.4896 -3 50 3 6.83139 5.48741 -257 39 217 1.73631 1.08038 -98 callsubr
+ -8 0 -83 -26 -227 90.08673 -47.60095 0 0 0 0 0.46121 -103 callsubr
+ -104 -20 66 128 0 -107 47 97 -14.12784 12.96083 -184 9 151 -17.89468 35.20593 -34 -40 33 -18.60399 -8.85864 33 -102 -12 -13.5339 -25.60909 0 0 0 -0.96652 -0.11095 -100 callsubr
+ -40 0 -240 -66 -8.18893 -5.89154 -107 callsubr
+ -186 0 62 -46 92 24 -37 -93 45 20.73647 4 0 -4 1.78328 -0.95058 83 58 -30 -62.64705 2.17653 -21 -37 50 -21.73412 7.28648 217 108 -145 72.49706 3 5 blend
+ hhcurveto
+ 7 81 24 269 -144.39244 0.66486 -107 callsubr
+ 105 53 72 95 -1 242 137 -145 85.28868 3.7952 69 51 -85 32.85559 1.41281 0 46 -16 5.7626 1.27429 32 50 -16 6.10808 1.3851 1 1 -1 -0.6738 0.03645 -100 callsubr
+
+
+ 200 350 -50 -80 -90 callsubr
+ -170 -36 -340 40 70 0 -214 -60 -106 callsubr
+ 380 36 -380 680 200 -40 0 214 60 -680 -200 40 3 blend
+ hlineto
+
+
+ 232 358 145 -72 1 blend
+ -10 rmoveto
+ 106 65 48 144 183 145 -81.42715 117 33 6.42715 -79 callsubr
+ 29.11732 -117 43 69.51163 -64 23 30.88268 -183 59 117.48837 -182 61 114.48837 -116 44 68.51163 64 -23 -30.88268 106 -94 -29.11732 8 blend
+ vhcurveto
+ 518 -40 -518 -170 -11 30 -85 callsubr
+ 170 61 -80 -88 callsubr
+ -100 -94 39 117 31 8.45772 -70 -67 41 181 144 -80.45772 -98 callsubr
+
+
+ 378 700 752 352 -182 -95 callsubr
+ -41 -5 -209 -75 -107 callsubr
+ -130 -700 -371 46 125 -86 callsubr
+ 36 9 184 51 -107 callsubr
+ -178 700 -356 -88 192 -95 callsubr
+ -45 -9 -295 -121 -107 callsubr
+ 135 -700 373 -19 -119 -86 callsubr
+ 40 9 280 121 -107 callsubr
+ 40 39 -19 50 -21 -3 221 3 2 blend
+ rmoveto
+ -70 -39 70 10 -200 -160 3 -221 -3 -10 200 160 -105 callsubr
+
+
+ 500 700 824 377 -352 -95 callsubr
+ -42 1 -218 -119 -107 callsubr
+ -87 -638 -210 39 184 0 108 -94 callsubr
+ 6 6 36 -24 -107 callsubr
+ -94 638 -211 44 185 0 -108 -94 callsubr
+ -38 12 -167 -82 -107 callsubr
+ -95 -638 -196 50 173 -10 108 10 -103 callsubr
+ 8 9 34 -27 -107 callsubr
+ -93 638 -217 39 198 10 -108 -10 -103 callsubr
+ -43 0 -246 -144 -107 callsubr
+ 107 -700 226 -5 -172 -86 callsubr
+ 45 -27 243 181 -107 callsubr
+ 89 639 -10 0 95 -639 204 -43 -180 17 -230 43 -6 -32 -16 -1 0 1 220 -38 -190 -16 230 -44 6 blend
+ rlineto
+ 45 -28 272 198 -107 callsubr
+
+
+ 337 583 23 -173 -99 callsubr
+ 45 15 335 95 -107 callsubr
+ -169 364 -141 336 -291 -70 79 5 110 -1 -269 30 81 -5 -10 1 4 blend
+ rlineto
+ -45 -15 -335 -95 1 blend
+ hlineto
+ 160 -363 285 78 -94 14 -87 10 -103 callsubr
+ -167 -337 -286 -71 95 -16 -13 -8 -106 callsubr
+ 40 0 142 332 13 4 155 364 8 190 212 2 0 -2 279 -57 -161 19 -20 -10 -1 220 -106 -6 30 -28 292 27 -13 -13 90 38 8 blend
+ rlineto
+ -40 -10 -190 -210 -107 callsubr
+ -130 -337 -16 -6 -287 41 153 5 78 -66 4 -212 89 8 -44 42 -102 callsubr
+
+
+ 400 700 560 330 -100 -95 callsubr
+ -41 -9 -189 -111 -107 callsubr
+ -154 -490 25 0 -262 -16 127 -10 -110 20 -13 175 93 -29 0 29 -102 callsubr
+ -163 490 -263 -8 69 39 110 -49 -106 callsubr
+ -47 -3 -302 -78 -107 callsubr
+ 170 -490 38 0 281 30 -106 -39 -110 49 -15 252 115 29 0 -29 -102 callsubr
+ 2 44 9 28 -9 -33 26 133 -106 callsubr
+ -40 -254 40 0 -280 -100 43 -16 -153 0 280 100 3 blend
+ hlineto
+
+
+ 60 36 60 -30 -30 0 214 30 -106 callsubr
+ 35 -10 285 638 -35 10 0 315 170 -10 -10 -70 640 -55 -230 10 -318 10 0 -315 -170 10 10 70 6 blend
+ rlineto
+ -285 -10 -640 55 230 -10 -10 -70 -106 callsubr
+ 320 36 -320 640 260 -60 0 214 30 -640 -260 60 3 blend
+ hlineto
+ -700 0 -83 callsubr
+ 320 36 -320 640 260 -60 0 214 30 -640 -260 60 3 blend
+ hlineto
+
+
+ 50 730 -20 -30 20 0 100 -101 callsubr
+ 150 8 40 120 40 0 -8 -94 callsubr
+ 32 0 88 0 1 blend
+ vlineto
+ -150 -10 -40 -120 -40 0 -20 -94 callsubr
+
+
+ 137 271 0 79 0 -250 55 -25 -106 callsubr
+ 29 0 373 -97 callsubr
+ 6 269 500 66 40 1 blend
+ rlineto
+ -41 0 -374 -97 callsubr
+ -31 -210 0 -168 0 -500 50 -40 -106 callsubr
+ 52 -190 50 189 0 356 0 0 -236 0 0 354 0 0 236 0 -102 callsubr
+
+
+ 136 371 0 195 -75 0 267 -38 -106 callsubr
+ -29 0 -468 95 1 blend
+ vlineto
+ 423 500 -196 425 1 blend
+ -6 rlineto
+ 41 0 469 -95 1 blend
+ vlineto
+ -364 31 -500 237 -350 0 130 38 -106 callsubr
+ -190 -52 189 -50 0 -236 0 -75 callsubr
+ -102 callsubr
+
+
+ 308 345 625 -71 300 0 -183 38 -106 callsubr
+ 29 0 468 -95 1 blend
+ vlineto
+ -298 -625 71 -300 1 blend
+ 6 rlineto
+ -41 0 -469 95 1 blend
+ vlineto
+ 239 -31 625 -112 225 0 -130 -38 -106 callsubr
+ 190 52 -189 50 0 236 0 0 356 -1 0 -236 0 0 354 1 4 blend
+ rlineto
+
+
+ 165 409 0 451 0 250 46 -30 2 blend
+ rmoveto
+ -29 0 -373 -97 callsubr
+ -6 -269 -500 -66 -40 1 blend
+ rlineto
+ 41 0 374 -97 callsubr
+ 31 210 0 168 0 500 -50 40 2 blend
+ rmoveto
+ -52 190 -50 -189 -75 callsubr
+ 0 -236 0 -102 callsubr
+
+
+
+
+ 111 60 109 -30 -99 callsubr
+ 120 -50 -120 -67 callsubr
+ -100 -180 100 3 blend
+ vlineto
+ 32 -8 -11 20 0 47 0 0 -8 0 0 3 0 0 8 0 4 blend
+ -22 -105 12 0 -50 0 0 60 0 2 blend
+ -2 rlineto
+
+
+
+
+ 50 730 0 10 0 0 110 -101 callsubr
+ 40 60 -40 0 150 0 0 65 0 0 -150 0 3 blend
+ hlineto
+
+
+
+
+ 50 vmoveto
+ -50 50 vlineto
+ 5 vsindex
+ -50 750 750 750 -750 0 0 -750 -103 callsubr
+
+
+ 60 60 -30 -30 -99 callsubr
+ 50 120 -50 0 140 0 -67 callsubr
+ 3 blend
+ hlineto
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 7 vsindex
+ 70 278 0 -241 0 1 blend
+ rmoveto
+ 239 143 0 -97 callsubr
+ 0 102 70 0 0 0 70 0 0 -102 0 0 -70 0 0 102 -102 callsubr
+ 284 -175 0 241 0 -143 0 0 2 blend
+ -76 -134 vlineto
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ wght
+ 0x0
+ 100.0
+ 100.0
+ 900.0
+ 256
+
+
+
+
+ wdth
+ 0x0
+ 0.0
+ 0.0
+ 1000.0
+ 257
+
+
+
+
+ V000
+ 0x1
+ -1.0
+ 0.0
+ 1.0
+ 258
+
+
+
+
+ V001
+ 0x1
+ -1.0
+ 0.0
+ 1.0
+ 259
+
+
+
+
diff --git a/tests/data/MutatorSans.ttx b/tests/data/MutatorSans.ttf.ttx
similarity index 100%
rename from tests/data/MutatorSans.ttx
rename to tests/data/MutatorSans.ttf.ttx
diff --git a/tests/data/figArnaud.otf.ttx b/tests/data/figArnaud.otf.ttx
new file mode 100644
index 0000000..7a24748
--- /dev/null
+++ b/tests/data/figArnaud.otf.ttx
@@ -0,0 +1,2861 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ wght
+
+
+ V000
+
+
+ V001
+
+
+ V002
+
+
+ V003
+
+
+ V004
+
+
+ V005
+
+
+ V006
+
+
+ wght
+
+
+ V000
+
+
+ V001
+
+
+ V002
+
+
+ V003
+
+
+ V004
+
+
+ V005
+
+
+ V006
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0 0 0
+
+ 2 blend
+ rmoveto
+
+
+ -107 callsubr
+ 0
+
+ 2 blend
+ rlineto
+
+
+ 16 blend
+ vhcurveto
+
+
+ -30 -105 callsubr
+ 40 -180 0 100
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 307 162 260 190 0 1 -106 callsubr
+ 109 -48 59 -88 -83 -53 -66 -102 -110 50 -64 86 82 54 69 105 -5 -4 -45 -51 5 9 -65 -49 -61 -52 -49 -48 -3 -3 3 -2 5 4 47 50 -5 -5 63 50 62 54 48 46 3 0 -3 1 -103 callsubr
+ -30 -1 0 -170 0 28 -106 callsubr
+ -94 -39 -54 -67 -67 -39 54 94 94 39 54 67 67 39 -54 -94 4 50 -46 27 -4 31 -64 43 -64 43 -46 27 4 -31 -4 -50 -4 -54 46 -25 4 -27 64 -45 64 -43 46 -27 -4 31 4 50 -103 callsubr
+ 15 299 -10 175 0 -39 -106 callsubr
+ 97 -44 55 -77 -71 -50 -62 -90 -97 44 -54 77 72 49 61 90 -2 0 -39 -52 2 10 -61 -53 -59 -59 -41 -46 -1 -3 1 -7 3 0 39 47 -3 -5 61 58 59 64 41 41 1 -3 -1 8 -103 callsubr
+ -30 -1 0 -165 0 -34 -106 callsubr
+ -81 -34 -48 -57 -57 -34 48 81 79 35 49 56 56 35 -49 -79 2 41 -40 23 -2 26 -60 37 -60 39 -40 21 2 -23 -2 -44 -1 -38 40 -24 1 -28 60 -36 60 -36 40 -24 -1 28 1 38 -103 callsubr
+
+
+ 53 343 30 10 -40 -46 -106 callsubr
+ 28 0 0 137 14 0 2 blend
+ rlineto
+ 257 -28 26 46 0 -137 2 blend
+ vlineto
+ 190 -25 240 141 0 -120 -106 callsubr
+ 25 -190 -25 0 120 -240 -141 0 -120 3 blend
+ vlineto
+ -33 -547 10 -20 32 143 -106 callsubr
+ -26 26 35 -14 39 -20 -12 23 27 42 25 -12 -11 50 41 5 blend
+ hhcurveto
+ 88 53 71 119 121 -51 69 -90 -24 -21 -6 -13 -22 65 44 50 46 5 17 -5 3 -6 -6 -49 -35 6 6 -66 -43 -50 -28 -44 -39 -11 -11 -20 -12 -31 -18 13 blend
+ hvcurveto
+ -16 -9 -84 1 blend
+ vlineto
+ 7 30 16 3 17 25 2 16 1 54 10 15 1 60 9 5 blend
+ hhcurveto
+ 75 40 -58 -107 -106 -39 -59 -71 -31 -29 11 21 -22 60 -13 50 -4 -8 34 8 67 7 70 -51 10 -7 35 -64 29 -48 -6 -40 1 11 0 21 1 -29 -14 13 blend
+ hvcurveto
+
+
+ 2 vsindex
+ 212 20 0 -10 0 0 -50 220 1 blend
+ hmoveto
+ 28 -105 callsubr
+ 0 162 0 1 blend
+ 600 -28 -105 callsubr
+ 0 -162 0 1 blend
+ hlineto
+ -197 -455 -102 callsubr
+ -65 -105 callsubr
+ 2 blend
+ rmoveto
+ 297 25 -297 30 0 0 100 0 120 250 0 0 130 -105 callsubr
+ -30 0 0 -100 0 -120 -250 3 blend
+ hlineto
+ 29 181 -105 callsubr
+ 0 4 1 blend
+ hmoveto
+ 188 412 -151 -107 callsubr
+ -10 -40 176 -341 -100 -64 0 200 -6 3 -104 callsubr
+ 18 -20 341 0 -1 0 -200 6 -3 -105 callsubr
+ 10 0 0 2 blend
+ vlineto
+ -197 -430 -102 callsubr
+ 65 -105 callsubr
+ 2 blend
+ rlineto
+
+
+ 3 vsindex
+ 279 414 0 280 201 0 -10 -25 -106 callsubr
+ 127 -39 71 -81 -80 -44 -68 -123 -107 39 -62 78 47 36 24 41 9 0 -2 0 0 -55 -54 0 12 25 0 -60 -54 0 -67 -51 0 -58 -52 0 -14 -26 0 6 -10 0 -1 -10 0 56 48 0 -11 -24 0 61 37 0 68 12 -3 45 13 0 22 -3 0 40 13 0 20 33 17 blend
+ vhcurveto
+ -6 -10 -24 -99 -58 -119 -81 -94 0 0 -101 0 10 15 0 -4 -31 0 -31 11 -17 -52 25 15 3 76 0 -90 -3 10 -14 3 8 blend
+ rlinecurve
+ 21 -15 20 -21 98 -25 -10 -70 -104 callsubr
+ 117 136 66 172 126 0 86 92 0 -14 97 0 71 -12 0 -20 -91 0 24 -6 5 blend
+ vvcurveto
+ -30 12 0 -1 -155 0 0 -9 -106 callsubr
+ -98 -30 -51 -62 -62 -30 51 98 102 32 59 60 60 32 -59 -102 0 3 40 0 -54 17 0 -13 25 0 -65 33 0 -65 37 0 -54 17 0 13 -22 0 -3 -43 0 -3 -47 0 56 -19 0 13 -29 0 63 -35 0 63 -31 0 56 -19 0 -13 32 0 3 44 -103 callsubr
+
+
+ 105 70 30 1 blend
+ hmoveto
+ 29 0 161 1 blend
+ 600 -24 0 -131 1 blend
+ hlineto
+ -18 -18 -10 0 -10 1 2 blend
+ -2 -2 -15 1 0 -10 -1 2 blend
+ hvcurveto
+ -29 -4 -70 -70 -1 -10 -104 callsubr
+ -20 75 0 -105 100 40 2 blend
+ vlineto
+
+
+ 4 vsindex
+ 30 0 0 40 10 1 blend
+ hmoveto
+ 28 100 0 6 162 1 blend
+ hlineto
+ 224 580 0 0 220 -40 -107 callsubr
+ -100 -104 callsubr
+ -28 -100 0 -6 -162 1 blend
+ hlineto
+ -211 -5 0 0 -214 7 0 -100 0 -25 -106 callsubr
+ 229 100 -50 220 15 1 blend
+ hlineto
+ 10 5 0 50 0 140 0 100 0 25 -104 callsubr
+ 20 -239 -107 callsubr
+ 100 -100 0 -220 -155 2 blend
+ vlineto
+
+
+ 3 vsindex
+ 35 196 0 40 -10 0 0 15 -106 callsubr
+ -137 39 -71 81 80 44 68 133 117 -39 62 -78 -47 -33 -24 -41 -9 0 12 10 0 55 54 0 -12 -25 0 60 54 0 67 51 0 58 52 0 14 26 0 -16 0 0 -9 0 0 -56 -48 0 11 24 0 -61 -37 0 -68 -12 0 -48 -16 0 -22 3 0 -40 -13 0 -20 -33 17 blend
+ vhcurveto
+ 6 10 24 99 55 99 81 94 0 0 101 0 -10 -15 0 4 31 0 31 -11 20 55 -22 -15 17 -56 0 90 3 -10 14 -3 8 blend
+ rlinecurve
+ -21 15 -20 21 -98 25 10 70 -104 callsubr
+ -117 -136 -66 -152 -136 0 -86 -92 0 14 -97 0 -71 12 0 0 71 0 -14 16 5 blend
+ vvcurveto
+ 30 -12 0 1 155 0 0 9 -106 callsubr
+ 108 30 51 62 62 30 -51 -108 -112 -32 -59 -60 -60 -32 59 112 0 -13 -50 0 54 -17 0 13 -25 0 65 -33 0 65 -37 0 54 -17 0 -13 22 0 13 53 0 13 57 0 -56 19 0 -13 29 0 -63 35 0 -63 31 0 -56 19 0 13 -32 0 -13 -54 -103 callsubr
+
+
+ 268 151 247 162 10 15 -106 callsubr
+ 99 -52 63 -82 -6 0 -36 -37 -4 0 -56 -55 4 blend
+ vhcurveto
+ -67 -20 66 -90 -60 0 -70 90 40 3 blend
+ hlineto
+ 64 41 -57 -89 -86 -40 -49 -70 -33 -29 11 21 -22 55 -29 35 -19 4 36 6 57 -1 54 -41 14 -9 27 -54 31 -43 1 -44 11 13 -5 20 5 -23 -17 13 blend
+ hvcurveto
+ -19 -16 0 -57 0 -86 -104 callsubr
+ -27 27 35 -13 43 -19 -20 20 22 44 34 -14 -13 45 38 5 blend
+ hhcurveto
+ 85 53 63 100 55 42 43 41 7 12 3 3 4 blend
+ hvcurveto
+ -18 308 -20 -30 1 blend
+ rmoveto
+ 94 -48 59 -75 -37 -36 -16 -28 -26 1 1 -42 -40 9 14 -52 -39 -42 -30 -39 -38 -10 -12 -18 -16 -26 -24 9 blend
+ vhcurveto
+ 19 -16 -4 57 -3 -87 -104 callsubr
+ 21 18 30 14 29 26 2 39 13 25 -7 5 -5 49 -1 5 blend
+ hhcurveto
+ 62 34 -45 -84 -79 -38 -61 -48 49 -27 41 -11 -11 25 1 53 4 50 -37 21 6 40 -53 14 8 blend
+ hvcurveto
+ -67 -15 68 -90 -40 0 -65 90 50 3 blend
+ hlineto
+ 68 47 64 92 55 62 37 40 -5 -2 -5 2 4 blend
+ hvcurveto
+
+
+ 1 vsindex
+ 43 25 10 60 0 66 147 0 90 0 0 125 -106 callsubr
+ -10 -5 0 -60 0 -20 -140 0 -90 0 0 -25 -104 callsubr
+ -20 257 25 -105 callsubr
+ -100 0 0 200 223 137 0 90 0 0 125 3 blend
+ vlineto
+ -265 534 0 0 -200 -229 -154 0 -90 0 -36 -143 -106 callsubr
+ 16 -18 -105 callsubr
+ 51 -107 callsubr
+ -1 -113 -104 callsubr
+ 35 34 33 11 35 -107 callsubr
+ 23 -12 -107 callsubr
+ 27 -10 -107 callsubr
+ 29 -9 -107 callsubr
+ 14 4 -107 callsubr
+ 50 -2 5 blend
+ hhcurveto
+ 61 41 -44 -65 -65 -30 -49 -40 -76 -107 callsubr
+ 51 -21 -107 callsubr
+ 36 -15 -107 callsubr
+ -21 24 -107 callsubr
+ -27 33 -107 callsubr
+ -27 29 -107 callsubr
+ -37 6 -107 callsubr
+ -11 23 -107 callsubr
+ -36 6 -107 callsubr
+ 17 32 9 blend
+ hvcurveto
+ -142 -268 32 0 132 251 -107 callsubr
+ -114 11 -107 callsubr
+ 69 98 20 0 0 9 172 -105 callsubr
+ -10 -107 callsubr
+ 94 -28 -107 callsubr
+ -76 -110 6 blend
+ rlineto
+ 53 101 26 35 71 -107 callsubr
+ 43 -1 -107 callsubr
+ -27 -30 -10 0 0 42 -4 -107 callsubr
+ 24 10 -14 0 0 31 -7 5 blend
+ vvcurveto
+ 80 -53 54 -78 -40 -41 -14 -39 -39 13 0 0 28 26 -9 0 0 -36 -35 1 0 0 20 21 -107 callsubr
+ -53 -46 -1 0 0 -49 -32 -107 callsubr
+ -30 -29 -107 callsubr
+ -14 -12 -107 callsubr
+ -22 -6 -107 callsubr
+ -26 -14 9 blend
+ vhcurveto
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 327 330 190 1 blend
+ 301 rmoveto
+ 211 -47 100 -99 -97 -49 -104 -207 -217 45 -96 101 97 49 105 208 -16 -2 -61 -37 16 2 -84 -63 -80 -64 -65 -36 -17 1 17 -1 21 8 63 40 -21 -8 82 60 80 65 65 35 17 -2 -17 2 16 blend
+ vhcurveto
+ -30 -2 -170 1 blend
+ -1 rmoveto
+ -193 -38 -94 -78 -78 -38 94 193 193 38 94 78 78 38 -94 -193 14 79 -59 28 -12 41 -84 42 -84 42 -59 28 12 -41 -14 -79 -14 -79 59 -28 12 -41 84 -42 84 -42 59 -28 -12 41 14 79 -103 callsubr
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ wght
+ 0x0
+ 400.0
+ 400.0
+ 700.0
+ 256
+
+
+
+
+ V000
+ 0x1
+ -1.0
+ 0.0
+ 1.0
+ 257
+
+
+
+
+ V001
+ 0x1
+ -1.0
+ 0.0
+ 1.0
+ 258
+
+
+
+
+ V002
+ 0x1
+ -1.0
+ 0.0
+ 1.0
+ 259
+
+
+
+
+ V003
+ 0x1
+ -1.0
+ 0.0
+ 1.0
+ 260
+
+
+
+
+ V004
+ 0x1
+ -1.0
+ 0.0
+ 1.0
+ 261
+
+
+
+
+ V005
+ 0x1
+ -1.0
+ 0.0
+ 1.0
+ 262
+
+
+
+
+ V006
+ 0x1
+ -1.0
+ 0.0
+ 1.0
+ 263
+
+
+
+
diff --git a/tests/data/figArnaud.ttx b/tests/data/figArnaud.ttf.ttx
similarity index 100%
rename from tests/data/figArnaud.ttx
rename to tests/data/figArnaud.ttf.ttx
diff --git a/tests/data/notosanscjksc.fontra/font-data.json b/tests/data/notosanscjksc.fontra/font-data.json
new file mode 100644
index 0000000..d92d38f
--- /dev/null
+++ b/tests/data/notosanscjksc.fontra/font-data.json
@@ -0,0 +1,99 @@
+{
+"axes": {
+"axes": [
+{
+"name": "wght",
+"label": "wght",
+"tag": "wght",
+"minValue": 100,
+"defaultValue": 100,
+"maxValue": 900,
+"mapping": [
+[
+100,
+0
+],
+[
+300,
+0.15997314453125
+],
+[
+350,
+0.32000732421875
+],
+[
+400,
+0.3900146484375
+],
+[
+500,
+0.55999755859375
+],
+[
+700,
+0.780029296875
+],
+[
+900,
+1
+]
+]
+}
+]
+},
+"customData": {
+"fontra.sourceStatusFieldDefinitions": [
+{
+"color": [
+1,
+0,
+0,
+1
+],
+"isDefault": true,
+"label": "In progress",
+"value": 0
+},
+{
+"color": [
+1,
+0.5,
+0,
+1
+],
+"label": "Checking-1",
+"value": 1
+},
+{
+"color": [
+1,
+1,
+0,
+1
+],
+"label": "Checking-2",
+"value": 2
+},
+{
+"color": [
+0,
+0.5,
+1,
+1
+],
+"label": "Checking-3",
+"value": 3
+},
+{
+"color": [
+0,
+1,
+0.5,
+1
+],
+"label": "Validated",
+"value": 4
+}
+]
+}
+}
diff --git a/tests/data/notosanscjksc.fontra/glyph-info.csv b/tests/data/notosanscjksc.fontra/glyph-info.csv
new file mode 100644
index 0000000..f977fb1
--- /dev/null
+++ b/tests/data/notosanscjksc.fontra/glyph-info.csv
@@ -0,0 +1,12 @@
+glyph name;code points
+T_4EBA_2FF1;
+VG_31CF_00;
+VG_4E00_00;
+VG_4E28_00;
+VG_4E3F_01;
+VG_531A_00;
+VG_53E3_00;
+VG_65E5_00;
+VG_7530_00;
+uni3479;U+3479
+uni531A;U+531A
diff --git a/tests/data/notosanscjksc.fontra/glyphs/T_4EBA_2FF1^PP.json b/tests/data/notosanscjksc.fontra/glyphs/T_4EBA_2FF1^PP.json
new file mode 100644
index 0000000..45e906d
--- /dev/null
+++ b/tests/data/notosanscjksc.fontra/glyphs/T_4EBA_2FF1^PP.json
@@ -0,0 +1,225 @@
+{
+"name": "T_4EBA_2FF1",
+"axes": [
+{
+"name": "height",
+"minValue": 299,
+"defaultValue": 454,
+"maxValue": 454
+}
+],
+"sources": [
+{
+"name": "",
+"layerName": "foreground",
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "wght=1",
+"layerName": "wght=1",
+"location": {
+"wght": 1
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "height=299",
+"layerName": "height=299",
+"location": {
+"height": 299
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "wght=1,height=299",
+"layerName": "wght=1,height=299",
+"location": {
+"height": 299,
+"wght": 1
+},
+"customData": {
+"fontra.development.status": 0
+}
+}
+],
+"layers": {
+"foreground": {
+"glyph": {
+"components": [
+{
+"name": "VG_31CF_00",
+"transformation": {
+"translateX": 429,
+"translateY": -52
+},
+"location": {
+"B_weightH": -1,
+"B_weightV": 3,
+"T_weightH": -1,
+"T_weightV": -3,
+"curveH": -9,
+"curveV": -19,
+"height": 407.2,
+"weight": 30,
+"width": 473.12
+}
+},
+{
+"name": "VG_4E3F_01",
+"transformation": {
+"translateX": -405,
+"translateY": 40
+},
+"location": {
+"bottom_weightH": 4,
+"bottom_weightV": 2,
+"curveH": 19,
+"curveV": 0,
+"height": 448.5,
+"top_weightH": 1,
+"top_weightV": -3,
+"weight": 30,
+"width": 495.5
+}
+}
+],
+"xAdvance": 1000
+}
+},
+"height=299": {
+"glyph": {
+"components": [
+{
+"name": "VG_31CF_00",
+"transformation": {
+"translateX": 424,
+"translateY": -23
+},
+"location": {
+"B_weightH": -1,
+"B_weightV": 3,
+"T_weightH": 2,
+"T_weightV": -3,
+"curveH": 11,
+"curveV": 1,
+"height": 277.2,
+"weight": 30,
+"width": 472.12
+}
+},
+{
+"name": "VG_4E3F_01",
+"transformation": {
+"translateX": -418,
+"translateY": 39
+},
+"location": {
+"bottom_weightH": 4,
+"bottom_weightV": 2,
+"curveH": 41,
+"curveV": 0,
+"height": 292.5,
+"top_weightH": 5,
+"top_weightV": -6,
+"weight": 30,
+"width": 484.5
+}
+}
+],
+"xAdvance": 1000
+}
+},
+"wght=1": {
+"glyph": {
+"components": [
+{
+"name": "VG_31CF_00",
+"transformation": {
+"translateX": 383,
+"translateY": -71
+},
+"location": {
+"B_weightH": -13,
+"B_weightV": 25,
+"T_weightH": -8,
+"T_weightV": 11,
+"curveH": -22,
+"curveV": -9,
+"height": 406.2,
+"weight": 160,
+"width": 561.12
+}
+},
+{
+"name": "VG_4E3F_01",
+"transformation": {
+"translateX": -369,
+"translateY": 49
+},
+"location": {
+"bottom_weightH": 4,
+"bottom_weightV": 20,
+"curveH": 12,
+"curveV": 0,
+"height": 431.5,
+"top_weightH": 8,
+"top_weightV": -16,
+"weight": 166,
+"width": 526.5
+}
+}
+],
+"xAdvance": 1000
+}
+},
+"wght=1,height=299": {
+"glyph": {
+"components": [
+{
+"name": "VG_31CF_00",
+"transformation": {
+"translateX": 402,
+"translateY": -25
+},
+"location": {
+"B_weightH": -5,
+"B_weightV": 28,
+"T_weightH": -15,
+"T_weightV": 11,
+"curveH": -2,
+"curveV": 11,
+"height": 286.2,
+"weight": 130,
+"width": 538.12
+}
+},
+{
+"name": "VG_4E3F_01",
+"transformation": {
+"translateX": -380,
+"translateY": 68
+},
+"location": {
+"bottom_weightH": 6,
+"bottom_weightV": 20,
+"curveH": 44,
+"curveV": 3,
+"height": 301.5,
+"top_weightH": 42,
+"top_weightV": -31,
+"weight": 129,
+"width": 525.5
+}
+}
+],
+"xAdvance": 1000
+}
+}
+}
+}
diff --git a/tests/data/notosanscjksc.fontra/glyphs/VG_31CF_00^33.json b/tests/data/notosanscjksc.fontra/glyphs/VG_31CF_00^33.json
new file mode 100644
index 0000000..f1a8fa9
--- /dev/null
+++ b/tests/data/notosanscjksc.fontra/glyphs/VG_31CF_00^33.json
@@ -0,0 +1,1394 @@
+{
+"name": "VG_31CF_00",
+"axes": [
+{
+"name": "weight",
+"minValue": 25,
+"defaultValue": 25,
+"maxValue": 170
+},
+{
+"name": "height",
+"minValue": 180,
+"defaultValue": 900,
+"maxValue": 900
+},
+{
+"name": "width",
+"minValue": 180,
+"defaultValue": 900,
+"maxValue": 900
+},
+{
+"name": "T_weightH",
+"minValue": -100,
+"defaultValue": 0,
+"maxValue": 100
+},
+{
+"name": "T_weightV",
+"minValue": -100,
+"defaultValue": 0,
+"maxValue": 100
+},
+{
+"name": "B_weightH",
+"minValue": -100,
+"defaultValue": 0,
+"maxValue": 100
+},
+{
+"name": "B_weightV",
+"minValue": -100,
+"defaultValue": 0,
+"maxValue": 100
+},
+{
+"name": "curveH",
+"minValue": -100,
+"defaultValue": 0,
+"maxValue": 100
+},
+{
+"name": "curveV",
+"minValue": -100,
+"defaultValue": 0,
+"maxValue": 100
+}
+],
+"sources": [
+{
+"name": "",
+"layerName": "foreground",
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "weight=170",
+"layerName": "weight=170",
+"location": {
+"weight": 170
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "height=180",
+"layerName": "height=180",
+"location": {
+"height": 180
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "width=180",
+"layerName": "width=180",
+"location": {
+"width": 180
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "weight=170,width=180",
+"layerName": "weight=170,width=180",
+"location": {
+"weight": 170,
+"width": 180
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "weight=170,height=180,width=180",
+"layerName": "weight=170,height=180,width=180",
+"location": {
+"height": 180,
+"weight": 170,
+"width": 180
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "T_weightH=-100",
+"layerName": "T_weightH=-100",
+"location": {
+"T_weightH": -100
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "T_weightH=100",
+"layerName": "T_weightH=100",
+"location": {
+"T_weightH": 100
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "T_weightV=-100",
+"layerName": "T_weightV=-100",
+"location": {
+"T_weightV": -100
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "T_weightV=100",
+"layerName": "T_weightV=100",
+"location": {
+"T_weightV": 100
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "B_weightH=-100",
+"layerName": "B_weightH=-100",
+"location": {
+"B_weightH": -100
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "B_weightH=100",
+"layerName": "B_weightH=100",
+"location": {
+"B_weightH": 100
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "B_weightV=-100",
+"layerName": "B_weightV=-100",
+"location": {
+"B_weightV": -100
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "B_weightV=100",
+"layerName": "B_weightV=100",
+"location": {
+"B_weightV": 100
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "curveH=-100",
+"layerName": "curveH=-100",
+"location": {
+"curveH": -100
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "curveH=100",
+"layerName": "curveH=100",
+"location": {
+"curveH": 100
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "curveV=-100",
+"layerName": "curveV=-100",
+"location": {
+"curveV": -100
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "curveV=100",
+"layerName": "curveV=100",
+"location": {
+"curveV": 100
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "height=180,width=180",
+"layerName": "height=180,width=180",
+"location": {
+"height": 180,
+"width": 180
+},
+"customData": {
+"fontra.development.status": 0
+}
+}
+],
+"layers": {
+"B_weightH=-100": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 83,
+"y": 838
+},
+{
+"x": 59,
+"y": 830
+},
+{
+"x": 200,
+"y": 384,
+"type": "cubic"
+},
+{
+"x": 484,
+"y": 64,
+"type": "cubic"
+},
+{
+"x": 943,
+"y": -62
+},
+{
+"x": 912,
+"y": -53,
+"type": "cubic"
+},
+{
+"x": 886,
+"y": -46,
+"type": "cubic"
+},
+{
+"x": 859,
+"y": -40
+},
+{
+"x": 447.7423679442857,
+"y": 70.86075298893167,
+"type": "cubic"
+},
+{
+"x": 218.66836970337044,
+"y": 406.23788911920064,
+"type": "cubic"
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"B_weightH=100": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 83,
+"y": 838
+},
+{
+"x": 59,
+"y": 830
+},
+{
+"x": 200,
+"y": 384,
+"type": "cubic"
+},
+{
+"x": 484,
+"y": 64,
+"type": "cubic"
+},
+{
+"x": 943,
+"y": -62
+},
+{
+"x": 979,
+"y": -53,
+"type": "cubic"
+},
+{
+"x": 1015,
+"y": -46,
+"type": "cubic"
+},
+{
+"x": 1059,
+"y": -40
+},
+{
+"x": 549.8748064095068,
+"y": 97.24244348961119,
+"type": "cubic"
+},
+{
+"x": 221.47762096555581,
+"y": 397.2974982410048,
+"type": "cubic"
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"B_weightV=-100": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 83,
+"y": 838
+},
+{
+"x": 59,
+"y": 830
+},
+{
+"x": 200,
+"y": 384,
+"type": "cubic"
+},
+{
+"x": 484,
+"y": 64,
+"type": "cubic"
+},
+{
+"x": 943,
+"y": -62
+},
+{
+"x": 949,
+"y": -87,
+"type": "cubic"
+},
+{
+"x": 954,
+"y": -116,
+"type": "cubic"
+},
+{
+"x": 959,
+"y": -140
+},
+{
+"x": 495.26388605776907,
+"y": -14.992873632963835,
+"type": "cubic"
+},
+{
+"x": 234.2673065394611,
+"y": 356.5945572904742,
+"type": "cubic"
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"B_weightV=100": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 83,
+"y": 838
+},
+{
+"x": 59,
+"y": 830
+},
+{
+"x": 200,
+"y": 384,
+"type": "cubic"
+},
+{
+"x": 484,
+"y": 64,
+"type": "cubic"
+},
+{
+"x": 943,
+"y": -62
+},
+{
+"x": 944,
+"y": -22,
+"type": "cubic"
+},
+{
+"x": 950,
+"y": 20,
+"type": "cubic"
+},
+{
+"x": 959,
+"y": 60
+},
+{
+"x": 502.3593191732545,
+"y": 183.09444439677486,
+"type": "cubic"
+},
+{
+"x": 205.87958095199198,
+"y": 446.93797594840504,
+"type": "cubic"
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"T_weightH=-100": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": -17,
+"y": 838
+},
+{
+"x": 59,
+"y": 830
+},
+{
+"x": 200,
+"y": 384,
+"type": "cubic"
+},
+{
+"x": 484,
+"y": 64,
+"type": "cubic"
+},
+{
+"x": 943,
+"y": -62
+},
+{
+"x": 947,
+"y": -54,
+"type": "cubic"
+},
+{
+"x": 954,
+"y": -45,
+"type": "cubic"
+},
+{
+"x": 959,
+"y": -40
+},
+{
+"x": 449.8748064095068,
+"y": 97.24244348961119,
+"type": "cubic"
+},
+{
+"x": 121.47762096555581,
+"y": 397.2974982410048,
+"type": "cubic"
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"T_weightH=100": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 183,
+"y": 838
+},
+{
+"x": 59,
+"y": 830
+},
+{
+"x": 200,
+"y": 384,
+"type": "cubic"
+},
+{
+"x": 484,
+"y": 64,
+"type": "cubic"
+},
+{
+"x": 943,
+"y": -62
+},
+{
+"x": 947,
+"y": -54,
+"type": "cubic"
+},
+{
+"x": 954,
+"y": -45,
+"type": "cubic"
+},
+{
+"x": 959,
+"y": -40
+},
+{
+"x": 547.7423679442858,
+"y": 70.86075298893165,
+"type": "cubic"
+},
+{
+"x": 318.66836970337044,
+"y": 406.23788911920064,
+"type": "cubic"
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"T_weightV=-100": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 83,
+"y": 738
+},
+{
+"x": 59,
+"y": 830
+},
+{
+"x": 200,
+"y": 384,
+"type": "cubic"
+},
+{
+"x": 484,
+"y": 64,
+"type": "cubic"
+},
+{
+"x": 943,
+"y": -62
+},
+{
+"x": 947,
+"y": -54,
+"type": "cubic"
+},
+{
+"x": 954,
+"y": -45,
+"type": "cubic"
+},
+{
+"x": 959,
+"y": -40
+},
+{
+"x": 502.3593191732545,
+"y": 83.09444439677486,
+"type": "cubic"
+},
+{
+"x": 205.87958095199198,
+"y": 346.93797594840504,
+"type": "cubic"
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"T_weightV=100": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 83,
+"y": 938
+},
+{
+"x": 59,
+"y": 830
+},
+{
+"x": 200,
+"y": 384,
+"type": "cubic"
+},
+{
+"x": 484,
+"y": 64,
+"type": "cubic"
+},
+{
+"x": 943,
+"y": -62
+},
+{
+"x": 947,
+"y": -54,
+"type": "cubic"
+},
+{
+"x": 954,
+"y": -45,
+"type": "cubic"
+},
+{
+"x": 959,
+"y": -40
+},
+{
+"x": 495.26388605776907,
+"y": 85.00712636703616,
+"type": "cubic"
+},
+{
+"x": 234.2673065394611,
+"y": 456.5945572904742,
+"type": "cubic"
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"curveH=-100": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 83,
+"y": 838
+},
+{
+"x": 59,
+"y": 830
+},
+{
+"x": 300,
+"y": 384,
+"type": "cubic"
+},
+{
+"x": 584,
+"y": 64,
+"type": "cubic"
+},
+{
+"x": 943,
+"y": -62
+},
+{
+"x": 947,
+"y": -54,
+"type": "cubic"
+},
+{
+"x": 954,
+"y": -45,
+"type": "cubic"
+},
+{
+"x": 959,
+"y": -40
+},
+{
+"x": 599,
+"y": 84,
+"type": "cubic"
+},
+{
+"x": 320,
+"y": 402,
+"type": "cubic"
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"curveH=100": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 83,
+"y": 838
+},
+{
+"x": 59,
+"y": 830
+},
+{
+"x": 100,
+"y": 384,
+"type": "cubic"
+},
+{
+"x": 384,
+"y": 64,
+"type": "cubic"
+},
+{
+"x": 943,
+"y": -62
+},
+{
+"x": 947,
+"y": -54,
+"type": "cubic"
+},
+{
+"x": 954,
+"y": -45,
+"type": "cubic"
+},
+{
+"x": 959,
+"y": -40
+},
+{
+"x": 399,
+"y": 84,
+"type": "cubic"
+},
+{
+"x": 120,
+"y": 402,
+"type": "cubic"
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"curveV=-100": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 83,
+"y": 838
+},
+{
+"x": 59,
+"y": 830
+},
+{
+"x": 200,
+"y": 484,
+"type": "cubic"
+},
+{
+"x": 484,
+"y": 164,
+"type": "cubic"
+},
+{
+"x": 943,
+"y": -62
+},
+{
+"x": 947,
+"y": -54,
+"type": "cubic"
+},
+{
+"x": 954,
+"y": -45,
+"type": "cubic"
+},
+{
+"x": 959,
+"y": -40
+},
+{
+"x": 499,
+"y": 184,
+"type": "cubic"
+},
+{
+"x": 220,
+"y": 502,
+"type": "cubic"
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"curveV=100": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 83,
+"y": 838
+},
+{
+"x": 59,
+"y": 830
+},
+{
+"x": 200,
+"y": 284,
+"type": "cubic"
+},
+{
+"x": 484,
+"y": -36,
+"type": "cubic"
+},
+{
+"x": 943,
+"y": -62
+},
+{
+"x": 947,
+"y": -54,
+"type": "cubic"
+},
+{
+"x": 954,
+"y": -44,
+"type": "cubic"
+},
+{
+"x": 959,
+"y": -39
+},
+{
+"x": 499,
+"y": -15,
+"type": "cubic"
+},
+{
+"x": 220,
+"y": 302,
+"type": "cubic"
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"foreground": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 83,
+"y": 838
+},
+{
+"x": 59,
+"y": 830
+},
+{
+"x": 200,
+"y": 384,
+"type": "cubic"
+},
+{
+"x": 484,
+"y": 64,
+"type": "cubic"
+},
+{
+"x": 943,
+"y": -62
+},
+{
+"x": 947,
+"y": -54,
+"type": "cubic"
+},
+{
+"x": 954,
+"y": -45,
+"type": "cubic"
+},
+{
+"x": 959,
+"y": -40
+},
+{
+"x": 499,
+"y": 84,
+"type": "cubic"
+},
+{
+"x": 220,
+"y": 402,
+"type": "cubic"
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"height=180": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 70,
+"y": 838
+},
+{
+"x": 59,
+"y": 815
+},
+{
+"x": 317,
+"y": 726,
+"type": "cubic"
+},
+{
+"x": 641,
+"y": 674,
+"type": "cubic"
+},
+{
+"x": 944,
+"y": 658
+},
+{
+"x": 947,
+"y": 666,
+"type": "cubic"
+},
+{
+"x": 953,
+"y": 676,
+"type": "cubic"
+},
+{
+"x": 959,
+"y": 683
+},
+{
+"x": 643,
+"y": 699,
+"type": "cubic"
+},
+{
+"x": 324,
+"y": 751,
+"type": "cubic"
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"height=180,width=180": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 80,
+"y": 838
+},
+{
+"x": 59,
+"y": 823
+},
+{
+"x": 101.2361115390622,
+"y": 767.0125963319407,
+"type": "cubic"
+},
+{
+"x": 154.40138285234912,
+"y": 711.8989134731543,
+"type": "cubic"
+},
+{
+"x": 223,
+"y": 658
+},
+{
+"x": 229.3546273110161,
+"y": 664.354627311016,
+"type": "cubic"
+},
+{
+"x": 234.51174531248404,
+"y": 671.3621765624931,
+"type": "cubic"
+},
+{
+"x": 243,
+"y": 675
+},
+{
+"x": 170.06248082234146,
+"y": 728.4875140636162,
+"type": "cubic"
+},
+{
+"x": 119.86199386739136,
+"y": 783.5543498396606,
+"type": "cubic"
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"weight=170": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 220,
+"y": 838
+},
+{
+"x": 59,
+"y": 779
+},
+{
+"x": 198,
+"y": 343,
+"type": "cubic"
+},
+{
+"x": 408,
+"y": 51,
+"type": "cubic"
+},
+{
+"x": 848,
+"y": -62
+},
+{
+"x": 871,
+"y": -19,
+"type": "cubic"
+},
+{
+"x": 922,
+"y": 51,
+"type": "cubic"
+},
+{
+"x": 959,
+"y": 85
+},
+{
+"x": 548,
+"y": 177,
+"type": "cubic"
+},
+{
+"x": 331,
+"y": 458,
+"type": "cubic"
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"weight=170,height=180,width=180": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 202,
+"y": 838
+},
+{
+"x": 56,
+"y": 816
+},
+{
+"x": 65,
+"y": 756,
+"type": "cubic"
+},
+{
+"x": 76.72605327113206,
+"y": 714.6392090340252,
+"type": "cubic"
+},
+{
+"x": 101,
+"y": 658
+},
+{
+"x": 140,
+"y": 685,
+"type": "cubic"
+},
+{
+"x": 192,
+"y": 708,
+"type": "cubic"
+},
+{
+"x": 239,
+"y": 722
+},
+{
+"x": 222,
+"y": 758,
+"type": "cubic"
+},
+{
+"x": 210.970408738444,
+"y": 791.1545321436813,
+"type": "cubic"
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"weight=170,width=180": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 196,
+"y": 838
+},
+{
+"x": 59,
+"y": 831
+},
+{
+"x": 64,
+"y": 438,
+"type": "cubic"
+},
+{
+"x": 71,
+"y": 232,
+"type": "cubic"
+},
+{
+"x": 100,
+"y": -62
+},
+{
+"x": 137,
+"y": -32,
+"type": "cubic"
+},
+{
+"x": 190,
+"y": -10,
+"type": "cubic"
+},
+{
+"x": 239,
+"y": -1
+},
+{
+"x": 216,
+"y": 243,
+"type": "cubic"
+},
+{
+"x": 206,
+"y": 459,
+"type": "cubic"
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"width=180": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 85,
+"y": 838
+},
+{
+"x": 59,
+"y": 836
+},
+{
+"x": 94,
+"y": 444,
+"type": "cubic"
+},
+{
+"x": 151,
+"y": 146,
+"type": "cubic"
+},
+{
+"x": 218,
+"y": -62
+},
+{
+"x": 225,
+"y": -58,
+"type": "cubic"
+},
+{
+"x": 235,
+"y": -55,
+"type": "cubic"
+},
+{
+"x": 243,
+"y": -54
+},
+{
+"x": 176,
+"y": 148,
+"type": "cubic"
+},
+{
+"x": 118,
+"y": 454,
+"type": "cubic"
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+}
+}
+}
diff --git a/tests/data/notosanscjksc.fontra/glyphs/VG_4E00_00^J.json b/tests/data/notosanscjksc.fontra/glyphs/VG_4E00_00^J.json
new file mode 100644
index 0000000..b2f30e5
--- /dev/null
+++ b/tests/data/notosanscjksc.fontra/glyphs/VG_4E00_00^J.json
@@ -0,0 +1,138 @@
+{
+"name": "VG_4E00_00",
+"axes": [
+{
+"name": "weight",
+"minValue": -100,
+"defaultValue": 10,
+"maxValue": 200
+},
+{
+"name": "width",
+"minValue": 10,
+"defaultValue": 1000,
+"maxValue": 1000
+}
+],
+"sources": [
+{
+"name": "",
+"layerName": "foreground",
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "weight=200",
+"layerName": "weight=200",
+"location": {
+"weight": 200
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "width=10",
+"layerName": "width=10",
+"location": {
+"width": 10
+},
+"customData": {
+"fontra.development.status": 0
+}
+}
+],
+"layers": {
+"foreground": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 0,
+"y": 390
+},
+{
+"x": 0,
+"y": 380
+},
+{
+"x": 1000,
+"y": 380
+},
+{
+"x": 1000,
+"y": 390
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"weight=200": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 0,
+"y": 580
+},
+{
+"x": 0,
+"y": 380
+},
+{
+"x": 1000,
+"y": 380
+},
+{
+"x": 1000,
+"y": 580
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"width=10": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 0,
+"y": 390
+},
+{
+"x": 0,
+"y": 380
+},
+{
+"x": 10,
+"y": 380
+},
+{
+"x": 10,
+"y": 390
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+}
+}
+}
diff --git a/tests/data/notosanscjksc.fontra/glyphs/VG_4E28_00^J.json b/tests/data/notosanscjksc.fontra/glyphs/VG_4E28_00^J.json
new file mode 100644
index 0000000..c8128fe
--- /dev/null
+++ b/tests/data/notosanscjksc.fontra/glyphs/VG_4E28_00^J.json
@@ -0,0 +1,224 @@
+{
+"name": "VG_4E28_00",
+"axes": [
+{
+"name": "weight",
+"minValue": -100,
+"defaultValue": 10,
+"maxValue": 200
+},
+{
+"name": "height",
+"minValue": 10,
+"defaultValue": 1000,
+"maxValue": 2000
+},
+{
+"name": "T_slant",
+"minValue": 0,
+"defaultValue": 0,
+"maxValue": 100
+}
+],
+"sources": [
+{
+"name": "",
+"layerName": "foreground",
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "weight=200",
+"layerName": "weight=200",
+"location": {
+"weight": 200
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "height=10",
+"layerName": "height=10",
+"location": {
+"height": 10
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "height=2000",
+"layerName": "height=2000",
+"location": {
+"height": 2000
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "T_slant=100",
+"layerName": "T_slant=100",
+"location": {
+"T_slant": 100
+},
+"customData": {
+"fontra.development.status": 0
+}
+}
+],
+"layers": {
+"T_slant=100": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 500,
+"y": 880
+},
+{
+"x": 500,
+"y": -120
+},
+{
+"x": 510,
+"y": -120
+},
+{
+"x": 510,
+"y": 980
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"foreground": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 500,
+"y": 880
+},
+{
+"x": 500,
+"y": -120
+},
+{
+"x": 510,
+"y": -120
+},
+{
+"x": 510,
+"y": 880
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"height=10": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 500,
+"y": 880
+},
+{
+"x": 500,
+"y": 870
+},
+{
+"x": 510,
+"y": 870
+},
+{
+"x": 510,
+"y": 880
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"height=2000": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 500,
+"y": 880
+},
+{
+"x": 500,
+"y": -1120
+},
+{
+"x": 510,
+"y": -1120
+},
+{
+"x": 510,
+"y": 880
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"weight=200": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 500,
+"y": 880
+},
+{
+"x": 500,
+"y": -120
+},
+{
+"x": 700,
+"y": -120
+},
+{
+"x": 700,
+"y": 880
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+}
+}
+}
diff --git a/tests/data/notosanscjksc.fontra/glyphs/VG_4E3F_01^J2.json b/tests/data/notosanscjksc.fontra/glyphs/VG_4E3F_01^J2.json
new file mode 100644
index 0000000..f1a9a96
--- /dev/null
+++ b/tests/data/notosanscjksc.fontra/glyphs/VG_4E3F_01^J2.json
@@ -0,0 +1,2197 @@
+{
+"name": "VG_4E3F_01",
+"axes": [
+{
+"name": "weight",
+"minValue": 30,
+"defaultValue": 30,
+"maxValue": 170
+},
+{
+"name": "width",
+"minValue": 130,
+"defaultValue": 930,
+"maxValue": 930
+},
+{
+"name": "height",
+"minValue": 130,
+"defaultValue": 780,
+"maxValue": 780
+},
+{
+"name": "curveH",
+"minValue": 0,
+"defaultValue": 0,
+"maxValue": 100
+},
+{
+"name": "curveV",
+"minValue": 0,
+"defaultValue": 0,
+"maxValue": 100
+},
+{
+"name": "top_weightH",
+"minValue": -100,
+"defaultValue": 0,
+"maxValue": 100
+},
+{
+"name": "top_weightV",
+"minValue": -100,
+"defaultValue": 0,
+"maxValue": 100
+},
+{
+"name": "bottom_weightH",
+"minValue": -100,
+"defaultValue": 0,
+"maxValue": 100
+},
+{
+"name": "bottom_weightV",
+"minValue": -100,
+"defaultValue": 0,
+"maxValue": 100
+}
+],
+"sources": [
+{
+"name": "",
+"layerName": "foreground",
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "weight=170",
+"layerName": "weight=170",
+"location": {
+"weight": 170
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "width=130",
+"layerName": "width=130",
+"location": {
+"width": 130
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "height=130",
+"layerName": "height=130",
+"location": {
+"height": 130
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "width=130,height=130",
+"layerName": "width=130,height=130",
+"location": {
+"height": 130,
+"width": 130
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "weight=170,width=130",
+"layerName": "weight=170,width=130",
+"location": {
+"weight": 170,
+"width": 130
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "weight=170,height=130",
+"layerName": "weight=170,height=130",
+"location": {
+"height": 130,
+"weight": 170
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "weight=170,width=130,height=130",
+"layerName": "weight=170,width=130,height=130",
+"location": {
+"height": 130,
+"weight": 170,
+"width": 130
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "curveH=100",
+"layerName": "curveH=100",
+"location": {
+"curveH": 100
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "curveV=100",
+"layerName": "curveV=100",
+"location": {
+"curveV": 100
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "top_weightH=-100",
+"layerName": "top_weightH=-100",
+"location": {
+"top_weightH": -100
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "top_weightV=100",
+"layerName": "top_weightV=100",
+"location": {
+"top_weightV": 100
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "top_weightH=100",
+"layerName": "top_weightH=100",
+"location": {
+"top_weightH": 100
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "top_weightV=-100",
+"layerName": "top_weightV=-100",
+"location": {
+"top_weightV": -100
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "bottom_weightH=-100",
+"layerName": "bottom_weightH=-100",
+"location": {
+"bottom_weightH": -100
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "bottom_weightH=100",
+"layerName": "bottom_weightH=100",
+"location": {
+"bottom_weightH": 100
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "bottom_weightV=-100",
+"layerName": "bottom_weightV=-100",
+"location": {
+"bottom_weightV": -100
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "bottom_weightV=100",
+"layerName": "bottom_weightV=100",
+"location": {
+"bottom_weightV": 100
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "weight=170,width=130,bottom_weightV=100",
+"layerName": "weight=170,width=130,bottom_weightV=100",
+"location": {
+"bottom_weightV": 100,
+"weight": 170,
+"width": 130
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "weight=170,width=130,top_weightH=100,bottom_weightV=100",
+"layerName": "weight=170,width=130,top_weightH=100,bottom_weightV=100",
+"location": {
+"bottom_weightV": 100,
+"top_weightH": 100,
+"weight": 170,
+"width": 130
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "weight=170,width=130,height=130,top_weightH=100,bottom_weightV=100",
+"layerName": "weight=170,width=130,height=130,top_weightH=100,bottom_weightV=100",
+"location": {
+"bottom_weightV": 100,
+"height": 130,
+"top_weightH": 100,
+"weight": 170,
+"width": 130
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "weight=170,width=130,top_weightH=-100",
+"layerName": "weight=170,width=130,top_weightH=-100",
+"location": {
+"top_weightH": -100,
+"weight": 170,
+"width": 130
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "weight=170,width=130,height=130,top_weightH=-100",
+"layerName": "weight=170,width=130,height=130,top_weightH=-100",
+"location": {
+"height": 130,
+"top_weightH": -100,
+"weight": 170,
+"width": 130
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "width=130,bottom_weightV=100",
+"layerName": "width=130,bottom_weightV=100",
+"location": {
+"bottom_weightV": 100,
+"width": 130
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "width=130,height=130,bottom_weightV=100",
+"layerName": "width=130,height=130,bottom_weightV=100",
+"location": {
+"bottom_weightV": 100,
+"height": 130,
+"width": 130
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "wght=1,weight=170,width=130,height=130,bottom_weightV=100",
+"layerName": "wght=1,weight=170,width=130,height=130,bottom_weightV=100",
+"location": {
+"bottom_weightV": 100,
+"height": 130,
+"weight": 170,
+"wght": 1,
+"width": 130
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "width=130,bottom_weightH=-100",
+"layerName": "width=130,bottom_weightH=-100",
+"location": {
+"bottom_weightH": -100,
+"width": 130
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "top_weightH=100,bottom_weightH=-100",
+"layerName": "top_weightH=100,bottom_weightH=-100",
+"location": {
+"bottom_weightH": -100,
+"top_weightH": 100
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "wght=1,weight=170,width=130,top_weightH=100,bottom_weightH=-100",
+"layerName": "wght=1,weight=170,width=130,top_weightH=100,bottom_weightH=-100",
+"location": {
+"bottom_weightH": -100,
+"top_weightH": 100,
+"weight": 170,
+"wght": 1,
+"width": 130
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "wght=1,weight=170,width=130,height=130,top_weightH=100,bottom_weightH=-100",
+"layerName": "wght=1,weight=170,width=130,height=130,top_weightH=100,bottom_weightH=-100",
+"location": {
+"bottom_weightH": -100,
+"height": 130,
+"top_weightH": 100,
+"weight": 170,
+"wght": 1,
+"width": 130
+},
+"customData": {
+"fontra.development.status": 0
+}
+}
+],
+"layers": {
+"bottom_weightH=-100": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 924,
+"y": 793
+},
+{
+"x": 713.3701789510591,
+"y": 480.9200357852848,
+"type": "cubic"
+},
+{
+"x": 456.02003588010075,
+"y": 183.98988034812038,
+"type": "cubic"
+},
+{
+"x": 121,
+"y": 36
+},
+{
+"x": 98,
+"y": 28,
+"type": "cubic"
+},
+{
+"x": 71,
+"y": 20,
+"type": "cubic"
+},
+{
+"x": 42,
+"y": 13
+},
+{
+"x": 408,
+"y": 179,
+"type": "cubic"
+},
+{
+"x": 722,
+"y": 446,
+"type": "cubic"
+},
+{
+"x": 951,
+"y": 780
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"bottom_weightH=100": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 924,
+"y": 793
+},
+{
+"x": 698.1669596362449,
+"y": 458.3941649656289,
+"type": "cubic"
+},
+{
+"x": 324.4747361623256,
+"y": 214.22867749175902,
+"type": "cubic"
+},
+{
+"x": -79,
+"y": 36
+},
+{
+"x": -36,
+"y": 32,
+"type": "cubic"
+},
+{
+"x": 3,
+"y": 25,
+"type": "cubic"
+},
+{
+"x": 42,
+"y": 13
+},
+{
+"x": 408,
+"y": 179,
+"type": "cubic"
+},
+{
+"x": 722,
+"y": 446,
+"type": "cubic"
+},
+{
+"x": 951,
+"y": 780
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"bottom_weightV=-100": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 924,
+"y": 793
+},
+{
+"x": 685.8400578239529,
+"y": 440.12999393182,
+"type": "cubic"
+},
+{
+"x": 398.38893626474754,
+"y": 102.70568187304565,
+"type": "cubic"
+},
+{
+"x": 21,
+"y": -64
+},
+{
+"x": 29,
+"y": -41,
+"type": "cubic"
+},
+{
+"x": 38,
+"y": -7,
+"type": "cubic"
+},
+{
+"x": 42,
+"y": 13
+},
+{
+"x": 408,
+"y": 179,
+"type": "cubic"
+},
+{
+"x": 722,
+"y": 446,
+"type": "cubic"
+},
+{
+"x": 951,
+"y": 780
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"bottom_weightV=100": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 924,
+"y": 793
+},
+{
+"x": 725.3359855215677,
+"y": 498.6491895571852,
+"type": "cubic"
+},
+{
+"x": 382.4906332456932,
+"y": 295.68285425216254,
+"type": "cubic"
+},
+{
+"x": 21,
+"y": 136
+},
+{
+"x": 34,
+"y": 96,
+"type": "cubic"
+},
+{
+"x": 41,
+"y": 53,
+"type": "cubic"
+},
+{
+"x": 42,
+"y": 13
+},
+{
+"x": 408,
+"y": 179,
+"type": "cubic"
+},
+{
+"x": 722,
+"y": 446,
+"type": "cubic"
+},
+{
+"x": 951,
+"y": 780
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"curveH=100": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 924,
+"y": 793
+},
+{
+"x": 806,
+"y": 470,
+"type": "cubic"
+},
+{
+"x": 490,
+"y": 199,
+"type": "cubic"
+},
+{
+"x": 21,
+"y": 36
+},
+{
+"x": 29,
+"y": 30,
+"type": "cubic"
+},
+{
+"x": 37,
+"y": 20,
+"type": "cubic"
+},
+{
+"x": 42,
+"y": 13
+},
+{
+"x": 508,
+"y": 179,
+"type": "cubic"
+},
+{
+"x": 822,
+"y": 446,
+"type": "cubic"
+},
+{
+"x": 951,
+"y": 780
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"curveV=100": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 924,
+"y": 793
+},
+{
+"x": 706,
+"y": 370,
+"type": "cubic"
+},
+{
+"x": 390,
+"y": 99,
+"type": "cubic"
+},
+{
+"x": 21,
+"y": 36
+},
+{
+"x": 29,
+"y": 30,
+"type": "cubic"
+},
+{
+"x": 37,
+"y": 20,
+"type": "cubic"
+},
+{
+"x": 42,
+"y": 13
+},
+{
+"x": 408,
+"y": 79,
+"type": "cubic"
+},
+{
+"x": 722,
+"y": 346,
+"type": "cubic"
+},
+{
+"x": 951,
+"y": 780
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"foreground": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 924,
+"y": 793
+},
+{
+"x": 706,
+"y": 470,
+"type": "cubic"
+},
+{
+"x": 390,
+"y": 199,
+"type": "cubic"
+},
+{
+"x": 21,
+"y": 36
+},
+{
+"x": 29,
+"y": 30,
+"type": "cubic"
+},
+{
+"x": 37,
+"y": 20,
+"type": "cubic"
+},
+{
+"x": 42,
+"y": 13
+},
+{
+"x": 408,
+"y": 179,
+"type": "cubic"
+},
+{
+"x": 722,
+"y": 446,
+"type": "cubic"
+},
+{
+"x": 951,
+"y": 780
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"height=130": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 940,
+"y": 809
+},
+{
+"x": 653.5699483082634,
+"y": 726.5885465307987,
+"type": "cubic"
+},
+{
+"x": 348,
+"y": 691,
+"type": "cubic"
+},
+{
+"x": 29,
+"y": 689
+},
+{
+"x": 32,
+"y": 680,
+"type": "cubic"
+},
+{
+"x": 33,
+"y": 667,
+"type": "cubic"
+},
+{
+"x": 32,
+"y": 658
+},
+{
+"x": 349,
+"y": 662,
+"type": "cubic"
+},
+{
+"x": 655,
+"y": 695,
+"type": "cubic"
+},
+{
+"x": 951,
+"y": 780
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"top_weightH=-100": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 1024,
+"y": 793
+},
+{
+"x": 798.1669596362449,
+"y": 458.3941649656289,
+"type": "cubic"
+},
+{
+"x": 424.4747361623256,
+"y": 214.22867749175902,
+"type": "cubic"
+},
+{
+"x": 21,
+"y": 36
+},
+{
+"x": 29,
+"y": 30,
+"type": "cubic"
+},
+{
+"x": 37,
+"y": 20,
+"type": "cubic"
+},
+{
+"x": 42,
+"y": 13
+},
+{
+"x": 408,
+"y": 179,
+"type": "cubic"
+},
+{
+"x": 722,
+"y": 446,
+"type": "cubic"
+},
+{
+"x": 951,
+"y": 780
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"top_weightH=100": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 824,
+"y": 793
+},
+{
+"x": 613.2578832282923,
+"y": 480.7536526731119,
+"type": "cubic"
+},
+{
+"x": 356.1485662937221,
+"y": 184.04665665549243,
+"type": "cubic"
+},
+{
+"x": 21,
+"y": 36
+},
+{
+"x": 29,
+"y": 30,
+"type": "cubic"
+},
+{
+"x": 37,
+"y": 20,
+"type": "cubic"
+},
+{
+"x": 42,
+"y": 13
+},
+{
+"x": 408,
+"y": 179,
+"type": "cubic"
+},
+{
+"x": 722,
+"y": 446,
+"type": "cubic"
+},
+{
+"x": 951,
+"y": 780
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"top_weightH=100,bottom_weightH=-100": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 824,
+"y": 793
+},
+{
+"x": 711,
+"y": 492,
+"type": "cubic"
+},
+{
+"x": 332,
+"y": 169,
+"type": "cubic"
+},
+{
+"x": 121,
+"y": 36
+},
+{
+"x": 98,
+"y": 28,
+"type": "cubic"
+},
+{
+"x": 71,
+"y": 20,
+"type": "cubic"
+},
+{
+"x": 42,
+"y": 13
+},
+{
+"x": 408,
+"y": 179,
+"type": "cubic"
+},
+{
+"x": 722,
+"y": 446,
+"type": "cubic"
+},
+{
+"x": 951,
+"y": 780
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"top_weightV=-100": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 924,
+"y": 693
+},
+{
+"x": 725.3359855215677,
+"y": 398.6491895571852,
+"type": "cubic"
+},
+{
+"x": 382.4906332456932,
+"y": 195.68285425216257,
+"type": "cubic"
+},
+{
+"x": 21,
+"y": 36
+},
+{
+"x": 29,
+"y": 30,
+"type": "cubic"
+},
+{
+"x": 37,
+"y": 20,
+"type": "cubic"
+},
+{
+"x": 42,
+"y": 13
+},
+{
+"x": 408,
+"y": 179,
+"type": "cubic"
+},
+{
+"x": 722,
+"y": 446,
+"type": "cubic"
+},
+{
+"x": 951,
+"y": 780
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"top_weightV=100": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 924,
+"y": 893
+},
+{
+"x": 685.8400578239529,
+"y": 540.1299939318201,
+"type": "cubic"
+},
+{
+"x": 398.38893626474754,
+"y": 202.70568187304565,
+"type": "cubic"
+},
+{
+"x": 21,
+"y": 36
+},
+{
+"x": 29,
+"y": 30,
+"type": "cubic"
+},
+{
+"x": 37,
+"y": 20,
+"type": "cubic"
+},
+{
+"x": 42,
+"y": 13
+},
+{
+"x": 408,
+"y": 179,
+"type": "cubic"
+},
+{
+"x": 722,
+"y": 446,
+"type": "cubic"
+},
+{
+"x": 951,
+"y": 780
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"weight=170": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 850,
+"y": 819
+},
+{
+"x": 655,
+"y": 494,
+"type": "cubic"
+},
+{
+"x": 344,
+"y": 238,
+"type": "cubic"
+},
+{
+"x": -26,
+"y": 101
+},
+{
+"x": 4,
+"y": 65,
+"type": "cubic"
+},
+{
+"x": 49,
+"y": -3,
+"type": "cubic"
+},
+{
+"x": 72,
+"y": -45
+},
+{
+"x": 480,
+"y": 120,
+"type": "cubic"
+},
+{
+"x": 781,
+"y": 381,
+"type": "cubic"
+},
+{
+"x": 1015,
+"y": 758
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"weight=170,height=130": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 919,
+"y": 878
+},
+{
+"x": 639.2521646444263,
+"y": 797.7925786742761,
+"type": "cubic"
+},
+{
+"x": 340.64673980204435,
+"y": 760.9538980551853,
+"type": "cubic"
+},
+{
+"x": 29,
+"y": 759
+},
+{
+"x": 35,
+"y": 712,
+"type": "cubic"
+},
+{
+"x": 36,
+"y": 637,
+"type": "cubic"
+},
+{
+"x": 32,
+"y": 588
+},
+{
+"x": 349,
+"y": 592,
+"type": "cubic"
+},
+{
+"x": 655,
+"y": 625,
+"type": "cubic"
+},
+{
+"x": 951,
+"y": 710
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"weight=170,width=130": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 851,
+"y": 792
+},
+{
+"x": 838.150779897201,
+"y": 534.0271963976514,
+"type": "cubic"
+},
+{
+"x": 807.29174163576,
+"y": 255.52109572515965,
+"type": "cubic"
+},
+{
+"x": 742,
+"y": 27
+},
+{
+"x": 799,
+"y": 22,
+"type": "cubic"
+},
+{
+"x": 857.9047250160156,
+"y": 12.019407867107926,
+"type": "cubic"
+},
+{
+"x": 912,
+"y": 1
+},
+{
+"x": 976,
+"y": 232,
+"type": "cubic"
+},
+{
+"x": 1008,
+"y": 512,
+"type": "cubic"
+},
+{
+"x": 1021,
+"y": 780
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"weight=170,width=130,bottom_weightV=100": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 851,
+"y": 792
+},
+{
+"x": 837,
+"y": 563,
+"type": "cubic"
+},
+{
+"x": 807,
+"y": 352,
+"type": "cubic"
+},
+{
+"x": 742,
+"y": 127
+},
+{
+"x": 800,
+"y": 88,
+"type": "cubic"
+},
+{
+"x": 858,
+"y": 45,
+"type": "cubic"
+},
+{
+"x": 912,
+"y": 1
+},
+{
+"x": 976,
+"y": 232,
+"type": "cubic"
+},
+{
+"x": 1008,
+"y": 512,
+"type": "cubic"
+},
+{
+"x": 1021,
+"y": 780
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"weight=170,width=130,height=130": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 858,
+"y": 831
+},
+{
+"x": 829,
+"y": 782,
+"type": "cubic"
+},
+{
+"x": 808,
+"y": 750,
+"type": "cubic"
+},
+{
+"x": 774,
+"y": 708
+},
+{
+"x": 817,
+"y": 682,
+"type": "cubic"
+},
+{
+"x": 874,
+"y": 643,
+"type": "cubic"
+},
+{
+"x": 916,
+"y": 611
+},
+{
+"x": 952,
+"y": 654,
+"type": "cubic"
+},
+{
+"x": 978,
+"y": 693,
+"type": "cubic"
+},
+{
+"x": 1009,
+"y": 750
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"weight=170,width=130,height=130,top_weightH=-100": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 958,
+"y": 831
+},
+{
+"x": 895,
+"y": 785,
+"type": "cubic"
+},
+{
+"x": 844,
+"y": 751,
+"type": "cubic"
+},
+{
+"x": 774,
+"y": 708
+},
+{
+"x": 817,
+"y": 682,
+"type": "cubic"
+},
+{
+"x": 874,
+"y": 643,
+"type": "cubic"
+},
+{
+"x": 916,
+"y": 611
+},
+{
+"x": 954,
+"y": 654,
+"type": "cubic"
+},
+{
+"x": 976,
+"y": 693,
+"type": "cubic"
+},
+{
+"x": 1009,
+"y": 750
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"weight=170,width=130,height=130,top_weightH=100,bottom_weightV=100": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 758,
+"y": 831
+},
+{
+"x": 764,
+"y": 826,
+"type": "cubic"
+},
+{
+"x": 769,
+"y": 819,
+"type": "cubic"
+},
+{
+"x": 774,
+"y": 808
+},
+{
+"x": 818,
+"y": 748,
+"type": "cubic"
+},
+{
+"x": 874,
+"y": 676,
+"type": "cubic"
+},
+{
+"x": 916,
+"y": 611
+},
+{
+"x": 954,
+"y": 654,
+"type": "cubic"
+},
+{
+"x": 976,
+"y": 693,
+"type": "cubic"
+},
+{
+"x": 1009,
+"y": 750
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"weight=170,width=130,top_weightH=-100": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 951,
+"y": 792
+},
+{
+"x": 918,
+"y": 522,
+"type": "cubic"
+},
+{
+"x": 850,
+"y": 271,
+"type": "cubic"
+},
+{
+"x": 742,
+"y": 27
+},
+{
+"x": 799,
+"y": 22,
+"type": "cubic"
+},
+{
+"x": 858,
+"y": 12,
+"type": "cubic"
+},
+{
+"x": 912,
+"y": 1
+},
+{
+"x": 976,
+"y": 232,
+"type": "cubic"
+},
+{
+"x": 1008,
+"y": 512,
+"type": "cubic"
+},
+{
+"x": 1021,
+"y": 780
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"weight=170,width=130,top_weightH=100,bottom_weightV=100": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 751,
+"y": 792
+},
+{
+"x": 766,
+"y": 574,
+"type": "cubic"
+},
+{
+"x": 763,
+"y": 337,
+"type": "cubic"
+},
+{
+"x": 742,
+"y": 127
+},
+{
+"x": 800,
+"y": 88,
+"type": "cubic"
+},
+{
+"x": 858,
+"y": 45,
+"type": "cubic"
+},
+{
+"x": 912,
+"y": 1
+},
+{
+"x": 976,
+"y": 232,
+"type": "cubic"
+},
+{
+"x": 1008,
+"y": 512,
+"type": "cubic"
+},
+{
+"x": 1021,
+"y": 780
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"wght=1,weight=170,width=130,height=130,bottom_weightV=100": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 858,
+"y": 831
+},
+{
+"x": 830,
+"y": 823,
+"type": "cubic"
+},
+{
+"x": 803,
+"y": 816,
+"type": "cubic"
+},
+{
+"x": 774,
+"y": 808
+},
+{
+"x": 818,
+"y": 748,
+"type": "cubic"
+},
+{
+"x": 874,
+"y": 676,
+"type": "cubic"
+},
+{
+"x": 916,
+"y": 611
+},
+{
+"x": 952,
+"y": 654,
+"type": "cubic"
+},
+{
+"x": 978,
+"y": 693,
+"type": "cubic"
+},
+{
+"x": 1009,
+"y": 750
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"wght=1,weight=170,width=130,height=130,top_weightH=100,bottom_weightH=-100": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 758,
+"y": 831
+},
+{
+"x": 790,
+"y": 803,
+"type": "cubic"
+},
+{
+"x": 845,
+"y": 746,
+"type": "cubic"
+},
+{
+"x": 874,
+"y": 708
+},
+{
+"x": 886,
+"y": 680,
+"type": "cubic"
+},
+{
+"x": 908,
+"y": 643,
+"type": "cubic"
+},
+{
+"x": 916,
+"y": 611
+},
+{
+"x": 952,
+"y": 654,
+"type": "cubic"
+},
+{
+"x": 978,
+"y": 693,
+"type": "cubic"
+},
+{
+"x": 1009,
+"y": 750
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"wght=1,weight=170,width=130,top_weightH=100,bottom_weightH=-100": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 751,
+"y": 792
+},
+{
+"x": 789,
+"y": 556,
+"type": "cubic"
+},
+{
+"x": 824,
+"y": 226,
+"type": "cubic"
+},
+{
+"x": 842,
+"y": 27
+},
+{
+"x": 868,
+"y": 20,
+"type": "cubic"
+},
+{
+"x": 892,
+"y": 12,
+"type": "cubic"
+},
+{
+"x": 912,
+"y": 1
+},
+{
+"x": 976,
+"y": 232,
+"type": "cubic"
+},
+{
+"x": 1008,
+"y": 512,
+"type": "cubic"
+},
+{
+"x": 1021,
+"y": 780
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"width=130": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 921,
+"y": 781
+},
+{
+"x": 907.9834970985261,
+"y": 519.6686725165625,
+"type": "cubic"
+},
+{
+"x": 878,
+"y": 238,
+"type": "cubic"
+},
+{
+"x": 812,
+"y": 7
+},
+{
+"x": 822,
+"y": 7,
+"type": "cubic"
+},
+{
+"x": 834,
+"y": 4,
+"type": "cubic"
+},
+{
+"x": 842,
+"y": 1
+},
+{
+"x": 906,
+"y": 232,
+"type": "cubic"
+},
+{
+"x": 938,
+"y": 512,
+"type": "cubic"
+},
+{
+"x": 951,
+"y": 780
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"width=130,bottom_weightH=-100": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 921,
+"y": 781
+},
+{
+"x": 931,
+"y": 531,
+"type": "cubic"
+},
+{
+"x": 927,
+"y": 223,
+"type": "cubic"
+},
+{
+"x": 912,
+"y": 7
+},
+{
+"x": 891,
+"y": 5,
+"type": "cubic"
+},
+{
+"x": 868,
+"y": 4,
+"type": "cubic"
+},
+{
+"x": 842,
+"y": 1
+},
+{
+"x": 906,
+"y": 232,
+"type": "cubic"
+},
+{
+"x": 938,
+"y": 512,
+"type": "cubic"
+},
+{
+"x": 951,
+"y": 780
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"width=130,bottom_weightV=100": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 921,
+"y": 781
+},
+{
+"x": 906,
+"y": 546,
+"type": "cubic"
+},
+{
+"x": 874,
+"y": 335,
+"type": "cubic"
+},
+{
+"x": 812,
+"y": 107
+},
+{
+"x": 823,
+"y": 73,
+"type": "cubic"
+},
+{
+"x": 834,
+"y": 37,
+"type": "cubic"
+},
+{
+"x": 842,
+"y": 1
+},
+{
+"x": 906,
+"y": 232,
+"type": "cubic"
+},
+{
+"x": 938,
+"y": 512,
+"type": "cubic"
+},
+{
+"x": 951,
+"y": 780
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"width=130,height=130": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 925,
+"y": 795
+},
+{
+"x": 900,
+"y": 754,
+"type": "cubic"
+},
+{
+"x": 866,
+"y": 706,
+"type": "cubic"
+},
+{
+"x": 833,
+"y": 671
+},
+{
+"x": 841,
+"y": 666,
+"type": "cubic"
+},
+{
+"x": 852,
+"y": 657,
+"type": "cubic"
+},
+{
+"x": 857,
+"y": 652
+},
+{
+"x": 888,
+"y": 687,
+"type": "cubic"
+},
+{
+"x": 924,
+"y": 736,
+"type": "cubic"
+},
+{
+"x": 951,
+"y": 780
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"width=130,height=130,bottom_weightV=100": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 925,
+"y": 795
+},
+{
+"x": 892,
+"y": 786,
+"type": "cubic"
+},
+{
+"x": 866,
+"y": 779,
+"type": "cubic"
+},
+{
+"x": 833,
+"y": 771
+},
+{
+"x": 842,
+"y": 732,
+"type": "cubic"
+},
+{
+"x": 852,
+"y": 690,
+"type": "cubic"
+},
+{
+"x": 857,
+"y": 652
+},
+{
+"x": 888,
+"y": 687,
+"type": "cubic"
+},
+{
+"x": 924,
+"y": 736,
+"type": "cubic"
+},
+{
+"x": 951,
+"y": 780
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+}
+}
+}
diff --git a/tests/data/notosanscjksc.fontra/glyphs/VG_531A_00^32.json b/tests/data/notosanscjksc.fontra/glyphs/VG_531A_00^32.json
new file mode 100644
index 0000000..168b63b
--- /dev/null
+++ b/tests/data/notosanscjksc.fontra/glyphs/VG_531A_00^32.json
@@ -0,0 +1,1033 @@
+{
+"name": "VG_531A_00",
+"axes": [
+{
+"name": "width",
+"minValue": 100,
+"defaultValue": 1000,
+"maxValue": 1000
+},
+{
+"name": "height",
+"minValue": 100,
+"defaultValue": 1000,
+"maxValue": 1000
+},
+{
+"name": "weight",
+"minValue": 20,
+"defaultValue": 20,
+"maxValue": 160
+},
+{
+"name": "L_S_end_length",
+"minValue": 0,
+"defaultValue": 0,
+"maxValue": 100
+},
+{
+"name": "L_S_weight",
+"minValue": -20,
+"defaultValue": 0,
+"maxValue": 20
+},
+{
+"name": "TB_2H_weight",
+"minValue": -50,
+"defaultValue": 0,
+"maxValue": 50
+},
+{
+"name": "T_H_right_length",
+"minValue": -50,
+"defaultValue": 0,
+"maxValue": 50
+}
+],
+"sources": [
+{
+"name": "",
+"layerName": "foreground",
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "width=100",
+"layerName": "width=100",
+"location": {
+"width": 100
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "height=100",
+"layerName": "height=100",
+"location": {
+"height": 100
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "width=100,height=100",
+"layerName": "width=100,height=100",
+"location": {
+"height": 100,
+"width": 100
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "weight=160",
+"layerName": "weight=160",
+"location": {
+"weight": 160
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "L_S_end_length=100",
+"layerName": "L_S_end_length=100",
+"location": {
+"L_S_end_length": 100
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "L_S_weight=20",
+"layerName": "L_S_weight=20",
+"location": {
+"L_S_weight": 20
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "L_S_weight=-20",
+"layerName": "L_S_weight=-20",
+"location": {
+"L_S_weight": -20
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "TB_2H_weight=50",
+"layerName": "TB_2H_weight=50",
+"location": {
+"TB_2H_weight": 50
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "TB_2H_weight=-50",
+"layerName": "TB_2H_weight=-50",
+"location": {
+"TB_2H_weight": -50
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "T_H_right_length=50",
+"layerName": "T_H_right_length=50",
+"location": {
+"T_H_right_length": 50
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "T_H_right_length=-50",
+"layerName": "T_H_right_length=-50",
+"location": {
+"T_H_right_length": -50
+},
+"customData": {
+"fontra.development.status": 0
+}
+}
+],
+"layers": {
+"L_S_end_length=100": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 0,
+"y": 880
+},
+{
+"x": 0,
+"y": -220
+},
+{
+"x": 20,
+"y": -220
+},
+{
+"x": 20,
+"y": 880
+}
+],
+"isClosed": true
+},
+{
+"points": [
+{
+"x": 0,
+"y": 880
+},
+{
+"x": 0,
+"y": 860
+},
+{
+"x": 1000,
+"y": 860
+},
+{
+"x": 1000,
+"y": 880
+}
+],
+"isClosed": true
+},
+{
+"points": [
+{
+"x": 0,
+"y": -100
+},
+{
+"x": 0,
+"y": -120
+},
+{
+"x": 1000,
+"y": -120
+},
+{
+"x": 1000,
+"y": -100
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"L_S_weight=-20": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 0,
+"y": 880
+},
+{
+"x": 0,
+"y": -120
+},
+{
+"x": 0,
+"y": -120
+},
+{
+"x": 0,
+"y": 880
+}
+],
+"isClosed": true
+},
+{
+"points": [
+{
+"x": 0,
+"y": 880
+},
+{
+"x": 0,
+"y": 860
+},
+{
+"x": 1000,
+"y": 860
+},
+{
+"x": 1000,
+"y": 880
+}
+],
+"isClosed": true
+},
+{
+"points": [
+{
+"x": 0,
+"y": -100
+},
+{
+"x": 0,
+"y": -120
+},
+{
+"x": 1000,
+"y": -120
+},
+{
+"x": 1000,
+"y": -100
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"L_S_weight=20": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 0,
+"y": 880
+},
+{
+"x": 0,
+"y": -120
+},
+{
+"x": 40,
+"y": -120
+},
+{
+"x": 40,
+"y": 880
+}
+],
+"isClosed": true
+},
+{
+"points": [
+{
+"x": 0,
+"y": 880
+},
+{
+"x": 0,
+"y": 860
+},
+{
+"x": 1000,
+"y": 860
+},
+{
+"x": 1000,
+"y": 880
+}
+],
+"isClosed": true
+},
+{
+"points": [
+{
+"x": 0,
+"y": -100
+},
+{
+"x": 0,
+"y": -120
+},
+{
+"x": 1000,
+"y": -120
+},
+{
+"x": 1000,
+"y": -100
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"TB_2H_weight=-50": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 0,
+"y": 880
+},
+{
+"x": 0,
+"y": -120
+},
+{
+"x": 20,
+"y": -120
+},
+{
+"x": 20,
+"y": 880
+}
+],
+"isClosed": true
+},
+{
+"points": [
+{
+"x": 0,
+"y": 880
+},
+{
+"x": 0,
+"y": 910
+},
+{
+"x": 1000,
+"y": 910
+},
+{
+"x": 1000,
+"y": 880
+}
+],
+"isClosed": true
+},
+{
+"points": [
+{
+"x": 0,
+"y": -150
+},
+{
+"x": 0,
+"y": -120
+},
+{
+"x": 1000,
+"y": -120
+},
+{
+"x": 1000,
+"y": -150
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"TB_2H_weight=50": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 0,
+"y": 880
+},
+{
+"x": 0,
+"y": -120
+},
+{
+"x": 20,
+"y": -120
+},
+{
+"x": 20,
+"y": 880
+}
+],
+"isClosed": true
+},
+{
+"points": [
+{
+"x": 0,
+"y": 880
+},
+{
+"x": 0,
+"y": 810
+},
+{
+"x": 1000,
+"y": 810
+},
+{
+"x": 1000,
+"y": 880
+}
+],
+"isClosed": true
+},
+{
+"points": [
+{
+"x": 0,
+"y": -50
+},
+{
+"x": 0,
+"y": -120
+},
+{
+"x": 1000,
+"y": -120
+},
+{
+"x": 1000,
+"y": -50
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"T_H_right_length=-50": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 0,
+"y": 880
+},
+{
+"x": 0,
+"y": -120
+},
+{
+"x": 20,
+"y": -120
+},
+{
+"x": 20,
+"y": 880
+}
+],
+"isClosed": true
+},
+{
+"points": [
+{
+"x": 0,
+"y": 880
+},
+{
+"x": 0,
+"y": 860
+},
+{
+"x": 950,
+"y": 860
+},
+{
+"x": 950,
+"y": 880
+}
+],
+"isClosed": true
+},
+{
+"points": [
+{
+"x": 0,
+"y": -100
+},
+{
+"x": 0,
+"y": -120
+},
+{
+"x": 1000,
+"y": -120
+},
+{
+"x": 1000,
+"y": -100
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"T_H_right_length=50": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 0,
+"y": 880
+},
+{
+"x": 0,
+"y": -120
+},
+{
+"x": 20,
+"y": -120
+},
+{
+"x": 20,
+"y": 880
+}
+],
+"isClosed": true
+},
+{
+"points": [
+{
+"x": 0,
+"y": 880
+},
+{
+"x": 0,
+"y": 860
+},
+{
+"x": 1050,
+"y": 860
+},
+{
+"x": 1050,
+"y": 880
+}
+],
+"isClosed": true
+},
+{
+"points": [
+{
+"x": 0,
+"y": -100
+},
+{
+"x": 0,
+"y": -120
+},
+{
+"x": 1000,
+"y": -120
+},
+{
+"x": 1000,
+"y": -100
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"foreground": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 0,
+"y": 880
+},
+{
+"x": 0,
+"y": -120
+},
+{
+"x": 20,
+"y": -120
+},
+{
+"x": 20,
+"y": 880
+}
+],
+"isClosed": true
+},
+{
+"points": [
+{
+"x": 0,
+"y": 880
+},
+{
+"x": 0,
+"y": 860
+},
+{
+"x": 1000,
+"y": 860
+},
+{
+"x": 1000,
+"y": 880
+}
+],
+"isClosed": true
+},
+{
+"points": [
+{
+"x": 0,
+"y": -100
+},
+{
+"x": 0,
+"y": -120
+},
+{
+"x": 1000,
+"y": -120
+},
+{
+"x": 1000,
+"y": -100
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"height=100": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 0,
+"y": -20
+},
+{
+"x": 0,
+"y": -120
+},
+{
+"x": 20,
+"y": -120
+},
+{
+"x": 20,
+"y": -20
+}
+],
+"isClosed": true
+},
+{
+"points": [
+{
+"x": 0,
+"y": -20
+},
+{
+"x": 0,
+"y": -40
+},
+{
+"x": 1000,
+"y": -40
+},
+{
+"x": 1000,
+"y": -20
+}
+],
+"isClosed": true
+},
+{
+"points": [
+{
+"x": 0,
+"y": -100
+},
+{
+"x": 0,
+"y": -120
+},
+{
+"x": 1000,
+"y": -120
+},
+{
+"x": 1000,
+"y": -100
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"weight=160": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 0,
+"y": 880
+},
+{
+"x": 0,
+"y": -120
+},
+{
+"x": 160,
+"y": -120
+},
+{
+"x": 160,
+"y": 880
+}
+],
+"isClosed": true
+},
+{
+"points": [
+{
+"x": 0,
+"y": 880
+},
+{
+"x": 0,
+"y": 720
+},
+{
+"x": 1000,
+"y": 720
+},
+{
+"x": 1000,
+"y": 880
+}
+],
+"isClosed": true
+},
+{
+"points": [
+{
+"x": 0,
+"y": 40
+},
+{
+"x": 0,
+"y": -120
+},
+{
+"x": 1000,
+"y": -120
+},
+{
+"x": 1000,
+"y": 40
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"width=100": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 0,
+"y": 880
+},
+{
+"x": 0,
+"y": -120
+},
+{
+"x": 20,
+"y": -120
+},
+{
+"x": 20,
+"y": 880
+}
+],
+"isClosed": true
+},
+{
+"points": [
+{
+"x": 0,
+"y": 880
+},
+{
+"x": 0,
+"y": 860
+},
+{
+"x": 100,
+"y": 860
+},
+{
+"x": 100,
+"y": 880
+}
+],
+"isClosed": true
+},
+{
+"points": [
+{
+"x": 0,
+"y": -100
+},
+{
+"x": 0,
+"y": -120
+},
+{
+"x": 100,
+"y": -120
+},
+{
+"x": 100,
+"y": -100
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"width=100,height=100": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 0,
+"y": -20
+},
+{
+"x": 0,
+"y": -120
+},
+{
+"x": 20,
+"y": -120
+},
+{
+"x": 20,
+"y": -20
+}
+],
+"isClosed": true
+},
+{
+"points": [
+{
+"x": 0,
+"y": -20
+},
+{
+"x": 0,
+"y": -40
+},
+{
+"x": 100,
+"y": -40
+},
+{
+"x": 100,
+"y": -20
+}
+],
+"isClosed": true
+},
+{
+"points": [
+{
+"x": 0,
+"y": -100
+},
+{
+"x": 0,
+"y": -120
+},
+{
+"x": 100,
+"y": -120
+},
+{
+"x": 100,
+"y": -100
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+}
+}
+}
diff --git a/tests/data/notosanscjksc.fontra/glyphs/VG_53E3_00^31.json b/tests/data/notosanscjksc.fontra/glyphs/VG_53E3_00^31.json
new file mode 100644
index 0000000..2fd0b0f
--- /dev/null
+++ b/tests/data/notosanscjksc.fontra/glyphs/VG_53E3_00^31.json
@@ -0,0 +1,1459 @@
+{
+"name": "VG_53E3_00",
+"axes": [
+{
+"name": "weight",
+"minValue": 30,
+"defaultValue": 30,
+"maxValue": 160
+},
+{
+"name": "T_H_weight",
+"minValue": -100,
+"defaultValue": 0,
+"maxValue": 100
+},
+{
+"name": "B_H_weight",
+"minValue": -100,
+"defaultValue": 0,
+"maxValue": 100
+},
+{
+"name": "L_S_weight",
+"minValue": -100,
+"defaultValue": 0,
+"maxValue": 100
+},
+{
+"name": "R_S_weight",
+"minValue": -100,
+"defaultValue": 0,
+"maxValue": 100
+},
+{
+"name": "height",
+"minValue": 60,
+"defaultValue": 1000,
+"maxValue": 1000
+},
+{
+"name": "width",
+"minValue": 60,
+"defaultValue": 1000,
+"maxValue": 1000
+},
+{
+"name": "L_S_bottom_length",
+"minValue": 0,
+"defaultValue": 0,
+"maxValue": 200
+},
+{
+"name": "R_S_bottom_length",
+"minValue": 0,
+"defaultValue": 0,
+"maxValue": 200
+},
+{
+"name": "B_H_moveV",
+"minValue": -300,
+"defaultValue": 0,
+"maxValue": 300
+},
+{
+"name": "B_H_length",
+"minValue": -500,
+"defaultValue": 0,
+"maxValue": 0
+}
+],
+"sources": [
+{
+"name": "",
+"layerName": "foreground",
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "weight=160",
+"layerName": "weight=160",
+"location": {
+"weight": 160
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "T_H_weight=100",
+"layerName": "T_H_weight=100",
+"location": {
+"T_H_weight": 100
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "T_H_weight=-100",
+"layerName": "T_H_weight=-100",
+"location": {
+"T_H_weight": -100
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "B_H_weight=100",
+"layerName": "B_H_weight=100",
+"location": {
+"B_H_weight": 100
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "B_H_weight=-100",
+"layerName": "B_H_weight=-100",
+"location": {
+"B_H_weight": -100
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "L_S_weight=100",
+"layerName": "L_S_weight=100",
+"location": {
+"L_S_weight": 100
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "L_S_weight=-100",
+"layerName": "L_S_weight=-100",
+"location": {
+"L_S_weight": -100
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "R_S_weight=100",
+"layerName": "R_S_weight=100",
+"location": {
+"R_S_weight": 100
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "R_S_weight=-100",
+"layerName": "R_S_weight=-100",
+"location": {
+"R_S_weight": -100
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "height=60",
+"layerName": "height=60",
+"location": {
+"height": 60
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "width=60",
+"layerName": "width=60",
+"location": {
+"width": 60
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "height=60,width=60",
+"layerName": "height=60,width=60",
+"location": {
+"height": 60,
+"width": 60
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "L_S_bottom_length=200",
+"layerName": "L_S_bottom_length=200",
+"location": {
+"L_S_bottom_length": 200
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "R_S_bottom_length=200",
+"layerName": "R_S_bottom_length=200",
+"location": {
+"R_S_bottom_length": 200
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "B_H_moveV=300",
+"layerName": "B_H_moveV=300",
+"location": {
+"B_H_moveV": 300
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "B_H_moveV=-300",
+"layerName": "B_H_moveV=-300",
+"location": {
+"B_H_moveV": -300
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "B_H_length=-500",
+"layerName": "B_H_length=-500",
+"location": {
+"B_H_length": -500
+},
+"customData": {
+"fontra.development.status": 0
+}
+}
+],
+"layers": {
+"B_H_length=-500": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 0,
+"y": 880
+},
+{
+"x": 0,
+"y": -120
+},
+{
+"x": 30,
+"y": -120
+},
+{
+"x": 30,
+"y": 850
+},
+{
+"x": 970,
+"y": 850
+},
+{
+"x": 970,
+"y": -120
+},
+{
+"x": 1000,
+"y": -120
+},
+{
+"x": 1000,
+"y": 880
+}
+],
+"isClosed": true
+},
+{
+"points": [
+{
+"x": 260,
+"y": -90
+},
+{
+"x": 260,
+"y": -120
+},
+{
+"x": 740,
+"y": -120
+},
+{
+"x": 740,
+"y": -90
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"B_H_moveV=-300": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 0,
+"y": 880
+},
+{
+"x": 0,
+"y": -120
+},
+{
+"x": 30,
+"y": -120
+},
+{
+"x": 30,
+"y": 850
+},
+{
+"x": 970,
+"y": 850
+},
+{
+"x": 970,
+"y": -120
+},
+{
+"x": 1000,
+"y": -120
+},
+{
+"x": 1000,
+"y": 880
+}
+],
+"isClosed": true
+},
+{
+"points": [
+{
+"x": 10,
+"y": -390
+},
+{
+"x": 10,
+"y": -420
+},
+{
+"x": 999,
+"y": -420
+},
+{
+"x": 999,
+"y": -390
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"B_H_moveV=300": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 0,
+"y": 880
+},
+{
+"x": 0,
+"y": -120
+},
+{
+"x": 30,
+"y": -120
+},
+{
+"x": 30,
+"y": 850
+},
+{
+"x": 970,
+"y": 850
+},
+{
+"x": 970,
+"y": -120
+},
+{
+"x": 1000,
+"y": -120
+},
+{
+"x": 1000,
+"y": 880
+}
+],
+"isClosed": true
+},
+{
+"points": [
+{
+"x": 10,
+"y": 210
+},
+{
+"x": 10,
+"y": 180
+},
+{
+"x": 999,
+"y": 180
+},
+{
+"x": 999,
+"y": 210
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"B_H_weight=-100": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 0,
+"y": 880
+},
+{
+"x": 0,
+"y": -120
+},
+{
+"x": 30,
+"y": -120
+},
+{
+"x": 30,
+"y": 850
+},
+{
+"x": 970,
+"y": 850
+},
+{
+"x": 970,
+"y": -120
+},
+{
+"x": 1000,
+"y": -120
+},
+{
+"x": 1000,
+"y": 880
+}
+],
+"isClosed": true
+},
+{
+"points": [
+{
+"x": 10,
+"y": -190
+},
+{
+"x": 10,
+"y": -120
+},
+{
+"x": 999,
+"y": -120
+},
+{
+"x": 999,
+"y": -190
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"B_H_weight=100": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 0,
+"y": 880
+},
+{
+"x": 0,
+"y": -120
+},
+{
+"x": 30,
+"y": -120
+},
+{
+"x": 30,
+"y": 850
+},
+{
+"x": 970,
+"y": 850
+},
+{
+"x": 970,
+"y": -120
+},
+{
+"x": 1000,
+"y": -120
+},
+{
+"x": 1000,
+"y": 880
+}
+],
+"isClosed": true
+},
+{
+"points": [
+{
+"x": 10,
+"y": 10
+},
+{
+"x": 10,
+"y": -120
+},
+{
+"x": 999,
+"y": -120
+},
+{
+"x": 999,
+"y": 10
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"L_S_bottom_length=200": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 0,
+"y": 880
+},
+{
+"x": 0,
+"y": -320
+},
+{
+"x": 30,
+"y": -320
+},
+{
+"x": 30,
+"y": 850
+},
+{
+"x": 970,
+"y": 850
+},
+{
+"x": 970,
+"y": -120
+},
+{
+"x": 1000,
+"y": -120
+},
+{
+"x": 1000,
+"y": 880
+}
+],
+"isClosed": true
+},
+{
+"points": [
+{
+"x": 10,
+"y": -90
+},
+{
+"x": 10,
+"y": -120
+},
+{
+"x": 999,
+"y": -120
+},
+{
+"x": 999,
+"y": -90
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"L_S_weight=-100": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 0,
+"y": 880
+},
+{
+"x": 0,
+"y": -120
+},
+{
+"x": -70,
+"y": -120
+},
+{
+"x": -70,
+"y": 850
+},
+{
+"x": 970,
+"y": 850
+},
+{
+"x": 970,
+"y": -120
+},
+{
+"x": 1000,
+"y": -120
+},
+{
+"x": 1000,
+"y": 880
+}
+],
+"isClosed": true
+},
+{
+"points": [
+{
+"x": 10,
+"y": -90
+},
+{
+"x": 10,
+"y": -120
+},
+{
+"x": 999,
+"y": -120
+},
+{
+"x": 999,
+"y": -90
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"L_S_weight=100": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 0,
+"y": 880
+},
+{
+"x": 0,
+"y": -120
+},
+{
+"x": 130,
+"y": -120
+},
+{
+"x": 130,
+"y": 850
+},
+{
+"x": 970,
+"y": 850
+},
+{
+"x": 970,
+"y": -120
+},
+{
+"x": 1000,
+"y": -120
+},
+{
+"x": 1000,
+"y": 880
+}
+],
+"isClosed": true
+},
+{
+"points": [
+{
+"x": 10,
+"y": -90
+},
+{
+"x": 10,
+"y": -120
+},
+{
+"x": 999,
+"y": -120
+},
+{
+"x": 999,
+"y": -90
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"R_S_bottom_length=200": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 0,
+"y": 880
+},
+{
+"x": 0,
+"y": -120
+},
+{
+"x": 30,
+"y": -120
+},
+{
+"x": 30,
+"y": 850
+},
+{
+"x": 970,
+"y": 850
+},
+{
+"x": 970,
+"y": -320
+},
+{
+"x": 1000,
+"y": -320
+},
+{
+"x": 1000,
+"y": 880
+}
+],
+"isClosed": true
+},
+{
+"points": [
+{
+"x": 10,
+"y": -90
+},
+{
+"x": 10,
+"y": -120
+},
+{
+"x": 999,
+"y": -120
+},
+{
+"x": 999,
+"y": -90
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"R_S_weight=-100": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 0,
+"y": 880
+},
+{
+"x": 0,
+"y": -120
+},
+{
+"x": 30,
+"y": -120
+},
+{
+"x": 30,
+"y": 850
+},
+{
+"x": 1070,
+"y": 850
+},
+{
+"x": 1070,
+"y": -120
+},
+{
+"x": 1000,
+"y": -120
+},
+{
+"x": 1000,
+"y": 880
+}
+],
+"isClosed": true
+},
+{
+"points": [
+{
+"x": 10,
+"y": -90
+},
+{
+"x": 10,
+"y": -120
+},
+{
+"x": 999,
+"y": -120
+},
+{
+"x": 999,
+"y": -90
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"R_S_weight=100": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 0,
+"y": 880
+},
+{
+"x": 0,
+"y": -120
+},
+{
+"x": 30,
+"y": -120
+},
+{
+"x": 30,
+"y": 850
+},
+{
+"x": 870,
+"y": 850
+},
+{
+"x": 870,
+"y": -120
+},
+{
+"x": 1000,
+"y": -120
+},
+{
+"x": 1000,
+"y": 880
+}
+],
+"isClosed": true
+},
+{
+"points": [
+{
+"x": 10,
+"y": -90
+},
+{
+"x": 10,
+"y": -120
+},
+{
+"x": 999,
+"y": -120
+},
+{
+"x": 999,
+"y": -90
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"T_H_weight=-100": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 0,
+"y": 880
+},
+{
+"x": 0,
+"y": -120
+},
+{
+"x": 30,
+"y": -120
+},
+{
+"x": 30,
+"y": 950
+},
+{
+"x": 970,
+"y": 950
+},
+{
+"x": 970,
+"y": -120
+},
+{
+"x": 1000,
+"y": -120
+},
+{
+"x": 1000,
+"y": 880
+}
+],
+"isClosed": true
+},
+{
+"points": [
+{
+"x": 10,
+"y": -90
+},
+{
+"x": 10,
+"y": -120
+},
+{
+"x": 999,
+"y": -120
+},
+{
+"x": 999,
+"y": -90
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"T_H_weight=100": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 0,
+"y": 880
+},
+{
+"x": 0,
+"y": -120
+},
+{
+"x": 30,
+"y": -120
+},
+{
+"x": 30,
+"y": 750
+},
+{
+"x": 970,
+"y": 750
+},
+{
+"x": 970,
+"y": -120
+},
+{
+"x": 1000,
+"y": -120
+},
+{
+"x": 1000,
+"y": 880
+}
+],
+"isClosed": true
+},
+{
+"points": [
+{
+"x": 10,
+"y": -90
+},
+{
+"x": 10,
+"y": -120
+},
+{
+"x": 999,
+"y": -120
+},
+{
+"x": 999,
+"y": -90
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"foreground": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 0,
+"y": 880
+},
+{
+"x": 0,
+"y": -120
+},
+{
+"x": 30,
+"y": -120
+},
+{
+"x": 30,
+"y": 850
+},
+{
+"x": 970,
+"y": 850
+},
+{
+"x": 970,
+"y": -120
+},
+{
+"x": 1000,
+"y": -120
+},
+{
+"x": 1000,
+"y": 880
+}
+],
+"isClosed": true
+},
+{
+"points": [
+{
+"x": 10,
+"y": -90
+},
+{
+"x": 10,
+"y": -120
+},
+{
+"x": 999,
+"y": -120
+},
+{
+"x": 999,
+"y": -90
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"height=60": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 0,
+"y": 880
+},
+{
+"x": 0,
+"y": 820
+},
+{
+"x": 30,
+"y": 820
+},
+{
+"x": 30,
+"y": 850
+},
+{
+"x": 970,
+"y": 850
+},
+{
+"x": 970,
+"y": 820
+},
+{
+"x": 1000,
+"y": 820
+},
+{
+"x": 1000,
+"y": 880
+}
+],
+"isClosed": true
+},
+{
+"points": [
+{
+"x": 10,
+"y": 850
+},
+{
+"x": 10,
+"y": 820
+},
+{
+"x": 999,
+"y": 820
+},
+{
+"x": 999,
+"y": 850
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"height=60,width=60": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 0,
+"y": 880
+},
+{
+"x": 0,
+"y": 820
+},
+{
+"x": 30,
+"y": 820
+},
+{
+"x": 30,
+"y": 850
+},
+{
+"x": 30,
+"y": 850
+},
+{
+"x": 30,
+"y": 820
+},
+{
+"x": 60,
+"y": 820
+},
+{
+"x": 60,
+"y": 880
+}
+],
+"isClosed": true
+},
+{
+"points": [
+{
+"x": 10,
+"y": 850
+},
+{
+"x": 10,
+"y": 820
+},
+{
+"x": 59,
+"y": 820
+},
+{
+"x": 59,
+"y": 850
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"weight=160": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 0,
+"y": 880
+},
+{
+"x": 0,
+"y": -120
+},
+{
+"x": 160,
+"y": -120
+},
+{
+"x": 160,
+"y": 720
+},
+{
+"x": 840,
+"y": 720
+},
+{
+"x": 840,
+"y": -120
+},
+{
+"x": 1000,
+"y": -120
+},
+{
+"x": 1000,
+"y": 880
+}
+],
+"isClosed": true
+},
+{
+"points": [
+{
+"x": 10,
+"y": 40
+},
+{
+"x": 10,
+"y": -120
+},
+{
+"x": 999,
+"y": -120
+},
+{
+"x": 999,
+"y": 40
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+},
+"width=60": {
+"glyph": {
+"path": {
+"contours": [
+{
+"points": [
+{
+"x": 0,
+"y": 880
+},
+{
+"x": 0,
+"y": -120
+},
+{
+"x": 30,
+"y": -120
+},
+{
+"x": 30,
+"y": 850
+},
+{
+"x": 30,
+"y": 850
+},
+{
+"x": 30,
+"y": -120
+},
+{
+"x": 60,
+"y": -120
+},
+{
+"x": 60,
+"y": 880
+}
+],
+"isClosed": true
+},
+{
+"points": [
+{
+"x": 10,
+"y": -90
+},
+{
+"x": 10,
+"y": -120
+},
+{
+"x": 59,
+"y": -120
+},
+{
+"x": 59,
+"y": -90
+}
+],
+"isClosed": true
+}
+]
+},
+"xAdvance": 1000
+}
+}
+}
+}
diff --git a/tests/data/notosanscjksc.fontra/glyphs/VG_65E5_00^31.json b/tests/data/notosanscjksc.fontra/glyphs/VG_65E5_00^31.json
new file mode 100644
index 0000000..9387579
--- /dev/null
+++ b/tests/data/notosanscjksc.fontra/glyphs/VG_65E5_00^31.json
@@ -0,0 +1,657 @@
+{
+"name": "VG_65E5_00",
+"axes": [
+{
+"name": "weight",
+"minValue": 20,
+"defaultValue": 20,
+"maxValue": 160
+},
+{
+"name": "width",
+"minValue": 60,
+"defaultValue": 1000,
+"maxValue": 1000
+},
+{
+"name": "height",
+"minValue": 60,
+"defaultValue": 1000,
+"maxValue": 1000
+},
+{
+"name": "H_weight",
+"minValue": -90,
+"defaultValue": 0,
+"maxValue": 50
+},
+{
+"name": "M_H_weight",
+"minValue": -50,
+"defaultValue": 0,
+"maxValue": 0
+},
+{
+"name": "M_H_moveV",
+"minValue": -100,
+"defaultValue": 0,
+"maxValue": 100
+},
+{
+"name": "L_S_bottom_length",
+"minValue": 0,
+"defaultValue": 0,
+"maxValue": 200
+},
+{
+"name": "R_S_bottom_length",
+"minValue": 0,
+"defaultValue": 0,
+"maxValue": 200
+},
+{
+"name": "M_H_right_length",
+"minValue": -200,
+"defaultValue": 0,
+"maxValue": 0
+},
+{
+"name": "L_S_weight",
+"minValue": -100,
+"defaultValue": 0,
+"maxValue": 100
+}
+],
+"sources": [
+{
+"name": "",
+"layerName": "foreground",
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "weight=160",
+"layerName": "weight=160",
+"location": {
+"weight": 160
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "width=60",
+"layerName": "width=60",
+"location": {
+"width": 60
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "height=60",
+"layerName": "height=60",
+"location": {
+"height": 60
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "H_weight=-90",
+"layerName": "H_weight=-90",
+"location": {
+"H_weight": -90
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "M_H_weight=-50",
+"layerName": "M_H_weight=-50",
+"location": {
+"M_H_weight": -50
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "M_H_moveV=-100",
+"layerName": "M_H_moveV=-100",
+"location": {
+"M_H_moveV": -100
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "M_H_moveV=100",
+"layerName": "M_H_moveV=100",
+"location": {
+"M_H_moveV": 100
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "L_S_bottom_length=200",
+"layerName": "L_S_bottom_length=200",
+"location": {
+"L_S_bottom_length": 200
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "R_S_bottom_length=200",
+"layerName": "R_S_bottom_length=200",
+"location": {
+"R_S_bottom_length": 200
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "H_weight=50",
+"layerName": "H_weight=50",
+"location": {
+"H_weight": 50
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "M_H_right_length=-200",
+"layerName": "M_H_right_length=-200",
+"location": {
+"M_H_right_length": -200
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "L_S_weight=100",
+"layerName": "L_S_weight=100",
+"location": {
+"L_S_weight": 100
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "L_S_weight=-100",
+"layerName": "L_S_weight=-100",
+"location": {
+"L_S_weight": -100
+},
+"customData": {
+"fontra.development.status": 0
+}
+}
+],
+"layers": {
+"H_weight=-90": {
+"glyph": {
+"components": [
+{
+"name": "VG_53E3_00",
+"location": {
+"B_H_moveV": 0,
+"B_H_weight": -100,
+"L_S_bottom_length": 0,
+"L_S_weight": -10,
+"R_S_bottom_length": 0,
+"R_S_weight": -10,
+"T_H_weight": -100,
+"height": 1000,
+"weight": 30,
+"width": 1000
+}
+},
+{
+"name": "VG_4E00_00",
+"transformation": {
+"translateY": 35
+},
+"location": {
+"weight": -70,
+"width": 1000
+}
+}
+],
+"xAdvance": 1000
+}
+},
+"H_weight=50": {
+"glyph": {
+"components": [
+{
+"name": "VG_53E3_00",
+"location": {
+"B_H_moveV": 0,
+"B_H_weight": 40,
+"L_S_bottom_length": 0,
+"L_S_weight": -10,
+"R_S_bottom_length": 0,
+"R_S_weight": -10,
+"T_H_weight": 40,
+"height": 1000,
+"weight": 30,
+"width": 1000
+}
+},
+{
+"name": "VG_4E00_00",
+"transformation": {
+"translateY": -35
+},
+"location": {
+"weight": 70,
+"width": 1000
+}
+}
+],
+"xAdvance": 1000
+}
+},
+"L_S_bottom_length=200": {
+"glyph": {
+"components": [
+{
+"name": "VG_53E3_00",
+"location": {
+"B_H_moveV": 0,
+"B_H_weight": -10,
+"L_S_bottom_length": 200,
+"L_S_weight": -10,
+"R_S_bottom_length": 0,
+"R_S_weight": -10,
+"T_H_weight": -10,
+"height": 1000,
+"weight": 30,
+"width": 1000
+}
+},
+{
+"name": "VG_4E00_00",
+"transformation": {
+"translateY": -10
+},
+"location": {
+"weight": 20,
+"width": 1000
+}
+}
+],
+"xAdvance": 1000
+}
+},
+"L_S_weight=-100": {
+"glyph": {
+"components": [
+{
+"name": "VG_53E3_00",
+"location": {
+"B_H_moveV": 0,
+"B_H_weight": -10,
+"L_S_bottom_length": 0,
+"L_S_weight": -100,
+"R_S_bottom_length": 0,
+"R_S_weight": -10,
+"T_H_weight": -10,
+"height": 1000,
+"weight": 30,
+"width": 1000
+}
+},
+{
+"name": "VG_4E00_00",
+"transformation": {
+"translateY": -10
+},
+"location": {
+"weight": 20,
+"width": 1000
+}
+}
+],
+"xAdvance": 1000
+}
+},
+"L_S_weight=100": {
+"glyph": {
+"components": [
+{
+"name": "VG_53E3_00",
+"location": {
+"B_H_moveV": 0,
+"B_H_weight": -10,
+"L_S_bottom_length": 0,
+"L_S_weight": 90,
+"R_S_bottom_length": 0,
+"R_S_weight": -10,
+"T_H_weight": -10,
+"height": 1000,
+"weight": 30,
+"width": 1000
+}
+},
+{
+"name": "VG_4E00_00",
+"transformation": {
+"translateY": -10
+},
+"location": {
+"weight": 20,
+"width": 1000
+}
+}
+],
+"xAdvance": 1000
+}
+},
+"M_H_moveV=-100": {
+"glyph": {
+"components": [
+{
+"name": "VG_53E3_00",
+"location": {
+"B_H_moveV": 0,
+"B_H_weight": -10,
+"L_S_bottom_length": 0,
+"L_S_weight": -10,
+"R_S_bottom_length": 0,
+"R_S_weight": -10,
+"T_H_weight": -10,
+"height": 1000,
+"weight": 30,
+"width": 1000
+}
+},
+{
+"name": "VG_4E00_00",
+"transformation": {
+"translateY": -110
+},
+"location": {
+"weight": 20,
+"width": 1000
+}
+}
+],
+"xAdvance": 1000
+}
+},
+"M_H_moveV=100": {
+"glyph": {
+"components": [
+{
+"name": "VG_53E3_00",
+"location": {
+"B_H_moveV": 0,
+"B_H_weight": -10,
+"L_S_bottom_length": 0,
+"L_S_weight": -10,
+"R_S_bottom_length": 0,
+"R_S_weight": -10,
+"T_H_weight": -10,
+"height": 1000,
+"weight": 30,
+"width": 1000
+}
+},
+{
+"name": "VG_4E00_00",
+"transformation": {
+"translateY": 90
+},
+"location": {
+"weight": 20,
+"width": 1000
+}
+}
+],
+"xAdvance": 1000
+}
+},
+"M_H_right_length=-200": {
+"glyph": {
+"components": [
+{
+"name": "VG_53E3_00",
+"location": {
+"B_H_moveV": 0,
+"B_H_weight": -10,
+"L_S_bottom_length": 0,
+"L_S_weight": -10,
+"R_S_bottom_length": 0,
+"R_S_weight": -10,
+"T_H_weight": -10,
+"height": 1000,
+"weight": 30,
+"width": 1000
+}
+},
+{
+"name": "VG_4E00_00",
+"transformation": {
+"translateY": -10
+},
+"location": {
+"weight": 20,
+"width": 800
+}
+}
+],
+"xAdvance": 1000
+}
+},
+"M_H_weight=-50": {
+"glyph": {
+"components": [
+{
+"name": "VG_53E3_00",
+"location": {
+"B_H_moveV": 0,
+"B_H_weight": -10,
+"L_S_bottom_length": 0,
+"L_S_weight": -10,
+"R_S_bottom_length": 0,
+"R_S_weight": -10,
+"T_H_weight": -10,
+"height": 1000,
+"weight": 30,
+"width": 1000
+}
+},
+{
+"name": "VG_4E00_00",
+"transformation": {
+"translateY": 15
+},
+"location": {
+"weight": -30,
+"width": 1000
+}
+}
+],
+"xAdvance": 1000
+}
+},
+"R_S_bottom_length=200": {
+"glyph": {
+"components": [
+{
+"name": "VG_53E3_00",
+"location": {
+"B_H_moveV": 0,
+"B_H_weight": -10,
+"L_S_bottom_length": 0,
+"L_S_weight": -10,
+"R_S_bottom_length": 200,
+"R_S_weight": -10,
+"T_H_weight": -10,
+"height": 1000,
+"weight": 30,
+"width": 1000
+}
+},
+{
+"name": "VG_4E00_00",
+"transformation": {
+"translateY": -10
+},
+"location": {
+"weight": 20,
+"width": 1000
+}
+}
+],
+"xAdvance": 1000
+}
+},
+"foreground": {
+"glyph": {
+"components": [
+{
+"name": "VG_53E3_00",
+"location": {
+"B_H_moveV": 0,
+"B_H_weight": -10,
+"L_S_bottom_length": 0,
+"L_S_weight": -10,
+"R_S_bottom_length": 0,
+"R_S_weight": -10,
+"T_H_weight": -10,
+"height": 1000,
+"weight": 30,
+"width": 1000
+}
+},
+{
+"name": "VG_4E00_00",
+"transformation": {
+"translateY": -10
+},
+"location": {
+"weight": 20,
+"width": 1000
+}
+}
+],
+"xAdvance": 1000
+}
+},
+"height=60": {
+"glyph": {
+"components": [
+{
+"name": "VG_53E3_00",
+"transformation": {
+"translateY": -940
+},
+"location": {
+"B_H_moveV": 0,
+"B_H_weight": -10,
+"L_S_bottom_length": 0,
+"L_S_weight": -10,
+"R_S_bottom_length": 0,
+"R_S_weight": -10,
+"T_H_weight": -10,
+"height": 60,
+"weight": 30,
+"width": 1000
+}
+},
+{
+"name": "VG_4E00_00",
+"transformation": {
+"translateY": -480
+},
+"location": {
+"weight": 20,
+"width": 1000
+}
+}
+],
+"xAdvance": 1000
+}
+},
+"weight=160": {
+"glyph": {
+"components": [
+{
+"name": "VG_53E3_00",
+"location": {
+"B_H_moveV": 0,
+"B_H_weight": 0,
+"L_S_bottom_length": 0,
+"L_S_weight": 0,
+"R_S_bottom_length": 0,
+"R_S_weight": 0,
+"T_H_weight": 0,
+"height": 1000,
+"weight": 160,
+"width": 1000
+}
+},
+{
+"name": "VG_4E00_00",
+"transformation": {
+"translateY": -80
+},
+"location": {
+"weight": 160,
+"width": 1000
+}
+}
+],
+"xAdvance": 1000
+}
+},
+"width=60": {
+"glyph": {
+"components": [
+{
+"name": "VG_53E3_00",
+"location": {
+"B_H_moveV": 0,
+"B_H_weight": -10,
+"L_S_bottom_length": 0,
+"L_S_weight": -10,
+"R_S_bottom_length": 0,
+"R_S_weight": -10,
+"T_H_weight": -10,
+"height": 1000,
+"weight": 30,
+"width": 60
+}
+},
+{
+"name": "VG_4E00_00",
+"transformation": {
+"translateY": -10
+},
+"location": {
+"weight": 20,
+"width": 60
+}
+}
+],
+"xAdvance": 1000
+}
+}
+}
+}
diff --git a/tests/data/notosanscjksc.fontra/glyphs/VG_7530_00^3.json b/tests/data/notosanscjksc.fontra/glyphs/VG_7530_00^3.json
new file mode 100644
index 0000000..13867ca
--- /dev/null
+++ b/tests/data/notosanscjksc.fontra/glyphs/VG_7530_00^3.json
@@ -0,0 +1,921 @@
+{
+"name": "VG_7530_00",
+"axes": [
+{
+"name": "weight",
+"minValue": 20,
+"defaultValue": 20,
+"maxValue": 160
+},
+{
+"name": "width",
+"minValue": 60,
+"defaultValue": 1000,
+"maxValue": 1000
+},
+{
+"name": "height",
+"minValue": 60,
+"defaultValue": 1000,
+"maxValue": 1000
+},
+{
+"name": "H_weight",
+"minValue": -90,
+"defaultValue": 0,
+"maxValue": 50
+},
+{
+"name": "M_H_weight",
+"minValue": -50,
+"defaultValue": 0,
+"maxValue": 0
+},
+{
+"name": "M_H_moveV",
+"minValue": -100,
+"defaultValue": 0,
+"maxValue": 100
+},
+{
+"name": "L_S_bottom_length",
+"minValue": 0,
+"defaultValue": 0,
+"maxValue": 200
+},
+{
+"name": "R_S_bottom_length",
+"minValue": 0,
+"defaultValue": 0,
+"maxValue": 200
+},
+{
+"name": "M_S_top_length",
+"minValue": 0,
+"defaultValue": 0,
+"maxValue": 1000
+},
+{
+"name": "M_S_bottom_length",
+"minValue": 0,
+"defaultValue": 0,
+"maxValue": 1000
+},
+{
+"name": "M_S_moveH",
+"minValue": -100,
+"defaultValue": 0,
+"maxValue": 0
+},
+{
+"name": "M_S_weight",
+"minValue": -50,
+"defaultValue": 0,
+"maxValue": 0
+},
+{
+"name": "L_S_weight",
+"minValue": -50,
+"defaultValue": 0,
+"maxValue": 0
+}
+],
+"sources": [
+{
+"name": "",
+"layerName": "foreground",
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "weight=160",
+"layerName": "weight=160",
+"location": {
+"weight": 160
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "width=60",
+"layerName": "width=60",
+"location": {
+"width": 60
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "height=60",
+"layerName": "height=60",
+"location": {
+"height": 60
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "H_weight=-90",
+"layerName": "H_weight=-90",
+"location": {
+"H_weight": -90
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "M_H_weight=-50",
+"layerName": "M_H_weight=-50",
+"location": {
+"M_H_weight": -50
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "M_H_moveV=-100",
+"layerName": "M_H_moveV=-100",
+"location": {
+"M_H_moveV": -100
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "M_H_moveV=100",
+"layerName": "M_H_moveV=100",
+"location": {
+"M_H_moveV": 100
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "L_S_bottom_length=200",
+"layerName": "L_S_bottom_length=200",
+"location": {
+"L_S_bottom_length": 200
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "R_S_bottom_length=200",
+"layerName": "R_S_bottom_length=200",
+"location": {
+"R_S_bottom_length": 200
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "H_weight=50",
+"layerName": "H_weight=50",
+"location": {
+"H_weight": 50
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "M_S_top_length=1000",
+"layerName": "M_S_top_length=1000",
+"location": {
+"M_S_top_length": 1000
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "M_S_bottom_length=1000",
+"layerName": "M_S_bottom_length=1000",
+"location": {
+"M_S_bottom_length": 1000
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "M_S_moveH=-100",
+"layerName": "M_S_moveH=-100",
+"location": {
+"M_S_moveH": -100
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "M_S_weight=-50",
+"layerName": "M_S_weight=-50",
+"location": {
+"M_S_weight": -50
+},
+"customData": {
+"fontra.development.status": 0
+}
+},
+{
+"name": "L_S_weight=-50",
+"layerName": "L_S_weight=-50",
+"location": {
+"L_S_weight": -50
+},
+"customData": {
+"fontra.development.status": 0
+}
+}
+],
+"layers": {
+"H_weight=-90": {
+"glyph": {
+"components": [
+{
+"name": "VG_53E3_00",
+"location": {
+"B_H_moveV": 0,
+"B_H_weight": -100,
+"L_S_bottom_length": 0,
+"L_S_weight": -10,
+"R_S_bottom_length": 0,
+"R_S_weight": -10,
+"T_H_weight": -100,
+"height": 1000,
+"weight": 30,
+"width": 1000
+}
+},
+{
+"name": "VG_4E00_00",
+"transformation": {
+"translateY": 35
+},
+"location": {
+"weight": -70,
+"width": 1000
+}
+},
+{
+"name": "VG_4E28_00",
+"transformation": {
+"translateX": -10
+},
+"location": {
+"height": 1000,
+"weight": 20
+}
+}
+],
+"xAdvance": 1000
+}
+},
+"H_weight=50": {
+"glyph": {
+"components": [
+{
+"name": "VG_53E3_00",
+"location": {
+"B_H_moveV": 0,
+"B_H_weight": 40,
+"L_S_bottom_length": 0,
+"L_S_weight": -10,
+"R_S_bottom_length": 0,
+"R_S_weight": -10,
+"T_H_weight": 40,
+"height": 1000,
+"weight": 30,
+"width": 1000
+}
+},
+{
+"name": "VG_4E00_00",
+"transformation": {
+"translateY": -35
+},
+"location": {
+"weight": 70,
+"width": 1000
+}
+},
+{
+"name": "VG_4E28_00",
+"transformation": {
+"translateX": -10
+},
+"location": {
+"height": 1000,
+"weight": 20
+}
+}
+],
+"xAdvance": 1000
+}
+},
+"L_S_bottom_length=200": {
+"glyph": {
+"components": [
+{
+"name": "VG_53E3_00",
+"location": {
+"B_H_moveV": 0,
+"B_H_weight": -10,
+"L_S_bottom_length": 200,
+"L_S_weight": -10,
+"R_S_bottom_length": 0,
+"R_S_weight": -10,
+"T_H_weight": -10,
+"height": 1000,
+"weight": 30,
+"width": 1000
+}
+},
+{
+"name": "VG_4E00_00",
+"transformation": {
+"translateY": -10
+},
+"location": {
+"weight": 20,
+"width": 1000
+}
+},
+{
+"name": "VG_4E28_00",
+"transformation": {
+"translateX": -10
+},
+"location": {
+"height": 1000,
+"weight": 20
+}
+}
+],
+"xAdvance": 1000
+}
+},
+"L_S_weight=-50": {
+"glyph": {
+"components": [
+{
+"name": "VG_53E3_00",
+"location": {
+"B_H_moveV": 0,
+"B_H_weight": -10,
+"L_S_bottom_length": 0,
+"L_S_weight": -60,
+"R_S_bottom_length": 0,
+"R_S_weight": -10,
+"T_H_weight": -10,
+"height": 1000,
+"weight": 30,
+"width": 1000
+}
+},
+{
+"name": "VG_4E00_00",
+"transformation": {
+"translateY": -10
+},
+"location": {
+"weight": 20,
+"width": 1000
+}
+},
+{
+"name": "VG_4E28_00",
+"transformation": {
+"translateX": -10
+},
+"location": {
+"height": 1000,
+"weight": 20
+}
+}
+],
+"xAdvance": 1000
+}
+},
+"M_H_moveV=-100": {
+"glyph": {
+"components": [
+{
+"name": "VG_53E3_00",
+"location": {
+"B_H_moveV": 0,
+"B_H_weight": -10,
+"L_S_bottom_length": 0,
+"L_S_weight": -10,
+"R_S_bottom_length": 0,
+"R_S_weight": -10,
+"T_H_weight": -10,
+"height": 1000,
+"weight": 30,
+"width": 1000
+}
+},
+{
+"name": "VG_4E00_00",
+"transformation": {
+"translateY": -110
+},
+"location": {
+"weight": 20,
+"width": 1000
+}
+},
+{
+"name": "VG_4E28_00",
+"transformation": {
+"translateX": -10
+},
+"location": {
+"height": 1000,
+"weight": 20
+}
+}
+],
+"xAdvance": 1000
+}
+},
+"M_H_moveV=100": {
+"glyph": {
+"components": [
+{
+"name": "VG_53E3_00",
+"location": {
+"B_H_moveV": 0,
+"B_H_weight": -10,
+"L_S_bottom_length": 0,
+"L_S_weight": -10,
+"R_S_bottom_length": 0,
+"R_S_weight": -10,
+"T_H_weight": -10,
+"height": 1000,
+"weight": 30,
+"width": 1000
+}
+},
+{
+"name": "VG_4E00_00",
+"transformation": {
+"translateY": 90
+},
+"location": {
+"weight": 20,
+"width": 1000
+}
+},
+{
+"name": "VG_4E28_00",
+"transformation": {
+"translateX": -10
+},
+"location": {
+"height": 1000,
+"weight": 20
+}
+}
+],
+"xAdvance": 1000
+}
+},
+"M_H_weight=-50": {
+"glyph": {
+"components": [
+{
+"name": "VG_53E3_00",
+"location": {
+"B_H_moveV": 0,
+"B_H_weight": -10,
+"L_S_bottom_length": 0,
+"L_S_weight": -10,
+"R_S_bottom_length": 0,
+"R_S_weight": -10,
+"T_H_weight": -10,
+"height": 1000,
+"weight": 30,
+"width": 1000
+}
+},
+{
+"name": "VG_4E00_00",
+"transformation": {
+"translateY": 15
+},
+"location": {
+"weight": -30,
+"width": 1000
+}
+},
+{
+"name": "VG_4E28_00",
+"transformation": {
+"translateX": -10
+},
+"location": {
+"height": 1000,
+"weight": 20
+}
+}
+],
+"xAdvance": 1000
+}
+},
+"M_S_bottom_length=1000": {
+"glyph": {
+"components": [
+{
+"name": "VG_53E3_00",
+"location": {
+"B_H_moveV": 0,
+"B_H_weight": -10,
+"L_S_bottom_length": 0,
+"L_S_weight": -10,
+"R_S_bottom_length": 0,
+"R_S_weight": -10,
+"T_H_weight": -10,
+"height": 1000,
+"weight": 30,
+"width": 1000
+}
+},
+{
+"name": "VG_4E00_00",
+"transformation": {
+"translateY": -10
+},
+"location": {
+"weight": 20,
+"width": 1000
+}
+},
+{
+"name": "VG_4E28_00",
+"transformation": {
+"translateX": -10
+},
+"location": {
+"height": 2000,
+"weight": 20
+}
+}
+],
+"xAdvance": 1000
+}
+},
+"M_S_moveH=-100": {
+"glyph": {
+"components": [
+{
+"name": "VG_53E3_00",
+"location": {
+"B_H_moveV": 0,
+"B_H_weight": -10,
+"L_S_bottom_length": 0,
+"L_S_weight": -10,
+"R_S_bottom_length": 0,
+"R_S_weight": -10,
+"T_H_weight": -10,
+"height": 1000,
+"weight": 30,
+"width": 1000
+}
+},
+{
+"name": "VG_4E00_00",
+"transformation": {
+"translateY": -10
+},
+"location": {
+"weight": 20,
+"width": 1000
+}
+},
+{
+"name": "VG_4E28_00",
+"transformation": {
+"translateX": -110
+},
+"location": {
+"height": 1000,
+"weight": 20
+}
+}
+],
+"xAdvance": 1000
+}
+},
+"M_S_top_length=1000": {
+"glyph": {
+"components": [
+{
+"name": "VG_53E3_00",
+"location": {
+"B_H_moveV": 0,
+"B_H_weight": -10,
+"L_S_bottom_length": 0,
+"L_S_weight": -10,
+"R_S_bottom_length": 0,
+"R_S_weight": -10,
+"T_H_weight": -10,
+"height": 1000,
+"weight": 30,
+"width": 1000
+}
+},
+{
+"name": "VG_4E00_00",
+"transformation": {
+"translateY": -10
+},
+"location": {
+"weight": 20,
+"width": 1000
+}
+},
+{
+"name": "VG_4E28_00",
+"transformation": {
+"translateX": -10,
+"translateY": 1000
+},
+"location": {
+"height": 2000,
+"weight": 20
+}
+}
+],
+"xAdvance": 1000
+}
+},
+"M_S_weight=-50": {
+"glyph": {
+"components": [
+{
+"name": "VG_53E3_00",
+"location": {
+"B_H_moveV": 0,
+"B_H_weight": -10,
+"L_S_bottom_length": 0,
+"L_S_weight": -10,
+"R_S_bottom_length": 0,
+"R_S_weight": -10,
+"T_H_weight": -10,
+"height": 1000,
+"weight": 30,
+"width": 1000
+}
+},
+{
+"name": "VG_4E00_00",
+"transformation": {
+"translateY": -10
+},
+"location": {
+"weight": 20,
+"width": 1000
+}
+},
+{
+"name": "VG_4E28_00",
+"transformation": {
+"translateX": 15
+},
+"location": {
+"height": 1000,
+"weight": -30
+}
+}
+],
+"xAdvance": 1000
+}
+},
+"R_S_bottom_length=200": {
+"glyph": {
+"components": [
+{
+"name": "VG_53E3_00",
+"location": {
+"B_H_moveV": 0,
+"B_H_weight": -10,
+"L_S_bottom_length": 0,
+"L_S_weight": -10,
+"R_S_bottom_length": 200,
+"R_S_weight": -10,
+"T_H_weight": -10,
+"height": 1000,
+"weight": 30,
+"width": 1000
+}
+},
+{
+"name": "VG_4E00_00",
+"transformation": {
+"translateY": -10
+},
+"location": {
+"weight": 20,
+"width": 1000
+}
+},
+{
+"name": "VG_4E28_00",
+"transformation": {
+"translateX": -10
+},
+"location": {
+"height": 1000,
+"weight": 20
+}
+}
+],
+"xAdvance": 1000
+}
+},
+"foreground": {
+"glyph": {
+"components": [
+{
+"name": "VG_53E3_00",
+"location": {
+"B_H_moveV": 0,
+"B_H_weight": -10,
+"L_S_bottom_length": 0,
+"L_S_weight": -10,
+"R_S_bottom_length": 0,
+"R_S_weight": -10,
+"T_H_weight": -10,
+"height": 1000,
+"weight": 30,
+"width": 1000
+}
+},
+{
+"name": "VG_4E00_00",
+"transformation": {
+"translateY": -10
+},
+"location": {
+"weight": 20,
+"width": 1000
+}
+},
+{
+"name": "VG_4E28_00",
+"transformation": {
+"translateX": -10
+},
+"location": {
+"height": 1000,
+"weight": 20
+}
+}
+],
+"xAdvance": 1000
+}
+},
+"height=60": {
+"glyph": {
+"components": [
+{
+"name": "VG_53E3_00",
+"transformation": {
+"translateY": -940
+},
+"location": {
+"B_H_moveV": 0,
+"B_H_weight": -10,
+"L_S_bottom_length": 0,
+"L_S_weight": -10,
+"R_S_bottom_length": 0,
+"R_S_weight": -10,
+"T_H_weight": -10,
+"height": 60,
+"weight": 30,
+"width": 1000
+}
+},
+{
+"name": "VG_4E00_00",
+"transformation": {
+"translateY": -480
+},
+"location": {
+"weight": 20,
+"width": 1000
+}
+},
+{
+"name": "VG_4E28_00",
+"transformation": {
+"translateX": -10,
+"translateY": -940
+},
+"location": {
+"height": 60,
+"weight": 20
+}
+}
+],
+"xAdvance": 1000
+}
+},
+"weight=160": {
+"glyph": {
+"components": [
+{
+"name": "VG_53E3_00",
+"location": {
+"B_H_moveV": 0,
+"B_H_weight": 0,
+"L_S_bottom_length": 0,
+"L_S_weight": 0,
+"R_S_bottom_length": 0,
+"R_S_weight": 0,
+"T_H_weight": 0,
+"height": 1000,
+"weight": 160,
+"width": 1000
+}
+},
+{
+"name": "VG_4E00_00",
+"transformation": {
+"translateY": -80
+},
+"location": {
+"weight": 160,
+"width": 1000
+}
+},
+{
+"name": "VG_4E28_00",
+"transformation": {
+"translateX": -80
+},
+"location": {
+"height": 1000,
+"weight": 160
+}
+}
+],
+"xAdvance": 1000
+}
+},
+"width=60": {
+"glyph": {
+"components": [
+{
+"name": "VG_53E3_00",
+"location": {
+"B_H_moveV": 0,
+"B_H_weight": -10,
+"L_S_bottom_length": 0,
+"L_S_weight": -10,
+"R_S_bottom_length": 0,
+"R_S_weight": -10,
+"T_H_weight": -10,
+"height": 1000,
+"weight": 30,
+"width": 60
+}
+},
+{
+"name": "VG_4E00_00",
+"transformation": {
+"translateY": -10
+},
+"location": {
+"weight": 20,
+"width": 60
+}
+},
+{
+"name": "VG_4E28_00",
+"transformation": {
+"translateX": -480
+},
+"location": {
+"height": 1000,
+"weight": 20
+}
+}
+],
+"xAdvance": 1000
+}
+}
+}
+}
diff --git a/tests/data/notosanscjksc.fontra/glyphs/uni3479.json b/tests/data/notosanscjksc.fontra/glyphs/uni3479.json
new file mode 100644
index 0000000..10df3a8
--- /dev/null
+++ b/tests/data/notosanscjksc.fontra/glyphs/uni3479.json
@@ -0,0 +1,149 @@
+{
+"name": "uni3479",
+"sources": [
+{
+"name": "",
+"layerName": "foreground",
+"customData": {
+"fontra.development.status": 4
+}
+},
+{
+"name": "wght=1",
+"layerName": "wght=1",
+"location": {
+"wght": 1
+},
+"customData": {
+"fontra.development.status": 4
+}
+}
+],
+"layers": {
+"foreground": {
+"glyph": {
+"components": [
+{
+"name": "VG_65E5_00",
+"transformation": {
+"translateX": 238,
+"translateY": 93
+},
+"location": {
+"H_weight": 0,
+"L_S_bottom_length": 43,
+"M_H_moveV": 3,
+"M_H_right_length": 0,
+"M_H_weight": 0,
+"R_S_bottom_length": 38,
+"height": 276,
+"weight": 30,
+"width": 539
+}
+},
+{
+"name": "VG_7530_00",
+"transformation": {
+"translateX": 174,
+"translateY": 431
+},
+"location": {
+"H_weight": 0,
+"L_S_bottom_length": 0,
+"M_H_moveV": 3,
+"M_H_weight": 0,
+"M_S_bottom_length": 0,
+"M_S_moveH": 0,
+"M_S_top_length": 87.0909678312641,
+"R_S_bottom_length": 0,
+"height": 234,
+"weight": 30,
+"width": 651
+}
+},
+{
+"name": "VG_4E00_00",
+"transformation": {
+"translateX": 332,
+"translateY": 232
+},
+"location": {
+"weight": 30,
+"width": 344
+}
+},
+{
+"name": "T_4EBA_2FF1",
+"location": {
+"height": 299
+}
+}
+],
+"xAdvance": 1000
+}
+},
+"wght=1": {
+"glyph": {
+"components": [
+{
+"name": "VG_65E5_00",
+"transformation": {
+"translateX": 198,
+"translateY": 51
+},
+"location": {
+"H_weight": -55,
+"L_S_bottom_length": 25,
+"M_H_moveV": 0,
+"M_H_right_length": 0,
+"M_H_weight": 0,
+"R_S_bottom_length": 21,
+"height": 326,
+"weight": 146,
+"width": 608
+}
+},
+{
+"name": "VG_7530_00",
+"transformation": {
+"translateX": 146,
+"translateY": 394
+},
+"location": {
+"H_weight": -35,
+"L_S_bottom_length": 0,
+"M_H_moveV": -1,
+"M_H_weight": -14,
+"M_S_bottom_length": 0,
+"M_S_moveH": -6,
+"M_S_top_length": 78.0909678312641,
+"M_S_weight": -5,
+"R_S_bottom_length": 0,
+"height": 293,
+"weight": 123,
+"width": 710
+}
+},
+{
+"name": "VG_4E00_00",
+"transformation": {
+"translateX": 320,
+"translateY": 210
+},
+"location": {
+"weight": 91,
+"width": 357
+}
+},
+{
+"name": "T_4EBA_2FF1",
+"location": {
+"height": 299
+}
+}
+],
+"xAdvance": 1000
+}
+}
+}
+}
diff --git a/tests/data/notosanscjksc.fontra/glyphs/uni531A^02.json b/tests/data/notosanscjksc.fontra/glyphs/uni531A^02.json
new file mode 100644
index 0000000..57a52f0
--- /dev/null
+++ b/tests/data/notosanscjksc.fontra/glyphs/uni531A^02.json
@@ -0,0 +1,70 @@
+{
+"name": "uni531A",
+"sources": [
+{
+"name": "",
+"layerName": "foreground",
+"customData": {
+"fontra.development.status": 4
+}
+},
+{
+"name": "wght=1",
+"layerName": "wght=1",
+"location": {
+"wght": 1
+},
+"customData": {
+"fontra.development.status": 4
+}
+}
+],
+"layers": {
+"foreground": {
+"glyph": {
+"components": [
+{
+"name": "VG_531A_00",
+"transformation": {
+"translateX": 142,
+"translateY": 129
+},
+"location": {
+"L_S_end_length": 0,
+"L_S_weight": 0,
+"TB_2H_weight": -1,
+"T_H_right_length": -20,
+"height": 741,
+"weight": 30,
+"width": 745
+}
+}
+],
+"xAdvance": 1000
+}
+},
+"wght=1": {
+"glyph": {
+"components": [
+{
+"name": "VG_531A_00",
+"transformation": {
+"translateX": 91,
+"translateY": 79
+},
+"location": {
+"L_S_end_length": 0,
+"L_S_weight": 0,
+"TB_2H_weight": -1,
+"T_H_right_length": -27,
+"height": 838,
+"weight": 136,
+"width": 845
+}
+}
+],
+"xAdvance": 1000
+}
+}
+}
+}
diff --git a/tests/data/notosanscjksc.otf.ttx b/tests/data/notosanscjksc.otf.ttx
new file mode 100644
index 0000000..4c077a2
--- /dev/null
+++ b/tests/data/notosanscjksc.otf.ttx
@@ -0,0 +1,4460 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ wght
+
+
+ V000
+
+
+ V001
+
+
+ V002
+
+
+ V003
+
+
+ V004
+
+
+ V005
+
+
+ V006
+
+
+ V007
+
+
+ V008
+
+
+ V009
+
+
+ V010
+
+
+ V011
+
+
+ V012
+
+
+ wght
+
+
+ V000
+
+
+ V001
+
+
+ V002
+
+
+ V003
+
+
+ V004
+
+
+ V005
+
+
+ V006
+
+
+ V007
+
+
+ V008
+
+
+ V009
+
+
+ V010
+
+
+ V011
+
+
+ V012
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ -106 callsubr
+ 0
+
+ 0 0 0
+
+ -99 callsubr
+ 0
+
+ -107 callsubr
+ 0 0
+
+ -0.01941
+
+ 0.01941
+
+ -0.09528
+
+ 0.09528
+
+ -104 callsubr
+ 0 0
+
+ -105 callsubr
+ -106 callsubr
+
+
+ 0 -95 callsubr
+ 0
+
+ -106 callsubr
+ -90 callsubr
+ 3 blend
+ vlineto
+
+
+ 0 0 -94 callsubr
+
+
+ 0 0 -93 callsubr
+
+
+ -100 100 -104 callsubr
+ -107 callsubr
+
+
+ 0 -900 -104 callsubr
+ -106 callsubr
+
+
+ 0 0 100 -100 -104 callsubr
+ 0 0
+
+ 140 -106 callsubr
+ -50 50 -106 callsubr
+
+
+ -106 callsubr
+ 2 0 2 -106 callsubr
+
+
+
+
+
+
+
+
+
+
+
+ 1 vsindex
+ 83 838 137 -13 2 -93 callsubr
+ -26 8 11 -97 callsubr
+ 2 blend
+ rmoveto
+ -24 -8 141 -446 284 -320 459 -126 -137 13 -2 100 -100 -105 callsubr
+ 0 26 -8 -14 -51 -15 6 -91 callsubr
+ 46 2 -2 -2 117 -106 -99 callsubr
+ 100 -100 0 0 -28 -109.76389 -3.23611 10 357 54 -105 callsubr
+ 0 100 -100 -11 -20.9874 -3.0126 -74 40 -227 -98 callsubr
+ 24 -43.83473 8.56078 28 268 22 -98 callsubr
+ 64 -25.11368 -78.2471 -19 -156 -392 -99 callsubr
+ -100 100 0 0 -19 157.59862 -6.32468 13 110 -82 -105 callsubr
+ 0 -100 100 -99 44.10109 83.2597 8 blend
+ rlinecurve
+ 4 8 7 9 5 5 -460 124 -279 318 -137 436 19 -1 3 -107 callsubr
+ -35 32 2 -3 -107 callsubr
+ 11 0.35463 2.64537 35 0 -4 -107 callsubr
+ 1 1 -33 32 -107 callsubr
+ -9 2.35463 -5.35463 44 -1 3 -107 callsubr
+ -33 29 -2 -1 -107 callsubr
+ -1 -3.84288 3.84288 61 1 -6 -107 callsubr
+ -2 -2 -38 33 -106 callsubr
+ 1 -42 3 -3 32 1 3 -107 callsubr
+ -32 39 0 4 -107 callsubr
+ 9 -0.51175 -2.48825 29 2 -4 -107 callsubr
+ 1 1 -29 35 -107 callsubr
+ -21 0.63782 2.36218 49 144 393 -49.1252 48.74237 3.35931 -3.73611 48.74237 -49.1252 -3.73611 3.35931 100 -100 0 0 -5 -149.93752 11.93752 -32 -108 78 13.24245 -13.13925 -0.90555 1 -13.13925 13.24245 1 -0.90555 0 0 100 -100 74 -40.51248 -59.48752 62 -40 221 -49.39719 49.926 -17.47974 18 49.926 -49.39719 18 -17.47974 -107 callsubr
+ -14 47.79951 -8.8291 -37 -266 -12 -17.94495 17.37714 -54.15646 53.59456 17.37714 -17.94495 53.59456 -54.15646 -106 callsubr
+ -1 -53 15.06683 68.08769 26 -117 104 -1.47762 1.33163 14.12042 -14.2673 1.33163 -1.47762 -14.2673 14.12042 -100 100 0 0 -3 110.138 7.89159 -56 -349 -52 4.7025 -4.23788 -44.93797 45.40544 -4.23788 4.7025 45.40544 -44.93797 0 0 -100 100 51 19.44565 -2.60019 12 blend
+ rrcurveto
+
+
+ 2 vsindex
+ 390 190 0 1 blend
+ vmoveto
+ -10 1000 10 -190 0 0 -990 190 0 3 blend
+ vlineto
+
+
+ 500 880 rmoveto
+ 3 vsindex
+ -1000 10 1000 0 990 -1000 0 190 -107 callsubr
+ -990 1000 100 3 blend
+ vlineto
+
+
+ 4 vsindex
+ 924 793 -74 -3 16 0 0 100 -100 -104 callsubr
+ 4 53 -12 -106 callsubr
+ -50 0 -99 callsubr
+ 26 -12 16 -107 callsubr
+ -100 100 -107 callsubr
+ -15 43 -2 -106 callsubr
+ -18 -105 callsubr
+ 2 blend
+ rmoveto
+ -218 -323 -316 -271 -369 -163 8 -6 8 -10 5 -7 23 204.98349 -68.43005 100 0 -7.83304 7.25789 19.33598 -20.15994 7.37018 -7.83304 -20.15994 19.33598 -22.83272 -16.31778 56.44655 15.64632 -21.31949 90.37193 12.1505 -12.31773 0.83272 -6.01651 -13.84921 21.74211 13.16728 8.16728 -69.7971 10.15079 -2 61.66867 240.58855 0 -100 -11.60583 10.75365 28.64919 -29.87001 10.92003 -11.60583 -29.87001 28.64919 5.35852 4.20403 -20.25722 0.41129 -2.31786 0.32631 -15.56256 -0.42136 2.64148 5.66867 15.02719 0.24635 -1.64148 6.35852 -0.43849 -0.97281 5 286.01651 10.43005 0 0 -57.69223 58.89069 -26.84535 28.54887 58.64986 -57.69223 28.54887 -26.84535 -5.87553 1.96452 -14.44655 -32.66637 24.82884 -180.54054 11.91101 20.55125 2.87553 10.01651 7.14096 -31.89069 -11.87553 -16.87553 161.52539 10.14096 15 -10.66867 235.41145 0 0 26.83452 -25.707 68.03366 -66.42432 -25.93016 26.83452 -66.42432 68.03366 -11.83743 -16.25014 -1.74278 -0.40117 2.63501 -0.36285 29.08755 0.67159 -3.16257 -29.66867 -29.5061 -0.293 13.16257 -12.83743 0.90727 26.4939 -1 303 50 -100 0 -34.47473 33.85144 7.50937 -8.38893 33.97997 -34.47473 -8.38893 7.50937 1.70825 8.35326 -17 17.02003 -3.50937 90.16861 -10.06152 -8.23352 -3.70825 -4 6.70825 10.14856 -1.29175 8.70825 -91.72829 -20.29175 26 -68 161 0 100 -15.22868 14.95334 3.31714 -3.70569 15.01012 -15.22868 -3.70569 3.31714 -23.5211 -25.9539 35 -0.01012 -0.31714 0.03653 16.47499 -0.25023 0.5211 24 14.4789 0.04666 -11.5211 6.4789 -0.46878 -25.5211 22 2 -5 -104 callsubr
+ -31 35 0 5 25 -19 3 0 -4 0 7 -105 callsubr
+ -30 6 -3 -104 callsubr
+ -2 2 29 -34 25 -8 -2 -106 callsubr
+ -8 -105 callsubr
+ 37 4 -7 -104 callsubr
+ -35 31 1 -1 9.90472 -37 6 -106 callsubr
+ 36.09528 -100 callsubr
+ -100 callsubr
+ 0 -101 callsubr
+ 0 -101 callsubr
+ -101 callsubr
+ -100 callsubr
+ -101 callsubr
+ -58 7 -3 -104 callsubr
+ 2 3 44 -33 51.01941 -4 -3 -106 callsubr
+ -19.01941 -103 callsubr
+ -103 callsubr
+ 0 -102 callsubr
+ 0 -102 callsubr
+ -102 callsubr
+ -103 callsubr
+ -102 callsubr
+ 18 3 -6 -104 callsubr
+ -34 34 -1 -4 28.09528 -21 3 0 4 0 11.90472 -101 callsubr
+ -101 callsubr
+ 0 -100 callsubr
+ 0 -100 callsubr
+ -100 callsubr
+ -101 callsubr
+ -100 callsubr
+ -35 4 -2 -104 callsubr
+ 0 -5 27 -33 26.98059 -5 -107 callsubr
+ -13.98059 -102 callsubr
+ -102 callsubr
+ 0 -103 callsubr
+ 0 -103 callsubr
+ -103 callsubr
+ -102 callsubr
+ -103 callsubr
+ 12 blend
+ rrcurveto
+ 366 166 314 267 229 334 42 -302 -49 100 -105 callsubr
+ -42 -42 16 -106 callsubr
+ 47 -89 callsubr
+ -1 65 -162 0 -100 -99 callsubr
+ 1 1 -34 -106 callsubr
+ 7 -105 callsubr
+ -13 -282 -8 -105 callsubr
+ 0 13 13 12 -106 callsubr
+ -23 -106 callsubr
+ -4 0 -4 -106 callsubr
+ -6 13 -234 -105 callsubr
+ 0 6 6 3 -106 callsubr
+ -16 -105 callsubr
+ 5 -216 67 -100 -105 callsubr
+ -5 -5 -53 -106 callsubr
+ 9 -89 callsubr
+ 43 -66 -249 0 100 -99 callsubr
+ -43 -43 25 -106 callsubr
+ 56 -105 callsubr
+ 6 blend
+ rrcurveto
+
+
+ 5 vsindex
+ 880 -92 callsubr
+ 1 blend
+ vmoveto
+ -1000 20 1000 0 900 0 -100 -105 callsubr
+ 140 0 -20 20 -104 callsubr
+ -900 0 100 -104 callsubr
+ 0 3 blend
+ vlineto
+ -20 0 0 -140 0 20 -20 0 -107 callsubr
+ 1 blend
+ hmoveto
+ -20 1000 20 0 0 -140 -106 callsubr
+ 50 -50 -106 callsubr
+ -900 -104 callsubr
+ 0 -50 50 -96 callsubr
+ -1000 -980 900 -104 callsubr
+ 0 50 -50 0 0 900 -90 callsubr
+ 2 blend
+ rmoveto
+ -20 1000 20 0 0 -140 -106 callsubr
+ 50 -50 0 0 -92 callsubr
+ -96 callsubr
+
+
+ 880 vmoveto
+ 6 vsindex
+ -1000 30 970 940 -970 30 1000 -105 callsubr
+ 940 0 -200 -107 callsubr
+ 0 130 -95 callsubr
+ -130 100 -100 -104 callsubr
+ -940 0 200 -107 callsubr
+ 0 -260 -107 callsubr
+ 100 -100 100 -100 0 -940 -104 callsubr
+ 130 -100 100 -104 callsubr
+ 940 0 0 -200 -107 callsubr
+ 130 0 -97 callsubr
+ 0 -107 callsubr
+ 0 -940 0 0 200 -107 callsubr
+ 7 blend
+ vlineto
+ -990 -970 -105 callsubr
+ 0 940 -107 callsubr
+ 250 0 130 0 0 -100 100 -107 callsubr
+ 940 -106 callsubr
+ -300 300 0 0 2 blend
+ rmoveto
+ -30 989 30 -130 -91 callsubr
+ 0 0 0 -105 callsubr
+ 0 0 -940 -107 callsubr
+ -509 0 130 -94 callsubr
+ 0 0 3 blend
+ vlineto
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ wght
+ 0x0
+ 100.0
+ 100.0
+ 900.0
+ 256
+
+
+
+
+ V000
+ 0x1
+ -1.0
+ 0.0
+ 1.0
+ 257
+
+
+
+
+ V001
+ 0x1
+ -1.0
+ 0.0
+ 1.0
+ 258
+
+
+
+
+ V002
+ 0x1
+ -1.0
+ 0.0
+ 1.0
+ 259
+
+
+
+
+ V003
+ 0x1
+ -1.0
+ 0.0
+ 1.0
+ 260
+
+
+
+
+ V004
+ 0x1
+ -1.0
+ 0.0
+ 1.0
+ 261
+
+
+
+
+ V005
+ 0x1
+ -1.0
+ 0.0
+ 1.0
+ 262
+
+
+
+
+ V006
+ 0x1
+ -1.0
+ 0.0
+ 1.0
+ 263
+
+
+
+
+ V007
+ 0x1
+ -1.0
+ 0.0
+ 1.0
+ 264
+
+
+
+
+ V008
+ 0x1
+ -1.0
+ 0.0
+ 1.0
+ 265
+
+
+
+
+ V009
+ 0x1
+ -1.0
+ 0.0
+ 1.0
+ 266
+
+
+
+
+ V010
+ 0x1
+ -1.0
+ 0.0
+ 1.0
+ 267
+
+
+
+
+ V011
+ 0x1
+ -1.0
+ 0.0
+ 1.0
+ 268
+
+
+
+
+ V012
+ 0x1
+ -1.0
+ 0.0
+ 1.0
+ 269
+
+
+
+
diff --git a/tests/test_compile.py b/tests/test_compile.py
index fd987a9..4c3709f 100644
--- a/tests/test_compile.py
+++ b/tests/test_compile.py
@@ -21,14 +21,17 @@ def cleanupTTX(ttx):
@pytest.mark.parametrize("sourceName", ["figArnaud.rcjk", "MutatorSans.fontra"])
-def test_main(tmpdir, sourceName):
+@pytest.mark.parametrize("outSuffix", [".ttf", ".otf"])
+def test_main(tmpdir, sourceName, outSuffix):
tmpdir = pathlib.Path(tmpdir)
sourcePath = dataDir / sourceName
- ttxPath = dataDir / (sourcePath.stem + ".ttx")
- outPath = tmpdir / (sourcePath.stem + ".ttf")
- outTTXPath = tmpdir / (sourcePath.stem + ".ttx")
+ outFileName = sourcePath.stem + outSuffix
+ ttxFileName = outFileName + ".ttx"
+ ttxPath = dataDir / ttxFileName
+ outPath = tmpdir / outFileName
+ outTTXPath = tmpdir / ttxFileName
subprocess.run(["fontra-compile", sourcePath, outPath], check=True)
- subprocess.run(["ttx", outPath], check=True)
+ subprocess.run(["ttx", outPath, "-o", outTTXPath], check=True)
# # Write expected
# ttxPath.write_text(outTTXPath.read_text())
diff --git a/tests/test_workflow.py b/tests/test_workflow.py
index 11fe631..5994cd3 100644
--- a/tests/test_workflow.py
+++ b/tests/test_workflow.py
@@ -1,8 +1,15 @@
+from __future__ import annotations
+
import pathlib
+import random
import subprocess
+from dataclasses import dataclass, replace
import pytest
import yaml
+from fontra.core.classes import VariableGlyph
+from fontra.workflow.actions import registerFilterAction
+from fontra.workflow.actions.base import BaseFilter
from fontra.workflow.workflow import Workflow
from test_compile import cleanupTTX
@@ -10,6 +17,15 @@
dataDir = testDir / "data"
+@registerFilterAction("randomize-glyph-source-order")
+@dataclass(kw_only=True)
+class RandomizeGlyphSourceOrder(BaseFilter):
+ async def processGlyph(self, glyph: VariableGlyph) -> VariableGlyph:
+ newSources = list(glyph.sources)
+ random.shuffle(newSources)
+ return replace(glyph, sources=newSources)
+
+
testData = [
(
"""
@@ -19,7 +35,56 @@
- output: compile-varc
destination: "output1.ttf"
""",
- "MutatorSans.ttx",
+ "MutatorSans.ttf.ttx",
+ ),
+ (
+ """
+steps:
+- input: fontra-read
+ source: "tests/data/MutatorSans.fontra"
+- output: compile-varc
+ destination: "output1.otf"
+""",
+ "MutatorSans.otf.ttx",
+ ),
+ (
+ """
+# Check that we produce the same output regardless of glyph source order.
+steps:
+- input: fontra-read
+ source: "tests/data/MutatorSans.fontra"
+- filter: randomize-glyph-source-order
+- output: compile-varc
+ destination: "output-random-source-order.ttf"
+""",
+ "MutatorSans.ttf.ttx",
+ ),
+ (
+ """
+# Check that we produce the same output regardless of glyph source order.
+steps:
+- input: fontra-read
+ source: "tests/data/MutatorSans.fontra"
+- filter: randomize-glyph-source-order
+- output: compile-varc
+ destination: "output-random-source-order.otf"
+""",
+ "MutatorSans.otf.ttx",
+ ),
+ (
+ """
+# This test font contains two problem cases:
+# 1. VG_531A_00 contains a rectangle that has no width in a single source,
+# which uncovered a bug with implied lineto calls with the CFF writer.
+# 2. uni3479 (㑹) which uses "asymmetrical" axes, that lead to wrong results
+# in normalized space: https://github.com/googlefonts/fontra-compile/issues/45
+steps:
+- input: fontra-read
+ source: "tests/data/notosanscjksc.fontra"
+- output: compile-varc
+ destination: "output.otf"
+""",
+ "notosanscjksc.otf.ttx",
),
(
"""