xbfont.icn: Procedures for X font selection

procedure BestFont:        generate best X fonts
procedure RankFonts:       generate scores for X fonts

link xbfont
May 2, 2001; Gregg M. Townsend
Requires: Version 9 graphics under Unix
This file is in the public domain.

BestFont(W, s, ...) generates X-windows font names matching a
given specification, beginning with the closest match.  The
ranking algorithm is similar to that used in Font() but it is
not identical.
____________________________________________________________

   BestFont(window, spec, ...) returns the name of whichever available
X-Windows font most closely matches the given specification.  Note that
matching is done using a slightly different algorithm from that of the
Icon runtime system; this procedure preceded Icon's font selection
implementation and served as a prototype.

   The font specification is one or more strings containing whitespace-
or comma-separated tokens.  Tokens are case-insensitive.  There are
three kinds of tokens.
   A token having the form of an integer specifies the desired "pixel
size" (height).  If no size is included, a target size of 14 is used.
   An unrecognized token is taken as a substring of the desired X font
name.  Family names, weights, and other such factors are specified this
way.
   Certain tokens are recognized and handled specially:
      m  mono  monospaced
      p  prop  proportional
      r  roman
      i  italic
      o  oblique
      s  sans  sans-serif  sansserif
These are turned into search strings of a particular form.  For example,
"roman" and "r" specify the search string "-r-".

   The "best match" to a given specification is calculated by reviewing
all the available fonts, assigning a score to each, then choosing the
one with the highest value.  There are several aspects of scoring.
   Size is the most important factor.  A tuned font of the correct size
gets the maximum score.  Nearby sizes receive partial credit, with
an undersized font preferred over an oversized font.  Scalable fonts
are also recognized, but a tuned font of the correct or nearly-correct
size gets a higher score.
   Each successful substring match increases the score, whether the
test string comes from an unrecognized token or a special keyword.
Earlier tokens receive slightly more weight than later ones.
   All tokens need not match.  The string "lucida gill sans 18"
is perfectly reasonable; it specifies a preference for Lucida Sans
over Gill Sans by the position of the tokens, but will match either.
   Ties are broken by giving slight preferences for normal weight,
no slant, normal width, and ASCII ("iso8859") encoding.  A slight
penalty is assessed for "typewriter" fonts.  Oblique fonts receive
partial credit for matching "italic" requests, and vice versa.
   The scoring function can be altered by assigning values to certain
global variables.  See XBF_defaults() for a commented list of these.

   For a scalable font, the returned value is a string specifying an
instance of the font scaled to the target size.  For large sizes, the
scaling time may be noticeable when the font is used.

   BestFont() is actually a generator that produces the entire list
of available fonts in order of preference.  RankFonts(w, spec, ...)
is similar to BestFont but produces a sequence of two-element records,
where result.str is the font name and result.val is its score.  For
either of these, a list of X font names can be passed instead of a
window.

   There is some startup cost the first time BestFont is called; it
opens a pipe to the "xlsfonts" program and reads the output.  Results
are cached, so this overhead is only incurred once.

   Examples:
      Font(w, BestFont(w, "times bold italic 20"))
      s := BestFont(w, size, family, "italic")

Source code | Program Library Page | Icon Home Page