Classic Computer Magazine Archive Article from Atari Classics magazine

PROGRAMMiNG WiTh DAiSy-DOT FONTS

by ThOMAS J. ANdREWS, AC CONTRibUTiNG AUThOR.

DD Fonts: Neat Stuff!
    We've all seen the fantastic Daisy Dot NLQ fonts used in Dave Richardson's column, "Exploring the Wild FONTier," and many of us have used one or more of the Daisy Dot series of programs. But how would you like to know how to use Daisy Dot fonts in your own programs? It's a snap once you know how the Daisy Dot system works. (You non-programmers, stick around awhile. There's something for you here, too.)
    Before we start, be aware this article only applies to fonts created for the original Daisy Dot and Daisy Dot 2 (files with the NLQ extender). The structure of Daisy Dot 3 font files with extenders of NL1, NL2, etc. is different, and they won't work with this system. Lack of space prevents me from explaining them here. (Translation: I haven't figured them out yet!) Also, this system may not work with printers other than those listed in the program: Epson compatibles (specifically the Epson LX-series), Star Gemini 10X, and the Atari XMM801.

What Is A Daisy Dot Font?
    Daisy Dot (hereafter called DD) fonts are printed using the graphics capabilities of the dot-matrix printer. Half the dots that form the characters are printed on one print line, the paper is advanced a minimal amount, and the rest of the dots are printed, filling in the spaces in the first set. This is much the same method used by printers with builtin NLQ capability.
    DD fonts are also proportional. This means the characters have different widths. For example, an "I" wouldn't be as wide as a "W". The use of proportional fonts increases text readability. Some printers have a proportional mode, others don't. Some that do, don't have an NLQ proportional mode. DD character widths can be expressed in "dots." Each character can be as narrow as one dot or as wide as 19.
    DD fonts don't support all ASCII characters. Only characters with ASCII values of 32-95, 97-122, and 124 are supported. Another thing to remember is that DD fonts are only 8 points high. (A "point" is 1/72nd of an inch, or one dot.) Most dot-matrix printers print 9 point text.

File Structure
    The first record of a DD font file is always "DAISY-DOT NLQ FONT." Any program using DD fonts should check for this record and provide error handling if it isn't there.
    The rest of the records contain the character bit maps, one record per character. The ASCII value of the first byte is the width of the character. The next few bytes are the values to be sent to the printer for the first line, followed by those for the second. For example, if a character is 8 bytes wide, the first byte of the record is a CHR$(8). The next 8 bytes are the bit maps for the first part of the character, and the 8 bytes after that are for the second part.
    There are two ASCII values that can't be in a DD bit map. These are CHR$(13) and CHR$(155). Some interfaces issue a line feed whenever they get a CHR$(13), the ASCII value for a carriage return. All interfaces for the Classic Atari change any CHR$(155) they get to a CHR$(13). Most interfaces aren't smart enough to know when these values are part of a data string, so they change them all. (By the way, this is true of any 8-bit program dealing with printer graphics.)

An Example
    So now you have all the information you need, and you can go ahead and use DD fonts in your own programs, right? No? All right, I'll program an example for you. While I'm at it I'll make it do something useful. With all the DD fonts in the Public Domain, it would be nice to have a way to have a printed sample of all your fonts, each printed in the same way and in several densities, so you could compare and contrast them for yourself.
    FONTEXAM.BAS (on ACs February'94 Software Disk) does just that for you. If you just want to use it, not analyze it, go ahead. It'll work with either AtariBASIC or TurboBASIC, but TurboBASIC is a bit faster. It's designed to work with AtariDOS 2.0s or 2.5. I don't know if it'll work with others DOSs. [Editor's Note: It works with the SpartaDOS--X cartridge BASIC XL, BASIC XE, and should work equally well with SpartaDOS 3.2d and MyDOS. -CC]
    All you have to do is follow the prompts. When asked for the "FONT NAME MASK," use any DOS 2.n-legal file name. If you don't specify a device code, disk drive D1: is assumed. The NLQ extender will be added for you, so don't include it. Wild cards are accepted. Use "'" or RETURN to do all NLQ fonts on D1:.
    FONTEXAM will search the directory for NLQ file names that fit the mask, then print them, one at a time, in three densities (two for the XMM801). The file name is also printed using the DD font. Up to nine fonts can be printed on a page. For those with more than one font disk, FONTEXAM will pick up printing of the new disk where the old one left off.

Back To You Programmers
    To help you understand what's going on here, I've sprinkled REM's throughout the program to identify the functions of each section. The text of each REM is in inverse for easy identification. After an information-bearing opening screen, FONTEXAM gets the printer type from the user and assigns the proper graphics function commands for that printer. (We'll ignore the M/L routine for the moment.) If you have any thoughts about releasing a program using printer graphics, please try to support as many printers as you can. There are lots of older printers still in use, and not all are Epson-compatible.
    Next, the program gets the filenames of the fonts it's to print and stores them in the variable called FL$. This is done by requesting a filename mask from the user and getting a directory listing for that mask. To avoid getting the "free sectors" message included as a filename, check for an "S" at the end of each directory record. Filename entries in DOS 2.n always end in digits, and the sectors message always ends in "S". The number of fonts to print is stored in NF.
    Now we have to load a font. After getting the first filename from the list, the font file is opened and checked for the identifier record. Before we can load this font, we have to pay attention to just how we're going to store it in RAM, since the storage method, in large part, depends on the access method. I can think of four basic ways to store/access a DD font, and there are probably more than that. I'm going to use the DELIMITER method.

