ieee1275: split up grub_machine_get_bootlocation
[grub.git] / util / grub-gen-asciih.c
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
29 #include FT_SYNTHESIS_H
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     {
84       fprintf (stderr, "Freetype Error %d loading glyph 0x%x for U+0x%x",
85               err, glyph_idx, char_code);
86
87       if (err > 0 && err < (signed) ARRAY_SIZE (ft_errmsgs))
88         fprintf (stderr, ": %s\n", ft_errmsgs[err]);
89       else
90         fprintf (stderr, "\n");
91       exit (1);
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 {
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;
140       struct grub_glyph_info glyph;
141
142       glyph_idx = FT_Get_Char_Index (face, char_code);
143       if (!glyph_idx)
144         return;
145
146       memset (&glyph, 0, sizeof(glyph));
147
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 }