Classpath currently has almost no support for graphics, although this would be needed for many applications. An important part of any graphics API is text handling, which requires an infrastructure for fonts. This document is intended as a basis for discussion with other GNU Classpath developers.
Sascha Brawer, July 29, 2003
Motivation
– Requirements
– Implementation
– Missing Parts
Dependencies (or: please help!)
– Patents
– Background Literature
GNU Classpath is currently far away from a serious implementation of anything related to graphics. This is rather unfortunate, since Java defines a rich and well-designed interface for programming graphics applications.
If Classpath had a working implementation of Java2D, developers could write graphics applications that run on GNU and other free operating systems. Because Java2D is part of Sun’s “Java 2 Standard Edition,” it will be needed for executing Java applications in free desktop environments. A good graphics library would also be important for some embedded systems, and it is an absolute necessity for any client-side OS based on Java. Finally, there are also server applications needing graphics.
A picture may say more than a thousand words, but graphics without text is almost useless. Fonts are at the core of text processing. Therefore, a reasonable infrastructure for fonts seems a good starting point for an implementation of Java2D.
A prospective font infrastructure for GNU Classpath should fulfill at least the following requirements:
New fonts at any time — A Java
application can define fonts at any time by calling Font.createFont. — This
must be supported.
Character set — Java uses the full 21-bit character set of Unicode, but encodes characters in UTF-16. Codepoints in the Basic Multilingual Plane are stored without modification, those above U+FFFF are squished into surrogate pairs (U+D800 – U+DFFF). — Support for the entire Unicode character set would be nice to have. Support for 16-bit characters is required.
Glyph selection — The mapping from a
sequence of Unicode codepoints to the glyphs in a font is very
complicated. — The initial version must support simple
table-based lookup of glyphs, as required for Font.createGlyphVector. Support
for contextual glyph selection (see Font.layoutGlyphVector) is not required for
the initial version. This means that it will initially not be possible
to correctly display e.g. Urdu, Hebrew, or Devanagari. Even some Latin
accents will not be displayed correctly. However, this initial support
would be sufficient for glyphs in “simple” writing
systems, under the condition that only pre-composed codepoints are
used for accented characters.
Printing — The font library should
expose what is needed to embed some glyphs of a font into a stream
sent to a printer. It should be possible to write a
javax.print.StreamPrintService for PostScript or
PDF.
Rasterization — OpenType supports three variants to specify the shape of a glyph: Straight line segments plus quadratic Bézier curves (TrueType), straigt line segments plus cubic Bézier curves (PostScript Type 1), and bitmaps. — For a first version, it seems acceptable to support only the “rasterization” of bitmaps. This would be sufficient for server and command line applications that use Java2D to generate PostScript or PDF, because these just need to measure and embed glyphs, but they do not need to rasterize them. It would also be sufficient for displaying a GUI, as long as the GUI uses a font with embedded bitmaps. One could produce a version of GNU Unifont in OpenType format, and the authors of Free UCS outline fonts could be asked to embed bitmaps. — Later, rasterization should be performed as well. A rasterizer could be written in Java, or one could call the rasterization code from FreeType. Either variant is a major project and needs to be coordinated with the scan-line conversion code for normal graphics.
Hinting — When rasterized for low resolution, vector fonts look ugly. Therefore, a process called Hinting moves the vector control points before rasterization. There exists an online demo which uses FreeType to show how (TrueType) glyphs look with and without hinting. For bitmaps, no hinting is needed.
Metrics — The geometric extent of
glyphs must be determined for Font.getStringBounds and related methods. It would
be nice to take into account the FontRenderContext,
because the exact values depend on device resolution and other
parameters, such as whether anti-aliasing is performed. However, this
would mean that vector fonts need to be hinted. For an initial
version, it seems acceptable to assume an ideal device with infinite
resolution, and to assume that glyph metrics grow linearly with point
size. This won’t be sufficient for high-end typography, but it
should be enough for a start.
Localized Names — TrueType and OpenType
Fonts can specify a variety of names in multiple languages. —
This should be supported for Font.getFontName(Locale).
Thread safety — Fonts must be safe to
access from multiple simulaneous threads. Otherwise, it would not be
possible to e.g. prepare a picture in a background thread. Note that
the performance-critical methods of java.awt.Font expect
data in bulk amounts, for example for creating a
GlyphVector. Therefore, the locking overhead should not be
prohibitive.
Memory management — Some fonts can be
quite large. There exist Kanji fonts whose size exceeds ten
megabytes. — The font library should thus avoid reading data
unless it is really needed. It should support font files that have been
mapped into the virtual address space (java.nio.MappedByteBuffer).
License — To fit with the rest of Classpath, the font library must have same license: GPL with the compiler exception, copyright assigned to the Free Software Foundation.
Written in Java — Being platform independent, it would be good for Classpath to provide a Java implementation for almost everything. This would be a reference implementation and would be of great help when porting Classpath to a new platform. Then, according to the underlying system, an optimized version can be made using native methods written in C. Where Classpath is used in combination with a decent compiler, no native code would be needed at all. Therefore, only the absolute minimum, if anything at all, should be implemented in native code. — A possible candidate for native code would be the stack machine for interpreting TrueType bytecodes (which could be taken from the FreeType project; see the above section about rasterization). Not a good candidate for native code would be glyph selection, or extraction of font names.
Dandelis (i.e., Sascha) has implemented a first version of a library that could serve as the described font infrastructure for GNU Classpath. See the automatically generated documentation of the library.
There also is a test program which allows to show all glyphs in the font, to display some font names, to layout a glyph vector, and to perform other operations which test the library. To build the test program from its source, execute the following command on a GNU/Linux (or UNIX) machine which has at least JDK 1.4 installed:
% tar zxf fonts-July29.tar.gz ; make
To execute the test program (which can also be downloaded in pre-compiled form), execute the following:
% java -jar fonttest.jar
SomeFontFile.[ttf|ttc|otf|dfont]
For each font that is embedded in SomeFontFile, a
window will appear where example text can be entered. It is also
possible to specify a point size. The test program will use the font
library of GNU Classpath to create an instance of
java.awt.font.GlyphVector, and to retrieve the outline of
each glyph as a java.awt.geom.GeneralPath. That path is
passed to a Graphics2D object for anti-aliased rendering. Because GNU
Classpath does not yet support graphics, it is not (yet) possible to
run the test program without the Sun JDK.

