All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/2] font: Add font scaling feature to grub_font_draw_glyph()
@ 2022-05-31 10:44 Zhang Boyang
  2022-05-31 10:44 ` [PATCH 2/2] term/gfxterm: Preliminary HiDPI support Zhang Boyang
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Zhang Boyang @ 2022-05-31 10:44 UTC (permalink / raw)
  To: grub-devel; +Cc: Zhang Boyang

This patch adds an argument 'scale' to grub_font_draw_glyph(). If
scale > 1, then the function will scale the bitmap of the drawing glyph
on the fly, and draw the scaled glyph. The scaled bitmap is placed in a
local static buffer, so it will not affect the glyph or font itself.

Signed-off-by: Zhang Boyang <zhangboyang.id@gmail.com>
---
 grub-core/commands/videotest.c |  4 +--
 grub-core/font/font.c          | 54 ++++++++++++++++++++++++++++++----
 grub-core/gfxmenu/font.c       |  2 +-
 grub-core/term/gfxterm.c       |  2 +-
 include/grub/font.h            |  3 +-
 5 files changed, 55 insertions(+), 10 deletions(-)

diff --git a/grub-core/commands/videotest.c b/grub-core/commands/videotest.c
index ac145afc2..d95ee411d 100644
--- a/grub-core/commands/videotest.c
+++ b/grub-core/commands/videotest.c
@@ -87,7 +87,7 @@ grub_cmd_videotest (grub_command_t cmd __attribute__ ((unused)),
       return grub_error (GRUB_ERR_BAD_FONT, "no font loaded");
 
     glyph = grub_font_get_glyph (fixed, '*');
-    grub_font_draw_glyph (glyph, color, 200 ,0);
+    grub_font_draw_glyph (glyph, color, 200, 0, 1);
 
     color = grub_video_map_rgb (255, 255, 255);
 
@@ -148,7 +148,7 @@ grub_cmd_videotest (grub_command_t cmd __attribute__ ((unused)),
       {
 	color = grub_video_map_color (i);
 	palette[i] = color;
-	grub_font_draw_glyph (glyph, color, 16 + i * 16, 220);
+	grub_font_draw_glyph (glyph, color, 16 + i * 16, 220, 1);
       }
   }
 
diff --git a/grub-core/font/font.c b/grub-core/font/font.c
index 42189c325..ab74fddee 100644
--- a/grub-core/font/font.c
+++ b/grub-core/font/font.c
@@ -1568,9 +1568,12 @@ grub_font_construct_glyph (grub_font_t hinted_font,
    side location of the character.  */
 grub_err_t
 grub_font_draw_glyph (struct grub_font_glyph * glyph,
-		      grub_video_color_t color, int left_x, int baseline_y)
+		      grub_video_color_t color, int left_x, int baseline_y,
+		      int scale)
 {
   struct grub_video_bitmap glyph_bitmap;
+  static grub_uint8_t *buffer = NULL;
+  static grub_size_t max_buffer_size = 0;
 
   /* Don't try to draw empty glyphs (U+0020, etc.).  */
   if (glyph->width == 0 || glyph->height == 0)
@@ -1601,11 +1604,52 @@ grub_font_draw_glyph (struct grub_font_glyph * glyph,
 			  &glyph_bitmap.mode_info.fg_alpha);
   glyph_bitmap.data = glyph->bitmap;
 
-  int bitmap_left = left_x + glyph->offset_x;
-  int bitmap_bottom = baseline_y - glyph->offset_y;
-  int bitmap_top = bitmap_bottom - glyph->height;
+  /* Try to scale glyph bitmap */
+  grub_size_t new_buffer_size =
+    ((glyph->width * scale) * (glyph->height * scale) + 7) / 8;
+  if (scale > 1)
+    {
+      if (max_buffer_size < new_buffer_size)
+	{
+	  grub_uint8_t *new_buffer = grub_malloc(new_buffer_size);
+	  if (new_buffer)
+	    {
+	      grub_free(buffer);
+	      buffer = new_buffer;
+	      max_buffer_size = new_buffer_size;
+	    }
+	}
+      if (max_buffer_size < new_buffer_size)
+	{
+	  /* Unable to alloc buffer, fallback to no-scale */
+	  scale = 1;
+	}
+    }
+  if (scale > 1)
+    {
+      /* FIXME: Scale bitmap pixel by pixel is slow */
+      int i, j;
+      grub_memset(buffer, 0, new_buffer_size);
+      for (i = 0; i < glyph->height * scale; i++)
+	for (j = 0; j < glyph->width * scale; j++)
+	  {
+	    int n = (i / scale) * glyph->width + (j / scale);
+	    int m = i * (glyph->width * scale) + j;
+	    int pixel = (glyph->bitmap[n / 8] >> (7 - n % 8)) & 1;
+	    buffer[m / 8] |= pixel << (7 - m % 8);
+	  }
+      glyph_bitmap.mode_info.width = glyph->width * scale;
+      glyph_bitmap.mode_info.height = glyph->height * scale;
+      glyph_bitmap.mode_info.pitch = glyph->width * scale;
+      glyph_bitmap.data = buffer;
+    }
+
+  int bitmap_left = left_x + glyph->offset_x * scale;
+  int bitmap_bottom = baseline_y - glyph->offset_y * scale;
+  int bitmap_top = bitmap_bottom - glyph->height * scale;
 
   return grub_video_blit_bitmap (&glyph_bitmap, GRUB_VIDEO_BLIT_BLEND,
 				 bitmap_left, bitmap_top,
-				 0, 0, glyph->width, glyph->height);
+				 0, 0,
+				 glyph->width * scale, glyph->height * scale);
 }
diff --git a/grub-core/gfxmenu/font.c b/grub-core/gfxmenu/font.c
index 756c24f20..ed59ca954 100644
--- a/grub-core/gfxmenu/font.c
+++ b/grub-core/gfxmenu/font.c
@@ -67,7 +67,7 @@ grub_font_draw_string (const char *str, grub_font_t font,
 	  err = grub_errno;
 	  goto out;
 	}
-      err = grub_font_draw_glyph (glyph, color, x, baseline_y);
+      err = grub_font_draw_glyph (glyph, color, x, baseline_y, 1);
       if (err)
 	goto out;
       x += glyph->device_width;
diff --git a/grub-core/term/gfxterm.c b/grub-core/term/gfxterm.c
index 3c468f459..4512dee6f 100644
--- a/grub-core/term/gfxterm.c
+++ b/grub-core/term/gfxterm.c
@@ -656,7 +656,7 @@ paint_char (unsigned cx, unsigned cy)
   /* Render glyph to text layer.  */
   grub_video_set_active_render_target (text_layer);
   grub_video_fill_rect (bgcolor, x, y, width, height);
-  grub_font_draw_glyph (glyph, color, x, y + ascent);
+  grub_font_draw_glyph (glyph, color, x, y + ascent, 1);
   grub_video_set_active_render_target (render_target);
 
   /* Mark character to be drawn.  */
diff --git a/include/grub/font.h b/include/grub/font.h
index 708fa42ac..5d66ba523 100644
--- a/include/grub/font.h
+++ b/include/grub/font.h
@@ -141,7 +141,8 @@ struct grub_font_glyph *EXPORT_FUNC (grub_font_get_glyph_with_fallback) (grub_fo
 
 grub_err_t EXPORT_FUNC (grub_font_draw_glyph) (struct grub_font_glyph *glyph,
 					       grub_video_color_t color,
-					       int left_x, int baseline_y);
+					       int left_x, int baseline_y,
+					       int scale);
 
 int
 EXPORT_FUNC (grub_font_get_constructed_device_width) (grub_font_t hinted_font,
-- 
2.30.2



^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 2/2] term/gfxterm: Preliminary HiDPI support
  2022-05-31 10:44 [PATCH 1/2] font: Add font scaling feature to grub_font_draw_glyph() Zhang Boyang
@ 2022-05-31 10:44 ` Zhang Boyang
  2022-05-31 11:36 ` [PATCH 1/2] font: Add font scaling feature to grub_font_draw_glyph() Gerd Hoffmann
  2022-05-31 12:51 ` Vladimir 'phcoder' Serbinenko
  2 siblings, 0 replies; 6+ messages in thread
