grub-devel
[Top][All Lists]
Advanced

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

[PATCH v3 2/2] term/gfxterm: Preliminary HiDPI support


From: Zhang Boyang
Subject: [PATCH v3 2/2] term/gfxterm: Preliminary HiDPI support
Date: Wed, 1 Jun 2022 16:23:09 +0800

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 | 72 ++++++++++++++++++++++++++++------------
 include/grub/gfxterm.h   |  3 +-
 4 files changed, 64 insertions(+), 23 deletions(-)

diff --git a/docs/grub.texi b/docs/grub.texi
index acf462ccf..2d98ad6ff 100644
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -3274,6 +3274,7 @@ These variables have special meaning to GRUB.
 * gfxmode::
 * gfxpayload::
 * gfxterm_font::
+* gfxterm_scale::
 * grub_cpu::
 * grub_platform::
 * icondir::
@@ -3548,6 +3549,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..df2d3f86b 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;
@@ -297,7 +299,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 +309,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;
@@ -332,11 +335,13 @@ static grub_err_t
 grub_gfxterm_fullscreen (void)
 {
   const char *font_name;
+  const char *scale_conf;
   struct grub_video_mode_info mode_info;
   grub_video_color_t color;
   grub_err_t err;
   int double_redraw;
   grub_font_t font;
+  int scale;
 
   err = grub_video_get_info (&mode_info);
   /* Figure out what mode we ended up.  */
@@ -366,12 +371,34 @@ grub_gfxterm_fullscreen (void)
   if (!font)
     return grub_error (GRUB_ERR_BAD_FONT, "no font loaded");
 
+  /* Decide font scale factor. */
+  scale_conf = grub_env_get ("gfxterm_scale");
+  scale = 0;
+  if (scale_conf)
+    scale = (int) grub_strtoul (scale_conf, 0, 0);
+  if (scale < 0 || scale > GRUB_FONT_MAX_SCALE)
+    scale = 0;
+  if (scale == 0)
+    {
+      if (mode_info.width > 7680 && mode_info.height > 4320)
+       scale = 8;
+      else if (mode_info.width > 3840 && mode_info.height > 2160)
+       scale = 4;
+      else if (mode_info.width > 1920 && mode_info.height > 1080)
+       scale = 2;
+      else
+       scale = 1;
+    }
+  if (grub_font_get_max_char_width(font) * scale > GRUB_FONT_MAX_DIMENSION
+      || grub_font_get_max_char_height(font) * scale > GRUB_FONT_MAX_DIMENSION)
+    scale = 1;
+
   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 +669,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 +683,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 +717,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 +728,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 +984,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 +1008,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
diff --git a/include/grub/gfxterm.h b/include/grub/gfxterm.h
index 7e1ff6dfc..73735a26e 100644
--- a/include/grub/gfxterm.h
+++ b/include/grub/gfxterm.h
@@ -29,7 +29,8 @@ 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




reply via email to

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