Freetype Library

0.7

Re: Wine cannot find the FreeType font library. Post by lnx64 » Tue Nov 08, 2016 12:32 pm Looks like I was able to fix this by completely purging the i386 freetype, and reinstalling it.

So here's a quick tutorial to show you how to use the FreeType font rendering library in OpenGL. By using the FreeType library we can create anti-aliased text that looks better than text make using bitmap fonts (as in lesson 13). Our text will also have some other advantages over bitmap fonts - it will be easy to rotate and work well with OpenGL's picking functions.

Motivation

Freetype LibraryLibraryHere I've printed out the same text using both WGL bitmap fonts and fonts rendered with FreeType as per this tutorial (both are Arial Black Italic).The basic problem with using bitmaps fonts is that in OpenGL bitmaps are by definition binary images. This means that an OpenGL bitmap stores only one bit of information per-pixel. If you zoom in on the text created using WGL bitmaps, the result looks like this:Because bitmaps are binary images, there are no gray pixels in the image above, and it means that the text looks blocky.
  1. FreeType is written in C. It is designed to be small, efficient, and highly customizable while capable of producing high-quality output (glyph images) of most vector and bitmap font formats for digital typography. FreeType is a freely available and portable software library to render fonts.
  2. Create a new project 'freetype'. In the project settings change the 'Output' to a static library: Add the freetype sources to the project, and build. Do not use your 'amalgamated' source file - that will destroy the library granularity and lead to excessively large code. Add the resulting freetype.lib file to your application project.

Luckily it is fairly easy to make better looking fonts using the GNU FreeType library. FreeType is the same library that Blizzard uses to render the fonts in their games, so you know it has to be good!

Here's a close up of the text that I've created with the help of the FreeType library:

You can see that there are a fair number of gray pixels around the edges of the text, this is the typical of an anti-aliased font, the gray pixels make the font look smoother from a distance.

Creating the Program

The first step is to get yourself a copy of the GNU FreeType library. Go to http://gnuwin32.sourceforge.net/packages/freetype.htm and download the binaries and developer files. When you install it make sure to notice the licensing terms, which basically say that if you are going to use FreeType in your own programs, you need to give them credit somewhere in your documentation.

Now we need to setup MSVC to use FreeType. So create new project as in lesson 1 , but when you go to Project->Settings->Link add libfreetype.lib to Object Modules / libraries along with opengl32.lib, glu32.lib and glaux.lib.

Python Freetype Library Not Found

Next we need to go to Tools->Options->Directories and add the FreeType library directories. Under 'Show Directories For' select 'Include Files', then double click on the empty line at the bottom of the directory list, after you double click a '...' button will appear that you can use to browse for a directory. In this way add

and To you list of header directories.

Now under 'Show Directories For' select 'Library Files', and this time add

At this point we should be able to compile programs using FreeType, but they won't run unless they can access the freetype-6.dll. Right now you have a copy of that DLL file in your GNUWIN32BIN directory, and if you put it somewhere where all your programs can see it (Program FilesMicrosoft Visual StudioVC98Bin is a good choice), you will be able to run programs using FreeType. But remember that if you distribute a program that you have made using FreeType, you will need to also distribute copies of the DLL along with it.

Ok, now we can finally start writing code. I've decided to work off the lesson13 source, so grab a copy of lesson 13 if you don't have one already. Copy lesson13.cpp to your project directory, and add the file to the project.

Now add and create two new files called 'freetype.cpp' and 'freetype.h'. We will put all our FreeType specific code into these files, and then modify lesson13 a little to show off the functions that we've written. When we are done, we will have created a very simple OpenGL FreeType library that could theoretically be used in any OpenGL project.

We will start with freetype.h.

Naturally, we need include the FreeType and OpenGL headers. We will also include some handy parts of the Standard Template Library, including STL's exception classes, which will make it easier for us create nice debugging messages.

