video: truetype: Support a limit on the width of a line
Expo needs to be able to word-wrap lines so that they are displayed as
the user expects. Add a limit on the width of each line and support this
in the measurement algorithm.
Add a log category to truetype while we are here.
Signed-off-by: Simon Glass <sjg@chromium.org>
diff --git a/drivers/video/console_truetype.c b/drivers/video/console_truetype.c
index 6eca5d7..2e3e6f0 100644
--- a/drivers/video/console_truetype.c
+++ b/drivers/video/console_truetype.c
@@ -3,6 +3,8 @@
* Copyright (c) 2016 Google, Inc
*/
+#define LOG_CATEGORY UCLASS_VIDEO
+
#include <abuf.h>
#include <dm.h>
#include <log.h>
@@ -733,16 +735,17 @@
}
static int truetype_measure(struct udevice *dev, const char *name, uint size,
- const char *text, struct vidconsole_bbox *bbox,
- struct alist *lines)
+ const char *text, int pixel_limit,
+ struct vidconsole_bbox *bbox, struct alist *lines)
{
struct console_tt_metrics *met;
struct vidconsole_mline mline;
- const char *s;
+ const char *s, *last_space;
+ int width, last_width;
stbtt_fontinfo *font;
int lsb, advance;
- int width;
int start;
+ int limit;
int lastch;
int ret;
@@ -754,14 +757,30 @@
if (!*text)
return 0;
+ limit = -1;
+ if (pixel_limit != -1)
+ limit = tt_ceil((double)pixel_limit / met->scale);
+
font = &met->font;
width = 0;
bbox->y1 = 0;
+ bbox->x1 = 0;
start = 0;
+ last_space = NULL;
+ last_width = 0;
for (lastch = 0, s = text; *s; s++) {
int neww;
int ch = *s;
+ if (ch == ' ') {
+ /*
+ * store the position and width so we can use it again
+ * if we need to word-wrap
+ */
+ last_space = s;
+ last_width = width;
+ }
+
/* First get some basic metrics about this character */
stbtt_GetCodepointHMetrics(font, ch, &advance, &lsb);
neww = width + advance;
@@ -772,10 +791,16 @@
lastch = ch;
/* see if we need to start a new line */
- if (ch == '\n') {
+ if (ch == '\n' || (limit != -1 && neww >= limit)) {
+ if (ch != '\n' && last_space) {
+ s = last_space;
+ width = last_width;
+ }
+ last_space = NULL;
mline.bbox.x0 = 0;
mline.bbox.y0 = bbox->y1;
mline.bbox.x1 = tt_ceil((double)width * met->scale);
+ bbox->x1 = max(bbox->x1, mline.bbox.x1);
bbox->y1 += met->font_size;
mline.bbox.y1 = bbox->y1;
mline.bbox.valid = true;
@@ -788,8 +813,7 @@
mline.start, mline.len, mline.len, text + mline.start);
start = s - text;
- if (ch == '\n')
- start++;
+ start++;
lastch = 0;
neww = 0;
}
@@ -811,7 +835,7 @@
bbox->valid = true;
bbox->x0 = 0;
bbox->y0 = 0;
- bbox->x1 = tt_ceil((double)width * met->scale);
+ bbox->x1 = max(bbox->x1, mline.bbox.x1);
return 0;
}
diff --git a/drivers/video/vidconsole-uclass.c b/drivers/video/vidconsole-uclass.c
index 4ca41dc..3259bd2 100644
--- a/drivers/video/vidconsole-uclass.c
+++ b/drivers/video/vidconsole-uclass.c
@@ -608,8 +608,8 @@
}
int vidconsole_measure(struct udevice *dev, const char *name, uint size,
- const char *text, struct vidconsole_bbox *bbox,
- struct alist *lines)
+ const char *text, int limit,
+ struct vidconsole_bbox *bbox, struct alist *lines)
{
struct vidconsole_priv *priv = dev_get_uclass_priv(dev);
struct vidconsole_ops *ops = vidconsole_get_ops(dev);
@@ -618,7 +618,7 @@
if (ops->measure) {
if (lines)
alist_empty(lines);
- ret = ops->measure(dev, name, size, text, bbox, lines);
+ ret = ops->measure(dev, name, size, text, limit, bbox, lines);
if (ret != -ENOSYS)
return ret;
}