It should also be noted that the text field (the top line) is a normal Swing text field. The font library of GNU Classpath is only involved in the display of the bottom field. Actually, pure black-and-white text (without anti-aliasing) would be close to illegible without hinting, at least for small point sizes. See below for details.
A number of example texts are available from an option in the Edit menu. In the View menu, you can make the logical bounding box of each glyph visible (which gets painted in pink and blue). There, you can also display the visual bounding box of each glyph (which gets painted in green).

Please note the last character, which was obtained from the Unicode
sequence U+0078 U+0303 U+031F (LATIN SMALL LETTER X; COMBINING
TILDE; COMBINING PLUS SIGN BELOW). However, the font library
currently does not move accents to attachment points, so a tilde on a
capital X would not be placed at the right position. You are of course
more than welcome to enhance the library!
Also in the View menu is a menu item which allows to display every glyph in the font, together with the glyph name. The latter would be important for embedding glyphs into PostScript or PDF.

Finally, you can view the localized names and other information by selecting “Show Information” from the View menu. The screen shot below is from a different font (Helvetica Bold from MacOS X), because the Lucida fonts do not contain localized font names.

There are some missing parts. You would be very welcome to work on these; please contact Sascha Brawer.
Glyph positions — Some glyphs in the
LucidaSans font get placed at weird positions, for example the closing
parenthesis or bracket. Also, accents get placed at the wrong
positions with some fonts. The latter affects composite glyphs that
specify an attachment point in addition to a transformation matrix.
An example would be all accented glyphs in the Helvetica font that
comes with MacOS X. This needs fixing
gnu.java.awt.font.opentype.truetype.GlyphLoader.
Hinting — The class gnu.java.awt.font.opentype.truetype.VirtualMachine is
currently able to execute arithmetic and control flow instructions,
which is enough for font pre-programs. However, most geometric
instructions (which move control points around) are currently not
implemented.
CFF (PostScript) — The library understands the OpenType font file format, but is not able to retrieve outlines that are described in the PostScript CFF format.
Caching — Glyph bitmaps should be cached, but they are not right now. This might be best done at the same time when Classpath’s rasterizer gets implemented. Right now, it is not clear (to me) what format the cache should use.
Bitmaps — For the same reason, the library is currently not able to render embedded bitmaps.
Contextual glyph substitution, reordering — Complex script systems that require re-ordering glyphs, or substituting glyphs depending on context (using deterministic finite-state machines which can be part of the font data) are not yet supported. Neither is the more primitive OpenType mechanism supported. This means that is is currently not possible to render text in Arabic, Farsi, Hebrew, Hindi, Thai, Urdu, or in any other language that requires a non-trivial glyph selection/positioning.
TextLayout — A big missing part is
java.awt.font.TextLayout. To implement it efficiently,
it will probably be necessary to extend the interface gnu.java.awt.font.FontDelegate.
Glue code — Finally, some glue to
java.awt.font is missing; for example, it is currently
not possible to retrieve glyph justification information. It seems
that the best time for doing this would be when
java.awt.font.TextLayout gets implemented.
The library depends on some parts that are not yet present in GNU Classpath. Some will require serious work, and this would be an area where your help would be greatly appreciated. The work would also be needed for other parts of Classpath, not just the font infrastructure described here.
java.nio — Make sure that java.nio works. It is heavily used by the font infrastructure, for reasons explained above. Especially tricky is to make direct buffers work, because it needs support from the virtual machine.
java.nio.charset.spi — Write a service provider for some charsets. The font infrastructure needs only decoders, most urgently MacRoman for extracting font names. This should not take more than a day for each character set, and it would be useful for much more than just font names.
java.awt.geom — Complete the
implementation of QuadCurve2D.
java.text.Bidi — Implement the Unicode Bidirectional algorithm. This should take only a few days, but it would be helpful to be familiar with the algorithm. A speaker of Arabic, Hebrew, or some other language that is written right to left would be ideal for this task, although this is not strictly necessary. (The Bidi class is not yet used by the font library, but it will be needed to support OpenType fonts with bi-directional script systems).
If you think that one of these tasks would suit your interests, or
if you would like to do something else for GNU Classpath, please
contact the GNU Classpath mailing list, classpath at gnu dot
org.
Apple Computer holds several patents on the algorithm that is needed to fully hint TrueType glyphs; see the FreeType patent page for further information.
There exist serveral possibilities to deal with the patent issue.