/* * GRUB -- GRand Unified Bootloader * Copyright (C) 2009,2010 Free Software Foundation, Inc. * * GRUB is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GRUB is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GRUB. If not, see . */ #include #include #include #include #include #include FT_FREETYPE_H #include FT_TRUETYPE_TAGS_H #include FT_TRUETYPE_TABLES_H #include FT_SYNTHESIS_H #undef __FTERRORS_H__ #define FT_ERROR_START_LIST const char *ft_errmsgs[] = { #define FT_ERRORDEF(e, v, s) [e] = s, #define FT_ERROR_END_LIST }; #include FT_ERRORS_H #define GRUB_FONT_DEFAULT_SIZE 16 #define ARRAY_SIZE(array) (sizeof (array) / sizeof (array[0])) struct grub_glyph_info { int width; int height; int x_ofs; int y_ofs; int device_width; int bitmap_size; unsigned char *bitmap; }; static void add_pixel (unsigned char **data, int *mask, int not_blank) { if (*mask == 0) { (*data)++; **data = 0; *mask = 128; } if (not_blank) **data |= *mask; *mask >>= 1; } static void add_glyph (FT_UInt glyph_idx, FT_Face face, unsigned int char_code, struct grub_glyph_info *glyph_info) { int width, height; int cuttop, cutbottom, cutleft, cutright; unsigned char *data; int mask, i, j, bitmap_size; FT_GlyphSlot glyph; int flag = FT_LOAD_RENDER | FT_LOAD_MONOCHROME; FT_Error err; err = FT_Load_Glyph (face, glyph_idx, flag); if (err) { fprintf (stderr, "Freetype Error %d loading glyph 0x%x for U+0x%x", err, glyph_idx, char_code); if (err > 0 && err < (signed) ARRAY_SIZE (ft_errmsgs)) fprintf (stderr, ": %s\n", ft_errmsgs[err]); else fprintf (stderr, "\n"); exit (1); } glyph = face->glyph; if (glyph->next) printf ("%x\n", char_code); cuttop = cutbottom = cutleft = cutright = 0; width = glyph->bitmap.width; height = glyph->bitmap.rows; bitmap_size = ((width * height + 7) / 8); glyph_info->bitmap = malloc (bitmap_size); if (!glyph_info->bitmap) { fprintf (stderr, "grub-gen-asciih: error: out of memory"); exit (1); } glyph_info->bitmap_size = bitmap_size; glyph_info->width = width; glyph_info->height = height; glyph_info->x_ofs = glyph->bitmap_left; glyph_info->y_ofs = glyph->bitmap_top - height; glyph_info->device_width = glyph->metrics.horiAdvance / 64; mask = 0; data = &glyph_info->bitmap[0] - 1; for (j = cuttop; j < height + cuttop; j++) for (i = cutleft; i < width + cutleft; i++) add_pixel (&data, &mask, glyph->bitmap.buffer[i / 8 + j * glyph->bitmap.pitch] & (1 << (7 - (i & 7)))); } static void write_font_ascii_bitmap (FILE *file, FT_Face face) { int char_code; fprintf (file, "/* THIS CHUNK OF BYTES IS AUTOMATICALLY GENERATED */\n"); fprintf (file, "unsigned char ascii_bitmaps[] =\n"); fprintf (file, "{\n"); for (char_code = 0; char_code <= 0x7f; char_code++) { FT_UInt glyph_idx; struct grub_glyph_info glyph; glyph_idx = FT_Get_Char_Index (face, char_code); if (!glyph_idx) return; memset (&glyph, 0, sizeof(glyph)); add_glyph (glyph_idx, face, char_code, &glyph); if (glyph.width == 8 && glyph.height == 16 && glyph.x_ofs == 0 && glyph.y_ofs == 0) { int row; for (row = 0; row < 16; row++) fprintf (file, "0x%02x, ", glyph.bitmap[row]); } else { unsigned char glph[16]; int p = 0, mask = 0x80; int row, col; int dy = 12 - glyph.height - glyph.y_ofs; for (row = 0; row < 16; row++) glph[row] = 0; for (row = 0; row < glyph.height; row++) for (col = 0; col < glyph.width; col++) { int val = glyph.bitmap[p] & mask; mask >>= 1; if (mask == 0) { mask = 0x80; p++; } if (val && dy + row >= 0 && dy + row < 16 && glyph.x_ofs + col >= 0 && glyph.x_ofs + col < 8) glph[dy + row] |= 1 << (7 - (glyph.x_ofs + col)); } for (row = 0; row < 16; row++) fprintf (file, "0x%02x, ", glph[row]); } fprintf (file, "\n"); free (glyph.bitmap); } fprintf (file, "};\n"); } int main (int argc, char *argv[]) { FT_Library ft_lib; FT_Face ft_face; FILE *file; if (argc != 3) { fprintf (stderr, "grub-gen-asciih: usage: INPUT OUTPUT"); return 1; } if (FT_Init_FreeType (&ft_lib)) { fprintf (stderr, "grub-gen-asciih: error: FT_Init_FreeType fails"); return 1; } { int size; FT_Error err; err = FT_New_Face (ft_lib, argv[1], 0, &ft_face); if (err) { fprintf (stderr, "can't open file %s, index %d: error %d", argv[1], 0, err); if (err > 0 && err < (signed) ARRAY_SIZE (ft_errmsgs)) fprintf (stderr, ": %s\n", ft_errmsgs[err]); else fprintf (stderr, "\n"); return 1; } if ((ft_face->face_flags & FT_FACE_FLAG_SCALABLE) || (! ft_face->num_fixed_sizes)) size = GRUB_FONT_DEFAULT_SIZE; else size = ft_face->available_sizes[0].height; if (FT_Set_Pixel_Sizes (ft_face, size, size)) { fprintf (stderr, "grub-gen-asciih: error: can't set %dx%d font size", size, size); return 1; } } file = fopen (argv[2], "w"); if (! file) { fprintf (stderr, "grub-gen-asciih: error: cannot write to `%s': %s", argv[2], strerror (errno)); return 1; } write_font_ascii_bitmap (file, ft_face); fclose (file); FT_Done_Face (ft_face); FT_Done_FreeType (ft_lib); return 0; }