Fonts R Us!

From EDM2
Jump to: navigation, search

by Kelvin R. Lawrence

OS/2 2.1 comes with support for, and provides a selection of, both image (bitmap) fonts and Adobe type 1 outline fonts. In this article, we look at some of the considerations that you should make when using these fonts in a Presentation Manager application. We will take an overall look at the issues of dealing with fonts and explain some of the most commonly used terminology.

Plan Ahead!

Before adding font support to an application, stop and consider what type of application you are producing. You must decide whether the application is a screen-only application or if it will support other devices such as printers and plotters. This decision will affect the way that you write font-handling code in your application. Also, if your application demands WYSIWYG (what-you-see-is-what-you-get) support, then it should be using the outline fonts, which are much more flexible than image fonts.

System Image vs. Outline Fonts - Which to Use?

The image fonts that come as part of the OS/2 system should, ideally, only be used for displaying text on the screen. They consist of a set of fixed point sizes that are not scaleable and, thus, have limited flexibility. Image fonts cannot be sheared, sized, and rotated in the way that outline fonts can. For applications that just want to write to the screen they might be ideal; however, outline fonts are far better suited for more general uses.

The outline fonts, on the other hand. are far more flexible and can be used in a wide variety of ways. You can use them effectively both on the screen and hardcopy devices because they can be sized accurately with graphics, such that words and pictures appear in the same scale. In addition, they have more flexible uses such as producing outlines, constructing fills, using paths, and constructing clip paths. Outline fonts also can be transformed just like any other graphical primitives; they can be accurately rotated, scaled, and sheared.

Some General Font and Typeface Terminology

When discussing fonts, and typefaces in general, it is useful to define some of the common terminology. This terminology is not unique to the computer industry; almost all of the basic font-related terminology comes from the printing and typesetting world. You can open almost any book in the art section of your local bookstore that deals with typesetting and find a good explanation of the basic terms. In fact, I would recommend people new to working with fonts do just that.

The Font Metrics Structure

Given this diagram, we can look at the font metrics (FONTMETRICS) structure as used by the GpiQueryFonts function. This structure definition can be found in the OS2DEF.H header file that is part of the Developer's Toolkit for OS/2. As you can see, this structure contains all of the relevant information, or metrics. about a particular font.

typedef struct _FONTMETRICS     /* fm */
{
  CHAR    szFamilyname[FACESIZE];
  CHAR    szFacename[FACESIZE];
  USHORT  idRegistry;
  USHORT  usCodePage;
  LONG    lEmHeight;
  LONG    lXHeight;
  LONG    lMaxAscender;
  LONG    lMaxDescender;
  LONG    lLowerCaseAscent;
  LONG    lLowerCaseDescent;
  LONG    lInternalLeading;
  LONG    lExternalLeading;
  LONG    lAveCharWidth;
  LONG    lMaxCharInc;
  LONG    lEmInc;
  LONG    lMaxBaselineExt;
  SHORT   sCharSlope;
  SHORT   sInlineDir;
  SHORT   sCharRot;
  USHORT  usWeightClass;
  USHORT  usWidthClass;
  SHORT   sXDeviceRes;
  SHORT   sYDeviceRes;
  SHORT   sFirstChar;
  SHORT   sLastChar;
  SHORT   sDefaultChar;
  SHORT   sBreakChar;
  SHORT   sNominalPointSize;
  SHORT   sMinimumPointSize;
  SHORT   sMaximumPointSize;
  USHORT  fsType;
  USHORT  fsDefn;
  USHORT  fsSelection;
  USHORT  fsCapabilities;
  LONG    lSubscriptXSize;
  LONG    lSubscriptYSize;
  LONG    lSubscriptXOffset;
  LONG    lSubscriptYOffset;
  LONG    lSuperscriptXSize;
  LONG    lSuperscriptYSize;
  LONG    lSuperscriptXOffset;
  LONG    lSuperscriptYOffset;
  LONG    lUnderscoreSize;
  LONG    lUnderscorePosition;
  LONG    lStrikeoutSize;
  LONG    lStrikeoutPosition;
  SHORT   sKerningPairs;
  SHORT   sFamilyClass;
  LONG    lMatch;
  LONG    FamilyNameAtom;
  LONG    FaceNameAtom;
  PANOSE  panose;
} FONTMETRICS;

Figure 1. Font Metrics

So, What Fonts Do I Have?

To determine the fonts that currently are loaded in the system, an application can call the GpiQueryFonts function. Use this function to query how many fonts are available and to retrieve the metrics for some, or all, of these fonts. The function, MyQueryFonts, calculates how many fonts are loaded in the system, allocates space to store the font metrics, and retrieves the metrics. An application can query information about just the public (that is, system-wide) fonts or private fonts (that is, local to the application) or both. Do this by using one or both of the QF_PUBLIC and QF_PRIVATE flags on the call.

