From 752fcb64241bc1cc2b40e1b44d6f04a89967dd62 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Wed, 20 Mar 2024 18:23:09 +0530 Subject: [PATCH] macOS: Fix text rendered with fallback fonts not respecting bold/italic styling --- docs/changelog.rst | 2 ++ kitty/core_text.m | 30 +++++++++++++++++++++++------- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/docs/changelog.rst b/docs/changelog.rst index 22e31e920..dab909f38 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -54,6 +54,8 @@ Detailed list of changes - Splits layout: Allow resizing until one of the halves in a split is minimally sized (:iss:`7220`) +- macOS: Fix text rendered with fallback fonts not respecting bold/italic styling (:disc:`7241`) + 0.33.0 [2024-03-12] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/kitty/core_text.m b/kitty/core_text.m index 36b53be74..51403d7ed 100644 --- a/kitty/core_text.m +++ b/kitty/core_text.m @@ -249,8 +249,26 @@ find_substitute_face(CFStringRef str, CTFontRef old_font, CPUCell *cpu_cell) { return NULL; } +static CTFontRef +apply_styles_to_fallback_font(CTFontRef original_fallback_font, bool bold, bool italic) { + if (!original_fallback_font || is_last_resort_font(original_fallback_font)) return original_fallback_font; + CTFontRef ans = nil; + CTFontDescriptorRef original_descriptor = CTFontCopyFontDescriptor(original_fallback_font); + CTFontSymbolicTraits traits = kCTFontTraitMonoSpace; + if (bold) traits |= kCTFontTraitBold; + if (italic) traits |= kCTFontTraitItalic; + CTFontDescriptorRef descriptor = CTFontDescriptorCreateCopyWithSymbolicTraits(original_descriptor, traits, traits); + CFRelease(original_descriptor); + if (descriptor) { + ans = CTFontCreateWithFontDescriptor(descriptor, CTFontGetSize(original_fallback_font), NULL); + CFRelease(descriptor); + } + if (ans) { CFRelease(original_fallback_font); return ans; } + return original_fallback_font; +} + PyObject* -create_fallback_face(PyObject *base_face, CPUCell* cell, bool UNUSED bold, bool UNUSED italic, bool emoji_presentation, FONTS_DATA_HANDLE fg) { +create_fallback_face(PyObject *base_face, CPUCell* cell, bool bold, bool italic, bool emoji_presentation, FONTS_DATA_HANDLE fg) { CTFace *self = (CTFace*)base_face; CTFontRef new_font; #define search_for_fallback() \ @@ -268,21 +286,19 @@ create_fallback_face(PyObject *base_face, CPUCell* cell, bool UNUSED bold, bool search_for_fallback(); } } - else { search_for_fallback(); } + else { search_for_fallback(); new_font = apply_styles_to_fallback_font(new_font, bold, italic); } if (new_font == NULL) return NULL; - NSURL *url = (NSURL*)CTFontCopyAttribute(new_font, kCTFontURLAttribute); - const char *font_path = [[url path] UTF8String]; + PyObject *postscript_name = Py_BuildValue("s", convert_cfstring(CTFontCopyPostScriptName(new_font), true)); ssize_t idx = -1; PyObject *q, *ans = NULL; while ((q = iter_fallback_faces(fg, &idx))) { CTFace *qf = (CTFace*)q; - const char *qpath; - if (qf->path && (qpath = PyUnicode_AsUTF8(qf->path)) && strcmp(qpath, font_path) == 0) { + if (PyObject_RichCompareBool(postscript_name, qf->postscript_name, Py_EQ) == 1) { ans = PyLong_FromSsize_t(idx); break; } } - [url release]; + Py_CLEAR(postscript_name); if (ans == NULL) return (PyObject*)ct_face(new_font, fg); CFRelease(new_font); return ans;