All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/5] Font fixes and preliminary HiDPI support
@ 2022-12-05 11:29 Zhang Boyang
  2022-12-05 11:29 ` [PATCH 1/5] font: Check return value of grub_malloc() in ascii_glyph_lookup() Zhang Boyang
                   ` (4 more replies)
  0 siblings, 5 replies; 10+ messages in thread
From: Zhang Boyang @ 2022-12-05 11:29 UTC (permalink / raw)
  To: grub-devel

Hi,

PATCH 1-3 are additional fixes to font code.

PATCH 4-5 are the refactored and rebased version of HiDPI patches. They
add preliminary HiDPI support for gfxterm. There is no HiDPI support for
gfxmenu yet.

Best Regards,
Zhang Boyang




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

* [PATCH 1/5] font: Check return value of grub_malloc() in ascii_glyph_lookup()
  2022-12-05 11:29 [PATCH 0/5] Font fixes and preliminary HiDPI support Zhang Boyang
@ 2022-12-05 11:29 ` Zhang Boyang
  2022-12-13 17:16   ` Daniel Kiper
  2022-12-05 11:29 ` [PATCH 2/5] font: Assign null_font to unknown_glyph Zhang Boyang
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 10+ messages in thread
From: Zhang Boyang @ 2022-12-05 11:29 UTC (permalink / raw)
  To: grub-devel; +Cc: Zhang Boyang

There is a problem in ascii_glyph_lookup(). It doesn't check the return
value of grub_malloc(). If memory can't be allocated, then NULL pointer
will be written to.

This patch fixes the problem by fallbacking to unknown_glyph in case of
grub_malloc() returns NULL.

Signed-off-by: Zhang Boyang <zhangboyang.id@gmail.com>
---
 grub-core/font/font.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/grub-core/font/font.c b/grub-core/font/font.c
index 3821937e6..19a47f873 100644
--- a/grub-core/font/font.c
+++ b/grub-core/font/font.c
@@ -131,6 +131,11 @@ ascii_glyph_lookup (grub_uint32_t code)
 	{
 	  ascii_font_glyph[current] =
 	    grub_malloc (sizeof (struct grub_font_glyph) + ASCII_BITMAP_SIZE);
+	  if (ascii_font_glyph[current] == NULL)
+	    {
+	      ascii_font_glyph[current] = unknown_glyph;
+	      continue;
+	    }
 
 	  ascii_font_glyph[current]->width = 8;
 	  ascii_font_glyph[current]->height = 16;
-- 
2.30.2



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

* [PATCH 2/5] font: Assign null_font to unknown_glyph
  2022-12-05 11:29 [PATCH 0/5] Font fixes and preliminary HiDPI support Zhang Boyang
  2022-12-05 11:29 ` [PATCH 1/5] font: Check return value of grub_malloc() in ascii_glyph_lookup() Zhang Boyang
