Here is the path for anti-aliased fonts. Everything my path does is:
1) Enriches grub-mkfont with ability to write (and debug with -vv) pff3 (as I call it now) font format. There are 2 differences between pff2 and pff3 formats: FILE magic (PFF2 becomes PFF3) and DATA block entires size multiples by 8 (1bit -> 8bit). In other words PFF3 stores 8-bit alpha channel instead of 1-bit. And grub-mkfont will still be able to generate pff2, of course. 2) Adds pff3 format parsing and drawing ability to font.c. And of course pff2 still there; actually as you can understand 95% of code is reused because of such a little differences in formats. Drawing itself implemented pretty straightforward: on each glyph drawing A channel (from glyph) and foreground color are converted to RGBA buffer and then blended in RGBA_8888 mode. As far as I understand writing custom blitter for now will not worth it in terms of efficiency. When I test it I was unable to see performance difference between 1-bit fonts and my version. They both flickers a little. Files affected: /font/font.c and /util/grub-mkfont.c.
--- font.c 2010-01-22 16:52:54.980914210 +0600 +++ font.bak.c 2010-01-22 00:38:28.000000000 +0600 @@ -51,7 +51,6 @@ struct grub_font { - grub_uint8_t version; char *name; grub_file_t file; char *family; @@ -65,7 +64,6 @@ grub_uint32_t num_chars; struct char_index_entry *char_index; grub_uint16_t *bmp_idx; - grub_uint8_t *glyph_bitmap_buffer; }; /* Definition of font registry. */ @@ -93,7 +91,6 @@ /* Font file format constants. */ static const char pff2_magic[4] = { 'P', 'F', 'F', '2' }; -static const char pff3_magic[4] = { 'P', 'F', 'F', '3' }; static const char section_names_file[4] = { 'F', 'I', 'L', 'E' }; static const char section_names_font_name[4] = { 'N', 'A', 'M', 'E' }; static const char section_names_point_size[4] = { 'P', 'T', 'S', 'Z' }; @@ -216,8 +213,6 @@ static void font_init (grub_font_t font) { - font->version = 2; - font->name = 0; font->file = 0; font->family = 0; @@ -445,7 +440,6 @@ struct font_file_section section; char magic[4]; grub_font_t font = 0; - grub_uint8_t pff3 = 0; #if FONT_DEBUG >= 1 grub_printf("add_font(%s)\n", filename); @@ -495,15 +489,12 @@ grub_printf("read magic ok\n"); #endif - if (grub_memcmp (magic, pff2_magic, 4) != 0 && grub_memcmp (magic, pff3_magic, 4) != 0) + if (grub_memcmp (magic, pff2_magic, 4) != 0) { grub_error (GRUB_ERR_BAD_FONT, "invalid font magic %x %x %x %x", magic[0], magic[1], magic[2], magic[3]); goto fail; } - else - if (grub_memcmp (magic, pff3_magic, 4) == 0) - pff3 = 1; #if FONT_DEBUG >= 3 grub_printf("compare magic ok\n"); @@ -517,9 +508,6 @@ font_init (font); font->file = file; - if (pff3 != 0) - font->version = 3; - #if FONT_DEBUG >= 3 grub_printf("allocate font ok; loading font info\n"); #endif @@ -621,9 +609,6 @@ font->max_char_width, font->max_char_height, font->num_chars); #endif - - /* Font loaded. Create glyph to bitmap conversion buffer */ - font->glyph_bitmap_buffer = grub_malloc (font->max_char_width * font->max_char_height * 4); if (font->max_char_width == 0 || font->max_char_height == 0 @@ -752,10 +737,7 @@ return 0; } - if (font->version == 3) - len = width * height; - else - len = (width * height + 7) / 8; + len = (width * height + 7) / 8; glyph = grub_malloc (sizeof (struct grub_font_glyph) + len); if (! glyph) { @@ -806,7 +788,6 @@ grub_free (font->name); grub_free (font->family); grub_free (font->char_index); - grub_free (font->glyph_bitmap_buffer); grub_free (font); } } @@ -1079,59 +1060,29 @@ glyph_bitmap.mode_info.width = glyph->width; glyph_bitmap.mode_info.height = glyph->height; - - if (glyph->font->version == 3) - { - glyph_bitmap.mode_info.mode_type = - (1 << GRUB_VIDEO_MODE_TYPE_DEPTH_POS) - | GRUB_VIDEO_MODE_TYPE_RGB | GRUB_VIDEO_MODE_TYPE_ALPHA; - glyph_bitmap.mode_info.blit_format = GRUB_VIDEO_BLIT_FORMAT_RGBA_8888; - glyph_bitmap.mode_info.bpp = 32; - glyph_bitmap.mode_info.bytes_per_pixel = 4; - glyph_bitmap.mode_info.pitch = glyph->width * 4; - } - else - { - glyph_bitmap.mode_info.mode_type = - (1 << GRUB_VIDEO_MODE_TYPE_DEPTH_POS) - | GRUB_VIDEO_MODE_TYPE_1BIT_BITMAP; - glyph_bitmap.mode_info.blit_format = GRUB_VIDEO_BLIT_FORMAT_1BIT_PACKED; - glyph_bitmap.mode_info.bpp = 1; - - /* Really 1 bit per pixel. */ - glyph_bitmap.mode_info.bytes_per_pixel = 0; - - /* Packed densely as bits. */ - glyph_bitmap.mode_info.pitch = glyph->width; - - glyph_bitmap.mode_info.number_of_colors = 2; - glyph_bitmap.mode_info.bg_red = 0; - glyph_bitmap.mode_info.bg_green = 0; - glyph_bitmap.mode_info.bg_blue = 0; - glyph_bitmap.mode_info.bg_alpha = 0; - } - + glyph_bitmap.mode_info.mode_type = + (1 << GRUB_VIDEO_MODE_TYPE_DEPTH_POS) + | GRUB_VIDEO_MODE_TYPE_1BIT_BITMAP; + glyph_bitmap.mode_info.blit_format = GRUB_VIDEO_BLIT_FORMAT_1BIT_PACKED; + glyph_bitmap.mode_info.bpp = 1; + + /* Really 1 bit per pixel. */ + glyph_bitmap.mode_info.bytes_per_pixel = 0; + + /* Packed densely as bits. */ + glyph_bitmap.mode_info.pitch = glyph->width; + + glyph_bitmap.mode_info.number_of_colors = 2; + glyph_bitmap.mode_info.bg_red = 0; + glyph_bitmap.mode_info.bg_green = 0; + glyph_bitmap.mode_info.bg_blue = 0; + glyph_bitmap.mode_info.bg_alpha = 0; grub_video_unmap_color(color, &glyph_bitmap.mode_info.fg_red, &glyph_bitmap.mode_info.fg_green, &glyph_bitmap.mode_info.fg_blue, &glyph_bitmap.mode_info.fg_alpha); - - if (glyph->font->version == 3) - { - int i; - grub_uint8_t *pixel = glyph->font->glyph_bitmap_buffer; - for (i = 0; i < glyph->width * glyph->height; i++) - { - *pixel = glyph_bitmap.mode_info.fg_red; pixel++; - *pixel = glyph_bitmap.mode_info.fg_green; pixel++; - *pixel = glyph_bitmap.mode_info.fg_blue; pixel++; - *pixel = glyph->bitmap[i]; pixel++; - } - glyph_bitmap.data = glyph->font->glyph_bitmap_buffer; - } - else - glyph_bitmap.data = glyph->bitmap; + glyph_bitmap.data = glyph->bitmap; int bitmap_left = left_x + glyph->offset_x; int bitmap_bottom = baseline_y - glyph->offset_y;
--- grub-mkfont.c 2010-01-22 15:01:47.664910782 +0600 +++ grub-mkfont.bak.c 2010-01-22 00:38:28.000000000 +0600 @@ -51,7 +51,7 @@ enum file_formats { - PFN, + PF2, ASCII_BITMAPS }; @@ -59,7 +59,6 @@ #define GRUB_FONT_FLAG_NOBITMAP 2 #define GRUB_FONT_FLAG_NOHINTING 4 #define GRUB_FONT_FLAG_FORCEHINT 8 -#define GRUB_FONT_FLAG_8BIT_AA 4096 struct grub_font_info { @@ -95,7 +94,6 @@ {"version", no_argument, 0, 'V'}, {"verbose", no_argument, 0, 'v'}, {"ascii-bitmaps", no_argument, 0, 0x102}, - {"pff3", no_argument, 0, '3'}, {0, 0, 0, 0} }; @@ -111,7 +109,6 @@ Usage: %s [OPTIONS] FONT_FILES\n\ \nOptions:\n\ -o, --output=FILE_NAME set output file name\n\ - -3, --pff3 save in pff3 format (antialiased)\n\ --ascii-bitmaps save only the ASCII bitmaps\n\ -i, --index=N set face index\n\ -r, --range=A-B[,C-D] set font range\n\ @@ -157,12 +154,7 @@ grub_uint8_t *data; int mask, i, j, bitmap_size; FT_GlyphSlot glyph; - int flag = FT_LOAD_RENDER; - - if (font_info->flags & GRUB_FONT_FLAG_8BIT_AA) - flag |= FT_LOAD_TARGET_NORMAL; - else - flag |= FT_LOAD_MONOCHROME; + int flag = FT_LOAD_RENDER | FT_LOAD_MONOCHROME; if (font_info->flags & GRUB_FONT_FLAG_NOBITMAP) flag |= FT_LOAD_NO_BITMAP; @@ -193,11 +185,7 @@ width = glyph->bitmap.width; height = glyph->bitmap.rows; - if (font_info->flags & GRUB_FONT_FLAG_8BIT_AA) - bitmap_size = width * height; - else - bitmap_size = ((width * height + 7) / 8); - + bitmap_size = ((width * height + 7) / 8); glyph_info = xmalloc (sizeof (struct grub_glyph_info) + bitmap_size); glyph_info->bitmap_size = bitmap_size; @@ -223,18 +211,13 @@ if (glyph_info->y_ofs + height > font_info->max_y) font_info->max_y = glyph_info->y_ofs + height; - if (font_info->flags & GRUB_FONT_FLAG_8BIT_AA) - memcpy (glyph_info->bitmap, glyph->bitmap.buffer, bitmap_size); - else - { - mask = 0; - data = &glyph_info->bitmap[0] - 1; - for (j = 0; j < height; j++) - for (i = 0; i < width; i++) - add_pixel (&data, &mask, - glyph->bitmap.buffer[i / 8 + j * glyph->bitmap.pitch] & - (1 << (7 - (i & 7)))); - } + mask = 0; + data = &glyph_info->bitmap[0] - 1; + for (j = 0; j < height; j++) + for (i = 0; i < width; i++) + add_pixel (&data, &mask, + glyph->bitmap.buffer[i / 8 + j * glyph->bitmap.pitch] & + (1 << (7 - (i & 7)))); } void @@ -246,17 +229,18 @@ grub_uint32_t j; for (i = 0; i < font_info->num_range; i++) - for (j = font_info->ranges[i * 2]; j <= font_info->ranges[i * 2 + 1]; j++) - add_char (font_info, face, j); + for (j = font_info->ranges[i * 2]; j <= font_info->ranges[i * 2 + 1]; + j++) + add_char (font_info, face, j); } else { grub_uint32_t char_code, glyph_index; for (char_code = FT_Get_First_Char (face, &glyph_index); - glyph_index; - char_code = FT_Get_Next_Char (face, char_code, &glyph_index)) - add_char (font_info, face, char_code); + glyph_index; + char_code = FT_Get_Next_Char (face, char_code, &glyph_index)) + add_char (font_info, face, char_code); } } @@ -308,74 +292,56 @@ xmax = glyph->x_ofs + glyph->width; if (xmax < glyph->device_width) - xmax = glyph->device_width; + xmax = glyph->device_width; xmin = glyph->x_ofs; if (xmin > 0) - xmin = 0; + xmin = 0; ymax = glyph->y_ofs + glyph->height; if (ymax < font_info->asce) - ymax = font_info->asce; + ymax = font_info->asce; ymin = glyph->y_ofs; if (ymin > - font_info->desc) - ymin = - font_info->desc; + ymin = - font_info->desc; bitmap = glyph->bitmap; mask = 0x80; for (y = ymax - 1; y >= ymin; y--) - { - int line_pos; + { + int line_pos; - line_pos = 0; - for (x = xmin; x < xmax; x++) - { - if ((x >= glyph->x_ofs) && - (x < glyph->x_ofs + glyph->width) && - (y >= glyph->y_ofs) && - (y < glyph->y_ofs + glyph->height)) - { - if (font_info->flags & GRUB_FONT_FLAG_8BIT_AA) - { - if (*bitmap > 127) - line[line_pos++] = '#'; - else if (*bitmap > 64) - line[line_pos++] = '8'; - else if (*bitmap > 8) - line[line_pos++] = 'o'; - else if (*bitmap > 1) - line[line_pos++] = '-'; - else - line[line_pos++] = '_'; - - bitmap++; - } - else - { - line[line_pos++] = (*bitmap & mask) ? '#' : '_'; - mask >>= 1; - if (mask == 0) - { - mask = 0x80; - bitmap++; - } - } - } - else if ((x >= 0) && - (x < glyph->device_width) && - (y >= - font_info->desc) && - (y < font_info->asce)) - { - line[line_pos++] = ((x == 0) || (y == 0)) ? '+' : '.'; - } - else - line[line_pos++] = '*'; - } - line[line_pos] = 0; - printf ("%s\n", line); - } - } + line_pos = 0; + for (x = xmin; x < xmax; x++) + { + if ((x >= glyph->x_ofs) && + (x < glyph->x_ofs + glyph->width) && + (y >= glyph->y_ofs) && + (y < glyph->y_ofs + glyph->height)) + { + line[line_pos++] = (*bitmap & mask) ? '#' : '_'; + mask >>= 1; + if (mask == 0) + { + mask = 0x80; + bitmap++; + } + } + else if ((x >= 0) && + (x < glyph->device_width) && + (y >= - font_info->desc) && + (y < font_info->asce)) + { + line[line_pos++] = ((x == 0) || (y == 0)) ? '+' : '.'; + } + else + line[line_pos++] = '*'; + } + line[line_pos] = 0; + printf ("%s\n", line); + } + } } void @@ -396,22 +362,22 @@ if (glyph->width != 8 || glyph->height != 16) { /* printf ("Width or height from glyph U+%04x not supported, skipping.\n", glyph->char_code); */ - correct_size = 0; + correct_size = 0; } int row; for (row = 0; row < glyph->height; row++) { - if (correct_size) - fwrite (&glyph->bitmap[row], sizeof(glyph->bitmap[row]), 1, file); - else - fwrite (&correct_size, 1, 1, file); + if (correct_size) + fwrite (&glyph->bitmap[row], sizeof(glyph->bitmap[row]), 1, file); + else + fwrite (&correct_size, 1, 1, file); } } - fclose (file); + fclose (file); } void -write_font_pfN (struct grub_font_info *font_info, char *output_file) +write_font_pf2 (struct grub_font_info *font_info, char *output_file) { FILE *file; grub_uint32_t leng, data; @@ -428,11 +394,7 @@ leng = grub_cpu_to_be32 (4); grub_util_write_image ("FILE", 4, file); grub_util_write_image ((char *) &leng, 4, file); - if (font_info->flags & GRUB_FONT_FLAG_8BIT_AA) - grub_util_write_image ("PFF3", 4, file); - else - grub_util_write_image ("PFF2", 4, file); - + grub_util_write_image ("PFF2", 4, file); offset += 12; if (! font_info->name) @@ -562,7 +524,7 @@ int font_index = 0; int font_size = 0; char *output_file = NULL; - enum file_formats file_format = PFN; + enum file_formats file_format = PF2; memset (&font_info, 0, sizeof (font_info)); @@ -573,7 +535,7 @@ /* Check for options. */ while (1) { - int c = getopt_long (argc, argv, "bao:n:i:s:d:r:hVv3", options, 0); + int c = getopt_long (argc, argv, "bao:n:i:s:d:r:hVv", options, 0); if (c == -1) break; @@ -670,10 +632,6 @@ case 0x102: file_format = ASCII_BITMAPS; break; - - case '3': - font_info.flags |= GRUB_FONT_FLAG_8BIT_AA; - break; default: usage (1); @@ -739,8 +697,8 @@ FT_Done_FreeType (ft_lib); - if (file_format == PFN) - write_font_pfN (&font_info, output_file); + if (file_format == PF2) + write_font_pf2 (&font_info, output_file); else if (file_format == ASCII_BITMAPS) write_font_ascii_bitmap (&font_info, output_file);
_______________________________________________ Grub-devel mailing list Grub-devel@gnu.org http://lists.gnu.org/mailman/listinfo/grub-devel