Skip to content

Commit

Permalink
Merge pull request #167 from googlefonts/axis-refactor
Browse files Browse the repository at this point in the history
Adapt to new Axes API
  • Loading branch information
justvanrossum authored Apr 14, 2024
2 parents 1d4fa34 + c823f11 commit 95f36af
Show file tree
Hide file tree
Showing 6 changed files with 58 additions and 62 deletions.
19 changes: 6 additions & 13 deletions src/fontra_rcjk/backend_fs.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,7 @@

from fontra.backends.filewatcher import Change, FileWatcher
from fontra.backends.ufo_utils import extractGlyphNameAndCodePoints
from fontra.core.classes import (
Font,
FontInfo,
GlobalAxis,
GlobalDiscreteAxis,
GlobalSource,
VariableGlyph,
)
from fontra.core.classes import Axes, Font, FontInfo, FontSource, VariableGlyph
from fontra.core.instancer import mapLocationFromUserToSource
from fontra.core.protocols import WritableFontBackend
from fontTools.ufoLib.filenames import userNameToFileName
Expand Down Expand Up @@ -119,7 +112,7 @@ def getGlyphSetForGlyph(self, glyphName):

@cached_property
def _defaultLocation(self):
axes = self.designspace.axes
axes = self.designspace.axes.axes
userLoc = {axis.name: axis.defaultValue for axis in axes}
return mapLocationFromUserToSource(userLoc, axes)

Expand All @@ -136,17 +129,17 @@ async def putFontInfo(self, fontInfo: FontInfo):
self.designspace.fontInfo = deepcopy(fontInfo)
self._writeDesignspace()

async def getSources(self) -> dict[str, GlobalSource]:
async def getSources(self) -> dict[str, FontSource]:
return deepcopy(self.designspace.sources)

async def putSources(self, sources: dict[str, GlobalSource]) -> None:
async def putSources(self, sources: dict[str, FontSource]) -> None:
self.designspace.sources = deepcopy(sources)
self._writeDesignspace()

async def getGlobalAxes(self) -> list[GlobalAxis | GlobalDiscreteAxis]:
async def getAxes(self) -> Axes:
return deepcopy(self.designspace.axes)

async def putGlobalAxes(self, axes: list[GlobalAxis | GlobalDiscreteAxis]) -> None:
async def putAxes(self, axes: Axes) -> None:
self.designspace.axes = deepcopy(axes)
if hasattr(self, "_defaultLocation"):
del self._defaultLocation
Expand Down
21 changes: 11 additions & 10 deletions src/fontra_rcjk/backend_mysql.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,10 @@
from typing import Any, Awaitable, Callable

