From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with archive (Exim 4.43) id 1KaQ7p-0003nW-Sf for mharc-grub-devel@gnu.org; Tue, 02 Sep 2008 03:16:29 -0400 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1KaQ7n-0003nR-Jv for grub-devel@gnu.org; Tue, 02 Sep 2008 03:16:27 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1KaQ7l-0003mz-BZ for grub-devel@gnu.org; Tue, 02 Sep 2008 03:16:26 -0400 Received: from [199.232.76.173] (port=49200 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1KaQ7l-0003mm-6a for grub-devel@gnu.org; Tue, 02 Sep 2008 03:16:25 -0400 Received: from mx20.gnu.org ([199.232.41.8]:3031) by monty-python.gnu.org with esmtps (TLS-1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.60) (envelope-from ) id 1KaQ7k-0003d3-Q7 for grub-devel@gnu.org; Tue, 02 Sep 2008 03:16:25 -0400 Received: from mandel.name ([85.214.43.148]) by mx20.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1KaQ7i-0000NF-H1 for grub-devel@gnu.org; Tue, 02 Sep 2008 03:16:23 -0400 Received: from gucky.stanford.edu ([171.64.56.203]) by mandel.name with esmtpsa (TLSv1:AES256-SHA:256) (Exim 4.63) (envelope-from ) id 1KaQ7f-0003bS-D3; Tue, 02 Sep 2008 09:16:19 +0200 Message-ID: <48BCE865.1010505@mandel.name> Date: Tue, 02 Sep 2008 00:16:53 -0700 From: Olaf Mandel User-Agent: IceDove 1.5.0.14eol (X11/20080724) MIME-Version: 1.0 To: Colin D Bennett References: <48B75500.9080706@mandel.name> <48B80E15.1070103@nic.fi> <48B8D666.5040502@mandel.name> <20080831084613.51ea00d8@gamma.lan> In-Reply-To: <20080831084613.51ea00d8@gamma.lan> X-Enigmail-Version: 0.94.2.0 OpenPGP: id=33398848 Content-Type: multipart/signed; micalg=pgp-sha1; protocol="application/pgp-signature"; boundary="------------enig853156006A0F5FEF850D6E17" X-SA-Exim-Connect-IP: 171.64.56.203 X-SA-Exim-Rcpt-To: colin@gibibit.com, grub-devel@gnu.org X-SA-Exim-Mail-From: olaf@mandel.name X-SA-Exim-Scanned: No (on mandel.name); SAEximRunCond expanded to false X-detected-kernel: by mx20.gnu.org: Linux 2.6, seldom 2.4 (older, 4) X-detected-kernel: by monty-python.gnu.org: Linux 2.6, seldom 2.4 (older, 4) Cc: The development of GRUB 2 Subject: Re: [patch] background_image: image centering and scaling X-BeenThere: grub-devel@gnu.org X-Mailman-Version: 2.1.5 Precedence: list Reply-To: The development of GRUB 2 List-Id: The development of GRUB 2 List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 02 Sep 2008 07:16:27 -0000 This is an OpenPGP/MIME signed message (RFC 2440 and 3156) --------------enig853156006A0F5FEF850D6E17 Content-Type: multipart/mixed; boundary="------------050505060809090509000108" This is a multi-part message in MIME format. --------------050505060809090509000108 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable Colin D Bennett schrieb: -Snipp- > Thanks for your work! It would be great if you wanted to enhance my > code by adding a preserve-aspect-ratio mode; currently my > background_image command scales to fit the screen without regard for > the image's original aspect ratio. [...] -Snipp- Hello, I have a patch that adds one more setting for --mode that allows the picture to be scaled while keeping the aspectratio constant: fit. Also, there is now a second option --pos / -p that has 9 possible settings: tl, t, tr, l, c, r, bl, b, br. The center-position is the default. Start off with SVN r1845, apply the GsoC patch 09_bitmap-scaling.patch and then the one attached here. The patch does not work correctly for me though: the string comparisons, e.g.: grub_strcmp (state[BACKGROUND_CMD_ARGINDEX_MODE].arg, "stretch") do not work reliable. On some occasions, the command works as expected, but often the command goes with the default value, even if something else was specified. This appears to be random... For example, the command= : background_image --mode=3Dnormal --pos=3Dtl /grub/grub.png will often display the image fitted into the larger screen (wrong), and sometimes as a small picture in the upper left corner (correct). I have had no luck trying to output the content of the variables on the screen or the like... What would the correct code for that be? I hope someone finds the bug or can tell me how to continue about debugging it myself. Best regards, Olaf Mandel --=20 Olaf Mandel PGP key: 1024D/33398848 2002-09-19 Fingerprint: 0E33 BEA6 1A71 9C5E 62BD FC0E 99A7 D2C6 3339 8848 --------------050505060809090509000108 Content-Type: text/x-patch; name="new_centering+scaling.patch" Content-Transfer-Encoding: quoted-printable Content-Disposition: inline; filename="new_centering+scaling.patch" diff -urN grub2/include/grub/bitmap_scale.h grub3/include/grub/bitmap_sca= le.h --- grub2/include/grub/bitmap_scale.h 2008-09-01 19:05:55.000000000 -0700= +++ grub3/include/grub/bitmap_scale.h 2008-09-01 22:26:35.000000000 -0700= @@ -51,4 +51,11 @@ enum grub_video_bitmap_scale_method scale_me= thod); =20 +grub_err_t +grub_video_bitmap_create_fitted (struct grub_video_bitmap **dst, + int max_width, int max_height, + struct grub_video_bitmap *src, + enum + grub_video_bitmap_scale_method scale_me= thod); + #endif /* ! GRUB_BITMAP_SCALE_HEADER */ diff -urN grub2/term/gfxterm.c grub3/term/gfxterm.c --- grub2/term/gfxterm.c 2008-09-01 19:05:55.000000000 -0700 +++ grub3/term/gfxterm.c 2008-09-01 23:58:24.000000000 -0700 @@ -113,6 +113,8 @@ =20 static struct grub_video_render_target *text_layer; =20 +static int bitmap_x; +static int bitmap_y; static unsigned int bitmap_width; static unsigned int bitmap_height; static struct grub_video_bitmap *bitmap; @@ -514,43 +516,96 @@ { /* Render bitmap as background. */ grub_video_blit_bitmap (bitmap, GRUB_VIDEO_BLIT_REPLACE, x, y,=20 - x, y,=20 + x - bitmap_x, y - bitmap_y, width, height); =20 /* If bitmap is smaller than requested blit area, use background=20 color. */ color =3D virtual_screen.bg_color; =20 + /* Fill top side of the bitmap (including corners) if needed. */ + if ((int)y < bitmap_y) + { + int h =3D height; + =20 + if ((int)y + h > bitmap_y) + { + h =3D bitmap_y - y; + } + =20 + /* Render background layer. */ + grub_video_fill_rect (color, x, y, width, h); =20 + } + + /* Fill left side of the bitmap if needed. */ + if (((int)x < bitmap_x) && ((int)y < bitmap_y + (int)bitmap_height= ) + && ((int)(y + height) > bitmap_y)) + { + int w =3D width; + int h =3D height; + unsigned int ty =3D y; + + if ((int)x + w > bitmap_x) + { + w =3D bitmap_x - x; + } + + if ((int)ty < bitmap_y) + { + h -=3D bitmap_y - ty; + ty =3D bitmap_y; + } + =20 + if (ty + h > bitmap_y + bitmap_height) + { + h =3D bitmap_y + bitmap_height - ty; + } + =20 + /* Render background layer. */ + grub_video_fill_rect (color, x, ty, w, h); =20 + } +=20 /* Fill right side of the bitmap if needed. */ - if ((x + width >=3D bitmap_width) && (y < bitmap_height)) + if ((x + width > bitmap_x + bitmap_width) + && ((int)y < bitmap_y + (int)bitmap_height) + && ((int)(y + height) > bitmap_y)) { - int w =3D (x + width) - bitmap_width; + int w =3D width; int h =3D height; unsigned int tx =3D x; + unsigned int ty =3D y; =20 - if (y + height >=3D bitmap_height) + if (tx < bitmap_x + bitmap_width) { - h =3D bitmap_height - y; + w -=3D bitmap_x + bitmap_width - tx; + tx =3D bitmap_x + bitmap_width; } =20 - if (bitmap_width > tx) + if ((int)ty < bitmap_y) { - tx =3D bitmap_width; + h -=3D bitmap_y - ty; + ty =3D bitmap_y; } =20 + if (ty + h > bitmap_y + bitmap_height) + { + h =3D bitmap_y + bitmap_height - ty; + } + /* Render background layer. */ - grub_video_fill_rect (color, tx, y, w, h); =20 + grub_video_fill_rect (color, tx, ty, w, h); =20 } =20 - /* Fill bottom side of the bitmap if needed. */ - if (y + height >=3D bitmap_height) + /* Fill bottom side of the bitmap (including corners) if needed. = */ + if (y + height > bitmap_y + bitmap_height) { - int h =3D (y + height) - bitmap_height; + int h =3D height; unsigned int ty =3D y; =20 - if (bitmap_height > ty) + if (ty < bitmap_y + bitmap_height) { - ty =3D bitmap_height; + h -=3D bitmap_y + bitmap_height - ty; + ty =3D bitmap_y + bitmap_height; } =20 /* Render background layer. */ @@ -1014,10 +1069,12 @@ =20 /* Option array indices. */ #define BACKGROUND_CMD_ARGINDEX_MODE 0 +#define BACKGROUND_CMD_ARGINDEX_POS 1 =20 static const struct grub_arg_option background_image_cmd_options[] =3D {= - {"mode", 'm', 0, "Background image mode (`stretch', `normal').", 0,=20 + {"mode", 'm', 0, "Background image mode ([`fit'], `stretch', `normal')= =2E", 0,=20 ARG_TYPE_STRING}, + {"pos", 'p', 0, "Position of image (`tl', `t', `tr', `l', [`c'], `r', = `bl', `b', `br').", 0, ARG_TYPE_STRING}, {0, 0, 0, 0, 0, 0} }; =20 @@ -1049,30 +1106,6 @@ if (grub_errno !=3D GRUB_ERR_NONE) return grub_errno; =20 - /* Determine if the bitmap should be scaled to fit the screen. */ - if (!state[BACKGROUND_CMD_ARGINDEX_MODE].set - || grub_strcmp (state[BACKGROUND_CMD_ARGINDEX_MODE].arg, - "stretch") =3D=3D 0) - { - if (mode_info.width !=3D grub_video_bitmap_get_width (bitmap) - || mode_info.height !=3D grub_video_bitmap_get_height (bit= map))=20 - { - struct grub_video_bitmap *scaled_bitmap; - grub_video_bitmap_create_scaled (&scaled_bitmap, - mode_info.width,=20 - mode_info.height, - bitmap, - GRUB_VIDEO_BITMAP_SCALE_ME= THOD_BEST); - if (grub_errno =3D=3D GRUB_ERR_NONE) - { - /* Replace the original bitmap with the scaled one. */= - grub_video_bitmap_destroy (bitmap); - bitmap =3D scaled_bitmap; - } - } - } - - /* If bitmap was loaded correctly, display it. */ if (bitmap) { @@ -1080,6 +1113,119 @@ bitmap_width =3D grub_video_bitmap_get_width (bitmap); bitmap_height =3D grub_video_bitmap_get_height (bitmap); =20 + /* Determine if the bitmap should be scaled to fit the screen. *= / + if (mode_info.width !=3D bitmap_width + || mode_info.height !=3D bitmap_height)=20 + { + if (state[BACKGROUND_CMD_ARGINDEX_MODE].set + && grub_strcmp (state[BACKGROUND_CMD_ARGINDEX_MODE].arg,= + "stretch") =3D=3D 0) + { + struct grub_video_bitmap *scaled_bitmap; + grub_video_bitmap_create_scaled (&scaled_bitmap, + mode_info.width,=20 + mode_info.height, + bitmap, + GRUB_VIDEO_BITMAP_SCAL= E_METHOD_BEST); + if (grub_errno =3D=3D GRUB_ERR_NONE) + { + /* Replace the original bitmap with the scaled one= =2E */ + grub_video_bitmap_destroy (bitmap); + bitmap =3D scaled_bitmap; + } + } + else if (state[BACKGROUND_CMD_ARGINDEX_MODE].set + && grub_strcmp (state[BACKGROUND_CMD_ARGINDEX_MODE]= =2Earg, + "normal") =3D=3D 0) + { + /* There is nothing to do in this case */ + } + else /* This is for mode=3D"fit", for unknown values of mode= and if no + mode parameter is given. */ + { + struct grub_video_bitmap *fitted_bitmap; + grub_video_bitmap_create_fitted (&fitted_bitmap, + mode_info.width,=20 + mode_info.height, + bitmap, + GRUB_VIDEO_BITMAP_SCAL= E_METHOD_BEST); + if (grub_errno =3D=3D GRUB_ERR_NONE) + { + /* Replace the original bitmap with the fitted one= =2E */ + grub_video_bitmap_destroy (bitmap); + bitmap =3D fitted_bitmap; + } + } + + /* Re-Determine bitmap dimensions. */ + bitmap_width =3D grub_video_bitmap_get_width (bitmap); + bitmap_height =3D grub_video_bitmap_get_height (bitmap); + } + + /* Determine where to place the bitmap on the screen. */ + if (state[BACKGROUND_CMD_ARGINDEX_POS].set + && grub_strcmp (state[BACKGROUND_CMD_ARGINDEX_POS].arg, + "tl") =3D=3D 0) + { + bitmap_x =3D 0; + bitmap_y =3D 0; + } + else if (state[BACKGROUND_CMD_ARGINDEX_POS].set + && grub_strcmp (state[BACKGROUND_CMD_ARGINDEX_POS].arg,= + "t") =3D=3D 0) + { + bitmap_x =3D (int)(mode_info.width - bitmap_width) / 2; + bitmap_y =3D 0; + } + else if (state[BACKGROUND_CMD_ARGINDEX_POS].set + && grub_strcmp (state[BACKGROUND_CMD_ARGINDEX_POS].arg,= + "tr") =3D=3D 0) + { + bitmap_x =3D mode_info.width - bitmap_width; + bitmap_y =3D 0; + } + else if (state[BACKGROUND_CMD_ARGINDEX_POS].set + && grub_strcmp (state[BACKGROUND_CMD_ARGINDEX_POS].arg,= + "l") =3D=3D 0) + { + bitmap_x =3D 0; + bitmap_y =3D (int)(mode_info.height - bitmap_height) / 2; + } + else if (state[BACKGROUND_CMD_ARGINDEX_POS].set + && grub_strcmp (state[BACKGROUND_CMD_ARGINDEX_POS].arg,= + "r") =3D=3D 0) + { + bitmap_x =3D mode_info.width - bitmap_width; + bitmap_y =3D (int)(mode_info.height - bitmap_height) / 2; + } + else if (state[BACKGROUND_CMD_ARGINDEX_POS].set + && grub_strcmp (state[BACKGROUND_CMD_ARGINDEX_POS].arg,= + "bl") =3D=3D 0) + { + bitmap_x =3D 0; + bitmap_y =3D mode_info.height - bitmap_height; + } + else if (state[BACKGROUND_CMD_ARGINDEX_POS].set + && grub_strcmp (state[BACKGROUND_CMD_ARGINDEX_POS].arg,= + "b") =3D=3D 0) + { + bitmap_x =3D (int)(mode_info.width - bitmap_width) / 2; + bitmap_y =3D mode_info.height - bitmap_height; + } + else if (state[BACKGROUND_CMD_ARGINDEX_POS].set + && grub_strcmp (state[BACKGROUND_CMD_ARGINDEX_POS].arg,= + "br") =3D=3D 0) + { + bitmap_x =3D mode_info.width - bitmap_width; + bitmap_y =3D mode_info.height - bitmap_height; + } + else /* This is for pos=3D"c", for unknown values of pos and if = no + pos parameter is given. */ + { + bitmap_x =3D (int)(mode_info.width - bitmap_width) / 2; + bitmap_y =3D (int)(mode_info.height - bitmap_height) / 2; + } + /* Mark whole screen as dirty. */ dirty_region_reset (); dirty_region_add (0, 0, mode_info.width, mode_info.height); diff -urN grub2/video/bitmap_scale.c grub3/video/bitmap_scale.c --- grub2/video/bitmap_scale.c 2008-09-01 19:05:55.000000000 -0700 +++ grub3/video/bitmap_scale.c 2008-09-01 22:26:28.000000000 -0700 @@ -99,3 +99,49 @@ return ret; } } + +/*=20 + * This function creates a new scaled version of the bitmap SRC. The ne= w + * bitmap has the same aspect ratio as SRC and is smaller or equal in si= ze + * to MAX_WIDTH and MAX_HEIGHT. One of these two dimensions is exactly = right, + * the other may be smaller in order to preserve the aspect ratio. The = scaling + * algorithm is given by SCALE_METHOD. + * + * This function internally uses grub_video_bitmap_create_scaled(), so t= he + * error handling is identical to that function. Also, all limitations = of + * *_scaled() also apply to *_fitted(). + */ +grub_err_t +grub_video_bitmap_create_fitted (struct grub_video_bitmap **dst, + int max_width, int max_height, + struct grub_video_bitmap *src, + enum grub_video_bitmap_scale_method + scale_method) +{ + int w; + int h; + int width =3D max_width; + int height =3D max_height; + + /* Verify the simplifying assumptions and get src dimensions. */ + if (src =3D=3D 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "null src bitmap in grub_video_bitmap_create_fitt= ed"); + w =3D src->mode_info.width; + h =3D src->mode_info.height; + if (max_width <=3D 0 || max_height <=3D 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "requested to fit to a size w/ a zero dimension")= ; + + /* Is the new region wider than the old bitmap? Use products instead o= f + * fractions. */ + if (w * max_height < max_width * h) + width =3D w * max_height / h; + + /* Is the new region higher than the old bitmap? */ + if (w * max_height > max_width * h) + height =3D h * max_width / w; + + return grub_video_bitmap_create_scaled (dst, width, height, src, + scale_method); +} --------------050505060809090509000108-- --------------enig853156006A0F5FEF850D6E17 Content-Type: application/pgp-signature; name="signature.asc" Content-Description: OpenPGP digital signature Content-Disposition: attachment; filename="signature.asc" -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.9 (GNU/Linux) iEYEARECAAYFAki86GoACgkQmafSxjM5iEjtlQCeKu+NV3HTv213+4469vSlIMdo cHwAn255EtOC9B9wuaM2ce6f96wv+DNW =w1uU -----END PGP SIGNATURE----- --------------enig853156006A0F5FEF850D6E17--