From patchwork Fri Sep 19 20:14:46 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 381 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=1758313055; bh=lLodAZTgmP1kAsniY9oJKIJpBFinulQjsUinEaOnlaw=; 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=Qc9Amd2Wm30LyrFH0EPcwZvJ1+BiGOvtrKDB6qgKcRieKVQWKfH3jXqyElqi4RwMd yNjbMY23lNS+gzNbQlLCslxD0lp3T4XsyWjPuZRZU2rPHHaNPtnEKLxITQreTqs+x8 ik9RTPleArS1B1RZvSUTq8V2nKnEiMwuPXpYL9yflopNi4BvVmY4JQf+f9GFdrfGCU oE4ihjEnduE9QS2m3dcdrw63SjS2dXLqFbtvv29uMdUaGXypHxPHruGomcWt0G0KKn pKLNsIiwXFZVnJgKhWvxL3i70/WwohLOSYdxm4lMbWym14hYsX5erOV1GGOtvRy0gJ OQ9q482N2UeJA== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 0AEC767C88 for ; Fri, 19 Sep 2025 14:17:35 -0600 (MDT) 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 czQniurCNOXN for ; Fri, 19 Sep 2025 14:17:34 -0600 (MDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1758313054; bh=lLodAZTgmP1kAsniY9oJKIJpBFinulQjsUinEaOnlaw=; 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=ffVNrKMJJGiZTtRMnOJA3ldCIrur3q0O8rc2EvKTJIgKsPbSvGJkd3d8iq+RDXL4O ACvNk5PIv+DMvwvo8+KZDlDlFlBbJiqi+FJ7SuZfZzFn9YWboeouWEOm2WgvyBVmo9 43lVUdOdOnb+XCQEzX8r5I6E/MGOvmofVErpgHE/K7whW8pfC8KQs6PFcGRY5XT+lb TN9qav/CEoHs0Ugt3BzFdvVfXY7kV2cR8ve0wOtoivna5QfWrX1FbhfisKkIZdFKNZ 7Zyq7pMBppClDJBIv2tAuN292Ln4DxChG0athZwB67GaYox7ICNFaSsj66FNQl9Id5 6NStr8Xhje7BA== Received: from mail.u-boot.org (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id E4E4067C0E for ; Fri, 19 Sep 2025 14:17:34 -0600 (MDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1758313052; bh=/te0abcUOn3EQngu4rt6IPKE+RYXejH1lagAC5GoNCY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=jLNFhIayZRLj8prmjCDo1WtkEAtYWVLeTS8I1MyXi4KwhNscPu35Zsf93zzi3fxbk cdC65V1IVVrwFJiN6xG1hPxcbOqsdLRcF76Qcx0XfeytHYgJ2gfQ7AZAjlinnXKPwB O0DZ8kQwtsxsnIdM2PECeYZdVl2WstNUlvKxsF5Wg7HsCNieyK/Kydn+/oRCu1oCHT QkwjQyh50pq5f2bBGZKWSqCtVqQLHMHabNS+U8o2Qs3vHYCbFmC3xxFgJEisWW2Jw1 UlCu5gmiSoGjzX+/hVjWdHbbtu30nPWnWZ77JuHFuqW/O+FQRbBIYcdxaQUHbFVtTd URP88Vnj+J7mg== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 3E50567B3B; Fri, 19 Sep 2025 14:17:32 -0600 (MDT) 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 jjy5ed4AkT8m; Fri, 19 Sep 2025 14:17:32 -0600 (MDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1758313050; bh=YI9lm2WGrcw5DqgDTni3BFLVtYLcqpIoZylKQ5XZvzo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=rXB0lSCWB18vJ4mG4Z6uW5UYBgJNIdrn2wX2ESMSEH+sBWsEDJc9dwtgulw+a/fR1 6hU7/RUc2cgIsTawrMmifuL8D4cIkQUnR0BCdCv601CBT3NIoSzH+GRsCwRYu0sZsV p7ictaCUfV5evboy9wld7pXNMA8i90PWqdQg9wSQAsbhq1pbDAxXi8fYFb3vqP9HiQ ons5AOBG6rrChOt3Dn/NiVISZA0yoUCLiG2q7L97r6m7ls3oj5+sSCopZYEWo5yoE+ d5fHK67p8kXekvcjEPlXJSLdVjISAiD+0mCqhuqUjOWcusqE2cFC7VWZfXPu9VVR+i Wyg5+qERNWxLA== Received: from u-boot.org (unknown [73.34.74.121]) by mail.u-boot.org (Postfix) with ESMTPSA id 6F87F67BFC; Fri, 19 Sep 2025 14:17:30 -0600 (MDT) From: Simon Glass To: U-Boot Concept Date: Fri, 19 Sep 2025 14:14:46 -0600 Message-ID: <20250919201507.4024144-40-sjg@u-boot.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250919201507.4024144-1-sjg@u-boot.org> References: <20250919201507.4024144-1-sjg@u-boot.org> MIME-Version: 1.0 Message-ID-Hash: GV32L4ZWDPYPYOR6T7E2CNUMR2Y5MCMA X-Message-ID-Hash: GV32L4ZWDPYPYOR6T7E2CNUMR2Y5MCMA 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: Heinrich Schuchardt , Simon Glass X-Mailman-Version: 3.3.10 Precedence: list Subject: [Concept] [PATCH 39/42] video: truetype: Clear after the current char on insert 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 Within the CLI, inserting a character works by writing out the new char and then all the ones after it. With the truetype console this results in gibberish since the new chars are written on top of the old. To resolve this, clear the rest of the input when a character is inserted. Consider that the end of the input, at least until furture characters are written. As an optimisation, don't clear if the new character is the same as the old. This cleans up a dot above the 'g' of greatness which should not be there, so update the dm_test_video_truetype() test. It also clean up the part of the 't' of 'not be' which should not be there, so update dm_test_video_truetype_bs() too. Signed-off-by: Simon Glass --- drivers/video/console_truetype.c | 76 ++++++++++++++++++++++++++++++-- test/dm/video.c | 4 +- 2 files changed, 74 insertions(+), 6 deletions(-) diff --git a/drivers/video/console_truetype.c b/drivers/video/console_truetype.c index fc2985ed92f..a42ae318fc8 100644 --- a/drivers/video/console_truetype.c +++ b/drivers/video/console_truetype.c @@ -295,6 +295,58 @@ static int console_truetype_move_rows(struct udevice *dev, uint rowdst, return 0; } +/** + * clear_from() - Clear characters on the display from given index onwards + * + * Erases all characters from the specified position index in the position + * history to the end of the position array (pos_count). This handles line + * wrapping by clearing to the end of lines and continuing on subsequent lines. + * + * @dev: Device to update + * @index: Starting index in priv->pos array to erase from + */ +static void clear_from(struct udevice *dev, int index) +{ + struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev); + struct console_tt_priv *priv = dev_get_priv(dev); + struct udevice *vid_dev = dev->parent; + struct video_priv *vid_priv = dev_get_uclass_priv(vid_dev); + struct pos_info *start_pos, *end_pos; + int xstart, xend; + int ystart, yend; + + assert(priv->pos_count && index && index < priv->pos_count); + + start_pos = &priv->pos[index]; + xstart = VID_TO_PIXEL(start_pos->xpos_frac); + ystart = start_pos->ypos; + + /* End position is the last character in the position array */ + end_pos = &priv->pos[priv->pos_count - 1]; + xend = VID_TO_PIXEL(end_pos->xpos_frac) + end_pos->width; + yend = end_pos->ypos; + + /* If on the same line, just erase from start to end position */ + if (ystart == yend) { + video_fill_part(vid_dev, xstart, ystart, xend, ystart + vc_priv->y_charsize, + vid_priv->colour_bg); + } else { + /* Different lines - erase to end of first line */ + video_fill_part(vid_dev, xstart, ystart, vid_priv->xsize, + ystart + vc_priv->y_charsize, vid_priv->colour_bg); + + /* Erase any complete lines in between */ + if (yend > ystart + vc_priv->y_charsize) { + video_fill_part(vid_dev, 0, ystart + vc_priv->y_charsize, + vid_priv->xsize, yend, vid_priv->colour_bg); + } + + /* Erase from start of final line to end of last character */ + video_fill_part(vid_dev, 0, yend, xend, yend + vc_priv->y_charsize, + vid_priv->colour_bg); + } +} + static int console_truetype_putc_xy(struct udevice *dev, uint x, uint y, int cp) { @@ -326,15 +378,19 @@ static int console_truetype_putc_xy(struct udevice *dev, uint x, uint y, * First out our current X position in fractional pixels. If we wrote * a character previously, use kerning to fine-tune the position of * this character */ + pos = priv->pos_ptr < priv->pos_count ? &priv->pos[priv->pos_ptr] : + NULL; xpos = frac(VID_TO_PIXEL((double)x)); kern = 0; if (vc_priv->last_ch) { - kern = stbtt_GetCodepointKernAdvance(font, vc_priv->last_ch, - cp); + int last_cp = vc_priv->last_ch; + + if (pos) + last_cp = pos->cp; + kern = stbtt_GetCodepointKernAdvance(font, last_cp, cp); if (_DEBUG) { console_printf_select_stderr(true, "kern %c (%02x)", - vc_priv->last_ch, - vc_priv->last_ch); + last_cp, last_cp); } xpos += met->scale * kern; } @@ -357,6 +413,18 @@ static int console_truetype_putc_xy(struct udevice *dev, uint x, uint y, /* Write the current cursor position into history */ if (priv->pos_ptr < POS_HISTORY_SIZE) { + bool erase = false; + + /* Check if we're overwriting a different character */ + if (pos && pos->cp != cp) { + erase = true; + /* Erase using the old character's position before updating */ + clear_from(dev, priv->pos_ptr); + + /* After erasing, we don't care about erased characters */ + priv->pos_count = priv->pos_ptr; + } + pos = &priv->pos[priv->pos_ptr]; pos->xpos_frac = vc_priv->xcur_frac; pos->ypos = vc_priv->ycur; diff --git a/test/dm/video.c b/test/dm/video.c index 3ec12956909..3395fd9f1b3 100644 --- a/test/dm/video.c +++ b/test/dm/video.c @@ -594,7 +594,7 @@ static int dm_test_video_truetype(struct unit_test_state *uts) ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con)); vidconsole_put_string(con, test_string); vidconsole_put_stringn(con, test_string, 30); - ut_asserteq(13055, video_compress_fb(uts, dev, false)); + ut_asserteq(13073, video_compress_fb(uts, dev, false)); ut_assertok(video_check_copy_fb(uts, dev)); return 0; @@ -648,7 +648,7 @@ static int dm_test_video_truetype_bs(struct unit_test_state *uts) ut_assertok(video_get_nologo(uts, &dev)); ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con)); vidconsole_put_string(con, test_string); - ut_asserteq(29223, video_compress_fb(uts, dev, false)); + ut_asserteq(29310, video_compress_fb(uts, dev, false)); ut_assertok(video_check_copy_fb(uts, dev)); return 0;