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