VOID MyQueryFonts( HWND hwnd )
{
  LONG lNum;
  LONG lRem;
  LONG lReq=0;
  PFONTMETRICS pfm;
  HPS hps;
  // Get a presentation space for the window provided
  hps = WinGetPS( hwnd );
  // Query how many fonts are available to us at this time
  lNum = GpiQueryFonts( hps
                      , QF_PUBLIC | QF_PRIVATE
                      , NULL
                      , &lReq
                      , 0L
                      , NULL
                      );
  // Allocate space to store the fontmetrics structures
  pfm = (PFONTMETRICS) malloc( sizeof(FONTMETRICS) *lNum );
  // Now query the metrics structures
  lRem = GpiQueryFonts( hps
                      , QF_PUBLIC | QF_PRIVATE
                      , NULL
                      , &lNum
                      , sizeof(FONTMETRICS)
                      , pfm
                      );
  // Free resources
  free( pfm );
  WinReleasePS( hps );
}

Sample Code 1. My Query Fonts function

Having queried the list of available fonts, the application can present the user with a list and have them choose a font to use for a particular task. However, as the following section indicates, OS/2 provides a standard dialog interface for choosing fonts that all applications should use. This lets each program offer a consistent interface for selecting fonts. More importantly than using the metric information to generate lists of the available fonts in the system, applications can use the information in the FONTMETRICS structure to calculate such things as line and character spacing.

Another Structure

The font attributes (FATTRS) structure as used by the GpiCreateLogFont and the WinFontDlg functions display the font selection dialog. The FATTRS structure also is defined in the OS2DEF.H header file.

typedef struct _FATTRS            /* fat */
{
  USHORT  usRecordLength;
  USHORT  fsSelection;
  LONG    lMatch;
  CHAR    szFacename[FACESIZE];
  USHORT  idRegistry;
  USHORT  usCodePage;
  LONG    lMaxBaselineExt;
  LONG    lAveCharWidth;
  USHORT  fsType;
  USHORT  fsFontUse;
} FATTRS;

Figure 2. The Font Attributes structure

A Consistent Dialog

Offering a list of fonts to choose from is something that many Presentation Manager applications must do. Rather than have each application programmer invent a new set of dialogs for doing this, we provide a standard interface as part of the base system. Use the WinFontDlg function to display the dialog. Although can be a very complex function (at first look), it is actually very flexible. The best way to get familiar with the power offered by the font dialog is to experiment with it in your applications.

However, at a minimum, the function DisplayFontDialog shows how to set up a call to WinFontDlg having specified only a few of the many parameters that are available. The WinFontDlg call expects to receive a FONTDLG structure as one of its parameters. This is a large structure; therefore, only those parts of the structure needed in the example are filled in by the DisplayFontDlg function.

  typedef struct _FONTDLG     /* fntdlg */
  {
     ULONG   cbSize;                /* sizeof(FONTDLG)                 */
     HPS     hpsScreen;             /* Screen presentation space       */
     HPS     hpsPrinter;            /* Printer presentation space      */
     PSZ     pszTitle;              /* Application supplied title      */
     PSZ     pszPreview;            /* String to print in preview wndw */
     PSZ     pszPtSizeList;         /* Application provided size list  */
     PFNWP   pfnDlgProc;            /* Dialog subclass procedure       */
     PSZ     pszFamilyname;         /* Family name of font             */
     FIXED   fxPointSize;           /* Point size the user selected    */
     ULONG   fl;                    /* FNTS_* flags - dialog styles    */
     ULONG   flFlags;               /* FNTF_* state flags              */
     ULONG   flType;                /* Font type option bits           */
     ULONG   flTypeMask;            /* Mask of which font types to use */
     ULONG   flStyle;               /* The selected style bits         */
     ULONG   flStyleMask;           /* Mask of which style bits to use */
     LONG    clrFore;               /* Selected foreground color       */
     LONG    clrBack;               /* Selected background color       */
     ULONG   ulUser;                /* Blank field for application     */
     LONG    lReturn;               /* Return Value of the Dialog      */
     LONG    lSRC;                  /* System return code.             */
     LONG    lEmHeight;             /* Em height of the current font   */
     LONG    lXHeight;              /* X height of the current font    */
     LONG    lExternalLeading;      /* External Leading of font        */
     HMODULE hMod;                  /* Module to load custom template  */
     FATTRS  fAttrs;                /* Font attribute structure        */
     SHORT   sNominalPointSize;     /* Nominal Point Size of font      */
     USHORT  usWeight;              /* The boldness of the font        */
     USHORT  usWidth;               /* The width of the font           */
     SHORT   x;                     /* X coordinate of the dialog      */
     SHORT   y;                     /* Y coordinate of the dialog      */
     USHORT  usDlgId;               /* ID of a custom dialog template  */
     USHORT  usFamilyBufLen;        /* Length of family buffer provided*/
     USHORT  usReserved;            /* reserved                        */
  } FONTDLG;

