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>
24 #include <OpenGl_View.hxx>
25 #include <OpenGl_VertexBufferCompat.hxx>
27 #include <Font_FontMgr.hxx>
28 #include <Font_FTFont.hxx>
29 #include <Graphic3d_TransformUtils.hxx>
30 #include <TCollection_HAsciiString.hxx>
38 static const GLdouble THE_IDENTITY_MATRIX[16] =
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.Aspect()->Font().ToCString(), aPsFont);
120 #if !defined(GL_ES_VERSION_2_0)
123 glRasterPos2f (0.0f, 0.0f);
127 glRasterPos3f (0.0f, 0.0f, 0.0f);
131 glBitmap (1, 1, 0, 0, 0, 0, &aZero);
134 // Standard GL2PS's alignment isn't used, because it doesn't work correctly
135 // for all formats, therefore alignment is calculated manually relative
136 // to the bottom-left corner, which corresponds to the GL2PS_TEXT_BL value
137 gl2psTextOpt (theText.ToCString(), aPsFont, (GLshort)theHeight, GL2PS_TEXT_BL, (float )theAspect.Aspect()->GetTextAngle());
141 //! Auxiliary tool for setting polygon offset temporarily.
142 struct BackPolygonOffsetSentry
144 BackPolygonOffsetSentry (const Handle(OpenGl_Context)& theCtx)
146 myOffsetBack (!theCtx.IsNull() ? theCtx->PolygonOffset() : Graphic3d_PolygonOffset())
148 if (!theCtx.IsNull())
150 Graphic3d_PolygonOffset aPolyOffset = myOffsetBack;
151 aPolyOffset.Mode = Aspect_POM_Fill;
152 aPolyOffset.Units += 1.0f;
153 theCtx->SetPolygonOffset (aPolyOffset);
157 ~BackPolygonOffsetSentry()
161 myCtx->SetPolygonOffset (myOffsetBack);
166 BackPolygonOffsetSentry (const BackPolygonOffsetSentry& );
167 BackPolygonOffsetSentry& operator= (const BackPolygonOffsetSentry& );
169 const Handle(OpenGl_Context)& myCtx;
170 const Graphic3d_PolygonOffset myOffsetBack;
173 } // anonymous namespace
175 // =======================================================================
176 // function : OpenGl_Text
178 // =======================================================================
179 OpenGl_Text::OpenGl_Text()
183 myScaleHeight (1.0f),
184 myPoint (0.0f, 0.0f, 0.0f),
187 myHasAnchorPoint (true)
189 myParams.Height = 10;
190 myParams.HAlign = Graphic3d_HTA_LEFT;
191 myParams.VAlign = Graphic3d_VTA_BOTTOM;
194 // =======================================================================
195 // function : OpenGl_Text
197 // =======================================================================
198 OpenGl_Text::OpenGl_Text (const Standard_Utf8Char* theText,
199 const OpenGl_Vec3& thePoint,
200 const OpenGl_TextParam& theParams)
204 myScaleHeight (1.0f),
205 myExportHeight (1.0f),
206 myParams (theParams),
211 myHasAnchorPoint (true)
216 // =======================================================================
217 // function : OpenGl_Text
219 // =======================================================================
220 OpenGl_Text::OpenGl_Text (const Standard_Utf8Char* theText,
221 const gp_Ax2& theOrientation,
222 const OpenGl_TextParam& theParams,
223 const bool theHasOwnAnchor)
228 myExportHeight (1.0),
229 myParams (theParams),
232 myOrientation (theOrientation),
234 myHasAnchorPoint (theHasOwnAnchor)
236 const gp_Pnt& aPoint = theOrientation.Location();
237 myPoint = OpenGl_Vec3 (static_cast<Standard_ShortReal> (aPoint.X()),
238 static_cast<Standard_ShortReal> (aPoint.Y()),
239 static_cast<Standard_ShortReal> (aPoint.Z()));
242 // =======================================================================
243 // function : SetPosition
245 // =======================================================================
246 void OpenGl_Text::SetPosition (const OpenGl_Vec3& thePoint)
251 // =======================================================================
252 // function : SetFontSize
254 // =======================================================================
255 void OpenGl_Text::SetFontSize (const Handle(OpenGl_Context)& theCtx,
256 const Standard_Integer theFontSize)
258 if (myParams.Height != theFontSize)
260 Release (theCtx.operator->());
262 myParams.Height = theFontSize;
265 // =======================================================================
268 // =======================================================================
269 void OpenGl_Text::Init (const Handle(OpenGl_Context)& theCtx,
270 const Standard_Utf8Char* theText,
271 const OpenGl_Vec3& thePoint)
273 releaseVbos (theCtx.operator->());
276 myString.FromUnicode (theText);
279 // =======================================================================
282 // =======================================================================
283 void OpenGl_Text::Init (const Handle(OpenGl_Context)& theCtx,
284 const Standard_Utf8Char* theText,
285 const OpenGl_Vec3& thePoint,
286 const OpenGl_TextParam& theParams)
288 if (myParams.Height != theParams.Height)
290 Release (theCtx.operator->());
294 releaseVbos (theCtx.operator->());
297 myParams = theParams;
299 myString.FromUnicode (theText);
302 // =======================================================================
305 // =======================================================================
306 void OpenGl_Text::Init (const Handle(OpenGl_Context)& theCtx,
307 const TCollection_ExtendedString& theText,
308 const OpenGl_Vec2& thePoint,
309 const OpenGl_TextParam& theParams)
311 if (myParams.Height != theParams.Height)
313 Release (theCtx.operator->());
317 releaseVbos (theCtx.operator->());
320 myParams = theParams;
321 myPoint.xy() = thePoint;
323 myString.FromUnicode (theText.ToExtString());
326 // =======================================================================
327 // function : ~OpenGl_Text
329 // =======================================================================
330 OpenGl_Text::~OpenGl_Text()
335 // =======================================================================
336 // function : releaseVbos
338 // =======================================================================
339 void OpenGl_Text::releaseVbos (OpenGl_Context* theCtx)
341 for (Standard_Integer anIter = 0; anIter < myVertsVbo.Length(); ++anIter)
343 Handle(OpenGl_VertexBuffer)& aVerts = myVertsVbo.ChangeValue (anIter);
344 Handle(OpenGl_VertexBuffer)& aTCrds = myTCrdsVbo.ChangeValue (anIter);
348 theCtx->DelayedRelease (aVerts);
349 theCtx->DelayedRelease (aTCrds);
355 && !myBndVertsVbo.IsNull())
357 theCtx->DelayedRelease (myBndVertsVbo);
363 myBndVertsVbo.Nullify();
366 // =======================================================================
367 // function : Release
369 // =======================================================================
370 void OpenGl_Text::Release (OpenGl_Context* theCtx)
372 releaseVbos (theCtx);
373 if (!myFont.IsNull())
375 const TCollection_AsciiString aKey = myFont->ResourceKey();
379 theCtx->ReleaseResource (aKey, Standard_True);
384 // =======================================================================
385 // function : StringSize
387 // =======================================================================
388 void OpenGl_Text::StringSize (const Handle(OpenGl_Context)& theCtx,
389 const NCollection_String& theText,
390 const OpenGl_AspectText& theTextAspect,
391 const OpenGl_TextParam& theParams,
392 const unsigned int theResolution,
393 Standard_ShortReal& theWidth,
394 Standard_ShortReal& theAscent,
395 Standard_ShortReal& theDescent)
400 const TCollection_AsciiString aFontKey = FontKey (theTextAspect, theParams.Height, theResolution);
401 Handle(OpenGl_Font) aFont = FindFont (theCtx, theTextAspect, theParams.Height, theResolution, aFontKey);
402 if (aFont.IsNull() || !aFont->IsValid())
407 theAscent = aFont->Ascender();
408 theDescent = aFont->Descender();
410 GLfloat aWidth = 0.0f;
411 for (NCollection_Utf8Iter anIter = theText.Iterator(); *anIter != 0;)
413 const Standard_Utf32Char aCharThis = *anIter;
414 const Standard_Utf32Char aCharNext = *++anIter;
416 if (aCharThis == '\x0D' // CR (carriage return)
417 || aCharThis == '\a' // BEL (alarm)
418 || aCharThis == '\f' // FF (form feed) NP (new page)
419 || aCharThis == '\b' // BS (backspace)
420 || aCharThis == '\v') // VT (vertical tab)
422 continue; // skip unsupported carriage control codes
424 else if (aCharThis == '\x0A') // LF (line feed, new line)
426 theWidth = Max (theWidth, aWidth);
430 else if (aCharThis == ' ')
432 aWidth += aFont->FTFont()->AdvanceX (aCharThis, aCharNext);
435 else if (aCharThis == '\t')
437 aWidth += aFont->FTFont()->AdvanceX (' ', aCharNext) * 8.0f;
441 aWidth += aFont->FTFont()->AdvanceX (aCharThis, aCharNext);
443 theWidth = Max (theWidth, aWidth);
445 Handle(OpenGl_Context) aCtx = theCtx;
447 aCtx->ReleaseResource (aFontKey, Standard_True);
450 // =======================================================================
453 // =======================================================================
454 void OpenGl_Text::Render (const Handle(OpenGl_Workspace)& theWorkspace) const
456 theWorkspace->SetAspectFace (&theWorkspace->FontFaceAspect());
457 theWorkspace->ApplyAspectFace();
458 const OpenGl_AspectText* aTextAspect = theWorkspace->ApplyAspectText();
459 const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
460 const Handle(OpenGl_TextureSet) aPrevTexture = aCtx->BindTextures (Handle(OpenGl_TextureSet)());
462 // Bind custom shader program or generate default version
463 aCtx->ShaderManager()->BindFontProgram (aTextAspect->ShaderProgramRes (aCtx));
465 myOrientationMatrix = theWorkspace->View()->Camera()->OrientationMatrix();
466 myProjMatrix.Convert (aCtx->ProjectionState.Current());
468 // use highlight color or colors from aspect
471 theWorkspace->TextColor(),
472 theWorkspace->TextSubtitleColor(),
476 if (!aPrevTexture.IsNull())
478 aCtx->BindTextures (aPrevTexture);
481 // restore Z buffer settings
482 if (theWorkspace->UseZBuffer())
484 glEnable (GL_DEPTH_TEST);
488 // =======================================================================
491 // =======================================================================
492 void OpenGl_Text::Render (const Handle(OpenGl_Context)& theCtx,
493 const OpenGl_AspectText& theTextAspect,
494 const unsigned int theResolution) const
496 render (theCtx, theTextAspect,
497 theTextAspect.Aspect()->ColorRGBA(),
498 theTextAspect.Aspect()->ColorSubTitleRGBA(),
502 // =======================================================================
503 // function : setupMatrix
505 // =======================================================================
506 void OpenGl_Text::setupMatrix (const Handle(OpenGl_Context)& theCtx,
507 const OpenGl_AspectText& theTextAspect,
508 const OpenGl_Vec3 theDVec) const
510 OpenGl_Mat4d aModViewMat;
511 OpenGl_Mat4d aProjectMat;
512 if (myHasPlane && myHasAnchorPoint)
514 aProjectMat = myProjMatrix * myOrientationMatrix;
518 aProjectMat = myProjMatrix;
523 Graphic3d_TransformUtils::Translate<GLdouble> (aModViewMat, myPoint.x() + theDVec.x(), myPoint.y() + theDVec.y(), 0.f);
524 Graphic3d_TransformUtils::Scale<GLdouble> (aModViewMat, 1.f, -1.f, 1.f);
525 Graphic3d_TransformUtils::Rotate<GLdouble> (aModViewMat, theTextAspect.Aspect()->GetTextAngle(), 0.f, 0.f, 1.f);
529 // align coordinates to the nearest integer
530 // to avoid extra interpolation issues
531 GLdouble anObjX, anObjY, anObjZ;
532 Graphic3d_TransformUtils::UnProject<Standard_Real> (std::floor (myWinX + theDVec.x()),
533 std::floor (myWinY + theDVec.y()),
534 myWinZ + theDVec.z(),
535 OpenGl_Mat4d::Map (THE_IDENTITY_MATRIX),
536 OpenGl_Mat4d::Map (aProjectMat),
544 const gp_Dir& aVectorDir = myOrientation.XDirection();
545 const gp_Dir& aVectorUp = myOrientation.Direction();
546 const gp_Dir& aVectorRight = myOrientation.YDirection();
548 aModViewMat.SetColumn (2, OpenGl_Vec3d (aVectorUp.X(), aVectorUp.Y(), aVectorUp.Z()));
549 aModViewMat.SetColumn (1, OpenGl_Vec3d (aVectorRight.X(), aVectorRight.Y(), aVectorRight.Z()));
550 aModViewMat.SetColumn (0, OpenGl_Vec3d (aVectorDir.X(), aVectorDir.Y(), aVectorDir.Z()));
552 if (!myHasAnchorPoint)
554 OpenGl_Mat4d aPosMat;
555 aPosMat.SetColumn (3, OpenGl_Vec3d (myPoint.x(), myPoint.y(), myPoint.z()));
556 aPosMat *= aModViewMat;
557 aModViewMat.SetColumn (3, aPosMat.GetColumn (3));
561 aModViewMat.SetColumn (3, OpenGl_Vec3d (anObjX, anObjY, anObjZ));
566 Graphic3d_TransformUtils::Translate<GLdouble> (aModViewMat, anObjX, anObjY, anObjZ);
567 Graphic3d_TransformUtils::Rotate<GLdouble> (aModViewMat, theTextAspect.Aspect()->GetTextAngle(), 0.0, 0.0, 1.0);
570 if (!theTextAspect.Aspect()->GetTextZoomable())
572 Graphic3d_TransformUtils::Scale<GLdouble> (aModViewMat, myScaleHeight, myScaleHeight, myScaleHeight);
574 else if (theCtx->HasRenderScale())
576 Graphic3d_TransformUtils::Scale<GLdouble> (aModViewMat, theCtx->RenderScaleInv(), theCtx->RenderScaleInv(), theCtx->RenderScaleInv());
580 if (myHasPlane && !myHasAnchorPoint)
582 OpenGl_Mat4d aCurrentWorldViewMat;
583 aCurrentWorldViewMat.Convert (theCtx->WorldViewState.Current());
584 theCtx->WorldViewState.SetCurrent<Standard_Real> (aCurrentWorldViewMat * aModViewMat);
588 theCtx->WorldViewState.SetCurrent<Standard_Real> (aModViewMat);
590 theCtx->ApplyWorldViewMatrix();
594 theCtx->ProjectionState.SetCurrent<Standard_Real> (aProjectMat);
595 theCtx->ApplyProjectionMatrix();
598 // Upload updated state to shader program
599 theCtx->ShaderManager()->PushState (theCtx->ActiveProgram());
602 // =======================================================================
603 // function : drawText
605 // =======================================================================
606 void OpenGl_Text::drawText (const Handle(OpenGl_Context)& theCtx,
607 const OpenGl_AspectText& theTextAspect) const
610 if (theCtx->IsFeedback())
612 // position of the text and alignment is calculated by transformation matrix
613 exportText (myString, myIs2d, theTextAspect, (Standard_Integer )myExportHeight);
617 (void )theTextAspect;
620 if (myVertsVbo.Length() != myTextures.Length()
621 || myTextures.IsEmpty())
626 for (Standard_Integer anIter = 0; anIter < myTextures.Length(); ++anIter)
628 const GLuint aTexId = myTextures.Value (anIter);
629 glBindTexture (GL_TEXTURE_2D, aTexId);
631 const Handle(OpenGl_VertexBuffer)& aVerts = myVertsVbo.Value (anIter);
632 const Handle(OpenGl_VertexBuffer)& aTCrds = myTCrdsVbo.Value (anIter);
633 aVerts->BindAttribute (theCtx, Graphic3d_TOA_POS);
634 aTCrds->BindAttribute (theCtx, Graphic3d_TOA_UV);
636 glDrawArrays (GL_TRIANGLES, 0, GLsizei(aVerts->GetElemsNb()));
638 aTCrds->UnbindAttribute (theCtx, Graphic3d_TOA_UV);
639 aVerts->UnbindAttribute (theCtx, Graphic3d_TOA_POS);
641 glBindTexture (GL_TEXTURE_2D, 0);
644 // =======================================================================
645 // function : FontKey
647 // =======================================================================
648 TCollection_AsciiString OpenGl_Text::FontKey (const OpenGl_AspectText& theAspect,
649 const Standard_Integer theHeight,
650 const unsigned int theResolution)
652 const Font_FontAspect anAspect = theAspect.Aspect()->GetTextFontAspect() != Font_FA_Undefined
653 ? theAspect.Aspect()->GetTextFontAspect()
655 return theAspect.Aspect()->Font()
656 + TCollection_AsciiString(":") + Standard_Integer(anAspect)
657 + TCollection_AsciiString(":") + Standard_Integer(theResolution)
658 + TCollection_AsciiString(":") + theHeight;
661 // =======================================================================
662 // function : FindFont
664 // =======================================================================
665 Handle(OpenGl_Font) OpenGl_Text::FindFont (const Handle(OpenGl_Context)& theCtx,
666 const OpenGl_AspectText& theAspect,
667 const Standard_Integer theHeight,
668 const unsigned int theResolution,
669 const TCollection_AsciiString theKey)
671 Handle(OpenGl_Font) aFont;
674 return aFont; // invalid parameters
677 if (!theCtx->GetResource (theKey, aFont))
679 Handle(Font_FontMgr) aFontMgr = Font_FontMgr::GetInstance();
680 const Handle(TCollection_HAsciiString) aFontName = new TCollection_HAsciiString (theAspect.Aspect()->Font());
681 const Font_FontAspect anAspect = theAspect.Aspect()->GetTextFontAspect() != Font_FA_Undefined
682 ? theAspect.Aspect()->GetTextFontAspect()
684 Handle(Font_SystemFont) aRequestedFont = aFontMgr->FindFont (aFontName, anAspect, theHeight);
685 Handle(Font_FTFont) aFontFt;
686 if (!aRequestedFont.IsNull())
688 aFontFt = new Font_FTFont (Handle(Font_FTLibrary)());
690 if (aFontFt->Init (aRequestedFont->FontPath()->ToCString(), theHeight, theResolution))
692 aFont = new OpenGl_Font (aFontFt, theKey);
693 if (!aFont->Init (theCtx))
695 TCollection_ExtendedString aMsg;
697 aMsg += theAspect.Aspect()->Font();
698 aMsg += "' - initialization of GL resources has failed!";
699 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, aMsg);
701 aFont->Release (theCtx.operator->());
702 aFont = new OpenGl_Font (aFontFt, theKey);
707 TCollection_ExtendedString aMsg;
709 aMsg += theAspect.Aspect()->Font();
710 aMsg += "' is broken or has incompatible format! File path: ";
711 aMsg += aRequestedFont->FontPath()->ToCString();
712 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, aMsg);
714 aFont = new OpenGl_Font (aFontFt, theKey);
719 TCollection_ExtendedString aMsg;
721 aMsg += theAspect.Aspect()->Font();
722 aMsg += "' is not found in the system!";
723 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, aMsg);
724 aFont = new OpenGl_Font (aFontFt, theKey);
727 theCtx->ShareResource (theKey, aFont);
732 // =======================================================================
733 // function : drawRect
735 // =======================================================================
736 void OpenGl_Text::drawRect (const Handle(OpenGl_Context)& theCtx,
737 const OpenGl_AspectText& theTextAspect,
738 const OpenGl_Vec4& theColorSubs) const
740 Handle(OpenGl_ShaderProgram) aPrevProgram = theCtx->ActiveProgram();
741 if (myBndVertsVbo.IsNull())
743 OpenGl_Vec2 aQuad[4] =
745 OpenGl_Vec2(myBndBox.Right, myBndBox.Bottom),
746 OpenGl_Vec2(myBndBox.Right, myBndBox.Top),
747 OpenGl_Vec2(myBndBox.Left, myBndBox.Bottom),
748 OpenGl_Vec2(myBndBox.Left, myBndBox.Top)
750 if (theCtx->ToUseVbo())
752 myBndVertsVbo = new OpenGl_VertexBuffer();
756 myBndVertsVbo = new OpenGl_VertexBufferCompat();
758 myBndVertsVbo->Init (theCtx, 2, 4, aQuad[0].GetData());
761 // bind unlit program
762 theCtx->ShaderManager()->BindFaceProgram (Handle(OpenGl_TextureSet)(), Graphic3d_TOSM_UNLIT,
763 Graphic3d_AlphaMode_Opaque, Standard_False, Standard_False,
764 Handle(OpenGl_ShaderProgram)());
766 #if !defined(GL_ES_VERSION_2_0)
767 if (theCtx->core11 != NULL
768 && theCtx->ActiveProgram().IsNull())
770 glBindTexture (GL_TEXTURE_2D, 0);
773 theCtx->SetColor4fv (theColorSubs);
774 setupMatrix (theCtx, theTextAspect, OpenGl_Vec3 (0.0f, 0.0f, 0.0f));
775 myBndVertsVbo->BindAttribute (theCtx, Graphic3d_TOA_POS);
777 theCtx->core20fwd->glDrawArrays (GL_TRIANGLE_STRIP, 0, 4);
779 myBndVertsVbo->UnbindAttribute (theCtx, Graphic3d_TOA_POS);
780 theCtx->BindProgram (aPrevProgram);
783 // =======================================================================
786 // =======================================================================
787 void OpenGl_Text::render (const Handle(OpenGl_Context)& theCtx,
788 const OpenGl_AspectText& theTextAspect,
789 const OpenGl_Vec4& theColorText,
790 const OpenGl_Vec4& theColorSubs,
791 const unsigned int theResolution) const
793 if (myString.IsEmpty())
798 // Note that using difference resolution in different Views in same Viewer
799 // will lead to performance regression (for example, text will be recreated every time).
800 const TCollection_AsciiString aFontKey = FontKey (theTextAspect, myParams.Height, theResolution);
802 && !myFont->ResourceKey().IsEqual (aFontKey))
805 const_cast<OpenGl_Text* > (this)->Release (theCtx.operator->());
810 myFont = FindFont (theCtx, theTextAspect, myParams.Height, theResolution, aFontKey);
812 if (!myFont->WasInitialized())
817 if (myTextures.IsEmpty())
819 Font_TextFormatter aFormatter;
820 aFormatter.SetupAlignment (myParams.HAlign, myParams.VAlign);
823 aFormatter.Append (myString, *myFont->FTFont().operator->());
826 OpenGl_TextBuilder aBuilder;
827 aBuilder.Perform (aFormatter,
829 *myFont.operator->(),
834 aFormatter.BndBox (myBndBox);
835 if (!myBndVertsVbo.IsNull())
837 myBndVertsVbo->Release (theCtx.get());
838 myBndVertsVbo.Nullify();
842 if (myTextures.IsEmpty())
847 myExportHeight = 1.0f;
848 myScaleHeight = 1.0f;
850 theCtx->WorldViewState.Push();
851 myModelMatrix.Convert (theCtx->WorldViewState.Current() * theCtx->ModelWorldState.Current());
853 const GLdouble aPointSize = (GLdouble )myFont->FTFont()->PointSize();
856 Graphic3d_TransformUtils::Project<Standard_Real> (myPoint.x(), myPoint.y(), myPoint.z(),
857 myModelMatrix, myProjMatrix, theCtx->Viewport(),
858 myWinX, myWinY, myWinZ);
860 // compute scale factor for constant text height
861 if (theTextAspect.Aspect()->GetTextZoomable())
863 myExportHeight = aPointSize;
867 Graphic3d_Vec3d aPnt1, aPnt2;
868 Graphic3d_TransformUtils::UnProject<Standard_Real> (myWinX, myWinY, myWinZ,
869 OpenGl_Mat4d::Map (THE_IDENTITY_MATRIX), myProjMatrix, theCtx->Viewport(),
870 aPnt1.x(), aPnt1.y(), aPnt1.z());
871 Graphic3d_TransformUtils::UnProject<Standard_Real> (myWinX, myWinY + aPointSize, myWinZ,
872 OpenGl_Mat4d::Map (THE_IDENTITY_MATRIX), myProjMatrix, theCtx->Viewport(),
873 aPnt2.x(), aPnt2.y(), aPnt2.z());
874 myScaleHeight = (aPnt2.y() - aPnt1.y()) / aPointSize;
877 myExportHeight = aPointSize / myExportHeight;
879 #if !defined(GL_ES_VERSION_2_0)
880 if (theCtx->core11 != NULL
881 && theCtx->caps->ffpEnable)
883 glDisable (GL_LIGHTING);
886 const Standard_Integer aPrevPolygonMode = theCtx->SetPolygonMode (GL_FILL);
887 const bool aPrevHatchingMode = theCtx->SetPolygonHatchEnabled (false);
891 const bool hasDepthTest = !myIs2d
892 && theTextAspect.Aspect()->Style() != Aspect_TOST_ANNOTATION;
895 glDisable (GL_DEPTH_TEST);
898 if (theCtx->core15fwd != NULL)
900 theCtx->core15fwd->glActiveTexture (GL_TEXTURE0);
902 #if !defined(GL_ES_VERSION_2_0)
903 // activate texture unit
904 GLint aTexEnvParam = GL_REPLACE;
905 if (theCtx->core11 != NULL)
907 glDisable (GL_TEXTURE_1D);
908 glEnable (GL_TEXTURE_2D);
909 glGetTexEnviv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &aTexEnvParam);
910 if (aTexEnvParam != GL_REPLACE)
912 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
919 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
920 const bool anAlphaToCoverageOld = theCtx->SetSampleAlphaToCoverage (false);
923 switch (theTextAspect.Aspect()->DisplayType())
925 case Aspect_TODT_BLEND:
927 #if !defined(GL_ES_VERSION_2_0)
928 glEnable (GL_COLOR_LOGIC_OP);
933 case Aspect_TODT_SUBTITLE:
935 BackPolygonOffsetSentry aPolygonOffsetTmp (hasDepthTest ? theCtx : Handle(OpenGl_Context)());
936 drawRect (theCtx, theTextAspect, theColorSubs);
939 case Aspect_TODT_DEKALE:
941 BackPolygonOffsetSentry aPolygonOffsetTmp (hasDepthTest ? theCtx : Handle(OpenGl_Context)());
942 theCtx->SetColor4fv (theColorSubs);
943 setupMatrix (theCtx, theTextAspect, OpenGl_Vec3 (+1.0f, +1.0f, 0.0f));
944 drawText (theCtx, theTextAspect);
945 setupMatrix (theCtx, theTextAspect, OpenGl_Vec3 (-1.0f, -1.0f, 0.0f));
946 drawText (theCtx, theTextAspect);
947 setupMatrix (theCtx, theTextAspect, OpenGl_Vec3 (-1.0f, +1.0f, 0.0f));
948 drawText (theCtx, theTextAspect);
949 setupMatrix (theCtx, theTextAspect, OpenGl_Vec3 (+1.0f, -1.0f, 0.0f));
950 drawText (theCtx, theTextAspect);
953 case Aspect_TODT_SHADOW:
955 BackPolygonOffsetSentry aPolygonOffsetTmp (hasDepthTest ? theCtx : Handle(OpenGl_Context)());
956 theCtx->SetColor4fv (theColorSubs);
957 setupMatrix (theCtx, theTextAspect, OpenGl_Vec3 (+1.0f, -1.0f, 0.0f));
958 drawText (theCtx, theTextAspect);
961 case Aspect_TODT_DIMENSION:
962 case Aspect_TODT_NORMAL:
969 theCtx->SetColor4fv (theColorText);
970 setupMatrix (theCtx, theTextAspect, OpenGl_Vec3 (0.0f, 0.0f, 0.0f));
971 drawText (theCtx, theTextAspect);
975 theCtx->ProjectionState.SetCurrent<Standard_Real> (myProjMatrix);
976 theCtx->ApplyProjectionMatrix();
979 #if !defined(GL_ES_VERSION_2_0)
980 if (theCtx->core11 != NULL)
982 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, aTexEnvParam);
986 if (theTextAspect.Aspect()->DisplayType() == Aspect_TODT_DIMENSION)
988 glDisable (GL_BLEND);
991 glDisable (GL_DEPTH_TEST);
993 #if !defined(GL_ES_VERSION_2_0)
994 if (theCtx->core11 != NULL)
996 glDisable (GL_TEXTURE_2D);
999 const bool aColorMaskBack = theCtx->SetColorMask (false);
1001 glClear (GL_STENCIL_BUFFER_BIT);
1002 glEnable (GL_STENCIL_TEST);
1003 glStencilFunc (GL_ALWAYS, 1, 0xFF);
1004 glStencilOp (GL_KEEP, GL_KEEP, GL_REPLACE);
1006 drawRect (theCtx, theTextAspect, OpenGl_Vec4 (1.0f, 1.0f, 1.0f, 1.0f));
1008 glStencilFunc (GL_ALWAYS, 0, 0xFF);
1010 theCtx->SetColorMask (aColorMaskBack);
1013 // reset OpenGL state
1014 glDisable (GL_BLEND);
1015 glDisable (GL_STENCIL_TEST);
1016 #if !defined(GL_ES_VERSION_2_0)
1017 glDisable (GL_COLOR_LOGIC_OP);
1019 theCtx->SetPolygonMode (aPrevPolygonMode);
1020 theCtx->SetPolygonHatchEnabled (aPrevHatchingMode);
1022 theCtx->SetSampleAlphaToCoverage (anAlphaToCoverageOld);
1024 // model view matrix was modified
1025 theCtx->WorldViewState.Pop();
1026 theCtx->ApplyModelViewMatrix();