Get font selection for the cascadia code variable fonts working

This commit is contained in:
Kovid Goyal
2024-05-15 22:09:59 +05:30
parent 7cdcbe6aeb
commit c27c731ffb
4 changed files with 48 additions and 29 deletions

View File

@@ -102,7 +102,7 @@ def find_medium_variant(font: Descriptor) -> Descriptor:
vd = get_variable_data_for_descriptor(font)
for i, ns in enumerate(vd['named_styles']):
if ns['name'] == 'Regular':
set_named_style(ns['psname'], font, vd)
set_named_style(ns['psname'] or ns['name'], font, vd)
return font
axis_values = {}
for i, ax in enumerate(vd['axes']):

View File

@@ -7,7 +7,7 @@ from collections import defaultdict
from functools import lru_cache
from typing import Dict, Generator, Iterable, List, NamedTuple, Optional, Sequence, Tuple
from kitty.fast_data_types import coretext_all_fonts
from kitty.fast_data_types import CTFace, coretext_all_fonts
from kitty.fonts import FontSpec, family_name_to_key
from kitty.options.types import Options
from kitty.typing import CoreTextFont
@@ -109,9 +109,9 @@ def weight_range_for_family(family: str) -> WeightRange:
bold = w
elif s == 'bold' and bold == wr.bold:
bold = w
elif s == 'medium':
elif s == 'regular':
medium = w
elif s == 'regular' and medium == wr.medium:
elif s == 'medium' and medium == wr.medium:
medium = w
return WeightRange(mini, maxi, medium, bold)
@@ -148,15 +148,18 @@ class CTScorer(Scorer):
families = {x['family'] for x in candidates}
if len(families) == 1:
wr = weight_range_for_family(next(iter(families)))
if wr.is_valid and wr.minimum < 0 and wr.maximum <= 0: # Operator Mono is an example of this craziness
if wr.is_valid and wr.medium < 0: # Operator Mono is an example of this craziness
self.weight_range = wr
candidates = sorted(candidates, key=self.score)
if dump:
print(self)
if self.weight_range:
print(self.weight_range)
for x in candidates:
assert x['descriptor_type'] == 'core_text'
print(x['postscript_name'], f'bold={x["bold"]}', f'italic={x["italic"]}', f'weight={x["weight"]:.2f}', f'slant={x["slant"]:.2f}')
print(self.score(x))
print(CTFace(descriptor=x).postscript_name(),
f'bold={x["bold"]}', f'italic={x["italic"]}', f'weight={x["weight"]:.2f}', f'slant={x["slant"]:.2f}')
print(' ', self.score(x))
print()
return candidates

View File

