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) );
418 //======================================================================
419 // Function: loadTexture
421 //=======================================================================
422 GLuint GLViewer_Drawer::loadTexture( const QString& fileName )
425 if ( fileName.isEmpty() || !buf.load( fileName ) )
429 int h = buf.height();
432 while( size < w || size < h )
436 GLubyte* pixels = new GLubyte[ size * size * 4 ];
438 for( int i = 0; i < size; i++ )
440 for( int j = 0; j < size; j++ )
445 QRgb pixel = buf.pixel( j, h - i - 1 );
446 r = (GLubyte)qRed( pixel );
447 g = (GLubyte)qGreen( pixel );
448 b = (GLubyte)qBlue( pixel );
449 a = (GLubyte)qAlpha( pixel );
459 int index = 4 * ( i * size + j );
461 pixels[ index + 1 ] = g;
462 pixels[ index + 2 ] = b;
463 pixels[ index + 3 ] = a;
468 glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
469 glGenTextures( 1, &texture );
470 glBindTexture( GL_TEXTURE_2D, texture );
471 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
472 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
473 glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, size, size, 0,
474 GL_RGBA, GL_UNSIGNED_BYTE, pixels );
481 //======================================================================
482 // Function: drawTexture
484 //=======================================================================
485 void GLViewer_Drawer::drawTexture( GLuint texture, GLint size, GLfloat x, GLfloat y )
490 glColor4f( 1.0, 1.0, 1.0, 1.0 );
492 glEnable( GL_TEXTURE_2D );
493 glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
494 glAlphaFunc( GL_GREATER, 0.95F );
495 glEnable( GL_ALPHA_TEST );
497 glBindTexture( GL_TEXTURE_2D, texture );
500 glTexCoord2f( 0.0, 0.0 );
501 glVertex3f( x-size/2., y-size/2., 0.0 );
503 glTexCoord2f( 0.0, 1.0 );
504 glVertex3f( x-size/2., y+size/2., 0.0 );
506 glTexCoord2f( 1.0, 1.0 );
507 glVertex3f( x+size/2., y+size/2., 0.0 );
509 glTexCoord2f( 1.0, 0.0 );
510 glVertex3f( x+size/2., y-size/2., 0.0 );
515 glDisable( GL_ALPHA_TEST );
516 glDisable( GL_TEXTURE_2D );
519 //======================================================================
520 // Function: drawText
522 //=======================================================================
523 void GLViewer_Drawer::drawText( const QString& text, GLfloat xPos, GLfloat yPos,
524 const QColor& color, QFont* theFont, int theSeparator, DisplayTextFormat theFormat )
526 if( theFormat == DTF_TEXTURE )
528 GLViewer_TexFont aTexFont( theFont, theSeparator );
529 aTexFont.generateTexture();
531 glGetIntegerv (GL_VIEWPORT, viewport);
532 glGetDoublev (GL_MODELVIEW_MATRIX, modelMatrix);
533 glGetDoublev (GL_PROJECTION_MATRIX, projMatrix);
534 status = gluProject (xPos, yPos, 0, modelMatrix, projMatrix, viewport, &winx, &winy, &winz);
536 glPushAttrib( GL_TRANSFORM_BIT | GL_VIEWPORT_BIT | GL_LIST_BIT );
537 glMatrixMode(GL_PROJECTION);
540 glOrtho(0,viewport[2],0,viewport[3],-100,100);
541 glMatrixMode(GL_MODELVIEW);
545 glColor3f( ( GLfloat )color.red() / 255,
546 ( GLfloat )color.green() / 255,
547 ( GLfloat )color.blue() / 255 );
549 aTexFont.drawString( text, winx, winy );
552 glMatrixMode(GL_PROJECTION);
556 else if( theFormat == DTF_BITMAP )
558 glColor3f( ( GLfloat )color.red() / 255,
559 ( GLfloat )color.green() / 255,
560 ( GLfloat )color.blue() / 255 );
561 glRasterPos2f( xPos, yPos );
562 glListBase( displayListBase( theFont ) );
563 glCallLists( text.length(), GL_UNSIGNED_BYTE, text.local8Bit().data() );
567 //======================================================================
568 // Function: drawText
570 //=======================================================================
571 void GLViewer_Drawer::drawText( GLViewer_Object* theObject )
576 GLViewer_Text* aText = theObject->getGLText();
580 GLfloat aPosX, aPosY;
581 aText->getPosition( aPosX, aPosY );
582 // get temporary copy of font
583 QFont aTmpVarFont = aText->getFont();
584 drawText( aText->getText(), aPosX, aPosY, aText->getColor(), &aTmpVarFont, aText->getSeparator(), aText->getDisplayTextFormat() );
587 //======================================================================
588 // Function: drawGLText
590 //=======================================================================
591 void GLViewer_Drawer::drawGLText( QString text, float x, float y,
592 int hPosition, int vPosition, QColor color, bool smallFont )
594 QFont aFont( "Arial", 10, QFont::Bold );
596 aFont.setPointSize( 8 );
598 QFontMetrics aFontMetrics( aFont );
599 float width = aFontMetrics.width( text ) / myXScale;
600 float height = aFontMetrics.height() / myXScale;
601 float gap = 5 / myXScale;
605 case GLText_Left : x -= ( gap + width ); break;
606 case GLText_Center : x -= width / 2; break;
607 case GLText_Right : x += gap; break;
613 case GLText_Top : y += height * 0.5; break;
614 case GLText_Center : y -= height * 0.5; break;
615 case GLText_Bottom : y -= height * 1.5; break;
619 drawText( text, x, y, color, &aFont, 2, DTF_BITMAP ); // DTF_BITMAP or DTF_TEXTURE
622 //======================================================================
623 // Function: drawRectangle
625 //=======================================================================
626 void GLViewer_Drawer::drawRectangle( GLViewer_Rect* rect, QColor color )
631 float x1 = rect->left();
632 float x2 = rect->right();
633 float y1 = rect->bottom();
634 float y2 = rect->top();
636 glColor3f( ( GLfloat )color.red() / 255,
637 ( GLfloat )color.green() / 255,
638 ( GLfloat )color.blue() / 255 );
641 glBegin( GL_LINE_LOOP );
642 glVertex2f( x1, y1 );
643 glVertex2f( x1, y2 );
644 glVertex2f( x2, y2 );
645 glVertex2f( x2, y1 );
649 //======================================================================
650 // Function: translateToHPGL
652 //=======================================================================
653 bool GLViewer_Drawer::translateToHPGL( QFile& hFile, GLViewer_CoordSystem* aViewerCS, GLViewer_CoordSystem* aHPGLCS )
656 for( int i=0, n=myObjects.count(); i<n; i++ )
657 result &= myObjects[i]->translateToHPGL( hFile, aViewerCS, aHPGLCS );
661 //======================================================================
662 // Function: translateToPS
664 //=======================================================================
665 bool GLViewer_Drawer::translateToPS( QFile& hFile, GLViewer_CoordSystem* aViewerCS, GLViewer_CoordSystem* aPSCS )
668 for( int i=0, n=myObjects.count(); i<n; i++ )
669 result &= myObjects[i]->translateToPS( hFile, aViewerCS, aPSCS );
674 //======================================================================
675 // Function: translateToEMF
677 //=======================================================================
678 bool GLViewer_Drawer::translateToEMF( HDC hDC, GLViewer_CoordSystem* aViewerCS, GLViewer_CoordSystem* aEMFCS )
681 for( int i=0, n=myObjects.count(); i<n; i++ )
682 result &= myObjects[i]->translateToEMF( hDC, aViewerCS, aEMFCS );