FreeType.NET Tutorial  
  Introduction

FreeType.NET is constructed of 3 layers:

The FreeType 2 library. This is a cross-platform DLL, installed as part of the Mono installation, or available here: www.freetype.org.

Rather confusingly, the download called FreeType2 is actually FreeType 1.1/1.4, whereas the download FreeType6 references FreeType 2.0.1 and higher. Icarus uses FreeType 2.1.9 or higher, and will refer to this as FreeType 2 in the documentation.

Tao.FreeType. This is a C# interface for FreeType 2, and is simply a replication of all the procedure calls and datastructures available in the FreeType 2 library.

FreeType.NET is an OpenGl interface for Tao.FreeType. FreeType 2 by itself is simply  a font file interpreter, it does not display the fonts at all, and knows nothing of OpenGl calls. By extension then, Tao.FreeType knows nothing of OpenGl, so FreeType.NET exists to make it easy and quick to get FreeType fonts up and running.

The following installation is written from the point of view of including FreeType into an existing project.

Windows Installation

The following files will need to be in the same path as the project binaries:

freetype6.dll                      A version of freetype6.dll, 2.3.4, is included in the download for FreeType.NET
Tao.FreeType.dll

The following files will need to be added as a Reference to the project:

FreeType.NET.dll
Tao.OpenGl

Linux Installation

FreeType 2 is installed by default with Mono as libfreetype.so.6. This is referenced by the Tao.Freetype.dll.config, and is installed on Fedora Core 7 in /usr/lib/libfreetype.so.6

The following files will need to be in the same path as the project binaries:

Tao.FreeType.dll
Tao.FreeType.dll.config
Tao.OpenGl.dll
Tao.OpenGl.dll.config

The following files will need to be added as a Reference to the project:

FreeType.NET.dll
Tao.OpenGl.dll

MacOSX Installation

FreeType 2 is installed by default with Mono to /Library/Frameworks/Mono.framework/Libraries/libfreetype.6.dylib

The following files will need to be in the same path as the project binaries:

Tao.FreeType.dll
Tao.FreeType.dll.config
Tao.OpenGl.dll.config

The following files will need to be added as a Reference to the project:

FreeType.NET.dll
Tao.OpenGl.dll

File Location

All *.dll.config files are located in the subdirectory for the specific operating system:
/Dependencies/Linux/
/Dependencies/MacOSX/

Binaries for Tao.FreeType.dll, FreeType.NET.dll, and freetype6.dll are available in
/Dependencies/FreeTypeDemo/bin/Release/

or

/Dependencies/FreeTypeDemo/bin/Debug/ for the debug version.

If Tao is not installed, Tao.OpenGl.dll is also available in the above folder.

The source for Tao.FreeType is in
/Dependencies/Tao.FreeType

The source for FreeType.NET is in
/Dependencies/FreeType.NET

A free sample font, FreeSans.ttf is available in:

/Dependencies/FreeTypeDemo/bin/Release/

FreeTypeDemo* and Tao.Sdl* files are not needed for installation into a project.

Running the Demo

Just copy over the entire /Dependencies/FreeTypeDemo/bin/Release/, copy in the correct .dll.config files for your operating system, and run the FreeTypeDemo.exe file

Basic Usage

Initialising

FreeType.NET works off external TrueType/OpenType font faces. These files are read in from external media, translated into OpenGL-compatible format, and then rendered to the screen, based on the current OpenGL setup.

To start, the installed version of the FreeType library can be accesses in one of two ways. Both are static methods:

FTFont.ftVersion(ref int Major, ref int Minor, ref int Patch);
This is useful for decoding the version and ensuring that the correct one is installed

string version = FTFont.ftVersionString();
this is useful to quickly output the version to a console or log


The FTFont class is the main interface to this. To get started, first create an instance of the class

int Errors = 0;
samplefont = new FTFont("FreeSans.ttf", out Errors);


This will initialise the freetype library (if not initialised already), then attempt to load the FreeSans.ttf file. Errors will equal 0 if there were no errors.

Once loaded, it now needs to be initialised. The current function to do this is:

samplefont.ftRenderToTexture(48,196);

This only needs to be done once for a given text size.

If the font size needs to be changed, this may be called again after a call to ftClearFont(), like so:

samplefont.ftClearFont();
samplefont.ftRenderToTexture(12,18);

There will be a slight delay while everything is recompiled.

The Render function will have 3 additional companion functions to support different ways of rendering the font, i.e. to support Outline fonts and Texture Mapped fonts (where there's one big texture that contains all the font glyphs).

ftRenderToTexture then renders each font character into it's own texture and uploads these to the graphics card. This routine is not thread-safe because it requires the thread to be the same as that used by OpenGl.

The first parameter is the desired height (in pixels) of the font. the second parameter is the DPI, or Dots Per Inch.

Setting Alignment

The next thing to do is to set the font alignment (although this can be done at any time):

samplefont.FT_ALIGN = FTFontAlign.FT_ALIGN_CENTERED

Rendering

Now that the font has been initialised, it's now ready to be rendered.  To do that, in the OpenGL rendering routine, the general process is as follows:

samplefont.ftBeginFont();
samplefont.ftWrite("Hello World");
samplefont.ftEndFont();


Standard open GL functions for colour, positioning, scale etc.. can be called either before or after the ftBeginFont. If OpenGL matrix-affecting calls are done after BeginFont, these will be "popped" by EndFont.

 If your OpenGL projection is set to Orthogonal, the font will not need to be scaled. However, if it is set to Projection, you will need to scale the font accordingly. If the font is set to 48 pixels in the initialisation, it will actually be drawn in Quads from 0,0 to 48,48. Since the Projection mode by default is from -1 to 1, something 48 units wide is far too big, and should typically be preceded with a glScalef(0.0035f,0.0035f,0.0035f) function to make it much smaller.

A more complicated example is shown here showing the scale, colour and translation in action:

Gl.glTranslatef(0.5f, 0.9f, 0);
Gl.glColor3f(1, 1, 1);
Gl.glScalef(0.0035f, 0.0035f, 0.0035f);

samplefont.ftBeginFont();
  samplefont.ftWrite("Press 1 for 12 point");

  Gl.glTranslatef(0, -32f, 0);
  samplefont.ftWrite("Press 2 for 18 point");

  Gl.glTranslatef(0, -32f, 0); 
  samplefont.ftWrite("Press 3 for 32 point");

  Gl.glTranslatef(0, -32f, 0); 
  samplefont.ftWrite("Press 4 for 64 point");

  Gl.glTranslatef(0, -32f, 0);
  samplefont.ftWrite("Press SPACE to toggle spinning");
samplefont.ftEndFont();

Note that the scale affects the later translations, which is why they are offset by -32f, and not -0.0035f, to indicate a new line.

Here is an example of the output of the above text from the Demo application. Note that it's slightly different, the above example has been simplified to one font to keep things simple, whereas the Demo application uses two fonts:

Screenshot of output from Demo application

Cleaning Up

Once a font is finished with, Dispose needs to be called to free up the Font face pointer, for each font created:

samplefont.Dispose();

Once FreeType is finished with, an additional call is needed:

FTFont.DisposeFreeType();

This is a static class method and does not need an object. This will clean up the pointer to the freetype library;