diff --git a/drawBot/context/baseContext.py b/drawBot/context/baseContext.py index dbc6923c..6a2f759e 100644 --- a/drawBot/context/baseContext.py +++ b/drawBot/context/baseContext.py @@ -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) def tabs(self, tab: tuple[float, str] | None, *tabs: tuple[float, str]): """ @@ -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 @@ -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: diff --git a/drawBot/context/tools/variation.py b/drawBot/context/tools/variation.py index 8b15ad99..72d01f5a 100644 --- a/drawBot/context/tools/variation.py +++ b/drawBot/context/tools/variation.py @@ -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