FreeType2 Usage Notes

The motivation of this page is that the FreeType2 tutorial doesn’t
give you complete working code. Lots of people complain about the lack
of very short simple working example. I too felt that was lacking, so I
posted up my first simple program.

See: text2text

This program should compile on linux, Irix, or solaris. Minor Makefile
adjustments may be needed if files don’t appear in the same locations
for you as the do me. Last tested on Irix w/ MIPSpro, RHEL3, Ubuntu
Warty Warthog, and Solaris9 w/ SunStudio. Solaris with GCC will require
you adjusting your system so cc invokes gcc.

Anyway, the program demonstrates simple usage of freetype2.

Below is the main piece. It opens the library, loads the font file,
sets the text size, then renders out the characters. As written, it
just assumes the canvas will be large enough for the text.

If you extrapolate as it is written, you would have to render the
text twice if you want to create a canvas that is sure to hold the
string (say because you want to render to a picture). Also, the code
below offers no method for dealing with ligatures.

error = FT_Init_FreeType( &library );
if ( error )
{
  printf("an error occured\n");
  exit(-1);
} 

error = FT_New_Face( library, fileName, 0, &face );
if ( error == FT_Err_Unknown_File_Format )
{
  //... the font file could be opened and read, but it appears
  //... that its font format is unsupported
  printf("Face error\n");
  exit(-1);
}
else if ( error )
{
  //... another error code means that the font file could not
  //... be opened or read, or simply that it is broken...
  printf("other Face error\n"); 
  exit(-1);
}

error = FT_Set_Char_Size( face, /* handle to face object */
0, /* char_width in 1/64th of points */
48*64, /* char_height in 1/64th of points */
40, /* horizontal device resolution */
18 ); /* vertical device resolution */

slot = face->glyph; /* a small shortcut */

pen_x = 0;
pen_y = 0;
for ( n = 0; n < num_chars; n++ )
{
  unsigned char * buf;

  /* load glyph image into the slot (erase previous one) */
  error = FT_Load_Char( face, text[n], FT_LOAD_DEFAULT );
  if ( error ) continue; /* ignore errors */

  /* convert to an anti-aliased bitmap */
  //FT_RENDER_MODE_MONO
  error = FT_Render_Glyph( face->glyph,  FT_RENDER_MODE_NORMAL );
  if ( error ) continue; /* now, draw to our target surface */

  buf = slot->bitmap.buffer;

  for(j=0; jbitmap.rows; j++)
  {
    for(i=0; ibitmap.width ; i++)
    {
      int index = (j*slot->bitmap.width)+(i);
      unsigned char c;
      //printf("index: %d offset %d\n", index/8, index%8);
      c=buf[index];

      pen_y = height -3-slot->bitmap_top;

       if (c>0 && c<128) output[(j+pen_y)*width+(i+pen_x)] = '.';
       if (c>127) output[(j+pen_y)*width+(i+pen_x)] = 'x';
    }
  }

  /* increment pen position */
  pen_x += slot->bitmap.width+2;
}

The big change I’m working on is making it use an array FT_Glyph
structures to be able to hold the string of glyphs. In
psuedo code, that would look something like this:

FT_Glyph * glyphs;
int width=0;
//setup array.

for (/*each char in char string*/)
{
  error = FT_Load_Char( face, string[i], FT_LOAD_NORMAL );
  error = FT_Get_Glyph( face->glyph, &(glyph[i]));
  error = FT_Render_Glyph( &(glyph[i]),  FT_RENDER_MODE_NORMAL );
  width += glyph[i]->bitmap.width + SPACE_BETWEEN_CHARS;
}

//create canvase

for (/*each char in char string*/)
{
  //do something with each render'd glyphs bitmap to copy to destination

  FT_Done_Glyph(glyphs[i]);
}

free(glyphs);

Keep in mind that is incomplete code. It hasn’t really been written
up and tested yet.

And I still don’t know how to deal with ligatures, kerning, and all
sorts of other features. However, if I implement the pseudo code above,
I expect I’ll have everything I need for now.