@ 2022-12-05 11:29 ` Zhang Boyang
  2022-12-13 17:17   ` Daniel Kiper
  2022-12-05 11:29 ` [PATCH 3/5] font: Reject fonts with negative max_char_width or max_char_height Zhang Boyang
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 10+ messages in thread
From: Zhang Boyang @ 2022-12-05 11:29 UTC (permalink / raw)
  To: grub-devel; +Cc: Zhang Boyang

Like glyphs in ascii_font_glyph[], assign null_font to
unknown_glyph->font in order to prevent grub_font_get_*() from
dereferencing NULL pointer.

Signed-off-by: Zhang Boyang <zhangboyang.id@gmail.com>
---
 grub-core/font/font.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/grub-core/font/font.c b/grub-core/font/font.c
index 19a47f873..674043d0d 100644
--- a/grub-core/font/font.c
+++ b/grub-core/font/font.c
@@ -177,6 +177,7 @@ grub_font_loader_init (void)
   unknown_glyph->offset_x = 0;
   unknown_glyph->offset_y = -3;
   unknown_glyph->device_width = 8;
+  unknown_glyph->font = &null_font;
   grub_memcpy (unknown_glyph->bitmap,
 	       unknown_glyph_bitmap, sizeof (unknown_glyph_bitmap));
 
-- 
2.30.2



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

* [PATCH 3/5] font: Reject fonts with negative max_char_width or max_char_height
  2022-12-05 11:29 [PATCH 0/5] Font fixes and preliminary HiDPI support Zhang Boyang
  2022-12-05 11:29 ` [PATCH 1/5] font: Check return value of grub_malloc() in ascii_glyph_lookup() Zhang Boyang
  2022-12-05 11:29 ` [PATCH 2/5] font: Assign null_font to unknown_glyph Zhang Boyang
@ 2022-12-05 11:29 ` Zhang Boyang
  2022-12-13 17:17   ` Daniel Kiper
  2022-12-05 11:29 ` [PATCH 4/5] font: Add font scaling feature to grub_font_draw_glyph() Zhang Boyang
  2022-12-05 11:29 ` [PATCH 5/5] term/gfxterm: Preliminary HiDPI support Zhang Boyang
  4 siblings, 1 reply; 10+ messages in thread
From: Zhang Boyang @ 2022-12-05 11:29 UTC (permalink / raw)
  To: grub-devel; +Cc: Zhang Boyang

If max_char_width or max_char_height is negative, bad values might be
propagated by grub_font_get_max_char_width() or
grub_font_get_max_char_height(). Prevent this from happening.

Signed-off-by: Zhang Boyang <zhangboyang.id@gmail.com>
---
 grub-core/font/font.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/grub-core/font/font.c b/grub-core/font/font.c
index 674043d0d..24adcb35a 100644
--- a/grub-core/font/font.c
+++ b/grub-core/font/font.c
@@ -644,8 +644,8 @@ grub_font_load (const char *filename)
 	       font->max_char_width, font->max_char_height, font->num_chars);
 #endif
 
-  if (font->max_char_width == 0
-      || font->max_char_height == 0
+  if (font->max_char_width <= 0
+      || font->max_char_height <= 0
       || font->num_chars == 0
       || font->char_index == 0 || font->ascent == 0 || font->descent == 0)
     {
-- 
2.30.2



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

* [PATCH 4/5] font: Add font scaling feature to grub_font_draw_glyph()
  2022-12-05 11:29 [PATCH 0/5] Font fixes and preliminary HiDPI support Zhang Boyang
                   ` (2 preceding siblings ...)
  2022-12-05 11:29 ` [PATCH 3/5] font: Reject fonts with negative max_char_width or max_char_height Zhang Boyang
@ 2022-12-05 11:29 ` Zhang Boyang
  2022-12-05 11:42   ` Zhang Boyang
  2022-12-05 11:29 ` [PATCH 5/5] term/gfxterm: Preliminary HiDPI support Zhang Boyang
  4 siblings, 1 reply; 10+ messages in thread
From: Zhang Boyang @ 2022-12-05 11:29 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 create a new scaled bitmap of the
drawing glyph, and draws the scaled glyph. The scaled bitmap is cached
in the glyph itself, so it can be reused if same glyph is used many
times.

This patch also adds a new metadata entry named MAXS to font files,
limiting the maximum acceptable scale factor at runtime for a specific
font. Currently MAXS is set to 8, which is sufficient for 16K monitors.

Signed-off-by: Zhang Boyang <zhangboyang.id@gmail.com>
---
 grub-core/commands/videotest.c |  4 +-
 grub-core/font/font.c          | 91 +++++++++++++++++++++++++++++++---
 grub-core/gfxmenu/font.c       |  2 +-
 grub-core/term/gfxterm.c       |  2 +-
 include/grub/font.h            |  9 +++-
 5 files changed, 97 insertions(+), 11 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 24adcb35a..536cbde71 100644
--- a/grub-core/font/font.c
+++ b/grub-core/font/font.c
@@ -142,6 +142,8 @@ ascii_glyph_lookup (grub_uint32_t code)
 	  ascii_font_glyph[current]->offset_x = 0;
 	  ascii_font_glyph[current]->offset_y = -2;
 	  ascii_font_glyph[current]->device_width = 8;
