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"
20 static int FirstSymbolNumber = 32;
21 static int LastSymbolNumber = 127;
23 QMap<GLViewer_TexFindId,GLViewer_TexIdStored> GLViewer_TexFont::TexFontBase;
27 GLboolean TFLoaded = GL_FALSE;
29 GLdouble modelMatrix[16], projMatrix[16];
31 GLdouble winx, winy, winz;
34 GLViewer_TexFont* staticGlFont;
37 /***************************************************************************
38 ** Class: GLViewer_TexFont
39 ** Descr: Texture Font for GLViewer_Object
41 ** Created: UI team, 01.10.01
42 ****************************************************************************/
43 GLViewer_TexFont::GLViewer_TexFont()
45 myQFont = QFont::defaultFont();
46 QFontMetrics aFM( myQFont );
47 myWidths = new int[LastSymbolNumber - FirstSymbolNumber+1];
48 myPositions = new int[LastSymbolNumber - FirstSymbolNumber+1];
50 for( int k = FirstSymbolNumber, aWidth = 0; k <= LastSymbolNumber; k++ )
52 myWidths[ k - FirstSymbolNumber ] = aFM.width( k );
53 myPositions[ k - FirstSymbolNumber ] = aWidth;
54 aWidth += myWidths[ k - FirstSymbolNumber ] + 2;//mySeparator;
61 GLViewer_TexFont::GLViewer_TexFont( QFont* theFont, int theSeparator )
64 QFontMetrics aFM( myQFont );
65 myWidths = new int[LastSymbolNumber - FirstSymbolNumber+1];
66 myPositions = new int[LastSymbolNumber - FirstSymbolNumber+1];
67 mySeparator = theSeparator;
68 for( int k = FirstSymbolNumber, aWidth = 0; k <= LastSymbolNumber; k++ )
70 myWidths[ k - FirstSymbolNumber ] = aFM.width( k );
71 myPositions[ k - FirstSymbolNumber ] = aWidth;
72 aWidth += myWidths[ k - FirstSymbolNumber ] + 2;//mySeparator;
80 GLViewer_TexFont::~GLViewer_TexFont()
86 void GLViewer_TexFont::generateTexture()
88 QFontMetrics aFM( myQFont );
90 GLViewer_TexFindId aFindFont;
91 aFindFont.myFontString = myQFont.toString();
92 aFindFont.myViewPortId = (int)QGLContext::currentContext();
94 if( TexFontBase.contains( aFindFont ) )
96 GLViewer_TexIdStored aTexture = TexFontBase[ aFindFont ];
97 myTexFont = aTexture.myTexFontId;
98 myTexFontWidth = aTexture.myTexFontWidth;
99 myTexFontHeight = aTexture.myTexFontHeight;
105 int pixelsHight = aFM.height();
107 myTexFontHeight = 64;
109 pixelsWidth = myWidths[LastSymbolNumber - FirstSymbolNumber] +
110 myPositions[LastSymbolNumber - FirstSymbolNumber];
112 while( myTexFontWidth < pixelsWidth )
113 myTexFontWidth = myTexFontWidth * 2;
114 while( myTexFontHeight < pixelsHight )
115 myTexFontHeight = myTexFontHeight * 2;
117 QPixmap aPixmap( myTexFontWidth, myTexFontHeight );
118 aPixmap.fill( QColor( 0, 0, 0) );
119 QPainter aPainter( &aPixmap );
120 aPainter.setFont( myQFont );
121 for( int l = 0/*, gap = 0*/; l < LastSymbolNumber - FirstSymbolNumber; l++ )
124 aLetter += (char)(FirstSymbolNumber + l);
125 aPainter.setPen( QColor( 255,255,255) );
126 aPainter.drawText ( myPositions[l], pixelsHight, aLetter );
129 QImage aImage = aPixmap.convertToImage();
130 char* pixels = new char[myTexFontWidth * myTexFontHeight * 2];
132 for( int i = 0; i < myTexFontHeight; i++ )
134 for( int j = 0; j < myTexFontWidth; j++ )
136 int aRed = qRed( aImage.pixel( j, myTexFontHeight - i - 1 ) );
137 int aGreen = qGreen( aImage.pixel( j, myTexFontHeight - i - 1 ) );
138 int aBlue = qBlue( aImage.pixel( j, myTexFontHeight - i - 1 ) );
140 if( aRed != 0 || aGreen != 0 || aBlue != 0 )
142 pixels[i * myTexFontWidth * 2 + j * 2] = (GLubyte)( (aRed + aGreen + aBlue)/3 );
143 pixels[i * myTexFontWidth * 2 + j * 2 + 1]= (GLubyte) 255;
147 pixels[i * myTexFontWidth * 2 + j * 2] = (GLubyte) 0;
148 pixels[i * myTexFontWidth * 2 + j * 2 + 1]= (GLubyte) 0;
153 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
154 glGenTextures(1, &myTexFont);
155 glBindTexture(GL_TEXTURE_2D, myTexFont);
156 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
157 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
158 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
159 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
160 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
161 glTexImage2D(GL_TEXTURE_2D, 0, 2, myTexFontWidth,
162 myTexFontHeight, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, pixels);
166 GLViewer_TexIdStored aTexture;
167 aTexture.myTexFontId = myTexFont;
168 aTexture.myTexFontWidth = myTexFontWidth;
169 aTexture.myTexFontHeight = myTexFontHeight;
171 TexFontBase.insert( aFindFont, aTexture );
175 void GLViewer_TexFont::drawString( QString theStr, GLdouble theX , GLdouble theY )
177 glEnable(GL_TEXTURE_2D);
178 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
179 glPixelTransferi(GL_MAP_COLOR, 0);
180 glAlphaFunc(GL_GEQUAL, 0.5F);
181 glEnable(GL_ALPHA_TEST);
182 glBindTexture(GL_TEXTURE_2D, myTexFont);
185 QFontMetrics aFM( myQFont );
186 int pixelsHeight = aFM.height();
188 theY = theY - myTexFontHeight + pixelsHeight;
190 for( int i = 0, aGap = 0; i < theStr.length(); i++ )
192 char aLetter = theStr.data()[i];
193 int aLettIndex = (int)aLetter - FirstSymbolNumber;
195 float aLettBegin = (float)myPositions[aLettIndex];
196 float aLettEnd = aLettBegin + myWidths[aLettIndex]-1;
198 aLettBegin = aLettBegin / myTexFontWidth;
199 aLettEnd = aLettEnd / myTexFontWidth;
201 glTexCoord2f( aLettBegin, 0.0 ); glVertex3f( theX + aGap, theY, 1.0 );
202 glTexCoord2f( aLettBegin, 1.0 ); glVertex3f( theX + aGap, theY + myTexFontHeight, 1.0 );
203 glTexCoord2f( aLettEnd, 1.0 ); glVertex3f( theX + aGap + myWidths[aLettIndex]-1, theY + myTexFontHeight, 1.0 );
204 glTexCoord2f( aLettEnd, 0.0 ); glVertex3f( theX + aGap + myWidths[aLettIndex]-1, theY, 1.0 );
206 aGap += myWidths[aLettIndex]-1 + mySeparator;
210 glDisable(GL_ALPHA_TEST);
211 glDisable(GL_TEXTURE_2D);
214 int GLViewer_TexFont::getStringWidth( QString theStr )
217 for( int i = 0; i < theStr.length(); i ++ )
219 char aLetter = theStr.data()[i];
220 int aLettIndex = (int)aLetter - FirstSymbolNumber;
221 aWidth += myWidths[aLettIndex] + mySeparator;
227 int GLViewer_TexFont::getStringHeight()
229 QFontMetrics aFM( myQFont );
233 void GLViewer_Drawer::destroyAllTextures()
235 QMap<GLViewer_TexFindId,GLViewer_TexIdStored>::Iterator anIt= GLViewer_TexFont::TexFontBase.begin();
236 QMap<GLViewer_TexFindId,GLViewer_TexIdStored>::Iterator anEndIt= GLViewer_TexFont::TexFontBase.end();
238 for( ; anIt != anEndIt; anIt++ )
239 glDeleteTextures( 1, &(anIt.data().myTexFontId) );
242 static GLuint displayListBase( QFont* theFont )
245 static QMap<GLViewer_TexFindId, GLuint> fontCache;
246 GLViewer_TexFindId aFindFont;
247 aFindFont.myFontString = theFont->toString();
250 HGLRC ctx = ::wglGetCurrentContext();
254 aFindFont.myViewPortId = (int)ctx;
256 if ( fontCache.contains( aFindFont ) )
257 aList = fontCache[aFindFont];
261 QMap<GLViewer_TexFindId, GLuint>::iterator it = fontCache.begin();
262 for ( ; it != fontCache.end(); ++it )
264 if ( it.key().myViewPortId == (int)ctx && it.data() > listBase )
265 listBase = it.data();
269 HDC glHdc = ::wglGetCurrentDC();
270 ::SelectObject( glHdc, theFont->handle() );
271 if ( !::wglUseFontBitmaps( glHdc, 0, 256, listBase ) )
274 fontCache[aFindFont] = aList;
277 Display* aDisp = glXGetCurrentDisplay();
280 printf( "Can't find current dislay\n" );
284 GLXContext aCont = glXGetCurrentContext();
287 printf( "Can't find current context\n" );
291 aFindFont.myViewPortId = (int)aCont;
293 if ( fontCache.contains( aFindFont ) )
294 aList = fontCache[aFindFont];
298 QMap<GLViewer_TexFindId, GLuint>::iterator it = fontCache.begin();
299 for ( ; it != fontCache.end(); ++it )
301 if ( it.key().myViewPortId == (int)aCont && it.data() > listBase )
302 listBase = it.data();
306 glXUseXFont( (Font)(theFont->handle()), 0, 256, listBase );
309 fontCache[aFindFont] = aList;
317 /***************************************************************************
318 ** Class: GLViewer_Drawer
319 ** Descr: Drawer for GLViewer_Object
321 ** Created: UI team, 01.10.01
322 ****************************************************************************/
323 GLViewer_Drawer::GLViewer_Drawer()
325 myXScale = myYScale = 0.0;
327 myTextList = 0/*-1*/;
328 myObjectType = "GLViewer_Object";
332 GLViewer_Drawer::~GLViewer_Drawer()
335 glDeleteLists( myTextList, 1 );
338 GLuint GLViewer_Drawer::loadTexture( const QString& fileName )
341 if ( fileName.isEmpty() || !buf.load( fileName ) )
345 int h = buf.height();
348 while( size < w || size < h )
352 GLubyte* pixels = new GLubyte[ size * size * 4 ];
354 for( int i = 0; i < size; i++ )
356 for( int j = 0; j < size; j++ )
361 QRgb pixel = buf.pixel( j, h - i - 1 );
362 r = (GLubyte)qRed( pixel );
363 g = (GLubyte)qGreen( pixel );
364 b = (GLubyte)qBlue( pixel );
373 int index = 4 * ( i * size + j );
375 pixels[ index + 1 ] = g;
376 pixels[ index + 2 ] = b;
378 if( r == (GLubyte)255 && g == (GLubyte)255 && b == (GLubyte)255 )
379 pixels[ index + 3 ] = (GLubyte)0;
381 pixels[ index + 3 ] = (GLubyte)255;
386 glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
387 glGenTextures( 1, &texture );
388 glBindTexture( GL_TEXTURE_2D, texture );
389 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
390 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
391 glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, size, size, 0,
392 GL_RGBA, GL_UNSIGNED_BYTE, pixels );
399 void GLViewer_Drawer::drawTexture( GLuint texture, GLint size, GLfloat x, GLfloat y )
401 float xScale = myXScale;
402 float yScale = myYScale;
404 glColor4f( 1.0, 1.0, 1.0, 1.0 );
406 glEnable( GL_TEXTURE_2D );
407 glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
408 glAlphaFunc( GL_GREATER, 0.95F );
409 glEnable( GL_ALPHA_TEST );
411 glBindTexture( GL_TEXTURE_2D, texture );
414 glTexCoord2f( 0.0, 0.0 );
415 glVertex3f( x-size/2./xScale, y-size/2./yScale, 0.0 );
417 glTexCoord2f( 0.0, 1.0 );
418 glVertex3f( x-size/2./xScale, y+size/2./yScale, 0.0 );
420 glTexCoord2f( 1.0, 1.0 );
421 glVertex3f( x+size/2./xScale, y+size/2./yScale, 0.0 );
423 glTexCoord2f( 1.0, 0.0 );
424 glVertex3f( x+size/2./xScale, y-size/2./yScale, 0.0 );
429 glDisable( GL_ALPHA_TEST );
430 glDisable( GL_TEXTURE_2D );
433 void GLViewer_Drawer::drawText( const QString& text, GLfloat xPos, GLfloat yPos,
434 const QColor& color, QFont* theFont, int theSeparator, DisplayTextFormat theFormat )
436 if( theFormat == DTF_TEXTURE )
438 GLViewer_TexFont aTexFont( theFont, theSeparator );
439 aTexFont.generateTexture();
441 glGetIntegerv (GL_VIEWPORT, viewport);
442 glGetDoublev (GL_MODELVIEW_MATRIX, modelMatrix);
443 glGetDoublev (GL_PROJECTION_MATRIX, projMatrix);
444 status = gluProject (xPos, yPos, 0, modelMatrix, projMatrix, viewport, &winx, &winy, &winz);
446 glPushAttrib( GL_TRANSFORM_BIT | GL_VIEWPORT_BIT | GL_LIST_BIT );
447 glMatrixMode(GL_PROJECTION);
450 glOrtho(0,viewport[2],0,viewport[3],-100,100);
451 glMatrixMode(GL_MODELVIEW);
455 glColor3f( ( GLfloat )color.red() / 255,
456 ( GLfloat )color.green() / 255,
457 ( GLfloat )color.blue() / 255 );
459 aTexFont.drawString( text, winx, winy );
462 glMatrixMode(GL_PROJECTION);
466 else if( theFormat == DTF_BITMAP )
468 glColor3f( ( GLfloat )color.red() / 255,
469 ( GLfloat )color.green() / 255,
470 ( GLfloat )color.blue() / 255 );
471 glRasterPos2f( xPos, yPos );
472 glListBase( displayListBase( theFont ) );
473 glCallLists( text.length(), GL_UNSIGNED_BYTE, text.local8Bit().data() );
477 void GLViewer_Drawer::drawText( GLViewer_Object* theObject )
482 GLViewer_Text* aText = theObject->getGLText();
486 GLfloat aPosX, aPosY;
487 aText->getPosition( aPosX, aPosY );
488 // get temporary copy of font
489 QFont aTmpVarFont = aText->getFont();
490 drawText( aText->getText(), aPosX, aPosY, aText->getColor(), &aTmpVarFont, aText->getSeparator(), aText->getDisplayTextFormat() );
493 void GLViewer_Drawer::drawGLText( QString text, float x, float y,
494 int hPosition, int vPosition, QColor color, bool smallFont )
496 QFont aFont( "Arial", 10, QFont::Bold );
498 aFont.setPointSize( 8 );
500 QFontMetrics aFontMetrics( aFont );
501 float width = aFontMetrics.width( text ) / myXScale;
502 float height = aFontMetrics.height() / myXScale;
503 float gap = 5 / myXScale;
507 case GLText_Left : x -= ( gap + width ); break;
508 case GLText_Center : x -= width / 2; break;
509 case GLText_Right : x += gap; break;
515 case GLText_Top : y += height * 0.5; break;
516 case GLText_Center : y -= height * 0.5; break;
517 case GLText_Bottom : y -= height * 1.5; break;
521 drawText( text, x, y, color, &aFont, 2 );
524 void GLViewer_Drawer::drawRectangle( GLViewer_Rect* rect, QColor color )
529 float x1 = rect->left();
530 float x2 = rect->right();
531 float y1 = rect->bottom();
532 float y2 = rect->top();
534 glColor3f( ( GLfloat )color.red() / 255,
535 ( GLfloat )color.green() / 255,
536 ( GLfloat )color.blue() / 255 );
539 glBegin( GL_LINE_LOOP );
540 glVertex2f( x1, y1 );
541 glVertex2f( x1, y2 );
542 glVertex2f( x2, y2 );
543 glVertex2f( x2, y1 );
547 bool GLViewer_Drawer::translateToHPGL( QFile& hFile, GLViewer_CoordSystem* aViewerCS, GLViewer_CoordSystem* aHPGLCS )
550 for( int i=0, n=myObjects.count(); i<n; i++ )
551 result &= myObjects[i]->translateToHPGL( hFile, aViewerCS, aHPGLCS );
555 bool GLViewer_Drawer::translateToPS( QFile& hFile, GLViewer_CoordSystem* aViewerCS, GLViewer_CoordSystem* aPSCS )
558 for( int i=0, n=myObjects.count(); i<n; i++ )
559 result &= myObjects[i]->translateToPS( hFile, aViewerCS, aPSCS );
564 bool GLViewer_Drawer::translateToEMF( HDC hDC, GLViewer_CoordSystem* aViewerCS, GLViewer_CoordSystem* aEMFCS )
567 for( int i=0, n=myObjects.count(); i<n; i++ )
568 result &= myObjects[i]->translateToEMF( hDC, aViewerCS, aEMFCS );