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_Aspects.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 <Font_TextFormatter.hxx>
30 #include <Graphic3d_TransformUtils.hxx>
31 #include <TCollection_HAsciiString.hxx>
35 static const OpenGl_Mat4d THE_IDENTITY_MATRIX;
37 static const TCollection_AsciiString THE_DEFAULT_FONT (Font_NOF_ASCII_MONO);
39 //! Auxiliary tool for setting polygon offset temporarily.
40 struct BackPolygonOffsetSentry
42 BackPolygonOffsetSentry (OpenGl_Context* theCtx)
47 myOffsetBack = theCtx->PolygonOffset();
48 Graphic3d_PolygonOffset aPolyOffset = myOffsetBack;
49 aPolyOffset.Mode = Aspect_POM_Fill;
50 aPolyOffset.Units += 1.0f;
51 theCtx->SetPolygonOffset (aPolyOffset);
55 ~BackPolygonOffsetSentry()
59 myCtx->SetPolygonOffset (myOffsetBack);
64 BackPolygonOffsetSentry (const BackPolygonOffsetSentry& );
65 BackPolygonOffsetSentry& operator= (const BackPolygonOffsetSentry& );
67 OpenGl_Context* myCtx;
68 Graphic3d_PolygonOffset myOffsetBack;
71 } // anonymous namespace
73 // =======================================================================
74 // function : OpenGl_Text
76 // =======================================================================
77 OpenGl_Text::OpenGl_Text()
78 : myScaleHeight (1.0f),
79 myIs2d (Standard_False)
81 myText = new Graphic3d_Text (10.);
85 // =======================================================================
86 // function : OpenGl_Text
88 // =======================================================================
89 OpenGl_Text::OpenGl_Text (const Handle(Graphic3d_Text)& theTextParams)
90 : myText (theTextParams),
92 myIs2d (Standard_False)
96 // =======================================================================
97 // function : SetPosition
99 // =======================================================================
100 void OpenGl_Text::SetPosition (const OpenGl_Vec3& thePoint)
102 myText->SetPosition (gp_Pnt (thePoint.x(), thePoint.y(), thePoint.z()));
105 // =======================================================================
106 // function : SetFontSize
108 // =======================================================================
109 void OpenGl_Text::SetFontSize (const Handle(OpenGl_Context)& theCtx,
110 const Standard_Integer theFontSize)
112 if (myText->Height() != theFontSize)
114 Release (theCtx.operator->());
116 myText->SetHeight ((Standard_ShortReal)theFontSize);
119 // =======================================================================
122 // =======================================================================
123 void OpenGl_Text::Reset (const Handle(OpenGl_Context)& theCtx)
125 if (!myFont.IsNull() && myFont->FTFont()->PointSize() != myText->Height())
127 Release (theCtx.operator->());
131 releaseVbos (theCtx.operator->());
135 // =======================================================================
138 // =======================================================================
139 void OpenGl_Text::Init (const Handle(OpenGl_Context)& theCtx,
140 const Standard_Utf8Char* theText,
141 const OpenGl_Vec3& thePoint)
144 Set2D (Standard_False);
146 NCollection_String aText;
147 aText.FromUnicode (theText);
148 myText->SetText (aText);
149 myText->SetPosition (gp_Pnt (thePoint.x(), thePoint.y(), thePoint.z()));
152 // =======================================================================
153 // function : ~OpenGl_Text
155 // =======================================================================
156 OpenGl_Text::~OpenGl_Text()
161 // =======================================================================
162 // function : releaseVbos
164 // =======================================================================
165 void OpenGl_Text::releaseVbos (OpenGl_Context* theCtx)
167 for (Standard_Integer anIter = 0; anIter < myVertsVbo.Length(); ++anIter)
169 Handle(OpenGl_VertexBuffer)& aVerts = myVertsVbo.ChangeValue (anIter);
170 Handle(OpenGl_VertexBuffer)& aTCrds = myTCrdsVbo.ChangeValue (anIter);
174 theCtx->DelayedRelease (aVerts);
175 theCtx->DelayedRelease (aTCrds);
181 && !myBndVertsVbo.IsNull())
183 theCtx->DelayedRelease (myBndVertsVbo);
189 myBndVertsVbo.Nullify();
192 // =======================================================================
193 // function : Release
195 // =======================================================================
196 void OpenGl_Text::Release (OpenGl_Context* theCtx)
198 releaseVbos (theCtx);
199 if (!myFont.IsNull())
201 const TCollection_AsciiString aKey = myFont->ResourceKey();
205 theCtx->ReleaseResource (aKey, Standard_True);
210 // =======================================================================
211 // function : EstimatedDataSize
213 // =======================================================================
214 Standard_Size OpenGl_Text::EstimatedDataSize() const
216 Standard_Size aSize = 0;
217 for (Standard_Integer anIter = myVertsVbo.Lower(); anIter <= myVertsVbo.Upper(); ++anIter)
219 if (const Handle(OpenGl_VertexBuffer)& aVerts = myVertsVbo.Value (anIter))
221 aSize += aVerts->EstimatedDataSize();
223 if (const Handle(OpenGl_VertexBuffer)& aTCrds = myTCrdsVbo.Value (anIter))
225 aSize += aTCrds->EstimatedDataSize();
228 if (!myBndVertsVbo.IsNull())
230 aSize += myBndVertsVbo->EstimatedDataSize();
235 // =======================================================================
236 // function : UpdateDrawStats
238 // =======================================================================
239 void OpenGl_Text::UpdateDrawStats (Graphic3d_FrameStatsDataTmp& theStats,
240 bool theIsDetailed) const
242 ++theStats[Graphic3d_FrameStatsCounter_NbElemsNotCulled];
243 ++theStats[Graphic3d_FrameStatsCounter_NbElemsTextNotCulled];
246 for (Standard_Integer anIter = myVertsVbo.Lower(); anIter <= myVertsVbo.Upper(); ++anIter)
248 if (const Handle(OpenGl_VertexBuffer)& aVerts = myVertsVbo.Value (anIter))
250 theStats[Graphic3d_FrameStatsCounter_NbTrianglesNotCulled] += aVerts->GetElemsNb() / 3; // 2 non-indexed triangles per glyph
256 // =======================================================================
257 // function : StringSize
259 // =======================================================================
260 void OpenGl_Text::StringSize (const Handle(OpenGl_Context)& theCtx,
261 const NCollection_String& theText,
262 const OpenGl_Aspects& theTextAspect,
263 const Standard_ShortReal theHeight,
264 const unsigned int theResolution,
265 Standard_ShortReal& theWidth,
266 Standard_ShortReal& theAscent,
267 Standard_ShortReal& theDescent)
272 const TCollection_AsciiString aFontKey = FontKey (theTextAspect, (Standard_Integer)theHeight, theResolution);
273 Handle(OpenGl_Font) aFont = FindFont (theCtx, theTextAspect, (Standard_Integer)theHeight, theResolution, aFontKey);
274 if (aFont.IsNull() || !aFont->IsValid())
279 theAscent = aFont->Ascender();
280 theDescent = aFont->Descender();
282 GLfloat aWidth = 0.0f;
283 for (NCollection_Utf8Iter anIter = theText.Iterator(); *anIter != 0;)
285 const Standard_Utf32Char aCharThis = *anIter;
286 const Standard_Utf32Char aCharNext = *++anIter;
288 if (aCharThis == '\x0D' // CR (carriage return)
289 || aCharThis == '\a' // BEL (alarm)
290 || aCharThis == '\f' // FF (form feed) NP (new page)
291 || aCharThis == '\b' // BS (backspace)
292 || aCharThis == '\v') // VT (vertical tab)
294 continue; // skip unsupported carriage control codes
296 else if (aCharThis == '\x0A') // LF (line feed, new line)
298 theWidth = Max (theWidth, aWidth);
302 else if (aCharThis == ' ')
304 aWidth += aFont->FTFont()->AdvanceX (aCharThis, aCharNext);
307 else if (aCharThis == '\t')
309 aWidth += aFont->FTFont()->AdvanceX (' ', aCharNext) * 8.0f;
313 aWidth += aFont->FTFont()->AdvanceX (aCharThis, aCharNext);
315 theWidth = Max (theWidth, aWidth);
317 Handle(OpenGl_Context) aCtx = theCtx;
319 aCtx->ReleaseResource (aFontKey, Standard_True);
322 // =======================================================================
325 // =======================================================================
326 void OpenGl_Text::Render (const Handle(OpenGl_Workspace)& theWorkspace) const
328 const OpenGl_Aspects* aTextAspect = theWorkspace->ApplyAspects (false); // do not bind textures as they will be disabled anyway
329 const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
331 // Bind custom shader program or generate default version
332 aCtx->ShaderManager()->BindFontProgram (aTextAspect->ShaderProgramRes (aCtx));
333 const Handle(OpenGl_TextureSet) aPrevTexture = aCtx->BindTextures (Handle(OpenGl_TextureSet)(), Handle(OpenGl_ShaderProgram)());
335 if (myText->HasPlane() && myText->HasOwnAnchorPoint())
337 myOrientationMatrix = aCtx->Camera()->OrientationMatrix();
338 // reset translation part
339 myOrientationMatrix.ChangeValue (0, 3) = 0.0;
340 myOrientationMatrix.ChangeValue (1, 3) = 0.0;
341 myOrientationMatrix.ChangeValue (2, 3) = 0.0;
344 myProjMatrix.Convert (aCtx->ProjectionState.Current());
346 // use highlight color or colors from aspect
349 theWorkspace->TextColor(),
350 theWorkspace->TextSubtitleColor(),
354 if (!aPrevTexture.IsNull())
356 aCtx->BindTextures (aPrevTexture, Handle(OpenGl_ShaderProgram)());
359 // restore Z buffer settings
360 if (theWorkspace->UseZBuffer())
362 glEnable (GL_DEPTH_TEST);
366 // =======================================================================
369 // =======================================================================
370 void OpenGl_Text::Render (const Handle(OpenGl_Context)& theCtx,
371 const OpenGl_Aspects& theTextAspect,
372 unsigned int theResolution) const
374 #if !defined(GL_ES_VERSION_2_0)
375 const Standard_Integer aPrevPolygonMode = theCtx->SetPolygonMode (GL_FILL);
376 const bool aPrevHatchingMode = theCtx->SetPolygonHatchEnabled (false);
379 render (theCtx, theTextAspect,
380 theTextAspect.Aspect()->ColorRGBA(),
381 theTextAspect.Aspect()->ColorSubTitleRGBA(),
384 #if !defined(GL_ES_VERSION_2_0)
385 theCtx->SetPolygonMode (aPrevPolygonMode);
386 theCtx->SetPolygonHatchEnabled (aPrevHatchingMode);
390 // =======================================================================
391 // function : setupMatrix
393 // =======================================================================
394 void OpenGl_Text::setupMatrix (const Handle(OpenGl_Context)& theCtx,
395 const OpenGl_Aspects& theTextAspect,
396 const OpenGl_Vec3& theDVec) const
398 OpenGl_Mat4d aModViewMat, aProjectMat;
399 if (myText->HasPlane() && myText->HasOwnAnchorPoint())
401 aProjectMat = myProjMatrix * myOrientationMatrix;
405 aProjectMat = myProjMatrix;
410 const gp_Pnt& aPoint = myText->Position();
411 Graphic3d_TransformUtils::Translate<GLdouble> (aModViewMat, aPoint.X() + theDVec.x(), aPoint.Y() + theDVec.y(), 0.f);
412 Graphic3d_TransformUtils::Scale<GLdouble> (aModViewMat, 1.f, -1.f, 1.f);
413 Graphic3d_TransformUtils::Rotate<GLdouble> (aModViewMat, theTextAspect.Aspect()->TextAngle(), 0.f, 0.f, 1.f);
417 OpenGl_Vec3d anObjXYZ;
418 OpenGl_Vec3d aWinXYZ = myWinXYZ + OpenGl_Vec3d (theDVec);
419 if (!myText->HasPlane() && !theTextAspect.Aspect()->IsTextZoomable())
421 // Align coordinates to the nearest integer to avoid extra interpolation issues.
422 // Note that for better readability we could also try aligning freely rotated in 3D text (myHasPlane),
423 // when camera orientation co-aligned with horizontal text orientation,
424 // but this might look awkward while rotating camera.
425 aWinXYZ.x() = Floor (aWinXYZ.x());
426 aWinXYZ.y() = Floor (aWinXYZ.y());
428 Graphic3d_TransformUtils::UnProject<Standard_Real> (aWinXYZ.x(), aWinXYZ.y(), aWinXYZ.z(),
429 THE_IDENTITY_MATRIX, aProjectMat, theCtx->Viewport(),
430 anObjXYZ.x(), anObjXYZ.y(), anObjXYZ.z());
432 if (myText->HasPlane())
434 const gp_Ax2& anOrientation = myText->Orientation();
435 const gp_Dir& aVectorDir = anOrientation.XDirection();
436 const gp_Dir& aVectorUp = anOrientation.Direction();
437 const gp_Dir& aVectorRight = anOrientation.YDirection();
439 aModViewMat.SetColumn (2, OpenGl_Vec3d (aVectorUp.X(), aVectorUp.Y(), aVectorUp.Z()));
440 aModViewMat.SetColumn (1, OpenGl_Vec3d (aVectorRight.X(), aVectorRight.Y(), aVectorRight.Z()));
441 aModViewMat.SetColumn (0, OpenGl_Vec3d (aVectorDir.X(), aVectorDir.Y(), aVectorDir.Z()));
443 if (!myText->HasOwnAnchorPoint())
445 OpenGl_Mat4d aPosMat;
446 const gp_Pnt& aPoint = myText->Position();
447 aPosMat.SetColumn (3, OpenGl_Vec3d (aPoint.X(), aPoint.Y(), aPoint.Z()));
448 aPosMat *= aModViewMat;
449 aModViewMat.SetColumn (3, aPosMat.GetColumn (3));
453 aModViewMat.SetColumn (3, anObjXYZ);
458 Graphic3d_TransformUtils::Translate<GLdouble> (aModViewMat, anObjXYZ.x(), anObjXYZ.y(), anObjXYZ.z());
459 Graphic3d_TransformUtils::Rotate<GLdouble> (aModViewMat, theTextAspect.Aspect()->TextAngle(), 0.0, 0.0, 1.0);
462 if (!theTextAspect.Aspect()->IsTextZoomable())
464 Graphic3d_TransformUtils::Scale<GLdouble> (aModViewMat, myScaleHeight, myScaleHeight, myScaleHeight);
466 else if (theCtx->HasRenderScale())
468 Graphic3d_TransformUtils::Scale<GLdouble> (aModViewMat, theCtx->RenderScaleInv(), theCtx->RenderScaleInv(), theCtx->RenderScaleInv());
472 if (myText->HasPlane() && !myText->HasOwnAnchorPoint())
474 OpenGl_Mat4d aCurrentWorldViewMat;
475 aCurrentWorldViewMat.Convert (theCtx->WorldViewState.Current());
477 // apply local transformation
478 OpenGl_Mat4d aModelWorld;
479 aModelWorld.Convert (theCtx->ModelWorldState.Current());
480 aCurrentWorldViewMat = aCurrentWorldViewMat * aModelWorld;
482 theCtx->WorldViewState.SetCurrent<Standard_Real> (aCurrentWorldViewMat * aModViewMat);
486 theCtx->WorldViewState.SetCurrent<Standard_Real> (aModViewMat);
488 theCtx->ApplyWorldViewMatrix();
492 theCtx->ProjectionState.SetCurrent<Standard_Real> (aProjectMat);
493 theCtx->ApplyProjectionMatrix();
496 // Upload updated state to shader program
497 theCtx->ShaderManager()->PushState (theCtx->ActiveProgram());
500 // =======================================================================
501 // function : drawText
503 // =======================================================================
504 void OpenGl_Text::drawText (const Handle(OpenGl_Context)& theCtx,
505 const OpenGl_Aspects& theTextAspect) const
507 (void )theTextAspect;
508 if (myVertsVbo.Length() != myTextures.Length()
509 || myTextures.IsEmpty())
514 for (Standard_Integer anIter = 0; anIter < myTextures.Length(); ++anIter)
516 const GLuint aTexId = myTextures.Value (anIter);
517 glBindTexture (GL_TEXTURE_2D, aTexId);
519 const Handle(OpenGl_VertexBuffer)& aVerts = myVertsVbo.Value (anIter);
520 const Handle(OpenGl_VertexBuffer)& aTCrds = myTCrdsVbo.Value (anIter);
521 aVerts->BindAttribute (theCtx, Graphic3d_TOA_POS);
522 aTCrds->BindAttribute (theCtx, Graphic3d_TOA_UV);
524 glDrawArrays (GL_TRIANGLES, 0, GLsizei(aVerts->GetElemsNb()));
526 aTCrds->UnbindAttribute (theCtx, Graphic3d_TOA_UV);
527 aVerts->UnbindAttribute (theCtx, Graphic3d_TOA_POS);
529 glBindTexture (GL_TEXTURE_2D, 0);
532 // =======================================================================
533 // function : FontKey
535 // =======================================================================
536 TCollection_AsciiString OpenGl_Text::FontKey (const OpenGl_Aspects& theAspect,
537 Standard_Integer theHeight,
538 unsigned int theResolution)
540 const Font_FontAspect anAspect = theAspect.Aspect()->TextFontAspect() != Font_FA_Undefined
541 ? theAspect.Aspect()->TextFontAspect()
543 const TCollection_AsciiString& aFont = !theAspect.Aspect()->TextFont().IsNull() ? theAspect.Aspect()->TextFont()->String() : THE_DEFAULT_FONT;
545 + TCollection_AsciiString(":") + Standard_Integer(anAspect)
546 + TCollection_AsciiString(":") + Standard_Integer(theResolution)
547 + TCollection_AsciiString(":") + theHeight;
550 // =======================================================================
551 // function : FindFont
553 // =======================================================================
554 Handle(OpenGl_Font) OpenGl_Text::FindFont (const Handle(OpenGl_Context)& theCtx,
555 const OpenGl_Aspects& theAspect,
556 Standard_Integer theHeight,
557 unsigned int theResolution,
558 const TCollection_AsciiString& theKey)
560 Handle(OpenGl_Font) aFont;
563 return aFont; // invalid parameters
566 if (!theCtx->GetResource (theKey, aFont))
568 Handle(Font_FontMgr) aFontMgr = Font_FontMgr::GetInstance();
569 const TCollection_AsciiString& aFontName = !theAspect.Aspect()->TextFont().IsNull()
570 ? theAspect.Aspect()->TextFont()->String()
572 Font_FontAspect anAspect = theAspect.Aspect()->TextFontAspect() != Font_FA_Undefined
573 ? theAspect.Aspect()->TextFontAspect()
575 Font_FTFontParams aParams;
576 aParams.PointSize = theHeight;
577 aParams.Resolution = theResolution;
578 if (Handle(Font_FTFont) aFontFt = Font_FTFont::FindAndCreate (aFontName, anAspect, aParams, Font_StrictLevel_Any))
580 aFont = new OpenGl_Font (aFontFt, theKey);
581 if (!aFont->Init (theCtx))
583 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
584 TCollection_AsciiString ("Font '") + aFontName + "' - initialization of GL resources has failed!");
586 aFont->Release (theCtx.get());
587 aFont = new OpenGl_Font (aFontFt, theKey);
592 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
593 TCollection_AsciiString ("Font '") + aFontName + "' is not found in the system!");
594 aFont = new OpenGl_Font (aFontFt, theKey);
597 theCtx->ShareResource (theKey, aFont);
602 // =======================================================================
603 // function : drawRect
605 // =======================================================================
606 void OpenGl_Text::drawRect (const Handle(OpenGl_Context)& theCtx,
607 const OpenGl_Aspects& theTextAspect,
608 const OpenGl_Vec4& theColorSubs) const
610 Handle(OpenGl_ShaderProgram) aPrevProgram = theCtx->ActiveProgram();
611 if (myBndVertsVbo.IsNull())
613 OpenGl_Vec2 aQuad[4] =
615 OpenGl_Vec2(myBndBox.Right, myBndBox.Bottom),
616 OpenGl_Vec2(myBndBox.Right, myBndBox.Top),
617 OpenGl_Vec2(myBndBox.Left, myBndBox.Bottom),
618 OpenGl_Vec2(myBndBox.Left, myBndBox.Top)
620 if (theCtx->ToUseVbo())
622 myBndVertsVbo = new OpenGl_VertexBuffer();
626 myBndVertsVbo = new OpenGl_VertexBufferCompat();
628 myBndVertsVbo->Init (theCtx, 2, 4, aQuad[0].GetData());
631 // bind unlit program
632 theCtx->ShaderManager()->BindFaceProgram (Handle(OpenGl_TextureSet)(), Graphic3d_TOSM_UNLIT,
633 Graphic3d_AlphaMode_Opaque, Standard_False, Standard_False,
634 Handle(OpenGl_ShaderProgram)());
636 #if !defined(GL_ES_VERSION_2_0)
637 if (theCtx->core11 != NULL
638 && theCtx->ActiveProgram().IsNull())
640 glBindTexture (GL_TEXTURE_2D, 0);
643 theCtx->SetColor4fv (theColorSubs);
644 setupMatrix (theCtx, theTextAspect, OpenGl_Vec3 (0.0f, 0.0f, 0.0f));
645 myBndVertsVbo->BindAttribute (theCtx, Graphic3d_TOA_POS);
647 theCtx->core20fwd->glDrawArrays (GL_TRIANGLE_STRIP, 0, 4);
649 myBndVertsVbo->UnbindAttribute (theCtx, Graphic3d_TOA_POS);
650 theCtx->BindProgram (aPrevProgram);
653 // =======================================================================
656 // =======================================================================
657 void OpenGl_Text::render (const Handle(OpenGl_Context)& theCtx,
658 const OpenGl_Aspects& theTextAspect,
659 const OpenGl_Vec4& theColorText,
660 const OpenGl_Vec4& theColorSubs,
661 unsigned int theResolution) const
663 if (myText->Text().IsEmpty() && myText->TextFormatter().IsNull())
668 // Note that using difference resolution in different Views in same Viewer
669 // will lead to performance regression (for example, text will be recreated every time).
670 const TCollection_AsciiString aFontKey = FontKey (theTextAspect, (Standard_Integer)myText->Height(), theResolution);
672 && !myFont->ResourceKey().IsEqual (aFontKey))
675 const_cast<OpenGl_Text* > (this)->Release (theCtx.operator->());
680 myFont = FindFont (theCtx, theTextAspect, (Standard_Integer)myText->Height(), theResolution, aFontKey);
682 if (!myFont->WasInitialized())
687 if (myTextures.IsEmpty())
689 Handle(Font_TextFormatter) aFormatter = myText->TextFormatter();
690 if (aFormatter.IsNull())
692 aFormatter = new Font_TextFormatter();
694 aFormatter->SetupAlignment (myText->HorizontalAlignment(), myText->VerticalAlignment());
697 aFormatter->Append (myText->Text(), *myFont->FTFont());
698 aFormatter->Format();
700 OpenGl_TextBuilder aBuilder;
701 aBuilder.Perform (aFormatter,
703 *myFont.operator->(),
708 aFormatter->BndBox (myBndBox);
709 if (!myBndVertsVbo.IsNull())
711 myBndVertsVbo->Release (theCtx.get());
712 myBndVertsVbo.Nullify();
716 if (myTextures.IsEmpty())
721 myScaleHeight = 1.0f;
723 theCtx->WorldViewState.Push();
724 myModelMatrix.Convert (theCtx->WorldViewState.Current() * theCtx->ModelWorldState.Current());
726 const GLdouble aPointSize = (GLdouble )myFont->FTFont()->PointSize();
729 const gp_Pnt& aPoint = myText->Position();
730 Graphic3d_TransformUtils::Project<Standard_Real> (aPoint.X(), aPoint.Y(), aPoint.Z(),
731 myModelMatrix, myProjMatrix, theCtx->Viewport(),
732 myWinXYZ.x(), myWinXYZ.y(), myWinXYZ.z());
734 // compute scale factor for constant text height
735 if (!theTextAspect.Aspect()->IsTextZoomable())
737 Graphic3d_Vec3d aPnt1, aPnt2;
738 Graphic3d_TransformUtils::UnProject<Standard_Real> (myWinXYZ.x(), myWinXYZ.y(), myWinXYZ.z(),
739 THE_IDENTITY_MATRIX, myProjMatrix, theCtx->Viewport(),
740 aPnt1.x(), aPnt1.y(), aPnt1.z());
741 Graphic3d_TransformUtils::UnProject<Standard_Real> (myWinXYZ.x(), myWinXYZ.y() + aPointSize, myWinXYZ.z(),
742 THE_IDENTITY_MATRIX, myProjMatrix, theCtx->Viewport(),
743 aPnt2.x(), aPnt2.y(), aPnt2.z());
744 myScaleHeight = (aPnt2.y() - aPnt1.y()) / aPointSize;
748 #if !defined(GL_ES_VERSION_2_0)
749 if (theCtx->core11 != NULL
750 && theCtx->caps->ffpEnable)
752 glDisable (GL_LIGHTING);
757 const bool hasDepthTest = !myIs2d
758 && theTextAspect.Aspect()->TextStyle() != Aspect_TOST_ANNOTATION;
761 glDisable (GL_DEPTH_TEST);
764 if (theCtx->core15fwd != NULL)
766 theCtx->core15fwd->glActiveTexture (GL_TEXTURE0);
768 #if !defined(GL_ES_VERSION_2_0)
769 // activate texture unit
770 GLint aTexEnvParam = GL_REPLACE;
771 if (theCtx->core11 != NULL)
773 glDisable (GL_TEXTURE_1D);
774 glEnable (GL_TEXTURE_2D);
775 glGetTexEnviv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &aTexEnvParam);
776 if (aTexEnvParam != GL_REPLACE)
778 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
785 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
787 // alpha to coverage makes text too thin
788 theCtx->SetSampleAlphaToCoverage (false);
791 switch (theTextAspect.Aspect()->TextDisplayType())
793 case Aspect_TODT_BLEND:
795 #if !defined(GL_ES_VERSION_2_0)
796 glEnable (GL_COLOR_LOGIC_OP);
801 case Aspect_TODT_SUBTITLE:
803 BackPolygonOffsetSentry aPolygonOffsetTmp (hasDepthTest ? theCtx.get() : NULL);
804 drawRect (theCtx, theTextAspect, theColorSubs);
807 case Aspect_TODT_DEKALE:
809 BackPolygonOffsetSentry aPolygonOffsetTmp (hasDepthTest ? theCtx.get() : NULL);
810 theCtx->SetColor4fv (theColorSubs);
811 setupMatrix (theCtx, theTextAspect, OpenGl_Vec3 (+1.0f, +1.0f, 0.0f));
812 drawText (theCtx, theTextAspect);
813 setupMatrix (theCtx, theTextAspect, OpenGl_Vec3 (-1.0f, -1.0f, 0.0f));
814 drawText (theCtx, theTextAspect);
815 setupMatrix (theCtx, theTextAspect, OpenGl_Vec3 (-1.0f, +1.0f, 0.0f));
816 drawText (theCtx, theTextAspect);
817 setupMatrix (theCtx, theTextAspect, OpenGl_Vec3 (+1.0f, -1.0f, 0.0f));
818 drawText (theCtx, theTextAspect);
821 case Aspect_TODT_SHADOW:
823 BackPolygonOffsetSentry aPolygonOffsetTmp (hasDepthTest ? theCtx.get() : NULL);
824 theCtx->SetColor4fv (theColorSubs);
825 setupMatrix (theCtx, theTextAspect, OpenGl_Vec3 (+1.0f, -1.0f, 0.0f));
826 drawText (theCtx, theTextAspect);
829 case Aspect_TODT_DIMENSION:
830 case Aspect_TODT_NORMAL:
837 theCtx->SetColor4fv (theColorText);
838 setupMatrix (theCtx, theTextAspect, OpenGl_Vec3 (0.0f, 0.0f, 0.0f));
839 drawText (theCtx, theTextAspect);
843 theCtx->ProjectionState.SetCurrent<Standard_Real> (myProjMatrix);
844 theCtx->ApplyProjectionMatrix();
847 #if !defined(GL_ES_VERSION_2_0)
848 if (theCtx->core11 != NULL)
850 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, aTexEnvParam);
854 if (theTextAspect.Aspect()->TextDisplayType() == Aspect_TODT_DIMENSION)
856 glDisable (GL_BLEND);
859 glDisable (GL_DEPTH_TEST);
861 #if !defined(GL_ES_VERSION_2_0)
862 if (theCtx->core11 != NULL)
864 glDisable (GL_TEXTURE_2D);
867 const bool aColorMaskBack = theCtx->SetColorMask (false);
869 glClear (GL_STENCIL_BUFFER_BIT);
870 glEnable (GL_STENCIL_TEST);
871 glStencilFunc (GL_ALWAYS, 1, 0xFF);
872 glStencilOp (GL_KEEP, GL_KEEP, GL_REPLACE);
874 drawRect (theCtx, theTextAspect, OpenGl_Vec4 (1.0f, 1.0f, 1.0f, 1.0f));
876 glStencilFunc (GL_ALWAYS, 0, 0xFF);
878 theCtx->SetColorMask (aColorMaskBack);
881 // reset OpenGL state
882 glDisable (GL_BLEND);
883 glDisable (GL_STENCIL_TEST);
884 #if !defined(GL_ES_VERSION_2_0)
885 glDisable (GL_COLOR_LOGIC_OP);
888 // model view matrix was modified
889 theCtx->WorldViewState.Pop();
890 theCtx->ApplyModelViewMatrix();
893 // =======================================================================
894 // function : DumpJson
896 // =======================================================================
897 void OpenGl_Text::DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth) const
899 OCCT_DUMP_CLASS_BEGIN (theOStream, OpenGl_Text)
900 OCCT_DUMP_BASE_CLASS (theOStream, theDepth, OpenGl_Element)
902 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myTextures.Size())
904 for (NCollection_Vector<Handle(OpenGl_VertexBuffer)>::Iterator aCrdsIt (myTCrdsVbo); aCrdsIt.More(); aCrdsIt.Next())
906 const Handle(OpenGl_VertexBuffer)& aVertexBuffer = aCrdsIt.Value();
907 OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, aVertexBuffer.get())
910 OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &myBndBox)