aboutsummaryrefslogtreecommitdiff
path: root/src/graphics
diff options
context:
space:
mode:
Diffstat (limited to 'src/graphics')
-rw-r--r--src/graphics/font.c7
-rw-r--r--src/graphics/text.c121
2 files changed, 50 insertions, 78 deletions
diff --git a/src/graphics/font.c b/src/graphics/font.c
index c017755..175c571 100644
--- a/src/graphics/font.c
+++ b/src/graphics/font.c
@@ -84,6 +84,11 @@ int mgl_font_load_from_file(mgl_font *self, const char *filepath, unsigned int c
continue;
}
+ /*if(!stbtt_PackFontRange(&pc, filedata.data, 0, self->character_size, 0x00004E00, self->num_packed_chars, self->packed_chars)) {
+ stbtt_PackEnd(&pc);
+ continue;
+ }*/
+
stbtt_PackEnd(&pc);
atlas_created = true;
break;
@@ -124,7 +129,7 @@ void mgl_font_unload(mgl_font *self) {
int mgl_font_get_glyph(const mgl_font *self, uint32_t codepoint, mgl_font_glyph *glyph) {
stbtt_packedchar *packed_chars = self->packed_chars;
- if(codepoint >= self->num_packed_chars)
+ if(codepoint < 0 || codepoint >= 0 + self->num_packed_chars)
return -1;
float x = 0.0f;
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 <stdio.h>
#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);