0027961: Visualization - remove unused and no more working OpenGl_AVIWriter
[occt.git] / src / OpenGl / OpenGl_Text.cxx
CommitLineData
b311480e 1// Created on: 2011-07-13
2// Created by: Sergey ZERCHANINOV
a174a3c5 3// Copyright (c) 2011-2013 OPEN CASCADE SAS
b311480e 4//
973c2be1 5// This file is part of Open CASCADE Technology software library.
b311480e 6//
d5f74e42 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
973c2be1 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.
b311480e 12//
973c2be1 13// Alternatively, this file may be used under the terms of Open CASCADE
14// commercial license or contractual agreement.
b311480e 15
2166f0fa 16#include <OpenGl_AspectText.hxx>
30f0ad28 17#include <OpenGl_GlCore11.hxx>
a174a3c5 18#include <OpenGl_GraphicDriver.hxx>
30f0ad28 19#include <OpenGl_ShaderManager.hxx>
20#include <OpenGl_ShaderProgram.hxx>
21#include <OpenGl_ShaderStates.hxx>
22#include <OpenGl_Text.hxx>
bf75be98 23#include <OpenGl_Workspace.hxx>
ce01ec26 24#include <OpenGl_View.hxx>
2166f0fa 25
a174a3c5 26#include <Font_FontMgr.hxx>
d2eddacc 27#include <Font_FTFont.hxx>
825aa485 28#include <Graphic3d_TransformUtils.hxx>
a174a3c5 29#include <TCollection_HAsciiString.hxx>
30
a174a3c5 31#ifdef HAVE_GL2PS
32 #include <gl2ps.h>
33#endif
34
35namespace
2166f0fa 36{
c827ea3a 37 static const GLdouble THE_IDENTITY_MATRIX[16] =
a174a3c5 38 {
c827ea3a 39 1.0, 0.0, 0.0, 0.0,
40 0.0, 1.0, 0.0, 0.0,
41 0.0, 0.0, 1.0, 0.0,
42 0.0, 0.0, 0.0, 1.0
a174a3c5 43 };
44
45#ifdef HAVE_GL2PS
46 static char const* TheFamily[] = {"Helvetica", "Courier", "Times"};
47 static char const* TheItalic[] = {"Oblique", "Oblique", "Italic"};
48 static char const* TheBase[] = {"", "", "-Roman"};
49
50 //! Convert font name used for rendering to some "good" font names
51 //! that produce good vector text.
52 static void getGL2PSFontName (const char* theSrcFont,
53 char* thePsFont)
54 {
55 if (strstr (theSrcFont, "Symbol"))
56 {
57 sprintf (thePsFont, "%s", "Symbol");
58 return;
59 }
60 else if (strstr (theSrcFont, "ZapfDingbats"))
61 {
62 sprintf (thePsFont, "%s", "WingDings");
63 return;
64 }
2166f0fa 65
a174a3c5 66 int aFontId = 0;
67 bool isBold = false;
68 bool isItalic = false;
69 if (strstr (theSrcFont, "Courier"))
70 {
71 aFontId = 1;
72 }
73 else if (strstr (theSrcFont, "Times"))
74 {
75 aFontId = 2;
76 }
2166f0fa 77
a174a3c5 78 if (strstr (theSrcFont, "Bold"))
79 {
80 isBold = true;
81 }
82 if (strstr (theSrcFont, "Italic")
83 || strstr (theSrcFont, "Oblique"))
84 {
85 isItalic = true;
86 }
2166f0fa 87
a174a3c5 88 if (isBold)
89 {
a174a3c5 90 if (isItalic)
91 {
8b224a09 92 sprintf (thePsFont, "%s-Bold%s", TheFamily[aFontId], TheItalic[aFontId]);
93 }
94 else
95 {
96 sprintf (thePsFont, "%s-Bold", TheFamily[aFontId]);
a174a3c5 97 }
98 }
99 else if (isItalic)
100 {
101 sprintf (thePsFont, "%s-%s", TheFamily[aFontId], TheItalic[aFontId]);
102 }
103 else
104 {
105 sprintf (thePsFont, "%s%s", TheFamily[aFontId], TheBase[aFontId]);
106 }
107 }
2166f0fa 108
a174a3c5 109 static void exportText (const NCollection_String& theText,
110 const Standard_Boolean theIs2d,
111 const OpenGl_AspectText& theAspect,
112 const Standard_Integer theHeight)
113 {
2166f0fa 114
a174a3c5 115 char aPsFont[64];
b6472664 116 getGL2PSFontName (theAspect.Aspect()->Font().ToCString(), aPsFont);
2166f0fa 117
ca3c13d1 118 #if !defined(GL_ES_VERSION_2_0)
a174a3c5 119 if (theIs2d)
120 {
121 glRasterPos2f (0.0f, 0.0f);
122 }
123 else
124 {
125 glRasterPos3f (0.0f, 0.0f, 0.0f);
126 }
127
128 GLubyte aZero = 0;
129 glBitmap (1, 1, 0, 0, 0, 0, &aZero);
ca3c13d1 130 #endif
a174a3c5 131
132 // Standard GL2PS's alignment isn't used, because it doesn't work correctly
133 // for all formats, therefore alignment is calculated manually relative
134 // to the bottom-left corner, which corresponds to the GL2PS_TEXT_BL value
b6472664 135 gl2psTextOpt (theText.ToCString(), aPsFont, (GLshort)theHeight, GL2PS_TEXT_BL, (float )theAspect.Aspect()->GetTextAngle());
a174a3c5 136 }
137#endif
138
68858c7d 139} // anonymous namespace
a174a3c5 140
141// =======================================================================
142// function : OpenGl_Text
143// purpose :
144// =======================================================================
145OpenGl_Text::OpenGl_Text()
146: myWinX (0.0f),
147 myWinY (0.0f),
148 myWinZ (0.0f),
149 myScaleHeight (1.0f),
150 myPoint (0.0f, 0.0f, 0.0f),
ce01ec26 151 myIs2d (false),
3f1eb0ab 152 myHasPlane (false),
153 myHasAnchorPoint (true)
a174a3c5 154{
155 myParams.Height = 10;
156 myParams.HAlign = Graphic3d_HTA_LEFT;
157 myParams.VAlign = Graphic3d_VTA_BOTTOM;
2166f0fa
SK
158}
159
a174a3c5 160// =======================================================================
161// function : OpenGl_Text
162// purpose :
163// =======================================================================
b64d84be 164OpenGl_Text::OpenGl_Text (const Standard_Utf8Char* theText,
165 const OpenGl_Vec3& thePoint,
166 const OpenGl_TextParam& theParams)
a174a3c5 167: myWinX (0.0f),
168 myWinY (0.0f),
169 myWinZ (0.0f),
170 myScaleHeight (1.0f),
171 myExportHeight (1.0f),
172 myParams (theParams),
b64d84be 173 myString (theText),
a174a3c5 174 myPoint (thePoint),
ce01ec26 175 myIs2d (false),
3f1eb0ab 176 myHasPlane (false),
177 myHasAnchorPoint (true)
a174a3c5 178{
179 //
180}
2166f0fa 181
ce01ec26 182// =======================================================================
183// function : OpenGl_Text
184// purpose :
185// =======================================================================
186OpenGl_Text::OpenGl_Text (const Standard_Utf8Char* theText,
187 const gp_Ax2& theOrientation,
3f1eb0ab 188 const OpenGl_TextParam& theParams,
189 const bool theHasOwnAnchor)
ce01ec26 190: myWinX (0.0),
191 myWinY (0.0),
192 myWinZ (0.0),
193 myScaleHeight (1.0),
194 myExportHeight (1.0),
195 myParams (theParams),
196 myString (theText),
197 myIs2d (false),
198 myOrientation (theOrientation),
3f1eb0ab 199 myHasPlane (true),
200 myHasAnchorPoint (theHasOwnAnchor)
ce01ec26 201{
202 const gp_Pnt& aPoint = theOrientation.Location();
203 myPoint = OpenGl_Vec3 (static_cast<Standard_ShortReal> (aPoint.X()),
204 static_cast<Standard_ShortReal> (aPoint.Y()),
205 static_cast<Standard_ShortReal> (aPoint.Z()));
206}
207
a174a3c5 208// =======================================================================
209// function : SetPosition
210// purpose :
211// =======================================================================
212void OpenGl_Text::SetPosition (const OpenGl_Vec3& thePoint)
2166f0fa 213{
a174a3c5 214 myPoint = thePoint;
2166f0fa
SK
215}
216
a174a3c5 217// =======================================================================
218// function : SetFontSize
219// purpose :
220// =======================================================================
221void OpenGl_Text::SetFontSize (const Handle(OpenGl_Context)& theCtx,
222 const Standard_Integer theFontSize)
223{
224 if (myParams.Height != theFontSize)
225 {
10b9c7df 226 Release (theCtx.operator->());
a174a3c5 227 }
228 myParams.Height = theFontSize;
229}
230
231// =======================================================================
232// function : Init
233// purpose :
234// =======================================================================
235void OpenGl_Text::Init (const Handle(OpenGl_Context)& theCtx,
236 const Standard_Utf8Char* theText,
237 const OpenGl_Vec3& thePoint)
238{
10b9c7df 239 releaseVbos (theCtx.operator->());
a174a3c5 240 myIs2d = false;
241 myPoint = thePoint;
242 myString.FromUnicode (theText);
243}
244
245// =======================================================================
246// function : Init
247// purpose :
248// =======================================================================
249void OpenGl_Text::Init (const Handle(OpenGl_Context)& theCtx,
250 const Standard_Utf8Char* theText,
251 const OpenGl_Vec3& thePoint,
252 const OpenGl_TextParam& theParams)
253{
254 if (myParams.Height != theParams.Height)
255 {
10b9c7df 256 Release (theCtx.operator->());
a174a3c5 257 }
258 else
259 {
10b9c7df 260 releaseVbos (theCtx.operator->());
a174a3c5 261 }
262 myIs2d = false;
263 myParams = theParams;
264 myPoint = thePoint;
265 myString.FromUnicode (theText);
266}
2166f0fa 267
a174a3c5 268// =======================================================================
269// function : Init
270// purpose :
271// =======================================================================
272void OpenGl_Text::Init (const Handle(OpenGl_Context)& theCtx,
273 const TCollection_ExtendedString& theText,
274 const OpenGl_Vec2& thePoint,
275 const OpenGl_TextParam& theParams)
2166f0fa 276{
a174a3c5 277 if (myParams.Height != theParams.Height)
278 {
10b9c7df 279 Release (theCtx.operator->());
a174a3c5 280 }
281 else
282 {
10b9c7df 283 releaseVbos (theCtx.operator->());
a174a3c5 284 }
285 myIs2d = true;
286 myParams = theParams;
287 myPoint.xy() = thePoint;
288 myPoint.z() = 0.0f;
fb0b0531 289 myString.FromUnicode (theText.ToExtString());
a174a3c5 290}
291
292// =======================================================================
293// function : ~OpenGl_Text
294// purpose :
295// =======================================================================
296OpenGl_Text::~OpenGl_Text()
297{
298 //
299}
300
301// =======================================================================
302// function : releaseVbos
303// purpose :
304// =======================================================================
10b9c7df 305void OpenGl_Text::releaseVbos (OpenGl_Context* theCtx)
a174a3c5 306{
307 for (Standard_Integer anIter = 0; anIter < myVertsVbo.Length(); ++anIter)
308 {
309 Handle(OpenGl_VertexBuffer)& aVerts = myVertsVbo.ChangeValue (anIter);
310 Handle(OpenGl_VertexBuffer)& aTCrds = myTCrdsVbo.ChangeValue (anIter);
311
10b9c7df 312 if (theCtx)
a174a3c5 313 {
314 theCtx->DelayedRelease (aVerts);
315 theCtx->DelayedRelease (aTCrds);
316 }
317 aVerts.Nullify();
318 aTCrds.Nullify();
319 }
320 myTextures.Clear();
321 myVertsVbo.Clear();
322 myTCrdsVbo.Clear();
a174a3c5 323}
324
325// =======================================================================
326// function : Release
327// purpose :
328// =======================================================================
10b9c7df 329void OpenGl_Text::Release (OpenGl_Context* theCtx)
a174a3c5 330{
331 releaseVbos (theCtx);
332 if (!myFont.IsNull())
333 {
334 Handle(OpenGl_Context) aCtx = theCtx;
335 const TCollection_AsciiString aKey = myFont->ResourceKey();
336 myFont.Nullify();
c04c30b3 337 if (! aCtx.IsNull())
10b9c7df 338 aCtx->ReleaseResource (aKey, Standard_True);
a174a3c5 339 }
340}
341
342// =======================================================================
343// function : StringSize
344// purpose :
345// =======================================================================
346void OpenGl_Text::StringSize (const Handle(OpenGl_Context)& theCtx,
347 const NCollection_String& theText,
348 const OpenGl_AspectText& theTextAspect,
349 const OpenGl_TextParam& theParams,
4b1c8733 350 const unsigned int theResolution,
a174a3c5 351 Standard_ShortReal& theWidth,
352 Standard_ShortReal& theAscent,
353 Standard_ShortReal& theDescent)
354{
355 theWidth = 0.0f;
356 theAscent = 0.0f;
357 theDescent = 0.0f;
4b1c8733 358 const TCollection_AsciiString aFontKey = FontKey (theTextAspect, theParams.Height, theResolution);
359 Handle(OpenGl_Font) aFont = FindFont (theCtx, theTextAspect, theParams.Height, theResolution, aFontKey);
a174a3c5 360 if (aFont.IsNull() || !aFont->IsValid())
361 {
2166f0fa 362 return;
a174a3c5 363 }
364
365 theAscent = aFont->Ascender();
366 theDescent = aFont->Descender();
367
368 GLfloat aWidth = 0.0f;
369 for (NCollection_Utf8Iter anIter = theText.Iterator(); *anIter != 0;)
370 {
371 const Standard_Utf32Char aCharThis = *anIter;
372 const Standard_Utf32Char aCharNext = *++anIter;
373
374 if (aCharThis == '\x0D' // CR (carriage return)
375 || aCharThis == '\a' // BEL (alarm)
376 || aCharThis == '\f' // FF (form feed) NP (new page)
377 || aCharThis == '\b' // BS (backspace)
378 || aCharThis == '\v') // VT (vertical tab)
379 {
380 continue; // skip unsupported carriage control codes
381 }
382 else if (aCharThis == '\x0A') // LF (line feed, new line)
383 {
384 theWidth = Max (theWidth, aWidth);
385 aWidth = 0.0f;
386 continue;
387 }
388 else if (aCharThis == ' ')
389 {
d2eddacc 390 aWidth += aFont->FTFont()->AdvanceX (aCharThis, aCharNext);
a174a3c5 391 continue;
392 }
393 else if (aCharThis == '\t')
394 {
d2eddacc 395 aWidth += aFont->FTFont()->AdvanceX (' ', aCharNext) * 8.0f;
a174a3c5 396 continue;
397 }
398
d2eddacc 399 aWidth += aFont->FTFont()->AdvanceX (aCharThis, aCharNext);
a174a3c5 400 }
401 theWidth = Max (theWidth, aWidth);
402
403 Handle(OpenGl_Context) aCtx = theCtx;
404 aFont.Nullify();
405 aCtx->ReleaseResource (aFontKey, Standard_True);
406}
407
408// =======================================================================
409// function : Render
410// purpose :
411// =======================================================================
412void OpenGl_Text::Render (const Handle(OpenGl_Workspace)& theWorkspace) const
413{
f9ba5c4d 414 const OpenGl_AspectText* aTextAspect = theWorkspace->ApplyAspectText();
25ef750e 415 const Handle(OpenGl_Texture) aPrevTexture = theWorkspace->DisableTexture();
416 const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
6d0e6be5 417#if !defined(GL_ES_VERSION_2_0)
418 const Standard_Integer aPrevPolygonMode = aCtx->SetPolygonMode (GL_FILL);
419 const bool aPrevHatchingMode = aCtx->SetPolygonHatchEnabled (false);
420#endif
30f0ad28 421
b990e557 422 // Bind custom shader program or generate default version
4e1523ef 423 if (aCtx->core20fwd != NULL)
30f0ad28 424 {
299e0ab9 425 aCtx->ShaderManager()->BindFontProgram (aTextAspect->ShaderProgramRes (aCtx));
30f0ad28 426 }
427
c357e426 428 myOrientationMatrix = theWorkspace->View()->Camera()->OrientationMatrix();
ce01ec26 429 myProjMatrix.Convert (aCtx->ProjectionState.Current());
430
a174a3c5 431 // use highlight color or colors from aspect
60273f77 432 render (aCtx,
f9ba5c4d 433 *aTextAspect,
434 theWorkspace->TextColor(),
435 theWorkspace->TextSubtitleColor(),
436 theWorkspace->View()->RenderingParams().Resolution);
2166f0fa 437
c6ad5e5f 438 aCtx->BindProgram (NULL);
439
a174a3c5 440 // restore aspects
441 if (!aPrevTexture.IsNull())
442 {
443 theWorkspace->EnableTexture (aPrevTexture);
444 }
6d0e6be5 445#if !defined(GL_ES_VERSION_2_0)
446 aCtx->SetPolygonMode (aPrevPolygonMode);
447 aCtx->SetPolygonHatchEnabled (aPrevHatchingMode);
448#endif
b34efb62 449
450 // restore Z buffer settings
eae454e3 451 if (theWorkspace->UseZBuffer())
b34efb62 452 {
453 glEnable (GL_DEPTH_TEST);
454 }
a174a3c5 455}
2166f0fa 456
a174a3c5 457// =======================================================================
458// function : Render
459// purpose :
460// =======================================================================
60273f77 461void OpenGl_Text::Render (const Handle(OpenGl_Context)& theCtx,
462 const OpenGl_AspectText& theTextAspect,
463 const unsigned int theResolution) const
a174a3c5 464{
60273f77 465 render (theCtx, theTextAspect,
b6472664 466 theTextAspect.Aspect()->ColorRGBA(),
467 theTextAspect.Aspect()->ColorSubTitleRGBA(),
468 theResolution);
a174a3c5 469}
2166f0fa 470
a174a3c5 471// =======================================================================
472// function : setupMatrix
473// purpose :
474// =======================================================================
60273f77 475void OpenGl_Text::setupMatrix (const Handle(OpenGl_Context)& theCtx,
476 const OpenGl_AspectText& theTextAspect,
477 const OpenGl_Vec3 theDVec) const
a174a3c5 478{
c827ea3a 479 OpenGl_Mat4d aModViewMat;
ce01ec26 480 OpenGl_Mat4d aProjectMat;
3f1eb0ab 481 if (myHasPlane && myHasAnchorPoint)
ce01ec26 482 {
483 aProjectMat = myProjMatrix * myOrientationMatrix;
484 }
485 else
486 {
487 aProjectMat = myProjMatrix;
488 }
c827ea3a 489
a174a3c5 490 if (myIs2d)
bf75be98 491 {
825aa485 492 Graphic3d_TransformUtils::Translate<GLdouble> (aModViewMat, myPoint.x() + theDVec.x(), myPoint.y() + theDVec.y(), 0.f);
493 Graphic3d_TransformUtils::Scale<GLdouble> (aModViewMat, 1.f, -1.f, 1.f);
b6472664 494 Graphic3d_TransformUtils::Rotate<GLdouble> (aModViewMat, theTextAspect.Aspect()->GetTextAngle(), 0.f, 0.f, 1.f);
2166f0fa
SK
495 }
496 else
497 {
a174a3c5 498 // align coordinates to the nearest integer
499 // to avoid extra interpolation issues
500 GLdouble anObjX, anObjY, anObjZ;
825aa485 501 Graphic3d_TransformUtils::UnProject<Standard_Real> (std::floor (myWinX + theDVec.x()),
502 std::floor (myWinY + theDVec.y()),
503 myWinZ + theDVec.z(),
504 OpenGl_Mat4d::Map (THE_IDENTITY_MATRIX),
ce01ec26 505 OpenGl_Mat4d::Map (aProjectMat),
3bffef55 506 theCtx->Viewport(),
825aa485 507 anObjX,
508 anObjY,
509 anObjZ);
510
ce01ec26 511 if (myHasPlane)
512 {
513 const gp_Dir& aVectorDir = myOrientation.XDirection();
514 const gp_Dir& aVectorUp = myOrientation.Direction();
515 const gp_Dir& aVectorRight = myOrientation.YDirection();
516
ce01ec26 517 aModViewMat.SetColumn (2, OpenGl_Vec3d (aVectorUp.X(), aVectorUp.Y(), aVectorUp.Z()));
518 aModViewMat.SetColumn (1, OpenGl_Vec3d (aVectorRight.X(), aVectorRight.Y(), aVectorRight.Z()));
519 aModViewMat.SetColumn (0, OpenGl_Vec3d (aVectorDir.X(), aVectorDir.Y(), aVectorDir.Z()));
3f1eb0ab 520
521 if (!myHasAnchorPoint)
522 {
523 OpenGl_Mat4d aPosMat;
524 aPosMat.SetColumn (3, OpenGl_Vec3d (myPoint.x(), myPoint.y(), myPoint.z()));
525 aPosMat *= aModViewMat;
526 aModViewMat.SetColumn (3, aPosMat.GetColumn (3));
527 }
528 else
529 {
530 aModViewMat.SetColumn (3, OpenGl_Vec3d (anObjX, anObjY, anObjZ));
531 }
ce01ec26 532 }
533 else
534 {
535 Graphic3d_TransformUtils::Translate<GLdouble> (aModViewMat, anObjX, anObjY, anObjZ);
b6472664 536 Graphic3d_TransformUtils::Rotate<GLdouble> (aModViewMat, theTextAspect.Aspect()->GetTextAngle(), 0.0, 0.0, 1.0);
ce01ec26 537 }
825aa485 538
b6472664 539 if (!theTextAspect.Aspect()->GetTextZoomable())
a174a3c5 540 {
825aa485 541 Graphic3d_TransformUtils::Scale<GLdouble> (aModViewMat, myScaleHeight, myScaleHeight, myScaleHeight);
a174a3c5 542 }
543 }
c827ea3a 544
3f1eb0ab 545 if (myHasPlane && !myHasAnchorPoint)
546 {
547 OpenGl_Mat4d aCurrentWorldViewMat;
548 aCurrentWorldViewMat.Convert (theCtx->WorldViewState.Current());
549 theCtx->WorldViewState.SetCurrent<Standard_Real> (aCurrentWorldViewMat * aModViewMat);
550 }
551 else
552 {
553 theCtx->WorldViewState.SetCurrent<Standard_Real> (aModViewMat);
554 }
c827ea3a 555 theCtx->ApplyWorldViewMatrix();
b990e557 556
ce01ec26 557 if (!myIs2d)
558 {
559 theCtx->ProjectionState.SetCurrent<Standard_Real> (aProjectMat);
560 theCtx->ApplyProjectionMatrix();
561 }
562
b990e557 563 if (!theCtx->ActiveProgram().IsNull())
564 {
565 // Upload updated state to shader program
566 theCtx->ShaderManager()->PushState (theCtx->ActiveProgram());
567 }
a174a3c5 568}
569
570// =======================================================================
571// function : drawText
572// purpose :
573// =======================================================================
60273f77 574void OpenGl_Text::drawText (const Handle(OpenGl_Context)& theCtx,
575 const OpenGl_AspectText& theTextAspect) const
a174a3c5 576{
577#ifdef HAVE_GL2PS
578 if (theCtx->IsFeedback())
579 {
580 // position of the text and alignment is calculated by transformation matrix
581 exportText (myString, myIs2d, theTextAspect, (Standard_Integer )myExportHeight);
582 return;
2166f0fa 583 }
60273f77 584#else
585 (void )theTextAspect;
a174a3c5 586#endif
2166f0fa 587
7d3e64ef 588 if (myVertsVbo.Length() != myTextures.Length()
589 || myTextures.IsEmpty())
2166f0fa 590 {
7d3e64ef 591 return;
2166f0fa 592 }
7d3e64ef 593
594 for (Standard_Integer anIter = 0; anIter < myTextures.Length(); ++anIter)
a174a3c5 595 {
7d3e64ef 596 const GLuint aTexId = myTextures.Value (anIter);
597 glBindTexture (GL_TEXTURE_2D, aTexId);
a174a3c5 598
7d3e64ef 599 const Handle(OpenGl_VertexBuffer)& aVerts = myVertsVbo.Value (anIter);
600 const Handle(OpenGl_VertexBuffer)& aTCrds = myTCrdsVbo.Value (anIter);
601 aVerts->BindAttribute (theCtx, Graphic3d_TOA_POS);
602 aTCrds->BindAttribute (theCtx, Graphic3d_TOA_UV);
2166f0fa 603
7d3e64ef 604 glDrawArrays (GL_TRIANGLES, 0, GLsizei(aVerts->GetElemsNb()));
2166f0fa 605
b990e557 606 aTCrds->UnbindAttribute (theCtx, Graphic3d_TOA_UV);
7d3e64ef 607 aVerts->UnbindAttribute (theCtx, Graphic3d_TOA_POS);
a174a3c5 608 }
7d3e64ef 609 glBindTexture (GL_TEXTURE_2D, 0);
a174a3c5 610}
2166f0fa 611
a174a3c5 612// =======================================================================
613// function : FontKey
614// purpose :
615// =======================================================================
616TCollection_AsciiString OpenGl_Text::FontKey (const OpenGl_AspectText& theAspect,
4b1c8733 617 const Standard_Integer theHeight,
618 const unsigned int theResolution)
a174a3c5 619{
b6472664 620 const Font_FontAspect anAspect = theAspect.Aspect()->GetTextFontAspect() != Font_FA_Undefined
621 ? theAspect.Aspect()->GetTextFontAspect()
622 : Font_FA_Regular;
623 return theAspect.Aspect()->Font()
a174a3c5 624 + TCollection_AsciiString(":") + Standard_Integer(anAspect)
4b1c8733 625 + TCollection_AsciiString(":") + Standard_Integer(theResolution)
a174a3c5 626 + TCollection_AsciiString(":") + theHeight;
627}
628
629// =======================================================================
630// function : FindFont
631// purpose :
632// =======================================================================
633Handle(OpenGl_Font) OpenGl_Text::FindFont (const Handle(OpenGl_Context)& theCtx,
634 const OpenGl_AspectText& theAspect,
635 const Standard_Integer theHeight,
4b1c8733 636 const unsigned int theResolution,
a174a3c5 637 const TCollection_AsciiString theKey)
638{
639 Handle(OpenGl_Font) aFont;
640 if (theHeight < 2)
2166f0fa 641 {
a174a3c5 642 return aFont; // invalid parameters
643 }
2166f0fa 644
a174a3c5 645 if (!theCtx->GetResource (theKey, aFont))
646 {
647 Handle(Font_FontMgr) aFontMgr = Font_FontMgr::GetInstance();
b6472664 648 const Handle(TCollection_HAsciiString) aFontName = new TCollection_HAsciiString (theAspect.Aspect()->Font());
649 const Font_FontAspect anAspect = theAspect.Aspect()->GetTextFontAspect() != Font_FA_Undefined
650 ? theAspect.Aspect()->GetTextFontAspect()
651 : Font_FA_Regular;
a174a3c5 652 Handle(Font_SystemFont) aRequestedFont = aFontMgr->FindFont (aFontName, anAspect, theHeight);
65360da3 653 Handle(Font_FTFont) aFontFt;
654 if (!aRequestedFont.IsNull())
2166f0fa 655 {
65360da3 656 aFontFt = new Font_FTFont (NULL);
317d68c9 657
4b1c8733 658 if (aFontFt->Init (aRequestedFont->FontPath()->ToCString(), theHeight, theResolution))
65360da3 659 {
660 aFont = new OpenGl_Font (aFontFt, theKey);
661 if (!aFont->Init (theCtx))
662 {
663 TCollection_ExtendedString aMsg;
664 aMsg += "Font '";
b6472664 665 aMsg += theAspect.Aspect()->Font();
65360da3 666 aMsg += "' - initialization of GL resources has failed!";
3b523c4c 667 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, aMsg);
65360da3 668 aFontFt.Nullify();
c6ad5e5f 669 aFont->Release (theCtx.operator->());
65360da3 670 aFont = new OpenGl_Font (aFontFt, theKey);
671 }
672 }
673 else
674 {
675 TCollection_ExtendedString aMsg;
676 aMsg += "Font '";
b6472664 677 aMsg += theAspect.Aspect()->Font();
65360da3 678 aMsg += "' is broken or has incompatible format! File path: ";
679 aMsg += aRequestedFont->FontPath()->ToCString();
3b523c4c 680 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, aMsg);
65360da3 681 aFontFt.Nullify();
682 aFont = new OpenGl_Font (aFontFt, theKey);
683 }
a174a3c5 684 }
65360da3 685 else
a174a3c5 686 {
65360da3 687 TCollection_ExtendedString aMsg;
688 aMsg += "Font '";
b6472664 689 aMsg += theAspect.Aspect()->Font();
65360da3 690 aMsg += "' is not found in the system!";
3b523c4c 691 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, aMsg);
65360da3 692 aFont = new OpenGl_Font (aFontFt, theKey);
a174a3c5 693 }
a174a3c5 694
b34efb62 695 theCtx->ShareResource (theKey, aFont);
a174a3c5 696 }
697 return aFont;
698}
699
700// =======================================================================
701// function : render
702// purpose :
703// =======================================================================
60273f77 704void OpenGl_Text::render (const Handle(OpenGl_Context)& theCtx,
705 const OpenGl_AspectText& theTextAspect,
706 const OpenGl_Vec4& theColorText,
707 const OpenGl_Vec4& theColorSubs,
708 const unsigned int theResolution) const
a174a3c5 709{
710 if (myString.IsEmpty())
711 {
712 return;
713 }
714
4b1c8733 715 // Note that using difference resolution in different Views in same Viewer
716 // will lead to performance regression (for example, text will be recreated every time).
717 const TCollection_AsciiString aFontKey = FontKey (theTextAspect, myParams.Height, theResolution);
a174a3c5 718 if (!myFont.IsNull()
719 && !myFont->ResourceKey().IsEqual (aFontKey))
720 {
721 // font changed
10b9c7df 722 const_cast<OpenGl_Text* > (this)->Release (theCtx.operator->());
a174a3c5 723 }
724
725 if (myFont.IsNull())
726 {
4b1c8733 727 myFont = FindFont (theCtx, theTextAspect, myParams.Height, theResolution, aFontKey);
65360da3 728 }
729 if (!myFont->WasInitialized())
730 {
731 return;
a174a3c5 732 }
733
734 if (myTextures.IsEmpty())
735 {
317d68c9 736 Font_TextFormatter aFormatter;
a174a3c5 737 aFormatter.SetupAlignment (myParams.HAlign, myParams.VAlign);
738 aFormatter.Reset();
317d68c9 739
d2eddacc 740 aFormatter.Append (myString, *myFont->FTFont().operator->());
a174a3c5 741 aFormatter.Format();
742
317d68c9 743 OpenGl_TextBuilder aBuilder;
744 aBuilder.Perform (aFormatter,
745 theCtx,
746 *myFont.operator->(),
747 myTextures,
748 myVertsVbo,
749 myTCrdsVbo);
750
a174a3c5 751 aFormatter.BndBox (myBndBox);
752 }
753
754 if (myTextures.IsEmpty())
755 {
756 return;
757 }
758
759 myExportHeight = 1.0f;
760 myScaleHeight = 1.0f;
761
3f1eb0ab 762 if (myHasPlane && !myHasAnchorPoint)
763 {
764 OpenGl_Mat4d aWorldViewMat;
765 aWorldViewMat.Convert (theCtx->WorldViewState.Current());
766 theCtx->WorldViewState.Push();
767 theCtx->WorldViewState.SetCurrent<Standard_Real> (aWorldViewMat);
768 theCtx->ApplyWorldViewMatrix();
769 }
770 else
771 {
772 theCtx->WorldViewState.Push();
773 }
c827ea3a 774
c827ea3a 775 myModelMatrix.Convert (theCtx->WorldViewState.Current() * theCtx->ModelWorldState.Current());
776
a174a3c5 777 if (!myIs2d)
778 {
825aa485 779 Graphic3d_TransformUtils::Project<Standard_Real> (myPoint.x(),
780 myPoint.y(),
781 myPoint.z(),
782 myModelMatrix,
783 myProjMatrix,
3bffef55 784 theCtx->Viewport(),
825aa485 785 myWinX,
786 myWinY,
787 myWinZ);
a174a3c5 788
789 // compute scale factor for constant text height
790 GLdouble x1, y1, z1;
825aa485 791 Graphic3d_TransformUtils::UnProject<Standard_Real> (myWinX,
792 myWinY,
793 myWinZ,
794 OpenGl_Mat4d::Map (THE_IDENTITY_MATRIX),
795 myProjMatrix,
3bffef55 796 theCtx->Viewport(),
825aa485 797 x1,
798 y1,
799 z1);
a174a3c5 800
801 GLdouble x2, y2, z2;
802 const GLdouble h = (GLdouble )myFont->FTFont()->PointSize();
825aa485 803 Graphic3d_TransformUtils::UnProject<Standard_Real> (myWinX,
804 myWinY + h,
805 myWinZ,
806 OpenGl_Mat4d::Map (THE_IDENTITY_MATRIX),
807 myProjMatrix,
3bffef55 808 theCtx->Viewport(),
825aa485 809 x2,
810 y2,
811 z2);
a174a3c5 812
813 myScaleHeight = (y2 - y1) / h;
b6472664 814 if (theTextAspect.Aspect()->GetTextZoomable())
a174a3c5 815 {
816 myExportHeight = (float )h;
817 }
818 }
819 myExportHeight = (float )myFont->FTFont()->PointSize() / myExportHeight;
820
b990e557 821#if !defined(GL_ES_VERSION_2_0)
65360da3 822 if (theCtx->core11 != NULL)
823 {
824 glDisable (GL_LIGHTING);
825 }
826#endif
a174a3c5 827
828 // setup depth test
eae454e3 829 if (myIs2d
b6472664 830 || theTextAspect.Aspect()->Style() == Aspect_TOST_ANNOTATION)
a174a3c5 831 {
832 glDisable (GL_DEPTH_TEST);
833 }
834
65360da3 835 if (theCtx->core15fwd != NULL)
a174a3c5 836 {
65360da3 837 theCtx->core15fwd->glActiveTexture (GL_TEXTURE0);
a174a3c5 838 }
65360da3 839#if !defined(GL_ES_VERSION_2_0)
a174a3c5 840 // activate texture unit
65360da3 841 GLint aTexEnvParam = GL_REPLACE;
842 if (theCtx->core11 != NULL)
a174a3c5 843 {
c6ad5e5f 844 // setup alpha test
845 glAlphaFunc (GL_GEQUAL, 0.285f);
846 glEnable (GL_ALPHA_TEST);
847
65360da3 848 glDisable (GL_TEXTURE_1D);
849 glEnable (GL_TEXTURE_2D);
850 glGetTexEnviv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &aTexEnvParam);
851 if (aTexEnvParam != GL_REPLACE)
852 {
853 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
854 }
a174a3c5 855 }
65360da3 856#endif
857
858 // setup blending
859 glEnable (GL_BLEND);
860 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
a174a3c5 861
862 // extra drawings
b6472664 863 switch (theTextAspect.Aspect()->DisplayType())
a174a3c5 864 {
2166f0fa 865 case Aspect_TODT_BLEND:
a174a3c5 866 {
65360da3 867 #if !defined(GL_ES_VERSION_2_0)
a174a3c5 868 glEnable (GL_COLOR_LOGIC_OP);
869 glLogicOp (GL_XOR);
65360da3 870 #endif
2166f0fa 871 break;
a174a3c5 872 }
2166f0fa
SK
873 case Aspect_TODT_SUBTITLE:
874 {
65360da3 875 #if !defined(GL_ES_VERSION_2_0)
876 if (theCtx->core11 != NULL)
877 {
b6472664 878 theCtx->SetColor4fv (theColorSubs);
60273f77 879 setupMatrix (theCtx, theTextAspect, OpenGl_Vec3 (0.0f, 0.0f, 0.00001f));
65360da3 880
881 glBindTexture (GL_TEXTURE_2D, 0);
882 glBegin (GL_QUADS);
883 glVertex2f (myBndBox.Left, myBndBox.Top);
884 glVertex2f (myBndBox.Right, myBndBox.Top);
885 glVertex2f (myBndBox.Right, myBndBox.Bottom);
886 glVertex2f (myBndBox.Left, myBndBox.Bottom);
887 glEnd();
888 }
889 #endif
2166f0fa
SK
890 break;
891 }
2166f0fa 892 case Aspect_TODT_DEKALE:
a174a3c5 893 {
b6472664 894 theCtx->SetColor4fv (theColorSubs);
60273f77 895 setupMatrix (theCtx, theTextAspect, OpenGl_Vec3 (+1.0f, +1.0f, 0.00001f));
896 drawText (theCtx, theTextAspect);
897 setupMatrix (theCtx, theTextAspect, OpenGl_Vec3 (-1.0f, -1.0f, 0.00001f));
898 drawText (theCtx, theTextAspect);
899 setupMatrix (theCtx, theTextAspect, OpenGl_Vec3 (-1.0f, +1.0f, 0.00001f));
900 drawText (theCtx, theTextAspect);
901 setupMatrix (theCtx, theTextAspect, OpenGl_Vec3 (+1.0f, -1.0f, 0.00001f));
902 drawText (theCtx, theTextAspect);
a174a3c5 903 break;
904 }
a6eb515f 905 case Aspect_TODT_DIMENSION:
a174a3c5 906 case Aspect_TODT_NORMAL:
907 {
2166f0fa
SK
908 break;
909 }
910 }
911
a174a3c5 912 // main draw call
b6472664 913 theCtx->SetColor4fv (theColorText);
60273f77 914 setupMatrix (theCtx, theTextAspect, OpenGl_Vec3 (0.0f, 0.0f, 0.0f));
915 drawText (theCtx, theTextAspect);
2166f0fa 916
ce01ec26 917 if (!myIs2d)
918 {
919 theCtx->ProjectionState.SetCurrent<Standard_Real> (myProjMatrix);
920 theCtx->ApplyProjectionMatrix();
921 }
922
65360da3 923#if !defined(GL_ES_VERSION_2_0)
924 if (theCtx->core11 != NULL)
925 {
926 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, aTexEnvParam);
927 }
928#endif
543f0db0 929
b6472664 930 if (theTextAspect.Aspect()->DisplayType() == Aspect_TODT_DIMENSION)
543f0db0 931 {
60273f77 932 setupMatrix (theCtx, theTextAspect, OpenGl_Vec3 (0.0f, 0.0f, 0.00001f));
543f0db0 933
934 glDisable (GL_BLEND);
543f0db0 935 if (!myIs2d)
936 {
937 glDisable (GL_DEPTH_TEST);
938 }
65360da3 939 #if !defined(GL_ES_VERSION_2_0)
940 if (theCtx->core11 != NULL)
941 {
942 glDisable (GL_TEXTURE_2D);
943 glDisable (GL_ALPHA_TEST);
944 }
945 #endif
543f0db0 946 glColorMask (GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
947
948 glClear (GL_STENCIL_BUFFER_BIT);
949 glEnable (GL_STENCIL_TEST);
950 glStencilFunc (GL_ALWAYS, 1, 0xFF);
951 glStencilOp (GL_KEEP, GL_KEEP, GL_REPLACE);
952
65360da3 953 #if !defined(GL_ES_VERSION_2_0)
954 if (theCtx->core11 != NULL)
955 {
956 glBegin (GL_QUADS);
957 glVertex2f (myBndBox.Left, myBndBox.Top);
958 glVertex2f (myBndBox.Right, myBndBox.Top);
959 glVertex2f (myBndBox.Right, myBndBox.Bottom);
960 glVertex2f (myBndBox.Left, myBndBox.Bottom);
961 glEnd();
962 }
963 #endif
543f0db0 964
965 glStencilFunc (GL_ALWAYS, 0, 0xFF);
543f0db0 966
967 glColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
968 }
969
b34efb62 970 // reset OpenGL state
971 glDisable (GL_BLEND);
b34efb62 972 glDisable (GL_STENCIL_TEST);
65360da3 973#if !defined(GL_ES_VERSION_2_0)
c6ad5e5f 974 if (theCtx->core11 != NULL)
975 {
976 glDisable (GL_ALPHA_TEST);
977 }
b34efb62 978 glDisable (GL_COLOR_LOGIC_OP);
65360da3 979#endif
c827ea3a 980
981 // model view matrix was modified
982 theCtx->WorldViewState.Pop();
983 theCtx->ApplyModelViewMatrix();
5e27df78 984}