1 // Copyright (C) 2005 OPEN CASCADE
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org
19 // Author : OPEN CASCADE
22 // File: GLViewer_Drawer.cxx
23 // Created: November, 2004
25 //#include <GLViewerAfx.h>
26 #include "GLViewer_Drawer.h"
27 #include "GLViewer_Object.h"
28 #include "GLViewer_Text.h"
29 #include "GLViewer_ViewFrame.h"
30 #include "GLViewer_ViewPort2d.h"
36 #include <gp_Pnt2d.hxx>
42 // Two texture components for texmapped fonts: luminance and alpha
44 // A font is split into rows each containing 32 characters
45 #define TEX_ROW_LEN 32
46 // Gap in pixels between two character rows in a font texture
49 GLfloat modelMatrix[16];
52 //! code of first font symbol
53 static int FirstSymbolNumber = 32;
54 //! code of last font symbol
55 static int LastSymbolNumber = 127;
57 QMap<GLViewer_TexFindId,GLViewer_TexIdStored> GLViewer_TexFont::TexFontBase;
58 QMap<GLViewer_TexFindId,GLuint> GLViewer_TexFont::BitmapFontCache;
61 Clears all generated fonts
63 void GLViewer_TexFont::clearTextBases()
65 //cout << "Clear font map" << endl;
67 BitmapFontCache.clear();
73 GLViewer_TexFont::GLViewer_TexFont()
74 : myMaxRowWidth( 0 ), myFontHeight( 0 )
76 myQFont = QFont::defaultFont();
78 myIsResizeable = false;
79 myMinMagFilter = GL_LINEAR;
86 \param theFont - a base font
87 \param theSeparator - separator between letters
88 \param theIsResizeable - specifies whether text drawn by this object can be scaled along with the scene
89 \param theMinMagFilter - min/mag filter, affects text sharpness
91 GLViewer_TexFont::GLViewer_TexFont( QFont* theFont, int theSeparator, bool theIsResizeable, GLuint theMinMagFilter )
92 : myMaxRowWidth( 0 ), myFontHeight( 0 )
95 mySeparator = theSeparator;
96 myIsResizeable = theIsResizeable;
97 myMinMagFilter = theMinMagFilter;
105 GLViewer_TexFont::~GLViewer_TexFont()
108 delete[] myPositions;
112 Initializes font parameters
114 void GLViewer_TexFont::init()
116 myNbSymbols = LastSymbolNumber - FirstSymbolNumber + 1;
118 // It is unsafe to draw all characters in a single row -
119 // this leads to problems on some graphic cards with small GL_MAX_TEXTURE_SIZE.
120 // So splitting the characters into rows each containing 32 characters (or less).
121 // Assuming contant height of each row (64 pixels) to simplify texture mapping.
122 // However, this can be improved if necessary.
123 QFontMetrics aFM( myQFont );
124 myFontHeight = aFM.height();
126 myWidths = new int[myNbSymbols];
127 myPositions = new int[myNbSymbols];
129 for( int i = 0, k = FirstSymbolNumber, aWidth = 0; i < myNbSymbols; i++, k++ )
131 // is it time to start a new row?
132 if ( !( i % TEX_ROW_LEN ) )
134 if( aWidth > myMaxRowWidth )
135 myMaxRowWidth = aWidth;
138 myWidths[i] = aFM.width( k );
139 myPositions[i] = aWidth;
140 aWidth += myWidths[i] + 2;
148 Generating font texture
150 bool GLViewer_TexFont::generateTexture()
152 GLViewer_TexFindId aFindFont;
153 aFindFont.myFontFamily = myQFont.family();//myQFont.toString();
154 aFindFont.myIsBold = myQFont.bold();
155 aFindFont.myIsItal = myQFont.italic();
156 aFindFont.myIsUndl = myQFont.underline();
157 aFindFont.myPointSize = myQFont.pointSize();
158 aFindFont.myViewPortId = size_t(QGLContext::currentContext());
160 if( TexFontBase.contains( aFindFont ) )
162 GLViewer_TexIdStored aTexture = TexFontBase[ aFindFont ];
163 myTexFont = aTexture.myTexFontId;
164 myTexFontWidth = aTexture.myTexFontWidth;
165 myTexFontHeight = aTexture.myTexFontHeight;
169 // Adding some pixels to have a gap between rows
170 int aRowPixelHeight = myFontHeight + TEX_ROW_GAP;
171 int aDescent = QFontMetrics( myQFont ).descent();
173 int aNumRows = myNbSymbols / TEX_ROW_LEN;
174 if ( myNbSymbols % TEX_ROW_LEN )
176 int pixelsHight = aNumRows * aRowPixelHeight;
179 myTexFontHeight = 64;
181 while( myTexFontWidth < myMaxRowWidth )
182 myTexFontWidth <<= 1;
183 while( myTexFontHeight < pixelsHight )
184 myTexFontHeight <<= 1;
186 // Checking whether the texture dimensions for the requested font
187 // do not exceed the maximum size supported by the OpenGL implementation
189 glGetIntegerv( GL_MAX_TEXTURE_SIZE, &maxSize );
190 if ( myTexFontWidth > maxSize || myTexFontHeight > maxSize )
193 QPixmap aPixmap( myTexFontWidth, myTexFontHeight );
194 aPixmap.fill( QColor( 0, 0, 0) );
195 QPainter aPainter( &aPixmap );
196 aPainter.setFont( myQFont );
198 for( int l = 0; l < myNbSymbols; l++ )
200 row = l / TEX_ROW_LEN;
202 aLetter += (char)(FirstSymbolNumber + l);
203 aPainter.setPen( QColor( 255,255,255) );
204 aPainter.drawText( myPositions[l], ( row + 1 ) * aRowPixelHeight - aDescent, aLetter );
207 QImage aImage = aPixmap.convertToImage();
211 // aImage.save("w:\\work\\CATHARE\\texture.png", "PNG");
213 char* pixels = new char[myTexFontWidth * myTexFontHeight * NB_TEX_COMP];
215 for( int i = 0; i < myTexFontHeight; i++ )
217 for( int j = 0; j < myTexFontWidth; j++ )
219 int aRed = qRed( aImage.pixel( j, myTexFontHeight - i - 1 ) );
220 int aGreen = qGreen( aImage.pixel( j, myTexFontHeight - i - 1 ) );
221 int aBlue = qBlue( aImage.pixel( j, myTexFontHeight - i - 1 ) );
223 if( aRed != 0 || aGreen != 0 || aBlue != 0 )
225 pixels[i * myTexFontWidth * NB_TEX_COMP + j * NB_TEX_COMP] = (GLubyte)( (aRed + aGreen + aBlue)/3 );
226 pixels[i * myTexFontWidth * NB_TEX_COMP + j * NB_TEX_COMP + 1]= (GLubyte) 255;
230 pixels[i * myTexFontWidth * NB_TEX_COMP + j * NB_TEX_COMP] = (GLubyte) 0;
231 pixels[i * myTexFontWidth * NB_TEX_COMP + j * NB_TEX_COMP + 1]= (GLubyte) 0;
236 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
237 glGenTextures(1, &myTexFont);
238 glBindTexture(GL_TEXTURE_2D, myTexFont);
239 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, myMinMagFilter);
240 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, myMinMagFilter);
241 glTexImage2D(GL_TEXTURE_2D,
253 GLViewer_TexIdStored aTexture;
254 aTexture.myTexFontId = myTexFont;
255 aTexture.myTexFontWidth = myTexFontWidth;
256 aTexture.myTexFontHeight = myTexFontHeight;
258 TexFontBase.insert( aFindFont, aTexture );
264 Drawing string in viewer
265 \param theStr - string to be drawn
266 \param theX - X position
267 \param theY - Y position
268 \param theScale - scale coefficient
270 void GLViewer_TexFont::drawString( QString theStr, GLdouble theX , GLdouble theY, GLfloat theScale )
272 // Adding some pixels to have a gap between rows
273 int aRowPixelHeight = myFontHeight + TEX_ROW_GAP;
275 float aXScale = 1.f, aYScale = 1.f;
276 if ( !myIsResizeable )
278 glGetFloatv (GL_MODELVIEW_MATRIX, modelMatrix);
279 aXScale = modelMatrix[0];
280 aYScale = modelMatrix[5];
282 else if ( theScale > 0.f )
284 aXScale = aXScale / theScale;
285 aYScale = aYScale / theScale;
289 glPushAttrib( GL_ENABLE_BIT | GL_TEXTURE_BIT );
291 glEnable(GL_TEXTURE_2D);
292 glPixelTransferi(GL_MAP_COLOR, 0);
294 glAlphaFunc(GL_GEQUAL, 0.05F);
295 glEnable(GL_ALPHA_TEST);
298 glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
300 glBindTexture(GL_TEXTURE_2D, myTexFont);
301 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
305 float aLettBeginS, aLettEndS, aLettBeginT, aLettEndT;
306 float aDY = ( aRowPixelHeight - 1 ) / aYScale, aDX;
309 for( int i = 0; i < theStr.length(); i++ )
311 aLetter = theStr.data()[i];
312 aLettIndex = (int)aLetter - FirstSymbolNumber;
313 row = aLettIndex / TEX_ROW_LEN;
315 aLettBeginS = (float)myPositions[aLettIndex] / ( (float)myTexFontWidth - 1.f );
316 aLettEndS = aLettBeginS + ( (float)myWidths[aLettIndex] - 1.f ) / ( (float)myTexFontWidth - 1.f );
317 aLettBeginT = ( myTexFontHeight - ( row + 1 ) * aRowPixelHeight ) / ( (float)myTexFontHeight - 1.f );
318 aLettEndT = aLettBeginT + ( (float)aRowPixelHeight - 1.f ) / ( (float)myTexFontHeight - 1.f );
320 aDX = ( (float)myWidths[aLettIndex] - 1.f ) / aXScale;
322 glTexCoord2f( aLettBeginS, aLettBeginT ); glVertex3f( theX, theY, 1.f );
323 glTexCoord2f( aLettBeginS, aLettEndT ); glVertex3f( theX, theY + aDY, 1.f );
324 glTexCoord2f( aLettEndS, aLettEndT ); glVertex3f( theX + aDX, theY + aDY, 1.f );
325 glTexCoord2f( aLettEndS, aLettBeginT ); glVertex3f( theX + aDX, theY, 1.f );
327 theX += aDX + mySeparator / aXScale;
331 // restore attributes
336 \return width of string in pixels
338 int GLViewer_TexFont::getStringWidth( QString theStr )
341 for( int i = 0; i < theStr.length(); i ++ )
343 char aLetter = theStr.data()[i];
344 int aLettIndex = (int)aLetter - FirstSymbolNumber;
345 aWidth += myWidths[aLettIndex] + mySeparator;
352 \return height of string in pixels
354 int GLViewer_TexFont::getStringHeight()
356 QFontMetrics aFM( myQFont );
361 Generates list base for bitmap fonts
363 static GLuint displayListBase( QFont* theFont )
368 //static QMap<GLViewer_TexFindId, GLuint> fontCache;
369 GLViewer_TexFindId aFindFont;
370 aFindFont.myFontFamily = theFont->family();//theFont->toString();
371 aFindFont.myIsBold = theFont->bold();
372 aFindFont.myIsItal = theFont->italic();
373 aFindFont.myIsUndl = theFont->underline();
374 aFindFont.myPointSize = theFont->pointSize();
377 HGLRC ctx = ::wglGetCurrentContext();
381 aFindFont.myViewPortId = (int)ctx;
383 if ( GLViewer_TexFont::BitmapFontCache.contains( aFindFont ) )
384 aList = GLViewer_TexFont::BitmapFontCache[aFindFont];
388 QMap<GLViewer_TexFindId, GLuint>::iterator it = GLViewer_TexFont::BitmapFontCache.begin();
389 for ( ; it != GLViewer_TexFont::BitmapFontCache.end(); ++it )
391 if ( it.key().myViewPortId == (int)ctx && it.data() > listBase )
392 listBase = it.data();
396 HDC glHdc = ::wglGetCurrentDC();
397 ::SelectObject( glHdc, theFont->handle() );
398 if ( !::wglUseFontBitmaps( glHdc, 0, 256, listBase ) )
401 GLViewer_TexFont::BitmapFontCache[aFindFont] = aList;
404 Display* aDisp = glXGetCurrentDisplay();
408 printf( "Can't find current dislay\n" );
413 GLXContext aCont = glXGetCurrentContext();
417 printf( "Can't find current context\n" );
422 aFindFont.myViewPortId = size_t(aCont);
424 if ( GLViewer_TexFont::BitmapFontCache.contains( aFindFont ) )
425 aList = GLViewer_TexFont::BitmapFontCache[aFindFont];
429 QMap<GLViewer_TexFindId, GLuint>::iterator it = GLViewer_TexFont::BitmapFontCache.begin();
430 for ( ; it != GLViewer_TexFont::BitmapFontCache.end(); ++it )
432 if ( it.key().myViewPortId == size_t(aCont) && it.data() > listBase )
433 listBase = it.data();
437 //glXUseXFont( (Font)(theFont->handle()), 0, 256, listBase );
439 QString aFontDef = theFont->toString();
440 char** xFontList = XListFonts( aDisp, aFontDef.latin1()/*aFindFont.myFontString.data()*/, 1, &aFontCont );
441 if( !theFont->handle() )
444 printf( "Can't load font %s. loading default font....\n", aFontDef.latin1()/*aFindFont.myFontString.data()*/ );
446 QString aFontMask ("-*-*-*-r-*-*-");
447 aFontMask += aFontDef/*aFindFont.myFontString*/.section( ',', 1, 1 );
449 printf( "Height of Default font: %s\n", aFontDef/*aFindFont.myFontString*/.section( ',', 1, 1 ).data() );
451 aFontMask += "-*-*-*-m-*-*-*";
452 xFontList = XListFonts( aDisp, aFontMask.data()/*"-*-*-*-r-*-*-12-*-*-*-m-*-*-*"*/, 1, &aFontCont );
456 printf( "Can't load default font\n" );
460 glXUseXFont( (Font)(XLoadFont( aDisp,xFontList[0] )), 0, 256, listBase );
463 glXUseXFont( (Font)(theFont->handle()), 0, 256, listBase );
466 GLViewer_TexFont::BitmapFontCache[aFindFont] = aList;
477 GLViewer_Drawer::GLViewer_Drawer()
478 : myFont( "Helvetica", 10, QFont::Bold )
480 myXScale = myYScale = 0.0;
482 myTextList = 0/*-1*/;
483 myObjectType = "GLViewer_Object";
485 myTextFormat = DTF_BITMAP;
492 GLViewer_Drawer::~GLViewer_Drawer()
495 glDeleteLists( myTextList, 1 );
499 Clears all generated textures
501 void GLViewer_Drawer::destroyAllTextures()
503 QMap<GLViewer_TexFindId,GLViewer_TexIdStored>::Iterator anIt= GLViewer_TexFont::TexFontBase.begin();
504 QMap<GLViewer_TexFindId,GLViewer_TexIdStored>::Iterator anEndIt= GLViewer_TexFont::TexFontBase.end();
506 for( ; anIt != anEndIt; anIt++ )
507 glDeleteTextures( 1, &(anIt.data().myTexFontId) );
511 Enables and disables antialiasing in Open GL (for points, lines and polygons).
512 \param on - if it is true, antialiasing is enabled
514 void GLViewer_Drawer::setAntialiasing(const bool on)
518 glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
519 glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);
521 glEnable(GL_POINT_SMOOTH);
522 glEnable(GL_LINE_SMOOTH);
523 glEnable(GL_POLYGON_SMOOTH);
524 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
529 glDisable(GL_POINT_SMOOTH);
530 glDisable(GL_LINE_SMOOTH);
531 glDisable(GL_POLYGON_SMOOTH);
532 glBlendFunc (GL_ONE, GL_ZERO);
533 glDisable (GL_BLEND);
537 /*! Loads texture from file
538 \param fileName - the name of texture file
539 \param x_size - the horizontal size of picture ( less or equal texture horizontal size )
540 \param y_size - the vertical size of picture ( less or equal texture vertical size )
541 \param t_size - the size of texture ( texture vertical size equals texture horizontal size )
543 GLuint GLViewer_Drawer::loadTexture( const QString& fileName,
549 if ( fileName.isEmpty() || !buf.load( fileName ) )
553 int h = buf.height();
556 while( size < w || size < h )
560 GLubyte* pixels = new GLubyte[ size * size * 4 ];
562 for( int i = 0; i < size; i++ )
564 for( int j = 0; j < size; j++ )
569 QRgb pixel = buf.pixel( j, h - i - 1 );
570 r = (GLubyte)qRed( pixel );
571 g = (GLubyte)qGreen( pixel );
572 b = (GLubyte)qBlue( pixel );
573 a = (GLubyte)qAlpha( pixel );
583 int index = 4 * ( i * size + j );
585 pixels[ index + 1 ] = g;
586 pixels[ index + 2 ] = b;
587 pixels[ index + 3 ] = a;
592 glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
593 glGenTextures( 1, &texture );
594 glBindTexture( GL_TEXTURE_2D, texture );
595 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
596 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
597 glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, size, size, 0,
598 GL_RGBA, GL_UNSIGNED_BYTE, pixels );
614 /*! Draw square texture
615 \param texture - the texture ID
616 \param size - the size of square texture
620 void GLViewer_Drawer::drawTexture( GLuint texture, GLint size, GLfloat x, GLfloat y )
622 /*float xScale = myXScale;
623 float yScale = myYScale;
625 glColor4f( 1.0, 1.0, 1.0, 1.0 );
627 glEnable( GL_TEXTURE_2D );
628 glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
629 glAlphaFunc( GL_GREATER, 0.95F );
630 glEnable( GL_ALPHA_TEST );
632 glBindTexture( GL_TEXTURE_2D, texture );
635 glTexCoord2f( 0.0, 0.0 );
636 glVertex3f( x-size/2./xScale, y-size/2./yScale, 0.0 );
638 glTexCoord2f( 0.0, 1.0 );
639 glVertex3f( x-size/2./xScale, y+size/2./yScale, 0.0 );
641 glTexCoord2f( 1.0, 1.0 );
642 glVertex3f( x+size/2./xScale, y+size/2./yScale, 0.0 );
644 glTexCoord2f( 1.0, 0.0 );
645 glVertex3f( x+size/2./xScale, y-size/2./yScale, 0.0 );
650 glDisable( GL_ALPHA_TEST );
651 glDisable( GL_TEXTURE_2D );*/
653 drawTexture( texture, size, size, x, y );
657 \param texture - the texture ID
658 \param x_size - the horizontal size of texture
659 \param y_size - the vertical size of texture
663 void GLViewer_Drawer::drawTexture( GLuint texture, GLint x_size, GLint y_size, GLfloat x, GLfloat y )
665 /*float xScale = myXScale;
666 float yScale = myYScale;
668 glColor4f( 1.0, 1.0, 1.0, 1.0 );
670 glEnable( GL_TEXTURE_2D );
671 glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
672 glAlphaFunc( GL_GREATER, 0.95F );
673 glEnable( GL_ALPHA_TEST );
675 glBindTexture( GL_TEXTURE_2D, texture );
678 glTexCoord2f( 0.0, 0.0 );
679 glVertex3f( x-x_size/2./xScale, y-y_size/2./yScale, 0.0 );
681 glTexCoord2f( 0.0, 1.0 );
682 glVertex3f( x-x_size/2./xScale, y+y_size/2./yScale, 0.0 );
684 glTexCoord2f( 1.0, 1.0 );
685 glVertex3f( x+x_size/2./xScale, y+y_size/2./yScale, 0.0 );
687 glTexCoord2f( 1.0, 0.0 );
688 glVertex3f( x+x_size/2./xScale, y-y_size/2./yScale, 0.0 );
693 glDisable( GL_ALPHA_TEST );
694 glDisable( GL_TEXTURE_2D );*/
695 drawTexturePart( texture, 1.0, 1.0, x_size, y_size, x, y );
698 /*! Draw texture part
699 \param texture - the texture ID
700 \param x_ratio - the horizontal ratio of texture part
701 \param y_ratio - the vertical ratio of texture part
702 \param x_size - the horizontal size of texture
703 \param y_size - the vertical size of texture
706 \param scale - common scale factor ( if = 0, use drawer scales )
708 void GLViewer_Drawer::drawTexturePart( GLuint texture,
720 float xScale = scale > 0. ? 1./scale : myXScale;
721 float yScale = scale > 0. ? 1./scale : myYScale;
723 glColor4f( 1.0, 1.0, 1.0, 1.0 );
726 glEnable( GL_TEXTURE_2D );
727 glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
728 bool hasAlpha = glIsEnabled( GL_ALPHA_TEST );
729 glDisable( GL_ALPHA_TEST );
731 glBindTexture( GL_TEXTURE_2D, texture );
734 glTexCoord2f( 0.0, 0.0 );
735 glVertex3f( x-x_size/2./xScale, y-y_size/2./yScale, 0.0 );
737 glTexCoord2f( 0.0, y_ratio );
738 glVertex3f( x-x_size/2./xScale, y+y_size/2./yScale, 0.0 );
740 glTexCoord2f( x_ratio, y_ratio );
741 glVertex3f( x+x_size/2./xScale, y+y_size/2./yScale, 0.0 );
743 glTexCoord2f( x_ratio, 0.0 );
744 glVertex3f( x+x_size/2./xScale, y-y_size/2./yScale, 0.0 );
750 glEnable( GL_ALPHA_TEST );
752 glDisable( GL_TEXTURE_2D );
757 \param text - text to be drawn
758 \param xPos - x position
759 \param yPos - y position
760 \param color - color of text
761 \param theFont - font of text
762 \param theSeparator - letter separator
763 \param theFormat - text format (by default DTF_BITMAP)
765 void GLViewer_Drawer::drawText( const QString& text, GLfloat xPos, GLfloat yPos,
766 const QColor& color, QFont* theFont, int theSeparator, DisplayTextFormat theFormat )
768 glColor3f( ( GLfloat )color.red() / 255,
769 ( GLfloat )color.green() / 255,
770 ( GLfloat )color.blue() / 255 );
772 if( theFormat != DTF_BITMAP )
774 GLViewer_TexFont aTexFont( theFont, theSeparator, theFormat == DTF_TEXTURE_SCALABLE, GL_LINEAR );
775 // Font texture was not found or generated --> cannot draw text
776 if ( !aTexFont.generateTexture() )
779 if ( theFormat == DTF_TEXTURE_SCALABLE )
780 aTexFont.drawString( text, xPos, yPos, textScale() );
782 aTexFont.drawString( text, xPos, yPos );
786 glRasterPos2f( xPos, yPos );
787 glListBase( displayListBase( theFont ) );
788 glCallLists( text.length(), GL_UNSIGNED_BYTE, text.local8Bit().data() );
795 void GLViewer_Drawer::drawText( GLViewer_Object* theObject )
800 GLViewer_Text* aText = theObject->getGLText();
804 GLfloat aPosX, aPosY;
805 aText->getPosition( aPosX, aPosY );
806 // get temporary copy of font
807 QFont aTmpVarFont = aText->getFont();
808 drawText( aText->getText(), aPosX, aPosY, aText->getColor(), &aTmpVarFont, aText->getSeparator(), aText->getDisplayTextFormat() );
812 \param text - the text string
815 \param hPosition - horizontal alignment
816 \param vPosition - vertical alignment
817 \param color - text color
818 \param smallFont - font format
820 void GLViewer_Drawer::drawGLText( QString text, float x, float y,
821 int hPosition, int vPosition, QColor color, bool smallFont )
823 QFont aFont( myFont );
825 aFont.setPointSize( int(aFont.pointSize() * 0.8) );
827 GLfloat scale = textScale() > 0. ? textScale() : 1.;
829 QFontMetrics aFontMetrics( aFont );
830 float width = myTextFormat == DTF_TEXTURE_SCALABLE ? aFontMetrics.width( text ) * scale : aFontMetrics.width( text ) / myXScale;
831 float height = myTextFormat == DTF_TEXTURE_SCALABLE ? aFontMetrics.height() * scale : aFontMetrics.height() / myYScale;
832 float gap = 5 / myXScale;
836 case GLText_Left : x -= ( gap + width ); break;
837 case GLText_Center : x -= width / 2; break;
838 case GLText_Right : x += gap; break;
844 case GLText_Top : y += height * 0.5; break;
845 case GLText_Center : y -= height * 0.5; break;
846 case GLText_Bottom : y -= height * 1.5; break;
850 drawText( text, x, y, color, &aFont, 2, myTextFormat );
854 \return a rectangle of text (without viewer scale)
856 GLViewer_Rect GLViewer_Drawer::textRect( const QString& text ) const
858 GLfloat scale = textScale() > 0. ? textScale() : 1.;
860 QFontMetrics aFontMetrics( myFont );
861 float width = myTextFormat == DTF_TEXTURE_SCALABLE ? aFontMetrics.width( text ) * scale : aFontMetrics.width( text );
862 float height = myTextFormat == DTF_TEXTURE_SCALABLE ? aFontMetrics.height() * scale : aFontMetrics.height();
864 return GLViewer_Rect( 0, width, height, 0 );
869 \param rect - instance of primitive
870 \param color - color of primitive
872 void GLViewer_Drawer::drawRectangle( GLViewer_Rect* rect, QColor color )
877 float x1 = rect->left();
878 float x2 = rect->right();
879 float y1 = rect->bottom();
880 float y2 = rect->top();
882 glColor3f( ( GLfloat )color.red() / 255,
883 ( GLfloat )color.green() / 255,
884 ( GLfloat )color.blue() / 255 );
887 glBegin( GL_LINE_LOOP );
888 glVertex2f( x1, y1 );
889 glVertex2f( x1, y2 );
890 glVertex2f( x2, y2 );
891 glVertex2f( x2, y1 );
896 Saves object to file with format of HPGL
898 \param aViewerCS - viewer co-ordinate system
899 \param aHPGLCS - paper co-ordinate system
901 bool GLViewer_Drawer::translateToHPGL( QFile& hFile, GLViewer_CoordSystem* aViewerCS, GLViewer_CoordSystem* aHPGLCS )
904 for( int i=0, n=myObjects.count(); i<n; i++ )
905 result &= myObjects[i]->translateToHPGL( hFile, aViewerCS, aHPGLCS );
910 Saves object to file with format of PostScript
912 \param aViewerCS - viewer co-ordinate system
913 \param aPSCS - paper co-ordinate system
915 bool GLViewer_Drawer::translateToPS( QFile& hFile, GLViewer_CoordSystem* aViewerCS, GLViewer_CoordSystem* aPSCS )
918 for( int i=0, n=myObjects.count(); i<n; i++ )
919 result &= myObjects[i]->translateToPS( hFile, aViewerCS, aPSCS );
925 Saves object to file with format of EMF
927 \param aViewerCS - viewer co-ordinate system
928 \param aEMFCS - paper co-ordinate system
930 bool GLViewer_Drawer::translateToEMF( HDC hDC, GLViewer_CoordSystem* aViewerCS, GLViewer_CoordSystem* aEMFCS )
933 for( int i=0, n=myObjects.count(); i<n; i++ )
934 result &= myObjects[i]->translateToEMF( hDC, aViewerCS, aEMFCS );
941 \param rect - instance of primitive
942 \param lineWidth - width of line
943 \param gap - gap of rectangle
944 \param color - color of primitive
945 \param filled - if it is true, then rectangle will be drawn filled with color "fillingColor"
946 \param fillingColor - color of filling
948 void GLViewer_Drawer::drawRectangle( GLViewer_Rect* rect, GLfloat lineWidth, GLfloat gap,
949 QColor color, bool filled, QColor fillingColor )
954 float x1 = rect->left() - gap;
955 float x2 = rect->right() + gap;
956 float y1 = rect->bottom() - gap;
957 float y2 = rect->top() + gap;
961 glColor3f( ( GLfloat )fillingColor.red() / 255,
962 ( GLfloat )fillingColor.green() / 255,
963 ( GLfloat )fillingColor.blue() / 255 );
964 glBegin( GL_POLYGON );
965 glVertex2f( x1, y1 );
966 glVertex2f( x1, y2 );
967 glVertex2f( x2, y2 );
968 glVertex2f( x2, y1 );
972 glColor3f( ( GLfloat )color.red() / 255,
973 ( GLfloat )color.green() / 255,
974 ( GLfloat )color.blue() / 255 );
975 glLineWidth( lineWidth );
977 glBegin( GL_LINE_LOOP );
978 glVertex2f( x1, y1 );
979 glVertex2f( x1, y2 );
980 glVertex2f( x2, y2 );
981 glVertex2f( x2, y1 );
987 \param pntList - list of points
988 \param color - color of contour
989 \param lineWidth - width of line
991 void GLViewer_Drawer::drawContour( const GLViewer_PntList& pntList, QColor color, GLfloat lineWidth )
993 glColor3f( ( GLfloat )color.red() / 255,
994 ( GLfloat )color.green() / 255,
995 ( GLfloat )color.blue() / 255 );
996 glLineWidth( lineWidth );
999 QValueList<GLViewer_Pnt>::const_iterator it = pntList.begin();
1000 for( ; it != pntList.end(); ++it )
1001 glVertex2f( (*it).x(), (*it).y() );
1006 Draws rectangular contour
1007 \param rect - instance of rectangle
1008 \param color - color of primitive
1009 \param lineWidth - width of line
1010 \param pattern - pattern of line
1011 \param isStripe - enables line stipple
1013 void GLViewer_Drawer::drawContour( GLViewer_Rect* rect, QColor color, GLfloat lineWidth,
1014 GLushort pattern, bool isStripe )
1016 float x1 = rect->left();
1017 float x2 = rect->right();
1018 float y1 = rect->bottom();
1019 float y2 = rect->top();
1021 glColor3f( ( GLfloat )color.red() / 255,
1022 ( GLfloat )color.green() / 255,
1023 ( GLfloat )color.blue() / 255 );
1024 glLineWidth( lineWidth );
1028 glEnable( GL_LINE_STIPPLE );
1029 glLineStipple( 1, pattern );
1032 glBegin( GL_LINE_LOOP );
1034 glVertex2f( x1, y1 );
1035 glVertex2f( x1, y2 );
1036 glVertex2f( x2, y2 );
1037 glVertex2f( x2, y1 );
1040 glDisable( GL_LINE_STIPPLE );
1045 \param pntList - list of points
1046 \param color - color of polygon
1048 void GLViewer_Drawer::drawPolygon( const GLViewer_PntList& pntList, QColor color )
1050 glColor3f( ( GLfloat )color.red() / 255,
1051 ( GLfloat )color.green() / 255,
1052 ( GLfloat )color.blue() / 255 );
1053 glBegin( GL_POLYGON );
1054 QValueList<GLViewer_Pnt>::const_iterator it = pntList.begin();
1055 for( ; it != pntList.end(); ++it )
1056 glVertex2f( (*it).x(), (*it).y() );
1062 \param rect - instance of rectangle
1063 \param color - color of polygon
1064 \param pattern - pattern of line
1065 \param isStripe - enables line stipple
1067 void GLViewer_Drawer::drawPolygon( GLViewer_Rect* rect, QColor color,
1068 GLushort pattern, bool isStripe )
1070 float x1 = rect->left();
1071 float x2 = rect->right();
1072 float y1 = rect->bottom();
1073 float y2 = rect->top();
1074 glColor3f( ( GLfloat )color.red() / 255,
1075 ( GLfloat )color.green() / 255,
1076 ( GLfloat )color.blue() / 255 );
1080 glEnable( GL_LINE_STIPPLE );
1081 glLineStipple( 1, pattern );
1083 glBegin( GL_POLYGON );
1085 glVertex2f( x1, y1 );
1086 glVertex2f( x1, y2 );
1087 glVertex2f( x2, y2 );
1088 glVertex2f( x2, y1 );
1091 glDisable( GL_LINE_STIPPLE );
1094 GLubyte rasterVertex[5] = { 0x70, 0xf8, 0xf8, 0xf8, 0x70 };
1098 \param x - x position
1099 \param y - y position
1100 \param color - color of vertex
1102 void GLViewer_Drawer::drawVertex( GLfloat x, GLfloat y, QColor color )
1104 glColor3f( ( GLfloat )color.red() / 255, ( GLfloat )color.green() / 255, ( GLfloat )color.blue() / 255 );
1105 glRasterPos2f( x, y );
1106 glBitmap( 5, 5, 2, 2, 0, 0, rasterVertex );
1109 GLubyte rasterCross[7] = { 0x82, 0x44, 0x28, 0x10, 0x28, 0x44, 0x82 };
1113 \param x - x position
1114 \param y - y position
1115 \param color - color of cross
1117 void GLViewer_Drawer::drawCross( GLfloat x, GLfloat y, QColor color )
1119 glColor3f( ( GLfloat )color.red() / 255, ( GLfloat )color.green() / 255, ( GLfloat )color.blue() / 255 );
1120 glRasterPos2f( x, y );
1121 glBitmap( 7, 7, 3, 3, 0, 0, rasterCross );
1126 \param red, green, blue - components of color
1127 \param lineWidth - width of line
1129 \param length - length of arrow
1130 \param width - width of arrow
1131 \param x - x position
1132 \param y - y position
1133 \param angle - angle of arrow
1134 \param filled - drawn as filled
1136 void GLViewer_Drawer::drawArrow( const GLfloat red, const GLfloat green, const GLfloat blue,
1138 GLfloat staff, GLfloat length, GLfloat width,
1139 GLfloat x, GLfloat y, GLfloat angle, GLboolean filled )
1142 GLfloat vy1 = y + staff + length;
1143 GLfloat vx2 = vx1 - width / 2;
1144 GLfloat vy2 = vy1 - length;
1145 GLfloat vx3 = vx1 + width / 2;
1146 GLfloat vy3 = vy1 - length;
1148 gp_Pnt2d p0( x, y );
1149 gp_Pnt2d p1( vx1, vy1 );
1150 gp_Pnt2d p2( vx2, vy2 );
1151 gp_Pnt2d p3( vx3, vy3 );
1153 p1.Rotate( p0, angle );
1154 p2.Rotate( p0, angle );
1155 p3.Rotate( p0, angle );
1157 vx1 = p1.X(); vy1 = p1.Y();
1158 vx2 = p2.X(); vy2 = p2.Y();
1159 vx3 = p3.X(); vy3 = p3.Y();
1161 glColor3f( red, green, blue );
1162 glLineWidth( lineWidth );
1164 glBegin( GL_LINES );
1166 glVertex2f( vx1, vy1 );
1172 glBegin( GL_LINES );
1173 glVertex2f( vx1, vy1 );
1174 glVertex2f( vx2, vy2 );
1175 glVertex2f( vx1, vy1 );
1176 glVertex2f( vx3, vy3 );
1181 glBegin( GL_POLYGON );
1182 glVertex2f( vx1, vy1 );
1183 glVertex2f( vx2, vy2 );
1184 glVertex2f( vx3, vy3 );