/* * demo3.cpp: Third Demo of the OGLFT library * Copyright (C) 2002 lignum Computing, Inc. * $Id$ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include "OGLFT.h" #include "vignette.h" #include "vignette.moc" #include "Demo3UnicodeExample.h" #include "Demo3UnicodeExample2.h" class Vignette0 : public Vignette { static const unsigned int FRAME_COUNT = 32; static const unsigned int FRAME_RATE = 16; const char* text_; OGLFT::Filled* face_; public: Vignette0 ( const char* text, const char* fontfile ) : text_( text ) { face_ = new OGLFT::Filled( fontfile, 288, 75 ); face_->setForegroundColor( 0., .5, .75 ); face_->setHorizontalJustification( OGLFT::Face::CENTER ); } ~Vignette0 ( void ) { // std::cout << "destructing Vignette 0" << std::endl; delete face_; } unsigned int frame_count ( void ) { return FRAME_COUNT; } unsigned int frame_rate ( void ) { return FRAME_RATE; } void init ( void ) { std::cout << "Vignette 0" << std::endl; } void draw ( unsigned int frame_number ) { glPushMatrix(); glTranslatef( 0., 0., - 1. - ( FRAME_COUNT - frame_number ) ); face_->draw( 0., 0., text_ ); glPopMatrix(); } void finish ( void ) { } }; class Vignette1 : public Vignette { static const unsigned int FRAME_COUNT = 49; static const unsigned int FRAME_RATE = 16; const char* text_; OGLFT::Filled* face_; public: Vignette1 ( const char* text, const char* fontfile ) : text_( text ) { face_ = new OGLFT::Filled( fontfile, 288, 75 ); face_->setForegroundColor( 0., .5, .75 ); face_->setHorizontalJustification( OGLFT::Face::CENTER ); } ~Vignette1 ( void ) { // std::cout << "destructing Vignette 1" << std::endl; delete face_; } unsigned int frame_count ( void ) { return FRAME_COUNT; } unsigned int frame_rate ( void ) { return FRAME_RATE; } void init ( void ) { std::cout << "Vignette 1" << std::endl; } void draw ( unsigned int frame_number ) { glPushMatrix(); glTranslatef( 0., 0., - 1. - ( FRAME_COUNT - frame_number ) ); glRotatef( frame_number * 15., 0., 0., 1. ); face_->draw( 0., 0., text_ ); glPopMatrix(); } void finish ( void ) { } }; class Vignette2 : public Vignette { static const unsigned int FRAME_COUNT = 60; static const unsigned int FRAME_RATE = 12; const char* text_; OGLFT::Filled* face_; GLfloat x_; public: Vignette2 ( const char* text, const char* fontfile ) : text_( text ) { face_ = new OGLFT::Filled( fontfile, 32, 75 ); face_->setCompileMode( OGLFT::Face::IMMEDIATE ); face_->setForegroundColor( 0., .5, .75 ); face_->setHorizontalJustification( OGLFT::Face::RIGHT ); face_->setCharacterRotationZ( 30. ); x_ = -250.; } ~Vignette2 ( void ) { // std::cout << "destructing Vignette 2" << std::endl; delete face_; } unsigned int frame_count ( void ) { return FRAME_COUNT; } unsigned int frame_rate ( void ) { return FRAME_RATE; } void init ( void ) { std::cout << "Vignette 2" << std::endl; } void draw ( unsigned int frame_number ) { glPushMatrix(); if ( frame_number <= 48 ) { x_ += 10.; face_->setCharacterRotationZ( face_->characterRotationZ() - 30. ); } else x_ = 250.; glTranslatef( x_, 0., 0. ); face_->draw( 0., 0., text_ ); glPopMatrix(); } void view ( GLdouble left, GLdouble right, GLdouble bottom, GLdouble top ) { glMatrixMode( GL_PROJECTION ); glLoadIdentity(); glOrtho( left, right, bottom, top, -250., 250. ); glMatrixMode( GL_MODELVIEW ); } void finish ( void ) { } }; class Vignette3 : public Vignette { static const unsigned int FRAME_COUNT = 36; static const unsigned int FRAME_RATE = 16; const char* text_; OGLFT::Filled* face_; public: Vignette3 ( const char* text, const char* fontfile ) : text_( text ) { face_ = new OGLFT::Filled( fontfile, 32, 75 ); face_->setCompileMode( OGLFT::Face::IMMEDIATE ); face_->setForegroundColor( 0., .5, .75 ); face_->setHorizontalJustification( OGLFT::Face::CENTER ); face_->setCharacterRotationY( 90. ); } ~Vignette3 ( void ) { // std::cout << "destructing Vignette 3" << std::endl; delete face_; } unsigned int frame_count ( void ) { return FRAME_COUNT; } unsigned int frame_rate ( void ) { return FRAME_RATE; } void init ( void ) { std::cout << "Vignette 3" << std::endl; } void view ( GLdouble left, GLdouble right, GLdouble bottom, GLdouble top ) { glMatrixMode( GL_PROJECTION ); glLoadIdentity(); glOrtho( left, right, bottom, top, -250., 250. ); glMatrixMode( GL_MODELVIEW ); } void draw ( unsigned int frame_number ) { glPushMatrix(); glTranslatef( 0., 0., - 1. - ( FRAME_COUNT - frame_number ) ); face_->setCharacterRotationY( face_->characterRotationY() + 10. ); face_->draw( 0., 0., text_ ); glPopMatrix(); } void finish ( void ) { } }; class Vignette4 : public Vignette { static const unsigned int FRAME_COUNT = 82; static const unsigned int FRAME_RATE = 10; const char* text_; #ifndef OGLFT_NO_SOLID OGLFT::Solid* face_; #else OGLFT::Filled* face_; #endif OGLFT::Translucent* annotation_; QImage* bg00b; QImage* bg01; QImage* bg10b; QImage* bg11; GLuint bg_textures_[6]; public: Vignette4 ( const char* text, const char* fontfile ) : text_( text ) { #ifndef OGLFT_NO_SOLID face_ = new OGLFT::Solid( fontfile, 120, 75 ); face_->setDepth( 24. ); #else face_ = new OGLFT::Filled( fontfile, 120, 75 ); #endif face_->setCompileMode( OGLFT::Face::IMMEDIATE ); face_->setForegroundColor( 1., 1., 0. ); face_->setHorizontalJustification( OGLFT::Face::CENTER ); face_->setVerticalJustification( OGLFT::Face::MIDDLE ); face_->setCharacterRotationY( 0. ); face_->setCharacterRotationZ( 0. ); annotation_ = new OGLFT::Translucent( fontfile, 10, 75 ); annotation_->setForegroundColor( 1., 1., 0., 0.5 ); annotation_->setHorizontalJustification( OGLFT::Face::RIGHT ); annotation_->setVerticalJustification( OGLFT::Face::BOTTOM ); bg00b = new QImage( "background00b.png" ); bg01 = new QImage( "background01.png" ); bg10b = new QImage( "background10b.png" ); bg11 = new QImage( "background11.png" ); } ~Vignette4 ( void ) { // std::cout << "destructing Vignette 4" << std::endl; glDeleteTextures( 6, bg_textures_ ); delete bg00b; delete bg01; delete bg10b; delete bg11; delete face_; } unsigned int frame_count ( void ) { return FRAME_COUNT; } unsigned int frame_rate ( void ) { return FRAME_RATE; } void init ( void ) { std::cout << "Vignette 4" << std::endl; glPixelStorei( GL_UNPACK_ALIGNMENT, 1 ); glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); glGenTextures( 6, bg_textures_ ); glBindTexture( GL_TEXTURE_2D, bg_textures_[1] ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, bg01->width(), bg01->height(), 0, GL_BGRA, GL_UNSIGNED_BYTE, bg01->bits() ); glBindTexture( GL_TEXTURE_2D, bg_textures_[3] ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, bg11->width(), bg11->height(), 0, GL_BGRA, GL_UNSIGNED_BYTE, bg11->bits() ); glBindTexture( GL_TEXTURE_2D, bg_textures_[4] ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, bg00b->width(), bg00b->height(), 0, GL_BGRA, GL_UNSIGNED_BYTE, bg00b->bits() ); glBindTexture( GL_TEXTURE_2D, bg_textures_[5] ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, bg10b->width(), bg10b->height(), 0, GL_BGRA, GL_UNSIGNED_BYTE, bg10b->bits() ); glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); glEnable( GL_LIGHT0 ); } void view ( GLdouble left, GLdouble right, GLdouble bottom, GLdouble top ) { glMatrixMode( GL_PROJECTION ); glLoadIdentity(); glOrtho( left, right, bottom, top, -250., 250. ); glMatrixMode( GL_MODELVIEW ); GLint viewport[4]; GLdouble matrix[16]; glGetIntegerv( GL_VIEWPORT, viewport ); glGetDoublev( GL_PROJECTION_MATRIX, matrix ); glGetDoublev( GL_MODELVIEW_MATRIX, matrix ); } void draw ( unsigned int frame_number ) { glPushMatrix(); GLubyte alpha = 255; if ( frame_number < FRAME_COUNT ) alpha = (GLubyte)( 255. * (GLfloat)frame_number/(FRAME_COUNT) ); glEnable( GL_BLEND ); glBegin( GL_QUADS ); glColor4ub( 128, 164, 212, alpha ); glVertex2f( -250., 0. ); glVertex2f( 250., 0. ); glColor4ub( 101, 142, 198, alpha ); glVertex2f( 250., 250. ); glVertex2f( -250., 250. ); glEnd(); glDisable( GL_BLEND ); glEnable( GL_LIGHTING ); glEnable( GL_DEPTH_TEST ); glEnable( GL_COLOR_MATERIAL ); GLfloat y; if ( frame_number <= 72 ) { face_->setCharacterRotationX( face_->characterRotationX() + 25. ); face_->setCharacterRotationY( face_->characterRotationY() + 25. ); #if 0 face_->setCharacterRotationZ( face_->characterRotationZ() - 12.5 ); #endif y = 3.5*frame_number - 55.; } else y = 3.5*72 - 55.; face_->draw( 0., y, text_ ); if ( frame_number < FRAME_COUNT ) { // Fade in the background GLdouble f = (GLfloat)frame_number/(FRAME_COUNT); glColor4f( f, f, f, 1. ); } else glColor4f( 1., 1., 1., 1. ); glDisable( GL_LIGHTING ); glDisable( GL_DEPTH_TEST ); glDisable( GL_COLOR_MATERIAL ); glEnable( GL_TEXTURE_2D ); glEnable( GL_BLEND ); glBindTexture( GL_TEXTURE_2D, bg_textures_[1] ); glBegin( GL_QUADS ); glTexCoord2f( 0., 1. ); glVertex2f( -250., -250. ); glTexCoord2f( 1., 1. ); glVertex2f( 0., -250. ); glTexCoord2f( 1., 0. ); glVertex2f( 0., 0. ); glTexCoord2f( 0., 0. ); glVertex2f( -250., 0. ); glEnd(); glBindTexture( GL_TEXTURE_2D, bg_textures_[3] ); glBegin( GL_QUADS ); glTexCoord2f( 0., 1. ); glVertex2f( 0., -250. ); glTexCoord2f( 1., 1. ); glVertex2f( 250., -250. ); glTexCoord2f( 1., 0. ); glVertex2f( 250., 0. ); glTexCoord2f( 0., 0. ); glVertex2f( 0., 0. ); glEnd(); glBindTexture( GL_TEXTURE_2D, bg_textures_[4] ); glBegin( GL_QUADS ); glTexCoord2f( 0., 1. ); glVertex2f( -250., 0. ); glTexCoord2f( 1., 1. ); glVertex2f( 0., 0. ); glTexCoord2f( 1., 0. ); glVertex2f( 0., 250. ); glTexCoord2f( 0., 0. ); glVertex2f( -250., 250. ); glEnd(); glBindTexture( GL_TEXTURE_2D, bg_textures_[5] ); glBegin( GL_QUADS ); glTexCoord2f( 0., 1. ); glVertex2f( 0., 0. ); glTexCoord2f( 1., 1. ); glVertex2f( 250., 0. ); glTexCoord2f( 1., 0. ); glVertex2f( 250., 250. ); glTexCoord2f( 0., 0. ); glVertex2f( 0., 250. ); glEnd(); glDisable( GL_TEXTURE_2D ); glDisable( GL_BLEND ); glEnable( GL_BLEND ); annotation_->draw( 250., -250., "Hoodoos @ Bryce Canyon National Park, Utah, USA" ); glDisable( GL_BLEND ); glPopMatrix(); } void finish ( void ) { } }; class Vignette5 : public Vignette { static const unsigned int FRAME_COUNT = 124; static const unsigned int FRAME_RATE = 8; const char* text_; OGLFT::Monochrome* monochrome_; OGLFT::Grayscale* grayscale_; OGLFT::Translucent* translucent_; OGLFT::Outline* outline_; OGLFT::Filled* filled_; #ifndef OGLFT_NO_SOLID OGLFT::Solid* solid_; #else OGLFT::Monochrome* solid_; #endif OGLFT::MonochromeTexture* monochrome_texture_; OGLFT::GrayscaleTexture* grayscale_texture_; OGLFT::TranslucentTexture* translucent_texture_; public: Vignette5 ( const char* text, const char* fontfile ) : text_( text ) { int point_size = 20; monochrome_ = new OGLFT::Monochrome( fontfile, point_size, 75 ); monochrome_->setHorizontalJustification( OGLFT::Face::CENTER ); monochrome_->setForegroundColor( 1., 0., 0., 1. ); grayscale_ = new OGLFT::Grayscale( fontfile, point_size, 75 ); grayscale_->setHorizontalJustification( OGLFT::Face::CENTER ); grayscale_->setForegroundColor( 0., 0., .5, 1. ); grayscale_->setBackgroundColor( 0., 1., 1., 1. ); translucent_ = new OGLFT::Translucent( fontfile, point_size, 75 ); translucent_->setHorizontalJustification( OGLFT::Face::CENTER ); translucent_->setForegroundColor( 0., .5, 0., 1. ); outline_ = new OGLFT::Outline( fontfile, point_size, 75 ); outline_->setForegroundColor( 1., 1., 0., 1. ); outline_->setHorizontalJustification( OGLFT::Face::CENTER ); filled_ = new OGLFT::Filled( fontfile, point_size, 75 ); filled_->setForegroundColor( .5, 0., 1., 1. ); filled_->setHorizontalJustification( OGLFT::Face::CENTER ); #ifndef OGLFT_NO_SOLID solid_ = new OGLFT::Solid( fontfile, point_size, 75 ); solid_->setDepth( 10. ); solid_->setCharacterRotationX( 25. ); solid_->setCharacterRotationY( 25. ); solid_->setTessellationSteps( 3 ); #else solid_ = new OGLFT::Monochrome( fontfile, point_size, 75 ); #endif solid_->setHorizontalJustification( OGLFT::Face::CENTER ); solid_->setForegroundColor( 1., .5, 0., 1. ); monochrome_texture_ = new OGLFT::MonochromeTexture( fontfile, point_size, 75 ); monochrome_texture_->setHorizontalJustification( OGLFT::Face::CENTER ); monochrome_texture_->setForegroundColor( 0., .5, .75, 1. ); grayscale_texture_ = new OGLFT::GrayscaleTexture( fontfile, point_size, 75 ); grayscale_texture_->setHorizontalJustification( OGLFT::Face::CENTER ); grayscale_texture_->setForegroundColor( 0.9, .65, .9, 1. ); grayscale_texture_->setBackgroundColor( 0.5, .5, .75, 0.3 ); translucent_texture_ = new OGLFT::TranslucentTexture( fontfile, point_size, 75 ); translucent_texture_->setHorizontalJustification( OGLFT::Face::CENTER ); translucent_texture_->setForegroundColor( 0.75, 1., .75, 1. ); } ~Vignette5 ( void ) { // std::cout << "destructing Vignette 5" << std::endl; delete monochrome_; delete grayscale_; delete translucent_; delete outline_; delete filled_; delete solid_; delete monochrome_texture_; delete grayscale_texture_; delete translucent_texture_; } unsigned int frame_count ( void ) { return FRAME_COUNT; } unsigned int frame_rate ( void ) { return FRAME_RATE; } void init ( void ) { std::cout << "Vignette 5" << std::endl; glPixelStorei( GL_UNPACK_ALIGNMENT, 1 ); glEnable( GL_RASTER_POSITION_UNCLIPPED_IBM ); glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); glEnable( GL_LIGHT0 ); } void view ( GLdouble left, GLdouble right, GLdouble bottom, GLdouble top ) { glMatrixMode( GL_PROJECTION ); glLoadIdentity(); glOrtho( left, right, bottom, top, -250., 250. ); glMatrixMode( GL_MODELVIEW ); } void draw ( unsigned int frame_number ) { GLdouble y; glPushMatrix(); if ( frame_number <= 12 ) y = -240. + 490. * ( 12 - frame_number ) / 12; else y = -240.; monochrome_->draw( 0., y, "Draw text as monochrome bitmaps" ); if ( frame_number >= 12 ) { if ( frame_number <= 24 ) y = -190. + 440. * ( 24 - frame_number ) / 12; else y = -190.; grayscale_->draw( 0., y, "Draw text as antialiased, grayscale pixmaps" ); } if ( frame_number >= 24 ) { if ( frame_number <= 36 ) y = -140. + 390. * ( 36 - frame_number ) / 12; else y = -140.; glEnable( GL_BLEND ); translucent_->draw( 0., y, "Draw text as antialiased, blended pixmaps" ); glDisable( GL_BLEND ); } if ( frame_number >= 36 ) { if ( frame_number <= 48 ) y = -90. + 340. * ( 48 - frame_number ) / 12; else y = -90.; outline_->draw( 0., y, "Draw text as line segments" ); } if ( frame_number >= 48 ) { if ( frame_number <= 60 ) y = -40. + 290. * ( 60 - frame_number ) / 12; else y = -40.; filled_->draw( 0., y, "Draw text as filled polygons" ); } if ( frame_number >= 60 ) { if ( frame_number <= 72 ) y = 10. + 240. * ( 72 - frame_number ) / 12; else y = 10.; #ifndef OGLFT_NO_SOLID glEnable( GL_LIGHTING ); glEnable( GL_DEPTH_TEST ); glEnable( GL_COLOR_MATERIAL ); solid_->draw( 0., y, "Draw text as solid with GLE" ); glDisable( GL_COLOR_MATERIAL ); glDisable( GL_DEPTH_TEST ); glDisable( GL_LIGHTING ); #else solid_->draw( 0., y, "" ); #endif } glEnable( GL_TEXTURE_2D ); glEnable( GL_BLEND ); if ( frame_number >= 72 ) { if ( frame_number <= 84 ) y = 60. + 190. * ( 84 - frame_number ) / 12; else y = 60.; monochrome_texture_->draw( 0., y, "Draw text as monochrome texture maps" ); } if ( frame_number >= 84 ) { if ( frame_number <= 96 ) y = 110. + 140. * ( 96 - frame_number ) / 12; else y = 110.; grayscale_texture_->draw( 0., y, "Draw text as antialiased, grayscale texture maps" ); } if ( frame_number >= 96 ) { if ( frame_number <= 108 ) y = 160. + 90. * ( 108 - frame_number ) / 12; else y = 160.; translucent_texture_->draw( 0., y, "Draw text as antialiased, blended texture maps" ); } glDisable( GL_BLEND ); glDisable( GL_TEXTURE_2D ); glPopMatrix(); } void finish ( void ) { } }; class Vignette6 : public Vignette { static const unsigned int FRAME_COUNT = 48; static const unsigned int FRAME_RATE = 12; const char* text_; OGLFT::Filled* face_; class MyColorTess : public OGLFT::ColorTess { public: QColor hsv_; GLfloat colors_[4]; int phase_; MyColorTess () { hsv_.setHsv( 0, 255, 255 ); colors_[OGLFT::R] = hsv_.red() / 255.; colors_[OGLFT::G] = hsv_.green() / 255.; colors_[OGLFT::B] = hsv_.blue() / 255.; colors_[OGLFT::A] = 1.; phase_ = 0; } void setPhase ( int phase ) { phase_ = phase; } int phase ( void ) const { return phase_; } }; class MyColorTessVertical : public MyColorTess { public: GLfloat* color ( GLdouble* p ) { int hue = (int)( 360. * p[OGLFT::Y] / 36. + phase_ ) % 360; if ( hue < 0 ) hue += 360; hsv_.setHsv( hue, 255, 255 ); colors_[OGLFT::R] = hsv_.red() / 255.; colors_[OGLFT::G] = hsv_.green() / 255.; colors_[OGLFT::B] = hsv_.blue() / 255.; return colors_; } }; class MyColorTessHorizontal : public MyColorTess { public: GLfloat* color ( GLdouble* p ) { int hue = (int)( 360. * p[OGLFT::X] / 36. + phase_ ) % 360; if ( hue < 0 ) hue += 360; hsv_.setHsv( hue, 255, 255 ); colors_[OGLFT::R] = hsv_.red() / 255.; colors_[OGLFT::G] = hsv_.green() / 255.; colors_[OGLFT::B] = hsv_.blue() / 255.; return colors_; } }; MyColorTessVertical color_tess_v_; MyColorTessHorizontal color_tess_h_; public: Vignette6 ( const char* text, const char* fontfile ) : text_( text ) { face_ = new OGLFT::Filled( fontfile, 72, 75 ); face_->setForegroundColor( 0., .5, .75 ); face_->setHorizontalJustification( OGLFT::Face::CENTER ); face_->setVerticalJustification( OGLFT::Face::MIDDLE ); face_->setTessellationSteps( 3 ); face_->setCompileMode( OGLFT::Face::IMMEDIATE ); } ~Vignette6 ( void ) { // std::cout << "destructing Vignette 6" << std::endl; delete face_; } unsigned int frame_count ( void ) { return FRAME_COUNT; } unsigned int frame_rate ( void ) { return FRAME_RATE; } void init ( void ) { std::cout << "Vignette 6" << std::endl; } void view ( GLdouble left, GLdouble right, GLdouble bottom, GLdouble top ) { glMatrixMode( GL_PROJECTION ); glLoadIdentity(); glOrtho( left, right, bottom, top, -250., 250. ); glMatrixMode( GL_MODELVIEW ); } void draw ( unsigned int /*frame_number*/ ) { glPushMatrix(); face_->setColorTess( &color_tess_h_ ); face_->draw( 0., 72., "Apply a per" ); face_->draw( 0., 0., "vertex color" ); face_->draw( 0., -72., "function" ); glPopMatrix(); color_tess_h_.setPhase( color_tess_h_.phase() + 15 ); color_tess_v_.setPhase( color_tess_v_.phase() + 15 ); } void finish ( void ) { } }; class Vignette7 : public Vignette { static const unsigned int FRAME_COUNT = 48; static const unsigned int FRAME_RATE = 12; const char* text_; OGLFT::Filled* face_; QImage* image_; GLuint texture_; class MyTextureTess : public OGLFT::TextureTess { int phase_; GLfloat texCoords_[2]; public: MyTextureTess () { texCoords_[0] = texCoords_[1] = 0.; phase_ = 0; } GLfloat* texCoord ( GLdouble* p ) { texCoords_[0] = ( p[OGLFT::X] + phase_ ) / 18.; texCoords_[1] = ( p[OGLFT::Y] + phase_ ) / 18.; return texCoords_; } void setPhase ( int phase ) { phase_ = phase; } int phase ( void ) const { return phase_; } }; MyTextureTess texture_tess_; public: Vignette7 ( const char* text, const char* fontfile ) : text_( text ) { face_ = new OGLFT::Filled( fontfile, 72, 75 ); face_->setForegroundColor( 0., .5, .75 ); face_->setHorizontalJustification( OGLFT::Face::CENTER ); face_->setVerticalJustification( OGLFT::Face::MIDDLE ); face_->setTessellationSteps( 3 ); face_->setCompileMode( OGLFT::Face::IMMEDIATE ); face_->setTextureTess( &texture_tess_ ); image_ = new QImage( "texture.png" ); } ~Vignette7 ( void ) { // std::cout << "destructing Vignette 7" << std::endl; glDeleteTextures( 1, &texture_ ); delete image_; delete face_; } unsigned int frame_count ( void ) { return FRAME_COUNT; } unsigned int frame_rate ( void ) { return FRAME_RATE; } void init ( void ) { std::cout << "Vignette 7" << std::endl; glPixelStorei( GL_UNPACK_ALIGNMENT, 1 ); glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE ); glGenTextures( 1, &texture_ ); glBindTexture( GL_TEXTURE_2D, texture_ ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, image_->width(), image_->height(), 0, GL_BGRA, GL_UNSIGNED_BYTE, image_->bits() ); glEnable( GL_TEXTURE_2D ); } void view ( GLdouble left, GLdouble right, GLdouble bottom, GLdouble top ) { glMatrixMode( GL_PROJECTION ); glLoadIdentity(); glOrtho( left, right, bottom, top, -250., 250. ); glMatrixMode( GL_MODELVIEW ); } void draw ( unsigned int frame_number ) { glPushMatrix(); face_->draw( 0., 144., "Apply a" ); face_->draw( 0., 72., "per vertex" ); face_->draw( 0., 0., "texture" ); face_->draw( 0., -72., "function" ); texture_tess_.setPhase( frame_number ); glPopMatrix(); } void finish ( void ) { glDisable( GL_TEXTURE_2D ); } }; class Vignette8 : public Vignette { static const unsigned int FRAME_COUNT = 48; static const unsigned int FRAME_RATE = 3; char* text_; unsigned int text_length_; OGLFT::Monochrome* face_; static const int N_SIZES = 8; static const int sizes_[N_SIZES]; public: Vignette8 ( const char* text, const char* fontfile ) { face_ = new OGLFT::Monochrome( fontfile, 36, 75 ); face_->setForegroundColor( 1., 0., 0. ); text_ = strdup( text ); text_length_ = strlen( text_ ); } ~Vignette8 ( void ) { // std::cout << "destructing Vignette 8" << std::endl; delete face_; free( text_ ); } unsigned int frame_count ( void ) { return text_length_ + 3; } unsigned int frame_rate ( void ) { return FRAME_RATE; } void init ( void ) { std::cout << "Vignette 8" << std::endl; glPixelStorei( GL_UNPACK_ALIGNMENT, 1 ); glEnable( GL_RASTER_POSITION_UNCLIPPED_IBM ); glPushAttrib( GL_POLYGON_BIT ); } void draw ( unsigned int frame_number ) { char save_char = '\0'; if ( frame_number < text_length_ ) { save_char = text_[frame_number]; text_[frame_number] = '\0'; } glPushMatrix(); glTranslatef( -225., 250., 0. ); for ( int i = 0; i < N_SIZES; i++ ) { glTranslatef( 0., -2. * sizes_[i], 0. ); face_->setPointSize( sizes_[i] ); OGLFT::BBox size = face_->measure( text_ ); glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); glColor3f( 1., 1., 1. ); glRectf( size.x_min_, size.y_min_, size.x_max_, size.y_max_ ); face_->draw( 0., 0., text_ ); glPolygonMode( GL_FRONT_AND_BACK, GL_LINE ); glColor3f( 0., 0., 1. ); glRectf( size.x_min_, 0., size.x_max_, size.y_max_ ); } if ( frame_number < text_length_ ) text_[frame_number] = save_char; glPopMatrix(); } void view ( GLdouble left, GLdouble right, GLdouble bottom, GLdouble top ) { glMatrixMode( GL_PROJECTION ); glLoadIdentity(); glOrtho( left, right, bottom, top, -250., 250. ); glMatrixMode( GL_MODELVIEW ); } void finish ( void ) { glPopAttrib(); } }; const int Vignette8::sizes_[8] = { 64, 48, 32, 24, 18, 12, 10, 6 }; class Vignette9 : public Vignette { static const unsigned int FRAME_COUNT = 32; static const unsigned int FRAME_RATE = 8; const char* text_; OGLFT::Filled* face_; public: Vignette9 ( const char* text, const char* fontfile ) : text_( text ) { face_ = new OGLFT::Filled( fontfile, 288, 75 ); face_->setForegroundColor( 0., .5, .75 ); face_->setHorizontalJustification( OGLFT::Face::CENTER ); face_->setCharacterRotationX( 12. ); } ~Vignette9 ( void ) { // std::cout << "destructing Vignette 9" << std::endl; delete face_; } unsigned int frame_count ( void ) { return FRAME_COUNT; } unsigned int frame_rate ( void ) { return FRAME_RATE; } void init ( void ) { std::cout << "Vignette 9" << std::endl; } void draw ( unsigned int /*frame_number*/ ) { glPushMatrix(); glTranslatef( 0., 0., -8. ); face_->draw( 0., 0., text_ ); face_->setCharacterRotationX( face_->characterRotationX() - 0.5 ); glPopMatrix(); } void finish ( void ) { } }; class Vignette10 : public Vignette { static const unsigned int FRAME_COUNT = 108; static const unsigned int FRAME_RATE = 8; const char* text_; unsigned int text_length_; OGLFT::Filled* face_; GLuint glyph_dl_; OGLFT::DisplayLists dlists; GLfloat x_; public: Vignette10 ( const char* text, const char* fontfile ) : text_( text ) { face_ = new OGLFT::Filled( fontfile, 24, 75 ); face_->setForegroundColor( 0., .5, .75 ); face_->setHorizontalJustification( OGLFT::Face::LEFT ); text_length_ = strlen( text_ ); x_ = 250.; } ~Vignette10 ( void ) { // std::cout << "destructing Vignette 10" << std::endl; delete face_; } unsigned int frame_count ( void ) { return FRAME_COUNT; } unsigned int frame_rate ( void ) { return FRAME_RATE; } void init ( void ) { std::cout << "Vignette 10" << std::endl; glyph_dl_ = glGenLists( 2 * text_length_ ); dlists.push_back( 0 ); QColor hsv; for ( unsigned int i = 0; i < text_length_; i++ ) { float dy = 50. * ( + sin( M_PI + (i+1) * 4 * M_PI / text_length_ ) - sin( M_PI + i * 4 * M_PI / text_length_ ) ); hsv.setHsv( (int)(360. * i / text_length_), 255, 255 ); glNewList( glyph_dl_ + i, GL_COMPILE ); glTranslatef( 0., dy, 0. ); glColor3ub( hsv.red(), hsv.green(), hsv.blue() ); glEndList(); dlists.push_back( glyph_dl_ + i ); } for ( unsigned int i = 0; i < text_length_; i++ ) { float y = 50. * sin( M_PI - i * 4 * M_PI / text_length_ ); hsv.setHsv( (int)(360. * (text_length_ - i) / text_length_), 255, 255 ); glNewList( glyph_dl_ + text_length_ + i, GL_COMPILE ); glTranslatef( 0., y, 0. ); glColor3ub( hsv.red(), hsv.green(), hsv.blue() ); glEndList(); dlists.push_back( glyph_dl_ + text_length_ + i ); } dlists[0] = dlists[text_length_]; face_->setCharacterDisplayLists( dlists ); } void view ( GLdouble left, GLdouble right, GLdouble bottom, GLdouble top ) { glMatrixMode( GL_PROJECTION ); glLoadIdentity(); glOrtho( left, right, bottom, top, -250., 250. ); glMatrixMode( GL_MODELVIEW ); } void draw ( unsigned int /*frame_number*/ ) { OGLFT::DLI first = face_->characterDisplayLists().begin() + 1; OGLFT::DLI next = first + text_length_ - 1; OGLFT::DLI last = first + text_length_; rotate( first, next, last ); first = face_->characterDisplayLists().begin() + text_length_ + 1; next = first + 1; last = first + text_length_; rotate( first, next, last ); face_->characterDisplayLists()[0] = face_->characterDisplayLists()[text_length_+1]; face_->draw( x_, 0., text_ ); x_ -= 10.; } void finish ( void ) { glDeleteLists( glyph_dl_, 2 * text_length_ ); } }; class Vignette11 : public Vignette { static const unsigned int FRAME_COUNT = 10; static const unsigned int FRAME_RATE = 1; const QString text_; QString equation_; OGLFT::Translucent* face_; public: Vignette11 ( const char* text, const char* fontfile ) : text_( text ) { // First, open a face in the usual way. face_ = new OGLFT::Translucent( fontfile, 18, 75 ); // Now, create a second face, in this case, using a built-in font. #if 0 FT_Library library = OGLFT::Library::instance(); FT_Face ft_face; FT_New_Memory_Face( library, Demo3UnicodeExample_ttf, Demo3UnicodeExample_ttf_size, 0, &ft_face ); face_->addAuxiliaryFace( ft_face ); #else // Somewhat simpler with new interface. face_->addAuxiliaryFace( Demo3UnicodeExample_ttf, Demo3UnicodeExample_ttf_size ); #endif face_->setForegroundColor( 0., .5, .75 ); // Manually create the equation in UNICODE points equation_ = QChar( 0x2207 );//Nabla equation_ += QChar( 0x2219 );//Dot equation_ += QChar( 0x03a9 );//Omega equation_ += QChar( 0x03c8 );//psi equation_ += QChar( ' ' ); equation_ += QChar( '+' ); equation_ += QChar( ' ' ); equation_ += QChar( 0x03c3 );//sigma equation_ += QChar( 0x03c8 );//psi equation_ += QChar( ' ' ); equation_ += QChar( '=' ); equation_ += QChar( ' ' ); equation_ += QChar( 0x222b );//integral equation_ += QChar( 'd' ); equation_ += QChar( 0x03a9 );//Omega equation_ += QChar( '\'' ); equation_ += QChar( 0x03c3 );//sigma equation_ += QChar( '(' ); equation_ += QChar( 0x03a9 );//Omega equation_ += QChar( '\'' ); equation_ += QChar( 0x2192 );//right arrow equation_ += QChar( 0x03a9 );//Omega equation_ += QChar( ')' ); equation_ += QChar( 0x03c8 );//psi equation_ += QChar( '(' ); equation_ += QChar( 0x03a9 );//Omega equation_ += QChar( '\'' ); equation_ += QChar( ')' ); } ~Vignette11 ( void ) { // std::cout << "destructing Vignette 11" << std::endl; delete face_; } unsigned int frame_count ( void ) { return FRAME_COUNT; } unsigned int frame_rate ( void ) { return FRAME_RATE; } void init ( void ) { std::cout << "Vignette 11" << std::endl; glPixelStorei( GL_UNPACK_ALIGNMENT, 1 ); glEnable( GL_RASTER_POSITION_UNCLIPPED_IBM ); glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); glEnable( GL_BLEND ); } void view ( GLdouble left, GLdouble right, GLdouble bottom, GLdouble top ) { glMatrixMode( GL_PROJECTION ); glLoadIdentity(); glOrtho( left, right, bottom, top, -250., 250. ); glMatrixMode( GL_MODELVIEW ); glTranslated( left, 0, 0 ); } void draw ( unsigned int /*frame_number*/ ) { face_->setHorizontalJustification( OGLFT::Face::LEFT ); face_->draw( 2., 128., "This frame demonstrates two...no three...features:" ); face_->draw( 2., 96., "1. Drawing a UNICODE string (using Qt's QString)." ); face_->draw( 2., 64., "2. Combining two fonts to cover more UNICODE points." ); face_->draw( 2., 32., "3. Embedding a font in the program." ); face_->setHorizontalJustification( OGLFT::Face::CENTER ); face_->draw( 250., 0., equation_ ); face_->setHorizontalJustification( OGLFT::Face::LEFT ); face_->draw( 2., -32., "Thanks to Oliver Bock for the font-in-memory code!" ); } void finish ( void ) { glDisable( GL_BLEND ); } }; class Vignette12 : public Vignette { static const unsigned int FRAME_COUNT = 10; static const unsigned int FRAME_RATE = 1; const QString text_; QString equation_; #if 1 OGLFT::Monochrome* face_; #else OGLFT::Filled* face_; #endif public: Vignette12 ( const char* text, const char* fontfile ) : text_( text ) { // First, open a face in the usual way. #if 1 face_ = new OGLFT::Monochrome( fontfile, 18, 75 ); #else face_ = new OGLFT::Filled( fontfile, 18, 75 ); #endif face_->setForegroundColor( 0., .75, .75 ); // Now, create a second face, in this case, using a built-in font. FT_Library library = OGLFT::Library::instance(); FT_Face ft_face; FT_New_Memory_Face( library, lCSymbols_ttf, lCSymbols_ttf_size, 0, &ft_face ); face_->addAuxiliaryFace( ft_face ); } ~Vignette12 ( void ) { // cout << "destructing Vignette 12" << endl; delete face_; } unsigned int frame_count ( void ) { return FRAME_COUNT; } unsigned int frame_rate ( void ) { return FRAME_RATE; } void init ( void ) { std::cout << "Vignette 12" << std::endl; glPixelStorei( GL_UNPACK_ALIGNMENT, 1 ); glEnable( GL_RASTER_POSITION_UNCLIPPED_IBM ); glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); glEnable( GL_BLEND ); } void view ( GLdouble left, GLdouble right, GLdouble bottom, GLdouble top ) { glMatrixMode( GL_PROJECTION ); glLoadIdentity(); glOrtho( left, right, bottom, top, -250., 250. ); glMatrixMode( GL_MODELVIEW ); glTranslated( left, 0, 0 ); } void draw ( unsigned int /*frame_number*/ ) { face_->setVerticalJustification( OGLFT::Face::TOP ); face_->setHorizontalJustification( OGLFT::Face::CENTER ); face_->draw( 250., 250., "Example of numeric formatting" ); face_->setVerticalJustification( OGLFT::Face::BASELINE ); face_->setHorizontalJustification( OGLFT::Face::ORIGIN ); face_->draw( 0., 128., "%.6f", 100.123456789 ); face_->draw( 0., 96., "%12.6e", 100.123456789 ); face_->draw( 0., 64., "%12.6g", 100.123456789 ); for ( int i = 1; i <= 8; ++i ) { for ( int j = 1; j <= i; j++ ) { double a = i + (double)j / ( 1 << i ); OGLFT::BBox bbox = face_->measure( "%p\"", a ); glPushMatrix(); glTranslated( j*42, -i * 18, 0 ); glColor3f( .25, .25, .25 ); glRectd( bbox.x_min_, bbox.y_min_, bbox.x_max_, bbox.y_max_ ); face_->draw( 0, 0, "%p\"", a ); glPopMatrix(); } } for ( int r = 0; r < 360; r += 45 ) { double sinr = sin( (double)r/180 * M_PI ); double cosr = cos( (double)r/180 * M_PI ); face_->setStringRotation( r ); OGLFT::BBox bbox = face_->measure( "%p\"", 1.015625 ); glPushMatrix(); glTranslated( 250.+cosr*24, 96.+sinr*24, 0 ); glColor3f( .25, .25, .25 ); glRectd( bbox.x_min_, bbox.y_min_, bbox.x_max_, bbox.y_max_ ); face_->draw( 0, 0, "%p\"", 1.015625 ); glPopMatrix(); } face_->setStringRotation( 0 ); } void finish ( void ) { glDisable( GL_BLEND ); } }; CharacterView::CharacterView ( bool flank_speed, const char* fontfile, QWidget* parent, const char* name ) : QGLWidget( ), flank_speed_( flank_speed ) { vignettes.enqueue( new Vignette0( "Welcome to OGLFT!", fontfile ) ); vignettes.enqueue( new Vignette1( "The OpenGL/FreeType library", fontfile ) ); vignettes.enqueue( new Vignette2( "Featuring a mind numbing", fontfile ) ); vignettes.enqueue( new Vignette3( "collection of rendering options", fontfile ) ); vignettes.enqueue( new Vignette9( "and other text effects.", fontfile ) ); vignettes.enqueue( new Vignette5( "Sampler", fontfile ) ); vignettes.enqueue( new Vignette8( "Measuring the text.", fontfile ) ); vignettes.enqueue( new Vignette6( "Per vertex color", fontfile ) ); vignettes.enqueue( new Vignette7( "Per vertex texture coord", fontfile ) ); vignettes.enqueue( new Vignette10( "Each glyph can have it's own display list", fontfile ) ); vignettes.enqueue( new Vignette11( "QString Example", fontfile ) ); vignettes.enqueue( new Vignette12( "Formatting Numbers", fontfile ) ); vignettes.enqueue( new Vignette4( "OGLFT", fontfile ) ); frame_counter_ = 0; counter_snapshot_ = 0; animation_frame_counter_ = 0; animation_frame_count_ = vignettes.current()->frame_count(); animation_frame_rate_ = 1000 / vignettes.current()->frame_rate(); connect( &redraw_timer_, SIGNAL(timeout()), SLOT(redraw()) ); connect( &performance_timer_, SIGNAL(timeout()), SLOT(measure_performance()) ); if ( flank_speed_ ) redraw_timer_.start( 0 ); else redraw_timer_.start( animation_frame_rate_ ); performance_timer_.start( PERFORMANCE_SAMPLE_RATE_HZ * 1000 ); } void CharacterView::redraw ( void ) { updateGL(); frame_counter_++; animation_frame_counter_++; if ( animation_frame_counter_ >= animation_frame_count_ ) { redraw_timer_.stop(); vignettes.current()->finish(); delete vignettes.dequeue(); if ( !vignettes.isEmpty() ) { counter_snapshot_ = frame_counter_; animation_frame_counter_ = 0; vignettes.current()->init(); resetView(); animation_frame_count_ = vignettes.current()->frame_count(); animation_frame_rate_ = 1000 / vignettes.current()->frame_rate(); if ( flank_speed_ ) redraw_timer_.start( 0 ); else redraw_timer_.start( animation_frame_rate_ ); } else { // Evidently, events may be processed during exiting, so... redraw_timer_.stop(); performance_timer_.stop(); qApp->exit( 0 ); } } } void CharacterView::measure_performance ( void ) { int delta_count = frame_counter_ - counter_snapshot_; std::cout << delta_count << " FPS" << std::endl; counter_snapshot_ = frame_counter_; } void CharacterView::initializeGL ( void ) { std::cout << glGetString( GL_VENDOR ) << " " << glGetString( GL_RENDERER ) << " " << glGetString( GL_VERSION ) << std::endl; glClearColor( 0., 0., 0., 1. ); // Let the first vignette do any initialization it wants (though this // should probably be called by the animation controller). vignettes.current()->init(); } void CharacterView::resizeGL ( int w, int h ) { window_width_ = w; window_height_ = h; glViewport( 0, 0, window_width_, window_height_ ); view_width_ = window_width_; view_height_ = window_height_; view_left_ = -view_width_ / 2.; view_right_ = view_width_ / 2.; view_bottom_ = -view_height_ / 2.; view_top_ = view_height_ / 2.; resetView(); } void CharacterView::paintGL ( void ) { glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); vignettes.current()->draw( animation_frame_counter_ % animation_frame_count_ ); } void CharacterView::keyPressEvent ( QKeyEvent* e ) { switch ( e->key() ) { case Key_Q: case Key_Escape: qApp->exit( 0 ); case Key_Return: // "Speed up the harvest." L, Skywalker animation_frame_counter_ = animation_frame_count_; updateGL(); } } void CharacterView::resetView ( void ) { glMatrixMode( GL_PROJECTION ); glLoadIdentity(); glFrustum( view_left_, view_right_, view_bottom_, view_top_, 1., 100. ); glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); vignettes.current()->view( view_left_, view_right_, view_bottom_, view_top_ ); } int main ( int argc, char* argv[] ) { QApplication app( argc, argv ); if ( argc < 2 ) { std::cerr << "usage: " << argv[0] << " [-f] fontfile" << std::endl; std::cerr << " -f ignore the animation timings and run as fast as possible" << std::endl; return 1; } int argn = 1; bool flank_speed = false; if ( !strcmp( argv[argn], "-f" ) ) { flank_speed = true; argn++; } if ( argc <= argn ) { std::cerr << "usage: " << argv[0] << " [-f] fontfile" << std::endl; std::cerr << " -f ignore the animation timings and run as fast as possible" << std::endl; return 1; } // Test the supplied face to make sure it will work OK OGLFT::Monochrome* test_face = new OGLFT::Monochrome( argv[argn] ); if ( !test_face->isValid() ) { std::cerr << "Freetype did not recognize \"" << argv[1] << "\" as a font file" << std::endl; return 1; } delete test_face; CharacterView cv( flank_speed, argv[argn] ); cv.resize( 500, 500 ); app.setMainWidget( &cv ); cv.show(); return app.exec(); }