Files
kitty/kitty/fonts/__init__.py
Kovid Goyal 4ab8c16184 ...
2024-06-24 07:54:16 +05:30

177 lines
3.6 KiB
Python

from enum import Enum, IntEnum, auto
from typing import TYPE_CHECKING, Callable, Dict, List, Literal, NamedTuple, Tuple, TypedDict, Union
from kitty.types import run_once
from kitty.typing import CoreTextFont, FontConfigPattern
if TYPE_CHECKING:
import re
class ListedFont(TypedDict):
family: str
style: str
full_name: str
postscript_name: str
is_monospace: bool
is_variable: bool
descriptor: Union[FontConfigPattern, CoreTextFont]
class VariableAxis(TypedDict):
minimum: float
maximum: float
default: float
hidden: bool
tag: str
strid: str # Can be empty string when not present
class NamedStyle(TypedDict):
axis_values: Dict[str, float]
name: str
psname: str # can be empty string when not present
class DesignValue1(TypedDict):
format: Literal[1]
flags: int
name: str
value: float
class DesignValue2(TypedDict):
format: Literal[2]
flags: int
name: str
value: float
minimum: float
maximum: float
class DesignValue3(TypedDict):
format: Literal[3]
flags: int
name: str
value: float
linked_value: float
DesignValue = Union[DesignValue1, DesignValue2, DesignValue3]
class DesignAxis(TypedDict):
name: str
ordering: int
tag: str
values: List[DesignValue]
class AxisValue(TypedDict):
design_index: int
value: float
class MultiAxisStyle(TypedDict):
flags: int
name: str
values: Tuple[AxisValue, ...]
class VariableData(TypedDict):
axes: Tuple[VariableAxis, ...]
named_styles: Tuple[NamedStyle, ...]
variations_postscript_name_prefix: str
elided_fallback_name: str
design_axes: Tuple[DesignAxis, ...]
multi_axis_styles: Tuple[MultiAxisStyle, ...]
class FontFeature:
__slots__ = 'name', 'parsed'
def __init__(self, name: str, parsed: bytes):
self.name = name
self.parsed = parsed
def __repr__(self) -> str:
return repr(self.name)
class ModificationType(Enum):
underline_position = auto()
underline_thickness = auto()
strikethrough_position = auto()
strikethrough_thickness = auto()
cell_width = auto()
cell_height = auto()
baseline = auto()
size = auto()
class ModificationUnit(IntEnum):
pt = 0
percent = 1
pixel = 2
class ModificationValue(NamedTuple):
val: float
unit: ModificationUnit
def __repr__(self) -> str:
u = '%' if self.unit is ModificationUnit.percent else ''
return f'{self.val:g}{u}'
class FontModification(NamedTuple):
mod_type: ModificationType
mod_value: ModificationValue
font_name: str = ''
def __repr__(self) -> str:
fn = f' {self.font_name}' if self.font_name else ''
return f'{self.mod_type.name}{fn} {self.mod_value}'
class FontSpec(NamedTuple):
family: str = ''
style: str = ''
postscript_name: str = ''
full_name: str = ''
system: str = ''
axes: Tuple[Tuple[str, float], ...] = ()
variable_name: str = ''
created_from_string: str = ''
@property
def is_system(self) -> bool:
return bool(self.system)
@property
def is_auto(self) -> bool:
return self.system == 'auto'
class Score(NamedTuple):
variable_score: int
style_score: int
monospace_score: int
width_score: int
weight_distance_from_medium: float = 0
Descriptor = Union[FontConfigPattern, CoreTextFont]
Scorer = Callable[[Descriptor], Score]
@run_once
def fnname_pat() -> 're.Pattern[str]':
import re
return re.compile(r'\s+')
def family_name_to_key(family: str) -> str:
return fnname_pat().sub(' ', family).strip().lower()