more work on win32 fonts

This commit is contained in:
Allen Webster 2016-06-06 11:24:06 -04:00
parent 428696d95e
commit 682d99dacc
1 changed files with 173 additions and 6 deletions

View File

@ -9,6 +9,21 @@
// TOP // TOP
struct Glyph_Bitmap{
HBITMAP bitmap_handle;
char *pixels;
};
void
win32_get_box(HDC dc, TCHAR character, int *x0, int *y0, int *x1, int *y1){
SIZE size;
GetTextExtentPoint32A(dc, &character, 1, &size);
*x0 = 0;
*y0 = 0;
*x1 = size.cx;
*y1 = size.cy;
}
internal i32 internal i32
win32_draw_font_load(Partition *part, win32_draw_font_load(Partition *part,
Render_Font *font_out, Render_Font *font_out,
@ -44,20 +59,172 @@ win32_draw_font_load(Partition *part,
HDC dc = CreateCompatibleDC(0); HDC dc = CreateCompatibleDC(0);
if (dc){ if (dc){
// TODO(allen): Have to get metrics TEXTMETRIC metrics;
GetTextMetrics(dc, &metrics);
font_out->height = metrics.tmHeight + metrics.tmExternalLeading;
font_out->ascent = metrics.tmAscent;
font_out->descent = -metrics.tmDescent;
font_out->line_skip = metrics.tmExternalLeading;
font_out->advance = metrics.tmMaxCharWidth;
result = 1; result = 1;
if (store_texture){ if (store_texture){
Temp_Memory temp = begin_temp_memory(part);
i32 tex_width = pt_size*16*oversample; i32 tex_width = pt_size*16*oversample;
i32 tex_height = pt_size*16*oversample; i32 tex_height = pt_size*16*oversample;
HBITAMP bitmap = CreateCompatibleBitmap(dc, tex_width, tex_height); Glyph_Bitmap glyph_bitmap;
glyph_bitmap.bitmap_handle = CreateCompatibleBitmap(dc, tex_width, tex_height);
glyph_bitmap.pixels = push_array(part, char, tex_width*tex_height);
// TODO(allen): pack each glyph into a texture SelectObject(dc, glyph_bitmap.bitmap_handle);
// and generate the equivalent data output by stb SelectObject(dc, font_handle);
// in the stbtt_packedchar array.
SetBkColor(dc, RGB(0, 0, 0));
stbtt_pack_context context = {0};
stbtt_PackBegin(&context, (unsigned char*)glyph_bitmap.pixels, tex_width, tex_height, 0, 1, part);
{
stbtt_pack_context *spc = &context;
int first_unicode_char_in_range = 0;
int num_chars_in_range = 128;
stbtt_packedchar *chardata_for_range = font_out->chardata;
{
stbtt_pack_range range;
range.first_unicode_char_in_range = first_unicode_char_in_range;
range.num_chars_in_range = num_chars_in_range;
range.chardata_for_range = chardata_for_range;
{
stbtt_pack_range *ranges = ⦥
int num_ranges = 1;
{
float recip_h = 1.0f / spc->h_oversample;
float recip_v = 1.0f / spc->v_oversample;
float sub_x = stbtt__oversample_shift(spc->h_oversample);
float sub_y = stbtt__oversample_shift(spc->v_oversample);
int i,j,k,n, return_value = 1;
stbrp_context *context = (stbrp_context *) spc->pack_info;
stbrp_rect *rects;
// flag all characters as NOT packed
for (i=0; i < num_ranges; ++i)
for (j=0; j < ranges[i].num_chars_in_range; ++j)
ranges[i].chardata_for_range[j].x0 =
ranges[i].chardata_for_range[j].y0 =
ranges[i].chardata_for_range[j].x1 =
ranges[i].chardata_for_range[j].y1 = 0;
n = 0;
for (i=0; i < num_ranges; ++i)
n += ranges[i].num_chars_in_range;
rects = (stbrp_rect *) STBTT_malloc(sizeof(*rects) * n, spc->user_allocator_context);
if (rects == NULL)
return 0;
k=0;
for (i=0; i < num_ranges; ++i) {
for (j=0; j < ranges[i].num_chars_in_range; ++j) {
int x0,y0,x1,y1;
TCHAR character = (TCHAR)(ranges[i].first_unicode_char_in_range + j);
win32_get_box(dc, character, &x0, &y0, &x1, &y1);
rects[k].w = (stbrp_coord) (x1-x0 + spc->padding + spc->h_oversample-1);
rects[k].h = (stbrp_coord) (y1-y0 + spc->padding + spc->v_oversample-1);
++k;
}
}
stbrp_pack_rects(context, rects, k);
k = 0;
for (i=0; i < num_ranges; ++i) {
for (j=0; j < ranges[i].num_chars_in_range; ++j) {
stbrp_rect *r = &rects[k];
if (r->was_packed) {
stbtt_packedchar *bc = &ranges[i].chardata_for_range[j];
int advance, x0,y0,x1,y1;
int glyph = ranges[i].first_unicode_char_in_range + j;
stbrp_coord pad = (stbrp_coord) spc->padding;
GetCharWidth32W(dc, glyph, glyph, &advance);
TCHAR character = (TCHAR)(ranges[i].first_unicode_char_in_range + j);
win32_get_box(dc, character, &x0, &y0, &x1, &y1);
// pad on left and top
r->x += pad;
r->y += pad;
r->w -= pad;
r->h -= pad;
SetTextColor(dc, RGB(255, 255, 255));
TextOutA(dc, r->x, r->y, &character, 1);
if (spc->h_oversample > 1)
stbtt__h_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes,
r->w, r->h, spc->stride_in_bytes,
spc->h_oversample);
if (spc->v_oversample > 1)
stbtt__v_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes,
r->w, r->h, spc->stride_in_bytes,
spc->v_oversample);
bc->x0 = (stbtt_int16) r->x;
bc->y0 = (stbtt_int16) r->y;
bc->x1 = (stbtt_int16) (r->x + r->w);
bc->y1 = (stbtt_int16) (r->y + r->h);
bc->xadvance = (float) advance;
bc->xoff = (float) x0 * recip_h + sub_x;
bc->yoff = (float) y0 * recip_v + sub_y;
bc->xoff2 = (x0 + r->w) * recip_h + sub_x;
bc->yoff2 = (y0 + r->h) * recip_v + sub_y;
} else {
return_value = 0; // if any fail, report failure
}
++k;
}
}
STBTT_free(rects, spc->user_allocator_context);
result = return_value;
if (return_value){
GLuint font_tex;
glGenTextures(1, &font_tex);
glBindTexture(GL_TEXTURE_2D, font_tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, tex_width, tex_height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, glyph_bitmap.pixels);
font_out->tex = font_tex;
glBindTexture(GL_TEXTURE_2D, 0);
font_out->chardata['\r'] = font_out->chardata[' '];
font_out->chardata['\n'] = font_out->chardata[' '];
font_out->chardata['\t'] = font_out->chardata[' '];
font_out->chardata['\t'].xadvance *= tab_width;
}
}
}
}
}
stbtt_PackEnd(&context);
end_temp_memory(temp);
} }
} }