]> SALOME platform Git repositories - modules/gui.git/blob - src/GLViewer/GLViewer_Drawer.cxx
Salome HOME
Merge from OCC_development_generic_2006
[modules/gui.git] / src / GLViewer / GLViewer_Drawer.cxx
1 //  Copyright (C) 2005 OPEN CASCADE
2 //
3 //  This library is free software; you can redistribute it and/or
4 //  modify it under the terms of the GNU Lesser General Public
5 //  License as published by the Free Software Foundation; either
6 //  version 2.1 of the License.
7 //
8 //  This library is distributed in the hope that it will be useful,
9 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
10 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 //  Lesser General Public License for more details.
12 //
13 //  You should have received a copy of the GNU Lesser General Public
14 //  License along with this library; if not, write to the Free Software
15 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 //  See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org
18 //
19 //  Author : OPEN CASCADE
20 //
21
22 // File:      GLViewer_Drawer.cxx
23 // Created:   November, 2004
24
25 //#include <GLViewerAfx.h>
26 #include "GLViewer_Drawer.h"
27 #include "GLViewer_Object.h"
28 #include "GLViewer_Text.h"
29 #include "GLViewer_ViewFrame.h"
30 #include "GLViewer_ViewPort2d.h"
31
32 #ifndef WIN32
33 #include <GL/glx.h>
34 #endif
35
36 #include <gp_Pnt2d.hxx>
37
38 #include <qimage.h>
39 #include <qpainter.h>
40
41 #define TEXT_GAP    5
42 // Two texture components for texmapped fonts: luminance and alpha
43 #define NB_TEX_COMP 2
44 // A font is split into rows each containing 32 characters
45 #define TEX_ROW_LEN 32
46 // Gap in pixels between two character rows in a font texture
47 #define TEX_ROW_GAP 2
48
49 GLfloat modelMatrix[16];
50
51 //================================================================
52 // Class       : GLViewer_TexFont
53 // Description : 
54 //================================================================
55 //! code of first font symbol
56 static int FirstSymbolNumber = 32;
57 //! code of last font symbol
58 static int LastSymbolNumber = 127;
59
60 QMap<GLViewer_TexFindId,GLViewer_TexIdStored> GLViewer_TexFont::TexFontBase;
61 QMap<GLViewer_TexFindId,GLuint>               GLViewer_TexFont::BitmapFontCache; 
62
63 //=======================================================================
64 // Function: clearTextBases
65 // Purpose :
66 //=======================================================================
67 void GLViewer_TexFont::clearTextBases()
68 {
69   //cout << "Clear font map" << endl;
70   TexFontBase.clear();
71   BitmapFontCache.clear();
72 }
73
74 //======================================================================
75 // Function: GLViewer_TexFont
76 // Purpose :
77 //=======================================================================
78 GLViewer_TexFont::GLViewer_TexFont()
79 : myMaxRowWidth( 0 ), myFontHeight( 0 )
80 {
81     myQFont = QFont::defaultFont();
82     mySeparator = 2;
83     myIsResizeable = false;
84     myMinMagFilter = GL_LINEAR;
85
86     init();
87 }
88
89 //======================================================================
90 // Function: GLViewer_TexFont
91 // Purpose :
92 //=======================================================================
93 GLViewer_TexFont::GLViewer_TexFont( QFont* theFont, int theSeparator, bool theIsResizeable, GLuint theMinMagFilter )
94 : myMaxRowWidth( 0 ), myFontHeight( 0 )
95 {
96     myQFont = *theFont;
97     mySeparator = theSeparator;
98     myIsResizeable = theIsResizeable;
99     myMinMagFilter = theMinMagFilter;
100
101     init();
102 }
103
104 //======================================================================
105 // Function: ~GLViewer_TexFont
106 // Purpose :
107 //=======================================================================
108 GLViewer_TexFont::~GLViewer_TexFont()
109 {
110     delete[] myWidths;
111     delete[] myPositions;
112
113
114 //======================================================================
115 // Function: init
116 // Purpose :
117 //=======================================================================
118 void GLViewer_TexFont::init()
119 {
120     myNbSymbols = LastSymbolNumber - FirstSymbolNumber + 1;
121
122     // It is unsafe to draw all characters in a single row -
123     // this leads to problems on some graphic cards with small GL_MAX_TEXTURE_SIZE.
124     // So splitting the characters into rows each containing 32 characters (or less).
125     // Assuming contant height of each row (64 pixels) to simplify texture mapping.
126     // However, this can be improved if necessary.
127     QFontMetrics aFM( myQFont ); 
128     myFontHeight = aFM.height();
129     
130     myWidths    = new int[myNbSymbols];
131     myPositions = new int[myNbSymbols];
132
133     for( int i = 0, k = FirstSymbolNumber, aWidth = 0; i < myNbSymbols; i++, k++ )
134     {
135         // is it time to start a new row?
136         if ( !( i % TEX_ROW_LEN ) )
137         {
138           if( aWidth > myMaxRowWidth )
139             myMaxRowWidth = aWidth;
140           aWidth = 0;
141         }
142         myWidths[i]    = aFM.width( k );
143         myPositions[i] = aWidth;
144         aWidth += myWidths[i] + 2;
145     }
146
147     myTexFontWidth  = 0;
148     myTexFontHeight = 0;
149 }
150   
151 //======================================================================
152 // Function: generateTexture
153 // Purpose :
154 //=======================================================================
155 bool GLViewer_TexFont::generateTexture()
156 {
157     GLViewer_TexFindId aFindFont;
158     aFindFont.myFontFamily = myQFont.family();//myQFont.toString();
159     aFindFont.myIsBold = myQFont.bold();
160     aFindFont.myIsItal = myQFont.italic();
161     aFindFont.myIsUndl = myQFont.underline();
162     aFindFont.myPointSize = myQFont.pointSize();
163     aFindFont.myViewPortId = (int)QGLContext::currentContext();
164         
165     if( TexFontBase.contains( aFindFont ) )
166     {
167         GLViewer_TexIdStored aTexture = TexFontBase[ aFindFont ];
168         myTexFont = aTexture.myTexFontId;
169         myTexFontWidth = aTexture.myTexFontWidth;
170         myTexFontHeight = aTexture.myTexFontHeight;
171     }    
172     else    
173     {
174         // Adding some pixels to have a gap between rows
175         int aRowPixelHeight = myFontHeight + TEX_ROW_GAP;
176         int aDescent = QFontMetrics( myQFont ).descent();
177
178         int aNumRows = myNbSymbols / TEX_ROW_LEN;
179         if ( myNbSymbols % TEX_ROW_LEN ) 
180           aNumRows++;
181         int pixelsHight = aNumRows * aRowPixelHeight;
182
183         myTexFontWidth  = 64;
184         myTexFontHeight = 64;
185
186         while( myTexFontWidth < myMaxRowWidth )
187             myTexFontWidth <<= 1;
188         while( myTexFontHeight < pixelsHight )
189             myTexFontHeight <<= 1;
190         
191         // Checking whether the texture dimensions for the requested font
192         // do not exceed the maximum size supported by the OpenGL implementation
193         int maxSize;
194         glGetIntegerv( GL_MAX_TEXTURE_SIZE, &maxSize );
195         if ( myTexFontWidth > maxSize || myTexFontHeight > maxSize )
196           return false;
197
198         QPixmap aPixmap( myTexFontWidth, myTexFontHeight );
199         aPixmap.fill( QColor( 0, 0, 0) );
200         QPainter aPainter( &aPixmap );
201         aPainter.setFont( myQFont );
202         int row;
203         for( int l = 0; l < myNbSymbols; l++  )
204         {
205             row = l / TEX_ROW_LEN;
206             QString aLetter;
207             aLetter += (char)(FirstSymbolNumber + l);
208             aPainter.setPen( QColor( 255,255,255) );
209             aPainter.drawText( myPositions[l], ( row + 1 ) * aRowPixelHeight - aDescent, aLetter );
210         }
211     
212         QImage aImage = aPixmap.convertToImage();
213
214         //int qqq = 0;
215         //if (qqq)
216         //  aImage.save("w:\\work\\CATHARE\\texture.png", "PNG");
217
218         char* pixels = new char[myTexFontWidth * myTexFontHeight * NB_TEX_COMP];
219
220         for( int i = 0; i < myTexFontHeight; i++ )
221         {            
222             for( int j = 0; j < myTexFontWidth;  j++ )
223             {
224                 int aRed = qRed( aImage.pixel( j, myTexFontHeight - i - 1 ) );
225                 int aGreen = qGreen( aImage.pixel( j, myTexFontHeight - i - 1 ) );
226                 int aBlue = qBlue( aImage.pixel( j, myTexFontHeight - i - 1 ) );
227           
228                 if( aRed != 0 || aGreen != 0 || aBlue != 0 )
229                 {
230                     pixels[i * myTexFontWidth * NB_TEX_COMP + j * NB_TEX_COMP] = (GLubyte)( (aRed + aGreen + aBlue)/3 );
231                     pixels[i * myTexFontWidth * NB_TEX_COMP + j * NB_TEX_COMP + 1]= (GLubyte) 255;
232                 }
233                 else
234                 {
235                     pixels[i * myTexFontWidth * NB_TEX_COMP + j * NB_TEX_COMP] = (GLubyte) 0;
236                     pixels[i * myTexFontWidth * NB_TEX_COMP + j * NB_TEX_COMP + 1]= (GLubyte) 0;
237                 }                
238             }
239         }
240
241         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
242         glGenTextures(1, &myTexFont);
243         glBindTexture(GL_TEXTURE_2D, myTexFont);  
244         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, myMinMagFilter);
245         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, myMinMagFilter);
246         glTexImage2D(GL_TEXTURE_2D, 
247                      0, 
248                      GL_INTENSITY, 
249                      myTexFontWidth,
250                      myTexFontHeight, 
251                      0, 
252                      GL_LUMINANCE_ALPHA, 
253                      GL_UNSIGNED_BYTE, 
254                      pixels);
255     
256         delete[] pixels;
257         
258         GLViewer_TexIdStored aTexture;
259         aTexture.myTexFontId = myTexFont;
260         aTexture.myTexFontWidth = myTexFontWidth;
261         aTexture.myTexFontHeight = myTexFontHeight;
262
263         TexFontBase.insert( aFindFont, aTexture );
264     }
265     return true;
266 }
267
268 //======================================================================
269 // Function: drawString
270 // Purpose :
271 //=======================================================================
272 void GLViewer_TexFont::drawString( QString theStr, GLdouble theX , GLdouble theY, GLfloat theScale )
273 {
274     // Adding some pixels to have a gap between rows
275     int aRowPixelHeight = myFontHeight + TEX_ROW_GAP;
276
277     float aXScale = 1.f, aYScale = 1.f;
278     if ( !myIsResizeable )
279     {
280       glGetFloatv (GL_MODELVIEW_MATRIX, modelMatrix);
281       aXScale = modelMatrix[0];
282       aYScale = modelMatrix[5];     
283     } 
284     else if ( theScale > 0.f )
285     {
286       aXScale = aXScale / theScale;
287       aYScale = aYScale / theScale;
288     }
289
290     // store attributes
291     glPushAttrib( GL_ENABLE_BIT | GL_TEXTURE_BIT );
292
293     glEnable(GL_TEXTURE_2D);
294     glPixelTransferi(GL_MAP_COLOR, 0);
295
296     glAlphaFunc(GL_GEQUAL, 0.05F);
297     glEnable(GL_ALPHA_TEST);
298
299     glEnable(GL_BLEND);
300     glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
301
302     glBindTexture(GL_TEXTURE_2D, myTexFont);
303     glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
304
305     glBegin(GL_QUADS);
306
307     float aLettBeginS, aLettEndS, aLettBeginT, aLettEndT;
308     float aDY = ( aRowPixelHeight - 1 ) / aYScale, aDX;
309     char aLetter;
310     int aLettIndex, row;
311     for( int i = 0; i < theStr.length(); i++ )
312     {
313         aLetter    = theStr.data()[i];
314         aLettIndex = (int)aLetter - FirstSymbolNumber;
315         row        = aLettIndex / TEX_ROW_LEN;
316
317         aLettBeginS = (float)myPositions[aLettIndex] / ( (float)myTexFontWidth - 1.f );
318         aLettEndS   = aLettBeginS + ( (float)myWidths[aLettIndex] - 1.f ) / ( (float)myTexFontWidth - 1.f );
319         aLettBeginT = ( myTexFontHeight - ( row + 1 ) * aRowPixelHeight ) / ( (float)myTexFontHeight - 1.f ); 
320         aLettEndT   = aLettBeginT + ( (float)aRowPixelHeight - 1.f ) / ( (float)myTexFontHeight - 1.f );
321
322         aDX = ( (float)myWidths[aLettIndex] - 1.f ) / aXScale;
323
324         glTexCoord2f( aLettBeginS, aLettBeginT ); glVertex3f( theX,       theY,       1.f );
325         glTexCoord2f( aLettBeginS, aLettEndT   ); glVertex3f( theX,       theY + aDY, 1.f );
326         glTexCoord2f( aLettEndS,   aLettEndT   ); glVertex3f( theX + aDX, theY + aDY, 1.f );
327         glTexCoord2f( aLettEndS,   aLettBeginT ); glVertex3f( theX + aDX, theY,       1.f );
328
329         theX += aDX + mySeparator / aXScale;
330     }
331
332     glEnd();
333     // restore attributes
334     glPopAttrib();
335 }
336
337 //======================================================================
338 // Function: getStringWidth
339 // Purpose :
340 //=======================================================================
341 int GLViewer_TexFont::getStringWidth( QString theStr )
342 {
343     int aWidth = 0;
344     for( int i = 0; i < theStr.length(); i ++ )
345     {
346         char aLetter = theStr.data()[i];
347         int aLettIndex = (int)aLetter - FirstSymbolNumber;
348         aWidth += myWidths[aLettIndex] + mySeparator;
349     }
350
351     return aWidth;
352 }
353
354 //======================================================================
355 // Function: getStringHeight
356 // Purpose :
357 //=======================================================================
358 int GLViewer_TexFont::getStringHeight()
359 {
360     QFontMetrics aFM( myQFont );
361     return aFM.height();
362 }
363
364 //! function for generation list base for bitmap fonts
365 static GLuint displayListBase( QFont* theFont )
366 {
367   if ( !theFont )
368     return 0;
369   GLuint aList = 0;
370   //static QMap<GLViewer_TexFindId, GLuint> fontCache;
371   GLViewer_TexFindId aFindFont;
372   aFindFont.myFontFamily = theFont->family();//theFont->toString();
373   aFindFont.myIsBold = theFont->bold();
374   aFindFont.myIsItal = theFont->italic();
375   aFindFont.myIsUndl = theFont->underline();
376   aFindFont.myPointSize = theFont->pointSize();
377
378 #ifdef WIN32
379   HGLRC ctx = ::wglGetCurrentContext();
380   if ( !ctx )
381     return aList;  
382   
383   aFindFont.myViewPortId = (int)ctx;
384
385   if ( GLViewer_TexFont::BitmapFontCache.contains( aFindFont ) )
386     aList = GLViewer_TexFont::BitmapFontCache[aFindFont];
387   else
388   {
389     GLuint listBase = 0;
390     QMap<GLViewer_TexFindId, GLuint>::iterator it = GLViewer_TexFont::BitmapFontCache.begin();
391     for ( ; it != GLViewer_TexFont::BitmapFontCache.end(); ++it )
392     {
393       if ( it.key().myViewPortId == (int)ctx && it.data() > listBase )
394         listBase = it.data();
395     }
396     listBase += 256;
397
398     HDC glHdc = ::wglGetCurrentDC();
399     ::SelectObject( glHdc, theFont->handle() );
400     if ( !::wglUseFontBitmaps( glHdc, 0, 256, listBase ) )
401       listBase = 0;
402     aList = listBase;
403     GLViewer_TexFont::BitmapFontCache[aFindFont] = aList;
404   }
405 #else //X Window
406   Display* aDisp = glXGetCurrentDisplay();
407   if( !aDisp )
408   {
409 #ifdef _DEBUG_
410     printf( "Can't find current dislay\n" );
411 #endif
412     return aList;
413   }
414   
415   GLXContext aCont = glXGetCurrentContext();
416   if( !aCont )
417   {
418 #ifdef _DEBUG_
419     printf( "Can't find current context\n" );
420 #endif
421     return aList;
422   }
423
424   aFindFont.myViewPortId = (int)aCont;
425
426   if ( GLViewer_TexFont::BitmapFontCache.contains( aFindFont ) )
427     aList = GLViewer_TexFont::BitmapFontCache[aFindFont];
428   else
429   {
430     GLuint listBase = 0;
431     QMap<GLViewer_TexFindId, GLuint>::iterator it = GLViewer_TexFont::BitmapFontCache.begin();
432     for ( ; it != GLViewer_TexFont::BitmapFontCache.end(); ++it )
433     {
434       if ( it.key().myViewPortId == (int)aCont && it.data() > listBase )
435         listBase = it.data();
436     }
437     listBase += 256;
438     
439     //glXUseXFont( (Font)(theFont->handle()), 0, 256, listBase );
440     int aFontCont = 0;
441     QString aFontDef = theFont->toString();
442     char** xFontList = XListFonts( aDisp, aFontDef.latin1()/*aFindFont.myFontString.data()*/, 1, &aFontCont  );
443     if( !theFont->handle() )
444     {       
445 #ifdef _DEBUG_
446       printf( "Can't load font %s. loading default font....\n", aFontDef.latin1()/*aFindFont.myFontString.data()*/ );
447 #endif
448       QString aFontMask ("-*-*-*-r-*-*-");
449       aFontMask += aFontDef/*aFindFont.myFontString*/.section( ',', 1, 1 );
450 #ifdef _DEBUG_
451       printf( "Height of Default font: %s\n", aFontDef/*aFindFont.myFontString*/.section( ',', 1, 1 ).data() );
452 #endif
453       aFontMask += "-*-*-*-m-*-*-*";
454       xFontList = XListFonts( aDisp, aFontMask.data()/*"-*-*-*-r-*-*-12-*-*-*-m-*-*-*"*/, 1, &aFontCont  );
455       if( aFontCont == 0 )
456       {      
457 #ifdef _DEBUG_
458         printf( "Can't load default font\n" );
459 #endif
460         return 0;
461       }
462       glXUseXFont( (Font)(XLoadFont( aDisp,xFontList[0] )), 0, 256, listBase );
463     }
464     else
465       glXUseXFont( (Font)(theFont->handle()), 0, 256, listBase );
466     
467     aList = listBase;
468     GLViewer_TexFont::BitmapFontCache[aFindFont] = aList;
469   }
470
471 #endif
472
473   return aList;
474 }
475
476 /***************************************************************************
477 **  Class:   GLViewer_Drawer
478 **  Descr:   Drawer for GLViewer_Object
479 **  Module:  GLViewer
480 **  Created: UI team, 01.10.01
481 ****************************************************************************/
482 //======================================================================
483 // Function: GLViewer_Drawer
484 // Purpose :
485 //=======================================================================
486 GLViewer_Drawer::GLViewer_Drawer()
487 : myFont( "Helvetica", 10, QFont::Bold )
488 {
489   myXScale = myYScale = 0.0;
490   myObjects.clear();
491   myTextList = 0/*-1*/;
492   myObjectType = "GLViewer_Object";
493   myPriority = 0;
494   myTextFormat = DTF_BITMAP;
495   myTextScale = 0.125;
496 }
497
498 //======================================================================
499 // Function: ~GLViewer_Drawer
500 // Purpose :
501 //=======================================================================
502 GLViewer_Drawer::~GLViewer_Drawer()
503 {
504   myObjects.clear();
505   glDeleteLists( myTextList, 1 );
506 }
507
508 //======================================================================
509 // Function: destroyAllTextures
510 // Purpose :
511 //=======================================================================
512 void GLViewer_Drawer::destroyAllTextures()
513 {
514     QMap<GLViewer_TexFindId,GLViewer_TexIdStored>::Iterator anIt= GLViewer_TexFont::TexFontBase.begin();
515     QMap<GLViewer_TexFindId,GLViewer_TexIdStored>::Iterator anEndIt= GLViewer_TexFont::TexFontBase.end();
516
517     for( ; anIt != anEndIt; anIt++ )
518         glDeleteTextures( 1, &(anIt.data().myTexFontId) );
519 }
520
521 //=======================================================================
522 // Function: setAntialiasing
523 // Purpose : The function enables and disables antialiasing in Open GL (for points, lines and polygons).
524 //=======================================================================
525 void GLViewer_Drawer::setAntialiasing(const bool on)
526 {
527         if (on)
528         {
529     glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
530     glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);
531
532                 glEnable(GL_POINT_SMOOTH);
533                 glEnable(GL_LINE_SMOOTH);
534                 glEnable(GL_POLYGON_SMOOTH);
535                 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 
536                 glEnable (GL_BLEND);
537         }
538         else
539         {
540                 glDisable(GL_POINT_SMOOTH);
541                 glDisable(GL_LINE_SMOOTH);
542                 glDisable(GL_POLYGON_SMOOTH);
543                 glBlendFunc (GL_ONE, GL_ZERO);
544                 glDisable (GL_BLEND);
545         }
546 }
547
548 //======================================================================
549 // Function: loadTexture
550 // Purpose :
551 //=======================================================================
552 GLuint GLViewer_Drawer::loadTexture( const QString& fileName,
553                                      GLint* x_size,
554                                      GLint* y_size,
555                                      GLint* t_size )
556 {
557     QImage buf;
558     if ( fileName.isEmpty() || !buf.load( fileName ) )
559         return 0;
560
561     int w = buf.width();
562     int h = buf.height();
563
564     int size = 16;
565     while( size < w || size < h )
566         size = size * 2;
567
568     GLuint texture;
569     GLubyte* pixels = new GLubyte[ size * size * 4 ];
570
571     for( int i = 0; i < size; i++ )
572     {            
573         for( int j = 0; j < size; j++ )
574         {
575             GLubyte r, g, b, a;
576             if( j < w && i < h )
577             {
578                 QRgb pixel = buf.pixel( j, h - i - 1 );
579                 r = (GLubyte)qRed( pixel );
580                 g = (GLubyte)qGreen( pixel );
581                 b = (GLubyte)qBlue( pixel );
582                 a = (GLubyte)qAlpha( pixel );
583             }
584             else
585             {
586                 r = (GLubyte)255;
587                 g = (GLubyte)255;
588                 b = (GLubyte)255;
589                 a = (GLubyte)255;
590             }
591
592             int index = 4 * ( i * size + j );
593             pixels[ index ] = r;
594             pixels[ index + 1 ] = g;
595             pixels[ index + 2 ] = b;
596             pixels[ index + 3 ] = a;
597         }
598     }
599
600     //initialize texture
601     glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
602     glGenTextures( 1, &texture );
603     glBindTexture( GL_TEXTURE_2D, texture );
604     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
605     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
606     glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, size, size, 0,
607                   GL_RGBA, GL_UNSIGNED_BYTE, pixels );
608
609     delete[] pixels;
610
611     if ( x_size )
612       *(x_size) = w;
613
614     if ( y_size )
615       *(y_size) = h;
616
617     if ( t_size )
618       *(t_size) = size;
619
620     return texture;
621 }
622
623 //======================================================================
624 // Function: drawTexture
625 // Purpose :
626 //=======================================================================
627 void GLViewer_Drawer::drawTexture( GLuint texture, GLint size, GLfloat x, GLfloat y )
628 {
629     /*float xScale = myXScale;
630     float yScale = myYScale;
631
632     glColor4f( 1.0, 1.0, 1.0, 1.0 );
633
634     glEnable( GL_TEXTURE_2D );
635     glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
636     glAlphaFunc( GL_GREATER, 0.95F );
637     glEnable( GL_ALPHA_TEST );
638     
639     glBindTexture( GL_TEXTURE_2D, texture );
640     glBegin( GL_QUADS );
641
642     glTexCoord2f( 0.0, 0.0 );
643     glVertex3f( x-size/2./xScale, y-size/2./yScale, 0.0 );
644
645     glTexCoord2f( 0.0, 1.0 );
646     glVertex3f( x-size/2./xScale, y+size/2./yScale, 0.0 );
647
648     glTexCoord2f( 1.0, 1.0 );
649     glVertex3f( x+size/2./xScale, y+size/2./yScale, 0.0 );
650
651     glTexCoord2f( 1.0, 0.0 );
652     glVertex3f( x+size/2./xScale, y-size/2./yScale, 0.0 );
653     
654     glEnd();
655     glFlush();
656
657     glDisable( GL_ALPHA_TEST );
658     glDisable( GL_TEXTURE_2D );*/
659
660   drawTexture( texture, size, size, x, y );
661 }
662
663 //======================================================================
664 // Function: drawTexture
665 // Purpose :
666 //=======================================================================
667 void GLViewer_Drawer::drawTexture( GLuint texture, GLint x_size, GLint y_size, GLfloat x, GLfloat y )
668 {
669     /*float xScale = myXScale;
670     float yScale = myYScale;
671
672     glColor4f( 1.0, 1.0, 1.0, 1.0 );
673
674     glEnable( GL_TEXTURE_2D );
675     glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
676     glAlphaFunc( GL_GREATER, 0.95F );
677     glEnable( GL_ALPHA_TEST );
678     
679     glBindTexture( GL_TEXTURE_2D, texture );
680     glBegin( GL_QUADS );
681
682     glTexCoord2f( 0.0, 0.0 );
683     glVertex3f( x-x_size/2./xScale, y-y_size/2./yScale, 0.0 );
684
685     glTexCoord2f( 0.0, 1.0 );
686     glVertex3f( x-x_size/2./xScale, y+y_size/2./yScale, 0.0 );
687
688     glTexCoord2f( 1.0, 1.0 );
689     glVertex3f( x+x_size/2./xScale, y+y_size/2./yScale, 0.0 );
690
691     glTexCoord2f( 1.0, 0.0 );
692     glVertex3f( x+x_size/2./xScale, y-y_size/2./yScale, 0.0 );
693     
694     glEnd();
695     glFlush();
696
697     glDisable( GL_ALPHA_TEST );
698     glDisable( GL_TEXTURE_2D );*/
699   drawTexturePart( texture, 1.0, 1.0, x_size, y_size, x, y );
700 }
701
702 //======================================================================
703 // Function: drawTexture
704 // Purpose :
705 //=======================================================================
706 void GLViewer_Drawer::drawTexturePart( GLuint texture,
707                                        GLfloat x_ratio,
708                                        GLfloat y_ratio,
709                                        GLfloat x_size,
710                                        GLfloat y_size,
711                                        GLfloat x,
712                                        GLfloat y,
713                                        GLfloat scale )
714 {
715   if( !texture )
716     return;
717
718   float xScale = scale > 0. ? 1./scale : myXScale;
719   float yScale = scale > 0. ? 1./scale : myYScale;
720
721   glColor4f( 1.0, 1.0, 1.0, 1.0 );
722
723
724   glEnable( GL_TEXTURE_2D );
725   glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
726   bool hasAlpha = glIsEnabled( GL_ALPHA_TEST );
727   glDisable( GL_ALPHA_TEST );
728
729   glBindTexture( GL_TEXTURE_2D, texture );
730   glBegin( GL_QUADS );
731
732   glTexCoord2f( 0.0, 0.0 );
733   glVertex3f( x-x_size/2./xScale, y-y_size/2./yScale, 0.0 );
734
735   glTexCoord2f( 0.0, y_ratio );
736   glVertex3f( x-x_size/2./xScale, y+y_size/2./yScale, 0.0 );
737
738   glTexCoord2f( x_ratio, y_ratio );
739   glVertex3f( x+x_size/2./xScale, y+y_size/2./yScale, 0.0 );
740
741   glTexCoord2f( x_ratio, 0.0 );
742   glVertex3f( x+x_size/2./xScale, y-y_size/2./yScale, 0.0 );
743   
744   glEnd();
745   glFlush();
746
747   if ( hasAlpha )
748     glEnable( GL_ALPHA_TEST );
749
750   glDisable( GL_TEXTURE_2D );
751 }
752
753 //======================================================================
754 // Function: drawText
755 // Purpose :
756 //=======================================================================
757 void GLViewer_Drawer::drawText( const QString& text, GLfloat xPos, GLfloat yPos,
758                                 const QColor& color, QFont* theFont, int theSeparator, DisplayTextFormat theFormat )
759 {
760   glColor3f( ( GLfloat )color.red() / 255, 
761              ( GLfloat )color.green() / 255, 
762              ( GLfloat )color.blue() / 255 );
763
764   if( theFormat != DTF_BITMAP )
765   {
766     GLViewer_TexFont aTexFont( theFont, theSeparator, theFormat == DTF_TEXTURE_SCALABLE, GL_LINEAR );
767     // Font texture was not found or generated --> cannot draw text
768     if ( !aTexFont.generateTexture() )
769       return;
770
771     if ( theFormat == DTF_TEXTURE_SCALABLE )
772       aTexFont.drawString( text, xPos, yPos, textScale() );
773     else
774       aTexFont.drawString( text, xPos, yPos );
775   }
776   else
777   {
778     glRasterPos2f( xPos, yPos );
779     glListBase( displayListBase( theFont ) );
780     glCallLists( text.length(), GL_UNSIGNED_BYTE, text.local8Bit().data() );
781   }
782 }
783
784 //======================================================================
785 // Function: drawText
786 // Purpose :
787 //=======================================================================
788 void GLViewer_Drawer::drawText( GLViewer_Object* theObject )
789 {
790   if( !theObject )
791     return;
792
793   GLViewer_Text* aText = theObject->getGLText();
794   if( !aText )
795     return;
796
797   GLfloat aPosX, aPosY;
798   aText->getPosition( aPosX, aPosY );
799   // get temporary copy of font
800   QFont aTmpVarFont = aText->getFont();
801   drawText( aText->getText(), aPosX, aPosY, aText->getColor(), &aTmpVarFont, aText->getSeparator(), aText->getDisplayTextFormat() );
802 }
803
804 //======================================================================
805 // Function: drawGLText
806 // Purpose :
807 //=======================================================================
808 void GLViewer_Drawer::drawGLText( QString text, float x, float y,
809                                   int hPosition, int vPosition, QColor color, bool smallFont )
810 {
811   QFont aFont( myFont );
812   if( smallFont )
813     aFont.setPointSize( aFont.pointSize() * 0.8 );
814
815   GLfloat scale = textScale() > 0. ? textScale() : 1.;
816
817   QFontMetrics aFontMetrics( aFont );
818   float width  = myTextFormat == DTF_TEXTURE_SCALABLE ? aFontMetrics.width( text ) * scale : aFontMetrics.width( text ) / myXScale;
819   float height = myTextFormat == DTF_TEXTURE_SCALABLE ? aFontMetrics.height() * scale : aFontMetrics.height() / myYScale;
820   float gap = 5 / myXScale;
821
822   switch( hPosition )
823   {
824       case GLText_Left   : x -= ( gap + width ); break;
825       case GLText_Center : x -= width / 2; break;
826       case GLText_Right  : x += gap; break;
827       default : break;
828   }
829
830   switch( vPosition )
831   {
832       case GLText_Top    : y += height * 0.5; break;
833       case GLText_Center : y -= height * 0.5; break;
834       case GLText_Bottom : y -= height * 1.5; break;
835       default : break;
836   }
837
838   drawText( text, x, y, color, &aFont, 2, myTextFormat );
839 }
840
841 //======================================================================
842 // Function: textRect
843 // Purpose :
844 //=======================================================================
845 GLViewer_Rect GLViewer_Drawer::textRect( const QString& text ) const
846 {
847   GLfloat scale = textScale() > 0. ? textScale() : 1.;
848
849   QFontMetrics aFontMetrics( myFont );
850   float width  = myTextFormat == DTF_TEXTURE_SCALABLE ? aFontMetrics.width( text ) * scale : aFontMetrics.width( text );
851   float height = myTextFormat == DTF_TEXTURE_SCALABLE ? aFontMetrics.height() * scale : aFontMetrics.height();
852
853   return GLViewer_Rect( 0, width, height, 0 );
854 }
855
856 //======================================================================
857 // Function: drawRectangle
858 // Purpose :
859 //=======================================================================
860 void GLViewer_Drawer::drawRectangle( GLViewer_Rect* rect, QColor color )
861 {
862   if( !rect )
863     return;
864
865   float x1 = rect->left();
866   float x2 = rect->right();
867   float y1 = rect->bottom();
868   float y2 = rect->top();
869   
870   glColor3f( ( GLfloat )color.red() / 255,
871     ( GLfloat )color.green() / 255,
872     ( GLfloat )color.blue() / 255 );
873   glLineWidth( 1.0 );
874   
875   glBegin( GL_LINE_LOOP );
876   glVertex2f( x1, y1 );
877   glVertex2f( x1, y2 );
878   glVertex2f( x2, y2 );
879   glVertex2f( x2, y1 );
880   glEnd();
881 }
882
883 //======================================================================
884 // Function: translateToHPGL
885 // Purpose :
886 //=======================================================================
887 bool GLViewer_Drawer::translateToHPGL( QFile& hFile, GLViewer_CoordSystem* aViewerCS, GLViewer_CoordSystem* aHPGLCS )
888 {
889     bool result = true;
890     for( int i=0, n=myObjects.count(); i<n; i++ ) 
891         result &= myObjects[i]->translateToHPGL( hFile, aViewerCS, aHPGLCS );
892     return result;
893 }
894
895 //======================================================================
896 // Function: translateToPS
897 // Purpose :
898 //=======================================================================
899 bool GLViewer_Drawer::translateToPS( QFile& hFile, GLViewer_CoordSystem* aViewerCS, GLViewer_CoordSystem* aPSCS )
900 {
901     bool result = true;
902     for( int i=0, n=myObjects.count(); i<n; i++ ) 
903         result &= myObjects[i]->translateToPS( hFile, aViewerCS, aPSCS );
904     return result;
905 }
906
907 #ifdef WIN32
908 //======================================================================
909 // Function: translateToEMF
910 // Purpose :
911 //=======================================================================
912 bool GLViewer_Drawer::translateToEMF( HDC hDC, GLViewer_CoordSystem* aViewerCS, GLViewer_CoordSystem* aEMFCS )
913 {
914     bool result = true;
915     for( int i=0, n=myObjects.count(); i<n; i++ ) 
916         result &= myObjects[i]->translateToEMF( hDC, aViewerCS, aEMFCS );
917     return result;
918 }
919 #endif
920
921 //======================================================================
922 // Function: drawRectangle
923 // Purpose :
924 //=======================================================================
925 void GLViewer_Drawer::drawRectangle( GLViewer_Rect* rect, GLfloat lineWidth, GLfloat gap,
926                                      QColor color, bool filled, QColor fillingColor )
927 {
928   if( !rect )
929     return;
930
931   float x1 = rect->left() - gap;
932   float x2 = rect->right() + gap;
933   float y1 = rect->bottom() - gap;
934   float y2 = rect->top() + gap;
935   
936   if( filled )
937   {
938     glColor3f( ( GLfloat )fillingColor.red() / 255,
939       ( GLfloat )fillingColor.green() / 255,
940       ( GLfloat )fillingColor.blue() / 255 );
941     glBegin( GL_POLYGON );
942     glVertex2f( x1, y1 );
943     glVertex2f( x1, y2 );
944     glVertex2f( x2, y2 );
945     glVertex2f( x2, y1 );
946     glEnd();
947   }
948
949   glColor3f( ( GLfloat )color.red() / 255,
950     ( GLfloat )color.green() / 255,
951     ( GLfloat )color.blue() / 255 );
952   glLineWidth( lineWidth );
953   
954   glBegin( GL_LINE_LOOP );
955   glVertex2f( x1, y1 );
956   glVertex2f( x1, y2 );
957   glVertex2f( x2, y2 );
958   glVertex2f( x2, y1 );
959   glEnd();
960 }
961
962 //======================================================================
963 // Function: drawContour
964 // Purpose :
965 //=======================================================================
966 void GLViewer_Drawer::drawContour( const GLViewer_PntList& pntList, QColor color, GLfloat lineWidth )
967 {
968   glColor3f( ( GLfloat )color.red() / 255,
969     ( GLfloat )color.green() / 255,
970     ( GLfloat )color.blue() / 255 );
971   glLineWidth( lineWidth );
972   
973   glBegin( GL_LINES );
974   QValueList<GLViewer_Pnt>::const_iterator it = pntList.begin();
975   for( ; it != pntList.end(); ++it )
976     glVertex2f( (*it).x(), (*it).y() );
977   glEnd();
978 }
979
980 //======================================================================
981 // Function: drawContour
982 // Purpose :
983 //=======================================================================
984 void GLViewer_Drawer::drawContour( GLViewer_Rect* rect, QColor color, GLfloat lineWidth,
985                                    GLushort pattern, bool isStripe )
986 {
987   float x1 = rect->left();
988   float x2 = rect->right();
989   float y1 = rect->bottom();
990   float y2 = rect->top();
991   
992   glColor3f( ( GLfloat )color.red() / 255,
993     ( GLfloat )color.green() / 255,
994     ( GLfloat )color.blue() / 255 );
995   glLineWidth( lineWidth );
996   
997   if ( isStripe )
998   {
999     glEnable( GL_LINE_STIPPLE );
1000     glLineStipple( 1, pattern );
1001   }
1002
1003   glBegin( GL_LINE_LOOP );
1004
1005   glVertex2f( x1, y1 );
1006   glVertex2f( x1, y2 );
1007   glVertex2f( x2, y2 );
1008   glVertex2f( x2, y1 );
1009
1010   glEnd();
1011   glDisable( GL_LINE_STIPPLE );
1012 }
1013
1014 //======================================================================
1015 // Function: drawPolygon
1016 // Purpose :
1017 //=======================================================================
1018 void GLViewer_Drawer::drawPolygon( const GLViewer_PntList& pntList, QColor color )
1019 {
1020   glColor3f( ( GLfloat )color.red() / 255,
1021     ( GLfloat )color.green() / 255,
1022     ( GLfloat )color.blue() / 255 );
1023   glBegin( GL_POLYGON );
1024   QValueList<GLViewer_Pnt>::const_iterator it = pntList.begin();
1025   for( ; it != pntList.end(); ++it )
1026     glVertex2f( (*it).x(), (*it).y() );
1027   glEnd();
1028 }
1029
1030 //======================================================================
1031 // Function: drawPolygon
1032 // Purpose :
1033 //=======================================================================
1034 void GLViewer_Drawer::drawPolygon( GLViewer_Rect* rect, QColor color,
1035                                       GLushort pattern, bool isStripe )
1036 {
1037   float x1 = rect->left();
1038   float x2 = rect->right();
1039   float y1 = rect->bottom();
1040   float y2 = rect->top();
1041   glColor3f( ( GLfloat )color.red() / 255,
1042     ( GLfloat )color.green() / 255,
1043     ( GLfloat )color.blue() / 255 );
1044
1045   if ( isStripe )
1046   {
1047     glEnable( GL_LINE_STIPPLE );
1048     glLineStipple( 1, pattern );
1049   }
1050   glBegin( GL_POLYGON );
1051
1052   glVertex2f( x1, y1 );
1053   glVertex2f( x1, y2 );
1054   glVertex2f( x2, y2 );
1055   glVertex2f( x2, y1 );
1056
1057   glEnd();
1058   glDisable( GL_LINE_STIPPLE );
1059 }
1060
1061 //======================================================================
1062 // Function: drawVertex
1063 // Purpose :
1064 //=======================================================================
1065 GLubyte rasterVertex[5] = { 0x70, 0xf8, 0xf8, 0xf8, 0x70 };
1066 void GLViewer_Drawer::drawVertex( GLfloat x, GLfloat y, QColor color )
1067 {
1068   glColor3f( ( GLfloat )color.red() / 255, ( GLfloat )color.green() / 255, ( GLfloat )color.blue() / 255 );
1069   glRasterPos2f( x, y );
1070   glBitmap( 5, 5, 2, 2, 0, 0, rasterVertex );
1071 }
1072
1073 //======================================================================
1074 // Function: drawCross
1075 // Purpose :
1076 //=======================================================================
1077 GLubyte rasterCross[7] =  { 0x82, 0x44, 0x28, 0x10, 0x28, 0x44, 0x82 };
1078 void GLViewer_Drawer::drawCross( GLfloat x, GLfloat y, QColor color )
1079 {
1080   glColor3f( ( GLfloat )color.red() / 255, ( GLfloat )color.green() / 255, ( GLfloat )color.blue() / 255 );
1081   glRasterPos2f( x, y );
1082   glBitmap( 7, 7, 3, 3, 0, 0, rasterCross );
1083 }
1084
1085 //======================================================================
1086 // Function: drawArrow
1087 // Purpose :
1088 //=======================================================================
1089 void GLViewer_Drawer::drawArrow( const GLfloat red, const GLfloat green, const GLfloat blue,
1090                                  GLfloat lineWidth,
1091                                  GLfloat staff, GLfloat length, GLfloat width,
1092                                  GLfloat x, GLfloat y, GLfloat angle, GLboolean filled )
1093 {
1094   GLfloat vx1 = x;
1095   GLfloat vy1 = y + staff + length;
1096   GLfloat vx2 = vx1 - width / 2;
1097   GLfloat vy2 = vy1 - length;
1098   GLfloat vx3 = vx1 + width / 2;
1099   GLfloat vy3 = vy1 - length;
1100
1101   gp_Pnt2d p0( x, y );
1102   gp_Pnt2d p1( vx1, vy1 );
1103   gp_Pnt2d p2( vx2, vy2 );
1104   gp_Pnt2d p3( vx3, vy3 );
1105
1106   p1.Rotate( p0, angle );
1107   p2.Rotate( p0, angle );
1108   p3.Rotate( p0, angle );
1109   
1110   vx1 = p1.X(); vy1 = p1.Y();
1111   vx2 = p2.X(); vy2 = p2.Y();
1112   vx3 = p3.X(); vy3 = p3.Y();
1113
1114   glColor3f( red, green, blue );
1115   glLineWidth( lineWidth );
1116
1117   glBegin( GL_LINES );
1118   glVertex2f( x, y );
1119   glVertex2f( vx1, vy1 );
1120   glEnd();
1121
1122   filled = true;
1123   if( !filled )
1124   {
1125     glBegin( GL_LINES );
1126     glVertex2f( vx1, vy1 );
1127     glVertex2f( vx2, vy2 );
1128     glVertex2f( vx1, vy1 );
1129     glVertex2f( vx3, vy3 );
1130     glEnd();
1131   }
1132   else
1133   {
1134     glBegin( GL_POLYGON );
1135     glVertex2f( vx1, vy1 );
1136     glVertex2f( vx2, vy2 );
1137     glVertex2f( vx3, vy3 );
1138     glEnd();
1139   }
1140 }