31   FT_Library Library::library_;
 
   39     FT_Error error = FT_Init_FreeType( &library_ );
 
   42       std::cerr << 
"Could not initialize the FreeType library. Exiting." << std::endl;
 
   49     FT_Error error = FT_Done_FreeType( library_ );
 
   52       std::cerr << 
"Could not terminate the FreeType library." << std::endl;
 
   65   Face::Face ( 
const char* filename, 
float point_size, FT_UInt resolution )
 
   66     : point_size_( point_size ), resolution_( resolution )
 
   81     if ( ft_face->charmap == 0 && ft_face->num_charmaps > 0 )
 
   82       FT_Select_Charmap( ft_face, ft_face->charmaps[0]->encoding );
 
   84     faces_.push_back( FaceData( ft_face ) );
 
   91   Face::Face ( FT_Face face, 
float point_size, FT_UInt resolution )
 
   92     : point_size_( point_size ), resolution_( resolution )
 
   98     if ( face->charmap == 0 && face->num_charmaps > 0 )
 
   99       FT_Select_Charmap( face, face->charmaps[0]->encoding );
 
  101     faces_.push_back( FaceData( face, 
false ) );
 
  108   void Face::init ( 
void )
 
  149     for ( 
unsigned int i = 0; 
i < 
faces_.size(); 
i++ )
 
  151     FT_Done_Face( 
faces_[
i].face_ );
 
  165     faces_.push_back( FaceData( ft_face ) );
 
  176     faces_.push_back( FaceData( face, 
false ) );
 
  289     GLfloat foreground_color[4];
 
  290     foreground_color[
R] = qRed( foreground_rgba ) / 255.;
 
  291     foreground_color[
G] = qGreen( foreground_rgba ) / 255.;
 
  292     foreground_color[
B] = qBlue( foreground_rgba ) / 255.;
 
  293     foreground_color[
A] = qAlpha( foreground_rgba ) / 255.;
 
  313     GLfloat background_color[4];
 
  314     background_color[
R] = qRed( background_rgba ) / 255.;
 
  315     background_color[
G] = qGreen( background_rgba ) / 255.;
 
  316     background_color[
B] = qBlue( background_rgba ) / 255.;
 
  317     background_color[
A] = qAlpha( background_rgba ) / 255.;
 
  354     FT_Matrix rotation_matrix;
 
  357     FT_Vector_Unit( &sinus, (FT_Angle)(angle * 0x10000L) );
 
  359     rotation_matrix.xx = sinus.x;
 
  360     rotation_matrix.xy = -sinus.y;
 
  361     rotation_matrix.yx = sinus.y;
 
  362     rotation_matrix.yy = sinus.x;
 
  364     for ( 
unsigned int i = 0; 
i < 
faces_.size(); 
i++ )
 
  365       FT_Set_Transform( 
faces_[
i].face_, &rotation_matrix, 0 );
 
  368     for ( 
unsigned int i = 0; 
i < 
faces_.size(); 
i++ )
 
  369       FT_Set_Transform( 
faces_[
i].face_, 0, 0 );
 
  378     FT_UInt glyph_index = 0;
 
  380     for ( f = 0; f < 
faces_.size(); f++ ) {
 
  381       glyph_index = FT_Get_Char_Index( 
faces_[f].face_, c );
 
  382       if ( glyph_index != 0 ) 
break;
 
  387       FT_Error error = FT_Load_Glyph( 
faces_[f].face_, glyph_index,
 
  390       if ( error != 0 ) 
return;
 
  407     if ( ( c = *s++ ) != 0 ) {
 
  411       for ( c = *s; c != 0; c = *++s ) {
 
  426     for ( 
char c = *s; 
c != 0; 
c = *++s ) {
 
  430       FT_UInt glyph_index = 0;
 
  432       for ( f = 0; f < 
faces_.size(); f++ ) {
 
  433     glyph_index = FT_Get_Char_Index( 
faces_[f].face_, 
c );
 
  434     if ( glyph_index != 0 ) 
break;
 
  437       if ( glyph_index == 0 ) 
continue;
 
  439       FT_Error error = FT_Load_Glyph( 
faces_[f].face_, glyph_index,
 
  441       if ( error != 0 ) 
continue;
 
  444       error = FT_Get_Glyph( 
faces_[f].face_->glyph, &glyph );
 
  445       if ( error != 0 ) 
continue;
 
  448       FT_Glyph_Get_CBox( glyph, ft_glyph_bbox_unscaled, &ft_bbox );
 
  450       FT_Done_Glyph( glyph );
 
  466     if ( s.length() > 0 ) {
 
  470       for ( 
unsigned int i = 1; 
i < s.length(); 
i++ ) {
 
  483     return measure( format_number( format, number ) );
 
  490     for ( 
unsigned int i = 0; 
i < s.length(); 
i++ ) {
 
  494       FT_UInt glyph_index = 0;
 
  496       for ( f = 0; f < 
faces_.size(); f++ ) {
 
  497     glyph_index = FT_Get_Char_Index( 
faces_[f].face_, s.at( 
i ).unicode() );
 
  498     if ( glyph_index != 0 ) 
break;
 
  501       if ( glyph_index == 0 ) {
 
  505       FT_Error error = FT_Load_Glyph( 
faces_[f].face_, glyph_index,
 
  507       if ( error != 0 ) 
continue;
 
  510       error = FT_Get_Glyph( 
faces_[f].face_->glyph, &glyph );
 
  511       if ( error != 0 ) 
continue;
 
  514       FT_Glyph_Get_CBox( glyph, ft_glyph_bbox_unscaled, &ft_bbox );
 
  516       FT_Done_Glyph( glyph );
 
  519       char_bbox.advance_ = 
faces_[
f].face_->glyph->advance;
 
  530   BBox Face::measure_nominal ( 
const char* s )
 
  535     for ( 
unsigned int f = 0; f < 
faces_.size(); f++ )
 
  536       FT_Set_Transform( 
faces_[f].face_, 0, 0 );
 
  548     FT_Matrix rotation_matrix;
 
  551     FT_Vector_Unit( &sinus, (FT_Angle)(angle * 0x10000L) );
 
  553     rotation_matrix.xx = sinus.x;
 
  554     rotation_matrix.xy = -sinus.y;
 
  555     rotation_matrix.yx = sinus.y;
 
  556     rotation_matrix.yy = sinus.x;
 
  558     for ( 
unsigned int f = 0; f < 
faces_.size(); f++ )
 
  559       FT_Set_Transform( 
faces_[f].face_, &rotation_matrix, 0 );
 
  567   BBox Face::measure_nominal ( 
const QString& s )
 
  572     for ( 
unsigned int f = 0; f < 
faces_.size(); f++ )
 
  573       FT_Set_Transform( 
faces_[f].face_, 0, 0 );
 
  585     FT_Matrix rotation_matrix;
 
  588     FT_Vector_Unit( &sinus, (FT_Angle)(angle * 0x10000L) );
 
  590     rotation_matrix.xx = sinus.x;
 
  591     rotation_matrix.xy = -sinus.y;
 
  592     rotation_matrix.yx = sinus.y;
 
  593     rotation_matrix.yy = sinus.x;
 
  595     for ( 
unsigned int f = 0; f < 
faces_.size(); f++ )
 
  596       FT_Set_Transform( 
faces_[f].face_, &rotation_matrix, 0 );
 
  606   QString Face::format_number ( 
const QString& format, 
double number )
 
  613     QRegExp format_regexp(
"((?:[^%]|%%)*)(%[0-9]*\\.?[0-9]*[efgp])?((?:[^%]|%%)*)");
 
  614      format_regexp.search( format );
 
  616     QStringList list = format_regexp.capturedTexts();
 
  618     QStringList::Iterator it = list.begin();
 
  620     it = list.remove( it ); 
 
  622     if ( it == list.end() ) 
return QString::null; 
 
  626     QString prefix, value_format, postfix;
 
  629     if ( !(*it).isEmpty() )
 
  634     if ( it != list.end() ) {
 
  635       if ( !(*it).isEmpty() ) {
 
  637     QRegExp specifier_regexp( 
"([0-9]*)\\.?([0-9]*)([efgp])" );
 
  638     (void)specifier_regexp.search( *it );
 
  639     QStringList specifier_list = specifier_regexp.capturedTexts();
 
  641     QStringList::Iterator sit = specifier_list.begin();
 
  643     sit = specifier_list.remove( sit );
 
  645     int width = (*sit).toInt();
 
  647     int precision = (*sit).toInt();
 
  650     type = (*sit).at(0).latin1();
 
  653     if ( type == 
'e' || type == 
'f' || type == 
'g' )
 
  654       value_format = QString( 
"%1" ).arg( number, width, type, precision );
 
  658     else if ( type == 
'p' ) {
 
  660       if ( fabs( number ) < 1./256. )
 
  667           value_format = QString::number( a );
 
  671         int b = (int)rint( 256. * fabs( number - a ) );
 
  676           value_format = QString::number( rint( number ) );
 
  681           for ( ; ( b & 0x1 ) == 0; b >>= 1, c >>= 1 );
 
  684           QString numerator = QString::number( b );
 
  685           for ( uint 
i = 0; 
i < numerator.length(); 
i++ ) {
 
  686         numerator.at(
i) = QChar( numerator.at(
i).unicode() -
 
  687                      QChar(
'0').unicode() +
 
  690           value_format += numerator;
 
  691           value_format += QChar( 0xE00a ); 
 
  693           QString denominator = QString::number( c );
 
  694           for ( uint 
i = 0; 
i < denominator.length(); 
i++ ) {
 
  695         denominator.at(
i) = QChar( denominator.at(
i).unicode() -
 
  696                        QChar(
'0').unicode() +
 
  699           value_format += denominator;
 
  707       if ( it != list.end() && !(*it).isEmpty() )
 
  711     return prefix + value_format + postfix;
 
  721     const char* s_tmp = s;
 
  723     for ( 
char c = *s_tmp; c != 0; c = *++s_tmp ) {
 
  727     GLuint dlist = glGenLists( 1 );
 
  728     glNewList( dlist, GL_COMPILE );
 
  751     for ( 
unsigned int i = 0; 
i < s.length(); 
i++ ) {
 
  755     GLuint dlist = glGenLists( 1 );
 
  756     glNewList( dlist, GL_COMPILE );
 
  786     FT_UInt glyph_index = 0;
 
  788     for ( f = 0; f < 
faces_.size(); f++ ) {
 
  789       glyph_index = FT_Get_Char_Index( 
faces_[f].face_, c );
 
  790       if ( glyph_index != 0 ) 
break;
 
  793     if ( glyph_index == 0 )
 
  817     FT_UInt glyph_index = 0;
 
  819     for ( f = 0; f < 
faces_.size(); f++ ) {
 
  820       glyph_index = FT_Get_Char_Index( 
faces_[f].face_, c.unicode() );
 
  821       if ( glyph_index != 0 ) 
break;
 
  824     if ( glyph_index == 0 )
 
  845     for ( 
char c = *s; c != 0; c = *++s ) {
 
  848     glCallList( *character_display_list );
 
  849     character_display_list++;
 
  867     for ( 
unsigned int i = 0; 
i < s.length(); 
i++ ) {
 
  870     glCallList( *character_display_list );
 
  871     character_display_list++;
 
  889       glCallList( fgi->second );
 
  894     FT_UInt glyph_index = 0;
 
  896     for ( f = 0; f < 
faces_.size(); f++ ) {
 
  897       glyph_index = FT_Get_Char_Index( 
faces_[f].face_, c );
 
  898       if ( glyph_index != 0 ) 
break;
 
  901     if ( glyph_index == 0 )
 
  928       glCallList( fgi->second );
 
  933     FT_UInt glyph_index = 0;
 
  935     for ( f = 0; f < 
faces_.size(); f++ ) {
 
  936       glyph_index = FT_Get_Char_Index( 
faces_[f].face_, c.unicode() );
 
  937       if ( glyph_index != 0 ) {
 
  942     if ( glyph_index == 0 )
 
  964     glTranslatef( x, y, 0. );
 
  969     glRasterPos2i( 0, 0 );
 
  977   void Face::draw ( GLfloat 
x, GLfloat y, GLfloat z, 
unsigned char c )
 
  979     glTranslatef( x, y, z );
 
  984     glRasterPos2i( 0, 0 );
 
  994     glTranslatef( x, y, 0. );
 
  999     glRasterPos2i( 0, 0 );
 
 1007   void Face::draw ( GLfloat 
x, GLfloat y, GLfloat z, QChar c )
 
 1009     glTranslatef( x, y, z );
 
 1014     glRasterPos2i( 0, 0 );
 
 1031       BBox bbox = measure_nominal( s );
 
 1033       GLfloat dx = 0, dy = 0;
 
 1037     dx = -bbox.
x_min_; 
break;
 
 1041     dx = -bbox.
x_max_; 
break;
 
 1047     dy = -bbox.
y_min_; 
break;
 
 1051     dy = -bbox.
y_max_; 
break;
 
 1059       glTranslatef( dx, dy, 0 );
 
 1063     glTranslatef( x, y, 0. );
 
 1068     glRasterPos2i( 0, 0 );
 
 1091       BBox bbox = measure_nominal( s );
 
 1093       GLfloat dx = 0, dy = 0;
 
 1097     dx = -bbox.
x_min_; 
break;
 
 1101     dx = -bbox.
x_max_; 
break;
 
 1107     dy = -bbox.
y_min_; 
break;
 
 1111     dy = -bbox.
y_max_; 
break;
 
 1119       glTranslatef( dx, dy, 0 );
 
 1123     glTranslatef( x, y, z );
 
 1128     glRasterPos2i( 0, 0 );
 
 1143   void Face::draw ( GLfloat 
x, GLfloat y, 
const QString& s )
 
 1152       BBox bbox = measure_nominal( s );
 
 1154       GLfloat dx = 0, dy = 0;
 
 1158     dx = -bbox.
x_min_; 
break;
 
 1162     dx = -bbox.
x_max_; 
break;
 
 1166     dy = -bbox.
y_min_; 
break;
 
 1170     dy = -bbox.
y_max_; 
break;
 
 1176       glTranslatef( dx, dy, 0 );
 
 1180     glTranslatef( x, y, 0. );
 
 1185     glRasterPos2i( 0, 0 );
 
 1199   void Face::draw ( GLfloat x, GLfloat y, GLfloat z, 
const QString& s )
 
 1219     for ( 
unsigned int f = 0; f < 
faces_.size(); f++ )
 
 1220       FT_Set_Transform( 
faces_[f].face_, 0, 0 );
 
 1233     FT_Matrix rotation_matrix;
 
 1236     FT_Vector_Unit( &sinus, (FT_Angle)(angle * 0x10000L) );
 
 1238     rotation_matrix.xx = sinus.x;
 
 1239     rotation_matrix.xy = -sinus.y;
 
 1240     rotation_matrix.yx = sinus.y;
 
 1241     rotation_matrix.yy = sinus.x;
 
 1243     for ( 
unsigned int f = 0; f < 
faces_.size(); f++ )
 
 1244       FT_Set_Transform( 
faces_[f].face_, &rotation_matrix, 0 );
 
 1249       GLfloat dx = 0, dy = 0;
 
 1252     dx = bbox.x_min_; 
break;
 
 1254     dx = ( bbox.x_min_ + bbox.x_max_ ) / 2; 
break;
 
 1256     dx = bbox.x_max_; 
break;
 
 1260     dy = bbox.y_min_; 
break;
 
 1262     dy = ( bbox.y_min_ + bbox.y_max_ ) /2; 
break;
 
 1264     dy = bbox.y_max_; 
break;
 
 1269       GLdouble modelview[16], projection[16];
 
 1271       glGetIntegerv( GL_VIEWPORT, viewport );
 
 1272       glGetDoublev( GL_MODELVIEW_MATRIX, modelview );
 
 1273       glGetDoublev( GL_PROJECTION_MATRIX, projection );
 
 1275       GLdouble x0, y0, z0;
 
 1276       gluUnProject( 0, 0, 0, modelview, projection, viewport, &x0, &y0, &z0 );
 
 1278       GLdouble dx_m, dy_m, dz_m;
 
 1279       gluUnProject( dx, dy, 0., modelview, projection, viewport,&dx_m,&dy_m,&dz_m );
 
 1281       glTranslated( x0-dx_m, y0-dy_m, z0-dz_m );
 
 1284     glTranslatef( x, y, z );
 
 1289     glRasterPos2i( 0, 0 );
 
 1303   void Face::draw ( GLfloat x, GLfloat y, 
const QString& format, 
double number )
 
 1305     draw( x, y, format_number( format, number ) );
 
 1310   void Face::draw ( GLfloat x, GLfloat y, GLfloat z, 
const QString& format,
 
 1313     draw( x, y, z, format_number( format, number ) );
 
 1318     : 
Face( filename, point_size, resolution )
 
 1326     : 
Face( face, point_size, resolution )
 
 1331   void Raster::init ( 
void )
 
 1356     if ( 
faces_[0].face_->height > 0 )
 
 1357       return faces_[0].face_->height / 64.;
 
 1359       return faces_[0].face_->size->metrics.y_ppem;
 
 1367     FT_UInt glyph_index = 0;
 
 1369     for ( f = 0; f < 
faces_.size(); f++ ) {
 
 1370       glyph_index = FT_Get_Char_Index( 
faces_[f].face_, c );
 
 1371       if ( glyph_index != 0 ) 
break;
 
 1374     if ( glyph_index == 0 )
 
 1377     FT_Error error = FT_Load_Glyph( 
faces_[f].face_, glyph_index,
 
 1383     error = FT_Get_Glyph( 
faces_[f].face_->glyph, &glyph );
 
 1388     FT_Glyph_Get_CBox( glyph, ft_glyph_bbox_unscaled, &ft_bbox );
 
 1390     FT_Done_Glyph( glyph );
 
 1401     GLdouble modelview[16], projection[16];
 
 1403     glGetIntegerv( GL_VIEWPORT, viewport );
 
 1404     glGetDoublev( GL_MODELVIEW_MATRIX, modelview );
 
 1405     glGetDoublev( GL_PROJECTION_MATRIX, projection );
 
 1409     GLdouble x0, y0, z0;
 
 1410     gluUnProject( 0., 0., 0., modelview, projection, viewport, &x0, &y0, &z0 );
 
 1413     gluUnProject( bbox.
x_min_, bbox.
y_min_, 0., modelview, projection, viewport,
 
 1418     gluUnProject( bbox.
x_max_, bbox.
y_max_, 0., modelview, projection, viewport,
 
 1438     FT_UInt glyph_index = 0;
 
 1440     for ( f = 0; f < 
faces_.size(); f++ ) {
 
 1441       glyph_index = FT_Get_Char_Index( 
faces_[f].face_, c.unicode() );
 
 1442       if ( glyph_index != 0 ) 
break;
 
 1445     if ( glyph_index == 0 )
 
 1448     FT_Error error = FT_Load_Glyph( 
faces_[f].face_, glyph_index,
 
 1454     error = FT_Get_Glyph( 
faces_[f].face_->glyph, &glyph );
 
 1459     FT_Glyph_Get_CBox( glyph, ft_glyph_bbox_unscaled, &ft_bbox );
 
 1461     FT_Done_Glyph( glyph );
 
 1472     GLdouble modelview[16], projection[16];
 
 1474     glGetIntegerv( GL_VIEWPORT, viewport );
 
 1475     glGetDoublev( GL_MODELVIEW_MATRIX, modelview );
 
 1476     glGetDoublev( GL_PROJECTION_MATRIX, projection );
 
 1480     GLdouble x0, y0, z0;
 
 1481     gluUnProject( 0., 0., 0., modelview, projection, viewport, &x0, &y0, &z0 );
 
 1484     gluUnProject( bbox.
x_min_, bbox.
y_min_, 0., modelview, projection, viewport,
 
 1489     gluUnProject( bbox.
x_max_, bbox.
y_max_, 0., modelview, projection, viewport,
 
 1504   GLuint Raster::compileGlyph ( FT_Face face, FT_UInt glyph_index )
 
 1506     GLuint dlist = glGenLists( 1 );
 
 1507     glNewList( dlist, GL_COMPILE );
 
 1516   void Raster::setCharSize ( 
void )
 
 1519     for ( 
unsigned int i = 0; 
i < 
faces_.size(); 
i++ ) {
 
 1520       error = FT_Set_Char_Size( 
faces_[
i].face_,
 
 1525       if ( error != 0 ) 
return;
 
 1529       setRotationOffset();
 
 1532   void Raster::setRotationOffset ( 
void )
 
 1544   void Raster::clearCaches ( 
void )
 
 1549       glDeleteLists( fgi->second, 1 );
 
 1556                FT_UInt resolution )
 
 1557     : 
Raster( filename, point_size, resolution )
 
 1561     : 
Raster( face, point_size, resolution )
 
 1567   GLubyte* Monochrome::invertBitmap ( 
const FT_Bitmap& bitmap )
 
 1573     int width = bitmap.width / 8 + ( ( bitmap.width & 7 ) > 0 ? 1 : 0 );
 
 1575     GLubyte* inverse = 
new GLubyte[ bitmap.rows * width ];
 
 1576     GLubyte* inverse_ptr = inverse;
 
 1578     for ( 
int r = 0; r < bitmap.rows; r++ ) {
 
 1580       GLubyte* bitmap_ptr = &bitmap.buffer[bitmap.pitch * ( bitmap.rows - r - 1 )];
 
 1582       for ( 
int p = 0; 
p < width; 
p++ )
 
 1583     *inverse_ptr++ = *bitmap_ptr++;
 
 1589   void Monochrome::renderGlyph ( FT_Face face, FT_UInt glyph_index )
 
 1593     FT_Error error = FT_Load_Glyph( face, glyph_index, FT_LOAD_DEFAULT );
 
 1598     FT_Glyph original_glyph;
 
 1601     error = FT_Get_Glyph( face->glyph, &original_glyph );
 
 1606     error = FT_Glyph_Copy( original_glyph, &glyph );
 
 1608     FT_Done_Glyph( original_glyph );
 
 1627       FT_Matrix rotation_matrix;
 
 1632       rotation_matrix.xx = sinus.x;
 
 1633       rotation_matrix.xy = -sinus.y;
 
 1634       rotation_matrix.yx = sinus.y;
 
 1635       rotation_matrix.yy = sinus.x;
 
 1637       FT_Vector original_offset, rotation_offset;
 
 1639       original_offset.x = ( face->glyph->metrics.width / 2
 
 1640     + face->glyph->metrics.horiBearingX ) / 64 * 0x10000L;
 
 1643       rotation_offset = original_offset;
 
 1645       FT_Vector_Rotate( &rotation_offset,
 
 1648       rotation_offset.x = original_offset.x - rotation_offset.x;
 
 1649       rotation_offset.y = original_offset.y - rotation_offset.y;
 
 1651       rotation_offset.x /= 1024;
 
 1652       rotation_offset.y /= 1024;
 
 1654       error = FT_Glyph_Transform( glyph, &rotation_matrix, &rotation_offset );
 
 1657     error = FT_Glyph_To_Bitmap( &glyph, FT_RENDER_MODE_MONO, 0, 1 );
 
 1660       FT_Done_Glyph( glyph );
 
 1664     FT_BitmapGlyph bitmap_glyph = (FT_BitmapGlyph)glyph;
 
 1670     GLubyte* inverted_bitmap = invertBitmap( bitmap_glyph->bitmap );
 
 1672     glBitmap( bitmap_glyph->bitmap.width, bitmap_glyph->bitmap.rows,
 
 1673           -bitmap_glyph->left,
 
 1674           bitmap_glyph->bitmap.rows - bitmap_glyph->top,
 
 1675           face->glyph->advance.x / 64.,
 
 1676           face->glyph->advance.y / 64.,
 
 1679     FT_Done_Glyph( glyph );
 
 1681     delete[] inverted_bitmap;
 
 1685                FT_UInt resolution )
 
 1686     : 
Raster( filename, point_size, resolution )
 
 1690     : 
Raster( face, point_size, resolution )
 
 1696   GLubyte* Grayscale::invertPixmap ( 
const FT_Bitmap& bitmap )
 
 1698     GLubyte* inverse = 
new GLubyte[ bitmap.rows * bitmap.pitch ];
 
 1699     GLubyte* inverse_ptr = inverse;
 
 1701     for ( 
int r = 0; r < bitmap.rows; r++ ) {
 
 1703       GLubyte* bitmap_ptr = &bitmap.buffer[bitmap.pitch * ( bitmap.rows - r - 1 )];
 
 1705       for ( 
int p = 0; 
p < bitmap.pitch; 
p++ ) {
 
 1706     *inverse_ptr++ = *bitmap_ptr++;
 
 1713   void Grayscale::renderGlyph ( FT_Face face, FT_UInt glyph_index )
 
 1715     FT_Error error = FT_Load_Glyph( face, glyph_index, FT_LOAD_DEFAULT );
 
 1720     FT_Glyph original_glyph;
 
 1723     error = FT_Get_Glyph( face->glyph, &original_glyph );
 
 1725     if ( error != 0 ) 
return;
 
 1727     error = FT_Glyph_Copy( original_glyph, &glyph );
 
 1729     FT_Done_Glyph( original_glyph );
 
 1731     if ( error != 0 ) 
return;
 
 1734       FT_Matrix rotation_matrix;
 
 1739       rotation_matrix.xx = sinus.x;
 
 1740       rotation_matrix.xy = -sinus.y;
 
 1741       rotation_matrix.yx = sinus.y;
 
 1742       rotation_matrix.yy = sinus.x;
 
 1744       FT_Vector original_offset, rotation_offset;
 
 1746       original_offset.x = ( face->glyph->metrics.width / 2
 
 1747     + face->glyph->metrics.horiBearingX ) / 64 * 0x10000L;
 
 1750       rotation_offset = original_offset;
 
 1752       FT_Vector_Rotate( &rotation_offset,
 
 1755       rotation_offset.x = original_offset.x - rotation_offset.x;
 
 1756       rotation_offset.y = original_offset.y - rotation_offset.y;
 
 1758       rotation_offset.x /= 1024;
 
 1759       rotation_offset.y /= 1024;
 
 1761       error = FT_Glyph_Transform( glyph, &rotation_matrix, &rotation_offset );
 
 1764     error = FT_Glyph_To_Bitmap( &glyph, FT_RENDER_MODE_NORMAL, 0, 1 );
 
 1767       FT_Done_Glyph( glyph );
 
 1771     FT_BitmapGlyph bitmap_glyph = (FT_BitmapGlyph)glyph;
 
 1776     GLubyte* inverted_pixmap = invertPixmap( bitmap_glyph->bitmap );
 
 1782     glPushAttrib( GL_PIXEL_MODE_BIT );
 
 1792     glBitmap( 0, 0, 0, 0,
 
 1794           bitmap_glyph->top - bitmap_glyph->bitmap.rows,
 
 1797     glDrawPixels( bitmap_glyph->bitmap.width, bitmap_glyph->bitmap.rows,
 
 1798           GL_LUMINANCE, GL_UNSIGNED_BYTE,
 
 1804     glBitmap( 0, 0, 0, 0,
 
 1805           -bitmap_glyph->left + face->glyph->advance.x / 64.,
 
 1806           bitmap_glyph->bitmap.rows - bitmap_glyph->top +
 
 1807           face->glyph->advance.y / 64.,
 
 1810     FT_Done_Glyph( glyph );
 
 1814     delete[] inverted_pixmap;
 
 1818                FT_UInt resolution )
 
 1819     : 
Raster( filename, point_size, resolution )
 
 1823     : 
Raster( face, point_size, resolution )
 
 1835   GLubyte* Translucent::invertPixmapWithAlpha ( 
const FT_Bitmap& bitmap )
 
 1837     GLubyte* inverse = 
new GLubyte[ 2 * bitmap.rows * bitmap.pitch ];
 
 1838     GLubyte* inverse_ptr = inverse;
 
 1840     for ( 
int r = 0; r < bitmap.rows; r++ ) {
 
 1842       GLubyte* bitmap_ptr = &bitmap.buffer[bitmap.pitch * ( bitmap.rows - r - 1 )];
 
 1844       for ( 
int p = 0; 
p < bitmap.pitch; 
p++ ) {
 
 1845     *inverse_ptr++ = *bitmap_ptr ? 255 : 0;
 
 1846     *inverse_ptr++ = *bitmap_ptr++;
 
 1853   void Translucent::renderGlyph ( FT_Face face, FT_UInt glyph_index )
 
 1855     FT_Error error = FT_Load_Glyph( face, glyph_index, FT_LOAD_DEFAULT );
 
 1860     FT_Glyph original_glyph;
 
 1863     error = FT_Get_Glyph( face->glyph, &original_glyph );
 
 1865     if ( error != 0 ) 
return;
 
 1867     error = FT_Glyph_Copy( original_glyph, &glyph );
 
 1869     FT_Done_Glyph( original_glyph );
 
 1871     if ( error != 0 ) 
return;
 
 1874       FT_Matrix rotation_matrix;
 
 1879       rotation_matrix.xx = sinus.x;
 
 1880       rotation_matrix.xy = -sinus.y;
 
 1881       rotation_matrix.yx = sinus.y;
 
 1882       rotation_matrix.yy = sinus.x;
 
 1884       FT_Vector original_offset, rotation_offset;
 
 1886       original_offset.x = ( face->glyph->metrics.width / 2
 
 1887     + face->glyph->metrics.horiBearingX ) / 64 * 0x10000L;
 
 1890       rotation_offset = original_offset;
 
 1892       FT_Vector_Rotate( &rotation_offset,
 
 1895       rotation_offset.x = original_offset.x - rotation_offset.x;
 
 1896       rotation_offset.y = original_offset.y - rotation_offset.y;
 
 1898       rotation_offset.x /= 1024;
 
 1899       rotation_offset.y /= 1024;
 
 1901       error = FT_Glyph_Transform( glyph, &rotation_matrix, &rotation_offset );
 
 1904     error = FT_Glyph_To_Bitmap( &glyph, FT_RENDER_MODE_NORMAL, 0, 1 );
 
 1907       FT_Done_Glyph( glyph );
 
 1911     FT_BitmapGlyph bitmap_glyph = (FT_BitmapGlyph)glyph;
 
 1918     GLubyte* inverted_pixmap = invertPixmapWithAlpha( bitmap_glyph->bitmap );
 
 1920     glPushAttrib( GL_PIXEL_MODE_BIT );
 
 1933     glBitmap( 0, 0, 0, 0,
 
 1935           bitmap_glyph->top - bitmap_glyph->bitmap.rows,
 
 1938     glDrawPixels( bitmap_glyph->bitmap.width, bitmap_glyph->bitmap.rows,
 
 1939           GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE,
 
 1945     glBitmap( 0, 0, 0, 0,
 
 1946           -bitmap_glyph->left + face->glyph->advance.x / 64.,
 
 1947           bitmap_glyph->bitmap.rows - bitmap_glyph->top +
 
 1948           face->glyph->advance.y / 64.,
 
 1951     FT_Done_Glyph( glyph );
 
 1955     delete[] inverted_pixmap;
 
 1959     : 
Face( filename, point_size, resolution )
 
 1967     : 
Face( face, point_size, resolution )
 
 1972   void Polygonal::init ( 
void )
 
 1992     (GLdouble)( 
faces_.front().face_->units_per_EM * 72 );
 
 1995     (GLdouble)( 
faces_.front().face_->units_per_EM );
 
 2095   void Polygonal::setCharSize ( 
void )
 
 2097     for ( 
unsigned int i = 0; 
i < 
faces_.size(); 
i++ ) {
 
 2098       FT_Error error = FT_Set_Char_Size( 
faces_[
i].face_,
 
 2100                      faces_[
i].face_->units_per_EM * 64,
 
 2103       if ( error != 0 ) 
return;
 
 2107       setRotationOffset();
 
 2110   void Polygonal::setRotationOffset ( 
void )
 
 2129     if ( 
faces_[0].face_->height > 0 )
 
 2131     ( 72. * 
faces_[0].face_->units_per_EM );
 
 2134     ( 72. * 
faces_[0].face_->units_per_EM );
 
 2142     FT_UInt glyph_index = 0;
 
 2144     for ( f = 0; f < 
faces_.size(); f++ ) {
 
 2145       glyph_index = FT_Get_Char_Index( 
faces_[f].face_, c );
 
 2146       if ( glyph_index != 0 ) 
break;
 
 2149     if ( glyph_index == 0 )
 
 2152     FT_Error error = FT_Load_Glyph( 
faces_[f].face_, glyph_index,
 
 2158     error = FT_Get_Glyph( 
faces_[f].face_->glyph, &glyph );
 
 2163     FT_Glyph_Get_CBox( glyph, ft_glyph_bbox_unscaled, &ft_bbox );
 
 2165     FT_Done_Glyph( glyph );
 
 2180     FT_UInt glyph_index = 0;
 
 2182     for ( f = 0; f < 
faces_.size(); f++ ) {
 
 2183       glyph_index = FT_Get_Char_Index( 
faces_[f].face_, c.unicode() );
 
 2184       if ( glyph_index != 0 ) 
break;
 
 2187     if ( glyph_index == 0 )
 
 2190     FT_Error error = FT_Load_Glyph( 
faces_[f].face_, glyph_index,
 
 2196     error = FT_Get_Glyph( 
faces_[f].face_->glyph, &glyph );
 
 2201     FT_Glyph_Get_CBox( glyph, ft_glyph_bbox_unscaled, &ft_bbox );
 
 2203     FT_Done_Glyph( glyph );
 
 2214   GLuint Polygonal::compileGlyph ( FT_Face face, FT_UInt glyph_index )
 
 2216     GLuint dlist = glGenLists( 1 );
 
 2218     glNewList( dlist, GL_COMPILE );
 
 2232       glDeleteLists( fgi->second, 1 );
 
 2239     : 
Polygonal( filename, point_size, resolution )
 
 2247     : 
Polygonal( face, point_size, resolution )
 
 2252   void Outline::init ( 
void )
 
 2254     interface_.move_to = (FT_Outline_MoveTo_Func)moveToCallback;
 
 2255     interface_.line_to = (FT_Outline_LineTo_Func)lineToCallback;
 
 2256     interface_.conic_to = (FT_Outline_ConicTo_Func)conicToCallback;
 
 2257     interface_.cubic_to = (FT_Outline_CubicTo_Func)cubicToCallback;
 
 2265   void Outline::renderGlyph ( FT_Face face, FT_UInt glyph_index )
 
 2267     FT_Error error = FT_Load_Glyph( face, glyph_index, FT_LOAD_DEFAULT );
 
 2274     error = FT_Get_Glyph( face->glyph, (FT_Glyph*)&g );
 
 2283       glTranslatef( ( face->glyph->metrics.width / 2. +
 
 2284               face->glyph->metrics.horiBearingX ) / 64.
 
 2298       glTranslatef( -( face->glyph->metrics.width / 2. +
 
 2299               face->glyph->metrics.horiBearingX ) / 64.
 
 2311     error = FT_Outline_Decompose( &g->outline, &
interface_, 
this );
 
 2313     FT_Done_Glyph( (FT_Glyph)g );
 
 2337   int Outline::moveToCallback ( FT_Vector* to, Outline* outline )
 
 2339     if ( outline->contour_open_ ) {
 
 2343     outline->last_vertex_ = VertexInfo( to,
 
 2344                     outline->colorTess(),
 
 2345                     outline->textureTess() );
 
 2347     glBegin( GL_LINE_LOOP );
 
 2349     outline->contour_open_ = 
true;
 
 2354   int Outline::lineToCallback ( FT_Vector* to, Outline* outline )
 
 2356     outline->last_vertex_ = VertexInfo( to,
 
 2357                     outline->colorTess(),
 
 2358                     outline->textureTess() );
 
 2361     g[
X] = outline->last_vertex_.v_[
X] * outline->vector_scale_;
 
 2362     g[
Y] = outline->last_vertex_.v_[
Y] * outline->vector_scale_;
 
 2369   int Outline::conicToCallback ( FT_Vector* control, FT_Vector* to, Outline* outline )
 
 2373     VertexInfo to_vertex( to, outline->colorTess(), outline->textureTess() );
 
 2374     VertexInfo control_vertex( control, outline->colorTess(), outline->textureTess() );
 
 2376     double b[2], c[2], 
d[2], f[2], df[2], d2f[2];
 
 2381     b[
X] = outline->last_vertex_.v_[
X] - 2 * control_vertex.v_[
X] +
 
 2383     b[
Y] = outline->last_vertex_.v_[
Y] - 2 * control_vertex.v_[
Y] +
 
 2386     c[
X] = -2 * outline->last_vertex_.v_[
X] + 2 * control_vertex.v_[
X];
 
 2387     c[
Y] = -2 * outline->last_vertex_.v_[
Y] + 2 * control_vertex.v_[
Y];
 
 2389     d[
X] = outline->last_vertex_.v_[
X];
 
 2390     d[
Y] = outline->last_vertex_.v_[
Y];
 
 2394     df[
X] = c[
X] * outline->delta_ + b[
X] * outline->delta2_;
 
 2395     df[
Y] = c[
Y] * outline->delta_ + b[
Y] * outline->delta2_;
 
 2396     d2f[
X] = 2 * b[
X] * outline->delta2_;
 
 2397     d2f[
Y] = 2 * b[
Y] * outline->delta2_;
 
 2399     for ( 
unsigned int i = 0; 
i < outline->tessellation_steps_-1; 
i++ ) {
 
 2404       g[
X] = f[
X] * outline->vector_scale_;
 
 2405       g[
Y] = f[
Y] * outline->vector_scale_;
 
 2407       if ( outline->colorTess() )
 
 2408     glColor4fv( outline->colorTess()->color( g ) );
 
 2416     g[
X] = to_vertex.v_[
X] * outline->vector_scale_;
 
 2417     g[
Y] = to_vertex.v_[
Y] * outline->vector_scale_;
 
 2419     if ( outline->colorTess() )
 
 2420       glColor4fv( outline->colorTess()->color( g ) );
 
 2424     outline->last_vertex_ = to_vertex;
 
 2429   int Outline::cubicToCallback ( FT_Vector* control1, FT_Vector* control2,
 
 2430                  FT_Vector* to, Outline* outline )
 
 2434     VertexInfo to_vertex( to, outline->colorTess(), outline->textureTess() );
 
 2435     VertexInfo control1_vertex( control1, outline->colorTess(), outline->textureTess() );
 
 2436     VertexInfo control2_vertex( control2, outline->colorTess(), outline->textureTess() );
 
 2438     double a[2], b[2], c[2], d[2], f[2], df[2], d2f[2], d3f[2];
 
 2443     a[
X] = -outline->last_vertex_.v_[
X] + 3 * control1_vertex.v_[
X]
 
 2444       -3 * control2_vertex.v_[
X] + to_vertex.v_[
X];
 
 2445     a[
Y] = -outline->last_vertex_.v_[
Y] + 3 * control1_vertex.v_[
Y]
 
 2446       -3 * control2_vertex.v_[
Y] + to_vertex.v_[
Y];
 
 2448     b[
X] = 3 * outline->last_vertex_.v_[
X] - 6 * control1_vertex.v_[
X] +
 
 2449       3 * control2_vertex.v_[
X];
 
 2450     b[
Y] = 3 * outline->last_vertex_.v_[
Y] - 6 * control1_vertex.v_[
Y] +
 
 2451       3 * control2_vertex.v_[
Y];
 
 2453     c[
X] = -3 * outline->last_vertex_.v_[
X] + 3 * control1_vertex.v_[
X];
 
 2454     c[
Y] = -3 * outline->last_vertex_.v_[
Y] + 3 * control1_vertex.v_[
Y];
 
 2456     d[
X] = outline->last_vertex_.v_[
X];
 
 2457     d[
Y] = outline->last_vertex_.v_[
Y];
 
 2461     df[
X] = c[
X] * outline->delta_ + b[
X] * outline->delta2_
 
 2462       + a[
X] * outline->delta3_;
 
 2463     df[
Y] = c[
Y] * outline->delta_ + b[
Y] * outline->delta2_
 
 2464       + a[
Y] * outline->delta3_;
 
 2465     d2f[
X] = 2 * b[
X] * outline->delta2_ + 6 * a[
X] * outline->delta3_;
 
 2466     d2f[
Y] = 2 * b[
Y] * outline->delta2_ + 6 * a[
Y] * outline->delta3_;
 
 2467     d3f[
X] = 6 * a[
X] * outline->delta3_;
 
 2468     d3f[
Y] = 6 * a[
Y] * outline->delta3_;
 
 2470     for ( 
unsigned int i = 0; 
i < outline->tessellation_steps_-1; 
i++ ) {
 
 2475       g[
X] = f[
X] * outline->vector_scale_;
 
 2476       g[
Y] = f[
Y] * outline->vector_scale_;
 
 2478       if ( outline->colorTess() )
 
 2479     glColor4fv( outline->colorTess()->color( g ) );
 
 2489     g[
X] = to_vertex.v_[
X] * outline->vector_scale_;
 
 2490     g[
Y] = to_vertex.v_[
Y] * outline->vector_scale_;
 
 2492     if ( outline->colorTess() )
 
 2493       glColor4fv( outline->colorTess()->color( g ) );
 
 2497     outline->last_vertex_ = to_vertex;
 
 2503     : 
Polygonal( filename, point_size, resolution )
 
 2511     : 
Polygonal( face, point_size, resolution )
 
 2516   void Filled::init ( 
void )
 
 2520     interface_.move_to = (FT_Outline_MoveTo_Func)moveToCallback;
 
 2521     interface_.line_to = (FT_Outline_LineTo_Func)lineToCallback;
 
 2522     interface_.conic_to = (FT_Outline_ConicTo_Func)conicToCallback;
 
 2523     interface_.cubic_to = (FT_Outline_CubicTo_Func)cubicToCallback;
 
 2527     tess_obj_ = gluNewTess();
 
 2529     gluTessCallback( (GLUtriangulatorObj *)tess_obj_, GLU_TESS_VERTEX, (
GLUTessCallback)vertexCallback );
 
 2530     gluTessCallback( (GLUtriangulatorObj *)tess_obj_, GLU_TESS_BEGIN, (
GLUTessCallback)beginCallback );
 
 2531     gluTessCallback( (GLUtriangulatorObj *)tess_obj_, GLU_TESS_END, (
GLUTessCallback)endCallback );
 
 2532     gluTessCallback( (GLUtriangulatorObj *)tess_obj_, GLU_TESS_COMBINE_DATA, (
GLUTessCallback)combineCallback );
 
 2533     gluTessCallback( (GLUtriangulatorObj *)tess_obj_, GLU_TESS_ERROR, (
GLUTessCallback)errorCallback );
 
 2538     gluDeleteTess( tess_obj_ );
 
 2543     FT_Error error = FT_Load_Glyph( face, glyph_index, FT_LOAD_DEFAULT );
 
 2550     error = FT_Get_Glyph( face->glyph, (FT_Glyph*)&g );
 
 2559       glTranslatef( ( face->glyph->metrics.width / 2. +
 
 2560               face->glyph->metrics.horiBearingX ) / 64.
 
 2574       glTranslatef( -( face->glyph->metrics.width / 2. +
 
 2575               face->glyph->metrics.horiBearingX ) / 64.
 
 2584       glNormal3f( 0., 0., 1. );
 
 2587       glNormal3f( 0., 0., -1. );
 
 2590     glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
 
 2594     gluTessBeginPolygon( tess_obj_, 
this );
 
 2601     error = FT_Outline_Decompose( &g->outline, &
interface_, 
this );
 
 2603     FT_Done_Glyph( (FT_Glyph)g );
 
 2608       gluTessEndContour( tess_obj_ );
 
 2610     gluTessEndPolygon( tess_obj_ );
 
 2625     for ( 
VILI vili = extra_vertices_.begin(); vili != extra_vertices_.end(); vili++ )
 
 2628     extra_vertices_.clear();
 
 2636   int Filled::moveToCallback ( FT_Vector* to, 
Filled* filled )
 
 2639       gluTessEndContour( filled->tess_obj_ );
 
 2644     gluTessBeginContour( filled->tess_obj_ );
 
 2651   int Filled::lineToCallback ( FT_Vector* to, Filled* filled )
 
 2653     filled->last_vertex_ = VertexInfo( to, filled->colorTess(), filled->textureTess() );
 
 2655     VertexInfo* vertex = 
new VertexInfo( to, filled->colorTess(), filled->textureTess() );
 
 2657     vertex->v_[
X] *= filled->vector_scale_;
 
 2658     vertex->v_[
Y] *= filled->vector_scale_;
 
 2660     gluTessVertex( filled->tess_obj_, vertex->v_, vertex );
 
 2662     filled->vertices_.push_back( vertex );
 
 2667   int Filled::conicToCallback ( FT_Vector* control, FT_Vector* to, Filled* filled )
 
 2671     VertexInfo to_vertex( to, filled->colorTess(), filled->textureTess() );
 
 2672     VertexInfo control_vertex( control, filled->colorTess(), filled->textureTess() );
 
 2674     double b[2], c[2], d[2], f[2], df[2], d2f[2];
 
 2676     b[
X] = filled->last_vertex_.v_[
X] - 2 * control_vertex.v_[
X] +
 
 2678     b[
Y] = filled->last_vertex_.v_[
Y] - 2 * control_vertex.v_[
Y] +
 
 2681     c[
X] = -2 * filled->last_vertex_.v_[
X] + 2 * control_vertex.v_[
X];
 
 2682     c[
Y] = -2 * filled->last_vertex_.v_[
Y] + 2 * control_vertex.v_[
Y];
 
 2684     d[
X] = filled->last_vertex_.v_[
X];
 
 2685     d[
Y] = filled->last_vertex_.v_[
Y];
 
 2689     df[
X] = c[
X] * filled->delta_ + b[
X] * filled->delta2_;
 
 2690     df[
Y] = c[
Y] * filled->delta_ + b[
Y] * filled->delta2_;
 
 2691     d2f[
X] = 2 * b[
X] * filled->delta2_;
 
 2692     d2f[
Y] = 2 * b[
Y] * filled->delta2_;
 
 2694     for ( 
unsigned int i = 0; 
i < filled->tessellation_steps_-1; 
i++ ) {
 
 2699       VertexInfo* vertex = 
new VertexInfo( f, filled->colorTess(), filled->textureTess() );
 
 2701       vertex->v_[
X] *= filled->vector_scale_;
 
 2702       vertex->v_[
Y] *= filled->vector_scale_;
 
 2704       filled->vertices_.push_back( vertex );
 
 2706       gluTessVertex( filled->tess_obj_, vertex->v_, vertex );
 
 2712     VertexInfo* vertex = 
new VertexInfo( to, filled->colorTess(), filled->textureTess() );
 
 2714     vertex->v_[
X] *= filled->vector_scale_;
 
 2715     vertex->v_[
Y] *= filled->vector_scale_;
 
 2717     filled->vertices_.push_back( vertex );
 
 2719     gluTessVertex( filled->tess_obj_, vertex->v_, vertex );
 
 2721     filled->last_vertex_ = to_vertex;
 
 2726   int Filled::cubicToCallback ( FT_Vector* control1, FT_Vector* control2,
 
 2727                 FT_Vector* to, Filled* filled )
 
 2731     VertexInfo to_vertex( to, filled->colorTess(), filled->textureTess() );
 
 2732     VertexInfo control1_vertex( control1, filled->colorTess(), filled->textureTess() );
 
 2733     VertexInfo control2_vertex( control2, filled->colorTess(), filled->textureTess() );
 
 2735     double a[2], b[2], c[2], d[2], f[2], df[2], d2f[2], d3f[2];
 
 2737     a[
X] = -filled->last_vertex_.v_[
X] + 3 * control1_vertex.v_[
X]
 
 2738       -3 * control2_vertex.v_[
X] + to_vertex.v_[
X];
 
 2739     a[
Y] = -filled->last_vertex_.v_[
Y] + 3 * control1_vertex.v_[
Y]
 
 2740       -3 * control2_vertex.v_[
Y] + to_vertex.v_[
Y];
 
 2742     b[
X] = 3 * filled->last_vertex_.v_[
X] - 6 * control1_vertex.v_[
X] +
 
 2743       3 * control2_vertex.v_[
X];
 
 2744     b[
Y] = 3 * filled->last_vertex_.v_[
Y] - 6 * control1_vertex.v_[
Y] +
 
 2745       3 * control2_vertex.v_[
Y];
 
 2747     c[
X] = -3 * filled->last_vertex_.v_[
X] + 3 * control1_vertex.v_[
X];
 
 2748     c[
Y] = -3 * filled->last_vertex_.v_[
Y] + 3 * control1_vertex.v_[
Y];
 
 2750     d[
X] = filled->last_vertex_.v_[
X];
 
 2751     d[
Y] = filled->last_vertex_.v_[
Y];
 
 2755     df[
X] = c[
X] * filled->delta_ + b[
X] * filled->delta2_
 
 2756       + a[
X] * filled->delta3_;
 
 2757     df[
Y] = c[
Y] * filled->delta_ + b[
Y] * filled->delta2_
 
 2758       + a[
Y] * filled->delta3_;
 
 2759     d2f[
X] = 2 * b[
X] * filled->delta2_ + 6 * a[
X] * filled->delta3_;
 
 2760     d2f[
Y] = 2 * b[
Y] * filled->delta2_ + 6 * a[
Y] * filled->delta3_;
 
 2761     d3f[
X] = 6 * a[
X] * filled->delta3_;
 
 2762     d3f[
Y] = 6 * a[
Y] * filled->delta3_;
 
 2764     for ( 
unsigned int i = 0; 
i < filled->tessellation_steps_-1; 
i++ ) {
 
 2769       VertexInfo* vertex = 
new VertexInfo( f, filled->colorTess(), filled->textureTess() );
 
 2771       vertex->v_[
X] *= filled->vector_scale_;
 
 2772       vertex->v_[
Y] *= filled->vector_scale_;
 
 2774       filled->vertices_.push_back( vertex );
 
 2776       gluTessVertex( filled->tess_obj_, vertex->v_, vertex );
 
 2784     VertexInfo* vertex = 
new VertexInfo( to, filled->colorTess(), filled->textureTess() );
 
 2786     vertex->v_[
X] *= filled->vector_scale_;
 
 2787     vertex->v_[
Y] *= filled->vector_scale_;
 
 2789     filled->vertices_.push_back( vertex );
 
 2791     gluTessVertex( filled->tess_obj_, vertex->v_, vertex );
 
 2793     filled->last_vertex_ = to_vertex;
 
 2798   void Filled::vertexCallback ( VertexInfo* vertex )
 
 2800     if ( vertex->color_tess_ != 0 )
 
 2801       glColor4fv( vertex->color_tess_->color( vertex->v_ ) );
 
 2803     if ( vertex->texture_tess_ != 0 )
 
 2804       glTexCoord2fv( vertex->texture_tess_->texCoord( vertex->v_ ) );
 
 2806     glVertex3dv( vertex->v_ );
 
 2809   void Filled::beginCallback ( GLenum which )
 
 2814   void Filled::endCallback ( 
void )
 
 2819   void Filled::combineCallback ( GLdouble coords[3], 
void* vertex_data[4],
 
 2820                  GLfloat weight[4], 
void** out_data,
 
 2826     VertexInfo* vertex = 
new VertexInfo( coords );
 
 2828     filled->extraVertices().push_back( vertex );
 
 2831   void Filled::errorCallback ( GLenum error_code )
 
 2833     std::cerr << 
"hmm. error during tessellation?:" << gluErrorString( error_code ) << std::endl;
 
 2836 #ifndef OGLFT_NO_SOLID 
 2837   Solid::Solid ( 
const char* filename, 
float point_size, FT_UInt resolution )
 
 2838     : 
Filled( filename, point_size, resolution )
 
 2846     : 
Filled( face, point_size, resolution )
 
 2851   void Solid::init ( 
void )
 
 2853     interface_.move_to = (FT_Outline_MoveTo_Func)moveToCallback;
 
 2854     interface_.line_to = (FT_Outline_LineTo_Func)lineToCallback;
 
 2855     interface_.conic_to = (FT_Outline_ConicTo_Func)conicToCallback;
 
 2856     interface_.cubic_to = (FT_Outline_CubicTo_Func)cubicToCallback;
 
 2857     interface_.shift = 0;
 
 2858     interface_.delta = 0;
 
 2861     extrusion_.depth_ = 1.;
 
 2862     extrusion_.up_[
X] = 0.;
 
 2863     extrusion_.up_[
Y] = 1.;
 
 2864     extrusion_.up_[
Z] = 0.;
 
 2865     extrusion_.n_polyline_pts_ = N_POLYLINE_PTS;
 
 2867     assign( extrusion_.point_array_[0], 0., 0., extrusion_.depth_ + 1. );
 
 2868     assign( extrusion_.point_array_[1], 0., 0., extrusion_.depth_ );
 
 2869     assign( extrusion_.point_array_[2], 0., 0., 0. );
 
 2870     assign( extrusion_.point_array_[3], 0., 0., -1. );
 
 2874     gleSetJoinStyle( TUBE_JN_RAW | TUBE_CONTOUR_CLOSED | TUBE_NORM_EDGE );
 
 2884     if ( depth > 0. && depth != extrusion_.depth_ ) {
 
 2885       extrusion_.depth_ = 
depth;
 
 2887       assign( extrusion_.point_array_[0], 0., 0., extrusion_.depth_ + 1. );
 
 2888       assign( extrusion_.point_array_[1], 0., 0., extrusion_.depth_ );
 
 2894   void Solid::renderGlyph ( FT_Face face, FT_UInt glyph_index )
 
 2896     FT_Error error = FT_Load_Glyph( face, glyph_index, FT_LOAD_DEFAULT );
 
 2903     error = FT_Get_Glyph( face->glyph, (FT_Glyph*)&g );
 
 2913       glTranslatef( ( face->glyph->metrics.width / 2. +
 
 2914               face->glyph->metrics.horiBearingX ) / 64.
 
 2928       glTranslatef( -( face->glyph->metrics.width / 2. +
 
 2929               face->glyph->metrics.horiBearingX ) / 64.
 
 2941     if ( g->outline.flags & FT_OUTLINE_REVERSE_FILL ) {
 
 2942       extrusion_.normal_sign_.x_ = -1;
 
 2943       extrusion_.normal_sign_.y_ = 1;
 
 2946       extrusion_.normal_sign_.x_ = 1;
 
 2947       extrusion_.normal_sign_.y_ = -1;
 
 2953     error = FT_Outline_Decompose( &g->outline, &interface_, 
this );
 
 2955     FT_Done_Glyph( (FT_Glyph)g );
 
 2960       extrusion_.contour_normals_.push_back( extrusion_.contour_normals_.front() );
 
 2962       gleExtrusion( extrusion_.contour_.size(),
 
 2963             &extrusion_.contour_.begin()->p_,
 
 2964             &extrusion_.contour_normals_[1].p_,
 
 2966             extrusion_.n_polyline_pts_,
 
 2967             extrusion_.point_array_,
 
 2970       extrusion_.contour_.clear();
 
 2971       extrusion_.contour_normals_.clear();
 
 3004   int Solid::moveToCallback ( FT_Vector* to, Solid* solid )
 
 3006     if ( solid->contour_open_ ) {
 
 3018       solid->extrusion_.contour_normals_.
 
 3019     push_back( solid->extrusion_.contour_normals_.front() );
 
 3021       gleExtrusion( solid->extrusion_.contour_.size(),
 
 3022             &solid->extrusion_.contour_.begin()->p_,
 
 3023             &solid->extrusion_.contour_normals_[1].p_,
 
 3024             solid->extrusion_.up_,
 
 3025             solid->extrusion_.n_polyline_pts_,
 
 3026             solid->extrusion_.point_array_,
 
 3029       solid->extrusion_.contour_.clear();
 
 3030       solid->extrusion_.contour_normals_.clear();
 
 3033     solid->last_vertex_ = VertexInfo( to, solid->colorTess(), solid->textureTess() );
 
 3035     solid->contour_open_ = 
true;
 
 3040   int Solid::lineToCallback ( FT_Vector* to, Solid* solid )
 
 3042     VertexInfo vertex( to, solid->colorTess(), solid->textureTess() );
 
 3044     VertexInfo normal( solid->extrusion_.normal_sign_.y_ *
 
 3045                ( vertex.v_[
Y] - solid->last_vertex_.v_[
Y] ),
 
 3046                solid->extrusion_.normal_sign_.x_ *
 
 3047                ( vertex.v_[
X] - solid->last_vertex_.v_[
X] ) );
 
 3049     solid->last_vertex_ = vertex;
 
 3051     vertex.v_[
X] *= solid->vector_scale_;
 
 3052     vertex.v_[
Y] *= solid->vector_scale_;
 
 3056     solid->extrusion_.contour_.push_back( vertex );
 
 3057     solid->extrusion_.contour_normals_.push_back( normal );
 
 3062   int Solid::conicToCallback ( FT_Vector* control, FT_Vector* to, Solid* solid )
 
 3066     VertexInfo to_vertex( to, solid->colorTess(), solid->textureTess() );
 
 3067     VertexInfo control_vertex( control, solid->colorTess(), solid->textureTess() );
 
 3069     double b[2], c[2], d[2], f[2], df[2], d2f[2];
 
 3071     b[
X] = solid->last_vertex_.v_[
X] - 2 * control_vertex.v_[
X] +
 
 3073     b[
Y] = solid->last_vertex_.v_[
Y] - 2 * control_vertex.v_[
Y] +
 
 3076     c[
X] = -2 * solid->last_vertex_.v_[
X] + 2 * control_vertex.v_[
X];
 
 3077     c[
Y] = -2 * solid->last_vertex_.v_[
Y] + 2 * control_vertex.v_[
Y];
 
 3079     d[
X] = solid->last_vertex_.v_[
X];
 
 3080     d[
Y] = solid->last_vertex_.v_[
Y];
 
 3084     df[
X] = c[
X] * solid->delta_ + b[
X] * solid->delta2_;
 
 3085     df[
Y] = c[
Y] * solid->delta_ + b[
Y] * solid->delta2_;
 
 3086     d2f[
X] = 2 * b[
X] * solid->delta2_;
 
 3087     d2f[
Y] = 2 * b[
Y] * solid->delta2_;
 
 3089     for ( 
unsigned int i = 0; 
i < solid->tessellation_steps_-1; 
i++ ) {
 
 3094       VertexInfo vertex( f, solid->colorTess(), solid->textureTess() );
 
 3096       VertexInfo normal( solid->extrusion_.normal_sign_.y_ * df[
Y],
 
 3097              solid->extrusion_.normal_sign_.x_ * df[
X] );
 
 3099       vertex.v_[
X] *= solid->vector_scale_;
 
 3100       vertex.v_[
Y] *= solid->vector_scale_;
 
 3104       solid->extrusion_.contour_.push_back( vertex );
 
 3105       solid->extrusion_.contour_normals_.push_back( normal );
 
 3111     VertexInfo vertex( to, solid->colorTess(), solid->textureTess() );
 
 3113     VertexInfo normal( solid->extrusion_.normal_sign_.y_ * df[
Y],
 
 3114                solid->extrusion_.normal_sign_.x_ * df[
X] );
 
 3116     vertex.v_[
X] *= solid->vector_scale_;
 
 3117     vertex.v_[
Y] *= solid->vector_scale_;
 
 3121     solid->extrusion_.contour_.push_back( vertex );
 
 3122     solid->extrusion_.contour_normals_.push_back( normal );
 
 3124     solid->last_vertex_ = to_vertex;
 
 3129   int Solid::cubicToCallback ( FT_Vector* control1, FT_Vector* control2,
 
 3130                    FT_Vector* to, Solid* solid )
 
 3134     VertexInfo to_vertex( to, solid->colorTess(), solid->textureTess() );
 
 3135     VertexInfo control1_vertex( control1, solid->colorTess(), solid->textureTess() );
 
 3136     VertexInfo control2_vertex( control2, solid->colorTess(), solid->textureTess() );
 
 3138     double a[2], b[2], c[2], d[2], f[2], df[2], d2f[2], d3f[2];
 
 3140     a[
X] = -solid->last_vertex_.v_[
X] + 3 * control1_vertex.v_[
X]
 
 3141       -3 * control2_vertex.v_[
X] + to_vertex.v_[
X];
 
 3142     a[
Y] = -solid->last_vertex_.v_[
Y] + 3 * control1_vertex.v_[
Y]
 
 3143       -3 * control2_vertex.v_[
Y] + to_vertex.v_[
Y];
 
 3145     b[
X] = 3 * solid->last_vertex_.v_[
X] - 6 * control1_vertex.v_[
X] +
 
 3146       3 * control2_vertex.v_[
X];
 
 3147     b[
Y] = 3 * solid->last_vertex_.v_[
Y] - 6 * control1_vertex.v_[
Y] +
 
 3148       3 * control2_vertex.v_[
Y];
 
 3150     c[
X] = -3 * solid->last_vertex_.v_[
X] + 3 * control1_vertex.v_[
X];
 
 3151     c[
Y] = -3 * solid->last_vertex_.v_[
Y] + 3 * control1_vertex.v_[
Y];
 
 3153     d[
X] = solid->last_vertex_.v_[
X];
 
 3154     d[
Y] = solid->last_vertex_.v_[
Y];
 
 3158     df[
X] = c[
X] * solid->delta_ + b[
X] * solid->delta2_
 
 3159       + a[
X] * solid->delta3_;
 
 3160     df[
Y] = c[
Y] * solid->delta_ + b[
Y] * solid->delta2_
 
 3161       + a[
Y] * solid->delta3_;
 
 3162     d2f[
X] = 2 * b[
X] * solid->delta2_ + 6 * a[
X] * solid->delta3_;
 
 3163     d2f[
Y] = 2 * b[
Y] * solid->delta2_ + 6 * a[
Y] * solid->delta3_;
 
 3164     d3f[
X] = 6 * a[
X] * solid->delta3_;
 
 3165     d3f[
Y] = 6 * a[
Y] * solid->delta3_;
 
 3167     for ( 
unsigned int i = 0; 
i < solid->tessellation_steps_-1; 
i++ ) {
 
 3172       VertexInfo vertex( f, solid->colorTess(), solid->textureTess() );
 
 3174       VertexInfo normal( solid->extrusion_.normal_sign_.y_ * df[
Y],
 
 3175              solid->extrusion_.normal_sign_.x_ * df[
X] );
 
 3177       vertex.v_[
X] *= solid->vector_scale_;
 
 3178       vertex.v_[
Y] *= solid->vector_scale_;
 
 3182       solid->extrusion_.contour_.push_back( vertex );
 
 3183       solid->extrusion_.contour_normals_.push_back( normal );
 
 3191     VertexInfo vertex( to, solid->colorTess(), solid->textureTess() );
 
 3193     VertexInfo normal( solid->extrusion_.normal_sign_.y_ * df[
Y],
 
 3194                solid->extrusion_.normal_sign_.x_ * df[
X] );
 
 3196     vertex.v_[
X] *= solid->vector_scale_;
 
 3197     vertex.v_[
Y] *= solid->vector_scale_;
 
 3201     solid->extrusion_.contour_.push_back( vertex );
 
 3202     solid->extrusion_.contour_normals_.push_back( normal );
 
 3204     solid->last_vertex_ = to_vertex;
 
 3208 #endif // OGLFT_NO_SOLID 
 3211     : 
Face( filename, point_size, resolution )
 
 3219     : 
Face( face, point_size, resolution )
 
 3224   void Texture::init ( 
void )
 
 3288   void Texture::setCharSize ( 
void )
 
 3290     for ( 
unsigned int f = 0; f < 
faces_.size(); f++ ) {
 
 3291       FT_Error error = FT_Set_Char_Size( 
faces_[f].face_,
 
 3301       setRotationOffset();
 
 3304   void Texture::setRotationOffset ( 
void )
 
 3321     FT_UInt glyph_index = 0;
 
 3323     for ( f = 0; f < 
faces_.size(); f++ ) {
 
 3324       glyph_index = FT_Get_Char_Index( 
faces_[f].face_, c );
 
 3325       if ( glyph_index != 0 ) 
break;
 
 3328     if ( glyph_index == 0 )
 
 3331     FT_Error error = FT_Load_Glyph( 
faces_[f].face_, glyph_index,
 
 3337     error = FT_Get_Glyph( 
faces_[f].face_->glyph, &glyph );
 
 3342     FT_Glyph_Get_CBox( glyph, ft_glyph_bbox_unscaled, &ft_bbox );
 
 3344     FT_Done_Glyph( glyph );
 
 3354     if ( 
faces_[0].face_->height > 0 )
 
 3355       return faces_[0].face_->height / 64.;
 
 3357       return faces_[0].face_->size->metrics.y_ppem;
 
 3367     FT_UInt glyph_index = 0;
 
 3369     for ( f = 0; f < 
faces_.size(); f++ ) {
 
 3370       glyph_index = FT_Get_Char_Index( 
faces_[f].face_, c.unicode() );
 
 3371       if ( glyph_index != 0 ) 
break;
 
 3374     if ( glyph_index == 0 )
 
 3377     FT_Error error = FT_Load_Glyph( 
faces_[f].face_, glyph_index,
 
 3383     error = FT_Get_Glyph( 
faces_[f].face_->glyph, &glyph );
 
 3388     FT_Glyph_Get_CBox( glyph, ft_glyph_bbox_unscaled, &ft_bbox );
 
 3390     FT_Done_Glyph( glyph );
 
 3398   GLuint Texture::compileGlyph ( FT_Face face, FT_UInt glyph_index )
 
 3402     GLuint dlist = glGenLists( 1 );
 
 3403     glNewList( dlist, GL_COMPILE );
 
 3405     renderGlyph( face, glyph_index );
 
 3412   void Texture::renderGlyph ( FT_Face face, FT_UInt glyph_index )
 
 3414     FT_Error error = FT_Load_Glyph( face, glyph_index, FT_LOAD_DEFAULT );
 
 3419     TextureInfo texture_info;
 
 3433     texture_info = texture_object->second;
 
 3435     glBindTexture( GL_TEXTURE_2D, texture_info.texture_name_ );
 
 3439       glTranslatef( ( texture_info.width_ / 2. +
 
 3440               texture_info.left_bearing_ ),
 
 3452       glTranslatef( -( texture_info.width_ / 2. +
 
 3453               texture_info.left_bearing_ ),
 
 3457     glBegin( GL_QUADS );
 
 3459     glTexCoord2i( 0, 0 );
 
 3460     glVertex2f( texture_info.left_bearing_, texture_info.bottom_bearing_ );
 
 3462     glTexCoord2f( texture_info.texture_s_, 0. );
 
 3463     glVertex2f( texture_info.left_bearing_ + texture_info.width_,
 
 3464         texture_info.bottom_bearing_ );
 
 3466     glTexCoord2f( texture_info.texture_s_, texture_info.texture_t_ );
 
 3467     glVertex2f( texture_info.left_bearing_ + texture_info.width_,
 
 3468         texture_info.bottom_bearing_ + texture_info.height_ );
 
 3470     glTexCoord2f( 0., texture_info.texture_t_ );
 
 3471     glVertex2f( texture_info.left_bearing_,
 
 3472         texture_info.bottom_bearing_ + texture_info.height_ );
 
 3481     glTranslatef( texture_info.advance_.x / 64.,
 
 3482           texture_info.advance_.y / 64.,
 
 3486   void Texture::clearCaches ( 
void )
 
 3491       glDeleteLists( fgi->second, 1 );
 
 3499       glDeleteTextures( 1, &fti->second.texture_name_ );
 
 3510     if ( a == 0 ) 
return 1;
 
 3517       else if ( b == 3 ) {
 
 3526     if ( c < a ) c *= 2;
 
 3532                      FT_UInt resolution )
 
 3533     : 
Texture( filename, point_size, resolution )
 
 3537                      FT_UInt resolution )
 
 3538     : 
Texture( face, point_size, resolution )
 
 3548   GLubyte* MonochromeTexture::invertBitmap ( 
const FT_Bitmap& bitmap,
 
 3549                          int* width, 
int* height )
 
 3554     GLubyte* inverse = 
new GLubyte[ ( *width + 7) / 8 * *height ];
 
 3555     GLubyte* inverse_ptr = inverse;
 
 3557     memset( inverse, 0, 
sizeof( GLubyte )*( *width + 7 ) / 8 * *height );
 
 3559     for ( 
int r = 0; r < bitmap.rows; r++ ) {
 
 3561       GLubyte* bitmap_ptr = &bitmap.buffer[bitmap.pitch * ( bitmap.rows - r - 1 )];
 
 3563       for ( 
int p = 0; 
p < bitmap.pitch; 
p++ ) {
 
 3565     *inverse_ptr++ = *bitmap_ptr++;
 
 3568       inverse_ptr += ( ( *width + 7 ) / 8 - bitmap.pitch );
 
 3577   void MonochromeTexture::bindTexture ( FT_Face face, FT_UInt glyph_index )
 
 3586     FT_Error error = FT_Load_Glyph( face, glyph_index, FT_LOAD_DEFAULT );
 
 3591     error = FT_Render_Glyph( face->glyph, FT_RENDER_MODE_MONO );
 
 3596     TextureInfo texture_info;
 
 3598     glGenTextures( 1, &texture_info.texture_name_ );
 
 3599     glBindTexture( GL_TEXTURE_2D, texture_info.texture_name_ );
 
 3600     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
 
 3601     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
 
 3602     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
 
 3603     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
 
 3608     GLubyte* inverted_pixmap =
 
 3609       invertBitmap( face->glyph->bitmap, &width, &height );
 
 3616     glPixelMapfv( GL_PIXEL_MAP_I_TO_R, 2, red_map );
 
 3617     glPixelMapfv( GL_PIXEL_MAP_I_TO_G, 2, green_map );
 
 3618     glPixelMapfv( GL_PIXEL_MAP_I_TO_B, 2, blue_map );
 
 3619     glPixelMapfv( GL_PIXEL_MAP_I_TO_A, 2, alpha_map );
 
 3621     glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, width, height,
 
 3622           0, GL_COLOR_INDEX, GL_BITMAP, inverted_pixmap );
 
 3625     texture_info.left_bearing_ = face->glyph->bitmap_left;
 
 3626     texture_info.bottom_bearing_ = -( face->glyph->bitmap.rows
 
 3627                     - face->glyph->bitmap_top );
 
 3628     texture_info.width_ = face->glyph->bitmap.width;
 
 3629     texture_info.height_ = face->glyph->bitmap.rows;
 
 3630     texture_info.texture_s_ = (GLfloat)texture_info.width_ / width;
 
 3631     texture_info.texture_t_ = (GLfloat)texture_info.height_ / 
height;
 
 3632     texture_info.advance_ = face->glyph->advance;
 
 3636     delete[] inverted_pixmap;
 
 3640                        FT_UInt resolution )
 
 3641     : 
Texture( filename, point_size, resolution )
 
 3645                        FT_UInt resolution )
 
 3646     : 
Texture( face, point_size, resolution )
 
 3655   GLubyte* GrayscaleTexture::invertPixmap ( 
const FT_Bitmap& bitmap,
 
 3656                         int* width, 
int* height )
 
 3661     GLubyte* inverse = 
new GLubyte[ *width * *
height ];
 
 3662     GLubyte* inverse_ptr = inverse;
 
 3664     for ( 
int r = 0; r < bitmap.rows; r++ ) {
 
 3666       GLubyte* bitmap_ptr = &bitmap.buffer[bitmap.pitch * ( bitmap.rows - r - 1 )];
 
 3668       for ( 
int p = 0; 
p < bitmap.width; 
p++ ) {
 
 3669     *inverse_ptr++ = *bitmap_ptr++;
 
 3672       inverse_ptr += ( *width - bitmap.pitch );
 
 3680   void GrayscaleTexture::bindTexture ( FT_Face face, FT_UInt glyph_index )
 
 3689     FT_Error error = FT_Load_Glyph( face, glyph_index, FT_LOAD_DEFAULT );
 
 3694     error = FT_Render_Glyph( face->glyph, FT_RENDER_MODE_NORMAL );
 
 3699     TextureInfo texture_info;
 
 3701     glGenTextures( 1, &texture_info.texture_name_ );
 
 3702     glBindTexture( GL_TEXTURE_2D, texture_info.texture_name_ );
 
 3703     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
 
 3704     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
 
 3705     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
 
 3706     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
 
 3711     GLubyte* inverted_pixmap =
 
 3712       invertPixmap( face->glyph->bitmap, &width, &height );
 
 3714     glPushAttrib( GL_PIXEL_MODE_BIT );
 
 3724     glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, width, height,
 
 3725           0, GL_LUMINANCE, GL_UNSIGNED_BYTE, inverted_pixmap );
 
 3729     texture_info.left_bearing_ = face->glyph->bitmap_left;
 
 3730     texture_info.bottom_bearing_ = -( face->glyph->bitmap.rows
 
 3731                       - face->glyph->bitmap_top );
 
 3732     texture_info.width_ = face->glyph->bitmap.width;
 
 3733     texture_info.height_ = face->glyph->bitmap.rows;
 
 3734     texture_info.texture_s_ = (GLfloat)texture_info.width_ / width;
 
 3735     texture_info.texture_t_ = (GLfloat)texture_info.height_ / 
height;
 
 3736     texture_info.advance_ = face->glyph->advance;
 
 3740     delete[] inverted_pixmap;
 
 3744                        FT_UInt resolution )
 
 3745     : 
Texture( filename, point_size, resolution )
 
 3749                        FT_UInt resolution )
 
 3750     : 
Texture( face, point_size, resolution )
 
 3759   GLubyte* TranslucentTexture::invertPixmap ( 
const FT_Bitmap& bitmap,
 
 3760                         int* width, 
int* height )
 
 3765     GLubyte* inverse = 
new GLubyte[ 2 * *width * *
height ];
 
 3766     GLubyte* inverse_ptr = inverse;
 
 3768     for ( 
int r = 0; r < bitmap.rows; r++ ) {
 
 3770       GLubyte* bitmap_ptr = &bitmap.buffer[bitmap.pitch * ( bitmap.rows - r - 1 )];
 
 3772       for ( 
int p = 0; 
p < bitmap.width; 
p++ ) {
 
 3773     *inverse_ptr++ = 0xff;
 
 3774     *inverse_ptr++ = *bitmap_ptr++;
 
 3777       inverse_ptr += 2 * ( *width - bitmap.pitch );
 
 3785   void TranslucentTexture::bindTexture ( FT_Face face, FT_UInt glyph_index )
 
 3794     FT_Error error = FT_Load_Glyph( face, glyph_index, FT_LOAD_DEFAULT );
 
 3799     error = FT_Render_Glyph( face->glyph, FT_RENDER_MODE_NORMAL );
 
 3804     TextureInfo texture_info;
 
 3806     glGenTextures( 1, &texture_info.texture_name_ );
 
 3807     glBindTexture( GL_TEXTURE_2D, texture_info.texture_name_ );
 
 3808     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
 
 3809     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
 
 3810     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
 
 3811     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
 
 3816     GLubyte* inverted_pixmap =
 
 3817       invertPixmap( face->glyph->bitmap, &width, &height );
 
 3819     glPushAttrib( GL_PIXEL_MODE_BIT );
 
 3829     glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, width, height,
 
 3830           0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, inverted_pixmap );
 
 3835     texture_info.left_bearing_ = face->glyph->bitmap_left;
 
 3836     texture_info.bottom_bearing_ = -( face->glyph->bitmap.rows
 
 3837                     - face->glyph->bitmap_top );
 
 3838     texture_info.width_ = face->glyph->bitmap.width;
 
 3839     texture_info.height_ = face->glyph->bitmap.rows;
 
 3840     texture_info.texture_s_ = (GLfloat)texture_info.width_ / width;
 
 3841     texture_info.texture_t_ = (GLfloat)texture_info.height_ / 
height;
 
 3842     texture_info.advance_ = face->glyph->advance;
 
 3846     delete[] inverted_pixmap;
 
double height(void) const 
 
Baseline alignment of text (default) 
 
Render text as a filled polygons. 
 
float x_max_
The right-most position at which "ink" appears. 
 
Monochrome(const char *filename, float point_size=12, FT_UInt resolution=100)
 
void setForegroundColor(GLfloat red=0.0, GLfloat green=0.0, GLfloat blue=0.0, GLfloat alpha=1.0)
 
BBox measure(unsigned char c)
 
void setTessellationSteps(unsigned int tessellation_steps)
 
The Blue component of a color. 
 
DisplayLists::const_iterator DLCI
A convenience definition of an iterator for display list vectors. 
 
void setCharacterRotationX(GLfloat character_rotation_x)
 
The Z component of space. 
 
enum VerticalJustification vertical_justification_
PHIGS-like vertical positioning of text. 
 
Face(const char *filename, float point_size=12, FT_UInt resolution=100)
 
GlyphTexObjs::iterator GTOI
 
float y_min_
the bottom-most position at which "ink" appears. 
 
~TranslucentTexture(void)
 
This is the base class of the polygonal styles: outline, filled and solid. 
 
virtual BBox measure(unsigned char c)=0
 
Filled(const char *filename, float point_size=12, FT_UInt resolution=100)
 
GLfloat foreground_color_[4]
 
virtual void setCharSize(void)=0
 
virtual void clearCaches(void)=0
 
The Red component of a color. 
 
MonochromeTexture(const char *filename, float point_size=12, FT_UInt resolution=100)
 
float y_max_
The top-most position at which "ink" appears. 
 
void(* GLUTessCallback)(void)
Callback from GLU tessellation routines. 
 
Right justified alignment of text. 
 
The FreeType library instance. 
 
GlyphDLists::iterator GDLI
 
bool advance_
Does rendering text affect the MODELVIEW matrix? 
 
virtual GLuint compileGlyph(FT_Face face, FT_UInt glyph_index)=0
 
void setResolution(FT_UInt resolution)
 
float point_size_
Nominal point size. 
 
enum GlyphCompileMode compile_mode_
Glyph display list creation mode. 
 
Left justified justification of text. 
 
FT_Face rotation_reference_face_
The rotation reference character could be in any face. 
 
std::vector< FaceData > faces_
 
GLuint compile(const char *s)
 
float dx_
Advance increment in the X direction. 
 
GLfloat rotation_offset_y_
 
static FT_Library & instance(void)
 
Raster(const char *filename, float point_size=12, FT_UInt resolution=100)
 
struct OGLFT::Polygonal::@57 character_rotation_
Angle of rotation of characters relative to text orientation. 
 
virtual void bindTexture(FT_Face face, FT_UInt glyph_index)=0
 
Descender alignment of text. 
 
BBox measure(unsigned char c)
 
double height(void) const 
 
FT_UInt resolution_
Display resolution in pixels per inch. 
 
moTypes MOint moText moParamIndex moParamReference int iRow int int i int i
 
float dy_
Advance increment in the Y direction. 
 
bool valid_
Did a font load OK? 
 
Solid(const char *filename, float point_size=12, FT_UInt resolution=100)
 
Compile new glyphs when seen for the first time. 
 
FT_UInt rotation_reference_glyph_
 
TextureTess * textureTess(void) const 
 
BBox measure(unsigned char c)
 
virtual void renderGlyph(FT_Face face, FT_UInt glyph_index)=0
 
void setCharacterRotationY(GLfloat character_rotation_y)
 
The Alpha (or transparency) of a color. 
 
enum HorizontalJustification horizontal_justification_
PHIGS-like horizontal positioning of text. 
 
Polygonal(const char *filename, float point_size=12, FT_UInt resolution=100)
 
void setCharacterRotationZ(GLfloat character_rotation_z)
 
TextureTess * texture_tess_
 
unsigned int tessellation_steps_
 
GlyphDLists::const_iterator GDLCI
 
GLfloat background_color_[4]
Background color (what modes would use this?) 
 
GlyphTexObjs glyph_texobjs_
Cache of defined glyph texture objects. 
 
void setDepth(double depth)
 
static const unsigned int DEFAULT_TESSELLATION_STEPS
 
GLfloat string_rotation_
Rotate an entire string in the Z plane. 
 
The Y component of space. 
 
Advance advance_
The (total) advancement. 
 
The X component of space. 
 
void setCharacterRotationZ(GLfloat character_rotation_z)
 
ColorTess * colorTess(void) const 
 
VertexInfoList::iterator VILI
A convenience definition of the iterator over the list of vertices. 
 
void setCharacterRotationZ(GLfloat character_rotation_z)
 
virtual void setRotationOffset(void)=0
 
GrayscaleTexture(const char *filename, float point_size=12, FT_UInt resolution=100)
 
virtual BBox measureRaw(const char *s)
 
Centered alignment of text. 
 
void setBackgroundColor(GLfloat red=1.0, GLfloat green=1.0, GLfloat blue=1.0, GLfloat alpha=0.0)
 
A face (aka font) used to render text with OpenGL. 
 
Ascender justification of text. 
 
void setPointSize(float point_size)
 
The Green component of a color. 
 
Grayscale(const char *filename, float point_size=12, FT_UInt resolution=100)
 
Center justified alignment of text. 
 
bool addAuxiliaryFace(const char *filename)
 
GlyphDLists glyph_dlists_
Cache of defined glyph display lists. 
 
void setCharacterRotationX(GLfloat character_rotation_x)
 
double height(void) const 
 
All of OGLFT C++ objects are in this namespace. 
 
GLfloat character_rotation_z_
 
Texture(const char *filename, float point_size=12, FT_UInt resolution=100)
 
TranslucentTexture(const char *filename, float point_size=12, FT_UInt resolution=100)
 
GlyphTexObjs::const_iterator GTOCI
 
float x_min_
The left-most position at which "ink" appears. 
 
void setColorTess(ColorTess *color_tess)
 
struct OGLFT::Texture::@60 character_rotation_
Angle of rotation of characters relative to text orientation. 
 
void setTextureTess(TextureTess *texture_tess)
 
Natural origin alignment of text (default) 
 
void setStringRotation(GLfloat string_rotation)
 
This is the base class of the texture style. 
 
void renderGlyph(FT_Face face, FT_UInt glyph_index)
 
unsigned int nearestPowerCeil(unsigned int a)
 
Translucent(const char *filename, float point_size=12, FT_UInt resolution=100)
 
void setCharacterRotationReference(unsigned char c)
 
Outline(const char *filename, float point_size=12, FT_UInt resolution=100)
 
FT_Outline_Funcs interface_
Callbacks for FreeType glyph decomposition into outlines. 
 
void setCharacterRotationY(GLfloat character_rotation_y)
 
DisplayLists character_display_lists_