2009-06-05 Colin D Bennett <colin@gibibit.com>

Optimized font character lookup using binary search instead of linear
	search.  Fonts now are required to have the character index ordered by
	code point.

	* font/font.c (load_font_index): Verify that fonts have ordered
	character indices.
	(find_glyph): Use binary search instead of linear search to find a
	character in a font.
This commit is contained in:
phcoder 2009-06-05 21:22:14 +00:00
parent 408305be7a
commit c8048e32d6
2 changed files with 42 additions and 7 deletions

View file

@ -1,3 +1,14 @@
2009-06-05 Colin D Bennett <colin@gibibit.com>
Optimized font character lookup using binary search instead of linear
search. Fonts now are required to have the character index ordered by
code point.
* font/font.c (load_font_index): Verify that fonts have ordered
character indices.
(find_glyph): Use binary search instead of linear search to find a
character in a font.
2009-06-05 Michael Scherer <misc@mandriva.org> 2009-06-05 Michael Scherer <misc@mandriva.org>
* fs/hfsplus.c (grub_hfsplus_mount): Determine if the filesystem * fs/hfsplus.c (grub_hfsplus_mount): Determine if the filesystem

View file

@ -249,6 +249,7 @@ load_font_index (grub_file_t file, grub_uint32_t sect_length, struct
grub_font *font) grub_font *font)
{ {
unsigned i; unsigned i;
grub_uint32_t last_code;
#if FONT_DEBUG >= 2 #if FONT_DEBUG >= 2
grub_printf("load_font_index(sect_length=%d)\n", sect_length); grub_printf("load_font_index(sect_length=%d)\n", sect_length);
@ -277,6 +278,8 @@ load_font_index (grub_file_t file, grub_uint32_t sect_length, struct
grub_printf("num_chars=%d)\n", font->num_chars); grub_printf("num_chars=%d)\n", font->num_chars);
#endif #endif
last_code = 0;
/* Load the character index data from the file. */ /* Load the character index data from the file. */
for (i = 0; i < font->num_chars; i++) for (i = 0; i < font->num_chars; i++)
{ {
@ -287,6 +290,17 @@ load_font_index (grub_file_t file, grub_uint32_t sect_length, struct
return 1; return 1;
entry->code = grub_be_to_cpu32 (entry->code); entry->code = grub_be_to_cpu32 (entry->code);
/* Verify that characters are in ascending order. */
if (i != 0 && entry->code <= last_code)
{
grub_error (GRUB_ERR_BAD_FONT,
"Font characters not in ascending order: %u <= %u",
entry->code, last_code);
return 1;
}
last_code = entry->code;
/* Read storage flags byte. */ /* Read storage flags byte. */
if (grub_file_read (file, (char *) &entry->storage_flags, 1) != 1) if (grub_file_read (file, (char *) &entry->storage_flags, 1) != 1)
return 1; return 1;
@ -583,15 +597,25 @@ read_be_int16 (grub_file_t file, grub_int16_t * value)
static struct char_index_entry * static struct char_index_entry *
find_glyph (const grub_font_t font, grub_uint32_t code) find_glyph (const grub_font_t font, grub_uint32_t code)
{ {
grub_uint32_t i; struct char_index_entry *table;
grub_uint32_t len = font->num_chars; grub_size_t lo;
struct char_index_entry *table = font->char_index; grub_size_t hi;
grub_size_t mid;
/* Do a linear search. */ /* Do a binary search in `char_index', which is ordered by code point. */
for (i = 0; i < len; i++) table = font->char_index;
lo = 0;
hi = font->num_chars - 1;
while (lo <= hi)
{ {
if (table[i].code == code) mid = lo + (hi - lo) / 2;
return &table[i]; if (code < table[mid].code)
hi = mid - 1;
else if (code > table[mid].code)
lo = mid + 1;
else
return &table[mid];
} }
return 0; return 0;