Finally fixed the oldest bug in this library
For now month I failed to find out why text calculation was bugged for zahnrads own vertex buffer font. I finally found the problem and fixed it.
This commit is contained in:
parent
0970db1088
commit
9757f59c66
|
@ -25,7 +25,6 @@ If you have an idea for new features just [open an issue](https://github.com/vur
|
|||
## Bugs
|
||||
* Seperator widget is currently bugged and does not work as intended
|
||||
* Text handling is still a little bit janky and probably needs to be further tested and polished
|
||||
* Text pixel width is bugged at the moment if you edit text with enabled font baking and vertex buffer API.
|
||||
* `zr_edit_buffer` with multiline flag is bugged for '\n', need to differentiate between visible and non-visible characters
|
||||
* `zr_layout_space_xxx` with `ZR_DYNAMIC` currently does not work
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ render backends it only focuses on the actual UI.
|
|||
- Immediate mode graphical user interface toolkit
|
||||
- Written in C89 (ANSI C)
|
||||
- Small codebase (~9kLOC)
|
||||
- Focus on portability, efficiency, simplicity and minimal internal state
|
||||
- Focus on portability, efficiency and simplicity
|
||||
- No dependencies (not even the standard library)
|
||||
- No global or hidden state
|
||||
- Configurable style and colors
|
||||
|
|
|
@ -288,9 +288,15 @@ input_key(struct zr_context *ctx, ALLEGRO_EVENT *evt, int down)
|
|||
zr_input_key(ctx, ZR_KEY_DEL, down);
|
||||
else if (sym == ALLEGRO_KEY_ENTER)
|
||||
zr_input_key(ctx, ZR_KEY_ENTER, down);
|
||||
else if (sym == ALLEGRO_KEY_TAB)
|
||||
else if (sym == ALLEGRO_KEY_TAB) {
|
||||
zr_input_key(ctx, ZR_KEY_TAB, down);
|
||||
else if (sym == ALLEGRO_KEY_BACKSPACE)
|
||||
if (!down) {
|
||||
zr_input_unicode(ctx, ' ');
|
||||
zr_input_unicode(ctx, ' ');
|
||||
zr_input_unicode(ctx, ' ');
|
||||
zr_input_unicode(ctx, ' ');
|
||||
}
|
||||
} else if (sym == ALLEGRO_KEY_BACKSPACE)
|
||||
zr_input_key(ctx, ZR_KEY_BACKSPACE, down);
|
||||
else if (sym == ALLEGRO_KEY_LEFT)
|
||||
zr_input_key(ctx, ZR_KEY_LEFT, down);
|
||||
|
|
|
@ -120,9 +120,15 @@ input_key(struct zr_context *ctx, ALLEGRO_EVENT *evt, int down)
|
|||
zr_input_key(ctx, ZR_KEY_DEL, down);
|
||||
else if (sym == ALLEGRO_KEY_ENTER)
|
||||
zr_input_key(ctx, ZR_KEY_ENTER, down);
|
||||
else if (sym == ALLEGRO_KEY_TAB)
|
||||
else if (sym == ALLEGRO_KEY_TAB) {
|
||||
zr_input_key(ctx, ZR_KEY_TAB, down);
|
||||
else if (sym == ALLEGRO_KEY_BACKSPACE)
|
||||
if (!down) {
|
||||
zr_input_unicode(ctx, ' ');
|
||||
zr_input_unicode(ctx, ' ');
|
||||
zr_input_unicode(ctx, ' ');
|
||||
zr_input_unicode(ctx, ' ');
|
||||
}
|
||||
} else if (sym == ALLEGRO_KEY_BACKSPACE)
|
||||
zr_input_key(ctx, ZR_KEY_BACKSPACE, down);
|
||||
else if (sym == ALLEGRO_KEY_LEFT)
|
||||
zr_input_key(ctx, ZR_KEY_LEFT, down);
|
||||
|
|
|
@ -384,12 +384,19 @@ input_key(GLFWwindow *window, int key, int scancode, int action, int mods)
|
|||
UNUSED(scancode);
|
||||
if (key == GLFW_KEY_RIGHT_SHIFT || key == GLFW_KEY_LEFT_SHIFT)
|
||||
zr_input_key(&gui.ctx, ZR_KEY_SHIFT, down);
|
||||
else if (key == GLFW_KEY_DELETE)
|
||||
else if (key == GLFW_KEY_TAB) {
|
||||
zr_input_key(&gui.ctx, ZR_KEY_TAB, down);
|
||||
/* because: reasons */
|
||||
if (!down) {
|
||||
zr_input_unicode(&gui.ctx, ' ');
|
||||
zr_input_unicode(&gui.ctx, ' ');
|
||||
zr_input_unicode(&gui.ctx, ' ');
|
||||
zr_input_unicode(&gui.ctx, ' ');
|
||||
}
|
||||
} else if (key == GLFW_KEY_DELETE)
|
||||
zr_input_key(&gui.ctx, ZR_KEY_DEL, down);
|
||||
else if (key == GLFW_KEY_ENTER)
|
||||
zr_input_key(&gui.ctx, ZR_KEY_ENTER, down);
|
||||
else if (key == GLFW_KEY_TAB)
|
||||
zr_input_key(&gui.ctx, ZR_KEY_TAB, down);
|
||||
else if (key == GLFW_KEY_BACKSPACE)
|
||||
zr_input_key(&gui.ctx, ZR_KEY_BACKSPACE, down);
|
||||
else if (key == GLFW_KEY_LEFT)
|
||||
|
|
|
@ -549,9 +549,15 @@ input_key(struct XWindow *xw, struct zr_context *ctx, XEvent *evt, int down)
|
|||
zr_input_key(ctx, ZR_KEY_DEL, down);
|
||||
else if (*code == XK_Return)
|
||||
zr_input_key(ctx, ZR_KEY_ENTER, down);
|
||||
else if (*code == XK_Tab)
|
||||
else if (*code == XK_Tab) {
|
||||
zr_input_key(ctx, ZR_KEY_TAB, down);
|
||||
else if (*code == XK_space && !down)
|
||||
if (!down) {
|
||||
zr_input_unicode(ctx, ' ');
|
||||
zr_input_unicode(ctx, ' ');
|
||||
zr_input_unicode(ctx, ' ');
|
||||
zr_input_unicode(ctx, ' ');
|
||||
}
|
||||
} else if (*code == XK_space && !down)
|
||||
zr_input_char(ctx, ' ');
|
||||
else if (*code == XK_Left)
|
||||
zr_input_key(ctx, ZR_KEY_LEFT, down);
|
||||
|
|
|
@ -173,9 +173,15 @@ input_key(struct zr_context *ctx, SDL_Event *evt, int down)
|
|||
zr_input_key(ctx, ZR_KEY_DEL, down);
|
||||
else if (sym == SDLK_RETURN)
|
||||
zr_input_key(ctx, ZR_KEY_ENTER, down);
|
||||
else if (sym == SDLK_TAB)
|
||||
else if (sym == SDLK_TAB) {
|
||||
zr_input_key(ctx, ZR_KEY_TAB, down);
|
||||
else if (sym == SDLK_BACKSPACE)
|
||||
if (!down) {
|
||||
zr_input_unicode(ctx, ' ');
|
||||
zr_input_unicode(ctx, ' ');
|
||||
zr_input_unicode(ctx, ' ');
|
||||
zr_input_unicode(ctx, ' ');
|
||||
}
|
||||
} else if (sym == SDLK_BACKSPACE)
|
||||
zr_input_key(ctx, ZR_KEY_BACKSPACE, down);
|
||||
else if (sym == SDLK_LEFT)
|
||||
zr_input_key(ctx, ZR_KEY_LEFT, down);
|
||||
|
|
|
@ -373,9 +373,15 @@ input_key(struct zr_context *ctx, SDL_Event *evt, int down)
|
|||
zr_input_key(ctx, ZR_KEY_DEL, down);
|
||||
else if (sym == SDLK_RETURN)
|
||||
zr_input_key(ctx, ZR_KEY_ENTER, down);
|
||||
else if (sym == SDLK_TAB)
|
||||
else if (sym == SDLK_TAB) {
|
||||
zr_input_key(ctx, ZR_KEY_TAB, down);
|
||||
else if (sym == SDLK_BACKSPACE)
|
||||
if (!down) {
|
||||
zr_input_unicode(ctx, ' ');
|
||||
zr_input_unicode(ctx, ' ');
|
||||
zr_input_unicode(ctx, ' ');
|
||||
zr_input_unicode(ctx, ' ');
|
||||
}
|
||||
} else if (sym == SDLK_BACKSPACE)
|
||||
zr_input_key(ctx, ZR_KEY_BACKSPACE, down);
|
||||
else if (sym == SDLK_LEFT)
|
||||
zr_input_key(ctx, ZR_KEY_LEFT, down);
|
||||
|
|
|
@ -361,9 +361,15 @@ input_key(struct XWindow *xw, struct zr_context *ctx, XEvent *evt, int down)
|
|||
zr_input_key(ctx, ZR_KEY_DEL, down);
|
||||
else if (*code == XK_Return)
|
||||
zr_input_key(ctx, ZR_KEY_ENTER, down);
|
||||
else if (*code == XK_Tab)
|
||||
else if (*code == XK_Tab) {
|
||||
zr_input_key(ctx, ZR_KEY_TAB, down);
|
||||
else if (*code == XK_space && !down)
|
||||
if (!down) {
|
||||
zr_input_unicode(ctx, ' ');
|
||||
zr_input_unicode(ctx, ' ');
|
||||
zr_input_unicode(ctx, ' ');
|
||||
zr_input_unicode(ctx, ' ');
|
||||
}
|
||||
} else if (*code == XK_space && !down)
|
||||
zr_input_char(ctx, ' ');
|
||||
else if (*code == XK_Left)
|
||||
zr_input_key(ctx, ZR_KEY_LEFT, down);
|
||||
|
|
96
zahnrad.c
96
zahnrad.c
|
@ -1335,24 +1335,53 @@ zr_use_font_glyph_clamp(const struct zr_user_font *font, const char *text,
|
|||
|
||||
static zr_size
|
||||
zr_user_font_glyphs_fitting_in_space(const struct zr_user_font *font,
|
||||
const char *text, zr_size text_len, float space, zr_size *row_len,
|
||||
const char *text, zr_size len, float space, zr_size *row_len,
|
||||
zr_size *glyphs, float *text_width, int has_newline)
|
||||
{
|
||||
zr_size glyph_len;
|
||||
float width = 0;
|
||||
float last_width = 0;
|
||||
|
||||
zr_size width = 0;
|
||||
zr_rune unicode = 0;
|
||||
zr_size offset = 0;
|
||||
zr_size g = 0;
|
||||
zr_size l = 0;
|
||||
zr_size s;
|
||||
zr_size text_len = 0;
|
||||
zr_size row_advance = 0;
|
||||
|
||||
glyph_len = zr_utf_decode(text, &unicode, text_len);
|
||||
s = font->width(font->userdata, font->height, text, glyph_len);
|
||||
width = last_width = (float)s;
|
||||
ZR_ASSERT(glyphs);
|
||||
ZR_ASSERT(text_width);
|
||||
ZR_ASSERT(row_len);
|
||||
|
||||
while ((width <= space) && text_len && glyph_len) {
|
||||
*glyphs = 0;
|
||||
*row_len = 0;
|
||||
*text_width = 0;
|
||||
|
||||
glyph_len = text_len = zr_utf_decode(text, &unicode, len);
|
||||
if (!glyph_len) return 0;
|
||||
width = font->width(font->userdata, font->height, text, text_len);
|
||||
while ((width <= space) && (text_len <= len) && glyph_len) {
|
||||
*text_width = width;
|
||||
*glyphs+=1;
|
||||
*row_len = text_len;
|
||||
row_advance += glyph_len;
|
||||
|
||||
if (has_newline && (unicode == '\n' || unicode == '\r')) {
|
||||
zr_rune next = 0;
|
||||
zr_utf_decode(text+text_len, &next, len - text_len);
|
||||
if (unicode == '\r') {
|
||||
*row_len-=1; *glyphs-=1;
|
||||
} else if ((unicode == '\n') && (next == '\r')) {
|
||||
*row_len-= 2; *glyphs-=2;
|
||||
} else {
|
||||
*row_len-=1; *glyphs-=1;
|
||||
}
|
||||
*text_width = font->width(font->userdata, font->height, text, *row_len);
|
||||
break;
|
||||
}
|
||||
glyph_len = zr_utf_decode(text + text_len, &unicode, len - text_len);
|
||||
text_len += glyph_len;
|
||||
width = font->width(font->userdata, font->height, text, text_len);
|
||||
}
|
||||
return row_advance;
|
||||
|
||||
#if 0
|
||||
while ((width <= space) && (text_len <= len) && glyph_len) {
|
||||
text_len -= glyph_len;
|
||||
offset += glyph_len;
|
||||
g++; l += glyph_len;
|
||||
|
@ -1380,7 +1409,9 @@ zr_user_font_glyphs_fitting_in_space(const struct zr_user_font *font,
|
|||
*text_width = last_width;
|
||||
*row_len = l;
|
||||
return offset;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* ==============================================================
|
||||
*
|
||||
* BUFFER
|
||||
|
@ -2694,12 +2725,11 @@ zr_canvas_add_text(struct zr_canvas *list, const struct zr_user_font *font,
|
|||
struct zr_rect rect, const char *text, zr_size len, float font_height,
|
||||
struct zr_color bg, struct zr_color fg)
|
||||
{
|
||||
float x, scale;
|
||||
float x;
|
||||
zr_size text_len;
|
||||
zr_rune unicode, next;
|
||||
zr_size glyph_len, next_glyph_len;
|
||||
struct zr_user_font_glyph g;
|
||||
scale = font_height / font->height;
|
||||
|
||||
ZR_ASSERT(list);
|
||||
if (!list || !len || !text) return;
|
||||
|
@ -2723,14 +2753,14 @@ zr_canvas_add_text(struct zr_canvas *list, const struct zr_user_font *font,
|
|||
|
||||
/* query currently drawn glyph information */
|
||||
next_glyph_len = zr_utf_decode(text + text_len, &next, len - text_len);
|
||||
font->query(font->userdata, font->height, &g, unicode,
|
||||
font->query(font->userdata, font_height, &g, unicode,
|
||||
(next == ZR_UTF_INVALID) ? '\0' : next);
|
||||
|
||||
/* calculate and draw glyph drawing rectangle and image */
|
||||
gx = x + g.offset.x * scale;
|
||||
gy = rect.y + (rect.h/2) - (font->height/2) + g.offset.y * scale;
|
||||
gw = g.width * scale; gh = g.height * scale;
|
||||
char_width = g.xadvance * scale;
|
||||
gx = x + g.offset.x;
|
||||
gy = rect.y + (rect.h/2) - (font->height/2) + g.offset.y;
|
||||
gw = g.width; gh = g.height;
|
||||
char_width = g.xadvance;
|
||||
zr_canvas_push_rect_uv(list, zr_vec2(gx,gy), zr_vec2(gx + gw, gy+ gh),
|
||||
g.uv[0], g.uv[1], fg);
|
||||
|
||||
|
@ -3008,7 +3038,8 @@ zr_font_korean_glyph_ranges(void)
|
|||
return ranges;
|
||||
}
|
||||
|
||||
void zr_font_bake_memory(zr_size *temp, int *glyph_count,
|
||||
void
|
||||
zr_font_bake_memory(zr_size *temp, int *glyph_count,
|
||||
struct zr_font_config *config, int count)
|
||||
{
|
||||
int i, range_count = 0;
|
||||
|
@ -3242,6 +3273,8 @@ zr_font_bake(void *image_memory, int width, int height,
|
|||
glyph->x1 = q.x1; glyph->y1 = q.y1;
|
||||
glyph->y0 += (dst_font->ascent + 0.5f);
|
||||
glyph->y1 += (dst_font->ascent + 0.5f);
|
||||
glyph->w = glyph->x1 - glyph->x0 + 0.5f;
|
||||
glyph->h = glyph->y1 - glyph->y0;
|
||||
|
||||
if (cfg->coord_type == ZR_COORD_PIXEL) {
|
||||
glyph->u0 = q.s0 * (float)width;
|
||||
|
@ -3365,7 +3398,7 @@ zr_font_text_width(zr_handle handle, float height, const char *text, zr_size len
|
|||
{
|
||||
zr_rune unicode;
|
||||
zr_size text_len = 0;
|
||||
zr_size text_width = 0;
|
||||
float text_width = 0;
|
||||
zr_size glyph_len = 0;
|
||||
float scale = 0;
|
||||
|
||||
|
@ -3375,6 +3408,22 @@ zr_font_text_width(zr_handle handle, float height, const char *text, zr_size len
|
|||
return 0;
|
||||
|
||||
scale = height/font->size;
|
||||
glyph_len = text_len = zr_utf_decode(text, &unicode, len);
|
||||
if (!glyph_len) return 0;
|
||||
while (text_len <= len && glyph_len) {
|
||||
const struct zr_font_glyph *g;
|
||||
if (unicode == ZR_UTF_INVALID) break;
|
||||
|
||||
/* query currently drawn glyph information */
|
||||
g = zr_font_find_glyph(font, unicode);
|
||||
text_width += g->xadvance * scale;
|
||||
|
||||
/* offset next glyph */
|
||||
glyph_len = zr_utf_decode(text + text_len, &unicode, len - text_len);
|
||||
text_len += glyph_len;
|
||||
}
|
||||
|
||||
#if 0
|
||||
glyph_len = zr_utf_decode(text, &unicode, len);
|
||||
while (text_len < len && glyph_len) {
|
||||
const struct zr_font_glyph *glyph;
|
||||
|
@ -3384,7 +3433,8 @@ zr_font_text_width(zr_handle handle, float height, const char *text, zr_size len
|
|||
text_width += (zr_size)((glyph->xadvance * scale));
|
||||
glyph_len = zr_utf_decode(text + text_len, &unicode, len - text_len);
|
||||
}
|
||||
return text_width;
|
||||
#endif
|
||||
return (zr_size)text_width;
|
||||
}
|
||||
|
||||
#if ZR_COMPILE_WITH_VERTEX_BUFFER
|
||||
|
@ -4926,6 +4976,8 @@ zr_widget_edit_field(struct zr_command_buffer *out, struct zr_rect r,
|
|||
if (box->active && field->show_cursor) {
|
||||
if (box->cursor == box->glyphs) {
|
||||
/* draw the cursor at the end of the string */
|
||||
text_width = font->width(font->userdata, font->height,
|
||||
buffer + offset, text_len);
|
||||
zr_draw_rect(out, zr_rect(label.x+(float)text_width,
|
||||
label.y, (float)cursor_w, label.h), 0, field->cursor);
|
||||
} else {
|
||||
|
|
|
@ -402,7 +402,7 @@ struct zr_font_glyph {
|
|||
/* unicode codepoint */
|
||||
float xadvance;
|
||||
/* xoffset to the next character */
|
||||
float x0, y0, x1, y1;
|
||||
float x0, y0, x1, y1, w, h;
|
||||
/* glyph bounding points in pixel inside the glyph image with top
|
||||
* left and bottom right */
|
||||
float u0, v0, u1, v1;
|
||||
|
|
Loading…
Reference in New Issue