diff options
author | Leo Tenenbaum <pommicket@gmail.com> | 2020-11-20 22:28:38 -0500 |
---|---|---|
committer | Leo Tenenbaum <pommicket@gmail.com> | 2020-11-20 22:28:38 -0500 |
commit | 5e458dff3bcc832b0b28d83bd3ef482174d1dc09 (patch) | |
tree | 28ac081edae5d36aad5df5b2e53848034dc2b99c /text.c | |
parent | c3fd9dfa23969c842991da4cd852330288889463 (diff) |
more text rendering
Diffstat (limited to 'text.c')
-rw-r--r-- | text.c | 82 |
1 files changed, 65 insertions, 17 deletions
@@ -1,27 +1,25 @@ #include "base.h" +#include "text.h" +#define STB_TRUETYPE_IMPLEMENTATION +#define STBTT_STATIC no_warn_start #include "stb_truetype.h" no_warn_end #include <stdarg.h> #include <stdlib.h> +#include <GL/gl.h> -typedef struct { +struct Font { float char_height; - u32 nchars; GLuint texture; + u32 nchars; stbtt_bakedchar chars[]; -} Font; +}; static char text_err[200]; static void text_clear_err(void) { text_err[0] = '\0'; } -static void text_set_err(char const *fmt, ...) { - va_list args; - va_start(args, fmt); - vsnprintf(text_err, sizeof text_err - 1, fmt, args); - va_end(args); -} static bool text_has_err(void) { return text_err[0] != '\0'; @@ -31,6 +29,15 @@ char const *text_get_err(void) { return text_err; } +static void text_set_err(char const *fmt, ...) { + if (!text_has_err()) { + va_list args; + va_start(args, fmt); + vsnprintf(text_err, sizeof text_err - 1, fmt, args); + va_end(args); + } +} + Font *text_font_load(char const *ttf_filename, float font_size) { Font *font = NULL; u32 nchars = 128; @@ -42,30 +49,71 @@ Font *text_font_load(char const *ttf_filename, float font_size) { fseek(ttf_file, 0, SEEK_END); u32 file_size = (u32)ftell(ttf_file); if (file_size < (50UL<<20)) { // fonts aren't usually bigger than 50 MB - char *file_data = calloc(1, file_size); - Font *font = calloc(1, sizeof *font + nchars * sizeof *font->chars); + u8 *file_data = calloc(1, file_size); + font = calloc(1, sizeof *font + nchars * sizeof *font->chars); if (file_data && font) { - font->nchars = nchars; - font->char_height = font_size; - stbtt_ + if (fread(file_data, 1, file_size, ttf_file) == file_size) { + font->nchars = nchars; + font->char_height = font_size; + + for (int bitmap_width = 256, bitmap_height = 256; bitmap_width <= 4096; bitmap_width *= 2, bitmap_height *= 2) { + u8 *bitmap = calloc((size_t)bitmap_width, (size_t)bitmap_height); + if (bitmap) { + int err = stbtt_BakeFontBitmap(file_data, 0, font->char_height, bitmap, + bitmap_width, bitmap_height, 0, (int)font->nchars, font->chars); + if (err > 0) { + // font converted to bitmap successfully. + GLuint texture = 0; + glGenTextures(1, &texture); + glBindTexture(GL_TEXTURE_2D, texture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, bitmap_width, bitmap_height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, bitmap); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + #if DEBUG + debug_println("Loaded font %s with %dx%d bitmap.", ttf_filename, bitmap_width, bitmap_height); + #endif + font->texture = texture; + if (glGetError()) { + text_set_err("Couldn't create texture for font."); + } + } + } else { + text_set_err("Not enough memory for font bitmap."); + } + free(bitmap); + if (font->texture) { // if font loaded successfully + break; + } + } + if (!font->texture && !text_has_err()) { + text_set_err("Couldn't convert font to bitmap."); + } + } else { + text_set_err("Couldn't read font file.", ttf_filename); + } } else { text_set_err("Not enough memory for font."); } free(file_data); - if (text_has_err()) + if (text_has_err()) { free(font); + font = NULL; + } fclose(ttf_file); } else { text_set_err("Font file too big (%u megabytes).", (uint)(file_size >> 20)); } } else { - text_set_err("Couldn't open font file: %s.", ttf_filename); + text_set_err("Couldn't open font file.", ttf_filename); } - return NULL; + return font; } +#if 0 void text_render(Font *font, char const *text, float x, float y) { + } void text_get_size(Font *font, char const *text, float *width, float *height) { } +#endif |