1 // File: GLViewer_Drawer.cxx
2 // Created: November, 2004
4 // Copyright (C) CEA 2004
6 //#include <GLViewerAfx.h>
7 #include "GLViewer_Drawer.h"
8 #include "GLViewer_Object.h"
9 #include "GLViewer_Text.h"
10 #include "GLViewer_ViewFrame.h"
11 #include "GLViewer_ViewPort2d.h"
22 GLboolean TFLoaded = GL_FALSE;
24 GLdouble modelMatrix[16], projMatrix[16];
26 GLdouble winx, winy, winz;
29 GLViewer_TexFont* staticGlFont;
31 //================================================================
32 // Class : GLViewer_TexFont
34 //================================================================
35 //! code of first font symbol
36 static int FirstSymbolNumber = 32;
37 //! code of last font symbol
38 static int LastSymbolNumber = 127;
40 QMap<GLViewer_TexFindId,GLViewer_TexIdStored> GLViewer_TexFont::TexFontBase;
41 QMap<GLViewer_TexFindId,GLuint> GLViewer_TexFont::BitmapFontCache;
43 //=======================================================================
44 // Function: clearTextBases
46 //=======================================================================
47 void GLViewer_TexFont::clearTextBases()
49 //cout << "Clear font map" << endl;
51 BitmapFontCache.clear();
54 //======================================================================
55 // Function: GLViewer_TexFont
57 //=======================================================================
58 GLViewer_TexFont::GLViewer_TexFont()
60 myQFont = QFont::defaultFont();
61 QFontMetrics aFM( myQFont );
62 myWidths = new int[LastSymbolNumber - FirstSymbolNumber+1];
63 myPositions = new int[LastSymbolNumber - FirstSymbolNumber+1];
65 for( int k = FirstSymbolNumber, aWidth = 0; k <= LastSymbolNumber; k++ )
67 myWidths[ k - FirstSymbolNumber ] = aFM.width( k );
68 myPositions[ k - FirstSymbolNumber ] = aWidth;
69 aWidth += myWidths[ k - FirstSymbolNumber ] + 2;//mySeparator;
76 //======================================================================
77 // Function: GLViewer_TexFont
79 //=======================================================================
80 GLViewer_TexFont::GLViewer_TexFont( QFont* theFont, int theSeparator )
83 QFontMetrics aFM( myQFont );
84 myWidths = new int[LastSymbolNumber - FirstSymbolNumber+1];
85 myPositions = new int[LastSymbolNumber - FirstSymbolNumber+1];
86 mySeparator = theSeparator;
87 for( int k = FirstSymbolNumber, aWidth = 0; k <= LastSymbolNumber; k++ )
89 myWidths[ k - FirstSymbolNumber ] = aFM.width( k );
90 myPositions[ k - FirstSymbolNumber ] = aWidth;
91 aWidth += myWidths[ k - FirstSymbolNumber ] + 2;//mySeparator;
99 //======================================================================
100 // Function: ~GLViewer_TexFont
102 //=======================================================================
103 GLViewer_TexFont::~GLViewer_TexFont()
106 delete[] myPositions;
109 //======================================================================
110 // Function: generateTexture
112 //=======================================================================
113 void GLViewer_TexFont::generateTexture()
115 QFontMetrics aFM( myQFont );
117 GLViewer_TexFindId aFindFont;
118 aFindFont.myFontString = myQFont.toString();
119 aFindFont.myViewPortId = (int)QGLContext::currentContext();
121 if( TexFontBase.contains( aFindFont ) )
123 GLViewer_TexIdStored aTexture = TexFontBase[ aFindFont ];
124 myTexFont = aTexture.myTexFontId;
125 myTexFontWidth = aTexture.myTexFontWidth;
126 myTexFontHeight = aTexture.myTexFontHeight;
132 int pixelsHight = aFM.height();
134 myTexFontHeight = 64;
136 pixelsWidth = myWidths[LastSymbolNumber - FirstSymbolNumber] +
137 myPositions[LastSymbolNumber - FirstSymbolNumber];
139 while( myTexFontWidth < pixelsWidth )
140 myTexFontWidth = myTexFontWidth * 2;
141 while( myTexFontHeight < pixelsHight )
142 myTexFontHeight = myTexFontHeight * 2;
144 QPixmap aPixmap( myTexFontWidth, myTexFontHeight );
145 aPixmap.fill( QColor( 0, 0, 0) );
146 QPainter aPainter( &aPixmap );
147 aPainter.setFont( myQFont );
148 for( int l = 0/*, gap = 0*/; l < LastSymbolNumber - FirstSymbolNumber; l++ )
151 aLetter += (char)(FirstSymbolNumber + l);
152 aPainter.setPen( QColor( 255,255,255) );
153 aPainter.drawText ( myPositions[l], pixelsHight, aLetter );
156 QImage aImage = aPixmap.convertToImage();
157 char* pixels = new char[myTexFontWidth * myTexFontHeight * 2];
159 for( int i = 0; i < myTexFontHeight; i++ )
161 for( int j = 0; j < myTexFontWidth; j++ )
163 int aRed = qRed( aImage.pixel( j, myTexFontHeight - i - 1 ) );
164 int aGreen = qGreen( aImage.pixel( j, myTexFontHeight - i - 1 ) );
165 int aBlue = qBlue( aImage.pixel( j, myTexFontHeight - i - 1 ) );
167 if( aRed != 0 || aGreen != 0 || aBlue != 0 )
169 pixels[i * myTexFontWidth * 2 + j * 2] = (GLubyte)( (aRed + aGreen + aBlue)/3 );
170 pixels[i * myTexFontWidth * 2 + j * 2 + 1]= (GLubyte) 255;
174 pixels[i * myTexFontWidth * 2 + j * 2] = (GLubyte) 0;
175 pixels[i * myTexFontWidth * 2 + j * 2 + 1]= (GLubyte) 0;
180 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
181 glGenTextures(1, &myTexFont);
182 glBindTexture(GL_TEXTURE_2D, myTexFont);
183 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
184 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
185 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
186 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
187 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
188 glTexImage2D(GL_TEXTURE_2D, 0, 2, myTexFontWidth,
189 myTexFontHeight, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, pixels);
193 GLViewer_TexIdStored aTexture;
194 aTexture.myTexFontId = myTexFont;
195 aTexture.myTexFontWidth = myTexFontWidth;
196 aTexture.myTexFontHeight = myTexFontHeight;
198 TexFontBase.insert( aFindFont, aTexture );
202 //======================================================================
203 // Function: drawString
205 //=======================================================================
206 void GLViewer_TexFont::drawString( QString theStr, GLdouble theX , GLdouble theY )
208 glEnable(GL_TEXTURE_2D);
209 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
210 glPixelTransferi(GL_MAP_COLOR, 0);
211 glAlphaFunc(GL_GEQUAL, 0.5F);
212 glEnable(GL_ALPHA_TEST);
213 glBindTexture(GL_TEXTURE_2D, myTexFont);
216 QFontMetrics aFM( myQFont );
217 int pixelsHeight = aFM.height();
219 theY = theY - myTexFontHeight + pixelsHeight;
221 for( int i = 0, aGap = 0; i < theStr.length(); i++ )
223 char aLetter = theStr.data()[i];
224 int aLettIndex = (int)aLetter - FirstSymbolNumber;
226 float aLettBegin = (float)myPositions[aLettIndex];
227 float aLettEnd = aLettBegin + myWidths[aLettIndex]-1;
229 aLettBegin = aLettBegin / myTexFontWidth;
230 aLettEnd = aLettEnd / myTexFontWidth;
232 glTexCoord2f( aLettBegin, 0.0 ); glVertex3f( theX + aGap, theY, 1.0 );
233 glTexCoord2f( aLettBegin, 1.0 ); glVertex3f( theX + aGap, theY + myTexFontHeight, 1.0 );
234 glTexCoord2f( aLettEnd, 1.0 ); glVertex3f( theX + aGap + myWidths[aLettIndex]-1, theY + myTexFontHeight, 1.0 );
235 glTexCoord2f( aLettEnd, 0.0 ); glVertex3f( theX + aGap + myWidths[aLettIndex]-1, theY, 1.0 );
237 aGap += myWidths[aLettIndex]-1 + mySeparator;
241 glDisable(GL_ALPHA_TEST);
242 glDisable(GL_TEXTURE_2D);
245 //======================================================================
246 // Function: getStringWidth
248 //=======================================================================
249 int GLViewer_TexFont::getStringWidth( QString theStr )
252 for( int i = 0; i < theStr.length(); i ++ )
254 char aLetter = theStr.data()[i];
255 int aLettIndex = (int)aLetter - FirstSymbolNumber;
256 aWidth += myWidths[aLettIndex] + mySeparator;
262 //======================================================================
263 // Function: getStringHeight
265 //=======================================================================
266 int GLViewer_TexFont::getStringHeight()
268 QFontMetrics aFM( myQFont );
272 //! function for generation list base for bitmap fonts
273 static GLuint displayListBase( QFont* theFont )
276 //static QMap<GLViewer_TexFindId, GLuint> fontCache;
277 GLViewer_TexFindId aFindFont;
278 aFindFont.myFontString = theFont->toString();
281 HGLRC ctx = ::wglGetCurrentContext();
285 aFindFont.myViewPortId = (int)ctx;
287 if ( GLViewer_TexFont::BitmapFontCache.contains( aFindFont ) )
288 aList = GLViewer_TexFont::BitmapFontCache[aFindFont];
292 QMap<GLViewer_TexFindId, GLuint>::iterator it = GLViewer_TexFont::BitmapFontCache.begin();
293 for ( ; it != GLViewer_TexFont::BitmapFontCache.end(); ++it )
295 if ( it.key().myViewPortId == (int)ctx && it.data() > listBase )
296 listBase = it.data();
300 HDC glHdc = ::wglGetCurrentDC();
301 ::SelectObject( glHdc, theFont->handle() );
302 if ( !::wglUseFontBitmaps( glHdc, 0, 256, listBase ) )
305 GLViewer_TexFont::BitmapFontCache[aFindFont] = aList;
308 Display* aDisp = glXGetCurrentDisplay();
312 printf( "Can't find current dislay\n" );
317 GLXContext aCont = glXGetCurrentContext();
321 printf( "Can't find current context\n" );
326 aFindFont.myViewPortId = (int)aCont;
328 if ( GLViewer_TexFont::BitmapFontCache.contains( aFindFont ) )
329 aList = GLViewer_TexFont::BitmapFontCache[aFindFont];
333 QMap<GLViewer_TexFindId, GLuint>::iterator it = GLViewer_TexFont::BitmapFontCache.begin();
334 for ( ; it != GLViewer_TexFont::BitmapFontCache.end(); ++it )
336 if ( it.key().myViewPortId == (int)aCont && it.data() > listBase )
337 listBase = it.data();
341 //glXUseXFont( (Font)(theFont->handle()), 0, 256, listBase );
343 char** xFontList = XListFonts( aDisp, aFindFont.myFontString.data(), 1, &aFontCont );
344 if( !theFont->handle() )
347 printf( "Can't load font %s. loading default font....\n", aFindFont.myFontString.data() );
349 QString aFontMask ("-*-*-*-r-*-*-");
350 aFontMask += aFindFont.myFontString.section( ',', 1, 1 );
352 printf( "Height of Default font: %s\n", aFindFont.myFontString.section( ',', 1, 1 ).data() );
354 aFontMask += "-*-*-*-m-*-*-*";
355 xFontList = XListFonts( aDisp, aFontMask.data()/*"-*-*-*-r-*-*-12-*-*-*-m-*-*-*"*/, 1, &aFontCont );
359 printf( "Can't load default font\n" );
363 glXUseXFont( (Font)(XLoadFont( aDisp,xFontList[0] )), 0, 256, listBase );
366 glXUseXFont( (Font)(theFont->handle()), 0, 256, listBase );
369 GLViewer_TexFont::BitmapFontCache[aFindFont] = aList;
377 /***************************************************************************
378 ** Class: GLViewer_Drawer
379 ** Descr: Drawer for GLViewer_Object
381 ** Created: UI team, 01.10.01
382 ****************************************************************************/
383 //======================================================================
384 // Function: GLViewer_Drawer
386 //=======================================================================
387 GLViewer_Drawer::GLViewer_Drawer()
389 myXScale = myYScale = 0.0;
391 myTextList = 0/*-1*/;
392 myObjectType = "GLViewer_Object";
396 //======================================================================
397 // Function: ~GLViewer_Drawer
399 //=======================================================================
400 GLViewer_Drawer::~GLViewer_Drawer()
403 glDeleteLists( myTextList, 1 );
406 //======================================================================
407 // Function: destroyAllTextures
409 //=======================================================================
410 void GLViewer_Drawer::destroyAllTextures()
412 QMap<GLViewer_TexFindId,GLViewer_TexIdStored>::Iterator anIt= GLViewer_TexFont::TexFontBase.begin();
413 QMap<GLViewer_TexFindId,GLViewer_TexIdStored>::Iterator anEndIt= GLViewer_TexFont::TexFontBase.end();
415 for( ; anIt != anEndIt; anIt++ )
416 glDeleteTextures( 1, &(anIt.data().myTexFontId) );
419 //=======================================================================
420 // Function: setAntialiasing
421 // Purpose : The function enables and disables antialiasing in Open GL (for points, lines and polygons).
422 //=======================================================================
423 void GLViewer_Drawer::setAntialiasing(const bool on)
427 glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
428 glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);
430 glEnable(GL_POINT_SMOOTH);
431 glEnable(GL_LINE_SMOOTH);
432 glEnable(GL_POLYGON_SMOOTH);
433 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
438 glDisable(GL_POINT_SMOOTH);
439 glDisable(GL_LINE_SMOOTH);
440 glDisable(GL_POLYGON_SMOOTH);
441 glBlendFunc (GL_ONE, GL_ZERO);
442 glDisable (GL_BLEND);
446 //======================================================================
447 // Function: loadTexture
449 //=======================================================================
450 GLuint GLViewer_Drawer::loadTexture( const QString& fileName )
453 if ( fileName.isEmpty() || !buf.load( fileName ) )
457 int h = buf.height();
460 while( size < w || size < h )
464 GLubyte* pixels = new GLubyte[ size * size * 4 ];
466 for( int i = 0; i < size; i++ )
468 for( int j = 0; j < size; j++ )
473 QRgb pixel = buf.pixel( j, h - i - 1 );
474 r = (GLubyte)qRed( pixel );
475 g = (GLubyte)qGreen( pixel );
476 b = (GLubyte)qBlue( pixel );
477 a = (GLubyte)qAlpha( pixel );
487 int index = 4 * ( i * size + j );
489 pixels[ index + 1 ] = g;
490 pixels[ index + 2 ] = b;
491 pixels[ index + 3 ] = a;
496 glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
497 glGenTextures( 1, &texture );
498 glBindTexture( GL_TEXTURE_2D, texture );
499 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
500 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
501 glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, size, size, 0,
502 GL_RGBA, GL_UNSIGNED_BYTE, pixels );
509 //======================================================================
510 // Function: drawTexture
512 //=======================================================================
513 void GLViewer_Drawer::drawTexture( GLuint texture, GLint size, GLfloat x, GLfloat y )
518 glColor4f( 1.0, 1.0, 1.0, 1.0 );
520 glEnable( GL_TEXTURE_2D );
521 glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
522 glAlphaFunc( GL_GREATER, 0.95F );
523 glEnable( GL_ALPHA_TEST );
525 glBindTexture( GL_TEXTURE_2D, texture );
528 glTexCoord2f( 0.0, 0.0 );
529 glVertex3f( x-size/2., y-size/2., 0.0 );
531 glTexCoord2f( 0.0, 1.0 );
532 glVertex3f( x-size/2., y+size/2., 0.0 );
534 glTexCoord2f( 1.0, 1.0 );
535 glVertex3f( x+size/2., y+size/2., 0.0 );
537 glTexCoord2f( 1.0, 0.0 );
538 glVertex3f( x+size/2., y-size/2., 0.0 );
543 glDisable( GL_ALPHA_TEST );
544 glDisable( GL_TEXTURE_2D );
547 //======================================================================
548 // Function: drawText
550 //=======================================================================
551 void GLViewer_Drawer::drawText( const QString& text, GLfloat xPos, GLfloat yPos,
552 const QColor& color, QFont* theFont, int theSeparator, DisplayTextFormat theFormat )
554 if( theFormat == DTF_TEXTURE )
556 GLViewer_TexFont aTexFont( theFont, theSeparator );
557 aTexFont.generateTexture();
559 glGetIntegerv (GL_VIEWPORT, viewport);
560 glGetDoublev (GL_MODELVIEW_MATRIX, modelMatrix);
561 glGetDoublev (GL_PROJECTION_MATRIX, projMatrix);
562 status = gluProject (xPos, yPos, 0, modelMatrix, projMatrix, viewport, &winx, &winy, &winz);
564 glPushAttrib( GL_TRANSFORM_BIT | GL_VIEWPORT_BIT | GL_LIST_BIT );
565 glMatrixMode(GL_PROJECTION);
568 glOrtho(0,viewport[2],0,viewport[3],-100,100);
569 glMatrixMode(GL_MODELVIEW);
573 glColor3f( ( GLfloat )color.red() / 255,
574 ( GLfloat )color.green() / 255,
575 ( GLfloat )color.blue() / 255 );
577 aTexFont.drawString( text, winx, winy );
580 glMatrixMode(GL_PROJECTION);
584 else if( theFormat == DTF_BITMAP )
586 glColor3f( ( GLfloat )color.red() / 255,
587 ( GLfloat )color.green() / 255,
588 ( GLfloat )color.blue() / 255 );
589 glRasterPos2f( xPos, yPos );
590 glListBase( displayListBase( theFont ) );
591 glCallLists( text.length(), GL_UNSIGNED_BYTE, text.local8Bit().data() );
595 //======================================================================
596 // Function: drawText
598 //=======================================================================
599 void GLViewer_Drawer::drawText( GLViewer_Object* theObject )
604 GLViewer_Text* aText = theObject->getGLText();
608 GLfloat aPosX, aPosY;
609 aText->getPosition( aPosX, aPosY );
610 // get temporary copy of font
611 QFont aTmpVarFont = aText->getFont();
612 drawText( aText->getText(), aPosX, aPosY, aText->getColor(), &aTmpVarFont, aText->getSeparator(), aText->getDisplayTextFormat() );
615 //======================================================================
616 // Function: drawGLText
618 //=======================================================================
619 void GLViewer_Drawer::drawGLText( QString text, float x, float y,
620 int hPosition, int vPosition, QColor color, bool smallFont )
622 QFont aFont( "Arial", 10, QFont::Bold );
624 aFont.setPointSize( 8 );
626 QFontMetrics aFontMetrics( aFont );
627 float width = aFontMetrics.width( text ) / myXScale;
628 float height = aFontMetrics.height() / myXScale;
629 float gap = 5 / myXScale;
633 case GLText_Left : x -= ( gap + width ); break;
634 case GLText_Center : x -= width / 2; break;
635 case GLText_Right : x += gap; break;
641 case GLText_Top : y += height * 0.5; break;
642 case GLText_Center : y -= height * 0.5; break;
643 case GLText_Bottom : y -= height * 1.5; break;
647 drawText( text, x, y, color, &aFont, 2, DTF_BITMAP ); // DTF_BITMAP or DTF_TEXTURE
650 //======================================================================
651 // Function: drawRectangle
653 //=======================================================================
654 void GLViewer_Drawer::drawRectangle( GLViewer_Rect* rect, QColor color )
659 float x1 = rect->left();
660 float x2 = rect->right();
661 float y1 = rect->bottom();
662 float y2 = rect->top();
664 glColor3f( ( GLfloat )color.red() / 255,
665 ( GLfloat )color.green() / 255,
666 ( GLfloat )color.blue() / 255 );
669 glBegin( GL_LINE_LOOP );
670 glVertex2f( x1, y1 );
671 glVertex2f( x1, y2 );
672 glVertex2f( x2, y2 );
673 glVertex2f( x2, y1 );
677 //======================================================================
678 // Function: translateToHPGL
680 //=======================================================================
681 bool GLViewer_Drawer::translateToHPGL( QFile& hFile, GLViewer_CoordSystem* aViewerCS, GLViewer_CoordSystem* aHPGLCS )
684 for( int i=0, n=myObjects.count(); i<n; i++ )
685 result &= myObjects[i]->translateToHPGL( hFile, aViewerCS, aHPGLCS );
689 //======================================================================
690 // Function: translateToPS
692 //=======================================================================
693 bool GLViewer_Drawer::translateToPS( QFile& hFile, GLViewer_CoordSystem* aViewerCS, GLViewer_CoordSystem* aPSCS )
696 for( int i=0, n=myObjects.count(); i<n; i++ )
697 result &= myObjects[i]->translateToPS( hFile, aViewerCS, aPSCS );
702 //======================================================================
703 // Function: translateToEMF
705 //=======================================================================
706 bool GLViewer_Drawer::translateToEMF( HDC hDC, GLViewer_CoordSystem* aViewerCS, GLViewer_CoordSystem* aEMFCS )
709 for( int i=0, n=myObjects.count(); i<n; i++ )
710 result &= myObjects[i]->translateToEMF( hDC, aViewerCS, aEMFCS );