aboutsummaryrefslogtreecommitdiff
path: root/src/graphics/text.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/graphics/text.c')
-rw-r--r--src/graphics/text.c67
1 files changed, 56 insertions, 11 deletions
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);