From 8d03d7216f77b4dc5069f7aebe22ee9d0cc4c30e Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Fri, 29 Sep 2017 11:57:17 +0530 Subject: [PATCH] Do not crash when failing to render a glyph, instead render the missing glyph and print an error msg to stderr --- kitty/fonts/freetype.py | 5 ++++- kitty/freetype.c | 12 ++++++++---- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/kitty/fonts/freetype.py b/kitty/fonts/freetype.py index 2f3051855..e61ba6f3b 100644 --- a/kitty/fonts/freetype.py +++ b/kitty/fonts/freetype.py @@ -8,7 +8,7 @@ from collections import namedtuple from functools import lru_cache from itertools import chain -from kitty.fast_data_types import FT_PIXEL_MODE_GRAY, Face +from kitty.fast_data_types import FT_PIXEL_MODE_GRAY, Face, FreeTypeError from kitty.fonts.box_drawing import render_missing_glyph from kitty.utils import ceil_int, get_logical_dpi, safe_print, wcwidth, adjust_line_height @@ -258,6 +258,9 @@ def render_cell(text=' ', bold=False, italic=False): except FontNotFound as err: safe_print('ERROR:', err, file=sys.stderr) return missing_glyph(width) + except FreeTypeError as err: + safe_print('Failed to render text:', repr(text), 'with error:', err, file=sys.stderr) + return missing_glyph(width) second = None if width == 2: if bitmap_char.columns > cell_width: diff --git a/kitty/freetype.c b/kitty/freetype.c index 6cb918310..d6a7bc7c8 100644 --- a/kitty/freetype.c +++ b/kitty/freetype.c @@ -18,6 +18,7 @@ typedef struct { bool is_scalable; } Face; +static PyObject* FreeType_Exception = NULL; void set_freetype_error(const char* prefix, int err_code) { @@ -41,12 +42,12 @@ set_freetype_error(const char* prefix, int err_code) { while(ft_errors[i].err_msg != NULL) { if (ft_errors[i].err_code == err_code) { - PyErr_Format(PyExc_ValueError, "%s %s", prefix, ft_errors[i].err_msg); + PyErr_Format(FreeType_Exception, "%s %s", prefix, ft_errors[i].err_msg); return; } i++; } - PyErr_Format(PyExc_ValueError, "%s (error code: %d)", prefix, err_code); + PyErr_Format(FreeType_Exception, "%s (error code: %d)", prefix, err_code); } static FT_Library library; @@ -190,7 +191,7 @@ trim_to_width(Face UNUSED *self, PyObject *args) { rows = PyLong_AsUnsignedLong(PyStructSequence_GET_ITEM(bitmap, 0)); width = PyLong_AsUnsignedLong(PyStructSequence_GET_ITEM(bitmap, 1)); extra = width - cell_width; - if (extra >= cell_width) { PyErr_SetString(PyExc_ValueError, "Too large for trimming"); return NULL; } + if (extra >= cell_width) { PyErr_SetString(FreeType_Exception, "Too large for trimming"); return NULL; } PyObject *ans = PyStructSequence_New(&BitmapType); if (ans == NULL) return PyErr_NoMemory(); src = (unsigned char*)PyByteArray_AS_STRING(PyStructSequence_GET_ITEM(bitmap, 3)); @@ -267,13 +268,16 @@ free_freetype() { bool init_freetype_library(PyObject *m) { + FreeType_Exception = PyErr_NewException("fast_data_types.FreeTypeError", NULL, NULL); + if (FreeType_Exception == NULL) return false; + if (PyModule_AddObject(m, "FreeTypeError", FreeType_Exception) != 0) return false; int error = FT_Init_FreeType(&library); if (error) { set_freetype_error("Failed to initialize FreeType library, with error:", error); return false; } if (Py_AtExit(free_freetype) != 0) { - PyErr_SetString(PyExc_RuntimeError, "Failed to register the freetype library at exit handler"); + PyErr_SetString(FreeType_Exception, "Failed to register the freetype library at exit handler"); return false; } if (PyStructSequence_InitType2(&GlpyhMetricsType, &gm_desc) != 0) return false;