diff --git a/bin64/liboverlay.so.0 b/bin64/liboverlay.so.0 index 5c5dfcb..51c4bd0 100755 Binary files a/bin64/liboverlay.so.0 and b/bin64/liboverlay.so.0 differ diff --git a/ftgl/font-manager.o b/ftgl/font-manager.o index 9d22c09..bcb5165 100644 Binary files a/ftgl/font-manager.o and b/ftgl/font-manager.o differ diff --git a/ftgl/makefont.o b/ftgl/makefont.o index a18e58d..3d52698 100644 Binary files a/ftgl/makefont.o and b/ftgl/makefont.o differ diff --git a/ftgl/text-buffer.o b/ftgl/text-buffer.o index 8ff8eb1..474528a 100644 Binary files a/ftgl/text-buffer.o and b/ftgl/text-buffer.o differ diff --git a/ftgl/texture-atlas.c b/ftgl/texture-atlas.c index 74219ac..1d31e0f 100644 --- a/ftgl/texture-atlas.c +++ b/ftgl/texture-atlas.c @@ -36,6 +36,7 @@ texture_atlas_new( const size_t width, self->height = height; self->depth = depth; self->id = 0; + self->dirty = 1; vector_push_back( self->nodes, &node ); self->data = (unsigned char *) @@ -99,6 +100,7 @@ texture_atlas_set_region( texture_atlas_t * self, memcpy( self->data+((y+i)*self->width + x ) * charsize * depth, data + (i*stride) * charsize, width * charsize * depth ); } + self->dirty = 1; } diff --git a/ftgl/texture-atlas.h b/ftgl/texture-atlas.h index 4738871..4cc65bb 100644 --- a/ftgl/texture-atlas.h +++ b/ftgl/texture-atlas.h @@ -110,6 +110,11 @@ typedef struct texture_atlas_t */ unsigned char * data; + /** + * Custom field + */ + char dirty; + } texture_atlas_t; diff --git a/ftgl/texture-atlas.o b/ftgl/texture-atlas.o index 6523894..c2ad287 100644 Binary files a/ftgl/texture-atlas.o and b/ftgl/texture-atlas.o differ diff --git a/ftgl/texture-font.o b/ftgl/texture-font.o index f4eb390..579fe89 100644 Binary files a/ftgl/texture-font.o and b/ftgl/texture-font.o differ diff --git a/include/drawglx_internal.h b/include/drawglx_internal.h index 46e7563..6f78458 100644 --- a/include/drawglx_internal.h +++ b/include/drawglx_internal.h @@ -8,6 +8,7 @@ #pragma once #include "drawglx.h" +#include "fontapi_internal.h" #include "programs.h" #include "vector.h" @@ -34,13 +35,13 @@ struct draw_instruction_t union { /* DI_SWITCH_PROGRAM */ - int program; + int program; /* DI_PUSH_VERTICES / DI_PUSH_INDICES */ - size_t count; + size_t count; /* DI_PROGRAM_SWITCH_TEXTURE */ - GLuint texture; + GLuint texture; /* DI_PROGRAM_SWITCH_FONT */ - texture_font_t *font; + xoverlay_font_handle_t font; }; }; @@ -96,7 +97,7 @@ void dis_program_switch_texture(GLuint texture); void -dis_program_switch_font(texture_font_t *font); +dis_program_switch_font(xoverlay_font_handle_t font); void dis_finish(); @@ -111,7 +112,9 @@ struct draw_state int program; int dirty; - GLuint texture; + GLuint texture; + xoverlay_font_handle_t font; + GLuint shader; }; @@ -141,6 +144,14 @@ ds_post_render(); void ds_render_next_frame(); +/* To be called by draw functions */ + +void +ds_prepare_texture(GLuint texture); + +void +ds_prepare_font(xoverlay_font_handle_t font); + /* To be called from programs */ void @@ -149,6 +160,9 @@ ds_bind_texture(GLuint texture); void ds_use_shader(GLuint shader); +void +ds_use_font(xoverlay_font_handle_t font); + /* Primitive Internal Drawing API */ void @@ -164,13 +178,10 @@ void draw_rect_textured(vec2 xy, vec2 hw, vec4 color, int texture, vec2 uv, vec2 st); void -draw_string(vec2 xy, const char *string, texture_font_t *font, vec4 color); +draw_string_internal(vec2 xy, const char *string, xoverlay_font_handle_t font, vec4 color, int *out_x, int *out_y); void -draw_string_outline(vec2 xy, const char *string, texture_font_t *font, vec4 color); +draw_string(vec2 xy, const char *string, xoverlay_font_handle_t font, vec4 color, int *out_x, int *out_y); void -draw_string_with_outline(vec2 xy, const char *string, texture_font_t *font, vec4 color, vec4 outline_color); - -void -get_string_size(const char *string, texture_font_t *font, vec2 *out); +draw_string_with_outline(vec2 xy, const char *string, xoverlay_font_handle_t font, vec4 color, vec4 outline_color, float outline_width, int adjust_outline_alpha, int *out_x, int *out_y); diff --git a/include/fontapi.h b/include/fontapi.h new file mode 100644 index 0000000..dcd268b --- /dev/null +++ b/include/fontapi.h @@ -0,0 +1,20 @@ +/* + * fontapi.h + * + * Created on: Nov 11, 2017 + * Author: nullifiedcat + */ + +#pragma once + +typedef unsigned int xoverlay_font_handle_t; +#define XOVERLAY_FONT_COUNT 64 + +xoverlay_font_handle_t +xoverlay_font_load(const char *path, float size); + +void +xoverlay_font_unload(xoverlay_font_handle_t handle); + +void +xoverlay_string_size(xoverlay_font_handle_t handle, const char *string, int *x, int *y); diff --git a/include/fontapi_internal.h b/include/fontapi_internal.h new file mode 100644 index 0000000..33621c0 --- /dev/null +++ b/include/fontapi_internal.h @@ -0,0 +1,34 @@ +/* + * fontapi_internal.h + * + * Created on: Nov 11, 2017 + * Author: nullifiedcat + */ + +#pragma once + +#include "fontapi.h" + +#include "freetype-gl.h" + +struct fontapi_font_t +{ + int init; + + texture_font_t *font; + texture_atlas_t *atlas; +}; + +struct fontapi_font_t loaded_fonts[XOVERLAY_FONT_COUNT]; + +texture_font_t* +fontapi_get(xoverlay_font_handle_t handle); + +int +fontapi_init(); + +void +fontapi_destroy(); + +xoverlay_font_handle_t +fontapi_add_font(struct fontapi_font_t font); diff --git a/include/overlay.h b/include/overlay.h index a677b51..634e063 100644 --- a/include/overlay.h +++ b/include/overlay.h @@ -7,6 +7,8 @@ #pragma once +#include "fontapi.h" + #include #include @@ -106,6 +108,11 @@ xoverlay_draw_rect(xoverlay_vec2_t xy, xoverlay_vec2_t hw, xoverlay_rgba_t color void xoverlay_draw_rect_outline(xoverlay_vec2_t xy, xoverlay_vec2_t hw, xoverlay_rgba_t color, float thickness); +void +xoverlay_draw_string(xoverlay_vec2_t xy, const char *string, xoverlay_font_handle_t font, xoverlay_vec4_t color, int *out_x, int *out_y); + +void +xoverlay_draw_string_with_outline(xoverlay_vec2_t xy, const char *string, xoverlay_font_handle_t font, xoverlay_vec4_t color, xoverlay_vec4_t outline_color, float outline_width, int adjust_outline_alpha, int *out_x, int *out_y); void xoverlay_poll_events(); void xoverlay_draw_begin(); diff --git a/include/programs.h b/include/programs.h index 44f5df4..2b479bc 100644 --- a/include/programs.h +++ b/include/programs.h @@ -9,6 +9,7 @@ #include "freetype-gl.h" #include "vertex-buffer.h" +#include "fontapi.h" struct draw_cmd; @@ -67,4 +68,4 @@ DECL_PROGRAM(triangles_textured); DECL_PROGRAM(freetype); void -program_freetype_switch_font(texture_font_t *font); +program_freetype_switch_font(xoverlay_font_handle_t font); diff --git a/src/drawglx.o b/src/drawglx.o index ce22706..d54eea0 100644 Binary files a/src/drawglx.o and b/src/drawglx.o differ diff --git a/src/drawglx_internal.c b/src/drawglx_internal.c index 947e70c..5d46812 100644 --- a/src/drawglx_internal.c +++ b/src/drawglx_internal.c @@ -200,7 +200,7 @@ dis_program_switch_texture(GLuint texture) } void -dis_program_switch_font(texture_font_t *font) +dis_program_switch_font(xoverlay_font_handle_t font) { struct draw_instruction_t *last = dis_last_pushed_instruction(); @@ -245,6 +245,7 @@ ds_init() memset(&ds, 0, sizeof(struct draw_state)); dis_init(); ds.program = -1; + ds.font = 0; mat4_set_identity(&ds.projection); mat4_set_identity(&ds.view); mat4_set_identity(&ds.model); @@ -316,6 +317,9 @@ ds_render_next_frame() ds_pre_render(); dis_finish(); ds.program = -1; + ds.font = 0; + ds.texture = 0; + ds.shader = 0; struct draw_instruction_t *instr; instr = dis_fetch_instruction(); @@ -374,6 +378,7 @@ ds_bind_texture(GLuint texture) { if (ds.texture != texture) { + printf("Swithing texture %u -> %u\n", ds.texture, texture); ds.texture = texture; glBindTexture(GL_TEXTURE_2D, texture); } @@ -384,11 +389,21 @@ ds_use_shader(GLuint shader) { if (ds.shader != shader) { + printf("Switching shader %u -> %u\n", ds.shader, shader); ds.shader = shader; glUseProgram(shader); } } +void +ds_use_font(xoverlay_font_handle_t font) +{ + if (ds.font != font) + { + ds.font = font; + } +} + void ds_prepare_program(int program) { @@ -399,6 +414,26 @@ ds_prepare_program(int program) } } +void +ds_prepare_texture(GLuint texture) +{ + if (texture != ds.texture) + { + dis_program_switch_texture(texture); + ds.texture = texture; + } +} + +void +ds_prepare_font(xoverlay_font_handle_t font) +{ + if (font != ds.font) + { + dis_program_switch_font(font); + ds.font = font; + } +} + void draw_line(vec2 xy, vec2 delta, vec4 color, float thickness) { @@ -529,25 +564,96 @@ draw_rect_textured(vec2 xy, vec2 hw, vec4 color, int texture, vec2 uv, vec2 st) } void -draw_string(vec2 xy, const char *string, texture_font_t *font, vec4 color) +draw_string_internal(vec2 xy, const char *string, xoverlay_font_handle_t font, vec4 color, int *out_x, int *out_y) { ds_prepare_program(PROGRAM_FREETYPE); + ds_prepare_font(font); + + texture_font_t *fnt = fontapi_get(font); + if (!fnt) + return; + + vec2 pen = { xy.x, xy.y }; + vec2 pen_start = pen; + vec2 size = { 0, 0 }; + texture_font_load_glyphs(fnt, string); + + for (size_t i = 0; i < strlen(string); ++i) + { + texture_glyph_t *glyph = texture_font_find_glyph(fnt, &string[i]); + if (glyph == NULL) + { + printf("glyph is NULL\n"); + continue; + } + if (i > 0) + { + pen.x += texture_glyph_get_kerning(glyph, &string[i - 1]); + } + + float x0 = (pen.x + glyph->offset_x); + float y0 = (pen.y - glyph->offset_y); + float x1 = (x0 + glyph->width); + float y1 = (y0 + glyph->height); + float s0 = glyph->s0; + float t0 = glyph->t0; + float s1 = glyph->s1; + float t1 = glyph->t1; + + GLuint idx = dstream.next_index; + GLuint indices[] = { idx, idx + 1, idx + 2, + idx + 2, idx + 3, idx }; + struct vertex_v2ft2fc4f vertices[] = { + { (vec2){ x0, y0 }, (vec2){ s0, t0 }, color }, + { (vec2){ x0, y1 }, (vec2){ s0, t1 }, color }, + { (vec2){ x1, y1 }, (vec2){ s1, t1 }, color }, + { (vec2){ x1, y0 }, (vec2){ s1, t0 }, color } + }; + + dis_push_indices(6, indices); + dis_push_vertices(4, sizeof(struct vertex_v2ft2fc4f), vertices); + + pen.x += glyph->advance_x; + if (glyph->height > size.y) + size.y = glyph->height; + } + size.x = pen.x - pen_start.x; + if (out_x) + *out_x = size.x; + if (out_y) + *out_y = size.y; } void -draw_string_outline(vec2 xy, const char *string, texture_font_t *font, vec4 color) +draw_string(vec2 xy, const char *string, xoverlay_font_handle_t font, vec4 color, int *out_x, int *out_y) { ds_prepare_program(PROGRAM_FREETYPE); + ds_prepare_font(font); + + texture_font_t *fnt = fontapi_get(font); + fnt->rendermode = RENDER_NORMAL; + fnt->outline_thickness = 0.0f; + + draw_string_internal(xy, string, font, color, out_x, out_y); } void -draw_string_with_outline(vec2 xy, const char *string, texture_font_t *font, vec4 color, vec4 outline_color) +draw_string_with_outline(vec2 xy, const char *string, xoverlay_font_handle_t font, vec4 color, vec4 outline_color, float outline_width, int adjust_outline_alpha, int *out_x, int *out_y) { ds_prepare_program(PROGRAM_FREETYPE); -} + ds_prepare_font(font); -void -get_string_size(const char *string, texture_font_t *font, vec2 *out) -{ + if (adjust_outline_alpha) + outline_color.a = color.a; + + texture_font_t *fnt = fontapi_get(font); + + fnt->rendermode = RENDER_OUTLINE_POSITIVE; + fnt->outline_thickness = outline_width; + draw_string_internal(xy, string, font, outline_color, 0, 0); + + fnt->rendermode = RENDER_NORMAL; + fnt->outline_thickness = 0.0f; + draw_string_internal(xy, string, font, color, out_x, out_y); } diff --git a/src/drawglx_internal.o b/src/drawglx_internal.o index 388ff1a..29fe5ec 100644 Binary files a/src/drawglx_internal.o and b/src/drawglx_internal.o differ diff --git a/src/fontapi.c b/src/fontapi.c new file mode 100644 index 0000000..e6ac169 --- /dev/null +++ b/src/fontapi.c @@ -0,0 +1,82 @@ +/* + * fontapi.c + * + * Created on: Nov 11, 2017 + * Author: nullifiedcat + */ + +#include "fontapi_internal.h" + +#include +#include + +int +fontapi_init() +{ + memset(loaded_fonts, 0, sizeof(loaded_fonts)); + return 0; +} + +void +fontapi_destroy() +{ + +} + +xoverlay_font_handle_t +xoverlay_font_load(const char *path, float size) +{ + struct fontapi_font_t result; + memset(&result, 0, sizeof(result)); + result.atlas = texture_atlas_new(1024, 1024, 1); + result.font = texture_font_new_from_file(result.atlas, size, path); + + return fontapi_add_font(result); +} + +void +xoverlay_font_unload(xoverlay_font_handle_t handle) +{ + if (handle == 0) + return; + if (handle > XOVERLAY_FONT_COUNT) + return; + if (loaded_fonts[handle - 1].init == 0) + return; + + texture_atlas_delete(loaded_fonts[handle - 1].atlas); + texture_font_delete(loaded_fonts[handle - 1].font); +} + +xoverlay_font_handle_t +fontapi_add_font(struct fontapi_font_t font) +{ + for (xoverlay_font_handle_t i = 0; i < XOVERLAY_FONT_COUNT; ++i) + { + if (loaded_fonts[i].init == 0) + { + memcpy(&loaded_fonts[i], &font, sizeof(font)); + loaded_fonts[i].init = 1; + return i + 1; + } + } + return 0; +} + +texture_font_t* +fontapi_get(xoverlay_font_handle_t handle) +{ + if (handle == 0) + return NULL; + if (handle >= XOVERLAY_FONT_COUNT) + return NULL; + if (loaded_fonts[handle - 1].init == 0) + return NULL; + return loaded_fonts[handle - 1].font; +} + +void +xoverlay_string_size(xoverlay_font_handle_t handle, const char *string, int *x, int *y) +{ + +} diff --git a/src/fontapi.o b/src/fontapi.o new file mode 100644 index 0000000..a183610 Binary files /dev/null and b/src/fontapi.o differ diff --git a/src/overlay.c b/src/overlay.c index 9264427..19f1e71 100644 --- a/src/overlay.c +++ b/src/overlay.c @@ -251,6 +251,19 @@ void xoverlay_poll_events() }*/ } +void +xoverlay_draw_string(xoverlay_vec2_t xy, const char *string, xoverlay_font_handle_t font, xoverlay_vec4_t color, int *out_x, int *out_y) +{ + draw_string(*(vec2*)&xy, string, font, *(vec4*)&color, out_x, out_y); +} + +void +xoverlay_draw_string_with_outline(xoverlay_vec2_t xy, const char *string, xoverlay_font_handle_t font, xoverlay_vec4_t color, xoverlay_vec4_t outline_color, float outline_width, int adjust_outline_alpha, int *out_x, int *out_y) +{ + draw_string_with_outline(*(vec2*)&xy, string, font, *(vec4*)&color, *(vec4*)&outline_color, outline_width, adjust_outline_alpha, out_x, out_y); +} + + void xoverlay_draw_begin() { if (!xoverlay_library.init) return; diff --git a/src/overlay.o b/src/overlay.o index 592f35a..2000bc9 100644 Binary files a/src/overlay.o and b/src/overlay.o differ diff --git a/src/program_freetype.c b/src/program_freetype.c index 4998dab..986251a 100644 --- a/src/program_freetype.c +++ b/src/program_freetype.c @@ -10,21 +10,20 @@ #include "freetype-gl.h" #include "programs.h" #include "texture-atlas.h" - -texture_atlas_t *atlas; -texture_font_t *font; -vec2 pen; +#include "drawglx_internal.h" DECL_PROGRAM_INIT(freetype) { - atlas = texture_atlas_new(1024, 1024, 1); - font = texture_font_new_from_file(atlas, 14, "/usr/share/fonts/truetype/freefont/FreeMono.ttf"); - glGenTextures(1, &atlas->id); } DECL_PROGRAM_LOAD(freetype) { vertex_buffer_clear(programs[PROGRAM_FREETYPE].vertex); + ds_use_shader(programs[PROGRAM_FREETYPE].shader); + texture_font_t *fnt = fontapi_get(ds.font); + if (fnt == NULL) + return; + ds_bind_texture(fnt->atlas->id); } DECL_PROGRAM_RENDER(freetype) @@ -41,13 +40,28 @@ DECL_PROGRAM_UNLOAD(freetype) DECL_PROGRAM_DESTROY(freetype) { - texture_atlas_delete(atlas); - texture_font_delete(font); } void -program_freetype_switch_font(texture_font_t *font) +program_freetype_switch_font(xoverlay_font_handle_t font) { - + texture_font_t *fnt = fontapi_get(font); + if (fnt == NULL) + return; + printf("Switching font to %u\n", font); + if (fnt->atlas->id == 0) + { + glGenTextures(1, &fnt->atlas->id); + } + ds_bind_texture(fnt->atlas->id); + if (fnt->atlas->dirty) { + printf("Refreshing atlas\n"); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, fnt->atlas->width, fnt->atlas->height, 0, GL_RED, GL_UNSIGNED_BYTE, fnt->atlas->data); + fnt->atlas->dirty = 0; + } } diff --git a/src/program_freetype.o b/src/program_freetype.o index f8dc975..28d11d0 100644 Binary files a/src/program_freetype.o and b/src/program_freetype.o differ diff --git a/src/program_triangles_plain.c b/src/program_triangles_plain.c index 46b40ca..7374621 100644 --- a/src/program_triangles_plain.c +++ b/src/program_triangles_plain.c @@ -8,6 +8,7 @@ #include #include "programs.h" +#include "drawglx_internal.h" DECL_PROGRAM_INIT(triangles_plain) { diff --git a/src/program_triangles_plain.o b/src/program_triangles_plain.o index 1175427..4afd7cc 100644 Binary files a/src/program_triangles_plain.o and b/src/program_triangles_plain.o differ diff --git a/src/program_triangles_textured.o b/src/program_triangles_textured.o index 2d8d9d0..4e08454 100644 Binary files a/src/program_triangles_textured.o and b/src/program_triangles_textured.o differ diff --git a/src/programs.c b/src/programs.c index 440af7e..abcbf85 100644 --- a/src/programs.c +++ b/src/programs.c @@ -108,7 +108,8 @@ const char *shader_v2ft2fc4f_frag = "uniform sampler2D texture;\n" "void main()\n" "{\n" - " gl_FragColor = texture2D(texture, gl_TexCoord[0].xy) * gl_Color;\n" + " float a = texture2D(texture, gl_TexCoord[0].xy).r;\n" + "gl_FragColor = vec4(gl_Color.rgb, gl_Color.a*a);\n" "}"; void diff --git a/src/programs.o b/src/programs.o index 824fdb0..b93af79 100644 Binary files a/src/programs.o and b/src/programs.o differ