Use builtin NERD font for symbol_map if no system NERD font is available

This commit is contained in:
Kovid Goyal
2024-07-02 15:33:07 +05:30
parent a783e5d85a
commit fd5b96b43b
5 changed files with 40 additions and 20 deletions

View File

@@ -640,7 +640,18 @@ cell_metrics(PyObject *s, unsigned int* cell_width, unsigned int* cell_height, u
PyObject*
face_from_descriptor(PyObject *descriptor, FONTS_DATA_HANDLE fg) {
RAII_CoreFoundation(CTFontDescriptorRef, desc, font_descriptor_from_python(descriptor));
RAII_CoreFoundation(CTFontDescriptorRef, desc, NULL);
if (builtin_nerd_font_descriptor) {
PyObject *psname = PyDict_GetItemString(descriptor, "postscript_name");
if (psname && PyUnicode_CompareWithASCIIString(psname, "SymbolsNFM") == 0) {
RAII_PyObject(path, get_path_for_font_descriptor(builtin_nerd_font_descriptor));
PyObject *dpath = PyDict_GetItemString(descriptor, "path");
if (dpath && PyUnicode_Compare(path, dpath) == 0) {
desc = builtin_nerd_font_descriptor; CFRetain(desc);
}
}
}
if (!desc) desc = font_descriptor_from_python(descriptor);
if (!desc) return NULL;
RAII_CoreFoundation(CTFontRef, font, CTFontCreateWithFontDescriptor(desc, fg ? scaled_point_sz(fg) : 12, NULL));
if (!font) { PyErr_SetString(PyExc_ValueError, "Failed to create CTFont object"); return NULL; }
@@ -672,8 +683,7 @@ new(PyTypeObject *type UNUSED, PyObject *args, PyObject *kw) {
PyObject*
specialize_font_descriptor(PyObject *base_descriptor, double font_sz_in_pts UNUSED, double dpi_x UNUSED, double dpi_y UNUSED) {
Py_INCREF(base_descriptor);
return base_descriptor;
return PyDict_Copy(base_descriptor);
}
struct RenderBuffers {
@@ -1135,7 +1145,7 @@ set_builtin_nerd_font(PyObject UNUSED *self, PyObject *pypath) {
if (builtin_nerd_font_descriptor) CFRelease(builtin_nerd_font_descriptor);
builtin_nerd_font_descriptor = CFArrayGetValueAtIndex(descriptors, 0);
CFRetain(builtin_nerd_font_descriptor);
Py_RETURN_NONE;
return font_descriptor_to_python(builtin_nerd_font_descriptor);
}
static PyMethodDef module_methods[] = {

View File

@@ -426,7 +426,7 @@ def fc_match_postscript_name(
def add_font_file(path: str) -> bool: ...
def set_builtin_nerd_font(path: str) -> None: ...
def set_builtin_nerd_font(path: str) -> Union[CoreTextFont, FontConfigPattern]: ...
class FeatureData(TypedDict):

View File

@@ -426,6 +426,12 @@ specialize_font_descriptor(PyObject *base_descriptor, double font_sz_in_pts, dou
AP(FcPatternAddDouble, FC_DPI, (dpi_x + dpi_y) / 2.0, "dpi");
ans = _fc_match(pat);
FcPatternDestroy(pat); pat = NULL;
if (!ans) return NULL;
// fontconfig returns a completely random font if the base descriptor
// points to a font that fontconfig hasnt indexed, for example the builting
// NERD font
PyObject *new_path = PyDict_GetItemString(ans, "path");
if (!new_path || PyObject_RichCompareBool(p, new_path, Py_EQ) != 1) { Py_CLEAR(ans); ans = PyDict_Copy(base_descriptor); if (!ans) return NULL; }
if (face_idx > 0) {
// For some reason FcFontMatch sets the index to zero, so manually restore it.
@@ -538,6 +544,7 @@ set_builtin_nerd_font(PyObject UNUSED *self, PyObject *pypath) {
copy(hinting); copy(hint_style);
#undef copy
if (PyDict_SetItemString(builtin_nerd_font.descriptor, "path", pypath) != 0) goto end;
if (PyDict_SetItemString(builtin_nerd_font.descriptor, "index", PyLong_FromLong(0)) != 0) goto end;
}
end:
if (pat) FcPatternDestroy(pat);
@@ -546,7 +553,8 @@ end:
Py_CLEAR(builtin_nerd_font.descriptor);
return NULL;
}
Py_RETURN_NONE;
Py_INCREF(builtin_nerd_font.descriptor);
return builtin_nerd_font.descriptor;
}

View File

@@ -31,6 +31,7 @@ from kitty.types import _T
from kitty.typing import CoreTextFont, FontConfigPattern
from kitty.utils import log_error
from . import family_name_to_key
from .common import get_font_files
if is_macos:
@@ -40,6 +41,7 @@ else:
FontObject = Union[CoreTextFont, FontConfigPattern]
current_faces: List[Tuple[FontObject, bool, bool]] = []
builtin_nerd_font_descriptor: Optional[FontObject] = None
def font_for_family(family: str) -> Tuple[FontObject, bool, bool]:
@@ -145,6 +147,10 @@ def create_symbol_map(opts: Options) -> Tuple[Tuple[int, int, int], ...]:
for family in val.values():
if family not in family_map:
font, bold, italic = font_for_family(family)
fkey = family_name_to_key(family)
if fkey in ('symbolsnfm', 'symbols nerd font mono') and font['postscript_name'] != 'SymbolsNFM' and builtin_nerd_font_descriptor:
font = builtin_nerd_font_descriptor
bold = italic = False
family_map[family] = count
count += 1
current_faces.append((font, bold, italic))
@@ -172,8 +178,8 @@ def dump_font_debug() -> None:
log_error(' ' + s.identify_for_debug())
def set_font_family(opts: Optional[Options] = None, override_font_size: Optional[float] = None) -> None:
global current_faces
def set_font_family(opts: Optional[Options] = None, override_font_size: Optional[float] = None, add_builtin_nerd_font: bool = False) -> None:
global current_faces, builtin_nerd_font_descriptor
opts = opts or defaults
sz = override_font_size or opts.font_size
font_map = get_font_files(opts)
@@ -185,6 +191,12 @@ def set_font_family(opts: Optional[Options] = None, override_font_size: Optional
indices[k] = len(current_faces)
current_faces.append((font_map[k], 'b' in k, 'i' in k))
before = len(current_faces)
if add_builtin_nerd_font:
builtin_nerd_font_path = os.path.join(fonts_dir, 'SymbolsNerdFontMono-Regular.ttf')
if os.path.exists(builtin_nerd_font_path):
builtin_nerd_font_descriptor = set_builtin_nerd_font(builtin_nerd_font_path)
else:
log_error(f'No builtin NERD font found in {fonts_dir}')
sm = create_symbol_map(opts)
ns = create_narrow_symbols(opts)
num_symbol_fonts = len(current_faces) - before
@@ -195,15 +207,6 @@ def set_font_family(opts: Optional[Options] = None, override_font_size: Optional
)
def add_application_fonts() -> None:
for font in ('SymbolsNerdFontMono-Regular.ttf',):
path = os.path.join(fonts_dir, font)
if os.path.exists(path):
set_builtin_nerd_font(path)
else:
log_error(f'No builtin NERD font found in {fonts_dir}')
if TYPE_CHECKING:
CBufType = ctypes.Array[ctypes.c_ubyte]
else:

View File

@@ -44,7 +44,7 @@ from .fast_data_types import (
set_options,
)
from .fonts.box_drawing import set_scale
from .fonts.render import add_application_fonts, dump_font_debug, set_font_family
from .fonts.render import dump_font_debug, set_font_family
from .options.types import Options
from .options.utils import DELETE_ENV_VAR
from .os_window_size import edge_spacing, initial_window_size_func
@@ -248,8 +248,7 @@ class AppRunner:
set_scale(opts.box_drawing_scale)
set_options(opts, is_wayland(), args.debug_rendering, args.debug_font_fallback)
try:
set_font_family(opts)
add_application_fonts()
set_font_family(opts, add_builtin_nerd_font=True)
_run_app(opts, args, bad_lines, talk_fd)
finally:
set_options(None)