@@ -12,6 +12,7 @@ from kitty.fast_data_types import (
FC_SLANT_ROMAN,
FC_WEIGHT_REGULAR,
FC_WIDTH_NORMAL,
Face,
fc_list,
)
from kitty.fast_data_types import (
@@ -117,9 +118,9 @@ def weight_range_for_family(family: str) -> WeightRange:
bold = w
elif s == 'bold' and bold == wr.bold:
bold = w
elif s == 'medium':
elif s == 'regular':
medium = w
elif s == 'regular' and medium == wr.medium:
elif s == 'medium' and medium == wr.medium:
medium = w
return WeightRange(mini, maxi, medium, bold)
@@ -148,15 +149,17 @@ class FCScorer(Scorer):
families = {x['family'] for x in candidates}
if len(families) == 1:
wr = weight_range_for_family(next(iter(families)))
if wr.is_valid and wr.maximum < 100: # Operator Mono is an example of this craziness
if wr.is_valid and wr.medium < 100: # Operator Mono and Cascadia Code are examples
self.weight_range = wr
candidates = sorted(candidates, key=self.score)
if dump:
print(self)
if self.weight_range:
print(self.weight_range)
for x in candidates:
assert x['descriptor_type'] == 'fontconfig'
print(x['postscript_name'], f'weight={x["weight"]}', f'slant={x["slant"]}')
print(self.score(x))
print(Face(descriptor=x).postscript_name(), f'weight={x["weight"]}', f'slant={x["slant"]}')
print(' ', self.score(x))
print()
return candidates

View File

@@ -25,19 +25,13 @@ class Selection(BaseTest):
opts = Options()
fonts_map = all_fonts_map(True)
names = set(fonts_map['family_map']) | set(fonts_map['variable_map'])
def has(x: str) -> bool:
return family_name_to_key(x) in names
has_source_code_pro = has('Source Code Pro')
has_source_code_vf = has('sourcecodeVf')
has_fira_code = has('Fira Code')
has_hack = has('Hack')
has_operator_mono = has('Operator Mono')
del fonts_map, has
del fonts_map
def s(family: str, *expected: str) -> None:
opts.font_family = parse_font_spec(family)
ff = get_font_files(opts)
actual = tuple(face_from_descriptor(ff[x]).postscript_name() for x in ('medium', 'bold', 'italic', 'bi')) # type: ignore
del ff
with self.subTest(spec=family):
self.ae(expected, actual)
@@ -45,15 +39,34 @@ class Selection(BaseTest):
for family in (family, f'family="{family}"'):
s(family, *expected)
if has_source_code_pro:
both('Source Code Pro', 'SourceCodePro-Regular', 'SourceCodePro-Semibold', 'SourceCodePro-It', 'SourceCodePro-SemiboldIt')
if has_source_code_vf:
both('sourcecodeVf', 'SourceCodeVF-Regular', 'SourceCodeVF-Semibold', 'SourceCodeVF-Italic', 'SourceCodeVF-SemiboldItalic')
if has_fira_code:
both('fira code', 'FiraCodeRoman-Regular', 'FiraCodeRoman-SemiBold', 'FiraCodeRoman-Regular', 'FiraCodeRoman-SemiBold')
if has_hack:
both('hack', 'Hack-Regular', 'Hack-Bold', 'Hack-Italic', 'Hack-BoldItalic')
if has_operator_mono:
def has(family):
return family_name_to_key(family) in names
def t(family, psprefix, bold='Bold', italic='Italic', bi='', reg='Regular'):
if has(family):
bi = bi or bold + italic
if reg:
reg = '-' + reg
both(family, f'{psprefix}{reg}', f'{psprefix}-{bold}', f'{psprefix}-{italic}', f'{psprefix}-{bi}')
t('Source Code Pro', 'SourceCodePro', 'Semibold', 'It')
t('sourcecodeVf', 'SourceCodeVF', 'Semibold')
t('fira code', 'FiraCodeRoman', 'SemiBold', 'Regular', 'SemiBold')
t('hack', 'Hack')
t('fantasque sans mono', 'FantasqueSansMono')
t('jetbrains mono', 'JetBrainsMono', 'SemiBold')
t('consolas', 'Consolas', reg='')
if has('cascadia code'):
if is_macos:
both('cascadia code', 'CascadiaCode-Regular', 'CascadiaCode-Regular_SemiBold', 'CascadiaCode-Italic', 'CascadiaCode-Italic_SemiBold-Italic')
else:
both('cascadia code', 'CascadiaCodeRoman-Regular', 'CascadiaCodeRoman-SemiBold', 'CascadiaCode-Italic', 'CascadiaCode-SemiBoldItalic')
if has('cascadia mono'):
if is_macos:
both('cascadia mono', 'CascadiaMono-Regular', 'CascadiaMono-Regular_SemiBold', 'CascadiaMono-Italic', 'CascadiaMono-Italic_SemiBold-Italic')
else:
both('cascadia mono', 'CascadiaMonoRoman-Regular', 'CascadiaMonoRoman-SemiBold', 'CascadiaMono-Italic', 'CascadiaMono-SemiBoldItalic')
if has('operator mono'):
both('operator mono', 'OperatorMono-Medium', 'OperatorMono-Bold', 'OperatorMono-MediumItalic', 'OperatorMono-BoldItalic')