grub-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH 1/2] font: Add font scaling feature to grub_font_draw_glyph()


From: Zhang Boyang
Subject: Re: [PATCH 1/2] font: Add font scaling feature to grub_font_draw_glyph()
Date: Tue, 31 May 2022 21:26:00 +0800
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Thunderbird/91.9.1

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



reply via email to

[Prev in Thread] Current Thread [Next in Thread]