We will put all the information that each font needs into one structure (this will make managing multiple fonts a little easier). As we learned in lesson13, when WGL creates a font, it generates a set of consecutive display lists. This is nifty, because it means that you can use glCallLists to print out a string of characters with just one command. When we create our font we will set things up the same way, which means that the list_base field will store the first of 128 consecutive display lists. Because we are going to use textures to draw our text, so we will also need storage for the 128 associated textures. The last bit of info that we will need is the height, in pixels, of the font that we have created (this will make it possible to handle newlines in our print function).

The last thing we need is a prototype for our print function:

And that's the end of the header file! Time to open up freetype.cpp.

We are using textures to display each character in our font. OpenGL textures need to have dimensions that are powers of two, so we need to pad the font bitmaps created by FreeType to make them a legal size. That's why we need this function:

The next function that we need is make_dlist, it is really the heart of this code. It takes in an FT_Face, which is an object that FreeType uses to store information about a font, and creates a display list coresponding to the character which we pass in.

Library

Now that we have a bitmap created by Freetype, we need to pad it with empty pixels to make it a legal source for an OpenGL texture. It's important to remember that while OpenGL uses the term 'bitmap' to mean binary images, in FreeType bitmaps store 8 bits of information per pixel, so FreeType's bitmaps can store the grays that we need to create anti-aliased text.

With the padding done, we can get onto creating the OpenGL texture. We are including an alpha channel so that the black parts of the bitmap will be transparent, and so that the edges of the text will be slightly translucent (which should make them look right against any background).

We use texture mapped quads to draw our text. This means that it will be easy to rotate and scale text, and it will also make fonts inherit their color from the current OpenGL color (none of which would be true if we used pixmaps).

The next function that we are going to create will use make_dlist to create a set of display lists corresponding to a given font file and pixel height.

FreeType uses truetype fonts, so you will want to find yourself some truetype font files to feed into this function. Truetype font files are very common, and there are a bunch of sites out there where you can download lots of different truetype fonts for free. Windows98 used truetype for nearly all of it's fonts, so if you can find an old computer running windows98, you can get all of the standard fonts in truetype format from its windows/fonts directory.

Freetype library download

Now we need a function to cleanup all the displaylist and textures associated with a font.

Here are two little functions that we are going to define in anticipation of our print function. The print function is going to want to think in pixel coordinates (also called window coordinates), so we are going to need to switch to a projection matrix that makes everything measured in pixel coordinates.

We are using two very handy OpenGL functions here, glGet to get the window dimensions, and glPush/PopAttrib to make sure that leave the matrix mode in the same state as we found it. If you are not familiar with these functions, it's probably worth your time to look them up in your favorite OpenGL reference manual.

Our printing function looks very much like the one from lesson 13, but there are a couple of important differences. The OpenGL enable flags that we set are different, which reflects the fact that we are actually using 2 channel textures rather than bitmaps. We also do a little extra processing on the line of text that we get in order to properly handle newlines. Because we are such good samaritans, we take care to use OpenGL's matrix and attribute stacks to ensure that the function undoes any changes that it makes to OpenGL's internal state (this will prevent anyone using the function from suddenly finding that, say, the modelview matrix had mysteriously changed).

Because we are using texture mapped quads, any transformations that we apply to the modelview matrix before making our glCallLists call will apply to the text itself. This means that there is the potential to rotate or scale the text (another advantage over using WGL bitmaps). The most natural way to take advantage of this fact would be to leave the current modelview matrix alone, thus letting any transformation made before the print function apply to the text. But because of the way that we are using the modelview matrix to set font position, this won't work. Our next best option is to save a copy of the modelview matrix that is passed in, and apply it between the glTranslate and the glCallLists. This is easy enough to do, but because we need to draw the text using a special projection matrix the effects of the modelview matrix will be a little different than one might expect- everything will be will be interpreted on scale of pixels. We could get around this issue entirely by not resetting the projection matrix inside of print. This is probably a good idea in some situations - but if you try it make sure to scale the fonts to an appropriate size (they tend to be something like 32x32, and you probably want something on the order of 0.01x0.01).

