REALbasic University Resources:

RBU: Glossary Defines common REALbasic programming terms
  Archives Previously published columns
Translations: Dutch Courtesy of Floris van Sandwijk
  Japanese Courtesy of Kazuo Ishizuka
  Chinese Courtesy of Dong Li
  RBU Translation Guide Information on Translating RBU into other languages
Books: Matt's Book (2nd Edition!) Ideal for experienced programmers
  Erick's Book Best for beginning programmers
Websites: Mother Ship The publisher of REALbasic
  RB Webring Links to hundreds of REALbasic websites
  RESExcellence Another REALbasic programming column
  REALbasic Developer Magazine The premiere source for REALbasic instruction.

REALbasic University is Sponsored by

Make your Mac do what YOU want it to. Create games, utilities, cool Mac OS X tricks. Download REALbasic now and create your own software.


Print This Article

REALbasic University: Column 066

FontPrinter: Part Five

In our previous lesson we added a Print Preview window feature. But right now FontPrinter doesn't do what it was designed to do: print out lists of fonts. Today we'll finish the program by finalizing the drawing routine.

Drawing the Printing

The core of FontPrinter is the drawIt routine, which does the actual drawing. This is a somewhat complex routine, so we'll step through it carefully.

First, let's consider what we want to do. Our goal is to display all the "typeable" characters of a font. So that means we need to show each character on the keyboard the way it normally appears (no modifiers pressed), show it as it looks with the Shift key down, with the Option key down, and with the Shift and Option keys keld down. That's four different versions of the same thing, so a sensible way to display that would be four columns of letters.

