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_GlCore11.hxx>
17 #include <OpenGl_GraphicDriver.hxx>
18 #include <OpenGl_ShaderManager.hxx>
19 #include <OpenGl_ShaderProgram.hxx>
20 #include <OpenGl_Text.hxx>
21 #include <OpenGl_View.hxx>
22 #include <OpenGl_VertexBufferCompat.hxx>
24 #include <Font_FontMgr.hxx>
25 #include <Font_FTFont.hxx>
26 #include <Font_TextFormatter.hxx>
27 #include <Graphic3d_TransformUtils.hxx>
28 #include <TCollection_HAsciiString.hxx>
32 static const OpenGl_Mat4d THE_IDENTITY_MATRIX;
34 static const TCollection_AsciiString THE_DEFAULT_FONT (Font_NOF_ASCII_MONO);
36 //! Auxiliary tool for setting polygon offset temporarily.
37 struct BackPolygonOffsetSentry
39 BackPolygonOffsetSentry (OpenGl_Context* theCtx)
44 myOffsetBack = theCtx->PolygonOffset();
45 Graphic3d_PolygonOffset aPolyOffset = myOffsetBack;
46 aPolyOffset.Mode = Aspect_POM_Fill;
47 aPolyOffset.Units += 1.0f;
48 theCtx->SetPolygonOffset (aPolyOffset);
52 ~BackPolygonOffsetSentry()
56 myCtx->SetPolygonOffset (myOffsetBack);
61 BackPolygonOffsetSentry (const BackPolygonOffsetSentry& );
62 BackPolygonOffsetSentry& operator= (const BackPolygonOffsetSentry& );
64 OpenGl_Context* myCtx;
65 Graphic3d_PolygonOffset myOffsetBack;
68 } // anonymous namespace
70 // =======================================================================
71 // function : OpenGl_Text
73 // =======================================================================
74 OpenGl_Text::OpenGl_Text()
75 : myScaleHeight (1.0f),
76 myIs2d (Standard_False)
78 myText = new Graphic3d_Text (10.);
82 // =======================================================================
83 // function : OpenGl_Text
85 // =======================================================================
86 OpenGl_Text::OpenGl_Text (const Handle(Graphic3d_Text)& theTextParams)
87 : myText (theTextParams),
89 myIs2d (Standard_False)
93 // =======================================================================
94 // function : SetPosition
96 // =======================================================================
97 void OpenGl_Text::SetPosition (const OpenGl_Vec3& thePoint)
99 myText->SetPosition (gp_Pnt (thePoint.x(), thePoint.y(), thePoint.z()));
102 // =======================================================================
103 // function : SetFontSize
105 // =======================================================================
106 void OpenGl_Text::SetFontSize (const Handle(OpenGl_Context)& theCtx,
107 const Standard_Integer theFontSize)
109 if (myText->Height() != theFontSize)
111 Release (theCtx.operator->());
113 myText->SetHeight ((Standard_ShortReal)theFontSize);
116 // =======================================================================
119 // =======================================================================
120 void OpenGl_Text::Reset (const Handle(OpenGl_Context)& theCtx)
122 if (!myFont.IsNull() && myFont->FTFont()->PointSize() != myText->Height())
124 Release (theCtx.operator->());
128 releaseVbos (theCtx.operator->());
132 // =======================================================================
135 // =======================================================================
136 void OpenGl_Text::Init (const Handle(OpenGl_Context)& theCtx,
137 const Standard_Utf8Char* theText,
138 const OpenGl_Vec3& thePoint)
141 Set2D (Standard_False);
143 NCollection_String aText;
144 aText.FromUnicode (theText);
145 myText->SetText (aText);
146 myText->SetPosition (gp_Pnt (thePoint.x(), thePoint.y(), thePoint.z()));
149 // =======================================================================
150 // function : ~OpenGl_Text
152 // =======================================================================
153 OpenGl_Text::~OpenGl_Text()
158 // =======================================================================
159 // function : releaseVbos
161 // =======================================================================
162 void OpenGl_Text::releaseVbos (OpenGl_Context* theCtx)
164 for (Standard_Integer anIter = 0; anIter < myVertsVbo.Length(); ++anIter)
166 Handle(OpenGl_VertexBuffer)& aVerts = myVertsVbo.ChangeValue (anIter);
167 Handle(OpenGl_VertexBuffer)& aTCrds = myTCrdsVbo.ChangeValue (anIter);
171 theCtx->DelayedRelease (aVerts);
172 theCtx->DelayedRelease (aTCrds);
178 && !myBndVertsVbo.IsNull())
180 theCtx->DelayedRelease (myBndVertsVbo);
186 myBndVertsVbo.Nullify();
189 // =======================================================================
190 // function : Release
192 // =======================================================================
193 void OpenGl_Text::Release (OpenGl_Context* theCtx)
195 releaseVbos (theCtx);
196 if (!myFont.IsNull())
198 const TCollection_AsciiString aKey = myFont->ResourceKey();
202 theCtx->ReleaseResource (aKey, Standard_True);
207 // =======================================================================
208 // function : EstimatedDataSize
210 // =======================================================================
211 Standard_Size OpenGl_Text::EstimatedDataSize() const
213 Standard_Size aSize = 0;
214 for (Standard_Integer anIter = myVertsVbo.Lower(); anIter <= myVertsVbo.Upper(); ++anIter)
216 if (const Handle(OpenGl_VertexBuffer)& aVerts = myVertsVbo.Value (anIter))
218 aSize += aVerts->EstimatedDataSize();
220 if (const Handle(OpenGl_VertexBuffer)& aTCrds = myTCrdsVbo.Value (anIter))
222 aSize += aTCrds->EstimatedDataSize();
225 if (!myBndVertsVbo.IsNull())
227 aSize += myBndVertsVbo->EstimatedDataSize();
232 // =======================================================================
233 // function : UpdateDrawStats
235 // =======================================================================
236 void OpenGl_Text::UpdateDrawStats (Graphic3d_FrameStatsDataTmp& theStats,
237 bool theIsDetailed) const
239 ++theStats[Graphic3d_FrameStatsCounter_NbElemsNotCulled];
240 ++theStats[Graphic3d_FrameStatsCounter_NbElemsTextNotCulled];
243 for (Standard_Integer anIter = myVertsVbo.Lower(); anIter <= myVertsVbo.Upper(); ++anIter)
245 if (const Handle(OpenGl_VertexBuffer)& aVerts = myVertsVbo.Value (anIter))
247 theStats[Graphic3d_FrameStatsCounter_NbTrianglesNotCulled] += aVerts->GetElemsNb() / 3; // 2 non-indexed triangles per glyph
253 // =======================================================================
254 // function : StringSize
256 // =======================================================================
257 void OpenGl_Text::StringSize (const Handle(OpenGl_Context)& theCtx,
258 const NCollection_String& theText,
259 const OpenGl_Aspects& theTextAspect,
260 const Standard_ShortReal theHeight,
261 const unsigned int theResolution,
262 const Font_Hinting theFontHinting,
263 Standard_ShortReal& theWidth,
264 Standard_ShortReal& theAscent,
265 Standard_ShortReal& theDescent)
270 const TCollection_AsciiString aFontKey = FontKey (theTextAspect, (Standard_Integer)theHeight, theResolution, theFontHinting);
271 Handle(OpenGl_Font) aFont = FindFont (theCtx, theTextAspect, (Standard_Integer)theHeight, theResolution, theFontHinting, aFontKey);
272 if (aFont.IsNull() || !aFont->IsValid())
277 theAscent = aFont->Ascender();
278 theDescent = aFont->Descender();
280 GLfloat aWidth = 0.0f;
281 for (NCollection_Utf8Iter anIter = theText.Iterator(); *anIter != 0;)
283 const Standard_Utf32Char aCharThis = *anIter;
284 const Standard_Utf32Char aCharNext = *++anIter;
286 if (aCharThis == '\x0D' // CR (carriage return)
287 || aCharThis == '\a' // BEL (alarm)
288 || aCharThis == '\f' // FF (form feed) NP (new page)
289 || aCharThis == '\b' // BS (backspace)
290 || aCharThis == '\v') // VT (vertical tab)
292 continue; // skip unsupported carriage control codes
294 else if (aCharThis == '\x0A') // LF (line feed, new line)
296 theWidth = Max (theWidth, aWidth);
300 else if (aCharThis == ' ')
302 aWidth += aFont->FTFont()->AdvanceX (aCharThis, aCharNext);
305 else if (aCharThis == '\t')
307 aWidth += aFont->FTFont()->AdvanceX (' ', aCharNext) * 8.0f;
311 aWidth += aFont->FTFont()->AdvanceX (aCharThis, aCharNext);
313 theWidth = Max (theWidth, aWidth);
315 const Handle(OpenGl_Context)& aCtx = theCtx;
317 aCtx->ReleaseResource (aFontKey, Standard_True);
320 // =======================================================================
323 // =======================================================================
324 void OpenGl_Text::Render (const Handle(OpenGl_Workspace)& theWorkspace) const
326 const OpenGl_Aspects* aTextAspect = theWorkspace->ApplyAspects (false); // do not bind textures as they will be disabled anyway
327 const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
329 // Bind custom shader program or generate default version
330 aCtx->ShaderManager()->BindFontProgram (aTextAspect->ShaderProgramRes (aCtx));
331 const Handle(OpenGl_TextureSet) aPrevTexture = aCtx->BindTextures (Handle(OpenGl_TextureSet)(), Handle(OpenGl_ShaderProgram)());
333 if (myText->HasPlane() && myText->HasOwnAnchorPoint())
335 myOrientationMatrix = aCtx->Camera()->OrientationMatrix();
336 // reset translation part
337 myOrientationMatrix.ChangeValue (0, 3) = 0.0;
338 myOrientationMatrix.ChangeValue (1, 3) = 0.0;
339 myOrientationMatrix.ChangeValue (2, 3) = 0.0;
342 myProjMatrix.Convert (aCtx->ProjectionState.Current());
344 // use highlight color or colors from aspect
347 theWorkspace->TextColor(),
348 theWorkspace->TextSubtitleColor(),
350 theWorkspace->View()->RenderingParams().FontHinting);
353 if (!aPrevTexture.IsNull())
355 aCtx->BindTextures (aPrevTexture, Handle(OpenGl_ShaderProgram)());
358 // restore Z buffer settings
359 if (theWorkspace->UseZBuffer())
361 aCtx->core11fwd->glEnable (GL_DEPTH_TEST);
365 // =======================================================================
368 // =======================================================================
369 void OpenGl_Text::Render (const Handle(OpenGl_Context)& theCtx,
370 const OpenGl_Aspects& theTextAspect,
371 unsigned int theResolution,
372 Font_Hinting theFontHinting) const
374 const Standard_Integer aPrevPolygonMode = theCtx->SetPolygonMode (GL_FILL);
375 const bool aPrevHatchingMode = theCtx->SetPolygonHatchEnabled (false);
377 render (theCtx, theTextAspect,
378 theTextAspect.Aspect()->ColorRGBA(),
379 theTextAspect.Aspect()->ColorSubTitleRGBA(),
383 theCtx->SetPolygonMode (aPrevPolygonMode);
384 theCtx->SetPolygonHatchEnabled (aPrevHatchingMode);
387 // =======================================================================
388 // function : setupMatrix
390 // =======================================================================
391 void OpenGl_Text::setupMatrix (const Handle(OpenGl_Context)& theCtx,
392 const OpenGl_Aspects& theTextAspect,
393 const OpenGl_Vec3& theDVec) const
395 OpenGl_Mat4d aModViewMat, aProjectMat;
396 if (myText->HasPlane() && myText->HasOwnAnchorPoint())
398 aProjectMat = myProjMatrix * myOrientationMatrix;
402 aProjectMat = myProjMatrix;
407 const gp_Pnt& aPoint = myText->Position();
408 Graphic3d_TransformUtils::Translate<GLdouble> (aModViewMat, aPoint.X() + theDVec.x(), aPoint.Y() + theDVec.y(), 0.f);
409 Graphic3d_TransformUtils::Scale<GLdouble> (aModViewMat, 1.f, -1.f, 1.f);
410 Graphic3d_TransformUtils::Rotate<GLdouble> (aModViewMat, theTextAspect.Aspect()->TextAngle(), 0.f, 0.f, 1.f);
414 OpenGl_Vec3d anObjXYZ;
415 OpenGl_Vec3d aWinXYZ = myWinXYZ + OpenGl_Vec3d (theDVec);
416 if (!myText->HasPlane() && !theTextAspect.Aspect()->IsTextZoomable())
418 // Align coordinates to the nearest integer to avoid extra interpolation issues.
419 // Note that for better readability we could also try aligning freely rotated in 3D text (myHasPlane),
420 // when camera orientation co-aligned with horizontal text orientation,
421 // but this might look awkward while rotating camera.
422 aWinXYZ.x() = Floor (aWinXYZ.x());
423 aWinXYZ.y() = Floor (aWinXYZ.y());
425 Graphic3d_TransformUtils::UnProject<Standard_Real> (aWinXYZ.x(), aWinXYZ.y(), aWinXYZ.z(),
426 THE_IDENTITY_MATRIX, aProjectMat, theCtx->Viewport(),
427 anObjXYZ.x(), anObjXYZ.y(), anObjXYZ.z());
429 if (myText->HasPlane())
431 const gp_Ax2& anOrientation = myText->Orientation();
432 const gp_Dir& aVectorDir = anOrientation.XDirection();
433 const gp_Dir& aVectorUp = anOrientation.Direction();
434 const gp_Dir& aVectorRight = anOrientation.YDirection();
436 aModViewMat.SetColumn (2, OpenGl_Vec3d (aVectorUp.X(), aVectorUp.Y(), aVectorUp.Z()));
437 aModViewMat.SetColumn (1, OpenGl_Vec3d (aVectorRight.X(), aVectorRight.Y(), aVectorRight.Z()));
438 aModViewMat.SetColumn (0, OpenGl_Vec3d (aVectorDir.X(), aVectorDir.Y(), aVectorDir.Z()));
440 if (!myText->HasOwnAnchorPoint())
442 OpenGl_Mat4d aPosMat;
443 const gp_Pnt& aPoint = myText->Position();
444 aPosMat.SetColumn (3, OpenGl_Vec3d (aPoint.X(), aPoint.Y(), aPoint.Z()));
445 aPosMat *= aModViewMat;
446 aModViewMat.SetColumn (3, aPosMat.GetColumn (3));
450 aModViewMat.SetColumn (3, anObjXYZ);
455 Graphic3d_TransformUtils::Translate<GLdouble> (aModViewMat, anObjXYZ.x(), anObjXYZ.y(), anObjXYZ.z());
456 Graphic3d_TransformUtils::Rotate<GLdouble> (aModViewMat, theTextAspect.Aspect()->TextAngle(), 0.0, 0.0, 1.0);
459 if (!theTextAspect.Aspect()->IsTextZoomable())
461 Graphic3d_TransformUtils::Scale<GLdouble> (aModViewMat, myScaleHeight, myScaleHeight, myScaleHeight);
463 else if (theCtx->HasRenderScale())
465 Graphic3d_TransformUtils::Scale<GLdouble> (aModViewMat, theCtx->RenderScaleInv(), theCtx->RenderScaleInv(), theCtx->RenderScaleInv());
469 if (myText->HasPlane() && !myText->HasOwnAnchorPoint())
471 OpenGl_Mat4d aCurrentWorldViewMat;
472 aCurrentWorldViewMat.Convert (theCtx->WorldViewState.Current());
474 // apply local transformation
475 OpenGl_Mat4d aModelWorld;
476 aModelWorld.Convert (theCtx->ModelWorldState.Current());
477 aCurrentWorldViewMat = aCurrentWorldViewMat * aModelWorld;
479 theCtx->WorldViewState.SetCurrent<Standard_Real> (aCurrentWorldViewMat * aModViewMat);
483 theCtx->WorldViewState.SetCurrent<Standard_Real> (aModViewMat);
485 theCtx->ApplyWorldViewMatrix();
489 theCtx->ProjectionState.SetCurrent<Standard_Real> (aProjectMat);
490 theCtx->ApplyProjectionMatrix();
493 // Upload updated state to shader program
494 theCtx->ShaderManager()->PushState (theCtx->ActiveProgram());
497 // =======================================================================
498 // function : drawText
500 // =======================================================================
501 void OpenGl_Text::drawText (const Handle(OpenGl_Context)& theCtx,
502 const OpenGl_Aspects& theTextAspect) const
504 (void )theTextAspect;
505 if (myVertsVbo.Length() != myTextures.Length()
506 || myTextures.IsEmpty())
511 for (Standard_Integer anIter = 0; anIter < myTextures.Length(); ++anIter)
513 const GLuint aTexId = myTextures.Value (anIter);
514 theCtx->core11fwd->glBindTexture (GL_TEXTURE_2D, aTexId);
516 const Handle(OpenGl_VertexBuffer)& aVerts = myVertsVbo.Value (anIter);
517 const Handle(OpenGl_VertexBuffer)& aTCrds = myTCrdsVbo.Value (anIter);
518 aVerts->BindAttribute (theCtx, Graphic3d_TOA_POS);
519 aTCrds->BindAttribute (theCtx, Graphic3d_TOA_UV);
521 theCtx->core11fwd->glDrawArrays (GL_TRIANGLES, 0, GLsizei(aVerts->GetElemsNb()));
523 aTCrds->UnbindAttribute (theCtx, Graphic3d_TOA_UV);
524 aVerts->UnbindAttribute (theCtx, Graphic3d_TOA_POS);
526 theCtx->core11fwd->glBindTexture (GL_TEXTURE_2D, 0);
529 // =======================================================================
530 // function : FontKey
532 // =======================================================================
533 TCollection_AsciiString OpenGl_Text::FontKey (const OpenGl_Aspects& theAspect,
534 Standard_Integer theHeight,
535 unsigned int theResolution,
536 Font_Hinting theFontHinting)
538 const Font_FontAspect anAspect = theAspect.Aspect()->TextFontAspect() != Font_FA_Undefined
539 ? theAspect.Aspect()->TextFontAspect()
541 const TCollection_AsciiString& aFont = !theAspect.Aspect()->TextFont().IsNull() ? theAspect.Aspect()->TextFont()->String() : THE_DEFAULT_FONT;
544 Sprintf (aSuff, ":%d:%d:%d:%d",
545 Standard_Integer(anAspect),
546 Standard_Integer(theResolution),
548 Standard_Integer(theFontHinting));
549 return aFont + aSuff;
552 // =======================================================================
553 // function : FindFont
555 // =======================================================================
556 Handle(OpenGl_Font) OpenGl_Text::FindFont (const Handle(OpenGl_Context)& theCtx,
557 const OpenGl_Aspects& theAspect,
558 Standard_Integer theHeight,
559 unsigned int theResolution,
560 Font_Hinting theFontHinting,
561 const TCollection_AsciiString& theKey)
563 Handle(OpenGl_Font) aFont;
566 return aFont; // invalid parameters
569 if (!theCtx->GetResource (theKey, aFont))
571 Handle(Font_FontMgr) aFontMgr = Font_FontMgr::GetInstance();
572 const TCollection_AsciiString& aFontName = !theAspect.Aspect()->TextFont().IsNull()
573 ? theAspect.Aspect()->TextFont()->String()
575 Font_FontAspect anAspect = theAspect.Aspect()->TextFontAspect() != Font_FA_Undefined
576 ? theAspect.Aspect()->TextFontAspect()
578 Font_FTFontParams aParams;
579 aParams.PointSize = theHeight;
580 aParams.Resolution = theResolution;
581 aParams.FontHinting = theFontHinting;
582 if (Handle(Font_FTFont) aFontFt = Font_FTFont::FindAndCreate (aFontName, anAspect, aParams, Font_StrictLevel_Any))
584 aFont = new OpenGl_Font (aFontFt, theKey);
585 if (!aFont->Init (theCtx))
587 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
588 TCollection_AsciiString ("Font '") + aFontName + "' - initialization of GL resources has failed!");
590 aFont->Release (theCtx.get());
591 aFont = new OpenGl_Font (aFontFt, theKey);
596 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
597 TCollection_AsciiString ("Font '") + aFontName + "' is not found in the system!");
598 aFont = new OpenGl_Font (aFontFt, theKey);
601 theCtx->ShareResource (theKey, aFont);
606 // =======================================================================
607 // function : drawRect
609 // =======================================================================
610 void OpenGl_Text::drawRect (const Handle(OpenGl_Context)& theCtx,
611 const OpenGl_Aspects& theTextAspect,
612 const OpenGl_Vec4& theColorSubs) const
614 Handle(OpenGl_ShaderProgram) aPrevProgram = theCtx->ActiveProgram();
615 if (myBndVertsVbo.IsNull())
617 OpenGl_Vec2 aQuad[4] =
619 OpenGl_Vec2(myBndBox.Right, myBndBox.Bottom),
620 OpenGl_Vec2(myBndBox.Right, myBndBox.Top),
621 OpenGl_Vec2(myBndBox.Left, myBndBox.Bottom),
622 OpenGl_Vec2(myBndBox.Left, myBndBox.Top)
624 if (theCtx->ToUseVbo())
626 myBndVertsVbo = new OpenGl_VertexBuffer();
630 myBndVertsVbo = new OpenGl_VertexBufferCompat();
632 myBndVertsVbo->Init (theCtx, 2, 4, aQuad[0].GetData());
635 // bind unlit program
636 theCtx->ShaderManager()->BindFaceProgram (Handle(OpenGl_TextureSet)(), Graphic3d_TypeOfShadingModel_Unlit,
637 Graphic3d_AlphaMode_Opaque, Standard_False, Standard_False,
638 Handle(OpenGl_ShaderProgram)());
640 if (theCtx->core11ffp != NULL
641 && theCtx->ActiveProgram().IsNull())
643 theCtx->core11fwd->glBindTexture (GL_TEXTURE_2D, 0);
646 theCtx->SetColor4fv (theColorSubs);
647 setupMatrix (theCtx, theTextAspect, OpenGl_Vec3 (0.0f, 0.0f, 0.0f));
648 myBndVertsVbo->BindAttribute (theCtx, Graphic3d_TOA_POS);
650 theCtx->core20fwd->glDrawArrays (GL_TRIANGLE_STRIP, 0, 4);
652 myBndVertsVbo->UnbindAttribute (theCtx, Graphic3d_TOA_POS);
653 theCtx->BindProgram (aPrevProgram);
656 // =======================================================================
659 // =======================================================================
660 void OpenGl_Text::render (const Handle(OpenGl_Context)& theCtx,
661 const OpenGl_Aspects& theTextAspect,
662 const OpenGl_Vec4& theColorText,
663 const OpenGl_Vec4& theColorSubs,
664 unsigned int theResolution,
665 Font_Hinting theFontHinting) const
667 if (myText->Text().IsEmpty() && myText->TextFormatter().IsNull())
672 // Note that using difference resolution in different Views in same Viewer
673 // will lead to performance regression (for example, text will be recreated every time).
674 const TCollection_AsciiString aFontKey = FontKey (theTextAspect, (Standard_Integer)myText->Height(), theResolution, theFontHinting);
676 && !myFont->ResourceKey().IsEqual (aFontKey))
679 const_cast<OpenGl_Text* > (this)->Release (theCtx.operator->());
684 myFont = FindFont (theCtx, theTextAspect, (Standard_Integer)myText->Height(), theResolution, theFontHinting, aFontKey);
687 || !myFont->WasInitialized())
692 if (myTextures.IsEmpty())
694 Handle(Font_TextFormatter) aFormatter = myText->TextFormatter();
695 if (aFormatter.IsNull())
697 aFormatter = new Font_TextFormatter();
699 aFormatter->SetupAlignment (myText->HorizontalAlignment(), myText->VerticalAlignment());
702 aFormatter->Append (myText->Text(), *myFont->FTFont());
703 aFormatter->Format();
705 OpenGl_TextBuilder aBuilder;
706 aBuilder.Perform (aFormatter,
708 *myFont.operator->(),
713 aFormatter->BndBox (myBndBox);
714 if (!myBndVertsVbo.IsNull())
716 myBndVertsVbo->Release (theCtx.get());
717 myBndVertsVbo.Nullify();
721 if (myTextures.IsEmpty())
726 myScaleHeight = 1.0f;
728 theCtx->WorldViewState.Push();
729 myModelMatrix.Convert (theCtx->WorldViewState.Current() * theCtx->ModelWorldState.Current());
731 const GLdouble aPointSize = (GLdouble )myFont->FTFont()->PointSize();
734 const gp_Pnt& aPoint = myText->Position();
735 Graphic3d_TransformUtils::Project<Standard_Real> (aPoint.X(), aPoint.Y(), aPoint.Z(),
736 myModelMatrix, myProjMatrix, theCtx->Viewport(),
737 myWinXYZ.x(), myWinXYZ.y(), myWinXYZ.z());
739 // compute scale factor for constant text height
740 if (!theTextAspect.Aspect()->IsTextZoomable())
742 Graphic3d_Vec3d aPnt1, aPnt2;
743 Graphic3d_TransformUtils::UnProject<Standard_Real> (myWinXYZ.x(), myWinXYZ.y(), myWinXYZ.z(),
744 THE_IDENTITY_MATRIX, myProjMatrix, theCtx->Viewport(),
745 aPnt1.x(), aPnt1.y(), aPnt1.z());
746 Graphic3d_TransformUtils::UnProject<Standard_Real> (myWinXYZ.x(), myWinXYZ.y() + aPointSize, myWinXYZ.z(),
747 THE_IDENTITY_MATRIX, myProjMatrix, theCtx->Viewport(),
748 aPnt2.x(), aPnt2.y(), aPnt2.z());
749 myScaleHeight = (aPnt2.y() - aPnt1.y()) / aPointSize;
753 if (theCtx->core11ffp != NULL
754 && theCtx->caps->ffpEnable)
756 theCtx->core11fwd->glDisable (GL_LIGHTING);
760 const bool hasDepthTest = !myIs2d
761 && theTextAspect.Aspect()->TextStyle() != Aspect_TOST_ANNOTATION;
764 theCtx->core11fwd->glDisable (GL_DEPTH_TEST);
767 if (theCtx->core15fwd != NULL)
769 theCtx->core15fwd->glActiveTexture (GL_TEXTURE0);
772 // activate texture unit
773 if (theCtx->core11ffp != NULL && theCtx->ActiveProgram().IsNull())
775 const Handle(OpenGl_Texture)& aTexture = myFont->Texture();
776 OpenGl_Sampler::applyGlobalTextureParams (theCtx, *aTexture, aTexture->Sampler()->Parameters());
780 if (theTextAspect.Aspect()->AlphaMode() == Graphic3d_AlphaMode_MaskBlend)
782 theCtx->core11fwd->glEnable (GL_BLEND);
783 theCtx->core11fwd->glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
786 // alpha to coverage makes text too thin
787 theCtx->SetSampleAlphaToCoverage (false);
790 switch (theTextAspect.Aspect()->TextDisplayType())
792 case Aspect_TODT_BLEND:
794 if (theCtx->GraphicsLibrary() == Aspect_GraphicsLibrary_OpenGL)
796 theCtx->core11fwd->glEnable (GL_COLOR_LOGIC_OP);
797 theCtx->core11fwd->glLogicOp (GL_XOR);
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 (theCtx->core11ffp != NULL && theCtx->ActiveProgram().IsNull())
849 const Handle(OpenGl_Texture)& aTexture = myFont->Texture();
850 OpenGl_Sampler::resetGlobalTextureParams (theCtx, *aTexture, aTexture->Sampler()->Parameters());
853 if (theTextAspect.Aspect()->TextDisplayType() == Aspect_TODT_DIMENSION)
855 if (theTextAspect.Aspect()->AlphaMode() == Graphic3d_AlphaMode_MaskBlend)
857 theCtx->core11fwd->glDisable (GL_BLEND);
861 theCtx->core11fwd->glDisable (GL_DEPTH_TEST);
863 if (theCtx->core11ffp != NULL)
865 theCtx->core11fwd->glDisable (GL_TEXTURE_2D);
868 const bool aColorMaskBack = theCtx->SetColorMask (false);
870 theCtx->core11fwd->glClear (GL_STENCIL_BUFFER_BIT);
871 theCtx->core11fwd->glEnable (GL_STENCIL_TEST);
872 theCtx->core11fwd->glStencilFunc (GL_ALWAYS, 1, 0xFF);
873 theCtx->core11fwd->glStencilOp (GL_KEEP, GL_KEEP, GL_REPLACE);
875 drawRect (theCtx, theTextAspect, OpenGl_Vec4 (1.0f, 1.0f, 1.0f, 1.0f));
877 theCtx->core11fwd->glStencilFunc (GL_ALWAYS, 0, 0xFF);
879 theCtx->SetColorMask (aColorMaskBack);
882 // reset OpenGL state
883 if (theTextAspect.Aspect()->AlphaMode() == Graphic3d_AlphaMode_MaskBlend)
885 theCtx->core11fwd->glDisable (GL_BLEND);
887 theCtx->core11fwd->glDisable (GL_STENCIL_TEST);
888 if (theCtx->GraphicsLibrary() == Aspect_GraphicsLibrary_OpenGL)
890 theCtx->core11fwd->glDisable (GL_COLOR_LOGIC_OP);
893 // model view matrix was modified
894 theCtx->WorldViewState.Pop();
895 theCtx->ApplyModelViewMatrix();
898 // =======================================================================
899 // function : DumpJson
901 // =======================================================================
902 void OpenGl_Text::DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth) const
904 OCCT_DUMP_CLASS_BEGIN (theOStream, OpenGl_Text)
905 OCCT_DUMP_BASE_CLASS (theOStream, theDepth, OpenGl_Element)
907 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myTextures.Size())
909 for (NCollection_Vector<Handle(OpenGl_VertexBuffer)>::Iterator aCrdsIt (myTCrdsVbo); aCrdsIt.More(); aCrdsIt.Next())
911 const Handle(OpenGl_VertexBuffer)& aVertexBuffer = aCrdsIt.Value();
912 OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, aVertexBuffer.get())
915 OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &myBndBox)