idk cache I guess
This commit is contained in:
parent
dcce0ed11b
commit
e80d426872
22 changed files with 198 additions and 3793 deletions
|
|
@ -1,42 +1,31 @@
|
|||
#define _POSIX_C_SOURCE 200809l
|
||||
#define STB_TRUETYPE_IMPLEMENTATION
|
||||
#define STBTT_STATIC
|
||||
#define MSDF_IMPLEMENTATION
|
||||
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
||||
|
||||
#include <grapheme.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "font.h"
|
||||
#include "msdf_c/stb_truetype.h"
|
||||
#include "msdf_c/msdf.h"
|
||||
#include "stb_truetype.h"
|
||||
#include "stb_image_write.h"
|
||||
#include "util.h"
|
||||
#include "cache.h"
|
||||
|
||||
|
||||
#define UTF8(c) (c&0x80)
|
||||
#define BDEPTH 3
|
||||
#define BDEPTH 1
|
||||
#define BORDER 4
|
||||
|
||||
// Generates a cached atlas of font glyphs encoded usign a signed distance field
|
||||
// https://www.youtube.com/watch?v=1b5hIMqz_wM
|
||||
// https://github.com/pjako/msdf_c
|
||||
// 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
|
||||
|
||||
// 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;
|
||||
// FIXME: as of now only monospaced fonts work correctly since no kerning information
|
||||
// is stored
|
||||
|
||||
|
||||
struct priv {
|
||||
stbtt_fontinfo stb;
|
||||
msdf_AllocCtx ctx;
|
||||
msdf_Result msdf;
|
||||
float scale;
|
||||
int baseline;
|
||||
unsigned char *bitmap;
|
||||
};
|
||||
#define PRIV(x) ((struct priv *)x->priv)
|
||||
|
||||
|
|
@ -56,8 +45,9 @@ struct font_atlas * font_init(void)
|
|||
}
|
||||
|
||||
|
||||
// loads a font into memory, storing all the ASCII characters in the atlas
|
||||
int font_load(struct font_atlas *atlas, const char *path)
|
||||
// loads a font into memory, storing all the ASCII characters in the atlas, each font
|
||||
// atlas structure holds glyphs of a specific size
|
||||
int font_load(struct font_atlas *atlas, const char *path, int size)
|
||||
{
|
||||
if (!atlas || !path)
|
||||
return -1;
|
||||
|
|
@ -69,23 +59,24 @@ int font_load(struct font_atlas *atlas, const char *path)
|
|||
err = stbtt_InitFont(&(PRIV(atlas)->stb), (unsigned char *)atlas->file, 0);
|
||||
ERROR(err == 0, -1);
|
||||
|
||||
PRIV(atlas)->scale = stbtt_ScaleForPixelHeight(&(PRIV(atlas)->stb), glyph_h);
|
||||
//int ascent, descent, linegap, baseline;
|
||||
//int x0,y0,x1,y1;
|
||||
//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 = emalloc(CACHE_SIZE*BDEPTH*glyph_h*glyph_w);
|
||||
memset(atlas->atlas, 0, CACHE_SIZE*BDEPTH*glyph_h*glyph_w);
|
||||
int ascent, descent, linegap, baseline;
|
||||
int x0,y0,x1,y1;
|
||||
float scale;
|
||||
scale = stbtt_ScaleForPixelHeight(&(PRIV(atlas)->stb), size);
|
||||
stbtt_GetFontVMetrics(&(PRIV(atlas)->stb), &ascent, &descent, &linegap);
|
||||
stbtt_GetFontBoundingBox(&(PRIV(atlas)->stb), &x0, &y0, &x1, &y1);
|
||||
baseline = scale * -y0;
|
||||
atlas->glyph_max_w = (scale*x1) - (scale*x0);
|
||||
atlas->glyph_max_h = (baseline+scale*y1) - (baseline+scale*y0);
|
||||
atlas->atlas = emalloc(CACHE_SIZE*BDEPTH*atlas->glyph_max_w*atlas->glyph_max_h);
|
||||
memset(atlas->atlas, 0, CACHE_SIZE*BDEPTH*atlas->glyph_max_w*atlas->glyph_max_h);
|
||||
PRIV(atlas)->baseline = atlas->glyph_max_h - baseline;
|
||||
PRIV(atlas)->scale = scale;
|
||||
PRIV(atlas)->bitmap = emalloc(BDEPTH*atlas->glyph_max_w*atlas->glyph_max_h);
|
||||
// FIXME: make this a square atlas
|
||||
atlas->width = glyph_w*CACHE_SIZE/4;
|
||||
atlas->height = glyph_h*4;
|
||||
|
||||
PRIV(atlas)->ctx = (msdf_AllocCtx){_emalloc, _efree, NULL};
|
||||
atlas->width = atlas->glyph_max_w*CACHE_SIZE/4;
|
||||
atlas->height = atlas->glyph_max_h*4;
|
||||
atlas->size = size;
|
||||
|
||||
cache_init();
|
||||
|
||||
|
|
@ -103,6 +94,7 @@ int font_free(struct font_atlas *atlas)
|
|||
{
|
||||
efree(atlas->atlas);
|
||||
efree(atlas->file);
|
||||
efree(PRIV(atlas)->bitmap);
|
||||
efree(atlas->priv);
|
||||
efree(atlas);
|
||||
cache_destroy();
|
||||
|
|
@ -127,73 +119,65 @@ const struct font_glyph * font_get_glyph_texture(struct font_atlas *atlas, unsig
|
|||
// generate the sdf and put it into the cache
|
||||
// TODO: generate the whole block at once
|
||||
int idx = stbtt_FindGlyphIndex(&PRIV(atlas)->stb, code);
|
||||
// FIXME: what happens if I change the range?
|
||||
int err;
|
||||
err = msdf_genGlyph(&PRIV(atlas)->msdf,
|
||||
int x0,y0,x1,y1,gw,gh,l,off_x,off_y,adv;
|
||||
stbtt_GetGlyphBitmapBoxSubpixel(
|
||||
&PRIV(atlas)->stb,
|
||||
idx,
|
||||
BORDER,
|
||||
PRIV(atlas)->scale,
|
||||
2.0f/glyph_h,
|
||||
&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) {
|
||||
PRIV(atlas)->msdf.width = 0;
|
||||
PRIV(atlas)->msdf.height = 0;
|
||||
}
|
||||
PRIV(atlas)->scale,
|
||||
0,0,
|
||||
&x0,&y0,
|
||||
&x1, &y1);
|
||||
gw = x1 - x0;
|
||||
gh = y1 - y0;
|
||||
stbtt_GetGlyphHMetrics(&PRIV(atlas)->stb, idx, &adv, &l);
|
||||
adv *= PRIV(atlas)->scale;
|
||||
off_x = PRIV(atlas)->scale*l;
|
||||
off_y = atlas->glyph_max_h+y0;
|
||||
stbtt_MakeGlyphBitmapSubpixel(
|
||||
&PRIV(atlas)->stb,
|
||||
PRIV(atlas)->bitmap,
|
||||
atlas->glyph_max_w,
|
||||
atlas->glyph_max_h,
|
||||
atlas->glyph_max_w,
|
||||
PRIV(atlas)->scale,
|
||||
PRIV(atlas)->scale,
|
||||
0, 0,
|
||||
idx);
|
||||
|
||||
// TODO: bounds check usign atlas height
|
||||
// TODO: clear spot area in the atlas before writing on it
|
||||
unsigned int spot = cache_get();
|
||||
unsigned int oy = (glyph_h * spot) / atlas->width;
|
||||
unsigned int ox = (glyph_h * spot) % atlas->height;
|
||||
unsigned int oy = ((atlas->glyph_max_w * spot) / atlas->width) * atlas->glyph_max_h;
|
||||
unsigned int ox = (atlas->glyph_max_w * spot) % atlas->width;
|
||||
unsigned int w = atlas->width;
|
||||
|
||||
// sum magic shit
|
||||
struct {unsigned char r,g,b;} *a = (void *)atlas->atlas;
|
||||
msdf_Result *res = &PRIV(atlas)->msdf;
|
||||
float s = glyph_h;
|
||||
float tw = ((s * 0.7f) + s) / (s * 2.0f);
|
||||
float ta = tw - 0.5f;
|
||||
float ts = 0.5 - ta / 2;
|
||||
float te = ts + ta;
|
||||
unsigned char *a = (void *)atlas->atlas;
|
||||
|
||||
#define NORMALIZE(x) x = x > ts ? (x > te ? 1.0f : (x-ts)/ta+0.0f) : (0.0f)
|
||||
//printf("max:%d %d spot:%d : %d %d %d %d\n", atlas->glyph_max_w, atlas->glyph_max_h, spot, ox, oy, off_x, off_y);
|
||||
|
||||
for (int y = 0; y < res->height; y++) {
|
||||
int yPos = res->width * 3 * y;
|
||||
for (int x = 0; x < res->width; x++) {
|
||||
|
||||
int i = yPos + (x * 3);
|
||||
float r = res->rgb[i+0];
|
||||
float g = res->rgb[i+1];
|
||||
float b = res->rgb[i+2];
|
||||
|
||||
r = (r + s) / (s * 2.0f);
|
||||
g = (g + s) / (s * 2.0f);
|
||||
b = (b + s) / (s * 2.0f);
|
||||
|
||||
NORMALIZE(r);
|
||||
NORMALIZE(g);
|
||||
NORMALIZE(b);
|
||||
|
||||
a[(oy+y)*w + (ox+x)].r = r * 255.0f; // (r > 0.5f) ? 255.0f : r * 255.0f;
|
||||
a[(oy+y)*w + (ox+x)].g = g * 255.0f; // (g > 0.5f) ? 255.0f : g * 255.0f;
|
||||
a[(oy+y)*w + (ox+x)].b = b * 255.0f; // (b > 0.5f) ? 255.0f : b * 255.0f;
|
||||
for (int y = 0; y < gh; y++) {
|
||||
for (int x = 0; x < gw; x++) {
|
||||
int c, r;
|
||||
r = (oy+y)*w;
|
||||
c = ox+x;
|
||||
a[r+c] = PRIV(atlas)->bitmap[y*atlas->glyph_max_w+x];
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: get the advance
|
||||
struct font_glyph g = {
|
||||
.codepoint = code,
|
||||
.u = ox,
|
||||
.v = oy,
|
||||
.w = res->width,
|
||||
.h = res->height,
|
||||
.w = gw,
|
||||
.h = gh,
|
||||
.x = off_x,
|
||||
.y = off_y,
|
||||
.a = adv,
|
||||
};
|
||||
const struct font_glyph *ret = cache_insert(&g, spot);
|
||||
|
||||
efree(PRIV(atlas)->msdf.rgb);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue