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
[email protected]
http://lists.gnu.org/mailman/listinfo/grub-devel