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