from fontra.core.classes import (
Axes,
Font,
FontInfo,
GlobalAxis,
GlobalDiscreteAxis,
GlobalSource,
FontSource,
VariableGlyph,
structure,
unstructure,
Expand Down Expand Up @@ -143,8 +142,10 @@ async def _getDesignspace(self) -> Font:
return designspace

def _updateDefaultLocation(self, designspace):
userLoc = {axis.name: axis.defaultValue for axis in designspace.axes}
self._defaultLocation = mapLocationFromUserToSource(userLoc, designspace.axes)
userLoc = {axis.name: axis.defaultValue for axis in designspace.axes.axes}
self._defaultLocation = mapLocationFromUserToSource(
userLoc, designspace.axes.axes
)

async def getFontInfo(self) -> FontInfo:
designspace = await self._getDesignspace()
Expand All @@ -155,20 +156,20 @@ async def putFontInfo(self, fontInfo: FontInfo):
designspace.fontInfo = deepcopy(fontInfo)
await self._writeDesignspace(designspace)

async def getSources(self) -> dict[str, GlobalSource]:
async def getSources(self) -> dict[str, FontSource]:
designspace = await self._getDesignspace()
return deepcopy(designspace.sources)

async def putSources(self, sources: dict[str, GlobalSource]) -> None:
async def putSources(self, sources: dict[str, FontSource]) -> None:
designspace = await self._getDesignspace()
designspace.sources = deepcopy(sources)
await self._writeDesignspace(designspace)

async def getGlobalAxes(self) -> list[GlobalAxis | GlobalDiscreteAxis]:
async def getAxes(self) -> Axes:
designspace = await self._getDesignspace()
return deepcopy(designspace.axes)

async def putGlobalAxes(self, axes: list[GlobalAxis | GlobalDiscreteAxis]) -> None:
async def putAxes(self, axes: Axes) -> None:
designspace = await self._getDesignspace()
designspace.axes = deepcopy(axes)
self._updateDefaultLocation(designspace)
Expand All @@ -181,7 +182,7 @@ async def _writeDesignspace(self, designspace) -> None:

async def getDefaultLocation(self) -> dict[str, float]:
if self._defaultLocation is None:
_ = await self.getGlobalAxes()
_ = await self.getAxes()
assert self._defaultLocation is not None
return self._defaultLocation

Expand Down
29 changes: 14 additions & 15 deletions src/fontra_rcjk/base.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
import asyncio
import hashlib
from copy import deepcopy
from dataclasses import asdict
from functools import cached_property
from typing import Any, Union

from fontra.backends.designspace import cleanupTransform
from fontra.core.classes import (
Component,
DiscreteFontAxis,
Font,
GlobalAxis,
GlobalDiscreteAxis,
FontAxis,
GlyphAxis,
GlyphSource,
Layer,
LocalAxis,
Source,
StaticGlyph,
VariableGlyph,
structure,
Expand Down Expand Up @@ -117,7 +116,7 @@ def cleanupAxis(axisDict):
axisDict["minValue"] = minValue
axisDict["defaultValue"] = defaultValue
axisDict["maxValue"] = maxValue
return LocalAxis(**axisDict)
return GlyphAxis(**axisDict)


def buildVariableGlyphFromLayerGlyphs(layerGlyphs) -> VariableGlyph:
Expand All @@ -138,7 +137,7 @@ def buildVariableGlyphFromLayerGlyphs(layerGlyphs) -> VariableGlyph:
dcNames = [c.name for c in defaultComponents]

sources = [
Source(
GlyphSource(
name="<default>",
layerName="foreground",
customData={FONTRA_STATUS_KEY: defaultGlyph.lib.get("robocjk.status", 0)},
Expand Down Expand Up @@ -205,7 +204,7 @@ def buildVariableGlyphFromLayerGlyphs(layerGlyphs) -> VariableGlyph:
k: float(v) if isinstance(v, str) else v for k, v in location.items()
}
sources.append(
Source(
GlyphSource(
name=sourceName,
location=location,
layerName=fontraLayerNameMapping.get(layerName, layerName),
Expand Down Expand Up @@ -293,7 +292,7 @@ def buildLayerGlyphsFromVariableGlyph(
defaultGlyph = layerGlyphs["foreground"]

if glyph.axes:
defaultGlyph.lib["robocjk.axes"] = [asdict(axis) for axis in glyph.axes]
defaultGlyph.lib["robocjk.axes"] = [unstructure(axis) for axis in glyph.axes]
else:
defaultGlyph.lib.pop("robocjk.axes", None)

Expand Down Expand Up @@ -490,10 +489,10 @@ def makeSafeLayerName(layerName):


def structureDesignspaceData(designspaceData: dict[str, Any]) -> Font:
designspaceData = {
**designspaceData,
"axes": updateAxes(designspaceData.get("axes", [])),
}
if isinstance(designspaceData.get("axes"), list):
# old format
designspaceData = deepcopy(designspaceData)
designspaceData["axes"] = updateAxes(designspaceData["axes"])
return structure(designspaceData, Font)


Expand All @@ -514,9 +513,9 @@ def unpackAxes(dsAxes):

def _unpackDSAxis(dsAxis):
if "label" in dsAxis:
return structure(dsAxis, Union[GlobalAxis, GlobalDiscreteAxis])
return structure(dsAxis, Union[FontAxis, DiscreteFontAxis])
# Legacy rcjk ds data
return GlobalAxis(
return FontAxis(
label=dsAxis["name"],
name=dsAxis["tag"],
tag=dsAxis["tag"],
Expand Down
6 changes: 3 additions & 3 deletions tests/data/figArnaud.rcjk/characterGlyph/uni0030.glif
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@
<array>
<dict>
<key>defaultValue</key>
<real>0.0</real>
<integer>0</integer>
<key>maxValue</key>
<real>1.0</real>
<integer>1</integer>
<key>minValue</key>
<real>0.0</real>
<integer>0</integer>
<key>name</key>
<string>wght</string>
</dict>
Expand Down
2 changes: 1 addition & 1 deletion tests/test_copy.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ async def test_copy_font(tmpdir):
assert glyphMap == await dupedFont.getGlyphMap()
assert await srcFont.getFontInfo() == await dupedFont.getFontInfo()
assert await srcFont.getSources() == await dupedFont.getSources()
assert await srcFont.getGlobalAxes() == await dupedFont.getGlobalAxes()
assert await srcFont.getAxes() == await dupedFont.getAxes()
assert await srcFont.getCustomData() == await dupedFont.getCustomData()
for glyphName in glyphMap:
assert await srcFont.getGlyph(glyphName) == await dupedFont.getGlyph(
Expand Down
43 changes: 23 additions & 20 deletions tests/test_font.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@

import pytest
from fontra.core.classes import (
GlobalAxis,
Axes,
FontAxis,
GlyphAxis,
GlyphSource,
Layer,
LocalAxis,
PackedPath,
Source,
StaticGlyph,
VariableGlyph,
structure,
Expand Down Expand Up @@ -415,25 +416,27 @@ async def test_getGlyphUnknownGlyph():
getGlobalAxesTestData = [
(
"rcjk",
[
GlobalAxis(
label="Weight",
name="wght",
tag="wght",
minValue=400,
defaultValue=400,
maxValue=700,
),
],
Axes(
axes=[
FontAxis(
label="Weight",
name="wght",
tag="wght",
minValue=400,
defaultValue=400,
maxValue=700,
),
]
),
),
]


@pytest.mark.asyncio
@pytest.mark.parametrize("backendName, expectedGlobalAxes", getGlobalAxesTestData)
async def test_getGlobalAxes(backendName, expectedGlobalAxes):
async def test_getAxes(backendName, expectedGlobalAxes):
font = getTestFont(backendName)
globalAxes = await font.getGlobalAxes()
globalAxes = await font.getAxes()
assert expectedGlobalAxes == globalAxes


Expand Down Expand Up @@ -674,10 +677,10 @@ async def test_new_glyph(writableTestFont):
async with contextlib.aclosing(writableTestFont):
glyph = VariableGlyph(
name="b",
axes=[LocalAxis(name="wght", minValue=100, defaultValue=400, maxValue=700)],
axes=[GlyphAxis(name="wght", minValue=100, defaultValue=400, maxValue=700)],
sources=[
Source(name="default", layerName="default"),
Source(name="bold", layerName="bold"),
GlyphSource(name="default", layerName="default"),
GlyphSource(name="bold", layerName="bold"),
],
layers={
"default": Layer(glyph=StaticGlyph(path=makeTestPath())),
Expand All @@ -701,7 +704,7 @@ async def test_add_new_layer(writableTestFont):
layerPath = writableTestFont.path / "characterGlyph" / newLayerName
assert not layerPath.exists()

glyph.sources.append(Source(name=newLayerName, layerName=newLayerName))
glyph.sources.append(GlyphSource(name=newLayerName, layerName=newLayerName))
glyph.layers[newLayerName] = Layer(
glyph=StaticGlyph(xAdvance=500, path=makeTestPath())
)
Expand Down Expand Up @@ -817,7 +820,7 @@ async def test_bad_layer_name(writableTestFont):
layerPath = writableTestFont.path / "characterGlyph" / safeLayerName
assert not layerPath.exists()

glyph.sources.append(Source(name=badLayerName, layerName=badLayerName))
glyph.sources.append(GlyphSource(name=badLayerName, layerName=badLayerName))
glyph.layers[badLayerName] = Layer(
glyph=StaticGlyph(xAdvance=500, path=makeTestPath())
)
Expand Down

0 comments on commit 95f36af

Please sign in to comment.