Delimiter: Say What?
    A delimiter is a marker used to separate subgroups of data within a larger group. The occasional paragraph headings in this article could be considered delimiters. With this method, if you want to find a particular data subgroup all you have to do is scan for delimiters and count until you find the right one. This can be done very quickly using machine language, with minimal code.
    By its very nature, a delimiter must be something that can't appear in the data as data. In the case of a DD font, a first glance shows two possibilities, CHR$(13) and CHR$(155). But remember, characters could easily be 13 bytes wide, and the width is included in the font data. This means that CHR$(155) is the only choice. Fortunately, one choice is quite sufficient.
    So, the loading process consists of inputing each set of character data and storing it in one long string, with CHR$(155)'s between each set. The string must also have a CHR$(155) as its first character. Access to this data will be through the use of the M/L routine in DDFIND$. When called with the USR function, the address of the start of the font data [ADR(FONT$)] and the ASCII value of the character to be printed are passed along to it. When finished, DDFIND$ returns the FONT$ position of the width byte for that character. If DDFIND$ is called with a non-DD ASCII value, a 0 is returned.
    FONTEXAM lines 290-370 show how to use DDFIND$ to prepare a DD output line for a printer. With all the printers supported by FONTEXAM, graphics printing is pretty much the same in general form. Only the individual graphics command codes are different. Each sequence starts with a CHR$(27), followed by a byte indicating the density to be used. This byte is the one that's different for different printers.
    The next two bytes are the low and high parts of the number of data bytes to be sent. Depending on the density used, the maximum for this number is 480, 960, or 1920 bytes. Some printers will have even more densities, with different limits. Check your printer manual for them.
    The rest of the command is the string of data bytes. Each byte will produce a vertical row of up to 8 dots, with the individual bits determining which dots are printed. Bit values of 1 produce dots; 0's do not. On these printers, Bit 0 controls the lowest dot; Bit 7 controls the one on top.
    To prepare for the output procedure, the print output strings must be filled. Each print line requires two passes, remember, so there must be two strings. For the first print line, LBL$ contains the text to be printed, the filename of the current font. For each character in turn, DDFIND$ is used to locate the width byte in the font data. Let's say it's a CHR$(8). The next 8 bytes of the font string are placed at the end of OUT$, the first line of print data. The next 8 bytes after that are put into OUT2$, the second line of print data.

Character Spacing
    DD fonts don't contain any data for the space between letters. That must be provided by the user/program at print time. This feature allows the user to adjust for readability of the font and to program for microspace justification as found in commercially printed books, magazines, and newspapers. In FONTEXAM, I use standardized letter spacings, which are detailed on the opening screen. This is done by adding CHR$(0)'s, the ATASCII heart character, between each group of character print data in both OUT$ and OUT2$, one for each microspace. It's most important to use the same number of 0's in each string.
    Once the data strings are filled, the next step is to calculate the high and low bytes of their length. Both strings are the same length, so this only has to be done once.
    There's one more thing to check on before the actual printing takes place. Remember, all Atari printer interfaces change CHR$(155)'s to CHR$(13)'s, and some add on a CHR$(10). While there won't be any 155's or 13's in the DD data, there could easily be one or the other in the low byte of the string length. (Print line length limits keep it out of the high byte.) If the low byte DOES turn out to be a 155 or 13, a 1 must be added or subtracted from it, and the output string lengths adjusted accordingly. In FONTEXAM, I know the last byte of both output strings is a 0 (microspace), so I shorten each string. If this isn't done I can practically guarantee some mighty strange results from your printer!

Anything Else?
    Now we're finally ready to print a line. To do this, issue the following byte sequences to the printer. Be sure to use PRINT # and put a semicolon on the end if you don't want to issue a CHR$(155), or use PUT #. Do NOT use LPRINT!
    1. Change the line feed size to the minimum possible for the printer.
    2. Position the print head by issuing spaces or using tabs.
    3. Issue the appropriate printer graphics command sequence for the desired density.
    4. Issue the low, then the high bytes of the output string length.
    5. Issue the entire first output string (OUT$ in FONTEXAM), followed by a CHR$(155). (The printer will produce a carriage return and minimal line feed.)
    6. Repeat steps 2, 3, and 4.
    7. Issue the entire second output string (OUT2$ in FONTEXAM),followed by a CHR$(155).
    8. Issue a one-time line feed command of the proper size to position the print head vertically for the next line.
    Step 1 need not be repeated for subsequent lines, but remember to restore the line feed size when you're done using DD fonts.
    This procedure could've been done without changing the line feed size, but then it wouldn't have worked with all the printers listed. This particular procedure will work with all combinations of interfaces and these printers, at least all those that I know about.
    There now, that wasn't so difficult, was it? The only other thing to remember is to be sure the output strings aren't longer than the maximum dots/line of the density you're using. In fact, it's best to keep it one short of that limit. Some printers will issue a full-sized line feed as that last dot is printed, and that would really mess things up. Others will send an error message back to the computer, and a few will just sit there, looking confused.
    For double- or triple- width characters, just use each data element two or three times in the character output. Other special effects are possible. Play around with it. You can't hurt anything, as long as you back things up first.
    All the Daisy Dot program packages are copyrighted by Roy Goldman, so you can't use his program code without permission. The DD fonts, however, are all in the Public Domain, so you can do whatever you want with them.

Typing FONTEXAM: Watch Out!
    You can create a working copy of FONTEXAM from the magazine listing on page 13 by typing in the listing and SAVEing it to disk under the filename FONTEXAM.BAS. Watch out for line 110 (the M/L subroutine): typing that line is hairy! Due to the length of the program and the typing difficulty, most readers will probably want to just run it from the menu on the AC February '94 Software Disk


Daisy-Dot Font Examiner (Atari Classics)
FONTEXAM.BAS