macOS: Fix a character that cannot be rendered in any font causing font fallback for all subsequent characters that cannot be rendered in the main font to fail
Fixes #799
This commit is contained in:
@@ -6,6 +6,10 @@ Changelog
|
|||||||
0.12.1 [future]
|
0.12.1 [future]
|
||||||
------------------------------
|
------------------------------
|
||||||
|
|
||||||
|
- macOS: Fix a character that cannot be rendered in any font causing
|
||||||
|
font fallback for all subsequent characters that cannot be rendered in the
|
||||||
|
main font to fail (:iss:`799`)
|
||||||
|
|
||||||
- Allow mapping shortcuts using the raw key code from the OS (:iss:`848`)
|
- Allow mapping shortcuts using the raw key code from the OS (:iss:`848`)
|
||||||
|
|
||||||
- Allow mapping of individual keypresses without modifiers as shortcuts
|
- Allow mapping of individual keypresses without modifiers as shortcuts
|
||||||
|
|||||||
@@ -171,6 +171,14 @@ find_substitute_face(CFStringRef str, CTFontRef old_font) {
|
|||||||
else start++;
|
else start++;
|
||||||
if (new_font == NULL) { PyErr_SetString(PyExc_ValueError, "Failed to find fallback CTFont"); return NULL; }
|
if (new_font == NULL) { PyErr_SetString(PyExc_ValueError, "Failed to find fallback CTFont"); return NULL; }
|
||||||
if (new_font == old_font) { CFRelease(new_font); continue; }
|
if (new_font == old_font) { CFRelease(new_font); continue; }
|
||||||
|
CFStringRef name = CTFontCopyPostScriptName(new_font);
|
||||||
|
CFComparisonResult cr = CFStringCompare(name, CFSTR("LastResort"), 0);
|
||||||
|
CFRelease(name);
|
||||||
|
if (cr == kCFCompareEqualTo) {
|
||||||
|
CFRelease(new_font);
|
||||||
|
PyErr_SetString(PyExc_ValueError, "Failed to find fallback CTFont other than the LastResort font");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
return new_font;
|
return new_font;
|
||||||
}
|
}
|
||||||
PyErr_SetString(PyExc_ValueError, "CoreText returned the same font as a fallback font");
|
PyErr_SetString(PyExc_ValueError, "CoreText returned the same font as a fallback font");
|
||||||
|
|||||||
@@ -1280,6 +1280,7 @@ get_fallback_font(PyObject UNUSED *self, PyObject *args) {
|
|||||||
if (italic) gpu_cell.attrs |= 1 << ITALIC_SHIFT;
|
if (italic) gpu_cell.attrs |= 1 << ITALIC_SHIFT;
|
||||||
FontGroup *fg = font_groups;
|
FontGroup *fg = font_groups;
|
||||||
ssize_t ans = fallback_font(fg, &cpu_cell, &gpu_cell);
|
ssize_t ans = fallback_font(fg, &cpu_cell, &gpu_cell);
|
||||||
|
if (ans == MISSING_FONT) { PyErr_SetString(PyExc_ValueError, "No fallback font found"); return NULL; }
|
||||||
if (ans < 0) { PyErr_SetString(PyExc_ValueError, "Too many fallback fonts"); return NULL; }
|
if (ans < 0) { PyErr_SetString(PyExc_ValueError, "Too many fallback fonts"); return NULL; }
|
||||||
return fg->fonts[ans].face;
|
return fg->fonts[ans].face;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,10 +2,13 @@
|
|||||||
# vim:fileencoding=utf-8
|
# vim:fileencoding=utf-8
|
||||||
# License: GPL v3 Copyright: 2017, Kovid Goyal <kovid at kovidgoyal.net>
|
# License: GPL v3 Copyright: 2017, Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import unittest
|
||||||
|
|
||||||
from kitty.constants import is_macos
|
from kitty.constants import is_macos
|
||||||
from kitty.fast_data_types import (
|
from kitty.fast_data_types import (
|
||||||
DECAWM, sprite_map_set_layout, sprite_map_set_limits, test_render_line,
|
DECAWM, get_fallback_font, sprite_map_set_layout, sprite_map_set_limits,
|
||||||
test_sprite_position_for, wcwidth
|
test_render_line, test_sprite_position_for, wcwidth
|
||||||
)
|
)
|
||||||
from kitty.fonts.box_drawing import box_chars
|
from kitty.fonts.box_drawing import box_chars
|
||||||
from kitty.fonts.render import render_string, setup_for_testing, shape_string
|
from kitty.fonts.render import render_string, setup_for_testing, shape_string
|
||||||
@@ -106,3 +109,16 @@ class Rendering(BaseTest):
|
|||||||
s.draw('\ufe0f')
|
s.draw('\ufe0f')
|
||||||
self.ae((s.cursor.x, s.cursor.y), (2, 4))
|
self.ae((s.cursor.x, s.cursor.y), (2, 4))
|
||||||
self.ae(str(s.line(s.cursor.y)), '\u2716\ufe0f')
|
self.ae(str(s.line(s.cursor.y)), '\u2716\ufe0f')
|
||||||
|
|
||||||
|
@unittest.skipUnless(is_macos, 'Only macOS has a Last Resort font')
|
||||||
|
def test_fallback_font_not_last_resort(self):
|
||||||
|
# Ensure that the LastResort font is not reported as a fallback font on
|
||||||
|
# macOS. See https://github.com/kovidgoyal/kitty/issues/799
|
||||||
|
from io import StringIO
|
||||||
|
orig, buf = sys.stderr, StringIO()
|
||||||
|
sys.stderr = buf
|
||||||
|
try:
|
||||||
|
self.assertRaises(ValueError, get_fallback_font, '\U0010FFFF', False, False)
|
||||||
|
finally:
|
||||||
|
sys.stderr = orig
|
||||||
|
self.assertIn('LastResort', buf.getvalue())
|
||||||
|
|||||||
Reference in New Issue
Block a user