summaryrefslogtreecommitdiff
path: root/src/gui/font.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/font.c')
-rw-r--r--src/gui/font.c59
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;