Re: Physical and logical fonts
Roedy Green wrote:
On Tue, 8 Jan 2008 09:30:29 -0800 (PST), failure_to@yahoo.co.uk wrote,
quoted or indirectly quoted someone who said :
Say we have a font that is able to display all ascii characters.
We also have two different 7 bit encodings EN_1 and EN_2. Both are
able to display all ascii characters. But they have different code
points for individual characters ( for example in EN_1 code point for
character A may be 65, while in EN_2 codepoint for A may be 100 ).
Java just uses the Unicode encoding and ignores the rest. Read up on
the OpenType format to understand how you can have multiple encodings.
see http://mindprod.com/jgloss/opentype.html
As usual Roedy has answered your questions. But I'd like to take a
stab at drawing a big picture for you:
The term "font" is vague and different people use it in different ways.
For now assume a font an array of tiny graphics created by an artist to
share a particular look, and to "map" to letters, digits, and other
characters. (For the real story search the Internet and visit
Unicode.org, and see the Javadoc API comments for java.awt.Font.)
Type designers knew some things about how humans read text, and
devised "serif" fonts which are letter shapes composed of lines
of varying thickness and small extra bits on the ends of the
strokes. Text of such fonts is much easier to read and pretty
much all books and magazines use serif fonts for body text.
(As should you!)
Text without the extra bits, and often drawn with lines of constant
thickness, are called sans-serif ("sans" is French for "without")
and are used for attention-grabbing such as for headings and captions.
In the early computer era usually a single screen font was built into
terminals. Printers were based on daisy-wheel or line-printer
technology, again that supported a single font. These early
computer screens and printers were limited to drawing
each character in the same sized rectangular block. Such fonts
are called mono-spaced singe all characters take up the same amount
of horizontal space. This leads to an un-even appearance as fat
letters such as 'm' take the same space as skinny letters such as
'i'. As the technology grew more sophisticated computers and printers
became capable of displaying traditional fonts called "proportional".
In these fonts the space between the characters is the same, giving
the text an even appearance. (Are you reading this in a mono-spaced
or proportional font? Look at this to decide: "MMMMMMllllll".)
So a font can be either proportional or mono-spaced. It can have
serifs or be sans-serif. That's four possibilities, but fonts
can have other attributes such as heaviness of the strokes
(bold) or if the letters are straight (roman) or slanted
(italics).
[
Early Unix systems used "X Window" fonts that were named for
each of 14 possible font attributes. You could find a bold,
12 point (one point is roughly 1/72 of an inch) font by doing
a directory listing for: -*-*-bold-*-*-*-12-*-*-*-*-*-*-*
which might find the font file:
-adobe-utopia-bold-r-normal--12-120-75-75-p-70-iso8859-1
Nowadays fonts have names such as "Helvetica" or "Bookman",
which is much less helpful.
]
When Java programmers set a font to use, they typically don't know
what fonts are available on the user's system. So if you guess to
use a font "Ariel" it may or may not be available. However all
home computers ship with a set of fonts standard for that platform.
So for every platform Sun supports, they picked 3 available fonts
(these are the actual fonts installed and are called "physical") and
gave them names you can use in your program. The names are called
"logical font names" since the names reflect the type of the font:
Monospaced" (and usually sans-serif but not necessarily),
"SansSerif" (a proportional font), and "Serif" (also proportional).
So in your program you can chose the system-specific mono-spaced
font for code listings, sans-serif for headings and captions, and
serif for body text. And you don't need to know the real or
"physical" name for that font.
Most home computer systems also have a distinct look and feel to
the pop-up dialog boxes and other system elements (e.g., window
titles). You can use these as well as Sun as kindly defined
the system standard font for dialog boxes as "Dialog" and
"DialogInput" logical font names, so you can make your dialogs
appear native.
Modern AWT does include classes and methods to list all available
fonts installed, so you can look for specific (physical) fonts
and use them if you wish:
import java.awt.*;
public class ShowFonts {
public static void main ( String [] args ) {
Font[] fonts = GraphicsEnvironment.getLocalGraphicsEnvironment()
.getAllFonts();
for ( int i = 0; i < fonts.length; ++i ) {
System.out.print( fonts[i].getFontName() + " : " );
System.out.print( fonts[i].getFamily() + " : " );
System.out.println( fonts[i].getName() );
}
System.out.println( "\n\n\tAvailable Fonts:\n" );
String[] names = GraphicsEnvironment.getLocalGraphicsEnvironment()
.getAvailableFontFamilyNames();
for ( int i = 0; i < names.length; ++i )
System.out.println( names[i] );
} // end of main
}
Still it may be a problem to not know the actual font used by some
logical font name, as different proportional fonts can do line breaks
in different places and mess up the carefully planned appearance of
your application or applet. For this reason the JRE ships with
a set of related fonts called "Lucida". These physical fonts are
available in all Sun JREs and include mono-spaced, Sans-Serif, and
Serif versions. (Look in .../jre/lib/fonts on your system.)
(I don't think Roedy mentioned this in his answer; Roday, as
long as you're updating your font page anyway, remember to
mention this.)
In short Sun as identified three of the fonts on each platform
and given them logical names. You can use one of these three,
the platform-specific dialog fonts (making five logical font
names in all), or pick some actual font name (a physical font)
and hope it is available. It will be if you pick Lucida and
you have a Sun JRE.
As to your last question, remember each font is a collection,
an array or "vector" of graphics known as "glyphs". (It's more
that that really.) Each glyph is identified by a number. For
example a capital "A" glyph in any font that has such a glyph,
is identified by the number 65. Of course anyone can make
their own collection of glyphs as a font, and identify any
glyph with any number. For Java and most software today,
the mapping of numbers to glyphs is the one defined by the
Unicode standard.
Unicode had defined numbers for many thousands of glyphs and it
is unlikely you have a single font file that has every glyph
defined by Unicode. This can be a problem when using logical
font names, since you don't always know if the actual font
has a glyph for all the symbols, arrows, smiley faces, Greek
letters, math and engineering symbols, etc., that you might want
to use. If that is a problem you can find a font that
can display the characters you need with code such as this:
for (Iterator<Font> i = fontList.iterator(); i.hasNext(); ) {
Font f = i.next();
if ( ! f.canDisplay( '\u25B6' ) )
i.remove();
}
(See http://www.hccfl.edu/pollock/Java/UnicodeSymbols.htm for
a sample applet with source that does this.)
There is a whole lot more to the story including ligatures,
kerning, leading, and other fascinating (to me anyway)
facts and history. (Did you know that originally printers
(human ones) traveled with cases containing little wooden or
lead font blocks? The capital letters were used much less
often then the others and were stored in the top or upper
part of the case while the rest were kept in the more
convenient lower part of the case, and that's how we got
the terms lowercase and uppercase letters.)
-Wayne