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 Standard_Utf8Char* theText,
162 const OpenGl_Vec3& thePoint,
163 const OpenGl_TextParam& theParams)
167 myScaleHeight (1.0f),
168 myExportHeight (1.0f),
169 myParams (theParams),
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 glScalef (1.0f, -1.0f, 1.0f);
460 glRotatef (theTextAspect.Angle(), 0.0, 0.0, 1.0);
464 // align coordinates to the nearest integer
465 // to avoid extra interpolation issues
466 GLdouble anObjX, anObjY, anObjZ;
467 gluUnProject (std::floor (myWinX + (GLdouble )theDVec.x()),
468 std::floor (myWinY + (GLdouble )theDVec.y()),
469 myWinZ + (GLdouble )theDVec.z(),
470 (GLdouble* )THE_IDENTITY_MATRIX, myProjMatrix, myViewport,
471 &anObjX, &anObjY, &anObjZ);
474 glTranslated (anObjX, anObjY, anObjZ);
475 glRotated (theTextAspect.Angle(), 0.0, 0.0, 1.0);
476 if (!theTextAspect.IsZoomable())
479 // if the context has assigned printer context, use it's parameters
480 if (!thePrintCtx.IsNull())
482 // get printing scaling in x and y dimensions
483 GLfloat aTextScalex = 1.0f, aTextScaley = 1.0f;
484 thePrintCtx->GetScale (aTextScalex, aTextScaley);
486 // text should be scaled in all directions with same
487 // factor to save its proportions, so use height (y) scaling
488 // as it is better for keeping text/3d graphics proportions
489 glScalef (aTextScaley, aTextScaley, aTextScaley);
492 glScaled (myScaleHeight, myScaleHeight, myScaleHeight);
497 // =======================================================================
498 // function : drawText
500 // =======================================================================
502 void OpenGl_Text::drawText (const Handle(OpenGl_PrinterContext)& ,
503 const Handle(OpenGl_Context)& theCtx,
505 const OpenGl_AspectText& theTextAspect) const
507 const OpenGl_AspectText& ) const
511 if (theCtx->IsFeedback())
513 // position of the text and alignment is calculated by transformation matrix
514 exportText (myString, myIs2d, theTextAspect, (Standard_Integer )myExportHeight);
519 if (myVertsVbo.Length() == myTextures.Length())
521 for (Standard_Integer anIter = 0; anIter < myTextures.Length(); ++anIter)
523 const GLuint aTexId = myTextures.Value (anIter);
524 const Handle(OpenGl_VertexBuffer)& aVerts = myVertsVbo.Value (anIter);
525 const Handle(OpenGl_VertexBuffer)& aTCrds = myTCrdsVbo.Value (anIter);
526 aVerts->BindFixed (theCtx, GL_VERTEX_ARRAY);
527 aTCrds->BindFixed (theCtx, GL_TEXTURE_COORD_ARRAY);
528 glBindTexture (GL_TEXTURE_2D, aTexId);
530 glDrawArrays (GL_TRIANGLES, 0, GLsizei(aVerts->GetElemsNb()));
532 glBindTexture (GL_TEXTURE_2D, 0);
533 aTCrds->UnbindFixed (theCtx, GL_TEXTURE_COORD_ARRAY);
534 aVerts->UnbindFixed (theCtx, GL_VERTEX_ARRAY);
537 else if (myVertsArray.Length() == myTextures.Length())
539 glEnableClientState (GL_VERTEX_ARRAY);
540 glEnableClientState (GL_TEXTURE_COORD_ARRAY);
541 for (Standard_Integer anIter = 0; anIter < myTextures.Length(); ++anIter)
543 const GLuint aTexId = myTextures.Value (anIter);
544 const Handle(OpenGl_Vec2Array)& aVerts = myVertsArray.Value (anIter);
545 const Handle(OpenGl_Vec2Array)& aTCrds = myTCrdsArray.Value (anIter);
547 glVertexPointer (2, GL_FLOAT, 0, (GLfloat* )&aVerts->First());
548 glTexCoordPointer (2, GL_FLOAT, 0, (GLfloat* )&aTCrds->First());
549 glBindTexture (GL_TEXTURE_2D, aTexId);
551 glDrawArrays (GL_TRIANGLES, 0, aVerts->Length());
553 glBindTexture (GL_TEXTURE_2D, 0);
555 glDisableClientState (GL_TEXTURE_COORD_ARRAY);
556 glDisableClientState (GL_VERTEX_ARRAY);
560 // =======================================================================
561 // function : FontKey
563 // =======================================================================
564 TCollection_AsciiString OpenGl_Text::FontKey (const OpenGl_AspectText& theAspect,
565 const Standard_Integer theHeight)
567 const Font_FontAspect anAspect = (theAspect.FontAspect() != Font_FA_Undefined) ? theAspect.FontAspect() : Font_FA_Regular;
568 return theAspect.FontName()
569 + TCollection_AsciiString(":") + Standard_Integer(anAspect)
570 + TCollection_AsciiString(":") + theHeight;
573 // =======================================================================
574 // function : FindFont
576 // =======================================================================
577 Handle(OpenGl_Font) OpenGl_Text::FindFont (const Handle(OpenGl_Context)& theCtx,
578 const OpenGl_AspectText& theAspect,
579 const Standard_Integer theHeight,
580 const TCollection_AsciiString theKey)
582 Handle(OpenGl_Font) aFont;
585 return aFont; // invalid parameters
588 if (!theCtx->GetResource (theKey, aFont))
590 Handle(Font_FontMgr) aFontMgr = Font_FontMgr::GetInstance();
591 const Handle(TCollection_HAsciiString) aFontName = new TCollection_HAsciiString (theAspect.FontName());
592 const Font_FontAspect anAspect = (theAspect.FontAspect() != Font_FA_Undefined) ? theAspect.FontAspect() : Font_FA_Regular;
593 Handle(Font_SystemFont) aRequestedFont = aFontMgr->FindFont (aFontName, anAspect, theHeight);
594 if (aRequestedFont.IsNull())
599 Handle(Font_FTFont) aFontFt = new Font_FTFont (NULL);
600 if (!aFontFt->Init (aRequestedFont->FontPath()->ToCString(), theHeight))
605 Handle(OpenGl_Context) aCtx = theCtx;
606 glPushAttrib (GL_TEXTURE_BIT);
607 aFont = new OpenGl_Font (aFontFt, theKey);
608 if (!aFont->Init (aCtx))
611 //return aFont; // out of resources?
613 glPopAttrib(); // texture bit
615 aCtx->ShareResource (theKey, aFont);
620 // =======================================================================
623 // =======================================================================
624 void OpenGl_Text::render (const Handle(OpenGl_PrinterContext)& thePrintCtx,
625 const Handle(OpenGl_Context)& theCtx,
626 const OpenGl_AspectText& theTextAspect,
627 const TEL_COLOUR& theColorText,
628 const TEL_COLOUR& theColorSubs) const
630 if (myString.IsEmpty())
635 const TCollection_AsciiString aFontKey = FontKey (theTextAspect, myParams.Height);
637 && !myFont->ResourceKey().IsEqual (aFontKey))
640 const_cast<OpenGl_Text* > (this)->Release (theCtx);
645 myFont = FindFont (theCtx, theTextAspect, myParams.Height, aFontKey);
652 if (myTextures.IsEmpty())
654 OpenGl_TextFormatter aFormatter;
655 aFormatter.SetupAlignment (myParams.HAlign, myParams.VAlign);
657 aFormatter.Append (theCtx, myString, *myFont.operator->());
660 if (!theCtx->caps->vboDisable && theCtx->core15 != NULL)
662 aFormatter.Result (theCtx, myTextures, myVertsVbo, myTCrdsVbo);
666 aFormatter.Result (theCtx, myTextures, myVertsArray, myTCrdsArray);
668 aFormatter.BndBox (myBndBox);
671 if (myTextures.IsEmpty())
676 myExportHeight = 1.0f;
677 myScaleHeight = 1.0f;
679 glMatrixMode (GL_MODELVIEW);
683 // retrieve active matrices for project/unproject calls
684 glGetDoublev (GL_MODELVIEW_MATRIX, myModelMatrix);
685 glGetDoublev (GL_PROJECTION_MATRIX, myProjMatrix);
686 glGetIntegerv (GL_VIEWPORT, myViewport);
687 gluProject (myPoint.x(), myPoint.y(), myPoint.z(),
688 myModelMatrix, myProjMatrix, myViewport,
689 &myWinX, &myWinY, &myWinZ);
691 // compute scale factor for constant text height
693 gluUnProject (myWinX, myWinY, myWinZ,
694 (GLdouble* )THE_IDENTITY_MATRIX, myProjMatrix, myViewport,
698 const GLdouble h = (GLdouble )myFont->FTFont()->PointSize();
699 gluUnProject (myWinX, myWinY + h - 1.0, myWinZ,
700 (GLdouble* )THE_IDENTITY_MATRIX, myProjMatrix, myViewport,
703 myScaleHeight = (y2 - y1) / h;
704 if (theTextAspect.IsZoomable())
706 myExportHeight = (float )h;
709 myExportHeight = (float )myFont->FTFont()->PointSize() / myExportHeight;
711 // push enabled flags to the stack
712 glPushAttrib (GL_ENABLE_BIT);
713 glDisable (GL_LIGHTING);
717 && theTextAspect.StyleType() != Aspect_TOST_ANNOTATION)
719 glEnable (GL_DEPTH_TEST);
723 glDisable (GL_DEPTH_TEST);
727 GLint aTexEnvParam = GL_REPLACE;
728 glGetTexEnviv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &aTexEnvParam);
729 if (aTexEnvParam != GL_REPLACE)
731 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
733 glAlphaFunc (GL_GEQUAL, 0.285f);
734 glEnable (GL_ALPHA_TEST);
738 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // GL_ONE
740 // activate texture unit
741 glDisable (GL_TEXTURE_1D);
742 glEnable (GL_TEXTURE_2D);
743 if (theCtx->core15fwd != NULL)
745 theCtx->core15fwd->glActiveTexture (GL_TEXTURE0);
749 switch (theTextAspect.DisplayType())
751 case Aspect_TODT_BLEND:
753 glEnable (GL_COLOR_LOGIC_OP);
757 case Aspect_TODT_SUBTITLE:
759 glColor3fv (theColorSubs.rgb);
760 setupMatrix (thePrintCtx, theCtx, theTextAspect, OpenGl_Vec3 (0.0f, 0.0f, 0.00001f));
762 glBindTexture (GL_TEXTURE_2D, 0);
764 glVertex2f (myBndBox.Left, myBndBox.Top);
765 glVertex2f (myBndBox.Right, myBndBox.Top);
766 glVertex2f (myBndBox.Right, myBndBox.Bottom);
767 glVertex2f (myBndBox.Left, myBndBox.Bottom);
771 case Aspect_TODT_DEKALE:
773 glColor3fv (theColorSubs.rgb);
774 setupMatrix (thePrintCtx, theCtx, theTextAspect, OpenGl_Vec3 (+1.0f, +1.0f, 0.00001f));
775 drawText (thePrintCtx, theCtx, theTextAspect);
776 setupMatrix (thePrintCtx, theCtx, theTextAspect, OpenGl_Vec3 (-1.0f, -1.0f, 0.00001f));
777 drawText (thePrintCtx, theCtx, theTextAspect);
778 setupMatrix (thePrintCtx, theCtx, theTextAspect, OpenGl_Vec3 (-1.0f, +1.0f, 0.00001f));
779 drawText (thePrintCtx, theCtx, theTextAspect);
780 setupMatrix (thePrintCtx, theCtx, theTextAspect, OpenGl_Vec3 (+1.0f, -1.0f, 0.00001f));
781 drawText (thePrintCtx, theCtx, theTextAspect);
784 case Aspect_TODT_DIMENSION:
785 case Aspect_TODT_NORMAL:
792 glColor3fv (theColorText.rgb);
793 setupMatrix (thePrintCtx, theCtx, theTextAspect, OpenGl_Vec3 (0.0f, 0.0f, 0.0f));
794 drawText (thePrintCtx, theCtx, theTextAspect);
796 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, aTexEnvParam);
798 if (theTextAspect.DisplayType() == Aspect_TODT_DIMENSION)
800 setupMatrix (thePrintCtx, theCtx, theTextAspect, OpenGl_Vec3 (0.0f, 0.0f, 0.00001f));
802 glDisable (GL_BLEND);
803 glDisable (GL_TEXTURE_2D);
804 glDisable (GL_ALPHA_TEST);
807 glDisable (GL_DEPTH_TEST);
809 glColorMask (GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
811 glClear (GL_STENCIL_BUFFER_BIT);
812 glEnable (GL_STENCIL_TEST);
813 glStencilFunc (GL_ALWAYS, 1, 0xFF);
814 glStencilOp (GL_KEEP, GL_KEEP, GL_REPLACE);
817 glVertex2f (myBndBox.Left, myBndBox.Top);
818 glVertex2f (myBndBox.Right, myBndBox.Top);
819 glVertex2f (myBndBox.Right, myBndBox.Bottom);
820 glVertex2f (myBndBox.Left, myBndBox.Bottom);
823 glStencilFunc (GL_ALWAYS, 0, 0xFF);
824 // glPopAttrib() will reset state for us
825 //glDisable (GL_STENCIL_TEST);
826 //if (!myIs2d) glEnable (GL_DEPTH_TEST);
828 glColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
831 // revert OpenGL state
832 glPopAttrib(); // enable bit
833 glPopMatrix(); // model view matrix was modified