[Concept,12/42] video: Allow selection of bitmap fonts in truetype

Message ID 20250919201507.4024144-13-sjg@u-boot.org
State New
Headers
Series video: Support a cursor more generally |

Commit Message

Simon Glass Sept. 19, 2025, 8:14 p.m. UTC
  From: Simon Glass <sjg@chromium.org>

It is sometimes useful to use a bitmap font for the console even when
truetype fonts are available. As a starting point, pull in the
font table and provide information about font sizes. Allow selection of
a bitmap font by name, as well as listing available bitmap fonts.

Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <sjg@chromium.org>
---

 drivers/video/console_truetype.c | 64 ++++++++++++++++++++++++++++++--
 test/cmd/font.c                  |  8 +++-
 2 files changed, 67 insertions(+), 5 deletions(-)
  

Patch

diff --git a/drivers/video/console_truetype.c b/drivers/video/console_truetype.c
index a17519282fc..eb9e7f55d68 100644
--- a/drivers/video/console_truetype.c
+++ b/drivers/video/console_truetype.c
@@ -12,6 +12,7 @@ 
 #include <spl.h>
 #include <video.h>
 #include <video_console.h>
+#include <video_font.h>
 
 /* Functions needed by stb_truetype.h */
 static int tt_floor(double val)
@@ -169,6 +170,7 @@  struct console_tt_metrics {
  *		last character. We record enough characters to go back to the
  *		start of the current command line.
  * @pos_ptr:	Current position in the position history
+ * @cur_fontdata:	Current fixed font data (NULL if using TrueType)
  */
 struct console_tt_priv {
 	struct console_tt_metrics *cur_met;
@@ -176,6 +178,7 @@  struct console_tt_priv {
 	int num_metrics;
 	struct pos_info pos[POS_HISTORY_SIZE];
 	int pos_ptr;
+	struct video_fontdata *cur_fontdata;
 };
 
 /**
@@ -595,9 +598,19 @@  int console_truetype_get_font(struct udevice *dev, int seq,
 			      struct vidfont_info *info)
 {
 	struct font_info *tab;
+	struct video_fontdata *fontdata;
 	int i;
 
-	for (i = 0, tab = font_table; tab->begin; tab++, i++) {
+	/* List fixed fonts first */
+	for (i = 0, fontdata = fonts; fontdata->name; fontdata++, i++) {
+		if (i == seq) {
+			info->name = fontdata->name;
+			return 0;
+		}
+	}
+
+	/* then list TrueType fonts */
+	for (tab = font_table; tab->begin; tab++, i++) {
 		if (i == seq && font_valid(tab)) {
 			info->name = tab->name;
 			return 0;
@@ -671,6 +684,27 @@  static struct console_tt_metrics *find_metrics(struct udevice *dev,
 	return NULL;
 }
 
+/**
+ * set_bitmap_font() - Set up console to use a fixed font
+ *
+ * @dev:	Console device
+ * @fontdata:	Fixed font data to use
+ * Return: 0 if OK, -ve on error
+ */
+static void set_bitmap_font(struct udevice *dev,
+			    struct video_fontdata *fontdata)
+{
+	struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev);
+	struct console_tt_priv *priv = dev_get_priv(dev);
+
+	priv->cur_fontdata = fontdata;
+	priv->cur_met = NULL;
+
+	vidconsole_set_bitmap_font(dev, fontdata);
+
+	vc_priv->tab_width_frac = VID_TO_POS(fontdata->width) * 8 / 2;
+}
+
 static void select_metrics(struct udevice *dev, struct console_tt_metrics *met)
 {
 	struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev);
@@ -734,9 +768,24 @@  static int get_metrics(struct udevice *dev, const char *name, uint size,
 static int truetype_select_font(struct udevice *dev, const char *name,
 				uint size)
 {
+	struct console_tt_priv *priv = dev_get_priv(dev);
 	struct console_tt_metrics *met;
+	struct video_fontdata *fontdata;
 	int ret;
 
+	/* Check if this is a request for a fixed font */
+	if (name) {
+		for (fontdata = fonts; fontdata->name; fontdata++) {
+			if (!strcmp(name, fontdata->name)) {
+				/* Switch to fixed-font mode */
+				set_bitmap_font(dev, fontdata);
+				return 0;
+			}
+		}
+	}
+
+	/* Continue with TrueType font selection */
+	priv->cur_fontdata = NULL;
 	ret = get_metrics(dev, name, size, &met);
 	if (ret)
 		return log_msg_ret("sel", ret);
@@ -1036,11 +1085,18 @@  static int truetype_set_cursor_visible(struct udevice *dev, bool visible,
 const char *console_truetype_get_font_size(struct udevice *dev, uint *sizep)
 {
 	struct console_tt_priv *priv = dev_get_priv(dev);
-	struct console_tt_metrics *met = priv->cur_met;
 
-	*sizep = met->font_size;
+	if (priv->cur_fontdata) {
+		/* Using fixed font */
+		*sizep = priv->cur_fontdata->height;
+		return priv->cur_fontdata->name;
+	} else {
+		/* Using TrueType font */
+		struct console_tt_metrics *met = priv->cur_met;
 
-	return met->font_name;
+		*sizep = met->font_size;
+		return met->font_name;
+	}
 }
 
 static int console_truetype_probe(struct udevice *dev)
diff --git a/test/cmd/font.c b/test/cmd/font.c
index 7ae648d7395..b2610ddef8d 100644
--- a/test/cmd/font.c
+++ b/test/cmd/font.c
@@ -26,6 +26,10 @@  static int font_test_base(struct unit_test_state *uts)
 	ut_assertok(uclass_first_device_err(UCLASS_VIDEO_CONSOLE, &dev));
 
 	ut_assertok(run_command("font list", 0));
+	if (IS_ENABLED(CONFIG_VIDEO_FONT_8X16))
+		ut_assert_nextline("8x16");
+	if (IS_ENABLED(CONFIG_VIDEO_FONT_SUN12X22))
+		ut_assert_nextline("12x22");
 	if (IS_ENABLED(CONFIG_CONSOLE_TRUETYPE_NIMBUS))
 		ut_assert_nextline("nimbus_sans_l_regular");
 	if (IS_ENABLED(CONFIG_CONSOLE_TRUETYPE_ANKACODER))
@@ -37,8 +41,10 @@  static int font_test_base(struct unit_test_state *uts)
 	ut_assertok(vidconsole_get_font_size(dev, &name, &size));
 	if (IS_ENABLED(CONFIG_CONSOLE_TRUETYPE_ANKACODER))
 		ut_asserteq_str("ankacoder_c75_r", name);
-	else
+	else if (IS_ENABLED(CONFIG_CONSOLE_TRUETYPE_NIMBUS))
 		ut_asserteq_str("nimbus_sans_l_regular", name);
+	else
+		ut_asserteq_str("8x16", name);
 	ut_asserteq(CONFIG_CONSOLE_TRUETYPE_SIZE, size);
 
 	if (!IS_ENABLED(CONFIG_CONSOLE_TRUETYPE_CANTORAONE))