Salome HOME
05cec9698ec118c6f9d306d14f6e0c6e9a330a68
[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 <qimage.h>
37 #include <qpainter.h>
38
39 #define TEXT_GAP    5
40
41 GLboolean          TFLoaded = GL_FALSE;
42
43 GLdouble           modelMatrix[16], projMatrix[16];
44 GLint              viewport[4];
45 GLdouble           winx, winy, winz;
46 GLint              status;
47
48 GLViewer_TexFont*  staticGlFont;
49
50 //================================================================
51 // Class       : GLViewer_TexFont
52 // Description : 
53 //================================================================
54 //! code of first font symbol
55 static int FirstSymbolNumber = 32;
56 //! code of last font symbol
57 static int LastSymbolNumber = 127;
58
59 QMap<GLViewer_TexFindId,GLViewer_TexIdStored> GLViewer_TexFont::TexFontBase;
60 QMap<GLViewer_TexFindId,GLuint>               GLViewer_TexFont::BitmapFontCache; 
61
62 //=======================================================================
63 // Function: clearTextBases
64 // Purpose :
65 //=======================================================================
66 void GLViewer_TexFont::clearTextBases()
67 {
68   //cout << "Clear font map" << endl;
69   TexFontBase.clear();
70   BitmapFontCache.clear();
71 }
72
73 //======================================================================
74 // Function: GLViewer_TexFont
75 // Purpose :
76 //=======================================================================
77 GLViewer_TexFont::GLViewer_TexFont()
78 {
79     myQFont = QFont::defaultFont();
80     QFontMetrics aFM( myQFont );        
81     myWidths = new int[LastSymbolNumber - FirstSymbolNumber+1];
82     myPositions = new int[LastSymbolNumber - FirstSymbolNumber+1];
83     mySeparator = 2;
84     for( int k = FirstSymbolNumber, aWidth = 0; k <= LastSymbolNumber; k++ )
85     {
86         myWidths[ k - FirstSymbolNumber ] = aFM.width( k );
87         myPositions[ k - FirstSymbolNumber ] = aWidth;
88         aWidth += myWidths[ k - FirstSymbolNumber ] + 2;//mySeparator;
89     }
90
91     myTexFontWidth = 0;
92     myTexFontHeight = 0; 
93     myIsResizeable = false;
94     //myMinMagFilter = GL_NEAREST;
95     myMinMagFilter = GL_LINEAR_ATTENUATION ;
96 }
97
98 //======================================================================
99 // Function: GLViewer_TexFont
100 // Purpose :
101 //=======================================================================
102 GLViewer_TexFont::GLViewer_TexFont( QFont* theFont, int theSeparator, bool theIsResizeable, GLuint theMinMagFilter )
103 {
104     myQFont = *theFont;
105     QFontMetrics aFM( myQFont );        
106     myWidths = new int[LastSymbolNumber - FirstSymbolNumber+1];
107     myPositions = new int[LastSymbolNumber - FirstSymbolNumber+1];
108     mySeparator = theSeparator;
109     for( int k = FirstSymbolNumber, aWidth = 0; k <= LastSymbolNumber; k++ )
110     {
111         myWidths[ k - FirstSymbolNumber ] = aFM.width( k );
112         myPositions[ k - FirstSymbolNumber ] = aWidth;
113         aWidth += myWidths[ k - FirstSymbolNumber ] + 2;//mySeparator;
114     }
115
116     myTexFontWidth = 0;
117     myTexFontHeight = 0;
118     myIsResizeable = theIsResizeable;
119     myMinMagFilter = theMinMagFilter;
120     
121 }
122
123 //======================================================================
124 // Function: ~GLViewer_TexFont
125 // Purpose :
126 //=======================================================================
127 GLViewer_TexFont::~GLViewer_TexFont()
128 {
129     delete[] myWidths;
130     delete[] myPositions;
131
132   
133 //======================================================================
134 // Function: generateTexture
135 // Purpose :
136 //=======================================================================
137 void GLViewer_TexFont::generateTexture()
138 {
139     QFontMetrics aFM( myQFont );
140
141     GLViewer_TexFindId aFindFont;
142     aFindFont.myFontString = myQFont.toString();
143     aFindFont.myViewPortId = (int)QGLContext::currentContext();
144         
145     if( TexFontBase.contains( aFindFont ) )
146     {
147         GLViewer_TexIdStored aTexture = TexFontBase[ aFindFont ];
148         myTexFont = aTexture.myTexFontId;
149         myTexFontWidth = aTexture.myTexFontWidth;
150         myTexFontHeight = aTexture.myTexFontHeight;
151     }    
152     else    
153     {
154         QString aStr;
155         int pixelsWidth = 0;
156         int pixelsHight = aFM.height();
157         myTexFontWidth = 64;
158         myTexFontHeight = 64;
159     
160         pixelsWidth = myWidths[LastSymbolNumber - FirstSymbolNumber] + 
161                       myPositions[LastSymbolNumber - FirstSymbolNumber];
162
163         while( myTexFontWidth < pixelsWidth )
164             myTexFontWidth = myTexFontWidth * 2;
165         while( myTexFontHeight < pixelsHight )
166             myTexFontHeight = myTexFontHeight * 2;
167
168         QPixmap aPixmap( myTexFontWidth, myTexFontHeight );
169         aPixmap.fill( QColor( 0, 0, 0) );
170         QPainter aPainter( &aPixmap );
171         aPainter.setFont( myQFont );
172         for( int l = 0/*, gap = 0*/; l < LastSymbolNumber - FirstSymbolNumber; l++  )
173         {
174             QString aLetter;
175             aLetter += (char)(FirstSymbolNumber + l);
176             aPainter.setPen( QColor( 255,255,255) );
177             aPainter.drawText ( myPositions[l], pixelsHight, aLetter );
178         }
179     
180         QImage aImage = aPixmap.convertToImage();
181         char* pixels = new char[myTexFontWidth * myTexFontHeight * 2];
182
183         for( int i = 0; i < myTexFontHeight; i++ )
184         {            
185             for( int j = 0; j < myTexFontWidth;  j++ )
186             {
187                 int aRed = qRed( aImage.pixel( j, myTexFontHeight - i - 1 ) );
188                 int aGreen = qGreen( aImage.pixel( j, myTexFontHeight - i - 1 ) );
189                 int aBlue = qBlue( aImage.pixel( j, myTexFontHeight - i - 1 ) );
190           
191                 if( aRed != 0 || aGreen != 0 || aBlue != 0 )
192                 {
193                     pixels[i * myTexFontWidth * 2 + j * 2] = (GLubyte)( (aRed + aGreen + aBlue)/3 );
194                     pixels[i * myTexFontWidth * 2 + j * 2 + 1]= (GLubyte) 255;
195                 }
196                 else
197                 {
198                     pixels[i * myTexFontWidth * 2 + j * 2] = (GLubyte) 0;
199                     pixels[i * myTexFontWidth * 2 + j * 2 + 1]= (GLubyte) 0;
200                 }                
201             }
202         }
203
204         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
205         glGenTextures(1, &myTexFont);
206         glBindTexture(GL_TEXTURE_2D, myTexFont);  
207         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
208         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
209         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, myMinMagFilter);
210         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, myMinMagFilter);
211         glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
212         glTexImage2D(GL_TEXTURE_2D, 
213                      0, 
214                      GL_INTENSITY, 
215                      myTexFontWidth,
216                      myTexFontHeight, 
217                      0, 
218                      GL_LUMINANCE_ALPHA, 
219                      GL_UNSIGNED_BYTE, 
220                      pixels);
221     
222         delete[] pixels;
223         
224         GLViewer_TexIdStored aTexture;
225         aTexture.myTexFontId = myTexFont;
226         aTexture.myTexFontWidth = myTexFontWidth;
227         aTexture.myTexFontHeight = myTexFontHeight;
228
229         TexFontBase.insert( aFindFont, aTexture );
230     }
231 }
232
233 //======================================================================
234 // Function: drawString
235 // Purpose :
236 //=======================================================================
237 void GLViewer_TexFont::drawString( QString theStr, GLdouble theX , GLdouble theY )
238 {
239     double aXScale = 1., aYScale = 1.;
240     // store attributes
241     glPushAttrib( GL_ENABLE_BIT | GL_TEXTURE_BIT );
242
243     if ( !myIsResizeable )
244     {
245       glGetDoublev (GL_MODELVIEW_MATRIX, modelMatrix);
246       aXScale = modelMatrix[0];
247       aYScale = modelMatrix[5];
248     }
249
250     glEnable(GL_TEXTURE_2D);
251
252     glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
253     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
254     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
255     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, myMinMagFilter);
256     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, myMinMagFilter);
257
258     glPixelTransferi(GL_MAP_COLOR, 0);
259
260     glAlphaFunc(GL_GEQUAL, 0.05F);
261     glEnable(GL_ALPHA_TEST);
262
263     glEnable(GL_BLEND);
264     glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
265
266     glBindTexture(GL_TEXTURE_2D, myTexFont);
267     glBegin(GL_QUADS);
268
269     theY = theY - ( myTexFontHeight - QFontMetrics( myQFont ).height() ) / aYScale;
270
271     double aLettBegin, aLettEnd, aDY = ( myTexFontHeight - 1 ) / aYScale, aDX;
272     char aLetter;
273     int aLettIndex;
274     for( int i = 0; i < theStr.length(); i++ )
275     {
276         aLetter    = theStr.data()[i];
277         aLettIndex = (int)aLetter - FirstSymbolNumber;
278
279         aLettBegin = (double)myPositions[aLettIndex] / ( (double)myTexFontWidth - 1. );
280         aLettEnd   = aLettBegin + ( (double)myWidths[aLettIndex] - 1. ) / ( (double)myTexFontWidth - 1. );
281
282         aDX = ( (double)myWidths[aLettIndex] - 1. ) / aXScale;
283
284         glTexCoord2d( aLettBegin, 0.0 ); glVertex3d( theX,       theY,       1.0 );
285         glTexCoord2d( aLettBegin, 1.0 ); glVertex3d( theX,       theY + aDY, 1.0 );
286         glTexCoord2d( aLettEnd,   1.0 ); glVertex3d( theX + aDX, theY + aDY, 1.0 );
287         glTexCoord2d( aLettEnd,   0.0 ); glVertex3d( theX + aDX, theY,       1.0 );
288
289         theX += aDX + mySeparator / aXScale;
290     }
291
292     glEnd();
293     // restore attributes
294     glPopAttrib();
295 }
296
297 //======================================================================
298 // Function: getStringWidth
299 // Purpose :
300 //=======================================================================
301 int GLViewer_TexFont::getStringWidth( QString theStr )
302 {
303     int aWidth = 0;
304     for( int i = 0; i < theStr.length(); i ++ )
305     {
306         char aLetter = theStr.data()[i];
307         int aLettIndex = (int)aLetter - FirstSymbolNumber;
308         aWidth += myWidths[aLettIndex] + mySeparator;
309     }
310
311     return aWidth;
312 }
313
314 //======================================================================
315 // Function: getStringHeight
316 // Purpose :
317 //=======================================================================
318 int GLViewer_TexFont::getStringHeight()
319 {
320     QFontMetrics aFM( myQFont );
321     return aFM.height();
322 }
323
324 //! function for generation list base for bitmap fonts
325 static GLuint displayListBase( QFont* theFont )
326 {
327   GLuint aList = 0;
328   //static QMap<GLViewer_TexFindId, GLuint> fontCache;
329   GLViewer_TexFindId aFindFont;
330   aFindFont.myFontString = theFont->toString();
331
332 #ifdef WIN32
333   HGLRC ctx = ::wglGetCurrentContext();
334   if ( !ctx )
335     return aList;  
336   
337   aFindFont.myViewPortId = (int)ctx;
338
339   if ( GLViewer_TexFont::BitmapFontCache.contains( aFindFont ) )
340     aList = GLViewer_TexFont::BitmapFontCache[aFindFont];
341   else
342   {
343     GLuint listBase = 0;
344     QMap<GLViewer_TexFindId, GLuint>::iterator it = GLViewer_TexFont::BitmapFontCache.begin();
345     for ( ; it != GLViewer_TexFont::BitmapFontCache.end(); ++it )
346     {
347       if ( it.key().myViewPortId == (int)ctx && it.data() > listBase )
348         listBase = it.data();
349     }
350     listBase += 256;
351
352     HDC glHdc = ::wglGetCurrentDC();
353     ::SelectObject( glHdc, theFont->handle() );
354     if ( !::wglUseFontBitmaps( glHdc, 0, 256, listBase ) )
355       listBase = 0;
356     aList = listBase;
357     GLViewer_TexFont::BitmapFontCache[aFindFont] = aList;
358   }
359 #else //X Window
360   Display* aDisp = glXGetCurrentDisplay();
361   if( !aDisp )
362   {
363 #ifdef _DEBUG_
364     printf( "Can't find current dislay\n" );
365 #endif
366     return aList;
367   }
368   
369   GLXContext aCont = glXGetCurrentContext();
370   if( !aCont )
371   {
372 #ifdef _DEBUG_
373     printf( "Can't find current context\n" );
374 #endif
375     return aList;
376   }
377
378   aFindFont.myViewPortId = (int)aCont;
379
380   if ( GLViewer_TexFont::BitmapFontCache.contains( aFindFont ) )
381     aList = GLViewer_TexFont::BitmapFontCache[aFindFont];
382   else
383   {
384     GLuint listBase = 0;
385     QMap<GLViewer_TexFindId, GLuint>::iterator it = GLViewer_TexFont::BitmapFontCache.begin();
386     for ( ; it != GLViewer_TexFont::BitmapFontCache.end(); ++it )
387     {
388       if ( it.key().myViewPortId == (int)aCont && it.data() > listBase )
389         listBase = it.data();
390     }
391     listBase += 256;
392     
393     //glXUseXFont( (Font)(theFont->handle()), 0, 256, listBase );
394     int aFontCont = 0;
395     char** xFontList = XListFonts( aDisp, aFindFont.myFontString.data(), 1, &aFontCont  );
396     if( !theFont->handle() )
397     {       
398 #ifdef _DEBUG_
399       printf( "Can't load font %s. loading default font....\n", aFindFont.myFontString.data() );
400 #endif
401       QString aFontMask ("-*-*-*-r-*-*-");
402       aFontMask += aFindFont.myFontString.section( ',', 1, 1 );
403 #ifdef _DEBUG_
404       printf( "Height of Default font: %s\n", aFindFont.myFontString.section( ',', 1, 1 ).data() );
405 #endif
406       aFontMask += "-*-*-*-m-*-*-*";
407       xFontList = XListFonts( aDisp, aFontMask.data()/*"-*-*-*-r-*-*-12-*-*-*-m-*-*-*"*/, 1, &aFontCont  );
408       if( aFontCont == 0 )
409       {      
410 #ifdef _DEBUG_
411         printf( "Can't load default font\n" );
412 #endif
413         return 0;
414       }
415       glXUseXFont( (Font)(XLoadFont( aDisp,xFontList[0] )), 0, 256, listBase );
416     }
417     else
418       glXUseXFont( (Font)(theFont->handle()), 0, 256, listBase );
419     
420     aList = listBase;
421     GLViewer_TexFont::BitmapFontCache[aFindFont] = aList;
422   }
423
424 #endif
425
426   return aList;
427 }
428
429 /***************************************************************************
430 **  Class:   GLViewer_Drawer
431 **  Descr:   Drawer for GLViewer_Object
432 **  Module:  GLViewer
433 **  Created: UI team, 01.10.01
434 ****************************************************************************/
435 //======================================================================
436 // Function: GLViewer_Drawer
437 // Purpose :
438 //=======================================================================
439 GLViewer_Drawer::GLViewer_Drawer()
440 : myFont( "Helvetica", 10, QFont::Bold )
441 {
442   myXScale = myYScale = 0.0;
443   myObjects.clear();
444   myTextList = 0/*-1*/;
445   myObjectType = "GLViewer_Object";
446   myPriority = 0;
447   myTextFormat = DTF_BITMAP;
448 }
449
450 //======================================================================
451 // Function: ~GLViewer_Drawer
452 // Purpose :
453 //=======================================================================
454 GLViewer_Drawer::~GLViewer_Drawer()
455 {
456   myObjects.clear();
457   glDeleteLists( myTextList, 1 );
458 }
459
460 //======================================================================
461 // Function: destroyAllTextures
462 // Purpose :
463 //=======================================================================
464 void GLViewer_Drawer::destroyAllTextures()
465 {
466     QMap<GLViewer_TexFindId,GLViewer_TexIdStored>::Iterator anIt= GLViewer_TexFont::TexFontBase.begin();
467     QMap<GLViewer_TexFindId,GLViewer_TexIdStored>::Iterator anEndIt= GLViewer_TexFont::TexFontBase.end();
468
469     for( ; anIt != anEndIt; anIt++ )
470         glDeleteTextures( 1, &(anIt.data().myTexFontId) );
471 }
472
473 //=======================================================================
474 // Function: setAntialiasing
475 // Purpose : The function enables and disables antialiasing in Open GL (for points, lines and polygons).
476 //=======================================================================
477 void GLViewer_Drawer::setAntialiasing(const bool on)
478 {
479         if (on)
480         {
481     glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
482     glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);
483
484                 glEnable(GL_POINT_SMOOTH);
485                 glEnable(GL_LINE_SMOOTH);
486                 glEnable(GL_POLYGON_SMOOTH);
487                 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 
488                 glEnable (GL_BLEND);
489         }
490         else
491         {
492                 glDisable(GL_POINT_SMOOTH);
493                 glDisable(GL_LINE_SMOOTH);
494                 glDisable(GL_POLYGON_SMOOTH);
495                 glBlendFunc (GL_ONE, GL_ZERO);
496                 glDisable (GL_BLEND);
497         }
498 }
499
500 //======================================================================
501 // Function: loadTexture
502 // Purpose :
503 //=======================================================================
504 GLuint GLViewer_Drawer::loadTexture( const QString& fileName )
505 {
506     QImage buf;
507     if ( fileName.isEmpty() || !buf.load( fileName ) )
508         return 0;
509
510     int w = buf.width();
511     int h = buf.height();
512
513     int size = 16;
514     while( size < w || size < h )
515         size = size * 2;
516
517     GLuint texture;
518     GLubyte* pixels = new GLubyte[ size * size * 4 ];
519
520     for( int i = 0; i < size; i++ )
521     {            
522         for( int j = 0; j < size; j++ )
523         {
524             GLubyte r, g, b, a;
525             if( j < w && i < h )
526             {
527                 QRgb pixel = buf.pixel( j, h - i - 1 );
528                 r = (GLubyte)qRed( pixel );
529                 g = (GLubyte)qGreen( pixel );
530                 b = (GLubyte)qBlue( pixel );
531                 a = (GLubyte)qAlpha( pixel );
532             }
533             else
534             {
535                 r = (GLubyte)255;
536                 g = (GLubyte)255;
537                 b = (GLubyte)255;
538                 a = (GLubyte)255;
539             }
540
541             int index = 4 * ( i * size + j );
542             pixels[ index ] = r;
543             pixels[ index + 1 ] = g;
544             pixels[ index + 2 ] = b;
545             pixels[ index + 3 ] = a;
546         }
547     }
548
549     //initialize texture
550     glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
551     glGenTextures( 1, &texture );
552     glBindTexture( GL_TEXTURE_2D, texture );
553     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
554     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
555     glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, size, size, 0,
556                   GL_RGBA, GL_UNSIGNED_BYTE, pixels );
557
558     delete[] pixels;
559
560     return texture;
561 }
562
563 //======================================================================
564 // Function: drawTexture
565 // Purpose :
566 //=======================================================================
567 void GLViewer_Drawer::drawTexture( GLuint texture, GLint size, GLfloat x, GLfloat y )
568 {
569     if( !texture )
570         return;
571
572     glEnable( GL_TEXTURE_2D );
573     glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
574     bool hasAlpha = glIsEnabled( GL_ALPHA_TEST );
575     glDisable( GL_ALPHA_TEST );
576     
577     glBindTexture( GL_TEXTURE_2D, texture );
578     glBegin( GL_QUADS );
579     
580     glTexCoord2f( 0.0, 0.0 );
581     glVertex3f( x-size/2., y-size/2., 0.0 );
582
583     glTexCoord2f( 0.0, 1.0 );
584     glVertex3f( x-size/2., y+size/2., 0.0 );
585
586     glTexCoord2f( 1.0, 1.0 );
587     glVertex3f( x+size/2., y+size/2., 0.0 );
588
589     glTexCoord2f( 1.0, 0.0 );
590     glVertex3f( x+size/2., y-size/2., 0.0 );
591     
592     glEnd();
593
594     if ( hasAlpha )
595       glEnable( GL_ALPHA_TEST );
596     glDisable( GL_TEXTURE_2D );
597 }
598
599 //======================================================================
600 // Function: drawText
601 // Purpose :
602 //=======================================================================
603 void GLViewer_Drawer::drawText( const QString& text, GLfloat xPos, GLfloat yPos,
604                                 const QColor& color, QFont* theFont, int theSeparator, DisplayTextFormat theFormat )
605 {
606   glColor3f( ( GLfloat )color.red() / 255, 
607              ( GLfloat )color.green() / 255, 
608              ( GLfloat )color.blue() / 255 );
609
610   if( theFormat != DTF_BITMAP )
611   {
612     GLViewer_TexFont aTexFont( theFont, theSeparator, theFormat == DTF_TEXTURE_SCALABLE, GL_LINEAR );
613     aTexFont.generateTexture();
614     aTexFont.drawString( text, xPos, yPos );
615   }
616   else
617   {
618     glRasterPos2f( xPos, yPos );
619     glListBase( displayListBase( theFont ) );
620     glCallLists( text.length(), GL_UNSIGNED_BYTE, text.local8Bit().data() );
621   }
622 }
623
624 //======================================================================
625 // Function: drawText
626 // Purpose :
627 //=======================================================================
628 void GLViewer_Drawer::drawText( GLViewer_Object* theObject )
629 {
630   if( !theObject )
631     return;
632
633   GLViewer_Text* aText = theObject->getGLText();
634   if( !aText )
635     return;
636
637   GLfloat aPosX, aPosY;
638   aText->getPosition( aPosX, aPosY );
639   // get temporary copy of font
640   QFont aTmpVarFont = aText->getFont();
641   drawText( aText->getText(), aPosX, aPosY, aText->getColor(), &aTmpVarFont, aText->getSeparator(), aText->getDisplayTextFormat() );
642 }
643
644 //======================================================================
645 // Function: drawGLText
646 // Purpose :
647 //=======================================================================
648 void GLViewer_Drawer::drawGLText( QString text, float x, float y,
649                                   int hPosition, int vPosition, QColor color, bool smallFont )
650 {
651   QFont aFont( myFont );
652   if( smallFont )
653     aFont.setPointSize( aFont.pointSize() * 0.8 );
654
655   QFontMetrics aFontMetrics( aFont );
656   float width  = myTextFormat == DTF_TEXTURE_SCALABLE ? aFontMetrics.width( text ) : aFontMetrics.width( text ) / myXScale;
657   float height = myTextFormat == DTF_TEXTURE_SCALABLE ? aFontMetrics.height() : aFontMetrics.height() / myYScale;
658   float gap = 5 / myXScale;
659
660   switch( hPosition )
661   {
662       case GLText_Left   : x -= ( gap + width ); break;
663       case GLText_Center : x -= width / 2; break;
664       case GLText_Right  : x += gap; break;
665       default : break;
666   }
667
668   switch( vPosition )
669   {
670       case GLText_Top    : y += height * 0.5; break;
671       case GLText_Center : y -= height * 0.5; break;
672       case GLText_Bottom : y -= height * 1.5; break;
673       default : break;
674   }
675
676   drawText( text, x, y, color, &aFont, 2, myTextFormat );
677 }
678
679 //======================================================================
680 // Function: drawRectangle
681 // Purpose :
682 //=======================================================================
683 void GLViewer_Drawer::drawRectangle( GLViewer_Rect* rect, QColor color )
684 {
685   if( !rect )
686     return;
687
688   float x1 = rect->left();
689   float x2 = rect->right();
690   float y1 = rect->bottom();
691   float y2 = rect->top();
692   
693   glColor3f( ( GLfloat )color.red() / 255,
694     ( GLfloat )color.green() / 255,
695     ( GLfloat )color.blue() / 255 );
696   glLineWidth( 1.0 );
697   
698   glBegin( GL_LINE_LOOP );
699   glVertex2f( x1, y1 );
700   glVertex2f( x1, y2 );
701   glVertex2f( x2, y2 );
702   glVertex2f( x2, y1 );
703   glEnd();
704 }
705
706 //======================================================================
707 // Function: translateToHPGL
708 // Purpose :
709 //=======================================================================
710 bool GLViewer_Drawer::translateToHPGL( QFile& hFile, GLViewer_CoordSystem* aViewerCS, GLViewer_CoordSystem* aHPGLCS )
711 {
712     bool result = true;
713     for( int i=0, n=myObjects.count(); i<n; i++ ) 
714         result &= myObjects[i]->translateToHPGL( hFile, aViewerCS, aHPGLCS );
715     return result;
716 }
717
718 //======================================================================
719 // Function: translateToPS
720 // Purpose :
721 //=======================================================================
722 bool GLViewer_Drawer::translateToPS( QFile& hFile, GLViewer_CoordSystem* aViewerCS, GLViewer_CoordSystem* aPSCS )
723 {
724     bool result = true;
725     for( int i=0, n=myObjects.count(); i<n; i++ ) 
726         result &= myObjects[i]->translateToPS( hFile, aViewerCS, aPSCS );
727     return result;
728 }
729
730 #ifdef WIN32
731 //======================================================================
732 // Function: translateToEMF
733 // Purpose :
734 //=======================================================================
735 bool GLViewer_Drawer::translateToEMF( HDC hDC, GLViewer_CoordSystem* aViewerCS, GLViewer_CoordSystem* aEMFCS )
736 {
737     bool result = true;
738     for( int i=0, n=myObjects.count(); i<n; i++ ) 
739         result &= myObjects[i]->translateToEMF( hDC, aViewerCS, aEMFCS );
740     return result;
741 }
742 #endif