0024381: Visualization, TKOpenGl - revise matrices stack and usage of temporary matrices
[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>
25ef750e 22#include <OpenGl_Sampler.hxx>
30f0ad28 23#include <OpenGl_Text.hxx>
c827ea3a 24#include <OpenGl_Utils.hxx>
bf75be98 25#include <OpenGl_Workspace.hxx>
2166f0fa 26
a174a3c5 27#include <Font_FontMgr.hxx>
28#include <TCollection_HAsciiString.hxx>
29
a174a3c5 30#ifdef HAVE_GL2PS
31 #include <gl2ps.h>
32#endif
33
34namespace
2166f0fa 35{
c827ea3a 36 static const GLdouble THE_IDENTITY_MATRIX[16] =
a174a3c5 37 {
c827ea3a 38 1.0, 0.0, 0.0, 0.0,
39 0.0, 1.0, 0.0, 0.0,
40 0.0, 0.0, 1.0, 0.0,
41 0.0, 0.0, 0.0, 1.0
a174a3c5 42 };
43
44#ifdef HAVE_GL2PS
45 static char const* TheFamily[] = {"Helvetica", "Courier", "Times"};
46 static char const* TheItalic[] = {"Oblique", "Oblique", "Italic"};
47 static char const* TheBase[] = {"", "", "-Roman"};
48
49 //! Convert font name used for rendering to some "good" font names
50 //! that produce good vector text.
51 static void getGL2PSFontName (const char* theSrcFont,
52 char* thePsFont)
53 {
54 if (strstr (theSrcFont, "Symbol"))
55 {
56 sprintf (thePsFont, "%s", "Symbol");
57 return;
58 }
59 else if (strstr (theSrcFont, "ZapfDingbats"))
60 {
61 sprintf (thePsFont, "%s", "WingDings");
62 return;
63 }
2166f0fa 64
a174a3c5 65 int aFontId = 0;
66 bool isBold = false;
67 bool isItalic = false;
68 if (strstr (theSrcFont, "Courier"))
69 {
70 aFontId = 1;
71 }
72 else if (strstr (theSrcFont, "Times"))
73 {
74 aFontId = 2;
75 }
2166f0fa 76
a174a3c5 77 if (strstr (theSrcFont, "Bold"))
78 {
79 isBold = true;
80 }
81 if (strstr (theSrcFont, "Italic")
82 || strstr (theSrcFont, "Oblique"))
83 {
84 isItalic = true;
85 }
2166f0fa 86
a174a3c5 87 if (isBold)
88 {
a174a3c5 89 if (isItalic)
90 {
8b224a09 91 sprintf (thePsFont, "%s-Bold%s", TheFamily[aFontId], TheItalic[aFontId]);
92 }
93 else
94 {
95 sprintf (thePsFont, "%s-Bold", TheFamily[aFontId]);
a174a3c5 96 }
97 }
98 else if (isItalic)
99 {
100 sprintf (thePsFont, "%s-%s", TheFamily[aFontId], TheItalic[aFontId]);
101 }
102 else
103 {
104 sprintf (thePsFont, "%s%s", TheFamily[aFontId], TheBase[aFontId]);
105 }
106 }
2166f0fa 107
a174a3c5 108 static void exportText (const NCollection_String& theText,
109 const Standard_Boolean theIs2d,
110 const OpenGl_AspectText& theAspect,
111 const Standard_Integer theHeight)
112 {
2166f0fa 113
a174a3c5 114 char aPsFont[64];
115 getGL2PSFontName (theAspect.FontName().ToCString(), aPsFont);
2166f0fa 116
ca3c13d1 117 #if !defined(GL_ES_VERSION_2_0)
a174a3c5 118 if (theIs2d)
119 {
120 glRasterPos2f (0.0f, 0.0f);
121 }
122 else
123 {
124 glRasterPos3f (0.0f, 0.0f, 0.0f);
125 }
126
127 GLubyte aZero = 0;
128 glBitmap (1, 1, 0, 0, 0, 0, &aZero);
ca3c13d1 129 #endif
a174a3c5 130
131 // Standard GL2PS's alignment isn't used, because it doesn't work correctly
132 // for all formats, therefore alignment is calculated manually relative
133 // to the bottom-left corner, which corresponds to the GL2PS_TEXT_BL value
105aae76 134 gl2psTextOpt (theText.ToCString(), aPsFont, (GLshort)theHeight, GL2PS_TEXT_BL, theAspect.Angle());
a174a3c5 135 }
136#endif
137
138};
139
140// =======================================================================
141// function : OpenGl_Text
142// purpose :
143// =======================================================================
144OpenGl_Text::OpenGl_Text()
145: myWinX (0.0f),
146 myWinY (0.0f),
147 myWinZ (0.0f),
148 myScaleHeight (1.0f),
149 myPoint (0.0f, 0.0f, 0.0f),
150 myIs2d (false)
151{
152 myParams.Height = 10;
153 myParams.HAlign = Graphic3d_HTA_LEFT;
154 myParams.VAlign = Graphic3d_VTA_BOTTOM;
2166f0fa
SK
155}
156
a174a3c5 157// =======================================================================
158// function : OpenGl_Text
159// purpose :
160// =======================================================================
b64d84be 161OpenGl_Text::OpenGl_Text (const Standard_Utf8Char* theText,
162 const OpenGl_Vec3& thePoint,
163 const OpenGl_TextParam& theParams)
a174a3c5 164: myWinX (0.0f),
165 myWinY (0.0f),
166 myWinZ (0.0f),
167 myScaleHeight (1.0f),
168 myExportHeight (1.0f),
169 myParams (theParams),
b64d84be 170 myString (theText),
a174a3c5 171 myPoint (thePoint),
172 myIs2d (false)
173{
174 //
175}
2166f0fa 176
a174a3c5 177// =======================================================================
178// function : SetPosition
179// purpose :
180// =======================================================================
181void OpenGl_Text::SetPosition (const OpenGl_Vec3& thePoint)
2166f0fa 182{
a174a3c5 183 myPoint = thePoint;
2166f0fa
SK
184}
185
a174a3c5 186// =======================================================================
187// function : SetFontSize
188// purpose :
189// =======================================================================
190void OpenGl_Text::SetFontSize (const Handle(OpenGl_Context)& theCtx,
191 const Standard_Integer theFontSize)
192{
193 if (myParams.Height != theFontSize)
194 {
10b9c7df 195 Release (theCtx.operator->());
a174a3c5 196 }
197 myParams.Height = theFontSize;
198}
199
200// =======================================================================
201// function : Init
202// purpose :
203// =======================================================================
204void OpenGl_Text::Init (const Handle(OpenGl_Context)& theCtx,
205 const Standard_Utf8Char* theText,
206 const OpenGl_Vec3& thePoint)
207{
10b9c7df 208 releaseVbos (theCtx.operator->());
a174a3c5 209 myIs2d = false;
210 myPoint = thePoint;
211 myString.FromUnicode (theText);
212}
213
214// =======================================================================
215// function : Init
216// purpose :
217// =======================================================================
218void OpenGl_Text::Init (const Handle(OpenGl_Context)& theCtx,
219 const Standard_Utf8Char* theText,
220 const OpenGl_Vec3& thePoint,
221 const OpenGl_TextParam& theParams)
222{
223 if (myParams.Height != theParams.Height)
224 {
10b9c7df 225 Release (theCtx.operator->());
a174a3c5 226 }
227 else
228 {
10b9c7df 229 releaseVbos (theCtx.operator->());
a174a3c5 230 }
231 myIs2d = false;
232 myParams = theParams;
233 myPoint = thePoint;
234 myString.FromUnicode (theText);
235}
2166f0fa 236
a174a3c5 237// =======================================================================
238// function : Init
239// purpose :
240// =======================================================================
241void OpenGl_Text::Init (const Handle(OpenGl_Context)& theCtx,
242 const TCollection_ExtendedString& theText,
243 const OpenGl_Vec2& thePoint,
244 const OpenGl_TextParam& theParams)
2166f0fa 245{
a174a3c5 246 if (myParams.Height != theParams.Height)
247 {
10b9c7df 248 Release (theCtx.operator->());
a174a3c5 249 }
250 else
251 {
10b9c7df 252 releaseVbos (theCtx.operator->());
a174a3c5 253 }
254 myIs2d = true;
255 myParams = theParams;
256 myPoint.xy() = thePoint;
257 myPoint.z() = 0.0f;
258 myString.FromUnicode ((Standard_Utf16Char* )theText.ToExtString());
259}
260
261// =======================================================================
262// function : ~OpenGl_Text
263// purpose :
264// =======================================================================
265OpenGl_Text::~OpenGl_Text()
266{
267 //
268}
269
270// =======================================================================
271// function : releaseVbos
272// purpose :
273// =======================================================================
10b9c7df 274void OpenGl_Text::releaseVbos (OpenGl_Context* theCtx)
a174a3c5 275{
276 for (Standard_Integer anIter = 0; anIter < myVertsVbo.Length(); ++anIter)
277 {
278 Handle(OpenGl_VertexBuffer)& aVerts = myVertsVbo.ChangeValue (anIter);
279 Handle(OpenGl_VertexBuffer)& aTCrds = myTCrdsVbo.ChangeValue (anIter);
280
10b9c7df 281 if (theCtx)
a174a3c5 282 {
283 theCtx->DelayedRelease (aVerts);
284 theCtx->DelayedRelease (aTCrds);
285 }
286 aVerts.Nullify();
287 aTCrds.Nullify();
288 }
289 myTextures.Clear();
290 myVertsVbo.Clear();
291 myTCrdsVbo.Clear();
a174a3c5 292}
293
294// =======================================================================
295// function : Release
296// purpose :
297// =======================================================================
10b9c7df 298void OpenGl_Text::Release (OpenGl_Context* theCtx)
a174a3c5 299{
300 releaseVbos (theCtx);
301 if (!myFont.IsNull())
302 {
303 Handle(OpenGl_Context) aCtx = theCtx;
304 const TCollection_AsciiString aKey = myFont->ResourceKey();
305 myFont.Nullify();
10b9c7df 306 if (aCtx)
307 aCtx->ReleaseResource (aKey, Standard_True);
a174a3c5 308 }
309}
310
311// =======================================================================
312// function : StringSize
313// purpose :
314// =======================================================================
315void OpenGl_Text::StringSize (const Handle(OpenGl_Context)& theCtx,
316 const NCollection_String& theText,
317 const OpenGl_AspectText& theTextAspect,
318 const OpenGl_TextParam& theParams,
319 Standard_ShortReal& theWidth,
320 Standard_ShortReal& theAscent,
321 Standard_ShortReal& theDescent)
322{
323 theWidth = 0.0f;
324 theAscent = 0.0f;
325 theDescent = 0.0f;
326 const TCollection_AsciiString aFontKey = FontKey (theTextAspect, theParams.Height);
327 Handle(OpenGl_Font) aFont = FindFont (theCtx, theTextAspect, theParams.Height, aFontKey);
328 if (aFont.IsNull() || !aFont->IsValid())
329 {
2166f0fa 330 return;
a174a3c5 331 }
332
333 theAscent = aFont->Ascender();
334 theDescent = aFont->Descender();
335
336 GLfloat aWidth = 0.0f;
337 for (NCollection_Utf8Iter anIter = theText.Iterator(); *anIter != 0;)
338 {
339 const Standard_Utf32Char aCharThis = *anIter;
340 const Standard_Utf32Char aCharNext = *++anIter;
341
342 if (aCharThis == '\x0D' // CR (carriage return)
343 || aCharThis == '\a' // BEL (alarm)
344 || aCharThis == '\f' // FF (form feed) NP (new page)
345 || aCharThis == '\b' // BS (backspace)
346 || aCharThis == '\v') // VT (vertical tab)
347 {
348 continue; // skip unsupported carriage control codes
349 }
350 else if (aCharThis == '\x0A') // LF (line feed, new line)
351 {
352 theWidth = Max (theWidth, aWidth);
353 aWidth = 0.0f;
354 continue;
355 }
356 else if (aCharThis == ' ')
357 {
358 aWidth += aFont->AdvanceX (aCharThis, aCharNext);
359 continue;
360 }
361 else if (aCharThis == '\t')
362 {
363 aWidth += aFont->AdvanceX (' ', aCharNext) * 8.0f;
364 continue;
365 }
366
367 aWidth += aFont->AdvanceX (aCharThis, aCharNext);
368 }
369 theWidth = Max (theWidth, aWidth);
370
371 Handle(OpenGl_Context) aCtx = theCtx;
372 aFont.Nullify();
373 aCtx->ReleaseResource (aFontKey, Standard_True);
374}
375
376// =======================================================================
377// function : Render
378// purpose :
379// =======================================================================
380void OpenGl_Text::Render (const Handle(OpenGl_Workspace)& theWorkspace) const
381{
25ef750e 382 const OpenGl_AspectText* aTextAspect = theWorkspace->AspectText (Standard_True);
383 const Handle(OpenGl_Texture) aPrevTexture = theWorkspace->DisableTexture();
384 const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
385 const Handle(OpenGl_Sampler)& aSampler = aCtx->TextureSampler();
386 if (!aSampler.IsNull())
387 {
388 aSampler->Unbind (*aCtx);
389 }
30f0ad28 390
391 if (aCtx->IsGlGreaterEqual (2, 0))
392 {
8625ef7e 393 const Handle(OpenGl_ShaderProgram)& aProgram = aTextAspect->ShaderProgramRes (aCtx);
7d3e64ef 394 aCtx->BindProgram (aProgram);
30f0ad28 395 if (!aProgram.IsNull())
396 {
7d3e64ef 397 aProgram->ApplyVariables (aCtx);
30f0ad28 398
399 const OpenGl_MaterialState* aMaterialState = aCtx->ShaderManager()->MaterialState (aProgram);
5322131b 400
30f0ad28 401 if (aMaterialState == NULL || aMaterialState->Aspect() != aTextAspect)
402 aCtx->ShaderManager()->UpdateMaterialStateTo (aProgram, aTextAspect);
5322131b 403
30f0ad28 404 aCtx->ShaderManager()->PushState (aProgram);
405 }
30f0ad28 406 }
407
a174a3c5 408 // use highlight color or colors from aspect
409 if (theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT)
410 {
411 render (theWorkspace->PrinterContext(),
30f0ad28 412 aCtx,
a174a3c5 413 *aTextAspect,
414 *theWorkspace->HighlightColor,
415 *theWorkspace->HighlightColor);
416 }
417 else
418 {
419 render (theWorkspace->PrinterContext(),
30f0ad28 420 aCtx,
a174a3c5 421 *aTextAspect,
422 aTextAspect->Color(),
423 aTextAspect->SubtitleColor());
424 }
2166f0fa 425
a174a3c5 426 // restore aspects
25ef750e 427 if (!aSampler.IsNull())
428 {
429 aSampler->Bind (*aCtx);
430 }
a174a3c5 431 if (!aPrevTexture.IsNull())
432 {
433 theWorkspace->EnableTexture (aPrevTexture);
434 }
435}
2166f0fa 436
a174a3c5 437// =======================================================================
438// function : Render
439// purpose :
440// =======================================================================
441void OpenGl_Text::Render (const Handle(OpenGl_PrinterContext)& thePrintCtx,
442 const Handle(OpenGl_Context)& theCtx,
443 const OpenGl_AspectText& theTextAspect) const
444{
445 render (thePrintCtx, theCtx, theTextAspect, theTextAspect.Color(), theTextAspect.SubtitleColor());
446}
2166f0fa 447
a174a3c5 448// =======================================================================
449// function : setupMatrix
450// purpose :
451// =======================================================================
452void OpenGl_Text::setupMatrix (const Handle(OpenGl_PrinterContext)& thePrintCtx,
ca3c13d1 453 const Handle(OpenGl_Context)& theCtx,
a174a3c5 454 const OpenGl_AspectText& theTextAspect,
455 const OpenGl_Vec3 theDVec) const
456{
457 // setup matrix
ca3c13d1 458#if !defined(GL_ES_VERSION_2_0)
c827ea3a 459
460 OpenGl_Mat4d aModViewMat;
461
a174a3c5 462 if (myIs2d)
bf75be98 463 {
c827ea3a 464 OpenGl_Utils::Translate<GLdouble> (aModViewMat, myPoint.x() + theDVec.x(), myPoint.y() + theDVec.y(), 0.f);
465 OpenGl_Utils::Scale<GLdouble> (aModViewMat, 1.f, -1.f, 1.f);
466 OpenGl_Utils::Rotate<GLdouble> (aModViewMat, theTextAspect.Angle(), 0.f, 0.f, 1.f);
2166f0fa
SK
467 }
468 else
469 {
a174a3c5 470 // align coordinates to the nearest integer
471 // to avoid extra interpolation issues
472 GLdouble anObjX, anObjY, anObjZ;
c827ea3a 473 OpenGl_Utils::UnProject<Standard_Real> (std::floor (myWinX + theDVec.x()),
474 std::floor (myWinY + theDVec.y()),
475 myWinZ + theDVec.z(),
476 OpenGl_Mat4d::Map (THE_IDENTITY_MATRIX),
477 OpenGl_Mat4d::Map (myProjMatrix),
478 myViewport,
479 anObjX,
480 anObjY,
481 anObjZ);
482
483 OpenGl_Utils::Translate<GLdouble> (aModViewMat, anObjX, anObjY, anObjZ);
484 OpenGl_Utils::Rotate<GLdouble> (aModViewMat, theTextAspect.Angle(), 0.0, 0.0, 1.0);
485
a174a3c5 486 if (!theTextAspect.IsZoomable())
487 {
488 #ifdef _WIN32
489 // if the context has assigned printer context, use it's parameters
490 if (!thePrintCtx.IsNull())
491 {
492 // get printing scaling in x and y dimensions
493 GLfloat aTextScalex = 1.0f, aTextScaley = 1.0f;
494 thePrintCtx->GetScale (aTextScalex, aTextScaley);
495
496 // text should be scaled in all directions with same
497 // factor to save its proportions, so use height (y) scaling
498 // as it is better for keeping text/3d graphics proportions
c827ea3a 499 OpenGl_Utils::Scale<GLdouble> (aModViewMat, aTextScaley, aTextScaley, aTextScaley);
a174a3c5 500 }
501 #endif
c827ea3a 502 OpenGl_Utils::Scale<GLdouble> (aModViewMat, myScaleHeight, myScaleHeight, myScaleHeight);
a174a3c5 503 }
504 }
c827ea3a 505
506 theCtx->WorldViewState.SetCurrent<Standard_Real> (aModViewMat);
507 theCtx->ApplyWorldViewMatrix();
ca3c13d1 508#endif
a174a3c5 509}
510
511// =======================================================================
512// function : drawText
513// purpose :
514// =======================================================================
35e08fe8 515
516void OpenGl_Text::drawText (const Handle(OpenGl_PrinterContext)& ,
a174a3c5 517 const Handle(OpenGl_Context)& theCtx,
35e08fe8 518 #ifdef HAVE_GL2PS
a174a3c5 519 const OpenGl_AspectText& theTextAspect) const
35e08fe8 520 #else
521 const OpenGl_AspectText& ) const
522 #endif
a174a3c5 523{
524#ifdef HAVE_GL2PS
525 if (theCtx->IsFeedback())
526 {
527 // position of the text and alignment is calculated by transformation matrix
528 exportText (myString, myIs2d, theTextAspect, (Standard_Integer )myExportHeight);
529 return;
2166f0fa 530 }
a174a3c5 531#endif
2166f0fa 532
7d3e64ef 533 if (myVertsVbo.Length() != myTextures.Length()
534 || myTextures.IsEmpty())
2166f0fa 535 {
7d3e64ef 536 return;
2166f0fa 537 }
7d3e64ef 538
539 for (Standard_Integer anIter = 0; anIter < myTextures.Length(); ++anIter)
a174a3c5 540 {
7d3e64ef 541 const GLuint aTexId = myTextures.Value (anIter);
542 glBindTexture (GL_TEXTURE_2D, aTexId);
a174a3c5 543
7d3e64ef 544 const Handle(OpenGl_VertexBuffer)& aVerts = myVertsVbo.Value (anIter);
545 const Handle(OpenGl_VertexBuffer)& aTCrds = myTCrdsVbo.Value (anIter);
546 aVerts->BindAttribute (theCtx, Graphic3d_TOA_POS);
547 aTCrds->BindAttribute (theCtx, Graphic3d_TOA_UV);
2166f0fa 548
7d3e64ef 549 glDrawArrays (GL_TRIANGLES, 0, GLsizei(aVerts->GetElemsNb()));
2166f0fa 550
7d3e64ef 551 aVerts->UnbindAttribute (theCtx, Graphic3d_TOA_UV);
552 aVerts->UnbindAttribute (theCtx, Graphic3d_TOA_POS);
a174a3c5 553 }
7d3e64ef 554 glBindTexture (GL_TEXTURE_2D, 0);
a174a3c5 555}
2166f0fa 556
a174a3c5 557// =======================================================================
558// function : FontKey
559// purpose :
560// =======================================================================
561TCollection_AsciiString OpenGl_Text::FontKey (const OpenGl_AspectText& theAspect,
562 const Standard_Integer theHeight)
563{
564 const Font_FontAspect anAspect = (theAspect.FontAspect() != Font_FA_Undefined) ? theAspect.FontAspect() : Font_FA_Regular;
565 return theAspect.FontName()
566 + TCollection_AsciiString(":") + Standard_Integer(anAspect)
567 + TCollection_AsciiString(":") + theHeight;
568}
569
570// =======================================================================
571// function : FindFont
572// purpose :
573// =======================================================================
574Handle(OpenGl_Font) OpenGl_Text::FindFont (const Handle(OpenGl_Context)& theCtx,
575 const OpenGl_AspectText& theAspect,
576 const Standard_Integer theHeight,
577 const TCollection_AsciiString theKey)
578{
579 Handle(OpenGl_Font) aFont;
580 if (theHeight < 2)
2166f0fa 581 {
a174a3c5 582 return aFont; // invalid parameters
583 }
2166f0fa 584
a174a3c5 585 if (!theCtx->GetResource (theKey, aFont))
586 {
587 Handle(Font_FontMgr) aFontMgr = Font_FontMgr::GetInstance();
588 const Handle(TCollection_HAsciiString) aFontName = new TCollection_HAsciiString (theAspect.FontName());
589 const Font_FontAspect anAspect = (theAspect.FontAspect() != Font_FA_Undefined) ? theAspect.FontAspect() : Font_FA_Regular;
590 Handle(Font_SystemFont) aRequestedFont = aFontMgr->FindFont (aFontName, anAspect, theHeight);
591 if (aRequestedFont.IsNull())
2166f0fa 592 {
a174a3c5 593 return aFont;
594 }
595
596 Handle(Font_FTFont) aFontFt = new Font_FTFont (NULL);
597 if (!aFontFt->Init (aRequestedFont->FontPath()->ToCString(), theHeight))
598 {
599 return aFont;
600 }
601
602 Handle(OpenGl_Context) aCtx = theCtx;
ca3c13d1 603 #if !defined(GL_ES_VERSION_2_0)
a174a3c5 604 glPushAttrib (GL_TEXTURE_BIT);
ca3c13d1 605 #endif
a174a3c5 606 aFont = new OpenGl_Font (aFontFt, theKey);
607 if (!aFont->Init (aCtx))
608 {
609 //glPopAttrib();
610 //return aFont; // out of resources?
611 }
ca3c13d1 612 #if !defined(GL_ES_VERSION_2_0)
a174a3c5 613 glPopAttrib(); // texture bit
ca3c13d1 614 #endif
a174a3c5 615
616 aCtx->ShareResource (theKey, aFont);
617 }
618 return aFont;
619}
620
621// =======================================================================
622// function : render
623// purpose :
624// =======================================================================
625void OpenGl_Text::render (const Handle(OpenGl_PrinterContext)& thePrintCtx,
626 const Handle(OpenGl_Context)& theCtx,
627 const OpenGl_AspectText& theTextAspect,
628 const TEL_COLOUR& theColorText,
629 const TEL_COLOUR& theColorSubs) const
630{
631 if (myString.IsEmpty())
632 {
633 return;
634 }
635
636 const TCollection_AsciiString aFontKey = FontKey (theTextAspect, myParams.Height);
637 if (!myFont.IsNull()
638 && !myFont->ResourceKey().IsEqual (aFontKey))
639 {
640 // font changed
10b9c7df 641 const_cast<OpenGl_Text* > (this)->Release (theCtx.operator->());
a174a3c5 642 }
643
644 if (myFont.IsNull())
645 {
646 myFont = FindFont (theCtx, theTextAspect, myParams.Height, aFontKey);
647 if (myFont.IsNull())
648 {
649 return;
650 }
651 }
652
653 if (myTextures.IsEmpty())
654 {
655 OpenGl_TextFormatter aFormatter;
656 aFormatter.SetupAlignment (myParams.HAlign, myParams.VAlign);
657 aFormatter.Reset();
658 aFormatter.Append (theCtx, myString, *myFont.operator->());
659 aFormatter.Format();
660
7d3e64ef 661 aFormatter.Result (theCtx, myTextures, myVertsVbo, myTCrdsVbo);
a174a3c5 662 aFormatter.BndBox (myBndBox);
663 }
664
665 if (myTextures.IsEmpty())
666 {
667 return;
668 }
669
670 myExportHeight = 1.0f;
671 myScaleHeight = 1.0f;
672
c827ea3a 673 theCtx->WorldViewState.Push();
674
ca3c13d1 675#if !defined(GL_ES_VERSION_2_0)
c827ea3a 676 myModelMatrix.Convert (theCtx->WorldViewState.Current() * theCtx->ModelWorldState.Current());
677
a174a3c5 678 if (!myIs2d)
679 {
a174a3c5 680 glGetIntegerv (GL_VIEWPORT, myViewport);
c827ea3a 681 myProjMatrix.Convert (theCtx->ProjectionState.Current());
682
683 OpenGl_Utils::Project<Standard_Real> (myPoint.x(),
684 myPoint.y(),
685 myPoint.z(),
686 myModelMatrix,
687 myProjMatrix,
688 myViewport,
689 myWinX,
690 myWinY,
691 myWinZ);
a174a3c5 692
693 // compute scale factor for constant text height
694 GLdouble x1, y1, z1;
c827ea3a 695 OpenGl_Utils::UnProject<Standard_Real> (myWinX,
696 myWinY,
697 myWinZ,
698 OpenGl_Mat4d::Map (THE_IDENTITY_MATRIX),
699 myProjMatrix,
700 myViewport,
701 x1,
702 y1,
703 z1);
a174a3c5 704
705 GLdouble x2, y2, z2;
706 const GLdouble h = (GLdouble )myFont->FTFont()->PointSize();
c827ea3a 707 OpenGl_Utils::UnProject<Standard_Real> (myWinX,
708 myWinY + h,
709 myWinZ,
710 OpenGl_Mat4d::Map (THE_IDENTITY_MATRIX),
711 myProjMatrix,
712 myViewport,
713 x2,
714 y2,
715 z2);
a174a3c5 716
717 myScaleHeight = (y2 - y1) / h;
718 if (theTextAspect.IsZoomable())
719 {
720 myExportHeight = (float )h;
721 }
722 }
723 myExportHeight = (float )myFont->FTFont()->PointSize() / myExportHeight;
724
725 // push enabled flags to the stack
726 glPushAttrib (GL_ENABLE_BIT);
5322131b 727 glDisable (GL_LIGHTING);
a174a3c5 728
729 // setup depth test
730 if (!myIs2d
731 && theTextAspect.StyleType() != Aspect_TOST_ANNOTATION)
732 {
733 glEnable (GL_DEPTH_TEST);
734 }
735 else
736 {
737 glDisable (GL_DEPTH_TEST);
738 }
739
740 // setup alpha test
741 GLint aTexEnvParam = GL_REPLACE;
742 glGetTexEnviv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &aTexEnvParam);
743 if (aTexEnvParam != GL_REPLACE)
744 {
745 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
746 }
747 glAlphaFunc (GL_GEQUAL, 0.285f);
748 glEnable (GL_ALPHA_TEST);
749
750 // setup blending
751 glEnable (GL_BLEND);
752 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // GL_ONE
753
754 // activate texture unit
755 glDisable (GL_TEXTURE_1D);
756 glEnable (GL_TEXTURE_2D);
01ca42b2 757 if (theCtx->core15fwd != NULL)
a174a3c5 758 {
01ca42b2 759 theCtx->core15fwd->glActiveTexture (GL_TEXTURE0);
a174a3c5 760 }
761
25ef750e 762 // unbind current OpenGL sampler
763 const Handle(OpenGl_Sampler)& aSampler = theCtx->TextureSampler();
764 if (!aSampler.IsNull() && aSampler->IsValid())
765 {
766 aSampler->Unbind (*theCtx);
767 }
768
a174a3c5 769 // extra drawings
770 switch (theTextAspect.DisplayType())
771 {
2166f0fa 772 case Aspect_TODT_BLEND:
a174a3c5 773 {
774 glEnable (GL_COLOR_LOGIC_OP);
775 glLogicOp (GL_XOR);
2166f0fa 776 break;
a174a3c5 777 }
2166f0fa
SK
778 case Aspect_TODT_SUBTITLE:
779 {
ca3c13d1 780 theCtx->core11->glColor3fv (theColorSubs.rgb);
a174a3c5 781 setupMatrix (thePrintCtx, theCtx, theTextAspect, OpenGl_Vec3 (0.0f, 0.0f, 0.00001f));
782
783 glBindTexture (GL_TEXTURE_2D, 0);
784 glBegin (GL_QUADS);
785 glVertex2f (myBndBox.Left, myBndBox.Top);
786 glVertex2f (myBndBox.Right, myBndBox.Top);
787 glVertex2f (myBndBox.Right, myBndBox.Bottom);
788 glVertex2f (myBndBox.Left, myBndBox.Bottom);
2166f0fa
SK
789 glEnd();
790 break;
791 }
2166f0fa 792 case Aspect_TODT_DEKALE:
a174a3c5 793 {
ca3c13d1 794 theCtx->core11->glColor3fv (theColorSubs.rgb);
a174a3c5 795 setupMatrix (thePrintCtx, theCtx, theTextAspect, OpenGl_Vec3 (+1.0f, +1.0f, 0.00001f));
796 drawText (thePrintCtx, theCtx, theTextAspect);
797 setupMatrix (thePrintCtx, theCtx, theTextAspect, OpenGl_Vec3 (-1.0f, -1.0f, 0.00001f));
798 drawText (thePrintCtx, theCtx, theTextAspect);
799 setupMatrix (thePrintCtx, theCtx, theTextAspect, OpenGl_Vec3 (-1.0f, +1.0f, 0.00001f));
800 drawText (thePrintCtx, theCtx, theTextAspect);
801 setupMatrix (thePrintCtx, theCtx, theTextAspect, OpenGl_Vec3 (+1.0f, -1.0f, 0.00001f));
802 drawText (thePrintCtx, theCtx, theTextAspect);
803 break;
804 }
a6eb515f 805 case Aspect_TODT_DIMENSION:
a174a3c5 806 case Aspect_TODT_NORMAL:
807 {
2166f0fa
SK
808 break;
809 }
810 }
811
a174a3c5 812 // main draw call
ca3c13d1 813 theCtx->core11->glColor3fv (theColorText.rgb);
a174a3c5 814 setupMatrix (thePrintCtx, theCtx, theTextAspect, OpenGl_Vec3 (0.0f, 0.0f, 0.0f));
815 drawText (thePrintCtx, theCtx, theTextAspect);
2166f0fa 816
a174a3c5 817 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, aTexEnvParam);
543f0db0 818
819 if (theTextAspect.DisplayType() == Aspect_TODT_DIMENSION)
820 {
821 setupMatrix (thePrintCtx, theCtx, theTextAspect, OpenGl_Vec3 (0.0f, 0.0f, 0.00001f));
822
823 glDisable (GL_BLEND);
824 glDisable (GL_TEXTURE_2D);
825 glDisable (GL_ALPHA_TEST);
826 if (!myIs2d)
827 {
828 glDisable (GL_DEPTH_TEST);
829 }
830 glColorMask (GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
831
832 glClear (GL_STENCIL_BUFFER_BIT);
833 glEnable (GL_STENCIL_TEST);
834 glStencilFunc (GL_ALWAYS, 1, 0xFF);
835 glStencilOp (GL_KEEP, GL_KEEP, GL_REPLACE);
836
837 glBegin (GL_QUADS);
838 glVertex2f (myBndBox.Left, myBndBox.Top);
839 glVertex2f (myBndBox.Right, myBndBox.Top);
840 glVertex2f (myBndBox.Right, myBndBox.Bottom);
841 glVertex2f (myBndBox.Left, myBndBox.Bottom);
842 glEnd();
843
844 glStencilFunc (GL_ALWAYS, 0, 0xFF);
845 // glPopAttrib() will reset state for us
846 //glDisable (GL_STENCIL_TEST);
847 //if (!myIs2d) glEnable (GL_DEPTH_TEST);
848
849 glColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
850 }
851
852 // revert OpenGL state
a174a3c5 853 glPopAttrib(); // enable bit
c827ea3a 854
855 // model view matrix was modified
856 theCtx->WorldViewState.Pop();
857 theCtx->ApplyModelViewMatrix();
25ef750e 858
859 // revert custom OpenGL sampler
860 if (!aSampler.IsNull() && aSampler->IsValid())
861 {
862 aSampler->Bind (*theCtx);
863 }
ca3c13d1 864#endif
5e27df78 865}