1 // Copyright (C) 2007-2016 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
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.
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.
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
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 // Author : OPEN CASCADE
24 // File: GLViewer_Drawer.cxx
25 // Created: November, 2004
26 //#include <GLViewerAfx.h>
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"
34 #include <QApplication>
43 #include <gp_Pnt2d.hxx>
46 // Two texture components for texmapped fonts: luminance and alpha
48 // A font is split into rows each containing 32 characters
49 #define TEX_ROW_LEN 32
50 // Gap in pixels between two character rows in a font texture
53 GLfloat modelMatrix[16];
56 //! code of first font symbol
57 static int FirstSymbolNumber = 32;
58 //! code of last font symbol
59 static int LastSymbolNumber = 127;
61 QMap<GLViewer_TexFindId,GLViewer_TexIdStored> GLViewer_TexFont::TexFontBase;
62 QMap<GLViewer_TexFindId,GLuint> GLViewer_TexFont::BitmapFontCache;
65 Clears all generated fonts
67 void GLViewer_TexFont::clearTextBases()
69 //cout << "Clear font map" << endl;
71 BitmapFontCache.clear();
77 GLViewer_TexFont::GLViewer_TexFont()
78 : myMaxRowWidth( 0 ), myFontHeight( 0 )
80 myQFont = QApplication::font();//QFont::defaultFont();
82 myIsResizeable = false;
83 myMinMagFilter = GL_LINEAR;
90 \param theFont - a base font
91 \param theSeparator - separator between letters
92 \param theIsResizeable - specifies whether text drawn by this object can be scaled along with the scene
93 \param theMinMagFilter - min/mag filter, affects text sharpness
95 GLViewer_TexFont::GLViewer_TexFont( QFont* theFont, int theSeparator, bool theIsResizeable, GLuint theMinMagFilter )
96 : myMaxRowWidth( 0 ), myFontHeight( 0 )
99 mySeparator = theSeparator;
100 myIsResizeable = theIsResizeable;
101 myMinMagFilter = theMinMagFilter;
109 GLViewer_TexFont::~GLViewer_TexFont()
112 delete[] myPositions;
116 Initializes font parameters
118 void GLViewer_TexFont::init()
120 myNbSymbols = LastSymbolNumber - FirstSymbolNumber + 1;
122 // It is unsafe to draw all characters in a single row -
123 // this leads to problems on some graphic cards with small GL_MAX_TEXTURE_SIZE.
124 // So splitting the characters into rows each containing 32 characters (or less).
125 // Assuming contant height of each row (64 pixels) to simplify texture mapping.
126 // However, this can be improved if necessary.
127 QFontMetrics aFM( myQFont );
128 myFontHeight = aFM.height();
130 myWidths = new int[myNbSymbols];
131 myPositions = new int[myNbSymbols];
133 for( int i = 0, k = FirstSymbolNumber, aWidth = 0; i < myNbSymbols; i++, k++ )
135 // is it time to start a new row?
136 if ( !( i % TEX_ROW_LEN ) )
138 if( aWidth > myMaxRowWidth )
139 myMaxRowWidth = aWidth;
142 myWidths[i] = aFM.width( k );
143 myPositions[i] = aWidth;
144 aWidth += myWidths[i] + 2;
152 Generating font texture
154 bool GLViewer_TexFont::generateTexture()
156 GLViewer_TexFindId aFindFont;
157 aFindFont.myFontFamily = myQFont.family();//myQFont.toString();
158 aFindFont.myIsBold = myQFont.bold();
159 aFindFont.myIsItal = myQFont.italic();
160 aFindFont.myIsUndl = myQFont.underline();
161 aFindFont.myPointSize = myQFont.pointSize();
162 aFindFont.myViewPortId = size_t(QGLContext::currentContext());
164 if( TexFontBase.contains( aFindFont ) )
166 GLViewer_TexIdStored aTexture = TexFontBase[ aFindFont ];
167 myTexFont = aTexture.myTexFontId;
168 myTexFontWidth = aTexture.myTexFontWidth;
169 myTexFontHeight = aTexture.myTexFontHeight;
173 // Adding some pixels to have a gap between rows
174 int aRowPixelHeight = myFontHeight + TEX_ROW_GAP;
175 int aDescent = QFontMetrics( myQFont ).descent();
177 int aNumRows = myNbSymbols / TEX_ROW_LEN;
178 if ( myNbSymbols % TEX_ROW_LEN )
180 int pixelsHight = aNumRows * aRowPixelHeight;
183 myTexFontHeight = 64;
185 while( myTexFontWidth < myMaxRowWidth )
186 myTexFontWidth <<= 1;
187 while( myTexFontHeight < pixelsHight )
188 myTexFontHeight <<= 1;
190 // Checking whether the texture dimensions for the requested font
191 // do not exceed the maximum size supported by the OpenGL implementation
193 glGetIntegerv( GL_MAX_TEXTURE_SIZE, &maxSize );
194 if ( myTexFontWidth > maxSize || myTexFontHeight > maxSize )
197 QPixmap aPixmap( myTexFontWidth, myTexFontHeight );
198 aPixmap.fill( QColor( 0, 0, 0) );
199 QPainter aPainter( &aPixmap );
200 aPainter.setFont( myQFont );
202 for( int l = 0; l < myNbSymbols; l++ )
204 row = l / TEX_ROW_LEN;
206 aLetter += (char)(FirstSymbolNumber + l);
207 aPainter.setPen( QColor( 255,255,255) );
208 aPainter.drawText( myPositions[l], ( row + 1 ) * aRowPixelHeight - aDescent, aLetter );
211 QImage aImage = aPixmap.toImage();
215 // aImage.save("w:\\work\\CATHARE\\texture.png", "PNG");
217 char* pixels = new char[myTexFontWidth * myTexFontHeight * NB_TEX_COMP];
219 for( int i = 0; i < myTexFontHeight; i++ )
221 for( int j = 0; j < myTexFontWidth; j++ )
223 int aRed = qRed( aImage.pixel( j, myTexFontHeight - i - 1 ) );
224 int aGreen = qGreen( aImage.pixel( j, myTexFontHeight - i - 1 ) );
225 int aBlue = qBlue( aImage.pixel( j, myTexFontHeight - i - 1 ) );
227 if( aRed != 0 || aGreen != 0 || aBlue != 0 )
229 pixels[i * myTexFontWidth * NB_TEX_COMP + j * NB_TEX_COMP] = (GLubyte)( (aRed + aGreen + aBlue)/3 );
230 pixels[i * myTexFontWidth * NB_TEX_COMP + j * NB_TEX_COMP + 1]= (GLubyte) 255;
234 pixels[i * myTexFontWidth * NB_TEX_COMP + j * NB_TEX_COMP] = (GLubyte) 0;
235 pixels[i * myTexFontWidth * NB_TEX_COMP + j * NB_TEX_COMP + 1]= (GLubyte) 0;
240 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
241 glGenTextures(1, &myTexFont);
242 glBindTexture(GL_TEXTURE_2D, myTexFont);
243 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, myMinMagFilter);
244 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, myMinMagFilter);
245 glTexImage2D(GL_TEXTURE_2D,
257 GLViewer_TexIdStored aTexture;
258 aTexture.myTexFontId = myTexFont;
259 aTexture.myTexFontWidth = myTexFontWidth;
260 aTexture.myTexFontHeight = myTexFontHeight;
262 TexFontBase.insert( aFindFont, aTexture );
268 Drawing string in viewer
269 \param theStr - string to be drawn
270 \param theX - X position
271 \param theY - Y position
272 \param theScale - scale coefficient
274 void GLViewer_TexFont::drawString( QString theStr, GLdouble theX , GLdouble theY, GLfloat theScale )
276 // Adding some pixels to have a gap between rows
277 int aRowPixelHeight = myFontHeight + TEX_ROW_GAP;
279 float aXScale = 1.f, aYScale = 1.f;
280 if ( !myIsResizeable )
282 glGetFloatv (GL_MODELVIEW_MATRIX, modelMatrix);
283 aXScale = modelMatrix[0];
284 aYScale = modelMatrix[5];
286 else if ( theScale > 0.f )
288 aXScale = aXScale / theScale;
289 aYScale = aYScale / theScale;
293 glPushAttrib( GL_ENABLE_BIT | GL_TEXTURE_BIT );
295 glEnable(GL_TEXTURE_2D);
296 glPixelTransferi(GL_MAP_COLOR, 0);
298 glAlphaFunc(GL_GEQUAL, 0.05F);
299 glEnable(GL_ALPHA_TEST);
302 glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
304 glBindTexture(GL_TEXTURE_2D, myTexFont);
305 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
309 float aLettBeginS, aLettEndS, aLettBeginT, aLettEndT;
310 float aDY = ( aRowPixelHeight - 1 ) / aYScale, aDX;
313 for ( int i = 0; i < (int)theStr.length(); i++ )
315 aLetter = theStr.data()[i].toLatin1();
316 aLettIndex = (int)aLetter - FirstSymbolNumber;
317 row = aLettIndex / TEX_ROW_LEN;
319 aLettBeginS = (float)myPositions[aLettIndex] / ( (float)myTexFontWidth - 1.f );
320 aLettEndS = aLettBeginS + ( (float)myWidths[aLettIndex] - 1.f ) / ( (float)myTexFontWidth - 1.f );
321 aLettBeginT = ( myTexFontHeight - ( row + 1 ) * aRowPixelHeight ) / ( (float)myTexFontHeight - 1.f );
322 aLettEndT = aLettBeginT + ( (float)aRowPixelHeight - 1.f ) / ( (float)myTexFontHeight - 1.f );
324 aDX = ( (float)myWidths[aLettIndex] - 1.f ) / aXScale;
326 glTexCoord2f( aLettBeginS, aLettBeginT ); glVertex3f( theX, theY, 1.f );
327 glTexCoord2f( aLettBeginS, aLettEndT ); glVertex3f( theX, theY + aDY, 1.f );
328 glTexCoord2f( aLettEndS, aLettEndT ); glVertex3f( theX + aDX, theY + aDY, 1.f );
329 glTexCoord2f( aLettEndS, aLettBeginT ); glVertex3f( theX + aDX, theY, 1.f );
331 theX += aDX + mySeparator / aXScale;
335 // restore attributes
340 \return width of string in pixels
342 int GLViewer_TexFont::getStringWidth( QString theStr )
345 for ( int i = 0; i < (int)theStr.length(); i ++ )
347 char aLetter = theStr.data()[i].toLatin1();
348 int aLettIndex = (int)aLetter - FirstSymbolNumber;
349 aWidth += myWidths[aLettIndex] + mySeparator;
356 \return height of string in pixels
358 int GLViewer_TexFont::getStringHeight()
360 QFontMetrics aFM( myQFont );
365 Generates list base for bitmap fonts
367 static GLuint displayListBase( QFont* theFont )
372 //static QMap<GLViewer_TexFindId, GLuint> fontCache;
373 GLViewer_TexFindId aFindFont;
374 aFindFont.myFontFamily = theFont->family();//theFont->toString();
375 aFindFont.myIsBold = theFont->bold();
376 aFindFont.myIsItal = theFont->italic();
377 aFindFont.myIsUndl = theFont->underline();
378 aFindFont.myPointSize = theFont->pointSize();
381 HGLRC ctx = ::wglGetCurrentContext();
385 aFindFont.myViewPortId = (int)ctx;
387 if ( GLViewer_TexFont::BitmapFontCache.contains( aFindFont ) )
388 aList = GLViewer_TexFont::BitmapFontCache[aFindFont];
392 QMap<GLViewer_TexFindId, GLuint>::iterator it = GLViewer_TexFont::BitmapFontCache.begin();
393 for ( ; it != GLViewer_TexFont::BitmapFontCache.end(); ++it )
395 if ( it.key().myViewPortId == (int)ctx && it.value() > listBase )
396 listBase = it.value();
400 HDC glHdc = ::wglGetCurrentDC();
401 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
402 ::SelectObject( glHdc, theFont->handle() );
404 if ( !::wglUseFontBitmaps( glHdc, 0, 256, listBase ) )
407 GLViewer_TexFont::BitmapFontCache[aFindFont] = aList;
410 Display* aDisp = glXGetCurrentDisplay();
414 printf( "Can't find current dislay\n" );
419 GLXContext aCont = glXGetCurrentContext();
423 printf( "Can't find current context\n" );
428 aFindFont.myViewPortId = size_t(aCont);
430 if ( GLViewer_TexFont::BitmapFontCache.contains( aFindFont ) )
431 aList = GLViewer_TexFont::BitmapFontCache[aFindFont];
435 QMap<GLViewer_TexFindId, GLuint>::iterator it = GLViewer_TexFont::BitmapFontCache.begin();
436 for ( ; it != GLViewer_TexFont::BitmapFontCache.end(); ++it )
438 if ( it.key().myViewPortId == size_t(aCont) && it.value() > listBase )
439 listBase = it.value();
443 //glXUseXFont( (Font)(theFont->handle()), 0, 256, listBase );
445 QString aFontDef = theFont->toString();
446 char** xFontList = XListFonts( aDisp, aFontDef.toLatin1()/*aFindFont.myFontString.data()*/, 1, &aFontCont );
447 // TODO (QT5 PORTING) Below is a temporary solution, to allow compiling with Qt 5
448 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
449 if( !theFont->handle() )
453 printf( "Can't load font %s. loading default font....\n", aFontDef.toLatin1().data()/*aFindFont.myFontString.data()*/ );
455 QString aFontMask ("-*-*-*-r-*-*-");
456 aFontMask += aFontDef/*aFindFont.myFontString*/.section( ',', 1, 1 );
458 printf( "Height of Default font: %s\n", aFontDef/*aFindFont.myFontString*/.section( ',', 1, 1 ).data() );
460 aFontMask += "-*-*-*-m-*-*-*";
461 xFontList = XListFonts( aDisp, aFontMask.toLatin1().constData()/*"-*-*-*-r-*-*-12-*-*-*-m-*-*-*"*/, 1, &aFontCont );
465 printf( "Can't load default font\n" );
469 glXUseXFont( (Font)(XLoadFont( aDisp,xFontList[0] )), 0, 256, listBase );
470 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
473 glXUseXFont( (Font)(theFont->handle()), 0, 256, listBase );
476 GLViewer_TexFont::BitmapFontCache[aFindFont] = aList;
487 GLViewer_Drawer::GLViewer_Drawer()
488 : myFont( "Helvetica", 10, QFont::Bold )
490 myXScale = myYScale = 0.0;
492 myTextList = 0/*-1*/;
493 myObjectType = "GLViewer_Object";
495 myTextFormat = DTF_BITMAP;
502 GLViewer_Drawer::~GLViewer_Drawer()
505 glDeleteLists( myTextList, 1 );
509 Clears all generated textures
511 void GLViewer_Drawer::destroyAllTextures()
513 QMap<GLViewer_TexFindId,GLViewer_TexIdStored>::Iterator anIt= GLViewer_TexFont::TexFontBase.begin();
514 QMap<GLViewer_TexFindId,GLViewer_TexIdStored>::Iterator anEndIt= GLViewer_TexFont::TexFontBase.end();
516 for( ; anIt != anEndIt; anIt++ )
517 glDeleteTextures( 1, &(anIt.value().myTexFontId) );
521 Enables and disables antialiasing in Open GL (for points, lines and polygons).
522 \param on - if it is true, antialiasing is enabled
524 void GLViewer_Drawer::setAntialiasing(const bool on)
528 glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
529 glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);
531 glEnable(GL_POINT_SMOOTH);
532 glEnable(GL_LINE_SMOOTH);
533 glEnable(GL_POLYGON_SMOOTH);
534 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
539 glDisable(GL_POINT_SMOOTH);
540 glDisable(GL_LINE_SMOOTH);
541 glDisable(GL_POLYGON_SMOOTH);
542 glBlendFunc (GL_ONE, GL_ZERO);
543 glDisable (GL_BLEND);
547 /*! Loads texture from file
548 \param fileName - the name of texture file
549 \param x_size - the horizontal size of picture ( less or equal texture horizontal size )
550 \param y_size - the vertical size of picture ( less or equal texture vertical size )
551 \param t_size - the size of texture ( texture vertical size equals texture horizontal size )
553 GLuint GLViewer_Drawer::loadTexture( const QString& fileName,
559 if ( fileName.isEmpty() || !buf.load( fileName ) )
563 int h = buf.height();
566 while( size < w || size < h )
570 GLubyte* pixels = new GLubyte[ size * size * 4 ];
572 for( int i = 0; i < size; i++ )
574 for( int j = 0; j < size; j++ )
579 QRgb pixel = buf.pixel( j, h - i - 1 );
580 r = (GLubyte)qRed( pixel );
581 g = (GLubyte)qGreen( pixel );
582 b = (GLubyte)qBlue( pixel );
583 a = (GLubyte)qAlpha( pixel );
593 int index = 4 * ( i * size + j );
595 pixels[ index + 1 ] = g;
596 pixels[ index + 2 ] = b;
597 pixels[ index + 3 ] = a;
602 glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
603 glGenTextures( 1, &texture );
604 glBindTexture( GL_TEXTURE_2D, texture );
605 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
606 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
607 glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, size, size, 0,
608 GL_RGBA, GL_UNSIGNED_BYTE, pixels );
624 /*! Draw square texture
625 \param texture - the texture ID
626 \param size - the size of square texture
630 void GLViewer_Drawer::drawTexture( GLuint texture, GLint size, GLfloat x, GLfloat y )
632 /*float xScale = myXScale;
633 float yScale = myYScale;
635 glColor4f( 1.0, 1.0, 1.0, 1.0 );
637 glEnable( GL_TEXTURE_2D );
638 glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
639 glAlphaFunc( GL_GREATER, 0.95F );
640 glEnable( GL_ALPHA_TEST );
642 glBindTexture( GL_TEXTURE_2D, texture );
645 glTexCoord2f( 0.0, 0.0 );
646 glVertex3f( x-size/2./xScale, y-size/2./yScale, 0.0 );
648 glTexCoord2f( 0.0, 1.0 );
649 glVertex3f( x-size/2./xScale, y+size/2./yScale, 0.0 );
651 glTexCoord2f( 1.0, 1.0 );
652 glVertex3f( x+size/2./xScale, y+size/2./yScale, 0.0 );
654 glTexCoord2f( 1.0, 0.0 );
655 glVertex3f( x+size/2./xScale, y-size/2./yScale, 0.0 );
660 glDisable( GL_ALPHA_TEST );
661 glDisable( GL_TEXTURE_2D );*/
663 drawTexture( texture, size, size, x, y );
667 \param texture - the texture ID
668 \param x_size - the horizontal size of texture
669 \param y_size - the vertical size of texture
673 void GLViewer_Drawer::drawTexture( GLuint texture, GLint x_size, GLint y_size, GLfloat x, GLfloat y )
675 /*float xScale = myXScale;
676 float yScale = myYScale;
678 glColor4f( 1.0, 1.0, 1.0, 1.0 );
680 glEnable( GL_TEXTURE_2D );
681 glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
682 glAlphaFunc( GL_GREATER, 0.95F );
683 glEnable( GL_ALPHA_TEST );
685 glBindTexture( GL_TEXTURE_2D, texture );
688 glTexCoord2f( 0.0, 0.0 );
689 glVertex3f( x-x_size/2./xScale, y-y_size/2./yScale, 0.0 );
691 glTexCoord2f( 0.0, 1.0 );
692 glVertex3f( x-x_size/2./xScale, y+y_size/2./yScale, 0.0 );
694 glTexCoord2f( 1.0, 1.0 );
695 glVertex3f( x+x_size/2./xScale, y+y_size/2./yScale, 0.0 );
697 glTexCoord2f( 1.0, 0.0 );
698 glVertex3f( x+x_size/2./xScale, y-y_size/2./yScale, 0.0 );
703 glDisable( GL_ALPHA_TEST );
704 glDisable( GL_TEXTURE_2D );*/
705 drawTexturePart( texture, 1.0, 1.0, x_size, y_size, x, y );
708 /*! Draw texture part
709 \param texture - the texture ID
710 \param x_ratio - the horizontal ratio of texture part
711 \param y_ratio - the vertical ratio of texture part
712 \param x_size - the horizontal size of texture
713 \param y_size - the vertical size of texture
716 \param scale - common scale factor ( if = 0, use drawer scales )
718 void GLViewer_Drawer::drawTexturePart( GLuint texture,
730 float xScale = scale > 0. ? 1./scale : myXScale;
731 float yScale = scale > 0. ? 1./scale : myYScale;
733 glColor4f( 1.0, 1.0, 1.0, 1.0 );
736 glEnable( GL_TEXTURE_2D );
737 glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
738 bool hasAlpha = glIsEnabled( GL_ALPHA_TEST );
739 glDisable( GL_ALPHA_TEST );
741 glBindTexture( GL_TEXTURE_2D, texture );
744 glTexCoord2f( 0.0, 0.0 );
745 glVertex3f( x-x_size/2./xScale, y-y_size/2./yScale, 0.0 );
747 glTexCoord2f( 0.0, y_ratio );
748 glVertex3f( x-x_size/2./xScale, y+y_size/2./yScale, 0.0 );
750 glTexCoord2f( x_ratio, y_ratio );
751 glVertex3f( x+x_size/2./xScale, y+y_size/2./yScale, 0.0 );
753 glTexCoord2f( x_ratio, 0.0 );
754 glVertex3f( x+x_size/2./xScale, y-y_size/2./yScale, 0.0 );
760 glEnable( GL_ALPHA_TEST );
762 glDisable( GL_TEXTURE_2D );
767 \param text - text to be drawn
768 \param xPos - x position
769 \param yPos - y position
770 \param color - color of text
771 \param theFont - font of text
772 \param theSeparator - letter separator
773 \param theFormat - text format (by default DTF_BITMAP)
775 void GLViewer_Drawer::drawText( const QString& text, GLfloat xPos, GLfloat yPos,
776 const QColor& color, QFont* theFont, int theSeparator, DisplayTextFormat theFormat )
778 glColor3f( ( GLfloat )color.red() / 255,
779 ( GLfloat )color.green() / 255,
780 ( GLfloat )color.blue() / 255 );
782 if( theFormat != DTF_BITMAP )
784 GLViewer_TexFont aTexFont( theFont, theSeparator, theFormat == DTF_TEXTURE_SCALABLE, GL_LINEAR );
785 // Font texture was not found or generated --> cannot draw text
786 if ( !aTexFont.generateTexture() )
789 if ( theFormat == DTF_TEXTURE_SCALABLE )
790 aTexFont.drawString( text, xPos, yPos, textScale() );
792 aTexFont.drawString( text, xPos, yPos );
796 glRasterPos2f( xPos, yPos );
797 glListBase( displayListBase( theFont ) );
798 glCallLists( text.length(), GL_UNSIGNED_BYTE, text.toLocal8Bit().data() );
805 void GLViewer_Drawer::drawText( GLViewer_Object* theObject )
810 GLViewer_Text* aText = theObject->getGLText();
814 GLfloat aPosX, aPosY;
815 aText->getPosition( aPosX, aPosY );
816 // get temporary copy of font
817 QFont aTmpVarFont = aText->getFont();
818 drawText( aText->getText(), aPosX, aPosY, aText->getColor(), &aTmpVarFont, aText->getSeparator(), aText->getDisplayTextFormat() );
822 \param text - the text string
825 \param hPosition - horizontal alignment
826 \param vPosition - vertical alignment
827 \param color - text color
828 \param smallFont - font format
830 void GLViewer_Drawer::drawGLText( QString text, float x, float y,
831 int hPosition, int vPosition, QColor color, bool smallFont )
833 QFont aFont( myFont );
835 aFont.setPointSize( int(aFont.pointSize() * 0.8) );
837 GLfloat scale = textScale() > 0. ? textScale() : 1.;
839 QFontMetrics aFontMetrics( aFont );
840 float width = myTextFormat == DTF_TEXTURE_SCALABLE ? aFontMetrics.width( text ) * scale : aFontMetrics.width( text ) / myXScale;
841 float height = myTextFormat == DTF_TEXTURE_SCALABLE ? aFontMetrics.height() * scale : aFontMetrics.height() / myYScale;
842 float gap = 5 / myXScale;
846 case GLText_Left : x -= ( gap + width ); break;
847 case GLText_Center : x -= width / 2; break;
848 case GLText_Right : x += gap; break;
854 case GLText_Top : y += height * 0.5; break;
855 case GLText_Center : y -= height * 0.5; break;
856 case GLText_Bottom : y -= height * 1.5; break;
860 drawText( text, x, y, color, &aFont, 2, myTextFormat );
864 \return a rectangle of text (without viewer scale)
866 GLViewer_Rect GLViewer_Drawer::textRect( const QString& text ) const
868 GLfloat scale = textScale() > 0. ? textScale() : 1.;
870 QFontMetrics aFontMetrics( myFont );
871 float width = myTextFormat == DTF_TEXTURE_SCALABLE ? aFontMetrics.width( text ) * scale : aFontMetrics.width( text );
872 float height = myTextFormat == DTF_TEXTURE_SCALABLE ? aFontMetrics.height() * scale : aFontMetrics.height();
874 return GLViewer_Rect( 0, width, height, 0 );
879 \param rect - instance of primitive
880 \param color - color of primitive
882 void GLViewer_Drawer::drawRectangle( GLViewer_Rect* rect, QColor color )
887 float x1 = rect->left();
888 float x2 = rect->right();
889 float y1 = rect->bottom();
890 float y2 = rect->top();
892 glColor3f( ( GLfloat )color.red() / 255,
893 ( GLfloat )color.green() / 255,
894 ( GLfloat )color.blue() / 255 );
897 glBegin( GL_LINE_LOOP );
898 glVertex2f( x1, y1 );
899 glVertex2f( x1, y2 );
900 glVertex2f( x2, y2 );
901 glVertex2f( x2, y1 );
906 Saves object to file with format of HPGL
908 \param aViewerCS - viewer co-ordinate system
909 \param aHPGLCS - paper co-ordinate system
911 bool GLViewer_Drawer::translateToHPGL( QFile& hFile, GLViewer_CoordSystem* aViewerCS, GLViewer_CoordSystem* aHPGLCS )
914 for( int i=0, n=myObjects.count(); i<n; i++ )
915 result &= myObjects[i]->translateToHPGL( hFile, aViewerCS, aHPGLCS );
920 Saves object to file with format of PostScript
922 \param aViewerCS - viewer co-ordinate system
923 \param aPSCS - paper co-ordinate system
925 bool GLViewer_Drawer::translateToPS( QFile& hFile, GLViewer_CoordSystem* aViewerCS, GLViewer_CoordSystem* aPSCS )
928 for( int i=0, n=myObjects.count(); i<n; i++ )
929 result &= myObjects[i]->translateToPS( hFile, aViewerCS, aPSCS );
935 Saves object to file with format of EMF
937 \param aViewerCS - viewer co-ordinate system
938 \param aEMFCS - paper co-ordinate system
940 bool GLViewer_Drawer::translateToEMF( HDC hDC, GLViewer_CoordSystem* aViewerCS, GLViewer_CoordSystem* aEMFCS )
943 for( int i=0, n=myObjects.count(); i<n; i++ )
944 result &= myObjects[i]->translateToEMF( hDC, aViewerCS, aEMFCS );
951 \param rect - instance of primitive
952 \param lineWidth - width of line
953 \param gap - gap of rectangle
954 \param color - color of primitive
955 \param filled - if it is true, then rectangle will be drawn filled with color "fillingColor"
956 \param fillingColor - color of filling
958 void GLViewer_Drawer::drawRectangle( GLViewer_Rect* rect, GLfloat lineWidth, GLfloat gap,
959 QColor color, bool filled, QColor fillingColor )
964 float x1 = rect->left() - gap;
965 float x2 = rect->right() + gap;
966 float y1 = rect->bottom() - gap;
967 float y2 = rect->top() + gap;
971 glColor3f( ( GLfloat )fillingColor.red() / 255,
972 ( GLfloat )fillingColor.green() / 255,
973 ( GLfloat )fillingColor.blue() / 255 );
974 glBegin( GL_POLYGON );
975 glVertex2f( x1, y1 );
976 glVertex2f( x1, y2 );
977 glVertex2f( x2, y2 );
978 glVertex2f( x2, y1 );
982 glColor3f( ( GLfloat )color.red() / 255,
983 ( GLfloat )color.green() / 255,
984 ( GLfloat )color.blue() / 255 );
985 glLineWidth( lineWidth );
987 glBegin( GL_LINE_LOOP );
988 glVertex2f( x1, y1 );
989 glVertex2f( x1, y2 );
990 glVertex2f( x2, y2 );
991 glVertex2f( x2, y1 );
997 \param pntList - list of points
998 \param color - color of contour
999 \param lineWidth - width of line
1001 void GLViewer_Drawer::drawContour( const GLViewer_PntList& pntList, QColor color, GLfloat lineWidth )
1003 glColor3f( ( GLfloat )color.red() / 255,
1004 ( GLfloat )color.green() / 255,
1005 ( GLfloat )color.blue() / 255 );
1006 glLineWidth( lineWidth );
1008 glBegin( GL_LINES );
1009 QList<GLViewer_Pnt>::const_iterator it = pntList.begin();
1010 for( ; it != pntList.end(); ++it )
1011 glVertex2f( (*it).x(), (*it).y() );
1016 Draws rectangular contour
1017 \param rect - instance of rectangle
1018 \param color - color of primitive
1019 \param lineWidth - width of line
1020 \param pattern - pattern of line
1021 \param isStripe - enables line stipple
1023 void GLViewer_Drawer::drawContour( GLViewer_Rect* rect, QColor color, GLfloat lineWidth,
1024 GLushort pattern, bool isStripe )
1026 float x1 = rect->left();
1027 float x2 = rect->right();
1028 float y1 = rect->bottom();
1029 float y2 = rect->top();
1031 glColor3f( ( GLfloat )color.red() / 255,
1032 ( GLfloat )color.green() / 255,
1033 ( GLfloat )color.blue() / 255 );
1034 glLineWidth( lineWidth );
1038 glEnable( GL_LINE_STIPPLE );
1039 glLineStipple( 1, pattern );
1042 glBegin( GL_LINE_LOOP );
1044 glVertex2f( x1, y1 );
1045 glVertex2f( x1, y2 );
1046 glVertex2f( x2, y2 );
1047 glVertex2f( x2, y1 );
1050 glDisable( GL_LINE_STIPPLE );
1055 \param pntList - list of points
1056 \param color - color of polygon
1058 void GLViewer_Drawer::drawPolygon( const GLViewer_PntList& pntList, QColor color )
1060 glColor3f( ( GLfloat )color.red() / 255,
1061 ( GLfloat )color.green() / 255,
1062 ( GLfloat )color.blue() / 255 );
1063 glBegin( GL_POLYGON );
1064 QList<GLViewer_Pnt>::const_iterator it = pntList.begin();
1065 for( ; it != pntList.end(); ++it )
1066 glVertex2f( (*it).x(), (*it).y() );
1072 \param rect - instance of rectangle
1073 \param color - color of polygon
1074 \param pattern - pattern of line
1075 \param isStripe - enables line stipple
1077 void GLViewer_Drawer::drawPolygon( GLViewer_Rect* rect, QColor color,
1078 GLushort pattern, bool isStripe )
1080 float x1 = rect->left();
1081 float x2 = rect->right();
1082 float y1 = rect->bottom();
1083 float y2 = rect->top();
1084 glColor3f( ( GLfloat )color.red() / 255,
1085 ( GLfloat )color.green() / 255,
1086 ( GLfloat )color.blue() / 255 );
1090 glEnable( GL_LINE_STIPPLE );
1091 glLineStipple( 1, pattern );
1093 glBegin( GL_POLYGON );
1095 glVertex2f( x1, y1 );
1096 glVertex2f( x1, y2 );
1097 glVertex2f( x2, y2 );
1098 glVertex2f( x2, y1 );
1101 glDisable( GL_LINE_STIPPLE );
1104 GLubyte rasterVertex[5] = { 0x70, 0xf8, 0xf8, 0xf8, 0x70 };
1108 \param x - x position
1109 \param y - y position
1110 \param color - color of vertex
1112 void GLViewer_Drawer::drawVertex( GLfloat x, GLfloat y, QColor color )
1114 glColor3f( ( GLfloat )color.red() / 255, ( GLfloat )color.green() / 255, ( GLfloat )color.blue() / 255 );
1115 glRasterPos2f( x, y );
1116 glBitmap( 5, 5, 2, 2, 0, 0, rasterVertex );
1119 GLubyte rasterCross[7] = { 0x82, 0x44, 0x28, 0x10, 0x28, 0x44, 0x82 };
1123 \param x - x position
1124 \param y - y position
1125 \param color - color of cross
1127 void GLViewer_Drawer::drawCross( GLfloat x, GLfloat y, QColor color )
1129 glColor3f( ( GLfloat )color.red() / 255, ( GLfloat )color.green() / 255, ( GLfloat )color.blue() / 255 );
1130 glRasterPos2f( x, y );
1131 glBitmap( 7, 7, 3, 3, 0, 0, rasterCross );
1136 \param red, green, blue - components of color
1137 \param lineWidth - width of line
1139 \param length - length of arrow
1140 \param width - width of arrow
1141 \param x - x position
1142 \param y - y position
1143 \param angle - angle of arrow
1144 \param filled - drawn as filled
1146 void GLViewer_Drawer::drawArrow( const GLfloat red, const GLfloat green, const GLfloat blue,
1148 GLfloat staff, GLfloat length, GLfloat width,
1149 GLfloat x, GLfloat y, GLfloat angle, GLboolean filled )
1152 GLfloat vy1 = y + staff + length;
1153 GLfloat vx2 = vx1 - width / 2;
1154 GLfloat vy2 = vy1 - length;
1155 GLfloat vx3 = vx1 + width / 2;
1156 GLfloat vy3 = vy1 - length;
1158 gp_Pnt2d p0( x, y );
1159 gp_Pnt2d p1( vx1, vy1 );
1160 gp_Pnt2d p2( vx2, vy2 );
1161 gp_Pnt2d p3( vx3, vy3 );
1163 p1.Rotate( p0, angle );
1164 p2.Rotate( p0, angle );
1165 p3.Rotate( p0, angle );
1167 vx1 = p1.X(); vy1 = p1.Y();
1168 vx2 = p2.X(); vy2 = p2.Y();
1169 vx3 = p3.X(); vy3 = p3.Y();
1171 glColor3f( red, green, blue );
1172 glLineWidth( lineWidth );
1174 glBegin( GL_LINES );
1176 glVertex2f( vx1, vy1 );
1182 glBegin( GL_LINES );
1183 glVertex2f( vx1, vy1 );
1184 glVertex2f( vx2, vy2 );
1185 glVertex2f( vx1, vy1 );
1186 glVertex2f( vx3, vy3 );
1191 glBegin( GL_POLYGON );
1192 glVertex2f( vx1, vy1 );
1193 glVertex2f( vx2, vy2 );
1194 glVertex2f( vx3, vy3 );