grub-devel
[Top][All Lists]
Advanced

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

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


From: Zhang Boyang
Subject: [PATCH 1/2] font: Add font scaling feature to grub_font_draw_glyph()
Date: Tue, 31 May 2022 18:44:49 +0800

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




reply via email to

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