// Tiny C shim over FreeType and HarfBuzz, so gui.zig only imports the stable // renderer API. The implementation owns FreeType's library and face objects // and HarfBuzz's font and buffer, and keeps the caller's font bytes borrowed // for the face lifetime. #ifndef UI_FONT_H #define UI_FONT_H #include #include #ifdef __cplusplus extern "C" { #endif typedef struct UIFont UIFont; // Every allocation FreeType, HarfBuzz and this shim make: C's malloc, calloc, // realloc and free, implemented by gui.zig over a Zig allocator. HarfBuzz is // compiled to call them (hb_malloc_impl and friends); FreeType gets them as // each library's memory manager. void *ui_malloc(size_t size); void *ui_calloc(size_t count, size_t size); void *ui_realloc(void *block, size_t size); void ui_free(void *block); // Parse the first face in an in-memory font. `data` must stay alive for the // lifetime of the font. Returns NULL on failure. UIFont *ui_font_new(const uint8_t *data, int32_t len); // The face FreeType actually accepted. Prefer its PostScript name (the same // identity the macOS shell reports); fall back to the family name when the // font has no PostScript table. Borrowed for the UIFont lifetime. const char *ui_font_name(UIFont *f); // The glyph the selected Unicode charmap maps `cp` to. Glyph zero is the // face's .notdef box: the codepoint is missing, which is what fallback choice // asks. uint32_t ui_font_glyph(UIFont *f, int32_t cp); // `px` is the pixel height. Metrics and rasterization both configure FreeType // at that size, so hinted advances, baseline and bitmaps stay in step. void ui_font_cell_metrics(UIFont *f, float px, int32_t *cell_w, int32_t *cell_h, int32_t *ascent); // What one grid cell draws: `slice` of the glyph `glyph` rasterized across // `span` cells with its own cell `lead` cells from the left. A plain cell is // its own glyph, lead 0, span 1, slice 0. typedef struct { uint32_t glyph; uint8_t lead; uint8_t span; uint8_t slice; } UIShapedCell; // The longest glyph strip a ligature may claim, in cells. #define UI_MAX_SPAN 8 // Whether a lookup of the font's ligature features (liga, calt, clig, rlig, // rclt) could replace `glyph`. When it cannot, shaping leaves the glyph alone // and its cell needs no shaping at all. int ui_font_substitutes(UIFont *f, uint32_t glyph); // One cell per codepoint of `cps`, all in this face, shaped by HarfBuzz with // the font's ligature features (a run with no glyph ui_font_substitutes // reports comes back nominal without it). A substituted glyph whose ink // reaches over neighbouring cells that draw nothing of their own (a // ligature's spacers, or the cells a merged cluster swallowed) claims them as // a strip. Otherwise, and for anything the grid cannot place (several glyphs // in one cell, positioned marks), each cell is its nominal glyph. void ui_font_shape(UIFont *f, float px, int32_t cell_w, const uint32_t *cps, int32_t n, UIShapedCell *out); // Rasterize `glyph` into `out` as a hinted grayscale mask of `width` x // `height` (`stride` bytes per row). The glyph's advance is centered in the // `cell_w` pixels that start at `cell_x`, and its baseline is `ascent` pixels // from the top; ink outside the mask is clipped. `bold` emboldens the outline // before rendering (synthetic bold, same advance). Returns 1 when the glyph // produced coverage, 0 for blank/error. int ui_font_raster(UIFont *f, float px, uint32_t glyph, int bold, uint8_t *out, int32_t stride, int32_t width, int32_t height, int32_t cell_x, int32_t cell_w, int32_t ascent); // Center bitmap ink bounds, independent of advance and baseline bearings. int ui_font_raster_centered(UIFont *f, float px, uint32_t glyph, int bold, uint8_t *out, int32_t stride, int32_t width, int32_t height); void ui_font_free(UIFont *f); // HarfBuzz makes a few process-wide objects on first use and keeps them for // the life of the process (the default Unicode functions, the locale's // language, hb-ft's font functions). Making them here, with `f`'s face, lets // the caller hand them an allocator that does not count them as leaks. void ui_font_prime(UIFont *f); #ifdef __cplusplus } #endif #endif