*** CUSTOMIZED FONTS, also by Jakob Krarup... ******************************** One of the things I've noticed on the net is that a lot of people see you as a low- or medium skilled Basic programmer until you have your own font in your programs. Well - after reading Alex Warren's article on binary numbers in BASIX issue 9 I decided to make one myself. If you don't feel at home in the binary numbers, please read Warren's article again before continuing. Truth to tell, I had already made a font editor that allowed you to draw a 6x8 pixels font, but the way I stored it was *very* simple (don't laugh!). The fontfile itself was opened with: OPEN "filename.ext" FOR OUTPUT AS #1 and then every pixel was written to the file as an integer (0 or 1) using the command: PRINT #1, ... this resulted in each pixel in the font taking up three bytes instead of one bit because PRINT #1 writes a string to the filenumber indicated and finishes it off with two ascii signs CR and LF. CR (ASCII value 13) is a 'Carriage Return' which means: go to the beginning of the line again, and LF (ASCII value 10) is a 'Line Feed' which means: go down a line. All these two values do is is to put the cursor on the next line, back at the left margin. Anyway, with 140 characters in the font, each character with 6x8 (48) pixels, and each of these written in a byte followed by the two CR + LF bytes - this would mean a whopping: 140 x 6 x 8 x 3 bytes = 20,160 bytes or more than 20 Kb for the font. If I could put this into a bit per pixel, it would mean 140 x 6 x 8 bits = 6,720 bits / 8 = 840 bytes or only 4.2 percent of the original. This I had to work on! Okay - to begin with, I had a pretty good way of numbering the characters in my font, because I simply used the ASCII character number 33 (the exclamation point) as my first letter, and then ended up with ASCII value 172 (the 1/4 or one quarter sign) as the last letter. That way I could deduct 33 from the ASCII value of a letter the program was to write and index the values in the font array. I skipped the first 32 characters as most of them are unprintable anyway - look at the ASCII table in the BASIC helpfile for yourself. While I was still editing the font, each bit would have an integer value that determined whether there would be a pixel or not. So in memory the font would be dimensioned DIM Font% (140, 6, 8) and since there wasn't need for much more memory this was the easiest, instead of encoding and decoding to and from binary while editing. My font looked like this bitwise: (Capital A) 0 1 2 3 4 5 Columns Rows 0 0 0 1 0 0 0 1 0 1 0 1 0 0 2 1 0 0 0 1 0 3 1 1 1 1 1 0 4 1 0 0 0 1 0 5 1 0 0 0 1 0 6 0 0 0 0 0 0 7 0 0 0 0 0 0 And to encode them from the Font% array to the binary mode I'd do it one column at a time, top down, by multiplying the digits with 2 to the power of the row they are in. So the columns would look like this: (remember it's top down) Column 0 Column 1 Column 2 0 * 2^0 = 0 0 * 2^0 = 0 1 * 2^0 = 1 0 * 2^1 = 0 1 * 2^1 = 2 0 * 2^1 = 0 1 * 2^2 = 4 0 * 2^2 = 0 0 * 2^2 = 0 1 * 2^3 = 8 1 * 2^3 = 8 1 * 2^3 = 8 1 * 2^4 = 16 0 * 2^4 = 0 0 * 2^4 = 0 1 * 2^5 = 32 0 * 2^5 = 0 0 * 2^5 = 0 0 * 2^6 = 0 0 * 2^6 = 0 0 * 2^6 = 0 + 0 * 2^7 = 0 + 0 * 2^7 = 0 + 0 * 2^7 = 0 ---------------- ---------------- ---------------- = 60 = 10 = 9 ================ ================ ================ and so on... The fontstoring array would be dimensioned: DIM FontArray AS STRING * 840 '140 letters with 6 columns each and I'd then store the ASCII values in a string array using the chr$(ASCII code). That way the six first bytes were the first letter, the six next were the second etc. Then I could save the font using the BINARY format: OPEN "filename.ext" FOR BINARY AS #1 PUT #1, 1, FontArray CLOSE #1 Easy - huh? I could load the font file the same way OPEN "filename.ext" FOR BINARY AS #1 GET #1, 1, FontArray CLOSE #1 and then write them to the screen using PSET. The writing algorithm would look up the letter, and check each bit by AND'ing with 2 to the power of the pixel position in the column. Text$ = "Hi there!" SCREEN 13 'go into graphics mode Xmargin% = 100 'Where should writing begin on screen Ymargin% = 50 ColorDesired% = 14 'here we are writing with yellow FOR Letter% = 1 TO LEN(Text$) 'We check each letter in the text. AsciiValue% = ASC(MID$(Tekst, Letter%, 1)) - 33 'First we find the ASCII value and subtract 33 'to find the first byte (column) in the letter IF AsciiValue% >= 0 AND AsciiValue% <= 140 THEN 'and see if it's in the font FOR X% = 0 TO 5 'Checks the Columns FOR Y% = 0 TO 7 'Checks the rows IF ASC(FontArray (AsciiValue% * 6 + X%)) AND 2^Y THEN 'We AND the column byte with 2^row PSET (Xmargin% + (Letter% - 1) * 6 + X%, Ymargin% + Y%), ColorDesired% ENDIF NEXT Y% NEXT X% END IF NEXT Letter% Unfortunately this is rather slow on older machines - and you can actually see the font being written. So I made a look-up-table of all the values 0 - 7 squared and used that when AND'ing instead of doing math every time a pixel was set. The table is dimensioned and initiated like this: DIM LookUpTable(8) as INTEGER FOR Counter% = 0 to 7 LookUpTable(Counter%) = 2^Counter% 'generates the numbers 1, 2, 4, 8, ... 128 NEXT Counter% The center three lines in the fontdrawing algorithm would look like this then: IF ASC(FontArray (AsciiValue% * 6 + X%)) AND LookUpTable(Y) THEN PSET (Xmargin% + (Letter% - 1) * 6 + X%, Ymargin% + Y%), ColorDesired% ENDIF This speeds up the drawing quite a bit on math-weak machines. Finally - make the font drawing routine into a sub by all means and just pass along X and Y coordinates, the string to be printed and a color. SUB Write (Xmargin%, Ymargin%, Text$, ColorDesired%) FOR Letter% = 1 TO LEN(Text$) 'We check each letter in the text. AsciiValue% = ASC(MID$(Tekst$, Letter%, 1)) - 33 'First we find the ASCII value IF AsciiValue% >= 0 AND AsciiValue% <= 140 THEN 'then see if it's in the font FOR X% = 0 TO 5 'Check each column FOR Y% = 0 TO 7 'Check each row IF ASC(FontArray (AsciiValue% * 6 + X%)) AND 2^Y% THEN PSET (Xmargin% + (Letter% - 1) * 6 + X%, Ymargin% + Y%), ColorDesired% ENDIF NEXT Y% NEXT X% END IF NEXT Letter% END SUB Hope you can use this information in making your own fonts! Jakob Krarup - Jake@post5.tele.dk. -------------------------------------------------------- * EDITOR'S NOTE: * This article was originally printed in Peter Cooper's BASIX Fanzine, * Issue #10 from April 1998. This issue was edited by Alex Warren.