]> git.proxmox.com Git - grub2.git/blame - font/manager.c
2005-11-13 Marco Gerards <mgerards@xs4all.nl>
[grub2.git] / font / manager.c
CommitLineData
18d9c7cd 1/*
4b13b216 2 * GRUB -- GRand Unified Bootloader
502c87e8 3 * Copyright (C) 2003,2005 Free Software Foundation, Inc.
18d9c7cd 4 *
5 * This program 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 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program 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.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
4b13b216 20#include <grub/file.h>
21#include <grub/misc.h>
22#include <grub/dl.h>
23#include <grub/normal.h>
24#include <grub/types.h>
25#include <grub/mm.h>
26#include <grub/font.h>
18d9c7cd 27
28struct entry
29{
4b13b216 30 grub_uint32_t code;
31 grub_uint32_t offset;
18d9c7cd 32};
33
34struct font
35{
36 struct font *next;
4b13b216 37 grub_file_t file;
38 grub_uint32_t num;
18d9c7cd 39 struct entry table[0];
40};
41
42static struct font *font_list;
43
44static int
45add_font (const char *filename)
46{
4b13b216 47 grub_file_t file = 0;
18d9c7cd 48 char magic[4];
4b13b216 49 grub_uint32_t num, i;
18d9c7cd 50 struct font *font = 0;
51
4b13b216 52 file = grub_file_open (filename);
18d9c7cd 53 if (! file)
54 goto fail;
55
4b13b216 56 if (grub_file_read (file, magic, 4) != 4)
18d9c7cd 57 goto fail;
58
4b13b216 59 if (grub_memcmp (magic, GRUB_FONT_MAGIC, 4) != 0)
18d9c7cd 60 {
4b13b216 61 grub_error (GRUB_ERR_BAD_FONT, "invalid font magic");
18d9c7cd 62 goto fail;
63 }
64
4b13b216 65 if (grub_file_read (file, (char *) &num, 4) != 4)
18d9c7cd 66 goto fail;
67
4b13b216 68 num = grub_le_to_cpu32 (num);
69 font = (struct font *) grub_malloc (sizeof (struct font)
18d9c7cd 70 + sizeof (struct entry) * num);
71 if (! font)
72 goto fail;
73
74 font->file = file;
75 font->num = num;
76
77 for (i = 0; i < num; i++)
78 {
4b13b216 79 grub_uint32_t code, offset;
18d9c7cd 80
4b13b216 81 if (grub_file_read (file, (char *) &code, 4) != 4)
18d9c7cd 82 goto fail;
83
4b13b216 84 if (grub_file_read (file, (char *) &offset, 4) != 4)
18d9c7cd 85 goto fail;
86
4b13b216 87 font->table[i].code = grub_le_to_cpu32 (code);
88 font->table[i].offset = grub_le_to_cpu32 (offset);
18d9c7cd 89 }
90
91 font->next = font_list;
92 font_list = font;
93
94 return 1;
95
96 fail:
97 if (font)
4b13b216 98 grub_free (font);
18d9c7cd 99
100 if (file)
4b13b216 101 grub_file_close (file);
18d9c7cd 102
103 return 0;
104}
105
106static void
107remove_font (struct font *font)
108{
109 struct font **p, *q;
110
111 for (p = &font_list, q = *p; q; p = &(q->next), q = q->next)
112 if (q == font)
113 {
114 *p = q->next;
115
4b13b216 116 grub_file_close (font->file);
117 grub_free (font);
18d9c7cd 118
119 break;
120 }
121}
122
123/* Return the offset of the glyph corresponding to the codepoint CODE
124 in the font FONT. If no found, return zero. */
4b13b216 125static grub_uint32_t
126find_glyph (const struct font *font, grub_uint32_t code)
18d9c7cd 127{
4b13b216 128 grub_uint32_t start = 0;
129 grub_uint32_t end = font->num - 1;
18d9c7cd 130 struct entry *table = font->table;
131
132 /* This shouldn't happen. */
133 if (font->num == 0)
134 return 0;
135
136 /* Do a binary search. */
137 while (start <= end)
138 {
4b13b216 139 grub_uint32_t i = (start + end) / 2;
18d9c7cd 140
141 if (table[i].code < code)
142 start = i + 1;
143 else if (table[i].code > code)
144 end = i - 1;
145 else
146 return table[i].offset;
147 }
148
149 return 0;
150}
151
152/* Set the glyph to something stupid. */
153static void
154fill_with_default_glyph (unsigned char bitmap[32], unsigned *width)
155{
156 if (bitmap)
157 {
158 unsigned i;
159
160 for (i = 0; i < 16; i++)
161 bitmap[i] = (i & 1) ? 0x55 : 0xaa;
162 }
163
164 *width = 1;
165}
166
167/* Get a glyph corresponding to the codepoint CODE. Always fill BITMAP
168 and WIDTH with something, even if no glyph is found. */
169int
4b13b216 170grub_font_get_glyph (grub_uint32_t code,
18d9c7cd 171 unsigned char bitmap[32], unsigned *width)
172{
173 struct font *font;
174
175 /* FIXME: It is necessary to cache glyphs! */
176
177 restart:
178 for (font = font_list; font; font = font->next)
179 {
4b13b216 180 grub_uint32_t offset;
18d9c7cd 181
182 offset = find_glyph (font, code);
183 if (offset)
184 {
4b13b216 185 grub_uint32_t w;
18d9c7cd 186
4b13b216 187 grub_file_seek (font->file, offset);
188 if (grub_file_read (font->file, (char *) &w, 4) != 4)
18d9c7cd 189 {
190 remove_font (font);
191 goto restart;
192 }
193
4b13b216 194 w = grub_le_to_cpu32 (w);
18d9c7cd 195 if (w != 1 && w != 2)
196 {
4b13b216 197 /* grub_error (GRUB_ERR_BAD_FONT, "invalid width"); */
18d9c7cd 198 remove_font (font);
199 goto restart;
200 }
201
202 if (bitmap
4b13b216 203 && (grub_file_read (font->file, bitmap, w * 16)
204 != (grub_ssize_t) w * 16))
18d9c7cd 205 {
206 remove_font (font);
207 goto restart;
208 }
209
210 *width = w;
211 return 1;
212 }
213 }
214
215 /* Uggh... No font was found. */
216 fill_with_default_glyph (bitmap, width);
217 return 0;
218}
219
4b13b216 220static grub_err_t
221font_command (struct grub_arg_list *state __attribute__ ((unused)),
db1771cf 222 int argc __attribute__ ((unused)),
223 char **args __attribute__ ((unused)))
18d9c7cd 224{
225 if (argc == 0)
4b13b216 226 return grub_error (GRUB_ERR_BAD_ARGUMENT, "no font specified");
18d9c7cd 227
228 while (argc--)
db1771cf 229 if (! add_font (*args++))
18d9c7cd 230 return 1;
231
232 return 0;
233}
234
6d099807 235GRUB_MOD_INIT(fontmanager)
18d9c7cd 236{
db1771cf 237 (void) mod; /* Stop warning. */
4b13b216 238 grub_register_command ("font", font_command, GRUB_COMMAND_FLAG_BOTH,
502c87e8 239 "font FILE...",
240 "Specify one or more font files to display.", 0);
18d9c7cd 241}
242
6d099807 243GRUB_MOD_FINI(fontmanager)
18d9c7cd 244{
4b13b216 245 grub_unregister_command ("font");
18d9c7cd 246}