merge mainline into emu-mod

This commit is contained in:
Vladimir 'phcoder' Serbinenko 2010-02-07 03:06:33 +01:00
commit 19a9fb834b
459 changed files with 26481 additions and 7640 deletions

View file

@ -1,7 +1,7 @@
/* font.c - Font API and font file loader. */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2003,2005,2006,2007,2008,2009 Free Software Foundation, Inc.
* Copyright (C) 2003,2005,2006,2007,2008,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
@ -26,6 +26,11 @@
#include <grub/types.h>
#include <grub/video.h>
#include <grub/bitmap.h>
#include <grub/fontformat.h>
#ifdef USE_ASCII_FAILBACK
#include "ascii.h"
#endif
#ifndef FONT_DEBUG
#define FONT_DEBUG 0
@ -43,6 +48,7 @@ struct char_index_entry
#define FONT_WEIGHT_NORMAL 100
#define FONT_WEIGHT_BOLD 200
#define ASCII_BITMAP_SIZE 16
struct grub_font
{
@ -58,6 +64,7 @@ struct grub_font
short leading;
grub_uint32_t num_chars;
struct char_index_entry *char_index;
grub_uint16_t *bmp_idx;
};
/* Definition of font registry. */
@ -83,19 +90,6 @@ struct font_file_section
int 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_point_size[4] = { 'P', 'T', 'S', 'Z' };
static const char section_names_weight[4] = { 'W', 'E', 'I', 'G' };
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[] =
{
@ -129,6 +123,48 @@ static struct grub_font null_font;
/* Flag to ensure module is initialized only once. */
static grub_uint8_t font_loader_initialized;
#ifdef USE_ASCII_FAILBACK
static struct grub_font_glyph *ascii_font_glyph[0x80];
#endif
static struct grub_font_glyph *
ascii_glyph_lookup (grub_uint32_t code)
{
#ifdef USE_ASCII_FAILBACK
static int ascii_failback_initialized = 0;
if (code >= 0x80)
return unknown_glyph;
if (ascii_failback_initialized == 0)
{
int current;
for (current = 0; current < 0x80; current++)
{
ascii_font_glyph[current] = grub_malloc(sizeof(struct grub_font_glyph)
+ ASCII_BITMAP_SIZE);
ascii_font_glyph[current]->width = 8;
ascii_font_glyph[current]->height = 16;
ascii_font_glyph[current]->offset_x = 0;
ascii_font_glyph[current]->offset_y = -2;
ascii_font_glyph[current]->device_width = 8;
grub_memcpy (ascii_font_glyph[current]->bitmap,
&ascii_bitmaps[(0x7f - current) * ASCII_BITMAP_SIZE],
ASCII_BITMAP_SIZE);
}
ascii_failback_initialized = 1;
}
return ascii_font_glyph[code];
#else
(void) code;
return unknown_glyph;
#endif
}
void
grub_font_loader_init (void)
{
@ -180,6 +216,7 @@ font_init (grub_font_t font)
font->descent = 0;
font->num_chars = 0;
font->char_index = 0;
font->bmp_idx = 0;
}
/* Open the next section in the file.
@ -210,7 +247,7 @@ open_section (grub_file_t file, struct font_file_section *section)
else if (retval < 0)
{
grub_error (GRUB_ERR_BAD_FONT,
"Font format error: can't read section name");
"font format error: can't read section name");
return 1;
}
@ -225,7 +262,7 @@ open_section (grub_file_t file, struct font_file_section *section)
else if (retval < 0)
{
grub_error (GRUB_ERR_BAD_FONT,
"Font format error: can't read section length");
"font format error: can't read section length");
return 1;
}
@ -259,7 +296,7 @@ load_font_index (grub_file_t file, grub_uint32_t sect_length, struct
if ((sect_length % FONT_CHAR_INDEX_ENTRY_SIZE) != 0)
{
grub_error (GRUB_ERR_BAD_FONT,
"Font file format error: character index length %d "
"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;
@ -273,6 +310,14 @@ load_font_index (grub_file_t file, grub_uint32_t sect_length, struct
* sizeof (struct char_index_entry));
if (! font->char_index)
return 1;
font->bmp_idx = grub_malloc (0x10000 * sizeof (grub_uint16_t));
if (! font->bmp_idx)
{
grub_free (font->char_index);
return 1;
}
grub_memset (font->bmp_idx, 0xff, 0x10000 * sizeof (grub_uint16_t));
#if FONT_DEBUG >= 2
grub_printf("num_chars=%d)\n", font->num_chars);
@ -294,11 +339,14 @@ load_font_index (grub_file_t file, grub_uint32_t sect_length, struct
if (i != 0 && entry->code <= last_code)
{
grub_error (GRUB_ERR_BAD_FONT,
"Font characters not in ascending order: %u <= %u",
"font characters not in ascending order: %u <= %u",
entry->code, last_code);
return 1;
}
if (entry->code < 0x10000)
font->bmp_idx[entry->code] = i;
last_code = entry->code;
/* Read storage flags byte. */
@ -357,7 +405,7 @@ read_section_as_short (struct font_file_section *section, grub_int16_t *value)
if (section->length != 2)
{
grub_error (GRUB_ERR_BAD_FONT,
"Font file format error: section %c%c%c%c length "
"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],
@ -400,10 +448,11 @@ grub_font_load (const char *filename)
#if FONT_DEBUG >= 3
grub_printf("opened FILE section\n");
#endif
if (grub_memcmp (section.name, section_names_file, 4) != 0)
if (grub_memcmp (section.name, FONT_FORMAT_SECTION_NAMES_FILE,
sizeof(FONT_FORMAT_SECTION_NAMES_FILE) - 1) != 0)
{
grub_error (GRUB_ERR_BAD_FONT,
"Font file format error: 1st section must be FILE");
"font file format error: 1st section must be FILE");
goto fail;
}
@ -413,7 +462,7 @@ grub_font_load (const char *filename)
if (section.length != 4)
{
grub_error (GRUB_ERR_BAD_FONT,
"Font file format error (file type ID length is %d "
"font file format error (file type ID length is %d "
"but should be 4)", section.length);
goto fail;
}
@ -429,9 +478,9 @@ grub_font_load (const char *filename)
grub_printf("read magic ok\n");
#endif
if (grub_memcmp (magic, pff2_magic, 4) != 0)
if (grub_memcmp (magic, FONT_FORMAT_PFF2_MAGIC, 4) != 0)
{
grub_error (GRUB_ERR_BAD_FONT, "Invalid font magic %x %x %x %x",
grub_error (GRUB_ERR_BAD_FONT, "invalid font magic %x %x %x %x",
magic[0], magic[1], magic[2], magic[3]);
goto fail;
}
@ -469,18 +518,22 @@ grub_font_load (const char *filename)
section.name[2], section.name[3]);
#endif
if (grub_memcmp (section.name, section_names_font_name, 4) == 0)
if (grub_memcmp (section.name, FONT_FORMAT_SECTION_NAMES_FONT_NAME,
sizeof(FONT_FORMAT_SECTION_NAMES_FONT_NAME) - 1) == 0)
{
font->name = read_section_as_string (&section);
if (!font->name)
goto fail;
}
else if (grub_memcmp (section.name, section_names_point_size, 4) == 0)
else if (grub_memcmp (section.name,
FONT_FORMAT_SECTION_NAMES_POINT_SIZE,
sizeof(FONT_FORMAT_SECTION_NAMES_POINT_SIZE) - 1) == 0)
{
if (read_section_as_short (&section, &font->point_size) != 0)
goto fail;
}
else if (grub_memcmp (section.name, section_names_weight, 4) == 0)
else if (grub_memcmp (section.name, FONT_FORMAT_SECTION_NAMES_WEIGHT,
sizeof(FONT_FORMAT_SECTION_NAMES_WEIGHT) - 1) == 0)
{
char *wt;
wt = read_section_as_string (&section);
@ -493,32 +546,42 @@ grub_font_load (const char *filename)
font->weight = FONT_WEIGHT_BOLD;
grub_free (wt);
}
else if (grub_memcmp (section.name, section_names_max_char_width, 4) == 0)
else if (grub_memcmp (section.name,
FONT_FORMAT_SECTION_NAMES_MAX_CHAR_WIDTH,
sizeof(FONT_FORMAT_SECTION_NAMES_MAX_CHAR_WIDTH) - 1) == 0)
{
if (read_section_as_short (&section, &font->max_char_width) != 0)
goto fail;
}
else if (grub_memcmp (section.name, section_names_max_char_height, 4) == 0)
else if (grub_memcmp (section.name,
FONT_FORMAT_SECTION_NAMES_MAX_CHAR_HEIGHT,
sizeof(FONT_FORMAT_SECTION_NAMES_MAX_CHAR_HEIGHT) - 1) == 0)
{
if (read_section_as_short (&section, &font->max_char_height) != 0)
goto fail;
}
else if (grub_memcmp (section.name, section_names_ascent, 4) == 0)
else if (grub_memcmp (section.name,
FONT_FORMAT_SECTION_NAMES_ASCENT,
sizeof(FONT_FORMAT_SECTION_NAMES_ASCENT) - 1) == 0)
{
if (read_section_as_short (&section, &font->ascent) != 0)
goto fail;
}
else if (grub_memcmp (section.name, section_names_descent, 4) == 0)
else if (grub_memcmp (section.name, FONT_FORMAT_SECTION_NAMES_DESCENT,
sizeof(FONT_FORMAT_SECTION_NAMES_DESCENT) - 1) == 0)
{
if (read_section_as_short (&section, &font->descent) != 0)
goto fail;
}
else if (grub_memcmp (section.name, section_names_char_index, 4) == 0)
else if (grub_memcmp (section.name,
FONT_FORMAT_SECTION_NAMES_CHAR_INDEX,
sizeof(FONT_FORMAT_SECTION_NAMES_CHAR_INDEX) - 1) == 0)
{
if (load_font_index (file, section.length, font) != 0)
goto fail;
}
else if (grub_memcmp (section.name, section_names_data, 4) == 0)
else if (grub_memcmp (section.name, FONT_FORMAT_SECTION_NAMES_DATA,
sizeof(FONT_FORMAT_SECTION_NAMES_DATA) - 1) == 0)
{
/* When the DATA section marker is reached, we stop reading. */
break;
@ -558,7 +621,7 @@ grub_font_load (const char *filename)
|| font->descent == 0)
{
grub_error (GRUB_ERR_BAD_FONT,
"Invalid font file: missing some required data.");
"invalid font file: missing some required data");
goto fail;
}
@ -594,7 +657,7 @@ read_be_int16 (grub_file_t file, grub_int16_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 *
static inline struct char_index_entry *
find_glyph (const grub_font_t font, grub_uint32_t code)
{
struct char_index_entry *table;
@ -602,8 +665,17 @@ find_glyph (const grub_font_t font, grub_uint32_t code)
grub_size_t hi;
grub_size_t mid;
/* Do a binary search in `char_index', which is ordered by code point. */
table = font->char_index;
/* Use BMP index if possible. */
if (code < 0x10000 && font->bmp_idx)
{
if (font->bmp_idx[code] == 0xffff)
return 0;
return &table[font->bmp_idx[code]];
}
/* Do a binary search in `char_index', which is ordered by code point. */
lo = 0;
hi = font->num_chars - 1;
@ -865,15 +937,18 @@ grub_font_get_string_width (grub_font_t font, const char *str)
}
/* 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. */
Returns the ASCII glyph for the code if no other fonts are available.
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);
struct grub_font_glyph *glyph = 0;
if (font)
glyph = grub_font_get_glyph_internal (font, code);
if (glyph == 0)
glyph = unknown_glyph;
{
glyph = ascii_glyph_lookup (code);
}
return glyph;
}
@ -968,8 +1043,8 @@ grub_font_get_glyph_with_fallback (grub_font_t font, grub_uint32_t code)
if (best_glyph)
return best_glyph;
else
/* Glyph not available in any font. Return unknown glyph. */
return unknown_glyph;
/* Glyph not available in any font. Return ASCII failback. */
return ascii_glyph_lookup (code);
}

View file

@ -62,7 +62,7 @@ GRUB_MOD_INIT(font)
cmd_loadfont =
grub_register_command ("loadfont", loadfont_command,
"loadfont FILE...",
"FILE...",
"Specify one or more font files to load.");
cmd_lsfonts =
grub_register_command ("lsfonts", lsfonts_command,