From patchwork Thu Jan 22 04:11:41 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1772 Return-Path: X-Original-To: u-boot-concept@u-boot.org Delivered-To: u-boot-concept@u-boot.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1769055189; bh=w+43iceiYzZOHOEed9buG1+iJzsDJY1hw0dBEMM8YXo=; h=From:To:Date:In-Reply-To:References:CC:Subject:List-Id: List-Archive:List-Help:List-Owner:List-Post:List-Subscribe: List-Unsubscribe:From; b=GgVltukDCXW+HymsMOqBmA0GMEfES9mjcLlhfS5PAevwM9qWzXvu3h7ifepajRwrP 82pT1ox7ulQSgFqWjNlTcnaTXXfj208P9hqrde2AI3jRLHDJILHktc81AM5O5HDdrQ yZEIVY3zlrA4n0A98agN1fLDORMwVlWZkvTlDqdvSrz1CgB3263GAVaE9aIFBgiTLv IVg830FkhTdzXXZkEx/srrGuBEVzY9KowVRBeqWXZC4IF+0vCYLJ5aivfNOPdPYR5b hXHLZrUtkKn6+d5J4ThugNznSoyABXbHZtueX++PzxWfaR7htYeXNKPIOyw/g9u6+4 g6ln1Q1k374Zg== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 394ED6962E for ; Wed, 21 Jan 2026 21:13:09 -0700 (MST) X-Virus-Scanned: Debian amavis at Received: from mail.u-boot.org ([127.0.0.1]) by localhost (mail.u-boot.org [127.0.0.1]) (amavis, port 10024) with ESMTP id si027JeirWtX for ; Wed, 21 Jan 2026 21:13:09 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1769055189; bh=w+43iceiYzZOHOEed9buG1+iJzsDJY1hw0dBEMM8YXo=; h=From:To:Date:In-Reply-To:References:CC:Subject:List-Id: List-Archive:List-Help:List-Owner:List-Post:List-Subscribe: List-Unsubscribe:From; b=GgVltukDCXW+HymsMOqBmA0GMEfES9mjcLlhfS5PAevwM9qWzXvu3h7ifepajRwrP 82pT1ox7ulQSgFqWjNlTcnaTXXfj208P9hqrde2AI3jRLHDJILHktc81AM5O5HDdrQ yZEIVY3zlrA4n0A98agN1fLDORMwVlWZkvTlDqdvSrz1CgB3263GAVaE9aIFBgiTLv IVg830FkhTdzXXZkEx/srrGuBEVzY9KowVRBeqWXZC4IF+0vCYLJ5aivfNOPdPYR5b hXHLZrUtkKn6+d5J4ThugNznSoyABXbHZtueX++PzxWfaR7htYeXNKPIOyw/g9u6+4 g6ln1Q1k374Zg== Received: from mail.u-boot.org (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 2800D6962C for ; Wed, 21 Jan 2026 21:13:09 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1769055186; bh=vbTpOMFIUIzxMG6q2MN6T3C+sqtHtTeekRnmlQRbq40=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=tebHawQ4MHz0BGWKmGttsELccxj/4GfeD+hLG1/0cSGbMNGr7/JQBKeIuxOj23ill JC1BKM0RlUHFCO0UnGjiui5iK7dLDXGQ7wX6uTqqAQOCSiLqn6b73/rxYctMvSYTsa IRiHfhxShAjMN2MkrswdRhTAGHd+UnWMGxLt22EWBUl4YHEJOJxi6A52imECODDM+8 BcQAoRMGHkDZnodxw1LpEdi26OwY+XYmfhqmPDTi6ZzSPhhkoXhymsaQaUhVYwchFi wTHtKo0i3CGOMTY+WJMbK1059wYRG5az+xRpiFkLaaZeFxGx5hdOJWLEfutouBPzez EGU+//xh7CrJw== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id E07E2694CC; Wed, 21 Jan 2026 21:13:06 -0700 (MST) X-Virus-Scanned: Debian amavis at Received: from mail.u-boot.org ([127.0.0.1]) by localhost (mail.u-boot.org [127.0.0.1]) (amavis, port 10026) with ESMTP id WU1YAdqzQRoq; Wed, 21 Jan 2026 21:13:06 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1769055182; bh=nupaMu+rDpQenfrd57AQ//N6gpw79ZHjmUm8/UbwaEo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=BeH3ozmPR3gRBfq+YTshXaAU2y3HSN5VKn1J+kjexVxlk2U8JuFmao6R0CxmrtcDe TZX4Mgr+SiorRSaVARHyvU/H5jtb1Xet6dLgNAbD8HlI9ftCtUVWR/XY5KyeCBVAcQ 32aDCKXKwpUDaHJ8EJkPP1Q/oDasIp6GIY1/GdNFl11XToKky1uSp3DcVALRBuwLCy tVcCJEl08hPc0ggFIyjXsPIgdevHkZAS1D7WvN7hl7bxSFcOTiqGlxL3tN8gy8ihUV qUKK2I70cMnrTo23be0h/GYl3O+Px/n9YRvjIlvXMYtmggVXLLgf7VWnGaWr/1Crrt rgNAmC6c9xhnA== Received: from u-boot.org (unknown [73.34.74.121]) by mail.u-boot.org (Postfix) with ESMTPSA id 4E01569616; Wed, 21 Jan 2026 21:13:02 -0700 (MST) From: Simon Glass To: U-Boot Concept Date: Wed, 21 Jan 2026 21:11:41 -0700 Message-ID: <20260122041155.174721-14-sjg@u-boot.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260122041155.174721-1-sjg@u-boot.org> References: <20260122041155.174721-1-sjg@u-boot.org> MIME-Version: 1.0 Message-ID-Hash: APQBOT2UPGFJZ7SUYLJ4EJFE2E3KEZVK X-Message-ID-Hash: APQBOT2UPGFJZ7SUYLJ4EJFE2E3KEZVK X-MailFrom: sjg@u-boot.org X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: Simon Glass , "Claude Opus 4 . 5" X-Mailman-Version: 3.3.10 Precedence: list Subject: [Concept] [PATCH 13/16] video: Add len parameter to vidconsole_measure() List-Id: Discussion and patches related to U-Boot Concept Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: From: Simon Glass 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 Signed-off-by: Simon Glass --- 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);