The XFont Class


Introduction

This article describes the XFont class, an implementation of the previously described XFont project.
To recall: this project allows home brew scalable fonts allowing for a varriety of styles.
Coding is very effective. A complete font needs less than 30KBytes, including the styles.
Drawing of characters is fast: typical over 10000 a second when the character height is 20 or less.

To implement the XFont in applications, a class is build around it.
Also an exerciser program is designed to test the properties and methods of this new class.
This article also describes the exerciser.

The XFont writes characters in a XBitmap. This is a TBitmap component with some extra's.
The pixelformat is always 32 bits.
The XBitmap class is described here.
But with only small modifications a "normal" TBitmap may be used.

XFont class options

    - scalable characters, vertical pixel size from 10 to 96. Above 96 a loss of quality becomes evident.
    - selectable font styles
      - bold
      - italic
      - wide
      - background color
      - underline
    - soft edges
    - 4 drawing levels encoded in pen and in brush color
    - clipping rectangle : no screen pixels can be altered outside this rectangle
    - modification rectangle (read only) : the modified (bitmap) area of the last write operation
Since XFont methods write in memory, a draw or copyrect operation is necessary to show the result of a write
on the screen.

styles

Below I show some results. This screen shot is from the exerciser program.

drawing levels

The levels are 0 (highest) to 3 (lowest).
The level is coded as bits 0,1 of the blue color in a 32bit pixelformat.
The idea is to have the effect of drawing into 1 of 4 planes, were pixels in the first plane obscure
pixels in the planes behind.
During a draw operation, a pixel having a higher level cannot be overwritten by a lower level color.
This enables the dominance of text over graphics information as well as grids over background (brush) colors
regardless the sequence of the draw operations.
When no colorlevels are required, give all colors the same level.
Picture below shows some effects.
First the ellips is written using a pen level of 0 and a brush level of 3.
Then the text is written using a pen level of 1.
Here the ellipse pen color is dominant over the text color.

Clipping rectangle

In some cases it is desired to limit a text to a certain rectangle.
Editfields are a well known example.
See the picture below for an example
First a line of H characters is written.
Then a cliprect is selected and the same line of H characters is written somewhat above the previous line.

Font height

The size of the character is defined by the font height.
Picture below shows some different font heights.
Remember that character images are coded as horizontal stripes in a 96 * 96 pixel image.
The codes also allow for pixelalignment to avoid aliasing.
The requested font height is obtained by drawing with the scale needed.

Modification rectangle

This is a read only property showing the area modified during the last character draw operation.
Copy this rectangle to the canvas of a paintbox to make the character visible.
More areas may be combined by the unirect(..,..) function if a canvas needs to be updated after
drawing multiple characters.

Drawing and screen location

A character is written at certain (x,y) screen coordinates, where the left top of the character
coincides with pixel (x,y).
After the draw operation the x value is incremented by the width of the character.
Horizontal spacing is part of the character code and no extra action is necessary.
The vertical size is always exactly the height selected.
The character width varies with the specific character and the style selected.

Font installation

The font drawing codes are stored as bitmap pixels in a TImage component which is part of the application .
Before writing a character, the font must be installed by calling the install method.
Installation amounts to saving font information, it's name, and a pointer to the bitmap memory
location in an internal table. Fonts are addressed by a number, not by name.

The first installed font is number 1, and so on.

Font styles

A font style is represented by a bit. Fontstyle is not a set.
Definition of font styles
          xfBold       = $1;
          xfItalic     = $2;
          xfWide       = $4;
          xfBrush      = $8;
          xfUnderline  = $10;
      
Use the "or" operator to combine font styles.

XFont properties

    textmap : TXbitmap write setTextmap;define the XBitmap used
    posX : smallint read FposX write FposX;
    posY : smallint read FposY write FposY;
    set (x,y) coordinates for output
    maxfont : byte read FmaxFont;the highest font number installed
    cliprect : Trect read Fcliprect write Fcliprect;select or read the clipping rectangle
    modrect : Trect read Fmodrect;property cliprect : Trect read Fcliprect write Fcliprect;read the modified rectangle
    FontHeight : byte read FHeight write setFontHeight;select or read the font height in pixels
    FontStyle : byte read FStyle write setFontStyle;select or read the font style
    penColor : DWORD read getFGcolor write setFGcolor;set or read the color of the pen. Includes level in blue bits 0,1
    brushColor : DWORD read getBGcolor write setBGcolor;set or read the color of the brush. Includes level in blue bits 0,1
    PenLevel : byte read FPenlevel write setpenlevel;set or read the pen level. Codes the level into the pen color.
    Brushlevel : byte read FBrushlevel write setBrushlevel;set or read the level of the brush. Codes the level into the brush color.

