fixed text overdraw
This commit is contained in:
parent
4e97a489b2
commit
f88e92dd43
@ -550,7 +550,6 @@ struct demo_gui {
|
||||
zr_size w, h;
|
||||
};
|
||||
|
||||
|
||||
/* -----------------------------------------------------------------
|
||||
* WIDGETS
|
||||
* ----------------------------------------------------------------- */
|
||||
|
@ -250,6 +250,7 @@ font_bake_and_upload(struct device *dev, struct zr_font *font,
|
||||
dev->null.texture.id = (zr_int)dev->font_tex;
|
||||
dev->null.uv = zr_vec2((custom.x + 0.5f)/(zr_float)img_width,
|
||||
(custom.y + 0.5f)/(zr_float)img_height);
|
||||
|
||||
/* setup font with glyphes. IMPORTANT: the font only references the glyphes
|
||||
this was done to have the possibility to have multible fonts with one
|
||||
total glyph array. Not quite sure if it is a good thing since the
|
||||
|
@ -555,7 +555,7 @@ file_browser_run(struct file_browser *browser, int width, int height)
|
||||
{
|
||||
/* draw one row of icons */
|
||||
size_t n = j + cols;
|
||||
zr_layout_row_dynamic(&sub, 120, cols);
|
||||
zr_layout_row_dynamic(&sub, 130, cols);
|
||||
zr_style_push_color(&browser->config, ZR_COLOR_BUTTON, zr_rgb(45, 45, 45));
|
||||
zr_style_push_color(&browser->config, ZR_COLOR_BORDER, zr_rgb(45, 45, 45));
|
||||
for (; j < count && j < n; ++j) {
|
||||
@ -581,6 +581,7 @@ file_browser_run(struct file_browser *browser, int width, int height)
|
||||
}
|
||||
{
|
||||
/* draw one row of labels */
|
||||
zr_style_push_property(&browser->config, ZR_PROPERTY_ITEM_SPACING, zr_vec2(4, 4));
|
||||
size_t n = k + cols;
|
||||
zr_layout_row_dynamic(&sub, 20, cols);
|
||||
for (; k < count && k < n; k++) {
|
||||
@ -591,6 +592,7 @@ file_browser_run(struct file_browser *browser, int width, int height)
|
||||
zr_label(&sub,browser->files[t],ZR_TEXT_CENTERED);
|
||||
}
|
||||
}
|
||||
zr_style_pop_property(&browser->config);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -222,9 +222,11 @@ node_editor_draw(struct zr_context *layout, struct node_editor *nodedit,
|
||||
/* execute each node as a moveable group */
|
||||
zr_style_push_color(config, ZR_COLOR_WINDOW, zr_rgb(48, 48, 48));
|
||||
while (it) {
|
||||
/* draw node */
|
||||
/* calculate node group space */
|
||||
zr_layout_row_space_push(layout, zr_rect(it->bounds.x - nodedit->scrolling.x,
|
||||
it->bounds.y - nodedit->scrolling.y, it->bounds.w, it->bounds.h));
|
||||
|
||||
/* execute node window */
|
||||
zr_group_begin(layout, &node, it->name,
|
||||
ZR_WINDOW_MOVEABLE|ZR_WINDOW_NO_SCROLLBAR, zr_vec2(0,0));
|
||||
{
|
||||
@ -394,6 +396,8 @@ node_editor_draw(struct zr_context *layout, struct node_editor *nodedit,
|
||||
}
|
||||
}
|
||||
zr_layout_row_space_end(layout);
|
||||
|
||||
/* window content scrolling */
|
||||
if (zr_input_is_mouse_hovering_rect(in, layout->bounds) &&
|
||||
zr_input_is_mouse_down(in, ZR_BUTTON_MIDDLE)) {
|
||||
nodedit->scrolling.x += in->mouse.delta.x;
|
||||
|
154
zahnrad.c
154
zahnrad.c
@ -659,6 +659,85 @@ zr_utf_len(const zr_char *str, zr_size len)
|
||||
}
|
||||
return src_len;
|
||||
}
|
||||
|
||||
static zr_size
|
||||
zr_user_font_glyph_index_at_pos(const struct zr_user_font *font, const char *text,
|
||||
zr_size text_len, zr_float xoff)
|
||||
{
|
||||
zr_long unicode;
|
||||
zr_size glyph_offset = 0;
|
||||
zr_size glyph_len = zr_utf_decode(text, &unicode, text_len);
|
||||
zr_size text_width = font->width(font->userdata, text, glyph_len);
|
||||
zr_size src_len = glyph_len;
|
||||
|
||||
while (text_len && glyph_len) {
|
||||
if (text_width >= xoff)
|
||||
return glyph_offset;
|
||||
glyph_offset++;
|
||||
text_len -= glyph_len;
|
||||
glyph_len = zr_utf_decode(text + src_len, &unicode, text_len);
|
||||
src_len += glyph_len;
|
||||
text_width = font->width(font->userdata, text, src_len);
|
||||
}
|
||||
return glyph_offset;
|
||||
}
|
||||
|
||||
static zr_size
|
||||
zr_use_font_glyph_clamp(const struct zr_user_font *font, const char *text,
|
||||
zr_size text_len, zr_float space, zr_size *glyphes, zr_float *text_width)
|
||||
{
|
||||
zr_size len = 0;
|
||||
zr_size glyph_len;
|
||||
zr_float width = 0;
|
||||
zr_float last_width = 0;
|
||||
zr_long unicode;
|
||||
zr_size g = 0;
|
||||
|
||||
glyph_len = zr_utf_decode(text, &unicode, text_len);
|
||||
while (glyph_len && (width < space) && (len < text_len)) {
|
||||
zr_size s;
|
||||
len += glyph_len;
|
||||
s = font->width(font->userdata, text, len);
|
||||
last_width = width;
|
||||
width = (zr_float)s;
|
||||
glyph_len = zr_utf_decode(&text[len], &unicode, text_len - len);
|
||||
g++;
|
||||
}
|
||||
|
||||
*glyphes = g;
|
||||
*text_width = last_width;
|
||||
return len;
|
||||
}
|
||||
|
||||
static zr_size
|
||||
zr_user_font_glyphes_fitting_in_space(const struct zr_user_font *font, const char *text,
|
||||
zr_size text_len, zr_float space, zr_size *glyphes, zr_float *text_width)
|
||||
{
|
||||
zr_size glyph_len;
|
||||
zr_float width = 0;
|
||||
zr_float last_width = 0;
|
||||
zr_long unicode;
|
||||
zr_size offset = 0;
|
||||
zr_size g = 0;
|
||||
zr_size s;
|
||||
|
||||
glyph_len = zr_utf_decode(text, &unicode, text_len);
|
||||
s = font->width(font->userdata, text, glyph_len);
|
||||
width = last_width = (zr_float)s;
|
||||
while ((width < space) && text_len) {
|
||||
g++;
|
||||
offset += glyph_len;
|
||||
text_len -= glyph_len;
|
||||
last_width = width;
|
||||
glyph_len = zr_utf_decode(&text[offset], &unicode, text_len);
|
||||
s = font->width(font->userdata, &text[offset], glyph_len);
|
||||
width += (zr_float)s;
|
||||
}
|
||||
|
||||
*glyphes = g;
|
||||
*text_width = last_width;
|
||||
return offset;
|
||||
}
|
||||
/*
|
||||
* ==============================================================
|
||||
*
|
||||
@ -1387,6 +1466,7 @@ zr_command_buffer_push_text(struct zr_command_buffer *b, struct zr_rect r,
|
||||
const zr_char *string, zr_size length, const struct zr_user_font *font,
|
||||
struct zr_color bg, struct zr_color fg)
|
||||
{
|
||||
zr_size text_width = 0;
|
||||
struct zr_command_text *cmd;
|
||||
ZR_ASSERT(b);
|
||||
ZR_ASSERT(font);
|
||||
@ -1397,6 +1477,15 @@ zr_command_buffer_push_text(struct zr_command_buffer *b, struct zr_rect r,
|
||||
return;
|
||||
}
|
||||
|
||||
/* make sure text fits inside bounds */
|
||||
text_width = font->width(font->userdata, string, length);
|
||||
if (text_width > r.w){
|
||||
zr_float txt_width = (zr_float)text_width;
|
||||
zr_size glyphes = 0;
|
||||
length = zr_use_font_glyph_clamp(font, string, length, r.w, &glyphes, &txt_width);
|
||||
}
|
||||
|
||||
if (!length) return;
|
||||
cmd = (struct zr_command_text*)
|
||||
zr_command_buffer_push(b, ZR_COMMAND_TEXT, sizeof(*cmd) + length + 1);
|
||||
if (!cmd) return;
|
||||
@ -2542,6 +2631,7 @@ zr_draw_list_add_text(struct zr_draw_list *list, const struct zr_user_font *font
|
||||
zr_long unicode, next;
|
||||
zr_size glyph_len, next_glyph_len;
|
||||
struct zr_user_font_glyph g;
|
||||
|
||||
ZR_ASSERT(list);
|
||||
if (!list || !len || !text) return;
|
||||
if (rect.x > (list->clip_rect.x + list->clip_rect.w) ||
|
||||
@ -2568,7 +2658,6 @@ zr_draw_list_add_text(struct zr_draw_list *list, const struct zr_user_font *font
|
||||
|
||||
/* calculate and draw glyph drawing rectangle and image */
|
||||
gx = x + g.offset.x;
|
||||
/*gy = rect.y + (font->height/2) + (rect.h/2) - g.offset.y;*/
|
||||
gy = rect.y + (rect.h/2) - (font->height/2) + g.offset.y;
|
||||
gw = g.width; gh = g.height;
|
||||
char_width = g.xadvance;
|
||||
@ -2602,6 +2691,7 @@ zr_draw_list_path_line_to(struct zr_draw_list *list, struct zr_vec2 pos)
|
||||
if (!list) return;
|
||||
if (!list->cmd_count)
|
||||
zr_draw_list_add_clip(list, zr_null_rect);
|
||||
|
||||
cmd = zr_draw_list_command_last(list);
|
||||
if (cmd->texture.ptr != list->null.texture.ptr)
|
||||
zr_draw_list_push_image(list, list->null.texture);
|
||||
@ -2668,6 +2758,7 @@ zr_draw_list_path_rect_to(struct zr_draw_list *list, struct zr_vec2 a,
|
||||
r = rounding;
|
||||
r = MIN(r, ((b.x-a.x) < 0) ? -(b.x-a.x): (b.x-a.x));
|
||||
r = MIN(r, ((b.y-a.y) < 0) ? -(b.y-a.y): (b.y-a.y));
|
||||
|
||||
if (r == 0.0f) {
|
||||
zr_draw_list_path_line_to(list, a);
|
||||
zr_draw_list_path_line_to(list, zr_vec2(b.x,a.y));
|
||||
@ -3700,8 +3791,9 @@ zr_widget_text(struct zr_command_buffer *o, struct zr_rect b,
|
||||
label.x = 0; label.w = 0;
|
||||
label.y = b.y + t->padding.y;
|
||||
label.h = MAX(0, b.h - 2 * t->padding.y);
|
||||
|
||||
text_width = f->width(f->userdata, (const zr_char*)string, len);
|
||||
b.w = MAX(b.w, (2 * t->padding.x + (zr_float)text_width));
|
||||
text_width += (zr_size)(2 * t->padding.x);
|
||||
|
||||
if (a == ZR_TEXT_LEFT) {
|
||||
label.x = b.x + t->padding.x;
|
||||
@ -3709,12 +3801,12 @@ zr_widget_text(struct zr_command_buffer *o, struct zr_rect b,
|
||||
} else if (a == ZR_TEXT_CENTERED) {
|
||||
label.w = MAX(1, 2 * t->padding.x + (zr_float)text_width);
|
||||
label.x = (b.x + t->padding.x + ((b.w - 2 * t->padding.x)/2));
|
||||
if (label.x > label.w/2) label.x -= (label.w/2);
|
||||
if (label.x >= label.w/2) label.x -= (label.w/2);
|
||||
label.x = MAX(b.x + t->padding.x, label.x);
|
||||
label.w = MIN(b.x + b.w, label.x + label.w);
|
||||
if (label.w > label.x) label.w -= label.x;
|
||||
if (label.w >= label.x) label.w -= label.x;
|
||||
} else if (a == ZR_TEXT_RIGHT) {
|
||||
label.x = (b.x + b.w) - (2 * t->padding.x + (zr_float)text_width);
|
||||
label.x = MAX(b.x + t->padding.x, (b.x + b.w) - (2 * t->padding.x + (zr_float)text_width));
|
||||
label.w = (zr_float)text_width + 2 * t->padding.x;
|
||||
} else return;
|
||||
zr_command_buffer_push_text(o, label, (const zr_char*)string,
|
||||
@ -4152,58 +4244,6 @@ zr_widget_progress(struct zr_command_buffer *out, struct zr_rect r,
|
||||
return prog_value;
|
||||
}
|
||||
|
||||
static zr_size
|
||||
zr_user_font_glyph_index_at_pos(const struct zr_user_font *font, const char *text,
|
||||
zr_size text_len, zr_float xoff)
|
||||
{
|
||||
zr_long unicode;
|
||||
zr_size glyph_offset = 0;
|
||||
zr_size glyph_len = zr_utf_decode(text, &unicode, text_len);
|
||||
zr_size text_width = font->width(font->userdata, text, glyph_len);
|
||||
zr_size src_len = glyph_len;
|
||||
|
||||
while (text_len && glyph_len) {
|
||||
if (text_width >= xoff)
|
||||
return glyph_offset;
|
||||
glyph_offset++;
|
||||
text_len -= glyph_len;
|
||||
glyph_len = zr_utf_decode(text + src_len, &unicode, text_len);
|
||||
src_len += glyph_len;
|
||||
text_width = font->width(font->userdata, text, src_len);
|
||||
}
|
||||
return glyph_offset;
|
||||
}
|
||||
|
||||
static zr_size
|
||||
zr_user_font_glyphes_fitting_in_space(const struct zr_user_font *font, const char *text,
|
||||
zr_size text_len, zr_float space, zr_size *glyphes, zr_float *text_width)
|
||||
{
|
||||
zr_size glyph_len;
|
||||
zr_float width = 0;
|
||||
zr_float last_width = 0;
|
||||
zr_long unicode;
|
||||
zr_size offset = 0;
|
||||
zr_size g = 0;
|
||||
zr_size s;
|
||||
|
||||
glyph_len = zr_utf_decode(text, &unicode, text_len);
|
||||
s = font->width(font->userdata, text, glyph_len);
|
||||
width = last_width = (zr_float)s;
|
||||
while ((width < space) && text_len) {
|
||||
g++;
|
||||
offset += glyph_len;
|
||||
text_len -= glyph_len;
|
||||
last_width = width;
|
||||
glyph_len = zr_utf_decode(&text[offset], &unicode, text_len);
|
||||
s = font->width(font->userdata, &text[offset], glyph_len);
|
||||
width += (zr_float)s;
|
||||
}
|
||||
|
||||
*glyphes = g;
|
||||
*text_width = last_width;
|
||||
return offset;
|
||||
}
|
||||
|
||||
void
|
||||
zr_widget_editbox(struct zr_command_buffer *out, struct zr_rect r,
|
||||
struct zr_edit_box *box, const struct zr_edit *field,
|
||||
|
152
zahnrad.h
152
zahnrad.h
@ -1015,7 +1015,7 @@ const struct zr_command* zr_command_queue_next(struct zr_command_queue*,
|
||||
draw list even with anti-aliasing.
|
||||
|
||||
The draw list consist internaly of three user provided buffers that will be
|
||||
filled with data. The first buffer is the the draw command and temporary
|
||||
filled with data. The first buffer is the draw command and temporary
|
||||
path buffer which permanetly stores all draw batch commands. The vertex and
|
||||
element buffer are the same buffers as their hardware renderer counter-parts,
|
||||
in fact it is even possible to directly map one of these buffers and fill
|
||||
@ -3561,6 +3561,80 @@ enum zr_tree_node_operation zr_tree_leaf_icon(struct zr_tree*,
|
||||
*/
|
||||
void zr_tree_end(struct zr_context*, struct zr_tree*, struct zr_vec2 *scrollbar);
|
||||
/* this function ends a the tree building process */
|
||||
/* --------------------------------------------------------------
|
||||
* Group
|
||||
* --------------------------------------------------------------
|
||||
GROUP
|
||||
A group window represents a window inside a window. The group thereby has a fixed height
|
||||
but just like a normal window has a scrollbar. It main promise is to group together
|
||||
a group of widgets into a small space inside a window and to provide a scrollable
|
||||
space inside a window.
|
||||
|
||||
USAGE
|
||||
To create a group you first have to allocate space in a window. This is done
|
||||
by the group row layout API and works the same as widgets. After that the
|
||||
`zr_group_begin` has to be called with the parent layout to create
|
||||
the group in and a group layout to create a new window inside the window.
|
||||
Just like a window layout structures the group layout only has a lifetime
|
||||
between the `zr_group_begin` and `zr_group_end` and does
|
||||
not have to be persistent.
|
||||
|
||||
group window API
|
||||
zr_group_begin -- adds a scrollable fixed space inside the window
|
||||
zr_group_begin -- ends the scrollable space
|
||||
*/
|
||||
void zr_group_begin(struct zr_context*, struct zr_context *tab,
|
||||
const char *title, zr_flags, struct zr_vec2);
|
||||
/* this function adds a grouped group window into the parent window
|
||||
IMPORTANT: You need to set the height of the group with zr_row_layout
|
||||
Input:
|
||||
- group title to write into the header
|
||||
- group scrollbar offset
|
||||
Output:
|
||||
- group layout to fill with widgets
|
||||
*/
|
||||
void zr_group_end(struct zr_context*, struct zr_context*, struct zr_vec2 *scrollbar);
|
||||
/* this function finishes the previously started group layout
|
||||
Output:
|
||||
- The from user input updated group scrollbar pixel offset
|
||||
*/
|
||||
/* --------------------------------------------------------------
|
||||
* SHELF
|
||||
* --------------------------------------------------------------
|
||||
SHELF
|
||||
A shelf extends the concept of a group as an window inside a window
|
||||
with the possibility to decide which content should be drawn into the group.
|
||||
This is achieved by tabs on the top of the group window with one selected
|
||||
tab. The selected tab thereby defines which content should be drawn inside
|
||||
the group window by an index it returns. So you just have to check the returned
|
||||
index and depending on it draw the wanted content.
|
||||
|
||||
shelf API
|
||||
zr_shelf_begin -- begins a shelf with a number of selectable tabs
|
||||
zr_shelf_end -- ends a previously started shelf build up process
|
||||
|
||||
*/
|
||||
zr_size zr_shelf_begin(struct zr_context*, struct zr_context*,
|
||||
const char *tabs[], zr_size size,
|
||||
zr_size active, struct zr_vec2 offset);
|
||||
/* this function adds a shelf child window into the parent window
|
||||
IMPORTANT: You need to set the height of the shelf with zr_row_layout
|
||||
Input:
|
||||
- all possible selectible tabs of the shelf with names as a string array
|
||||
- number of seletectible tabs
|
||||
- current active tab array index
|
||||
- scrollbar pixel offset for the shelf
|
||||
Output:
|
||||
- group layout to fill with widgets
|
||||
- the from user input updated current shelf tab index
|
||||
*/
|
||||
void zr_shelf_end(struct zr_context *p, struct zr_context *s, struct zr_vec2 *scrollbar);
|
||||
/* this function finishes the previously started shelf layout
|
||||
Input:
|
||||
- previously started group layout
|
||||
Output:
|
||||
- The from user input updated shelf scrollbar pixel offset
|
||||
*/
|
||||
/* --------------------------------------------------------------
|
||||
* POPUP
|
||||
* --------------------------------------------------------------
|
||||
@ -3772,82 +3846,6 @@ void zr_tooltip_begin(struct zr_context *parent, struct zr_context *tip,
|
||||
*/
|
||||
void zr_tooltip_end(struct zr_context *parent, struct zr_context *tip);
|
||||
/* this function ends the tooltip window */
|
||||
/* --------------------------------------------------------------
|
||||
* Group
|
||||
* --------------------------------------------------------------
|
||||
*
|
||||
GROUP
|
||||
A group window represents a window inside a window. The group thereby has a fixed height
|
||||
but just like a normal window has a scrollbar. It main promise is to group together
|
||||
a group of widgets into a small space inside a window and to provide a scrollable
|
||||
space inside a window.
|
||||
|
||||
USAGE
|
||||
To create a group you first have to allocate space in a window. This is done
|
||||
by the group row layout API and works the same as widgets. After that the
|
||||
`zr_group_begin` has to be called with the parent layout to create
|
||||
the group in and a group layout to create a new window inside the window.
|
||||
Just like a window layout structures the group layout only has a lifetime
|
||||
between the `zr_group_begin` and `zr_group_end` and does
|
||||
not have to be persistent.
|
||||
|
||||
group window API
|
||||
zr_group_begin -- adds a scrollable fixed space inside the window
|
||||
zr_group_begin -- ends the scrollable space
|
||||
*/
|
||||
void zr_group_begin(struct zr_context*, struct zr_context *tab,
|
||||
const char *title, zr_flags, struct zr_vec2);
|
||||
/* this function adds a grouped group window into the parent window
|
||||
IMPORTANT: You need to set the height of the group with zr_row_layout
|
||||
Input:
|
||||
- group title to write into the header
|
||||
- group scrollbar offset
|
||||
Output:
|
||||
- group layout to fill with widgets
|
||||
*/
|
||||
void zr_group_end(struct zr_context*, struct zr_context*, struct zr_vec2 *scrollbar);
|
||||
/* this function finishes the previously started group layout
|
||||
Output:
|
||||
- The from user input updated group scrollbar pixel offset
|
||||
*/
|
||||
/* --------------------------------------------------------------
|
||||
* SHELF
|
||||
* --------------------------------------------------------------
|
||||
SHELF
|
||||
A shelf extends the concept of a group as an window inside a window
|
||||
with the possibility to decide which content should be drawn into the group.
|
||||
This is achieved by tabs on the top of the group window with one selected
|
||||
tab. The selected tab thereby defines which content should be drawn inside
|
||||
the group window by an index it returns. So you just have to check the returned
|
||||
index and depending on it draw the wanted content.
|
||||
|
||||
shelf API
|
||||
zr_shelf_begin -- begins a shelf with a number of selectable tabs
|
||||
zr_shelf_end -- ends a previously started shelf build up process
|
||||
|
||||
*/
|
||||
zr_size zr_shelf_begin(struct zr_context*, struct zr_context*,
|
||||
const char *tabs[], zr_size size,
|
||||
zr_size active, struct zr_vec2 offset);
|
||||
/* this function adds a shelf child window into the parent window
|
||||
IMPORTANT: You need to set the height of the shelf with zr_row_layout
|
||||
Input:
|
||||
- all possible selectible tabs of the shelf with names as a string array
|
||||
- number of seletectible tabs
|
||||
- current active tab array index
|
||||
- scrollbar pixel offset for the shelf
|
||||
Output:
|
||||
- group layout to fill with widgets
|
||||
- the from user input updated current shelf tab index
|
||||
*/
|
||||
void zr_shelf_end(struct zr_context *p, struct zr_context *s, struct zr_vec2 *scrollbar);
|
||||
/* this function finishes the previously started shelf layout
|
||||
Input:
|
||||
- previously started group layout
|
||||
Output:
|
||||
- The from user input updated shelf scrollbar pixel offset
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user