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++ )
150 if (
faces_[i].free_on_exit_ )
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 );
992 void Face::draw ( GLfloat x, GLfloat y, QChar c )
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 );
1082 void Face::draw ( GLfloat x, GLfloat y, GLfloat z,
const char* s )
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.
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_