Java font class fonts
The Font class represents fonts, which are used to render text in a visible way. A font provides the information needed to map sequences of characters to sequences of glyphs and to render sequences of glyphs on Graphics and Component objects.
Characters and Glyphs
A character is a symbol that represents an item such as a letter, a digit, or punctuation in an abstract way. For example, ‘g’ , LATIN SMALL LETTER G, is a character. A glyph is a shape used to render a character or a sequence of characters. In simple writing systems, such as Latin, typically one glyph represents one character. In general, however, characters and glyphs do not have one-to-one correspondence. For example, the character ‘á’ LATIN SMALL LETTER A WITH ACUTE, can be represented by two glyphs: one for ‘a’ and one for ‘´’. On the other hand, the two-character string «fi» can be represented by a single glyph, an «fi» ligature. In complex writing systems, such as Arabic or the South and South-East Asian writing systems, the relationship between characters and glyphs can be more complicated and involve context-dependent selection of glyphs as well as glyph reordering. A font encapsulates the collection of glyphs needed to render a selected set of characters as well as the tables needed to map sequences of characters to corresponding sequences of glyphs.
Physical and Logical Fonts
The Java Platform distinguishes between two kinds of fonts: physical fonts and logical fonts. Physical fonts are the actual font libraries containing glyph data and tables to map from character sequences to glyph sequences, using a font technology such as TrueType or PostScript Type 1. All implementations of the Java Platform must support TrueType fonts; support for other font technologies is implementation dependent. Physical fonts may use names such as Helvetica, Palatino, HonMincho, or any number of other font names. Typically, each physical font supports only a limited set of writing systems, for example, only Latin characters or only Japanese and Basic Latin. The set of available physical fonts varies between configurations. Applications that require specific fonts can bundle them and instantiate them using the createFont method. Logical fonts are the five font families defined by the Java platform which must be supported by any Java runtime environment: Serif, SansSerif, Monospaced, Dialog, and DialogInput. These logical fonts are not actual font libraries. Instead, the logical font names are mapped to physical fonts by the Java runtime environment. The mapping is implementation and usually locale dependent, so the look and the metrics provided by them vary. Typically, each logical font name maps to several physical fonts in order to cover a large range of characters. Peered AWT components, such as Label and TextField , can only use logical fonts. For a discussion of the relative advantages and disadvantages of using physical or logical fonts, see the Internationalization FAQ document.
Font Faces and Names
A Font can have many faces, such as heavy, medium, oblique, gothic and regular. All of these faces have similar typographic design. There are three different names that you can get from a Font object. The logical font name is simply the name that was used to construct the font. The font face name, or just font name for short, is the name of a particular font face, like Helvetica Bold. The family name is the name of the font family that determines the typographic design across several faces, like Helvetica. The Font class represents an instance of a font face from a collection of font faces that are present in the system resources of the host system. As examples, Arial Bold and Courier Bold Italic are font faces. There can be several Font objects associated with a font face, each differing in size, style, transform and font features. The getAllFonts method of the GraphicsEnvironment class returns an array of all font faces available in the system. These font faces are returned as Font objects with a size of 1, identity transform and default font features. These base fonts can then be used to derive new Font objects with varying sizes, styles, transforms and font features via the deriveFont methods in this class.
Font and TextAttribute
- FOREGROUND and BACKGROUND use Paint values. The subclass Color is serializable, while GradientPaint and TexturePaint are not.
- CHAR_REPLACEMENT uses GraphicAttribute values. The subclasses ShapeGraphicAttribute and ImageGraphicAttribute are not serializable.
- INPUT_METHOD_HIGHLIGHT uses InputMethodHighlight values, which are not serializable. See InputMethodHighlight .
Clients who create custom subclasses of Paint and GraphicAttribute can make them serializable and avoid this problem. Clients who use input method highlights can convert these to the platform-specific attributes for that highlight on the current platform and set them on the Font as a workaround.
The Map -based constructor and deriveFont APIs ignore the FONT attribute, and it is not retained by the Font; the static getFont(java.util.Map) method should be used if the FONT attribute might be present. See TextAttribute.FONT for more information.
Several attributes will cause additional rendering overhead and potentially invoke layout. If a Font has such attributes, the hasLayoutAttributes() method will return true.
Note: Font rotations can cause text baselines to be rotated. In order to account for this (rare) possibility, font APIs are specified to return metrics and take parameters ‘in baseline-relative coordinates’. This maps the ‘x’ coordinate to the advance along the baseline, (positive x is forward along the baseline), and the ‘y’ coordinate to a distance along the perpendicular to the baseline at ‘x’ (positive y is 90 degrees clockwise from the baseline vector). APIs for which this is especially important are called out as having ‘baseline-relative coordinates.’
Field Summary
How Java works with fonts
In this article, I will try to briefly describe how Java Virtual Machine works with fonts. Once I needed to change the font used by the JVM and, surprisingly, found only pieces of legacy information about this. I spent a little time investigating the problem and now want to share this information with anybody who could find it useful. Feel free to leave any comments 🙂
First of all, let’s agree on definitions:
- TrueType — font technology, the way to describe fonts in vector format ( .ttf files).
- FreeType — library to transform vector fonts to bitmaps.
- Logical font — front-end representation of fonts in Java; Font class and its instances.
- Physical font — font file in the system (e.g. .ttf file).
How letters are drawn?
The logical font is set in the Java program (manually or automatically during the creation of instances of some AWT/Swing classes). The five Java logical fonts Dialog, DialogInput, Monospaced, SansSerif and Serif must be supported by any JRE [2].
The next step happens during the execution of compiled Java Bytecode. JVM maps logical font onto the most suitable physical font available on the machine (JRE supports TrueType and PostScript Type 1 fonts). Mapping is done through a special mapfile (font configuration file). Old documentation says that font configuration files are located in $JAVA_HOME/lib . One file is chosen depending on OS and OS version. If there is no suitable file then default fontconfig.properties is chosen. [3]
I found that these files exist only in Oracle JDK (in $JAVA_HOME/jre/lib/ ) and have names like fontconfig.properties.src . There were no such files in other OpenJDK builds I investigated.
Tracing the execution of a simple Java program that works with fonts showed the following (this is true for all JDKs, including Oracle):
$ javac FontView.java $ strace -f java FontView &> out.txt $ grep open out.txt | grep properties . [pid 24909] openat(AT_FDCWD, "/home/user/.java/fonts/1.8.0_222/fcinfo-1-pc-Ubuntu-16.04-en.properties", O_RDONLY) = 5
Here it is! The actual location of Java’s font configuration file (mapfile) is $HOME/.java/fonts/[version] . If there is no such file, JVM creates it automatically and fills it with the fonts matched with the help of libfontconfig . This makes me believe that $JAVA_HOME/lib/fontconfig.properties (a.k.a, $JAVA_HOME/jre/lib/fontconfig.properties.src ) is some kind of legacy.
To draw physical fonts as accurately as possible, fontconfig library ( libfontconfig ) is used. Long story short, vector fonts are configured with several configuration values, e.g. antialias, embolden, dpi, or size. libfontconfig is used to deal with all these dependencies.
Finally, libfontconfig calls for FreeType library. Now the text is ready to be mapped from memory to our screen 🙂
How to change the font?
The simplest way is described. The whole system will use a directory with your desired fonts only. fonts.conf is responsible for this (it tells which physical fonts are available for OS and programs). If you want a more advanced setup of fonts.conf then read additional sources.
- Install the desired physical font on the system (e.g. place .ttf files to /etc/fonts/my-custom-fonts ).
- Check that /etc/fonts/font.conf contains the line
/etc/fonts/my-custom-fonts inside of tag and there are no othertags. - Remove old configuration file(s):
$ rm $HOME/.java/fonts/[version]/* - Run any program with text and fonts to create a new mapfile:
$ java FontView - Check that Java uses new physical font now:
$ cat $HOME/.java/fonts/[version]/[fontconfig file].properties