Last active
October 31, 2023 00:45
-
-
Save rygorous/6f2779a451d2040371e3acb79e16eaff to your computer and use it in GitHub Desktop.
HarfBuzz->stb_truetype
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ---- loading a font | |
static void load_font(void) | |
{ | |
hb_blob_t *blob; | |
hb_face_t *face; | |
size_t filelen = 0; | |
void *filedata = stb_file("c:/windows/fonts/arial.ttf", &filelen); | |
if (filedata == 0) stbpg_fatal("Couldn't load font"); | |
if (!stbtt_InitFont(&font, filedata, stbtt_GetFontOffsetForIndex(filedata,0))) stbpg_fatal("Couldn't parse font"); | |
font_scale = stbtt_ScaleForPixelHeight(&font, 32); | |
blob = hb_blob_create((const char *)filedata, (unsigned int)filelen, HB_MEMORY_MODE_READONLY, NULL, NULL); | |
if (!blob) stbpg_fatal("Font blob create failed"); | |
face = hb_face_create(blob, 0); | |
if (!face) stbpg_fatal("Font face create failed"); | |
hb_blob_destroy(blob); // face keeps its ref. | |
hb_font = hb_font_create(face); | |
if (!hb_font) stbpg_fatal("Font create failed"); | |
hb_face_destroy(face); // font keeps ref | |
// stb_truetype only does TrueType/OpenType which HB supports natively | |
hb_ot_font_set_funcs(hb_font); | |
} | |
static void cleanup_font(void) | |
{ | |
hb_font_destroy(hb_font); | |
} | |
// ---- shaping and rendering | |
static void print_message_shaped(int x, int y, const char *msg) | |
{ | |
hb_buffer_t *buf; | |
hb_glyph_info_t *ginf; | |
hb_glyph_position_t *gpos; | |
unsigned int len = 0; | |
unsigned int i; | |
int j; | |
buf = hb_buffer_create(); | |
if (!buf) stbpg_fatal("no buf"); | |
// set up the buffer | |
hb_buffer_set_flags(buf, HB_BUFFER_FLAG_BOT | HB_BUFFER_FLAG_EOT); // beginning and end of text both | |
hb_buffer_add_utf8(buf, msg, -1, 0, -1); | |
hb_buffer_guess_segment_properties(buf); | |
// shape it | |
hb_shape(hb_font, buf, NULL, 0); | |
ginf = hb_buffer_get_glyph_infos(buf, &len); | |
gpos = hb_buffer_get_glyph_positions(buf, &len); | |
if ((!ginf || !gpos) && len) stbpg_fatal("no glyph info"); | |
// make sure we have the glyphs | |
glPixelStorei(GL_UNPACK_ALIGNMENT, 1); | |
for (i = 0; i < len; ++i) { | |
int glyph = ginf[i].codepoint; | |
if (!glyphs[glyph].init) | |
bake_glyph(&font, font_scale, glyph); | |
} | |
// render the text | |
glBegin(GL_QUADS); | |
for (i = 0; i < len; ++i) { | |
hb_glyph_info_t *gi = &ginf[i]; | |
hb_glyph_position_t *gp = &gpos[i]; | |
glyph_quad *gq = &glyphs[gi->codepoint]; | |
float xb, yb; | |
xb = x + gp->x_offset*font_scale; | |
yb = y - gp->y_offset*font_scale; // our +y goes down, glyph +y goes up | |
for (j = 0; j < 4; ++j) { | |
int k = j ^ (j >> 1); | |
int xd = ((k&1) ? gq->w : 0); | |
int yd = ((k&2) ? gq->h : 0); | |
glTexCoord2f(1.0f * (gq->x0 + xd) / FONT_W, 1.0f * (gq->y0 + yd) / FONT_H); | |
glVertex2f(xb + (gq->xo + xd)/((float) OVERSAMPLE), yb + (gq->yo + yd)/((float)OVERSAMPLE)); | |
} | |
x += gp->x_advance*font_scale; | |
} | |
glEnd(); | |
hb_buffer_destroy(buf); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment