Skip to content

Commit

Permalink
Merge pull request #170 from googlefonts/new-shadow-axis-behavior
Browse files Browse the repository at this point in the history
Upconvert legacy glyph data, to adapt to new "shadow axis" behavior
  • Loading branch information
justvanrossum authored Apr 16, 2024
2 parents 421eac6 + f1a88ad commit f2f837d
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 22 deletions.
4 changes: 3 additions & 1 deletion src/fontra_rcjk/backend_fs.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
5 changes: 4 additions & 1 deletion src/fontra_rcjk/backend_mysql.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
47 changes: 45 additions & 2 deletions src/fontra_rcjk/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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 = []
Expand Down Expand Up @@ -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


Expand Down
2 changes: 2 additions & 0 deletions tests/data/figArnaud.rcjk/characterGlyph/a.glif
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ some note
</outline>
<lib>
<dict>
<key>robocjk.localAxes.behavior.2024</key>
<true/>
<key>robocjk.status</key>
<integer>0</integer>
<key>robocjk.variationGlyphs</key>
Expand Down
17 changes: 3 additions & 14 deletions tests/data/figArnaud.rcjk/characterGlyph/uni0030.glif
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,6 @@
<dict>
<key>public.markColor</key>
<string>1,0,0,1</string>
<key>robocjk.axes</key>
<array>
<dict>
<key>defaultValue</key>
<integer>0</integer>
<key>maxValue</key>
<integer>1</integer>
<key>minValue</key>
<integer>0</integer>
<key>name</key>
<string>wght</string>
</dict>
</array>
<key>robocjk.deepComponents</key>
<array>
<dict>
Expand Down Expand Up @@ -55,6 +42,8 @@
</dict>
</dict>
</array>
<key>robocjk.localAxes.behavior.2024</key>
<true/>
<key>robocjk.status</key>
<integer>0</integer>
<key>robocjk.variationGlyphs</key>
Expand Down Expand Up @@ -96,7 +85,7 @@
<key>location</key>
<dict>
<key>wght</key>
<real>1.0</real>
<real>700.0</real>
</dict>
<key>on</key>
<true/>
Expand Down
20 changes: 16 additions & 4 deletions tests/test_font.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,9 +154,7 @@
(
"rcjk",
{
"axes": [
{"defaultValue": 0.0, "maxValue": 1.0, "minValue": 0.0, "name": "wght"}
],
"axes": [],
"name": "uni0031",
"sources": [
{
Expand All @@ -167,7 +165,7 @@
},
{
"name": "wght",
"location": {"wght": 1.0},
"location": {"wght": 700},
"layerName": "wght",
"customData": {"fontra.development.status": 0},
},
Expand Down Expand Up @@ -482,6 +480,8 @@ def writableTestFont(tmpdir):
" </outline>",
" <lib>",
" <dict>",
" <key>robocjk.localAxes.behavior.2024</key>",
" <true/>",
" <key>robocjk.status</key>",
" <integer>0</integer>",
" <key>robocjk.variationGlyphs</key>",
Expand Down Expand Up @@ -527,6 +527,8 @@ def writableTestFont(tmpdir):
" </outline>",
" <lib>",
" <dict>",
" <key>robocjk.localAxes.behavior.2024</key>",
" <true/>",
" <key>robocjk.status</key>",
" <integer>0</integer>",
" <key>robocjk.variationGlyphs</key>",
Expand Down Expand Up @@ -592,6 +594,8 @@ async def test_putGlyph(writableTestFont):
" </outline>",
" <lib>",
" <dict>",
" <key>robocjk.localAxes.behavior.2024</key>",
" <true/>",
" <key>robocjk.status</key>",
" <integer>0</integer>",
" <key>xyz.fontra.something.nothing</key>",
Expand Down Expand Up @@ -644,6 +648,8 @@ async def test_delete_source_layer(writableTestFont):
" <string>wght</string>",
" </dict>",
" </array>",
" <key>robocjk.localAxes.behavior.2024</key>",
" <true/>",
" <key>robocjk.status</key>",
" <integer>0</integer>",
" <key>robocjk.variationGlyphs</key>",
Expand Down Expand Up @@ -752,6 +758,8 @@ async def test_write_roundtrip(writableTestFont, glyphName):
" </outline>",
" <lib>",
" <dict>",
" <key>robocjk.localAxes.behavior.2024</key>",
" <true/>",
" <key>robocjk.status</key>",
" <integer>0</integer>",
" <key>robocjk.variationGlyphs</key>",
Expand Down Expand Up @@ -850,6 +858,8 @@ async def test_bad_layer_name(writableTestFont):
" <dict>",
" <key>public.markColor</key>",
" <string>1,0,0,1</string>",
" <key>robocjk.localAxes.behavior.2024</key>",
" <true/>",
" <key>robocjk.status</key>",
" <integer>0</integer>",
" <key>xyz.fontra.test</key>",
Expand Down Expand Up @@ -977,6 +987,8 @@ async def test_readMixClassicAndVariableComponents():
" </dict>",
" </dict>",
" </array>",
" <key>robocjk.localAxes.behavior.2024</key>",
" <true/>",
" <key>robocjk.status</key>",
" <integer>0</integer>",
" </dict>",
Expand Down

0 comments on commit f2f837d

Please sign in to comment.