video: truetype: Support newlines in the measured string
authorSimon Glass <sjg@chromium.org>
Tue, 1 Apr 2025 17:29:38 +0000 (06:29 +1300)
committerTom Rini <trini@konsulko.com>
Fri, 2 May 2025 19:40:25 +0000 (13:40 -0600)
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>
drivers/video/console_truetype.c
include/video_console.h
test/dm/video.c

index 39d77ad..6eca5d7 100644 (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);
index ee9ce3c..a0ee9ab 100644 (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)
index d3fd74a..a3f3b04 100644 (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;
 }