OpenJDK: Font Scaler Replacement Project

An encumbrance. This Project became inactive shortly after the feature was delivered into JDK 7 and was subsequently dissolved Oct 2023. Discussion about font rasterization may be found on client-libs-dev.

At this time, the project is essentially complete, as freetype has been implemented as a replacement. Soon we will remove this project and transfer bugs and improvements into the scope of the 2D group.

Java 2D incorporates technology that converts scalable outline fonts to a specified size and fits this outline to a pixel grid to produce a raster for subsequent blitting. Hence the terms font scaling and rasterization.

The goal of this project is to create an open source JDK text rasterization subsystem. The existing implementation was licensed by Sun from a 3rd party and can not be released as open source.

This project is of a temporary nature and will be open until all major objectives are accomplished.

Background

The current font rasteriser is a native library licensed for use by Java 2D. The rasterizer works with Truetype and Type1 font formats, providing a means to obtain bitmap, outline and metrics for a particular glyph in the particular rasterization mode. Supported rasterization modes are: black&white, greyscale antialiasing, and subpixel antialiasing. The raterizer is also capable of performing arbitrary affine transforms and applying style to outlines (e.g. bolding or italicizing). The proprietary implementation fully supports Truetype hinting and limited Type1 hinting.

The rasterizer module has tight connections with several other modules. In particular:

font management subsystem
Provides higher level API on top of rasterizer (i.e. rasterizer interface is almost entirely defined by the needs of this subsystem). Triggers creation of native state and keeps pointers to native state in the java objects.
This also includes infrastructure such as bitmap caching and communication to the "blitting" code.
 
text layout engine
Directly uses rasterizer on the native layer to access some truetype tables fromt the font file. Note that this is independent from rasterization of a glyph.
 
java2d disposer
This is an internal mechanism for disposing of graphics-related resources used by Java2D. The rasterizer relies on it to ensure that native resources are properly released.
The current implementation has better support for Truetype in the java layer. In particular, mapping from char codes to glyphs is performed without access to the native library. For Type1 fonts some additional work is delegated to the native rasterizer library.

Note, that input data is not necessarily valid or well-formed and problems can be hard to detect beforehand. Given that the rasterizer is largely native code, unexpected problems often leads to a crash. Robustness is one of the important requirements, and the current implementation is addresing it on several different levels:

Requirements and objectives

The main objectives are: Requirements for solution: Also, it is desired to minimize the import of 3rd party code into the OpenJDK workspace, i.e. link with external binary library (without any modification to this library).

Overall, we are trying to refactor the logic of working with proprietary code in the way which simplifies plugging another implementation of the font rasterizer instead. But we want to minimize changes to other subsystems to avoid risk of introducing incompatibilities.

Approach

We identified freetype as the most viable cross-platform alternative. It supports the required font formats and rasterization modes. Moreover, it is already used by the native desktops on Linux and OpenSolaris.

Technically, the native part of rasterizer-related code is split between fontmanager and rasterizer specific library (t2k for proprietary rasterizer). As part of refactoring we separated JNI calls to the rasterizer-specific and shared parts. Most of the rasterizer-specific calls will are performed through implementation of the newly added FontScaler interface.

Note that there are some caveats. In particular, the native text layout engine needs to obtain pointers to certain truetype tables. (There is no need to process these tables. The contract is to return the pointer to the table in the truetype format.)

The current implementation is based on two notions - FontScaler and FontStrike. FontScaler is specific to particular physical font file (or data stream). FontStrike is specific to not just the font file but also to a particular size, style and rasterization mode. There could be more than one strike per same scaler.

This additional context is available (as native object) on every call to the rasterizer library and it is used to set parameters before processing particular request.

We expect that any scaler implementation will handle errors internally. It should throw an exception if the font (i.e. scaler) becomes unusable and make sure native resources are released.

The solution is to use freetype as a separate binary library (and probably use freetype library installed on the platform (if available)). So, hopefully there will be only a few freetype-specific files in the OpenJDK workspace (native glue code and java wrapper (implementation of FontScaler)).

Issues

We do not expect freetype to be identical in behaviour to the existing rasterizer, Eg,
  1. glyph images may differ
  2. metrics may differ
  3. set of displayable glyphs may differ
It is likely that resolving some of these may require changes in the freetype library. Also, freetype's API is not frozen and therefore different library versions might be incompatible. Having said that, these differences are expected to be small in significance, and few in number.

Status

At this time, the project is essentially complete, as freetype has been implemented as a replacement. Soon we will remove this project and transfer bugs and improvements into the scope of the 2D group.

How to contribute?

You can help by:

Note that this project uses OpenJDK contribution rules. Please see them for further details.

Community