Differences

This shows you the differences between two versions of the page.

Link to this comparison view

cybiko:fontfileformat [2009/11/27 17:54] (current)
Line 1: Line 1:
 +======Font File format======
  
 +Typically, fonts are saved with "​.fnt"​ as the file extension.
 +AFAIK, there are no actual rules as to what you save a font
 +file as. The font file format is not limited to fonts. It is
 +for any monochrome bitmap sequence. ​  Since it is unlikely
 +that you would want a monochrome bitmap for anything other
 +than a font (although bitmasking is a possibility),​ i'll
 +differentiate them from the 2 bit bitmap sequence files by
 +just calling them font files.
 +
 +=====Structure of the file=====
 +
 +A font file is divided into two parts, the font header
 +and the character records. ​
 +<​code>​
 +[FONTHDR] ​  4 BYTES //font header ​
 +[CHRRECS] ​  ? BYTES //character records
 +</​code>​
 +i'm going to give a section to each part of the file format ​
 +
 + 
 +====The font header(FNTHDR)====
 +
 +The font header contains information about the font, including
 +how many characters are in the font as well as how wide the
 +font is. 
 +<​code>​
 +[FONTHDR]
 +BEGIN
 +    [FILEID] 1 BYTE VALUE=0x01 //0x01 as the first byte of the header indicates a monochrome bmp seq
 +    [CHRCNT] 1 BYTE VALUE=? ​   //number of character records that can be found in the bmp seq
 +    [MAXWID] 1 BYTE VALUE=? ​   //largest width found in the bmp seq
 +    [MAXHGT] 1 BYTE VALUE=? ​   //largest height found in the bmp seq
 +END
 +</​code>​
 +MAXWID and MAXHGT are measured in pixels. ​
 +
 + 
 +====Character records(CHRRECS)====
 +
 +Within the character records portion of the file, a number
 +(corresponding to CHRCNT from FONTHDR) of variably sized character
 +records are stored. ​
 +<​code>​
 +[CHRRECS]
 +BEGIN
 +    [CHRREC0] ? BYTES //first character record
 +    [CHRREC1] ? BYTES //second character record
 +    [CHRREC2] ? BYTES //third character record
 +    .
 +    .
 +    .
 +    [CHRRECn] ? BYTES //last character record (n=CHRCNT-1)
 +END
 +</​code>​
 +
 +====Individual Characters(CHRRECx)====
 +
 +A single character record contains binary data about the character,
 +as well as a header containing the extent of that binary data. 
 +<​code>​
 +[CHRRECx] ​ //x is any record number
 +BEGIN
 +    [CHRHDR] 4 BYTES //character record header
 +    [CHRDAT] ? BYTES //binary data for bitmap
 +END
 +</​code>​
 +
 +====Character Header(CHRHDR)====
 +
 +The character header contains information about an individual
 +character'​s extent. ​
 +<​code>​
 +[CHRHDR]
 +BEGIN
 +    [CHRX] 1 BYTE //x offset(in pixels)
 +    [CHRY] 1 BYTE //y offset(in pixels)
 +    [CHRW] 1 BYTE //width of bitmap data(in pixels)
 +    [CHRH] 1 BYTE //height of bitmap data(in pixels)
 +END
 +</​code>​
 +This describes a rectangle that must lie within the rectangle
 +specified by the font header. ​
 +
 +CHRX must be in the range [0,​MAXWID)*\\
 +CHRY must be in the range [0,MAXHGT)*
 +
 +CHRX+CHRW must not exceed MAXWID and must be at least 1*\\
 +CHRY+CHRH must not exceed MAXHGT and must be at least 1*
 +
 +<note classic>
 +these are not hard and fast rules, but not following them could lead to unexpected results. ​
 +</​note>​
 +
 +The size of CHRDAT can be determined based on CHRW and CHRH 
 +<​code>​
 +(size of CHRDAT)=(CHRH)*(((CHRW)+7)/​8) ​
 +</​code>​
 +
 +====Character Data(CHRDAT)====
 +
 +The character data contains a number of variably sized
 +scan lines corresponding to CHRH. 
 +<​code>​
 +[CHRDAT]
 +BEGIN
 +    [SCANLINE0] ? BYTES //first scan line
 +    [SCANLINE1] ? BYTES //second scan line
 +    [SCANLINE2] ? BYTES //third scan line
 +    .
 +    .
 +    .
 +    [SCANLINEn] ? BYTES //last scan line(n=CHRH-1)
 +END
 +</​code>​
 +
 +====Scan lines(SCANLINEx)====
 +
 +Individual scan lines contain bit values for each horizontal
 +row in the bmp.   It contains one byte for every eight pixels
 +in the bmp, or any fraction thereof. ​
 +
 +If CHRW is [1,8], there will be 1 BYTE in the scan line if\\
 +CHRW is [9,16], there will be 2 BYTES in the scan line If\\
 +CHRW is [17,24] there will be 3 BYTES in the scan line (etc)
 +
 +Each byte contains information for up to eight pixels.
 +The first pixel is represented by bit7, then bit6, and so on. 
 +
 +For example, the following line of pixels (1=black, 0=white): ​
 +<​code>​
 +010110 ​
 +</​code>​
 +would have the following bit values and would fit into a single byte: 
 +<​code>​
 +b7: 0 
 +b6: 1 b5: 0 b4: 1 b3: 1 b2: 0 (b1 and b0 will have a value of 0, although they will be ignored)
 +for a byte value of 0x58 
 +</​code>​
 +
 +For another example, the following line of pixels: ​
 +
 +01011000101 ​
 +
 +would require 2 bytes, since there are 11 pixels, and the bit
 +values would look like: 
 +<​code>​
 +BYTE0: ​
 +b7: 0 b6: 1 b5: 0 b4: 1 b3: 1 b2: 0 b1: 0 b0: 0
 +
 +BYTE1: ​
 +b7: 1 b6: 0 b5: 1 (b4 through b0 are ignored and have a value of 0)
 +</​code>​
 +and so, the bytes would be 0x58 and 0xA0 
 +
 +=====Encoding Letters=====
 +
 +Here are two examples of encoding a monochrome bitmap into a
 +character record. ​
 +
 +The letter A 
 +
 +**Bit pattern:**
 +<​code>​
 +   ​01234567 ​
 +0 00110000 ​
 +1 01111000 ​
 +2 11001100 ​
 +3 11001100 ​
 +4 11111100 ​
 +5 11001100 ​
 +6 11001100 ​
 +7 00000000 ​
 +</​code>​
 +(indices for x and y position are above and to left of bit pattern) ​
 +
 +Determine CHRX and CHRY 
 +
 +The first column with a 1 in it is the first column(index 0),
 +so CHRX will be 0 The first row with a 1 in it is the first
 +row(index 0), so CHRY will be 0
 +
 +Determine CHRW and CHRH 
 +
 +The two rightmost columns are not used, the first unused column
 +having an index of 6, so CHRW=6-CHRX=6-0=6. The bottom most row
 +is not used, the first unused row has an index of 7, so CHRH=7-CHRY=7-0=7
 +
 +so, the CHRHDR will look like: 
 +
 +00 00 06 07 
 +
 +We strip away the excess columns and rows from the bit pattern: ​
 +
 +<​code>​
 +   ​012345 ​
 +0 001100 ​
 +1 011110 ​
 +2 110011 ​
 +3 110011 ​
 +4 111111 ​
 +5 110011 ​
 +6 110011 ​
 +</​code>​
 +And we encode each scan line, winding up with CHRDAT looking like: 
 +
 +30 78 CC CC FC CC CC 
 +
 +The entire character record looks like: 
 +
 +00 00 06 07 30 78 CC CC FC CC CC 
 +
 +The Comma (,) 
 +
 +The bit pattern: ​
 +
 +<​code>​
 +   ​01234567 ​
 +0 00000000 ​
 +1 00000000 ​
 +2 00000000 ​
 +3 00000000 ​
 +4 00000000 ​
 +5 00011000 ​
 +6 00011000 ​
 +7 00110000 ​
 +</​code>​
 +Determine CHRX and CHRY 
 +
 +the first column with a 1 in it has an index of 2, so CHRX=2
 +the first row with a 1 in it has an index of 5, so CHRY=5
 +
 +Determine CHRW and CHRH 
 +
 +the rightmost three columns are unused. the first of these
 +has and index of 5, so CHRW=5-CHRX=5-2=3 the bottommost row is
 +used, so the first unused row would have an index of 8,
 +so CHRH=8-CHRY=8-5=3
 +
 +The CHRHDR for this character would look like: 
 +<​code>​
 +02 05 03 03 
 +</​code>​
 +Remove rows and columns from the bit pattern ​
 +
 +<​code>​
 +   ​012 ​
 +0 011 
 +1 011 
 +2 110 
 +</​code>​
 +(note: i renumbered the indices) ​
 +
 +now, encode each of the scan lines into a single byte
 +(since there are only 3 bits each) 
 +
 +60 60 C0 
 +
 +and the entire character record would look like: 
 +
 +02 05 03 03 60 60 C0 
 +
 +
 +=====Final Words=====
 +
 +One thing remains to say.   The first bitmap in the font file
 +[CHRREC0] corresponds to character 0x20, which is more commonly
 +known as just "the space"​. ​  
 +
 +i've had difficulty using 2pic.exe to make font files. ​  i guess
 +the command line for it is just too long.
 +{{tag>​cybiko}}