strans/font.c
2025-12-23 20:21:56 +09:00

88 lines
1.7 KiB
C

#define STB_TRUETYPE_IMPLEMENTATION
#include "stb_truetype.h"
#include "dat.h"
#include "fn.h"
typedef struct Glyph Glyph;
struct Glyph
{
uchar *bmp;
int w, h, ox, oy;
};
static stbtt_fontinfo font;
static uchar *fontdata;
static float scale;
static Glyph cache[Nglyphs];
static u32int blendtab[2][256];
static u32int
blend(u32int bg, int a)
{
int r, g, b, inv;
inv = 255 - a;
r = (bg >> 16 & 0xff) * inv / 255;
g = (bg >> 8 & 0xff) * inv / 255;
b = (bg & 0xff) * inv / 255;
return (r << 16) | (g << 8) | b;
}
void
fontinit(char *path)
{
int fd, a;
long sz, n;
fd = open(path, OREAD);
if(fd < 0)
die("can't open font: %s", path);
sz = seek(fd, 0, 2);
seek(fd, 0, 0);
fontdata = emalloc(sz);
n = readn(fd, fontdata, sz);
close(fd);
if(n != sz)
die("can't read font: %s", path);
if(!stbtt_InitFont(&font, fontdata, stbtt_GetFontOffsetForIndex(fontdata, 0)))
die("can't init font: %s", path);
scale = stbtt_ScaleForPixelHeight(&font, Fontsz);
for(a = 0; a < 256; a++){
blendtab[0][a] = blend(Colbg, a);
blendtab[1][a] = blend(Colsel, a);
}
}
void
putfont(u32int *buf, int w, int h, int px, int py, Rune r)
{
Glyph *g;
int i, j, x, y, a, sel;
u32int *p;
if(r >= Nglyphs)
return;
g = &cache[r];
if(g->bmp == nil){
g->bmp = stbtt_GetCodepointBitmap(&font, scale, scale, r, &g->w, &g->h, &g->ox, &g->oy);
if(g->bmp == nil)
return;
}
for(j = 0; j < g->h; j++){
y = py + j + g->oy + Fontsz - Fontbase;
if(y < 0 || y >= h)
continue;
for(i = 0; i < g->w; i++){
x = px + i + g->ox;
if(x < 0 || x >= w)
continue;
a = g->bmp[j * g->w + i];
if(a > 0){
p = &buf[y * w + x];
sel = (*p == Colsel) ? 1 : 0;
*p = blendtab[sel][a];
}
}
}
}