diff --git a/src/fontra_rcjk/backend_fs.py b/src/fontra_rcjk/backend_fs.py index 4221bcb..b5108b2 100644 --- a/src/fontra_rcjk/backend_fs.py +++ b/src/fontra_rcjk/backend_fs.py @@ -164,7 +164,9 @@ async def getGlyph(self, glyphName: str) -> VariableGlyph | None: layerGlyphs = self._getLayerGlyphs(glyphName) except KeyError: return None - return buildVariableGlyphFromLayerGlyphs(layerGlyphs) + return buildVariableGlyphFromLayerGlyphs( + layerGlyphs, self.designspace.axes.axes + ) def _getLayerGlyphs(self, glyphName): layerGlyphs = self._tempGlyphCache.get(glyphName) diff --git a/src/fontra_rcjk/backend_mysql.py b/src/fontra_rcjk/backend_mysql.py index dc555c4..04b1b25 100644 --- a/src/fontra_rcjk/backend_mysql.py +++ b/src/fontra_rcjk/backend_mysql.py @@ -256,8 +256,11 @@ async def getGlyph(self, glyphName: str) -> VariableGlyph | None: return None glyph = self._readGlyphFromCacheDir(glyphName) if glyph is None: + designspace = await self._getDesignspace() layerGlyphs = await self._getLayerGlyphs(glyphName) - glyph = buildVariableGlyphFromLayerGlyphs(layerGlyphs) + glyph = buildVariableGlyphFromLayerGlyphs( + layerGlyphs, designspace.axes.axes + ) self._writeGlyphToCacheDir(glyphName, glyph) return glyph diff --git a/src/fontra_rcjk/base.py b/src/fontra_rcjk/base.py index 1422372..0f62dff 100644 --- a/src/fontra_rcjk/base.py +++ b/src/fontra_rcjk/base.py @@ -22,6 +22,7 @@ from fontTools.misc.transform import DecomposedTransform from fontTools.ufoLib.filenames import illegalCharacters from fontTools.ufoLib.glifLib import readGlyphFromString, writeGlyphToString +from fontTools.varLib.models import piecewiseLinearMap FONTRA_STATUS_KEY = "fontra.development.status" @@ -119,7 +120,7 @@ def cleanupAxis(axisDict): return GlyphAxis(**axisDict) -def buildVariableGlyphFromLayerGlyphs(layerGlyphs) -> VariableGlyph: +def buildVariableGlyphFromLayerGlyphs(layerGlyphs, fontAxes) -> VariableGlyph: layers = { layerName: Layer(glyph=glyph.toStaticGlyph()) for layerName, glyph in layerGlyphs.items() @@ -219,13 +220,52 @@ def buildVariableGlyphFromLayerGlyphs(layerGlyphs) -> VariableGlyph: for layerName, layer in layers.items() } - return VariableGlyph( + glyph = VariableGlyph( name=defaultGlyph.name, axes=defaultGlyph.axes, sources=sources, layers=layers, ) + if not defaultGlyph.lib.get("robocjk.localAxes.behavior.2024", False): + upconvertShadowAxes(glyph, fontAxes) + + return glyph + + +def upconvertShadowAxes(glyph, fontAxes): + fontAxisNames = {axis.name for axis in fontAxes} + glyphAxisNames = {axis.name for axis in glyph.axes} + if fontAxisNames.isdisjoint(glyphAxisNames): + return + + glyphAxesByName = {axis.name: axis for axis in glyph.axes} + + for fontAxis in fontAxes: + axisName = fontAxis.name + fontAxisTuple = (fontAxis.minValue, fontAxis.defaultValue, fontAxis.maxValue) + if fontAxis.mapping: + mapping = dict(fontAxis.mapping) + fontAxisTuple = tuple(piecewiseLinearMap(v, mapping) for v in fontAxisTuple) + + glyphAxis = glyphAxesByName.get(axisName) + if glyphAxis is None: + continue + + mapping = dict( + zip( + [glyphAxis.minValue, glyphAxis.defaultValue, glyphAxis.maxValue], + fontAxisTuple, + ) + ) + + for source in glyph.sources: + v = source.location.get(axisName) + if v is not None: + source.location[axisName] = piecewiseLinearMap(v, mapping) + + glyph.axes = [axis for axis in glyph.axes if axis.name not in fontAxisNames] + def buildVariableComponentsFromLibComponents(deepComponents, dcNames): components = [] @@ -359,6 +399,9 @@ def buildLayerGlyphsFromVariableGlyph( # Get rid of legacy data defaultGlyph.lib.pop("fontra.layerNames", None) + # Mark that we shouldn't try to upconvert shadow axes + defaultGlyph.lib["robocjk.localAxes.behavior.2024"] = True + return layerGlyphs diff --git a/tests/data/figArnaud.rcjk/characterGlyph/a.glif b/tests/data/figArnaud.rcjk/characterGlyph/a.glif index 7ffd2f8..12e54e3 100644 --- a/tests/data/figArnaud.rcjk/characterGlyph/a.glif +++ b/tests/data/figArnaud.rcjk/characterGlyph/a.glif @@ -15,6 +15,8 @@ some note + robocjk.localAxes.behavior.2024 + robocjk.status 0 robocjk.variationGlyphs diff --git a/tests/data/figArnaud.rcjk/characterGlyph/uni0030.glif b/tests/data/figArnaud.rcjk/characterGlyph/uni0030.glif index 734ab1f..af42200 100644 --- a/tests/data/figArnaud.rcjk/characterGlyph/uni0030.glif +++ b/tests/data/figArnaud.rcjk/characterGlyph/uni0030.glif @@ -11,19 +11,6 @@ public.markColor 1,0,0,1 - robocjk.axes - - - defaultValue - 0 - maxValue - 1 - minValue - 0 - name - wght - - robocjk.deepComponents @@ -55,6 +42,8 @@ + robocjk.localAxes.behavior.2024 + robocjk.status 0 robocjk.variationGlyphs @@ -96,7 +85,7 @@ location wght - 1.0 + 700.0 on diff --git a/tests/test_font.py b/tests/test_font.py index 7c09821..ed29975 100644 --- a/tests/test_font.py +++ b/tests/test_font.py @@ -154,9 +154,7 @@ ( "rcjk", { - "axes": [ - {"defaultValue": 0.0, "maxValue": 1.0, "minValue": 0.0, "name": "wght"} - ], + "axes": [], "name": "uni0031", "sources": [ { @@ -167,7 +165,7 @@ }, { "name": "wght", - "location": {"wght": 1.0}, + "location": {"wght": 700}, "layerName": "wght", "customData": {"fontra.development.status": 0}, }, @@ -482,6 +480,8 @@ def writableTestFont(tmpdir): " ", " ", " ", + " robocjk.localAxes.behavior.2024", + " ", " robocjk.status", " 0", " robocjk.variationGlyphs", @@ -527,6 +527,8 @@ def writableTestFont(tmpdir): " ", " ", " ", + " robocjk.localAxes.behavior.2024", + " ", " robocjk.status", " 0", " robocjk.variationGlyphs", @@ -592,6 +594,8 @@ async def test_putGlyph(writableTestFont): " ", " ", " ", + " robocjk.localAxes.behavior.2024", + " ", " robocjk.status", " 0", " xyz.fontra.something.nothing", @@ -644,6 +648,8 @@ async def test_delete_source_layer(writableTestFont): " wght", " ", " ", + " robocjk.localAxes.behavior.2024", + " ", " robocjk.status", " 0", " robocjk.variationGlyphs", @@ -752,6 +758,8 @@ async def test_write_roundtrip(writableTestFont, glyphName): " ", " ", " ", + " robocjk.localAxes.behavior.2024", + " ", " robocjk.status", " 0", " robocjk.variationGlyphs", @@ -850,6 +858,8 @@ async def test_bad_layer_name(writableTestFont): " ", " public.markColor", " 1,0,0,1", + " robocjk.localAxes.behavior.2024", + " ", " robocjk.status", " 0", " xyz.fontra.test", @@ -977,6 +987,8 @@ async def test_readMixClassicAndVariableComponents(): " ", " ", " ", + " robocjk.localAxes.behavior.2024", + " ", " robocjk.status", " 0", " ",