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