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