CoreText: When finding medium face for a family prefer variable font if available

This commit is contained in:
Kovid Goyal
2024-05-16 11:37:37 +05:30
parent 5d725c4883
commit 8ba6d5a296
3 changed files with 22 additions and 7 deletions

View File

@@ -92,7 +92,7 @@ def pprint(*a: Any) -> None:
pprint(*a)
def find_medium_variant(font: Descriptor) -> Descriptor:
def find_medium_variant(font: DescriptorVar) -> DescriptorVar:
font = font.copy()
vd = get_variable_data_for_descriptor(font)
for i, ns in enumerate(vd['named_styles']):

View File

@@ -183,6 +183,15 @@ def find_best_match(
if possible != ignore_face:
return possible
# See if we have a variable font
if not bold and not italic and font_map['variable_map'].get(q):
candidates = font_map['variable_map'][q]
candidates = scorer.sorted_candidates(candidates)
possible = candidates[0]
if possible != ignore_face:
from .common import find_medium_variant
return find_medium_variant(possible)
# Let CoreText choose the font if the family exists, otherwise
# fallback to Menlo
if q not in font_map['family_map']:

View File

@@ -27,7 +27,7 @@ class Selection(BaseTest):
names = set(fonts_map['family_map']) | set(fonts_map['variable_map'])
del fonts_map
def s(family: str, *expected: str) -> None:
def s(family: str, *expected: str, alternate=None) -> 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
@@ -36,11 +36,17 @@ class Selection(BaseTest):
if '/' in x: # Old FreeType failed to generate postscript name for a variable font probably
return
with self.subTest(spec=family):
self.ae(expected, actual)
try:
self.ae(expected, actual)
except AssertionError:
if alternate:
self.ae(tuple(map(alternate, expected)), actual)
else:
raise
def both(family: str, *expected: str) -> None:
def both(family: str, *expected: str, alternate=None) -> None:
for family in (family, f'family="{family}"'):
s(family, *expected)
s(family, *expected, alternate=alternate)
def has(family, allow_missing_in_ci=False):
ans = family_name_to_key(family) in names
@@ -48,12 +54,12 @@ class Selection(BaseTest):
raise AssertionError(f'The family: {family} is not available')
return ans
def t(family, psprefix, bold='Bold', italic='Italic', bi='', reg='Regular', allow_missing_in_ci=False):
def t(family, psprefix, bold='Bold', italic='Italic', bi='', reg='Regular', allow_missing_in_ci=False, alternate=None):
if has(family, allow_missing_in_ci=allow_missing_in_ci):
bi = bi or bold + italic
if reg:
reg = '-' + reg
both(family, f'{psprefix}{reg}', f'{psprefix}-{bold}', f'{psprefix}-{italic}', f'{psprefix}-{bi}')
both(family, f'{psprefix}{reg}', f'{psprefix}-{bold}', f'{psprefix}-{italic}', f'{psprefix}-{bi}', alternate=alternate)
t('Source Code Pro', 'SourceCodePro', 'Semibold', 'It')
t('sourcecodeVf', 'SourceCodeVF', 'Semibold')