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>
This commit is contained in:
Simon Glass
2025-04-02 06:29:38 +13:00
committed by Tom Rini
parent a7bbc59c31
commit 030e53aaaa
3 changed files with 48 additions and 7 deletions

View File

@@ -771,10 +771,33 @@ static int truetype_measure(struct udevice *dev, const char *name, uint size,
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);

View File

@@ -244,6 +244,8 @@ struct vidconsole_ops {
/**
* 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 @@ int vidconsole_select_font(struct udevice *dev, const char *name, uint size);
/**
* 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)

View File

@@ -781,7 +781,7 @@ DM_TEST(dm_test_video_damage, UTF_SCAN_PDATA | UTF_SCAN_FDT);
/* 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 @@ static int dm_test_font_measure(struct unit_test_state *uts)
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 @@ static int dm_test_font_measure(struct unit_test_state *uts)
&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;
}