summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTor Andersson <tor.andersson@artifex.com>2018-07-04 13:05:30 +0200
committerTor Andersson <tor.andersson@artifex.com>2018-07-06 13:54:49 +0200
commitf265c6b08f2366ffa7198cdc52c6e1884f7e4226 (patch)
tree16b1ad3f6a38e982209666dfb50de680ed33d13f
parent028d4e030cfba44896be509f4251712652c7272d (diff)
downloadmupdf-f265c6b08f2366ffa7198cdc52c6e1884f7e4226.tar.xz
gl: Multi-line labels.
-rw-r--r--platform/gl/gl-app.h9
-rw-r--r--platform/gl/gl-font.c92
-rw-r--r--platform/gl/gl-input.c98
-rw-r--r--platform/gl/gl-ui.c36
4 files changed, 133 insertions, 102 deletions
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 <string.h>
#include <stdio.h>
-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;