Fix medium face selection when more than family specified

This commit is contained in:
Kovid Goyal
2024-05-17 17:34:48 +05:30
parent ff89f5187d
commit 28f2919753
2 changed files with 26 additions and 8 deletions

View File

@@ -59,6 +59,10 @@ cache_for_variable_data_by_path: Dict[str, VariableData] = {}
attr_map = {(False, False): 'font_family', (True, False): 'bold_font', (False, True): 'italic_font', (True, True): 'bold_italic_font'} attr_map = {(False, False): 'font_family', (True, False): 'bold_font', (False, True): 'italic_font', (True, True): 'bold_italic_font'}
class Event:
is_set: bool = False
def get_variable_data_for_descriptor(d: Descriptor) -> VariableData: def get_variable_data_for_descriptor(d: Descriptor) -> VariableData:
if not d['path']: if not d['path']:
return face_from_descriptor(d).get_variable_data() return face_from_descriptor(d).get_variable_data()
@@ -87,9 +91,10 @@ def find_best_match_in_candidates(
return x return x
return None return None
def pprint(*a: Any) -> None:
def pprint(*a: Any, **kw: Any) -> None:
from pprint import pprint from pprint import pprint
pprint(*a) pprint(*a, **kw)
def find_medium_variant(font: DescriptorVar) -> DescriptorVar: def find_medium_variant(font: DescriptorVar) -> DescriptorVar:
@@ -173,7 +178,7 @@ def find_best_variable_face(spec: FontSpec, bold: bool, italic: bool, monospaced
def get_fine_grained_font( def get_fine_grained_font(
spec: FontSpec, bold: bool = False, italic: bool = False, medium_font_spec: FontSpec = FontSpec(), spec: FontSpec, bold: bool = False, italic: bool = False, medium_font_spec: FontSpec = FontSpec(),
resolved_medium_font: Optional[Descriptor] = None, monospaced: bool = True resolved_medium_font: Optional[Descriptor] = None, monospaced: bool = True, match_is_more_specific_than_family: Event = Event()
) -> Descriptor: ) -> Descriptor:
font_map = all_fonts_map(monospaced) font_map = all_fonts_map(monospaced)
is_medium_face = resolved_medium_font is None is_medium_face = resolved_medium_font is None
@@ -181,10 +186,12 @@ def get_fine_grained_font(
if spec.postscript_name: if spec.postscript_name:
q = find_best_match_in_candidates(font_map['ps_map'].get(family_name_to_key(spec.postscript_name), []), scorer, is_medium_face) q = find_best_match_in_candidates(font_map['ps_map'].get(family_name_to_key(spec.postscript_name), []), scorer, is_medium_face)
if q: if q:
match_is_more_specific_than_family.is_set = True
return q return q
if spec.full_name: if spec.full_name:
q = find_best_match_in_candidates(font_map['full_map'].get(family_name_to_key(spec.full_name), []), scorer, is_medium_face) q = find_best_match_in_candidates(font_map['full_map'].get(family_name_to_key(spec.full_name), []), scorer, is_medium_face)
if q: if q:
match_is_more_specific_than_family.is_set = True
return q return q
if spec.family: if spec.family:
key = family_name_to_key(spec.family) key = family_name_to_key(spec.family)
@@ -194,6 +201,7 @@ def get_fine_grained_font(
q = candidates[0] if len(candidates) == 1 else find_best_variable_face(spec, bold, italic, monospaced, candidates) q = candidates[0] if len(candidates) == 1 else find_best_variable_face(spec, bold, italic, monospaced, candidates)
q, applied = apply_variation_to_pattern(q, spec) q, applied = apply_variation_to_pattern(q, spec)
if applied: if applied:
match_is_more_specific_than_family.is_set = True
return q return q
return find_medium_variant(q) if resolved_medium_font is None else find_bold_italic_variant(resolved_medium_font, bold, italic) return find_medium_variant(q) if resolved_medium_font is None else find_bold_italic_variant(resolved_medium_font, bold, italic)
# Now look for any font # Now look for any font
@@ -234,10 +242,11 @@ def apply_variation_to_pattern(pat: Descriptor, spec: FontSpec) -> Tuple[Descrip
def get_font_from_spec( def get_font_from_spec(
spec: FontSpec, bold: bool = False, italic: bool = False, medium_font_spec: FontSpec = FontSpec(), spec: FontSpec, bold: bool = False, italic: bool = False, medium_font_spec: FontSpec = FontSpec(),
resolved_medium_font: Optional[Descriptor] = None resolved_medium_font: Optional[Descriptor] = None, match_is_more_specific_than_family: Event = Event()
) -> Descriptor: ) -> Descriptor:
if not spec.is_system: if not spec.is_system:
return get_fine_grained_font(spec, bold, italic, medium_font_spec, resolved_medium_font) return get_fine_grained_font(spec, bold, italic, medium_font_spec, resolved_medium_font,
match_is_more_specific_than_family=match_is_more_specific_than_family)
family = spec.system family = spec.system
if family == 'auto': if family == 'auto':
if bold or italic: if bold or italic:
@@ -271,8 +280,10 @@ def is_actually_variable_despite_fontconfigs_lies(d: Descriptor) -> bool:
def get_font_files(opts: Options) -> FontFiles: def get_font_files(opts: Options) -> FontFiles:
ans: Dict[str, Descriptor] = {} ans: Dict[str, Descriptor] = {}
medium_font = get_font_from_spec(opts.font_family) match_is_more_specific_than_family = Event()
if is_variable(medium_font) or is_actually_variable_despite_fontconfigs_lies(medium_font): medium_font = get_font_from_spec(opts.font_family, match_is_more_specific_than_family=match_is_more_specific_than_family)
if not match_is_more_specific_than_family.is_set and (
is_variable(medium_font) or is_actually_variable_despite_fontconfigs_lies(medium_font)):
medium_font = find_medium_variant(medium_font) medium_font = find_medium_variant(medium_font)
kd = {(False, False): 'medium', (True, False): 'bold', (False, True): 'italic', (True, True): 'bi'} kd = {(False, False): 'medium', (True, False): 'bold', (False, True): 'italic', (True, True): 'bi'}
for (bold, italic), attr in attr_map.items(): for (bold, italic), attr in attr_map.items():

View File

@@ -11,7 +11,7 @@ from kitty.constants import is_macos, read_kitty_resource
from kitty.fast_data_types import DECAWM, get_fallback_font, sprite_map_set_layout, sprite_map_set_limits, test_render_line, test_sprite_position_for, wcwidth from kitty.fast_data_types import DECAWM, get_fallback_font, sprite_map_set_layout, sprite_map_set_limits, test_render_line, test_sprite_position_for, wcwidth
from kitty.fonts import family_name_to_key from kitty.fonts import family_name_to_key
from kitty.fonts.box_drawing import box_chars from kitty.fonts.box_drawing import box_chars
from kitty.fonts.common import all_fonts_map, face_from_descriptor, get_font_files from kitty.fonts.common import all_fonts_map, face_from_descriptor, get_font_files, get_named_style
from kitty.fonts.render import coalesce_symbol_maps, render_string, setup_for_testing, shape_string from kitty.fonts.render import coalesce_symbol_maps, render_string, setup_for_testing, shape_string
from kitty.options.types import Options from kitty.options.types import Options
from kitty.options.utils import parse_font_spec from kitty.options.utils import parse_font_spec
@@ -87,6 +87,13 @@ class Selection(BaseTest):
if has('operator mono', allow_missing_in_ci=True): if has('operator mono', allow_missing_in_ci=True):
both('operator mono', 'OperatorMono-Medium', 'OperatorMono-Bold', 'OperatorMono-MediumItalic', 'OperatorMono-BoldItalic') both('operator mono', 'OperatorMono-Medium', 'OperatorMono-Bold', 'OperatorMono-MediumItalic', 'OperatorMono-BoldItalic')
if has('SourceCodeVF'):
opts = Options()
opts.font_family = parse_font_spec('family="SourceCodeVF" variable_name="SourceCodeUpright" style="Black"')
d = get_font_files(opts)['medium']
face = face_from_descriptor(d)
self.ae(get_named_style(face)['name'], 'Black')
class Rendering(BaseTest): class Rendering(BaseTest):