From 9ebbd2ea7ff747b2758b08aea87217c65fb0be0c Mon Sep 17 00:00:00 2001 From: Just van Rossum Date: Fri, 12 Jul 2024 16:57:38 +0200 Subject: [PATCH 01/29] Rename var/attr to be more explicit --- src/fontra_compile/builder.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/fontra_compile/builder.py b/src/fontra_compile/builder.py index d7fbe6a..faaa8d8 100644 --- a/src/fontra_compile/builder.py +++ b/src/fontra_compile/builder.py @@ -57,7 +57,7 @@ class GlyphInfo: hasContours: bool xAdvance: float = 500 xAdvanceVariations: list = field(default_factory=list) - variations: list = field(default_factory=list) + gvarVariations: list = field(default_factory=list) variableComponents: list = field(default_factory=list) localAxisTags: set = field(default_factory=set) model: VariationModel | None = None @@ -226,7 +226,7 @@ async def prepareOneGlyph(self, glyphName: str) -> GlyphInfo: xAdvanceVariations = prepareXAdvanceVariations(glyph, glyphSources) sourceCoordinates = prepareSourceCoordinates(glyph, glyphSources) - variations = ( + gvarVariations = ( prepareGvarVariations(sourceCoordinates, model) if model is not None else [] ) @@ -244,7 +244,7 @@ async def prepareOneGlyph(self, glyphName: str) -> GlyphInfo: hasContours=not defaultGlyph.path.isEmpty(), xAdvance=max(defaultGlyph.xAdvance or 0, 0), xAdvanceVariations=xAdvanceVariations, - variations=variations, + gvarVariations=gvarVariations, variableComponents=componentInfo, localAxisTags=set(localAxisTags.values()), model=model, @@ -417,9 +417,9 @@ 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) + gvarVariations = getGlyphInfoAttributes(self.glyphInfos, "gvarVariations") + if gvarVariations: + builder.setupGvar(gvarVariations) if any(glyphInfo.variableComponents for glyphInfo in self.glyphInfos.values()): varcTable = self.buildVARC(axisTags) From 266bec7e1ae1bad641f2ea7726a2bd0b73e04289 Mon Sep 17 00:00:00 2001 From: Just van Rossum Date: Fri, 12 Jul 2024 17:46:31 +0200 Subject: [PATCH 02/29] Prepare for charstrings --- src/fontra_compile/builder.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/fontra_compile/builder.py b/src/fontra_compile/builder.py index faaa8d8..ae73335 100644 --- a/src/fontra_compile/builder.py +++ b/src/fontra_compile/builder.py @@ -53,15 +53,23 @@ class MissingBaseGlyphError(Exception): @dataclass class GlyphInfo: - ttGlyph: TTGlyph hasContours: bool - xAdvance: float = 500 - xAdvanceVariations: list = field(default_factory=list) - gvarVariations: list = field(default_factory=list) + xAdvance: float + xAdvanceVariations: list + ttGlyph: TTGlyph | None = None + gvarVariations: list | None = None + charString: Any | 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 + @dataclass class ComponentInfo: @@ -199,6 +207,7 @@ async def prepareGlyphs(self) -> None: hasContours=False, xAdvance=500, xAdvanceVariations=[500], + gvarVariations=[], ) self.glyphInfos[glyphName] = glyphInfo From 46c442cd6e0b61b68d3ccf2d791d7cd60d19354e Mon Sep 17 00:00:00 2001 From: Just van Rossum Date: Fri, 12 Jul 2024 17:54:43 +0200 Subject: [PATCH 03/29] Improve type checking, make Builder a dataclass --- src/fontra_compile/__main__.py | 4 +++- src/fontra_compile/builder.py | 11 +++++++---- src/fontra_compile/compile_varc_action.py | 3 ++- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/fontra_compile/__main__.py b/src/fontra_compile/__main__.py index f68cabf..1e38f51 100644 --- a/src/fontra_compile/__main__.py +++ b/src/fontra_compile/__main__.py @@ -25,7 +25,9 @@ async def main_async(): ) reader = getFileSystemBackend(sourceFontPath) - builder = Builder(reader, glyphNames) + builder = Builder( + reader, 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 ae73335..fc55e5c 100644 --- a/src/fontra_compile/builder.py +++ b/src/fontra_compile/builder.py @@ -3,6 +3,7 @@ from fontra.core.classes import VariableGlyph from fontra.core.path import PackedPath +from fontra.core.protocols import ReadableFontBackend from fontTools.designspaceLib import AxisDescriptor from fontTools.fontBuilder import FontBuilder from fontTools.misc.fixedTools import floatToFixed as fl2fi @@ -133,10 +134,11 @@ def addLocationToComponent(self, compo, axisIndicesMapping, axisTags, storeBuild compo.axisValuesVarIndex = varIdx +@dataclass 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() @@ -157,7 +159,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] = {} @@ -173,6 +175,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 diff --git a/src/fontra_compile/compile_varc_action.py b/src/fontra_compile/compile_varc_action.py index 09adb74..2eeb72c 100644 --- a/src/fontra_compile/compile_varc_action.py +++ b/src/fontra_compile/compile_varc_action.py @@ -31,7 +31,8 @@ async def process( ) -> None: outputDir = pathlib.Path(outputDir) outputFontPath = outputDir / self.destination - builder = Builder(self.input) + assert self.input is not None + builder = Builder(self.input, buildCFF2=outputFontPath.suffix.lower() == ".otf") await builder.setup() ttFont = await builder.build() ttFont.save(outputFontPath) From 50725b845fd8ba0471a1f153079a8359f681af8d Mon Sep 17 00:00:00 2001 From: Just van Rossum Date: Fri, 12 Jul 2024 17:56:34 +0200 Subject: [PATCH 04/29] Make Builder only take keyword args --- src/fontra_compile/__main__.py | 6 ++++-- src/fontra_compile/builder.py | 2 +- src/fontra_compile/compile_varc_action.py | 4 +++- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/fontra_compile/__main__.py b/src/fontra_compile/__main__.py index 1e38f51..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") @@ -26,7 +26,9 @@ async def main_async(): reader = getFileSystemBackend(sourceFontPath) builder = Builder( - reader, glyphNames, buildCFF2=outputFontPath.suffix.lower() == ".otf" + reader=reader, + requestedGlyphNames=glyphNames, + buildCFF2=outputFontPath.suffix.lower() == ".otf", ) await builder.setup() ttFont = await builder.build() diff --git a/src/fontra_compile/builder.py b/src/fontra_compile/builder.py index fc55e5c..3bc4ecc 100644 --- a/src/fontra_compile/builder.py +++ b/src/fontra_compile/builder.py @@ -134,7 +134,7 @@ def addLocationToComponent(self, compo, axisIndicesMapping, axisTags, storeBuild compo.axisValuesVarIndex = varIdx -@dataclass +@dataclass(kw_only=True) class Builder: reader: ReadableFontBackend # a Fontra Backend, such as DesignspaceBackend requestedGlyphNames: list = field(default_factory=list) diff --git a/src/fontra_compile/compile_varc_action.py b/src/fontra_compile/compile_varc_action.py index 2eeb72c..7b4dd07 100644 --- a/src/fontra_compile/compile_varc_action.py +++ b/src/fontra_compile/compile_varc_action.py @@ -32,7 +32,9 @@ async def process( outputDir = pathlib.Path(outputDir) outputFontPath = outputDir / self.destination assert self.input is not None - builder = Builder(self.input, buildCFF2=outputFontPath.suffix.lower() == ".otf") + builder = Builder( + reader=self.input, buildCFF2=outputFontPath.suffix.lower() == ".otf" + ) await builder.setup() ttFont = await builder.build() ttFont.save(outputFontPath) From 46362ab2c768c6a7dfd076c7535c5554da86bc35 Mon Sep 17 00:00:00 2001 From: Just van Rossum Date: Fri, 12 Jul 2024 18:02:30 +0200 Subject: [PATCH 05/29] Prepare for CFF2 --- src/fontra_compile/builder.py | 39 +++++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/src/fontra_compile/builder.py b/src/fontra_compile/builder.py index 3bc4ecc..ed961a8 100644 --- a/src/fontra_compile/builder.py +++ b/src/fontra_compile/builder.py @@ -237,26 +237,36 @@ async def prepareOneGlyph(self, glyphName: str) -> GlyphInfo: xAdvanceVariations = prepareXAdvanceVariations(glyph, glyphSources) - sourceCoordinates = prepareSourceCoordinates(glyph, glyphSources) - gvarVariations = ( - 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() + gvarVariations = None + ttGlyph = None + charString = None + + if not self.buildCFF2: + ttGlyphPen = TTGlyphPointPen(None) + defaultGlyph.path.drawPoints(ttGlyphPen) + ttGlyph = ttGlyphPen.glyph() + + sourceCoordinates = prepareSourceCoordinates(glyph, glyphSources) + gvarVariations = ( + prepareGvarVariations(sourceCoordinates, model) + if model is not None + else [] + ) + else: + raise NotImplementedError() componentInfo = await self.collectComponentInfo(glyph, defaultSourceIndex) return GlyphInfo( ttGlyph=ttGlyph, + gvarVariations=gvarVariations, + charString=charString, hasContours=not defaultGlyph.path.isEmpty(), xAdvance=max(defaultGlyph.xAdvance or 0, 0), xAdvanceVariations=xAdvanceVariations, - gvarVariations=gvarVariations, variableComponents=componentInfo, localAxisTags=set(localAxisTags.values()), model=model, @@ -414,7 +424,6 @@ async def buildFont(self) -> TTFont: 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(): @@ -429,9 +438,13 @@ async def buildFont(self) -> TTFont: if any(axis.map for axis in dsAxes): builder.setupAvar(dsAxes) - gvarVariations = getGlyphInfoAttributes(self.glyphInfos, "gvarVariations") - if gvarVariations: - builder.setupGvar(gvarVariations) + if not self.buildCFF2: + builder.setupGlyf(getGlyphInfoAttributes(self.glyphInfos, "ttGlyph")) + gvarVariations = getGlyphInfoAttributes(self.glyphInfos, "gvarVariations") + if gvarVariations: + builder.setupGvar(gvarVariations) + else: + raise NotImplementedError() if any(glyphInfo.variableComponents for glyphInfo in self.glyphInfos.values()): varcTable = self.buildVARC(axisTags) From 758e462fbc4706e75828b3ac3ab13c018899bc43 Mon Sep 17 00:00:00 2001 From: Just van Rossum Date: Fri, 12 Jul 2024 21:15:27 +0200 Subject: [PATCH 06/29] Parametrize output format --- tests/data/{MutatorSans.ttx => MutatorSans.ttf.ttx} | 0 tests/data/{figArnaud.ttx => figArnaud.ttf.ttx} | 0 tests/test_compile.py | 13 ++++++++----- tests/test_workflow.py | 2 +- 4 files changed, 9 insertions(+), 6 deletions(-) rename tests/data/{MutatorSans.ttx => MutatorSans.ttf.ttx} (100%) rename tests/data/{figArnaud.ttx => figArnaud.ttf.ttx} (100%) 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.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/test_compile.py b/tests/test_compile.py index fd987a9..2fe8ccc 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"]) +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..c215c1f 100644 --- a/tests/test_workflow.py +++ b/tests/test_workflow.py @@ -19,7 +19,7 @@ - output: compile-varc destination: "output1.ttf" """, - "MutatorSans.ttx", + "MutatorSans.ttf.ttx", ), ( """ From 93f29fc669437aa521218b13f5b1428a8cb2ef09 Mon Sep 17 00:00:00 2001 From: Just van Rossum Date: Fri, 12 Jul 2024 21:24:48 +0200 Subject: [PATCH 07/29] Factor out TTF glyph builder --- src/fontra_compile/builder.py | 36 ++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/src/fontra_compile/builder.py b/src/fontra_compile/builder.py index ed961a8..f41ae0b 100644 --- a/src/fontra_compile/builder.py +++ b/src/fontra_compile/builder.py @@ -60,6 +60,7 @@ class GlyphInfo: ttGlyph: TTGlyph | None = None gvarVariations: list | None = None charString: Any | None = None + charStringSupports: list | None = None variableComponents: list = field(default_factory=list) localAxisTags: set = field(default_factory=set) model: VariationModel | None = None @@ -238,22 +239,18 @@ async def prepareOneGlyph(self, glyphName: str) -> GlyphInfo: xAdvanceVariations = prepareXAdvanceVariations(glyph, glyphSources) defaultSourceIndex = model.reverseMapping[0] if model is not None else 0 - defaultGlyph = glyph.layers[glyphSources[defaultSourceIndex].layerName].glyph + defaultLayerGlyph = glyph.layers[ + glyphSources[defaultSourceIndex].layerName + ].glyph - gvarVariations = None ttGlyph = None + gvarVariations = None charString = None + charStringSupports = None if not self.buildCFF2: - ttGlyphPen = TTGlyphPointPen(None) - defaultGlyph.path.drawPoints(ttGlyphPen) - ttGlyph = ttGlyphPen.glyph() - - sourceCoordinates = prepareSourceCoordinates(glyph, glyphSources) - gvarVariations = ( - prepareGvarVariations(sourceCoordinates, model) - if model is not None - else [] + ttGlyph, gvarVariations = buildTTGlyph( + glyph, glyphSources, defaultLayerGlyph, model ) else: raise NotImplementedError() @@ -264,8 +261,9 @@ async def prepareOneGlyph(self, glyphName: str) -> GlyphInfo: ttGlyph=ttGlyph, gvarVariations=gvarVariations, charString=charString, - hasContours=not defaultGlyph.path.isEmpty(), - xAdvance=max(defaultGlyph.xAdvance or 0, 0), + charStringSupports=charStringSupports, + hasContours=not defaultLayerGlyph.path.isEmpty(), + xAdvance=max(defaultLayerGlyph.xAdvance or 0, 0), xAdvanceVariations=xAdvanceVariations, variableComponents=componentInfo, localAxisTags=set(localAxisTags.values()), @@ -668,6 +666,18 @@ def prepareXAdvanceVariations(glyph: VariableGlyph, glyphSources): return [glyph.layers[source.layerName].glyph.xAdvance for source in glyphSources] +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 = [] From 3732758d5a04754abe6f81f3e3a9340c7c7667bd Mon Sep 17 00:00:00 2001 From: Just van Rossum Date: Fri, 12 Jul 2024 22:52:19 +0200 Subject: [PATCH 08/29] Implement CFF2 export --- src/fontra_compile/builder.py | 99 +- tests/data/MutatorSans.otf.ttx | 2090 +++++++++++++++++++++++ tests/data/figArnaud.otf.ttx | 2893 ++++++++++++++++++++++++++++++++ tests/test_compile.py | 2 +- 4 files changed, 5074 insertions(+), 10 deletions(-) create mode 100644 tests/data/MutatorSans.otf.ttx create mode 100644 tests/data/figArnaud.otf.ttx diff --git a/src/fontra_compile/builder.py b/src/fontra_compile/builder.py index f41ae0b..0fdbf86 100644 --- a/src/fontra_compile/builder.py +++ b/src/fontra_compile/builder.py @@ -11,6 +11,9 @@ 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.t2CharStringPen import T2CharStringPen from fontTools.pens.ttGlyphPen import TTGlyphPointPen from fontTools.ttLib import TTFont, newTable from fontTools.ttLib.tables import otTables as ot @@ -19,7 +22,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, @@ -57,6 +61,7 @@ class GlyphInfo: hasContours: bool xAdvance: float xAdvanceVariations: list + leftSideBearing: int ttGlyph: TTGlyph | None = None gvarVariations: list | None = None charString: Any | None = None @@ -207,11 +212,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=[], + gvarVariations=None if self.buildCFF2 else [], ) self.glyphInfos[glyphName] = glyphInfo @@ -253,10 +266,19 @@ async def prepareOneGlyph(self, glyphName: str) -> GlyphInfo: glyph, glyphSources, defaultLayerGlyph, model ) else: - raise NotImplementedError() + charString = buildCharString(glyph, glyphSources, defaultLayerGlyph, model) + charStringSupports = ( + tuple(tuple(sorted(sup.items())) for sup in model.supports[1:]) + if model is not None + else None + ) componentInfo = await self.collectComponentInfo(glyph, defaultSourceIndex) + boundsPen = (ControlBoundsPen if self.buildCFF2 else BoundsPen)(None) + defaultLayerGlyph.path.drawPoints(PointToSegmentPen(boundsPen)) + leftSideBearing = boundsPen.bounds[0] if boundsPen.bounds is not None else 0 + return GlyphInfo( ttGlyph=ttGlyph, gvarVariations=gvarVariations, @@ -265,6 +287,7 @@ async def prepareOneGlyph(self, glyphName: str) -> GlyphInfo: hasContours=not defaultLayerGlyph.path.isEmpty(), xAdvance=max(defaultLayerGlyph.xAdvance or 0, 0), xAdvanceVariations=xAdvanceVariations, + leftSideBearing=leftSideBearing, variableComponents=componentInfo, localAxisTags=set(localAxisTags.values()), model=model, @@ -417,7 +440,11 @@ 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) @@ -442,7 +469,41 @@ async def buildFont(self) -> TTFont: if gvarVariations: builder.setupGvar(gvarVariations) else: - raise NotImplementedError() + charStrings = getGlyphInfoAttributes(self.glyphInfos, "charString") + charStringSupports = getGlyphInfoAttributes( + self.glyphInfos, "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)) + + builder.setupCFF2(charStrings) + addCFFVarStore(builder.font, None, varDataList, regionList) if any(glyphInfo.variableComponents for glyphInfo in self.glyphInfos.values()): varcTable = self.buildVARC(axisTags) @@ -451,7 +512,7 @@ async def buildFont(self) -> TTFont: builder.setupHorizontalHeader() builder.setupHorizontalMetrics( addLSB( - builder.font["glyf"], + getGlyphInfoAttributes(self.glyphInfos, "leftSideBearing"), getGlyphInfoAttributes(self.glyphInfos, "xAdvance"), ) ) @@ -716,9 +777,29 @@ 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]]: +def buildCharString(glyph, glyphSources, defaultLayerGlyph, model): + if model is None: + pen = T2CharStringPen(None, None, CFF2=True) + defaultLayerGlyph.path.drawPoints(PointToSegmentPen(pen)) + charString = pen.getCharString() + else: + pen = CFF2CharStringMergePen([], glyph.name, len(glyphSources), 0) + pointPen = PointToSegmentPen(pen) + for sourceIndex, source in enumerate(glyphSources): + if sourceIndex: + pen.restart(sourceIndex) + layerGlyph = glyph.layers[source.layerName].glyph + layerGlyph.path.drawPoints(pointPen) + charString = pen.getCharString(var_model=model) + + return charString + + +def addLSB( + leftSideBearings: dict[str, int], metrics: dict[str, int] +) -> dict[str, tuple[int, int]]: return { - glyphName: (xAdvance, glyfTable[glyphName].xMin) + glyphName: (xAdvance, leftSideBearings.get(glyphName, 0)) for glyphName, xAdvance in metrics.items() } diff --git a/tests/data/MutatorSans.otf.ttx b/tests/data/MutatorSans.otf.ttx new file mode 100644 index 0000000..6964207 --- /dev/null +++ b/tests/data/MutatorSans.otf.ttx @@ -0,0 +1,2090 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + weight + + + width + + + V000 + + + V001 + + + weight + + + width + + + V000 + + + V001 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 20 30 -30 0 1 blend + hmoveto + 40 7 220 63 1 blend + hlineto + 140 700 375 -56 -169 0 100 0 2 blend + rlineto + -35 -7 -195 -43 1 blend + hlineto + -90 -536 -235 96 79 60 -144 -60 2 blend + rmoveto + 250 36 -250 450 220 -190 -6 174 16 -450 -220 190 3 blend + hlineto + 257 -200 585 23 -275 -54 -130 44 2 blend + rmoveto + 44 9 296 121 1 blend + hlineto + -145 700 -375 29 151 0 100 0 2 blend + rlineto + -39 -9 -281 -121 1 blend + hlineto + -17 -39 15 -73 5 3 -221 -3 2 blend + rmoveto + 47 39 -47 3 223 147 -3 221 3 -3 -223 -147 3 blend + hlineto + + + + + + + 1 vsindex + 60 60 -21 -30 -30 1 blend + hmoveto + 40 700 -40 0 193 270 110 0 72 100 1 0 -193 -270 -110 3 blend + hlineto + 20 -367 0 164 230 140 0 -84 -86 -11 2 blend + rmoveto + 130 610 -36 -65 -393 1 blend + hlineto + 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 8 blend + hvcurveto + -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 2 blend + rlineto + 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 3 blend + hlineto + 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 8 blend + hvcurveto + -110 -570 22 45 392 1 blend + hlineto + + + 410 264 773 102 -379 13 114 -29 2 blend + rmoveto + -179 -13 -57 -59 -83 4 85 14 -27 11 13 -130 33 93 -17 29 15 -193 23 162 5 blend + hhcurveto + -11 -39 3 -47 1 blend + hlineto + -94 -60 78 248 247 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 8 blend + hvcurveto + 11 39 -3 47 1 blend + hlineto + 82 57 -56 -176 14 192 -22 -162 129 -33 -92 -17 28 15 6 86 13 28 -12 -13 5 blend + hvcurveto + 39 5 1 251 136 -1 24 18 2 blend + rlineto + 191 -17 -71 72 -104 -5 48 -18 -27 -2 4 -130 -67 67 17 42 -28 -193 -107 104 5 blend + hhcurveto + -11 -39 -14 -136 1 blend + hlineto + -121 -75 -95 -263 -264 75 -98 121 -217 -118 118 -137 -75 75 -20 -36 20 20 -13 -20 20 -15 -20 137 75 -75 -20 -36 20 217 118 -118 8 blend + hvcurveto + 11 39 14 136 1 blend + hlineto + 105 71 74 194 16 194 106 -103 130 68 -67 18 43 -28 -3 49 -18 27 2 -5 5 blend + hvcurveto + + + 60 60 -30 -30 1 blend + hmoveto + 40 700 -40 0 249 131 0 100 0 0 -249 -131 3 blend + hlineto + 26 -36 -6 207 143 0 -218 0 2 blend + rmoveto + 121 309 -39 -168 1 blend + hlineto + 113 81 -65 -247 -248 -81 -68 -113 200 -57 -150 117 -61 -71 -20 23 20 20 146 -20 20 143 -20 -117 61 71 -20 24 20 -200 57 150 8 blend + hvcurveto + -121 -36 121 -309 31 176 0 -218 0 309 -23 -132 3 blend + hlineto + 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 8 blend + hvcurveto + -121 -309 31 124 1 blend + hlineto + + + 1 vsindex + 60 60 -14.31456 -20 -40 1 blend + hmoveto + 40 700 -40 0 178.932 250 130 0 71.5728 100 0 0 -178.932 -250 -130 3 blend + hlineto + 20 -36 0 50.10097 70 0 0 -167.48035 -234 0 2 blend + rmoveto + 260 36 -260 540 128.83104 180 -55 0 167.48035 234 0 -540 -128.83104 -180 55 3 blend + hlineto + -700 0 -71.5728 -100 0 1 blend + vmoveto + 260 36 -260 540 128.83104 180 -55 0 167.48035 234 0 -540 -128.83104 -180 55 3 blend + hlineto + 0 298 0 0.2136 0 0 0 -204.48035 -253 0 2 blend + rmoveto + 240 36 -240 480 119 166 -50 0 146 134 0 -480 -119 -166 50 3 blend + hlineto + + + 1 vsindex + 60 60 -14 -30 -30 1 blend + hmoveto + 40 700 -40 0 179 280 100 0 72 100 0 0 -179 -280 -100 3 blend + hlineto + 20 -36 0 50 80 -10 0 -168 -214 -20 2 blend + rmoveto + 260 36 -260 580 129 140 -55 0 168 214 20 -580 -129 -140 55 3 blend + hlineto + -386 -20 -89 -139 -20 1 blend + vmoveto + 240 36 -240 580 119 146 -155 0 146 174 20 -580 -119 -146 155 3 blend + hlineto + + + 1 vsindex + 250 300 220 82 170 0 0 -24 5 10 2 blend + rmoveto + 159 -84 600 25 8 -500 0 24 -5 -10 2 blend + hlineto + 9 9 66 91 91 1 blend + -216 28 -9 80.3677 85 139 1 blend + 0 0 335 0 -0.3677 0 0 -5 104 95 -5 2 blend + rlineto + -196 -600 -171 -184 270 1 blend + hlineto + 160 -51 603 5.31882 -48 -449 -2 -36.72157 -1 6 2 blend + rmoveto + -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 5 blend + hhcurveto + -11 -89 2.14719 3 3 1 blend + hlineto + -94 -62 78 248 247 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 8 blend + hvcurveto + 11 89 -2.14719 -3 -3 1 blend + hlineto + 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 5 blend + hhcurveto + -11 -89 -10.02019 -14 -86 1 blend + hlineto + -121 -84 -95 -263 -264 75 -98 121 -217 -84.4559 -118 118 -128 -47.23805 -66 66 -20 -25.7662 -36 20 20 -9.30446 -13 -20 20 -10.73592 -15 -20 137 53.6796 75 -75 -20 -25.7662 -36 20 217 84.4559 118 -118 8 blend + hvcurveto + 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 5 blend + hvcurveto + + + 60 60 -30 -30 1 blend + hmoveto + 40 700 -40 0 280 100 0 100 0 0 -280 -100 3 blend + hlineto + 20 -366 3 90 57 0 -174 10 2 blend + rmoveto + 300 36 -300 561 170 -131 0 224 0 -561 -170 131 3 blend + hlineto + 280 -370 557 -20 -167 0 -150 -10 2 blend + rmoveto + 40 700 -40 0 280 100 0 100 0 0 -280 -100 3 blend + hlineto + + + 140 310 -20 -130 1 blend + hmoveto + 40 700 -40 0 280 100 0 100 0 0 -280 -100 3 blend + hlineto + -80 -36 -250 -10 100 0 -244 30 2 blend + rmoveto + 200 36 -200 490 300 -90 0 244 -30 -490 -300 90 3 blend + hlineto + -700 0 -100 0 1 blend + vmoveto + 200 36 -200 490 300 -90 0 244 -30 -490 -300 90 3 blend + hlineto + + + 60 60 -30 -30 1 blend + hmoveto + 40 700 -40 0 280 100 0 100 0 0 -280 -100 3 blend + hlineto + + + 100 320 60 250 112 113 57 -30 2 blend + rmoveto + 380 -40 -380 -113 43 30 0 -280 -112 113 -43 -30 3 blend + vlineto + 172 -330 298 175 -72 -113 -57 30 2 blend + rmoveto + 106 65 48 144 183 145 -81 117 33 6 70 67 -41 100 94 -39 4 blend + hvcurveto + 518 -40 -518 -170 -61 80 0 -280 -111 170 11 -30 3 blend + vlineto + -122 -50 -34 -81 -81 -51 34 122 -106 94 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 0 -280 -112 27 29 -36 3 blend + vlineto + -144 64 -48 108 -73.03868 -64 23.52126 117 31 8 -56.96132 -57 37.47874 181 144 -80 4 blend + vhcurveto + + + 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 4 blend + hvcurveto + 518 -40 -518 -140 -61 70 0 -280 -111 140 11 -40 3 blend + vlineto + -122 -50 -34 -81 -81 -51 34 122 -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 3 blend + vlineto + -144 64 -48 108 -52.45589 -94 17.45589 86.72974 31 3.27026 -47.54411 -67 48.54411 131.27026 144 -85.27026 4 blend + vhcurveto + + + 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 2 blend + rlineto + -5 19 21 -2 22 -5 -15 17 31 37 -35 34 45 -45 -3 -8 10 38 52 -54 5 blend + hhcurveto + + + 60 60 -30 -30 1 blend + hmoveto + 40 700 -40 0 280 100 0 100 0 0 -280 -100 3 blend + hlineto + 14 -366 0 280 -30 -39 -122 39 2 blend + rmoveto + 71 20 -33 106 1 blend + hlineto + 213 -334 49 416 -115 -248 39 22 -39 34 302 127 3 blend + 0 -247 370 -6 0 -443 85 136 -45 163 45 -1 -267 -35 3 -81 -3 4 blend + rlineto + -80 -26 28 -86 1 blend + hlineto + 50 -17 20 -7 73 2 -9 -2 2 blend + rmoveto + 27 -15 248 362 14 220 -60 4 -93 -34 446 -56 -29 36 120 -6 4 blend + rlineto + -46 -20 -286 -120 1 blend + hlineto + + + 60 60 -30 -30 1 blend + hmoveto + 40 700 -40 0 280 100 0 100 0 0 -280 -100 3 blend + hlineto + 20 -700 0 80 -10 0 -100 0 2 blend + rmoveto + 260 36 -260 530 140 -30 0 214 30 -530 -140 30 3 blend + hlineto + + + 60 60 -30 -30 1 blend + hmoveto + 40 700 -40 0 210 70 0 100 0 0 -210 -70 3 blend + hlineto + 410 -700 624 362 -218 0 -100 0 2 blend + rmoveto + 700 -40 -700 0 100 0 0 -210 -70 0 -100 0 3 blend + vlineto + 23 658 -5 113 -15 6 -229 -31 2 blend + rmoveto + -23 42 -170 -358 17 5 -113 15 -6 329 31 -331 21 186 -81 109 77 31 9 -7 5 blend + 0 -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 1 blend + hlineto + + + 60 60 -30 -30 1 blend + hmoveto + 35 700 -35 5 215 65 0 100 0 -5 -215 -65 3 blend + hlineto + 16 -54 7 54 127 18 -226 -84 2 blend + rmoveto + 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 0 2 blend + rmoveto + 35 700 -35 5 215 65 0 100 0 -5 -215 -65 3 blend + hlineto + + + 246 384 163 -203 1 blend + -10 rmoveto + 11 49 14 126 1 blend + hlineto + 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 8 blend + hvcurveto + -11 -49 -14 -126 1 blend + hlineto + -121 -75 -95 -263 -264 75 -98 121 -217 -118 118 -137 -75 75 -20 -36 20 20 -13 -20 20 -15 -20 137 75 -75 -20 -36 20 217 118 -118 8 blend + hvcurveto + 0 36 0 9 45 0 228 0 2 blend + rmoveto + -94 -60 78 248 247 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 8 blend + hvcurveto + 11 49 -3 37 1 blend + hlineto + 95 59 -75 -247 -248 -59 -78 -95 218 -39 -168 139 -39 -93 -20 33 20 20 146 -20 20 143 -20 -139 39 93 -20 34 20 -218 39 168 8 blend + hvcurveto + + + 60 60 -30 -30 1 blend + hmoveto + 40 700 -40 0 280 100 0 100 0 0 -280 -100 3 blend + hlineto + 20 -40 0 230 0 0 -212 -35 2 blend + rmoveto + 100 390 -25 -48 1 blend + hlineto + 119 55 -95 -133 -133 -55 -94 -119 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 8 blend + hvcurveto + -100 -40 90 -390 25 48 0 -213 -35 390 8 -105 3 blend + hlineto + 160 63 121 146 148 -63 120 -160 215 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 8 blend + hvcurveto + -90 -390 -9 104 1 blend + hlineto + + + 330 378 80 -228 1 blend + -130 rmoveto + 44 0 266 110 1 blend + hlineto + -99 143 -32 -18 0 -11 -30 0 157 0 0 -251 -137 0 18 0 4 blend + rlineto + + + 350 630 35 -215 1 blend + hmoveto + 44 24 276 87 1 blend + hlineto + -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 1 blend + hlineto + -153 -195 -450 -183 156 10 -109 84 2 blend + rmoveto + 40 700 -40 0 280 100 0 100 0 0 -280 -100 3 blend + hlineto + 20 -40 0 230 44 0 -212 -35 2 blend + rmoveto + 100 400 -15 -68 1 blend + hlineto + 119 55 -95 -133 -133 -55 -94 -119 176 -90 -142 28 -42 -13 10 83 -10 -10 84 13 -10 78 12 -28 42 13 10 86 -10 -176 90 142 8 blend + hvcurveto + -100 -40 90 -400 15 68 0 -152 -76 390 28 -125 3 blend + hlineto + 160 63 121 146 148 -63 120 -160 215 53 -51 3 26 36 0 -28 12 0 46 22 0 43 48 -3 -36 -26 0 -28 24 -215 -54 54 8 blend + hvcurveto + -90 -390 -17 112 1 blend + hlineto + + + 350 630 35 -215 1 blend + hmoveto + 44 24 276 87 1 blend + hlineto + -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 1 blend + hlineto + -153 -195 -450 -183 156 10 -109 84 2 blend + rmoveto + 40 700 -40 0 280 100 0 100 0 0 -280 -100 3 blend + hlineto + 20 -40 0 230 44 0 -212 -35 2 blend + rmoveto + 100 400 -15 -68 1 blend + hlineto + 119 55 -95 -133 -133 -55 -94 -119 176 -90 -142 28 -42 -13 10 83 -10 -10 84 13 -10 78 12 -28 42 13 10 86 -10 -176 90 142 8 blend + hvcurveto + -100 -40 90 -400 15 68 0 -152 -76 390 28 -125 3 blend + hlineto + 160 63 121 146 148 -63 120 -160 215 53 -51 3 26 36 0 -28 12 0 46 22 0 43 48 -3 -36 -26 0 -28 24 -215 -54 54 8 blend + hvcurveto + -90 -390 -17 112 1 blend + hlineto + + + 2 vsindex + 349 157 731 329 -219 69.90141 34 96 -34 22.23555 2 blend + rmoveto + -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 4 blend + vhcurveto + 8 63 44 89 13.53165 1 blend + hlineto + 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 5 blend + hvcurveto + 17 37 5 19 -6 4.49112 -4 195 4 54.21736 2 blend + rlineto + 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 1 blend + hlineto + -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 0 0 0 -0.15161 5 blend + hvcurveto + 0 -81 44 -57 82 -65 50 -40 0 0 0 -0.15161 -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 4 blend + vhcurveto + -8 -63 -43 -78 -11.8934 1 blend + hlineto + -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 5 blend + hvcurveto + -17 -37 0 -19 1 -5.10217 4 -198 -4 -55.04384 2 blend + rlineto + -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 1 blend + hlineto + 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 2 blend + rmoveto + -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 4 blend + vhcurveto + 5 126 23 93 -36.10632 15.57735 1 blend + hlineto + 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 5 blend + hvcurveto + 39 0 0 221 76 -18.91333 55.7757 0 0 0 0.6738 -0.38344 2 blend + rlineto + 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 1 blend + hlineto + -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 -1 -1 1 -0.28877 0 5 blend + hvcurveto + 1 -81 40 -64 85 -58 58 -40 -1 -1 1 -0.28877 0 -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 4 blend + vhcurveto + -8 0 -83 -26 -227 90.08673 -47.60095 0 0 0 0 0.46121 2 blend + rlineto + -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 5 blend + hvcurveto + -40 0 -240 -66 -8.18893 -5.89154 1 blend + hlineto + -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 1 blend + hlineto + 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 5 blend + hvcurveto + + + 200 350 -50 -80 1 blend + hmoveto + 40 700 -40 0 280 100 0 100 0 0 -280 -100 3 blend + hlineto + -170 -36 -340 40 70 0 -214 -60 2 blend + rmoveto + 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 70 67 -41 100 94 -39 4 blend + hvcurveto + 518 -40 -518 -170 -61 80 0 -280 -111 170 11 -30 3 blend + vlineto + -122 -50 -34 -81 -81 -51 34 122 -106 94 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 0 -280 -112 170 61 -80 3 blend + vlineto + -144 64 -48 108 -100 -94 39 117 31 8.45772 -70 -67 41 181 144 -80.45772 4 blend + vhcurveto + + + 378 700 752 352 -182 0 100 0 2 blend + rmoveto + -41 -5 -209 -75 1 blend + hlineto + -130 -700 -371 46 125 0 -100 0 2 blend + rlineto + 36 9 184 51 1 blend + hlineto + -178 700 -356 -88 192 0 100 0 2 blend + rmoveto + -45 -9 -295 -121 1 blend + hlineto + 135 -700 373 -19 -119 0 -100 0 2 blend + rlineto + 40 9 280 121 1 blend + hlineto + 40 39 -19 50 -21 -3 221 3 2 blend + rmoveto + -70 -39 70 10 -200 -160 3 -221 -3 -10 200 160 3 blend + hlineto + + + 500 700 824 377 -352 0 100 0 2 blend + rmoveto + -42 1 -218 -119 1 blend + hlineto + -87 -638 6 -210 39 184 0 108 0 6 36 -24 3 blend + 0 -94 638 -38 -211 44 185 0 -108 0 12 -167 -82 3 blend + 0 -95 -638 8 -196 50 173 -10 108 10 9 34 -27 3 blend + 0 -93 638 -43 -217 39 198 10 -108 -10 0 -246 -144 3 blend + 0 107 -700 45 226 -5 -172 0 -100 0 -27 243 181 3 blend + 0 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 1 blend + hlineto + + + 337 583 23 -173 1 blend + hmoveto + 45 15 335 95 1 blend + hlineto + -169 364 -141 336 -45 -291 -70 79 5 110 -1 -269 30 81 -5 -10 1 -15 -335 -95 5 blend + 0 160 -363 285 78 -94 14 -87 10 2 blend + rlineto + -167 -337 -286 -71 95 -16 -13 -8 2 blend + rmoveto + 40 0 142 332 13 4 155 364 -40 8 190 212 2 0 -2 279 -57 -161 19 -20 -10 -1 220 -106 -6 30 -28 292 27 -13 -13 90 38 -10 -190 -210 9 blend + 0 -130 -337 -16 -6 -287 41 153 5 78 -66 4 -212 89 8 -44 42 4 blend + rlineto + + + 400 700 560 330 -100 0 100 0 2 blend + rmoveto + -41 -9 -189 -111 1 blend + hlineto + -154 -490 25 0 -262 -16 127 -10 -110 20 -13 175 93 -29 0 29 4 blend + rlineto + -163 490 -263 -8 69 39 110 -49 2 blend + rmoveto + -47 -3 -302 -78 1 blend + hlineto + 170 -490 38 0 281 30 -106 -39 -110 49 -15 252 115 29 0 -29 4 blend + rlineto + 2 44 9 28 -9 -33 26 133 2 blend + rmoveto + -40 -254 40 0 -280 -100 43 -16 -153 0 280 100 3 blend + hlineto + + + 60 36 60 -30 -30 0 214 30 2 blend + rmoveto + 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 2 blend + rmoveto + 320 36 -320 640 260 -60 0 214 30 -640 -260 60 3 blend + hlineto + -700 0 -100 0 1 blend + vmoveto + 320 36 -320 640 260 -60 0 214 30 -640 -260 60 3 blend + hlineto + + + 50 730 -20 -30 20 0 100 0 2 blend + rmoveto + 150 8 40 120 40 0 -8 0 2 blend + 0 32 -150 -10 0 88 0 -40 -120 -40 0 -20 0 3 blend + rlineto + + + 137 271 0 79 0 -250 55 -25 2 blend + rmoveto + 29 0 373 0 1 blend + hlineto + 6 269 500 66 40 1 blend + rlineto + -41 0 -374 0 1 blend + hlineto + -31 -210 0 -168 0 -500 50 -40 2 blend + rmoveto + 52 -190 50 189 0 356 0 0 -236 0 0 354 0 0 236 0 4 blend + rlineto + + + 136 371 0 195 -75 0 267 -38 2 blend + rmoveto + -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 2 blend + rmoveto + -190 -52 189 -50 0 -236 0 0 -356 0 0 236 0 0 -354 0 4 blend + rlineto + + + 308 345 625 -71 300 0 -183 38 2 blend + rmoveto + 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 2 blend + rmoveto + 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 0 1 blend + hlineto + -6 -269 -500 -66 -40 1 blend + rlineto + 41 0 374 0 1 blend + hlineto + 31 210 0 168 0 500 -50 40 2 blend + rmoveto + -52 190 -50 -189 0 -356 0 0 236 0 0 -354 0 0 -236 0 4 blend + rlineto + + + + + 111 60 109 -30 1 blend + hmoveto + 120 -50 -120 100 180 -100 0 -140 0 -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 0 2 blend + rmoveto + 40 60 -40 0 150 0 0 65 0 0 -150 0 3 blend + hlineto + + + 4 vsindex + + + 5 vsindex + 50 vmoveto + -50 50 vlineto + -50 750 750 750 -750 0 0 -750 2 blend + rlineto + + + 60 60 -30 -30 1 blend + hmoveto + 50 120 -50 0 140 0 100 180 -100 0 -140 0 3 blend + hlineto + + + + + + + + + + + + + + + 6 vsindex + + + 7 vsindex + 70 278 0 -241 0 1 blend + rmoveto + 239 143 0 0 1 blend + hlineto + 0 102 70 0 0 0 70 0 0 -102 0 0 -70 0 0 102 4 blend + rlineto + 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/figArnaud.otf.ttx b/tests/data/figArnaud.otf.ttx new file mode 100644 index 0000000..ec83bb3 --- /dev/null +++ b/tests/data/figArnaud.otf.ttx @@ -0,0 +1,2893 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + wght + + + V000 + + + V001 + + + V002 + + + V003 + + + V004 + + + V005 + + + V006 + + + wght + + + V000 + + + V001 + + + V002 + + + V003 + + + V004 + + + V005 + + + V006 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 vsindex + + + + + 2 vsindex + + + + + 3 vsindex + + + 4 vsindex + + + + + 3 vsindex + + + 307 162 260 190 0 1 2 blend + rmoveto + 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 16 blend + vhcurveto + -30 -1 0 -170 0 28 2 blend + rmoveto + -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 16 blend + vhcurveto + 15 299 -10 175 0 -39 2 blend + rmoveto + 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 16 blend + vhcurveto + -30 -1 0 -165 0 -34 2 blend + rmoveto + -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 16 blend + vhcurveto + + + 53 343 30 10 -40 -46 2 blend + rmoveto + 28 0 0 137 14 0 2 blend + rlineto + 257 -28 26 46 0 -137 2 blend + vlineto + 190 -25 240 141 0 -120 2 blend + rmoveto + 25 -190 -25 0 120 -240 -141 0 -120 3 blend + vlineto + -33 -547 10 -20 32 143 2 blend + rmoveto + -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 0 0 0 0 0 162 0 1 blend + 600 -28 0 0 0 0 0 -162 0 1 blend + hlineto + -197 -455 -30 0 0 0 0 40 -180 0 100 -65 0 0 0 0 2 blend + rmoveto + 297 25 -297 30 0 0 100 0 120 250 0 0 130 0 0 0 0 -30 0 0 -100 0 -120 -250 3 blend + hlineto + 29 181 0 0 0 0 0 4 1 blend + hmoveto + 188 412 -151 0 0 0 -10 -40 176 -341 -100 -64 0 200 -6 3 2 blend + rlineto + 18 -20 341 0 -1 0 -200 6 -3 0 0 0 0 10 0 0 2 blend + vlineto + -197 -430 -30 0 0 0 0 40 -180 0 100 65 0 0 0 0 2 blend + rlineto + + + 3 vsindex + 279 414 0 280 201 0 -10 -25 2 blend + rmoveto + 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 0 0 -101 0 10 15 2 blend + rlineto + -24 -99 -58 -119 -81 -94 21 -15 0 -4 -31 0 -31 11 -17 -52 25 15 3 76 0 -90 -3 10 -14 3 20 -21 98 -25 -10 -70 8 blend + rcurveline + 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 2 blend + rmoveto + -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 16 blend + vhcurveto + + + 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 2 blend + rlineto + -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 0 0 0 -100 2 blend + rlineto + -28 -100 0 -6 -162 1 blend + hlineto + -211 -5 0 0 -214 7 0 -100 0 -25 2 blend + rmoveto + 229 100 -50 220 15 1 blend + hlineto + 10 5 0 50 0 140 0 100 0 25 2 blend + rlineto + 20 -239 0 0 0 100 -100 0 -220 -155 2 blend + vlineto + + + 3 vsindex + 35 196 0 40 -10 0 0 15 2 blend + rmoveto + -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 0 0 101 0 -10 -15 2 blend + rlineto + 24 99 55 99 81 94 -21 15 0 4 31 0 31 -11 20 55 -22 -15 17 -56 0 90 3 -10 14 -3 -20 21 -98 25 10 70 8 blend + rcurveline + -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 2 blend + rmoveto + 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 16 blend + vhcurveto + + + 268 151 247 162 10 15 2 blend + rmoveto + 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 2 blend + rlineto + -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 2 blend + rlineto + 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 2 blend + rmoveto + -10 -5 0 -60 0 -20 -140 0 -90 0 0 -25 2 blend + rlineto + -20 257 25 0 0 0 0 -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 2 blend + rmoveto + 16 -18 0 0 0 0 51 0 0 0 -1 -113 2 blend + rlineto + 35 34 33 11 35 0 0 0 23 -12 0 0 0 27 -10 0 0 0 29 -9 0 0 0 14 4 0 0 0 50 -2 5 blend + hhcurveto + 61 41 -44 -65 -65 -30 -49 -40 -76 0 0 0 51 -21 0 0 0 36 -15 0 0 0 -21 24 0 0 0 -27 33 0 0 0 -27 29 0 0 0 -37 6 0 0 0 -11 23 0 0 0 -36 6 0 0 0 17 32 9 blend + hvcurveto + -142 -268 32 0 132 251 0 0 0 -114 11 0 0 0 69 98 20 0 0 9 172 0 0 0 0 -10 0 0 0 94 -28 0 0 0 -76 -110 6 blend + rlineto + 53 101 26 35 71 0 0 0 43 -1 0 0 0 -27 -30 -10 0 0 42 -4 0 0 0 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 0 0 0 -53 -46 -1 0 0 -49 -32 0 0 0 -30 -29 0 0 0 -14 -12 0 0 0 -22 -6 0 0 0 -26 -14 9 blend + vhcurveto + + + 5 vsindex + + + 5 vsindex + + + 5 vsindex + + + 5 vsindex + + + 5 vsindex + + + 5 vsindex + + + 5 vsindex + + + 5 vsindex + + + 5 vsindex + + + 5 vsindex + + + 5 vsindex + + + 5 vsindex + + + 5 vsindex + + + 5 vsindex + + + 5 vsindex + + + 5 vsindex + + + 5 vsindex + + + 5 vsindex + + + 5 vsindex + + + 5 vsindex + + + 5 vsindex + + + 5 vsindex + + + 5 vsindex + + + 5 vsindex + + + 5 vsindex + + + 5 vsindex + + + 5 vsindex + + + 5 vsindex + + + 5 vsindex + + + 5 vsindex + + + 5 vsindex + + + 5 vsindex + + + 5 vsindex + + + 5 vsindex + + + 5 vsindex + + + 5 vsindex + + + 5 vsindex + + + 5 vsindex + + + 5 vsindex + + + 5 vsindex + + + 5 vsindex + + + 5 vsindex + + + 5 vsindex + + + 5 vsindex + + + 5 vsindex + + + 5 vsindex + + + 5 vsindex + + + 5 vsindex + + + 5 vsindex + + + 5 vsindex + + + 5 vsindex + + + 5 vsindex + + + 5 vsindex + + + 5 vsindex + + + 5 vsindex + + + 5 vsindex + + + 5 vsindex + + + 5 vsindex + + + 5 vsindex + + + 5 vsindex + + + 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 16 blend + vhcurveto + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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/test_compile.py b/tests/test_compile.py index 2fe8ccc..4c3709f 100644 --- a/tests/test_compile.py +++ b/tests/test_compile.py @@ -21,7 +21,7 @@ def cleanupTTX(ttx): @pytest.mark.parametrize("sourceName", ["figArnaud.rcjk", "MutatorSans.fontra"]) -@pytest.mark.parametrize("outSuffix", [".ttf"]) +@pytest.mark.parametrize("outSuffix", [".ttf", ".otf"]) def test_main(tmpdir, sourceName, outSuffix): tmpdir = pathlib.Path(tmpdir) sourcePath = dataDir / sourceName From bf24754f263dfc6dc134fde7810de9ecb7a4bc88 Mon Sep 17 00:00:00 2001 From: Just van Rossum Date: Fri, 12 Jul 2024 22:56:15 +0200 Subject: [PATCH 09/29] Factor out the CFF var data hard bits --- src/fontra_compile/builder.py | 60 +++++++++++++++++++---------------- 1 file changed, 33 insertions(+), 27 deletions(-) diff --git a/src/fontra_compile/builder.py b/src/fontra_compile/builder.py index 0fdbf86..42a231e 100644 --- a/src/fontra_compile/builder.py +++ b/src/fontra_compile/builder.py @@ -474,33 +474,7 @@ async def buildFont(self) -> TTFont: self.glyphInfos, "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)) + varDataList, regionList = prepareCFFVarData(charStrings, charStringSupports) builder.setupCFF2(charStrings) addCFFVarStore(builder.font, None, varDataList, regionList) @@ -795,6 +769,38 @@ def buildCharString(glyph, glyphSources, defaultLayerGlyph, model): return charString +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 addLSB( leftSideBearings: dict[str, int], metrics: dict[str, int] ) -> dict[str, tuple[int, int]]: From 90245b005ed0ddaa9d4ecf354b929a687ae14df1 Mon Sep 17 00:00:00 2001 From: Just van Rossum Date: Fri, 12 Jul 2024 22:57:03 +0200 Subject: [PATCH 10/29] whitespace --- src/fontra_compile/builder.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/fontra_compile/builder.py b/src/fontra_compile/builder.py index 42a231e..e1452e6 100644 --- a/src/fontra_compile/builder.py +++ b/src/fontra_compile/builder.py @@ -473,9 +473,7 @@ async def buildFont(self) -> TTFont: charStringSupports = getGlyphInfoAttributes( self.glyphInfos, "charStringSupports" ) - varDataList, regionList = prepareCFFVarData(charStrings, charStringSupports) - builder.setupCFF2(charStrings) addCFFVarStore(builder.font, None, varDataList, regionList) From bd3dee089d3e5b72eaffc5726da786b95127f3b7 Mon Sep 17 00:00:00 2001 From: Just van Rossum Date: Fri, 12 Jul 2024 23:01:29 +0200 Subject: [PATCH 11/29] Fix bounds pen usage: for CFF2 we need tight bounds, for TTF control bounds --- src/fontra_compile/builder.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fontra_compile/builder.py b/src/fontra_compile/builder.py index e1452e6..1615696 100644 --- a/src/fontra_compile/builder.py +++ b/src/fontra_compile/builder.py @@ -275,7 +275,7 @@ async def prepareOneGlyph(self, glyphName: str) -> GlyphInfo: componentInfo = await self.collectComponentInfo(glyph, defaultSourceIndex) - boundsPen = (ControlBoundsPen if self.buildCFF2 else BoundsPen)(None) + boundsPen = (BoundsPen if self.buildCFF2 else ControlBoundsPen)(None) defaultLayerGlyph.path.drawPoints(PointToSegmentPen(boundsPen)) leftSideBearing = boundsPen.bounds[0] if boundsPen.bounds is not None else 0 From 263d44b0a1d4886b3c58a4a3fba17508065161bb Mon Sep 17 00:00:00 2001 From: Just van Rossum Date: Fri, 12 Jul 2024 23:04:26 +0200 Subject: [PATCH 12/29] Fiddle --- src/fontra_compile/builder.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/fontra_compile/builder.py b/src/fontra_compile/builder.py index 1615696..1c13d9a 100644 --- a/src/fontra_compile/builder.py +++ b/src/fontra_compile/builder.py @@ -76,6 +76,9 @@ def __post_init__(self) -> 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 @@ -224,7 +227,7 @@ async def prepareGlyphs(self) -> None: xAdvance=500, leftSideBearing=0, # TODO: fix when actual notdef shape is added xAdvanceVariations=[500], - gvarVariations=None if self.buildCFF2 else [], + gvarVariations=None, ) self.glyphInfos[glyphName] = glyphInfo From 27708b1b4b8d08c64adb3cc5c2d9f2193cbb96cb Mon Sep 17 00:00:00 2001 From: Just van Rossum Date: Sat, 13 Jul 2024 07:34:10 +0200 Subject: [PATCH 13/29] Do subroutinization --- pyproject.toml | 2 +- src/fontra_compile/builder.py | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 5326128..513e32d 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 = [ diff --git a/src/fontra_compile/builder.py b/src/fontra_compile/builder.py index 1c13d9a..93087e5 100644 --- a/src/fontra_compile/builder.py +++ b/src/fontra_compile/builder.py @@ -1,6 +1,7 @@ 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.protocols import ReadableFontBackend @@ -498,6 +499,9 @@ async def buildFont(self) -> TTFont: builder.setupOS2() builder.setupPost() + if self.buildCFF2: + cffsubr.subroutinize(builder.font) + return builder.font def buildVARC(self, axisTags): From aa699e6c8237cc3b219941aab16f1085f1d28887 Mon Sep 17 00:00:00 2001 From: Just van Rossum Date: Sat, 13 Jul 2024 07:36:03 +0200 Subject: [PATCH 14/29] Adjust expected output to subroutinization --- tests/data/MutatorSans.otf.ttx | 905 +++++++++++++++------------------ tests/data/figArnaud.otf.ttx | 268 +++++----- 2 files changed, 534 insertions(+), 639 deletions(-) diff --git a/tests/data/MutatorSans.otf.ttx b/tests/data/MutatorSans.otf.ttx index 6964207..261eec7 100644 --- a/tests/data/MutatorSans.otf.ttx +++ b/tests/data/MutatorSans.otf.ttx @@ -63,12 +63,12 @@ - + - - + + @@ -449,6 +449,161 @@ + + + + 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 + @@ -456,30 +611,20 @@ - 20 30 -30 0 1 blend - hmoveto - 40 7 220 63 1 blend - hlineto - 140 700 375 -56 -169 0 100 0 2 blend + 20 30 -30 0 -99 callsubr + 40 7 220 63 -107 callsubr + 140 700 375 -56 -169 -84 callsubr rlineto - -35 -7 -195 -43 1 blend - hlineto - -90 -536 -235 96 79 60 -144 -60 2 blend - rmoveto - 250 36 -250 450 220 -190 -6 174 16 -450 -220 190 3 blend - hlineto - 257 -200 585 23 -275 -54 -130 44 2 blend - rmoveto - 44 9 296 121 1 blend - hlineto - -145 700 -375 29 151 0 100 0 2 blend + -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 1 blend - hlineto - -17 -39 15 -73 5 3 -221 -3 2 blend - rmoveto - 47 39 -47 3 223 147 -3 221 3 -3 -223 -147 3 blend - hlineto + -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 @@ -487,211 +632,141 @@ 1 vsindex - 60 60 -21 -30 -30 1 blend - hmoveto - 40 700 -40 0 193 270 110 0 72 100 1 0 -193 -270 -110 3 blend - hlineto - 20 -367 0 164 230 140 0 -84 -86 -11 2 blend - rmoveto - 130 610 -36 -65 -393 1 blend - hlineto - 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 8 blend - hvcurveto + 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 2 blend - rlineto + 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 3 blend - hlineto - 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 8 blend - hvcurveto - -110 -570 22 45 392 1 blend - hlineto + -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 2 blend - rmoveto - -179 -13 -57 -59 -83 4 85 14 -27 11 13 -130 33 93 -17 29 15 -193 23 162 5 blend - hhcurveto - -11 -39 3 -47 1 blend - hlineto - -94 -60 78 248 247 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 8 blend - hvcurveto - 11 39 -3 47 1 blend - hlineto - 82 57 -56 -176 14 192 -22 -162 129 -33 -92 -17 28 15 6 86 13 28 -12 -13 5 blend - hvcurveto - 39 5 1 251 136 -1 24 18 2 blend - rlineto - 191 -17 -71 72 -104 -5 48 -18 -27 -2 4 -130 -67 67 17 42 -28 -193 -107 104 5 blend - hhcurveto - -11 -39 -14 -136 1 blend - hlineto - -121 -75 -95 -263 -264 75 -98 121 -217 -118 118 -137 -75 75 -20 -36 20 20 -13 -20 20 -15 -20 137 75 -75 -20 -36 20 217 118 -118 8 blend - hvcurveto - 11 39 14 136 1 blend - hlineto - 105 71 74 194 16 194 106 -103 130 68 -67 18 43 -28 -3 49 -18 27 2 -5 5 blend - hvcurveto + 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 -30 -30 1 blend - hmoveto - 40 700 -40 0 249 131 0 100 0 0 -249 -131 3 blend - hlineto - 26 -36 -6 207 143 0 -218 0 2 blend - rmoveto - 121 309 -39 -168 1 blend - hlineto - 113 81 -65 -247 -248 -81 -68 -113 200 -57 -150 117 -61 -71 -20 23 20 20 146 -20 20 143 -20 -117 61 71 -20 24 20 -200 57 150 8 blend - hvcurveto - -121 -36 121 -309 31 176 0 -218 0 309 -23 -132 3 blend - hlineto - 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 8 blend - hvcurveto - -121 -309 31 124 1 blend - hlineto + 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 1 blend - hmoveto - 40 700 -40 0 178.932 250 130 0 71.5728 100 0 0 -178.932 -250 -130 3 blend - hlineto - 20 -36 0 50.10097 70 0 0 -167.48035 -234 0 2 blend - rmoveto - 260 36 -260 540 128.83104 180 -55 0 167.48035 234 0 -540 -128.83104 -180 55 3 blend - hlineto - -700 0 -71.5728 -100 0 1 blend - vmoveto - 260 36 -260 540 128.83104 180 -55 0 167.48035 234 0 -540 -128.83104 -180 55 3 blend - hlineto - 0 298 0 0.2136 0 0 0 -204.48035 -253 0 2 blend - rmoveto - 240 36 -240 480 119 166 -50 0 146 134 0 -480 -119 -166 50 3 blend - hlineto + 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 -30 -30 1 blend - hmoveto - 40 700 -40 0 179 280 100 0 72 100 0 0 -179 -280 -100 3 blend - hlineto + 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 - 260 36 -260 580 129 140 -55 0 168 214 20 -580 -129 -140 55 3 blend - hlineto + -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 3 blend - hlineto + 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 2 blend - rmoveto + 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 28 -9 80.3677 85 139 1 blend - 0 0 335 0 -0.3677 0 0 -5 104 95 -5 2 blend - rlineto - -196 -600 -171 -184 270 1 blend - hlineto - 160 -51 603 5.31882 -48 -449 -2 -36.72157 -1 6 2 blend - rmoveto - -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 5 blend - hhcurveto - -11 -89 2.14719 3 3 1 blend - hlineto - -94 -62 78 248 247 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 8 blend - hvcurveto - 11 89 -2.14719 -3 -3 1 blend - hlineto + -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 5 blend - hhcurveto - -11 -89 -10.02019 -14 -86 1 blend - hlineto - -121 -84 -95 -263 -264 75 -98 121 -217 -84.4559 -118 118 -128 -47.23805 -66 66 -20 -25.7662 -36 20 20 -9.30446 -13 -20 20 -10.73592 -15 -20 137 53.6796 75 -75 -20 -25.7662 -36 20 217 84.4559 118 -118 8 blend - hvcurveto + 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 5 blend - hvcurveto + 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 - 60 60 -30 -30 1 blend - hmoveto - 40 700 -40 0 280 100 0 100 0 0 -280 -100 3 blend - hlineto - 20 -366 3 90 57 0 -174 10 2 blend - rmoveto - 300 36 -300 561 170 -131 0 224 0 -561 -170 131 3 blend - hlineto - 280 -370 557 -20 -167 0 -150 -10 2 blend - rmoveto - 40 700 -40 0 280 100 0 100 0 0 -280 -100 3 blend - hlineto + -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 1 blend - hmoveto - 40 700 -40 0 280 100 0 100 0 0 -280 -100 3 blend - hlineto - -80 -36 -250 -10 100 0 -244 30 2 blend - rmoveto - 200 36 -200 490 300 -90 0 244 -30 -490 -300 90 3 blend - hlineto - -700 0 -100 0 1 blend - vmoveto - 200 36 -200 490 300 -90 0 244 -30 -490 -300 90 3 blend - hlineto + 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 - 60 60 -30 -30 1 blend - hmoveto - 40 700 -40 0 280 100 0 100 0 0 -280 -100 3 blend - hlineto + -91 callsubr 100 320 60 250 112 113 57 -30 2 blend rmoveto - 380 -40 -380 -113 43 30 0 -280 -112 113 -43 -30 3 blend - vlineto - 172 -330 298 175 -72 -113 -57 30 2 blend - rmoveto - 106 65 48 144 183 145 -81 117 33 6 70 67 -41 100 94 -39 4 blend - hvcurveto - 518 -40 -518 -170 -61 80 0 -280 -111 170 11 -30 3 blend - vlineto - -122 -50 -34 -81 -81 -51 34 122 -106 94 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 0 -280 -112 27 29 -36 3 blend + 380 -40 -380 -113 43 30 -85 callsubr + 113 -43 -30 3 blend vlineto - -144 64 -48 108 -73.03868 -64 23.52126 117 31 8 -56.96132 -57 37.47874 181 144 -80 4 blend + 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 4 blend - hvcurveto - 518 -40 -518 -140 -61 70 0 -280 -111 140 11 -40 3 blend - vlineto - -122 -50 -34 -81 -81 -51 34 122 -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 3 blend - vlineto - -144 64 -48 108 -52.45589 -94 17.45589 86.72974 31 3.27026 -47.54411 -67 48.54411 131.27026 144 -85.27026 4 blend + 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 @@ -702,429 +777,287 @@ 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 2 blend - rlineto + -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 - 60 60 -30 -30 1 blend - hmoveto - 40 700 -40 0 280 100 0 100 0 0 -280 -100 3 blend - hlineto - 14 -366 0 280 -30 -39 -122 39 2 blend - rmoveto - 71 20 -33 106 1 blend - hlineto - 213 -334 49 416 -115 -248 39 22 -39 34 302 127 3 blend - 0 -247 370 -6 0 -443 85 136 -45 163 45 -1 -267 -35 3 -81 -3 4 blend - rlineto - -80 -26 28 -86 1 blend - hlineto - 50 -17 20 -7 73 2 -9 -2 2 blend - rmoveto - 27 -15 248 362 14 220 -60 4 -93 -34 446 -56 -29 36 120 -6 4 blend - rlineto - -46 -20 -286 -120 1 blend - hlineto + -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 - 60 60 -30 -30 1 blend - hmoveto - 40 700 -40 0 280 100 0 100 0 0 -280 -100 3 blend - hlineto - 20 -700 0 80 -10 0 -100 0 2 blend - rmoveto - 260 36 -260 530 140 -30 0 214 30 -530 -140 30 3 blend - hlineto + -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 -30 -30 1 blend - hmoveto - 40 700 -40 0 210 70 0 100 0 0 -210 -70 3 blend - hlineto - 410 -700 624 362 -218 0 -100 0 2 blend - rmoveto + 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 2 blend - rmoveto - -23 42 -170 -358 17 5 -113 15 -6 329 31 -331 21 186 -81 109 77 31 9 -7 5 blend - 0 -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 + 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 1 blend - hlineto + 25 7 59 43 -107 callsubr - 60 60 -30 -30 1 blend - hmoveto - 35 700 -35 5 215 65 0 100 0 -5 -215 -65 3 blend - hlineto - 16 -54 7 54 127 18 -226 -84 2 blend - rmoveto + 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 0 2 blend - rmoveto - 35 700 -35 5 215 65 0 100 0 -5 -215 -65 3 blend - hlineto + 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 1 blend - hlineto - 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 8 blend - hvcurveto - -11 -49 -14 -126 1 blend - hlineto - -121 -75 -95 -263 -264 75 -98 121 -217 -118 118 -137 -75 75 -20 -36 20 20 -13 -20 20 -15 -20 137 75 -75 -20 -36 20 217 118 -118 8 blend - hvcurveto - 0 36 0 9 45 0 228 0 2 blend - rmoveto - -94 -60 78 248 247 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 8 blend - hvcurveto - 11 49 -3 37 1 blend - hlineto - 95 59 -75 -247 -248 -59 -78 -95 218 -39 -168 139 -39 -93 -20 33 20 20 146 -20 20 143 -20 -139 39 93 -20 34 20 -218 39 168 8 blend - hvcurveto + 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 - 60 60 -30 -30 1 blend - hmoveto - 40 700 -40 0 280 100 0 100 0 0 -280 -100 3 blend - hlineto - 20 -40 0 230 0 0 -212 -35 2 blend - rmoveto - 100 390 -25 -48 1 blend - hlineto - 119 55 -95 -133 -133 -55 -94 -119 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 8 blend - hvcurveto - -100 -40 90 -390 25 48 0 -213 -35 390 8 -105 3 blend - hlineto - 160 63 121 146 148 -63 120 -160 215 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 8 blend - hvcurveto - -90 -390 -9 104 1 blend - hlineto + -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 1 blend - hlineto - -99 143 -32 -18 0 -11 -30 0 157 0 0 -251 -137 0 18 0 4 blend - rlineto + 44 0 266 110 -107 callsubr + -99 143 -32 -18 0 -11 -30 0 157 0 0 -251 -137 0 18 0 -102 callsubr - 350 630 35 -215 1 blend - hmoveto - 44 24 276 87 1 blend - hlineto - -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 1 blend - hlineto - -153 -195 -450 -183 156 10 -109 84 2 blend - rmoveto - 40 700 -40 0 280 100 0 100 0 0 -280 -100 3 blend - hlineto - 20 -40 0 230 44 0 -212 -35 2 blend - rmoveto - 100 400 -15 -68 1 blend - hlineto - 119 55 -95 -133 -133 -55 -94 -119 176 -90 -142 28 -42 -13 10 83 -10 -10 84 13 -10 78 12 -28 42 13 10 86 -10 -176 90 142 8 blend - hvcurveto - -100 -40 90 -400 15 68 0 -152 -76 390 28 -125 3 blend - hlineto - 160 63 121 146 148 -63 120 -160 215 53 -51 3 26 36 0 -28 12 0 46 22 0 43 48 -3 -36 -26 0 -28 24 -215 -54 54 8 blend - hvcurveto - -90 -390 -17 112 1 blend - hlineto + -81 callsubr - 350 630 35 -215 1 blend - hmoveto - 44 24 276 87 1 blend - hlineto - -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 1 blend - hlineto - -153 -195 -450 -183 156 10 -109 84 2 blend - rmoveto - 40 700 -40 0 280 100 0 100 0 0 -280 -100 3 blend - hlineto - 20 -40 0 230 44 0 -212 -35 2 blend - rmoveto - 100 400 -15 -68 1 blend - hlineto - 119 55 -95 -133 -133 -55 -94 -119 176 -90 -142 28 -42 -13 10 83 -10 -10 84 13 -10 78 12 -28 42 13 10 86 -10 -176 90 142 8 blend - hvcurveto - -100 -40 90 -400 15 68 0 -152 -76 390 28 -125 3 blend - hlineto - 160 63 121 146 148 -63 120 -160 215 53 -51 3 26 36 0 -28 12 0 46 22 0 43 48 -3 -36 -26 0 -28 24 -215 -54 54 8 blend - hvcurveto - -90 -390 -17 112 1 blend - hlineto + -81 callsubr 2 vsindex - 349 157 731 329 -219 69.90141 34 96 -34 22.23555 2 blend - rmoveto + 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 4 blend - vhcurveto - 8 63 44 89 13.53165 1 blend - hlineto - 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 5 blend - hvcurveto - 17 37 5 19 -6 4.49112 -4 195 4 54.21736 2 blend - rlineto + 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 1 blend - hlineto - -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 0 0 0 -0.15161 5 blend + -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 0 0 0 -0.15161 -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 + 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 4 blend - vhcurveto - -8 -63 -43 -78 -11.8934 1 blend - hlineto - -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 5 blend - hvcurveto - -17 -37 0 -19 1 -5.10217 4 -198 -4 -55.04384 2 blend - rlineto + -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 1 blend - hlineto + 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 2 blend - rmoveto + 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 4 blend - vhcurveto - 5 126 23 93 -36.10632 15.57735 1 blend - hlineto - 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 5 blend - hvcurveto - 39 0 0 221 76 -18.91333 55.7757 0 0 0 0.6738 -0.38344 2 blend - rlineto + 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 1 blend - hlineto - -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 -1 -1 1 -0.28877 0 5 blend + -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 -1 -1 1 -0.28877 0 -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 + 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 4 blend - vhcurveto - -8 0 -83 -26 -227 90.08673 -47.60095 0 0 0 0 0.46121 2 blend - rlineto - -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 5 blend - hvcurveto - -40 0 -240 -66 -8.18893 -5.89154 1 blend - hlineto + -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 1 blend - hlineto - 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 5 blend - hvcurveto + 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 1 blend - hmoveto - 40 700 -40 0 280 100 0 100 0 0 -280 -100 3 blend - hlineto - -170 -36 -340 40 70 0 -214 -60 2 blend - rmoveto + 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 70 67 -41 100 94 -39 4 blend - hvcurveto - 518 -40 -518 -170 -61 80 0 -280 -111 170 11 -30 3 blend - vlineto - -122 -50 -34 -81 -81 -51 34 122 -106 94 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 0 -280 -112 170 61 -80 3 blend - vlineto - -144 64 -48 108 -100 -94 39 117 31 8.45772 -70 -67 41 181 144 -80.45772 4 blend + 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 0 100 0 2 blend - rmoveto - -41 -5 -209 -75 1 blend - hlineto - -130 -700 -371 46 125 0 -100 0 2 blend - rlineto - 36 9 184 51 1 blend - hlineto - -178 700 -356 -88 192 0 100 0 2 blend - rmoveto - -45 -9 -295 -121 1 blend - hlineto - 135 -700 373 -19 -119 0 -100 0 2 blend - rlineto - 40 9 280 121 1 blend - hlineto + 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 3 blend - hlineto + -70 -39 70 10 -200 -160 3 -221 -3 -10 200 160 -105 callsubr - 500 700 824 377 -352 0 100 0 2 blend - rmoveto - -42 1 -218 -119 1 blend - hlineto - -87 -638 6 -210 39 184 0 108 0 6 36 -24 3 blend - 0 -94 638 -38 -211 44 185 0 -108 0 12 -167 -82 3 blend - 0 -95 -638 8 -196 50 173 -10 108 10 9 34 -27 3 blend - 0 -93 638 -43 -217 39 198 10 -108 -10 0 -246 -144 3 blend - 0 107 -700 45 226 -5 -172 0 -100 0 -27 243 181 3 blend - 0 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 + 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 1 blend - hlineto + 45 -28 272 198 -107 callsubr - 337 583 23 -173 1 blend - hmoveto - 45 15 335 95 1 blend - hlineto - -169 364 -141 336 -45 -291 -70 79 5 110 -1 -269 30 81 -5 -10 1 -15 -335 -95 5 blend - 0 160 -363 285 78 -94 14 -87 10 2 blend + 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 - -167 -337 -286 -71 95 -16 -13 -8 2 blend - rmoveto - 40 0 142 332 13 4 155 364 -40 8 190 212 2 0 -2 279 -57 -161 19 -20 -10 -1 220 -106 -6 30 -28 292 27 -13 -13 90 38 -10 -190 -210 9 blend - 0 -130 -337 -16 -6 -287 41 153 5 78 -66 4 -212 89 8 -44 42 4 blend + -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 0 100 0 2 blend - rmoveto - -41 -9 -189 -111 1 blend - hlineto - -154 -490 25 0 -262 -16 127 -10 -110 20 -13 175 93 -29 0 29 4 blend - rlineto - -163 490 -263 -8 69 39 110 -49 2 blend - rmoveto - -47 -3 -302 -78 1 blend - hlineto - 170 -490 38 0 281 30 -106 -39 -110 49 -15 252 115 29 0 -29 4 blend - rlineto - 2 44 9 28 -9 -33 26 133 2 blend - rmoveto + 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 2 blend - rmoveto + 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 2 blend - rmoveto + -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 -100 0 1 blend - vmoveto + -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 0 2 blend - rmoveto - 150 8 40 120 40 0 -8 0 2 blend - 0 32 -150 -10 0 88 0 -40 -120 -40 0 -20 0 3 blend - rlineto + 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 2 blend - rmoveto - 29 0 373 0 1 blend - hlineto + 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 0 1 blend - hlineto - -31 -210 0 -168 0 -500 50 -40 2 blend - rmoveto - 52 -190 50 189 0 356 0 0 -236 0 0 354 0 0 236 0 4 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 2 blend - rmoveto + 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 2 blend - rmoveto - -190 -52 189 -50 0 -236 0 0 -356 0 0 236 0 0 -354 0 4 blend - rlineto + -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 2 blend - rmoveto + 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 2 blend - rmoveto + 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 0 1 blend - hlineto + -29 0 -373 -97 callsubr -6 -269 -500 -66 -40 1 blend rlineto - 41 0 374 0 1 blend - hlineto + 41 0 374 -97 callsubr 31 210 0 168 0 500 -50 40 2 blend rmoveto - -52 190 -50 -189 0 -356 0 0 236 0 0 -354 0 0 -236 0 4 blend - rlineto + -52 190 -50 -189 -75 callsubr + 0 -236 0 -102 callsubr - 111 60 109 -30 1 blend - hmoveto - 120 -50 -120 100 180 -100 0 -140 0 -100 -180 100 3 blend + 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 @@ -1133,25 +1066,22 @@ - 50 730 0 10 0 0 110 0 2 blend - rmoveto + 50 730 0 10 0 0 110 -101 callsubr 40 60 -40 0 150 0 0 65 0 0 -150 0 3 blend hlineto - 4 vsindex - 5 vsindex 50 vmoveto -50 50 vlineto - -50 750 750 750 -750 0 0 -750 2 blend - rlineto + 5 vsindex + -50 750 750 750 -750 0 0 -750 -103 callsubr - 60 60 -30 -30 1 blend - hmoveto - 50 120 -50 0 140 0 100 180 -100 0 -140 0 3 blend + 60 60 -30 -30 -99 callsubr + 50 120 -50 0 140 0 -67 callsubr + 3 blend hlineto @@ -1167,16 +1097,13 @@ - 6 vsindex 7 vsindex 70 278 0 -241 0 1 blend rmoveto - 239 143 0 0 1 blend - hlineto - 0 102 70 0 0 0 70 0 0 -102 0 0 -70 0 0 102 4 blend - rlineto + 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 diff --git a/tests/data/figArnaud.otf.ttx b/tests/data/figArnaud.otf.ttx index ec83bb3..7a24748 100644 --- a/tests/data/figArnaud.otf.ttx +++ b/tests/data/figArnaud.otf.ttx @@ -90,12 +90,12 @@ - + - - + + @@ -465,6 +465,29 @@ + + + + 0 0 0 + + 2 blend + rmoveto + + + -107 callsubr + 0 + + 2 blend + rlineto + + + 16 blend + vhcurveto + + + -30 -105 callsubr + 40 -180 0 100 + @@ -476,57 +499,41 @@ - 1 vsindex - 2 vsindex - 3 vsindex - 4 vsindex - 3 vsindex - 307 162 260 190 0 1 2 blend - rmoveto - 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 16 blend - vhcurveto - -30 -1 0 -170 0 28 2 blend - rmoveto - -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 16 blend - vhcurveto - 15 299 -10 175 0 -39 2 blend - rmoveto - 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 16 blend - vhcurveto - -30 -1 0 -165 0 -34 2 blend - rmoveto - -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 16 blend - vhcurveto + 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 2 blend - rmoveto + 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 2 blend - rmoveto + 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 2 blend - rmoveto + -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 @@ -542,38 +549,43 @@ 2 vsindex 212 20 0 -10 0 0 -50 220 1 blend hmoveto - 28 0 0 0 0 0 162 0 1 blend - 600 -28 0 0 0 0 0 -162 0 1 blend + 28 -105 callsubr + 0 162 0 1 blend + 600 -28 -105 callsubr + 0 -162 0 1 blend hlineto - -197 -455 -30 0 0 0 0 40 -180 0 100 -65 0 0 0 0 2 blend + -197 -455 -102 callsubr + -65 -105 callsubr + 2 blend rmoveto - 297 25 -297 30 0 0 100 0 120 250 0 0 130 0 0 0 0 -30 0 0 -100 0 -120 -250 3 blend + 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 0 0 0 0 0 4 1 blend + 29 181 -105 callsubr + 0 4 1 blend hmoveto - 188 412 -151 0 0 0 -10 -40 176 -341 -100 -64 0 200 -6 3 2 blend - rlineto - 18 -20 341 0 -1 0 -200 6 -3 0 0 0 0 10 0 0 2 blend + 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 -30 0 0 0 0 40 -180 0 100 65 0 0 0 0 2 blend + -197 -430 -102 callsubr + 65 -105 callsubr + 2 blend rlineto 3 vsindex - 279 414 0 280 201 0 -10 -25 2 blend - rmoveto + 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 0 0 -101 0 10 15 2 blend - rlineto - -24 -99 -58 -119 -81 -94 21 -15 0 -4 -31 0 -31 11 -17 -52 25 15 3 76 0 -90 -3 10 -14 3 20 -21 98 -25 -10 -70 8 blend - rcurveline + -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 2 blend - rmoveto - -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 16 blend - vhcurveto + -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 @@ -584,8 +596,7 @@ -18 -18 -10 0 -10 1 2 blend -2 -2 -15 1 0 -10 -1 2 blend hvcurveto - -29 -4 -70 -70 -1 -10 2 blend - rlineto + -29 -4 -70 -70 -1 -10 -104 callsubr -20 75 0 -105 100 40 2 blend vlineto @@ -595,47 +606,40 @@ hmoveto 28 100 0 6 162 1 blend hlineto - 224 580 0 0 220 -40 0 0 0 -100 2 blend - rlineto + 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 2 blend - rmoveto + -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 2 blend - rlineto - 20 -239 0 0 0 100 -100 0 -220 -155 2 blend + 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 2 blend - rmoveto + 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 0 0 101 0 -10 -15 2 blend - rlineto - 24 99 55 99 81 94 -21 15 0 4 31 0 31 -11 20 55 -22 -15 17 -56 0 90 3 -10 14 -3 -20 21 -98 25 10 70 8 blend - rcurveline + 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 2 blend - rmoveto - 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 16 blend - vhcurveto + 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 2 blend - rmoveto + 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 2 blend - rlineto + -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 @@ -644,8 +648,7 @@ 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 2 blend - rlineto + 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 @@ -657,206 +660,172 @@ 1 vsindex - 43 25 10 60 0 66 147 0 90 0 0 125 2 blend - rmoveto - -10 -5 0 -60 0 -20 -140 0 -90 0 0 -25 2 blend - rlineto - -20 257 25 0 0 0 0 -100 0 0 200 223 137 0 90 0 0 125 3 blend + 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 2 blend - rmoveto - 16 -18 0 0 0 0 51 0 0 0 -1 -113 2 blend - rlineto - 35 34 33 11 35 0 0 0 23 -12 0 0 0 27 -10 0 0 0 29 -9 0 0 0 14 4 0 0 0 50 -2 5 blend + -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 0 0 0 51 -21 0 0 0 36 -15 0 0 0 -21 24 0 0 0 -27 33 0 0 0 -27 29 0 0 0 -37 6 0 0 0 -11 23 0 0 0 -36 6 0 0 0 17 32 9 blend + 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 0 0 0 -114 11 0 0 0 69 98 20 0 0 9 172 0 0 0 0 -10 0 0 0 94 -28 0 0 0 -76 -110 6 blend + -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 0 0 0 43 -1 0 0 0 -27 -30 -10 0 0 42 -4 0 0 0 24 10 -14 0 0 31 -7 5 blend + 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 0 0 0 -53 -46 -1 0 0 -49 -32 0 0 0 -30 -29 0 0 0 -14 -12 0 0 0 -22 -6 0 0 0 -26 -14 9 blend + 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 - 5 vsindex - 5 vsindex - 5 vsindex - 5 vsindex - 5 vsindex - 5 vsindex - 5 vsindex - 5 vsindex - 5 vsindex - 5 vsindex - 5 vsindex - 5 vsindex - 5 vsindex - 5 vsindex - 5 vsindex - 5 vsindex - 5 vsindex - 5 vsindex - 5 vsindex - 5 vsindex - 5 vsindex - 5 vsindex - 5 vsindex - 5 vsindex - 5 vsindex - 5 vsindex - 5 vsindex - 5 vsindex - 5 vsindex - 5 vsindex - 5 vsindex - 5 vsindex - 5 vsindex - 5 vsindex - 5 vsindex - 5 vsindex - 5 vsindex - 5 vsindex - 5 vsindex - 5 vsindex - 5 vsindex - 5 vsindex - 5 vsindex - 5 vsindex - 5 vsindex - 5 vsindex - 5 vsindex - 5 vsindex - 5 vsindex - 5 vsindex - 5 vsindex - 5 vsindex - 5 vsindex - 5 vsindex - 5 vsindex - 5 vsindex - 5 vsindex - 5 vsindex - 5 vsindex - 5 vsindex 327 330 190 1 blend @@ -865,8 +834,7 @@ 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 16 blend - vhcurveto + -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 From 30a9b88cff5f6aed9d882e3cec04f66f324e2269 Mon Sep 17 00:00:00 2001 From: Just van Rossum Date: Sat, 13 Jul 2024 07:40:43 +0200 Subject: [PATCH 15/29] Ignore cffsubr for type checking --- pyproject.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index 513e32d..53ecd7a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -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 From bd0fdf9a0ab1d04748a664f8b4eeb7d7eebacc21 Mon Sep 17 00:00:00 2001 From: Just van Rossum Date: Sat, 13 Jul 2024 07:42:22 +0200 Subject: [PATCH 16/29] Fix type annotation --- src/fontra_compile/builder.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fontra_compile/builder.py b/src/fontra_compile/builder.py index 93087e5..dd5ad89 100644 --- a/src/fontra_compile/builder.py +++ b/src/fontra_compile/builder.py @@ -66,7 +66,7 @@ class GlyphInfo: ttGlyph: TTGlyph | None = None gvarVariations: list | None = None charString: Any | None = None - charStringSupports: list | None = None + charStringSupports: tuple | None = None variableComponents: list = field(default_factory=list) localAxisTags: set = field(default_factory=set) model: VariationModel | None = None From 080b14b11b5d9fe86a0e0fcf4695dcace65c6fc0 Mon Sep 17 00:00:00 2001 From: Just van Rossum Date: Sat, 13 Jul 2024 07:51:08 +0200 Subject: [PATCH 17/29] Also test otf export via fontra-workflow --- tests/test_workflow.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/test_workflow.py b/tests/test_workflow.py index c215c1f..ac97c5d 100644 --- a/tests/test_workflow.py +++ b/tests/test_workflow.py @@ -24,6 +24,16 @@ ( """ steps: +- input: fontra-read + source: "tests/data/MutatorSans.fontra" +- output: compile-varc + destination: "output1.otf" +""", + "MutatorSans.otf.ttx", + ), + ( + """ +steps: - input: fontra-read source: "tests/data/MutatorSans.fontra" - output: compile-fontmake From 7f561241c6450e2e4326f2ab3e26ed0753e89535 Mon Sep 17 00:00:00 2001 From: Just van Rossum Date: Sat, 13 Jul 2024 13:47:43 +0200 Subject: [PATCH 18/29] Fold two operations into one func --- src/fontra_compile/builder.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/fontra_compile/builder.py b/src/fontra_compile/builder.py index dd5ad89..95352f7 100644 --- a/src/fontra_compile/builder.py +++ b/src/fontra_compile/builder.py @@ -270,11 +270,8 @@ async def prepareOneGlyph(self, glyphName: str) -> GlyphInfo: glyph, glyphSources, defaultLayerGlyph, model ) else: - charString = buildCharString(glyph, glyphSources, defaultLayerGlyph, model) - charStringSupports = ( - tuple(tuple(sorted(sup.items())) for sup in model.supports[1:]) - if model is not None - else None + charString, charStringSupports = buildCharString( + glyph, glyphSources, defaultLayerGlyph, model ) componentInfo = await self.collectComponentInfo(glyph, defaultSourceIndex) @@ -771,7 +768,13 @@ def buildCharString(glyph, glyphSources, defaultLayerGlyph, model): layerGlyph.path.drawPoints(pointPen) charString = pen.getCharString(var_model=model) - return charString + charStringSupports = ( + tuple(tuple(sorted(sup.items())) for sup in model.supports[1:]) + if model is not None + else None + ) + + return charString, charStringSupports def prepareCFFVarData(charStrings, charStringSupports): From 48b53664390ebc92ca98624d1f4896e0d4758c11 Mon Sep 17 00:00:00 2001 From: Just van Rossum Date: Sat, 13 Jul 2024 14:01:54 +0200 Subject: [PATCH 19/29] Ensure we use a model that has the default source as the first item --- src/fontra_compile/builder.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/fontra_compile/builder.py b/src/fontra_compile/builder.py index 95352f7..60a9385 100644 --- a/src/fontra_compile/builder.py +++ b/src/fontra_compile/builder.py @@ -759,6 +759,13 @@ def buildCharString(glyph, glyphSources, defaultLayerGlyph, model): defaultLayerGlyph.path.drawPoints(PointToSegmentPen(pen)) charString = pen.getCharString() 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) pointPen = PointToSegmentPen(pen) for sourceIndex, source in enumerate(glyphSources): From b87d94b8751023fdaa07b212d173331db061d9aa Mon Sep 17 00:00:00 2001 From: Just van Rossum Date: Sat, 13 Jul 2024 14:16:14 +0200 Subject: [PATCH 20/29] Test that our CFF2CharStringMergePen source order fix is effective --- tests/test_workflow.py | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/tests/test_workflow.py b/tests/test_workflow.py index ac97c5d..f85258d 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 = [ ( """ @@ -33,6 +49,20 @@ ), ( """ +# This test confirms that the order of sources in glyphs is irrelevant. +# In other words, 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", + ), + ( + """ steps: - input: fontra-read source: "tests/data/MutatorSans.fontra" From 24aaaf6311c4aa2a8fd95b07ffc31957d7edfd3c Mon Sep 17 00:00:00 2001 From: Just van Rossum Date: Sat, 13 Jul 2024 14:21:30 +0200 Subject: [PATCH 21/29] Simplify by not repeating condition --- src/fontra_compile/builder.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/fontra_compile/builder.py b/src/fontra_compile/builder.py index 60a9385..b4e2a81 100644 --- a/src/fontra_compile/builder.py +++ b/src/fontra_compile/builder.py @@ -758,6 +758,7 @@ def buildCharString(glyph, glyphSources, defaultLayerGlyph, model): 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 @@ -773,13 +774,11 @@ def buildCharString(glyph, glyphSources, defaultLayerGlyph, model): pen.restart(sourceIndex) layerGlyph = glyph.layers[source.layerName].glyph layerGlyph.path.drawPoints(pointPen) - charString = pen.getCharString(var_model=model) - charStringSupports = ( - tuple(tuple(sorted(sup.items())) for sup in model.supports[1:]) - if model is not None - else None - ) + charString = pen.getCharString(var_model=model) + charStringSupports = tuple( + tuple(sorted(sup.items())) for sup in model.supports[1:] + ) return charString, charStringSupports From 3c73ea199a66812652dc7051a76ee2ccd0fe4e46 Mon Sep 17 00:00:00 2001 From: Just van Rossum Date: Sat, 13 Jul 2024 14:35:49 +0200 Subject: [PATCH 22/29] Also test random glyph source order for ttf output --- tests/test_workflow.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/test_workflow.py b/tests/test_workflow.py index f85258d..a569dc1 100644 --- a/tests/test_workflow.py +++ b/tests/test_workflow.py @@ -56,6 +56,20 @@ async def processGlyph(self, glyph: VariableGlyph) -> VariableGlyph: - 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", + ), + ( + """ +# This test confirms that the order of sources in glyphs is irrelevant. +# In other words, 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" """, From ed34d8c82b99c6f1087ef1ad8077dbd2cef270e0 Mon Sep 17 00:00:00 2001 From: Just van Rossum Date: Sat, 13 Jul 2024 14:37:23 +0200 Subject: [PATCH 23/29] Simplify explainer comment --- tests/test_workflow.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/tests/test_workflow.py b/tests/test_workflow.py index a569dc1..45a7491 100644 --- a/tests/test_workflow.py +++ b/tests/test_workflow.py @@ -49,9 +49,7 @@ async def processGlyph(self, glyph: VariableGlyph) -> VariableGlyph: ), ( """ -# This test confirms that the order of sources in glyphs is irrelevant. -# In other words, check that we produce the same output regardless of glyph -# source order. +# Check that we produce the same output regardless of glyph source order. steps: - input: fontra-read source: "tests/data/MutatorSans.fontra" @@ -63,9 +61,7 @@ async def processGlyph(self, glyph: VariableGlyph) -> VariableGlyph: ), ( """ -# This test confirms that the order of sources in glyphs is irrelevant. -# In other words, check that we produce the same output regardless of glyph -# source order. +# Check that we produce the same output regardless of glyph source order. steps: - input: fontra-read source: "tests/data/MutatorSans.fontra" From f08bf1e5663cb4a4d3c017e7484f35fff8a4396c Mon Sep 17 00:00:00 2001 From: Just van Rossum Date: Sat, 13 Jul 2024 14:47:27 +0200 Subject: [PATCH 24/29] Generalize helper func, because who knows --- src/fontra_compile/builder.py | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/fontra_compile/builder.py b/src/fontra_compile/builder.py index b4e2a81..9225364 100644 --- a/src/fontra_compile/builder.py +++ b/src/fontra_compile/builder.py @@ -484,9 +484,9 @@ async def buildFont(self) -> TTFont: builder.setupHorizontalHeader() builder.setupHorizontalMetrics( - addLSB( - getGlyphInfoAttributes(self.glyphInfos, "leftSideBearing"), + dictZip( getGlyphInfoAttributes(self.glyphInfos, "xAdvance"), + getGlyphInfoAttributes(self.glyphInfos, "leftSideBearing"), ) ) hvarTable = self.buildHVAR(axisTags) @@ -815,13 +815,11 @@ def prepareCFFVarData(charStrings, charStringSupports): return varDataList, regionList -def addLSB( - leftSideBearings: dict[str, int], metrics: dict[str, int] -) -> dict[str, tuple[int, int]]: - return { - glyphName: (xAdvance, leftSideBearings.get(glyphName, 0)) - for glyphName, xAdvance in metrics.items() - } +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]: From 8def733217b6bfd56063fe7698ca1e831f2f70e4 Mon Sep 17 00:00:00 2001 From: Just van Rossum Date: Sun, 14 Jul 2024 10:39:32 +0200 Subject: [PATCH 25/29] Work around fonttools issue with PointToSegmentPen --- src/fontra_compile/builder.py | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/fontra_compile/builder.py b/src/fontra_compile/builder.py index 9225364..02658bc 100644 --- a/src/fontra_compile/builder.py +++ b/src/fontra_compile/builder.py @@ -14,6 +14,7 @@ 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 @@ -768,12 +769,11 @@ def buildCharString(glyph, glyphSources, defaultLayerGlyph, model): assert model.reverseMapping[0] == 0 pen = CFF2CharStringMergePen([], glyph.name, len(glyphSources), 0) - pointPen = PointToSegmentPen(pen) for sourceIndex, source in enumerate(glyphSources): if sourceIndex: pen.restart(sourceIndex) layerGlyph = glyph.layers[source.layerName].glyph - layerGlyph.path.drawPoints(pointPen) + drawPathToSegmentPen(layerGlyph.path, pen) charString = pen.getCharString(var_model=model) charStringSupports = tuple( @@ -921,3 +921,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() From e06ad24da3986f8a4cdf8f32b70889d06379c347 Mon Sep 17 00:00:00 2001 From: Just van Rossum Date: Mon, 15 Jul 2024 10:27:31 +0200 Subject: [PATCH 26/29] Add tiny subset of Noto Sans CJK VarCo to test edge case in otf export --- .../data/notosanscjksc.fontra/font-data.json | 99 + .../data/notosanscjksc.fontra/glyph-info.csv | 12 + .../glyphs/T_4EBA_2FF1^PP.json | 225 + .../glyphs/VG_31CF_00^33.json | 1394 ++++++ .../glyphs/VG_4E00_00^J.json | 138 + .../glyphs/VG_4E28_00^J.json | 224 + .../glyphs/VG_4E3F_01^J2.json | 2197 ++++++++ .../glyphs/VG_531A_00^32.json | 1033 ++++ .../glyphs/VG_53E3_00^31.json | 1459 ++++++ .../glyphs/VG_65E5_00^31.json | 657 +++ .../glyphs/VG_7530_00^3.json | 921 ++++ .../notosanscjksc.fontra/glyphs/uni3479.json | 149 + .../glyphs/uni531A^02.json | 70 + tests/data/notosanscjksc.otf.ttx | 4460 +++++++++++++++++ tests/test_workflow.py | 10 + 15 files changed, 13048 insertions(+) create mode 100644 tests/data/notosanscjksc.fontra/font-data.json create mode 100644 tests/data/notosanscjksc.fontra/glyph-info.csv create mode 100644 tests/data/notosanscjksc.fontra/glyphs/T_4EBA_2FF1^PP.json create mode 100644 tests/data/notosanscjksc.fontra/glyphs/VG_31CF_00^33.json create mode 100644 tests/data/notosanscjksc.fontra/glyphs/VG_4E00_00^J.json create mode 100644 tests/data/notosanscjksc.fontra/glyphs/VG_4E28_00^J.json create mode 100644 tests/data/notosanscjksc.fontra/glyphs/VG_4E3F_01^J2.json create mode 100644 tests/data/notosanscjksc.fontra/glyphs/VG_531A_00^32.json create mode 100644 tests/data/notosanscjksc.fontra/glyphs/VG_53E3_00^31.json create mode 100644 tests/data/notosanscjksc.fontra/glyphs/VG_65E5_00^31.json create mode 100644 tests/data/notosanscjksc.fontra/glyphs/VG_7530_00^3.json create mode 100644 tests/data/notosanscjksc.fontra/glyphs/uni3479.json create mode 100644 tests/data/notosanscjksc.fontra/glyphs/uni531A^02.json create mode 100644 tests/data/notosanscjksc.otf.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_workflow.py b/tests/test_workflow.py index 45a7491..266c1bb 100644 --- a/tests/test_workflow.py +++ b/tests/test_workflow.py @@ -74,6 +74,16 @@ async def processGlyph(self, glyph: VariableGlyph) -> VariableGlyph: ( """ steps: +- input: fontra-read + source: "tests/data/notosanscjksc.fontra" +- output: compile-varc + destination: "output.otf" +""", + "notosanscjksc.otf.ttx", + ), + ( + """ +steps: - input: fontra-read source: "tests/data/MutatorSans.fontra" - output: compile-fontmake From 8bbb973a6044e0b1c760921ee8a756ad4247b39d Mon Sep 17 00:00:00 2001 From: Just van Rossum Date: Mon, 15 Jul 2024 10:51:14 +0200 Subject: [PATCH 27/29] Explain the need for this test case --- tests/test_workflow.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/test_workflow.py b/tests/test_workflow.py index 266c1bb..5994cd3 100644 --- a/tests/test_workflow.py +++ b/tests/test_workflow.py @@ -73,6 +73,11 @@ async def processGlyph(self, glyph: VariableGlyph) -> VariableGlyph: ), ( """ +# 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" From a82fae459f73e0b99c688ef678fc753f61eac09c Mon Sep 17 00:00:00 2001 From: Just van Rossum Date: Mon, 15 Jul 2024 10:58:48 +0200 Subject: [PATCH 28/29] Factor out computation of LSB --- src/fontra_compile/builder.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/fontra_compile/builder.py b/src/fontra_compile/builder.py index 02658bc..e5a484b 100644 --- a/src/fontra_compile/builder.py +++ b/src/fontra_compile/builder.py @@ -3,7 +3,7 @@ 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 @@ -277,9 +277,7 @@ async def prepareOneGlyph(self, glyphName: str) -> GlyphInfo: componentInfo = await self.collectComponentInfo(glyph, defaultSourceIndex) - boundsPen = (BoundsPen if self.buildCFF2 else ControlBoundsPen)(None) - defaultLayerGlyph.path.drawPoints(PointToSegmentPen(boundsPen)) - leftSideBearing = boundsPen.bounds[0] if boundsPen.bounds is not None else 0 + leftSideBearing = computeLeftSideBearing(defaultLayerGlyph.path, self.buildCFF2) return GlyphInfo( ttGlyph=ttGlyph, @@ -783,6 +781,12 @@ def buildCharString(glyph, glyphSources, defaultLayerGlyph, model): return charString, charStringSupports +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 prepareCFFVarData(charStrings, charStringSupports): vsindexMap = {} for supports in charStringSupports.values(): From a9e9bcc2e5c3bc2f9a44810777de7d6c7054484f Mon Sep 17 00:00:00 2001 From: Just van Rossum Date: Mon, 15 Jul 2024 11:00:52 +0200 Subject: [PATCH 29/29] Move helper func --- src/fontra_compile/builder.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/fontra_compile/builder.py b/src/fontra_compile/builder.py index e5a484b..67a9202 100644 --- a/src/fontra_compile/builder.py +++ b/src/fontra_compile/builder.py @@ -702,6 +702,12 @@ 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) @@ -781,12 +787,6 @@ def buildCharString(glyph, glyphSources, defaultLayerGlyph, model): return charString, charStringSupports -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 prepareCFFVarData(charStrings, charStringSupports): vsindexMap = {} for supports in charStringSupports.values():