XFont methods

    constructor create;myXfont := XFont.create;//create an XFont component in run time
    function install(im : Timage) : byte;//result = fontNr <> 0 if OK. Font number is sequential.
    procedure charOut(ch : byte);;//write character with code ch at (posx,posY). Increase posX after drawing
    function fontprops : TXfontprops;//read the font properties
    function charWidth(ch : byte) : byte;//get the width of the character having code ch
    function charmetrics(ch : byte) : Tcharmetrics;//get the layout of the character with code ch
Note: insert a myXFont.free statement in the destroy procedure of the main form of your application.

The TFontProps type

These values are returned by the fontprops function.
All values are relative to the design resolution (96 pixels at present).
TXFontProps = record
                name       : string;
                length     : word;       //length of fonttable DWORDS
                resolution : byte;
                driver     : byte;       //1 : stripe driver
                revision   : byte;
                baseline   : byte;
                HiTop      : byte;       //top of 'A'
                LoTop      : byte;       //top of 'a'
                PXfont     : PXFont;     //points to fontlist
               end;
namestring from the font Timage. Set during design time
length the length in DWORDS of the font table
resolution set by design (here : 96 pixels)
driver 1 (denotes the stripe driver). Future options may include other drivers.
revision revision number of the font
baseline distance from top to baseline in pixels
HiTop distance from top to top of 'A'
LoTop distance from top to top of 'a'
PXFont = TImage.bitmap.scanline[height-1] {lowest DWORD of bitmap canvas}

The Tcharmetrics type

The charmetrics function supplies specifics of a character design in the 96 pixel resolution.
So, a selected font height or style is not accounted for.
 TcharMetrics = record
                     code : byte;
                     width : byte;
                     hspace : byte;
                     top : byte;
                     bottom : byte;
                    end;
codecharacter code. If a code is not defined, 0 is returned
widththe width of the character in pixels
hspaceleft space in pixels (provides horizontal spacing
topposition of top pixel in character
bottomposition of bottom pixel in character

Notes
    - the width of a character is extended by 4 in case of a bold style.
    - the width is multiplied by 1.33 in case of a w i d e style.
    - for an italic style, the top pixel x positions are multiplied by 1.25, bottom pixels remain in place
    - character width is not affected by an italic style.
    - append a space ' ' after the last italic character for proper background filling
This concludes the description of the XFont class.
Click at the download (lightning) icon at the top of this page to download the xfontclass program.

Please refer to the source code for details.
Click [ here ] to download the complete Delphi-7 project.

Notes:
1.
the project also supplies the XBitmap class in a separate unit.
2.
the project uses the davColorpicker and davArrayButton components which are described
and made available at this website.
3.
The xfontclass project includes the XBitmap class, where a new function was added:
    function colorlevel(clr : dword; level : byte) : DWORD;
This function returns color clr with the encoded level.
Colors are in Windows "bb-gg-rr" format.
Use the function swapcolor(c : DWORD) : DWORD to convert the Windows format to the pf32 bit internal
bitmap format "rr-gg-bb" and vice versa.

Keep in mind: selecting a color also changes the level, because the levek is coded into the color.
setting a level also modifies a previously selected color.
The XBitmap class was changed to be compatible with the xfont class in this respect.
4.
Some caution is required: the xfont class has not yet been implemented in a real application.
Some characters need slight retuning: sometimes the scaling produces the effect of a maladjusted typewriter.
The cause is different Y-slide definitions per character.

The xfontclass exerciser

Unit1 of the project supplies buttons and procedures to test the XFont options.
After starting the program, click on the left top "install" button to install the (3) fonts.

Enter text and press "show chars" to display the text on the screen at (x,y) selected.
The "clear" button clears the screen and sets the cliprect to the paintbox boundaries.

The "graph1" and "graph2" buttons paint an ellipse or grid with the selected colors and levels.
The "BG1" and "BG2" buttons are for future options.

The "showProps" button displays the properties of the selected font number.
The "metrics" button displays the layout of the selected character code.