diff options
Diffstat (limited to 'src/gui/font.c')
| -rw-r--r-- | src/gui/font.c | 59 |
1 files changed, 47 insertions, 12 deletions
diff --git a/src/gui/font.c b/src/gui/font.c index 5cb98e1a..aebe26e6 100644 --- a/src/gui/font.c +++ b/src/gui/font.c @@ -6,14 +6,17 @@ #include "font.h" #include <freetype-zig.h> #include <freetype/ftbitmap.h> +#include <freetype/ftmodapi.h> #include <hb-ft.h> #include <hb-ot.h> #include <hb.h> -#include <stdlib.h> #include <string.h> struct UIFont { + // FreeType allocates through ui_malloc and friends: the library holds a + // pointer to this for its lifetime, which the UIFont outlives. + struct FT_MemoryRec_ memory; FT_Library library; FT_Face face; FT_F26Dot6 size; @@ -60,20 +63,42 @@ static FT_Int32 load_flags(void) { return FT_LOAD_DEFAULT | FT_LOAD_TARGET_LIGHT; } +static void *ft_alloc(FT_Memory memory, long size) { + (void)memory; + return ui_malloc((size_t)size); +} + +static void ft_free(FT_Memory memory, void *block) { + (void)memory; + ui_free(block); +} + +static void *ft_realloc(FT_Memory memory, long cur_size, long new_size, + void *block) { + (void)memory; + (void)cur_size; + return ui_realloc(block, (size_t)new_size); +} + UIFont *ui_font_new(const uint8_t *data, int32_t len) { if (!data || len <= 0) return NULL; - UIFont *f = (UIFont *)calloc(1, sizeof(UIFont)); + UIFont *f = (UIFont *)ui_calloc(1, sizeof(UIFont)); if (!f) return NULL; - if (FT_Init_FreeType(&f->library) != 0) { - free(f); + // FT_Init_FreeType is exactly FT_New_Library over FT_New_Memory's malloc + // manager, then the default modules and properties: the same, over ours. + f->memory = (struct FT_MemoryRec_){NULL, ft_alloc, ft_free, ft_realloc}; + if (FT_New_Library(&f->memory, &f->library) != 0) { + ui_free(f); return NULL; } + FT_Add_Default_Modules(f->library); + FT_Set_Default_Properties(f->library); if (FT_New_Memory_Face(f->library, data, (FT_Long)len, 0, &f->face) != 0) { - FT_Done_FreeType(f->library); - free(f); + FT_Done_Library(f->library); + ui_free(f); return NULL; } // Some symbol fonts do not expose a Unicode charmap. FreeType already @@ -136,10 +161,20 @@ void ui_font_free(UIFont *f) { if (f->face) FT_Done_Face(f->face); if (f->library) - FT_Done_FreeType(f->library); - free(f->own); - free(f->state); - free(f); + FT_Done_Library(f->library); + ui_free(f->own); + ui_free(f->state); + ui_free(f); +} + +void ui_font_prime(UIFont *f) { + if (!f) + return; + hb_font_destroy(hb_ft_font_create_referenced(f->face)); + hb_buffer_t *buffer = hb_buffer_create(); + hb_buffer_add_utf8(buffer, "a", 1, 0, 1); + hb_buffer_guess_segment_properties(buffer); + hb_buffer_destroy(buffer); } void ui_font_cell_metrics(UIFont *f, float px, int32_t *cell_w, int32_t *cell_h, @@ -325,11 +360,11 @@ void ui_font_shape(UIFont *f, float px, int32_t cell_w, const uint32_t *cps, if (!substitutable || cell_w <= 0 || !set_size(f, px)) return; if (n > f->scratch) { - uint32_t *own = (uint32_t *)realloc(f->own, (size_t)n * sizeof *own); + uint32_t *own = (uint32_t *)ui_realloc(f->own, (size_t)n * sizeof *own); if (!own) return; f->own = own; - uint8_t *state = (uint8_t *)realloc(f->state, (size_t)n); + uint8_t *state = (uint8_t *)ui_realloc(f->state, (size_t)n); if (!state) return; f->state = state; |
