Friday, March 4, 2011

Compiling FTGL-2.1.3~rc5 on Windows Using the Mingw Compiler Bundled With Qt

If you are trying to compile FTGL on Windows, you may have run into the same problem I did: it's not really set up to make that easy. I couldn't get it to work with Cygwin's configure tool. So I tried to make my own Makefile. After searching a fair amount, I found this page to be useful:

http://www.pitt.edu/~mwr12/compcorner/linuxstuff/ftgl.html

I followed Step 3, adding the following to the bottom of FTGL/ftgl.h just before the last #endif:

#ifdef WIN32
    #include <GL/gl.h>
    #include <GL/glu.h>
    #include <windows.h>
#endif

Then, after studying the Makefile for FTGL, and after looking at the script in Step 5 (from the website linked above), I finally came up with a Makefile that worked for me:

# Makefile.in generated by automake 1.10.1 from Makefile.am.
# src/Makefile.  Generated from Makefile.in by configure.

# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
# 2003, 2004, 2005, 2006, 2007, 2008  Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.


top_builddir = ..
COMPILER_DIR = C:/Qt/2010.05/mingw
CONFIG_HEADER = $(top_builddir)/config.h
CPPFLAGS =  -Wall -Wpointer-arith -Wcast-align -Wcast-qual -Wshadow -Wsign-compare
CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CPPFLAGS)
CXX = g++ -g -O2
DEFAULT_INCLUDES = -I. -I$(top_builddir) -IFTGL/
DEFS = -DHAVE_CONFIG_H
FT2_CFLAGS = -I$(COMPILER_DIR)/include/freetype -I$(COMPILER_DIR)/include
FT2_LIBS = -L$(COMPILER_DIR)/lib -lfreetype
GL_CFLAGS = -I$(COMPILER_DIR)/include
GL_LIBS = -lglu32 -lopengl32
HEADER_FLAGS = -I$(COMPILER_DIR)/include
NULL = 
libftgl_dll_CXXFLAGS = $(FT2_CFLAGS) $(GL_CFLAGS)
libftgl_dll_LIBADD = $(GL_LIBS) $(FT2_LIBS)

libftgl_a_objects = \
    FTBuffer.o \
    FTCharmap.o \
    FTContour.o \
    FTFace.o \
    FTGlyphContainer.o \
    FTLibrary.o \
    FTPoint.o \
    FTSize.o \
    FTVectoriser.o \
    $(ftglyph_objects) \
    $(ftfont_objects) \
    $(ftlayout_objects) \
    $(NULL)

libftgl_a_SOURCES = \
    FTBuffer.cpp \
    FTCharmap.cpp \
    FTCharmap.h \
    FTCharToGlyphIndexMap.h \
    FTContour.cpp \
    FTContour.h \
    FTFace.cpp \
    FTFace.h \
    FTGlyphContainer.cpp \
    FTGlyphContainer.h \
    FTInternals.h \
    FTLibrary.cpp \
    FTLibrary.h \
    FTList.h \
    FTPoint.cpp \
    FTSize.cpp \
    FTSize.h \
    FTVector.h \
    FTVectoriser.cpp \
    FTVectoriser.h \
    FTUnicode.h \
    $(ftglyph_sources) \
    $(ftfont_sources) \
    $(ftlayout_sources) \
    $(ftgl_headers) \
    $(NULL)

ftgl_headers = \
    FTGL/ftgl.h \
    FTGL/FTBBox.h \
    FTGL/FTBuffer.h \
    FTGL/FTPoint.h \
    FTGL/FTGlyph.h \
    FTGL/FTBitmapGlyph.h \
    FTGL/FTBufferGlyph.h \
    FTGL/FTExtrdGlyph.h \
    FTGL/FTOutlineGlyph.h \
    FTGL/FTPixmapGlyph.h \
    FTGL/FTPolyGlyph.h \
    FTGL/FTTextureGlyph.h \
    FTGL/FTFont.h \
    FTGL/FTGLBitmapFont.h \
    FTGL/FTBufferFont.h \
    FTGL/FTGLExtrdFont.h \
    FTGL/FTGLOutlineFont.h \
    FTGL/FTGLPixmapFont.h \
    FTGL/FTGLPolygonFont.h \
    FTGL/FTGLTextureFont.h \
    FTGL/FTLayout.h \
    FTGL/FTSimpleLayout.h \
    ${NULL}

ftglyph_objects = \
    FTGlyph/FTGlyph.o \
    FTGlyph/FTGlyphGlue.o \
    FTGlyph/FTBitmapGlyph.o \
    FTGlyph/FTBufferGlyph.o \
    FTGlyph/FTExtrudeGlyph.o \
    FTGlyph/FTOutlineGlyph.o \
    FTGlyph/FTPixmapGlyph.o \
    FTGlyph/FTPolygonGlyph.o \
    FTGlyph/FTTextureGlyph.o \
    $(NULL)

