> Fonts.Formats Font File Formats ----------------- IntMetrics: 40 Name of font, padded with 4 16 4 16 1 n = number of defined characters 3 reserved (must be 0) 256 character mapping (ie. indices into following arrays) 2n x0 - bounding box of character (in 1/1000ths em) 2n y0 - coordinates are relative to the 'origin point' 2n x1 - 2 bytes per entry 2n y1 - 2n x-offset after printing this character 2n y-offset after printing this character x90y45: Index: 1 point size (not multiplied by 16) 1 bits per pixel (4) 1 pixels per inch (x-direction) 1 pixels per inch (y-direction) 4 reserved (was checksum) - must be 0 4 offset of pixel data in file 4 size of pixel data ... more of the same 1 0 Pixel data: 4 x-size in 1/16ths point * pixels per inch (x) 4 y-size in 1/16ths point * pixels per inch (y) 4 pixels per inch (x-direction) 4 pixels per inch (y-direction) 1 x0 - maximum bounding box for any character 1 y0 - bottom-left is inclusive 1 x1 - top-right is exclusive 1 y1 - all coordinates are in pixels 512 2-byte offsets from table start of character data 0 => character is not defined (pixel data is limited to 64K per block) Character data: 1 x0 - bounding box 1 y0 1 x1-x0 1 y1-y0 4*n 4-bpp, consecutive rows bottom->top not aligned until the end Outlines / f9999x9999 / b9999x9999: b9999x9999 1-bpp definition a9999x9999 4-bpp (anti-aliased) definition Outlines the outline file '9999' = pixel size (ie. point size * 16 * dpi / 72) zero-suppressed decimal number File header: 4 "FONT" - identification word 1 Bits per pixel: 0 = outlines 1 = 1 bpp 4 = 4 bpp 1 Version number of file format (currently 4) 2 if bpp = 0: design size of font if bpp > 0: flags: bit 0 set => horizontal subpixel placement bit 1 set => vertical subpixel placement 2 x0 - font bounding box (16-bit signed) 2 y0 - units are pixels or design units 2 x1-x0 - x0,y0 inclusive, x1,y1 exclusive 2 y1-y0 4 file offset of 0..31 chunk (word-aligned) 4 file offset of 32..63 chunk ... 4 file offset of 224..255 chunk 4 file offset of end (ie. size of file) if offset(n+1)=offset(n), then chunk n is null. Table start: 2 n = size of table/scaffold data Bitmaps: (n=10 normally - other values are reserved) 2 x-size (1/16th point) 2 x-res (dpi) 2 y-size (1/16th point) 2 y-res (dpi) Outlines: 510 offsets of scaffold data from table start 0 => no scaffold data for char ? ... sets of scaffold data (see below) Table end: ? description of contents of file: , 0, "Outlines", 0 "999x999 point at 999x999 dpi", 0 ... word-aligned chunks follow Scaffold data: 1 char code of 'base' scaffold entry (0 ==> none) 1 bit n set ==> x-scaffold line n defined in base char 1 bit n set ==> y-scaffold line n defined in base char 1 bit n set ==> x-scaffold line n defined locally 1 bit n set ==> y-scaffold line n defined locally ... local scaffold lines follow Scaffold lines: 2 bits 0..11 = coordinate (signed) bits 12..14 = scaffold link index (0 => none) bit 15 set => 'linear' scaffold link 1 width (254 ==> L-tangent, 255 ==> R-tangent) Chunk data: 4 * 32 offset within chunk to character 0 => character is not defined * 4 for vertical placement * 4 for horizontal placement Character index is more tightly bound than vertical placement which is more tightly bound than horizontal placement. Note: All character definitions must follow the index in the order in which they are specified in the index. This is to allow the font editor to easily determine the size of each character. ... word-aligned character data follows Char data: 1 flags: bit 0 set => coords are 12-bit, else 8-bit bit 1 set => data is 1-bpp, else 4-bpp bit 2 set => initial pixel is black, else white bit 3 set => data is outline, else bitmap bits 4..7 = 'f' value for char (0 ==> not encoded) 2/3 x0, y0 sign-extended 8- or 12- bit coordinates 2/3 xs, ys width, height (bbox = x0,y0,x0+xs,y0+ys) n data: (depends on type of file) 1-bpp uncrunched: rows from bottom->top 4-bpp uncrunched: rows from bottom->top 1-bpp crunched: list of (packed) run-lengths outlines: list of move/line/curve segments word-aligned at the end of the character data Outline char format ------------------- Here the 'pixel bounding box' is actually the bounding box of the outline in terms of the design size of the font (in the file header). The data following the bounding box consists of a series of move/line/curve segments followed by a terminator and an optional extra set of line segments followed by another terminator. When constructing the bitmap from the outlines, the font manager will fill the first set of line segments to half-way through the boundary using an even-odd fill, and will thin-stroke the second set of line segments (if present). See the documentation on the Draw module for further details. Each line segment consists of: 1 bits 0..1 = segment type: 0 => terminator (bit 2 set => stroke follows) 1 => move to x,y 2 => line to x,y 3 => curve to x1,y1,x2,y2,x3,y3 bits 2..4 = x-scaffold link bits 5..7 = y-scaffold link ... coordinates follow The coordinates are either 8- or 12-bit, depending on bit 0 of the character flags (see above). The scaffold links associated with each line segment relate to the last point specified in the definition of that move/line/curve, and the control points of a bezier curve have the same links as their nearest endpoint. 1-bpp uncompacted format ------------------------ 1 bit per pixel, bit set => paint in foreground colour, in rows from bottom-left to top-right, not aligned until word-aligned at the end of the character. 1-bpp compacted data format --------------------------- The whole character is initially treated as a stream of bits, as for the uncompacted form. The bit stream is then scanned row by row, with consecutive duplicate rows being replaced by a 'repeat count', and alternate runs of black and white pixels are noted. The repeat counts and run counts are then themselves encoded in a set of 4-bit entries. Bit 2 of the character flags determine whether the initial pixel is black or white (black = foreground), and bits 4..7 are the value of 'f' (see below). The character is then represented as a series of packed numbers, which represent the length of the next run of pixels. These runs can span more than one row, and after each run the pixel colour is changed over. Special values are used to denote row repeats. == 0 followed by n-1 zeroes, followed by n+1 nibbles = resulting number + (13-f)*16 + f+1 - 16 i = 1 .. f i i = f+1 .. 13 (i-f-1)*16 + next nibble + f + 1 14 followed by n= = repeat count of n 15 repeat count of 1 (ie. 1 extra copy of this row) The optimal value of f lies between 1 and 12, and must be computed individually for each character, by scanning the data and calculating the length of the output for each possible value. The value yielding the shortest result is then used, unless that is larger than the bitmap itself, in which case the bitmap is used. Repeat counts operate on the current row, as understood by the unpacking algorithm, ie. at the end of the row the repeat count is used to duplicate the row as many times as necessary. This effectively means that the repeat count applies to the row containing the first pixel of the next run to start up. Note that rows consisting of entirely white or entirely black pixels cannot always be represented by using repeat counts, since the run may span more than one row, so a long run count is used instead.