+	  ascii_font_glyph[current]->scaled_bitmap = NULL;
+	  ascii_font_glyph[current]->scale = 0;
 	  ascii_font_glyph[current]->font = &null_font;
 
 	  grub_memcpy (ascii_font_glyph[current]->bitmap,
@@ -177,6 +179,8 @@ grub_font_loader_init (void)
   unknown_glyph->offset_x = 0;
   unknown_glyph->offset_y = -3;
   unknown_glyph->device_width = 8;
+  unknown_glyph->scaled_bitmap = NULL;
+  unknown_glyph->scale = 0;
   unknown_glyph->font = &null_font;
   grub_memcpy (unknown_glyph->bitmap,
 	       unknown_glyph_bitmap, sizeof (unknown_glyph_bitmap));
@@ -806,6 +810,8 @@ grub_font_get_glyph_internal (grub_font_t font, grub_uint32_t code)
       glyph->offset_x = xoff;
       glyph->offset_y = yoff;
       glyph->device_width = dwidth;
+      glyph->scaled_bitmap = NULL;
+      glyph->scale = 0;
 
       /* Don't try to read empty bitmaps (e.g., space characters).  */
       if (len != 0)
@@ -813,6 +819,7 @@ grub_font_get_glyph_internal (grub_font_t font, grub_uint32_t code)
 	  if (grub_file_read (font->file, glyph->bitmap, len) != len)
 	    {
 	      remove_font (font);
+	      grub_free (glyph->scaled_bitmap);
 	      grub_free (glyph);
 	      return 0;
 	    }
@@ -1559,10 +1566,19 @@ grub_font_construct_glyph (grub_font_t hinted_font,
 
   if (max_glyph_size < cur_glyph_size)
     {
-      grub_free (glyph);
+      if (glyph)
+	{
+	  grub_free (glyph->scaled_bitmap);
+	  grub_free (glyph);
+	}
       if (grub_mul (cur_glyph_size, 2, &max_glyph_size))
 	max_glyph_size = 0;
       glyph = max_glyph_size > 0 ? grub_malloc (max_glyph_size) : NULL;
+      if (glyph)
+	{
+	  glyph->scaled_bitmap = NULL;
+	  glyph->scale = 0;
+	}
     }
   if (!glyph)
     {
@@ -1571,9 +1587,12 @@ grub_font_construct_glyph (grub_font_t hinted_font,
       return main_glyph;
     }
 
+  grub_free (glyph->scaled_bitmap);
   grub_memset (glyph, 0, cur_glyph_size);
 
   glyph->font = main_glyph->font;
+  glyph->scaled_bitmap = NULL;
+  glyph->scale = 0;
   if (bounds.width == 0 || bounds.height == 0 ||
       grub_cast (bounds.width, &glyph->width) ||
       grub_cast (bounds.height, &glyph->height) ||
@@ -1598,12 +1617,55 @@ grub_font_construct_glyph (grub_font_t hinted_font,
   return glyph;
 }
 
+/*
+ * Scale the glyph bitmap by `scale` times.
+ * If succeeded, scaled bitmap will be stored at glyph->scaled_bitmap, and
+ * the corresponding scale factor will be stored at glyph->scale.
+ * If failed, glyph will not be touched.
+ */
+static void
+try_scale_glyph (struct grub_font_glyph *glyph, int scale)
+{
+  unsigned i, j, src_bit, dst_bit;
+  int pixel;
+  grub_uint16_t new_width, new_height;
+  grub_size_t bitmap_size;
+  grub_uint8_t *bitmap;
+
+  if (glyph->scale == scale)
+    return;
+
+  if (grub_mul (glyph->width, scale, &new_width) ||
+      grub_mul (glyph->height, scale, &new_height))
+    return;
+
+  if (grub_video_bitmap_calc_1bpp_bufsz (new_width, new_height, &bitmap_size))
+    return;
+  bitmap = grub_zalloc (bitmap_size);
+  if (bitmap == NULL)
+    return;
+
+  for (i = 0; i < new_height; i++)
+    for (j = 0; j < new_width; j++)
+      {
+	src_bit = (i / scale) * glyph->width + (j / scale);
+	dst_bit = i * new_width + j;
+	pixel = (glyph->bitmap[src_bit / 8] >> (7 - src_bit % 8)) & 1;
+	bitmap[dst_bit / 8] |= pixel << (7 - dst_bit % 8);
+      }
+  
+  grub_free (glyph->scaled_bitmap);
+  glyph->scaled_bitmap = bitmap;
+  glyph->scale = scale;
+}
+
 /* Draw the specified glyph at (x, y).  The y coordinate designates the
    baseline of the character, while the x coordinate designates the left
    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;
 
@@ -1636,11 +1698,28 @@ 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;
+  if (scale > 1)
+    try_scale_glyph (glyph, scale);
+
+  if (glyph->scale == scale)
+    {
+      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 = glyph->scaled_bitmap;
+    }
+  else
+    {
+      /* Scaled bitmap not suitable, fallback to no-scale.  */
+      scale = 1;
+    }
+
+  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..6417e5b58 100644
--- a/include/grub/font.h
+++ b/include/grub/font.h
@@ -79,6 +79,12 @@ struct grub_font_glyph
   /* Number of pixels to advance to start the next character.  */
   grub_uint16_t device_width;
 
+  /* Pointer to cached scaled bitmap.  Allocated during a scaling drawing.  */
+  grub_uint8_t *scaled_bitmap;
+
+  /* The scale factor for cached scaled bitmap.  */
+  int scale;
+
   /* Row-major order, packed bits (no padding; rows can break within a byte).
      The length of the array is (width * height + 7) / 8.  Within a
      byte, the most significant bit is the first (leftmost/uppermost) pixel.
@@ -141,7 +147,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] 10+ messages in thread

* [PATCH 5/5] term/gfxterm: Preliminary HiDPI support
  2022-12-05 11:29 [PATCH 0/5] Font fixes and preliminary HiDPI support Zhang Boyang
                   ` (3 preceding siblings ...)
  2022-12-05 11:29 ` [PATCH 4/5] font: Add font scaling feature to grub_font_draw_glyph() Zhang Boyang
@ 2022-12-05 11:29 ` Zhang Boyang
  4 siblings, 0 replies; 10+ messages in thread
From: Zhang Boyang @ 2022-12-05 11:29 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. It introduces a
new environment variable 'gfxterm_scale'. If set to 0, and a high
resolution monitor is detected, it will scale the font size
automatically. If set to other number, that number will be the scale
factor, overriding automatic scale factor calculation.

Signed-off-by: Zhang Boyang <zhangboyang.id@gmail.com>
---
 docs/grub.texi           |  11 ++++
 grub-core/gfxmenu/view.c |   1 +
 grub-core/term/gfxterm.c | 120 ++++++++++++++++++++++++++++++++-------
 include/grub/gfxterm.h   |   8 ++-
 4 files changed, 117 insertions(+), 23 deletions(-)

diff --git a/docs/grub.texi b/docs/grub.texi
index 50c811a88..b754a465b 100644
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -3309,6 +3309,7 @@ These variables have special meaning to GRUB.
 * gfxmode::
 * gfxpayload::
 * gfxterm_font::
+* gfxterm_scale::
 * grub_cpu::
 * grub_platform::
 * icondir::
@@ -3588,6 +3589,16 @@ If this variable is set, it names a font to use for text on the
 available font.
 
 
+@node gfxterm_scale
+@subsection gfxterm_scale
+
+If this variable is not set, or set to @samp{0}, the @samp{gfxterm}
+graphical terminal will scale the font automatically when a high resolution
+monitor is detected.  If set to other number, the font scale factor will be
+forced to that number.  Set this to @samp{1} if user don't want
+@samp{gfxterm} to scale the font on screen.
+
+
 @node grub_cpu
 @subsection grub_cpu
 
diff --git a/grub-core/gfxmenu/view.c b/grub-core/gfxmenu/view.c
index 6358004b2..94b9ef4db 100644
--- a/grub-core/gfxmenu/view.c
+++ b/grub-core/gfxmenu/view.c
@@ -546,6 +546,7 @@ init_terminal (grub_gfxmenu_view_t view)
                            view->terminal_rect.height,
                            view->double_repaint,
                            terminal_font,
+                           1,
                            view->terminal_border);
   grub_gfxterm_decorator_hook = grub_gfxmenu_draw_terminal_box;
 }
diff --git a/grub-core/term/gfxterm.c b/grub-core/term/gfxterm.c
index 4512dee6f..d16410f5e 100644
--- a/grub-core/term/gfxterm.c
+++ b/grub-core/term/gfxterm.c
@@ -37,6 +37,13 @@ GRUB_MOD_LICENSE ("GPLv3+");
 
 #define DEFAULT_STANDARD_COLOR  0x07
 
+/* Arbitrarily pick half of 80x24 as minimum number of rows and columns. */
+#define MIN_COL	40
+#define MIN_ROW	12
+
+/* For 8x16 fonts, 8x is sufficient on a 16K monitor. */
+#define MAX_SCALE	8
+
 struct grub_dirty_region
 {
   int top_left_x;
@@ -65,6 +72,9 @@ struct grub_virtual_screen
   unsigned int offset_x;
   unsigned int offset_y;
 
+  /* Scale factor.  */
+  int scale;
+
   /* TTY Character sizes in pixes.  */
   unsigned int normal_char_width;
   unsigned int normal_char_height;
@@ -201,10 +211,51 @@ grub_virtual_screen_free (void)
   text_layer = 0;
 }
 
+/*
+ * Adjust scale factor, `scale` can be any untrusted value.
+ * If `scale` is 0, determine scale factor heuristically.
+ * Returns the adjusted value, which is always in [1, MAX_SCALE].
+ */
+int
+grub_gfxterm_adjust_scale_factor (grub_font_t font, int scale,
+				  int width, int height,
+				  int border_width)
+{
+  int i;
+  int max_scale;
+  int normal_char_width, normal_char_height;
+  int columns, rows;
+
+  normal_char_width = calculate_normal_character_width (font);
+  normal_char_height = grub_font_get_max_char_height (font);
+
+  max_scale = 1;
+  for (i = 2; i <= MAX_SCALE; i++)
+    {
+      columns = (width - 2 * border_width * i) / (normal_char_width * i);
+      rows = (height - 2 * border_width * i) / (normal_char_height * i);
+      if (columns < MIN_COL || rows < MIN_ROW)
+	break;
+      max_scale = i;
+    }
+
+  if (scale == 0)
+    {
+      scale = 1;
+      for (i = 2; i <= MAX_SCALE; i *= 2)
+	if (width > 1920 * (i / 2) && height > 1080 * (i / 2))
+	  scale = i;
+    }
+
+  scale = grub_max (scale, 1);
+  scale = grub_min (scale, max_scale);
+  return scale;
+}
+
 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, int scale)
 {
   unsigned int i;
 
@@ -213,16 +264,17 @@ 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;
   virtual_screen.offset_y = y;
   virtual_screen.normal_char_width =
-    calculate_normal_character_width (virtual_screen.font);
+    calculate_normal_character_width (virtual_screen.font) * virtual_screen.scale;
   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;
@@ -234,10 +286,10 @@ grub_virtual_screen_setup (unsigned int x, unsigned int y,
 
   /*
    * There must be a minimum number of rows and columns for the screen to
-   * make sense. Arbitrarily pick half of 80x24. If either dimensions is 0
-   * we would allocate 0 bytes for the text_buffer.
+   * make sense. If either dimensions is 0 we would allocate 0 bytes for
+   * the text_buffer.
    */
-  if (virtual_screen.columns < 40 || virtual_screen.rows < 12)
+  if (virtual_screen.columns < MIN_COL || virtual_screen.rows < MIN_ROW)
     return grub_error (GRUB_ERR_BAD_FONT,
 		       "font: glyphs too large to fit on screen");
 
@@ -297,7 +349,8 @@ grub_err_t
 grub_gfxterm_set_window (struct grub_video_render_target *target,
 			 int x, int y, int width, int height,
 			 int double_repaint,
-			 grub_font_t font, int border_width)
+			 grub_font_t font, int scale,
+			 int border_width)
 {
   /* Clean up any prior instance.  */
   destroy_window ();
@@ -306,10 +359,10 @@ grub_gfxterm_set_window (struct grub_video_render_target *target,
   render_target = target;
 
   /* 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;
@@ -337,6 +390,8 @@ grub_gfxterm_fullscreen (void)
   grub_err_t err;
   int double_redraw;
   grub_font_t font;
+  int scale;
+  const char *scale_str;
 
   err = grub_video_get_info (&mode_info);
   /* Figure out what mode we ended up.  */
@@ -366,12 +421,32 @@ grub_gfxterm_fullscreen (void)
   if (!font)
     return grub_error (GRUB_ERR_BAD_FONT, "no font loaded");
 
+  /* Decide scale factor. */
+  scale = 0;
+
+  scale_str = grub_env_get ("gfxterm_scale");
+  if (scale_str)
+    {
+      const char *scale_str_end;
+      unsigned long scale_ull;
+      grub_error_push ();
+      scale_ull = grub_strtoull (scale_str, &scale_str_end, 10);
+      if (*scale_str == '\0' || *scale_str_end != '\0' || grub_errno != GRUB_ERR_NONE
+	  || grub_cast (scale_ull, &scale))
+	scale = 0;
+      grub_error_pop ();
+    }
+
+  scale = grub_gfxterm_adjust_scale_factor (font, scale,
+					    mode_info.width, mode_info.height,
+					    DEFAULT_BORDER_WIDTH);
+
   grub_gfxterm_decorator_hook = NULL;
 
   return grub_gfxterm_set_window (GRUB_VIDEO_RENDER_TARGET_DISPLAY,
 				  0, 0, mode_info.width, mode_info.height,
 				  double_redraw,
-				  font, DEFAULT_BORDER_WIDTH);
+				  font, scale, DEFAULT_BORDER_WIDTH);
 }
 
 static grub_err_t
@@ -642,7 +717,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 +731,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 +765,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 +776,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);
@@ -968,7 +1043,7 @@ calculate_character_width (struct grub_font_glyph *glyph)
   if (! glyph || glyph->device_width == 0)
     return 1;
 
-  return (glyph->device_width
+  return (glyph->device_width * virtual_screen.scale
           + (virtual_screen.normal_char_width - 1))
          / virtual_screen.normal_char_width;
 }
@@ -983,8 +1058,9 @@ grub_gfxterm_getcharwidth (struct grub_term_output *term __attribute__ ((unused)
   if (dev_width == 0)
     return 1;
 
-  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
diff --git a/include/grub/gfxterm.h b/include/grub/gfxterm.h
index 7e1ff6dfc..6cd99dd54 100644
--- a/include/grub/gfxterm.h
+++ b/include/grub/gfxterm.h
@@ -25,11 +25,17 @@
 #include <grub/video.h>
 #include <grub/font.h>
 
+int
+EXPORT_FUNC (grub_gfxterm_adjust_scale_factor) (grub_font_t font, int scale,
+						int width, int height,
+						int border_width);
+
 grub_err_t
 EXPORT_FUNC (grub_gfxterm_set_window) (struct grub_video_render_target *target,
 				       int x, int y, int width, int height,
 				       int double_repaint,
-				       grub_font_t font, int border_width);
+				       grub_font_t font, int scale,
+				       int border_width);
 
 void EXPORT_FUNC (grub_gfxterm_schedule_repaint) (void);
 
-- 
2.30.2



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

* Re: [PATCH 4/5] font: Add font scaling feature to grub_font_draw_glyph()
  2022-12-05 11:29 ` [PATCH 4/5] font: Add font scaling feature to grub_font_draw_glyph() Zhang Boyang
@ 2022-12-05 11:42   ` Zhang Boyang
  0 siblings, 0 replies; 10+ messages in thread
From: Zhang Boyang @ 2022-12-05 11:42 UTC (permalink / raw)
  To: The development of GNU GRUB

On 2022/12/5 19:29, Zhang Boyang wrote:
> This patch also adds a new metadata entry named MAXS to font files,
> limiting the maximum acceptable scale factor at runtime for a specific
> font. Currently MAXS is set to 8, which is sufficient for 16K monitors.

Oh, I forgot to delete this paragraph of commit message when 
refactoring. There is no such change in this commit. Please ignore this 
paragraph.

Best Regards,
Zhang Boyang


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

* Re: [PATCH 1/5] font: Check return value of grub_malloc() in ascii_glyph_lookup()
  2022-12-05 11:29 ` [PATCH 1/5] font: Check return value of grub_malloc() in ascii_glyph_lookup() Zhang Boyang
@ 2022-12-13 17:16   ` Daniel Kiper
  0 siblings, 0 replies; 10+ messages in thread
From: Daniel Kiper @ 2022-12-13 17:16 UTC (permalink / raw)
  To: Zhang Boyang; +Cc: grub-devel

On Mon, Dec 05, 2022 at 07:29:36PM +0800, Zhang Boyang wrote:
> There is a problem in ascii_glyph_lookup(). It doesn't check the return
> value of grub_malloc(). If memory can't be allocated, then NULL pointer
> will be written to.
>
> This patch fixes the problem by fallbacking to unknown_glyph in case of
> grub_malloc() returns NULL.
>
> Signed-off-by: Zhang Boyang <zhangboyang.id@gmail.com>

Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>

Daniel


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

* Re: [PATCH 2/5] font: Assign null_font to unknown_glyph
  2022-12-05 11:29 ` [PATCH 2/5] font: Assign null_font to unknown_glyph Zhang Boyang
@ 2022-12-13 17:17   ` Daniel Kiper
  0 siblings, 0 replies; 10+ messages in thread
From: Daniel Kiper @ 2022-12-13 17:17 UTC (permalink / raw)
  To: Zhang Boyang; +Cc: grub-devel

On Mon, Dec 05, 2022 at 07:29:37PM +0800, Zhang Boyang wrote:
> Like glyphs in ascii_font_glyph[], assign null_font to
> unknown_glyph->font in order to prevent grub_font_get_*() from
> dereferencing NULL pointer.
>
> Signed-off-by: Zhang Boyang <zhangboyang.id@gmail.com>

Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>

Daniel


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

* Re: [PATCH 3/5] font: Reject fonts with negative max_char_width or max_char_height
  2022-12-05 11:29 ` [PATCH 3/5] font: Reject fonts with negative max_char_width or max_char_height Zhang Boyang
@ 2022-12-13 17:17   ` Daniel Kiper
  0 siblings, 0 replies; 10+ messages in thread
From: Daniel Kiper @ 2022-12-13 17:17 UTC (permalink / raw)
  To: Zhang Boyang; +Cc: grub-devel

On Mon, Dec 05, 2022 at 07:29:38PM +0800, Zhang Boyang wrote:
> If max_char_width or max_char_height is negative, bad values might be
> propagated by grub_font_get_max_char_width() or
> grub_font_get_max_char_height(). Prevent this from happening.
>
> Signed-off-by: Zhang Boyang <zhangboyang.id@gmail.com>

Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>

Daniel


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

end of thread, other threads:[~2022-12-13 17:18 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-12-05 11:29 [PATCH 0/5] Font fixes and preliminary HiDPI support Zhang Boyang
2022-12-05 11:29 ` [PATCH 1/5] font: Check return value of grub_malloc() in ascii_glyph_lookup() Zhang Boyang
2022-12-13 17:16   ` Daniel Kiper
2022-12-05 11:29 ` [PATCH 2/5] font: Assign null_font to unknown_glyph Zhang Boyang
2022-12-13 17:17   ` Daniel Kiper
2022-12-05 11:29 ` [PATCH 3/5] font: Reject fonts with negative max_char_width or max_char_height Zhang Boyang
2022-12-13 17:17   ` Daniel Kiper
2022-12-05 11:29 ` [PATCH 4/5] font: Add font scaling feature to grub_font_draw_glyph() Zhang Boyang
2022-12-05 11:42   ` Zhang Boyang
2022-12-05 11:29 ` [PATCH 5/5] term/gfxterm: Preliminary HiDPI support 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.