summaryrefslogtreecommitdiff
path: root/src/gui/font.h
blob: db964fb0ab3b78571cd603ea6f1b07978cf219ad (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
// 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 <stddef.h>
#include <stdint.h>

#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