diff --git a/src/fontra_glyphs/backend.py b/src/fontra_glyphs/backend.py index 361be45..a94794f 100644 --- a/src/fontra_glyphs/backend.py +++ b/src/fontra_glyphs/backend.py @@ -790,7 +790,7 @@ def variableGlyphToGSGlyph(variableGlyph, gsGlyph): ] gsLayer.attributes["coordinates"] = gsLocation - associatedMasterId = getAssociatedMasterId(gsGlyph, gsLocation) + associatedMasterId = getAssociatedMasterId(gsGlyph.parent, gsLocation) if associatedMasterId: gsLayer.associatedMasterId = associatedMasterId diff --git a/src/fontra_glyphs/utils.py b/src/fontra_glyphs/utils.py index 1ad45c2..16f0bd4 100644 --- a/src/fontra_glyphs/utils.py +++ b/src/fontra_glyphs/utils.py @@ -22,12 +22,11 @@ def getLocationFromSources(sources, layerName): return {k.lower(): v for k, v in s.location.items()} -def getAssociatedMasterId(gsGlyph, gsLocation): +def getAssociatedMasterId(gsFont, gsLocation): # Best guess for associatedMasterId - closestMaster = None + closestMasterID = gsFont.masters[0].id # default first master. closestDistance = float("inf") - for gsLayer in gsGlyph.layers: - gsMaster = gsLayer.master + for gsMaster in gsFont.masters: distance = sum( abs(gsMaster.axes[i] - gsLocation[i]) for i in range(len(gsMaster.axes)) @@ -35,8 +34,9 @@ def getAssociatedMasterId(gsGlyph, gsLocation): ) if distance < closestDistance: closestDistance = distance - closestMaster = gsMaster - return closestMaster.id if closestMaster else None + closestMasterID = gsMaster.id + + return closestMasterID def gsFormatting(content): diff --git a/tests/test_utils.py b/tests/test_utils.py index 339a8d8..aa0bcbd 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -1,8 +1,8 @@ import pathlib -import glyphsLib import pytest from fontra.backends import getFileSystemBackend +from glyphsLib.classes import GSAxis, GSFont, GSFontMaster, GSGlyph, GSLayer from fontra_glyphs.utils import ( getAssociatedMasterId, @@ -22,9 +22,54 @@ def testFont(request): return getFileSystemBackend(request.param) -@pytest.fixture(scope="module", params=[glyphs2Path, glyphs3Path, glyphsPackagePath]) -def testGSFont(request): - return glyphsLib.GSFont(request.param) +def createGSFontMaster(axes=[100, 100], id="DUMMY-MASTER-ID"): + master = GSFontMaster() + master.axes = axes + master.id = id + return master + + +def createGSGlyph(name="GlyphName", unicodes=[], layers=[]): + glyph = GSGlyph() + glyph.name = name + glyph.unicodes = unicodes + glyph.layers = layers + return glyph + + +@pytest.fixture(scope="module") +def testGSFontWW(): + gsFont = GSFont() + gsFont.format_version = 3 + gsFont.axes = [ + GSAxis(name="Optical Size", tag="opsz"), + GSAxis(name="Weight", tag="wght"), + GSAxis(name="Width", tag="wdth"), + ] + gsFont.masters = [ + createGSFontMaster(axes=[12, 50, 100], id="MasterID-TextCondLight"), + createGSFontMaster(axes=[12, 50, 400], id="MasterID-TextCondRegular"), + createGSFontMaster(axes=[12, 50, 900], id="MasterID-TextCondBold"), + createGSFontMaster(axes=[12, 200, 100], id="MasterID-TextWideLight"), + createGSFontMaster(axes=[12, 200, 400], id="MasterID-TextWideRegular"), + createGSFontMaster(axes=[12, 200, 900], id="MasterID-TextWideBold"), + createGSFontMaster(axes=[60, 50, 100], id="MasterID-PosterCondLight"), + createGSFontMaster(axes=[60, 50, 400], id="MasterID-PosterCondRegular"), + createGSFontMaster(axes=[60, 50, 900], id="MasterID-PosterCondBold"), + createGSFontMaster(axes=[60, 200, 100], id="MasterID-PosterWideLight"), + createGSFontMaster(axes=[60, 200, 400], id="MasterID-PosterWideRegular"), + createGSFontMaster(axes=[60, 200, 900], id="MasterID-PosterWideBold"), + ] + gsFont.glyphs.append( + createGSGlyph( + name="A", + unicodes=[ + 0x0041, + ], + layers=[GSLayer()], + ) + ) + return gsFont async def test_getLocationFromSources(testFont): @@ -35,13 +80,23 @@ async def test_getLocationFromSources(testFont): assert location == {"weight": 155} -def test_getAssociatedMasterId(testGSFont): - # TODO: need more complex test with at least two axes, - # then improvement getAssociatedMasterId - gsGlyph = testGSFont.glyphs["a"] - associatedMasterId = getAssociatedMasterId(gsGlyph, [155]) - associatedMaster = gsGlyph.layers[associatedMasterId] - assert associatedMaster.name == "Regular" +expectedAssociatedMasterId = [ + # gsLocation, associatedMasterId + [[14, 155, 900], "MasterID-TextWideBold"], + [[14, 155, 100], "MasterID-TextWideLight"], + [[14, 55, 900], "MasterID-TextCondBold"], + [[14, 55, 110], "MasterID-TextCondLight"], + [[55, 155, 900], "MasterID-PosterWideBold"], + [[55, 155, 100], "MasterID-PosterWideLight"], + [[55, 55, 900], "MasterID-PosterCondBold"], + [[55, 55, 110], "MasterID-PosterCondLight"], + [[30, 100, 399], "MasterID-TextCondRegular"], +] + + +@pytest.mark.parametrize("gsLocation,expected", expectedAssociatedMasterId) +def test_getAssociatedMasterId(testGSFontWW, gsLocation, expected): + assert getAssociatedMasterId(testGSFontWW, gsLocation) == expected contentSnippets = [