=== modified file 'commands/videotest.c'
--- commands/videotest.c 2007-07-21 22:32:33 +0000
+++ commands/videotest.c 2008-10-05 04:30:04 +0000
@@ -44,7 +44,8 @@
unsigned int width;
unsigned int height;
int i;
- struct grub_font_glyph glyph;
+ grub_font_t font;
+ struct grub_font_glyph *glyph;
struct grub_video_render_target *text_layer;
grub_video_color_t palette[16];
@@ -65,8 +66,12 @@
color = grub_video_map_rgb (0, 255, 255);
grub_video_fill_rect (color, 100, 100, 100, 100);
- grub_font_get_glyph ('*', &glyph);
- grub_video_blit_glyph (&glyph, color, 200 ,0);
+ font = grub_font_get ("Helvetica Bold 14");
+ if (! font)
+ return grub_error (GRUB_ERR_BAD_FONT, "No font loaded.");
+
+ glyph = grub_font_get_glyph (font, '*');
+ grub_video_blit_glyph (glyph, color, 200 ,0);
grub_video_set_viewport (x + 150, y + 150,
width - 150 * 2, height - 150 * 2);
@@ -77,18 +82,18 @@
color = grub_video_map_rgb (255, 255, 255);
- grub_font_get_glyph ('A', &glyph);
- grub_video_blit_glyph (&glyph, color, 16, 16);
- grub_font_get_glyph ('B', &glyph);
- grub_video_blit_glyph (&glyph, color, 16 * 2, 16);
+ glyph = grub_font_get_glyph (font, 'A');
+ grub_video_blit_glyph (glyph, color, 16, 16);
+ glyph = grub_font_get_glyph (font, 'B');
+ grub_video_blit_glyph (glyph, color, 16 * 2, 16);
- grub_font_get_glyph ('*', &glyph);
+ glyph = grub_font_get_glyph (font, '*');
for (i = 0; i < 16; i++)
{
color = grub_video_map_color (i);
palette[i] = color;
- grub_video_blit_glyph (&glyph, color, 16 + i * 16, 32);
+ grub_video_blit_glyph (glyph, color, 16 + i * 16, 32);
}
grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY);
=== modified file 'conf/common.rmk'
--- conf/common.rmk 2008-09-29 13:57:05 +0000
+++ conf/common.rmk 2008-10-05 04:30:04 +0000
@@ -364,7 +364,7 @@
help_mod_LDFLAGS = $(COMMON_LDFLAGS)
# For font.mod.
-font_mod_SOURCES = font/manager.c
+font_mod_SOURCES = font/font_cmd.c font/font.c font/loader.c
font_mod_CFLAGS = $(COMMON_CFLAGS)
font_mod_LDFLAGS = $(COMMON_LDFLAGS)
=== modified file 'conf/sparc64-ieee1275.rmk'
--- conf/sparc64-ieee1275.rmk 2008-09-08 12:52:30 +0000
+++ conf/sparc64-ieee1275.rmk 2008-10-05 04:30:04 +0000
@@ -196,7 +196,7 @@
cat_mod_LDFLAGS = $(COMMON_LDFLAGS)
# For font.mod.
-font_mod_SOURCES = font/manager.c
+font_mod_SOURCES = font/font_cmd.c font/font.c font/loader.c
font_mod_CFLAGS = $(COMMON_CFLAGS)
font_mod_LDFLAGS = $(COMMON_LDFLAGS)
=== added file 'font/font.c'
--- font/font.c 1970-01-01 00:00:00 +0000
+++ font/font.c 2008-10-05 04:30:04 +0000
@@ -0,0 +1,92 @@
+/* font.c - Font functions. */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2008 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
+#include
+
+grub_font_t
+grub_font_get (const char *font_name)
+{
+ struct font_node *node;
+
+ for (node = grub_font_list; node; node = node->next)
+ {
+ grub_font_t font = node->value;
+ if (grub_strcmp (font->name, font_name) == 0)
+ return font;
+ }
+
+ /* If no font by that name is found, return the first font in the list
+ * as a fallback. */
+ return grub_font_list->value;
+}
+
+const char *
+grub_font_get_name (grub_font_t font)
+{
+ return font->name;
+}
+
+int
+grub_font_get_max_char_width (grub_font_t font)
+{
+ return font->max_char_width;
+}
+
+int
+grub_font_get_max_char_height (grub_font_t font)
+{
+ return font->max_char_height;
+}
+
+int
+grub_font_get_ascent (grub_font_t font)
+{
+ return font->ascent;
+}
+
+int
+grub_font_get_descent (grub_font_t font)
+{
+ return font->descent;
+}
+
+int
+grub_font_get_string_width (grub_font_t font, const char *str)
+{
+ int i;
+ int width;
+ struct grub_font_glyph *glyph;
+ grub_size_t len;
+
+ len = grub_strlen (str);
+
+ for (i = 0, width = 0; i < len; i++)
+ {
+ glyph = grub_font_get_glyph (font, str[i]);
+ width += glyph->device_width;
+ }
+
+ return width;
+}
=== added file 'font/font_cmd.c'
--- font/font_cmd.c 1970-01-01 00:00:00 +0000
+++ font/font_cmd.c 2008-10-05 04:30:04 +0000
@@ -0,0 +1,75 @@
+/* font_cmd.c - Font command definition. */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2003,2005,2006,2007 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
+
+static grub_err_t
+loadfont_command (struct grub_arg_list *state __attribute__ ((unused)),
+ int argc,
+ char **args)
+{
+ if (argc == 0)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "no font specified");
+
+ while (argc--)
+ if (grub_font_load (*args++) != 0)
+ return GRUB_ERR_BAD_FONT;
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+lsfonts_command (struct grub_arg_list *state __attribute__ ((unused)),
+ int argc __attribute__ ((unused)),
+ char **args __attribute__ ((unused)))
+{
+ struct font_node *node;
+
+ grub_printf ("Loaded fonts:\n");
+ for (node = grub_font_list; node; node = node->next)
+ {
+ grub_font_t font = node->value;
+ grub_printf ("%s\n", font->name);
+ }
+
+ return GRUB_ERR_NONE;
+}
+
+GRUB_MOD_INIT(font_manager)
+{
+ grub_font_loader_init ();
+
+ grub_register_command ("loadfont", loadfont_command, GRUB_COMMAND_FLAG_BOTH,
+ "loadfont FILE...",
+ "Specify one or more font files to load.", 0);
+
+ grub_register_command ("lsfonts", lsfonts_command, GRUB_COMMAND_FLAG_BOTH,
+ "lsfonts",
+ "List the loaded fonts.", 0);
+}
+
+GRUB_MOD_FINI(font_manager)
+{
+ /* Should this free fonts, unknown_glyph, etc.? Freeing fonts could
+ * be a Bad Thing if there are still references to any of them. */
+
+ grub_unregister_command ("loadfont");
+}
+
=== added file 'font/loader.c'
--- font/loader.c 1970-01-01 00:00:00 +0000
+++ font/loader.c 2008-10-05 04:30:04 +0000
@@ -0,0 +1,689 @@
+/* loader.c - Functions to handle loading fonts and glyphs from files. */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2003,2005,2006,2007,2008 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
+
+/* Definition of font registry. */
+struct font_node *grub_font_list;
+
+static int register_font (grub_font_t font);
+static void free_font (grub_font_t font);
+static void remove_font (grub_font_t font);
+
+struct font_file_section
+{
+ grub_file_t file; /* The file this section is in. */
+ char name[4]; /* FOURCC name of the section. */
+ grub_uint32_t length; /* Length of the section contents. */
+ int eof; /* Set by open_section() on EOF. */
+};
+
+/* Font file format constants. */
+static const char pff2_magic[4] = { 'P', 'F', 'F', '2' };
+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_max_char_width[4] = { 'M', 'A', 'X', 'W' };
+static const char section_names_max_char_height[4] = { 'M', 'A', 'X', 'H' };
+static const char section_names_ascent[4] = { 'A', 'S', 'C', 'E' };
+static const char section_names_descent[4] = { 'D', 'E', 'S', 'C' };
+static const char section_names_char_index[4] = { 'C', 'H', 'I', 'X' };
+static const char section_names_data[4] = { 'D', 'A', 'T', 'A' };
+
+/* Replace unknown glyphs with a rounded question mark. */
+static grub_uint8_t unknown_glyph_bitmap[] =
+{
+ /* 76543210 */
+ 0x7C, /* ooooo */
+ 0x82, /* o o */
+ 0xBA, /* o ooo o */
+ 0xAA, /* o o o o */
+ 0xAA, /* o o o o */
+ 0x8A, /* o o o */
+ 0x9A, /* o oo o */
+ 0x92, /* o o o */
+ 0x92, /* o o o */
+ 0x92, /* o o o */
+ 0x92, /* o o o */
+ 0x82, /* o o */
+ 0x92, /* o o o */
+ 0x82, /* o o */
+ 0x7C, /* ooooo */
+ 0x00 /* */
+};
+
+static struct grub_font_glyph *unknown_glyph;
+
+void
+grub_font_loader_init (void)
+{
+ unknown_glyph = grub_malloc(sizeof(struct grub_font_glyph)
+ + sizeof(unknown_glyph_bitmap));
+ if (! unknown_glyph)
+ return;
+
+ unknown_glyph->width = 8;
+ unknown_glyph->height = 16;
+ unknown_glyph->offset_x = 0;
+ unknown_glyph->offset_y = 0;
+ unknown_glyph->device_width = 8;
+ grub_memcpy(unknown_glyph->bitmap,
+ unknown_glyph_bitmap, sizeof(unknown_glyph_bitmap));
+}
+
+/*
+ Open the next section in the file.
+
+ On success, the section name is stored in section->name and the length in
+ section->length, and 0 is returned. On failure, 1 is returned and
+ grub_errno is set approriately with an error message.
+
+ If 1 is returned due to being at the end of the file, then section->eof is
+ set to 1; otherwise, section->eof is set to 0.
+ */
+static int
+open_section (grub_file_t file, struct font_file_section *section)
+{
+ grub_ssize_t retval;
+ grub_uint32_t raw_length;
+
+ section->file = file;
+ section->eof = 0;
+
+ /* Read the FOURCC section name. */
+ retval = grub_file_read (file, section->name, 4);
+ if (retval >= 0 && retval < 4)
+ {
+ section->eof = 1;
+ return 1; /* EOF encountered. */
+ }
+ else if (retval < 0)
+ {
+ grub_error (GRUB_ERR_BAD_FONT,
+ "Font format error: can't read section name");
+ return 1; /* Read error. */
+ }
+
+ /* Read the big-endian 32-bit section length. */
+ retval = grub_file_read (file, (char *) &raw_length, 4);
+ if (retval >= 0 && retval < 4)
+ {
+ section->eof = 1;
+ return 1; /* EOF encountered. */
+ }
+ else if (retval < 0)
+ {
+ grub_error (GRUB_ERR_BAD_FONT,
+ "Font format error: can't read section length");
+ return 1; /* Read error. */
+ }
+
+ /* Convert byte-order and store in *length. */
+ section->length = grub_be_to_cpu32 (raw_length);
+
+ return 0;
+}
+
+/* Size in bytes of each character index (CHIX section)
+ entry in the font file. */
+#define FONT_CHAR_INDEX_ENTRY_SIZE (4 + 1 + 4)
+
+/*
+ Load the character index (CHIX) section contents from the font file. This
+ presumes that the position of FILE is positioned immediately after the
+ section length for the CHIX section (i.e., at the start of the section
+ contents). Returns 0 upon success, nonzero for failure (in which case
+ grub_errno is set appropriately).
+ */
+static int
+load_font_index (grub_file_t file, grub_uint32_t sect_length, struct
+ grub_font *font)
+{
+ unsigned i;
+
+#if FONT_DEBUG >= 2
+ grub_printf("load_font_index(sect_length=%d)\n", sect_length);
+#endif
+
+ /* Sanity check: ensure section length is divisible by the entry size. */
+ if (sect_length % FONT_CHAR_INDEX_ENTRY_SIZE != 0)
+ {
+ grub_error (GRUB_ERR_BAD_FONT,
+ "Font file format error: character index length %d "
+ "is not a multiple of the entry size %d",
+ sect_length, FONT_CHAR_INDEX_ENTRY_SIZE);
+ return 1; /* Invalid index section length. */
+ }
+
+ /* Calculate the number of characters. */
+ font->num_chars = sect_length / FONT_CHAR_INDEX_ENTRY_SIZE;
+
+ /* Allocate the character index array. */
+ font->char_index = grub_malloc (font->num_chars
+ * sizeof (struct char_index_entry));
+ if (!font->char_index)
+ return 1; /* Error allocating memory. */
+
+#if FONT_DEBUG >= 2
+ grub_printf("num_chars=%d)\n", font->num_chars);
+#endif
+
+ /* Load the character index data from the file. */
+ for (i = 0; i < font->num_chars; i++)
+ {
+ struct char_index_entry *entry = &font->char_index[i];
+
+ /* Read code point value; convert to native byte order. */
+ if (grub_file_read (file, (char *) &entry->code, 4) != 4)
+ return 1;
+ entry->code = grub_be_to_cpu32 (entry->code);
+
+ /* Read storage flags byte. */
+ if (grub_file_read (file, (char *) &entry->storage_flags, 1) != 1)
+ return 1;
+
+ /* Read glyph data offset; convert to native byte order. */
+ if (grub_file_read (file, (char *) &entry->offset, 4) != 4)
+ return 1;
+ entry->offset = grub_be_to_cpu32 (entry->offset);
+
+ /* No glyph loaded. Will be loaded on demand and cached thereafter. */
+ entry->glyph = 0;
+
+#if FONT_DEBUG >= 5
+ if (i < 10) /* Print the 1st 10 characters. */
+ grub_printf("c=%d o=%d\n", entry->code, entry->offset);
+#endif
+ }
+
+ return 0; /* Index loaded OK. */
+}
+
+/*
+ Read the contents of the specified section as a string, which is
+ allocated on the heap. Returns 0 if there is an error.
+ */
+static char *
+read_section_as_string (struct font_file_section *section)
+{
+ char *str;
+ grub_ssize_t ret;
+
+ str = grub_malloc (section->length + 1);
+ if (!str)
+ return 0;
+
+ ret = grub_file_read (section->file, str, section->length);
+ if (ret < 0 || ret != (grub_ssize_t) section->length)
+ {
+ grub_free (str);
+ return 0;
+ }
+
+ str[section->length] = '\0';
+ return str;
+}
+
+/*
+ Read the contents of the current section as a 16-bit integer value,
+ which is stored into *VALUE. Returns 0 upon success, nonzero upon failure.
+ */
+static int
+read_section_as_short (struct font_file_section *section, grub_int16_t *value)
+{
+ grub_uint16_t raw_value;
+
+ if (section->length != 2)
+ {
+ grub_error (GRUB_ERR_BAD_FONT,
+ "Font file format error: section %c%c%c%c length "
+ "is %d but should be 2",
+ section->name[0], section->name[1],
+ section->name[2], section->name[3],
+ section->length);
+ return 1; /* An error occurred. */
+ }
+ if (grub_file_read (section->file, (char *) &raw_value, 2) != 2)
+ return 1; /* An error occurred. */
+
+ *value = grub_be_to_cpu16 (raw_value);
+ return 0; /* Successfully read the value. */
+}
+
+/*
+ Load a font and add it to the beginning of the global font list.
+ Returns 0 upon success, nonzero upon failure.
+ */
+int
+grub_font_load (const char *filename)
+{
+ grub_file_t file = 0;
+ struct font_file_section section;
+ char magic[4];
+ grub_font_t font = 0;
+
+#if FONT_DEBUG >= 1
+ grub_printf("add_font(%s)\n", filename);
+#endif
+
+ file = grub_buffile_open (filename, 1024);
+ if (!file)
+ goto fail;
+
+#if FONT_DEBUG >= 3
+ grub_printf("file opened\n");
+#endif
+
+ /* Read the FILE section. It indicates the file format. */
+ if (open_section (file, §ion) != 0)
+ goto fail;
+
+#if FONT_DEBUG >= 3
+ grub_printf("opened FILE section\n");
+#endif
+ if (grub_memcmp (section.name, section_names_file, 4) != 0)
+ {
+ grub_error (GRUB_ERR_BAD_FONT,
+ "Font file format error: 1st section must be FILE");
+ goto fail;
+ }
+
+#if FONT_DEBUG >= 3
+ grub_printf("section name ok\n");
+#endif
+ if (section.length != 4)
+ {
+ grub_error (GRUB_ERR_BAD_FONT,
+ "Font file format error (file type ID length is %d "
+ "but should be 4)", section.length);
+ goto fail;
+ }
+
+#if FONT_DEBUG >= 3
+ grub_printf("section length ok\n");
+#endif
+ /* Check the file format type code. */
+ if (grub_file_read (file, magic, 4) != 4)
+ goto fail;
+
+#if FONT_DEBUG >= 3
+ grub_printf("read magic ok\n");
+#endif
+
+ 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;
+ }
+
+#if FONT_DEBUG >= 3
+ grub_printf("compare magic ok\n");
+#endif
+
+ /* Allocate the font object. */
+ font = (grub_font_t) grub_malloc (sizeof (struct grub_font));
+ if (!font)
+ goto fail;
+
+ font->file = file;
+ font->name = 0;
+ font->ascent = 0;
+ font->descent = 0;
+ font->max_char_width = 0;
+ font->max_char_height = 0;
+ font->num_chars = 0;
+ font->char_index = 0;
+
+#if FONT_DEBUG >= 3
+ grub_printf("allocate font ok; loading font info\n");
+#endif
+
+ /* Load the font information. */
+ while (1)
+ {
+ if (open_section (file, §ion) != 0)
+ {
+ if (section.eof)
+ break; /* Done reading the font file. */
+ else
+ goto fail;
+ }
+
+#if FONT_DEBUG >= 2
+ grub_printf("opened section %c%c%c%c ok\n",
+ section.name[0], section.name[1],
+ section.name[2], section.name[3]);
+#endif
+
+ if (grub_memcmp (section.name, section_names_font_name, 4) == 0)
+ {
+ font->name = read_section_as_string (§ion);
+ if (!font->name)
+ goto fail;
+ }
+ else if (grub_memcmp (section.name, section_names_max_char_width, 4) == 0)
+ {
+ if (read_section_as_short (§ion, &font->max_char_width) != 0)
+ goto fail;
+ }
+ else if (grub_memcmp (section.name, section_names_max_char_height, 4) == 0)
+ {
+ if (read_section_as_short (§ion, &font->max_char_height) != 0)
+ goto fail;
+ }
+ else if (grub_memcmp (section.name, section_names_ascent, 4) == 0)
+ {
+ if (read_section_as_short (§ion, &font->ascent) != 0)
+ goto fail;
+ }
+ else if (grub_memcmp (section.name, section_names_descent, 4) == 0)
+ {
+ if (read_section_as_short (§ion, &font->descent) != 0)
+ goto fail;
+ }
+ else if (grub_memcmp (section.name, section_names_char_index, 4) == 0)
+ {
+ /* Load the font index. */
+ if (load_font_index (file, section.length, font) != 0)
+ goto fail;
+ }
+ else if (grub_memcmp (section.name, section_names_data, 4) == 0)
+ {
+ /* When the DATA section marker is reached, we stop reading. */
+ break;
+ }
+ else
+ {
+ /* Unhandled section type, simply skip past it. */
+#if FONT_DEBUG >= 3
+ grub_printf("Unhandled section type, skipping.\n");
+#endif
+ grub_off_t section_end = grub_file_tell (file) + section.length;
+ if ((int) grub_file_seek (file, section_end) == -1)
+ goto fail;
+ }
+ }
+
+ if (!font->name)
+ {
+ grub_printf ("Note: Font has no name.\n");
+ font->name = grub_strdup ("Unknown");
+ }
+
+#if FONT_DEBUG >= 1
+ grub_printf ("Loaded font `%s'.\n"
+ "Ascent=%d Descent=%d MaxW=%d MaxH=%d Number of characters=%d.\n",
+ font->name,
+ font->ascent, font->descent,
+ font->max_char_width, font->max_char_height,
+ font->num_chars);
+#endif
+
+ if (font->max_char_width == 0
+ || font->max_char_height == 0
+ || font->num_chars == 0
+ || font->char_index == 0
+ || font->ascent == 0
+ || font->descent == 0)
+ {
+ grub_error (GRUB_ERR_BAD_FONT,
+ "Invalid font file: missing some required data.");
+ goto fail;
+ }
+
+ /* Add the font to the global font registry. */
+ if (register_font (font) != 0)
+ goto fail;
+
+ return 0; /* Font loaded ok. */
+
+fail:
+ free_font (font);
+ return 1; /* Failed to load font. */
+}
+
+/*
+ Read a 16-bit big-endian integer from FILE, convert it to native byte
+ order, and store it in *VALUE.
+ Returns 0 on success, 1 on failure.
+ */
+static int
+read_be_uint16 (grub_file_t file, grub_uint16_t * value)
+{
+ if (grub_file_read (file, (char *) value, 2) != 2)
+ return 1;
+ *value = grub_be_to_cpu16 (*value);
+ return 0;
+}
+
+static int
+read_be_int16 (grub_file_t file, grub_int16_t * value)
+{
+ /* For the signed integer version, use the same code as for unsigned. */
+ return read_be_uint16 (file, (grub_uint16_t *) value);
+}
+
+/*
+ Return a pointer to the character index entry for the glyph corresponding to
+ the codepoint CODE in the font FONT. If not found, return zero.
+ */
+static struct char_index_entry *
+find_glyph (const grub_font_t font, grub_uint32_t code)
+{
+ grub_uint32_t i;
+ grub_uint32_t len = font->num_chars;
+ struct char_index_entry *table = font->char_index;
+
+ /* Do a linear search. */
+ for (i = 0; i < len; i++)
+ {
+ if (table[i].code == code)
+ return &table[i];
+ }
+
+ return 0; /* No entry found for code point CODE. */
+}
+
+static struct grub_font_glyph *
+grub_font_get_glyph_internal (grub_font_t font, grub_uint32_t code)
+{
+ struct char_index_entry *index_entry;
+
+ index_entry = find_glyph (font, code);
+ if (index_entry)
+ {
+ struct grub_font_glyph *glyph = 0;
+ grub_uint16_t width;
+ grub_uint16_t height;
+ grub_int16_t xoff;
+ grub_int16_t yoff;
+ grub_int16_t dwidth;
+ int len;
+
+ if (index_entry->glyph)
+ return index_entry->glyph; /* Return cached glyph. */
+
+ /* Make sure we can find glyphs for error messages. Push active
+ error message to error stack and reset error message. */
+ grub_error_push ();
+
+ grub_file_seek (font->file, index_entry->offset);
+
+ /* Read the glyph width, height, and baseline. */
+ if (read_be_uint16(font->file, &width) != 0
+ || read_be_uint16(font->file, &height) != 0
+ || read_be_int16(font->file, &xoff) != 0
+ || read_be_int16(font->file, &yoff) != 0
+ || read_be_int16(font->file, &dwidth) != 0)
+ {
+ remove_font (font);
+ return 0;
+ }
+
+ len = (width * height + 7) / 8;
+ glyph = grub_malloc (sizeof (struct grub_font_glyph) + len);
+ if (! glyph)
+ {
+ remove_font (font);
+ return 0;
+ }
+
+ glyph->font = font;
+ glyph->width = width;
+ glyph->height = height;
+ glyph->offset_x = xoff;
+ glyph->offset_y = yoff;
+ glyph->device_width = dwidth;
+
+ /* Don't try to read empty bitmaps (e.g., space characters). */
+ if (len != 0)
+ {
+ if (grub_file_read (font->file, (char *) glyph->bitmap, len) != len)
+ {
+ remove_font (font);
+ return 0;
+ }
+ }
+
+ /* Restore old error message. */
+ grub_error_pop ();
+
+ /* Cache the glyph. */
+ index_entry->glyph = glyph;
+
+ return glyph; /* Glyph loaded ok. */
+ }
+
+ return 0;
+}
+
+/* Get the glyph for FONT corresponding to the Unicode code point CODE.
+ Returns a pointer to an glyph indicating there is no glyph available
+ if CODE does not exist in the font. The glyphs are cached once loaded. */
+struct grub_font_glyph *
+grub_font_get_glyph (grub_font_t font, grub_uint32_t code)
+{
+ struct grub_font_glyph *glyph;
+ glyph = grub_font_get_glyph_internal (font, code);
+ if (glyph == 0)
+ glyph = unknown_glyph;
+ return glyph;
+}
+
+/* Get a glyph corresponding to the codepoint CODE. If no glyph is available
+ for CODE in the available fonts, then a glyph representing an unknown
+ character is returned. This function never returns NULL.
+ The returned glyph is owned by the font manager and should not be freed
+ by the caller. The glyphs are cached. */
+struct grub_font_glyph *
+grub_font_get_glyph_any (grub_uint32_t code)
+{
+ struct font_node *node;
+ /* Keep track of next node, in case there's an I/O error in
+ grub_font_get_glyph() and the font is removed from the list. */
+ struct font_node *next;
+
+ for (node = grub_font_list; node; node = next)
+ {
+ grub_font_t font;
+ struct grub_font_glyph *glyph;
+
+ font = node->value;
+ next = node->next;
+
+ glyph = grub_font_get_glyph_internal (font, code);
+ if (glyph)
+ return glyph;
+ }
+
+ /* Uggh... Glyph was not found in any font. */
+ return unknown_glyph; /* Failed to load glyph. */
+}
+
+/*
+ Free the memory used by a font.
+ This should not be called if the font has been made available to
+ users (once it is added to the global font list), since there would
+ be the possibility of a dangling pointer.
+ */
+static void
+free_font (grub_font_t font)
+{
+ if (font)
+ {
+ if (font->file)
+ grub_file_close (font->file);
+ if (font->name)
+ grub_free (font->name);
+ if (font->char_index)
+ grub_free (font->char_index);
+ grub_free (font);
+ }
+}
+
+/*
+ Add FONT to the global font registry.
+ Returns 0 upon success, nonzero on failure (the font was not registered).
+ */
+static int
+register_font (grub_font_t font)
+{
+ struct font_node *node = 0;
+
+ node = grub_malloc (sizeof (struct font_node));
+ if (!node)
+ return 1; /* Error. */
+
+ node->value = font;
+ node->next = grub_font_list;
+ grub_font_list = node;
+
+ return 0; /* Success. */
+}
+
+/*
+ Remove the font from the global font list. We don't actually free the
+ font's memory since users could be holding references to the font.
+ */
+static void
+remove_font (grub_font_t font)
+{
+ struct font_node **nextp, *cur;
+
+ for (nextp = &grub_font_list, cur = *nextp;
+ cur;
+ nextp = &cur->next, cur = cur->next)
+ {
+ if (cur->value == font)
+ {
+ *nextp = cur->next;
+
+ /* Free the node, but not the font itself. */
+ grub_free (cur);
+
+ return;
+ }
+ }
+}
+
=== removed file 'font/manager.c'
--- font/manager.c 2008-08-01 03:06:55 +0000
+++ font/manager.c 1970-01-01 00:00:00 +0000
@@ -1,283 +0,0 @@
-/*
- * GRUB -- GRand Unified Bootloader
- * Copyright (C) 2003,2005,2006,2007 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
-#include
-#include
-
-struct entry
-{
- grub_uint32_t code;
- grub_uint32_t offset;
-};
-
-struct font
-{
- struct font *next;
- grub_file_t file;
- grub_uint32_t num;
- struct entry table[0];
-};
-
-static struct font *font_list;
-
-/* Fill unknown glyph's with rounded question mark. */
-static grub_uint8_t unknown_glyph[16] =
-{ /* 76543210 */
- 0x7C, /* ooooo */
- 0x82, /* o o */
- 0xBA, /* o ooo o */
- 0xAA, /* o o o o */
- 0xAA, /* o o o o */
- 0x8A, /* o o o */
- 0x9A, /* o oo o */
- 0x92, /* o o o */
- 0x92, /* o o o */
- 0x92, /* o o o */
- 0x92, /* o o o */
- 0x82, /* o o */
- 0x92, /* o o o */
- 0x82, /* o o */
- 0x7C, /* ooooo */
- 0x00 /* */
-};
-
-static int
-add_font (const char *filename)
-{
- grub_file_t file = 0;
- char magic[4];
- grub_uint32_t num, i;
- struct font *font = 0;
-
- file = grub_buffile_open (filename, 0);
- if (! file)
- goto fail;
-
- if (grub_file_read (file, magic, 4) != 4)
- goto fail;
-
- if (grub_memcmp (magic, GRUB_FONT_MAGIC, 4) != 0)
- {
- grub_error (GRUB_ERR_BAD_FONT, "invalid font magic");
- goto fail;
- }
-
- if (grub_file_read (file, (char *) &num, 4) != 4)
- goto fail;
-
- num = grub_le_to_cpu32 (num);
- font = (struct font *) grub_malloc (sizeof (struct font)
- + sizeof (struct entry) * num);
- if (! font)
- goto fail;
-
- font->file = file;
- font->num = num;
-
- for (i = 0; i < num; i++)
- {
- grub_uint32_t code, offset;
-
- if (grub_file_read (file, (char *) &code, 4) != 4)
- goto fail;
-
- if (grub_file_read (file, (char *) &offset, 4) != 4)
- goto fail;
-
- font->table[i].code = grub_le_to_cpu32 (code);
- font->table[i].offset = grub_le_to_cpu32 (offset);
- }
-
- font->next = font_list;
- font_list = font;
-
- return 1;
-
- fail:
- if (font)
- grub_free (font);
-
- if (file)
- grub_file_close (file);
-
- return 0;
-}
-
-static void
-remove_font (struct font *font)
-{
- struct font **p, *q;
-
- for (p = &font_list, q = *p; q; p = &(q->next), q = q->next)
- if (q == font)
- {
- *p = q->next;
-
- grub_file_close (font->file);
- grub_free (font);
-
- break;
- }
-}
-
-/* Return the offset of the glyph corresponding to the codepoint CODE
- in the font FONT. If no found, return zero. */
-static grub_uint32_t
-find_glyph (const struct font *font, grub_uint32_t code)
-{
- grub_uint32_t start = 0;
- grub_uint32_t end = font->num - 1;
- const struct entry *table = font->table;
-
- /* This shouldn't happen. */
- if (font->num == 0)
- return 0;
-
- /* Do a binary search. */
- while (start <= end)
- {
- grub_uint32_t i = (start + end) / 2;
-
- if (table[i].code < code)
- start = i + 1;
- else if (table[i].code > code)
- end = i - 1;
- else
- return table[i].offset;
- }
-
- return 0;
-}
-
-/* Set the glyph to something stupid. */
-static void
-fill_with_default_glyph (grub_font_glyph_t glyph)
-{
- unsigned i;
-
- /* Use pre-defined pattern to fill unknown glyphs. */
- for (i = 0; i < 16; i++)
- glyph->bitmap[i] = unknown_glyph[i];
-
- glyph->char_width = 1;
- glyph->width = glyph->char_width * 8;
- glyph->height = 16;
- glyph->baseline = (16 * 3) / 4;
-}
-
-/* Get a glyph corresponding to the codepoint CODE. Always fill glyph
- information with something, even if no glyph is found. */
-int
-grub_font_get_glyph (grub_uint32_t code,
- grub_font_glyph_t glyph)
-{
- struct font *font;
- grub_uint8_t bitmap[32];
-
- /* FIXME: It is necessary to cache glyphs! */
-
- restart:
- for (font = font_list; font; font = font->next)
- {
- grub_uint32_t offset;
-
- offset = find_glyph (font, code);
- if (offset)
- {
- grub_uint32_t w;
- int len;
-
- /* Make sure we can find glyphs for error messages. Push active
- error message to error stack and reset error message. */
- grub_error_push ();
-
- grub_file_seek (font->file, offset);
- if ((len = grub_file_read (font->file, (char *) &w, sizeof (w)))
- != sizeof (w))
- {
- remove_font (font);
- goto restart;
- }
-
- w = grub_le_to_cpu32 (w);
- if (w != 1 && w != 2)
- {
- /* grub_error (GRUB_ERR_BAD_FONT, "invalid width"); */
- remove_font (font);
- goto restart;
- }
-
- if (grub_file_read (font->file, (char *) bitmap, w * 16)
- != (grub_ssize_t) w * 16)
- {
- remove_font (font);
- goto restart;
- }
-
- /* Fill glyph with information. */
- grub_memcpy (glyph->bitmap, bitmap, w * 16);
-
- glyph->char_width = w;
- glyph->width = glyph->char_width * 8;
- glyph->height = 16;
- glyph->baseline = (16 * 3) / 4;
-
- /* Restore old error message. */
- grub_error_pop ();
-
- return 1;
- }
- }
-
- /* Uggh... No font was found. */
- fill_with_default_glyph (glyph);
- return 0;
-}
-
-static grub_err_t
-font_command (struct grub_arg_list *state __attribute__ ((unused)),
- int argc __attribute__ ((unused)),
- char **args __attribute__ ((unused)))
-{
- if (argc == 0)
- return grub_error (GRUB_ERR_BAD_ARGUMENT, "no font specified");
-
- while (argc--)
- if (! add_font (*args++))
- return 1;
-
- return 0;
-}
-
-GRUB_MOD_INIT(font_manager)
-{
- grub_register_command ("font", font_command, GRUB_COMMAND_FLAG_BOTH,
- "font FILE...",
- "Specify one or more font files to display.", 0);
-}
-
-GRUB_MOD_FINI(font_manager)
-{
- grub_unregister_command ("font");
-}
=== modified file 'include/grub/font.h'
--- include/grub/font.h 2007-07-21 22:32:33 +0000
+++ include/grub/font.h 2008-10-05 04:30:04 +0000
@@ -1,6 +1,6 @@
/*
* GRUB -- GRand Unified Bootloader
- * Copyright (C) 2003,2007 Free Software Foundation, Inc.
+ * Copyright (C) 2003,2007,2008 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
@@ -21,33 +21,85 @@
#include
-#define GRUB_FONT_MAGIC "PPF\x7f"
+/* Forward declaration of opaque structure grub_font.
+ * Users only pass struct grub_font pointers to the font module functions,
+ * and do not have knowledge of the structure contents. */
+struct grub_font;
+
+/* Font type used to access font functions. */
+typedef struct grub_font *grub_font_t;
+
struct grub_font_glyph
{
- /* Glyph width in pixels. */
- grub_uint8_t width;
-
- /* Glyph height in pixels. */
- grub_uint8_t height;
-
- /* Glyph width in characters. */
- grub_uint8_t char_width;
-
- /* Glyph baseline position in pixels (from up). */
- grub_uint8_t baseline;
-
- /* Glyph bitmap data array of bytes in ((width + 7) / 8) * height.
- Bitmap is formulated by height scanlines, each scanline having
- width number of pixels. Pixels are coded as bits, value 1 meaning
- of opaque pixel and 0 is transparent. If width does not fit byte
- boundary, it will be padded with 0 to make it fit. */
- grub_uint8_t bitmap[32];
+ /* Reference to the font this glyph belongs to. */
+ grub_font_t font;
+
+ /* Glyph bitmap width in pixels. */
+ grub_uint16_t width;
+
+ /* Glyph bitmap height in pixels. */
+ grub_uint16_t height;
+
+ /* Glyph bitmap x offset in pixels. Add to screen coordinate. */
+ grub_int16_t offset_x;
+
+ /* Glyph bitmap y offset in pixels. Subtract from screen coordinate. */
+ grub_int16_t offset_y;
+
+ /* Number of pixels to advance to start the next character. */
+ grub_uint16_t device_width;
+
+ /* Row-major order, packed bits (no padding; rows can break within a byte).
+ * The length of the array is (width * height + 7) / 8. Within a
+ * byte, the most significant bit is the first (leftmost/uppermost) pixel.
+ * Pixels are coded as bits, value 1 meaning of opaque pixel and 0 is
+ * transparent. If the length of the array does not fit byte boundary, it
+ * will be padded with 0 bits to make it fit. */
+ grub_uint8_t bitmap[0];
};
-typedef struct grub_font_glyph *grub_font_glyph_t;
-
-int grub_font_get_glyph (grub_uint32_t code,
- grub_font_glyph_t glyph);
+
+/****** font/font.c ******/
+
+/* Get the font that has the specified name. Font names are in the form
+ * "Family Name Bold Italic 14", where Bold and Italic are optional.
+ * If no font matches the name specified, the most recently loaded font
+ * is returned as a fallback. */
+grub_font_t grub_font_get (const char *font_name);
+
+const char *grub_font_get_name (grub_font_t font);
+
+int grub_font_get_max_char_width (grub_font_t font);
+
+int grub_font_get_max_char_height (grub_font_t font);
+
+int grub_font_get_ascent (grub_font_t font);
+
+int grub_font_get_descent (grub_font_t font);
+
+int grub_font_get_string_width (grub_font_t font, const char *str);
+
+
+/****** font/loader.c ******/
+
+/*
+ * Load a font and add it to the beginning of the global font list.
+ * Returns: 0 upon success; nonzero upon failure.
+ */
+int grub_font_load (const char *filename);
+
+/* Get the glyph for FONT corresponding to the Unicode code point CODE.
+ * Returns a pointer to an glyph indicating there is no glyph available
+ * if CODE does not exist in the font. The glyphs are cached once loaded. */
+struct grub_font_glyph *grub_font_get_glyph (grub_font_t font,
+ grub_uint32_t code);
+
+/* Get a glyph corresponding to the codepoint CODE. If no glyph is available
+ * for CODE in the available fonts, then a glyph representing an unknown
+ * character is returned. This function never returns NULL.
+ * The returned glyph is owned by the font manager and should not be freed
+ * by the caller. The glyphs are cached. */
+struct grub_font_glyph *grub_font_get_glyph_any (grub_uint32_t code);
#endif /* ! GRUB_FONT_HEADER */
=== added file 'include/grub/font_internal.h'
--- include/grub/font_internal.h 1970-01-01 00:00:00 +0000
+++ include/grub/font_internal.h 2008-10-05 04:30:04 +0000
@@ -0,0 +1,71 @@
+/* font_internal.h - Font declarations for use internally by the font module.
+ * Users of the font module should not include this header. */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2003,2005,2006,2007,2008 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 .
+ */
+
+#ifndef GRUB_FONT_INTERNAL_HEADER
+#define GRUB_FONT_INTERNAL_HEADER 1
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define FONT_DEBUG 0
+
+struct char_index_entry
+{
+ grub_uint32_t code;
+ grub_uint8_t storage_flags;
+ grub_uint32_t offset;
+ struct grub_font_glyph *glyph; /* Glyph if loaded, or null. */
+};
+
+struct grub_font
+{
+ char *name;
+ grub_file_t file;
+ short max_char_width;
+ short max_char_height;
+ short ascent;
+ short descent;
+ grub_uint32_t num_chars;
+ struct char_index_entry *char_index;
+};
+
+struct font_node
+{
+ struct font_node *next;
+ struct grub_font *value;
+};
+
+extern struct font_node *grub_font_list;
+
+
+/****** loader.c ******/
+
+/* Initialize the font loader module. */
+void
+grub_font_loader_init (void);
+
+
+#endif /* ! GRUB_FONT_INTERNAL_HEADER */
+
=== modified file 'include/grub/video.h'
--- include/grub/video.h 2008-10-05 04:28:39 +0000
+++ include/grub/video.h 2008-10-05 04:30:04 +0000
@@ -21,6 +21,7 @@
#include
#include
+#include
/* Video color in hardware dependent format. Users should not assume any
specific coding format. */
@@ -31,17 +32,17 @@
struct grub_video_render_target;
/* Forward declarations for used data structures. */
-struct grub_font_glyph;
struct grub_video_bitmap;
/* Defines used to describe video mode or rendering target. */
-#define GRUB_VIDEO_MODE_TYPE_ALPHA 0x00000008
-#define GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED 0x00000004
+#define GRUB_VIDEO_MODE_TYPE_ALPHA 0x00000020
+#define GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED 0x00000010
+#define GRUB_VIDEO_MODE_TYPE_1BIT_BITMAP 0x00000004
#define GRUB_VIDEO_MODE_TYPE_INDEX_COLOR 0x00000002
#define GRUB_VIDEO_MODE_TYPE_RGB 0x00000001
/* Defines used to mask flags. */
-#define GRUB_VIDEO_MODE_TYPE_COLOR_MASK 0x00000003
+#define GRUB_VIDEO_MODE_TYPE_COLOR_MASK 0x0000000F
/* Defines used to specify requested bit depth. */
#define GRUB_VIDEO_MODE_TYPE_DEPTH_MASK 0x0000ff00
@@ -72,7 +73,9 @@
GRUB_VIDEO_BLIT_FORMAT_BGR_565,
/* When needed, decode color or just use value as is. */
- GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR
+ GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR,
+ /* Two color bitmap; bits packed: rows are not padded to byte boundary. */
+ GRUB_VIDEO_BLIT_FORMAT_1BIT_PACKED
};
/* Define blitting operators. */
@@ -135,6 +138,18 @@
/* What is location of reserved color bits. In Index Color mode,
this is 0. */
unsigned int reserved_field_pos;
+
+ /* For 1-bit bitmaps, the background color. Used for bits = 0. */
+ grub_uint8_t bg_red;
+ grub_uint8_t bg_green;
+ grub_uint8_t bg_blue;
+ grub_uint8_t bg_alpha;
+
+ /* For 1-bit bitmaps, the foreground color. Used for bits = 1. */
+ grub_uint8_t fg_red;
+ grub_uint8_t fg_green;
+ grub_uint8_t fg_blue;
+ grub_uint8_t fg_alpha;
};
struct grub_video_palette_data
@@ -189,7 +204,12 @@
unsigned int width, unsigned int height);
grub_err_t (*blit_glyph) (struct grub_font_glyph *glyph,
- grub_video_color_t color, int x, int y);
+ grub_video_color_t color,
+ int left_x, int baseline_y);
+
+ grub_err_t (*draw_string) (const char *str, grub_font_t font,
+ grub_video_color_t color,
+ int left_x, int baseline_y);
grub_err_t (*blit_bitmap) (struct grub_video_bitmap *bitmap,
enum grub_video_blit_operators oper,
@@ -261,7 +281,12 @@
unsigned int width, unsigned int height);
grub_err_t grub_video_blit_glyph (struct grub_font_glyph *glyph,
- grub_video_color_t color, int x, int y);
+ grub_video_color_t color,
+ int left_x, int baseline_y);
+
+grub_err_t grub_video_draw_string (const char *str, grub_font_t font,
+ grub_video_color_t color,
+ int left_x, int baseline_y);
grub_err_t grub_video_blit_bitmap (struct grub_video_bitmap *bitmap,
enum grub_video_blit_operators oper,
=== modified file 'term/gfxterm.c'
--- term/gfxterm.c 2008-08-31 03:08:13 +0000
+++ term/gfxterm.c 2008-10-05 04:30:04 +0000
@@ -35,9 +35,6 @@
#define DEFAULT_VIDEO_HEIGHT 480
#define DEFAULT_VIDEO_FLAGS 0
-#define DEFAULT_CHAR_WIDTH 8
-#define DEFAULT_CHAR_HEIGHT 16
-
#define DEFAULT_BORDER_WIDTH 10
#define DEFAULT_STANDARD_COLOR 0x07
@@ -91,6 +88,9 @@
unsigned int cursor_y;
int cursor_state;
+ /* Font settings. */
+ grub_font_t font;
+
/* Terminal color settings. */
grub_uint8_t standard_color_setting;
grub_uint8_t normal_color_setting;
@@ -169,18 +169,25 @@
static grub_err_t
grub_virtual_screen_setup (unsigned int x, unsigned int y,
- unsigned int width, unsigned int height)
+ unsigned int width, unsigned int height,
+ const char *font_name)
{
/* Free old virtual screen. */
grub_virtual_screen_free ();
/* Initialize with default data. */
+ virtual_screen.font = grub_font_get (font_name);
+ if (!virtual_screen.font)
+ return grub_error (GRUB_ERR_BAD_FONT,
+ "No font loaded.");
virtual_screen.width = width;
virtual_screen.height = height;
virtual_screen.offset_x = x;
virtual_screen.offset_y = y;
- virtual_screen.char_width = DEFAULT_CHAR_WIDTH;
- virtual_screen.char_height = DEFAULT_CHAR_HEIGHT;
+ virtual_screen.char_width =
+ grub_font_get_max_char_width (virtual_screen.font);
+ virtual_screen.char_height =
+ grub_font_get_max_char_height (virtual_screen.font);
virtual_screen.cursor_x = 0;
virtual_screen.cursor_y = 0;
virtual_screen.cursor_state = 1;
@@ -226,6 +233,7 @@
static grub_err_t
grub_gfxterm_init (void)
{
+ char *font_name;
char *modevar;
int width = DEFAULT_VIDEO_WIDTH;
int height = DEFAULT_VIDEO_HEIGHT;
@@ -233,6 +241,11 @@
int flags = DEFAULT_VIDEO_FLAGS;
grub_video_color_t color;
+ /* Select the font to use. */
+ font_name = grub_env_get ("gfxterm_font");
+ if (!font_name)
+ font_name = ""; /* Allow fallback to any font. */
+
/* Parse gfxmode environment variable if set. */
modevar = grub_env_get ("gfxmode");
if (modevar)
@@ -472,7 +485,7 @@
/* Create virtual screen. */
if (grub_virtual_screen_setup (DEFAULT_BORDER_WIDTH, DEFAULT_BORDER_WIDTH,
- width, height) != GRUB_ERR_NONE)
+ width, height, font_name) != GRUB_ERR_NONE)
{
grub_video_restore ();
return grub_errno;
@@ -658,11 +671,12 @@
write_char (void)
{
struct grub_colored_char *p;
- struct grub_font_glyph glyph;
+ struct grub_font_glyph *glyph;
grub_video_color_t color;
grub_video_color_t bgcolor;
unsigned int x;
unsigned int y;
+ int ascent;
/* Find out active character. */
p = (virtual_screen.text_buffer
@@ -672,7 +686,8 @@
p -= p->index;
/* Get glyph for character. */
- grub_font_get_glyph (p->code, &glyph);
+ glyph = grub_font_get_glyph (virtual_screen.font, p->code);
+ ascent = grub_font_get_ascent (virtual_screen.font);
color = p->fg_color;
bgcolor = p->bg_color;
@@ -682,13 +697,13 @@
/* Render glyph to text layer. */
grub_video_set_active_render_target (text_layer);
- grub_video_fill_rect (bgcolor, x, y, glyph.width, glyph.height);
- grub_video_blit_glyph (&glyph, color, x, y);
+ grub_video_fill_rect (bgcolor, x, y, glyph->width, glyph->height);
+ grub_video_blit_glyph (glyph, color, x, y + ascent);
grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY);
/* Mark character to be drawn. */
dirty_region_add (virtual_screen.offset_x + x, virtual_screen.offset_y + y,
- glyph.width, glyph.height);
+ glyph->width, glyph->height);
}
static void
@@ -702,7 +717,8 @@
/* Determine cursor properties and position on text layer. */
x = virtual_screen.cursor_x * virtual_screen.char_width;
- y = ((virtual_screen.cursor_y + 1) * virtual_screen.char_height) - 3;
+ y = (virtual_screen.cursor_y * virtual_screen.char_height
+ + grub_font_get_ascent (virtual_screen.font));
width = virtual_screen.char_width;
height = 2;
@@ -819,14 +835,18 @@
}
else
{
- struct grub_font_glyph glyph;
+ struct grub_font_glyph *glyph;
struct grub_colored_char *p;
+ unsigned char_width;
/* Get properties of the character. */
- grub_font_get_glyph (c, &glyph);
+ glyph = grub_font_get_glyph (virtual_screen.font, c);
+
+ /* TODO Fix wide characters. Bi-width font support? */
+ char_width = 1;
/* If we are about to exceed line length, wrap to next line. */
- if (virtual_screen.cursor_x + glyph.char_width > virtual_screen.columns)
+ if (virtual_screen.cursor_x + char_width > virtual_screen.columns)
grub_putchar ('\n');
/* Find position on virtual screen, and fill information. */
@@ -836,18 +856,18 @@
p->code = c;
p->fg_color = virtual_screen.fg_color;
p->bg_color = virtual_screen.bg_color;
- p->width = glyph.char_width - 1;
+ p->width = char_width - 1;
p->index = 0;
/* If we have large glyph, add fixup info. */
- if (glyph.char_width > 1)
+ if (char_width > 1)
{
unsigned i;
- for (i = 1; i < glyph.char_width; i++)
+ for (i = 1; i < char_width; i++)
{
p[i].code = ' ';
- p[i].width = glyph.char_width - 1;
+ p[i].width = char_width - 1;
p[i].index = i;
}
}
@@ -856,7 +876,7 @@
write_char ();
/* Make sure we scroll screen when needed and wrap line correctly. */
- virtual_screen.cursor_x += glyph.char_width;
+ virtual_screen.cursor_x += char_width;
if (virtual_screen.cursor_x >= virtual_screen.columns)
{
virtual_screen.cursor_x = 0;
@@ -876,11 +896,16 @@
static grub_ssize_t
grub_gfxterm_getcharwidth (grub_uint32_t c)
{
- struct grub_font_glyph glyph;
-
- grub_font_get_glyph (c, &glyph);
-
- return glyph.char_width;
+#if 0
+ struct grub_font_glyph *glyph;
+
+ glyph = grub_font_get_glyph (c);
+
+ return glyph->char_width;
+#else
+ (void) c; /* Prevent warning. */
+ return 1; /* TODO Fix wide characters. */
+#endif
}
static grub_uint16_t
=== modified file 'term/i386/pc/vesafb.c'
--- term/i386/pc/vesafb.c 2007-12-30 08:52:06 +0000
+++ term/i386/pc/vesafb.c 2008-10-05 04:30:04 +0000
@@ -250,10 +250,11 @@
break;
default:
- return grub_font_get_glyph (code, bitmap, width);
+ return grub_font_get_glyph_any (code, bitmap, width);
}
}
+ /* TODO This is wrong for the new font module. Should it be fixed? */
if (bitmap)
grub_memcpy (bitmap,
vga_font + code * virtual_screen.char_height,
=== modified file 'term/i386/pc/vga.c'
--- term/i386/pc/vga.c 2008-01-21 15:48:27 +0000
+++ term/i386/pc/vga.c 2008-10-05 04:30:04 +0000
@@ -65,6 +65,7 @@
static struct colored_char text_buf[TEXT_WIDTH * TEXT_HEIGHT];
static unsigned char saved_map_mask;
static int page = 0;
+static grub_font_t font = 0;
#define SEQUENCER_ADDR_PORT 0x3C4
#define SEQUENCER_DATA_PORT 0x3C5
@@ -161,6 +162,9 @@
saved_map_mask = get_map_mask ();
set_map_mask (0x0f);
set_start_address (PAGE_OFFSET (page));
+ font = grub_font_get (""); /* Choose any font, for now. */
+ if (!font)
+ return grub_error (GRUB_ERR_BAD_FONT, "No font loaded.");
return GRUB_ERR_NONE;
}
@@ -185,7 +189,7 @@
write_char (void)
{
struct colored_char *p = text_buf + xpos + ypos * TEXT_WIDTH;
- struct grub_font_glyph glyph;
+ struct grub_font_glyph *glyph;
unsigned char *mem_base;
unsigned plane;
@@ -194,7 +198,7 @@
p -= p->index;
/* Get glyph for character. */
- grub_font_get_glyph (p->code, &glyph);
+ glyph = grub_font_get_glyph (font, p->code);
for (plane = 0x01; plane <= 0x08; plane <<= 1)
{
@@ -208,19 +212,23 @@
y < CHAR_HEIGHT;
y++, mem += TEXT_WIDTH)
{
+ /* TODO Re-implement glyph drawing for vga module. */
+#if 0
unsigned i;
- for (i = 0; i < glyph.char_width && offset < 32; i++)
+ unsigned char_width = 1; /* TODO Figure out wide characters. */
+ for (i = 0; i < char_width && offset < 32; i++)
{
unsigned char fg_mask, bg_mask;
- fg_mask = (p->fg_color & plane) ? glyph.bitmap[offset] : 0;
- bg_mask = (p->bg_color & plane) ? ~(glyph.bitmap[offset]) : 0;
+ fg_mask = (p->fg_color & plane) ? glyph->bitmap[offset] : 0;
+ bg_mask = (p->bg_color & plane) ? ~(glyph->bitmap[offset]) : 0;
offset++;
if (check_vga_mem (mem + i))
mem[i] = (fg_mask | bg_mask);
}
+#endif /* 0 */
}
}
@@ -320,36 +328,37 @@
}
else
{
- struct grub_font_glyph glyph;
+ struct grub_font_glyph *glyph;
struct colored_char *p;
+ unsigned char_width = 1;
- grub_font_get_glyph(c, &glyph);
+ glyph = grub_font_get_glyph(font, c);
- if (xpos + glyph.char_width > TEXT_WIDTH)
+ if (xpos + char_width > TEXT_WIDTH)
grub_putchar ('\n');
p = text_buf + xpos + ypos * TEXT_WIDTH;
p->code = c;
p->fg_color = fg_color;
p->bg_color = bg_color;
- p->width = glyph.char_width - 1;
+ p->width = char_width - 1;
p->index = 0;
- if (glyph.char_width > 1)
+ if (char_width > 1)
{
unsigned i;
- for (i = 1; i < glyph.char_width; i++)
+ for (i = 1; i < char_width; i++)
{
p[i].code = ' ';
- p[i].width = glyph.char_width - 1;
+ p[i].width = char_width - 1;
p[i].index = i;
}
}
write_char ();
- xpos += glyph.char_width;
+ xpos += char_width;
if (xpos >= TEXT_WIDTH)
{
xpos = 0;
@@ -381,11 +390,16 @@
static grub_ssize_t
grub_vga_getcharwidth (grub_uint32_t c)
{
+#if 0
struct grub_font_glyph glyph;
- grub_font_get_glyph (c, &glyph);
+ glyph = grub_font_get_glyph (c);
return glyph.char_width;
+#else
+ (void) c; /* Prevent warning. */
+ return 1; /* TODO Fix wide characters? */
+#endif
}
static grub_uint16_t
=== modified file 'video/i386/pc/vbe.c'
--- video/i386/pc/vbe.c 2008-10-03 15:25:34 +0000
+++ video/i386/pc/vbe.c 2008-10-05 04:30:04 +0000
@@ -896,6 +896,16 @@
return minindex;
}
+ else if ((render_target->mode_info.mode_type
+ & GRUB_VIDEO_MODE_TYPE_1BIT_BITMAP) != 0)
+ {
+ if (red == render_target->mode_info.fg_red
+ && green == render_target->mode_info.fg_green
+ && blue == render_target->mode_info.fg_blue)
+ return 1;
+ else
+ return 0;
+ }
else
{
grub_uint32_t value;
@@ -926,6 +936,17 @@
/* No alpha available in index color modes, just use
same value as in only RGB modes. */
return grub_video_vbe_map_rgb (red, green, blue);
+ else if ((render_target->mode_info.mode_type
+ & GRUB_VIDEO_MODE_TYPE_1BIT_BITMAP) != 0)
+ {
+ if (red == render_target->mode_info.fg_red
+ && green == render_target->mode_info.fg_green
+ && blue == render_target->mode_info.fg_blue
+ && alpha == render_target->mode_info.fg_alpha)
+ return 1;
+ else
+ return 0;
+ }
else
{
grub_uint32_t value;
@@ -988,6 +1009,24 @@
*alpha = framebuffer.palette[color].a;
return;
}
+ else if ((mode_info->mode_type
+ & GRUB_VIDEO_MODE_TYPE_1BIT_BITMAP) != 0)
+ {
+ if (color & 1)
+ {
+ *red = mode_info->fg_red;
+ *green = mode_info->fg_green;
+ *blue = mode_info->fg_blue;
+ *alpha = mode_info->fg_alpha;
+ }
+ else
+ {
+ *red = mode_info->bg_red;
+ *green = mode_info->bg_green;
+ *blue = mode_info->bg_blue;
+ *alpha = mode_info->bg_alpha;
+ }
+ }
else
{
grub_uint32_t tmp;
@@ -1111,76 +1150,6 @@
return GRUB_ERR_NONE;
}
-// TODO: Remove this method and replace with bitmap based glyphs
-static grub_err_t
-grub_video_vbe_blit_glyph (struct grub_font_glyph * glyph,
- grub_video_color_t color, int x, int y)
-{
- struct grub_video_i386_vbeblit_info target;
- unsigned int width;
- unsigned int charwidth;
- unsigned int height;
- unsigned int i;
- unsigned int j;
- unsigned int x_offset = 0;
- unsigned int y_offset = 0;
-
- /* Make sure there is something to do. */
- if (x >= (int)render_target->viewport.width)
- return GRUB_ERR_NONE;
-
- if (y >= (int)render_target->viewport.height)
- return GRUB_ERR_NONE;
-
- /* Calculate glyph dimensions. */
- width = ((glyph->width + 7) / 8) * 8;
- charwidth = width;
- height = glyph->height;
-
- if (x + (int)width < 0)
- return GRUB_ERR_NONE;
-
- if (y + (int)height < 0)
- return GRUB_ERR_NONE;
-
- /* Do not allow drawing out of viewport. */
- if (x < 0)
- {
- width += x;
- x_offset = (unsigned int)-x;
- x = 0;
- }
- if (y < 0)
- {
- height += y;
- y_offset = (unsigned int)-y;
- y = 0;
- }
-
- if ((x + width) > render_target->viewport.width)
- width = render_target->viewport.width - x;
- if ((y + height) > render_target->viewport.height)
- height = render_target->viewport.height - y;
-
- /* Add viewport offset. */
- x += render_target->viewport.x;
- y += render_target->viewport.y;
-
- /* Use vbeblit_info to encapsulate rendering. */
- target.mode_info = &render_target->mode_info;
- target.data = render_target->data;
-
- /* Draw glyph. */
- for (j = 0; j < height; j++)
- for (i = 0; i < width; i++)
- if ((glyph->bitmap[((i + x_offset) / 8)
- + (j + y_offset) * (charwidth / 8)]
- & (1 << ((charwidth - (i + x_offset) - 1) % 8))))
- set_pixel (&target, x+i, y+j, color);
-
- return GRUB_ERR_NONE;
-}
-
/* NOTE: This function assumes that given coordinates are within bounds of
handled data. */
static void
@@ -1474,6 +1443,77 @@
return GRUB_ERR_NONE;
}
+/*
+ * Draw the specified glyph at (x, y). The y coordinate designates the
+ * baseline of the character, while the x coordinate designates the left
+ * side location of the character.
+ */
+static grub_err_t
+grub_video_vbe_blit_glyph (struct grub_font_glyph *glyph,
+ grub_video_color_t color,
+ int left_x, int baseline_y)
+{
+ struct grub_video_bitmap glyph_bitmap;
+
+ /* Don't try to draw empty glyphs (U+0020, etc.). */
+ if (glyph->width == 0 || glyph->height == 0)
+ return GRUB_ERR_NONE;
+
+ glyph_bitmap.mode_info.width = glyph->width;
+ glyph_bitmap.mode_info.height = glyph->height;
+ 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;
+ glyph_bitmap.mode_info.bytes_per_pixel = 0; /* Really 1 bit per pixel. */
+ glyph_bitmap.mode_info.pitch = glyph->width; /* Packed densely as bits. */
+ 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_vbe_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);
+ glyph_bitmap.data = glyph->bitmap;
+
+ int bitmap_left = left_x + glyph->offset_x;
+ int bitmap_bottom = baseline_y - glyph->offset_y;
+ int bitmap_top = bitmap_bottom - glyph->height;
+
+ return grub_video_vbe_blit_bitmap (&glyph_bitmap, GRUB_VIDEO_BLIT_BLEND,
+ bitmap_left, bitmap_top,
+ 0, 0,
+ glyph->width, glyph->height);
+}
+
+static grub_err_t
+grub_video_vbe_draw_string (const char *str, grub_font_t font,
+ grub_video_color_t color,
+ int left_x, int baseline_y)
+{
+ grub_size_t len;
+ grub_size_t i;
+ int x;
+ struct grub_font_glyph *glyph;
+
+ len = grub_strlen (str);
+ x = left_x;
+ for (i = 0; i < len; i++)
+ {
+ glyph = grub_font_get_glyph (font, str[i]);
+ if (grub_video_vbe_blit_glyph (glyph, color, x, baseline_y)
+ != GRUB_ERR_NONE)
+ return grub_errno;
+ x += glyph->device_width;
+ }
+
+ return GRUB_ERR_NONE;
+}
+
static grub_err_t
grub_video_vbe_blit_render_target (struct grub_video_render_target *source,
enum grub_video_blit_operators oper,
@@ -1805,6 +1845,7 @@
.unmap_color = grub_video_vbe_unmap_color,
.fill_rect = grub_video_vbe_fill_rect,
.blit_glyph = grub_video_vbe_blit_glyph,
+ .draw_string = grub_video_vbe_draw_string,
.blit_bitmap = grub_video_vbe_blit_bitmap,
.blit_render_target = grub_video_vbe_blit_render_target,
.scroll = grub_video_vbe_scroll,
=== modified file 'video/i386/pc/vbeutil.c'
--- video/i386/pc/vbeutil.c 2007-07-21 22:32:33 +0000
+++ video/i386/pc/vbeutil.c 2008-10-05 04:30:04 +0000
@@ -52,6 +52,11 @@
+ y * source->mode_info->pitch
+ x;
break;
+
+ /* case 1: */
+ /* For 1-bit bitmaps, addressing needs to be done at the bit level
+ * and it doesn't make sense, in general, to ask for a pointer
+ * to a particular pixel's data. */
}
return ptr;
@@ -86,6 +91,17 @@
color = *(grub_uint8_t *)get_data_ptr (source, x, y);
break;
+ case 1:
+ if (source->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_1BIT_PACKED)
+ {
+ int bit_index = y * source->mode_info->width + x;
+ grub_uint8_t *ptr = (grub_uint8_t *)source->data
+ + bit_index / 8;
+ int bit_pos = 7 - bit_index % 8;
+ color = (*ptr >> bit_pos) & 0x01;
+ }
+ break;
+
default:
break;
}
@@ -143,6 +159,17 @@
}
break;
+ case 1:
+ if (source->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_1BIT_PACKED)
+ {
+ int bit_index = y * source->mode_info->width + x;
+ grub_uint8_t *ptr = (grub_uint8_t *)source->data
+ + bit_index / 8;
+ int bit_pos = 7 - bit_index % 8;
+ *ptr = (*ptr & ~(1 << bit_pos)) | ((color & 0x01) << bit_pos);
+ }
+ break;
+
default:
break;
}
=== modified file 'video/video.c'
--- video/video.c 2008-10-03 15:25:34 +0000
+++ video/video.c 2008-10-05 04:30:04 +0000
@@ -339,12 +339,27 @@
/* Blit glyph to screen using specified color. */
grub_err_t
grub_video_blit_glyph (struct grub_font_glyph *glyph,
- grub_video_color_t color, int x, int y)
-{
- if (! grub_video_adapter_active)
- return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
-
- return grub_video_adapter_active->blit_glyph (glyph, color, x, y);
+ grub_video_color_t color,
+ int left_x, int baseline_y)
+{
+ if (! grub_video_adapter_active)
+ return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+
+ return grub_video_adapter_active->blit_glyph (glyph, color,
+ left_x, baseline_y);
+}
+
+/* Draw string to screen using specified color and font. */
+grub_err_t
+grub_video_draw_string (const char *str, grub_font_t font,
+ grub_video_color_t color,
+ int left_x, int baseline_y)
+{
+ if (! grub_video_adapter_active)
+ return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+
+ return grub_video_adapter_active->draw_string (str, font, color,
+ left_x, baseline_y);
}
/* Blit bitmap to screen. */