Figure 3. The Font Dialog structure All of the flags and the FONTDLG structure are defined in the PMSTDDLG.H header file, which is part of the Developer's Toolkit for OS/2 2.1. The following function displays the font dialog:

VOID DisplayFontDlg( HWND hwnd )
{
 HPS hps;
 FONTDLG fd;
 // Set the title the dialog will use
 CHAR pszTitle[17] = "Font Dialog Test";
 // Reserve storage for the fonts name
 CHAR pszFamilyName[FACESIZE] = "\0";
 // Initialize the font dialog structure.
 memset( &fd, 0, sizeof( FONTDLG ));
 hps = WinGetPS( hwnd );
 fd.hpsScreen = hps;
 fd.cbSize    = sizeof( FONTDLG );
 fd.pszFamilyname =  pszFamilyName ;
 fd.pszTitle = pszTitle;
 fd.usFamilyBufLen = FACESIZE;
 fd.fxPointSize = (FIXED)0;
 fd.clrFore = CLR_BLACK;
 fd.clrBack = CLR_WHITE;
 fd.pszPreview = "Sample Text";
 fd.fl = FNTS_CENTER;
 WinFontDlg( HWND_DESKTOP, hwnd, &fd );
 WinReleasePS( hps );
}

Sample Code 2. The DisplayFontDlg() function

Upon return from a call to WinFontDlg, the fAttrs field of the font dialog structure contains the font attributes for the font that was selected by the user. These attributes, then, can be passed to the GpiCreateLogFont function to create a logical font representing the font chosen by the user.

Creating a Logical Font and Displaying Text

Having established the font attributes structure for the font that we wish to display text in, before we can actually display the text, create a logical font for the selected font and establish that font as the current character set for our presentation s pace. The function CreateFontAndDisplayIt creates a logical font, using the fAttrs structure returned from the call to WinFontDlg and displays the string "Hello!" using that font.

VOID CreateFontAndDisplayIt( HWND hwnd, PFATTRS pfAttrs )
{
#define MYCHARSET 99L
HPS hps = WinGetPS( hwnd );
SIZEF box;
// Create a logical font for the FATTRS passed in. Use MYCHARSET as
// the character set number for this logical font.
GpiCreateLogFont( hps, NULL, MYCHARSET, pfAttrs );
// Select MYCHARSET as the current one for thhis Presentation Space
GpiSetCharSet( hps, MYCHARSET );
// If the user had slected an outline font then, as a rough approximation
// set the character box to the maximum baseline extent so that the text
// will be roughly in the size requested. Note that bitmap fonts are of
// size and we don't have to explicitly size them. Note this is an inaccurate
// sizing algorithm.
if ( pfAttrs->fsFontUse & FATTR_FONTUSE_OUTLINE )
{
  box.cx = box.cy = pfAttrs->lMaxBaselineExt << 16;
  GpiSetCharBox( hps, &box );
}
// Draw a text string at the current position, using our new logical font
GpiCharString( hps, 6L,  "Hello!" );
WinReleasePS( hps );
}

Sample Code 3. A function to create a font, then display it.

If the Font Fits...

The CreateFontAndDisplayIt function uses a somewhat inaccurate calculation to approximate the size that the character box should be set to if the user selects an outline font. For much more exact sizing of an outline font for display on a specific device, you can use the following algorithm:

  1. Choose the point size required
  2. Apply the following formula:
    • pt = selected point size
    • dev = device graphics resolution in pels per meter
    • mi = 0.0254 (meters/inch)
    • ip = 0.9961/72 (inches/point)
    • character box = pt * dev * mi * ip

Then, use the GpiSetCharBox function to set the character box accordingly.

The formula uses the following basic rules from the typesetting world:

  • 12 points = 1 pica
  • 6 picas = 1 inch (actually 0.9961 inches)
  • 72 points = 1 inch
  • 1 inch = 2.54 cm
  • 1 inch = 0.0254 m

And, That's Not All!

In this article, we have only touched on some of the many features that OS/2 Presentation Manager provides for manipulating and displaying text characters in different fonts. As always, the best way to get familiar with these interfaces is to try them out in your own programs. Complete sample programs can be found on your accompanying Developer Connection for OS/2 CD-ROM.

In a future article, we will look at some more complex ways to use fonts in your applications.

Reprint Courtesy of International Business Machines Corporation, © International Business Machines Corporation