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
;
44 add_font (const char *filename
)
49 struct font
*font
= 0;
51 file
= grub_file_open (filename
);
55 if (grub_file_read (file
, magic
, 4) != 4)
58 if (grub_memcmp (magic
, GRUB_FONT_MAGIC
, 4) != 0)
60 grub_error (GRUB_ERR_BAD_FONT
, "invalid font magic");
64 if (grub_file_read (file
, (char *) &num
, 4) != 4)
67 num
= grub_le_to_cpu32 (num
);
68 font
= (struct font
*) grub_malloc (sizeof (struct font
)
69 + sizeof (struct entry
) * num
);
76 for (i
= 0; i
< num
; i
++)
78 grub_uint32_t code
, offset
;
80 if (grub_file_read (file
, (char *) &code
, 4) != 4)
83 if (grub_file_read (file
, (char *) &offset
, 4) != 4)
86 font
->table
[i
].code
= grub_le_to_cpu32 (code
);
87 font
->table
[i
].offset
= grub_le_to_cpu32 (offset
);
90 font
->next
= font_list
;
100 grub_file_close (file
);
106 remove_font (struct font
*font
)
110 for (p
= &font_list
, q
= *p
; q
; p
= &(q
->next
), q
= q
->next
)
115 grub_file_close (font
->file
);
122 /* Return the offset of the glyph corresponding to the codepoint CODE
123 in the font FONT. If no found, return zero. */
125 find_glyph (const struct font
*font
, grub_uint32_t code
)
127 grub_uint32_t start
= 0;
128 grub_uint32_t end
= font
->num
- 1;
129 const struct entry
*table
= font
->table
;
131 /* This shouldn't happen. */
135 /* Do a binary search. */
138 grub_uint32_t i
= (start
+ end
) / 2;
140 if (table
[i
].code
< code
)
142 else if (table
[i
].code
> code
)
145 return table
[i
].offset
;
151 /* Set the glyph to something stupid. */
153 fill_with_default_glyph (grub_font_glyph_t glyph
)
157 for (i
= 0; i
< 16; i
++)
158 glyph
->bitmap
[i
] = (i
& 1) ? 0x55 : 0xaa;
160 glyph
->char_width
= 1;
161 glyph
->width
= glyph
->char_width
* 8;
163 glyph
->baseline
= (16 * 3) / 4;
166 /* Get a glyph corresponding to the codepoint CODE. Always fill glyph
167 information with something, even if no glyph is found. */
169 grub_font_get_glyph (grub_uint32_t code
,
170 grub_font_glyph_t glyph
)
173 grub_uint8_t bitmap
[32];
175 /* FIXME: It is necessary to cache glyphs! */
178 for (font
= font_list
; font
; font
= font
->next
)
180 grub_uint32_t offset
;
182 offset
= find_glyph (font
, code
);
188 /* Make sure we can find glyphs for error messages. Push active
189 error message to error stack and reset error message. */
192 grub_file_seek (font
->file
, offset
);
193 if ((len
= grub_file_read (font
->file
, (char *) &w
, sizeof (w
)))
200 w
= grub_le_to_cpu32 (w
);
201 if (w
!= 1 && w
!= 2)
203 /* grub_error (GRUB_ERR_BAD_FONT, "invalid width"); */
208 if (grub_file_read (font
->file
, (char *) bitmap
, w
* 16)
209 != (grub_ssize_t
) w
* 16)
215 /* Fill glyph with information. */
216 grub_memcpy (glyph
->bitmap
, bitmap
, w
* 16);
218 glyph
->char_width
= w
;
219 glyph
->width
= glyph
->char_width
* 8;
221 glyph
->baseline
= (16 * 3) / 4;
223 /* Restore old error message. */
230 /* Uggh... No font was found. */
231 fill_with_default_glyph (glyph
);
236 font_command (struct grub_arg_list
*state
__attribute__ ((unused
)),
237 int argc
__attribute__ ((unused
)),
238 char **args
__attribute__ ((unused
)))
241 return grub_error (GRUB_ERR_BAD_ARGUMENT
, "no font specified");
244 if (! add_font (*args
++))
250 GRUB_MOD_INIT(font_manager
)
252 grub_register_command ("font", font_command
, GRUB_COMMAND_FLAG_BOTH
,
254 "Specify one or more font files to display.", 0);
257 GRUB_MOD_FINI(font_manager
)
259 grub_unregister_command ("font");