}
ret = vidconsole_measure(scn->expo->cons, txt->font_name,
- txt->font_size, str, &bbox, NULL);
+ txt->font_size, str, -1, &bbox, NULL);
if (ret)
return log_msg_ret("mea", ret);
if (widthp)
* Copyright (c) 2016 Google, Inc
*/
+#define LOG_CATEGORY UCLASS_VIDEO
+
#include <abuf.h>
#include <dm.h>
#include <log.h>
}
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;
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;
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;
mline.start, mline.len, mline.len, text + mline.start);
start = s - text;
- if (ch == '\n')
- start++;
+ start++;
lastch = 0;
neww = 0;
}
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;
}
}
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);
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;
}
* @name: Font name to use (NULL to use default)
* @size: Font size to use (0 to use default)
* @text: Text to measure
+ * @limit: Width limit for each line, or -1 if none
* @bbox: Returns bounding box of text, assuming it is positioned
* at 0,0
* @lines: If non-NULL, this must be an alist of
* Returns: 0 on success, -ENOENT if no such font
*/
int (*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);
/**
* nominal() - Measure the expected width of a line of text
* @name: Font name to use (NULL to use default)
* @size: Font size to use (0 to use default)
* @text: Text to measure
+ * @limit: Width limit for each line, or -1 if none
* @bbox: Returns bounding box of text, assuming it is positioned
* at 0,0
* @lines: If non-NULL, this must be an alist of
* Returns: 0 on success, -ENOENT if no such font
*/
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);
/**
* vidconsole_nominal() - Measure the expected width of a line of text
*
struct vidconsole_bbox bbox;
struct video_priv *priv;
struct udevice *dev, *con;
+ const int limit = 0x320;
struct alist lines;
int nl;
ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
vidconsole_position_cursor(con, 0, 0);
alist_init_struct(&lines, struct vidconsole_mline);
- ut_assertok(vidconsole_measure(con, NULL, 0, test_string, &bbox,
+ ut_assertok(vidconsole_measure(con, NULL, 0, test_string, -1, &bbox,
&lines));
ut_asserteq(0, bbox.x0);
ut_asserteq(0, bbox.y0);
ut_asserteq(163, line->len);
ut_asserteq(strlen(test_string + nl + 1), line->len);
+ /* now use a limit on the width */
+ ut_assertok(vidconsole_measure(con, NULL, 0, test_string, limit, &bbox,
+ &lines));
+ ut_asserteq(0, bbox.x0);
+ ut_asserteq(0, bbox.y0);
+ ut_asserteq(0x31e, bbox.x1);
+ ut_asserteq(0x36, bbox.y1);
+ ut_asserteq(3, lines.count);
+
+ nl = strchr(test_string, '\n') - test_string;
+
+ line = alist_get(&lines, 0, struct vidconsole_mline);
+ ut_assertnonnull(line);
+ ut_asserteq(0, line->bbox.x0);
+ ut_asserteq(0, line->bbox.y0);
+ ut_asserteq(0x8c, line->bbox.x1);
+ ut_asserteq(0x12, line->bbox.y1);
+ ut_asserteq(0, line->start);
+ ut_asserteq(20, line->len);
+ ut_asserteq(nl, line->len);
+ printf("line0 '%.*s'\n", line->len, test_string + line->start);
+ ut_asserteq_strn("There is always much",
+ test_string + line->start);
+
+ line++;
+ ut_asserteq(0x0, line->bbox.x0);
+ ut_asserteq(0x12, line->bbox.y0);
+ ut_asserteq(0x31e, line->bbox.x1);
+ ut_asserteq(0x24, line->bbox.y1);
+ ut_asserteq(21, line->start);
+ ut_asserteq(nl + 1, line->start);
+ ut_asserteq(129, line->len);
+ printf("line1 '%.*s'\n", line->len, test_string + line->start);
+ ut_asserteq_strn("to be said for not attempting more than you can do "
+ "and for making a certainty of what you try. But this "
+ "principle, like others in",
+ test_string + line->start);
+
+ line++;
+ ut_asserteq(0x0, line->bbox.x0);
+ ut_asserteq(0x24, line->bbox.y0);
+ ut_asserteq(0xc8, line->bbox.x1);
+ ut_asserteq(0x36, line->bbox.y1);
+ ut_asserteq(21 + 130, line->start);
+ ut_asserteq(33, line->len);
+ printf("line2 '%.*s'\n", line->len, test_string + line->start);
+ ut_asserteq_strn("life and war, has its exceptions.",
+ test_string + line->start);
+
+ /*
+ * all characters should be accounted for, except the newline and the
+ * space which is consumed in the wordwrap
+ */
+ ut_asserteq(strlen(test_string) - 2,
+ line[-2].len + line[-1].len + line->len);
+
return 0;
}
DM_TEST(dm_test_font_measure, UTF_SCAN_FDT);