Library for rendering crisp vector fonts in opengl (haxe side using ogl lib) based on distance fields

cpp, neko
haxelib install gl3font 0.0.3


rendering example

Simple, high quality font rendering for opengl.

Whilst the API in this library is specific to Haxe and the hx-ogl API, the ttfcompile tool would be easily used in any suitable environment where we haxe programmable shaders, so any stage3d (flash), or other opengl/directx environment.

Based upon Valve's siggraph paper:


This small c++ tool takes a font file (compatible with freetype2), eg TrueType .ttf, and produces a texture atlas .png of a given set of characters (By default all ISO-1 Latin + ISO-7 Greek characters) as a signed distance field, together with a .dat file describing necessary information to make use of the atlas.

Support for full unicode.

./ttfcompile font size gap search-radius output-size [-chars=chars-set] [-charsfile=chars-file] [-o=output-name]
  • font : The font file (eg: /usr/share/fonts/truetype/freefont/FreeSans.ttf)
  • size : Pixel size for font when rendering an intial atlas of characters. Should aim for some large value like 250 so that we have a sufficiently high quality atlas to compute the distance field from.
  • gap : Pixel gap between characters in initial atlas, a value of 3 seems to give a good tradeoff between efficiency in terms of how large the output image must be to get good quality, whilst preventing adjacent characters intefering in the distance field.
  • search-radius : Pixel radius in the initial high quality atlas for performing brute-force search of nearest boundary, needs to scale with the pixel font size, a value of 40 for a font size of 250 seems to work well.
  • output-size : Pixel size for the dimensions of the output distance field (Actual output may likely have one dimension shorter, output is not generally an exact square).
  • chars-set : Set of unicode characters to use for the atlast, by default all of the ISO-1 latin + ISO-7 greek code pages.
  • chars-file : Name of utf8-textfile that contains char-set.
  • output-name : Name for output files (and location), output files written as output-name.png and output-name.dat. By default the given font file name/location is used for output-name.

A set of fonts are already pregenerated in the free and dejavu subdirectories generated by the commands listed in the ttfcompile/given bash script.

The ttfcompile tool depends on libraries: libpng, png++, icu, freetype2 and requires c++11 compatible compiler.

The output .dat file has the following, simple (binary) format:

character-count : uint32  // number of characters in the font atlas
line-height     : float   // height between baselines for font rendering.
line-ascender   : float   // (not-guaranteed) height from the base line to
                             highest point in the font.
line-descender  : float   // (not-guaranteed) height from the base line to
                             lowest point in the font.
{ character-code : uint32   // Unicode code point associated with atlas index.
  horiz-advance  : float    // How much to advance pen-position after
                               rendering this character.
  offset-left    : float    // horizontal offset to pen-position when
                               rendering this character.
  offset-top     : float    // vertical offset to pen-position when
                               rendering this character.
  char-width     : float    // width of character
  char-height    : float    // height of character
  atlas-u        : float    // normalised tex-coordinate in atlas
                               for this character.
  atlas-v        : float    // normalised tex-coordinate in atlas
                               for this character.
  atlas-w        : float    // normalised width in atlas for character.
  atlas-h        : float    // normalised height in atlas for character.
}  <-- repeated character-count times.
{ horiz-kerning  : float    // horizontal offset to be applied before rendering
                               a character based on previously rendered char.
  repeats        : uint32   // number of times this kerning value is repeated in
                               the matrix.
}  <-- repeated as many times as is necessary to enumerate
      character-count * character-count entries.

All values are based on the font having a pixel size of 1px regardless of input parameters to ttfcompile.

example, the kerning matrix:

[[ 0, 0, 0, 1 ]
 [-1, 1, 1, 0 ]
 [ 0, 0, 0, 0 ]
 [ 1, 1, 1, 1 ]]

would be encoded in the .dat file as

0:ft, 3:u32, 1:ft, 1:u32, -1:ft, 1:u32, 1:ft, 2:u32, 0:ft, 5:u32, 1:ft, 4:u32

