From f265c6b08f2366ffa7198cdc52c6e1884f7e4226 Mon Sep 17 00:00:00 2001 From: Tor Andersson Date: Wed, 4 Jul 2018 13:05:30 +0200 Subject: gl: Multi-line labels. --- platform/gl/gl-app.h | 9 +++++ platform/gl/gl-font.c | 92 +++++++++++++++++++++++++++++++++++++++++++---- platform/gl/gl-input.c | 98 ++++++++------------------------------------------ platform/gl/gl-ui.c | 36 ++++++++++++------- 4 files changed, 133 insertions(+), 102 deletions(-) (limited to 'platform/gl') diff --git a/platform/gl/gl-app.h b/platform/gl/gl-app.h index 0cc330d6..64c9335f 100644 --- a/platform/gl/gl-app.h +++ b/platform/gl/gl-app.h @@ -117,7 +117,14 @@ float ui_draw_character(int ucs, float x, float y); void ui_end_text(void); float ui_draw_string(float x, float y, const char *str); +void ui_draw_string_part(float x, float y, const char *s, const char *e); float ui_measure_string(const char *str); +float ui_measure_string_part(const char *s, const char *e); + +struct line { char *a, *b; }; + +int ui_break_lines(char *a, struct line *lines, int nlines, int width, int *maxwidth); +void ui_draw_lines(float x, float y, struct line *lines, int n); struct texture { @@ -158,6 +165,8 @@ int ui_mouse_inside(fz_irect *area); void ui_layout(enum side side, enum fill fill, enum anchor anchor, int padx, int pady); fz_irect ui_pack_layout(int slave_w, int slave_h, enum side side, enum fill fill, enum anchor anchor, int padx, int pady); fz_irect ui_pack(int slave_w, int slave_h); +int ui_available_width(void); +int ui_available_height(void); void ui_pack_push(fz_irect cavity); void ui_pack_pop(void); diff --git a/platform/gl/gl-font.c b/platform/gl/gl-font.c index 8a331b3e..3b7c3e77 100644 --- a/platform/gl/gl-font.c +++ b/platform/gl/gl-font.c @@ -282,30 +282,108 @@ void ui_end_text(void) float ui_draw_string(float x, float y, const char *str) { int ucs; - ui_begin_text(); - while (*str) { str += fz_chartorune(&ucs, str); - x += ui_draw_character(ucs, x, y); + x += ui_draw_character(ucs, x, y + ui.baseline); } - ui_end_text(); - return x; } +void ui_draw_string_part(float x, float y, const char *s, const char *e) +{ + int c; + ui_begin_text(); + while (s < e) + { + s += fz_chartorune(&c, s); + x += ui_draw_character(c, x, y + ui.baseline); + } + ui_end_text(); +} + float ui_measure_string(const char *str) { int ucs; float x = 0; - while (*str) { str += fz_chartorune(&ucs, str); x += ui_measure_character(ucs); } - return x; } + +float ui_measure_string_part(const char *s, const char *e) +{ + int c; + float w = 0; + while (s < e) + { + s += fz_chartorune(&c, s); + w += ui_measure_character(c); + } + return w; +} + +int ui_break_lines(char *a, struct line *lines, int maxlines, int width, int *maxwidth) +{ + char *next, *b = a; + int c, n = 0; + float x = 0, w = 0; + if (maxwidth) + *maxwidth = 0; + while (*b) + { + next = b + fz_chartorune(&c, b); + if (c == '\n' || c == '\r') + { + if (n + 1 < maxlines) + { + if (maxwidth && x > *maxwidth) + *maxwidth = x; + lines[n].a = a; + lines[n].b = b; + ++n; + a = next; + x = 0; + } + } + else + { + w = ui_measure_character(c); + if (x + w > width && (n + 1 < maxlines)) + { + if (maxwidth && x > *maxwidth) + *maxwidth = x; + lines[n].a = a; + lines[n].b = b; + ++n; + a = b; + x = w; + } + else + { + x += w; + } + } + b = next; + } + if (maxwidth && x > *maxwidth) + *maxwidth = x; + lines[n].a = a; + lines[n].b = b; + return n + 1; +} + +void ui_draw_lines(float x, float y, struct line *lines, int n) +{ + int i; + for (i = 0; i < n; ++i) + { + ui_draw_string_part(x, y, lines[i].a, lines[i].b); + y += ui.lineheight; + } +} diff --git a/platform/gl/gl-input.c b/platform/gl/gl-input.c index c3898f50..4163926f 100644 --- a/platform/gl/gl-input.c +++ b/platform/gl/gl-input.c @@ -3,74 +3,6 @@ #include #include -struct line { char *a, *b; }; - -static int break_lines(char *a, char *end, struct line *lines, int maxlines, int width) -{ - char *next, *b = a; - int c, n = 0; - float x = 0, w = 0; - while (b < end) - { - next = b + fz_chartorune(&c, b); - if (c == '\n' || c == '\r') - { - if (n + 1 < maxlines) - { - lines[n].a = a; - lines[n].b = b; - ++n; - a = next; - x = 0; - } - } - else - { - w = ui_measure_character(c); - if (x + w > width && (n + 1 < maxlines)) - { - lines[n].a = a; - lines[n].b = b; - ++n; - a = b; - x = w; - } - else - { - x += w; - } - } - b = next; - } - lines[n].a = a; - lines[n].b = b; - return n + 1; -} - -static void draw_string_part(float x, float y, const char *s, const char *e) -{ - int c; - ui_begin_text(); - while (s < e) - { - s += fz_chartorune(&c, s); - x += ui_draw_character(c, x, y + ui.baseline); - } - ui_end_text(); -} - -static float measure_string_part(const char *s, const char *e) -{ - int c; - float w = 0; - while (s < e) - { - s += fz_chartorune(&c, s); - w += ui_measure_character(c); - } - return w; -} - static char *find_string_location(char *s, char *e, float w, float x) { int c; @@ -414,7 +346,7 @@ int ui_input(struct input *input, int width, int height) if (height > 1) area.x1 -= ui.lineheight; - n = break_lines(input->text, input->end, lines, nelem(lines), area.x1-area.x0-2); + n = ui_break_lines(input->text, lines, nelem(lines), area.x1-area.x0-2, NULL); if (height > 1) ui_scrollbar(area.x1, area.y0, area.x1+ui.lineheight, area.y1, &input->scroll, 1, fz_maxi(0, n-height)+1); @@ -454,54 +386,54 @@ int ui_input(struct input *input, int width, int height) { if (p >= a && p <= b && q >= a && q <= b) { - float px = ax + measure_string_part(a, p); - float qx = px + measure_string_part(p, q); + float px = ax + ui_measure_string_part(a, p); + float qx = px + ui_measure_string_part(p, q); glColorHex(UI_COLOR_TEXT_SEL_BG); glRectf(px, ay, qx+1, ay + ui.lineheight); glColorHex(UI_COLOR_TEXT_FG); - draw_string_part(ax, ay, a, p); + ui_draw_string_part(ax, ay, a, p); glColorHex(UI_COLOR_TEXT_SEL_FG); - draw_string_part(px, ay, p, q); + ui_draw_string_part(px, ay, p, q); glColorHex(UI_COLOR_TEXT_FG); - draw_string_part(qx, ay, q, b); + ui_draw_string_part(qx, ay, q, b); } else if (p < a && q >= a && q <= b) { - float qx = ax + measure_string_part(a, q); + float qx = ax + ui_measure_string_part(a, q); glColorHex(UI_COLOR_TEXT_SEL_BG); glRectf(ax, ay, qx+1, ay + ui.lineheight); glColorHex(UI_COLOR_TEXT_SEL_FG); - draw_string_part(ax, ay, a, q); + ui_draw_string_part(ax, ay, a, q); glColorHex(UI_COLOR_TEXT_FG); - draw_string_part(qx, ay, q, b); + ui_draw_string_part(qx, ay, q, b); } else if (p >= a && p <= b && q > b) { - float px = ax + measure_string_part(a, p); + float px = ax + ui_measure_string_part(a, p); glColorHex(UI_COLOR_TEXT_SEL_BG); glRectf(px, ay, bx, ay + ui.lineheight); glColorHex(UI_COLOR_TEXT_FG); - draw_string_part(ax, ay, a, p); + ui_draw_string_part(ax, ay, a, p); glColorHex(UI_COLOR_TEXT_SEL_FG); - draw_string_part(px, ay, p, b); + ui_draw_string_part(px, ay, p, b); } else if (p < a && q > b) { glColorHex(UI_COLOR_TEXT_SEL_BG); glRectf(ax, ay, bx, ay + ui.lineheight); glColorHex(UI_COLOR_TEXT_SEL_FG); - draw_string_part(ax, ay, a, b); + ui_draw_string_part(ax, ay, a, b); } else { glColorHex(UI_COLOR_TEXT_FG); - draw_string_part(ax, ay, a, b); + ui_draw_string_part(ax, ay, a, b); } } else { glColorHex(UI_COLOR_TEXT_FG); - draw_string_part(ax, ay, a, b); + ui_draw_string_part(ax, ay, a, b); } ay += ui.lineheight; } diff --git a/platform/gl/gl-ui.c b/platform/gl/gl-ui.c index 9539af7b..7ce94500 100644 --- a/platform/gl/gl-ui.c +++ b/platform/gl/gl-ui.c @@ -631,6 +631,16 @@ fz_irect ui_pack(int slave_w, int slave_h) return ui_pack_layout(slave_w, slave_h, ui.layout->side, ui.layout->fill, ui.layout->anchor, ui.layout->padx, ui.layout->pady); } +int ui_available_width(void) +{ + return ui.cavity->x1 - ui.cavity->x0 - ui.layout->padx * 2; +} + +int ui_available_height(void) +{ + return ui.cavity->y1 - ui.cavity->y0 - ui.layout->pady * 2; +} + void ui_pack_push(fz_irect cavity) { *(++ui.cavity) = cavity; @@ -704,7 +714,8 @@ void ui_spacer(void) void ui_label(const char *fmt, ...) { char buf[512]; - int width; + struct line lines[20]; + int avail, used, n; fz_irect area; va_list ap; @@ -712,10 +723,11 @@ void ui_label(const char *fmt, ...) fz_vsnprintf(buf, sizeof buf, fmt, ap); va_end(ap); - width = ui_measure_string(buf); - area = ui_pack(width, ui.lineheight); + avail = ui_available_width(); + n = ui_break_lines(buf, lines, nelem(lines), avail, &used); + area = ui_pack(used, n * ui.lineheight); glColorHex(UI_COLOR_TEXT_FG); - ui_draw_string(area.x0, area.y0 + ui.baseline, buf); + ui_draw_lines(area.x0, area.y0, lines, n); } int ui_button(const char *label) @@ -735,7 +747,7 @@ int ui_button(const char *label) pressed = (ui.hot == label && ui.active == label && ui.down); ui_draw_bevel_rect(area, UI_COLOR_BUTTON, pressed); glColorHex(UI_COLOR_TEXT_FG); - ui_draw_string(text_x + pressed, area.y0+3 + ui.baseline + pressed, label); + ui_draw_string(text_x + pressed, area.y0+3 + pressed, label); return ui.hot == label && ui.active == label && !ui.down; } @@ -748,7 +760,7 @@ int ui_checkbox(const char *label, int *value) int pressed; glColorHex(UI_COLOR_TEXT_FG); - ui_draw_string(mark.x1 + 4, area.y0 + ui.baseline, label); + ui_draw_string(mark.x1 + 4, area.y0, label); if (ui_mouse_inside(&area)) { @@ -991,12 +1003,12 @@ int ui_list_item_x(struct list *list, const void *id, int indent, const char *la glColorHex(UI_COLOR_TEXT_SEL_BG); glRectf(area.x0, area.y0, area.x1, area.y1); glColorHex(UI_COLOR_TEXT_SEL_FG); - ui_draw_string(area.x0 + indent, area.y0 + ui.baseline, label); + ui_draw_string(area.x0 + indent, area.y0, label); } else { glColorHex(UI_COLOR_TEXT_FG); - ui_draw_string(area.x0 + indent, area.y0 + ui.baseline, label); + ui_draw_string(area.x0 + indent, area.y0, label); } } @@ -1036,7 +1048,7 @@ int ui_popup(const void *id, const char *label, int is_button, int count) { ui_draw_bevel_rect(area, UI_COLOR_BUTTON, pressed); glColorHex(UI_COLOR_TEXT_FG); - ui_draw_string(area.x0 + 6+pressed, area.y0+3 + ui.baseline+pressed, label); + ui_draw_string(area.x0 + 6+pressed, area.y0+3+pressed, label); glBegin(GL_TRIANGLES); glVertex2f(area.x1+pressed-8-10, area.y0+pressed+9); glVertex2f(area.x1+pressed-8, area.y0+pressed+9); @@ -1048,7 +1060,7 @@ int ui_popup(const void *id, const char *label, int is_button, int count) fz_irect arrow = { area.x1-22, area.y0+2, area.x1-2, area.y1-2 }; ui_draw_bevel_rect(area, UI_COLOR_TEXT_BG, 1); glColorHex(UI_COLOR_TEXT_FG); - ui_draw_string(area.x0 + 6, area.y0+3 + ui.baseline, label); + ui_draw_string(area.x0 + 6, area.y0+3, label); ui_draw_ibevel_rect(arrow, UI_COLOR_BUTTON, pressed); glColorHex(UI_COLOR_TEXT_FG); @@ -1101,12 +1113,12 @@ int ui_popup_item(const char *title) glColorHex(UI_COLOR_TEXT_SEL_BG); glRectf(area.x0, area.y0, area.x1, area.y1); glColorHex(UI_COLOR_TEXT_SEL_FG); - ui_draw_string(area.x0 + 4, area.y0 + ui.baseline, title); + ui_draw_string(area.x0 + 4, area.y0, title); } else { glColorHex(UI_COLOR_TEXT_FG); - ui_draw_string(area.x0 + 4, area.y0 + ui.baseline, title); + ui_draw_string(area.x0 + 4, area.y0, title); } return ui.hot == title && !ui.down; -- cgit v1.2.3