Now since the user might be printing a symbol font (a font with pictures instead of letters), we have to make sure to print the "normal" (no modifier) character in a normal font. I chose Helvetica, but you could use any standard font (ideally, choose one that's installed on all Macs). The solution I came up with is to print, in small type, enclosed in parenthesis, the normal character. Then to the right of that, in large type, the letter in the user's font.

Here I ran into another problem. To get all the letters to fit on a single page, I can't double-space the lines of type: they need to be close together. But then the larger letters overlap each other. I quickly came up with a simple solution: stagger the larger letters. By not printing them directly on top of each other, there's room for each letter but the line spacing of the entire grid can still be tight enough to fit all the letters on a single page.

A Unicode Problem

Now in the original version of this program, written back in Mac OS 9 days, I didn't have to worry about text conversion. If I specified a particular ASCII number that's what I got (i.e. chr(65) would be a capital "A" in Helvetica, or a six-pointed star in Zapf Dingbats). But Mac OS X is more sophisticated: it's actually intelligent about font characters and if I specify I want a capital "A" but in the Zapf Dingbats font, it will give me a capital A in a default font that has a capital A, but it won't be in Zapf Dingbats. That's because Mac OS X knows that Zapf Dingbats doesn't have a capital A and Mac OS X assumes that's what I want since ASCII 65 is supposed to be a capital A. The Mac OS X solution is to use Unicode and specify the actual character I'm wanting.

In Detail

If you're not familiar with Unicode, TidBITS has this excellent introduction (part two is available here).

In brief, Unicode is a new international, multi-platform standard that maps every possible character a person could want to type (in any language) to a unique number. This is far better than the current system, where ASCII 65 might be one thing in one font or on one platform, and something completely different on another. With Unicode, if you specify the specific letter you want, that's what you'll get.

Unfortunately, right now the Unicode situation is similar to a few years ago when Apple made the switch from serial to USB: not all programs (even Mac OS X ones) are Unicode aware, the implementations vary from program to program, and even Mac OS X is missing some Unicode support. And of course, millions still use Mac OS 9, which does not support Unicode.

So currently we live in a world that's part Unicode and part not Unicode, and the transition is confusing and awkward. Eventually Unicode will make FontPrinter obsolete: after all, the whole point of FontPrinter is to show us the keyboard strokes needed to produce various letters in various fonts, but Mac OS X overrides that by continuing to produce the characters we're typing, not the ones in the font we specify. It's weird: in Mac OS X's TextEdit, try to type the six-point star (Shift-A) in Zapf Dingbats. You can't! Mac OS X won't let you. Even if you change the font to Zapf Dingbats, the letters display in the default (normal) font:

So the keyboard shortcuts described by FontPrinter are useless under Mac OS X Unicode-aware applications. (They still work for some Carbon apps and all Classic ones.)

How to type Unicode characters is beyond the scope of this column, but let's just say it's currently not as easy as it used to be. Have patience, though: it will get better. Personally, I'm not crazy about this Mac OS X automatic changing of my fonts. I'm used to the old way and my thinking's stuck in that mode. However, it does make sense that Unicode is the future, and eventually I'll learn to like it.

Our problem is that Mac OS X's Unicode support will prevent us from displaying the symbol characters in unusual fonts. What we want is a return to the old way: a way to display fonts in their actual font and not be overridden by Mac OS X's automatic font replacement system.

In other words, if we don't do something, when the user picks Zapf Dingbats as the font, our program won't display the six-pointed star for ASCII 65: it'll display a captial A in some replacement font. That's not what we want.

(Sharp readers might remember we ran into this problem while creating RBU Pyramid. We originally used the Symbol font to draw the symbols for the various playing card suits, but later had to change that routine to use imported graphics because Mac OS X overrode our Symbol request thinking we wanted normal letters.)

Fortunately, REALbasic gives us the tools to solve this problem. REALbasic is aware of Unicode (and other encodings) and can convert from one to another. The basic principle is this: you tell REALbasic what you're converting from (the input encoding) and what you want that converted to (the output encoding) and then tell it to convert the text. In principle, that's simple enough. However, REALbasic's object-oriented approach to things actually makes this a bit confusing.

Remember, in object-oriented programming, an object knows how to manipulate itself. That's the whole idea. So instead of a procedural approach like this:

  
newText = convertText(oldText, inputEncoding, outputEncoding)

we must instead do a couple steps, like this:

  
converter = getTextConverter(inputEncoding, outputEncoding)
newText = converter.convert(oldText)

That's not that hard, once you see it like this. However, you also have to get your inputEncoding and outputEncoding objects. You can do that with the getFontTextEncoding command like this:

  
inputEncoding = getFontTextEncoding("Zapf Dingbats")
outputEncoding = getFontTextEncoding("Zapf Dingbats")

What this does is tell REALbasic that both our input and output fonts are Zapf Dingbats, meaning that that's what we want it to use (no automatic substitution). Once we convert the text (the previous bit of code), REALbasic makes sure that our symbols are the Zapf Dingbat ones.

The result of all this is we have multiple objects: text encoding objects (which contain the info about the specific encoding type) and a text converter object (which actually does the conversion). It's not that bad, but just trying to figure that out from the built-in documentation can be tough (not to mention learning about all the encoding types, something I avoid in this situation by using the GetFontTextEncoding function).

There are also differences in how this works between the various versions of REALbasic. The above code is how it works for REALbasic 4.5, but REALbasic 4 seems to act a little differently, and earlier versions of REALbasic supported Unicode incompletely. Your best bet is to use the latest version of REALbasic and test your code thoroughly to make sure what you think is happening is really happening.

The DrawIt Code

But enough of all this lecturing. Let's take a look at the code for drawIt and see if you understand how it works:

  
dim i, j, x, y as integer
dim c, s as string
dim tcon as textConverter
dim t as textEncoding

const defaultFont = "Helvetica"

t = getFontTextEncoding(fontPopup.text)
tcon = getTextConverter(t, t)

g.textFont = defaultFont
g.textSize = 18
g.bold = true
g.drawString "Font: " + fontPopup.text, 72, 26

x = 72 // left margin
for i = 1 to 4
y = 48 // top margin
select case i
case 1
s = "Normal"
case 2
s = "Shift"
case 3
s = "Option"
case 4
s = "Shift-Option"
end select

g.textFont = defaultFont
g.textSize = 14
g.bold = true
g.drawString s, x, y

for j = 1 to len(gTheString(i))
y = y + 14
c = mid(gTheString(i), j, 1)

g.textFont = defaultFont
g.textSize = 10
g.bold = false

g.drawString "(", x, y
g.drawString c, x + 16, y
g.drawString ")", x + 32, y

if j / 2 = j \ 2 then
g.foreColor = rgb(230, 230, 230) // gray
g.fillRect(x, y, 117, 14)
g.foreColor = rgb(0, 0, 0) // black
end if

g.textFont = fontPopup.text
g.textSize = 24
g.bold = false

if tcon <> nil then
c = tcon.convert(c)
end if
if j / 2 = j \ 2 then
g.drawString c, x + 48 + 36, y
else
g.drawString c, x + 48, y
end if
next // j
x = x + 117 // a fourth of the width
next // i

As usual, we begin by defining the variables (properties) our method will use. You'll note there are some unusual objects here: tcon as textConverter and t as textEncoding. We'll need those to convert our text to make sure we output the proper symbols.

Next, you'll note that we define a local constant. This is the name of the "normal" (non-symbol) font we'll use for displaying the characters to type. I chose Helvetica, but you could use Arial, Monaco, System, or whatever.

Right at the beginning we set our textEncoding object, t, to the proper encoding by passing the getFontTextEncoding function the name of the font we're using (which happens to be the text of fontPopup). Then we create our textConverter object, tcon. Note that we haven't converted anything yet: all we're doing here is preparation.

Now we're ready to draw. We begin by drawing the name of the font we'll be drawing in large letters at the top of the page. We draw it in our default font, not the user font, so we can be sure it will be readable.

Then we set up a loop. We'll have four columns of info, so we need a 4x loop. For each step through the loop we establish different text for the column's label. We draw that label at the top of each column.

Now, a couple lessons ago, we created a routine to fill the array gTheString with text from a TEXT resource in FontPrinter's resource fork. That method is called init and it's in globalsModule, if you'd like to reexamine it. Each index of gTheString contains a different set of characters obtained by typing with or without various modifiers pressed (Shift, Option, etc.). So for each step through the i loop, we use a different index of gTheString.

Because we're going to be drawing letter-by-letter, we need to step through each character in gTheString. So we do that with another loop, j. For each letter, we first draw (using defaultFont) the standard letter enclosed in parenthesis. Note that after every letter we advance the value of x (x and y are basically our cursor point, the coordinates of where we are drawing, with x being the horizontal direction and y the vertical).

Then we have an interesting line of code: if j / 2 = j \ 2 then. What does that mean? Well, the / operator divides, of course. So does the \ operator: but it does an integer divide, meaning that it always returns a whole number, never a fraction. By comparing the two divide-by-two operations, we can easily tell if j is an odd or even number. If j is an odd number, like 5, the two operations won't equal (since 5 / 2 is 2.5 and 5 \ 2 is 2). So the code after this if statement will only be executed if j is an even number!

And what does that code do? We'll, it draws a horizontal gray box. The box is as tall as a line of text and as wide as one column. That's it. The effect of this will be to put a horizontal light gray line across every other line of text, making the grid of letters much easier to read (see the sample image at the end of this article).

Next, we get ready to draw the large character in the user's font choice. We set our font and font size, and then we try to convert our text to the proper encoding. I say try, because I found that in REALbasic 4 tcon would always equal nil (the tcon object failed to be created by our getTextConvert command), while in REALbasic 4.5, it would be a valid object. Obviously there's some difference in how the text encoding stuff works between 4 and 4.5. But in REALbasic 4 we don't experience the font substitution problems we do in 4.5, so all we have to do is only convert the text if tcon is a valid object. In RB 4 (or any time the tcon object isn't there), the program will just use the text as it is without any conversion.

