Back to index

salome-gui  6.5.0
GLViewer_Drawer.cxx
Go to the documentation of this file.
00001 // Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
00002 //
00003 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
00004 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
00005 //
00006 // This library is free software; you can redistribute it and/or
00007 // modify it under the terms of the GNU Lesser General Public
00008 // License as published by the Free Software Foundation; either
00009 // version 2.1 of the License.
00010 //
00011 // This library is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014 // Lesser General Public License for more details.
00015 //
00016 // You should have received a copy of the GNU Lesser General Public
00017 // License along with this library; if not, write to the Free Software
00018 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00019 //
00020 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
00021 //
00022 
00023 //  Author : OPEN CASCADE
00024 // File:      GLViewer_Drawer.cxx
00025 // Created:   November, 2004
00026 //#include <GLViewerAfx.h>
00027 //
00028 #include "GLViewer_Drawer.h"
00029 #include "GLViewer_Object.h"
00030 #include "GLViewer_Text.h"
00031 #include "GLViewer_ViewFrame.h"
00032 #include "GLViewer_ViewPort2d.h"
00033 
00034 #include <QApplication>
00035 #include <QImage>
00036 #include <QPainter>
00037 #include <QFile>
00038 
00039 #ifndef WIN32
00040 #include <GL/glx.h>
00041 #endif
00042 
00043 #include <gp_Pnt2d.hxx>
00044 
00045 #define TEXT_GAP    5
00046 // Two texture components for texmapped fonts: luminance and alpha
00047 #define NB_TEX_COMP 2
00048 // A font is split into rows each containing 32 characters
00049 #define TEX_ROW_LEN 32
00050 // Gap in pixels between two character rows in a font texture
00051 #define TEX_ROW_GAP 2
00052 
00053 GLfloat modelMatrix[16];
00054 
00055 
00057 static int FirstSymbolNumber = 32;
00059 static int LastSymbolNumber = 127;
00060 
00061 QMap<GLViewer_TexFindId,GLViewer_TexIdStored> GLViewer_TexFont::TexFontBase;
00062 QMap<GLViewer_TexFindId,GLuint>               GLViewer_TexFont::BitmapFontCache; 
00063 
00067 void GLViewer_TexFont::clearTextBases()
00068 {
00069   //cout << "Clear font map" << endl;
00070   TexFontBase.clear();
00071   BitmapFontCache.clear();
00072 }
00073 
00077 GLViewer_TexFont::GLViewer_TexFont()
00078 : myMaxRowWidth( 0 ), myFontHeight( 0 )
00079 {
00080     myQFont = QApplication::font();//QFont::defaultFont();
00081     mySeparator = 2;
00082     myIsResizeable = false;
00083     myMinMagFilter = GL_LINEAR;
00084 
00085     init();
00086 }
00087 
00095 GLViewer_TexFont::GLViewer_TexFont( QFont* theFont, int theSeparator, bool theIsResizeable, GLuint theMinMagFilter )
00096 : myMaxRowWidth( 0 ), myFontHeight( 0 )
00097 {
00098     myQFont = *theFont;
00099     mySeparator = theSeparator;
00100     myIsResizeable = theIsResizeable;
00101     myMinMagFilter = theMinMagFilter;
00102 
00103     init();
00104 }
00105 
00109 GLViewer_TexFont::~GLViewer_TexFont()
00110 {
00111     delete[] myWidths;
00112     delete[] myPositions;
00113 } 
00114 
00118 void GLViewer_TexFont::init()
00119 {
00120     myNbSymbols = LastSymbolNumber - FirstSymbolNumber + 1;
00121 
00122     // It is unsafe to draw all characters in a single row -
00123     // this leads to problems on some graphic cards with small GL_MAX_TEXTURE_SIZE.
00124     // So splitting the characters into rows each containing 32 characters (or less).
00125     // Assuming contant height of each row (64 pixels) to simplify texture mapping.
00126     // However, this can be improved if necessary.
00127     QFontMetrics aFM( myQFont ); 
00128     myFontHeight = aFM.height();
00129     
00130     myWidths    = new int[myNbSymbols];
00131     myPositions = new int[myNbSymbols];
00132 
00133     for( int i = 0, k = FirstSymbolNumber, aWidth = 0; i < myNbSymbols; i++, k++ )
00134     {
00135         // is it time to start a new row?
00136         if ( !( i % TEX_ROW_LEN ) )
00137         {
00138           if( aWidth > myMaxRowWidth )
00139             myMaxRowWidth = aWidth;
00140           aWidth = 0;
00141         }
00142         myWidths[i]    = aFM.width( k );
00143         myPositions[i] = aWidth;
00144         aWidth += myWidths[i] + 2;
00145     }
00146 
00147     myTexFontWidth  = 0;
00148     myTexFontHeight = 0;
00149 }
00150   
00154 bool GLViewer_TexFont::generateTexture()
00155 {
00156     GLViewer_TexFindId aFindFont;
00157     aFindFont.myFontFamily = myQFont.family();//myQFont.toString();
00158     aFindFont.myIsBold = myQFont.bold();
00159     aFindFont.myIsItal = myQFont.italic();
00160     aFindFont.myIsUndl = myQFont.underline();
00161     aFindFont.myPointSize = myQFont.pointSize();
00162     aFindFont.myViewPortId = size_t(QGLContext::currentContext());
00163         
00164     if( TexFontBase.contains( aFindFont ) )
00165     {
00166         GLViewer_TexIdStored aTexture = TexFontBase[ aFindFont ];
00167         myTexFont = aTexture.myTexFontId;
00168         myTexFontWidth = aTexture.myTexFontWidth;
00169         myTexFontHeight = aTexture.myTexFontHeight;
00170     }    
00171     else    
00172     {
00173         // Adding some pixels to have a gap between rows
00174         int aRowPixelHeight = myFontHeight + TEX_ROW_GAP;
00175         int aDescent = QFontMetrics( myQFont ).descent();
00176 
00177         int aNumRows = myNbSymbols / TEX_ROW_LEN;
00178         if ( myNbSymbols % TEX_ROW_LEN ) 
00179           aNumRows++;
00180         int pixelsHight = aNumRows * aRowPixelHeight;
00181 
00182         myTexFontWidth  = 64;
00183         myTexFontHeight = 64;
00184 
00185         while( myTexFontWidth < myMaxRowWidth )
00186             myTexFontWidth <<= 1;
00187         while( myTexFontHeight < pixelsHight )
00188             myTexFontHeight <<= 1;
00189         
00190         // Checking whether the texture dimensions for the requested font
00191         // do not exceed the maximum size supported by the OpenGL implementation
00192         int maxSize;
00193         glGetIntegerv( GL_MAX_TEXTURE_SIZE, &maxSize );
00194         if ( myTexFontWidth > maxSize || myTexFontHeight > maxSize )
00195           return false;
00196 
00197         QPixmap aPixmap( myTexFontWidth, myTexFontHeight );
00198         aPixmap.fill( QColor( 0, 0, 0) );
00199         QPainter aPainter( &aPixmap );
00200         aPainter.setFont( myQFont );
00201         int row;
00202         for( int l = 0; l < myNbSymbols; l++  )
00203         {
00204             row = l / TEX_ROW_LEN;
00205             QString aLetter;
00206             aLetter += (char)(FirstSymbolNumber + l);
00207             aPainter.setPen( QColor( 255,255,255) );
00208             aPainter.drawText( myPositions[l], ( row + 1 ) * aRowPixelHeight - aDescent, aLetter );
00209         }
00210     
00211         QImage aImage = aPixmap.toImage();
00212 
00213         //int qqq = 0;
00214         //if (qqq)
00215         //  aImage.save("w:\\work\\CATHARE\\texture.png", "PNG");
00216 
00217         char* pixels = new char[myTexFontWidth * myTexFontHeight * NB_TEX_COMP];
00218 
00219         for( int i = 0; i < myTexFontHeight; i++ )
00220         {            
00221             for( int j = 0; j < myTexFontWidth;  j++ )
00222             {
00223                 int aRed = qRed( aImage.pixel( j, myTexFontHeight - i - 1 ) );
00224                 int aGreen = qGreen( aImage.pixel( j, myTexFontHeight - i - 1 ) );
00225                 int aBlue = qBlue( aImage.pixel( j, myTexFontHeight - i - 1 ) );
00226           
00227                 if( aRed != 0 || aGreen != 0 || aBlue != 0 )
00228                 {
00229                     pixels[i * myTexFontWidth * NB_TEX_COMP + j * NB_TEX_COMP] = (GLubyte)( (aRed + aGreen + aBlue)/3 );
00230                     pixels[i * myTexFontWidth * NB_TEX_COMP + j * NB_TEX_COMP + 1]= (GLubyte) 255;
00231                 }
00232                 else
00233                 {
00234                     pixels[i * myTexFontWidth * NB_TEX_COMP + j * NB_TEX_COMP] = (GLubyte) 0;
00235                     pixels[i * myTexFontWidth * NB_TEX_COMP + j * NB_TEX_COMP + 1]= (GLubyte) 0;
00236                 }                
00237             }
00238         }
00239 
00240         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
00241         glGenTextures(1, &myTexFont);
00242         glBindTexture(GL_TEXTURE_2D, myTexFont);  
00243         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, myMinMagFilter);
00244         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, myMinMagFilter);
00245         glTexImage2D(GL_TEXTURE_2D, 
00246                      0, 
00247                      GL_INTENSITY, 
00248                      myTexFontWidth,
00249                      myTexFontHeight, 
00250                      0, 
00251                      GL_LUMINANCE_ALPHA, 
00252                      GL_UNSIGNED_BYTE, 
00253                      pixels);
00254     
00255         delete[] pixels;
00256         
00257         GLViewer_TexIdStored aTexture;
00258         aTexture.myTexFontId = myTexFont;
00259         aTexture.myTexFontWidth = myTexFontWidth;
00260         aTexture.myTexFontHeight = myTexFontHeight;
00261 
00262         TexFontBase.insert( aFindFont, aTexture );
00263     }
00264     return true;
00265 }
00266 
00274 void GLViewer_TexFont::drawString( QString theStr, GLdouble theX , GLdouble theY, GLfloat theScale )
00275 {
00276     // Adding some pixels to have a gap between rows
00277     int aRowPixelHeight = myFontHeight + TEX_ROW_GAP;
00278 
00279     float aXScale = 1.f, aYScale = 1.f;
00280     if ( !myIsResizeable )
00281     {
00282       glGetFloatv (GL_MODELVIEW_MATRIX, modelMatrix);
00283       aXScale = modelMatrix[0];
00284       aYScale = modelMatrix[5];     
00285     } 
00286     else if ( theScale > 0.f )
00287     {
00288       aXScale = aXScale / theScale;
00289       aYScale = aYScale / theScale;
00290     }
00291 
00292     // store attributes
00293     glPushAttrib( GL_ENABLE_BIT | GL_TEXTURE_BIT );
00294 
00295     glEnable(GL_TEXTURE_2D);
00296     glPixelTransferi(GL_MAP_COLOR, 0);
00297 
00298     glAlphaFunc(GL_GEQUAL, 0.05F);
00299     glEnable(GL_ALPHA_TEST);
00300 
00301     glEnable(GL_BLEND);
00302     glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
00303 
00304     glBindTexture(GL_TEXTURE_2D, myTexFont);
00305     glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
00306 
00307     glBegin(GL_QUADS);
00308 
00309     float aLettBeginS, aLettEndS, aLettBeginT, aLettEndT;
00310     float aDY = ( aRowPixelHeight - 1 ) / aYScale, aDX;
00311     char aLetter;
00312     int aLettIndex, row;
00313     for ( int i = 0; i < (int)theStr.length(); i++ )
00314     {
00315         aLetter    = theStr.data()[i].toLatin1();
00316         aLettIndex = (int)aLetter - FirstSymbolNumber;
00317         row        = aLettIndex / TEX_ROW_LEN;
00318 
00319         aLettBeginS = (float)myPositions[aLettIndex] / ( (float)myTexFontWidth - 1.f );
00320         aLettEndS   = aLettBeginS + ( (float)myWidths[aLettIndex] - 1.f ) / ( (float)myTexFontWidth - 1.f );
00321         aLettBeginT = ( myTexFontHeight - ( row + 1 ) * aRowPixelHeight ) / ( (float)myTexFontHeight - 1.f ); 
00322         aLettEndT   = aLettBeginT + ( (float)aRowPixelHeight - 1.f ) / ( (float)myTexFontHeight - 1.f );
00323 
00324         aDX = ( (float)myWidths[aLettIndex] - 1.f ) / aXScale;
00325 
00326         glTexCoord2f( aLettBeginS, aLettBeginT ); glVertex3f( theX,       theY,       1.f );
00327         glTexCoord2f( aLettBeginS, aLettEndT   ); glVertex3f( theX,       theY + aDY, 1.f );
00328         glTexCoord2f( aLettEndS,   aLettEndT   ); glVertex3f( theX + aDX, theY + aDY, 1.f );
00329         glTexCoord2f( aLettEndS,   aLettBeginT ); glVertex3f( theX + aDX, theY,       1.f );
00330 
00331         theX += aDX + mySeparator / aXScale;
00332     }
00333 
00334     glEnd();
00335     // restore attributes
00336     glPopAttrib();
00337 }
00338 
00342 int GLViewer_TexFont::getStringWidth( QString theStr )
00343 {
00344     int aWidth = 0;
00345     for ( int i = 0; i < (int)theStr.length(); i ++ )
00346     {
00347         char aLetter = theStr.data()[i].toLatin1();
00348         int aLettIndex = (int)aLetter - FirstSymbolNumber;
00349         aWidth += myWidths[aLettIndex] + mySeparator;
00350     }
00351 
00352     return aWidth;
00353 }
00354 
00358 int GLViewer_TexFont::getStringHeight()
00359 {
00360     QFontMetrics aFM( myQFont );
00361     return aFM.height();
00362 }
00363 
00367 static GLuint displayListBase( QFont* theFont )
00368 {
00369   if ( !theFont )
00370     return 0;
00371   GLuint aList = 0;
00372   //static QMap<GLViewer_TexFindId, GLuint> fontCache;
00373   GLViewer_TexFindId aFindFont;
00374   aFindFont.myFontFamily = theFont->family();//theFont->toString();
00375   aFindFont.myIsBold = theFont->bold();
00376   aFindFont.myIsItal = theFont->italic();
00377   aFindFont.myIsUndl = theFont->underline();
00378   aFindFont.myPointSize = theFont->pointSize();
00379 
00380 #ifdef WIN32
00381   HGLRC ctx = ::wglGetCurrentContext();
00382   if ( !ctx )
00383     return aList;  
00384   
00385   aFindFont.myViewPortId = (int)ctx;
00386 
00387   if ( GLViewer_TexFont::BitmapFontCache.contains( aFindFont ) )
00388     aList = GLViewer_TexFont::BitmapFontCache[aFindFont];
00389   else
00390   {
00391     GLuint listBase = 0;
00392     QMap<GLViewer_TexFindId, GLuint>::iterator it = GLViewer_TexFont::BitmapFontCache.begin();
00393     for ( ; it != GLViewer_TexFont::BitmapFontCache.end(); ++it )
00394     {
00395       if ( it.key().myViewPortId == (int)ctx && it.value() > listBase )
00396         listBase = it.value();
00397     }
00398     listBase += 256;
00399 
00400     HDC glHdc = ::wglGetCurrentDC();
00401     ::SelectObject( glHdc, theFont->handle() );
00402     if ( !::wglUseFontBitmaps( glHdc, 0, 256, listBase ) )
00403       listBase = 0;
00404     aList = listBase;
00405     GLViewer_TexFont::BitmapFontCache[aFindFont] = aList;
00406   }
00407 #else //X Window
00408   Display* aDisp = glXGetCurrentDisplay();
00409   if( !aDisp )
00410   {
00411 #ifdef _DEBUG_
00412     printf( "Can't find current dislay\n" );
00413 #endif
00414     return aList;
00415   }
00416   
00417   GLXContext aCont = glXGetCurrentContext();
00418   if( !aCont )
00419   {
00420 #ifdef _DEBUG_
00421     printf( "Can't find current context\n" );
00422 #endif
00423     return aList;
00424   }
00425 
00426   aFindFont.myViewPortId = size_t(aCont);
00427 
00428   if ( GLViewer_TexFont::BitmapFontCache.contains( aFindFont ) )
00429     aList = GLViewer_TexFont::BitmapFontCache[aFindFont];
00430   else
00431   {
00432     GLuint listBase = 0;
00433     QMap<GLViewer_TexFindId, GLuint>::iterator it = GLViewer_TexFont::BitmapFontCache.begin();
00434     for ( ; it != GLViewer_TexFont::BitmapFontCache.end(); ++it )
00435     {
00436       if ( it.key().myViewPortId == size_t(aCont) && it.value() > listBase )
00437         listBase = it.value();
00438     }
00439     listBase += 256;
00440     
00441     //glXUseXFont( (Font)(theFont->handle()), 0, 256, listBase );
00442     int aFontCont = 0;
00443     QString aFontDef = theFont->toString();
00444     char** xFontList = XListFonts( aDisp, aFontDef.toLatin1()/*aFindFont.myFontString.data()*/, 1, &aFontCont  );
00445     if( !theFont->handle() )
00446     {       
00447 #ifdef _DEBUG_
00448       printf( "Can't load font %s. loading default font....\n", aFontDef.toLatin1().data()/*aFindFont.myFontString.data()*/ );
00449 #endif
00450       QString aFontMask ("-*-*-*-r-*-*-");
00451       aFontMask += aFontDef/*aFindFont.myFontString*/.section( ',', 1, 1 );
00452 #ifdef _DEBUG_
00453       printf( "Height of Default font: %s\n", aFontDef/*aFindFont.myFontString*/.section( ',', 1, 1 ).data() );
00454 #endif
00455       aFontMask += "-*-*-*-m-*-*-*";
00456       xFontList = XListFonts( aDisp, aFontMask.toLatin1().constData()/*"-*-*-*-r-*-*-12-*-*-*-m-*-*-*"*/, 1, &aFontCont  );
00457       if( aFontCont == 0 )
00458       {      
00459 #ifdef _DEBUG_
00460         printf( "Can't load default font\n" );
00461 #endif
00462         return 0;
00463       }
00464       glXUseXFont( (Font)(XLoadFont( aDisp,xFontList[0] )), 0, 256, listBase );
00465     }
00466     else
00467       glXUseXFont( (Font)(theFont->handle()), 0, 256, listBase );
00468     
00469     aList = listBase;
00470     GLViewer_TexFont::BitmapFontCache[aFindFont] = aList;
00471   }
00472 
00473 #endif
00474 
00475   return aList;
00476 }
00477 
00481 GLViewer_Drawer::GLViewer_Drawer()
00482 : myFont( "Helvetica", 10, QFont::Bold )
00483 {
00484   myXScale = myYScale = 0.0;
00485   myObjects.clear();
00486   myTextList = 0/*-1*/;
00487   myObjectType = "GLViewer_Object";
00488   myPriority = 0;
00489   myTextFormat = DTF_BITMAP;
00490   myTextScale = 0.125;
00491 }
00492 
00496 GLViewer_Drawer::~GLViewer_Drawer()
00497 {
00498   myObjects.clear();
00499   glDeleteLists( myTextList, 1 );
00500 }
00501 
00505 void GLViewer_Drawer::destroyAllTextures()
00506 {
00507     QMap<GLViewer_TexFindId,GLViewer_TexIdStored>::Iterator anIt= GLViewer_TexFont::TexFontBase.begin();
00508     QMap<GLViewer_TexFindId,GLViewer_TexIdStored>::Iterator anEndIt= GLViewer_TexFont::TexFontBase.end();
00509 
00510     for( ; anIt != anEndIt; anIt++ )
00511         glDeleteTextures( 1, &(anIt.value().myTexFontId) );
00512 }
00513 
00518 void GLViewer_Drawer::setAntialiasing(const bool on)
00519 {
00520         if (on)
00521         {
00522     glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
00523     glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);
00524 
00525                 glEnable(GL_POINT_SMOOTH);
00526                 glEnable(GL_LINE_SMOOTH);
00527                 glEnable(GL_POLYGON_SMOOTH);
00528                 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 
00529                 glEnable (GL_BLEND);
00530         }
00531         else
00532         {
00533                 glDisable(GL_POINT_SMOOTH);
00534                 glDisable(GL_LINE_SMOOTH);
00535                 glDisable(GL_POLYGON_SMOOTH);
00536                 glBlendFunc (GL_ONE, GL_ZERO);
00537                 glDisable (GL_BLEND);
00538         }
00539 }
00540 
00547 GLuint GLViewer_Drawer::loadTexture( const QString& fileName,
00548                                      GLint* x_size,
00549                                      GLint* y_size,
00550                                      GLint* t_size )
00551 {
00552     QImage buf;
00553     if ( fileName.isEmpty() || !buf.load( fileName ) )
00554         return 0;
00555 
00556     int w = buf.width();
00557     int h = buf.height();
00558 
00559     int size = 16;
00560     while( size < w || size < h )
00561         size = size * 2;
00562 
00563     GLuint texture;
00564     GLubyte* pixels = new GLubyte[ size * size * 4 ];
00565 
00566     for( int i = 0; i < size; i++ )
00567     {            
00568         for( int j = 0; j < size; j++ )
00569         {
00570             GLubyte r, g, b, a;
00571             if( j < w && i < h )
00572             {
00573                 QRgb pixel = buf.pixel( j, h - i - 1 );
00574                 r = (GLubyte)qRed( pixel );
00575                 g = (GLubyte)qGreen( pixel );
00576                 b = (GLubyte)qBlue( pixel );
00577                 a = (GLubyte)qAlpha( pixel );
00578             }
00579             else
00580             {
00581                 r = (GLubyte)255;
00582                 g = (GLubyte)255;
00583                 b = (GLubyte)255;
00584                 a = (GLubyte)255;
00585             }
00586 
00587             int index = 4 * ( i * size + j );
00588             pixels[ index ] = r;
00589             pixels[ index + 1 ] = g;
00590             pixels[ index + 2 ] = b;
00591             pixels[ index + 3 ] = a;
00592         }
00593     }
00594 
00595     //initialize texture
00596     glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
00597     glGenTextures( 1, &texture );
00598     glBindTexture( GL_TEXTURE_2D, texture );
00599     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
00600     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
00601     glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, size, size, 0,
00602                   GL_RGBA, GL_UNSIGNED_BYTE, pixels );
00603 
00604     delete[] pixels;
00605 
00606     if ( x_size )
00607       *(x_size) = w;
00608 
00609     if ( y_size )
00610       *(y_size) = h;
00611 
00612     if ( t_size )
00613       *(t_size) = size;
00614 
00615     return texture;
00616 }
00617 
00624 void GLViewer_Drawer::drawTexture( GLuint texture, GLint size, GLfloat x, GLfloat y )
00625 {
00626     /*float xScale = myXScale;
00627     float yScale = myYScale;
00628 
00629     glColor4f( 1.0, 1.0, 1.0, 1.0 );
00630 
00631     glEnable( GL_TEXTURE_2D );
00632     glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
00633     glAlphaFunc( GL_GREATER, 0.95F );
00634     glEnable( GL_ALPHA_TEST );
00635     
00636     glBindTexture( GL_TEXTURE_2D, texture );
00637     glBegin( GL_QUADS );
00638 
00639     glTexCoord2f( 0.0, 0.0 );
00640     glVertex3f( x-size/2./xScale, y-size/2./yScale, 0.0 );
00641 
00642     glTexCoord2f( 0.0, 1.0 );
00643     glVertex3f( x-size/2./xScale, y+size/2./yScale, 0.0 );
00644 
00645     glTexCoord2f( 1.0, 1.0 );
00646     glVertex3f( x+size/2./xScale, y+size/2./yScale, 0.0 );
00647 
00648     glTexCoord2f( 1.0, 0.0 );
00649     glVertex3f( x+size/2./xScale, y-size/2./yScale, 0.0 );
00650     
00651     glEnd();
00652     glFlush();
00653 
00654     glDisable( GL_ALPHA_TEST );
00655     glDisable( GL_TEXTURE_2D );*/
00656 
00657   drawTexture( texture, size, size, x, y );
00658 }
00659 
00667 void GLViewer_Drawer::drawTexture( GLuint texture, GLint x_size, GLint y_size, GLfloat x, GLfloat y )
00668 {
00669     /*float xScale = myXScale;
00670     float yScale = myYScale;
00671 
00672     glColor4f( 1.0, 1.0, 1.0, 1.0 );
00673 
00674     glEnable( GL_TEXTURE_2D );
00675     glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
00676     glAlphaFunc( GL_GREATER, 0.95F );
00677     glEnable( GL_ALPHA_TEST );
00678     
00679     glBindTexture( GL_TEXTURE_2D, texture );
00680     glBegin( GL_QUADS );
00681 
00682     glTexCoord2f( 0.0, 0.0 );
00683     glVertex3f( x-x_size/2./xScale, y-y_size/2./yScale, 0.0 );
00684 
00685     glTexCoord2f( 0.0, 1.0 );
00686     glVertex3f( x-x_size/2./xScale, y+y_size/2./yScale, 0.0 );
00687 
00688     glTexCoord2f( 1.0, 1.0 );
00689     glVertex3f( x+x_size/2./xScale, y+y_size/2./yScale, 0.0 );
00690 
00691     glTexCoord2f( 1.0, 0.0 );
00692     glVertex3f( x+x_size/2./xScale, y-y_size/2./yScale, 0.0 );
00693     
00694     glEnd();
00695     glFlush();
00696 
00697     glDisable( GL_ALPHA_TEST );
00698     glDisable( GL_TEXTURE_2D );*/
00699   drawTexturePart( texture, 1.0, 1.0, x_size, y_size, x, y );
00700 }
00701 
00712 void GLViewer_Drawer::drawTexturePart( GLuint texture,
00713                                        GLfloat x_ratio,
00714                                        GLfloat y_ratio,
00715                                        GLfloat x_size,
00716                                        GLfloat y_size,
00717                                        GLfloat x,
00718                                        GLfloat y,
00719                                        GLfloat scale )
00720 {
00721   if( !texture )
00722     return;
00723 
00724   float xScale = scale > 0. ? 1./scale : myXScale;
00725   float yScale = scale > 0. ? 1./scale : myYScale;
00726 
00727   glColor4f( 1.0, 1.0, 1.0, 1.0 );
00728 
00729 
00730   glEnable( GL_TEXTURE_2D );
00731   glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
00732   bool hasAlpha = glIsEnabled( GL_ALPHA_TEST );
00733   glDisable( GL_ALPHA_TEST );
00734 
00735   glBindTexture( GL_TEXTURE_2D, texture );
00736   glBegin( GL_QUADS );
00737 
00738   glTexCoord2f( 0.0, 0.0 );
00739   glVertex3f( x-x_size/2./xScale, y-y_size/2./yScale, 0.0 );
00740 
00741   glTexCoord2f( 0.0, y_ratio );
00742   glVertex3f( x-x_size/2./xScale, y+y_size/2./yScale, 0.0 );
00743 
00744   glTexCoord2f( x_ratio, y_ratio );
00745   glVertex3f( x+x_size/2./xScale, y+y_size/2./yScale, 0.0 );
00746 
00747   glTexCoord2f( x_ratio, 0.0 );
00748   glVertex3f( x+x_size/2./xScale, y-y_size/2./yScale, 0.0 );
00749   
00750   glEnd();
00751   glFlush();
00752 
00753   if ( hasAlpha )
00754     glEnable( GL_ALPHA_TEST );
00755 
00756   glDisable( GL_TEXTURE_2D );
00757 }
00758 
00769 void GLViewer_Drawer::drawText( const QString& text, GLfloat xPos, GLfloat yPos,
00770                                 const QColor& color, QFont* theFont, int theSeparator, DisplayTextFormat theFormat )
00771 {
00772   glColor3f( ( GLfloat )color.red() / 255, 
00773              ( GLfloat )color.green() / 255, 
00774              ( GLfloat )color.blue() / 255 );
00775 
00776   if( theFormat != DTF_BITMAP )
00777   {
00778     GLViewer_TexFont aTexFont( theFont, theSeparator, theFormat == DTF_TEXTURE_SCALABLE, GL_LINEAR );
00779     // Font texture was not found or generated --> cannot draw text
00780     if ( !aTexFont.generateTexture() )
00781       return;
00782 
00783     if ( theFormat == DTF_TEXTURE_SCALABLE )
00784       aTexFont.drawString( text, xPos, yPos, textScale() );
00785     else
00786       aTexFont.drawString( text, xPos, yPos );
00787   }
00788   else
00789   {
00790     glRasterPos2f( xPos, yPos );
00791     glListBase( displayListBase( theFont ) );
00792     glCallLists( text.length(), GL_UNSIGNED_BYTE, text.toLocal8Bit().data() );
00793   }
00794 }
00795 
00799 void GLViewer_Drawer::drawText( GLViewer_Object* theObject )
00800 {
00801   if( !theObject )
00802     return;
00803 
00804   GLViewer_Text* aText = theObject->getGLText();
00805   if( !aText )
00806     return;
00807 
00808   GLfloat aPosX, aPosY;
00809   aText->getPosition( aPosX, aPosY );
00810   // get temporary copy of font
00811   QFont aTmpVarFont = aText->getFont();
00812   drawText( aText->getText(), aPosX, aPosY, aText->getColor(), &aTmpVarFont, aText->getSeparator(), aText->getDisplayTextFormat() );
00813 }
00814 
00824 void GLViewer_Drawer::drawGLText( QString text, float x, float y,
00825                                   int hPosition, int vPosition, QColor color, bool smallFont )
00826 {
00827   QFont aFont( myFont );
00828   if( smallFont )
00829     aFont.setPointSize( int(aFont.pointSize() * 0.8) );
00830 
00831   GLfloat scale = textScale() > 0. ? textScale() : 1.;
00832 
00833   QFontMetrics aFontMetrics( aFont );
00834   float width  = myTextFormat == DTF_TEXTURE_SCALABLE ? aFontMetrics.width( text ) * scale : aFontMetrics.width( text ) / myXScale;
00835   float height = myTextFormat == DTF_TEXTURE_SCALABLE ? aFontMetrics.height() * scale : aFontMetrics.height() / myYScale;
00836   float gap = 5 / myXScale;
00837 
00838   switch( hPosition )
00839   {
00840       case GLText_Left   : x -= ( gap + width ); break;
00841       case GLText_Center : x -= width / 2; break;
00842       case GLText_Right  : x += gap; break;
00843       default : break;
00844   }
00845 
00846   switch( vPosition )
00847   {
00848       case GLText_Top    : y += height * 0.5; break;
00849       case GLText_Center : y -= height * 0.5; break;
00850       case GLText_Bottom : y -= height * 1.5; break;
00851       default : break;
00852   }
00853 
00854   drawText( text, x, y, color, &aFont, 2, myTextFormat );
00855 }
00856 
00860 GLViewer_Rect GLViewer_Drawer::textRect( const QString& text ) const
00861 {
00862   GLfloat scale = textScale() > 0. ? textScale() : 1.;
00863 
00864   QFontMetrics aFontMetrics( myFont );
00865   float width  = myTextFormat == DTF_TEXTURE_SCALABLE ? aFontMetrics.width( text ) * scale : aFontMetrics.width( text );
00866   float height = myTextFormat == DTF_TEXTURE_SCALABLE ? aFontMetrics.height() * scale : aFontMetrics.height();
00867 
00868   return GLViewer_Rect( 0, width, height, 0 );
00869 }
00870 
00876 void GLViewer_Drawer::drawRectangle( GLViewer_Rect* rect, QColor color )
00877 {
00878   if( !rect )
00879     return;
00880 
00881   float x1 = rect->left();
00882   float x2 = rect->right();
00883   float y1 = rect->bottom();
00884   float y2 = rect->top();
00885   
00886   glColor3f( ( GLfloat )color.red() / 255,
00887     ( GLfloat )color.green() / 255,
00888     ( GLfloat )color.blue() / 255 );
00889   glLineWidth( 1.0 );
00890   
00891   glBegin( GL_LINE_LOOP );
00892   glVertex2f( x1, y1 );
00893   glVertex2f( x1, y2 );
00894   glVertex2f( x2, y2 );
00895   glVertex2f( x2, y1 );
00896   glEnd();
00897 }
00898 
00905 bool GLViewer_Drawer::translateToHPGL( QFile& hFile, GLViewer_CoordSystem* aViewerCS, GLViewer_CoordSystem* aHPGLCS )
00906 {
00907     bool result = true;
00908     for( int i=0, n=myObjects.count(); i<n; i++ ) 
00909         result &= myObjects[i]->translateToHPGL( hFile, aViewerCS, aHPGLCS );
00910     return result;
00911 }
00912 
00919 bool GLViewer_Drawer::translateToPS( QFile& hFile, GLViewer_CoordSystem* aViewerCS, GLViewer_CoordSystem* aPSCS )
00920 {
00921     bool result = true;
00922     for( int i=0, n=myObjects.count(); i<n; i++ ) 
00923         result &= myObjects[i]->translateToPS( hFile, aViewerCS, aPSCS );
00924     return result;
00925 }
00926 
00927 #ifdef WIN32
00928 
00934 bool GLViewer_Drawer::translateToEMF( HDC hDC, GLViewer_CoordSystem* aViewerCS, GLViewer_CoordSystem* aEMFCS )
00935 {
00936     bool result = true;
00937     for( int i=0, n=myObjects.count(); i<n; i++ ) 
00938         result &= myObjects[i]->translateToEMF( hDC, aViewerCS, aEMFCS );
00939     return result;
00940 }
00941 #endif
00942 
00952 void GLViewer_Drawer::drawRectangle( GLViewer_Rect* rect, GLfloat lineWidth, GLfloat gap,
00953                                      QColor color, bool filled, QColor fillingColor )
00954 {
00955   if( !rect )
00956     return;
00957 
00958   float x1 = rect->left() - gap;
00959   float x2 = rect->right() + gap;
00960   float y1 = rect->bottom() - gap;
00961   float y2 = rect->top() + gap;
00962   
00963   if( filled )
00964   {
00965     glColor3f( ( GLfloat )fillingColor.red() / 255,
00966       ( GLfloat )fillingColor.green() / 255,
00967       ( GLfloat )fillingColor.blue() / 255 );
00968     glBegin( GL_POLYGON );
00969     glVertex2f( x1, y1 );
00970     glVertex2f( x1, y2 );
00971     glVertex2f( x2, y2 );
00972     glVertex2f( x2, y1 );
00973     glEnd();
00974   }
00975 
00976   glColor3f( ( GLfloat )color.red() / 255,
00977     ( GLfloat )color.green() / 255,
00978     ( GLfloat )color.blue() / 255 );
00979   glLineWidth( lineWidth );
00980   
00981   glBegin( GL_LINE_LOOP );
00982   glVertex2f( x1, y1 );
00983   glVertex2f( x1, y2 );
00984   glVertex2f( x2, y2 );
00985   glVertex2f( x2, y1 );
00986   glEnd();
00987 }
00988 
00995 void GLViewer_Drawer::drawContour( const GLViewer_PntList& pntList, QColor color, GLfloat lineWidth )
00996 {
00997   glColor3f( ( GLfloat )color.red() / 255,
00998     ( GLfloat )color.green() / 255,
00999     ( GLfloat )color.blue() / 255 );
01000   glLineWidth( lineWidth );
01001   
01002   glBegin( GL_LINES );
01003   QList<GLViewer_Pnt>::const_iterator it = pntList.begin();
01004   for( ; it != pntList.end(); ++it )
01005     glVertex2f( (*it).x(), (*it).y() );
01006   glEnd();
01007 }
01008 
01017 void GLViewer_Drawer::drawContour( GLViewer_Rect* rect, QColor color, GLfloat lineWidth,
01018                                    GLushort pattern, bool isStripe )
01019 {
01020   float x1 = rect->left();
01021   float x2 = rect->right();
01022   float y1 = rect->bottom();
01023   float y2 = rect->top();
01024   
01025   glColor3f( ( GLfloat )color.red() / 255,
01026     ( GLfloat )color.green() / 255,
01027     ( GLfloat )color.blue() / 255 );
01028   glLineWidth( lineWidth );
01029   
01030   if ( isStripe )
01031   {
01032     glEnable( GL_LINE_STIPPLE );
01033     glLineStipple( 1, pattern );
01034   }
01035 
01036   glBegin( GL_LINE_LOOP );
01037 
01038   glVertex2f( x1, y1 );
01039   glVertex2f( x1, y2 );
01040   glVertex2f( x2, y2 );
01041   glVertex2f( x2, y1 );
01042 
01043   glEnd();
01044   glDisable( GL_LINE_STIPPLE );
01045 }
01046 
01052 void GLViewer_Drawer::drawPolygon( const GLViewer_PntList& pntList, QColor color )
01053 {
01054   glColor3f( ( GLfloat )color.red() / 255,
01055     ( GLfloat )color.green() / 255,
01056     ( GLfloat )color.blue() / 255 );
01057   glBegin( GL_POLYGON );
01058   QList<GLViewer_Pnt>::const_iterator it = pntList.begin();
01059   for( ; it != pntList.end(); ++it )
01060     glVertex2f( (*it).x(), (*it).y() );
01061   glEnd();
01062 }
01063 
01071 void GLViewer_Drawer::drawPolygon( GLViewer_Rect* rect, QColor color,
01072                                       GLushort pattern, bool isStripe )
01073 {
01074   float x1 = rect->left();
01075   float x2 = rect->right();
01076   float y1 = rect->bottom();
01077   float y2 = rect->top();
01078   glColor3f( ( GLfloat )color.red() / 255,
01079     ( GLfloat )color.green() / 255,
01080     ( GLfloat )color.blue() / 255 );
01081 
01082   if ( isStripe )
01083   {
01084     glEnable( GL_LINE_STIPPLE );
01085     glLineStipple( 1, pattern );
01086   }
01087   glBegin( GL_POLYGON );
01088 
01089   glVertex2f( x1, y1 );
01090   glVertex2f( x1, y2 );
01091   glVertex2f( x2, y2 );
01092   glVertex2f( x2, y1 );
01093 
01094   glEnd();
01095   glDisable( GL_LINE_STIPPLE );
01096 }
01097 
01098 GLubyte rasterVertex[5] = { 0x70, 0xf8, 0xf8, 0xf8, 0x70 };
01099 
01106 void GLViewer_Drawer::drawVertex( GLfloat x, GLfloat y, QColor color )
01107 {
01108   glColor3f( ( GLfloat )color.red() / 255, ( GLfloat )color.green() / 255, ( GLfloat )color.blue() / 255 );
01109   glRasterPos2f( x, y );
01110   glBitmap( 5, 5, 2, 2, 0, 0, rasterVertex );
01111 }
01112 
01113 GLubyte rasterCross[7] =  { 0x82, 0x44, 0x28, 0x10, 0x28, 0x44, 0x82 };
01114 
01121 void GLViewer_Drawer::drawCross( GLfloat x, GLfloat y, QColor color )
01122 {
01123   glColor3f( ( GLfloat )color.red() / 255, ( GLfloat )color.green() / 255, ( GLfloat )color.blue() / 255 );
01124   glRasterPos2f( x, y );
01125   glBitmap( 7, 7, 3, 3, 0, 0, rasterCross );
01126 }
01127 
01140 void GLViewer_Drawer::drawArrow( const GLfloat red, const GLfloat green, const GLfloat blue,
01141                                  GLfloat lineWidth,
01142                                  GLfloat staff, GLfloat length, GLfloat width,
01143                                  GLfloat x, GLfloat y, GLfloat angle, GLboolean filled )
01144 {
01145   GLfloat vx1 = x;
01146   GLfloat vy1 = y + staff + length;
01147   GLfloat vx2 = vx1 - width / 2;
01148   GLfloat vy2 = vy1 - length;
01149   GLfloat vx3 = vx1 + width / 2;
01150   GLfloat vy3 = vy1 - length;
01151 
01152   gp_Pnt2d p0( x, y );
01153   gp_Pnt2d p1( vx1, vy1 );
01154   gp_Pnt2d p2( vx2, vy2 );
01155   gp_Pnt2d p3( vx3, vy3 );
01156 
01157   p1.Rotate( p0, angle );
01158   p2.Rotate( p0, angle );
01159   p3.Rotate( p0, angle );
01160   
01161   vx1 = p1.X(); vy1 = p1.Y();
01162   vx2 = p2.X(); vy2 = p2.Y();
01163   vx3 = p3.X(); vy3 = p3.Y();
01164 
01165   glColor3f( red, green, blue );
01166   glLineWidth( lineWidth );
01167 
01168   glBegin( GL_LINES );
01169   glVertex2f( x, y );
01170   glVertex2f( vx1, vy1 );
01171   glEnd();
01172 
01173   filled = true;
01174   if( !filled )
01175   {
01176     glBegin( GL_LINES );
01177     glVertex2f( vx1, vy1 );
01178     glVertex2f( vx2, vy2 );
01179     glVertex2f( vx1, vy1 );
01180     glVertex2f( vx3, vy3 );
01181     glEnd();
01182   }
01183   else
01184   {
01185     glBegin( GL_POLYGON );
01186     glVertex2f( vx1, vy1 );
01187     glVertex2f( vx2, vy2 );
01188     glVertex2f( vx3, vy3 );
01189     glEnd();
01190   }
01191 }