working fonts

This commit is contained in:
nullifiedcat 2017-11-11 15:16:58 +03:00
parent 29914468df
commit e79aa9488f
27 changed files with 330 additions and 33 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -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;
}

View File

@ -110,6 +110,11 @@ typedef struct texture_atlas_t
*/
unsigned char * data;
/**
* Custom field
*/
char dirty;
} texture_atlas_t;

Binary file not shown.

Binary file not shown.

View File

@ -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);

20
include/fontapi.h Normal file
View File

@ -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);

View File

@ -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);

View File

@ -7,6 +7,8 @@
#pragma once
#include "fontapi.h"
#include <X11/Xlib.h>
#include <X11/XKBlib.h>
@ -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();

View File

@ -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);

Binary file not shown.

View File

@ -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);
}

Binary file not shown.

82
src/fontapi.c Normal file
View File

@ -0,0 +1,82 @@
/*
* fontapi.c
*
* Created on: Nov 11, 2017
* Author: nullifiedcat
*/
#include "fontapi_internal.h"
#include <string.h>
#include <memory.h>
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)
{
}

BIN
src/fontapi.o Normal file

Binary file not shown.

View File

@ -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;

Binary file not shown.

View File

@ -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;
}
}

Binary file not shown.

View File

@ -8,6 +8,7 @@
#include <GL/glew.h>
#include "programs.h"
#include "drawglx_internal.h"
DECL_PROGRAM_INIT(triangles_plain)
{

Binary file not shown.

Binary file not shown.

View File

@ -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

Binary file not shown.