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>
38 struct entry table
[0];
41 static struct font
*font_list
;
43 /* Fill unknown glyph's with rounded question mark. */
44 static grub_uint8_t unknown_glyph
[16] =
65 add_font (const char *filename
)
70 struct font
*font
= 0;
72 file
= grub_file_open (filename
);
76 if (grub_file_read (file
, magic
, 4) != 4)
79 if (grub_memcmp (magic
, GRUB_FONT_MAGIC
, 4) != 0)
81 grub_error (GRUB_ERR_BAD_FONT
, "invalid font magic");
85 if (grub_file_read (file
, (char *) &num
, 4) != 4)
88 num
= grub_le_to_cpu32 (num
);
89 font
= (struct font
*) grub_malloc (sizeof (struct font
)
90 + sizeof (struct entry
) * num
);
97 for (i
= 0; i
< num
; i
++)
99 grub_uint32_t code
, offset
;
101 if (grub_file_read (file
, (char *) &code
, 4) != 4)
104 if (grub_file_read (file
, (char *) &offset
, 4) != 4)
107 font
->table
[i
].code
= grub_le_to_cpu32 (code
);
108 font
->table
[i
].offset
= grub_le_to_cpu32 (offset
);
111 font
->next
= font_list
;
121 grub_file_close (file
);
127 remove_font (struct font
*font
)
131 for (p
= &font_list
, q
= *p
; q
; p
= &(q
->next
), q
= q
->next
)
136 grub_file_close (font
->file
);
143 /* Return the offset of the glyph corresponding to the codepoint CODE
144 in the font FONT. If no found, return zero. */
146 find_glyph (const struct font
*font
, grub_uint32_t code
)
148 grub_uint32_t start
= 0;
149 grub_uint32_t end
= font
->num
- 1;
150 const struct entry
*table
= font
->table
;
152 /* This shouldn't happen. */
156 /* Do a binary search. */
159 grub_uint32_t i
= (start
+ end
) / 2;
161 if (table
[i
].code
< code
)
163 else if (table
[i
].code
> code
)
166 return table
[i
].offset
;
172 /* Set the glyph to something stupid. */
174 fill_with_default_glyph (grub_font_glyph_t glyph
)
178 /* Use pre-defined pattern to fill unknown glyphs. */
179 for (i
= 0; i
< 16; i
++)
180 glyph
->bitmap
[i
] = unknown_glyph
[i
];
182 glyph
->char_width
= 1;
183 glyph
->width
= glyph
->char_width
* 8;
185 glyph
->baseline
= (16 * 3) / 4;
188 /* Get a glyph corresponding to the codepoint CODE. Always fill glyph
189 information with something, even if no glyph is found. */
191 grub_font_get_glyph (grub_uint32_t code
,
192 grub_font_glyph_t glyph
)
195 grub_uint8_t bitmap
[32];
197 /* FIXME: It is necessary to cache glyphs! */
200 for (font
= font_list
; font
; font
= font
->next
)
202 grub_uint32_t offset
;
204 offset
= find_glyph (font
, code
);
210 /* Make sure we can find glyphs for error messages. Push active
211 error message to error stack and reset error message. */
214 grub_file_seek (font
->file
, offset
);
215 if ((len
= grub_file_read (font
->file
, (char *) &w
, sizeof (w
)))
222 w
= grub_le_to_cpu32 (w
);
223 if (w
!= 1 && w
!= 2)
225 /* grub_error (GRUB_ERR_BAD_FONT, "invalid width"); */
230 if (grub_file_read (font
->file
, (char *) bitmap
, w
* 16)
231 != (grub_ssize_t
) w
* 16)
237 /* Fill glyph with information. */
238 grub_memcpy (glyph
->bitmap
, bitmap
, w
* 16);
240 glyph
->char_width
= w
;
241 glyph
->width
= glyph
->char_width
* 8;
243 glyph
->baseline
= (16 * 3) / 4;
245 /* Restore old error message. */
252 /* Uggh... No font was found. */
253 fill_with_default_glyph (glyph
);
258 font_command (struct grub_arg_list
*state
__attribute__ ((unused
)),
259 int argc
__attribute__ ((unused
)),
260 char **args
__attribute__ ((unused
)))
263 return grub_error (GRUB_ERR_BAD_ARGUMENT
, "no font specified");
266 if (! add_font (*args
++))
272 GRUB_MOD_INIT(font_manager
)
274 grub_register_command ("font", font_command
, GRUB_COMMAND_FLAG_BOTH
,
276 "Specify one or more font files to display.", 0);
279 GRUB_MOD_FINI(font_manager
)
281 grub_unregister_command ("font");