/* font.c - Font API and font file loader. */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2003,2005,2006,2007,2008,2009,2010 Free Software Foundation, Inc.
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include <grub/fontformat.h>
GRUB_MOD_LICENSE ("GPLv3+");
#ifdef USE_ASCII_FAILBACK
#include "ascii.h"
#endif
#ifndef FONT_DEBUG
#define FONT_DEBUG 0
#endif
struct char_index_entry
{
/* Glyph if loaded, or NULL otherwise. */
};
struct grub_font
{
char *name;
char *family;
short point_size;
short weight;
short max_char_width;
short max_char_height;
short ascent;
short descent;
short leading;
};
/* Definition of font registry. */
struct font_file_section
{
/* The file this section is in. */
/* FOURCC name of the section. */
/* Length of the section contents. */
/* Set by open_section() on EOF. */
int eof;
};
/* Replace unknown glyphs with a rounded question mark. */
/* 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 /* */
};
/* The "unknown glyph" glyph, used as a last resort. */
/* The font structure used when no other font is loaded. This functions
as a "Null Object" pattern, so that code everywhere does not have to
check for a NULL grub_font_t to avoid dereferencing a null pointer. */
/* Flag to ensure module is initialized only once. */
#ifdef USE_ASCII_FAILBACK
#endif
static struct grub_font_glyph *
{
#ifdef USE_ASCII_FAILBACK
static int ascii_failback_initialized = 0;
if (code >= 0x80)
return NULL;
if (ascii_failback_initialized == 0)
{
int current;
{
}
}
return ascii_font_glyph[code];
#else
(void) code;
return NULL;
#endif
}
void
grub_font_loader_init (void)
{
/* Only initialize font loader once. */
return;
/* Make glyph for unknown glyph. */
+ sizeof (unknown_glyph_bitmap));
if (!unknown_glyph)
return;
unknown_glyph->offset_x = 0;
unknown_glyph_bitmap, sizeof (unknown_glyph_bitmap));
/* Initialize the null font. */
}
/* Initialize the font object with initial default values. */
static void
{
font->point_size = 0;
/* Default leading value, not in font file yet. */
font->max_char_width = 0;
font->max_char_height = 0;
font->char_index = 0;
}
/* 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 appropriately 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
{
/* Read the FOURCC section name. */
{
/* EOF encountered. */
return 1;
}
else if (retval < 0)
{
/* Read error. */
return 1;
}
/* Read the big-endian 32-bit section length. */
{
/* EOF encountered. */
return 1;
}
else if (retval < 0)
{
/* Read error. */
return 1;
}
/* Convert byte-order and store in *length. */
return 0;
}
/* Size in bytes of each character index (CHIX section)
entry in the font file. */
/* 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
{
unsigned i;
#if FONT_DEBUG >= 2
#endif
/* Sanity check: ensure section length is divisible by the entry size. */
if ((sect_length % FONT_CHAR_INDEX_ENTRY_SIZE) != 0)
{
"font file format error: character index length %d "
"is not a multiple of the entry size %d",
return 1;
}
/* Calculate the number of characters. */
/* Allocate the character index array. */
* sizeof (struct char_index_entry));
if (!font->char_index)
return 1;
return 1;
#if FONT_DEBUG >= 2
#endif
last_code = 0;
/* Load the character index data from the file. */
{
/* Read code point value; convert to native byte order. */
return 1;
/* Verify that characters are in ascending order. */
{
"font characters not in ascending order: %u <= %u",
return 1;
}
/* Read storage flags byte. */
return 1;
/* Read glyph data offset; convert to native byte order. */
return 1;
/* No glyph loaded. Will be loaded on demand and cached thereafter. */
#if FONT_DEBUG >= 5
/* Print the 1st 10 characters. */
if (i < 10)
#endif
}
return 0;
}
/* 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 *
{
char *str;
if (!str)
return 0;
{
return 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
{
{
"font file format error: section %c%c%c%c length "
"is %d but should be 2",
return 1;
}
return 1;
return 0;
}
/* Load a font and add it to the beginning of the global font list.
Returns 0 upon success, nonzero upon failure. */
int
{
#if FONT_DEBUG >= 1
#endif
if (!file)
goto fail;
#if FONT_DEBUG >= 3
grub_printf ("file opened\n");
#endif
/* Read the FILE section. It indicates the file format. */
goto fail;
#if FONT_DEBUG >= 3
grub_printf ("opened FILE section\n");
#endif
sizeof (FONT_FORMAT_SECTION_NAMES_FILE) - 1) != 0)
{
"font file format error: 1st section must be FILE");
goto fail;
}
#if FONT_DEBUG >= 3
grub_printf ("section name ok\n");
#endif
{
"font file format error (file type ID length is %d "
goto fail;
}
#if FONT_DEBUG >= 3
grub_printf ("section length ok\n");
#endif
/* Check the file format type code. */
goto fail;
#if FONT_DEBUG >= 3
grub_printf ("read magic ok\n");
#endif
{
goto fail;
}
#if FONT_DEBUG >= 3
grub_printf ("compare magic ok\n");
#endif
/* Allocate the font object. */
if (!font)
goto fail;
#if FONT_DEBUG >= 3
grub_printf ("allocate font ok; loading font info\n");
#endif
/* Load the font information. */
while (1)
{
{
break; /* Done reading the font file. */
else
goto fail;
}
#if FONT_DEBUG >= 2
grub_printf ("opened section %c%c%c%c ok\n",
#endif
sizeof (FONT_FORMAT_SECTION_NAMES_FONT_NAME) - 1) == 0)
{
goto fail;
}
sizeof (FONT_FORMAT_SECTION_NAMES_POINT_SIZE) -
1) == 0)
{
goto fail;
}
sizeof (FONT_FORMAT_SECTION_NAMES_WEIGHT) - 1)
== 0)
{
char *wt;
if (!wt)
continue;
/* Convert the weight string 'normal' or 'bold' into a number. */
}
- 1) == 0)
{
goto fail;
}
- 1) == 0)
{
goto fail;
}
sizeof (FONT_FORMAT_SECTION_NAMES_ASCENT) - 1)
== 0)
{
goto fail;
}
sizeof (FONT_FORMAT_SECTION_NAMES_DESCENT) - 1)
== 0)
{
goto fail;
}
sizeof (FONT_FORMAT_SECTION_NAMES_CHAR_INDEX) -
1) == 0)
{
goto fail;
}
sizeof (FONT_FORMAT_SECTION_NAMES_DATA) - 1) == 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
goto fail;
}
}
{
}
#if FONT_DEBUG >= 1
grub_printf ("Loaded font `%s'.\n"
"Ascent=%d Descent=%d MaxW=%d MaxH=%d Number of characters=%d.\n",
#endif
if (font->max_char_width == 0
|| font->max_char_height == 0
{
"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;
fail:
if (file)
if (font)
return 1;
}
/* 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
{
return 1;
return 0;
}
static int
{
/* For the signed integer version, use the same code as for unsigned. */
}
/* 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 inline struct char_index_entry *
{
/* Use BMP index if possible. */
{
return 0;
}
/* Do a binary search in `char_index', which is ordered by code point. */
lo = 0;
if (!table)
return 0;
{
else
}
return 0;
}
/* Get a glyph for the Unicode character CODE in FONT. The glyph is loaded
from the font file if has not been loaded yet.
Returns a pointer to the glyph if found, or 0 if it is not found. */
static struct grub_font_glyph *
{
if (index_entry)
{
int len;
if (index_entry->glyph)
/* Return cached glyph. */
return index_entry->glyph;
/* No open file, can't load any glyphs. */
return 0;
/* Make sure we can find glyphs for error messages. Push active
error message to error stack and reset error message. */
grub_error_push ();
/* Read the glyph width, height, and baseline. */
{
remove_font (font);
return 0;
}
if (!glyph)
{
remove_font (font);
return 0;
}
/* Don't try to read empty bitmaps (e.g., space characters). */
if (len != 0)
{
{
remove_font (font);
return 0;
}
}
/* Restore old error message. */
grub_error_pop ();
/* Cache the glyph. */
return glyph;
}
return 0;
}
/* Free the memory used by 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
{
if (font)
{
}
}
/* Add FONT to the global font registry.
Returns 0 upon success, nonzero on failure
(the font was not registered). */
static int
{
if (!node)
return 1;
return 0;
}
/* 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
{
{
{
/* Free the node, but not the font itself. */
return;
}
}
}
/* Get a font from the list of loaded fonts. This function will return
another font if the requested font is not available. If no fonts are
loaded, then a special 'null font' is returned, which contains no glyphs,
but is not a null pointer so the caller may omit checks for NULL. */
{
{
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;
else
/* The null_font is a last resort. */
return &null_font;
}
/* Get the full name of the font. */
const char *
{
}
/* Get the maximum width of any character in the font in pixels. */
int
{
return font->max_char_width;
}
/* Get the maximum height of any character in the font in pixels. */
int
{
return font->max_char_height;
}
/* Get the distance in pixels from the top of characters to the baseline. */
int
{
}
/* Get the distance in pixels from the baseline to the lowest descenders
(for instance, in a lowercase 'y', 'g', etc.). */
int
{
}
/* FIXME: not correct for all fonts. */
int
{
}
/* Get the *standard leading* of the font in pixel, which is the spacing
between two lines of text. Specifically, it is the space between the
descent of one line and the ascent of the next line. This is included
in the *height* metric. */
int
{
}
/* Get the distance in pixels between baselines of adjacent lines of text. */
int
{
}
/* Get the glyph for FONT corresponding to the Unicode code point CODE.
Returns the ASCII glyph for the code if no other fonts are available.
The glyphs are cached once loaded. */
struct grub_font_glyph *
{
if (font)
if (glyph == 0)
{
}
return glyph;
}
/* Calculate a subject value representing "how similar" two fonts are.
This is used to prioritize the order that fonts are scanned for missing
glyphs. The object is to select glyphs from the most similar font
possible, for the best appearance.
The heuristic is crude, but it helps greatly when fonts of similar
sizes are used so that tiny 8 point glyphs are not mixed into a string
of 24 point text unless there is no other choice. */
static int
{
int d;
d = 0;
else
/* Penalty for missing attributes. */
d += 50;
if (a->max_char_height && b->max_char_height)
else
/* Penalty for missing attributes. */
d += 50;
/* Weight is a minor factor. */
return d;
}
/* Get a glyph corresponding to the codepoint CODE. If FONT contains the
specified glyph, then it is returned. Otherwise, all other loaded fonts
are searched until one is found that contains a glyph for CODE.
If no glyph is available for CODE in the loaded 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 *
{
/* Keep track of next node, in case there's an I/O error in
grub_font_get_glyph_internal() and the font is removed from the list. */
/* Information on the best glyph found so far, to help find the glyph in
the best matching to the requested one. */
int best_diversity;
if (font)
{
/* First try to get the glyph from the specified font. */
if (glyph)
return glyph;
}
/* Otherwise, search all loaded fonts for the glyph and use the one from
the font that best matches the requested font. */
best_diversity = 10000;
best_glyph = 0;
{
return glyph;
if (glyph)
{
int d;
if (d < best_diversity)
{
best_diversity = d;
best_glyph = glyph;
}
}
}
return best_glyph;
}
static struct grub_font_glyph *
{
if (!ret)
return NULL;
return ret;
}
/* FIXME: suboptimal. */
static void
{
unsigned i, j;
{
{
& 0x80) >> tgt_bit;
src_bit++;
tgt_bit++;
if (src_bit == 8)
{
src_byte++;
src_bit = 0;
}
if (tgt_bit == 8)
{
tgt_byte++;
tgt_bit = 0;
}
}
}
}
static void
struct grub_font_glyph *src,
{
signed src_bit;
unsigned i, j;
{
{
& 0x80) >> tgt_bit;
src_bit--;
tgt_bit++;
if (src_bit == -1)
{
src_byte--;
src_bit = 7;
}
if (tgt_bit == 8)
{
tgt_byte++;
tgt_bit = 0;
}
}
}
}
static void
struct grub_font_glyph *glyph,
struct grub_video_signed_rect *bounds_out,
struct grub_font_glyph *main_glyph,
{
unsigned i;
signed min_devwidth = 0;
{
if (glyph)
{
}
{
}
}
auto void add_device_width (int val);
{
if (glyph)
if (device_width)
*device_width += val;
}
if (glyph)
if (device_width)
below_righty = bounds.y;
{
/* Center by default. */
if (!combining_glyphs[i])
continue;
/* CGJ is to avoid diacritics reordering. */
continue;
{
do_blit (combining_glyphs[i],
break;
break;
break;
break;
break;
targetx =
goto above_on_main;
goto above_on_main;
targetx =
combining_glyphs[i]->width;
if (space <= 0)
+ combining_glyphs[i]->height));
break;
/* TODO: Put dammah, fathah and alif nearer to shadda. */
case GRUB_UNICODE_STACK_ABOVE:
if (space <= 0)
+ combining_glyphs[i]->height));
break;
/* TODO: placement in final kaf and under reish. */
/* TODO: Put kasra and kasratan under shadda. */
/* I don't know how ypogegrammeni differs from subscript. */
case GRUB_UNICODE_STACK_BELOW:
+ combining_glyphs[i]->height);
if (space <= 0)
break;
case GRUB_UNICODE_COMB_MN:
{
goto stacked_above;
goto stacked_below;
}
/* Fall through. */
default:
{
/* Default handling. Just draw combining character on top
of base character.
FIXME: support more unicode types correctly.
*/
do_blit (combining_glyphs[i],
+ combining_glyphs[i]->offset_x,
-(combining_glyphs[i]->height
+ combining_glyphs[i]->offset_y));
}
}
}
if (bounds_out)
*bounds_out = bounds;
}
static struct grub_font_glyph *
const struct grub_unicode_glyph *glyph_id,
struct grub_video_signed_rect *bounds,
struct grub_font_glyph ***combining_glyphs_out,
int *device_width)
{
if (combining_glyphs_out)
if (!main_glyph)
/* Glyph not available in any font. Use ASCII fallback. */
if (!main_glyph)
/* Glyph not available in any font. Return unknown glyph. */
if (!main_glyph)
return NULL;
if (device_width)
return main_glyph;
{
return main_glyph;
}
{
unsigned i;
}
if (combining_glyphs_out)
else
return main_glyph;
}
int
const struct grub_unicode_glyph
*glyph_id)
{
int ret;
if (!main_glyph)
return unknown_glyph->device_width;
return ret;
}
struct grub_font_glyph *
const struct grub_unicode_glyph *glyph_id)
{
if (!main_glyph)
return grub_font_dup_glyph (unknown_glyph);
if (!combining_glyphs)
return grub_font_dup_glyph (main_glyph);
glyph =
if (!glyph)
{
return grub_font_dup_glyph (main_glyph);
}
- (main_glyph->height +
main_glyph->offset_y));
else
return glyph;
}
/* 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. */
{
/* Don't try to draw empty glyphs (U+0020, etc.). */
return GRUB_ERR_NONE;
/* Really 1 bit per pixel. */
/* Packed densely as bits. */
}