************************************** * BMFC.doc * * for BMFC 0.00 * * Copyright 1992 by Adam M. Costello * ************************************** BMFC 0.00 is a package containing: + This doc file. + The C source for the program "bmfc". + The BMF source for the fonts Lucid 10, 12, 13, and 15. BMFC 1.00 will also contain the source for the program "bmfd". TABLE OF CONTENTS TABLE OF CONTENTS FILE LIST LEGAL STUFF RELEASE NOTES DESCRIPTION USAGE ABOUT AMIGA BITMAP FONTS SOURCE LANGUAGE Basic Syntax Instructions TECHNICAL NOTES BUGS FILE LIST The BMFC 0.00 package is always distributed with at least the following files: BMFC.doc bmfc.c build.h build.c parse.h parse.c error.h error.c Lucid10.bmf Lucid12.bmf Lucid13.bmf Lucid15.bmf Each file is a text file that identifies itself on its second line, and the version of BMFC to which it belongs on the third line, so you can tell which file is which even if your file system doesn't allow these filenames. LEGAL STUFF The files listed in the FILE LIST section above are each Copyright 1992 by Adam M. Costello. I make no guarantees, and may not be held liable for any damage resulting from the use of those files. I, Adam M. Costello, grant you, whoever you are, permission to use those files in any way you wish, with the following two restrictions: 1) You may not distribute modifications of any of the files. 2) Whenever you distribute any one of the files, it must be accompanied by all the others. Of course, I cannot disallow the distribution of patches for the files, but I would much prefer that you send me any suggestions for modifications, so that I can incorporate them into a future version of BMFC. See the BUGS section for my addresses. RELEASE NOTES The changes between each released version of BMFC and the previous one are described here. BMFC 0.00 released Sun 30 Aug 1992: This is the first release. It is premature; bmfc has not been comprehensively tested, and bmfd has not even been written. I release this version only because I know there are a few people claiming to be "desperate" for a font editor. This is a compiler, not an editor, but but it serves the same purpose. DESCRIPTION bmfc compiles a BMF source file into an Amiga bitmap font load file. The C source for bmfc is not Amiga specific; it may be compiled and run on any machine which has an ANSI C compiler, assuming that fgetc() and fputc() read and write files a byte at a time. The load files which it produces, however, are useful only on an Amiga. No program is provided for creating .font files, since the program FixFonts, which comes with the operating system, does this. bmfd decompiles an Amiga bitmap font into a BMF source file. The source file, if compiled with bmfc, will produce a font which looks just like the original. The load file will almost certainly be different, though, because many different load files can specify same-looking fonts. bmfdump is useful for creating fonts which are very similar to existing fonts for which BMF source is unavailable. bmfd is an Amiga specific program, which requires the Amiga include files, amiga.lib, and the Amiga shared libraries. Lucid 10, 12, 13, and 15 are fonts designed to replace Topaz, since they have a similar style but are (in my opinion) much more readable. They are all non-proportional, non-color fonts with width 8. USAGE bmfc [-o ] is the name of the load file to be created (or overwritten). If the -o option is not supplied, the file created will have as its name the decimal numeral for its height in pixels. If the -o option is supplied more than once, the last one applies. is the name of the bmf source file. It's name must not begin with a minus sign. bmfd [-o ] is the name of the source file to be created (or overwritten). If the -o option is not supplied, the name .bmf will be used. If the -o option is supplied more than once, the last one applies. is the name of the font. Fonts:.font must exist (unless the font is already in memory). is the size of the font (height in pixels), as a decimal integer. Fonts:/ must exist (unless the font is already in memory). ABOUT AMIGA BITMAP FONTS An Amiga bitmap font, if it resides on disk, is a load file (i.e. a file that can be loaded directly into memory by the system function LoadSeg()) inside a subdirectory of Fonts: . For example, the font Lucid 10 is the load file "Fonts:Lucid/10". For a font to be usable, there must be a .font file in Fonts: whose name, minus the .font extension, is equal to the name of the subdirectory. For example, to use Lucid 10, there must be the file "Fonts:Lucid.font". The .font file describes the contents of the subdirectory. The program FixFonts, which comes with the Amiga operating system, will create or update all of the .font files. A font consists of glyphs, which are rectangular arrays of pixels. All glyphs in a font have the same height, but needn't have the same width. A font may define up to 256 glyphs, numbered 0 through 255, plus one default glyph, which is used in place of undefined glyphs. A font may be a color font, in which case each pixel may have a specific color defined by the designer, or a non-color font, whose pixels are just on or off. A font may be a proportional font, in which case the "pen" moves over by the width of the glyph in the process of drawing the glyph, or a non- proportional font, in which case the pen always moves over by a fixed amount regardless of the width of the glyph. When the system draws glyphs, it may be able to algorithmically bold, italicize, or underline them, depending on whether the font grants permission for these alterations. For more details about Amiga bitmap fonts, see the Rom Kernal Reference Manual Libraries, or see what you can glean from the SOURCE LANGUAGE and TECHNICAL NOTES sections of this doc file. SOURCE LANGUAGE The source language is called BMF. Basic Syntax In BMF, there are 6 classes of characters: class members --------------------- ------------------------- escape \ begin-comment { end-comment } instruction-separator ; blank space, formfeed, newline, carriage return, tab, vertical tab regular anything else Note that every character belongs to exactly one class. An escape causes the next character to be treated as a regular, even if it normally isn't. Comments begin with a begin-comment and end with an end-comment. Comments may be nested. Comments are skipped; that is, they do not become part of instructions or words (see below). Escapes take precedence over begin- and end-comments, so in the sequence "{\}", the escape is not commented out; rather, the end-comment is escaped. Instructions are separated by instruction-separators. Instructions may have length 0, so the sequence "a;;b" contains 3 instructions. Comments take precedence over instruction-separators, so in the sequence "{;}", the instruction-separator doesn't actually separate instructions, because the entire comment is skipped. Within an instruction, words are separated by blanks. Words may not have length 0, so the sequence "a b" contains only 2 words. Comments take precedence over blanks, so in the sequence "a{ }b", there is only one word, namely "ab". To make sure you understand the syntax, see if you agree that the file a\;b{c d{e}f\} g}h;\i j\\k contains two instructions, the first containing the single word "a;bh", the second containing the two words "i" and "j\k". Note that it is an error for the source file to end with an escape, or to end inside a comment. If a word consists of one or more decimal digits (0-9), or consists of a dollar sign ($) followed by one or more hex digits (0-9, A-F, a-f), or consists of a percent sign (%) followed by one or more binary digits (0-1), then it represents an integer (it should be obvious which one!). Only integers in the range [0,4294967295] are allowed. Instructions We now know what counts as an instruction syntactically, but only certain instructions are actually acceptable. In the descriptions that follow, whenever it is said that a word must be in a range [a,b], it is implied that the word must represent an integer. Most instructions are not required, most may appear no more than once, and for most, it does not matter where in the source file they appear. All exceptions to these norms will be explicitly stated. The empty instruction, which contains no words, does nothing, but is acceptable. bitmapfont This must be the first instruction in the source file. will be used to fill in the fontname in the load file, and will be truncated to 32 characters if necessary. Since the fontname will be overwritten with the name of the .font file when the file is loaded, is not really important, except to help humans looking at the load file to identify it. is the height of the font in pixels, i.e., the number of rows in each glyph. It must be in the range [1,65535]. xydpi Causes a TA_DeviceDPI tag to be associated with the font. and describe the aspect ratio of the output device for which the font was designed. The individual values are not important, only the ratio. Both must be in the range [1,32767]. colors ... The number of words in this instruction is determined by the value of , which must be in the range [0,256]. This instruction defines the colors for a color font. Each must be in the range [$000,$FFF], and represents a 4 bit/gun RGB color of the form $RGB. colorsym The character , which must be a one-character word, is mapped to color #. The map affects the way the glyph instruction is interpreted (see below). The colorsym instruction may appear any numbers of times, and its placement is significant. Each instance of the instruction modifies the current map, and each glyph instruction is interpreted using the current map at that point in the source file. Before any colorsym instructions are encountered, the map looks like this: characters color number ---------- ------------ @#*1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 Aa 10 Bb 11 Cc 12 Dd 13 Ee 14 Ff 15 (All other characters are mapped to color number 0) must be in the range [0,255]. glyph ... ... ... The number of words in this instruction is determined by the values of and , each of which must be in the range [0,256], with <= , and by the value of from the bitmapfont instruction. The number of words following is ( - + 1) * Each word defines one row of one glyph, as hinted by the choice of word names above. All the words pertaining to a particular glyph must have the same length. Each character in the word is mapped to a color number according to the current map (see the colorsym instruction), and defines one pixel of the glyph. A non-color font may use only color numbers 0 and 1. A color font may use only color numbers 0 through 2^depth - 1 (see the depth parameter, below). The order of the words is intended to allow the source file to contain the appearances of the defined glyphs. For example: glyph 65 66 __#___ ####__ _#_#__ #___#_ #___#_ #___#_ #___#_ ####__ #####_ #___#_ #___#_ #___#_ #___#_ ####__ ______ ______ ; The glyph instruction may appear more than once, but the same glyph may not be defined more than once. Glyph 256 is the default glyph, used for all undefined glyphs (even if there are none), so glyph 256 must be defined. Also, at least one of the glyphs 0-255 must be defined. nullglyph This instruction defines glyphs through to be zero-width glyphs. and must be in the range [0,256], with <= . This instruction may appear more than once, but no glyph may be defined more than once. This instruction is provided because Amiga bitmap fonts allow zero-width glyphs, but the glyph instruction doesn't. I can't imagine why anyone would want such glyphs, but the possibility is here. The remaining instructions are all assignments. An assignment sets the value of a parameter. The form of an assignment is Each parameter may be assigned no more than once. Parameters that are not assigned receive default values. Descriptions of all parameters follow, in the form If the or is a function rather than a constant, it will be replaced by an asterisk, and described in the . antialias 0 [0,1] If 1, indicates something about the colors defined by the colors instruction. I'm not sure what. This instruction sets a flag which is defined in graphics/text.h, but which is not mentioned in RKM Libraries. Unused in a non-color font. baseline * * Defaults to - 2, or 0 if is 1, where is from the bitmapfont instruction. Range [0, - 1]. If the rows of a glyph are numbered starting with 0 at the top, then row baseline+1 is the one that gets set when the font is algorithmically underlined. bold 0 [0,1] If 1, indicates that the font is already bold, and may not be algorithmically bolded. boldsmear 1 [0,65535] The number of pixels to the right to re-render the glyph when algorithmically bolding. colorfont 0 [0,1] If 1, indicates that the font is a color font. depth 1 [1,8] Specifies the number of bitplanes for a color font. Unused for a non-color font. extended 0 [0,1] If 1, indicates that the font is extended. fgcolor 255 [0,255] Specifies which color number should be replaced by the foreground color. 255 means no color should be replaced. Unused for a non-color font. greyfont 0 [0,1] If 1, indicates that the colors defined by the colors instruction are intended to be even-stepped greyshades. Unused for a non-color font. high * * Defaults to 2^depth - 1 (see parameter depth). Range [low, 2^depth - 1] (see parameter low). Specifies the greatest color number used by this font. Unused for non-color fonts. italic 0 [0,1] If 1, indicates that the font is already italic, and may not be algorithmically italicized. low 0 * Specifies the least color number used by the font. Range [0, 2^depth - 1] (see parameter depth). Unused for non-color fonts. planeonoff 0 [0,255] Specifies that a background plane which doesn't receive glyph data should be set, if the corresponding bit in planeonoff is 1, or cleared, if the corresponding bit in planeonoff is 0. Unused for non-color fonts. planepick 255 [0,255] Chooses into which planes of the background to render the planes of the glyphs. Plane 0 of the glyphs is rendered into the background plane corresponding to the least significant 1-bit in planepick. Plane 1 of the glyphs is rendered into the background plane corresponding to the next more significant 1-bit of planepick, and so on. Unused for non-color fonts. proportional * [0,1] Defaults to 1 unless all defined glyphs have the same width, in which case it defaults to 0. If 0, indicates that the actual widths of the glyphs should be ignored, and xsize used instead for positioning the glyphs (see parameter xsize). returncode 100 [0,127] The returncode if the load file is executed. revision 0 [0,65535] The revision number of the font. revpath 0 [0,1] If 0, the font goes from left to right. If 1, the font goes from right to left. talldot 0 [0,1] If 1, indicates that the font was designed for a high resolution non-interlaced screen. underlined 0 [0,1] If 1, indicates that the font is already underlined and may not be algorithmically underlined. widedot 0 [0,1] If 1, indicates that the font was designed for a low resolution interlaced screen. xsize * [0,65535] Defaults to the maximum width of all the defined glyphs. For a non- proportional font, the actual width of each glyph (which may not equal xsize) is ignored, and this value used instead for positioning glyphs. This value is also used by the console.device when reading keyboard input, even for proportional fonts. You may have noticed that the descriptions of the parameters greyfont, low, high, planepick, and planeonoff were rather vague. That's because I don't fully understand them myself. TECHNICAL NOTES The origin of each field of the struct DiskFontHeader is described below: dfh_NextSegment is not actually part of the struct DiskFontHeader, and is not even contained in the load file; it is supplied by LoadSeg(). dfh_ReturnCode is $70xx4E75, where the xx is filled in with returncode. This is not actually part of the struct DiskFontHeader, but appears at the start of the code hunk in the load file. It is the 68000 machine code for: MOVEQ #$xx,D0 RTS dfh_DF.ln_Succ is 0, but will be overwritten when the font is loaded. dfh_DF.ln_Pred is 0, but will be overwritten when the font is loaded. dfh_DF.ln_Type is NT_FONT = 12. dfh_DF.ln_Pri is 0. dfh_DF.ln_Name points to dfh_Name. dfh_FileID is DFH_ID = $0F80. dfh_Revision is revision. dfh_Segment is 0, but will be overwritten when loaded. This is also called dfh_TagList. Someone please give me a clue here. See the BUGS section. dfh_Name is from the bitmapfont instruction, padded with 0's or truncated to 32 bytes. It will be overwritten when the font is loaded. dfh_TF.tf_Message.mn_Node is a copy of dfh_DF. dfh_TF.tf_Message.mn_ReplyPort is 0, but will be overwritten when the font is loaded. It is also called dfh_TF.tf_Extension. Someone please give me a clue here. See the BUGS section. dfh_TF.tf_Message.mn_Length is 0. It's reserved, so I don't know what will become of it when the font is loaded. dfh_TF.tf_YSize is from the bitmapfont instruction. dfh_TF.tf_Style is FSF_UNDERLINED * underlined + FSF_BOLD * bold + FSF_ITALIC * italic + FSF_EXTENDED * extended + FSF_COLORFONT * colorfont = underlined + 2 * bold + 4 * italic + 8 * extended + 64 * colorfont dfh_TF.tf_Flags is FPF_DISKFONT + FPF_REVPATH * revpath + FPF_TALLDOT * talldot + FPF_WIDEDOT * widedot + FPF_PROPORTIONAL * proportional + FPF_DESIGNED = 2 + 4 * revpath + 8 * talldot + 16 * widedot + 32 * proportional + 64 dfh_TF.tf_XSize is xsize. dfh_TF.tf_Baseline is baseline. dfh_TF.tf_Boldsmear is boldsmear. dfh_TF.tf_Accessors is 0, but will be overwritten after the font is loaded. dfh_TF.tf_LowChar is the least defined glyph number. dfh_TF.tf_HighChar is the greatest defined glyph number other than 256. dfh_TF.tf_CharData points to the bitplane containing the defined glyphs, in order, stripped of blank columns on their sides. The bitplane is padded on the right with blank columns to bring its width up to a multiple of 16. A blank column is one whose pixels are all color #0. dfh_TF.tf_Modulo is the number of bytes in each row of the bitplane. dfh_TF.tf_CharLoc points to an array of pairs of UWORDs, one pair for each glyph from tf_LowChar through tf_HighChar, plus one pair for glyph 256. The first word of each pair is the horizontal offset into tf_CharData at which the corresponding glyph starts. The second word of each pair is the width of the glyph, after being stripped of blank columns on its sides. dfh_TF.tf_CharSpace and dfh_TF.tf_CharKern: Each points an array of WORDs, one WORD for each glyph from tf_LowChar through tf_HighChar, plus one WORD for glyph 256. For each glyph, let A be the number of blank columns on the left side, let C be the number of blank columns on the right side, and let B be the number of columns remaining in the middle. If all columns are blank, then A = B = 0, and C = the total number of columns. B is the width of the glyph in the bitmap. For a forward path font, the tf_CharKern value is A and the tf_CharSpace value is B+C. For a reverse path font, the tf_CharKern value is -B - C, and the tf_CharSpace value is -A. If the font is a color font, there are additional fields: dfh_TF.ctf_Flags is CT_COLORFONT * + CT_GREYFONT * greyfont + CT_ANTIALIAS * antialias = + 2 * greyfont + 4 * antialias where is 1 if the colors instruction appeared in the source, and 0 if it didn't. dfh_TF.ctf_Depth is depth. dfh_TF.ctf_FgColor is fgcolor. dfh_TF.ctf_Low is low. dfh_TF.ctf_High is high. dfh_TF.ctf_PlanePick is planepick. dfh_TF.ctf_PlaneOnOff is planeonoff. dfh_TF.ctf_ColorFontColors->cfc_Reserved is 0. dfh_TF.ctf_ColorFontColors->cfc_Count is from the colors instruction, or 0 if there was no colors instruction. dfh_TF.ctf_ColorFontColors->cfc_ColorTable is 0 if cfc_Count is 0, otherwise it points to an array of cfc_Count UWORDs containing the values from the colors instruction. dfh_TF.ctf_CharData is an array of 8 pointers. The first depth pointers point to the individual bitplanes in dfh_TF.tf_CharData ("depth" is a number, not an adjective!). The remaining pointers are 0. BUGS The xydpi instruction doesn't actually cause a TA_DeviceDPI tag to be put into the load file because I don't know whether to use dfh_TagList or dfh_TF.tf_Extension or both, or if I'm even allowed to put tags into the load file (maybe they only appear in the .font file). Someone please give me a clue here, because the RKMs are not clear on this. There are certainly other bugs waiting to be discovered (after all, this is only version 0.00). I do intend to fix them, but please help me find them. Send all bug reports and suggestions to the email address amc@cics.wustl.edu or to the United States postal address Adam Costello 6515 Wydown Blvd. #4240 St. Louis, MO 63105 Note that both addresses may change in August 1993.