I can't even
This commit is contained in:
parent
805f633af0
commit
dcce0ed11b
11 changed files with 611 additions and 165 deletions
|
|
@ -25,27 +25,22 @@
|
|||
// this way the texture atlas for the font will be bigger but we save up the space
|
||||
// needed for rendering the font in multiple sizes
|
||||
|
||||
|
||||
struct font_atlas {
|
||||
unsigned int glyphs, width, height;
|
||||
unsigned char *atlas;
|
||||
|
||||
struct {
|
||||
stbtt_fontinfo stb;
|
||||
msdf_AllocCtx ctx;
|
||||
msdf_Result msdf;
|
||||
float scale;
|
||||
} priv;
|
||||
|
||||
int file_size;
|
||||
unsigned char *file;
|
||||
};
|
||||
// as of now only monospaced fonts work correctly since no kerning information is stored
|
||||
|
||||
|
||||
const unsigned int glyph_w = 32;
|
||||
const unsigned int glyph_h = 32;
|
||||
|
||||
|
||||
struct priv {
|
||||
stbtt_fontinfo stb;
|
||||
msdf_AllocCtx ctx;
|
||||
msdf_Result msdf;
|
||||
float scale;
|
||||
};
|
||||
#define PRIV(x) ((struct priv *)x->priv)
|
||||
|
||||
|
||||
// only useful for msdf_c
|
||||
static inline void * _emalloc(size_t x, void *_) { (void)_; return emalloc(x); }
|
||||
static inline void _efree(void *x, void *_) { (void)_; efree(x); }
|
||||
|
|
@ -53,7 +48,11 @@ static inline void _efree(void *x, void *_) { (void)_; efree(x); }
|
|||
|
||||
struct font_atlas * font_init(void)
|
||||
{
|
||||
return emalloc(sizeof(struct font_atlas));
|
||||
struct font_atlas *p = emalloc(sizeof(struct font_atlas));
|
||||
memset(p, 0, sizeof(struct font_atlas));
|
||||
p->priv = emalloc(sizeof(struct priv));
|
||||
memset(p->priv, 0, sizeof(struct priv));
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -67,28 +66,35 @@ int font_load(struct font_atlas *atlas, const char *path)
|
|||
|
||||
dump_file(path, &(atlas->file), &(atlas->file_size));
|
||||
|
||||
err = stbtt_InitFont(&(atlas->priv.stb), atlas->file, 0);
|
||||
err = stbtt_InitFont(&(PRIV(atlas)->stb), (unsigned char *)atlas->file, 0);
|
||||
ERROR(err == 0, -1);
|
||||
|
||||
atlas->priv.scale = stbtt_ScaleForPixelHeight(&(atlas->priv.stb), glyph_h);
|
||||
PRIV(atlas)->scale = stbtt_ScaleForPixelHeight(&(PRIV(atlas)->stb), glyph_h);
|
||||
//int ascent, descent, linegap, baseline;
|
||||
//int x0,y0,x1,y1;
|
||||
//stbtt_GetFontVMetrics(&(atlas->priv.stb), &ascent, &descent, &linegap);
|
||||
//stbtt_GetFontBoundingBox(&(atlas->priv.stb), &x0, &y0, &x1, &y1);
|
||||
//baseline = atlas->priv.scale * -y0;
|
||||
//atlas->glyph_max_w = (atlas->priv.scale*x1) - (atlas->priv.scale*x0);
|
||||
//atlas->glyph_max_h = (baseline+atlas->priv.scale*y1) - (baseline+atlas->priv.scale*y0);
|
||||
//stbtt_GetFontVMetrics(&(PRIV(atlas)->stb), &ascent, &descent, &linegap);
|
||||
//stbtt_GetFontBoundingBox(&(PRIV(atlas)->stb), &x0, &y0, &x1, &y1);
|
||||
//baseline = PRIV(atlas)->scale * -y0;
|
||||
//atlas->glyph_max_w = (PRIV(atlas)->scale*x1) - (PRIV(atlas)->scale*x0);
|
||||
//atlas->glyph_max_h = (baseline+PRIV(atlas)->scale*y1) - (baseline+PRIV(atlas)->scale*y0);
|
||||
//atlas->atlas = emalloc(atlas->glyph_max_w*atlas->glyph_max_h*CACHE_SIZE);
|
||||
|
||||
atlas->atlas = ecalloc(CACHE_SIZE, BDEPTH*glyph_h*glyph_w);
|
||||
atlas->atlas = emalloc(CACHE_SIZE*BDEPTH*glyph_h*glyph_w);
|
||||
memset(atlas->atlas, 0, CACHE_SIZE*BDEPTH*glyph_h*glyph_w);
|
||||
atlas->width = glyph_w*CACHE_SIZE/2;
|
||||
atlas->height = glyph_h*CACHE_SIZE/2;
|
||||
// FIXME: make this a square atlas
|
||||
atlas->width = glyph_w*CACHE_SIZE/4;
|
||||
atlas->height = glyph_h*4;
|
||||
|
||||
atlas->priv.ctx = (msdf_AllocCtx){_emalloc, _efree, NULL};
|
||||
PRIV(atlas)->ctx = (msdf_AllocCtx){_emalloc, _efree, NULL};
|
||||
|
||||
cache_init();
|
||||
|
||||
// preallocate all ascii characters
|
||||
for (char c = ' '; c <= '~'; c++) {
|
||||
if (!font_get_glyph_texture(atlas, c, NULL))
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -97,6 +103,7 @@ int font_free(struct font_atlas *atlas)
|
|||
{
|
||||
efree(atlas->atlas);
|
||||
efree(atlas->file);
|
||||
efree(atlas->priv);
|
||||
efree(atlas);
|
||||
cache_destroy();
|
||||
return 0;
|
||||
|
|
@ -105,33 +112,38 @@ int font_free(struct font_atlas *atlas)
|
|||
|
||||
// FIXME: when generating the sdf I only use the height, so to not encounter memory
|
||||
// errors height and width must be equal
|
||||
const struct font_glyph * font_get_glyph_texture(struct font_atlas *atlas, unsigned int code)
|
||||
const struct font_glyph * font_get_glyph_texture(struct font_atlas *atlas, unsigned int code, int *updated)
|
||||
{
|
||||
const struct font_glyph *r;
|
||||
if ((r = cache_search(code)) != NULL)
|
||||
return r;
|
||||
int u = 0;
|
||||
if (!updated) updated = &u;
|
||||
|
||||
const struct font_glyph *r;
|
||||
if ((r = cache_search(code)) != NULL) {
|
||||
*updated = 0;
|
||||
return r;
|
||||
}
|
||||
|
||||
*updated = 1;
|
||||
// generate the sdf and put it into the cache
|
||||
// TODO: generate the whole block at once
|
||||
int idx = stbtt_FindGlyphIndex(&atlas->priv.stb, code);
|
||||
int idx = stbtt_FindGlyphIndex(&PRIV(atlas)->stb, code);
|
||||
// FIXME: what happens if I change the range?
|
||||
int err;
|
||||
err = msdf_genGlyph(&atlas->priv.msdf,
|
||||
&atlas->priv.stb,
|
||||
err = msdf_genGlyph(&PRIV(atlas)->msdf,
|
||||
&PRIV(atlas)->stb,
|
||||
idx,
|
||||
BORDER,
|
||||
atlas->priv.scale,
|
||||
PRIV(atlas)->scale,
|
||||
2.0f/glyph_h,
|
||||
&atlas->priv.ctx);
|
||||
&PRIV(atlas)->ctx);
|
||||
// msdf_genGlyph returns 0 only when there are no contours, so only for
|
||||
// whitespace and such, for those insert a zero uv map into the cache
|
||||
// FIXME: this is a waste of space
|
||||
if (!err) {
|
||||
atlas->priv.msdf.width = 0;
|
||||
atlas->priv.msdf.height = 0;
|
||||
PRIV(atlas)->msdf.width = 0;
|
||||
PRIV(atlas)->msdf.height = 0;
|
||||
}
|
||||
|
||||
|
||||
unsigned int spot = cache_get();
|
||||
unsigned int oy = (glyph_h * spot) / atlas->width;
|
||||
unsigned int ox = (glyph_h * spot) % atlas->height;
|
||||
|
|
@ -139,7 +151,7 @@ const struct font_glyph * font_get_glyph_texture(struct font_atlas *atlas, unsig
|
|||
|
||||
// sum magic shit
|
||||
struct {unsigned char r,g,b;} *a = (void *)atlas->atlas;
|
||||
msdf_Result *res = &atlas->priv.msdf;
|
||||
msdf_Result *res = &PRIV(atlas)->msdf;
|
||||
float s = glyph_h;
|
||||
float tw = ((s * 0.7f) + s) / (s * 2.0f);
|
||||
float ta = tw - 0.5f;
|
||||
|
|
@ -178,7 +190,11 @@ const struct font_glyph * font_get_glyph_texture(struct font_atlas *atlas, unsig
|
|||
.w = res->width,
|
||||
.h = res->height,
|
||||
};
|
||||
return cache_insert(&g, spot);
|
||||
const struct font_glyph *ret = cache_insert(&g, spot);
|
||||
|
||||
efree(PRIV(atlas)->msdf.rgb);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -186,9 +202,8 @@ void font_dump(const struct font_atlas *atlas, const char *path)
|
|||
{
|
||||
stbi_write_png(
|
||||
path,
|
||||
//atlas->width,
|
||||
//atlas->height,
|
||||
128, 128,
|
||||
atlas->width,
|
||||
atlas->height,
|
||||
BDEPTH,
|
||||
atlas->atlas,
|
||||
BDEPTH*atlas->width);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue