mirror of
https://github.com/kovidgoyal/kitty
synced 2026-07-25 01:38:02 +02:00
macOS: When CoreText fails to find a fallback font for a character in the first Private Use Unicode Area, preferentially use the NERD font, if available, for it
Fixes #6043
This commit is contained in:
@@ -56,6 +56,9 @@ Detailed list of changes
|
|||||||
|
|
||||||
- macOS: Fix text rendered with fallback fonts not respecting bold/italic styling (:disc:`7241`)
|
- macOS: Fix text rendered with fallback fonts not respecting bold/italic styling (:disc:`7241`)
|
||||||
|
|
||||||
|
- macOS: When CoreText fails to find a fallback font for a character in the first Private Use Unicode Area, preferentially use the NERD font, if available, for it (:iss:`6043`)
|
||||||
|
|
||||||
|
|
||||||
0.33.0 [2024-03-12]
|
0.33.0 [2024-03-12]
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
|||||||
@@ -184,12 +184,17 @@ glyph_id_for_codepoint_ctfont(CTFontRef ct_font, char_type ch) {
|
|||||||
return glyphs[0];
|
return glyphs[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
cf_string_equals(CFStringRef a, CFStringRef b) { return CFStringCompare(a, b, 0) == kCFCompareEqualTo; }
|
||||||
|
|
||||||
|
#define LAST_RESORT_FONT_NAME "LastResort"
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
is_last_resort_font(CTFontRef new_font) {
|
is_last_resort_font(CTFontRef new_font) {
|
||||||
CFStringRef name = CTFontCopyPostScriptName(new_font);
|
CFStringRef name = CTFontCopyPostScriptName(new_font);
|
||||||
CFComparisonResult cr = CFStringCompare(name, CFSTR("LastResort"), 0);
|
bool ans = cf_string_equals(name, CFSTR(LAST_RESORT_FONT_NAME));
|
||||||
CFRelease(name);
|
CFRelease(name);
|
||||||
return cr == kCFCompareEqualTo;
|
return ans;
|
||||||
}
|
}
|
||||||
|
|
||||||
static CTFontRef
|
static CTFontRef
|
||||||
@@ -197,26 +202,29 @@ manually_search_fallback_fonts(CTFontRef current_font, CPUCell *cell) {
|
|||||||
CFArrayRef fonts = CTFontCollectionCreateMatchingFontDescriptors(all_fonts_collection());
|
CFArrayRef fonts = CTFontCollectionCreateMatchingFontDescriptors(all_fonts_collection());
|
||||||
CTFontRef ans = NULL;
|
CTFontRef ans = NULL;
|
||||||
const CFIndex count = CFArrayGetCount(fonts);
|
const CFIndex count = CFArrayGetCount(fonts);
|
||||||
|
char_type ch = cell->ch ? cell->ch : ' ';
|
||||||
|
bool in_first_pua = 0xe000 <= ch && ch <= 0xf8ff;
|
||||||
|
// preferentially load from NERD fonts
|
||||||
for (CFIndex i = 0; i < count; i++) {
|
for (CFIndex i = 0; i < count; i++) {
|
||||||
CTFontDescriptorRef descriptor = (CTFontDescriptorRef)CFArrayGetValueAtIndex(fonts, i);
|
CTFontDescriptorRef descriptor = (CTFontDescriptorRef)CFArrayGetValueAtIndex(fonts, i);
|
||||||
|
CFStringRef name = CTFontDescriptorCopyAttribute(descriptor, kCTFontNameAttribute);
|
||||||
|
bool is_last_resort_font = cf_string_equals(name, CFSTR(LAST_RESORT_FONT_NAME));
|
||||||
|
bool is_nerd_font = cf_string_equals(name, CFSTR("SymbolsNFM"));
|
||||||
|
CFRelease(name);
|
||||||
|
if (is_last_resort_font) continue;
|
||||||
CTFontRef new_font = CTFontCreateWithFontDescriptor(descriptor, CTFontGetSize(current_font), NULL);
|
CTFontRef new_font = CTFontCreateWithFontDescriptor(descriptor, CTFontGetSize(current_font), NULL);
|
||||||
if (new_font) {
|
bool found = true;
|
||||||
if (!is_last_resort_font(new_font)) {
|
if (!glyph_id_for_codepoint_ctfont(new_font, ch)) found = false;
|
||||||
char_type ch = cell->ch ? cell->ch : ' ';
|
for (unsigned i = 0; i < arraysz(cell->cc_idx) && cell->cc_idx[i] && found; i++) {
|
||||||
bool found = true;
|
char_type cch = codepoint_for_mark(cell->cc_idx[i]);
|
||||||
if (!glyph_id_for_codepoint_ctfont(new_font, ch)) found = false;
|
if (!glyph_id_for_codepoint_ctfont(new_font, cch)) found = false;
|
||||||
for (unsigned i = 0; i < arraysz(cell->cc_idx) && cell->cc_idx[i] && found; i++) {
|
|
||||||
ch = codepoint_for_mark(cell->cc_idx[i]);
|
|
||||||
if (!glyph_id_for_codepoint_ctfont(new_font, ch)) found = false;
|
|
||||||
}
|
|
||||||
if (found) {
|
|
||||||
ans = new_font;
|
|
||||||
if (global_state.debug_font_fallback) fprintf(stderr, "Manually found fallback font.\n");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
CFRelease(new_font);
|
|
||||||
}
|
}
|
||||||
|
if (found) {
|
||||||
|
// preferentially use NERD font for glyphs in first PUA
|
||||||
|
if (!ans || is_nerd_font) { if (ans) CFRelease(ans); ans = new_font; CFRetain(ans); }
|
||||||
|
if (is_nerd_font || !in_first_pua) break;
|
||||||
|
}
|
||||||
|
CFRelease(new_font);
|
||||||
}
|
}
|
||||||
CFRelease(fonts);
|
CFRelease(fonts);
|
||||||
return ans;
|
return ans;
|
||||||
@@ -241,7 +249,7 @@ find_substitute_face(CFStringRef str, CTFontRef old_font, CPUCell *cpu_cell) {
|
|||||||
new_font = manually_search_fallback_fonts(old_font, cpu_cell);
|
new_font = manually_search_fallback_fonts(old_font, cpu_cell);
|
||||||
if (new_font) return new_font;
|
if (new_font) return new_font;
|
||||||
}
|
}
|
||||||
PyErr_Format(PyExc_ValueError, "Failed to find fallback CTFont other than the LastResort font for: %s", [(NSString *)str UTF8String]);
|
PyErr_Format(PyExc_ValueError, "Failed to find fallback CTFont other than the %s font for: %s", LAST_RESORT_FONT_NAME, [(NSString *)str UTF8String]);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
return new_font;
|
return new_font;
|
||||||
|
|||||||
Reference in New Issue
Block a user