From: Zhang Boyang @ 2022-05-31 10:44 UTC (permalink / raw)
  To: grub-devel; +Cc: Zhang Boyang

Currently GRUB's default font is too small to see on a HiDPI monitor.
This patch adds preliminary HiDPI support to gfxterm. If default font
and a HiDPI monitor are both detected, it will scale the font size on
the fly.

Signed-off-by: Zhang Boyang <zhangboyang.id@gmail.com>
---
 grub-core/term/gfxterm.c | 55 +++++++++++++++++++++++++---------------
 1 file changed, 35 insertions(+), 20 deletions(-)

diff --git a/grub-core/term/gfxterm.c b/grub-core/term/gfxterm.c
index 4512dee6f..8c6bb8e83 100644
--- a/grub-core/term/gfxterm.c
+++ b/grub-core/term/gfxterm.c
@@ -82,6 +82,7 @@ struct grub_virtual_screen
 
   /* Font settings. */
   grub_font_t font;
+  unsigned int scale;
 
   /* Terminal color settings.  */
   grub_uint8_t standard_color_setting;
@@ -204,7 +205,7 @@ grub_virtual_screen_free (void)
 static grub_err_t
 grub_virtual_screen_setup (unsigned int x, unsigned int y,
                            unsigned int width, unsigned int height,
-			   grub_font_t font)
+			   grub_font_t font, unsigned int scale)
 {
   unsigned int i;
 
@@ -213,6 +214,7 @@ grub_virtual_screen_setup (unsigned int x, unsigned int y,
 
   /* Initialize with default data.  */
   virtual_screen.font = font;
+  virtual_screen.scale = scale;
   virtual_screen.width = width;
   virtual_screen.height = height;
   virtual_screen.offset_x = x;
@@ -220,9 +222,9 @@ grub_virtual_screen_setup (unsigned int x, unsigned int y,
   virtual_screen.normal_char_width =
     calculate_normal_character_width (virtual_screen.font);
   virtual_screen.normal_char_height =
-    grub_font_get_max_char_height (virtual_screen.font);
+    grub_font_get_max_char_height (virtual_screen.font) * virtual_screen.scale;
   if (virtual_screen.normal_char_height == 0)
-    virtual_screen.normal_char_height = 16;
+    virtual_screen.normal_char_height = 16 * virtual_screen.scale;
   virtual_screen.cursor_x = 0;
   virtual_screen.cursor_y = 0;
   virtual_screen.cursor_state = 1;
@@ -299,17 +301,29 @@ grub_gfxterm_set_window (struct grub_video_render_target *target,
 			 int double_repaint,
 			 grub_font_t font, int border_width)
 {
+  int scale;
+
   /* Clean up any prior instance.  */
   destroy_window ();
 
   /* Set the render target.  */
   render_target = target;
 
+  /* Decide font scale factor. */
+  scale = 1;
+  if (font->max_char_height == 16) /* FIXME: Better logic */
+    {
+      if (width > 3840 && height > 2160)
+	scale = 4;
+      else if (width > 1920 && height > 1080)
+	scale = 2;
+    }
+
   /* Create virtual screen.  */
-  if (grub_virtual_screen_setup (border_width, border_width,
-                                 width - 2 * border_width,
-                                 height - 2 * border_width,
-                                 font)
+  if (grub_virtual_screen_setup (border_width * scale, border_width * scale,
+                                 width - 2 * border_width * scale,
+                                 height - 2 * border_width * scale,
+                                 font, scale)
       != GRUB_ERR_NONE)
     {
       return grub_errno;
@@ -642,7 +656,7 @@ paint_char (unsigned cx, unsigned cy)
       grub_errno = GRUB_ERR_NONE;
       return;
     }
-  ascent = grub_font_get_ascent (virtual_screen.font);
+  ascent = grub_font_get_ascent (virtual_screen.font) * virtual_screen.scale;
 
   width = virtual_screen.normal_char_width * calculate_character_width(glyph);
   height = virtual_screen.normal_char_height;
@@ -656,7 +670,7 @@ paint_char (unsigned cx, unsigned cy)
   /* Render glyph to text layer.  */
   grub_video_set_active_render_target (text_layer);
   grub_video_fill_rect (bgcolor, x, y, width, height);
-  grub_font_draw_glyph (glyph, color, x, y + ascent, 1);
+  grub_font_draw_glyph (glyph, color, x, y + ascent, virtual_screen.scale);
   grub_video_set_active_render_target (render_target);
 
   /* Mark character to be drawn.  */
@@ -690,9 +704,9 @@ draw_cursor (int show)
     return;
 
   /* Ensure that cursor doesn't go outside of character box.  */
-  ascent = grub_font_get_ascent(virtual_screen.font);
-  if (ascent > virtual_screen.normal_char_height - 2)
-    ascent = virtual_screen.normal_char_height - 2;
+  ascent = grub_font_get_ascent(virtual_screen.font) * virtual_screen.scale;
+  if (ascent > virtual_screen.normal_char_height - 2 * virtual_screen.scale)
+    ascent = virtual_screen.normal_char_height - 2 * virtual_screen.scale;
 
   /* Determine cursor properties and position on text layer. */
   x = virtual_screen.cursor_x * virtual_screen.normal_char_width;
@@ -701,7 +715,7 @@ draw_cursor (int show)
   y = ((virtual_screen.cursor_y + virtual_screen.total_scroll)
        * virtual_screen.normal_char_height
        + ascent);
-  height = 2;
+  height = 2 * virtual_screen.scale;
 
   /* Render cursor to text layer.  */
   grub_video_set_active_render_target (text_layer);
@@ -957,18 +971,18 @@ calculate_normal_character_width (grub_font_t font)
 	width = glyph->device_width;
     }
   if (!width)
-    return 8;
+    return 8 * virtual_screen.scale;
 
-  return width;
+  return width * virtual_screen.scale;
 }
 
 static unsigned char
 calculate_character_width (struct grub_font_glyph *glyph)
 {
   if (! glyph || glyph->device_width == 0)
-    return 1;
+    return 1 * virtual_screen.scale;
 
-  return (glyph->device_width
+  return (glyph->device_width * virtual_screen.scale
           + (virtual_screen.normal_char_width - 1))
          / virtual_screen.normal_char_width;
 }
@@ -981,10 +995,11 @@ grub_gfxterm_getcharwidth (struct grub_term_output *term __attribute__ ((unused)
   dev_width = grub_font_get_constructed_device_width (virtual_screen.font, c);
 
   if (dev_width == 0)
-    return 1;
+    return 1 * virtual_screen.scale;
 
-  return (dev_width + (virtual_screen.normal_char_width - 1))
-    / virtual_screen.normal_char_width;
+  return (dev_width * virtual_screen.scale
+          + (virtual_screen.normal_char_width - 1))
+         / virtual_screen.normal_char_width;
 }
 
 static struct grub_term_coordinate
-- 
2.30.2



^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH 1/2] font: Add font scaling feature to grub_font_draw_glyph()
  2022-05-31 10:44 [PATCH 1/2] font: Add font scaling feature to grub_font_draw_glyph() Zhang Boyang
  2022-05-31 10:44 ` [PATCH 2/2] term/gfxterm: Preliminary HiDPI support Zhang Boyang
@ 2022-05-31 11:36 ` Gerd Hoffmann
  2022-05-31 12:17   ` Zhang Boyang
  2022-05-31 12:51 ` Vladimir 'phcoder' Serbinenko
  2 siblings, 1 reply; 6+ messages in thread
From: Gerd Hoffmann @ 2022-05-31 11:36 UTC (permalink / raw)
  To: The development of GNU GRUB; +Cc: Zhang Boyang

  Hi,

> +      /* FIXME: Scale bitmap pixel by pixel is slow */

So how about doing the scaling when loading the font,
so you have to do it only once?

take care,
  Gerd



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 1/2] font: Add font scaling feature to grub_font_draw_glyph()
  2022-05-31 11:36 ` [PATCH 1/2] font: Add font scaling feature to grub_font_draw_glyph() Gerd Hoffmann
@ 2022-05-31 12:17   ` Zhang Boyang
  0 siblings, 0 replies; 6+ messages in thread
From: Zhang Boyang @ 2022-05-31 12:17 UTC (permalink / raw)
  To: Gerd Hoffmann, The development of GNU GRUB

Hi,

In fact it is pretty "fast" because only the displayed glyphs are 
scaled. That's a very small subset of the whole font. It will be slower 
if we scale every glyph when loading the font. Also, the scale factor 
are hard to determine at font loading time, because the video driver may 
haven't been loaded at that time.

It is possible to cache the scaled glyphs, so only one scaling pass is 
needed for one glyph. But this will not change the computational 
complexity because the drawing algorithm itself is O(n) and scaling is 
also O(n). So I think we can optimize later if this simple-but-slow 
scaling code become performance bottleneck.


Best Regards,
Zhang Boyang


On 2022/5/31 19:36, Gerd Hoffmann wrote:
>    Hi,
> 
>> +      /* FIXME: Scale bitmap pixel by pixel is slow */
> 
> So how about doing the scaling when loading the font,
> so you have to do it only once?
> 
> take care,
>    Gerd
> 


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 1/2] font: Add font scaling feature to grub_font_draw_glyph()
  2022-05-31 10:44 [PATCH 1/2] font: Add font scaling feature to grub_font_draw_glyph() Zhang Boyang
  2022-05-31 10:44 ` [PATCH 2/2] term/gfxterm: Preliminary HiDPI support Zhang Boyang
  2022-05-31 11:36 ` [PATCH 1/2] font: Add font scaling feature to grub_font_draw_glyph() Gerd Hoffmann
@ 2022-05-31 12:51 ` Vladimir 'phcoder' Serbinenko
  2022-05-31 13:26   ` Zhang Boyang
  2 siblings, 1 reply; 6+ messages in thread
From: Vladimir 'phcoder' Serbinenko @ 2022-05-31 12:51 UTC (permalink / raw)
  To: The development of GNU GRUB

[-- Attachment #1: Type: text/plain, Size: 7080 bytes --]

We should avoid mallocs on every character as mallocs can be slow. Can we
instead save scaled versions and reuse them so that we need to do mallocs
only once per glyph instead of every time it's used?

Le mar. 31 mai 2022, 13:21, Zhang Boyang <zhangboyang.id@gmail.com> a
écrit :

> This patch adds an argument 'scale' to grub_font_draw_glyph(). If
> scale > 1, then the function will scale the bitmap of the drawing glyph
> on the fly, and draw the scaled glyph. The scaled bitmap is placed in a
> local static buffer, so it will not affect the glyph or font itself.
>
> Signed-off-by: Zhang Boyang <zhangboyang.id@gmail.com>
> ---
>  grub-core/commands/videotest.c |  4 +--
>  grub-core/font/font.c          | 54 ++++++++++++++++++++++++++++++----
>  grub-core/gfxmenu/font.c       |  2 +-
>  grub-core/term/gfxterm.c       |  2 +-
>  include/grub/font.h            |  3 +-
>  5 files changed, 55 insertions(+), 10 deletions(-)
>
> diff --git a/grub-core/commands/videotest.c
> b/grub-core/commands/videotest.c
> index ac145afc2..d95ee411d 100644
> --- a/grub-core/commands/videotest.c
> +++ b/grub-core/commands/videotest.c
> @@ -87,7 +87,7 @@ grub_cmd_videotest (grub_command_t cmd __attribute__
> ((unused)),
>        return grub_error (GRUB_ERR_BAD_FONT, "no font loaded");
>
>      glyph = grub_font_get_glyph (fixed, '*');
> -    grub_font_draw_glyph (glyph, color, 200 ,0);
> +    grub_font_draw_glyph (glyph, color, 200, 0, 1);
>
>      color = grub_video_map_rgb (255, 255, 255);
>
> @@ -148,7 +148,7 @@ grub_cmd_videotest (grub_command_t cmd __attribute__
> ((unused)),
>        {
>         color = grub_video_map_color (i);
>         palette[i] = color;
> -       grub_font_draw_glyph (glyph, color, 16 + i * 16, 220);
> +       grub_font_draw_glyph (glyph, color, 16 + i * 16, 220, 1);
>        }
>    }
>
> diff --git a/grub-core/font/font.c b/grub-core/font/font.c
> index 42189c325..ab74fddee 100644
> --- a/grub-core/font/font.c
> +++ b/grub-core/font/font.c
> @@ -1568,9 +1568,12 @@ grub_font_construct_glyph (grub_font_t hinted_font,
>     side location of the character.  */
>  grub_err_t
>  grub_font_draw_glyph (struct grub_font_glyph * glyph,
> -                     grub_video_color_t color, int left_x, int baseline_y)
> +                     grub_video_color_t color, int left_x, int baseline_y,
> +                     int scale)
>  {
>    struct grub_video_bitmap glyph_bitmap;
> +  static grub_uint8_t *buffer = NULL;
> +  static grub_size_t max_buffer_size = 0;
>
>    /* Don't try to draw empty glyphs (U+0020, etc.).  */
>    if (glyph->width == 0 || glyph->height == 0)
> @@ -1601,11 +1604,52 @@ grub_font_draw_glyph (struct grub_font_glyph *
> glyph,
>                           &glyph_bitmap.mode_info.fg_alpha);
>    glyph_bitmap.data = glyph->bitmap;
>
> -  int bitmap_left = left_x + glyph->offset_x;
> -  int bitmap_bottom = baseline_y - glyph->offset_y;
> -  int bitmap_top = bitmap_bottom - glyph->height;
> +  /* Try to scale glyph bitmap */
> +  grub_size_t new_buffer_size =
> +    ((glyph->width * scale) * (glyph->height * scale) + 7) / 8;
> +  if (scale > 1)
> +    {
> +      if (max_buffer_size < new_buffer_size)
> +       {
> +         grub_uint8_t *new_buffer = grub_malloc(new_buffer_size);
> +         if (new_buffer)
> +           {
> +             grub_free(buffer);
> +             buffer = new_buffer;
> +             max_buffer_size = new_buffer_size;
> +           }
> +       }
> +      if (max_buffer_size < new_buffer_size)
> +       {
> +         /* Unable to alloc buffer, fallback to no-scale */
> +         scale = 1;
> +       }
> +    }
> +  if (scale > 1)
> +    {
> +      /* FIXME: Scale bitmap pixel by pixel is slow */
> +      int i, j;
> +      grub_memset(buffer, 0, new_buffer_size);
> +      for (i = 0; i < glyph->height * scale; i++)
> +       for (j = 0; j < glyph->width * scale; j++)
> +         {
> +           int n = (i / scale) * glyph->width + (j / scale);
> +           int m = i * (glyph->width * scale) + j;
> +           int pixel = (glyph->bitmap[n / 8] >> (7 - n % 8)) & 1;
> +           buffer[m / 8] |= pixel << (7 - m % 8);
> +         }
> +      glyph_bitmap.mode_info.width = glyph->width * scale;
> +      glyph_bitmap.mode_info.height = glyph->height * scale;
> +      glyph_bitmap.mode_info.pitch = glyph->width * scale;
> +      glyph_bitmap.data = buffer;
> +    }
> +
> +  int bitmap_left = left_x + glyph->offset_x * scale;
> +  int bitmap_bottom = baseline_y - glyph->offset_y * scale;
> +  int bitmap_top = bitmap_bottom - glyph->height * scale;
>
>    return grub_video_blit_bitmap (&glyph_bitmap, GRUB_VIDEO_BLIT_BLEND,
>                                  bitmap_left, bitmap_top,
> -                                0, 0, glyph->width, glyph->height);
> +                                0, 0,
> +                                glyph->width * scale, glyph->height *
> scale);
>  }
> diff --git a/grub-core/gfxmenu/font.c b/grub-core/gfxmenu/font.c
> index 756c24f20..ed59ca954 100644
> --- a/grub-core/gfxmenu/font.c
> +++ b/grub-core/gfxmenu/font.c
> @@ -67,7 +67,7 @@ grub_font_draw_string (const char *str, grub_font_t font,
>           err = grub_errno;
>           goto out;
>         }
> -      err = grub_font_draw_glyph (glyph, color, x, baseline_y);
> +      err = grub_font_draw_glyph (glyph, color, x, baseline_y, 1);
>        if (err)
>         goto out;
>        x += glyph->device_width;
> diff --git a/grub-core/term/gfxterm.c b/grub-core/term/gfxterm.c
> index 3c468f459..4512dee6f 100644
> --- a/grub-core/term/gfxterm.c
> +++ b/grub-core/term/gfxterm.c
> @@ -656,7 +656,7 @@ paint_char (unsigned cx, unsigned cy)
>    /* Render glyph to text layer.  */
>    grub_video_set_active_render_target (text_layer);
>    grub_video_fill_rect (bgcolor, x, y, width, height);
> -  grub_font_draw_glyph (glyph, color, x, y + ascent);
> +  grub_font_draw_glyph (glyph, color, x, y + ascent, 1);
>    grub_video_set_active_render_target (render_target);
>
>    /* Mark character to be drawn.  */
> diff --git a/include/grub/font.h b/include/grub/font.h
> index 708fa42ac..5d66ba523 100644
> --- a/include/grub/font.h
> +++ b/include/grub/font.h
> @@ -141,7 +141,8 @@ struct grub_font_glyph *EXPORT_FUNC
> (grub_font_get_glyph_with_fallback) (grub_fo
>
>  grub_err_t EXPORT_FUNC (grub_font_draw_glyph) (struct grub_font_glyph
> *glyph,
>                                                grub_video_color_t color,
> -                                              int left_x, int baseline_y);
> +                                              int left_x, int baseline_y,
> +                                              int scale);
>
>  int
>  EXPORT_FUNC (grub_font_get_constructed_device_width) (grub_font_t
> hinted_font,
> --
> 2.30.2
>
>
> _______________________________________________
> Grub-devel mailing list
> Grub-devel@gnu.org
> https://lists.gnu.org/mailman/listinfo/grub-devel
>

[-- Attachment #2: Type: text/html, Size: 8562 bytes --]

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 1/2] font: Add font scaling feature to grub_font_draw_glyph()
  2022-05-31 12:51 ` Vladimir 'phcoder' Serbinenko
@ 2022-05-31 13:26   ` Zhang Boyang
  0 siblings, 0 replies; 6+ messages in thread
From: Zhang Boyang @ 2022-05-31 13:26 UTC (permalink / raw)
  To: The development of GNU GRUB, Vladimir 'phcoder' Serbinenko

Hi,

All scaled glyphs share one buffer, and the static local pointer 
'buffer' points to that shared buffer. So the malloc() only occurs when 
current glyph size is bigger than all previous glyphs. Once a new buffer 
is allocated, future glyphs smaller than current will not require a 
malloc().

Best Regards,
Zhang Boyang


On 2022/5/31 20:51, Vladimir 'phcoder' Serbinenko wrote:
> We should avoid mallocs on every character as mallocs can be slow. Can we
> instead save scaled versions and reuse them so that we need to do mallocs
> only once per glyph instead of every time it's used?
> 
> Le mar. 31 mai 2022, 13:21, Zhang Boyang <zhangboyang.id@gmail.com> a
> écrit :
> 
>> This patch adds an argument 'scale' to grub_font_draw_glyph(). If
>> scale > 1, then the function will scale the bitmap of the drawing glyph
>> on the fly, and draw the scaled glyph. The scaled bitmap is placed in a
>> local static buffer, so it will not affect the glyph or font itself.
>>
>> Signed-off-by: Zhang Boyang <zhangboyang.id@gmail.com>
>> ---
>>   grub-core/commands/videotest.c |  4 +--
>>   grub-core/font/font.c          | 54 ++++++++++++++++++++++++++++++----
>>   grub-core/gfxmenu/font.c       |  2 +-
>>   grub-core/term/gfxterm.c       |  2 +-
>>   include/grub/font.h            |  3 +-
>>   5 files changed, 55 insertions(+), 10 deletions(-)
>>
>> diff --git a/grub-core/commands/videotest.c
>> b/grub-core/commands/videotest.c
>> index ac145afc2..d95ee411d 100644
>> --- a/grub-core/commands/videotest.c
>> +++ b/grub-core/commands/videotest.c
>> @@ -87,7 +87,7 @@ grub_cmd_videotest (grub_command_t cmd __attribute__
>> ((unused)),
>>         return grub_error (GRUB_ERR_BAD_FONT, "no font loaded");
>>
>>       glyph = grub_font_get_glyph (fixed, '*');
>> -    grub_font_draw_glyph (glyph, color, 200 ,0);
>> +    grub_font_draw_glyph (glyph, color, 200, 0, 1);
>>
>>       color = grub_video_map_rgb (255, 255, 255);
>>
>> @@ -148,7 +148,7 @@ grub_cmd_videotest (grub_command_t cmd __attribute__
>> ((unused)),
>>         {
>>          color = grub_video_map_color (i);
>>          palette[i] = color;
>> -       grub_font_draw_glyph (glyph, color, 16 + i * 16, 220);
>> +       grub_font_draw_glyph (glyph, color, 16 + i * 16, 220, 1);
>>         }
>>     }
>>
>> diff --git a/grub-core/font/font.c b/grub-core/font/font.c
>> index 42189c325..ab74fddee 100644
>> --- a/grub-core/font/font.c
>> +++ b/grub-core/font/font.c
>> @@ -1568,9 +1568,12 @@ grub_font_construct_glyph (grub_font_t hinted_font,
>>      side location of the character.  */
>>   grub_err_t
>>   grub_font_draw_glyph (struct grub_font_glyph * glyph,
>> -                     grub_video_color_t color, int left_x, int baseline_y)
>> +                     grub_video_color_t color, int left_x, int baseline_y,
>> +                     int scale)
>>   {
>>     struct grub_video_bitmap glyph_bitmap;
>> +  static grub_uint8_t *buffer = NULL;
>> +  static grub_size_t max_buffer_size = 0;
>>
>>     /* Don't try to draw empty glyphs (U+0020, etc.).  */
>>     if (glyph->width == 0 || glyph->height == 0)
>> @@ -1601,11 +1604,52 @@ grub_font_draw_glyph (struct grub_font_glyph *
>> glyph,
>>                            &glyph_bitmap.mode_info.fg_alpha);
>>     glyph_bitmap.data = glyph->bitmap;
>>
>> -  int bitmap_left = left_x + glyph->offset_x;
>> -  int bitmap_bottom = baseline_y - glyph->offset_y;
>> -  int bitmap_top = bitmap_bottom - glyph->height;
>> +  /* Try to scale glyph bitmap */
>> +  grub_size_t new_buffer_size =
>> +    ((glyph->width * scale) * (glyph->height * scale) + 7) / 8;
>> +  if (scale > 1)
>> +    {
>> +      if (max_buffer_size < new_buffer_size)
>> +       {
>> +         grub_uint8_t *new_buffer = grub_malloc(new_buffer_size);
>> +         if (new_buffer)
>> +           {
>> +             grub_free(buffer);
>> +             buffer = new_buffer;
>> +             max_buffer_size = new_buffer_size;
>> +           }
>> +       }
>> +      if (max_buffer_size < new_buffer_size)
>> +       {
>> +         /* Unable to alloc buffer, fallback to no-scale */
>> +         scale = 1;
>> +       }
>> +    }
>> +  if (scale > 1)
>> +    {
>> +      /* FIXME: Scale bitmap pixel by pixel is slow */
>> +      int i, j;
>> +      grub_memset(buffer, 0, new_buffer_size);
>> +      for (i = 0; i < glyph->height * scale; i++)
>> +       for (j = 0; j < glyph->width * scale; j++)
>> +         {
>> +           int n = (i / scale) * glyph->width + (j / scale);
>> +           int m = i * (glyph->width * scale) + j;
>> +           int pixel = (glyph->bitmap[n / 8] >> (7 - n % 8)) & 1;
>> +           buffer[m / 8] |= pixel << (7 - m % 8);
>> +         }
>> +      glyph_bitmap.mode_info.width = glyph->width * scale;
>> +      glyph_bitmap.mode_info.height = glyph->height * scale;
>> +      glyph_bitmap.mode_info.pitch = glyph->width * scale;
>> +      glyph_bitmap.data = buffer;
>> +    }
>> +
>> +  int bitmap_left = left_x + glyph->offset_x * scale;
>> +  int bitmap_bottom = baseline_y - glyph->offset_y * scale;
>> +  int bitmap_top = bitmap_bottom - glyph->height * scale;
>>
>>     return grub_video_blit_bitmap (&glyph_bitmap, GRUB_VIDEO_BLIT_BLEND,
>>                                   bitmap_left, bitmap_top,
>> -                                0, 0, glyph->width, glyph->height);
>> +                                0, 0,
>> +                                glyph->width * scale, glyph->height *
>> scale);
>>   }
>> diff --git a/grub-core/gfxmenu/font.c b/grub-core/gfxmenu/font.c
>> index 756c24f20..ed59ca954 100644
>> --- a/grub-core/gfxmenu/font.c
>> +++ b/grub-core/gfxmenu/font.c
>> @@ -67,7 +67,7 @@ grub_font_draw_string (const char *str, grub_font_t font,
>>            err = grub_errno;
>>            goto out;
>>          }
>> -      err = grub_font_draw_glyph (glyph, color, x, baseline_y);
>> +      err = grub_font_draw_glyph (glyph, color, x, baseline_y, 1);
>>         if (err)
>>          goto out;
>>         x += glyph->device_width;
>> diff --git a/grub-core/term/gfxterm.c b/grub-core/term/gfxterm.c
>> index 3c468f459..4512dee6f 100644
>> --- a/grub-core/term/gfxterm.c
>> +++ b/grub-core/term/gfxterm.c
>> @@ -656,7 +656,7 @@ paint_char (unsigned cx, unsigned cy)
>>     /* Render glyph to text layer.  */
>>     grub_video_set_active_render_target (text_layer);
>>     grub_video_fill_rect (bgcolor, x, y, width, height);
>> -  grub_font_draw_glyph (glyph, color, x, y + ascent);
>> +  grub_font_draw_glyph (glyph, color, x, y + ascent, 1);
>>     grub_video_set_active_render_target (render_target);
>>
>>     /* Mark character to be drawn.  */
>> diff --git a/include/grub/font.h b/include/grub/font.h
>> index 708fa42ac..5d66ba523 100644
>> --- a/include/grub/font.h
>> +++ b/include/grub/font.h
>> @@ -141,7 +141,8 @@ struct grub_font_glyph *EXPORT_FUNC
>> (grub_font_get_glyph_with_fallback) (grub_fo
>>
>>   grub_err_t EXPORT_FUNC (grub_font_draw_glyph) (struct grub_font_glyph
>> *glyph,
>>                                                 grub_video_color_t color,
>> -                                              int left_x, int baseline_y);
>> +                                              int left_x, int baseline_y,
>> +                                              int scale);
>>
>>   int
>>   EXPORT_FUNC (grub_font_get_constructed_device_width) (grub_font_t
>> hinted_font,
>> --
>> 2.30.2
>>
>>
>> _______________________________________________
>> Grub-devel mailing list
>> Grub-devel@gnu.org
>> https://lists.gnu.org/mailman/listinfo/grub-devel
>>
> 
> 
> _______________________________________________
> Grub-devel mailing list
> Grub-devel@gnu.org
> https://lists.gnu.org/mailman/listinfo/grub-devel


^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2022-05-31 13:26 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-05-31 10:44 [PATCH 1/2] font: Add font scaling feature to grub_font_draw_glyph() Zhang Boyang
2022-05-31 10:44 ` [PATCH 2/2] term/gfxterm: Preliminary HiDPI support Zhang Boyang
2022-05-31 11:36 ` [PATCH 1/2] font: Add font scaling feature to grub_font_draw_glyph() Gerd Hoffmann
2022-05-31 12:17   ` Zhang Boyang
2022-05-31 12:51 ` Vladimir 'phcoder' Serbinenko
2022-05-31 13:26   ` Zhang Boyang

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.