Start work on listing variable fonts under macOS

This commit is contained in:
Kovid Goyal
2024-04-20 13:48:57 +05:30
parent fcbf0782b5
commit 2f3578ad93
7 changed files with 29 additions and 11 deletions

View File

@@ -98,8 +98,10 @@ font_descriptor_to_python(CTFontDescriptorRef descriptor) {
unsigned int straits = [traits[(id)kCTFontSymbolicTrait] unsignedIntValue];
float weightVal = [traits[(id)kCTFontWeightTrait] floatValue];
float widthVal = [traits[(id)kCTFontWidthTrait] floatValue];
NSDictionary *variation = (NSDictionary *)CTFontDescriptorCopyAttribute(descriptor, kCTFontVariationAttribute);
PyObject *ans = Py_BuildValue("{ssssssss sOsOsOsOsOsO sfsfsI}",
PyObject *ans = Py_BuildValue("{ssssssssss sOsOsOsOsOsOsO sfsfsI}",
"descriptor_type", "core_text",
"path", [[url path] UTF8String],
"postscript_name", [psName UTF8String],
"family", [family UTF8String],
@@ -111,6 +113,7 @@ font_descriptor_to_python(CTFontDescriptorRef descriptor) {
"expanded", (straits & kCTFontExpandedTrait) != 0 ? Py_True : Py_False,
"condensed", (straits & kCTFontCondensedTrait) != 0 ? Py_True : Py_False,
"color_glyphs", (straits & kCTFontColorGlyphsTrait) != 0 ? Py_True : Py_False,
"variable", variation ? Py_True : Py_False,
"weight", weightVal,
"width", widthVal,
@@ -121,6 +124,7 @@ font_descriptor_to_python(CTFontDescriptorRef descriptor) {
[family release];
[style release];
[traits release];
if (variation) [variation release];
return ans;
}

View File

@@ -1,6 +1,6 @@
import termios
from ctypes import Array, c_ubyte
from typing import Any, Callable, Dict, Iterator, List, NewType, Optional, Tuple, TypedDict, Union, overload
from typing import Any, Callable, Dict, Iterator, List, Literal, NewType, Optional, Tuple, TypedDict, Union, overload
from kitty.boss import Boss
from kitty.fonts import FontFeature, VariableData
@@ -373,6 +373,7 @@ def default_color_table() -> Tuple[int, ...]:
class FontConfigPattern(TypedDict):
descriptor_type: Literal['fontconfig']
path: str
index: int
family: str
@@ -422,6 +423,7 @@ class Face:
class CoreTextFont(TypedDict):
descriptor_type: Literal['core_text']
path: str
postscript_name: str
family: str
@@ -432,6 +434,7 @@ class CoreTextFont(TypedDict):
condensed: bool
color_glyphs: bool
monospace: bool
variable: bool
weight: float
width: float
traits: int

View File

@@ -150,7 +150,7 @@ pyspacing(int val) {
static PyObject*
pattern_as_dict(FcPattern *pat) {
PyObject *ans = PyDict_New(), *p = NULL, *list = NULL;
PyObject *ans = Py_BuildValue("{ss}", "descriptor_type", "fontconfig"), *p = NULL, *list = NULL;
if (ans == NULL) return NULL;
#define PS(x) PyUnicode_Decode((const char*)x, strlen((const char*)x), "UTF-8", "replace")

View File

@@ -1,5 +1,7 @@
from enum import Enum, IntEnum, auto
from typing import Any, NamedTuple, Optional, Tuple, TypedDict
from typing import NamedTuple, Optional, Tuple, TypedDict, Union
from kitty.typing import CoreTextFont, FontConfigPattern
class ListedFont(TypedDict):
@@ -8,7 +10,7 @@ class ListedFont(TypedDict):
postscript_name: str
is_monospace: bool
is_variable: bool
descriptor: Any
descriptor: Union[FontConfigPattern, CoreTextFont]
class VariableAxis(TypedDict):

View File

@@ -5,7 +5,7 @@ import re
from typing import Dict, Generator, Iterable, List, Optional, Tuple
from kitty.fast_data_types import coretext_all_fonts
from kitty.fonts import FontFeature
from kitty.fonts import FontFeature, VariableData
from kitty.options.types import Options
from kitty.typing import CoreTextFont
from kitty.utils import log_error
@@ -47,7 +47,8 @@ def list_fonts() -> Generator[ListedFont, None, None]:
if f:
fn = f'{f} {fd.get("style", "")}'.strip()
is_mono = bool(fd['monospace'])
yield {'family': f, 'full_name': fn, 'postscript_name': fd['postscript_name'] or '', 'is_monospace': is_mono}
yield {'family': f, 'full_name': fn, 'postscript_name': fd['postscript_name'] or '', 'is_monospace': is_mono,
'is_variable': fd['variable'], 'descriptor': fd}
def find_font_features(postscript_name: str) -> Tuple[FontFeature, ...]:
@@ -114,3 +115,9 @@ def get_font_files(opts: Options) -> Dict[str, CoreTextFont]:
def font_for_family(family: str) -> Tuple[CoreTextFont, bool, bool]:
ans = find_best_match(resolve_family(family, getattr(get_font_files, 'medium_family')))
return ans, ans['bold'], ans['italic']
def get_variable_data_for_descriptor(f: ListedFont) -> VariableData:
d = f['descriptor']
assert d['descriptor_type'] == 'core_text'
return d['variable_data']

View File

@@ -177,5 +177,7 @@ def font_for_family(family: str) -> Tuple[FontConfigPattern, bool, bool]:
return ans, ans.get('weight', 0) >= FC_WEIGHT_BOLD, ans.get('slant', FC_SLANT_ROMAN) != FC_SLANT_ROMAN
def get_variable_data_for_descriptor(fd: FontConfigPattern) -> VariableData:
return Face(descriptor=fd).get_variable_data()
def get_variable_data_for_descriptor(f: ListedFont) -> VariableData:
d = f['descriptor']
assert d['descriptor_type'] == 'fontconfig'
return Face(descriptor=d).get_variable_data()

View File

@@ -11,7 +11,7 @@ from kitty.types import run_once
from . import ListedFont
if is_macos:
from .core_text import list_fonts
from .core_text import get_variable_data_for_descriptor, list_fonts
else:
from .fontconfig import get_variable_data_for_descriptor, list_fonts
@@ -58,7 +58,7 @@ def create_family_groups(monospaced: bool = True) -> Dict[str, List[ListedFont]]
def show_variable(f: ListedFont, psnames: bool) -> None:
vd = get_variable_data_for_descriptor(f['descriptor'])
vd = get_variable_data_for_descriptor(f)
p = f"{italic(f['full_name'])} {variable_font_label('Variable font')}"
print(indented(p))
print(indented(variable_font_label('Axes of variation'), level=2))