From cb679636f77fe2a03e8dab3a511e28e1ab898316 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Sat, 6 Nov 2021 15:55:42 +0100 Subject: Fix exit being called when closing window, respond to wm ping, add is_open function to window --- src/graphics/text.c | 121 +++++++++++++++++++--------------------------------- 1 file changed, 44 insertions(+), 77 deletions(-) (limited to 'src/graphics/text.c') diff --git a/src/graphics/text.c b/src/graphics/text.c index 31ae794..9804ab2 100644 --- a/src/graphics/text.c +++ b/src/graphics/text.c @@ -1,27 +1,12 @@ #include "../../include/mgl/graphics/text.h" #include "../../include/mgl/graphics/font.h" +#include "../../include/mgl/system/utf8.h" #include "../../include/mgl/mgl.h" - -/* - 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. -*/ +#include #define TAB_WIDTH 4 -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; -} - -static float fmax(float a, float b) { +static float max_float(float a, float b) { return a >= b ? a : b; } @@ -33,63 +18,65 @@ static mgl_vec2f mgl_text_calculate_bounds(mgl_text *self) { /* TODO: Combine this with the loop in mgl_text_draw */ mgl_font_glyph glyph; float width = 0.0f; - for(size_t i = 0; i < self->text_size; ++i) { - unsigned char c = *(unsigned char*)&self->text[i]; - if((c >= 32 && c < 128)) { - if(mgl_font_get_glyph(self->font, c, &glyph) == 0) { - width += glyph.advance; - bounds.x = fmax(bounds.x, width); - } - } else if(c == '\t') { + for(size_t i = 0; i < self->text_size;) { + unsigned char *cp = (unsigned char*)&self->text[i]; + uint32_t codepoint = 0; + const size_t clen = mgl_utf8_decode(cp, &codepoint); + if(codepoint == '\t') { if(mgl_font_get_glyph(self->font, ' ', &glyph) == 0) { width += (glyph.advance * TAB_WIDTH); - bounds.x = fmax(bounds.x, width); + bounds.x = max_float(bounds.x, width); } - } else if(c == '\n') { + } else if(codepoint == '\n') { width = 0.0f; bounds.y += self->font->character_size; + } else { + if(mgl_font_get_glyph(self->font, codepoint, &glyph) == 0) { + width += glyph.advance; + bounds.x = max_float(bounds.x, width); + } } + i += clen; } return bounds; } -int mgl_text_init(mgl_text *self, mgl_font *font, const char *str, size_t str_size, mgl_text_options *options) { +int mgl_text_init(mgl_text *self, mgl_font *font, const char *str, size_t str_size) { self->font = font; - mgl_text_set_string(self, str, str_size); self->color = (mgl_color){ 255, 255, 255, 255 }; self->position = (mgl_vec2f){ 0.0f, 0.0f }; - - if(options) { - self->options = *options; - } else { - self->options.userdata = NULL; - self->options.before_syntax_highlight = NULL; - } - - if(!options || !options->syntax_highlight) - self->options.syntax_highlight = default_syntax_highlight; - - return 0; + self->text = NULL; + self->text_size = 0; + return mgl_text_set_string(self, str, str_size); } void mgl_text_deinit(mgl_text *self) { (void)self; } -void mgl_text_set_string(mgl_text *self, const char *str, size_t str_size) { +int mgl_text_set_string(mgl_text *self, const char *str, size_t str_size) { + if(str) { + if(!mgl_utf8_is_valid((const unsigned char*)str, str_size)) { + fprintf(stderr, "Error: mgl_text_set_string received an invalid utf8 string\n"); + return -1; + } + } + self->text = str; self->text_size = str_size; if(self->text && self->text_size > 0 && self->font) self->bounds = mgl_text_calculate_bounds(self); else self->bounds = (mgl_vec2f){ 0.0f, 0.0f }; + + return 0; } void mgl_text_set_font(mgl_text *self, mgl_font *font) { self->font = font; if(self->font) { - if(self->bounds.x < 0.001f && self->bounds.y < 0.001f) + if(self->bounds.x < 0.001f && self->bounds.y < 0.001f && self->text && self->text_size > 0) self->bounds = mgl_text_calculate_bounds(self); } else { self->bounds = (mgl_vec2f){ 0.0f, 0.0f }; @@ -122,19 +109,6 @@ 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) { @@ -145,34 +119,27 @@ void mgl_text_draw(mgl_context *context, mgl_text *text) { 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); - 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; - } - } else if(c == '\t') { + for(size_t i = 0; i < text->text_size;) { + unsigned char *cp = (unsigned char*)&text->text[i]; + uint32_t codepoint = 0; + const size_t clen = mgl_utf8_decode(cp, &codepoint); + if(codepoint == '\t') { if(mgl_font_get_glyph(text->font, ' ', &glyph) == 0) { - for(int i = 0; i < TAB_WIDTH; ++i) { - mgl_text_draw_glyph(context, &glyph, position); - position.x += glyph.advance; - } + position.x += (glyph.advance * TAB_WIDTH); } - } else if(c == '\n') { + } else if(codepoint == '\n') { position.x = text->position.x; position.y += text->font->character_size; + } else { + if(mgl_font_get_glyph(text->font, codepoint, &glyph) == 0) { + mgl_text_draw_glyph(context, &glyph, position); + position.x += glyph.advance; + } } + i += clen; } context->gl.glEnd(); context->gl.glBindTexture(GL_TEXTURE_2D, 0); -- cgit v1.2.3