1 /* widget_box.c - Pixmap-stylized box widget. */
3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 2008,2009 Free Software Foundation, Inc.
6 * GRUB is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * GRUB is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
20 #include <grub/types.h>
21 #include <grub/misc.h>
24 #include <grub/video.h>
25 #include <grub/bitmap.h>
26 #include <grub/bitmap_scale.h>
27 #include <grub/gfxwidgets.h>
31 BOX_PIXMAP_NW
, BOX_PIXMAP_NE
, BOX_PIXMAP_SE
, BOX_PIXMAP_SW
,
32 BOX_PIXMAP_N
, BOX_PIXMAP_E
, BOX_PIXMAP_S
, BOX_PIXMAP_W
,
36 static const char *box_pixmap_names
[] = {
38 "nw", "ne", "se", "sw",
45 #define BOX_NUM_PIXMAPS (sizeof(box_pixmap_names)/sizeof(*box_pixmap_names))
48 get_height (struct grub_video_bitmap
*bitmap
)
51 return grub_video_bitmap_get_height (bitmap
);
57 get_width (struct grub_video_bitmap
*bitmap
)
60 return grub_video_bitmap_get_width (bitmap
);
66 blit (grub_gfxmenu_box_t self
, int pixmap_index
, int x
, int y
)
68 struct grub_video_bitmap
*bitmap
;
69 bitmap
= self
->scaled_pixmaps
[pixmap_index
];
72 grub_video_blit_bitmap (bitmap
, GRUB_VIDEO_BLIT_BLEND
,
74 grub_video_bitmap_get_width (bitmap
),
75 grub_video_bitmap_get_height (bitmap
));
79 draw (grub_gfxmenu_box_t self
, int x
, int y
)
90 height_n
= get_height (self
->scaled_pixmaps
[BOX_PIXMAP_N
]);
91 height_s
= get_height (self
->scaled_pixmaps
[BOX_PIXMAP_S
]);
92 height_e
= get_height (self
->scaled_pixmaps
[BOX_PIXMAP_E
]);
93 height_w
= get_height (self
->scaled_pixmaps
[BOX_PIXMAP_W
]);
94 width_n
= get_width (self
->scaled_pixmaps
[BOX_PIXMAP_N
]);
95 width_s
= get_width (self
->scaled_pixmaps
[BOX_PIXMAP_S
]);
96 width_e
= get_width (self
->scaled_pixmaps
[BOX_PIXMAP_E
]);
97 width_w
= get_width (self
->scaled_pixmaps
[BOX_PIXMAP_W
]);
100 blit (self
, BOX_PIXMAP_N
, x
+ width_w
, y
);
101 blit (self
, BOX_PIXMAP_S
, x
+ width_w
, y
+ height_n
+ self
->content_height
);
102 blit (self
, BOX_PIXMAP_E
, x
+ width_w
+ self
->content_width
, y
+ height_n
);
103 blit (self
, BOX_PIXMAP_W
, x
, y
+ height_n
);
106 blit (self
, BOX_PIXMAP_NW
, x
, y
);
107 blit (self
, BOX_PIXMAP_NE
, x
+ width_w
+ self
->content_width
, y
);
108 blit (self
, BOX_PIXMAP_SE
,
109 x
+ width_w
+ self
->content_width
,
110 y
+ height_n
+ self
->content_height
);
111 blit (self
, BOX_PIXMAP_SW
, x
, y
+ height_n
+ self
->content_height
);
114 blit (self
, BOX_PIXMAP_CENTER
, x
+ width_w
, y
+ height_n
);
118 scale_pixmap (grub_gfxmenu_box_t self
, int i
, int w
, int h
)
120 struct grub_video_bitmap
**scaled
= &self
->scaled_pixmaps
[i
];
121 struct grub_video_bitmap
*raw
= self
->raw_pixmaps
[i
];
127 w
= grub_video_bitmap_get_width (raw
);
129 h
= grub_video_bitmap_get_height (raw
);
132 || ((int) grub_video_bitmap_get_width (*scaled
) != w
)
133 || ((int) grub_video_bitmap_get_height (*scaled
) != h
))
137 grub_video_bitmap_destroy (*scaled
);
141 /* Don't try to create a bitmap with a zero dimension. */
142 if (w
!= 0 && h
!= 0)
143 grub_video_bitmap_create_scaled (scaled
, w
, h
, raw
,
144 GRUB_VIDEO_BITMAP_SCALE_METHOD_BEST
);
145 if (grub_errno
!= GRUB_ERR_NONE
)
148 grub_error (grub_errno
,
149 "failed to scale bitmap for styled box pixmap #%d", i
);
157 set_content_size (grub_gfxmenu_box_t self
,
158 int width
, int height
)
160 self
->content_width
= width
;
161 self
->content_height
= height
;
163 /* Resize sides to match the width and height. */
164 /* It is assumed that the corners width/height match the adjacent sides. */
166 /* Resize N and S sides to match width. */
167 if (scale_pixmap(self
, BOX_PIXMAP_N
, width
, -1) != GRUB_ERR_NONE
)
169 if (scale_pixmap(self
, BOX_PIXMAP_S
, width
, -1) != GRUB_ERR_NONE
)
172 /* Resize E and W sides to match height. */
173 if (scale_pixmap(self
, BOX_PIXMAP_E
, -1, height
) != GRUB_ERR_NONE
)
175 if (scale_pixmap(self
, BOX_PIXMAP_W
, -1, height
) != GRUB_ERR_NONE
)
178 /* Don't scale the corners--they are assumed to match the sides. */
179 if (scale_pixmap(self
, BOX_PIXMAP_NW
, -1, -1) != GRUB_ERR_NONE
)
181 if (scale_pixmap(self
, BOX_PIXMAP_SW
, -1, -1) != GRUB_ERR_NONE
)
183 if (scale_pixmap(self
, BOX_PIXMAP_NE
, -1, -1) != GRUB_ERR_NONE
)
185 if (scale_pixmap(self
, BOX_PIXMAP_SE
, -1, -1) != GRUB_ERR_NONE
)
188 /* Scale the center area. */
189 if (scale_pixmap(self
, BOX_PIXMAP_CENTER
, width
, height
) != GRUB_ERR_NONE
)
194 get_left_pad (grub_gfxmenu_box_t self
)
196 return get_width (self
->raw_pixmaps
[BOX_PIXMAP_W
]);
200 get_top_pad (grub_gfxmenu_box_t self
)
202 return get_height (self
->raw_pixmaps
[BOX_PIXMAP_N
]);
206 get_right_pad (grub_gfxmenu_box_t self
)
208 return get_width (self
->raw_pixmaps
[BOX_PIXMAP_E
]);
212 get_bottom_pad (grub_gfxmenu_box_t self
)
214 return get_height (self
->raw_pixmaps
[BOX_PIXMAP_S
]);
218 destroy (grub_gfxmenu_box_t self
)
221 for (i
= 0; i
< BOX_NUM_PIXMAPS
; i
++)
223 if (self
->raw_pixmaps
[i
])
224 grub_video_bitmap_destroy(self
->raw_pixmaps
[i
]);
225 self
->raw_pixmaps
[i
] = 0;
227 if (self
->scaled_pixmaps
[i
])
228 grub_video_bitmap_destroy(self
->scaled_pixmaps
[i
]);
229 self
->scaled_pixmaps
[i
] = 0;
231 grub_free (self
->raw_pixmaps
);
232 self
->raw_pixmaps
= 0;
233 grub_free (self
->scaled_pixmaps
);
234 self
->scaled_pixmaps
= 0;
236 /* Free self: must be the last step! */
241 /* Create a new box. If PIXMAPS_PREFIX and PIXMAPS_SUFFIX are both non-null,
242 then an attempt is made to load the north, south, east, west, northwest,
243 northeast, southeast, southwest, and center pixmaps.
244 If either PIXMAPS_PREFIX or PIXMAPS_SUFFIX is 0, then no pixmaps are
245 loaded, and the box has zero-width borders and is drawn transparent. */
247 grub_gfxmenu_create_box (const char *pixmaps_prefix
,
248 const char *pixmaps_suffix
)
251 grub_gfxmenu_box_t box
;
253 box
= (grub_gfxmenu_box_t
) grub_malloc (sizeof (*box
));
257 box
->content_width
= 0;
258 box
->content_height
= 0;
260 (struct grub_video_bitmap
**)
261 grub_malloc (BOX_NUM_PIXMAPS
* sizeof (struct grub_video_bitmap
*));
262 box
->scaled_pixmaps
=
263 (struct grub_video_bitmap
**)
264 grub_malloc (BOX_NUM_PIXMAPS
* sizeof (struct grub_video_bitmap
*));
266 /* Initialize all pixmap pointers to NULL so that proper destruction can
267 be performed if an error is encountered partway through construction. */
268 for (i
= 0; i
< BOX_NUM_PIXMAPS
; i
++)
269 box
->raw_pixmaps
[i
] = 0;
270 for (i
= 0; i
< BOX_NUM_PIXMAPS
; i
++)
271 box
->scaled_pixmaps
[i
] = 0;
273 /* Load the pixmaps. */
274 for (i
= 0; i
< BOX_NUM_PIXMAPS
; i
++)
276 if (pixmaps_prefix
&& pixmaps_suffix
)
281 path
= grub_malloc (grub_strlen (pixmaps_prefix
)
282 + grub_strlen (box_pixmap_names
[i
])
283 + grub_strlen (pixmaps_suffix
)
286 goto fail_and_destroy
;
288 /* Construct the specific path for this pixmap. */
289 path_end
= grub_stpcpy (path
, pixmaps_prefix
);
290 path_end
= grub_stpcpy (path_end
, box_pixmap_names
[i
]);
291 path_end
= grub_stpcpy (path_end
, pixmaps_suffix
);
293 grub_video_bitmap_load (&box
->raw_pixmaps
[i
], path
);
296 /* Ignore missing pixmaps. */
297 grub_errno
= GRUB_ERR_NONE
;
302 box
->set_content_size
= set_content_size
;
303 box
->get_left_pad
= get_left_pad
;
304 box
->get_top_pad
= get_top_pad
;
305 box
->get_right_pad
= get_right_pad
;
306 box
->get_bottom_pad
= get_bottom_pad
;
307 box
->destroy
= destroy
;