ftglyph_sources = \
    FTGlyph/FTGlyph.cpp \
    FTGlyph/FTGlyphImpl.h \
    FTGlyph/FTGlyphGlue.cpp \
    FTGlyph/FTBitmapGlyph.cpp \
    FTGlyph/FTBitmapGlyphImpl.h \
    FTGlyph/FTBufferGlyph.cpp \
    FTGlyph/FTBufferGlyphImpl.h \
    FTGlyph/FTExtrudeGlyph.cpp \
    FTGlyph/FTExtrudeGlyphImpl.h \
    FTGlyph/FTOutlineGlyph.cpp \
    FTGlyph/FTOutlineGlyphImpl.h \
    FTGlyph/FTPixmapGlyph.cpp \
    FTGlyph/FTPixmapGlyphImpl.h \
    FTGlyph/FTPolygonGlyph.cpp \
    FTGlyph/FTPolygonGlyphImpl.h \
    FTGlyph/FTTextureGlyph.cpp \
    FTGlyph/FTTextureGlyphImpl.h \
    $(NULL)

ftfont_objects = \
    FTFont/FTFont.o \
    FTFont/FTFontGlue.o \
    FTFont/FTBitmapFont.o \
    FTFont/FTBufferFont.o \
    FTFont/FTExtrudeFont.o \
    FTFont/FTOutlineFont.o \
    FTFont/FTPixmapFont.o \
    FTFont/FTPolygonFont.o \
    FTFont/FTTextureFont.o \
    $(NULL)

ftfont_sources = \
    FTFont/FTFont.cpp \
    FTFont/FTFontImpl.h \
    FTFont/FTFontGlue.cpp \
    FTFont/FTBitmapFont.cpp \
    FTFont/FTBitmapFontImpl.h \
    FTFont/FTBufferFont.cpp \
    FTFont/FTBufferFontImpl.h \
    FTFont/FTExtrudeFont.cpp \
    FTFont/FTExtrudeFontImpl.h \
    FTFont/FTOutlineFont.cpp \
    FTFont/FTOutlineFontImpl.h \
    FTFont/FTPixmapFont.cpp \
    FTFont/FTPixmapFontImpl.h \
    FTFont/FTPolygonFont.cpp \
    FTFont/FTPolygonFontImpl.h \
    FTFont/FTTextureFont.cpp \
    FTFont/FTTextureFontImpl.h \
    $(NULL)

ftlayout_objects = \
    FTLayout/FTLayout.o \
    FTLayout/FTLayoutGlue.o \
    FTLayout/FTSimpleLayout.o \
    $(NULL)

ftlayout_sources = \
    FTLayout/FTLayout.cpp \
    FTLayout/FTLayoutImpl.h \
    FTLayout/FTLayoutGlue.cpp \
    FTLayout/FTSimpleLayout.cpp \
    FTLayout/FTSimpleLayoutImpl.h \
    $(NULL)

all: libftgl.a ftgl.dll

.cpp.o:
 $(CXXCOMPILE) -c $(HEADER_FLAGS) -DFTGL_LIBRARY_STATIC -o $@ $<

libftgl.a: $(libftgl_a_objects)
 ar -r $@ $(libftgl_a_objects)

ftgl.dll: $(libftgl_a_SOURCES)
 $(CXXCOMPILE) $(libftgl_a_SOURCES) $(libftgl_dll_CXXFLAGS) $(libftgl_dll_LIBADD) -DFTGL_LIBRARY -DFTGL_DLL_EXPORTS -shared -Wl,--out-implib,libftgl.dll.a -o ftgl.dll
  
clean:
 @-del /S *.o
 @-del ftgl.dll
 @-del libftgl.dll.a
 @-del libftgl.a


This will compile the library for static and dynamic use. You will need to copy the FTGL folder to mingw/include. Then, to use as a static library, copy the resulting file src/libftgl.a to mingw/lib. To use as a dynamic library, copy the file src/libftgl.dll.a to mingw/lib and rename it to libftgl.a, and then copy src/ftgl.dll to the folder in your application.

As a side note, I am using this in a Qt application, so I had to update the .pro file to include the following line:

LIBS += -lftgl -lfreetype -lglu32 -lopengl32

When using ftgl.dll, I didn't need to add the '-lglu32 -lopengl32'. After using the static library, however, the linker complained about not having opengl functions defined. Also note the ordering of the libraries. Placing the opengl includes before the ftgl include didn't work. I had to put them after to satisfy the linker.

I could then follow the tutorials and get them to work. Also, another side note: The resulting text turned out to be far bigger than the -1,1 box in opengl, since it is measured in bigger units. Either scaling or using projection should help with that.

Another issue I found when using FTGLTextureFont is that the depth test needed to be set correctly, or the letter boxes seemed to overlap each other, blocking some of the letters. Setting the depth function using glDepthFunc(GL_LEQUAL); solved this problem for the most part. Another problem remained: at some font sizes, some of the letters seem to be clipped by either their neighbor or their own box. It is especially noticable on the letters 'e' and 'o'. This problem can be avoided by changing the font size to a size where this doesn't happen and then scaling to compensate.