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
|
// stb_truetype wrapper for ui_sdl.zig. See font.h. Compiled into the SDL UI
// backend module alongside stb_truetype_impl.c (which defines the impl).
#include "font.h"
#include "stb_truetype.h"
#include <stdlib.h>
#include <string.h>
struct UIFont {
stbtt_fontinfo info;
const uint8_t *data;
};
UIFont *ui_font_new(const uint8_t *data, int32_t len) {
if (!data || len <= 0) return NULL;
UIFont *f = (UIFont *)calloc(1, sizeof(UIFont));
if (!f) return NULL;
f->data = data;
int offset = stbtt_GetFontOffsetForIndex(data, 0);
if (offset < 0 || !stbtt_InitFont(&f->info, (const unsigned char *)data, offset)) {
free(f);
return NULL;
}
return f;
}
void ui_font_free(UIFont *f) {
free(f);
}
float ui_font_scale_for_height(UIFont *f, float px) {
return stbtt_ScaleForPixelHeight(&f->info, px);
}
void ui_font_cell_metrics(UIFont *f, float scale, int32_t *cell_w, int32_t *cell_h, int32_t *ascent) {
int asc = 0, desc = 0, gap = 0;
stbtt_GetFontVMetrics(&f->info, &asc, &desc, &gap);
int a = (int)(asc * scale + 0.5f);
int d = (int)(-desc * scale + 0.5f);
int g = (int)(gap * scale + 0.5f);
*ascent = a;
*cell_h = a + d + g;
if (*cell_h < 1) *cell_h = 1;
// monospace advance of 'M'
int adv = 0, lsb = 0;
stbtt_GetCodepointHMetrics(&f->info, 'M', &adv, &lsb);
int w = (int)(adv * scale + 0.5f);
if (w < 1) w = 1;
*cell_w = w;
}
int ui_font_raster(UIFont *f, float scale, int32_t cp,
uint8_t *out, int32_t stride, int32_t cell_w, int32_t cell_h,
int32_t ascent) {
if (!out || cell_w <= 0 || cell_h <= 0) return 0;
// zero the cell
for (int y = 0; y < cell_h; y++)
memset(out + (size_t)y * stride, 0, (size_t)cell_w);
int w = 0, h = 0, xoff = 0, yoff = 0;
unsigned char *bm = stbtt_GetCodepointBitmap(&f->info, scale, scale, cp, &w, &h, &xoff, &yoff);
if (!bm || w <= 0 || h <= 0) {
if (bm) stbtt_FreeBitmap(bm, NULL);
return 0;
}
// origin = (0, baseline=ascent); glyph top-left = (xoff, ascent + yoff).
int gx = xoff;
int gy = ascent + yoff;
for (int y = 0; y < h; y++) {
int dy = gy + y;
if (dy < 0 || dy >= cell_h) continue;
for (int x = 0; x < w; x++) {
int dx = gx + x;
if (dx < 0 || dx >= cell_w) continue;
uint8_t v = bm[y * w + x];
if (v) out[(size_t)dy * stride + dx] = v;
}
}
stbtt_FreeBitmap(bm, NULL);
return 1;
}
|