Finally, we have our code that actually draws the character in the large font. Note that we have staggered it: on even lines the letter appears 36 points to the right. If it's bigger than the height of our line, that's okay, since there's plenty of room above and below it.

Our last line is to add 114 (one column width) to x. You'll see that at the start of the i loop, y is reset to 48, the top margin of the column. That moves our cursor over to the right one column, and back at the top of the page ready to draw the next column.

On subsequent trips through the loop, the entire process is repeated, but each time a different set of letters is used (each of the four gTheString elements).

And that's it! FontPrinter is now done and should work for you. You should end up with a preview window that looks something like this (using Zapf Dingbats):

If you hit print, the same page should be produced by your printer.

Enjoy, and I hope this was a helpful tutorial. Feel free to expand on it. You could make Print Preview support multiple pages, and you could even add a feature where FontPrinter prints out a page for every installed font. Let me know how you get along improving the program.

If you would like the complete REALbasic project file for this week's tutorial (including resources), you may download it here.

Next Week

A mini-review of REALbasic 4.5.

Letters

Our letter this week is from Paul, who has a quick tip about a potential problem in FontPrinter under Mac OS X 10.2:

Hi Marc, a quick email...

10.2 does not like pictures of 8-bit depth. I discovered this info from the RB Mailing list.

When I tried your FontPrinter app, the preview window -- which should show 'this is a test' -- shows nothing. Changing the depth to 16 in the printInit method fixes this.

