1 // Created on: 2011-07-13
2 // Created by: Sergey ZERCHANINOV
3 // Copyright (c) 2011-2013 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
16 #include <OpenGl_AspectText.hxx>
17 #include <OpenGl_GlCore11.hxx>
18 #include <OpenGl_GraphicDriver.hxx>
19 #include <OpenGl_ShaderManager.hxx>
20 #include <OpenGl_ShaderProgram.hxx>
21 #include <OpenGl_ShaderStates.hxx>
22 #include <OpenGl_Text.hxx>
23 #include <OpenGl_Workspace.hxx>
25 #include <Font_FontMgr.hxx>
26 #include <TCollection_HAsciiString.hxx>
38 static const GLdouble THE_IDENTITY_MATRIX[4][4] =
47 static char const* TheFamily[] = {"Helvetica", "Courier", "Times"};
48 static char const* TheItalic[] = {"Oblique", "Oblique", "Italic"};
49 static char const* TheBase[] = {"", "", "-Roman"};
51 //! Convert font name used for rendering to some "good" font names
52 //! that produce good vector text.
53 static void getGL2PSFontName (const char* theSrcFont,
56 if (strstr (theSrcFont, "Symbol"))
58 sprintf (thePsFont, "%s", "Symbol");
61 else if (strstr (theSrcFont, "ZapfDingbats"))
63 sprintf (thePsFont, "%s", "WingDings");
69 bool isItalic = false;
70 if (strstr (theSrcFont, "Courier"))
74 else if (strstr (theSrcFont, "Times"))
79 if (strstr (theSrcFont, "Bold"))
83 if (strstr (theSrcFont, "Italic")
84 || strstr (theSrcFont, "Oblique"))
93 sprintf (thePsFont, "%s-Bold%s", TheFamily[aFontId], TheItalic[aFontId]);
97 sprintf (thePsFont, "%s-Bold", TheFamily[aFontId]);
102 sprintf (thePsFont, "%s-%s", TheFamily[aFontId], TheItalic[aFontId]);
106 sprintf (thePsFont, "%s%s", TheFamily[aFontId], TheBase[aFontId]);
110 static void exportText (const NCollection_String& theText,
111 const Standard_Boolean theIs2d,
112 const OpenGl_AspectText& theAspect,
113 const Standard_Integer theHeight)
117 getGL2PSFontName (theAspect.FontName().ToCString(), aPsFont);
121 glRasterPos2f (0.0f, 0.0f);
125 glRasterPos3f (0.0f, 0.0f, 0.0f);
129 glBitmap (1, 1, 0, 0, 0, 0, &aZero);
131 // Standard GL2PS's alignment isn't used, because it doesn't work correctly
132 // for all formats, therefore alignment is calculated manually relative
133 // to the bottom-left corner, which corresponds to the GL2PS_TEXT_BL value
134 gl2psTextOpt (theText.ToCString(), aPsFont, (GLshort)theHeight, GL2PS_TEXT_BL, theAspect.Angle());
140 // =======================================================================
141 // function : OpenGl_Text
143 // =======================================================================
144 OpenGl_Text::OpenGl_Text()
148 myScaleHeight (1.0f),
149 myPoint (0.0f, 0.0f, 0.0f),
152 myParams.Height = 10;
153 myParams.HAlign = Graphic3d_HTA_LEFT;
154 myParams.VAlign = Graphic3d_VTA_BOTTOM;
157 // =======================================================================
158 // function : OpenGl_Text
160 // =======================================================================
161 OpenGl_Text::OpenGl_Text (const TCollection_ExtendedString& theText,
162 const OpenGl_Vec3& thePoint,
163 const OpenGl_TextParam& theParams)
167 myScaleHeight (1.0f),
168 myExportHeight (1.0f),
169 myParams (theParams),
170 myString ((Standard_Utf16Char* )theText.ToExtString()),
177 // =======================================================================
178 // function : SetPosition
180 // =======================================================================
181 void OpenGl_Text::SetPosition (const OpenGl_Vec3& thePoint)
186 // =======================================================================
187 // function : SetFontSize
189 // =======================================================================
190 void OpenGl_Text::SetFontSize (const Handle(OpenGl_Context)& theCtx,
191 const Standard_Integer theFontSize)
193 if (myParams.Height != theFontSize)
197 myParams.Height = theFontSize;
200 // =======================================================================
203 // =======================================================================
204 void OpenGl_Text::Init (const Handle(OpenGl_Context)& theCtx,
205 const Standard_Utf8Char* theText,
206 const OpenGl_Vec3& thePoint)
208 releaseVbos (theCtx);
211 myString.FromUnicode (theText);
214 // =======================================================================
217 // =======================================================================
218 void OpenGl_Text::Init (const Handle(OpenGl_Context)& theCtx,
219 const Standard_Utf8Char* theText,
220 const OpenGl_Vec3& thePoint,
221 const OpenGl_TextParam& theParams)
223 if (myParams.Height != theParams.Height)
229 releaseVbos (theCtx);
232 myParams = theParams;
234 myString.FromUnicode (theText);
237 // =======================================================================
240 // =======================================================================
241 void OpenGl_Text::Init (const Handle(OpenGl_Context)& theCtx,
242 const TCollection_ExtendedString& theText,
243 const OpenGl_Vec2& thePoint,
244 const OpenGl_TextParam& theParams)
246 if (myParams.Height != theParams.Height)
252 releaseVbos (theCtx);
255 myParams = theParams;
256 myPoint.xy() = thePoint;
258 myString.FromUnicode ((Standard_Utf16Char* )theText.ToExtString());
261 // =======================================================================
262 // function : ~OpenGl_Text
264 // =======================================================================
265 OpenGl_Text::~OpenGl_Text()
270 // =======================================================================
271 // function : releaseVbos
273 // =======================================================================
274 void OpenGl_Text::releaseVbos (const Handle(OpenGl_Context)& theCtx)
276 for (Standard_Integer anIter = 0; anIter < myVertsVbo.Length(); ++anIter)
278 Handle(OpenGl_VertexBuffer)& aVerts = myVertsVbo.ChangeValue (anIter);
279 Handle(OpenGl_VertexBuffer)& aTCrds = myTCrdsVbo.ChangeValue (anIter);
281 if (!theCtx.IsNull())
283 theCtx->DelayedRelease (aVerts);
284 theCtx->DelayedRelease (aTCrds);
292 myVertsArray.Clear();
293 myTCrdsArray.Clear();
296 // =======================================================================
297 // function : Release
299 // =======================================================================
300 void OpenGl_Text::Release (const Handle(OpenGl_Context)& theCtx)
302 releaseVbos (theCtx);
303 if (!myFont.IsNull())
305 Handle(OpenGl_Context) aCtx = theCtx;
306 const TCollection_AsciiString aKey = myFont->ResourceKey();
308 aCtx->ReleaseResource (aKey, Standard_True);
312 // =======================================================================
313 // function : StringSize
315 // =======================================================================
316 void OpenGl_Text::StringSize (const Handle(OpenGl_Context)& theCtx,
317 const NCollection_String& theText,
318 const OpenGl_AspectText& theTextAspect,
319 const OpenGl_TextParam& theParams,
320 Standard_ShortReal& theWidth,
321 Standard_ShortReal& theAscent,
322 Standard_ShortReal& theDescent)
327 const TCollection_AsciiString aFontKey = FontKey (theTextAspect, theParams.Height);
328 Handle(OpenGl_Font) aFont = FindFont (theCtx, theTextAspect, theParams.Height, aFontKey);
329 if (aFont.IsNull() || !aFont->IsValid())
334 theAscent = aFont->Ascender();
335 theDescent = aFont->Descender();
337 GLfloat aWidth = 0.0f;
338 for (NCollection_Utf8Iter anIter = theText.Iterator(); *anIter != 0;)
340 const Standard_Utf32Char aCharThis = *anIter;
341 const Standard_Utf32Char aCharNext = *++anIter;
343 if (aCharThis == '\x0D' // CR (carriage return)
344 || aCharThis == '\a' // BEL (alarm)
345 || aCharThis == '\f' // FF (form feed) NP (new page)
346 || aCharThis == '\b' // BS (backspace)
347 || aCharThis == '\v') // VT (vertical tab)
349 continue; // skip unsupported carriage control codes
351 else if (aCharThis == '\x0A') // LF (line feed, new line)
353 theWidth = Max (theWidth, aWidth);
357 else if (aCharThis == ' ')
359 aWidth += aFont->AdvanceX (aCharThis, aCharNext);
362 else if (aCharThis == '\t')
364 aWidth += aFont->AdvanceX (' ', aCharNext) * 8.0f;
368 aWidth += aFont->AdvanceX (aCharThis, aCharNext);
370 theWidth = Max (theWidth, aWidth);
372 Handle(OpenGl_Context) aCtx = theCtx;
374 aCtx->ReleaseResource (aFontKey, Standard_True);
377 // =======================================================================
380 // =======================================================================
381 void OpenGl_Text::Render (const Handle(OpenGl_Workspace)& theWorkspace) const
383 const OpenGl_AspectText* aTextAspect = theWorkspace->AspectText (Standard_True);
384 const Handle(OpenGl_Texture) aPrevTexture = theWorkspace->DisableTexture();
386 const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
388 if (aCtx->IsGlGreaterEqual (2, 0))
390 Handle(OpenGl_ShaderProgram) aProgram = aTextAspect->ShaderProgramRes (theWorkspace);
392 if (!aProgram.IsNull())
394 aProgram->BindWithVariables (aCtx);
396 const OpenGl_MaterialState* aMaterialState = aCtx->ShaderManager()->MaterialState (aProgram);
398 if (aMaterialState == NULL || aMaterialState->Aspect() != aTextAspect)
399 aCtx->ShaderManager()->UpdateMaterialStateTo (aProgram, aTextAspect);
401 aCtx->ShaderManager()->PushState (aProgram);
405 OpenGl_ShaderProgram::Unbind (aCtx);
409 // use highlight color or colors from aspect
410 if (theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT)
412 render (theWorkspace->PrinterContext(),
415 *theWorkspace->HighlightColor,
416 *theWorkspace->HighlightColor);
420 render (theWorkspace->PrinterContext(),
423 aTextAspect->Color(),
424 aTextAspect->SubtitleColor());
428 if (!aPrevTexture.IsNull())
430 theWorkspace->EnableTexture (aPrevTexture);
434 // =======================================================================
437 // =======================================================================
438 void OpenGl_Text::Render (const Handle(OpenGl_PrinterContext)& thePrintCtx,
439 const Handle(OpenGl_Context)& theCtx,
440 const OpenGl_AspectText& theTextAspect) const
442 render (thePrintCtx, theCtx, theTextAspect, theTextAspect.Color(), theTextAspect.SubtitleColor());
445 // =======================================================================
446 // function : setupMatrix
448 // =======================================================================
449 void OpenGl_Text::setupMatrix (const Handle(OpenGl_PrinterContext)& thePrintCtx,
450 const Handle(OpenGl_Context)& /*theCtx*/,
451 const OpenGl_AspectText& theTextAspect,
452 const OpenGl_Vec3 theDVec) const
458 glTranslatef (myPoint.x() + theDVec.x(), myPoint.y() + theDVec.y(), 0.0f);
459 glRotatef (180.0f, 1.0f, 0.0f, 0.0f);
463 // align coordinates to the nearest integer
464 // to avoid extra interpolation issues
465 GLdouble anObjX, anObjY, anObjZ;
466 gluUnProject (std::floor (myWinX + (GLdouble )theDVec.x()),
467 std::floor (myWinY + (GLdouble )theDVec.y()),
468 myWinZ + (GLdouble )theDVec.z(),
469 (GLdouble* )THE_IDENTITY_MATRIX, myProjMatrix, myViewport,
470 &anObjX, &anObjY, &anObjZ);
473 glTranslated (anObjX, anObjY, anObjZ);
474 glRotated (theTextAspect.Angle(), 0.0, 0.0, 1.0);
475 if (!theTextAspect.IsZoomable())
478 // if the context has assigned printer context, use it's parameters
479 if (!thePrintCtx.IsNull())
481 // get printing scaling in x and y dimensions
482 GLfloat aTextScalex = 1.0f, aTextScaley = 1.0f;
483 thePrintCtx->GetScale (aTextScalex, aTextScaley);
485 // text should be scaled in all directions with same
486 // factor to save its proportions, so use height (y) scaling
487 // as it is better for keeping text/3d graphics proportions
488 glScalef (aTextScaley, aTextScaley, aTextScaley);
491 glScaled (myScaleHeight, myScaleHeight, myScaleHeight);
496 // =======================================================================
497 // function : drawText
499 // =======================================================================
501 void OpenGl_Text::drawText (const Handle(OpenGl_PrinterContext)& ,
502 const Handle(OpenGl_Context)& theCtx,
504 const OpenGl_AspectText& theTextAspect) const
506 const OpenGl_AspectText& ) const
510 if (theCtx->IsFeedback())
512 // position of the text and alignment is calculated by transformation matrix
513 exportText (myString, myIs2d, theTextAspect, (Standard_Integer )myExportHeight);
518 if (myVertsVbo.Length() == myTextures.Length())
520 for (Standard_Integer anIter = 0; anIter < myTextures.Length(); ++anIter)
522 const GLuint aTexId = myTextures.Value (anIter);
523 const Handle(OpenGl_VertexBuffer)& aVerts = myVertsVbo.Value (anIter);
524 const Handle(OpenGl_VertexBuffer)& aTCrds = myTCrdsVbo.Value (anIter);
525 aVerts->BindFixed (theCtx, GL_VERTEX_ARRAY);
526 aTCrds->BindFixed (theCtx, GL_TEXTURE_COORD_ARRAY);
527 glBindTexture (GL_TEXTURE_2D, aTexId);
529 glDrawArrays (GL_TRIANGLES, 0, GLsizei(aVerts->GetElemsNb()));
531 glBindTexture (GL_TEXTURE_2D, 0);
532 aTCrds->UnbindFixed (theCtx, GL_TEXTURE_COORD_ARRAY);
533 aVerts->UnbindFixed (theCtx, GL_VERTEX_ARRAY);
536 else if (myVertsArray.Length() == myTextures.Length())
538 glEnableClientState (GL_VERTEX_ARRAY);
539 glEnableClientState (GL_TEXTURE_COORD_ARRAY);
540 for (Standard_Integer anIter = 0; anIter < myTextures.Length(); ++anIter)
542 const GLuint aTexId = myTextures.Value (anIter);
543 const Handle(OpenGl_Vec2Array)& aVerts = myVertsArray.Value (anIter);
544 const Handle(OpenGl_Vec2Array)& aTCrds = myTCrdsArray.Value (anIter);
546 glVertexPointer (2, GL_FLOAT, 0, (GLfloat* )&aVerts->First());
547 glTexCoordPointer (2, GL_FLOAT, 0, (GLfloat* )&aTCrds->First());
548 glBindTexture (GL_TEXTURE_2D, aTexId);
550 glDrawArrays (GL_TRIANGLES, 0, aVerts->Length());
552 glBindTexture (GL_TEXTURE_2D, 0);
554 glDisableClientState (GL_TEXTURE_COORD_ARRAY);
555 glDisableClientState (GL_VERTEX_ARRAY);
559 // =======================================================================
560 // function : FontKey
562 // =======================================================================
563 TCollection_AsciiString OpenGl_Text::FontKey (const OpenGl_AspectText& theAspect,
564 const Standard_Integer theHeight)
566 const Font_FontAspect anAspect = (theAspect.FontAspect() != Font_FA_Undefined) ? theAspect.FontAspect() : Font_FA_Regular;
567 return theAspect.FontName()
568 + TCollection_AsciiString(":") + Standard_Integer(anAspect)
569 + TCollection_AsciiString(":") + theHeight;
572 // =======================================================================
573 // function : FindFont
575 // =======================================================================
576 Handle(OpenGl_Font) OpenGl_Text::FindFont (const Handle(OpenGl_Context)& theCtx,
577 const OpenGl_AspectText& theAspect,
578 const Standard_Integer theHeight,
579 const TCollection_AsciiString theKey)
581 Handle(OpenGl_Font) aFont;
584 return aFont; // invalid parameters
587 if (!theCtx->GetResource (theKey, aFont))
589 Handle(Font_FontMgr) aFontMgr = Font_FontMgr::GetInstance();
590 const Handle(TCollection_HAsciiString) aFontName = new TCollection_HAsciiString (theAspect.FontName());
591 const Font_FontAspect anAspect = (theAspect.FontAspect() != Font_FA_Undefined) ? theAspect.FontAspect() : Font_FA_Regular;
592 Handle(Font_SystemFont) aRequestedFont = aFontMgr->FindFont (aFontName, anAspect, theHeight);
593 if (aRequestedFont.IsNull())
598 Handle(Font_FTFont) aFontFt = new Font_FTFont (NULL);
599 if (!aFontFt->Init (aRequestedFont->FontPath()->ToCString(), theHeight))
604 Handle(OpenGl_Context) aCtx = theCtx;
605 glPushAttrib (GL_TEXTURE_BIT);
606 aFont = new OpenGl_Font (aFontFt, theKey);
607 if (!aFont->Init (aCtx))
610 //return aFont; // out of resources?
612 glPopAttrib(); // texture bit
614 aCtx->ShareResource (theKey, aFont);
619 // =======================================================================
622 // =======================================================================
623 void OpenGl_Text::render (const Handle(OpenGl_PrinterContext)& thePrintCtx,
624 const Handle(OpenGl_Context)& theCtx,
625 const OpenGl_AspectText& theTextAspect,
626 const TEL_COLOUR& theColorText,
627 const TEL_COLOUR& theColorSubs) const
629 if (myString.IsEmpty())
634 const TCollection_AsciiString aFontKey = FontKey (theTextAspect, myParams.Height);
636 && !myFont->ResourceKey().IsEqual (aFontKey))
639 const_cast<OpenGl_Text* > (this)->Release (theCtx);
644 myFont = FindFont (theCtx, theTextAspect, myParams.Height, aFontKey);
651 if (myTextures.IsEmpty())
653 OpenGl_TextFormatter aFormatter;
654 aFormatter.SetupAlignment (myParams.HAlign, myParams.VAlign);
656 aFormatter.Append (theCtx, myString, *myFont.operator->());
659 if (!theCtx->caps->vboDisable && theCtx->core15 != NULL)
661 aFormatter.Result (theCtx, myTextures, myVertsVbo, myTCrdsVbo);
665 aFormatter.Result (theCtx, myTextures, myVertsArray, myTCrdsArray);
667 aFormatter.BndBox (myBndBox);
670 if (myTextures.IsEmpty())
675 myExportHeight = 1.0f;
676 myScaleHeight = 1.0f;
678 glMatrixMode (GL_MODELVIEW);
682 // retrieve active matrices for project/unproject calls
683 glGetDoublev (GL_MODELVIEW_MATRIX, myModelMatrix);
684 glGetDoublev (GL_PROJECTION_MATRIX, myProjMatrix);
685 glGetIntegerv (GL_VIEWPORT, myViewport);
686 gluProject (myPoint.x(), myPoint.y(), myPoint.z(),
687 myModelMatrix, myProjMatrix, myViewport,
688 &myWinX, &myWinY, &myWinZ);
690 // compute scale factor for constant text height
692 gluUnProject (myWinX, myWinY, myWinZ,
693 (GLdouble* )THE_IDENTITY_MATRIX, myProjMatrix, myViewport,
697 const GLdouble h = (GLdouble )myFont->FTFont()->PointSize();
698 gluUnProject (myWinX, myWinY + h - 1.0, myWinZ,
699 (GLdouble* )THE_IDENTITY_MATRIX, myProjMatrix, myViewport,
702 myScaleHeight = (y2 - y1) / h;
703 if (theTextAspect.IsZoomable())
705 myExportHeight = (float )h;
708 myExportHeight = (float )myFont->FTFont()->PointSize() / myExportHeight;
710 // push enabled flags to the stack
711 glPushAttrib (GL_ENABLE_BIT);
712 glDisable (GL_LIGHTING);
716 && theTextAspect.StyleType() != Aspect_TOST_ANNOTATION)
718 glEnable (GL_DEPTH_TEST);
722 glDisable (GL_DEPTH_TEST);
726 GLint aTexEnvParam = GL_REPLACE;
727 glGetTexEnviv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &aTexEnvParam);
728 if (aTexEnvParam != GL_REPLACE)
730 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
732 glAlphaFunc (GL_GEQUAL, 0.285f);
733 glEnable (GL_ALPHA_TEST);
737 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // GL_ONE
739 // activate texture unit
740 glDisable (GL_TEXTURE_1D);
741 glEnable (GL_TEXTURE_2D);
742 if (theCtx->core13 != NULL)
744 theCtx->core13->glActiveTexture (GL_TEXTURE0);
748 switch (theTextAspect.DisplayType())
750 case Aspect_TODT_BLEND:
752 glEnable (GL_COLOR_LOGIC_OP);
756 case Aspect_TODT_SUBTITLE:
758 glColor3fv (theColorSubs.rgb);
759 setupMatrix (thePrintCtx, theCtx, theTextAspect, OpenGl_Vec3 (0.0f, 0.0f, 0.00001f));
761 glBindTexture (GL_TEXTURE_2D, 0);
763 glVertex2f (myBndBox.Left, myBndBox.Top);
764 glVertex2f (myBndBox.Right, myBndBox.Top);
765 glVertex2f (myBndBox.Right, myBndBox.Bottom);
766 glVertex2f (myBndBox.Left, myBndBox.Bottom);
770 case Aspect_TODT_DEKALE:
772 glColor3fv (theColorSubs.rgb);
773 setupMatrix (thePrintCtx, theCtx, theTextAspect, OpenGl_Vec3 (+1.0f, +1.0f, 0.00001f));
774 drawText (thePrintCtx, theCtx, theTextAspect);
775 setupMatrix (thePrintCtx, theCtx, theTextAspect, OpenGl_Vec3 (-1.0f, -1.0f, 0.00001f));
776 drawText (thePrintCtx, theCtx, theTextAspect);
777 setupMatrix (thePrintCtx, theCtx, theTextAspect, OpenGl_Vec3 (-1.0f, +1.0f, 0.00001f));
778 drawText (thePrintCtx, theCtx, theTextAspect);
779 setupMatrix (thePrintCtx, theCtx, theTextAspect, OpenGl_Vec3 (+1.0f, -1.0f, 0.00001f));
780 drawText (thePrintCtx, theCtx, theTextAspect);
783 case Aspect_TODT_DIMENSION:
784 case Aspect_TODT_NORMAL:
791 glColor3fv (theColorText.rgb);
792 setupMatrix (thePrintCtx, theCtx, theTextAspect, OpenGl_Vec3 (0.0f, 0.0f, 0.0f));
793 drawText (thePrintCtx, theCtx, theTextAspect);
795 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, aTexEnvParam);
797 if (theTextAspect.DisplayType() == Aspect_TODT_DIMENSION)
799 setupMatrix (thePrintCtx, theCtx, theTextAspect, OpenGl_Vec3 (0.0f, 0.0f, 0.00001f));
801 glDisable (GL_BLEND);
802 glDisable (GL_TEXTURE_2D);
803 glDisable (GL_ALPHA_TEST);
806 glDisable (GL_DEPTH_TEST);
808 glColorMask (GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
810 glClear (GL_STENCIL_BUFFER_BIT);
811 glEnable (GL_STENCIL_TEST);
812 glStencilFunc (GL_ALWAYS, 1, 0xFF);
813 glStencilOp (GL_KEEP, GL_KEEP, GL_REPLACE);
816 glVertex2f (myBndBox.Left, myBndBox.Top);
817 glVertex2f (myBndBox.Right, myBndBox.Top);
818 glVertex2f (myBndBox.Right, myBndBox.Bottom);
819 glVertex2f (myBndBox.Left, myBndBox.Bottom);
822 glStencilFunc (GL_ALWAYS, 0, 0xFF);
823 // glPopAttrib() will reset state for us
824 //glDisable (GL_STENCIL_TEST);
825 //if (!myIs2d) glEnable (GL_DEPTH_TEST);
827 glColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
830 // revert OpenGL state
831 glPopAttrib(); // enable bit
832 glPopMatrix(); // model view matrix was modified