]> git.proxmox.com Git - grub2.git/blame - gfxmenu/gui_image.c
Merge multiterm into gfxmenu+multiterm
[grub2.git] / gfxmenu / gui_image.c
CommitLineData
d920a32a
CB
1/* gui_image.c - GUI component to display an image. */
2/*
3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 2008,2009 Free Software Foundation, Inc.
5 *
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.
10 *
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.
15 *
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/>.
18 */
19
20#include <grub/mm.h>
21#include <grub/misc.h>
22#include <grub/gui.h>
23#include <grub/gui_string_util.h>
24#include <grub/bitmap.h>
25#include <grub/bitmap_scale.h>
26
27struct grub_gui_image
28{
9a175884 29 struct grub_gui_component component;
d920a32a
CB
30
31 grub_gui_container_t parent;
32 grub_video_rect_t bounds;
33 char *id;
d920a32a
CB
34 struct grub_video_bitmap *raw_bitmap;
35 struct grub_video_bitmap *bitmap;
36};
37
38typedef struct grub_gui_image *grub_gui_image_t;
39
40static void
41image_destroy (void *vself)
42{
43 grub_gui_image_t self = vself;
44
45 /* Free the scaled bitmap, unless it's a reference to the raw bitmap. */
46 if (self->bitmap && (self->bitmap != self->raw_bitmap))
47 grub_video_bitmap_destroy (self->bitmap);
48 if (self->raw_bitmap)
49 grub_video_bitmap_destroy (self->raw_bitmap);
50
51 grub_free (self);
52}
53
54static const char *
55image_get_id (void *vself)
56{
57 grub_gui_image_t self = vself;
58 return self->id;
59}
60
61static int
62image_is_instance (void *vself __attribute__((unused)), const char *type)
63{
64 return grub_strcmp (type, "component") == 0;
65}
66
67static void
947fa16c 68image_paint (void *vself, const grub_video_rect_t *region)
d920a32a
CB
69{
70 grub_gui_image_t self = vself;
947fa16c
VS
71 grub_video_rect_t vpsave;
72
d920a32a
CB
73 if (! self->bitmap)
74 return;
947fa16c
VS
75 if (!grub_video_have_common_points (region, &self->bounds))
76 return;
77
d920a32a
CB
78 grub_gui_set_viewport (&self->bounds, &vpsave);
79 grub_video_blit_bitmap (self->bitmap, GRUB_VIDEO_BLIT_BLEND,
80 0, 0, 0, 0,
81 grub_video_bitmap_get_width (self->bitmap),
82 grub_video_bitmap_get_height (self->bitmap));
83 grub_gui_restore_viewport (&vpsave);
84}
85
86static void
87image_set_parent (void *vself, grub_gui_container_t parent)
88{
89 grub_gui_image_t self = vself;
90 self->parent = parent;
91}
92
93static grub_gui_container_t
94image_get_parent (void *vself)
95{
96 grub_gui_image_t self = vself;
97 return self->parent;
98}
99
100static grub_err_t
101rescale_image (grub_gui_image_t self)
102{
103 if (! self->raw_bitmap)
104 {
105 if (self->bitmap)
106 {
107 grub_video_bitmap_destroy (self->bitmap);
108 self->bitmap = 0;
109 }
110 return grub_errno;
111 }
112
113 unsigned width = self->bounds.width;
114 unsigned height = self->bounds.height;
115
116 if (self->bitmap
117 && (grub_video_bitmap_get_width (self->bitmap) == width)
118 && (grub_video_bitmap_get_height (self->bitmap) == height))
119 {
120 /* Nothing to do; already the right size. */
121 return grub_errno;
122 }
123
124 /* Free any old scaled bitmap,
125 *unless* it's a reference to the raw bitmap. */
126 if (self->bitmap && (self->bitmap != self->raw_bitmap))
127 grub_video_bitmap_destroy (self->bitmap);
128
129 self->bitmap = 0;
130
131 /* Create a scaled bitmap, unless the requested size is the same
132 as the raw size -- in that case a reference is made. */
133 if (grub_video_bitmap_get_width (self->raw_bitmap) == width
134 && grub_video_bitmap_get_height (self->raw_bitmap) == height)
135 {
136 self->bitmap = self->raw_bitmap;
137 return grub_errno;
138 }
139
140 /* Don't scale to an invalid size. */
141 if (width == 0 || height == 0)
142 return grub_errno;
143
144 /* Create the scaled bitmap. */
145 grub_video_bitmap_create_scaled (&self->bitmap,
146 width,
147 height,
148 self->raw_bitmap,
149 GRUB_VIDEO_BITMAP_SCALE_METHOD_BEST);
150 if (grub_errno != GRUB_ERR_NONE)
151 {
152 grub_error_push ();
153 grub_error (grub_errno, "failed to scale bitmap for image component");
154 }
155 return grub_errno;
156}
157
158static void
159image_set_bounds (void *vself, const grub_video_rect_t *bounds)
160{
161 grub_gui_image_t self = vself;
162 self->bounds = *bounds;
163 rescale_image (self);
164}
165
166static void
167image_get_bounds (void *vself, grub_video_rect_t *bounds)
168{
169 grub_gui_image_t self = vself;
170 *bounds = self->bounds;
171}
172
9a175884 173/* FIXME: inform rendering system it's not forced minimum. */
d920a32a 174static void
9a175884 175image_get_minimal_size (void *vself, unsigned *width, unsigned *height)
d920a32a
CB
176{
177 grub_gui_image_t self = vself;
178
179 if (self->raw_bitmap)
180 {
181 *width = grub_video_bitmap_get_width (self->raw_bitmap);
182 *height = grub_video_bitmap_get_height (self->raw_bitmap);
183 }
184 else
185 {
186 *width = 0;
187 *height = 0;
188 }
d920a32a
CB
189}
190
191static grub_err_t
192load_image (grub_gui_image_t self, const char *path)
193{
194 struct grub_video_bitmap *bitmap;
195 if (grub_video_bitmap_load (&bitmap, path) != GRUB_ERR_NONE)
196 return grub_errno;
197
198 if (self->bitmap && (self->bitmap != self->raw_bitmap))
199 grub_video_bitmap_destroy (self->bitmap);
200 if (self->raw_bitmap)
201 grub_video_bitmap_destroy (self->raw_bitmap);
202
203 self->raw_bitmap = bitmap;
204 return rescale_image (self);
205}
206
207static grub_err_t
208image_set_property (void *vself, const char *name, const char *value)
209{
210 grub_gui_image_t self = vself;
211 if (grub_strcmp (name, "file") == 0)
212 return load_image (self, value);
d920a32a
CB
213 else if (grub_strcmp (name, "id") == 0)
214 {
215 grub_free (self->id);
216 if (value)
217 self->id = grub_strdup (value);
218 else
219 self->id = 0;
220 }
221 return grub_errno;
222}
223
224static struct grub_gui_component_ops image_ops =
225{
226 .destroy = image_destroy,
227 .get_id = image_get_id,
228 .is_instance = image_is_instance,
229 .paint = image_paint,
230 .set_parent = image_set_parent,
231 .get_parent = image_get_parent,
232 .set_bounds = image_set_bounds,
233 .get_bounds = image_get_bounds,
9a175884 234 .get_minimal_size = image_get_minimal_size,
d920a32a
CB
235 .set_property = image_set_property
236};
237
238grub_gui_component_t
239grub_gui_image_new (void)
240{
241 grub_gui_image_t image;
9a175884 242 image = grub_zalloc (sizeof (*image));
d920a32a
CB
243 if (! image)
244 return 0;
9a175884 245 image->component.ops = &image_ops;
d920a32a
CB
246 return (grub_gui_component_t) image;
247}
248