Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 20 additions & 5 deletions drawBot/context/baseContext.py
Original file line number Diff line number Diff line change
Expand Up @@ -1905,8 +1905,20 @@ def listNamedInstances(self, fontNameOrPath: SomePath | None = None, fontNumber:
"""
if fontNameOrPath is None:
fontNameOrPath = self._font
font = getNSFontFromNameOrPath(fontNameOrPath, 10, fontNumber)
return variation.getNamedInstancesForFont(font)
if not os.path.exists(fontNameOrPath):
# the font is installed
font = getNSFontFromNameOrPath(fontNameOrPath, 10, fontNumber)
# get the url from the font descriptor
url = CoreText.CTFontDescriptorCopyAttribute(font.fontDescriptor(), CoreText.kCTFontURLAttribute)
if url is None:
return dict()
else:
path = url.path()
else:
path = fontNameOrPath

descriptors = getFontDescriptorsFromPath(path)
return variation.getNamedInstancesForDescriptors(descriptors)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're somehow ignoring fontNumber here.

Yet I don't know what to do, since CTFontManagerCreateFontDescriptorsFromData() does not (can not?) distinguish between "multiple instances in a VF", "multiple statics in a TTC" or even "multiple instances for multiple VFs in a TTC".


def tabs(self, tab: tuple[float, str] | None, *tabs: tuple[float, str]):
"""
Expand Down Expand Up @@ -3013,8 +3025,11 @@ def _getNSFontFromNameOrPath(fontNameOrPath, fontSize, fontNumber):

@memoize
def getFontDescriptorsFromPath(fontPath):
modTime = os.stat(fontPath).st_mtime
prevModTime, descriptors = _reloadedFontDescriptors.get(fontPath, (modTime, None))
if os.path.exists(fontPath):
modTime = os.stat(fontPath).st_mtime
else:
modTime = -1
prevModTime, descriptors = _reloadedFontDescriptors.get(fontPath, (modTime, ()))
if modTime == prevModTime:
if not descriptors:
# Load font from disk, letting the OS handle caching and loading
Expand All @@ -3032,7 +3047,7 @@ def getFontDescriptorsFromPath(fontPath):
data = AppKit.NSData.dataWithContentsOfFile_(fontPath)
descriptors = CoreText.CTFontManagerCreateFontDescriptorsFromData(data)
_reloadedFontDescriptors[fontPath] = modTime, descriptors
return descriptors
return tuple(descriptors)


def getFontName(font) -> str | None:
Expand Down
48 changes: 19 additions & 29 deletions drawBot/context/tools/variation.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,43 +49,33 @@ def getVariationAxesForFont(font):


@memoize
def getNamedInstancesForFont(font):
def getNamedInstancesForDescriptors(descriptors):
"""
Return a dict { postscriptName: location } of all named instances in a given font.
"""
instances = OrderedDict()
if font is None:
return instances
fontDescriptor = font.fontDescriptor()
url = CoreText.CTFontDescriptorCopyAttribute(fontDescriptor, CoreText.kCTFontURLAttribute)
if url is None:
return instances
instances = dict()

variationAxesDescriptions = CoreText.CTFontCopyVariationAxes(font)
if variationAxesDescriptions is None:
# non-variable fonts have no named instances
return instances
tagNameMap = {}
for variationAxesDescription in variationAxesDescriptions:
tag = convertIntToVariationTag(variationAxesDescription[CoreText.kCTFontVariationAxisIdentifierKey])
name = variationAxesDescription[CoreText.kCTFontVariationAxisNameKey]
tagNameMap[tag] = name
for descriptor in descriptors:
# convert to a ctFont
font = CoreText.CTFontCreateWithFontDescriptor(descriptor, 10, None)
# get the default variation axes
variationAxesDescriptions = CoreText.CTFontCopyVariationAxes(font)

if variationAxesDescriptions is not None:
# variable fonts have named instances
fontVariation = CoreText.CTFontCopyVariation(font)
variationCoordinates = {}

ft = TTFont(url.path(), lazy=True, fontNumber=0)
if "fvar" in ft:
cgFont, _ = CoreText.CTFontCopyGraphicsFont(font, None)
fvar = ft["fvar"]
for variationAxesDescription in variationAxesDescriptions:
tag = convertIntToVariationTag(variationAxesDescription[CoreText.NSFontVariationAxisIdentifierKey])
variationCoordinates[tag] = variationAxesDescription[CoreText.NSFontVariationAxisDefaultValueKey]

for instance in fvar.instances:
fontVariations = dict()
for axis, value in instance.coordinates.items():
fontVariations[tagNameMap[axis]] = value
for fontVariationKey, fontVariationValue in fontVariation.items():
tag = convertIntToVariationTag(fontVariationKey)
variationCoordinates[tag] = fontVariationValue

varFont = CoreText.CGFontCreateCopyWithVariations(cgFont, fontVariations)
postScriptName = CoreText.CGFontCopyPostScriptName(varFont)
instances[postScriptName] = instance.coordinates
instances[descriptor.postscriptName()] = variationCoordinates

ft.close()
return instances


Expand Down