From ca6010789e26685d2b19a5a960fc7311fab64856 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Fri, 18 Sep 2020 07:40:30 +0530 Subject: [PATCH] Fix a memory leak when changing font sizes had forgotten to free unused font groups --- docs/changelog.rst | 2 ++ kitty/fonts.c | 71 +++++++++++++++++++++++----------------------- 2 files changed, 38 insertions(+), 35 deletions(-) diff --git a/docs/changelog.rst b/docs/changelog.rst index 2b01cb6aa..917ef5223 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -59,6 +59,8 @@ To update |kitty|, :doc:`follow the instructions `. - Fix a regression that broke the ``move_window_to_top`` action (:pull:`2953`) +- Fix a memory leak when changing font sizes + 0.18.3 [2020-08-11] ------------------- diff --git a/kitty/fonts.c b/kitty/fonts.c index 9869482c3..dad465aaa 100644 --- a/kitty/fonts.c +++ b/kitty/fonts.c @@ -130,12 +130,48 @@ font_group_is_unused(FontGroup *fg) { return true; } +void +free_maps(Font *font) { +#define free_a_map(type, attr) {\ + type *s, *t; \ + for (size_t i = 0; i < sizeof(font->attr)/sizeof(font->attr[0]); i++) { \ + s = font->attr[i].next; \ + while (s) { \ + t = s; \ + s = s->next; \ + free(t); \ + } \ + }\ + memset(font->attr, 0, sizeof(font->attr)); \ +} + free_a_map(SpritePosition, sprite_map); + free_a_map(SpecialGlyphCache, special_glyph_cache); +#undef free_a_map +} + +static inline void +del_font(Font *f) { + Py_CLEAR(f->face); + free(f->ffs_hb_features); f->ffs_hb_features = NULL; + free_maps(f); + f->bold = false; f->italic = false; +} + +static inline void +del_font_group(FontGroup *fg) { + free(fg->canvas); fg->canvas = NULL; + fg->sprite_map = free_sprite_map(fg->sprite_map); + for (size_t i = 0; i < fg->fonts_count; i++) del_font(fg->fonts + i); + free(fg->fonts); fg->fonts = NULL; +} + static inline void trim_unused_font_groups(void) { save_window_font_groups(); size_t i = 0; while (i < num_font_groups) { if (font_group_is_unused(font_groups + i)) { + del_font_group(font_groups + i); size_t num_to_right = (--num_font_groups) - i; if (!num_to_right) break; memmove(font_groups + i, font_groups + 1 + i, num_to_right * sizeof(FontGroup)); @@ -282,25 +318,6 @@ sprite_tracker_current_layout(FONTS_DATA_HANDLE data, unsigned int *x, unsigned *x = fg->sprite_tracker.xnum; *y = fg->sprite_tracker.ynum; *z = fg->sprite_tracker.z; } -void -free_maps(Font *font) { -#define free_a_map(type, attr) {\ - type *s, *t; \ - for (size_t i = 0; i < sizeof(font->attr)/sizeof(font->attr[0]); i++) { \ - s = font->attr[i].next; \ - while (s) { \ - t = s; \ - s = s->next; \ - free(t); \ - } \ - }\ - memset(font->attr, 0, sizeof(font->attr)); \ -} - free_a_map(SpritePosition, sprite_map); - free_a_map(SpecialGlyphCache, special_glyph_cache); -#undef free_a_map -} - void clear_sprite_map(Font *font) { #define CLEAR(s) s->filled = false; s->rendered = false; s->colored = false; s->glyph = 0; zero_at_ptr(&s->extra_glyphs); s->x = 0; s->y = 0; s->z = 0; s->ligature_index = 0; @@ -384,22 +401,6 @@ init_font(Font *f, PyObject *face, bool bold, bool italic, bool emoji_presentati return true; } -static inline void -del_font(Font *f) { - Py_CLEAR(f->face); - free(f->ffs_hb_features); f->ffs_hb_features = NULL; - free_maps(f); - f->bold = false; f->italic = false; -} - -static inline void -del_font_group(FontGroup *fg) { - free(fg->canvas); fg->canvas = NULL; - fg->sprite_map = free_sprite_map(fg->sprite_map); - for (size_t i = 0; i < fg->fonts_count; i++) del_font(fg->fonts + i); - free(fg->fonts); fg->fonts = NULL; -} - static inline void free_font_groups(void) { if (font_groups) {