From: Simon Glass <simon.glass@canonical.com> Add a len parameter to vidconsole_measure() to allow measuring a substring of the input text. This is useful for measuring text up to a specific cursor position, which is needed for cursor-positioning with multi-line text input. Also return the position of the character where the substring ended, needed for cursor positioning. Pass -1 for len to measure the whole string (existing behaviour). Co-developed-by: Claude Opus 4.5 <noreply@anthropic.com> Signed-off-by: Simon Glass <simon.glass@canonical.com> --- boot/scene.c | 2 +- drivers/video/console_truetype.c | 9 ++++++--- drivers/video/vidconsole-uclass.c | 7 ++++--- include/video_console.h | 8 ++++++-- test/dm/video.c | 6 +++--- 5 files changed, 20 insertions(+), 12 deletions(-) diff --git a/boot/scene.c b/boot/scene.c index 52cb7055eb3..ff21b524843 100644 --- a/boot/scene.c +++ b/boot/scene.c @@ -538,7 +538,7 @@ int scene_obj_get_hw(struct scene *scn, uint id, int *widthp) obj->req_bbox.x1 - obj->req_bbox.x0 : -1; ret = vidconsole_measure(scn->expo->cons, gen->font_name, - gen->font_size, str, limit, &bbox, + gen->font_size, str, -1, limit, &bbox, &gen->lines); if (ret) return log_msg_ret("mea", ret); diff --git a/drivers/video/console_truetype.c b/drivers/video/console_truetype.c index 78683f8de13..25df22e31b0 100644 --- a/drivers/video/console_truetype.c +++ b/drivers/video/console_truetype.c @@ -1004,12 +1004,12 @@ static int truetype_select_font(struct udevice *dev, void *vctx, } static int truetype_measure(struct udevice *dev, const char *name, uint size, - const char *text, int pixel_limit, + const char *text, int len, int pixel_limit, struct vidconsole_bbox *bbox, struct alist *lines) { struct console_tt_metrics *met; struct vidconsole_mline mline; - const char *s, *last_space; + const char *s, *last_space, *end; int width, last_width; stbtt_fontinfo *font; int lsb, advance; @@ -1030,6 +1030,7 @@ static int truetype_measure(struct udevice *dev, const char *name, uint size, if (pixel_limit != -1) limit = tt_ceil((double)pixel_limit / met->scale); + end = len < 0 ? NULL : text + len; font = &met->font; width = 0; bbox->y1 = 0; @@ -1037,7 +1038,7 @@ static int truetype_measure(struct udevice *dev, const char *name, uint size, start = 0; last_space = NULL; last_width = 0; - for (lastch = 0, s = text; *s; s++) { + for (lastch = 0, s = text; *s && s != end; s++) { int neww; int ch = *s; @@ -1069,6 +1070,7 @@ static int truetype_measure(struct udevice *dev, const char *name, uint size, mline.bbox.x0 = 0; mline.bbox.y0 = bbox->y1; mline.bbox.x1 = tt_ceil((double)width * met->scale); + mline.xpos = (int)((double)width * met->scale); bbox->x1 = max(bbox->x1, mline.bbox.x1); bbox->y1 += met->font_size; mline.bbox.y1 = bbox->y1; @@ -1095,6 +1097,7 @@ static int truetype_measure(struct udevice *dev, const char *name, uint size, mline.bbox.x0 = 0; mline.bbox.y0 = bbox->y1; mline.bbox.x1 = tt_ceil((double)width * met->scale); + mline.xpos = (int)((double)width * met->scale); bbox->y1 += met->font_size; mline.bbox.y1 = bbox->y1; mline.start = start; diff --git a/drivers/video/vidconsole-uclass.c b/drivers/video/vidconsole-uclass.c index 0f9e9e35a98..d13b4eac272 100644 --- a/drivers/video/vidconsole-uclass.c +++ b/drivers/video/vidconsole-uclass.c @@ -665,7 +665,7 @@ int vidconsole_select_font(struct udevice *dev, void *ctx, const char *name, } int vidconsole_measure(struct udevice *dev, const char *name, uint size, - const char *text, int limit, + const char *text, int len, int limit, struct vidconsole_bbox *bbox, struct alist *lines) { struct vidconsole_ctx *ctx = vidconsole_ctx(dev); @@ -675,7 +675,8 @@ int vidconsole_measure(struct udevice *dev, const char *name, uint size, if (ops->measure) { if (lines) alist_empty(lines); - ret = ops->measure(dev, name, size, text, limit, bbox, lines); + ret = ops->measure(dev, name, size, text, len, limit, bbox, + lines); if (ret != -ENOSYS) return ret; } @@ -683,7 +684,7 @@ int vidconsole_measure(struct udevice *dev, const char *name, uint size, bbox->valid = true; bbox->x0 = 0; bbox->y0 = 0; - bbox->x1 = ctx->x_charsize * strlen(text); + bbox->x1 = ctx->x_charsize * (len < 0 ? strlen(text) : len); bbox->y1 = ctx->y_charsize; return 0; diff --git a/include/video_console.h b/include/video_console.h index 13d32dea2a9..1861138c152 100644 --- a/include/video_console.h +++ b/include/video_console.h @@ -221,11 +221,13 @@ struct vidconsole_bbox { * vidconsole_mline - Holds information about a line of measured text * * @bbox: Bounding box of the line, assuming it starts at 0,0 + * @xpos: Cursor x position at end of line (truncated, not ceiled like bbox.x1) * @start: String index of the first character in the line * @len: Number of characters in the line */ struct vidconsole_mline { struct vidconsole_bbox bbox; + int xpos; int start; int len; }; @@ -355,6 +357,7 @@ struct vidconsole_ops { * @name: Font name to use (NULL to use default) * @size: Font size to use (0 to use default) * @text: Text to measure + * @len: Number of characters to measure, or -1 for whole string * @limit: Width limit for each line, or -1 if none * @bbox: Returns bounding box of text, assuming it is positioned * at 0,0 @@ -365,7 +368,7 @@ struct vidconsole_ops { * Returns: 0 on success, -ENOENT if no such font */ int (*measure)(struct udevice *dev, const char *name, uint size, - const char *text, int limit, + const char *text, int len, int limit, struct vidconsole_bbox *bbox, struct alist *lines); /** @@ -485,6 +488,7 @@ int vidconsole_select_font(struct udevice *dev, void *ctx, const char *name, * @name: Font name to use (NULL to use default) * @size: Font size to use (0 to use default) * @text: Text to measure + * @len: Number of characters to measure, or -1 for whole string * @limit: Width limit for each line, or -1 if none * @bbox: Returns bounding box of text, assuming it is positioned * at 0,0 @@ -495,7 +499,7 @@ int vidconsole_select_font(struct udevice *dev, void *ctx, const char *name, * Returns: 0 on success, -ENOENT if no such font */ int vidconsole_measure(struct udevice *dev, const char *name, uint size, - const char *text, int limit, + const char *text, int len, int limit, struct vidconsole_bbox *bbox, struct alist *lines); /** * vidconsole_nominal() - Measure the expected width of a line of text diff --git a/test/dm/video.c b/test/dm/video.c index d3ecb62b43a..92b2ee9a6e3 100644 --- a/test/dm/video.c +++ b/test/dm/video.c @@ -982,7 +982,7 @@ static int dm_test_font_measure(struct unit_test_state *uts) 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, -1, &bbox, + ut_assertok(vidconsole_measure(con, NULL, 0, test_string, -1, -1, &bbox, &lines)); ut_asserteq(0, bbox.x0); ut_asserteq(0, bbox.y0); @@ -1013,8 +1013,8 @@ static int dm_test_font_measure(struct unit_test_state *uts) 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_assertok(vidconsole_measure(con, NULL, 0, test_string, -1, limit, + &bbox, &lines)); ut_asserteq(0, bbox.x0); ut_asserteq(0, bbox.y0); ut_asserteq(0x31e, bbox.x1); -- 2.43.0