1 // Copyright (C) 2007-2023 CEA, EDF, 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>
39 #if defined(__APPLE__)
40 #include <OpenGL/CGLCurrent.h>
45 #include <gp_Pnt2d.hxx>
48 // Two texture components for texmapped fonts: luminance and alpha
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
55 GLfloat modelMatrix[16];
58 //! code of first font symbol
59 static int FirstSymbolNumber = 32;
60 //! code of last font symbol
61 static int LastSymbolNumber = 127;
63 QMap<GLViewer_TexFindId,GLViewer_TexIdStored> GLViewer_TexFont::TexFontBase;
64 QMap<GLViewer_TexFindId,GLuint> GLViewer_TexFont::BitmapFontCache;
67 Clears all generated fonts
69 void GLViewer_TexFont::clearTextBases()
71 //cout << "Clear font map" << endl;
73 BitmapFontCache.clear();
79 GLViewer_TexFont::GLViewer_TexFont()
80 : myFontHeight( 0 ), myMaxRowWidth( 0 )
82 myQFont = QApplication::font();//QFont::defaultFont();
84 myIsResizeable = false;
85 myMinMagFilter = GL_LINEAR;
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
97 GLViewer_TexFont::GLViewer_TexFont( QFont* theFont, int theSeparator, bool theIsResizeable, GLuint theMinMagFilter )
98 : myFontHeight( 0 ), myMaxRowWidth( 0 )
101 mySeparator = theSeparator;
102 myIsResizeable = theIsResizeable;
103 myMinMagFilter = theMinMagFilter;
111 GLViewer_TexFont::~GLViewer_TexFont()
114 delete[] myPositions;
118 Initializes font parameters
120 void GLViewer_TexFont::init()
122 myNbSymbols = LastSymbolNumber - FirstSymbolNumber + 1;
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();
132 myWidths = new int[myNbSymbols];
133 myPositions = new int[myNbSymbols];
135 for( int i = 0, k = FirstSymbolNumber, aWidth = 0; i < myNbSymbols; i++, k++ )
137 // is it time to start a new row?
138 if ( !( i % TEX_ROW_LEN ) )
140 if( aWidth > myMaxRowWidth )
141 myMaxRowWidth = aWidth;
144 myWidths[i] = aFM.width( k );
145 myPositions[i] = aWidth;
146 aWidth += myWidths[i] + 2;
154 Generating font texture
156 bool GLViewer_TexFont::generateTexture()
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 = (long)QGLContext::currentContext(); //!<TODO: conversion from "size_t" to "long"
166 if( TexFontBase.contains( aFindFont ) )
168 GLViewer_TexIdStored aTexture = TexFontBase[ aFindFont ];
169 myTexFont = aTexture.myTexFontId;
170 myTexFontWidth = aTexture.myTexFontWidth;
171 myTexFontHeight = aTexture.myTexFontHeight;
175 // Adding some pixels to have a gap between rows
176 int aRowPixelHeight = myFontHeight + TEX_ROW_GAP;
177 int aDescent = QFontMetrics( myQFont ).descent();
179 int aNumRows = myNbSymbols / TEX_ROW_LEN;
180 if ( myNbSymbols % TEX_ROW_LEN )
182 int pixelsHight = aNumRows * aRowPixelHeight;
185 myTexFontHeight = 64;
187 while( myTexFontWidth < myMaxRowWidth )
188 myTexFontWidth <<= 1;
189 while( myTexFontHeight < pixelsHight )
190 myTexFontHeight <<= 1;
192 // Checking whether the texture dimensions for the requested font
193 // do not exceed the maximum size supported by the OpenGL implementation
195 glGetIntegerv( GL_MAX_TEXTURE_SIZE, &maxSize );
196 if ( myTexFontWidth > maxSize || myTexFontHeight > maxSize )
199 QPixmap aPixmap( myTexFontWidth, myTexFontHeight );
200 aPixmap.fill( QColor( 0, 0, 0) );
201 QPainter aPainter( &aPixmap );
202 aPainter.setFont( myQFont );
204 for( int l = 0; l < myNbSymbols; l++ )
206 row = l / TEX_ROW_LEN;
208 aLetter += (char)(FirstSymbolNumber + l);
209 aPainter.setPen( QColor( 255,255,255) );
210 aPainter.drawText( myPositions[l], ( row + 1 ) * aRowPixelHeight - aDescent, aLetter );
213 QImage aImage = aPixmap.toImage();
217 // aImage.save("w:\\work\\CATHARE\\texture.png", "PNG");
219 char* pixels = new char[myTexFontWidth * myTexFontHeight * NB_TEX_COMP];
221 for( int i = 0; i < myTexFontHeight; i++ )
223 for( int j = 0; j < myTexFontWidth; j++ )
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 ) );
229 if( aRed != 0 || aGreen != 0 || aBlue != 0 )
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;
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;
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,
259 GLViewer_TexIdStored aTexture;
260 aTexture.myTexFontId = myTexFont;
261 aTexture.myTexFontWidth = myTexFontWidth;
262 aTexture.myTexFontHeight = myTexFontHeight;
264 TexFontBase.insert( aFindFont, aTexture );
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
276 void GLViewer_TexFont::drawString( QString theStr, GLdouble theX , GLdouble theY, GLfloat theScale )
278 // Adding some pixels to have a gap between rows
279 int aRowPixelHeight = myFontHeight + TEX_ROW_GAP;
281 float aXScale = 1.f, aYScale = 1.f;
282 if ( !myIsResizeable )
284 glGetFloatv (GL_MODELVIEW_MATRIX, modelMatrix);
285 aXScale = modelMatrix[0];
286 aYScale = modelMatrix[5];
288 else if ( theScale > 0.f )
290 aXScale = aXScale / theScale;
291 aYScale = aYScale / theScale;
295 glPushAttrib( GL_ENABLE_BIT | GL_TEXTURE_BIT );
297 glEnable(GL_TEXTURE_2D);
298 glPixelTransferi(GL_MAP_COLOR, 0);
300 glAlphaFunc(GL_GEQUAL, 0.05F);
301 glEnable(GL_ALPHA_TEST);
304 glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
306 glBindTexture(GL_TEXTURE_2D, myTexFont);
307 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
311 float aLettBeginS, aLettEndS, aLettBeginT, aLettEndT;
312 float aDY = ( aRowPixelHeight - 1 ) / aYScale, aDX;
315 for ( int i = 0; i < (int)theStr.length(); i++ )
317 aLetter = theStr.data()[i].toLatin1();
318 aLettIndex = (int)aLetter - FirstSymbolNumber;
319 row = aLettIndex / TEX_ROW_LEN;
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 );
326 aDX = ( (float)myWidths[aLettIndex] - 1.f ) / aXScale;
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 );
333 theX += aDX + mySeparator / aXScale;
337 // restore attributes
342 \return width of string in pixels
344 int GLViewer_TexFont::getStringWidth( QString theStr )
347 for ( int i = 0; i < (int)theStr.length(); i ++ )
349 char aLetter = theStr.data()[i].toLatin1();
350 int aLettIndex = (int)aLetter - FirstSymbolNumber;
351 aWidth += myWidths[aLettIndex] + mySeparator;
358 \return height of string in pixels
360 int GLViewer_TexFont::getStringHeight()
362 QFontMetrics aFM( myQFont );
367 Generates list base for bitmap fonts
369 static GLuint displayListBase( QFont* theFont )
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();
383 HGLRC ctx = ::wglGetCurrentContext();
387 aFindFont.myViewPortId = (LONG_PTR)ctx;
389 if ( GLViewer_TexFont::BitmapFontCache.contains( aFindFont ) )
390 aList = GLViewer_TexFont::BitmapFontCache[aFindFont];
394 QMap<GLViewer_TexFindId, GLuint>::iterator it = GLViewer_TexFont::BitmapFontCache.begin();
395 for ( ; it != GLViewer_TexFont::BitmapFontCache.end(); ++it )
397 if ( it.key().myViewPortId == (LONG_PTR)ctx && it.value() > listBase )
398 listBase = it.value();
402 HDC glHdc = ::wglGetCurrentDC();
403 if ( !::wglUseFontBitmaps( glHdc, 0, 256, listBase ) )
406 GLViewer_TexFont::BitmapFontCache[aFindFont] = aList;
408 #elif defined(__APPLE__)
409 CGLContextObj ctx = ::CGLGetCurrentContext();
413 aFindFont.myViewPortId = (long)ctx;
415 if ( GLViewer_TexFont::BitmapFontCache.contains( aFindFont ) )
416 aList = GLViewer_TexFont::BitmapFontCache[aFindFont];
420 QMap<GLViewer_TexFindId, GLuint>::iterator it = GLViewer_TexFont::BitmapFontCache.begin();
421 for ( ; it != GLViewer_TexFont::BitmapFontCache.end(); ++it )
423 if ( it.key().myViewPortId == (long)ctx && it.value() > listBase )
424 listBase = it.value();
428 //HDC glHdc = ::wglGetCurrentDC();
429 //::SelectObject( glHdc, theFont->handle() );
430 //if ( !::wglUseFontBitmaps( glHdc, 0, 256, listBase ) )
433 GLViewer_TexFont::BitmapFontCache[aFindFont] = aList;
436 Display* aDisp = glXGetCurrentDisplay();
440 printf( "Can't find current dislay\n" );
445 GLXContext aCont = glXGetCurrentContext();
449 printf( "Can't find current context\n" );
454 aFindFont.myViewPortId = (long)aCont;
456 if ( GLViewer_TexFont::BitmapFontCache.contains( aFindFont ) )
457 aList = GLViewer_TexFont::BitmapFontCache[aFindFont];
461 QMap<GLViewer_TexFindId, GLuint>::iterator it = GLViewer_TexFont::BitmapFontCache.begin();
462 for ( ; it != GLViewer_TexFont::BitmapFontCache.end(); ++it )
464 if ( it.key().myViewPortId == (long)aCont && it.value() > listBase )
465 listBase = it.value();
469 //glXUseXFont( (Font)(theFont->handle()), 0, 256, listBase );
471 QString aFontDef = theFont->toString();
472 char** xFontList = XListFonts( aDisp, aFontDef.toLatin1()/*aFindFont.myFontString.data()*/, 1, &aFontCont );
473 // TODO (QT5 PORTING) Below is a temporary solution, to allow compiling with Qt 5
475 printf( "Can't load font %s. loading default font....\n", aFontDef.toLatin1().data()/*aFindFont.myFontString.data()*/ );
477 QString aFontMask ("-*-*-*-r-*-*-");
478 aFontMask += aFontDef/*aFindFont.myFontString*/.section( ',', 1, 1 );
480 printf( "Height of Default font: %s\n", aFontDef/*aFindFont.myFontString*/.section( ',', 1, 1 ).data() );
482 aFontMask += "-*-*-*-m-*-*-*";
483 xFontList = XListFonts( aDisp, aFontMask.toLatin1().constData()/*"-*-*-*-r-*-*-12-*-*-*-m-*-*-*"*/, 1, &aFontCont );
487 printf( "Can't load default font\n" );
491 glXUseXFont( (Font)(XLoadFont( aDisp,xFontList[0] )), 0, 256, listBase );
493 GLViewer_TexFont::BitmapFontCache[aFindFont] = aList;
504 GLViewer_Drawer::GLViewer_Drawer()
505 : myFont( "Helvetica", 10, QFont::Bold )
507 myXScale = myYScale = 0.0;
509 myTextList = 0/*-1*/;
510 myObjectType = "GLViewer_Object";
512 myTextFormat = DTF_BITMAP;
519 GLViewer_Drawer::~GLViewer_Drawer()
522 glDeleteLists( myTextList, 1 );
526 Clears all generated textures
528 void GLViewer_Drawer::destroyAllTextures()
530 QMap<GLViewer_TexFindId,GLViewer_TexIdStored>::Iterator anIt= GLViewer_TexFont::TexFontBase.begin();
531 QMap<GLViewer_TexFindId,GLViewer_TexIdStored>::Iterator anEndIt= GLViewer_TexFont::TexFontBase.end();
533 for( ; anIt != anEndIt; anIt++ )
534 glDeleteTextures( 1, &(anIt.value().myTexFontId) );
538 Enables and disables antialiasing in Open GL (for points, lines and polygons).
539 \param on - if it is true, antialiasing is enabled
541 void GLViewer_Drawer::setAntialiasing(const bool on)
545 glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
546 glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);
548 glEnable(GL_POINT_SMOOTH);
549 glEnable(GL_LINE_SMOOTH);
550 glEnable(GL_POLYGON_SMOOTH);
551 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
556 glDisable(GL_POINT_SMOOTH);
557 glDisable(GL_LINE_SMOOTH);
558 glDisable(GL_POLYGON_SMOOTH);
559 glBlendFunc (GL_ONE, GL_ZERO);
560 glDisable (GL_BLEND);
564 /*! Loads texture from file
565 \param fileName - the name of texture file
566 \param x_size - the horizontal size of picture ( less or equal texture horizontal size )
567 \param y_size - the vertical size of picture ( less or equal texture vertical size )
568 \param t_size - the size of texture ( texture vertical size equals texture horizontal size )
570 GLuint GLViewer_Drawer::loadTexture( const QString& fileName,
576 if ( fileName.isEmpty() || !buf.load( fileName ) )
580 int h = buf.height();
583 while( size < w || size < h )
587 GLubyte* pixels = new GLubyte[ size * size * 4 ];
589 for( int i = 0; i < size; i++ )
591 for( int j = 0; j < size; j++ )
596 QRgb pixel = buf.pixel( j, h - i - 1 );
597 r = (GLubyte)qRed( pixel );
598 g = (GLubyte)qGreen( pixel );
599 b = (GLubyte)qBlue( pixel );
600 a = (GLubyte)qAlpha( pixel );
610 int index = 4 * ( i * size + j );
612 pixels[ index + 1 ] = g;
613 pixels[ index + 2 ] = b;
614 pixels[ index + 3 ] = a;
619 glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
620 glGenTextures( 1, &texture );
621 glBindTexture( GL_TEXTURE_2D, texture );
622 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
623 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
624 glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, size, size, 0,
625 GL_RGBA, GL_UNSIGNED_BYTE, pixels );
641 /*! Draw square texture
642 \param texture - the texture ID
643 \param size - the size of square texture
647 void GLViewer_Drawer::drawTexture( GLuint texture, GLint size, GLfloat x, GLfloat y )
649 /*float xScale = myXScale;
650 float yScale = myYScale;
652 glColor4f( 1.0, 1.0, 1.0, 1.0 );
654 glEnable( GL_TEXTURE_2D );
655 glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
656 glAlphaFunc( GL_GREATER, 0.95F );
657 glEnable( GL_ALPHA_TEST );
659 glBindTexture( GL_TEXTURE_2D, texture );
662 glTexCoord2f( 0.0, 0.0 );
663 glVertex3f( x-size/2./xScale, y-size/2./yScale, 0.0 );
665 glTexCoord2f( 0.0, 1.0 );
666 glVertex3f( x-size/2./xScale, y+size/2./yScale, 0.0 );
668 glTexCoord2f( 1.0, 1.0 );
669 glVertex3f( x+size/2./xScale, y+size/2./yScale, 0.0 );
671 glTexCoord2f( 1.0, 0.0 );
672 glVertex3f( x+size/2./xScale, y-size/2./yScale, 0.0 );
677 glDisable( GL_ALPHA_TEST );
678 glDisable( GL_TEXTURE_2D );*/
680 drawTexture( texture, size, size, x, y );
684 \param texture - the texture ID
685 \param x_size - the horizontal size of texture
686 \param y_size - the vertical size of texture
690 void GLViewer_Drawer::drawTexture( GLuint texture, GLint x_size, GLint y_size, GLfloat x, GLfloat y )
692 /*float xScale = myXScale;
693 float yScale = myYScale;
695 glColor4f( 1.0, 1.0, 1.0, 1.0 );
697 glEnable( GL_TEXTURE_2D );
698 glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
699 glAlphaFunc( GL_GREATER, 0.95F );
700 glEnable( GL_ALPHA_TEST );
702 glBindTexture( GL_TEXTURE_2D, texture );
705 glTexCoord2f( 0.0, 0.0 );
706 glVertex3f( x-x_size/2./xScale, y-y_size/2./yScale, 0.0 );
708 glTexCoord2f( 0.0, 1.0 );
709 glVertex3f( x-x_size/2./xScale, y+y_size/2./yScale, 0.0 );
711 glTexCoord2f( 1.0, 1.0 );
712 glVertex3f( x+x_size/2./xScale, y+y_size/2./yScale, 0.0 );
714 glTexCoord2f( 1.0, 0.0 );
715 glVertex3f( x+x_size/2./xScale, y-y_size/2./yScale, 0.0 );
720 glDisable( GL_ALPHA_TEST );
721 glDisable( GL_TEXTURE_2D );*/
722 drawTexturePart( texture, 1.0, 1.0, x_size, y_size, x, y );
725 /*! Draw texture part
726 \param texture - the texture ID
727 \param x_ratio - the horizontal ratio of texture part
728 \param y_ratio - the vertical ratio of texture part
729 \param x_size - the horizontal size of texture
730 \param y_size - the vertical size of texture
733 \param scale - common scale factor ( if = 0, use drawer scales )
735 void GLViewer_Drawer::drawTexturePart( GLuint texture,
747 float xScale = scale > 0. ? 1./scale : myXScale;
748 float yScale = scale > 0. ? 1./scale : myYScale;
750 glColor4f( 1.0, 1.0, 1.0, 1.0 );
753 glEnable( GL_TEXTURE_2D );
754 glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
755 bool hasAlpha = glIsEnabled( GL_ALPHA_TEST );
756 glDisable( GL_ALPHA_TEST );
758 glBindTexture( GL_TEXTURE_2D, texture );
761 glTexCoord2f( 0.0, 0.0 );
762 glVertex3f( x-x_size/2./xScale, y-y_size/2./yScale, 0.0 );
764 glTexCoord2f( 0.0, y_ratio );
765 glVertex3f( x-x_size/2./xScale, y+y_size/2./yScale, 0.0 );
767 glTexCoord2f( x_ratio, y_ratio );
768 glVertex3f( x+x_size/2./xScale, y+y_size/2./yScale, 0.0 );
770 glTexCoord2f( x_ratio, 0.0 );
771 glVertex3f( x+x_size/2./xScale, y-y_size/2./yScale, 0.0 );
777 glEnable( GL_ALPHA_TEST );
779 glDisable( GL_TEXTURE_2D );
784 \param text - text to be drawn
785 \param xPos - x position
786 \param yPos - y position
787 \param color - color of text
788 \param theFont - font of text
789 \param theSeparator - letter separator
790 \param theFormat - text format (by default DTF_BITMAP)
792 void GLViewer_Drawer::drawText( const QString& text, GLfloat xPos, GLfloat yPos,
793 const QColor& color, QFont* theFont, int theSeparator, DisplayTextFormat theFormat )
795 glColor3f( ( GLfloat )color.red() / 255,
796 ( GLfloat )color.green() / 255,
797 ( GLfloat )color.blue() / 255 );
799 if( theFormat != DTF_BITMAP )
801 GLViewer_TexFont aTexFont( theFont, theSeparator, theFormat == DTF_TEXTURE_SCALABLE, GL_LINEAR );
802 // Font texture was not found or generated --> cannot draw text
803 if ( !aTexFont.generateTexture() )
806 if ( theFormat == DTF_TEXTURE_SCALABLE )
807 aTexFont.drawString( text, xPos, yPos, textScale() );
809 aTexFont.drawString( text, xPos, yPos );
813 glRasterPos2f( xPos, yPos );
814 glListBase( displayListBase( theFont ) );
815 glCallLists( text.length(), GL_UNSIGNED_BYTE, text.toLocal8Bit().data() );
822 void GLViewer_Drawer::drawText( GLViewer_Object* theObject )
827 GLViewer_Text* aText = theObject->getGLText();
831 GLfloat aPosX, aPosY;
832 aText->getPosition( aPosX, aPosY );
833 // get temporary copy of font
834 QFont aTmpVarFont = aText->getFont();
835 drawText( aText->getText(), aPosX, aPosY, aText->getColor(), &aTmpVarFont, aText->getSeparator(), aText->getDisplayTextFormat() );
839 \param text - the text string
842 \param hPosition - horizontal alignment
843 \param vPosition - vertical alignment
844 \param color - text color
845 \param smallFont - font format
847 void GLViewer_Drawer::drawGLText( QString text, float x, float y,
848 int hPosition, int vPosition, QColor color, bool smallFont )
850 QFont aFont( myFont );
852 aFont.setPointSize( int(aFont.pointSize() * 0.8) );
854 GLfloat scale = textScale() > 0. ? textScale() : 1.;
856 QFontMetrics aFontMetrics( aFont );
857 float width = myTextFormat == DTF_TEXTURE_SCALABLE ? aFontMetrics.width( text ) * scale : aFontMetrics.width( text ) / myXScale;
858 float height = myTextFormat == DTF_TEXTURE_SCALABLE ? aFontMetrics.height() * scale : aFontMetrics.height() / myYScale;
859 float gap = 5 / myXScale;
863 case GLText_Left : x -= ( gap + width ); break;
864 case GLText_Center : x -= width / 2; break;
865 case GLText_Right : x += gap; break;
871 case GLText_Top : y += height * 0.5; break;
872 case GLText_Center : y -= height * 0.5; break;
873 case GLText_Bottom : y -= height * 1.5; break;
877 drawText( text, x, y, color, &aFont, 2, myTextFormat );
881 \return a rectangle of text (without viewer scale)
883 GLViewer_Rect GLViewer_Drawer::textRect( const QString& text ) const
885 GLfloat scale = textScale() > 0. ? textScale() : 1.;
887 QFontMetrics aFontMetrics( myFont );
888 float width = myTextFormat == DTF_TEXTURE_SCALABLE ? aFontMetrics.width( text ) * scale : aFontMetrics.width( text );
889 float height = myTextFormat == DTF_TEXTURE_SCALABLE ? aFontMetrics.height() * scale : aFontMetrics.height();
891 return GLViewer_Rect( 0, width, height, 0 );
896 \param rect - instance of primitive
897 \param color - color of primitive
899 void GLViewer_Drawer::drawRectangle( GLViewer_Rect* rect, QColor color )
904 float x1 = rect->left();
905 float x2 = rect->right();
906 float y1 = rect->bottom();
907 float y2 = rect->top();
909 glColor3f( ( GLfloat )color.red() / 255,
910 ( GLfloat )color.green() / 255,
911 ( GLfloat )color.blue() / 255 );
914 glBegin( GL_LINE_LOOP );
915 glVertex2f( x1, y1 );
916 glVertex2f( x1, y2 );
917 glVertex2f( x2, y2 );
918 glVertex2f( x2, y1 );
923 Saves object to file with format of HPGL
925 \param aViewerCS - viewer co-ordinate system
926 \param aHPGLCS - paper co-ordinate system
928 bool GLViewer_Drawer::translateToHPGL( QFile& hFile, GLViewer_CoordSystem* aViewerCS, GLViewer_CoordSystem* aHPGLCS )
931 for( int i=0, n=myObjects.count(); i<n; i++ )
932 result &= myObjects[i]->translateToHPGL( hFile, aViewerCS, aHPGLCS );
937 Saves object to file with format of PostScript
939 \param aViewerCS - viewer co-ordinate system
940 \param aPSCS - paper co-ordinate system
942 bool GLViewer_Drawer::translateToPS( QFile& hFile, GLViewer_CoordSystem* aViewerCS, GLViewer_CoordSystem* aPSCS )
945 for( int i=0, n=myObjects.count(); i<n; i++ )
946 result &= myObjects[i]->translateToPS( hFile, aViewerCS, aPSCS );
952 Saves object to file with format of EMF
954 \param aViewerCS - viewer co-ordinate system
955 \param aEMFCS - paper co-ordinate system
957 bool GLViewer_Drawer::translateToEMF( HDC hDC, GLViewer_CoordSystem* aViewerCS, GLViewer_CoordSystem* aEMFCS )
960 for( int i=0, n=myObjects.count(); i<n; i++ )
961 result &= myObjects[i]->translateToEMF( hDC, aViewerCS, aEMFCS );
968 \param rect - instance of primitive
969 \param lineWidth - width of line
970 \param gap - gap of rectangle
971 \param color - color of primitive
972 \param filled - if it is true, then rectangle will be drawn filled with color "fillingColor"
973 \param fillingColor - color of filling
975 void GLViewer_Drawer::drawRectangle( GLViewer_Rect* rect, GLfloat lineWidth, GLfloat gap,
976 QColor color, bool filled, QColor fillingColor )
981 float x1 = rect->left() - gap;
982 float x2 = rect->right() + gap;
983 float y1 = rect->bottom() - gap;
984 float y2 = rect->top() + gap;
988 glColor3f( ( GLfloat )fillingColor.red() / 255,
989 ( GLfloat )fillingColor.green() / 255,
990 ( GLfloat )fillingColor.blue() / 255 );
991 glBegin( GL_POLYGON );
992 glVertex2f( x1, y1 );
993 glVertex2f( x1, y2 );
994 glVertex2f( x2, y2 );
995 glVertex2f( x2, y1 );
999 glColor3f( ( GLfloat )color.red() / 255,
1000 ( GLfloat )color.green() / 255,
1001 ( GLfloat )color.blue() / 255 );
1002 glLineWidth( lineWidth );
1004 glBegin( GL_LINE_LOOP );
1005 glVertex2f( x1, y1 );
1006 glVertex2f( x1, y2 );
1007 glVertex2f( x2, y2 );
1008 glVertex2f( x2, y1 );
1014 \param pntList - list of points
1015 \param color - color of contour
1016 \param lineWidth - width of line
1018 void GLViewer_Drawer::drawContour( const GLViewer_PntList& pntList, QColor color, GLfloat lineWidth )
1020 glColor3f( ( GLfloat )color.red() / 255,
1021 ( GLfloat )color.green() / 255,
1022 ( GLfloat )color.blue() / 255 );
1023 glLineWidth( lineWidth );
1025 glBegin( GL_LINES );
1026 QList<GLViewer_Pnt>::const_iterator it = pntList.begin();
1027 for( ; it != pntList.end(); ++it )
1028 glVertex2f( (*it).x(), (*it).y() );
1033 Draws rectangular contour
1034 \param rect - instance of rectangle
1035 \param color - color of primitive
1036 \param lineWidth - width of line
1037 \param pattern - pattern of line
1038 \param isStripe - enables line stipple
1040 void GLViewer_Drawer::drawContour( GLViewer_Rect* rect, QColor color, GLfloat lineWidth,
1041 GLushort pattern, bool isStripe )
1043 float x1 = rect->left();
1044 float x2 = rect->right();
1045 float y1 = rect->bottom();
1046 float y2 = rect->top();
1048 glColor3f( ( GLfloat )color.red() / 255,
1049 ( GLfloat )color.green() / 255,
1050 ( GLfloat )color.blue() / 255 );
1051 glLineWidth( lineWidth );
1055 glEnable( GL_LINE_STIPPLE );
1056 glLineStipple( 1, pattern );
1059 glBegin( GL_LINE_LOOP );
1061 glVertex2f( x1, y1 );
1062 glVertex2f( x1, y2 );
1063 glVertex2f( x2, y2 );
1064 glVertex2f( x2, y1 );
1067 glDisable( GL_LINE_STIPPLE );
1072 \param pntList - list of points
1073 \param color - color of polygon
1075 void GLViewer_Drawer::drawPolygon( const GLViewer_PntList& pntList, QColor color )
1077 glColor3f( ( GLfloat )color.red() / 255,
1078 ( GLfloat )color.green() / 255,
1079 ( GLfloat )color.blue() / 255 );
1080 glBegin( GL_POLYGON );
1081 QList<GLViewer_Pnt>::const_iterator it = pntList.begin();
1082 for( ; it != pntList.end(); ++it )
1083 glVertex2f( (*it).x(), (*it).y() );
1089 \param rect - instance of rectangle
1090 \param color - color of polygon
1091 \param pattern - pattern of line
1092 \param isStripe - enables line stipple
1094 void GLViewer_Drawer::drawPolygon( GLViewer_Rect* rect, QColor color,
1095 GLushort pattern, bool isStripe )
1097 float x1 = rect->left();
1098 float x2 = rect->right();
1099 float y1 = rect->bottom();
1100 float y2 = rect->top();
1101 glColor3f( ( GLfloat )color.red() / 255,
1102 ( GLfloat )color.green() / 255,
1103 ( GLfloat )color.blue() / 255 );
1107 glEnable( GL_LINE_STIPPLE );
1108 glLineStipple( 1, pattern );
1110 glBegin( GL_POLYGON );
1112 glVertex2f( x1, y1 );
1113 glVertex2f( x1, y2 );
1114 glVertex2f( x2, y2 );
1115 glVertex2f( x2, y1 );
1118 glDisable( GL_LINE_STIPPLE );
1121 GLubyte rasterVertex[5] = { 0x70, 0xf8, 0xf8, 0xf8, 0x70 };
1125 \param x - x position
1126 \param y - y position
1127 \param color - color of vertex
1129 void GLViewer_Drawer::drawVertex( GLfloat x, GLfloat y, QColor color )
1131 glColor3f( ( GLfloat )color.red() / 255, ( GLfloat )color.green() / 255, ( GLfloat )color.blue() / 255 );
1132 glRasterPos2f( x, y );
1133 glBitmap( 5, 5, 2, 2, 0, 0, rasterVertex );
1136 GLubyte rasterCross[7] = { 0x82, 0x44, 0x28, 0x10, 0x28, 0x44, 0x82 };
1140 \param x - x position
1141 \param y - y position
1142 \param color - color of cross
1144 void GLViewer_Drawer::drawCross( GLfloat x, GLfloat y, QColor color )
1146 glColor3f( ( GLfloat )color.red() / 255, ( GLfloat )color.green() / 255, ( GLfloat )color.blue() / 255 );
1147 glRasterPos2f( x, y );
1148 glBitmap( 7, 7, 3, 3, 0, 0, rasterCross );
1153 \param red, green, blue - components of color
1154 \param lineWidth - width of line
1156 \param length - length of arrow
1157 \param width - width of arrow
1158 \param x - x position
1159 \param y - y position
1160 \param angle - angle of arrow
1161 \param filled - drawn as filled
1163 void GLViewer_Drawer::drawArrow( const GLfloat red, const GLfloat green, const GLfloat blue,
1165 GLfloat staff, GLfloat length, GLfloat width,
1166 GLfloat x, GLfloat y, GLfloat angle, GLboolean filled )
1169 GLfloat vy1 = y + staff + length;
1170 GLfloat vx2 = vx1 - width / 2;
1171 GLfloat vy2 = vy1 - length;
1172 GLfloat vx3 = vx1 + width / 2;
1173 GLfloat vy3 = vy1 - length;
1175 gp_Pnt2d p0( x, y );
1176 gp_Pnt2d p1( vx1, vy1 );
1177 gp_Pnt2d p2( vx2, vy2 );
1178 gp_Pnt2d p3( vx3, vy3 );
1180 p1.Rotate( p0, angle );
1181 p2.Rotate( p0, angle );
1182 p3.Rotate( p0, angle );
1184 vx1 = p1.X(); vy1 = p1.Y();
1185 vx2 = p2.X(); vy2 = p2.Y();
1186 vx3 = p3.X(); vy3 = p3.Y();
1188 glColor3f( red, green, blue );
1189 glLineWidth( lineWidth );
1191 glBegin( GL_LINES );
1193 glVertex2f( vx1, vy1 );
1199 glBegin( GL_LINES );
1200 glVertex2f( vx1, vy1 );
1201 glVertex2f( vx2, vy2 );
1202 glVertex2f( vx1, vy1 );
1203 glVertex2f( vx3, vy3 );
1208 glBegin( GL_POLYGON );
1209 glVertex2f( vx1, vy1 );
1210 glVertex2f( vx2, vy2 );
1211 glVertex2f( vx3, vy3 );