video: truetype: Support newlines in the measured string
It is useful to be able to embed newline characters in the string and
have the text measured into multiple lines. Add support for this.
Signed-off-by: Simon Glass <sjg@chromium.org>
diff --git a/drivers/video/console_truetype.c b/drivers/video/console_truetype.c
index 39d77ad..6eca5d7 100644
--- a/drivers/video/console_truetype.c
+++ b/drivers/video/console_truetype.c
@@ -771,10 +771,33 @@
neww += stbtt_GetCodepointKernAdvance(font, lastch, ch);
lastch = ch;
+ /* see if we need to start a new line */
+ if (ch == '\n') {
+ mline.bbox.x0 = 0;
+ mline.bbox.y0 = bbox->y1;
+ mline.bbox.x1 = tt_ceil((double)width * met->scale);
+ bbox->y1 += met->font_size;
+ mline.bbox.y1 = bbox->y1;
+ mline.bbox.valid = true;
+ mline.start = start;
+ mline.len = (s - text) - start;
+ if (lines && !alist_add(lines, mline))
+ return log_msg_ret("ttm", -ENOMEM);
+ log_debug("line x1 %d y0 %d y1 %d start %d len %d text '%.*s'\n",
+ mline.bbox.x1, mline.bbox.y0, mline.bbox.y1,
+ mline.start, mline.len, mline.len, text + mline.start);
+
+ start = s - text;
+ if (ch == '\n')
+ start++;
+ lastch = 0;
+ neww = 0;
+ }
+
width = neww;
}
- /* add the line */
+ /* add the final line */
mline.bbox.x0 = 0;
mline.bbox.y0 = bbox->y1;
mline.bbox.x1 = tt_ceil((double)width * met->scale);
diff --git a/include/video_console.h b/include/video_console.h
index ee9ce3c..a0ee9ab 100644
--- a/include/video_console.h
+++ b/include/video_console.h
@@ -244,6 +244,8 @@
/**
* measure() - Measure the bounding box of some text
*
+ * The text can include newlines
+ *
* @dev: Console device to use
* @name: Font name to use (NULL to use default)
* @size: Font size to use (0 to use default)
@@ -342,6 +344,8 @@
/**
* vidconsole_measure() - Measure the bounding box of some text
*
+ * The text can include newlines
+ *
* @dev: Device to adjust
* @name: Font name to use (NULL to use default)
* @size: Font size to use (0 to use default)
diff --git a/test/dm/video.c b/test/dm/video.c
index d3fd74a..a3f3b04 100644
--- a/test/dm/video.c
+++ b/test/dm/video.c
@@ -781,7 +781,7 @@
/* Test font measurement */
static int dm_test_font_measure(struct unit_test_state *uts)
{
- const char *test_string = "There is always much to be said for not "
+ const char *test_string = "There is always much\nto 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 life and "
"war, has its exceptions.";
@@ -790,6 +790,7 @@
struct video_priv *priv;
struct udevice *dev, *con;
struct alist lines;
+ int nl;
ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
priv = dev_get_uclass_priv(dev);
@@ -804,18 +805,31 @@
&lines));
ut_asserteq(0, bbox.x0);
ut_asserteq(0, bbox.y0);
- ut_asserteq(0x47a, bbox.x1);
- ut_asserteq(0x12, bbox.y1);
- ut_asserteq(1, lines.count);
+ ut_asserteq(0x3ea, bbox.x1);
+ ut_asserteq(0x24, bbox.y1);
+ ut_asserteq(2, 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(0x47a, line->bbox.x1);
+ ut_asserteq(0x8c, line->bbox.x1);
ut_asserteq(0x12, line->bbox.y1);
ut_asserteq(0, line->start);
- ut_asserteq(strlen(test_string), line->len);
+ ut_asserteq(20, line->len);
+ ut_asserteq(nl, line->len);
+
+ line++;
+ ut_asserteq(0x0, line->bbox.x0);
+ ut_asserteq(0x12, line->bbox.y0);
+ ut_asserteq(0x3ea, line->bbox.x1);
+ ut_asserteq(0x24, line->bbox.y1);
+ ut_asserteq(21, line->start);
+ ut_asserteq(nl + 1, line->start);
+ ut_asserteq(163, line->len);
+ ut_asserteq(strlen(test_string + nl + 1), line->len);
return 0;
}