Introduction
This article will explain how to render true type text to a OpenGL surface by wrapping the FreeType
library; using open source tools and technology; these include the Mono, SDL, TAO and FreeType
/2 packages.
Background
One of the first things you'd want to accomplish when starting off with 3D graphics is to be able to render true type text; this is not as easy as it sounds... in 3D space you'd need to create a set of quads for each character in the font; the quads define the stroke or rather outline for each character in the true type font. On Windows platform, the function wglUseFontOutlines
which is binded to a Device Context; this is all good but on Linux there's no such thing as wglUseFontOutlines
nor Device Context; all true type text rendering is managed by a library called FreeType
.
After many days of Web browsing, I finally came to the conclusion that there does not exist a decent wrapper for FreeType
on the .NET platform; a number of people have asked me to publish the code so I've decided to put it here.
Using the Code
You'll need the following packages installed on Linux:
- Mono & Mono-Develop
- Tao-Framework .NET
- SDL.NET
- FreeType/2
Ensure you have a line similar to the one below in your /etc/mono/config file if it's not already there; refer to the mono documentation for more information.
<dllmap dll="opengl32.dll" target="libGL.so">
<dllmap dll="freetype.dll" target="libfreetype.so">
Our FreeTypeWrap
namespace defines the wrapper for the native FreeType
API; in it we have defined a set of classes; they are defined using the sequential
attribute; so that the order in which they appear in memory is the same as the order in which we define them in the code; by default the .NET runtime will sometimes shuffle class members around so it can optimize memory usage; when it comes to marshalling native code this is definitely not what you want. Some class members contain static
methods which are context bound so it makes the code easier to read and understand when working with it.
It's worth mentioning that the wrapper is native to FreeType
itself and does not wrap around a custom build library (as in the case of SDL); it essentially blends in directly with FreeType
instead; the version I used was 9.8.3 (freetype-config --version).
[StructLayout (LayoutKind.Sequential)]
public class Library {
public System.IntPtr memory;
...
We mostly make use of System.IntPtr
for memory pointers; in the case where FreeType
allocates the memory, it is passed with an out
operator which tells the .NET runtime that the memory is not part of our process but belongs to an external process; we only have a pointer to it (it's the C# version of void*
).
[DllImport ("freetype.dll")]
public static extern int FT_Init_FreeType( out System.IntPtr lib );
Note that our FreeTypeWrap
namespace only defines the classes that we need in order to render true type text to an OpenGL surface; it is by far not a complete representation of the entire FreeType
API; which is huge; keep in mind though that it can extend easily to support the entire API following the same basic principles.
Font3D
is where most of the fun stuff happens; it is a utility class which can be instantiated so you can create more than one font at a time; the constructor accepts the name of the font file from which to load and a generic point size. From here on, it creates a 3D texture and the set of quads for the first 128 characters in the font.
Our print
method will print the text to the current OpenGL surface, it does this without disrupting the current model and view matrix settings.
The extent
method is used to calculate the distance of a specific text string; this is nice when you need to center text.
The sample application will rotate some text around the screen, it relies on SDL for event and video handling and uses TAO.Gl to do the rendering.
I hope this helps someone.
History
- 3rd March, 2006: First release