]>
Commit | Line | Data |
---|---|---|
c6b066f2 VS |
1 | /* |
2 | * GRUB -- GRand Unified Bootloader | |
3 | * Copyright (C) 2009,2010 Free Software Foundation, Inc. | |
4 | * | |
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. | |
9 | * | |
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. | |
14 | * | |
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/>. | |
17 | */ | |
18 | ||
19 | #include <stdio.h> | |
20 | #include <stdlib.h> | |
21 | #include <string.h> | |
22 | ||
23 | #include <errno.h> | |
24 | ||
25 | #include <ft2build.h> | |
26 | #include FT_FREETYPE_H | |
27 | #include FT_TRUETYPE_TAGS_H | |
28 | #include FT_TRUETYPE_TABLES_H | |
fd0df6d0 | 29 | #include FT_SYNTHESIS_H |
c6b066f2 VS |
30 | |
31 | #undef __FTERRORS_H__ | |
32 | #define FT_ERROR_START_LIST const char *ft_errmsgs[] = { | |
33 | #define FT_ERRORDEF(e, v, s) [e] = s, | |
34 | #define FT_ERROR_END_LIST }; | |
35 | #include FT_ERRORS_H | |
36 | ||
37 | #define GRUB_FONT_DEFAULT_SIZE 16 | |
38 | ||
39 | #define ARRAY_SIZE(array) (sizeof (array) / sizeof (array[0])) | |
40 | ||
41 | struct grub_glyph_info | |
42 | { | |
43 | int width; | |
44 | int height; | |
45 | int x_ofs; | |
46 | int y_ofs; | |
47 | int device_width; | |
48 | int bitmap_size; | |
49 | unsigned char *bitmap; | |
50 | }; | |
51 | ||
52 | static void | |
53 | add_pixel (unsigned char **data, int *mask, int not_blank) | |
54 | { | |
55 | if (*mask == 0) | |
56 | { | |
57 | (*data)++; | |
58 | **data = 0; | |
59 | *mask = 128; | |
60 | } | |
61 | ||
62 | if (not_blank) | |
63 | **data |= *mask; | |
64 | ||
65 | *mask >>= 1; | |
66 | } | |
67 | ||
68 | static void | |
69 | add_glyph (FT_UInt glyph_idx, FT_Face face, | |
70 | unsigned int char_code, | |
71 | struct grub_glyph_info *glyph_info) | |
72 | { | |
73 | int width, height; | |
74 | int cuttop, cutbottom, cutleft, cutright; | |
75 | unsigned char *data; | |
76 | int mask, i, j, bitmap_size; | |
77 | FT_GlyphSlot glyph; | |
78 | int flag = FT_LOAD_RENDER | FT_LOAD_MONOCHROME; | |
79 | FT_Error err; | |
80 | ||
81 | err = FT_Load_Glyph (face, glyph_idx, flag); | |
82 | if (err) | |
83 | { | |
87de66d9 | 84 | fprintf (stderr, "Freetype Error %d loading glyph 0x%x for U+0x%x", |
c6b066f2 VS |
85 | err, glyph_idx, char_code); |
86 | ||
87 | if (err > 0 && err < (signed) ARRAY_SIZE (ft_errmsgs)) | |
87de66d9 | 88 | fprintf (stderr, ": %s\n", ft_errmsgs[err]); |
c6b066f2 | 89 | else |
87de66d9 TW |
90 | fprintf (stderr, "\n"); |
91 | exit (1); | |
c6b066f2 VS |
92 | } |
93 | ||
94 | glyph = face->glyph; | |
95 | ||
96 | if (glyph->next) | |
97 | printf ("%x\n", char_code); | |
98 | ||
99 | cuttop = cutbottom = cutleft = cutright = 0; | |
100 | ||
101 | width = glyph->bitmap.width; | |
102 | height = glyph->bitmap.rows; | |
103 | ||
104 | bitmap_size = ((width * height + 7) / 8); | |
105 | glyph_info->bitmap = malloc (bitmap_size); | |
106 | if (!glyph_info->bitmap) | |
107 | { | |
108 | fprintf (stderr, "grub-gen-asciih: error: out of memory"); | |
109 | exit (1); | |
110 | } | |
111 | glyph_info->bitmap_size = bitmap_size; | |
112 | ||
113 | glyph_info->width = width; | |
114 | glyph_info->height = height; | |
115 | glyph_info->x_ofs = glyph->bitmap_left; | |
116 | glyph_info->y_ofs = glyph->bitmap_top - height; | |
117 | glyph_info->device_width = glyph->metrics.horiAdvance / 64; | |
118 | ||
119 | mask = 0; | |
120 | data = &glyph_info->bitmap[0] - 1; | |
121 | for (j = cuttop; j < height + cuttop; j++) | |
122 | for (i = cutleft; i < width + cutleft; i++) | |
123 | add_pixel (&data, &mask, | |
124 | glyph->bitmap.buffer[i / 8 + j * glyph->bitmap.pitch] & | |
125 | (1 << (7 - (i & 7)))); | |
126 | } | |
127 | ||
128 | static void | |
129 | write_font_ascii_bitmap (FILE *file, FT_Face face) | |
130 | { | |
c6b066f2 VS |
131 | int char_code; |
132 | ||
133 | fprintf (file, "/* THIS CHUNK OF BYTES IS AUTOMATICALLY GENERATED */\n"); | |
134 | fprintf (file, "unsigned char ascii_bitmaps[] =\n"); | |
135 | fprintf (file, "{\n"); | |
136 | ||
137 | for (char_code = 0; char_code <= 0x7f; char_code++) | |
138 | { | |
139 | FT_UInt glyph_idx; | |
87de66d9 TW |
140 | struct grub_glyph_info glyph; |
141 | ||
c6b066f2 VS |
142 | glyph_idx = FT_Get_Char_Index (face, char_code); |
143 | if (!glyph_idx) | |
144 | return; | |
87de66d9 TW |
145 | |
146 | memset (&glyph, 0, sizeof(glyph)); | |
147 | ||
c6b066f2 VS |
148 | add_glyph (glyph_idx, face, char_code, &glyph); |
149 | ||
150 | if (glyph.width == 8 && glyph.height == 16 | |
151 | && glyph.x_ofs == 0 && glyph.y_ofs == 0) | |
152 | { | |
153 | int row; | |
154 | for (row = 0; row < 16; row++) | |
155 | fprintf (file, "0x%02x, ", glyph.bitmap[row]); | |
156 | } | |
157 | else | |
158 | { | |
159 | unsigned char glph[16]; | |
160 | int p = 0, mask = 0x80; | |
161 | int row, col; | |
162 | int dy = 12 - glyph.height - glyph.y_ofs; | |
163 | for (row = 0; row < 16; row++) | |
164 | glph[row] = 0; | |
165 | for (row = 0; row < glyph.height; row++) | |
166 | for (col = 0; col < glyph.width; col++) | |
167 | { | |
168 | int val = glyph.bitmap[p] & mask; | |
169 | mask >>= 1; | |
170 | if (mask == 0) | |
171 | { | |
172 | mask = 0x80; | |
173 | p++; | |
174 | } | |
175 | if (val && dy + row >= 0 | |
176 | && dy + row < 16 | |
177 | && glyph.x_ofs + col >= 0 | |
178 | && glyph.x_ofs + col < 8) | |
179 | glph[dy + row] |= 1 << (7 - (glyph.x_ofs + col)); | |
180 | } | |
181 | for (row = 0; row < 16; row++) | |
182 | fprintf (file, "0x%02x, ", glph[row]); | |
183 | } | |
184 | fprintf (file, "\n"); | |
185 | free (glyph.bitmap); | |
186 | } | |
187 | fprintf (file, "};\n"); | |
188 | } | |
189 | ||
190 | int | |
191 | main (int argc, char *argv[]) | |
192 | { | |
193 | FT_Library ft_lib; | |
194 | FT_Face ft_face; | |
195 | FILE *file; | |
196 | ||
197 | if (argc != 3) | |
198 | { | |
199 | fprintf (stderr, "grub-gen-asciih: usage: INPUT OUTPUT"); | |
200 | return 1; | |
201 | } | |
202 | ||
203 | if (FT_Init_FreeType (&ft_lib)) | |
204 | { | |
205 | fprintf (stderr, "grub-gen-asciih: error: FT_Init_FreeType fails"); | |
206 | return 1; | |
207 | } | |
208 | ||
209 | { | |
210 | int size; | |
211 | FT_Error err; | |
212 | ||
213 | err = FT_New_Face (ft_lib, argv[1], 0, &ft_face); | |
214 | if (err) | |
215 | { | |
216 | fprintf (stderr, "can't open file %s, index %d: error %d", | |
217 | argv[1], 0, err); | |
218 | if (err > 0 && err < (signed) ARRAY_SIZE (ft_errmsgs)) | |
219 | fprintf (stderr, ": %s\n", ft_errmsgs[err]); | |
220 | else | |
221 | fprintf (stderr, "\n"); | |
222 | ||
223 | return 1; | |
224 | } | |
225 | ||
226 | if ((ft_face->face_flags & FT_FACE_FLAG_SCALABLE) || | |
227 | (! ft_face->num_fixed_sizes)) | |
228 | size = GRUB_FONT_DEFAULT_SIZE; | |
229 | else | |
230 | size = ft_face->available_sizes[0].height; | |
231 | ||
232 | if (FT_Set_Pixel_Sizes (ft_face, size, size)) | |
233 | { | |
234 | fprintf (stderr, "grub-gen-asciih: error: can't set %dx%d font size", size, size); | |
235 | return 1; | |
236 | } | |
237 | } | |
238 | ||
239 | file = fopen (argv[2], "w"); | |
240 | if (! file) | |
241 | { | |
242 | fprintf (stderr, "grub-gen-asciih: error: cannot write to `%s': %s", argv[2], | |
243 | strerror (errno)); | |
244 | return 1; | |
245 | } | |
246 | ||
247 | write_font_ascii_bitmap (file, ft_face); | |
248 | ||
249 | fclose (file); | |
250 | ||
251 | FT_Done_Face (ft_face); | |
252 | ||
253 | FT_Done_FreeType (ft_lib); | |
254 | ||
255 | return 0; | |
256 | } |