* grub-core/gfxmenu/theme_loader.c: New global options for the
theme background image handling. desktop-image-scale-method, desktop-image-h-align, desktop-image-v-align. * grub-core/gfxmenu/view.c: Likewise. * include/gfxmenu_view.h: Likewise. * include/bitmap_scale.h: Proportional scale functions introduced. * grub-core/video/bitmap_scale.c: Likewise. Verification checks are put in a separate functions. GRUB_ERR_BUG is set for grub_error in cases of unexpected input variables for scale functions. * docs/grub.texi: Updated documentation for new options.
This commit is contained in:
parent
c573914389
commit
ebc1da55cd
7 changed files with 417 additions and 107 deletions
13
ChangeLog
13
ChangeLog
|
@ -1,3 +1,16 @@
|
||||||
|
2013-10-02 Vladimir Testov <vladimir.testov@rosalab.ru>
|
||||||
|
|
||||||
|
* grub-core/gfxmenu/theme_loader.c: New global options for the
|
||||||
|
theme background image handling. desktop-image-scale-method,
|
||||||
|
desktop-image-h-align, desktop-image-v-align.
|
||||||
|
* grub-core/gfxmenu/view.c: Likewise.
|
||||||
|
* include/gfxmenu_view.h: Likewise.
|
||||||
|
* include/bitmap_scale.h: Proportional scale functions introduced.
|
||||||
|
* grub-core/video/bitmap_scale.c: Likewise. Verification checks are
|
||||||
|
put in a separate functions. GRUB_ERR_BUG is set for grub_error in
|
||||||
|
cases of unexpected input variables for scale functions.
|
||||||
|
* docs/grub.texi: Updated documentation for new options.
|
||||||
|
|
||||||
2013-10-02 Vladimir Serbinenko <phcoder@gmail.com>
|
2013-10-02 Vladimir Serbinenko <phcoder@gmail.com>
|
||||||
|
|
||||||
* grub-core/video/readers/png.c: Support narrow (4-/2-/1-bpp) PNG.
|
* grub-core/video/readers/png.c: Support narrow (4-/2-/1-bpp) PNG.
|
||||||
|
|
|
@ -1907,7 +1907,28 @@ In this example, name3 is assigned a color value.
|
||||||
@item message-font @tab Defines the font used for messages, such as when GRUB is unable to automatically boot an entry.
|
@item message-font @tab Defines the font used for messages, such as when GRUB is unable to automatically boot an entry.
|
||||||
@item message-color @tab Defines the color of the message text.
|
@item message-color @tab Defines the color of the message text.
|
||||||
@item message-bg-color @tab Defines the background color of the message text area.
|
@item message-bg-color @tab Defines the background color of the message text area.
|
||||||
@item desktop-image @tab Specifies the image to use as the background. It will be scaled to fit the screen size.
|
@item desktop-image
|
||||||
|
@tab Specifies the image to use as the background. It will be scaled
|
||||||
|
to fit the screen size or proportionally scaled depending on the scale
|
||||||
|
method.
|
||||||
|
@item desktop-image-scale-method
|
||||||
|
@tab Specifies the scaling method for the *desktop-image*. Options are
|
||||||
|
``stretch``, ``crop``, ``padding``, ``fitwidth``, ``fitheight``.
|
||||||
|
``stretch`` for fitting the screen size. Otherwise it is proportional
|
||||||
|
scaling of a part of *desktop-image* to the part of the screen.
|
||||||
|
``crop`` part of the *desktop-image* will be proportionally scaled to
|
||||||
|
fit the screen sizes. ``padding`` the entire *desktop-image* will be
|
||||||
|
contained on the screen. ``fitwidth`` for fitting the *desktop-image*'s
|
||||||
|
width with screen width. ``fitheight`` for fitting the *desktop-image*'s
|
||||||
|
height with the screen height. Default is ``stretch``.
|
||||||
|
@item desktop-image-h-align
|
||||||
|
@tab Specifies the horizontal alignment of the *desktop-image* if
|
||||||
|
*desktop-image-scale-method* isn't equeal to ``stretch``. Options are
|
||||||
|
``left``, ``center``, ``right``. Default is ``center``.
|
||||||
|
@item desktop-image-v-align
|
||||||
|
@tab Specifies the vertical alignment of the *desktop-image* if
|
||||||
|
*desktop-image-scale-method* isn't equeal to ``stretch``. Options are
|
||||||
|
``top``, ``center``, ``bottom``. Default is ``center``.
|
||||||
@item desktop-color @tab Specifies the color for the background if *desktop-image* is not specified.
|
@item desktop-color @tab Specifies the color for the background if *desktop-image* is not specified.
|
||||||
@item terminal-box @tab Specifies the file name pattern for the styled box slices used for the command line terminal window. For example, ``terminal-box: terminal_*.png'' will use the images ``terminal_c.png`` as the center area, ``terminal_n.png`` as the north (top) edge, ``terminal_nw.png`` as the northwest (upper left) corner, and so on. If the image for any slice is not found, it will simply be left empty.
|
@item terminal-box @tab Specifies the file name pattern for the styled box slices used for the command line terminal window. For example, ``terminal-box: terminal_*.png'' will use the images ``terminal_c.png`` as the center area, ``terminal_n.png`` as the north (top) edge, ``terminal_nw.png`` as the northwest (upper left) corner, and so on. If the image for any slice is not found, it will simply be left empty.
|
||||||
@item terminal-border @tab Specifies the border width of the terminal window.
|
@item terminal-border @tab Specifies the border width of the terminal window.
|
||||||
|
|
|
@ -165,7 +165,6 @@ theme_set_string (grub_gfxmenu_view_t view,
|
||||||
else if (! grub_strcmp ("desktop-image", name))
|
else if (! grub_strcmp ("desktop-image", name))
|
||||||
{
|
{
|
||||||
struct grub_video_bitmap *raw_bitmap;
|
struct grub_video_bitmap *raw_bitmap;
|
||||||
struct grub_video_bitmap *scaled_bitmap;
|
|
||||||
char *path;
|
char *path;
|
||||||
path = grub_resolve_relative_path (theme_dir, value);
|
path = grub_resolve_relative_path (theme_dir, value);
|
||||||
if (! path)
|
if (! path)
|
||||||
|
@ -176,20 +175,56 @@ theme_set_string (grub_gfxmenu_view_t view,
|
||||||
return grub_errno;
|
return grub_errno;
|
||||||
}
|
}
|
||||||
grub_free(path);
|
grub_free(path);
|
||||||
grub_video_bitmap_create_scaled (&scaled_bitmap,
|
grub_video_bitmap_destroy (view->raw_desktop_image);
|
||||||
view->screen.width,
|
view->raw_desktop_image = raw_bitmap;
|
||||||
view->screen.height,
|
}
|
||||||
raw_bitmap,
|
else if (! grub_strcmp ("desktop-image-scale-method", name))
|
||||||
GRUB_VIDEO_BITMAP_SCALE_METHOD_BEST);
|
{
|
||||||
grub_video_bitmap_destroy (raw_bitmap);
|
if (! value || ! grub_strcmp ("stretch", value))
|
||||||
if (! scaled_bitmap)
|
view->desktop_image_scale_method =
|
||||||
{
|
GRUB_VIDEO_BITMAP_SELECTION_METHOD_STRETCH;
|
||||||
grub_error_push ();
|
else if (! grub_strcmp ("crop", value))
|
||||||
return grub_error (grub_errno, "error scaling desktop image");
|
view->desktop_image_scale_method =
|
||||||
}
|
GRUB_VIDEO_BITMAP_SELECTION_METHOD_CROP;
|
||||||
|
else if (! grub_strcmp ("padding", value))
|
||||||
grub_video_bitmap_destroy (view->desktop_image);
|
view->desktop_image_scale_method =
|
||||||
view->desktop_image = scaled_bitmap;
|
GRUB_VIDEO_BITMAP_SELECTION_METHOD_PADDING;
|
||||||
|
else if (! grub_strcmp ("fitwidth", value))
|
||||||
|
view->desktop_image_scale_method =
|
||||||
|
GRUB_VIDEO_BITMAP_SELECTION_METHOD_FITWIDTH;
|
||||||
|
else if (! grub_strcmp ("fitheight", value))
|
||||||
|
view->desktop_image_scale_method =
|
||||||
|
GRUB_VIDEO_BITMAP_SELECTION_METHOD_FITHEIGHT;
|
||||||
|
else
|
||||||
|
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||||
|
_("Unsupported scale method: %s"),
|
||||||
|
grub_strdup (value));
|
||||||
|
}
|
||||||
|
else if (! grub_strcmp ("desktop-image-h-align", name))
|
||||||
|
{
|
||||||
|
if (! grub_strcmp ("left", value))
|
||||||
|
view->desktop_image_h_align = GRUB_VIDEO_BITMAP_H_ALIGN_LEFT;
|
||||||
|
else if (! grub_strcmp ("center", value))
|
||||||
|
view->desktop_image_h_align = GRUB_VIDEO_BITMAP_H_ALIGN_CENTER;
|
||||||
|
else if (! grub_strcmp ("right", value))
|
||||||
|
view->desktop_image_h_align = GRUB_VIDEO_BITMAP_H_ALIGN_RIGHT;
|
||||||
|
else
|
||||||
|
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||||
|
_("Unsupported horizontal align method: %s"),
|
||||||
|
grub_strdup (value));
|
||||||
|
}
|
||||||
|
else if (! grub_strcmp ("desktop-image-v-align", name))
|
||||||
|
{
|
||||||
|
if (! grub_strcmp ("top", value))
|
||||||
|
view->desktop_image_v_align = GRUB_VIDEO_BITMAP_V_ALIGN_TOP;
|
||||||
|
else if (! grub_strcmp ("center", value))
|
||||||
|
view->desktop_image_v_align = GRUB_VIDEO_BITMAP_V_ALIGN_CENTER;
|
||||||
|
else if (! grub_strcmp ("bottom", value))
|
||||||
|
view->desktop_image_v_align = GRUB_VIDEO_BITMAP_V_ALIGN_BOTTOM;
|
||||||
|
else
|
||||||
|
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||||
|
_("Unsupported vertical align method: %s"),
|
||||||
|
grub_strdup (value));
|
||||||
}
|
}
|
||||||
else if (! grub_strcmp ("desktop-color", name))
|
else if (! grub_strcmp ("desktop-color", name))
|
||||||
grub_video_parse_color (value, &view->desktop_color);
|
grub_video_parse_color (value, &view->desktop_color);
|
||||||
|
|
|
@ -40,6 +40,8 @@
|
||||||
|
|
||||||
static void
|
static void
|
||||||
init_terminal (grub_gfxmenu_view_t view);
|
init_terminal (grub_gfxmenu_view_t view);
|
||||||
|
static void
|
||||||
|
init_background (grub_gfxmenu_view_t view);
|
||||||
static grub_gfxmenu_view_t term_view;
|
static grub_gfxmenu_view_t term_view;
|
||||||
|
|
||||||
/* Create a new view object, loading the theme specified by THEME_PATH and
|
/* Create a new view object, loading the theme specified by THEME_PATH and
|
||||||
|
@ -91,7 +93,11 @@ grub_gfxmenu_view_new (const char *theme_path,
|
||||||
view->title_color = default_fg_color;
|
view->title_color = default_fg_color;
|
||||||
view->message_color = default_bg_color;
|
view->message_color = default_bg_color;
|
||||||
view->message_bg_color = default_fg_color;
|
view->message_bg_color = default_fg_color;
|
||||||
view->desktop_image = 0;
|
view->raw_desktop_image = 0;
|
||||||
|
view->scaled_desktop_image = 0;
|
||||||
|
view->desktop_image_scale_method = GRUB_VIDEO_BITMAP_SELECTION_METHOD_STRETCH;
|
||||||
|
view->desktop_image_h_align = GRUB_VIDEO_BITMAP_H_ALIGN_CENTER;
|
||||||
|
view->desktop_image_v_align = GRUB_VIDEO_BITMAP_V_ALIGN_CENTER;
|
||||||
view->desktop_color = default_bg_color;
|
view->desktop_color = default_bg_color;
|
||||||
view->terminal_box = grub_gfxmenu_create_box (0, 0);
|
view->terminal_box = grub_gfxmenu_create_box (0, 0);
|
||||||
view->title_text = grub_strdup (_("GRUB Boot Menu"));
|
view->title_text = grub_strdup (_("GRUB Boot Menu"));
|
||||||
|
@ -128,7 +134,8 @@ grub_gfxmenu_view_destroy (grub_gfxmenu_view_t view)
|
||||||
grub_gfxmenu_timeout_notifications = grub_gfxmenu_timeout_notifications->next;
|
grub_gfxmenu_timeout_notifications = grub_gfxmenu_timeout_notifications->next;
|
||||||
grub_free (p);
|
grub_free (p);
|
||||||
}
|
}
|
||||||
grub_video_bitmap_destroy (view->desktop_image);
|
grub_video_bitmap_destroy (view->raw_desktop_image);
|
||||||
|
grub_video_bitmap_destroy (view->scaled_desktop_image);
|
||||||
if (view->terminal_box)
|
if (view->terminal_box)
|
||||||
view->terminal_box->destroy (view->terminal_box);
|
view->terminal_box->destroy (view->terminal_box);
|
||||||
grub_free (view->terminal_font_name);
|
grub_free (view->terminal_font_name);
|
||||||
|
@ -144,9 +151,9 @@ static void
|
||||||
redraw_background (grub_gfxmenu_view_t view,
|
redraw_background (grub_gfxmenu_view_t view,
|
||||||
const grub_video_rect_t *bounds)
|
const grub_video_rect_t *bounds)
|
||||||
{
|
{
|
||||||
if (view->desktop_image)
|
if (view->scaled_desktop_image)
|
||||||
{
|
{
|
||||||
struct grub_video_bitmap *img = view->desktop_image;
|
struct grub_video_bitmap *img = view->scaled_desktop_image;
|
||||||
grub_video_blit_bitmap (img, GRUB_VIDEO_BLIT_REPLACE,
|
grub_video_blit_bitmap (img, GRUB_VIDEO_BLIT_REPLACE,
|
||||||
bounds->x, bounds->y,
|
bounds->x, bounds->y,
|
||||||
bounds->x - view->screen.x,
|
bounds->x - view->screen.x,
|
||||||
|
@ -328,6 +335,8 @@ grub_gfxmenu_view_draw (grub_gfxmenu_view_t view)
|
||||||
{
|
{
|
||||||
init_terminal (view);
|
init_terminal (view);
|
||||||
|
|
||||||
|
init_background (view);
|
||||||
|
|
||||||
/* Clear the screen; there may be garbage left over in video memory. */
|
/* Clear the screen; there may be garbage left over in video memory. */
|
||||||
grub_video_fill_rect (grub_video_map_rgb (0, 0, 0),
|
grub_video_fill_rect (grub_video_map_rgb (0, 0, 0),
|
||||||
view->screen.x, view->screen.y,
|
view->screen.x, view->screen.y,
|
||||||
|
@ -524,6 +533,35 @@ init_terminal (grub_gfxmenu_view_t view)
|
||||||
grub_gfxterm_decorator_hook = grub_gfxmenu_draw_terminal_box;
|
grub_gfxterm_decorator_hook = grub_gfxmenu_draw_terminal_box;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
init_background (grub_gfxmenu_view_t view)
|
||||||
|
{
|
||||||
|
if (view->scaled_desktop_image)
|
||||||
|
return;
|
||||||
|
|
||||||
|
struct grub_video_bitmap *scaled_bitmap;
|
||||||
|
if (view->desktop_image_scale_method ==
|
||||||
|
GRUB_VIDEO_BITMAP_SELECTION_METHOD_STRETCH)
|
||||||
|
grub_video_bitmap_create_scaled (&scaled_bitmap,
|
||||||
|
view->screen.width,
|
||||||
|
view->screen.height,
|
||||||
|
view->raw_desktop_image,
|
||||||
|
GRUB_VIDEO_BITMAP_SCALE_METHOD_BEST);
|
||||||
|
else
|
||||||
|
grub_video_bitmap_scale_proportional (&scaled_bitmap,
|
||||||
|
view->screen.width,
|
||||||
|
view->screen.height,
|
||||||
|
view->raw_desktop_image,
|
||||||
|
GRUB_VIDEO_BITMAP_SCALE_METHOD_BEST,
|
||||||
|
view->desktop_image_scale_method,
|
||||||
|
view->desktop_image_v_align,
|
||||||
|
view->desktop_image_h_align);
|
||||||
|
if (! scaled_bitmap)
|
||||||
|
return;
|
||||||
|
view->scaled_desktop_image = scaled_bitmap;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/* FIXME: previously notifications were displayed in special case.
|
/* FIXME: previously notifications were displayed in special case.
|
||||||
Is it necessary?
|
Is it necessary?
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -33,6 +33,46 @@ static grub_err_t scale_nn (struct grub_video_bitmap *dst,
|
||||||
static grub_err_t scale_bilinear (struct grub_video_bitmap *dst,
|
static grub_err_t scale_bilinear (struct grub_video_bitmap *dst,
|
||||||
struct grub_video_bitmap *src);
|
struct grub_video_bitmap *src);
|
||||||
|
|
||||||
|
static grub_err_t
|
||||||
|
verify_source_bitmap (struct grub_video_bitmap *src)
|
||||||
|
{
|
||||||
|
/* Verify the simplifying assumptions. */
|
||||||
|
if (src == 0)
|
||||||
|
return grub_error (GRUB_ERR_BUG,
|
||||||
|
"null src bitmap in grub_video_bitmap_create_scaled");
|
||||||
|
if (src->mode_info.red_field_pos % 8 != 0
|
||||||
|
|| src->mode_info.green_field_pos % 8 != 0
|
||||||
|
|| src->mode_info.blue_field_pos % 8 != 0
|
||||||
|
|| src->mode_info.reserved_field_pos % 8 != 0)
|
||||||
|
return grub_error (GRUB_ERR_BUG,
|
||||||
|
"src format not supported for scale");
|
||||||
|
if (src->mode_info.width == 0 || src->mode_info.height == 0)
|
||||||
|
return grub_error (GRUB_ERR_BUG,
|
||||||
|
"source bitmap has a zero dimension");
|
||||||
|
if (src->mode_info.bytes_per_pixel * 8 != src->mode_info.bpp)
|
||||||
|
return grub_error (GRUB_ERR_BUG,
|
||||||
|
"bitmap to scale has inconsistent Bpp and bpp");
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static grub_err_t
|
||||||
|
grub_video_bitmap_scale (struct grub_video_bitmap *dst,
|
||||||
|
struct grub_video_bitmap *src,
|
||||||
|
enum grub_video_bitmap_scale_method scale_method)
|
||||||
|
{
|
||||||
|
switch (scale_method)
|
||||||
|
{
|
||||||
|
case GRUB_VIDEO_BITMAP_SCALE_METHOD_FASTEST:
|
||||||
|
case GRUB_VIDEO_BITMAP_SCALE_METHOD_NEAREST:
|
||||||
|
return scale_nn (dst, src);
|
||||||
|
case GRUB_VIDEO_BITMAP_SCALE_METHOD_BEST:
|
||||||
|
case GRUB_VIDEO_BITMAP_SCALE_METHOD_BILINEAR:
|
||||||
|
return scale_bilinear (dst, src);
|
||||||
|
default:
|
||||||
|
return grub_error (GRUB_ERR_BUG, "Invalid scale_method value");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* This function creates a new scaled version of the bitmap SRC. The new
|
/* This function creates a new scaled version of the bitmap SRC. The new
|
||||||
bitmap has dimensions DST_WIDTH by DST_HEIGHT. The scaling algorithm
|
bitmap has dimensions DST_WIDTH by DST_HEIGHT. The scaling algorithm
|
||||||
is given by SCALE_METHOD. If an error is encountered, the return code is
|
is given by SCALE_METHOD. If an error is encountered, the return code is
|
||||||
|
@ -52,25 +92,12 @@ grub_video_bitmap_create_scaled (struct grub_video_bitmap **dst,
|
||||||
{
|
{
|
||||||
*dst = 0;
|
*dst = 0;
|
||||||
|
|
||||||
/* Verify the simplifying assumptions. */
|
grub_err_t err = verify_source_bitmap(src);
|
||||||
if (src == 0)
|
if (err != GRUB_ERR_NONE)
|
||||||
return grub_error (GRUB_ERR_BUG,
|
return err;
|
||||||
"null src bitmap in grub_video_bitmap_create_scaled");
|
|
||||||
if (src->mode_info.red_field_pos % 8 != 0
|
|
||||||
|| src->mode_info.green_field_pos % 8 != 0
|
|
||||||
|| src->mode_info.blue_field_pos % 8 != 0
|
|
||||||
|| src->mode_info.reserved_field_pos % 8 != 0)
|
|
||||||
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
|
||||||
"src format not supported for scale");
|
|
||||||
if (src->mode_info.width == 0 || src->mode_info.height == 0)
|
|
||||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
|
||||||
"source bitmap has a zero dimension");
|
|
||||||
if (dst_width <= 0 || dst_height <= 0)
|
if (dst_width <= 0 || dst_height <= 0)
|
||||||
return grub_error (GRUB_ERR_BUG,
|
return grub_error (GRUB_ERR_BUG,
|
||||||
"requested to scale to a size w/ a zero dimension");
|
"requested to scale to a size w/ a zero dimension");
|
||||||
if (src->mode_info.bytes_per_pixel * 8 != src->mode_info.bpp)
|
|
||||||
return grub_error (GRUB_ERR_BUG,
|
|
||||||
"bitmap to scale has inconsistent Bpp and bpp");
|
|
||||||
|
|
||||||
/* Create the new bitmap. */
|
/* Create the new bitmap. */
|
||||||
grub_err_t ret;
|
grub_err_t ret;
|
||||||
|
@ -79,20 +106,171 @@ grub_video_bitmap_create_scaled (struct grub_video_bitmap **dst,
|
||||||
if (ret != GRUB_ERR_NONE)
|
if (ret != GRUB_ERR_NONE)
|
||||||
return ret; /* Error. */
|
return ret; /* Error. */
|
||||||
|
|
||||||
switch (scale_method)
|
ret = grub_video_bitmap_scale (*dst, src, scale_method);
|
||||||
|
|
||||||
|
if (ret == GRUB_ERR_NONE)
|
||||||
{
|
{
|
||||||
case GRUB_VIDEO_BITMAP_SCALE_METHOD_FASTEST:
|
/* Success: *dst is now a pointer to the scaled bitmap. */
|
||||||
case GRUB_VIDEO_BITMAP_SCALE_METHOD_NEAREST:
|
return GRUB_ERR_NONE;
|
||||||
ret = scale_nn (*dst, src);
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Destroy the bitmap and return the error code. */
|
||||||
|
grub_video_bitmap_destroy (*dst);
|
||||||
|
*dst = 0;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static grub_err_t
|
||||||
|
make_h_align (int *x, int *w, int new_w,
|
||||||
|
grub_video_bitmap_h_align_t h_align)
|
||||||
|
{
|
||||||
|
grub_err_t ret = GRUB_ERR_NONE;
|
||||||
|
switch (h_align)
|
||||||
|
{
|
||||||
|
case GRUB_VIDEO_BITMAP_H_ALIGN_LEFT:
|
||||||
|
*x = 0;
|
||||||
break;
|
break;
|
||||||
case GRUB_VIDEO_BITMAP_SCALE_METHOD_BEST:
|
case GRUB_VIDEO_BITMAP_H_ALIGN_CENTER:
|
||||||
case GRUB_VIDEO_BITMAP_SCALE_METHOD_BILINEAR:
|
*x = (*w - new_w) / 2;
|
||||||
ret = scale_bilinear (*dst, src);
|
break;
|
||||||
|
case GRUB_VIDEO_BITMAP_H_ALIGN_RIGHT:
|
||||||
|
*x = *w - new_w;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ret = grub_error (GRUB_ERR_BUG, "Invalid scale_method value");
|
ret = grub_error (GRUB_ERR_BUG, "Invalid h_align value");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
*w = new_w;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static grub_err_t
|
||||||
|
make_v_align (int *y, int *h, int new_h,
|
||||||
|
grub_video_bitmap_v_align_t v_align)
|
||||||
|
{
|
||||||
|
grub_err_t ret = GRUB_ERR_NONE;
|
||||||
|
switch (v_align)
|
||||||
|
{
|
||||||
|
case GRUB_VIDEO_BITMAP_V_ALIGN_TOP:
|
||||||
|
*y = 0;
|
||||||
|
break;
|
||||||
|
case GRUB_VIDEO_BITMAP_V_ALIGN_CENTER:
|
||||||
|
*y = (*h - new_h) / 2;
|
||||||
|
break;
|
||||||
|
case GRUB_VIDEO_BITMAP_V_ALIGN_BOTTOM:
|
||||||
|
*y = *h - new_h;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ret = grub_error (GRUB_ERR_BUG, "Invalid v_align value");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
*h = new_h;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
grub_err_t
|
||||||
|
grub_video_bitmap_scale_proportional (struct grub_video_bitmap **dst,
|
||||||
|
int dst_width, int dst_height,
|
||||||
|
struct grub_video_bitmap *src,
|
||||||
|
enum grub_video_bitmap_scale_method
|
||||||
|
scale_method,
|
||||||
|
grub_video_bitmap_selection_method_t
|
||||||
|
selection_method,
|
||||||
|
grub_video_bitmap_v_align_t v_align,
|
||||||
|
grub_video_bitmap_h_align_t h_align)
|
||||||
|
{
|
||||||
|
*dst = 0;
|
||||||
|
grub_err_t ret = verify_source_bitmap(src);
|
||||||
|
if (ret != GRUB_ERR_NONE)
|
||||||
|
return ret;
|
||||||
|
if (dst_width <= 0 || dst_height <= 0)
|
||||||
|
return grub_error (GRUB_ERR_BUG,
|
||||||
|
"requested to scale to a size w/ a zero dimension");
|
||||||
|
|
||||||
|
ret = grub_video_bitmap_create (dst, dst_width, dst_height,
|
||||||
|
src->mode_info.blit_format);
|
||||||
|
if (ret != GRUB_ERR_NONE)
|
||||||
|
return ret; /* Error. */
|
||||||
|
|
||||||
|
int dx0 = 0;
|
||||||
|
int dy0 = 0;
|
||||||
|
int dw = dst_width;
|
||||||
|
int dh = dst_height;
|
||||||
|
int sx0 = 0;
|
||||||
|
int sy0 = 0;
|
||||||
|
int sw = src->mode_info.width;
|
||||||
|
int sh = src->mode_info.height;
|
||||||
|
|
||||||
|
switch (selection_method)
|
||||||
|
{
|
||||||
|
case GRUB_VIDEO_BITMAP_SELECTION_METHOD_CROP:
|
||||||
|
/* Comparing sw/sh VS dw/dh. */
|
||||||
|
if (sw * dh < dw * sh)
|
||||||
|
ret = make_v_align (&sy0, &sh, sw * dh / dw, v_align);
|
||||||
|
else
|
||||||
|
ret = make_h_align (&sx0, &sw, sh * dw / dh, h_align);
|
||||||
|
break;
|
||||||
|
case GRUB_VIDEO_BITMAP_SELECTION_METHOD_PADDING:
|
||||||
|
if (sw * dh < dw * sh)
|
||||||
|
ret = make_h_align (&dx0, &dw, sw * dh / sh, h_align);
|
||||||
|
else
|
||||||
|
ret = make_v_align (&dy0, &dh, sh * dw / sw, v_align);
|
||||||
|
break;
|
||||||
|
case GRUB_VIDEO_BITMAP_SELECTION_METHOD_FITWIDTH:
|
||||||
|
if (sw * dh < dw * sh)
|
||||||
|
ret = make_v_align (&sy0, &sh, sw * dh / dw, v_align);
|
||||||
|
else
|
||||||
|
ret = make_v_align (&dy0, &dh, sh * dw / sw, v_align);
|
||||||
|
break;
|
||||||
|
case GRUB_VIDEO_BITMAP_SELECTION_METHOD_FITHEIGHT:
|
||||||
|
if (sw * dh < dw * sh)
|
||||||
|
ret = make_h_align (&dx0, &dw, sw * dh / sh, h_align);
|
||||||
|
else
|
||||||
|
ret = make_h_align (&sx0, &sw, sh * dw / dh, h_align);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ret = grub_error (GRUB_ERR_BUG, "Invalid selection_method value");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret == GRUB_ERR_NONE)
|
||||||
|
{
|
||||||
|
/* Backup original data. */
|
||||||
|
int src_width_orig = src->mode_info.width;
|
||||||
|
int src_height_orig = src->mode_info.height;
|
||||||
|
grub_uint8_t *src_data_orig = src->data;
|
||||||
|
int dst_width_orig = (*dst)->mode_info.width;
|
||||||
|
int dst_height_orig = (*dst)->mode_info.height;
|
||||||
|
grub_uint8_t *dst_data_orig = (*dst)->data;
|
||||||
|
|
||||||
|
int dstride = (*dst)->mode_info.pitch;
|
||||||
|
int sstride = src->mode_info.pitch;
|
||||||
|
/* bytes_per_pixel is the same for both src and dst. */
|
||||||
|
int bytes_per_pixel = src->mode_info.bytes_per_pixel;
|
||||||
|
|
||||||
|
/* Crop src and dst. */
|
||||||
|
src->mode_info.width = sw;
|
||||||
|
src->mode_info.height = sh;
|
||||||
|
src->data = (grub_uint8_t *) src->data + sx0 * bytes_per_pixel
|
||||||
|
+ sy0 * sstride;
|
||||||
|
(*dst)->mode_info.width = dw;
|
||||||
|
(*dst)->mode_info.height = dh;
|
||||||
|
(*dst)->data = (grub_uint8_t *) (*dst)->data + dx0 * bytes_per_pixel
|
||||||
|
+ dy0 * dstride;
|
||||||
|
|
||||||
|
/* Scale our image. */
|
||||||
|
ret = grub_video_bitmap_scale (*dst, src, scale_method);
|
||||||
|
|
||||||
|
/* Restore original data. */
|
||||||
|
src->mode_info.width = src_width_orig;
|
||||||
|
src->mode_info.height = src_height_orig;
|
||||||
|
src->data = src_data_orig;
|
||||||
|
(*dst)->mode_info.width = dst_width_orig;
|
||||||
|
(*dst)->mode_info.height = dst_height_orig;
|
||||||
|
(*dst)->data = dst_data_orig;
|
||||||
|
}
|
||||||
|
|
||||||
if (ret == GRUB_ERR_NONE)
|
if (ret == GRUB_ERR_NONE)
|
||||||
{
|
{
|
||||||
|
@ -108,6 +286,46 @@ grub_video_bitmap_create_scaled (struct grub_video_bitmap **dst,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static grub_err_t
|
||||||
|
verify_bitmaps (struct grub_video_bitmap *dst, struct grub_video_bitmap *src)
|
||||||
|
{
|
||||||
|
/* Verify the simplifying assumptions. */
|
||||||
|
if (dst == 0 || src == 0)
|
||||||
|
return grub_error (GRUB_ERR_BUG, "null bitmap in scale function");
|
||||||
|
if (dst->mode_info.red_field_pos % 8 != 0
|
||||||
|
|| dst->mode_info.green_field_pos % 8 != 0
|
||||||
|
|| dst->mode_info.blue_field_pos % 8 != 0
|
||||||
|
|| dst->mode_info.reserved_field_pos % 8 != 0)
|
||||||
|
return grub_error (GRUB_ERR_BUG,
|
||||||
|
"dst format not supported");
|
||||||
|
if (src->mode_info.red_field_pos % 8 != 0
|
||||||
|
|| src->mode_info.green_field_pos % 8 != 0
|
||||||
|
|| src->mode_info.blue_field_pos % 8 != 0
|
||||||
|
|| src->mode_info.reserved_field_pos % 8 != 0)
|
||||||
|
return grub_error (GRUB_ERR_BUG,
|
||||||
|
"src format not supported");
|
||||||
|
if (dst->mode_info.red_field_pos != src->mode_info.red_field_pos
|
||||||
|
|| dst->mode_info.red_mask_size != src->mode_info.red_mask_size
|
||||||
|
|| dst->mode_info.green_field_pos != src->mode_info.green_field_pos
|
||||||
|
|| dst->mode_info.green_mask_size != src->mode_info.green_mask_size
|
||||||
|
|| dst->mode_info.blue_field_pos != src->mode_info.blue_field_pos
|
||||||
|
|| dst->mode_info.blue_mask_size != src->mode_info.blue_mask_size
|
||||||
|
|| dst->mode_info.reserved_field_pos !=
|
||||||
|
src->mode_info.reserved_field_pos
|
||||||
|
|| dst->mode_info.reserved_mask_size !=
|
||||||
|
src->mode_info.reserved_mask_size)
|
||||||
|
return grub_error (GRUB_ERR_BUG,
|
||||||
|
"dst and src not compatible");
|
||||||
|
if (dst->mode_info.bytes_per_pixel != src->mode_info.bytes_per_pixel)
|
||||||
|
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
||||||
|
"dst and src not compatible");
|
||||||
|
if (dst->mode_info.width == 0 || dst->mode_info.height == 0
|
||||||
|
|| src->mode_info.width == 0 || src->mode_info.height == 0)
|
||||||
|
return grub_error (GRUB_ERR_BUG, "bitmap has a zero dimension");
|
||||||
|
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
/* Nearest neighbor bitmap scaling algorithm.
|
/* Nearest neighbor bitmap scaling algorithm.
|
||||||
|
|
||||||
Copy the bitmap SRC to the bitmap DST, scaling the bitmap to fit the
|
Copy the bitmap SRC to the bitmap DST, scaling the bitmap to fit the
|
||||||
|
@ -121,39 +339,9 @@ grub_video_bitmap_create_scaled (struct grub_video_bitmap **dst,
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
scale_nn (struct grub_video_bitmap *dst, struct grub_video_bitmap *src)
|
scale_nn (struct grub_video_bitmap *dst, struct grub_video_bitmap *src)
|
||||||
{
|
{
|
||||||
/* Verify the simplifying assumptions. */
|
grub_err_t err = verify_bitmaps(dst, src);
|
||||||
if (dst == 0 || src == 0)
|
if (err != GRUB_ERR_NONE)
|
||||||
return grub_error (GRUB_ERR_BUG, "null bitmap in scale_nn");
|
return err;
|
||||||
if (dst->mode_info.red_field_pos % 8 != 0
|
|
||||||
|| dst->mode_info.green_field_pos % 8 != 0
|
|
||||||
|| dst->mode_info.blue_field_pos % 8 != 0
|
|
||||||
|| dst->mode_info.reserved_field_pos % 8 != 0)
|
|
||||||
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
|
||||||
"dst format not supported");
|
|
||||||
if (src->mode_info.red_field_pos % 8 != 0
|
|
||||||
|| src->mode_info.green_field_pos % 8 != 0
|
|
||||||
|| src->mode_info.blue_field_pos % 8 != 0
|
|
||||||
|| src->mode_info.reserved_field_pos % 8 != 0)
|
|
||||||
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
|
||||||
"src format not supported");
|
|
||||||
if (dst->mode_info.red_field_pos != src->mode_info.red_field_pos
|
|
||||||
|| dst->mode_info.red_mask_size != src->mode_info.red_mask_size
|
|
||||||
|| dst->mode_info.green_field_pos != src->mode_info.green_field_pos
|
|
||||||
|| dst->mode_info.green_mask_size != src->mode_info.green_mask_size
|
|
||||||
|| dst->mode_info.blue_field_pos != src->mode_info.blue_field_pos
|
|
||||||
|| dst->mode_info.blue_mask_size != src->mode_info.blue_mask_size
|
|
||||||
|| dst->mode_info.reserved_field_pos !=
|
|
||||||
src->mode_info.reserved_field_pos
|
|
||||||
|| dst->mode_info.reserved_mask_size !=
|
|
||||||
src->mode_info.reserved_mask_size)
|
|
||||||
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
|
||||||
"dst and src not compatible");
|
|
||||||
if (dst->mode_info.bytes_per_pixel != src->mode_info.bytes_per_pixel)
|
|
||||||
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
|
||||||
"dst and src not compatible");
|
|
||||||
if (dst->mode_info.width == 0 || dst->mode_info.height == 0
|
|
||||||
|| src->mode_info.width == 0 || src->mode_info.height == 0)
|
|
||||||
return grub_error (GRUB_ERR_BUG, "bitmap has a zero dimension");
|
|
||||||
|
|
||||||
grub_uint8_t *ddata = dst->data;
|
grub_uint8_t *ddata = dst->data;
|
||||||
grub_uint8_t *sdata = src->data;
|
grub_uint8_t *sdata = src->data;
|
||||||
|
@ -208,35 +396,9 @@ scale_nn (struct grub_video_bitmap *dst, struct grub_video_bitmap *src)
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
scale_bilinear (struct grub_video_bitmap *dst, struct grub_video_bitmap *src)
|
scale_bilinear (struct grub_video_bitmap *dst, struct grub_video_bitmap *src)
|
||||||
{
|
{
|
||||||
/* Verify the simplifying assumptions. */
|
grub_err_t err = verify_bitmaps(dst, src);
|
||||||
if (dst == 0 || src == 0)
|
if (err != GRUB_ERR_NONE)
|
||||||
return grub_error (GRUB_ERR_BUG, "null bitmap in scale func");
|
return err;
|
||||||
if (dst->mode_info.red_field_pos % 8 != 0
|
|
||||||
|| dst->mode_info.green_field_pos % 8 != 0
|
|
||||||
|| dst->mode_info.blue_field_pos % 8 != 0
|
|
||||||
|| dst->mode_info.reserved_field_pos % 8 != 0)
|
|
||||||
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "dst format not supported");
|
|
||||||
if (src->mode_info.red_field_pos % 8 != 0
|
|
||||||
|| src->mode_info.green_field_pos % 8 != 0
|
|
||||||
|| src->mode_info.blue_field_pos % 8 != 0
|
|
||||||
|| src->mode_info.reserved_field_pos % 8 != 0)
|
|
||||||
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "src format not supported");
|
|
||||||
if (dst->mode_info.red_field_pos != src->mode_info.red_field_pos
|
|
||||||
|| dst->mode_info.red_mask_size != src->mode_info.red_mask_size
|
|
||||||
|| dst->mode_info.green_field_pos != src->mode_info.green_field_pos
|
|
||||||
|| dst->mode_info.green_mask_size != src->mode_info.green_mask_size
|
|
||||||
|| dst->mode_info.blue_field_pos != src->mode_info.blue_field_pos
|
|
||||||
|| dst->mode_info.blue_mask_size != src->mode_info.blue_mask_size
|
|
||||||
|| dst->mode_info.reserved_field_pos !=
|
|
||||||
src->mode_info.reserved_field_pos
|
|
||||||
|| dst->mode_info.reserved_mask_size !=
|
|
||||||
src->mode_info.reserved_mask_size)
|
|
||||||
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "dst and src not compatible");
|
|
||||||
if (dst->mode_info.bytes_per_pixel != src->mode_info.bytes_per_pixel)
|
|
||||||
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "dst and src not compatible");
|
|
||||||
if (dst->mode_info.width == 0 || dst->mode_info.height == 0
|
|
||||||
|| src->mode_info.width == 0 || src->mode_info.height == 0)
|
|
||||||
return grub_error (GRUB_ERR_BUG, "bitmap has a zero dimension");
|
|
||||||
|
|
||||||
grub_uint8_t *ddata = dst->data;
|
grub_uint8_t *ddata = dst->data;
|
||||||
grub_uint8_t *sdata = src->data;
|
grub_uint8_t *sdata = src->data;
|
||||||
|
|
|
@ -38,6 +38,29 @@ enum grub_video_bitmap_scale_method
|
||||||
GRUB_VIDEO_BITMAP_SCALE_METHOD_BILINEAR
|
GRUB_VIDEO_BITMAP_SCALE_METHOD_BILINEAR
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef enum grub_video_bitmap_selection_method
|
||||||
|
{
|
||||||
|
GRUB_VIDEO_BITMAP_SELECTION_METHOD_STRETCH,
|
||||||
|
GRUB_VIDEO_BITMAP_SELECTION_METHOD_CROP,
|
||||||
|
GRUB_VIDEO_BITMAP_SELECTION_METHOD_PADDING,
|
||||||
|
GRUB_VIDEO_BITMAP_SELECTION_METHOD_FITWIDTH,
|
||||||
|
GRUB_VIDEO_BITMAP_SELECTION_METHOD_FITHEIGHT
|
||||||
|
} grub_video_bitmap_selection_method_t;
|
||||||
|
|
||||||
|
typedef enum grub_video_bitmap_v_align
|
||||||
|
{
|
||||||
|
GRUB_VIDEO_BITMAP_V_ALIGN_TOP,
|
||||||
|
GRUB_VIDEO_BITMAP_V_ALIGN_CENTER,
|
||||||
|
GRUB_VIDEO_BITMAP_V_ALIGN_BOTTOM
|
||||||
|
} grub_video_bitmap_v_align_t;
|
||||||
|
|
||||||
|
typedef enum grub_video_bitmap_h_align
|
||||||
|
{
|
||||||
|
GRUB_VIDEO_BITMAP_H_ALIGN_LEFT,
|
||||||
|
GRUB_VIDEO_BITMAP_H_ALIGN_CENTER,
|
||||||
|
GRUB_VIDEO_BITMAP_H_ALIGN_RIGHT
|
||||||
|
} grub_video_bitmap_h_align_t;
|
||||||
|
|
||||||
grub_err_t
|
grub_err_t
|
||||||
EXPORT_FUNC (grub_video_bitmap_create_scaled) (struct grub_video_bitmap **dst,
|
EXPORT_FUNC (grub_video_bitmap_create_scaled) (struct grub_video_bitmap **dst,
|
||||||
int dst_width, int dst_height,
|
int dst_width, int dst_height,
|
||||||
|
@ -46,4 +69,17 @@ EXPORT_FUNC (grub_video_bitmap_create_scaled) (struct grub_video_bitmap **dst,
|
||||||
grub_video_bitmap_scale_method
|
grub_video_bitmap_scale_method
|
||||||
scale_method);
|
scale_method);
|
||||||
|
|
||||||
|
grub_err_t
|
||||||
|
EXPORT_FUNC (grub_video_bitmap_scale_proportional)
|
||||||
|
(struct grub_video_bitmap **dst,
|
||||||
|
int dst_width, int dst_height,
|
||||||
|
struct grub_video_bitmap *src,
|
||||||
|
enum grub_video_bitmap_scale_method
|
||||||
|
scale_method,
|
||||||
|
grub_video_bitmap_selection_method_t
|
||||||
|
selection_method,
|
||||||
|
grub_video_bitmap_v_align_t v_align,
|
||||||
|
grub_video_bitmap_h_align_t h_align);
|
||||||
|
|
||||||
|
|
||||||
#endif /* ! GRUB_BITMAP_SCALE_HEADER */
|
#endif /* ! GRUB_BITMAP_SCALE_HEADER */
|
||||||
|
|
|
@ -75,6 +75,7 @@ int grub_font_get_string_width (grub_font_t font,
|
||||||
|
|
||||||
#include <grub/video.h>
|
#include <grub/video.h>
|
||||||
#include <grub/bitmap.h>
|
#include <grub/bitmap.h>
|
||||||
|
#include <grub/bitmap_scale.h>
|
||||||
#include <grub/gui.h>
|
#include <grub/gui.h>
|
||||||
#include <grub/gfxwidgets.h>
|
#include <grub/gfxwidgets.h>
|
||||||
#include <grub/icon_manager.h>
|
#include <grub/icon_manager.h>
|
||||||
|
@ -94,7 +95,11 @@ struct grub_gfxmenu_view
|
||||||
grub_video_rgba_color_t title_color;
|
grub_video_rgba_color_t title_color;
|
||||||
grub_video_rgba_color_t message_color;
|
grub_video_rgba_color_t message_color;
|
||||||
grub_video_rgba_color_t message_bg_color;
|
grub_video_rgba_color_t message_bg_color;
|
||||||
struct grub_video_bitmap *desktop_image;
|
struct grub_video_bitmap *raw_desktop_image;
|
||||||
|
struct grub_video_bitmap *scaled_desktop_image;
|
||||||
|
grub_video_bitmap_selection_method_t desktop_image_scale_method;
|
||||||
|
grub_video_bitmap_h_align_t desktop_image_h_align;
|
||||||
|
grub_video_bitmap_v_align_t desktop_image_v_align;
|
||||||
grub_video_rgba_color_t desktop_color;
|
grub_video_rgba_color_t desktop_color;
|
||||||
grub_gfxmenu_box_t terminal_box;
|
grub_gfxmenu_box_t terminal_box;
|
||||||
char *title_text;
|
char *title_text;
|
||||||
|
|
Loading…
Reference in a new issue