UEFI News and Commentary

Showing posts with label Fonts. Show all posts
Showing posts with label Fonts. Show all posts

Saturday, January 30, 2010

UEFI HII (Part 9): Font Package Encoding

Ok, now into the gory details of how font packages are encoded. In many ways, font packages are like string packages except, instead of strings, we are talking about font glyphs. There is a font header, followed by font information and then a series of font blocks.



The glyph blocks represent the glyphs in sorted order, starting with the glyph for character value 0x0001 and incrementing from there. Each glyph block increments the character value by either 1 or N. There are five basic types of glyph blocks:
  1. Glyphs. These actually contain glyph data. There are variants for a single glyph or multiple glyphs, ones which use default character cell information or their own character cell information. The current character value is incremented by either 1 (for single glyph versions) or N (for multiple glyph versions).
  2. Duplicate. This block duplicates the glyph data for a character value that has already been processed.  The current character value is incremented by 1.
  3. Skip. These blocks skip a specified number of character values. For example, there might be no glyphs for character values 0x2000-0x20FF, but then one more glyph for character value 0x2100. A Skip block leaves a gap. The current character value is incremented by the skip count specified.
  4. Defaults. This block sets up the default character cell information for the subsequent glyph blocks which use defaults. This is useful for fonts where a lot of characters share a specific set of information, such as Courier or other fixed-format fonts.
  5. End. This marks the end of the glyph block information.
The actual glyph data is packed with one bit per pixel of the glyph, but rows are rounded up to the nearest byte (8 pixel) boundary. For example, consider the letter 'A'.


In this case, the actual glyph data is 9 pixels wide and 11 pixels high. If optimally packed, this would lead to a storage size of 99 bits or 13 bytes (12 with 3 bits left over). However, when this was being discussed, some preliminary implementation data suggested that the glyphs were much easier to handle if each row was byte aligned (the blue shaded area in the diagram). Then, after testing with compression software (since we assumed that the fonts would be stored compressed) that the bit-packed data actually was larger after compression than the byte-packed data.

Conclusion
This wraps up the second on fonts. Next week, we'll dive into how HII stores and handles images.

Saturday, January 23, 2010

UEFI HII (Part 8): Proportional Fonts

The UEFI Specification provids services and storage for manipulating bitmap fonts as part of the Human Interface Infrastructure (HII). Last week, we looked at the Simple Font, which describes a means of storing a fixed-width font for Unicode character values. Each character in the Simple Font is either in an 8 x 19 (narrow) pixel or 16 x 19 (wide) pixel character cell.

Proportional fonts extend bitmapped font support in several significant ways:
  1. There can be multiple fonts, each described by its name, height and style (bold, italics, underline, etc.).
  2. Each character cell in the font can be a different width.
Fonts
So, for UEFI, a font is a logical grouping of glyphs identified by a name, a size and a style.
  • Font Name. "The font name describes, in broad terms, the visual style of the font." How do you tell that a character is part of the Arial font? Or Times New Roman? Well, they tend to share certain visual characteristics, such as whether they have serifs, or whether they are rounded or angular or represent alphabetic characters or symbols. 
  • Font Size. "The font size describes the maximum height of the character cell, in pixels. The standard font always has the font size of 19." Rather than describing characters in terms of "points", the UEFI specification describes them in terms of the height of the character cell, in pixels. The UEFI specification does not use points, because (a) it only uses bitmapped fonts and (b) although points technically refers to 1/72nd of an inch, it actually does little to describe how much screen space a font will take up (except in comparison with another point size for the same font).
  • Font Style. "The font style describes standard visual modifies to the base visual style of a font." In other words, you can have Arial, Arial + Bold, Arial + Italic, Arial + Bold and Italic, etc. They are still an Arial font, but they have additional stylistic modifiers. The UEFI specification explicitly supports bold, italic, underline, double-underline, embossed, outline and shadowed.
Glyphs
The glyph is the image representation of the character, with each dot in the image represented by a single bit, on or off. The off pixels are either not drawn (for transparent drawing) or else drawn in the background color. The on pixels are drawn in the foreground color. For example, for the letter A, it might look like this:


But this isn't enough information to draw the glyph. For one thing, we don't know how much space to leave between this glyph and other glyphs that we have drawn. This is one of the key differences between this font and the simple font in the previous articles. Simple fonts have the empty space above, below, before and after the character image built into the glyph. Proportional fonts track this sort of information separately, using three key ideas:
  1. The character cell.
  2. The baseline.
  3. The character advance.
Character Cell

The character cell is a box that the glyph's image is positioned inside of. Each font has a character cell and each character glyph's image is placed relative to the top-left corner of that cell, or box. For example:




Baseline
The baseline (or Offset Y) allows UEFI firmware to draw text from different fonts on the same line and still have everything line up correctly. The baseline is calculated as the number of pixels above the Origin of the tallest character image.

 

