diff --git a/text_rendering/font.c b/text_rendering/font.c index a3c4175..6504eec 100644 --- a/text_rendering/font.c +++ b/text_rendering/font.c @@ -107,8 +107,8 @@ int font_free(struct font_atlas *atlas) // errors height and width must be equal const struct font_glyph * font_get_glyph_texture(struct font_atlas *atlas, unsigned int code, int *updated) { - int u = 0; - if (!updated) updated = &u; + int _u = 0; + if (!updated) updated = &_u; const struct font_glyph *r; if ((r = cache_search(&PRIV(atlas)->c, code)) != NULL) { @@ -120,7 +120,8 @@ const struct font_glyph * font_get_glyph_texture(struct font_atlas *atlas, unsig // generate the sdf and put it into the cache // TODO: generate the whole block at once int idx = stbtt_FindGlyphIndex(&PRIV(atlas)->stb, code); - int x0,y0,x1,y1,gw,gh,l,off_x,off_y,adv; + int x0,y0,x1,y1,gw,gh,l,off_x,off_y,adv,base; + base = atlas->glyph_max_h - PRIV(atlas)->baseline; stbtt_GetGlyphBitmapBoxSubpixel( &PRIV(atlas)->stb, idx, @@ -149,19 +150,19 @@ const struct font_glyph * font_get_glyph_texture(struct font_atlas *atlas, unsig // TODO: bounds check usign atlas height // TODO: clear spot area in the atlas before writing on it unsigned int spot = cache_get(&PRIV(atlas)->c); - unsigned int oy = ((atlas->glyph_max_w * spot) / atlas->width) * atlas->glyph_max_h; - unsigned int ox = (atlas->glyph_max_w * spot) % atlas->width; + unsigned int ty = ((atlas->glyph_max_w * spot) / atlas->width) * atlas->glyph_max_h; + unsigned int tx = (atlas->glyph_max_w * spot) % atlas->width; unsigned int w = atlas->width; unsigned char *a = (void *)atlas->atlas; - //printf("max:%d %d spot:%d : %d %d %d %d\n", atlas->glyph_max_w, atlas->glyph_max_h, spot, ox, oy, off_x, off_y); + //printf("max:%d %d spot:%d : %d %d %d %d\n", atlas->glyph_max_w, atlas->glyph_max_h, spot, tx, ty, off_x, off_y); for (int y = 0; y < gh; y++) { for (int x = 0; x < gw; x++) { int c, r; - r = (oy+y)*w; - c = ox+x; + r = (ty+y)*w; + c = tx+x; a[r+c] = PRIV(atlas)->bitmap[y*atlas->glyph_max_w+x]; } } @@ -169,12 +170,12 @@ const struct font_glyph * font_get_glyph_texture(struct font_atlas *atlas, unsig // FIXME: get the advance struct font_glyph g = { .codepoint = code, - .u = ox, - .v = oy, + .u = tx, + .v = ty, .w = gw, .h = gh, .x = off_x, - .y = off_y, + .y = off_y-base, .a = adv, }; return cache_insert(&PRIV(atlas)->c, &g, g.codepoint, spot); diff --git a/text_rendering/main.c b/text_rendering/main.c index 6af1070..09ef219 100644 --- a/text_rendering/main.c +++ b/text_rendering/main.c @@ -8,7 +8,9 @@ #include "util.h" -const char *str = "Ciao Mamma!\nprova: òçà°ù§|¬³¼$£ì\t"; +//const char *str1 = "Ciao Mamma!\nprova: òçà°ù§|¬³¼$£ì\t"; +const char *str1 = "j"; +const char *str2 = "gmt"; SDL_Window *win; @@ -17,10 +19,14 @@ void draw(void) static unsigned int frame = 0; printf("frame: %d\n", frame++); ren_clear(); - if (ren_render_text(str, 10, 10, 100, 50, 20)) + ren_render_box(10, 10, 100, 50, 0xffff0000); + if (ren_render_text(str1, 10, 10, 100, 50, 20)) printf("text: %s\n", ren_strerror()); - ren_render_text("altro font", 200, 40, 300, 300, 40); - ren_render_box(100, 300, 50, 50, 0xffff0000); + int w, h; + ren_get_text_box(str2, &w, &h, 40); + printf("box for: %s -> (%d, %d)\n", str2, w, h); + ren_render_box(200, 40, w, h, 0xffff0000); + ren_render_text(str2, 200, 40, 300, 300, 40); SDL_GL_SwapWindow(win); } @@ -30,6 +36,7 @@ int main(void) SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS); SDL_SetHint(SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR, "0"); SDL_SetHint(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, "1"); + SDL_SetHint(SDL_HINT_VIDEO_HIGHDPI_DISABLED, "0"); win = SDL_CreateWindow( "test render", @@ -37,7 +44,7 @@ int main(void) SDL_WINDOWPOS_UNDEFINED, 500, 500, - SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE); + SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI); if (ren_init(win)) { printf("renderer init error: %s\n", ren_strerror()); return 1; diff --git a/text_rendering/ren.c b/text_rendering/ren.c index 26aa9ab..b159af4 100644 --- a/text_rendering/ren.c +++ b/text_rendering/ren.c @@ -1,7 +1,6 @@ #include #include #include -#include #include #include #include @@ -19,6 +18,7 @@ __FILE__, __LINE__, __func__, x, a, glerr[a]); \ } #define GL(f) f; GLERR(#f) +#define REN_RET(a,b) {ren_errno = b; return a;} enum REN_ERR { @@ -101,29 +101,29 @@ static int ren_errno; // print shader compilation errors -static int shader_compile_error(GLuint shader) +static int shader_compile_error(GLuint shader, const char *path) { GLint status; - glGetShaderiv(shader, GL_COMPILE_STATUS, &status); + GL(glGetShaderiv(shader, GL_COMPILE_STATUS, &status)) if (status != GL_FALSE) return 0; GLint log_length; - glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &log_length); + GL(glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &log_length)) GLchar *log_str = emalloc((log_length + 1)*sizeof(GLchar)); - glGetShaderInfoLog(shader, log_length, NULL, log_str); + GL(glGetShaderInfoLog(shader, log_length, NULL, log_str)) const char *shader_type_str = NULL; GLint shader_type; - glGetShaderiv(shader, GL_SHADER_TYPE, &shader_type); + GL(glGetShaderiv(shader, GL_SHADER_TYPE, &shader_type)) switch(shader_type) { case GL_VERTEX_SHADER: shader_type_str = "vertex"; break; case GL_GEOMETRY_SHADER: shader_type_str = "geometry"; break; case GL_FRAGMENT_SHADER: shader_type_str = "fragment"; break; } - fprintf(stderr, "Compile failure in %s shader:\n%s\n", shader_type_str, log_str); + fprintf(stderr, "Compile failure in %s shader %s:\n%s\n", shader_type_str, path, log_str); efree(log_str); return -1; } @@ -133,15 +133,15 @@ static int shader_compile_error(GLuint shader) static int shader_link_error(GLuint prog) { GLint status; - glGetProgramiv (prog, GL_LINK_STATUS, &status); + GL(glGetProgramiv(prog, GL_LINK_STATUS, &status)) if (status != GL_FALSE) return 0; GLint log_length; - glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &log_length); + GL(glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &log_length)) GLchar *log_str = emalloc((log_length + 1)*sizeof(GLchar)); - glGetProgramInfoLog(prog, log_length, NULL, log_str); + GL(glGetProgramInfoLog(prog, log_length, NULL, log_str)) fprintf(stderr, "Linker failure: %s\n", log_str); efree(log_str); @@ -149,8 +149,7 @@ static int shader_link_error(GLuint prog) } -#define REN_RET(a,b) {ren_errno = b; return a;} -static GLuint shader_compile(const char *shader, GLuint type) +static GLuint shader_compile(const char *path, const char *shader, GLuint type) { GLuint s; // initialize the vertex shader and get the corresponding id @@ -159,7 +158,7 @@ static GLuint shader_compile(const char *shader, GLuint type) // get the shader into opengl GL(glShaderSource(s, 1, &shader, NULL)) GL(glCompileShader(s)) - if (shader_compile_error(s)) + if (shader_compile_error(s, path)) REN_RET(0, REN_COMPILE) return s; } @@ -184,14 +183,14 @@ static GLuint ren_compile_program(const char *vs_path, const char *fs_path) dump_file(vs_path, &str, NULL); if (!str) REN_RET(0, REN_ERRNO) - gl_vertshader = shader_compile(str, GL_VERTEX_SHADER); + gl_vertshader = shader_compile(vs_path, str, GL_VERTEX_SHADER); efree(str); if (!gl_vertshader) return 0; dump_file(fs_path, &str, NULL); if (!str) REN_RET(0, REN_ERRNO) - gl_fragshader = shader_compile(str, GL_FRAGMENT_SHADER); + gl_fragshader = shader_compile(fs_path, str, GL_FRAGMENT_SHADER); efree(str); if (!gl_fragshader) return 0; @@ -218,6 +217,15 @@ static GLuint ren_compile_program(const char *vs_path, const char *fs_path) } +static void set_texture_parameters(GLuint type, GLuint wrap_s, GLuint wrap_t, GLuint upscale, GLuint downscale) +{ + GL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_s)) + GL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_t)) + GL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, upscale)) + GL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, downscale)) +} + + static GLuint ren_texturergb_2d(const char *buf, int w, int h, int upscale, int downscale) { GLuint t; @@ -231,24 +239,12 @@ static GLuint ren_texturergb_2d(const char *buf, int w, int h, int upscale, int GL(glBindTexture(GL_TEXTURE_2D, t)) GL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, buf)) - GL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT)) - GL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)) - GL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, downscale)) - GL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, upscale)) + set_texture_parameters(GL_TEXTURE_2D, GL_REPEAT, GL_REPEAT, upscale, downscale); return t; } -static void set_texture_parameters(GLuint type, GLuint wrap_s, GLuint wrap_t, GLuint upscale, GLuint downscale) -{ - GL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_s)) - GL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_t)) - GL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, upscale)) - GL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, downscale)) -} - - static GLuint ren_texturergba_2d(const char *buf, int w, int h, int upscale, int downscale) { GLuint t; @@ -374,17 +370,27 @@ int ren_init(SDL_Window *w) // Initialize OpenGL if (!w) REN_RET(-1, REN_INVAL) + // using version 3 does not allow to use glVertexAttribPointer() without + // vertex buffer objects + // TODO: make the switch to opengl 3.3 to go with the shader versions + //SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1); + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); ren.gl = SDL_GL_CreateContext(w); - if (!ren.gl) + if (!ren.gl) { + printf("SDL: %s\n", SDL_GetError()); REN_RET(-1, REN_CONTEXT) + } GL(glEnable(GL_BLEND)) GL(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)) GL(glDisable(GL_CULL_FACE)) GL(glDisable(GL_DEPTH_TEST)) GL(glEnable(GL_SCISSOR_TEST)) - GL(glEnable(GL_TEXTURE_2D)) - GL(glEnable(GL_TEXTURE_RECTANGLE)) +// GL(glEnable(GL_TEXTURE_2D)) +// GL(glEnable(GL_TEXTURE_RECTANGLE)) GLenum glew_err = glewInit(); if (glew_err != GLEW_OK) @@ -492,6 +498,7 @@ static int ren_draw_font_stack(int idx) GL(glDisableVertexAttribArray(REN_VERTEX_IDX)) GL(glDisableVertexAttribArray(REN_UV_IDX)) GL(glBindBuffer(GL_ARRAY_BUFFER, 0)) + GL(glBindTexture(GL_TEXTURE_RECTANGLE, 0)) GL(glUseProgram(0)) vtstack_clear(&ren.font_stack); @@ -576,7 +583,7 @@ int ren_set_scissor(int x, int y, int w, int h) static int ren_push_glyph(const struct font_glyph *g, int gx, int gy) { /* x4,y4 x3,y3 - * +-------------+ + * o-------------+ * |(x,y) /| * | / | * | 2 / | @@ -589,7 +596,7 @@ static int ren_push_glyph(const struct font_glyph *g, int gx, int gy) struct v_text v; struct font_glyph c; c = *g; - //printf("g: u=%d v=%d w=%d h=%d a=%d x=%d y=%d\n", c.u, c.v, c.w, c.h, c.a, c.x, c.y); + printf("g: u=%d v=%d w=%d h=%d a=%d x=%d y=%d\n", c.u, c.v, c.w, c.h, c.a, c.x, c.y); //printf("v: x=%d y=%d u=%d v=%d\n", v.pos.x, v.pos.y, v.uv.u, v.uv.v); // x1,y1 v = (struct v_text){ @@ -643,6 +650,7 @@ int ren_get_text_box(const char *str, int *rw, int *rh, int size) if (idx < 0) return -1; + h = y = ren.fonts[idx].font->glyph_max_h; for (off = 0; (ret = grapheme_decode_utf8(str+off, SIZE_MAX, &cp)) > 0 && cp != 0; off += ret) { if (iscntrl(cp)) goto skip_get; g = font_get_glyph_texture(ren.fonts[idx].font, cp, &updated); @@ -736,7 +744,7 @@ int ren_render_text(const char *str, int x, int y, int w, int h, int size) static int ren_push_box(int x, int y, int w, int h, unsigned int color) { /* x4,y4 x3,y3 - * +-------------+ + * o-------------+ * |(x,y) /| * | / | * | 2 / |