Thought you should know! Thanks for the first issue of RBD too, and excellent publication!!

A column suggestion? Some comprehensive Print tutorials and examples I think!!

Regards, Paul

Thanks for the info, Paul! I, sadly, do not yet have my copy of Jaguar. I pre-ordered it but it has yet to arrive. I'm not sure why Jaguar wouldn't like 8-bit depth pictures, but that's good to know. I only chose 8-bit to make it use less memory, but under Mac OS X that isn't an issue anyway.

The line to change, if you're wondering, is in the printIt method. The old line:

  
p = newPicture(thePrinter.pageWidth, thePrinter.pageHeight, 8)

The new line:

  
p = newPicture(thePrinter.pageWidth, thePrinter.pageHeight, 16)

That should work fine, now.


About the Column
REALbasic University is a weekly instructional column on programming with REALbasic and is brought to you by REALbasic Developer, the magazine for REALbasic programmers.

Each week we answer select reader questions, and we're always open to ideas for future columns. Send your questions to . (Keep your questions simple and specific. General queries like "How do I write my own web browser?" will be neglected.) Your question won't be answered immediately, but will be answered in a future column. (If you don't want your correspondence published, just be sure to indicate that when you write. Otherwise it's fair game.)

About the Author
is an author, philosopher, graphic designer, photographer, film director, soccer fanatic, and programmer (among other things). He writes for MacOpinion, runs his own software company, Stone Table Software, which sells the revolutionary Z-Write word processor, and is Publisher and Editor of REALbasic Developer. He lives in Northern California with his cats, Mischief and Mayhem, and is rapidly running out of free time.

See the REALbasic University Archives


REALbasic University contents ©2001-2004 by Marc Zeedar and REALbasic Developer. All Rights Reserved.

Email This Article - Comment On This Article

.

Reader Specials

Server Racks Online:
Apple Xserve CompatibleServer Racks and Universal Network Racks
42U KVM Switch Solutions:
High-End Mac and Multi-Platform KVM Matrix switching solutions!
Digital Camera Online:
Great prices on Digital Cameras and accessories!
KVM Switches Online:
Great prices on Mac KVM Switches from the leading manufacturers!
LCD Monitors Online:
Great prices on LCD Monitors from the leading manufacturers!
LCD Projectors Online:
Shop online for LCD Projectors from the leading manufacturers!
USB 2.0 Online:
Great prices on USB 2.0 products from the leading manufacturers

Serious Business Software:
Accounting, Sales, Inventory, CRM, Shipping, Payroll & more!

KVM Switch solutions for MACs:
DAXTEN is a KVM switch, KVM extender and monitor splitter specialist for PC, SUN and MAC applications from name brand manufacturers - offices worldwide.

The "Think Different Store: The iPod Accessories Store - iPod cases, iPod mini, iPod photo, speakers, itrip, inMotion, Soundstage and all other iPod accessories

Earn Cash with the ThinkDifferent Store Affiliates Program

Need A Web Site?
Applelinks Web Hosting Starting at 19.95 a Month

iTunes_RGB_9mm

.

iTunes_RGB_9mm

Cool Mac Gear


iPod 1G-2G
iPod 3G
iPod 4G
iPod Mini
PowerBook-iBook
Keyboard Skins
Garageband