diff options
| author | Aldrik Ramaekers <aldrik.ramaekers@protonmail.com> | 2020-02-04 14:53:49 +0100 |
|---|---|---|
| committer | Aldrik Ramaekers <aldrik.ramaekers@protonmail.com> | 2020-02-04 14:53:49 +0100 |
| commit | e271c4518fd02c8dac2343ef0b9fd2cecd0812be (patch) | |
| tree | 74b79885021d97ef83dd25bb596f8a20b090c4ce /src | |
| parent | 3cb8d5ce252c246e2218a05968dc10db38116994 (diff) | |
fix text calculation and rendering floating error
Diffstat (limited to 'src')
| -rw-r--r-- | src/assets.c | 4 | ||||
| -rw-r--r-- | src/assets.h | 2 | ||||
| -rw-r--r-- | src/render.c | 174 | ||||
| -rw-r--r-- | src/render.h | 1 | ||||
| -rw-r--r-- | src/ui.c | 75 |
5 files changed, 162 insertions, 94 deletions
diff --git a/src/assets.c b/src/assets.c index 0ba6192..d5f1540 100644 --- a/src/assets.c +++ b/src/assets.c @@ -129,6 +129,10 @@ bool assets_queue_worker_load_font(font *font) new_glyph.xoff = xoff; new_glyph.yoff = yoff; + stbtt_GetCodepointHMetrics(&info, i, &new_glyph.advance, &new_glyph.lsb); + new_glyph.advance *= scale; + new_glyph.lsb *= scale; + if (i == 'M') font->px_h = -yoff; font->glyphs[i-TEXT_CHARSET_START] = new_glyph; diff --git a/src/assets.h b/src/assets.h index 1b76785..a9816b5 100644 --- a/src/assets.h +++ b/src/assets.h @@ -28,6 +28,8 @@ typedef struct t_glyph { s32 width; s32 height; + s32 advance; + s32 lsb; s32 xoff; s32 yoff; void *bitmap; diff --git a/src/render.c b/src/render.c index 666b2f9..7f61ce8 100644 --- a/src/render.c +++ b/src/render.c @@ -88,11 +88,8 @@ s32 render_text_ellipsed(font *font, s32 x, s32 y, s32 maxw, char *text, color t s32 width = g.width; - int advance, lsb, kern; - stbtt_GetCodepointHMetrics(&font->info, ch, &advance, &lsb); - s32 y_ = y + font->px_h + g.yoff; - s32 x_to_render = x_ + (lsb*font->scale); + s32 x_to_render = x_ + (g.lsb); glTexCoord2i(0, 0); glVertex3i(x_to_render,y_, render_depth); glTexCoord2i(0, 1); glVertex3i(x_to_render,y_+g.height, render_depth); @@ -102,8 +99,8 @@ s32 render_text_ellipsed(font *font, s32 x, s32 y, s32 maxw, char *text, color t glEnd(); /* add kerning */ - kern = stbtt_GetCodepointKernAdvance(&font->info, ch, ch_next); - x_ += (advance*font->scale)+(kern*font->scale); + //kern = stbtt_GetCodepointKernAdvance(&font->info, ch, ch_next); + x_ += (g.advance); if (!in_ellipse && (x_-x) > maxw-(font->glyphs['.'].width*3)) { @@ -117,7 +114,7 @@ s32 render_text_ellipsed(font *font, s32 x, s32 y, s32 maxw, char *text, color t return maxw; } -s32 render_text(font *font, s32 x, s32 y, char *text, color tint) +s32 render_text_with_selection(font *font, s32 x, s32 y, char *text, color tint, s32 selection_start, s32 selection_length) { if (!font->loaded) return 0; @@ -127,6 +124,9 @@ s32 render_text(font *font, s32 x, s32 y, char *text, color tint) s32 x_ = x; utf8_int32_t ch; + s32 index = 0; + s32 selection_start_x = x_; + s32 selection_end_x = x_; while((text = utf8codepoint(text, &ch)) && ch) { if (ch == 9) ch = 32; @@ -144,11 +144,119 @@ s32 render_text(font *font, s32 x, s32 y, char *text, color tint) s32 width = g.width; - int advance, lsb, kern; - stbtt_GetCodepointHMetrics(&font->info, ch, &advance, &lsb); + s32 y_ = y + font->px_h + g.yoff; + s32 x_to_render = x_ + (g.lsb); + + glTexCoord2i(0, 0); glVertex3i(x_to_render,y_, render_depth); + glTexCoord2i(0, 1); glVertex3i(x_to_render,y_+g.height, render_depth); + glTexCoord2i(1, 1); glVertex3i(x_to_render+g.width,y_+g.height, render_depth); + glTexCoord2i(1, 0); glVertex3i(x_to_render+g.width,y_, render_depth); + + glEnd(); + + /* add kerning */ + //kern = stbtt_GetCodepointKernAdvance(&font->info, ch, ch_next); + x_ += (g.advance); + + index++; + if (index == selection_start) + { + selection_start_x = x_; + } + if (index == selection_start+selection_length) + { + selection_end_x = x_; + } + } + + glDisable(GL_TEXTURE_2D); + + render_rectangle(selection_start_x, y-3, selection_end_x-selection_start_x, TEXTBOX_HEIGHT - 10, rgba(66, 134, 244, 120)); + + return x_ - x; +} + +s32 render_text_with_cursor(font *font, s32 x, s32 y, char *text, color tint, s32 cursor_pos) +{ + if (!font->loaded) + return 0; + + glEnable(GL_TEXTURE_2D); + glColor4f(tint.r/255.0f, tint.g/255.0f, tint.b/255.0f, tint.a/255.0f); + + float x_ = x; + utf8_int32_t ch; + s32 index = 0; + s32 cursor_x = x_; + while((text = utf8codepoint(text, &ch)) && ch) + { + if (ch == 9) ch = 32; + utf8_int32_t ch_next; + utf8codepoint(text, &ch_next); + if (ch < TEXT_CHARSET_START || ch > TEXT_CHARSET_END) + { + ch = 0x3f; + } + + glyph g = font->glyphs[ch]; + + glBindTexture(GL_TEXTURE_2D, g.textureID); + glBegin(GL_QUADS); + + s32 y_ = y + font->px_h + g.yoff; + s32 x_to_render = x_ + (g.lsb); + + glTexCoord2i(0, 0); glVertex3i(x_to_render,y_, render_depth); + glTexCoord2i(0, 1); glVertex3i(x_to_render,y_+g.height, render_depth); + glTexCoord2i(1, 1); glVertex3i(x_to_render+g.width,y_+g.height, render_depth); + glTexCoord2i(1, 0); glVertex3i(x_to_render+g.width,y_, render_depth); + + glEnd(); + + /* add kerning */ + //kern = stbtt_GetCodepointKernAdvance(&font->info, ch, ch_next); + x_ += (g.advance); + index++; + + if (index == cursor_pos) + { + cursor_x = x_; + } + } + glDisable(GL_TEXTURE_2D); + + render_rectangle(cursor_x, y-3, 2, TEXTBOX_HEIGHT - 10, global_ui_context.style.textbox_foreground); + + return x_ - x; +} + +s32 render_text(font *font, s32 x, s32 y, char *text, color tint) +{ + if (!font->loaded) + return 0; + + glEnable(GL_TEXTURE_2D); + glColor4f(tint.r/255.0f, tint.g/255.0f, tint.b/255.0f, tint.a/255.0f); + + s32 x_ = x; + utf8_int32_t ch; + while((text = utf8codepoint(text, &ch)) && ch) + { + if (ch == 9) ch = 32; + utf8_int32_t ch_next; + utf8codepoint(text, &ch_next); + if (ch < TEXT_CHARSET_START || ch > TEXT_CHARSET_END) + { + ch = 0x3f; + } + + glyph g = font->glyphs[ch]; + + glBindTexture(GL_TEXTURE_2D, g.textureID); + glBegin(GL_QUADS); s32 y_ = y + font->px_h + g.yoff; - s32 x_to_render = x_ + (lsb*font->scale); + s32 x_to_render = x_ + (g.lsb); glTexCoord2i(0, 0); glVertex3i(x_to_render,y_, render_depth); glTexCoord2i(0, 1); glVertex3i(x_to_render,y_+g.height, render_depth); @@ -158,8 +266,8 @@ s32 render_text(font *font, s32 x, s32 y, char *text, color tint) glEnd(); /* add kerning */ - kern = stbtt_GetCodepointKernAdvance(&font->info, ch, ch_next); - x_ += (advance*font->scale)+(kern*font->scale); + //kern = stbtt_GetCodepointKernAdvance(&font->info, ch, ch_next); + x_ += (g.advance); } glDisable(GL_TEXTURE_2D); @@ -213,13 +321,8 @@ s32 render_text_cutoff(font *font, s32 x, s32 y, char *text, color tint, u16 cut glBindTexture(GL_TEXTURE_2D, g.textureID); glBegin(GL_QUADS); - s32 width = g.width; - - int advance, lsb, kern; - stbtt_GetCodepointHMetrics(&font->info, ch, &advance, &lsb); - s32 y__ = y_ + font->px_h + g.yoff; - s32 x_to_render = x_ + (lsb*font->scale); + s32 x_to_render = x_ + (g.lsb); glTexCoord2i(0, 0); glVertex3i(x_to_render,y__, render_depth); glTexCoord2i(0, 1); glVertex3i(x_to_render,y__+g.height, render_depth); @@ -229,8 +332,8 @@ s32 render_text_cutoff(font *font, s32 x, s32 y, char *text, color tint, u16 cut glEnd(); /* add kerning */ - kern = stbtt_GetCodepointKernAdvance(&font->info, ch, ch_next); - x_ += (advance*font->scale)+(kern*font->scale); + //kern = stbtt_GetCodepointKernAdvance(&font->info, ch, ch_next); + x_ += (g.advance); if (x_ > x+cutoff_width) { @@ -271,13 +374,9 @@ s32 calculate_cursor_position(font *font, char *text, s32 click_x) s32 width_next = font->glyphs[ch_next].width; - int advance, lsb, kern; - stbtt_GetCodepointHMetrics(&font->info, ch, &advance, &lsb); - /* add kerning */ - kern = stbtt_GetCodepointKernAdvance(&font->info, ch, ch_next); - x += (advance*font->scale)+(kern*font->scale); - + //kern = stbtt_GetCodepointKernAdvance(&font->info, ch, ch_next); + x += (g.advance); if (x - (width_next/5) > click_x) { return index; @@ -314,12 +413,9 @@ s32 calculate_text_width_from_upto(font *font, char *text, s32 from, s32 index) if (i >= from) { - int advance, lsb, kern; - stbtt_GetCodepointHMetrics(&font->info, ch, &advance, &lsb); - /* add kerning */ - kern = stbtt_GetCodepointKernAdvance(&font->info, ch, ch_next); - x += (advance*font->scale)+(kern*font->scale); + //kern = stbtt_GetCodepointKernAdvance(&font->info, ch, ch_next); + x += (g.advance); } i++; @@ -351,12 +447,9 @@ s32 calculate_text_width_upto(font *font, char *text, s32 index) glyph g = font->glyphs[ch]; s32 width = g.width; - int advance, lsb, kern; - stbtt_GetCodepointHMetrics(&font->info, ch, &advance, &lsb); - /* add kerning */ - kern = stbtt_GetCodepointKernAdvance(&font->info, ch, ch_next); - x += (advance*font->scale)+(kern*font->scale); + //kern = stbtt_GetCodepointKernAdvance(&font->info, ch, ch_next); + x += (g.advance); i++; } @@ -369,7 +462,7 @@ s32 calculate_text_width(font *font, char *text) if (!font->loaded) return 0; - s32 x = 0; + float x = 0; utf8_int32_t ch; while((text = utf8codepoint(text, &ch)) && ch) { @@ -384,12 +477,9 @@ s32 calculate_text_width(font *font, char *text) glyph g = font->glyphs[ch]; s32 width = g.width; - int advance, lsb, kern; - stbtt_GetCodepointHMetrics(&font->info, ch, &advance, &lsb); - /* add kerning */ - kern = stbtt_GetCodepointKernAdvance(&font->info, ch, ch_next); - x += (advance*font->scale)+(kern*font->scale); + //kern = stbtt_GetCodepointKernAdvance(&font->info, ch, ch_next); + x += (g.advance); } return x; diff --git a/src/render.h b/src/render.h index 4d29eea..de6ff6d 100644 --- a/src/render.h +++ b/src/render.h @@ -39,6 +39,7 @@ s32 render_text(font *font, s32 x, s32 y, char *text, color tint); s32 render_text_ellipsed(font *font, s32 x, s32 y, s32 maxw, char *text, color tint); s32 render_text_cutoff(font *font, s32 x, s32 y, char *text, color tint, u16 cutoff_width); s32 render_text_vertical(font *font, s32 x, s32 y, char *text, color tint); +s32 render_text_with_cursor(font *font, s32 x, s32 y, char *text, color tint, s32 cursor_pos); s32 calculate_cursor_position(font *font, char *text, s32 click_x); s32 calculate_text_width(font *font, char *text); @@ -675,10 +675,6 @@ bool ui_push_textbox(textbox_state *state, char *placeholder) } s32 cursor_text_w; - s32 cursor_x = 0; - - //if (!global_ui_context.keyboard->has_selection) - //state->diff = 0; // select first character on click if (clicked_to_set_cursor) @@ -780,10 +776,9 @@ bool ui_push_textbox(textbox_state *state, char *placeholder) s32 text_w = calculate_text_width(global_ui_context.font_small, state->buffer); - cursor_x = text_x + cursor_text_w - state->diff; - +#if 1 // change offset after cursor position change - if (!is_selecting && !global_ui_context.keyboard->has_selection) + if (!is_selecting && !global_ui_context.keyboard->has_selection && !state->attempting_to_select) { if (cursor_text_w < state->diff) { @@ -794,6 +789,7 @@ bool ui_push_textbox(textbox_state *state, char *placeholder) state->diff = (cursor_text_w) - (TEXTBOX_WIDTH - 10); } } +#endif // make sure offset is recalculated when text changes or a portion of text is changed so the textbox doesnt end up half empty #if 1 @@ -839,24 +835,25 @@ bool ui_push_textbox(textbox_state *state, char *placeholder) } +#if 1 if (is_selecting) { // move text offset x when selecting so we can select more text than available on screen. - if (global_ui_context.mouse->x < x + 10) + if (global_ui_context.mouse->x < x + 20) { s32 text_w = calculate_text_width(global_ui_context.font_small, state->buffer); - if (text_w > TEXTBOX_WIDTH-10) + if (text_w > TEXTBOX_WIDTH-20) { state->diff -= TEXTBOX_SCROLL_X_SPEED; if (state->diff < 0) state->diff = 0; } } - if (global_ui_context.mouse->x > x + TEXTBOX_WIDTH - 10) + if (global_ui_context.mouse->x > x + TEXTBOX_WIDTH - 25) { s32 text_w = calculate_text_width(global_ui_context.font_small, state->buffer); - s32 diff = text_w - TEXTBOX_WIDTH + 10; + s32 diff = text_w - TEXTBOX_WIDTH + 25; - if (text_w > TEXTBOX_WIDTH-10) + if (text_w > TEXTBOX_WIDTH-25) { state->diff += TEXTBOX_SCROLL_X_SPEED; if (state->diff > diff) @@ -865,6 +862,7 @@ bool ui_push_textbox(textbox_state *state, char *placeholder) } /////////////////////////////////////////////////////////// } +#endif // change selection area based on cursor position. // if double clicked to select the entire textbox we should only @@ -894,44 +892,6 @@ bool ui_push_textbox(textbox_state *state, char *placeholder) state->double_clicked_to_select = false; } } - - // render cursor - if (state->state) - { - last_cursor_pos = global_ui_context.keyboard->cursor; - - s32 cursor_y = y + 4; - s32 cursor_h = TEXTBOX_HEIGHT - 8; - s32 cursor_w = 2; - - if (cursor_tick % 40 < 20 && !global_ui_context.keyboard->has_selection) - render_rectangle(cursor_x, cursor_y, cursor_w, cursor_h, global_ui_context.style.textbox_foreground); - } - - - // render selection area - if (global_ui_context.keyboard->has_selection && state->state) - { - char tmp_buffer[MAX_INPUT_LENGTH]; - utf8_str_copy_upto(state->buffer, - global_ui_context.keyboard->selection_begin_offset, - tmp_buffer); - - s32 selection_start_x = calculate_text_width(global_ui_context.font_small, - tmp_buffer); - - utf8_str_copy_upto( - utf8_str_upto( - state->buffer, - global_ui_context.keyboard->selection_begin_offset), - global_ui_context.keyboard->selection_length, - tmp_buffer); - - s32 selection_width = calculate_text_width(global_ui_context.font_small, - tmp_buffer); - - render_rectangle(text_x - state->diff + selection_start_x, y+4, selection_width, TEXTBOX_HEIGHT-8, global_ui_context.style.textbox_active_border); - } #endif if (!has_text) @@ -941,8 +901,19 @@ bool ui_push_textbox(textbox_state *state, char *placeholder) } else { - render_text(global_ui_context.font_small, text_x - state->diff, text_y, - state->buffer, global_ui_context.style.foreground); + s32 www; + last_cursor_pos = global_ui_context.keyboard->cursor; + + if (global_ui_context.keyboard->has_selection && state->state && global_ui_context.keyboard->selection_length) + render_text_with_selection(global_ui_context.font_small, text_x - state->diff, text_y, + state->buffer, global_ui_context.style.foreground, global_ui_context.keyboard->selection_begin_offset, + global_ui_context.keyboard->selection_length); + else if (state->state) + render_text_with_cursor(global_ui_context.font_small, text_x - state->diff, text_y, + state->buffer, global_ui_context.style.foreground, global_ui_context.keyboard->cursor); + else + render_text(global_ui_context.font_small, text_x - state->diff, text_y, + state->buffer, global_ui_context.style.foreground); } ui_pop_scissor(); |
