Managing Multiple Fonts
In PowerBASIC, a font is defined in this fashion:
FONT NEW fontname$ [,points!, style&, charset&, pitch&, escapement&] TO FontHdl&
Point sizes can be fractional — hence the single-precision designation. Style is a bit array of the following characteristics:
0 = Normal 2 = Italic 8 = Strikeout 1 = Bold 4 = Underline 16 = Leading
Any descriptor that is omitted or unspecified is set to the system default. I personally have no use for the charset or pitch attributes, and it is possible that you don't either. So if one is not planning to print text at an angle, then the last three parameters can be ignored. My suggested setup does just that, concerning itself only with points and style. I also have no use whatever for fractional point sizes; so that parameter will be an integer. In fact, fractional values are unavailable with this method for an unusual reason, as you will see.
The standard syntax for setting up a printer font is:
XPRINT SET FONT FontHndl&
That seems easy enough, but what is the value of FontHndl? You will need to know it later. Did you write down that number somewhere? Did you create a little lookup table in your comments containing references for a couple dozen fonts? There is an easier, albeit unorthodox, way to handle (sic) this matter.
The plan is to create an array of font handles. Most of the array elements will remain unused, but so what? These days, memory allocation is not an issue, and the array will be pretty small in any case:
DIM FNT(5,36,3) AS GLOBAL LONG
The dimensions are sized at least to the following values:
(1) number of different font faces to be referenced
(2) point size of the largest font to be used
(3) maximum style-value assigned to any font
This sample program will utilize 5 font-face specifications, up to
36-point size, and up to style=3 (bold italic).
Firstly, some universally accessible font names must be initialized:
GLOBAL Arial&, Courier&, Times&, NameFont&, EventFont&
If you prefer to set them up as equates, that's fine; but the code reads better without them.
Ten potentially different fonts are to be used in the program. For example
purposes, two variable fonts will have names to be determined in
perhaps from an INI file.
FTname$ = "ms sans serif"
FTevent$ = "comic sans ms"
Those type faces might or might not match other designated font specs; it doesn't matter.
'[Name, Point size, Style: 0=normal 1=bold 2=italic]
'IN: FTname$, FTevent$
Arial=1: Courier=2: Times=3: NameFont=4: EventFont=5
FONT NEW "Arial",10,0 TO FNT(Arial,10,0)
FONT NEW "Arial",10,1 TO FNT(Arial,10,1)
FONT NEW "Arial",36,3 TO FNT(Arial,36,3)
FONT NEW "Courier New",10,0 TO FNT(Courier,10,0)
FONT NEW "Courier New",10,1 TO FNT(Courier,10,1)
FONT NEW "Courier New",12,0 TO FNT(Courier,12,0)
FONT NEW "Courier New",12,1 TO FNT(Courier,12,1)
FONT NEW "Times New Roman",16,0 TO FNT(Times,16,0)
FONT NEW FTname$,12,0 TO FNT(NameFont,12,0)
FONT NEW FTevent$,12,0 TO FNT(EventFont,12,0)
That's right — the array locations of the font handles are determined by
the point sizes and style attributes themselves! Only 10 of 888 elements
actually will be used; but who cares? This arrangement will prove
Naturally, no new idea is complete without a nifty new shortcut:
MACRO SetFont(A,B,C)= XPRINT SET FONT FNT(A,B,C)
Now we're ready.
To use Courier New, 10 points, boldface:
SetFont(courier,10,1) XPRINT "Able was I ere I saw Elba."
It doesn't get any tidier than that, and little memory work is required. To print the event name:
'uses whatever typeface was specified by FTevent$
XPRINT "Western States 100"
Let's try one more — a headline centered at the top of the page:
'use default printer, 8×10½ palette, grid in inches
A$="DEWEY DEFEATS TRUMAN!"
'get text width for specified font
'center-align text with a half-inch top margin
Oops! Using five different macros rendered that module quite elegant,
but it didn't work properly in this case. Why? In our sample setup, a font
handle had been initialized for Style=3, but not for Style=2.
That's a different font. Unless that oversight is corrected, output probably
would be in PB's fallback
format — Courier New with no attributes.
Angled printing can be accommodated by adding one dimension to the array of font handles:
DIM FNT(5,36,3,3) AS GLOBAL LONG
The font-setting macro must be adjusted as well:
MACRO SetFont(A,B,C,D)= XPRINT SET FONT FNT(A,B,C,D)
A printing direction is defined in tenths of degrees of counter-clockwise rotation;
so a value of 900 represents text rotated 90 degrees and is readable from the
right-hand side of the page. If the angles to be used always are multiples
of 90 degrees from normal, it is useful to define them using compass directions:
'----- Global vars or Equates -----
Arial=1: Courier=2: Times=3
South=0: East=1: North=2: West=3
'[Name, Point size, Style, Angle: 0=S,1=E,2=N,3=W]
FONT NEW "Arial",10,0,0,0,0 TO FNT(arial,10,0,0)
FONT NEW "Arial",10,0,0,0,900 TO FNT(arial,10,0,1)
FONT NEW "Arial",10,0,0,0,1800 TO FNT(arial,10,0,2)
FONT NEW "Arial",10,0,0,0,2700 TO FNT(arial,10,0,3)
That module enables the 'Normal 10-point Arial' font to be printed in a compass direction of one's choice. To rotate some text 180 degrees:
SetFont(arial,10,0,north) XPRINT "This text is upside-down."
Be aware that text always is printed first-character to
as normal, yet in the context of its actual angle; so West-oriented
type will print from the page-top down, North-facing text prints
right to left, etcetera. The page coordinates never change, though.
Names also could be established for the style parameter, I suppose; then one wouldn't have to think at all:
Normal=0: Bold=1: Italic=2: Bolditalic=3: ...
Code doesn't come any more readable than that! Of course, one still can
choose to set up a new font the hard way; also, a useful tactic could be to load
FNT() with every font definition that might ever be desired,
and be done with it. That is the whole idea, after all —
to make life easier on the programmer.