In this picture, the baseline is the height of the tallest character (A). Notice that the character 'q' starts 3 pixels below the baseline, while both the 'A' and 'x' start on the baseline and the quotation mark (") starts 8 pixels above the baseline. The gap between the Origin and the left-most pixel of the glyph is known as Offset X. For the 'A' and 'q' and quotation mark, this is 1 pixel. For the 'x', this is 0 pixels.

Character Advance
The character advance is the number of pixels to move the Origin to the right. The character advance determines how much whitespace to put to the left and right of the glyph.

Conclusion
All of these details about offsets and baselines, advances and cells may seem intimidating, especially in a firmware environment. Many basic tasks become a lot more difficult when using proportional fonts: drawing text, editing a string or selecting text (with a mouse!). Fortunately, the EFI_HII_FONT_PROTOCOL provides functions which not only draw a string to a buffer or to the screen, but also report back information about the width and height of each character drawn. We will investigate these in more detail later.

Next week we will return to how the fonts are encoded.

Saturday, November 28, 2009

UEFI HII (Part 6): Simple Fonts

Prior to to UEFI 2.10, there was only one graphics display mode: 800 x 600 x 32-bit color depth. Those numbers still show up as a required mode for external plug-in graphics adapters. But what if you want to draw text on those graphical displays? Where does the font come from? How big is it? Does the font really hold all 40K+ characters from the Unicode specification?

According to the EFI (and then UEFI), the system firmware was required to carry the ISO Latin-1 charcters (essentially characters U-0020 through U-00FF in the Unicode specification) as well as the line drawing characters. But that still leaves the question: how big are the bitmaps (or glyphs) in the font?

For a long time, prior to the UEFI 2.10 specification, the answer was 8 pixels wide and 19 pixels high. With a little math, you find that this works perfectly to put 80 columns and 25 rows of text on a 640 x 480 pixel display. That number of pixels, in turn, happens to be the highest resolution that could be produced by a standard VGA adapter. However, a character cell of 8 x 19 is not large enough to hold many of the glyphs found in other scripts, most notably Chinese, Japanese and Korean. So, in addition to the narrow 8 x 19 pixel character cells, a wide 16 x 19 pixel character cell was also supported.

One of the design goals for HII, back when UEFI 2.10 was being crafted, was the support for bitmapped, proportional fonts. But rather than throw away the previous way that font glyph encoding, the previous method was added as another package type: Simple Fonts (type 0x07).

Glyphs

Narrow glyphs consist of a header, followed by 19 bytes. Each of the bytes represents one row of the glyph. Byte 0 represents the top of the glyph and byte 18 represents the bottom of the glyph. Each bit in those bytes represents a single pixel, with a value of zero being off and a value of one being on. Bit 0 is the left-most pixel and bit 7 is the right-most pixel.

Wide glyphs consist of a header, followed by 38 bytes. Essentially they are encoded as two narrow glyphs, first the left half 8 x 19 image, followed by the right half 8 x 19 image.

Packages
The Simple Font package consists of the standard package header, a bit of housekeeping data and then an array of narrow glyph information, followed by an array of wide glyph information.
Each of the narrow glyphs has a small header, followed by the encoded glyph data.
typedef struct _EFI_HII_SIMPLE_FONT_PACKAGE_HDR {

  EFI_HII_PACKAGE_HEADER Header;
      UINT16           NumberOfNarrowGlyphs;
      UINT16           NumberOfWideGlyphs;
      EFI_NARROW_GLYPH NarrowGlyphs[];
      EFI_WIDE_GLYPH   WideGlyphs[];
    } EFI_HII_SIMPLE_FONT_PACKAGE_HDR;

Next week, we'll look at normal fonts.

typedef struct {

  CHAR16 UnicodeWeight;
  UINT8  Attributes;
  UINT8  GlyphCol1[EFI_GLYPH_HEIGHT];
} EFI_NARROW_GLYPH;

The Attributes indicate whether the glyph is narrow or wide and whether the character value is non-spacing. Normally, after drawing a character, the position of the next character would be directly to the right. For non-spacing characters, the next character would be drawn in exactly the same character cell. This allows, for example, the ` or ~ character to act as combining diacritical marks so that, when printed prior to an a or n, would display as á or ñ.
Each of the wide glyphs has a small header followed by the encoded glyph data:

typedef struct {

  CHAR16 UnicodeWeight;
  UINT8 Attributes;
  UINT8 GlyphCol1[EFI_GLYPH_HEIGHT];
  UINT8 GlyphCol2[EFI_GLYPH_HEIGHT];
  UINT8 Pad[3];
} EFI_WIDE_GLYPH;


Multiple Language Support
Let's say I'm designing a plug-in card and I want to support Chinese. But I don't know whether or not the system firmware in the platform where my card is installed supports all the Chinese characters (glyphs) that I need. What can I do? Well, with UEFI 2.10, your driver can just carry the characters you need that are in addition to those provided by the ISO Latin-1 characters that the platform is required to carry in its firmware. The HII Database will automatically combine glyphs from fonts which have the same font family, size and style.
Using The Simple Font
The simple font can be accessed, like all other fonts, through the HII Font protocol. The simple font has the name 'system' and has a height of 19 pixels.