diff options
Diffstat (limited to 'src/graphics')
-rw-r--r-- | src/graphics/font.c | 9 | ||||
-rw-r--r-- | src/graphics/text.c | 67 |
2 files changed, 61 insertions, 15 deletions
diff --git a/src/graphics/font.c b/src/graphics/font.c index 8344a04..2ed54d2 100644 --- a/src/graphics/font.c +++ b/src/graphics/font.c @@ -47,8 +47,8 @@ int mgl_font_load_from_file(mgl_font *self, const char *filepath, unsigned int c /* TODO: Optimize */ /* Find optimal size for atlas, starting from small to large */ for(int i = 0; i < 4; ++i) { - self->font_atlas.width = (8 + (8 * i)) * self->character_size; - self->font_atlas.height = (8 + (8 * i)) * self->character_size; + self->font_atlas.width = (14 + (8 * i)) * self->character_size; + self->font_atlas.height = (14 + (8 * i)) * self->character_size; unsigned char *new_atlas = realloc(self->font_atlas.atlas, self->font_atlas.width * self->font_atlas.height); if(!new_atlas) { fprintf(stderr, "Error: failed to load font %s, error: out of memory\n", filepath); @@ -67,6 +67,8 @@ int mgl_font_load_from_file(mgl_font *self, const char *filepath, unsigned int c return -1; } + stbtt_PackSetOversampling(&pc, 2, 2); + if(!stbtt_PackFontRange(&pc, filedata.data, 0, self->character_size, 0, self->num_packed_chars, self->packed_chars)) { stbtt_PackEnd(&pc); continue; @@ -92,7 +94,6 @@ int mgl_font_load_from_file(mgl_font *self, const char *filepath, unsigned int c } /* TODO: Use stbtt_GetCodepointSDF */ - /* TODO: Use stbtt_PackSetOversampling */ mgl_filedata_free(&filedata); return 0; @@ -119,7 +120,7 @@ int mgl_font_get_glyph(const mgl_font *self, uint32_t codepoint, mgl_font_glyph float x = 0.0f; float y = 0.0f; stbtt_aligned_quad quad; - stbtt_GetPackedQuad(packed_chars, self->font_atlas.width, self->font_atlas.height, codepoint, &x, &y, &quad, 1); + stbtt_GetPackedQuad(packed_chars, self->font_atlas.width, self->font_atlas.height, codepoint, &x, &y, &quad, 0); glyph->position = (mgl_vec2f){ quad.x0, quad.y0 }; glyph->size = (mgl_vec2f){ quad.x1 - quad.x0, quad.y1 - quad.y0 }; diff --git a/src/graphics/text.c b/src/graphics/text.c index 76fd852..9a849a9 100644 --- a/src/graphics/text.c +++ b/src/graphics/text.c @@ -2,20 +2,48 @@ #include "../../include/mgl/graphics/font.h" #include "../../include/mgl/mgl.h" -int mgl_text_init(mgl_text *self, mgl_font *font, const char *text, float x, float y) { +/* + TODO: Do syntax highlight in constructor/mgl_text_set_string for optimization. + Syntax highlighting should the first text that is visible in the text editor and find the start and end, + and start syntax highlight from there until the last visible text. + In that case there should also be a function to rerun the syntax highlighting, to update it + when an asynchronous process finishes that parses code, such as a lsp client parsing C++ code which + takes a while. +*/ + +static bool default_syntax_highlight(void *userdata, const char *str, size_t size, mgl_color *color) { + (void)userdata; + (void)str; + (void)size; + (void)color; + return false; +} + +int mgl_text_init(mgl_text *self, mgl_font *font, const char *str, size_t str_size, mgl_text_options *options) { self->font = font; - self->text = text; + self->text = str; + self->text_size = str_size; self->color = (mgl_color){ 255, 255, 255, 255 }; - self->position = (mgl_vec2f){ x, y }; + self->position = (mgl_vec2f){ 0.0f, 0.0f }; + + if(options) + self->options = *options; + else + self->options.userdata = NULL; + + if(!options || !options->syntax_highlight) + self->options.syntax_highlight = default_syntax_highlight; + return 0; } void mgl_text_deinit(mgl_text *self) { - + (void)self; } -void mgl_text_set_string(mgl_text *self, const char *str) { +void mgl_text_set_string(mgl_text *self, const char *str, size_t str_size) { self->text = str; + self->text_size = str_size; } void mgl_text_set_font(mgl_text *self, mgl_font *font) { @@ -44,25 +72,43 @@ static void mgl_text_draw_glyph(mgl_context *context, mgl_font_glyph *glyph, mgl context->gl.glVertex3f(position.x + glyph->position.x, position.y + glyph->position.y + glyph->size.y, 0.0f); } +static void mgl_text_run_syntax_highlight(mgl_context *context, mgl_text *text, const char *str, size_t size, mgl_color *color, bool *color_changed) { + if(text->options.syntax_highlight(text->options.userdata, str, size, color)) { + context->gl.glColor4ub(color->r, color->g, color->b, color->a); + *color_changed = true; + } else { + if(*color_changed) { + *color = text->color; + context->gl.glColor4ub(color->r, color->g, color->b, color->a); + *color_changed = false; + } + } +} + /* TODO: Use opengl buffer object instead */ /* TODO: Cache texture bind to not bind texture if its already bound and do not bind texture 0 */ void mgl_text_draw(mgl_context *context, mgl_text *text) { - if(!text->text || !text->font) + if(!text->text || text->text_size == 0 || !text->font) return; - const char *str = text->text; - mgl_font_glyph glyph; mgl_vec2f position = text->position; position.y += text->font->character_size; + mgl_color color = text->color; + bool color_changed = false; + + if(text->options.before_syntax_highlight) + text->options.before_syntax_highlight(text->options.userdata); + context->gl.glColor4ub(text->color.r, text->color.g, text->color.b, text->color.a); context->gl.glBindTexture(GL_TEXTURE_2D, text->font->texture.id); context->gl.glBegin(GL_QUADS); - while(*str) { - unsigned char c = *(unsigned char*)str; + for(size_t i = 0; i < text->text_size; ++i) { + unsigned char c = *(unsigned char*)&text->text[i]; if((c >= 32 && c < 128)) { if(mgl_font_get_glyph(text->font, c, &glyph) == 0) { + mgl_text_run_syntax_highlight(context, text, (const char*)&c, 1, &color, &color_changed); mgl_text_draw_glyph(context, &glyph, position); position.x += glyph.advance; } @@ -78,7 +124,6 @@ void mgl_text_draw(mgl_context *context, mgl_text *text) { position.x = text->position.x; position.y += text->font->character_size; } - ++str; } context->gl.glEnd(); context->gl.glBindTexture(GL_TEXTURE_2D, 0); |