Can check the free, and dejavu subdirectories for example outputs.

Alternative usage.

./ttfcompile -transform input.png search-radius output-size [-o=output-name]

To convert an input greyscale png (high resolution) to a distance field as per ttf transformation.

No data output is made (obviously).

gl3font API:

Simple API for rendering said fonts generated with ttfcompile using ogl, all types included with import gl3font.Font;

Depends upon ogl and hxformat.

Font class used to load and parse font files from ttfcompile.

class Font {
    // Load font files, create opengl texture (must have a context!)
    // Can pass null for .dat path if wanting to simply load
    // the distance map to a texture for use.
    function new(path_to_dat:Null<String>, path_to_png:String);

    // ID for the opengl texture generated.
    var texture : GLuint;

    // Information from .dat file parsed.
    var info : FontInfo;

    // Destroy GL state, can't use font following this call.
    function destroy();

Structure storing font metric information from .dat file.

class FontInfo {
    // Map from character's unicode point value, to index in the atlas/FontInfo structure.
    var idmap : Map<Int,Int>;

    // Global font metrics
    var height : Float;
    var ascender : Float;
    var descender : Float;

    // Kerning matrix, [prev][curr] : Float for horizontal offset before rendering 'curr' after 'prev'
    var kerning : Array<Array<Float>>;

    // Metrics for each character in the font
    var metrics : Array<Metric>;

Per character metrics from .dat file.

class Metric {
    // Horizontal offset after rendering character.
    var advance : Float;

    // Horizontal and vertical offsets for rendering character.
    var left : Float;
    var top : Float;

    // Character size
    var width : Float;
    var height : Float;

    // Character texture rectangle in atlas png
    var u : Float;
    var v : Float;
    var w : Float;
    var h : Float;

Rendering engine for gl3font fonts.

class FontRenderer {

    function new();

    // Set transformation matrix for rendering font to the screen.
    function setTransform(mat:Mat4) : FontRenderer;

    // Set font colour for rendering
    function setColour(colour:Vec4) : FontRenderer;

    // Begin rendering fonts (Selects gl program, enables vertex attrib arrays)
    function begin() : FontRenderer;

    // End rendering of fonts (disables vertex attrib arrays)
    function end() : FontRenderer;

    // Render a string, must be called being begin() and end()
    function render(string:StringBuffer) : FontRenderer;

    // Render arbitrary vertex data (with distance field texture)
    function renderRaw(texture:GLuint, vertexBuffer:GLuint) : FontRenderer;

    // Destroy GL state, can't use renderer following this call.
    function destroy();

GL3Font 'string', string data is buffered for efficient rendering.

class StringBuffer {

    // Create string buffer with initial space for 'size' characters
    // and with vertex buffer set for either static, or dynamic drawing.
    // (Strings that frequently change should be dynamic).
    function new(font:Font, ?size:Int=1, ?staticDraw:Bool=false);

    // Font in use for string, can be changed at any 'reasonable' time.
    // i.e. changing font, after setting text, but before rencering has no effect
    // on that rendered text.
    var font:Font;

    // Set StringBuffer to render the given string, using given alignment.
    // Multiline strings (delimited by \n) permitted.
    // Returns Vec4 for text bounds (x,y,width,height)
    function set(string:String, ?align:FontAlign=AlignLeft) : Vec4;

    // Destroy GL state, can't use string buffer following this call.
    function destroy();

Possible alignment modes for rendering font.

enum FontAlign {
    AlignLeft;   // Text drawn starting with first baseline at y=0, rendering each line to the right of origin.
    AlignRight;  // Text drawn starting with first baseline at y=0, rendering each line to the left of origin.
    AlignCentre; // Text drawn starting with first baseline at y=0, rendering each line centered on x=0.

    // Justified varients of the above. Each line has spacing artificially scaled up so that every line covers
    // the same horizontal space.


Basic usage example (depends upon glfw3) demonstrating basic text rendering, using suitable transforms to render text centered at mouse cursor with given pixel size and rotation on 2d screen.