2 * GRUB -- GRand Unified Bootloader
3 * Copyright (C) 2003,2005,2006,2007 Free Software Foundation, Inc.
5 * GRUB is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * GRUB is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
19 #include <grub/file.h>
20 #include <grub/misc.h>
22 #include <grub/normal.h>
23 #include <grub/types.h>
25 #include <grub/font.h>
26 #include <grub/bufio.h>
39 struct entry table
[0];
42 static struct font
*font_list
;
44 /* Fill unknown glyph's with rounded question mark. */
45 static grub_uint8_t unknown_glyph
[16] =
66 add_font (const char *filename
)
71 struct font
*font
= 0;
73 file
= grub_buffile_open (filename
, 0);
77 if (grub_file_read (file
, magic
, 4) != 4)
80 if (grub_memcmp (magic
, GRUB_FONT_MAGIC
, 4) != 0)
82 grub_error (GRUB_ERR_BAD_FONT
, "invalid font magic");
86 if (grub_file_read (file
, (char *) &num
, 4) != 4)
89 num
= grub_le_to_cpu32 (num
);
90 font
= (struct font
*) grub_malloc (sizeof (struct font
)
91 + sizeof (struct entry
) * num
);
98 for (i
= 0; i
< num
; i
++)
100 grub_uint32_t code
, offset
;
102 if (grub_file_read (file
, (char *) &code
, 4) != 4)
105 if (grub_file_read (file
, (char *) &offset
, 4) != 4)
108 font
->table
[i
].code
= grub_le_to_cpu32 (code
);
109 font
->table
[i
].offset
= grub_le_to_cpu32 (offset
);
112 font
->next
= font_list
;
122 grub_file_close (file
);
128 remove_font (struct font
*font
)
132 for (p
= &font_list
, q
= *p
; q
; p
= &(q
->next
), q
= q
->next
)
137 grub_file_close (font
->file
);
144 /* Return the offset of the glyph corresponding to the codepoint CODE
145 in the font FONT. If no found, return zero. */
147 find_glyph (const struct font
*font
, grub_uint32_t code
)
149 grub_uint32_t start
= 0;
150 grub_uint32_t end
= font
->num
- 1;
151 const struct entry
*table
= font
->table
;
153 /* This shouldn't happen. */
157 /* Do a binary search. */
160 grub_uint32_t i
= (start
+ end
) / 2;
162 if (table
[i
].code
< code
)
164 else if (table
[i
].code
> code
)
167 return table
[i
].offset
;
173 /* Set the glyph to something stupid. */
175 fill_with_default_glyph (grub_font_glyph_t glyph
)
179 /* Use pre-defined pattern to fill unknown glyphs. */
180 for (i
= 0; i
< 16; i
++)
181 glyph
->bitmap
[i
] = unknown_glyph
[i
];
183 glyph
->char_width
= 1;
184 glyph
->width
= glyph
->char_width
* 8;
186 glyph
->baseline
= (16 * 3) / 4;
189 /* Get a glyph corresponding to the codepoint CODE. Always fill glyph
190 information with something, even if no glyph is found. */
192 grub_font_get_glyph (grub_uint32_t code
,
193 grub_font_glyph_t glyph
)
196 grub_uint8_t bitmap
[32];
198 /* FIXME: It is necessary to cache glyphs! */
201 for (font
= font_list
; font
; font
= font
->next
)
203 grub_uint32_t offset
;
205 offset
= find_glyph (font
, code
);
211 /* Make sure we can find glyphs for error messages. Push active
212 error message to error stack and reset error message. */
215 grub_file_seek (font
->file
, offset
);
216 if ((len
= grub_file_read (font
->file
, (char *) &w
, sizeof (w
)))
223 w
= grub_le_to_cpu32 (w
);
224 if (w
!= 1 && w
!= 2)
226 /* grub_error (GRUB_ERR_BAD_FONT, "invalid width"); */
231 if (grub_file_read (font
->file
, (char *) bitmap
, w
* 16)
232 != (grub_ssize_t
) w
* 16)
238 /* Fill glyph with information. */
239 grub_memcpy (glyph
->bitmap
, bitmap
, w
* 16);
241 glyph
->char_width
= w
;
242 glyph
->width
= glyph
->char_width
* 8;
244 glyph
->baseline
= (16 * 3) / 4;
246 /* Restore old error message. */
253 /* Uggh... No font was found. */
254 fill_with_default_glyph (glyph
);
259 font_command (struct grub_arg_list
*state
__attribute__ ((unused
)),
260 int argc
__attribute__ ((unused
)),
261 char **args
__attribute__ ((unused
)))
264 return grub_error (GRUB_ERR_BAD_ARGUMENT
, "no font specified");
267 if (! add_font (*args
++))
273 GRUB_MOD_INIT(font_manager
)
275 grub_register_command ("font", font_command
, GRUB_COMMAND_FLAG_BOTH
,
277 "Specify one or more font files to display.", 0);
280 GRUB_MOD_FINI(font_manager
)
282 grub_unregister_command ("font");