The library is now finished. Open up lesson13.cpp and we will make some minor modifications to show off the functions we just wrote.

Underneth the other headers, add in the freetype.h header.

And while we are here, let's create a global font_data object.

Now we need to see about creating and destroying the resources for our font. So add the following line to the end of InitGL

And add this line to the start of KillGLWindow to destroy the font when we are finished.

Now we need to modify the function DrawGLScene function so that it uses our print function. This could have been as simple to adding a single line 'hello world' command to the end of the function, but I got a little more creative because I wanted to show off rotations and scaling.

The last thing to do is put in a little exception handling code. Go to WinMain and open up a try { .. } statement at the beginning of the function.

Then modify the end of the function to have a catch {} command.

Now if we ever hit an exception, we will get a little message box telling us what happened. Note that exception handling can slow down your code, so when you are compiling a release version of your program, you may want to go to Project->Settings->C/C++, switch to the 'C++ Language' category, and turn off exception handling.

So that's it! Compile the program and you should see some nice FreeType rendered text moving around underneath the original bitmapped text from lesson 13.

General Notes

There are a number of improvements that you might want to make to this library. For one thing using the font data objects directly tends to be a little awkward, so you might want to create a standard cache of fonts to hide font resource management from users. You might also want to take a tip from the OpenGL library itself and create a font stack, which would let you avoid passing in references to font objects each time you called the print function. (These are all things that I currently do things in my own code, but decided to leave out of the tutorial for the sake of simplicity.) You might also want to make a version of print that centers the text- to do that you will probably need to use the techniques discussed below.

Right now I have the text spinning around it's center. However, to get an effect like this to work for arbitrary text, you would need to have some way of knowing exactly how long the line of text was - this can be a little tricky. One way to get the length of the text is to put glBitmap commands into the font's display lists in order modify the raster position as well as the modelview matrix (I've left the necessary line in the code, but it is commented out). Then you can set the raster position to x,y before using glCallLists, and use glGet to find the raster position after the text is drawn - the difference in raster positions will give you the length of the text in pixels.

Freetype Library

You should be aware that FreeType fonts take up much more memory than WGL's bitmap fonts (that's one the advantages of binary images, they use very little space). If for some reason you really need to conserve your texture memory, you might want to stick with the code from lesson 13.

Another interesting advantage of using texture mapped quads to represent fonts is that quads, unlike bitmaps, work well with the OpenGL picking functions (see lesson 32 ). This makes life much easier if you want to create text that responds when someone holds the mouse over it or clicks on it. (Making WGL fonts work well with picking functions is possible, again the key trick is to use raster coordinates to figure out the length of the text in pixels).

And finally, here are some links to OpenGL font libraries. Depending on your goals and compiler you may want to use one of them instead of this code (there are many more of them out there, I've generally only included things that I have some amount of experience with myself).

GLTT This library is an old library that doesn't seem to still be maintained, but it has gotten some very positive reviews. Based on FreeType1. I think you will need to find a copy of the old Freetype1 source distribution to compile it in MSVC6. Download available from http://www.opengl.org/developers/faqs/technical/fonts.htm

OGLFT A nice Freetype2 based font library, it takes a bit of work to compile under MSVC though (mostly just typical for-loop scope problems). Seems to be targeted at linux machines. http://oglft.sourceforge.net/

FTGL Yet a third Freetype based font library, this one was clearly developed for OS X. http://homepages.paradise.net.nz/henryj/code/#FTGL

FNT A non-Freetype library that is part of PLIB. Seems to have a nice interface, uses its own font format, compiles under MSVC6 with a minimum amount of fuss. http://plib.sourceforge.net/fnt/

Code

Microsoft Visual C++ 6 source code: includes the doxyfile, text and images used to generate this page as well as the source code. While lesson13.cpp is very MSVC specific, you should be able to port the library to another OS with very little work... (somewhere around here I have an earlier version of this code that was written with GLUT...) Generated on Wed Sep 17 10:07:30 2003 for freetype_tut by1.3.3