0026784: Coding rules - eliminate GCC warning -Wunused-parameter
[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>
825aa485 27#include <Graphic3d_TransformUtils.hxx>
a174a3c5 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),
ce01ec26 150 myIs2d (false),
151 myHasPlane (false)
a174a3c5 152{
153 myParams.Height = 10;
154 myParams.HAlign = Graphic3d_HTA_LEFT;
155 myParams.VAlign = Graphic3d_VTA_BOTTOM;
2166f0fa
SK
156}
157
a174a3c5 158// =======================================================================
159// function : OpenGl_Text
160// purpose :
161// =======================================================================
b64d84be 162OpenGl_Text::OpenGl_Text (const Standard_Utf8Char* theText,
163 const OpenGl_Vec3& thePoint,
164 const OpenGl_TextParam& theParams)
a174a3c5 165: myWinX (0.0f),
166 myWinY (0.0f),
167 myWinZ (0.0f),
168 myScaleHeight (1.0f),
169 myExportHeight (1.0f),
170 myParams (theParams),
b64d84be 171 myString (theText),
a174a3c5 172 myPoint (thePoint),
ce01ec26 173 myIs2d (false),
174 myHasPlane (false)
a174a3c5 175{
176 //
177}
2166f0fa 178
ce01ec26 179// =======================================================================
180// function : OpenGl_Text
181// purpose :
182// =======================================================================
183OpenGl_Text::OpenGl_Text (const Standard_Utf8Char* theText,
184 const gp_Ax2& theOrientation,
185 const OpenGl_TextParam& theParams)
186: myWinX (0.0),
187 myWinY (0.0),
188 myWinZ (0.0),
189 myScaleHeight (1.0),
190 myExportHeight (1.0),
191 myParams (theParams),
192 myString (theText),
193 myIs2d (false),
194 myOrientation (theOrientation),
195 myHasPlane (true)
196{
197 const gp_Pnt& aPoint = theOrientation.Location();
198 myPoint = OpenGl_Vec3 (static_cast<Standard_ShortReal> (aPoint.X()),
199 static_cast<Standard_ShortReal> (aPoint.Y()),
200 static_cast<Standard_ShortReal> (aPoint.Z()));
201}
202
a174a3c5 203// =======================================================================
204// function : SetPosition
205// purpose :
206// =======================================================================
207void OpenGl_Text::SetPosition (const OpenGl_Vec3& thePoint)
2166f0fa 208{
a174a3c5 209 myPoint = thePoint;
2166f0fa
SK
210}
211
a174a3c5 212// =======================================================================
213// function : SetFontSize
214// purpose :
215// =======================================================================
216void OpenGl_Text::SetFontSize (const Handle(OpenGl_Context)& theCtx,
217 const Standard_Integer theFontSize)
218{
219 if (myParams.Height != theFontSize)
220 {
10b9c7df 221 Release (theCtx.operator->());
a174a3c5 222 }
223 myParams.Height = theFontSize;
224}
225
226// =======================================================================
227// function : Init
228// purpose :
229// =======================================================================
230void OpenGl_Text::Init (const Handle(OpenGl_Context)& theCtx,
231 const Standard_Utf8Char* theText,
232 const OpenGl_Vec3& thePoint)
233{
10b9c7df 234 releaseVbos (theCtx.operator->());
a174a3c5 235 myIs2d = false;
236 myPoint = thePoint;
237 myString.FromUnicode (theText);
238}
239
240// =======================================================================
241// function : Init
242// purpose :
243// =======================================================================
244void OpenGl_Text::Init (const Handle(OpenGl_Context)& theCtx,
245 const Standard_Utf8Char* theText,
246 const OpenGl_Vec3& thePoint,
247 const OpenGl_TextParam& theParams)
248{
249 if (myParams.Height != theParams.Height)
250 {
10b9c7df 251 Release (theCtx.operator->());
a174a3c5 252 }
253 else
254 {
10b9c7df 255 releaseVbos (theCtx.operator->());
a174a3c5 256 }
257 myIs2d = false;
258 myParams = theParams;
259 myPoint = thePoint;
260 myString.FromUnicode (theText);
261}
2166f0fa 262
a174a3c5 263// =======================================================================
264// function : Init
265// purpose :
266// =======================================================================
267void OpenGl_Text::Init (const Handle(OpenGl_Context)& theCtx,
268 const TCollection_ExtendedString& theText,
269 const OpenGl_Vec2& thePoint,
270 const OpenGl_TextParam& theParams)
2166f0fa 271{
a174a3c5 272 if (myParams.Height != theParams.Height)
273 {
10b9c7df 274 Release (theCtx.operator->());
a174a3c5 275 }
276 else
277 {
10b9c7df 278 releaseVbos (theCtx.operator->());
a174a3c5 279 }
280 myIs2d = true;
281 myParams = theParams;
282 myPoint.xy() = thePoint;
283 myPoint.z() = 0.0f;
284 myString.FromUnicode ((Standard_Utf16Char* )theText.ToExtString());
285}
286
287// =======================================================================
288// function : ~OpenGl_Text
289// purpose :
290// =======================================================================
291OpenGl_Text::~OpenGl_Text()
292{
293 //
294}
295
296// =======================================================================
297// function : releaseVbos
298// purpose :
299// =======================================================================
10b9c7df 300void OpenGl_Text::releaseVbos (OpenGl_Context* theCtx)
a174a3c5 301{
302 for (Standard_Integer anIter = 0; anIter < myVertsVbo.Length(); ++anIter)
303 {
304 Handle(OpenGl_VertexBuffer)& aVerts = myVertsVbo.ChangeValue (anIter);
305 Handle(OpenGl_VertexBuffer)& aTCrds = myTCrdsVbo.ChangeValue (anIter);
306
10b9c7df 307 if (theCtx)
a174a3c5 308 {
309 theCtx->DelayedRelease (aVerts);
310 theCtx->DelayedRelease (aTCrds);
311 }
312 aVerts.Nullify();
313 aTCrds.Nullify();
314 }
315 myTextures.Clear();
316 myVertsVbo.Clear();
317 myTCrdsVbo.Clear();
a174a3c5 318}
319
320// =======================================================================
321// function : Release
322// purpose :
323// =======================================================================
10b9c7df 324void OpenGl_Text::Release (OpenGl_Context* theCtx)
a174a3c5 325{
326 releaseVbos (theCtx);
327 if (!myFont.IsNull())
328 {
329 Handle(OpenGl_Context) aCtx = theCtx;
330 const TCollection_AsciiString aKey = myFont->ResourceKey();
331 myFont.Nullify();
c04c30b3 332 if (! aCtx.IsNull())
10b9c7df 333 aCtx->ReleaseResource (aKey, Standard_True);
a174a3c5 334 }
335}
336
337// =======================================================================
338// function : StringSize
339// purpose :
340// =======================================================================
341void OpenGl_Text::StringSize (const Handle(OpenGl_Context)& theCtx,
342 const NCollection_String& theText,
343 const OpenGl_AspectText& theTextAspect,
344 const OpenGl_TextParam& theParams,
4b1c8733 345 const unsigned int theResolution,
a174a3c5 346 Standard_ShortReal& theWidth,
347 Standard_ShortReal& theAscent,
348 Standard_ShortReal& theDescent)
349{
350 theWidth = 0.0f;
351 theAscent = 0.0f;
352 theDescent = 0.0f;
4b1c8733 353 const TCollection_AsciiString aFontKey = FontKey (theTextAspect, theParams.Height, theResolution);
354 Handle(OpenGl_Font) aFont = FindFont (theCtx, theTextAspect, theParams.Height, theResolution, aFontKey);
a174a3c5 355 if (aFont.IsNull() || !aFont->IsValid())
356 {
2166f0fa 357 return;
a174a3c5 358 }
359
360 theAscent = aFont->Ascender();
361 theDescent = aFont->Descender();
362
363 GLfloat aWidth = 0.0f;
364 for (NCollection_Utf8Iter anIter = theText.Iterator(); *anIter != 0;)
365 {
366 const Standard_Utf32Char aCharThis = *anIter;
367 const Standard_Utf32Char aCharNext = *++anIter;
368
369 if (aCharThis == '\x0D' // CR (carriage return)
370 || aCharThis == '\a' // BEL (alarm)
371 || aCharThis == '\f' // FF (form feed) NP (new page)
372 || aCharThis == '\b' // BS (backspace)
373 || aCharThis == '\v') // VT (vertical tab)
374 {
375 continue; // skip unsupported carriage control codes
376 }
377 else if (aCharThis == '\x0A') // LF (line feed, new line)
378 {
379 theWidth = Max (theWidth, aWidth);
380 aWidth = 0.0f;
381 continue;
382 }
383 else if (aCharThis == ' ')
384 {
385 aWidth += aFont->AdvanceX (aCharThis, aCharNext);
386 continue;
387 }
388 else if (aCharThis == '\t')
389 {
390 aWidth += aFont->AdvanceX (' ', aCharNext) * 8.0f;
391 continue;
392 }
393
394 aWidth += aFont->AdvanceX (aCharThis, aCharNext);
395 }
396 theWidth = Max (theWidth, aWidth);
397
398 Handle(OpenGl_Context) aCtx = theCtx;
399 aFont.Nullify();
400 aCtx->ReleaseResource (aFontKey, Standard_True);
401}
402
403// =======================================================================
404// function : Render
405// purpose :
406// =======================================================================
407void OpenGl_Text::Render (const Handle(OpenGl_Workspace)& theWorkspace) const
408{
25ef750e 409 const OpenGl_AspectText* aTextAspect = theWorkspace->AspectText (Standard_True);
410 const Handle(OpenGl_Texture) aPrevTexture = theWorkspace->DisableTexture();
411 const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
30f0ad28 412
b990e557 413 // Bind custom shader program or generate default version
4e1523ef 414 if (aCtx->core20fwd != NULL)
30f0ad28 415 {
b990e557 416 aCtx->ShaderManager()->BindProgram (
417 aTextAspect, aTextAspect->ShaderProgramRes (aCtx));
30f0ad28 418 }
419
c357e426 420 myOrientationMatrix = theWorkspace->View()->Camera()->OrientationMatrix();
ce01ec26 421 myProjMatrix.Convert (aCtx->ProjectionState.Current());
422
a174a3c5 423 // use highlight color or colors from aspect
424 if (theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT)
425 {
426 render (theWorkspace->PrinterContext(),
30f0ad28 427 aCtx,
a174a3c5 428 *aTextAspect,
429 *theWorkspace->HighlightColor,
4b1c8733 430 *theWorkspace->HighlightColor,
431 theWorkspace->View()->RenderingParams().Resolution);
a174a3c5 432 }
433 else
434 {
435 render (theWorkspace->PrinterContext(),
30f0ad28 436 aCtx,
a174a3c5 437 *aTextAspect,
438 aTextAspect->Color(),
4b1c8733 439 aTextAspect->SubtitleColor(),
440 theWorkspace->View()->RenderingParams().Resolution);
a174a3c5 441 }
2166f0fa 442
c6ad5e5f 443 aCtx->BindProgram (NULL);
444
a174a3c5 445 // restore aspects
446 if (!aPrevTexture.IsNull())
447 {
448 theWorkspace->EnableTexture (aPrevTexture);
449 }
b34efb62 450
451 // restore Z buffer settings
eae454e3 452 if (theWorkspace->UseZBuffer())
b34efb62 453 {
454 glEnable (GL_DEPTH_TEST);
455 }
a174a3c5 456}
2166f0fa 457
a174a3c5 458// =======================================================================
459// function : Render
460// purpose :
461// =======================================================================
462void OpenGl_Text::Render (const Handle(OpenGl_PrinterContext)& thePrintCtx,
463 const Handle(OpenGl_Context)& theCtx,
4b1c8733 464 const OpenGl_AspectText& theTextAspect,
465 const unsigned int theResolution) const
a174a3c5 466{
4b1c8733 467 render (thePrintCtx, theCtx, theTextAspect, theTextAspect.Color(), theTextAspect.SubtitleColor(), theResolution);
a174a3c5 468}
2166f0fa 469
a174a3c5 470// =======================================================================
471// function : setupMatrix
472// purpose :
473// =======================================================================
474void OpenGl_Text::setupMatrix (const Handle(OpenGl_PrinterContext)& thePrintCtx,
ca3c13d1 475 const Handle(OpenGl_Context)& theCtx,
a174a3c5 476 const OpenGl_AspectText& theTextAspect,
477 const OpenGl_Vec3 theDVec) const
478{
c827ea3a 479 OpenGl_Mat4d aModViewMat;
ce01ec26 480 OpenGl_Mat4d aProjectMat;
481
482 if (myHasPlane)
483 {
484 aProjectMat = myProjMatrix * myOrientationMatrix;
485 }
486 else
487 {
488 aProjectMat = myProjMatrix;
489 }
c827ea3a 490
a174a3c5 491 if (myIs2d)
bf75be98 492 {
825aa485 493 Graphic3d_TransformUtils::Translate<GLdouble> (aModViewMat, myPoint.x() + theDVec.x(), myPoint.y() + theDVec.y(), 0.f);
494 Graphic3d_TransformUtils::Scale<GLdouble> (aModViewMat, 1.f, -1.f, 1.f);
495 Graphic3d_TransformUtils::Rotate<GLdouble> (aModViewMat, theTextAspect.Angle(), 0.f, 0.f, 1.f);
2166f0fa
SK
496 }
497 else
498 {
a174a3c5 499 // align coordinates to the nearest integer
500 // to avoid extra interpolation issues
501 GLdouble anObjX, anObjY, anObjZ;
825aa485 502 Graphic3d_TransformUtils::UnProject<Standard_Real> (std::floor (myWinX + theDVec.x()),
503 std::floor (myWinY + theDVec.y()),
504 myWinZ + theDVec.z(),
505 OpenGl_Mat4d::Map (THE_IDENTITY_MATRIX),
ce01ec26 506 OpenGl_Mat4d::Map (aProjectMat),
825aa485 507 myViewport,
508 anObjX,
509 anObjY,
510 anObjZ);
511
ce01ec26 512 if (myHasPlane)
513 {
514 const gp_Dir& aVectorDir = myOrientation.XDirection();
515 const gp_Dir& aVectorUp = myOrientation.Direction();
516 const gp_Dir& aVectorRight = myOrientation.YDirection();
517
518 aModViewMat.SetColumn (3, OpenGl_Vec3d (anObjX, anObjY, anObjZ));
519 aModViewMat.SetColumn (2, OpenGl_Vec3d (aVectorUp.X(), aVectorUp.Y(), aVectorUp.Z()));
520 aModViewMat.SetColumn (1, OpenGl_Vec3d (aVectorRight.X(), aVectorRight.Y(), aVectorRight.Z()));
521 aModViewMat.SetColumn (0, OpenGl_Vec3d (aVectorDir.X(), aVectorDir.Y(), aVectorDir.Z()));
522 }
523 else
524 {
525 Graphic3d_TransformUtils::Translate<GLdouble> (aModViewMat, anObjX, anObjY, anObjZ);
526 Graphic3d_TransformUtils::Rotate<GLdouble> (aModViewMat, theTextAspect.Angle(), 0.0, 0.0, 1.0);
527 }
825aa485 528
a174a3c5 529 if (!theTextAspect.IsZoomable())
530 {
531 #ifdef _WIN32
532 // if the context has assigned printer context, use it's parameters
533 if (!thePrintCtx.IsNull())
534 {
535 // get printing scaling in x and y dimensions
536 GLfloat aTextScalex = 1.0f, aTextScaley = 1.0f;
537 thePrintCtx->GetScale (aTextScalex, aTextScaley);
538
539 // text should be scaled in all directions with same
540 // factor to save its proportions, so use height (y) scaling
541 // as it is better for keeping text/3d graphics proportions
825aa485 542 Graphic3d_TransformUtils::Scale<GLdouble> (aModViewMat, aTextScaley, aTextScaley, aTextScaley);
a174a3c5 543 }
c85385c0 544 #else
545 (void )thePrintCtx;
a174a3c5 546 #endif
825aa485 547 Graphic3d_TransformUtils::Scale<GLdouble> (aModViewMat, myScaleHeight, myScaleHeight, myScaleHeight);
a174a3c5 548 }
549 }
c827ea3a 550
551 theCtx->WorldViewState.SetCurrent<Standard_Real> (aModViewMat);
552 theCtx->ApplyWorldViewMatrix();
b990e557 553
ce01ec26 554 if (!myIs2d)
555 {
556 theCtx->ProjectionState.SetCurrent<Standard_Real> (aProjectMat);
557 theCtx->ApplyProjectionMatrix();
558 }
559
b990e557 560 if (!theCtx->ActiveProgram().IsNull())
561 {
562 // Upload updated state to shader program
563 theCtx->ShaderManager()->PushState (theCtx->ActiveProgram());
564 }
a174a3c5 565}
566
567// =======================================================================
568// function : drawText
569// purpose :
570// =======================================================================
35e08fe8 571
572void OpenGl_Text::drawText (const Handle(OpenGl_PrinterContext)& ,
a174a3c5 573 const Handle(OpenGl_Context)& theCtx,
35e08fe8 574 #ifdef HAVE_GL2PS
a174a3c5 575 const OpenGl_AspectText& theTextAspect) const
35e08fe8 576 #else
577 const OpenGl_AspectText& ) const
578 #endif
a174a3c5 579{
580#ifdef HAVE_GL2PS
581 if (theCtx->IsFeedback())
582 {
583 // position of the text and alignment is calculated by transformation matrix
584 exportText (myString, myIs2d, theTextAspect, (Standard_Integer )myExportHeight);
585 return;
2166f0fa 586 }
a174a3c5 587#endif
2166f0fa 588
7d3e64ef 589 if (myVertsVbo.Length() != myTextures.Length()
590 || myTextures.IsEmpty())
2166f0fa 591 {
7d3e64ef 592 return;
2166f0fa 593 }
7d3e64ef 594
595 for (Standard_Integer anIter = 0; anIter < myTextures.Length(); ++anIter)
a174a3c5 596 {
7d3e64ef 597 const GLuint aTexId = myTextures.Value (anIter);
598 glBindTexture (GL_TEXTURE_2D, aTexId);
a174a3c5 599
7d3e64ef 600 const Handle(OpenGl_VertexBuffer)& aVerts = myVertsVbo.Value (anIter);
601 const Handle(OpenGl_VertexBuffer)& aTCrds = myTCrdsVbo.Value (anIter);
602 aVerts->BindAttribute (theCtx, Graphic3d_TOA_POS);
603 aTCrds->BindAttribute (theCtx, Graphic3d_TOA_UV);
2166f0fa 604
7d3e64ef 605 glDrawArrays (GL_TRIANGLES, 0, GLsizei(aVerts->GetElemsNb()));
2166f0fa 606
b990e557 607 aTCrds->UnbindAttribute (theCtx, Graphic3d_TOA_UV);
7d3e64ef 608 aVerts->UnbindAttribute (theCtx, Graphic3d_TOA_POS);
a174a3c5 609 }
7d3e64ef 610 glBindTexture (GL_TEXTURE_2D, 0);
a174a3c5 611}
2166f0fa 612
a174a3c5 613// =======================================================================
614// function : FontKey
615// purpose :
616// =======================================================================
617TCollection_AsciiString OpenGl_Text::FontKey (const OpenGl_AspectText& theAspect,
4b1c8733 618 const Standard_Integer theHeight,
619 const unsigned int theResolution)
a174a3c5 620{
621 const Font_FontAspect anAspect = (theAspect.FontAspect() != Font_FA_Undefined) ? theAspect.FontAspect() : Font_FA_Regular;
622 return theAspect.FontName()
623 + TCollection_AsciiString(":") + Standard_Integer(anAspect)
4b1c8733 624 + TCollection_AsciiString(":") + Standard_Integer(theResolution)
a174a3c5 625 + TCollection_AsciiString(":") + theHeight;
626}
627
628// =======================================================================
629// function : FindFont
630// purpose :
631// =======================================================================
632Handle(OpenGl_Font) OpenGl_Text::FindFont (const Handle(OpenGl_Context)& theCtx,
633 const OpenGl_AspectText& theAspect,
634 const Standard_Integer theHeight,
4b1c8733 635 const unsigned int theResolution,
a174a3c5 636 const TCollection_AsciiString theKey)
637{
638 Handle(OpenGl_Font) aFont;
639 if (theHeight < 2)
2166f0fa 640 {
a174a3c5 641 return aFont; // invalid parameters
642 }
2166f0fa 643
a174a3c5 644 if (!theCtx->GetResource (theKey, aFont))
645 {
646 Handle(Font_FontMgr) aFontMgr = Font_FontMgr::GetInstance();
647 const Handle(TCollection_HAsciiString) aFontName = new TCollection_HAsciiString (theAspect.FontName());
648 const Font_FontAspect anAspect = (theAspect.FontAspect() != Font_FA_Undefined) ? theAspect.FontAspect() : Font_FA_Regular;
649 Handle(Font_SystemFont) aRequestedFont = aFontMgr->FindFont (aFontName, anAspect, theHeight);
65360da3 650 Handle(Font_FTFont) aFontFt;
651 if (!aRequestedFont.IsNull())
2166f0fa 652 {
65360da3 653 aFontFt = new Font_FTFont (NULL);
317d68c9 654
4b1c8733 655 if (aFontFt->Init (aRequestedFont->FontPath()->ToCString(), theHeight, theResolution))
65360da3 656 {
657 aFont = new OpenGl_Font (aFontFt, theKey);
658 if (!aFont->Init (theCtx))
659 {
660 TCollection_ExtendedString aMsg;
661 aMsg += "Font '";
662 aMsg += theAspect.FontName();
663 aMsg += "' - initialization of GL resources has failed!";
3b523c4c 664 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, aMsg);
65360da3 665 aFontFt.Nullify();
c6ad5e5f 666 aFont->Release (theCtx.operator->());
65360da3 667 aFont = new OpenGl_Font (aFontFt, theKey);
668 }
669 }
670 else
671 {
672 TCollection_ExtendedString aMsg;
673 aMsg += "Font '";
674 aMsg += theAspect.FontName();
675 aMsg += "' is broken or has incompatible format! File path: ";
676 aMsg += aRequestedFont->FontPath()->ToCString();
3b523c4c 677 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, aMsg);
65360da3 678 aFontFt.Nullify();
679 aFont = new OpenGl_Font (aFontFt, theKey);
680 }
a174a3c5 681 }
65360da3 682 else
a174a3c5 683 {
65360da3 684 TCollection_ExtendedString aMsg;
685 aMsg += "Font '";
686 aMsg += theAspect.FontName();
687 aMsg += "' is not found in the system!";
3b523c4c 688 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, aMsg);
65360da3 689 aFont = new OpenGl_Font (aFontFt, theKey);
a174a3c5 690 }
a174a3c5 691
b34efb62 692 theCtx->ShareResource (theKey, aFont);
a174a3c5 693 }
694 return aFont;
695}
696
697// =======================================================================
698// function : render
699// purpose :
700// =======================================================================
701void OpenGl_Text::render (const Handle(OpenGl_PrinterContext)& thePrintCtx,
702 const Handle(OpenGl_Context)& theCtx,
703 const OpenGl_AspectText& theTextAspect,
704 const TEL_COLOUR& theColorText,
4b1c8733 705 const TEL_COLOUR& theColorSubs,
706 const unsigned int theResolution) const
a174a3c5 707{
708 if (myString.IsEmpty())
709 {
710 return;
711 }
712
4b1c8733 713 // Note that using difference resolution in different Views in same Viewer
714 // will lead to performance regression (for example, text will be recreated every time).
715 const TCollection_AsciiString aFontKey = FontKey (theTextAspect, myParams.Height, theResolution);
a174a3c5 716 if (!myFont.IsNull()
717 && !myFont->ResourceKey().IsEqual (aFontKey))
718 {
719 // font changed
10b9c7df 720 const_cast<OpenGl_Text* > (this)->Release (theCtx.operator->());
a174a3c5 721 }
722
723 if (myFont.IsNull())
724 {
4b1c8733 725 myFont = FindFont (theCtx, theTextAspect, myParams.Height, theResolution, aFontKey);
65360da3 726 }
727 if (!myFont->WasInitialized())
728 {
729 return;
a174a3c5 730 }
731
732 if (myTextures.IsEmpty())
733 {
317d68c9 734 Font_TextFormatter aFormatter;
a174a3c5 735 aFormatter.SetupAlignment (myParams.HAlign, myParams.VAlign);
736 aFormatter.Reset();
317d68c9 737
738 aFormatter.Append (myString, *myFont->FTFont());
a174a3c5 739 aFormatter.Format();
740
317d68c9 741 OpenGl_TextBuilder aBuilder;
742 aBuilder.Perform (aFormatter,
743 theCtx,
744 *myFont.operator->(),
745 myTextures,
746 myVertsVbo,
747 myTCrdsVbo);
748
a174a3c5 749 aFormatter.BndBox (myBndBox);
750 }
751
752 if (myTextures.IsEmpty())
753 {
754 return;
755 }
756
757 myExportHeight = 1.0f;
758 myScaleHeight = 1.0f;
759
c827ea3a 760 theCtx->WorldViewState.Push();
761
c827ea3a 762 myModelMatrix.Convert (theCtx->WorldViewState.Current() * theCtx->ModelWorldState.Current());
763
a174a3c5 764 if (!myIs2d)
765 {
a174a3c5 766 glGetIntegerv (GL_VIEWPORT, myViewport);
c827ea3a 767
825aa485 768 Graphic3d_TransformUtils::Project<Standard_Real> (myPoint.x(),
769 myPoint.y(),
770 myPoint.z(),
771 myModelMatrix,
772 myProjMatrix,
773 myViewport,
774 myWinX,
775 myWinY,
776 myWinZ);
a174a3c5 777
778 // compute scale factor for constant text height
779 GLdouble x1, y1, z1;
825aa485 780 Graphic3d_TransformUtils::UnProject<Standard_Real> (myWinX,
781 myWinY,
782 myWinZ,
783 OpenGl_Mat4d::Map (THE_IDENTITY_MATRIX),
784 myProjMatrix,
785 myViewport,
786 x1,
787 y1,
788 z1);
a174a3c5 789
790 GLdouble x2, y2, z2;
791 const GLdouble h = (GLdouble )myFont->FTFont()->PointSize();
825aa485 792 Graphic3d_TransformUtils::UnProject<Standard_Real> (myWinX,
793 myWinY + h,
794 myWinZ,
795 OpenGl_Mat4d::Map (THE_IDENTITY_MATRIX),
796 myProjMatrix,
797 myViewport,
798 x2,
799 y2,
800 z2);
a174a3c5 801
802 myScaleHeight = (y2 - y1) / h;
803 if (theTextAspect.IsZoomable())
804 {
805 myExportHeight = (float )h;
806 }
807 }
808 myExportHeight = (float )myFont->FTFont()->PointSize() / myExportHeight;
809
b990e557 810#if !defined(GL_ES_VERSION_2_0)
65360da3 811 if (theCtx->core11 != NULL)
812 {
813 glDisable (GL_LIGHTING);
814 }
815#endif
a174a3c5 816
817 // setup depth test
eae454e3 818 if (myIs2d
819 || theTextAspect.StyleType() == Aspect_TOST_ANNOTATION)
a174a3c5 820 {
821 glDisable (GL_DEPTH_TEST);
822 }
823
65360da3 824 if (theCtx->core15fwd != NULL)
a174a3c5 825 {
65360da3 826 theCtx->core15fwd->glActiveTexture (GL_TEXTURE0);
a174a3c5 827 }
65360da3 828#if !defined(GL_ES_VERSION_2_0)
a174a3c5 829 // activate texture unit
65360da3 830 GLint aTexEnvParam = GL_REPLACE;
831 if (theCtx->core11 != NULL)
a174a3c5 832 {
c6ad5e5f 833 // setup alpha test
834 glAlphaFunc (GL_GEQUAL, 0.285f);
835 glEnable (GL_ALPHA_TEST);
836
65360da3 837 glDisable (GL_TEXTURE_1D);
838 glEnable (GL_TEXTURE_2D);
839 glGetTexEnviv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &aTexEnvParam);
840 if (aTexEnvParam != GL_REPLACE)
841 {
842 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
843 }
a174a3c5 844 }
65360da3 845#endif
846
847 // setup blending
848 glEnable (GL_BLEND);
849 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
a174a3c5 850
851 // extra drawings
852 switch (theTextAspect.DisplayType())
853 {
2166f0fa 854 case Aspect_TODT_BLEND:
a174a3c5 855 {
65360da3 856 #if !defined(GL_ES_VERSION_2_0)
a174a3c5 857 glEnable (GL_COLOR_LOGIC_OP);
858 glLogicOp (GL_XOR);
65360da3 859 #endif
2166f0fa 860 break;
a174a3c5 861 }
2166f0fa
SK
862 case Aspect_TODT_SUBTITLE:
863 {
65360da3 864 #if !defined(GL_ES_VERSION_2_0)
865 if (theCtx->core11 != NULL)
866 {
867 theCtx->core11->glColor3fv (theColorSubs.rgb);
868 setupMatrix (thePrintCtx, theCtx, theTextAspect, OpenGl_Vec3 (0.0f, 0.0f, 0.00001f));
869
870 glBindTexture (GL_TEXTURE_2D, 0);
871 glBegin (GL_QUADS);
872 glVertex2f (myBndBox.Left, myBndBox.Top);
873 glVertex2f (myBndBox.Right, myBndBox.Top);
874 glVertex2f (myBndBox.Right, myBndBox.Bottom);
875 glVertex2f (myBndBox.Left, myBndBox.Bottom);
876 glEnd();
877 }
878 #endif
2166f0fa
SK
879 break;
880 }
2166f0fa 881 case Aspect_TODT_DEKALE:
a174a3c5 882 {
b990e557 883 theCtx->SetColor4fv (*(const OpenGl_Vec4* )theColorSubs.rgb);
a174a3c5 884 setupMatrix (thePrintCtx, theCtx, theTextAspect, OpenGl_Vec3 (+1.0f, +1.0f, 0.00001f));
885 drawText (thePrintCtx, theCtx, theTextAspect);
886 setupMatrix (thePrintCtx, theCtx, theTextAspect, OpenGl_Vec3 (-1.0f, -1.0f, 0.00001f));
887 drawText (thePrintCtx, theCtx, theTextAspect);
888 setupMatrix (thePrintCtx, theCtx, theTextAspect, OpenGl_Vec3 (-1.0f, +1.0f, 0.00001f));
889 drawText (thePrintCtx, theCtx, theTextAspect);
890 setupMatrix (thePrintCtx, theCtx, theTextAspect, OpenGl_Vec3 (+1.0f, -1.0f, 0.00001f));
891 drawText (thePrintCtx, theCtx, theTextAspect);
892 break;
893 }
a6eb515f 894 case Aspect_TODT_DIMENSION:
a174a3c5 895 case Aspect_TODT_NORMAL:
896 {
2166f0fa
SK
897 break;
898 }
899 }
900
a174a3c5 901 // main draw call
b990e557 902 theCtx->SetColor4fv (*(const OpenGl_Vec4* )theColorText.rgb);
a174a3c5 903 setupMatrix (thePrintCtx, theCtx, theTextAspect, OpenGl_Vec3 (0.0f, 0.0f, 0.0f));
904 drawText (thePrintCtx, theCtx, theTextAspect);
2166f0fa 905
ce01ec26 906 if (!myIs2d)
907 {
908 theCtx->ProjectionState.SetCurrent<Standard_Real> (myProjMatrix);
909 theCtx->ApplyProjectionMatrix();
910 }
911
65360da3 912#if !defined(GL_ES_VERSION_2_0)
913 if (theCtx->core11 != NULL)
914 {
915 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, aTexEnvParam);
916 }
917#endif
543f0db0 918
919 if (theTextAspect.DisplayType() == Aspect_TODT_DIMENSION)
920 {
921 setupMatrix (thePrintCtx, theCtx, theTextAspect, OpenGl_Vec3 (0.0f, 0.0f, 0.00001f));
922
923 glDisable (GL_BLEND);
543f0db0 924 if (!myIs2d)
925 {
926 glDisable (GL_DEPTH_TEST);
927 }
65360da3 928 #if !defined(GL_ES_VERSION_2_0)
929 if (theCtx->core11 != NULL)
930 {
931 glDisable (GL_TEXTURE_2D);
932 glDisable (GL_ALPHA_TEST);
933 }
934 #endif
543f0db0 935 glColorMask (GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
936
937 glClear (GL_STENCIL_BUFFER_BIT);
938 glEnable (GL_STENCIL_TEST);
939 glStencilFunc (GL_ALWAYS, 1, 0xFF);
940 glStencilOp (GL_KEEP, GL_KEEP, GL_REPLACE);
941
65360da3 942 #if !defined(GL_ES_VERSION_2_0)
943 if (theCtx->core11 != NULL)
944 {
945 glBegin (GL_QUADS);
946 glVertex2f (myBndBox.Left, myBndBox.Top);
947 glVertex2f (myBndBox.Right, myBndBox.Top);
948 glVertex2f (myBndBox.Right, myBndBox.Bottom);
949 glVertex2f (myBndBox.Left, myBndBox.Bottom);
950 glEnd();
951 }
952 #endif
543f0db0 953
954 glStencilFunc (GL_ALWAYS, 0, 0xFF);
543f0db0 955
956 glColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
957 }
958
b34efb62 959 // reset OpenGL state
960 glDisable (GL_BLEND);
b34efb62 961 glDisable (GL_STENCIL_TEST);
65360da3 962#if !defined(GL_ES_VERSION_2_0)
c6ad5e5f 963 if (theCtx->core11 != NULL)
964 {
965 glDisable (GL_ALPHA_TEST);
966 }
b34efb62 967 glDisable (GL_COLOR_LOGIC_OP);
65360da3 968#endif
c827ea3a 969
970 // model view matrix was modified
971 theCtx->WorldViewState.Pop();
972 theCtx->ApplyModelViewMatrix();
5e27df78 973}