cybiko:fontfileformat

no way to compare when less than two revisions

Differences

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


cybiko:fontfileformat [2009/11/27 17:54] (current) – created - external edit 127.0.0.1
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}}
  • cybiko/fontfileformat.txt
  • Last modified: 2009/11/27 17:54
  • by 127.0.0.1